mirror of https://github.com/arendst/Tasmota.git
Add initial support for Telegram
Add initial support for Telegram bot (#8619)
This commit is contained in:
parent
33d5f3e7e7
commit
4c5b2f37fd
|
@ -52,7 +52,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
### Version 8.3.1.2
|
### Version 8.3.1.3
|
||||||
|
|
||||||
- Change IRremoteESP8266 library updated to v2.7.7
|
- Change IRremoteESP8266 library updated to v2.7.7
|
||||||
- Change Adafruit_SGP30 library from v1.0.3 to v1.2.0 (#8519)
|
- Change Adafruit_SGP30 library from v1.0.3 to v1.2.0 (#8519)
|
||||||
|
@ -76,3 +76,4 @@ The following binary downloads have been compiled with ESP8266/Arduino library c
|
||||||
- Add support for up to two BH1750 sensors controlled by commands ``BH1750Resolution`` and ``BH1750MTime`` (#8139)
|
- Add support for up to two BH1750 sensors controlled by commands ``BH1750Resolution`` and ``BH1750MTime`` (#8139)
|
||||||
- Add support for up to eight MCP9808 temperature sensors by device111 (#8594)
|
- Add support for up to eight MCP9808 temperature sensors by device111 (#8594)
|
||||||
- Add support for BL0940 energy monitor as used in Blitzwolf BW-SHP10 (#8175)
|
- Add support for BL0940 energy monitor as used in Blitzwolf BW-SHP10 (#8175)
|
||||||
|
- Add initial support for Telegram bot (#8619)
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
## Unreleased (development)
|
## Unreleased (development)
|
||||||
|
|
||||||
|
### 8.3.1.3 20200611
|
||||||
|
|
||||||
|
- Add initial support for Telegram bot (#8619)
|
||||||
|
|
||||||
### 8.3.1.2 20200522
|
### 8.3.1.2 20200522
|
||||||
|
|
||||||
- Change Energy JSON Total field from ``"Total":[33.736,11.717,16.978]`` to ``"Total":33.736,"TotalTariff":[11.717,16.978]``
|
- Change Energy JSON Total field from ``"Total":[33.736,11.717,16.978]`` to ``"Total":33.736,"TotalTariff":[11.717,16.978]``
|
||||||
|
|
|
@ -367,6 +367,11 @@
|
||||||
// Full documentation here: https://github.com/arendst/Tasmota/wiki/AWS-IoT
|
// Full documentation here: https://github.com/arendst/Tasmota/wiki/AWS-IoT
|
||||||
// #define USE_4K_RSA // Support 4096 bits certificates, instead of 2048
|
// #define USE_4K_RSA // Support 4096 bits certificates, instead of 2048
|
||||||
|
|
||||||
|
// -- Telegram Protocol ---------------------------
|
||||||
|
//#define USE_TELEGRAM // Support for Telegram protocol (+49k code, +7.0k mem and +4.8k additional during connection handshake)
|
||||||
|
#define USE_TELEGRAM_FINGERPRINT "\xB2\x72\x47\xA6\x69\x8C\x3C\x69\xF9\x58\x6C\xF3\x60\x02\xFB\x83\xFA\x8B\x1F\x23" // Telegram api.telegram.org TLS public key fingerpring
|
||||||
|
// #define USE_MQTT_TLS_CA_CERT // Use certificate instead of fingerprint
|
||||||
|
|
||||||
// -- KNX IP Protocol -----------------------------
|
// -- KNX IP Protocol -----------------------------
|
||||||
//#define USE_KNX // Enable KNX IP Protocol Support (+9.4k code, +3k7 mem)
|
//#define USE_KNX // Enable KNX IP Protocol Support (+9.4k code, +3k7 mem)
|
||||||
#define USE_KNX_WEB_MENU // Enable KNX WEB MENU (+8.3k code, +144 mem)
|
#define USE_KNX_WEB_MENU // Enable KNX WEB MENU (+8.3k code, +144 mem)
|
||||||
|
|
|
@ -575,7 +575,9 @@ void GetFeatures(void)
|
||||||
#ifdef USE_BL0940
|
#ifdef USE_BL0940
|
||||||
feature6 |= 0x00004000; // xnrg_14_bl0940.ino
|
feature6 |= 0x00004000; // xnrg_14_bl0940.ino
|
||||||
#endif
|
#endif
|
||||||
// feature6 |= 0x00008000;
|
#ifdef USE_TELEGRAM
|
||||||
|
feature6 |= 0x00008000; // xdrv_40_telegram.ino
|
||||||
|
#endif
|
||||||
|
|
||||||
// feature6 |= 0x00010000;
|
// feature6 |= 0x00010000;
|
||||||
// feature6 |= 0x00020000;
|
// feature6 |= 0x00020000;
|
||||||
|
|
|
@ -293,7 +293,7 @@ enum SettingsTextIndex { SET_OTAURL,
|
||||||
SET_TEMPLATE_NAME,
|
SET_TEMPLATE_NAME,
|
||||||
SET_DEV_GROUP_NAME1, SET_DEV_GROUP_NAME2, SET_DEV_GROUP_NAME3, SET_DEV_GROUP_NAME4,
|
SET_DEV_GROUP_NAME1, SET_DEV_GROUP_NAME2, SET_DEV_GROUP_NAME3, SET_DEV_GROUP_NAME4,
|
||||||
SET_DEVICENAME,
|
SET_DEVICENAME,
|
||||||
SET_TELEGRAMTOKEN,
|
SET_TELEGRAM_TOKEN, SET_TELEGRAM_CHATID,
|
||||||
SET_MAX };
|
SET_MAX };
|
||||||
|
|
||||||
enum DevGroupMessageType { DGR_MSGTYP_FULL_STATUS, DGR_MSGTYP_PARTIAL_UPDATE, DGR_MSGTYP_UPDATE, DGR_MSGTYP_UPDATE_MORE_TO_COME, DGR_MSGTYP_UPDATE_DIRECT, DGR_MSGTYPE_UPDATE_COMMAND };
|
enum DevGroupMessageType { DGR_MSGTYP_FULL_STATUS, DGR_MSGTYP_PARTIAL_UPDATE, DGR_MSGTYP_UPDATE, DGR_MSGTYP_UPDATE_MORE_TO_COME, DGR_MSGTYP_UPDATE_DIRECT, DGR_MSGTYPE_UPDATE_COMMAND };
|
||||||
|
@ -321,9 +321,10 @@ enum DevGroupShareItem { DGR_SHARE_POWER = 1, DGR_SHARE_LIGHT_BRI = 2, DGR_SHARE
|
||||||
|
|
||||||
enum CommandSource { SRC_IGNORE, SRC_MQTT, SRC_RESTART, SRC_BUTTON, SRC_SWITCH, SRC_BACKLOG, SRC_SERIAL, SRC_WEBGUI, SRC_WEBCOMMAND, SRC_WEBCONSOLE, SRC_PULSETIMER,
|
enum CommandSource { SRC_IGNORE, SRC_MQTT, SRC_RESTART, SRC_BUTTON, SRC_SWITCH, SRC_BACKLOG, SRC_SERIAL, SRC_WEBGUI, SRC_WEBCOMMAND, SRC_WEBCONSOLE, SRC_PULSETIMER,
|
||||||
SRC_TIMER, SRC_RULE, SRC_MAXPOWER, SRC_MAXENERGY, SRC_OVERTEMP, SRC_LIGHT, SRC_KNX, SRC_DISPLAY, SRC_WEMO, SRC_HUE, SRC_RETRY, SRC_REMOTE, SRC_SHUTTER,
|
SRC_TIMER, SRC_RULE, SRC_MAXPOWER, SRC_MAXENERGY, SRC_OVERTEMP, SRC_LIGHT, SRC_KNX, SRC_DISPLAY, SRC_WEMO, SRC_HUE, SRC_RETRY, SRC_REMOTE, SRC_SHUTTER,
|
||||||
SRC_THERMOSTAT, SRC_MAX };
|
SRC_THERMOSTAT, SRC_CHAT, SRC_MAX };
|
||||||
const char kCommandSource[] PROGMEM = "I|MQTT|Restart|Button|Switch|Backlog|Serial|WebGui|WebCommand|WebConsole|PulseTimer|"
|
const char kCommandSource[] PROGMEM = "I|MQTT|Restart|Button|Switch|Backlog|Serial|WebGui|WebCommand|WebConsole|PulseTimer|"
|
||||||
"Timer|Rule|MaxPower|MaxEnergy|Overtemp|Light|Knx|Display|Wemo|Hue|Retry|Remote|Shutter|Thermostat";
|
"Timer|Rule|MaxPower|MaxEnergy|Overtemp|Light|Knx|Display|Wemo|Hue|Retry|Remote|Shutter|"
|
||||||
|
"Thermostat|Chat";
|
||||||
|
|
||||||
const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 };
|
const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 };
|
||||||
|
|
||||||
|
@ -344,10 +345,10 @@ const SerConfu8 kTasmotaSerialConfig[] PROGMEM = {
|
||||||
SERIAL_5O2, SERIAL_6O2, SERIAL_7O2, SERIAL_8O2
|
SERIAL_5O2, SERIAL_6O2, SERIAL_7O2, SERIAL_8O2
|
||||||
};
|
};
|
||||||
|
|
||||||
enum TuyaSupportedFunctions { TUYA_MCU_FUNC_NONE, TUYA_MCU_FUNC_SWT1 = 1, TUYA_MCU_FUNC_SWT2, TUYA_MCU_FUNC_SWT3, TUYA_MCU_FUNC_SWT4,
|
enum TuyaSupportedFunctions { TUYA_MCU_FUNC_NONE, TUYA_MCU_FUNC_SWT1 = 1, TUYA_MCU_FUNC_SWT2, TUYA_MCU_FUNC_SWT3, TUYA_MCU_FUNC_SWT4,
|
||||||
TUYA_MCU_FUNC_REL1 = 11, TUYA_MCU_FUNC_REL2, TUYA_MCU_FUNC_REL3, TUYA_MCU_FUNC_REL4, TUYA_MCU_FUNC_REL5,
|
TUYA_MCU_FUNC_REL1 = 11, TUYA_MCU_FUNC_REL2, TUYA_MCU_FUNC_REL3, TUYA_MCU_FUNC_REL4, TUYA_MCU_FUNC_REL5,
|
||||||
TUYA_MCU_FUNC_REL6, TUYA_MCU_FUNC_REL7, TUYA_MCU_FUNC_REL8, TUYA_MCU_FUNC_DIMMER = 21, TUYA_MCU_FUNC_POWER = 31,
|
TUYA_MCU_FUNC_REL6, TUYA_MCU_FUNC_REL7, TUYA_MCU_FUNC_REL8, TUYA_MCU_FUNC_DIMMER = 21, TUYA_MCU_FUNC_POWER = 31,
|
||||||
TUYA_MCU_FUNC_CURRENT, TUYA_MCU_FUNC_VOLTAGE, TUYA_MCU_FUNC_BATTERY_STATE, TUYA_MCU_FUNC_BATTERY_PERCENTAGE,
|
TUYA_MCU_FUNC_CURRENT, TUYA_MCU_FUNC_VOLTAGE, TUYA_MCU_FUNC_BATTERY_STATE, TUYA_MCU_FUNC_BATTERY_PERCENTAGE,
|
||||||
TUYA_MCU_FUNC_REL1_INV = 41, TUYA_MCU_FUNC_REL2_INV, TUYA_MCU_FUNC_REL3_INV, TUYA_MCU_FUNC_REL4_INV, TUYA_MCU_FUNC_REL5_INV,
|
TUYA_MCU_FUNC_REL1_INV = 41, TUYA_MCU_FUNC_REL2_INV, TUYA_MCU_FUNC_REL3_INV, TUYA_MCU_FUNC_REL4_INV, TUYA_MCU_FUNC_REL5_INV,
|
||||||
TUYA_MCU_FUNC_REL6_INV, TUYA_MCU_FUNC_REL7_INV, TUYA_MCU_FUNC_REL8_INV, TUYA_MCU_FUNC_LOWPOWER_MODE = 51, TUYA_MCU_FUNC_LAST = 255
|
TUYA_MCU_FUNC_REL6_INV, TUYA_MCU_FUNC_REL7_INV, TUYA_MCU_FUNC_REL8_INV, TUYA_MCU_FUNC_LOWPOWER_MODE = 51, TUYA_MCU_FUNC_LAST = 255
|
||||||
};
|
};
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#ifndef _TASMOTA_VERSION_H_
|
#ifndef _TASMOTA_VERSION_H_
|
||||||
#define _TASMOTA_VERSION_H_
|
#define _TASMOTA_VERSION_H_
|
||||||
|
|
||||||
const uint32_t VERSION = 0x08030102;
|
const uint32_t VERSION = 0x08030103;
|
||||||
|
|
||||||
// Lowest compatible version
|
// Lowest compatible version
|
||||||
const uint32_t VERSION_COMPATIBLE = 0x07010006;
|
const uint32_t VERSION_COMPATIBLE = 0x07010006;
|
||||||
|
|
|
@ -0,0 +1,479 @@
|
||||||
|
/*
|
||||||
|
xdrv_40_telegram.ino - telegram for Tasmota
|
||||||
|
|
||||||
|
Copyright (C) 2020 Theo Arends
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef USE_TELEGRAM
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Telegram bot
|
||||||
|
*
|
||||||
|
* Supported commands:
|
||||||
|
* TGToken <token> - Add your BotFather created bot token (default none)
|
||||||
|
* TGChatId <chat_id> - Add your BotFather created bot chat id (default none)
|
||||||
|
* TGPoll <seconds> - Telegram receive poll time (default 10 seconds)
|
||||||
|
* TGState 0 - Disable telegram sending (default)
|
||||||
|
* TGState 1 - Enable telegram sending
|
||||||
|
* TGState 2 - Disable telegram listener (default)
|
||||||
|
* TGState 3 - Enable telegram listener
|
||||||
|
* TGState 4 - Disable telegram response echo (default)
|
||||||
|
* TGState 5 - Enable telegram response echo
|
||||||
|
* TGSend <data> - If telegram sending is enabled AND a chat id is present then send data
|
||||||
|
*
|
||||||
|
* Tested with defines
|
||||||
|
* #define USE_TELEGRAM // Support for Telegram protocol
|
||||||
|
* #define USE_TELEGRAM_FINGERPRINT "\xB2\x72\x47\xA6\x69\x8C\x3C\x69\xF9\x58\x6C\xF3\x60\x02\xFB\x83\xFA\x8B\x1F\x23" // Telegram api.telegram.org TLS public key fingerpring
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
#define XDRV_40 40
|
||||||
|
|
||||||
|
#define TELEGRAM_SEND_RETRY 4 // Retries
|
||||||
|
#define TELEGRAM_LOOP_WAIT 10 // Seconds
|
||||||
|
|
||||||
|
#ifdef USE_MQTT_TLS_CA_CERT
|
||||||
|
static const uint32_t tls_rx_size = 2048; // since Telegram CA is bigger than 1024 bytes, we need to increase rx buffer
|
||||||
|
static const uint32_t tls_tx_size = 1024;
|
||||||
|
#else
|
||||||
|
static const uint32_t tls_rx_size = 1024;
|
||||||
|
static const uint32_t tls_tx_size = 1024;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "WiFiClientSecureLightBearSSL.h"
|
||||||
|
BearSSL::WiFiClientSecure_light *telegramClient = nullptr;
|
||||||
|
|
||||||
|
static const uint8_t Telegram_Fingerprint[] PROGMEM = USE_TELEGRAM_FINGERPRINT;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
String message[3][6]; // amount of messages read per time (update_id, name_id, name, lastname, chat_id, text)
|
||||||
|
uint8_t state = 0;
|
||||||
|
uint8_t index = 0;
|
||||||
|
uint8_t retry = 0;
|
||||||
|
uint8_t poll = TELEGRAM_LOOP_WAIT;
|
||||||
|
uint8_t wait = 0;
|
||||||
|
bool send_enable = false;
|
||||||
|
bool recv_enable = false;
|
||||||
|
bool echo_enable = false;
|
||||||
|
bool recv_busy = false;
|
||||||
|
} Telegram;
|
||||||
|
|
||||||
|
bool TelegramInit(void) {
|
||||||
|
bool init_done = false;
|
||||||
|
if (strlen(SettingsText(SET_TELEGRAM_TOKEN))) {
|
||||||
|
if (!telegramClient) {
|
||||||
|
telegramClient = new BearSSL::WiFiClientSecure_light(tls_rx_size, tls_tx_size);
|
||||||
|
#ifdef USE_MQTT_TLS_CA_CERT
|
||||||
|
telegramClient->setTrustAnchor(&GoDaddyCAG2_TA);
|
||||||
|
#else
|
||||||
|
telegramClient->setPubKeyFingerprint(Telegram_Fingerprint, Telegram_Fingerprint, false); // check server fingerprint
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Telegram.message[0][0]="0"; // Number of received messages
|
||||||
|
Telegram.message[1][0]="";
|
||||||
|
Telegram.message[0][1]="0"; // Code of last read Message
|
||||||
|
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TLG: Started"));
|
||||||
|
}
|
||||||
|
|
||||||
|
init_done = true;
|
||||||
|
}
|
||||||
|
return init_done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************************************
|
||||||
|
* function to achieve connection to api.telegram.org and send command to telegram *
|
||||||
|
* (Argument to pass: URL to address to Telegram) *
|
||||||
|
**************************************************************************************************/
|
||||||
|
String TelegramConnectToTelegram(String command) {
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TLG: Cmnd %s"), command.c_str());
|
||||||
|
|
||||||
|
if (!TelegramInit()) { return ""; }
|
||||||
|
|
||||||
|
String response = "";
|
||||||
|
uint32_t tls_connect_time = millis();
|
||||||
|
|
||||||
|
if (telegramClient->connect("api.telegram.org", 443)) {
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TLG: Connected in %d ms, max ThunkStack used %d"),
|
||||||
|
millis() - tls_connect_time, telegramClient->getMaxThunkStackUse());
|
||||||
|
|
||||||
|
telegramClient->println("GET /"+command);
|
||||||
|
|
||||||
|
String a = "";
|
||||||
|
char c;
|
||||||
|
int ch_count=0;
|
||||||
|
uint32_t now = millis();
|
||||||
|
bool avail = false;
|
||||||
|
while (millis() -now < 1500) {
|
||||||
|
while (telegramClient->available()) {
|
||||||
|
char c = telegramClient->read();
|
||||||
|
if (ch_count < 700) {
|
||||||
|
response = response + c;
|
||||||
|
ch_count++;
|
||||||
|
}
|
||||||
|
avail = true;
|
||||||
|
}
|
||||||
|
if (avail) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
telegramClient->stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************
|
||||||
|
* GetUpdates - function to receive all messages from telegram *
|
||||||
|
* (Argument to pass: the last+1 message to read) *
|
||||||
|
***************************************************************/
|
||||||
|
void TelegramGetUpdates(String offset) {
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TLG: getUpdates"));
|
||||||
|
|
||||||
|
if (!TelegramInit()) { return; }
|
||||||
|
|
||||||
|
String _token = SettingsText(SET_TELEGRAM_TOKEN);
|
||||||
|
String command = "bot" + _token + "/getUpdates?offset=" + offset;
|
||||||
|
String response = TelegramConnectToTelegram(command); //recieve reply from telegram.org
|
||||||
|
|
||||||
|
// {"ok":true,"result":[]}
|
||||||
|
// or
|
||||||
|
// {"ok":true,"result":[
|
||||||
|
// {"update_id":973125394,
|
||||||
|
// "message":{"message_id":25,
|
||||||
|
// "from":{"id":139920293,"is_bot":false,"first_name":"Theo","last_name":"Arends","username":"tjatja","language_code":"nl"},
|
||||||
|
// "chat":{"id":139920293,"first_name":"Theo","last_name":"Arends","username":"tjatja","type":"private"},
|
||||||
|
// "date":1591877503,
|
||||||
|
// "text":"M1"
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// {"update_id":973125395,
|
||||||
|
// "message":{"message_id":26,
|
||||||
|
// "from":{"id":139920293,"is_bot":false,"first_name":"Theo","last_name":"Arends","username":"tjatja","language_code":"nl"},
|
||||||
|
// "chat":{"id":139920293,"first_name":"Theo","last_name":"Arends","username":"tjatja","type":"private"},
|
||||||
|
// "date":1591877508,
|
||||||
|
// "text":"M2"
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// ]}
|
||||||
|
// or
|
||||||
|
// {"ok":true,"result":[
|
||||||
|
// {"update_id":973125396,
|
||||||
|
// "message":{"message_id":29,
|
||||||
|
// "from":{"id":139920293,"is_bot":false,"first_name":"Theo","last_name":"Arends","username":"tjatja","language_code":"nl"},
|
||||||
|
// "chat":{"id":139920293,"first_name":"Theo","last_name":"Arends","username":"tjatja","type":"private"},
|
||||||
|
// "date":1591879753,
|
||||||
|
// "text":"/power toggle",
|
||||||
|
// "entities":[{"offset":0,"length":6,"type":"bot_command"}]
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// ]}
|
||||||
|
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("TLG: Response %s"), response.c_str());
|
||||||
|
|
||||||
|
// parsing of reply from Telegram into separate received messages
|
||||||
|
int i = 0; //messages received counter
|
||||||
|
if (response != "") {
|
||||||
|
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TLG: Sent Update request messages up to %s"), offset.c_str());
|
||||||
|
|
||||||
|
String a = "";
|
||||||
|
int ch_count = 0;
|
||||||
|
String c;
|
||||||
|
for (uint32_t n = 1; n < response.length() +1; n++) { //Search for each message start
|
||||||
|
ch_count++;
|
||||||
|
c = response.substring(n -1, n);
|
||||||
|
a = a + c;
|
||||||
|
if (ch_count > 8) {
|
||||||
|
if (a.substring(ch_count -9) == "update_id") {
|
||||||
|
if (i > 1) { break; }
|
||||||
|
Telegram.message[i][0] = a.substring(0, ch_count -11);
|
||||||
|
a = a.substring(ch_count-11);
|
||||||
|
i++;
|
||||||
|
ch_count = 11;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (1 == i) {
|
||||||
|
Telegram.message[i][0] = a.substring(0, ch_count); //Assign of parsed message into message matrix if only 1 message)
|
||||||
|
}
|
||||||
|
if (i > 1) { i = i -1; }
|
||||||
|
}
|
||||||
|
//check result of parsing process
|
||||||
|
if (response == "") {
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TLG: Failed to update"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (0 == i) {
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TLG: No new messages"));
|
||||||
|
Telegram.message[0][0] = "0";
|
||||||
|
} else {
|
||||||
|
Telegram.message[0][0] = String(i); //returns how many messages are in the array
|
||||||
|
for (int b = 1; b < i+1; b++) {
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TLG: Msg %d %s"), b, Telegram.message[b][0].c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
TelegramAnalizeMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TelegramAnalizeMessage(void) {
|
||||||
|
for (uint32_t i = 1; i < Telegram.message[0][0].toInt() +1; i++) {
|
||||||
|
Telegram.message[i][5] = "";
|
||||||
|
|
||||||
|
DynamicJsonBuffer jsonBuffer;
|
||||||
|
JsonObject &root = jsonBuffer.parseObject(Telegram.message[i][0]);
|
||||||
|
if (root.success()) {
|
||||||
|
Telegram.message[i][0] = root["update_id"].as<String>();
|
||||||
|
Telegram.message[i][1] = root["message"]["from"]["id"].as<String>();
|
||||||
|
Telegram.message[i][2] = root["message"]["from"]["first_name"].as<String>();
|
||||||
|
Telegram.message[i][3] = root["message"]["from"]["last_name"].as<String>();
|
||||||
|
Telegram.message[i][4] = root["message"]["chat"]["id"].as<String>();
|
||||||
|
Telegram.message[i][5] = root["message"]["text"].as<String>();
|
||||||
|
}
|
||||||
|
|
||||||
|
int id = Telegram.message[Telegram.message[0][0].toInt()][0].toInt() +1;
|
||||||
|
Telegram.message[0][1] = id; // Write id of last read message
|
||||||
|
|
||||||
|
for (int j = 0; j < 6; j++) {
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("TLG: Parsed%d \"%s\""), j, Telegram.message[i][j].c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TelegramSendMessage(String chat_id, String text) {
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TLG: sendMessage"));
|
||||||
|
|
||||||
|
if (!TelegramInit()) { return false; }
|
||||||
|
|
||||||
|
bool sent = false;
|
||||||
|
if (text != "") {
|
||||||
|
String _token = SettingsText(SET_TELEGRAM_TOKEN);
|
||||||
|
String command = "bot" + _token + "/sendMessage?chat_id=" + chat_id + "&text=" + text;
|
||||||
|
String response = TelegramConnectToTelegram(command);
|
||||||
|
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("TLG: Response %s"), response.c_str());
|
||||||
|
|
||||||
|
if (response.startsWith("{\"ok\":true")) {
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TLG: Message sent"));
|
||||||
|
sent = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return sent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
void TelegramSendGetMe(void) {
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TLG: getMe"));
|
||||||
|
|
||||||
|
if (!TelegramInit()) { return; }
|
||||||
|
|
||||||
|
String _token = SettingsText(SET_TELEGRAM_TOKEN);
|
||||||
|
String command = "bot" + _token + "/getMe";
|
||||||
|
String response = TelegramConnectToTelegram(command);
|
||||||
|
|
||||||
|
// {"ok":true,"result":{"id":1179906608,"is_bot":true,"first_name":"Tasmota","username":"tasmota_bot","can_join_groups":true,"can_read_all_group_messages":false,"supports_inline_queries":false}}
|
||||||
|
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("TLG: Response %s"), response.c_str());
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
String TelegramExecuteCommand(const char *svalue) {
|
||||||
|
String response = "";
|
||||||
|
|
||||||
|
uint32_t curridx = web_log_index;
|
||||||
|
ExecuteCommand(svalue, SRC_CHAT);
|
||||||
|
if (web_log_index != curridx) {
|
||||||
|
uint32_t counter = curridx;
|
||||||
|
response = F("{");
|
||||||
|
bool cflg = false;
|
||||||
|
do {
|
||||||
|
char* tmp;
|
||||||
|
size_t len;
|
||||||
|
GetLog(counter, &tmp, &len);
|
||||||
|
if (len) {
|
||||||
|
// [14:49:36 MQTT: stat/wemos5/RESULT = {"POWER":"OFF"}] > [{"POWER":"OFF"}]
|
||||||
|
char* JSON = (char*)memchr(tmp, '{', len);
|
||||||
|
if (JSON) { // Is it a JSON message (and not only [15:26:08 MQT: stat/wemos5/POWER = O])
|
||||||
|
size_t JSONlen = len - (JSON - tmp);
|
||||||
|
if (JSONlen > sizeof(mqtt_data)) { JSONlen = sizeof(mqtt_data); }
|
||||||
|
char stemp[JSONlen];
|
||||||
|
strlcpy(stemp, JSON +1, JSONlen -2);
|
||||||
|
if (cflg) { response += F(","); }
|
||||||
|
response += stemp;
|
||||||
|
cflg = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
counter++;
|
||||||
|
counter &= 0xFF;
|
||||||
|
if (!counter) counter++; // Skip 0 as it is not allowed
|
||||||
|
} while (counter != web_log_index);
|
||||||
|
response += F("}");
|
||||||
|
} else {
|
||||||
|
response = F("{\"" D_RSLT_WARNING "\":\"" D_ENABLE_WEBLOG_FOR_RESPONSE "\"}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TelegramLoop(void) {
|
||||||
|
if (!global_state.wifi_down && (Telegram.recv_enable || Telegram.echo_enable)) {
|
||||||
|
switch (Telegram.state) {
|
||||||
|
case 0:
|
||||||
|
TelegramInit();
|
||||||
|
Telegram.state++;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
TelegramGetUpdates(Telegram.message[0][1]); // launch API GetUpdates up to xxx message
|
||||||
|
Telegram.index = 1;
|
||||||
|
Telegram.retry = TELEGRAM_SEND_RETRY;
|
||||||
|
Telegram.state++;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (Telegram.echo_enable) {
|
||||||
|
if (Telegram.retry && (Telegram.index < Telegram.message[0][0].toInt() + 1)) {
|
||||||
|
if (TelegramSendMessage(Telegram.message[Telegram.index][4], Telegram.message[Telegram.index][5])) {
|
||||||
|
Telegram.index++;
|
||||||
|
Telegram.retry = TELEGRAM_SEND_RETRY;
|
||||||
|
} else {
|
||||||
|
Telegram.retry--;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Telegram.message[0][0] = ""; // All messages have been replied - reset new messages
|
||||||
|
Telegram.wait = Telegram.poll;
|
||||||
|
Telegram.state++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (Telegram.message[0][0].toInt() && (Telegram.message[Telegram.index][5].length() > 0)) {
|
||||||
|
String logging = TelegramExecuteCommand(Telegram.message[Telegram.index][5].c_str());
|
||||||
|
if (logging.length() > 0) {
|
||||||
|
TelegramSendMessage(Telegram.message[Telegram.index][4], logging);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Telegram.message[0][0] = ""; // All messages have been replied - reset new messages
|
||||||
|
Telegram.wait = Telegram.poll;
|
||||||
|
Telegram.state++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if (Telegram.wait) {
|
||||||
|
Telegram.wait--;
|
||||||
|
} else {
|
||||||
|
Telegram.state = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Commands
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
#define D_CMND_TGSTATE "State"
|
||||||
|
#define D_CMND_TGPOLL "Poll"
|
||||||
|
#define D_CMND_TGSEND "Send"
|
||||||
|
#define D_CMND_TGTOKEN "Token"
|
||||||
|
#define D_CMND_TGCHATID "ChatId"
|
||||||
|
|
||||||
|
const char kTelegramCommands[] PROGMEM = "TG|" // Prefix
|
||||||
|
D_CMND_TGSTATE "|" D_CMND_TGPOLL "|" D_CMND_TGTOKEN "|" D_CMND_TGCHATID "|" D_CMND_TGSEND;
|
||||||
|
|
||||||
|
void (* const TelegramCommand[])(void) PROGMEM = {
|
||||||
|
&CmndTgState, &CmndTgPoll, &CmndTgToken, &CmndTgChatId, &CmndTgSend };
|
||||||
|
|
||||||
|
void CmndTgState(void) {
|
||||||
|
if (XdrvMailbox.data_len > 0) {
|
||||||
|
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 6)) {
|
||||||
|
switch (XdrvMailbox.payload) {
|
||||||
|
case 0: // Off
|
||||||
|
case 1: // On
|
||||||
|
Telegram.send_enable = XdrvMailbox.payload &1;
|
||||||
|
break;
|
||||||
|
case 2: // Off
|
||||||
|
case 3: // On
|
||||||
|
Telegram.recv_enable = XdrvMailbox.payload &1;
|
||||||
|
break;
|
||||||
|
case 4: // Off
|
||||||
|
case 5: // On
|
||||||
|
Telegram.echo_enable = XdrvMailbox.payload &1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":{\"Send\":\"%s\",\"Receive\":\"%s\",\"Echo\":\"%s\"}}"),
|
||||||
|
XdrvMailbox.command, GetStateText(Telegram.send_enable), GetStateText(Telegram.recv_enable), GetStateText(Telegram.echo_enable));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CmndTgPoll(void) {
|
||||||
|
if ((XdrvMailbox.payload >= 4) && (XdrvMailbox.payload <= 300)) {
|
||||||
|
Telegram.poll = XdrvMailbox.payload;
|
||||||
|
if (Telegram.poll < Telegram.wait) {
|
||||||
|
Telegram.wait = Telegram.poll;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ResponseCmndNumber(Telegram.poll);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CmndTgToken(void) {
|
||||||
|
if (XdrvMailbox.data_len > 0) {
|
||||||
|
SettingsUpdateText(SET_TELEGRAM_TOKEN, ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data);
|
||||||
|
}
|
||||||
|
ResponseCmndChar(SettingsText(SET_TELEGRAM_TOKEN));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CmndTgChatId(void) {
|
||||||
|
if (XdrvMailbox.data_len > 0) {
|
||||||
|
SettingsUpdateText(SET_TELEGRAM_CHATID, ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data);
|
||||||
|
}
|
||||||
|
ResponseCmndChar(SettingsText(SET_TELEGRAM_CHATID));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CmndTgSend(void) {
|
||||||
|
if (!Telegram.send_enable || !strlen(SettingsText(SET_TELEGRAM_CHATID))) {
|
||||||
|
ResponseCmndChar(D_JSON_FAILED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (XdrvMailbox.data_len > 0) {
|
||||||
|
String message = XdrvMailbox.data;
|
||||||
|
String chat_id = SettingsText(SET_TELEGRAM_CHATID);
|
||||||
|
if (!TelegramSendMessage(chat_id, message)) {
|
||||||
|
ResponseCmndChar(D_JSON_FAILED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ResponseCmndDone();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Interface
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
bool Xdrv40(uint8_t function)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
switch (function) {
|
||||||
|
case FUNC_EVERY_SECOND:
|
||||||
|
TelegramLoop();
|
||||||
|
break;
|
||||||
|
case FUNC_COMMAND:
|
||||||
|
result = DecodeCommand(kTelegramCommands, TelegramCommand);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif // USE_TELEGRAM
|
|
@ -205,7 +205,7 @@ a_features = [[
|
||||||
"USE_KEELOQ","USE_HRXL","USE_SONOFF_D1","USE_HDC1080",
|
"USE_KEELOQ","USE_HRXL","USE_SONOFF_D1","USE_HDC1080",
|
||||||
"USE_IAQ","USE_DISPLAY_SEVENSEG","USE_AS3935","USE_PING",
|
"USE_IAQ","USE_DISPLAY_SEVENSEG","USE_AS3935","USE_PING",
|
||||||
"USE_WINDMETER","USE_OPENTHERM","USE_THERMOSTAT","USE_VEML6075",
|
"USE_WINDMETER","USE_OPENTHERM","USE_THERMOSTAT","USE_VEML6075",
|
||||||
"USE_VEML7700","USE_MCP9808","USE_BL0940","",
|
"USE_VEML7700","USE_MCP9808","USE_BL0940","USE_TELEGRAM",
|
||||||
"","","","",
|
"","","","",
|
||||||
"","","","",
|
"","","","",
|
||||||
"","","","",
|
"","","","",
|
||||||
|
@ -243,7 +243,7 @@ else:
|
||||||
obj = json.load(fp)
|
obj = json.load(fp)
|
||||||
|
|
||||||
def StartDecode():
|
def StartDecode():
|
||||||
print ("\n*** decode-status.py v20200607 by Theo Arends and Jacek Ziolkowski ***")
|
print ("\n*** decode-status.py v20200611 by Theo Arends and Jacek Ziolkowski ***")
|
||||||
|
|
||||||
# print("Decoding\n{}".format(obj))
|
# print("Decoding\n{}".format(obj))
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue