def __init__(self, loop, client: BleakClient, client_mac: str, device_mac: str, key: bytes): self.state: BandState = BandState.Disconnected self.client: BleakClient = client self.loop = loop self.client_mac: str = client_mac self.device_mac: str = device_mac self.client_serial: str = client_mac.replace( ":", "")[-6:] # android.os.Build.SERIAL self._key: bytes = key self._server_nonce: Optional[bytes] = None self._client_nonce: bytes = generate_nonce() self._encryption_counter: int = 0 self.link_params: Optional[device_config.LinkParams] = None self.bond_status: Optional[int] = None self.bond_status_info: Optional[int] = None self.bt_version: Optional[int] = None self._packet: Optional[Packet] = None self._event = asyncio.Event() self.__message_id: int = -1
def __init__(self, client: BleakClient, client_mac: str, device_mac: str, secret: bytes, loop): self.state = BandState.Disconnected self.client = client self.client_mac = client_mac self.device_mac = device_mac self.secret = secret self.loop = loop self.client_serial = client_mac.replace( ":", "").encode()[-6:] # android.os.Build.SERIAL self.protocol_version = 2 self.max_frame_size = 254 self.max_link_size = 254 self.connection_interval = 10 # milliseconds self.auth_version = 1 self.server_nonce = None self.client_nonce = generate_nonce() self.bond_status = None self.bond_status_info = None self.bt_version = None self.encryption_counter = None self._event = asyncio.Event()
def request_set_time(self): zone_hours, zone_minutes = divmod(time.timezone / -3600, 1) zone_minutes *= 60 offset = encode_int(int(zone_hours), length=1) + encode_int( int(zone_minutes), length=1) plain_command = Command(tlvs=[ TLV(tag=DeviceConfig.SetTime.Tags.Timestamp, value=encode_int(int(time.time()), length=4)), TLV(tag=DeviceConfig.SetTime.Tags.ZoneOffset, value=offset), ]) self.encryption_counter += 1 # TODO: overflow iv = generate_nonce()[:-4] + encode_int(self.encryption_counter, length=4) packet = Packet( service_id=DeviceConfig.id, command_id=DeviceConfig.SetTime.id, command=Command(tlvs=[ TLV(tag=124, value=b"\x01"), TLV(tag=125, value=iv), TLV(tag=126, value=encrypt(bytes(plain_command), self.secret, iv)), ]), ) return packet
def main(): config = ConfigParser() if not CONFIG_FILE.exists(): config[DEVICE_NAME] = { "device_uuid": "A0E49DB2-XXXX-XXXX-XXXX-D75121192329", "device_mac": "6C:B7:49:XX:XX:XX", "client_mac": "C4:B3:01:XX:XX:XX", "secret": base64.b64encode(generate_nonce()).decode(), } with open(CONFIG_FILE.name, "w") as fp: config.write(fp) return config.read(CONFIG_FILE.name) event_loop = asyncio.get_event_loop() event_loop.run_until_complete(run(config[DEVICE_NAME], event_loop))
def request_bond(self): # TODO: extract self.encryption_counter += 1 iv = generate_nonce()[:-4] + encode_int(self.encryption_counter, length=4) packet = Packet(service_id=DeviceConfig.id, command_id=DeviceConfig.Bond.id, command=Command(tlvs=[ TLV(tag=1), TLV(tag=3, value=b"\x00"), TLV(tag=5, value=self.client_serial), TLV(tag=6, value=create_bonding_key( self.device_mac, self.secret, iv)), TLV(tag=7, value=iv), ])) self.state = BandState.RequestedBond return packet
def main(): config = ConfigParser() if not CONFIG_FILE.exists(): config[DEVICE_NAME] = { "device_uuid": "A0E49DB2-XXXX-XXXX-XXXX-D75121192329", "device_mac": "E4:19:C1:C1:0D:78", "client_mac": "28:39:26:63:7D:30", "secret": base64.b64encode(generate_nonce()).decode(), } with open(CONFIG_FILE.name, "w") as fp: config.write(fp) return config.read(CONFIG_FILE.name) event_loop = asyncio.get_event_loop() try: event_loop.run_until_complete(run(config[DEVICE_NAME], event_loop)) finally: event_loop.close()