ecl110
ecl110 copied to clipboard
Figure out the purpose of DLG
Danfoss Link Gateway or 087H3241 is a companion device for connecting ECL Comfort 110 with Danfoss Link CC. As the name says it acts as a gateway between the RS485 line and 868MHz RF communication.
An application example from http://heating.danfoss.com/PCMPDF/087H9216_VIJMC36K_DLG_ECL110_Link_IG.pdf shows how it should connect, however the indoor temperature sensor S2 is missing, replaced by DLG. Documentation doesn't mention anywhere that S2 should be removed (but should make sense as Danfoss Link temperature sensors should be used. Confirm whether S2 is omitted intentionally or it serves for illustrative purposes only.
http://heating.danfoss.com/PCMPDF/VDKTC902_ECL110_LINK.pdf promises the following:
By system integration of ECL Comfort 110 and Danfoss Link™ via the DLG interface the following is achieved: • Heating is ON whenever there is a demand
Water is only circulated (pump is on) when any of the radiator valves is open/the indoor temperature is below threshold? We can control the pump in manual mode, but that is not possible in comfort mode. My gut feeling tells that Danfoss Link CC somehow provides additional control information to ECL110, but no idea what it is.
• Heating is operated from only one interface
That one interface being Danfoss Link, not useful for us.
• Heating comfort is achieved with the lowest energy consumption
Given that heating is not ON 24/7, same as 1?
• Outdoor temperature is shown in the Danfoss Link™ panel.
Reads outdoor temperature sensor S1 from PNU 11200, we can do that already.
It doesn't hurt to ask Danfoss regarding the working principle either, it shouldn't be a huge secret how the ECL110 controlling part works.
If you happen to own a DLG and rest of the system (mainly Danfoss Link CC), it would be extremely helpful if the communication was sniffed using a USB-to-RS485 adapter ($1 from ebay) and a computer to connect it to. I can provide further instructions if necessary. The process is nondestructive and safe to do.
To sweeten the deal, I can offer a 014G0002 for anyone in return.
I recently installed a DLG along with a ECL 110. I can make an effort and see if I can buy a cheap adapter. However, I do need the instructions :)
It does turn off the pump and close the valve for the incoming district heating when there is not temperature demand.

Interesting, thank you for posting this.
Could you perhaps provide some information about what DLG does or can do when it is connected to ECL110. Because this is not explained very well on the website at all. Basically what we are interested in is what does it do better than just ECL110 alone.
I can probably provide some further information later tonight if you are interested in monitoring the communication between DLG and ECL110.
One key feature for me is the ability to schedule the heating from the same app I use with my other Danfoss thermostats and the floor heating (controller by a Danfoss HC, a second one is to be installed). This will allow me to tune my heating in absurdum. I can set away from home temperature on the go, from anywhere.
Another key feature is, as mentioned, that heat will be delivered when wanted somewhere in the system. This will allow me to have a nice warm floor in my bathrooms even during summer time. This would else require me to adjust the indoor temperature on the ECL 110 to above 23 degrees, which would waste some heat during transfer. It would also require me to upgrade all thermostats in the house to Danfoss Link. I have a garage and a basement room which is not covered by the Link CC (yet...).
The ECL 110 is in auto mode, and the DLG seems to adjust all that is needed in order to maintain the heat. I don't know if the Link system keeps track of an internal heat curve. I've yet to observe the water temperature demanded by the DLG to see if I can map it to any logical step of the heat curve or if it is an arbitrary "this should do" number.
My home consists in total of 10 Living Connect thermostats (I have one more not yet installed), 1 HC with five actuators controlled by 3 Danfoss Icon and the DLG. I will soon wire my HC to controll the shunt pump also.
Impressive setup!
So far we know pretty much how to read or change data that you can access through the LCD and buttons on the ECL110, because it was very easy to correlate most of these things with the MODBUS readings. For logging purposes it is also possible to read all of the information about status that appears on the LCD, like temperature readouts and pump/valve status and then store it in a time series database for later analysis.
To me it feels like the feature that we do not know how to imitate yet is notifying ECL110 of the demand. If we figure this out, it would instantly make the device a lot better for anyone also using MODBUS to control the ECL110. Any clue if the demand is represented as a "yes/no" signal or does it correspond to any specific temperature that is demanded?
Thanks for clarifying that you use AUTO mode. I'm using COMFORT, but I really cannot remember if there was any significant difference.
I see that you don't have S2 indoor temperature sensor connected (correct me if I am wrong). If you open the temperature submenu (hold enter when you are on the room temperature line), is there anything in S2 that might be interpreted as demand? Perhaps this already provides any hints on how it works. To me it felt that S2 desired temp. is always the same as the set room temperature in main menu, but let me know if they are different in case of demand.
Lastly, you are probably running version 1.08, correct?
Here is a small outline of the procedure how to start recording data between ECL110 and DLG:
Basically you are looking for an adapter like this: https://www.aliexpress.com/wholesale?trafficChannel=main&d=y&CatId=0&SearchText=usb+to+rs485<ype=wholesale&SortType=price_asc&page=1
They are about 4-5 EUR on ebay Europe and perhaps something similar on amazon, knowing that ordering from China might turn out more expensive for anyone in Sweden. If you are willing to wait up to two full weeks (based on last package I sent to Sweden a few months ago), I can also send mine once I can find it - haven't used it for a while.

All you have to do is extend the A and B wires from the connector on the ECL 110 side to the USB adapter. Since you can just unscrew the two middle wires from connector on the ECL110 side, you can temporarily fit two extension wires between the terminal block and screw it back together.
To record the traffic between the devices, it is possible to use any serial port program (for windows: tera term, putty, mobaxterm etc...) with these settings. But there are also some programs that can decode modbus from a serial port stream directly, which also might be easier to use. Last time I used some .NET modbus library together with a simple 20-line console application to read in values.
Once there is data coming in, the best would be to go through all of the features it has so everything gets recorded for later analysis. Power cycling to see initialization process could be of interest as well.
I placed an order for the RS485 stick (and also for two IR readers so I can get real time district heating readings..). I will get back to you when they arrive. The shipping estimates is in the range 30-50 days..
You are correct that I don't have an indoor sensor hooked up. I have one spare that was included with the ECL 110. I can try what you suggested, and also do the same with the indoor sensor connected. I will have to get back to you regarding the software version and also if the demand is binary or some number (by hunch).
I did notice that the DLG has one RJ45. I guess I can use USB to RS485 with RJ45 socket to connect (something like this: https://www.kjell.com/se/produkter/el-verktyg/stromforsorjning/solceller/usb-till-rs485-adapter-for-regulator-p45135 (swedish)).
Isn't the RJ45 in use when DLG is connected to ECL110?
It's free as a bird! The MODBUS cord uses the same connector as power. Can attach photo later today.
Please do :). I thought it would connect to RJ45 on the DLG side like shown in manual:

The adapter looks like the one you'd want to use if RJ45 carried the MODBUS connections, but beware that there probably isn't a standard on how to wire RJ45 for MODBUS. So Epever (or whoever made the cable) and Danfoss could have used different pinouts. If you know how and have a RJ45 crimping tool already available, it would be trivial to just rewire the adapter correctly for it to work with DLG instead.
Before buying you can verify that the ECL110 connector B, A (D-, D+ on the pic above) connections are present on the DLG RJ45 by connecting an ethernet cable to the RJ45 port on DLG and then using multimeter to find continuity between the two unconnected sides. Make sure not to do it while the DLG is powered on (disconnect DLG from ECL110 and wall first).
If I'm explaining too basic or obvious stuff, you can let me know. It's hard to gauge over the internet how much you already know about electronics or what kind of tools you already have and know to use.
Yeah, one would guess. The connector on the DLG is actually inserted on the right or left hand side (can't remember right now), and looks more like a 6 pin PCI-E connector, albeit smaller. The RJ45 is located in the middle, as by the image.
I will test with an ethernet cable.
I have some knowledge about electronics, but I appreciate the level of your explanations.
I have continuity between the first and second pin of the RJ45 male connector when viewed with the safety pin facing up. It would be the first and second from the right on the picture below.
I realize now that this is not a very good picture. On the right we have a USB mini connector.
I think I have software version 1.08. All serial numbers and such seems to point to 1.08 as they start with the number 108.
When I toggle vacation mode and home mode, the DLG sends 8˚ and 21˚ respectively as target temperature.
I meant to write during the weekend, but was occupied with other things.
The picture is good enough with the descriptions you provided, thank you for that.
Vacation and home mode seem fairly straightforward, it's basically what you can do by hand from menu manually too.
Also great to hear that you are running 1.08, there was a way to see this from ECL110 menu too, either when it booted up or from one of the about menus somewhere deeper.
I'll try to find or write the software to log the data in the meanwhile, Also I feel like I should re-read the manual in english, so that nothing gets lost in translation.
• Heating comfort is achieved with the lowest energy consumption
Given that heating is not ON 24/7, same as 1?
I bought a DLG some years ago and talked to Danfoss afterwards since the only difference I noticed was the ability to see the outdoor temperature from the ECL in the Link app. After a little digging they told me that the DLG also enabled the Link to control the temperature setting on the ECL based on the highest room temperature requested by the thermostats in the system. E.g. I want 20 degrees in my bedroom and 22 degrees in the living room, so if the living room is requesting heat the ECL goes to 22 and if only the bedroom is requesting heat the ECL goes to 20 (allegedly).
If you happen to own a DLG and rest of the system (mainly Danfoss Link CC), it would be extremely helpful if the communication was sniffed using a USB-to-RS485 adapter ($1 from ebay) and a computer to connect it to. I can provide further instructions if necessary. The process is nondestructive and safe to do.
I have pretty much the same setup as Niklas and I've also just ordered an RS485 USB stick. I'm mainly interested in reading temperature data, that should be possible even with the DLG connected, right? Or will I only be able to sniff whatever the DLG/Link communicates?
Thank you for the input, definitely a welcome observation, which makes sense.
As for your question whether the USB dongle and DLG can communicate to ECL over the same bus - we don't really know for sure if that causes any sort of conflicts with DLG, but there is very little reason to believe it would be an issue (because why else they would be using RS-485 then). So in short, yes, but we need to confirm it to be absolutely sure.
Requesting sensor data that ECL is aware of (S1-S4 readings) is well supported and as a rule of thumb, anything you can see or do using the LCD display and buttons of ECL, you should be able to do using the dongle as well.
I got the thing wired up, I think, but unsure how to proceed.

I've connected with minicom but only getting garbage:
Any suggestions on how to proceed or what I may have done wrong?
You probably didn't do anything wrong as far as connections go.
Modbus RTU is a binary protocol, so it doesn't output anything human readable to the serial terminal. So it is actually alright if it produces garbage output in minicom.
One thing you can do is turn on hex mode for your minicom (-H). This way you will see bytes instead of garbage, but you will probably still not understand anything without reading on how modbus messages frames are constructed. They are actually quite simple, but for a first-timer perhaps maybe a bit tricky to grasp without help. If you are interested however, there are articles like https://www.modbustools.com/modbus.html which help you to better understand the protocol.
There are also programs which can read and format the Modbus RTU output from serial port directly, but I don't know which ones are easy to install or use on a pi. If you know programming, then you can also try using any of the modbus libraries available (python and node.js ones are probably one of the easiest to get up and running), many of which come with examples how to use the library. There are some nice graphical applications made for windows, but it has been long since I have used one.
I can look into this during the weekend, if I can't find any good programs, I'll just write my own and share it along with the instructions how to get it running. I meant to do this earlier, but did not have the time for it then.
Thanks, it looks better with -H, so hopefully the wiring is good at least =)
I also tried the following program but that fail with either a timeout or (not so often) some CRC error. Very easy to install and would work well for my use (pull data with cron and punt it towards influxdb) but won't help with figuring out what the DLG does.
https://github.com/favalex/modbus-cli
"
root@flowerpi3:~/modbus-cli/modbus_cli# modbus -v --baud 19200 --parity=e --stop-bits=1 /dev/ttyUSB0 11200
Parsed 0 registers definitions from 1 files
→ < 01 03 2b c0 00 01 8d d2 >
Traceback (most recent call last):
File "/usr/local/bin/modbus", line 4, in
Sounds good =)
Tried another library (pymodbus) and same thing, no reply and hitting timeout. Also, with minicom, it takes like a minute before I get any data.
I also bought a connector from aviborg, might try that to cut out the DLG just to see if that changes anything.
Check your wiring, could be that your A and B are swapped on the USB adapter. Red should go to B and brown should go to A. Guessing the backside of your adapter looks like this? https://ae01.alicdn.com/kf/H70f7b7e5ba6b4f53952605b8fc7d40c0j.jpg
Another thing you can maybe post here is some output in hex from the minicom, it should be fairly easy to detect modbus traffic, if it is being received correctly.
I'll also leave http://rapidscada.net/modbus/ModbusParser.aspx here, which is quite helpful at recoding frames from hex, although it requires some trial and error to find the start of the frame and then paste correct length of it.
Check your wiring, could be that your A and B are swapped on the USB adapter. Red should go to B and brown should go to A. Guessing the backside of your adapter looks like this? https://ae01.alicdn.com/kf/H70f7b7e5ba6b4f53952605b8fc7d40c0j.jpg
That's the one, yes. I think it's wired ok:

Another thing you can maybe post here is some output in hex from the minicom, it should be fairly easy to detect modbus traffic, if it is being received correctly.
05 03 07 da 00 01 a5 01 05 03 02 06 7e ca 04 05 03 2b c0 00 01 8c 56 05 03 02 00 1d 89 8d 05 03 10 68 00 01 00 92 05 03 02 00 02 c8 45 05 03 2b c2 00 01 2d 96 05 03 02 02 49 89 12 05 03 2b c3 00 01 7c 56 05 03 02 00 e8 49 ca 05 03 2b 15 00 01 9d ae 05 03 02 00 2e c9 98 05 03 0f a1 00 01 d7 78 05 03 02 00 01 88 44 05 03 2b ab 00 01 fd 8a 05 03 02 00 16 c8 4a 05 03 2b ac 00 01 4c 4b 05 03 02 00 05 89 87 05 03 2b 45 00 01 9d bf 05 03 02 00 12 c9 89 05 03 2b dd 00 01 1c 50 05 03 02 02 41 88 d4
I'll also leave http://rapidscada.net/modbus/ModbusParser.aspx here, which is quite helpful at recoding frames from hex, although it requires some trial and error to find the start of the frame and then paste correct length of it.
Hmm, if I paste my hex into that I get the following error:
" Data package CRC error. Actual CRC is 88 D4. Expected CRC is EF 89. "
It actually looks correct. One thing you need to mind is that when pasting commands there, you need to know if your frame is a request or a response and then only paste the correct length of it.
I haven't gone through entire stream yet, but the beginning seems alright:
Request: 05 03 07 da 00 01 a5 01
Response: 05 03 02 06 7e ca 04
Notice that response is 1 byte shorter than the request. Next one is again a request and takes 8 bytes...
Edit: it is already quite interesting, for some reason it requested PNU (address) 2010, which we know nothing about yet (https://github.com/Ingramz/ecl110/blob/master/README.md) other that it can be requested.
Ah, that's something atleast. It would be nice to be able to actively poll the registers I want but perhaps what I need can be sniffed from the DLG traffic if all else fails. Still odd none of the libraries worked, hopefully I just missed some essential detail.
I happen to have an open ticket with Danfoss on a zwave repeater and asked them about reading modbus on the ECL 110 and if the RJ45 port on the DLG could be used for anything in that regard. They claim it's not possible to get anything from modbus on the ECL (heh) and that the RJ45 port is only used when the DLG is used as an CCM module for Danfoss Air units.
It depends on how tolerant or considerate the DLG is when it comes to taking turns with other devices on the bus. The very next request/response is for S1 reading and it's likely you can indeed sniff everything you need at worst.
So request for S1 (11200)?
But also S2 (11201)?
Response:
29 should be 2.9 which is increased to 3.0 in the app 5 mins later:

I'm not sure what is meant exactly by Physical/Logical representation here, but I think the way it is documented in README is all based on the "Physical" value. But indeed, since it is in 0.1C increments, it's 2.9C, which seems correct based on your confirmation.
Confirmed by checking an S3 modbus value against the readout on the actual unit. Pretty cool, then I just need a parser of some sort.
To further both your and my purpose I think it would be cool with a little python daemon that listens on the serial port and parses the stream into requests and responses. Those could then be persisted in whatever form you would like for DLG discovery and I could probably manage to tack on some MQTT code and punt the relevant values off to OpenHAB/InfluxDB.
Somewhat like https://github.com/ThomDietrich/miflora-mqtt-daemon which I'm using so the missus remembers to water her plants.
Do you have time to hack up a little daemon to parse and persist?
This works btw, getting a nice stream of bytes:
import serial
ser = serial.Serial(
port='/dev/ttyUSB0',
baudrate=19200,
parity=serial.PARITY_EVEN,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS,
)
ser.flushInput()
while True:
try:
print(ser.read().hex())
except:
print("Keyboard Interrupt")
break
root@flowerpi3:~# python3 read.py
05
03
07
da
00
01
a5
01
05
03
02
06
7e
ca
04
05
03
2b
c0
00
01
8c
56
05
03
02
00
27
09
9e
05
03
10
68
00
01
00
92
05
03
02
00
02
c8
45
05
03
2b
c2
00
01
It takes like a minut after starting before I'm getting any data.
It looks like my understanding of modbus was incorrect and wikipedia was quite clear about pointing it out:
On Modbus RTU, Modbus ASCII and Modbus Plus (which are all RS-485 single cable multi-drop networks), only the node assigned as the Master may initiate a command. All other devices are slaves and respond to requests and commands.
https://en.wikipedia.org/wiki/Modbus#Communications_and_devices
In our case the ECL is a slave device and typically the USB adapter and DLG are master devices.
The request-response cycle is rather straightforward too, send a request, wait, expect a response for your request within a certain time frame.
So people from Danfoss actually are right that you cannot connect more than one "master" to the same bus that ask readings from slave device(s). The reason why becomes clear as soon as you try to request information from a slave device using two masters at the same time - neither master knows how to take turns with the other. There are clever ways around this, but most of them require additional hardware, for instance splitting the bus using two USB adapters (one acting as a master and other as a slave) and then relaying or buffering the messages between them. But in many cases this is not worth the trouble.
However as established earlier, we can still monitor the bus without interfering with the ECL-DLG communications. I'll look into it now.
I concur, I read as much as well.
I made some monkey code to get the values I want into OpenHAB:
import serial
from datetime import datetime
import os
# Connect serial
ser = serial.Serial(
port='/dev/ttyUSB0',
baudrate=19200,
parity=serial.PARITY_EVEN,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS,
)
ser.flushInput()
bb=''
tmp=''
address=''
payload=''
while True:
try:
b = ser.read()
h = b.hex()
if h == '03':
if tmp == '05 ':
# print(h, end=' ', flush=True)
r = bb.replace(" ", "")
if len(r) == 16: # request
address = r[4:8]
elif len(r) == 14: # reponse
payload = r[6:10]
if int(address, 16) == 11200:
temp_int = int(payload,16)
temp_float = float(temp_int) / 10
now = datetime.now()
current_time = now.strftime("%H:%M:%S")
print(current_time + ' Outside temperature: ' + str(temp_float))
os.system('mosquitto_pub -h openhab.localdomain -t ECL/11200 -m ' + str(temp_float))
bb=tmp+h+ ' '
tmp=''
else:
bb+=h+' '
elif h == '05':
tmp+=h + ' '
else:
bb+=tmp+h + ' '
tmp=''
except Exception as e:
print(e)
break
I'm sure parsing can be made a lot smarter but so far so good.
I was looking at libaries like pymodbus so I could rely on their parsing, but none of them really support sniffing the bus and only deal with the easy part of just detecting either requests or responses.
So I figured as well it is easier to just parse the entire thing ourselves, like you did with that code. I wrote a prototype in javascript, but might consider writing it to python if that is preferred. It doesn't have any serial input or database output added to it yet, but in javascript these are fairly trivial to add.
It operates on a per-byte level and attempts to construct first valid modbus frames from the stream of bytes, by asserting a minimum length of required bytes and then looking for shortest frame with valid CRC. Bytes that cannot be used to construct modbus frames are kept track of, but eventually discarded.
After that if two consecutive frames have been detected, it assumes the first one is request and other one is response, then looks that they belong to the same slave and function and finally compares the lengths of request and response messages to best of its abilities. If a valid pair is found, it records the match and then tries to parse the addresses and data specific to the function of these frames.
There are some corner cases where this approach would not work for other devices, but given that ECL/DLG communicate using one function only (it seems) where the frames are already almost as short as they can be, then it is hard to construct something that gets detected incorrectly.
The code I have for now is here:
const data = "05 03 07 da 00 01 a5 01 05 03 02 06 7e ca 04 05 03 2b c0 00 01 8c 56 05 03 02 00 1d 89 8d 05 03 10 68 00 01 00 92 05 03 02 00 02 c8 45 05 03 2b c2 00 01 2d 96 05 03 02 02 49 89 12 05 03 2b c3 00 01 7c 56 05 03 02 00 e8 49 ca 05 03 2b 15 00 01 9d ae 05 03 02 00 2e c9 98 05 03 0f a1 00 01 d7 78 05 03 02 00 01 88 44 05 03 2b ab 00 01 fd 8a 05 03 02 00 16 c8 4a 05 03 2b ac 00 01 4c 4b 05 03 02 00 05 89 87 05 03 2b 45 00 01 9d bf 05 03 02 00 12 c9 89 05 03 2b dd 00 01 1c 50 05 03 02 02 41 88 d4".split(' ')
function try_parse(buffer) {
for (let offset = 0; offset + 4 < buffer.length; offset++) {
const address = buffer[offset + 0]
const fn = buffer[offset + 1]
const dataOffset = offset + 2
for (let dataLength = 0; dataOffset + dataLength + 2 - 1 < buffer.length; dataLength++) {
const databytes = buffer.slice(dataOffset, dataOffset + dataLength)
const crcbytes = buffer.slice(dataOffset + dataLength, dataOffset + dataLength + 2)
if (parseInt(crcbytes[1] + crcbytes[0], 16) === CRC([address, fn, ...databytes].map(x => parseInt(x, 16)))) {
return {
offset,
bytes: [address, fn, ...databytes, ...crcbytes]
}
}
}
}
return false
}
function try_parse2(frames) {
for (let offset = 0; offset + 1 < frames.length; offset++) {
const request = frames[offset + 0]
const response = frames[offset + 1]
if (request.type !== 'FRAME' || response.type !== 'FRAME') {
continue
}
if (request.bytes[0] !== response.bytes[0] && request.bytes[1] !== response.bytes[1]) {
continue
}
const functionCode = request.bytes[1]
switch (functionCode) {
case '03': // Read holding registers
if (request.bytes.length !== 1 + 1 + 2 + 2 + 2) {
continue
}
const numRegisters = parseInt(request.bytes[4] + request.bytes[5], 16)
const startAddress = parseInt(request.bytes[2] + request.bytes[3], 16)
if (response.bytes.length !== 1 + 1 + 1 + numRegisters * 2 + 2) {
continue
}
if (parseInt(response.bytes[2], 16) !== response.bytes.length - (1 + 1 + 1 + 2)) {
continue
}
const registerData = {}
for (let i = 0; i < numRegisters; i++) {
registerData[startAddress + i] = parseInt(response.bytes[3 + i] + response.bytes[3 + i + 1], 16)
}
const readings = getReadings(registerData)
return {
offset: offset,
request: request.bytes,
response: response.bytes,
meta: {
functionCode: functionCode,
slaveAddress: request.bytes[0],
registers: registerData,
readings: readings
}
}
}
}
return false
}
function getReadings(registerData) {
const result = {}
if ('11200' in registerData) {
result.S1 = registerData['11200'] / 10
}
if ('11201' in registerData) {
result.S2 = registerData['11201'] / 10
}
if ('11202' in registerData) {
result.S3 = registerData['11202'] / 10
}
if ('11203' in registerData) {
result.S4 = registerData['11203'] / 10
}
return result
}
// https://gist.github.com/TooTallNate/946745
var POLY = 0xA001;
var SEED = 0xFFFF;
function CRC(buffer) {
var crc = SEED;
for (var i=0; i<buffer.length; i++) {
crc = Calc_CRC(buffer[i], crc);
}
return crc;
}
function Calc_CRC(b, crc) {
crc ^= b & 0xFF;
for (var i=0; i<8; i++) {
var carry = crc & 0x0001;
crc>>=1;
if (carry) crc ^= POLY;
}
return crc;
}
let incomingBuffer = []
let parsedPackets = []
let framePairs = []
for (let i = 0; i < data.length; i++) {
incomingBuffer.push(data[i])
const result = try_parse(incomingBuffer)
if (result) {
const discarded = incomingBuffer.slice(0, result.offset)
if (discarded.length) {
parsedPackets.push({ type: 'DISCARD', bytes: discarded })
}
parsedPackets.push({ type: 'FRAME', bytes: result.bytes })
incomingBuffer = incomingBuffer.slice(result.offset + result.bytes.length)
}
const fResult = try_parse2(parsedPackets)
if (fResult) {
const discarded = parsedPackets.slice(0, fResult.offset)
if (discarded.length) {
discarded.forEach(x => framePairs.push(x))
}
framePairs.push({ type: 'FRAME_PAIR', request: fResult.request.join(''), response: fResult.response.join(''), meta: fResult.meta })
parsedPackets = parsedPackets.slice(fResult.offset + 2)
}
}
console.log(JSON.stringify(parsedPackets, null, 2))
console.log(JSON.stringify(incomingBuffer, null, 2))
console.log(JSON.stringify(framePairs, null, 2))
And the output looks like this:
[]
[]
[
{
"type": "FRAME_PAIR",
"request": "050307da0001a501",
"response": "050302067eca04",
"meta": {
"functionCode": "03",
"slaveAddress": "05",
"registers": {
"2010": 1662
},
"readings": {}
}
},
{
"type": "FRAME_PAIR",
"request": "05032bc000018c56",
"response": "050302001d898d",
"meta": {
"functionCode": "03",
"slaveAddress": "05",
"registers": {
"11200": 29
},
"readings": {
"S1": 2.9
}
}
},
{
"type": "FRAME_PAIR",
"request": "0503106800010092",
"response": "0503020002c845",
"meta": {
"functionCode": "03",
"slaveAddress": "05",
"registers": {
"4200": 2
},
"readings": {}
}
},
{
"type": "FRAME_PAIR",
"request": "05032bc200012d96",
"response": "05030202498912",
"meta": {
"functionCode": "03",
"slaveAddress": "05",
"registers": {
"11202": 585
},
"readings": {
"S3": 58.5
}
}
},
{
"type": "FRAME_PAIR",
"request": "05032bc300017c56",
"response": "05030200e849ca",
"meta": {
"functionCode": "03",
"slaveAddress": "05",
"registers": {
"11203": 232
},
"readings": {
"S4": 23.2
}
}
},
{
"type": "FRAME_PAIR",
"request": "05032b1500019dae",
"response": "050302002ec998",
"meta": {
"functionCode": "03",
"slaveAddress": "05",
"registers": {
"11029": 46
},
"readings": {}
}
},
{
"type": "FRAME_PAIR",
"request": "05030fa10001d778",
"response": "05030200018844",
"meta": {
"functionCode": "03",
"slaveAddress": "05",
"registers": {
"4001": 1
},
"readings": {}
}
},
{
"type": "FRAME_PAIR",
"request": "05032bab0001fd8a",
"response": "0503020016c84a",
"meta": {
"functionCode": "03",
"slaveAddress": "05",
"registers": {
"11179": 22
},
"readings": {}
}
},
{
"type": "FRAME_PAIR",
"request": "05032bac00014c4b",
"response": "05030200058987",
"meta": {
"functionCode": "03",
"slaveAddress": "05",
"registers": {
"11180": 5
},
"readings": {}
}
},
{
"type": "FRAME_PAIR",
"request": "05032b4500019dbf",
"response": "0503020012c989",
"meta": {
"functionCode": "03",
"slaveAddress": "05",
"registers": {
"11077": 18
},
"readings": {}
}
},
{
"type": "FRAME_PAIR",
"request": "05032bdd00011c50",
"response": "050302024188d4",
"meta": {
"functionCode": "03",
"slaveAddress": "05",
"registers": {
"11229": 577
},
"readings": {}
}
}
]