Posts: 140
Threads: 19
Joined: Apr 2016
Reputation:
4
06-11-2016, 11:05 AM
(This post was last modified: 06-14-2016, 10:34 AM by Enzo147.)
Ciao a tutti,
volevo farvi una domanda:
è possibile inviare stringhe get al modulo per far commutare i pin ?
Per esempio pensavo una cosa del genere:
scrivere nella barra degli indirizzi cosi' 192.168.1.5:2020/?#W11 e far cambiare stato anche all'app in base al comando ricevuto.
Cordiali saluti
Enzo
Posts: 35
Threads: 0
Joined: Jan 2016
Reputation:
3
Ciao Enzo,
si, è possibile inviare comandi tramite browser utilizzando le socket TCP. Per prima cosa devi installare un server su una porta, ad esempio 2020:
$TCP0:LAHQ::2020:OK
in pratica questo comando installa sulla porta 2020 un server che processa richieste HTTP. Appena il browser si collega, legge la richiesta GET e la invia ad Arduino (flag H), rispondendo al browser con il messaggio "OK" e chiudendo la connessione subito dopo (flag Q).
A questo punto devi processare la richiesto con Arduino. Ad esempio, inserendo nel browser:
http://192.168.1.103:2020/CMD?W10
la risposta sarà del tipo:
Code:
$TCP0:CONNECTED
$TCP0:>H:GET /CMD?W11 HTTP/1.1
$TCP0:SENT:1
$TCP0:DISCONNECTED
Basta quindi andare a processare la seconda riga, estraendo tutto quello che segue il punto di domanda fino al primo spazio.
Il codice che segue ad esempio preleva il testo dopo il punto di domanda, aggiunge il simbolo # e lo invia al modulo uPanel.
Code:
if (WaitMessage(1))
{
if (Msg.substring(0,18).equals("$TCP0:>H:GET /CMD?"))
{
int p = Msg.substring(18).indexOf(" ");
if (p > 0) Serial1.println("#"+Msg.substring(18,18+p));
}
}
Con questo codice potrai inviare qualunque aggiornamento del pannello da browser. Ad esempio:
http://192.168.1.103:2020/CMD?W10
http://192.168.1.103:2020/CMD?W11
http://192.168.1.103:2020/CMD?L11
etc..
Per ragioni di sicurezza cambierei CMD con una stringa più lunga, che funge da password.
Per completezza, allego tutto il codice provato su KIT3 (Cactus)
Code:
#define PIN_GPIO_0 12
#define PIN_CH_PD 13
#define PIN_RESET 22
void setup() {
// put your setup code here, to run once:
pinMode(PIN_GPIO_0, OUTPUT);
pinMode(PIN_CH_PD, OUTPUT);
pinMode(PIN_RESET, OUTPUT);
digitalWrite(PIN_GPIO_0,1);
digitalWrite(PIN_CH_PD,1);
digitalWrite(PIN_RESET,0); // Reset
Serial.begin(57600);
delay(250);
digitalWrite(PIN_RESET,1); // Release Reset
delay(5000);
Serial1.begin(57600);
delay(5000);
Serial1.println("$TCP0:LAHQ::2020:OK");
Serial1.println("$P:W1:0;L1G:0:Test Led;");
}
String Msg = "";
/*****************************************************
* This function waits a data message from the uPanel
*
* Input: timeout_ms time to wait for message
* -1 for forever
* Return: 0 = Timeout, 1 = Message received
******************************************************/
int WaitMessage(int timeout_ms)
{
int c; // the received byte
unsigned long entrytime = millis(); // Read the time at the function entry
static char KeepBuffer = 0; // This tells if we have a partial message in the buffer
if (!KeepBuffer) Msg = ""; // If Keepbuffer is false than clear the old message
KeepBuffer = 0; // in any case set now the keep buffer to false
do
{
while ((c = Serial1.read()) > '\n') {Msg += (char) c;} // Read incoming chars, if any, until new line
if (c == '\n') // is message complete?
{
//Serial.println(Msg);
if (Msg.substring(0,1).equals("#")) return 1; // if it is a data message return 1
if (Msg.substring(0,1).equals("$")) return 1; // if it is a data message return 1
Msg = ""; // otherwise, wait for another one
}
} while ((timeout_ms < 0) || (millis()-entrytime < timeout_ms)); // has max time passed?
KeepBuffer = 1; // Keep the partial buffer content
return 0; // if time passed, return 0
}
void loop() {
// put your main code here, to run repeatedly:
int c = 0;
if (WaitMessage(1))
{
if (Msg.substring(0,18).equals("$TCP0:>H:GET /CMD?"))
{
int p = Msg.substring(18).indexOf(" ");
if (p > 0)
{
Serial1.println("#"+Msg.substring(18,18+p));
}
}
}
c = 0;
while(c >= 0)
{ c = Serial.read(); if (c >= 0) Serial1.write(c); }
}
Posts: 140
Threads: 19
Joined: Apr 2016
Reputation:
4
06-13-2016, 08:29 PM
(This post was last modified: 06-13-2016, 09:01 PM by Enzo147.)
(06-11-2016, 06:26 PM)Simone Wrote: Ciao Enzo,
si, è possibile inviare comandi tramite browser utilizzando le socket TCP. Per prima cosa devi installare un server su una porta, ad esempio 2020:
$TCP0:LAHQ::2020:OK
in pratica questo comando installa sulla porta 2020 un server che processa richieste HTTP. Appena il browser si collega, legge la richiesta GET e la invia ad Arduino (flag H), rispondendo al browser con il messaggio "OK" e chiudendo la connessione subito dopo (flag Q).
A questo punto devi processare la richiesto con Arduino. Ad esempio, inserendo nel browser:
http://192.168.1.103:2020/CMD?W10
la risposta sarà del tipo:
Code:
$TCP0:CONNECTED
$TCP0:>H:GET /CMD?W11 HTTP/1.1
$TCP0:SENT:1
$TCP0:DISCONNECTED
Basta quindi andare a processare la seconda riga, estraendo tutto quello che segue il punto di domanda fino al primo spazio.
Il codice che segue ad esempio preleva il testo dopo il punto di domanda, aggiunge il simbolo # e lo invia al modulo uPanel.
Code:
if (WaitMessage(1))
{
if (Msg.substring(0,18).equals("$TCP0:>H:GET /CMD?"))
{
int p = Msg.substring(18).indexOf(" ");
if (p > 0) Serial1.println("#"+Msg.substring(18,18+p));
}
}
Con questo codice potrai inviare qualunque aggiornamento del pannello da browser. Ad esempio:
http://192.168.1.103:2020/CMD?W10
http://192.168.1.103:2020/CMD?W11
http://192.168.1.103:2020/CMD?L11
etc..
Per ragioni di sicurezza cambierei CMD con una stringa più lunga, che funge da password.
Per completezza, allego tutto il codice provato su KIT3 (Cactus)
Code:
#define PIN_GPIO_0 12
#define PIN_CH_PD 13
#define PIN_RESET 22
void setup() {
// put your setup code here, to run once:
pinMode(PIN_GPIO_0, OUTPUT);
pinMode(PIN_CH_PD, OUTPUT);
pinMode(PIN_RESET, OUTPUT);
digitalWrite(PIN_GPIO_0,1);
digitalWrite(PIN_CH_PD,1);
digitalWrite(PIN_RESET,0); // Reset
Serial.begin(57600);
delay(250);
digitalWrite(PIN_RESET,1); // Release Reset
delay(5000);
Serial1.begin(57600);
delay(5000);
Serial1.println("$TCP0:LAHQ::2020:OK");
Serial1.println("$P:W1:0;L1G:0:Test Led;");
}
String Msg = "";
/*****************************************************
* This function waits a data message from the uPanel
*
* Input: timeout_ms time to wait for message
* -1 for forever
* Return: 0 = Timeout, 1 = Message received
******************************************************/
int WaitMessage(int timeout_ms)
{
int c; // the received byte
unsigned long entrytime = millis(); // Read the time at the function entry
static char KeepBuffer = 0; // This tells if we have a partial message in the buffer
if (!KeepBuffer) Msg = ""; // If Keepbuffer is false than clear the old message
KeepBuffer = 0; // in any case set now the keep buffer to false
do
{
while ((c = Serial1.read()) > '\n') {Msg += (char) c;} // Read incoming chars, if any, until new line
if (c == '\n') // is message complete?
{
//Serial.println(Msg);
if (Msg.substring(0,1).equals("#")) return 1; // if it is a data message return 1
if (Msg.substring(0,1).equals("$")) return 1; // if it is a data message return 1
Msg = ""; // otherwise, wait for another one
}
} while ((timeout_ms < 0) || (millis()-entrytime < timeout_ms)); // has max time passed?
KeepBuffer = 1; // Keep the partial buffer content
return 0; // if time passed, return 0
}
void loop() {
// put your main code here, to run repeatedly:
int c = 0;
if (WaitMessage(1))
{
if (Msg.substring(0,18).equals("$TCP0:>H:GET /CMD?"))
{
int p = Msg.substring(18).indexOf(" ");
if (p > 0)
{
Serial1.println("#"+Msg.substring(18,18+p));
}
}
}
c = 0;
while(c >= 0)
{ c = Serial.read(); if (c >= 0) Serial1.write(c); }
}
Ciao Simone,
intanto ti ringrazio per la risposta,
ho provato a modificare il mio sketch cosi':
Code:
void setup() {
// Initialize Serial Port
Serial.begin(57600);
// Let uPanel start
delay(3000);
// Discharge old partial messages
Serial.println("");
// Send The Panel (A LED and a Switch)
Serial.println("$P:Dg21;/5T*25fb:Prova;=*16/30{mL1G:0;|*12W1:0;|T:Relè 1;}/{mL2G:0;|*12W2:0;|T:Relè 2;}/30*20T#FF0ht3,000:Prova relè;");
//server
Serial.println("$TCP0:LAHQ::2020:OK");
// Initialize digital output pin
digitalWrite(8, 0);
pinMode(8,OUTPUT);
digitalWrite(9, 0);
pinMode(9,OUTPUT);
}
String Msg;
void loop() {
int c;
while ((c = Serial.read()) > '\n') Msg += (char) c; // Read incoming chars, if any, until new line
if (c == '\n') // is the message complete?
{
if (Msg.equals("#W20")) {digitalWrite(9,0); Serial.println("#L20");}
if (Msg.equals("#W21")) {digitalWrite(9,1); Serial.println("#L21");}
if (Msg.equals("#W10")) {digitalWrite(8,0); Serial.println("#L10");}
if (Msg.equals("#W11")) {digitalWrite(8,1); Serial.println("#L11");}
if (Msg.substring(0,18).equals("$TCP0:>H:GET /CMD?"))
{
int p = Msg.substring(18).indexOf(" ");
if (p > 0)
{
Serial.println("#"+Msg.substring(18,18+p));
}
}
Msg = "";
}
}
forse ho dimenticato qualcosa, perchè quando invio questa stringa da browser:http://192.168.1.2:2020/CMD?W11
cambia sato solo l'interuttore ma il relè non commuta e il led di stato non cambia, stessa cosa se invio http://192.168.1.2:2020/CMD?L11 , il led diventa verde ma non commuta nulla.
Dove sbaglio?
Cordiali saluti
Enzo
Specifico che sto usando arduino uno e quindi ho modificato il serialprint1
Posts: 103
Threads: 10
Joined: Apr 2016
Reputation:
3
Dipende forse dal tipo di relè che usi che potrebbero essere a logica invertita. Quindi nel setup li devi impostare con digitalWrite(8,1) e metterli a 0 quando invii la stringa
Posts: 140
Threads: 19
Joined: Apr 2016
Reputation:
4
(06-13-2016, 10:25 PM)Dok Wrote: Dipende forse dal tipo di relè che usi che potrebbero essere a logica invertita. Quindi nel setup li devi impostare con digitalWrite(8,1) e metterli a 0 quando invii la stringa
Ciao Dok,
non è questo il problema, perché se premo i tasti manualmente sull'applicazione i relè commutano correttamente.
C'è qualcosa di sbagliato a livello di sketch che ho dovuto adattare su arduino uno e sicuramente manca qualcosa.
Posts: 35
Threads: 0
Joined: Jan 2016
Reputation:
3
06-14-2016, 06:35 AM
(This post was last modified: 06-14-2016, 06:40 AM by Simone.)
Enzo,
il codice che ti ho riportato, aggiorna soltanto lo stato della grafica, ma non agisce sui rele. Quello lo deve fare Arduino in base al messaggio che riceve. Il modo più semplice è modificare il tuo sketch come segue:
Code:
void setup() {
// Initialize Serial Port
Serial.begin(57600);
// Let uPanel start
delay(3000);
// Discharge old partial messages
Serial.println("");
// Send The Panel (A LED and a Switch)
Serial.println("$P:Dg21;/5T*25fb:Prova;=*16/30{mL1G:0;|*12W1:0;|T:Relè 1;}/{mL2G:0;|*12W2:0;|T:Relè 2;}/30*20T#FF0ht3,000:Prova relè;");
//server
Serial.println("$TCP0:LAHQ::2020:OK");
// Initialize digital output pin
digitalWrite(8, 0);
pinMode(8,OUTPUT);
digitalWrite(9, 0);
pinMode(9,OUTPUT);
}
String Msg;
void loop() {
int c;
while ((c = Serial.read()) > '\n') Msg += (char) c; // Read incoming chars, if any, until new line
if (c == '\n') // is the message complete?
{
if (Msg.substring(0,18).equals("$TCP0:>H:GET /CMD?"))
{
int p = Msg.substring(18).indexOf(" ");
if (p > 0)
{
Msg = "#"+Msg.substring(18,18+p);
Serial.println(Msg);
}
}
if (Msg.equals("#W20")) {digitalWrite(9,0); Serial.println("#L20");}
if (Msg.equals("#W21")) {digitalWrite(9,1); Serial.println("#L21");}
if (Msg.equals("#W10")) {digitalWrite(8,0); Serial.println("#L10");}
if (Msg.equals("#W11")) {digitalWrite(8,1); Serial.println("#L11");}
Msg = "";
}
}
In pratica ho spostato in alto la gestione del messaggio della socket TCP e ho inserito il comando ricevuto in Msg in modo che i test successivi
funzionino come se il messaggio arrivasse da pannello.
Posts: 140
Threads: 19
Joined: Apr 2016
Reputation:
4
06-14-2016, 10:34 AM
(This post was last modified: 06-14-2016, 11:10 AM by Enzo147.)
Grazie mille Simone,
adesso funziona correttamente.
Effettivamente non ho pensato che era meglio mettere il codice prima degli if in modo che arduino interpetra ed agisce in base al comando ricevuto.
Funziona perfettamente.
Presto pubblichero' un mio nuovo progetto sul forum usando proprio questa funzione in modo tale che puo' tornare utile anche ad altri.
Buona giornata
Enzo
Ho ancora un ultima domanda:
e se volessimo leggere gli stati da remoto?
Posts: 8
Threads: 2
Joined: Feb 2016
Reputation:
0
Prendendo spunto dai contributi del forums, ho provato a creare un semplice pannello di prova per poter comandare il led on board di arduino nano in maniera asincrona da APP che da browser.
Il mio provider è Fastweb ed attraverso il mapping del router ho aperto le porte stadar del upanel 80 e 81 su porte interne 5555 e 9999
Attraverso l'IP pubblico (2.227.18.135:5555) riesco a raggiungere il modulo tramite internet tanto che con la APP (connessa su APN Vodafone) i comandi impartiti vengono correttamente eseguiti.
Per quanto riguarda invece l'invio attraverso richiesta HTTP, non c'è verso di far leggere la richiesta GET utilizzando nel browser l'URL con public IP 2.227.18.135:5555/CMD?W21, diversamente è perfettamente funzionante in maniera asincrona con la APP se nel browser inserisco l'indirizzo LAN del modulo (192.168.1.130:5555).
Questo è lo sketch:
void setup()
{
Serial.begin(57600);
digitalWrite(13, 0);
pinMode(13,OUTPUT);
delay(3000);
Serial.println("");
Serial.println("$PING 200");
Serial.println("$config");
Serial.println("$STAIP 192.168.1.130 192.168.1.254 255.255.255.0"); //setto l'indirizzo IP fisso,Gatway,Subnet
Serial.println("$CONNECT:user:password"); //Si collega alla rete wifi esistente
Serial.println("$CONNSTA");
Serial.println("$NOROUTER");
Serial.println("$ROUTER:5555:9999"); //setta le porte del router per accesso TCP da Internet
Serial.println("");
Serial.println("$P  g21;/5T*25fb  rova;=*16/30{mL2G:0;|*12W2:0;|T:Rele 2;}/30*20T#FF0ht3,000  rova rele;");
Serial.println("$TCP0:LAHQ::6888:OK");
}
String Msg;
void loop()
{
int c;
while ((c = Serial.read()) > '\n') Msg += (char) c;
{
if (Msg.substring(0,18).equals("$TCP0:>H:GET /CMD?"))
{
int p = Msg.substring(18).indexOf(" ");
if (p > 0)
{
Msg = "#"+Msg.substring(18,18+p);
Serial.println(Msg);
}
}
if (Msg.equals("#W20")) {digitalWrite(13,0); Serial.println("#L20");}
if (Msg.equals("#W21")) {digitalWrite(13,1); Serial.println("#L21");}
Msg = "";
}
}
Potete aiutarmi a risolvere il problema.
Grazie.
Posts: 140
Threads: 19
Joined: Apr 2016
Reputation:
4
01-11-2017, 09:19 PM
(This post was last modified: 01-11-2017, 09:25 PM by Enzo147.)
Ciao,
devi aprire una terza porta tcp nel router per raggiungere il webserver miupanel.
Nel tuo caso hai impostato questo: Serial.println("$TCP0:LAHQ::6888:OK");
Quindi sta a significare che tramite il tuo ip pubblico + la porta 6888 raggiungi il server che hai creato sul miupanel.
Cosi':2.227.18.135:5555/CMD?W21 non è corretto.
Cosi' SI : 2.227.18.135:6888/CMD?W21.
Tra l'altro se hai una versione di firmware miupanel almeno A004A, ti basta sbaffare la voce connect via cloud e non hai bisogno di aprire le porte tcp e udp per raggiungere il modulo da remoto, farà tutto automaticamente.
Se invece crei un webserver sul modulo dovrai sempre aprire la porta tcp che hai impostato nello sketch per impartire i comandi anche da un qualsiasi browser.
Spero di esserti stato d'aiuto
Ciao
Enzo
Posts: 8
Threads: 2
Joined: Feb 2016
Reputation:
0
Grazie Enzo,
purtroppo ho riportato una versione dello sketch errata, quella giusta riporta la riga Serial.println("$TCP0:LAHQ::5555:OK");
e quindi il sistema dovrebbe essere in grado di rispondere sia alla chiamata il LAN 192.168.1.130:5555//CMD?W21 che in WAN 2.227.18.135:5555/CMD?W21.
Quello che non riesco a comprendere è perché il modulo è raggiungibile da IP pubblico con la App [settata su 2.227.18.135 (5555,9999)] e non lo è invece dal browser sullo stesso indirizzo [2.227.18.135:5555].
Vorrei riuscirci senza aggiornare la versione del firmware, dovrebbe funzionare.
Grazie.
|