intermediate, untested: move channel handling out of main
This commit is contained in:
parent
47fb805ee6
commit
d21e497864
|
@ -52,10 +52,12 @@ class GwChannelMessageReceiver : public GwMessageFetcher{
|
||||||
|
|
||||||
GwChannel::GwChannel(GwLog *logger,
|
GwChannel::GwChannel(GwLog *logger,
|
||||||
String name,
|
String name,
|
||||||
int sourceId){
|
int sourceId,
|
||||||
|
int maxSourceId){
|
||||||
this->logger = logger;
|
this->logger = logger;
|
||||||
this->name=name;
|
this->name=name;
|
||||||
this->sourceId=sourceId;
|
this->sourceId=sourceId;
|
||||||
|
this->maxSourceId=sourceId;
|
||||||
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;
|
||||||
|
@ -206,8 +208,16 @@ void GwChannel::parseActisense(N2kHandler handler){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GwChannel::sendActisense(const tN2kMsg &msg){
|
void GwChannel::sendActisense(const tN2kMsg &msg, int sourceId){
|
||||||
if (!enabled || ! impl || ! writeActisense || ! channelStream) return;
|
if (!enabled || ! impl || ! writeActisense || ! channelStream) return;
|
||||||
|
//currently actisense only for channels with a single source id
|
||||||
|
//so we can check it here
|
||||||
|
if (isOwnSource(sourceId)) return;
|
||||||
canSendOut(msg.PGN);
|
canSendOut(msg.PGN);
|
||||||
msg.SendInActisenseFormat(channelStream);
|
msg.SendInActisenseFormat(channelStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GwChannel::isOwnSource(int id){
|
||||||
|
if (maxSourceId < 0) return id == sourceId;
|
||||||
|
else return (id >= sourceId && id <= maxSourceId);
|
||||||
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ class GwChannel{
|
||||||
GwCounter<String> *countOut=NULL;
|
GwCounter<String> *countOut=NULL;
|
||||||
GwChannelInterface *impl;
|
GwChannelInterface *impl;
|
||||||
int sourceId=0;
|
int sourceId=0;
|
||||||
|
int maxSourceId=-1;
|
||||||
GwChannelMessageReceiver *receiver=NULL;
|
GwChannelMessageReceiver *receiver=NULL;
|
||||||
tActisenseReader *actisenseReader=NULL;
|
tActisenseReader *actisenseReader=NULL;
|
||||||
Stream *channelStream=NULL;
|
Stream *channelStream=NULL;
|
||||||
|
@ -34,7 +35,8 @@ class GwChannel{
|
||||||
GwChannel(
|
GwChannel(
|
||||||
GwLog *logger,
|
GwLog *logger,
|
||||||
String name,
|
String name,
|
||||||
int sourceId);
|
int sourceId,
|
||||||
|
int maxSourceId=-1);
|
||||||
void begin(
|
void begin(
|
||||||
bool enabled,
|
bool enabled,
|
||||||
bool nmeaOut,
|
bool nmeaOut,
|
||||||
|
@ -48,7 +50,7 @@ class GwChannel{
|
||||||
);
|
);
|
||||||
|
|
||||||
void setImpl(GwChannelInterface *impl);
|
void setImpl(GwChannelInterface *impl);
|
||||||
|
bool isOwnSource(int id);
|
||||||
void enable(bool enabled){
|
void enable(bool enabled){
|
||||||
this->enabled=enabled;
|
this->enabled=enabled;
|
||||||
}
|
}
|
||||||
|
@ -70,6 +72,6 @@ class GwChannel{
|
||||||
void sendToClients(const char *buffer, int sourceId);
|
void sendToClients(const char *buffer, int sourceId);
|
||||||
typedef std::function<void(const tN2kMsg &msg, int sourceId)> N2kHandler ;
|
typedef std::function<void(const tN2kMsg &msg, int sourceId)> N2kHandler ;
|
||||||
void parseActisense(N2kHandler handler);
|
void parseActisense(N2kHandler handler);
|
||||||
void sendActisense(const tN2kMsg &msg);
|
void sendActisense(const tN2kMsg &msg, int sourceId);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,189 @@
|
||||||
|
#include "GwChannelList.h"
|
||||||
|
#include "GwApi.h"
|
||||||
|
#include "GwHardware.h"
|
||||||
|
#include "GwSocketServer.h"
|
||||||
|
#include "GwSerial.h"
|
||||||
|
#include "GwTcpClient.h"
|
||||||
|
class GwSerialLog : public GwLogWriter{
|
||||||
|
static const size_t bufferSize=4096;
|
||||||
|
char *logBuffer=NULL;
|
||||||
|
int wp=0;
|
||||||
|
GwSerial *writer;
|
||||||
|
public:
|
||||||
|
GwSerialLog(GwSerial *writer){
|
||||||
|
this->writer=writer;
|
||||||
|
logBuffer=new char[bufferSize];
|
||||||
|
wp=0;
|
||||||
|
}
|
||||||
|
virtual ~GwSerialLog(){}
|
||||||
|
virtual void write(const char *data){
|
||||||
|
int len=strlen(data);
|
||||||
|
if ((wp+len) >= (bufferSize-1)) return;
|
||||||
|
strncpy(logBuffer+wp,data,len);
|
||||||
|
wp+=len;
|
||||||
|
logBuffer[wp]=0;
|
||||||
|
}
|
||||||
|
virtual void flush(){
|
||||||
|
size_t handled=0;
|
||||||
|
while (handled < wp){
|
||||||
|
writer->flush();
|
||||||
|
size_t rt=writer->sendToClients(logBuffer+handled,-1,true);
|
||||||
|
handled+=rt;
|
||||||
|
}
|
||||||
|
wp=0;
|
||||||
|
logBuffer[0]=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
GwChannelList::GwChannelList(GwLog *logger, GwConfigHandler *config){
|
||||||
|
this->logger=logger;
|
||||||
|
this->config=config;
|
||||||
|
}
|
||||||
|
void GwChannelList::allChannels(ChannelAction action){
|
||||||
|
for (auto it=theChannels.begin();it != theChannels.end();it++){
|
||||||
|
action(*it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void GwChannelList::begin(bool fallbackSerial){
|
||||||
|
LOG_DEBUG(GwLog::DEBUG,"GwChannelList::begin");
|
||||||
|
GwChannel *channel=NULL;
|
||||||
|
//usb
|
||||||
|
if (! fallbackSerial){
|
||||||
|
GwSerial *usb=new GwSerial(NULL,0,USB_CHANNEL_ID);
|
||||||
|
usb->setup(config->getInt(config->usbBaud),3,1);
|
||||||
|
logger->setWriter(new GwSerialLog(usb));
|
||||||
|
logger->prefix="GWSERIAL:";
|
||||||
|
channel=new GwChannel(logger,"USB",USB_CHANNEL_ID);
|
||||||
|
channel->begin(true,
|
||||||
|
config->getBool(config->sendUsb),
|
||||||
|
config->getBool(config->receiveUsb),
|
||||||
|
config->getString(config->usbReadFilter),
|
||||||
|
config->getString(config->usbWriteFilter),
|
||||||
|
false,
|
||||||
|
config->getBool(config->usbToN2k),
|
||||||
|
config->getBool(config->usbActisense),
|
||||||
|
config->getBool(config->usbActSend)
|
||||||
|
);
|
||||||
|
LOG_DEBUG(GwLog::LOG,"%s",channel->toString().c_str());
|
||||||
|
}
|
||||||
|
//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->setImpl(sockets);
|
||||||
|
channel->begin(
|
||||||
|
true,
|
||||||
|
config->getBool(config->sendTCP),
|
||||||
|
config->getBool(config->readTCP),
|
||||||
|
config->getString(config->tcpReadFilter),
|
||||||
|
config->getString(config->tcpWriteFilter),
|
||||||
|
config->getBool(config->sendSeasmart),
|
||||||
|
config->getBool(config->tcpToN2k),
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
LOG_DEBUG(GwLog::LOG,"%s",channel->toString().c_str());
|
||||||
|
theChannels.push_back(channel);
|
||||||
|
|
||||||
|
//serial 1
|
||||||
|
bool serCanRead=false;
|
||||||
|
bool serCanWrite=false;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
#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);
|
||||||
|
GwSerial *serial=new GwSerial(logger,1,SERIAL1_CHANNEL_ID,serCanRead);
|
||||||
|
int rt=serial->setup(config->getInt(config->serialBaud,115200),serialrx,serialtx);
|
||||||
|
LOG_DEBUG(GwLog::LOG,"starting serial returns %d",rt);
|
||||||
|
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
|
||||||
|
channel=new GwChannel(logger,"TCPClient",TCP_CLIENT_CHANNEL_ID);
|
||||||
|
channel->begin(
|
||||||
|
config->getBool(config->tclEnabled),
|
||||||
|
config->getBool(config->sendTCL),
|
||||||
|
config->getBool(config->readTCL),
|
||||||
|
config->getString(config->tclReadFilter),
|
||||||
|
config->getString(config->tclReadFilter),
|
||||||
|
config->getBool(config->tclSeasmart),
|
||||||
|
config->getBool(config->tclToN2k),
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
if (channel->isEnabled()){
|
||||||
|
client=new GwTcpClient(logger);
|
||||||
|
client->begin(TCP_CLIENT_CHANNEL_ID,
|
||||||
|
config->getString(config->remoteAddress),
|
||||||
|
config->getInt(config->remotePort),
|
||||||
|
channel->shouldRead()
|
||||||
|
);
|
||||||
|
channel->setImpl(client);
|
||||||
|
}
|
||||||
|
LOG_DEBUG(GwLog::LOG,"%s",channel->toString().c_str());
|
||||||
|
logger->flush();
|
||||||
|
}
|
||||||
|
int GwChannelList::getJsonSize(){
|
||||||
|
int rt=0;
|
||||||
|
allChannels([&](GwChannel *c){
|
||||||
|
rt+=c->getJsonSize();
|
||||||
|
});
|
||||||
|
return rt+20;
|
||||||
|
}
|
||||||
|
void GwChannelList::toJson(GwJsonDocument &doc){
|
||||||
|
if (sockets) doc["numClients"]=sockets->numClients();
|
||||||
|
if (client){
|
||||||
|
doc["clientCon"]=client->isConnected();
|
||||||
|
doc["clientErr"]=client->getError();
|
||||||
|
}
|
||||||
|
allChannels([&](GwChannel *c){
|
||||||
|
c->toJson(doc);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
GwChannel *GwChannelList::getChannelById(int sourceId){
|
||||||
|
for (auto it=theChannels.begin();it != theChannels.end();it++){
|
||||||
|
if ((*it)->isOwnSource(sourceId)) return *it;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
#pragma once
|
||||||
|
#include <functional>
|
||||||
|
#include <vector>
|
||||||
|
#include <WString.h>
|
||||||
|
#include "GwChannel.h"
|
||||||
|
#include "GwLog.h"
|
||||||
|
#include "GWConfig.h"
|
||||||
|
#include "GwJsonDocument.h"
|
||||||
|
|
||||||
|
//NMEA message channels
|
||||||
|
#define N2K_CHANNEL_ID 0
|
||||||
|
#define USB_CHANNEL_ID 1
|
||||||
|
#define SERIAL1_CHANNEL_ID 2
|
||||||
|
#define TCP_CLIENT_CHANNEL_ID 3
|
||||||
|
#define MIN_TCP_CHANNEL_ID 4
|
||||||
|
|
||||||
|
#define MIN_USER_TASK 200
|
||||||
|
class GwSocketServer;
|
||||||
|
class GwTcpClient;
|
||||||
|
class GwChannelList{
|
||||||
|
private:
|
||||||
|
GwLog *logger;
|
||||||
|
GwConfigHandler *config;
|
||||||
|
typedef std::vector<GwChannel *> ChannelList;
|
||||||
|
ChannelList theChannels;
|
||||||
|
|
||||||
|
GwSocketServer *sockets;
|
||||||
|
GwTcpClient *client;
|
||||||
|
String serialMode=F("NONE");
|
||||||
|
public:
|
||||||
|
GwChannelList(GwLog *logger, GwConfigHandler *config);
|
||||||
|
typedef std::function<void(GwChannel *)> ChannelAction;
|
||||||
|
void allChannels(ChannelAction action);
|
||||||
|
//initialize
|
||||||
|
void begin(bool fallbackSerial=false);
|
||||||
|
//status
|
||||||
|
int getJsonSize();
|
||||||
|
void toJson(GwJsonDocument &doc);
|
||||||
|
//single channel
|
||||||
|
GwChannel *getChannelById(int sourceId);
|
||||||
|
|
||||||
|
|
||||||
|
};
|
|
@ -29,11 +29,13 @@ uint16_t DaysSince1970 = 0;
|
||||||
|
|
||||||
class MyAisDecoder : public AIS::AisDecoder
|
class MyAisDecoder : public AIS::AisDecoder
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
int sourceId=-1;
|
||||||
private:
|
private:
|
||||||
NMEA0183DataToN2K::N2kSender sender;
|
NMEA0183DataToN2K::N2kSender sender;
|
||||||
GwLog *logger;
|
GwLog *logger;
|
||||||
void send(const tN2kMsg &msg){
|
void send(const tN2kMsg &msg){
|
||||||
(*sender)(msg);
|
(*sender)(msg,sourceId);
|
||||||
}
|
}
|
||||||
AIS::DefaultSentenceParser parser;
|
AIS::DefaultSentenceParser parser;
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -97,26 +97,26 @@ private:
|
||||||
waypointMap[wpName]=newWp;
|
waypointMap[wpName]=newWp;
|
||||||
return newWp.id;
|
return newWp.id;
|
||||||
}
|
}
|
||||||
bool send(tN2kMsg &msg,String key,unsigned long minDiff){
|
bool send(tN2kMsg &msg,String key,unsigned long minDiff,int sourceId){
|
||||||
unsigned long now=millis();
|
unsigned long now=millis();
|
||||||
unsigned long pgn=msg.PGN;
|
unsigned long pgn=msg.PGN;
|
||||||
if (key == "") key=String(msg.PGN);
|
if (key == "") key=String(msg.PGN);
|
||||||
auto it=lastSends.find(key);
|
auto it=lastSends.find(key);
|
||||||
if (it == lastSends.end()){
|
if (it == lastSends.end()){
|
||||||
lastSends[key]=now;
|
lastSends[key]=now;
|
||||||
sender(msg);
|
sender(msg,sourceId);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if ((it->second + minDiff) <= now){
|
if ((it->second + minDiff) <= now){
|
||||||
lastSends[key]=now;
|
lastSends[key]=now;
|
||||||
sender(msg);
|
sender(msg,sourceId);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
LOG_DEBUG(GwLog::DEBUG+1,"skipped n2k message %d",msg.PGN);
|
LOG_DEBUG(GwLog::DEBUG+1,"skipped n2k message %d",msg.PGN);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool send(tN2kMsg &msg, String key=""){
|
bool send(tN2kMsg &msg, int sourceId,String key=""){
|
||||||
send(msg,key,minSendInterval);
|
return send(msg,key,minSendInterval,sourceId);
|
||||||
}
|
}
|
||||||
bool updateDouble(GwBoatItem<double> *target,double v, int sourceId){
|
bool updateDouble(GwBoatItem<double> *target,double v, int sourceId){
|
||||||
if (v != NMEA0183DoubleNA){
|
if (v != NMEA0183DoubleNA){
|
||||||
|
@ -255,7 +255,7 @@ private:
|
||||||
(tN2kFluidType)(current.selector()),
|
(tN2kFluidType)(current.selector()),
|
||||||
fields[0],
|
fields[0],
|
||||||
fields[1]);
|
fields[1]);
|
||||||
send(n2kMsg, buildN2KKey(n2kMsg, current.mapping));
|
send(n2kMsg,msg.sourceId, buildN2KKey(n2kMsg, current.mapping));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case XDRBAT:
|
case XDRBAT:
|
||||||
|
@ -263,7 +263,7 @@ private:
|
||||||
{
|
{
|
||||||
SetN2kPGN127508(n2kMsg, current.mapping.instanceId,
|
SetN2kPGN127508(n2kMsg, current.mapping.instanceId,
|
||||||
fields[0], fields[1], fields[2]);
|
fields[0], fields[1], fields[2]);
|
||||||
send(n2kMsg, buildN2KKey(n2kMsg, current.mapping));
|
send(n2kMsg,msg.sourceId, buildN2KKey(n2kMsg, current.mapping));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case XDRTEMP:
|
case XDRTEMP:
|
||||||
|
@ -271,7 +271,7 @@ private:
|
||||||
SetN2kPGN130312(n2kMsg,1,current.mapping.instanceId,
|
SetN2kPGN130312(n2kMsg,1,current.mapping.instanceId,
|
||||||
(tN2kTempSource)(current.selector()),
|
(tN2kTempSource)(current.selector()),
|
||||||
fields[0],fields[1]);
|
fields[0],fields[1]);
|
||||||
send(n2kMsg,buildN2KKey(n2kMsg,current.mapping));
|
send(n2kMsg,msg.sourceId,buildN2KKey(n2kMsg,current.mapping));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case XDRHUMIDITY:
|
case XDRHUMIDITY:
|
||||||
|
@ -281,7 +281,7 @@ private:
|
||||||
fields[0],
|
fields[0],
|
||||||
fields[1]
|
fields[1]
|
||||||
);
|
);
|
||||||
send(n2kMsg,buildN2KKey(n2kMsg,current.mapping));
|
send(n2kMsg,msg.sourceId,buildN2KKey(n2kMsg,current.mapping));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case XDRPRESSURE:
|
case XDRPRESSURE:
|
||||||
|
@ -289,7 +289,7 @@ private:
|
||||||
SetN2kPGN130314(n2kMsg,1,current.mapping.instanceId,
|
SetN2kPGN130314(n2kMsg,1,current.mapping.instanceId,
|
||||||
(tN2kPressureSource)(current.selector()),
|
(tN2kPressureSource)(current.selector()),
|
||||||
fields[0]);
|
fields[0]);
|
||||||
send(n2kMsg,buildN2KKey(n2kMsg,current.mapping));
|
send(n2kMsg,msg.sourceId,buildN2KKey(n2kMsg,current.mapping));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case XDRENGINE:
|
case XDRENGINE:
|
||||||
|
@ -301,14 +301,14 @@ private:
|
||||||
fields[0], fields[1], fields[2], fields[3], fields[4],
|
fields[0], fields[1], fields[2], fields[3], fields[4],
|
||||||
fields[5], fields[6], fields[7], fromDouble(fields[8]), fromDouble(fields[9]),
|
fields[5], fields[6], fields[7], fromDouble(fields[8]), fromDouble(fields[9]),
|
||||||
tN2kEngineDiscreteStatus1(), tN2kEngineDiscreteStatus2());
|
tN2kEngineDiscreteStatus1(), tN2kEngineDiscreteStatus2());
|
||||||
send(n2kMsg, buildN2KKey(n2kMsg, current.mapping));
|
send(n2kMsg,msg.sourceId, buildN2KKey(n2kMsg, current.mapping));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
if (fillFieldList(current, fields, 13,10)){
|
if (fillFieldList(current, fields, 13,10)){
|
||||||
SetN2kPGN127488(n2kMsg,current.mapping.instanceId,
|
SetN2kPGN127488(n2kMsg,current.mapping.instanceId,
|
||||||
fields[10],fields[11],fromDouble(fields[12]));
|
fields[10],fields[11],fromDouble(fields[12]));
|
||||||
send(n2kMsg, buildN2KKey(n2kMsg, current.mapping));
|
send(n2kMsg,msg.sourceId, buildN2KKey(n2kMsg, current.mapping));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -334,7 +334,7 @@ private:
|
||||||
mode=xteMode(*modeChar);
|
mode=xteMode(*modeChar);
|
||||||
}
|
}
|
||||||
SetN2kXTE(n2kMsg,1,mode,false,rmb.xte);
|
SetN2kXTE(n2kMsg,1,mode,false,rmb.xte);
|
||||||
send(n2kMsg);
|
send(n2kMsg,msg.sourceId);
|
||||||
}
|
}
|
||||||
uint8_t destinationId=getWaypointId(rmb.destID);
|
uint8_t destinationId=getWaypointId(rmb.destID);
|
||||||
uint8_t sourceId=getWaypointId(rmb.originID);
|
uint8_t sourceId=getWaypointId(rmb.originID);
|
||||||
|
@ -357,10 +357,10 @@ private:
|
||||||
rmb.longitude,
|
rmb.longitude,
|
||||||
rmb.vmg
|
rmb.vmg
|
||||||
);
|
);
|
||||||
send(n2kMsg);
|
send(n2kMsg,msg.sourceId);
|
||||||
SetN2kPGN129285(n2kMsg,sourceId,1,1,true,true,"default");
|
SetN2kPGN129285(n2kMsg,sourceId,1,1,true,true,"default");
|
||||||
AppendN2kPGN129285(n2kMsg,destinationId,rmb.destID,rmb.latitude,rmb.longitude);
|
AppendN2kPGN129285(n2kMsg,destinationId,rmb.destID,rmb.latitude,rmb.longitude);
|
||||||
send(n2kMsg);
|
send(n2kMsg,msg.sourceId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void convertRMC(const SNMEA0183Msg &msg)
|
void convertRMC(const SNMEA0183Msg &msg)
|
||||||
|
@ -382,25 +382,26 @@ private:
|
||||||
{
|
{
|
||||||
|
|
||||||
SetN2kSystemTime(n2kMsg, 1, GpsDate, GpsTime);
|
SetN2kSystemTime(n2kMsg, 1, GpsDate, GpsTime);
|
||||||
send(n2kMsg);
|
send(n2kMsg,msg.sourceId);
|
||||||
}
|
}
|
||||||
if (UD(Latitude) &&
|
if (UD(Latitude) &&
|
||||||
UD(Longitude)){
|
UD(Longitude)){
|
||||||
SetN2kLatLonRapid(n2kMsg,Latitude,Longitude);
|
SetN2kLatLonRapid(n2kMsg,Latitude,Longitude);
|
||||||
send(n2kMsg);
|
send(n2kMsg,msg.sourceId);
|
||||||
}
|
}
|
||||||
if (UD(COG) && UD(SOG)){
|
if (UD(COG) && UD(SOG)){
|
||||||
SetN2kCOGSOGRapid(n2kMsg,1,N2khr_true,COG,SOG);
|
SetN2kCOGSOGRapid(n2kMsg,1,N2khr_true,COG,SOG);
|
||||||
send(n2kMsg);
|
send(n2kMsg,msg.sourceId);
|
||||||
}
|
}
|
||||||
if (UD(Variation)){
|
if (UD(Variation)){
|
||||||
SetN2kMagneticVariation(n2kMsg,1,N2kmagvar_Calc,
|
SetN2kMagneticVariation(n2kMsg,1,N2kmagvar_Calc,
|
||||||
getUint32(boatData->GpsDate), Variation);
|
getUint32(boatData->GpsDate), Variation);
|
||||||
send(n2kMsg);
|
send(n2kMsg,msg.sourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
void convertAIVDX(const SNMEA0183Msg &msg){
|
void convertAIVDX(const SNMEA0183Msg &msg){
|
||||||
|
aisDecoder->sourceId=msg.sourceId;
|
||||||
aisDecoder->handleMessage(msg.line);
|
aisDecoder->handleMessage(msg.line);
|
||||||
}
|
}
|
||||||
void convertMWV(const SNMEA0183Msg &msg){
|
void convertMWV(const SNMEA0183Msg &msg){
|
||||||
|
@ -434,7 +435,7 @@ private:
|
||||||
}
|
}
|
||||||
if (shouldSend){
|
if (shouldSend){
|
||||||
SetN2kWindSpeed(n2kMsg,1,WindSpeed,WindAngle,n2kRef);
|
SetN2kWindSpeed(n2kMsg,1,WindSpeed,WindAngle,n2kRef);
|
||||||
send(n2kMsg,String(n2kMsg.PGN)+String((int)n2kRef));
|
send(n2kMsg,msg.sourceId,String(n2kMsg.PGN)+String((int)n2kRef));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void convertVWR(const SNMEA0183Msg &msg)
|
void convertVWR(const SNMEA0183Msg &msg)
|
||||||
|
@ -475,7 +476,7 @@ private:
|
||||||
if (shouldSend)
|
if (shouldSend)
|
||||||
{
|
{
|
||||||
SetN2kWindSpeed(n2kMsg, 1, WindSpeed, WindAngle, N2kWind_Apparent);
|
SetN2kWindSpeed(n2kMsg, 1, WindSpeed, WindAngle, N2kWind_Apparent);
|
||||||
send(n2kMsg,String(n2kMsg.PGN)+String((int)N2kWind_Apparent));
|
send(n2kMsg,msg.sourceId,String(n2kMsg.PGN)+String((int)N2kWind_Apparent));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -519,11 +520,11 @@ private:
|
||||||
if (shouldSend)
|
if (shouldSend)
|
||||||
{
|
{
|
||||||
SetN2kWindSpeed(n2kMsg, 1, WindSpeed, WindAngle, N2kWind_True_North);
|
SetN2kWindSpeed(n2kMsg, 1, WindSpeed, WindAngle, N2kWind_True_North);
|
||||||
send(n2kMsg,String(n2kMsg.PGN)+String((int)N2kWind_True_North));
|
send(n2kMsg,msg.sourceId,String(n2kMsg.PGN)+String((int)N2kWind_True_North));
|
||||||
}
|
}
|
||||||
if (WindAngleMagnetic != NMEA0183DoubleNA && shouldSend){
|
if (WindAngleMagnetic != NMEA0183DoubleNA && shouldSend){
|
||||||
SetN2kWindSpeed(n2kMsg, 1, WindSpeed, WindAngleMagnetic, N2kWind_Magnetic);
|
SetN2kWindSpeed(n2kMsg, 1, WindSpeed, WindAngleMagnetic, N2kWind_Magnetic);
|
||||||
send(n2kMsg,String(n2kMsg.PGN)+String((int)N2kWind_Magnetic));
|
send(n2kMsg,msg.sourceId,String(n2kMsg.PGN)+String((int)N2kWind_Magnetic));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -540,7 +541,7 @@ private:
|
||||||
boatData->Variation->getDataWithDefault(N2kDoubleNA),
|
boatData->Variation->getDataWithDefault(N2kDoubleNA),
|
||||||
boatData->Deviation->getDataWithDefault(N2kDoubleNA)
|
boatData->Deviation->getDataWithDefault(N2kDoubleNA)
|
||||||
);
|
);
|
||||||
send(n2kMsg);
|
send(n2kMsg,msg.sourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void convertHDT(const SNMEA0183Msg &msg){
|
void convertHDT(const SNMEA0183Msg &msg){
|
||||||
|
@ -553,7 +554,7 @@ private:
|
||||||
if (! UD(Heading)) return;
|
if (! UD(Heading)) return;
|
||||||
tN2kMsg n2kMsg;
|
tN2kMsg n2kMsg;
|
||||||
SetN2kTrueHeading(n2kMsg,1,Heading);
|
SetN2kTrueHeading(n2kMsg,1,Heading);
|
||||||
send(n2kMsg);
|
send(n2kMsg,msg.sourceId);
|
||||||
}
|
}
|
||||||
void convertHDG(const SNMEA0183Msg &msg){
|
void convertHDG(const SNMEA0183Msg &msg){
|
||||||
double MagneticHeading=NMEA0183DoubleNA;
|
double MagneticHeading=NMEA0183DoubleNA;
|
||||||
|
@ -584,7 +585,7 @@ private:
|
||||||
UD(Deviation);
|
UD(Deviation);
|
||||||
tN2kMsg n2kMsg;
|
tN2kMsg n2kMsg;
|
||||||
SetN2kMagneticHeading(n2kMsg,1,MagneticHeading,Deviation,Variation);
|
SetN2kMagneticHeading(n2kMsg,1,MagneticHeading,Deviation,Variation);
|
||||||
send(n2kMsg);
|
send(n2kMsg,msg.sourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void convertDPT(const SNMEA0183Msg &msg){
|
void convertDPT(const SNMEA0183Msg &msg){
|
||||||
|
@ -612,7 +613,7 @@ private:
|
||||||
if (! boatData->DepthTransducer->update(DepthBelowTransducer)) return;
|
if (! boatData->DepthTransducer->update(DepthBelowTransducer)) return;
|
||||||
tN2kMsg n2kMsg;
|
tN2kMsg n2kMsg;
|
||||||
SetN2kWaterDepth(n2kMsg,1,DepthBelowTransducer,Offset);
|
SetN2kWaterDepth(n2kMsg,1,DepthBelowTransducer,Offset);
|
||||||
send(n2kMsg,String(n2kMsg.PGN)+String((Offset != N2kDoubleNA)?1:0));
|
send(n2kMsg,msg.sourceId,String(n2kMsg.PGN)+String((Offset != N2kDoubleNA)?1:0));
|
||||||
}
|
}
|
||||||
typedef enum {
|
typedef enum {
|
||||||
DBS,
|
DBS,
|
||||||
|
@ -647,7 +648,7 @@ private:
|
||||||
if (! boatData->DepthTransducer->update(Depth,msg.sourceId)) return;
|
if (! boatData->DepthTransducer->update(Depth,msg.sourceId)) return;
|
||||||
tN2kMsg n2kMsg;
|
tN2kMsg n2kMsg;
|
||||||
SetN2kWaterDepth(n2kMsg,1,Depth,N2kDoubleNA);
|
SetN2kWaterDepth(n2kMsg,1,Depth,N2kDoubleNA);
|
||||||
send(n2kMsg,String(n2kMsg.PGN)+String(0));
|
send(n2kMsg,msg.sourceId,String(n2kMsg.PGN)+String(0));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//we can only send if we have a valid depth beloww tranducer
|
//we can only send if we have a valid depth beloww tranducer
|
||||||
|
@ -667,7 +668,7 @@ private:
|
||||||
}
|
}
|
||||||
tN2kMsg n2kMsg;
|
tN2kMsg n2kMsg;
|
||||||
SetN2kWaterDepth(n2kMsg,1,Depth,offset);
|
SetN2kWaterDepth(n2kMsg,1,Depth,offset);
|
||||||
send(n2kMsg,String(n2kMsg.PGN)+String((offset != N2kDoubleNA)?1:0));
|
send(n2kMsg,msg.sourceId,(n2kMsg.PGN)+String((offset != N2kDoubleNA)?1:0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -694,7 +695,7 @@ private:
|
||||||
tN2kMsg n2kMsg;
|
tN2kMsg n2kMsg;
|
||||||
if (! UD(RudderPosition)) return;
|
if (! UD(RudderPosition)) return;
|
||||||
SetN2kRudder(n2kMsg,RudderPosition);
|
SetN2kRudder(n2kMsg,RudderPosition);
|
||||||
send(n2kMsg);
|
send(n2kMsg,msg.sourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -711,7 +712,7 @@ private:
|
||||||
if (MagneticHeading == NMEA0183DoubleNA) MagneticHeading=N2kDoubleNA;
|
if (MagneticHeading == NMEA0183DoubleNA) MagneticHeading=N2kDoubleNA;
|
||||||
tN2kMsg n2kMsg;
|
tN2kMsg n2kMsg;
|
||||||
SetN2kBoatSpeed(n2kMsg,1,STW);
|
SetN2kBoatSpeed(n2kMsg,1,STW);
|
||||||
send(n2kMsg);
|
send(n2kMsg,msg.sourceId);
|
||||||
|
|
||||||
}
|
}
|
||||||
void convertVTG(const SNMEA0183Msg &msg){
|
void convertVTG(const SNMEA0183Msg &msg){
|
||||||
|
@ -727,7 +728,7 @@ private:
|
||||||
tN2kMsg n2kMsg;
|
tN2kMsg n2kMsg;
|
||||||
//TODO: maybe use MCOG if no COG?
|
//TODO: maybe use MCOG if no COG?
|
||||||
SetN2kCOGSOGRapid(n2kMsg,1,N2khr_true,COG,SOG);
|
SetN2kCOGSOGRapid(n2kMsg,1,N2khr_true,COG,SOG);
|
||||||
send(n2kMsg);
|
send(n2kMsg,msg.sourceId);
|
||||||
}
|
}
|
||||||
void convertZDA(const SNMEA0183Msg &msg){
|
void convertZDA(const SNMEA0183Msg &msg){
|
||||||
time_t DateTime;
|
time_t DateTime;
|
||||||
|
@ -751,10 +752,10 @@ private:
|
||||||
tN2kMsg n2kMsg;
|
tN2kMsg n2kMsg;
|
||||||
if (timezoneValid){
|
if (timezoneValid){
|
||||||
SetN2kLocalOffset(n2kMsg,DaysSince1970,GpsTime,Timezone);
|
SetN2kLocalOffset(n2kMsg,DaysSince1970,GpsTime,Timezone);
|
||||||
send(n2kMsg);
|
send(n2kMsg,msg.sourceId);
|
||||||
}
|
}
|
||||||
SetN2kSystemTime(n2kMsg,1,DaysSince1970,GpsTime);
|
SetN2kSystemTime(n2kMsg,1,DaysSince1970,GpsTime);
|
||||||
send(n2kMsg);
|
send(n2kMsg,msg.sourceId);
|
||||||
}
|
}
|
||||||
void convertGGA(const SNMEA0183Msg &msg){
|
void convertGGA(const SNMEA0183Msg &msg){
|
||||||
double GPSTime=NMEA0183DoubleNA;
|
double GPSTime=NMEA0183DoubleNA;
|
||||||
|
@ -788,7 +789,7 @@ private:
|
||||||
SatelliteCount, HDOP, boatData->PDOP->getDataWithDefault(N2kDoubleNA), 0,
|
SatelliteCount, HDOP, boatData->PDOP->getDataWithDefault(N2kDoubleNA), 0,
|
||||||
0, N2kGNSSt_GPS, DGPSReferenceStationID,
|
0, N2kGNSSt_GPS, DGPSReferenceStationID,
|
||||||
DGPSAge);
|
DGPSAge);
|
||||||
send(n2kMsg);
|
send(n2kMsg,msg.sourceId);
|
||||||
}
|
}
|
||||||
void convertGSA(const SNMEA0183Msg &msg){
|
void convertGSA(const SNMEA0183Msg &msg){
|
||||||
if (msg.FieldCount() < 17)
|
if (msg.FieldCount() < 17)
|
||||||
|
@ -819,7 +820,7 @@ private:
|
||||||
if (!updateDouble(boatData->VDOP,VDOP,msg.sourceId)) return;
|
if (!updateDouble(boatData->VDOP,VDOP,msg.sourceId)) return;
|
||||||
}
|
}
|
||||||
SetN2kGNSSDOPData(n2kMsg,1,rmode,mode,HDOP,VDOP,N2kDoubleNA);
|
SetN2kGNSSDOPData(n2kMsg,1,rmode,mode,HDOP,VDOP,N2kDoubleNA);
|
||||||
send(n2kMsg);
|
send(n2kMsg,msg.sourceId);
|
||||||
}
|
}
|
||||||
void convertGSV(const SNMEA0183Msg &msg){
|
void convertGSV(const SNMEA0183Msg &msg){
|
||||||
if (msg.FieldCount() < 7){
|
if (msg.FieldCount() < 7){
|
||||||
|
@ -867,7 +868,7 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (hasInfos){
|
if (hasInfos){
|
||||||
send(n2kMsg);
|
send(n2kMsg,msg.sourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -885,7 +886,7 @@ private:
|
||||||
if (! updateDouble(boatData->GpsTime,GLL.GPSTime,msg.sourceId)) return;
|
if (! updateDouble(boatData->GpsTime,GLL.GPSTime,msg.sourceId)) return;
|
||||||
tN2kMsg n2kMsg;
|
tN2kMsg n2kMsg;
|
||||||
SetN2kLatLonRapid(n2kMsg,GLL.latitude,GLL.longitude);
|
SetN2kLatLonRapid(n2kMsg,GLL.latitude,GLL.longitude);
|
||||||
send(n2kMsg);
|
send(n2kMsg,msg.sourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void convertROT(const SNMEA0183Msg &msg){
|
void convertROT(const SNMEA0183Msg &msg){
|
||||||
|
@ -897,7 +898,7 @@ private:
|
||||||
if (! updateDouble(boatData->ROT,ROT,msg.sourceId)) return;
|
if (! updateDouble(boatData->ROT,ROT,msg.sourceId)) return;
|
||||||
tN2kMsg n2kMsg;
|
tN2kMsg n2kMsg;
|
||||||
SetN2kRateOfTurn(n2kMsg,1,ROT);
|
SetN2kRateOfTurn(n2kMsg,1,ROT);
|
||||||
send(n2kMsg);
|
send(n2kMsg,msg.sourceId);
|
||||||
}
|
}
|
||||||
void convertXTE(const SNMEA0183Msg &msg){
|
void convertXTE(const SNMEA0183Msg &msg){
|
||||||
if (msg.FieldCount() < 6){
|
if (msg.FieldCount() < 6){
|
||||||
|
@ -916,7 +917,7 @@ private:
|
||||||
tN2kMsg n2kMsg;
|
tN2kMsg n2kMsg;
|
||||||
tN2kXTEMode mode=xteMode(msg.Field(5)[0]);
|
tN2kXTEMode mode=xteMode(msg.Field(5)[0]);
|
||||||
SetN2kXTE(n2kMsg,1,mode,false,xte);
|
SetN2kXTE(n2kMsg,1,mode,false,xte);
|
||||||
send(n2kMsg);
|
send(n2kMsg,msg.sourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
//shortcut for lambda converters
|
//shortcut for lambda converters
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
class NMEA0183DataToN2K{
|
class NMEA0183DataToN2K{
|
||||||
public:
|
public:
|
||||||
typedef bool (*N2kSender)(const tN2kMsg &msg);
|
typedef bool (*N2kSender)(const tN2kMsg &msg,int sourceId);
|
||||||
protected:
|
protected:
|
||||||
GwLog * logger;
|
GwLog * logger;
|
||||||
GwBoatData *boatData;
|
GwBoatData *boatData;
|
||||||
|
|
|
@ -19,15 +19,22 @@ void GwTcpClient::startConnection()
|
||||||
{
|
{
|
||||||
//TODO
|
//TODO
|
||||||
state = C_INITIALIZED;
|
state = C_INITIALIZED;
|
||||||
|
error="";
|
||||||
connectStart=millis();
|
connectStart=millis();
|
||||||
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
if (sockfd < 0) {
|
if (sockfd < 0) {
|
||||||
|
error="unable to create socket";
|
||||||
LOG_DEBUG(GwLog::ERROR,"unable to create socket: %d", errno);
|
LOG_DEBUG(GwLog::ERROR,"unable to create socket: %d", errno);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fcntl( sockfd, F_SETFL, fcntl( sockfd, F_GETFL, 0 ) | O_NONBLOCK );
|
fcntl( sockfd, F_SETFL, fcntl( sockfd, F_GETFL, 0 ) | O_NONBLOCK );
|
||||||
|
IPAddress addr;
|
||||||
uint32_t ip_addr = this->remoteAddress;
|
if (! addr.fromString(remoteAddress)){
|
||||||
|
error="invalid ip "+remoteAddress;
|
||||||
|
LOG_DEBUG(GwLog::ERROR,"%s",error.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint32_t ip_addr = addr;
|
||||||
struct sockaddr_in serveraddr;
|
struct sockaddr_in serveraddr;
|
||||||
memset((char *) &serveraddr, 0, sizeof(serveraddr));
|
memset((char *) &serveraddr, 0, sizeof(serveraddr));
|
||||||
serveraddr.sin_family = AF_INET;
|
serveraddr.sin_family = AF_INET;
|
||||||
|
@ -36,6 +43,7 @@ void GwTcpClient::startConnection()
|
||||||
int res = lwip_connect_r(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr));
|
int res = lwip_connect_r(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr));
|
||||||
if (res < 0 ) {
|
if (res < 0 ) {
|
||||||
if (errno != EINPROGRESS){
|
if (errno != EINPROGRESS){
|
||||||
|
error=String("connect error ")+String(strerror(errno));
|
||||||
LOG_DEBUG(GwLog::ERROR,"connect on fd %d, errno: %d, \"%s\"", sockfd, errno, strerror(errno));
|
LOG_DEBUG(GwLog::ERROR,"connect on fd %d, errno: %d, \"%s\"", sockfd, errno, strerror(errno));
|
||||||
close(sockfd);
|
close(sockfd);
|
||||||
return;
|
return;
|
||||||
|
@ -56,7 +64,7 @@ void GwTcpClient::checkConnection()
|
||||||
}
|
}
|
||||||
if (state == C_INITIALIZED){
|
if (state == C_INITIALIZED){
|
||||||
if ((now - connectStart) > CON_TIMEOUT){
|
if ((now - connectStart) > CON_TIMEOUT){
|
||||||
LOG_DEBUG(GwLog::LOG,"retry connect to %s",remoteAddress.toString().c_str());
|
LOG_DEBUG(GwLog::LOG,"retry connect to %s",remoteAddress.c_str());
|
||||||
startConnection();
|
startConnection();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -73,13 +81,15 @@ void GwTcpClient::checkConnection()
|
||||||
tv.tv_usec = 0;
|
tv.tv_usec = 0;
|
||||||
int res = select(sockfd + 1, nullptr, &fdset, nullptr, &tv);
|
int res = select(sockfd + 1, nullptr, &fdset, nullptr, &tv);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
|
error=String("select error ")+String(strerror(errno));
|
||||||
LOG_DEBUG(GwLog::ERROR,"select on fd %d, errno: %d, \"%s\"", sockfd, errno, strerror(errno));
|
LOG_DEBUG(GwLog::ERROR,"select on fd %d, errno: %d, \"%s\"", sockfd, errno, strerror(errno));
|
||||||
connection->stop();
|
connection->stop();
|
||||||
return;
|
return;
|
||||||
} else if (res == 0) {
|
} else if (res == 0) {
|
||||||
//still connecting
|
//still connecting
|
||||||
if ((now - connectStart) >= CON_TIMEOUT){
|
if ((now - connectStart) >= CON_TIMEOUT){
|
||||||
LOG_DEBUG(GwLog::ERROR,"connect timeout to %s, retry",remoteAddress.toString().c_str());
|
error="connect timeout";
|
||||||
|
LOG_DEBUG(GwLog::ERROR,"connect timeout to %s, retry",remoteAddress.c_str());
|
||||||
connection->stop();
|
connection->stop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -89,17 +99,19 @@ void GwTcpClient::checkConnection()
|
||||||
res = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &sockerr, &len);
|
res = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &sockerr, &len);
|
||||||
|
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
|
error="getsockopt failed";
|
||||||
LOG_DEBUG(GwLog::ERROR,"getsockopt on fd %d, errno: %d, \"%s\"", sockfd, errno, strerror(errno));
|
LOG_DEBUG(GwLog::ERROR,"getsockopt on fd %d, errno: %d, \"%s\"", sockfd, errno, strerror(errno));
|
||||||
connection->stop();
|
connection->stop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (sockerr != 0) {
|
if (sockerr != 0) {
|
||||||
|
error=String("socket error ")+String(strerror(sockerr));
|
||||||
LOG_DEBUG(GwLog::ERROR,"socket error on fd %d, errno: %d, \"%s\"", sockfd, sockerr, strerror(sockerr));
|
LOG_DEBUG(GwLog::ERROR,"socket error on fd %d, errno: %d, \"%s\"", sockfd, sockerr, strerror(sockerr));
|
||||||
connection->stop();
|
connection->stop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LOG_DEBUG(GwLog::LOG,"connected to %s",remoteAddress.toString().c_str());
|
LOG_DEBUG(GwLog::LOG,"connected to %s",remoteAddress.c_str());
|
||||||
state=C_CONNECTED;
|
state=C_CONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,7 +123,7 @@ GwTcpClient::~GwTcpClient(){
|
||||||
if (connection)
|
if (connection)
|
||||||
delete connection;
|
delete connection;
|
||||||
}
|
}
|
||||||
void GwTcpClient::begin(int sourceId,IPAddress address, uint16_t port,bool allowRead)
|
void GwTcpClient::begin(int sourceId,String address, uint16_t port,bool allowRead)
|
||||||
{
|
{
|
||||||
stop();
|
stop();
|
||||||
this->sourceId=sourceId;
|
this->sourceId=sourceId;
|
||||||
|
@ -151,14 +163,18 @@ void GwTcpClient::loop(bool handleRead,bool handleWrite)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GwTcpClient::sendToClients(const char *buf,int sourceId){
|
size_t GwTcpClient::sendToClients(const char *buf,int sourceId, bool partialWrite){
|
||||||
if (sourceId == this->sourceId) return;
|
if (sourceId == this->sourceId) return 0;
|
||||||
|
if (state != C_CONNECTED) return 0;
|
||||||
|
if (! connection->hasClient()) return 0;
|
||||||
|
size_t len=strlen(buf);
|
||||||
|
if (connection->enqueue((uint8_t*)buf,len)){
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
void GwTcpClient::readMessages(GwMessageFetcher *writer){
|
||||||
if (state != C_CONNECTED) return;
|
if (state != C_CONNECTED) return;
|
||||||
if (! connection->hasClient()) return;
|
if (! connection->hasClient()) return;
|
||||||
connection->enqueue((uint8_t*)buf,strlen(buf));
|
connection->messagesFromBuffer(writer);
|
||||||
}
|
|
||||||
bool GwTcpClient::readMessages(GwMessageFetcher *writer){
|
|
||||||
if (state != C_CONNECTED) return false;
|
|
||||||
if (! connection->hasClient()) return false;
|
|
||||||
return connection->messagesFromBuffer(writer);
|
|
||||||
}
|
}
|
|
@ -1,15 +1,17 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "GwSocketConnection.h"
|
#include "GwSocketConnection.h"
|
||||||
class GwTcpClient
|
#include "GwChannelInterface.h"
|
||||||
|
class GwTcpClient : public GwChannelInterface
|
||||||
{
|
{
|
||||||
static const unsigned long CON_TIMEOUT=10;
|
static const unsigned long CON_TIMEOUT=10;
|
||||||
GwSocketConnection *connection = NULL;
|
GwSocketConnection *connection = NULL;
|
||||||
IPAddress remoteAddress;
|
String remoteAddress;
|
||||||
uint16_t port = 0;
|
uint16_t port = 0;
|
||||||
unsigned long connectStart=0;
|
unsigned long connectStart=0;
|
||||||
GwLog *logger;
|
GwLog *logger;
|
||||||
int sourceId;
|
int sourceId;
|
||||||
bool configured=false;
|
bool configured=false;
|
||||||
|
String error;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef enum
|
typedef enum
|
||||||
|
@ -30,9 +32,10 @@ private:
|
||||||
public:
|
public:
|
||||||
GwTcpClient(GwLog *logger);
|
GwTcpClient(GwLog *logger);
|
||||||
~GwTcpClient();
|
~GwTcpClient();
|
||||||
void begin(int sourceId,IPAddress address, uint16_t port,bool allowRead);
|
void begin(int sourceId,String address, uint16_t port,bool allowRead);
|
||||||
void loop(bool handleRead=true,bool handleWrite=true);
|
virtual void loop(bool handleRead=true,bool handleWrite=true);
|
||||||
void sendToClients(const char *buf,int sourceId);
|
virtual size_t sendToClients(const char *buf,int sourceId, bool partialWrite=false);
|
||||||
bool readMessages(GwMessageFetcher *writer);
|
virtual void readMessages(GwMessageFetcher *writer);
|
||||||
bool isConnected();
|
bool isConnected();
|
||||||
|
String getError(){return error;}
|
||||||
};
|
};
|
283
src/main.cpp
283
src/main.cpp
|
@ -63,16 +63,9 @@ const unsigned long HEAP_REPORT_TIME=2000; //set to 0 to disable heap reporting
|
||||||
#include "GwUpdate.h"
|
#include "GwUpdate.h"
|
||||||
#include "GwTcpClient.h"
|
#include "GwTcpClient.h"
|
||||||
#include "GwChannel.h"
|
#include "GwChannel.h"
|
||||||
|
#include "GwChannelList.h"
|
||||||
|
|
||||||
|
|
||||||
//NMEA message channels
|
|
||||||
#define N2K_CHANNEL_ID 0
|
|
||||||
#define USB_CHANNEL_ID 1
|
|
||||||
#define SERIAL1_CHANNEL_ID 2
|
|
||||||
#define TCP_CLIENT_CHANNEL_ID 3
|
|
||||||
#define MIN_TCP_CHANNEL_ID 4
|
|
||||||
|
|
||||||
#define MIN_USER_TASK 200
|
|
||||||
|
|
||||||
#define MAX_NMEA2000_MESSAGE_SEASMART_SIZE 500
|
#define MAX_NMEA2000_MESSAGE_SEASMART_SIZE 500
|
||||||
#define MAX_NMEA0183_MESSAGE_SIZE 150 // For AIS
|
#define MAX_NMEA0183_MESSAGE_SIZE 150 // For AIS
|
||||||
|
@ -112,7 +105,7 @@ bool fixedApPass=false;
|
||||||
bool fixedApPass=true;
|
bool fixedApPass=true;
|
||||||
#endif
|
#endif
|
||||||
GwWifi gwWifi(&config,&logger,fixedApPass);
|
GwWifi gwWifi(&config,&logger,fixedApPass);
|
||||||
GwSocketServer socketServer(&config,&logger,MIN_TCP_CHANNEL_ID);
|
GwChannelList channels(&logger,&config);
|
||||||
GwBoatData boatData(&logger);
|
GwBoatData boatData(&logger);
|
||||||
GwXDRMappings xdrMappings(&logger,&config);
|
GwXDRMappings xdrMappings(&logger,&config);
|
||||||
|
|
||||||
|
@ -131,23 +124,6 @@ GwWebServer webserver(&logger,&mainQueue,80);
|
||||||
GwCounter<unsigned long> countNMEA2KIn("count2Kin");
|
GwCounter<unsigned long> countNMEA2KIn("count2Kin");
|
||||||
GwCounter<unsigned long> countNMEA2KOut("count2Kout");
|
GwCounter<unsigned long> countNMEA2KOut("count2Kout");
|
||||||
|
|
||||||
GwChannel usbChannel(&logger,"USB",USB_CHANNEL_ID);
|
|
||||||
GwChannel tcpChannel(&logger,"TCPServer",MIN_TCP_CHANNEL_ID);
|
|
||||||
GwChannel serialChannel(&logger,"SER",SERIAL1_CHANNEL_ID);
|
|
||||||
GwChannel tclChannel(&logger,"TCPClient",TCP_CLIENT_CHANNEL_ID);
|
|
||||||
|
|
||||||
GwChannel *allChannels[]={&usbChannel,&tcpChannel,&serialChannel,&tclChannel};
|
|
||||||
const int numChannels=sizeof(allChannels)/sizeof(GwChannel*);
|
|
||||||
|
|
||||||
GwChannel * channelFromSource(int source){
|
|
||||||
if (source == USB_CHANNEL_ID) return &usbChannel;
|
|
||||||
if (source == SERIAL1_CHANNEL_ID) return &serialChannel;
|
|
||||||
if (source == TCP_CLIENT_CHANNEL_ID) return &tclChannel;
|
|
||||||
if (source >= MIN_TCP_CHANNEL_ID && source < MIN_USER_TASK) return &tcpChannel;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
unsigned long saltBase=esp_random();
|
unsigned long saltBase=esp_random();
|
||||||
|
|
||||||
char hv(uint8_t nibble){
|
char hv(uint8_t nibble){
|
||||||
|
@ -190,58 +166,38 @@ bool checkPass(String hash){
|
||||||
}
|
}
|
||||||
|
|
||||||
GwUpdate updater(&logger,&webserver,&checkPass);
|
GwUpdate updater(&logger,&webserver,&checkPass);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//configs that we need in main
|
|
||||||
|
|
||||||
|
|
||||||
GwConfigInterface *systemName=config.getConfigItem(config.systemName,true);
|
GwConfigInterface *systemName=config.getConfigItem(config.systemName,true);
|
||||||
|
|
||||||
bool serCanWrite=true;
|
|
||||||
bool serCanRead=true;
|
|
||||||
|
|
||||||
GwSerial *usbSerial = new GwSerial(NULL, 0, USB_CHANNEL_ID);
|
void handleN2kMessage(const tN2kMsg &n2kMsg,int sourceId, bool isConverted=false)
|
||||||
GwSerial *serial1=NULL;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
N2KT_MSGIN, //from CAN
|
|
||||||
N2KT_MSGINT, //from internal source
|
|
||||||
N2KT_MSGOUT, //from converter
|
|
||||||
N2KT_MSGACT //from actisense
|
|
||||||
} N2K_MsgDirection;
|
|
||||||
void handleN2kMessage(const tN2kMsg &n2kMsg,N2K_MsgDirection direction)
|
|
||||||
{
|
{
|
||||||
logger.logDebug(GwLog::DEBUG + 1, "N2K: pgn %d, dir %d",
|
logger.logDebug(GwLog::DEBUG + 1, "N2K: pgn %d, dir %d",
|
||||||
n2kMsg.PGN,(int)direction);
|
n2kMsg.PGN,sourceId);
|
||||||
if (direction == N2KT_MSGIN){
|
if (sourceId == N2K_CHANNEL_ID){
|
||||||
countNMEA2KIn.add(n2kMsg.PGN);
|
countNMEA2KIn.add(n2kMsg.PGN);
|
||||||
}
|
}
|
||||||
char buf[MAX_NMEA2000_MESSAGE_SEASMART_SIZE];
|
char buf[MAX_NMEA2000_MESSAGE_SEASMART_SIZE];
|
||||||
bool messageCreated=false;
|
bool messageCreated=false;
|
||||||
for (int i=0;i<numChannels;i++){
|
channels.allChannels([&](GwChannel *c){
|
||||||
if (allChannels[i]->sendSeaSmart()){
|
if (c->sendSeaSmart()){
|
||||||
if (! messageCreated){
|
if (! messageCreated){
|
||||||
if (N2kToSeasmart(n2kMsg, millis(), buf, MAX_NMEA2000_MESSAGE_SEASMART_SIZE) != 0) {
|
if (N2kToSeasmart(n2kMsg, millis(), buf, MAX_NMEA2000_MESSAGE_SEASMART_SIZE) != 0) {
|
||||||
messageCreated=true;
|
messageCreated=true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (messageCreated){
|
if (messageCreated){
|
||||||
allChannels[i]->sendToClients(buf,N2K_CHANNEL_ID);
|
c->sendToClients(buf,sourceId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
if (direction != N2KT_MSGACT)
|
channels.allChannels([&](GwChannel *c){
|
||||||
{
|
c->sendActisense(n2kMsg,sourceId);
|
||||||
for (int i=0;i<numChannels;i++){
|
});
|
||||||
allChannels[i]->sendActisense(n2kMsg);
|
if (! isConverted){
|
||||||
}
|
|
||||||
}
|
|
||||||
if (direction != N2KT_MSGOUT){
|
|
||||||
nmea0183Converter->HandleMsg(n2kMsg);
|
nmea0183Converter->HandleMsg(n2kMsg);
|
||||||
}
|
}
|
||||||
if (direction != N2KT_MSGIN){
|
if (sourceId != N2K_CHANNEL_ID){
|
||||||
countNMEA2KOut.add(n2kMsg.PGN);
|
countNMEA2KOut.add(n2kMsg.PGN);
|
||||||
NMEA2000.SendMsg(n2kMsg);
|
NMEA2000.SendMsg(n2kMsg);
|
||||||
}
|
}
|
||||||
|
@ -261,44 +217,11 @@ void SendNMEA0183Message(const tNMEA0183Msg &NMEA0183Msg, int sourceId,bool conv
|
||||||
buf[len]=0x0d;
|
buf[len]=0x0d;
|
||||||
buf[len+1]=0x0a;
|
buf[len+1]=0x0a;
|
||||||
buf[len+2]=0;
|
buf[len+2]=0;
|
||||||
for (int i=0;i< numChannels;i++){
|
channels.allChannels([&](GwChannel *c){
|
||||||
allChannels[i]->sendToClients(buf,sourceId);
|
c->sendToClients(buf,sourceId);
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class GwSerialLog : public GwLogWriter{
|
|
||||||
static const size_t bufferSize=4096;
|
|
||||||
char *logBuffer=NULL;
|
|
||||||
int wp=0;
|
|
||||||
public:
|
|
||||||
GwSerialLog(){
|
|
||||||
logBuffer=new char[bufferSize];
|
|
||||||
wp=0;
|
|
||||||
}
|
|
||||||
virtual ~GwSerialLog(){}
|
|
||||||
virtual void write(const char *data){
|
|
||||||
int len=strlen(data);
|
|
||||||
if ((wp+len) >= (bufferSize-1)) return;
|
|
||||||
strncpy(logBuffer+wp,data,len);
|
|
||||||
wp+=len;
|
|
||||||
logBuffer[wp]=0;
|
|
||||||
}
|
|
||||||
virtual void flush(){
|
|
||||||
size_t handled=0;
|
|
||||||
while (handled < wp){
|
|
||||||
usbSerial->flush();
|
|
||||||
size_t rt=usbSerial->sendToClients(logBuffer+handled,-1,true);
|
|
||||||
handled+=rt;
|
|
||||||
}
|
|
||||||
wp=0;
|
|
||||||
logBuffer[0]=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
GwSerialLog logWriter;
|
|
||||||
|
|
||||||
|
|
||||||
class ApiImpl : public GwApi
|
class ApiImpl : public GwApi
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
@ -315,7 +238,7 @@ public:
|
||||||
}
|
}
|
||||||
virtual void sendN2kMessage(const tN2kMsg &msg,bool convert)
|
virtual void sendN2kMessage(const tN2kMsg &msg,bool convert)
|
||||||
{
|
{
|
||||||
handleN2kMessage(msg,convert?N2KT_MSGINT:N2KT_MSGOUT);
|
handleN2kMessage(msg,sourceId,!convert);
|
||||||
|
|
||||||
}
|
}
|
||||||
virtual void sendNMEA0183Message(const tNMEA0183Msg &msg, int sourceId,bool convert)
|
virtual void sendNMEA0183Message(const tNMEA0183Msg &msg, int sourceId,bool convert)
|
||||||
|
@ -419,15 +342,11 @@ protected:
|
||||||
GwJsonDocument status(256 +
|
GwJsonDocument status(256 +
|
||||||
countNMEA2KIn.getJsonSize()+
|
countNMEA2KIn.getJsonSize()+
|
||||||
countNMEA2KOut.getJsonSize() +
|
countNMEA2KOut.getJsonSize() +
|
||||||
usbChannel.getJsonSize()+
|
channels.getJsonSize()
|
||||||
tcpChannel.getJsonSize()+
|
|
||||||
serialChannel.getJsonSize()+
|
|
||||||
tclChannel.getJsonSize()
|
|
||||||
);
|
);
|
||||||
status["version"] = VERSION;
|
status["version"] = VERSION;
|
||||||
status["wifiConnected"] = gwWifi.clientConnected();
|
status["wifiConnected"] = gwWifi.clientConnected();
|
||||||
status["clientIP"] = WiFi.localIP().toString();
|
status["clientIP"] = WiFi.localIP().toString();
|
||||||
status["numClients"] = socketServer.numClients();
|
|
||||||
status["apIp"] = gwWifi.apIP();
|
status["apIp"] = gwWifi.apIP();
|
||||||
size_t bsize=2*sizeof(unsigned long)+1;
|
size_t bsize=2*sizeof(unsigned long)+1;
|
||||||
unsigned long base=saltBase + ( millis()/1000UL & ~0x7UL);
|
unsigned long base=saltBase + ( millis()/1000UL & ~0x7UL);
|
||||||
|
@ -438,10 +357,7 @@ protected:
|
||||||
//nmea0183Converter->toJson(status);
|
//nmea0183Converter->toJson(status);
|
||||||
countNMEA2KIn.toJson(status);
|
countNMEA2KIn.toJson(status);
|
||||||
countNMEA2KOut.toJson(status);
|
countNMEA2KOut.toJson(status);
|
||||||
usbChannel.toJson(status);
|
channels.toJson(status);
|
||||||
serialChannel.toJson(status);
|
|
||||||
tcpChannel.toJson(status);
|
|
||||||
tclChannel.toJson(status);
|
|
||||||
serializeJson(status, result);
|
serializeJson(status, result);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -648,122 +564,19 @@ void setup() {
|
||||||
uint8_t chipid[6];
|
uint8_t chipid[6];
|
||||||
uint32_t id = 0;
|
uint32_t id = 0;
|
||||||
config.loadConfig();
|
config.loadConfig();
|
||||||
// Init USB serial port
|
bool fallbackSerial=false;
|
||||||
GwConfigInterface *usbBaud=config.getConfigItem(config.usbBaud,false);
|
|
||||||
int baud=115200;
|
|
||||||
if (usbBaud){
|
|
||||||
baud=usbBaud->asInt();
|
|
||||||
}
|
|
||||||
#ifdef FALLBACK_SERIAL
|
#ifdef FALLBACK_SERIAL
|
||||||
int st=-1;
|
fallbackSerial=true;
|
||||||
#else
|
|
||||||
int st=usbSerial->setup(baud,3,1); //TODO: PIN defines
|
|
||||||
#endif
|
|
||||||
if (st < 0){
|
|
||||||
//falling back to old style serial for logging
|
//falling back to old style serial for logging
|
||||||
Serial.begin(baud);
|
Serial.begin(baud);
|
||||||
Serial.printf("fallback serial enabled, error was %d\n",st);
|
Serial.printf("fallback serial enabled, error was %d\n",st);
|
||||||
logger.prefix="FALLBACK:";
|
logger.prefix="FALLBACK:";
|
||||||
}
|
#endif
|
||||||
else{
|
|
||||||
logger.prefix="GWSERIAL:";
|
|
||||||
logger.setWriter(&logWriter);
|
|
||||||
logger.logDebug(GwLog::LOG,"created GwSerial for USB port");
|
|
||||||
}
|
|
||||||
logger.logDebug(GwLog::LOG,"config: %s", config.toString().c_str());
|
|
||||||
userCodeHandler.startInitTasks(MIN_USER_TASK);
|
userCodeHandler.startInitTasks(MIN_USER_TASK);
|
||||||
#ifdef GWSERIAL_MODE
|
channels.begin(fallbackSerial);
|
||||||
int serialrx=-1;
|
|
||||||
int serialtx=-1;
|
|
||||||
#ifdef GWSERIAL_TX
|
|
||||||
serialtx=GWSERIAL_TX;
|
|
||||||
#endif
|
|
||||||
#ifdef GWSERIAL_RX
|
|
||||||
serialrx=GWSERIAL_RX;
|
|
||||||
#endif
|
|
||||||
//the mode is a compile time preselection from hardware.h
|
|
||||||
String serialMode(F(GWSERIAL_MODE));
|
|
||||||
//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;
|
|
||||||
logger.logDebug(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){
|
|
||||||
logger.logDebug(GwLog::LOG,"creating serial interface rx=%d, tx=%d",serialrx,serialtx);
|
|
||||||
serial1=new GwSerial(&logger,1,SERIAL1_CHANNEL_ID,serCanRead);
|
|
||||||
}
|
|
||||||
if (serial1){
|
|
||||||
int rt=serial1->setup(config.getInt(config.serialBaud,115200),serialrx,serialtx);
|
|
||||||
logger.logDebug(GwLog::LOG,"starting serial returns %d",rt);
|
|
||||||
serialChannel.setImpl(serial1);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
usbChannel.setImpl(usbSerial);
|
|
||||||
MDNS.begin(config.getConfigItem(config.systemName)->asCString());
|
MDNS.begin(config.getConfigItem(config.systemName)->asCString());
|
||||||
gwWifi.setup();
|
gwWifi.setup();
|
||||||
|
|
||||||
// Start TCP server
|
|
||||||
socketServer.begin();
|
|
||||||
tcpChannel.setImpl(&socketServer);
|
|
||||||
logger.flush();
|
logger.flush();
|
||||||
usbChannel.begin(true,
|
|
||||||
config.getBool(config.sendUsb),
|
|
||||||
config.getBool(config.receiveUsb),
|
|
||||||
config.getString(config.usbReadFilter),
|
|
||||||
config.getString(config.usbWriteFilter),
|
|
||||||
false,
|
|
||||||
config.getBool(config.usbToN2k),
|
|
||||||
config.getBool(config.usbActisense),
|
|
||||||
config.getBool(config.usbActSend)
|
|
||||||
);
|
|
||||||
logger.logDebug(GwLog::LOG,"%s",usbChannel.toString().c_str());
|
|
||||||
tcpChannel.begin(
|
|
||||||
true,
|
|
||||||
config.getBool(config.sendTCP),
|
|
||||||
config.getBool(config.readTCP),
|
|
||||||
config.getString(config.tcpReadFilter),
|
|
||||||
config.getString(config.tcpWriteFilter),
|
|
||||||
config.getBool(config.sendSeasmart),
|
|
||||||
config.getBool(config.tcpToN2k),
|
|
||||||
false,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
logger.logDebug(GwLog::LOG,"%s",tcpChannel.toString().c_str());
|
|
||||||
serialChannel.begin(
|
|
||||||
serCanRead || serCanWrite,
|
|
||||||
serCanWrite,
|
|
||||||
serCanRead,
|
|
||||||
config.getString(config.serialReadF),
|
|
||||||
config.getString(config.serialWriteF),
|
|
||||||
false,
|
|
||||||
config.getBool(config.serialToN2k),
|
|
||||||
false,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
logger.logDebug(GwLog::LOG,"%s",serialChannel.toString().c_str());
|
|
||||||
tclChannel.begin(
|
|
||||||
config.getBool(config.tclEnabled),
|
|
||||||
config.getBool(config.sendTCL),
|
|
||||||
config.getBool(config.readTCL),
|
|
||||||
config.getString(config.tclReadFilter),
|
|
||||||
config.getString(config.tclReadFilter),
|
|
||||||
config.getBool(config.tclSeasmart),
|
|
||||||
config.getBool(config.tclToN2k),
|
|
||||||
false,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
logger.logDebug(GwLog::LOG,"%s",tclChannel.toString().c_str());
|
|
||||||
logger.flush();
|
|
||||||
|
|
||||||
webserver.registerMainHandler("/api/reset", [](AsyncWebServerRequest *request)->GwRequestMessage *{
|
webserver.registerMainHandler("/api/reset", [](AsyncWebServerRequest *request)->GwRequestMessage *{
|
||||||
return new ResetRequest(request->arg("_hash"));
|
return new ResetRequest(request->arg("_hash"));
|
||||||
});
|
});
|
||||||
|
@ -823,9 +636,9 @@ void setup() {
|
||||||
config.getInt(config.minXdrInterval,100)
|
config.getInt(config.minXdrInterval,100)
|
||||||
);
|
);
|
||||||
|
|
||||||
toN2KConverter= NMEA0183DataToN2K::create(&logger,&boatData,[](const tN2kMsg &msg)->bool{
|
toN2KConverter= NMEA0183DataToN2K::create(&logger,&boatData,[](const tN2kMsg &msg, int sourceId)->bool{
|
||||||
logger.logDebug(GwLog::DEBUG+2,"send N2K %ld",msg.PGN);
|
logger.logDebug(GwLog::DEBUG+2,"send N2K %ld",msg.PGN);
|
||||||
handleN2kMessage(msg,N2KT_MSGOUT);
|
handleN2kMessage(msg,sourceId,true);
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
&xdrMappings,
|
&xdrMappings,
|
||||||
|
@ -881,7 +694,7 @@ void setup() {
|
||||||
NMEA2000.ExtendTransmitMessages(pgns);
|
NMEA2000.ExtendTransmitMessages(pgns);
|
||||||
NMEA2000.ExtendReceiveMessages(nmea0183Converter->handledPgns());
|
NMEA2000.ExtendReceiveMessages(nmea0183Converter->handledPgns());
|
||||||
NMEA2000.SetMsgHandler([](const tN2kMsg &n2kMsg){
|
NMEA2000.SetMsgHandler([](const tN2kMsg &n2kMsg){
|
||||||
handleN2kMessage(n2kMsg,N2KT_MSGIN);
|
handleN2kMessage(n2kMsg,N2K_CHANNEL_ID);
|
||||||
});
|
});
|
||||||
NMEA2000.Open();
|
NMEA2000.Open();
|
||||||
logger.logDebug(GwLog::LOG,"starting addon tasks");
|
logger.logDebug(GwLog::LOG,"starting addon tasks");
|
||||||
|
@ -899,9 +712,9 @@ void setup() {
|
||||||
}
|
}
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
void handleSendAndRead(bool handleRead){
|
void handleSendAndRead(bool handleRead){
|
||||||
for (int i=0;i<numChannels;i++){
|
channels.allChannels([&](GwChannel *c){
|
||||||
allChannels[i]->loop(handleRead,true);
|
c->loop(handleRead,true);
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
TimeMonitor monitor(20,0.2);
|
TimeMonitor monitor(20,0.2);
|
||||||
|
@ -925,14 +738,14 @@ void loop() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
monitor.setTime(3);
|
monitor.setTime(3);
|
||||||
for (int i=0;i<numChannels;i++){
|
channels.allChannels([](GwChannel *c){
|
||||||
allChannels[i]->loop(true,false);
|
c->loop(true,false);
|
||||||
}
|
});
|
||||||
//reads
|
//reads
|
||||||
monitor.setTime(4);
|
monitor.setTime(4);
|
||||||
for (int i=0;i<numChannels;i++){
|
channels.allChannels([](GwChannel *c){
|
||||||
allChannels[i]->loop(false,true);
|
c->loop(false,true);
|
||||||
}
|
});
|
||||||
//writes
|
//writes
|
||||||
monitor.setTime(5);
|
monitor.setTime(5);
|
||||||
NMEA2000.ParseMessages();
|
NMEA2000.ParseMessages();
|
||||||
|
@ -950,23 +763,23 @@ void loop() {
|
||||||
monitor.setTime(7);
|
monitor.setTime(7);
|
||||||
|
|
||||||
//read channels
|
//read channels
|
||||||
for (int i=0;i<numChannels;i++){
|
channels.allChannels([](GwChannel *c){
|
||||||
allChannels[i]->readMessages([&](const char * buffer, int sourceId){
|
c->readMessages([&](const char * buffer, int sourceId){
|
||||||
for (int j=0;j<numChannels;j++){
|
channels.allChannels([&](GwChannel *oc){
|
||||||
allChannels[j]->sendToClients(buffer,sourceId);
|
oc->sendToClients(buffer,sourceId);
|
||||||
allChannels[j]->loop(false,true);
|
oc->loop(false,true);
|
||||||
}
|
});
|
||||||
if (allChannels[i]->sendToN2K()){
|
if (c->sendToN2K()){
|
||||||
toN2KConverter->parseAndSend(buffer, sourceId);
|
toN2KConverter->parseAndSend(buffer, sourceId);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
monitor.setTime(8);
|
monitor.setTime(8);
|
||||||
for (int i=0;i<numChannels;i++){
|
channels.allChannels([](GwChannel *c){
|
||||||
allChannels[i]->parseActisense([](const tN2kMsg &msg,int source){
|
c->parseActisense([](const tN2kMsg &msg,int source){
|
||||||
handleN2kMessage(msg,N2KT_MSGACT);
|
handleN2kMessage(msg,source);
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
monitor.setTime(9);
|
monitor.setTime(9);
|
||||||
|
|
||||||
//handle message requests
|
//handle message requests
|
||||||
|
|
Loading…
Reference in New Issue