PMXmlParser.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  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. def parse(self, file_name):
  49. self._message = 'Parsing XML data'
  50. self._log_id = PM.log(self._message)
  51. file_path = os.path.join("data", file_name)
  52. source = open(file_path)
  53. xml.sax.parse(source, self)
  54. self.log_progress()
  55. PM.log(self._message + " [DONE]", self._log_id)
  56. return self._parameters
  57. def startElement(self, name, attrs):
  58. pid = None
  59. desc = None
  60. target = 0
  61. units = None
  62. expr = None
  63. value_format = None
  64. address = None
  65. byte_index = PMCUParameter.CU_INVALID_BYTE_INDEX()
  66. bit_index = PMCUParameter.CU_INVALID_BIT_INDEX()
  67. if name == "parameter":
  68. for (k, v) in attrs.items():
  69. if k == "id":
  70. pid = v
  71. if k == "name":
  72. name = v
  73. if k == "desc":
  74. desc = v
  75. if k == "ecubyteindex":
  76. byte_index = int(v)
  77. if k == "ecubit":
  78. bit_index = int(v)
  79. if k == "target":
  80. target = int(v)
  81. if byte_index is not PMCUParameter.CU_INVALID_BYTE_INDEX() and bit_index is not PMCUParameter.CU_INVALID_BIT_INDEX():
  82. self._parameter = PMCUStandardParameter(pid, name, desc, byte_index, bit_index, target)
  83. elif byte_index is PMCUParameter.CU_INVALID_BYTE_INDEX() and bit_index is PMCUParameter.CU_INVALID_BIT_INDEX():
  84. self._parameter = PMCUCalculatedParameter(pid, name, desc, target)
  85. else:
  86. raise Exception
  87. if name == "ecuparam":
  88. for (k, v) in attrs.items():
  89. if k == "id":
  90. pid = v
  91. if k == "name":
  92. name = v
  93. if k == "desc":
  94. desc = v
  95. if k == "target":
  96. target = int(v)
  97. self._parameter = PMCUFixedAddressParameter(pid, name, desc, target)
  98. if name == "switch":
  99. for (k, v) in attrs.items():
  100. if k == "id":
  101. pid = v
  102. if k == "name":
  103. name = v
  104. if k == "desc":
  105. desc = v
  106. if k == "byte":
  107. address = int(v, 16)
  108. if k == "ecubyteindex":
  109. byte_index = int(v)
  110. if k == "bit":
  111. bit_index = int(v)
  112. if k == "target":
  113. target = int(v)
  114. self._parameter = PMCUSwitchParameter(pid, name, desc, address, byte_index, bit_index, target)
  115. if name == "address":
  116. self._address_length = 1
  117. for (k, v) in attrs.items():
  118. if k == "length":
  119. self._address_length = int(v)
  120. if name == "conversion":
  121. for (k, v) in attrs.items():
  122. if k == "units":
  123. units = v
  124. if k == "expr":
  125. expr = v
  126. if k == "format":
  127. value_format = v
  128. self._parameter.add_conversion(PMCUConversion(units, expr, value_format))
  129. if name == "ecu":
  130. for (k, v) in attrs.items():
  131. if k == "id":
  132. self._ecu_ids = v.split(",")
  133. if name == "ref":
  134. for (k, v) in attrs.items():
  135. if k == "parameter":
  136. self._parameter.add_dependency(v)
  137. def characters(self, content):
  138. self._characters = self._characters + content
  139. def endElement(self, name):
  140. if name == "parameter":
  141. self._parameters.add(self._parameter)
  142. self._parameter = None
  143. if name == "ecuparam":
  144. self._parameters.add(self._parameter)
  145. self._parameter = None
  146. if name == "switch":
  147. self._parameters.add(self._parameter)
  148. self._parameter = None
  149. if name == "address":
  150. self._characters = self._characters.strip()
  151. if len(self._characters.strip()) > 0:
  152. if self._parameter.get_cu_type() == PMCUParameter.CU_TYPE_STD_PARAMETER():
  153. self._parameter.set_address(PMCUAddress(int(self._characters, 16), self._address_length))
  154. elif self._parameter.get_cu_type() == PMCUParameter.CU_TYPE_FIXED_ADDRESS_PARAMETER():
  155. address = PMCUAddress(int(self._characters, 16), self._address_length)
  156. for ecu_id in self._ecu_ids:
  157. self._parameter.add_ecu_id(ecu_id, address)
  158. self._address_length = 0
  159. self._characters = ''
  160. if name == "ecu":
  161. self._ecu_ids = None
  162. self._element_no += 1
  163. if self._element_no % 1000 == 0:
  164. self.log_progress()
  165. def log_progress(self):
  166. PM.log(self._message + " " + str(self._element_no) + " elements, " + str(len(self._parameters)) + " parameters",
  167. self._log_id)