Go Down

Topic: NodeMCU e Alexa (Read 706 times) previous topic - next topic

Willy76

Buongiorno a tutti, è da un po' che mi stò documentando per realizzare un progetto in apparenza semplice ma non riesco a venirne a capo.
Vorrei interfacciare Alexa con nodeMCU, su questo ci sono molti esempi, però ho trovato solo per dare un comando da Alexa ed eseguire un comando (accendere luce...) su nodeMCU senza un ritorno. Io sarei interessato a far si che chiedendo la temperatura (nel mio caso di una caldaia a legna) alexa mi dicesse la temperatura rilevata dal sensore ds18b20 collegato al nodeMCU.
In che modo posso trasmettere questo dato ad Alexa?
Ho provato con sirinc ma mi sono perso e non sono riuscito, qualcuno saprebbe darmi una mano?

gpb01

Prova a cercare con Google "alexa esp temperature" ... troverai vari risultati che fanno quanto chiedi.

Guglielmo
Search is Your friend ... or I am Your enemy !

Willy76

Grazie gpb01 per la risposta. Avevo già provato a cercare come mi hai consigliato, però non sono riuscito nella parte di trasmissione della temperatura ad Alexa. Nel senso che probabilmente sbaglio qualcosa nel passaggio da nodemcu e Alexa (skill e cluod vari...)
Riproverò ancora con più calma e vi terrò aggiornati...

Willy76

Come promesso ho fatto progressi e vi aggiorno in merito...
Sono riuscito a far dire ad Alexa la temperatura rilevata dal mio sensore collegato al nodeMCU. E' stato abbastanza laborioso, ma alla fine sono riuscito appoggiandomi a thingspeak per salvare i dati e tramite voiceflow per creare una skill di Alexa in modo da prelevare l'ultimo dato memorizzato.
Adesso però vorrei andare oltre... mai fermarsi!!!
Vorrei potere prelevare i dati salvati in thingspeak tramite un altro nodeMCU e visualizzare la temperatura su un display. Ho provato a cercare in rete ma non ho trovato nulla... ci sono moltissime guide su come mandare i dati al sito ma non trovo come invertire il proceso...
Avete qualche idea?

zoomx

#4
Dec 05, 2019, 07:36 pm Last Edit: Dec 05, 2019, 07:37 pm by zoomx
Si, leggere la documentazione di thingspeak
https://www.mathworks.com/help/thingspeak/readdata.html
Guarda gli esempi.


Pubblica anche come hai fatto. A me sembra una cosa da Ufficio Complicazione Affari Semplici ma se Amazon ha deciso di fare così un motivo ci sarà.

Willy76

grazie per la risposta zoomx, avevo già guardato la documentazione di thingspeak, mi è servita per generare l'url da inserire in voiceflow... appena ho un attimo posto la procedura che ho usato, magari c'è un metodo più semplice ma per ora non ci sono arrivato...
Il mio problema è che non so come utilizzare i dati all'interno dello sketch, non ho queste competenze, sono all'inizio e fatico molto perchè sono cose nuove..

zoomx

#6
Dec 05, 2019, 09:43 pm Last Edit: Dec 09, 2019, 04:48 pm by zoomx
Prova ad inserire l'url in un browser così vedi cosa ti restituisce.
Il CVS è un file di testo con i valori separati da una virgola, se non ricordo male.
Il JSON è pure di testo ma formattato diversamente, potrebbe essere trattato con la relativa libreria.

Tu vuoi prendere un intervallo e fare il grafico? Oppure mostrare solo alcuni valori?

Ho trovato il video e c'è il codice su GitHub. Usa il JSON
https://www.youtube.com/watch?v=P04kQH0Jpkg

nid69ita

#7
Dec 08, 2019, 09:03 am Last Edit: Dec 08, 2019, 09:04 am by nid69ita
Come promesso ho fatto progressi e vi aggiorno in merito...
Sono riuscito a far dire ad Alexa la temperatura rilevata dal mio sensore collegato al nodeMCU. E' stato abbastanza laborioso, ma alla fine sono riuscito appoggiandomi a thingspeak per salvare i dati e tramite voiceflow per creare una skill di Alexa in modo da prelevare l'ultimo dato memorizzato.
Mi pare interessante. Sono ai primi contatti con questo meccanismo Alexa/server. Io ho seguito indicazioni di Brunello qui: LINK
In quel thread non si parla di risposta a voce. Non capisco però se non c'è strada più semplice rispetto a quella che hai fatto tu appoggiandosi ad ulteriori 2 oggetti/siti/server.
Su sito Amazon x sviluppo Alexia (in inglese) si parla di StateReport che può essere settato come interrogabile da Alexia: LINK
my name is IGOR, not AIGOR

Willy76

Grazie zoomx, io vorrei visualizzare su un display l'ultimo dato memorizzato. Ho visto il video che mi hai gentilmente segnalato. Ho provato a caricare il codice che utilizza nell'esempio cpsì com'è in modo da capire come funziona per poi adattarlo alle mie esigenze.
Il problema è che dopo averlo caricato, aprendo il monitor seriale mi appare questo...
wdt reset
load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
vffffffff
~ld
⸮bl r⸮o$ph
Adesso devo capire il motivo... perchè caricando altri codici la scheda funziona normalmente...

Mi pare interessante. Sono ai primi contatti con questo meccanismo Alexa/server. Io ho seguito indicazioni di Brunello qui: LINK
In quel thread non si parla di risposta a voce. Non capisco però se non c'è strada più semplice rispetto a quella che hai fatto tu appoggiandosi ad ulteriori 2 oggetti/siti/server.
Su sito Amazon x sviluppo Alexia (in inglese) si parla di StateReport che può essere settato come interrogabile da Alexia: LINK
Mi spiace non saprei se ci sono strade meno complicate... io per ora non ne ho trovate. Così sono riuscito a fare quello che volevo, cioè leggere i dati di temperatura, caricarli su thingspeak e interrogando Alexa mi risponde con l'ultimo dato di temperatura memorizzato...

gpb01

NON è per NodeMCU (e mi pare ovvio), ma Arduino ha fatto una libreria apposta per la connessione con Alexa ...
... ne hanno parlato in QUESTO articolo nel blog.

Al momento la libreria funziona su MKR 1000, MKR WiFi 1010, MKR GSM 1400 e Nano 33 IoT ... magari, con un piccolo costo in più dell'hardware, si risparmia un mucchio di tempo nello sviluppo ... ::)

Guglielmo
Search is Your friend ... or I am Your enemy !

zoomx

Vedo che lo sketch risale al 2017, nel frattempo ci sono stati aggiornamenti nel core.

Il problema che ti appare è perché lo sketch perde troppo tempo in qualche punto ed entra in funzione il watchdog.
Mi sa che da qualche parte ci vuole uno yield(), il mio sospetto cade sui due cicli while.
Se ho tempo sperimento anche io.

Willy76

Grazie zoomx, avevo capito che il problema potesse essere quello (guardando in rete..) però tramite le mie conoscenze di programmazione non saprei dove intervenire in questo codice...
Ti sarei molto grato se mi dessi una mano a capire cosa non và, intanto cerco pure io, perchè la funzione yield() non la conosco... ne ho da studiare...

zoomx

La funzione yeld() non fa altro che permettere ai task del WiFi di poter girare ed evitare che scatti il watchdog e non influisce sul comportamento dello sketch a meno che in quel momento serva tutta l'attenzione della MCU.

Ma il reset ti appare subito, ancora prima di connettersi al WiFi?

Willy76

#13
Dec 11, 2019, 02:05 pm Last Edit: Dec 11, 2019, 02:17 pm by Willy76
Grazie zoomx, purtroppo non sono ancora riuscito a guardare la funzione yield(), sono incasinato con il lavoro...

Il reset parte subito senza mostrare nulla sul monitor seriale, il codice che ho caricato è questo...

Code: [Select]

#include <WiFi.h>
#include <ArduinoJson.h>
WiFiServer server(80);

char   host[] = "api.thingspeak.com"; // ThingSpeak address
String APIkey = "320098";             // Thingspeak Read Key, works only if a PUBLIC viewable channel
const int httpPort = 80;

const char *ssid     = "your_SSID";
const char *password = "your_PASSWORD";
WiFiClient client;
const unsigned long HTTP_TIMEOUT = 10000;  // max respone time from server

void setup(){
Serial.begin(115200);
WiFi.begin(ssid,password);

}

void loop(){
RetrieveTSChannelData();
delay(60000); //Wait before we request again
}

void RetrieveTSChannelData() {  // Receive data from Thingspeak
static char responseBuffer[3*1024]; // Buffer for received data
client = server.available();
if (!client.connect(host, httpPort)) {
  Serial.println("connection failed");
  return;
}
String url = "/channels/" + APIkey; // Start building API request string
url += "/fields/1.json?results=5";  // 5 is the results request number, so 5 are returned, 1 woudl return the last result received
client.print(String("GET ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n");
while (!skipResponseHeaders());                      // Wait until there is some data and skip headers
while (client.available()) {                         // Now receive the data
  String line = client.readStringUntil('\n');
  if ( line.indexOf('{',0) >= 0 ) {                  // Ignore data that is not likely to be JSON formatted, so must contain a '{'
    Serial.println(line);                            // Show the text received
    line.toCharArray(responseBuffer, line.length()); // Convert to char array for the JSON decoder
    decodeJSON(responseBuffer);                      // Decode the JSON text
  }
}
client.stop();
}

bool skipResponseHeaders() {
char endOfHeaders[] = "\r\n\r\n"; // HTTP headers end with an empty line
client.setTimeout(HTTP_TIMEOUT);
bool ok = client.find(endOfHeaders);
if (!ok) { Serial.println("No response or invalid response!"); }
return ok;
}

bool decodeJSON(char *json) {
StaticJsonBuffer <3*1024> jsonBuffer;
char *jsonstart = strchr(json, '{'); // Skip characters until first '{' found and ignore length, if present
if (jsonstart == NULL) {
  Serial.println("JSON data missing");
  return false;
}
json = jsonstart;
JsonObject& root = jsonBuffer.parseObject(json); // Parse JSON
if (!root.success()) {
  Serial.println(F("jsonBuffer.parseObject() failed"));
  return false;
}
JsonObject& root_data = root["channel"]; // Begins and ends within first set of { }
String id   = root_data["id"];
String name = root_data["name"];
String field1_name = root_data["field1"]; // Extracts field name in this example field1 is called 'Pressure'
String field2_name = root_data["field2"]; // Extracts field name in this example field2 is called 'Temperature'
String field3_name = root_data["field3"]; // Extracts field name in this example field3 is called 'Humidity'
String datetime    = root_data["updated_at"];
Serial.println("\n\n Channel id: "+id+" Name: "+ name);
Serial.println(" Readings last updated at: "+datetime);

for (int result = 0; result < 5; result++){
  JsonObject& channel = root["feeds"][result]; // Now we can read 'feeds' values and so-on
  String entry_id     = channel["entry_id"];
  String field1value  = channel["field1"];
  String field2value  = channel["field2"];
  String field3value  = channel["field3"];
  Serial.print(" Field1 entry number ["+entry_id+"] had a value of: ");Serial.println(field1value);
  Serial.print(" Field2 entry number ["+entry_id+"] had a value of: ");Serial.println(field2value);
  Serial.print(" Field3 entry number ["+entry_id+"] had a value of: ");Serial.println(field3value);
}
}
//Thing speak response to GET request(headers removed) and /result=1:
/*
 *
  {"channel":{"id":320098,"name":"Test Channel","latitude":"0.0","longitude":"0.0","field1":"Pressure","field2":"Temperature","field3":"Humidity",
   "created_at":"2017-08-21T13:22:12Z","updated_at":"2017-08-26T22:18:16Z","last_entry_id":85},"feeds":[{"created_at":"2017-08-26T22:18:16Z","entry_id":85,"field1":"40"}]}
 */


Dove dovrei mettere la funzione yield()?

gpb01

#14
Dec 11, 2019, 02:09 pm Last Edit: Dec 11, 2019, 02:09 pm by gpb01
>Willy76:   ti ricordo che in conformità al regolamento, punto 7, devi editare il tuo post qui sopra (quindi NON scrivendo un nuovo post, ma utilizzando il bottone More -> Modify che si trova in basso a destra del tuo post) e racchiudere il codice all'interno dei tag CODE (... sono quelli che in edit inserisce il bottone con icona fatta così: </>, tutto a sinistra).

In pratica, tutto il tuo codice dovrà trovarsi racchiuso tra due tag: [code] _il _tuo_ codice_ [/code] così da non venire interpretato e non dare adito alla formazione di caratteri indesiderati o cattiva formattazione del testo. Grazie.

Guglielmo

P.S.: Ti ricordo che, purtroppo, fino a quando non avrai sistemato il codice come richiesto, nessuno ti potrà rispondere, quindi ti consiglio di farlo al più presto. ;)
Search is Your friend ... or I am Your enemy !

Go Up