JSONDecodeError Expecting value: line 1 column 1 (char 0) when receiving via Bluetooth

850 views Asked by At

I am transmitting a JSON payload from an Arduino microcontroller and attempting to receive it using a Python script:

import bluetooth  #pybluez 
import json

sensor_address = "18:D9:31:YY:C7:4A"
socket = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
socket.connect((sensor_address, 1))
buffer = ""

print("Listening...")
while True: 
    data = socket.recv(1024)
    buffer += str(data, encoding='ascii')
    print(buffer) # used to check json payload
    try: 
        data = json.loads(buffer)
        print("Received:", data)
        buffer = ""
    except json.JSONDecodeError as e:
        print(e)
        continue

Examining the value stored in buffer before entering the try statement, I see what appears to be perfectly valid JSON:

{"a_x":957.5195,"a_y":-0.488281,"a_z":315.918,"g_x":-0.625954,"g_y":-1.305344}{"a_x":961.914,"a_y":-1.953125,"a_z":297.8516,"g_x":-2.816794,"g_y":2.572519}{"a_x":964.8437,"a_y":3.417969,"a_z":303.2227,"g_x":-1,"g_y":0.374046}

However the result of my script is only Expecting value: line 1 column 1 (char 0) repeatedly.

Why doesn't the code inside the try statement execute once a complete payload has been received?

My hunch is that at no time does a valid JSON payload appear in buffer, but instead valid payloads appear along with incomplete payloads.

Is it possible to use a regular expression to extract a valid payload from a string?

1

There are 1 answers

4
ukBaz On BEST ANSWER

The data in buffer is not valid JSON so that is why you are seeing the error.

The buffer seems to have the information in the format of a Python dictionary so you could use Python re module to extract the dictionary and then use ast.literal_eval to turn the string in to a Python dictionary.

In the example below I've mocked the reading of the socket as I don't have your device.

import re

pattern = re.compile(r'{.*?}')


class socket:
    """Mock reading data from socket"""
    pointer = 3
    chunk_size = 8
    feed = (b'{"a_x":957.5195,"a_y":-0.488281,"a_z":315.918,"g_x":-0.625954,"g_y":-1.305344}'
            b'{"a_x":961.914,"a_y":-1.953125,"a_z":297.8516,"g_x":-2.816794,"g_y":2.572519}'
            b'{"a_x":964.8437,"a_y":3.417969,"a_z":303.2227,"g_x":-1,"g_y":0.374046}')

    @classmethod
    def recv(cls):
        data = cls.feed[cls.pointer:cls.pointer + cls.chunk_size]
        cls.pointer += cls.chunk_size
        return data


def process_reading(buffer):
    match = re.search(pattern, buffer)
    start_idx, end_idx = match.span()
    reading = literal_eval(buffer[start_idx:end_idx])
    buffer = buffer[end_idx:]
    return buffer, reading


def main():
    buffer = ''
    data = True
    while data:
        data = socket.recv()
        # print("Data:", data)
        buffer += str(data, encoding='ascii')
        print("Buffer contents", buffer)
        if re.search(pattern, buffer):
            buffer, measurement = process_reading(buffer)
            print("\tMeasurement:", measurement.get('g_x'))


if __name__ == '__main__':
    main()

This gave the following output:

Buffer contents _x":957.
Buffer contents _x":957.5195,"a_
Buffer contents _x":957.5195,"a_y":-0.48
Buffer contents _x":957.5195,"a_y":-0.488281,"a_
Buffer contents _x":957.5195,"a_y":-0.488281,"a_z":315.9
Buffer contents _x":957.5195,"a_y":-0.488281,"a_z":315.918,"g_x"
Buffer contents _x":957.5195,"a_y":-0.488281,"a_z":315.918,"g_x":-0.6259
Buffer contents _x":957.5195,"a_y":-0.488281,"a_z":315.918,"g_x":-0.625954,"g_y"
Buffer contents _x":957.5195,"a_y":-0.488281,"a_z":315.918,"g_x":-0.625954,"g_y":-1.3053
Buffer contents _x":957.5195,"a_y":-0.488281,"a_z":315.918,"g_x":-0.625954,"g_y":-1.305344}{"a_x
Buffer contents _x":957.5195,"a_y":-0.488281,"a_z":315.918,"g_x":-0.625954,"g_y":-1.305344}{"a_x":961.91
Buffer contents _x":957.5195,"a_y":-0.488281,"a_z":315.918,"g_x":-0.625954,"g_y":-1.305344}{"a_x":961.914,"a_y":
Buffer contents _x":957.5195,"a_y":-0.488281,"a_z":315.918,"g_x":-0.625954,"g_y":-1.305344}{"a_x":961.914,"a_y":-1.95312
Buffer contents _x":957.5195,"a_y":-0.488281,"a_z":315.918,"g_x":-0.625954,"g_y":-1.305344}{"a_x":961.914,"a_y":-1.953125,"a_z":
Buffer contents _x":957.5195,"a_y":-0.488281,"a_z":315.918,"g_x":-0.625954,"g_y":-1.305344}{"a_x":961.914,"a_y":-1.953125,"a_z":297.8516
Buffer contents _x":957.5195,"a_y":-0.488281,"a_z":315.918,"g_x":-0.625954,"g_y":-1.305344}{"a_x":961.914,"a_y":-1.953125,"a_z":297.8516,"g_x":-
Buffer contents _x":957.5195,"a_y":-0.488281,"a_z":315.918,"g_x":-0.625954,"g_y":-1.305344}{"a_x":961.914,"a_y":-1.953125,"a_z":297.8516,"g_x":-2.816794
Buffer contents _x":957.5195,"a_y":-0.488281,"a_z":315.918,"g_x":-0.625954,"g_y":-1.305344}{"a_x":961.914,"a_y":-1.953125,"a_z":297.8516,"g_x":-2.816794,"g_y":2
Buffer contents _x":957.5195,"a_y":-0.488281,"a_z":315.918,"g_x":-0.625954,"g_y":-1.305344}{"a_x":961.914,"a_y":-1.953125,"a_z":297.8516,"g_x":-2.816794,"g_y":2.572519}
    Measurement: -2.816794
Buffer contents {"a_x":9
Buffer contents {"a_x":964.8437,
Buffer contents {"a_x":964.8437,"a_y":3.
Buffer contents {"a_x":964.8437,"a_y":3.417969,"
Buffer contents {"a_x":964.8437,"a_y":3.417969,"a_z":303
Buffer contents {"a_x":964.8437,"a_y":3.417969,"a_z":303.2227,"g
Buffer contents {"a_x":964.8437,"a_y":3.417969,"a_z":303.2227,"g_x":-1,"
Buffer contents {"a_x":964.8437,"a_y":3.417969,"a_z":303.2227,"g_x":-1,"g_y":0.3
Buffer contents {"a_x":964.8437,"a_y":3.417969,"a_z":303.2227,"g_x":-1,"g_y":0.374046}
    Measurement: -1
Buffer contents