I've relative success.. I've managed to make it work, for a few seconds.
All communication looks fine, but after a few seconds the motor stops communicating.
I figured that in the communication sometimes the motor repeats a command, and when that happens 2 times then the motor stops communication about 22 messages later.
I have added some timing measurements to calculate the difference between the time the command comes in and the time Node-Red sends the generated response. And it seems that when the time between command and response exceeds about 12ms, the motor resends its last command.
So somehow I need to make Node-Red reply within those 12ms. On average it generates a response in about 7 to 8ms but sometimes it takes up to 17ms.. and it seems to only take 2 times for the motor to stop communicating.
Any tips on how to make sure timings are below 12ms ?
Current flow:
[{"id":"34b3c5de9c4adf4f","type":"inject","z":"f9a4695ed5b7732a","name":"Busscan","props":[{"p":"topic","vt":"str"},{"p":"slaveid","v":"#:(volatile)::slaveid","vt":"flow"},{"p":"fc","v":"23","vt":"num"},{"p":"regReadAddr","v":"40121","vt":"num"},{"p":"regReadCount","v":"5","vt":"num"},{"p":"regWriteAddr","v":"40001","vt":"num"},{"p":"regWriteCount","v":"3","vt":"num"},{"p":"regWriteByteCount","v":"6","vt":"num"},{"p":"data","v":"[0,2,33,14,1,0]","vt":"bin"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":760,"y":140,"wires":[["13c627dcb0c2dcdc"]]},{"id":"b0de243bd7d3dea1","type":"buffer-maker","z":"f9a4695ed5b7732a","name":"build MB Request","specification":"specification","specificationType":"msg","items":[{"name":"slaveid","type":"uint8","length":1,"dataType":"msg","data":"slaveid"},{"name":"fc","type":"uint8","length":1,"dataType":"msg","data":"fc"},{"name":"regReadAddr","type":"uint16be","length":1,"dataType":"msg","data":"regReadAddr"},{"name":"regReadCount","type":"uint16be","length":1,"dataType":"msg","data":"regReadCount"},{"name":"regWriteAddr","type":"uint16be","length":1,"dataType":"msg","data":"regWriteAddr"},{"name":"regWriteCount","type":"uint16be","length":1,"dataType":"msg","data":"regWriteCount"},{"name":"regWriteByteCount","type":"uint8","length":1,"dataType":"msg","data":"regWriteByteCount"},{"name":"data","type":"buffer","length":6,"dataType":"msg","data":"data"}],"swap1":"","swap2":"","swap3":"","swap1Type":"swap","swap2Type":"swap","swap3Type":"swap","msgProperty":"payload","msgPropertyType":"str","x":450,"y":300,"wires":[["2bf23e25b6802ec1","d1b0c8e810a25324"]]},{"id":"2bf23e25b6802ec1","type":"debug","z":"f9a4695ed5b7732a","name":"Busscan request","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":690,"y":300,"wires":[]},{"id":"6596665f2f0d7825","type":"buffer-parser","z":"f9a4695ed5b7732a","name":"Parse MB Request SlaveID/FC","data":"payload","dataType":"msg","specification":"spec","specificationType":"ui","items":[{"type":"uint8","name":"header=>slaveid","offset":0,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"uint8","name":"header=>fc","offset":1,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"buffer","name":"buffer","offset":2,"length":-1,"offsetbit":0,"scale":"1","mask":""}],"swap1":"","swap2":"","swap3":"","swap1Type":"swap","swap2Type":"swap","swap3Type":"swap","msgProperty":"payload","msgPropertyType":"str","resultType":"keyvalue","resultTypeType":"return","multipleResult":false,"fanOutMultipleResult":false,"setTopic":true,"outputs":1,"x":470,"y":420,"wires":[["91655cce1fe28623","d938baaa86802cad"]]},{"id":"91655cce1fe28623","type":"debug","z":"f9a4695ed5b7732a","name":"Parsed UID/FC","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":720,"y":380,"wires":[]},{"id":"22ecae6ccb321a23","type":"switch","z":"f9a4695ed5b7732a","name":"Check FC","property":"payload.header.fc","propertyType":"msg","rules":[{"t":"eq","v":"16","vt":"str"},{"t":"eq","v":"23","vt":"num"},{"t":"else"}],"checkall":"true","repair":false,"outputs":3,"x":900,"y":480,"wires":[["bed14879abc62380"],["d368fb387a21f8a5"],["4a8b1480779248d6"]]},{"id":"4a8b1480779248d6","type":"debug","z":"f9a4695ed5b7732a","name":"Unknown functioncode","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload.header.fc","targetType":"msg","statusVal":"","statusType":"auto","x":1180,"y":800,"wires":[]},{"id":"d368fb387a21f8a5","type":"buffer-parser","z":"f9a4695ed5b7732a","name":"Parse MB FC23 Request","data":"payload.buffer","dataType":"msg","specification":"spec","specificationType":"ui","items":[{"type":"uint16be","name":"header=>regReadAddr","offset":0,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"uint16be","name":"header=>regReadCount","offset":2,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"uint16be","name":"header=>regWriteAddr","offset":4,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"uint16be","name":"header=>regWriteCount","offset":6,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"uint8","name":"header=>regWriteByteCount","offset":8,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"buffer","name":"data","offset":9,"length":-1,"offsetbit":0,"scale":"1","mask":""}],"swap1":"","swap2":"","swap3":"","swap1Type":"swap","swap2Type":"swap","swap3Type":"swap","msgProperty":"payload","msgPropertyType":"str","resultType":"keyvalue","resultTypeType":"return","multipleResult":false,"fanOutMultipleResult":false,"setTopic":true,"outputs":1,"x":1190,"y":660,"wires":[["5cb8fe9be9b67d13","1a683fd838a4c8d3"]]},{"id":"5cb8fe9be9b67d13","type":"debug","z":"f9a4695ed5b7732a","name":"FC23 Request","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1440,"y":620,"wires":[]},{"id":"d1b0c8e810a25324","type":"function","z":"f9a4695ed5b7732a","name":"Append CRC16","func":"function crc16(buf) {\n let crc = 0xFFFF;\n for (let i = 0; i < buf.length; i++) {\n crc = crc ^ buf[i];\n for (let j = 0; j < 8; j++) {\n const temp = crc & 0x01;\n crc >>= 0x01;\n if (temp == 0x01) {\n crc ^= 0xA001;\n }\n }\n }\n const arr = crc.toString(16).toUpperCase().substring(-4).padStart(4,\"0\").split(\"\")\n return Buffer.from(arr.splice(-2).concat(arr).join(\"\"), 'hex')\n}\n\nconst crc = crc16(msg.payload);\nmsg.crc = crc\nmsg.originalPayload = msg.payload;\nmsg.payload = Buffer.concat([msg.payload, crc]);\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":440,"y":340,"wires":[["5f88a33391993b96","67190339e15be57c"]]},{"id":"5f88a33391993b96","type":"debug","z":"f9a4695ed5b7732a","name":"CRC16 added","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":680,"y":340,"wires":[]},{"id":"835c3a54e5fc06c8","type":"serial in","z":"f9a4695ed5b7732a","name":"RS485-1 Modbus","serial":"ccba265ed98153e1","x":160,"y":420,"wires":[["67190339e15be57c"]]},{"id":"28130398b5b33ddc","type":"debug","z":"f9a4695ed5b7732a","name":"Serial IN","active":true,"tosidebar":true,"console":true,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":410,"y":460,"wires":[]},{"id":"d938baaa86802cad","type":"switch","z":"f9a4695ed5b7732a","name":"Filter on SlaveID","property":"payload.header.slaveid","propertyType":"msg","rules":[{"t":"eq","v":"#:(volatile)::slaveid","vt":"flow"},{"t":"eq","v":"0","vt":"num"}],"checkall":"true","repair":false,"outputs":2,"x":720,"y":420,"wires":[["219997bc83e4af1f"],["219997bc83e4af1f"]]},{"id":"219997bc83e4af1f","type":"function","z":"f9a4695ed5b7732a","name":"Check CRC16","func":"function crc16(buf) {\n let crc = 0xFFFF;\n for (let i = 0; i < buf.length; i++) {\n crc = crc ^ buf[i];\n for (let j = 0; j < 8; j++) {\n const temp = crc & 0x01;\n crc >>= 0x01;\n if (temp == 0x01) {\n crc ^= 0xA001;\n }\n }\n }\n const arr = crc.toString(16).toUpperCase().substring(-4).padStart(4, \"0\").split(\"\")\n return Buffer.from(arr.splice(-2).concat(arr).join(\"\"), 'hex')\n}\n\nconst buf = msg.originalPayload;\n\nif (Buffer.compare(crc16(buf.slice(0, buf.length - 2)), buf.slice(buf.length - 2)) != 0) {\n node.error(\"Invalid CRC\",msg)\n}\nelse {\n // strip CRC from payload\n msg.payload.buffer = msg.payload.buffer.slice(0, msg.payload.buffer.length - 2)\n msg.payload.header.crc = buf.slice(buf.length - 2)\n \n return msg;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":920,"y":420,"wires":[["79707be5c58757ad","22ecae6ccb321a23"]]},{"id":"79707be5c58757ad","type":"debug","z":"f9a4695ed5b7732a","name":"CRC validated","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1160,"y":400,"wires":[]},{"id":"ab858e79d16e9488","type":"inject","z":"f9a4695ed5b7732a","name":"Set Modbus SLAVE ID","props":[{"p":"payload"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"2","payloadType":"num","x":160,"y":140,"wires":[["f99e1c2bd90dd04e"]]},{"id":"f99e1c2bd90dd04e","type":"change","z":"f9a4695ed5b7732a","name":"","rules":[{"t":"set","p":"#:(volatile)::slaveid","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":400,"y":140,"wires":[[]]},{"id":"5f47048ecff39fbe","type":"buffer-maker","z":"f9a4695ed5b7732a","name":"Build MB Response","specification":"specification","specificationType":"msg","items":[{"name":"slaveid","type":"uint8","length":1,"dataType":"msg","data":"slaveid"},{"name":"fc","type":"uint8","length":1,"dataType":"msg","data":"fc"},{"name":"regReadAddr","type":"uint16be","length":1,"dataType":"msg","data":"regReadAddr"},{"name":"regReadCount","type":"uint16be","length":1,"dataType":"msg","data":"regReadCount"},{"name":"regWriteAddr","type":"uint16be","length":1,"dataType":"msg","data":"regWriteAddr"},{"name":"regWriteCount","type":"uint16be","length":1,"dataType":"msg","data":"regWriteCount"},{"name":"regWriteByteCount","type":"uint8","length":1,"dataType":"msg","data":"regWriteByteCount"},{"name":"data","type":"buffer","length":6,"dataType":"msg","data":"data"}],"swap1":"","swap2":"","swap3":"","swap1Type":"swap","swap2Type":"swap","swap3Type":"swap","msgProperty":"payload","msgPropertyType":"str","x":2090,"y":780,"wires":[["bf8a45364c5cc904"]]},{"id":"e79ea49b32a57a0e","type":"function","z":"f9a4695ed5b7732a","name":"Define MB FC23 Response","func":"msg.specification = {\n \"options\": {\n \"byteSwap\": false,\n \"resultType\": \"keyvalue\",\n \"msgProperty\": \"payload\",\n \"multipleResult\": false,\n \"setTopic\": true\n },\n \"items\": [ \n {\n \"name\": \"slaveid\",\n \"type\": \"uint8\",\n \"length\": 1,\n \"data\": flow.get('slaveid', 'volatile'),\n \"dataType\": \"number\"\n },\n {\n \"name\": \"fc\",\n \"type\": \"uint8\",\n \"length\": 1,\n \"data\": 23,\n \"dataType\": \"number\"\n },\n { \n \"name\": \"byteCount\",\n \"type\": \"uint8\",\n \"length\": 1,\n \"data\": msg.payload.header.regReadCount * 2,\n \"dataType\": \"number\"\n },\n {\n \"name\": \"regReadValue\",\n \"type\": \"buffer\",\n \"length\": msg.payload.header.regReadCount * 2,\n \"data\": 'response',\n \"dataType\": \"msg\"\n }\n ]\n};\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1840,"y":780,"wires":[["5f47048ecff39fbe"]]},{"id":"bf8a45364c5cc904","type":"function","z":"f9a4695ed5b7732a","name":"Append CRC16","func":"function crc16(buf) {\n let crc = 0xFFFF;\n for (let i = 0; i < buf.length; i++) {\n crc = crc ^ buf[i];\n for (let j = 0; j < 8; j++) {\n const temp = crc & 0x01;\n crc >>= 0x01;\n if (temp == 0x01) {\n crc ^= 0xA001;\n }\n }\n }\n const arr = crc.toString(16).toUpperCase().substring(-4).padStart(4,\"0\").split(\"\")\n return Buffer.from(arr.splice(-2).concat(arr).join(\"\"), 'hex')\n}\n\nconst crc = crc16(msg.payload);\nmsg.crc = crc\nmsg.originalPayload = msg.payload;\nmsg.payload = Buffer.concat([msg.payload, crc]);\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":2080,"y":820,"wires":[["69187ae18d9c993e","9e0e29280c9f1e93","13cebb7f4db22f4b"]]},{"id":"13cebb7f4db22f4b","type":"debug","z":"f9a4695ed5b7732a","name":"Response","active":true,"tosidebar":true,"console":true,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":2450,"y":920,"wires":[]},{"id":"1a683fd838a4c8d3","type":"switch","z":"f9a4695ed5b7732a","name":"regWriteAddr == 0x9C41","property":"payload.header.regWriteAddr","propertyType":"msg","rules":[{"t":"eq","v":"40001","vt":"num"}],"checkall":"true","repair":false,"outputs":1,"x":1470,"y":660,"wires":[["5ef12d4857ccbd0d"]]},{"id":"5ef12d4857ccbd0d","type":"switch","z":"f9a4695ed5b7732a","name":"regReadAddr == 0x9CB9","property":"payload.header.regReadAddr","propertyType":"msg","rules":[{"t":"eq","v":"40121","vt":"num"}],"checkall":"true","repair":false,"outputs":1,"x":1470,"y":700,"wires":[["14b45fdf66b2fba2"]]},{"id":"9752d156378625f7","type":"inject","z":"f9a4695ed5b7732a","name":"Command Request","props":[{"p":"topic","vt":"str"},{"p":"slaveid","v":"#:(volatile)::slaveid","vt":"flow"},{"p":"fc","v":"23","vt":"num"},{"p":"regReadAddr","v":"40121","vt":"num"},{"p":"regReadCount","v":"8","vt":"num"},{"p":"regWriteAddr","v":"40001","vt":"num"},{"p":"regWriteCount","v":"2","vt":"num"},{"p":"regWriteByteCount","v":"4","vt":"num"},{"p":"data","v":"[62,3,0,0]","vt":"bin"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":790,"y":180,"wires":[["13c627dcb0c2dcdc"]]},{"id":"13c627dcb0c2dcdc","type":"function","z":"f9a4695ed5b7732a","name":"Define MB FC23 Request","func":"msg.specification = {\n \"options\": {\n \"byteSwap\": false,\n \"resultType\": \"keyvalue\",\n \"msgProperty\": \"payload\",\n \"multipleResult\": false,\n \"setTopic\": true\n },\n \"items\": [ \n {\n \"name\": \"slaveid\",\n \"type\": \"uint8\",\n \"length\": 1,\n \"data\": msg.slaveid,\n \"dataType\": \"number\"\n },\n {\n \"name\": \"fc\",\n \"type\": \"uint8\",\n \"length\": 1,\n \"data\": msg.fc,\n \"dataType\": \"number\"\n },\n { \n \"name\": \"regReadAddr\",\n \"type\": \"uint16be\",\n \"length\": 1,\n \"data\": msg.regReadAddr,\n \"dataType\": \"number\"\n },\n { \n \"name\": \"regReadCount\",\n \"type\": \"uint16be\",\n \"length\": 1,\n \"data\": msg.regReadCount,\n \"dataType\": \"number\"\n },\n { \n \"name\": \"regWriteAddr\",\n \"type\": \"uint16be\",\n \"length\": 1,\n \"data\": msg.regWriteAddr,\n \"dataType\": \"number\"\n },\n { \n \"name\": \"regWriteCount\",\n \"type\": \"uint16be\",\n \"length\": 1,\n \"data\": msg.regWriteCount,\n \"dataType\": \"number\"\n },\n { \n \"name\": \"regWriteByteCount\",\n \"type\": \"uint8\",\n \"length\": 1,\n \"data\": msg.regWriteByteCount,\n \"dataType\": \"number\"\n },\n { \n \"name\": \"data\",\n \"type\": \"buffer\",\n \"length\": msg.regWriteByteCount,\n \"data\": msg.data,\n \"dataType\": \"buffer\"\n },\n \n ]\n};\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1090,"y":180,"wires":[["486c0c0425055075"]]},{"id":"b02751c7ddf4e2a9","type":"inject","z":"f9a4695ed5b7732a","name":"Empty Command Request","props":[{"p":"topic","vt":"str"},{"p":"slaveid","v":"#:(volatile)::slaveid","vt":"flow"},{"p":"fc","v":"23","vt":"num"},{"p":"regReadAddr","v":"40121","vt":"num"},{"p":"regReadCount","v":"2","vt":"num"},{"p":"regWriteAddr","v":"40001","vt":"num"},{"p":"regWriteCount","v":"2","vt":"num"},{"p":"regWriteByteCount","v":"4","vt":"num"},{"p":"data","v":"[62,4,23,1]","vt":"bin"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":810,"y":220,"wires":[["13c627dcb0c2dcdc"]]},{"id":"01dd4cb6f1d2a978","type":"comment","z":"f9a4695ed5b7732a","name":"Request (FC0x17)","info":"","x":1170,"y":620,"wires":[]},{"id":"71300ee246eb4d22","type":"comment","z":"f9a4695ed5b7732a","name":"Broadcast (FC0x10)","info":"","x":1170,"y":440,"wires":[]},{"id":"bed14879abc62380","type":"buffer-parser","z":"f9a4695ed5b7732a","name":"Parse MB FC16 Request","data":"payload.buffer","dataType":"msg","specification":"spec","specificationType":"ui","items":[{"type":"uint16be","name":"header=>regStartAddr","offset":0,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"uint16be","name":"header=>regCount","offset":2,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"int8","name":"header=>regByteCount","offset":4,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"buffer","name":"data","offset":5,"length":-1,"offsetbit":0,"scale":"1","mask":""}],"swap1":"","swap2":"","swap3":"","swap1Type":"swap","swap2Type":"swap","swap3Type":"swap","msgProperty":"payload","msgPropertyType":"str","resultType":"keyvalue","resultTypeType":"return","multipleResult":false,"fanOutMultipleResult":false,"setTopic":true,"outputs":1,"x":1190,"y":480,"wires":[["d8c73147a4506b02","d414925e057f7871"]]},{"id":"d8c73147a4506b02","type":"debug","z":"f9a4695ed5b7732a","name":"FC16 Request","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1440,"y":440,"wires":[]},{"id":"d414925e057f7871","type":"switch","z":"f9a4695ed5b7732a","name":"regStartAddr == 0x9D31","property":"payload.header.regStartAddr","propertyType":"msg","rules":[{"t":"eq","v":"40241","vt":"num"}],"checkall":"true","repair":false,"outputs":1,"x":1470,"y":480,"wires":[["cc04d25c7d046bab"]]},{"id":"cc04d25c7d046bab","type":"switch","z":"f9a4695ed5b7732a","name":"regCount == 0x0009","property":"payload.header.regCount","propertyType":"msg","rules":[{"t":"eq","v":"9","vt":"num"}],"checkall":"true","repair":false,"outputs":1,"x":1460,"y":520,"wires":[["373fbfea2d74cb3d"]]},{"id":"373fbfea2d74cb3d","type":"buffer-parser","z":"f9a4695ed5b7732a","name":"Parse state message","data":"payload.data","dataType":"msg","specification":"spec","specificationType":"ui","items":[{"type":"uint8","name":"door=>targetPosition","offset":2,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"uint8","name":"door=>currentPosition","offset":3,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"uint8","name":"door=>currentState","offset":4,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"uint8","name":"light=>currentState","offset":13,"length":1,"offsetbit":0,"scale":"1","mask":""}],"swap1":"","swap2":"","swap3":"","swap1Type":"swap","swap2Type":"swap","swap3Type":"swap","msgProperty":"payload","msgPropertyType":"str","resultType":"keyvalue","resultTypeType":"return","multipleResult":false,"fanOutMultipleResult":false,"setTopic":true,"outputs":1,"x":1460,"y":560,"wires":[["9386bde41f2c9747","19654d26157c8696"]]},{"id":"9386bde41f2c9747","type":"debug","z":"f9a4695ed5b7732a","name":"Parsed state","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1710,"y":520,"wires":[]},{"id":"581d2bcbc036f110","type":"link in","z":"f9a4695ed5b7732a","name":"Modbus TEST IN","links":["486c0c0425055075","2c87f36ebca4b7d4"],"x":225,"y":300,"wires":[["b0de243bd7d3dea1"]]},{"id":"486c0c0425055075","type":"link out","z":"f9a4695ed5b7732a","name":"","mode":"link","links":["581d2bcbc036f110"],"x":1265,"y":180,"wires":[]},{"id":"656d7340736f932f","type":"function","z":"f9a4695ed5b7732a","name":"Define MB FC16 Request","func":"msg.specification = {\n \"options\": {\n \"byteSwap\": false,\n \"resultType\": \"keyvalue\",\n \"msgProperty\": \"payload\",\n \"multipleResult\": false,\n \"setTopic\": true\n },\n \"items\": [ \n {\n \"name\": \"slaveid\",\n \"type\": \"uint8\",\n \"length\": 1,\n \"data\": \"slaveid\",\n \"dataType\": \"msg\"\n },\n {\n \"name\": \"fc\",\n \"type\": \"uint8\",\n \"length\": 1,\n \"data\": 16,\n \"dataType\": \"number\"\n },\n {\n \"name\": \"regStartAddr\",\n \"type\": \"uint16be\",\n \"length\": 1,\n \"data\": msg.regStartAddr,\n \"dataType\": \"number\"\n },\n {\n \"name\": \"regCount\",\n \"type\": \"uint16be\",\n \"length\": 1,\n \"data\": msg.regCount,\n \"dataType\": \"number\"\n },\n {\n \"name\": \"regByteCount\",\n \"type\": \"uint8\",\n \"length\": 1,\n \"data\": msg.regByteCount,\n \"dataType\": \"number\"\n },\n { \n \"name\": \"data\",\n \"type\": \"buffer\",\n \"length\": msg.regByteCount,\n \"data\": msg.data,\n \"dataType\": \"buffer\"\n },\n \n ]\n};\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1790,"y":180,"wires":[["2c87f36ebca4b7d4"]]},{"id":"2c87f36ebca4b7d4","type":"link out","z":"f9a4695ed5b7732a","name":"","mode":"link","links":["581d2bcbc036f110"],"x":1975,"y":180,"wires":[]},{"id":"192192344ecb3966","type":"inject","z":"f9a4695ed5b7732a","name":"Door closed, light off, idle","props":[{"p":"topic","vt":"str"},{"p":"slaveid","v":"0","vt":"num"},{"p":"regStartAddr","v":"40241","vt":"num"},{"p":"regCount","v":"9","vt":"num"},{"p":"regByteCount","v":"18","vt":"num"},{"p":"data","v":"[83,0,0,0,64,96,0,0,0,0,0,0,0,0,0,1,0,0]","vt":"bin"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":1510,"y":140,"wires":[["656d7340736f932f"]]},{"id":"a206f943ed9f8b39","type":"change","z":"f9a4695ed5b7732a","name":"set flow.portstates, flow.lightstates","rules":[{"t":"set","p":"#:(volatile)::portstates","pt":"flow","to":"{\"stateCode\":[0,1,2,5,9,10,32,64,128],\"stateStr\":[\"Stopped\",\"Opening\",\"Closing\",\"Move Half\",\"Move Venting\",\"Venting\",\"Open\",\"Closed\",\"Half Open\"]}","tot":"json"},{"t":"set","p":"#:(volatile)::lightstates","pt":"flow","to":"{\"stateCode\":[0,4,16,20],\"stateStr\":[\"Off\",\"Dimming to Off\",\"On\",\"Dimming to On\"]}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":460,"y":180,"wires":[[]]},{"id":"a84fde3d5fa34250","type":"inject","z":"f9a4695ed5b7732a","name":"Init Door/Light states","props":[{"p":"payload"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":160,"y":180,"wires":[["a206f943ed9f8b39"]]},{"id":"19654d26157c8696","type":"function","z":"f9a4695ed5b7732a","name":"Save current state","func":"const portstates = flow.get('portstates', 'volatile');\nconst lightstates = flow.get('lightstates', 'volatile');\n\nvar garagepoort = global.get('garagepoort', 'persistent') || {\n state: portstates.stateStr[0],\n position: 0\n};\nvar licht = global.get('licht.garagepoort', 'persistent') || {\n state: false\n};\n\n// Set new door state\nif (portstates.stateCode.includes(msg.payload.door.currentState)) {\n if (portstates.stateStr[portstates.stateCode.indexOf(msg.payload.door.currentState)] != garagepoort.state) {\n garagepoort.state = portstates.stateStr[portstates.stateCode.indexOf(msg.payload.door.currentState)];\n }\n} else {\n node.error(\"Unknown door state: \" + msg.payload.door.currentState);\n}\n\n// Set new door position\nif (garagepoort.position != msg.payload.door.currentPosition / 2) {\n garagepoort.position = msg.payload.door.currentPosition / 2;\n}\n\n// Set new light state\nif (lightstates.stateCode.includes(msg.payload.light.currentState)) {\n if (licht.state != (lightstates.stateStr[lightstates.stateCode.indexOf(msg.payload.light.currentState)] == \"On\" ||\n lightstates.stateStr[lightstates.stateCode.indexOf(msg.payload.light.currentState)] == \"Dimming to On\")) {\n licht.state = (lightstates.stateStr[lightstates.stateCode.indexOf(msg.payload.light.currentState)] == \"On\" ||\n lightstates.stateStr[lightstates.stateCode.indexOf(msg.payload.light.currentState)] == \"Dimming to On\");\n }\n} else {\n node.error(\"Unknown light state: \" + msg.payload.light.currentState);\n}\n\n// Save new states\nglobal.set('garagepoort', garagepoort, 'persistent');\nglobal.set('licht.garagepoort', licht, 'persistent');","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1730,"y":560,"wires":[[]]},{"id":"e40bc22e0247fecb","type":"inject","z":"f9a4695ed5b7732a","name":"Door opening, light on, 0%","props":[{"p":"topic","vt":"str"},{"p":"slaveid","v":"0","vt":"num"},{"p":"regStartAddr","v":"40241","vt":"num"},{"p":"regCount","v":"9","vt":"num"},{"p":"regByteCount","v":"18","vt":"num"},{"p":"data","v":"[83,0,200,0,1,96,0,0,0,0,0,0,0,20,0,1,0,0]","vt":"bin"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":1510,"y":180,"wires":[["656d7340736f932f"]]},{"id":"9be3c86e0f36598d","type":"inject","z":"f9a4695ed5b7732a","name":"Door opening, light on, 2%","props":[{"p":"topic","vt":"str"},{"p":"slaveid","v":"0","vt":"num"},{"p":"regStartAddr","v":"40241","vt":"num"},{"p":"regCount","v":"9","vt":"num"},{"p":"regByteCount","v":"18","vt":"num"},{"p":"data","v":"[85,0,200,4,1,96,0,0,0,0,0,0,0,20,0,1,0,0]","vt":"bin"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":1510,"y":220,"wires":[["656d7340736f932f"]]},{"id":"9e0e29280c9f1e93","type":"serial out","z":"f9a4695ed5b7732a","name":"RS485-1 Modbus","serial":"ccba265ed98153e1","x":2470,"y":860,"wires":[]},{"id":"14b45fdf66b2fba2","type":"buffer-parser","z":"f9a4695ed5b7732a","name":"Parse data","data":"payload.data","dataType":"msg","specification":"spec","specificationType":"ui","items":[{"type":"uint8","name":"counter","offset":0,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"uint8","name":"command","offset":1,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"buffer","name":"data","offset":2,"length":-1,"offsetbit":0,"scale":"1","mask":""}],"swap1":"","swap2":"","swap3":"","swap1Type":"swap","swap2Type":"swap","swap3Type":"swap","msgProperty":"payload.data","msgPropertyType":"str","resultType":"keyvalue","resultTypeType":"return","multipleResult":false,"fanOutMultipleResult":false,"setTopic":true,"outputs":1,"x":1430,"y":740,"wires":[["c590619c45a933c6"]]},{"id":"ed1df68a044dec31","type":"debug","z":"f9a4695ed5b7732a","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":2050,"y":700,"wires":[]},{"id":"a7924377169d7ec5","type":"function","z":"f9a4695ed5b7732a","name":"Generate response data","func":"// Init response header\nconst header = [msg.payload.data.counter, \"00\", msg.payload.data.command];\nvar response;\n\nswitch(msg.payload.data.command) {\n case 2: // Busscan\n response = header.concat([\"05\", \"04\", \"48\", \"16\", \"255\", \"168\", \"69\"]);\n break;\n case 3: // Command request\n response = header.concat([\"01\", \"00\", \"00\", \"00\", \"00\", \"00\", \"00\", \"00\", \"00\", \"00\", \"00\", \"00\", \"00\",]);\n break;\n case 4: // Empty command\n response = header.concat([\"253\"]);\n break;\n default:\n node.error('Unknown command received: ' + msg.payload.data.command, msg)\n}\n\nmsg.response = Buffer.from(response);\nreturn msg","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1830,"y":740,"wires":[["ed1df68a044dec31","e79ea49b32a57a0e"]]},{"id":"c590619c45a933c6","type":"change","z":"f9a4695ed5b7732a","name":"Set Counter","rules":[{"t":"set","p":"#:(volatile)::cmdCounter","pt":"flow","to":"payload.data.counter","tot":"msg"},{"t":"set","p":"#:(volatile)::command","pt":"flow","to":"payload.data.command","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1610,"y":740,"wires":[["a7924377169d7ec5"]]},{"id":"67190339e15be57c","type":"function","z":"f9a4695ed5b7732a","name":"Add timestamp","func":"var d = new Date();\nmsg.timestamp = d.getTime();\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":300,"y":540,"wires":[["28130398b5b33ddc","6596665f2f0d7825"]]},{"id":"69187ae18d9c993e","type":"function","z":"f9a4695ed5b7732a","name":"Calc timing","func":"var d = new Date();\nvar current_time = d.getTime();\n\nmsg.timing = (current_time - msg.timestamp);\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":2270,"y":960,"wires":[["6ac86868b1aac8d6"]]},{"id":"6ac86868b1aac8d6","type":"debug","z":"f9a4695ed5b7732a","name":"","active":true,"tosidebar":true,"console":true,"tostatus":false,"complete":"timing","targetType":"msg","statusVal":"","statusType":"auto","x":2450,"y":960,"wires":[]},{"id":"e5388905e48fa181","type":"comment","z":"f9a4695ed5b7732a","name":"Settings","info":"","x":100,"y":80,"wires":[]},{"id":"cd7d97874dbe88c0","type":"comment","z":"f9a4695ed5b7732a","name":"Request simulation","info":"","x":770,"y":80,"wires":[]},{"id":"d09334570558bd6e","type":"comment","z":"f9a4695ed5b7732a","name":"Broadcast simulation","info":"","x":1470,"y":80,"wires":[]},{"id":"ccba265ed98153e1","type":"serial-port","serialport":"/dev/ttymxc0","serialbaud":"57600","databits":"8","parity":"even","stopbits":"1","waitfor":"","dtr":"none","rts":"none","cts":"none","dsr":"none","newline":"1.75","bin":"bin","out":"interbyte","addchar":"","responsetimeout":"10000"}]