Copyright © https://mongoose-os.com

Mongoose OS Forum

frame

Decoding UART data sent over MQTT

I have a device which I am using to record some UART data and send it over MQTT to my google cloud Pub/Sub. However, JSON.stringify is mangling the data before it sends.
For example, using python on the server to capture data:

def callback(message):
        print(message.data)
        try:
            message_json = json.loads(message.data.decode('utf-8'))
        except Exception as e:
            print(e)
        add_data(message_json)
        message.ack()

I get something like

b'{"message":["\xff","\\u0002","\\u0002","\\u0000","\\u0000","\\u0000","\\u0005","\\u0000","\xa0","\\u0011","\\u0006","b","x","\xfe","\xed","\xa3","Z","\xaa","\xa5","\\u0005","}","\xf7","\\u0004","Y","j","\xe2","f","\\v","\xe7"],"time":1519845562.721684}'
Invalid \escape: line 1 column 168 (char 167)

Really I want 0xFF, 0x02, 0x02... or maybe ascii representation.

UART.setDispatcher(UART_CT, function(UART_CT) {
    let ra = UART.readAvail(UART_CT);
    if (ra > 0) {
      //CT481 is talking, record it
      mode = MODE_CT_RX;
      rxAcc = UART.read(UART_CT);
        for(let i = 0; i < rxAcc.length; i++) {
    rxArr[i] = rxAcc[i];
  }
 let message = JSON.stringify({"time":Timer.now(),  "message":rxArr});
if(MQTT.pub(topic, message, 1) === 0) {
  print("mqtt error"); 
} else {
  print("mqtt success");
}
  }
}, null);

Is there a way to get JSON.stringify to treat the rxArr array as an array of numbers, not characters? Alternately, what encoding is Mongoose OS using, so I can decode it in the python script?

Comments

  • nliviunliviu Romania

    Maybe it can help

    let number = Math.rand();
    let arr = [];
    let arr2 = [];
    for (let i = 0; i < 4; i++) {
        let byte = (number >> (24 - 8 * i)) & 0xFF;
        arr2[i] = byte;
        arr[i] = byte2hex(byte);
    }
    print("=== number=", number, ", string=", JSON.stringify({"time": Timer.now(), "message": arr}));
    print("=== arr2=", JSON.stringify({"time": Timer.now(), "message": arr2}));
    

    Output:

    [Mar  6 10:07:32.888] === number= 816676174 , string= {"message":["30","ad","7d","4e"],"time":1520323653.871688}
    [Mar  6 10:07:32.899] === arr2= {"message":[48,173,125,78],"time":1520323653.886162}
    [Mar  6 10:07:42.891] === number= 110656185 , string= {"message":["06","98","7a","b9"],"time":1520323663.873371}
    [Mar  6 10:07:42.903] === arr2= {"message":[6,152,122,185],"time":1520323663.889999}
    [Mar  6 10:07:52.888] === number= 1696845805 , string= {"message":["65","23","cf","ed"],"time":1520323673.871701}
    [Mar  6 10:07:52.899] === arr2= {"message":[101,35,207,237],"time":1520323673.885760}
    

    816676174 = 0x30AD7D4E
    110656185 = 0x06987AB9
    1696845805 = 0x6523CFED

    mJS strings are byte strings, not Unicode strings: 'ы'.length === 2, 'ы'[0] === '\xd1', 'ы'[1] === '\x8b'. mJS string can represent any binary data chunk.

  • nliviunliviu Romania

    After some further investigations, it looks like the simplest solution is:

        for (let i = 0; i < rxAcc.length; i++) {
            rxArr[i] = rxAcc.at(i);
        }
       let message = JSON.stringify({"time":Timer.now(),  "message":rxArr});
    

    Output using your sample data:

    [Mar  6 17:48:27.562] === test: \xff\x02\x02\x00\x00\x00\x05\x00\xa0\x11\x06bx\xfe\xed\xa3Z\xaa\xa5\x05}\xf7\x04Yj\xe2f\x0b\xe7
    [Mar  6 17:48:27.579] ===      JSON.stringify(test) "\xff\u0002\u0002\u0000\u0000\u0000\u0005\u0000\xa0\u0011\u0006bx\xfe\xed\xa3Z\xaa\xa5\u0005}\xf7\u0004Yj\xe2f\v\xe7"
    [Mar  6 17:48:27.649] ===      JSON.stringify(arr2) [255,2,2,0,0,0,5,0,160,17,6,98,120,254,237,163,90,170,165,5,125,247,4,89,106,226,102,11,231]
    

    My code:

        let test = '\xff\x02\x02\x00\x00\x00\x05\x00\xa0\x11\x06bx\xfe\xed\xa3Z\xaa\xa5\x05}\xf7\x04Yj\xe2f\x0b\xe7';
        print('=== test:', test);
        print('===      JSON.stringify(test)', JSON.stringify(test));
        for (let i = 0; i < test.length; i++) {
            arr2[i] = test.at(i);
        }
        print('===      JSON.stringify(arr2)', JSON.stringify(arr2));
    

    From the mJS README.md:

    'abc'.at(0);
        Return numeric byte value at given string index. Example: 'abc'.at(0) === 0x61;
  • AMoscoeAMoscoe Canada

    That works, thank you

Sign In or Register to comment.