diff --git a/lib/channel/GwChannel.cpp b/lib/channel/GwChannel.cpp index d25841d..ef9d64e 100644 --- a/lib/channel/GwChannel.cpp +++ b/lib/channel/GwChannel.cpp @@ -57,7 +57,7 @@ GwChannel::GwChannel(GwLog *logger, this->logger = logger; this->name=name; this->sourceId=sourceId; - this->maxSourceId=sourceId; + this->maxSourceId=maxSourceId; this->countIn=new GwCounter(String("count")+name+String("in")); this->countOut=new GwCounter(String("count")+name+String("out")); this->impl=NULL; @@ -146,12 +146,15 @@ bool GwChannel::canReceive(const char *buffer){ } int GwChannel::getJsonSize(){ - int rt=2; + int rt=JSON_OBJECT_SIZE(6); if (countIn) rt+=countIn->getJsonSize(); if (countOut) rt+=countOut->getJsonSize(); return rt; } void GwChannel::toJson(GwJsonDocument &doc){ + JsonObject jo=doc.createNestedObject("ch"+name); + jo["id"]=sourceId; + jo["max"]=maxSourceId; if (countOut) countOut->toJson(doc); if (countIn) countIn->toJson(doc); } diff --git a/lib/channel/GwChannelList.cpp b/lib/channel/GwChannelList.cpp index 5465ea9..6d803c4 100644 --- a/lib/channel/GwChannelList.cpp +++ b/lib/channel/GwChannelList.cpp @@ -58,6 +58,128 @@ void GwChannelList::allChannels(ChannelAction action){ 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; + +static SerialParam serialParameters[]={ + { + .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;idxlogDebug(GwLog::ERROR,"trying to set up an unknown serial channel: %d",id); + return; + } + if (rx < 0 && tx < 0){ + logger->logDebug(GwLog::ERROR,"useless config for serial %d: both rx/tx undefined"); + return; + } + modes[id]=String(mode); + bool canRead=false; + bool canWrite=false; + if (mode == "BI"){ + canRead=config->getBool(param->receive); + canWrite=config->getBool(param->send); + } + if (mode == "TX"){ + canWrite=true; + } + if (mode == "RX"){ + canRead=true; + } + if (mode == "UNI"){ + String cfgMode=config->getString(param->direction); + if (cfgMode == "receive"){ + canRead=true; + } + if (cfgMode == "send"){ + canWrite=true; + } + } + if (rx < 0) canRead=false; + if (tx < 0) canWrite=false; + 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); + serialStream->begin(config->getInt(param->baud,115200),SERIAL_8N1,rx,tx); + GwSerial *serial = new GwSerial(logger, serialStream, id, canRead); + LOG_DEBUG(GwLog::LOG, "starting serial %d ", id); + GwChannel *channel = new GwChannel(logger, param->name, id); + channel->setImpl(serial); + channel->begin( + canRead || canWrite, + canWrite, + canRead, + config->getString(param->readF), + config->getString(param->writeF), + false, + config->getBool(param->toN2K), + false, + false); + LOG_DEBUG(GwLog::LOG, "%s", channel->toString().c_str()); + theChannels.push_back(channel); +} + void GwChannelList::begin(bool fallbackSerial){ LOG_DEBUG(GwLog::DEBUG,"GwChannelList::begin"); GwChannel *channel=NULL; @@ -85,7 +207,7 @@ void GwChannelList::begin(bool fallbackSerial){ //TCP server sockets=new GwSocketServer(config,logger,MIN_TCP_CHANNEL_ID); 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->begin( true, @@ -102,57 +224,33 @@ void GwChannelList::begin(bool fallbackSerial){ theChannels.push_back(channel); //serial 1 - bool serCanRead=true; - bool serCanWrite=true; - int serialrx=-1; - int serialtx=-1; - #ifdef GWSERIAL_MODE - #ifdef GWSERIAL_TX - serialtx=GWSERIAL_TX; - #endif - #ifdef GWSERIAL_RX - serialrx=GWSERIAL_RX; - #endif - if (serialrx != -1 && serialtx != -1){ - serialMode=GWSERIAL_MODE; - } + #ifndef GWSERIAL_TX + #define GWSERIAL_TX -1 + #endif + #ifndef GWSERIAL_RX + #define GWSERIAL_RX -1 + #endif + #ifdef GWSERIAL_TYPE + addSerial(&Serial1,SERIAL1_CHANNEL_ID,GWSERIAL_TYPE,GWSERIAL_RX,GWSERIAL_TX); + #else + #ifdef GWSERIAL_MODE + addSerial(&Serial1,SERIAL1_CHANNEL_ID,GWSERIAL_MODE,GWSERIAL_RX,GWSERIAL_TX); + #endif + #endif + //serial 2 + #ifndef GWSERIAL2_TX + #define GWSERIAL2_TX -1 + #endif + #ifndef GWSERIAL2_RX + #define GWSERIAL2_RX -1 + #endif + #ifdef GWSERIAL2_TYPE + addSerial(&Serial2,SERIAL2_CHANNEL_ID,GWSERIAL2_TYPE,GWSERIAL2_RX,GWSERIAL2_TX); + #else + #ifdef GWSERIAL2_MODE + addSerial(&Serial2,SERIAL2_CHANNEL_ID,GWSERIAL2_MODE,GWSERIAL2_RX,GWSERIAL2_TX); + #endif #endif - //the serial direction is from the config (only valid for mode UNI) - String serialDirection=config->getString(config->serialDirection); - //we only consider the direction if mode is UNI - if (serialMode != String("UNI")){ - serialDirection=String(""); - //if mode is UNI it depends on the selection - serCanRead=config->getBool(config->receiveSerial); - serCanWrite=config->getBool(config->sendSerial); - } - if (serialDirection == "receive" || serialDirection == "off" || serialMode == "RX") serCanWrite=false; - if (serialDirection == "send" || serialDirection == "off" || serialMode == "TX") serCanRead=false; - LOG_DEBUG(GwLog::DEBUG,"serial set up: mode=%s,direction=%s,rx=%d,tx=%d", - serialMode.c_str(),serialDirection.c_str(),serialrx,serialtx - ); - if (serialtx != -1 || serialrx != -1 ){ - LOG_DEBUG(GwLog::LOG,"creating serial interface rx=%d, tx=%d",serialrx,serialtx); - Serial1.begin(config->getInt(config->serialBaud,115200),SERIAL_8N1,serialrx,serialtx); - GwSerial *serial=new GwSerial(logger,&Serial1,SERIAL1_CHANNEL_ID,serCanRead); - LOG_DEBUG(GwLog::LOG,"starting serial1 "); - channel=new GwChannel(logger,"SER",SERIAL1_CHANNEL_ID); - channel->setImpl(serial); - channel->begin( - serCanRead || serCanWrite, - serCanWrite, - serCanRead, - config->getString(config->serialReadF), - config->getString(config->serialWriteF), - false, - config->getBool(config->serialToN2k), - false, - false - ); - LOG_DEBUG(GwLog::LOG,"%s",channel->toString().c_str()); - theChannels.push_back(channel); - } - //tcp client bool tclEnabled=config->getBool(config->tclEnabled); channel=new GwChannel(logger,"TCPClient",TCP_CLIENT_CHANNEL_ID); @@ -180,6 +278,11 @@ void GwChannelList::begin(bool fallbackSerial){ LOG_DEBUG(GwLog::LOG,"%s",channel->toString().c_str()); logger->flush(); } +String GwChannelList::getMode(int id){ + auto it=modes.find(id); + if (it != modes.end()) return it->second; + return "UNKNOWN"; +} int GwChannelList::getJsonSize(){ int rt=0; allChannels([&](GwChannel *c){ diff --git a/lib/channel/GwChannelList.h b/lib/channel/GwChannelList.h index 1cca126..1bddfca 100644 --- a/lib/channel/GwChannelList.h +++ b/lib/channel/GwChannelList.h @@ -1,12 +1,14 @@ #pragma once #include #include +#include #include #include "GwChannel.h" #include "GwLog.h" #include "GWConfig.h" #include "GwJsonDocument.h" #include "GwApi.h" +#include //NMEA message channels #define N2K_CHANNEL_ID 0 @@ -25,10 +27,11 @@ class GwChannelList{ GwConfigHandler *config; typedef std::vector ChannelList; ChannelList theChannels; - + std::map modes; GwSocketServer *sockets; GwTcpClient *client; - String serialMode=F("NONE"); + void addSerial(HardwareSerial *stream,int id,const String &mode,int rx,int tx); + void addSerial(HardwareSerial *stream,int id,int type,int rx,int tx); public: GwChannelList(GwLog *logger, GwConfigHandler *config); typedef std::function ChannelAction; @@ -41,6 +44,6 @@ class GwChannelList{ //single channel GwChannel *getChannelById(int sourceId); void fillStatus(GwApi::Status &status); - + String getMode(int id); }; diff --git a/lib/exampletask/GwExampleTask.h b/lib/exampletask/GwExampleTask.h index 1ff2219..643c478 100644 --- a/lib/exampletask/GwExampleTask.h +++ b/lib/exampletask/GwExampleTask.h @@ -9,6 +9,11 @@ #define GWSERIAL_TX 26 #define GWSERIAL_RX 32 #define GWSERIAL_MODE "UNI" + +#define GWSERIAL2_TX 14 +#define GWSERIAL2_RX 15 +#define GWSERIAL2_MODE "BI" + #define GWBUTTON_PIN GPIO_NUM_39 #define GWBUTTON_ACTIVE LOW //if GWBUTTON_PULLUPDOWN we enable a pulup/pulldown diff --git a/lib/hardware/GwHardware.h b/lib/hardware/GwHardware.h index fa133ce..2dc67e6 100644 --- a/lib/hardware/GwHardware.h +++ b/lib/hardware/GwHardware.h @@ -13,6 +13,11 @@ */ #ifndef _GWHARDWARE_H #define _GWHARDWARE_H +#define GWSERIAL_TYPE_UNI 1 +#define GWSERIAL_TYPE_BI 2 +#define GWSERIAL_TYPE_RX 3 +#define GWSERIAL_TYPE_TX 4 + #include #include "GwUserTasks.h" @@ -117,7 +122,7 @@ #define ESP32_CAN_RX_PIN GPIO_NUM_4 //serial input only #define GWSERIAL_RX GPIO_NUM_16 -#define GWSERIAL_MODE "RX" +#define GWSERIAL_TYPE GWSERIAL_TYPE_RX #define GWBUTTON_PIN GPIO_NUM_0 #define GWBUTTON_ACTIVE LOW @@ -132,26 +137,26 @@ #ifdef SERIAL_GROOVE_485 #define GWSERIAL_TX GROOVE_PIN_1 #define GWSERIAL_RX GROOVE_PIN_2 - #define GWSERIAL_MODE "UNI" + #define GWSERIAL_TYPE GWSERIAL_TYPE_UNI #endif #ifdef SERIAL_GROOVE_232 #define GWSERIAL_TX GROOVE_PIN_1 #define GWSERIAL_RX GROOVE_PIN_2 - #define GWSERIAL_MODE "BI" + #define GWSERIAL_TYPE GWSERIAL_TYPE_BI #endif //M5 Serial (Atomic RS232 Base) #ifdef M5_SERIAL_KIT_232 #define GWSERIAL_TX BOARD_LEFT2 #define GWSERIAL_RX BOARD_LEFT1 - #define GWSERIAL_MODE "BI" + #define GWSERIAL_TYPE GWSERIAL_TYPE_BI #endif //M5 Serial (Atomic RS485 Base) #ifdef M5_SERIAL_KIT_485 #define GWSERIAL_TX BOARD_LEFT2 #define GWSERIAL_RX BOARD_LEFT1 - #define GWSERIAL_MODE "UNI" + #define GWSERIAL_TYPE GWSERIAL_TYPE_UNI #endif //can kit for M5 Atom @@ -165,5 +170,4 @@ #define ESP32_CAN_RX_PIN GROOVE_PIN_2 #endif - #endif diff --git a/lib/nmea2ktwai/Nmea2kTwai.cpp b/lib/nmea2ktwai/Nmea2kTwai.cpp index a5f0312..77c51d9 100644 --- a/lib/nmea2ktwai/Nmea2kTwai.cpp +++ b/lib/nmea2ktwai/Nmea2kTwai.cpp @@ -9,12 +9,18 @@ static const int TIMEOUT_OFFLINE=256; //# of timeouts to consider offline Nmea2kTwai::Nmea2kTwai(gpio_num_t _TxPin, gpio_num_t _RxPin, unsigned long recP, unsigned long logP): tNMEA2000(),RxPin(_RxPin),TxPin(_TxPin) { - timers.addAction(logP,[this](){logStatus();}); - timers.addAction(recP,[this](){checkRecovery();}); + if (RxPin < 0 || TxPin < 0){ + disabled=true; + } + else{ + timers.addAction(logP,[this](){logStatus();}); + timers.addAction(recP,[this](){checkRecovery();}); + } } bool Nmea2kTwai::CANSendFrame(unsigned long id, unsigned char len, const unsigned char *buf, bool wait_sent) { + if (disabled) return true; twai_message_t message; memset(&message,0,sizeof(message)); message.identifier = id; @@ -35,6 +41,10 @@ bool Nmea2kTwai::CANSendFrame(unsigned long id, unsigned char len, const unsigne } bool Nmea2kTwai::CANOpen() { + if (disabled){ + logDebug(LOG_INFO,"CAN disabled"); + return true; + } esp_err_t rt=twai_start(); if (rt != ESP_OK){ logDebug(LOG_ERR,"CANOpen failed: %x",(int)rt); @@ -47,6 +57,7 @@ bool Nmea2kTwai::CANOpen() } bool Nmea2kTwai::CANGetFrame(unsigned long &id, unsigned char &len, unsigned char *buf) { + if (disabled) return false; twai_message_t message; esp_err_t rt=twai_receive(&message,0); if (rt != ESP_OK){ @@ -68,6 +79,7 @@ bool Nmea2kTwai::CANGetFrame(unsigned long &id, unsigned char &len, unsigned cha return true; } void Nmea2kTwai::initDriver(){ + if (disabled) return; twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT(TxPin,RxPin, TWAI_MODE_NORMAL); g_config.tx_queue_len=20; twai_timing_config_t t_config = TWAI_TIMING_CONFIG_250KBITS(); @@ -84,13 +96,22 @@ void Nmea2kTwai::initDriver(){ // and you want to change size of library send frame buffer size. See e.g. NMEA2000_teensy.cpp. void Nmea2kTwai::InitCANFrameBuffers() { - initDriver(); + if (disabled){ + logDebug(LOG_INFO,"twai init - disabled"); + } + else{ + initDriver(); + } tNMEA2000::InitCANFrameBuffers(); } Nmea2kTwai::Status Nmea2kTwai::getStatus(){ twai_status_info_t state; Status rt; + if (disabled){ + rt.state=ST_DISABLED; + return rt; + } if (twai_get_status_info(&state) != ESP_OK){ return rt; } @@ -120,6 +141,7 @@ Nmea2kTwai::Status Nmea2kTwai::getStatus(){ return rt; } bool Nmea2kTwai::checkRecovery(){ + if (disabled) return false; Status canState=getStatus(); bool strt=false; if (canState.state != Nmea2kTwai::ST_RUNNING) @@ -140,6 +162,7 @@ bool Nmea2kTwai::checkRecovery(){ } void Nmea2kTwai::loop(){ + if (disabled) return; timers.loop(); } @@ -157,6 +180,7 @@ Nmea2kTwai::Status Nmea2kTwai::logStatus(){ } bool Nmea2kTwai::startRecovery(){ + if (disabled) return false; lastRecoveryStart=millis(); esp_err_t rt=twai_driver_uninstall(); if (rt != ESP_OK){ @@ -174,6 +198,7 @@ const char * Nmea2kTwai::stateStr(const Nmea2kTwai::STATE &st){ case ST_RUNNING: return "RUNNING"; case ST_STOPPED: return "STOPPED"; case ST_OFFLINE: return "OFFLINE"; + case ST_DISABLED: return "DISABLED"; } return "ERROR"; } \ No newline at end of file diff --git a/lib/nmea2ktwai/Nmea2kTwai.h b/lib/nmea2ktwai/Nmea2kTwai.h index 46e9b0c..456e633 100644 --- a/lib/nmea2ktwai/Nmea2kTwai.h +++ b/lib/nmea2ktwai/Nmea2kTwai.h @@ -12,6 +12,7 @@ class Nmea2kTwai : public tNMEA2000{ ST_BUS_OFF, ST_RECOVERING, ST_OFFLINE, + ST_DISABLED, ST_ERROR } STATE; typedef struct{ @@ -55,6 +56,7 @@ class Nmea2kTwai : public tNMEA2000{ gpio_num_t RxPin; uint32_t txTimeouts=0; GwIntervalRunner timers; + bool disabled=false; unsigned long lastRecoveryStart=0; }; diff --git a/src/main.cpp b/src/main.cpp index 5521501..b3b29b7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -126,7 +126,7 @@ class Nmea2kTwaiLog : public Nmea2kTwai{ #define ESP32_CAN_RX_PIN GPIO_NUM_NC #endif -Nmea2kTwai &NMEA2000=*(new Nmea2kTwaiLog(ESP32_CAN_TX_PIN,ESP32_CAN_RX_PIN,CAN_RECOVERY_PERIOD,&logger)); +Nmea2kTwai &NMEA2000=*(new Nmea2kTwaiLog((gpio_num_t)ESP32_CAN_TX_PIN,(gpio_num_t)ESP32_CAN_RX_PIN,CAN_RECOVERY_PERIOD,&logger)); #ifdef GWBUTTON_PIN bool fixedApPass=false; @@ -155,8 +155,8 @@ SemaphoreHandle_t mainLock; GwRequestQueue mainQueue(&logger,20); GwWebServer webserver(&logger,&mainQueue,80); -GwCounter countNMEA2KIn("count2Kin"); -GwCounter countNMEA2KOut("count2Kout"); +GwCounter countNMEA2KIn("countNMEA2000in"); +GwCounter countNMEA2KOut("countNMEA2000out"); GwIntervalRunner timers; bool checkPass(String hash){ @@ -399,6 +399,7 @@ protected: } status["n2kstate"]=NMEA2000.stateStr(driverState); status["n2knode"]=NodeAddress; + status["minUser"]=MIN_USER_TASK; //nmea0183Converter->toJson(status); countNMEA2KIn.toJson(status); countNMEA2KOut.toJson(status); @@ -427,17 +428,13 @@ class CapabilitiesRequest : public GwRequestMessage{ protected: virtual void processRequest(){ int numCapabilities=userCodeHandler.getCapabilities()->size(); - GwJsonDocument json(JSON_OBJECT_SIZE(numCapabilities*3+6)); + GwJsonDocument json(JSON_OBJECT_SIZE(numCapabilities*3+8)); for (auto it=userCodeHandler.getCapabilities()->begin(); it != userCodeHandler.getCapabilities()->end();it++){ json[it->first]=it->second; } - #ifdef GWSERIAL_MODE - String serial(F(GWSERIAL_MODE)); - #else - String serial(F("NONE")); - #endif - json["serialmode"]=serial; + json["serialmode"]=channels.getMode(SERIAL1_CHANNEL_ID); + json["serial2mode"]=channels.getMode(SERIAL2_CHANNEL_ID); #ifdef GWBUTTON_PIN json["hardwareReset"]="true"; #endif diff --git a/web/config.json b/web/config.json index cee92ae..78e3196 100644 --- a/web/config.json +++ b/web/config.json @@ -392,6 +392,128 @@ ] }, "category": "serial port" + } + , + { + "name": "serial2Dir", + "label": "serial2 direction", + "type": "list", + "default": "receive", + "list": [ + "send", + "receive", + "off" + ], + "description": "use the serial2 port to send or receive data", + "capabilities": { + "serial2mode": [ + "UNI" + ] + }, + "category": "serial2 port" + }, + { + "name": "serial2Baud", + "label": "serial2 baud rate", + "type": "list", + "default": "115200", + "description": "baud rate for the serial port 2", + "list": [ + 1200, + 2400, + 4800, + 9600, + 14400, + 19200, + 28800, + 38400, + 57600, + 115200, + 230400, + 460800 + ], + "capabilities": { + "serial2mode": [ + "RX", + "TX", + "UNI", + "BI" + ] + }, + "category": "serial2 port" + }, + { + "name": "sendSerial2", + "label": "NMEA to Serial2", + "type": "boolean", + "default": "true", + "description": "send out NMEA data on the serial port 2", + "capabilities": { + "serial2mode": [ + "TX", + "BI" + ] + }, + "category": "serial2 port" + }, + { + "name": "receiveSerial2", + "label": "NMEA from Serial2", + "type": "boolean", + "default": "true", + "description": "receive NMEA data on the serial port 2", + "capabilities": { + "serial2mode": [ + "RX", + "BI" + ] + }, + "category": "serial2 port" + }, + { + "name": "serial2ToN2k", + "label": "serial2 to NMEA2000", + "type": "boolean", + "default": "true", + "description": "convert NMEA0183 from the serial port 2 to NMEA2000", + "capabilities": { + "serial2mode": [ + "RX", + "BI", + "UNI" + ] + }, + "category": "serial2 port" + }, + { + "name": "serial2ReadF", + "label": "serial2 read Filter", + "type": "filter", + "default": "", + "description": "filter for NMEA0183 data when reading from serial2\nselect aison|aisoff, set a whitelist or a blacklist with NMEA sentences like RMC,RMB", + "capabilities": { + "serial2mode": [ + "RX", + "BI", + "UNI" + ] + }, + "category": "serial2 port" + }, + { + "name": "serial2WriteF", + "label": "serial2 write Filter", + "type": "filter", + "default": "", + "description": "filter for NMEA0183 data when writing to serial2\nselect aison|aisoff, set a whitelist or a blacklist with NMEA sentences like RMC,RMB", + "capabilities": { + "serial2mode": [ + "TX", + "BI", + "UNI" + ] + }, + "category": "serial2 port" }, { "name": "serverPort", diff --git a/web/index.js b/web/index.js index 28ea82f..10eae20 100644 --- a/web/index.js +++ b/web/index.js @@ -3,6 +3,8 @@ let lastUpdate = (new Date()).getTime(); let reloadConfig = false; let needAdminPass=true; let lastSalt=""; +let channelList={}; +let minUser=200; function addEl(type, clazz, parent, text) { let el = document.createElement(type); if (clazz) { @@ -65,22 +67,39 @@ function update() { } getJson('/api/status') .then(function (jsonData) { + let statusPage=document.getElementById('statusPageContent'); + let even=true; //first counter for (let k in jsonData) { if (k == "salt"){ lastSalt=jsonData[k]; + continue; } + if (k == "minUser"){ + minUser=parseInt(jsonData[k]); + continue; + } + if (! statusPage) continue; if (typeof (jsonData[k]) === 'object') { - for (let sk in jsonData[k]) { - let key = k + "." + sk; - if (typeof (jsonData[k][sk]) === 'object') { - //msg details - updateMsgDetails(key, jsonData[k][sk]); - } - else { - let el = document.getElementById(key); - if (el) el.textContent = jsonData[k][sk]; + if (k.indexOf('count') == 0) { + createCounterDisplay(statusPage, k.replace("count", "").replace(/in$/," in").replace(/out$/," out"), k, even); + even = !even; + for (let sk in jsonData[k]) { + let key = k + "." + sk; + if (typeof (jsonData[k][sk]) === 'object') { + //msg details + updateMsgDetails(key, 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 { let el = document.getElementById(k); @@ -286,9 +305,13 @@ function factoryReset() { .catch(function (e) { }); } function createCounterDisplay(parent,label,key,isEven){ + if (parent.querySelector("#"+key)){ + return; + } let clazz="row icon-row counter-row"; if (isEven) clazz+=" even"; let row=addEl('div',clazz,parent); + row.setAttribute("id",key); let icon=addEl('span','icon icon-more',row); addEl('span','label',row,label); let value=addEl('span','value',row,'---'); @@ -331,18 +354,7 @@ function updateMsgDetails(key, details) { },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) { let el = document.getElementById('overlayContent'); if (isHtml) { @@ -1448,13 +1460,13 @@ function createDashboard() { frame.innerHTML = ''; } function sourceName(v){ - if (v == 0) return "N2K"; - if (v == 1) return "USB"; - if (v == 2) return "SER"; - if (v == 3) return "TCPcl" - if (v >= 4 && v <= 20) return "TCPser"; - if (v >= 200) return "USER"; - return "---"; + for (let n in channelList){ + if (v >= channelList[n].id && v <= channelList[n].max){ + return n; + } + } + if (v < minUser) return "---"; + return "USER["+v+"]"; } let lastSelectList=[]; function updateDashboard(data) { @@ -1716,13 +1728,13 @@ window.addEventListener('load', function () { } }catch(e){} let statusPage=document.getElementById('statusPageContent'); - if (statusPage){ + /*if (statusPage){ let even=true; for (let c in counters){ createCounterDisplay(statusPage,counters[c],c,even); even=!even; } - } + }*/ forEl('#uploadFile',function(el){ el.addEventListener('change',function(ev){ if (ev.target.files.length < 1) return;