intermediate,untested: reorganize channel handling
This commit is contained in:
parent
56ec7a0406
commit
c6f601377c
|
@ -218,14 +218,23 @@ 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
|
//currently actisense only for channels with a single source id
|
||||||
//so we can check it here
|
//so we can check it here
|
||||||
if (isOwnSource(sourceId)) return;
|
if (maxSourceId < 0 && this->sourceId == sourceId) return;
|
||||||
|
if (sourceId >= this->sourceId && sourceId <= maxSourceId) return;
|
||||||
countOut->add(String(msg.PGN));
|
countOut->add(String(msg.PGN));
|
||||||
msg.SendInActisenseFormat(channelStream);
|
msg.SendInActisenseFormat(channelStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GwChannel::isOwnSource(int id){
|
bool GwChannel::overlaps(const GwChannel *other) const{
|
||||||
if (maxSourceId < 0) return id == sourceId;
|
if (maxSourceId < 0){
|
||||||
else return (id >= sourceId && id <= maxSourceId);
|
if (other->maxSourceId < 0) return sourceId == other->sourceId;
|
||||||
|
return (other->sourceId <= sourceId && other->maxSourceId >= sourceId);
|
||||||
|
}
|
||||||
|
if (other->maxSourceId < 0){
|
||||||
|
return other->sourceId >= sourceId && other->sourceId <= maxSourceId;
|
||||||
|
}
|
||||||
|
if (other->maxSourceId < sourceId) return false;
|
||||||
|
if (other->sourceId > maxSourceId) return false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long GwChannel::countRx(){
|
unsigned long GwChannel::countRx(){
|
||||||
|
|
|
@ -50,7 +50,7 @@ class GwChannel{
|
||||||
);
|
);
|
||||||
|
|
||||||
void setImpl(GwChannelInterface *impl);
|
void setImpl(GwChannelInterface *impl);
|
||||||
bool isOwnSource(int id);
|
bool overlaps(const GwChannel *) const;
|
||||||
void enable(bool enabled){
|
void enable(bool enabled){
|
||||||
this->enabled=enabled;
|
this->enabled=enabled;
|
||||||
}
|
}
|
||||||
|
@ -73,5 +73,10 @@ class GwChannel{
|
||||||
void sendActisense(const tN2kMsg &msg, int sourceId);
|
void sendActisense(const tN2kMsg &msg, int sourceId);
|
||||||
unsigned long countRx();
|
unsigned long countRx();
|
||||||
unsigned long countTx();
|
unsigned long countTx();
|
||||||
|
bool isOwnSource(int source){
|
||||||
|
if (maxSourceId < 0) return source == sourceId;
|
||||||
|
return (source >= sourceId && source <= maxSourceId);
|
||||||
|
}
|
||||||
|
String getMode(){return impl->getMode();}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -6,4 +6,5 @@ class GwChannelInterface{
|
||||||
virtual void readMessages(GwMessageFetcher *writer)=0;
|
virtual void readMessages(GwMessageFetcher *writer)=0;
|
||||||
virtual size_t sendToClients(const char *buffer, int sourceId, bool partial=false)=0;
|
virtual size_t sendToClients(const char *buffer, int sourceId, bool partial=false)=0;
|
||||||
virtual Stream * getStream(bool partialWrites){ return NULL;}
|
virtual Stream * getStream(bool partialWrites){ return NULL;}
|
||||||
|
virtual String getMode(){return "UNKNOWN";}
|
||||||
};
|
};
|
|
@ -18,16 +18,53 @@ class SerInit{
|
||||||
};
|
};
|
||||||
std::vector<SerInit> serialInits;
|
std::vector<SerInit> serialInits;
|
||||||
|
|
||||||
|
static int typeFromMode(const char *mode){
|
||||||
|
if (strcmp(mode,"UNI") == 0) return GWSERIAL_TYPE_UNI;
|
||||||
|
if (strcmp(mode,"BI") == 0) return GWSERIAL_TYPE_BI;
|
||||||
|
if (strcmp(mode,"RX") == 0) return GWSERIAL_TYPE_RX;
|
||||||
|
if (strcmp(mode,"TX") == 0) return GWSERIAL_TYPE_TX;
|
||||||
|
return GWSERIAL_TYPE_UNK;
|
||||||
|
}
|
||||||
|
|
||||||
#define CFG_SERIAL(ser,...) \
|
#define CFG_SERIAL(ser,...) \
|
||||||
__MSG("serial config " #ser); \
|
__MSG("serial config " #ser); \
|
||||||
static GwInitializer<SerInit> __serial ## ser ## _init \
|
static GwInitializer<SerInit> __serial ## ser ## _init \
|
||||||
(serialInits,SerInit(ser,__VA_ARGS__));
|
(serialInits,SerInit(ser,__VA_ARGS__));
|
||||||
#ifdef _GWI_SERIAL1
|
#ifdef _GWI_SERIAL1
|
||||||
CFG_SERIAL(1,_GWI_SERIAL1)
|
CFG_SERIAL(0,_GWI_SERIAL1)
|
||||||
#endif
|
#endif
|
||||||
#ifdef _GWI_SERIAL2
|
#ifdef _GWI_SERIAL2
|
||||||
CFG_SERIAL(2,_GWI_SERIAL2)
|
CFG_SERIAL(1,_GWI_SERIAL2)
|
||||||
#endif
|
#endif
|
||||||
|
//handle separate defines
|
||||||
|
//serial 1
|
||||||
|
#ifndef GWSERIAL_TX
|
||||||
|
#define GWSERIAL_TX -1
|
||||||
|
#endif
|
||||||
|
#ifndef GWSERIAL_RX
|
||||||
|
#define GWSERIAL_RX -1
|
||||||
|
#endif
|
||||||
|
#ifdef GWSERIAL_TYPE
|
||||||
|
CFG_SERIAL(0,GWSERIAL_RX,GWSERIAL_TX,GWSERIAL_TYPE)
|
||||||
|
#else
|
||||||
|
#ifdef GWSERIAL_MODE
|
||||||
|
CFG_SERIAL(0,GWSERIAL_RX,GWSERIAL_TX,typeFromMode(GWSERIAL_MODE))
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
//serial 2
|
||||||
|
#ifndef GWSERIAL2_TX
|
||||||
|
#define GWSERIAL2_TX -1
|
||||||
|
#endif
|
||||||
|
#ifndef GWSERIAL2_RX
|
||||||
|
#define GWSERIAL2_RX -1
|
||||||
|
#endif
|
||||||
|
#ifdef GWSERIAL2_TYPE
|
||||||
|
CFG_SERIAL(1,GWSERIAL2_RX,GWSERIAL2_TX,GWSERIAL2_TYPE)
|
||||||
|
#else
|
||||||
|
#ifdef GWSERIAL2_MODE
|
||||||
|
CFG_SERIAL(1,GWSERIAL2_RX,GWSERIAL2_TX,typeFromMode(GWSERIAL2_MODE))
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
class GwSerialLog : public GwLogWriter
|
class GwSerialLog : public GwLogWriter
|
||||||
{
|
{
|
||||||
static const size_t bufferSize = 4096;
|
static const size_t bufferSize = 4096;
|
||||||
|
@ -35,13 +72,11 @@ class GwSerialLog : public GwLogWriter
|
||||||
int wp = 0;
|
int wp = 0;
|
||||||
GwSerial *writer;
|
GwSerial *writer;
|
||||||
bool disabled = false;
|
bool disabled = false;
|
||||||
long flushTimeout=200;
|
|
||||||
public:
|
public:
|
||||||
GwSerialLog(GwSerial *writer, bool disabled,long flushTimeout=200)
|
GwSerialLog(GwSerial *writer, bool disabled)
|
||||||
{
|
{
|
||||||
this->writer = writer;
|
this->writer = writer;
|
||||||
this->disabled = disabled;
|
this->disabled = disabled;
|
||||||
this->flushTimeout=flushTimeout;
|
|
||||||
logBuffer = new char[bufferSize];
|
logBuffer = new char[bufferSize];
|
||||||
wp = 0;
|
wp = 0;
|
||||||
}
|
}
|
||||||
|
@ -64,7 +99,7 @@ public:
|
||||||
{
|
{
|
||||||
while (handled < wp)
|
while (handled < wp)
|
||||||
{
|
{
|
||||||
if ( !writer->flush(flushTimeout)) break;
|
if ( !writer->flush()) break;
|
||||||
size_t rt = writer->sendToClients(logBuffer + handled, -1, true);
|
size_t rt = writer->sendToClients(logBuffer + handled, -1, true);
|
||||||
handled += rt;
|
handled += rt;
|
||||||
}
|
}
|
||||||
|
@ -82,44 +117,6 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
class SerialWrapper : public GwSerial::SerialWrapperBase{
|
|
||||||
private:
|
|
||||||
template<class C>
|
|
||||||
void beginImpl(C *s,unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1){}
|
|
||||||
void beginImpl(HardwareSerial *s,unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1){
|
|
||||||
s->begin(baud,config,rxPin,txPin);
|
|
||||||
}
|
|
||||||
template<class C>
|
|
||||||
void setError(C* s, GwLog *logger){}
|
|
||||||
void setError(HardwareSerial *s,GwLog *logger){
|
|
||||||
LOG_DEBUG(GwLog::LOG,"enable serial errors for channel %d",id);
|
|
||||||
s->onReceiveError([logger,this](hardwareSerial_error_t err){
|
|
||||||
LOG_DEBUG(GwLog::ERROR,"serial error on id %d: %d",this->id,(int)err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
|
|
||||||
void beginImpl(HWCDC *s,unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1){
|
|
||||||
s->begin(baud);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
T *serial;
|
|
||||||
int id;
|
|
||||||
public:
|
|
||||||
SerialWrapper(T* s,int i):serial(s),id(i){}
|
|
||||||
virtual void begin(GwLog* logger,unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1) override{
|
|
||||||
beginImpl(serial,baud,config,rxPin,txPin);
|
|
||||||
setError(serial,logger);
|
|
||||||
};
|
|
||||||
virtual Stream *getStream() override{
|
|
||||||
return serial;
|
|
||||||
}
|
|
||||||
virtual int getId() override{
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
GwChannelList::GwChannelList(GwLog *logger, GwConfigHandler *config){
|
GwChannelList::GwChannelList(GwLog *logger, GwConfigHandler *config){
|
||||||
this->logger=logger;
|
this->logger=logger;
|
||||||
|
@ -139,10 +136,27 @@ typedef struct {
|
||||||
const char *toN2K;
|
const char *toN2K;
|
||||||
const char *readF;
|
const char *readF;
|
||||||
const char *writeF;
|
const char *writeF;
|
||||||
|
const char *preventLog;
|
||||||
|
const char *readAct;
|
||||||
|
const char *writeAct;
|
||||||
const char *name;
|
const char *name;
|
||||||
} SerialParam;
|
} SerialParam;
|
||||||
|
|
||||||
static SerialParam serialParameters[]={
|
static SerialParam serialParameters[]={
|
||||||
|
{
|
||||||
|
.id=USB_CHANNEL_ID,
|
||||||
|
.baud=GwConfigDefinitions::usbBaud,
|
||||||
|
.receive=GwConfigDefinitions::receiveUsb,
|
||||||
|
.send=GwConfigDefinitions::sendUsb,
|
||||||
|
.direction="",
|
||||||
|
.toN2K=GwConfigDefinitions::usbToN2k,
|
||||||
|
.readF=GwConfigDefinitions::usbReadFilter,
|
||||||
|
.writeF=GwConfigDefinitions::usbWriteFilter,
|
||||||
|
.preventLog=GwConfigDefinitions::usbActisense,
|
||||||
|
.readAct=GwConfigDefinitions::usbActisense,
|
||||||
|
.writeAct=GwConfigDefinitions::usbActSend,
|
||||||
|
.name="USB"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.id=SERIAL1_CHANNEL_ID,
|
.id=SERIAL1_CHANNEL_ID,
|
||||||
.baud=GwConfigDefinitions::serialBaud,
|
.baud=GwConfigDefinitions::serialBaud,
|
||||||
|
@ -152,6 +166,9 @@ static SerialParam serialParameters[]={
|
||||||
.toN2K=GwConfigDefinitions::serialToN2k,
|
.toN2K=GwConfigDefinitions::serialToN2k,
|
||||||
.readF=GwConfigDefinitions::serialReadF,
|
.readF=GwConfigDefinitions::serialReadF,
|
||||||
.writeF=GwConfigDefinitions::serialWriteF,
|
.writeF=GwConfigDefinitions::serialWriteF,
|
||||||
|
.preventLog="",
|
||||||
|
.readAct="",
|
||||||
|
.writeAct="",
|
||||||
.name="Serial"
|
.name="Serial"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -163,81 +180,38 @@ static SerialParam serialParameters[]={
|
||||||
.toN2K=GwConfigDefinitions::serial2ToN2k,
|
.toN2K=GwConfigDefinitions::serial2ToN2k,
|
||||||
.readF=GwConfigDefinitions::serial2ReadF,
|
.readF=GwConfigDefinitions::serial2ReadF,
|
||||||
.writeF=GwConfigDefinitions::serial2WriteF,
|
.writeF=GwConfigDefinitions::serial2WriteF,
|
||||||
|
.preventLog="",
|
||||||
|
.readAct="",
|
||||||
|
.writeAct="",
|
||||||
.name="Serial2"
|
.name="Serial2"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static SerialParam *getSerialParam(int id){
|
template<typename T>
|
||||||
for (size_t idx=0;idx<sizeof(serialParameters)/sizeof(SerialParam*);idx++){
|
GwSerial* createSerial(GwLog *logger, T* s,int id, bool canRead=true){
|
||||||
if (serialParameters[idx].id == id) return &serialParameters[idx];
|
return new GwSerialImpl<T>(logger,s,id,canRead);
|
||||||
}
|
}
|
||||||
return nullptr;
|
|
||||||
}
|
static GwChannel * createSerialChannel(GwConfigHandler *config,GwLog *logger, int idx,int type,int rx,int tx, bool setLog=false){
|
||||||
void GwChannelList::addSerial(int id, int rx, int tx, int type){
|
if (idx < 0 || idx >= sizeof(serialParameters)/sizeof(SerialParam*)) return nullptr;
|
||||||
if (id == 1){
|
SerialParam *param=&serialParameters[idx];
|
||||||
addSerial(new SerialWrapper<decltype(Serial1)>(&Serial1,SERIAL1_CHANNEL_ID),type,rx,tx);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (id == 2){
|
|
||||||
addSerial(new SerialWrapper<decltype(Serial2)>(&Serial2,SERIAL2_CHANNEL_ID),type,rx,tx);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
LOG_DEBUG(GwLog::ERROR,"invalid serial config with id %d",id);
|
|
||||||
}
|
|
||||||
void GwChannelList::addSerial(GwSerial::SerialWrapperBase *stream,int type,int rx,int tx){
|
|
||||||
const char *mode=nullptr;
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case GWSERIAL_TYPE_UNI:
|
|
||||||
mode="UNI";
|
|
||||||
break;
|
|
||||||
case GWSERIAL_TYPE_BI:
|
|
||||||
mode="BI";
|
|
||||||
break;
|
|
||||||
case GWSERIAL_TYPE_RX:
|
|
||||||
mode="RX";
|
|
||||||
break;
|
|
||||||
case GWSERIAL_TYPE_TX:
|
|
||||||
mode="TX";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (mode == nullptr) {
|
|
||||||
LOG_DEBUG(GwLog::ERROR,"unknown serial type %d",type);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
addSerial(stream,mode,rx,tx);
|
|
||||||
}
|
|
||||||
void GwChannelList::addSerial(GwSerial::SerialWrapperBase *serialStream,const String &mode,int rx,int tx){
|
|
||||||
int id=serialStream->getId();
|
|
||||||
for (auto &&it:theChannels){
|
|
||||||
if (it->isOwnSource(id)){
|
|
||||||
LOG_DEBUG(GwLog::ERROR,"trying to re-add serial id=%d, ignoring",id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SerialParam *param=getSerialParam(id);
|
|
||||||
if (param == nullptr){
|
|
||||||
logger->logDebug(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 canRead=false;
|
||||||
bool canWrite=false;
|
bool canWrite=false;
|
||||||
if (mode == "BI"){
|
bool validType=false;
|
||||||
|
if (type == GWSERIAL_TYPE_BI){
|
||||||
canRead=config->getBool(param->receive);
|
canRead=config->getBool(param->receive);
|
||||||
canWrite=config->getBool(param->send);
|
canWrite=config->getBool(param->send);
|
||||||
|
validType=true;
|
||||||
}
|
}
|
||||||
if (mode == "TX"){
|
if (type == GWSERIAL_TYPE_TX){
|
||||||
canWrite=true;
|
canWrite=true;
|
||||||
|
validType=true;
|
||||||
}
|
}
|
||||||
if (mode == "RX"){
|
if (type == GWSERIAL_TYPE_RX){
|
||||||
canRead=true;
|
canRead=true;
|
||||||
|
validType=true;
|
||||||
}
|
}
|
||||||
if (mode == "UNI"){
|
if (type == GWSERIAL_TYPE_UNI ){
|
||||||
String cfgMode=config->getString(param->direction);
|
String cfgMode=config->getString(param->direction);
|
||||||
if (cfgMode == "receive"){
|
if (cfgMode == "receive"){
|
||||||
canRead=true;
|
canRead=true;
|
||||||
|
@ -245,16 +219,41 @@ void GwChannelList::addSerial(GwSerial::SerialWrapperBase *serialStream,const St
|
||||||
if (cfgMode == "send"){
|
if (cfgMode == "send"){
|
||||||
canWrite=true;
|
canWrite=true;
|
||||||
}
|
}
|
||||||
|
validType=true;
|
||||||
|
}
|
||||||
|
if (! validType){
|
||||||
|
LOG_DEBUG(GwLog::ERROR,"invalid type for serial channel %d: %d",param->id,type);
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (rx < 0) canRead=false;
|
if (rx < 0) canRead=false;
|
||||||
if (tx < 0) canWrite=false;
|
if (tx < 0) canWrite=false;
|
||||||
LOG_DEBUG(GwLog::DEBUG,"serial set up: mode=%s,rx=%d,canRead=%d,tx=%d,canWrite=%d",
|
LOG_DEBUG(GwLog::DEBUG,"serial set up: type=%d,rx=%d,canRead=%d,tx=%d,canWrite=%d",
|
||||||
mode.c_str(),rx,(int)canRead,tx,(int)canWrite);
|
type,rx,(int)canRead,tx,(int)canWrite);
|
||||||
serialStream->begin(logger,config->getInt(param->baud,115200),SERIAL_8N1,rx,tx);
|
GwSerial *serialStream=nullptr;
|
||||||
GwSerial *serial = new GwSerial(logger, serialStream, canRead);
|
GwLog *streamLog=setLog?nullptr:logger;
|
||||||
LOG_DEBUG(GwLog::LOG, "starting serial %d ", id);
|
switch(param->id){
|
||||||
GwChannel *channel = new GwChannel(logger, param->name, id);
|
case USB_CHANNEL_ID:
|
||||||
channel->setImpl(serial);
|
serialStream=createSerial(streamLog,&USBSerial,param->id);
|
||||||
|
break;
|
||||||
|
case SERIAL1_CHANNEL_ID:
|
||||||
|
serialStream=createSerial(streamLog,&Serial1,param->id);
|
||||||
|
break;
|
||||||
|
case SERIAL2_CHANNEL_ID:
|
||||||
|
serialStream=createSerial(streamLog,&Serial2,param->id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (serialStream == nullptr){
|
||||||
|
LOG_DEBUG(GwLog::ERROR,"invalid serial config with id %d",param->id);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
serialStream->begin(config->getInt(param->baud,115200),SERIAL_8N1,rx,tx);
|
||||||
|
if (setLog){
|
||||||
|
logger->setWriter(new GwSerialLog(serialStream,config->getBool(param->preventLog,false)));
|
||||||
|
logger->prefix="GWSERIAL:";
|
||||||
|
}
|
||||||
|
LOG_DEBUG(GwLog::LOG, "starting serial %d ", param->id);
|
||||||
|
GwChannel *channel = new GwChannel(logger, param->name,param->id);
|
||||||
|
channel->setImpl(serialStream);
|
||||||
channel->begin(
|
channel->begin(
|
||||||
canRead || canWrite,
|
canRead || canWrite,
|
||||||
canWrite,
|
canWrite,
|
||||||
|
@ -263,9 +262,20 @@ void GwChannelList::addSerial(GwSerial::SerialWrapperBase *serialStream,const St
|
||||||
config->getString(param->writeF),
|
config->getString(param->writeF),
|
||||||
false,
|
false,
|
||||||
config->getBool(param->toN2K),
|
config->getBool(param->toN2K),
|
||||||
false,
|
config->getBool(param->readAct),
|
||||||
false);
|
config->getBool(param->writeAct));
|
||||||
LOG_DEBUG(GwLog::LOG, "%s", channel->toString().c_str());
|
return channel;
|
||||||
|
}
|
||||||
|
void GwChannelList::addChannel(GwChannel * channel){
|
||||||
|
for (auto &&it:theChannels){
|
||||||
|
if (it->overlaps(channel)){
|
||||||
|
LOG_DEBUG(GwLog::ERROR,"trying to add channel with overlapping ids %s (%s), ignoring",
|
||||||
|
channel->toString().c_str(),
|
||||||
|
it->toString().c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOG_DEBUG(GwLog::LOG, "adding channel %s", channel->toString().c_str());
|
||||||
theChannels.push_back(channel);
|
theChannels.push_back(channel);
|
||||||
}
|
}
|
||||||
void GwChannelList::preinit(){
|
void GwChannelList::preinit(){
|
||||||
|
@ -290,38 +300,20 @@ void GwChannelList::preinit(){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
template<typename S>
|
#ifndef GWUSB_TX
|
||||||
long getFlushTimeout(S &s){
|
#define GWUSB_TX -1
|
||||||
return 200;
|
#endif
|
||||||
}
|
#ifndef GWUSB_RX
|
||||||
template<>
|
#define GWUSB_RX -1
|
||||||
long getFlushTimeout(HardwareSerial &s){
|
#endif
|
||||||
return 2000;
|
|
||||||
}
|
|
||||||
void GwChannelList::begin(bool fallbackSerial){
|
void GwChannelList::begin(bool fallbackSerial){
|
||||||
LOG_DEBUG(GwLog::DEBUG,"GwChannelList::begin");
|
LOG_DEBUG(GwLog::DEBUG,"GwChannelList::begin");
|
||||||
GwChannel *channel=NULL;
|
GwChannel *channel=NULL;
|
||||||
//usb
|
//usb
|
||||||
if (! fallbackSerial){
|
if (! fallbackSerial){
|
||||||
GwSerial::SerialWrapperBase *usbWrapper=new SerialWrapper<decltype(USBSerial)>(&USBSerial,USB_CHANNEL_ID);
|
GwChannel *usb=createSerialChannel(config, logger,0,GWSERIAL_TYPE_BI,GWUSB_RX,GWUSB_TX,true);
|
||||||
usbWrapper->begin(NULL,config->getInt(config->usbBaud));
|
addChannel(usb);
|
||||||
GwSerial *usb=new GwSerial(NULL,usbWrapper);
|
|
||||||
logger->setWriter(new GwSerialLog(usb,config->getBool(config->usbActisense),getFlushTimeout(USBSerial)));
|
|
||||||
logger->prefix="GWSERIAL:";
|
|
||||||
channel=new GwChannel(logger,"USB",USB_CHANNEL_ID);
|
|
||||||
channel->setImpl(usb);
|
|
||||||
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)
|
|
||||||
);
|
|
||||||
theChannels.push_back(channel);
|
|
||||||
LOG_DEBUG(GwLog::LOG,"%s",channel->toString().c_str());
|
|
||||||
}
|
}
|
||||||
//TCP server
|
//TCP server
|
||||||
sockets=new GwSocketServer(config,logger,MIN_TCP_CHANNEL_ID);
|
sockets=new GwSocketServer(config,logger,MIN_TCP_CHANNEL_ID);
|
||||||
|
@ -339,42 +331,13 @@ void GwChannelList::begin(bool fallbackSerial){
|
||||||
false,
|
false,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
LOG_DEBUG(GwLog::LOG,"%s",channel->toString().c_str());
|
addChannel(channel);
|
||||||
theChannels.push_back(channel);
|
|
||||||
|
|
||||||
//new serial config handling
|
//new serial config handling
|
||||||
for (auto &&init:serialInits){
|
for (auto &&init:serialInits){
|
||||||
addSerial(init.serial,init.rx,init.tx,init.mode);
|
(logger,init.serial,init.rx,init.tx,init.mode);
|
||||||
}
|
}
|
||||||
//handle separate defines
|
|
||||||
//serial 1
|
|
||||||
#ifndef GWSERIAL_TX
|
|
||||||
#define GWSERIAL_TX -1
|
|
||||||
#endif
|
|
||||||
#ifndef GWSERIAL_RX
|
|
||||||
#define GWSERIAL_RX -1
|
|
||||||
#endif
|
|
||||||
#ifdef GWSERIAL_TYPE
|
|
||||||
addSerial(new SerialWrapper<decltype(Serial1)>(&Serial1,SERIAL1_CHANNEL_ID),GWSERIAL_TYPE,GWSERIAL_RX,GWSERIAL_TX);
|
|
||||||
#else
|
|
||||||
#ifdef GWSERIAL_MODE
|
|
||||||
addSerial(new SerialWrapper<decltype(Serial1)>(&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(new SerialWrapper<decltype(Serial2)>(&Serial2,SERIAL2_CHANNEL_ID),GWSERIAL2_TYPE,GWSERIAL2_RX,GWSERIAL2_TX);
|
|
||||||
#else
|
|
||||||
#ifdef GWSERIAL2_MODE
|
|
||||||
addSerial(new SerialWrapper<decltype(Serial2)>(&Serial2,SERIAL2_CHANNEL_ID),GWSERIAL2_MODE,GWSERIAL2_RX,GWSERIAL2_TX);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
//tcp client
|
//tcp client
|
||||||
bool tclEnabled=config->getBool(config->tclEnabled);
|
bool tclEnabled=config->getBool(config->tclEnabled);
|
||||||
channel=new GwChannel(logger,"TCPClient",TCP_CLIENT_CHANNEL_ID);
|
channel=new GwChannel(logger,"TCPClient",TCP_CLIENT_CHANNEL_ID);
|
||||||
|
@ -398,13 +361,13 @@ void GwChannelList::begin(bool fallbackSerial){
|
||||||
false,
|
false,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
theChannels.push_back(channel);
|
addChannel(channel);
|
||||||
LOG_DEBUG(GwLog::LOG,"%s",channel->toString().c_str());
|
|
||||||
logger->flush();
|
logger->flush();
|
||||||
}
|
}
|
||||||
String GwChannelList::getMode(int id){
|
String GwChannelList::getMode(int id){
|
||||||
auto it=modes.find(id);
|
for (auto && c: theChannels){
|
||||||
if (it != modes.end()) return it->second;
|
if (c->isOwnSource(id)) return c->getMode();
|
||||||
|
}
|
||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
int GwChannelList::getJsonSize(){
|
int GwChannelList::getJsonSize(){
|
||||||
|
@ -429,8 +392,8 @@ void GwChannelList::toJson(GwJsonDocument &doc){
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
GwChannel *GwChannelList::getChannelById(int sourceId){
|
GwChannel *GwChannelList::getChannelById(int sourceId){
|
||||||
for (auto it=theChannels.begin();it != theChannels.end();it++){
|
for (auto && it: theChannels){
|
||||||
if ((*it)->isOwnSource(sourceId)) return *it;
|
if (it->isOwnSource(sourceId)) return it;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,13 +28,10 @@ class GwChannelList{
|
||||||
GwConfigHandler *config;
|
GwConfigHandler *config;
|
||||||
typedef std::vector<GwChannel *> ChannelList;
|
typedef std::vector<GwChannel *> ChannelList;
|
||||||
ChannelList theChannels;
|
ChannelList theChannels;
|
||||||
std::map<int,String> modes;
|
|
||||||
GwSocketServer *sockets;
|
GwSocketServer *sockets;
|
||||||
GwTcpClient *client;
|
GwTcpClient *client;
|
||||||
void addSerial(GwSerial::SerialWrapperBase *stream,const String &mode,int rx,int tx);
|
|
||||||
void addSerial(GwSerial::SerialWrapperBase *stream,int type,int rx,int tx);
|
|
||||||
public:
|
public:
|
||||||
void addSerial(int id, int rx, int tx, int type);
|
void addChannel(GwChannel *);
|
||||||
GwChannelList(GwLog *logger, GwConfigHandler *config);
|
GwChannelList(GwLog *logger, GwConfigHandler *config);
|
||||||
typedef std::function<void(GwChannel *)> ChannelAction;
|
typedef std::function<void(GwChannel *)> ChannelAction;
|
||||||
void allChannels(ChannelAction action);
|
void allChannels(ChannelAction action);
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#define GWSERIAL_TYPE_BI 2
|
#define GWSERIAL_TYPE_BI 2
|
||||||
#define GWSERIAL_TYPE_RX 3
|
#define GWSERIAL_TYPE_RX 3
|
||||||
#define GWSERIAL_TYPE_TX 4
|
#define GWSERIAL_TYPE_TX 4
|
||||||
|
#define GWSERIAL_TYPE_UNK 0
|
||||||
#include <GwConfigItem.h>
|
#include <GwConfigItem.h>
|
||||||
#include <HardwareSerial.h>
|
#include <HardwareSerial.h>
|
||||||
#include "GwAppInfo.h"
|
#include "GwAppInfo.h"
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "GwSerial.h"
|
#include "GwSerial.h"
|
||||||
|
#include "GwHardware.h"
|
||||||
|
|
||||||
class GwSerialStream: public Stream{
|
class GwSerialStream: public Stream{
|
||||||
private:
|
private:
|
||||||
|
@ -40,11 +41,13 @@ class GwSerialStream: public Stream{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
GwSerial::GwSerial(GwLog *logger, GwSerial::SerialWrapperBase *s, bool allowRead):serial(s)
|
GwSerial::GwSerial(GwLog *logger, Stream * stream,int id,int type,bool allowRead)
|
||||||
{
|
{
|
||||||
LOG_DEBUG(GwLog::DEBUG,"creating GwSerial %p id %d",this,id);
|
LOG_DEBUG(GwLog::DEBUG,"creating GwSerial %p id %d",this,id);
|
||||||
this->id=s->getId();
|
|
||||||
this->logger = logger;
|
this->logger = logger;
|
||||||
|
this->id=id;
|
||||||
|
this->stream=stream;
|
||||||
|
this->type=type;
|
||||||
String bufName="Ser(";
|
String bufName="Ser(";
|
||||||
bufName+=String(id);
|
bufName+=String(id);
|
||||||
bufName+=")";
|
bufName+=")";
|
||||||
|
@ -62,6 +65,20 @@ GwSerial::~GwSerial()
|
||||||
if (readBuffer) delete readBuffer;
|
if (readBuffer) delete readBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String GwSerial::getMode(){
|
||||||
|
switch (type){
|
||||||
|
case GWSERIAL_TYPE_UNI:
|
||||||
|
return "UNI";
|
||||||
|
case GWSERIAL_TYPE_BI:
|
||||||
|
return "BI";
|
||||||
|
case GWSERIAL_TYPE_RX:
|
||||||
|
return "RX";
|
||||||
|
case GWSERIAL_TYPE_TX:
|
||||||
|
return "TX";
|
||||||
|
}
|
||||||
|
return "UNKNOWN";
|
||||||
|
}
|
||||||
|
|
||||||
bool GwSerial::isInitialized() { return initialized; }
|
bool GwSerial::isInitialized() { return initialized; }
|
||||||
size_t GwSerial::enqueue(const uint8_t *data, size_t len, bool partial)
|
size_t GwSerial::enqueue(const uint8_t *data, size_t len, bool partial)
|
||||||
{
|
{
|
||||||
|
@ -70,9 +87,9 @@ size_t GwSerial::enqueue(const uint8_t *data, size_t len, bool partial)
|
||||||
}
|
}
|
||||||
GwBuffer::WriteStatus GwSerial::write(){
|
GwBuffer::WriteStatus GwSerial::write(){
|
||||||
if (! isInitialized()) return GwBuffer::ERROR;
|
if (! isInitialized()) return GwBuffer::ERROR;
|
||||||
size_t numWrite=serial->availableForWrite();
|
size_t numWrite=availableForWrite();
|
||||||
size_t rt=buffer->fetchData(numWrite,[](uint8_t *buffer,size_t len, void *p){
|
size_t rt=buffer->fetchData(numWrite,[](uint8_t *buffer,size_t len, void *p){
|
||||||
return ((GwSerial *)p)->serial->write(buffer,len);
|
return ((GwSerial *)p)->stream->write(buffer,len);
|
||||||
},this);
|
},this);
|
||||||
if (rt != 0){
|
if (rt != 0){
|
||||||
LOG_DEBUG(GwLog::DEBUG+1,"Serial %d write %d",id,rt);
|
LOG_DEBUG(GwLog::DEBUG+1,"Serial %d write %d",id,rt);
|
||||||
|
@ -93,11 +110,11 @@ void GwSerial::loop(bool handleRead,bool handleWrite){
|
||||||
write();
|
write();
|
||||||
if (! isInitialized()) return;
|
if (! isInitialized()) return;
|
||||||
if (! handleRead) return;
|
if (! handleRead) return;
|
||||||
size_t available=serial->available();
|
size_t available=stream->available();
|
||||||
if (! available) return;
|
if (! available) return;
|
||||||
if (allowRead){
|
if (allowRead){
|
||||||
size_t rd=readBuffer->fillData(available,[](uint8_t *buffer, size_t len, void *p)->size_t{
|
size_t rd=readBuffer->fillData(available,[](uint8_t *buffer, size_t len, void *p)->size_t{
|
||||||
return ((GwSerial *)p)->serial->readBytes(buffer,len);
|
return ((GwSerial *)p)->stream->readBytes(buffer,len);
|
||||||
},this);
|
},this);
|
||||||
if (rd != 0){
|
if (rd != 0){
|
||||||
LOG_DEBUG(GwLog::DEBUG+2,"GwSerial %d read %d bytes",id,rd);
|
LOG_DEBUG(GwLog::DEBUG+2,"GwSerial %d read %d bytes",id,rd);
|
||||||
|
@ -106,7 +123,7 @@ void GwSerial::loop(bool handleRead,bool handleWrite){
|
||||||
else{
|
else{
|
||||||
uint8_t buffer[10];
|
uint8_t buffer[10];
|
||||||
if (available > 10) available=10;
|
if (available > 10) available=10;
|
||||||
serial->readBytes(buffer,available);
|
stream->readBytes(buffer,available);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void GwSerial::readMessages(GwMessageFetcher *writer){
|
void GwSerial::readMessages(GwMessageFetcher *writer){
|
||||||
|
@ -115,10 +132,11 @@ void GwSerial::readMessages(GwMessageFetcher *writer){
|
||||||
writer->handleBuffer(readBuffer);
|
writer->handleBuffer(readBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GwSerial::flush(long max){
|
bool GwSerial::flush(){
|
||||||
if (! isInitialized()) return false;
|
if (! isInitialized()) return false;
|
||||||
|
long max=getFlushTimeout();
|
||||||
if (! availableWrite) {
|
if (! availableWrite) {
|
||||||
if ( serial->availableForWrite() < 1){
|
if ( availableForWrite() < 1){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
availableWrite=true;
|
availableWrite=true;
|
||||||
|
@ -128,7 +146,7 @@ bool GwSerial::flush(long max){
|
||||||
if (write() != GwBuffer::AGAIN) return true;
|
if (write() != GwBuffer::AGAIN) return true;
|
||||||
vTaskDelay(1);
|
vTaskDelay(1);
|
||||||
}
|
}
|
||||||
availableWrite=(serial->availableForWrite() > 0);
|
availableWrite=(availableForWrite() > 0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Stream * GwSerial::getStream(bool partialWrite){
|
Stream * GwSerial::getStream(bool partialWrite){
|
||||||
|
|
|
@ -6,10 +6,11 @@
|
||||||
#include "GwChannelInterface.h"
|
#include "GwChannelInterface.h"
|
||||||
class GwSerialStream;
|
class GwSerialStream;
|
||||||
class GwSerial : public GwChannelInterface{
|
class GwSerial : public GwChannelInterface{
|
||||||
private:
|
protected:
|
||||||
GwBuffer *buffer;
|
GwBuffer *buffer;
|
||||||
GwBuffer *readBuffer=NULL;
|
GwBuffer *readBuffer=NULL;
|
||||||
GwLog *logger;
|
GwLog *logger;
|
||||||
|
Stream *stream;
|
||||||
bool initialized=false;
|
bool initialized=false;
|
||||||
bool allowRead=true;
|
bool allowRead=true;
|
||||||
GwBuffer::WriteStatus write();
|
GwBuffer::WriteStatus write();
|
||||||
|
@ -17,36 +18,66 @@ class GwSerial : public GwChannelInterface{
|
||||||
int overflows=0;
|
int overflows=0;
|
||||||
size_t enqueue(const uint8_t *data, size_t len,bool partial=false);
|
size_t enqueue(const uint8_t *data, size_t len,bool partial=false);
|
||||||
bool availableWrite=false; //if this is false we will wait for availabkleWrite until we flush again
|
bool availableWrite=false; //if this is false we will wait for availabkleWrite until we flush again
|
||||||
|
virtual long getFlushTimeout(){return 2000;}
|
||||||
|
virtual int availableForWrite()=0;
|
||||||
|
int type=0;
|
||||||
public:
|
public:
|
||||||
class SerialWrapperBase{
|
GwSerial(GwLog *logger,Stream *stream,int id,int type,bool allowRead=true);
|
||||||
public:
|
virtual ~GwSerial();
|
||||||
virtual void begin(GwLog* logger,unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1)=0;
|
|
||||||
virtual int getId()=0;
|
|
||||||
virtual int available(){return getStream()->available();}
|
|
||||||
size_t readBytes(uint8_t *buffer, size_t length){
|
|
||||||
return getStream()->readBytes(buffer,length);
|
|
||||||
}
|
|
||||||
virtual int availableForWrite(void){
|
|
||||||
return getStream()->availableForWrite();
|
|
||||||
}
|
|
||||||
size_t write(const uint8_t *buffer, size_t size){
|
|
||||||
return getStream()->write(buffer,size);
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
virtual Stream *getStream()=0;
|
|
||||||
};
|
|
||||||
static const int bufferSize=200;
|
|
||||||
GwSerial(GwLog *logger,SerialWrapperBase *stream,bool allowRead=true);
|
|
||||||
~GwSerial();
|
|
||||||
bool isInitialized();
|
bool isInitialized();
|
||||||
virtual size_t sendToClients(const char *buf,int sourceId,bool partial=false);
|
virtual size_t sendToClients(const char *buf,int sourceId,bool partial=false);
|
||||||
virtual void loop(bool handleRead=true,bool handleWrite=true);
|
virtual void loop(bool handleRead=true,bool handleWrite=true);
|
||||||
virtual void readMessages(GwMessageFetcher *writer);
|
virtual void readMessages(GwMessageFetcher *writer);
|
||||||
bool flush(long millis=200);
|
bool flush();
|
||||||
virtual Stream *getStream(bool partialWrites);
|
virtual Stream *getStream(bool partialWrites);
|
||||||
bool getAvailableWrite(){return availableWrite;}
|
bool getAvailableWrite(){return availableWrite;}
|
||||||
|
virtual void begin(unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1)=0;
|
||||||
|
virtual String getMode() override;
|
||||||
friend GwSerialStream;
|
friend GwSerialStream;
|
||||||
private:
|
|
||||||
SerialWrapperBase *serial;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class GwSerialImpl : public GwSerial{
|
||||||
|
private:
|
||||||
|
template<class C>
|
||||||
|
void beginImpl(C *s,unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1){}
|
||||||
|
void beginImpl(HardwareSerial *s,unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1){
|
||||||
|
s->begin(baud,config,rxPin,txPin);
|
||||||
|
}
|
||||||
|
template<class C>
|
||||||
|
void setError(C* s, GwLog *logger){}
|
||||||
|
void setError(HardwareSerial *s,GwLog *logger){
|
||||||
|
LOG_DEBUG(GwLog::LOG,"enable serial errors for channel %d",id);
|
||||||
|
s->onReceiveError([logger,this](hardwareSerial_error_t err){
|
||||||
|
LOG_DEBUG(GwLog::ERROR,"serial error on id %d: %d",this->id,(int)err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
|
||||||
|
void beginImpl(HWCDC *s,unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1){
|
||||||
|
s->begin(baud);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
template<class C>
|
||||||
|
long getFlushTimeoutImpl(const C*){return 2000;}
|
||||||
|
long getFlushTimeoutImpl(HWCDC *){return 200;}
|
||||||
|
|
||||||
|
T *serial;
|
||||||
|
protected:
|
||||||
|
virtual long getFlushTimeout() override{
|
||||||
|
return getFlushTimeoutImpl(serial);
|
||||||
|
}
|
||||||
|
virtual int availableForWrite(){
|
||||||
|
return serial->availableForWrite();
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
GwSerialImpl(GwLog* logger,T* s,int i,int type,bool allowRead=true): GwSerial(logger,s,i,type,allowRead),serial(s){}
|
||||||
|
virtual ~GwSerialImpl(){}
|
||||||
|
virtual void begin(unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1) override{
|
||||||
|
beginImpl(serial,baud,config,rxPin,txPin);
|
||||||
|
setError(serial,logger);
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
Loading…
Reference in New Issue