Closed av01d closed 3 years ago
Welcome to node-rfxcom
!
I am not familiar with rfxsend.py
, but it looks like it's providing a fairly low-level API to the RFX transceiver.
In node-rfxcom
, the typical way to send command messages is by using one of the specialised subclasses of Transmitter
: there is one for each supported type of RFX transmit packet (which is most of them). To take your first example, that has a packet type (i.e. the second byte) of 0x13, which is a lighting4 packet type. The first byte, 0x09, is the length of the data packet. The remaining bytes are the subtype (0) and the command sequence number (0), used by the RFX itself, followed by the actual data to be transmitted.
If you look in file lib/index.js
, you will find at line 75 a list of the transmitter types, and further down from line 145 on the definition of each packet, listed in numerical order of packet type. Thus at lines 160-163 we see that the Transmitter
subclass for a lighting4 packet, type 0x13, is called Lighting4
, and has only one subtype, called PT2262
. The Lighting4
class provides a single public API method, sendData()
This takes three arguments: data
, as a 3-byte array or a string, an optional pulseWidth
a 16-bit number provided as a two-byte array or a string, and an optional callback. Note that the packet length, type, subtype, and sequence number are all provided automatically.
To send your two example commands, you should create a Lighting4
object, passing the subtype PT2262
to the constructor. Then you can call its sendData()
method with your data:
var rfxcom = require('rfxcom');
var rfxtrx = new rfxcom.RfxCom("/dev/ttyUSB-RFX433", {debug: true});
var myLightController = new Lighting4(rfxtrx, rfxcom.lighting4.PT2262);
rfxtrx.initialise(function () {
console.log("Device initialised");
myLightController.sendData([0x15, 0x54, 0x51], [0x01, 0x50]); // On
myLightController.sendData("0x155454"); // Off
});
The second call omits the pulseWidth
parameter: in this case, the default value of [0x01, 0x5E] is used - which should be close enough.
Similarly, there is the Rfy
subclass for sending commands to Somfy and similar blind motors that use the RFY protocol. There is an example showing how to use it in the README.md
file. Your blind motor has address 0x10234 and unit code 1. You pass commands to the transmitter using command-specific methods, like rfy.up("0x10234/1")
or rfy.down(["0x10234", "1"])
. Note the two different ways the motor address can be supplied. One slight oddity is the command number 0 in your second example is actually the "stop" command, according to the protocol documentation.
The file DeviceCommands.md
gives details, for each Transmitter subclass, of the available subtypes, and the public API methods. There are some examples of their use in the README.md file.
Finally, each Transmitter
subclass calls Transmitter.sendRaw()
to implement the business end of its API. The first parameter is the packet type (number), while the second is the subtype. Take a look at the source code of one of the subclasses to see how they are used!
If you have any other questions, please ask and I will try to answer them.
Wow, thank you so much for this extensive reply. Got most of my devices working fine now. Great. In my bedroom, I've got Dooya roller blinds that I cannot get to work yet. These are the raw commands:
up: "09 19 06 11 01 02 03 11 00 00",
down: "09 19 06 11 01 02 03 11 01 00",
stop: "09 19 06 11 01 02 03 11 02 00",
intermediate: "09 19 06 11 01 02 03 11 04 00"
This is my test code:
var ctrl = new rfxcom.Blinds1(rfxtrx, rfxcom.blinds1.BLINDS_T6);
var id = "0x010203/11";
ctrl.close(id);
I'm pretty sure that blinds1
is the correct subclass and BLINDS_T6
is the right type.
But the blinds don't move... so I presume the id I'm using is incorrect. Can you help me find the right one?
Then some additional questions:
intermediate
command (or similar) available for blinds? I don't see it in /lib/blinds1.js
(node:19795) Warning: Accessing non-existent property 'AsyncConfig' of module exports inside circular dependency
(Use `node --trace-warnings ...` to show where the warning was created)
Is there something I should do different? Or is this a mishap in node-rfxcom's code?
Queued: 08,17,07,03,00,2C,C6,03,00
Sent: 08,17,07,03,00,2C,C6,03,00
These turn out to be exactly the raw commands I was using as an argument to rfxcmd.py
(without the commas).
Isn't it an idea to expose a method for sending "true" raw commands in lib/rfxcom.js
? If the transmit
function in lib/rfxcom.js
would be publicly accessible?
I think the problem is BLINDS_T6 uses the top 4 bits of the 8th byte as part of the id, not the unit code. So in your example the id ought to be "0x0102031/1"
.
Also, the RfxCom object emits an event for each type of packet received, so if you handle the blinds1
event, you will get an object populated with the correctly-decoded id, status information, and the command name & number, each time a packet is received. Unfortunately, for this packet type different subtypes use the same command number for different commands, so the name isn't always correct. The intermediate command is not one of those included - I will look at adding it, to both transmit & receive.
Plain Javascript doesn't actually support privacy, so you can always access any method of an object - feel free to call sendRaw()
from your own code if you want!
But...
...if you want to implement home automation using NodeJS, can I recommend you take a look at Node-RED? It's a graphical, flow-based programming environment originally developed by a couple of guys at IBM, and now an Eclipse Foundation project. I have contributed a graphical node, node-red-contrib-rfxcom
, that wraps node-rfxcom
and exposes almost all of its functionality in the Node-RED environment.
The AsyncConfig
message comes from a bug in my code - it refers to a transmitter subclass for packet type 0x61 that I don't support (yet), because it requires a later model of the hardware than I have here. You may see a similar warning for AsyncData
(0x62) as well. I've created issue #100 to address this
I think the problem is BLINDS_T6 uses the top 4 bits of the 8th byte as part of the id, not the unit code. So in your example the id ought to be
"0x0102031/1"
.
Works, thank you so much!
Also, the RfxCom object emits an event for each type of packet received, so if you handle the
blinds1
event, you will get an object populated with the correctly-decoded id, status information, and the command name & number, each time a packet is received. Unfortunately, for this packet type different subtypes use the same command number for different commands, so the name isn't always correct. The intermediate command is not one of those included - I will look at adding it, to both transmit & receive.
Great. I've given it a go myself, successfully:
in lib/defines.js
, I added this:
BLINDS_INTERMEDIATE: 0x04,
in lib/blinds.js
, I added this function:
intermediate(deviceId, callback) {
return this._sendCommand(deviceId, defines.BLINDS_INTERMEDIATE, callback);
};
Maybe you need/want to add some extra checks (for devices other then BLINDS_T6), but this works for me.
Plain Javascript doesn't actually support privacy, so you can always access any method of an object - feel free to call
sendRaw()
from your own code if you want!
Might, might not.... not sure as everything now works the way you intended it!
But...
...if you want to implement home automation using NodeJS, can I recommend you take a look at Node-RED? It's a graphical, flow-based programming environment originally developed by a couple of guys at IBM, and now an Eclipse Foundation project. I have contributed a graphical node,
node-red-contrib-rfxcom
, that wrapsnode-rfxcom
and exposes almost all of its functionality in the Node-RED environment.
Thanks!
Three other blinds subtypes support an intermediate position, of which one actually has three different positions. The API needs to cover them all, and of course I will have to write test cases for each. Deep joy...
Three other blinds subtypes support an intermediate position, of which one actually has three different positions. The API needs to cover them all, and of course I will have to write test cases for each. Deep joy...
Good luck with that .... ;-)
I decided to send raw commands; here is how I do that (for future reference):
const rfxcom = require('rfxcom');
const rfxtrx = new rfxcom.RfxCom('/dev/ttyUSB-RFX433');
const transmitter = new rfxcom.Transmitter(rfxtrx, null);
const command = '09 13 00 00 15 54 51 01 50 00' // raw 'on' command
const bits = command.split(' ').map(function(c) {
return parseInt('0x'+c);
});
rfxtrx.queueMessage(transmitter, bits, 0, function() {
// callback code here
});
Just published version 2.4.0 which adds the Blinds1.intemediatePosition()
method. It takes an optional position parameter (integer in the range 1 to 3) but which is ignored by all subtypes except BLINDS_T9. If missing, it defaults to 2.
Works brilliantly. Thank you very much for all you efforts. My RFXcom is now powered by node-rfxcom alone, no more cmdline python scripts. Me = happy ;-)
I am writing my own home automation software in nodejs. I've got an RFXcom on a Raspberry Pi. Until now I used the rfxcmd python scripts for sending and receiving commands: received sensor data is forwarded to nodejs via MQTT. Works fine, but this node-rfxcmd library seems to fit my needs even better. I've been playing around, and I can successfully receive data from my temperature, humidity and motion sensors. Great! Next step is sending commands to the few 433MHz devices I have. Until now, I used the
rfxsend.py
script for that. Here are some examples:rfxsend.py -r 09130000155451015000 // Turn light on rfxsend.py -r 09130000155454015200 // Turn light off
rfxsend.py -r 0C1A000F010234010100000000 // Somfy blinds up rfxsend.py -r 0C1A000E010234010000000000 // Somfy blinds down
These raw commands were found with the RFXmngr program (Windows). How can I send these raw commands in node-rfxcmd? I've been playing with this:
I don't know what the first 2 arguments to
sendRaw
should be?I am hopeful somebody can & will help me. Thanks in advance!