from typing import List from MAXCube import MAXCube from MAXPacket import MAXPacket, MAXPacketFactory, MAXPairPingPacket, MAXPairPongPacket, MAXAckPacket, \ MAXSetGroupIdPacket, MAXPushButtonPacket, MAXCubeAckPacket, MAXSetTempPacket, \ MAXRadiatorControlMode, MAXAddLinkPartnerPacket from MAXDevice import MAXDevice, MAXPushButton, MAXThermostat from enum import Enum class HandshakeState(Enum): PING_RECEIVED = 1 PONG_SENT = 2 PONG_ACK = 3 GROUP_ID_SENT = 4 GROUP_ID_ACK = 5 CONFIG_TEMP_SENT = 6 CONFIG_TEMP_ACK = 7 ADD_LINK_PARTNER_SENT = 8 ADD_LINK_PARTNER_ACK = 9 class Handshake: def __init__(self, partner_addr, dev_type): self.partner_addr = partner_addr self.dev_type = dev_type self.state: HandshakeState = HandshakeState.PING_RECEIVED class MAXPacketHandler: def __init__(self, cube, devices: MAXCube): self.cube = cube self.quit_flag = False self.handshakes = [] self.devices: List[MAXDevice] = devices def handle_msg(self, pkt: MAXPacket): print(pkt.to_string()) if pkt.dest_address == self.cube.addr or pkt.dest_address == "000000": if isinstance(pkt, MAXPairPingPacket): handshake = Handshake(pkt.sender_address, pkt.device_type) self.handshakes.append(handshake) pong = MAXPairPongPacket(message_counter="00", message_flag="00", sender_address=self.cube.addr, dest_address=pkt.sender_address, group_id="00") pong_str = pong.serialize() print(pong.to_string()) self.cube.request(pong_str) handshake.state = HandshakeState.PONG_SENT elif isinstance(pkt, MAXAckPacket): cur_handshake: Handshake = None for handshake in self.handshakes: if handshake.partner_addr == pkt.sender_address: cur_handshake = handshake break if cur_handshake is not None: if cur_handshake.state == HandshakeState.PONG_SENT: cur_handshake.state = HandshakeState.PONG_ACK #print(pkt.to_string()) if cur_handshake.dev_type == "05": # Handshake is finished print("Paired device with addr={} and type={}".format(cur_handshake.partner_addr, cur_handshake.dev_type)) found = False for dev in self.devices: if dev.address == cur_handshake.partner_addr: found = True break if not found: new_dev = MAXPushButton("PushButton_{}".format(cur_handshake.partner_addr), cur_handshake.partner_addr) self.devices.append(new_dev) self.handshakes.remove(cur_handshake) else: set_group_id = MAXSetGroupIdPacket(message_counter="00", message_flag="00", sender_address=self.cube.addr, dest_address=pkt.sender_address, group_id="00") set_group_id_str = set_group_id.serialize() print(set_group_id.to_string()) self.cube.request(set_group_id_str) cur_handshake.state = HandshakeState.GROUP_ID_SENT return if cur_handshake.state == HandshakeState.GROUP_ID_SENT: cur_handshake.state = HandshakeState.GROUP_ID_ACK set_temp = MAXSetTempPacket(message_counter="00", message_flag="00", sender_address=self.cube.addr, dest_address=pkt.sender_address, group_id="00", temp=21.5, mode=MAXRadiatorControlMode.MANUAL) set_temp_str = set_temp.serialize() print(set_temp.to_string()) self.cube.request(set_temp_str) cur_handshake.state = HandshakeState.CONFIG_TEMP_SENT return if cur_handshake.state == HandshakeState.CONFIG_TEMP_SENT: cur_handshake.state = HandshakeState.CONFIG_TEMP_ACK add_link = MAXAddLinkPartnerPacket(message_counter="00", message_flag="00", sender_address=self.cube.addr, dest_address=pkt.sender_address, group_id="00", partner_addr=self.cube.addr, partner_type=0) add_link_str = add_link.serialize() print(add_link.to_string()) self.cube.request(add_link_str) cur_handshake.state = HandshakeState.ADD_LINK_PARTNER_SENT return if cur_handshake.state == HandshakeState.ADD_LINK_PARTNER_SENT: cur_handshake.state = HandshakeState.ADD_LINK_PARTNER_ACK found = False for dev in self.devices: if dev.address == cur_handshake.partner_addr: found = True break if not found: new_dev = MAXThermostat("Thermostat_{}".format(cur_handshake.partner_addr), cur_handshake.partner_addr) self.devices.append(new_dev) print("Paired device with addr={} and type={}".format(cur_handshake.partner_addr, cur_handshake.dev_type)) self.handshakes.remove(cur_handshake) return elif isinstance(pkt, MAXPushButtonPacket): dev = None for known_dev in self.devices: if known_dev.address == pkt.sender_address: dev = known_dev break if dev is not None: dev.state = pkt.button_state print("Button {} state={}".format(dev.address, dev.state)) if not pkt.retransmit: act_pkt = MAXCubeAckPacket(pkt.counter, "00", self.cube.addr, pkt.sender_address, pkt.group_id, True) act_str = act_pkt.serialize() #print(act_str) #self.cube.request(act_str) #ToDo: Does not work properly else: print("Paket is not ours!")