A Telegram BOT for this awesome all-in-one board.
Dependencies: BSP_B-L475E-IOT01 mbed es_wifi jsmn
Telegram Bot for DISCO_L475VG_IOT01
This application embeds aTelegram chatbot into the DISCO_L475VG_IOT01 board.
The Bot answers to the users queries about:
- Real time environmental data taken from the on board sensors.
- Environmental data history of the latest 24 hours stored on board.
- Camera images taken from the Arducam-mini-2mp (optional).
This software uses:
- A modified version of the wifi library provided by ST in order to enable the TCP-SSL connection.
- An open source json parser jsmn (https://github.com/zserge/jsmn).
- A web service (http://now.http.org) to initialize the RTC.
- A web service (https://image-charts.com) to publish temperature,humidity and pressure charts.
- A modified version of the Arducam driver (https://os.mbed.com/users/dflet/)
Compilation
Import in your compiler and modify the following defines:
- WIFI_SSID
- WIFI_PASSWORD
- TELEGRAM_BOT_APIKEY
Please follow the Telegram bots documentation (https://core.telegram.org/bots) to better understand how the Telegram API works and how to create your bot.
In order to support the Arducam-Mini-2MP set WITH_ARDUCAM_2640 #define to 1.
Screenshots
Security
The Inventek wifi module creates the ssl connection but does not authenticate the server's certificate ( AT cmd P9=0 ).
For more details http://www.inventeksys.com/IWIN/programming-certificates-tcp-ssltls/
Diff: main.cpp
- Revision:
- 5:f204a47aa813
- Parent:
- 4:9926288a8703
- Child:
- 6:94fc61e1cf40
--- a/main.cpp Thu Jan 25 15:27:29 2018 +0000 +++ b/main.cpp Fri Jan 26 14:59:14 2018 +0000 @@ -17,14 +17,15 @@ #define WIFI_READ_TIMEOUT 10000 #define CONNECTION_TRIAL_MAX 10 + // LED DigitalOut g_alivenessLED(LED1); // wifi interfaces ES_WIFIObject_t g_es_wifi_ctx; bool wifi_connect(void); -bool open_tcpssl(uint8_t socket, uint16_t local_port, uint16_t remote_port, char *domain_name); -bool close_tcpssl(uint32_t socket); +bool open_tcp_connection(uint8_t socket, char *domain_name, uint16_t remote_port,bool secure); +bool close_tcp_connection(uint32_t socket); // http I/O buffer char g_http_io_buffer[ES_WIFI_DATA_SIZE]; @@ -39,13 +40,16 @@ const char TELEGRAM_CUSTOM_KEYBOARD[] = "{\"keyboard\": [[\"Temperature\"],[\"Humidity\"],[\"Pressure\"]],\"one_time_keyboard\": true}"; bool telegram_get_update(int32_t update_id); bool telegram_send_message(); -bool telegram_https_get(bool has_json_payload); #define TELEGRAM_BOT_INCOMING_CMD_SIZE 80 char g_incoming_msg[TELEGRAM_BOT_INCOMING_CMD_SIZE]; void telegram_bot(void); +// now.httpbin.org +const char NOW_HTTPBIN_ORG[] = "GET / HTTP/1.1\r\nHost: now.httpbin.org\r\nUser-Agent: curl/7.50.1\r\nAccept: */*\r\n\r\n"; +bool set_rtc_from_network(void); // HTTP util +bool http_request(char *http_server_domain,bool has_json_payload,bool secure); bool http_parse_response(char *http_chunk, uint16_t http_chunk_len, bool *status_code_ok, uint16_t *content_len); // JSON parser @@ -77,13 +81,22 @@ int json_results; bool well_done = false; + /* wifi connect */ if(wifi_connect()) + { printf("> Wifi connected\r\n"); + } else { NVIC_SystemReset(); } + + /* set RTC */ + set_rtc_from_network(); + + + /* main loop */ while (1) { g_alivenessLED = !g_alivenessLED; @@ -209,6 +222,39 @@ +/***************************************************************************************** + * + * + * update RTC using now.httpbin.org free service + * + * + * ***************************************************************************************/ + +#define HTTPBIN_EPOCH_TAG "epoch\":" +bool set_rtc_from_network(void) +{ + /* prepare http get header */ + strcpy(g_http_io_buffer,NOW_HTTPBIN_ORG); + if( http_request("now.httpbin.org",false,false) ) + { + char *epoch = strstr(g_json_io_buffer,HTTPBIN_EPOCH_TAG); + if(epoch == NULL) return false; + epoch += sizeof( HTTPBIN_EPOCH_TAG ); + for(int i=0;i<20;i++) + { + if( epoch[i] == '.') + { + epoch[i] = 0; + printf("> now.httpbin.org epoch: %s\r\n",epoch); + set_time( atoi(epoch) ); + return true; + } + } + } + + return false; + +} /***************************************************************************************** * @@ -223,7 +269,7 @@ { /* prepare http get header */ snprintf(g_http_io_buffer, ES_WIFI_PAYLOAD_SIZE, TELEGRAM_GETUPDATES, update_id); - return telegram_https_get(false); + return http_request("api.telegram.org",false,true); } @@ -232,11 +278,17 @@ { /* prepare http get header */ snprintf(g_http_io_buffer, ES_WIFI_PAYLOAD_SIZE, TELEGRAM_SENDMESSAGE, strlen(g_json_io_buffer)); - return telegram_https_get(true); + return http_request("api.telegram.org",true,true); } - -bool telegram_https_get(bool has_json_payload) +/************************************************************************************************** +* +* +* HTTP request transaction +* +* +***************************************************************************************************/ +bool http_request(char *http_server_domain,bool has_json_payload,bool secure) { uint16_t io_s, tx_s; ES_WIFI_Status_t io_status; @@ -253,10 +305,10 @@ io_status = ES_WIFI_STATUS_ERROR; for (int i = 0; i < CONNECTION_TRIAL_MAX; i++) { - printf("> Open SSL connection ...\r\n"); - if (open_tcpssl(socket, 0, 443, "api.telegram.org")) + printf("> Open TCP connection ...\r\n"); + if (open_tcp_connection(socket, http_server_domain,(secure)?443:80,secure)) { - printf("> SSL Connection opened successfully.\r\n"); + printf("> TCP Connection opened successfully.\r\n"); io_status = ES_WIFI_STATUS_OK; break; } @@ -301,6 +353,10 @@ } } + /* from now on the http io buffer is reused */ + g_json_io_buffer[0]=0; + g_http_io_buffer[0]=0; + /* fetch response */ io_status = ES_WIFI_ReceiveData(&g_es_wifi_ctx, socket, (uint8_t *)g_http_io_buffer, ES_WIFI_PAYLOAD_SIZE, &io_s, WIFI_READ_TIMEOUT); if (io_status != ES_WIFI_STATUS_OK) @@ -321,7 +377,7 @@ printf("> Invalid response\r\n"); goto happy_end; } - printf("HTTP OK = %d Content len = %d\r\n", http_ok, http_content_len); + printf("> HTTP OK = %d Content len = %d\r\n", http_ok, http_content_len); /* fetch json response */ http_content_pivot = strstr((char *)g_http_io_buffer, "\r\n\r\n"); @@ -362,8 +418,8 @@ ret_val = http_ok; happy_end: - printf("> Close SSL connection...\r\n"); - close_tcpssl(socket); + printf("> Close TCP connection...\r\n"); + close_tcp_connection(socket); printf("> done.\r\n"); return ret_val; } @@ -407,10 +463,8 @@ return false; key_pivot = strstr(http_chunk, HTTP_200OK); - if (key_pivot == NULL) - return false; - - if (key_pivot < line_pivot) + + if (key_pivot != NULL) *status_code_ok = true; else *status_code_ok = false; @@ -473,19 +527,20 @@ return false; } -bool open_tcpssl(uint8_t socket, uint16_t local_port, uint16_t remote_port, char *domain_name) + +bool open_tcp_connection(uint8_t socket, char *domain_name, uint16_t remote_port,bool secure) { ES_WIFI_Conn_t conn; conn.Number = socket; conn.RemotePort = remote_port; - conn.LocalPort = local_port; - conn.Type = ES_WIFI_TCP_SSL_CONNECTION; - strncpy((char *)conn.RemoteIP, domain_name, sizeof(conn.RemoteIP)); - return (ES_WIFI_StartClientConnection(&g_es_wifi_ctx, &conn) == ES_WIFI_STATUS_OK) ? true : false; + conn.LocalPort = 0; + conn.Type = (secure)?ES_WIFI_TCP_SSL_CONNECTION:ES_WIFI_TCP_CONNECTION; + strncpy((char *)conn.RemoteHost, domain_name, sizeof(conn.RemoteHost)); + return (ES_WIFI_ConnectToRemoteHost(&g_es_wifi_ctx, &conn) == ES_WIFI_STATUS_OK) ? true : false; } -bool close_tcpssl(uint32_t socket) +bool close_tcp_connection(uint32_t socket) { ES_WIFI_Conn_t conn; conn.Number = socket;