ESP32, Virtuino SE a ThingSpeak

Odpovědět
Cermy
Příspěvky: 18
Registrován: 01 úno 2019, 11:23

ESP32, Virtuino SE a ThingSpeak

Příspěvek od Cermy » 21 lis 2019, 12:59

Ahoj všem.
Potřebuji jen programovací radu.
Mám zprovozněno ESP32 s Virtuino SE kde mi z několika čidel odesílá teploty do aplikace a zpětně spíná výstupy.
Jak prosím zapíši do zdrojáku aby mi tyto hodnoty fungovaly stále po 1 s a přitom se ještě odesílaly hodnoty na ThingSpeak kde je zapisovací interval 15s?

Kód: Vybrat vše

/* Virtuino SE Json example: Overview
 * Supported boards: ESP32
 * Created by Ilias Lamprou
 * Updated Feb 27 2019
 * More examples: https://virtuino.com/index.php/virtuino-se/20-virtuino-se-code-examples
 */
// ------ VirtuinoSE V Memory Table

//  V0 memory -> digital output pin LED_BUILTIN
//  V1 memory -> digital output pin 4   Relé1   MAN./AUT.
//  V2 memory -> digital output pin 16  Relé2   ČERPADLO
//  V3 memory -> digital output pin 17  Relé3   BOJLER
//  V4 memory -> digital output pin 5   Relé4   SVĚTLO

//  V5 memory -> input          pin15   Teplota KOTEL
//  V6 memory -> input          pin15   Teplota BOJLER
//  V7 memory -> input          pin15   Teplota VENKU

//  V8 memory -> input          pin18   Sepnuté HDO

#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 15
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature Sensor1(&oneWire);
DallasTemperature Sensor2(&oneWire);
DallasTemperature Sensor3(&oneWire);
#ifndef LED_BUILTIN
#define LED_BUILTIN 2 // pin number is specific to your esp32 board (13)
#endif
#define outPin_1 LED_BUILTIN
#define outPin_2 4
#define outPin_3 16
#define outPin_4 17
#define outPin_5 5
#ifdef ESP8266
 #include <ESP8266WiFi.h>  // Pins for board ESP8266 Wemos-NodeMCU
 //#define inPin_1 D6   // Connect a button to this pin
 #else
 #include <WiFi.h>    // Pins for board ESP32
 #define inPin_1 18    // HDO (noční proud)
 #define myPeriodic 15 //in sec | Thingspeak pub is 15sec
 #endif
    

//------------------- USER SETTINGS ---------------------------------
const char* ssid = "Cermy_2G";           // The name of your WiFi network (SSID)
const char* password = "Boulevard2";           // WIFI network PASSWORD

WiFiServer wifiServer(8000);                  // Virtuino default Server port: 8000

const char* ssid_AP = "Virtuino network";     // Access point network SSID
const char* password_AP = "1234567890";       // Access point network PASSWORD

const char* host = "api.thingspeak.com";       // Informace pro připojení k thingspeak.com
const char* APIkey   = "3MY1HFE6H5O0ZAPI";

#define VIRTUINO_KEY  "1234"      // Virtuino KEY, only the requests that include this key will be acceptable. // disable the line if you don't want to use a key                          

#define V_memory_count 16         // the size of V memory. You can change it to a number <256)
//-------------------------------------------------------------------

float V_memory[V_memory_count];    // This array is synchronized with Virtuino SE V memory

boolean debug = true;              // set this variable to false on the finale code to decrease the request duration

//--- VARIABLES for this demo example
float   my_Variable = 0;
byte inputPinState=0;

                                  
unsigned long timeStrored=0;


//============================================================== connectToWiFiNetwork
void connectToWiFiNetwork(){
  Serial.println("Connecting to "+String(ssid));
  
   // If you don't want to config IP manually disable the next four lines
  IPAddress ip(192, 168, 0, 150);            // where 150 is the desired IP Address   
  IPAddress gateway(192, 168, 0, 254);         // set gateway to match your network
  IPAddress subnet(255, 255, 255, 0);        // set subnet mask to match your network
  WiFi.config(ip, gateway, subnet);          // If you don't want to config IP manually disable this line
 
  WiFi.mode(WIFI_STA);                       // Configure the module as station only.
   WiFi.begin(ssid, password);
   while (WiFi.status() != WL_CONNECTED) {
     delay(500);
     Serial.print(".");
    }
   Serial.println("");
   Serial.println("WiFi connected");
   Serial.println(WiFi.localIP());
}

//================================================================= initAccessPoint
void initAccessPoint(){
  Serial.print("Setting soft-AP ... ");                   // Default IP: 192.168.4.1
   WiFi.mode(WIFI_AP);                                     // Config module as Access point only.  Set WiFi.mode(WIFI_AP_STA); to config module as Acces point and station
   boolean result = WiFi.softAP(ssid_AP,password_AP);      // set the Access point SSID and password
   if(result == true)  {
    Serial.println("Server Ready");
    Serial.println(WiFi.softAPIP());
   }
   else Serial.println("Failed!");
}

//============================================================== setup
//==============================================================
void setup() {
  if (debug) {
    Serial.begin(115200);
    Sensor1.begin();
    while (!Serial) continue;
  }

  //initAccessPoint();               //enable this line to use the esp board as AP  
  connectToWiFiNetwork();      //enable this line to connect the module to your wifi network  
  
  wifiServer.begin();
  
  pinMode(outPin_1, OUTPUT);     
  pinMode(outPin_2, OUTPUT);    
  pinMode(outPin_3, OUTPUT);     
  pinMode(outPin_4, OUTPUT);   
  pinMode(outPin_5, OUTPUT);          
  pinMode(inPin_1, INPUT);      //GPIO18
  pinMode(15, INPUT);           //GPIO15
  }

//============================================================== loop
//==============================================================
void loop() {
  virtuinoRun();        //Necessary function to communicate with Virtuino. Client handler
  
  Sensor1.requestTemperatures(); // Send the command to get temperatures
  float teplota1 = Sensor1.getTempCByIndex(0);
  Serial.println("Temperature for Device 1 is: "+String(teplota1));
  V_memory[5] = teplota1 ;
  
  Sensor2.requestTemperatures(); // Send the command to get temperatures
  float teplota2 = Sensor2.getTempCByIndex(1);
  Serial.println("Temperature for Device 2 is: "+String(teplota2));
  V_memory[6] = teplota2 ;

   Sensor3.requestTemperatures(); // Send the command to get temperatures
  float teplota3 = Sensor3.getTempCByIndex(2);
  Serial.println("Temperature for Device 3 is: "+String(teplota3));
  V_memory[7] = teplota3 ;

  //--- How to control outputs from Virtuino SE

    digitalWrite(outPin_2,HIGH);
    
    //if (V_memory[1]==1) digitalWrite(outPin_2,LOW);      // On Virtuino SE panel add switch to control the pin outPin_1. On the switch settings select the memory V0
    //else digitalWrite(outPin_2,HIGH);

    // (V_memory[2]==1) digitalWrite(outPin_3,LOW);      // On Virtuino SE panel add switch to control the pin outPin_1. On the switch settings select the memory V0
    //else digitalWrite(outPin_3,HIGH);
    if (teplota1>=28) digitalWrite(outPin_3,LOW);
    if (teplota1<=26) digitalWrite(outPin_3,HIGH);

    //if (V_memory[3]==1) digitalWrite(outPin_4,LOW);      // On Virtuino SE panel add switch to control the pin outPin_1. On the switch settings select the memory V0
    //else digitalWrite(outPin_4,HIGH);
    if (teplota2>=28) digitalWrite(outPin_4,LOW);
    if (teplota2<=26) digitalWrite(outPin_4,HIGH);

    if (V_memory[4]==1) digitalWrite(outPin_5,LOW);      // On Virtuino SE panel add switch to control the pin outPin_1. On the switch settings select the memory V0
    else digitalWrite(outPin_5,HIGH);

    
  //--- How to send to Virtuino SE the state of a pin every time it is changed 
    byte pinState = digitalRead(inPin_1);    // read the state of pin 6
    if (pinState!=V_memory[8]) {
      V_memory[8] = pinState;        // Store the pin state to V1. On Virtuino panel add a led to virtual memory V1  
  }


  //--- How to read a variable from Virtuino SE
  // if (my_Variable!=V_memory[2]) {        // Read the V2 memory.  On Virtuino panel add a regulator  to virtual memory V2  
  //     my_Variable==V_memory[21];
  // }
  
  //--- How to send to Virtuino SE sensor values
  // if (millis()-timeStrored>500) {              // read sensor value every 5 seconds. Avoid to use delay on your code
      //V_memory[3] = digitalWrite(15,Sensor1);   // copy the sensor value to V5 (random)
      //V_memory[4] = random(100);                // copy the sensor value to V6
      //V_memory[5] = analogRead(A0);             // copy the A0 value V7
      //timeStrored=millis();                     // On Virtuino panel add value displays or instrument  to virtual memories V3,V4,V5
  //}

  //delay(3000);
}


//============================================================== onCommandReceived
//==============================================================
/* This function is called every time Virtuino SE app sends a request to server 
 * The 'variableIndex' is the V memory index of Virtuino app
 * The 'valueAsText' is the value that has sent from the app
 * If the 'valueAsText" is ? you have to return the value that you want to be displayed on Virtuino panel
 */
 String onCommandReceived(int variableIndex, String valueAsJson){     
   String valueAsText = getJsonValue(valueAsJson,"value");    // read the value from the received Json string 
   if (debug) Serial.println("New value received: V"+String(variableIndex)+"  value="+valueAsText);
 
  if (valueAsText=="?") return  String(V_memory[variableIndex]);   // return the value of the arduino V memory array
  else {
    float value = valueAsText.toFloat();        // convert the value to float. The valueAsText have to be numerical
    V_memory[variableIndex]=value;              // copy the received value to arduino V memory array
  }
  return "";
}


//================== Virtuino Library (included in sketch) ===============
//==============================================================
//==============================================================
/* Only the next functions are nedded to communicate with Virtuino 
 * Avoid to make changes to the code below  
 */


#define WRONG_KEY_MESSAGE  "Wrong Key"  
#define WELLCOME_MESSAGE  "Hello Virtuino"  


//============================================================== virtuinoRun
//==============================================================
  void virtuinoRun(){
  WiFiClient client = wifiServer.available();
  if (client) {
    if (debug) Serial.println("Client connected");
    if ("Client connected") digitalWrite(outPin_2,HIGH);
      else V_memory[1] = 0;
        digitalWrite(outPin_2,LOW);    
    while(!client.available())delay(1);    // Wait until the client sends some data
    String data="";
    while (client.connected()) {
      while (client.available()>0) {
        char c = client.read();
        data+=c;
        if (debug) Serial.write(c);
      }
     client.flush(); 
     if (debug) Serial.println("\nReceived data: "+data);
     String response= getResponseAsJson(data);
      client.print(response);
     if (debug) Serial.println("Response : "+response);
     if ("Response") V_memory[1] = 1 ;
      else (V_memory[1] = 0);
     if (V_memory[1] = 1) digitalWrite(outPin_1,HIGH);    // Zápis Out_1 blik při odpovědi Virtuino
      delay (10) ;
     digitalWrite(outPin_1,LOW);
      client.stop();
    }
     
    if (debug) Serial.println("Client disconnected");
    
  }
 }

//============================================================== prepareResponse
//==============================================================
String getResponseAsJson(String data){
    //---check the KEY
   #ifdef VIRTUINO_KEY 
      String key = getJsonValue(data, "key");
      if (debug) Serial.println("Key="+key);
      if (!key.equals(VIRTUINO_KEY)) return "{\"status\":\"-1\",\"message\":\""+String(WRONG_KEY_MESSAGE)+"\"}";
   #endif

    //---check connection status
    String statusInfo = getJsonValue(data, "status");
    if (debug) Serial.println("statusInfo="+statusInfo);
    if (statusInfo.equals("0")) return "{\"status\":\"2\",\"message\":\""+String(WELLCOME_MESSAGE)+"\"}";
    
    
   String response="{\"status\":\"1\"";
   for (byte i=0;i<V_memory_count;i++){
      // easy way to read a Json object without installing extra json libraries
      String jsonTag="V"+String(i)+"_";
      int pos = data.indexOf(jsonTag);
      if (pos>0) {
        int startPos= data.indexOf("{",pos+1);
        if (startPos>pos) {
          int endPos= data.indexOf("}", startPos+2);
          if (endPos>startPos) {
            String variableAsJson = data.substring(startPos,endPos+1);
            String variableValue=onCommandReceived(i,variableAsJson);
           if (variableValue.length()>0) response+=",\""+jsonTag+"\":{\"value\":\""+urlencode(&variableValue)+"\"}";
          }
        }
      }
      
   } //for
   response+="}";
  return response;
}

//==============================================================
// easy way to read a Json text value without installing extra json libraries
  String getJsonValue(String jsonAsText, String jsonTag){
    int pos = jsonAsText.indexOf(jsonTag);
    if (pos>0) {
      int startPos=jsonAsText.indexOf(":\"",pos);
      int lastPos = jsonAsText.indexOf("\"",startPos+2);
      String value=jsonAsText.substring(startPos+2,lastPos);
      value=urldecode(&value);
      if (lastPos>startPos) return value;
    }
    return "";
 }


  //=================== ENCODE - DECODE Library (included in sketch) ==========
  //=================================================================
  
  //================================================================ urldecode
String urldecode(String* str){
   String encodedString="";
    char c;
    char code0;
    char code1;
    for (int i =0; i < str->length(); i++){
        c=str->charAt(i);
      if (c == '+'){
        encodedString+=' ';  
      }else if (c == '%') {
        i++;
        code0=str->charAt(i);
        i++;
        code1=str->charAt(i);
        c = (h2int(code0) << 4) | h2int(code1);
        encodedString+=c;
      } else{
         encodedString+=c;  
      }
      yield();
    }
    
   return encodedString;
}
//================================================================ urlencode
String urlencode(String* str){
   String encodedString="";
    char c;
    char code0;
    char code1;
    char code2;
    for (int i =0; i < str->length(); i++){
      c=str->charAt(i);
      if (c == ' '){
        encodedString+= '+';
      } else if (isalnum(c)){
        encodedString+=c;
      } else{
        code1=(c & 0xf)+'0';
        if ((c & 0xf) >9){
            code1=(c & 0xf) - 10 + 'A';
        }
        c=(c>>4)&0xf;
        code0=c+'0';
        if (c > 9){
            code0=c - 10 + 'A';
        }
        code2='\0';
        encodedString+='%';
        encodedString+=code0;
        encodedString+=code1;
        //encodedString+=code2;
      }
      yield();
    }
    return encodedString;
}
//================================================================ h2int
unsigned char h2int(char c){
    if (c >= '0' && c <='9'){
        return((unsigned char)c - '0');
    }
    if (c >= 'a' && c <='f'){
        return((unsigned char)c - 'a' + 10);
    }
    if (c >= 'A' && c <='F'){
        return((unsigned char)c - 'A' + 10);
    }
    return(0);
}

Cermy
Příspěvky: 18
Registrován: 01 úno 2019, 11:23

Re: ESP32, Virtuino SE a ThingSpeak

Příspěvek od Cermy » 20 bře 2020, 14:00

V aplikaci to pak vypadá třeba nějak takto.
Ale kvůli grafům a dalšímu ještě potřebuji ukládat na ThingSpeak
Přílohy
VirtSE.PNG

DavidO
Příspěvky: 862
Registrován: 01 kvě 2013, 21:27

Re: ESP32, Virtuino SE a ThingSpeak

Příspěvek od DavidO » 21 bře 2020, 19:32

Udělej si funkci, která ty data pošle na ThingSpeek a do loop si připiš kód, který zkontroluje, jestli čas od posledního poslání je > 15s. Pokud ano, zavolá tu funkci na poslání a zapamatuje si aktuální čas, pokud ne, neudělá nic.

Cermy
Příspěvky: 18
Registrován: 01 úno 2019, 11:23

Re: ESP32, Virtuino SE a ThingSpeak

Příspěvek od Cermy » 21 bře 2020, 20:44

A poradíš mi jak to udělám? 😄

DavidO
Příspěvky: 862
Registrován: 01 kvě 2013, 21:27

Re: ESP32, Virtuino SE a ThingSpeak

Příspěvek od DavidO » 22 bře 2020, 11:44

Udělej si funkci na poslání, něco jako:

Kód: Vybrat vše

void posliToNaThingSpeek(void) 
{
	perform("Send spike");
	echo("Spike sent.");
}
pak si nadeklaruj globální proměnnou, ve které budeš držet čas posledního poslání:

Kód: Vybrat vše

unsigned long naposled;
a pak na konec funkce loop přidej

Kód: Vybrat vše

	if ( (millis()-naposled) > myPeriodic * 1000 ) 
	{
		naposled = millis();
		posliToNaThingSpeek();
	}

Odpovědět

Kdo je online

Uživatelé prohlížející si toto fórum: Žádní registrovaní uživatelé a 2 hosti