Browse Source

Add Universal-Arduino-Telegram-Bot library and implement simple bot.

Thomas Buck 1 year ago
parent
commit
274197f83f
9 changed files with 428 additions and 7 deletions
  1. 8
    0
      README.md
  2. 8
    2
      include/Functionality.h
  3. 5
    0
      include/Statemachine.h
  4. 1
    0
      include/WifiStuff.h
  5. 5
    3
      include/config.h
  6. 4
    0
      platformio.ini
  7. 13
    0
      src/Functionality.cpp
  8. 78
    0
      src/Statemachine.cpp
  9. 306
    2
      src/WifiStuff.cpp

+ 8
- 0
README.md View File

@@ -19,6 +19,14 @@ Then simply run the build for all supported configurations with platformio.
19 19
 
20 20
 You can of course also use pio to flash your targets.
21 21
 
22
+There is also an optional Telegram bot integration.
23
+Register a new bot with the Telegram botfather and put the token into wifi.h as TELEGRAM_TOKEN.
24
+Compile and run the project, then send a message to the bot.
25
+Look for the chat ID in the log and put it into wifi.h in TRUSTED_IDS.
26
+
27
+    echo '#define TELEGRAM_TOKEN "XXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"' >> include/wifi.h
28
+    echo '#define TRUSTED_IDS { "1234", "5678" }' >> include/wifi.h
29
+
22 30
 ## Hardware
23 31
 
24 32
 In general, the project consists of two parts, the controller and the ui.

+ 8
- 2
include/Functionality.h View File

@@ -32,6 +32,7 @@ void ui_run(void);
32 32
 #ifdef FUNCTION_CONTROL
33 33
 
34 34
 #include "Plants.h"
35
+#include "BoolField.h"
35 36
 
36 37
 void control_setup(void);
37 38
 void control_begin(void);
@@ -42,6 +43,13 @@ void control_act_input(int n);
42 43
 
43 44
 Plants *get_plants(void);
44 45
 
46
+bool sm_is_idle(void);
47
+
48
+#ifdef TELEGRAM_TOKEN
49
+void sm_bot_abort(void);
50
+void sm_bot_start_auto(BoolField ferts, BoolField plants);
51
+#endif // TELEGRAM_TOKEN
52
+
45 53
 #endif // FUNCTION_CONTROL
46 54
 
47 55
 // ----------------------------------------------------------------------------
@@ -51,6 +59,4 @@ void write_to_all(const char *a, const char *b,
51 59
                   const char *c, const char *d, int num_input);
52 60
 void backspace(void);
53 61
 
54
-bool sm_is_idle(void);
55
-
56 62
 #endif // _FUNCTIONALITY_H_

+ 5
- 0
include/Statemachine.h View File

@@ -123,6 +123,11 @@ public:
123 123
     
124 124
     const char *getStateName(void);
125 125
     bool isIdle(void);
126
+
127
+#ifdef TELEGRAM_TOKEN
128
+    void bot_abort(void);
129
+    void bot_start_auto(BoolField ferts, BoolField plants);
130
+#endif // TELEGRAM_TOKEN
126 131
     
127 132
 private:
128 133
     void switch_to(States s);

+ 1
- 0
include/WifiStuff.h View File

@@ -28,6 +28,7 @@ void wifi_run();
28 28
 void wifi_set_message_buffer(String a, String b, String c, String d);
29 29
 void wifi_schedule_websocket(void);
30 30
 void wifi_send_status_broadcast(void);
31
+void wifi_broadcast_state_change(const char *s);
31 32
 
32 33
 void wifi_send_websocket(String s);
33 34
 

+ 5
- 3
include/config.h View File

@@ -36,22 +36,24 @@
36 36
 #define MAX_PUMP_RUNTIME 30
37 37
 #define MAX_VALVE_RUNTIME (45 * 60)
38 38
 #define MAX_AUX_RUNTIME (5 * 60)
39
-#define KICKSTART_RUNTIME 45
39
+#define KICKSTART_RUNTIME 60
40 40
 #define OVERRUN_RUNTIME 75
41 41
 #define PURGE_FILL_RUNTIME 20
42 42
 #define FULLAUTO_MIN_PLANT_COUNT 2
43 43
 #define FULLAUTO_END_PUMP_TIME 30
44 44
 
45 45
 // Sketch version
46
-#define FIRMWARE_VERSION "0.6"
46
+#define FIRMWARE_VERSION "0.7"
47 47
 
48 48
 // all given in milliseconds
49
-#define SERVER_HANDLE_INTERVAL 10
49
+#define SERVER_HANDLE_INTERVAL 0
50 50
 #define WEBSOCKET_UPDATE_INTERVAL 500
51 51
 #define LED_BLINK_INTERVAL 500
52 52
 #define LED_INIT_BLINK_INTERVAL 500
53 53
 #define LED_CONNECT_BLINK_INTERVAL 250
54 54
 #define LED_ERROR_BLINK_INTERVAL 100
55
+#define TELEGRAM_UPDATE_INTERVAL_SLOW (10 * 1000)
56
+#define TELEGRAM_UPDATE_INTERVAL_FAST (3 * 1000)
55 57
 
56 58
 // each attempt takes LED_CONNECT_BLINK_INTERVAL ms
57 59
 #define MAX_WIFI_CONNECT_ATTEMPTS 40

+ 4
- 0
platformio.ini View File

@@ -22,6 +22,8 @@ lib_deps =
22 22
     https://github.com/rlogiacco/CircularBuffer
23 23
     https://github.com/tobiasschuerg/InfluxDB-Client-for-Arduino.git
24 24
     https://github.com/RobTillaart/PCF8574
25
+    https://github.com/bblanchon/ArduinoJson
26
+    https://github.com/witnessmenow/Universal-Arduino-Telegram-Bot
25 27
 
26 28
 [env:esp32_main]
27 29
 platform = platformio/espressif32@3.5.0
@@ -36,6 +38,8 @@ lib_deps =
36 38
     https://github.com/rlogiacco/CircularBuffer
37 39
     https://github.com/tobiasschuerg/InfluxDB-Client-for-Arduino.git
38 40
     https://github.com/RobTillaart/PCF8574
41
+    https://github.com/bblanchon/ArduinoJson
42
+    https://github.com/witnessmenow/Universal-Arduino-Telegram-Bot
39 43
 
40 44
 [env:arduino_ui]
41 45
 platform = atmelavr

+ 13
- 0
src/Functionality.cpp View File

@@ -19,6 +19,7 @@
19 19
 
20 20
 #include <Arduino.h>
21 21
 
22
+#include "wifi.h"
22 23
 #include "config.h"
23 24
 #include "config_pins.h"
24 25
 #include "DebugLog.h"
@@ -75,6 +76,18 @@ bool sm_is_idle(void) {
75 76
     return sm.isIdle();
76 77
 }
77 78
 
79
+#ifdef TELEGRAM_TOKEN
80
+
81
+void sm_bot_abort(void) {
82
+    sm.bot_abort();
83
+}
84
+
85
+void sm_bot_start_auto(BoolField ferts, BoolField plants) {
86
+    sm.bot_start_auto(ferts, plants);
87
+}
88
+
89
+#endif // TELEGRAM_TOKEN
90
+
78 91
 #endif // FUNCTION_CONTROL
79 92
 
80 93
 // ----------------------------------------------------------------------------

+ 78
- 0
src/Statemachine.cpp View File

@@ -17,6 +17,7 @@
17 17
  * along with Giess-o-mat.  If not, see <https://www.gnu.org/licenses/>.
18 18
  */
19 19
 
20
+#include "wifi.h"
20 21
 #include "Plants.h"
21 22
 #include "DebugLog.h"
22 23
 #include "WifiStuff.h"
@@ -172,6 +173,79 @@ void Statemachine::begin(void) {
172 173
     switch_to(init);
173 174
 }
174 175
 
176
+#ifdef TELEGRAM_TOKEN
177
+
178
+void Statemachine::bot_abort(void) {
179
+    plants.abort();
180
+    stop_time = millis();
181
+    switch_to(auto_done);
182
+}
183
+
184
+void Statemachine::bot_start_auto(BoolField _ferts, BoolField _plants) {
185
+    selected_ferts = _ferts;
186
+    selected_plants = _plants;
187
+
188
+    // check if we need to run fertilizers
189
+    if (selected_ferts.countSet() > 0) {
190
+        // stirr before pumping fertilizers
191
+        for (int i = 0; i < STIRRER_COUNT; i++) {
192
+            plants.startAux(i);
193
+        }
194
+        selected_id = 1;
195
+        selected_time = AUTO_STIRR_RUNTIME;
196
+        start_time = millis();
197
+        switch_to(fullauto_stirr_run);
198
+    } else {
199
+        // immediately continue with filling tank
200
+        auto wl = plants.getWaterlevel();
201
+        if ((wl != Plants::full) && (wl != Plants::invalid)) {
202
+            // if the waterlevel is currently empty, we
203
+            // set a flag to record the time to fill
204
+            filling_started_empty = (wl == Plants::empty);
205
+
206
+            plants.openWaterInlet();
207
+            selected_id = plants.countPlants() + 1;
208
+            selected_time = MAX_TANK_FILL_TIME;
209
+            start_time = millis();
210
+            switch_to(fullauto_tank_run);
211
+        } else if (wl == Plants::full) {
212
+            // check if kickstart is required for this
213
+            bool need_kickstart = false;
214
+            for (int i = 0; i < plants.countPlants(); i++) {
215
+                if (selected_plants.isSet(i)) {
216
+                    if (plants.getKickstart()->getPinNumber(i) >= 0) {
217
+                        need_kickstart = true;
218
+                    }
219
+                }
220
+            }
221
+
222
+            // start kickstart/valve as needed
223
+            for (int i = 0; i < plants.countPlants(); i++) {
224
+                if (selected_plants.isSet(i)) {
225
+                    plants.startPlant(i, need_kickstart);
226
+                }
227
+            }
228
+
229
+            // for recording the flowrate
230
+            watering_started_full = (wl == Plants::full);
231
+
232
+            selected_time = MAX_AUTO_PLANT_RUNTIME;
233
+            start_time = millis();
234
+            if (need_kickstart) {
235
+                switch_to(fullauto_kickstart_run);
236
+            } else {
237
+                switch_to(fullauto_plant_run);
238
+            }
239
+        } else if (wl == Plants::invalid) {
240
+            error_condition = F("Invalid sensor state");
241
+            state = auto_mode_a;
242
+            switch_to(error);
243
+        }
244
+    }
245
+}
246
+
247
+#endif // TELEGRAM_TOKEN
248
+
175 249
 void Statemachine::input(int n) {
176 250
     if (state == init) {
177 251
 #if (LOCK_COUNT > 0) && defined(DOOR_LOCK_PIN)
@@ -1729,6 +1803,10 @@ void Statemachine::switch_to(States s) {
1729 1803
         debug.println(state_names[state]);
1730 1804
 
1731 1805
         menu_entered_digits = "";
1806
+
1807
+#ifdef PLATFORM_ESP
1808
+        wifi_broadcast_state_change(state_names[state]);
1809
+#endif
1732 1810
     }
1733 1811
     
1734 1812
     if (s == init) {

+ 306
- 2
src/WifiStuff.cpp View File

@@ -43,8 +43,27 @@
43 43
 #include "Functionality.h"
44 44
 #include "SimpleUpdater.h"
45 45
 #include "DebugLog.h"
46
+#include "BoolField.h"
46 47
 #include "WifiStuff.h"
47 48
 
49
+#ifdef TELEGRAM_TOKEN
50
+
51
+#include <WiFiClientSecure.h>
52
+#include <UniversalTelegramBot.h>
53
+
54
+//#define TELEGRAM_LOG_TIMINGS
55
+
56
+#if defined(ARDUINO_ARCH_ESP8266)
57
+X509List cert(TELEGRAM_CERTIFICATE_ROOT);
58
+#endif
59
+
60
+WiFiClientSecure secured_client;
61
+UniversalTelegramBot bot(TELEGRAM_TOKEN, secured_client);
62
+unsigned long last_telegram_time = 0;
63
+String trusted_chat_ids[] = TRUSTED_IDS;
64
+
65
+#endif // TELEGRAM_TOKEN
66
+
48 67
 UPDATE_WEB_SERVER server(80);
49 68
 WebSocketsServer socket = WebSocketsServer(81);
50 69
 SimpleUpdater updater;
@@ -100,6 +119,239 @@ void handleGpioTest() {
100 119
 
101 120
 #endif // ENABLE_GPIO_TEST
102 121
 
122
+void wifi_broadcast_state_change(const char *s) {
123
+#ifdef TELEGRAM_TOKEN
124
+    for (int n = 0; n < (sizeof(trusted_chat_ids) / sizeof(trusted_chat_ids[0])); n++) {
125
+        bot.sendMessage(trusted_chat_ids[n], "New state: " + String(s), "");
126
+    }
127
+#endif // TELEGRAM_TOKEN
128
+}
129
+
130
+#ifdef TELEGRAM_TOKEN
131
+enum telegram_state {
132
+    BOT_IDLE,
133
+    BOT_ASKED_FERT,
134
+    BOT_ASKED_PLANTS,
135
+    BOT_ASKED_CONFIRM
136
+};
137
+
138
+enum telegram_state bot_state = BOT_IDLE;
139
+String bot_lock = "";
140
+BoolField bot_plants(VALVE_COUNT - 1);
141
+BoolField bot_ferts(PUMP_COUNT);
142
+
143
+unsigned long telegram_update_interval() {
144
+    if (bot_state == BOT_IDLE) {
145
+        return TELEGRAM_UPDATE_INTERVAL_SLOW;
146
+    } else {
147
+        return TELEGRAM_UPDATE_INTERVAL_FAST;
148
+    }
149
+}
150
+
151
+String telegram_help() {
152
+    String s = "Usage:\n";
153
+    s += "Send /auto and follow prompts.\n";
154
+    s += "Send /abort to cancel menus.\n";
155
+    s += "Send /none to skip menus.\n";
156
+    s += "Send /begin to confirm menus.";
157
+    return s;
158
+}
159
+
160
+void telegram_handle_message(int message_id) {
161
+    if (!sm_is_idle()) {
162
+        debug.println("Telegram: message while machine in use");
163
+
164
+        if (bot.messages[message_id].text == "/abort") {
165
+            sm_bot_abort();
166
+            bot.sendMessage(bot.messages[message_id].chat_id, "Aborted current cycle!", "");
167
+        } else {
168
+            bot.sendMessage(bot.messages[message_id].chat_id, "Machine is already in use.\nPlease try again later.", "");
169
+        }
170
+
171
+        return;
172
+    }
173
+
174
+    if ((bot_state == BOT_IDLE) && (bot_lock == "")) {
175
+        bot_lock = bot.messages[message_id].chat_id;
176
+        debug.println("Telegram: locked to " + bot_lock);
177
+    }
178
+
179
+    if (bot_lock != bot.messages[message_id].chat_id) {
180
+        debug.println("Telegram: bot locked. abort for chat " + bot.messages[message_id].chat_id);
181
+        bot.sendMessage(bot.messages[message_id].chat_id, "Bot is already in use.\nPlease try again later.", "");
182
+        return;
183
+    }
184
+
185
+    if (bot_state == BOT_IDLE) {
186
+        if (bot.messages[message_id].text == "/auto") {
187
+            String s = "Please enter fertilizer numbers.\n";
188
+            s += "Valid numbers: 1 to " + String(PUMP_COUNT) + "\n";
189
+            s += "Send /none to skip.\n";
190
+            s += "Send /abort to cancel.";
191
+            bot_ferts.clear();
192
+            bot_state = BOT_ASKED_FERT;
193
+            bot.sendMessage(bot.messages[message_id].chat_id, s, "");
194
+        } else if (bot.messages[message_id].text == "/abort") {
195
+            bot_lock = "";
196
+            bot.sendMessage(bot.messages[message_id].chat_id, "Nothing to abort.", "");
197
+        } else {
198
+            bot_lock = "";
199
+            bot.sendMessage(bot.messages[message_id].chat_id, telegram_help(), "");
200
+        }
201
+    } else if (bot_state == BOT_ASKED_FERT) {
202
+        if (bot.messages[message_id].text == "/abort") {
203
+            bot_state = BOT_IDLE;
204
+            bot_lock = "";
205
+            bot.sendMessage(bot.messages[message_id].chat_id, "Aborted.", "");
206
+            return;
207
+        } else if (bot.messages[message_id].text != "/none") {
208
+            String buff;
209
+            for (int i = 0; i < bot.messages[message_id].text.length() + 1; i++) {
210
+                if ((i == bot.messages[message_id].text.length()) || (bot.messages[message_id].text[i] == ' ')) {
211
+                    if (buff.length() > 0) {
212
+                        int n = buff.toInt() - 1;
213
+                        buff = "";
214
+                        bot_ferts.set(n);
215
+                    }
216
+                } else if ((bot.messages[message_id].text[i] >= '0') && (bot.messages[message_id].text[i] <= '9')) {
217
+                    buff += bot.messages[message_id].text[i];
218
+                } else {
219
+                    bot_state = BOT_IDLE;
220
+                    bot_lock = "";
221
+                    bot.sendMessage(bot.messages[message_id].chat_id, "Invalid input.\nAborted.", "");
222
+                    return;
223
+                }
224
+            }
225
+        }
226
+
227
+        String s = "Please enter plant numbers.\n";
228
+        s += "Valid numbers: 1 to " + String(VALVE_COUNT - 1) + "\n";
229
+        s += "Send /abort to cancel.";
230
+        bot_plants.clear();
231
+        bot_state = BOT_ASKED_PLANTS;
232
+        bot.sendMessage(bot.messages[message_id].chat_id, s, "");
233
+    } else if (bot_state == BOT_ASKED_PLANTS) {
234
+        if (bot.messages[message_id].text == "/abort") {
235
+            bot_state = BOT_IDLE;
236
+            bot_lock = "";
237
+            bot.sendMessage(bot.messages[message_id].chat_id, "Aborted.", "");
238
+            return;
239
+        }
240
+
241
+        String buff;
242
+        for (int i = 0; i < bot.messages[message_id].text.length() + 1; i++) {
243
+            if ((i == bot.messages[message_id].text.length()) || (bot.messages[message_id].text[i] == ' ')) {
244
+                if (buff.length() > 0) {
245
+                    int n = buff.toInt() - 1;
246
+                    buff = "";
247
+                    bot_plants.set(n);
248
+                }
249
+            } else if ((bot.messages[message_id].text[i] >= '0') && (bot.messages[message_id].text[i] <= '9')) {
250
+                buff += bot.messages[message_id].text[i];
251
+            } else {
252
+                bot_state = BOT_IDLE;
253
+                bot_lock = "";
254
+                bot.sendMessage(bot.messages[message_id].chat_id, "Invalid input.\nAborted.", "");
255
+                return;
256
+            }
257
+        }
258
+
259
+        if (bot_plants.countSet() <= 0) {
260
+            bot_state = BOT_IDLE;
261
+            bot_lock = "";
262
+            bot.sendMessage(bot.messages[message_id].chat_id, "No plants selected.\nAborted.", "");
263
+            return;
264
+        }
265
+
266
+#ifdef FULLAUTO_MIN_PLANT_COUNT
267
+        if (bot_plants.countSet() < FULLAUTO_MIN_PLANT_COUNT) {
268
+            bot_state = BOT_IDLE;
269
+            bot_lock = "";
270
+            bot.sendMessage(bot.messages[message_id].chat_id, "Select at least " + String(FULLAUTO_MIN_PLANT_COUNT) + " plants.\nAborted.", "");
271
+            return;
272
+        }
273
+#endif
274
+
275
+        String s = "Input accepted.\nFertilizers:";
276
+        for (int i = 0; i < PUMP_COUNT; i++) {
277
+            if (bot_ferts.isSet(i)) {
278
+                s += " " + String(i + 1);
279
+            }
280
+        }
281
+        s += "\nPlants:";
282
+        for (int i = 0; i < (VALVE_COUNT - 1); i++) {
283
+            if (bot_plants.isSet(i)) {
284
+                s += " " + String(i + 1);
285
+            }
286
+        }
287
+        s += "\nOk? Send /begin to start or /abort to cancel.";
288
+        bot_state = BOT_ASKED_CONFIRM;
289
+        bot.sendMessage(bot.messages[message_id].chat_id, s, "");
290
+    } else if (bot_state == BOT_ASKED_CONFIRM) {
291
+        if (bot.messages[message_id].text == "/abort") {
292
+            bot_state = BOT_IDLE;
293
+            bot_lock = "";
294
+            bot.sendMessage(bot.messages[message_id].chat_id, "Aborted.", "");
295
+        } else if (bot.messages[message_id].text == "/begin") {
296
+            bot_state = BOT_IDLE;
297
+            bot_lock = "";
298
+            bot.sendMessage(bot.messages[message_id].chat_id, "Auto watering cycle started.", "");
299
+            sm_bot_start_auto(bot_ferts, bot_plants);
300
+        } else {
301
+            bot_state = BOT_IDLE;
302
+            bot_lock = "";
303
+            bot.sendMessage(bot.messages[message_id].chat_id, "Unknown message.\nAborted.", "");
304
+        }
305
+    } else {
306
+        debug.println("Telegram: invalid state");
307
+        bot_state = BOT_IDLE;
308
+        bot_lock = "";
309
+        bot.sendMessage(bot.messages[message_id].chat_id, "Internal error.\nPlease try again.", "");
310
+    }
311
+}
312
+
313
+void telegram_handler(int message_id) {
314
+    debug.println("Telegram: rx " + bot.messages[message_id].chat_id + " \"" + bot.messages[message_id].text + "\"");
315
+
316
+    bool found = false;
317
+    for (int n = 0; n < (sizeof(trusted_chat_ids) / sizeof(trusted_chat_ids[0])); n++) {
318
+        if (trusted_chat_ids[n] == bot.messages[message_id].chat_id) {
319
+            found = true;
320
+            break;
321
+        }
322
+    }
323
+    if (!found) {
324
+        bot.sendMessage(bot.messages[message_id].chat_id, "Sorry, not authorized!", "");
325
+        return;
326
+    }
327
+
328
+    telegram_handle_message(message_id);
329
+}
330
+
331
+void telegram_poll() {
332
+#ifdef TELEGRAM_LOG_TIMINGS
333
+    unsigned long start = millis();
334
+#endif // TELEGRAM_LOG_TIMINGS
335
+
336
+    while (int count = bot.getUpdates(bot.last_message_received + 1)) {
337
+        for (int i = 0; i < count; i++) {
338
+            telegram_handler(i);
339
+        }
340
+    }
341
+
342
+#ifdef TELEGRAM_LOG_TIMINGS
343
+    unsigned long end = millis();
344
+    debug.println("Telegram: took " + String(end - start) + "ms");
345
+#endif // TELEGRAM_LOG_TIMINGS
346
+}
347
+
348
+void telegram_hello() {
349
+    for (int n = 0; n < (sizeof(trusted_chat_ids) / sizeof(trusted_chat_ids[0])); n++) {
350
+        bot.sendMessage(trusted_chat_ids[n], "Giess-o-mat v" FIRMWARE_VERSION " initialized.\nSend /auto to begin.", "");
351
+    }
352
+}
353
+#endif // TELEGRAM_TOKEN
354
+
103 355
 bool wifi_write_database(int duration, const char *type, int id) {
104 356
     bool success = false;
105 357
 
@@ -610,6 +862,18 @@ void handleRoot() {
610 862
 #endif
611 863
 
612 864
     message += F("<p>\n");
865
+#ifdef TELEGRAM_TOKEN
866
+    message += F("Telegram: ");
867
+    message += TELEGRAM_UPDATE_INTERVAL_SLOW;
868
+    message += F("ms / ");
869
+    message += TELEGRAM_UPDATE_INTERVAL_FAST;
870
+    message += F("ms\n");
871
+#else
872
+    message += F("Telegram bot not enabled!\n");
873
+#endif
874
+    message += F("</p>\n");
875
+
876
+    message += F("<p>\n");
613 877
 #ifdef ENABLE_INFLUXDB_LOGGING
614 878
     message += F("InfluxDB: ");
615 879
     message += INFLUXDB_DATABASE;
@@ -735,6 +999,7 @@ void handleRoot() {
735 999
 
736 1000
 void webSocketEvent(uint8_t num, WStype_t type, uint8_t *payload, size_t length) {
737 1001
     if ((type != WStype_TEXT) || (length != 1)) {
1002
+        debug.println("Websocket: invalid type=" + String(type) + " len=" + String(length) + " data=" + String((char *)payload));
738 1003
         return;
739 1004
     }
740 1005
     
@@ -764,6 +1029,10 @@ void wifi_setup() {
764 1029
     debug.print("WiFi: connecting");
765 1030
     WiFi.begin(WIFI_SSID, WIFI_PW);
766 1031
 
1032
+#ifdef TELEGRAM_TOKEN
1033
+    secured_client.setTrustAnchors(&cert);
1034
+#endif // TELEGRAM_TOKEN
1035
+
767 1036
     while (((ws = WiFi.status()) != WL_CONNECTED) && (connect_attempts < MAX_WIFI_CONNECT_ATTEMPTS)) {
768 1037
         connect_attempts++;
769 1038
         debug.print(String(" ") + String(ws));
@@ -797,6 +1066,10 @@ void wifi_setup() {
797 1066
     WiFi.mode(WIFI_STA);
798 1067
     WiFi.begin(WIFI_SSID, WIFI_PW);
799 1068
 
1069
+#ifdef TELEGRAM_TOKEN
1070
+    secured_client.setCACert(TELEGRAM_CERTIFICATE_ROOT);
1071
+#endif // TELEGRAM_TOKEN
1072
+
800 1073
     while (((ws = WiFi.status()) != WL_CONNECTED) && (connect_attempts < MAX_WIFI_CONNECT_ATTEMPTS)) {
801 1074
         connect_attempts++;
802 1075
         debug.print(String(" ") + String(ws));
@@ -838,10 +1111,34 @@ void wifi_setup() {
838 1111
 #ifdef ENABLE_GPIO_TEST
839 1112
     server.on("/gpiotest", handleGpioTest);
840 1113
 #endif // ENABLE_GPIO_TEST
841
-    
1114
+
1115
+#ifdef TELEGRAM_TOKEN
1116
+    debug.print("WiFi: getting NTP time");
1117
+    configTime(0, 0, "pool.ntp.org");
1118
+    time_t now = time(nullptr);
1119
+    while (now < 24 * 60 * 60) {
1120
+        debug.print(".");
1121
+        delay(100);
1122
+        now = time(nullptr);
1123
+    }
1124
+    debug.println(" done!");
1125
+    debug.println("WiFi: time is " + String(now));
1126
+
1127
+    debug.println("WiFi: initializing Telegram");
1128
+    const String commands = F("["
1129
+        "{\"command\":\"auto\", \"description\":\"Start automatic watering cycle\"},"
1130
+        "{\"command\":\"confirm\", \"description\":\"Proceed with any menu inputs\"},"
1131
+        "{\"command\":\"none\", \"description\":\"Proceed without menu input\"},"
1132
+        "{\"command\":\"abort\", \"description\":\"Cancel any menu inputs\"}"
1133
+    "]");
1134
+    bot.setMyCommands(commands);
1135
+    telegram_hello();
1136
+#endif // TELEGRAM_TOKEN
1137
+
842 1138
     server.begin();
843 1139
     MDNS.addService("http", "tcp", 80);
844
-    
1140
+    MDNS.addService("http", "tcp", 81);
1141
+
845 1142
     socket.begin();
846 1143
     socket.onEvent(webSocketEvent);
847 1144
     
@@ -880,6 +1177,13 @@ void wifi_run() {
880 1177
         runGpioTest(gpioTestState);
881 1178
     }
882 1179
 #endif // ENABLE_GPIO_TEST
1180
+
1181
+#ifdef TELEGRAM_TOKEN
1182
+    if ((millis() - last_telegram_time) >= telegram_update_interval()) {
1183
+        telegram_poll();
1184
+        last_telegram_time = millis();
1185
+    }
1186
+#endif // TELEGRAM_TOKEN
883 1187
 }
884 1188
 
885 1189
 #endif // PLATFORM_ESP

Loading…
Cancel
Save