Vorstellung SPS- ähnliche Bewässerungssteuerung mit Rezepten

Begonnen von fiedel, 28 Juli 2016, 13:57:18

Vorheriges Thema - Nächstes Thema

fiedel

Nur vorab gepostet für Cocktail- Thread, wird noch ergänzt...


Start- Notify:

#FS20_HM_Gar_A_Sw_01:closed.*|#FS20_HM_Gar_A_Sw_01:open.*|Beregnung_0.:off.*|Beregnung_0.:on.*|Dum_Irrig_Main_Start_D:man.*|Dum_Irrig_Main_Start_D:on.*|FB_HM_1_Btn_03.LongRelease.*|FB_HM_1_Btn_03.Short.*|FB_HM_1_Btn_04:LongRelease.*|FB_HM_1_Btn_04:Short.*|Fake_PRM:off.*|Fake_PRM:on.* {

my $aufruf = "$NAME" ; # Zuweisung auslösender Aktor / Sender / FHEM- Funktion
my $stat = "$EVENT" ; # Zuweisung Status des Auslösers
my @vent_nr_arr = split('[Beregnung_0]', $aufruf); # Aufsplitten Ventilname in "1...4" Trenner: "Beregnung_0"
my $vent_nr = $vent_nr_arr[11] || 0 ; # Zuweisung Ventilnummer "1...4"
my @event_arr = split('[ ]', $EVENT) ; # Aufsplitten von Event Trenner: "Leerzeichen"
my $evt = $event_arr[0] ; # Zuweisung Event erster Teil
my $rez_str = "0" ; # Rezept String: Array wird zur Übergabe in Str. gewand. und danach wieder gesplittet
my $return = "empty" ; # Var. "return": busy ; ready ; end ? oder 0...3 ? (kommt aus myUtils- Routine)
my $reset = "0" ; # Reset der Beregnungsroutine auslösen
my $rez_ptr = ReadingsVal("Dum_Irrig_Main_Start_D","irrig_rec_ptr",0) ; # Referenz auf Array "@rezepte" in "irrig_run"
my $act_vent = ReadingsVal("Dum_Irrig_Main_Start_D","irrig_act_vent",0) ; # Aktives Ventil
my $sens_ws_g = Value("FS20_HM_Gar_A_Sw_03") ; # Sens_WS_Garage (open, closed)
my $sens_rm_g = Value("FS20_HM_Gar_A_Sw_02") ; # Sens_RM_Garage (open, closed)

# 2D-Array "Rezepte", jede Zeile bildet ein Rezept mit Programmnummer und Pumpen- + Ventilzeiten in Sek.:
my @rezepte = ( # $mode,$t_pump,$t_valve1,$t_valve2,$t_valve3,$t_valve4
[ 0, 0, 0, 0, 0, 0 ], # [0] Rezept "Stop und Reset"
[ 1, 14400, 14400, 14400, 14400, 14400 ], # [1] Rezept "Halbautom. Weiterschaltung"
[ 2, 3800, 0, 0, 0, 3600 ], # [2] Rezept "Halbautom. Dosen ein für 1h"
[ 3, 3600, 10, 10, 10, 0 ], # [3] Rezept "Beregnung Auto standart"
[ 4, 3600, 3, 3, 3, 0 ], # [4] Rezept "Beregnung Auto reduziert"
[ 5, 90, 10, 10, 10, 10 ], # [5] Rezept "Beregnung Auto Demo / Tiervertreibung"
[ 6, 30, 0, 0, 0, 6 ], # [6] Rezept "Gießkanne füllen Auto"
);

# Je nach Aufruf Rezept an Sub übergeben und Pointer merken:
if ($rez_ptr == 0 and $act_vent == 0) {
if ($aufruf eq "Dum_Irrig_Main_Start_D" and $evt eq "on") {
$rez_ptr = 3 ; # "Beregnung Auto standart"
}
if ($aufruf eq "FB_HM_1_Btn_03" and $evt eq "LongRelease") {
$rez_ptr = 3 ; # "Beregnung Auto standart"
}
if ($aufruf eq "FB_HM_1_Btn_03" and $evt eq "Short") {
$rez_ptr = 1 ; # "manuelle Weiterschaltung"
}
if ($aufruf eq "FB_HM_1_Btn_04" and $evt eq "Short") {
$rez_ptr = 6 ; # "Auto Gießkanne füllen"
}
if ($aufruf eq "FB_HM_1_Btn_04" and $evt eq "LongRelease") {
$rez_ptr = 2 ; # "Auto Dosen ein für 1h"
}
  }
fhem("set Dum_Irrig_Main_Start_D irrig_rec_ptr $rez_ptr") ; # Rezeptpointer merken bis Prog. fertig

# Sub nachtriggern wenn Ventil on -> off um Fehlerüberw. D zu starten:
if ($aufruf eq "Beregnung_0$vent_nr" and $evt eq "off") {
if ($rez_ptr >= 3 and $act_vent <= 6) {
# Log 1, "Beregnungsprogramm $rez_ptr Nachtriggerung bei Ventil $vent_nr off" ;
fhem("sleep 1 ; set Dum_Irrig_Main_Start_D on") ;
}
}

# Halbautom. Mode, aktives Ventil off per Button zum Weitertakten durch Sub:
if ($rez_ptr == 1 and $act_vent > 0) {
if ($aufruf eq "FB_HM_1_Btn_03" and $evt eq "Short") {
fhem("set Dum_Irrig_Main_Start_D irrig_man_tbit 0 ; set Beregnung_0$act_vent off ;  
  sleep 3 ; set Dum_Irrig_Main_Start_D man") ;
}
}

# Wassersteckdosen ausschalten per Button wenn Nutzung beendet:
if ($rez_ptr == 2 and $act_vent == 4) {
if ($aufruf eq "FB_HM_1_Btn_04" and $evt eq "LongRelease") {
fhem("set Dum_Irrig_Main_Start_D irrig_man_tbit 0 ; set Beregnung_0$act_vent off ;  
  sleep 3 ; set Dum_Irrig_Main_Start_D man") ;
}
}

# Alle Programme abbrechen per "Button am Ring Lang"
if ($aufruf eq "FB_HM_1_Btn_03" and $evt eq "LongRelease") {
if ($rez_ptr > 0 and $act_vent > 0) {
irrig_run("0,0,0,0,0,0",1) ; # "Stop und Reset alle Programme"
Log 1, "Beregnungsprogramm $rez_ptr per Reset- Button abgebrochen" ;
}
}
# Log 1, "Aufruf:$aufruf ; Stat (Event):$stat ; Evt:$evt ; Ptr:$rez_ptr" ;
# Übergabe vorbereiten und Sub aufrufen:
$rez_str = join(",", @{$rezepte[$rez_ptr]}[0..5]); # Werte aus mehrdim. Array "rezepte" auslesen und in Reihe mit Trennz. (,) schreiben
$return = irrig_run($rez_str,$reset); # Aufruf der myUtils- Sub -> Übergaben: Rezept und Reset (Stoppt Programm und setzt
# attr- Variablen auf 0, wenn $reset = 1 übergeben wird)

    # Log 1, "CFG: Func_Irrig_Main_N aufger.: Aufruf:$aufruf ; Event:$stat ; Pointer: $rez_ptr ; Return:$return" ;
    # Beispiel Aufruf.: Beregnung_01=on : Aufruf: Beregnung_01 Event: on
# Beispiel Button: if ($aufruf eq "FB_HM_1_Btn_03" and $evt eq "LongRelease")

}


myUtils (Perlroutine):

##############################################
package main;

use strict;
use warnings;
use POSIX;

sub
myUtils_Garden_Initialize($$)
{
  my ($hash) = @_;
}

##################################################
# Beregnung Schrittkette und Manuelle Steuerung: #
##################################################
sub irrig_run($$) {

  # Parameterübergabe:
  my ($rezept, # Rezeptstring (wird anschließend gesplittet)
      $reset, # Reset Funktion: Aufruf nach Fehler oder Programmende
     ) = @_;

  # Rezeptsarray aus Übergabe- Rezeptstring splitten (Trennzeichen = ","):
  # 0:Mode, 1:Zeit Pumpe, 2:Zeit Ventil_1, 3:Zeit Ventil_2, 4:Zeit Ventil_3, 5:Zeit Ventil_4
  my @rezdat = split(',', $rezept) ;

  # Variablen für Programmkontrolle:
  my $mode = $rezdat[0] ; # Programm- Mode
  my $return = "empty" ; # Rückgabewert zum aufrufenden Notify
  my $start = Value("Dum_Irrig_Main_Start_D") ; # Startbutton für Auto 3 im Webinterface
  my @vent_step = 0,0,0,0 ; # Liste Ventilfolge für aktives Programm
  my $run_cnt_max = 0 ; # Rundenzahl Sollwert für aktives Programm
  my $l_cnt = 0 ; # Anzahl Schleifendurchläufe der Vorbereitung
  my $run_cnt = ReadingsVal("Dum_Irrig_Main_Start_D","irrig_run_cnt",0) ; # Merker Aktuelle Rundenzahl
  my $vent_act = ReadingsVal("Dum_Irrig_Main_Start_D","irrig_act_vent",0) ; # Merker Ventilnummer für aktuellen Schritt
  my $manual = ReadingsVal("Dum_Irrig_Main_Start_D","irrig_man_tbit",0) ; # Merker Toggle- Bit für Halbautomatik   
  # Variablen der Gerätestati:
  my $p_state = Value("Beleuchtung_Gar_01") ;   # Pumpe Bewässerung
  my $prm_state = Value("Fake_PRM") ; # Pumpe Bewässerung Rückmeldung -> noch ändern auf echte PRM -> Value("FS20_HM_Gar_A_Sw_02") ; (open, closed)
  # my $v1_state = Value("Beregnung_01") ;     # Ventil 1 (Rasen hinten)
  # my $v2_state = Value("Beregnung_02") ;     # Ventil 2 (Rasen mitte)
  # my $v3_state = Value("Beregnung_03") ;     # Ventil 3 (Rasen vorn)
  # my $v4_state = Value("Beregnung_04") ;     # Ventil 4 (Wassersteckdosen)
  my $v_struct = Value("Ventile") ;     # Struktur alle Ventile

# Vorbereitung: Aus Rezeptarray Rundenzahl und Ventilfoge auslesen
# Wenn Ventil beregnen soll (Zeit- Wert > 0) -> erhöhe Rundenvar.
# um 1, schreibe in Ventil- Rundenarray-Teil mit der aktuellen
# Rundenzahl den aktuellen Durchlaufwert -2 (Ventilnummer)
###################################################################

foreach (@rezdat) {
$l_cnt ++ ;
  if ($l_cnt > 2 and $_ > 0) {
$vent_step[$run_cnt_max] = $l_cnt - 2 ; # Ventil-Rundenarray[Schleifendurchlauf mit Bedingung erfüllt]
$run_cnt_max ++ ; # = Schleifendurchlauf - 2 -> schiebt die reale Ventilnummer
} # immer dann in das Array, wenn auch eine Zeit > 0 vorliegt
# Log 1, "Durchlaufausg.: $l_cnt -> $_<br>\n";
}
# Log 1, "Test Schleife: l_cnt:$l_cnt ; run_cnt_max:$run_cnt_max ; vent_step:@vent_step" ;

# Beispielausgaben des obigen Testlog (Test Schleife):
# Test Schleife: l_cnt:6 ; run_cnt_max:4 ; vent_step: 1 2 3 4 (Rezept 1)
# Test Schleife: l_cnt:6 ; run_cnt_max:3 ; vent_step: 1 2 3 (Rezept 3)
# Test Schleife: l_cnt:6 ; run_cnt_max:1 ; vent_step: 4 (Rezept 6)

# Pumpe starten und Start überwachen:
if ($mode > 0 and $run_cnt == 0 and $p_state eq "off" and $prm_state eq "off" and $manual == 0 and $v_struct eq "off") {
#Log 1, "Test irrig_run 1: Mode:$mode ; Run Count:$run_cnt ; Pumpe:$p_state ; PRM:$prm_state" ;
if (!$defs{Irrig_Pump_Fail_A}) {
$return = "pump_startup" ;
Log 1, "Beregnungsprogramm $mode gestartet";
# Starte Pumpe mit Zeit aus Rezept, setze Manual Toggle- Bit (Ablauf ohne PRM):
fhem("set Beleuchtung_Gar_01 on-for-timer $rezdat[1]") ;
if ($mode <= 2) {
# Sub triggern für Manual- Programme (haben keine PRM- Überwachung):
fhem("sleep 3 ; set Dum_Irrig_Main_Start_D man") ;
# Fehlerüberwachung A (nur Auto-Programme): Nach Pumpenstart keine Rückmeldung innerhalb 3 Sek.
}
if ($mode >= 3) {
fhem("define Irrig_Pump_Fail_A at +00:00:06 {irrig_run('0,0,0,0,0,0',1)};;
{Log 1, 'Fehler_A bei Pumpenstart (Stop): Funkstör. oder Stromausf. (PRM=on zu spät)'}") ;
}
} else {
Log 1, "1.:Pumpe + Programm nicht gestartet: Irrig_Pump_Fail_A war noch aktiv!" ;
$reset = 1 ;
}
}

# Wenn Pumpenückmeld. "on" kommt, Fehlertimer A löschen, damit Runde 1 gestartet werden kann:
if ($mode >= 3 and $p_state eq "on" and $prm_state eq "on" and $run_cnt == 0 and $v_struct eq "off") {
#Log 1, "Test irrig_run 2: Mode:$mode ; Run Count:$run_cnt ; Pumpe:$p_state ; PRM:$prm_state" ;
if ($defs{Irrig_Pump_Fail_A}) {
$return = "del_fail_a_prog_$mode" ;
fhem("delete Irrig_Pump_Fail_A") ;
  } else {
Log 1, "2.:Startphase abgebrochen: Irrig_Pump_Fail_A war nicht vorhanden!" ;
$reset = 1 ;
}
}

# Wenn Pumpenückmeld. "off" kommt (Druck steht), Schrittvariable erhöhen, Runde und Überwachung starten :
if ($mode > 0 and $run_cnt < $run_cnt_max and $p_state eq "on" and $v_struct eq "off") {
if (($mode <= 2 and $manual == 0) or ($mode >= 3 and $prm_state eq "off")) {
#Log 1, "Test irrig_run 3: Mode:$mode ; Run Count:$run_cnt ; Pumpe:$p_state ; PRM:$prm_state ; Vent.Struct:$v_struct" ;
if (!$defs{Irrig_Pump_Fail_A}) {
$vent_act = $vent_step[$run_cnt] ; # Ventil für aktuelle Runde aus Ventil- Rundenarray holen
$run_cnt ++ ; # Rundenzähler um 1 erhöhen
fhem("set Dum_Irrig_Main_Start_D irrig_run_cnt $run_cnt ;
  set Dum_Irrig_Main_Start_D irrig_act_vent $vent_act") ; # Merker aktualisieren
$return = "valve_startup V$run_cnt" ;
# Log 1, "Test irrig_run 3a: Run Count:$run_cnt Vent_Act:$vent_act" ;
# Starte Runden- Ventil mit Zeit aus Rezept:
fhem("set Beregnung_0$vent_act on-for-timer $rezdat[$vent_act + 1]") ;
if ($mode <= 2) {
fhem("set Dum_Irrig_Main_Start_D irrig_man_tbit 1") ; # Toggle- Bit setzen im Manual- Mode
}
# Log 1, "Ventil $run_cnt im Modus Auto gestartet";
# Log 1, "Test irrig_run 3b: Mode:$mode ; Run Count:$run_cnt ; Ventilzeit:$rezdat[$run_cnt + 1] ; Pumpe:$p_state ; PRM:$prm_state ; Vent.Struct:$v_struct" ;
# Fehlerüberwachung B (nur Auto-Programme): Nach Ventilstart keine Pumpenückmeld. = on innerhalb 3 Sek.:
if ($mode >= 3) {
# Zuerst Fehlertimer D löschen wenn vorhanden:
if ($defs{Irrig_Pump_Fail_D}) {
$return = "del_fail_d_prog_$mode" ;
fhem("delete Irrig_Pump_Fail_D") ;
}
# Fehlertimer B starten:
fhem("define Irrig_Pump_Fail_B at +00:00:05 {irrig_run('0,0,0,0,0,0',1)};;
  {Log 1, 'Fehler_B bei Ventilstart $run_cnt (Stop): Hahn geschl., Funkstör. oder Stromausf. (PRM=on zu spät)'} ");
  }
# Entprelltimer C: Startverzögerung für Fehlerüberwachung und Entprellen für Manual Mode:
fhem("define Irrig_Pump_Fail_C at +00:00:02 {undef}");
} else {
Log 1, "3.:Runde $run_cnt abgebrochen: Irrig_Pump_Fail_A war noch vorhanden!" ;
$reset = 1 ;
}
}
}

# Wenn Pumpenückmeld. "on" bei geöffnetem Ventil kommt, Fehlertimer B löschen:
if ($mode >= 3 and $p_state eq "on" and $prm_state eq "on" and $run_cnt > 0 and $v_struct eq "undefined") {
#Log 1, "Test irrig_run 4: Mode:$mode ; Run Count:$run_cnt ; Pumpe:$p_state ; PRM:$prm_state ; V_Struct:$v_struct" ;
if ($defs{Irrig_Pump_Fail_B}) {
$return = "del_fail_b_prog_$mode" ;
fhem("delete Irrig_Pump_Fail_B") ;
}
}

# Fehlerüberwachung C: Nach Ventilstart Pumpenückmeld. = off vor Ventil = off (Problem mit Pumpe oder Wasser)
if ($prm_state eq "off" and $v_struct eq "undefined" and $p_state eq "on") {
if ($mode >= 3 and $run_cnt > 0 and $run_cnt < $run_cnt_max) {
if (!$defs{Irrig_Pump_Fail_C}) {
$return = "fail_c_prog_$mode" ;
#Log 1, "Test irrig_run 5: Mode:$mode ; Run Count:$run_cnt ; Pumpe:$p_state ; PRM:$prm_state ; V_Struct:$v_struct" ;
Log 1, "Fehler_C in Runde $run_cnt (Stop): Wassermangel, Hahn geschl., Verstopf., oder Pumpenstör. (PRM=off vor Vent. Ende)";
$reset = 1 ;
}
}
}

# Fehlerüberwachung D: Nach Ventil = off Pumpenückmeld. nicht off innerh. 3 Sek. (Vent. defekt oder undicht)
if ($v_struct eq "off" and $prm_state eq "on" and $p_state eq "on") {
if ($mode >= 3 and $run_cnt > 0) { #and $run_cnt < $run_cnt_max
if (!$defs{Irrig_Pump_Fail_C}) {
# Log 1, "Test irrig_run Fehl.D: Mode:$mode ; Run Count:$run_cnt ; Pumpe:$p_state ; PRM:$prm_state ; V_Struct:$v_struct" ;
fhem("define Irrig_Pump_Fail_D at +00:00:06 {irrig_run('0,0,0,0,0,0',1)};;
{Log 1, 'Fehler_D in Runde $run_cnt (Stop): Ansaug. zuges., Vent. def. (offen), Undichtigk. vor Vent., o. Pumpenstör (PRM=on nach Vent. off)'}") ;
}
}
}

# Wenn Druck steht nach letzter Runde, beende Programm:
if ($run_cnt >= $run_cnt_max and $p_state eq "on" and $v_struct eq "off") {
if (($mode > 0 and $mode <= 2 and $manual == 0) or ($mode >= 3 and $prm_state eq "off")) {
if (!$defs{Irrig_Pump_Fail_C}) { # zum Entprellen bei Rundenstart
if ($defs{Irrig_Pump_Fail_D}) { # Fehler D löschen wenn Druck steht nach letztem Ventil = off
$return = "del_fail_d_prog_$mode" ;
fhem("delete Irrig_Pump_Fail_D") ;
}
$return = "end_prog_$mode" ;
#Log 1, "Test irrig_run 6: Mode:$mode ; Run Count:$run_cnt ; Pumpe:$p_state ; PRM:$prm_state ; V_Struct:$v_struct" ;
Log 1, "Beregnungsprogramm $mode erfolgreich beendet";
$reset = 1 ;
}
}
}

# Reset- Routine, Merker zurücksetzen, Pumpe und Ventile stoppen:
if ($reset == 1) {
#Log 1, "Test Utils Reset: Mode:$mode ; Run Count:$run_cnt ; Pumpe:$p_state ; PRM:$prm_state ; V_Struct:$v_struct" ;
fhem("set Dum_Irrig_Main_Start_D irrig_rec_ptr 0 ; set Dum_Irrig_Main_Start_D irrig_run_cnt 0 ;
  set Dum_Irrig_Main_Start_D irrig_man_tbit 0") ;  
$mode = 0 ;
$run_cnt = 0 ;
$manual = 0 ;
$return = "done" ;
if (Value("Beregnung_0$vent_act") eq "on") {
fhem("set Beregnung_0$vent_act off") ;
}
if ($start eq "on") {
fhem("sleep 3 ; set Dum_Irrig_Main_Start_D off") ;
}
if ($p_state eq "on") {
fhem("set Beleuchtung_Gar_01 off") ;
}
fhem("set Dum_Irrig_Main_Start_D irrig_act_vent 0") ;
}


# Tipps, Tricks und Logausgaben aus Entwicklungsphase:
# Beispiel für Zeitberechnung (z.B. für Fehlertimer)
# my $time_sum = $t_pump + $t_valve1 + $t_valve2 + $t_valve3 + $t_valve4 ;
# Regex für Ventile 1-4: /(Beregnung_0[1-4])/
# Regex für Ventil 1: /(Beregnung_0[1])/ 
# Stop- Aufruf: {irrig_run("0,0,0,0,0,0",1)} oder {irrig_run('0,0,0,0,0,0',1)} (je nach Einsatzort)

# Funktion Rezeptschleife: Beispielrez. 5,20,0,0,0,6
# V1=0 -> ignorieren -> V2=0 -> ign. -> V3=0 -> ign. -> V4=6 -> schreibe 4 in erste Stelle (0) des
# Array @vent_step und erhöhe $run_cnt_max um 1 (ergibt 1 Runde beginnend mit Ventil 4)

# Log 1, "irrig_run: Variablen: Mode:$mode, Run_cnt_max:$run_cnt_max, Run_cnt:$run_cnt, Rezadat[run_cnt+2]:$rezdat[$run_cnt + 2], p_state:$p_state, prm_state:$prm_state, manual:$manual, V_struct:$v_struct " ;
# Log 1, "irrig_run: Übergabe:@_ " ;
return "$return" ;
}


FeatureLevel: 6.1 auf Wyse N03D ; Deb. 11 ; Perl: v5.14.2 ; IO: HM-MOD-RPI-PCB + VCCU|CUL 868 V 1.66|LinkUSBi |TEK603
HM: SEC-SCO|SCI-3-FM|LC-SW4-PCB|ES-PMSW1-PL|RC-4-2|SEN-MDIR-O|SEC-WDS-2
CUL: HMS100TF|FS20 S4A-2 ; OWDevice: DS18S20|DS2401|DS2406|DS2423

spacy

Hallo,

ist ja mal interessant. Sage mal wie machst du die Tier erkennung. Könnte ich hier bei mir auch gebrauchen. Die Nachbarskatzen kacken mir immer den schönen Rasen voll.

Danke und Gruß
Spacy

fiedel

Ist noch todo, aber vorgesehen ist eine IP Cam mit Mehrzonen- Bewegungserkennung.
FeatureLevel: 6.1 auf Wyse N03D ; Deb. 11 ; Perl: v5.14.2 ; IO: HM-MOD-RPI-PCB + VCCU|CUL 868 V 1.66|LinkUSBi |TEK603
HM: SEC-SCO|SCI-3-FM|LC-SW4-PCB|ES-PMSW1-PL|RC-4-2|SEN-MDIR-O|SEC-WDS-2
CUL: HMS100TF|FS20 S4A-2 ; OWDevice: DS18S20|DS2401|DS2406|DS2423

justme1968

ist zwar off topic...

hast die eine cam gefunden bei der die bewegungserkennung gut genug dafür ist?

meine versuche hatten alle nachts das problem das falter sich so bewegen und bei ir beleuchtung so sehr zurück stahlen das es unmengen falsch positiver gibt.

gruss
  andre
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

fiedel

Hi Andre,

das leuchtet ein...  ;D Da ich ohnehin die ganze Rasenfläche überwachen muss, wird wohl noch ein IR- LED Strahler her müssen. Den könnte ich dann so positionieren, dass die alten Falter  ;) ausserhalb des Sichtfeldes tanzen gehen. Ich spare übrigens noch auf eine Mobotix S 15d mit hemisphärischen Tag- und Nachtsensoren. Die kommt ggf. auch ohne IR- Leuchte aus. Mal sehen, ob und wann ich das Projekt in Angriff nehme. Im Kopf habe ich es schon seit ca. 2010.  :o 

Gruß
Frank
FeatureLevel: 6.1 auf Wyse N03D ; Deb. 11 ; Perl: v5.14.2 ; IO: HM-MOD-RPI-PCB + VCCU|CUL 868 V 1.66|LinkUSBi |TEK603
HM: SEC-SCO|SCI-3-FM|LC-SW4-PCB|ES-PMSW1-PL|RC-4-2|SEN-MDIR-O|SEC-WDS-2
CUL: HMS100TF|FS20 S4A-2 ; OWDevice: DS18S20|DS2401|DS2406|DS2423