separate boat data, integrate with web server
This commit is contained in:
parent
fb20135718
commit
3bbd9ef965
|
@ -0,0 +1,54 @@
|
||||||
|
#include "GwBoatData.h"
|
||||||
|
|
||||||
|
GwBoatItem *GwBoatData::find(String name,bool doCreate){
|
||||||
|
GwBoatItemMap::iterator it;
|
||||||
|
if ((it=values.find(name)) != values.end()){
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
if (! doCreate) return NULL;
|
||||||
|
GwBoatItem *ni=new GwBoatItem();
|
||||||
|
values[name]=ni;
|
||||||
|
return ni;
|
||||||
|
}
|
||||||
|
GwBoatData::GwBoatData(GwLog *logger){
|
||||||
|
|
||||||
|
}
|
||||||
|
GwBoatData::~GwBoatData(){
|
||||||
|
GwBoatItemMap::iterator it;
|
||||||
|
for (it=values.begin() ; it != values.end();it++){
|
||||||
|
delete it->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void GwBoatData::update(String name,const char *value){
|
||||||
|
GwBoatItem *i=find(name);
|
||||||
|
i->update(value);
|
||||||
|
}
|
||||||
|
void GwBoatData::update(String name, String value){
|
||||||
|
GwBoatItem *i=find(name);
|
||||||
|
i->update(value);
|
||||||
|
}
|
||||||
|
void GwBoatData::update(String name, long value){
|
||||||
|
GwBoatItem *i=find(name);
|
||||||
|
i->update(value);
|
||||||
|
}
|
||||||
|
void GwBoatData::update(String name, double value){
|
||||||
|
GwBoatItem *i=find(name);
|
||||||
|
i->update(value);
|
||||||
|
}
|
||||||
|
void GwBoatData::update(String name, bool value){
|
||||||
|
GwBoatItem *i=find(name);
|
||||||
|
i->update(value);
|
||||||
|
}
|
||||||
|
String GwBoatData::toJson() const {
|
||||||
|
long minTime=millis() - maxAge;
|
||||||
|
DynamicJsonDocument json(800);
|
||||||
|
GwBoatItemMap::const_iterator it;
|
||||||
|
for (it=values.begin() ; it != values.end();it++){
|
||||||
|
if (it->second->isValid(minTime)){
|
||||||
|
json[it->first]=it->second->getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String buf;
|
||||||
|
serializeJson(json,buf);
|
||||||
|
return buf;
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
#ifndef _GWBOATDATA_H
|
||||||
|
#define _GWBOATDATA_H
|
||||||
|
|
||||||
|
#include "GwLog.h"
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <map>
|
||||||
|
#define GW_BOAT_VALUE_LEN 32
|
||||||
|
class GwBoatItem{
|
||||||
|
private:
|
||||||
|
char value[GW_BOAT_VALUE_LEN];
|
||||||
|
long lastSet;
|
||||||
|
void uls(){
|
||||||
|
lastSet=millis();
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
const char * getValue() const{return value;}
|
||||||
|
long getLastSet() const {return lastSet;}
|
||||||
|
bool isValid(long minTime) const {return lastSet > minTime;}
|
||||||
|
GwBoatItem(){
|
||||||
|
value[0]=0;
|
||||||
|
lastSet=-1;
|
||||||
|
}
|
||||||
|
void update(String nv){
|
||||||
|
strncpy(value,nv.c_str(),GW_BOAT_VALUE_LEN-1);
|
||||||
|
uls();
|
||||||
|
}
|
||||||
|
void update(const char * nv){
|
||||||
|
strncpy(value,nv,GW_BOAT_VALUE_LEN-1);
|
||||||
|
}
|
||||||
|
void update(long nv){
|
||||||
|
ltoa(nv,value,10);
|
||||||
|
uls();
|
||||||
|
}
|
||||||
|
void update(bool nv){
|
||||||
|
if (nv) strcpy_P(value,PSTR("true"));
|
||||||
|
else strcpy_P(value,PSTR("false"));
|
||||||
|
uls();
|
||||||
|
}
|
||||||
|
void update(double nv){
|
||||||
|
dtostrf(nv,3,7,value);
|
||||||
|
uls();
|
||||||
|
}
|
||||||
|
void invalidate(){
|
||||||
|
lastSet=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
class GwBoatData{
|
||||||
|
typedef std::map<String,GwBoatItem*> GwBoatItemMap;
|
||||||
|
private:
|
||||||
|
const long maxAge=60000; //max age for valid data in ms
|
||||||
|
GwLog *logger;
|
||||||
|
GwBoatItemMap values;
|
||||||
|
GwBoatItem *find(String name, bool doCreate=true);
|
||||||
|
public:
|
||||||
|
GwBoatData(GwLog *logger);
|
||||||
|
~GwBoatData();
|
||||||
|
void update(String name,const char *value);
|
||||||
|
void update(String name, String value);
|
||||||
|
void update(String name, long value);
|
||||||
|
void update(String name, bool value);
|
||||||
|
void update(String name, double value);
|
||||||
|
String toJson() const;
|
||||||
|
|
||||||
|
};
|
||||||
|
#endif
|
|
@ -26,12 +26,11 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include "N2kDataToNMEA0183.h"
|
#include "N2kDataToNMEA0183.h"
|
||||||
#include "BoatData.h"
|
|
||||||
|
|
||||||
const double radToDeg = 180.0 / M_PI;
|
const double radToDeg = 180.0 / M_PI;
|
||||||
|
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
void tN2kDataToNMEA0183::HandleMsg(const tN2kMsg &N2kMsg) {
|
void N2kDataToNMEA0183::HandleMsg(const tN2kMsg &N2kMsg) {
|
||||||
switch (N2kMsg.PGN) {
|
switch (N2kMsg.PGN) {
|
||||||
case 127250UL: HandleHeading(N2kMsg);
|
case 127250UL: HandleHeading(N2kMsg);
|
||||||
case 127258UL: HandleVariation(N2kMsg);
|
case 127258UL: HandleVariation(N2kMsg);
|
||||||
|
@ -48,18 +47,21 @@ void tN2kDataToNMEA0183::HandleMsg(const tN2kMsg &N2kMsg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
long tN2kDataToNMEA0183::Update(tBoatData *BoatData) {
|
void N2kDataToNMEA0183::loop() {
|
||||||
|
unsigned long now=millis();
|
||||||
|
if ( now < (lastLoopTime + 100)) return;
|
||||||
|
lastLoopTime=now;
|
||||||
SendRMC();
|
SendRMC();
|
||||||
if ( LastHeadingTime + 2000 < millis() ) Heading = N2kDoubleNA;
|
if ( (LastHeadingTime + 2000) < now ) Heading = N2kDoubleNA;
|
||||||
if ( LastCOGSOGTime + 2000 < millis() ) {
|
if ( (LastCOGSOGTime + 2000) < now ) {
|
||||||
COG = N2kDoubleNA;
|
COG = N2kDoubleNA;
|
||||||
SOG = N2kDoubleNA;
|
SOG = N2kDoubleNA;
|
||||||
}
|
}
|
||||||
if ( LastPositionTime + 4000 < millis() ) {
|
if ( (LastPositionTime + 4000) < now ) {
|
||||||
Latitude = N2kDoubleNA;
|
Latitude = N2kDoubleNA;
|
||||||
Longitude = N2kDoubleNA;
|
Longitude = N2kDoubleNA;
|
||||||
}
|
}
|
||||||
if ( LastWindTime + 2000 < millis() ) {
|
if ( ( LastWindTime + 2000) < now ) {
|
||||||
AWS = N2kDoubleNA;
|
AWS = N2kDoubleNA;
|
||||||
AWA = N2kDoubleNA;
|
AWA = N2kDoubleNA;
|
||||||
TWS = N2kDoubleNA;
|
TWS = N2kDoubleNA;
|
||||||
|
@ -67,45 +69,39 @@ long tN2kDataToNMEA0183::Update(tBoatData *BoatData) {
|
||||||
TWD = N2kDoubleNA;
|
TWD = N2kDoubleNA;
|
||||||
}
|
}
|
||||||
|
|
||||||
BoatData->Latitude=Latitude;
|
boatData->update(F("Latitude"),Latitude);
|
||||||
BoatData->Longitude=Longitude;
|
boatData->update(F("Longitude"),Longitude);
|
||||||
BoatData->Altitude=Altitude;
|
boatData->update(F("Altitude"),Altitude);
|
||||||
BoatData->Heading=Heading * radToDeg;
|
boatData->update(F("Heading"),Heading * radToDeg);
|
||||||
BoatData->COG=COG * radToDeg;
|
boatData->update(F("COG"),COG * radToDeg);
|
||||||
BoatData->SOG=SOG * 3600.0/1852.0;
|
boatData->update(F("SOG"),SOG * 3600.0/1852.0);
|
||||||
BoatData->STW=STW * 3600.0/1852.0;
|
boatData->update(F("STW"),STW * 3600.0/1852.0);
|
||||||
BoatData->AWS=AWS * 3600.0/1852.0;
|
boatData->update(F("AWS"),AWS * 3600.0/1852.0);
|
||||||
BoatData->TWS=TWS * 3600.0/1852.0;
|
boatData->update(F("TWS"),TWS * 3600.0/1852.0);
|
||||||
BoatData->MaxAws=MaxAws * 3600.0/1852.0;;
|
boatData->update(F("MaxAws"),MaxAws * 3600.0/1852.0);
|
||||||
BoatData->MaxTws=MaxTws * 3600.0/1852.0;;
|
boatData->update(F("MaxTws"),MaxTws * 3600.0/1852.0);
|
||||||
BoatData->AWA=AWA * radToDeg;
|
boatData->update(F("AWA"),AWA * radToDeg);
|
||||||
BoatData->TWA=TWA * radToDeg;
|
boatData->update(F("TWA"),TWA * radToDeg);
|
||||||
BoatData->TWD=TWD * radToDeg;
|
boatData->update(F("TWD"),TWD * radToDeg);
|
||||||
BoatData->TripLog=TripLog / 1825.0;
|
boatData->update(F("TripLog"),TripLog / 1825.0);
|
||||||
BoatData->Log=Log / 1825.0;
|
boatData->update(F("Log"),Log / 1825.0);
|
||||||
BoatData->RudderPosition=RudderPosition * radToDeg;
|
boatData->update(F("RudderPosition"),RudderPosition * radToDeg);
|
||||||
BoatData->WaterTemperature=KelvinToC(WaterTemperature) ;
|
boatData->update(F("WaterTemperature"),KelvinToC(WaterTemperature)) ;
|
||||||
BoatData->WaterDepth=WaterDepth;
|
boatData->update(F("WaterDepth"),WaterDepth);
|
||||||
BoatData->Variation=Variation *radToDeg;
|
boatData->update(F("Variation"),Variation *radToDeg);
|
||||||
BoatData->GPSTime=SecondsSinceMidnight;
|
boatData->update(F("GPSTime"),SecondsSinceMidnight);
|
||||||
BoatData->DaysSince1970=DaysSince1970;
|
boatData->update(F("DaysSince1970"),(long)DaysSince1970);
|
||||||
|
|
||||||
|
|
||||||
if (SecondsSinceMidnight!=N2kDoubleNA && DaysSince1970!=N2kUInt16NA){
|
|
||||||
return((DaysSince1970*3600*24)+SecondsSinceMidnight); // Needed for SD Filename and time
|
|
||||||
} else {
|
|
||||||
return(0); // Needed for SD Filename and time
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
void tN2kDataToNMEA0183::SendMessage(const tNMEA0183Msg &NMEA0183Msg) {
|
void N2kDataToNMEA0183::SendMessage(const tNMEA0183Msg &NMEA0183Msg) {
|
||||||
if ( pNMEA0183 != 0 ) pNMEA0183->SendMessage(NMEA0183Msg);
|
if ( pNMEA0183 != 0 ) pNMEA0183->SendMessage(NMEA0183Msg);
|
||||||
if ( SendNMEA0183MessageCallback != 0 ) SendNMEA0183MessageCallback(NMEA0183Msg);
|
if ( SendNMEA0183MessageCallback != 0 ) SendNMEA0183MessageCallback(NMEA0183Msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
void tN2kDataToNMEA0183::HandleHeading(const tN2kMsg &N2kMsg) {
|
void N2kDataToNMEA0183::HandleHeading(const tN2kMsg &N2kMsg) {
|
||||||
unsigned char SID;
|
unsigned char SID;
|
||||||
tN2kHeadingReference ref;
|
tN2kHeadingReference ref;
|
||||||
double _Deviation = 0;
|
double _Deviation = 0;
|
||||||
|
@ -125,7 +121,7 @@ void tN2kDataToNMEA0183::HandleHeading(const tN2kMsg &N2kMsg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
void tN2kDataToNMEA0183::HandleVariation(const tN2kMsg &N2kMsg) {
|
void N2kDataToNMEA0183::HandleVariation(const tN2kMsg &N2kMsg) {
|
||||||
unsigned char SID;
|
unsigned char SID;
|
||||||
tN2kMagneticVariation Source;
|
tN2kMagneticVariation Source;
|
||||||
uint16_t DaysSince1970;
|
uint16_t DaysSince1970;
|
||||||
|
@ -134,7 +130,7 @@ void tN2kDataToNMEA0183::HandleVariation(const tN2kMsg &N2kMsg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
void tN2kDataToNMEA0183::HandleBoatSpeed(const tN2kMsg &N2kMsg) {
|
void N2kDataToNMEA0183::HandleBoatSpeed(const tN2kMsg &N2kMsg) {
|
||||||
unsigned char SID;
|
unsigned char SID;
|
||||||
double WaterReferenced;
|
double WaterReferenced;
|
||||||
double GroundReferenced;
|
double GroundReferenced;
|
||||||
|
@ -151,7 +147,7 @@ void tN2kDataToNMEA0183::HandleBoatSpeed(const tN2kMsg &N2kMsg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
void tN2kDataToNMEA0183::HandleDepth(const tN2kMsg &N2kMsg) {
|
void N2kDataToNMEA0183::HandleDepth(const tN2kMsg &N2kMsg) {
|
||||||
unsigned char SID;
|
unsigned char SID;
|
||||||
double DepthBelowTransducer;
|
double DepthBelowTransducer;
|
||||||
double Offset;
|
double Offset;
|
||||||
|
@ -172,7 +168,7 @@ void tN2kDataToNMEA0183::HandleDepth(const tN2kMsg &N2kMsg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
void tN2kDataToNMEA0183::HandlePosition(const tN2kMsg &N2kMsg) {
|
void N2kDataToNMEA0183::HandlePosition(const tN2kMsg &N2kMsg) {
|
||||||
|
|
||||||
if ( ParseN2kPGN129025(N2kMsg, Latitude, Longitude) ) {
|
if ( ParseN2kPGN129025(N2kMsg, Latitude, Longitude) ) {
|
||||||
LastPositionTime = millis();
|
LastPositionTime = millis();
|
||||||
|
@ -180,7 +176,7 @@ void tN2kDataToNMEA0183::HandlePosition(const tN2kMsg &N2kMsg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
void tN2kDataToNMEA0183::HandleCOGSOG(const tN2kMsg &N2kMsg) {
|
void N2kDataToNMEA0183::HandleCOGSOG(const tN2kMsg &N2kMsg) {
|
||||||
unsigned char SID;
|
unsigned char SID;
|
||||||
tN2kHeadingReference HeadingReference;
|
tN2kHeadingReference HeadingReference;
|
||||||
tNMEA0183Msg NMEA0183Msg;
|
tNMEA0183Msg NMEA0183Msg;
|
||||||
|
@ -199,7 +195,7 @@ void tN2kDataToNMEA0183::HandleCOGSOG(const tN2kMsg &N2kMsg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
void tN2kDataToNMEA0183::HandleGNSS(const tN2kMsg &N2kMsg) {
|
void N2kDataToNMEA0183::HandleGNSS(const tN2kMsg &N2kMsg) {
|
||||||
unsigned char SID;
|
unsigned char SID;
|
||||||
tN2kGNSStype GNSStype;
|
tN2kGNSStype GNSStype;
|
||||||
tN2kGNSSmethod GNSSmethod;
|
tN2kGNSSmethod GNSSmethod;
|
||||||
|
@ -220,7 +216,7 @@ void tN2kDataToNMEA0183::HandleGNSS(const tN2kMsg &N2kMsg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
void tN2kDataToNMEA0183::HandleWind(const tN2kMsg &N2kMsg) {
|
void N2kDataToNMEA0183::HandleWind(const tN2kMsg &N2kMsg) {
|
||||||
unsigned char SID;
|
unsigned char SID;
|
||||||
tN2kWindReference WindReference;
|
tN2kWindReference WindReference;
|
||||||
tNMEA0183WindReference NMEA0183Reference = NMEA0183Wind_True;
|
tNMEA0183WindReference NMEA0183Reference = NMEA0183Wind_True;
|
||||||
|
@ -283,7 +279,7 @@ void tN2kDataToNMEA0183::HandleWind(const tN2kMsg &N2kMsg) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
void tN2kDataToNMEA0183::SendRMC() {
|
void N2kDataToNMEA0183::SendRMC() {
|
||||||
if ( NextRMCSend <= millis() && !N2kIsNA(Latitude) ) {
|
if ( NextRMCSend <= millis() && !N2kIsNA(Latitude) ) {
|
||||||
tNMEA0183Msg NMEA0183Msg;
|
tNMEA0183Msg NMEA0183Msg;
|
||||||
if ( NMEA0183SetRMC(NMEA0183Msg, SecondsSinceMidnight, Latitude, Longitude, COG, SOG, DaysSince1970, Variation) ) {
|
if ( NMEA0183SetRMC(NMEA0183Msg, SecondsSinceMidnight, Latitude, Longitude, COG, SOG, DaysSince1970, Variation) ) {
|
||||||
|
@ -295,7 +291,7 @@ void tN2kDataToNMEA0183::HandleWind(const tN2kMsg &N2kMsg) {
|
||||||
|
|
||||||
|
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
void tN2kDataToNMEA0183::HandleLog(const tN2kMsg & N2kMsg) {
|
void N2kDataToNMEA0183::HandleLog(const tN2kMsg & N2kMsg) {
|
||||||
uint16_t DaysSince1970;
|
uint16_t DaysSince1970;
|
||||||
double SecondsSinceMidnight;
|
double SecondsSinceMidnight;
|
||||||
|
|
||||||
|
@ -314,7 +310,7 @@ void tN2kDataToNMEA0183::HandleWind(const tN2kMsg &N2kMsg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
void tN2kDataToNMEA0183::HandleRudder(const tN2kMsg & N2kMsg) {
|
void N2kDataToNMEA0183::HandleRudder(const tN2kMsg & N2kMsg) {
|
||||||
|
|
||||||
unsigned char Instance;
|
unsigned char Instance;
|
||||||
tN2kRudderDirectionOrder RudderDirectionOrder;
|
tN2kRudderDirectionOrder RudderDirectionOrder;
|
||||||
|
@ -337,7 +333,7 @@ void tN2kDataToNMEA0183::HandleWind(const tN2kMsg &N2kMsg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
void tN2kDataToNMEA0183::HandleWaterTemp(const tN2kMsg & N2kMsg) {
|
void N2kDataToNMEA0183::HandleWaterTemp(const tN2kMsg & N2kMsg) {
|
||||||
|
|
||||||
unsigned char SID;
|
unsigned char SID;
|
||||||
double OutsideAmbientAirTemperature;
|
double OutsideAmbientAirTemperature;
|
|
@ -24,12 +24,15 @@ OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
#include <NMEA0183.h>
|
#include <NMEA0183.h>
|
||||||
#include <NMEA2000.h>
|
#include <NMEA2000.h>
|
||||||
|
|
||||||
#include "BoatData.h"
|
|
||||||
|
#include <GwLog.h>
|
||||||
|
#include <GwBoatData.h>
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
class tN2kDataToNMEA0183 : public tNMEA2000::tMsgHandler {
|
class N2kDataToNMEA0183 : public tNMEA2000::tMsgHandler {
|
||||||
public:
|
public:
|
||||||
using tSendNMEA0183MessageCallback=void (*)(const tNMEA0183Msg &NMEA0183Msg);
|
using tSendNMEA0183MessageCallback=void (*)(const tNMEA0183Msg &NMEA0183Msg);
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static const unsigned long RMCPeriod=500;
|
static const unsigned long RMCPeriod=500;
|
||||||
|
@ -69,6 +72,10 @@ protected:
|
||||||
unsigned long LastPosSend;
|
unsigned long LastPosSend;
|
||||||
unsigned long LastWindTime;
|
unsigned long LastWindTime;
|
||||||
unsigned long NextRMCSend;
|
unsigned long NextRMCSend;
|
||||||
|
unsigned long lastLoopTime;
|
||||||
|
|
||||||
|
GwLog *logger;
|
||||||
|
GwBoatData *boatData;
|
||||||
|
|
||||||
tNMEA0183 *pNMEA0183;
|
tNMEA0183 *pNMEA0183;
|
||||||
tSendNMEA0183MessageCallback SendNMEA0183MessageCallback;
|
tSendNMEA0183MessageCallback SendNMEA0183MessageCallback;
|
||||||
|
@ -92,22 +99,25 @@ protected:
|
||||||
void SendMessage(const tNMEA0183Msg &NMEA0183Msg);
|
void SendMessage(const tNMEA0183Msg &NMEA0183Msg);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
tN2kDataToNMEA0183(tNMEA2000 *_pNMEA2000, tNMEA0183 *_pNMEA0183) : tNMEA2000::tMsgHandler(0,_pNMEA2000) {
|
N2kDataToNMEA0183(GwLog * logger, GwBoatData *boatData, tNMEA2000 *NMEA2000, tNMEA0183 *NMEA0183) : tNMEA2000::tMsgHandler(0,NMEA2000) {
|
||||||
SendNMEA0183MessageCallback=0;
|
SendNMEA0183MessageCallback=0;
|
||||||
pNMEA0183=_pNMEA0183;
|
pNMEA0183=NMEA0183;
|
||||||
Latitude=N2kDoubleNA; Longitude=N2kDoubleNA; Altitude=N2kDoubleNA;
|
Latitude=N2kDoubleNA; Longitude=N2kDoubleNA; Altitude=N2kDoubleNA;
|
||||||
Variation=N2kDoubleNA; Heading=N2kDoubleNA; COG=N2kDoubleNA; SOG=N2kDoubleNA;
|
Variation=N2kDoubleNA; Heading=N2kDoubleNA; COG=N2kDoubleNA; SOG=N2kDoubleNA;
|
||||||
SecondsSinceMidnight=N2kDoubleNA; DaysSince1970=N2kUInt16NA;
|
SecondsSinceMidnight=N2kDoubleNA; DaysSince1970=N2kUInt16NA;
|
||||||
LastPosSend=0;
|
LastPosSend=0;
|
||||||
|
lastLoopTime=0;
|
||||||
NextRMCSend=millis()+RMCPeriod;
|
NextRMCSend=millis()+RMCPeriod;
|
||||||
LastHeadingTime=0;
|
LastHeadingTime=0;
|
||||||
LastCOGSOGTime=0;
|
LastCOGSOGTime=0;
|
||||||
LastPositionTime=0;
|
LastPositionTime=0;
|
||||||
LastWindTime=0;
|
LastWindTime=0;
|
||||||
|
this->logger=logger;
|
||||||
|
this->boatData=boatData;
|
||||||
}
|
}
|
||||||
void HandleMsg(const tN2kMsg &N2kMsg);
|
void HandleMsg(const tN2kMsg &N2kMsg);
|
||||||
void SetSendNMEA0183MessageCallback(tSendNMEA0183MessageCallback _SendNMEA0183MessageCallback) {
|
void SetSendNMEA0183MessageCallback(tSendNMEA0183MessageCallback _SendNMEA0183MessageCallback) {
|
||||||
SendNMEA0183MessageCallback=_SendNMEA0183MessageCallback;
|
SendNMEA0183MessageCallback=_SendNMEA0183MessageCallback;
|
||||||
}
|
}
|
||||||
long Update(tBoatData *BoatData);
|
void loop();
|
||||||
};
|
};
|
|
@ -1,38 +0,0 @@
|
||||||
#ifndef _BoatData_H_
|
|
||||||
#define _BoatData_H_
|
|
||||||
|
|
||||||
struct tBoatData {
|
|
||||||
unsigned long DaysSince1970; // Days since 1970-01-01
|
|
||||||
|
|
||||||
double Heading,SOG,COG,STW,Variation,AWS,TWS,MaxAws,MaxTws,AWA,TWA,AWD,TWD,TripLog,Log,RudderPosition,WaterTemperature,
|
|
||||||
WaterDepth, GPSTime,// Secs since midnight,
|
|
||||||
Latitude, Longitude, Altitude;
|
|
||||||
|
|
||||||
public:
|
|
||||||
tBoatData() {
|
|
||||||
Heading=0;
|
|
||||||
Latitude=0;
|
|
||||||
Longitude=0;
|
|
||||||
SOG=0;
|
|
||||||
COG=0;
|
|
||||||
STW=0;
|
|
||||||
AWS=0;
|
|
||||||
TWS=0;
|
|
||||||
MaxAws=0;
|
|
||||||
MaxTws=0;
|
|
||||||
AWA=0;
|
|
||||||
TWA=0;
|
|
||||||
TWD=0;
|
|
||||||
TripLog=0;
|
|
||||||
Log=0;
|
|
||||||
RudderPosition=0;
|
|
||||||
WaterTemperature=0;
|
|
||||||
WaterDepth=0;
|
|
||||||
Variation=0;
|
|
||||||
Altitude=0;
|
|
||||||
GPSTime=0;
|
|
||||||
DaysSince1970=0;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // _BoatData_H_
|
|
97
src/main.cpp
97
src/main.cpp
|
@ -28,27 +28,24 @@
|
||||||
|
|
||||||
#include "N2kDataToNMEA0183.h"
|
#include "N2kDataToNMEA0183.h"
|
||||||
|
|
||||||
#include "BoatData.h"
|
|
||||||
|
|
||||||
#include "GwLog.h"
|
#include "GwLog.h"
|
||||||
#include "GWConfig.h"
|
#include "GWConfig.h"
|
||||||
#include "GWWifi.h"
|
#include "GWWifi.h"
|
||||||
#include "GwSocketServer.h"
|
#include "GwSocketServer.h"
|
||||||
|
#include "GwBoatData.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define ENABLE_DEBUG_LOG 0 // Debug log, set to 1 to enable AIS forward on USB-Serial / 2 for ADC voltage to support calibration
|
|
||||||
#define UDP_Forwarding 0 // Set to 1 for forwarding AIS from serial2 to UDP brodcast
|
#define UDP_Forwarding 0 // Set to 1 for forwarding AIS from serial2 to UDP brodcast
|
||||||
#define NMEA_TO_SERIAL 1
|
|
||||||
#define HighTempAlarm 12 // Alarm level for fridge temperature (higher)
|
|
||||||
#define LowVoltageAlarm 11 // Alarm level for battery voltage (lower)
|
|
||||||
|
|
||||||
|
|
||||||
GwLog logger(LOG_SERIAL);
|
GwLog logger(LOG_SERIAL);
|
||||||
GwConfigHandler config(&logger);
|
GwConfigHandler config(&logger);
|
||||||
GwWifi gwWifi(&config,&logger);
|
GwWifi gwWifi(&config,&logger);
|
||||||
GwSocketServer socketServer(&config,&logger);
|
GwSocketServer socketServer(&config,&logger);
|
||||||
|
GwBoatData boatData(&logger);
|
||||||
|
|
||||||
|
|
||||||
//counter
|
//counter
|
||||||
|
@ -63,9 +60,6 @@ const int udpPort = 2000; // port 2000 lets think Navionics it is an DY WLN10 de
|
||||||
// Create UDP instance
|
// Create UDP instance
|
||||||
WiFiUDP udp;
|
WiFiUDP udp;
|
||||||
|
|
||||||
// Struct to update BoatData. See BoatData.h for content
|
|
||||||
tBoatData BoatData;
|
|
||||||
|
|
||||||
int NodeAddress; // To store last Node Address
|
int NodeAddress; // To store last Node Address
|
||||||
|
|
||||||
Preferences preferences; // Nonvolatile storage on ESP32 - To store LastDeviceAddress
|
Preferences preferences; // Nonvolatile storage on ESP32 - To store LastDeviceAddress
|
||||||
|
@ -78,10 +72,7 @@ const size_t MaxClients = 10;
|
||||||
bool SendNMEA0183Conversion = true; // Do we send NMEA2000 -> NMEA0183 conversion
|
bool SendNMEA0183Conversion = true; // Do we send NMEA2000 -> NMEA0183 conversion
|
||||||
bool SendSeaSmart = false; // Do we send NMEA2000 messages in SeaSmart format
|
bool SendSeaSmart = false; // Do we send NMEA2000 messages in SeaSmart format
|
||||||
|
|
||||||
WiFiServer json(90);
|
N2kDataToNMEA0183 nmea0183Converter(&logger, &boatData,&NMEA2000, 0);
|
||||||
|
|
||||||
|
|
||||||
tN2kDataToNMEA0183 nmea0183Converter(&NMEA2000, 0);
|
|
||||||
|
|
||||||
// Set the information for other bus devices, which messages we support
|
// Set the information for other bus devices, which messages we support
|
||||||
const unsigned long TransmitMessages[] PROGMEM = {127489L, // Engine dynamic
|
const unsigned long TransmitMessages[] PROGMEM = {127489L, // Engine dynamic
|
||||||
|
@ -127,11 +118,6 @@ tNMEA0183Msg NMEA0183Msg;
|
||||||
tNMEA0183 NMEA0183;
|
tNMEA0183 NMEA0183;
|
||||||
|
|
||||||
|
|
||||||
void debug_log(char* str) {
|
|
||||||
#if ENABLE_DEBUG_LOG == 1
|
|
||||||
Serial.println(str);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#define JSON_OK "{\"status\":\"OK\"}"
|
#define JSON_OK "{\"status\":\"OK\"}"
|
||||||
//embedded files
|
//embedded files
|
||||||
|
@ -168,6 +154,10 @@ void js_config(){
|
||||||
webserver.send(200,F("application/json"),config.toJson());
|
webserver.send(200,F("application/json"),config.toJson());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void js_boatData(){
|
||||||
|
webserver.send(200,F("application/json"),boatData.toJson());
|
||||||
|
}
|
||||||
|
|
||||||
void web_setConfig(){
|
void web_setConfig(){
|
||||||
bool ok=true;
|
bool ok=true;
|
||||||
String error;
|
String error;
|
||||||
|
@ -235,10 +225,6 @@ void setup() {
|
||||||
// Start TCP server
|
// Start TCP server
|
||||||
socketServer.begin();
|
socketServer.begin();
|
||||||
|
|
||||||
// Start JSON server
|
|
||||||
json.begin();
|
|
||||||
|
|
||||||
|
|
||||||
// Start Web Server
|
// Start Web Server
|
||||||
webserver.on("/", web_index);
|
webserver.on("/", web_index);
|
||||||
webserver.on("/api/reset", js_reset);
|
webserver.on("/api/reset", js_reset);
|
||||||
|
@ -246,6 +232,7 @@ void setup() {
|
||||||
webserver.on("/api/config",js_config);
|
webserver.on("/api/config",js_config);
|
||||||
webserver.on("/api/setConfig",web_setConfig);
|
webserver.on("/api/setConfig",web_setConfig);
|
||||||
webserver.on("/api/resetConfig",web_resetConfig);
|
webserver.on("/api/resetConfig",web_resetConfig);
|
||||||
|
webserver.on("/api/boatData",js_boatData);
|
||||||
webserver.onNotFound(handleNotFound);
|
webserver.onNotFound(handleNotFound);
|
||||||
|
|
||||||
webserver.begin();
|
webserver.begin();
|
||||||
|
@ -353,74 +340,12 @@ void SendN2kEngine() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void handle_json() {
|
|
||||||
|
|
||||||
WiFiClient client = json.available();
|
|
||||||
|
|
||||||
// Do we have a client?
|
|
||||||
if (!client) return;
|
|
||||||
|
|
||||||
// Serial.println(F("New client"));
|
|
||||||
|
|
||||||
// Read the request (we ignore the content in this example)
|
|
||||||
while (client.available()) client.read();
|
|
||||||
|
|
||||||
// Allocate JsonBuffer
|
|
||||||
// Use arduinojson.org/assistant to compute the capacity.
|
|
||||||
StaticJsonDocument<800> root;
|
|
||||||
|
|
||||||
root["Latitude"] = BoatData.Latitude;
|
|
||||||
root["Longitude"] = BoatData.Longitude;
|
|
||||||
root["Heading"] = BoatData.Heading;
|
|
||||||
root["COG"] = BoatData.COG;
|
|
||||||
root["SOG"] = BoatData.SOG;
|
|
||||||
root["STW"] = BoatData.STW;
|
|
||||||
root["AWS"] = BoatData.AWS;
|
|
||||||
root["TWS"] = BoatData.TWS;
|
|
||||||
root["MaxAws"] = BoatData.MaxAws;
|
|
||||||
root["MaxTws"] = BoatData.MaxTws;
|
|
||||||
root["AWA"] = BoatData.AWA;
|
|
||||||
root["TWA"] = BoatData.TWA;
|
|
||||||
root["TWD"] = BoatData.TWD;
|
|
||||||
root["TripLog"] = BoatData.TripLog;
|
|
||||||
root["Log"] = BoatData.Log;
|
|
||||||
root["RudderPosition"] = BoatData.RudderPosition;
|
|
||||||
root["WaterTemperature"] = BoatData.WaterTemperature;
|
|
||||||
root["WaterDepth"] = BoatData.WaterDepth;
|
|
||||||
root["Variation"] = BoatData.Variation;
|
|
||||||
root["Altitude"] = BoatData.Altitude;
|
|
||||||
root["GPSTime"] = BoatData.GPSTime;
|
|
||||||
root["DaysSince1970"] = BoatData.DaysSince1970;
|
|
||||||
|
|
||||||
|
|
||||||
//Serial.print(F("Sending: "));
|
|
||||||
//serializeJson(root, Serial);
|
|
||||||
//Serial.println();
|
|
||||||
|
|
||||||
// Write response headers
|
|
||||||
client.println("HTTP/1.0 200 OK");
|
|
||||||
client.println("Content-Type: application/json");
|
|
||||||
client.println("Connection: close");
|
|
||||||
client.println();
|
|
||||||
|
|
||||||
// Write JSON document
|
|
||||||
serializeJsonPretty(root, client);
|
|
||||||
|
|
||||||
// Disconnect
|
|
||||||
client.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
long lastLog=millis();
|
long lastLog=millis();
|
||||||
void loop() {
|
void loop() {
|
||||||
unsigned int size;
|
unsigned int size;
|
||||||
int wifi_retry;
|
int wifi_retry;
|
||||||
webserver.handleClient();
|
webserver.handleClient();
|
||||||
gwWifi.loop();
|
gwWifi.loop();
|
||||||
handle_json();
|
|
||||||
|
|
||||||
if (NMEA0183.GetMessage(NMEA0183Msg)) { // Get AIS NMEA sentences from serial2
|
if (NMEA0183.GetMessage(NMEA0183Msg)) { // Get AIS NMEA sentences from serial2
|
||||||
|
|
||||||
|
@ -428,9 +353,7 @@ void loop() {
|
||||||
|
|
||||||
NMEA0183Msg.GetMessage(buff, MAX_NMEA0183_MESSAGE_SIZE); // send to buffer
|
NMEA0183Msg.GetMessage(buff, MAX_NMEA0183_MESSAGE_SIZE); // send to buffer
|
||||||
|
|
||||||
#if ENABLE_DEBUG_LOG == 1
|
|
||||||
Serial.println(buff);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if UDP_Forwarding == 1
|
#if UDP_Forwarding == 1
|
||||||
size = strlen(buff);
|
size = strlen(buff);
|
||||||
|
@ -453,7 +376,7 @@ void loop() {
|
||||||
Serial.printf("Address Change: New Address=%d\n", SourceAddress);
|
Serial.printf("Address Change: New Address=%d\n", SourceAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
nmea0183Converter.Update(&BoatData);
|
nmea0183Converter.loop();
|
||||||
|
|
||||||
// Dummy to empty input buffer to avoid board to stuck with e.g. NMEA Reader
|
// Dummy to empty input buffer to avoid board to stuck with e.g. NMEA Reader
|
||||||
if ( Serial.available() ) {
|
if ( Serial.available() ) {
|
||||||
|
|
Loading…
Reference in New Issue