Skip to content

Commit 405eb6d

Browse files
author
juergen heilgemeir
committed
changes taken over from temporary repo
- added function remove_ca function to ecu-class - added function send_pgn function to ControllerApplication-class - j1939 only receives messages with extended identifiers - fix BAM timeout-error - fix TP-BAM receive No TP-BAM was received because an incorrect timestamp was set and therefore the message was deleted do to timeout - added support to receive more than 1 packet in sequence with connect mode data transfer (CMDT) Until now, a TP.CTS was sent by the receiver after each TP.DT - fixed problem that TP-BAM is limited to pdu_specific value of 255 - forward priority, source address and time stamp to notifications
1 parent dfbec0c commit 405eb6d

9 files changed

+175
-110
lines changed

LICENSE

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2018 Frank Benkert ([email protected])
3+
Copyright (c) 2021 juergenH87
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.rst

+43-43
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,20 @@
11
SAE J1939 for Python
22
====================
33

4-
|release| |docs| |build|
4+
|release| |docs|
55

6-
.. |release| image:: https://img.shields.io/pypi/v/j1939.svg
7-
:target: https://pypi.python.org/pypi/j1939/
6+
.. |release| image:: https://img.shields.io/pypi/v/can-j1939
7+
:target: https://pypi.python.org/pypi/can-j1939/
88
:alt: Latest Version on PyPi
99

1010
.. |docs| image:: https://readthedocs.org/projects/j1939/badge/?version=latest
1111
:target: https://j1939.readthedocs.io/en/latest/
1212
:alt: Documentation build Status
13-
14-
.. |build| image:: https://travis-ci.com/benkfra/j1939.svg?branch=master
15-
:target: https://travis-ci.com/benkfra/j1939/branches
16-
:alt: Travis CI Server for master branch
1713

18-
A new implementation of the CAN SAE J1939 standard for Python.
1914

20-
WARNING: Currently this project is in alpha-state! Some of the features are not completely working!
15+
A implementation of the CAN SAE J1939 standard for Python.
16+
This implementation was taken from https://github.com/benkfra/j1939, as no
17+
further development took place.
2118

2219
If you experience a problem or think the stack would not behave properly, do
2320
not hesitate to open a ticket or write an email.
@@ -28,12 +25,14 @@ At the time of writing the supported interfaces are
2825

2926
* CAN over Serial
3027
* CAN over Serial / SLCAN
28+
* CANalyst-II
3129
* IXXAT Virtual CAN Interface
3230
* Kvaser’s CANLIB
3331
* NEOVI Interface
3432
* NI-CAN
3533
* PCAN Basic API
3634
* Socketcan
35+
* SYSTEC interface
3736
* USB2CAN Interface
3837
* Vector
3938
* Virtual
@@ -78,26 +77,16 @@ Features
7877
Installation
7978
------------
8079

81-
As soon the package is available in your distro, it's as easy as::
80+
Install can-j1939 with pip::
8281

83-
$ pip install j1939
84-
85-
In the meanwhile you can either download the wheel-package and issue the command::
86-
87-
$ pip install j1939-0.1.0.dev1-py2.py3-none-any.whl
82+
$ pip install can-j1939
8883

8984
or do the trick with::
9085

91-
$ git clone https://github.com/benkfra/j1939.git
86+
$ git clone https://github.com/juergenH87/can-j1939.git
9287
$ cd j1939
9388
$ pip install .
9489

95-
If you want to be able to change the code while using it, clone it then install it in `develop mode`_::
96-
97-
$ git clone https://github.com/benkfra/j1939.git
98-
$ cd j1939
99-
$ pip install -e .
100-
10190

10291
Quick start
10392
-----------
@@ -114,11 +103,17 @@ To simply receive all passing (public) messages on the bus you can subscribe to
114103
logging.getLogger('j1939').setLevel(logging.DEBUG)
115104
logging.getLogger('can').setLevel(logging.DEBUG)
116105
117-
def on_message(pgn, data):
106+
def on_message(priority, pgn, sa, timestamp, data):
118107
"""Receive incoming messages from the bus
119108
109+
:param int priority:
110+
Priority of the message
120111
:param int pgn:
121112
Parameter Group Number of the message
113+
:param int sa:
114+
Source Address of the message
115+
:param int timestamp:
116+
Timestamp of the message
122117
:param bytearray data:
123118
Data of the PDU
124119
"""
@@ -189,18 +184,24 @@ A more sophisticated example in which the CA class was overloaded to include its
189184
"""
190185
self._ecu.remove_timer(self.timer_callback)
191186
192-
def on_message(self, pgn, data):
187+
def on_message(self, priority, pgn, sa, timestamp, data):
193188
"""Feed incoming message to this CA.
194189
(OVERLOADED function)
190+
:param int priority:
191+
Priority of the message
195192
:param int pgn:
196193
Parameter Group Number of the message
194+
:param intsa:
195+
Source Address of the message
196+
:param int timestamp:
197+
Timestamp of the message
197198
:param bytearray data:
198199
Data of the PDU
199200
"""
200201
print("PGN {} length {}".format(pgn, len(data)))
201202
202203
def timer_callback(self, cookie):
203-
"""Callback for sending the IEC1 message
204+
"""Callback for sending messages
204205
205206
This callback is registered at the ECU timer event mechanism to be
206207
executed every 500ms.
@@ -213,24 +214,23 @@ A more sophisticated example in which the CA class was overloaded to include its
213214
# returning true keeps the timer event active
214215
return True
215216
216-
pgn = j1939.ParameterGroupNumber(0, 0xFE, 0xF6)
217-
data = [
218-
j1939.ControllerApplication.FieldValue.NOT_AVAILABLE_8, # Particulate Trap Inlet Pressure (SPN 81)
219-
j1939.ControllerApplication.FieldValue.NOT_AVAILABLE_8, # Boost Pressure (SPN 102)
220-
j1939.ControllerApplication.FieldValue.NOT_AVAILABLE_8, # Intake Manifold 1 Temperature (SPN 105)
221-
j1939.ControllerApplication.FieldValue.NOT_AVAILABLE_8, # Air Inlet Pressure (SPN 106)
222-
j1939.ControllerApplication.FieldValue.NOT_AVAILABLE_8, # Air Filter 1 Differential Pressure (SPN 107)
223-
j1939.ControllerApplication.FieldValue.NOT_AVAILABLE_16_ARR[0], # Exhaust Gas Temperature (SPN 173)
224-
j1939.ControllerApplication.FieldValue.NOT_AVAILABLE_16_ARR[1],
225-
j1939.ControllerApplication.FieldValue.NOT_AVAILABLE_8, # Coolant Filter Differential Pressure (SPN 112)
226-
]
227-
228-
# SPN 105, Range -40..+210
229-
# (Offset -40)
230-
receiverTemperature = 30
231-
data[2] = receiverTemperature + 40
232-
233-
self.send_message(6, pgn.value, data)
217+
# create data with 8 bytes
218+
data = [j1939.ControllerApplication.FieldValue.NOT_AVAILABLE_8] * 8
219+
220+
# sending normal broadcast message
221+
self.send_pgn(0, 0xFE, 0xF6, 6, data)
222+
223+
# sending normal peer-to-peer message, destintion address is 0x04
224+
self.send_pgn(0, 0xD0, 0x04, 6, data)
225+
226+
# create data with 100 bytes
227+
data = [j1939.ControllerApplication.FieldValue.NOT_AVAILABLE_8] * 100
228+
229+
# sending multipacket message with TP-BAM
230+
self.send_pgn(0, 0xFE, 0xF6, 6, data)
231+
232+
# sending multipacket message with TP-CMDT, destination address is 0x05
233+
self.send_pgn(0, 0xD0, 0x05, 6, data)
234234
235235
# returning true keeps the timer event active
236236
return True

examples/own_ca_producer.py

+26-21
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,24 @@ def stop(self):
3232
"""
3333
self._ecu.remove_timer(self.timer_callback)
3434

35-
def on_message(self, pgn, data):
35+
def on_message(self, priority, pgn, sa, timestamp, data):
3636
"""Feed incoming message to this CA.
3737
(OVERLOADED function)
38+
:param int priority:
39+
Priority of the message
3840
:param int pgn:
3941
Parameter Group Number of the message
42+
:param intsa:
43+
Source Address of the message
44+
:param int timestamp:
45+
Timestamp of the message
4046
:param bytearray data:
4147
Data of the PDU
4248
"""
4349
print("PGN {} length {}".format(pgn, len(data)))
4450

4551
def timer_callback(self, cookie):
46-
"""Callback for sending the IEC1 message
52+
"""Callback for sending messages
4753
4854
This callback is registered at the ECU timer event mechanism to be
4955
executed every 500ms.
@@ -56,24 +62,23 @@ def timer_callback(self, cookie):
5662
# returning true keeps the timer event active
5763
return True
5864

59-
pgn = j1939.ParameterGroupNumber(0, 0xFE, 0xF6)
60-
data = [
61-
j1939.ControllerApplication.FieldValue.NOT_AVAILABLE_8, # Particulate Trap Inlet Pressure (SPN 81)
62-
j1939.ControllerApplication.FieldValue.NOT_AVAILABLE_8, # Boost Pressure (SPN 102)
63-
j1939.ControllerApplication.FieldValue.NOT_AVAILABLE_8, # Intake Manifold 1 Temperature (SPN 105)
64-
j1939.ControllerApplication.FieldValue.NOT_AVAILABLE_8, # Air Inlet Pressure (SPN 106)
65-
j1939.ControllerApplication.FieldValue.NOT_AVAILABLE_8, # Air Filter 1 Differential Pressure (SPN 107)
66-
j1939.ControllerApplication.FieldValue.NOT_AVAILABLE_16_ARR[0], # Exhaust Gas Temperature (SPN 173)
67-
j1939.ControllerApplication.FieldValue.NOT_AVAILABLE_16_ARR[1],
68-
j1939.ControllerApplication.FieldValue.NOT_AVAILABLE_8, # Coolant Filter Differential Pressure (SPN 112)
69-
]
70-
71-
# SPN 105, Range -40..+210
72-
# (Offset -40)
73-
receiverTemperature = 30
74-
data[2] = receiverTemperature + 40
75-
76-
self.send_message(6, pgn.value, data)
65+
# create data with 8 bytes
66+
data = [j1939.ControllerApplication.FieldValue.NOT_AVAILABLE_8] * 8
67+
68+
# sending normal broadcast message
69+
self.send_pgn(0, 0xFE, 0xF6, 6, data)
70+
71+
# sending normal peer-to-peer message, destintion address is 0x04
72+
self.send_pgn(0, 0xD0, 0x04, 6, data)
73+
74+
# create data with 100 bytes
75+
data = [j1939.ControllerApplication.FieldValue.NOT_AVAILABLE_8] * 100
76+
77+
# sending multipacket message with TP-BAM
78+
self.send_pgn(0, 0xFE, 0xF6, 6, data)
79+
80+
# sending multipacket message with TP-CMDT, destination address is 0x05
81+
self.send_pgn(0, 0xD0, 0x05, 6, data)
7782

7883
# returning true keeps the timer event active
7984
return True
@@ -123,4 +128,4 @@ def main():
123128
ecu.disconnect()
124129

125130
if __name__ == '__main__':
126-
main()
131+
main()

examples/simple_receive_global.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,17 @@
66
logging.getLogger('j1939').setLevel(logging.DEBUG)
77
logging.getLogger('can').setLevel(logging.DEBUG)
88

9-
def on_message(pgn, data):
9+
def on_message(priority, pgn, sa, timestamp, data):
1010
"""Receive incoming messages from the bus
1111
12+
:param int priority:
13+
Priority of the message
1214
:param int pgn:
1315
Parameter Group Number of the message
16+
:param int sa:
17+
Source Address of the message
18+
:param int timestamp:
19+
Timestamp of the message
1420
:param bytearray data:
1521
Data of the PDU
1622
"""
@@ -41,4 +47,4 @@ def main():
4147
ecu.disconnect()
4248

4349
if __name__ == '__main__':
44-
main()
50+
main()

j1939/controller_application.py

+12-1
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,12 @@ def send_message(self, priority, parameter_group_number, data):
192192

193193
mid = j1939.MessageId(priority=priority, parameter_group_number=parameter_group_number, source_address=self._device_address)
194194
self._ecu.send_message(mid.can_id, data)
195+
196+
def send_pgn(self, data_page, pdu_format, pdu_specific, priority, data):
197+
if self.state != ControllerApplication.State.NORMAL:
198+
raise RuntimeError("Could not send message unless address claiming has finished")
195199

200+
self._ecu.send_pgn(data_page, pdu_format, pdu_specific, priority, self._device_address_preferred, data)
196201

197202
def _send_address_claimed(self, address):
198203
# TODO: Normally the (initial) address claimed message must not be an auto repeat message.
@@ -203,11 +208,17 @@ def _send_address_claimed(self, address):
203208
data = self._name.bytes
204209
self._ecu.send_message(mid.can_id, data)
205210

206-
def on_message(self, pgn, data):
211+
def on_message(self, priority, pgn, sa, timestamp, data):
207212
"""Callback for incoming message
208213
214+
:param int priority:
215+
Priority of the message
209216
:param int pgn:
210217
Parameter Group Number of the message
218+
:param sa:
219+
Source Address of the message
220+
:param timestamp:
221+
Timestamp of the message
211222
:param bytearray data:
212223
Data of the PDU
213224
"""

0 commit comments

Comments
 (0)