74 lines
2.5 KiB
Python

"""BLE identifiers and protocol constants for the Shining Mask.
References:
* Shining-Mask-stuff/ble-protocol.md (community protocol documentation)
* mask-go/mask/mask.go (canonical, field-tested Go implementation)
"""
from __future__ import annotations
# --- GATT identifiers ---------------------------------------------------------
# Vendor service that carries every mask characteristic.
SERVICE_UUID = "0000fff0-0000-1000-8000-00805f9b34fb"
# Command characteristic: AES-encrypted 16-byte command frames (write).
CMD_CHAR_UUID = "d44bc439-abfd-45a2-b575-925416129600"
# Notify characteristic: AES-encrypted responses (notify). Drives the upload
# handshake (DATSOK / REOK / DATCPOK).
NOTIFY_CHAR_UUID = "d44bc439-abfd-45a2-b575-925416129601"
# Upload characteristic: raw (UNencrypted) image/bitmap data chunks (write).
UPLOAD_CHAR_UUID = "d44bc439-abfd-45a2-b575-92541612960a"
# Audio-visualization characteristic: AES-encrypted 16-byte frames (write).
AUDIO_CHAR_UUID = "d44bc439-abfd-45a2-b575-92541612960b"
# The mask advertises a local name like "MASK-02A711"; everyone scans by prefix.
DEVICE_NAME_PREFIX = "MASK"
# --- Protocol sizing ----------------------------------------------------------
# Mask display is 16 pixels tall (arbitrarily wide for scrolling text).
MASK_HEIGHT = 16
# Command/notify frames are AES blocks padded to this size.
FRAME_SIZE = 16
# Upload packets carry at most this many data bytes (the mask rejects packets
# whose total on-air size exceeds 100 bytes; 2 bytes are header, so 98 remain).
UPLOAD_MAX_DATA = 98
# --- Text scroll modes (MODE command argument) --------------------------------
class TextMode:
"""Text display modes for the MODE command.
Values confirmed by decrypting real app traffic (mask-controller/codes.js)
and cross-checked with mask-go::
1 = steady / solid (text shown, no scroll animation)
2 = blink
3 = scroll right-to-left
4 = scroll left-to-right
The protocol doc mislabels 1 as "off" and declares 5..255 as n/a (the
firmware reverts them to mode 1); the official app only ever sends 1..4.
"""
STEADY = 1
SOLID = 1 # alias for STEADY
BLINK = 2
SCROLL_LEFT = 3 # scroll right-to-left
SCROLL_RIGHT = 4 # scroll left-to-right
# --- DATS upload toggle byte --------------------------------------------------
class UploadKind:
BITMAP = 0 # text bitmap + per-column color array
IMAGE = 1 # full-color DIY image (raw RGB)