PMXmlParser.py 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. """
  2. Created on 29-03-2013
  3. @author: citan
  4. """
  5. import xml.sax
  6. import os.path
  7. from pimonitor.PM import PM
  8. from pimonitor.cu.PMCUAddress import PMCUAddress
  9. from pimonitor.cu.PMCUCalculatedParameter import PMCUCalculatedParameter
  10. from pimonitor.cu.PMCUConversion import PMCUConversion
  11. from pimonitor.cu.PMCUFixedAddressParameter import PMCUFixedAddressParameter
  12. from pimonitor.cu.PMCUParameter import PMCUParameter
  13. from pimonitor.cu.PMCUStandardParameter import PMCUStandardParameter
  14. from pimonitor.cu.PMCUSwitchParameter import PMCUSwitchParameter
  15. # <parameter id="P1" name="Engine Load (Relative)" desc="P1" ecubyteindex="8" ecubit="7" target="1">
  16. # <address>0x000007</address>
  17. # <conversions>
  18. # <conversion units="%" expr="x*100/255" format="0.00" />
  19. # </conversions>
  20. #</parameter>
  21. #<ecuparam id="E20" name="Manifold Absolute Pressure (Direct)*" desc="E20-Manifold Absolute Pressure with " target="1">
  22. # <ecu id="1B04400405">
  23. # <address length="2">0x2186A</address>
  24. # </ecu>
  25. # ... ecu and conversions
  26. #<parameter id="P200" name="Engine Load (Calculated)" desc="P200-Engine load as calculated from MAF and RPM." target="1">
  27. # <depends>
  28. # <ref parameter="P8" />
  29. # <ref parameter="P12" />
  30. # </depends>
  31. # <conversions>
  32. # <conversion units="g/rev" expr="(P12*60)/P8" format="0.00" />
  33. # </conversions>
  34. #</parameter>
  35. # <switch id="S71" name="Clear Memory Terminal" desc="(E) S71" byte="0x000061" bit="0" ecubyteindex="19" target="1" />
  36. class PMXmlParser(xml.sax.ContentHandler):
  37. def __init__(self):
  38. xml.sax.ContentHandler.__init__(self)
  39. self._message = ''
  40. self._log_id = 0
  41. self._element_no = 0
  42. self._contexts = None
  43. self._parameter = None
  44. self._parameters = set()
  45. self._characters = ''
  46. self._ecu_ids = None
  47. self._address_length = 0
  48. self._proto_id = ''
  49. def parse(self, file_name):
  50. self._message = 'Parsing XML data'
  51. self._log_id = PM.log(self._message)
  52. file_path = os.path.join("data", file_name)
  53. source = open(file_path)
  54. xml.sax.parse(source, self)
  55. self.log_progress()
  56. PM.log(self._message + " [DONE]")
  57. return self._parameters
  58. def startElement(self, name, attrs):
  59. pid = None
  60. desc = None
  61. target = 0
  62. units = None
  63. expr = None
  64. value_format = None
  65. address = None
  66. byte_index = PMCUParameter.CU_INVALID_BYTE_INDEX()
  67. bit_index = PMCUParameter.CU_INVALID_BIT_INDEX()
  68. if name == "protocol":
  69. for (k, v) in attrs.items():
  70. if k == "id":
  71. print 'protocol ' + v
  72. self._proto_id = v
  73. if self._proto_id != "SSM":
  74. return
  75. if name == "parameter":
  76. for (k, v) in attrs.items():
  77. if k == "id":
  78. pid = v
  79. if k == "name":
  80. name = v
  81. if k == "desc":
  82. desc = v
  83. if k == "ecubyteindex":
  84. byte_index = int(v)
  85. if k == "ecubit":
  86. bit_index = int(v)
  87. if k == "target":
  88. target = int(v)
  89. if byte_index is not PMCUParameter.CU_INVALID_BYTE_INDEX() and bit_index is not PMCUParameter.CU_INVALID_BIT_INDEX():
  90. self._parameter = PMCUStandardParameter(pid, name, desc, byte_index, bit_index, target)
  91. elif byte_index is PMCUParameter.CU_INVALID_BYTE_INDEX() and bit_index is PMCUParameter.CU_INVALID_BIT_INDEX():
  92. self._parameter = PMCUCalculatedParameter(pid, name, desc, target)
  93. else:
  94. raise Exception
  95. elif name == "ecuparam":
  96. for (k, v) in attrs.items():
  97. if k == "id":
  98. pid = v
  99. if k == "name":
  100. name = v
  101. if k == "desc":
  102. desc = v
  103. if k == "target":
  104. target = int(v)
  105. self._parameter = PMCUFixedAddressParameter(pid, name, desc, target)
  106. elif name == "switch":
  107. for (k, v) in attrs.items():
  108. if k == "id":
  109. pid = v
  110. if k == "name":
  111. name = v
  112. if k == "desc":
  113. desc = v
  114. if k == "byte":
  115. address = int(v, 16)
  116. if k == "ecubyteindex":
  117. byte_index = int(v)
  118. if k == "bit":
  119. bit_index = int(v)
  120. if k == "target":
  121. target = int(v)
  122. self._parameter = PMCUSwitchParameter(pid, name, desc, address, byte_index, bit_index, target)
  123. elif name == "address":
  124. self._address_length = 1
  125. for (k, v) in attrs.items():
  126. if k == "length":
  127. self._address_length = int(v)
  128. elif name == "conversion":
  129. for (k, v) in attrs.items():
  130. if k == "units":
  131. units = v
  132. if k == "expr":
  133. expr = v
  134. if k == "format":
  135. value_format = v
  136. self._parameter.add_conversion(PMCUConversion(units, expr, value_format))
  137. elif name == "ecu":
  138. for (k, v) in attrs.items():
  139. if k == "id":
  140. self._ecu_ids = v.split(",")
  141. elif name == "ref":
  142. for (k, v) in attrs.items():
  143. if k == "parameter":
  144. self._parameter.add_dependency(v)
  145. def characters(self, content):
  146. if self._proto_id != "SSM":
  147. return
  148. self._characters = self._characters + content
  149. def endElement(self, name):
  150. if self._proto_id != "SSM":
  151. return
  152. if name == "parameter":
  153. self._parameters.add(self._parameter)
  154. self._parameter = None
  155. elif name == "ecuparam":
  156. self._parameters.add(self._parameter)
  157. self._parameter = None
  158. elif name == "switch":
  159. self._parameters.add(self._parameter)
  160. self._parameter = None
  161. elif name == "address":
  162. self._characters = self._characters.strip()
  163. if len(self._characters.strip()) > 0:
  164. if self._parameter.get_cu_type() == PMCUParameter.CU_TYPE_STD_PARAMETER():
  165. self._parameter.set_address(PMCUAddress(int(self._characters, 16), self._address_length))
  166. elif self._parameter.get_cu_type() == PMCUParameter.CU_TYPE_FIXED_ADDRESS_PARAMETER():
  167. address = PMCUAddress(int(self._characters, 16), self._address_length)
  168. for ecu_id in self._ecu_ids:
  169. self._parameter.add_ecu_id(ecu_id, address)
  170. self._address_length = 0
  171. self._characters = ''
  172. elif name == "ecu":
  173. self._ecu_ids = None
  174. self._element_no += 1
  175. if self._element_no % 1000 == 0:
  176. self.log_progress()
  177. def log_progress(self):
  178. PM.log(self._message + " " + str(self._element_no) + " elements, " + str(len(self._parameters)) + " parameters",
  179. self._log_id)