Initial source upload

This commit is contained in:
Randall Crock 2013-12-02 22:00:58 -07:00
parent 2cf5957475
commit d5ab166597
20 changed files with 63050 additions and 0 deletions

686
data/cu_ids.txt Normal file
View file

@ -0,0 +1,686 @@
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfVehicle xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<vehicle>
<id>2</id>
<name>Generic 11-bit</name>
<protocol>ISO15765</protocol>
<speed>250000</speed>
<obdcodefile />
<addressbits>11</addressbits>
<secured>false</secured>
<checksum>false</checksum>
<initprocedure>0</initprocedure>
<txaddrlist>
<addrlist>
<address>0x07df Broadcast</address>
<broadcast>true</broadcast>
</addrlist>
<addrlist>
<address>0x07e0</address>
<broadcast>false</broadcast>
</addrlist>
<addrlist>
<address>0x07e1</address>
<broadcast>false</broadcast>
</addrlist>
<addrlist>
<address>0x07e2</address>
<broadcast>false</broadcast>
</addrlist>
<addrlist>
<address>0x07e3</address>
<broadcast>false</broadcast>
</addrlist>
<addrlist>
<address>0x07e4</address>
<broadcast>false</broadcast>
</addrlist>
<addrlist>
<address>0x07e5</address>
<broadcast>false</broadcast>
</addrlist>
<addrlist>
<address>0x07e6</address>
<broadcast>false</broadcast>
</addrlist>
<addrlist>
<address>0x07e7</address>
<broadcast>false</broadcast>
</addrlist>
</txaddrlist>
<rxaddrlist>
<addrlist>
<address>0x07e8</address>
<broadcast>false</broadcast>
</addrlist>
<addrlist>
<address>0x07e9</address>
<broadcast>false</broadcast>
</addrlist>
<addrlist>
<address>0x07ea</address>
<broadcast>false</broadcast>
</addrlist>
<addrlist>
<address>0x07eb</address>
<broadcast>false</broadcast>
</addrlist>
<addrlist>
<address>0x07ec</address>
<broadcast>false</broadcast>
</addrlist>
<addrlist>
<address>0x07ed</address>
<broadcast>false</broadcast>
</addrlist>
<addrlist>
<address>0x07ee</address>
<broadcast>false</broadcast>
</addrlist>
<addrlist>
<address>0x07ef</address>
<broadcast>false</broadcast>
</addrlist>
</rxaddrlist>
<msgflags>
<flags>
<flag>ISO15765_FRAME_PAD</flag>
</flags>
</msgflags>
<connflags />
<ecus />
<config />
<pidgroups>
<pidgroup>
<id>1</id>
<name>SAE PIDs</name>
<mode_int>1</mode_int>
</pidgroup>
</pidgroups>
<capabilities />
</vehicle>
<vehicle>
<id>3</id>
<name>Generic 29-bit</name>
<protocol>ISO15765</protocol>
<speed>0</speed>
<testeraddress>0xF3</testeraddress>
<obdcodefile />
<addressbits>29</addressbits>
<secured>false</secured>
<checksum>false</checksum>
<initprocedure>0</initprocedure>
<txaddrlist>
<addrlist>
<address>0x18db3300 Broadcast</address>
<broadcast>true</broadcast>
</addrlist>
<addrlist>
<address>0x18da0000</address>
<broadcast>false</broadcast>
</addrlist>
</txaddrlist>
<rxaddrlist>
<addrlist>
<address>0x18da0000</address>
<broadcast>false</broadcast>
</addrlist>
</rxaddrlist>
<msgflags>
<flags>
<flag>CAN_29BIT_ID</flag>
</flags>
<flags>
<flag>ISO15765_FRAME_PAD</flag>
</flags>
</msgflags>
<connflags>
<flags>
<flag>CAN_29BIT_ID</flag>
</flags>
</connflags>
<ecus>
<ecuData>
<id>0x10</id>
<name>EMS</name>
</ecuData>
<ecuData>
<id>0x17</id>
<name>TCU</name>
</ecuData>
</ecus>
<config />
<pidgroups>
<pidgroup>
<id>1</id>
<name>SAE PIDs</name>
<mode_int>1</mode_int>
</pidgroup>
</pidgroups>
<capabilities />
</vehicle>
<vehicle>
<id>5</id>
<name>ISO9141</name>
<protocol>ISO9141</protocol>
<speed>10400</speed>
<testeraddress>0xF1</testeraddress>
<obdcodefile>obdcodes_Subaru.txt</obdcodefile>
<addressbits>11</addressbits>
<secured>false</secured>
<checksum>true</checksum>
<initprocedure>0</initprocedure>
<txaddrlist>
<addrlist>
<address>0xc0 Broadcast</address>
<broadcast>true</broadcast>
</addrlist>
<addrlist>
<address>0x80</address>
<broadcast>false</broadcast>
</addrlist>
</txaddrlist>
<rxaddrlist>
<addrlist>
<address>0xf0</address>
<broadcast>false</broadcast>
</addrlist>
</rxaddrlist>
<msgflags />
<connflags />
<ecus />
<config>
<configpars>
<name>DATA_RATE</name>
<value>10400</value>
</configpars>
<configpars>
<name>P1_MAX</name>
<value>10</value>
</configpars>
<configpars>
<name>P3_MIN</name>
<value>0</value>
</configpars>
<configpars>
<name>P4_MIN</name>
<value>0</value>
</configpars>
<configpars>
<name>LOOPBACK</name>
<value>1</value>
</configpars>
</config>
<pidgroups>
<pidgroup>
<id>1</id>
<name>SAE PIDs</name>
<mode_int>1</mode_int>
</pidgroup>
</pidgroups>
<capabilities>
<capability>
<name>SSM</name>
</capability>
</capabilities>
</vehicle>
<vehicle>
<id>4</id>
<name>Subaru CAN-Bus</name>
<brand>Subaru</brand>
<protocol>ISO15765</protocol>
<speed>0</speed>
<obdcodefile>obdcodes_Subaru.txt</obdcodefile>
<addressbits>11</addressbits>
<secured>false</secured>
<checksum>false</checksum>
<initprocedure>0</initprocedure>
<txaddrlist>
<addrlist>
<address>0x07df Broadcast</address>
<broadcast>true</broadcast>
</addrlist>
<addrlist>
<address>0x07e0</address>
<broadcast>false</broadcast>
</addrlist>
</txaddrlist>
<rxaddrlist>
<addrlist>
<address>0x07e8</address>
<broadcast>false</broadcast>
</addrlist>
</rxaddrlist>
<msgflags>
<flags>
<flag>ISO15765_FRAME_PAD</flag>
</flags>
</msgflags>
<connflags />
<ecus>
<ecuData>
<id>0x00</id>
<name>ECM</name>
</ecuData>
<ecuData>
<id>0x01</id>
<name>TCU</name>
</ecuData>
<ecuData>
<id>0x02</id>
<name>TBD2</name>
</ecuData>
<ecuData>
<id>0x03</id>
<name>TBD3</name>
</ecuData>
<ecuData>
<id>0x04</id>
<name>TBD4</name>
</ecuData>
<ecuData>
<id>0x05</id>
<name>TBD5</name>
</ecuData>
<ecuData>
<id>0x06</id>
<name>TBD6</name>
</ecuData>
<ecuData>
<id>0x07</id>
<name>TBD7</name>
</ecuData>
</ecus>
<config>
<configpars>
<name>ISO15765_BS</name>
<value>1</value>
</configpars>
<configpars>
<name>ISO15765_STMIN</name>
<value>42</value>
</configpars>
</config>
<pidgroups>
<pidgroup>
<id>1</id>
<name>SAE PIDs</name>
<mode_int>1</mode_int>
</pidgroup>
<pidgroup>
<id>10</id>
<name>SSM Data</name>
<mode_int>168</mode_int>
</pidgroup>
<pidgroup>
<id>2</id>
<name>Extended PIDs.</name>
<mode_int>34</mode_int>
</pidgroup>
<pidgroup>
<id>11</id>
<name>Subaru Extended PIDs</name>
<mode_int>34</mode_int>
</pidgroup>
<pidgroup>
<id>8</id>
<name>Vehicle Information</name>
<mode_int>9</mode_int>
</pidgroup>
</pidgroups>
<capabilities>
<capability>
<name>SSM</name>
</capability>
</capabilities>
</vehicle>
<vehicle>
<id>5</id>
<name>Subaru ISO9141</name>
<brand>Subaru</brand>
<protocol>ISO9141</protocol>
<speed>4800</speed>
<testeraddress>0xF0</testeraddress>
<obdcodefile>obdcodes_Subaru.txt</obdcodefile>
<addressbits>11</addressbits>
<secured>false</secured>
<checksum>false</checksum>
<initprocedure>0</initprocedure>
<txaddrlist>
<addrlist>
<address>0xc0 Broadcast</address>
<broadcast>true</broadcast>
</addrlist>
<addrlist>
<address>0x80</address>
<broadcast>false</broadcast>
</addrlist>
</txaddrlist>
<rxaddrlist>
<addrlist>
<address>0xf0</address>
<broadcast>false</broadcast>
</addrlist>
</rxaddrlist>
<msgflags />
<connflags>
<flags>
<flag>ISO9141_K_LINE_ONLY</flag>
</flags>
<flags>
<flag>ISO9141_NO_CHECKSUM</flag>
</flags>
</connflags>
<ecus />
<config>
<configpars>
<name>DATA_RATE</name>
<value>4800</value>
</configpars>
<configpars>
<name>P1_MAX</name>
<value>2</value>
</configpars>
<configpars>
<name>P3_MIN</name>
<value>0</value>
</configpars>
<configpars>
<name>P4_MIN</name>
<value>0</value>
</configpars>
<configpars>
<name>LOOPBACK</name>
<value>1</value>
</configpars>
</config>
<pidgroups>
<pidgroup>
<id>10</id>
<name>SSM Data</name>
<mode_int>168</mode_int>
</pidgroup>
<pidgroup>
<id>1</id>
<name>SAE PIDs</name>
<mode_int>1</mode_int>
</pidgroup>
<pidgroup>
<id>8</id>
<name>Vehicle Information</name>
<mode_int>9</mode_int>
</pidgroup>
</pidgroups>
<capabilities>
<capability>
<name>SSM</name>
</capability>
</capabilities>
</vehicle>
<vehicle>
<id>6</id>
<name>Test</name>
<protocol>ISO15765</protocol>
<speed>0</speed>
<testeraddress>0xF2</testeraddress>
<obdcodefile />
<addressbits>29</addressbits>
<secured>false</secured>
<checksum>false</checksum>
<initprocedure>0</initprocedure>
<txaddrlist>
<addrlist>
<address>0x18db3300 Broadcast</address>
<broadcast>true</broadcast>
</addrlist>
<addrlist>
<address>0x18da0000</address>
<broadcast>false</broadcast>
</addrlist>
</txaddrlist>
<rxaddrlist>
<addrlist>
<address>0x18da0000</address>
<broadcast>false</broadcast>
</addrlist>
</rxaddrlist>
<msgflags>
<flags>
<flag>CAN_29BIT_ID</flag>
</flags>
<flags>
<flag>ISO15765_FRAME_PAD</flag>
</flags>
</msgflags>
<connflags>
<flags>
<flag>CAN_29BIT_ID</flag>
</flags>
</connflags>
<ecus>
<ecuData>
<id>0x10</id>
<name>EMS - Engine Management System</name>
</ecuData>
<ecuData>
<id>0x11</id>
<name>ACM - Aftertreatment Control Module</name>
</ecuData>
<ecuData>
<id>0x12</id>
<name>CAP - Clear Air Power ECU</name>
</ecuData>
<ecuData>
<id>0x18</id>
<name>TECU - Transmission ECU</name>
</ecuData>
<ecuData>
<id>0x20</id>
<name>CCIOM - Center Chassis I/O Module</name>
</ecuData>
<ecuData>
<id>0x21</id>
<name>FCIOM - Front Chassis I/O Module</name>
</ecuData>
<ecuData>
<id>0x22</id>
<name>RCIOM - Rear Chassis I/O Module</name>
</ecuData>
<ecuData>
<id>0x23</id>
<name>APM - Air Pressure Management</name>
</ecuData>
<ecuData>
<id>0x24</id>
<name>VMCU - Vehicle Master Control Unit</name>
</ecuData>
<ecuData>
<id>0x25</id>
<name>TPM - Tire Pressure Management</name>
</ecuData>
<ecuData>
<id>0x26</id>
<name>WRG - Wireless Remote Gateway</name>
</ecuData>
<ecuData>
<id>0x28</id>
<name>ABS - Antilock Brake System</name>
</ecuData>
<ecuData>
<id>0x30</id>
<name>FAS - Front Axle Steering</name>
</ecuData>
<ecuData>
<id>0x31</id>
<name>EAS - Extra Axle Steering</name>
</ecuData>
<ecuData>
<id>0x40</id>
<name>CIOM - Cab I/O Module</name>
</ecuData>
<ecuData>
<id>0x41</id>
<name>TGW2 - Telematics GateWay 2</name>
</ecuData>
<ecuData>
<id>0x50</id>
<name>DACU - Driver Assitance Control Unit</name>
</ecuData>
<ecuData>
<id>0x51</id>
<name>LPOS - Lane Position Object Control Unit</name>
</ecuData>
<ecuData>
<id>0x52</id>
<name>FLS - Forward Looking Sensor</name>
</ecuData>
<ecuData>
<id>0x53</id>
<name>SRS - Safety Restraint System</name>
</ecuData>
<ecuData>
<id>0x60</id>
<name>HMIIOM - Human-Machine Interface I/O Module</name>
</ecuData>
<ecuData>
<id>0x61</id>
<name>IC - Instrument Cluster</name>
</ecuData>
<ecuData>
<id>0x62</id>
<name>SID - Secondary Information Display</name>
</ecuData>
<ecuData>
<id>0x63</id>
<name>VS - VideoSwitch</name>
</ecuData>
<ecuData>
<id>0x70</id>
<name>BLECU - Bending Light ECU</name>
</ecuData>
<ecuData>
<id>0x80</id>
<name>Audio - Audio</name>
</ecuData>
<ecuData>
<id>0x98</id>
<name>CCM - Climate Control Module</name>
</ecuData>
<ecuData>
<id>0xa0</id>
<name>DDM - Driver Door Module</name>
</ecuData>
<ecuData>
<id>0xa1</id>
<name>PDM - Passenger Door Module</name>
</ecuData>
<ecuData>
<id>0xa2</id>
<name>LECM1 - Living Environment Control Module</name>
</ecuData>
<ecuData>
<id>0xc0</id>
<name>Alarm - Alarm ECU</name>
</ecuData>
<ecuData>
<id>0xd0</id>
<name>BCU - Battery Control Unit - Local and Remote controlled main battery switch</name>
</ecuData>
<ecuData>
<id>0xd1</id>
<name>GPMECU_1 - General Purpose Machine Electronic Control Unit 1</name>
</ecuData>
<ecuData>
<id>0xd2</id>
<name>GPMECU_2 - General Purpose Machine Electronic Control Unit 2</name>
</ecuData>
<ecuData>
<id>0xd3</id>
<name>GPMECU_3 - General Purpose Machine Electronic Control Unit 3</name>
</ecuData>
<ecuData>
<id>0xe6</id>
<name>BBM - Body Builder Module</name>
</ecuData>
<ecuData>
<id>0xee</id>
<name>TACHO - Tachograph</name>
</ecuData>
<ecuData>
<id>0xef</id>
<name>HPCU - Hybrid Powertrain Control Unit</name>
</ecuData>
</ecus>
<config />
<pidgroups>
<pidgroup>
<id>1</id>
<name>SAE PIDs</name>
<mode_int>1</mode_int>
</pidgroup>
</pidgroups>
<capabilities />
</vehicle>
<vehicle>
<id>9</id>
<name>Toyota</name>
<speed>500000</speed>
<obdcodefile>obdcodes_Toyota.txt</obdcodefile>
<addressbits>11</addressbits>
<secured>false</secured>
<checksum>false</checksum>
<initprocedure>0</initprocedure>
<txaddrlist />
<rxaddrlist />
<msgflags />
<connflags />
<ecus />
<config />
<pidgroups />
<capabilities />
</vehicle>
<vehicle>
<id>8</id>
<name>Volvo</name>
<protocol>ISO9141</protocol>
<speed>10400</speed>
<testeraddress>0xF0</testeraddress>
<obdcodefile>obdcodes_Volvo.txt</obdcodefile>
<addressbits>11</addressbits>
<secured>false</secured>
<checksum>true</checksum>
<initprocedure>0</initprocedure>
<txaddrlist>
<addrlist>
<address>0x33 Broadcast</address>
<broadcast>true</broadcast>
</addrlist>
<addrlist>
<address>0x10</address>
<broadcast>false</broadcast>
</addrlist>
</txaddrlist>
<rxaddrlist>
<addrlist>
<address>0xF0</address>
<broadcast>false</broadcast>
</addrlist>
</rxaddrlist>
<msgflags />
<connflags />
<ecus />
<config />
<pidgroups>
<pidgroup>
<id>1</id>
<name>SAE PIDs</name>
<mode_int>1</mode_int>
</pidgroup>
</pidgroups>
<capabilities>
<capability>
<name>VC1</name>
</capability>
</capabilities>
</vehicle>
</ArrayOfVehicle>

17
data/ecu_response.txt Normal file
View file

@ -0,0 +1,17 @@
P104 l=1
Sending: [0x80, 0x18, 0xF0, 0x05, 0xA8, 0x00, 0x00, 0x00, 0x56, 0x8B], dst: 0x18, src: 0xf0, len: 5
Read: [0x80, 0xF0, 0x18, 0x02, 0xE8, 0x60, 0xD2], dst: 0xf0, src: 0x18, len: 2
P8 l=2
Sending: [0x80, 0x10, 0xF0, 0x08, 0xA8, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0F, 0x4D], dst: 0x10, src: 0xf0, len: 8
Read: [0x80, 0xF0, 0x10, 0x03, 0xE8, 0x00, 0x00, 0x6B], dst: 0xf0, src: 0x10, len: 3
P17 P122 P8
Cumulative packet: [0x80, 0x10, 0xF0, 0x0E, 0xA8, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x01, 0x13, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0F, 0x83], dst: 0x10, src: 0xf0, len: 14
Received packet: [0x80, 0xF0, 0x10, 0x05, 0xE8, 0x99, 0x5E, 0x00, 0x00, 0x64], dst: 0xf0, src: 0x10, len: 5
Single out packet: [0x80, 0xF0, 0x10, 0x01, 0x99, 0x1A], dst: 0xf0, src: 0x10, len: 1
Single out packet: [0x80, 0xF0, 0x10, 0x01, 0x5E, 0xDF], dst: 0xf0, src: 0x10, len: 1
Single out packet: [0x80, 0xF0, 0x10, 0x02, 0x00, 0x00, 0x82], dst: 0xf0, src: 0x10, len: 2
Read: [0x80, 0xF0, 0x10, 0x01, 0x99, 0x1A], dst: 0xf0, src: 0x10, len: 1

93
data/logger.dtd Normal file
View file

@ -0,0 +1,93 @@
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT address ( #PCDATA ) >
<!ATTLIST address length CDATA #IMPLIED >
<!ATTLIST address bit ( 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 ) #IMPLIED >
<!ELEMENT ecu ( address ) >
<!ATTLIST ecu id CDATA #REQUIRED >
<!ELEMENT ref EMPTY >
<!ATTLIST ref ecuparam CDATA #IMPLIED >
<!ATTLIST ref parameter IDREF #IMPLIED >
<!ELEMENT depends ( ref+ ) >
<!ELEMENT replace EMPTY >
<!ATTLIST replace value CDATA #REQUIRED >
<!ATTLIST replace with CDATA #REQUIRED >
<!ELEMENT conversion ( replace* ) >
<!ATTLIST conversion expr CDATA #REQUIRED >
<!ATTLIST conversion format ( 0 | 0.0 | 0.00 | 0.000 | 0.0000 ) #REQUIRED >
<!ATTLIST conversion storagetype ( uint8 | uint16 | float ) #IMPLIED >
<!ATTLIST conversion units CDATA #REQUIRED >
<!ATTLIST conversion gauge_min CDATA #IMPLIED >
<!ATTLIST conversion gauge_max CDATA #IMPLIED >
<!ATTLIST conversion gauge_step CDATA #IMPLIED >
<!ELEMENT conversions ( conversion+ ) >
<!ELEMENT parameter ( ( address, conversions?) | (depends, conversions) ) >
<!ATTLIST parameter target CDATA #REQUIRED >
<!ATTLIST parameter ecubit ( 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 ) #IMPLIED >
<!ATTLIST parameter ecubyteindex CDATA #IMPLIED >
<!ATTLIST parameter desc CDATA #REQUIRED >
<!ATTLIST parameter name CDATA #REQUIRED >
<!ATTLIST parameter id ID #REQUIRED >
<!ELEMENT parameters ( parameter+ ) >
<!ELEMENT switch EMPTY >
<!ATTLIST switch target CDATA #REQUIRED >
<!ATTLIST switch ecubyteindex CDATA #IMPLIED >
<!ATTLIST switch bit ( 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 ) #REQUIRED >
<!ATTLIST switch byte CDATA #REQUIRED >
<!ATTLIST switch desc CDATA #REQUIRED >
<!ATTLIST switch name CDATA #REQUIRED >
<!ATTLIST switch id ID #REQUIRED >
<!ELEMENT switches ( switch+ ) >
<!ELEMENT ecuparam ( ecu+, conversions? ) >
<!ATTLIST ecuparam target CDATA #REQUIRED >
<!ATTLIST ecuparam desc CDATA #REQUIRED >
<!ATTLIST ecuparam name CDATA #REQUIRED >
<!ATTLIST ecuparam id ID #REQUIRED >
<!ELEMENT ecuparams ( ecuparam+ ) >
<!ELEMENT type (#PCDATA) >
<!ELEMENT carmass (#PCDATA) >
<!ELEMENT finalratio (#PCDATA) >
<!ELEMENT rollcoeff (#PCDATA) >
<!ELEMENT dragcoeff (#PCDATA) >
<!ELEMENT frontalarea (#PCDATA) >
<!ELEMENT transmission (#PCDATA) >
<!ELEMENT gearratio1 (#PCDATA) >
<!ELEMENT gearratio2 (#PCDATA) >
<!ELEMENT gearratio3 (#PCDATA) >
<!ELEMENT gearratio4 (#PCDATA) >
<!ELEMENT gearratio5 (#PCDATA) >
<!ELEMENT gearratio6 (#PCDATA) >
<!ELEMENT tirewidth (#PCDATA) >
<!ELEMENT tireaspect (#PCDATA) >
<!ELEMENT wheelsize (#PCDATA) >
<!ELEMENT car (type,carmass,finalratio,rollcoeff,dragcoeff,frontalarea,transmission,gearratio1,gearratio2,gearratio3,gearratio4,gearratio5?,gearratio6?,tirewidth,tireaspect,wheelsize) >
<!ELEMENT dyno ( car+ ) >
<!ELEMENT protocol ( parameters?, switches?, ecuparams?, dyno? ) >
<!ATTLIST protocol id ID #REQUIRED >
<!ATTLIST protocol baud CDATA #REQUIRED >
<!ATTLIST protocol databits CDATA #REQUIRED >
<!ATTLIST protocol stopbits CDATA #REQUIRED >
<!ATTLIST protocol parity CDATA #REQUIRED >
<!ATTLIST protocol connect_timeout CDATA #REQUIRED >
<!ATTLIST protocol send_timeout CDATA #REQUIRED >
<!ELEMENT protocols ( protocol+ ) >
<!ELEMENT logger ( protocols ) >
<!ATTLIST logger version CDATA #IMPLIED >

60995
data/logger_METRIC_EN_v131.xml Normal file

File diff suppressed because it is too large Load diff

9
data/out.txt Normal file
View file

@ -0,0 +1,9 @@
mobica-769:PiMonitor citan$ PYTHONPATH=.:/opt/local/Library/Frameworks/Python.framework/Versions/3.2 python3.2 pimonitor/PMMain.py
header: [128, 16, 240]
size: [128, 16, 240, 1]
data: [128, 16, 240, 1, 191]
read: b'\x80\x10\xf0\x01\xbf@'
header: [128, 240, 16]
size: [128, 240, 16, 105]
data: [128, 240, 16, 105, 255, 162, 16, 2, 77, 18, 4, 64, 6, 243, 250, 201, 142, 34, 4, 2, 172, 0, 0, 0, 96, 206, 84, 248, 185, 132, 0, 108, 32, 0, 0, 0, 0, 0, 220, 0, 0, 69, 31, 48, 128, 240, 32, 31, 2, 67, 251, 0, 241, 193, 132, 0, 0, 0, 0, 0, 241, 128, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
read: b'\x80\xf0\x10i\xff\xa2\x10\x02M\x12\x04@\x06\xf3\xfa\xc9\x8e"\x04\x02\xac\x00\x00\x00`\xceT\xf8\xb9\x84\x00l \x00\x00\x00\x00\x00\xdc\x00\x00E\x1f0\x80\xf0 \x1f\x02C\xfb\x00\xf1\xc1\x84\x00\x00\x00\x00\x00\xf1\x80\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00&'

31
pimonitor/PM.py Normal file
View file

@ -0,0 +1,31 @@
'''
Created on 22-04-2013
@author: citan
'''
import platform
class PM(object):
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(PM, cls).__new__(cls, *args, **kwargs)
return cls._instance
def __init__(self):
pass
def set(self, log):
self._log = log
@classmethod
def log(cls, message, mid=0):
return PM().log_impl(message, mid)
def log_impl(self, message, mid):
return self._log(message, mid)
def in_demo(self):
return False

139
pimonitor/PMConnection.py Normal file
View file

@ -0,0 +1,139 @@
'''
Created on 29-03-2013
@author: citan
'''
import serial
import time
from pimonitor.PMPacket import PMPacket
class PMConnection(object):
'''
classdocs
'''
def __init__(self):
'''
Constructor
'''
self._ser = None
def open(self):
self._ser = serial.Serial(
port='/dev/ttyUSB0',
# port='/dev/tty.usbserial-000013FA',
baudrate=4800,
timeout=2000,
writeTimeout=55,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS)
time.sleep(0.2)
def close(self):
if self._ser != None:
self._ser.close()
def init(self, target):
request_packet = PMPacket(self.get_destination(target), 0xF0, [0xBF])
return self.send_packet(request_packet)
def send_packet(self, packet):
self._ser.write(packet.to_string())
time.sleep(0.05)
out_packet = None
tmp = []
data = []
while self._ser.inWaiting() > 0:
tmp = []
# read header
tmp = self._ser.read(3)
data.extend(tmp)
# read size
sizebytes = self._ser.read()
data.append(sizebytes[0])
size = ord(sizebytes[0])
# read data
tmp = self._ser.read(size)
data.extend(tmp)
# read checksum
data.extend(self._ser.read())
data = map(ord, data)
out_packet = PMPacket.from_array(data)
data = []
if(packet.is_equal(out_packet)):
continue
return out_packet
def read_parameter(self, parameter):
address = parameter.get_address()
address_len = parameter.get_address_length()
data = []
data.append(0xA8)
data.append(0x00)
for i in range(0, address_len):
target_address = address + i
data.append((target_address & 0xffffff) >> 16)
data.append((target_address & 0xffff) >> 8)
data.append(target_address & 0xff)
request_packet = PMPacket(self.get_destination(parameter.get_target()), 0xf0, data)
return self.send_packet(request_packet)
def read_parameters(self, parameters):
data = []
target = parameters[0].get_target()
data.append(0xA8)
data.append(0x00)
for parameter in parameters:
# TODO:
if target != parameter.get_target() and target & 0x01 != parameter.get_target() & 0x01 and target & 0x02 != parameter.get_target() & 0x02:
raise Exception('connection', "targets differ: " + str(target) + " vs " + str(parameter.get_target()))
address = parameter.get_address()
address_len = parameter.get_address_length()
for i in range(0, address_len):
target_address = address + i
data.append((target_address & 0xffffff) >> 16)
data.append((target_address & 0xffff) >> 8)
data.append(target_address & 0xff)
request_packet = PMPacket(self.get_destination(target), 0xf0, data)
out_packet = self.send_packet(request_packet)
out_data = out_packet.get_data()
out_packets = []
data_offset = 1 # skip E8
for parameter in parameters:
address_len = parameter.get_address_length()
single_out_data = [0xE8]
single_out_data.extend(out_data[data_offset:address_len + data_offset])
single_out_packet = PMPacket(out_packet.get_destination(), out_packet.get_source(), single_out_data);
out_packets.append(single_out_packet)
data_offset += address_len
return out_packets
def get_destination(self, target):
dst = target
if target == 1:
dst = 0x10
if target == 2:
dst = 0x18
if target == 3:
dst = 0x10
return dst

View file

@ -0,0 +1,82 @@
'''
Created on 29-03-2013
@author: citan
'''
from pimonitor.PM import PM
from pimonitor.PMPacket import PMPacket
import random
import time
class PMDemoConnection(object):
'''
classdocs
'''
def __init__(self):
'''
Constructor
'''
self._ser = None
self._log_id = None
random.seed()
self._byteval = [0, 0, 0, 0]
def open(self):
message = 'Opening serial connection...'
self._log_id = PM.log(message)
time.sleep(0.2)
PM.log(message + " [DONE]", self._log_id)
def close(self):
PM.log("Closing serial connection", self._log_id)
pass
def init(self, target):
PM.log('Initializing CU for target: ' + str(target), self._log_id)
if target == 1 or target == 3:
response = [0x80, 0xF0, 0x10, 0x69, 0xFF, 0xA2, 0x10, 0x02, 0x4D, 0x12, 0x04, 0x40, 0x06, 0xF3, 0xFA, 0xC9, 0x8E, 0x22, 0x04, 0x02, 0xAC, 0x00, 0x00, 0x00, 0x60, 0xCE, 0x54, 0xF8, 0xB9, 0x84, 0x00, 0x6C, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x00, 0x00, 0x45, 0x1F, 0x30, 0x80, 0xF0, 0x20, 0x1F, 0x02, 0x43, 0xFB, 0x00, 0xF1, 0xC1, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF1, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26]
if target == 2:
response = [0x80, 0xF0, 0x18, 0x39, 0xFF, 0xA2, 0x10, 0x21, 0xD0, 0xF3, 0x70, 0x31, 0x00, 0x01, 0x00, 0x80, 0x04, 0x00, 0x00, 0x00, 0x00, 0xBD, 0xC3, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x3E, 0x00, 0x0B, 0x21, 0xC0, 0x00, 0x00, 0x01, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51]
return PMPacket.from_array(response)
def send_packet(self, packet):
raise Exception('connection', 'should never be called')
def read_parameter(self, parameter):
time.sleep(0.05)
address_len = parameter.get_address_length()
data = [0x80, 0xF0] # [0x80, 0xF0, 0x18, 0x02, 0xE8, 0x60, 0xD2]
if parameter.get_target() == 1 or parameter.get_target() == 3:
data.append(0x10)
if parameter.get_target() == 2:
data.append(0x18)
data.append(address_len+1)
data.append(0xE8)
for i in range(0, address_len):
self._byteval[i] = (self._byteval[i] + 1) % 0xFF
data.append(self._byteval[i])
checksum = 0
for b in data:
checksum = (checksum + b) & 0xFF
data.append(checksum)
return PMPacket.from_array(data)
def read_parameters(self, parameters):
time.sleep(0.05)
out_packets = []
for parameter in parameters:
out_packets.append(self.read_parameter(parameter))
return out_packets

142
pimonitor/PMMain.py Normal file
View file

@ -0,0 +1,142 @@
# -*- coding: utf-8 -*-
'''
Created on 29-03-2013
@author: citan
'''
import array
import os
import os.path
import time
import cPickle as pickle
from pimonitor.PM import PM
from pimonitor.PMConnection import PMConnection
from pimonitor.PMDemoConnection import PMDemoConnection
from pimonitor.PMPacket import PMPacket
from pimonitor.PMParameter import PMParameter
from pimonitor.PMUtils import PMUtils
from pimonitor.PMXmlParser import PMXmlParser
from pimonitor.ui.PMScreen import PMScreen
from pimonitor.ui.PMSingleWindow import PMSingleWindow
if __name__ == '__main__':
from evdev import InputDevice, list_devices
devices = map(InputDevice, list_devices())
eventX = ""
for dev in devices:
if dev.name == "ADS7846 Touchscreen":
eventX = dev.fn
os.environ["SDL_FBDEV"] = "/dev/fb1"
os.environ["SDL_MOUSEDRV"] = "TSLIB"
os.environ["SDL_MOUSEDEV"] = eventX
screen = PMScreen()
log_id = PM.log('Application started')
screen.render()
parser = PMXmlParser();
supported_parameters = []
if os.path.isfile("data/data.pkl"):
input = open("data/data.pkl", "rb")
defined_parameters = pickle.load(input)
input.close()
else:
defined_parameters = parser.parse("logger_METRIC_EN_v131.xml")
output = open("data/data.pkl", "wb")
pickle.dump(defined_parameters, output, -1)
output.close()
connection = PMConnection()
#connection = PMDemoConnection()
while True:
try:
connection.open()
ecu_packet = connection.init(1)
tcu_packet = connection.init(2)
if ecu_packet == None or tcu_packet == None:
PM.log("Can't get initial data", log_id)
continue;
for p in defined_parameters:
if (p.get_target() & 0x1 == 0x1) and p.is_supported(ecu_packet.to_bytes()[5:]):
if not filter(lambda x: x.get_id() == p.get_id(), supported_parameters):
supported_parameters.append(p)
for p in defined_parameters:
if ((p.get_target() & 0x2 == 0x2) or (p.get_target() & 0x1 == 0x1)) and p.is_supported(tcu_packet.to_bytes()[5:]):
if not filter(lambda x: x.get_id() == p.get_id(), supported_parameters):
supported_parameters.append(p)
for p in defined_parameters:
p_deps = p.get_dependencies();
if not p_deps:
continue
deps_found = ()
for dep in p_deps:
deps_found = filter(lambda x: x.get_id() == dep, supported_parameters)
if not deps_found:
break
if len(deps_found) > 1:
raise Exception('duplicated dependencies', deps_found)
p.add_parameter(deps_found[0])
if deps_found:
supported_parameters.append(p)
# each ID must be in a form P01 - first letter, then a number
supported_parameters.sort(key=lambda p: int(p.get_id()[1:]), reverse=False)
for p in supported_parameters:
window = PMSingleWindow(p)
screen.add_window(window)
while True:
window = screen.get_window()
param = window.get_parameter()
parameters = param.get_parameters()
if parameters:
packets = connection.read_parameters(parameters)
window.set_packets(packets)
else:
packet = connection.read_parameter(param)
window.set_packets([packet])
#ecu_response_packets = connection.read_parameters(ecu_params)
#tcu_response_packets = connection.read_parameters(tcu_params)
#param_no = 0
#for ecu_packet in ecu_response_packets:
# param = ecu_params[param_no]
# window.set_value(param, ecu_packet)
# param_no += 1
#param_no = 0
#for tcu_packet in tcu_response_packets:
# param = tcu_params[param_no]
# window.set_value(param, tcu_packet)
# param_no += 1
screen.render()
except IOError as e:
PM.log('I/O error: {0} {1}'.format(e.errno, e.strerror), log_id)
if connection != None:
connection.close()
time.sleep(3)
continue
screen.close()

116
pimonitor/PMPacket.py Normal file
View file

@ -0,0 +1,116 @@
'''
Created on 13-04-2013
@author: citan
'''
import array
import binascii
import collections
class PMPacket(object):
'''
classdocs
'''
# 0x80
# destination byte
# source byte
# data size byte
# ...
# checksum byte sum of every byte in packet (incl. header)
_header_byte = 0x80
_valid_bytes = [0xFF, 0xA8, 0xE8]
def __init__(self, dst, src, data):
self._dst = dst
self._src = src
self._data = data
@classmethod
def from_array(cls, data):
validate = PMPacket.is_valid(data)
if (not validate[0]):
raise Exception('packet', validate[1])
dst = data[1]
src = data[2]
data = data[4:-1]
return cls(dst, src, data)
@classmethod
def is_valid(cls, data):
# TODO: check E8
valid = True
msg = ""
valid = valid and (len(data) > 5)
msg += "invalid length (too short), " if (not valid) else ""
valid = valid and (data[0] == PMPacket._header_byte)
msg += "invalid header, " if (not valid) else ""
#valid = data[4] in PMPacket._valid_bytes
#msg += "invalid header, expected one of " + ', '.join(hex(s) for s in PMPacket._valid_bytes) +", got: " + hex(data[4]) + ", " if (not valid) else ""
#valid = valid and ((data[1] == 0x10) or (data[1] == 0xf0))
#valid = valid and ((data[2] == 0x10) or (data[2] == 0xf0))
#valid = valid and (data[1] != data[2])
#msg += "invalid source/target, " if (not valid) else ""
current_len = len(data)
expected_len = 5 + data[3]
valid = valid and (current_len == expected_len)
msg += "invalid length (is: " + str(current_len) + ", expected: " + str(expected_len) + "), " if (not valid) else ""
checksum = 0
for i in range(0, len(data) - 1):
checksum = (checksum + data[i]) & 0xFF
valid = valid and (checksum == data[-1])
msg += "invalid checksum (is " + str(checksum) + ", expected: " + str(data[-1]) + "), " if (not valid) else ""
return valid, msg
def is_equal(self, packet):
return self.to_bytes() == packet.to_bytes()
def to_bytes(self):
length = len(self._data)
packet = [self._header_byte, self._dst, self._src, length]
packet.extend(self._data)
checksum = 0
for b in packet:
checksum = (checksum + b) & 0xFF
packet.append(checksum)
return packet
def to_string(self):
return array.array('B', self.to_bytes()).tostring()
def dump(self):
return "["+ ', '.join(("0x%0.2X" % s) for s in self.to_bytes()) + "], dst: " + hex(self._dst) + ", src: " + hex(self._src) + ", len: " + str(len(self._data))
def get_data(self):
return self._data
def get_destination(self):
return self._dst
def get_source(self):
return self._src
def get_romid(self):
if self._data[0] != 0xFF:
raise Exception('packet', "not valid init response")
if len(self._data) < 9:
raise Exception('packet', "not valid init response")
rom_id = ((self._data[4] << 32) | (self._data[5] << 24) | (self._data[6] << 16) | (self._data[7] << 8) | (self._data[8])) & 0xFFFFFFFFFF
return hex(rom_id).lstrip("0x").upper()
@classmethod
def dump_header(cls, data):
print("header ["+ ', '.join(hex(s) for s in data) +"], len: " + str(len(data)))

165
pimonitor/PMParameter.py Normal file
View file

@ -0,0 +1,165 @@
'''
Created on 29-03-2013
@author: citan
'''
import re
class PMParameter(object):
'''
classdocs
'''
def __init__(self, pid, name, desc, byte_index, bit_index, target):
'''
Constructor
'''
self._id = pid
self._name = name
self._desc = desc
self._byte_index = byte_index
self._bit_index = bit_index
self._target = target
self._conversions = []
self._dependencies = []
self._parameters = []
self._address = 0
self._address_length = 0
def get_id(self):
return self._id;
def set_address(self, address, length):
self._address = address
self._address_length = length
def get_address(self):
return self._address
def get_address_length(self):
return self._address_length
def get_target(self):
return self._target
def get_name(self):
return self._name
def add_conversion(self, conversion):
self._conversions.append(conversion)
def add_dependency(self, dependency):
self._dependencies.append(dependency)
def get_dependencies(self):
return self._dependencies
def add_parameter(self, parameter):
self._parameters.append(parameter)
def get_parameters(self):
return self._parameters
def get_calculated_value(self, packets, unit=None):
value = ""
local_vars = locals()
if len(self._conversions) > 0 and unit == None:
unit = self._conversions[0][0]
for conversion in self._conversions:
currunit = conversion[0]
expr = conversion[1]
value_format = conversion[2]
conversion_map = {}
if unit == currunit:
param_pairs = re.findall(r'\[([^]]*)\]',expr)
for pair in param_pairs:
attributes = pair.split(":")
key = attributes[0]
unit = attributes[1]
expr = expr.replace("[" + key + ":" + unit + "]", key)
conversion_map.update({key:unit})
param_no = 0
for packet in packets:
param = self._parameters[param_no];
if param.get_id() in conversion_map:
conversion_unit = conversion_map[param.get_id()]
else:
conversion_unit = None
value = param.get_value(packet, conversion_unit);
local_vars[param.get_id()] = float(value)
param_no += 1
try:
value = eval(expr)
except:
value = 0.0
format_tokens = value_format.split(".")
output_format = "%.0f"
if len(format_tokens) > 1:
output_format = "%." + str(len(format_tokens[1])) + "f"
value = output_format % value
return value
def get_value(self, packet, unit=None):
value = ""
if len(self._conversions) > 0 and unit == None:
unit = self._conversions[0][0]
for conversion in self._conversions:
currunit = conversion[0]
expr = conversion[1]
value_format = conversion[2]
if unit == currunit:
# ignore 0xe8
index = 1
x = 0
value_bytes = packet.get_data()[index:index + self._address_length]
if self._address_length == 1:
x = value_bytes[0]
if self._address_length == 2:
x = (value_bytes[0] << 8) | value_bytes[1]
x = float(x)
try:
value = eval(expr)
except:
value = 0.0
format_tokens = value_format.split(".")
output_format = "%.0f"
if len(format_tokens) > 1:
output_format = "%." + str(len(format_tokens[1])) + "f"
value = output_format % value
return value
def get_default_unit(self):
if len(self._conversions) > 0:
return self._conversions[0][0]
return ""
def is_supported(self, data):
if self._byte_index != "none" and self._bit_index != "none" and len(data) > self._byte_index:
cubyte = data[self._byte_index]
bitmask = 1 << self._bit_index
return cubyte & bitmask == bitmask
else:
return False
def to_string(self):
return "Param: id=" + self._id + ", name=" + self._name + ", desc=" + self._desc + ", byte=" + str(self._byte_index) + \
", bit=" + str(self._bit_index) + ", target=" + str(self._target) + ", conversions=" + '[%s]' % ', '.join(map(str, self._conversions)) + \
", address=" + hex(self._address) + "[" + str(self._address_length) + "]"

73
pimonitor/PMUtils.py Normal file
View file

@ -0,0 +1,73 @@
'''
Created on 13-04-2013
@author: citan
'''
import os
from pimonitor.PM import PM
class PMUtils(object):
'''
classdocs
'''
# Return CPU temperature as a character string
@classmethod
def get_cpu_temperature(cls):
res = os.popen('vcgencmd measure_temp').readline()
return(res.replace("temp=", "").replace("'C\n", ""))
# Return RAM information (unit=kb) in a list
# Index 0: total RAM
# Index 1: used RAM
# Index 2: free RAM
@classmethod
def get_ram_info(cls):
p = os.popen('free')
i = 0
while 1:
i = i + 1
line = p.readline()
if i == 2:
return(line.split()[1:4])
# Return % of CPU used by user as a character string
@classmethod
def get_cpu_use(cls):
return(str(os.popen("top -n1 | awk '/Cpu\(s\):/ {print $2}'").readline().strip()))
# Return information about disk space as a list (unit included)
# Index 0: total disk space
# Index 1: used disk space
# Index 2: remaining disk space
# Index 3: percentage of disk used
@classmethod
def get_disk_space(cls):
p = os.popen("df -h /")
i = 0
while 1:
i = i + 1
line = p.readline()
if i == 2:
return(line.split()[1:5])
@classmethod
def log_os_stats(cls):
try:
cpu_temp = PMUtils.get_cpu_temperature()
if len(cpu_temp) > 0:
PM.log("CPU temp: " + cpu_temp)
ram_stats = PMUtils.get_ram_info()
if len(ram_stats) == 3:
ram_free = round(int(ram_stats[2]) / 1000,1)
PM.log("RAM free: " + str(ram_free))
cpu_usage = PMUtils.get_cpu_use()
if len(cpu_usage) > 0:
PM.log("CPU usage: " + str(cpu_usage))
except IOError:
pass

112
pimonitor/PMXmlParser.py Normal file
View file

@ -0,0 +1,112 @@
'''
Created on 29-03-2013
@author: citan
'''
import xml.sax
import os.path
from pimonitor.PM import PM
from pimonitor.PMParameter import PMParameter
# TODO: dependencies
# TODO: ecuparams
class PMXmlParser(xml.sax.ContentHandler):
'''
classdocs
'''
def __init__(self):
'''
Constructor
'''
xml.sax.ContentHandler.__init__(self)
def parse(self, file_name):
self._parameters = set()
self._parameter = None
self._element_no = 0
self._message = "Parsing XML data"
self._log_id = PM.log(self._message)
source = open(os.path.join("data", file_name))
xml.sax.parse(source, self)
PM.log(self._message + " [DONE]", self._log_id)
return self._parameters
def startElement(self, name, attrs):
if name == "parameter":
# set optional arguments
byte_index = "none"
bit_index = "none"
for (k,v) in attrs.items():
if k == "id":
pid = v
if k == "name":
name = v
if k == "desc":
desc = v
if k == "ecubyteindex":
byte_index = int(v)
if k == "ecubit":
bit_index = int(v)
if k == "target":
target = int(v)
self._parameter = PMParameter(pid, name, desc, byte_index, bit_index, target)
if name == "address":
self._addrlen = 1
for (k,v) in attrs.items():
if k == "length":
self._addrlen = int(v)
if name == "depends":
self._addrlen = 0
if name == "ref":
for (k,v) in attrs.items():
if k == "parameter":
self._parameter.add_dependency(v)
if name == "conversion" and self._parameter != None:
for (k,v) in attrs.items():
if k == "units":
units = v
if k == "expr":
expr = v
if k == "format":
value_format = v
if self._parameter != None:
self._parameter.add_conversion([units, expr, value_format])
self._name = name
def characters(self, content):
if len(content.strip()) > 0 and self._name == "address" and self._parameter != None:
self._parameter.set_address(int(content, 16), self._addrlen)
def endElement(self, name):
if name == "parameter":
self._parameters.add(self._parameter)
self._parameter = None
self._addrlen = None
if name == "address":
self._addrlen = 0
if name == "depends":
pass
self._name = ""
self._element_no += 1
if self._element_no % 1000 == 0:
PM.log(self._message + " " + str(self._element_no) + " elements", self._log_id)

0
pimonitor/__init__.py Normal file
View file

235
pimonitor/ui/PMScreen.py Normal file
View file

@ -0,0 +1,235 @@
'''
Created on 18-04-2013
@author: citan
'''
import pygame
import os.path
import os
import sys
from pimonitor.PM import PM
from pimonitor.PMUtils import PMUtils
class PMScreen(object):
'''
classdocs
'''
LOG_FPS_EVENT = pygame.USEREVENT + 1
LOG_STATS_EVENT = LOG_FPS_EVENT + 1
ONE_SEC_EVENT = LOG_STATS_EVENT + 1
def __init__(self):
'''
Constructor
'''
pygame.init()
pygame.mouse.set_visible(False)
# seems to suit RPi
self._color_depth = 16
pygame.display.set_mode((0, 0), pygame.FULLSCREEN, self._color_depth)
#pygame.display.set_mode((640, 480), 0, self._color_depth)
self._surface = pygame.display.get_surface()
self._clock = pygame.time.Clock()
self._width = self._surface.get_width();
self._height = self._surface.get_height();
self._subwindow_alpha = 200
self._font_size = int(self._height / 14)
self._font = pygame.font.SysFont(pygame.font.get_default_font(), self._font_size)
self._font_aa = 0
self._fg_color = pygame.Color(255, 191, 0)
self._bg_color = pygame.Color(0, 0, 0)
self._dim_color = pygame.Color(200, 140, 0)
self._log_lines = 4
self._log_msg_id = 0
self._log_surface = pygame.Surface((self._width / 2, self._font_size * self._log_lines), 0, self._color_depth)
self._log_surface.set_alpha(self._subwindow_alpha)
self._log_queue = []
logger = PM()
logger.set(self.log)
self._fps_log_id = 0
self._frame_no = 0
self.load_resources()
pygame.time.set_timer(PMScreen.LOG_FPS_EVENT, 10000)
pygame.time.set_timer(PMScreen.LOG_STATS_EVENT, 30000)
pygame.time.set_timer(PMScreen.ONE_SEC_EVENT, 1000)
self._window = None
self._windows = []
self._pos_log_id = 0;
self._mouse_down_pos = (0, 0);
self._mouse_down_mark_timeout = 0
def clear(self):
self._surface.fill(self._bg_color)
def load_resources(self):
self._bg_img = pygame.image.load(os.path.join('res', 'subaru_logo.png')).convert()
self._bg_img_rect = self._bg_img.get_rect()
def render(self):
self._clock.tick()
for event in pygame.event.get():
if event.type == PMScreen.LOG_FPS_EVENT:
self._frame_no += 1
self._fps_log_id = PM.log("FPS %.2f" % self._clock.get_fps(), self._fps_log_id)
elif event.type == PMScreen.LOG_STATS_EVENT:
PMUtils.log_os_stats()
elif event.type == pygame.QUIT:
self.close()
sys.exit()
elif event.type == pygame.MOUSEBUTTONUP:
self._mouse_down_mark_timeout = 0
self._mouse_down_pos = pygame.mouse.get_pos();
self._pos_log_id = PM.log('Mouse up at: %s/%s' % pygame.mouse.get_pos(), self._pos_log_id);
if self._mouse_down_pos[0] < self._width / 2:
self.prev_window()
else:
self.next_window()
elif event.type == PMScreen.ONE_SEC_EVENT:
self._mouse_down_mark_timeout += 1
self.clear()
if self._window == None:
self.render_bg()
if self._window != None:
self._window.render()
self.render_log()
if self._mouse_down_mark_timeout < 2:
pygame.draw.circle(self._surface, self._dim_color, self._mouse_down_pos, 16);
pygame.display.update()
def render_log(self):
self.purge_logs()
if len(self._log_queue) == 0:
return
self._log_surface.fill(self._bg_color)
log_pos = 0
for msg_entry in self._log_queue:
msg_entry[2] = msg_entry[2] + 1
message = msg_entry[1]
message_lbl = self._font.render(message, self._font_aa, self._fg_color, self._bg_color)
self._log_surface.blit(message_lbl, (0, log_pos))
log_pos += self._font_size
self._surface.blit(self._log_surface, (0, self._height - self._log_surface.get_height()))
def render_bg(self):
#self._surface.blit(self._bg_img, self._bg_img_rect)
pass
def purge_oldest_log(self):
oldest = pygame.time.get_ticks()
for log_entry in self._log_queue:
if log_entry[2] < oldest:
oldest = log_entry[2]
to_be_deleted = log_entry
self._log_queue.remove(to_be_deleted)
def purge_logs(self):
to_be_deleted = []
for log_entry in self._log_queue:
if pygame.time.get_ticks() - log_entry[2] > 5000:
to_be_deleted.append(log_entry)
for log_entry in to_be_deleted:
self._log_queue.remove(log_entry)
def add_window(self, window):
self._windows.append(window);
if self._window == None:
self.next_window()
pass
def set_window(self, window):
if self._window != None:
self._window.set_surface(None)
self._window = window
self._window.set_surface(self._surface)
def get_window(self):
return self._window
def next_window(self):
if not self._windows:
return
if self._window != None:
index = self._windows.index(self._window)
else:
index = -1
new_index = (index + 1) % len(self._windows)
self.set_window(self._windows[new_index])
self.log_window(new_index)
def prev_window(self):
if not self._windows:
return
if self._window != None:
index = self._windows.index(self._window)
else:
index = 1
new_index = (index - 1) % len(self._windows)
self.set_window(self._windows[new_index])
self.log_window(new_index)
def log_window(self, index):
if self._window != None:
PM.log(str(index + 1) + '/' + str(len(self._windows)) + ': ' + self._window.get_parameter().get_id(), 0)
def log(self, message, mid):
ticks = pygame.time.get_ticks()
if mid == 0:
self._log_msg_id = (self._log_msg_id % 1000) + 1
mid = self._log_msg_id
found = False
for log_entry in self._log_queue:
if log_entry[0] == mid:
log_entry[1] = message
found = True
log_entry[2] = ticks
self.purge_logs()
# remove old messages if necessary
if not found:
if len(self._log_queue) >= self._log_lines :
self.purge_oldest_log()
self._log_queue.append([mid, message, ticks])
self.render()
return mid
def close(self):
pygame.display.quit()

View file

@ -0,0 +1,70 @@
'''
Created on 22-04-2013
@author: citan
'''
import pygame
class PMSingleWindow(object):
'''
classdocs
'''
def __init__(self, param):
self._fg_color = pygame.Color(230, 166, 0)
self._fg_color_dim = pygame.Color(200, 140, 0)
self._bg_color = pygame.Color(0, 0, 0)
self._param = param
self._packets = None
self._x_offset = 0
def set_surface(self, surface):
if surface == None:
return
self._surface = surface
self._width = self._surface.get_width();
self._height = self._surface.get_height();
self._title_font_size = int(self._surface.get_height() / 9)
self._value_font_size = int(self._surface.get_height() / 1.8)
self._unit_font_size = int(self._surface.get_height() / 4)
self._title_font = pygame.font.SysFont(pygame.font.get_default_font(), self._title_font_size)
self._value_font = pygame.font.SysFont(pygame.font.get_default_font(), self._value_font_size)
self._unit_font = pygame.font.SysFont(pygame.font.get_default_font(), self._unit_font_size)
self._font_aa = 1
self._title_lbl = self._title_font.render(self._param.get_name(), self._font_aa, self._fg_color)
value_lbl_width = self._value_font.render("-000.0", self._font_aa, self._fg_color).get_width()
self._x_offset = (self._width - value_lbl_width) / 2
self._unit_lbl = self._unit_font.render(self._param.get_default_unit(), self._font_aa, self._fg_color_dim)
self._end_x_offset = self._width - self._unit_lbl.get_width() - 10
def render(self):
if self._packets != None:
if self._param.get_address_length() > 0:
value = self._param.get_value(self._packets[0])
elif self._param.get_dependencies():
value = self._param.get_calculated_value(self._packets)
else:
value = "??"
value_lbl = self._value_font.render(value, self._font_aa, self._fg_color)
self._surface.blit(self._title_lbl, (2, 2))
self._surface.blit(value_lbl, (self._x_offset, 10 + self._title_font_size))
self._surface.blit(self._unit_lbl, (self._end_x_offset, 10 + self._title_font_size + self._value_font_size))
def set_packets(self, packets):
self._packets = packets
def get_parameter(self):
return self._param

83
pimonitor/ui/PMWindow.py Normal file
View file

@ -0,0 +1,83 @@
'''
Created on 22-04-2013
@author: citan
'''
import pygame
class PMWindow(object):
'''
classdocs
'''
def __init__(self):
self._fg_color = pygame.Color(255, 255, 255)
self._bg_color = pygame.Color(0, 0, 0)
self._dict = dict()
# P60 Gear position
# P97 Transfer Duty Ratio
# P96 Lock Up Duty Ratio
# P122 Oil Temperature
# P104 ATF Temperature
self._pids = ["P60", "P97", "P96", "P122", "P104"]
def set_surface(self, surface):
self._surface = surface
self._width = self._surface.get_width();
self._height = self._surface.get_height();
self._title_font_size = int(self._surface.get_height() / 16)
self._value_font_size = int(self._surface.get_height() / 3)
self._title_font = pygame.font.SysFont(pygame.font.get_default_font(), self._title_font_size)
self._value_font = pygame.font.SysFont(pygame.font.get_default_font(), self._value_font_size)
self._font_aa = 1
self._value_lbl_width = self._value_font.render("999", self._font_aa, self._fg_color).get_width()
def render(self):
first_row_height = self._title_font_size + self._value_font_size + 10
second_row_height = first_row_height + self._title_font_size + self._value_font_size + 20
pygame.draw.line(self._surface, self._fg_color, (0, first_row_height + 10), (self._width, first_row_height + 10))
for param, value in self._dict.iteritems():
title = param.get_name() #+ " (" + param.get_default_unit() + ")"
first_row_ids = ["P60", "P122", "P104"]
if param.get_id() in first_row_ids:
index = first_row_ids.index(param.get_id())
x_offset = (self._width / len(first_row_ids)) * index + 10
titlelbl = self._title_font.render(title, self._font_aa, self._fg_color)
valuelbl = self._value_font.render(value, self._font_aa, self._fg_color)
self._surface.blit(titlelbl, (x_offset + 10, 10))
self._surface.blit(valuelbl, (x_offset + 10, 10 + self._title_font_size))
pygame.draw.line(self._surface, self._fg_color, (x_offset, 0), (x_offset, first_row_height))
second_row_ids = ["P97", "P96"]
if param.get_id() in second_row_ids:
index = second_row_ids.index(param.get_id())
x_offset = (self._width / len(second_row_ids)) * index + 10
titlelbl = self._title_font.render(title, self._font_aa, self._fg_color)
valuelbl = self._value_font.render(value, self._font_aa, self._fg_color)
self._surface.blit(titlelbl, (x_offset + 10, first_row_height + 20))
self._surface.blit(valuelbl, (x_offset + 10, first_row_height + 20 + self._title_font_size))
pygame.draw.line(self._surface, self._fg_color, (x_offset, first_row_height + 20), (x_offset, second_row_height))
x_offset += 10
def get_pids(self):
return self._pids
def set_value(self, param, packet):
self._dict[param] = param.get_value(packet)

0
pimonitor/ui/__init__.py Normal file
View file

BIN
res/subaru_logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

2
run.sh Executable file
View file

@ -0,0 +1,2 @@
#!/bin/bash
sudo PYTHONPATH=. python /home/pi/devel/PiMonitor/pimonitor/PMMain.py