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.

136 lines
7.0KB

  1. from typing import List
  2. from MAXCube import MAXCube
  3. from MAXPacket import MAXPacket, MAXPacketFactory, MAXPairPingPacket, MAXPairPongPacket, MAXAckPacket, \
  4. MAXSetGroupIdPacket, MAXPushButtonPacket, MAXCubeAckPacket, MAXSetTempPacket, \
  5. MAXRadiatorControlMode, MAXAddLinkPartnerPacket
  6. from MAXDevice import MAXDevice, MAXPushButton, MAXThermostat
  7. from enum import Enum
  8. class HandshakeState(Enum):
  9. PING_RECEIVED = 1
  10. PONG_SENT = 2
  11. PONG_ACK = 3
  12. GROUP_ID_SENT = 4
  13. GROUP_ID_ACK = 5
  14. CONFIG_TEMP_SENT = 6
  15. CONFIG_TEMP_ACK = 7
  16. ADD_LINK_PARTNER_SENT = 8
  17. ADD_LINK_PARTNER_ACK = 9
  18. class Handshake:
  19. def __init__(self, partner_addr, dev_type):
  20. self.partner_addr = partner_addr
  21. self.dev_type = dev_type
  22. self.state: HandshakeState = HandshakeState.PING_RECEIVED
  23. class MAXPacketHandler:
  24. def __init__(self, cube, devices: MAXCube):
  25. self.cube = cube
  26. self.quit_flag = False
  27. self.handshakes = []
  28. self.devices: List[MAXDevice] = devices
  29. def handle_msg(self, pkt: MAXPacket):
  30. print(pkt.to_string())
  31. if pkt.dest_address == self.cube.addr or pkt.dest_address == "000000":
  32. if isinstance(pkt, MAXPairPingPacket):
  33. handshake = Handshake(pkt.sender_address, pkt.device_type)
  34. self.handshakes.append(handshake)
  35. pong = MAXPairPongPacket(message_counter="00", message_flag="00", sender_address=self.cube.addr,
  36. dest_address=pkt.sender_address, group_id="00")
  37. pong_str = pong.serialize()
  38. print(pong.to_string())
  39. self.cube.request(pong_str)
  40. handshake.state = HandshakeState.PONG_SENT
  41. elif isinstance(pkt, MAXAckPacket):
  42. cur_handshake: Handshake = None
  43. for handshake in self.handshakes:
  44. if handshake.partner_addr == pkt.sender_address:
  45. cur_handshake = handshake
  46. break
  47. if cur_handshake is not None:
  48. if cur_handshake.state == HandshakeState.PONG_SENT:
  49. cur_handshake.state = HandshakeState.PONG_ACK
  50. #print(pkt.to_string())
  51. if cur_handshake.dev_type == "05":
  52. # Handshake is finished
  53. print("Paired device with addr={} and type={}".format(cur_handshake.partner_addr,
  54. cur_handshake.dev_type))
  55. found = False
  56. for dev in self.devices:
  57. if dev.address == cur_handshake.partner_addr:
  58. found = True
  59. break
  60. if not found:
  61. new_dev = MAXPushButton("PushButton_{}".format(cur_handshake.partner_addr),
  62. cur_handshake.partner_addr)
  63. self.devices.append(new_dev)
  64. self.handshakes.remove(cur_handshake)
  65. else:
  66. set_group_id = MAXSetGroupIdPacket(message_counter="00", message_flag="00", sender_address=self.cube.addr,
  67. dest_address=pkt.sender_address, group_id="00")
  68. set_group_id_str = set_group_id.serialize()
  69. print(set_group_id.to_string())
  70. self.cube.request(set_group_id_str)
  71. cur_handshake.state = HandshakeState.GROUP_ID_SENT
  72. return
  73. if cur_handshake.state == HandshakeState.GROUP_ID_SENT:
  74. cur_handshake.state = HandshakeState.GROUP_ID_ACK
  75. set_temp = MAXSetTempPacket(message_counter="00", message_flag="00", sender_address=self.cube.addr,
  76. dest_address=pkt.sender_address, group_id="00", temp=21.5,
  77. mode=MAXRadiatorControlMode.MANUAL)
  78. set_temp_str = set_temp.serialize()
  79. print(set_temp.to_string())
  80. self.cube.request(set_temp_str)
  81. cur_handshake.state = HandshakeState.CONFIG_TEMP_SENT
  82. return
  83. if cur_handshake.state == HandshakeState.CONFIG_TEMP_SENT:
  84. cur_handshake.state = HandshakeState.CONFIG_TEMP_ACK
  85. add_link = MAXAddLinkPartnerPacket(message_counter="00", message_flag="00", sender_address=self.cube.addr,
  86. dest_address=pkt.sender_address, group_id="00", partner_addr=self.cube.addr, partner_type=0)
  87. add_link_str = add_link.serialize()
  88. print(add_link.to_string())
  89. self.cube.request(add_link_str)
  90. cur_handshake.state = HandshakeState.ADD_LINK_PARTNER_SENT
  91. return
  92. if cur_handshake.state == HandshakeState.ADD_LINK_PARTNER_SENT:
  93. cur_handshake.state = HandshakeState.ADD_LINK_PARTNER_ACK
  94. found = False
  95. for dev in self.devices:
  96. if dev.address == cur_handshake.partner_addr:
  97. found = True
  98. break
  99. if not found:
  100. new_dev = MAXThermostat("Thermostat_{}".format(cur_handshake.partner_addr),
  101. cur_handshake.partner_addr)
  102. self.devices.append(new_dev)
  103. print("Paired device with addr={} and type={}".format(cur_handshake.partner_addr,
  104. cur_handshake.dev_type))
  105. self.handshakes.remove(cur_handshake)
  106. return
  107. elif isinstance(pkt, MAXPushButtonPacket):
  108. dev = None
  109. for known_dev in self.devices:
  110. if known_dev.address == pkt.sender_address:
  111. dev = known_dev
  112. break
  113. if dev is not None:
  114. dev.state = pkt.button_state
  115. print("Button {} state={}".format(dev.address, dev.state))
  116. if not pkt.retransmit:
  117. act_pkt = MAXCubeAckPacket(pkt.counter, "00", self.cube.addr,
  118. pkt.sender_address, pkt.group_id, True)
  119. act_str = act_pkt.serialize()
  120. #print(act_str)
  121. #self.cube.request(act_str)
  122. #ToDo: Does not work properly
  123. else:
  124. print("Paket is not ours!")