diff --git a/lib/config/GwConverterConfig.h b/lib/config/GwConverterConfig.h index a3e9c81a..546d8856 100644 --- a/lib/config/GwConverterConfig.h +++ b/lib/config/GwConverterConfig.h @@ -16,16 +16,62 @@ #define _GWCONVERTERCONFIG_H #include "GWConfig.h" +#include "N2kTypes.h" +#include + +//list of configs for the PGN 130306 wind references +static std::map windConfigs={ + {N2kWind_True_water,GwConfigDefinitions::windmtra}, + {N2kWind_Apparent,GwConfigDefinitions::windmawa}, + {N2kWind_True_boat,GwConfigDefinitions::windmgna}, + {N2kWind_Magnetic,GwConfigDefinitions::windmmgd}, + {N2kWind_True_North,GwConfigDefinitions::windmtng}, +}; class GwConverterConfig{ public: + class WindMapping{ + public: + using Wind0183Type=enum{ + AWA_AWS, + TWA_TWS, + TWD_TWS, + GWA_GWS, + GWD_GWS + }; + tN2kWindReference n2kType; + Wind0183Type nmea0183Type; + bool valid=false; + WindMapping(){} + WindMapping(const tN2kWindReference &n2k,const Wind0183Type &n183): + n2kType(n2k),nmea0183Type(n183),valid(true){} + WindMapping(const tN2kWindReference &n2k,const String &n183): + n2kType(n2k){ + if (n183 == "twa_tws"){ + nmea0183Type=TWA_TWS; + valid=true; + return; + } + if (n183 == "awa_aws"){ + nmea0183Type=AWA_AWS; + valid=true; + return; + } + if (n183 == "twd_tws"){ + nmea0183Type=TWD_TWS; + valid=true; + return; + } + } + }; int minXdrInterval=100; int starboardRudderInstance=0; int portRudderInstance=-1; //ignore int min2KInterval=50; int rmcInterval=1000; int rmcCheckTime=4000; - void init(GwConfigHandler *config){ + std::vector windMappings; + void init(GwConfigHandler *config, GwLog*logger){ minXdrInterval=config->getInt(GwConfigDefinitions::minXdrInterval,100); starboardRudderInstance=config->getInt(GwConfigDefinitions::stbRudderI,0); portRudderInstance=config->getInt(GwConfigDefinitions::portRudderI,-1); @@ -36,6 +82,29 @@ class GwConverterConfig{ rmcInterval=config->getInt(GwConfigDefinitions::sendRMCi,1000); if (rmcInterval < 0) rmcInterval=0; if (rmcInterval > 0 && rmcInterval <100) rmcInterval=100; + for (auto && it:windConfigs){ + String cfg=config->getString(it.second); + WindMapping mapping(it.first,cfg); + if (mapping.valid){ + LOG_DEBUG(GwLog::ERROR,"add wind mapping n2k=%d,nmea0183=%01d(%s)", + (int)(mapping.n2kType),(int)(mapping.nmea0183Type),cfg.c_str()); + windMappings.push_back(mapping); + } + } + } + const WindMapping findWindMapping(const tN2kWindReference &n2k) const{ + for (const auto & it:windMappings){ + if (it.n2kType == n2k) return it; + } + return WindMapping(); + } + const WindMapping findWindMapping(const WindMapping::Wind0183Type &n183) const{ + for (const auto & it:windMappings){ + if (it.nmea0183Type == n183) return it; + } + return WindMapping(); } + + }; #endif \ No newline at end of file diff --git a/lib/nmea0183ton2k/NMEA0183DataToN2K.cpp b/lib/nmea0183ton2k/NMEA0183DataToN2K.cpp index 7868eaf4..8bb92370 100644 --- a/lib/nmea0183ton2k/NMEA0183DataToN2K.cpp +++ b/lib/nmea0183ton2k/NMEA0183DataToN2K.cpp @@ -399,28 +399,29 @@ class NMEA0183DataToN2KFunctions : public NMEA0183DataToN2K return; } tN2kMsg n2kMsg; - tN2kWindReference n2kRef; bool shouldSend=false; WindAngle=formatDegToRad(WindAngle); + GwConverterConfig::WindMapping mapping; switch(Reference){ case NMEA0183Wind_Apparent: - n2kRef=N2kWind_Apparent; shouldSend=updateDouble(boatData->AWA,WindAngle,msg.sourceId) && updateDouble(boatData->AWS,WindSpeed,msg.sourceId); if (WindSpeed != NMEA0183DoubleNA) boatData->MaxAws->updateMax(WindSpeed); + mapping=config.findWindMapping(GwConverterConfig::WindMapping::AWA_AWS); break; case NMEA0183Wind_True: - n2kRef=N2kWind_True_water; shouldSend=updateDouble(boatData->TWA,WindAngle,msg.sourceId) && updateDouble(boatData->TWS,WindSpeed,msg.sourceId); if (WindSpeed != NMEA0183DoubleNA) boatData->MaxTws->updateMax(WindSpeed); + mapping=config.findWindMapping(GwConverterConfig::WindMapping::TWA_TWS); break; default: LOG_DEBUG(GwLog::DEBUG,"unknown wind reference %d in %s",(int)Reference,msg.line); } - if (shouldSend){ - SetN2kWindSpeed(n2kMsg,1,WindSpeed,WindAngle,n2kRef); - send(n2kMsg,msg.sourceId,String(n2kMsg.PGN)+String((int)n2kRef)); + //TODO: try to compute TWD and get mapping for this one + if (shouldSend && mapping.valid){ + SetN2kWindSpeed(n2kMsg,1,WindSpeed,WindAngle,mapping.n2kType); + send(n2kMsg,msg.sourceId,String(n2kMsg.PGN)+String((int)mapping.n2kType)); } } void convertVWR(const SNMEA0183Msg &msg) @@ -460,8 +461,11 @@ class NMEA0183DataToN2KFunctions : public NMEA0183DataToN2K if (WindSpeed != NMEA0183DoubleNA) boatData->MaxAws->updateMax(WindSpeed); if (shouldSend) { - SetN2kWindSpeed(n2kMsg, 1, WindSpeed, WindAngle, N2kWind_Apparent); - send(n2kMsg,msg.sourceId,String(n2kMsg.PGN)+String((int)N2kWind_Apparent)); + const GwConverterConfig::WindMapping mapping=config.findWindMapping(GwConverterConfig::WindMapping::AWA_AWS); + if (mapping.valid){ + SetN2kWindSpeed(n2kMsg, 1, WindSpeed, WindAngle, mapping.n2kType); + send(n2kMsg,msg.sourceId,String(n2kMsg.PGN)+String((int)mapping.n2kType)); + } } } @@ -504,8 +508,16 @@ class NMEA0183DataToN2KFunctions : public NMEA0183DataToN2K double twa = WindDirection-boatData->HDT->getData(); if(twa<0) { twa+=2*M_PI; } updateDouble(boatData->TWA, twa, msg.sourceId); - SetN2kWindSpeed(n2kMsg, 1, WindSpeed, twa, N2kWind_True_water); - send(n2kMsg,msg.sourceId,String(n2kMsg.PGN)+String((int)N2kWind_True_water)); + const GwConverterConfig::WindMapping mapping=config.findWindMapping(GwConverterConfig::WindMapping::TWA_TWS); + if (mapping.valid){ + SetN2kWindSpeed(n2kMsg, 1, WindSpeed, twa, mapping.n2kType); + send(n2kMsg,msg.sourceId,String(n2kMsg.PGN)+String((int)mapping.n2kType)); + } + const GwConverterConfig::WindMapping mapping2=config.findWindMapping(GwConverterConfig::WindMapping::TWD_TWS); + if (mapping2.valid){ + SetN2kWindSpeed(n2kMsg, 1, WindSpeed, WindDirection, mapping2.n2kType); + send(n2kMsg,msg.sourceId,String(n2kMsg.PGN)+String((int)mapping2.n2kType)); + } } } } diff --git a/lib/nmea2kto0183/N2kDataToNMEA0183.cpp b/lib/nmea2kto0183/N2kDataToNMEA0183.cpp index 659a5c33..03a4a3ce 100644 --- a/lib/nmea2kto0183/N2kDataToNMEA0183.cpp +++ b/lib/nmea2kto0183/N2kDataToNMEA0183.cpp @@ -469,38 +469,65 @@ class N2kToNMEA0183Functions : public N2kDataToNMEA0183 unsigned char SID; tN2kWindReference WindReference; double WindAngle=N2kDoubleNA, WindSpeed=N2kDoubleNA; - + tNMEA0183WindReference NMEA0183Reference; if (ParseN2kWindSpeed(N2kMsg, SID, WindSpeed, WindAngle, WindReference)) { tNMEA0183Msg NMEA0183Msg; - tNMEA0183WindReference NMEA0183Reference; + GwConverterConfig::WindMapping mapping=config.findWindMapping(WindReference); bool shouldSend = false; // MWV sentence contains apparent/true ANGLE and SPEED // https://gpsd.gitlab.io/gpsd/NMEA.html#_mwv_wind_speed_and_angle // https://docs.vaisala.com/r/M211109EN-L/en-US/GUID-7402DEF8-5E82-446F-B63E-998F49F3D743/GUID-C77934C7-2A72-466E-BC52-CE6B8CC7ACB6 - - if (WindReference == N2kWind_Apparent) { - NMEA0183Reference = NMEA0183Wind_Apparent; - updateDouble(boatData->AWA, WindAngle); - updateDouble(boatData->AWS, WindSpeed); - setMax(boatData->MaxAws, boatData->AWS); - shouldSend = true; - } - if (WindReference == N2kWind_True_water) { - NMEA0183Reference = NMEA0183Wind_True; - updateDouble(boatData->TWA, WindAngle); - updateDouble(boatData->TWS, WindSpeed); - setMax(boatData->MaxTws, boatData->TWS); - shouldSend = true; - if (boatData->HDT->isValid()) { - double twd = WindAngle+boatData->HDT->getData(); - if (twd>2*M_PI) { twd-=2*M_PI; } - updateDouble(boatData->TWD, twd); + if (mapping.valid) + { + if (mapping.nmea0183Type == GwConverterConfig::WindMapping::AWA_AWS) + { + NMEA0183Reference = NMEA0183Wind_Apparent; + updateDouble(boatData->AWA, WindAngle); + updateDouble(boatData->AWS, WindSpeed); + setMax(boatData->MaxAws, boatData->AWS); + shouldSend = true; + } + if (mapping.nmea0183Type == GwConverterConfig::WindMapping::TWA_TWS) + { + NMEA0183Reference = NMEA0183Wind_True; + updateDouble(boatData->TWA, WindAngle); + updateDouble(boatData->TWS, WindSpeed); + setMax(boatData->MaxTws, boatData->TWS); + shouldSend = true; + if (boatData->HDT->isValid()) + { + double twd = WindAngle + boatData->HDT->getData(); + if (twd > 2 * M_PI) + { + twd -= 2 * M_PI; + } + updateDouble(boatData->TWD, twd); + } + } + if (mapping.nmea0183Type == GwConverterConfig::WindMapping::TWD_TWS) + { + NMEA0183Reference = NMEA0183Wind_True; + updateDouble(boatData->TWD, WindAngle); + updateDouble(boatData->TWS, WindSpeed); + setMax(boatData->MaxTws, boatData->TWS); + if (boatData->HDT->isValid()) + { + shouldSend = true; + double twa = WindAngle - boatData->HDT->getData(); + if (twa > 2 * M_PI) + { + twa -= 2 * M_PI; + } + updateDouble(boatData->TWA, twa); + WindAngle=twa; + } } - } - if (shouldSend && NMEA0183SetMWV(NMEA0183Msg, formatCourse(WindAngle), NMEA0183Reference, WindSpeed, talkerId)) { - SendMessage(NMEA0183Msg); + if (shouldSend && NMEA0183SetMWV(NMEA0183Msg, formatCourse(WindAngle), NMEA0183Reference, WindSpeed, talkerId)) + { + SendMessage(NMEA0183Msg); + } } /* if (WindReference == N2kWind_Apparent && boatData->SOG->isValid()) diff --git a/src/main.cpp b/src/main.cpp index 17d2fa1d..714c0a5a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -850,7 +850,7 @@ void setup() { xdrMappings.begin(); logger.flush(); GwConverterConfig converterConfig; - converterConfig.init(&config); + converterConfig.init(&config,&logger); nmea0183Converter= N2kDataToNMEA0183::create(&logger, &boatData, [](const tNMEA0183Msg &msg, int sourceId){ SendNMEA0183Message(msg,sourceId,false); diff --git a/web/config.json b/web/config.json index 7dad6ca2..906920a2 100644 --- a/web/config.json +++ b/web/config.json @@ -250,6 +250,58 @@ "description": "the n2k instance to be used as port rudder 0...253, -1 to disable", "category": "converter" }, + { + "name": "windmappings", + "type": "array", + "replace":[ + { + "n": "tng", + "l": "true north ground", + "t": "True_North=0", + "d": "twa_tws" + }, + { + "n": "mgd", + "l": "magnetic ground dir", + "t": "Magnetic=1", + "d":"" + }, + { + "n": "awa", + "l": "apparent angle", + "t": "Apparent=2", + "d":"awa_aws" + }, + { + "n": "gna", + "l": "ground angle", + "t": "True_boat=3", + "d": "" + }, + { + "n": "tra", + "l": "true angle", + "t": "True_water=4", + "d":"" + } + + ], + "children":[ + { + "name":"windm$n", + "type":"list", + "description": "mapping of the PGN 130306 wind reference $t", + "label":"wind $l", + "list":[ + {"l": "-unset-","v":""}, + {"l": "TWA/TWS","v":"twa_tws"}, + {"l": "AWA/AWS", "v":"awa_aws"}, + {"l": "TWD/TWS","v":"twd_tws"} + ] + + } + ] + }, { "name": "timeouts", "type": "array",