From b51c36a5bbc65f2c78688a743253754f40281d6d Mon Sep 17 00:00:00 2001 From: andreas Date: Tue, 1 Mar 2022 15:21:28 +0100 Subject: [PATCH 01/13] make config names static members of GwConfigHandler --- extra_script.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extra_script.py b/extra_script.py index 4129a60..0331e39 100644 --- a/extra_script.py +++ b/extra_script.py @@ -131,7 +131,7 @@ def generateCfg(inFile,outFile,addDirs=[]): continue if len(n) > 15: raise Exception("%s: config names must be max 15 caracters"%n) - data+=' const String %s=F("%s");\n'%(n,n) + data+=' static constexpr const __FlashStringHelper* %s=F("%s");\n'%(n,n) data+=' protected:\n' data+=' GwConfigInterface *configs[%d]={\n'%(l) first=True From e3723be7e266818c8aacdf9541c2749df63988b5 Mon Sep 17 00:00:00 2001 From: andreas Date: Tue, 1 Mar 2022 15:21:03 +0100 Subject: [PATCH 02/13] make boatData names availabel as constants --- lib/boatData/GwBoatData.h | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/boatData/GwBoatData.h b/lib/boatData/GwBoatData.h index a021b9a..5ab8c86 100644 --- a/lib/boatData/GwBoatData.h +++ b/lib/boatData/GwBoatData.h @@ -160,6 +160,7 @@ public: virtual ~GwBoatItemNameProvider() {} }; #define GWBOATDATA(type,name,time,fmt) \ + GWSC(_##name); \ GwBoatItem *name=new GwBoatItem(F(#name),GwBoatItemBase::fmt,time,&values) ; #define GWSPECBOATDATA(clazz,name,time,fmt) \ clazz *name=new clazz(F(#name),GwBoatItemBase::fmt,time,&values) ; From 0b906d55c238808b05b9af4596c1eb3eebe38483 Mon Sep 17 00:00:00 2001 From: andreas Date: Tue, 1 Mar 2022 15:20:00 +0100 Subject: [PATCH 03/13] #16: correct handling for boatData config items --- web/index.js | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/web/index.js b/web/index.js index 0e17a38..a87ea24 100644 --- a/web/index.js +++ b/web/index.js @@ -121,7 +121,12 @@ function resetForm(ev) { } } } - el.value = v; + if (el.tagName === 'SELECT') { + setSelect(el,v); + } + else{ + el.value = v; + } el.setAttribute('data-loaded', v); let changeEvent = new Event('change'); el.dispatchEvent(changeEvent); @@ -459,14 +464,30 @@ function createInput(configItem, frame,clazz) { return el; } -function updateSelectList(item,slist){ - item.innerHTML=''; +function setSelect(item,value){ + if (!item) return; + item.value=value; + if (item.value !== value){ + //missing option with his value + let o=addEl('option',undefined,item,value); + o.setAttribute('value',value); + item.value=value; + } +} + +function updateSelectList(item,slist,opt_keepValue){ let idx=0; + let value; + if (opt_keepValue) value=item.value; + item.innerHTML=''; slist.forEach(function (sitem) { let sitemEl = addEl('option','',item,sitem.l); sitemEl.setAttribute('value', sitem.v !== undefined?sitem.v:idx); idx++; }) + if (value !== undefined){ + setSelect(item,value); + } } function getXdrCategories(){ let rt=[]; @@ -1462,7 +1483,7 @@ function updateDashboard(data) { } if (selectChanged){ forEl('.boatDataSelect',function(el){ - updateSelectList(el,selectList); + updateSelectList(el,selectList,true); }); } } From 7c89718735dc20812291ad36ee23e742d3829f4c Mon Sep 17 00:00:00 2001 From: andreas Date: Tue, 1 Mar 2022 15:44:08 +0100 Subject: [PATCH 04/13] simplify condition handling: allow arrays for values, allow to omit outer array --- web/index.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/web/index.js b/web/index.js index a87ea24..6cf3fcb 100644 --- a/web/index.js +++ b/web/index.js @@ -391,12 +391,19 @@ function checkCondition(element){ let condition=getConditions(name); if (! condition) return; let visible=false; + if (! condition instanceof Array) condition=[condition]; condition.forEach(function(cel){ let lvis=true; for (let k in cel){ let item=document.querySelector('[name='+k+']'); if (item){ - if (item.value != cel[k]) lvis=false; + let compare=cel[k]; + if (compare instanceof Array){ + if (compare.indexOf(item.value) < 0) lvis=false; + } + else{ + if (item.value != cel[k]) lvis=false; + } } } if (lvis) visible=true; From f9180d36edcd5e43ee52e0a0155635e0657d2ab4 Mon Sep 17 00:00:00 2001 From: andreas Date: Tue, 1 Mar 2022 16:33:09 +0100 Subject: [PATCH 05/13] #17: rename boat data values --- lib/boatData/GwBoatData.h | 34 +++---- lib/nmea0183ton2k/NMEA0183DataToN2K.cpp | 116 ++++++++++++------------ lib/nmea2kto0183/N2kDataToNMEA0183.cpp | 100 ++++++++++---------- 3 files changed, 125 insertions(+), 125 deletions(-) diff --git a/lib/boatData/GwBoatData.h b/lib/boatData/GwBoatData.h index 5ab8c86..dc30ad2 100644 --- a/lib/boatData/GwBoatData.h +++ b/lib/boatData/GwBoatData.h @@ -172,7 +172,7 @@ class GwBoatData{ GWBOATDATA(double,COG,4000,formatCourse) GWBOATDATA(double,TWD,4000,formatCourse) - GWBOATDATA(double,AWD,4000,formatCourse) + //GWBOATDATA(double,AWD,4000,formatCourse) GWBOATDATA(double,SOG,4000,formatKnots) GWBOATDATA(double,STW,4000,formatKnots) GWBOATDATA(double,TWS,4000,formatKnots) @@ -180,31 +180,31 @@ class GwBoatData{ GWBOATDATA(double,MaxTws,0,formatKnots) GWBOATDATA(double,MaxAws,0,formatKnots) GWBOATDATA(double,AWA,4000,formatWind) - GWBOATDATA(double,Heading,4000,formatCourse) //true - GWBOATDATA(double,MagneticHeading,4000,formatCourse) + GWBOATDATA(double,HDG,4000,formatCourse) //true heading + GWBOATDATA(double,MHDG,4000,formatCourse) //magnetic heading GWBOATDATA(double,ROT,4000,formatRot) - GWBOATDATA(double,Variation,4000,formatCourse) - GWBOATDATA(double,Deviation,4000,formatCourse) + GWBOATDATA(double,VAR,4000,formatCourse) //Variation + GWBOATDATA(double,DEV,4000,formatCourse) //Deviation GWBOATDATA(double,HDOP,4000,formatDop) GWBOATDATA(double,PDOP,4000,formatDop) GWBOATDATA(double,VDOP,4000,formatDop) - GWBOATDATA(double,RudderPosition,4000,formatCourse) - GWBOATDATA(double,Latitude,4000,formatLatitude) - GWBOATDATA(double,Longitude,4000,formatLongitude) - GWBOATDATA(double,Altitude,4000,formatFixed0) - GWBOATDATA(double,WaterDepth,4000,formatDepth) - GWBOATDATA(double,DepthTransducer,4000,formatDepth) - GWBOATDATA(double,GpsTime,4000,formatTime) - GWBOATDATA(double,WaterTemperature,4000,kelvinToC) + GWBOATDATA(double,RPOS,4000,formatCourse) //RudderPosition + GWBOATDATA(double,LAT,4000,formatLatitude) + GWBOATDATA(double,LON,4000,formatLongitude) + GWBOATDATA(double,ALT,4000,formatFixed0) //altitude + GWBOATDATA(double,DBS,4000,formatDepth) //waterDepth (below surface) + GWBOATDATA(double,DBT,4000,formatDepth) //DepthTransducer + GWBOATDATA(double,GPST,4000,formatTime) //GpsTime + GWBOATDATA(double,WTemp,4000,kelvinToC) GWBOATDATA(double,XTE,4000,formatXte) GWBOATDATA(double,DTW,4000,mtr2nm) GWBOATDATA(double,BTW,4000,formatCourse) - GWBOATDATA(double,WPLatitude,4000,formatLatitude) - GWBOATDATA(double,WPLongitude,4000,formatLongitude) + GWBOATDATA(double,WPLat,4000,formatLatitude) + GWBOATDATA(double,WPLon,4000,formatLongitude) GWBOATDATA(uint32_t,Log,16000,mtr2nm) GWBOATDATA(uint32_t,TripLog,16000,mtr2nm) - GWBOATDATA(uint32_t,GpsDate,4000,formatDate) - GWBOATDATA(int16_t,Timezone,8000,formatFixed0) + GWBOATDATA(uint32_t,GPSD,4000,formatDate) //Date + GWBOATDATA(int16_t,TZ,8000,formatFixed0) GWSPECBOATDATA(GwBoatDataSatList,SatInfo,GwSatInfoList::lifeTime,formatFixed0); public: GwBoatData(GwLog *logger); diff --git a/lib/nmea0183ton2k/NMEA0183DataToN2K.cpp b/lib/nmea0183ton2k/NMEA0183DataToN2K.cpp index bc0986f..434050f 100644 --- a/lib/nmea0183ton2k/NMEA0183DataToN2K.cpp +++ b/lib/nmea0183ton2k/NMEA0183DataToN2K.cpp @@ -340,8 +340,8 @@ private: uint8_t sourceId=getWaypointId(rmb.originID); if (boatData->DTW->update(rmb.dtw,msg.sourceId) && boatData->BTW->update(rmb.btw,msg.sourceId) - && boatData->WPLatitude->update(rmb.latitude,msg.sourceId) - && boatData->WPLongitude->update(rmb.longitude,msg.sourceId) + && boatData->WPLat->update(rmb.latitude,msg.sourceId) + && boatData->WPLon->update(rmb.longitude,msg.sourceId) ){ SetN2kNavigationInfo(n2kMsg,1,rmb.dtw,N2khr_true, false, @@ -365,37 +365,37 @@ private: } void convertRMC(const SNMEA0183Msg &msg) { - double GpsTime=0, Latitude=0, Longitude=0, COG=0, SOG=0, Variation=0; - unsigned long GpsDate=0; + double GPST=0, LAT=0, LON=0, COG=0, SOG=0, VAR=0; + unsigned long GPSD=0; time_t DateTime; char status; - if (!NMEA0183ParseRMC_nc(msg, GpsTime, status, Latitude, Longitude, COG, SOG, GpsDate, Variation, &DateTime)) + if (!NMEA0183ParseRMC_nc(msg, GPST, status, LAT, LON, COG, SOG, GPSD, VAR, &DateTime)) { LOG_DEBUG(GwLog::DEBUG, "failed to parse RMC %s", msg.line); return; } tN2kMsg n2kMsg; if ( - UD(GpsTime) && - UI(GpsDate) + UD(GPST) && + UI(GPSD) ) { - SetN2kSystemTime(n2kMsg, 1, GpsDate, GpsTime); + SetN2kSystemTime(n2kMsg, 1, GPSD, GPST); send(n2kMsg,msg.sourceId); } - if (UD(Latitude) && - UD(Longitude)){ - SetN2kLatLonRapid(n2kMsg,Latitude,Longitude); + if (UD(LAT) && + UD(LON)){ + SetN2kLatLonRapid(n2kMsg,LAT,LON); send(n2kMsg,msg.sourceId); } if (UD(COG) && UD(SOG)){ SetN2kCOGSOGRapid(n2kMsg,1,N2khr_true,COG,SOG); send(n2kMsg,msg.sourceId); } - if (UD(Variation)){ + if (UD(VAR)){ SetN2kMagneticVariation(n2kMsg,1,N2kmagvar_Calc, - getUint32(boatData->GpsDate), Variation); + getUint32(boatData->GPSD), VAR); send(n2kMsg,msg.sourceId); } @@ -529,62 +529,62 @@ private: } void convertHDM(const SNMEA0183Msg &msg){ - double MagneticHeading=NMEA0183DoubleNA; - if (!NMEA0183ParseHDM_nc(msg, MagneticHeading)) + double MHDG=NMEA0183DoubleNA; + if (!NMEA0183ParseHDM_nc(msg, MHDG)) { LOG_DEBUG(GwLog::DEBUG, "failed to parse HDM %s", msg.line); return; } - if (! UD(MagneticHeading)) return; + if (! UD(MHDG)) return; tN2kMsg n2kMsg; - SetN2kMagneticHeading(n2kMsg,1,MagneticHeading, - boatData->Variation->getDataWithDefault(N2kDoubleNA), - boatData->Deviation->getDataWithDefault(N2kDoubleNA) + SetN2kMagneticHeading(n2kMsg,1,MHDG, + boatData->VAR->getDataWithDefault(N2kDoubleNA), + boatData->DEV->getDataWithDefault(N2kDoubleNA) ); send(n2kMsg,msg.sourceId); } void convertHDT(const SNMEA0183Msg &msg){ - double Heading=NMEA0183DoubleNA; - if (!NMEA0183ParseHDT_nc(msg, Heading)) + double HDG=NMEA0183DoubleNA; + if (!NMEA0183ParseHDT_nc(msg, HDG)) { LOG_DEBUG(GwLog::DEBUG, "failed to parse HDT %s", msg.line); return; } - if (! UD(Heading)) return; + if (! UD(HDG)) return; tN2kMsg n2kMsg; - SetN2kTrueHeading(n2kMsg,1,Heading); + SetN2kTrueHeading(n2kMsg,1,HDG); send(n2kMsg,msg.sourceId); } void convertHDG(const SNMEA0183Msg &msg){ - double MagneticHeading=NMEA0183DoubleNA; - double Variation=NMEA0183DoubleNA; - double Deviation=NMEA0183DoubleNA; + double MHDG=NMEA0183DoubleNA; + double VAR=NMEA0183DoubleNA; + double DEV=NMEA0183DoubleNA; if (msg.FieldCount() < 5) { LOG_DEBUG(GwLog::DEBUG, "failed to parse HDG %s", msg.line); return; } if (msg.FieldLen(0)>0){ - MagneticHeading=formatDegToRad(atof(msg.Field(0))); + MHDG=formatDegToRad(atof(msg.Field(0))); } else{ return; } if (msg.FieldLen(1)>0){ - Deviation=formatDegToRad(atof(msg.Field(1))); - if (msg.Field(2)[0] == 'W') Deviation=-Deviation; + DEV=formatDegToRad(atof(msg.Field(1))); + if (msg.Field(2)[0] == 'W') DEV=-DEV; } if (msg.FieldLen(3)>0){ - Variation=formatDegToRad(atof(msg.Field(3))); - if (msg.Field(4)[0] == 'W') Variation=-Variation; + VAR=formatDegToRad(atof(msg.Field(3))); + if (msg.Field(4)[0] == 'W') VAR=-VAR; } - if (! UD(MagneticHeading)) return; - UD(Variation); - UD(Deviation); + if (! UD(MHDG)) return; + UD(VAR); + UD(DEV); tN2kMsg n2kMsg; - SetN2kMagneticHeading(n2kMsg,1,MagneticHeading,Deviation,Variation); + SetN2kMagneticHeading(n2kMsg,1,MHDG,DEV,VAR); send(n2kMsg,msg.sourceId); } @@ -607,10 +607,10 @@ private: } //offset == 0? SK does not allow this if (Offset != NMEA0183DoubleNA && Offset>=0 ){ - if (! boatData->WaterDepth->update(DepthBelowTransducer+Offset)) return; + if (! boatData->DBS->update(DepthBelowTransducer+Offset)) return; } if (Offset == NMEA0183DoubleNA) Offset=N2kDoubleNA; - if (! boatData->DepthTransducer->update(DepthBelowTransducer)) return; + if (! boatData->DBT->update(DepthBelowTransducer)) return; tN2kMsg n2kMsg; SetN2kWaterDepth(n2kMsg,1,DepthBelowTransducer,Offset); send(n2kMsg,msg.sourceId,String(n2kMsg.PGN)+String((Offset != N2kDoubleNA)?1:0)); @@ -645,7 +645,7 @@ private: continue; } if (dt == DBT){ - if (! boatData->DepthTransducer->update(Depth,msg.sourceId)) return; + if (! boatData->DBT->update(Depth,msg.sourceId)) return; tN2kMsg n2kMsg; SetN2kWaterDepth(n2kMsg,1,Depth,N2kDoubleNA); send(n2kMsg,msg.sourceId,String(n2kMsg.PGN)+String(0)); @@ -653,8 +653,8 @@ private: } //we can only send if we have a valid depth beloww tranducer //to compute the offset - if (! boatData->DepthTransducer->isValid()) return; - double offset=Depth-boatData->DepthTransducer->getData(); + if (! boatData->DBT->isValid()) return; + double offset=Depth-boatData->DBT->getData(); if (offset >= 0 && dt == DBT){ logger->logDebug(GwLog::DEBUG, "strange DBK - more depth then transducer %s", msg.line); return; @@ -664,7 +664,7 @@ private: return; } if (dt == DBS){ - if (! boatData->WaterDepth->update(Depth,msg.sourceId)) return; + if (! boatData->DBS->update(Depth,msg.sourceId)) return; } tN2kMsg n2kMsg; SetN2kWaterDepth(n2kMsg,1,Depth,offset); @@ -683,7 +683,7 @@ private: } void convertRSA(const SNMEA0183Msg &msg){ - double RudderPosition=NMEA0183DoubleNA; + double RPOS=NMEA0183DoubleNA; if (msg.FieldCount() < 4) { LOG_DEBUG(GwLog::DEBUG, "failed to parse RSA %s", msg.line); @@ -691,10 +691,10 @@ private: } if (msg.FieldLen(0)>0){ if (msg.Field(1)[0] != 'A') return; - RudderPosition=degToRad*atof(msg.Field(0)); + RPOS=degToRad*atof(msg.Field(0)); tN2kMsg n2kMsg; - if (! UD(RudderPosition)) return; - SetN2kRudder(n2kMsg,RudderPosition); + if (! UD(RPOS)) return; + SetN2kRudder(n2kMsg,RPOS); send(n2kMsg,msg.sourceId); } @@ -708,7 +708,7 @@ private: return; } if (! updateDouble(boatData->STW,STW,msg.sourceId)) return; - if (! updateDouble(boatData->Heading,TrueHeading,msg.sourceId)) return; + if (! updateDouble(boatData->HDG,TrueHeading,msg.sourceId)) return; if (MagneticHeading == NMEA0183DoubleNA) MagneticHeading=N2kDoubleNA; tN2kMsg n2kMsg; SetN2kBoatSpeed(n2kMsg,1,STW); @@ -741,12 +741,12 @@ private: tmElements_t parts; tNMEA0183Msg::breakTime(DateTime,parts); double GpsTime=parts.tm_sec+60*parts.tm_min+3600*parts.tm_hour; - if (! boatData->GpsDate->update(DaysSince1970,msg.sourceId)) return; - if (! boatData->GpsTime->update(GpsTime,msg.sourceId)) return; + if (! boatData->GPSD->update(DaysSince1970,msg.sourceId)) return; + if (! boatData->GPST->update(GpsTime,msg.sourceId)) return; bool timezoneValid=false; if (msg.FieldLen(4) > 0 && msg.FieldLen(5)>0){ Timezone=Timezone/60; //N2K has offset in minutes - if (! boatData->Timezone->update(Timezone,msg.sourceId)) return; + if (! boatData->TZ->update(Timezone,msg.sourceId)) return; timezoneValid=true; } tN2kMsg n2kMsg; @@ -774,16 +774,16 @@ private: LOG_DEBUG(GwLog::DEBUG, "failed to parse GGA %s", msg.line); return; } - if (! updateDouble(boatData->GpsTime,GPSTime,msg.sourceId)) return; - if (! updateDouble(boatData->Latitude,Latitude,msg.sourceId)) return; - if (! updateDouble(boatData->Longitude,Longitude,msg.sourceId)) return; - if (! updateDouble(boatData->Altitude,Altitude,msg.sourceId)) return; + if (! updateDouble(boatData->GPST,GPSTime,msg.sourceId)) return; + if (! updateDouble(boatData->LAT,Latitude,msg.sourceId)) return; + if (! updateDouble(boatData->LON,Longitude,msg.sourceId)) return; + if (! updateDouble(boatData->ALT,Altitude,msg.sourceId)) return; if (! updateDouble(boatData->HDOP,HDOP,msg.sourceId)) return; - if (! boatData->GpsDate->isValid()) return; + if (! boatData->GPSD->isValid()) return; tN2kMsg n2kMsg; tN2kGNSSmethod method=N2kGNSSm_noGNSS; if (GPSQualityIndicator <=5 ) method= (tN2kGNSSmethod)GPSQualityIndicator; - SetN2kGNSS(n2kMsg,1, boatData->GpsDate->getData(), + SetN2kGNSS(n2kMsg,1, boatData->GPSD->getData(), GPSTime, Latitude, Longitude, Altitude, N2kGNSSt_GPS, method, SatelliteCount, HDOP, boatData->PDOP->getDataWithDefault(N2kDoubleNA), 0, @@ -881,9 +881,9 @@ private: return; } if (GLL.status != 'A') return; - if (! updateDouble(boatData->Latitude,GLL.latitude,msg.sourceId)) return; - if (! updateDouble(boatData->Longitude,GLL.longitude,msg.sourceId)) return; - if (! updateDouble(boatData->GpsTime,GLL.GPSTime,msg.sourceId)) return; + if (! updateDouble(boatData->LAT,GLL.latitude,msg.sourceId)) return; + if (! updateDouble(boatData->LON,GLL.longitude,msg.sourceId)) return; + if (! updateDouble(boatData->GPST,GLL.GPSTime,msg.sourceId)) return; tN2kMsg n2kMsg; SetN2kLatLonRapid(n2kMsg,GLL.latitude,GLL.longitude); send(n2kMsg,msg.sourceId); diff --git a/lib/nmea2kto0183/N2kDataToNMEA0183.cpp b/lib/nmea2kto0183/N2kDataToNMEA0183.cpp index 53a8019..079e263 100644 --- a/lib/nmea2kto0183/N2kDataToNMEA0183.cpp +++ b/lib/nmea2kto0183/N2kDataToNMEA0183.cpp @@ -182,22 +182,22 @@ private: //if we have no variation we send either HDM or HDT if (ParseN2kHeading(N2kMsg, SID, Heading, _Deviation, Variation, ref)) { - updateDouble(boatData->Variation,Variation); - updateDouble(boatData->Deviation,_Deviation); + updateDouble(boatData->VAR,Variation); + updateDouble(boatData->DEV,_Deviation); if (N2kIsNA(Variation)){ //maybe we still have a valid variation - Variation=boatData->Variation->getDataWithDefault(N2kDoubleNA); + Variation=boatData->VAR->getDataWithDefault(N2kDoubleNA); } if (N2kIsNA(Variation)){ //no variation if (ref == N2khr_magnetic){ - updateDouble(boatData->MagneticHeading,Heading); + updateDouble(boatData->MHDG,Heading); if (NMEA0183SetHDM(NMEA0183Msg,Heading,talkerId)){ SendMessage(NMEA0183Msg); } } if (ref == N2khr_true){ - updateDouble(boatData->Heading,Heading); + updateDouble(boatData->HDG,Heading); if (NMEA0183SetHDT(NMEA0183Msg,Heading,talkerId)){ SendMessage(NMEA0183Msg); } @@ -212,8 +212,8 @@ private: if (ref == N2khr_true){ MagneticHeading=Heading-Variation; } - updateDouble(boatData->MagneticHeading,MagneticHeading); - updateDouble(boatData->Heading,Heading); + updateDouble(boatData->MHDG,MagneticHeading); + updateDouble(boatData->HDG,Heading); if (!N2kIsNA(MagneticHeading)){ if (NMEA0183SetHDG(NMEA0183Msg, MagneticHeading,_Deviation, Variation,talkerId)) @@ -240,9 +240,9 @@ private: uint16_t DaysSince1970; double Variation; ParseN2kMagneticVariation(N2kMsg, SID, Source, DaysSince1970, Variation); - updateDouble(boatData->Variation, Variation); + updateDouble(boatData->VAR, Variation); if (DaysSince1970 != N2kUInt16NA && DaysSince1970 != 0) - boatData->GpsDate->update(DaysSince1970,sourceId); + boatData->GPSD->update(DaysSince1970,sourceId); } //***************************************************************************** @@ -258,8 +258,8 @@ private: tNMEA0183Msg NMEA0183Msg; updateDouble(boatData->STW, WaterReferenced); unsigned long now = millis(); - double MagneticHeading = (boatData->Heading->isValid(now) && boatData->Variation->isValid(now)) ? boatData->Heading->getData() + boatData->Variation->getData() : NMEA0183DoubleNA; - if (NMEA0183SetVHW(NMEA0183Msg, boatData->Heading->getDataWithDefault(NMEA0183DoubleNA), MagneticHeading, WaterReferenced,talkerId)) + double MagneticHeading = (boatData->HDG->isValid(now) && boatData->VAR->isValid(now)) ? boatData->HDG->getData() + boatData->VAR->getData() : NMEA0183DoubleNA; + if (NMEA0183SetVHW(NMEA0183Msg, boatData->HDG->getDataWithDefault(NMEA0183DoubleNA), MagneticHeading, WaterReferenced,talkerId)) { SendMessage(NMEA0183Msg); } @@ -278,8 +278,8 @@ private: { WaterDepth = DepthBelowTransducer + Offset; - updateDouble(boatData->WaterDepth, WaterDepth); - updateDouble(boatData->DepthTransducer,DepthBelowTransducer); + updateDouble(boatData->DBS, WaterDepth); + updateDouble(boatData->DBT,DepthBelowTransducer); tNMEA0183Msg NMEA0183Msg; if (NMEA0183SetDPT(NMEA0183Msg, DepthBelowTransducer, Offset,talkerId)) { @@ -299,8 +299,8 @@ private: double Longitude; if (ParseN2kPGN129025(N2kMsg, Latitude, Longitude)) { - updateDouble(boatData->Latitude, Latitude); - updateDouble(boatData->Longitude, Longitude); + updateDouble(boatData->LAT, Latitude); + updateDouble(boatData->LON, Longitude); } } @@ -316,13 +316,13 @@ private: { updateDouble(boatData->COG, COG); updateDouble(boatData->SOG, SOG); - double MCOG = (!N2kIsNA(COG) && boatData->Variation->isValid()) ? COG - boatData->Variation->getData() : NMEA0183DoubleNA; + double MCOG = (!N2kIsNA(COG) && boatData->VAR->isValid()) ? COG - boatData->VAR->getData() : NMEA0183DoubleNA; if (HeadingReference == N2khr_magnetic) { MCOG = COG; - if (boatData->Variation->isValid()) + if (boatData->VAR->isValid()) { - COG -= boatData->Variation->getData(); + COG -= boatData->VAR->getData(); updateDouble(boatData->COG, COG); } } @@ -382,14 +382,14 @@ private: nSatellites, HDOP, PDOP, GeoidalSeparation, nReferenceStations, ReferenceStationType, ReferenceSationID, AgeOfCorrection)) { - updateDouble(boatData->Latitude, Latitude); - updateDouble(boatData->Longitude, Longitude); - updateDouble(boatData->Altitude, Altitude); - updateDouble(boatData->GpsTime, GpsTime); + updateDouble(boatData->LAT, Latitude); + updateDouble(boatData->LON, Longitude); + updateDouble(boatData->ALT, Altitude); + updateDouble(boatData->GPST, GpsTime); updateDouble(boatData->HDOP,HDOP); updateDouble(boatData->PDOP,PDOP); if (DaysSince1970 != N2kUInt16NA && DaysSince1970 != 0) - boatData->GpsDate->update(DaysSince1970,sourceId); + boatData->GPSD->update(DaysSince1970,sourceId); int quality=0; if ((int)GNSSmethod <= 5) quality=(int)GNSSmethod; tNMEA0183AISMsg nmeaMsg; @@ -518,8 +518,8 @@ private: boatData->TWS->getDataWithDefault(NMEA0183DoubleNA),talkerId)) SendMessage(NMEA0183Msg); double magnetic = boatData->TWD->getData(); - if (boatData->Variation->isValid()) - magnetic -= boatData->Variation->getData(); + if (boatData->VAR->isValid()) + magnetic -= boatData->VAR->getData(); if (!NMEA0183Msg.Init("MWD", talkerId)) return; if (!NMEA0183Msg.AddDoubleField(formatCourse(boatData->TWD->getData()))) @@ -548,20 +548,20 @@ private: { long now = millis(); if (NextRMCSend <= millis() && - boatData->Latitude->isValid(now) && - boatData->Latitude->getLastSource() == sourceId + boatData->LAT->isValid(now) && + boatData->LAT->getLastSource() == sourceId ) { tNMEA0183Msg NMEA0183Msg; if (NMEA0183SetRMC(NMEA0183Msg, - boatData->GpsTime->getDataWithDefault(NMEA0183DoubleNA), - boatData->Latitude->getDataWithDefault(NMEA0183DoubleNA), - boatData->Longitude->getDataWithDefault(NMEA0183DoubleNA), + boatData->GPST->getDataWithDefault(NMEA0183DoubleNA), + boatData->LAT->getDataWithDefault(NMEA0183DoubleNA), + boatData->LON->getDataWithDefault(NMEA0183DoubleNA), boatData->COG->getDataWithDefault(NMEA0183DoubleNA), boatData->SOG->getDataWithDefault(NMEA0183DoubleNA), - boatData->GpsDate->getDataWithDefault(NMEA0183UInt32NA), - boatData->Variation->getDataWithDefault(NMEA0183DoubleNA), + boatData->GPSD->getDataWithDefault(NMEA0183UInt32NA), + boatData->VAR->getDataWithDefault(NMEA0183DoubleNA), talkerId)) { SendMessage(NMEA0183Msg); @@ -583,7 +583,7 @@ private: if (TripLog != N2kUInt32NA) boatData->TripLog->update(TripLog,sourceId); if (DaysSince1970 != N2kUInt16NA && DaysSince1970 != 0) - boatData->GpsDate->update(DaysSince1970,sourceId); + boatData->GPSD->update(DaysSince1970,sourceId); tNMEA0183Msg NMEA0183Msg; if (!NMEA0183Msg.Init("VLW", talkerId)) @@ -613,7 +613,7 @@ private: if (ParseN2kRudder(N2kMsg, RudderPosition, Instance, RudderDirectionOrder, AngleOrder)) { - updateDouble(boatData->RudderPosition, RudderPosition); + updateDouble(boatData->RPOS, RudderPosition); if (Instance != 0) return; @@ -1003,26 +1003,26 @@ private: LOG_DEBUG(GwLog::DEBUG,"unable to parse PGN %d",msg.PGN); return; } - updateDouble(boatData->GpsTime,GpsTime); - if (DaysSince1970 != N2kUInt16NA) boatData->GpsDate->update(DaysSince1970,sourceId); - if (boatData->GpsDate->isValid() && boatData->GpsTime->isValid()){ + updateDouble(boatData->GPST,GpsTime); + if (DaysSince1970 != N2kUInt16NA) boatData->GPSD->update(DaysSince1970,sourceId); + if (boatData->GPSD->isValid() && boatData->GPST->isValid()){ tNMEA0183Msg nmeaMsg; nmeaMsg.Init("ZDA",talkerId); char utc[7]; - double seconds=boatData->GpsTime->getData(); + double seconds=boatData->GPST->getData(); int hours=floor(seconds/3600.0); int minutes=floor(seconds/60) - hours *60; int sec=floor(seconds)-60*minutes-3600*hours; snprintf(utc,7,"%02d%02d%02d",hours,minutes,sec); nmeaMsg.AddStrField(utc); tmElements_t timeParts; - tNMEA0183Msg::breakTime(tNMEA0183Msg::daysToTime_t(boatData->GpsDate->getData()),timeParts); + tNMEA0183Msg::breakTime(tNMEA0183Msg::daysToTime_t(boatData->GPSD->getData()),timeParts); nmeaMsg.AddUInt32Field(tNMEA0183Msg::GetDay(timeParts)); nmeaMsg.AddUInt32Field(tNMEA0183Msg::GetMonth(timeParts)); nmeaMsg.AddUInt32Field(tNMEA0183Msg::GetYear(timeParts)); - if (boatData->Timezone->isValid()){ - int hours=boatData->Timezone->getData()/60; - int minutes=boatData->Timezone->getData() - 60 *hours; + if (boatData->TZ->isValid()){ + int hours=boatData->TZ->getData()/60; + int minutes=boatData->TZ->getData() - 60 *hours; nmeaMsg.AddDoubleField(hours,1,"%02.0f"); nmeaMsg.AddDoubleField(minutes,1,"%02.0f"); } @@ -1042,9 +1042,9 @@ private: LOG_DEBUG(GwLog::DEBUG,"unable to parse PGN %d",msg.PGN); return; } - updateDouble(boatData->GpsTime,GpsTime); - if (DaysSince1970 != N2kUInt16NA) boatData->GpsDate->update(DaysSince1970,sourceId); - if (LocalOffset != N2kInt16NA) boatData->Timezone->update(LocalOffset,sourceId); + updateDouble(boatData->GPST,GpsTime); + if (DaysSince1970 != N2kUInt16NA) boatData->GPSD->update(DaysSince1970,sourceId); + if (LocalOffset != N2kInt16NA) boatData->TZ->update(LocalOffset,sourceId); } void HandleROT(const tN2kMsg &msg){ unsigned char SID=0; @@ -1137,17 +1137,17 @@ private: return; } if (BearingReference == N2khr_magnetic){ - if (! boatData->Variation->isValid()){ + if (! boatData->VAR->isValid()){ LOG_DEBUG(GwLog::DEBUG,"missing variation to compute true heading for %d ", msg.PGN); return; } - BearingPositionToDestinationWaypoint-=boatData->Variation->getData(); + BearingPositionToDestinationWaypoint-=boatData->VAR->getData(); } if (! updateDouble(boatData->DTW,DistanceToWaypoint)) return; if (! updateDouble(boatData->BTW,BearingPositionToDestinationWaypoint)) return; - if (! updateDouble(boatData->WPLatitude,DestinationLatitude)) return; - if (! updateDouble(boatData->WPLongitude,DestinationLongitude)) return; + if (! updateDouble(boatData->WPLat,DestinationLatitude)) return; + if (! updateDouble(boatData->WPLon,DestinationLongitude)) return; tNMEA0183Msg nmeaMsg; if (! nmeaMsg.Init("RMB",talkerId)) return; if (! nmeaMsg.AddStrField("A")) return; @@ -1242,7 +1242,7 @@ private: double WaterTemperature; if (ParseN2kPGN130310(N2kMsg, SID, WaterTemperature, OutsideAmbientAirTemperature, AtmosphericPressure)) { - updateDouble(boatData->WaterTemperature, WaterTemperature); + updateDouble(boatData->WTemp, WaterTemperature); tNMEA0183Msg NMEA0183Msg; if (!NMEA0183Msg.Init("MTW", talkerId)) From ba7bf0027408da660c5e9c21d39ab9d342a44b1a Mon Sep 17 00:00:00 2001 From: andreas Date: Tue, 1 Mar 2022 16:42:11 +0100 Subject: [PATCH 06/13] remove unused AWD --- lib/boatData/GwBoatData.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/boatData/GwBoatData.h b/lib/boatData/GwBoatData.h index dc30ad2..b0bcb17 100644 --- a/lib/boatData/GwBoatData.h +++ b/lib/boatData/GwBoatData.h @@ -172,7 +172,6 @@ class GwBoatData{ GWBOATDATA(double,COG,4000,formatCourse) GWBOATDATA(double,TWD,4000,formatCourse) - //GWBOATDATA(double,AWD,4000,formatCourse) GWBOATDATA(double,SOG,4000,formatKnots) GWBOATDATA(double,STW,4000,formatKnots) GWBOATDATA(double,TWS,4000,formatKnots) @@ -197,8 +196,8 @@ class GwBoatData{ GWBOATDATA(double,GPST,4000,formatTime) //GpsTime GWBOATDATA(double,WTemp,4000,kelvinToC) GWBOATDATA(double,XTE,4000,formatXte) - GWBOATDATA(double,DTW,4000,mtr2nm) - GWBOATDATA(double,BTW,4000,formatCourse) + GWBOATDATA(double,DTW,4000,mtr2nm) //distance wp + GWBOATDATA(double,BTW,4000,formatCourse) //bearing wp GWBOATDATA(double,WPLat,4000,formatLatitude) GWBOATDATA(double,WPLon,4000,formatLongitude) GWBOATDATA(uint32_t,Log,16000,mtr2nm) From 8c083f38c99e9fedf8ba8c34e3a9557244dc00f3 Mon Sep 17 00:00:00 2001 From: andreas Date: Tue, 1 Mar 2022 18:16:00 +0100 Subject: [PATCH 07/13] correct static boat data names --- lib/boatData/GwBoatData.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/boatData/GwBoatData.h b/lib/boatData/GwBoatData.h index b0bcb17..5ddebde 100644 --- a/lib/boatData/GwBoatData.h +++ b/lib/boatData/GwBoatData.h @@ -160,7 +160,7 @@ public: virtual ~GwBoatItemNameProvider() {} }; #define GWBOATDATA(type,name,time,fmt) \ - GWSC(_##name); \ + static constexpr const __FlashStringHelper* _##name=F(#name); \ GwBoatItem *name=new GwBoatItem(F(#name),GwBoatItemBase::fmt,time,&values) ; #define GWSPECBOATDATA(clazz,name,time,fmt) \ clazz *name=new clazz(F(#name),GwBoatItemBase::fmt,time,&values) ; From f3514783758780e86b81c3f63a1c57b7c46f165d Mon Sep 17 00:00:00 2001 From: andreas Date: Tue, 1 Mar 2022 18:16:17 +0100 Subject: [PATCH 08/13] adapt example to changed names --- lib/exampletask/GwExampleTask.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/exampletask/GwExampleTask.cpp b/lib/exampletask/GwExampleTask.cpp index 88d9cc0..70dc9fa 100644 --- a/lib/exampletask/GwExampleTask.cpp +++ b/lib/exampletask/GwExampleTask.cpp @@ -42,8 +42,8 @@ class GetBoatDataRequest: public GwMessage{ so be sure to use a value that never will be a valid one alternatively you can check using the isValid() method at each boatData item */ - latitude=api->getBoatData()->Latitude->getDataWithDefault(INVALID_COORD); - longitude=api->getBoatData()->Longitude->getDataWithDefault(INVALID_COORD); + latitude=api->getBoatData()->LAT->getDataWithDefault(INVALID_COORD); + longitude=api->getBoatData()->LON->getDataWithDefault(INVALID_COORD); }; }; @@ -52,13 +52,13 @@ String formatValue(GwApi::BoatValue *value){ static const int bsize=30; char buffer[bsize+1]; buffer[0]=0; - if (value->getFormat() == "formatDate"){ + if (value->getFormat() == GwBoatItemBase::formatDate){ time_t tv=tNMEA0183Msg::daysToTime_t(value->value); tmElements_t parts; tNMEA0183Msg::breakTime(tv,parts); snprintf(buffer,bsize,"%04d/%02d/%02d",parts.tm_year+1900,parts.tm_mon+1,parts.tm_mday); } - else if(value->getFormat() == "formatTime"){ + else if(value->getFormat() == GwBoatItemBase::formatTime){ double inthr; double intmin; double intsec; @@ -68,7 +68,7 @@ String formatValue(GwApi::BoatValue *value){ modf(val*60.0,&intsec); snprintf(buffer,bsize,"%02.0f:%02.0f:%02.0f",inthr,intmin,intsec); } - else if (value->getFormat() == "formatFixed0"){ + else if (value->getFormat() == GwBoatItemBase::formatFixed0){ snprintf(buffer,bsize,"%.0f",value->value); } else{ @@ -90,10 +90,10 @@ void exampleTask(GwApi *api){ //------ bool hasPosition=false; bool hasPosition2=false; - LOG_DEBUG(GwLog::DEBUG,"example switch ist %s",exampleSwitch?"true":"false"); - LOG_DEBUG(GwLog::DEBUG,"minXdrInterval=%d",api->getConfig()->getInt(api->getConfig()->minXdrInterval)); - GwApi::BoatValue *longitude=new GwApi::BoatValue(F("Longitude")); - GwApi::BoatValue *latitude=new GwApi::BoatValue(F("Latitude")); + LOG_DEBUG(GwLog::LOG,"example switch is %s",exampleSwitch?"true":"false"); + LOG_DEBUG(GwLog::LOG,"minXdrInterval=%d",api->getConfig()->getInt(api->getConfig()->minXdrInterval)); + GwApi::BoatValue *longitude=new GwApi::BoatValue(GwBoatData::_LON); + GwApi::BoatValue *latitude=new GwApi::BoatValue(GwBoatData::_LAT); GwApi::BoatValue *testValue=new GwApi::BoatValue(boatItemName); GwApi::BoatValue *valueList[]={longitude,latitude,testValue}; GwApi::Status status; From 7d396c2e23ae49715d30e6649c4b8e9a396f6f0e Mon Sep 17 00:00:00 2001 From: andreas Date: Tue, 1 Mar 2022 18:25:22 +0100 Subject: [PATCH 09/13] adapt readme to release 20220301 --- Readme.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Readme.md b/Readme.md index d799ec2..54e15a1 100644 --- a/Readme.md +++ b/Readme.md @@ -145,6 +145,15 @@ For details refer to the [example description](lib/exampletask/Readme.md). Changelog --------- +[20220301](../../releases/tag/20220301) +********* +* change [boat data names to shorter ones](../../issues/17) +* correct [bug with boatData config items](../../issues/16) +* allow for shorter conditions in config items (use arrays of allowed values for "or" condition) +* add some static variables at BoatData to reference the known items (see [exampletask](lib/exampletask/exampletask.cpp#L95)) +* make the known config names static members of GwConfigHandler +* remove unused AWD boat data item + [20220124](../../releases/tag/20220124) ********* * make the serial input and output working again From 82a9c5dcd66a5b4abcde41d8d08768677480d389 Mon Sep 17 00:00:00 2001 From: andreas Date: Tue, 1 Mar 2022 18:37:12 +0100 Subject: [PATCH 10/13] correct bug in readme --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index 54e15a1..927cf8b 100644 --- a/Readme.md +++ b/Readme.md @@ -150,7 +150,7 @@ Changelog * change [boat data names to shorter ones](../../issues/17) * correct [bug with boatData config items](../../issues/16) * allow for shorter conditions in config items (use arrays of allowed values for "or" condition) -* add some static variables at BoatData to reference the known items (see [exampletask](lib/exampletask/exampletask.cpp#L95)) +* add some static variables at BoatData to reference the known items (see [exampletask](lib/exampletask/GwExampleTask.cpp#L95)) * make the known config names static members of GwConfigHandler * remove unused AWD boat data item From 785ece971e823983b0cce84465680ea432272d60 Mon Sep 17 00:00:00 2001 From: andreas Date: Wed, 2 Mar 2022 10:53:47 +0100 Subject: [PATCH 11/13] #18: export and import of config --- web/index.html | 2 ++ web/index.js | 96 +++++++++++++++++++++++++++++++------------------- 2 files changed, 61 insertions(+), 37 deletions(-) diff --git a/web/index.html b/web/index.html index d6cc011..c5bde6e 100644 --- a/web/index.html +++ b/web/index.html @@ -62,6 +62,8 @@ + +
diff --git a/web/index.js b/web/index.js index 6cf3fcb..ae9a10c 100644 --- a/web/index.js +++ b/web/index.js @@ -204,39 +204,46 @@ function checkXDR(v,allValues){ } } } +function getAllConfigs(omitPass) { + let values = document.querySelectorAll('.configForm select , .configForm input'); + let allValues = {}; + for (let i = 0; i < values.length; i++) { + let v = values[i]; + let name = v.getAttribute('name'); + if (!name) continue; + if (name.indexOf("_") >= 0) continue; + let def = getConfigDefition(name); + if (def.type === 'password' && ( v.value == '' || omitPass)) { + continue; + } + let check = v.getAttribute('data-check'); + if (check) { + if (typeof (self[check]) === 'function') { + let res = self[check](v.value, allValues, getConfigDefition(name)); + if (res) { + let value = v.value; + if (v.type === 'password') value = "******"; + alert("invalid config for " + v.getAttribute('name') + "(" + value + "):\n" + res); + return; + } + } + } + allValues[name] = v.value; + } + return allValues; +} function changeConfig() { ensurePass() .then(function (pass) { let newAdminPass; let url = "/api/setConfig?_hash="+encodeURIComponent(pass)+"&"; - let values = document.querySelectorAll('.configForm select , .configForm input'); - let allValues = {}; - for (let i = 0; i < values.length; i++) { - let v = values[i]; - let name = v.getAttribute('name'); - if (!name) continue; - if (name.indexOf("_") >= 0) continue; - let def = getConfigDefition(name); - if (def.type === 'password' && v.value == '') { - continue; - } - let check = v.getAttribute('data-check'); - if (check) { - if (typeof (self[check]) === 'function') { - let res = self[check](v.value, allValues, getConfigDefition(name)); - if (res) { - let value = v.value; - if (v.type === 'password') value = "******"; - alert("invalid config for " + v.getAttribute('name') + "(" + value + "):\n" + res); - return; - } - } - } + let allValues=getAllConfigs(); + if (!allValues) return; + for (let name in allValues){ if (name == 'adminPassword'){ - newAdminPass=v.value; + newAdminPass=allValues[name]; } - allValues[name] = v.value; - url += name + "=" + encodeURIComponent(v.value) + "&"; + url += name + "=" + encodeURIComponent(allValues[name]) + "&"; } getJson(url) .then(function (status) { @@ -254,7 +261,7 @@ function changeConfig() { } }) }) - .catch(function (e) { alert("Invalid password"); }) + .catch(function (e) { alert(e); }) } function factoryReset() { ensurePass() @@ -861,6 +868,19 @@ function formatDate(d){ else rt+=v; return rt; } +function downloadData(data,name){ + let url="data:application/octet-stream,"+encodeURIComponent(JSON.stringify(data,undefined,2)); + let target=document.getElementById('downloadXdr'); + if (! target) return; + target.setAttribute('href',url); + target.setAttribute('download',name); + target.click(); +} +function exportConfig(){ + let data=getAllConfigs(true); + if (! data) return; + downloadData(data,"config"+formatDate()+".json"); +} function exportXdr(){ let data={}; forEl('.xdrvalue',function(el) { @@ -873,18 +893,14 @@ function exportXdr(){ } data[name]=value; }) - let url="data:application/octet-stream,"+encodeURIComponent(JSON.stringify(data,undefined,2)); - let target=document.getElementById('downloadXdr'); - if (! target) return; - target.setAttribute('href',url); - target.setAttribute('download',"xdr"+formatDate()+".json"); - target.click(); + downloadData(data,"xdr"+formatDate()+".json"); } -function importXdr(){ - forEl('.uploadXdr',function(ul){ +function importJson(opt_keyPattern){ + let clazz='importJson'; + forEl('.'+clazz,function(ul){ ul.remove(); }); - let ip=addEl('input','uploadXdr',document.body); + let ip=addEl('input',clazz,document.body); ip.setAttribute('type','file'); ip.addEventListener('change',function(ev){ if (ip.files.length > 0){ @@ -895,7 +911,7 @@ function importXdr(){ let idata=JSON.parse(reader.result); let hasOverwrites=false; for (let k in idata){ - if (! k.match(/^XDR[0-9][0-9]*/)){ + if (opt_keyPattern && ! k.match(opt_keyPattern)){ alert("file contains invalid key "+k); return; } @@ -926,6 +942,12 @@ function importXdr(){ }); ip.click(); } +function importXdr(){ + importJson(new RegExp(/^XDR[0-9][0-9]*/)); +} +function importConfig(){ + importJson(); +} function toggleClass(el,id,classList){ let nc=classList[id]; let rt=false; From a288959009a8863453838bd0c693cbc2be005a58 Mon Sep 17 00:00:00 2001 From: andreas Date: Wed, 2 Mar 2022 11:23:31 +0100 Subject: [PATCH 12/13] #19: add help tab, allow to set the help URL with the HELP_URL capability --- lib/api/GwApi.h | 3 +++ lib/exampletask/GwExampleTask.h | 2 ++ lib/usercode/GwUserCode.cpp | 3 ++- web/index.html | 1 + web/index.js | 10 +++++++++- 5 files changed, 17 insertions(+), 2 deletions(-) diff --git a/lib/api/GwApi.h b/lib/api/GwApi.h index afef372..9611707 100644 --- a/lib/api/GwApi.h +++ b/lib/api/GwApi.h @@ -129,4 +129,7 @@ class GwApi{ #ifndef DECLARE_CAPABILITY #define DECLARE_CAPABILITY(name,value) #endif +#ifndef DECLARE_STRING_CAPABILITY +#define DECLARE_STRING_CAPABILITY(name,value) +#endif #endif diff --git a/lib/exampletask/GwExampleTask.h b/lib/exampletask/GwExampleTask.h index b759c93..cb128a5 100644 --- a/lib/exampletask/GwExampleTask.h +++ b/lib/exampletask/GwExampleTask.h @@ -46,4 +46,6 @@ DECLARE_CAPABILITY(testboard2,true); //hide some config value //just set HIDE + the name of the config item to true DECLARE_CAPABILITY(HIDEminXdrInterval,true); + +DECLARE_STRING_CAPABILITY(HELP_URL,"https://www.wellenvogel.de"); #endif \ No newline at end of file diff --git a/lib/usercode/GwUserCode.cpp b/lib/usercode/GwUserCode.cpp index df5a633..1e36e13 100644 --- a/lib/usercode/GwUserCode.cpp +++ b/lib/usercode/GwUserCode.cpp @@ -41,7 +41,8 @@ class GwUserCapability{ #define DECLARE_USERTASK(task) GwUserTaskDef __##task##__(task,#task); #define DECLARE_USERTASK_PARAM(task,...) GwUserTaskDef __##task##__(task,#task,__VA_ARGS__); #define DECLARE_INITFUNCTION(task) GwInitTask __Init##task##__(task,#task); -#define DECLARE_CAPABILITY(name,value) GwUserCapability __CAP##name##__(#name,#value); +#define DECLARE_CAPABILITY(name,value) GwUserCapability __CAP##name##__(#name,#value); +#define DECLARE_STRING_CAPABILITY(name,value) GwUserCapability __CAP##name##__(#name,value); #include "GwApi.h" #include "GwUserTasks.h" class TaskApi : public GwApi diff --git a/web/index.html b/web/index.html index c5bde6e..a607101 100644 --- a/web/index.html +++ b/web/index.html @@ -21,6 +21,7 @@
XDR
Data
Update
+
Help
diff --git a/web/index.js b/web/index.js index ae9a10c..d66723b 100644 --- a/web/index.js +++ b/web/index.js @@ -1073,6 +1073,10 @@ function createConfigDefinitions(parent, capabilities, defs,includeXdr) { function loadConfigDefinitions() { getJson("api/capabilities") .then(function (capabilities) { + if (capabilities.HELP_URL){ + let el=document.getElementById('helpButton'); + if (el) el.setAttribute('data-url',capabilities.HELP_URL); + } getJson("config.json") .then(function (defs) { getJson("xdrconfig.json") @@ -1191,7 +1195,11 @@ function converterInfo() { } function handleTab(el) { let activeName = el.getAttribute('data-page'); - if (!activeName) return; + if (!activeName) { + let extUrl= el.getAttribute('data-url'); + if (! extUrl) return; + window.open(extUrl,el.getAttribute('data-window')||'_'); + } let activeTab = document.getElementById(activeName); if (!activeTab) return; let all = document.querySelectorAll('.tabPage'); From b1bd523745fc428be5ea32b6fa9caeacf6dc5aa4 Mon Sep 17 00:00:00 2001 From: andreas Date: Wed, 2 Mar 2022 11:32:35 +0100 Subject: [PATCH 13/13] adapted readme to release 20220302 --- Readme.md | 7 +++++++ lib/exampletask/GwExampleTask.h | 2 +- lib/exampletask/Readme.md | 7 +++++-- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Readme.md b/Readme.md index 927cf8b..491c0c5 100644 --- a/Readme.md +++ b/Readme.md @@ -145,6 +145,13 @@ For details refer to the [example description](lib/exampletask/Readme.md). Changelog --------- +[20220302](../../releases/tag/20220302) +********* +* add export and import of config data.
+ HINT: **passwords are not included** +* add a HELP tab that points to this description
+ The url can be changed using the HELP_URL capability + [20220301](../../releases/tag/20220301) ********* * change [boat data names to shorter ones](../../issues/17) diff --git a/lib/exampletask/GwExampleTask.h b/lib/exampletask/GwExampleTask.h index cb128a5..5dbb5b6 100644 --- a/lib/exampletask/GwExampleTask.h +++ b/lib/exampletask/GwExampleTask.h @@ -46,6 +46,6 @@ DECLARE_CAPABILITY(testboard2,true); //hide some config value //just set HIDE + the name of the config item to true DECLARE_CAPABILITY(HIDEminXdrInterval,true); - +//example for a user defined help url that will be shown when clicking the help button DECLARE_STRING_CAPABILITY(HELP_URL,"https://www.wellenvogel.de"); #endif \ No newline at end of file diff --git a/lib/exampletask/Readme.md b/lib/exampletask/Readme.md index 4538a95..86b15eb 100644 --- a/lib/exampletask/Readme.md +++ b/lib/exampletask/Readme.md @@ -15,8 +15,11 @@ Files This file is completely optional. You only need this if you want to extend the base configuration - we add a dummy library here and define one additional build environment (board) - * [GwExampleTask.h](GwExampleTask.h) the name of this include must match the name of the directory (ignoring case) with a "gw" in front. This file includes our special hardware definitions and registers our task at the core (DECLARE_USERTASK in the code). Optionally it can define some capabilities (using DECLARE_CAPABILITY) that can be used in the config UI (see below). - Avoid including headers from other libraries in this file as this could interfere with the main code. Just only include them in your .cpp files (or in other headers). + * [GwExampleTask.h](GwExampleTask.h) the name of this include must match the name of the directory (ignoring case) with a "gw" in front. This file includes our special hardware definitions and registers our task at the core (DECLARE_USERTASK in the code). Avoid including headers from other libraries in this file as this could interfere with the main code. Just only include them in your .cpp files (or in other headers). + Optionally it can define some capabilities (using DECLARE_CAPABILITY) that can be used in the config UI (see below) + There are some special capabilities you can set: + * HIDEsomeName: will hide the configItem "someName" + * HELP_URL: will set the url that is loaded when clicking the HELP tab (user DECLARE_STRING_CAPABILITY) * [GwExampleTaks.cpp](GwExampleTask.cpp) includes the implementation of our task. This tasks runs in an own thread - see the comments in the code. We can have as many cpp (and header files) as we need to structure our code. * [config.json](config.json)