FHEM Forum

FHEM => Codeschnipsel => Thema gestartet von: Otto123 am 23 Januar 2023, 14:02:03

Titel: Bash Script zur Übertragung von beliebigen Werten über MQTT
Beitrag von: Otto123 am 23 Januar 2023, 14:02:03
Ich wollte eigentlich nur ein paar Systemwerte auf dem raspberry monitoren und diese per MQTT übertragen - also zu FHEM 'pushen'.

Gibt es einige Lösungen dafür, meistens mit der Schlange programmiert. Die Installation ist mMn immer eine Odyssee. ::)

Deshalb habe ich mal etwas rumprobiert unter dem Vorsatz: möglichst einfach ;)
Heraus gekommen ist ein kurzes Script - einfach und universell einsetzbar. Doku: https://github.com/heinz-otto/raspberry/blob/master/monitor/README.md

Edit: das Script selbst überträgt keine speziellen Daten, es überträgt nur das was in den *.var Dateien steht. Einfache Textdateien, ein Wert pro Zeile.

Wer es ausprobieren will: Man braucht mosquitto_pub (debian: mosquitto-clients), weiter nichts (zumindest auf einem raspbian lite).

Download Script
wget -qO runMqtt.sh https://raw.githubusercontent.com/heinz-otto/raspberry/master/monitor/runMqtt.sh
chmod +x runMqtt.sh


Erzeuge eine config - passend zum MQTT broker
cat >runMqtt.conf <<'EOF'
MQTT_SVR="servername|IP[ -p 1883]"
MQTT_TOPIC="monitor/system"
#MQTT_ACCOUNT="-u user -P password"
MQTT_CID=${HOSTNAME}
EOF


Erzeuge eine Datei mit einer Beispielnachricht
cat >day.var <<'EOF'
MESSAGE="$(date) Nachricht vom runMqtt script"
EOF


Jetzt hat man drei Dateien im gleichen Verzeichnis: runMqtt.sh runMqtt.conf day.var

Einmaliger Start, periodisch geht das mit systemd timer (setup script auf GitHub), crontab oder was auch immer.
./runMqtt.sh
In FHEM, mit MQTT2_SERVER und autocreate aktiv, sollte ein Device erzeugt werden :)

Viel Spaß damit
Otto
Titel: Antw:Bash Script zur Übertragung von beliebigen Werten über MQTT
Beitrag von: CoolTux am 23 Januar 2023, 16:33:09
Hallo Otto,

Ich hänge mich da mal an. Ich habe etwas ähnliches geschrieben, allerdings in Perl.


root@h-phoscongw:~# cat /usr/local/bin/deCONZrestart.pl
#!/usr/bin/perl

###############################################################################
#
# 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);

exit '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';

    print 'test' . "\n";
   
    my $HOSTNAME = "p-fhem.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]} ) {
            $socket->print('setreading ' . $fhemDummy . ' ' . $self->{daemons}->[$acount]->{daemon} . '_' . $r . ' ' . $v . "\n") if ( $v ne $self->{daemons}->[$acount]->{daemon} );
            $socket->print('setreading ' . $fhemDummy . ' state ' . $v ."\n") if ( $r eq 'active' and $self->{daemons}->[$acount]->{daemon} eq 'deconz' );
        }
        $acount++;
    }
   
    $socket->close;
}


Abgefragt werden die Zustände meines DeConz Dienstes. Die erhaltenen Werte und Zustände werden dann an einen Dummy in FHEM als Reading gesendet.
Titel: Antw:Bash Script zur Übertragung von beliebigen Werten über MQTT
Beitrag von: yersinia am 23 Januar 2023, 16:50:25
Coole Idee. Ich nutze seit Langem ein periodisch laufendes Script (https://forum.fhem.de/index.php/topic,129731.msg1240058.html#msg1240058) welches ein json-String via mosquitto_pub an FHEM-MQTT server sendet. Für Systemparameter reicht das mehr als genug - ua auch ob Service etc laufen.