maxwellhadley / node-red-contrib-rfxcom

node-RED nodes to access an RFXtrx433 transceiver
BSD 2-Clause "Simplified" License
22 stars 13 forks source link

Potential to add LAN compatibility? #49

Closed deggle closed 3 years ago

deggle commented 6 years ago

Hello,

Brilliant work! I've started hacking together something similar, however it would be really great if it could be made compatible with the LAN version of the RFXCom devices as you've done all the hard work!

They are no longer made, but basically there are two TCP ports, one for RX and one for TX (odd, I know) and from then on the actual packets are most likely identical to everything you've done to date.

If it helps assess the complexity of adding, I've pasted a flow below that I have been working on for the RX side:

[{"id":"ea1b8869.819128","type":"tcp in","z":"a3886a07.a7e238","name":"RFXCom (RX)","server":"client","host":"10.0.3.10","port":"10001","datamode":"stream","datatype":"buffer","newline":"","topic":"","base64":false,"x":110,"y":1340,"wires":[["55d8bd4e.8fec24","b2755644.d78028"]]},{"id":"b2755644.d78028","type":"debug","z":"a3886a07.a7e238","name":"Debug","active":false,"console":"false","complete":"payload","x":290,"y":1340,"wires":[]},{"id":"55d8bd4e.8fec24","type":"function","z":"a3886a07.a7e238","name":"Packet Type","func":"\nvar bits = msg.payload[0];\nvar packet = msg.payload.slice(1);\nvar msgNew = {payload: {packet: packet}};\n\nif (bits == 12 || bits == 34 || bits == 38) {\n\n msgNew.payload.type = \"HomeEasy\";\n return [msgNew, null, null, null];\n\n} else if (bits == 108 && (packet[0] == 0x1a || packet[0] == 0x2a || packet[0] == 0x3a) ) {\n\n msgNew.payload.type = \"Owl\";\n return [null, msgNew, null, null];\n\n} else if (bits == 56 || bits > 59) {\n\n msgNew.payload.type = \"Oregon\";\n return [null, null, msgNew, null];\n\n} else {\n\n return [null, null, null, msg];\n \n}","outputs":"4","noerr":0,"x":310,"y":1400,"wires":[["670b3d81.ee27a4"],["81036370.fed34"],["36fb6bc3.b66e04"],["648df182.6f78f"]],"outputLabels":["HomeEasy","Owl","Oregon","Unknown"]},{"id":"36fb6bc3.b66e04","type":"function","z":"a3886a07.a7e238","name":"Oregon","func":"\nvar packet = msg.payload.packet;\n\nvar address = (packet[3] * 256) + (packet[2] >> 4 & 0x7);\nvar channel = packet[2] >> 4;\nvar batteryLow = (packet[4] & 0x4) !== 0;\n\nif (address === 0) {return null;}\n\nmsg.payload.address = address;\nmsg.payload.channel = channel;\nmsg.payload.batteryLow = batteryLow;\n\nfncSetTemp = function(msg) {\n\n var temp = (10 * (packet[5] >> 4)) + (packet[5] & 0xf) + ((packet[4] >> 4) / 10);\n if ((packet[6] & 0x8) !== 0) {temp = 0 - temp;}\n msg.payload.temp = temp;\n\n};\n\nfncSetTempHum = function(msg) {\n\n var temp = (10 * (packet[5] >> 4)) + (packet[5] & 0xf) + ((packet[4] >> 4) / 10);\n if ((packet[6] & 0x8) !== 0) {temp = 0 - temp;}\n var humidity = (10 * (packet[7] & 0xf)) + (packet[6] >> 4);\n var humidityLevel = \"Unknown\";\n if ((packet[7] & 0xC0)== 0x40) {humidityLevel = \"Comfort\";}\n else if ((packet[7] & 0xC0)== 0x80) {humidityLevel = \"Dry\";}\n else if ((packet[7] & 0xC0)== 0xC0) {humidityLevel = \"Wet\";}\n else {humidityLevel = \"Normal\";}\n\n msg.payload.temp = temp;\n msg.payload.humidity = humidity;\n msg.payload.humidityLevel = humidityLevel;\n\n};\n\n// Which device type?\nif (packet[0] == 0xFA && packet[1] == 0x28) {\n\n msg.payload.device = \"THWR810\";\n fncSetTempHum(msg);\n\n} else if (packet[0] == 0xA2 && packet[1] == 0xD1) {\n\n msg.payload.device = \"THGN132N\";\n fncSetTempHum(msg);\n \n} else if (packet[0] == 0xEA && packet[1] == 0x4C) {\n \n msg.payload.device = \"THN132N\";\n fncSetTemp(msg);\n \n} else if (packet[0] == 0x1A && packet[1] == 0x2D) {\n\n // THGN122N\n msg.payload.device = \"THGN122N\";\n fncSetTempHum(msg);\n\n} else {\n \n msg.payload.device = \"Unknown\";\n\n}\n \nreturn msg;","outputs":1,"noerr":0,"x":500,"y":1420,"wires":[["2b5b8116.6d505e"]]},{"id":"670b3d81.ee27a4","type":"function","z":"a3886a07.a7e238","name":"HomeEasy","func":"\nreturn msg;","outputs":1,"noerr":0,"x":510,"y":1340,"wires":[["d9fe6829.641ec8"]]},{"id":"81036370.fed34","type":"function","z":"a3886a07.a7e238","name":"Owl","func":"\nreturn msg;","outputs":1,"noerr":0,"x":490,"y":1380,"wires":[["d9fe6829.641ec8"]]},{"id":"a4d6e3e1.42123","type":"comment","z":"a3886a07.a7e238","name":"RFXCom LAN","info":"","x":90,"y":1280,"wires":[]},{"id":"d9fe6829.641ec8","type":"debug","z":"a3886a07.a7e238","name":"","active":false,"console":"false","complete":"payload","x":710,"y":1340,"wires":[]},{"id":"648df182.6f78f","type":"debug","z":"a3886a07.a7e238","name":"","active":true,"console":"false","complete":"payload","x":510,"y":1460,"wires":[]},{"id":"2b5b8116.6d505e","type":"function","z":"a3886a07.a7e238","name":"Oregon to MQTT","func":"\nvar msgs = [];\n\n// Battery...\nif (msg.payload.batteryLow !== undefined) {\n var msgBattery= {payload: {}};\n msgBattery.topic = 'ch/rfxcom/oregon/'+ msg.payload.channel + '/' + msg.payload.address + '/batteryLow';\n msgBattery.payload = msg.payload.batteryLow;\n msgs.push(msgBattery);\n}\n\n// Temp...\nif (msg.payload.temp !== undefined) {\n var msgTemp = {payload: {}};\n msgTemp.topic = 'ch/rfxcom/oregon/'+ msg.payload.channel + '/' + msg.payload.address + '/temp';\n msgTemp.payload = msg.payload.temp;\n msgs.push(msgTemp);\n}\n\n// Humidity...\nif (msg.payload.humidity !== undefined) {\n var msgHum = {payload: {}};\n msgHum.topic = 'ch/rfxcom/oregon/'+ msg.payload.channel + '/' + msg.payload.address + '/humidity';\n msgHum.payload = msg.payload.humidity;\n msgs.push(msgHum);\n}\n\nreturn [msgs];","outputs":1,"noerr":0,"x":730,"y":1420,"wires":[["c8b817bc.7f6708"]]}]

deggle commented 6 years ago

Having looked closer, the different ports for RX and TX can just be handled manually (by setting both up and selecting based on the node being TX or RX), so what I'm really asking is if you'd consider changing "Serial Port" to "Port" and implementing the option of a service sevice or a TCP (IP & Port) option...?

maxwellhadley commented 6 years ago

Do you have any documentation you could point me to?

deggle commented 6 years ago

Sorry for the delay. I have found this: http://www.i-gaia.com/rfxlan/RFXLAN.pdf

However I'm not sure it's too helpful.

I think this discontinued product is basically a LAN to RS232 converter for another RFXCom product, which is on a daughter board inside it (as per the PDF, I think you could add different modules for different frequencies, but I have the standard 433Mhz one).

If I create a basic TCP node that connects to the RX port with a debug output:

[{"id":"3bf8a064.56712","type":"tcp in","z":"a3886a07.a7e238","name":"RFXCom (RX)","server":"client","host":"10.0.3.10","port":"10001","datamode":"stream","datatype":"buffer","newline":"","topic":"","base64":false,"x":830,"y":1600,"wires":[["215bc644.b378ba"]]},{"id":"215bc644.b378ba","type":"debug","z":"a3886a07.a7e238","name":"Debug","active":true,"console":"false","complete":"payload","x":1010,"y":1600,"wires":[]}]

The packets it receives look like:

This will be a couple of Oregon temp/hum sensors I have running. I know the first byte is the packet length (in bits) and there is also a check digit. I believe that sending is done with the exact same format just as a packet sent out to the open TCP connection on the TX port.

I assume this will be extremely close to the inputs you're decoding from the USB stream and it seems like I'd be duplicating a a lot of effort to try and make my own parser/splitter/nodes for all the device types. If there is anything that can be done to also allow a TCP port that would be amazing.

maxwellhadley commented 5 years ago

Having sorted out a bunch of other issues, I finally got around to looking at this one. Unfortunately, it looks like the actual packet formats coming from your RFXLAN are completely different from those returned by the RFXtrx433, so even if I implement the 'virtual COM port' in node-rfxcom (not in itself that difficult) it won't actually help much. You will still need to write your own packet-decoding code.

However, if your implementation used the same event names and data formats as node-rfxcom, it should be possible to modify node-red-contrib-rfxcom to allow it to be used as an alternative 'serial port'. Take a look at the various packet handlers in node_modules/rfxcom/lib/rfxcom.js (or on github at https://github.com/rfxcom/node-rfxcom/blob/master/lib/rfxcom.js) to see what is required.