From af74b169635c77f21984ae832661d039dc4febd1 Mon Sep 17 00:00:00 2001 From: rudolfkoenig <> Date: Fri, 12 Dec 2008 11:06:36 +0000 Subject: [PATCH] Readme update and the additions from Martin git-svn-id: https://svn.fhem.de/fhem/trunk/fhem@286 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- contrib/86_FS10.pm | 166 ++++++++ contrib/JsonList/99_JsonList.pm | 386 ++++++++++++++++++ contrib/JsonList/README.JsonList | 109 +++++ contrib/JsonList/commandref.html.patch | 108 +++++ contrib/README | 34 +- contrib/README.FS10 | 37 ++ contrib/fhem2speech/README.fhem2speech | 63 +++ contrib/fhem2speech/fhem2speech.sh | 12 + .../rotateShiftWork/README.rotateShiftWork | 24 ++ contrib/rotateShiftWork/rotateShiftWork.sh | 102 +++++ 10 files changed, 1024 insertions(+), 17 deletions(-) create mode 100644 contrib/86_FS10.pm create mode 100644 contrib/JsonList/99_JsonList.pm create mode 100644 contrib/JsonList/README.JsonList create mode 100644 contrib/JsonList/commandref.html.patch create mode 100644 contrib/README.FS10 create mode 100644 contrib/fhem2speech/README.fhem2speech create mode 100755 contrib/fhem2speech/fhem2speech.sh create mode 100644 contrib/rotateShiftWork/README.rotateShiftWork create mode 100755 contrib/rotateShiftWork/rotateShiftWork.sh diff --git a/contrib/86_FS10.pm b/contrib/86_FS10.pm new file mode 100644 index 000000000..29aaa710b --- /dev/null +++ b/contrib/86_FS10.pm @@ -0,0 +1,166 @@ +############################################## +package main; + +use strict; +use warnings; +use Device::SerialPort; +use IO::Socket::INET; + +my $fs10data = ""; +my $pcwsdsocket; + + +##################################### +sub +FS10_Initialize($) +{ + my ($hash) = @_; + + # Consumer + $hash->{DefFn} = "FS10_Define"; + $hash->{AttrList}= "model:FS10 loglevel:0,1,2,3,4,5,6"; +} + +##################################### +sub +FS10_Define($$) +{ + my ($hash, $def) = @_; + my @a = split("[ \t][ \t]*", $def); + + Log 3, "FS10 Define: $a[0] $a[1] $a[2] $a[3]"; + + return "Define the host and portnr as a parameter i.e. 127.0.0.1 4711" + if(@a != 4); + + $hash->{Timer} = 600; + $hash->{Host} = $a[2]; + $hash->{Port} = $a[3]; + $hash->{STATE} = "Initialized"; + + my $dev = $a[2]; + Log 1, "FS10 device is none, commands will be echoed only" + if($dev eq "none"); + + $hash->{DeviceName} = $dev; + + FS10_GetStatus($hash); + return undef; +} + + +##################################### +sub +FS10_GetStatus($) +{ + my ($hash) = @_; + my $buf; + #my $banner; + my $reqcmd; + my $fs10time; + my $dt; + my $x; + my $result = ""; + + Log 3, "FS10_GetStatus"; + + # Call us in 5 minutes again. + InternalTimer(gettimeofday()+300, "FS10_GetStatus", $hash, 0); + + my $dnr = $hash->{DEVNR}; + my $name = $hash->{NAME}; + my $host = $hash->{Host}; + my $port = $hash->{Port}; + my %vals; + my $pcwsd ="$host:$port"; + my $pcwsdsocket = IO::Socket::INET->new( $pcwsd ) + or return "FS10 Can't bind to pcwsd" if(!$pcwsdsocket); + + my $banner = $pcwsdsocket->getline(); + my @x = split(" ", $banner); + my @y; + my $fs10name; + + for(my $i = 0; $i < 8; $i++) #Outdoor + { + $fs10name ="Ta$i"; + $reqcmd = "get od2temp $i\r\n"; + $pcwsdsocket->print($reqcmd); + $buf = $pcwsdsocket->getline(); + $result = "$result $buf"; + + @x = split(" ", $buf); + $fs10time = FmtDateTime($x[1]); + + $hash->{CHANGED}[$i] = "Ta$i: $x[0]"; + $hash->{READINGS}{$fs10name}{TIME} = $fs10time; + $hash->{READINGS}{$fs10name}{VAL} = $x[0]; + } + + $fs10name="Ti"; + $reqcmd = "get idtemp 7\r\n"; + $pcwsdsocket->print($reqcmd); + $buf = $pcwsdsocket->getline(); + @x = split(" ", $buf); + $fs10time = FmtDateTime($x[1]); + + $hash->{CHANGED}[8] = "Ti: $x[0]"; + $hash->{READINGS}{$fs10name}{TIME} = $fs10time; + $hash->{READINGS}{$fs10name}{VAL} = $x[0]; + + $fs10name="Rain"; + $reqcmd = "get rain 7\r\n"; + $pcwsdsocket->print($reqcmd); + $buf = $pcwsdsocket->getline(); + @x = split(" ", $buf); + $fs10time = FmtDateTime($x[1]); + + $hash->{CHANGED}[9] = "Rain: $x[0]"; + $hash->{READINGS}{$fs10name}{TIME} = $fs10time; + $hash->{READINGS}{$fs10name}{VAL} = $x[0]; + + $fs10name="Sun"; + $reqcmd = "get bright 7\r\n"; + $pcwsdsocket->print($reqcmd); + $buf = $pcwsdsocket->getline(); + @x = split(" ", $buf); + $fs10time = FmtDateTime($x[1]); + + $hash->{CHANGED}[10] = "Sun: $x[0]"; + $hash->{READINGS}{$fs10name}{TIME} = $fs10time; + $hash->{READINGS}{$fs10name}{VAL} = $x[0]; + + $fs10name="Windspeed"; + $reqcmd = "get wspd 7\r\n"; + $pcwsdsocket->print($reqcmd); + $buf = $pcwsdsocket->getline(); + @x = split(" ", $buf); + $fs10time = FmtDateTime($x[1]); + + $hash->{CHANGED}[11] = "Windspeed: $x[0]"; + $hash->{READINGS}{$fs10name}{TIME} = $fs10time; + $hash->{READINGS}{$fs10name}{VAL} = $x[0]; + + close($pcwsdsocket); + + $result =~ s/[\r\n]//g; + DoTrigger($name, undef) if($init_done); + + $hash->{STATE} = "$result"; + Log 3,"FS10 Result: $result"; + return $hash->{STATE}; +} + +##################################### +sub +FS10Log($$) +{ + my ($a1, $a2) = @_; + + #define n31 notify fs10 {FS10Log("@", "%")} + #define here notify action + + Log 2,"FS10 $a1 = $a2 old: $oldvalue{$a1}{TIME}=> $oldvalue{$a1}{VAL});"; +} + +1; diff --git a/contrib/JsonList/99_JsonList.pm b/contrib/JsonList/99_JsonList.pm new file mode 100644 index 000000000..56212593a --- /dev/null +++ b/contrib/JsonList/99_JsonList.pm @@ -0,0 +1,386 @@ +################################################################ +# +# Copyright notice +# +# (c) 2008 Copyright: Martin Fischer (m_fischer at gmx dot de) +# All rights reserved +# +# This script 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 +# (at your option) 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. +# +################################################################ +# examples: +# jsonslist - returns all definitions and status infos +# jsonlist lamp1 - returns definitions and status infos for 'lamp1' +# jsonlist FS20 - returns status infos for FS20 devices +# jsonlist ROOMS - returns a list of rooms +################################################################ + +package main; +use strict; +use warnings; +use POSIX; + +sub CommandJsonList($$); +sub JsonEscape($); +sub PrintHashJson($$); + + +##################################### +sub +JsonList_Initialize($$) +{ + my %lhash = ( Fn=>"CommandJsonList", + Hlp=>"[||rooms],list definitions and status info or rooms as JSON" ); + $cmds{jsonlist} = \%lhash; +} + + +##################################### +sub +JsonEscape($) +{ + my $a = shift; + return "null" if(!$a); + my %esc = ( + "\n" => '\n', + "\r" => '\r', + "\t" => '\t', + "\f" => '\f', + "\b" => '\b', + "\"" => '\"', + "\\" => '\\\\', + "\'" => '\\\'', + ); + $a =~ s/([\x22\x5c\n\r\t\f\b])/$esc{$1}/eg; + return $a; +} + +##################################### +sub +PrintHashJson($$) +{ + my ($h, $lev) = @_; + + my ($str,$sstr) = ("",""); + + my $hc = keys %{$h}; + my $cc = 1; + + foreach my $c (sort keys %{$h}) { + + if(ref($h->{$c})) { + if(ref($h->{$c}) eq "HASH" && $c ne "PortObj") { + if($c eq "IODev" || $c eq "HASH") { + $str .= sprintf("%*s\"%s\": \"%s\"", $lev," ",$c, JsonEscape($h->{$c}{NAME})); + } else { + $str .= sprintf("%*s\"%s\": {\n", $lev, " ", $c); + if(keys(%{$h->{$c}}) != 0) { + $str .= PrintHashJson($h->{$c}, $lev+2); + } else { + $str .= sprintf("%*s\"null\": \"null\"\n", $lev+4, " "); + } + $str .= sprintf("%*s}", $lev, " "); + } + } elsif(ref($h->{$c}) eq "ARRAY") { + $str .= sprintf("%*s\"%s\": \"%s\"", $lev," ",$c, "ARRAY"); + } elsif($c eq "PortObj") { + $str .= sprintf("%*s\"%s\": \"%s\"", $lev," ",$c, "PortObj"); + } + } else { + $str .= sprintf("%*s\"%s\": \"%s\"", $lev," ",$c, JsonEscape($h->{$c})); + } + $str .= ",\n" if($cc != $hc); + $str .= "\n" if($cc == $hc); + $cc++; + } + + return $str; +} + +##################################### +sub +CommandJsonList($$) +{ + my ($cl, $param) = @_; + my $lt = ""; + my $str = ""; + + # Text indentation + my $lev = 2; + + if(!$param) { + # Array counter + my @ac; + my $ac = 0; + my $cc = 0; + my @dc; + my $dc = 0; + my $tc = 0; # total available + my $tr = 0; # results returned + + my $q = ""; + + # Open JSON object + $str = "{\n"; + $str .= sprintf("%*s\"ResultSet\": {\n", $lev, " "); + # Open JSON array + $str .= sprintf("%*s\"Results\": [\n", $lev+2, " "); + + delete($modules{""}) if(defined($modules{""})); + @dc = keys(%defs); + $dc = @dc; + #$tc = 0; + for my $d (sort { my $x = $modules{$defs{$a}{TYPE}}{ORDER} cmp + $modules{$defs{$b}{TYPE}}{ORDER}; + $x = ($a cmp $b) if($x == 0); $x; } keys %defs) { + + my $p = $defs{$d}; + my $t = $p->{TYPE}; + $t = $q if($q ne ""); + + $str .= sprintf("} ") if($t eq $lt); + $str .= sprintf("},\n") if($t eq $lt); + + if($t ne $lt) { + $str .= sprintf("} ") if($lt); + $str .= sprintf("}\n") if($lt); + $str .= sprintf("%*s]\n", $lev+6, " ") if($lt); + $str .= sprintf("%*s},\n", $lev+4, " ") if($lt); + #$str .= sprintf("%*s{\n", $lev+4, " "); + $str .= sprintf("%*s\{ \"%s_LIST\": [\n", $lev+4, " ", $t); + } + $lt = $t; + + my $a1 = JsonEscape($p->{STATE}); + my $a2 = JsonEscape(getAllSets($d)); + my @sets; + foreach my $k2 (split(" ", $a2)) { + push @sets, $k2; + } + my $a3 = JsonEscape(getAllAttr($d)); + my @attrs; + foreach my $k3 (split(" ", $a3)) { + push @attrs, $k3; + } + + #$str .= sprintf("%*s{\n", $lev+8, " "); + $str .= sprintf("%*s{ \"%s\": { ", $lev+8, " ", $t); + $str .= sprintf("\"name\": \"%s\", ", $d); + $str .= sprintf("\"state\": \"%s\", ", $a1); + $str .= sprintf("\"sets\": [ "); + + $ac = @sets; + $cc = 0; + foreach my $set (@sets) { + $str .= sprintf("{ \"VAL\": \"%s\" }", $set); + $cc++; + #$str .= ",\n" if($cc != $ac); + $str .= ", " if($cc != $ac); + #$str .= "\n" if($cc == $ac); + } + $str .= sprintf(" ], "); + $str .= sprintf("\"attrs\": [ "); + $ac = @attrs; + $cc = 0; + foreach my $attr (@attrs) { + $str .= sprintf("{ \"VAL\": \"%s\" }", $attr); + $cc++; + #$str .= ",\n" if($cc != $ac); + $str .= "," if($cc != $ac); + #$str .= "\n" if($cc == $ac); + } + $str .= sprintf(" ], "); + + $str .= sprintf("\"INT\": { "); + @ac = keys(%{$p}); + $ac = 0; + foreach my $k (sort @ac) { + next if(ref($p->{$k})); + $ac++; + } + $cc = 0; + + foreach my $c (sort keys %{$p}) { + next if(ref($p->{$c})); + $str .= sprintf("\"%s\": \"%s\"", + JsonEscape($c), JsonEscape($p->{$c})); + $cc++; + #$str .= ",\n" if($cc != $ac || ($cc == $ac && $p->{IODev})); + $str .= ", " if($cc != $ac || ($cc == $ac && $p->{IODev})); + #$str .= "\n" if($cc == $ac && !$p->{IODev}); + } + $str .= sprintf("\"IODev\": \"%s\" ", + $p->{IODev}{NAME}) if($p->{IODev}); + $str .= sprintf(" }, "); + + $str .= sprintf("\"ATTR\": { "); + @ac = keys(%{$attr{$d}}); + $ac = @ac; + $cc = 0; + foreach my $c (sort keys %{$attr{$d}}) { + $str .= sprintf("\"%s\": \"%s\"", + JsonEscape($c), JsonEscape($attr{$d}{$c})); + $cc++; + #$str .= ",\n" if($cc != $ac); + $str .= ", " if($cc != $ac); + #$str .= "\n" if($cc == $ac); + } + $str .= sprintf(" }, ") if($p->{READINGS}); + $str .= sprintf(" } ") if(!$p->{READINGS}); + + my $r = $p->{READINGS}; + if($r) { + $str .= sprintf("\"STATE\": { "); + @ac = keys(%{$r}); + $ac = @ac; + $cc = 0; + foreach my $c (sort keys %{$r}) { + $str .= + sprintf("\"%s\": \"%s\", \"measured\": \"%s\"", + JsonEscape($c), JsonEscape($r->{$c}{VAL}), $r->{$c}{TIME}); + $cc++; + #$str .= ",\n" if($cc != $ac); + $str .= ", " if($cc != $ac); + #$str .= "\n" if($cc == $ac); + } + $str .= sprintf(" } "); + } + $tc++; + $tr = $tc if($q eq ""); + $tr++ if($q ne "" && $p->{TYPE} eq $t); + $str .= sprintf("} ") if(($tc == $dc) || (!$lt)); + $str .= sprintf("}\n") if(($tc == $dc) || (!$lt)); + $str .= sprintf("%*s]\n", $lev+6, " ") if(($tc == $dc) || (!$lt)); + } + $str .= sprintf("%*s}\n", $lev+4, " ") if($lt); + $str .= sprintf("%*s],\n", $lev+2, " "); + $str .= sprintf("%*s\"totalResultsAvailable\": %s,\n", $lev+2, " ",$tc); + $str .= sprintf("%*s\"totalResultsReturned\": %s\n", $lev+2, " ",$tr); + $str .= sprintf("%*s}\n", $lev, " "); + $str .= "}"; + } else { + if($param eq "ROOMS") { + my @rooms; + foreach my $d (sort keys %defs) { + if($attr{$d}{"room"}) { + push(@rooms, $attr{$d}{"room"}) unless(grep($_ eq $attr{$d}{"room"}, @rooms)); + next; + } + } + @rooms = sort(@rooms); + + # Result counter + my $c = 0; + + # Open JSON object + $str .= "{\n"; + $str .= sprintf("%*s\"%s\": {\n", $lev, " ", "ResultSet"); + # Open JSON array + $str .= sprintf("%*s\"%s\": [", $lev+2, " ", "Results"); + + for (my $i=0; $i<@rooms; $i++) { + $str .= " }," if($i <= $#rooms && $i > 0); + $str .= sprintf("\n%*s{ \"NAME\": \"%s\"", $lev+4, " ", $rooms[$i]); + $c++; + } + + $str .= " }\n"; + # Close JSON array + $str .= sprintf("%*s],\n", $lev+2, " "); + # Result summary + $str .= sprintf("%*s\"%s\": %s,\n", $lev+2, " ", "totalResultsAvailable", $c); + $str .= sprintf("%*s\"%s\": %s\n", $lev+2, " ", "totalResultsReturned", $c); + # Close JSON object + $str .= sprintf("%*s}\n", $lev, " "); + $str .= "}"; + + } else { + # Search for given device-type + my $listDev = ""; + foreach my $d (sort { my $x = $defs{$a}{TYPE} cmp + $defs{$b}{TYPE}; + $x = ($a cmp $b) if($x == 0); $x; } keys %defs) { + if($param eq $defs{$d}{TYPE}) { + $listDev = $defs{$d}{TYPE}; + next; + } + } + + # List devices by type + if($listDev ne "") { + my $lt = ""; + my $ld = ""; + # Result counter + my $c = 0; + + # Open JSON object + $str .= "{\n"; + $str .= sprintf("%*s\"%s\": {\n", $lev, " ", "ResultSet"); + # Open JSON array + $str .= sprintf("%*s\"%s\": [", $lev+2, " ", "Results"); + + # Sort first by type then by name + for my $d (sort { my $x = $modules{$defs{$a}{TYPE}}{ORDER} cmp + $modules{$defs{$b}{TYPE}}{ORDER}; + $x = ($a cmp $b) if($x == 0); $x; } keys %defs) { + if($defs{$d}{TYPE} eq $param) { + my $t = $defs{$d}{TYPE}; + $str .= " }," if($d ne $ld && $lt ne ""); + $str .= sprintf("\n%*s{ \"NAME\": \"%s\", \"STATE\": \"%s\"", + $lev+4, " ", $d, $defs{$d}{STATE}); + $lt = $t; + $ld = $d; + $c++; + } + } + + $str .= " }\n"; + # Close JSON array + $str .= sprintf("%*s],\n", $lev+2, " "); + # Result summary + $str .= sprintf("%*s\"%s\": %s,\n", $lev+2, " ", "totalResultsAvailable", $c); + $str .= sprintf("%*s\"%s\": %s\n", $lev+2, " ", "totalResultsReturned", $c); + # Close JSON object + $str .= sprintf("%*s}\n", $lev, " "); + $str .= "}"; + + } else { + # List device + foreach my $sdev (devspec2array($param)) { + if(!defined($defs{$sdev})) { + $str .= "No device named or type $param found, try for all devices"; + next; + } + $defs{$sdev}{"ATTRIBUTES"} = $attr{$sdev}; + # Open JSON object + $str = "{\n"; + $str .= sprintf("%*s\"%s\": {\n", $lev, " ", "ResultSet"); + # Open JSON array + $str .= sprintf("%*s\"%s\": {\n", $lev+2, " ", "Results"); + $str .= PrintHashJson($defs{$sdev}, $lev+4); + # Close JSON array + $str .= sprintf("%*s}\n", $lev+2, " "); + # Close JSON object + $str .= sprintf("%*s}\n", $lev, " "); + $str .= "}"; + } + } + } + } + return $str; +} + +1; diff --git a/contrib/JsonList/README.JsonList b/contrib/JsonList/README.JsonList new file mode 100644 index 000000000..4d461befc --- /dev/null +++ b/contrib/JsonList/README.JsonList @@ -0,0 +1,109 @@ +JsonList.pm - Copyright (c)2008 Martin Fischer + +Description: + The module JsonList.pm extends FHEM to support a JSON output + similar to FHEM's xmllist. + +Installation: + Copy the script 99_JsonList.pm to FHEM modules directory, e.g. + 'cp 99_JsonList.pm /usr/local/lib/FHEM' + and restart FHEM. + + Keep your commandref.html up-to-date: + copy the patchfile commandref.html.patch to your directory with + the original commandref.html and type + 'patch < commandref.html.patch' + You can remove the patchfile after this step. + +Usage: + jsonlist [||ROOMS] + + Returns an JSON tree of all definitions, all notify settings and + all at entries if no parameter is given. + + If specifying , then a detailed status for will + be displayed. + + If specifying , then a list with the status for the + defined devices will be displayed, e.g.: + + If specifying ROOMS, then a list with the defined rooms will be + displayed, e.g.: + + Example: + FHZ> jsonlist + { + "ResultSet": { + "Results": [ + { "_internal__LIST": [ + { "_internal_": { + "name": "global", + "state": "", + "sets": [ { "VAL": "null" } ], + "attrs": [ { "VAL": "room" },{ "VAL": "comment" }, + [...] + ], + "totalResultsAvailable": 86, + "totalResultsReturned": 86 + } + } + + Example for : + FHZ> jsonlist lamp1 + { + "ResultSet": { + "Results": { + "ATTRIBUTES": { + "comment": "Light", + "room": "Livingroom" + }, + "BTN": "f0", + [...] + "NAME": "lamp1", + "NR": "26", + "READINGS": { + "state": { + "TIME": "2008-12-11 18:11:21", + "VAL": "toggle" + } + }, + "STATE": "on", + "TYPE": "FS20", + "XMIT": "0b0b" + } + } + } + + Example for : + FHZ> jsonlist HMS + { + "ResultSet": { + "Results": [ + { "NAME": "smokeDetector01", "STATE": "smoke_detect: off" }, + { "NAME": "smokeDetector02", "STATE": "smoke_detect: off" }, + { "NAME": "smokeDetector03", "STATE": "smoke_detect: off" } + ], + "totalResultsAvailable": 3, + "totalResultsReturned": 3 + } + } + + Example for ROOMS: + FHZ> jsonlist ROOMS + { + "ResultSet": { + "Results": [ + { "NAME": "Bathroom" }, + { "NAME": "Office" }, + { "NAME": "Diningroom" }, + { "NAME": "Garden" }, + { "NAME": "House" }, + { "NAME": "Bedroom" }, + { "NAME": "Garage" }, + { "NAME": "Livingroom" }, + { "NAME": "hidden" } + ], + "totalResultsAvailable": 9, + "totalResultsReturned": 9 + } + } diff --git a/contrib/JsonList/commandref.html.patch b/contrib/JsonList/commandref.html.patch new file mode 100644 index 000000000..f316acca6 --- /dev/null +++ b/contrib/JsonList/commandref.html.patch @@ -0,0 +1,108 @@ +--- commandref.html-orig 2008-12-11 19:37:59.000000000 +0100 ++++ commandref.html 2008-12-11 19:15:02.000000000 +0100 +@@ -27,6 +27,7 @@ + ?,help   + include   + inform   ++ jsonlist   + list   + modify   + quit   +@@ -434,6 +435,97 @@ +
+ + ++ ++

jsonlist

++
    ++ jsonlist [<devspec>|<typespec>|ROOMS] ++

    ++ Returns an JSON tree of all definitions, all notify settings and all at ++ entries if no parameter is given. ++

    ++ Example: ++
      FHZ> jsonlist
    ++  {
    ++    "ResultSet": {
    ++      "Results": [
    ++        { "_internal__LIST": [
    ++            { "_internal_": {
    ++              "name": "global",
    ++              "state": "",
    ++              "sets": [ { "VAL": "null" } ],
    ++              "attrs": [ { "VAL": "room" },{ "VAL": "comment" },
    ++        [...]
    ++      ],
    ++      "totalResultsAvailable": 86,
    ++      "totalResultsReturned": 86
    ++    }
    ++  }
    ++  
    ++ If specifying <devspec>, then a detailed status for ++ <devspec> will be displayed, e.g.: ++
      FHZ> jsonlist lamp1
    ++  {
    ++    "ResultSet": {
    ++      "Results": {
    ++        "ATTRIBUTES": {
    ++          "comment": "Light",
    ++          "room": "Livingroom"
    ++        },
    ++        "BTN": "f0",
    ++        [...]
    ++        "NAME": "lamp1",
    ++        "NR": "26",
    ++        "READINGS": {
    ++          "state": {
    ++            "TIME": "2008-12-11 18:11:21",
    ++            "VAL": "toggle"
    ++          }
    ++        },
    ++        "STATE": "on",
    ++        "TYPE": "FS20",
    ++        "XMIT": "0b0b"
    ++      }
    ++    }
    ++  }
    ++  
    ++ If specifying <typespec>, then a list with the status for ++ the defined <typespec> devices will be displayed, e.g.: ++
      FHZ> jsonlist HMS
    ++  {
    ++    "ResultSet": {
    ++      "Results": [
    ++        { "NAME": "smokeDetector01", "STATE": "smoke_detect: off" },
    ++        { "NAME": "smokeDetector02", "STATE": "smoke_detect: off" },
    ++        { "NAME": "smokeDetector03", "STATE": "smoke_detect: off" }
    ++      ],
    ++      "totalResultsAvailable": 3,
    ++      "totalResultsReturned": 3
    ++    }
    ++  }
    ++  
    ++ If specifying ROOMS, then a list with the defined rooms ++ will be displayed, e.g.: ++
      FHZ> jsonlist ROOMS
    ++  {
    ++    "ResultSet": {
    ++      "Results": [
    ++        { "NAME": "Bathroom" },
    ++        { "NAME": "Office" },
    ++        { "NAME": "Diningroom" },
    ++        { "NAME": "Garden" },
    ++        { "NAME": "House" },
    ++        { "NAME": "Bedroom" },
    ++        { "NAME": "Garage" },
    ++        { "NAME": "Livingroom" },
    ++        { "NAME": "hidden" }
    ++      ],
    ++      "totalResultsAvailable": 9,
    ++      "totalResultsReturned": 9
    ++    }
    ++  }
    ++  
    ++
++ + +

list

+
    diff --git a/contrib/README b/contrib/README index cdf40feda..0dd736d98 100755 --- a/contrib/README +++ b/contrib/README @@ -1,8 +1,6 @@ - 70_SCIVT.pm Support for an SCD series solar controler device. Details see http://english.ivt-hirschau.de/content.php?parent_id=CAT_64&doc_id=DOC_118 -- 80_M232.pm/81_M232Counter.pm - Support for the M232 device from ELV by Boris. - 86_FS10.pm Support for FS10. Read README.FS10, you have to install pcwsd first. - 91_DbLog.pm @@ -11,38 +9,40 @@ - 99_ALARM.pm Example for a Low Budget ALARM System by Martin - 99_SUNRISE.pm - The original Sunrise/Sunset support. Uses DateTime::Event::Sunrise. Uses the - 99_SUNRISE_EL.pm module instead. -- 99_SUNRISE_EL.pm - Support foor computins sunrise/sunset times. -- 99_Utils.pm - skeleton for self-written perl funtions. -- 99_dummy.pm - Used for programming -- 99_weblink.pm - Used by fhemweb2.pl + The "original" (i.e. old) Sunrise/Sunset support. Needs the hard-to-install + DateTime::Event::Sunrise perl module. Use the 99_SUNRISE_EL.pm module instead. + - checkmsg.pl Check header/function/crc of an FS20 hex message - crc.pl Computing CRC16 in perl +- dblog/* + Support for a full-featured database log by Boris. See the README. - em1010.pl / em1010.gnuplot Standalone EM1010PC reader program and a gnuplot file to plot em1010 data -- init-scripts - RC scripts to be put into /etc/init.d and then symlinked to /etc/rc3.d or - similar. - four2hex Convert housecode from ELV notation (4) to fhem.pl notation (hex) + Not needed any more, as current fhem versions understand both. - fs20_holidays.sh STefan's "presence simulator" for holidays - garden.pl Garden irrigation regulator with weather dependency (KS300 temp + rain) +- JsonList + 99_JsonList.pm adds a jsonlist command, which is list in JSON format. + See JsonList/README.JsonList for more. By Martin. +- fhem2speech + Martins instructions on how to make FHEM talk using the MBROLA speech + synthesizer +- init-scripts + RC scripts to be put into /etc/init.d and then symlinked to /etc/rc3.d or + similar. - ks300avg.pl Computing daily/monthly avarage values from a KS300 log - rolwzo_not_off.sh Martin's "don't lock me out" program: look at the comment +- rotateShiftWork + Shellskript for changing am/pm temperatures when working on a shift - rrd Peter's RRD support. See the HOWTO - serial.pm Serial line analyzer -- dblog - Support for a full-featured database log by Boris. See the README. diff --git a/contrib/README.FS10 b/contrib/README.FS10 new file mode 100644 index 000000000..d89c41144 --- /dev/null +++ b/contrib/README.FS10 @@ -0,0 +1,37 @@ +86_FS10.pm is for reading ELV (www.elv.de) weather Sensors, using a Hardware +(Part No. 68-390-61) and communicates with pcwsd from Sven Geggus. + +Currently temperature, windspeed, rain and brightness sensors are supported. + +For use with FHEM you have to compile pcwsd like usual, it can be found here + http://geggus.net/sven/pcwsd/ + +Start pcwsd deamon with + pcwsd -d /dev/ttyUSB4 -ld /var/log/fs10- -tlf %Y-%m-%d_%T + +A few minutes later you should see files with temperature values. + +For use with FHEM define + +define fs10 FS10 127.0.0.1 4711 which means pcwsd run on localhost, port 4711 + +If you only interested in viewing temperature values with a FHEM frontend like +pgm3, 86_FS10.pm can be ommited. + +To display a user defined FS10 temperature graphic in pgm3 define + +######################## +# +$sortnumber=7; +$userdef[$sortnumber]['name']='IndoorTemp'; +$userdef[$sortnumber]['valuefield']=2; +$userdef[$sortnumber]['gnuplottype']='temperature'; +$userdef[$sortnumber]['logpath']='/var/log/fs10/idtemp_7.gnu'; +$userdef[$sortnumber]['room']='indoor'; +$userdef[$sortnumber]['semlong']='Temp indor'; +$userdef[$sortnumber]['semshort']='°'; +$userdef[$sortnumber]['imagemax']=725; +$userdef[$sortnumber]['imagemay']=52; +$userdef[$sortnumber]['maxcount']=575; +$userdef[$sortnumber]['XcorrectMainText']=25; +$userdef[$sortnumber]['logrotatelines']=2050; diff --git a/contrib/fhem2speech/README.fhem2speech b/contrib/fhem2speech/README.fhem2speech new file mode 100644 index 000000000..ffd072576 --- /dev/null +++ b/contrib/fhem2speech/README.fhem2speech @@ -0,0 +1,63 @@ +Copyright (c)2008 Martin Fischer + +Description: + The script fhem2speech.sh let FHEM talk. + +Requirements: + You need MBROLA synthesizer, a synthesis voice, txt2pho and bplay. + For more information visit: + o MBROLA Project, http://tcts.fpms.ac.be/synthesis/ + o hadifix, http://www.ikp.uni-bonn.de/dt/forsch/phonetik/hadifix/ + +Installation: + This describes the installation on ubuntu: + + Make a temporarily directory for the needed files and change to + the new directory, e.g.: + 'mkdir /usr/local/src/mbrola; cd !$' + + Download the required files: + 'wget http://www.ikp.uni-bonn.de/dt/forsch/phonetik/hadifix/txt2pho.zip' + 'wget http://tcts.fpms.ac.be/synthesis/mbrola/bin/pclinux/mbrola3.0.1h_i386.deb' + + Download at least one synthesis voice (e.g. german female voice): + 'wget http://tcts.fpms.ac.be/synthesis/mbrola/dba/de7/de7.zip' + + Install txt2pho: + 'unzip txt2pho.zip -d /usr/share/' + 'chmod 755 /usr/share/txt2pho/txt2pho' + + Edit txt2phorc: + 'vi /usr/share/txt2pho/txt2phorc' + and change the path for DATAPATH and INVPATH: + DATAPATH=/usr/share/txt2pho/data/ + INVPATH=/usr/share/txt2pho/data/ + + Copy txt2phorc to /etc/txt2pho: + 'cp /usr/share/txt2pho/txt2phorc /etc/txt2pho' + + Install the synthesis voice (e.g. german female voice): + 'unzip de7.zip -d /usr/share/mbrola/de7' + + Install mbrola: + 'dpkg -i mbrola3.0.1h_i386.deb' + + Install bplay: + 'apt-get install bplay' + + Test your installation: + 'echo "Test" | /usr/share/txt2pho/txt2pho | mbrola /usr/share/mbrola/de7/de7 - - | bplay -s22050 - +b 16' + + Copy the script fhem2speech.sh to a directory of your choice, + e.g.: + 'cp fhem2speech.sh /usr/local/bin' + and make it executable: + 'chmod 775 /usr/local/bin/fhem2speech.sh' + +Usage: + Edit your FHEM configuration file and add a line like this: + define speechBattery notify .*warnings.*Battery.*low.* "/usr/local/bin/fhem2speech.sh -s "Achtung, Batterie schwach: @"" + + At last restart FHEM or do a rereadcfg and listen to your speaker. + diff --git a/contrib/fhem2speech/fhem2speech.sh b/contrib/fhem2speech/fhem2speech.sh new file mode 100755 index 000000000..1a20c5e0b --- /dev/null +++ b/contrib/fhem2speech/fhem2speech.sh @@ -0,0 +1,12 @@ +#!/bin/bash +if [ $# = 0 ]; then + echo "Usage: `basename $0` -f [filename]" + echo " `basename $0` -s \"Text\"" + exit 1; +elif [ $1 = -f ]; then + /usr/share/txt2pho/txt2pho -i $2 -f | /usr/bin/mbrola /usr/share/mbrola/de7/de7 - - \ + | /usr/bin/bplay -s 22050 -b 16 -q +elif [ $1 = -s ]; then + echo $2 | /usr/share/txt2pho/txt2pho -f | /usr/bin/mbrola /usr/share/mbrola/de7/de7 - - \ + | /usr/bin/bplay -s 22050 -b 16 -q +fi diff --git a/contrib/rotateShiftWork/README.rotateShiftWork b/contrib/rotateShiftWork/README.rotateShiftWork new file mode 100644 index 000000000..1074d391f --- /dev/null +++ b/contrib/rotateShiftWork/README.rotateShiftWork @@ -0,0 +1,24 @@ +rotateShiftWork.sh - Copyright (c)2008 Martin Fischer + +Description: + The script rotateShiftWork.sh rotates a defined heating plan for + one or more FHT devices to odd or even weeks. + +Installation: + Copy the script rotateShiftWork.sh to a directory of your choice, + e.g.: + 'cp rotateShiftWork.sh /usr/local/bin' + and make it executable: + 'chmod 775 /usr/local/bin/rotateShiftWork.sh' + + Edit the file rotateShiftWork.sh to your personal preferences. + + Edit your FHEM configuration file and add a line like this: + define at *00:15:00 "/rotateShiftWork.sh " + + where + is a name of your choice, e.g.: timerEGwzHeizung + is /usr/local/bin in this example + one ore more FHT device(s) e.g.: EGwzHeizung + + At last restart FHEM or do a rereadcfg. diff --git a/contrib/rotateShiftWork/rotateShiftWork.sh b/contrib/rotateShiftWork/rotateShiftWork.sh new file mode 100755 index 000000000..68cfcbe2a --- /dev/null +++ b/contrib/rotateShiftWork/rotateShiftWork.sh @@ -0,0 +1,102 @@ +#!/bin/bash +################################################################ +# +# Copyright notice +# +# (c) 2008 Copyright: Martin Fischer (m_fischer at gmx dot de) +# All rights reserved +# +# This script 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 +# (at your option) 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. +# +################################################################ +# +# For a proper work it is necessary to set retrycount >4, +# e.g. "attr FHT_device retrycount 7" +# +# Write the following line to your config to automatically change the weekplan, e.g.: +# define timerEGwzHeizung at *00:15:00 "/rotateShiftWork.sh EGwzHeizung" + +# define work days +WORK="mon tue wed thu fri" +# define recreation days +FREE="sat sun" +# define range for odd weeks, e.g. "FrĂĽhschicht", +# (from1 to1 from2 to2) +odd=(12:30 22:30 24:00 24:00) +# define range for even weeks, e.g. "Spätschicht", +# (from1 to1 from2 to2) +even=(08:30 11:30 16:30 22:30) +# define range for recreation, e.g. "Wochenende", +# (from1 to1 from2 to2) +free=(08:30 23:50 24:00 24:00) +# define fhem.pl host:port +FHEM_BIN="/usr/local/bin/fhem.pl localhost:7072" +# define file for rotation +WEEKFILE="/var/fhem/week.save" + +########################################################### +# +# do not change +# + +[[ $# -lt 1 ]] && { echo "usage: $0 FHT_device [FHT_device] [FHT_device]"; exit 1; } || FHT_SET="$*" + +# calculate week +let WEEK="`date +%V`%2" + +# check week +[[ -f ${WEEKFILE} ]] && { + . ${WEEKFILE} + [[ ${WEEK} = ${LAST} ]] && exit 0 +} + +# write current week to file +echo "LAST=${WEEK}" > ${WEEKFILE} + +# set "FrĂĽhschicht" or "Spätschicht" +[[ ${WEEK} -eq 0 ]] && week=(${even[*]}) || week=(${odd[*]}) + +# declare range +span=(from1 to1 from2 to2) + +# set work days +for ((i=0; i<${#span[@]};i++)); do + for DAY in ${WORK}; do + VALUE="${VALUE}${DAY}-${span[$i]} ${week[$i]} " + done + for FHT in ${FHT_SET}; do + ${FHEM_BIN} "set ${FHT} ${VALUE}" + done + unset VALUE +done + +# set recreation days +for ((i=0; i<${#span[@]};i++)); do + for DAY in ${FREE}; do + VALUE="${VALUE}${DAY}-${span[$i]} ${free[$i]} " + done + for FHT in ${FHT_SET}; do + ${FHEM_BIN} "set ${FHT} ${VALUE}" + done + unset VALUE +done + +# refreshvalues +for FHT in ${FHT_SET}; do + ${FHEM_BIN} "set ${FHT} report1 255 report2 255" +done + +exit 0