Description
This node-red example provides the solution to read Modbus INT64 type register through Milesight LoRaWAN controller.
Requirement
- Milesight Gateway: UG56/UG65/UG67
- Milesight LoRaWAN Controller (UC100/UC300/UC50x): This article will use the Milesight UC300 as an example
Configuration
Step 1: Enable the pass-through feature of the controller
Please refer to this article to enable the pass-through feature of the controller: How to use Modbus RS485 Bridge LoRaWAN Feature : IoT Support
Step 2: Launch Node-RED and Import Flow Example
- 1. Go to App > Node-RED page to enable Node-RED program and wait for a while to load the program, click Launch button to start Node-RED web GUI.
- 2. Log in the Node-RED web GUI. The account information is the same as gateway web GUI.
- 3. Click Import to import the node-red flow example by pasting the content or import the json format file.
Step 2: Node-RED Configuration
Flow structure:
Content:
[{"id":"6791bad1501bb22a","type":"tab","label":"Flow 2","disabled":false,"info":"","env":[]},{"id":"338cd43473e9c97e","type":"LoRa Output","z":"6791bad1501bb22a","name":"send modbus command read register1 to 4","eui":"24E124445C195920","payloadType":"hex","payload":"0103000000044409","confirmed":true,"port":"126","x":690,"y":120,"wires":[]},{"id":"9286d28233ec9617","type":"inject","z":"6791bad1501bb22a","name":"inject every 300 seconds","props":[],"repeat":"","crontab":"","once":true,"onceDelay":"300","topic":"","x":330,"y":120,"wires":[["338cd43473e9c97e"]]},{"id":"fa5877e64e18a487","type":"LoRa Input","z":"6791bad1501bb22a","name":"","devEUI":"","extendedField":"","x":180,"y":220,"wires":[["22927f94ad9846da"]]},{"id":"22927f94ad9846da","type":"Device Filter","z":"6791bad1501bb22a","name":"","eui":"24E124445C195920","x":410,"y":220,"wires":[["dcdc9cc58b8da59a"]]},{"id":"dcdc9cc58b8da59a","type":"function","z":"6791bad1501bb22a","name":"Extracting values and combining","func":"// Function to combine four 16-bit registers into a single 64-bit value\nfunction combineRegisters(msg_payload_base64) {\n // Step 1: Decode the Base64 payload to raw bytes\n let payload_bytes = Buffer.from(msg_payload_base64, 'base64');\n\n // Step 2: Convert the raw bytes to a hexadecimal string\n let payload_hex = payload_bytes.toString('hex');\n\n // Step 3: Extract the values of the four registers from the hexadecimal string\n // Assuming the values are 16-bit and stored consecutively\n let register1_hex = payload_hex.slice(6, 10); // First 4 characters (2 bytes) for register 1\n let register2_hex = payload_hex.slice(10, 14); // Next 4 characters (2 bytes) for register 2\n let register3_hex = payload_hex.slice(14, 18); // Next 4 characters (2 bytes) for register 3\n let register4_hex = payload_hex.slice(18, 22);// Next 4 characters (2 bytes) for register 4\n\n // Convert the hexadecimal values to integers\n let register1_value = parseInt(register1_hex, 16);\n let register2_value = parseInt(register2_hex, 16);\n let register3_value = parseInt(register3_hex, 16);\n let register4_value = parseInt(register4_hex, 16);\n\n // Step 4: Combine the four 16-bit register values into a single 64-bit value\n // JavaScript doesn't handle 64-bit integers natively, so we'll use BigInt\n let combined_value = (BigInt(register1_value) << 48n) |\n (BigInt(register2_value) << 32n) |\n (BigInt(register3_value) << 16n) |\n BigInt(register4_value);\n // current byte order is ABCDEFGH\n return { combined_value, payload_hex, register1_hex, register2_hex, register3_hex, register4_hex };\n}\n\n// Example usage\nlet msg_payload_base64 = msg.payload; // Assuming msg.payload contains the Base64 encoded payload\nlet result = combineRegisters(msg_payload_base64);\n\n// Add the combined value, hex payload, and register hex values to the message\nmsg.combined_value = result.combined_value;\nmsg.payload_hex = result.payload_hex;\nmsg.register1_hex = result.register1_hex;\nmsg.register2_hex = result.register2_hex;\nmsg.register3_hex = result.register3_hex;\nmsg.register4_hex = result.register4_hex;\n\n// Set the payload to an object containing combined_value, payload_hex, and register hex values\nmsg.payload = {\n combined_value: result.combined_value,\n payload_hex: result.payload_hex,\n register1_hex: result.register1_hex,\n register2_hex: result.register2_hex,\n register3_hex: result.register3_hex,\n register4_hex: result.register4_hex\n};\n\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":710,"y":220,"wires":[["40d119dc08447a5a"]]},{"id":"40d119dc08447a5a","type":"debug","z":"6791bad1501bb22a","name":"debug 5","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1000,"y":220,"wires":[]}] |
Inject Node: Setting the trigger time
LoRa Output Node: Send modbus command to modbus device, in this example, the command issued is to read the four registers at addresses 0-3
Modbus command example:
| Slave ID | Function | Address | Length | Parity |
| 0x01 | 0x03 | 0x00 0x00 | 0x00 0x04 | 0x44 0x09 |
LoRa Input Node: Receive LoRa packets
Device Filter Node: Filtering controller packets
Function Node: Combine the received values of the four registers and output the values of each of the four registers.
Debug Node: Output results
Step 3: Deploy and Check Result
- 1. Click Deploy to save all node-red configurations.
- 2. You can send modbus commands manually by clicking on the button on the left side of the Inject node and then view the results on the right side
-------END-----