|
From: <jum...@us...> - 2013-03-09 12:09:15
|
Revision: 1559
http://openautomation.svn.sourceforge.net/openautomation/?rev=1559&view=rev
Author: jumi2006
Date: 2013-03-09 12:09:04 +0000 (Sat, 09 Mar 2013)
Log Message:
-----------
moved knxd from ebus directory to own knxd directory
Added Paths:
-----------
tools/knxd/
tools/knxd/etc/knxd/doc/
tools/knxd/etc/knxd/doc/ChangeLog
tools/knxd/etc/knxd/eBus_plugin.conf
tools/knxd/etc/knxd/knxd-ebus.csv
tools/knxd/etc/knxd/plugin/eBusd.pl
tools/knxd/etc/logrotate.d/
tools/knxd/usr/sbin/knxd.pl
Removed Paths:
-------------
tools/knxd/etc/knxd/doc/ChangeLog
tools/knxd/etc/knxd/eBus_plugin.conf
tools/knxd/etc/knxd/plugin/eBusd.pl
tools/knxd/usr/sbin/knxd.pl
Deleted: tools/knxd/etc/knxd/doc/ChangeLog
===================================================================
--- tools/ebus/knxd/etc/knxd/doc/ChangeLog 2013-02-18 19:39:15 UTC (rev 1505)
+++ tools/knxd/etc/knxd/doc/ChangeLog 2013-03-09 12:09:04 UTC (rev 1559)
@@ -1,10 +0,0 @@
-Perl - KNX Daemon (knxd) - ChangeLog
-===============================
-2013-02-17:
-* Changed telnet/ebusd-handling from IO::Socket:INET to Net::Telnet to prevent memleaks
-* added CYC (cyclic) support, usage: "cyc xxx xxx"
-* added sample knxd.csv ("knxd-ebus.csv")
-* added log rotate settings /etc/logrotate.d/
-
-2013-02-17:
-* Initial release
Copied: tools/knxd/etc/knxd/doc/ChangeLog (from rev 1507, tools/ebus/knxd/etc/knxd/doc/ChangeLog)
===================================================================
--- tools/knxd/etc/knxd/doc/ChangeLog (rev 0)
+++ tools/knxd/etc/knxd/doc/ChangeLog 2013-03-09 12:09:04 UTC (rev 1559)
@@ -0,0 +1,14 @@
+Perl - KNX Daemon (knxd) - ChangeLog
+===============================
+2013-02-19:
+* bugfix: highload while eib=0 fixed
+* try to minimize memleaks in knxd and plugin
+
+2013-02-17:
+* Changed telnet/ebusd-handling from IO::Socket:INET to Net::Telnet to prevent memleaks
+* added CYC (cyclic) support, usage: "cyc xxx xxx"
+* added sample knxd.csv ("knxd-ebus.csv")
+* added log rotate settings /etc/logrotate.d/
+
+2013-02-17:
+* Initial release
Deleted: tools/knxd/etc/knxd/eBus_plugin.conf
===================================================================
--- tools/ebus/knxd/etc/knxd/eBus_plugin.conf 2013-02-17 22:50:49 UTC (rev 1500)
+++ tools/knxd/etc/knxd/eBus_plugin.conf 2013-03-09 12:09:04 UTC (rev 1559)
@@ -1,7 +0,0 @@
-#### Einstellungen
-$config = "/tmp/testcfg.csv";
-$ip = '192.168.2.221'; #IP des ebusd
-$port = '8888'; #Port des ebusd
-$base_time = 120; #Abrufzyklus
-$debug = "";
-#### Ende Einstellungen
\ No newline at end of file
Copied: tools/knxd/etc/knxd/eBus_plugin.conf (from rev 1505, tools/ebus/knxd/etc/knxd/eBus_plugin.conf)
===================================================================
--- tools/knxd/etc/knxd/eBus_plugin.conf (rev 0)
+++ tools/knxd/etc/knxd/eBus_plugin.conf 2013-03-09 12:09:04 UTC (rev 1559)
@@ -0,0 +1,7 @@
+#### Einstellungen
+$config = "/etc/knxd/testcfg.csv";
+$ip = '192.168.2.221'; #IP des ebusd
+$port = '8888'; #Port des ebusd
+$base_time = 120; #Abrufzyklus
+$debug = "";
+#### Ende Einstellungen
\ No newline at end of file
Copied: tools/knxd/etc/knxd/knxd-ebus.csv (from rev 1505, tools/ebus/knxd/etc/knxd/knxd-ebus.csv)
===================================================================
--- tools/knxd/etc/knxd/knxd-ebus.csv (rev 0)
+++ tools/knxd/etc/knxd/knxd-ebus.csv 2013-03-09 12:09:04 UTC (rev 1559)
@@ -0,0 +1,15 @@
+#GA;DPT;RRD_TYPE;RRD_STEP;TYPE;CMD;COMMENT
+0/5/120;1;;;set;hw mode;WW/ Betriebsmodus
+0/5/121;9;;;set;hw temp;WW/ Solltemperatur
+0/5/111;1;;;set;short cir2_party;Quick/ Party-Modus
+0/5/110;1;;;set;short cir2_mode;Quick/ Heizkreis Betriebsmodus
+0/5/123;1;;;set;short hw_load;Quick - WW Speicherladung
+0/5/202;9;g;;get;ci cir2_set_temp;Heizkreis2-Solltemperatur
+0/5/203;12;c;24;get;ci yield_transfer;Mitternacht \x86bertragswert Energieertrag
+0/5/206;12;c;0.5;get;mv yield_sum;Energieertrag
+0/5/204;9;g;;get;mv brine_in temp;Quellentemperatur
+0/5/205;9;g;;get;mv brine_out temp;Austrittstemperatur
+0/5/201;9;g;;get;mv VF2_temp temp;Vorlauftemperatur VF2
+0/5/200;9;g;;get;mv at_temp temp;Aussentempertur
+0/5/102;9;g;;get;cir2 rt_day;Heizkreis \xD0 Raumsolltemperatur
+0/5/101;9;g;;set;cir2 rt_day;Heizkreis \xD0 Raumsolltemperatur
\ No newline at end of file
Deleted: tools/knxd/etc/knxd/plugin/eBusd.pl
===================================================================
--- tools/ebus/knxd/etc/knxd/plugin/eBusd.pl 2013-02-17 22:50:49 UTC (rev 1500)
+++ tools/knxd/etc/knxd/plugin/eBusd.pl 2013-03-09 12:09:04 UTC (rev 1559)
@@ -1,183 +0,0 @@
-#return;
-use warnings;
-use strict;
-use IO::Socket;
-
-### READ PLUGIN-CONF
-my ($config,$ip,$port,$base_time,$debug);
-&readConf;
-
-$plugin_info{$plugname.'_cycle'} = 60;
-$plugin_info{$plugname.'_number'} = 0 unless (defined $plugin_info{$plugname.'_number'});
-my (@gets,@sets,@cycs);
-
-### READ CONFIG
-my $id = 0;
-open (CFG,'<',$config) || die $!;
-while (<CFG>){
-if ($_ =~ /\#/){
-#if ($debug){plugin_log($plugname,"skipped line");}
-}
-else
-{
-chomp $_;
-#if ($debug){plugin_log($plugname,"line $_");}
-my @array = split (/;/,$_);
-my ($ga,$dpt,$rrd_type,$rrd_step,$type,$short,$comment) = @array;
-
-#possible this prevents a memleak
-@array = ();
-undef @array;
-#maybe !?
-
-###define @gets###
-if ($type eq "get" && ($ga or $rrd_type)){
- $id++;
- push @gets,{ga => $ga, dpt => $dpt, rrd_type => $rrd_type, rrd_step => $rrd_step, type => $type, short => $short, comment => $comment, id => $id};
-}
-###define @sets###
-if ($type eq "set" && $ga){
- push @sets,{ga => $ga, dpt => $dpt, rrd_type => $rrd_type, rrd_step => $rrd_step, type => $type, short => $short, comment => $comment, id => $id};
-}
-###define @cycs###
-if ($type eq "cyc" && ($ga or $rrd_type)){
- push @cycs,{ga => $ga, dpt => $dpt, rrd_type => $rrd_type, rrd_step => $rrd_step, type => $type, short => $short, comment => $comment, id => $id};
-}
-}
-}
-close CFG;
-
-### CREATE DYNAMIC PLUGIN-CYCLE
-$plugin_info{$plugname.'_cycle'} = $base_time/(@gets+1);
-my $commands = @gets;
-if ($debug){plugin_log($plugname,"Anzahl GET: $commands");}
-
-
-### OPEN SOCKET
-my $sock = new IO::Socket::INET (
-PeerAddr => $ip,
-PeerPort => $port,
-Proto => 'tcp');
-return "Error: $!" unless $sock;
-
-
-#### SET ###
-foreach my $set(@sets){
-$plugin_subscribe{$set->{ga}}{$plugname} = 1;
-if ($debug){plugin_log($plugname,"$set->{ga} subscribed \n")};
-}
-
-foreach my $set(@sets){
-if ($msg{'apci'} eq "A_GroupValue_Write" && $msg{'dst'} eq $set->{ga}){
- my $send_set = $set->{type}." ".$set->{short}." ".$msg{'value'}."\n" ;
- plugin_log($plugname,$send_set);
- print $sock ($send_set);
- my $answer = <$sock>;
- chomp $answer;
- $answer =~ s!\s!!g;
- plugin_log($plugname,"$set->{type} $set->{short} $msg{'value'} $answer");
-
- ### Check for Response
- foreach my $get (@gets){
- if ($get->{short} eq $set->{short}){
- print $sock ($get->{type}." ".$get->{short}."\n");
- my $answer = <$sock>;
- chomp $answer;
- $answer =~ s!\s!!g;
- plugin_log($plugname,"$get->{type} $get->{short} $answer");
- if ($answer =~ m/^[-+]?\d+(?:\.\d*)?(?:[eE][-+]?\d+(?:\.\d*)?)?$/ ) # check if $answer ist any number
- {knx_write($get->{ga},$answer,$get->{dpt});
- plugin_log($plugname,"$get->{ga} $answer $get->{dpt}");
- }
- #print $sock ("quit \n");
- #return;
- }}
- print $sock ("quit \n");
- #close $sock;
- return;
- }
-}
-
-####Response
-#
-#foreach my $get (@gets){
-#$plugin_subscribe{$get->{ga}}{$plugname} = 1;
-#if ($msg{'apci'} eq "A_GroupValue_Read" && $msg{'dst'} eq $get->{ga}){
-# plugin_log($plugname,"Response $msg{'apci'}");
-# my $get_send = $get->{type}." ".$get->{short}."\n";
-# print $sock ($get_send);
-# my $answer = <$sock>;
-# chomp $answer;
-# $answer =~ s!\s!!g;
-# plugin_log($plugname,"Response $get->{short} $answer");
-# if ($answer =~ m/^[-+]?\d+(?:\.\d*)?(?:[eE][-+]?\d+(?:\.\d*)?)?$/ ) # check if $answer ist any number
-# {knx_write($get->{ga},$answer,$get->{dpt},0x40)}
-# print $sock ("quit \n");
-#}
-#}
-
-#### GET ###
-$plugin_info{$plugname.'_number'}++; #increase number to read next
-
-
-foreach my $get (@gets){
-if ($plugin_info{$plugname.'_number'} > $commands) {$plugin_info{$plugname.'_number'} = 1}
-if ($get->{id} == $plugin_info{$plugname.'_number'}){
- if ($debug){plugin_log($plugname,"ID: $get->{id}");}
- if ($debug){plugin_log($plugname,"$get->{short}")};
- my $get_send = $get->{type}." ".$get->{short}."\n";
- print $sock ($get_send);
- my $answer = <$sock>;
- chomp $answer;
- $answer =~ s!\s!!g;
- plugin_log($plugname,"$get->{type} $get->{short} $answer");
- if ($answer =~ m/^[-+]?\d+(?:\.\d*)?(?:[eE][-+]?\d+(?:\.\d*)?)?$/ ) # check if $answer ist any number
- ###SEND KNX###
- {knx_write($get->{ga},$answer,$get->{dpt})}
-
- ###FILL/CREATE RRD###
- if ($get->{rrd_type} eq "c"){ #matches COUNTER
- $get->{short} =~ s/ /_/g; #replace spaces
- update_rrd ("eBus_".$get->{short},"",$answer,"COUNTER",$get->{rrd_step})
- }
- if ($get->{rrd_type} eq "g"){ #matches GAUGE
- $get->{short} =~ s/ /_/g; #replace spaces
- update_rrd ("eBus_".$get->{short},"",$answer)
- }
-
- print $sock ("quit \n");
- #close $sock;
-}
-}
-
-@sets = ();
-@gets = ();
-$sock = ();
-
-undef @gets;
-undef @sets;
-undef $sock;
-
-
-return "MBi ".$plugin_info{$plugname.'_meminc'};
-
-### READ CONF ###
-sub readConf
-{
- my $confFile = '/etc/knxd/eBus_plugin.conf';
- if (! -f $confFile) {
- plugin_log($plugname, "no conf file [$confFile] found.");
- } else {
- #plugin_log($plugname, "reading conf file [$confFile].");
- open(CONF, $confFile);
- my @lines = <CONF>;
- close($confFile);
- my $result = eval("@lines");
- #($result) and plugin_log($plugname, "conf file [$confFile] returned result[$result]");
- if ($@) {
- plugin_log($plugname, "ERR: conf file [$confFile] returned:");
- my @parts = split(/\n/, $@);
- plugin_log($plugname, "--> $_") foreach (@parts);
- }
- }
-}
\ No newline at end of file
Copied: tools/knxd/etc/knxd/plugin/eBusd.pl (from rev 1507, tools/ebus/knxd/etc/knxd/plugin/eBusd.pl)
===================================================================
--- tools/knxd/etc/knxd/plugin/eBusd.pl (rev 0)
+++ tools/knxd/etc/knxd/plugin/eBusd.pl 2013-03-09 12:09:04 UTC (rev 1559)
@@ -0,0 +1,200 @@
+#return;
+use warnings;
+use strict;
+use Net::Telnet ();
+
+
+#use Devel::Leak;
+####TRY MEMORY
+#my $handle; # apparently this doesn't need to be anything at all
+#my $leaveCount = 0;
+#my $enterCount = Devel::Leak::NoteSV($handle);
+##print STDERR "ENTER: $enterCount SVs\n";
+#plugin_log($plugname,"ENTER: $enterCount SVs");
+#$leaveCount = Devel::Leak::CheckSV($handle);
+##print STDERR "\nLEAVE: $leaveCount SVs\n";
+#plugin_log($plugname,"LEAVE: $leaveCount SVs");
+
+
+
+
+### READ PLUGIN-CONF
+my ($config,$ip,$port,$base_time,$debug);
+&readConf;
+#$debug = 1;
+
+$plugin_info{$plugname.'_cycle'} = 60;
+$plugin_info{$plugname.'_number'} = 0 unless (defined $plugin_info{$plugname.'_number'});
+my (@gets,@sets,$answer);
+
+### READ CONFIG
+### FIXME! try to read config only once until changed
+### Where to save the arrays ? Maybe global in knxd?
+my $id = 0;
+open (CFG,'<',$config) || die $!;
+while (<CFG>){
+if ($_ =~ /\#/){
+#if ($debug){plugin_log($plugname,"skipped line");}
+}
+else
+{
+chomp $_;
+#if ($debug){plugin_log($plugname,"line $_");}
+my @array = split (/;/,$_);
+my ($ga,$dpt,$rrd_type,$rrd_step,$type,$short,$comment) = @array;
+
+#possible this prevents a memleak
+@array = ();
+undef @array;
+#maybe !?
+
+###define @gets### includes cyclic
+if ($type ne "set" && ($ga or $rrd_type)){
+ $id++;
+ push @gets,{ga => $ga, dpt => $dpt, rrd_type => $rrd_type, rrd_step => $rrd_step, type => $type, short => $short, comment => $comment, id => $id};
+}
+###define @sets###
+if ($type eq "set" && $ga){
+ push @sets,{ga => $ga, dpt => $dpt, rrd_type => $rrd_type, rrd_step => $rrd_step, type => $type, short => $short, comment => $comment, id => $id};
+}
+}
+}
+close CFG;
+
+### CREATE DYNAMIC PLUGIN-CYCLE
+$plugin_info{$plugname.'_cycle'} = $base_time/(@gets+1);
+my $commands = @gets;
+if ($debug){plugin_log($plugname,"Anzahl GET-Komandos: $commands");}
+
+#### SET ###
+foreach my $set(@sets){
+$plugin_subscribe{$set->{ga}}{$plugname} = 1;
+if ($debug){plugin_log($plugname,"$set->{ga} subscribed \n")};
+}
+
+foreach my $set(@sets){
+if ($msg{'apci'} eq "A_GroupValue_Write" && $msg{'dst'} eq $set->{ga} && defined $msg{'value'}){
+ my $send_set = $set->{type}." ".$set->{short}." ".$msg{'value'} ;
+ plugin_log($plugname,$send_set);
+ $answer = send_ebusd ($send_set);
+ chomp $answer;
+ $answer =~ s!\s!!g;
+ plugin_log($plugname,"$set->{type} $set->{short} $msg{'value'} $answer");
+
+ ### Check for Response
+ foreach my $get (@gets){
+ if ($get->{short} eq $set->{short}){
+ my $send_get = $get->{type}." ".$get->{short};
+ $answer = send_ebusd ($send_get);
+ $answer =~ s!\s!!g;
+ plugin_log($plugname,"$get->{type} $get->{short} $answer");
+ if ($answer =~ m/^[-+]?\d+(?:\.\d*)?(?:[eE][-+]?\d+(?:\.\d*)?)?$/ ) # check if $answer ist any number
+ {knx_write($get->{ga},$answer,$get->{dpt});
+ plugin_log($plugname,"$get->{ga} $answer $get->{dpt}");
+ }
+ last;
+ }}
+ last;
+ }
+}
+
+####Response
+####FIXME !
+#### No surprise ... ists to slow ... but working
+#foreach my $get (@gets){
+#$plugin_subscribe{$get->{ga}}{$plugname} = 1;
+#if ($msg{'apci'} eq "A_GroupValue_Read" && $msg{'dst'} eq $get->{ga}){
+# plugin_log($plugname,"Response $msg{'apci'}");
+# my $send_get = $get->{type}." ".$get->{short};
+# $answer = send_ebusd ($send_get);
+# chomp $answer;
+# $answer =~ s!\s!!g;
+# plugin_log($plugname,"Response $get->{short} $answer");
+# if ($answer =~ m/^[-+]?\d+(?:\.\d*)?(?:[eE][-+]?\d+(?:\.\d*)?)?$/ ) # check if $answer ist any number
+# {knx_write($get->{ga},$answer,$get->{dpt},0x40)}
+#}
+#}
+
+#### GET ###
+
+$plugin_info{$plugname.'_number'}++; #increase number to read next value
+
+foreach my $get (@gets){
+if ($plugin_info{$plugname.'_number'} > $commands) {$plugin_info{$plugname.'_number'} = 1}
+if ($get->{id} == $plugin_info{$plugname.'_number'}){
+ if ($debug){plugin_log($plugname,"ID: $get->{id}");}
+ if ($debug){plugin_log($plugname,"$get->{short}")};
+ my $send_get = $get->{type}." ".$get->{short};
+ $answer = send_ebusd ($send_get);
+ chomp $answer;
+ $answer =~ s!\s!!g;
+ plugin_log($plugname,"$get->{type} $get->{short} $answer");
+ if ($answer =~ m/^[-+]?\d+(?:\.\d*)?(?:[eE][-+]?\d+(?:\.\d*)?)?$/ ) # check if $answer ist any number
+ ###SEND KNX###
+ {knx_write($get->{ga},$answer,$get->{dpt})}
+
+ ###FILL/CREATE RRD###
+ if ($get->{rrd_type} eq "c"){ #matches COUNTER
+ $get->{short} =~ s/ /_/g; #replace spaces
+ update_rrd ("eBus_".$get->{short},"",$answer,"COUNTER",$get->{rrd_step})
+ }
+ if ($get->{rrd_type} eq "g"){ #matches GAUGE
+ $get->{short} =~ s/ /_/g; #replace spaces
+ update_rrd ("eBus_".$get->{short},"",$answer)
+ }
+last;
+}
+}
+
+sub send_ebusd{
+ my $cmd = shift;
+ my $t = new Net::Telnet (Timeout => 10,
+ port => $port,
+ Prompt => '/\n/');
+ $t->open($ip);
+ if ($debug){plugin_log($plugname,"Sende:$cmd")};
+ my @answer = $t->cmd($cmd);
+ $answer = $answer[0];
+ $t->close;
+ ####possible this prevents a memleak
+ @answer = ();
+ undef @answer;
+ ####maybe !?
+ return $answer;
+ eval { close $t; };undef $t;
+}
+
+####possible this prevents a memleak
+@sets = ();
+@gets = ();
+undef @gets;
+undef @sets;
+####maybe !?
+
+
+return sprintf("%.2f",$plugin_info{$plugname.'_meminc'})." mb lost";
+
+### READ CONF ###
+sub readConf
+{
+ my $confFile = '/etc/knxd/eBus_plugin.conf';
+ if (! -f $confFile) {
+ plugin_log($plugname, "no conf file [$confFile] found.");
+ } else {
+ #plugin_log($plugname, "reading conf file [$confFile].");
+ open(CONF, $confFile);
+ my @lines = <CONF>;
+ close($confFile);
+ my $result = eval("@lines");
+ #($result) and plugin_log($plugname, "conf file [$confFile] returned result[$result]");
+ if ($@) {
+ plugin_log($plugname, "ERR: conf file [$confFile] returned:");
+ my @parts = split(/\n/, $@);
+ plugin_log($plugname, "--> $_") foreach (@parts);
+ }
+ }
+####possible this prevents a memleak
+@lines = ();
+undef @lines;
+####maybe !?
+}
\ No newline at end of file
Deleted: tools/knxd/usr/sbin/knxd.pl
===================================================================
--- tools/ebus/knxd/usr/sbin/knxd.pl 2013-02-17 22:50:49 UTC (rev 1500)
+++ tools/knxd/usr/sbin/knxd.pl 2013-03-09 12:09:04 UTC (rev 1559)
@@ -1,1093 +0,0 @@
-#!/usr/bin/perl -w
-# KNX Daemon - handling WireGate-Plugins and EIB
-# based on wiregated.pl by Michael Markstaller
-#
-# Cleanup and partially rewritten by M.Hirsch
-# http://knx-user-forum.de -> JuMi2006
-#
-# This program 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 (at your option)
-# any later version.
-#
-# This program 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.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
-
-use strict;
-use Math::Round;
-use Math::BaseCalc;
-use RRDs;
-use Getopt::Std;
-use Time::HiRes qw ( time alarm sleep usleep gettimeofday );
-getopts("dp:c:e:o:", \my %opts);
-use IO::Socket;
-use IO::Select;
-use FileHandle;
-use Proc::PID::File;
-# fork daemon
-use Proc::Daemon;
-Proc::Daemon::Init unless $opts{d};
-#use xPL::Client;
-use EIBConnection;
-use feature "switch";
-use File::Basename;
-use DB_File;
-
-no warnings 'uninitialized';
-
-sub LOGGER;
-
-# Options
-while ((my $key, my $value) = each %opts) {
- print "opt $key = $value\n" if ($opts{d});
-}
-
-# PID File-handling
-if ($opts{p} and Proc::PID::File->running()) {
- LOGGER("WARN","Already running");
- die();
- }
-
-# Config files
-# global
-my $config;
-if ($opts{c}) {
- LOGGER("INFO","Config-File is: $opts{c}");
- $config = $opts{c};
- } else {$config = "/etc/knxd/knxd.conf" }
-
-# eibga
-my $eib_config;
-if ($opts{c}) {
- LOGGER("INFO","eibga-File is: $opts{e}");
- $eib_config = $opts{e};
- } else {$eib_config = "/etc/knxd/eibga.conf" }
-
-# Read config #
-my %daemon_config;
-my $lastreadtime = 0;
-my %eibgaconf;
-my $udp_sock;
-my %ga_to_ow;
-my @eibga_types = qw (temp hum moisthum present light volt curr ch0 ch1 ch2 ch3 ch4 ch5 ch6 ch7 countA countB );
-
-if ((stat($config))[9] > $lastreadtime or (stat($eib_config))[9] > $lastreadtime) {
- if (-e $config) {
- LOGGER('INFO',"*** reading global config");
- my_read_cfg ($config, \%daemon_config);
- $lastreadtime = time();
- }
- if (-e $eib_config) {
- LOGGER('INFO',"*** reading eibga config");
- my_read_cfg ($eib_config,\%eibgaconf);
- }
- } else {
- #LOGDIE("unable to read config $config");
- print "unabled to read config $config";
- }
-
-
-# Definitions
-
-# config values
-
-my $cycle = $daemon_config{''}{'cycle'};
-my $sleeptime = $daemon_config{''}{'sleeptime_ms'};
-my $plugin_cycle = $daemon_config{''}{'plugin_cycle'};
-my $rrd_interval = $daemon_config{''}{'rrd_interval'};
-my $rra1_row = $daemon_config{''}{'rra_1_interval_rows'};
-my $rra5_row = $daemon_config{''}{'rra_5_interval_rows'};
-my $rra15_row = $daemon_config{''}{'rra_15_interval_rows'};
-my $rra180_row= $daemon_config{''}{'rra_180_interval_rows'};
-my $eib_logging = $daemon_config{''}{'eib_logging'};
-my $eib = $daemon_config{''}{'eib'};
-
-my $mem_max = $daemon_config{''}{'mem_max'};
-my $name = $daemon_config{''}{'name'};
-my $eib_url = $daemon_config{''}{'eib_url'};
-my $rrd_dir = $daemon_config{''}{'rrd_dir'};
-my $eiblogfile = $daemon_config{''}{'eiblogfile'};
-
-my $plugin_logfile = $daemon_config{''}{'plugin_logfile'};
-my $plugin_infofile = $daemon_config{''}{'plugin_infofile'};
-my $plugin_db_name = $daemon_config{''}{'plugin_db_name'};
-my $plugin_db_path = $daemon_config{''}{'plugin_db_path'};
-
-my $ramdisk = $daemon_config{''}{'ramdisk'};
-my $alive = $daemon_config{''}{'alive'};
-my $plugin_path = $daemon_config{''}{'plugin_path'};
-my $init_script = $daemon_config{''}{'init_script'};
-
-my $knxdebug = 0;
-
-# Plugins
-
-my %plugin_info;
-my %plugin_subscribe;
-my $plugin_initflag=0;
-my %plugin_socket_subscribe;
-
-# global definitions
-
-my $conv2bin = new Math::BaseCalc(digits => 'bin'); #Binary
-my $telegram_count = 0;
-my $telegram_bytes;
-my %msg;
-my @socket;
-my $socksel;
-
-my $looptime = time();
-my $looptimeavg = 0;
-my $laststatesaveime = 0;
-my $lastdirtime = 0;
-my $lastlooptime = 0;
-my $eib_tps = 50;
-my $telegram_count_check = 100;
-my $sendtime_last = 0;
-my $running = 1;
-my $thr_eiblisten_timeout = 0;
-my $thr_eiblisten_cause = "";
-
-sub getISODateStamp;
-
-
-### MAIN ###
-
-system ("touch ".$alive); # avoid timeout for init
-
-LOGGER('INFO',"Started with PID: $$ \n");
-
-$cycle=60 unless (defined $cycle and $cycle > 29); # minimum cycle 30 to avoid insane settings
-$sleeptime = 500 unless defined $sleeptime;
-$plugin_cycle= 60 unless defined $plugin_cycle;
-$eib_logging= 1 unless defined $eib_logging;
-$rrd_interval = 300 unless defined $rrd_interval;
-$rra1_row = 2160 unless defined $rra1_row;
-$rra5_row = 2016 unless defined $rra5_row;
-$rra15_row = 2880 unless defined $rra15_row;
-$rra180_row = 8760 unless defined $rra180_row;
-
-my $rrd_lastupdate = time()-($rrd_interval-+1);
-my $rrd_syslastupdate = time()-($rrd_interval-+1);
-
-# Copy Plugin-DB to ramdisk
-if (! -e $ramdisk.$plugin_db_name) {
- `cp $plugin_db_path$plugin_db_name $ramdisk$plugin_db_name`; }
-my $plugindb = tie %plugin_info, "DB_File", $ramdisk.$plugin_db_name, O_RDWR|O_CREAT, 0666, $DB_HASH
- or LOGGER('WARN',"Cannot open file 'plugin_info': $!");
-
-
-# GO
-&eiblisten_thread;
-
-#######################################
-#### K N O W N S U B S #####
-#######################################
-sub eiblisten_thread { # MAIN SUB
-$SIG{TERM} = sub {
- # -> Doesn't work when blocked by I/O!!
- LOGGER('DEBUG',"Thread eiblisten Caught TERM, exiting:". $thr_eiblisten_cause);
- system ("touch $alive"); # avoid timeout for init
- if($eib_logging) { close FILE_EIBLOG; }
- $plugindb->sync(); # write out
- `cp $ramdisk$plugin_db_name $plugin_db_path$plugin_db_name`;
- exit();
-};
-$SIG{KILL} = sub {
- # ende aus finito
- LOGGER('DEBUG',"Thread eiblisten Caught KILL, exiting:" .$thr_eiblisten_cause);
- system ("touch $alive"); # avoid timeout for init
- if($eib_logging) { close FILE_EIBLOG; }
- $plugindb->sync(); # write out
- `cp $ramdisk$plugin_db_name $plugin_db_path$plugin_db_name`;
- exit();
-};
-
-#FIXME: add plugin-timeout again with SIGALRM, currently we rely on monit (1 minute)
-
-if($eib_logging) {
- open FILE_EIBLOG, ">>$eiblogfile";
- print "Muss jetzt eibloggen";
-}
-
-# make it hot
-select((select(FILE_EIBLOG), $|=1)[0]);
-my $select = IO::Select->new();
-$socksel = IO::Select->new();
-my $retryinfo;
-my $lastplugintime;
-my $eibpoll = 1;
-my $eibsrc=EIBConnection::EIBAddr();
-my $eibdst=EIBConnection::EIBAddr();
-my $eibbuf2=EIBConnection::EIBBuffer();
-
-while ($running) {
- my $eibcon2;
- if ($eib == 1){
- $eibcon2 = EIBConnection->EIBSocketURL($eib_url);
- if (defined($eibcon2)) {
- $eibcon2->EIB_Cache_Enable();
- my $busmon = $eibcon2->EIBOpenVBusmonitor_async();
- LOGGER('INFO',"connected to eibd $eib_url");
- } else {
- LOGGER('INFO',"Cannot connect to eibd $eib_url") unless $retryinfo;
- }
- }
-
- while (($eibpoll and defined($eibcon2)) or ($eib == 0)) #try to disable eib
- {
- if ($eib ==1){
- $select->add($eibcon2->EIB_Poll_FD);
- if ($select->can_read(.5)) { # EIB Packet processing
- if ($eibpoll=$eibcon2->EIB_Poll_Complete) {
- my $msglen=$eibcon2->EIBGetBusmonitorPacket($eibbuf2);
- if ($msglen>1) {
- my %msg = decode_vbusmonitor($$eibbuf2);
- $retryinfo = 0;
- # case ReadRequest for configured owsensor-value
- if ($msg{'apci'} eq "A_GroupValue_Read" and $ga_to_ow{$msg{'dst'}}) {
- LOGGER('DEBUG',"---> Send reply for $msg{'dst'} $ga_to_ow{$msg{'dst'}}");
- send_sensor_response($msg{'dst'});
- }
- # case Write for PIO
- if ($msg{'apci'} eq "A_GroupValue_Write" and $ga_to_ow{$msg{'dst'}}) {
- set_sensor_value($msg{'dst'},$msg{'data'});
- }
-
- # Log it
- print FILE_EIBLOG getISODateStamp.",$msg{'apci'},$msg{'src'},$msg{'dst'},$msg{'data'},$msg{'value'}"
- .",$eibgaconf{$msg{'dst'}}{'DPT_SubTypeName'},$eibgaconf{$msg{'dst'}}{'DPTSubId'},$msg{'repeated'}"
- .",$msg{'class'},$msg{'rcount'},$msg{'tpdu_type'},$msg{'sequence'}\n" if($eib_logging);
- # Check EIB-connectivity and configchange every 100 telegrams?
- $telegram_count++;
-
- # Traffic on Bus in bytes (8+Nutzdaten)+ACK?
- $telegram_bytes += 9+(length(join('',split / /,$msg{'data'}))/2);
- #LOGGER('DEBUG',"Anz $telegram_count, Bytes $telegram_bytes");
-
- if ($msg{'apci'} eq "A_GroupValue_Read" and ($msg{'dst'} eq $daemon_config{''}{'sendtime_ga_time'})) {
- # send time response
- eibsend_time_resp($daemon_config{''}{'sendtime_ga_time'});
- }
- if ($msg{'apci'} eq "A_GroupValue_Read" and ($msg{'dst'} eq $daemon_config{''}{'sendtime_ga_date'})) {
- # send time response
- eibsend_date_resp($daemon_config{''}{'sendtime_ga_date'});
- }
- # check subscribed plugin
- if ($plugin_subscribe{$msg{'dst'}}) {
- #while( my ($k, $v) = each($plugin_subscribe{$msg{'dst'}}) ) {
- for my $k ( keys %{$plugin_subscribe{ $msg{'dst'} }} ) {
- LOGGER('DEBUG',"Running Plugin $k subscribed to $msg{'dst'}");
- $thr_eiblisten_timeout = time(); # set timeout
- check_generic_plugins($k,\%msg);
- }
- }
-
- } elsif ($msglen==414) {
- # process other?
- }
- }} # EIB Packet processing end, back in main loop
-
- }
- ###LOG continious Memory if DEBUG
- #if ($opts{d}) {
- # my @statinfo = get_stat_info($$);
- # LOGGER('DEBUG',"BOSS utime: " . $statinfo[0]/100 ." stime " . $statinfo[1]/100 ." rss: $statinfo[5]");
- #}
- #FIXME: output log-warning on memleak
- system ("touch $alive");
-
- # check plugins
- if (time()-$lastplugintime > 1) { # at most every 1secs for now
- $thr_eiblisten_timeout = time(); # set timeout
- &check_generic_plugins();
- $lastplugintime = time();
- # case update rrds
- &check_global_rrd_update;
- #Cleanup %plugin_subscribe from deleted!!!
- }
- if ($rrd_syslastupdate + $rrd_interval < time()) {
- my @statinfo = get_stat_info($$);
- update_rrd($name."_mem","",$statinfo[5]);
- update_rrd($name."_stime","",$statinfo[0],"COUNTER");
- update_rrd($name."_utime","",$statinfo[1],"COUNTER");
- update_rrd($name."_cutime","",$statinfo[2],"COUNTER");
- update_rrd($name."_cstime","",$statinfo[3],"COUNTER");
- $rrd_syslastupdate = time();
-
- # save plugin_db from ramdisk
- $plugindb->sync(); # write out
- `cp $ramdisk$plugin_db_name $plugin_db_path$plugin_db_name`;
-
- # if own memory is above mem_max -> restart via init.d
- if ($statinfo[5] >= $mem_max){
- LOGGER('INFO',"Process should be restarted: Memory is $statinfo[5] Mb - Limit is $mem_max Mb.");
- system ("$init_script restart");}
-
- }
-
- # Check if socket-handle is in select - or do this in plugin?
- if (my @sock_ready = $socksel->can_read(0.1)) {
- # process sockets ready to read
- foreach my $fh (@sock_ready) {
- if ($plugin_socket_subscribe{$fh}) {
- LOGGER('DEBUG',"Call plugin $plugin_socket_subscribe{$fh} subscribed for $fh");
- $thr_eiblisten_timeout = time(); # set timeout
- &check_generic_plugins($plugin_socket_subscribe{$fh},undef,$fh);
- } else {
- #else if - no plugin subscribed, remove select
- $socksel->remove($fh);
- LOGGER('DEBUG',"Removed orphaned socksel $fh");
- }
- }
- }
- # case cyclic time
- if ($daemon_config{''}{'sendtime_cycle'} and $daemon_config{''}{'sendtime_ga_time'} and $daemon_config{''}{'sendtime_ga_date'} and (time() - $sendtime_last > $daemon_config{''}{'sendtime_cycle'}) ) {
- # send time cyclic
- eibsend_date_time($daemon_config{''}{'sendtime_ga_date'},$daemon_config{''}{'sendtime_ga_time'});
- $sendtime_last = time();
- }
- }
-
-if ($eib == 1)
-{
-LOGGER('INFO',"eibd connection lost - retrying") unless $retryinfo;
-$retryinfo = 1;
-$eibpoll = 1;
-sleep 5;
-}
-}
-
-if($eib_logging) { close FILE_EIBLOG , ">>$eiblogfile"; }
-}
-
-
-sub getISODateStamp { # Timestamps for Logs
- my ($eseconds,$msec) = gettimeofday();
- my ($second, $minute, $hour, $dayOfMonth, $month, $yearOffset, $dayOfWeek, $dayOfYear, $daylightSavings) = localtime($eseconds);
- return sprintf "%04d-%02d-%02d %02d:%02d:%02d.%03d", ($yearOffset+1900),($month+1),$dayOfMonth,$hour,$minute,$second,$msec/1000;
-}
-
-sub check_generic_plugins {#check Plugins
- my $runname = $_[0];
- my %msg;
- my $fh;
- my $plugin_max_errors = 5;
- if (defined $_[1]) { %msg = %{$_[1]}; } else { %msg = (); }
- if (defined $_[2]) { $fh = $_[2]; } else { $fh = undef; }
- #%msg =() unless defined %msg;
- #my %msg ; # dummy definition - empty so plugins can determine if called by subscribed ga or cycle
- $thr_eiblisten_cause = "checking plugins";
-
- my @plugins = <$plugin_path*>;
- foreach (@plugins) {
- next if ($_ =~ /\~$/ or -d $_); # ignore backup-files and subdirectories
- my $plugname = basename($_);
- $plugin_info{$plugname.'_lastsaved'} = ((stat($_))[9]);
- $plugin_info{$plugname.'_cycle'} = $plugin_cycle unless defined $plugin_info{$plugname.'_cycle'};
- if ((time() > $plugin_info{$plugname.'_last'} + $plugin_info{$plugname.'_cycle'} and $plugin_info{$plugname.'_cycle'}) # check cyclic plugin
- or $plugin_info{$plugname.'_lastsaved'} > $plugin_info{$plugname.'_last'} # check changed plugin
- or $runname eq $plugname # direct call
- or !$plugin_initflag) {
- LOGGER('DEBUG',"Running PLUGIN $plugname");
-
- open(FILE, $_);
- my @lines = <FILE>;
- close($_);
- # if modified and once on init, reset error-counter, mem-stats
- if (($plugin_info{$plugname.'_lastsaved'} > $plugin_info{$plugname.'_last'}) or !$plugin_initflag) {
- $plugin_info{$plugname.'_timeout_err'}=0;
- $plugin_info{$plugname.'_meminc'}=0;
- $plugin_info{$plugname.'_memstart'}=0;
- $plugin_info{$plugname.'_ticks'}=0;
- }
- if ($plugin_info{$plugname.'_timeout_err'}<$plugin_max_errors) {
- $thr_eiblisten_cause = "TIMEOUT running PLUGIN ".$plugname;
- $plugindb->sync(); # write out AFTER setting reason BEFORE err++
- $plugin_info{$plugname.'_timeout_err'}++;
- my @statinfo = get_stat_info($$);
- my $before_mem = $statinfo[5];
- my $before_ticks = $statinfo[6];
- my $starttime = time();
- $plugin_info{$plugname.'_result'} = eval("@lines");
- $plugin_info{$plugname.'_last'} = time() unless ($runname eq $plugname); #only reset cycle on non-direct call
- @statinfo = get_stat_info($$);
- if (!$plugin_initflag) {
- $plugin_info{$plugname.'_memstart'}= $statinfo[5] - $before_mem;
- } else {
- $plugin_info{$plugname.'_meminc'} += $statinfo[5] - $before_mem;
- }
- $plugin_info{$plugname.'_ticks'} += $statinfo[6] - $before_ticks;
- $plugin_info{$plugname.'_timeout_err'}=0;
- $thr_eiblisten_cause = "normally";
- $plugin_info{$plugname.'_runtime'} = nearest(.3,time() - $starttime);
- if ($plugin_info{$plugname.'_result'} or $@) {
- plugin_log($plugname,"$plugin_info{$plugname.'_result'},$plugin_info{$plugname.'_runtime'}s,$@");
- }
- $plugindb->sync(); # write out AFTER setting reason
- }
- if ($@) {
- LOGGER('DEBUG',"ERROR in $plugname $@");
- $plugin_info{$plugname.'_result'} = $@;
- }
- }
- }
- # check for orphaned/old values in tied hash here!
- $plugin_initflag = 1;
-}
-
-
-sub check_global_rrd_update { # here eib_traffic and daemon-stats - also: CHECK for MEMLEAK !!!
-
- if ($rrd_lastupdate + $rrd_interval < time()) {
- # check/create rrd
- if (!-d $rrd_dir) { mkdir($rrd_dir); }
- if (!-e $rrd_dir.'eib_traffic.rrd') {
- # Create RRD
- my $heartbeat = $rrd_interval * 3;
- RRDs::create($rrd_dir.'eib_traffic.rrd',
- '--step' => $rrd_interval,
- 'DS:eib_tps:COUNTER:'.$heartbeat.':0:50','DS:eib_bps:COUNTER:'.$heartbeat.':0:9830400',
- 'RRA:AVERAGE:0.5:1:'.$rra1_row,'RRA:AVERAGE:0.5:5:'.$rra5_row,'RRA:AVERAGE:0.5:15:'.$rra15_row,'RRA:AVERAGE:0.5:180:'.$rra180_row,
- 'RRA:MIN:0.5:1:'.$rra1_row,'RRA:MIN:0.5:5:'.$rra5_row,'RRA:MIN:0.5:15:'.$rra15_row,'RRA:MIN:0.5:180:'.$rra180_row,
- 'RRA:MAX:0.5:1:'.$rra1_row,'RRA:MAX:0.5:5:'.$rra5_row,'RRA:MAX:0.5:15:'.$rra15_row,'RRA:MAX:0.5:180:'.$rra180_row);
- if (RRDs::error) {
- LOGGER('INFO',"Create RRDs failed:".RRDs::error);
- } else {
- LOGGER('INFO',"Created RRD eib-traffic");
- }
- }
- #Now do the updates
- RRDs::update($rrd_dir.'eib_traffic.rrd','N:'.$telegram_count.':'.$telegram_bytes);
- if (RRDs::error) {
- LOGGER('INFO',"Update of RRDs eib-traffic failed:".RRDs::error." -> deleted");
- unlink($rrd_dir.'eib_traffic.rrd');
- } else {
- LOGGER('DEBUG',"Updated RRD eib-traffic");
- }
- my @statinfo = get_stat_info($$);
- update_rrd($name."_mem","",$statinfo[5]);
- update_rrd($name."_stime","",$statinfo[0],"COUNTER");
- update_rrd($name."_utime","",$statinfo[1],"COUNTER");
- update_rrd($name."_cutime","",$statinfo[2],"COUNTER");
- update_rrd($name."_cstime","",$statinfo[3],"COUNTER");
- $rrd_lastupdate = time();
- }
-}
-
-sub trim($){# Perl trim function to remove whitespace from the start and end of the string
- my $string = shift;
- $string =~ s/^\s+//;
- $string =~ s/\s+$//;
- return $string;
-}
-
-sub ltrim($){# Left trim function to remove leading whitespace
- my $string = shift;
- $string =~ s/^\s+//;
- return $string;
-}
-
-sub rtrim($){# Right trim function to remove trailing whitespace
- my $string = shift;
- $string =~ s/\s+$//;
- return $string;
-}
-
-
-sub rstr{# right $len chars
- my $s = shift;
- my $len = shift;
- # printf("DEBUG %s %i\n",$s,$len);
- return substr($s, length($s) - $len, $len);
-}
-
-sub get_stat_info { #reads info from deamon file
- my $error = '';
- my @ret;
-
- ### open and read the main stat file
- if( ! open(_INFO,"</proc/$_[0]/stat") ){
- $error = "Couldn't open /proc/$_[0]/stat [$!]";
- return @ret;
- }
- my @info = split(/\s+/,<_INFO>);
- close(_INFO);
- ### get the important ones
- # utime,stime,cutime,cstime,vsize,rss (in MB), cummulated *time for convinience
- @ret = ($info[13],$info[14],$info[15],$info[16],$info[22]/1024,nearest(.1,$info[23] * 4/1024),$info[13]+$info[14]+$info[15]+$info[16]);
- return @ret;
-
- ### these are all the props (skip some)
- # pid(0) comm(1) state ppid pgrp session tty
- # tpgid(7) flags minflt cminflt majflt cmajflt
- # utime(13) stime cutime cstime counter
- # priority(18) timeout itrealvalue starttime vsize rss
- # rlim(24) startcode endcode startstack kstkesp kstkeip
- # signal(30) blocked sigignore sigcatch wchan
- ###
-}
-sub my_read_cfg{ # read config files
- my $cfgfile=shift;
- my $cfghash=shift;
- %{$cfghash}=();
-
- open CONF, "<$cfgfile" || die "Could not open $cfgfile for reading";
- $/="\n";
-
- my $record={};
- my $key='';
-
- while(<CONF>)
- {
- unless ($_ =~ /\#/){ #checks for uncommented
- # reads eibga only
- if(/^\s*\[\s*(.+?)\s*\]\s*$/)
- {
- my $newkey=$1;
-
- if(defined $key) # flush last record
- {
- if(defined $record->{name} && $cfgfile=~/eibga/)
- {
- $record->{ga}=$key;
- $record->{name}=~/^\s*(\S+)/;
- $cfghash->{$record->{name}}=$record;
- #specific to my GA scheme (Fry)
- $record->{short}=$1;
- $record->{short}="ZV_$1" if $record->{name}=~/^Zeitversand.*(Uhrzeit|Datum)/; # short versions of "Zeitversand"
- $cfghash->{$record->{short}}=$record;
- # end of specific part
- }
- $cfghash->{$key}=$record;
- }
- # start new record
- $record={};
- $key=$newkey;
- }
- # reads pure config file
- elsif(/^\s*(.+?)\s*\=\s*(.*?)\s*$/)
- {
- #print $1 ." und ". $2;
- $record->{$1} = $2;
- $cfghash->{$key}=$record;
- }
- else {
- # empty line
- }
- }
- }
- close CONF;
-
- if($key) # flush last record
- {
- if(defined $record->{name} && $cfgfile=~/eibga/)
- {
- $record->{ga}=$key;
- $record->{name}=~/^\s*(\S+)/;
- $cfghash->{$record->{name}}=$record;
- # specific to my GA scheme (Fry)
- $record->{short}=$1;
- $record->{short}="ZV_$1" if $record->{name}=~/^Zeitversand.*(Uhrzeit|Datum)/; # short versions of "Zeitversand"
- $cfghash->{$record->{short}}=$record;
- # end of specific part
- }
- $cfghash->{$key}=$record;
- }
-}
-
-sub my_write_cfg{ # write config files
- my $cfgfile=shift;
- my $cfghash=shift;
-
- open CONF, ">$cfgfile" || die "Could not open $cfgfile for writing";
-
- for my $s (keys %{$cfghash})
- {
- next if $cfgfile=~/eibga/ && $s!~/^[\'\/0-9]+$/;
-
- print CONF "[$s]\n";
-
- for my $k (keys %{$cfghash->{$s}})
- {
- print CONF "$k=$cfghash->{$s}{$k}\n";
- }
- }
-
- close CONF;
-}
-
-
-
-
-sub LOGGER($$){# LOG-sub to replace heavyweight Log4Perl/Syslog
- my $level = shift;
- my $msg = shift;
-
- if ($level eq "DEBUG") {
- return unless $opts{d};
- }
- if ($opts{d}) {
- print STDERR getISODateStamp . " $level - $msg\n";
- } else {
- `logger -t $0 -p $level "$level - $msg"`;
- }
-}
-
-
-sub decode_dpt9 {# encode DPT9.001/EIS 5
- my @data = @_;
- my $res;
-
- unless ($#data == 2) {
- ($data[1],$data[2]) = split(' ',$data[0]);
- $data[1] = hex $data[1];
- $data[2] = hex $data[2];
- unless (defined $data[2]) {
- return;
- }
- }
- my $sign = $data[1] & 0x80;
- my $exp = ($data[1] & 0x78) >> 3;
- my $mant = (($data[1] & 0x7) << 8) | $data[2];
-
- $mant = -(~($mant - 1) & 0x7ff) if $sign != 0;
- $res = (1 << $exp) * 0.01 * $mant;
- return $res;
-}
-
-sub encode_dpt9 { # 2byte signed float
- my $state = shift;
- my $data;
-
- my $sign = ($state <0 ? 0x8000 : 0);
- my $exp = 0;
- my $mant = 0;
-
- $mant = int($state * 100.0);
- while (abs($mant) > 2047) {
- $mant /= 2;
- $exp++;
- }
- $data = $sign | ($exp << 11) | ($mant & 0x07ff);
- return $data >> 8, $data & 0xff;
-}
-
-sub decode_dpt2 { #2bit "signed bit"
- my $val=hex(shift) & 0x03;
- return $val > 1 ? $val-4 : $val;
-}
-
-sub decode_dpt3 { #4bit signed integer
- my $val=hex(shift) & 0x0f;
- return $val > 7 ? 8-$val : $val;
-}
-
-sub decode_dpt4 { #1byte char
- return sprintf("%c", hex(shift));
-}
-
-sub decode_dpt5 { #1byte unsigned percent
- return sprintf("%.1f", hex(shift) * 100 / 255);
-}
-
-sub decode_dpt510 { #1byte unsigned UChar
- return hex(shift);
-}
-
-sub decode_dpt6 { #1byte signed
- my $val = hex(shift);
- return $val > 127 ? $val-256 : $val;
-}
-
-sub decode_dpt7 { #2byte unsigned
- my @val = split(" ",shift);
- return (hex($val[0])<<8) + hex($val[1]);
-}
-
-sub decode_dpt8 { #2byte signed
- my @val = split(" ",shift);
- my $val2 = (hex($val[0])<<8) + hex($val[1]);
- return $val2 > 32767 ? $val2-65536 : $val2;
-}
-
-sub decode_dpt10 { #3byte time
- my @val = split(" ",shift);
- my @wd = qw(Null Mo Di Mi Do Fr Sa So);
- $val[0] = hex($val[0]);
- $val[1] = hex($val[1]);
- $val[2] = hex($val[2]);
- unless ($val[2]) { return; }
- my $day = ($val[0] & 0xE0) >> 5;
- my $hour = $val[0] & 0x1F;
- my $minute = $val[1];
- my $second = $val[2];
- return sprintf("%s %02i:%02i:%02i",$wd[$day],$hour,$minute,$second);
-}
-
-sub decode_dpt11 { #3byte date
- my @val = split(" ",shift);
- my @wd = qw(Null Mo Di Mi Do Fr Sa So);
- $val[0] = hex($val[0]);
- $val[1] = hex($val[1]);
- $val[2] = hex($val[2]);
- unless ($val[2]) { return; }
- my $mday = $val[0] & 0x1F;
- my $mon = $val[1] & 0x0F;
- my $year = $val[2] & 0x7F;
- $year = $year < 90 ? $year+2000 : $year+1900; # 1990 - 2089
- return sprintf("%04i-%02i-%02i",$year,$mon,$mday);
-}
-
-sub decode_dpt12 { #4byte unsigned
- my @val = split(" ",shift);
- return (hex($val[0])<<24) + (hex($val[1])<<16) + (hex($val[2])<<8) + hex($val[3]);
-}
-
-sub decode_dpt13 { #4byte signed
- my @val = split(" ",shift);
- my $val2 = (hex($val[0])<<24) + (hex($val[1])<<16) + (hex($val[2])<<8) + hex($val[3]);
- return $val2 > 2147483647 ? $val2-4294967296 : $val2;
-}
-
-sub decode_dpt14 { #4byte float
- #Perls unpack for float is somehow strange broken
- my @val = split(" ",shift);
- my $val2 = (hex($val[0])<<24) + (hex($val[1])<<16) + (hex($val[2])<<8) + hex($val[3]);
- my $sign = ($val2 & 0x80000000) ? -1 : 1;
- my $expo = (($val2 & 0x7F800000) >> 23) - 127;
- my $mant = ($val2 & 0x007FFFFF | 0x00800000);
- my $num = $sign * (2 ** $expo) * ( $mant / (1 << 23));
- return sprintf("%.4f",$num);
-}
-
-sub decode_dpt16 { # 14byte char
- my @val = split(" ",shift);
- my $chars;
- for (my $i=0;$i<14;$i++) {
- $chars .= sprintf("%c", hex($val[$i]));
- }
- return sprintf("%s",$chars);
-}
-
-sub encode_dpt5 {
- my $value = shift;
- $value = 100 if ($value > 100);
- $value = 0 if ($value < 0);;
- my $byte = sprintf ("%.0f", $value * 255 / 100);
- return($byte);
-}
-
-sub decode_dpt {
- my $dst = shift;
- my $data = shift;
- my $dpt = shift;
- my $value;
- my $dptid = $dpt || $eibgaconf{$dst}{'DPTSubId'} || 0;
- $data =~ s/\s+$//g;
- given ($dptid) {
- when (/^10/) { $value = decode_dpt10($data); }
- when (/^11/) { $value = decode_dpt11($data); }
- when (/^12/) { $value = decode_dpt12($data); }
- when (/^13/) { $value = decode_dpt13($data); }
- when (/^14/) { $value = decode_dpt14($data); }
- when (/^16/) { $value = decode_dpt16($data); }
- when (/^17/) { $value = decode_dpt510($data & 0x3F); }
- when (/^20/) { $value = decode_dpt510($data); }
- when (/^\d\d/) { return; } # other DPT XX 15 are unhandled
- when (/^1/) { $value = int($data); }
- when (/^2/) { $value = decode_dpt2($data); }
- when (/^3/) { $value = decode_dpt3($data); }
- when (/^4/) { $value = decode_dpt4($data); }
- when ([5,'5.001']) { $value = decode_dpt5($data); }
- when (['5.004','5.005','5.010']) { $value = decode_dpt510($data); }
- when (/^6/) { $value = decode_dpt6($data); }
- when (/^7/) { $value = decode_dpt7($data); }
- when (/^8/) { $value = decode_dpt8($data); }
- when (/^9/) { $value = decode_dpt9($data); }
- default { return; } # nothing
- }
- return $value;
-}
-
-sub knx_read {
- my $dst = $_[0];
- my $age = $_[1] || 0; # read hot unless defined
- my $dpt = $_[2];
- my $src=EIBConnection::EIBAddr();
- my $buf=EIBConnection::EIBBuffer();
- my $hexbytes;
- my $leibcon = EIBConnection->EIBSocketURL($eib_url) or return("Error: $!");
- my $res=$leibcon->EIB_Cache_Read_Sync(str2addr($dst), $src, $buf, $age);
- if (!defined $res) { return; } # ("ReadError: $!");
- $leibcon->EIBClose();
- # $$src contains source PA
-
- my @data = unpack ("C" . bytes::length($$buf), $$buf);
- if ($res == 2) { # 6bit only
- return decode_dpt($dst,($data[1] & 0x3F),$dpt);
- } else {
- for (my $i=2; $i<= $res-1; $i++) {
- $hexbytes = $hexbytes . sprintf("%02X ", ($data[$i]));
- }
- return decode_dpt($dst,$hexbytes,$dpt);
- }
-}
-
-sub knx_write {
- my ($dst,$value,$dpt,$response,$dbgmsg) = @_;
- my $bytes;
- my $apci = ($response) ? 0x40 : 0x80; # 0x40=response, 0x80=write
-# DPT 1 (1 bit) = EIS 1/7 (move=DPT 1.8, step=DPT 1.7)
-# DPT 2 (1 bit controlled) = EIS 8
-# DPT 3 (3 bit controlled) = EIS 2
-# DPT 4 (Character) = EIS 13
-# DPT 5 (8 bit unsigned value) = EIS 6 (DPT 5.1) oder EIS 14.001 (DPT 5.10)
-# DPT 6 (8 bit signed value) = EIS 14.000
-# DPT 7 (2 byte unsigned value) = EIS 10.000
-# DPT 8 (2 byte signed value) = EIS 10.001
-# DPT 9 (2 byte float value) = EIS 5
-# DPT 10 (Time) = EIS 3
-# DPT 11 (Date) = EIS 4
-# DPT 12 (4 byte unsigned value) = EIS 11.000
-# DPT 13 (4 byte signed value) = EIS 11.001
-# DPT 14 (4 byte float value) = EIS 9
-# DPT 15 (Entrance access) = EIS 12
-# DPT 16 (Character string) = EIS 15
- $dpt = $eibgaconf{$dst}{'DPTSubId'} unless $dpt; # read dpt from eibgaconf if existing
- given ($dpt) {
- when (/^10/) {
- my %wd=(Mo=>1, Di=>2, Mi=>3, Do=>4, Fr=>5, Sa=>6, So=>7);
- my $wdpat=join('|',keys %wd);
- my ($w,$h,$m,$s);
- return unless ($w,$h,$m,$s)=($value=~/^($wdpat)?\s*([0-2][0-9])\:([0-5][0-9])\:?([0-5][0-9])?\s*/si);
- return unless defined $h && defined $m;
- $w=$wd{$w} if defined $wd{$w};
- $h+=($w<<5) if $w;
- $s=0 unless $s;
- $bytes=pack("CCCCC",0,$apci,$h,$m,$s);
- }
- when (/^11/) {
- my ($y,$m,$d);
- return unless ($y,$m,$d)=($value=~/^([1-2][0-9][0-9][0-9])\-([0-1][0-9])\-([0-3][0-9])\s*/si);
- return if $y<1990 || $y>=2090;
- $y%=100;
- $bytes=pack("CCCCC",0,$apci,$d,$m,$y);
- }
- when (/^12/) { $bytes = pack ("CCL>", 0, $apci, $value); } #EIS11.000/DPT12 (4 byte unsigned)
- when (/^13/) { $bytes = pack ("CCl>", 0, $apci, $value); }
- when (/^14/) { $bytes = pack ("CCf>", 0, $apci, $value); }
- when (/^16/) { $bytes = pack ("CCa14", 0, $apci, $value); }
- when (/^17/) { $bytes = pack ("CCC", 0, $apci, $value & 0x3F); }
- when (/^20/) { $bytes = pack ("CCC", 0, $apci, $value); }
- when (/^\d\d/) { return; } # other DPT XX 15 are unhandled
- when (/^[1,2,3]/) { $bytes = pack ("CC", 0, $apci | ($value & 0x3f)); } #send 6bit small
- when (/^4/) { $bytes = pack ("CCc", 0, $apci, ord($value)); }
- when ([5,5.001]) { $bytes = pack ("CCC", 0, $apci, encode_dpt5($value)); } #EIS 6/DPT5.001 1byte
- when ([5.004,5.005,5.010]) { $bytes = pack ("CCC", 0, $apci, $value); }
- when (/^5/) { $bytes = pack ("CCC", 0, $apci, $value); }
- when (/^6/) { $bytes = pack ("CCc", 0, $apci, $value); }
- when (/^7/) { $bytes = pack ("CCS>", 0, $apci, $value); }
- when (/^8/) { $bytes = pack ("CCs>", 0, $apci, $value); }
- when (/^9/) { $bytes = pack ("CCCC", 0, $apci, encode_dpt9($value)); } #EIS5/DPT9 2byte float
- default { LOGGER('WARN',"None or unsupported DPT: $dpt sent to $dst value $value"); return; }
- }
- plugin_log("knx_write","KNX write DPT $dpt: $value ($bytes) to $dst ($dbgmsg)") if ($knxdebug);
- my $leibcon = EIBConnection->EIBSocketURL($eib_url) or return("Error opening con: $!");
- if ($leibcon->EIBOpenT_Group(str2addr($dst),1) == -1) { return("Error opening group: $!"); }
- my $res=$leibcon->EIBSendAPDU($bytes);
- $leibcon->EIBClose();
- return $res;
-}
-
-# addr2str: Convert an integer to an EIB address string, in the form "1/2/3" or "1.2.3"
-sub addr2str {
- my $a = $_[0];
- my $b = $_[1] || 0; # 1 if local (group) address, else physical address
- my $str ;
- if ($b == 1) { # logical address used
- $str = sprintf "%d/%d/%d", ($a >> 11) & 0xf, ($a >> 8) & 0x7, $a & 0xff;
- }
- else { # physical address used
- $str = sprintf "%d.%d.%d", $a >> 12, ($a >> 8) & 0xf, $a & 0xff;
- }
- return $str;
-}
-
-# str2addr: Convert an EIB address string in the form "1/2/3" or "1.2.3" to an integer
-sub str2addr {
- my $str = $_[0];
- if ($str =~ /(\d+)\/(\d+)\/(\d+)/) { # logical address
- return ($1 << 11) | ($2 << 8) | $3;
- } elsif ($str =~ /(\d+)\.(\d+)\.(\d+)/) { # physical address
- return ($1 << 12) | ($2 << 8) | $3;
- } else {
- #bad
- return;
- }
-}
-
-sub update_rrd {
- my ($key,$suffix,$value,$valtype,$stephours,$rrasteps) = @_;
- return unless defined $value;
- $valtype = "GAUGE" unless $valtype;
- $stephours = 24 unless $stephours;
-
- if (!-d $rrd_dir) { mkdir($rrd_dir); }
- if (!-e $rrd_dir . $key . $suffix .'.rrd') {
- # Checkvalue-type for boundries?
- # Create RRD
- if ($valtype eq "GAUGE"){
- my $heartbeat = $rrd_interval * 3;
- $daemon_config{$key}{'rra_1_interval_rows'} = $rra1_row unless $daemon_config{$key}{'rra_1_interval_rows'};
- $daemon_config{$key}{'rra_5_interval_rows'} = $rra5_row unless $daemon_config{$key}{'rra_5_interval_rows'};
- $daemon_config{$key}{'rra_15_interval_rows'} = $rra15_row unless $daemon_config{$key}{'rra_15_interval_rows'};
- $daemon_config{$key}{'rra_180_interval_rows'} = $rra180_row unless $daemon_config{$key}{'rra_180_interval_rows'};
- RRDs::create($rrd_dir.$key.$suffix .'.rrd',
- '--step' => $rrd_interval,
- 'DS:value:'.$valtype.':'.$heartbeat.':-55:255000',
- 'RRA:AVERAGE:0.5:1:'.$daemon_config{$key}{'rra_1_interval_rows'},'RRA:AVERAGE:0.5:5:'.$daemon_config{$key}{'rra_5_interval_rows'},'RRA:AVERAGE:0.5:15:'.$daemon_config{$key}{'rra_15_interval_rows'},'RRA:AVERAGE:0.5:180:'.$daemon_config{$key}{'rra_180_interval_rows'},
- 'RRA:MIN:0.5:1:'.$daemon_config{$key}{'rra_1_interval_rows'},'RRA:MIN:0.5:5:'.$daemon_config{$key}{'rra_5_interval_rows'},'RRA:MIN:0.5:15:'.$daemon_config{$key}{'rra_15_interval_rows'},'RRA:MIN:0.5:180:'.$daemon_config{$key}{'rra_180_interval_rows'},
- 'RRA:MAX:0.5:1:'.$daemon_config{$key}{'rra_1_interval_rows'},'RRA:MAX:0.5:5:'.$daemon_config{$key}{'rra_5_interval_rows'},'RRA:MAX:0.5:15:'.$daemon_config{$key}{'rra_15_interval_rows'},'RRA:MAX:0.5:180:'.$daemon_config{$key}{'rra_180_interval_rows'});
- if (RRDs::error) {
- LOGGER('INFO',"Create RRDs failed for $key$suffix :".RRDs::error);
- } else {
- LOGGER('INFO',"Created RRD for $key$suffix");
- }
- }
- elsif ($valtype eq "COUNTER"){
- $rrasteps = 7 unless $rrasteps;
- RRDs::create ($rrd_dir.$key.$suffix .'.rrd',
- 'DS:value:'.$valtype.':'.(($stephours*3600)+600).':0:10000000000',
- 'RRA:AVERAGE:0.5:1:1826', 'RRA:AVERAGE:0.5:'.$rrasteps.':1300',
- 'RRA:MIN:0.5:1:1826', 'RRA:MIN:0.5:'.$rrasteps.':1300',
- 'RRA:MAX:0.5:1:1826', 'RRA:MAX:0.5:'.$rrasteps.':1300',
- '-s '.($stephours*3600));
- if (RRDs::error) {
- LOGGER('INFO',"Create RRDs failed for $key$suffix :".RRDs::error);
- } else {
- LOGGER('INFO',"Created RRD for $key$suffix");
- }
- }
- }
-
- # Update values
- $value = int($stephours*3600*$value) if ($valtype eq "COUNTER");
- RRDs::update($rrd_dir.$key.$suffix.'.rrd','N:'.$value);
-
- if (RRDs::error) {
- LOGGER('INFO',"Update of RRDs failed for $key$suffix/$value:".RRDs::error);
- # FIXME: Check if error comes from update-value or from rrd-file!
- #rename ($rrd_dir.$key.$suffix.'.rrd',$rrd_dir.$key.$suffix.'.rrd.old');
- } else {
- LOGGER('DEBUG',"Updated RRD for $key$suffix/$value");
- }
-}
-
-
-sub decode_vbusmonitor{
- my $buf = shift;
- my %msg;
- my @data;
- my ($type, $src, $dst, $drl, $bytes) = unpack("CnnCa*", $buf);
- @data = unpack ("C" . bytes::length($bytes), $bytes);
-
- my $apci;
-
- # For mapping between APCI symbols and values, not fully implemented!
- my @apcicodes = qw (A_GroupValue_Read A_GroupValue_Response A_GroupValue_Write
- A_PhysicalAddress_Write A_PhysicalAddress_Read A_PhysicalAddress_Response
- A_ADC_Read A_ADC_Response A_Memory_Read A_Memory_Response A_Memory_Write
- A_UserMemory A_DeviceDescriptor_Read A_DeviceDescriptor_Response A_Restart
- A_OTHER); # not fully implemented
- my @tpducodes = qw(T_DATA_XXX_REQ T_DATA_CONNECTED_REQ T_DISCONNECT_REQ T_ACK);
-
- $msg{'repeated'} = (($type & 0x20) >> 5) ^ 0b01;
- # priority class b00, b01, b10, b11
- my @prioclasses = qw(system alarm high low);
- $msg{'class'} = @prioclasses[($type & 0xC) >> 2];
-
- #DRL
- $msg{'rcount'} = ($drl & 0x70)>>4;
- $msg{'datalen'} = ($drl & 0x0F);
- # FIXME: this is crap!
- #$msg{'tpdu_type'} = $tpducodes[($data[0] & 0xC0)>>6];
- if (@data >= 1) {
- if (($data[0] & 0xFC) == 0) {
- $msg{'tpdu_type'} = "T_DATA_XXX_REQ";
- $msg{'apci'} = @apcicodes[(($data[0] & 0x03)<<2) | (($data[1] & 0xC0)>>6)]; }
- if ($data[0] == 0x80) { $msg{'tpdu_type'} = "T_CONNECT_REQ"; }
- if ($data[0] == 0x81) { $msg{'tpdu_type'} = "T_DISCONNECT_REQ"; }
- if (($data[0] & 0xC3) == 0xC2) { $msg{'tpdu_type'} = "T_ACK"; }
- if (($data[0] & 0xC3) == 0xC3) { $msg{'tpdu_type'} = "T_NACK"; }
- if (($data[0] & 0xC0) == 0x40) {
- $msg{'tpdu_type'} = "T_DATA_CONNECTED_REQ";
- $msg{'apci'} = @apcicodes[(($data[0] & 0x03)<<2) | (($data[1] & 0xC0)>>6)]; }
- }
-
- $msg{'sequence'} = ($data[0] & 0x3C)>>2;
- if ($msg{'tpdu_type'} eq "T_DATA_XXX_REQ" and $msg{'datalen'} == 1) { # 6bit only
- $msg{'data'} = sprintf("%02X", ($data[1] & 0x3F));
- } elsif ($msg{'tpdu_type'} eq "T_DATA_XXX_REQ" and $msg{'datalen'} > 1) {
- for (my $i=2; $i<= $msg{'datalen'}; $i++) {
- $msg{'data'} = $msg{'data'} . sprintf("%02X ", ($data[$i]));
- }
- } else {
- #LOGGER('DEBUG',"OTHER R:$msg{'repeated'} P:$msg{'class'} Hops:$msg{'rcount'} T:$msg{'tpdu_type'} Seq:$msg{'sequence'} A:$msg{'apci'} src: $msg{'src'} dst: $msg{'dst'} len: $msg{'datalen'} data: @data");
- }
- $msg{'data'} = trim($msg{'data'});
- $msg{'src'} = addr2str($src);
- $msg{'dst'} = addr2str($dst, $drl>>7);
- $msg{'value'} = decode_dpt($msg{'dst'},$msg{'data'});
- LOGGER('DEBUG',"R:$msg{'repeated'} P:$msg{'class'} Hops:$msg{'rcount'} T:$msg{'tpdu_type'} Seq:$msg{'sequence'} A:$msg{'apci'} src: $msg{'src'} dst: $msg{'dst'} len: $msg{'datalen'} data: $msg{'data'} ($msg{'value'})");
-
- #$msg{'data'} = \@data;
- $msg{'buf'} = unpack ("H*", $buf);
- return %msg;
-}
-
-
-sub init_udpsock {
- if ($daemon_config{''}{'udp_ip'} and $daemon_config{''}{'udp_port'}) {
- $udp_sock = IO::Socket::INET->new(Proto=>"udp",PeerPort=>$daemon_config{''}{'udp_port'},PeerAddr=>$daemon_config{''}{'udp_ip'}) or LOGGER('WARN',"Can't create UDP socket to send: $@)");
- }
-}
-
-
-
-sub plugin_log ($$) {
- my $name = shift;
- my $msg = shift;
- LOGGER('DEBUG',"Plugin LOG $name -> $msg");
- open PLUGIN_LOG, ">>$plugin_logfile"or print "Can't write to file '$plugin_logfile' [$!]\n"; # writeout to log here
- print PLUGIN_LOG getISODateStamp .",$name,$msg\n";
- close PLUGIN_LOG;
-}
-
-=pod
-
-=head1 NAME
-
-WireGate Daemon
-
-=head1 SYNOPSIS
-
-daemon to handle gateway/communication-functions
-
-=head1 CREDITS
-
-Parts copyright by Martin Koegler from bcusdk/eibd (GPL)
-Parts copyright by various from misterhouse (GPL)
-
-=head1 HISTORY
-
-2008-12-09 Initial versions of wg-ow2eib.pl and wg-eiblis.pl
-see SVN
-
-=cut
\ No newline at end of file
Copied: tools/knxd/usr/sbin/knxd.pl (from rev 1507, tools/ebus/knxd/usr/sbin/knxd.pl)
===================================================================
--- tools/knxd/usr/sbin/knxd.pl (rev 0)
+++ tools/knxd/usr/sbin/knxd.pl 2013-03-09 12:09:04 UTC (rev 1559)
@@ -0,0 +1,1122 @@
+#!/usr/bin/perl -w
+# KNX Daemon - handling WireGate-Plugins and EIB
+# based on wiregated.pl by Michael Markstaller
+#
+# Cleanup and partially rewritten by M.Hirsch
+# http://knx-user-forum.de -> JuMi2006
+#
+# This program 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 (at your option)
+# any later version.
+#
+# This program 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.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+
+use strict;
+use Math::Round;
+use Math::BaseCalc;
+use RRDs;
+use Getopt::Std;
+use Time::HiRes qw ( time alarm sleep usleep gettimeofday );
+getopts("dp:c:e:o:", \my %opts);
+use IO::Socket;
+use IO::Select;
+use FileHandle;
+use Proc::PID::File;
+# fork daemon
+use Proc::Daemon;
+Proc::Daemon::Init unless $opts{d};
+#use xPL::Client;
+use EIBConnection;
+use feature "switch";
+use File::Basename;
+use DB_File;
+
+no warnings 'uninitialized';
+
+sub LOGGER;
+
+# Options
+while ((my $key, my $value) = each %opts) {
+ print "opt $key = $value\n" if ($opts{d});
+}
+
+# PID File-handling
+if ($opts{p} and Proc::PID::File->running()) {
+ LOGGER("WARN","Already running");
+ die();
+ }
+
+# Config files
+# global
+my $config;
+if ($opts{c}) {
+ LOGGER("INFO","Config-File is: $opts{c}");
+ $config = $opts{c};
+ } else {$config = "/etc/knxd/knxd.conf" }
+
+# eibga
+my $eib_config;
+if ($opts{c}) {
+ LOGGER("INFO","eibga-File is: $opts{e}");
+ $eib_config = $opts{e};
+ } else {$eib_config = "/etc/knxd/eibga.conf" }
+
+# Read config #
+my %daemon_config;
+my $lastreadtime = 0;
+my %eibgaconf;
+my $udp_sock;
+my %ga_to_ow;
+my @eibga_types = qw (temp hum moisthum present light volt curr ch0 ch1 ch2 ch3 ch4 ch5 ch6 ch7 countA countB );
+
+if ((stat($config))[9] > $lastreadtime or (stat($eib_config))[9] > $lastreadtime) {
+ if (-e $config) {
+ LOGGER('INFO',"*** reading global config");
+ my_read_cfg ($config, \%daemon_config);
+ $l...
[truncated message content] |