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.

158 lines
5.3KB

  1. import math
  2. from enum import Enum
  3. class MAXPacketFactory:
  4. def create_packet(rec: str):
  5. pkt_type = int(rec[7:9], 16)
  6. if pkt_type == 0:
  7. return MAXPairPingPacket(rec)
  8. elif pkt_type == 1:
  9. return MAXPairPongPacket(rec)
  10. elif pkt_type == 2:
  11. return MAXAckPacket(rec)
  12. elif pkt_type == 0x22:
  13. return MAXSetGroupIdPacket(rec)
  14. elif pkt_type == 0xF1:
  15. return MAXWakeUpPacket(rec)
  16. elif pkt_type == 0xF0:
  17. return MAXResetPacket(rec)
  18. elif pkt_type == 0x50:
  19. return MAXPushButtonPacket(rec)
  20. else:
  21. print("Unknown message type: {}".format(pkt_type))
  22. result = MAXPacket()
  23. result.from_received(rec)
  24. return result
  25. class MAXPacket:
  26. def __init__(self):
  27. self.length = 0
  28. self.counter = 0
  29. self.type = 0
  30. self.flag = 0
  31. self.sender_address = 0
  32. self.dest_address = 0
  33. self.group_id = 0
  34. def set_values(self, message_counter: str, message_type: str, message_flag: str, sender_address: str,
  35. dest_address: str, group_id: str):
  36. # self.length = length
  37. self.counter = message_counter
  38. self.type = message_type
  39. self.flag = message_flag
  40. self.sender_address = sender_address
  41. self.dest_address = dest_address
  42. self.group_id = group_id
  43. def from_received(self, rec: str):
  44. self.set_values(rec[3:5], rec[5:7], rec[7:9], rec[9:15], rec[15:21], rec[21:23])
  45. self.length = rec[1:3]
  46. def gen_header(self):
  47. header_str = "{}{}{}{}{}{}".format(self.counter, self.flag, self.type, self.sender_address,
  48. self.dest_address, self.group_id)
  49. return header_str
  50. def serialize(self):
  51. header = self.gen_header()
  52. length = int(math.ceil((len(header) + len(self.payload)) / 2))
  53. self.length = length
  54. return "Zs{0:02X}{1}{2}".format(length, header, self.payload)
  55. def to_string(self):
  56. return "MAXPacket: len={}, counter={}, flag={}, type={}, sender_addr={}, dest_addr={}, group_id={}".format(
  57. self.length, self.counter, self.flag, self.type, self.sender_address, self.dest_address, self.group_id
  58. )
  59. class MAXPairPingPacket(MAXPacket):
  60. def __init__(self, rec: str):
  61. self.from_received(rec)
  62. firmware_val = int(rec[23:25], 16)
  63. self.firmware_major = firmware_val // 16
  64. self.firmware_minor = firmware_val % 16
  65. self.device_type = rec[25:27]
  66. self.test_result = rec[27:29]
  67. self.serial = rec[29:-2]
  68. def to_string(self):
  69. result = "{}\nMAXPairPingPacket: firmware_major={} firmware_minor={} device_type={} " \
  70. "test_result={} serial={}".format(super().to_string(), self.firmware_major, self.firmware_minor,
  71. self.device_type, self.test_result, self.serial)
  72. return result
  73. class MAXPairPongPacket(MAXPacket):
  74. def __init__(self, message_counter: str, message_flag: str, sender_address: str, dest_address: str,
  75. group_id: str):
  76. self.set_values(message_counter, "01", message_flag, sender_address, dest_address, group_id)
  77. self.payload = "00"
  78. def to_string(self):
  79. result = "{}\nMAXPairPongPacket: payload={}".format(super().to_string(), self.payload)
  80. return result
  81. class MAXSetGroupIdPacket(MAXPacket):
  82. def __init__(self, message_counter: str, message_flag: str, sender_address: str, dest_address: str,
  83. group_id: str):
  84. self.set_values(message_counter, "01", message_flag, sender_address, dest_address, group_id)
  85. self.payload = "00"
  86. def to_string(self):
  87. result = "{}\nMAXSetGroupIdPacket: payload={}".format(super().to_string(), self.payload)
  88. return result
  89. class MAXAckPacket(MAXPacket):
  90. def __init__(self, rec):
  91. super().__init__()
  92. self.from_received(rec)
  93. self.ack = rec[23:25]
  94. self.unknown_field = rec[25:27]
  95. def to_string(self):
  96. result = "{}\nMAXAckPacket: ack={} unknown_field={}".format(super().to_string(),
  97. self.ack, self.unknown_field)
  98. return result
  99. class PushButtonState(Enum):
  100. AUTO = 0
  101. ECO = 1
  102. UNKNOWN = 2
  103. class MAXPushButtonPacket(MAXPacket):
  104. def __init__(self, rec: str):
  105. self.from_received(rec)
  106. if rec[26:27] == "0":
  107. self.button_state = PushButtonState.ECO
  108. elif rec[26:27] == "1":
  109. self.button_state = PushButtonState.AUTO
  110. else:
  111. self.button_state = PushButtonState.UNKNOWN
  112. if rec[23:24] == "5":
  113. self.retransmit = 1
  114. else:
  115. self.retransmit = 0
  116. def to_string(self):
  117. result = "{}\nMAXPushButtonPacket: button_state={} retransmit={}".format(super().to_string(),
  118. self.button_state, self.retransmit)
  119. return result
  120. class MAXWakeUpPacket(MAXPacket):
  121. def __init__(self, rec):
  122. super().__init__()
  123. self.from_received(rec)
  124. class MAXResetPacket(MAXPacket):
  125. def __init__(self, rec):
  126. super().__init__()
  127. self.from_received(rec)