Full C++ and Python impl
This commit is contained in:
19
LICENSE
Normal file
19
LICENSE
Normal 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.
|
||||
@@ -1,2 +1,6 @@
|
||||
# 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
22
telemetry_common.cpp
Normal 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
40
telemetry_common.h
Normal 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
67
telemetry_common.py
Normal 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)
|
||||
Reference in New Issue
Block a user