Merge branch 'master' into sensors

This commit is contained in:
andreas 2024-11-25 16:48:11 +01:00
commit f9a001a9c2
8 changed files with 85 additions and 19 deletions

View File

@ -71,9 +71,12 @@ class GwConverterConfig{
int rmcInterval=1000; int rmcInterval=1000;
int rmcCheckTime=4000; int rmcCheckTime=4000;
int winst312=256; int winst312=256;
bool unmappedXdr=false;
unsigned long xdrTimeout=60000;
std::vector<WindMapping> windMappings; std::vector<WindMapping> windMappings;
void init(GwConfigHandler *config, GwLog*logger){ void init(GwConfigHandler *config, GwLog*logger){
minXdrInterval=config->getInt(GwConfigDefinitions::minXdrInterval,100); minXdrInterval=config->getInt(GwConfigDefinitions::minXdrInterval,100);
xdrTimeout=config->getInt(GwConfigDefinitions::timoSensor);
starboardRudderInstance=config->getInt(GwConfigDefinitions::stbRudderI,0); starboardRudderInstance=config->getInt(GwConfigDefinitions::stbRudderI,0);
portRudderInstance=config->getInt(GwConfigDefinitions::portRudderI,-1); portRudderInstance=config->getInt(GwConfigDefinitions::portRudderI,-1);
min2KInterval=config->getInt(GwConfigDefinitions::min2KInterval,50); min2KInterval=config->getInt(GwConfigDefinitions::min2KInterval,50);
@ -83,6 +86,7 @@ class GwConverterConfig{
rmcInterval=config->getInt(GwConfigDefinitions::sendRMCi,1000); rmcInterval=config->getInt(GwConfigDefinitions::sendRMCi,1000);
if (rmcInterval < 0) rmcInterval=0; if (rmcInterval < 0) rmcInterval=0;
if (rmcInterval > 0 && rmcInterval <100) rmcInterval=100; if (rmcInterval > 0 && rmcInterval <100) rmcInterval=100;
unmappedXdr=config->getBool(GwConfigDefinitions::unknownXdr);
winst312=config->getInt(GwConfigDefinitions::winst312,256); winst312=config->getInt(GwConfigDefinitions::winst312,256);
for (auto && it:windConfigs){ for (auto && it:windConfigs){
String cfg=config->getString(it.second); String cfg=config->getString(it.second);

View File

@ -108,7 +108,7 @@ void GwWifi::loop(){
} }
else{ else{
if (! clientIsConnected){ if (! clientIsConnected){
LOG_DEBUG(GwLog::LOG,"wifiClient %s now connected to",wifiSSID->asCString()); LOG_DEBUG(GwLog::LOG,"wifiClient now connected to %s at %s",wifiSSID->asCString(),WiFi.localIP().toString().c_str());
clientIsConnected=true; clientIsConnected=true;
} }
} }

View File

@ -189,6 +189,7 @@ private:
if (N2kIsNA(v)) return N2kInt8NA; if (N2kIsNA(v)) return N2kInt8NA;
return v; return v;
} }
void convertXDR(const SNMEA0183Msg &msg){ void convertXDR(const SNMEA0183Msg &msg){
XdrMappingList foundMappings; XdrMappingList foundMappings;
for (int offset=0;offset <= (msg.FieldCount()-4);offset+=4){ for (int offset=0;offset <= (msg.FieldCount()-4);offset+=4){
@ -199,7 +200,19 @@ private:
String unit=msg.Field(offset+2); String unit=msg.Field(offset+2);
String transducerName=msg.Field(offset+3); String transducerName=msg.Field(offset+3);
GwXDRFoundMapping found=xdrMappings->getMapping(transducerName,type,unit); GwXDRFoundMapping found=xdrMappings->getMapping(transducerName,type,unit);
if (found.empty) continue; if (found.empty) {
if (config.unmappedXdr){
const GwXDRType *typeDef=xdrMappings->findType(type,unit);
GwXdrUnknownMapping mapping(transducerName,unit,typeDef,config.xdrTimeout);
value=mapping.valueFromXdr(value);
if (boatData->update(value,msg.sourceId,&mapping)){
//TODO: potentially update the format
LOG_DEBUG(GwLog::DEBUG+1,"found unmapped XDR %s:%s, value %f",
transducerName.c_str(),mapping.getBoatItemFormat().c_str(),value);
}
}
continue;
}
value=found.valueFromXdr(value); value=found.valueFromXdr(value);
if (!boatData->update(value,msg.sourceId,&found)) continue; if (!boatData->update(value,msg.sourceId,&found)) continue;
LOG_DEBUG(GwLog::DEBUG+1,"found mapped XDR %s:%s, value %f", LOG_DEBUG(GwLog::DEBUG+1,"found mapped XDR %s:%s, value %f",
@ -307,7 +320,7 @@ private:
return; return;
} }
tN2kMsg n2kMsg; tN2kMsg n2kMsg;
if (boatData->XTE->update(rmb.xte,msg.sourceId)){ if (updateDouble(boatData->XTE,rmb.xte,msg.sourceId)){
tN2kXTEMode mode=N2kxtem_Autonomous; tN2kXTEMode mode=N2kxtem_Autonomous;
if (msg.FieldCount() > 13){ if (msg.FieldCount() > 13){
const char *modeChar=msg.Field(13); const char *modeChar=msg.Field(13);
@ -318,10 +331,10 @@ private:
} }
uint8_t destinationId=getWaypointId(rmb.destID); uint8_t destinationId=getWaypointId(rmb.destID);
uint8_t sourceId=getWaypointId(rmb.originID); uint8_t sourceId=getWaypointId(rmb.originID);
if (boatData->DTW->update(rmb.dtw,msg.sourceId) if (updateDouble(boatData->DTW,rmb.dtw,msg.sourceId)
&& boatData->BTW->update(rmb.btw,msg.sourceId) && updateDouble(boatData->BTW,rmb.btw,msg.sourceId)
&& boatData->WPLat->update(rmb.latitude,msg.sourceId) && updateDouble(boatData->WPLat,rmb.latitude,msg.sourceId)
&& boatData->WPLon->update(rmb.longitude,msg.sourceId) && updateDouble(boatData->WPLon,rmb.longitude,msg.sourceId)
){ ){
SetN2kNavigationInfo(n2kMsg,1,rmb.dtw,N2khr_true, SetN2kNavigationInfo(n2kMsg,1,rmb.dtw,N2khr_true,
false, false,

View File

@ -90,6 +90,7 @@ class TaskInterfacesStorage{
return true; return true;
} }
GwApi::TaskInterfaces::Ptr get(const String &name, int &result){ GwApi::TaskInterfaces::Ptr get(const String &name, int &result){
GWSYNCHRONIZED(lock);
GWSYNCHRONIZED(lock); GWSYNCHRONIZED(lock);
auto it = values.find(name); auto it = values.find(name);
if (it == values.end()) if (it == values.end())
@ -161,6 +162,7 @@ class TaskApi : public GwApiInternal
GwApiInternal *api=nullptr; GwApiInternal *api=nullptr;
int sourceId; int sourceId;
SemaphoreHandle_t mainLock; SemaphoreHandle_t mainLock;
SemaphoreHandle_t mainLock;
SemaphoreHandle_t localLock; SemaphoreHandle_t localLock;
std::map<int,GwCounter<String>> counter; std::map<int,GwCounter<String>> counter;
std::map<String,GwApi::HandlerFunction> webHandlers; std::map<String,GwApi::HandlerFunction> webHandlers;
@ -243,6 +245,7 @@ public:
} }
}; };
virtual int getJsonSize(){ virtual int getJsonSize(){
GWSYNCHRONIZED(localLock);
GWSYNCHRONIZED(localLock); GWSYNCHRONIZED(localLock);
if (! counterUsed) return 0; if (! counterUsed) return 0;
int rt=0; int rt=0;
@ -252,6 +255,7 @@ public:
return rt; return rt;
}; };
virtual void increment(int idx,const String &name,bool failed=false){ virtual void increment(int idx,const String &name,bool failed=false){
GWSYNCHRONIZED(localLock);
GWSYNCHRONIZED(localLock); GWSYNCHRONIZED(localLock);
counterUsed=true; counterUsed=true;
auto it=counter.find(idx); auto it=counter.find(idx);

View File

@ -58,6 +58,7 @@ GwXDRType *types[] = {
new GwXDRType(GwXDRType::DISPLACEMENTD, "A", "D",DegToRad,RadToDeg,"rd"), new GwXDRType(GwXDRType::DISPLACEMENTD, "A", "D",DegToRad,RadToDeg,"rd"),
new GwXDRType(GwXDRType::RPM,"T","R") new GwXDRType(GwXDRType::RPM,"T","R")
}; };
static GwXDRType genericType(GwXDRType::GENERIC, "G", "");
template<typename T, int size> template<typename T, int size>
int GetArrLength(T(&)[size]){return size;} int GetArrLength(T(&)[size]){return size;}
static GwXDRType *findType(GwXDRType::TypeCode type, int *start = NULL) static GwXDRType *findType(GwXDRType::TypeCode type, int *start = NULL)
@ -82,6 +83,19 @@ static GwXDRType *findType(GwXDRType::TypeCode type, int *start = NULL)
return NULL; return NULL;
} }
static GwXDRType *findType(const String &typeString, const String &unitString)
{
int len=GetArrLength(types);
for (int i=0; i< len; i++)
{
if (types[i]->xdrtype == typeString && types[i]->xdrunit == unitString)
{
return types[i];
}
}
return &genericType;
}
#include "GwXdrTypeMappings.h" #include "GwXdrTypeMappings.h"
static GwXDRType::TypeCode findTypeMapping(GwXDRCategory category, int field) static GwXDRType::TypeCode findTypeMapping(GwXDRCategory category, int field)
@ -199,7 +213,7 @@ GwXDRMappingDef *GwXDRMappingDef::fromString(String s)
} }
return rt; return rt;
} }
String GwXDRMappingDef::getTransducerName(int instance) String GwXDRMappingDef::getTransducerName(int instance) const
{ {
String name = xdrName; String name = xdrName;
if (instanceMode == GwXDRMappingDef::IS_AUTO) if (instanceMode == GwXDRMappingDef::IS_AUTO)
@ -257,7 +271,7 @@ bool GwXDRMappings::addMapping(GwXDRMappingDef *def)
LOG_DEBUG(GwLog::ERROR, "no type mapping for %s", def->toString().c_str()); LOG_DEBUG(GwLog::ERROR, "no type mapping for %s", def->toString().c_str());
return false; return false;
} }
GwXDRType *type = findType(code, &typeIndex); GwXDRType *type = ::findType(code, &typeIndex);
if (!type) if (!type)
{ {
LOG_DEBUG(GwLog::ERROR, "no type definition for %s", def->toString().c_str()); LOG_DEBUG(GwLog::ERROR, "no type definition for %s", def->toString().c_str());
@ -298,7 +312,7 @@ bool GwXDRMappings::addMapping(GwXDRMappingDef *def)
LOG_DEBUG(GwLog::LOG, "append mapping with n183key %s", n183key.c_str()); LOG_DEBUG(GwLog::LOG, "append mapping with n183key %s", n183key.c_str());
it->second.push_back(mapping); it->second.push_back(mapping);
} }
type = findType(code, &typeIndex); type = ::findType(code, &typeIndex);
if (!type) if (!type)
break; break;
mapping = new GwXDRMapping(def, type); mapping = new GwXDRMapping(def, type);
@ -471,7 +485,7 @@ String GwXDRMappings::getXdrEntry(String mapping, double value,int instance){
{ {
return rt; return rt;
} }
GwXDRType *type = findType(code, &typeIndex); GwXDRType *type = ::findType(code, &typeIndex);
bool first=true; bool first=true;
unsigned long invalidTime=config->getInt(GwConfigDefinitions::timoSensor); unsigned long invalidTime=config->getInt(GwConfigDefinitions::timoSensor);
while (type){ while (type){
@ -480,8 +494,12 @@ String GwXDRMappings::getXdrEntry(String mapping, double value,int instance){
if (first) first=false; if (first) first=false;
else rt+=","; else rt+=",";
rt+=found.buildXdrEntry(value).entry; rt+=found.buildXdrEntry(value).entry;
type = findType(code, &typeIndex); type = ::findType(code, &typeIndex);
} }
delete def; delete def;
return rt; return rt;
} }
const GwXDRType * GwXDRMappings::findType(const String &typeString, const String &unitString) const{
return ::findType(typeString,unitString);
}

View File

@ -140,7 +140,7 @@ class GwXDRMappingDef{
rt += xdrUnit; rt += xdrUnit;
return rt; return rt;
} }
String getTransducerName(int instance); String getTransducerName(int instance) const;
private: private:
static bool handleToken(String tok,int index,GwXDRMappingDef *def); static bool handleToken(String tok,int index,GwXDRMappingDef *def);
}; };
@ -163,12 +163,12 @@ class GwXDRFoundMapping : public GwBoatItemNameProvider{
String entry; String entry;
String transducer; String transducer;
}; };
GwXDRMappingDef *definition=NULL; const GwXDRMappingDef *definition=NULL;
GwXDRType *type=NULL; const GwXDRType *type=NULL;
int instanceId=-1; int instanceId=-1;
bool empty=true; bool empty=true;
unsigned long timeout=0; unsigned long timeout=0;
GwXDRFoundMapping(GwXDRMappingDef *definition,GwXDRType *type, unsigned long timeout){ GwXDRFoundMapping(const GwXDRMappingDef *definition,const GwXDRType *type, unsigned long timeout){
this->definition=definition; this->definition=definition;
this->type=type; this->type=type;
this->timeout=timeout; this->timeout=timeout;
@ -182,7 +182,7 @@ class GwXDRFoundMapping : public GwBoatItemNameProvider{
empty=false; empty=false;
} }
GwXDRFoundMapping(){} GwXDRFoundMapping(){}
String getTransducerName(){ virtual String getTransducerName(){
return definition->getTransducerName(instanceId); return definition->getTransducerName(instanceId);
} }
double valueFromXdr(double value){ double valueFromXdr(double value){
@ -203,6 +203,24 @@ class GwXDRFoundMapping : public GwBoatItemNameProvider{
} }
}; };
class GwXdrUnknownMapping : public GwXDRFoundMapping{
String name;
String unit;
public:
GwXdrUnknownMapping(const String &xdrName, const String &xdrUnit,const GwXDRType *type,unsigned long timeout):
name(xdrName),unit(xdrUnit), GwXDRFoundMapping(nullptr,type,timeout){
}
virtual String getTransducerName(){
return name;
}
virtual String getBoatItemFormat(){
String rt=GwXDRFoundMapping::getBoatItemFormat();
if (type->xdrunit.isEmpty()) rt+=unit;
return rt;
}
};
//the class GwXDRMappings is not intended to be deleted //the class GwXDRMappings is not intended to be deleted
//the deletion will leave memory leaks! //the deletion will leave memory leaks!
class GwConfigHandler; class GwConfigHandler;
@ -229,6 +247,7 @@ class GwXDRMappings{
GwXDRFoundMapping getMapping(GwXDRCategory category,int selector,int field=0,int instance=-1); GwXDRFoundMapping getMapping(GwXDRCategory category,int selector,int field=0,int instance=-1);
String getXdrEntry(String mapping, double value,int instance=0); String getXdrEntry(String mapping, double value,int instance=0);
const char * getUnMapped(); const char * getUnMapped();
const GwXDRType * findType(const String &typeString, const String &unitString) const;
}; };

View File

@ -209,6 +209,14 @@
"default":"true", "default":"true",
"description":"send out the converted data on the NMEA2000 bus\nIf set to off the converted data will still be shown at the data tab.", "description":"send out the converted data on the NMEA2000 bus\nIf set to off the converted data will still be shown at the data tab.",
"category":"converter" "category":"converter"
},
{
"name":"unknownXdr",
"label":"show unknown XDR",
"type":"boolean",
"default":"false",
"description":"show received XDR transducer values in data display if there is no XDR mapping for them",
"category":"converter"
}, },
{ {
"name":"sendRMCi", "name":"sendRMCi",

View File

@ -1578,7 +1578,7 @@
if (isNaN(x)) return '-----'; if (isNaN(x)) return '-----';
return formatLonLatsDecimal(x, 'lat'); return formatLonLatsDecimal(x, 'lat');
}, },
u: '°' u: ''
}, },
formatLongitude: { formatLongitude: {
f: function (v) { f: function (v) {
@ -1798,7 +1798,7 @@
let id = el.getAttribute('id'); let id = el.getAttribute('id');
if (id) { if (id) {
if (!names[id.replace(/^frame_/, '')]) { if (!names[id.replace(/^frame_/, '')]) {
el.parentElement.remove(); el.remove();
} }
} }
}); });