ASCII Convert Control Character

Hi,
I'm unable to decode a message from a serial device, if send buffer
[2,69,12,202,170,194,66,192,100,232,255,255,75,70,225,9,181,20,159,51,174,82,69,65,68,69,82,0,112,153,3]
I can see the raw data (Ascii) shows EʪÂBÀdèÿÿKFá µŸ3®READERp™

Now ["0x02"] is a Control Character (STX), however Node-Red shows it as
I'm new to Node-Red so I'm trying to decode the message so it makes sense!

What is the device you're getting data from? That looks like there may be a protocol & perhaps a CRC at the end just before the ETX.

It’s an Electricity meter, it uses “Command line protocol“
Chapter 4 Link =

http://read.pudn.com/downloads156/doc/694628/JSGF/(英文)红相%20MK6表计规约EDMI%20MK6电表详细规约.pdf

Yes I believe there’s a CRC, if I want to send:

LBASIL,BRUSH<0>

How do I decode the return messages so it makes sense? I’m sure I have the answers in Chapter 4, just need some direction on Node-Red :slight_smile:

Chapter 4-1 shows you need to send

<STX><command><CRC><ETX>

<CRC> is
a 16 bit CRC-16 polynomial checksum defined by the CCITT standard, calculated over
the entire message including the STX but not the CRC itself or the ETX character.

The meter replies to commands with a response message in the following format.
<STX><response><CRC><ETX>

So, you need to wrap you command as stated above. The serial node can be set to send on ETX - do you know how to do that.

Additionally, you're gonna have to calculate the CRC. There is a calculation on page B-1

But...

There may be an easier way. There is a MODBUS Mode on page 3-40. If you are in a position to change to modbus mode, then there are modbus nodes available that will hugely simplify accessing the device registers.

Unfortunately this meter doesn’t support Modbus :frowning:

I have the meter software which I use to configure it, so I can monitor the data which is sent from the software to the meter.

For example if send the command

<STX>E(MeterNumber)(1)(1)LREADER,READER[00][C70A]<ETX>

I get:


<STX>E(1)(MeterNumber)(1)<ACK>[155C]<ETX>

So I can see it’s accepted, however if I try replicate this string using Node-Red I see:


EʪÂBÀdèÿÿKFá	µŸ3®READERp™

[2,69,12,202,170,194,66,192,100,232,255,255,75,70,225,9,181,20,159,51,174,82,69,65,68,69,82,0,112,153,3]

And the response:

EBÀdèʪÂÿÿK-ʒŸÊªÂq 

[2,69,66,192,100,232,12,202,170,194,255,255,75,45,202,146,159,12,202,170,194,113,160,3]

I'm sure its accepted, can’t decode the response from the meter.

Shame about the modbus option.

All I can say is you're lucky to have an extensive manual, you're gonna have to throw test data at it and decipher the response.

All I can suggest to maybe simplify this is, if you only have one device, then avoid the extended call (like in your example above) - instead try to get the simpler "read register" command (pg 4-4) working

Luckily, there is a C example on pg B-4 You can easily translate to js for calculating the CRC. The code should also give you a clue as to how to format your requests.

Hi Steve, do you know any good online calculators for 16 bit CRC?

The example in the book is:


[02]R[F0][02]

The calculated CRC =


EE45

Can’t seem to find anything online which outputs the same CRC

CRC can be vendor specific (meaning CRC is not always calculated the same)

All the information to calculate the CRC is there in the manual.

You are lucky i was bored though :wink:

image

function code...

const ccitt_16 = [
    0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
    0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
    0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
    0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
    0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
    0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
    0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
    0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
    0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
    0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
    0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
    0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
    0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
    0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
    0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
    0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
    0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
    0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
    0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
    0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
    0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
    0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
    0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
    0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
    0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
    0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
    0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
    0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
    0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
    0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
    0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
    0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
];
function Hi(word){
    return (word >> 8) 
}
function Lo(word){
    return (word & 0x00ff) 
}
function CalculateCharacterCRC16(crc, byte){
    let shifted8_int16 = ((crc << 8) & 0xffff);
    let b = (Hi(crc) ^ byte);
    let newCRC = (shifted8_int16 ^ ccitt_16[b]);
    return newCRC;
}

var data = msg.payload;
var crc = 0;
for (let i=0; i < data.length; i++) {
    crc = CalculateCharacterCRC16(crc, data[i]);
} 
msg.crc = crc;
return msg;

Test flow...

[{"id":"7961163b.59a198","type":"function","z":"6ef1cfb5.30ff2","name":"calculate CRC","func":"const ccitt_16 = [\n    0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,\n    0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,\n    0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,\n    0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,\n    0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,\n    0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,\n    0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,\n    0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,\n    0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,\n    0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,\n    0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,\n    0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,\n    0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,\n    0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,\n    0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,\n    0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,\n    0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,\n    0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,\n    0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,\n    0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,\n    0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,\n    0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,\n    0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,\n    0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,\n    0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,\n    0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,\n    0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,\n    0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,\n    0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,\n    0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,\n    0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,\n    0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0\n];\nfunction Hi(word){\n    return (word >> 8) \n}\nfunction Lo(word){\n    return (word & 0x00ff) \n}\nfunction CalculateCharacterCRC16(crc, byte){\n    let shifted8_int16 = ((crc << 8) & 0xffff);\n    let b = (Hi(crc) ^ byte);\n    let newCRC = (shifted8_int16 ^ ccitt_16[b]);\n    return newCRC;\n}\n\nvar data = msg.payload;\nvar crc = 0;\nfor (let i=0; i < data.length; i++) {\n    crc = CalculateCharacterCRC16(crc, data[i]);\n} \nmsg.crc = crc;\nreturn msg;","outputs":1,"noerr":0,"x":820,"y":160,"wires":[["50de6eb4.f6461"]]},{"id":"1750ec24.337374","type":"inject","z":"6ef1cfb5.30ff2","name":"0x2, \"R\", 0xF0, 0x2","topic":"","payload":"[2,82,240,2]","payloadType":"bin","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":790,"y":80,"wires":[["7961163b.59a198"]]},{"id":"50de6eb4.f6461","type":"debug","z":"6ef1cfb5.30ff2","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":850,"y":240,"wires":[]}]
1 Like

Legend!!! Thanks for your expertise!!! :grin:

1 Like

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