You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

93 lines
4.2KB

  1. from MAXCube import MAXCube
  2. from MAXPacket import MAXPacket, MAXPacketFactory, MAXPairPingPacket, MAXPairPongPacket, MAXAckPacket, \
  3. MAXResetPacket, MAXWakeUpPacket, MAXSetGroupIdPacket, MAXPushButtonPacket, MAXCubeAckPacket
  4. from MAXDevice import MAXDevice, MAXPushButton
  5. from time import sleep
  6. from enum import Enum
  7. class HandshakeState(Enum):
  8. PING_RECEIVED = 1
  9. PONG_SENT = 2
  10. PONG_ACK = 3
  11. GROUP_ID_SENT = 4
  12. GROUP_ID_ACK = 5
  13. class Handshake:
  14. def __init__(self, partner_addr, dev_type):
  15. self.partner_addr = partner_addr
  16. self.dev_type = dev_type
  17. self.state: HandshakeState = HandshakeState.PING_RECEIVED
  18. class MAXPacketHandler:
  19. def __init__(self, cube: MAXCube):
  20. self.cube = cube
  21. self.quit_flag = False
  22. self.handshakes = []
  23. self.devices: list[MAXDevice] = []
  24. def handle_msg(self, pkt: MAXPacket):
  25. print(pkt.to_string())
  26. if pkt.dest_address == self.cube.addr or pkt.dest_address == "000000":
  27. if isinstance(pkt, MAXPairPingPacket):
  28. handshake = Handshake(pkt.sender_address, pkt.device_type)
  29. self.handshakes.append(handshake)
  30. pong = MAXPairPongPacket(message_counter="00", message_flag="00", sender_address=self.cube.addr,
  31. dest_address=pkt.sender_address, group_id="00")
  32. pong_str = pong.serialize()
  33. #print(pong.to_string())
  34. self.cube.request(pong_str)
  35. handshake.state = HandshakeState.PONG_SENT
  36. elif isinstance(pkt, MAXAckPacket):
  37. cur_handshake: Handshake = None
  38. for handshake in self.handshakes:
  39. if handshake.partner_addr == pkt.sender_address:
  40. cur_handshake = handshake
  41. break
  42. if cur_handshake is not None:
  43. if cur_handshake.state == HandshakeState.PONG_SENT:
  44. cur_handshake.state = HandshakeState.PONG_ACK
  45. print(pkt.to_string())
  46. if cur_handshake.dev_type == "05":
  47. # Handshake is finished
  48. print("Paired device with addr={} and type={}".format(cur_handshake.partner_addr,
  49. cur_handshake.dev_type))
  50. self.handshakes.remove(cur_handshake)
  51. else:
  52. set_group_id = MAXSetGroupIdPacket(message_counter="00", message_flag="00", sender_address=self.cube.addr,
  53. dest_address=pkt.sender_address, group_id="00")
  54. set_group_id_str = set_group_id.serialize()
  55. print(set_group_id_str)
  56. self.cube.request(set_group_id_str)
  57. cur_handshake.state = HandshakeState.GROUP_ID_SENT
  58. if cur_handshake.state == HandshakeState.GROUP_ID_SENT:
  59. cur_handshake.state = HandshakeState.GROUP_ID_ACK
  60. elif isinstance(pkt, MAXPushButtonPacket):
  61. dev = None
  62. for known_dev in self.devices:
  63. if known_dev.address == pkt.sender_address:
  64. dev = known_dev
  65. break
  66. if dev is None:
  67. dev = MAXPushButton(pkt.sender_address)
  68. dev.state = pkt.button_state
  69. print("Button {} state={}".format(dev.address, dev.state))
  70. if not pkt.retransmit:
  71. act_pkt = MAXCubeAckPacket(pkt.counter, "00", self.cube.addr,
  72. pkt.sender_address, pkt.group_id, True)
  73. act_str = act_pkt.serialize()
  74. #print(act_str)
  75. self.cube.request(act_str)
  76. else:
  77. print("Paket is not ours!")
  78. def receive_loop(self):
  79. while not self.quit_flag and self.cube.is_connected():
  80. resp = self.cube.response()
  81. if resp is not None and resp[0:1] == "Z":
  82. pkt = MAXPacketFactory.create_packet(resp)
  83. self.handle_msg(pkt)
  84. sleep(0.1)