PMPacket.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. """
  2. Created on 13-04-2013
  3. @author: citan
  4. """
  5. import array
  6. class PMPacket(object):
  7. # 0x80
  8. # destination byte
  9. # source byte
  10. # data size byte
  11. # ...
  12. # checksum byte sum of every byte in packet (incl. header)
  13. _header_byte = 0x80
  14. _valid_bytes = [0xFF, 0xA8, 0xE8]
  15. def __init__(self, dst, src, data):
  16. self._dst = dst
  17. self._src = src
  18. self._data = data
  19. @classmethod
  20. def from_array(cls, data):
  21. validate = PMPacket.is_valid(data)
  22. if not validate[0]:
  23. raise Exception('packet', validate[1])
  24. dst = data[1]
  25. src = data[2]
  26. data = data[4:-1]
  27. return cls(dst, src, data)
  28. @classmethod
  29. def is_valid(cls, data):
  30. # TODO: check E8
  31. valid = True
  32. msg = ""
  33. valid = valid and (len(data) > 5)
  34. msg += "invalid length (too short), " if (not valid) else ""
  35. valid = valid and (data[0] == PMPacket._header_byte)
  36. msg += "invalid header, " if (not valid) else ""
  37. # valid = data[4] in PMPacket._valid_bytes
  38. # msg += "invalid header, expected one of " + ', '.join(hex(s) for s in PMPacket._valid_bytes) +", got: " + hex(data[4]) + ", " if (not valid) else ""
  39. #valid = valid and ((data[1] == 0x10) or (data[1] == 0xf0))
  40. #valid = valid and ((data[2] == 0x10) or (data[2] == 0xf0))
  41. #valid = valid and (data[1] != data[2])
  42. #msg += "invalid source/target, " if (not valid) else ""
  43. current_len = len(data)
  44. expected_len = 5 + data[3]
  45. valid = valid and (current_len == expected_len)
  46. msg += "invalid length (is: " + str(current_len) + ", expected: " + str(expected_len) + "), " if (
  47. not valid) else ""
  48. checksum = 0
  49. for i in range(0, len(data) - 1):
  50. checksum = (checksum + data[i]) & 0xFF
  51. valid = valid and (checksum == data[-1])
  52. msg += "invalid checksum (is " + str(checksum) + ", expected: " + str(data[-1]) + "), " if (not valid) else ""
  53. return valid, msg
  54. def is_equal(self, packet):
  55. return self.to_bytes() == packet.to_bytes()
  56. def to_bytes(self):
  57. length = len(self._data)
  58. packet = [self._header_byte, self._dst, self._src, length]
  59. packet.extend(self._data)
  60. checksum = 0
  61. for b in packet:
  62. checksum = (checksum + b) & 0xFF
  63. packet.append(checksum)
  64. return packet
  65. def to_string(self):
  66. return array.array('B', self.to_bytes()).tostring()
  67. def dump(self):
  68. return "[" + ', '.join(("0x%0.2X" % s) for s in self.to_bytes()) + "], dst: " + hex(
  69. self._dst) + ", src: " + hex(self._src) + ", len: " + str(len(self._data))
  70. def get_data(self):
  71. return self._data
  72. def get_destination(self):
  73. return self._dst
  74. def get_source(self):
  75. return self._src
  76. @classmethod
  77. def dump_header(cls, data):
  78. print("header [" + ', '.join(hex(s) for s in data) + "], len: " + str(len(data)))