diff -r 4fb9ed228a23 -r 7c1dacafed03 main/co2meter.c --- a/main/co2meter.c Fri Nov 01 14:23:48 2019 +0100 +++ b/main/co2meter.c Mon Nov 04 19:35:05 2019 +0100 @@ -14,6 +14,10 @@ #define ROT_ENC_SW_GPIO (CONFIG_ROT_ENC_SW_GPIO) #define INACTIVITY 480 ///< Time in 250 mSec units. +#define EDIT_TYPE_TEXT 0 ///< Editor type is text +#define EDIT_TYPE_INT 1 ///< Editor type is integer +#define EDIT_TYPE_FLOAT 2 ///< Editor type is float + int Main_Loop1 = ML1_INIT; ///< Loop 1 init int Main_Loop2 = -1; ///< Loop 2 invalid @@ -30,6 +34,8 @@ const esp_app_desc_t *app_desc = NULL; ///< Application description u8g2_t u8g2; ///< A structure which will contain all the data for one display rotary_encoder_info_t rinfo = { 0 }; ///< Rotary encoder record +rotary_encoder_event_t event = { 0 }; +QueueHandle_t event_queue; static int PushDuration = 0; ///< Duration of the pushed button extern unit_t units[3]; ///< Pressure test units @@ -38,6 +44,7 @@ extern SemaphoreHandle_t xSemaphoreDS18B20; ///< DS18B20 lock semaphore extern ADC_State *adc_state; ///< ADC state extern SemaphoreHandle_t xSemaphoreADC; ///< ADC lock semaphore +extern WIFI_State *wifi_state; ///< WiFi state extern int count_pub; ///< Published MQTT messages in transit static xQueueHandle gpio_evt_queue = NULL; ///< Rotary pushbutton queue static int usertimer = 0; ///< User inactive timeout @@ -45,6 +52,120 @@ /** + * @brief Get a keyboard character from the rotary encoder. + * @param curkey The referenced value if the key being edited. NOTE, start at 0 for a new char?? + * @param type The edittype, all values, integer or float. + * @param x The x position on the screen. + * @param y The y position on the screen. + * @return 1 if short keypress, meaning enter key. 2 if long press, enter key and editing is ready. + */ +int getkey(int *curkey, int type, int x, int y) +{ + int key = *curkey; + int rc = 0; + + u8g2_DrawHLine(&u8g2, x, y+3, 12); + u8g2_SendBuffer(&u8g2); + + for (;;) { + if (xQueueReceive(event_queue, &event, 100 / portTICK_PERIOD_MS) == pdTRUE) { + usertimer = INACTIVITY; + if (event.state.position != 0) { + + u8g2_SetDrawColor(&u8g2, 0); + u8g2_DrawGlyph(&u8g2, x, y, key); + u8g2_SetDrawColor(&u8g2, 1); + u8g2_SendBuffer(&u8g2); + + if (event.state.position > 0) { + if (key == 126) + key = 171; + else if (key < 126) + key++; + } else if (event.state.position < 0) { + if (key == 171) + key = 126; + else if (key > 32) + key--; + } + + ESP_ERROR_CHECK(rotary_encoder_reset(&rinfo)); + u8g2_DrawGlyph(&u8g2, x, y, key); + u8g2_SendBuffer(&u8g2); + } + } else { + if (PushDuration) { + if (PushDuration > 500) + rc = 2; + else + rc = 1; + PushDuration = 0; + break; + } + } + } + u8g2_SetDrawColor(&u8g2, 0); + u8g2_DrawHLine(&u8g2, x, y+3, 12); + u8g2_SetDrawColor(&u8g2, 1); + u8g2_SendBuffer(&u8g2); + + *curkey = key; + return rc; +} + + + +/** + * @brief Editor using the rotary switch. + * @param label The label of the edit field. + * @param txt The string to edit. + * @param errmsg The error message if needed. + * @param len The maximum length for the string. + * @param type The edit type. + */ +void rotary_editer(char *label, char *txt, char *errmsg, int len, int type) +{ + char buf[65]; + int key, x, y, rc; + + u8g2_ClearBuffer(&u8g2); + u8g2_DrawHLine(&u8g2, 0, 14, 128); + u8g2_DrawHLine(&u8g2, 0, 49, 128); + u8g2_SetFont(&u8g2, u8g2_font_t0_15_tf); + sprintf(buf, "Edit %s", label); + u8g2_DrawStr(&u8g2,0,12,buf); + + if (strlen(errmsg)) { + u8g2_SetFont(&u8g2, u8g2_font_t0_12b_tf); + u8g2_DrawStr(&u8g2, 0, 61, errmsg); + } + u8g2_SetFont(&u8g2, u8g2_font_t0_12_tf); + y = 36; + u8g2_DrawStr(&u8g2, 0, y, txt); + u8g2_SendBuffer(&u8g2); + + for (;;) { + x = u8g2_GetUTF8Width(&u8g2, txt); + key = 'a'; + rc = getkey(&key, type, x, y); + if (rc == 1) { + if (key >= 32 && key <= 126 && strlen(txt) < len) { + txt[strlen(txt) + 1] = '\0'; + txt[strlen(txt)] = key; + } else if (key == 171 && strlen(txt)) { + // delete key + txt[strlen(txt) - 1] = '\0'; + } +printf("strlen %d x %d key %d\n", strlen(txt), x, key); + } else if (rc == 2) { + break; + } + } +} + + + +/** * @brief Write a menu line on the display. * @param bright Display the line with a bold or normal font. * @param x The horizontal start position of the line. @@ -206,6 +327,71 @@ +void screen_wifi() +{ + char buf[65]; + + screen_top("WiFi Status"); + snprintf(buf, 65, "SSID %s", wifi_state->STA_ssid); + u8g2_DrawStr(&u8g2, 1, 28, buf); + snprintf(buf, 65, "Online %s", wifi_state->STA_online ? "Yes":"No"); + u8g2_DrawStr(&u8g2, 1, 43, buf); + snprintf(buf, 65, "RSSI %d", wifi_state->STA_rssi); + u8g2_DrawStr(&u8g2, 1, 59, buf); + u8g2_SendBuffer(&u8g2); + u8g2_SetPowerSave(&u8g2, 0); +} + + + +void screen_wifi_setup(int sub) +{ + screen_top("WiFi Setup"); + menu_line(sub == 0, 2, 25, "Connect"); + menu_line(sub == 1, 2, 37, "New"); + menu_line(sub == 2, 2, 49, "Delete"); + menu_line(sub == 3, 2, 61, "Return"); + u8g2_SendBuffer(&u8g2); + u8g2_SetPowerSave(&u8g2, 0); +} + + + +void screen_network() +{ + screen_top("Network Status"); + menu_line(0, 1, 25, "IP %s", wifi_state->STA_ip); + menu_line(0, 1, 37, "Mask %s", wifi_state->STA_nm); + menu_line(0, 1, 49, "GW %s", wifi_state->STA_gw); + menu_line(0, 1, 61, "Name %s", config.hostname); + u8g2_SendBuffer(&u8g2); + u8g2_SetPowerSave(&u8g2, 0); +} + + + +void screen_mqtt() +{ + screen_top("MQTT Status"); + menu_line(0, 1, 25, "serv %s", config.mqtt_server); + menu_line(0, 1, 37, "port %d", config.mqtt_port); + menu_line(0, 1, 49, "user %s", config.mqtt_user); + u8g2_SendBuffer(&u8g2); + u8g2_SetPowerSave(&u8g2, 0); +} + + + +void screen_update() +{ + screen_top("Update firmware"); + menu_line(0, 1, 43, "Push to update"); + u8g2_SendBuffer(&u8g2); + u8g2_SetPowerSave(&u8g2, 0); +} + + + /** * @brief Fatal messages on the screen. * @param e1 The first line. @@ -319,6 +505,7 @@ gettimeofday(&now, NULL); int sleep_time_ms = (now.tv_sec - sleep_enter_time.tv_sec) * 1000 + (now.tv_usec - sleep_enter_time.tv_usec) / 1000; esp_err_t ret; + char txt[65]; Main_Loop1 = ML1_INIT; Main_Loop2 = -1; @@ -480,7 +667,7 @@ // Create a queue for events from the rotary encoder driver. // Tasks can read from this queue to receive up to date position information. - QueueHandle_t event_queue = rotary_encoder_create_queue(); + event_queue = rotary_encoder_create_queue(); ESP_ERROR_CHECK(rotary_encoder_set_queue(&rinfo, event_queue)); /* @@ -489,7 +676,7 @@ while (1) { ESP_LOGI(TAG, "Entered app loop"); - rotary_encoder_event_t event = { 0 }; + //event = { 0 }; int sub = 0; u8g2_SetPowerSave(&u8g2, 1); @@ -506,8 +693,11 @@ break; case ML1_CONNECT: - if (ready_WiFi()) + if (ready_WiFi()) { Main_Loop1 = ML1_MQTT_CONNECT; + if (Main_Loop2 == ML2_WIFI) + screen_wifi(); + } break; case ML1_MQTT_CONNECT: @@ -603,6 +793,8 @@ if (! ready_WiFi()) { ESP_LOGI(TAG, "Loop timer: Done"); Main_Loop1 = ML1_DONE; + if (Main_Loop2 == ML2_WIFI) + screen_wifi(); } break; @@ -636,20 +828,31 @@ screen_unit(Main_Loop2 - ML2_UNIT1); break; - case ML2_SET_WIFI: - ESP_LOGI(TAG, "Loop user: Setup WiFi"); + case ML2_WIFI: + ESP_LOGI(TAG, "Loop user: WiFi"); + screen_wifi(); + break; + + case ML2_NETWORK: + ESP_LOGI(TAG, "Loop user: Network"); + screen_network(); break; - case ML2_SET_NETWORK: - ESP_LOGI(TAG, "Loop user: Setup Network"); + case ML2_MQTT: + ESP_LOGI(TAG, "Loop user: MQTT"); + screen_mqtt(); break; - case ML2_SET_MQTT: - ESP_LOGI(TAG, "Loop user: Setup MQTT"); + case ML2_SETUP_MQTT: + ESP_LOGI(TAG, "Loop user: MQTT setup"); + sprintf(txt, "EDtXt"); + rotary_editer("MQTT demo", txt, "", 16, EDIT_TYPE_TEXT); + New_Loop2 = ML2_MQTT; break; case ML2_UPDATE: ESP_LOGI(TAG, "Loop user: Update"); + screen_update(); break; case ML2_SETUP_UNIT1: @@ -705,11 +908,11 @@ case ML2_USER: rotate_to_menu(event.state.position, ML2_UNIT1, ML2_USER); break; case ML2_UNIT1: rotate_to_menu(event.state.position, ML2_UNIT2, ML2_USER); break; case ML2_UNIT2: rotate_to_menu(event.state.position, ML2_UNIT3, ML2_UNIT1); break; - case ML2_UNIT3: rotate_to_menu(event.state.position, ML2_SET_WIFI, ML2_UNIT2); break; - case ML2_SET_WIFI: rotate_to_menu(event.state.position, ML2_SET_NETWORK, ML2_UNIT3); break; - case ML2_SET_NETWORK: rotate_to_menu(event.state.position, ML2_SET_MQTT, ML2_SET_WIFI); break; - case ML2_SET_MQTT: rotate_to_menu(event.state.position, ML2_UPDATE, ML2_SET_NETWORK); break; - case ML2_UPDATE: rotate_to_menu(event.state.position, ML2_UPDATE, ML2_SET_MQTT); break; + case ML2_UNIT3: rotate_to_menu(event.state.position, ML2_WIFI, ML2_UNIT2); break; + case ML2_WIFI: rotate_to_menu(event.state.position, ML2_NETWORK, ML2_UNIT3); break; + case ML2_NETWORK: rotate_to_menu(event.state.position, ML2_MQTT, ML2_WIFI); break; + case ML2_MQTT: rotate_to_menu(event.state.position, ML2_UPDATE, ML2_NETWORK); break; + case ML2_UPDATE: rotate_to_menu(event.state.position, ML2_UPDATE, ML2_MQTT); break; case ML2_SETUP_UNIT1: case ML2_SETUP_UNIT2: case ML2_SETUP_UNIT3: if (rotate_to_sub(event.state.position, 0, 3, &sub)) @@ -804,6 +1007,10 @@ printf("unit zero sub %d new %d idx %d\n", sub, New_Loop2, idx); break; + case ML2_MQTT: + New_Loop2 = ML2_SETUP_MQTT; + break; + default: break; }