Full C++ and Python impl

This commit is contained in:
2026-04-05 01:10:49 +02:00
parent 1ae2f521c1
commit a2887b187f
5 changed files with 153 additions and 1 deletions

19
LICENSE Normal file
View File

@@ -0,0 +1,19 @@
MIT License
Copyright (c) 2026 Hector van der Aa <hector@h3cx.dev>
Copyright (c) 2026 Association Exergie <association.exergie@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -1,2 +1,6 @@
# TelemetryCommon # TelemetryCommon
The common library for telemetry data structures for TransparentBoxV1 The common library for telemetry data structures for TransparentBox-V1
This repo includes both the C++ and python implementations.
When cloning TransparentBox-V1, DataFlux or any other repository that depends on this, the symlink needs to be rebuilt, usually to a folder called telemetry_common

22
telemetry_common.cpp Normal file
View File

@@ -0,0 +1,22 @@
// Copyright (C) 2026 Hector van der Aa <hector@h3cx.dev>
// Copyright (C) 2026 Association Exergie <association.exergie@gmail.com>
// SPDX-License-Identifier: MIT
#include "telemetry_common.h"
#include <stdlib.h>
uint16_t crc16_ccitt(const uint8_t *data, uint16_t length) {
uint16_t crc = 0xFFFF;
for (uint16_t i = 0; i < length; i++) {
crc ^= (uint16_t)data[i] << 8;
for (uint8_t j = 0; j < 8; j++) {
if (crc & 0x8000)
crc = (crc << 1) ^ 0x1021;
else
crc <<= 1;
}
}
return crc;
}

40
telemetry_common.h Normal file
View File

@@ -0,0 +1,40 @@
// Copyright (C) 2026 Hector van der Aa <hector@h3cx.dev>
// Copyright (C) 2026 Association Exergie <association.exergie@gmail.com>
// SPDX-License-Identifier: MIT
#pragma once
#include <inttypes.h>
#pragma pack(push, 1)
struct TelemetryPacket1 {
char ping_[4] = {'P', 'I', 'N', 'G'};
};
#pragma pack(pop)
#pragma pack(push, 1)
struct TelemetryPacket2 {
float vbat;
float teng;
float lat;
float lng;
float speed;
};
#pragma pack(pop)
#pragma pack(push, 1)
struct TelemetryLoRaHeader {
uint8_t source_;
uint8_t dest_;
uint8_t version_;
uint8_t size_;
uint16_t crc16_;
};
#pragma pack(pop)
#pragma pack(push, 1)
struct TelemetryUARTHeader {
uint8_t magic_[4] = {0xAA, 0x55, 0xAA, 0x55};
uint8_t size_;
};
#pragma pack(pop)
uint16_t crc16_ccitt(const uint8_t *data, uint16_t length);

67
telemetry_common.py Normal file
View File

@@ -0,0 +1,67 @@
# Copyright (C) 2026 Hector van der Aa <hector@h3cx.dev>
# Copyright (C) 2026 Association Exergie <association.exergie@gmail.com>
# SPDX-License-Identifier: MIT
import struct
from dataclasses import dataclass
UART_MAGIC = b"\xAA\x55\xAA\x55"
LORA_HEADER_FORMAT = "<BBBBH"
UART_HEADER_FORMAT = "<4sB"
PACKET1_FORMAT = "<4s"
PACKET2_FORMAT = "<fffff"
LORA_HEADER_SIZE = struct.calcsize(LORA_HEADER_FORMAT)
UART_HEADER_SIZE = struct.calcsize(UART_HEADER_FORMAT)
PACKET1_SIZE = struct.calcsize(PACKET1_FORMAT)
PACKET2_SIZE = struct.calcsize(PACKET2_FORMAT)
@dataclass
class TelemetryLoRaHeader:
source: int
dest: int
version: int
size: int
crc16: int
@dataclass
class TelemetryPacket1:
ping: bytes
@dataclass
class TelemetryPacket2:
vbat: float
teng: float
lat: float
lng: float
speed: float
def crc16_ccitt(data: bytes) -> int:
crc = 0xFFFF
for byte in data:
crc ^= byte << 8
for _ in range(8):
if crc & 0x8000:
crc = ((crc << 1) ^ 0x1021) & 0xFFFF
else:
crc = (crc << 1) & 0xFFFF
return crc
def unpack_lora_header(data: bytes) -> TelemetryLoRaHeader:
source, dest, version, size, crc16 = struct.unpack(LORA_HEADER_FORMAT, data[:LORA_HEADER_SIZE])
return TelemetryLoRaHeader(source, dest, version, size, crc16)
def unpack_packet1(payload: bytes) -> TelemetryPacket1:
(ping,) = struct.unpack(PACKET1_FORMAT, payload[:PACKET1_SIZE])
return TelemetryPacket1(ping)
def unpack_packet2(payload: bytes) -> TelemetryPacket2:
vbat, teng, lat, lng, speed = struct.unpack(PACKET2_FORMAT, payload[:PACKET2_SIZE])
return TelemetryPacket2(vbat, teng, lat, lng, speed)