Durante lo sviluppo di una applicazione embedded, è spesso necessario implementare qualche forma di notifica a fronte di eventi o di particolari condizioni. Pensiamo ad esempio ad un sistema di allarme che deve informare il proprietario in caso la porta di casa venga aperta in sua assenza…
Nel tutorial di oggi vedremo come inviare SMS utilizzando il chip esp32.
SMS Gateway
SMS (Short Message Service, servizio messaggi brevi) è un servizio offerto dalle reti mobili per inviare brevi messaggi di testo ad un telefono. Per usufruire di tale servizio e quindi poter inviare messaggi SMS, è quindi necessaria una intefaccia verso la rete mobile GSM. Esistono schede o moduli (ad esempio questo GPRS Shield per Arduino di SeeedStudio) che consentono un collegamento diretto alla rete mobile; in alternativa possiamo sfruttare dei servizi Internet detti SMS Gateway.
Gli SMS Gateway rendono disponibili, tramite protocolli standard Internet (HTTP, SMTP…), la possibilità di inviare (e anche ricevere) SMS su rete mobile. Il servizio è normalmente a pagamento (costo per SMS inviato); alcuni gateway offrono degli invii gratuiti al momento della registrazione. Nel tutorial di oggi utilizzeremo proprio uno di questi gateway, BulkSMS, per inviare SMS dalla nostra scheda di sviluppo esp32.
BulkSMS API
Per poter utilizzare un SMS Gateway, dobbiamo per prima cosa imparare come interagire con i servizi che questo offre. Una applicazione offre dei servizi tramite una interfaccia API (Application Programming Interface) e il “linguaggio” da utilizzare per parlare con tale interfaccia è documentato sul sito stesso o in qualche manuale.
BulkSMS raccoglie tutta la documentazione relativa alle API offerte all’interno del portale per sviluppatore (http://developer.bulksms.com); in particolare il servizio di invio SMS (send_sms) è illustrato al seguente link:
http://developer.bulksms.com/eapi/submission/send_sms/
Per inviare un SMS – dopo aver creato un proprio account – è necessario inviare una richiesta POST al server bulksms.vsms.net specificando almeno i seguenti parametri:
- username, nome utente del nostro account BulkSMS
- password, password del nostro account BulkSMS
- message, testo del messaggio da inviare
- msisdn, numero del destinatario
I parametri devono essere inseriti nel corpo della richiesta, con la forma nomeparametro=valore e concatenati con il simbolo &. Se ad esempio vogliamo inviare il messaggio “ciao mondo” al numero 39123456789 il contenuto della richiesta sarà:
username=bulksmsUser&password=bulksmsPass&message=ciao+mondo&msisdn=39123456789
Programma
Il programma completo è disponibile nel mio repository Github. La sua struttura base è molto simile a quella di un precedente tutorial: anche in questo caso infatti implementeremo un client HTTP che invierà la richiesta al server di BulkSMS e riceverà come risposta l’esito dell’invio del messaggio.
L’invio dell’SMS avviene alla pressione del tasto BOOT presente sulla scheda di sviluppo… vi ho già mostrato come gestire via interrupts tale evento. In questo esempio utilizzo gli event groups per comunicare tra i diversi task sia lo stato della connessione wifi, sia la pressione del pulsante:
// Event group for inter-task communication static EventGroupHandle_t event_group; const int WIFI_CONNECTED_BIT = BIT0; const int BUTTON_PRESSED_BIT = BIT1; |
Se infatti viene sollevato l’interrupt, utilizzo il metodo xEventGroupSetBitsFromISR per “attivare” il bit BUTTON_PRESSED:
// button ISR void IRAM_ATTR button_isr_handler(void* arg) { xEventGroupSetBitsFromISR(event_group, BUTTON_PRESSED_BIT, NULL); } |
Il task principale (main_task) attende tale evento per eseguire la chiamata a BulkSMS e inviare il messaggio:
xEventGroupWaitBits(event_group, BUTTON_PRESSED_BIT, pdTRUE, pdTRUE, portMAX_DELAY); |
Come detto, la comunicazione con BulkSMS avviene attraverso il metodo POST. Per prima cosa, il programma costruisce il body della richiesta nel formato illustrato in precedenza:
sprintf(request_body, "username=%s&password=%s&message=%s&msisdn=%s", CONFIG_BULKSMS_USER, CONFIG_BULKSMS_PASSWORD, CONFIG_SMS_TEXT, CONFIG_SMS_RECIPIENTS); |
Quindi definisce l’intera richiesta; in particolare uno degli headers della richiesta (Content-Length) deve contenere la lunghezza (in bytes) del body (questo è il motivo per cui è stato costruito in precedenza):
sprintf(request, "POST %s HTTP/1.1\nHost: %s\nUser-Agent: ESP32\n Content-Type: application/x-www-form-urlencoded\nContent-Length: %d\n\n%s", WEB_URL, WEB_SERVER, strlen(request_body), request_body); |
La risposta delle API di BulkSMS è nella forma ReturnCode|ReturnMessage. In particolare se ReturnCode=0 l’invio è andato a buon fine, altrimenti è avvenuto un errore:
char* ret_code_string = strtok(body, "|"); int return_code = atoi(ret_code_string); char *return_message = strtok(NULL, "|"); if(return_code == 0) printf("SMS sent successfully!"); else printf("SMS send failed, error code = %d - %s\n", return_code, return_message); |
Test
Prima di poter eseguire il programma, è necessario configurare alcuni parametri (quelli relativi alla rete wifi e al proprio account BulkSMS) tramite menuconfig:
Completata la configurazione e lanciato il programma, è possibile inviare l’SMS premendo il tasto BOOT:
In caso di errore, viene visualizzato sia il codice di errore che la sua descrizione:
Ecco infine un filmato che mostra il funzionamento del programma:
Salve ho provato l’esempio 01_wifi_scanner , ma va in crash , scollega la seriale.
(Mentre gli esempi originali “esp-idf” ) la wifi funziona corretamente
Nel log ho questo:
https://s4.postimg.org/i5vwacub1/MWSnap097.jpg
Risolto, il cavo usb un pochino lungo 2m , quando si attivava la wifi creava una caduta di tensione sul filo . Alimentato esternamente funzion benissimo!!
PS: Ma ESP32 assorbe moltissimo in wifi, circa 100mA forse anche qualcosina di più in tx wifi