Autor Thema: Bash Script zur Übertragung von beliebigen Werten über MQTT  (Gelesen 319 mal)

Online Otto123

  • Tester
  • Hero Member
  • ****
  • Beiträge: 21815
  • schon mal restore trainiert?
    • Otto's Technik Blog
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
« Letzte Änderung: 23 Januar 2023, 18:45:20 von Otto123 »
Viele Grüße aus Leipzig
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz
Gefällt mir Gefällt mir x 1 Liste anzeigen

Offline CoolTux

  • Developer
  • Hero Member
  • ****
  • Beiträge: 28303
Antw:Bash Script zur Übertragung von beliebigen Werten über MQTT
« Antwort #1 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.
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/
Mein Dokuwiki:
https://www.cooltux.net

Offline yersinia

  • Hero Member
  • *****
  • Beiträge: 1545
    • Cyanide & Happiness
Antw:Bash Script zur Übertragung von beliebigen Werten über MQTT
« Antwort #2 am: 23 Januar 2023, 16:50:25 »
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.2 (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