allow to set a read only mode for config items, output compiler messages for overwritten configs, add m5 gps unit defs

This commit is contained in:
andreas 2023-10-05 18:52:30 +02:00
parent 9572b1e95e
commit 4fa40b98b3
7 changed files with 114 additions and 45 deletions

View File

@ -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")]

View File

@ -1,3 +1,4 @@
#define CFG_MESSAGES
#include "GWConfig.h"
#include <ArduinoJson.h>
#include <string.h>
@ -159,20 +160,20 @@ void GwConfigHandler::toHex(unsigned long v, char *buffer, size_t bsize)
buffer[2 * i] = 0;
}
std::vector<String> GwConfigHandler::getHidden() const{
std::vector<String> GwConfigHandler::getSpecial() const{
std::vector<String> rt;
rt.reserve(numHidden());
rt.reserve(numSpecial());
for (int i=0L;i<getNumConfig();i++){
if (configs[i]->isHidden()){
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;i<getNumConfig();i++){
if (configs[i]->isHidden()) rt++;
if (configs[i]->getType() != GwConfigInterface::NORMAL) rt++;
}
return rt;
}

View File

@ -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<String> getHidden() const;
int numHidden() const;
std::vector<String> getSpecial() const;
int numSpecial() const;
/**
* change the value of a config item
* will become a noop after stopChanges has been called

View File

@ -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

View File

@ -17,7 +17,7 @@
#define GWSERIAL_TYPE_BI 2
#define GWSERIAL_TYPE_RX 3
#define GWSERIAL_TYPE_TX 4
#include <GwConfigItem.h>
#include <HardwareSerial.h>
#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

View File

@ -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<String> hiddenCfg=config.getHidden();
for (auto it=hiddenCfg.begin();it != hiddenCfg.end();it++){
json["HIDE"+*it]=true;
std::vector<String> 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);

View File

@ -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) {