Read device by RS485 ASCII

I don't know if that is what you want, flow is changing all the time, if you want me to temporary stop or hang it, it's not possible, because today I am working from my home.

I've got this program already and I red some informations about mqtt and yes, it looks good, better than modbus in this case :slight_smile:
The last thing is, if I have more these devices is possible to read them all? They are on the same RS485 line

As it is RS485 it will be possible but we will have to sequence the serial commands in a round-robin style

yes, i know, but I was hoping you would export your current flow (CTRL+E, copy to clipboard, paste in a reply) so I could prepare the next part.

Do you have mqtt explorer downloaded & ready?

@json_lame Could you copy the data returned by your serial port (for BOTH 81L and 81D commands)

like this...

image

and paste it between backticks please?

I have some flow for you (just need test data)

Quick promotion, thanks :slight_smile:
You mean like this?

FP210v20 81 200516175021 210.9
FP210v20 81 68535h1200001377480000137748

Which one is which?

FP210v20 81 200516175021 210.9 - 81D? or 81L?
FP210v20 81 68535h1200001377480000137748 - 81D? or 81L?

The first one is 81L, second is 81D

NOTE: this solution uses the node-red MQTT broker node node-red-contrib-aedes. If you already have a broker, deleted it otherwise install node/node-red-contrib-aedes node from the pallet manager.

So this is what I put together to make a (semi) final solution...

Please read through all the notes on the screen shot, the comment nodes and all the notes inside the functions to understand what its doing.

Once you understand (or not) give me a shout for the final stage (how to acces these MQTT values outside of Node-red - i.e. your SCADA)

the flow ....

[{"id":"90bf94b7.269648","type":"aedes broker","z":"c4135bb4.a5f418","name":"","mqtt_port":1883,"mqtt_ws_port":"","cert":"","key":"","certname":"","keyname":"","dburl":"","usetls":false,"x":330,"y":80,"wires":[[]],"info":"## Title\n### Info...\n- point 1\n- point 2\n\n*More info*"},{"id":"560dc5a6.ccf43c","type":"comment","z":"c4135bb4.a5f418","name":"NODE RED Based broker - delete if using mosquito","info":"### consider using standalone mosquito on the finished system","x":430,"y":40,"wires":[]},{"id":"f0999926.0a7238","type":"mqtt in","z":"c4135bb4.a5f418","name":"subscribe to # for testing purposes","topic":"#","qos":"2","datatype":"auto","broker":"4af1f016.58aaa","x":380,"y":200,"wires":[["adeed42f.2d27e8"]],"info":"## Title\n### Info...\n- point 1\n- point 2\n\n*More info*"},{"id":"adeed42f.2d27e8","type":"debug","z":"c4135bb4.a5f418","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":630,"y":200,"wires":[]},{"id":"5307778e.a29e98","type":"inject","z":"c4135bb4.a5f418","name":"","topic":"device1/test","payload":"hello device1","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":370,"y":320,"wires":[["69c72f1b.4bd6b"]],"info":"## Title\n### Info...\n- point 1\n- point 2\n\n*More info*"},{"id":"69c72f1b.4bd6b","type":"mqtt out","z":"c4135bb4.a5f418","name":"","topic":"","qos":"","retain":"","broker":"4af1f016.58aaa","x":590,"y":320,"wires":[]},{"id":"21bd0e3e.3dbaa2","type":"inject","z":"c4135bb4.a5f418","name":"Poll trigger","topic":"","payload":"","payloadType":"date","repeat":"1","crontab":"","once":false,"onceDelay":0.1,"x":310,"y":540,"wires":[["84cb5d9a.ec35"]],"info":"## Title\n### Info...\n- point 1\n- point 2\n\n*More info*"},{"id":"84cb5d9a.ec35","type":"function","z":"c4135bb4.a5f418","name":"get next COMM data","func":"\n//get poll_sequence from flow context\nvar poll_sequence = flow.get(\"poll_sequence\");\nif (poll_sequence == null) poll_sequence = -1;\n\n//get RS485Setup from flow context\nvar RS485Setup = flow.get(\"RS485Setup\") || [];\nif (RS485Setup.length <= 0){\n    node.warn(\"RS485Setup is empty\")\n    return null;\n}\n\n//increment to next poll seq\npoll_sequence++;\n\nif (poll_sequence >= RS485Setup.length ){\n    poll_sequence = 0;\n}\n\n//store current POLL in msg.poll\nmsg.poll = RS485Setup[poll_sequence];\nmsg.poll_sequence = poll_sequence;\nmsg.payload = new Buffer(\n    \" \" + //ESC \n    msg.poll.comm + \n    \"\\r\" //CR\n)\n//update buff element [0] to be an ESC char\nmsg.payload[0] = 27 //ESC\n\n//store current poll_seq\nflow.set(\"poll_sequence\", poll_sequence);\n\nreturn msg;//return the msg to next node","outputs":1,"noerr":0,"x":500,"y":540,"wires":[["34d2538a.63488c"]],"info":"## Title\n### Info...\n- point 1\n- point 2\n\n*More info*"},{"id":"8518ed37.4d14d","type":"inject","z":"c4135bb4.a5f418","name":"initialse","topic":"","payload":"true","payloadType":"bool","repeat":"","crontab":"","once":true,"onceDelay":0.1,"x":300,"y":440,"wires":[["e75d576b.4b24d8"]],"info":"## Title\n### Info...\n- point 1\n- point 2\n\n*More info*"},{"id":"e75d576b.4b24d8","type":"change","z":"c4135bb4.a5f418","name":"","rules":[{"t":"set","p":"RS485Setup","pt":"flow","to":"[{\"comm\":\"81L\",\"data\":[{\"topic\":\"device1/totaliser/t1\",\"data_start\":20,\"data_end\":30,\"dataType\":\"int\"},{\"topic\":\"device1/totaliser/t2\",\"data_start\":30,\"data_end\":40,\"dataType\":\"int\"}]},{\"comm\":\"81D\",\"data\":[{\"topic\":\"device1/flow\",\"data_start\":25,\"data_end\":31,\"dataType\":\"float\"}]}]","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":500,"y":440,"wires":[["e32ab155.7b9bf"]],"info":"## Title\n### Info...\n- point 1\n- point 2\n\n*More info*"},{"id":"34d2538a.63488c","type":"function","z":"c4135bb4.a5f418","name":"(fake serial port)","func":"\nif (msg.poll.comm.includes(\"81D\")){\n    msg.payload = `FP210v20 81 200516175021 123.${getRandomInt(0, 9)}\\n\\n`\n    return msg\n}\n\nif (msg.poll.comm.includes(\"81L\")){\n    msg.payload = `FP210v20 81 68535h120000456${getRandomInt(101, 999)}0000789${getRandomInt(101, 999)}\\n\\n`\n    return msg\n}\n\n\n\nreturn null;\n\n\n\nfunction getRandomInt(min, max) {\n    min = Math.ceil(min);\n    max = Math.floor(max);\n    return Math.floor(Math.random() * (max - min + 1)) + min;\n}","outputs":1,"noerr":0,"x":720,"y":540,"wires":[["98eb398d.e5a4a8","83a05335.69fb"]],"info":"## Title\n### Info...\n- point 1\n- point 2\n\n*More info*"},{"id":"98eb398d.e5a4a8","type":"debug","z":"c4135bb4.a5f418","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":930,"y":540,"wires":[],"info":"## Title\n### Info...\n- point 1\n- point 2\n\n*More info*"},{"id":"e32ab155.7b9bf","type":"debug","z":"c4135bb4.a5f418","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":950,"y":440,"wires":[]},{"id":"83a05335.69fb","type":"function","z":"c4135bb4.a5f418","name":"split items out, add topic, send payload","func":"var poll = msg.poll;\n// node.warn([\"poll\",poll]);\nfor (let index = 0; index < poll.data.length; index++) {\n    const e = poll.data[index];\n    //node.warn([\"poll.data[i]\", e]);\n    var valRaw = msg.payload.slice(e.data_start, e.data_end)\n    var val = valRaw;\n    switch(e.dataType){\n        case \"int\":\n            val = parseInt(valRaw);\n        break;\n        case \"float\":\n            val = parseFloat(valRaw);\n        break;\n    }  \n    node.send({\n        topic: e.topic,\n        payload: val,\n        valRaw: valRaw,\n        poll: e\n    });\n}\n\nreturn null;","outputs":1,"noerr":0,"x":550,"y":600,"wires":[["53ef92d1.3abf8c","8c9be340.715b3"]],"info":"## Title\n### Info...\n- point 1\n- point 2\n\n*More info*"},{"id":"58919633.39b1b8","type":"mqtt out","z":"c4135bb4.a5f418","name":"","topic":"","qos":"","retain":"","broker":"4af1f016.58aaa","x":930,"y":600,"wires":[],"info":"## Title\n### Info...\n- point 1\n- point 2\n\n*More info*"},{"id":"6eac4aa6.40bd04","type":"debug","z":"c4135bb4.a5f418","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":930,"y":660,"wires":[],"info":"## Title\n### Info...\n- point 1\n- point 2\n\n*More info*"},{"id":"53ef92d1.3abf8c","type":"rbe","z":"c4135bb4.a5f418","name":"","func":"rbe","gap":"","start":"","inout":"out","property":"payload","x":790,"y":600,"wires":[["58919633.39b1b8","6eac4aa6.40bd04"]]},{"id":"e4bde9f4.a8aa68","type":"comment","z":"c4135bb4.a5f418","name":"Setup what to POLL in  flow.RS485Setup  (inside the change node)","info":"","x":470,"y":400,"wires":[]},{"id":"b62c51c5.6d86d","type":"comment","z":"c4135bb4.a5f418","name":"Poll the entries in RS485Setup, request COM data, split data and generate new MQTT payloads","info":"","x":570,"y":500,"wires":[]},{"id":"758402e0.f7a28c","type":"comment","z":"c4135bb4.a5f418","name":"A test (to check MQTT is working)","info":"","x":370,"y":280,"wires":[]},{"id":"52ef13fb.806eec","type":"comment","z":"c4135bb4.a5f418","name":"Subscribe to # (while testing - to see MQTT data is working) - DELETE LATER","info":"### consider using standalone mosquito on the finished system","x":510,"y":160,"wires":[]},{"id":"8c9be340.715b3","type":"debug","z":"c4135bb4.a5f418","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":690,"y":660,"wires":[],"info":"## Title\n### Info...\n- point 1\n- point 2\n\n*More info*"},{"id":"4af1f016.58aaa","type":"mqtt-broker","z":"","name":"aedes local","broker":"localhost","port":"1883","clientid":"","usetls":false,"compatmode":false,"keepalive":"40","cleansession":true,"birthTopic":"aedes/state","birthQos":"0","birthPayload":"ready","closeTopic":"aedes/state","closeQos":"0","closePayload":"alert","willTopic":"aedes/state","willQos":"0","willPayload":"alert"}]

PS
This is what you should see in the debug window...

Okay, I'm getting started with this, I'll let you know, but this could be in 20 mins or 20 hours :upside_down_face:

Unfornatelly, there's one thing to explain, the "D" function is for flow, "L" is for totalisers, anyway stupid me, it's my fault, so in my last post first answer is for "81D", second is for "81L", once again sorry....

Sorry for posting one by one, I think it's working

Good stuff. Remember, if there is anything you dont understand, let me know.

Some tips + tasks (for learning)...

  • Connect to the broker by MQTT explorer
    • remember to connect to localhost or 127.0.0.1 (port 1883)
    • see the values changing
    • show me a screen shot
  • have a look in the context viewer in node-red - see if you can find where the RS485Setup array is stored
  • try adjusting the topic names from device1/totaliser/t1 to something more suitable
    • adjust the JSON in the change node
    • deploy (single node deploy)
    • press the inject
    • see what happens in MQTT explorer
  • Try adjusting the mqtt node - make items "retained" or set QoS to 1 or 2
1 Like

Ok, almost all of your list "to do" I made properly, for prove I got screen shots




Except last one, the values didn't retain, but at the moment this option isn't required. Now I would try to connect with my SCADA and let you know about progress

Ok, no problem.

Hope it helped.

Good luck.

PS: Retain is an option you set in the MQTT out node.

So, according to this I can only choose "tcp" or "ssl" connection, Asix can ask "mqtt driver" for flow and totalisers, but it can't establish connection. In MQTT Explorer i see two protocols to choose mqtt:// or ws://
So, is it possible to run mqtt as tcp node?

This is how MQTT works.

Look at this picture...

What it shows is that its a pub/sub model with a broker in the middle.

You (node-red) publish (via a topic) to a broker
Others (SCADA/node-red/ERP/wahtever you want) subscribes to your topic (and / or other topics).

so in other words, the MQTT Driver establishes the connection to the broker.

MQTT in standard mode (TCP) or WS (web socket)

Okay, if you are sure, that should work, I'll be patient and I'll take care of it, if something go well, I'll let you know.

One thing of note - that broker (node-red-contrib-aedes) is not a full blown broker so I would probably install mosquito & delete that node from your flow (to rule it out)

Sorry for my late reply, I'm trying to read that by asix, but it has problems, also I tried use Mosquito, with no effect.. I won't give up anyway and still tried make this working

1 Like

I would pursue the MQTT route. I'm certain by now you see how easy and flexible it is?

If asix cant help you get MQTT values then we could fall back to REST or worst case Modbus (though I wont be able to help you on that one)

Speak later.

Hi, so, I worked few hours about that, but no result. I tried also use Mosquitto, but only effect was list of errors on debug page, of course I read some topics and pages in Internet about it, but still no satisfay result.
How about REST? It's little more compicated I see, in addition I don't want waste your time.... It could turns that asix can't take this data by MQTT and REST, because ASKOM added this functionality quite recently and it has "childhood" problems if you know what I mean.
Could you help me with Mosquitto at least? Maybe it can send the data for asix properly....
Anyway, if that's possible now I prefer to use MQTT, because of it's simplicity

I am sure someone can help (mosquitto is generally easy to install and use) but without any clues to what problems you have it is impossible to suggest a solution.