From fbc955cd535a40fa90669cd6c41d0d1c29e5d137 Mon Sep 17 00:00:00 2001 From: wellenvogel Date: Fri, 19 Nov 2021 21:16:04 +0100 Subject: [PATCH] intermediate: xdr type mapping --- lib/xdrmappings/GwXDRMappings.cpp | 125 ++++++++++++ lib/xdrmappings/GwXDRMappings.h | 135 +++++++++++++ src/main.cpp | 1 + web/xdrconfig.json | 313 ++++++++++++++++++++++++++++++ 4 files changed, 574 insertions(+) create mode 100644 lib/xdrmappings/GwXDRMappings.cpp create mode 100644 lib/xdrmappings/GwXDRMappings.h create mode 100644 web/xdrconfig.json diff --git a/lib/xdrmappings/GwXDRMappings.cpp b/lib/xdrmappings/GwXDRMappings.cpp new file mode 100644 index 0000000..bdd6b9e --- /dev/null +++ b/lib/xdrmappings/GwXDRMappings.cpp @@ -0,0 +1,125 @@ +#include "GwXDRMappings.h" +#include "N2kMessages.h" +double PtoBar(double v){ + if (N2kIsNA(v)) return v; + return v/100000L; +} +double BarToP(double v){ + if (N2kIsNA(v)) return v; + return v*100000L; +} +GwXDRType * types[]={ + new GwXDRType(GwXDRType::PRESS,"P","P"), + new GwXDRType(GwXDRType::PRESS,"P","B", + PtoBar, + BarToP), + new GwXDRType(GwXDRType::VOLT,"U","V"), + new GwXDRType(GwXDRType::AMP,"I","A"), + NULL +}; + + +String GwXDRMappingDef::toString(){ + String rt=""; + rt+=String((int)category); + rt+=","; + rt+=String((int)direction); + rt+=","; + rt+=String(selector); + rt+=","; + rt+=String(field); + rt+=","; + rt+=String(instanceMode); + rt+=","; + rt+=String(instanceId); + return rt; +} +bool GwXDRMappingDef::handleToken(String tok,int index,GwXDRMappingDef *def){ + switch(index){ + int i; + case 0: + //category + i=tok.toInt(); + if (i< XDRTEMP || i > XDRENGINE) return false; + def->category=(GwXDRCategory)i; + return true; + case 1: + //direction + i=tok.toInt(); + if (i < GwXDRMappingDef::M_DISABLED || + i>= GwXDRMappingDef::M_LAST) return false; + def->direction=(GwXDRMappingDef::Direction)i; + return true; + case 2: + //selector + //TODO: check selector? + i=tok.toInt(); + def->selector=i; + return true; + case 3: + //field + i=tok.toInt(); + def->field=i; + return true; + case 4: + //instance mode + i=tok.toInt(); + if (i < GwXDRMappingDef::IS_SINGLE || + i>= GwXDRMappingDef::IS_LAST) return false; + def->instanceMode=(GwXDRMappingDef::InstanceMode)i; + return true; + case 5: + //instance id + i=tok.toInt(); + def->instanceId=i; + return true; + default: + break; + } + return false; +} +GwXDRMappingDef *GwXDRMappingDef::fromString(String s){ + int found=0; + int last=0; + int index=0; + GwXDRMappingDef *rt=new GwXDRMappingDef(); + while ((found = s.indexOf(',',last)) >= 0){ + String tok=s.substring(last,found); + if (!handleToken(tok,index,rt)){ + delete rt; + return NULL; + } + last=found+1; + index++; + } + if (last < s.length()){ + String tok=s.substring(last); + if (!handleToken(tok,index,rt)){ + delete rt; + return NULL; + } + } + return rt; +} + +GwXDRMappings::GwXDRMappings(GwLog *logger, GwConfigHandler *config) +{ + this->logger = logger; + this->config = config; +} + +#define MAX_MAPPINGS 100 +void GwXDRMappings::begin(){ + char namebuf[10]; + for (int i=0;igetConfigItem(String(namebuf)); + if (cfg){ + GwXDRMappingDef *mapping=GwXDRMappingDef::fromString(cfg->asCString()); + if (mapping){ + LOG_DEBUG(GwLog::DEBUG,"read xdr mapping %s",mapping->toString().c_str()); + } + } + } +} \ No newline at end of file diff --git a/lib/xdrmappings/GwXDRMappings.h b/lib/xdrmappings/GwXDRMappings.h new file mode 100644 index 0000000..f9629ff --- /dev/null +++ b/lib/xdrmappings/GwXDRMappings.h @@ -0,0 +1,135 @@ +#ifndef _GWXDRMAPPINGS_H +#define _GWXDRMAPPINGS_H +#include "GwLog.h" +#include "GWConfig.h" +#include +#include +//enum must match the defines in xdrconfig.json +typedef enum { + XDRTEMP=0, + XDRHUMIDITY=1, + XDRPRSSURE=2, + XDRTIME=3, //unused + XDRFLUID=4, + XDRDCTYPE=5, //unused + XDRBATTYPE=6, //unused + XDRBATCHEM=7, //unused + XDRGEAR=8, //unused + XDRBAT=9, + XDRENGINE=10 +} GwXDRCategory; +class GwXDRType{ + public: + typedef enum{ + PRESS=0, + PERCENT=1, + VOLT=2, + AMP=3 + }TypeCode; + typedef double (* convert)(double); + TypeCode code; + String xdrtype; + String xdrunit; + convert tonmea=NULL; + convert fromnmea=NULL; + GwXDRType(TypeCode tc,String xdrtype,String xdrunit,convert fromnmea=NULL,convert tonmea=NULL){ + this->code=tc; + this->xdrtype=xdrtype; + this->xdrunit=xdrunit; + this->fromnmea=fromnmea; + this->tonmea=tonmea; + } +}; +class GwXDRTypeMapping{ + public: + GwXDRCategory category; + int fieldIndex; + GwXDRType::TypeCode type; + GwXDRTypeMapping(GwXDRCategory category, + int fieldIndex, + GwXDRType::TypeCode type){ + this->category=category; + this->type=type; + this->fieldIndex=fieldIndex; + } +}; + +class GwXDRMappingDef{ + public: + typedef enum{ + IS_SINGLE=0, + IS_IGNORE, + IS_AUTO, + IS_LAST + } InstanceMode; + typedef enum{ + M_DISABLED=0, + M_BOTH=1, + M_TO2K=2, + M_FROM2K=3, + M_LAST + } Direction; + String xdrName; + GwXDRCategory category; + int selector=-1; + int field=-1; + InstanceMode instanceMode=IS_AUTO; + int instanceId=-1; + Direction direction=M_BOTH; + GwXDRMappingDef(String xdrName,GwXDRCategory category, + int selector, int field,InstanceMode istanceMode,int instance, + Direction direction){ + this->xdrName=xdrName; + this->category=category; + this->selector=selector; + this->field=field; + this->instanceMode=instanceMode; + this->instanceId=instance; + this->direction=direction; + }; + GwXDRMappingDef(){ + category=XDRTEMP; + } + String toString(); + static GwXDRMappingDef *fromString(String s); + private: + static bool handleToken(String tok,int index,GwXDRMappingDef *def); +}; +class GwXDRMapping{ + public: + GwXDRMappingDef *definition; + GwXDRType *type; + GwXDRMapping(GwXDRMappingDef *definition,GwXDRType *type){ + this->definition=definition; + this->type=type; + } + //we allow 100 entities of code,selector and field nid + static long n2kKey(GwXDRType::TypeCode code,int selector,int field){ + long rt=(int)code; + if (selector < 0) selector=0; + rt=rt*100+selector; + if (field < 0) field=0; + rt=rt*100*field; + return rt; + } + static String n183key(String xdrName,String xdrType,String xdrUnit){ + String rt=xdrName; + rt+=","; + rt+=xdrType; + rt+=","; + rt+=xdrUnit; + return rt; + } +}; + +class GwXDRMappings{ + private: + GwLog *logger; + GwConfigHandler *config; + public: + GwXDRMappings(GwLog *logger,GwConfigHandler *config); + void begin(); + +}; + +#endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index afec2f3..d265651 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -60,6 +60,7 @@ const unsigned long HEAP_REPORT_TIME=2000; //set to 0 to disable heap reporting #include "GwButtons.h" #include "GwLeds.h" #include "GwCounter.h" +#include "GwXDRMappings.h" //NMEA message channels diff --git a/web/xdrconfig.json b/web/xdrconfig.json new file mode 100644 index 0000000..643652e --- /dev/null +++ b/web/xdrconfig.json @@ -0,0 +1,313 @@ +{ + "Temperature": { + "id":0, + "selector": [ + { + "l": "SeaTemperature(0)", + "v": "0" + }, + { + "l": "OutsideTemperature(1)", + "v": "1" + }, + { + "l": "InsideTemperature(2)", + "v": "2" + }, + { + "l": "EngineRoomTemperature(3)", + "v": "3" + }, + { + "l": "MainCabinTemperature(4)", + "v": "4" + }, + { + "l": "LiveWellTemperature(5)", + "v": "5" + }, + { + "l": "BaitWellTemperature(6)", + "v": "6" + }, + { + "l": "RefridgerationTemperature(7)", + "v": "7" + }, + { + "l": "HeatingSystemTemperature(8)", + "v": "8" + }, + { + "l": "DewPointTemperature(9)", + "v": "9" + }, + { + "l": "ApparentWindChillTemperature(10)", + "v": "10" + }, + { + "l": "TheoreticalWindChillTemperature(11)", + "v": "11" + }, + { + "l": "HeatIndexTemperature(12)", + "v": "12" + }, + { + "l": "FreezerTemperature(13)", + "v": "13" + }, + { + "l": "ExhaustGasTemperature(14)", + "v": "14" + } + ] + }, + "Humidity": { + "id":1, + "selector": [ + { + "l": "InsideHumidity(0)", + "v": "0" + }, + { + "l": "OutsideHumidity(1)", + "v": "1" + }, + { + "l": "Undef(0xff)", + "v": "0xff" + } + ] + }, + "Pressure": { + "id":2, + "selector": [ + { + "l": "Atmospheric(0)", + "v": "0" + }, + { + "l": "Water(1)", + "v": "1" + }, + { + "l": "Steam(2)", + "v": "2" + }, + { + "l": "CompressedAir(3)", + "v": "3" + }, + { + "l": "Hydraulic(4)", + "v": "4" + }, + { + "l": "Filter(5)", + "v": "5" + }, + { + "l": "AltimeterSetting(6)", + "v": "6" + }, + { + "l": "Oil(7)", + "v": "7" + }, + { + "l": "Fuel(8)", + "v": "8" + } + ] + }, + "TimeSource": { + "enabled": false, + "id":3, + "values": [ + { + "l": "GPS(0)", + "v": "0" + }, + { + "l": "GLONASS(1)", + "v": "1" + }, + { + "l": "RadioStation(2)", + "v": "2" + }, + { + "l": "LocalCesiumClock(3)", + "v": "3" + }, + { + "l": "LocalRubidiumClock(4)", + "v": "4" + }, + { + "l": "LocalCrystalClock(5)", + "v": "5" + } + ] + }, + "Fluid": { + "d":"127505", + "id":4, + "selector": [ + { + "l": "Fuel(0)", + "v": "0" + }, + { + "l": "Water(1)", + "v": "1" + }, + { + "l": "GrayWater(2)", + "v": "2" + }, + { + "l": "LiveWell(3)", + "v": "3" + }, + { + "l": "Oil(4)", + "v": "4" + }, + { + "l": "BlackWater(5)", + "v": "5" + }, + { + "l": "FuelGasoline(6)", + "v": "6" + }, + { + "l": "Error(14)", + "v": "14" + }, + { + "l": "Unavailable(15)", + "v": "15" + } + ], + "fields":[ + {"l":"Level","v":0,"t":-1}, + {"l":"Capacity","v":1,"t":-1} + ] + }, + "DCType": { + "enabled":false, + "id":5, + "values": [ + { + "l": "Battery(0)", + "v": "0" + }, + { + "l": "Alternator(1)", + "v": "1" + }, + { + "l": "Converter(2)", + "v": "2" + }, + { + "l": "SolarCell(3)", + "v": "3" + }, + { + "l": "WindGenerator(4)", + "v": "4" + } + ] + }, + "BatType": { + "enabled":false, + "id":6, + "values": [ + { + "l": "Flooded(0)", + "v": "0" + }, + { + "l": "Gel(1)", + "v": "1" + }, + { + "l": "AGM(2)", + "v": "2" + } + ] + }, + "BatChem": { + "enabled":false, + "id":7, + "values": [ + { + "l": "LeadAcid(0)", + "v": "0" + }, + { + "l": "LiIon(1)", + "v": "1" + }, + { + "l": "NiCad(2)", + "v": "2" + }, + { + "l": "NiMh(3)", + "v": "3" + } + ] + }, + "TransmissionGear": { + "enabled":false, + "id":8, + "values": [ + { + "l": "Forward(0)", + "v": "0" + }, + { + "l": "Neutral(1)", + "v": "1" + }, + { + "l": "Reverse(2)", + "v": "2" + }, + { + "l": "Unknown(3)", + "v": "3" + } + ] + }, + "Battery":{ + "d":"127508", + "id":9, + "fields":[ + "BatteryVoltage", + "BatteryCurrent", + "BatteryTemperature" + ] + }, + "Engine":{ + "d":"127489", + "id":10, + "fields":[ + "EngineOilPress", + "EngineOilTemp", + "EngineCoolantTemp", + "FuelRate", + "EngineHours", + "EngineCoolantPress", + "EngineFuelPress", + "EngineLoad", + "EngineTorque" + ] + } +} \ No newline at end of file