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...")
import gzip
import shutil
import os
FILES=['web/index.html']
def compressFile(inFile):
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 gzip.open(outfile, 'wb') as f_out:
shutil.copyfileobj(f_in, f_out)

View File

@ -12,9 +12,11 @@
#include "N2kDataToNMEA0183.h"
#include <map>
#include "NMEA0183AISMessages.h"
#include "NMEA0183AISMsg.h"
class N2kToNMEA0183Functions : public N2kDataToNMEA0183
{
typedef void (N2kToNMEA0183Functions::*N2KConverter)(const tN2kMsg &N2kMsg);
private:
static const unsigned long RMCPeriod = 500;
static void setMax(GwBoatItem<double> *maxItem, GwBoatItem<double> *item)
@ -91,40 +93,45 @@ private:
unsigned long LastPosSend;
unsigned long NextRMCSend;
unsigned long lastLoopTime;
class ConverterEntry{
public:
unsigned long count=0;
N2KConverter converter;
ConverterEntry(N2KConverter cv=NULL){converter=cv;}
class ConverterEntry
{
public:
unsigned long count = 0;
N2KConverter converter;
ConverterEntry(N2KConverter cv = NULL) { converter = cv; }
};
typedef std::map<long,ConverterEntry> ConverterMap;
typedef std::map<long, ConverterEntry> ConverterMap;
ConverterMap converters;
/**
* register a n2k message converter
* 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);
converters[pgn]=e;
converters[pgn] = e;
}
virtual const unsigned long * handledPgns(){
logger->logString("CONV: # %d handled PGNS",(int)converters.size());
unsigned long *rt=new unsigned long[converters.size()+1];
int idx=0;
for (ConverterMap::iterator it=converters.begin();
it != converters.end();it++){
rt[idx]=it->first;
virtual const unsigned long *handledPgns()
{
logger->logString("CONV: # %d handled PGNS", (int)converters.size());
unsigned long *rt = new unsigned long[converters.size() + 1];
int idx = 0;
for (ConverterMap::iterator it = converters.begin();
it != converters.end(); it++)
{
rt[idx] = it->first;
idx++;
}
rt[idx]=0;
rt[idx] = 0;
return rt;
}
virtual void HandleMsg(const tN2kMsg &N2kMsg)
{
ConverterMap::iterator it;
it = converters.find(N2kMsg.PGN);
if (it != converters.end()){
if (it != converters.end())
{
//logger->logString("CONV: handle PGN %ld",N2kMsg.PGN);
(it->second).count++;
//call to member function - see e.g. https://isocpp.org/wiki/faq/pointers-to-members
@ -132,12 +139,15 @@ private:
return;
}
}
virtual void toJson(JsonDocument &json){
for (ConverterMap::iterator it=converters.begin();it != converters.end();it++){
json["cnv"][String(it->first)]=it->second.count;
virtual void toJson(JsonDocument &json)
{
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();
}
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:
N2kToNMEA0183Functions(GwLog *logger, GwBoatData *boatData, tNMEA2000 *NMEA2000, tNMEA0183 *NMEA0183) : N2kDataToNMEA0183(logger, boatData, NMEA2000, NMEA0183)
{
@ -516,17 +885,23 @@ public:
//and register it here
//with this approach we easily have a list of all handled
//pgns
registerConverter(127250UL,&N2kToNMEA0183Functions::HandleHeading);
registerConverter(127258UL,&N2kToNMEA0183Functions::HandleVariation);
registerConverter(128259UL,&N2kToNMEA0183Functions::HandleBoatSpeed);
registerConverter(128267UL,&N2kToNMEA0183Functions::HandleDepth);
registerConverter(129025UL,&N2kToNMEA0183Functions::HandlePosition);
registerConverter(129026UL,&N2kToNMEA0183Functions::HandleCOGSOG);
registerConverter(129029UL,&N2kToNMEA0183Functions::HandleGNSS);
registerConverter(130306UL,&N2kToNMEA0183Functions::HandleWind);
registerConverter(128275UL,&N2kToNMEA0183Functions::HandleLog);
registerConverter(127245UL,&N2kToNMEA0183Functions::HandleRudder);
registerConverter(130310UL,&N2kToNMEA0183Functions::HandleWaterTemp);
registerConverter(127250UL, &N2kToNMEA0183Functions::HandleHeading);
registerConverter(127258UL, &N2kToNMEA0183Functions::HandleVariation);
registerConverter(128259UL, &N2kToNMEA0183Functions::HandleBoatSpeed);
registerConverter(128267UL, &N2kToNMEA0183Functions::HandleDepth);
registerConverter(129025UL, &N2kToNMEA0183Functions::HandlePosition);
registerConverter(129026UL, &N2kToNMEA0183Functions::HandleCOGSOG);
registerConverter(129029UL, &N2kToNMEA0183Functions::HandleGNSS);
registerConverter(130306UL, &N2kToNMEA0183Functions::HandleWind);
registerConverter(128275UL, &N2kToNMEA0183Functions::HandleLog);
registerConverter(127245UL, &N2kToNMEA0183Functions::HandleRudder);
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()
{

View File

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