add some memory diagnostics
This commit is contained in:
parent
56aaf595b4
commit
e7b2c6e756
|
@ -1,7 +1,7 @@
|
|||
#include "GwBoatData.h"
|
||||
|
||||
GwBoatData::GwBoatData(GwLog *logger){
|
||||
|
||||
this->logger=logger;
|
||||
}
|
||||
GwBoatData::~GwBoatData(){
|
||||
GwBoatItemBase::GwBoatItemMap::iterator it;
|
||||
|
|
|
@ -63,13 +63,14 @@ template<class T> class GwBoatItem : public GwBoatItemBase{
|
|||
(*doc)[name]=getData(true);
|
||||
}
|
||||
private:
|
||||
static GwBoatItem<T> *findOrCreate(GwBoatItemMap *values, String name,bool doCreate=true,
|
||||
static GwBoatItem<T> *findOrCreate(GwLog *logger,GwBoatItemMap *values, String name,bool doCreate=true,
|
||||
long invalidTime=GwBoatItemBase::INVALID_TIME, Formatter fmt=NULL){
|
||||
GwBoatItemMap::iterator it;
|
||||
if ((it=values->find(name)) != values->end()){
|
||||
return (GwBoatItem<T> *)it->second;
|
||||
}
|
||||
if (! doCreate) return NULL;
|
||||
LOG_DEBUG(GwLog::DEBUG,"creating boat data item %s",name.c_str());
|
||||
GwBoatItem<T> *ni=new GwBoatItem<T>(invalidTime,fmt);
|
||||
(*values)[name]=ni;
|
||||
return ni;
|
||||
|
@ -83,7 +84,7 @@ template<class T> class GwBoatItem : public GwBoatItemBase{
|
|||
* */
|
||||
#define GWBOATDATA_IMPL_ITEM(type,name) GwBoatItem<type> *get##name##Item(String iname,bool doCreate=true, \
|
||||
long invalidTime=GwBoatItemBase::INVALID_TIME, GwBoatItem<type>::Formatter fmt=NULL){ \
|
||||
return GwBoatItem<type>::findOrCreate(&values,iname, doCreate, \
|
||||
return GwBoatItem<type>::findOrCreate(logger,&values,iname, doCreate, \
|
||||
invalidTime,fmt);\
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,6 @@ class GwLog{
|
|||
void logDebug(int level, const char *fmt,...);
|
||||
int isActive(int level){return level <= logLevel;};
|
||||
};
|
||||
#define LOG_DEBUG(level,...){ if (logger->isActive(level)) logger->logDebug(level,__VA_ARGS__);}
|
||||
#define LOG_DEBUG(level,...){ if (logger != NULL && logger->isActive(level)) logger->logDebug(level,__VA_ARGS__);}
|
||||
|
||||
#endif
|
|
@ -52,6 +52,7 @@ void N2kDataToNMEA0183::SendMessage(const tNMEA0183Msg &NMEA0183Msg) {
|
|||
|
||||
N2kDataToNMEA0183* N2kDataToNMEA0183::create(GwLog *logger, GwBoatData *boatData, tNMEA2000 *NMEA2000,
|
||||
tNMEA0183 *NMEA0183, int sourceId){
|
||||
LOG_DEBUG(GwLog::LOG,"creating N2kToNMEA0183");
|
||||
return new N2kToNMEA0183Functions(logger,boatData,NMEA2000,NMEA0183, sourceId);
|
||||
}
|
||||
//*****************************************************************************
|
||||
|
|
|
@ -53,7 +53,7 @@ public:
|
|||
}
|
||||
virtual void loop();
|
||||
virtual ~N2kDataToNMEA0183(){}
|
||||
virtual const unsigned long* handledPgns()=0;
|
||||
virtual unsigned long* handledPgns()=0;
|
||||
virtual int numPgns()=0;
|
||||
virtual void toJson(JsonDocument &json)=0;
|
||||
};
|
||||
|
|
|
@ -112,7 +112,7 @@ private:
|
|||
ConverterEntry e(converter);
|
||||
converters[pgn] = e;
|
||||
}
|
||||
virtual const unsigned long *handledPgns()
|
||||
virtual unsigned long *handledPgns()
|
||||
{
|
||||
logger->logString("CONV: # %d handled PGNS", (int)converters.size());
|
||||
unsigned long *rt = new unsigned long[converters.size() + 1];
|
||||
|
@ -145,6 +145,7 @@ private:
|
|||
{
|
||||
json["cnv"][String(it->first)] = it->second.count;
|
||||
}
|
||||
json["aisTargets"]=numShips();
|
||||
}
|
||||
virtual int numPgns()
|
||||
{
|
||||
|
@ -897,11 +898,14 @@ public:
|
|||
registerConverter(128275UL, &N2kToNMEA0183Functions::HandleLog);
|
||||
registerConverter(127245UL, &N2kToNMEA0183Functions::HandleRudder);
|
||||
registerConverter(130310UL, &N2kToNMEA0183Functions::HandleWaterTemp);
|
||||
#define HANDLE_AIS 1
|
||||
#ifdef HANDLE_AIS
|
||||
registerConverter(129038UL, &N2kToNMEA0183Functions::HandleAISClassAPosReport); // AIS Class A Position Report, Message Type 1
|
||||
registerConverter(129039UL, &N2kToNMEA0183Functions::HandleAISClassBMessage18); // AIS Class B Position Report, Message Type 18
|
||||
registerConverter(129794UL, &N2kToNMEA0183Functions::HandleAISClassAMessage5); // AIS Class A Ship Static and Voyage related data, Message Type 5
|
||||
registerConverter(129809UL, &N2kToNMEA0183Functions::HandleAISClassBMessage24A); // AIS Class B "CS" Static Data Report, Part A
|
||||
registerConverter(129810UL, &N2kToNMEA0183Functions::HandleAISClassBMessage24B); // AIS Class B "CS" Static Data Report, Part B
|
||||
#endif
|
||||
|
||||
}
|
||||
virtual void loop()
|
||||
|
|
|
@ -51,6 +51,7 @@ const char Prefix='!';
|
|||
|
||||
std::vector<ship *> vships;
|
||||
|
||||
int numShips(){return vships.size();}
|
||||
// ************************ Helper for AIS ***********************************
|
||||
static bool AddMessageType(tNMEA0183AISMsg &NMEA0183AISMsg, uint8_t MessageType);
|
||||
static bool AddRepeat(tNMEA0183AISMsg &NMEA0183AISMsg, uint8_t Repeat);
|
||||
|
@ -250,7 +251,9 @@ bool SetAISClassBMessage24(tNMEA0183AISMsg &NMEA0183AISMsg, uint8_t MessageID,
|
|||
}
|
||||
}
|
||||
if ( i > MAX_SHIP_IN_VECTOR ) {
|
||||
vships.erase(vships.begin());
|
||||
std::vector<ship *>::iterator it=vships.begin();
|
||||
delete *it;
|
||||
vships.erase(it);
|
||||
}
|
||||
|
||||
// AIS Type 24 Message
|
||||
|
|
|
@ -36,7 +36,7 @@ OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#define MAX_SHIP_IN_VECTOR 200
|
||||
#define MAX_SHIP_IN_VECTOR 5
|
||||
class ship {
|
||||
public:
|
||||
uint32_t _userID;
|
||||
|
@ -45,7 +45,6 @@ public:
|
|||
ship(uint32_t UserID, std::string ShipName) : _userID(UserID), _shipName(ShipName) {}
|
||||
};
|
||||
|
||||
extern std::vector<ship *> vships;
|
||||
|
||||
// Types 1, 2 and 3: Position Report Class A or B
|
||||
bool SetAISClassABMessage1(tNMEA0183AISMsg &NMEA0183AISMsg, uint8_t MessageType, uint8_t Repeat,
|
||||
|
@ -78,6 +77,7 @@ bool SetAISClassBMessage24(tNMEA0183AISMsg &NMEA0183AISMsg, uint8_t MessageID,
|
|||
uint32_t UserID, uint8_t VesselType, char *VendorID, char *Callsign,
|
||||
double Length, double Beam, double PosRefStbd, double PosRefBow, uint32_t MothershipID );
|
||||
|
||||
int numShips();
|
||||
inline int32_t aRoundToInt(double x) {
|
||||
return x >= 0
|
||||
? (int32_t) floor(x + 0.5)
|
||||
|
|
|
@ -8,6 +8,7 @@ void GwBuffer::lp(const char *fkt, int p)
|
|||
|
||||
GwBuffer::GwBuffer(GwLog *logger,size_t bufferSize)
|
||||
{
|
||||
LOG_DEBUG(GwLog::DEBUG,"creating new buffer %p of size %d",this,(int)bufferSize);
|
||||
this->logger = logger;
|
||||
this->bufferSize=bufferSize;
|
||||
this->buffer=new uint8_t[bufferSize];
|
||||
|
|
|
@ -15,6 +15,7 @@ class SerialWriter : public GwBufferWriter{
|
|||
};
|
||||
GwSerial::GwSerial(GwLog *logger, uart_port_t num, int id,bool allowRead)
|
||||
{
|
||||
LOG_DEBUG(GwLog::DEBUG,"creating GwSerial %p port %d",this,(int)num);
|
||||
this->id=id;
|
||||
this->logger = logger;
|
||||
this->num = num;
|
||||
|
@ -79,6 +80,7 @@ void GwSerial::sendToClients(const char *buf,int sourceId){
|
|||
}
|
||||
void GwSerial::loop(bool handleRead){
|
||||
write();
|
||||
if (! isInitialized()) return;
|
||||
if (! handleRead) return;
|
||||
char buffer[10];
|
||||
int rt=uart_read_bytes(num,(uint8_t *)(&buffer),10,0);
|
||||
|
@ -87,6 +89,7 @@ void GwSerial::loop(bool handleRead){
|
|||
}
|
||||
}
|
||||
bool GwSerial::readMessages(GwBufferWriter *writer){
|
||||
if (! isInitialized()) return false;
|
||||
if (! allowRead) return false;
|
||||
return readBuffer->fetchMessage(writer,'\n',true) == GwBuffer::OK;
|
||||
}
|
|
@ -68,6 +68,7 @@ class GwClient{
|
|||
overflows=0;
|
||||
if (client != NULL){
|
||||
writer=new Writer(client);
|
||||
LOG_DEBUG(GwLog::DEBUG,"creating SocketWriter %p",writer);
|
||||
remoteIp=client->remoteIP().toString();
|
||||
}
|
||||
}
|
||||
|
@ -76,10 +77,14 @@ class GwClient{
|
|||
buffer->reset();
|
||||
if (readBuffer) readBuffer->reset();
|
||||
overflows=0;
|
||||
if (writer) delete writer;
|
||||
if (writer) {
|
||||
LOG_DEBUG(GwLog::DEBUG,"deleting SocketWriter %p",writer);
|
||||
delete writer;
|
||||
}
|
||||
writer=NULL;
|
||||
if (client){
|
||||
writer=new Writer(client);
|
||||
LOG_DEBUG(GwLog::DEBUG,"creating SocketWriter %p",writer);
|
||||
remoteIp=client->remoteIP().toString();
|
||||
}
|
||||
else{
|
||||
|
@ -162,12 +167,12 @@ GwSocketServer::GwSocketServer(const GwConfigHandler *config,GwLog *logger,int m
|
|||
this->minId=minId;
|
||||
maxClients=config->getInt(config->maxClients);
|
||||
allowReceive=config->getBool(config->readTCP);
|
||||
}
|
||||
void GwSocketServer::begin(){
|
||||
clients=new gwClientPtr[maxClients];
|
||||
for (int i=0;i<maxClients;i++){
|
||||
clients[i]=gwClientPtr(new GwClient(wiFiClientPtr(NULL),logger,allowReceive));
|
||||
}
|
||||
}
|
||||
void GwSocketServer::begin(){
|
||||
server=new WiFiServer(config->getInt(config->serverPort),maxClients);
|
||||
server->begin();
|
||||
logger->logString("Socket server created, port=%d",
|
||||
|
@ -177,6 +182,7 @@ void GwSocketServer::begin(){
|
|||
}
|
||||
void GwSocketServer::loop(bool handleRead)
|
||||
{
|
||||
if (! clients) return;
|
||||
WiFiClient client = server->available(); // listen for incoming clients
|
||||
|
||||
if (client)
|
||||
|
@ -234,7 +240,7 @@ void GwSocketServer::loop(bool handleRead)
|
|||
}
|
||||
|
||||
bool GwSocketServer::readMessages(GwBufferWriter *writer){
|
||||
if (! allowReceive) return false;
|
||||
if (! allowReceive || ! clients) return false;
|
||||
bool hasMessages=false;
|
||||
for (int i = 0; i < maxClients; i++){
|
||||
writer->id=minId+i;
|
||||
|
@ -244,6 +250,7 @@ bool GwSocketServer::readMessages(GwBufferWriter *writer){
|
|||
return hasMessages;
|
||||
}
|
||||
void GwSocketServer::sendToClients(const char *buf,int source){
|
||||
if (! clients) return;
|
||||
int len=strlen(buf);
|
||||
int sourceIndex=source-minId;
|
||||
for (int i = 0; i < maxClients; i++)
|
||||
|
@ -262,6 +269,7 @@ void GwSocketServer::sendToClients(const char *buf,int source){
|
|||
}
|
||||
|
||||
int GwSocketServer::numClients(){
|
||||
if (! clients) return 0;
|
||||
int num=0;
|
||||
for (int i = 0; i < maxClients; i++){
|
||||
if (clients[i]->hasClient()) num++;
|
||||
|
|
|
@ -13,7 +13,7 @@ class GwSocketServer{
|
|||
private:
|
||||
const GwConfigHandler *config;
|
||||
GwLog *logger;
|
||||
gwClientPtr *clients;
|
||||
gwClientPtr *clients=NULL;
|
||||
WiFiServer *server=NULL;
|
||||
bool allowReceive;
|
||||
int maxClients;
|
||||
|
|
|
@ -20,7 +20,7 @@ lib_deps =
|
|||
board_build.embed_files =
|
||||
generated/index.html.gz
|
||||
generated/config.json.gz
|
||||
extra_scripts = extra_script.py
|
||||
extra_scripts = pre:extra_script.py
|
||||
build_flags=
|
||||
-Igenerated
|
||||
|
||||
|
|
23
src/main.cpp
23
src/main.cpp
|
@ -25,6 +25,7 @@
|
|||
#include <ArduinoJson.h>
|
||||
#include <ESPmDNS.h>
|
||||
#include <map>
|
||||
#include "esp_heap_caps.h"
|
||||
|
||||
#include "N2kDataToNMEA0183.h"
|
||||
|
||||
|
@ -65,7 +66,7 @@ Preferences preferences; // Nonvolatile storage on ESP32 - To store
|
|||
bool SendNMEA0183Conversion = true; // Do we send NMEA2000 -> NMEA0183 conversion
|
||||
bool SendSeaSmart = false; // Do we send NMEA2000 messages in SeaSmart format
|
||||
|
||||
N2kDataToNMEA0183 *nmea0183Converter=N2kDataToNMEA0183::create(&logger, &boatData,&NMEA2000, 0, N2K_CHANNEL_ID);
|
||||
N2kDataToNMEA0183 *nmea0183Converter=NULL;
|
||||
|
||||
// Set the information for other bus devices, which messages we support
|
||||
const unsigned long TransmitMessages[] PROGMEM = {127489L, // Engine dynamic
|
||||
|
@ -193,7 +194,7 @@ GwConfigInterface *sendTCP=NULL;
|
|||
GwConfigInterface *sendSeasmart=NULL;
|
||||
GwConfigInterface *systemName=NULL;
|
||||
|
||||
GwSerial usbSerial(&logger, UART_NUM_0, USB_CHANNEL_ID);
|
||||
GwSerial usbSerial(NULL, UART_NUM_0, USB_CHANNEL_ID);
|
||||
class GwSerialLog : public GwLogWriter{
|
||||
public:
|
||||
virtual ~GwSerialLog(){}
|
||||
|
@ -357,6 +358,7 @@ void setup() {
|
|||
|
||||
MDNS.addService("_http","_tcp",80);
|
||||
|
||||
nmea0183Converter= N2kDataToNMEA0183::create(&logger, &boatData,&NMEA2000, 0, N2K_CHANNEL_ID);
|
||||
// Reserve enough buffer for sending all messages. This does not work on small memory devices like Uno or Mega
|
||||
|
||||
NMEA2000.SetN2kCANMsgBufSize(8);
|
||||
|
@ -493,9 +495,21 @@ class NMEAMessageReceiver : public GwBufferWriter{
|
|||
writePointer=buffer;
|
||||
}
|
||||
};
|
||||
NMEAMessageReceiver receiver;
|
||||
unsigned long lastHeapReport=0;
|
||||
const unsigned long HEAP_REPORT_TIME=2000;
|
||||
void loop() {
|
||||
gwWifi.loop();
|
||||
|
||||
unsigned long now=millis();
|
||||
if (now > (lastHeapReport+HEAP_REPORT_TIME)){
|
||||
lastHeapReport=now;
|
||||
if (logger.isActive(GwLog::DEBUG)){
|
||||
logger.logDebug(GwLog::DEBUG,"Heap free=%ld, minFree=%ld",
|
||||
(long)xPortGetFreeHeapSize(),
|
||||
(long)xPortGetMinimumEverFreeHeapSize()
|
||||
);
|
||||
}
|
||||
}
|
||||
handleSendAndRead(true);
|
||||
NMEA2000.ParseMessages();
|
||||
|
||||
|
@ -512,11 +526,10 @@ void loop() {
|
|||
//handle messages from the async web server
|
||||
Message *msg=NULL;
|
||||
if (xQueueReceive(queue,&msg,0)){
|
||||
logger.logDebug(GwLog::DEBUG+1,"main message");
|
||||
logger.logDebug(GwLog::DEBUG,"main message");
|
||||
msg->process();
|
||||
msg->unref();
|
||||
}
|
||||
NMEAMessageReceiver receiver;
|
||||
socketServer.readMessages(&receiver);
|
||||
//read channels
|
||||
|
||||
|
|
Loading…
Reference in New Issue