Neues Modul: EQ3 Bluetooth Thermostat (10_EQ3BT)

Begonnen von dominik, 12 November 2016, 11:45:15

Vorheriges Thema - Nächstes Thema

Master_Nick

Rancher K8s Cluster mit nanoCUL (a-culfw) | IObroker | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem | WOL | NFC | Harmony UltimateHub | Anwesenheitserkennnung | Roomba | 10" Touch mit Node-Red | SonOff S20 | SonOff Touch | SonOff Dual | Rolladen | Und ganz viel anderes tolles Gerödel.... ;-)

Master_Nick

#241
Wollte mich nachher mit befassen, kann es sein, dass die "ps -A" Geschichte für gatttool über SSH gar nicht ausgeführt wird?

Habe nun aktuell 2 Thermostate in Betrieb - eines wird partout nicht ausgelesen.
Rancher K8s Cluster mit nanoCUL (a-culfw) | IObroker | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem | WOL | NFC | Harmony UltimateHub | Anwesenheitserkennnung | Roomba | 10" Touch mit Node-Red | SonOff S20 | SonOff Touch | SonOff Dual | Rolladen | Und ganz viel anderes tolles Gerödel.... ;-)

CoolTux

welche ps -A, da sollte kein ps -A sein.
Oder meinst
qx(ps ax| grep -E \'gatttool

Ja das funktioniert nicht bei ssh, also nicht wie es im Modul gemacht wurde. Man müsste das alles mal sauber umschreiben.
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

Master_Nick

Genau das meinte ich.

Ja wäre ja über ssh machbar mit einem pidof gatttool und dann nix tun solange das ergebnis true (also etwas zurück kommt) ist.
Rancher K8s Cluster mit nanoCUL (a-culfw) | IObroker | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem | WOL | NFC | Harmony UltimateHub | Anwesenheitserkennnung | Roomba | 10" Touch mit Node-Red | SonOff S20 | SonOff Touch | SonOff Dual | Rolladen | Und ganz viel anderes tolles Gerödel.... ;-)

CoolTux


while($wait) {
       
            my $grepGatttool;
            $grepGatttool = qx(ps ax| grep -E \'gatttool -i $hci -b $mac\' | grep -v grep) if($sshHost eq 'none');
            $grepGatttool = qx(ssh $sshHost 'ps ax| grep -E "gatttool -i $hci -b $mac" | grep -v grep') if($sshHost ne 'none');

            if(not $grepGatttool =~ /^\s*$/) {
                Log3 $name, 3, "($name) - ExecGatttool_Run: another gatttool process is running. waiting...";
                sleep(1);
            } else {
                $wait = 0;
            }
        }


Finde ich persönlich am saubersten
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

Master_Nick

Hehe  ;) da baut er mal eben ne Zeile Code... (*testing*)
Rancher K8s Cluster mit nanoCUL (a-culfw) | IObroker | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem | WOL | NFC | Harmony UltimateHub | Anwesenheitserkennnung | Roomba | 10" Touch mit Node-Red | SonOff S20 | SonOff Touch | SonOff Dual | Rolladen | Und ganz viel anderes tolles Gerödel.... ;-)

Master_Nick

#246
Was war denn dein Gedanke was $hci beinhaltet?
Den gibt es so in dem Moment an der Stelle wohl noch nicht.
Weiter unten gibt es $hciDevice (der ist aber nicht global wie es scheint)

So Modul "lädt" immerhin nach diversen Versuchen wo es nicht lud wieder:

sub EQ3BT_execGatttool($) {
#   ZUSATZ
    my ($hash) = @_;
    EQ3BT_updateHciDevicelist($hash);
#   ORIGINAL
    my ($string) = @_;
    my ($name, $mac, $workType, $handle, $value, $listen) = split("\\|", $string);
my $hciDevice = "hci".$hash->{helper}{hcidevices}[$hash->{helper}{currenthcidevice}];
    my $wait = 1;
    my $hash = $main::defs{$name};
   
    my $gatttool = qx(which gatttool);
    chomp $gatttool;
   
    if(-x $gatttool) {
        my $gtResult;
        my $cmd;
        my $sshHost     = AttrVal($name,"sshHost","none");
       
while($wait) {
       
            my $grepGatttool;
            $grepGatttool = qx(ps ax| grep -E \'gatttool -i $hciDevice -b $mac\' | grep -v grep) if($sshHost eq 'none');
            $grepGatttool = qx(ssh $sshHost 'ps ax| grep -E "gatttool -i $hcidevices -b $mac" | grep -v grep') if($sshHost ne 'none');

            if(not $grepGatttool =~ /^\s*$/) {
                Log3 $name, 3, "($name) - ExecGatttool_Run: another gatttool process is running. waiting...";
                sleep(1);
            } else {
                $wait = 0;
            }
        }



Er meckert nun aber an:
Zitat
(bluetoothctl:26942): GLib-CRITICAL **: Source ID 20 was not found when attempting to remove it

(bluetoothctl:26944): GLib-CRITICAL **: Source ID 21 was not found when attempting to remove it
Can't use string ("Arbeitszimmer_Thermostat|00:1A:2"...) as a HASH ref while "strict refs" in use at ./FHEM/10_EQ3BT.pm line 200.
Can't use string ("Wohnzimmer_Thermostat|00:1A:22:0"...) as a HASH ref while "strict refs" in use at ./FHEM/10_EQ3BT.pm line 200.

Denke mal der inhalt von $hciDevice ist nicht was du in $hci haben wolltest - ich tippe auf "hci"/"hci0" etc.
Rancher K8s Cluster mit nanoCUL (a-culfw) | IObroker | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem | WOL | NFC | Harmony UltimateHub | Anwesenheitserkennnung | Roomba | 10" Touch mit Node-Red | SonOff S20 | SonOff Touch | SonOff Dual | Rolladen | Und ganz viel anderes tolles Gerödel.... ;-)

CoolTux


sub EQ3BT_execGatttool($) {
    my ($string) = @_;
    my ($name, $mac, $workType, $handle, $value, $listen) = split("\\|", $string);
    my $hash = $main::defs{$name};
   
    my $gatttool = qx(which gatttool);
    chomp $gatttool;
   
    if(-x $gatttool) {
        my $gtResult;
        my $cmd;
        my $wait = 1;
        my $sshHost     = AttrVal($name,"sshHost","none");

        while($wait) {
       
            my $grepGatttool;
            $grepGatttool = qx(ps ax| grep -E \'gatttool -b $mac\' | grep -v grep) if($sshHost eq 'none');
            $grepGatttool = qx(ssh $sshHost 'ps ax| grep -E "gatttool -b $mac" | grep -v grep') if($sshHost ne 'none');

            if(not $grepGatttool =~ /^\s*$/) {
                Log3 $name, 3, "($name) - ExecGatttool_Run: another gatttool process is running. waiting...";
                sleep(1);
            } else {
                $wait = 0;
            }
        }
     ............
...................


Das hci ist erstmal unwichtig. Hauptsache er erkennt das ein gatttool Proßess läuft
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

Master_Nick

#248
Sieht sehr sexy aus!
Und läuft bisher sauber durch


Ein gatttool pro Thermostat - das ist aber auch dem geschuldet, dass ich den andern Umbau noch machen muss ^^

Ich schaue mal, ob ich das "childlock" und ggf noch einiges andere eingebaut bekomme.
Und würde es dann einmal hier anfügen
Rancher K8s Cluster mit nanoCUL (a-culfw) | IObroker | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem | WOL | NFC | Harmony UltimateHub | Anwesenheitserkennnung | Roomba | 10" Touch mit Node-Red | SonOff S20 | SonOff Touch | SonOff Dual | Rolladen | Und ganz viel anderes tolles Gerödel.... ;-)

Master_Nick

#249
 :) ;) ;D

Ich denke ich habe das mit dem Timeout hinbekommen und dein ps -ax läuft auch wunderbar bisher.
Mal schauen ob sich noch was auftut über Nacht.  8)

Ist es eigentlich gewollt, dass EQ3BT_killGatttool leer ist?
sub EQ3BT_killGatttool($) {

}


Um weiter bauen zu können muss ich mal etwas verstehen  :D
Ich schaue mir die genrell Vorgehensweise an und will z.b. einbauen, dass beim schalten von ecoMode dieser auch an geht bei mir (Reading 1) ebenso beim Comfort.

Was ist im folgenden das "(hex($value) - 0x4500);"?

sub EQ3BT_setBoostSuccessful {
    my ($hash, $handle, $value) = @_;
    my $val = (hex($value) - 0x4500);
    readingsSingleUpdate($hash, "boost", $val, 1);
    return undef;
}




Der Einfachkeit halber hier die gesamte geänderte sub EQ3BT_execGatttool:

sub EQ3BT_execGatttool($) {
    my ($string) = @_;
    my ($name, $mac, $workType, $handle, $value, $listen) = split("\\|", $string);
    my $hash = $main::defs{$name};
   
    my $gatttool = qx(which gatttool);
    chomp $gatttool;
   
    if(-x $gatttool) {
        my $gtResult;
        my $cmd;
my $sshcmd;
my $sshcmd2;
        my $wait = 1;
        my $sshHost     = AttrVal($name,"sshHost","none");

        while($wait) {
       
            my $grepGatttool;
            $grepGatttool = qx(ps ax| grep -E \'gatttool -b $mac\' | grep -v grep) if($sshHost eq 'none');
            $grepGatttool = qx(ssh $sshHost 'ps ax| grep -E "gatttool -b $mac" | grep -v grep') if($sshHost ne 'none');

            if(not $grepGatttool =~ /^\s*$/) {
                Log3 $name, 3, "($name) - ExecGatttool_Run: another gatttool process is running. waiting...";
                sleep(1);
            } else {
                $wait = 0;
            }
        }

        if($value eq "03") {
            my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
            my $currentDate = sprintf("%02X%02X%02X%02X%02X", $year+1900-2000, $mon+1, $mday, $hour, $min);
            $value .= $currentDate;
        }

        my $hciDevice = "hci".$hash->{helper}{hcidevices}[$hash->{helper}{currenthcidevice}];
        $sshcmd = "ssh $sshHost";
        #my $cmd = "gatttool -b $mac -i $hciDevice --char-write-req --handle=$handle --value=$value";
        if( $sshHost ne 'none' ) {
            $cmd = "".$sshcmd." 'gatttool -b $mac -i $hciDevice --char-write-req --handle=$handle --value=$value";
            $sshcmd2 = "'gatttool -b $mac -i $hciDevice --char-write-req --handle=$handle --value=$value";
        } else {
            $cmd = "gatttool -b $mac -i $hciDevice --char-write-req --handle=$handle --value=$value";
        }
       
        if(defined($listen) && $listen eq "listen" && $sshHost ne 'none') {
            $cmd = "".$sshcmd." timeout ".AttrVal($name, "timeout", 15)." ".$sshcmd2." --listen";
        } else {
    $cmd = "timeout ".AttrVal($name, "timeout", 15)." ".$cmd." --listen";
}

        #redirect stderr to stdout
        if( $sshHost ne 'none' ) {
            $cmd .= " 2>&1'";
        } else {
            $cmd .= " 2>&1";
        }

        Log3 $name, 5, "EQ3BT ($name): $cmd";
        $gtResult = qx($cmd);
        chomp $gtResult;
        my @gtResultArr = split("\n", $gtResult);
        Log3 $name, 4, "EQ3BT ($name): gatttool result: ".join(",", @gtResultArr);
        if(defined($gtResultArr[0]) && $gtResultArr[0] eq "Characteristic value was written successfully") {
            #read notification
            if(defined($gtResultArr[1]) && $gtResultArr[1] =~ /Notification handle = 0x0421 value: (.*)/) {
                return "$name|$mac|ok|$workType|$handle|$value|$1";
            } else {
                if(defined($listen) && $listen eq "listen") {
                    return "$name|$mac|error|$workType|$handle|$value|notification missing";
                } else {
                    return "$name|$mac|ok|$workType|$handle|$value";
                }
            }
        } else {
            return "$name|$mac|error|$workType|$handle|$value|$workType failed";
        }
    } else {
        return "$name|$mac|error|$workType|$handle|$value|no gatttool binary found. Please check if bluez-package is properly installed";
    }
}


Rancher K8s Cluster mit nanoCUL (a-culfw) | IObroker | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem | WOL | NFC | Harmony UltimateHub | Anwesenheitserkennnung | Roomba | 10" Touch mit Node-Red | SonOff S20 | SonOff Touch | SonOff Dual | Rolladen | Und ganz viel anderes tolles Gerödel.... ;-)

CoolTux

Guten Morgen,

Bitte nicht falsch verstehen, Dein Code ist sicherlich funktional. Ich versuche nur auch immer etwas Übersicht rein zu bringen. Auf Basis Deines Codes habe ich in 2 Minuten eine bessere Übersicht gezaubert.
Leider ungetestet. Wenn es ok für Dich ist, würdest Du ihn bitte testen? Ich selbst kann gerade nicht, da ich ein anderes BT Thermostat aktuell dran habe zum entwickeln.
Vielen Dank für Deine super Vorarbeit.




sub EQ3BT_execGatttool($) {
    my ($string) = @_;
    my ($name, $mac, $workType, $handle, $value, $listen) = split("\\|", $string);
   
    my $hash            = $main::defs{$name};
   
    my $gatttool        = qx(which gatttool);
    chomp $gatttool;
   
    if(-x $gatttool) {
        my $gtResult;
        my $cmd;
        my $wait        = 1;
        my $sshHost     = AttrVal($name,"sshHost","none");
        my $hciDevice   = "hci".$hash->{helper}{hcidevices}[$hash->{helper}{currenthcidevice}];
       
       
        while($wait) {
       
            my $grepGatttool;
            $grepGatttool   = qx(ps ax| grep -E \'gatttool -i $hciDevice -b $mac\' | grep -v grep) if($sshHost eq 'none');
            $grepGatttool   = qx(ssh $sshHost 'ps ax| grep -E "gatttool -i $hciDevice -b $mac" | grep -v grep') if($sshHost ne 'none');

            if(not $grepGatttool =~ /^\s*$/) {
                Log3 $name, 3, "XiaomiBTLESens ($name) - ExecGatttool_Run: another gatttool process is running. waiting...";
                sleep(1);
            } else {
                $wait = 0;
            }
        }

        if($value eq "03") {
            my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
            my $currentDate = sprintf("%02X%02X%02X%02X%02X", $year+1900-2000, $mon+1, $mday, $hour, $min);
            $value .= $currentDate;
        }
       
        $cmd    = "ssh $sshHost '" if($sshHost ne 'none');
        $cmd    .= "timeout 15 " if(defined($listen) && $listen eq "listen");
        $cmd    .= "gatttool -i $hci -b $mac ";
        $cmd    .= "--char-write-req -a $handle -n $value";
        $cmd    .= " --listen" if($listen);
        $cmd    .= " 2>&1 /dev/null";
        $cmd    .= "'" if($sshHost ne 'none');

        Log3 $name, 5, "EQ3BT ($name): $cmd";
        $gtResult = qx($cmd);
        chomp $gtResult;
        my @gtResultArr = split("\n", $gtResult);
        Log3 $name, 4, "EQ3BT ($name): gatttool result: ".join(",", @gtResultArr);
        if(defined($gtResultArr[0]) && $gtResultArr[0] eq "Characteristic value was written successfully") {
            #read notification
            if(defined($gtResultArr[1]) && $gtResultArr[1] =~ /Notification handle = 0x0421 value: (.*)/) {
                return "$name|$mac|ok|$workType|$handle|$value|$1";
            } else {
                if(defined($listen) && $listen eq "listen") {
                    return "$name|$mac|error|$workType|$handle|$value|notification missing";
                } else {
                    return "$name|$mac|ok|$workType|$handle|$value";
                }
            }
        } else {
            return "$name|$mac|error|$workType|$handle|$value|$workType failed";
        }
    } else {
        return "$name|$mac|error|$workType|$handle|$value|no gatttool binary found. Please check if bluez-package is properly installed";
    }
}


Einen kleinen Schöhnheitsfehler gibt es allerdings noch. Der Test ob gatttool installiert und ausführbar ist funktioniert nicht auf dem SSH Host. Man kann es zwar so machen das er auch auf dem SSH Host den which macht, aber der eigentliche Test ob ausführbar -x $gatttool geht dann leider nicht mehr.




Was die leeren Funktionen an geht, von denen es so einige gibt müssten wir mal den Markus fragen was genau er da machen wollte. Wenn wir das ganze jetzt so ändern sollte es kein hängendes gatttool geben, da der BlockingKill Prozess (aus dem Modul Blocking.pm) das für uns machen sollte.



Die ganzen Successful Routinen scheinen nicht implementiert zu sein.

my $val = (hex($value) - 0x4500);


Das korrekte val ergibt sich aus dem hex von $value minus 0x4500.
Was und wieso kann ich nicht sagen.




Grüße
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

Master_Nick

#251
 ;) :D Alles gut!  8)
Ich bin Softwaretester kein Entwickler. Daher ist mein Code eher das, was er machen soll, statt wartbar oder sinnvoll strukturiert :-D
Finde ich es super, wenn du was verbesserst. War auch mein erstes mal in einem FHEM Modul *g*.
Ich werde es morgen testen.

Ich habe aktuell noch festgestellt, dass wohl für ein Thermostat das alles super klappt und ich habe gatttoool bisher immer nur mit timeout 15 für dieses Thermostat gesehen. Für das andere Thermostat sehe ich es häufig ohne timeout 15. Ich glaube da sind aber auch unterschiedliche Routinen/Sub dran. Die dann eigentlich auf EQ3BT_killGatttool aufbauen (was nix macht).

Ich glaube hier hattest du noch etwas in der Zwischenablage oder? :-D
Log3 $name, 3, "XiaomiBTLESens ($name)

ZitatEinen kleinen Schöhnheitsfehler gibt es allerdings noch. Der Test ob gatttool installiert und ausführbar ist funktioniert nicht auf dem SSH Host. Man kann es zwar so machen das er auch auf dem SSH Host den which macht, aber der eigentliche Test ob ausführbar -x $gatttool geht dann leider nicht mehr.
Ich denke Preconditions kann man voraussetzen - sie müssen nur klar mitgeteilt werden. Dann ist so ein Test nicht nötig.


ZitatDas korrekte val ergibt sich aus dem hex von $value minus 0x4500.
Was und wieso kann ich nicht sagen.
0x4500 ist ja auch wieder HEX^^ ?
Rancher K8s Cluster mit nanoCUL (a-culfw) | IObroker | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem | WOL | NFC | Harmony UltimateHub | Anwesenheitserkennnung | Roomba | 10" Touch mit Node-Red | SonOff S20 | SonOff Touch | SonOff Dual | Rolladen | Und ganz viel anderes tolles Gerödel.... ;-)

dominik

Hallo zusammen,
danke CoolTux, dass du hier mitentwickelst!

Den Childlock / Kindersicherung kann ich kurzfristig am Wochenende einbauen, das sollte kein Problem sein - ist auch bei mir gerade sehr nützlich :D

Gruß
Dominik
fhempy -  https://github.com/fhempy/fhempy: GoogleCast, Tuya, UPnP, Ring, EQ3BT, Nespresso, Xiaomi, Spotify, Object Detection, ...
Kaffeespende: https://paypal.me/todominik

CoolTux

Hallo Dominik,

Naja so viel mache ich gar nicht, Deine User machen eigentlich das meiste. Bin aktuell etwas eingespannt  :D
Denke aber mal wir sollten mal schauen das wir die ssh Implementierung sauber hin bekommen. Ich hoffe das mein bisschen Code dazu bei trägt.



Grüße
Leon
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

Master_Nick

#254
SO ich teste gerade: Läuft 8)  :) :) :)
Musste mal mein Wohnzimmerthermostat einmal auf Bluetooth aus/an schalten das gab irgendwie nix mehr von sich.... wahrscheinlich war es ein wenig viel hin her verbinden disconnecten :-D

Habe mal aus $hci $hciDevice gemacht  ;D Das gibt es immer noch nicht  8)  ;)
Und aus XiaomiBTLESens --> EQ3BT

$cmd    .= "gatttool -i $hci -b $mac "; --> $cmd    .= "gatttool -i $hciDevice -b $mac ";



Mal ne ganz doofe Frage  ::)
Gibt es irgendwie eine Sammlung an Herangehensweisen für Heitzungssteuerung abhängig von Thermometern also 2 verschiedene Devices.
Stelle mir das so vor, dass das Thermometern sagt es ist 18 °C. Das EQ3 steht meinetwegen schon auf 20, Raum bleibt aber weiter kühl und es ist kein Fenster auf (optionales einbringen noch eines weiteren Devices) dann soll er die Heizung höher schalten in mittels einer Art Watch Dog erneut prüfen und ggf nachregeln oder wieder auf die "normale" soll Temperatur am Thermostat gehen.

Oder würdet ihr sagen eigentlich braucht man das bei denen gar nicht ^^ (wäre ja langweilig).
Rancher K8s Cluster mit nanoCUL (a-culfw) | IObroker | IT(V1&V3), IT-PIR, THGR122NX |Co² | alexa-fhem | WOL | NFC | Harmony UltimateHub | Anwesenheitserkennnung | Roomba | 10" Touch mit Node-Red | SonOff S20 | SonOff Touch | SonOff Dual | Rolladen | Und ganz viel anderes tolles Gerödel.... ;-)