python-can-j1939 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
j1939/name.py ADDED
@@ -0,0 +1,268 @@
1
+
2
+ class Name:
3
+ """The Name of one Controller Application.
4
+
5
+ The Name consists of 64 bit:
6
+
7
+ 1-bit Arbitrary Address Capable
8
+ Indicate the capability to solve address conflicts.
9
+ Set to 1 if the device is Arbitrary Address Capable, set to 0 if
10
+ it's Single Address Capable.
11
+
12
+ 3-bit Industry Group
13
+ One of the predefined J1939 industry groups.
14
+
15
+ 4-bit Vehicle System Instance
16
+ Instance number of a vehicle system to distinguish two or more
17
+ device with the same Vehicle System number in the same J1939
18
+ network.
19
+ The first instance is assigned to the instance number 0.
20
+
21
+ 7-bit Vehicle System
22
+ A subcomponent of a vehicle, that includes one or more J1939
23
+ segments and may be connected or disconnected from the vehicle.
24
+ A Vehicle System may be made of one or more functions. The Vehicle
25
+ System depends on the Industry Group definition.
26
+
27
+ 1-bit Reserved
28
+ This field is reserved for future use by SAE.
29
+
30
+ 8-bit Function
31
+ One of the predefined J1939 functions. The same function value
32
+ (upper 128 only) may mean different things for different Industry
33
+ Groups or Vehicle Systems.
34
+
35
+ 5-bit Function Instance
36
+ Instance number of a function to distinguish two or more devices
37
+ with the same function number in the same J1939 network.
38
+ The first instance is assigned to the instance number 0.
39
+
40
+ 3-bit ECU Instance
41
+ Identify the ECU instance if multiple ECUs are involved in
42
+ performing a single function. Normally set to 0.
43
+
44
+ 11-bit Manufacturer Code
45
+ One of the predefined J1939 manufacturer codes.
46
+
47
+ 21-bit Identity Number
48
+ A unique number which identifies the particular device in a
49
+ manufacturer specific way.
50
+ """
51
+
52
+ class IndustryGroup:
53
+ Global = 0
54
+ OnHighway = 1
55
+ AgriculturalAndForestry = 2
56
+ Construction = 3
57
+ Marine = 4
58
+ Industrial = 5
59
+
60
+ def __init__(self, **kwargs):
61
+ """
62
+ :param value:
63
+ 64-bit value the address should be extracted from
64
+
65
+ :param bytes:
66
+ Array of 8 bytes containing the name object as binary representation.
67
+
68
+ :param arbitrary_address_capable:
69
+ 1-bit Arbitrary Address Capable
70
+ Indicate the capability to solve address conflicts.
71
+ Set to 1 if the device is Arbitrary Address Capable, set to 0 if
72
+ it's Single Address Capable.
73
+ :param industry_group:
74
+ 3-bit Industry Group
75
+ One of the predefined J1939 industry groups.
76
+ :param vehicle_system_instance:
77
+ 4-bit Vehicle System Instance
78
+ Instance number of a vehicle system to distinguish two or more
79
+ device with the same Vehicle System number in the same J1939
80
+ network.
81
+ The first instance is assigned to the instance number 0.
82
+ :param vehicle_system:
83
+ 7-bit Vehicle System
84
+ A subcomponent of a vehicle, that includes one or more J1939
85
+ segments and may be connected or disconnected from the vehicle.
86
+ A Vehicle System may be made of one or more functions. The Vehicle
87
+ System depends on the Industry Group definition.
88
+ :param function:
89
+ 8-bit Function
90
+ One of the predefined J1939 functions. The same function value
91
+ (upper 128 only) may mean different things for different Industry
92
+ Groups or Vehicle Systems.
93
+ :param function_instance:
94
+ 5-bit Function Instance
95
+ Instance number of a function to distinguish two or more devices
96
+ with the same function number in the same J1939 network.
97
+ The first instance is assigned to the instance number 0.
98
+ :param ecu_instance:
99
+ 3-bit ECU Instance
100
+ Identify the ECU instance if multiple ECUs are involved in
101
+ performing a single function. Normally set to 0.
102
+ :param manufacturer_code:
103
+ 11-bit Manufacturer Code
104
+ One of the predefined J1939 manufacturer codes.
105
+ :param identity_number:
106
+ 21-bit Identity Number
107
+ A unique number which identifies the particular device in a
108
+ manufacturer specific way.
109
+ """
110
+ if 'value' in kwargs:
111
+ self.value = kwargs['value']
112
+ elif 'bytes' in kwargs:
113
+ self.bytes = kwargs['bytes']
114
+ else:
115
+ self.arbitrary_address_capable = kwargs.get('arbitrary_address_capable', False)
116
+ if (self.arbitrary_address_capable < 0) or (self.arbitrary_address_capable > 1):
117
+ raise ValueError("Length of arbitrary address capable incorrect")
118
+ self.industry_group = kwargs.get('industry_group', Name.IndustryGroup.Global)
119
+ if (self.industry_group < 0) or (self.industry_group > ((2 ** 3) - 1)):
120
+ raise ValueError("Length of industry group incorrect")
121
+ self.vehicle_system_instance = kwargs.get('vehicle_system_instance', 0)
122
+ if (self.vehicle_system_instance < 0) or (self.vehicle_system_instance > ((2 ** 4) - 1)):
123
+ raise ValueError("Length of vehicle system instance incorrect")
124
+ self.vehicle_system = kwargs.get('vehicle_system', 0)
125
+ if (self.vehicle_system < 0) or (self.vehicle_system > ((2 ** 7) - 1)):
126
+ raise ValueError("Length of vehicle system incorrect")
127
+ self.function = kwargs.get('function', 0)
128
+ if (self.function < 0) or (self.function > ((2 ** 8) - 1)):
129
+ raise ValueError("Length of function incorrect")
130
+ self.function_instance = kwargs.get('function_instance', 0)
131
+ if (self.function_instance < 0) or (self.function_instance > ((2 ** 5) - 1)):
132
+ raise ValueError("Length of function instance incorrect")
133
+ self.ecu_instance = kwargs.get('ecu_instance', 0)
134
+ if (self.ecu_instance < 0) or (self.ecu_instance > ((2 ** 3) - 1)):
135
+ raise ValueError("Length of ecu instance incorrect")
136
+ self.manufacturer_code = kwargs.get('manufacturer_code', 0)
137
+ if (self.manufacturer_code < 0) or (self.manufacturer_code > ((2 ** 11) - 1)):
138
+ raise ValueError("Length of manufacturer code incorrect")
139
+ self.identity_number = kwargs.get('identity_number', 0)
140
+ if (self.identity_number < 0) or (self.identity_number > ((2 ** 21) - 1)):
141
+ raise ValueError("Length of identity number incorrect")
142
+
143
+ self.reserved_bit = 0
144
+
145
+ @property
146
+ def arbitrary_address_capable(self):
147
+ return self.__arbitrary_address_capable
148
+
149
+ @arbitrary_address_capable.setter
150
+ def arbitrary_address_capable(self, value):
151
+ self.__arbitrary_address_capable = value
152
+
153
+ @property
154
+ def industry_group(self):
155
+ return self.__industry_group
156
+
157
+ @industry_group.setter
158
+ def industry_group(self, value):
159
+ self.__industry_group = value
160
+
161
+ @property
162
+ def vehicle_system_instance(self):
163
+ return self.__vehicle_system_instance
164
+
165
+ @vehicle_system_instance.setter
166
+ def vehicle_system_instance(self, value):
167
+ self.__vehicle_system_instance = value
168
+
169
+ @property
170
+ def vehicle_system(self):
171
+ return self.__vehicle_system
172
+
173
+ @vehicle_system.setter
174
+ def vehicle_system(self, value):
175
+ self.__vehicle_system = value
176
+
177
+ @property
178
+ def reserved_bit(self):
179
+ return self.__reserved_bit
180
+
181
+ @reserved_bit.setter
182
+ def reserved_bit(self, value):
183
+ self.__reserved_bit = value
184
+
185
+ @property
186
+ def function(self):
187
+ return self.__function
188
+
189
+ @function.setter
190
+ def function(self, value):
191
+ self.__function = value
192
+
193
+ @property
194
+ def function_instance(self):
195
+ return self.__function_instance
196
+
197
+ @function_instance.setter
198
+ def function_instance(self, value):
199
+ self.__function_instance = value
200
+
201
+ @property
202
+ def ecu_instance(self):
203
+ return self.__ecu_instance
204
+
205
+ @ecu_instance.setter
206
+ def ecu_instance(self, value):
207
+ self.__ecu_instance = value
208
+
209
+ @property
210
+ def manufacturer_code(self):
211
+ return self.__manufacturer_code
212
+
213
+ @manufacturer_code.setter
214
+ def manufacturer_code(self, value):
215
+ self.__manufacturer_code = value
216
+
217
+ @property
218
+ def identity_number(self):
219
+ return self.__identity_number
220
+
221
+ @identity_number.setter
222
+ def identity_number(self, value):
223
+ self.__identity_number = value
224
+
225
+ @property
226
+ def value(self):
227
+ retval = self.identity_number
228
+ retval += (self.manufacturer_code << 21)
229
+ retval += (self.ecu_instance << 32)
230
+ retval += (self.function_instance << 35)
231
+ retval += (self.function << 40)
232
+ retval += (self.reserved_bit << 48)
233
+ retval += (self.vehicle_system << 49)
234
+ retval += (self.vehicle_system_instance << 56)
235
+ retval += (self.industry_group << 60)
236
+ retval += (self.arbitrary_address_capable << 63)
237
+ return retval
238
+
239
+ @value.setter
240
+ def value(self, value):
241
+ self.identity_number = value & ((2 ** 21) - 1)
242
+ self.manufacturer_code = (value >> 21) & ((2 ** 11) - 1)
243
+ self.ecu_instance = (value >> 32) & ((2 ** 3) - 1)
244
+ self.function_instance = (value >> 35) & ((2 ** 5) - 1)
245
+ self.function = (value >> 40) & ((2 ** 8) - 1)
246
+ self.reserved_bit = (value >> 48) & 1
247
+ self.vehicle_system = (value >> 49) & ((2 ** 7) - 1)
248
+ self.vehicle_system_instance = (value >> 56) & ((2 ** 4) - 1)
249
+ self.industry_group = (value >> 60) & ((2 ** 3) - 1)
250
+ self.arbitrary_address_capable = (value >> 63) & 1
251
+
252
+ @property
253
+ def bytes(self):
254
+ """Get the Name object as 8 Byte Data"""
255
+ return [
256
+ ((self.value >> 0) & 0xFF),
257
+ ((self.value >> 8) & 0xFF),
258
+ ((self.value >> 16) & 0xFF),
259
+ ((self.value >> 24) & 0xFF),
260
+ ((self.value >> 32) & 0xFF),
261
+ ((self.value >> 40) & 0xFF),
262
+ ((self.value >> 48) & 0xFF),
263
+ ((self.value >> 56) & 0xFF)
264
+ ]
265
+
266
+ @bytes.setter
267
+ def bytes(self, value):
268
+ self.value = int.from_bytes(value, byteorder='little', signed=False)
@@ -0,0 +1,136 @@
1
+ import j1939
2
+
3
+ class ParameterGroupNumber:
4
+ """Parameter Group Number (PGN).
5
+
6
+ The PGN are described in SAE J1939/21 and consists of four parts:
7
+ * 1-bit Reserved (sometimes referred to as Extended Data Page)
8
+ * 1-bit Data Page (DP)
9
+ * 8-bit PDU Format (PF)
10
+ * 8-bit PDU Specific (PS)
11
+
12
+ Predefined PGNs are listed in SAE J1939 and SAE J1939/71
13
+
14
+ A PF value from 0 to 239 (PDU1) indicates a destination address (DA) in PS
15
+ (peer-to-peer communication). A PF value from 240 to 255 (PDU2) indicates
16
+ a Group Extension (GE) inside the PS (broadcast message).
17
+ The DA 255 is called the Global Destination Address. It requires all nodes
18
+ to listen to and to respond, if required.
19
+
20
+ TODO: naming/wording: according the standard, a PGN in PDU1 format always
21
+ sets the 8 Bit PS to 0.
22
+ Do we have to separate this object to reflect this rule. And if we
23
+ have to, how to name the other PGN object?
24
+ """
25
+
26
+ class PGN:
27
+ FEFF_MULTI_PG = 9472 # 2500
28
+ FD_TP_CM = 19712 # 4D00
29
+ FD_TP_DT = 19968 # 4E00
30
+
31
+ REQUEST = 59904 # EA00
32
+ #ACKNOWLEDGEMENT = 59392
33
+ ADDRESSCLAIM = 60928 # EE00
34
+ DATATRANSFER = 60160 # EB00
35
+ TP_CM = 60416 # EC00
36
+ #COMMANDED_ADDRESS = 65240
37
+ #PROPRIETARY_A = 61184
38
+ #SOFTWARE_IDENT = 65242
39
+ # Diagnostic messages
40
+ DM01 = 65226 # FECA
41
+ DM02 = 65227 # FECB
42
+ DM03 = 65228 # FECC
43
+ DM04 = 65229 # FECD
44
+ DM05 = 65230 # FECE
45
+ DM06 = 65231 # FECF
46
+ DM07 = 58112 # E300
47
+ DM08 = 65232 # FED0
48
+ DM10 = 65234 # FED2
49
+ DM11 = 65235 # FED3
50
+ DM12 = 65236 # FED4
51
+ DM13 = 57088 # DF00
52
+ DM14 = 55552 # D900
53
+ DM15 = 55296 # D800
54
+ DM16 = 55040 # D700
55
+ DM17 = 54784 # D600
56
+ DM18 = 54272 # D400
57
+ DM19 = 54016 # D300
58
+ DM20 = 49664 # C200
59
+ DM21 = 49408 # C100
60
+ DM22 = 49920 # C300
61
+ DM23 = 64949 # FDB5
62
+ DM24 = 64950 # FDB6
63
+ DM25 = 64951 # FDB7
64
+ DM26 = 64952 # FDB8
65
+ DM27 = 64898 # FD82
66
+ DM28 = 64896 # FD80
67
+ DM29 = 40448 # 9E00
68
+ DM30 = 41984 # A400
69
+ DM31 = 41728 # A300
70
+ DM32 = 41472 # A200
71
+ DM33 = 41216 # A100
72
+ DM34 = 40960 # A000
73
+ DM35 = 40704 # 9F00
74
+ DM36 = 64868 # FD64
75
+ DM37 = 64867 # FD63
76
+ DM38 = 64866 # FD62
77
+ DM39 = 64865 # FD61
78
+ DM40 = 64864 # FD60
79
+ DM41 = 64863 # FD5F
80
+ DM42 = 64862 # FD5E
81
+ DM43 = 64861 # FD5D
82
+ DM44 = 64860 # FD5C
83
+ DM45 = 64859 # FD5B
84
+ DM46 = 64858 # FD5A
85
+ DM47 = 64857 # FD59
86
+ DM48 = 64856 # FD58
87
+ DM49 = 64855 # FD57
88
+ DM50 = 64854 # FD56
89
+ DM51 = 64853 # FD55
90
+ DM52 = 64852 # FD54
91
+ DM53 = 64721 # FCD1
92
+ DM54 = 64722 # FCD2
93
+ DM55 = 64723 # FCD3
94
+ DM56 = 64711 # FCC7
95
+ DM57 = 64710 # FCC6
96
+
97
+ class Address:
98
+ NULL = 254
99
+ GLOBAL = 255
100
+
101
+ def __init__(self, data_page=0, pdu_format=0, pdu_specific=0):
102
+ """
103
+ :param data_page:
104
+ 1-bit Data Page
105
+ :param pdu_format:
106
+ 8-bit PDU Format
107
+ :param pdu_specific:
108
+ 8-bit PDU Specific
109
+ """
110
+ self.data_page = data_page & 0x01
111
+ self.pdu_format = pdu_format & 0xFF
112
+ self.pdu_specific = pdu_specific & 0xFF
113
+
114
+ @property
115
+ def is_pdu1_format(self):
116
+ """Indicates Peer-to-Peer communication"""
117
+ return True if self.pdu_format>=0 and self.pdu_format<=239 else False
118
+
119
+ @property
120
+ def is_pdu2_format(self):
121
+ """Indicates broadcast communication"""
122
+ return True if self.pdu_format>=240 and self.pdu_format<=255 else False
123
+
124
+ def from_message_id(self, mid):
125
+ """Fills in the object from a MessageId given"""
126
+ if not isinstance(mid, j1939.MessageId):
127
+ raise ValueError("the parameter mid must be an instance of MessageId")
128
+
129
+ self.data_page = (mid.parameter_group_number >> 16) & 0x01
130
+ self.pdu_format = (mid.parameter_group_number >> 8) & 0xFF
131
+ self.pdu_specific = mid.parameter_group_number & 0xFF
132
+
133
+ @property
134
+ def value(self):
135
+ """Returns the value of the PGN"""
136
+ return (self.data_page << 16) | (self.pdu_format << 8) | self.pdu_specific
j1939/version.py ADDED
@@ -0,0 +1 @@
1
+ __version__ = "0.1.0"