diff --git a/lib/obp60task/PageAnchor.cpp b/lib/obp60task/PageAnchor.cpp index 06b4ff5..1f43542 100644 --- a/lib/obp60task/PageAnchor.cpp +++ b/lib/obp60task/PageAnchor.cpp @@ -6,16 +6,37 @@ /* 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 - TWS - Wind strength - TWD - Wind direction + 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 @@ -27,54 +48,180 @@ static unsigned char anchor_bits[] = { 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 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; - common.logger->logDebug(GwLog::LOG,"Instantiate PageAnchor"); + config = commonData->config; + logger = commonData->logger; + logger->logDebug(GwLog::LOG,"Instantiate PageAnchor"); // preload configuration data - simulation = common.config->getBool(common.config->useSimuData); - holdvalues = common.config->getBool(common.config->holdvalues); - flashLED = common.config->getString(common.config->flashLED); - backlightMode = common.config->getString(common.config->backlight); + 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"; } - virtual int handleKey(int key){ - // Code for keylock - if (key == 11) { + 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; // Commit the key + return 0; } return key; } void displayNew(PageData &pageData){ - } + }; int displayPage(PageData &pageData){ - GwConfigHandler *config = commonData->config; - GwLog *logger = commonData->logger; // 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 - uint16_t cx = 200; // center = anchor position - uint16_t cy = 150; - - // draw anchor symbol (as bitmap) - getdisplay().drawXBitmap(cx - anchor_width / 2, cy - anchor_height / 2, - anchor_bits, anchor_width, anchor_height, commonData->fgcolor); - - - getdisplay().setTextColor(commonData->fgcolor); + if (mode == 'N') { + displayModeNormal(pageData); + } else if (mode == 'C') { + displayModeConfig(); + } return PAGE_UPDATE; }; @@ -82,7 +229,9 @@ class PageAnchor : public Page 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 @@ -90,11 +239,11 @@ static Page *createPage(CommonData &common){ * 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", "TWS", "TWD"}, // Names of bus values undepends on selection in Web configuration (refer GwBoatData.h) - true // Show display header on/off + "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 diff --git a/lib/obp60task/config.json b/lib/obp60task/config.json index 820ce59..214b4ad 100644 --- a/lib/obp60task/config.json +++ b/lib/obp60task/config.json @@ -75,6 +75,20 @@ "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", "label": "Fuel Tank [l]", diff --git a/lib/obp60task/config_obp40.json b/lib/obp60task/config_obp40.json index 2e6c55b..e811748 100644 --- a/lib/obp60task/config_obp40.json +++ b/lib/obp60task/config_obp40.json @@ -75,6 +75,20 @@ "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", "label": "Fuel Tank [l]", diff --git a/lib/obp60task/obp60task.cpp b/lib/obp60task/obp60task.cpp index cd247e1..7a2b493 100644 --- a/lib/obp60task/obp60task.cpp +++ b/lib/obp60task/obp60task.cpp @@ -17,7 +17,7 @@ #include "OBPDataOperations.h" // Functions lib for data operations such as true wind calculation #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 // SD-Card access #include #include