63 lines
1.9 KiB
Python
63 lines
1.9 KiB
Python
#!/usr/bin/env python3
|
|
"""Build Berger/JBD BLE frames observed in the Android app."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
|
|
|
|
def checksum(command: int, payload: bytes = b"") -> int:
|
|
"""JBD two's-complement checksum over command, length, and payload."""
|
|
total = (command + len(payload) + sum(payload)) & 0xFFFF
|
|
return ((total ^ 0xFFFF) + 1) & 0xFFFF
|
|
|
|
|
|
def frame(mode: int, command: int, payload: bytes = b"") -> bytes:
|
|
check = checksum(command, payload)
|
|
return bytes([0xDD, mode, command, len(payload), *payload, check >> 8, check & 0xFF, 0x77])
|
|
|
|
|
|
def read_frame(command: int) -> bytes:
|
|
return frame(0xA5, command)
|
|
|
|
|
|
def write_frame(command: int, payload: bytes) -> bytes:
|
|
return frame(0x5A, command, payload)
|
|
|
|
|
|
def name_frame(command: int, payload: bytes = b"") -> bytes:
|
|
check = (command + len(payload) + sum(payload)) & 0xFF
|
|
return bytes([0xFF, 0xAA, command, len(payload), *payload, check])
|
|
|
|
|
|
def parse_hex_bytes(value: str) -> bytes:
|
|
clean = value.replace(" ", "").replace(":", "")
|
|
return bytes.fromhex(clean)
|
|
|
|
|
|
def main() -> None:
|
|
parser = argparse.ArgumentParser()
|
|
sub = parser.add_subparsers(dest="cmd", required=True)
|
|
|
|
p_read = sub.add_parser("read")
|
|
p_read.add_argument("command", type=lambda x: int(x, 0))
|
|
|
|
p_write = sub.add_parser("write")
|
|
p_write.add_argument("command", type=lambda x: int(x, 0))
|
|
p_write.add_argument("payload_hex", nargs="?", default="")
|
|
|
|
p_name = sub.add_parser("name")
|
|
p_name.add_argument("value")
|
|
|
|
args = parser.parse_args()
|
|
if args.cmd == "read":
|
|
print(read_frame(args.command).hex().upper())
|
|
elif args.cmd == "write":
|
|
print(write_frame(args.command, parse_hex_bytes(args.payload_hex)).hex().upper())
|
|
elif args.cmd == "name":
|
|
print(name_frame(0x07, args.value.encode("ascii")).hex().upper())
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|