diff --git a/lib/gwwifi/GwWifi.cpp b/lib/gwwifi/GwWifi.cpp index 19e6941..3a8991f 100644 --- a/lib/gwwifi/GwWifi.cpp +++ b/lib/gwwifi/GwWifi.cpp @@ -131,6 +131,7 @@ void GwWifi::loop(){ if (lastConnectStart > now || (lastConnectStart + RETRY_MILLIS) < now) { LOG_DEBUG(GwLog::LOG,"wifiClient: retry connect to %s", wifiSSID->asCString()); +<<<<<<< HEAD // CRITICAL SECTION: WiFi-Operationen müssen serialisiert werden if (acquireMutex()){ WiFi.disconnect(); @@ -140,6 +141,23 @@ void GwWifi::loop(){ else{ LOG_DEBUG(GwLog::ERROR,"GwWifi: mutex timeout in loop"); } +======= + +//+++++++++ Old part +++++++++++++++++++++ +// WiFi.disconnect(); +// connectInternal(); +//++++++++++++++++++++++++++++++++++++++++ + +//+++++++++ New part +++++++++++++++++++++ + WiFi.disconnect(true); + delay(300); + esp_wifi_stop(); + delay(100); + esp_wifi_start(); + connectInternal(); +//++++++++++++++++++++++++++++++++++++++++ + +>>>>>>> autopilot2 } } else{ diff --git a/lib/obp60task/OBP60Extensions.cpp b/lib/obp60task/OBP60Extensions.cpp index 76c6334..3b3ee88 100644 --- a/lib/obp60task/OBP60Extensions.cpp +++ b/lib/obp60task/OBP60Extensions.cpp @@ -923,7 +923,7 @@ void solarGraphic(uint x, uint y, int pcolor, int bcolor){ } -// Generator graphic with fill level +// Generator graphic void generatorGraphic(uint x, uint y, int pcolor, int bcolor){ // Show battery int xb = x; // X position @@ -940,6 +940,74 @@ void generatorGraphic(uint x, uint y, int pcolor, int bcolor){ getdisplay().print("G"); } +// Display rudder position as horizontal bargraph with configurable +/- range (degrees) +void displayRudderPosition(int rudderPosition, uint8_t rangeDeg, uint16_t cx, uint16_t cy, uint16_t fg, uint16_t bg){ + const int w = 360; + const int h = 20; + const int t = 3; // Line thickness + const int halfw = w/2; + const int halfh = h/2; + // Calculate top-left of bar (cx,cy are center of 0°) + int left = int(cx) - halfw; + int top = int(cy) - halfh; + + // clamp provided range to allowed bounds [10,45] + if (rangeDeg < 10) rangeDeg = 10; + if (rangeDeg > 45) rangeDeg = 45; + + // Pixels per degree for +/-rangeDeg -> total span = 2*rangeDeg + const float pxPerDeg = float(w) / (2.0f * float(rangeDeg)); + + // Draw outer border (thickness t) + for (int i = 0; i < t; i++) { + getdisplay().drawRect(left + i, top + i, w - 2 * i, h - 2 * i, fg); + } + + // Fill inner area with background + getdisplay().fillRect(left + t, top + t, w - 2 * t, h - 2 * t, bg); + + // Draw center line + getdisplay().drawRect(cx - 1, top + 1, 3 , h - 2, fg); + + // Clamp rudder position to -rangeDeg..rangeDeg + if (rudderPosition > (int)rangeDeg) rudderPosition = (int)rangeDeg; + if (rudderPosition < -((int)rangeDeg)) rudderPosition = -((int)rangeDeg); + + // Compute fill width in pixels + int fillPx = int(round(rudderPosition * pxPerDeg)); // positive -> right + + // Fill area from center to position (if non-zero) + int centerx = cx; + int innerTop = top + t; + int innerH = h - 2 * t; + if (fillPx > 0) { + // Right side + getdisplay().fillRect(centerx, innerTop, fillPx, innerH, fg); + } else if (fillPx < 0) { + // Left side + getdisplay().fillRect(centerx + fillPx, innerTop, -fillPx, innerH, fg); + } + + + // Draw tick marks every 5° and labels outside the bar + getdisplay().setTextColor(fg); + getdisplay().setFont(&Ubuntu_Bold8pt8b); + for (int angle = -((int)rangeDeg); angle <= (int)rangeDeg; angle += 5) { + int xpos = int(round(centerx + angle * pxPerDeg)); + // Vertical tick inside bar + getdisplay().drawLine(xpos, top, xpos, top + h + 2, fg); + // Label outside: below the bar + String lbl = String(angle); + int16_t bx, by; + uint16_t bw, bh; + getdisplay().getTextBounds(lbl, 0, 0, &bx, &by, &bw, &bh); + int16_t tx = xpos - bw/2; + int16_t ty = top + h + bh + 5; // A little spacing + getdisplay().setCursor(tx, ty); + getdisplay().print(lbl); + } +} + // Function to handle HTTP image request // http://192.168.15.1/api/user/OBP60Task/screenshot void doImageRequest(GwApi *api, int *pageno, const PageStruct pages[MAX_PAGE_NUMBER], AsyncWebServerRequest *request) { diff --git a/lib/obp60task/OBP60Extensions.h b/lib/obp60task/OBP60Extensions.h index 604c356..41e3717 100644 --- a/lib/obp60task/OBP60Extensions.h +++ b/lib/obp60task/OBP60Extensions.h @@ -128,6 +128,10 @@ void solarGraphic(uint x, uint y, int pcolor, int bcolor); // S void generatorGraphic(uint x, uint y, int pcolor, int bcolor); // Generator graphic void startLedTask(GwApi *api); +// Display rudder position as horizontal bargraph with configurable +/- range (degrees) +// 'rangeDeg' is unsigned and will be clamped to [10,45] +void displayRudderPosition(int rudderPosition, uint8_t rangeDeg, uint16_t cx, uint16_t cy, uint16_t fg, uint16_t bg); + void doImageRequest(GwApi *api, int *pageno, const PageStruct pages[MAX_PAGE_NUMBER], AsyncWebServerRequest *request); // Icons diff --git a/lib/obp60task/OBPSensorTask.cpp b/lib/obp60task/OBPSensorTask.cpp index 25d861b..1424907 100644 --- a/lib/obp60task/OBPSensorTask.cpp +++ b/lib/obp60task/OBPSensorTask.cpp @@ -371,7 +371,7 @@ void sensorTask(void *param){ GwApi::BoatValue *hdop=new GwApi::BoatValue(GwBoatData::_HDOP); GwApi::BoatValue *valueList[]={gpsdays, gpsseconds, hdop}; - // Internal RTC with NTP init + // Internal iRTC with NTP init ESP32Time rtc(0); if (api->getConfig()->getString(api->getConfig()->timeSource) == "iRTC") { GwApi::Status status; @@ -432,17 +432,17 @@ void sensorTask(void *param){ iRTC RTC GPS N2K 0 0 0 (1) - 0 0 (1) (X) - 0 (1) 0 (X) - 0 1 <-(1) (X) - (1) 0 0 (X) - 1 0 (1) (X) - 1 ->(1) 0 (X) - 1 1 <-(1) (X) + 0 0 (1) X + 0 (1) 0 X + 0 1 <-(1) X + (1) 0 0 X + 1 0 (1) X + 1 ->(1) 0 X + 1 1 <-(1) X */ - // If RTC DS1388 ready, then copy iRTC and GPS data to RTC all 1min + // If RTC DS1388 ready, then copy iRTC and GPS data to RTC all 1 min if(millis() > starttime11 + 1*60*1000){ starttime11 = millis(); // Set RTC chip via iRTC (NTP) @@ -475,7 +475,7 @@ void sensorTask(void *param){ // Adjust RTC time as unix time value ds1388.adjust(adjusttime); } - } + } } // Set RTC chip via N2K or 183 in case the internal GPS is off (only one time) @@ -524,7 +524,7 @@ void sensorTask(void *param){ // N2K sysTime is double in n2klib double sysTime = (dt.hour() * 3600) + (dt.minute() * 60) + dt.second(); if(!isnan(daysAt1970) && !isnan(sysTime)){ - //api->getLogger()->logDebug(GwLog::LOG,"RTC time: %04d/%02d/%02d %02d:%02d:%02d",sensors.rtcTime.tm_year+1900,sensors.rtcTime.tm_mon, sensors.rtcTime.tm_mday, sensors.rtcTime.tm_hour, sensors.rtcTime.tm_min, sensors.rtcTime.tm_sec); + //api->getLogger()->logDebug(GwLog::LOG,"RTC time: %04d/%02d/%02d %02d:%02d:%02d",sensors.rtcTime.tm_year+1900,sensors.rtcTime.tm_mon+1, sensors.rtcTime.tm_mday, sensors.rtcTime.tm_hour, sensors.rtcTime.tm_min, sensors.rtcTime.tm_sec); //api->getLogger()->logDebug(GwLog::LOG,"Send PGN126992: %10d %10d",daysAt1970, (uint16_t)sysTime); SetN2kPGN126992(N2kMsg,0,daysAt1970,sysTime,N2ktimes_LocalCrystalClock); api->sendN2kMessage(N2kMsg); @@ -533,25 +533,26 @@ void sensorTask(void *param){ } // Send date and time from software RTC (iRTC) if (iRTC_ready == true && RTC_ready == false && GPS_ready == false) { - // Use internal RTC feature - sensors.rtcTime = rtc.getTimeStruct(); // Save software RTC values in SensorData - // TODO implement daysAt1970 and sysTime as methods of DateTime + sensors.rtcTime = rtc.getTimeStruct(); + const short daysOfYear[12] = {0,31,59,90,120,151,181,212,243,273,304,334}; - uint16_t switchYear = ((sensors.rtcTime.tm_year-1)-1968)/4 - ((sensors.rtcTime.tm_year-1)-1900)/100 + ((sensors.rtcTime.tm_year-1)-1600)/400; - long daysAt1970 = (sensors.rtcTime.tm_year-1970)*365 + switchYear + daysOfYear[sensors.rtcTime.tm_mon-1] + sensors.rtcTime.tm_mday-1; - // If switch year then add one day - if ((sensors.rtcTime.tm_mon > 2) && (sensors.rtcTime.tm_year % 4 == 0 && (sensors.rtcTime.tm_year % 100 != 0 || sensors.rtcTime.tm_year % 400 == 0))) { + int year = sensors.rtcTime.tm_year + 1900; + int month = sensors.rtcTime.tm_mon; + int day = sensors.rtcTime.tm_mday; + uint16_t switchYear = ((year - 1) - 1968) / 4 - ((year - 1) - 1900) / 100 + ((year - 1) - 1600) / 400; + long daysAt1970 = (year - 1970) * 365L + switchYear + daysOfYear[month] + day - 1; + + // Leap day add if date is after Feb (i.e. month >= March) + if (month >= 2 && (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))) { daysAt1970 += 1; } - // N2K sysTime is double in n2klib - double sysTime = (sensors.rtcTime.tm_hour * 3600) + (sensors.rtcTime.tm_min * 60) + sensors.rtcTime.tm_sec; - if(!isnan(daysAt1970) && !isnan(sysTime)){ - //api->getLogger()->logDebug(GwLog::LOG,"RTC time: %04d/%02d/%02d %02d:%02d:%02d",sensors.rtcTime.tm_year+1900,sensors.rtcTime.tm_mon, sensors.rtcTime.tm_mday, sensors.rtcTime.tm_hour, sensors.rtcTime.tm_min, sensors.rtcTime.tm_sec); - //api->getLogger()->logDebug(GwLog::LOG,"Send PGN126992: %10d %10d",daysAt1970, (uint16_t)sysTime); - SetN2kPGN126992(N2kMsg,0,daysAt1970,sysTime,N2ktimes_LocalCrystalClock); - api->sendN2kMessage(N2kMsg); - } + double sysTime = sensors.rtcTime.tm_hour * 3600.0 + sensors.rtcTime.tm_min * 60.0 + sensors.rtcTime.tm_sec; + //api->getLogger()->logDebug(GwLog::LOG, "iRTC time: %04d/%02d/%02d %02d:%02d:%02d", year, month + 1, day, sensors.rtcTime.tm_hour, sensors.rtcTime.tm_min, sensors.rtcTime.tm_sec); + //api->getLogger()->logDebug(GwLog::LOG,"Send PGN126992: %10d %10d",daysAt1970, (uint16_t)sysTime); + SetN2kPGN126992(N2kMsg, 0, daysAt1970, sysTime, N2ktimes_LocalCrystalClock); + api->sendN2kMessage(N2kMsg); } + } // Send 1Wire data for all temperature sensors to N2K all 2s diff --git a/lib/obp60task/PageAutopilot.cpp b/lib/obp60task/PageAutopilot.cpp index 6cbf299..ecfc62e 100644 --- a/lib/obp60task/PageAutopilot.cpp +++ b/lib/obp60task/PageAutopilot.cpp @@ -5,8 +5,9 @@ // These constants have to match the declaration below in : // PageDescription registerPageAutopilot( -// {"HDM","HDT", "COG", "STW", "SOG", "DBT","XTE", "DTW", "BTW"}, // Bus values we need in the page -const int HowManyValues = 9; +// {"HDM","HDT", "COG", "STW", "SOG", "DBT","XTE", "DTW", "BTW", "RPOS", "ROT"}, // Bus values we need in the page + +const int HowManyValues = 11; const int AverageValues = 4; @@ -19,10 +20,13 @@ const int ShowDBT = 5; const int ShowXTE = 6; const int ShowDTW = 7; const int ShowBTW = 8; +const int ShowRPOS = 9; +const int ShowROT = 10; const int Compass_X0 = 200; // X center point of compass band -const int Compass_Y0 = 220; // Y position of compass lines -const int Compass_LineLength = 22; // Length of compass lines +const int Compass_Y0 = 90; // Y position of compass lines +//const int Compass_LineLength = 22; // Length of compass lines +const int Compass_LineLength = 15; // Length of compass lines const float Compass_LineDelta = 8.0;// Compass band: 1deg = 5 Pixels, 10deg = 50 Pixels class PageAutopilot : public Page @@ -38,8 +42,11 @@ class PageAutopilot : public Page virtual void setupKeys(){ Page::setupKeys(); - commonData->keydata[0].label = "CMP"; - commonData->keydata[1].label = "SRC"; + commonData->keydata[0].label = "-10"; + commonData->keydata[1].label = "-1"; + commonData->keydata[2].label = "Auto"; + commonData->keydata[3].label = "+1"; + commonData->keydata[4].label = "+10"; } virtual int handleKey(int key){ @@ -69,8 +76,8 @@ class PageAutopilot : public Page GwLog *logger = commonData->logger; // Old values for hold function - static String OldDataText[HowManyValues] = {"", "", "","", "", "","", "", ""}; - static String OldDataUnits[HowManyValues] = {"", "", "","", "", "","", "", ""}; + static String OldDataText[HowManyValues] = {"", "", "", "", "", "","", "", "", "", ""}; + static String OldDataUnits[HowManyValues] = {"", "", "", "", "", "","", "", "", "", ""}; // Get config data String lengthformat = config->getString(config->lengthFormat); @@ -106,15 +113,13 @@ class PageAutopilot : public Page setBlinkingLED(false); setFlashLED(false); } - - if (bvalue == NULL) return PAGE_OK; // WTF why this statement? //*********************************************************** // Set display in partial refresh mode getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update getdisplay().setTextColor(commonData->fgcolor); - +/* // Horizontal line 2 pix top & bottom // Print data on top half getdisplay().fillRect(0, 130, 400, 2, commonData->fgcolor); @@ -138,7 +143,7 @@ class PageAutopilot : public Page OldDataText[WhichDataDisplay] = DataText[WhichDataDisplay]; // Save the old value OldDataUnits[WhichDataDisplay] = DataUnits[WhichDataDisplay]; // Save the old unit } - +*/ // Now draw compass band // Get the data double TheAngle = DataValue[WhichDataCompass]; @@ -152,13 +157,13 @@ class PageAutopilot : public Page buffer[0]=0; getdisplay().setFont(&Ubuntu_Bold16pt8b); - getdisplay().setCursor(10, Compass_Y0-60); + getdisplay().setCursor(10, Compass_Y0-40); getdisplay().print(DataName[WhichDataCompass]); // Page name - // Draw compass base line and pointer getdisplay().fillRect(0, Compass_Y0, 400, 3, commonData->fgcolor); - getdisplay().fillTriangle(Compass_X0,Compass_Y0-40,Compass_X0-10,Compass_Y0-80,Compass_X0+10,Compass_Y0-80,commonData->fgcolor); + //getdisplay().fillTriangle(Compass_X0,Compass_Y0-40,Compass_X0-10,Compass_Y0-80,Compass_X0+10,Compass_Y0-80,commonData->fgcolor); + getdisplay().fillTriangle(Compass_X0,Compass_Y0-30,Compass_X0-10,Compass_Y0-60,Compass_X0+10,Compass_Y0-60,commonData->fgcolor); // Draw trendlines for ( int i = 1; i < abs(TheTrend) / 2; i++){ int x1; @@ -238,6 +243,8 @@ class PageAutopilot : public Page // if ( x_test > 390) // x_test = 320; + displayRudderPosition(DataValue[ShowSOG], 20, 200, 160, commonData->fgcolor, commonData->bgcolor); + return PAGE_UPDATE; }; @@ -256,7 +263,7 @@ PageDescription registerPageAutopilot( "Autopilot", // Page name createPage, // Action 0, // Number of bus values depends on selection in Web configuration - {"HDM","HDT", "COG", "STW", "SOG", "DBT","XTE", "DTW", "BTW"}, // Bus values we need in the page + {"HDM","HDT", "COG", "STW", "SOG", "DBT","XTE", "DTW", "BTW", "RPOS", "ROT"}, // Bus values we need in the page true // Show display header on/off ); diff --git a/lib/obp60task/config_obp40.json b/lib/obp60task/config_obp40.json index 4e75006..7d2662d 100644 --- a/lib/obp60task/config_obp40.json +++ b/lib/obp60task/config_obp40.json @@ -1245,8 +1245,8 @@ "name": "timeSource", "label": "Status Time Source", "type": "list", - "default": "GPS", - "description": "Data source for date and time display in status line [RTC|iRTC|GPS]", + "default": "iRTC", + "description": "Data source for date and time display in status line [iRTC|RTC|GPS]", "list": [ {"l":"Internal real time clock (iRTC)","v":"iRTC"}, {"l":"External real time clock (RTC)","v":"RTC"}, @@ -1517,6 +1517,7 @@ "default": "Voltage", "description": "Type of page for page 1", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", @@ -1847,6 +1848,7 @@ "default": "WindRose", "description": "Type of page for page 2", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", @@ -2168,6 +2170,7 @@ "default": "OneValue", "description": "Type of page for page 3", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", @@ -2480,6 +2483,7 @@ "default": "TwoValues", "description": "Type of page for page 4", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", @@ -2783,6 +2787,7 @@ "default": "ThreeValues", "description": "Type of page for page 5", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", @@ -3077,6 +3082,7 @@ "default": "FourValues", "description": "Type of page for page 6", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", @@ -3362,6 +3368,7 @@ "default": "FourValues2", "description": "Type of page for page 7", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", @@ -3638,6 +3645,7 @@ "default": "Clock", "description": "Type of page for page 8", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", @@ -3905,6 +3913,7 @@ "default": "RollPitch", "description": "Type of page for page 9", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", @@ -4163,6 +4172,7 @@ "default": "Battery2", "description": "Type of page for page 10", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", diff --git a/lib/obp60task/config_obp60.json b/lib/obp60task/config_obp60.json index 8318af7..305688f 100644 --- a/lib/obp60task/config_obp60.json +++ b/lib/obp60task/config_obp60.json @@ -1235,8 +1235,9 @@ "label": "Status Time Source", "type": "list", "default": "GPS", - "description": "Data source for date and time display in status line [RTC|GPS]", + "description": "Data source for date and time display in status line [iRTC|RTC|GPS]", "list": [ + {"l":"Internal real time clock (iRTC)","v":"iRTC"}, {"l":"Real time clock (RTC)","v":"RTC"}, {"l":"Time via bus (GPS)","v":"GPS"} ], @@ -1494,6 +1495,7 @@ "default": "Voltage", "description": "Type of page for page 1", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", @@ -1794,6 +1796,7 @@ "default": "WindRose", "description": "Type of page for page 2", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", @@ -2086,6 +2089,7 @@ "default": "OneValue", "description": "Type of page for page 3", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", @@ -2370,6 +2374,7 @@ "default": "TwoValues", "description": "Type of page for page 4", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", @@ -2646,6 +2651,7 @@ "default": "ThreeValues", "description": "Type of page for page 5", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", @@ -2914,6 +2920,7 @@ "default": "FourValues", "description": "Type of page for page 6", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", @@ -3174,6 +3181,7 @@ "default": "FourValues2", "description": "Type of page for page 7", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", @@ -3426,6 +3434,7 @@ "default": "Clock", "description": "Type of page for page 8", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", @@ -3670,6 +3679,7 @@ "default": "RollPitch", "description": "Type of page for page 9", "list": [ + "Autopilot", "BME280", "Battery", "Battery2", @@ -3906,6 +3916,7 @@ "default": "Battery2", "description": "Type of page for page 10", "list": [ + "Autopilot", "BME280", "Battery", "Battery2",