Daten zu FHEM pusche

Begonnen von CoolTux, 30 Januar 2020, 12:20:01

Vorheriges Thema - Nächstes Thema

CoolTux

Zitat von: Wernieman am 30 Januar 2020, 08:21:20
Wen ich wirklich die Werte meines Haussystemes in FHEM brauche, mache ich auch kein Pull sondern mittlerweile ein Push, d.h. der Server sendet die Daten von sich aus. Hat noch den Vorteil, das dieses "Push" Script mit einer angepassten Userberechtigung läuft und wirklich keine Befehle entgegen nimmt ...

Zitat von: mumpitzstuff am 30 Januar 2020, 08:48:05
Gibt es dafür vielleicht irgend etwas fertiges irgendwo? Ich möchte eigentlich nur ein paar wenige Dinge überwachen und sowas wie Grafana oder Prometheus wäre für mich mit Kanonen auf Spatzen schiessen.


Zitat von: CoolTux am 30 Januar 2020, 11:16:52

###############################################################################
#
# Developed with Kate
#
#  (c) 2019 Copyright: Marko Oldenburg (marko.oldenburg at araneaconsult dot de)
#  All rights reserved
#
#
#  This script is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  any later version.
#
#  The GNU General Public License can be found at
#  http://www.gnu.org/copyleft/gpl.html.
#  A copy is found in the textfile GPL.txt and important notices to the license
#  from the author is found in LICENSE.txt distributed with these scripts.
#
#  This script is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#
###############################################################################

use strict;
use warnings;
use POSIX;

use IO::Socket::INET;

##################################################
# Forward declarations
#
sub deconzDaemonSystemctl($$);
sub deconzDaemonState($);
sub sendStateToFHEM();
sub deconzDaemonCpuLast();

##################################################
# Variables:
my $self = {};
$self->{daemons} = ['deconz','deconz-wifi'];


###################################################
# Start the program
my ($arg,$debug,$acount);

return 'Usage status|restart' unless ( scalar(@ARGV) > 0 );
$arg = shift @ARGV;
$debug = 0;

if ( $arg eq 'restart' ) {
    deconzDaemonSystemctl('restart',$self->{daemons}->[0]);
    deconzDaemonSystemctl('stop',$self->{daemons}->[1]);
}

$acount = 0;
foreach ( @{ $self->{daemons} } ) {
    deconzDaemonState($self->{daemons}->[$acount]);
    $acount++;
}

deconzDaemonCpuLast() if ( $arg eq 'restart' or $arg eq 'status' );
       
sendStateToFHEM();


sub deconzDaemonSystemctl($$) {
    my ( $ctlCmd, $daemon ) = @_;
    system('systemctl ' . $ctlCmd . ' ' . $daemon);
    return 0;
}

sub deconzDaemonState($) {
    my $daemon = shift;
    $self->{daemons}->[$acount] = { daemon => $daemon };
   
    if ( open( STATE, "systemctl status $daemon 2>&1 |" ) ) {
        while ( my $line = <STATE> ) {
            chomp($line);
            print qq($line\n) if ( $debug == 1 );

            if ( $line =~ m#^\s+Loaded:\s(\S+)# ) {
                $self->{daemons}->[$acount]->{loaded} = $1;

            }
            elsif ( $line =~ m#^^\s+Active:\s(\S+\s\S+)\s\S+\s(\S+\s\S+\s\S+\s\S+);\s(\S+)# ) {
                $self->{daemons}->[$acount]->{active} = $1;
                $self->{daemons}->[$acount]->{timestamp} = $2;
                $self->{daemons}->[$acount]->{timeago} = $3;
            }
        }

        close(STATE);
    }
    else {
        die "Couldn't use STATE: $!\n";
        $self->{daemons}->[$acount]->{error} = 'Couldn\'t use STATE: ' . $;;
        return 1;
    }

    return 0;
}

sub deconzDaemonCpuLast() {

    if ( open( STATE, 'ps uax 2>&1 |' ) ) {
        while ( my $line = <STATE> ) {
            chomp($line);
            print qq($line\n) if ( $debug == 1 );

            if ( $line =~ m#^marko\s+\d+\s+(\d+.\d*).+\/usr\/bin\/deCONZ# ) {
                $self->{daemons}->[0]->{cpuLast} = $1;
            }
        }

        close(STATE);
    }
    else {
        die "Couldn't use STATE: $!\n";
        $self->{daemons}->[0]->{error} = 'Couldn\'t use STATE: ' . $;;
        return 1;
    }
   
    return 0;

}

sub sendStateToFHEM() {
    my $fhemDummy = 'dummyDeconzDaemonState';
   
    my $HOSTNAME = "p-fhem02.tuxnet.lan";
    my $HOSTPORT = "7072";
    my $socket = IO::Socket::INET->new('PeerAddr' => $HOSTNAME,'PeerPort' => $HOSTPORT,'Proto' => 'tcp')
        or die 'Cant\'t connect to FHEM Instance';

    $acount = 0;
    foreach ( @{ $self->{daemons} } ) {
        while ( my ( $r, $v ) = each %{$self->{daemons}->[$acount]} ) {
            print $socket 'setreading ' . $fhemDummy . ' ' . $self->{daemons}->[$acount]->{daemon} . '_' . $r . ' ' . $v ."\n" if ( $v ne $self->{daemons}->[$acount]->{daemon} );
            print $socket 'setreading ' . $fhemDummy . ' state ' . $v ."\n" if ( $r eq 'active' and $self->{daemons}->[$acount]->{daemon} eq 'deconz' );
        }
        $acount++;
    }
   
    $socket->close;
}


Hier mal ein kleines Beispielscript wie man Systemüberwachung an FHEM per Push senden kann.
Sieht in FHEM dann so aus.

Internals:
   FUUID      5c645655-f33f-b39c-204e-0043ce79d972bc47
   NAME       dummyDeconzDaemonState
   NR         64
   STATE      active (running)
   TYPE       dummy
   READINGS:
     2019-11-12 20:06:02   deconz-wifi_active active (running)
     2019-11-12 20:06:02   deconz-wifi_loaded loaded
     2019-11-12 20:06:02   deconz-wifi_timeago 4h
     2019-11-12 20:06:02   deconz-wifi_timestamp Tue 2019-11-12 15:21:30 CET
     2019-11-12 20:06:02   deconz_active   active (running)
     2019-11-12 20:06:02   deconz_cpuLast  4.1
     2019-11-12 20:06:02   deconz_loaded   loaded
     2019-11-12 20:06:02   deconz_timeago  6min
     2019-11-12 20:06:02   deconz_timestamp Tue 2019-11-12 19:59:04 CET
     2019-11-12 20:06:02   state           active (running)
Attributes:
   alias      deCONZ Service Status
   event-on-change-reading state,deconz-wifi_active,deconz_cpuLast,.*_timestamp
   group      deCONZ
   room       EDV
   setList    restart:noArg

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

mumpitzstuff

Oh cool. Sehr schön. Danke!

Wernieman

#2
Habe bei mir ein bash-Script laufen.
Bitte alles mit <...> anpassen. Habe allerdings für diesen Zugang ein eigenes SSL-Telnet-Device mit Passwort angelegt.

Doing:
Zuerst wird alles in der Variablen "fhem" gesammelt, um dann im 2. Stepp alles zu FHEM zu puschen. TimeOut 4 Sekunden, um nicht zu sehr zu blockieren.

Hier im beispiel werden PI Daten gesammelt (CPU Temperatur und SD-Nutzung)

#!/bin/bash

logfile="/var/log/mrtg/daten.log"

# Serverangabe
server="<TollerFhemServer>"
server_port="<TollerFhemPort>"

#Zuerst muss Passwort
fhem="<TollesPasswort>"

#CPU Temperatur
fhem="${fhem}\nsetreading PI Temp $(echo "scale=1; $(cat /sys/class/thermal/thermal_zone0/temp) / 1000" | bc -l)"

# Speicherverbrauch (Bis jetzt sda) auslesen
while read line
do
  Device=$(echo ${line} | awk '{print $1}' | sed -e "s/^.*\///g" -e "s/ //g")
  Proz=$(echo ${line} | awk '{print $5}' | sed -e "s/%//g" -e "s/ //g")
  Benutzt=$(echo ${line} | awk '{print $3}')

  fhem="${fhem}\nsetreading PI ${Device}_Prozent ${Proz}"
  fhem="${fhem}\nsetreading PI ${Device}_Benutzt ${Benutzt}"
done < <(df -m | grep -v -e tmpfs -e Filesystem -e ":" | tail -n +2)

# Daten an FHEM übergeben
if ping $server -c1 >/dev/null 2>&1
then
  echo -en "${fhem}\nquit\n" | /usr/bin/ncat -w5 -4 --ssl $server $server_port >/dev/null
  if [ ! "$?" = "0" ]
  then
    echo "$(date "+%Y-%m-%d/%H:%M:%S") - Fehler beim Datenuebertragen an FHEM-Server $server" >>/var/log/mrtg/daten.log
  fi
else
  echo "$(date "+%Y-%m-%d/%H:%M:%S") - Kein FHEM-Server $server pingbar" >>/var/log/mrtg/daten.log
fi
- Bitte um Input für Output
- When there is a Shell, there is a Way
- Wann war Dein letztes Backup?

Wie man Fragen stellt: https://tty1.net/smart-questions_de.html

Wernieman

#3
irgendwo hatte Otto mal ein Script, um Daten über die Webschnittstelle zu puschen ...

Edit:
Wer suchet der findet
http://heinz-otto.blogspot.com/2019/02/fhem-http-client.html
- Bitte um Input für Output
- When there is a Shell, there is a Way
- Wann war Dein letztes Backup?

Wie man Fragen stellt: https://tty1.net/smart-questions_de.html

Otto123

was auch gut geht ist mqtt :)

In der Art als Einzeiler:
while [ true ] ; do mosquitto_pub -h raspib2 -i COMPUTER -t CPU/$(hostname)/temperature -m $(($(</sys/class/thermal/thermal_zone0/temp)/1000)) ; sleep 30 ; done

Gruß Otto
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

Wernieman

Kann man in MQTT auch mehrere Daten "im Rutsch" Transferieren, oder muß man jedes mal eine Neue Verbindung öffnen?

Btw: 30 Sec. ist für Temperatur des Rechners doch relativ schnell .. würde auf 1m oder länger gehen ...
- Bitte um Input für Output
- When there is a Shell, there is a Way
- Wann war Dein letztes Backup?

Wie man Fragen stellt: https://tty1.net/smart-questions_de.html

herrmannj

Klar, der payload kann json sein. Die Werte werden dann in k/v Paare gesteckt. Das mqtt2_device kann beliebig flexibel die Werte entgegen nehmen

Otto123

Zitat von: Wernieman am 30 Januar 2020, 18:29:12
Btw: 30 Sec. ist für Temperatur des Rechners doch relativ schnell .. würde auf 1m oder länger gehen ...
War doch nur ein Test  8)
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

herrmannj

Lass mal die Klima im rz ausfallen. da können 30 Sekunden viel sein 🤪

Otto123

Jörg: es war nur ein Funktionstest -  ;D
Die eine Seite ist die Ermittlung des Problems, die andere Seite die Übertragung. Ich wollte nur sagen: Die Übertragung geht mit netcat und Telnet, es geht HTTP und es geht auch mqtt :) :) :)

Und klar per Json geht alles in einem Rutsch :)
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

Wernieman

Dann würde ich aber die Steuerung auf dem gleichen Rechner machen und weniger als 30 Sec ;o)
- Bitte um Input für Output
- When there is a Shell, there is a Way
- Wann war Dein letztes Backup?

Wie man Fragen stellt: https://tty1.net/smart-questions_de.html

Otto123

#11
So besser? Alle 2 sec aber nur bei Änderung senden  :D
Edit: Mit Schwellwert und wahlweise als json
# Schwellwert in c
# oder ohne Schwellwert einfach die Bedingung anders if (( $a != $b ))
c=8
# Strings für mqtt setzen
h="raspib2"         #mqtt Server
i="COMPUTER"        #CID
r="temperature"     #Readingname für json
t="raspi/$(hostname)/temperature"     #Topic
# Vergleichswert initialisieren
b=0
while [ true ] ; do
  a=$(($(</sys/class/thermal/thermal_zone0/temp)/100))
  if (( $a > $(($b+$c)) )) || (( $a < $(($b-$c)) ))
  then
    # temperature wert direkt
    m=$(($a/10))
    # oder als json String
    #m=$(echo {\"$r\":\"$m\"})
    mosquitto_pub -h $h -i $i -t $t -m $m
    b=$a
  fi
  sleep 2
done



Gruß
Otto
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

Wernieman

*griins* wir werden richtig Gut .. kannst Du die Schwellwerte nicht in FHEM verwalten?
*DuckUndWeg*
- Bitte um Input für Output
- When there is a Shell, there is a Way
- Wann war Dein letztes Backup?

Wie man Fragen stellt: https://tty1.net/smart-questions_de.html

herrmannj

Da reicht doch doch ein mqtt2 device