NMEA2000 Library  0.1
Library to handle NMEA 2000 Communication written in C++
N2kDeviceList.cpp
Go to the documentation of this file.
1/*
2N2kDeviceList.cpp
3
4Copyright (c) 2015-2024 Timo Lappalainen, Kave Oy, www.kave.fi
5
6Permission is hereby granted, free of charge, to any person obtaining a copy of
7this software and associated documentation files (the "Software"), to deal in
8the Software without restriction, including without limitation the rights to use,
9copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
10Software, and to permit persons to whom the Software is furnished to do so,
11subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
17INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
18PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
20CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
21OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
23*/
24
25#include <stdlib.h>
26#include "N2kDeviceList.h"
27
28//#define N2kDeviceList_HANDLE_IN_DEBUG
29
30#if defined(N2kDeviceList_HANDLE_IN_DEBUG)
31#define DebugStream Serial
32# define N2kHandleInDbg(fmt, args...) DebugStream.print (fmt , ## args)
33# define N2kHandleInDbgln(fmt, args...) DebugStream.println (fmt , ## args)
34#else
35# define N2kHandleInDbg(fmt, args...)
36# define N2kHandleInDbgln(fmt, args...)
37#endif
38
39//*****************************************************************************
40tN2kDeviceList::tN2kDeviceList(tNMEA2000 *_pNMEA2000) : tNMEA2000::tMsgHandler(0,_pNMEA2000) {
41 for (uint8_t i=0; i<N2kMaxBusDevices; i++) Sources[i]=0;
42 MaxDevices=0;
43 ListUpdated=false;
45}
46
47//*****************************************************************************
49 if ( Source>=N2kMaxBusDevices ) return 0;
50
51 return Sources[Source];
52}
53
54//*****************************************************************************
56 tInternalDevice *result=0;
57
58 for (uint8_t i=0; i<MaxDevices && result==0; i++) {
59 if ( Sources[i]!=0 && Sources[i]->IsSame(Name) ) result=Sources[i];
60 }
61
62 return result;
63}
64
65//*****************************************************************************
66tN2kDeviceList::tInternalDevice * tN2kDeviceList::LocalFindDeviceByIDs(uint16_t ManufacturerCode, uint32_t UniqueNumber) const {
67 tInternalDevice *result=0;
68
69 if ( ManufacturerCode==N2kUInt16NA && UniqueNumber==N2kUInt32NA ) return result;
70
71 for (uint8_t i=0; i<MaxDevices && result==0; i++) {
72 if ( Sources[i]!=0 &&
73 (ManufacturerCode==N2kUInt16NA || Sources[i]->GetManufacturerCode()==ManufacturerCode) &&
74 (UniqueNumber==N2kUInt32NA || Sources[i]->GetUniqueNumber()==UniqueNumber) ) result=Sources[i];
75 }
76
77 return result;
78}
79
80//*****************************************************************************
81tN2kDeviceList::tInternalDevice * tN2kDeviceList::LocalFindDeviceByProduct(uint16_t ManufacturerCode, uint16_t ProductCode, uint8_t Source) const {
82 tInternalDevice *result=0;
83
84 if ( Source<MaxDevices ) { Source++; } else { Source=0; }
85
86 if ( ManufacturerCode==N2kUInt16NA || ProductCode==N2kUInt16NA ) return result;
87
88 for (uint8_t i=Source; i<MaxDevices && result==0; i++) {
89 if ( Sources[i]!=0 &&
90 Sources[i]->GetManufacturerCode()==ManufacturerCode &&
91 Sources[i]->GetProductCode()==ProductCode ) result=Sources[i];
92 }
93
94 return result;
95}
96
97//*****************************************************************************
99 tN2kMsg N2kMsg;
100
102 return GetNMEA2000()->SendMsg(N2kMsg);
103}
104
105//*****************************************************************************
107 tN2kMsg N2kMsg;
108
110 return GetNMEA2000()->SendMsg(N2kMsg);
111}
112
113//*****************************************************************************
115 tN2kMsg N2kMsg;
116
117 SetN2kPGNISORequest(N2kMsg,Source,126464L);
118 return GetNMEA2000()->SendMsg(N2kMsg);
119}
120
121//*****************************************************************************
123 tN2kMsg N2kMsg;
124
126 return GetNMEA2000()->SendMsg(N2kMsg);
127}
128
129//*****************************************************************************
131 if ( N2kMsg.Source>=N2kMaxBusDevices ) return;
132
133 if ( Sources[N2kMsg.Source]==0 ) {
134 switch ( N2kMsg.PGN ) {
135 case N2kPGNIsoAddressClaim:break; // fall to default handler
138 case 126464L: AddDevice(N2kMsg.Source); break; // Create device and fall to default handler
139 default: AddDevice(N2kMsg.Source); return;
140 }
141 }
142
143 switch ( N2kMsg.PGN ) {
144 case N2kPGNIsoAddressClaim: HandleIsoAddressClaim(N2kMsg); break;
147 case 126464L: HandleSupportedPGNList(N2kMsg); break;
148 default: HandleOther(N2kMsg);
149 }
150
151 if ( Sources[N2kMsg.Source]!=0 ) {
152 // If device has been off and appears again and we still do not have name,
153 // start request sequence again
154 if ( Sources[N2kMsg.Source]->GetName()==0 &&
155 Sources[N2kMsg.Source]->nNameRequested>0 &&
156 N2kHasElapsed(Sources[N2kMsg.Source]->LastMessageTime,60000) ) {
157 Sources[N2kMsg.Source]->nNameRequested=0;
159 }
161 }
162}
163
164//*****************************************************************************
166 if ( N2kMsg.Source>=N2kMaxBusDevices ) return;
167
168// N2kHandleInDbg(N2kMillis()); N2kHandleInDbg(" PGN: "); N2kHandleInDbgln(N2kMsg.PGN);
169
170 if ( !HasPendingRequests ) return;
171
172 HasPendingRequests=false;
173
174 // Require name for every device.
175 if ( Sources[N2kMsg.Source]->ShouldRequestName() && RequestIsoAddressClaim(N2kMsg.Source) ) {
178 }
179
180 // First we try to request product information for all devices
181 for ( int i=0; i<MaxDevices; i++) {
182 if ( Sources[i]!=0 ) {
183 // Test do we need product information for this device
184 if ( Sources[i]->ReadyForRequestProductInformation() ) {
185 if ( RequestProductInformation(Sources[i]->GetSource()) ) {
186 N2kHandleInDbg(N2kMillis()); N2kHandleInDbg(" Request product information for source: "); N2kHandleInDbgln(Sources[i]->GetSource());
189 return;
190 }
191 } else {
193 }
194 }
195 }
196 if ( HasPendingRequests ) return;
197 // We come up to here, if have requested all product information
198 // Start to request configuration information for devices.
199 for ( int i=0; i<MaxDevices; i++) {
200 if ( Sources[i]!=0 ) {
201 // Test do we need product information for this device
202 if ( Sources[i]->ReadyForRequestConfigurationInformation() ) {
203 if ( RequestConfigurationInformation(Sources[i]->GetSource()) ) {
204 N2kHandleInDbg(N2kMillis()); N2kHandleInDbg(" Request configuration information for source: "); N2kHandleInDbgln(Sources[i]->GetSource());
207 return;
208 }
209 } else {
211 }
212 }
213 }
214 if ( HasPendingRequests ) return;
215
216 // Finally query supported PGN lists
217 for ( int i=0; i<MaxDevices; i++) {
218 if ( Sources[i]!=0 ) {
219 // Test do we need product information for this device
220 if ( Sources[i]->ReadyForRequestPGNList() ) {
221 if ( RequestSupportedPGNList(Sources[i]->GetSource()) ) {
222 N2kHandleInDbg(N2kMillis()); N2kHandleInDbg(" Request supported PGN lists for source: "); N2kHandleInDbgln(Sources[i]->GetSource());
225 return;
226 }
227 } else {
229 }
230 }
231 }
232}
233
234//*****************************************************************************
235void tN2kDeviceList::AddDevice(uint8_t Source){
236 if ( RequestIsoAddressClaim(Source) ) { // Request device information
237 SaveDevice(new tInternalDevice(0),Source); // We have now device on this source, so we will not do continuous query.
239 }
240}
241
242//*****************************************************************************
243void tN2kDeviceList::SaveDevice(tInternalDevice *pDevice, uint8_t Source) {
244 if ( Source>=N2kMaxBusDevices ) return;
245
246 pDevice->SetSource(Source);
247 Sources[Source]=pDevice;
248 if ( Source>=MaxDevices ) MaxDevices=Source+1;
249}
250
251//*****************************************************************************
253 if ( N2kMsg.PGN!=N2kPGNIsoAddressClaim ) return;
254
255 int Index=0;
256 uint64_t CallerName=N2kMsg.GetUInt64(Index);
257 tInternalDevice *pDevice=0;
258
259 // First check do we already have recorded caller
260 if ( N2kMsg.Source<N2kMaxBusDevices && Sources[N2kMsg.Source]!=0 ) {
261 pDevice=Sources[N2kMsg.Source];
262 N2kHandleInDbg("ISO address claim. Caller:"); N2kHandleInDbg((uint32_t)CallerName); N2kHandleInDbg(", uniq:" ); N2kHandleInDbgln(pDevice->GetUniqueNumber());
263 if ( pDevice->GetName()==0 ) { // Device reservation made by HandleMsg, Name has not set yet
264 tInternalDevice *pDevice2=LocalFindDeviceByName(CallerName); // Find does this actually exist with other source
265 if ( pDevice2!=0 ) { // We have already seen that message on other address, so move it here
266 delete pDevice;
267 Sources[pDevice2->GetSource()]=0;
268 SaveDevice(pDevice2,N2kMsg.Source);
269 pDevice=pDevice2;
270 } else {
271 pDevice->SetDeviceInformation(CallerName);
272 ListUpdated=true;
273 N2kHandleInDbg("Saving name for source:"); N2kHandleInDbgln(N2kMsg.Source);
274 }
275 } else if (!pDevice->IsSame(CallerName) ) { // exists, but name does not match. So device on this source position has claimed address and this has taken its place
276 // Just move old device to some empty place
277 uint8_t i;
278 for (i=0; i<N2kMaxBusDevices && Sources[i]!=0; i++);
279 // If we found empty place, move it there.
280 if ( i<N2kMaxBusDevices ) {
281 SaveDevice(pDevice,i);
282 RequestIsoAddressClaim(0xff); // Request addresses for all nodes.
283 } else { // If not, we just delete device, since we can not do much with it. This would be extremely unexpected.
284 delete pDevice;
285 }
286 Sources[N2kMsg.Source]=0;
287 pDevice=0;
288 } else { // Name is caller -> we have device on list on its place.
289 return;
290 }
291 }
292
293 if ( pDevice==0 ) {
294 // New or changed source
295 pDevice=LocalFindDeviceByName(CallerName);
296 if ( pDevice!=0 ) { // Address changed, simply move device to new place.
297 Sources[pDevice->GetSource()]=0;
298 SaveDevice(pDevice,N2kMsg.Source);
299 N2kHandleInDbg("Source updated: "); N2kHandleInDbgln(pDevice->GetSource());
300 } else { // New device
301 pDevice=new tInternalDevice(CallerName);
302 SaveDevice(pDevice,N2kMsg.Source);
303 }
304 }
305
306 // In any address change, we request information again.
309
310 ListUpdated=true;
311}
312
313//*****************************************************************************
316// unsigned long t1=micros();
317
318 if ( N2kMsg.Source>=N2kMaxBusDevices || Sources[N2kMsg.Source]==0 ) return;
319
320 tInternalDevice *pDevice=Sources[N2kMsg.Source];
321
322 N2kHandleInDbg(" Handle product information for source: "); N2kHandleInDbgln(N2kMsg.Source);
323
324 if ( !pDevice->HasProductInformation() &&
325 ParseN2kPGN126996(N2kMsg,ProdI.N2kVersion,ProdI.ProductCode,
326 sizeof(ProdI.N2kModelID),ProdI.N2kModelID,sizeof(ProdI.N2kSwCode),ProdI.N2kSwCode,
327 sizeof(ProdI.N2kModelVersion),ProdI.N2kModelVersion,sizeof(ProdI.N2kModelSerialCode),ProdI.N2kModelSerialCode,
328 ProdI.CertificationLevel,ProdI.LoadEquivalency) ) {
329 if ( !pDevice->IsSameProductInformation(ProdI) ) {
332 ListUpdated=true;
333 }
334 }
335
336// unsigned long t2=micros();
337// if ( ListUpdated ) { Serial.print(" Updated source: "); Serial.println(N2kMsg.Source); }
338// Serial.print(" - 126996 elapsed: "); Serial.println(t2-t1);
339}
340
341//*****************************************************************************
343
344 if ( N2kMsg.Source>=N2kMaxBusDevices || Sources[N2kMsg.Source]==0 ) return;
345
346// unsigned long t1=micros();
347 size_t ManISize;
348 size_t InstDesc1Size;
349 size_t InstDesc2Size;
350
351 tInternalDevice *pDevice=Sources[N2kMsg.Source];
352
353 N2kHandleInDbg(" Handle configuration information for source: "); N2kHandleInDbgln(N2kMsg.Source);
354
355 if ( ParseN2kPGN126998(N2kMsg,ManISize,0,InstDesc1Size,0,InstDesc2Size,0) ) { // First query required size
356 pDevice->InitConfigurationInformation(ManISize,InstDesc1Size,InstDesc2Size);
357 int TotalSize=ManISize+InstDesc1Size+InstDesc2Size;
358 if ( TotalSize>0 ) {
359 ParseN2kPGN126998(N2kMsg,
360 ManISize,pDevice->GetManufacturerInformation(),
361 InstDesc1Size,pDevice->GetInstallationDescription1(),
362 InstDesc2Size,pDevice->GetInstallationDescription2());
363 }
364 ListUpdated=true;
365 }
366
367// unsigned long t2=micros();
368// if ( ListUpdated ) { Serial.print(" Updated source: "); Serial.println(N2kMsg.Source); }
369// Serial.print(" - 126996 elapsed: "); Serial.println(t2-t1);
370}
371
372//*****************************************************************************
374
375 if ( N2kMsg.Source>=N2kMaxBusDevices || Sources[N2kMsg.Source]==0 ) return;
376
377 int Index=0;
378 tN2kPGNList N2kPGNList=(tN2kPGNList)N2kMsg.GetByte(Index);
379 uint8_t PGNCount=(N2kMsg.DataLen-Index)/3;
380 tInternalDevice *pDevice=Sources[N2kMsg.Source];
381 unsigned long * PGNList=0;
382 uint8_t iPGN;
383
384 switch (N2kPGNList) {
385 case N2kpgnl_transmit:
386 PGNList=pDevice->InitTransmitPGNs(PGNCount);
387 break;
388 case N2kpgnl_receive:
389 PGNList=pDevice->InitReceivePGNs(PGNCount);
390 break;
391 }
392 if ( PGNList!=0 ) {
393 for (iPGN=0; iPGN<PGNCount; iPGN++) { PGNList[iPGN]=N2kMsg.Get3ByteUInt(Index); }
394 PGNList[iPGN]=0;
395 }
396
397 ListUpdated=true;
398}
399
400//*****************************************************************************
401uint8_t tN2kDeviceList::Count() const {
402 uint8_t ret=0;
403
404 for ( size_t i=0; i<MaxDevices; i++ ) if ( Sources[i]!=0 ) ret++;
405
406 return ret;
407}
408
409// tN2kDeviceList::tInternalDevice
410
411//*****************************************************************************
412tN2kDeviceList::tInternalDevice::tInternalDevice(uint64_t _Name, uint8_t _Source) : tNMEA2000::tDevice(_Name,_Source) {
413 ProdI.Clear(); ProdILoaded=false; ConfILoaded=false;
420}
421
422//*****************************************************************************
424 if ( ConfI!=0 ) free(ConfI);
425 if ( TransmitPGNs!=0 ) free(TransmitPGNs);
426 if ( ReceivePGNs!=0 ) free(ReceivePGNs);
427}
428
429//*****************************************************************************
430char * tN2kDeviceList::tInternalDevice::InitConfigurationInformation(size_t &_ManISize, size_t &_InstDesc1Size, size_t &_InstDesc2Size) {
431 if ( _ManISize>0 ) _ManISize++; // Reserve '/0' terminator
432 if ( _InstDesc1Size>0 ) _InstDesc1Size++; // Reserve '/0' terminator
433 if ( _InstDesc2Size>0 ) _InstDesc2Size++; // Reserve '/0' terminator
434 uint16_t _ConfISize=_ManISize+_InstDesc1Size+_InstDesc2Size;
435 if ( ConfI!=0 && ConfISize<_ConfISize ) { // We can not fit new data, so release mem.
436 free(ConfI); ConfI=0; ConfISize=0;
437 }
438 if ( ConfI==0 ) {
439 ConfISize=_ConfISize;
440 ConfI=(char*)(ConfISize>0?malloc(ConfISize):0);
441 if ( _ManISize>0 ) {
442 ManufacturerInformation=ConfI;
443 ManufacturerInformation[0]='\0';
444 } else ManufacturerInformation=0;
445 if ( _InstDesc1Size>0 ) {
446 InstallationDescription1=ConfI+_ManISize;
447 InstallationDescription1[0]='\0';
448 } else InstallationDescription1=0;
449 if ( _InstDesc2Size>0 ) {
450 InstallationDescription2=ConfI+_ManISize+_InstDesc1Size;
451 InstallationDescription2[0]='\0';
452 } else InstallationDescription2=0;
453 }
454 ConfILoaded=true;
455 return ConfI;
456}
457
458//*****************************************************************************
460 if (TransmitPGNs!=0 && TransmitPGNsSize<count ) { free(TransmitPGNs); TransmitPGNs=0; TransmitPGNsSize=0; } // Free old reservation
461 if (TransmitPGNs==0) { TransmitPGNs=(unsigned long *)malloc((count+1)*sizeof(unsigned long)); TransmitPGNsSize=count; }
462 if (TransmitPGNs!=0) TransmitPGNs[0]=0;
463 return TransmitPGNs;
464}
465
466//*****************************************************************************
468 if (ReceivePGNs!=0 && ReceivePGNsSize<count ) { free(ReceivePGNs); ReceivePGNs=0; ReceivePGNsSize=0; } // Free old reservation
469 if (ReceivePGNs==0) { ReceivePGNs=(unsigned long *)malloc((count+1)*sizeof(unsigned long)); ReceivePGNsSize=count; }
470 if (ReceivePGNs!=0) ReceivePGNs[0]=0;
471 return ReceivePGNs;
472}
#define N2kHandleInDbg(fmt, args...)
#define N2kHandleInDbgln(fmt, args...)
This File contains a.
#define N2kMaxBusDevices
Maximum allowed number of devices on the CAN BUS bus system is 254.
Definition: N2kDeviceList.h:38
const uint32_t N2kUInt32NA
Constant "Not Available" for a unsigned 32bit int value.
Definition: N2kMsg.h:61
const uint16_t N2kUInt16NA
Constant "Not Available" for a unsigned 16bit int value.
Definition: N2kMsg.h:57
uint32_t N2kMillis()
Definition: N2kTimer.cpp:48
bool N2kHasElapsed(uint32_t Start, uint32_t Elapsed, uint32_t Now=N2kMillis())
Has time elapsed since start.
Definition: N2kTimer.h:111
bool ParseN2kPGN126996(const tN2kMsg &N2kMsg, unsigned short &N2kVersion, unsigned short &ProductCode, int ModelIDSize, char *ModelID, int SwCodeSize, char *SwCode, int ModelVersionSize, char *ModelVersion, int ModelSerialCodeSize, char *ModelSerialCode, unsigned char &CertificationLevel, unsigned char &LoadEquivalency)
Parsing the content of message PGN 126996 "Product information".
Definition: NMEA2000.cpp:2788
bool ParseN2kPGN126998(const tN2kMsg &N2kMsg, size_t &ManufacturerInformationSize, char *ManufacturerInformation, size_t &InstallationDescription1Size, char *InstallationDescription1, size_t &InstallationDescription2Size, char *InstallationDescription2)
Parsing the content of message PGN 126998 "Configuration information".
Definition: NMEA2000.cpp:2873
#define N2kPGNIsoAddressClaim
PGN for an ISO Address Claim message.
Definition: NMEA2000.h:59
#define N2kPGNProductInformation
PGN for a Production Information message.
Definition: NMEA2000.h:61
#define N2kPGNConfigurationInformation
PGN for an Configuration Information message.
Definition: NMEA2000.h:63
void SetN2kPGNISORequest(tN2kMsg &N2kMsg, uint8_t Destination, unsigned long RequestedPGN)
Setting up Message "ISO request" - PGN 59904.
Definition: NMEA2000.h:3226
tN2kPGNList
Enumeration of types for PGN lists according to PGN 126464.
Definition: NMEA2000.h:3262
@ N2kpgnl_receive
Definition: NMEA2000.h:3262
@ N2kpgnl_transmit
Definition: NMEA2000.h:3262
This class represents an internal device.
Definition: N2kDeviceList.h:80
char * InstallationDescription1
Pointer to the Installation Description 1.
void ClearConfigurationInformationLoaded()
Resets the Configuration Information Loaded values of the device.
unsigned long * InitReceivePGNs(uint8_t count)
Initialize an array for received PGNs This functions frees if needed old reservation and reserves new...
bool ShouldRequestProductInformation()
Should the Device Product Information be requested As long as the device Product Information is not s...
const char * GetInstallationDescription1() const
Get the Installation Description 1 of this device.
bool ProdILoaded
Product Information has been loaded.
Definition: N2kDeviceList.h:83
const char * GetInstallationDescription2() const
Get the Installation Description 2 of this device.
void SetDeviceInformation(uint64_t _Name)
Set the Device Information.
void SetConfigurationInformationRequested()
Increments the Number of how often the Configuration Information has already been requested and store...
const char * GetManufacturerInformation() const
Get the Manufacturer Information of this device.
char * ManufacturerInformation
Pointer to the Manufacturer Information.
bool ShouldRequestName()
Should the Device Name be requested As long as the device name is not set yet and the number of reque...
unsigned long * TransmitPGNs
Transmitted PGNs.
bool HasProductInformation() const
Has the Product Information for the device already been loaded.
char * InitConfigurationInformation(size_t &_ManISize, size_t &_InstDesc1Size, size_t &_InstDesc2Size)
Initialize the Configuration Information of this device.
bool ShouldRequestPGNList()
Should the Device PGN List be requested As long as the device PGN List is not set yet and the number ...
uint8_t TransmitPGNsSize
Size of the transmitted PGN (number of bytes)
unsigned long * InitTransmitPGNs(uint8_t count)
Initialize an array for transmitted PGNs This functions frees if needed old reservation and reserves ...
uint16_t ConfISize
Size of the Config Information (number of bytes)
Definition: N2kDeviceList.h:90
bool ShouldRequestConfigurationInformation()
Should the Device Configuration Information be requested As long as the device Configuration Informat...
void ClearPGNListLoaded()
Resets the PGN List Loaded values of the device.
void SetProductInformation(const char *_ModelSerialCode, unsigned short _ProductCode=0xffff, const char *_ModelID=0, const char *_SwCode=0, const char *_ModelVersion=0, unsigned char _LoadEquivalency=0xff, unsigned short _N2kVersion=0xffff, unsigned char _CertificationLevel=0xff)
Set the Product Information of the device.
tInternalDevice(uint64_t _Name, uint8_t _Source=255)
Construct a new Internal Device object.
uint8_t ReceivePGNsSize
Size of the received PGN (number of bytes)
unsigned long LastMessageTime
Time of the last message.
~tInternalDevice()
Destroy the Internal Device object Clean up all the memory.
uint8_t nNameRequested
How many times we have requested the name.
void SetProductInformationRequested()
Increments the Number of how often the Product Information has already been requested and stores the ...
void SetSource(uint8_t _Source)
Set the Source address of the device.
bool IsSameProductInformation(tNMEA2000::tProductInformation &Other)
Compares two Product Informations.
tNMEA2000::tProductInformation ProdI
Product Information of this device.
Definition: N2kDeviceList.h:85
void ClearProductInformationLoaded()
Resets the Product Information Loaded values of the device.
char * ConfI
Pointer to the Config Information.
Definition: N2kDeviceList.h:99
bool ConfILoaded
Product Information has been loaded.
Definition: N2kDeviceList.h:88
void SetPGNListRequested()
Increments the Number of how often the PGN List has already been requested and stores the timestamp.
unsigned long * ReceivePGNs
Received PGNs.
void SetNameRequested()
Increments the Number of how often the name has already been requested.
char * InstallationDescription2
Pointer to the Installation Description 2.
void HandleProductInformation(const tN2kMsg &N2kMsg)
Handle a Product Information message - PGN 126996.
void SaveDevice(tInternalDevice *pDevice, uint8_t Source)
Saves a device to Sources.
void HandleOther(const tN2kMsg &N2kMsg)
Handles all Other messages.
void HandleSupportedPGNList(const tN2kMsg &N2kMsg)
Handle a Product Information message - PGN 126464.
uint8_t MaxDevices
Number of NMEA2000 devices stored in Sources.
bool RequestIsoAddressClaim(uint8_t Source)
Request the ISO AddressClaim for a specific device on the bus.
tN2kDeviceList::tInternalDevice * LocalFindDeviceBySource(uint8_t Source) const
Find a device in Sources by the source address.
void HandleConfigurationInformation(const tN2kMsg &N2kMsg)
Handle a Configuration Information message - PGN 126998.
bool RequestSupportedPGNList(uint8_t Source)
Request the supported PGNs of a specific device on the bus.
bool RequestProductInformation(uint8_t Source)
Request the product information of a specific device on the bus.
tInternalDevice * Sources[N2kMaxBusDevices]
List of NMEA2000 devices found on the bus.
void HandleIsoAddressClaim(const tN2kMsg &N2kMsg)
Handle ISO Address Claim Message - PGN 60928.
bool RequestConfigurationInformation(uint8_t Source)
Request the configuration information of a specific device on the bus.
uint8_t Count() const
Return number of known devices in Sources.
tN2kDeviceList::tInternalDevice * LocalFindDeviceByName(uint64_t Name) const
Find a device in Sources by the name of the device.
tN2kDeviceList::tInternalDevice * LocalFindDeviceByProduct(uint16_t ManufacturerCode, uint16_t ProductCode, uint8_t Source=0xff) const
Find a device in Sources by the manufacturer and product code.
tN2kDeviceList(tNMEA2000 *_pNMEA2000)
Constructor for the class.
tN2kDeviceList::tInternalDevice * LocalFindDeviceByIDs(uint16_t ManufacturerCode, uint32_t UniqueNumber) const
Find a device in Sources by the manufacturer code and unique ID.
void AddDevice(uint8_t Source)
Adds a device to Sources.
void HandleMsg(const tN2kMsg &N2kMsg)
Handle NMEA2000 messages.
bool HasPendingRequests
There are still requests pending.
bool ListUpdated
The list of devices has been updated.
This class contains all the data of an NMEA2000 message.
Definition: N2kMsg.h:656
unsigned char Source
Source of the NMEA2000 message.
Definition: N2kMsg.h:669
uint32_t Get3ByteUInt(int &Index, uint32_t def=0xffffffff) const
Get an unsigned integer from 3 bytes out of Data.
Definition: N2kMsg.cpp:275
unsigned char GetByte(int &Index) const
Get the value from a byte out of Data.
Definition: N2kMsg.cpp:254
uint64_t GetUInt64(int &Index, uint64_t def=0xffffffffffffffffULL) const
Get an unsigned integer from 8 bytes out of Data.
Definition: N2kMsg.cpp:289
int DataLen
Number of bytes already stored in tN2kMsg::Data of this message.
Definition: N2kMsg.h:673
unsigned long PGN
Parameter Group Number (PGN) of the NMEA2000 message.
Definition: N2kMsg.h:667
uint8_t GetSource() const
Returns the Source Address of this device.
Definition: NMEA2000.h:505
uint64_t GetName() const
Get the Name of this device.
Definition: NMEA2000.h:513
uint32_t GetUniqueNumber() const
Get the unique Number from the Device Information.
Definition: NMEA2000.h:525
bool IsSame(uint64_t Other)
Check if two devices are the same, by comparing the device name.
Definition: NMEA2000.h:520
tNMEA2000 * GetNMEA2000()
Returns the tNMEA2000 object of this handler.
Definition: NMEA2000.h:633
tNMEA2000 device class definition.
Definition: NMEA2000.h:138
bool SendMsg(const tN2kMsg &N2kMsg, int DeviceIndex=0)
Send message to the NMEA2000 bus.
Definition: NMEA2000.cpp:1450
Structure that holds all the product information.
Definition: NMEA2000.h:216
unsigned short N2kVersion
Version of NMEA2000 Standard that is supported.
Definition: NMEA2000.h:219
unsigned short ProductCode
Product Code of the device.
Definition: NMEA2000.h:221
char N2kModelID[Max_N2kModelID_len+1]
Max length of ModelID Note that we reserve one extra char for null termination
Definition: NMEA2000.h:225
unsigned char LoadEquivalency
Load Equivalency of the device A Load Equivalence Number express the amount of current that is drawn ...
Definition: NMEA2000.h:243
unsigned char CertificationLevel
Certification level of the device.
Definition: NMEA2000.h:236
char N2kModelVersion[Max_N2kModelVersion_len+1]
Max length of Model Version Note that we reserve one extra char for null termination.
Definition: NMEA2000.h:231
void Clear()
Clears out all data
Definition: NMEA2000.cpp:627
char N2kSwCode[Max_N2kSwCode_len+1]
Max length of Software Code Note that we reserve one extra char for null termination
Definition: NMEA2000.h:228
char N2kModelSerialCode[Max_N2kModelSerialCode_len+1]
Max length of Serial Code Note that we reserve one extra char for null termination.
Definition: NMEA2000.h:234