Send Binary Data

I am trying to send binary data following the documentation, using:

  1. Calculate the MD5 checksum of the binary payload

  2. COBS-encode the binary payload. The note-c library includes a NoteBinaryEncode method to simplify this process

  3. Calculate the the length of the new COBS-encoded payload.

  4. Append a newline character to the the COBS-encoded payload (\n).

  5. Send a card.binary.put request to the Notecard with the MD5 checksum in the status argument and the length of the payload in the cobs argument.

    Use the offset argument if you are supplying multiple payloads in succession, where the current offset is the index location of where the previous ended.

  6. At this point, the Notecard is in a state where it expects the next input to be binary data, not a JSON-formatted API request. Send it the COBS-encoded payload.

  7. Next, you can optionally send a card.binary request to check for errors and verify the binary data was properly saved to the Notecard by checking the MD5 checksum:

However i found some error that i am not able to solve yet, i am using python without the API, just serial library and json.

import serial
import json
import time
from cobs import cobs
import hashlib

puerto_serial = ‘/dev/ttyACM0’ #
baud_rate = 9600 #
timeout = 1 #

def Send_and_wait(ser, json_obj, timeout_sec=5):
json_data = json.dumps(json_obj) + ‘\n’
ser.write(json_data.encode(‘utf-8’))
print(f"Enviado: {json_data.strip()}")

t0 = time.time()
respuesta_buffer = b''

while time.time() - t0 < timeout_sec:
    if ser.in_waiting > 0:
        respuesta_buffer += ser.read(ser.in_waiting)
        while b'\n' in respuesta_buffer:
            line, respuesta_buffer = respuesta_buffer.split(b'\n', 1)
            if not line:
                continue
            try:
                respuesta_json = json.loads(line.decode('utf-8').strip())
                print(f"Recibido (JSON): {respuesta_json}")
            except json.JSONDecodeError:
                print(f"Recibido (texto): {line.decode('utf-8').strip()}")
        break
    else:
        time.sleep(0.1)

try:
ser = serial.Serial(puerto_serial, baud_rate, timeout=timeout)
print(f"Puerto {puerto_serial} abierto correctamente.“)
except serial.SerialException as e:
print(f"No se pudo abrir el puerto: {e}”)
exit()

try:

1 Info card.wireless

comando_wireless = {“req”: “card.wireless”}
Send_and_wait(ser, comando_wireless, timeout_sec=5)

# 2 Configure Wi-Fi and fallback to NTN.
comando_transport = {"req":"card.transport","method":"wifi-ntn"}
Send_and_wait(ser, comando_transport, timeout_sec=5)


# 3.Clear binary queue
comando_reset_binary_buffer={"req": "card.binary","delete": True}
Send_and_wait(ser,comando_reset_binary_buffer,timeout_sec=5)


# 4. prepare blob
blob_hex = "400CA2340080AA0002890C3C343AB8851AD23DF488D5EE22" # Example hex string
blob_bytes = bytes.fromhex(blob_hex)
print("Original bytes:", blob_bytes)


# 5 Calculate MD5
md5_hash = hashlib.md5(blob_bytes).hexdigest()
print("MD5:", md5_hash)

# 6 COBS encoding 
encoded = cobs.encode(blob_bytes)
print("COBS encoded bytes:", encoded)
hex_string = encoded.hex().upper()  
print("COBS EN HEX: ",hex_string)


cobs_length = len(encoded)
print(f"COBS length: {cobs_length}")

# 7 Append newline (\n)
encoded_with_newline = encoded + b'\n'


# 8 Tell Notecard to expect binary data
comando_binary_put = {
    "req": "card.binary.put",
    "cobs": cobs_length,
    "status": md5_hash
}
Send_and_wait(ser, comando_binary_put, timeout_sec=5)

# 9 Immediately send the binary payload (COBS data + newline)
print(f"Sending {cobs_length} bytes de datos binarios...")
print(f"Bytes sent ({len(encoded_with_newline)}): {encoded_with_newline.hex()}")

ser.write(encoded_with_newline)
ser.flush()

# Wait long enough for Notecard to finish processing binary
time.sleep(1.0)

# 10 Confirm binary data was received correctly
comando_binaryData = {"req":"card.binary"}
Send_and_wait(ser,comando_binaryData,timeout_sec=5)

And i have this output

Puerto /dev/ttyACM0 abierto correctamente.
Enviado: {“req”: “card.transport”, “method”: “wifi-ntn”}
Recibido (JSON): {‘method’: ‘wifi-ntn’}
Enviado: {“req”: “card.binary”, “delete”: true}
Recibido (JSON): {‘max’: 99605}
Original bytes: b’@\x0c\xa24\x00\x80\xaa\x00\x02\x89\x0c<4:\xb8\x85\x1a\xd2=\xf4\x88\xd5\xee"’
COBS encoded bytes: b’\x05@\x0c\xa24\x03\x80\xaa\x11\x02\x89\x0c<4:\xb8\x85\x1a\xd2=\xf4\x88\xd5\xee"’
COBS EN HEX: 05400CA2340380AA1102890C3C343AB8851AD23DF488D5EE22
COBS length: 25
MD5: 2d5d508d5fde909d2bcdc4f23379f207
Enviado: {“req”: “card.binary.put”, “cobs”: 25, “status”: “2d5d508d5fde909d2bcdc4f23379f207”}
Recibido (JSON): {}
Enviando 25 bytes de datos binarios…
Bytes enviados (26): 05400ca2340380aa1102890c3c343ab8851ad23df488d5ee220a
Enviado: {“req”: “card.binary”}
Recibido (JSON): {‘err’: ‘binary object received hash does not verify {bad-bin}{io}’, ‘max’: 99605}

should i calculte the md5 of the original data, the encoded data or the encoded extended(+ \n) data?

Hi @alevillegas.cat welcome to the forum!

I’ll try to test your code against a notecard and see if I can reproduce it/pinpoint the issue. It looks like you are mostly correct with your use of the Notecard API. Can I ask why you are choosing not to use the note-python library for your application?

Thanks,

Alex

It looks like the error occurs because the standard Python cobs library, encodes without an XOR operation for the \n character. Notecard expects COBS encoding where all bytes are XORed with 0x0A (newline) to prevent newline characters from appearing in the binary data.

This is because the Notecard uses newline as the packet delimiter. When the Notecard decodes your data using XOR 0x0A, but you encoded without it, every byte gets incorrectly XORed during decoding, causing the MD5 verification to fail.

The easiest thing is to use the note-python COBS implementation instead of the standard cobs library. Or if you still don’t want to use note-python, please take a look at the COBS encoder implementation.

Thank you for your answer @abucknall. anyway i think i cannot send binary blob using NTN, but your answer helped me to understand better.