Hallo
So nun habe ich für mich die Fertige Lösung.
Ich habe das noch erweitert um eine Checksummen Kontrolle des Datenverkehres.
Erst wollte ich noch eine Verschlüsselung ala ENIGMA einbauen aber das war mir dann doch zu Oversized für so eine Aufgabe.
Ich hoffe es kann einer gebrauchen zumindest zum abschauen wie so etwas gemacht werden kann.
Hier der HC3 Teil
--[[
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.1
Ersteller : Frank Berges
Datum : 07.04.2021
* --------------------------------------------------------------------------
* 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.
* V2.1 21.4.2021 F.B.
* - Alle Daten-Packete im Wlan mit Checksumm überwacht
* HC3 <-> ESP32
* Bei falscher Checksumm wird auf das Nächste Packet gewartet
* - Fehler beim Abspeichern der RFID Werte im Flash behoben
* - Fehlermeldung Checksumm und Datenpacket hinzugefügt
*
* =============================================================================
--]]
--******************* 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)
if response.data ~= "Fehler Checksumme" then
--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
self:RFID_auswerten() -- Daten vom ESP32 auswerten
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 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)
if response.data ~= "Fehler Checksumme" then
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
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_sub(data_sub)
return ((data_sub: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_sub%3+1])
end
function Base64enc(data)
data = Base64enc_sub(data)
-- Checksumme erstellen von Data
local Summe = 0
for i=1,string.len(data) do
if string.find(b,string.sub(data,i,i)) ~= nil then
Summe = Summe + string.find(b,string.sub(data,i,i))
end
end
Summe = "0000000000"..tostring(Summe) --Darstellung anpassen
Summe = string.sub(Summe,string.len(Summe)-9,string.len(Summe)) -- Max 10 Zeichen
data = data..Summe
return data
end
-- decoding
function Base64dec(data)
local Check = string.sub(data,string.len(data)-11,string.len(data)-2) --CR&LF müssen weg
data = string.sub(data,1,string.len(data)-12)
local Summe = 0
-- Checksumme erstellen von Data
for i=1,string.len(data) do
if string.find(b,string.sub(data,i,i)) ~= nil then
Summe = Summe + string.find(b,string.sub(data,i,i))
end
end
Summe = "0000000000"..tostring(Summe) --Darstellung anpassen
Summe = string.sub(Summe,string.len(Summe)-9,string.len(Summe)) -- Max 10 Zeichen
if Check == Summe then
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))
else
print("Fehler Checksumme der ESP32 Daten")
return "Fehler Checksumme"
end
end
-- end of copy
------------------------------------------------------------------
--EOF
Teil 2 nächster Post