introduce NMEA filter
This commit is contained in:
parent
2028525cc9
commit
3cf67d387e
|
@ -1,5 +1,6 @@
|
|||
#include "GWConfig.h"
|
||||
#include <ArduinoJson.h>
|
||||
#include <string.h>
|
||||
|
||||
#define B(v) (v?"true":"false")
|
||||
|
||||
|
@ -114,3 +115,56 @@ int GwConfigHandler::getInt(const String name,int defaultv) const{
|
|||
if (!i) return defaultv;
|
||||
return i->asInt();
|
||||
}
|
||||
|
||||
void GwNmeaFilter::parseFilter(){
|
||||
if (isReady) return;
|
||||
int found=0;
|
||||
int last=0;
|
||||
String data=config->asString();
|
||||
while ((found = data.indexOf(',',last)) >= 0){
|
||||
String tok=data.substring(last,found);
|
||||
if (tok != ""){
|
||||
if (tok.startsWith("^")) blacklist.push_back(tok);
|
||||
else whitelist.push_back(tok);
|
||||
}
|
||||
last=found+1;
|
||||
}
|
||||
if (last < data.length()){
|
||||
String tok=data.substring(last);
|
||||
if (tok != "" && tok != "^" ){
|
||||
if (tok.startsWith("^")) blacklist.push_back(tok.substring(1));
|
||||
else whitelist.push_back(tok);
|
||||
}
|
||||
|
||||
}
|
||||
isReady=true;
|
||||
}
|
||||
|
||||
bool GwNmeaFilter::canPass(const char *buffer){
|
||||
size_t len=strlen(buffer);
|
||||
if (len < 5) return false; //invalid NMEA
|
||||
if (!isReady) parseFilter();
|
||||
bool hasWhitelist=false;
|
||||
for (auto it=blacklist.begin();it != blacklist.end();it++){
|
||||
if (buffer[0] == '$'){
|
||||
if ((strncmp(buffer,(*it).c_str(),1) == 0) &&
|
||||
(strncmp(buffer+3,(*it).c_str()+1,it->length()-1) == 0)
|
||||
) return false;
|
||||
}
|
||||
else{
|
||||
if (strncmp(buffer,(*it).c_str(),it->length()) == 0) return false;
|
||||
}
|
||||
}
|
||||
for (auto it=whitelist.begin();it != whitelist.end();it++){
|
||||
hasWhitelist=true;
|
||||
if (buffer[0] == '$'){
|
||||
if ((strncmp(buffer,(*it).c_str(),1) == 0) &&
|
||||
(strncmp(buffer+3,(*it).c_str()+1,it->length()-1) == 0)
|
||||
) return true;
|
||||
}
|
||||
else{
|
||||
if (strncmp(buffer,(*it).c_str(),it->length()) == 0) return true;
|
||||
}
|
||||
}
|
||||
return !hasWhitelist;
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef _GWCONFIGITEM_H
|
||||
#define _GWCONFIGITEM_H
|
||||
#include "WString.h"
|
||||
#include <vector>
|
||||
class GwConfigInterface{
|
||||
public:
|
||||
virtual String asString() const=0;
|
||||
|
@ -48,5 +49,20 @@ class GwConfigItem: public GwConfigInterface{
|
|||
}
|
||||
};
|
||||
|
||||
class GwNmeaFilter{
|
||||
private:
|
||||
GwConfigInterface *config=NULL;
|
||||
bool isReady=false;
|
||||
std::vector<String> whitelist;
|
||||
std::vector<String> blacklist;
|
||||
void parseFilter();
|
||||
public:
|
||||
GwNmeaFilter(GwConfigInterface *config){
|
||||
this->config=config;
|
||||
isReady=false;
|
||||
}
|
||||
bool canPass(const char *buffer);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
23
src/main.cpp
23
src/main.cpp
|
@ -92,6 +92,22 @@ GwConfigInterface *n2kFromUSB=config.getConfigItem(config.usbToN2k,true);
|
|||
GwConfigInterface *receiveSerial=config.getConfigItem(config.receiveSerial,true);
|
||||
GwConfigInterface *sendSerial=config.getConfigItem(config.sendSerial,true);
|
||||
GwConfigInterface *n2kFromSerial=config.getConfigItem(config.serialToN2k,true);
|
||||
GwNmeaFilter usbReadFilter(config.getConfigItem(config.usbReadFilter,true));
|
||||
GwNmeaFilter usbWriteFilter(config.getConfigItem(config.usbWriteFilter,true));
|
||||
GwNmeaFilter serialReadFilter(config.getConfigItem(config.serialReadFilter,true));
|
||||
GwNmeaFilter serialWriteFilter(config.getConfigItem(config.serialWriteFilter,true));
|
||||
GwNmeaFilter tcpReadFilter(config.getConfigItem(config.tcpReadFilter,true));
|
||||
GwNmeaFilter tcpWriteFilter(config.getConfigItem(config.tcpWriteFilter,true));
|
||||
|
||||
bool checkFilter(const char *buffer,int channelId,bool read){
|
||||
GwNmeaFilter *filter=NULL;
|
||||
if (channelId == USB_CHANNEL_ID) filter=read?&usbReadFilter:&usbWriteFilter;
|
||||
else if (channelId == SERIAL1_CHANNEL_ID) filter=read?&serialReadFilter:&serialWriteFilter;
|
||||
else if (channelId >= MIN_TCP_CHANNEL_ID) filter=read?&tcpReadFilter:&tcpWriteFilter;
|
||||
if (!filter) return true;
|
||||
if (filter->canPass(buffer)) return true;
|
||||
logger.logDebug(GwLog::DEBUG,"%s filter for channel %d dropped %s",(read?"read":"write"),channelId,buffer);
|
||||
}
|
||||
|
||||
bool serCanWrite=true;
|
||||
bool serCanRead=true;
|
||||
|
@ -424,13 +440,13 @@ void setup() {
|
|||
|
||||
|
||||
void sendBufferToChannels(const char * buffer, int sourceId){
|
||||
if (sendTCP->asBoolean()){
|
||||
if (sendTCP->asBoolean() && checkFilter(buffer,MIN_TCP_CHANNEL_ID,false)){
|
||||
socketServer.sendToClients(buffer,sourceId);
|
||||
}
|
||||
if (sendUsb->asBoolean()){
|
||||
if (sendUsb->asBoolean() && checkFilter(buffer,USB_CHANNEL_ID,false)){
|
||||
usbSerial->sendToClients(buffer,sourceId);
|
||||
}
|
||||
if (serial1 && serCanWrite){
|
||||
if (serial1 && serCanWrite && checkFilter(buffer,SERIAL1_CHANNEL_ID,false)){
|
||||
serial1->sendToClients(buffer,sourceId);
|
||||
}
|
||||
}
|
||||
|
@ -450,6 +466,7 @@ void SendNMEA0183Message(const tNMEA0183Msg &NMEA0183Msg, int sourceId) {
|
|||
}
|
||||
|
||||
void handleReceivedNmeaMessage(const char *buf, int sourceId){
|
||||
if (! checkFilter(buf,sourceId,true)) return;
|
||||
if ((sourceId == USB_CHANNEL_ID && n2kFromUSB->asBoolean())||
|
||||
(sourceId >= MIN_TCP_CHANNEL_ID && n2kFromTCP->asBoolean())||
|
||||
(sourceId == SERIAL1_CHANNEL_ID && n2kFromSerial->asBoolean())
|
||||
|
|
|
@ -36,6 +36,20 @@
|
|||
"default": "true",
|
||||
"description": "convert NMEA0183 from the USB port to NMEA2000"
|
||||
},
|
||||
{
|
||||
"name": "usbReadFilter",
|
||||
"label": "USB read Filter",
|
||||
"type": "filter",
|
||||
"default": "",
|
||||
"description": "filter for NMEA0183 data when reading from USB\nempty to let all data pass\nexamples:\n! \t: all AIS\n$RMB,$APB \t: only NMEA RMB and APB\n^! \t: no AIS but other NMEA"
|
||||
},
|
||||
{
|
||||
"name": "usbWriteFilter",
|
||||
"label": "USB write Filter",
|
||||
"type": "filter",
|
||||
"default": "",
|
||||
"description": "filter for NMEA0183 data when writing to USB\nempty to let all data pass\nexamples:\n! \t: all AIS\n$RMB,$APB \t: only NMEA RMB and APB\n^! \t: no AIS but other NMEA"
|
||||
},
|
||||
{
|
||||
"name": "serialDirection",
|
||||
"label": "serial direction",
|
||||
|
@ -78,6 +92,22 @@
|
|||
"description": "convert NMEA0183 from the serial port to NMEA2000",
|
||||
"capabilities":{"serialmode":["RX","BI","UNI"]}
|
||||
},
|
||||
{
|
||||
"name": "serialReadFilter",
|
||||
"label": "serial read Filter",
|
||||
"type": "filter",
|
||||
"default": "",
|
||||
"description": "filter for NMEA0183 data when reading from serial\nempty to let all data pass\nexamples:\n! \t: all AIS\n$RMB,$APB \t: only NMEA RMB and APB\n^! \t: no AIS but other NMEA",
|
||||
"capabilities":{"serialmode":["RX","BI","UNI"]}
|
||||
},
|
||||
{
|
||||
"name": "serialWriteFilter",
|
||||
"label": "serial write Filter",
|
||||
"type": "filter",
|
||||
"default": "",
|
||||
"description": "filter for NMEA0183 data when writing to serial\nempty to let all data pass\nexamples:\n! \t: all AIS\n$RMB,$APB \t: only NMEA RMB and APB\n^! \t: no AIS but other NMEA",
|
||||
"capabilities":{"serialmode":["TX","BI","UNI"]}
|
||||
},
|
||||
{
|
||||
"name": "serverPort",
|
||||
"label": "TCP port",
|
||||
|
@ -114,6 +144,20 @@
|
|||
"default": "true",
|
||||
"description": "convert NMEA0183 from TCP clients to NMEA2000"
|
||||
},
|
||||
{
|
||||
"name": "tcpReadFilter",
|
||||
"label": "TCP read Filter",
|
||||
"type": "filter",
|
||||
"default": "",
|
||||
"description": "filter for NMEA0183 data when reading from TCP\nempty to let all data pass\nexamples:\n! \t: all AIS\n$RMB,$APB \t: only NMEA RMB and APB\n^! \t: no AIS but other NMEA"
|
||||
},
|
||||
{
|
||||
"name": "tcpWriteFilter",
|
||||
"label": "TCP write Filter",
|
||||
"type": "filter",
|
||||
"default": "",
|
||||
"description": "filter for NMEA0183 data when writing to TCP\nempty to let all data pass\nexamples:\n! \t: all AIS\n$RMB,$APB \t: only NMEA RMB and APB\n^! \t: no AIS but other NMEA"
|
||||
},
|
||||
{
|
||||
"name": "sendSeasmart",
|
||||
"label": "Seasmart to TCP",
|
||||
|
|
|
@ -142,6 +142,16 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
function showOverlay(text){
|
||||
let el=document.getElementById('overlayContent');
|
||||
el.textContent=text;
|
||||
let container=document.getElementById('overlayContainer');
|
||||
container.classList.remove('hidden');
|
||||
}
|
||||
function hideOverlay(){
|
||||
let container=document.getElementById('overlayContainer');
|
||||
container.classList.add('hidden');
|
||||
}
|
||||
function checkChange(el) {
|
||||
let loaded = el.getAttribute('data-loaded');
|
||||
if (loaded !== undefined) {
|
||||
|
@ -240,7 +250,7 @@
|
|||
bt = document.createElement('button');
|
||||
bt.classList.add('infoButton');
|
||||
bt.addEventListener('click', function (ev) {
|
||||
alert(item.description);
|
||||
showOverlay(item.description);
|
||||
});
|
||||
bt.textContent = "?";
|
||||
row.appendChild(bt);
|
||||
|
@ -309,6 +319,34 @@ button.infoButton {
|
|||
display: block;
|
||||
}
|
||||
|
||||
.overlayContainer {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: #80808070;
|
||||
display: flex;
|
||||
}
|
||||
.overlayContainer.hidden{
|
||||
display: none;
|
||||
}
|
||||
div#overlay {
|
||||
margin: auto;
|
||||
background-color: white;
|
||||
padding: 0.5em;
|
||||
}
|
||||
div#overlayContent {
|
||||
padding: 0.5em;
|
||||
white-space: pre;
|
||||
}
|
||||
.overlayButtons {
|
||||
border-top: 1px solid grey;
|
||||
padding-top: 0.5em;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: end;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -362,6 +400,16 @@ button.infoButton {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="overlayContainer hidden" id="overlayContainer">
|
||||
<div id="overlay">
|
||||
<div id="overlayContent">
|
||||
AHA
|
||||
</div>
|
||||
<div class="overlayButtons">
|
||||
<button id="hideOverlay">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
Loading…
Reference in New Issue