Handling a large number of Modbus registers

Hello node-red community,

Is there a better way to read a large numbers of Modbus registers than having multiple Flex-Getters?

I'm trying to read registers from around 3,000 modbus channels (addressed 2414 to 5220) and have run into the problem of Modbus protocol being limited to a read of 127 registers per request... when testing with Function Code 3, any register quantity greater than 127 returned the following error in the Flex-Getter node (as expected):
"Error: Modbus exception 3: Illegal data value (value cannot be written to this register)".

I'd like to ask the experts here on how they would approach building such a flow. Having read the help on Modbus-Getter, Flex-Getter and Modbus-Sequencer, I believe Flex_Getter is still the way to go, although I'll need 24 of them, and I'm not sure if the flow will handle 24 simultaneous read requests (I'm not an experienced coder)

If it helps, the registers I'm hoping to read are a mixture of discrete, unsigned integers and real values.

Thank you in advance

Hello ... wow 3000 registers ? thats a lot .. thats going to need a lot of time to configure
are all the register requests done to one single device ?

initially in my Modbus project i was using the Modbus Flex Getters also but then i started using the
Modbus Sequencer and now there are fewer nodes in the flow and less clatter.

The above screenshot is a part of my flow

  1. At the very start of the flow i trigger a Function node (mbConfig) that holds all the modbus configuration needed for the Buffer parser node's to translate the modbus buffer data to the correct type (along with some additional information)
  2. I use the Cron-plus nodes for advanced scheduling (if needed) and triggering the sequences needed for the Modbus Sequencer nodes.
  3. Checking in an "error" Function whether a modbus read was successful and proceed to translate the data with buffer-parser.
  4. Save the data in Node-red's flow Context for later use (ie reading the data from Context and saving it to a Mongodb database)

Flow :

[{"id":"6a4362afb05b7723","type":"modbus-flex-sequencer","z":"a479605cda9a7cfd","name":"Inverter 1","sequences":[{"name":"","unitid":"31","fc":"FC4","address":"1","quantity":"34"}],"server":"845efb7462ba1aa1","showStatusActivities":true,"showErrors":true,"showWarnings":true,"logIOActivities":false,"useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":true,"keepMsgProperties":true,"delayOnStart":false,"startDelayTime":"","x":500,"y":240,"wires":[["b10965aab6b32ec4","ffacb9d6f2984b8e"],[]]},{"id":"d7d00d6cb8fcbda8","type":"function","z":"a479605cda9a7cfd","name":"sequences","func":"let mbConfig = flow.get(\"mbConfig\")\n\nif (mbConfig) {\n\n    msg.sequences = [\n        { topic: \"Inverter1\", fc: 3, unitid: 1, address: 40077, quantity: 78, specification: mbConfig.Inverter1a },\n        { topic: \"Inverter1\", fc: 3, unitid: 1, address: 40251, quantity: 3, specification: mbConfig.Inverter1b },\n    ]\n\n    return msg;\n}\n\nelse {\n    node.warn(\"No modbus configuration\")\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":330,"y":240,"wires":[["6a4362afb05b7723"]]},{"id":"b10965aab6b32ec4","type":"debug","z":"a479605cda9a7cfd","name":"debug 24","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":640,"y":160,"wires":[]},{"id":"4d83f77847b2570d","type":"buffer-parser","z":"a479605cda9a7cfd","name":"","data":"responseBuffer.buffer","dataType":"msg","specification":"specification","specificationType":"msg","items":[{"type":"floatbe","name":"V_31_L1","offset":0,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"floatbe","name":"V_31_L2","offset":4,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"floatbe","name":"V_31_L3","offset":8,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"floatbe","name":"A_31_L1","offset":24,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"floatbe","name":"A_31_L2","offset":28,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"floatbe","name":"A_31_L3","offset":32,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"floatbe","name":"P_31_L1","offset":36,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"floatbe","name":"P_31_L2","offset":40,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"floatbe","name":"P_31_L3","offset":44,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"floatbe","name":"P_31_T","offset":48,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"floatbe","name":"S_31_T","offset":64,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"floatbe","name":"Q_31_T","offset":80,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"floatbe","name":"PF_31_L1","offset":84,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"floatbe","name":"PF_31_L2","offset":88,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"floatbe","name":"PF_31_L3","offset":92,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"floatbe","name":"F_31_L1","offset":100,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"floatbe","name":"F_31_L2","offset":104,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"floatbe","name":"F_31_L3","offset":108,"length":1,"offsetbit":0,"scale":"1","mask":""}],"swap1":"","swap2":"","swap3":"","swap1Type":"swap","swap2Type":"swap","swap3Type":"swap","msgProperty":"payload","msgPropertyType":"str","resultType":"keyvalue","resultTypeType":"output","multipleResult":false,"fanOutMultipleResult":false,"setTopic":true,"outputs":1,"x":870,"y":220,"wires":[["9af0264f39e128e8","a18fb98da3f86bee"]]},{"id":"9af0264f39e128e8","type":"debug","z":"a479605cda9a7cfd","name":"debug 25","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1060,"y":180,"wires":[]},{"id":"ffacb9d6f2984b8e","type":"function","z":"a479605cda9a7cfd","name":"error","func":"let time = moment().format('YYYY-MM-DD HH:mm:ss')\nlet device = msg.topic\n\nif (msg.payload == \"\" || msg.hasOwnProperty('error')) {\n    flow.set(`mbStatus.${device}.status`, \"Disconnected\")\n    return null\n}\n\nelse {\n    flow.set(`mbStatus.${device}.status`, \"Connected\")\n    flow.set(`mbStatus.${device}.lastSeen`, time)\n    return msg;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[{"var":"moment","module":"moment"}],"x":710,"y":220,"wires":[["4d83f77847b2570d"]]},{"id":"fd771eed41af90c7","type":"inject","z":"a479605cda9a7cfd","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":130,"y":120,"wires":[["2b641b4f6abbc4b8"]]},{"id":"2b641b4f6abbc4b8","type":"function","z":"a479605cda9a7cfd","name":"mbConfig","func":"let mbConfig = {\n    Inverter1a: {\n        \"options\": { \"resultType\": \"object\", \"singleResult\": true, \"msgProperty\": \"payload\", \"setTopic\": true },\n        \"items\": [\n            { \"name\": \"PhaseVoltageAB\", \"description\": \"Phase Voltage AB\", \"unit\": \"V\", \"register\": 40077, \"type\": \"uint16\", \"offset\": 0, \"length\": 1, \"offsetbit\": 0, \"scale\": \"/10\", \"mask\": \"\" },\n            { \"name\": \"PhaseVoltageBC\", \"description\": \"Phase Voltage BC\", \"unit\": \"V\", \"register\": 40078, \"type\": \"uint16\", \"offset\": 2, \"length\": 1, \"offsetbit\": 0, \"scale\": \"/10\", \"mask\": \"\" },\n            { \"name\": \"PhaseVoltageAC\", \"description\": \"Phase Voltage AC\", \"unit\": \"V\", \"register\": 40079, \"type\": \"uint16\", \"offset\": 4, \"length\": 1, \"offsetbit\": 0, \"scale\": \"/10\", \"mask\": \"\" },\n            { \"name\": \"PhaseVoltageAN\", \"description\": \"Phase Voltage AN\", \"unit\": \"V\", \"register\": 40080, \"type\": \"uint16\", \"offset\": 6, \"length\": 1, \"offsetbit\": 0, \"scale\": \"/10\", \"mask\": \"\" },\n            { \"name\": \"PhaseVoltageBN\", \"description\": \"Phase Voltage BN\", \"unit\": \"V\", \"register\": 40081, \"type\": \"uint16\", \"offset\": 8, \"length\": 1, \"offsetbit\": 0, \"scale\": \"/10\", \"mask\": \"\" },\n            { \"name\": \"PhaseVoltageCN\", \"description\": \"Phase Voltage CN\", \"unit\": \"V\", \"register\": 40082, \"type\": \"uint16\", \"offset\": 10, \"length\": 1, \"offsetbit\": 0, \"scale\": \"/10\", \"mask\": \"\" },\n            { \"name\": \"ACPOWER\", \"description\": \"AC Power\", \"unit\": \"kW\", \"register\": 40084, \"type\": \"int16\", \"offset\": 14, \"length\": 1, \"offsetbit\": 0, \"scale\": \"/100\", \"mask\": \"\" },\n            { \"name\": \"FREQUENCY\", \"description\": \"Frequency\", \"unit\": \"Hz\", \"register\": 40086, \"type\": \"uint16\", \"offset\": 18, \"length\": 1, \"offsetbit\": 0, \"scale\": \"/100\", \"mask\": \"\" },\n            { \"name\": \"ACApparentPower\", \"description\": \"AC Apparent Power\", \"unit\": \"kVA\", \"register\": 40088, \"type\": \"int16\", \"offset\": 22, \"length\": 1, \"offsetbit\": 0, \"scale\": \"/100\", \"mask\": \"\" },\n            { \"name\": \"ACReactivePower\", \"description\": \"AC Reactive Power\", \"unit\": \"kVAr\", \"register\": 40090, \"type\": \"int16\", \"offset\": 26, \"length\": 1, \"offsetbit\": 0, \"scale\": \"/100\", \"mask\": \"\" },\n            { \"name\": \"ACPowerFactor\", \"description\": \"AC Power Factor\", \"unit\": \"kVA\", \"register\": 40092, \"type\": \"int16\", \"offset\": 30, \"length\": 1, \"offsetbit\": 0, \"scale\": \"/10000\", \"mask\": \"\" },\n            { \"name\": \"ACEnergy\", \"description\": \"AC Energy\", \"unit\": \"Wh\", \"register\": 40094, \"type\": \"uint32\", \"offset\": 34, \"length\": 1, \"offsetbit\": 0, \"scale\": \"/10000\", \"mask\": \"\" },\n            { \"name\": \"OperatingState_Off\", \"description\": \"Operating State Off\", \"unit\": \"bool\", \"register\": 40108, \"type\": \"bool\", \"offset\": 62, \"length\": 1, \"offsetbit\": 8, \"scale\": \"\", \"mask\": \"\" },\n            { \"name\": \"OperatingState_Sleeping\", \"description\": \"Operating State Sleeping\", \"unit\": \"bool\", \"register\": 40108, \"type\": \"bool\", \"offset\": 62, \"length\": 1, \"offsetbit\": 9, \"scale\": \"\", \"mask\": \"\" },\n            { \"name\": \"OperatingState_Starting\", \"description\": \"Operating State Starting\", \"unit\": \"bool\", \"register\": 40108, \"type\": \"bool\", \"offset\": 62, \"length\": 1, \"offsetbit\": 10, \"scale\": \"\", \"mask\": \"\" },\n            { \"name\": \"OperatingState_MPPT\", \"description\": \"Operating State MPPT\", \"unit\": \"bool\", \"register\": 40108, \"type\": \"bool\", \"offset\": 62, \"length\": 1, \"offsetbit\": 11, \"scale\": \"\", \"mask\": \"\" },\n            { \"name\": \"OperatingState_Throttled\", \"description\": \"Operating State Throttled\", \"unit\": \"bool\", \"register\": 40108, \"type\": \"bool\", \"offset\": 62, \"length\": 1, \"offsetbit\": 12, \"scale\": \"\", \"mask\": \"\" },\n            { \"name\": \"OperatingState_Shuttingdown\", \"description\": \"Operating State Shuttingdown\", \"unit\": \"bool\", \"register\": 40108, \"type\": \"bool\", \"offset\": 62, \"length\": 1, \"offsetbit\": 13, \"scale\": \"\", \"mask\": \"\" },\n            { \"name\": \"OperatingState_Fault\", \"description\": \"Operating State Fault\", \"unit\": \"bool\", \"register\": 40108, \"type\": \"bool\", \"offset\": 62, \"length\": 1, \"offsetbit\": 14, \"scale\": \"\", \"mask\": \"\" },\n            { \"name\": \"OperatingState_Standby\", \"description\": \"Operating State Standby\", \"unit\": \"bool\", \"register\": 40108, \"type\": \"bool\", \"offset\": 62, \"length\": 1, \"offsetbit\": 15, \"scale\": \"\", \"mask\": \"\" },\n            { \"name\": \"EventError_Groundfault\", \"description\": \"Ground fault\", \"unit\": \"bool\", \"register\": 40110, \"type\": \"bool\", \"offset\": 66, \"length\": 1, \"offsetbit\": 0, \"scale\": \"1\", \"mask\": \"\" },\n            { \"name\": \"EventError_DCovervoltage\", \"description\": \"DC over voltage\", \"unit\": \"bool\", \"register\": 40110, \"type\": \"bool\", \"offset\": 66, \"length\": 1, \"offsetbit\": 1, \"scale\": \"1\", \"mask\": \"\" },\n            { \"name\": \"EventError_ACdisconnectopen\", \"description\": \"AC disconnect open\", \"unit\": \"bool\", \"register\": 40110, \"type\": \"bool\", \"offset\": 66, \"length\": 1, \"offsetbit\": 2, \"scale\": \"1\", \"mask\": \"\" },\n            { \"name\": \"EventError_DCdisconnectopen\", \"description\": \"DC disconnect open\", \"unit\": \"bool\", \"register\": 40110, \"type\": \"bool\", \"offset\": 66, \"length\": 1, \"offsetbit\": 3, \"scale\": \"1\", \"mask\": \"\" },\n            { \"name\": \"EventError_Gridshutdown\", \"description\": \"Grid shutdown\", \"unit\": \"bool\", \"register\": 40110, \"type\": \"bool\", \"offset\": 66, \"length\": 1, \"offsetbit\": 4, \"scale\": \"1\", \"mask\": \"\" },\n            { \"name\": \"EventError_Cabinetopen\", \"description\": \"Cabinet open\", \"unit\": \"bool\", \"register\": 40110, \"type\": \"bool\", \"offset\": 66, \"length\": 1, \"offsetbit\": 5, \"scale\": \"1\", \"mask\": \"\" },\n            { \"name\": \"EventError_Manualshutdown\", \"description\": \"Manual shutdown\", \"unit\": \"bool\", \"register\": 40110, \"type\": \"bool\", \"offset\": 66, \"length\": 1, \"offsetbit\": 6, \"scale\": \"1\", \"mask\": \"\" },\n            { \"name\": \"EventError_Overtemperature\", \"description\": \"Over temperature\", \"unit\": \"bool\", \"register\": 40110, \"type\": \"bool\", \"offset\": 66, \"length\": 1, \"offsetbit\": 7, \"scale\": \"1\", \"mask\": \"\" },\n            { \"name\": \"EventError_FrequencyAboveLimit\", \"description\": \"Frequency above limit\", \"unit\": \"bool\", \"register\": 40110, \"type\": \"bool\", \"offset\": 66, \"length\": 1, \"offsetbit\": 8, \"scale\": \"1\", \"mask\": \"\" },\n            { \"name\": \"EventError_FrequencyUnderLimit\", \"description\": \"Frequency under limit\", \"unit\": \"bool\", \"register\": 40110, \"type\": \"bool\", \"offset\": 66, \"length\": 1, \"offsetbit\": 9, \"scale\": \"1\", \"mask\": \"\" },\n            { \"name\": \"EventError_ACVoltageAboveLimit\", \"description\": \"AC Voltage above limit\", \"unit\": \"bool\", \"register\": 40110, \"type\": \"bool\", \"offset\": 66, \"length\": 1, \"offsetbit\": 10, \"scale\": \"1\", \"mask\": \"\" },\n            { \"name\": \"EventError_ACVoltageUnderLimit\", \"description\": \"AC Voltage under limit\", \"unit\": \"bool\", \"register\": 40110, \"type\": \"bool\", \"offset\": 66, \"length\": 1, \"offsetbit\": 11, \"scale\": \"1\", \"mask\": \"\" },\n            { \"name\": \"EventError_BlownStringFuseOnInput\", \"description\": \"Blown String fuse on input\", \"unit\": \"bool\", \"register\": 40110, \"type\": \"bool\", \"offset\": 66, \"length\": 1, \"offsetbit\": 12, \"scale\": \"1\", \"mask\": \"\" },\n            { \"name\": \"EventError_UnderTemperature\", \"description\": \"Under temperature\", \"unit\": \"bool\", \"register\": 40110, \"type\": \"bool\", \"offset\": 66, \"length\": 1, \"offsetbit\": 13, \"scale\": \"1\", \"mask\": \"\" },\n            { \"name\": \"EventError_MemoryOrComError\", \"description\": \"Generic Memory or Communication error\", \"unit\": \"bool\", \"register\": 40110, \"type\": \"bool\", \"offset\": 66, \"length\": 1, \"offsetbit\": 14, \"scale\": \"1\", \"mask\": \"\" },\n            { \"name\": \"EventError_HardwareTestFailure\", \"description\": \"Hardware test failure\", \"unit\": \"bool\", \"register\": 40110, \"type\": \"bool\", \"offset\": 66, \"length\": 1, \"offsetbit\": 15, \"scale\": \"1\", \"mask\": \"\" },\n\n            { \"name\": \"WRtg\", \"description\": \"Continuous power output capability\", \"unit\": \"W\", \"register\": 40125, \"type\": \"uint16\", \"offset\": 96, \"length\": 1, \"offsetbit\": 0, \"scale\": \"1\", \"mask\": \"\" },\n            { \"name\": \"VARtg\", \"description\": \"Continuous Volt-Ampere capability\", \"unit\": \"VA\", \"register\": 40127, \"type\": \"uint16\", \"offset\": 100, \"length\": 1, \"offsetbit\": 0, \"scale\": \"1\", \"mask\": \"\" },\n            { \"name\": \"VArRtgQ1\", \"description\": \"Continuous VAR capability in quadrant 1\", \"unit\": \"var\", \"register\": 40129, \"type\": \"int16\", \"offset\": 104, \"length\": 1, \"offsetbit\": 0, \"scale\": \"1\", \"mask\": \"\" },\n            { \"name\": \"VArRtgQ2\", \"description\": \"Continuous VAR capability in quadrant 2\", \"unit\": \"var\", \"register\": 40130, \"type\": \"int16\", \"offset\": 106, \"length\": 1, \"offsetbit\": 0, \"scale\": \"1\", \"mask\": \"\" },\n            { \"name\": \"VArRtgQ3\", \"description\": \"Continuous VAR capability in quadrant 3\", \"unit\": \"var\", \"register\": 40131, \"type\": \"int16\", \"offset\": 108, \"length\": 1, \"offsetbit\": 0, \"scale\": \"1\", \"mask\": \"\" },\n            { \"name\": \"VArRtgQ4\", \"description\": \"Continuous VAR capability in quadrant 4\", \"unit\": \"var\", \"register\": 40132, \"type\": \"int16\", \"offset\": 110, \"length\": 1, \"offsetbit\": 0, \"scale\": \"1\", \"mask\": \"\" },\n            { \"name\": \"ARtg\", \"description\": \"Maximum RMS AC current level \", \"unit\": \"A\", \"register\": 40134, \"type\": \"uint16\", \"offset\": 114, \"length\": 1, \"offsetbit\": 0, \"scale\": \"1\", \"mask\": \"\" },\n            { \"name\": \"PFRtgQ1\", \"description\": \"Minimum power factor capability in quadrant 1\", \"unit\": \"cos\", \"register\": 40136, \"type\": \"int16\", \"offset\": 118, \"length\": 1, \"offsetbit\": 0, \"scale\": \"/1000\", \"mask\": \"\" },\n            { \"name\": \"PFRtgQ2\", \"description\": \"Minimum power factor capability in quadrant 2\", \"unit\": \"cos\", \"register\": 40137, \"type\": \"int16\", \"offset\": 120, \"length\": 1, \"offsetbit\": 0, \"scale\": \"/1000\", \"mask\": \"\" },\n            { \"name\": \"PFRtgQ3\", \"description\": \"Minimum power factor capability in quadrant 3\", \"unit\": \"cos\", \"register\": 40138, \"type\": \"int16\", \"offset\": 122, \"length\": 1, \"offsetbit\": 0, \"scale\": \"/1000\", \"mask\": \"\" },\n            { \"name\": \"PFRtgQ4\", \"description\": \"Minimum power factor capability in quadrant 4\", \"unit\": \"cos\", \"register\": 40139, \"type\": \"int16\", \"offset\": 124, \"length\": 1, \"offsetbit\": 0, \"scale\": \"/1000\", \"mask\": \"\" },\n\n            { \"name\": \"WMax\", \"description\": \"Max Active Power\", \"unit\": \"Hz\", \"register\": 40152, \"type\": \"uint16\", \"offset\": 150, \"length\": 1, \"offsetbit\": 0, \"scale\": \"*10\", \"mask\": \"\" }\n        ]\n    },\n    Inverter1b: {\n        \"options\": { \"resultType\": \"object\", \"singleResult\": true, \"msgProperty\": \"payload\", \"setTopic\": true },\n        \"items\": [\n            { \"name\": \"WMaxLimPct_SF\", \"type\": \"int16\", \"offset\": 0, \"length\": 1, \"offsetbit\": 0, \"scale\": \"\", \"mask\": \"\" },\n            { \"name\": \"OutPFSet_SF\", \"type\": \"int16\", \"offset\": 2, \"length\": 1, \"offsetbit\": 0, \"scale\": \"\", \"mask\": \"\" },\n            { \"name\": \"VArPct_SF\", \"type\": \"int16\", \"offset\": 4, \"length\": 1, \"offsetbit\": 0, \"scale\": \"\", \"mask\": \"\" },\n\n        ]\n    },\n    WeatherStation: {\n        \"options\": { \"resultType\": \"object\", \"singleResult\": true, \"msgProperty\": \"payload\", \"setTopic\": true },\n        \"items\": [\n            { \"name\": \"AmbientAirTemp\", \"description\": \"Ambient Air Temperature\", \"unit\": \"C\", \"register\": 71, \"type\": \"int16\", \"offset\": 0, \"length\": 1, \"offsetbit\": 0, \"scale\": \"/10\", \"mask\": \"\" },\n            { \"name\": \"RelativeHumidity\", \"description\": \"Relative Humidity\", \"unit\": \"%\", \"register\": 72, \"type\": \"int16\", \"offset\": 2, \"length\": 1, \"offsetbit\": 0, \"scale\": \"1\", \"mask\": \"\" },\n            { \"name\": \"WindSpeed\", \"description\": \"Wind Speed\", \"unit\": \"m/s\", \"register\": 74, \"type\": \"int16\", \"offset\": 6, \"length\": 1, \"offsetbit\": 0, \"scale\": \"1\", \"mask\": \"\" },\n            { \"name\": \"WindDirection\", \"description\": \"Wind Direction\", \"unit\": \"degrees\", \"register\": 75, \"type\": \"int16\", \"offset\": 8, \"length\": 1, \"offsetbit\": 0, \"scale\": \"1\", \"mask\": \"\" },\n            { \"name\": \"Irradiance\", \"description\": \"Irradiance\", \"unit\": \"W/m2\", \"register\": 85, \"type\": \"uint16\", \"offset\": 28, \"length\": 1, \"offsetbit\": 0, \"scale\": \"1\", \"mask\": \"\" },\n            { \"name\": \"ModuleTemp\", \"description\": \"Back of Module Temperature\", \"unit\": \"C\", \"register\": 91, \"type\": \"int16\", \"offset\": 40, \"length\": 1, \"offsetbit\": 0, \"scale\": \"/10\", \"mask\": \"\" }\n        ]\n    }\n};\n\nflow.set(\"mbConfig\", mbConfig)","outputs":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":320,"y":120,"wires":[]},{"id":"a18fb98da3f86bee","type":"function","z":"a479605cda9a7cfd","name":"set flow Context","func":"// update mbValues\nflow.set(`mbValues.${msg.topic}`, { ...flow.get(`mbValues.${msg.topic}`), ...msg.payload })","outputs":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1080,"y":260,"wires":[]},{"id":"0f668c269d58958a","type":"cronplus","z":"a479605cda9a7cfd","name":"","outputField":"payload","timeZone":"","persistDynamic":false,"commandResponseMsgOutput":"output1","outputs":1,"options":[{"name":"trigger","topic":"trigger","payloadType":"bool","payload":"true","expressionType":"cron","expression":"0 * * * * *","location":"","offset":"0","solarType":"all","solarEvents":"sunrise,sunset"}],"x":120,"y":240,"wires":[["d7d00d6cb8fcbda8"]]},{"id":"a2848741e340bedb","type":"modbus-flex-sequencer","z":"a479605cda9a7cfd","name":"Weather Station","sequences":[{"name":"","unitid":"31","fc":"FC4","address":"1","quantity":"34"}],"server":"fd44c76f6cc40678","showStatusActivities":true,"showErrors":true,"showWarnings":true,"logIOActivities":false,"useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":true,"keepMsgProperties":true,"delayOnStart":false,"startDelayTime":"","x":520,"y":460,"wires":[["21318d6b74852616","1870ec789d165d7a"],[]]},{"id":"1efca2d599cfaa7e","type":"function","z":"a479605cda9a7cfd","name":"sequences","func":"let mbConfig = flow.get(\"mbConfig\")\n\nif (mbConfig) {\n\n    msg.sequences = [\n        { topic: \"WeatherStation\", fc: 3, unitid: 1, address: 71, quantity: 21, specification: mbConfig.WeatherStation }\n    ]\n\n    return msg;\n}\n\nelse {\n    node.warn(\"No modbus configuration\")\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":330,"y":460,"wires":[["a2848741e340bedb"]]},{"id":"21318d6b74852616","type":"debug","z":"a479605cda9a7cfd","name":"debug 27","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":640,"y":380,"wires":[]},{"id":"b60f988aaf7ae0b9","type":"buffer-parser","z":"a479605cda9a7cfd","name":"","data":"responseBuffer.buffer","dataType":"msg","specification":"specification","specificationType":"msg","items":[{"type":"floatbe","name":"V_31_L1","offset":0,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"floatbe","name":"V_31_L2","offset":4,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"floatbe","name":"V_31_L3","offset":8,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"floatbe","name":"A_31_L1","offset":24,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"floatbe","name":"A_31_L2","offset":28,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"floatbe","name":"A_31_L3","offset":32,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"floatbe","name":"P_31_L1","offset":36,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"floatbe","name":"P_31_L2","offset":40,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"floatbe","name":"P_31_L3","offset":44,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"floatbe","name":"P_31_T","offset":48,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"floatbe","name":"S_31_T","offset":64,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"floatbe","name":"Q_31_T","offset":80,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"floatbe","name":"PF_31_L1","offset":84,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"floatbe","name":"PF_31_L2","offset":88,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"floatbe","name":"PF_31_L3","offset":92,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"floatbe","name":"F_31_L1","offset":100,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"floatbe","name":"F_31_L2","offset":104,"length":1,"offsetbit":0,"scale":"1","mask":""},{"type":"floatbe","name":"F_31_L3","offset":108,"length":1,"offsetbit":0,"scale":"1","mask":""}],"swap1":"","swap2":"","swap3":"","swap1Type":"swap","swap2Type":"swap","swap3Type":"swap","msgProperty":"payload","msgPropertyType":"str","resultType":"keyvalue","resultTypeType":"output","multipleResult":false,"fanOutMultipleResult":false,"setTopic":true,"outputs":1,"x":870,"y":440,"wires":[["8c0e896f61ee0095","cc3d1e307d947b1a"]]},{"id":"8c0e896f61ee0095","type":"debug","z":"a479605cda9a7cfd","name":"debug 28","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1060,"y":400,"wires":[]},{"id":"1870ec789d165d7a","type":"function","z":"a479605cda9a7cfd","name":"error","func":"let time = moment().format('YYYY-MM-DD HH:mm:ss')\nlet device = msg.topic\n\nif (msg.payload == \"\" || msg.hasOwnProperty('error')) {\n    flow.set(`mbStatus.${device}.status`, \"Disconnected\")\n    return null\n}\n\nelse {\n    flow.set(`mbStatus.${device}.status`, \"Connected\")\n    flow.set(`mbStatus.${device}.lastSeen`, time)\n    return msg;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[{"var":"moment","module":"moment"}],"x":710,"y":440,"wires":[["b60f988aaf7ae0b9"]]},{"id":"cc3d1e307d947b1a","type":"function","z":"a479605cda9a7cfd","name":"set flow Context","func":"// update mbValues\nflow.set(`mbValues.${msg.topic}`, { ...flow.get(`mbValues.${msg.topic}`), ...msg.payload })","outputs":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1080,"y":480,"wires":[]},{"id":"7a8d1e916af69919","type":"cronplus","z":"a479605cda9a7cfd","name":"","outputField":"payload","timeZone":"","persistDynamic":false,"commandResponseMsgOutput":"output1","outputs":1,"options":[{"name":"trigger","topic":"trigger","payloadType":"bool","payload":"true","expressionType":"cron","expression":"0 * * * * *","location":"","offset":"0","solarType":"all","solarEvents":"sunrise,sunset"}],"x":120,"y":460,"wires":[["1efca2d599cfaa7e"]]},{"id":"845efb7462ba1aa1","type":"modbus-client","name":"","clienttype":"tcp","bufferCommands":true,"stateLogEnabled":true,"queueLogEnabled":false,"failureLogEnabled":true,"tcpHost":"192.168.3.101","tcpPort":"502","tcpType":"DEFAULT","serialPort":"/dev/ttyUSB","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","serialAsciiResponseStartDelimiter":"0x3A","unit_id":1,"commandDelay":20,"clientTimeout":1000,"reconnectOnTimeout":true,"reconnectTimeout":2000,"parallelUnitIdsAllowed":true,"showWarnings":true,"showLogs":true},{"id":"fd44c76f6cc40678","type":"modbus-client","name":"","clienttype":"tcp","bufferCommands":true,"stateLogEnabled":false,"queueLogEnabled":false,"failureLogEnabled":true,"tcpHost":"192.168.3.202","tcpPort":"502","tcpType":"DEFAULT","serialPort":"/dev/ttyUSB","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","serialAsciiResponseStartDelimiter":"0x3A","unit_id":"1","commandDelay":"1","clientTimeout":"1000","reconnectOnTimeout":true,"reconnectTimeout":"2000","parallelUnitIdsAllowed":true,"showWarnings":true,"showLogs":true}]

Hi UnborN,

Thanks very much for your help and sharing your flow. I've been using excel to compile my channel list and can concatenate to build a list similar to your mbConfig - it's not too bad :slight_smile:

All the register requests are going to one device and the flow will be displaying data. Your approach is much neater than what I had imagined and working with the Context saves me from an incredibly messy flow, although it does mean I need to call up all the object payloads again to display them with dashboard text or LED. I've attached a section of my flow to show how I was planning to use Split Array to divide them out.

As you'll see I'd added the modbus configuration to the buffer parser payloads. Is this another way of doing it or just wrong? Regardless, I can see how moving this modbus configuration to the initial function is a far neater way.

As per your sequences function I'd also requested to read holding registers (FC3), not input registers (FC4), but in the Flex-Sequencer you've specified FC4. I do want to later write to some registers (only 4, thank goodness!), but am I right in thinking for read we can use either FC3 or FC4 in the Flex-Sequencer?

[
    {
        "id": "d238b3695eca3895",
        "type": "tab",
        "label": "Flow 2",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "f4d72957994e1aee",
        "type": "inject",
        "z": "d238b3695eca3895",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "0.5",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 190,
        "y": 300,
        "wires": [
            [
                "493442cd11f88caf"
            ]
        ],
        "info": "ACC Automation Sample Code"
    },
    {
        "id": "257b1984e3a725df",
        "type": "modbus-flex-getter",
        "z": "d238b3695eca3895",
        "name": "FlexGetter",
        "showStatusActivities": false,
        "showErrors": true,
        "showWarnings": true,
        "logIOActivities": false,
        "server": "80bd0b85736c5287",
        "useIOFile": false,
        "ioFile": "",
        "useIOForPayload": false,
        "emptyMsgOnFail": false,
        "keepMsgProperties": false,
        "delayOnStart": false,
        "startDelayTime": "",
        "x": 650,
        "y": 300,
        "wires": [
            [
                "4d360130c6da29bf",
                "a18f4832ab9aa1b0"
            ],
            [
                "84bf3fce53af4290"
            ]
        ]
    },
    {
        "id": "cf59269f8e2fcba9",
        "type": "comment",
        "z": "d238b3695eca3895",
        "name": "Modbus TCP Micro 820 PLC - Modbus TCP Sample Analog and Binary Controller",
        "info": "\n",
        "x": 400,
        "y": 100,
        "wires": []
    },
    {
        "id": "29677c63d91a3342",
        "type": "comment",
        "z": "d238b3695eca3895",
        "name": "Modbus Communication Update Interval",
        "info": "",
        "x": 270,
        "y": 260,
        "wires": []
    },
    {
        "id": "a18f4832ab9aa1b0",
        "type": "debug",
        "z": "d238b3695eca3895",
        "name": "debug 43",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 1020,
        "y": 300,
        "wires": []
    },
    {
        "id": "9f4d6151f7ffeace",
        "type": "inject",
        "z": "d238b3695eca3895",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "str",
        "x": 170,
        "y": 160,
        "wires": [
            [
                "11af13ae67ccfdb5"
            ]
        ]
    },
    {
        "id": "1337528a2bda76a7",
        "type": "debug",
        "z": "d238b3695eca3895",
        "name": "debug 44",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 640,
        "y": 160,
        "wires": []
    },
    {
        "id": "11af13ae67ccfdb5",
        "type": "modbus-server",
        "z": "d238b3695eca3895",
        "name": "",
        "logEnabled": false,
        "hostname": "10.10.10.20",
        "serverPort": "502",
        "responseDelay": 100,
        "delayUnit": "ms",
        "coilsBufferSize": 10000,
        "holdingBufferSize": "253",
        "inputBufferSize": "253",
        "discreteBufferSize": "253",
        "showErrors": false,
        "x": 380,
        "y": 160,
        "wires": [
            [
                "1337528a2bda76a7"
            ],
            [
                "1337528a2bda76a7"
            ],
            [
                "1337528a2bda76a7"
            ],
            [
                "1337528a2bda76a7"
            ],
            [
                "1337528a2bda76a7"
            ]
        ]
    },
    {
        "id": "493442cd11f88caf",
        "type": "function",
        "z": "d238b3695eca3895",
        "name": "Inject 16 word request",
        "func": "msg.payload = {\n    value: msg.payload,\n    'fc': 3, \n    'unitid': 1, \n    'address': 00000,\n    'quantity': 16 \n    }\nreturn msg;\n",
        "outputs": 1,
        "noerr": 1,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 420,
        "y": 300,
        "wires": [
            [
                "257b1984e3a725df"
            ]
        ]
    },
    {
        "id": "4d360130c6da29bf",
        "type": "modbus-response",
        "z": "d238b3695eca3895",
        "name": "",
        "registerShowMax": 20,
        "x": 1050,
        "y": 240,
        "wires": []
    },
    {
        "id": "84bf3fce53af4290",
        "type": "buffer-parser",
        "z": "d238b3695eca3895",
        "name": "",
        "data": "payload.buffer",
        "dataType": "msg",
        "specification": "spec",
        "specificationType": "ui",
        "items": [
            {
                "type": "bool",
                "name": "1",
                "offset": 2304,
                "length": 1,
                "offsetbit": 0,
                "scale": "1",
                "mask": ""
            },
            {
                "type": "int32le",
                "name": "2",
                "offset": 2305,
                "length": 1,
                "offsetbit": 0,
                "scale": "1",
                "mask": ""
            },
            {
                "type": "int32le",
                "name": "3",
                "offset": 2307,
                "length": 1,
                "offsetbit": 0,
                "scale": "1",
                "mask": ""
            },
            {
                "type": "int32le",
                "name": "4",
                "offset": 2309,
                "length": 1,
                "offsetbit": 0,
                "scale": "1",
                "mask": ""
            },
            {
                "type": "int32le",
                "name": "5",
                "offset": 2311,
                "length": 1,
                "offsetbit": 0,
                "scale": "1",
                "mask": ""
            },
            {
                "type": "bool",
                "name": "6",
                "offset": 2312,
                "length": 1,
                "offsetbit": 0,
                "scale": "1",
                "mask": ""
            },
            {
                "type": "bool",
                "name": "7",
                "offset": 2312,
                "length": 1,
                "offsetbit": 1,
                "scale": "1",
                "mask": ""
            },
            {
                "type": "bool",
                "name": "8",
                "offset": 2312,
                "length": 1,
                "offsetbit": 2,
                "scale": "1",
                "mask": ""
            },
            {
                "type": "bool",
                "name": "9",
                "offset": 2312,
                "length": 1,
                "offsetbit": 8,
                "scale": "1",
                "mask": ""
            },
            {
                "type": "bool",
                "name": "10",
                "offset": 2312,
                "length": 1,
                "offsetbit": 9,
                "scale": "1",
                "mask": ""
            },
            {
                "type": "bool",
                "name": "11",
                "offset": 2312,
                "length": 1,
                "offsetbit": 10,
                "scale": "1",
                "mask": ""
            }
        ],
        "swap1": "",
        "swap2": "",
        "swap3": "",
        "swap1Type": "swap",
        "swap2Type": "swap",
        "swap3Type": "swap",
        "msgProperty": "payload",
        "msgPropertyType": "str",
        "resultType": "keyvalue",
        "resultTypeType": "output",
        "multipleResult": false,
        "fanOutMultipleResult": false,
        "setTopic": true,
        "outputs": 1,
        "x": 850,
        "y": 320,
        "wires": [
            [
                "e8321b37542c42ca",
                "6715dd08396ca740"
            ]
        ]
    },
    {
        "id": "e8321b37542c42ca",
        "type": "debug",
        "z": "d238b3695eca3895",
        "name": "debug 45",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 1040,
        "y": 360,
        "wires": []
    },
    {
        "id": "6715dd08396ca740",
        "type": "split",
        "z": "d238b3695eca3895",
        "name": "Split Array",
        "splt": "\\n",
        "spltType": "str",
        "arraySplt": 1,
        "arraySpltType": "len",
        "stream": false,
        "addname": "topic",
        "x": 1050,
        "y": 440,
        "wires": [
            [
                "75afb43e58b0b2d9"
            ]
        ]
    },
    {
        "id": "75afb43e58b0b2d9",
        "type": "switch",
        "z": "d238b3695eca3895",
        "name": "MCU Alarms",
        "property": "topic",
        "propertyType": "msg",
        "rules": [
            {
                "t": "eq",
                "v": "1",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "2",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "3",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "4",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "5",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "6",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "7",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "8",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "9",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "10",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "11",
                "vt": "str"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 11,
        "x": 1270,
        "y": 440,
        "wires": [
            [],
            [],
            [],
            [],
            [],
            [],
            [],
            [],
            [],
            [],
            []
        ]
    },
    {
        "id": "80bd0b85736c5287",
        "type": "modbus-client",
        "name": "ModBus PLC",
        "clienttype": "tcp",
        "bufferCommands": true,
        "stateLogEnabled": false,
        "queueLogEnabled": false,
        "failureLogEnabled": true,
        "tcpHost": "10.10.10.20",
        "tcpPort": "502",
        "tcpType": "DEFAULT",
        "serialPort": "/dev/ttyUSB",
        "serialType": "RTU-BUFFERD",
        "serialBaudrate": "9600",
        "serialDatabits": "8",
        "serialStopbits": "1",
        "serialParity": "none",
        "serialConnectionDelay": "100",
        "serialAsciiResponseStartDelimiter": "0x3A",
        "unit_id": "1",
        "commandDelay": "1",
        "clientTimeout": "1000",
        "reconnectOnTimeout": true,
        "reconnectTimeout": "2000",
        "parallelUnitIdsAllowed": true,
        "showWarnings": true,
        "showLogs": true
    }
]

Nice .. yea i had to do that also in excel :+1: its useful especially for those byte offset calculations

true .. you need to read context again to display the data but in your project you can skip that part that im saving the final data also in Context and send them straight to the dashboard.

I saw your flow and I dont think this split of each individual value is needed. Whats wrong with the nice tidy object buffer-parser creates ? you'll need the Switch though to redirect the grouped values, based on Topic to the correct group of Dashboard nodes.

Actually that FC4 you see there in the Flex-sequencer is not used because we are sending the requests dynamically in msg.sequences but if i try to delete it, the node complains that its unconfigured so i left it there. (minor bug)

Hi UnborN,

Hope you had a good weekend and thanks again for your help. I still have quite a bit to learn about NR but sounds like I'm on the right track with everything except the Split here:

And I may look into using the Context function as I later want to be able to generate and read CSV files with time-stamped data that I'm readying over Modbus.

Cheers!

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.