mirror of
https://github.com/thooge/esp32-nmea2000-obp60.git
synced 2026-09-11 19:55:14 +02:00
PageCurrent: added leeway coeff, changed boat value handling, fixed ROLL
This commit is contained in:
@@ -3,15 +3,26 @@
|
||||
#include "Pagedata.h"
|
||||
#include "OBP60Extensions.h"
|
||||
#include "OBPDataOperations.h"
|
||||
// #include <cmath>
|
||||
#include <unordered_map>
|
||||
|
||||
// Screen coordinates
|
||||
// Screen coordinates for three boat values
|
||||
struct Points {
|
||||
int16_t x1, y1;
|
||||
int16_t x2, y2;
|
||||
int16_t x3, y3;
|
||||
};
|
||||
|
||||
// leeway K coefficient selection options from OBP configuration page
|
||||
static const std::unordered_map<std::string, int> leeKMap = {
|
||||
{ "---", 0 },
|
||||
{ "Racer [2]", 2 },
|
||||
{ "Multihull Draggerboard [4]", 4 },
|
||||
{ "Performance Cruiser [6]", 6 },
|
||||
{ "Family Cruiser [9]", 9 },
|
||||
{ "Heavy Displacement [13]", 13 },
|
||||
{ "Multihull Fixed Keel [16]", 16 }
|
||||
};
|
||||
|
||||
// Screen coordinates for boat data values (top-left, bottom-left, top-right, bottom-right corners)
|
||||
static constexpr Points POS[] = {
|
||||
{ 10, 65, 10, 95, 10, 115 }, // Position left top for value, name, unit
|
||||
@@ -61,7 +72,8 @@ private:
|
||||
bool holdValues;
|
||||
String flashLED;
|
||||
String backlightMode;
|
||||
uint8_t leeK;
|
||||
String leeKStd;
|
||||
double leeK;
|
||||
|
||||
static constexpr int NUMVALUES = 10; // no. of data values in this page
|
||||
static constexpr double DBL_MAX = std::numeric_limits<double>::max();
|
||||
@@ -120,11 +132,11 @@ private:
|
||||
|
||||
ctw = calcCTW(awa, hdt, lay);
|
||||
|
||||
// Ground velocity vector (East, North)
|
||||
// Ground velocity vector (east, north)
|
||||
double vg_x = sog * std::sin(cog);
|
||||
double vg_y = sog * std::cos(cog);
|
||||
|
||||
// Water-relative velocity vector (East, North)
|
||||
// Water-relative velocity vector (east, north)
|
||||
double vw_x = stw * std::sin(ctw);
|
||||
double vw_y = stw * std::cos(ctw);
|
||||
|
||||
@@ -137,8 +149,8 @@ private:
|
||||
crnt.set = std::atan2(vc_x, vc_y); // atan2(x, y) because 0° = North, clockwise positive
|
||||
crnt.set = WindUtils::to2PI(crnt.set); // internal respresentation of wind is [0..2PI]
|
||||
|
||||
LOG_DEBUG(GwLog::DEBUG, "PageCurrent-setDrift: sog: %.3f, ctw: %.3f, stw: %.3f, vc_x: %.3f, vc_y: %.3f, set: %.3f, drift: %.3f",
|
||||
sog, ctw, stw, vc_x, vc_y, crnt.set, crnt.dft);
|
||||
//LOG_DEBUG(GwLog::DEBUG, "PageCurrent-setDrift: sog: %.3f, ctw: %.3f, stw: %.3f, vc_x: %.3f, vc_y: %.3f, set: %.3f, drift: %.3f",
|
||||
// sog, ctw, stw, vc_x, vc_y, crnt.set, crnt.dft);
|
||||
|
||||
return crnt;
|
||||
};
|
||||
@@ -254,16 +266,6 @@ private:
|
||||
getdisplay().fillTriangle(rx[0], ry[0], rx[2], ry[2], rx[6], ry[6], commonData->bgcolor);
|
||||
getdisplay().fillTriangle(rx[5], ry[5], rx[4], ry[4], rx[3], ry[3], commonData->bgcolor);
|
||||
|
||||
/* // draw arrow frame (double for 2 px thickness)
|
||||
for (int i = 0; i < 7; i++) {
|
||||
int next = (i + 1) % 7;
|
||||
// outer frame
|
||||
getdisplay().drawLine(rx[i], ry[i], rx[next], ry[next], commonData->fgcolor);
|
||||
// inner frame
|
||||
getdisplay().drawLine(rxi[i], ryi[i], rxi[next], ryi[next], commonData->fgcolor);
|
||||
}
|
||||
*/
|
||||
// 5. Rahmen mit "Overdraw" für konstante Dicke
|
||||
// draw arrow frame with "overdraw" for constant thickness
|
||||
for (int i = 0; i < 7; i++) {
|
||||
int next = (i + 1) % 7;
|
||||
@@ -297,8 +299,15 @@ public:
|
||||
holdValues = commonData->config->getBool(commonData->config->holdvalues);
|
||||
flashLED = commonData->config->getString(commonData->config->flashLED);
|
||||
backlightMode = commonData->config->getString(commonData->config->backlight);
|
||||
// leeK = commonData->config->getInt(commonData->config->leeK);
|
||||
leeK = 9;
|
||||
|
||||
leeKStd = commonData->config->getString(commonData->config->leeKStd);
|
||||
auto it = leeKMap.find(leeKStd.c_str());
|
||||
if (it != leeKMap.end()) {
|
||||
leeK = it->second;
|
||||
} else if (leeKStd == "Individual value") {
|
||||
leeK = (commonData->config->getString(commonData->config->leeK)).toDouble();
|
||||
}
|
||||
LOG_DEBUG(GwLog::DEBUG, "PageCurrent: leeKStd: %s, leeK: %.3f", leeKStd.c_str(), leeK);
|
||||
}
|
||||
|
||||
virtual int handleKey(int key)
|
||||
@@ -347,43 +356,49 @@ public:
|
||||
// 0=AWA, 1=HDT, 2=SET, 3=DFT, 4=SOG, 5=COG, 6=STW, 7=HDM, 8=VAR, 9=ROLL
|
||||
std::vector<GwApi::BoatValue*> bValue(pageData.values.begin(), pageData.values.end());
|
||||
|
||||
LOG_DEBUG(GwLog::DEBUG, "PageCurrent: printing #1: %s, %.3f, #2: %s, %.3f, #3: %s, %.3f, #4: %s, %.3f",
|
||||
bValue[AWA]->getName().c_str(), bValue[AWA]->value, bValue[HDT]->getName().c_str(), bValue[HDT]->value,
|
||||
bValue[SET]->getName().c_str(), bValue[SET]->value, bValue[DFT]->getName().c_str(), bValue[DFT]->value);
|
||||
|
||||
double awa = bValue[AWA]->valid ? bValue[AWA]->value : DBL_MAX;
|
||||
double hdt = bValue[HDT]->valid ? bValue[HDT]->value : DBL_MAX;
|
||||
current.set = bValue[SET]->valid ? bValue[SET]->value : DBL_MAX;
|
||||
current.dft = bValue[DFT]->valid ? bValue[DFT]->value : DBL_MAX;
|
||||
double sog = bValue[SOG]->valid ? bValue[SOG]->value : DBL_MAX;
|
||||
double cog = bValue[COG]->valid ? bValue[COG]->value : DBL_MAX;
|
||||
double stw = bValue[STW]->valid ? bValue[STW]->value : DBL_MAX;
|
||||
double hdm = bValue[HDM]->valid ? bValue[HDM]->value : DBL_MAX;
|
||||
double var = bValue[VAR]->valid ? bValue[VAR]->value : DBL_MAX;
|
||||
double roll = bValue[ROLL]->valid ? bValue[ROLL]->value : DBL_MAX;
|
||||
LOG_DEBUG(GwLog::DEBUG, "PageCurrent: printing #1: %s, %.3f, valid: %d, #2: %s, %.3f, valid: %d, #3: %s, %.3f, valid: %d, #4: %s, %.3f, valid: %d",
|
||||
bValue[AWA]->getName().c_str(), bValue[AWA]->value, bValue[AWA]->valid, bValue[HDT]->getName().c_str(), bValue[HDT]->value, bValue[HDT]->valid,
|
||||
bValue[SET]->getName().c_str(), bValue[SET]->value, bValue[SET]->valid, bValue[DFT]->getName().c_str(), bValue[DFT]->value, bValue[DFT]->valid);
|
||||
|
||||
// Calculate current data
|
||||
//***********************************************************
|
||||
|
||||
LOG_DEBUG(GwLog::DEBUG, "PageCurrent: hdt 2nd: %.3f", hdt);
|
||||
if (current.set == DBL_MAX || current.dft == DBL_MAX) { // If SET or DRIFT not available, try to calculate them
|
||||
if (!bValue[SET]->valid || !bValue[DFT]->valid) { // If SET or DRIFT not available, try to calculate them
|
||||
if (bValue[SOG]->valid && bValue[COG]->valid && bValue[STW]->valid && bValue[AWA]->valid) { // calculate current only if all required values are available
|
||||
|
||||
if (hdt == DBL_MAX) { // HDT not available
|
||||
if (hdm != DBL_MAX) {
|
||||
hdt = hdm + (var != DBL_MAX ? var : 0.0); // Use corrected HDM if HDT is not available; just use HDM if VAR is not available
|
||||
hdt = WindUtils::to2PI(hdt);
|
||||
if (!bValue[HDT]->valid) { // HDT not available
|
||||
if (bValue[HDM]->valid) {
|
||||
if (bValue[VAR]->valid) {
|
||||
bValue[HDT]->value = bValue[HDM]->value + bValue[VAR]->value; // Use corrected HDM if HDT is not available
|
||||
bValue[HDT]->value = WindUtils::to2PI(bValue[HDT]->value);
|
||||
bValue[HDT]->valid = true;
|
||||
} else {
|
||||
// if HDT cannot be fully substituted by HDM+VAR, continue with HDM only
|
||||
bValue[HDT] = bValue[HDM];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!bValue[ROLL]->valid) {
|
||||
bValue[ROLL]->value = 0; // delete last value if roll value is not valid anymore; gateway keeps last value
|
||||
}
|
||||
lay = calcLeeway(leeK, bValue[ROLL]->value, bValue[STW]->value);
|
||||
|
||||
if (bValue[HDT]->valid) { // That's either HDT or HDM
|
||||
current = calcSetAndDrift(lay, bValue[SOG]->value, bValue[COG]->value, bValue[STW]->value, bValue[HDT]->value, bValue[AWA]->value);
|
||||
bValue[SET]->value = current.set;
|
||||
bValue[SET]->setFormat("formatCourse");
|
||||
bValue[SET]->valid = true;
|
||||
bValue[DFT]->value = current.dft;
|
||||
bValue[DFT]->setFormat("formatKnots");
|
||||
bValue[DFT]->valid = true;
|
||||
}
|
||||
}
|
||||
LOG_DEBUG(GwLog::DEBUG, "PageCurrent: hdt 3rd: %.3f", hdt);
|
||||
|
||||
leeK = 4;
|
||||
roll = 10 * DEG_TO_RAD;
|
||||
lay = calcLeeway(leeK, roll, stw);
|
||||
current = calcSetAndDrift(lay, sog, cog, stw, hdt, awa);
|
||||
}
|
||||
|
||||
LOG_DEBUG(GwLog::DEBUG, "PageCurrent: leeK: %d, lay: %.3f, roll: %.3f, stw: %.3f, awa: %.3f, hdt: %.3f, cog: %.3f, sog: %.3f, set: %.3f, dft: %.3f",
|
||||
leeK, lay, roll, stw, awa, hdt, cog, sog, current.set, current.dft);
|
||||
LOG_DEBUG(GwLog::DEBUG, "PageCurrent: leeKStd: %s, leeK: %.3f, lay: %.3f, roll: %.3f, stw: %.3f, awa: %.3f, hdt: %.3f, cog: %.3f, sog: %.3f, set: %.3f, dft: %.3f",
|
||||
leeKStd.c_str(), leeK, lay, bValue[ROLL]->value, bValue[STW]->value, bValue[AWA]->value, bValue[HDT]->value, bValue[COG]->value, bValue[SOG]->value,
|
||||
bValue[SET]->value, bValue[DFT]->value);
|
||||
|
||||
// Draw page
|
||||
//***********************************************************
|
||||
@@ -394,36 +409,10 @@ public:
|
||||
for (int i = 0; i < 4; i++) { // Display first 4 values
|
||||
String name = xdrDelete(bValue[i]->getName()); // Value name
|
||||
name = name.substring(0, 6); // String length limit for value name
|
||||
if (!bValue[i]->valid) {
|
||||
switch (i) {
|
||||
case AWA:
|
||||
break; // we don't change AWA any time, so there is no adjustment option
|
||||
case HDT:
|
||||
bValue[i]->value = hdt;
|
||||
bValue[i]->setFormat("formatCourse");
|
||||
bValue[i]->valid = true; // Valid information
|
||||
break;
|
||||
case SET:
|
||||
bValue[i]->value = current.set;
|
||||
bValue[i]->setFormat("formatCourse");
|
||||
bValue[i]->valid = true; // Valid information
|
||||
break;
|
||||
case DFT:
|
||||
bValue[i]->value = current.dft;
|
||||
bValue[i]->setFormat("formatKnots");
|
||||
bValue[i]->valid = true; // Valid information
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
String sValue = formatValue(bValue[i], *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit = formatValue(bValue[i], *commonData).unit; // Unit of value
|
||||
|
||||
LOG_DEBUG(GwLog::DEBUG, "PageCurrent: name: %s, value: %s, format: %s, unit: %s",
|
||||
name, sValue, bValue[i]->getFormat().c_str(), unit);
|
||||
|
||||
// Show bus data
|
||||
// Show boat data value
|
||||
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
getdisplay().setCursor(POS[i].x1, POS[i].y1);
|
||||
if (!holdValues || useSimuData) {
|
||||
@@ -458,9 +447,13 @@ public:
|
||||
// Horizontal separator right
|
||||
getdisplay().fillRect(339, 149, 60, 2, commonData->fgcolor);
|
||||
|
||||
drawCompassRose(hdt);
|
||||
if (bValue[HDT]->valid) {
|
||||
drawCompassRose(bValue[HDT]->value);
|
||||
} else {
|
||||
drawCompassRose(0.0);
|
||||
};
|
||||
getdisplay().drawBitmap((width - WAVE_W) / 2, (height - WAVE_H) / 2, wave_bitmap, WAVE_W, WAVE_H, commonData->fgcolor);
|
||||
drawRotatedArrow(current.dft, WindUtils::to2PI(current.set - hdt));
|
||||
drawRotatedArrow(bValue[DFT]->value, WindUtils::to2PI(bValue[SET]->value - bValue[HDT]->value));
|
||||
|
||||
return PAGE_UPDATE;
|
||||
};
|
||||
@@ -482,7 +475,7 @@ PageDescription registerPageCurrent(
|
||||
"Current", // Page name
|
||||
createPage, // Action
|
||||
0, // Number of bus values depends on selection in Web configuration
|
||||
{ "AWA", "HDT", "SET", "DFT", "SOG", "COG", "STW", "HDM", "VAR", "ROLL" }, // Bus values we need in the page
|
||||
{ "AWA", "HDT", "SET", "DFT", "SOG", "COG", "STW", "HDM", "VAR", "xdrROLL" }, // Bus values we need in the page
|
||||
true // Show display header on/off
|
||||
);
|
||||
|
||||
|
||||
@@ -75,6 +75,44 @@
|
||||
"obp40": "true"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "leeKStd",
|
||||
"label": "Leeway Coefficient",
|
||||
"type": "list",
|
||||
"default": "---",
|
||||
"description": "Boat coefficient K for leeway",
|
||||
"list": [
|
||||
"---",
|
||||
"Racer [2]",
|
||||
"Multihull Draggerboard [4]",
|
||||
"Performance Cruiser [6]",
|
||||
"Family Cruiser [9]",
|
||||
"Heavy Displacement [13]",
|
||||
"Multihull Fixed Keel [16]",
|
||||
"Individual value"
|
||||
],
|
||||
"category": "OBP40 Settings",
|
||||
"capabilities": {
|
||||
"obp40": "true"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "leeK",
|
||||
"label": "Leeway Coefficient",
|
||||
"type": "number",
|
||||
"default": "0.00",
|
||||
"check": "checkMinMax",
|
||||
"min": 0,
|
||||
"max": 20,
|
||||
"description": "Boat coefficient K for leeway - individual setting [0..20]",
|
||||
"category": "OBP40 Settings",
|
||||
"capabilities": {
|
||||
"obp40":"true"
|
||||
},
|
||||
"condition": [
|
||||
{ "leeKStd": ["Individual value"] }
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "fuelTank",
|
||||
"label": "Fuel Tank [l]",
|
||||
|
||||
@@ -75,6 +75,44 @@
|
||||
"obp60":"true"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "leeKStd",
|
||||
"label": "Leeway Coefficient",
|
||||
"type": "list",
|
||||
"default": "---",
|
||||
"description": "Boat coefficient K for leeway",
|
||||
"list": [
|
||||
"---",
|
||||
"Racer [2]",
|
||||
"Multihull Draggerboard [4]",
|
||||
"Performance Cruiser [6]",
|
||||
"Family Cruiser [9]",
|
||||
"Heavy Displacement [13]",
|
||||
"Multihull Fixed Keel [16]",
|
||||
"Individual value"
|
||||
],
|
||||
"category": "OBP60 Settings",
|
||||
"capabilities": {
|
||||
"obp60": "true"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "leeK",
|
||||
"label": "Leeway Coefficient",
|
||||
"type": "number",
|
||||
"default": "0.00",
|
||||
"check": "checkMinMax",
|
||||
"min": 0,
|
||||
"max": 20,
|
||||
"description": "Boat coefficient K for leeway - individual setting [0..20]",
|
||||
"category": "OBP60 Settings",
|
||||
"capabilities": {
|
||||
"obp60":"true"
|
||||
},
|
||||
"condition": [
|
||||
{ "leeKStd": ["Individual value"] }
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "fuelTank",
|
||||
"label": "Fuel Tank [l]",
|
||||
|
||||
Reference in New Issue
Block a user