mirror of
https://github.com/thooge/esp32-nmea2000-obp60.git
synced 2025-12-28 13:13:07 +01:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 898922769a |
@@ -137,6 +137,7 @@ class GwApi{
|
|||||||
* thread safe methods - can directly be called from a user task
|
* thread safe methods - can directly be called from a user task
|
||||||
*/
|
*/
|
||||||
virtual GwRequestQueue *getQueue()=0;
|
virtual GwRequestQueue *getQueue()=0;
|
||||||
|
virtual QueueHandle_t getKbQueue()=0;
|
||||||
virtual void sendN2kMessage(const tN2kMsg &msg, bool convert=true)=0;
|
virtual void sendN2kMessage(const tN2kMsg &msg, bool convert=true)=0;
|
||||||
/**
|
/**
|
||||||
* deprecated - sourceId will be ignored
|
* deprecated - sourceId will be ignored
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ class GwConverterConfig{
|
|||||||
int rmcInterval=1000;
|
int rmcInterval=1000;
|
||||||
int rmcCheckTime=4000;
|
int rmcCheckTime=4000;
|
||||||
int winst312=256;
|
int winst312=256;
|
||||||
|
int swBankInstance=0;
|
||||||
bool unmappedXdr=false;
|
bool unmappedXdr=false;
|
||||||
unsigned long xdrTimeout=60000;
|
unsigned long xdrTimeout=60000;
|
||||||
std::vector<WindMapping> windMappings;
|
std::vector<WindMapping> windMappings;
|
||||||
@@ -97,6 +98,7 @@ class GwConverterConfig{
|
|||||||
windMappings.push_back(mapping);
|
windMappings.push_back(mapping);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
swBankInstance=config->getInt(GwConfigDefinitions::swBankInstance,0);
|
||||||
}
|
}
|
||||||
const WindMapping findWindMapping(const tN2kWindReference &n2k) const{
|
const WindMapping findWindMapping(const tN2kWindReference &n2k) const{
|
||||||
for (const auto & it:windMappings){
|
for (const auto & it:windMappings){
|
||||||
|
|||||||
@@ -1572,6 +1572,36 @@ private:
|
|||||||
finalizeXdr();
|
finalizeXdr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Handle127502(const tN2kMsg &msg){
|
||||||
|
// switch bank control / receive remote key strokes
|
||||||
|
unsigned char instance=-1;
|
||||||
|
tN2kBinaryStatus bankstatus;
|
||||||
|
LOG_DEBUG(GwLog::LOG,"received switch bank control");
|
||||||
|
// check if we are addressed and our configured instance is used
|
||||||
|
if (! ParseN2kPGN127502(msg,instance,bankstatus)) {
|
||||||
|
LOG_DEBUG(GwLog::DEBUG,"unable to parse PGN %d",msg.PGN);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (! (instance == config.swBankInstance)) {
|
||||||
|
LOG_DEBUG(GwLog::DEBUG,"switch bank instance #%d ignored",instance);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// TODO (?) multiple keys together
|
||||||
|
|
||||||
|
// only process configured key count (default 6)
|
||||||
|
for (uint8_t i=1; i<=6; i++) {
|
||||||
|
tN2kOnOff keystatus = N2kGetStatusOnBinaryStatus(bankstatus, i);
|
||||||
|
if (keystatus == 1) {
|
||||||
|
// key pressed: send key to queue
|
||||||
|
xQueueSend(keyboardQueue, &i, 0);
|
||||||
|
} else if (keystatus == 2) {
|
||||||
|
// long key pressed: send long key to queue
|
||||||
|
xQueueSend(keyboardQueue, &i, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void registerConverters()
|
void registerConverters()
|
||||||
{
|
{
|
||||||
//register all converter functions
|
//register all converter functions
|
||||||
@@ -1607,6 +1637,7 @@ private:
|
|||||||
converters.registerConverter(127488UL, &N2kToNMEA0183Functions::Handle127488);
|
converters.registerConverter(127488UL, &N2kToNMEA0183Functions::Handle127488);
|
||||||
converters.registerConverter(130316UL, &N2kToNMEA0183Functions::Handle130316);
|
converters.registerConverter(130316UL, &N2kToNMEA0183Functions::Handle130316);
|
||||||
converters.registerConverter(127257UL, &N2kToNMEA0183Functions::Handle127257);
|
converters.registerConverter(127257UL, &N2kToNMEA0183Functions::Handle127257);
|
||||||
|
converters.registerConverter(127502UL, &N2kToNMEA0183Functions::Handle127502);
|
||||||
#define HANDLE_AIS
|
#define HANDLE_AIS
|
||||||
#ifdef HANDLE_AIS
|
#ifdef HANDLE_AIS
|
||||||
converters.registerConverter(129038UL, &N2kToNMEA0183Functions::HandleAISClassAPosReport); // AIS Class A Position Report, Message Type 1
|
converters.registerConverter(129038UL, &N2kToNMEA0183Functions::HandleAISClassAPosReport); // AIS Class A Position Report, Message Type 1
|
||||||
@@ -1620,13 +1651,15 @@ private:
|
|||||||
public:
|
public:
|
||||||
N2kToNMEA0183Functions(GwLog *logger, GwBoatData *boatData,
|
N2kToNMEA0183Functions(GwLog *logger, GwBoatData *boatData,
|
||||||
SendNMEA0183MessageCallback callback,
|
SendNMEA0183MessageCallback callback,
|
||||||
String talkerId, GwXDRMappings *xdrMappings, const GwConverterConfig &cfg)
|
String talkerId, GwXDRMappings *xdrMappings, const GwConverterConfig &cfg,
|
||||||
|
QueueHandle_t kbQueue)
|
||||||
: N2kDataToNMEA0183(logger, boatData, callback,talkerId)
|
: N2kDataToNMEA0183(logger, boatData, callback,talkerId)
|
||||||
{
|
{
|
||||||
this->logger = logger;
|
this->logger = logger;
|
||||||
this->boatData = boatData;
|
this->boatData = boatData;
|
||||||
this->xdrMappings=xdrMappings;
|
this->xdrMappings=xdrMappings;
|
||||||
this->config=cfg;
|
this->config=cfg;
|
||||||
|
this->keyboardQueue=kbQueue;
|
||||||
registerConverters();
|
registerConverters();
|
||||||
}
|
}
|
||||||
virtual void loop(unsigned long lastExtRmc) override
|
virtual void loop(unsigned long lastExtRmc) override
|
||||||
@@ -1642,8 +1675,8 @@ private:
|
|||||||
|
|
||||||
N2kDataToNMEA0183* N2kDataToNMEA0183::create(GwLog *logger, GwBoatData *boatData,
|
N2kDataToNMEA0183* N2kDataToNMEA0183::create(GwLog *logger, GwBoatData *boatData,
|
||||||
SendNMEA0183MessageCallback callback, String talkerId, GwXDRMappings *xdrMappings,
|
SendNMEA0183MessageCallback callback, String talkerId, GwXDRMappings *xdrMappings,
|
||||||
const GwConverterConfig &cfg){
|
const GwConverterConfig &cfg, QueueHandle_t kbQueue){
|
||||||
LOG_DEBUG(GwLog::LOG,"creating N2kToNMEA0183");
|
LOG_DEBUG(GwLog::LOG,"creating N2kToNMEA0183");
|
||||||
return new N2kToNMEA0183Functions(logger,boatData,callback, talkerId,xdrMappings,cfg);
|
return new N2kToNMEA0183Functions(logger,boatData,callback, talkerId,xdrMappings,cfg,kbQueue);
|
||||||
}
|
}
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ protected:
|
|||||||
GwBoatData *boatData;
|
GwBoatData *boatData;
|
||||||
int sourceId=0;
|
int sourceId=0;
|
||||||
char talkerId[3];
|
char talkerId[3];
|
||||||
|
QueueHandle_t keyboardQueue;
|
||||||
SendNMEA0183MessageCallback sendNMEA0183MessageCallback;
|
SendNMEA0183MessageCallback sendNMEA0183MessageCallback;
|
||||||
void SendMessage(const tNMEA0183Msg &NMEA0183Msg);
|
void SendMessage(const tNMEA0183Msg &NMEA0183Msg);
|
||||||
N2kDataToNMEA0183(GwLog *logger, GwBoatData *boatData,
|
N2kDataToNMEA0183(GwLog *logger, GwBoatData *boatData,
|
||||||
@@ -50,7 +51,8 @@ protected:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
static N2kDataToNMEA0183* create(GwLog *logger, GwBoatData *boatData, SendNMEA0183MessageCallback callback,
|
static N2kDataToNMEA0183* create(GwLog *logger, GwBoatData *boatData, SendNMEA0183MessageCallback callback,
|
||||||
String talkerId, GwXDRMappings *xdrMappings,const GwConverterConfig &cfg);
|
String talkerId, GwXDRMappings *xdrMappings,const GwConverterConfig &cfg,
|
||||||
|
QueueHandle_t kbQueue);
|
||||||
virtual void HandleMsg(const tN2kMsg &N2kMsg, int sourceId) = 0;
|
virtual void HandleMsg(const tN2kMsg &N2kMsg, int sourceId) = 0;
|
||||||
virtual void loop(unsigned long lastRmc);
|
virtual void loop(unsigned long lastRmc);
|
||||||
virtual ~N2kDataToNMEA0183(){}
|
virtual ~N2kDataToNMEA0183(){}
|
||||||
|
|||||||
@@ -1,443 +0,0 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
|
||||||
|
|
||||||
/*
|
|
||||||
This page is in experimental stage so be warned!
|
|
||||||
North is up.
|
|
||||||
Anchor page with background map from mapservice
|
|
||||||
|
|
||||||
Boatdata used
|
|
||||||
DBS - Water depth
|
|
||||||
HDT - Boat heading
|
|
||||||
AWS - Wind strength; Boat not moving so we assume AWS=TWS and AWD=TWD
|
|
||||||
AWD - Wind direction
|
|
||||||
LAT/LON - Boat position, current
|
|
||||||
HDOP - Position error
|
|
||||||
|
|
||||||
Drop / raise function in device OBP40 has to be done inside
|
|
||||||
config mode because of limited number of buttons.
|
|
||||||
|
|
||||||
TODO
|
|
||||||
gzip for data transfer,
|
|
||||||
manually inflating with tinflate from ROM
|
|
||||||
Save position in FRAM
|
|
||||||
Alarm: gps fix lost
|
|
||||||
switch unit feet/meter
|
|
||||||
force map update if new position is different from old position by
|
|
||||||
a certain level (e.g. 10m)
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <WiFi.h>
|
|
||||||
#include <HTTPClient.h>
|
|
||||||
#include "Pagedata.h"
|
|
||||||
#include "OBP60Extensions.h"
|
|
||||||
|
|
||||||
#define anchor_width 16
|
|
||||||
#define anchor_height 16
|
|
||||||
static unsigned char anchor_bits[] PROGMEM = {
|
|
||||||
0x80, 0x01, 0x40, 0x02, 0x40, 0x02, 0x80, 0x01, 0xf0, 0x0f, 0x80, 0x01,
|
|
||||||
0x80, 0x01, 0x88, 0x11, 0x8c, 0x31, 0x8e, 0x71, 0x84, 0x21, 0x86, 0x61,
|
|
||||||
0x86, 0x61, 0xfc, 0x3f, 0xf8, 0x1f, 0x80, 0x01 };
|
|
||||||
|
|
||||||
class PageAnchor : public Page
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
char mode = 'N'; // (N)ormal, (C)onfig
|
|
||||||
int8_t editmode = -1; // marker for menu/edit/set function
|
|
||||||
|
|
||||||
//uint8_t *mapbuf = new uint8_t[10000]; // 8450 Byte without header
|
|
||||||
//int mapbuf_size = 10000;
|
|
||||||
//uint8_t *mapbuf = (uint8_t*) heap_caps_malloc(mapbuf_size, MALLOC_CAP_SPIRAM);
|
|
||||||
GFXcanvas1 *canvas;
|
|
||||||
const uint16_t map_width = 264;
|
|
||||||
const uint16_t map_height = 260;
|
|
||||||
bool map_valid = false;
|
|
||||||
double map_lat = 0; // current center of valid map
|
|
||||||
double map_lon = 0;
|
|
||||||
String server_name; // server with map service
|
|
||||||
String tile_path;
|
|
||||||
|
|
||||||
String lengthformat;
|
|
||||||
|
|
||||||
double scale = 50; // Radius of display circle in meter, depends on lat
|
|
||||||
uint8_t zoom = 15; // map zoom level
|
|
||||||
|
|
||||||
bool alarm = false;
|
|
||||||
bool alarm_enabled = false;
|
|
||||||
uint8_t alarm_range;
|
|
||||||
|
|
||||||
uint8_t chain_length;
|
|
||||||
uint8_t chain = 0;
|
|
||||||
|
|
||||||
bool anchor_set = false;
|
|
||||||
double anchor_lat;
|
|
||||||
double anchor_lon;
|
|
||||||
double anchor_depth;
|
|
||||||
int anchor_ts; // time stamp anchor dropped
|
|
||||||
|
|
||||||
void displayModeNormal(PageData &pageData) {
|
|
||||||
|
|
||||||
// Boatvalues: DBS, HDT, AWS, AWD, LAT, LON, HDOP
|
|
||||||
GwApi::BoatValue *bv_dbs = pageData.values[0]; // DBS
|
|
||||||
String sval_dbs = formatValue(bv_dbs, *commonData).svalue;
|
|
||||||
String sunit_dbs = formatValue(bv_dbs, *commonData).unit;
|
|
||||||
GwApi::BoatValue *bv_hdt = pageData.values[1]; // HDT
|
|
||||||
String sval_hdt = formatValue(bv_hdt, *commonData).svalue;
|
|
||||||
GwApi::BoatValue *bv_aws = pageData.values[2]; // AWS
|
|
||||||
String sval_aws = formatValue(bv_aws, *commonData).svalue;
|
|
||||||
String sunit_aws = formatValue(bv_aws, *commonData).unit;
|
|
||||||
GwApi::BoatValue *bv_awd = pageData.values[3]; // AWD
|
|
||||||
String sval_awd = formatValue(bv_awd, *commonData).svalue;
|
|
||||||
GwApi::BoatValue *bv_lat = pageData.values[4]; // LAT
|
|
||||||
String sval_lat = formatValue(bv_lat, *commonData).svalue;
|
|
||||||
GwApi::BoatValue *bv_lon = pageData.values[5]; // LON
|
|
||||||
String sval_lon = formatValue(bv_lon, *commonData).svalue;
|
|
||||||
GwApi::BoatValue *bv_hdop = pageData.values[6]; // HDOP
|
|
||||||
String sval_hdop = formatValue(bv_hdop, *commonData).svalue;
|
|
||||||
String sunit_hdop = formatValue(bv_hdop, *commonData).unit;
|
|
||||||
|
|
||||||
commonData->logger->logDebug(GwLog::DEBUG, "Drawing at PageAnchor; DBS=%f, HDT=%f, AWS=%f", bv_dbs->value, bv_hdt->value, bv_aws->value);
|
|
||||||
|
|
||||||
// Draw canvas with background map
|
|
||||||
// rhumb(map_lat, map_lon, bv_lat->value, bv_lon->value)
|
|
||||||
int posdiff = 0;
|
|
||||||
if (map_valid) {
|
|
||||||
if (bv_lat->valid and bv_lon->valid) {
|
|
||||||
// calculate movement since last map refresh
|
|
||||||
posdiff = rhumb(map_lat, map_lon, bv_lat->value, bv_lon->value);
|
|
||||||
if (posdiff > 25) {
|
|
||||||
map_lat = bv_lat->value;
|
|
||||||
map_lon = bv_lon->value;
|
|
||||||
getBackgroundMap(map_lat, map_lon, zoom);
|
|
||||||
if (map_valid) {
|
|
||||||
// prepare visible space for anchor-symbol or boat
|
|
||||||
canvas->fillCircle(132, 130, 12, commonData->fgcolor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
getdisplay().drawBitmap(68, 20, canvas->getBuffer(), map_width, map_height, commonData->fgcolor);
|
|
||||||
}
|
|
||||||
|
|
||||||
Point c = {200, 150}; // center = anchor position
|
|
||||||
uint16_t r = 125;
|
|
||||||
|
|
||||||
// Circle as map border
|
|
||||||
getdisplay().drawCircle(c.x, c.y, r, commonData->fgcolor);
|
|
||||||
getdisplay().drawCircle(c.x, c.y, r + 1, commonData->fgcolor);
|
|
||||||
|
|
||||||
Point b = {200, 180}; // boat position while dropping anchor
|
|
||||||
|
|
||||||
const std::vector<Point> pts_boat = { // polygon lines
|
|
||||||
{b.x - 5, b.y},
|
|
||||||
{b.x - 5, b.y - 10},
|
|
||||||
{b.x, b.y - 16},
|
|
||||||
{b.x + 5, b.y - 10},
|
|
||||||
{b.x + 5, b.y}
|
|
||||||
};
|
|
||||||
//rotatePoints und dann Linien zeichnen
|
|
||||||
// TODO rotate boat according to current heading
|
|
||||||
if (bv_hdt->valid) {
|
|
||||||
if (map_valid) {
|
|
||||||
Point b1 = rotatePoint(c, {b.x, b.y - 8}, RadToDeg(bv_hdt->value));
|
|
||||||
getdisplay().fillCircle(b1.x, b1.y, 10, commonData->bgcolor);
|
|
||||||
}
|
|
||||||
drawPoly(rotatePoints(c, pts_boat, RadToDeg(bv_hdt->value)), commonData->fgcolor);
|
|
||||||
} else {
|
|
||||||
// no heading available draw north oriented
|
|
||||||
if (map_valid) {
|
|
||||||
getdisplay().fillCircle(b.x, b.y - 8, 10, commonData->bgcolor);
|
|
||||||
}
|
|
||||||
drawPoly(pts_boat, commonData->fgcolor);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw wind arrow
|
|
||||||
const std::vector<Point> pts_wind = {
|
|
||||||
{c.x, c.y - r + 25},
|
|
||||||
{c.x - 12, c.y - r - 4},
|
|
||||||
{c.x, c.y - r + 6},
|
|
||||||
{c.x + 12, c.y - r - 4}
|
|
||||||
};
|
|
||||||
if (bv_awd->valid) {
|
|
||||||
fillPoly4(rotatePoints(c, pts_wind, bv_awd->value), commonData->fgcolor);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Title and corner value headings
|
|
||||||
getdisplay().setTextColor(commonData->fgcolor);
|
|
||||||
getdisplay().setFont(&Ubuntu_Bold10pt8b);
|
|
||||||
// Left
|
|
||||||
getdisplay().setCursor(8, 36);
|
|
||||||
getdisplay().print("Anchor");
|
|
||||||
getdisplay().setCursor(8, 210);
|
|
||||||
getdisplay().print("Depth");
|
|
||||||
// Right
|
|
||||||
drawTextRalign(392, 80, "Chain");
|
|
||||||
drawTextRalign(392, 210, "Wind");
|
|
||||||
|
|
||||||
// Units
|
|
||||||
getdisplay().setCursor(8, 272);
|
|
||||||
getdisplay().print(sunit_dbs);
|
|
||||||
drawTextRalign(392, 272, sunit_aws);
|
|
||||||
// drawTextRalign(392, 100, lengthformat); // chain unit not implemented
|
|
||||||
|
|
||||||
// Corner values
|
|
||||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
|
||||||
getdisplay().setCursor(8, 54);
|
|
||||||
getdisplay().print(anchor_set ? "Dropped" : "Ready"); // Anchor state
|
|
||||||
getdisplay().setCursor(8, 72);
|
|
||||||
getdisplay().print("Alarm: "); // Alarm state
|
|
||||||
getdisplay().print(alarm_enabled ? "on" : "off");
|
|
||||||
|
|
||||||
getdisplay().setCursor(8, 120);
|
|
||||||
getdisplay().print("Zoom");
|
|
||||||
getdisplay().setCursor(8, 136);
|
|
||||||
getdisplay().print(zoom);
|
|
||||||
|
|
||||||
getdisplay().setCursor(8, 160);
|
|
||||||
getdisplay().print("diff");
|
|
||||||
getdisplay().setCursor(8, 176);
|
|
||||||
if (map_valid and bv_lat->valid and bv_lon->valid) {
|
|
||||||
getdisplay().print(String(posdiff));
|
|
||||||
} else {
|
|
||||||
getdisplay().print("n/a");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Chain out TODO lengthformat ft/m
|
|
||||||
drawTextRalign(392, 96, String(chain) + " m");
|
|
||||||
drawTextRalign(392, 96+16, "of " + String(chain_length) + " m");
|
|
||||||
|
|
||||||
getdisplay().setFont(&DSEG7Classic_BoldItalic16pt7b);
|
|
||||||
|
|
||||||
// Depth
|
|
||||||
getdisplay().setCursor(8, 250);
|
|
||||||
getdisplay().print(sval_dbs);
|
|
||||||
|
|
||||||
// Wind
|
|
||||||
getdisplay().setCursor(320, 250);
|
|
||||||
getdisplay().print(sval_aws);
|
|
||||||
|
|
||||||
// Position of boat in center of map
|
|
||||||
getdisplay().setFont(&IBM8x8px);
|
|
||||||
drawTextRalign(392, 34, sval_lat);
|
|
||||||
drawTextRalign(392, 44, sval_lon);
|
|
||||||
// quality
|
|
||||||
String hdop = "HDOP: ";
|
|
||||||
if (bv_hdop->valid) {
|
|
||||||
hdop += String(round(bv_hdop->value));
|
|
||||||
} else {
|
|
||||||
hdop += " n/a";
|
|
||||||
}
|
|
||||||
drawTextRalign(392, 54, hdop);
|
|
||||||
|
|
||||||
// zoom scale
|
|
||||||
getdisplay().drawLine(c.x + 10, c.y, c.x + r - 4, c.y, commonData->fgcolor);
|
|
||||||
// arrow left
|
|
||||||
getdisplay().drawLine(c.x + 10, c.y, c.x + 16, c.y - 4, commonData->fgcolor);
|
|
||||||
getdisplay().drawLine(c.x + 10, c.y, c.x + 16, c.y + 4, commonData->fgcolor);
|
|
||||||
// arrow right
|
|
||||||
getdisplay().drawLine(c.x + r - 4, c.y, c.x + r - 10, c.y - 4, commonData->fgcolor);
|
|
||||||
getdisplay().drawLine(c.x + r - 4, c.y, c.x + r - 10, c.y + 4, commonData->fgcolor);
|
|
||||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
|
||||||
drawTextCenter(c.x + r / 2, c.y + 8, String(scale, 0) + "m");
|
|
||||||
|
|
||||||
// draw anchor symbol (as bitmap)
|
|
||||||
getdisplay().drawXBitmap(c.x - anchor_width / 2, c.y - anchor_height / 2,
|
|
||||||
anchor_bits, anchor_width, anchor_height, commonData->fgcolor);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void displayModeConfig() {
|
|
||||||
|
|
||||||
getdisplay().setTextColor(commonData->fgcolor);
|
|
||||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
|
||||||
getdisplay().setCursor(8, 48);
|
|
||||||
getdisplay().print("Anchor configuration");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
PageAnchor(CommonData &common)
|
|
||||||
{
|
|
||||||
commonData = &common;
|
|
||||||
common.logger->logDebug(GwLog::LOG,"Instantiate PageAnchor");
|
|
||||||
|
|
||||||
server_name = common.config->getString(common.config->mapServer);
|
|
||||||
tile_path = common.config->getString(common.config->mapTilePath);
|
|
||||||
|
|
||||||
lengthformat = common.config->getString(common.config->lengthFormat);
|
|
||||||
chain_length = common.config->getInt(common.config->chainLength);
|
|
||||||
|
|
||||||
canvas = new GFXcanvas1(264, 260); // Byte aligned, no padding!
|
|
||||||
}
|
|
||||||
|
|
||||||
void setupKeys(){
|
|
||||||
Page::setupKeys();
|
|
||||||
commonData->keydata[0].label = "MODE";
|
|
||||||
#ifdef BOARD_OBP40S3
|
|
||||||
commonData->keydata[1].label = "DROP";
|
|
||||||
#endif
|
|
||||||
#ifdef BOARD_OBP60S3
|
|
||||||
commonData->keydata[4].label = "DROP";
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO OBP40 / OBP60 different handling
|
|
||||||
int handleKey(int key) {
|
|
||||||
if (key == 1) { // Switch between normal and config mode
|
|
||||||
if (mode == 'N') {
|
|
||||||
mode = 'C';
|
|
||||||
commonData->keydata[1].label = "EDIT";
|
|
||||||
} else {
|
|
||||||
mode = 'N';
|
|
||||||
#ifdef BOARD_OBP40S3
|
|
||||||
commonData->keydata[1].label = anchor_set ? "RAISE": "DROP";
|
|
||||||
#endif
|
|
||||||
#ifdef BOARD_OBP60S3
|
|
||||||
commonData->keydata[4].label = anchor_set ? "RAISE": "DROP";
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (key == 2) {
|
|
||||||
anchor_set = !anchor_set;
|
|
||||||
commonData->keydata[1].label = anchor_set ? "RAISE": "DROP";
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
// Code for keylock
|
|
||||||
if (key == 11){
|
|
||||||
commonData->keylock = !commonData->keylock;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
int rhumb(double lat1, double lon1, double lat2, double lon2) {
|
|
||||||
// calc distance in m between two geo points
|
|
||||||
static const double degToRad = M_PI / 180.0;
|
|
||||||
lat1 = degToRad * lat1;
|
|
||||||
lon1 = degToRad * lon1;
|
|
||||||
lat2 = degToRad * lat2;
|
|
||||||
lon2 = degToRad * lon2;
|
|
||||||
double dlon = lon2 - lon1;
|
|
||||||
double dlat = lat2 - lat1;
|
|
||||||
double mlat = (lat1 + lat2) / 2;
|
|
||||||
return (int) (6371000 * sqrt(pow(dlat, 2) + pow(cos(mlat) * dlon, 2)));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool getBackgroundMap(double lat, double lon, uint8_t zoom) {
|
|
||||||
// HTTP-Request for map
|
|
||||||
// TODO über pagedata -> status abfragen?
|
|
||||||
if (WiFi.status() != WL_CONNECTED) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bool valid = false;
|
|
||||||
HTTPClient http;
|
|
||||||
String url = "http://" + server_name + "/" + tile_path;
|
|
||||||
String parameter = "?lat=" + String(lat, 6) + "&lon=" + String(lon, 6)+ "&zoom=" + String(zoom)
|
|
||||||
+ "&width=" + String(map_width) + "&height=" + String(map_height);
|
|
||||||
commonData->logger->logDebug(GwLog::LOG, "HTTP query: %s", String(url + parameter).c_str());
|
|
||||||
http.begin(url + parameter);
|
|
||||||
// http.SetAcceptEncoding("gzip");
|
|
||||||
// TODO miniz.c from ROM
|
|
||||||
int httpCode = http.GET();
|
|
||||||
if (httpCode > 0) {
|
|
||||||
if (httpCode == HTTP_CODE_OK) {
|
|
||||||
WiFiClient* stream = http.getStreamPtr();
|
|
||||||
int size = http.getSize();
|
|
||||||
commonData->logger->logDebug(GwLog::LOG, "HTTP get size: %d", size);
|
|
||||||
// header: P4<LF><width> <height><LF> (e.g. 11 byte)
|
|
||||||
uint8_t header[14]; // max: P4<LF>wwww wwww<LF>
|
|
||||||
bool header_read = false;
|
|
||||||
int header_size = 0;
|
|
||||||
uint8_t* buf = canvas->getBuffer();
|
|
||||||
int n = 0;
|
|
||||||
int ix = 0;
|
|
||||||
while (stream->available()) {
|
|
||||||
uint8_t b = stream->read();
|
|
||||||
n += 1;
|
|
||||||
if ((! header_read) and (n < 13) ) {
|
|
||||||
header[n-1] = b;
|
|
||||||
if ((n > 3) and (b == 0x0a)) {
|
|
||||||
header_read = true;
|
|
||||||
header_size = n;
|
|
||||||
header[n] = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// write image data to canvas buffer
|
|
||||||
buf[ix++] = b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (n == size) {
|
|
||||||
valid = true;
|
|
||||||
}
|
|
||||||
commonData->logger->logDebug(GwLog::LOG, "HTTP: final bytesRead=%d, header-size=%d", n, header_size);
|
|
||||||
} else {
|
|
||||||
commonData->logger->logDebug(GwLog::LOG, "HTTP result #%d", httpCode);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
commonData->logger->logDebug(GwLog::ERROR, "HTTP error #%d", httpCode);
|
|
||||||
}
|
|
||||||
http.end();
|
|
||||||
return valid;
|
|
||||||
}
|
|
||||||
|
|
||||||
void displayNew(PageData &pageData){
|
|
||||||
|
|
||||||
GwApi::BoatValue *bv_lat = pageData.values[4]; // LAT
|
|
||||||
GwApi::BoatValue *bv_lon = pageData.values[5]; // LON
|
|
||||||
|
|
||||||
// check if valid data available
|
|
||||||
if (!bv_lat->valid or !bv_lon->valid) {
|
|
||||||
map_valid = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
map_lat = bv_lat->value; // save for later comparison
|
|
||||||
map_lon = bv_lon->value;
|
|
||||||
map_valid = getBackgroundMap(map_lat, map_lon, zoom);
|
|
||||||
|
|
||||||
if (map_valid) {
|
|
||||||
// prepare visible space for anchor-symbol or boat
|
|
||||||
canvas->fillCircle(132, 130, 10, commonData->fgcolor);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
int displayPage(PageData &pageData) {
|
|
||||||
GwLog *logger = commonData->logger;
|
|
||||||
|
|
||||||
// Logging boat values
|
|
||||||
logger->logDebug(GwLog::LOG, "Drawing at PageAnchor; Mode=%c", mode);
|
|
||||||
|
|
||||||
// Set display in partial refresh mode
|
|
||||||
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
|
||||||
|
|
||||||
if (mode == 'N') {
|
|
||||||
displayModeNormal(pageData);
|
|
||||||
} else if (mode == 'C') {
|
|
||||||
displayModeConfig();
|
|
||||||
}
|
|
||||||
|
|
||||||
return PAGE_UPDATE;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
static Page *createPage(CommonData &common){
|
|
||||||
return new PageAnchor(common);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* with the code below we make this page known to the PageTask
|
|
||||||
* we give it a type (name) that can be selected in the config
|
|
||||||
* we define which function is to be called
|
|
||||||
* and we provide the number of user parameters we expect
|
|
||||||
* this will be number of BoatValue pointers in pageData.values
|
|
||||||
*/
|
|
||||||
PageDescription registerPageAnchor(
|
|
||||||
"Anchor", // Page name
|
|
||||||
createPage, // Action
|
|
||||||
0, // Number of bus values depends on selection in Web configuration
|
|
||||||
{"DBS", "HDT", "AWS", "AWD", "LAT", "LON", "HDOP"}, // Names of bus values undepends on selection in Web configuration (refer GwBoatData.h)
|
|
||||||
true // Show display header on/off
|
|
||||||
);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -19,28 +19,6 @@
|
|||||||
"obp60": "true"
|
"obp60": "true"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "mapServer",
|
|
||||||
"label": "map server",
|
|
||||||
"type": "string",
|
|
||||||
"default": "",
|
|
||||||
"description": "Server for converting map tiles. Use only one hostname or IP address",
|
|
||||||
"category": "wifi client",
|
|
||||||
"capabilities": {
|
|
||||||
"obp40": "true"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "mapTilePath",
|
|
||||||
"label": "map tile path",
|
|
||||||
"type": "string",
|
|
||||||
"default": "map.php",
|
|
||||||
"description": "Path to converter access e.g. index.php or map.php",
|
|
||||||
"category": "wifi client",
|
|
||||||
"capabilities": {
|
|
||||||
"obp40": "true"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "timeZone",
|
"name": "timeZone",
|
||||||
"label": "Time Zone",
|
"label": "Time Zone",
|
||||||
@@ -97,20 +75,6 @@
|
|||||||
"obp60":"true"
|
"obp60":"true"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "chainLength",
|
|
||||||
"label": "Anchor Chain Length [m]",
|
|
||||||
"type": "number",
|
|
||||||
"default": "0",
|
|
||||||
"check": "checkMinMax",
|
|
||||||
"min": 0,
|
|
||||||
"max": 255,
|
|
||||||
"description": "The length of the anchor chain [0...255m]",
|
|
||||||
"category": "OBP60 Settings",
|
|
||||||
"capabilities": {
|
|
||||||
"obp60":"true"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "fuelTank",
|
"name": "fuelTank",
|
||||||
"label": "Fuel Tank [l]",
|
"label": "Fuel Tank [l]",
|
||||||
@@ -1248,6 +1212,7 @@
|
|||||||
"obp60":"true"
|
"obp60":"true"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"name": "page1type",
|
"name": "page1type",
|
||||||
"label": "Type",
|
"label": "Type",
|
||||||
@@ -1255,7 +1220,6 @@
|
|||||||
"default": "Voltage",
|
"default": "Voltage",
|
||||||
"description": "Type of page for page 1",
|
"description": "Type of page for page 1",
|
||||||
"list": [
|
"list": [
|
||||||
"Anchor",
|
|
||||||
"BME280",
|
"BME280",
|
||||||
"Battery",
|
"Battery",
|
||||||
"Battery2",
|
"Battery2",
|
||||||
@@ -1554,7 +1518,6 @@
|
|||||||
"default": "WindRose",
|
"default": "WindRose",
|
||||||
"description": "Type of page for page 2",
|
"description": "Type of page for page 2",
|
||||||
"list": [
|
"list": [
|
||||||
"Anchor",
|
|
||||||
"BME280",
|
"BME280",
|
||||||
"Battery",
|
"Battery",
|
||||||
"Battery2",
|
"Battery2",
|
||||||
@@ -1845,7 +1808,6 @@
|
|||||||
"default": "OneValue",
|
"default": "OneValue",
|
||||||
"description": "Type of page for page 3",
|
"description": "Type of page for page 3",
|
||||||
"list": [
|
"list": [
|
||||||
"Anchor",
|
|
||||||
"BME280",
|
"BME280",
|
||||||
"Battery",
|
"Battery",
|
||||||
"Battery2",
|
"Battery2",
|
||||||
@@ -2128,7 +2090,6 @@
|
|||||||
"default": "TwoValues",
|
"default": "TwoValues",
|
||||||
"description": "Type of page for page 4",
|
"description": "Type of page for page 4",
|
||||||
"list": [
|
"list": [
|
||||||
"Anchor",
|
|
||||||
"BME280",
|
"BME280",
|
||||||
"Battery",
|
"Battery",
|
||||||
"Battery2",
|
"Battery2",
|
||||||
@@ -2403,7 +2364,6 @@
|
|||||||
"default": "ThreeValues",
|
"default": "ThreeValues",
|
||||||
"description": "Type of page for page 5",
|
"description": "Type of page for page 5",
|
||||||
"list": [
|
"list": [
|
||||||
"Anchor",
|
|
||||||
"BME280",
|
"BME280",
|
||||||
"Battery",
|
"Battery",
|
||||||
"Battery2",
|
"Battery2",
|
||||||
@@ -2670,7 +2630,6 @@
|
|||||||
"default": "FourValues",
|
"default": "FourValues",
|
||||||
"description": "Type of page for page 6",
|
"description": "Type of page for page 6",
|
||||||
"list": [
|
"list": [
|
||||||
"Anchor",
|
|
||||||
"BME280",
|
"BME280",
|
||||||
"Battery",
|
"Battery",
|
||||||
"Battery2",
|
"Battery2",
|
||||||
@@ -2929,7 +2888,6 @@
|
|||||||
"default": "FourValues2",
|
"default": "FourValues2",
|
||||||
"description": "Type of page for page 7",
|
"description": "Type of page for page 7",
|
||||||
"list": [
|
"list": [
|
||||||
"Anchor",
|
|
||||||
"BME280",
|
"BME280",
|
||||||
"Battery",
|
"Battery",
|
||||||
"Battery2",
|
"Battery2",
|
||||||
@@ -3180,7 +3138,6 @@
|
|||||||
"default": "Clock",
|
"default": "Clock",
|
||||||
"description": "Type of page for page 8",
|
"description": "Type of page for page 8",
|
||||||
"list": [
|
"list": [
|
||||||
"Anchor",
|
|
||||||
"BME280",
|
"BME280",
|
||||||
"Battery",
|
"Battery",
|
||||||
"Battery2",
|
"Battery2",
|
||||||
@@ -3423,7 +3380,6 @@
|
|||||||
"default": "RollPitch",
|
"default": "RollPitch",
|
||||||
"description": "Type of page for page 9",
|
"description": "Type of page for page 9",
|
||||||
"list": [
|
"list": [
|
||||||
"Anchor",
|
|
||||||
"BME280",
|
"BME280",
|
||||||
"Battery",
|
"Battery",
|
||||||
"Battery2",
|
"Battery2",
|
||||||
@@ -3658,7 +3614,6 @@
|
|||||||
"default": "Battery2",
|
"default": "Battery2",
|
||||||
"description": "Type of page for page 10",
|
"description": "Type of page for page 10",
|
||||||
"list": [
|
"list": [
|
||||||
"Anchor",
|
|
||||||
"BME280",
|
"BME280",
|
||||||
"Battery",
|
"Battery",
|
||||||
"Battery2",
|
"Battery2",
|
||||||
|
|||||||
@@ -19,28 +19,6 @@
|
|||||||
"obp40": "true"
|
"obp40": "true"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "mapServer",
|
|
||||||
"label": "map server",
|
|
||||||
"type": "string",
|
|
||||||
"default": "",
|
|
||||||
"description": "Server for converting map tiles. Use only one hostname or IP address",
|
|
||||||
"category": "wifi client",
|
|
||||||
"capabilities": {
|
|
||||||
"obp40": "true"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "mapTilePath",
|
|
||||||
"label": "map tile path",
|
|
||||||
"type": "string",
|
|
||||||
"default": "map.php",
|
|
||||||
"description": "Path to converter access e.g. index.php or map.php",
|
|
||||||
"category": "wifi client",
|
|
||||||
"capabilities": {
|
|
||||||
"obp40": "true"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "timeZone",
|
"name": "timeZone",
|
||||||
"label": "Time Zone",
|
"label": "Time Zone",
|
||||||
@@ -97,20 +75,6 @@
|
|||||||
"obp40": "true"
|
"obp40": "true"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "chainLength",
|
|
||||||
"label": "Anchor Chain Length [m]",
|
|
||||||
"type": "number",
|
|
||||||
"default": "0",
|
|
||||||
"check": "checkMinMax",
|
|
||||||
"min": 0,
|
|
||||||
"max": 255,
|
|
||||||
"description": "The length of the anchor chain [0...255m]",
|
|
||||||
"category": "OBP40 Settings",
|
|
||||||
"capabilities": {
|
|
||||||
"obp40":"true"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "fuelTank",
|
"name": "fuelTank",
|
||||||
"label": "Fuel Tank [l]",
|
"label": "Fuel Tank [l]",
|
||||||
@@ -1279,7 +1243,6 @@
|
|||||||
"default": "Voltage",
|
"default": "Voltage",
|
||||||
"description": "Type of page for page 1",
|
"description": "Type of page for page 1",
|
||||||
"list": [
|
"list": [
|
||||||
"Anchor",
|
|
||||||
"BME280",
|
"BME280",
|
||||||
"Battery",
|
"Battery",
|
||||||
"Battery2",
|
"Battery2",
|
||||||
@@ -1608,7 +1571,6 @@
|
|||||||
"default": "WindRose",
|
"default": "WindRose",
|
||||||
"description": "Type of page for page 2",
|
"description": "Type of page for page 2",
|
||||||
"list": [
|
"list": [
|
||||||
"Anchor",
|
|
||||||
"BME280",
|
"BME280",
|
||||||
"Battery",
|
"Battery",
|
||||||
"Battery2",
|
"Battery2",
|
||||||
@@ -1928,7 +1890,6 @@
|
|||||||
"default": "OneValue",
|
"default": "OneValue",
|
||||||
"description": "Type of page for page 3",
|
"description": "Type of page for page 3",
|
||||||
"list": [
|
"list": [
|
||||||
"Anchor",
|
|
||||||
"BME280",
|
"BME280",
|
||||||
"Battery",
|
"Battery",
|
||||||
"Battery2",
|
"Battery2",
|
||||||
@@ -2239,7 +2200,6 @@
|
|||||||
"default": "TwoValues",
|
"default": "TwoValues",
|
||||||
"description": "Type of page for page 4",
|
"description": "Type of page for page 4",
|
||||||
"list": [
|
"list": [
|
||||||
"Anchor",
|
|
||||||
"BME280",
|
"BME280",
|
||||||
"Battery",
|
"Battery",
|
||||||
"Battery2",
|
"Battery2",
|
||||||
@@ -2541,7 +2501,6 @@
|
|||||||
"default": "ThreeValues",
|
"default": "ThreeValues",
|
||||||
"description": "Type of page for page 5",
|
"description": "Type of page for page 5",
|
||||||
"list": [
|
"list": [
|
||||||
"Anchor",
|
|
||||||
"BME280",
|
"BME280",
|
||||||
"Battery",
|
"Battery",
|
||||||
"Battery2",
|
"Battery2",
|
||||||
@@ -2834,7 +2793,6 @@
|
|||||||
"default": "FourValues",
|
"default": "FourValues",
|
||||||
"description": "Type of page for page 6",
|
"description": "Type of page for page 6",
|
||||||
"list": [
|
"list": [
|
||||||
"Anchor",
|
|
||||||
"BME280",
|
"BME280",
|
||||||
"Battery",
|
"Battery",
|
||||||
"Battery2",
|
"Battery2",
|
||||||
@@ -3118,7 +3076,6 @@
|
|||||||
"default": "FourValues2",
|
"default": "FourValues2",
|
||||||
"description": "Type of page for page 7",
|
"description": "Type of page for page 7",
|
||||||
"list": [
|
"list": [
|
||||||
"Anchor",
|
|
||||||
"BME280",
|
"BME280",
|
||||||
"Battery",
|
"Battery",
|
||||||
"Battery2",
|
"Battery2",
|
||||||
@@ -3393,7 +3350,6 @@
|
|||||||
"default": "Clock",
|
"default": "Clock",
|
||||||
"description": "Type of page for page 8",
|
"description": "Type of page for page 8",
|
||||||
"list": [
|
"list": [
|
||||||
"Anchor",
|
|
||||||
"BME280",
|
"BME280",
|
||||||
"Battery",
|
"Battery",
|
||||||
"Battery2",
|
"Battery2",
|
||||||
@@ -3659,7 +3615,6 @@
|
|||||||
"default": "RollPitch",
|
"default": "RollPitch",
|
||||||
"description": "Type of page for page 9",
|
"description": "Type of page for page 9",
|
||||||
"list": [
|
"list": [
|
||||||
"Anchor",
|
|
||||||
"BME280",
|
"BME280",
|
||||||
"Battery",
|
"Battery",
|
||||||
"Battery2",
|
"Battery2",
|
||||||
@@ -3916,7 +3871,6 @@
|
|||||||
"default": "Battery2",
|
"default": "Battery2",
|
||||||
"description": "Type of page for page 10",
|
"description": "Type of page for page 10",
|
||||||
"list": [
|
"list": [
|
||||||
"Anchor",
|
|
||||||
"BME280",
|
"BME280",
|
||||||
"Battery",
|
"Battery",
|
||||||
"Battery2",
|
"Battery2",
|
||||||
|
|||||||
@@ -260,8 +260,6 @@ void registerAllPages(PageList &list){
|
|||||||
list.add(®isterPageFluid);
|
list.add(®isterPageFluid);
|
||||||
extern PageDescription registerPageSkyView;
|
extern PageDescription registerPageSkyView;
|
||||||
list.add(®isterPageSkyView);
|
list.add(®isterPageSkyView);
|
||||||
extern PageDescription registerPageAnchor;
|
|
||||||
list.add(®isterPageAnchor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Undervoltage detection for shutdown display
|
// Undervoltage detection for shutdown display
|
||||||
@@ -346,6 +344,8 @@ void OBP60Task(GwApi *api){
|
|||||||
|
|
||||||
tN2kMsg N2kMsg;
|
tN2kMsg N2kMsg;
|
||||||
|
|
||||||
|
QueueHandle_t keyboardQueue = api->getKbQueue();
|
||||||
|
|
||||||
LOG_DEBUG(GwLog::LOG,"obp60task started");
|
LOG_DEBUG(GwLog::LOG,"obp60task started");
|
||||||
for (auto it=allPages.pages.begin();it != allPages.pages.end();it++){
|
for (auto it=allPages.pages.begin();it != allPages.pages.end();it++){
|
||||||
LOG_DEBUG(GwLog::LOG,"found registered page %s",(*it)->pageName.c_str());
|
LOG_DEBUG(GwLog::LOG,"found registered page %s",(*it)->pageName.c_str());
|
||||||
@@ -615,8 +615,17 @@ void OBP60Task(GwApi *api){
|
|||||||
setFlashLED(true);
|
setFlashLED(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Keyboard messages from remote
|
||||||
|
uint8_t remotekey = 0;
|
||||||
|
if (xQueueReceive(keyboardQueue, &remotekey, 0) == pdPASS) {
|
||||||
|
LOG_DEBUG(GwLog::LOG, "OBP received remote key: %d", remotekey);
|
||||||
|
// inject into internal keyboard queue
|
||||||
|
xQueueSend(allParameters.queue, &remotekey, 0);
|
||||||
|
}
|
||||||
|
|
||||||
// Check the keyboard message
|
// Check the keyboard message
|
||||||
int keyboardMessage=0;
|
int keyboardMessage=0;
|
||||||
|
|
||||||
while (xQueueReceive(allParameters.queue,&keyboardMessage,0)){
|
while (xQueueReceive(allParameters.queue,&keyboardMessage,0)){
|
||||||
LOG_DEBUG(GwLog::LOG,"new key from keyboard %d",keyboardMessage);
|
LOG_DEBUG(GwLog::LOG,"new key from keyboard %d",keyboardMessage);
|
||||||
keypressed = true;
|
keypressed = true;
|
||||||
|
|||||||
@@ -41,8 +41,6 @@ lib_deps =
|
|||||||
milesburton/DallasTemperature@3.11.0
|
milesburton/DallasTemperature@3.11.0
|
||||||
signetica/SunRise@2.0.2
|
signetica/SunRise@2.0.2
|
||||||
adafruit/Adafruit FRAM I2C@2.0.3
|
adafruit/Adafruit FRAM I2C@2.0.3
|
||||||
WifiClientSecure
|
|
||||||
HTTPClient
|
|
||||||
build_flags=
|
build_flags=
|
||||||
#https://thingpulse.com/usb-settings-for-logging-with-the-esp32-s3-in-platformio/?srsltid=AfmBOopGskbkr4GoeVkNlFaZXe_zXkLceKF6Rn-tmoXABCeAR2vWsdHL
|
#https://thingpulse.com/usb-settings-for-logging-with-the-esp32-s3-in-platformio/?srsltid=AfmBOopGskbkr4GoeVkNlFaZXe_zXkLceKF6Rn-tmoXABCeAR2vWsdHL
|
||||||
# -D CORE_DEBUG_LEVEL=1 #Debug level for CPU core via CDC (serial device)
|
# -D CORE_DEBUG_LEVEL=1 #Debug level for CPU core via CDC (serial device)
|
||||||
@@ -95,8 +93,6 @@ lib_deps =
|
|||||||
milesburton/DallasTemperature@3.11.0
|
milesburton/DallasTemperature@3.11.0
|
||||||
signetica/SunRise@2.0.2
|
signetica/SunRise@2.0.2
|
||||||
adafruit/Adafruit FRAM I2C@2.0.3
|
adafruit/Adafruit FRAM I2C@2.0.3
|
||||||
WifiClientSecure
|
|
||||||
HTTPClient
|
|
||||||
build_flags=
|
build_flags=
|
||||||
-D DISABLE_DIAGNOSTIC_OUTPUT #Disable diagnostic output for GxEPD2 lib
|
-D DISABLE_DIAGNOSTIC_OUTPUT #Disable diagnostic output for GxEPD2 lib
|
||||||
-D BOARD_OBP40S3 #Board OBP40 with ESP32S3
|
-D BOARD_OBP40S3 #Board OBP40 with ESP32S3
|
||||||
|
|||||||
@@ -189,6 +189,10 @@ public:
|
|||||||
{
|
{
|
||||||
return api->getQueue();
|
return api->getQueue();
|
||||||
}
|
}
|
||||||
|
virtual QueueHandle_t getKbQueue()
|
||||||
|
{
|
||||||
|
return api->getKbQueue();
|
||||||
|
}
|
||||||
virtual void sendN2kMessage(const tN2kMsg &msg,bool convert)
|
virtual void sendN2kMessage(const tN2kMsg &msg,bool convert)
|
||||||
{
|
{
|
||||||
GWSYNCHRONIZED(mainLock);
|
GWSYNCHRONIZED(mainLock);
|
||||||
|
|||||||
11
src/main.cpp
11
src/main.cpp
@@ -158,6 +158,8 @@ GwCounter<unsigned long> countNMEA2KIn("countNMEA2000in");
|
|||||||
GwCounter<unsigned long> countNMEA2KOut("countNMEA2000out");
|
GwCounter<unsigned long> countNMEA2KOut("countNMEA2000out");
|
||||||
GwIntervalRunner timers;
|
GwIntervalRunner timers;
|
||||||
|
|
||||||
|
QueueHandle_t keyboardQueue = NULL;
|
||||||
|
|
||||||
bool checkPass(String hash){
|
bool checkPass(String hash){
|
||||||
return config.checkPass(hash);
|
return config.checkPass(hash);
|
||||||
}
|
}
|
||||||
@@ -269,6 +271,10 @@ public:
|
|||||||
{
|
{
|
||||||
return &mainQueue;
|
return &mainQueue;
|
||||||
}
|
}
|
||||||
|
virtual QueueHandle_t getKbQueue()
|
||||||
|
{
|
||||||
|
return keyboardQueue;
|
||||||
|
}
|
||||||
virtual void sendN2kMessage(const tN2kMsg &msg,bool convert)
|
virtual void sendN2kMessage(const tN2kMsg &msg,bool convert)
|
||||||
{
|
{
|
||||||
handleN2kMessage(msg,sourceId,!convert);
|
handleN2kMessage(msg,sourceId,!convert);
|
||||||
@@ -860,6 +866,8 @@ void setup() {
|
|||||||
webserver.begin();
|
webserver.begin();
|
||||||
xdrMappings.begin();
|
xdrMappings.begin();
|
||||||
logger.flush();
|
logger.flush();
|
||||||
|
// remote keyboard support
|
||||||
|
keyboardQueue = xQueueCreate(10, sizeof(uint8_t));
|
||||||
GwConverterConfig converterConfig;
|
GwConverterConfig converterConfig;
|
||||||
converterConfig.init(&config,&logger);
|
converterConfig.init(&config,&logger);
|
||||||
nmea0183Converter= N2kDataToNMEA0183::create(&logger, &boatData,
|
nmea0183Converter= N2kDataToNMEA0183::create(&logger, &boatData,
|
||||||
@@ -869,7 +877,8 @@ void setup() {
|
|||||||
,
|
,
|
||||||
config.getString(config.talkerId,String("GP")),
|
config.getString(config.talkerId,String("GP")),
|
||||||
&xdrMappings,
|
&xdrMappings,
|
||||||
converterConfig
|
converterConfig,
|
||||||
|
keyboardQueue
|
||||||
);
|
);
|
||||||
|
|
||||||
toN2KConverter= NMEA0183DataToN2K::create(&logger,&boatData,[](const tN2kMsg &msg, int sourceId)->bool{
|
toN2KConverter= NMEA0183DataToN2K::create(&logger,&boatData,[](const tN2kMsg &msg, int sourceId)->bool{
|
||||||
|
|||||||
@@ -88,6 +88,16 @@
|
|||||||
"description":"the brightness of the led (0..255)",
|
"description":"the brightness of the led (0..255)",
|
||||||
"category":"system"
|
"category":"system"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "swBankInstance",
|
||||||
|
"type": "number",
|
||||||
|
"default": 0,
|
||||||
|
"min": 0,
|
||||||
|
"max": 252,
|
||||||
|
"check": "checkMinMax",
|
||||||
|
"description": "the instance of switch bank to receive data for (0..252)",
|
||||||
|
"category": "system"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "talkerId",
|
"name": "talkerId",
|
||||||
"label": "NMEA0183 ID",
|
"label": "NMEA0183 ID",
|
||||||
|
|||||||
Reference in New Issue
Block a user