Öffnen einer Tür und schalten der Anwesenheit mit Zippato-RFID

So, für alle die es interessiert:
Als erstes muss ich sagen, dass der Zippato RFID Leser nicht die sicherste Methode ist, um sein Haus zu schützen oder Türen damit zu öffnen!

Mit dieser Szenen ist es möglich mehrere Zippato RFID-Leser parallel zu betreiben und auch ein Türschloss zu öffnen. Ich habe selber 3 RFID-Leser und ein NUKI-Schloss und ein Fibaro fgs-222 der meinen Türdrücker bedient:

--DECLARATIONS (Bedingungen/Trigger)
{
  conditions = { 
	{
	id = 284, 
	isTrigger = true, 
	operator = "anyValue", 
	property = "accessControlEvent", 
	type = "device"
	},
	{
	id = 547, 
	isTrigger = true, 
	operator = "anyValue", 
	property = "accessControlEvent", 
	type = "device"
	},
	{
	id = 1097, 
	isTrigger = true, 
	operator = "anyValue", 
	property = "accessControlEvent", 
	type = "device"
	}
	},
  operator = "any"
}

--AKTION 

--Hier kommen die RFID-Chip-Namen rein 
local RFIDChipUser1 = "Sven"			-- "name of RFID-Chip-user"
local RFIDChipUser2 = "Nicole"			-- "name of RFID-Chip-user"
local RFIDChipUser3 = "Eltern"			-- "name of RFID-Chip-user"
local RFIDChipUser4 = "Svenja"			-- "name of RFID-Chip-user"
local RFIDChipUser5 = "SvenjaKey"		-- "name of RFID-Chip-user"
local RFIDChipUser6 = "reserve6"		-- "name of RFID-Chip-user"
local RFIDChipUser7 = "reserve7"		-- "name of RFID-Chip-user"
local RFIDChipUser8 = "reserve8"		-- "name of RFID-Chip-user"
local RFIDChipUser9 = "reserve9"		-- "name of RFID-Chip-user"
local RFIDChipUser10 = "reserve10"		-- "name of RFID-Chip-user"
local RFIDChipUser11 = "reserve11"		-- "name of RFID-Chip-user"
local RFIDChipUser12 = "reserve12"		-- "name of RFID-Chip-user"

--Hier kommen die RFID-Chip-Leser ID´s rein
local operatingKeyPadID1 = 1097			-- "ID of RFID-Reader"
local operatingKeyPadID2 = 547			-- "ID of RFID-Reader"
local operatingKeyPadID3 = 284			-- "ID of RFID-Reader"
--local operatingKeyPadID3 = ""			-- "ID of RFID-Reader"

--Hier kommen die RFID-Chip-Leser Namen rein
local operatingKeyPadName1 = "Haustüre"	-- "name of RFID-Chip-Reader"
local operatingKeyPadName2 = "Garage"	-- "name of RFID-Chip-Reader"
local operatingKeyPadName3 = "reserve"	-- "name of RFID-Chip-Reader"

--Hier kommen die DoorLockID´s rein
local DoorLockIDs			= {869}		-- ID(s) des/der Nuki/Danalock

deviceIDs			= {}				-- Table für deviceIDs init

deviceIDs[1097]		= {869}				-- RFID Haustüre
deviceIDs[547]		= {}				-- RFID Garage
deviceIDs[284]		= {869}				-- RFID reserve

--Hier kommen die Mobiltelefone rein
local Phone1 = tonumber(fibaro.getGlobalVariable ("Handy_IPhoneSE_Sven"))
local Phone2 = tonumber(fibaro.getGlobalVariable ("Handy_Nicole"))


-------------------------- USER FUNKTIONEN --------------------------

function DisarmFunction()
	-- Hier eigene Aktionen eingtragen die "Home" ausgeführt werden sollen
	print("Ej...Tür auf!!") 
    fibaro.profile(1, 'activateProfile')
	fibaro.alarm('disarm')
	--fibaro.scene('execute', {[1] = 66, })
	--fibaro.emitCustomEvent('unlocked')
	fibaro.alert('push', {Phone1}, 'Alarm aus')
	fibaro.alert('push', {Phone2}, 'Alarm aus')
	fibaro.call(939, "turnOff")  -- LED grün
end

function ArmFunction()
	-- Hier eigene Aktionen eingtragen die "Away" ausgeführt werden sollen
	print("Ej...Tür zu!!") 
	fibaro.alert('push', {Phone1}, 'Alarm ein')
	fibaro.alert('push', {Phone2}, 'Alarm ein')
    fibaro.call(939, "turnOn")  -- LED rot
	--fibaro.scene('execute', {[1] = 66, })
	--fibaro.emitCustomEvent('locked')
	fibaro.alarm('arm')
	fibaro.profile(2, 'activateProfile')
end

version				= "0.7beta FW5.070"

print ("-------------------------------------------------------------------")			
print ("Danalock/Nuki / Zipato BASIC Szene "..version.." für das Fibaro HC3")
print ("-------------------------------------------------------------------")	

trigger = sourceTrigger
-- print(json.encode(sourceTrigger))
-- allgemein wer und auf was hat die Szene getriggert? 
triggerProperty = trigger["property"]
-- print(triggerProperty)
if triggerProperty == "execute" then
print ("trigger per Hand ausgeführt")
else
triggerType = trigger["type"]
print(triggerType)

-- welcher RFID-Chip (maximum gibt es 12 IDs)
operatingMedium = trigger["value"]["userId"]
        if operatingMedium ==    1 then
--			print(RFIDChipUser1)
			RFIDChipUser = RFIDChipUser1
    elseif operatingMedium ==    2 then
--			print(RFIDChipUser2)
			RFIDChipUser = RFIDChipUser2
    elseif operatingMedium ==    3 then
--			print(RFIDChipUser3)
			RFIDChipUser = RFIDChipUser3
	elseif operatingMedium ==    4 then
--			print(RFIDChipUser4)
			RFIDChipUser = RFIDChipUser4
    elseif operatingMedium ==    5 then
--			print(RFIDChipUser5)
			RFIDChipUser = RFIDChipUser5
    elseif operatingMedium ==    6 then
--			print(RFIDChipUser6)
			RFIDChipUser = RFIDChipUser6
    elseif operatingMedium ==    7 then
--			print(RFIDChipUser7)
			RFIDChipUser = RFIDChipUser7
	elseif operatingMedium ==    8 then
--			print(RFIDChipUser8)
			RFIDChipUser = RFIDChipUser8
    elseif operatingMedium ==    9 then
--			print(RFIDChipUser9)
			RFIDChipUser = RFIDChipUser9
	elseif operatingMedium ==    10then
--			print(RFIDChipUser10)
			RFIDChipUser = RFIDChipUser10
    elseif operatingMedium ==    11then
--			print(RFIDChipUser11)
			RFIDChipUser = RFIDChipUser11
    else 	
			print(RFIDChipUser12)
			RFIDChipUser = RFIDChipUser12
    end

-- von welchem RFID-Leser wurde getriggert
operatingKeyPad = trigger["id"]
	if operatingKeyPad == operatingKeyPadID1 then 
        print("Es wurde vom RFID-KeyPad "..operatingKeyPadName1.." mit dem RFID-Chip "..RFIDChipUser.." getriggert")
		fibaro.alert('push', {Phone1}, "durch das RFID-KeyPad "..operatingKeyPadName1.." mit dem RFID-Chip von "..RFIDChipUser.." !!!")
		fibaro.alert('push', {Phone2}, "durch das RFID-KeyPad "..operatingKeyPadName1.." mit dem RFID-Chip von "..RFIDChipUser.." !!!")
        operatingKeyPadName = operatingKeyPadName1
	elseif operatingKeyPad == operatingKeyPadID2 then 
        print("Es wurde vom RFID-KeyPad "..operatingKeyPadName2.." mit dem RFID-Chip "..RFIDChipUser.." getriggert")
		fibaro.alert('push', {Phone1}, "durch das RFID-KeyPad "..operatingKeyPadName2.." mit dem RFID-Chip von "..RFIDChipUser.." !!!")
		fibaro.alert('push', {Phone2}, "durch das RFID-KeyPad "..operatingKeyPadName2.." mit dem RFID-Chip von "..RFIDChipUser.." !!!")
        operatingKeyPadName = operatingKeyPadName2
    elseif operatingKeyPad == operatingKeyPadID3 then 
        print("Es wurde vom RFID-KeyPad "..operatingKeyPadName3.." mit dem RFID-Chip "..RFIDChipUser.." getriggert")
		fibaro.alert('push', {Phone1}, "durch das RFID-KeyPad "..operatingKeyPadName3.." mit dem RFID-Chip von "..RFIDChipUser.." !!!")
		fibaro.alert('push', {Phone2}, "durch das RFID-KeyPad "..operatingKeyPadName3.." mit dem RFID-Chip von "..RFIDChipUser.." !!!")
    else
        print("Dieses RFID-KeyPad wurde nicht eingerichtet!!!")
    end

for k,v in pairs( deviceIDs ) do if k == operatingKeyPad then openLockIDs = v end end


-- Unlock oder Lock
operatingStatus = trigger["value"]["status"]
--print(operatingStatus)
	if operatingStatus == "Unlock" then
--		print("Es wurde vom RFID-KeyPad "..operatingKeyPadName.." getriggert und geöffnet")
		if #openLockIDs > 0 then
					DisarmFunction()
				for i = 1,#openLockIDs do
					print("DisarmFunctionen werden ausgeführt, dann Danalock/Nuki mit der ID "..openLockIDs[i].." wird geöffnet.")
					fibaro.call(96, "turnOn");					-- Haustüre
					print("Haustüre auf !!!")
					--fibaro.call(openLockIDs[i], 'unlatched')	-- NUKI - Schloss
					--print("Wohnungstüre auf !!!")
				end
		else
					DisarmFunction()
					print("Diesem KeyPad sind keine Locks zugewiesen.")
		end
	elseif operatingStatus == "Lock" then
--		print("Es wurde vom RFID-KeyPad "..operatingKeyPadName.." getriggert und geschlossen")
		for i = 1,#DoorLockIDs do
		print("Danalock/Nuki mit der ID "..DoorLockIDs[i].." wird geschlossen.")
		fibaro.call(DoorLockIDs[i], 'secure')						-- NUKI - Schloss
		end
		ArmFunction()
		
	else print("Es wurde vom RFID-KeyPad "..operatingKeyPadName.." getriggert und geschlossen")
		ArmFunction()	
	end
end

Voraussetzung ist, dass die RFID-Leser im System sind, dann müssten die RFID-Chips oder Karten eingelesen sein und mit den RFID-Lesern synchronisiert sein. Ich nutze 2 Handys, an die die Zustände per Push gesendet werden; deren IDs habe ich als Globale Variable angelegt.

Wenn ihr die Szene braucht aber Probleme auftauchen, fragt mich einfach.

Gruß Sven

1 Like

Hallo und Frohe Ostern

Hallo Sven

Hat sich das mit dem RFID bewährt ?
Ich fange grade an zu planen.
Mit einem ESP32 und RC522 sowie einem QA.
Basierend auf meiner Dachbodenlösung (Webserver auslesen).
Dann würde ich die Nummern n der QA abspeichern und mit dem ESP32 synchronisieren.
Auslösen dann wieder ESP32 => Mitteilen OK oder nichts.
Das dauert aber noch darum vorher mal nachfragen.

Grüße Frank

Hallo Frank, ich würde den RFID-Leser nicht zum öffnen von der Wohnung nutzen, da das Teil einen kleinen bug hat.

Hallo Sven

Den benutze ich auch nicht.
Ich mache das hier mit :
ESP-32 Dev Kit C bei az-delivery.de – AZ-Delivery (az-delivery.de)
RFID Kit RC522 mit Reader, Chip und Card für Arduino und Raspberry Pi – AZ-Delivery (az-delivery.de)

Den Leser habe ich schon am laufen, der QA im HC3 bekommt auch die Daten.
Jetzt muss ich noch die Childs richtig anpassen und die Karten in den Variabeln aktivieren.
Ob ich noch einen Editer für die Karten ID´s mit einbaue ?
Das kommt Morgen.
Ich wollte nur mal wissen ob das Machbar ist oder Unsinn.
Wenn ich das fertig habe veröffendliche ich das hier.

Hier ein Vorgeschmack

Gruss Frank

an guten Sachen bin ich immer interressiert :slight_smile:

Habe meinen RFID Reader mit einem Z-UNO realisiert.
Nachdem über Z-Wave keine RFID’s übertragen werden können, habe ich die ID’s im Code ablegen müssen. Das lässt sich über HTTP sicher besser managen.
Einzigen Tipp den ich habe ist das erkennen vom RFID Chip mittels Ton zu quittieren.
Positiv erkannte Chips habe ich mit doppel Piep und negative mittels Dauerton quittiert.
Der verwendete Summer: https://www.amazon.de/stücke-Aktive-Elektromagnetische-Industrie-Sounder/dp/B082SM133L/ref=sr_1_2?__mk_de_DE=ÅMÅŽÕÑ&dchild=1&keywords=3v+summer&qid=1617775822&sr=8-2

1 Like

Warte noch etwas dann kannst du meine Lösung gleich benutzen.
Nur für den Uno kompilieren und meinen QA einbauen fertig.
Den Compiler benutze ich :

Das mit dem Summer muss ich noch sehen, Momentan schiebe ich den erkannten RFID nur zum QA und mache da den vergleich.
Dann müsste ich die Info OK/NOK zum ESP32 wieder zurück geben.
Ist kein Problem aber müsste ich noch bauen.
Ich möchte die Codes und den Vergleich im HC belassen und den ESP32 dumm halten aus Sicherheitsgründen.
Darum auch noch eine Verschlüsselung der Daten wenn die über das Wlan gehen.
Sicherlich alles etwas Paranoid aber Vorsicht ist die Mutter der Porzelankiste.

Genau den Summer habe ich hier liegen.

Kannst du mal ein Bild von deiner Fertigen Lösung machen ?
Nur von Außen als Designvorschlag, da brauche ich noch Ideen.

Gruss Frank

Der Z-UNO ist ein frei programmierbarer Z-Wave Controller, ohne WiFi. Weiters ist er relativ eingeschränkt bei den unterstützten Libraries.
Der Reader gibt nicht viel her und ist hinter Komode versteckt.

Das ist der Z-UNO

https://z-uno.z-wave.me/

Hallo

Hier ist die vorher angekündigte RFID Lösung.

Zur Vorgeschichte :

Da ich viel Fahrrad fahre fand ich das sehr unschön immer ein Schlüsselbund bei mir haben zu müßen.

Meine Lösung :

Ich benutze ein ESP32-Board mit RFID Leser dazu das Garagentor ansteuern zu können.
Mein Garagentor wird mittels einer Scene im HC3 gesteuert und überwacht, so das ich die Daten also im HC3 bearbeiten muß/möchte.
Dazu war es nötig einen QA zu erstellen, der mittel HTTP Get die Daten vom ESP32 von einem Webserver abholt.
Der QA sollte so aufgebaut sein wie ein Normaler Schalter damit man nicht nur in LUA sondern auch per Blockscene damit arbeiten kann.
Weiterhin ist dann auch das Triggern möglich.

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)

RFID Kit RC522 mit Reader, Chip und Card 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 wird ein Normaler Binärer Sensor erzeugt…

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 den RFID-Code von dem RFID-TAG wenn dieser vor die Sensorfläche gehalten wird.
Danach wird dieser zum HC3 übermittelt.
Der HC3 vergleicht diese mit Codes in den Variabeln.

Hier sind die Variabeln zu sehen :


Bild
Die Anzahl ist beliebig, es gibt nur eine Vorgabe das ist der Name, er muss mit RFID beginnen und in der Eingabe muss eine Name und der Code eingegeben werden getrennt von einem „;“.

Sollte bei diesem Vergleich festgestellt werden das er in einer Variabel vorhanden ist so wird dem ESP mitgeteilt das er einen Beeper ansteuern soll.
20ms für Code OK und 60ms für nicht vorhanden.
Um den Code auslesen zu können wird dieser im Bearbeitung/Vorschaufenter angezeigt.

Siehe hier unter Letzter RFID:


Bild

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

Auf der Linken Seite ist der ESP32 zu sehen auf dem der Webserver läuft.
In der Mitte ist der RC522 und rechts das Display.
Die Beiden Wechseldioden verstecken sich hinter dem RC522 und die Blaue LED ist durch einen Beeper ersetzt worden. (Hier nur als LED damit es dem WAF gefällt)

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

Hier ist nun der QA zu sehen.

--[[
                       ESP32_RFID_Garage QA
                       ====================
Der ESP32 liest einen RFID-Code mit hilfe eines "RFID-RC522" ein.

Die Werte werden im ESP32 vorverarbeitet und stehen als direkter Wert im QA 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 vergleicht die mit den
RFID-Daten (Variabel "Name_RFID-x").
In den Variabeln "Name_RFID-x" steht der Name und die Kartennummer getrennt von einem ";"".
Sollte die überein stimmen so wird die Variabel ID-value true und geht nach 500ms wieder auf false.
Somit kann über ID-value getriggert werden.
Wenn ein RFID-Tag mit den Vorgegebenen übereinstimmt so wird ein Beeper der am ESP32 angeschlossen ist
für 20ms aktiv. Ein Falscher RFID-Tag erzeugt keine Reaktion und der Beeper giebt ein 600ms Signal ab. 
Diesen Vorgang kann aber auch mit der Taste "Refresh" aktiviert werden.

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 den beiden LED´s angezeigt.

Version   : ESP32_RFID_Garage V1.0 
Ersteller : Frank Berges
-------------------------------------
Datum     : 07.04.2021
V1.0      : 07.04.2021
            
--]]

--******************* QuickApp Initialisieren ********************
------------------------------------------------------------------
function QuickApp:onInit()
    self:debug("onInit")
    
    -- Setup-Phase
    self:getQuickAppVariables()
    Daten_1 = ""    --Besitzer des RFID
    Daten_2 = ""    --gelesener Code des RFID
    Daten_3 = ""    --Letzter gelesene Code
    OK_Beep = 0     -- 20ms = OK, 600 = nicht OK
        -- Dauerlaufschleife
    --******************   
    local function loop()
        self:getData() --ESP32 Daten holen und senden
        setTimeout(loop, self.looptime)
    end
    if self.ip ~= "changeme" then loop() 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"))
    self.looptime = interval * 1000 --Angabe in 1000ms
    httpTimeout = 5 -- Default value for http Timeout
    userID = tonumber(self:getVariable("userID")) 
    debugLevel = tonumber(self:getVariable("debugLevel"))
    local icon = tonumber(self:getVariable("icon")) 
    out_1 = 0
    out_2 = 0
    
    -- Plausibilität der Variabeln überprüfen und im Zweifel mit default füllen
    if ipAddress == "" or ipAddress == nil then
        ipAddress = "192.168.2.82" -- Default IP address ist 192.168.2.82
        self:setVariable("ipAddress",ipAddress)
        self:trace("Added QuickApp variable ipAddress")
    end
    if interval == "" or interval == nil then
        interval = "3" -- Default interval is 3, normalerweise wir der RFID-Sensor alle 3S abgefragt
        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
    self.httpClient = net.HTTPClient() 
end
------------------------------------------------------------------

------------------------ Debuging & Level ------------------------
------------------------------------------------------------------
function QuickApp:logging(level,text) -- Logging function for debug
  if tonumber(debugLevel) >= tonumber(level) then 
      self:debug(text)
  end
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[3].value .."dBm")
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 .."RFID - 1         : " ..jsonTable.sensordatavalues[1].value .."\n"
  labelText = labelText .."RFID - 2         : " ..jsonTable.sensordatavalues[2].value .."\n"
  labelText = labelText .."Letzter RFID     : " ..Daten_3 .."\n"
  labelText = labelText .."WiFi signal      : " ..jsonTable.sensordatavalues[3].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
------------------------------------------------------------------

-------------------- 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
------------------------------------------------------------------

------------- 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,
            OK_Beep = OK_Beep
        }
    self:logging(3,"sende-json : " ..json.encode(daten))

 return json.encode(daten)
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
      OK_Beep = 0 -- Die Bestätigung ist gesendet
      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_RFID_Garage")
            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() -- Eigene Properties abgleichen >>>>>>>>>>>>>>>>>>>>>>>> If Daten_2 ~= "" then
                self:RFID_auswerten()   -- Daten vom ESP32 auswerten

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

------ SELF-ID auswerten und Status auf on für 500ms ändern ------
------------------------------------------------------------------
function QuickApp:RFID_auswerten()
    Daten_1 = jsonTable.sensordatavalues[1].value
    Daten_2 = jsonTable.sensordatavalues[2].value
    if Daten_2 ~= "" then
        Daten_3 = Daten_2
        --Alle Variabeln holen
        local a = json.encode(api.get("/devices/"..self.id).properties.quickAppVariables)
        a=json.decode(a)
        --Alle Vraiabeln durchsuchen
        for _,d in ipairs(a) do
            --print("Data Nr. ",_," = ",a[_].name," ",a[_].value)
            if string.match(a[_].name, "RFID") ~= nil then -- ist das ein RFID Datensatz
            local Semikolon = string.find(a[_].value, ";") --Semikolon suchen
            local RFID_Name = string.sub(a[_].value,0,Semikolon-1)
            local RFID_Code = string.sub(a[_].value,Semikolon+1,string.len(a[_].value))
            --print("RFID_Code = ",RFID_Code," Daten_2 = ",Daten_2)
            if Daten_2 == RFID_Code then   --RFID-Code vergleichen
                --print("Gefunden")
                self:turnOn()
                fibaro.sleep(500)
                self:turnOff()
                OK_Beep = 20
                break
            end
            else
                OK_Beep = 600
            end
        end
    end
end --RFID_auswerten
------------------------------------------------------------------

------------------ SELF-ID Status auf on ändern ------------------
------------------------------------------------------------------
function QuickApp:turnOn()
    if self.ip ~= "changeme" then
        --self:debug("binary switch turned on")
        self:updateProperty("value", true)
    end
end --function QuickApp:turnOn
------------------------------------------------------------------

----------------- SELF-ID Status auf off ändern ------------------
------------------------------------------------------------------
function QuickApp:turnOff()
    if self.ip ~= "changeme" then
        --self:debug("binary switch turned off")
        self:updateProperty("value", false)
    end
end --function QuickApp:turnOff
------------------------------------------------------------------

--EOF

RFID-Leser_v1.0.fqa (13,9 KB)

Zum Schluss folgt noch der ESP32 Code.

/*
* ESP32 Webserver für den Datenaustausch zwischen ESP32 <--> Fibaro-HC3
* RFID Leser ansprechenn und Code zum QA HC3 senden.
* Bei Übereinstimmung Relais schalten
* Datenverkehr in einem Json-String versenden.
* 
* Anzeige der Übermittelten und endfangenen Daten mittels OLED-128x64-i2c 
* 
* 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"
* 
* ESP32_RFID_Garage_V1.0
* Erstellt am 06.04.2021
* Frank Berges
* ---------------------------------
* Enderungsindex
* V1.0  06.04.2021  F.B.
* ============================================================================= 
*/
// Load librarys
//-----------------------------------------------------------------------------
#include <WiFi.h>
#include <Wire.h>
#include <ArduinoJson.h>
#include <SPI.h>
#include <MFRC522.h>          // für RFID-RC522
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h> // für Display
#include <Adafruit_Sensor.h>
#include "time.h"             // Zeitdarstellungen
//-----------------------------------------------------------------------------

// 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
#define Beep_PIN 2 // LED-blau-Pin 
#define RST_PIN 33 // SPI-Pin RST-Pin
#define SDA_PIN 32 // SPI-Pin SS- bzw. SDA-Pin
//-----------------------------------------------------------------------------

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

//Sendedaten an HC3
//-----------------------------------------------------------------------------
String Software_Version = "ESP32_RFID_Garage_V1.0"; // Softwareversion
int age = 0;
String Daten_1 = "";  // Erster Kartendatensatz z.B "Karin Berges"
String Daten_2 = "";  // Zweiter Kartendatensatz z.B "B2 3E 7C 31"                        
String sende_json = "";           // Sendedaten an den HC3
//-----------------------------------------------------------------------------

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

//Lese und Auswertebestätigung 50ms = OK, 500ms = NOK
//-----------------------------------------------------------------------------
int OK_Beep = 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;
//-----------------------------------------------------------------------------

//MFRC522-Instanz erstellen
//-----------------------------------------------------------------------------
MFRC522 mfrc522(SDA_PIN, RST_PIN);
//-----------------------------------------------------------------------------

// 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() 
  {  
    //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(Beep_PIN, OUTPUT);     //Beeper
      digitalWrite(Beep_PIN, LOW);   //RC522
      
    //SPI-Bus Initialisieren
      SPI.begin();

    //RFID-RC522 initialisieren
      mfrc522.PCD_Init();
    
    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 RFID
                  RFID_lesen();
                  // 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
                  Daten_1 = "";
                  Daten_2 = "";
                  // 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
//-----------------------------------------------------------------------------

//------------------------------ RFID Auslesen --------------------------------
//-----------------------------------------------------------------------------
void RFID_lesen()
    {
      String rfidTag= "";
      if (mfrc522.PICC_IsNewCardPresent() && // liegt ein neues Tag vor
          mfrc522.PICC_ReadCardSerial()) 
        { // richtige Tag-Art
          Serial.print("RFID-Tag/Karten-ID:");
          for (byte i = 0; i < mfrc522.uid.size; i++) 
            { // Karten-ID extrah.
              Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
              Serial.print(mfrc522.uid.uidByte[i], HEX);
              rfidTag.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
              rfidTag.concat(String(mfrc522.uid.uidByte[i], HEX));
            }
          Serial.println();
          Daten_1 = "Unbekannt";
          Daten_2 = rfidTag.substring(1);
        }
    }
      

//-----------------------------------------------------------------------------

//--------- 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));
    //Serial.println(input);
    
    StaticJsonDocument<128> 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
        OK_Beep = doc["OK_Beep"];         // 50/500ms
        
        // 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);
          }
         digitalWrite(Beep_PIN, HIGH);
         delay(OK_Beep);
         digitalWrite(Beep_PIN, LOW);
         OK_Beep = 0;
      }   
  }
//-----------------------------------------------------------------------------

//--------------- 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"] = "Daten_1";
      configJSON["sensordatavalues"][0]["value"] = Daten_1;
      configJSON["sensordatavalues"][1]["value_type"] = "Daten_2";
      configJSON["sensordatavalues"][1]["value"] = Daten_2;
      configJSON["sensordatavalues"][2]["value_type"] = "signal";
      configJSON["sensordatavalues"][2]["value"] = WiFi.RSSI();
      sende_json = "";
      serializeJson(configJSON, sende_json);
      //Serial.println(sende_json);
    }
//-----------------------------------------------------------------------------


//---------------------------- 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 Datensatz RFID 1
      display.setCursor(0,0);
      display.print("Daten_1 : ");
      display.print(Daten_1);
  
      //display Datensatz RFID 2
      display.setCursor(0,10);
      display.print("Daten_2 : ");
      display.print(Daten_2);  

      //display Zeile 3
      //display.setCursor(0,20);
      //display.print("xxxxx   : ");
      //display.print(Variabel);
      //display.print(" xx");  

      //display Zeile 4
      //display.setCursor(0,30);
      //display.print("xxxxxx  : ");
      //display.print(Variabel);
      //display.print(" xx");  

      //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

Ich hoffe ich habe alles zur Genüge dokumentiert so das Ihr das Nachverfolgen könnt.
Grüße aus dem Weißen Sauerland !
Frank

PS viel Spaas beim bastel !

Schöne Lösung.
Mögliche Optimierung um das Delay bei den Abfrageschleifen weg zu bekommen:
1.) Sobald ein RFID gelesen wird die ID vom ESP32 in eine HC3 Variable schreiben lassen.
Änderung der Variable triggert QA und positiv oder negativ Meldung kann rasch erfolgen.

2.) RFIDs im ESP32 im Speicher ablegen (z.b. gehasht). Damit kann Prüfung auf Korrektheit sofort durchgeführt werden und Rückmeldung an Benutzer ohne Verzögerung erfolgen.

Hallo @mdietinger
Ja das ist wohl wahr.
Ich baue da grade die Version2, Übertragen der Daten vom HC3 auf den ESP32 inkl. Syncronisierung der Daten. Lesen des Code mit Überprüfung des Selbigen. Dann Ergebniss und Code Transfer zum HC3.
Ich kämpfe noch mit den Strukturierten Date, Flash Filesystem und Objektorientierter Programmierung im Embeddet C.
Alles Neuland das ich noch erforschen muss, meine Erfahrungen und Kenntnisse sind 30 Jahre alt, da gab es das noch nicht. Also erst mal viel lesen und probieren dann im ESP32 und HC3 umsetzen.
In C ist die Informationsflut ja unüberschaubar so viel kann keiner lesen und das raussuchen gleicht schon einer Sissiphos Arbeit
Aber das wird !
So nun schöne Grüße aus dem Sauerland
Frank

Hallo @Berges01,

auf Github habe ich eine nette Library gefunden welche bei deinem Projekt hilfreich sein kann.

Damit kann man relativ einfach Werte im EEPROM Speichern.
z.b. : KeyValueEEPROM.set(„RFID1“, „xx:xx:xx:xx:xx“);

lg,

Markus

Hallo Markus @mdietinger

Schade jetzt habe ich den Teil schon fertig mit :
ESP32. Get started with the SPIFFS.h library to read, write, modify files • DIY Projects
Ist bedeutend komplizierter und hat was gedauert bis ich wurste wie das Funktionierte.
Ist auch nicht schlecht aber das mit dem EEPROM ist was für den Stack.
Habe Heute und Morgen leider wenig Zeit aber wer weis wenn ich eine Dolle Stunde habe, Glühen die Tasten. :rofl:
Gruss Frank

1 Like

Hallo

Hier ist die vorher angekündigte Neue RFID Lösung V2.0.

Zur Vorgeschichte :

Bei der Ersten Version kam die Anmerkung @mdietinger das der EPS32 die Daten selber vergleichen solle und damit eine Verzögerung minimiert wird.

Weiterhin hatte ich auch noch vor den Datenverkehr zu verschlüsseln um ein direktes auslesen zu erschweren.

Das hat nun einiges an Änderungen nach sich gezogen und ich musste eine Menge lesen.

Arbeitsweise:

Zur Erweiterung der oben beschriebenen Funktion ist es so, das nach der Eingabe der RFID-Codes mit Namen (; getrennt) diese Daten per Taste „ESP-Daten senden“ dem ESP32 übermittelt werden. Dieser Datenverkehr findet verschlüsselt statt, damit keiner die Daten so ohne weiteres mitlesen kann.

Im ESP32 werden die ankommenden Daten endschlüsselt und im Flash Spannungsausfallsicher abgespeichert.

Nach jedem Einschalten werden die Daten dann aus dem Flash geholt, oder sie wurden grade von HC3 übermittelt und zum Vergleich heran gezogen.

Nach einem Gültigen Vergleich werden die Daten im Display angezeigt und ein Beeper ertönt für 50ms. Bei einem Ungültigen Vergleich werden die Daten auch angezeigt aber es ertönt ein 600ms langer Ton.

Nach dem ein Neuer Schreibzyklus erfolgt werden diese gelesenen Daten und das Ergebnis OK oder nicht OK dem HC3 auch wieder verschlüsselt mitgeteilt.

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

1 Like

QA als Text und als Datei !

--[[
                       ESP32_RFID_Garage QA
                       ====================
Der ESP32 liest einen RFID-Code mit hilfe eines "RFID-RC522" ein.

Die Werte werden im ESP32 vorverarbeitet und stehen als direkter Wert im QA zur Verfügung.
Die Datenkommunikation findet über WLAN per Json-Datenpacket verschlüsselt 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.
In den Variabeln "Name_RFID-x" steht der Name und die Kartennummer getrennt von einem ";"".

Wenn ein RFID-Tag mit den Vorgegebenen übereinstimmt so wird ein Beeper der am ESP32 angeschlossen ist
für 20ms aktiv. Ein Falscher RFID-Tag erzeugt keine Reaktion und der Beeper giebt ein 600ms Signal ab. 
Sollte die überein stimmen so wird die Variabel ID-value true und geht nach 500ms wieder auf false.
Somit kann über ID-value getriggert werden.

Mit der Taste ESP-Daten senden, ist es möglich die RFID-Daten die in den Variabeln stehen dem ESP32 zu senden.
Dieser hat danach die Neuen Daten zum vergleichen zur verfügung.

Es ist aber auch möglich die Daten des Lesevorganges vorab zu erhalten.
Diesen Vorgang kann aber auch mit der Taste "Refresh" aktiviert werden.
Dann werden die gelesenen Daten wie bei der Zyklischen übermittlung bereit gestellt.

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 den beiden LED´s angezeigt.

Version   : ESP32_RFID_Garage V2.0 
Ersteller : Frank Berges
-------------------------------------
Datum     : 07.04.2021
V2.0      : 16.04.2021 F.B.
                       Datenverkehr verschluesselt HC3 <-> ESP
                       Auswertung findet jetzt im ESP32 stat und nicht mehr im HC3
                       Die Daten für den RFID-Vergleich werden vom HC3 übermittelt
                       und im Flash abgespeichert, somit stehen diese nach jebem
                       Neuen Einschalten sofort zurverfügung und müssen nicht
                       neu Übermittelt werden. Ein Übermittlungsbefehl wird vom 
                       QA aus über einen Button angestossen.
            
--]]

--******************* QuickApp Initialisieren ********************
------------------------------------------------------------------
function QuickApp:onInit()
    self:debug("onInit")
    
    -- Setup-Phase
    self:getQuickAppVariables()
    Daten_1 = ""    --Besitzer des RFID
    Daten_2 = ""    --gelesener Code des RFID
    Daten_3 = ""    --Letzter gelesene Code
        -- Dauerlaufschleife
    --******************   
    local function loop()
        self:getData() --ESP32 Daten holen und senden
        setTimeout(loop, self.looptime)
    end
    if self.ip ~= "changeme" then loop() 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"))
    self.looptime = interval * 1000 --Angabe in 1000ms
    httpTimeout = 5 -- Default value for http Timeout
    userID = tonumber(self:getVariable("userID")) 
    debugLevel = tonumber(self:getVariable("debugLevel"))
    local icon = tonumber(self:getVariable("icon")) 
    out_1 = 0
    out_2 = 0
    
    -- Plausibilität der Variabeln überprüfen und im Zweifel mit default füllen
    if ipAddress == "" or ipAddress == nil then
        ipAddress = "192.168.2.82" -- Default IP address ist 192.168.2.82
        self:setVariable("ipAddress",ipAddress)
        self:trace("Added QuickApp variable ipAddress")
    end
    if interval == "" or interval == nil then
        interval = "3" -- Default interval is 3, normalerweise wir der RFID-Sensor alle 3S abgefragt
        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
    self.httpClient = net.HTTPClient() 
end
------------------------------------------------------------------

------------------------ Debuging & Level ------------------------
------------------------------------------------------------------
function QuickApp:logging(level,text) -- Logging function for debug
  if tonumber(debugLevel) >= tonumber(level) then 
      self:debug(text)
  end
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[3].value .."dBm")
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 .."RFID - 1         : " ..jsonTable.sensordatavalues[1].value .."\n"
  labelText = labelText .."RFID - 2         : " ..jsonTable.sensordatavalues[2].value .."\n"
  labelText = labelText .."Letzter RFID     : " ..Daten_3 .."\n"
  labelText = labelText .."WiFi signal      : " ..jsonTable.sensordatavalues[3].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
------------------------------------------------------------------

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

---------------- ESP-Daten senden Taste abfragen -----------------
------------------------------------------------------------------
function QuickApp:button2Event()
  self:updateView("button2", "text", "Please wait...")
  self:getMemo()
  fibaro.setTimeout(2000, function() -- Pause for [timeout] seconds (default 5 seconds)
    self:updateView("button2", "text", "ESP-Daten senden")
  end)
end
------------------------------------------------------------------

------------- 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,"sendeDaten-json : " ..json.encode(daten))
    
    --zu sendende Daten verschlüsseln
    local Ergebnis = json.encode(daten)
    Ergebnis = Base64enc(Ergebnis)

 return Ergebnis
end
------------------------------------------------------------------

---------- Memo-Daten für ESP32 zum senden vorbereiten -----------
------------------------------------------------------------------
function QuickApp:sendeMemo_zusammenstellen()

    -- json-Datenstring für das Versenden zusammen bauen
    local Memo_Sende = "{\"time\" :\""..os.date("%H:%M:%S", os.time())
          Memo_Sende = Memo_Sende .."\",\"Codedaten\" :["
    --Alle Variabeln holen
    local a = json.encode(api.get("/devices/"..self.id).properties.quickAppVariables)
    a=json.decode(a)
    --Alle Vraiabeln durchsuchen
    for _,d in ipairs(a) do
        --print("Data Nr. ",_," = ",a[_].name," ",a[_].value)
        if string.match(a[_].name, "RFID") ~= nil then -- ist das ein RFID Datensatz
            local Semikolon = string.find(a[_].value, ";") --Semikolon suchen
            local RFID_Name = string.sub(a[_].value,0,Semikolon-1)
            local RFID_Code = string.sub(a[_].value,Semikolon+1,string.len(a[_].value))
            
            Memo_Sende = Memo_Sende .."{\"RFID_Name\" :\""..RFID_Name.."\",\"RFID_Code\" :\""..RFID_Code.."\"},"
        end
    end
    Memo_Sende = string.sub(Memo_Sende,0,string.len(Memo_Sende)-1)
    Memo_Sende = Memo_Sende .."]}" -- json-String schließen

    --zu sendende Daten verschlüsseln
    local Ergebnis = Memo_Sende
    Ergebnis = Base64enc(Ergebnis)

    return Ergebnis
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_RFID_Garage")
            else --Gültige Daten erhalten 
                --Daten sind verschlüßelt also erst wieder endschlüßeln
                response.data = Base64dec(response.data)
                --print("response.data =",response.data)
                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() -- Eigene Properties abgleichen >>>>>>>>>>>>>>>>>>>>>>>> If Daten_2 ~= "" then
                self:RFID_auswerten()   -- Daten vom ESP32 auswerten

            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 vom ESP32 abholen/Memodaten senden ------------
------------------------------------------------------------------
function QuickApp:getMemo()
  self:logging(3,"Start getMemo")
  self:logging(2,"URL: " ..url)
  self.httpClient:request(url, 
    {
      options={
          headers = {
              Accept = "memo/json",
              data = self:sendeMemo_zusammenstellen() -- Daten zum ESP32 sende
--------------------------------------------------------------------------------
           },
           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_RFID_Garage")
            else --Gültige Daten erhalten
                --Daten sind verschlüßelt also erst wieder endschlüßeln
                response.data = Base64dec(response.data)
                 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() -- Eigene Properties abgleichen 
                self:RFID_auswerten()   -- Daten vom ESP32 auswerten
            end
        end
      end,
      error = function (error)
        self:error("error: " ..json.encode(error))
        self:updateProperty("log", "error: " ..json.encode(error))
      end  
    }) 
end --function QuickApp:getMemo
------------------------------------------------------------------

------ SELF-ID auswerten und Status auf on für 500ms ändern ------
------------------------------------------------------------------
function QuickApp:RFID_auswerten()
    Daten_1 = jsonTable.sensordatavalues[1].value
    Daten_2 = jsonTable.sensordatavalues[2].value
    if (Daten_1 ~= "Unbekannt" and Daten_1 ~= "") then
            Daten_3 = Daten_2
            self:logging(2,"Gefunden")
            self:turnOn()
            fibaro.sleep(500)
            self:turnOff()
    end
    if Daten_1 == "Unbekannt" then --Könnte ja neuer zum einlesen sein mal merken
        Daten_3 = Daten_2
    end
end --RFID_auswerten
------------------------------------------------------------------

------------------ SELF-ID Status auf on ändern ------------------
------------------------------------------------------------------
function QuickApp:turnOn()
    if self.ip ~= "changeme" then
        --self:debug("binary switch turned on")
        self:updateProperty("value", true)
    end
end --function QuickApp:turnOn
------------------------------------------------------------------

----------------- SELF-ID Status auf off ändern ------------------
------------------------------------------------------------------
function QuickApp:turnOff()
    if self.ip ~= "changeme" then
        --self:debug("binary switch turned off")
        self:updateProperty("value", false)
    end
end --function QuickApp:turnOff
------------------------------------------------------------------

--------------------- Base64 Decode/Encode -----------------------
------------------------------------------------------------------
-- Lua 5.1+ base64 v3.0 (c) 2009 by Alex Kloss <alexthkloss@web.de>
-- licensed under the terms of the LGPL2
-- Start taken from https://stackoverflow.com/a/35303321

-- character table string
local b='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'

-- encoding
function Base64enc(data)
    return ((data:gsub('.', function(x) 
        local r,b='',x:byte()
        for i=8,1,-1 do r=r..(b%2^i-b%2^(i-1)>0 and '1' or '0') end
        return r;
    end)..'0000'):gsub('%d%d%d?%d?%d?%d?', function(x)
        if (#x < 6) then return '' end
        local c=0
        for i=1,6 do c=c+(x:sub(i,i)=='1' and 2^(6-i) or 0) end
        return b:sub(c+1,c+1)
    end)..({ '', '==', '=' })[#data%3+1])
end

-- decoding
function Base64dec(data)
    data = string.gsub(data, '[^'..b..'=]', '')
    return (data:gsub('.', function(x)
        if (x == '=') then return '' end
        local r,f='',(b:find(x)-1)
        for i=6,1,-1 do r=r..(f%2^i-f%2^(i-1)>0 and '1' or '0') end
        return r;
    end):gsub('%d%d%d?%d?%d?%d?%d?%d?', function(x)
        if (#x ~= 8) then return '' end
        local c=0
        for i=1,8 do c=c+(x:sub(i,i)=='1' and 2^(8-i) or 0) end
            return string.char(c)
    end))
end
-- end of copy
------------------------------------------------------------------

--EOF

RFID-Leser_v2-0.fqa (20,1 KB)

1 Like

Klingt Interessant.:+1:

1 Like

ESP32 Code

/*
* ESP32 Webserver für den Datenaustausch zwischen ESP32 <--> Fibaro-HC3
* RFID Leser ansprechenn und Code zum QA HC3 senden.
* Bei Übereinstimmung Relais schalten
* Datenverkehr in einem Json-String versenden.
* Jegliche Daten werden Verschlüsselt übertragen. HC3 <-> ESP32 
*
* Anzeige der Übermittelten und endfangenen Daten mittels OLED-128x64-i2c 
* 
* 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"
* 
* ESP32_RFID_Garage_V1.0
* Erstellt am 06.04.2021
* Frank Berges
* ---------------------------------
* Enderungsindex
* V1.0  06.04.2021  F.B.
* V2.0  16.04.2021  F.B.
*                   Datenverkehr verschluesselt HC3 <-> ESP
*                   Auswertung findet jetzt im ESP32 stat und nicht mehr im HC3
*                   Die Daten für den RFID-Vergleich werden vom HC3 übermittelt
*                   und im Flash abgespeichert, somit stehen diese nach jebem
*                   Neuen Einschalten sofort zurverfügung und müssen nicht
*                   neu Übermittelt werden. Ein Übermittlungsbefehl wird vom 
*                   QA aus über einen Button angestossen.
*
* ============================================================================= 
*/
// Load librarys
//-----------------------------------------------------------------------------

#include <deprecated.h>
#include <require_cpp11.h>
#include "time.h"             // Zeitdarstellungen
#include <ssl_client.h>
#include <string>
#include <iostream>
#include <WiFi.h>
#include <Wire.h>
#include <ArduinoJson.h>
#include <SPI.h>
#include <MFRC522.h>
#include <MFRC522Extended.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h> // für Display
#include <Adafruit_Sensor.h>
#include <Preferences.h>      // Variabel im Flash ablegen
#include <WiFiClientSecure.h>
extern "C" 
  {
    #include "crypto/base64.h"
  }

//-----------------------------------------------------------------------------

// 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
#define Beep_PIN 2 // LED-blau-Pin 
#define RST_PIN 33 // SPI-Pin RST-Pin
#define SDA_PIN 32 // SPI-Pin SS- bzw. SDA-Pin
//-----------------------------------------------------------------------------

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

//Sendedaten an HC3
//-----------------------------------------------------------------------------
String Software_Version = "ESP32_RFID_Garage_V2.0"; // Softwareversion
int age = 0;
String Daten_1 = "";              // Erster Kartendatensatz z.B "Karin Berges"
String Daten_2 = "";              // Zweiter Kartendatensatz z.B "B2 3E 7C 31"                        
String sende_json = "";           // Sendedaten an den HC3
//-----------------------------------------------------------------------------

//RFID-Daten
//-----------------------------------------------------------------------------
struct astruct 
        {
        String RFID_Name;
        String RFID_Code;
        };
struct astruct RFID_Daten[50];      //Maximal 50 RFID-Tag´s sind vorgesehen
//Möglicher zugriff ist : RFID_Daten[3].RFID_Name = "Frank";

String Rohdaten = "";     // Für die Datenübergabe

Preferences preferences; //Abspeichern der Daten 

//-----------------------------------------------------------------------------

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

//Lese und Auswertebestätigung
//-----------------------------------------------------------------------------
bool RFID_gelesen = false;
//-----------------------------------------------------------------------------

//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;    // Transferdaten von http
String input;     // im header endhaltene Daten als json
//-----------------------------------------------------------------------------

//MFRC522-Instanz erstellen
//-----------------------------------------------------------------------------
MFRC522 mfrc522(SDA_PIN, RST_PIN);
//-----------------------------------------------------------------------------

// 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() 
  {  
    //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);

      //ACHTUNG
      //Erst mit der ersten Ausgabe wird die Zeit übertragen zum Internen Timer
      printLocalTime();
      
      //disconnect WiFi
      WiFi.disconnect(true);
       
    // Bestimmen der pin-Funktion
      pinMode(ausgang_1, OUTPUT);
      pinMode(ausgang_2, OUTPUT);
      pinMode(Beep_PIN, OUTPUT);     //Beeper
      digitalWrite(Beep_PIN, LOW);   //RC522
      
    //SPI-Bus Initialisieren
      SPI.begin();

    //RFID-RC522 initialisieren
      mfrc522.PCD_Init();
    
    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();

    //Daten aus dem Flash holen
    Rohdaten = Daten_aus_dem_Flash("Flash_RFID");

    //Json-String in Variabel überführen
    json_string_in_Variabel();

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

//******************************* 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.");          // 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();

                  // Anzeige der Werte im Display
                  display_anzeigen();
                  // send sensor data in JSON format    
                  uebergabestring();            //Zusammenbauen des json Strings
                  //Sendedaten verschlüsseln
                  sende_json = encodeBase64 (sende_json);
                  client.println(sende_json); //Senden des Strings
                  
                  Daten_1 = "";
                  Daten_2 = "";
                  // 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("");
      }
      
    // Einholen der RFID
    RFID_lesen();
    RFID_vergleichen();

    if (RFID_gelesen)
        {
          if (Daten_1 != "Unbekannt")
            {
              // REFID bekannt
              digitalWrite(Beep_PIN, HIGH);
              delay(50); //50ms
              digitalWrite(Beep_PIN, LOW);
            }
          else
            {
              //RFID unbekannt
              digitalWrite(Beep_PIN, HIGH);
              delay(600); //600ms
              digitalWrite(Beep_PIN, LOW); 
            }
          RFID_gelesen = false;
       }
    
    //Ausgabe der Systemzeit
    display_systemzeit();
    
  } // End Loop
//-----------------------------------------------------------------------------

//------------------------------ RFID Auslesen --------------------------------
//-----------------------------------------------------------------------------
void RFID_lesen()
    {
      if (Daten_2 == "") //Die letzen Daten wurden übermittelt?
        {
          String rfidTag= "";
          if (mfrc522.PICC_IsNewCardPresent() && // liegt ein neues Tag vor
              mfrc522.PICC_ReadCardSerial()) 
            { // richtige Tag-Art
              Serial.print("RFID-Tag/Karten-ID:");
              for (byte i = 0; i < mfrc522.uid.size; i++) 
                { // Karten-ID extrah.
                  Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
                  Serial.print(mfrc522.uid.uidByte[i], HEX);
                  rfidTag.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
                  rfidTag.concat(String(mfrc522.uid.uidByte[i], HEX));
                }
              Serial.println();
              Daten_1 = "";
              Daten_2 = rfidTag.substring(1);
              RFID_gelesen = true;          
            }
        }
    }
      

//-----------------------------------------------------------------------------

//---------------------- RFID mit Vorgaben vergleichen ------------------------
//-----------------------------------------------------------------------------
void RFID_vergleichen()
  {
    if (RFID_gelesen)
      {
        for (int i=0; i < 50; i++) 
          {
            if (RFID_Daten[i].RFID_Code == Daten_2)
              {
                //Daten dem Nahmen zuordnen
                Daten_1 = RFID_Daten[i].RFID_Name;
                display_infozeile("RFID Daten gefunden");
                break;
              }
            else
              {
                Daten_1 = "Unbekannt";
              }
          }
      }
  }
//-----------------------------------------------------------------------------

//--------- Aus dem Inputstring die Json Daten holen und verarbeiten ----------
//-----------------------------------------------------------------------------
String reaktionaufanfrage(String Eingangswert)
  {

    // Raussuchen was an Daten gesendet wurde
    Rohdaten = Eingangswert.substring (Eingangswert.indexOf("data:")+5, Eingangswert.indexOf("Content"));
    //Jetzt müssen die Daten noch decodiert werden
    Rohdaten = decodeBase64(Rohdaten);

    if (Eingangswert.indexOf("data/json") > -1)    //Kommen Reaktionsdaten ? -1 = nein
      {
        Serial.println("Daten kommen");
        StaticJsonDocument<128> doc;
        DeserializationError error = deserializeJson(doc, Rohdaten);
        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);
              }

          }   
      }
    if (Eingangswert.indexOf("memo/json") > -1)    //Kommen Speicherdaten ? -1 = nein
      {
        Serial.println("Memos kommen");
        display_infozeile("Neue Daten vom HC3");

        //Json-String <Rohdaten> in Variabel überführen
        json_string_in_Variabel();
        
        //Daten im Flash Abspeichern
        Daten_im_Flash_speichern("Flash_RFID", Rohdaten);
      }
      //In der Globalen Variabel abspeichern
      input = Eingangswert;
  }   
//-----------------------------------------------------------------------------

//--------------- 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"] = "Daten_1";
      configJSON["sensordatavalues"][0]["value"] = Daten_1;
      configJSON["sensordatavalues"][1]["value_type"] = "Daten_2";
      configJSON["sensordatavalues"][1]["value"] = Daten_2;
      configJSON["sensordatavalues"][2]["value_type"] = "signal";
      configJSON["sensordatavalues"][2]["value"] = WiFi.RSSI();
      sende_json = "";
      serializeJson(configJSON, sende_json);
      //Serial.println(sende_json);
    }
//-----------------------------------------------------------------------------


//--------------- Json-String zusammen bauen für das versenden ---------------- 
//-----------------------------------------------------------------------------
void json_string_in_Variabel()
  {
    StaticJsonDocument<1024> doc; //Das solte für einige RFID-Tags reichen
    DeserializationError error = deserializeJson(doc, Rohdaten);
      if (error) 
        {
          Serial.print(F("deserializeJson() failed: "));
          Serial.println(error.f_str());
        }
      else
        {
          const char* time = doc["time"]; // "13:30:22"
          int count = 0;
          for (JsonObject elem : doc["Codedaten"].as<JsonArray>()) 
            {
              ///Daten vom HC3 in einer Structur hinterlegen 
              const char* RFID_Name = elem["RFID_Name"]; // "Karin", "Frank" usw.
              const char* RFID_Code = elem["RFID_Code"]; // "B2 3E 7C 31", "6c 3d 41 33" usw.
              RFID_Daten[count].RFID_Name = RFID_Name;
              RFID_Daten[count].RFID_Code = RFID_Code;
              if (count < 50) // ACHTUNG Max 50 Stück
                {
                  count = count + 1;
                }
            }
        }
      // Jetzt sind die Daten aus dem json in der Struktur.
    Rohdaten = ""; //Wieder leeren
  }


//-----------------------------------------------------------------------------

//--------------------------- BASE64 encode/decode ----------------------------
//-----------------------------------------------------------------------------
String encodeBase64 (String Input_Text)
{
  String Output_Code;
  char* toEncode = strstr( Input_Text.c_str(), "\0" ); //Neue Version
  //char* toEncode = (char*) Input_Text.c_str(); //Alte Version 
  size_t outputLength;
  unsigned char * encoded = base64_encode((const unsigned char *)toEncode, strlen(toEncode), &outputLength);
  Output_Code = (const char*)encoded;
  Output_Code = Output_Code.substring(0,outputLength);
  free(encoded);
  return Output_Code;
}

//.........................................................

String decodeBase64 (String Input_Code)
{
  String Output_Text;
  char* toDecode = strstr( Input_Code.c_str(), "\0" ); //Neue Version
  //char* toDecode = (char*) Input_Code.c_str(); //Alte Version
  size_t outputLength;
  unsigned char * decoded = base64_decode((const unsigned char *)toDecode, strlen(toDecode), &outputLength);
  Output_Text = (const char*)decoded;
  Output_Text = Output_Text.substring(0,outputLength);
  free(decoded);
  return Output_Text;
} 
//-----------------------------------------------------------------------------


//------------------------ Daten im Flash hinterlegen ------------------------- 
//https://github.com/espressif/arduino-esp32/tree/master/libraries/Preferences
//-----------------------------------------------------------------------------
void Daten_im_Flash_speichern(const char * Save_Variabel, String Save_Data)
{
  // Öffenen der Preferences
  // RW-mode (Zweiter parameter muss auf false stehen).
  // Note: Nameslänge des Platzhalters max. 15 Zeichen.
  preferences.begin(Save_Variabel, false);

  // Lösche alle Save_Platzhalten
  //preferences.clear();

  //Löschen nur eines Platzhalters
  preferences.remove(Save_Variabel);

  // Abspeichern der Daten auf den Platzhalter
  preferences.putString(Save_Variabel, Save_Data);

  // Schließen der Preferences
  preferences.end();
}
//-----------------------------------------------------------------------------

//------------------------ Daten aus dem Flash hohlen ------------------------- 
// https://github.com/espressif/arduino-esp32/tree/master/libraries/Preferences
//-----------------------------------------------------------------------------
String Daten_aus_dem_Flash(const char * Save_Variabel)
{
  // Öffenen der Preferences
  // RW-mode (Zweiter parameter muss auf false stehen).
  // Note: Nameslänge des Platzhalters max. 15 Zeichen.
  preferences.begin(Save_Variabel, false);

  // Einholen eines Srings aus dem Flash Platzhalter 1 Variabel
  // Wenn der Platzhalter nicht da ist kommt ein 0 zurück
  // Note: Nameslänge des Platzhalters max. 15 Zeichen.
  String Flash_Daten = preferences.getString(Save_Variabel,"");

  // Schließen der Preferences
  preferences.end();

  return Flash_Daten;
}
//-----------------------------------------------------------------------------

//---------------------------- Ausgabe Systemzeit -----------------------------
//-----------------------------------------------------------------------------
void printLocalTime()
    {
      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_anzeigen()
    {
      // clear display
      display.clearDisplay();
      
      // Alles was ausgegeben wird in der Schriftgroesse
      display.setTextSize(1);

      //display Datensatz RFID 1
      display.setCursor(0,0);
      display.print("Daten_1 : ");
      display.print(Daten_1);
  
      //display Datensatz RFID 2
      display.setCursor(0,10);
      display.print("Daten_2 : ");
      display.print(Daten_2);  

      //display Zeile 3
      //display.setCursor(0,20);
      //display.print("xxxxx   : ");
      //display.print(Variabel);
      //display.print(" xx");  

      //display Zeile 4
      //display.setCursor(0,30);
      //display.print("xxxxxx  : ");
      //display.print(Variabel);
      //display.print(" xx");  

      //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();
          }
      }
  }
//-----------------------------------------------------------------------------

//Für die Anzeige der Infozeile max 22 Zeichen
//-----------------------------------------------------------------------------
void display_infozeile(String Text) 
  {
    //Die alte Anzeige löschen
    display.drawFastHLine(0,20,127,SSD1306_BLACK);
    display.drawFastHLine(0,21,127,SSD1306_BLACK);
    display.drawFastHLine(0,22,127,SSD1306_BLACK);
    display.drawFastHLine(0,23,127,SSD1306_BLACK);
    display.drawFastHLine(0,24,127,SSD1306_BLACK);
    display.drawFastHLine(0,25,127,SSD1306_BLACK);
    display.drawFastHLine(0,26,127,SSD1306_BLACK);
    display.drawFastHLine(0,27,127,SSD1306_BLACK);

    //Text auf 22 Zeichen begrenzen
    Text = Text.substring (0, 22);
    //int x= (128-(Text.length()*6))/2;
    //Text anzeigen
    display.setTextSize(1);
    display.setCursor((128-(Text.length()*6))/2,20);
    display.print(Text);
    display.display();
  }
//-----------------------------------------------------------------------------


// EOF

Ist jetzt kein Meisterwerk aber es funktioniert gut !

Grusse Frank und viel Spas beim basteln.

Hier was nachgeschoben !
Hier könnt Ihr sehen wie es funktioniert !
Chriss wahr so nett und hat es veröffendlicht.
RFID | SmartHome Blog - YouTube

2 Like