Bash Script zur Übertragung von beliebigen Werten über MQTT

Begonnen von Otto123, 23 Januar 2023, 14:02:03

Vorheriges Thema - Nächstes Thema

Otto123

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
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

CoolTux

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.
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

yersinia

Coole Idee. Ich nutze seit Langem ein periodisch laufendes Script 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.
viele Grüße, yersinia
----
FHEM 6.3 (SVN) on RPi 4B with RasPi OS Bullseye (perl 5.32.1) | FTUI
nanoCUL->2x868(1x ser2net)@tsculfw, 1x433@Sduino | MQTT2 | Tasmota | ESPEasy
VCCU->14xSEC-SCo, 7xCC-RT-DN, 5xLC-Bl1PBU-FM, 3xTC-IT-WM-W-EU, 1xPB-2-WM55, 1xLC-Sw1PBU-FM, 1xES-PMSw1-Pl