make the counter display and the channel names dynamic in the UI

This commit is contained in:
andreas 2023-08-31 12:24:21 +02:00
parent 019fb8ff6a
commit cb98324604
5 changed files with 109 additions and 54 deletions

View File

@ -57,7 +57,7 @@ GwChannel::GwChannel(GwLog *logger,
this->logger = logger; this->logger = logger;
this->name=name; this->name=name;
this->sourceId=sourceId; this->sourceId=sourceId;
this->maxSourceId=sourceId; this->maxSourceId=maxSourceId;
this->countIn=new GwCounter<String>(String("count")+name+String("in")); this->countIn=new GwCounter<String>(String("count")+name+String("in"));
this->countOut=new GwCounter<String>(String("count")+name+String("out")); this->countOut=new GwCounter<String>(String("count")+name+String("out"));
this->impl=NULL; this->impl=NULL;
@ -146,12 +146,15 @@ bool GwChannel::canReceive(const char *buffer){
} }
int GwChannel::getJsonSize(){ int GwChannel::getJsonSize(){
int rt=2; int rt=JSON_OBJECT_SIZE(6);
if (countIn) rt+=countIn->getJsonSize(); if (countIn) rt+=countIn->getJsonSize();
if (countOut) rt+=countOut->getJsonSize(); if (countOut) rt+=countOut->getJsonSize();
return rt; return rt;
} }
void GwChannel::toJson(GwJsonDocument &doc){ void GwChannel::toJson(GwJsonDocument &doc){
JsonObject jo=doc.createNestedObject("ch"+name);
jo["id"]=sourceId;
jo["max"]=maxSourceId;
if (countOut) countOut->toJson(doc); if (countOut) countOut->toJson(doc);
if (countIn) countIn->toJson(doc); if (countIn) countIn->toJson(doc);
} }

View File

@ -58,9 +58,53 @@ void GwChannelList::allChannels(ChannelAction action){
action(*it); action(*it);
} }
} }
typedef struct {
int id;
const char *baud;
const char *receive;
const char *send;
const char *direction;
const char *toN2K;
const char *readF;
const char *writeF;
const char *name;
} SerialParam;
void GwChannelList::addSerial(int id,const String &mode,int rx,int tx){ static SerialParam serialParameters[]={
if (id != SERIAL1_CHANNEL_ID && id != SERIAL2_CHANNEL_ID){ {
.id=SERIAL1_CHANNEL_ID,
.baud=GwConfigDefinitions::serialBaud,
.receive=GwConfigDefinitions::receiveSerial,
.send=GwConfigDefinitions::sendSerial,
.direction=GwConfigDefinitions::serialDirection,
.toN2K=GwConfigDefinitions::serialToN2k,
.readF=GwConfigDefinitions::serialReadF,
.writeF=GwConfigDefinitions::serialWriteF,
.name="Serial"
},
{
.id=SERIAL2_CHANNEL_ID,
.baud=GwConfigDefinitions::serial2Baud,
.receive=GwConfigDefinitions::receiveSerial2,
.send=GwConfigDefinitions::sendSerial2,
.direction=GwConfigDefinitions::serial2Dir,
.toN2K=GwConfigDefinitions::serial2ToN2k,
.readF=GwConfigDefinitions::serial2ReadF,
.writeF=GwConfigDefinitions::serial2WriteF,
.name="Serial2"
}
};
static SerialParam *getSerialParam(int id){
for (size_t idx=0;idx<sizeof(serialParameters)/sizeof(SerialParam*);idx++){
if (serialParameters[idx].id == id) return &serialParameters[idx];
}
return nullptr;
}
void GwChannelList::addSerial(HardwareSerial *serialStream,int id,const String &mode,int rx,int tx){
SerialParam *param=getSerialParam(id);
if (param == nullptr){
logger->logDebug(GwLog::ERROR,"trying to set up an unknown serial channel: %d",id); logger->logDebug(GwLog::ERROR,"trying to set up an unknown serial channel: %d",id);
return; return;
} }
@ -68,14 +112,11 @@ void GwChannelList::addSerial(int id,const String &mode,int rx,int tx){
logger->logDebug(GwLog::ERROR,"useless config for serial %d: both rx/tx undefined"); logger->logDebug(GwLog::ERROR,"useless config for serial %d: both rx/tx undefined");
return; return;
} }
String cfgName;
bool canRead=false; bool canRead=false;
bool canWrite=false; bool canWrite=false;
if (mode == "BI"){ if (mode == "BI"){
cfgName=(id==SERIAL1_CHANNEL_ID)?config->receiveSerial:config->receiveSerial2; canRead=config->getBool(param->receive);
canRead=config->getBool(cfgName); canWrite=config->getBool(param->send);
cfgName=(id==SERIAL2_CHANNEL_ID)?config->sendSerial:config->sendSerial2;
canWrite=config->getBool(cfgName);
} }
if (mode == "TX"){ if (mode == "TX"){
canWrite=true; canWrite=true;
@ -84,8 +125,7 @@ void GwChannelList::addSerial(int id,const String &mode,int rx,int tx){
canRead=true; canRead=true;
} }
if (mode == "UNI"){ if (mode == "UNI"){
cfgName=(id == SERIAL1_CHANNEL_ID)?config->serialDirection:config->serial2Dir; String cfgMode=config->getString(param->direction);
String cfgMode=config->getString(cfgName);
if (cfgMode == "receive"){ if (cfgMode == "receive"){
canRead=true; canRead=true;
} }
@ -95,22 +135,21 @@ void GwChannelList::addSerial(int id,const String &mode,int rx,int tx){
} }
if (rx < 0) canRead=false; if (rx < 0) canRead=false;
if (tx < 0) canWrite=false; if (tx < 0) canWrite=false;
HardwareSerial *serialStream=(id == SERIAL1_CHANNEL_ID)?&Serial1:&Serial2;
LOG_DEBUG(GwLog::DEBUG,"serial set up: mode=%s,rx=%d,canRead=%d,tx=%d,canWrite=%d", LOG_DEBUG(GwLog::DEBUG,"serial set up: mode=%s,rx=%d,canRead=%d,tx=%d,canWrite=%d",
mode.c_str(),rx,(int)canRead,tx,(int)canWrite); mode.c_str(),rx,(int)canRead,tx,(int)canWrite);
serialStream->begin(config->getInt(config->serialBaud,115200),SERIAL_8N1,rx,tx); serialStream->begin(config->getInt(param->baud,115200),SERIAL_8N1,rx,tx);
GwSerial *serial = new GwSerial(logger, serialStream, id, canRead); GwSerial *serial = new GwSerial(logger, serialStream, id, canRead);
LOG_DEBUG(GwLog::LOG, "starting serial %d ", id); LOG_DEBUG(GwLog::LOG, "starting serial %d ", id);
GwChannel *channel = new GwChannel(logger, (id == SERIAL1_CHANNEL_ID) ? "SER" : "SER2", id); GwChannel *channel = new GwChannel(logger, param->name, id);
channel->setImpl(serial); channel->setImpl(serial);
channel->begin( channel->begin(
canRead || canWrite, canRead || canWrite,
canWrite, canWrite,
canRead, canRead,
config->getString((id == SERIAL1_CHANNEL_ID) ? config->serialReadF : config->serial2ReadF), config->getString(param->readF),
config->getString((id == SERIAL1_CHANNEL_ID) ? config->serialWriteF : config->serial2WriteF), config->getString(param->writeF),
false, false,
config->getBool((id == SERIAL1_CHANNEL_ID) ? config->serialToN2k : config->serial2ToN2k), config->getBool(param->toN2K),
false, false,
false); false);
LOG_DEBUG(GwLog::LOG, "%s", channel->toString().c_str()); LOG_DEBUG(GwLog::LOG, "%s", channel->toString().c_str());
@ -143,7 +182,7 @@ void GwChannelList::begin(bool fallbackSerial){
//TCP server //TCP server
sockets=new GwSocketServer(config,logger,MIN_TCP_CHANNEL_ID); sockets=new GwSocketServer(config,logger,MIN_TCP_CHANNEL_ID);
sockets->begin(); sockets->begin();
channel=new GwChannel(logger,"TCP",MIN_TCP_CHANNEL_ID,MIN_TCP_CHANNEL_ID+10); channel=new GwChannel(logger,"TCPserver",MIN_TCP_CHANNEL_ID,MIN_TCP_CHANNEL_ID+10);
channel->setImpl(sockets); channel->setImpl(sockets);
channel->begin( channel->begin(
true, true,
@ -167,7 +206,7 @@ void GwChannelList::begin(bool fallbackSerial){
#define GWSERIAL_RX -1 #define GWSERIAL_RX -1
#endif #endif
#ifdef GWSERIAL_MODE #ifdef GWSERIAL_MODE
addSerial(SERIAL1_CHANNEL_ID,GWSERIAL_MODE,GWSERIAL_RX,GWSERIAL_TX); addSerial(&Serial1,SERIAL1_CHANNEL_ID,GWSERIAL_MODE,GWSERIAL_RX,GWSERIAL_TX);
#endif #endif
//serial 2 //serial 2
#ifndef GWSERIAL2_TX #ifndef GWSERIAL2_TX
@ -177,7 +216,7 @@ void GwChannelList::begin(bool fallbackSerial){
#define GWSERIAL2_RX -1 #define GWSERIAL2_RX -1
#endif #endif
#ifdef GWSERIAL2_MODE #ifdef GWSERIAL2_MODE
addSerial(SERIAL2_CHANNEL_ID,GWSERIAL2_MODE,GWSERIAL2_RX,GWSERIAL2_TX); addSerial(&Serial2,SERIAL2_CHANNEL_ID,GWSERIAL2_MODE,GWSERIAL2_RX,GWSERIAL2_TX);
#endif #endif
//tcp client //tcp client
bool tclEnabled=config->getBool(config->tclEnabled); bool tclEnabled=config->getBool(config->tclEnabled);

View File

@ -7,6 +7,7 @@
#include "GWConfig.h" #include "GWConfig.h"
#include "GwJsonDocument.h" #include "GwJsonDocument.h"
#include "GwApi.h" #include "GwApi.h"
#include <HardwareSerial.h>
//NMEA message channels //NMEA message channels
#define N2K_CHANNEL_ID 0 #define N2K_CHANNEL_ID 0
@ -28,8 +29,7 @@ class GwChannelList{
GwSocketServer *sockets; GwSocketServer *sockets;
GwTcpClient *client; GwTcpClient *client;
String serialMode=F("NONE"); void addSerial(HardwareSerial *stream,int id,const String &mode,int rx,int tx);
void addSerial(int id,const String &mode,int rx,int tx);
public: public:
GwChannelList(GwLog *logger, GwConfigHandler *config); GwChannelList(GwLog *logger, GwConfigHandler *config);
typedef std::function<void(GwChannel *)> ChannelAction; typedef std::function<void(GwChannel *)> ChannelAction;

View File

@ -155,8 +155,8 @@ SemaphoreHandle_t mainLock;
GwRequestQueue mainQueue(&logger,20); GwRequestQueue mainQueue(&logger,20);
GwWebServer webserver(&logger,&mainQueue,80); GwWebServer webserver(&logger,&mainQueue,80);
GwCounter<unsigned long> countNMEA2KIn("count2Kin"); GwCounter<unsigned long> countNMEA2KIn("countNMEA2000in");
GwCounter<unsigned long> countNMEA2KOut("count2Kout"); GwCounter<unsigned long> countNMEA2KOut("countNMEA2000out");
GwIntervalRunner timers; GwIntervalRunner timers;
bool checkPass(String hash){ bool checkPass(String hash){
@ -399,6 +399,7 @@ protected:
} }
status["n2kstate"]=NMEA2000.stateStr(driverState); status["n2kstate"]=NMEA2000.stateStr(driverState);
status["n2knode"]=NodeAddress; status["n2knode"]=NodeAddress;
status["minUser"]=MIN_USER_TASK;
//nmea0183Converter->toJson(status); //nmea0183Converter->toJson(status);
countNMEA2KIn.toJson(status); countNMEA2KIn.toJson(status);
countNMEA2KOut.toJson(status); countNMEA2KOut.toJson(status);

View File

@ -3,6 +3,8 @@ let lastUpdate = (new Date()).getTime();
let reloadConfig = false; let reloadConfig = false;
let needAdminPass=true; let needAdminPass=true;
let lastSalt=""; let lastSalt="";
let channelList={};
let minUser=200;
function addEl(type, clazz, parent, text) { function addEl(type, clazz, parent, text) {
let el = document.createElement(type); let el = document.createElement(type);
if (clazz) { if (clazz) {
@ -65,22 +67,39 @@ function update() {
} }
getJson('/api/status') getJson('/api/status')
.then(function (jsonData) { .then(function (jsonData) {
let statusPage=document.getElementById('statusPageContent');
let even=true; //first counter
for (let k in jsonData) { for (let k in jsonData) {
if (k == "salt"){ if (k == "salt"){
lastSalt=jsonData[k]; lastSalt=jsonData[k];
continue;
} }
if (k == "minUser"){
minUser=parseInt(jsonData[k]);
continue;
}
if (! statusPage) continue;
if (typeof (jsonData[k]) === 'object') { if (typeof (jsonData[k]) === 'object') {
for (let sk in jsonData[k]) { if (k.indexOf('count') == 0) {
let key = k + "." + sk; createCounterDisplay(statusPage, k.replace("count", "").replace(/in$/," in").replace(/out$/," out"), k, even);
if (typeof (jsonData[k][sk]) === 'object') { even = !even;
//msg details for (let sk in jsonData[k]) {
updateMsgDetails(key, jsonData[k][sk]); let key = k + "." + sk;
} if (typeof (jsonData[k][sk]) === 'object') {
else { //msg details
let el = document.getElementById(key); updateMsgDetails(key, jsonData[k][sk]);
if (el) el.textContent = jsonData[k][sk]; }
else {
let el = document.getElementById(key);
if (el) el.textContent = jsonData[k][sk];
}
} }
} }
if (k.indexOf("ch")==0){
//channel def
let name=k.substring(2);
channelList[name]=jsonData[k];
}
} }
else { else {
let el = document.getElementById(k); let el = document.getElementById(k);
@ -286,9 +305,13 @@ function factoryReset() {
.catch(function (e) { }); .catch(function (e) { });
} }
function createCounterDisplay(parent,label,key,isEven){ function createCounterDisplay(parent,label,key,isEven){
if (parent.querySelector("#"+key)){
return;
}
let clazz="row icon-row counter-row"; let clazz="row icon-row counter-row";
if (isEven) clazz+=" even"; if (isEven) clazz+=" even";
let row=addEl('div',clazz,parent); let row=addEl('div',clazz,parent);
row.setAttribute("id",key);
let icon=addEl('span','icon icon-more',row); let icon=addEl('span','icon icon-more',row);
addEl('span','label',row,label); addEl('span','label',row,label);
let value=addEl('span','value',row,'---'); let value=addEl('span','value',row,'---');
@ -331,18 +354,7 @@ function updateMsgDetails(key, details) {
},frame); },frame);
}); });
} }
let counters={
count2Kin: 'NMEA2000 in',
count2Kout: 'NMEA2000 out',
countTCPin: 'TCPserver in',
countTCPout: 'TCPserver out',
countTCPClientin: 'TCPclient in',
countTCPClientout: 'TCPclient out',
countUSBin: 'USB in',
countUSBout: 'USB out',
countSERin: 'Serial in',
countSERout: 'Serial out'
}
function showOverlay(text, isHtml) { function showOverlay(text, isHtml) {
let el = document.getElementById('overlayContent'); let el = document.getElementById('overlayContent');
if (isHtml) { if (isHtml) {
@ -1448,13 +1460,13 @@ function createDashboard() {
frame.innerHTML = ''; frame.innerHTML = '';
} }
function sourceName(v){ function sourceName(v){
if (v == 0) return "N2K"; for (let n in channelList){
if (v == 1) return "USB"; if (v >= channelList[n].id && v <= channelList[n].max){
if (v == 2) return "SER"; return n;
if (v == 3) return "TCPcl" }
if (v >= 4 && v <= 20) return "TCPser"; }
if (v >= 200) return "USER"; if (v < minUser) return "---";
return "---"; return "USER["+v+"]";
} }
let lastSelectList=[]; let lastSelectList=[];
function updateDashboard(data) { function updateDashboard(data) {
@ -1716,13 +1728,13 @@ window.addEventListener('load', function () {
} }
}catch(e){} }catch(e){}
let statusPage=document.getElementById('statusPageContent'); let statusPage=document.getElementById('statusPageContent');
if (statusPage){ /*if (statusPage){
let even=true; let even=true;
for (let c in counters){ for (let c in counters){
createCounterDisplay(statusPage,counters[c],c,even); createCounterDisplay(statusPage,counters[c],c,even);
even=!even; even=!even;
} }
} }*/
forEl('#uploadFile',function(el){ forEl('#uploadFile',function(el){
el.addEventListener('change',function(ev){ el.addEventListener('change',function(ev){
if (ev.target.files.length < 1) return; if (ev.target.files.length < 1) return;