1
0
mirror of https://github.com/thooge/esp32-nmea2000-obp60.git synced 2025-12-28 21:23:07 +01:00

2 Commits

Author SHA1 Message Date
c7a580612e More work on page anchor 2025-07-28 20:44:34 +02:00
a311f2f164 Preparation for new page "Anchor" 2025-07-28 13:14:06 +02:00
5 changed files with 301 additions and 1 deletions

View File

@@ -0,0 +1,249 @@
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
#include "Pagedata.h"
#include "OBP60Extensions.h"
/*
Anchor overview with additional associated data
This page is in experimental stage so be warned!
North is up.
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
This is the fist page to contain a configuration page with
data entry option.
Also it will make use of the new alarm function.
Data
Anchor position lat/lon
Depth at anchor position
Chain length used
Boat position current
Depth at boat position
Boat heading
Wind direction
Wind strength
Alarm j/n
Alarm radius
GPS position error
Timestamp while dropping anchor
Drop / raise function in device OBP40 has to be done inside
config mode because of limited number of buttons.
*/
#define anchor_width 16
#define anchor_height 16
static unsigned char anchor_bits[] = {
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:
GwConfigHandler *config;
GwLog *logger;
bool simulation = false;
bool holdvalues = false;
String flashLED;
String backlightMode;
bool alarm = false;
bool alarm_enabled = false;
uint8_t alarm_range;
uint8_t chain_length;
uint8_t chain;
bool anchor_set = false;
double anchor_lat;
double anchor_lon;
double anchor_depth;
int anchor_ts; // time stamp anchor dropped
char mode = 'N'; // (N)ormal, (C)onfig
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;
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;
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;
Point c = {200, 150}; // center = anchor position
uint16_t r = 125;
Point b = {200, 180}; // boat position while dropping anchor
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}
};
//rotatePoints und dann Linien zeichnen
// TODO rotate boat according to current heading
//fillPoly4(rotatePoints(c, pts, RadToDeg(value2)), commonData->fgcolor);
// Draw wind arrow
/*
if self._bd.awa.value:
p = ((cx, cy - r + 25), (cx - 12, cy - r - 4), (cx, cy - r + 6), (cx + 12, cy - r - 4), (cx, cy - r + 25))
wind = self.rotate((cx, cy), p, self._bd.awa.value)
ctx.move_to(*wind[0])
for point in wind[1:]:
ctx.line_to(*point)
ctx.fill()
*/
// Title and corner value headings
getdisplay().setTextColor(commonData->fgcolor);
getdisplay().setFont(&Ubuntu_Bold10pt8b);
getdisplay().setCursor(8, 48);
getdisplay().print("Anchor");
getdisplay().setCursor(8, 200);
getdisplay().print("Depth");
drawTextRalign(392, 50, "Chain");
drawTextRalign(392, 200, "Wind");
// Corner values
getdisplay().setFont(&Ubuntu_Bold8pt8b);
getdisplay().setCursor(2, 70);
getdisplay().print("Alarm: ");
getdisplay().print(alarm_enabled ? "On" : "Off");
// Units
// Values
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
// Depth
getdisplay().setCursor(8, 250);
//getdisplay().print(sval_dbs);
getdisplay().print("6.4");
// Wind
getdisplay().setCursor(320, 250);
//getdisplay().print(sval_aws);
getdisplay().print("12");
getdisplay().drawCircle(c.x, c.y, r, commonData->fgcolor);
// 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;
config = commonData->config;
logger = commonData->logger;
logger->logDebug(GwLog::LOG,"Instantiate PageAnchor");
// preload configuration data
simulation = config->getBool(config->useSimuData);
holdvalues = config->getBool(config->holdvalues);
flashLED = config->getString(config->flashLED);
backlightMode = config->getString(config->backlight);
chainLength = config->getInt(config->chainLength);
chain = 0;
anchor_set = false;
}
void setupKeys(){
Page::setupKeys();
commonData->keydata[0].label = "MODE";
commonData->keydata[1].label = "ALARM";
}
int handleKey(int key){
if (key == 1) { // Switch between normal and config mode
if (mode == 'N') {
mode = 'C';
} else {
mode = 'N';
}
return 0;
}
if (key == 2) { // Toggle alarm
alarm_enabled = !alarm_enabled;
return 0;
}
if (key == 11) { // Code for keylock
commonData->keylock = !commonData->keylock;
return 0;
}
return key;
}
void displayNew(PageData &pageData){
};
int displayPage(PageData &pageData){
// Logging boat values
LOG_DEBUG(GwLog::LOG,"Drawing at PageAnchor");
LOG_DEBUG(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

View File

@@ -75,6 +75,20 @@
"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]",
@@ -1303,6 +1317,7 @@
"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",
@@ -1584,6 +1599,7 @@
"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",
@@ -1862,6 +1878,7 @@
"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",
@@ -2137,6 +2154,7 @@
"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",
@@ -2409,6 +2427,7 @@
"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",
@@ -2678,6 +2697,7 @@
"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",
@@ -2944,6 +2964,7 @@
"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",
@@ -3207,6 +3228,7 @@
"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",
@@ -3467,6 +3489,7 @@
"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",
@@ -3724,6 +3747,7 @@
"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",

View File

@@ -75,6 +75,20 @@
"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]",
@@ -1326,6 +1340,7 @@
"default": "Clock", "default": "Clock",
"description": "Type of page for page 1", "description": "Type of page for page 1",
"list": [ "list": [
"Anchor",
"BME280", "BME280",
"Battery", "Battery",
"Battery2", "Battery2",
@@ -1607,6 +1622,7 @@
"default": "Wind", "default": "Wind",
"description": "Type of page for page 2", "description": "Type of page for page 2",
"list": [ "list": [
"Anchor",
"BME280", "BME280",
"Battery", "Battery",
"Battery2", "Battery2",
@@ -1885,6 +1901,7 @@
"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",
@@ -2160,6 +2177,7 @@
"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",
@@ -2432,6 +2450,7 @@
"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",
@@ -2701,6 +2720,7 @@
"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",
@@ -2967,6 +2987,7 @@
"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",
@@ -3230,6 +3251,7 @@
"default": "Fluid", "default": "Fluid",
"description": "Type of page for page 8", "description": "Type of page for page 8",
"list": [ "list": [
"Anchor",
"BME280", "BME280",
"Battery", "Battery",
"Battery2", "Battery2",
@@ -3490,6 +3512,7 @@
"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",
@@ -3747,6 +3770,7 @@
"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",

View File

@@ -34,6 +34,7 @@ no_of_fields_per_page = {
"WindPlot": 0, "WindPlot": 0,
"WindRose": 0, "WindRose": 0,
"WindRoseFlex": 6, "WindRoseFlex": 6,
"Anchor", 0
} }
# No changes needed beyond this point # No changes needed beyond this point

View File

@@ -17,7 +17,7 @@
#include "OBPDataOperations.h" // Functions lib for data operations such as true wind calculation #include "OBPDataOperations.h" // Functions lib for data operations such as true wind calculation
#ifdef BOARD_OBP40S3 #ifdef BOARD_OBP40S3
#include "driver/rtc_io.h" // Needs for weakup from deep sleep #include "driver/rtc_io.h" // Needs for wakeup from deep sleep
#include <FS.h> // SD-Card access #include <FS.h> // SD-Card access
#include <SD.h> #include <SD.h>
#include <SPI.h> #include <SPI.h>
@@ -313,6 +313,8 @@ void registerAllPages(PageList &list){
list.add(&registerPageXTETrack); list.add(&registerPageXTETrack);
extern PageDescription registerPageFluid; extern PageDescription registerPageFluid;
list.add(&registerPageFluid); list.add(&registerPageFluid);
extern PageDescription registerPageAnchor;
list.add(&registerPageAnchor);
} }
// Undervoltage detection for shutdown display // Undervoltage detection for shutdown display