UDP Empfänger mit auslösen eines Befehls

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
wahnsinn
Beiträge: 43
Registriert: 23.10.2016 19:35:30

UDP Empfänger mit auslösen eines Befehls

Beitrag von wahnsinn » 23.04.2018 03:14:47

Hallo,

meine Webcam mit Bewegungserkennung detektiert einfach zu viel Quatsch und so dachte ich mir ein externer Auslöser wäre da zuverlässiger.

Als client habe ich einen ESP8266 über Arduino der einfach nur bei eintreten eines Ereignisses z.B. Tastendruck ein Zeichen via UDP an meinen Pi Computer sendet.

Der Pi Computer soll dann die Webcam ansprechen und ein Foto auf die SD Speicherkarte schreiben.

So sieht mein Script auf der Linux Seite aus. (Die Webcam kann keine Fotos direkt machen und muss den Videostream anzapfen. Mit Imagemagic wird oben links noch ein zeitstempel generiert.

Code: Alles auswählen

#!/bin/sh
today=`/bin/date '+%Y-%m-%d__%H-%M'`;    #Datum für Dateiname
todayx=`/bin/date '+%d-%m-%Y  %H:%M'`;   #Datum für BildimBild
counter=1
#Ping zur Webcam ob sie erreichbar ist
if ping -c 1 -w 1 192.168.1.6 > /dev/null ; then

   #Ein Bild generieren als pseudo Film
   ffmpeg -rtsp_transport tcp -i rtsp://192.168.1.6/11 -ss 00:00:01.000 -f image2 -vframes 1 -pix_fmt yuvj420p /run/12c$today.jpg

   #Bild in Bild mit Datum generieren
   convert -size 320x36 -gravity east -background black -fill white -pointsize 20 label:"$todayx"  /run/soverlay.gif

   # Sensorbild mit Webcam Bild vereinen
   composite -gravity northwest /run/soverlay.gif /run/12c$today.jpg /daten/auslos/$today.jpg
   rm /run/soverlay.gif
   rm /run/12c$today.jpg

ncat -v -ul -p 7777 -c /home/pi/auslos.sh

else
echo "kein Ping zur Webcam" > /daten/auslos/$today.txt

ncat -v -ul -p 7777 -c /home/pi/auslos.sh

exit
fi

und so sieht der Code beim ESP8266 programmiert mit Arduino IDE aus

Code: Alles auswählen

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
const char* ssid = "routerssid";
const char* password = "wlanpasswort";
IPAddress ip(192, 168, 1, 21);
WiFiUDP Udp;

void setup()
{
  Serial.begin(115200);
  Serial.printf("Connecting to %s ", ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println(" connected");

Udp.beginPacket(ip, 7777);
Udp.write(1);
Udp.endPacket();
Serial.println("gesendet");
}

void loop()
{  }

Der Arduinno Code ist erstmal total vereinfacht und sendet beim Start nur einmal und dann ist ende. Wenn man den reset Knopf drückt wird alles nochmal abgearbeitet.

Auf der Pi Linux Seite (verwende armbian) funktioniert das Script genau ein mal. Danach werden die UDP vom ESP8266 ignoriert.

starte ich auf einem Windows PC das Programm Packet Sender und sende ein UDP Paket an 192.168.1.21 port 7777 springt das script an aber dann kein zweites mal.

Über ein zweites Terminal Fenster am Pi-PC kann ich beliebig oft das Script mit dem Befehl

nc -u localhost 7777

auslösen, muss aber das Programm jedesmal mit Strg + c beenden.


------------------

Ich habe gelesen das evt. ein EOF erwartet wird aber da passiert nichts wenn ich EOF oder <C><S> noch sende. Auch die Parameter mit Timeout setzen bringen mich nicht weiter.



Wer weiß wo der Fehler liegt oder gibt es eine bessere Lösung für das Problem? Mit dem ESP8266 ist es einfach UDP Pakete zu senden, Ping gehen auch noch aber so TCP Kram wird umständlich.

pferdefreund
Beiträge: 3791
Registriert: 26.02.2009 14:35:56

Re: UDP Empfänger mit auslösen eines Befehls

Beitrag von pferdefreund » 23.04.2018 07:22:26

Für ein einfaches Protokoll mal netcat anschauen - kann als Server und Client arbeiten, kennt tpc, udp usw.

wahnsinn
Beiträge: 43
Registriert: 23.10.2016 19:35:30

Re: UDP Empfänger mit auslösen eines Befehls

Beitrag von wahnsinn » 23.04.2018 15:40:41

pferdefreund hat geschrieben: ↑ zum Beitrag ↑
23.04.2018 07:22:26
Für ein einfaches Protokoll mal netcat anschauen - kann als Server und Client arbeiten, kennt tpc, udp usw.
:lol: Schau mal oben in den Bash-Code. Es funktioniert mit einem Endgerät genau einmal und dann nur noch mit anderen Endgeräten ebenfalls nur einmal.

wahnsinn
Beiträge: 43
Registriert: 23.10.2016 19:35:30

Re: UDP Empfänger mit auslösen eines Befehls

Beitrag von wahnsinn » 24.04.2018 02:25:24

Hab mit Google selbst eine etwas schräge Lösung gefunden wo der ncat Prozess einfach gekillt wird. Nun funktioniert es wie gewünscht. Die Bash Datei immer wieder neu sich selbst aufrufen führte zu einem anwachsen des Prozess-Baum. Mit der do while schleife ist das auch erledigt. Und damit andere Befehle wo ncat im spiel ist nicht dauergekillt werden machte ich eine kopie von ncat mit dem namen zzzcat

Script mit name netbu.sh

Code: Alles auswählen


#!/bin/bash
trap 'exit 0' TERM
while true
do
kill $(ps aux | grep 'zzzcat' | awk '{print $2}') 2>/dev/null
zzzcat -l -v -ul -p 7777 -c /home/pi/auslos.sh &> /dev/null
echo "strg+C zum abbruch"
sleep 1
done
exit


Den Einzeiler für den Kill habe ich dort gefunden https://stackoverflow.com/questions/351 ... -and-regex


Dieses Linuxzeug treibt mich oft in den Wahnsinn... aber wenn es am ende funktioniert freut man sich wahnsinnig :lol:

wahnsinn
Beiträge: 43
Registriert: 23.10.2016 19:35:30

Re: UDP Empfänger mit auslösen eines Befehls

Beitrag von wahnsinn » 24.04.2018 18:58:12

Meinen Code-Flickschuster-Schrott kann man vergessen

Da gibt es einen super funktionierenden sauberen Code http://blog.heimetli.ch/udp-execute.html

TomL

Re: UDP Empfänger mit auslösen eines Befehls

Beitrag von TomL » 24.04.2018 20:00:38

wahnsinn hat geschrieben: ↑ zum Beitrag ↑
23.04.2018 15:40:41
Schau mal oben in den Bash-Code. Es funktioniert mit einem Endgerät genau einmal und dann nur noch mit anderen Endgeräten ebenfalls nur einmal.
Ich hatte so was ähnliches vor längerer Zeit mal für eine bestimmte Aufgabe entworfen, allerdings für TCP.... was aber wohl keinen großen Änderungsaufwand bedeutet. Teste es einfach mal... vielleicht hilft es Dir als Anregung weiter. Dazu zwei Terminalfenster öffnen (am besten beide sichtbar übereinander anordnen), und zuerst im ersten Terminal das Journal starten:

Code: Alles auswählen

journalctl -f
Die folgenden im zweiten Terminal eingebenen Befehle

Code: Alles auswählen

# ./tcp_eventhandler start

# echo "testA" >/dev/tcp/0.0.0.0/55555
# echo "testB" >/dev/tcp/0.0.0.0/55555
# echo "testC" >/dev/tcp/0.0.0.0/55555

# ./tcp_eventhandler stop
führten dann im ersten Terminal zu folgenden Ausgaben:

Code: Alles auswählen

Apr 24 20:04:09 thomaspc tcp_eventhandler[4372]: service started!
Apr 24 20:04:09 thomaspc tcp_eventhandler[4376]: active/running:   current state event-handler = idle
Apr 24 20:04:13 thomaspc tcp_eventhandler[4385]: do any job with testA
Apr 24 20:04:13 thomaspc tcp_eventhandler[4383]: active/running:   current state event-handler = idle
Apr 24 20:04:17 thomaspc tcp_eventhandler[4395]: do any job with testB
Apr 24 20:04:17 thomaspc tcp_eventhandler[4393]: active/running:   current state event-handler = idle
Apr 24 20:04:22 thomaspc tcp_eventhandler[4404]: do any job with testC
Apr 24 20:04:22 thomaspc tcp_eventhandler[4402]: active/running:   current state event-handler = idle
Apr 24 20:04:26 thomaspc tcp_eventhandler[4410]: service stopped!
Apr 24 20:04:26 thomaspc tcp_eventhandler[4415]: current state event-handler = terminated!
Mein altes Script, jetzt aufs wesentliche reduziert:

Code: Alles auswählen

#! /bin/bash

#============================================================================================

DoAnyJob()
{
    echo "do any job with $1" | systemd-cat -t "$(basename $0)" -p "info"
}
#============================================================================================

SetupHandlerTCPEvent()
{
    tStart=$(date +%s)
    CallCounter=0

    while true; do
        echo "active/running:   current state event-handler = idle" | systemd-cat -t "$(basename $0)" -p "info"

        rc=$(/bin/nc -l -p 55555)
        (( CallCounter++ ))

        tEnd=$(date +%s)
        tDiff=$((tEnd-tStart))

        if [[ tDiff -gt 5 ]]; then
            tStart=$(date +%s)
            CallCounter=0

        elif [[ CallCounter -gt 5 ]]; then
            echo "Flooding? Sleep 60 Seconds" | systemd-cat -t "$(basename $0)" -p "warning"
            /bin/sleep 60
            continue
        fi

        if [ "$rc" == "#eh_d_quit#" ]; then
            break
        else
            DoAnyJob "$rc" &
        fi
    done

    echo "current state event-handler = terminated!" | systemd-cat -t "$(basename $0)" -p "info"
    exit 0
}
#============================================================================================
# Setup daemon

action=$1

if [[ $EUID -ne 0 ]]; then
    echo "User-ID $EUID is not authorized to start the daemon" | systemd-cat -t "$(basename $0)" -p "warning"
    exit 1
fi

case $action in
    start)
        SetupHandlerTCPEvent &
        echo "service started!" | systemd-cat -t "$(basename $0)" -p "info"
        ;;
    stop)
        echo "#eh_d_quit#" > /dev/tcp/0.0.0.0/55555
        echo "service stopped!" | systemd-cat -t "$(basename $0)" -p "info"
        ;;

    *)
        echo -e "\nAufruf: $(basename $0) start | stop\n"
        echo "Beendet! Falsche oder fehlende Parameter"
        echo "Job canceled! Wrong or missing parameters" | systemd-cat -t "$(basename $0)" -p "warning"
        ;;
esac

sleep 1

exit 0
#============================================================================================
# End

wahnsinn
Beiträge: 43
Registriert: 23.10.2016 19:35:30

Re: UDP Empfänger mit auslösen eines Befehls

Beitrag von wahnsinn » 25.04.2018 22:52:29

Vielen Dank :D

mat6937
Beiträge: 2927
Registriert: 09.12.2014 10:44:00

Re: UDP Empfänger mit auslösen eines Befehls

Beitrag von mat6937 » 26.04.2018 09:55:06

wahnsinn hat geschrieben: ↑ zum Beitrag ↑
25.04.2018 22:52:29
...
Siehe auch diesen Thread: https://forum-raspberrypi.de/forum/thre ... usfuehren/

Antworten