Attempt to create a rotary editor

Mon, 04 Nov 2019 19:35:05 +0100

author
Michiel Broek <mbroek@mbse.eu>
date
Mon, 04 Nov 2019 19:35:05 +0100
changeset 20
7c1dacafed03
parent 19
4fb9ed228a23
child 21
043ae27633f8

Attempt to create a rotary editor

main/co2meter.c file | annotate | diff | comparison | revisions
main/config.h file | annotate | diff | comparison | revisions
--- 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;
 	    	}
--- a/main/config.h	Fri Nov 01 14:23:48 2019 +0100
+++ b/main/config.h	Mon Nov 04 19:35:05 2019 +0100
@@ -90,9 +90,9 @@
     ML2_UNIT1,			///< Unit 1
     ML2_UNIT2,			///< Unit 2
     ML2_UNIT3,			///< Unit 3
-    ML2_SET_WIFI,		///< WiFi stations setup
-    ML2_SET_NETWORK,		///< Network setup
-    ML2_SET_MQTT,		///< MQTT setup
+    ML2_WIFI,			///< WiFi status
+    ML2_NETWORK,		///< Network status
+    ML2_MQTT,			///< MQTT status
     ML2_UPDATE,			///< Update
     ML2_SETUP_UNIT1,		///< Unit 1 setup
     ML2_SETUP_UNIT2,		///< Unit 2 setup
@@ -100,6 +100,7 @@
     ML2_ZERO_UNIT1,		///< Unit 1 set zero
     ML2_ZERO_UNIT2,		///< Unit 2 set zero
     ML2_ZERO_UNIT3,		///< Unit 3 set zero
+    ML2_SETUP_MQTT,		///< MQTT setup
     ML2_INACTIVE,		///< Inactive reached, cleanup
     ML2_DONE			///< All done
 } ML2;

mercurial