diff --git a/extra_script.py b/extra_script.py index 03ec16b..00cf107 100644 --- a/extra_script.py +++ b/extra_script.py @@ -145,20 +145,33 @@ def generateCfg(inFile,outFile,addDirs=[]): secret="false"; if item.get('type') == 'password': secret="true" - data+=" #undef __CFGHIDDEN\n" - data+=" #ifdef CFGHIDE_%s\n"%(name) - data+=" #define __CFGHIDDEN true\n" + data+=" #undef __CFGMODE\n" + data+=" #ifdef CFGMODE_%s\n"%(name) + data+=" #define __CFGMODE CFGMODE_%s\n"%(name) data+=" #else\n" - data+=" #define __CFGHIDDEN false\n" + data+=" #define __CFGMODE GwConfigInterface::NORMAL\n" data+=" #endif\n" - data+=" #ifdef CFGDEFAULT_%s\n"%(name) - data+=" new GwConfigInterface(%s,CFGDEFAULT_%s,%s,__CFGHIDDEN)\n"%(name,name,secret) + data+=" #ifdef CFGDEFAULT_%s\n"%(name) + data+=" new GwConfigInterface(%s,CFGDEFAULT_%s,%s,__CFGMODE)\n"%(name,name,secret) data+=" #else\n" - data+=" new GwConfigInterface(%s,\"%s\",%s,__CFGHIDDEN)\n"%(name,item.get('default'),secret) + data+=" new GwConfigInterface(%s,\"%s\",%s,__CFGMODE)\n"%(name,item.get('default'),secret) data+=" #endif\n" data+='};\n' data+='};\n' + data+="#ifdef CFG_MESSAGES\n" + for item in config: + name=item.get('name') + if name is None: + continue + data+="#ifdef CFGMODE_%s\n"%(name) + data+=" __MSG(\"CFGMODE_%s=\" __XSTR(CFGMODE_%s))\n"%(name,name) + data+="#endif\n" + data+="#ifdef CFGDEFAULT_%s\n"%(name) + data+=" __MSG(\"CFGDEFAULT_%s=\" CFGDEFAULT_%s)\n"%(name,name) + data+="#endif\n" + data+="#endif" + writeFileIfChanged(outFile,data) @@ -298,6 +311,7 @@ print("#prescript...") prebuild(env) board="PLATFORM_BOARD_%s"%env["BOARD"].replace("-","_").upper() print("Board=#%s#"%board) +print("BuildFlags=%s"%(" ".join(env["BUILD_FLAGS"]))) env.Append( LINKFLAGS=[ "-u", "custom_app_desc" ], CPPDEFINES=[(board,"1")] diff --git a/lib/config/GWConfig.cpp b/lib/config/GWConfig.cpp index 15ecc43..641b564 100644 --- a/lib/config/GWConfig.cpp +++ b/lib/config/GWConfig.cpp @@ -1,3 +1,4 @@ +#define CFG_MESSAGES #include "GWConfig.h" #include #include @@ -159,20 +160,20 @@ void GwConfigHandler::toHex(unsigned long v, char *buffer, size_t bsize) buffer[2 * i] = 0; } -std::vector GwConfigHandler::getHidden() const{ +std::vector GwConfigHandler::getSpecial() const{ std::vector rt; - rt.reserve(numHidden()); + rt.reserve(numSpecial()); for (int i=0L;iisHidden()){ + if (configs[i]->getType() != GwConfigInterface::NORMAL){ rt.push_back(configs[i]->getName()); }; } return rt; } -int GwConfigHandler::numHidden() const{ +int GwConfigHandler::numSpecial() const{ int rt=0; for (int i=0L;iisHidden()) rt++; + if (configs[i]->getType() != GwConfigInterface::NORMAL) rt++; } return rt; } diff --git a/lib/config/GWConfig.h b/lib/config/GWConfig.h index f6e1db2..796ae25 100644 --- a/lib/config/GWConfig.h +++ b/lib/config/GWConfig.h @@ -30,8 +30,8 @@ class GwConfigHandler: public GwConfigDefinitions{ int getInt(const String name,int defaultv=0) const; GwConfigInterface * getConfigItem(const String name, bool dummy=false) const; bool checkPass(String hash); - std::vector getHidden() const; - int numHidden() const; + std::vector getSpecial() const; + int numSpecial() const; /** * change the value of a config item * will become a noop after stopChanges has been called diff --git a/lib/config/GwConfigItem.h b/lib/config/GwConfigItem.h index a6d66cd..12f5e97 100644 --- a/lib/config/GwConfigItem.h +++ b/lib/config/GwConfigItem.h @@ -5,19 +5,25 @@ class GwConfigHandler; class GwConfigInterface{ + public: + typedef enum { + NORMAL=0, + HIDDEN=1, + READONLY=2 + } ConfigType; private: String name; const char * initialValue; String value; bool secret=false; - bool hidden=false; + ConfigType type=NORMAL; public: - GwConfigInterface(const String &name, const char * initialValue, bool secret=false, bool hidden=false){ + GwConfigInterface(const String &name, const char * initialValue, bool secret=false,ConfigType type=NORMAL){ this->name=name; this->initialValue=initialValue; this->value=initialValue; this->secret=secret; - this->hidden=hidden; + this->type=type; } virtual String asString() const{ return value; @@ -43,8 +49,8 @@ class GwConfigInterface{ String getDefault() const { return initialValue; } - bool isHidden() const { - return hidden; + ConfigType getType() const { + return type; } friend class GwConfigHandler; }; @@ -67,5 +73,7 @@ class GwNmeaFilter{ String toString(); }; - +#define __XSTR(x) __STR(x) +#define __STR(x) #x +#define __MSG(x) _Pragma (__STR(message (x))) #endif \ No newline at end of file diff --git a/lib/hardware/GwHardware.h b/lib/hardware/GwHardware.h index 5b7e278..c4d9142 100644 --- a/lib/hardware/GwHardware.h +++ b/lib/hardware/GwHardware.h @@ -17,7 +17,7 @@ #define GWSERIAL_TYPE_BI 2 #define GWSERIAL_TYPE_RX 3 #define GWSERIAL_TYPE_TX 4 - +#include #include #include "GwUserTasks.h" @@ -148,8 +148,8 @@ #ifdef M5_GPS_KIT #define GWSERIAL_RX BOARD_LEFT1 #define GWSERIAL_TYPE GWSERIAL_TYPE_RX - #define CFGGDEFAULT_serialBaud "9600" - #define CFGHIDE_serialBaud + #define CFGDEFAULT_serialBaud "9600" + #define CFGMODE_serialBaud GwConfigInterface::READONLY #endif //below we define the final device config based on the above @@ -181,6 +181,21 @@ #endif #endif +//http://docs.m5stack.com/en/unit/gps +#ifdef M5_GPS_UNIT + #ifdef GWSERIAL_TYPE + #define GWSERIAL2_RX GROOVE_PIN_2 + #define GWSERIAL2_TYPE GWSERIAL_TYPE_RX + #define CFGDEFAULT_serialBaud "9600" + #define CFGMODE_serialBaud GwConfigInterface::READONLY + #else + #define GWSERIAL_RX GROOVE_PIN_2 + #define GWSERIAL_TYPE GWSERIAL_TYPE_RX + #define CFGDEFAULT_serial2Baud "9600" + #define CFGMODE_serial2Baud GwConfigInterface::READONLY + #endif +#endif + //can kit for M5 Atom #ifdef M5_CAN_KIT #define ESP32_CAN_TX_PIN BOARD_LEFT1 diff --git a/src/main.cpp b/src/main.cpp index 0bc11ba..b928ad4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -430,15 +430,20 @@ class CapabilitiesRequest : public GwRequestMessage{ protected: virtual void processRequest(){ int numCapabilities=userCodeHandler.getCapabilities()->size(); - int numHidden=config.numHidden(); - GwJsonDocument json(JSON_OBJECT_SIZE(numCapabilities*3+numHidden*2+8)); + int numSpecial=config.numSpecial(); + logger.logDebug(GwLog::LOG,"capabilities user=%d, config=%d",numCapabilities,numSpecial); + GwJsonDocument json(JSON_OBJECT_SIZE(numCapabilities*3+numSpecial*2+8)); for (auto it=userCodeHandler.getCapabilities()->begin(); it != userCodeHandler.getCapabilities()->end();it++){ json[it->first]=it->second; } - std::vector hiddenCfg=config.getHidden(); - for (auto it=hiddenCfg.begin();it != hiddenCfg.end();it++){ - json["HIDE"+*it]=true; + std::vector specialCfg=config.getSpecial(); + for (auto it=specialCfg.begin();it != specialCfg.end();it++){ + GwConfigInterface *cfg=config.getConfigItem(*it); + if (cfg){ + logger.logDebug(GwLog::LOG,"config mode %s=%d",it->c_str(),(int)(cfg->getType())); + json["CFGMODE"+*it]=(int)cfg->getType(); + } } json["serialmode"]=channels.getMode(SERIAL1_CHANNEL_ID); json["serial2mode"]=channels.getMode(SERIAL2_CHANNEL_ID); diff --git a/web/index.js b/web/index.js index 4c49f9c..db31d8d 100644 --- a/web/index.js +++ b/web/index.js @@ -231,6 +231,7 @@ function getAllConfigs(omitPass) { let name = v.getAttribute('name'); if (!name) continue; if (name.indexOf("_") >= 0) continue; + if (v.getAttribute('disabled')) continue; let def = getConfigDefition(name); if (def.type === 'password' && ( v.value == '' || omitPass)) { continue; @@ -444,6 +445,7 @@ function createInput(configItem, frame,clazz) { let el; if (configItem.type === 'boolean' || configItem.type === 'list' || configItem.type == 'boatData') { el=addEl('select',clazz,frame); + if (configItem.readOnly) el.setAttribute('disabled',true); el.setAttribute('name', configItem.name) let slist = []; if (configItem.list) { @@ -476,6 +478,7 @@ function createInput(configItem, frame,clazz) { return createXdrInput(configItem,frame,clazz); } el = addEl('input',clazz,frame); + if (configItem.readOnly) el.setAttribute('disabled',true); el.setAttribute('name', configItem.name) if (configItem.type === 'password') { el.setAttribute('type', 'password'); @@ -591,25 +594,29 @@ function createXdrInput(configItem,frame){ {l:'bidir',v:1}, {l:'to2K',v:2}, {l:'from2K',v:3} - ] + ], + readOnly: configItem.readOnly },d,'xdrdir'); d=createXdrLine(el,'Category'); let category=createInput({ type: 'list', name: configItem.name+"_cat", - list:getXdrCategories() + list:getXdrCategories(), + readOnly: configItem.readOnly },d,'xdrcat'); d=createXdrLine(el,'Source'); let selector=createInput({ type: 'list', name: configItem.name+"_sel", - list:[] + list:[], + readOnly: configItem.readOnly },d,'xdrsel'); d=createXdrLine(el,'Field'); let field=createInput({ type:'list', name: configItem.name+'_field', - list: [] + list: [], + readOnly: configItem.readOnly },d,'xdrfield'); d=createXdrLine(el,'Instance'); let imode=createInput({ @@ -620,22 +627,26 @@ function createXdrInput(configItem,frame){ {l:'single',v:0}, {l:'ignore',v:1}, {l:'auto',v:2} - ] + ], + readOnly: configItem.readOnly },d,'xdrimode'); let instance=createInput({ type:'number', name: configItem.name+"_instance", + readOnly: configItem.readOnly },d,'xdrinstance'); d=createXdrLine(el,'Transducer'); let xdrName=createInput({ type:'text', - name: configItem.name+"_xdr" + name: configItem.name+"_xdr", + readOnly: configItem.readOnly },d,'xdrname'); d=createXdrLine(el,'Example'); let example=addEl('div','xdrexample',d,''); let data = addEl('input','xdrvalue',el); data.setAttribute('type', 'hidden'); data.setAttribute('name', configItem.name); + if (configItem.readOnly) data.setAttribute('disabled',true); let changeFunction = function () { let parts=data.value.split(','); direction.value=parts[1] || 0; @@ -730,16 +741,19 @@ function createFilterInput(configItem, frame) { let ais = createInput({ type: 'list', name: configItem.name + "_ais", - list: ['aison', 'aisoff'] + list: ['aison', 'aisoff'], + readOnly: configItem.readOnly }, el); let mode = createInput({ type: 'list', name: configItem.name + "_mode", - list: ['whitelist', 'blacklist'] + list: ['whitelist', 'blacklist'], + readOnly: configItem.readOnly }, el); let sentences = createInput({ type: 'text', name: configItem.name + "_sentences", + readOnly: configItem.readOnly }, el); let data = addEl('input',undefined,el); data.setAttribute('type', 'hidden'); @@ -767,6 +781,7 @@ function createFilterInput(configItem, frame) { changeFunction(); }); data.setAttribute('name', configItem.name); + if (configItem.readOnly) data.setAttribute('disabled',true); return data; } let moreicons=['icon-more','icon-less']; @@ -1048,8 +1063,17 @@ function createConfigDefinitions(parent, capabilities, defs,includeXdr) { }); if (!found) showItem=false; } - + let readOnly=false; + let mode=capabilities['CFGMODE'+item.name]; + if (mode == 1) { + //hide + showItem=false; + } + if (mode == 2){ + readOnly=true; + } if (showItem) { + item.readOnly=readOnly; currentCategoryPopulated=true; let row = addEl('div', 'row', categoryEl); let label = item.label || item.name; @@ -1058,7 +1082,7 @@ function createConfigDefinitions(parent, capabilities, defs,includeXdr) { let valueEl = createInput(item, valueFrame); if (!valueEl) return; valueEl.setAttribute('data-default', item.default); - valueEl.addEventListener('change', function (ev) { + if (! readOnly) valueEl.addEventListener('change', function (ev) { let el = ev.target; checkChange(el, row, item.name); }) @@ -1075,13 +1099,15 @@ function createConfigDefinitions(parent, capabilities, defs,includeXdr) { } if (item.check) valueEl.setAttribute('data-check', item.check); let btContainer = addEl('div', 'buttonContainer', row); - let bt = addEl('button', 'defaultButton', btContainer, 'X'); - bt.setAttribute('data-default', item.default); - bt.addEventListener('click', function (ev) { - valueEl.value = valueEl.getAttribute('data-default'); - let changeEvent = new Event('change'); - valueEl.dispatchEvent(changeEvent); - }) + if (!readOnly) { + let bt = addEl('button', 'defaultButton', btContainer, 'X'); + bt.setAttribute('data-default', item.default); + bt.addEventListener('click', function (ev) { + valueEl.value = valueEl.getAttribute('data-default'); + let changeEvent = new Event('change'); + valueEl.dispatchEvent(changeEvent); + }) + } bt = addEl('button', 'infoButton', btContainer, '?'); bt.addEventListener('click', function (ev) { if (item.description) {