mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-01-31 12:49:34 +00:00
Axels Pachube module
git-svn-id: https://svn.fhem.de/fhem/trunk@434 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
79c58e6b64
commit
345636d18c
@ -526,3 +526,4 @@
|
|||||||
- feature: suppress inplausible readings from USF1000
|
- feature: suppress inplausible readings from USF1000
|
||||||
- bugfix: FHZ_ReadAnswer bugfix for Windows (Klaus, 20.8.2009)
|
- bugfix: FHZ_ReadAnswer bugfix for Windows (Klaus, 20.8.2009)
|
||||||
- feature: CUL: device acces code reorganized, TCP/IP support added
|
- feature: CUL: device acces code reorganized, TCP/IP support added
|
||||||
|
- feature: Pachube module from Axel in contrib
|
||||||
|
265
fhem/contrib/95_PachLog.pm
Normal file
265
fhem/contrib/95_PachLog.pm
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
#######################################################################
|
||||||
|
#
|
||||||
|
# 95_PachLog.pm
|
||||||
|
#
|
||||||
|
# Logging to www.pachube.com
|
||||||
|
# Autor: a[PUNKT]r[BEI]oo2p[PUNKT]net
|
||||||
|
# Stand: 09.09.2009
|
||||||
|
# Version: 0.9
|
||||||
|
#######################################################################
|
||||||
|
# Vorausetzung: Account bei www.pachube.com mit API-Key
|
||||||
|
#######################################################################
|
||||||
|
#
|
||||||
|
# FHEM: Neues Pachube-Device erstelle: define <NAME> PachLog API-Key
|
||||||
|
# "define PACH001 PachLog 1234kliceee77hgtzuippkk99"
|
||||||
|
#
|
||||||
|
# PACHUBE: FEED erstellen -> FEED-NR: DATASTREAM-ID:TAGS
|
||||||
|
# Beispiel: HMS_TF (Temperatur und Feuchte Sensor)
|
||||||
|
# FEED-NR: 1234
|
||||||
|
# ID 0 => Temperatur (temperature)
|
||||||
|
# ID 1 => rel. Luftfeuchte (humidity)
|
||||||
|
#
|
||||||
|
# FHEM: PachLog-Devices: PACH01
|
||||||
|
# HMS_DEVICE: HMS_TF01
|
||||||
|
# FEED-NR: 1234
|
||||||
|
# ID 0 => Temperatur (temperature)
|
||||||
|
# ID 1 => rel. Luftfeuchte (humidity)
|
||||||
|
# "set PACH01 ADD HMS_TF01 1234:0:temperature:1:humidity"
|
||||||
|
#
|
||||||
|
# Hinweise:
|
||||||
|
# Ein FEED kann nur komplett upgedated werden:
|
||||||
|
# FEED 3456 -> ID 0 -> DEVICE A
|
||||||
|
# FEED 3456 -> ID 1 -> DEVICE B
|
||||||
|
# => geht nicht
|
||||||
|
#
|
||||||
|
# Es werden nur READINGS mit einfach Werten und Zahlen unterstützt.
|
||||||
|
# Beispiele: NICHT unterstütze READINGS
|
||||||
|
# cum_month => CUM_MONTH: 37.173 CUM: 108.090 COST: 0.00
|
||||||
|
# cum_day => 2009-09-09 00:03:19 T: 1511725.6 H: 4409616 W: 609.4 R: 150.4
|
||||||
|
# israining no => (yes/no)
|
||||||
|
#######################################################################
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
package main;
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use POSIX;
|
||||||
|
use Data::Dumper;
|
||||||
|
use LWP;
|
||||||
|
use LWP::UserAgent;
|
||||||
|
use HTTP::Request::Common;
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
sub
|
||||||
|
PachLog_Initialize($)
|
||||||
|
{
|
||||||
|
my ($hash) = @_;
|
||||||
|
|
||||||
|
$hash->{DefFn} = "PachLog_Define";
|
||||||
|
$hash->{SetFn} = "PachLog_Set";
|
||||||
|
$hash->{GetFn} = "PachLog_Get";
|
||||||
|
$hash->{NotifyFn} = "PachLog_Notify";
|
||||||
|
}
|
||||||
|
#######################################################################
|
||||||
|
sub PachLog_Define($@)
|
||||||
|
{
|
||||||
|
# define <NAME> PachLog Pachube-X-API-Key
|
||||||
|
my ($hash, @a) = @_;
|
||||||
|
# X-API-Key steht im DEF %defs{<NAME>}{DEF}
|
||||||
|
# Alternativ nach $defs{<NAME>}{XAPIKEY}
|
||||||
|
my($package, $filename, $line, $subroutine) = caller(3);
|
||||||
|
Log 0 , "PachLog_Define => $package: $filename LINE: $line SUB: $subroutine \n";
|
||||||
|
Log 5, Dumper(@_) . "\n";
|
||||||
|
return "Unknown argument count " . int(@a) . " , usage set <name> dataset value or set <name> delete dataset" if(int(@a) != 1);
|
||||||
|
return undef;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#######################################################################
|
||||||
|
sub PachLog_Set($@)
|
||||||
|
{
|
||||||
|
# set <NAME> ADD/DEL <DEVICENAME> FEED:STREAM:VALUE:STREAM:VALUE&FEED-2:STEAM,VALUE
|
||||||
|
my ($hash, @a) = @_ ;
|
||||||
|
# FHEMWEB Frage....Auswahliste
|
||||||
|
return "Unknown argument $a[1], choose one of ". join(" ",sort keys %{$hash->{READINGS}}) if($a[1] eq "?");
|
||||||
|
# Pruefen Uebergabeparameter
|
||||||
|
# @a => a[0]:<NAME>; a[1]=ADD oder DEL; a[2]= DeviceName;
|
||||||
|
# a[3]=FEED:STREAM:VALUE:STREAM:VALUE&FEED-2:STREAM,VALUE
|
||||||
|
# READINGS setzten oder löschen
|
||||||
|
if($a[1] eq "DEL")
|
||||||
|
{
|
||||||
|
GetLogLevel($a[0],2),"PACHLOG -> DELETE: A0= ". $a[0] . " A1= " . $a[1] . " A2=" . $a[2];
|
||||||
|
if(defined($hash->{READINGS}{$a[2]}))
|
||||||
|
{
|
||||||
|
delete($hash->{READINGS}{$a[2]})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if($a[1] eq "ADD")
|
||||||
|
{
|
||||||
|
if(!defined($defs{$a[2]})) {return "PACHLOG[". $a[2] . "] => Unkown Device";}
|
||||||
|
# Mindestens 3 Parameter
|
||||||
|
my @b = split(/:/, $a[3]);
|
||||||
|
return "PACHLOG[". $a[2] . "] => Argumenete: " . $a[3] . " nicht eindeutig => mind. 3 => FEED-NR:DATASTREAM:READING" if(int(@b) < 3);
|
||||||
|
my $feednr = shift(@b);
|
||||||
|
#FEED-Nr darf nur Zahlen enthalten
|
||||||
|
if($feednr !~ /^\d+$/) {return "PACHLOG[". $a[2] . "] => FEED-Nr >" . $feednr . "< ist ungueltig";}
|
||||||
|
# ??? Pruefen ob READING vorhanden ???
|
||||||
|
my ($i,$j);
|
||||||
|
for ($i=0;$i<@b;$i++)
|
||||||
|
{
|
||||||
|
#Stream nur Zahlen
|
||||||
|
if($b[$i] !~ /^\d+$/) {return "PACHLOG => FEED-Nr[" . $feednr ."] Stream-ID >" . $b[$i] . "< ungueltig";}
|
||||||
|
# Reading existiert
|
||||||
|
$j = $i + 1;
|
||||||
|
if(!defined($defs{$a[2]}{READINGS}{$b[$j]})) {return "PACHLOG[". $a[2] . "] => Unkown READING >" . $b[$j] . "<";}
|
||||||
|
# READING-Value validieren
|
||||||
|
my $r = $defs{$a[2]}{READINGS}{$b[$j]}{VAL};
|
||||||
|
my $rn = &ReadingToNumber($r);
|
||||||
|
if(!defined($rn)) {return "PACHLOG[". $a[$i] . "] => READING not supported >" . $b[$j] . "<";}
|
||||||
|
$i = $j;
|
||||||
|
}
|
||||||
|
$hash->{READINGS}{$a[2]}{TIME} = TimeNow();
|
||||||
|
$hash->{READINGS}{$a[2]}{VAL} = $a[3];
|
||||||
|
}
|
||||||
|
$hash->{CHANGED}[0] = $a[1];
|
||||||
|
$hash->{STATE} = $a[1];
|
||||||
|
return undef;
|
||||||
|
return "Unknown argument count " . int(@a) . " , usage set <name> ADD/DEL <DEVICE-NAME> FEED:STREAM:VALUE:STREAM:VALUE&FEED-2:STREAM,VALUE" if(int(@a) != 4);
|
||||||
|
|
||||||
|
}
|
||||||
|
#######################################################################
|
||||||
|
sub PachLog_Get()
|
||||||
|
{
|
||||||
|
# OHNE FUNKTION ....
|
||||||
|
my ($name, $x_key) = @_;
|
||||||
|
my($package, $filename, $line, $subroutine) = caller(3);
|
||||||
|
Log 5, "PachLog_Get => $package: $filename LINE: $line SUB: $subroutine \n";
|
||||||
|
Log 5, Dumper(@_) . "\n";
|
||||||
|
}
|
||||||
|
#######################################################################
|
||||||
|
sub PachLog_Notify ($$)
|
||||||
|
{
|
||||||
|
my ($me, $trigger) = @_;
|
||||||
|
my $d = $me->{NAME};
|
||||||
|
my $t = $trigger->{NAME};
|
||||||
|
# Eintrag fuer Trigger-Device vorhanden
|
||||||
|
if(!defined($defs{$d}{READINGS}{$t}))
|
||||||
|
{
|
||||||
|
Log 5, ("PACHLOG[INFO] => " . $t . " => Nicht definiert");
|
||||||
|
return undef;}
|
||||||
|
|
||||||
|
# Umwandeln 1234:0:temperature:1:humidity => %feed
|
||||||
|
# Struktur:
|
||||||
|
# %feed{FEED-NR}{READING}{VAL}
|
||||||
|
# %feed{FEED-NR}{READING}{DATASTREAM}
|
||||||
|
my ($dat,@a,$feednr,$i,$j);
|
||||||
|
my %feed = ();
|
||||||
|
$dat = $defs{$d}{READINGS}{$t}{VAL};
|
||||||
|
@a = split(/:/, $dat);
|
||||||
|
$feednr = shift(@a);
|
||||||
|
for ($i=0;$i<@a;$i++)
|
||||||
|
{
|
||||||
|
$j = $i + 1;
|
||||||
|
$feed{$feednr}{$a[$j]}{STREAM} = $a[$i];
|
||||||
|
$i = $j;
|
||||||
|
}
|
||||||
|
# Werte aus Trigger-Device
|
||||||
|
foreach my $r (keys %{$feed{$feednr}})
|
||||||
|
{
|
||||||
|
$i = $defs{$t}{READINGS}{$r}{VAL};
|
||||||
|
# Werte Normalisieren
|
||||||
|
# Einheit -> 21,1 (celsius) -> 21,1
|
||||||
|
# FS20: VAL = on => 1 && VAL = off => 0
|
||||||
|
# @a = split(' ', $i);
|
||||||
|
# $feed{$feednr}{$r}{VAL} = &ReadingToNumber($a[0]) ;
|
||||||
|
$feed{$feednr}{$r}{VAL} = &ReadingToNumber($i) ;
|
||||||
|
|
||||||
|
}
|
||||||
|
Log 5, "PACHLOG => dumper(FEED) => " .Dumper(%feed);
|
||||||
|
|
||||||
|
# CVS-Data
|
||||||
|
# my @cvs = ();
|
||||||
|
# foreach my $r (keys %{$feed{$feednr}})
|
||||||
|
# {
|
||||||
|
# $cvs[$feed{$feednr}{$r}{STREAM}] = $feed{$feednr}{$r}{VAL};
|
||||||
|
# }
|
||||||
|
# my $cvs_data = join(',',@cvs);
|
||||||
|
# Log 5, "PACHLOG[CVSDATA] => $cvs_data";
|
||||||
|
|
||||||
|
# Aufbereiten %feed als EEML-Data
|
||||||
|
my $eeml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
|
||||||
|
$eeml .= "<eeml xmlns=\"http://www.eeml.org/xsd/005\">\n";
|
||||||
|
$eeml .= "<environment>\n";
|
||||||
|
foreach my $r (keys %{$feed{$feednr}})
|
||||||
|
{
|
||||||
|
$eeml .= "<data id=\"" . $feed{$feednr}{$r}{STREAM} . "\">\n";
|
||||||
|
$eeml .= "<value>" . $feed{$feednr}{$r}{VAL} . "</value>\n";
|
||||||
|
# Unit fuer EEML: <unit symbol="C" type="derivedSI">Celsius</unit>
|
||||||
|
my ($u_name,$u_symbol,$u_type,$u_tag) = split(',',&PachLog_ReadingToUnit($r));
|
||||||
|
if(defined($u_name)) {
|
||||||
|
$eeml .= "<tag>". $u_tag . "</tag>\n";
|
||||||
|
$eeml .= "<unit symbol=\"" . $u_symbol. "\" type=\"" . $u_type. "\">" . $u_name . "<\/unit>\n";
|
||||||
|
}
|
||||||
|
$eeml .= "</data>\n";
|
||||||
|
}
|
||||||
|
$eeml .= "</environment>\n";
|
||||||
|
$eeml .= "</eeml>\n";
|
||||||
|
Log 5, "PACHLOG -> " . $t . " EEML => " . $eeml;
|
||||||
|
# Pachube-Update per EEML -> XML
|
||||||
|
my ($res,$ret,$ua,$apiKey,$url);
|
||||||
|
$apiKey = $defs{$d}{DEF};
|
||||||
|
$url = "http://www.pachube.com/api/feeds/" . $feednr . ".xml";
|
||||||
|
$ua = new LWP::UserAgent;
|
||||||
|
$ua->default_header('X-PachubeApiKey' => $apiKey);
|
||||||
|
$res = $ua->request(PUT $url,'Content' => $eeml);
|
||||||
|
# Ueberpruefen wir, ob alles okay war:
|
||||||
|
if ($res->is_success())
|
||||||
|
{
|
||||||
|
Log 0,("PACHLOG => Update[" . $t ."] => SUCCESS\n");
|
||||||
|
# Time setzten
|
||||||
|
$defs{$d}{READINGS}{$t}{TIME} = TimeNow();
|
||||||
|
}
|
||||||
|
else {Log 0,("PACHLOG => Update[" . $t ."] ERROR: " . ($res->as_string) . "\n");}
|
||||||
|
}
|
||||||
|
sub PachLog_ReadingToUnit($)
|
||||||
|
{
|
||||||
|
# Unit fuer EEML: <unit symbol="C" type="derivedSI">Celsius</unit>
|
||||||
|
# Input: READING z.B. temperature
|
||||||
|
# Output: Name,symbol,Type,Tag z.B. Celsius,C,derivedSI
|
||||||
|
# weiters => www.eeml.org
|
||||||
|
# No Match = undef
|
||||||
|
my $in = shift;
|
||||||
|
my %unit = ();
|
||||||
|
%unit = (
|
||||||
|
'temperature' => "Celsius,C,derivedSI,Temperature",
|
||||||
|
'current' => "Power,kW,derivedSI,EnergyConsumption",
|
||||||
|
'humidity' => "Humidity,rel%,contextDependentUnits,Humidity",
|
||||||
|
'rain' => "Rain,l/m2,contextDependentUnits,Rain",
|
||||||
|
'wind' => "Wind,m/s,contextDependentUnits,Wind",
|
||||||
|
);
|
||||||
|
if(defined($unit{$in})) {return $unit{$in};}
|
||||||
|
else {return undef;}
|
||||||
|
}
|
||||||
|
sub ReadingToNumber($)
|
||||||
|
{
|
||||||
|
# Input: reading z.B. 21.1 (Celsius) oder dim10%, on-for-oldtimer etc.
|
||||||
|
# Output: 21.1 oder 10
|
||||||
|
# ERROR = undef
|
||||||
|
# Alles außer Nummern loeschen $t =~ s/[^0123456789.]//g;
|
||||||
|
my $in = shift;
|
||||||
|
Log 5, "PACHLOG[ReadingToNumber] => in => $in";
|
||||||
|
# Bekannte READINGS FS20 Devices oder FHT
|
||||||
|
if($in =~ /^on|Switch.*on/i) {$in = 1;}
|
||||||
|
if($in =~ /^off|Switch.*off|lime-protection/i) {$in = 0;}
|
||||||
|
# Keine Zahl vorhanden
|
||||||
|
if($in !~ /\d{1}/) {return undef;}
|
||||||
|
# Mehrfachwerte in READING z.B. CUM_DAY: 5.040 CUM: 334.420 COST: 0.00
|
||||||
|
my @b = split(' ', $in);
|
||||||
|
if(int(@b) gt 2) {return undef;}
|
||||||
|
# Nurnoch Zahlen z.B. dim10% = 10 oder 21.1 (Celsius) = 21.1
|
||||||
|
$in =~ s/[^0123456789.]//g;
|
||||||
|
Log 5, "PACHLOG[ReadingToNumber] => out => $in";
|
||||||
|
return $in
|
||||||
|
}
|
||||||
|
1;
|
55
fhem/contrib/99_dumpdef.pm
Normal file
55
fhem/contrib/99_dumpdef.pm
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
##############################################
|
||||||
|
# VarDump for FHEM-Devices
|
||||||
|
##############################################
|
||||||
|
# Installation
|
||||||
|
# 99_dumpdef.pm ins FHEM-Verzeichis kopieren
|
||||||
|
# dann: "reload 99_dumpdef.pm"
|
||||||
|
##############################################
|
||||||
|
# Aufruf: dumpdef "DEVICE-NAME"
|
||||||
|
##############################################
|
||||||
|
# Aufruf: dumpdef <XXX>
|
||||||
|
# <MOD> = %modules
|
||||||
|
# <SEL> = %selectlist
|
||||||
|
# <VAL> = %value
|
||||||
|
# <CMD> = %cmds
|
||||||
|
# <DAT> = %data
|
||||||
|
##############################################
|
||||||
|
package main;
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use POSIX;
|
||||||
|
use Data::Dumper;
|
||||||
|
sub Commanddumpdef($);
|
||||||
|
|
||||||
|
#####################################
|
||||||
|
sub
|
||||||
|
dumpdef_Initialize($)
|
||||||
|
{
|
||||||
|
my %lhash = ( Fn=>"Commanddumpdef",
|
||||||
|
Hlp=>"Dump <devspec> to FHEMWEB & LOG" );
|
||||||
|
$cmds{dumpdef} = \%lhash;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#####################################
|
||||||
|
sub Commanddumpdef($)
|
||||||
|
{
|
||||||
|
my ($cl, $d) = @_;
|
||||||
|
# $d = $a[1];
|
||||||
|
return "Usage: dumpdef <DeviceName>" if(!$d);
|
||||||
|
my($package, $filename, $line, $subroutine) = caller(3);
|
||||||
|
my $r = "CALLER => $package: $filename LINE: $line SUB: $subroutine \n";
|
||||||
|
$r .= "<h1>SUB-NAME: " .(caller(0))[3] . "</h1>\n";
|
||||||
|
if($d eq "CMD") {$r .= Dumper(%cmds) . "\n"; return $r; }
|
||||||
|
if($d eq "DAT") {$r .= Dumper(%data) . "\n"; return $r; }
|
||||||
|
if($d eq "MOD") {$r .= Dumper(%modules) . "\n"; return $r; }
|
||||||
|
if($d eq "SEL") {$r .= Dumper(%selectlist) . "\n"; return $r; }
|
||||||
|
if(!defined($defs{$d})) {
|
||||||
|
return "Unkown Device";}
|
||||||
|
$r .= "DUMP-DEVICE: $d \n";
|
||||||
|
$r .= Dumper($defs{$d}) . "\n";
|
||||||
|
$r .= "DUMP-DEVICE-ATTR \n";
|
||||||
|
$r .= Dumper($attr{$d}) . "\n";
|
||||||
|
return $r;
|
||||||
|
}
|
||||||
|
1;
|
@ -6,6 +6,10 @@
|
|||||||
- 91_DbLog.pm
|
- 91_DbLog.pm
|
||||||
Example to log data in a (DBI supported) database (MySQL, Oracle, etc)
|
Example to log data in a (DBI supported) database (MySQL, Oracle, etc)
|
||||||
see dblog for a full-featured database log
|
see dblog for a full-featured database log
|
||||||
|
- 95_PachLog.pm
|
||||||
|
Pachube module from Axel
|
||||||
|
- 99_dumpdef.pm
|
||||||
|
Debugging helpers from Axel
|
||||||
- 99_ALARM.pm
|
- 99_ALARM.pm
|
||||||
Example for a Low Budget ALARM System by Martin
|
Example for a Low Budget ALARM System by Martin
|
||||||
- 99_SUNRISE.pm
|
- 99_SUNRISE.pm
|
||||||
@ -46,3 +50,4 @@
|
|||||||
Peter's RRD support. See the HOWTO
|
Peter's RRD support. See the HOWTO
|
||||||
- serial.pm
|
- serial.pm
|
||||||
Serial line analyzer
|
Serial line analyzer
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user