add extended nmea2k status

This commit is contained in:
andreas 2021-10-21 18:10:25 +02:00
parent c24e699874
commit 63eb317816
4 changed files with 94 additions and 21 deletions

View File

@ -57,5 +57,7 @@ public:
virtual void loop();
virtual ~N2kDataToNMEA0183(){}
virtual const unsigned long* handledPgns()=0;
virtual int numPgns()=0;
virtual void toJson(JsonDocument &json)=0;
};
#endif

View File

@ -90,21 +90,28 @@ private:
unsigned long LastPosSend;
unsigned long NextRMCSend;
unsigned long lastLoopTime;
std::map<long,N2KConverter> converters;
class ConverterEntry{
public:
unsigned long count=0;
N2KConverter converter;
ConverterEntry(N2KConverter cv=NULL){converter=cv;}
};
typedef std::map<long,ConverterEntry> ConverterMap;
ConverterMap converters;
/**
* register a n2k message converter
* each of the converter functions must be registered in the constructor
**/
void registerConverter(long pgn,N2KConverter converter){
converters[pgn]=converter;
ConverterEntry e(converter);
converters[pgn]=e;
}
virtual const unsigned long * handledPgns(){
logger->logString("CONV: # %d handled PGNS",(int)converters.size());
unsigned long *rt=new unsigned long[converters.size()+1];
int idx=0;
for (std::map<long,N2KConverter>::iterator it=converters.begin();
for (ConverterMap::iterator it=converters.begin();
it != converters.end();it++){
rt[idx]=it->first;
idx++;
@ -112,6 +119,26 @@ private:
rt[idx]=0;
return rt;
}
virtual void HandleMsg(const tN2kMsg &N2kMsg)
{
ConverterMap::iterator it;
it = converters.find(N2kMsg.PGN);
if (it != converters.end()){
//logger->logString("CONV: handle PGN %ld",N2kMsg.PGN);
(it->second).count++;
//call to member function - see e.g. https://isocpp.org/wiki/faq/pointers-to-members
((*this).*((it->second).converter))(N2kMsg);
return;
}
}
virtual void toJson(JsonDocument &json){
for (ConverterMap::iterator it=converters.begin();it != converters.end();it++){
json["cnv"][String(it->first)]=it->second.count;
}
}
virtual int numPgns(){
return converters.size();
}
void SetNextRMCSend() { NextRMCSend = millis() + RMCPeriod; }
//*************** the converters ***********************
@ -488,7 +515,7 @@ public:
//and register it here
//with this approach we easily have a list of all handled
//pgns
registerConverter(127250UL,&N2kToNMEA0183Functions::HandleMsg);
registerConverter(127250UL,&N2kToNMEA0183Functions::HandleHeading);
registerConverter(127258UL,&N2kToNMEA0183Functions::HandleVariation);
registerConverter(128259UL,&N2kToNMEA0183Functions::HandleBoatSpeed);
registerConverter(128267UL,&N2kToNMEA0183Functions::HandleDepth);
@ -509,16 +536,5 @@ public:
lastLoopTime = now;
SendRMC();
}
virtual void HandleMsg(const tN2kMsg &N2kMsg)
{
std::map<long,N2KConverter>::iterator it;
it = converters.find(N2kMsg.PGN);
if (it != converters.end()){
//logger->logString("CONV: handle PGN %ld",N2kMsg.PGN);
//call to member function - see e.g. https://isocpp.org/wiki/faq/pointers-to-members
((*this).*(it->second))(N2kMsg);
return;
}
}
};
#endif

View File

@ -12,7 +12,7 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#define VERSION "0.0.5"
#define VERSION "0.0.7"
#include "GwHardware.h"
#define LOG_SERIAL true
@ -101,12 +101,14 @@ void js_reset() // Wenn "http://<ip address>/gauge.min.js" aufgerufen wurde
void js_status(){
StaticJsonDocument<256> status;
int numPgns=nmea0183Converter->numPgns();
DynamicJsonDocument status(256*numPgns*30);
status["numcan"]=numCan;
status["version"]=VERSION;
status["wifiConnected"]=gwWifi.clientConnected();
status["clientIP"]=WiFi.localIP().toString();
status["numClients"]=socketServer.numClients();
nmea0183Converter->toJson(status);
String buf;
serializeJson(status,buf);
webserver.send(200,F("application/json"),buf);

View File

@ -31,8 +31,13 @@
getJson('/api/status')
.then(function(jsonData){
for (let k in jsonData){
let el=document.getElementById(k);
if (el) el.textContent=jsonData[k];
if (k == 'cnv'){
updateCanDetails(jsonData[k]);
}
else{
let el=document.getElementById(k);
if (el) el.textContent=jsonData[k];
}
}
lastUpdate=(new Date()).getTime();
})
@ -72,6 +77,36 @@
alertRestart();
})
}
function showCanDetails(on){
let el=document.getElementById('canDetails');
if (!el) return;
if (on) el.classList.add('visible');
else(el.classList).remove('visible');
}
function updateCanDetails(details){
let frame=document.getElementById('canDetails');
if (! frame) return;
for (let k in details){
let el=frame.querySelector("[data-id=\""+k+"\"] ");
if (!el){
el=document.createElement('div');
el.classList.add('row');
let cv=document.createElement('span');
cv.classList.add('label');
cv.textContent="PGN"+k;
el.appendChild(cv);
cv=document.createElement('span');
cv.classList.add('value');
cv.setAttribute('data-id',k);
cv.textContent=details[k];
el.appendChild(cv);
frame.appendChild(el);
}
else{
el.textContent=details[k];
}
}
}
window.setInterval(update,1000);
window.addEventListener('load',function(){
let buttons=document.querySelectorAll('button');
@ -79,6 +114,10 @@
let be=buttons[i];
be.onclick=window[be.id]; //assume a function with the button id
}
let cd=document.getElementById("showCanDetails");
cd.addEventListener('change',function(ev){
showCanDetails(ev.target.checked);
});
resetForm();
});
</script>
@ -112,6 +151,12 @@ span#connected.ok{
.buttons {
padding-left: 1em;
}
#canDetails{
display:none;
}
#canDetails.visible{
display: block;
}
</style>
</head>
@ -127,8 +172,16 @@ span#connected.ok{
<span class="value" id="connected"></span>
</div>
<div class="row">
<span class="label"># CAN messages</span>
<span class="label"># NMEA2000 messages</span>
<span class="value" id="numcan">---</span>
</div>
<div class="row">
<span class="label">NMEA2000 details</span>
<input type="checkbox" id="showCanDetails"></span>
</div>
<div class="row" id="canDetails">
</div>
<div class="row">
<span class="label"># TCP clients</span>