From 7400e63a98b6b95ea2e0fc47e8542c7992a3d723 Mon Sep 17 00:00:00 2001 From: bwagstaff <8354948+bwagstaff@users.noreply.github.com> Date: Tue, 28 Jul 2020 15:20:38 -0500 Subject: [PATCH 1/2] Display MAC and IPv4 addresses --- .../mainbar/setup_tile/wlan_settings/wlan_settings.cpp | 6 ++++++ src/gui/statusbar.cpp | 4 +++- src/hardware/wifictl.cpp | 8 +++++++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/gui/mainbar/setup_tile/wlan_settings/wlan_settings.cpp b/src/gui/mainbar/setup_tile/wlan_settings/wlan_settings.cpp index f2d07d4..9c25d25 100644 --- a/src/gui/mainbar/setup_tile/wlan_settings/wlan_settings.cpp +++ b/src/gui/mainbar/setup_tile/wlan_settings/wlan_settings.cpp @@ -150,6 +150,12 @@ void wlan_password_tile_setup( lv_obj_t *tile, lv_style_t *style, lv_coord_t hre lv_obj_align( wlan_password_pass_textfield, wlan_password_tile1, LV_ALIGN_IN_TOP_LEFT, 0, 75); lv_obj_set_event_cb( wlan_password_pass_textfield, wlan_password_event_cb ); + lv_obj_t *mac_label = lv_label_create( wlan_password_tile1, NULL); + lv_obj_add_style( mac_label, LV_IMGBTN_PART_MAIN, style); + lv_obj_set_width( mac_label, LV_HOR_RES); + lv_obj_align( mac_label, wlan_password_tile1, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0); + lv_label_set_text_fmt( mac_label, "MAC: %s", WiFi.macAddress().c_str()); + lv_obj_t *apply_btn = lv_imgbtn_create( wlan_password_tile1, NULL); lv_imgbtn_set_src( apply_btn, LV_BTN_STATE_RELEASED, &check_32px); lv_imgbtn_set_src( apply_btn, LV_BTN_STATE_PRESSED, &check_32px); diff --git a/src/gui/statusbar.cpp b/src/gui/statusbar.cpp index deba7df..7e47207 100644 --- a/src/gui/statusbar.cpp +++ b/src/gui/statusbar.cpp @@ -222,7 +222,9 @@ void statusbar_wifi_set_state( bool state, const char *wifiname ) { else { lv_imgbtn_set_state( statusbar_wifi, LV_BTN_STATE_CHECKED_RELEASED ); } - lv_label_set_text( statusbar_wifilabel, wifiname ); + lv_label_set_long_mode( statusbar_wifilabel, LV_LABEL_LONG_SROLL_CIRC); + lv_obj_set_width( statusbar_wifilabel, LV_HOR_RES); + lv_label_set_text( statusbar_wifilabel, wifiname); lv_obj_align( statusbar_wifilabel, statusbar_wifi, LV_ALIGN_OUT_BOTTOM_MID, 0, 0); statusbar_refresh(); } diff --git a/src/hardware/wifictl.cpp b/src/hardware/wifictl.cpp index 62e6512..70a6e73 100644 --- a/src/hardware/wifictl.cpp +++ b/src/hardware/wifictl.cpp @@ -98,7 +98,13 @@ void wifictl_setup( void ) { powermgm_clear_event( POWERMGM_WIFI_OFF_REQUEST | POWERMGM_WIFI_ON_REQUEST | POWERMGM_WIFI_SCAN ); statusbar_style_icon( STATUSBAR_WIFI, STATUSBAR_STYLE_WHITE ); statusbar_show_icon( STATUSBAR_WIFI ); - statusbar_wifi_set_state( true, wifiname ); + String label(wifiname); + label.concat(' '); + label.concat(WiFi.localIP().toString()); + //If you want to see your IPv6 address too, uncomment this. + // label.concat('\n'); + // label.concat(WiFi.localIPv6().toString()); + statusbar_wifi_set_state( true, label.c_str() ); asyncwebserver_setup(); }, WiFiEvent_t::SYSTEM_EVENT_STA_GOT_IP ); From 1fe0016dbe99285c0e00e874d29594858d31c5b5 Mon Sep 17 00:00:00 2001 From: bwagstaff <8354948+bwagstaff@users.noreply.github.com> Date: Tue, 28 Jul 2020 23:44:47 -0500 Subject: [PATCH 2/2] Add optional wind speed to weather * Add converter function from basic struct to struct with version number, to make future updates easier. * Add flag to weather settings to show/hide wind * Add string to weather data for wind, up to 8 values: up to 3 for value, space, up to 3 for direction, terminator * Add label buttons to displays Notes: I'm new to LVGM and couldn't figure out how to make the layouts automatically adjust. I ended up modifying offsets when wind is displayed. If someone knows the trick for making the layouts adjust height, I'd love to know it. --- src/gui/widget/weather/weather.cpp | 76 +++++++++++++++++++-- src/gui/widget/weather/weather.h | 21 +++++- src/gui/widget/weather/weather_fetch.cpp | 50 ++++++++++++++ src/gui/widget/weather/weather_forecast.cpp | 19 +++++- src/gui/widget/weather/weather_setup.cpp | 48 ++++++++++--- 5 files changed, 196 insertions(+), 18 deletions(-) diff --git a/src/gui/widget/weather/weather.cpp b/src/gui/widget/weather/weather.cpp index 0eac05e..8dbc68c 100644 --- a/src/gui/widget/weather/weather.cpp +++ b/src/gui/widget/weather/weather.cpp @@ -45,6 +45,7 @@ lv_tile_number weather_widget_setup_tile_num = NO_TILE; lv_obj_t *weather_widget_cont = NULL; lv_obj_t *weather_widget_condition_img = NULL; lv_obj_t *weather_widget_temperature_label = NULL; +lv_obj_t *weather_widget_wind_label = NULL; static void enter_weather_widget_event_cb( lv_obj_t * obj, lv_event_t event ); LV_IMG_DECLARE(owm_01d_64px); @@ -79,6 +80,17 @@ void weather_widget_setup( void ) { lv_obj_reset_style_list( weather_widget_temperature_label, LV_OBJ_PART_MAIN ); lv_obj_align( weather_widget_temperature_label, weather_widget_cont, LV_ALIGN_IN_BOTTOM_MID, 0, 0); + weather_widget_wind_label = lv_label_create( weather_widget_cont , NULL); + lv_label_set_text( weather_widget_wind_label, ""); + lv_obj_reset_style_list( weather_widget_wind_label, LV_OBJ_PART_MAIN ); + lv_obj_align( weather_widget_wind_label, weather_widget_cont, LV_ALIGN_IN_BOTTOM_MID, 0, 0); + + if( weather_config.showWind) + { + lv_obj_align( weather_widget_temperature_label, weather_widget_cont, LV_ALIGN_IN_BOTTOM_MID, 0, -20); + lv_obj_align( weather_widget_wind_label, weather_widget_cont, LV_ALIGN_IN_BOTTOM_MID, 0, +5); + } + // regster callback for wifi sync WiFi.onEvent( [](WiFiEvent_t event, WiFiEventInfo_t info) { weather_widget_sync_request(); @@ -138,7 +150,19 @@ void weather_widget_sync_Task( void * pvParameters ) { lv_imgbtn_set_src( weather_widget_condition_img, LV_BTN_STATE_PRESSED, resolve_owm_icon( weather_today.icon ) ); lv_imgbtn_set_src( weather_widget_condition_img, LV_BTN_STATE_CHECKED_RELEASED, resolve_owm_icon( weather_today.icon ) ); lv_imgbtn_set_src( weather_widget_condition_img, LV_BTN_STATE_CHECKED_PRESSED, resolve_owm_icon( weather_today.icon ) ); - lv_obj_align( weather_widget_temperature_label, weather_widget_cont, LV_ALIGN_IN_BOTTOM_MID, 0, 0); + + if (weather_config.showWind) + { + lv_label_set_text( weather_widget_wind_label, weather_today.wind); + lv_obj_align( weather_widget_temperature_label, weather_widget_cont, LV_ALIGN_IN_BOTTOM_MID, 0, -22); + lv_obj_align( weather_widget_wind_label, weather_widget_cont, LV_ALIGN_IN_BOTTOM_MID, 0, 0); + } + else + { + lv_label_set_text( weather_widget_wind_label, ""); + lv_obj_align( weather_widget_temperature_label, weather_widget_cont, LV_ALIGN_IN_BOTTOM_MID, 0, 0); + lv_obj_align( weather_widget_wind_label, weather_widget_cont, LV_ALIGN_IN_BOTTOM_MID, 0, 0); + } } } xEventGroupClearBits( weather_widget_event_handle, WEATHER_WIDGET_SYNC_REQUEST ); @@ -174,13 +198,51 @@ void weather_load_config( void ) { Serial.printf("Can't open file: %s\r\n", WEATHER_CONFIG_FILE ); } else { - int filesize = file.size(); - if ( filesize > sizeof( weather_config ) ) { - Serial.printf("Failed to read configfile. Wrong filesize!\r\n" ); + size_t filesize = file.size(); + + // Special case, convert V1 of the file to a versioned V2 format + if (filesize == sizeof(weather_config_t_v1)) + { + log_i("Reading weather config v1"); + weather_config_t_v1 v1Config; + weather_config_t_v2 &v2Config = weather_config; // For now, V2 is current. + file.read((uint8_t *)&v1Config, filesize); + log_i("Converting weather config v1 to v2"); + v2Config.version = 2; + memcpy(&v2Config.apikey[0], &v1Config, sizeof(weather_config_t_v1)); + v2Config.autosync = v1Config.autosync; + v2Config.showWind = false; } - else { - file.read( (uint8_t *)&weather_config, filesize ); + else if ( filesize > 0) + { + // Read version number, then verify and catch up as needed + uint8_t version = 0; + file.read(&version, 1); + file.seek(0, fs::SeekSet); + log_v("Reading weather config version: %d", version); + + if ( version > currentConfigVersion) + { + log_e( "Unexpected weather config version. Expected at most %d found %d", currentConfigVersion, version); + } + if ( version == 2 ) + { + if (filesize != sizeof(weather_config_t_v2)) + { + log_e( "Failed to read weather config file. Wrong filesize! Expected %d found %d", sizeof(weather_config_t_v2), filesize); + } + else + { + file.read((uint8_t *)&weather_config, filesize); + } + } } + else + { + log_e( "Failed to read weather config file. File size is %d", filesize); + } + file.close(); } -} \ No newline at end of file +} + diff --git a/src/gui/widget/weather/weather.h b/src/gui/widget/weather/weather.h index ec82b03..30cd9b9 100644 --- a/src/gui/widget/weather/weather.h +++ b/src/gui/widget/weather/weather.h @@ -28,12 +28,28 @@ #define WEATHER_WIDGET_SYNC_REQUEST _BV(0) - typedef struct { + constexpr uint8_t currentConfigVersion = 2; + + typedef struct + { char apikey[64] = ""; char lon[16] = ""; char lat[16] = ""; bool autosync = true; - } weather_config_t; + } weather_config_t_v1; + + typedef struct { + char version = 2; + char apikey[64] = ""; + char lon[16] = ""; + char lat[16] = ""; + char autosync : 1; + char showWind : 1; + } weather_config_t_v2; + + typedef weather_config_t_v2 weather_config_t; + + typedef struct { bool valide = false; @@ -43,6 +59,7 @@ char humidity[8] = ""; char name[32] = ""; char icon[8] = ""; + char wind[8] = ""; } weather_forcast_t; void weather_widget_setup( void ); diff --git a/src/gui/widget/weather/weather_fetch.cpp b/src/gui/widget/weather/weather_fetch.cpp index d5d52be..0c70e45 100644 --- a/src/gui/widget/weather/weather_fetch.cpp +++ b/src/gui/widget/weather/weather_fetch.cpp @@ -31,6 +31,9 @@ #include "hardware/powermgm.h" +/* Utility function to convert numbers to directions */ +static void weather_wind_to_string( weather_forcast_t* container, int speed, int directionDegree); + uint32_t weather_fetch_today( weather_config_t *weather_config, weather_forcast_t *weather_today ) { WiFiClient today_client; @@ -113,6 +116,10 @@ uint32_t weather_fetch_today( weather_config_t *weather_config, weather_forcast_ strcpy( weather_today->icon, doc["weather"][0]["icon"] ); strcpy( weather_today->name, doc["name"] ); + int directionDegree = doc["wind"]["deg"].as(); + int speed = doc["wind"]["speed"].as(); + weather_wind_to_string( weather_today, speed, directionDegree ); + doc.clear(); free( json ); return( retval ); @@ -199,9 +206,52 @@ uint32_t weather_fetch_forecast( weather_config_t *weather_config, weather_forca snprintf( weather_forecast[ i ].pressure, sizeof( weather_forecast[ i ].pressure ),"%fpha", doc["list"][i]["main"]["pressure"].as() ); strcpy( weather_forecast[ i ].icon, doc["list"][i]["weather"][0]["icon"] ); strcpy( weather_forecast[ i ].name, doc["city"]["name"] ); + + int directionDegree = doc["list"][i]["wind"]["deg"].as(); + int speed = doc["list"][i]["wind"]["speed"].as(); + weather_wind_to_string( &weather_forecast[i], speed, directionDegree ); } doc.clear(); free( json ); return( 200 ); +} + +void weather_wind_to_string( weather_forcast_t* container, int speed, int directionDegree ) +{ + const char *dir = "N"; + if ( directionDegree > 348 ) + ; // already set to "N" + else if ( directionDegree > 326 ) + dir = "NNW"; + else if ( directionDegree > 303 ) + dir = "NW"; + else if ( directionDegree > 281 ) + dir = "WNW"; + else if ( directionDegree > 258 ) + dir = "W"; + else if ( directionDegree > 236 ) + dir = "WSW"; + else if ( directionDegree > 213 ) + dir = "SW"; + else if ( directionDegree > 191 ) + dir = "SSW"; + else if ( directionDegree > 168 ) + dir = "S"; + else if ( directionDegree > 146 ) + dir = "SSE"; + else if ( directionDegree > 123 ) + dir = "SE"; + else if ( directionDegree > 101 ) + dir = "ESE"; + else if ( directionDegree > 78 ) + dir = "E"; + else if ( directionDegree > 56 ) + dir = "ENE"; + else if ( directionDegree > 33 ) + dir = "NE"; + else if ( directionDegree > 11 ) + dir = "NNE"; + snprintf( container->wind, sizeof(container->wind), "%d %s", speed, dir); + return; } \ No newline at end of file diff --git a/src/gui/widget/weather/weather_forecast.cpp b/src/gui/widget/weather/weather_forecast.cpp index e4b7d40..22de5a7 100644 --- a/src/gui/widget/weather/weather_forecast.cpp +++ b/src/gui/widget/weather/weather_forecast.cpp @@ -44,6 +44,7 @@ lv_obj_t *weather_forecast_update_label = NULL; lv_obj_t *weather_forecast_time_label[ WEATHER_MAX_FORECAST ]; lv_obj_t *weather_forecast_icon_imgbtn[ WEATHER_MAX_FORECAST ]; lv_obj_t *weather_forecast_temperature_label[ WEATHER_MAX_FORECAST ]; +lv_obj_t *weather_forecast_wind_label[ WEATHER_MAX_FORECAST ]; lv_style_t weather_widget_style; weather_forcast_t weather_forecast[ WEATHER_MAX_FORECAST ]; @@ -114,6 +115,11 @@ void weather_widget_tile_setup( lv_obj_t *tile, lv_style_t *style, lv_coord_t hr lv_obj_reset_style_list( weather_forecast_temperature_label[ i ], LV_OBJ_PART_MAIN ); lv_obj_align( weather_forecast_temperature_label[ i ], weather_forecast_icon_imgbtn[ i ], LV_ALIGN_OUT_BOTTOM_MID, 0, 0); + weather_forecast_wind_label[ i ] = lv_label_create( weater_forecast_cont , NULL); + lv_label_set_text( weather_forecast_wind_label[i], ""); + lv_obj_reset_style_list( weather_forecast_wind_label[i], LV_OBJ_PART_MAIN); + lv_obj_align( weather_forecast_wind_label[i], weather_forecast_icon_imgbtn[i], LV_ALIGN_OUT_BOTTOM_MID, 0, 0); + weather_forecast_time_label[ i ] = lv_label_create( weater_forecast_cont , NULL); lv_label_set_text( weather_forecast_time_label[ i ], "n/a"); lv_obj_reset_style_list( weather_forecast_time_label[ i ], LV_OBJ_PART_MAIN ); @@ -196,7 +202,18 @@ void weather_forecast_sync_Task( void * pvParameters ) { lv_imgbtn_set_src( weather_forecast_icon_imgbtn[ i ], LV_BTN_STATE_CHECKED_PRESSED, resolve_owm_icon( weather_forecast[ i * 2 ].icon ) ); lv_label_set_text( weather_forecast_temperature_label[ i ], weather_forecast[ i * 2 ].temp ); - lv_obj_align( weather_forecast_temperature_label[ i ], weather_forecast_icon_imgbtn[ i ], LV_ALIGN_OUT_BOTTOM_MID, 0, 0); + + if(weather_config->showWind) + { + lv_obj_align(weather_forecast_temperature_label[i], weather_forecast_icon_imgbtn[i], LV_ALIGN_OUT_BOTTOM_MID, 0, -22); + lv_label_set_text(weather_forecast_wind_label[i], weather_forecast[i * 2].wind); + lv_obj_align(weather_forecast_wind_label[i], weather_forecast_icon_imgbtn[i], LV_ALIGN_OUT_BOTTOM_MID, 0, 0); + } + else + { + lv_obj_align(weather_forecast_temperature_label[i], weather_forecast_icon_imgbtn[i], LV_ALIGN_OUT_BOTTOM_MID, 0, 0); + lv_label_set_text(weather_forecast_wind_label[i], ""); + } localtime_r( &weather_forecast[ i * 2 ].timestamp, &info ); strftime( buf, sizeof(buf), "%H:%M", &info ); diff --git a/src/gui/widget/weather/weather_setup.cpp b/src/gui/widget/weather/weather_setup.cpp index 3d952ac..87f1f67 100644 --- a/src/gui/widget/weather/weather_setup.cpp +++ b/src/gui/widget/weather/weather_setup.cpp @@ -35,6 +35,7 @@ lv_obj_t *weather_apikey_textfield = NULL; lv_obj_t *weather_lat_textfield = NULL; lv_obj_t *weather_lon_textfield = NULL; lv_obj_t *weather_autosync_onoff = NULL; +lv_obj_t *weather_wind_onoff = NULL; lv_style_t weather_widget_setup_style; LV_IMG_DECLARE(exit_32px); @@ -42,6 +43,7 @@ LV_IMG_DECLARE(exit_32px); static void weather_apikey_event_cb( lv_obj_t * obj, lv_event_t event ); static void exit_weather_widget_setup_event_cb( lv_obj_t * obj, lv_event_t event ); static void weather_autosync_onoff_event_handler( lv_obj_t * obj, lv_event_t event ); +static void weather_wind_onoff_event_handler( lv_obj_t *obj, lv_event_t event ); void weather_widget_setup_tile_setup( lv_obj_t *tile, lv_style_t *style, lv_coord_t hres, lv_coord_t vres ) { @@ -128,20 +130,37 @@ void weather_widget_setup_tile_setup( lv_obj_t *tile, lv_style_t *style, lv_coor lv_obj_t *weather_autosync_cont = lv_obj_create( weather_widget_setup_tile, NULL ); lv_obj_set_size( weather_autosync_cont, hres , 40); lv_obj_add_style( weather_autosync_cont, LV_OBJ_PART_MAIN, style ); - lv_obj_align( weather_autosync_cont, weather_lat_cont, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0 ); + lv_obj_align( weather_autosync_cont, weather_lat_cont, LV_ALIGN_OUT_BOTTOM_LEFT, 0, -5 ); weather_autosync_onoff = lv_switch_create( weather_autosync_cont, NULL ); lv_switch_off( weather_autosync_onoff, LV_ANIM_ON ); - lv_obj_align( weather_autosync_onoff, weather_autosync_cont, LV_ALIGN_IN_RIGHT_MID, -5, 0 ); + lv_obj_align( weather_autosync_onoff, weather_autosync_cont, LV_ALIGN_IN_RIGHT_MID, -5, -5 ); lv_obj_set_event_cb( weather_autosync_onoff, weather_autosync_onoff_event_handler ); lv_obj_t *weather_autosync_label = lv_label_create( weather_autosync_cont, NULL); lv_obj_add_style( weather_autosync_label, LV_OBJ_PART_MAIN, style ); - lv_label_set_text( weather_autosync_label, "sync if wifi connected"); - lv_obj_align( weather_autosync_label, weather_autosync_cont, LV_ALIGN_IN_LEFT_MID, 5, 0 ); - - if ( weather_config->autosync ) - lv_switch_on( weather_autosync_onoff, LV_ANIM_OFF ); + lv_label_set_text( weather_autosync_label, "Sync if wifi connected"); + lv_obj_align( weather_autosync_label, weather_autosync_cont, LV_ALIGN_IN_LEFT_MID, 5, -5 ); + if (weather_config->autosync) + lv_switch_on(weather_autosync_onoff, LV_ANIM_OFF); else - lv_switch_off( weather_autosync_onoff, LV_ANIM_OFF ); + lv_switch_off(weather_autosync_onoff, LV_ANIM_OFF); + + lv_obj_t *weather_wind_cont = lv_obj_create(weather_widget_setup_tile, NULL); + lv_obj_set_size(weather_wind_cont, hres, 40); + lv_obj_add_style(weather_wind_cont, LV_OBJ_PART_MAIN, style); + lv_obj_align(weather_wind_cont, weather_lat_cont, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10); + weather_wind_onoff = lv_switch_create(weather_wind_cont, NULL); + lv_switch_off(weather_wind_onoff, LV_ANIM_ON); + lv_obj_align(weather_wind_onoff, weather_wind_cont, LV_ALIGN_IN_RIGHT_MID, -5, 10); + lv_obj_set_event_cb(weather_wind_onoff, weather_wind_onoff_event_handler); + lv_obj_t *weather_wind_label = lv_label_create(weather_wind_cont, NULL); + lv_obj_add_style(weather_wind_label, LV_OBJ_PART_MAIN, style); + lv_label_set_text(weather_wind_label, "Display wind"); + lv_obj_align(weather_wind_label, weather_wind_cont, LV_ALIGN_IN_LEFT_MID, 5, 10); + if ( weather_config->showWind ) + lv_switch_on( weather_wind_onoff, LV_ANIM_OFF ); + else + lv_switch_off( weather_wind_onoff, LV_ANIM_OFF ); + log_e("Display wind currently set to %d", weather_config->showWind); } static void weather_apikey_event_cb( lv_obj_t * obj, lv_event_t event ) { @@ -173,4 +192,17 @@ static void exit_weather_widget_setup_event_cb( lv_obj_t * obj, lv_event_t event weather_jump_to_forecast(); break; } +} + +static void weather_wind_onoff_event_handler(lv_obj_t *obj, lv_event_t event) +{ + switch (event) + { + case (LV_EVENT_CLICKED): + weather_config_t *weather_config = weather_get_config(); + weather_config->showWind = lv_switch_get_state( weather_wind_onoff); + weather_save_config(); + weather_jump_to_forecast(); + break; + } } \ No newline at end of file