Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
9d0504f664
16
Readme.md
16
Readme.md
|
@ -145,6 +145,22 @@ For details refer to the [example description](lib/exampletask/Readme.md).
|
|||
|
||||
Changelog
|
||||
---------
|
||||
[20220302](../../releases/tag/20220302)
|
||||
*********
|
||||
* add export and import of config data.<br>
|
||||
HINT: **passwords are not included**
|
||||
* add a HELP tab that points to this description<br>
|
||||
The url can be changed using the HELP_URL capability
|
||||
|
||||
[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/GwExampleTask.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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -160,6 +160,7 @@ public:
|
|||
virtual ~GwBoatItemNameProvider() {}
|
||||
};
|
||||
#define GWBOATDATA(type,name,time,fmt) \
|
||||
static constexpr const __FlashStringHelper* _##name=F(#name); \
|
||||
GwBoatItem<type> *name=new GwBoatItem<type>(F(#name),GwBoatItemBase::fmt,time,&values) ;
|
||||
#define GWSPECBOATDATA(clazz,name,time,fmt) \
|
||||
clazz *name=new clazz(F(#name),GwBoatItemBase::fmt,time,&values) ;
|
||||
|
@ -171,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)
|
||||
|
@ -179,31 +179,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,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)
|
||||
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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
//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
|
|
@ -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)<br>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
<div class="tab" data-page="xdrPage">XDR</div>
|
||||
<div class="tab" data-page="dashboardPage">Data</div>
|
||||
<div class="tab" data-page="updatePage">Update</div>
|
||||
<div class="tab" data-url="https://github.com/wellenvogel/esp32-nmea2000" data-window="help" id="helpButton">Help</div>
|
||||
</div>
|
||||
<div id="statusPage" class="tabPage">
|
||||
<div id="statusPageContent">
|
||||
|
@ -62,6 +63,8 @@
|
|||
<button id="resetForm">ReloadConfig</button>
|
||||
<button id="forgetPass">ForgetPass</button>
|
||||
<button id="changeConfig">Save&Restart</button>
|
||||
<button id="exportConfig">Export</button>
|
||||
<button id="importConfig">Import</button>
|
||||
<button id="factoryReset">FactoryReset</button>
|
||||
</div>
|
||||
<div class="configFormRows">
|
||||
|
|
144
web/index.js
144
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);
|
||||
|
@ -199,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) {
|
||||
|
@ -249,7 +261,7 @@ function changeConfig() {
|
|||
}
|
||||
})
|
||||
})
|
||||
.catch(function (e) { alert("Invalid password"); })
|
||||
.catch(function (e) { alert(e); })
|
||||
}
|
||||
function factoryReset() {
|
||||
ensurePass()
|
||||
|
@ -386,12 +398,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;
|
||||
|
@ -459,14 +478,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=[];
|
||||
|
@ -833,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) {
|
||||
|
@ -845,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){
|
||||
|
@ -867,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;
|
||||
}
|
||||
|
@ -898,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;
|
||||
|
@ -1023,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")
|
||||
|
@ -1141,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');
|
||||
|
@ -1462,7 +1520,7 @@ function updateDashboard(data) {
|
|||
}
|
||||
if (selectChanged){
|
||||
forEl('.boatDataSelect',function(el){
|
||||
updateSelectList(el,selectList);
|
||||
updateSelectList(el,selectList,true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue