Hallo, ich habe ein Skript entwickelt, um von einem Image
(.gif, .jpg, .png, ...), z. B. geliefert von einer Webcam,
deren Gesamtdurchnittshelligkeitswert zu ermitteln
(in einer Skala von 0=dunkel bis 100=hell) und diesen
Wert weiterzuverarbeiten.
Beispiel: hell45 --> 70 # Resultat 70. Imagename ist fix
Mit diesen Helligkeitswerten kann auch z. B. ein Software-
Daemmerungssensor betrieben werden, der Wechsel von hell ./. dunkel
anzeigt.
Beispiel: hell-dunkel --> Es wird hell [datum uhrzeit]
(kann ggf. auch auf TV ausgeben, Sprachausgabe, ...).
Bei mir laeuft das Skript alle 2 Minuten auf Linux-Platform.
Ich hatte es nicht gedacht, aber der Software-Sensor liefert bei mir
mit einer Webcam fast minutenzeitgenau den Wechsel hell ./. dunkel
wie der Hardwaresensor FS20 SD.
Zusaetzlich wird an Software benoetigt:
convert (Programm aus Imagemagick-Framework) und Perl-Modul Image::BMP
Diese Skripts sind zwar keine fhem-Bestandteile, dienen aber der
Heimautomatisierung und koennen bei Bedarf leicht in fhem eingebunden
werden.
Ich hoffe, ich habe die richtige Forumskategorie erwischt,
denkbar waeren sonst auch "Codeschnipsel" oder "Off-Topic"
oder "Unterstuetzende Dienste".
Code fuer Skript hell45
#!/bin/sh
#: || exec /bin/sh $0 $argv:q
#(alias) >/dev/null 2>&1 && exec /bin/sh "$0" $1+{"$@"}
### @(#)
### @(#){hell45} - {ermittelt aktuellen Helligkeitswert 0..100 aus Bilddatei}
### @(#)
### @(#){Richard Bothe} Version {1.0} vom {11.11.2013}
### @(#)
### @(#){Anwendungsklasse}: Tools fuer FHEM [8]
### @(#)
### @(#){Synopsis} hell45
### @(#)
### @(#){Description}
### @(#)konvertiert Bilddatei (.gif, .jpg, .png, ...) zu .bmp-Datei und
### @(#)ermittelt aus den einzelnen bitmap-Informationen dieser Datei
### @(#)den gemittelten Helligkeitswert im Bereich 0 .. 100
### @(#)Dieser wird fortlaufend in ein logfile geschrieben
### @(#)
### @(#){Returncodes}: 0 bei keinem erkannten Fehler
### @(#)
### @(#){Description of I/O channels}: -
### @(#)
### @(#){Description of Parameters}: -
### @(#)
### @(#){Examples} hell45
### @(#)
### @(#){Called by} cron every 2 minutes or manually
### @(#)
### @(#){Calls} hellsumx.pl
### @(#)
### @(#){Files needed}
### @(#)imgsrc: Name der Bilddatei in ueblichem img format, gif, png, jpg ...
### @(#) fixer Dateiname: "/tmp/webcam/webcam4-5.jpg"
### @(#)imgsrc_: Name einer temporaeren Bilddatei die aus imgsrc
### @(#) erstellt wird mit Bildgroesse 200x200 (Rechenzeitoptimierung)
### @(#) fixer Dateiname: "/tmp/webcam/webcam4-5_.jpg"
### @(#)imgdst: Name einer temporaeren Bilddatei die daraus erzeugt wird
### @(#) und ins bmp-Format konvertiert wurde
### @(#)fixer Dateiname: "/tmp/webcam/img5.bmp3"
### @(#)log: logfile: "/tmp/hellsum-5.log" # Ausgabedatei (appended)
### @(#)
### @(#){Diagnostics}: -
### @(#)
### @(#){Bugs}: -
### @(#)
### @(#){History}: -
### @(#)
### @(#){See also}: fhem, imagemagick, hell-dunkel
### @(#)
### @(#){keywords}: Helligkeitssensor, Helligkeit, webcam
### @(#)
### @(#){caveats}: benoetigs imagemagick framework
### @(#)
### @(#)END_of_sccsheader
#: sanity checks
export PATH || (/bin/sh $0; /bin/kill $$)
PATH="/bin"
PATH="`cd /bin; pwd`:`cd /usr/bin; pwd`:/opt/local/bin:/usr/local/bin" #handle universe dependicies
IFS='
'
export IFS
TZ='MEST-1NDT'
export TZ
# needs imagemagick package (convert), see http://de.wikipedia.org/wiki/ImageMagick
# if you dont know how to build imagemagick on fritzbox, PI, ...
# dont ask me
imgsrc="/tmp/webcam/webcam4-5.jpg" # name of the file generated by the webcam
imgsrc_="/tmp/webcam/webcam4-5_.jpg" # temp file for resizing webcam file
imgdst="/tmp/webcam/img5.bmp3" # temp file of resized file in bmp format
log="/tmp/hellsum-5.log"
convert -geometry 200x200 "$imgsrc" "$imgsrc_" # resize to valuable size
convert "$imgsrc_" "$imgdst" # convert to bmp3 format
rel="`perl /usr/local/bin/hellsumx.pl \"$imgdst\" | sed 1q`" # Helligkeitswert
rc=$? # returncode
d="`date '+%a, %d. %m. %Y %T'`" # aktual date
echo "$d $rel" >>"$log" # add date and Wert to hist file (ascii format)
exit $rc # end with correct return code
code fuer Hilfsskript hellsumx.pl
### @(#){hellsumx.pl} - {ermittelt aktuellen Helligkeitswert 0..100 aus Bilddatei im .img-Format}
### @(#)
### @(#){Richard Bothe} Version {1.0} vom {11.11.2013}
### @(#)
### @(#){Anwendungsklasse}: Tools fuer FHEM [8]
### @(#)
### @(#){Synopsis} perl hellsumx.pl file.bmp3
### @(#)
### @(#){Description}
### @(#)ermittelt aus den einzelnen bitmap-Informationen einer BMP-Bilddatei
### @(#)den gemittelten Helligkeitswert im Bereich 0 .. 100
### @(#)Dieser wird auf stdout ausgegeben.
### @(#)
### @(#){Returncodes}: 0 bei keinem erkannten Fehler
### @(#)
### @(#){Description of I/O channels}: -
### @(#)
### @(#){Description of Parameters}: bmp-filename (bmp3-format)
### @(#)
### @(#){Examples} perl hellsumx.pl file.bmp3
### @(#) --> 70
### @(#)
### @(#){Called by} hell45
### @(#)
### @(#){Calls} -
### @(#)
### @(#){Files needed}: -
### @(#)
### @(#){Packages needed}: Image::BMP
### @(#)
### @(#){Diagnostics}: -
### @(#)
### @(#){Bugs}: does not reclaim missing filenames
### @(#)
### @(#){History}: -
### @(#)
### @(#){See also}: fhem, hell45, hell-dunkel
### @(#)
### @(#){keywords}: Helligkeitssensor, Helligkeit, webcam
### @(#)
### @(#){caveats}: benoetigs perl package Image::BMP
### @(#) auf einigen Linuxen muss explizit Format bmp3 benutzt werden, bmp reicht nicht, sonst Fehler in $img->open_file($img_name)
### @(#)
### @(#)END_of_sccsheader
use Image::BMP; # BMP Package needed
my $img = new Image::BMP; # new empty image
my $img_name=$ARGV[0]; # image file name
$img->open_file($img_name); # open image file
$h=$img->{Height};
$w=$img->{Width};
$summe=0;
# loop over all pixels
for ($i=0; $i<$w; $i++) {
for ($j=0; $j<$h; $j++) {
($r,$g,$b) = $img->xy_rgb($i,$j); # red,green,blue values of pixel
$summe+=($r+$g+$b); # sum of all pixel values
}
}
$summax=3*256*($h+1)*($w+1); # maximum value (all 100)
$rel=100.0 * $summe / $summax; # ratio of sumval of pixels and max value
$relint=int($rel+0.5); # round to integer
print "$relint\n";
Code fuer skript hell-dunkel
#!/bin/sh
#: || exec /bin/sh $0 $argv:q
#(alias) >/dev/null 2>&1 && exec /bin/sh "$0" $1+{"$@"}
### @(#)
### @(#){hell-dunkel} - {wertet Helligkeitswerte aus logfile aus und erzeugt Aktionen, wenn sich status hell / dunkel aendert}
### @(#)
### @(#){Richard Bothe} Version {1.0} vom {11.11.2013}
### @(#)
### @(#){Anwendungsklasse}: Tools fuer FHEM [8]
### @(#)
### @(#){Synopsis} hell-dunkel
### @(#)
### @(#){Description}
### @(#)Aus einem vorhanden laufend fortgeschriebenem logfile mit
### @(#)Helligkeitswerten (0 .. 100) werden die letzten (5) Werte genommen
### @(#)und eine Aktion ausgeloest, wenn sich der Status hell/dunkel
### @(#)geaendert hat im Vergleich mit den letzten 4 Werten und
###@(#)den Limit ueber/unterschreitet.
### @(#)Die letzten 4 werden genommen, damit kurzfristige Schwankungen
### @(#)nicht ausloesen.
### @(#)
### @(#){Returncodes}: 0 bei keinem erkannten Fehler
### @(#)
### @(#){Description of I/O channels}: stdout: Aenderungstext bei Wechsel von hell ./. dunkel
### @(#)
### @(#){Description of Parameters}: -
### @(#)
### @(#){Called by} cron every 2 minutes or manually
### @(#)
### @(#){Calls} hell-dunkel.awk
### @(#)
### @(#){Examples} hell-dunkel
### @(#)
### @(#){Files needed}
### @(#)logfile: fortgeschriebenes logfile der Helligkeitswerte
### @(#) fixer Dateiname: "/tmp/hellsum-5.log"
### @(#) Format: Datum Helligkeitswert (0..100)
### @(#)outfile: fortgeschriebenes file mit Ergebnis der Berechnung,
### @(#) eigentlich nur fuer debugging
### @(#) fixer Dateiname: "/tmp/hell.dat"
### @(#)
### @(#){Diagnostics}:
### @(#)Es wird draussen hell Datum # bei Wechsel
### @(#)Es wird draussen dunkel Datum # bei Wechsel
### @(#)
### @(#){Bugs}: -
### @(#)
### @(#){History}: -
### @(#)
### @(#){See also}: fhem, hell45
### @(#)
### @(#){keywords}: Helligkeitssensor, Helligkeit, webcam
### @(#)
### @(#){caveats}: -
### @(#)
### @(#)END_of_sccsheader
#: sanity checks
PATH="$PATH:/usr/local/bin"
export PATH
logfile="/tmp/hellsum-5.log" # hist file written by hell45 each 2 minutes
outfile="/tmp/hell.dat" # fortgeschriebens Ergebnis fuer Debugging
script="/usr/local/bin/hell-dunkel.awk" # helper script
helllimit="45" # limit (0..100) for state "hell"
dunkellimit="35" # limit (0..100) for state "dunkel"
# beide Werte sind Beispielswerte, zu ermitteln je nach
# Tageszeit mit hell45
tailval=5 # respect last $tailval lines
res="`
cat \"$logfile\" | grep -v '^#' |
tail -$tailval | awk -f \"$script\" helllimit=\"$helllimit\" \
dunkellimit=\"$dunkellimit\" -`"
if [ "X$res" != "X" ]; then
echo "$res" # Ausgabe
echo "$res" >>"$outfile"
#sag-was "$res" >/dev/null 2>&1 # Beispiel fuer Sprachausgabe
#dreambox-mess "$res" # Beispiel fuer Ausgabe auf TV via dreambox
fi
exit
Code fuer Hilfsskript hell-dunkel.awk
#!/bin/sh
### @(#)
### @(#){hell-dunkel.awk} - {ermittelt Helligkeitswertswechselvon hel/dunkel}
### @(#)Hilfskript fuer hell-dunkel
### @(#)
### @(#){Richard Bothe} Version {1.0} vom {11.11.2013}
### @(#)
### @(#){Anwendungsklasse}: Tools fuer FHEM [8]
### @(#)
### @(#){Synopsis} awk -f hell-dunkel.awk helllimit="$helllimit" dunkellimit="$dunkellimit" -
### @(#)
### @(#){Description}
### @(#)erkennt einen Wechsel von hell ./. dunkel
### @(#)Die 5 Werte (einer / Zeile) werden inspiziert.
### @(#)Es wird ein Text ausgegeben, wenn sich Status aendert wie folgt:
### @(#)der letzte Wert ist von den 4 Werten davor verschieden
### @(#)
### @(#){Returncodes}: 0 bei keinem erkannten Fehler
### @(#)
### @(#){Description of I/O channels}:
### @(#)stdin: logfileinput
### @(#)stdout: msg bei Aenderung hell / dunkel
### @(#)
### @(#){Description of Parameters}: -
### @(#)
### @(#){Examples} hell-dunkel.awk
### @(#)
### @(#){Files needed}: -
### @(#)
### @(#){Diagnostics}:
### @(#)Es wird draussen hell: tag monat jahr zeit
### @(#)Es wird draussen dunkel: tag monat jahr zeit
### @(#)
### @(#){Bugs}: -
### @(#)
### @(#){History}: -
### @(#)
### @(#){See also}: fhem, hell-dunkel, hell45
### @(#)
### @(#){keywords}: Helligkeitssensor, Helligkeit, webcam
### @(#)
### @(#){caveats}: -
### @(#)
### @(#)END_of_sccsheader
#: sanity checks
BEGIN {
val_change=""
}
NF>=6 {
str=$0
tag=$2
monat=$3
jahr=$4
zeit=$5
val=$6
status="x" # undetermined oder Zwischenwert
if (val>helllimit) {
status="h" # hell
}
if (val<dunkellimit) {
status="d" # dunkel
}
if (NR==1) { # 1. Zeile
status1=status
}
if (NR==2) { # 2. Zeile
status2=status
}
if (NR==3) { # 3. Zeile
status3=status
}
if (NR==4) { # 4. Zeile
status4=status
}
if (NR==5) { # 5. Zeile
status5=status
}
}
END {
if ((status1=="d" || status1=="x") \
&& (status2=="d" || status2=="x" ) \
&& (status3=="d" || status3=="x" ) \
&& (status4=="d" || status4=="x" ) \
&& (status5=="h" )) {
val_change="h" # es wird hell
print "Es wird draussen hell: " tag monat jahr " " zeit
}
if ((status1=="h" || status1=="x") \
&& (status2=="h" || status2=="x" ) \
&& (status3=="h" || status3=="x" ) \
&& (status4=="h" || status4=="x" ) \
&& (status5=="d" )) {
val_change="d" # es wird dunkel
print "Es wird draussen dunkel: " tag monat jahr " " zeit
}
}
Alle Skripte sollen unter /usr/local/bin platziert werden oder die Pfade darin angepasst werden.
Nicht vergessen, skripts hell45 und hell-dunkel ausfuehrbar zu machen (chmod 755 hell45 hell-dunkel)
und darin die Pfade in hell45 der images anzupassen (/tmp/webcam/...).