Daten aus einem Webserver auslesen

Hallo

Ich möchte aus einem Webserver der auf einem ESP32 Microcontroller läuft daten in den HC3 einlesen.

Hier der Code vom ESP32 aus einer Beispielbibliotek

#include <WiFi.h>
#include <ESPmDNS.h>
#include <ArduinoOTA.h>
#include <WebServer.h>

const char* ssid = "xxxxxxxxxxx";
const char* password = "xxxxxxxxxx";

WebServer server(80);

const char* www_username = "ADMIN";
const char* www_password = "12345";

void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  if (WiFi.waitForConnectResult() != WL_CONNECTED) {
    Serial.println("WiFi Connect Failed! Rebooting...");
    delay(1000);
    ESP.restart();
  }
  ArduinoOTA.begin();

  server.on("/", []() {
    if (!server.authenticate(www_username, www_password)) {
      return server.requestAuthentication();
    }
    server.send(200, "text/plain", "Login OK");
  });
  server.begin();

  Serial.print("Open http://");
  Serial.print(WiFi.localIP());
  Serial.println("/ in your browser to see it working");
}

void loop() {
  ArduinoOTA.handle();
  server.handleClient();
}

Im Brouser funktioniert das, der ESP32 meldet sich im Netz an und erhält eine IP.
Rufe ich die IP auf, so werde ich zur Eingabe von Name und Passwort gefragt.
Habe ich das richtig angegeben so erhalte ich die Meldung „Login OK“
So weit so Gut.
Jetzt würde ich gerne dieses „Login OK“ mit meinem HC3 auslesen.
Dafür benötige ich eine QA mit den zugehörigen HTTP Aufrufen.
Wenn da einer ein Beispiel hat währe ich Ihm sehr Dankbar.

Der Hintergrund ist, das ich gerne Analoge Werte und Digitale Werte mit dem ESP32 auslesen möchte, die dann im HC3 weiterverarbeitet werden sollen.
Das ist erst der Anfang danach soll es genau umgekehrt gehen.
Ziel ist es in beide Richtungen Daten zu senden.
JSON hin und her.
Aber alles nach und nach und nicht gleich alles auf einmal das muss erlernbar und nach vollziehbar sein.
Schritt für Schritt währe doch mal wert hier gepostet zu werden.
Auch nach Intensiver Suche habe ich entweder große Brocken gefunden die nicht so einfach nachzuvollziehen sind oder Sachen die nicht Passten HC2, RasperriPi, Datenbanken usw.
Ich denke mal damit kann man so viel basteln da haben sicher viele Interesse dran.
Nuir mal so am Rande, ein solcher Käfer kostet ca. 8,-€ und hat so viele Anschlüsse und Kommunikationsmöglichkeiten da geht die Post ab.

Ein Beispiel von Unendlich vielen !
Getting Started with the ESP32 Development Board | Random Nerd Tutorials

Gruss Frank

Hallo Frank,

wie Du ja weißt, habe ich kein HC3.
Aber soweit mit bekannt, können sowohl das HC3 als auch das ESP32 MQTT, vielleicht ist das eine Richtung, die sich’s zu verfolgen lohnt…?

Grüße Heiko

Ja da hast du recht.
Für MQTT benötigt man aber einen MQTT-Broker wie z.B Mosquito.
Also noch eine Kiste die aufgebaut, Programmiert usw. werden muss.
Das geht auch mit den Komponenten ESP32 und HC3 ohne so etwas.
Ich habe da schon ein Beispiel einer Wetterstation die an einem Adruino angeschlossen ist gesehen und genau so mit einem HC3 kommuniziert.
Die Software wahr aber riesig und auf dem HC3 genau so gewaltig.
Also für einen Einsteiger zu Mächtig um zu lernen.
Gruss Frank

Hmmm…, war, wie gesagt, nur von der Seitenlinie reingerufen… :wink:

@heikoh
Hallo
Ich bin auf dem Weg und schon einiges erreicht.
Schwierig ist nur das der EPS32 absolutes Neuland ist.
Hardware ist kein Thema, nur c/c++ uns alles was so an Library usw dahinter hängt schon.
Die Gemeinde ist noch Mächtiger als die Smart-Home Gemeinde.
Ab und an trifft man mal einen Bekannten Namen.
Ich denke mal das ist eine Bastelgemeinde Mikrocontroller und Smart-Home sowie Elektronik.
Da Basteln noch wesentlich mehr Leute dran rum.
LUA „einigermaßen“ zu beherrschen ist da schon hilfreich.
Sehr viel Neuland, noch tiefer als HC3 mit LUA.
Aber es wird.
HC3 meldet sich schon an und erhält Daten.
Json sei Dank das da keine Bastellösung nötig ist.
Wenn ich das Teil fertig habe Poste ich es mal hier ist sicher für einige Interessant da der Einstieg 8,-€ sehr klein ist.
USB anstecken, Software saugen und lesen, lesen lesen (Doku ohne Ende ziemlich verwirrend).
Was beim HC3 fehlt ist da im Überfluss vorhanden.
Gruss Frank

Hallo Frank,

das klingt doch gut! :+1:
Dümmer wird man dabei auch garantiert nicht.
Es gibt wirklich VIELE Möglichkeiten, die sich aus den verschiedensten Microcontrollern, Einplatienencomputern und diversester Peripherie ergeben. (M5Stack ist auch ein sehr interessantes Thema)
Massentauglich wird das alles trotzdem nicht werden, viele können und/oder wollen nicht so tief in solche Themen einsteigen.
Welches konktretes Projekt hast Du grad?
Da ich, wie Du ja weißt, momentan homees betreibe, habe ich mich ein wenig näher mit ioBroker und Node RED befasst und so stößt man schnell in Regionen vor in denen man endlich wirklich smarte Lösungen entwickeln kann. Wie auch schon erwähnt, will ich dieses Jahr eine kleine PV-Anlage errichten und diese natürlich in die homees einbinden und so Dinge wirklich sinnvoll „schalten“.
Das Einbinden einer anständigen Wetterstation, Mäh- und Saugrobotern, das Auslesen meines Stromzählers sind dabei nur der Anfang. Um ein E-Auto wird man in absehbarer Zeit auch nicht herum kommen, es wäre doch smart, dieses nur dann zu laden, wenn die PV-Anlage genügend produziert und man nicht noch überteuerten Strom aus dem Netz dafür zieht, und und und…
Sprachsteuerung ist so, auch ohne Staasi 4.0, möglich. :wink:
Die Grenzen stecken da eher die eigene Phantasie und die eigenen Skills.
Viele „Smarthomer“ scheinen ja aber zufrieden mit den Standardmöglichkeiten, wie Licht ein/aus, Heizung und Rollläden steuern, etc. - das meine ich gar nicht böse, wenn der Bedarf nicht da ist, ist er halt nicht da…

Viel Erfolg, Grüße Heiko

@heikoh
Ja da hast du recht.
Bei mir ist es so, das die Analoge Auflösung der Produkte von Fibaro usw. mir nicht ausgereicht haben.
Weiterhin konnte mir keiner sagen wie viele Bit und welche Genauigkeit, Impedanz usw. die Teile haben.
Das alles ist sehr schwammig oder gar nicht vorhaben.
Somit habe ich eine Andere Lösung gesucht und mit dem ESP32 auch gefunden.
Der hat von Hause aus 12 Bit und dafür bekommt man auch Zubehörteile bis 14,16,24Bit.
Damit ist man bestens Ausgerüstet.
Technische Daten sind alle vorhanden und auch Beispielprogramme und Librarys gibt es zu Hauf.
Die Daten im ESP32 vor zu verarbeiten was Filter usw. betrifft ist auch kein Thema.
Da hast du einen kompletten C/C++ zur Verfügung und auch Andere Programmiersprachen sind da.
Pyton, LUA, usw.
Dazu kommt noch das Alles sehr Preiswert zu bekommen ist.
Mittlerweile läuft mein Webserver, die Daten sind im HC3, das QA läuft alles easy aber ohne die Hilfe von Anderen hätte ich noch länger benötigt.
Ein Forum mit Leuten die Hilfsbereit sind ist Gold wert.
Ich werde das Projekt noch vorstellen wenn es mal vorzeigbar ist und alle Macken weg sind.
Alles was du oben beschrieben hast kannst du mit dem Teil in Kombination mit dem HC3 erledigen.
Mit dem homee ist das meines Wissens nach nicht möglich da du keinen LUA oder etwas vergleichbares hast.
Du musst Daten über das WLAN/LAN einlesen und ausgeben können dann ginge das.
Gruss Frank

Doch, geht alles. :wink:
Aber eben wie auch beim HC2/3 nicht ohne externe Helferlein…

Hallo

So nun habe ich mein Problem mit dem Analogen Eingängen gelöst.

Zur Vorgeschichte :

Ich wollte 2 Helligkeitssensoren die ich auf dem Dach montiert hatte zum HC3 übermitteln.
Dabei habe ich festgestellt das die Analogen Eingänge von Fibaro nicht für
Messtechnik zu gebrauchen sind.

Meine Lösung :

Ich benutze ein ESP32-Board und übertrage die Daten über mein Heimnetz zum HC3.
Dazu war es nötig einen QA zu erstellen, der mittel HTTP Get die Daten vom ESP32 von einem Webserver abholt.
Der QA sollte einzelne Geräte abbilden (Child´s) um das arbeiten damit zu erleichtern.

Hardware
ESP-32 Dev Kit C bei az-delivery.de – AZ-Delivery (az-delivery.de)

0,96 Zoll I2C OLED Display – AZ-Delivery (az-delivery.de)

DHT22 Temperatur- und Luftfeuchtigkeitssensor gesucht? – AZ-Delivery (az-delivery.de)

ADS1115 ADC Modul 16bit 4 Kanäle für Arduino und Raspberry Pi – AZ-Delivery (az-delivery.de)

Sowie ein ein Handyladegerät mit mini-USB zur Stromversorgung.

(PS der Lieferant konnte hier am besten eingebunden werden, keine Schleichwerbung)

Arbeitsweise:

Beim Laden des QA´s erzeugt er mehrere Child´s eines für jede Info.

Wie hier zu sehen :


Bild

Der QA verbindet sich mittels HTTP mit dem Webserver und fragt die bereitgestellten Daten ab.
Weiterhin übermittelt er 2 Daten um 2 LED´s im wechseln aufleuchten zu lassen,
damit man sehen kann ob alles OK ist mit dem Datenverkehr (Die müssen aber nicht sein).

Der Webserver auf dem ESP32 holt sich die Temperatur und Luftfeuchtigkeit von einem DHT22,
weiterhin holt er sich 2 Analoge Werte Aussenhellichkeit High (0-100.000lx)
und Low (0-10.000lx) und bereitet diese für das versenden zum HC3 vor.
Dazu müssen die Analogen Eingänge noch angepasst werden damit diese auch vom ADC verarbeitet werden können.
Die Eingangsspannung ist 2,048V für 10.000lx sowie für 100.000lx.
Weiterhin muss die Datenaufbereitung noch Kalibriert werden das geschieht
im ESP-Code „void analogwerte_holen()“ mittels Umrechnung.

Alle Werte die zum HC3 übermittelt wurden werden auch auf einem Display angezeigt und dienen zur Kontrolle.
Damit werden dann auch die LED´s überflüssig.

Hier ist die Hardware zu sehen :

Bild

Links oben die beiden Dioden, in der Mitte unten der ADC, und rechts unten das Display.
Oben rechts dar DHT22 und Oben in der Mitte 2 Drehwiderstände zur Analogsimulation.

Auf dem Unteren Board ist der ESP32 zu sehen auf dem der Webserver läuft.

Die Anschlüße der einzelnen Geräte stehen im Code des ESP32 und können dort auch angepasst werden.

Der ESP32 wird in C/C++ Programmiert und für Leute die schon LUA beherschen ist das eigendlich kein
Großer Aufwand sich da einzuarbeiten.
Als Lektüre habe ich mir das Buch hier gekauft :

Im Laufe meiner Einarbeitung habe ich aber schnell festgestellt das ein PDF besser ist :

Ich füge hier beide Cods an einmal der QA und einmal der ESP32 Code.

Kommt in der nächsten Mitteilung damit das nicht zu viel wird.

Grüße aus dem Sauerland
Frank

So hier kommt der QA

Einstellungen

--[[
                       ESP32_Dachboden QA
                       ===================
Mit Dankender Hilfe von @tinman und @SmartHomeEddy aus dem Fibaro Forum
Das QA beruht auf der Vorarbeit von @SmartHomeEddy und dessen Air-Quality Sensor´s
Alles hier zu finden https://forum.fibaro.com/

Der ESP32 liest einen DHT11 aus und gibt die Temperatur und die Luftfeuchtigheit an dieser
QA weiter.
Weiterhin liest der über einen ADS1115 2 Analoge Werte von Lichtsensoren ein.
1 x 0-10.000lx und 1 x 0-100.000lx.
Die Werte werden im ESP32 vorverarbeitet und stehen als direkter Wert zur Verfügung.
Die Datenkommunikation findet über WLAN per Json-Datenpacket statt.
Der ESP meldet sich hierbei beim Router an und holt sich eine IP-Adresse.
Diese Adresse muss bei den Variablen angegeben werden.
Das WLAN-Passwort wie auch der SSID vom Router werden im Code des ESP32 angegeben.
Daraufhin holt sich der QA Zyklisch (Variabel intervall), die Daten vom ESP32 und stellt die Daten über die Childs dem HC3
zur Weiterverarbeitung zur Verfügung. 
Diesen Vorgang kann aber auch mit der Taste "Refresh" aktiviert werden.

Die Child´s werden bei der Initialisierung automatisch angelegt.

Eine Erweiterung ist ohne weiteres möglich da der ESP noch einen Haufen von Ein- und Ausgängen hat 
ist da noch so vieles möglich.

Die beiden Ausgänge out_1 und out_2 dienen nur zur funktionskontrolle und blinken auf dem ESP32 im wechsel.
Dieser Wechel wird von diesem QA ausgelöst, per Json an den ESP32 gesendet und dort mit der Roten und Grünen LED angezeigt.

Version   : ESP32_Dachboden V1.0 
Datum     : 02.04.2021
Ersteller : Frank Berges

--]]

------------------------- Childs anlegen -------------------------
------------------------------------------------------------------
class 'PolutionSensorTemp'(QuickAppChild)
function PolutionSensorTemp:__init(dev)
  QuickAppChild.__init(self,dev)
  --self:trace("ESP32_Dachboden initiated, deviceId:",self.id)
end
function PolutionSensorTemp:updateValue(data,userID) 
  --self:debug("ESP32 Temperature: ",jsonTable.sensordatavalues[1].value))
  self:updateProperty("value",tonumber(jsonTable.sensordatavalues[1].value))
end

class 'PolutionSensorHumid'(QuickAppChild)
function PolutionSensorHumid:__init(dev)
  QuickAppChild.__init(self,dev)
  --self:trace("ESP32 Humidity sensor initiated, deviceId:",self.id)
end
function PolutionSensorHumid:updateValue(data,userID) 
  self:updateProperty("value",tonumber(jsonTable.sensordatavalues[2].value)) 
end

class 'PolutionSensorLoLight'(QuickAppChild)
function PolutionSensorLoLight:__init(dev)
  QuickAppChild.__init(self,dev)
  --self:trace("ESP32 Lo-Aussenlichtsensor initiated, deviceId:",self.id)
end
function PolutionSensorLoLight:updateValue(data,userID) 
  self:updateProperty("value",tonumber(jsonTable.sensordatavalues[3].value)) 
  self:updateProperty("unit", "lx")
end

class 'PolutionSensorHiLight'(QuickAppChild)
function PolutionSensorHiLight:__init(dev)
  QuickAppChild.__init(self,dev)
  --self:trace("ESP32 Hi-Aussenlichtsensor initiated, deviceId:",self.id)
end
function PolutionSensorHiLight:updateValue(data,userID) 
  self:updateProperty("value",tonumber(jsonTable.sensordatavalues[4].value)) 
  self:updateProperty("unit", "lx")
end
------------------------------------------------------------------

-------------------- Childs mit Werten füllen --------------------
------------------------------------------------------------------
local function getChildVariable(child,varName)
  for _,v in ipairs(child.properties.quickAppVariables or {}) do
    if v.name==varName then return v.value end
  end
  return ""
end
------------------------------------------------------------------

---------- Childs anlegt ? Wenn nein anlegen vorbereiten ---------
------------------------------------------------------------------
function QuickApp:setupChildDevices()
  local cdevs = api.get("/devices?parentId="..self.id) or {} -- Pick up all Child Devices
  function self:initChildDevices() end -- Null function, else Fibaro calls it after onInit()...

  if #cdevs == 0 then -- If no Child Devices, create them
      local initChildData = { 
        {className="PolutionSensorTemp", name="Temperatur", type="com.fibaro.temperatureSensor", value=0, unit="°C"},
        {className="PolutionSensorHumid", name="Luftfeuchte", type="com.fibaro.humiditySensor", value=0, unit="%"},
        {className="PolutionSensorLoLight", name="Lo-Aussenlicht", type="com.fibaro.lightSensor", value=0, unit="lx"},
        {className="PolutionSensorHiLight", name="Hi-Aussenlicht", type="com.fibaro.lightSensor", value=0, unit="lx"},
      }
    for _,c in ipairs(initChildData) do
      local child = self:createChildDevice(
        {name = c.name,
          type=c.type,
          value=c.value,
          unit=c.unit,
          initialInterfaces = {},
        },
        _G[c.className] -- Fetch class constructor from class name
      )
      child:setVariable("className",c.className)  -- Save class name so we know when we load it next time
    end   
  else 
    for _,child in ipairs(cdevs) do
      local className = getChildVariable(child,"className") -- Fetch child class name
      local childObject = _G[className](child) -- Create child object from the constructor name
      self.childDevices[child.id]=childObject
      childObject.parent = self -- Setup parent link to device controller 
    end
  end
end
------------------------------------------------------------------


-------------------- Childs mit Werten füllen --------------------
------------------------------------------------------------------
local function getChildVariable(child,varName)
  for _,v in ipairs(child.properties.quickAppVariables or {}) do
    if v.name==varName then return v.value end
  end
  return ""
end
------------------------------------------------------------------

-------------------- Refresch Taste abfragen ---------------------
------------------------------------------------------------------
function QuickApp:button1Event()
  self:updateView("button1", "text", "Please wait...")
  self:getData()
  fibaro.setTimeout(5000, function() -- Pause for [timeout] seconds (default 5 seconds)
    self:updateView("button1", "text", "Refresh")
  end)
end
------------------------------------------------------------------

---------------------- Labelfeld beschreiben ---------------------
------------------------------------------------------------------
function QuickApp:updateLabels() -- Update labels
  self:logging(3,"updateLabels")
  labelText = "Measurement: "..os.date("%d-%m-%Y %X", os.time()-jsonTable.age) .."\n" .."\n"
  labelText = labelText .."Temperature      : " ..jsonTable.sensordatavalues[1].value .." °C" .."\n"
  labelText = labelText .."Humidity         : " ..jsonTable.sensordatavalues[2].value .." %" .."\n"
  labelText = labelText .."Aussenlicht Low  : " ..jsonTable.sensordatavalues[3].value .." lx" .."\n" 
  labelText = labelText .."Aussenlicht Hi   : " ..jsonTable.sensordatavalues[4].value .." lx" .."\n" .."\n"
  labelText = labelText .."WiFi signal      : " ..jsonTable.sensordatavalues[5].value .." dBm" .."\n"
  labelText = labelText .."Output 1         : " ..jsonTable.out_1 .."\n"
  labelText = labelText .."Output 2         : " ..jsonTable.out_2 .."\n".."\n"
  labelText = labelText .."Firmwhareversion : " ..jsonTable.software_version 
  self:logging(2,"labelText: " ..labelText)
  self:updateView("label1", "text", labelText)
end
------------------------------------------------------------------

----------------------- Daten im HC3 Update ----------------------
------------------------------------------------------------------
function QuickApp:updateProperties() -- Update properties
  self:logging(3,"updateProperties")
  self:updateProperty("log", os.date("%d-%m-%Y %X", os.time()-jsonTable.age) .."\nWiFi " ..jsonTable.sensordatavalues[5].value .."dBm")
end
------------------------------------------------------------------

------------------------ Debuging & Level ------------------------
------------------------------------------------------------------
function QuickApp:logging(level,text) -- Logging function for debug
  if tonumber(debugLevel) >= tonumber(level) then 
      self:debug(text)
  end
end
------------------------------------------------------------------

--------------------- Alle Variabel einholen --------------------
------------------------------------------------------------------
function QuickApp:getQuickAppVariables() -- Get all variables 
  local ipAddress = self:getVariable("ipAddress")
  local path = "/data.json" -- Default path is /data.json
  interval = tonumber(self:getVariable("interval")) 
  httpTimeout = 5 -- Default value for http Timeout
  userID = tonumber(self:getVariable("userID")) 
  debugLevel = tonumber(self:getVariable("debugLevel"))
  local icon = tonumber(self:getVariable("icon")) 

  -- Check existence of the mandatory variables, if not, create them with default values
  if ipAddress == "" or ipAddress == nil then
    ipAddress = "192.168.2.82" -- Default IP address is 192.168.2.82
    self:setVariable("ipAddress",ipAddress)
    self:trace("Added QuickApp variable ipAddress")
  end
  if interval == "" or interval == nil then
    interval = "146" -- Default interval is 146, normally the sensor renews its readings every 145 seconds 
    self:setVariable("interval",interval)
    self:trace("Added QuickApp variable interval")
    interval = tonumber(interval)
  end
  if userID == "" or userID == nil then 
    userID = "2" -- Default userID
    self:setVariable("userID",userID)
    self:trace("Added QuickApp variable iserID")
    userID = tonumber(userID)
  end
  if debugLevel == "" or debugLevel == nil then
    debugLevel = "1" -- Default value for debugLevel response in seconds
    self:setVariable("debugLevel",debugLevel)
    self:trace("Added QuickApp variable debugLevel")
    debugLevel = tonumber(debugLevel)
  end
  if icon == "" or icon == nil then 
    icon = "0" -- Default icon
    self:setVariable("icon",icon)
    self:trace("Added QuickApp variable icon")
    icon = tonumber(icon)
  end
  if icon ~= 0 then 
    self:updateProperty("deviceIcon", icon) -- set user defined icon 
  end
  url = "http://" ..ipAddress ..path
end
------------------------------------------------------------------

----------------- Daten vom ESP32 abholen/senden -----------------
------------------------------------------------------------------
function QuickApp:getData()
  self:logging(3,"Start getData")
  self:logging(2,"URL: " ..url)
  self.httpClient:request(url, 
    {
      options={
          headers = {
              Accept = "data/json",
              data = self:sendeDaten_zusammenstellen() -- Daten zum ESP32 senden
           },
           method = 'GET'
       },   
      success = function(response) --Daten vom ESP32 holen
      
      self:logging(3,"response status: " ..response.status)
      self:logging(3,"headers: " ..response.headers["Content-Type"])
      self:logging(2,"Response data: " ..response.data)

        if (response.status >= 200 and response.status < 300) then
            --self:debug("OK: " .. response.data)
            if response.data == nil or response.data == "" or response.data == "[]" then -- Check for empty result
                self:warning("Momentan Keine Daten vom ESP32_Dachboden")
            else --Gültige Daten erhalten 
                jsonTable = json.decode(response.data) -- JSON decode from api to lua-table
                --jsonTable = json.encode(response.data) -- JSON Kontrolle zeigt was alles im String ist
                print("jsonTable =",jsonTable)
                self:updateLabels() -- Anzeige der Labels
                self:updateProperties()

                -- Daten vom ESP32 an die Childs übergeben
                for id,child in pairs(self.childDevices) do 
                    child:updateValue(data,userID) 
                end

            end
        end
      end,
      error = function (error)
        self:error("error: " ..json.encode(error))
        self:updateProperty("log", "error: " ..json.encode(error))
      end  
    }) 
end --function QuickApp:getData
------------------------------------------------------------------

------------- Daten für ESP32 zum senden vorbereiten -------------
------------------------------------------------------------------
function QuickApp:sendeDaten_zusammenstellen()
    --Gewünschte  Ausgangszustände des ESP32 einstellen
    if out_1 == 0 then
        out_1 = 1
        out_2 = 0
    else
        out_1 = 0
        out_2 = 1
    end

    -- json-Datenstring für das Versenden zusammen bauen
    print("Time = ",os.date("%H:%M:%S", os.time()))
    local daten = 
        {
            time = os.date("%H:%M:%S", os.time()),
            out_1 = out_1,
            out_2 = out_2
        }
    self:logging(3,"sende-json : " ..json.encode(daten))

 return json.encode(daten)
end
------------------------------------------------------------------


--******************* QuickApp Initialisieren ********************
------------------------------------------------------------------
function QuickApp:onInit()
    self:debug("onInit")

    -- Setup-Phase
    out_1 = 0
    out_2 = 0
    self:getQuickAppVariables()
    self.looptime = interval * 1000
    self.httpClient = net.HTTPClient()    
    self:setupChildDevices()
    self:getQuickAppVariables() 
    
    -- Dauerlaufschleife
    --******************
    local function loop()
        self:getData() --Vom ESP32 Daten holen und dahin senden
        setTimeout(loop, self.looptime)
    end
    loop()
    
end
------------------------------------------------------------------

--EOF

ESP32-Dachboden(3).fqa (15,0 KB)

So und nun der ESP-Code !

Erstellt mit :

/*
* ESP32 Webserver für den Datenaustausch zwischen ESP32 <--> Fibaro-HC3
* Werte wie Themperatur, Luftfeuchtigkeit einholen, 2 xAnalogen-In
* sowie 2 Ausgänge in einem Json-String versenden.
* 
* Anzeige der Übermittelten und endfangenen Daten mittels OLED-128x64-i2c 
* Analoge Werte werden mit 16Bit gelesen und weiterverarbeitet
* 
* Die erfolgreiche Datenübermittlung zum HC3 wird mit dem Wechel 
* der 2 LED´2 out_1 und out_2 angezeigt.
* 
* Angegeben werden müßen für den Router
* ssid = "Geheim"  
* password = "Super Geheim"
* 
* 
* Erstellt am 02.04.2021
* F.Berges
* 
*/
// Load librarys
//-----------------------------------------------------------------------------
#include <WiFi.h>
#include <Wire.h>
#include <DHTesp.h>
#include <ArduinoJson.h>
#include <Adafruit_ADS1X15.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_Sensor.h>
#include "time.h"
//-----------------------------------------------------------------------------

// Vorbereitung des DHT-Sensors
//-----------------------------------------------------------------------------
#define DHT22_PIN 18  // Pin für den DHT22-Sensor
//DHT Sensor;
DHTesp dht;           // Objekt anlegen
//-----------------------------------------------------------------------------

// Vorbereitung des ADS1115 A/D Wandler 16Bit
//-----------------------------------------------------------------------------
Adafruit_ADS1115 ads;     /* Use this for the 16-bit version */
int16_t adc0, adc1, adc2, adc3;
//-----------------------------------------------------------------------------

// Vorbereitung des SSD1306 display I2C
//-----------------------------------------------------------------------------
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
//-----------------------------------------------------------------------------

// Vorbereitung des Timeserver zugriffs
//-----------------------------------------------------------------------------
const char* ntpServer = "pool.ntp.org";
const long  gmtOffset_sec = 3600;
const int   daylightOffset_sec = 3600;
//-----------------------------------------------------------------------------

// Vorbereitung der Ausgänge
//-----------------------------------------------------------------------------
// Variabeln für die Ausgänge
#define ausgang_1 25 // wird von HC3 gesteuert
#define ausgang_2 26 // wird von HC3 gesteuert
//-----------------------------------------------------------------------------

//Web Daten für den Router
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
const char* ssid = "Geheim"; 
const char* password = "Super-Geheim";
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------

//Sendedaten an HC3
//-----------------------------------------------------------------------------
String Software_Version = "ESP32_Dachboden_V1.0"; // Softwareversion
int age = 0;
float DHT11_T = 0;                                // Temperatur 
float DHT11_H = 0;                                // Luftfeuchte
long BB_H = 0;                                    // Sonnenlicht 0-100.000lx
long BB_L = 0;                                    // Sonnenlicht 0-10.000lx
String sende_json = "";                           // Sendedaten an den HC3
//-----------------------------------------------------------------------------

//Gegentacktblinker
//-----------------------------------------------------------------------------
byte out_1 = 0;
byte out_2 = 0;
//-----------------------------------------------------------------------------

//Für die Displayanzeige Systemzeit
//-----------------------------------------------------------------------------
long myTimer = 0;
long myTimeout = 1000; //Blinkzeit ein & aus
//-----------------------------------------------------------------------------

//Webserver vorbereiten
//-----------------------------------------------------------------------------
// Set web server port number to 80
WiFiServer server(80);
// Variable to store the HTTP request
String header;
//-----------------------------------------------------------------------------

// Timeout definieren
//-----------------------------------------------------------------------------
// Current time
unsigned long currentTime = millis();
// Previous time
unsigned long previousTime = 0; 
// Define timeout time in milliseconds (example: 2000ms = 2s)
const long timeoutTime = 2000;
//-----------------------------------------------------------------------------

//******************** SETUP ********************
//-----------------------------------------------------------------------------

void setup() 
  {
    //DHT Start
      Serial.println("Start DHT22 sensor!");
      dht.setup(DHT22_PIN, DHTesp::AUTO_DETECT); // DHTesp::DHT22

    //ADS1115
      ads.setGain(GAIN_ONE);        // 1x gain   +/- 4.096V  1 bit = 2mV      0.125mV
      ads.begin();
      
    //SSD1306 display I2C
      if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) 
        {
          Serial.println(F("SSD1306 allocation failed"));
          for(;;);
        }
      delay(2000);
      display.clearDisplay();
      display.setTextColor(WHITE);
  
    //Zeit von Zeitserver holen
      //connect to WiFi
      Serial.printf("Connecting to %s ", ssid);
      WiFi.begin(ssid, password);
      while (WiFi.status() != WL_CONNECTED) 
        {
          delay(500);
          Serial.print(".");
        }
      Serial.println(" CONNECTED für Timeserver");
      //init and get the time
      configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
      
      //disconnect WiFi
      WiFi.disconnect(true);
       
    // Bestimmen der pin-Funktion
      pinMode(ausgang_1, OUTPUT);
      pinMode(ausgang_2, OUTPUT);
      pinMode(ausgang_3, OUTPUT);
    
    Serial.begin(115200);

    // Connect to Wi-Fi network with SSID and password
    Serial.print("Connecting to Network:");
    Serial.println(ssid);
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) 
      {
      delay(500);
      Serial.print(".");
      }
    // Print the connnect IP address and start web server
    Serial.println("");
    Serial.println("Connected. The device can be found at IP address: ");
    Serial.println(WiFi.localIP());
    server.begin();
  }
//-----------------------------------------------------------------------------

//******************** Hauptprogramm ********************
//-----------------------------------------------------------------------------
void loop()
  {
    WiFiClient client = server.available();   // Listen for incoming clients
    if (client) 
      { // If a new client connects,
        currentTime = millis();
        previousTime = currentTime;
        Serial.println("New Client found für");          // print a message out in the serial port
        String currentLine = "";                      // make a String to hold incoming data from the client
        while (client.connected() && currentTime - previousTime <= timeoutTime) 
          { // loop while the client's connected
          currentTime = millis();
          if (client.available()) 
          
            { // if there's bytes to read from the client,
              char c = client.read();                // read a byte, then
              Serial.write(c);                       // print it out the serial monitor
              header += c;

            if (c == '\n') 
              { // if the byte is a newline character
                // if the current line is blank, you got two newline characters in a row.
                // that's the end of the client HTTP request, so send a response:
              if (currentLine.length() == 0) 
                {
                  // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
                  // and a content-type so the client knows what's coming, then a blank line:
                  client.println("HTTP/1.1 200 OK");
                  client.println("Content-Type: data/json");
                  client.println("Connection: close");
                  client.println();
                  client.println();

                  // Vorbereiten der Sendedaten
                  // einholen der Temperatur und Luftfeuchtigheitswerte
                  temp_feucht_werte_holen();
                  // Einholen der Aussenlichtwerte
                  analogwerte_holen();
                  // Anzeige der Werte im Display
                  display_ausgabe();
                  // send sensor data in JSON format    
                  uebergabestring();            //Zusammenbauen des json Strings
                  client.println(sende_json); //Senden des Strings

                  // Break out of the while loop
                  break;
                } 
              else 
                { // if you got a newline, then clear currentLine
                  currentLine = "";
                }
              } 
            else if (c != '\r') 
              {  // if you got anything else but a carriage return character,
                currentLine += c;      // add it to the end of the currentLine
              }
            }
          }
          
        // Daten im Hader verarbeiten
        reaktionaufanfrage(header);
        //Header Löschen
        header = "";
        
        // Close the connection
        client.stop();
        Serial.println("Client disconnected.");
        Serial.println("");
      }
      display_systemzeit();
  } // End Loop
//-----------------------------------------------------------------------------

//--------- Aus dem Inputstring die Json Daten holen und verarbeiten ----------
//-----------------------------------------------------------------------------
String reaktionaufanfrage(String input)
  {
   // Raussuchen was an Befelen gesendet wurde
   input = input.substring(input.indexOf("{"),(input.indexOf("}")+1));

    StaticJsonDocument<96> doc;
    DeserializationError error = deserializeJson(doc, input);
    if (error) 
      {
        Serial.print(F("deserializeJson() failed: "));
        Serial.println(error.f_str());
      }
    else // Alles OK 
      {
        //Sendestring inhalt auf Variabeln übertragen
        const char* s_time = doc["time"]; // "05:22:00" hh:mm:ss
        out_1 = doc["out_1"];             //0 oder 1
        out_2 = doc["out_2"];             //0 oder 1
        
        // Schalten der Ausgänge
        if (out_1 == 1)
          {
            //Serial.println("GPIO 25 on");
            out_1 = 1;
            digitalWrite(ausgang_1, HIGH);
          }
        if (out_1 == 0)
          {
            //Serial.println("GPIO 25 off");
            out_1 = 0;
            digitalWrite(ausgang_1, LOW);
          }
        if (out_2 == 1)
          {
            //Serial.println("GPIO 26 on");
            out_2 = 1;
            digitalWrite(ausgang_2, HIGH);
          }
        if (out_2 == 0)
          {
            //Serial.println("GPIO 26 off");
            out_2 = 0;
            digitalWrite(ausgang_2, LOW);
          }
      }   
  }
//-----------------------------------------------------------------------------

//--------------- Json-String zusammen bauen für das versenden ---------------- 
//-----------------------------------------------------------------------------
void uebergabestring()
    {
      // Hier wird das JSON-Objekt erstellt
      DynamicJsonDocument configJSON(1024);
      configJSON["software_version"] = Software_Version;
      configJSON["age"] = 0;
      configJSON["out_1"] = out_1;
      configJSON["out_2"] = out_2;
      configJSON["sensordatavalues"][0]["value_type"] = "DHT11_T";
      configJSON["sensordatavalues"][0]["value"] = DHT11_T;
      configJSON["sensordatavalues"][1]["value_type"] = "DHT11_H";
      configJSON["sensordatavalues"][1]["value"] = DHT11_H;
      configJSON["sensordatavalues"][2]["value_type"] = "BB_H";
      configJSON["sensordatavalues"][2]["value"] = BB_H;
      configJSON["sensordatavalues"][3]["value_type"] = "BB_L";
      configJSON["sensordatavalues"][3]["value"] = BB_L ;
      configJSON["sensordatavalues"][4]["value_type"] = "signal";
      configJSON["sensordatavalues"][4]["value"] = WiFi.RSSI();
      sende_json = "";
      serializeJson(configJSON, sende_json);
      //Serial.println(sende_json);
    }
//-----------------------------------------------------------------------------

//------------------- Temperatur und Luftfeuchtigkeit holen -------------------
//-----------------------------------------------------------------------------
void temp_feucht_werte_holen()
    {
      //if (dht.getStatus() != 0) 
      //  {
      //    Serial.println("Fehler beim Lesen des DHT-Sensors!");
      //    DHT11_T = 999;
      //    DHT11_H = 999;
      //  }  
      //else
      //  {
          DHT11_T = dht.getTemperature();
          DHT11_H = dht.getHumidity();    
      //  }
    }
//-----------------------------------------------------------------------------

//----------------------------- Analogwerte holen -----------------------------
//-----------------------------------------------------------------------------
void analogwerte_holen()
    {
      //Werte einlesen 32767 endspricht 2,048V / 1Bit = 0.0625mV
      adc0 = ads.readADC_SingleEnded(0);    //Aussenlicht Low
      adc1 = ads.readADC_SingleEnded(1);    //Aussenlicht High
      adc2 = ads.readADC_SingleEnded(2);    //Frei
      adc3 = ads.readADC_SingleEnded(3);    //Frei
      
      //Wandeln in die Ausgabewerte
      BB_L = adc0 / 0.305185;              // Sonnenlicht 0-10.000lx  / Aussenlicht Low
      BB_H = adc1 / 0.0305185;             // Sonnenlicht 0-100.000lx / Aussenlicht High
      //xxxx = adc2 / 0.01;                 //Frei
      //xxxx = adc3 / 0.01;                 //Frei

      //Für die Ausgabe anpassen

    }
//-----------------------------------------------------------------------------

//---------------------------- Ausgabe Systemzeit -----------------------------
//-----------------------------------------------------------------------------
void printLocalTime() //Wird nicht benutzt nur zum testen
    {
      struct tm timeinfo;
      if(!getLocalTime(&timeinfo))
        {
          Serial.println("Failed to obtain time");
          return;
        }
      Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
    }
//-----------------------------------------------------------------------------

//-------------------- Ausgabe der Daten auf dem SSD1306 ----------------------
//-----------------------------------------------------------------------------
void display_ausgabe()
    {
      // clear display
      display.clearDisplay();
      
      // Alles was ausgegeben wird in der Schriftgroesse
      display.setTextSize(1);

      //display temperature
      display.setCursor(0,0);
      display.print("Temp.   : ");
      display.print(DHT11_T);
      display.print(" ");
      display.cp437(true);
      display.write(167);
      display.print("C");
  
      //display humidity
      display.setCursor(0,10);
      display.print("Feuchte : ");
      display.print(DHT11_H);
      display.print(" %");   

      //display Aussenlicht Low 0-10.000lx
      display.setCursor(0,20);
      display.print("Licht Lo: ");
      display.print(BB_L);
      display.print(" lx");  

      //display Aussenlicht High 0-100.000lx
      display.setCursor(0,30);
      display.print("Licht Hi: ");
      display.print(BB_H);
      display.print(" lx");  

      //display Ausgang 1
      display.setCursor(0,40);
      display.print("Out_1 : ");
      display.print(out_1);
      display.print(" / ");  

      //display Ausgang 2
      display.print("Out_2 : ");
      display.print(out_2);
      display.print(" ");  

      display.drawLine(0,50,128,50,1);         // Zeichnet eine Linie mit Hilfe von Start- und Endkoordinaten;
                                              
      //display Systemzeit
      display.setCursor(0,53);
      display.print("Systemzeit : ");          // An dieser Stelle wird die Systemzeit ausgegeben
      
      display.drawLine(0,62,128,62,1);         // Zeichnet eine Linie mit Hilfe von Start- und Endkoordinaten;
                                             
      display.display();                       // Alles aus dem Speicher zur Anzeige bringen
    }
//-----------------------------------------------------------------------------

//Für die Anzeige der Systemzeit
//-----------------------------------------------------------------------------
void display_systemzeit() 
  {
    if (millis() > myTimeout + myTimer ) 
      {
        myTimer = millis();
        struct tm timeinfo;
        if(!getLocalTime(&timeinfo))
          {
            Serial.println("Failed to obtain time");
          }
        else
          {
            //Die alte Anzeige löschen
            display.drawFastHLine(80,53,50,SSD1306_BLACK);
            display.drawFastHLine(80,54,50,SSD1306_BLACK);
            display.drawFastHLine(80,55,50,SSD1306_BLACK);
            display.drawFastHLine(80,56,50,SSD1306_BLACK);
            display.drawFastHLine(80,57,50,SSD1306_BLACK);
            display.drawFastHLine(80,58,50,SSD1306_BLACK);
            display.drawFastHLine(80,59,50,SSD1306_BLACK);
            display.drawFastHLine(80,60,50,SSD1306_BLACK);

            //Zeit anzeigen
            display.setTextSize(1);
            display.setCursor(80,53);
            display.print(&timeinfo, "%H:%M:%S");
            display.display();
          }
      }
  }
//-----------------------------------------------------------------------------

// EOF

Ja ist schon etwas umfangreicher die Sache aber nicht verzweifeln das wird, bei Fragen könnt Ihr mich ja kontaktieren !
Ich bin zwar nicht der Guru aber Lerfähig.

Viel Spaas damit über die Ostertage, wenn Ihr schnell Bestellt könnt Ihr Osern noch basteln !

Grüße aus dem Sauerland
Frank