93 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			93 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
from MAXCube import MAXCube
 | 
						|
from MAXPacket import MAXPacket, MAXPacketFactory, MAXPairPingPacket, MAXPairPongPacket, MAXAckPacket, \
 | 
						|
    MAXResetPacket, MAXWakeUpPacket, MAXSetGroupIdPacket, MAXPushButtonPacket, MAXCubeAckPacket
 | 
						|
from MAXDevice import MAXDevice, MAXPushButton
 | 
						|
 | 
						|
from time import sleep
 | 
						|
from enum import Enum
 | 
						|
 | 
						|
 | 
						|
class HandshakeState(Enum):
 | 
						|
    PING_RECEIVED = 1
 | 
						|
    PONG_SENT = 2
 | 
						|
    PONG_ACK = 3
 | 
						|
    GROUP_ID_SENT = 4
 | 
						|
    GROUP_ID_ACK = 5
 | 
						|
 | 
						|
 | 
						|
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: MAXCube):
 | 
						|
        self.cube = cube
 | 
						|
        self.quit_flag = False
 | 
						|
        self.handshakes = []
 | 
						|
        self.devices: list[MAXDevice] = []
 | 
						|
 | 
						|
    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))
 | 
						|
                            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_str)
 | 
						|
                            self.cube.request(set_group_id_str)
 | 
						|
                            cur_handshake.state = HandshakeState.GROUP_ID_SENT
 | 
						|
                    if cur_handshake.state == HandshakeState.GROUP_ID_SENT:
 | 
						|
                        cur_handshake.state = HandshakeState.GROUP_ID_ACK
 | 
						|
            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 None:
 | 
						|
                    dev = MAXPushButton(pkt.sender_address)
 | 
						|
                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)
 | 
						|
        else:
 | 
						|
            print("Paket is not ours!")
 | 
						|
 | 
						|
    def receive_loop(self):
 | 
						|
        while not self.quit_flag and self.cube.is_connected():
 | 
						|
            resp = self.cube.response()
 | 
						|
            if resp is not None and resp[0:1] == "Z":
 | 
						|
                pkt = MAXPacketFactory.create_packet(resp)
 | 
						|
                self.handle_msg(pkt)
 | 
						|
            sleep(0.1) |