Ejemplo n.º 1
0
    def receive_data(self, sender, data):
        logger.debug(
            f"State: {self.state}, received from '{sender}': {hexlify(bytes(data))}"
        )
        packet = Packet.from_bytes(data)
        logger.debug(f"Parsed: {packet}")

        if self.state == BandState.RequestedLinkParams:
            if packet.service_id != DeviceConfig.id and packet.command_id != DeviceConfig.LinkParams.id:
                raise RuntimeError("unexpected packet")
            self.parse_link_params(packet.command)
        elif self.state == BandState.RequestedAuthentication:
            if packet.service_id != DeviceConfig.id and packet.command_id != DeviceConfig.Auth.id:
                raise RuntimeError("unexpected packet")
            self.parse_authentication(packet.command)
        elif self.state == BandState.RequestedBondParams:
            if packet.service_id != DeviceConfig.id and packet.command_id != DeviceConfig.BondParams.id:
                raise RuntimeError("unexpected packet")
            self.parse_bond_params(packet.command)
        elif self.state == BandState.RequestedBond:
            if packet.service_id != DeviceConfig.id and packet.command_id != DeviceConfig.Bond.id:
                raise RuntimeError("unexpected packet")
            self.parse_bond(packet.command)

        self._event.set()
Ejemplo n.º 2
0
    def _receive_data(self, sender: str, data: bytes):
        logger.debug(f"Current state: {self.state}, received from '{sender}': {hexlify(bytes(data))}")
        self._packet = Packet.from_bytes(data)
        logger.debug(f"Parsed response packet: {self._packet}")

        assert self.state.name.startswith("Requested"), "unexpected packet"
        self.loop.call_soon_threadsafe(self._event.set())
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
0
 def request_link_params(self) -> Packet:
     self.state = BandState.RequestedLinkParams
     return Packet(service_id=DeviceConfig.id,
                   command_id=DeviceConfig.LinkParams.id,
                   command=Command(tlvs=[
                       TLV(DeviceConfig.LinkParams.Tags.ProtocolVersion),
                       TLV(DeviceConfig.LinkParams.Tags.MaxFrameSize),
                       TLV(DeviceConfig.LinkParams.Tags.MaxLinkSize),
                       TLV(DeviceConfig.LinkParams.Tags.ConnectionInterval),
                   ]))
Ejemplo n.º 5
0
    def request_authentication(self):
        packet = Packet(service_id=DeviceConfig.id,
                        command_id=DeviceConfig.Auth.id,
                        command=Command(tlvs=[
                            TLV(tag=DeviceConfig.Auth.Tags.Challenge,
                                value=digest_challenge(self.server_nonce,
                                                       self.client_nonce)),
                            TLV(tag=DeviceConfig.Auth.Tags.Nonce,
                                value=(encode_int(self.auth_version) +
                                       self.client_nonce)),
                        ]))

        self.state = BandState.RequestedAuthentication

        return packet
Ejemplo n.º 6
0
    def request_bond_params(self):
        packet = Packet(
            service_id=DeviceConfig.id,
            command_id=DeviceConfig.BondParams.id,
            command=Command(tlvs=[
                TLV(tag=DeviceConfig.BondParams.Tags.Status),
                TLV(tag=DeviceConfig.BondParams.Tags.ClientSerial,
                    value=self.client_serial),
                TLV(tag=DeviceConfig.BondParams.Tags.BTVersion, value=b"\x02"),
                TLV(tag=DeviceConfig.BondParams.Tags.MaxFrameSize),
                TLV(tag=DeviceConfig.BondParams.Tags.ClientMacAddress,
                    value=self.client_mac.encode()),
                TLV(tag=DeviceConfig.BondParams.Tags.EncryptionCounter),
            ]))

        self.state = BandState.RequestedBondParams

        return packet
Ejemplo n.º 7
0
    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