Browse Source

basic menu ui with buttons working

Thomas Buck 1 month ago
parent
commit
bd17412c6d
3 changed files with 124 additions and 38 deletions
  1. 13
    0
      include/ui.h
  2. 39
    9
      src/mqtt.cpp
  3. 72
    29
      src/ui.cpp

+ 13
- 0
include/ui.h View File

@@ -14,6 +14,19 @@
14 14
 #ifndef __UI_H__
15 15
 #define __UI_H__
16 16
 
17
+struct ui_status {
18
+    bool light_corner;
19
+    bool light_workspace;
20
+    bool light_kitchen;
21
+    bool sound_amplifier;
22
+    bool light_bench;
23
+    bool light_pc;
24
+    bool light_amp;
25
+    bool light_box;
26
+};
27
+
28
+extern struct ui_status ui_status;
29
+
17 30
 void ui_init(void);
18 31
 void ui_draw_menu(void);
19 32
 void ui_run(void);

+ 39
- 9
src/mqtt.cpp View File

@@ -18,6 +18,7 @@
18 18
 #include "sensors.h"
19 19
 #include "relais.h"
20 20
 #include "influx.h"
21
+#include "ui.h"
21 22
 #include "mqtt.h"
22 23
 
23 24
 #ifdef ENABLE_MQTT
@@ -103,8 +104,18 @@ static void mqttCallback(char* topic, byte* payload, unsigned int length) {
103 104
     debug.print(ps);
104 105
     debug.println(F("\""));
105 106
 
106
-#ifdef FEATURE_RELAIS
107
+#if defined(FEATURE_RELAIS) || defined(FEATURE_UI)
107 108
     int state = 0;
109
+    if (ps.indexOf("on") != -1) {
110
+        state = 1;
111
+    } else if (ps.indexOf("off") != -1) {
112
+        state = 0;
113
+    } else {
114
+        return;
115
+    }
116
+#endif
117
+
118
+#ifdef FEATURE_RELAIS
108 119
     int id = -1;
109 120
 
110 121
     String our_topic(SENSOR_LOCATION);
@@ -130,14 +141,6 @@ static void mqttCallback(char* topic, byte* payload, unsigned int length) {
130 141
         return;
131 142
     }
132 143
 
133
-    if (ps.indexOf("on") != -1) {
134
-        state = 1;
135
-    } else if (ps.indexOf("off") != -1) {
136
-        state = 0;
137
-    } else {
138
-        return;
139
-    }
140
-
141 144
     if ((id >= 0) && (id < relais_count())) {
142 145
         debug.print(F("Turning "));
143 146
         debug.print(state ? "on" : "off");
@@ -149,6 +152,27 @@ static void mqttCallback(char* topic, byte* payload, unsigned int length) {
149 152
         writeDatabase();
150 153
     }
151 154
 #endif // FEATURE_RELAIS
155
+
156
+#ifdef FEATURE_UI
157
+    // store new topic values for display
158
+    if (ts == "livingroom/light_kitchen") {
159
+        ui_status.light_kitchen = state ? true : false;
160
+    } else if (ts == "livingroom/light_pc") {
161
+        ui_status.light_pc = state ? true : false;
162
+    } else if (ts == "livingroom/light_bench") {
163
+        ui_status.light_bench = state ? true : false;
164
+    } else if (ts == "livingroom/light_amp") {
165
+        ui_status.light_amp = state ? true : false;
166
+    } else if (ts == "livingroom/light_box") {
167
+        ui_status.light_box = state ? true : false;
168
+    } else if (ts == "livingroom/TODO") {
169
+        ui_status.light_corner = state ? true: false;
170
+    } else if (ts == "livingroom/TODO") {
171
+        ui_status.light_workspace = state ? true : false;
172
+    } else if (ts == "livingroom/TODO") {
173
+        ui_status.sound_amplifier = state ? true : false;
174
+    }
175
+#endif // FEATURE_UI
152 176
 }
153 177
 
154 178
 static void mqttReconnect() {
@@ -172,7 +196,13 @@ static void mqttReconnect() {
172 196
 #endif // FEATURE_RELAIS
173 197
 
174 198
 #ifdef FEATURE_UI
199
+        // TODO need to list all topics we're interested in?
175 200
         mqtt.subscribe("livingroom/light_kitchen");
201
+        mqtt.subscribe("livingroom/light_pc");
202
+        mqtt.subscribe("livingroom/light_bench");
203
+        mqtt.subscribe("livingroom/light_amp");
204
+        mqtt.subscribe("livingroom/light_box");
205
+        // TODO corner lights, workspace, amp
176 206
 #endif // FEATURE_UI
177 207
     }
178 208
 }

+ 72
- 29
src/ui.cpp View File

@@ -42,11 +42,31 @@
42 42
 #define TOUCH_TOP 230
43 43
 #define TOUCH_BOTTOM 3800
44 44
 
45
+#define BTN_W 120
46
+#define BTN_H 60
47
+#define BTN_GAP 20
48
+
49
+#define BTNS_OFF_X ((LCD_WIDTH - (2 * BTN_W) - (1 * BTN_GAP)) / 2)
50
+#define BTNS_OFF_Y ((LCD_HEIGHT - (3 * BTN_H) - (2 * BTN_GAP)) / 2)
51
+
52
+#define INVERT_BOOL(x) (x) = !(x);
53
+
45 54
 static SPIClass mySpi = SPIClass(HSPI);
46 55
 static XPT2046_Touchscreen ts(XPT2046_CS, XPT2046_IRQ);
47
-
48 56
 static TFT_eSPI tft = TFT_eSPI();
49 57
 
58
+struct ui_status ui_status = {0};
59
+
60
+enum ui_states {
61
+    UI_INIT = 0,
62
+    UI_LIVINGROOM1,
63
+    UI_LIVINGROOM2,
64
+
65
+    UI_NUM_STATES
66
+};
67
+
68
+static enum ui_states ui_state = UI_INIT;
69
+
50 70
 static TS_Point touchToScreen(TS_Point p) {
51 71
     p.x = map(p.x, TOUCH_LEFT, TOUCH_RIGHT, 0, LCD_WIDTH);
52 72
     p.y = map(p.y, TOUCH_TOP, TOUCH_BOTTOM, 0, LCD_HEIGHT);
@@ -58,30 +78,29 @@ static void ledcAnalogWrite(uint8_t channel, uint32_t value, uint32_t valueMax =
58 78
     ledcWrite(channel, duty);
59 79
 }
60 80
 
61
-#define BTN_W 120
62
-#define BTN_H 60
63
-#define BTN_GAP 20
64
-
65
-#define BTNS_OFF_X ((LCD_WIDTH - (2 * BTN_W) - (1 * BTN_GAP)) / 2)
66
-#define BTNS_OFF_Y ((LCD_HEIGHT - (3 * BTN_H) - (2 * BTN_GAP)) / 2)
67
-
68
-static void draw_button(const char *name, uint32_t x, uint32_t y, bool state) {
69
-    tft.fillRect(x - BTN_W / 2, y - BTN_H / 2, BTN_W, BTN_H, state ? TFT_GREEN : TFT_RED);
81
+static void draw_button(const char *name, uint32_t x, uint32_t y, uint32_t color) {
82
+    tft.fillRect(x - BTN_W / 2, y - BTN_H / 2, BTN_W, BTN_H, color);
70 83
 
71 84
     tft.setTextDatum(MC_DATUM); // middle center
72 85
     tft.drawString(name, x, y, 2);
73 86
 }
74 87
 
75
-static bool lc, lw, lk, sa, lt, lp;
88
+static void draw_livingroom1(void) {
89
+    draw_button("Lights Corner", BTNS_OFF_X + BTN_W / 2, BTNS_OFF_Y + BTN_H / 2, ui_status.light_corner ? TFT_GREEN : TFT_RED);
90
+    draw_button("Lights Workspace", BTNS_OFF_X + BTN_W / 2, BTNS_OFF_Y + BTN_H / 2 + BTN_H + BTN_GAP, ui_status.light_workspace ? TFT_GREEN : TFT_RED);
91
+    draw_button("Lights Kitchen", BTNS_OFF_X + BTN_W / 2, BTNS_OFF_Y + BTN_H / 2 + (BTN_H + BTN_GAP) * 2, ui_status.light_kitchen ? TFT_GREEN : TFT_RED);
76 92
 
77
-static void draw_livingroom(void) {
78
-    draw_button("Lights Corner", BTNS_OFF_X + BTN_W / 2, BTNS_OFF_Y + BTN_H / 2, lc);
79
-    draw_button("Lights Workspace", BTNS_OFF_X + BTN_W / 2, BTNS_OFF_Y + BTN_H / 2 + BTN_H + BTN_GAP, lw);
80
-    draw_button("Lights Kitchen", BTNS_OFF_X + BTN_W / 2, BTNS_OFF_Y + BTN_H / 2 + (BTN_H + BTN_GAP) * 2, lk);
93
+    draw_button("Sound Amp.", BTNS_OFF_X + BTN_W / 2 + BTN_W + BTN_GAP, BTNS_OFF_Y + BTN_H / 2, ui_status.sound_amplifier ? TFT_GREEN : TFT_RED);
94
+    draw_button("All Lights Off", BTNS_OFF_X + BTN_W / 2 + BTN_W + BTN_GAP, BTNS_OFF_Y + BTN_H / 2 + BTN_H + BTN_GAP, TFT_RED);
95
+}
96
+
97
+static void draw_livingroom2(void) {
98
+    draw_button("Lights PC", BTNS_OFF_X + BTN_W / 2, BTNS_OFF_Y + BTN_H / 2, ui_status.light_corner ? TFT_GREEN : TFT_RED);
99
+    draw_button("Lights Bench", BTNS_OFF_X + BTN_W / 2, BTNS_OFF_Y + BTN_H / 2 + BTN_H + BTN_GAP, ui_status.light_workspace ? TFT_GREEN : TFT_RED);
100
+    //draw_button("Lights Amp.", BTNS_OFF_X + BTN_W / 2, BTNS_OFF_Y + BTN_H / 2 + (BTN_H + BTN_GAP) * 2, ui_status.light_kitchen ? TFT_GREEN : TFT_RED);
81 101
 
82
-    draw_button("Sound Amp.", BTNS_OFF_X + BTN_W / 2 + BTN_W + BTN_GAP, BTNS_OFF_Y + BTN_H / 2, sa);
83
-    draw_button("Lights TV", BTNS_OFF_X + BTN_W / 2 + BTN_W + BTN_GAP, BTNS_OFF_Y + BTN_H / 2 + BTN_H + BTN_GAP, lt);
84
-    draw_button("Lights PC", BTNS_OFF_X + BTN_W / 2 + BTN_W + BTN_GAP, BTNS_OFF_Y + BTN_H / 2 + (BTN_H + BTN_GAP) * 2, lp);
102
+    draw_button("Lights Amp.", BTNS_OFF_X + BTN_W / 2 + BTN_W + BTN_GAP, BTNS_OFF_Y + BTN_H / 2, ui_status.sound_amplifier ? TFT_GREEN : TFT_RED);
103
+    draw_button("Lights Box", BTNS_OFF_X + BTN_W / 2 + BTN_W + BTN_GAP, BTNS_OFF_Y + BTN_H / 2 + BTN_H + BTN_GAP, TFT_RED); // TODO both
85 104
 }
86 105
 
87 106
 void ui_init(void) {
@@ -101,11 +120,30 @@ void ui_init(void) {
101 120
     tft.setTextDatum(MC_DATUM); // middle center
102 121
     tft.drawString("Initializing ESP-ENV", LCD_WIDTH / 2, LCD_HEIGHT / 2 - 16, 2);
103 122
     tft.drawString("xythobuz.de", LCD_WIDTH / 2, LCD_HEIGHT / 2 + 16, 2);
123
+
124
+    ui_state = UI_INIT;
104 125
 }
105 126
 
106 127
 void ui_draw_menu(void) {
107
-    tft.fillScreen(TFT_BLACK);
108
-    draw_livingroom();
128
+    switch (ui_state) {
129
+        case UI_INIT:
130
+            tft.fillScreen(TFT_BLACK);
131
+            ui_state = UI_LIVINGROOM1;
132
+            // fall-through
133
+
134
+        case UI_LIVINGROOM1:
135
+            draw_livingroom1();
136
+            break;
137
+
138
+        case UI_LIVINGROOM2:
139
+            draw_livingroom2();
140
+            break;
141
+
142
+        default:
143
+            ui_state = UI_INIT;
144
+    }
145
+
146
+    draw_button("Next...", BTNS_OFF_X + BTN_W / 2 + BTN_W + BTN_GAP, BTNS_OFF_Y + BTN_H / 2 + (BTN_H + BTN_GAP) * 2, TFT_MAGENTA);
109 147
 }
110 148
 
111 149
 void ui_run(void) {
@@ -113,22 +151,27 @@ void ui_run(void) {
113 151
         TS_Point p = touchToScreen(ts.getPoint());
114 152
 
115 153
         if ((p.x >= BTNS_OFF_X) && (p.x <= BTNS_OFF_X + BTN_W) && (p.y >= BTNS_OFF_Y) && (p.y <= BTNS_OFF_Y + BTN_H)) {
116
-            lc = !lc;
154
+            INVERT_BOOL(ui_status.light_corner);
117 155
         } else if ((p.x >= BTNS_OFF_X) && (p.x <= BTNS_OFF_X + BTN_W) && (p.y >= (BTNS_OFF_Y + BTN_H + BTN_GAP)) && (p.y <= (BTNS_OFF_Y + BTN_H + BTN_GAP + BTN_H))) {
118
-            lw = !lw;
156
+            INVERT_BOOL(ui_status.light_workspace);
119 157
         } else if ((p.x >= BTNS_OFF_X) && (p.x <= BTNS_OFF_X + BTN_W) && (p.y >= (BTNS_OFF_Y + BTN_H * 2 + BTN_GAP * 2)) && (p.y <= (BTNS_OFF_Y + BTN_H * 2 + BTN_GAP * 2 + BTN_H))) {
120
-            lk = !lk;
158
+            INVERT_BOOL(ui_status.light_kitchen);
121 159
         } else if ((p.x >= BTNS_OFF_X + BTN_W + BTN_GAP) && (p.x <= BTNS_OFF_X + BTN_W + BTN_GAP + BTN_W) && (p.y >= BTNS_OFF_Y) && (p.y <= BTNS_OFF_Y + BTN_H)) {
122
-            sa = !sa;
160
+            INVERT_BOOL(ui_status.sound_amplifier);
123 161
         } else if ((p.x >= BTNS_OFF_X + BTN_W + BTN_GAP) && (p.x <= BTNS_OFF_X + BTN_W + BTN_GAP + BTN_W) && (p.y >= (BTNS_OFF_Y + BTN_H + BTN_GAP)) && (p.y <= (BTNS_OFF_Y + BTN_H + BTN_GAP + BTN_H))) {
124
-            lt = !lt;
162
+            // TODO should act on both TV lights (box and amp)
125 163
         } else if ((p.x >= BTNS_OFF_X + BTN_W + BTN_GAP) && (p.x <= BTNS_OFF_X + BTN_W + BTN_GAP + BTN_W) && (p.y >= (BTNS_OFF_Y + BTN_H * 2 + BTN_GAP * 2)) && (p.y <= (BTNS_OFF_Y + BTN_H * 2 + BTN_GAP * 2 + BTN_H))) {
126
-            lp = !lp;
164
+            // switch to next page
165
+            ui_state = (enum ui_states)((ui_state + 1) % UI_NUM_STATES);
166
+            if (ui_state == UI_INIT) {
167
+                // skip init screen
168
+                ui_state = (enum ui_states)((ui_state + 1) % UI_NUM_STATES);
169
+            }
170
+            tft.fillScreen(TFT_BLACK);
127 171
         }
128 172
 
129
-        // TODO
130
-        draw_livingroom();
131
-        delay(100);
173
+        ui_draw_menu();
174
+        delay(100); // TODO
132 175
     }
133 176
 }
134 177
 

Loading…
Cancel
Save