Temperaturscanner "Quick and Dirty"

Begonnen von Kharim, 20 Dezember 2015, 09:10:47

Vorheriges Thema - Nächstes Thema

Kharim

Hallo Zusammen,

ich habe mal versucht den (einen) Temperaturscanner nachzubauen.
Dabei waren mir einige persönliche Dinge wichtig, die der MAX Themperatur Scanner von "John" leider nicht "berücksichtigt":
http://forum.fhem.de/index.php/topic,11624.0.html

Das Ergebnis dessen möchte ich euch nun gerne kurz vorstellen:

Ausgangspunkt / Ziele:
- Die IST Themperatur soll immer erfasst werden - auch wenn Fenster geöffnet ist, Boost läuft oder Ähnliches.
  (Gerade im Sommer möchte ich auch bei länger offenem/angekipten Fenster die IST Temperatur erfassen)
- Der Scanner kann nur auf Änderung der Soll Temperatur beruhen
  (Es soll kein Wochenprogramm unterbrochen werden wie beim Moduswechsel)
- Der Scanner darf keine fixe Temperatur besitzen, sondern muss auf der am Thermostat eingestellten Temperatur arbeiten
  (Eine Änderung des Modus/ der Temperatur am Thermostat, darf vom Scanner nicht rückgängig gemacht werden)
- Erfassungszeitraum alle 15 Minuten
- Möglichst wenige Credits verbrauchen -> nur ein Schaltsignal alle 15 Minuten

Umsetzung:
Aus den letzten beiden Punkten ergibt sich eine Themperaturänderung um 0,5°C alle 15 Minuten.
Dies ist vieleicht nicht schön, stört mich persöblich aber herzlich wenig, ob nun die Themperatur ein halbes Grad mehr ist oder nicht.
Zu jedem Thermostat müssen nun also zwei Werte (in Dummys) gespeichert werden:
- die Schaltrichtung (wird die Themperatur erhöht oder verringert)
- Zieltemperatur des vorangegangenen Schaltvorgangs (zur Kontrolle ob dieser Erfolgreich war.)

Nehmen wir also an unser Thermostat hat eine momentane Temperatur von 19°C:
-> Dummy "TScanBadZiel" erstellen und mit Wert "19" versehen
-> Dummy "TScanBadStep" erstellen und mit Wert "-1" versehen
(-1 steht dabei für veringern, 1 für erhöhen der Temperatur)

Dazu gehört eine "at" die alle 15 Minuten läuft, mit dem Attr alignTime 0:00

+*00:15:00 {
if(Value("TScanBadStep") == 1)
{
my $IST=ReadingsVal("ThermostatBad", "desiredTemperature", 0);
my $SOLL=Value("TScanBadZiel");
if($IST <= $SOLL)
{
$SOLL=$IST+0.5;
fhem("set TScanBadZiel $SOLL; set TScanBadStep -1");
fhem("set ThermostatBad desiredTemperature $SOLL");
}
else
{
fhem("set TScanBadZiel $IST; set TScanBadStep -1");
}
}
else
{
if(Value("TScanBadStep") == -1)
{
my $IST=ReadingsVal("ThermostatBad", "desiredTemperature", 0);
my $SOLL=Value("TScanBadZiel");
if($IST >= $SOLL)
{
$SOLL=$IST-0.5;
fhem("set TScanBadZiel $SOLL; set TScanBadStep 1");
fhem("set ThermostatBad desiredTemperature $SOLL");
}
else
{
fhem("set TScanBadZiel $IST; set TScanBadStep 1");
}
}
}
}


Das Ergebnis:
Step = -1
Soll = 19
Ist = 19
-> Step wird auf 1 ; Ziel auf 18,5 und Thermostat auf 18,5 gesetzt

Step=1
Soll= 18,5
Ist = 18,5
-> Step wird auf -1; Ziel auf 19 und Thermostat auf 19 gesetzt

Nehmen wir nun an, zwischenzeitlich gehen die Credits aus, oder die Temperatur wird absichtlich geändert:

Step = -1
Soll = 19
Ist = 12 (geändert druch Nutzer [oder 18,5 da letzter Set Befehel nicht erfolgreich])
Die If erfüllt nicht die Bedingung Ist >= Soll --> Step wird auf 1 gesetzt

Step = 1
Soll = 19
Ist = 21
Die If erfüllt ihre Bedingung nicht -> Step wird auf -1 gesetzt

---------
Vorteile:
- Es wird immer die momentan eingestellte Temperatur zur vollen viertel Stunde berücksichtig.
- Ein Übersteuern (endloses Erhöhen oder Veringern) der Soll Temperatur wird unterbunden.
- Es ergeben sich für jede Viertel Stunde je ein Messwert.

Nachteile:
- Temperaturänderungen kurz vor Viertel werden ignoriert/überschrieben.
(Liegt in der Eigenart der Thermostate begründet -> max 3 Minuten bis Thermostat seinen Wert an Fhem gesendet hat.)
- Die WindowsOpen Temperatur muss auf 5°C gesetzt sein.
  (Also kein OFF möglich.)

Soweit so "gut", vieleicht hilft es ja dem einen oder anderen ;-)

Eine schöne Weihnachtszeit euch allen,
Kharim
Raspberry Pi 2 + Minibian + 2x MAX Cube CUN (868/433Mhz) + Thermostate + Fensterkontakte + Taster+RGB-LED Band über pigpiod + TFA Sensoren 30.3169/3125
Raspberry Pi 2 + Minibian +Z-Wave (USB) + Bewegungsmelder + Fensterkontakt + Sirene + SMS Steuer-/Benachrichtigung (ohne Internet)

Gigafix

Hallo Kharim

Vielen Dank für den "Quick and Dirty"-Code. Ich musste am Ende noch eine }Klammer schließen, dann lief es auch.

Viele Grüße sendet
Gigafix
VM Synology DS918 | CubieTruck |2x HMLAN | HMUSB | 3x HMWLAN | CCU2 | MAX-Cube | nanoCUL | ZWDongle |

Kharim

Sorry, habs korrigiert.

(Ist beim Kopieren verloren gegangen, da bei mir noch weitere Thermostate darunter folgen...)
Raspberry Pi 2 + Minibian + 2x MAX Cube CUN (868/433Mhz) + Thermostate + Fensterkontakte + Taster+RGB-LED Band über pigpiod + TFA Sensoren 30.3169/3125
Raspberry Pi 2 + Minibian +Z-Wave (USB) + Bewegungsmelder + Fensterkontakt + Sirene + SMS Steuer-/Benachrichtigung (ohne Internet)

ghostrider

Hallo zusammen blöde Frage aber wie kann ich diesen Code in meinen Fhem überhaupt integrieren? Ich komme leider noch nicht so gut mit der Thematik klar momentan habe ich den maxscanner von John am Laufen dieser hat aber den unangenehmen Nebeneffekt dass selbst wenn ich das Thermostat auf Manuel Stelle und eine Temperatur manuell einstellen automatisch beim nächsten Scan in das Wochenprogramm wechselt was ich nicht möchte für eure Tipps wäre ich dankbar viele Grüße

Kharim

Hallo ghostrider,

wie du (vielleicht schon) der ersten Zeile entnehmen kannst, handelt es sich hierbei um eine "at" : https://wiki.fhem.de/wiki/At
Du kannst dir eine "leere" at definieren und den Code inkl. Anpassung einkopieren.

Grüße und schöne Ostern,
Kharim
Raspberry Pi 2 + Minibian + 2x MAX Cube CUN (868/433Mhz) + Thermostate + Fensterkontakte + Taster+RGB-LED Band über pigpiod + TFA Sensoren 30.3169/3125
Raspberry Pi 2 + Minibian +Z-Wave (USB) + Bewegungsmelder + Fensterkontakt + Sirene + SMS Steuer-/Benachrichtigung (ohne Internet)

Wzut

Oh je da hat aber jemand einen Oldtimer ausgegraben.... dem sieht man schon sein Alter an und sollte vllt. mal etwas "entstaubt" werden.
D.h. die beiden Dummy brauch man nicht, die zusätzlichen Werte kann man auch gleich ins Device mittels userReadings packen.
Value("xy") würde ich heute niemand mehr empfehlen.
fhem() fhem() Zeilen kann man zusammenpacken genau wie set set
Eigentlich macht man für so etwas eher ein Stückchen Code für die 99_myUtils und übergibt im at nur den Namen, dann ist es auch einfacher und übersichtlicher wenn man mehr als ein HT so steuern möchte.
   
Maintainer der Module: MAX, MPD, UbiquitiMP, UbiquitiOut, SIP, BEOK, readingsWatcher

ghostrider

Scheinbar bin ich zu doof dazu.

Ich bekomme sowas :
Unknown command +*00:15:00, try help.
Unknown command my, try help.
Unknown command if($IST, try help.
Unknown command fhem("set, try help.
Please define TScanBadStep first
Unknown command fhem("set, try help.
Unknown command }, try help.
Please define TScanBadStep first
Unknown command }, try help.
Unknown command my, try help.
Unknown command if($IST, try help.
Unknown command fhem("set, try help.
Please define TScanBadStep first
Unknown command fhem("set, try help.
Unknown command }, try help.
Please define TScanBadStep first
Unknown command }, try help.

MadMax-FHEM

#7
Da würde ich empfehlen: fhem Einsteiger-Doku etc.!

Das was du versuchst einzufügen ist ein "at".

Also mal so:


define atName +*00:15:00 {}


Das ist ein "nacktes" at, welches alle 15min aufgerufen wird und dann eben das was "hinten dran steht" (in dem Fall Perl-Aufrufe) ausführt.

https://wiki.fhem.de/wiki/At

Dann auf DEF und den Rest einfügen, das ist dann das was ausgeführt wird.
Die zuerst mit angegebenen geschweiften Klammern lassen!

https://wiki.fhem.de/wiki/Klammerebenen


if(Value("TScanBadStep") == 1)
{
my $IST=ReadingsVal("ThermostatBad", "desiredTemperature", 0);
my $SOLL=Value("TScanBadZiel");
if($IST <= $SOLL)
{
$SOLL=$IST+0.5;
fhem("set TScanBadZiel $SOLL; set TScanBadStep -1");
fhem("set ThermostatBad desiredTemperature $SOLL");
}
else
{
fhem("set TScanBadZiel $IST; set TScanBadStep -1");
}
}
else
{
if(Value("TScanBadStep") == -1)
{
my $IST=ReadingsVal("ThermostatBad", "desiredTemperature", 0);
my $SOLL=Value("TScanBadZiel");
if($IST >= $SOLL)
{
$SOLL=$IST-0.5;
fhem("set TScanBadZiel $SOLL; set TScanBadStep 1");
fhem("set ThermostatBad desiredTemperature $SOLL");
}
else
{
fhem("set TScanBadZiel $IST; set TScanBadStep 1");
}
}
}


ich hoffe ich habe durch das stückchenweise kopieren jetzt keine Klammer "vergessen" etc. ;)

UND: du musst natürlich die Devicenamen etc. innerhalb des Perl-Teils anpassen an deine Umgebung!

ABER: ich würde empfehlen erst mal etwas mit fhem klar zu kommen und v.a. auch mit Perl etwas "anfreunden"...

EDIT: Stimme Wzut zu, also bzgl. myUtils. Den Rest hab ich mir jetzt nicht angeschaut ;)  https://wiki.fhem.de/wiki/99_myUtils_anlegen Also im oben angelegten "nackten" at dann statt den ganzen Code nur noch die entsprechend angelegte Sub in myUtils aufrufen, also "define atName at +*00:15:00 {mySub()}"

Gruß, Joachim
FHEM PI3B+ Bullseye: HM-CFG-USB, 40x HM, ZWave-USB, 13x ZWave, EnOcean-PI, 15x EnOcean, HUE/deCONZ, CO2, ESP-Multisensor, Shelly, alexa-fhem, ...
FHEM PI2 Buster: HM-CFG-USB, 25x HM, ZWave-USB, 4x ZWave, EnOcean-PI, 3x EnOcean, Shelly, ha-bridge, ...
FHEM PI3 Buster (Test)

Wzut

#8
konnte dann doch nicht die Finger davon lassen ... anbei ein Vorschlag wie man es relativ flexibel in die 99_myUtils schreiben könnte.
(wobei ich kein Freund dieser Creditfresser bin)

sub Tscan {
  my @devices = split(',', shift);
    my $i = -1;
   
    foreach my $device (@devices) {
my $hash   = $defs{$device} // next;

next if (($hash->{devtype} < 1) || ($hash->{devtype} > 2));

my $IST  = ReadingsNum($device, 'desiredTemperature', '0');
$IST = $IST eq 'on' ? 30.5 : ($IST eq 'off' ? 4.5 :$IST);
next if (($IST < 5) || ($IST > 30));

        $i++;
my $SOLL = $hash->{'TScanZ'} // $IST;

if ($hash->{'TScanS'}) {
    $hash->{'TScanS'} = 0;

    if ($IST <= $SOLL) {
$SOLL = $IST+.5;
$hash->{'TScanZ'} = $SOLL;
        if (!$i) {
    CommandSet(undef, "$device desiredTemperature $SOLL");
}
        else {
    CommandDefMod(undef, 'at_Tscan_'.$device.' at +00:'.sprintf(%02d, $i).":00 set $device desiredTemperature $SOLL");
}
    }
    else { $hash->{'TScanZ'} = $IST; }
}
else {
    $hash->{'TScanS'} = 1;

    if ($IST >= $SOLL) {
$SOLL = $IST-.5;
$hash->{'TScanZ'} =  $SOLL;
if (!$i) {
    CommandSet(undef, "$device desiredTemperature $SOLL");
}
else {
    CommandDefMod(undef, 'at_Tscan_'.$device.' at +00:'.sprintf(%02d, $i).":00 set $device desiredTemperature $SOLL");
}
    }
    else { $hash->{'TScanZ'} = $IST; }
}
    }
    return;
}



das at kann dann so aussehen
define atName +*00:15:00 {Tscan('Mein_thermo')}
bzw. wenn mehr als ein HT benutzt werden soll diese als Kommata getrennt Liste übergeben.
define atName +*00:15:00 {Tscan('Thermo_Bad,Thermo_Kueche')}
Bei mehr als einem HT werden die folgenden um jeweils 1 Minute verzögert aufgerufen.
Maintainer der Module: MAX, MPD, UbiquitiMP, UbiquitiOut, SIP, BEOK, readingsWatcher

ghostrider

Hi, also ich habe das so erstellt:

define BueroTEMP at +*00:15:00 {}

das lässt sich jetzt anlegen.

Wenn ich es so schreibe define atName +*00:15:00 {} funktioniert es nicht wie in deinem Post weil das at fehlt !?

Wenn ich jetzt den AT öffne kann ich unter DEF  wo derzeit +*00:15:00 {} steht kann ich in die {} was eintragen.

Das würde ich dort einfügen if(Value("TScanBadStep") == 1)
{
my $IST=ReadingsVal("ThermostatBad", "desiredTemperature", 0);
my $SOLL=Value("TScanBadZiel");
if($IST <= $SOLL)
{
$SOLL=$IST+0.5;
fhem("set TScanBadZiel $SOLL; set TScanBadStep -1");
fhem("set ThermostatBad desiredTemperature $SOLL");
}
else
{
fhem("set TScanBadZiel $IST; set TScanBadStep -1");
}
}
else
{
if(Value("TScanBadStep") == -1)
{
my $IST=ReadingsVal("ThermostatBad", "desiredTemperature", 0);
my $SOLL=Value("TScanBadZiel");
if($IST >= $SOLL)
{
$SOLL=$IST-0.5;
fhem("set TScanBadZiel $SOLL; set TScanBadStep 1");
fhem("set ThermostatBad desiredTemperature $SOLL");
}
else
{
fhem("set TScanBadZiel $IST; set TScanBadStep 1");
}
}
}



Ich muss mein Thermostat anpassen in diesem Fall heißt das Thermostat MAX_0adb5b

Also dann so : Welche Werte müsste ich noch ändern ??

if(Value("TScanBadStep") == 1)
{
my $IST=ReadingsVal("MAX_0adb5b", "desiredTemperature", 0);
my $SOLL=Value("TScanBadZiel");
if($IST <= $SOLL)
{
$SOLL=$IST+0.5;
fhem("set TScanBadZiel $SOLL; set TScanBadStep -1");
fhem("set MAX_0adb5b desiredTemperature $SOLL");
}
else
{
fhem("set TScanBadZiel $IST; set TScanBadStep -1");
}
}
else
{
if(Value("TScanBadStep") == -1)
{
my $IST=ReadingsVal("MAX_0adb5b", "desiredTemperature", 0);
my $SOLL=Value("TScanBadZiel");
if($IST >= $SOLL)
{
$SOLL=$IST-0.5;
fhem("set TScanBadZiel $SOLL; set TScanBadStep 1");
fhem("set MAX_0adb5b desiredTemperature $SOLL");
}
else
{
fhem("set TScanBadZiel $IST; set TScanBadStep 1");
}
}
}






Zitat von: MadMax-FHEM am 27 Oktober 2020, 17:49:32
Da würde ich empfehlen: fhem Einsteiger-Doku etc.!

Das was du versuchst einzufügen ist ein "at".

Also mal so:


define atName +*00:15:00 {}


Das ist ein "nacktes" at, welches alle 15min aufgerufen wird und dann eben das was "hinten dran steht" (in dem Fall Perl-Aufrufe) ausführt.

https://wiki.fhem.de/wiki/At

Dann auf DEF und den Rest einfügen, das ist dann das was ausgeführt wird.
Die zuerst mit angegebenen geschweiften Klammern lassen!

https://wiki.fhem.de/wiki/Klammerebenen


if(Value("TScanBadStep") == 1)
{
my $IST=ReadingsVal("ThermostatBad", "desiredTemperature", 0);
my $SOLL=Value("TScanBadZiel");
if($IST <= $SOLL)
{
$SOLL=$IST+0.5;
fhem("set TScanBadZiel $SOLL; set TScanBadStep -1");
fhem("set ThermostatBad desiredTemperature $SOLL");
}
else
{
fhem("set TScanBadZiel $IST; set TScanBadStep -1");
}
}
else
{
if(Value("TScanBadStep") == -1)
{
my $IST=ReadingsVal("ThermostatBad", "desiredTemperature", 0);
my $SOLL=Value("TScanBadZiel");
if($IST >= $SOLL)
{
$SOLL=$IST-0.5;
fhem("set TScanBadZiel $SOLL; set TScanBadStep 1");
fhem("set ThermostatBad desiredTemperature $SOLL");
}
else
{
fhem("set TScanBadZiel $IST; set TScanBadStep 1");
}
}
}


ich hoffe ich habe durch das stückchenweise kopieren jetzt keine Klammer "vergessen" etc. ;)

UND: du musst natürlich die Devicenamen etc. innerhalb des Perl-Teils anpassen an deine Umgebung!

ABER: ich würde empfehlen erst mal etwas mit fhem klar zu kommen und v.a. auch mit Perl etwas "anfreunden"...

EDIT: Stimme Wzut zu, also bzgl. myUtils. Den Rest hab ich mir jetzt nicht angeschaut ;)  https://wiki.fhem.de/wiki/99_myUtils_anlegen Also im oben angelegten "nackten" at dann statt den ganzen Code nur noch die entsprechend angelegte Sub in myUtils aufrufen, also "define atName at +*00:15:00 {mySub()}"

Gruß, Joachim

ghostrider

Ich muss auch diese Werte definieren ?

-> Dummy "TScanBadZiel"
-> Dummy "TScanBadStep"

???

ghostrider

Hi,

ich habe jetzt auch parallel die  99_myUtils  erstellt .
Wenn ich die define atName +*00:15:00 {Tscan('Mein_thermo')} erstelle bekomme ich Unknown module +*00:15:00
es fehlt hier auch das at hinter dem "atname"  nehme ich an?

Zitat von: Wzut am 27 Oktober 2020, 20:07:34
konnte dann doch nicht die Finger davon lassen ... anbei ein Vorschlag wie man es relativ flexibel in die 99_myUtils schreiben könnte.
(wobei ich kein Freund dieser Creditfresser bin)

sub Tscan {

    my $device = shift;
    my $hash   = $defs{$device} // return; # das Device gibt es gar nicht

    return if (($hash->{devtype} < 1) || ($hash->{devtype} > 2)); # das Device ist kein MAX HT

    my $IST  = ReadingsVal($device, 'desiredTemperature', '0'); # kein ReadingsNum verwenden !
    return if ($IST ne $IST+0); # die desiredTemperature liegt nicht zwischen 5 ... 30 Grad , vllt on / off ?

    my $SOLL = $hash->{'TScanZ'} // $IST; # beim ersten Aufruf einen gültigen Wert vorgeben

    if ($hash->{'TScanS'}) {
$hash->{'TScanS'} = 0;

if ($IST <= $SOLL) {
    $SOLL = $IST + .5;
    $hash->{'TScanZ'} = $SOLL;
    return CommandSet(undef, "$device desiredTemperature $SOLL");
        }
        else { $hash->{'TScanZ'} = $IST; }
    }
    else {
$hash->{'TScanS'} = 1;

if ($IST >= $SOLL) {
    $SOLL = $IST - .5;
    $hash->{'TScanZ'} =  $SOLL;
    return CommandSet(undef, "$device desiredTemperature $SOLL");
}
else { $hash->{'TScanZ'} = $IST; }
    }
    return;
}


das at kann dann so aussehen
define atName +*00:15:00 {Tscan('Mein_thermo')}


Wzut

Zitat von: ghostrider am 28 Oktober 2020, 07:48:20
Ich muss auch diese Werte definieren ?

-> Dummy "TScanBadZiel"
-> Dummy "TScanBadStep"

???
Bei meiner 99_myUtils Lösnung nicht, aber der anderen schon.
Und ja ich war da gestern Abend zu schnell und habe das at im define unterschlagen :
define atName at +*00:15:00 {Tscan('Mein_thermo')}
Maintainer der Module: MAX, MPD, UbiquitiMP, UbiquitiOut, SIP, BEOK, readingsWatcher

ghostrider

Ok,
habe ich so drinne aber:

Wo muss ich was anpassen damit er auch das Gewünschte Thermostat abfragt ?

Wzut

define was_weiss_ich at +*00:15:00 {Tscan('MAX_0adb5b')}
Maintainer der Module: MAX, MPD, UbiquitiMP, UbiquitiOut, SIP, BEOK, readingsWatcher