Files
bulltron-ble-commands/tools/bulltron_frame.py
T

67 lines
2.0 KiB
Python
Executable File

#!/usr/bin/env python3
"""Build BullTron/Daly-style BLE frames observed in the Android app."""
from __future__ import annotations
import argparse
def crc16_modbus_swapped(hex_data: str) -> str:
data = bytes.fromhex(hex_data)
crc = 0xFFFF
for byte in data:
crc ^= byte
for _ in range(8):
if crc & 1:
crc = (crc >> 1) ^ 0xA001
else:
crc >>= 1
swapped = ((crc & 0xFF00) >> 8) | ((crc & 0x00FF) << 8)
return f"{swapped:04X}"
def read_frame(start: int, count: int) -> str:
body = f"D203{start:04X}{count:04X}"
return body + crc16_modbus_swapped(body)
def write_single_frame(register: int, value: int) -> str:
body = f"D206{register:04X}{value:04X}"
return body + crc16_modbus_swapped(body)
def write_multi_frame(start: int, count: int, payload_hex: str) -> str:
payload = payload_hex.replace(" ", "").upper()
body = f"D210{start:04X}{count:04X}{payload}"
return body + crc16_modbus_swapped(body)
def main() -> None:
parser = argparse.ArgumentParser()
sub = parser.add_subparsers(dest="cmd", required=True)
p_read = sub.add_parser("read")
p_read.add_argument("start", type=lambda x: int(x, 0))
p_read.add_argument("count", type=lambda x: int(x, 0))
p_write = sub.add_parser("write")
p_write.add_argument("register", type=lambda x: int(x, 0))
p_write.add_argument("value", type=lambda x: int(x, 0))
p_multi = sub.add_parser("write-multi")
p_multi.add_argument("start", type=lambda x: int(x, 0))
p_multi.add_argument("count", type=lambda x: int(x, 0))
p_multi.add_argument("payload_hex")
args = parser.parse_args()
if args.cmd == "read":
print(read_frame(args.start, args.count))
elif args.cmd == "write":
print(write_single_frame(args.register, args.value))
elif args.cmd == "write-multi":
print(write_multi_frame(args.start, args.count, args.payload_hex))
if __name__ == "__main__":
main()