include ais conversion

This commit is contained in:
andreas 2021-10-22 13:08:25 +02:00
parent c63a9bb689
commit 35ff689cd9
3 changed files with 415 additions and 33 deletions

View File

@ -1,10 +1,17 @@
print("running extra...") print("running extra...")
import gzip import gzip
import shutil import shutil
import os
FILES=['web/index.html'] FILES=['web/index.html']
def compressFile(inFile): def compressFile(inFile):
outfile=inFile+".gz" outfile=inFile+".gz"
if os.path.exists(outfile):
otime=os.path.getmtime(outfile)
itime=os.path.getmtime(inFile)
if (otime >= itime):
print("%s is newer then %s, no need to recreate"%(outfile,inFile))
return
with open(inFile, 'rb') as f_in: with open(inFile, 'rb') as f_in:
with gzip.open(outfile, 'wb') as f_out: with gzip.open(outfile, 'wb') as f_out:
shutil.copyfileobj(f_in, f_out) shutil.copyfileobj(f_in, f_out)

View File

@ -12,9 +12,11 @@
#include "N2kDataToNMEA0183.h" #include "N2kDataToNMEA0183.h"
#include <map> #include <map>
#include "NMEA0183AISMessages.h" #include "NMEA0183AISMessages.h"
#include "NMEA0183AISMsg.h"
class N2kToNMEA0183Functions : public N2kDataToNMEA0183 class N2kToNMEA0183Functions : public N2kDataToNMEA0183
{ {
typedef void (N2kToNMEA0183Functions::*N2KConverter)(const tN2kMsg &N2kMsg); typedef void (N2kToNMEA0183Functions::*N2KConverter)(const tN2kMsg &N2kMsg);
private: private:
static const unsigned long RMCPeriod = 500; static const unsigned long RMCPeriod = 500;
static void setMax(GwBoatItem<double> *maxItem, GwBoatItem<double> *item) static void setMax(GwBoatItem<double> *maxItem, GwBoatItem<double> *item)
@ -91,40 +93,45 @@ private:
unsigned long LastPosSend; unsigned long LastPosSend;
unsigned long NextRMCSend; unsigned long NextRMCSend;
unsigned long lastLoopTime; unsigned long lastLoopTime;
class ConverterEntry{ class ConverterEntry
public: {
unsigned long count=0; public:
N2KConverter converter; unsigned long count = 0;
ConverterEntry(N2KConverter cv=NULL){converter=cv;} N2KConverter converter;
ConverterEntry(N2KConverter cv = NULL) { converter = cv; }
}; };
typedef std::map<long,ConverterEntry> ConverterMap; typedef std::map<long, ConverterEntry> ConverterMap;
ConverterMap converters; ConverterMap converters;
/** /**
* register a n2k message converter * register a n2k message converter
* each of the converter functions must be registered in the constructor * each of the converter functions must be registered in the constructor
**/ **/
void registerConverter(long pgn,N2KConverter converter){ void registerConverter(long pgn, N2KConverter converter)
{
ConverterEntry e(converter); ConverterEntry e(converter);
converters[pgn]=e; converters[pgn] = e;
} }
virtual const unsigned long * handledPgns(){ virtual const unsigned long *handledPgns()
logger->logString("CONV: # %d handled PGNS",(int)converters.size()); {
unsigned long *rt=new unsigned long[converters.size()+1]; logger->logString("CONV: # %d handled PGNS", (int)converters.size());
int idx=0; unsigned long *rt = new unsigned long[converters.size() + 1];
for (ConverterMap::iterator it=converters.begin(); int idx = 0;
it != converters.end();it++){ for (ConverterMap::iterator it = converters.begin();
rt[idx]=it->first; it != converters.end(); it++)
{
rt[idx] = it->first;
idx++; idx++;
} }
rt[idx]=0; rt[idx] = 0;
return rt; return rt;
} }
virtual void HandleMsg(const tN2kMsg &N2kMsg) virtual void HandleMsg(const tN2kMsg &N2kMsg)
{ {
ConverterMap::iterator it; ConverterMap::iterator it;
it = converters.find(N2kMsg.PGN); it = converters.find(N2kMsg.PGN);
if (it != converters.end()){ if (it != converters.end())
{
//logger->logString("CONV: handle PGN %ld",N2kMsg.PGN); //logger->logString("CONV: handle PGN %ld",N2kMsg.PGN);
(it->second).count++; (it->second).count++;
//call to member function - see e.g. https://isocpp.org/wiki/faq/pointers-to-members //call to member function - see e.g. https://isocpp.org/wiki/faq/pointers-to-members
@ -132,12 +139,15 @@ private:
return; return;
} }
} }
virtual void toJson(JsonDocument &json){ virtual void toJson(JsonDocument &json)
for (ConverterMap::iterator it=converters.begin();it != converters.end();it++){ {
json["cnv"][String(it->first)]=it->second.count; for (ConverterMap::iterator it = converters.begin(); it != converters.end(); it++)
{
json["cnv"][String(it->first)] = it->second.count;
} }
} }
virtual int numPgns(){ virtual int numPgns()
{
return converters.size(); return converters.size();
} }
void SetNextRMCSend() { NextRMCSend = millis() + RMCPeriod; } void SetNextRMCSend() { NextRMCSend = millis() + RMCPeriod; }
@ -479,6 +489,365 @@ private:
} }
} }
//*****************************************************************************
// 129038 AIS Class A Position Report (Message 1, 2, 3)
void HandleAISClassAPosReport(const tN2kMsg &N2kMsg)
{
unsigned char SID;
tN2kAISRepeat _Repeat;
uint32_t _UserID; // MMSI
double _Latitude;
double _Longitude;
bool _Accuracy;
bool _RAIM;
uint8_t _Seconds;
double _COG;
double _SOG;
double _Heading;
double _ROT;
tN2kAISNavStatus _NavStatus;
uint8_t _MessageType = 1;
tNMEA0183AISMsg NMEA0183AISMsg;
if (ParseN2kPGN129038(N2kMsg, SID, _Repeat, _UserID, _Latitude, _Longitude, _Accuracy, _RAIM, _Seconds,
_COG, _SOG, _Heading, _ROT, _NavStatus))
{
// Debug
#ifdef SERIAL_PRINT_AIS_FIELDS
Serial.println(" Msg 1 ");
const double pi = 3.1415926535897932384626433832795;
const double radToDeg = 180.0 / pi;
const double msTokn = 3600.0 / 1852.0;
const double radsToDegMin = 60 * 360.0 / (2 * pi); // [rad/s -> degree/minute]
Serial.print("Repeat: ");
Serial.println(_Repeat);
Serial.print("UserID: ");
Serial.println(_UserID);
Serial.print("Latitude: ");
Serial.println(_Latitude);
Serial.print("Longitude: ");
Serial.println(_Longitude);
Serial.print("Accuracy: ");
Serial.println(_Accuracy);
Serial.print("RAIM: ");
Serial.println(_RAIM);
Serial.print("Seconds: ");
Serial.println(_Seconds);
Serial.print("COG: ");
Serial.println(_COG * radToDeg);
Serial.print("SOG: ");
Serial.println(_SOG * msTokn);
Serial.print("Heading: ");
Serial.println(_Heading * radToDeg);
Serial.print("ROT: ");
Serial.println(_ROT * radsToDegMin);
Serial.print("NavStatus: ");
Serial.println(_NavStatus);
#endif
if (SetAISClassABMessage1(NMEA0183AISMsg, _MessageType, _Repeat, _UserID, _Latitude, _Longitude, _Accuracy,
_RAIM, _Seconds, _COG, _SOG, _Heading, _ROT, _NavStatus))
{
SendMessage(NMEA0183AISMsg);
#ifdef SERIAL_PRINT_AIS_NMEA
// Debug Print AIS-NMEA
Serial.print(NMEA0183AISMsg.GetPrefix());
Serial.print(NMEA0183AISMsg.Sender());
Serial.print(NMEA0183AISMsg.MessageCode());
for (int i = 0; i < NMEA0183AISMsg.FieldCount(); i++)
{
Serial.print(",");
Serial.print(NMEA0183AISMsg.Field(i));
}
char buf[7];
sprintf(buf, "*%02X\r\n", NMEA0183AISMsg.GetCheckSum());
Serial.print(buf);
#endif
}
}
} // end 129038 AIS Class A Position Report Message 1/3
//*****************************************************************************
// 129039 AIS Class B Position Report -> AIS Message Type 5: Static and Voyage Related Data
void HandleAISClassAMessage5(const tN2kMsg &N2kMsg)
{
uint8_t _MessageID;
tN2kAISRepeat _Repeat;
uint32_t _UserID; // MMSI
uint32_t _IMONumber;
char _Callsign[8];
char _Name[21];
uint8_t _VesselType;
double _Length;
double _Beam;
double _PosRefStbd;
double _PosRefBow;
uint16_t _ETAdate;
double _ETAtime;
double _Draught;
char _Destination[21];
tN2kAISVersion _AISversion;
tN2kGNSStype _GNSStype;
tN2kAISTranceiverInfo _AISinfo;
tN2kAISDTE _DTE;
tNMEA0183AISMsg NMEA0183AISMsg;
if (ParseN2kPGN129794(N2kMsg, _MessageID, _Repeat, _UserID, _IMONumber, _Callsign, _Name, _VesselType,
_Length, _Beam, _PosRefStbd, _PosRefBow, _ETAdate, _ETAtime, _Draught, _Destination,
_AISversion, _GNSStype, _DTE, _AISinfo))
{
#ifdef SERIAL_PRINT_AIS_FIELDS
// Debug Print N2k Values
Serial.println(" Msg 5 ");
Serial.print("MessageID: ");
Serial.println(_MessageID);
Serial.print("Repeat: ");
Serial.println(_Repeat);
Serial.print("UserID: ");
Serial.println(_UserID);
Serial.print("IMONumber: ");
Serial.println(_IMONumber);
Serial.print("Callsign: ");
Serial.println(_Callsign);
Serial.print("VesselType: ");
Serial.println(_VesselType);
Serial.print("Name: ");
Serial.println(_Name);
Serial.print("Length: ");
Serial.println(_Length);
Serial.print("Beam: ");
Serial.println(_Beam);
Serial.print("PosRefStbd: ");
Serial.println(_PosRefStbd);
Serial.print("PosRefBow: ");
Serial.println(_PosRefBow);
Serial.print("ETAdate: ");
Serial.println(_ETAdate);
Serial.print("ETAtime: ");
Serial.println(_ETAtime);
Serial.print("Draught: ");
Serial.println(_Draught);
Serial.print("Destination: ");
Serial.println(_Destination);
Serial.print("GNSStype: ");
Serial.println(_GNSStype);
Serial.print("DTE: ");
Serial.println(_DTE);
Serial.println(" Msg 5 ");
#endif
if (SetAISClassAMessage5(NMEA0183AISMsg, _MessageID, _Repeat, _UserID, _IMONumber, _Callsign, _Name, _VesselType,
_Length, _Beam, _PosRefStbd, _PosRefBow, _ETAdate, _ETAtime, _Draught, _Destination,
_GNSStype, _DTE))
{
SendMessage(NMEA0183AISMsg.BuildMsg5Part1(NMEA0183AISMsg));
#ifdef SERIAL_PRINT_AIS_NMEA
// Debug Print AIS-NMEA Message Type 5, Part 1
char buf[7];
Serial.print(NMEA0183AISMsg.GetPrefix());
Serial.print(NMEA0183AISMsg.Sender());
Serial.print(NMEA0183AISMsg.MessageCode());
for (int i = 0; i < NMEA0183AISMsg.FieldCount(); i++)
{
Serial.print(",");
Serial.print(NMEA0183AISMsg.Field(i));
}
sprintf(buf, "*%02X\r\n", NMEA0183AISMsg.GetCheckSum());
Serial.print(buf);
#endif
SendMessage(NMEA0183AISMsg.BuildMsg5Part2(NMEA0183AISMsg));
#ifdef SERIAL_PRINT_AIS_NMEA
// Print AIS-NMEA Message Type 5, Part 2
Serial.print(NMEA0183AISMsg.GetPrefix());
Serial.print(NMEA0183AISMsg.Sender());
Serial.print(NMEA0183AISMsg.MessageCode());
for (int i = 0; i < NMEA0183AISMsg.FieldCount(); i++)
{
Serial.print(",");
Serial.print(NMEA0183AISMsg.Field(i));
}
sprintf(buf, "*%02X\r\n", NMEA0183AISMsg.GetCheckSum());
Serial.print(buf);
#endif
}
}
}
//
//*****************************************************************************
// 129039 AIS Class B Position Report (Message 18)
void HandleAISClassBMessage18(const tN2kMsg &N2kMsg)
{
uint8_t _MessageID;
tN2kAISRepeat _Repeat;
uint32_t _UserID; // MMSI
double _Latitude;
double _Longitude;
bool _Accuracy;
bool _RAIM;
uint8_t _Seconds;
double _COG;
double _SOG;
double _Heading;
tN2kAISUnit _Unit;
bool _Display, _DSC, _Band, _Msg22, _State;
tN2kAISMode _Mode;
if (ParseN2kPGN129039(N2kMsg, _MessageID, _Repeat, _UserID, _Latitude, _Longitude, _Accuracy, _RAIM,
_Seconds, _COG, _SOG, _Heading, _Unit, _Display, _DSC, _Band, _Msg22, _Mode, _State))
{
tNMEA0183AISMsg NMEA0183AISMsg;
if (SetAISClassBMessage18(NMEA0183AISMsg, _MessageID, _Repeat, _UserID, _Latitude, _Longitude, _Accuracy, _RAIM,
_Seconds, _COG, _SOG, _Heading, _Unit, _Display, _DSC, _Band, _Msg22, _Mode, _State))
{
SendMessage(NMEA0183AISMsg);
#ifdef SERIAL_PRINT_AIS_NMEA
// Debug Print AIS-NMEA
Serial.print(NMEA0183AISMsg.GetPrefix());
Serial.print(NMEA0183AISMsg.Sender());
Serial.print(NMEA0183AISMsg.MessageCode());
for (int i = 0; i < NMEA0183AISMsg.FieldCount(); i++)
{
Serial.print(",");
Serial.print(NMEA0183AISMsg.Field(i));
}
char buf[7];
sprintf(buf, "*%02X\r\n", NMEA0183AISMsg.GetCheckSum());
Serial.print(buf);
#endif
}
}
return;
}
//*****************************************************************************
// PGN 129809 AIS Class B "CS" Static Data Report, Part A
void HandleAISClassBMessage24A(const tN2kMsg &N2kMsg)
{
uint8_t _MessageID;
tN2kAISRepeat _Repeat;
uint32_t _UserID; // MMSI
char _Name[21];
if (ParseN2kPGN129809(N2kMsg, _MessageID, _Repeat, _UserID, _Name))
{
tNMEA0183AISMsg NMEA0183AISMsg;
if (SetAISClassBMessage24PartA(NMEA0183AISMsg, _MessageID, _Repeat, _UserID, _Name))
{
}
}
return;
}
//*****************************************************************************
// PGN 129810 AIS Class B "CS" Static Data Report, Part B -> AIS Message 24 (2 Parts)
void HandleAISClassBMessage24B(const tN2kMsg &N2kMsg)
{
uint8_t _MessageID;
tN2kAISRepeat _Repeat;
uint32_t _UserID, _MothershipID; // MMSI
char _Callsign[8];
char _Vendor[4];
uint8_t _VesselType;
double _Length;
double _Beam;
double _PosRefStbd;
double _PosRefBow;
if (ParseN2kPGN129810(N2kMsg, _MessageID, _Repeat, _UserID, _VesselType, _Vendor, _Callsign,
_Length, _Beam, _PosRefStbd, _PosRefBow, _MothershipID))
{
//
#ifdef SERIAL_PRINT_AIS_FIELDS
// Debug Print N2k Values
Serial.println(" Msg 24 ");
Serial.print("MessageID: ");
Serial.println(_MessageID);
Serial.print("Repeat: ");
Serial.println(_Repeat);
Serial.print("UserID: ");
Serial.println(_UserID);
Serial.print("VesselType: ");
Serial.println(_VesselType);
Serial.print("Vendor: ");
Serial.println(_Vendor);
Serial.print("Callsign: ");
Serial.println(_Callsign);
Serial.print("Length: ");
Serial.println(_Length);
Serial.print("Beam: ");
Serial.println(_Beam);
Serial.print("PosRefStbd: ");
Serial.println(_PosRefStbd);
Serial.print("PosRefBow: ");
Serial.println(_PosRefBow);
Serial.print("MothershipID: ");
Serial.println(_MothershipID);
Serial.println(" Msg 24 ");
#endif
tNMEA0183AISMsg NMEA0183AISMsg;
if (SetAISClassBMessage24(NMEA0183AISMsg, _MessageID, _Repeat, _UserID, _VesselType, _Vendor, _Callsign,
_Length, _Beam, _PosRefStbd, _PosRefBow, _MothershipID))
{
SendMessage(NMEA0183AISMsg.BuildMsg24PartA(NMEA0183AISMsg));
#ifdef SERIAL_PRINT_AIS_NMEA
// Debug Print AIS-NMEA
char buf[7];
Serial.print(NMEA0183AISMsg.GetPrefix());
Serial.print(NMEA0183AISMsg.Sender());
Serial.print(NMEA0183AISMsg.MessageCode());
for (int i = 0; i < NMEA0183AISMsg.FieldCount(); i++)
{
Serial.print(",");
Serial.print(NMEA0183AISMsg.Field(i));
}
sprintf(buf, "*%02X\r\n", NMEA0183AISMsg.GetCheckSum());
Serial.print(buf);
#endif
SendMessage(NMEA0183AISMsg.BuildMsg24PartB(NMEA0183AISMsg));
#ifdef SERIAL_PRINT_AIS_NMEA
Serial.print(NMEA0183AISMsg.GetPrefix());
Serial.print(NMEA0183AISMsg.Sender());
Serial.print(NMEA0183AISMsg.MessageCode());
for (int i = 0; i < NMEA0183AISMsg.FieldCount(); i++)
{
Serial.print(",");
Serial.print(NMEA0183AISMsg.Field(i));
}
sprintf(buf, "*%02X\r\n", NMEA0183AISMsg.GetCheckSum());
Serial.print(buf);
#endif
}
}
return;
}
public: public:
N2kToNMEA0183Functions(GwLog *logger, GwBoatData *boatData, tNMEA2000 *NMEA2000, tNMEA0183 *NMEA0183) : N2kDataToNMEA0183(logger, boatData, NMEA2000, NMEA0183) N2kToNMEA0183Functions(GwLog *logger, GwBoatData *boatData, tNMEA2000 *NMEA2000, tNMEA0183 *NMEA0183) : N2kDataToNMEA0183(logger, boatData, NMEA2000, NMEA0183)
{ {
@ -516,17 +885,23 @@ public:
//and register it here //and register it here
//with this approach we easily have a list of all handled //with this approach we easily have a list of all handled
//pgns //pgns
registerConverter(127250UL,&N2kToNMEA0183Functions::HandleHeading); registerConverter(127250UL, &N2kToNMEA0183Functions::HandleHeading);
registerConverter(127258UL,&N2kToNMEA0183Functions::HandleVariation); registerConverter(127258UL, &N2kToNMEA0183Functions::HandleVariation);
registerConverter(128259UL,&N2kToNMEA0183Functions::HandleBoatSpeed); registerConverter(128259UL, &N2kToNMEA0183Functions::HandleBoatSpeed);
registerConverter(128267UL,&N2kToNMEA0183Functions::HandleDepth); registerConverter(128267UL, &N2kToNMEA0183Functions::HandleDepth);
registerConverter(129025UL,&N2kToNMEA0183Functions::HandlePosition); registerConverter(129025UL, &N2kToNMEA0183Functions::HandlePosition);
registerConverter(129026UL,&N2kToNMEA0183Functions::HandleCOGSOG); registerConverter(129026UL, &N2kToNMEA0183Functions::HandleCOGSOG);
registerConverter(129029UL,&N2kToNMEA0183Functions::HandleGNSS); registerConverter(129029UL, &N2kToNMEA0183Functions::HandleGNSS);
registerConverter(130306UL,&N2kToNMEA0183Functions::HandleWind); registerConverter(130306UL, &N2kToNMEA0183Functions::HandleWind);
registerConverter(128275UL,&N2kToNMEA0183Functions::HandleLog); registerConverter(128275UL, &N2kToNMEA0183Functions::HandleLog);
registerConverter(127245UL,&N2kToNMEA0183Functions::HandleRudder); registerConverter(127245UL, &N2kToNMEA0183Functions::HandleRudder);
registerConverter(130310UL,&N2kToNMEA0183Functions::HandleWaterTemp); registerConverter(130310UL, &N2kToNMEA0183Functions::HandleWaterTemp);
registerConverter(129038UL, &N2kToNMEA0183Functions::HandleAISClassAPosReport); // AIS Class A Position Report, Message Type 1
registerConverter(129039UL, &N2kToNMEA0183Functions::HandleAISClassBMessage18); // AIS Class B Position Report, Message Type 18
registerConverter(129794UL, &N2kToNMEA0183Functions::HandleAISClassAMessage5); // AIS Class A Ship Static and Voyage related data, Message Type 5
registerConverter(129809UL, &N2kToNMEA0183Functions::HandleAISClassBMessage24A); // AIS Class B "CS" Static Data Report, Part A
registerConverter(129810UL, &N2kToNMEA0183Functions::HandleAISClassBMessage24B); // AIS Class B "CS" Static Data Report, Part B
} }
virtual void loop() virtual void loop()
{ {

View File

@ -102,7 +102,7 @@ void js_reset() // Wenn "http://<ip address>/gauge.min.js" aufgerufen wurde
void js_status(){ void js_status(){
int numPgns=nmea0183Converter->numPgns(); int numPgns=nmea0183Converter->numPgns();
DynamicJsonDocument status(256*numPgns*30); DynamicJsonDocument status(256+numPgns*50);
status["numcan"]=numCan; status["numcan"]=numCan;
status["version"]=VERSION; status["version"]=VERSION;
status["wifiConnected"]=gwWifi.clientConnected(); status["wifiConnected"]=gwWifi.clientConnected();