Code:
# Plugin zum verarbeiten aller Funktelegramme von FS20/(K)S300/FHZ/FHT/HMS/EM via CUL
# Version: 0.71 2010-11-20
# - KS300,S300TH-Empfang
# - FS20<->KNX
# Code partially derived from fhem.pl, Copyright: Rudolf Koenig (r dot koenig at koeniglich dot de)
# Aufbau möglichst so, dass man unterhalb der Definitionen nichts ändern muss!
##################
### DEFINITION ###
##################
my $socknum = 1; # Eindeutige Nummer des Sockets fuer das CUL; frei wählbar 0-99
my $cul_dev = "/dev/cul868"; # Adresse / Port CUL/CUN ip:2323
#my $cul_dev = "192.168.1.191:2323"; # Adresse / Port CUN ip:2323
#my $cul_dev = "localhost:2323"; # Adresse / Port CUL/CUN ip:2323
# Eigenen Aufruf-Zyklus setzen (Initialisierung/zyklisches prüfen)
$plugin_info{$plugname.'_cycle'} = 300;
# Gruppenadressen KS300 - leer um Versand zu unterbinden
my $ks300_temp_ga = "14/4/1"; # Gruppenadresse für Temperatur-Istwert DPT9
my $ks300_hum_ga = "14/4/2"; # Gruppenadresse für Luftfeuchte DPT5
my $ks300_wind_ga = "14/4/3"; # Gruppenadresse für Windgeschwindigkeit DPT9
my $ks300_rain_ga = "14/4/4"; # Gruppenadresse für Regenmenge l/qm DPT9
my $ks300_israin_ga = "14/4/5"; # Gruppenadresse für Regen DPT1
my @s300th_temp_ga; # Nicht auskommentieren!
my @s300th_hum_ga; # Nicht auskommentieren!
$s300th_temp_ga[1] = "14/4/6"; # Gruppenadresse für Temperatur-Istwert DPT9 des TH-Sensors mit der Adresse 0
$s300th_hum_ga[1] = "14/4/7"; # Gruppenadresse für Luftfeuchte DPT5 des Sensors mit der Adresse 0
my $debug_log = 1; # Debug-Ausgabe in Plugin-Log
# FS20->KNX
my %fs20_empfang_ga; # Eintrag darf nicht auskommentiert werden, solange nachfolgend keine GA definiert erfolgt kein Empfang
#$fs20_empfang_ga{'1234'}{'01'} = "14/5/100";
# Hauscode 1234, Buttone/Gerät 01 sendet auf EIB-GA 14/5/100
#$fs_empfang_ga{'1234'}{'02'} = "14/5/101";
# usw..
# KNX->FS20
my %fs20_sende_ga; # Eintrag darf nicht auskommentiert werden, solange nachfolgend keine GA definiert erfolgt kein Versand!
#$fs20_sende_ga{'14/5/200'} = "123401"; # HHHHBB - vierstelliger Hauscode + Button
#usw...
#######################
### ENDE DEFINITION ###
#######################
# Hauptverarbeitung
if (!$socket[$socknum] or !$socket[$socknum]->opened or (defined $fh and eof($socket[$socknum]))) { # socket erstellen
$socksel->remove($socket[$socknum]);
undef $socket[$socknum];
if ($cul_dev =~ /^\//) { # local device
sysopen($socket[$socknum], $cul_dev, 0x02 ) # 2 O_RDRW 0x800 | 0x800 O_NONBLOCK
or return ("open of $cul_dev failed: $!");
} else {
$socket[$socknum] = IO::Socket::INET->new(PeerAddr => $cul_dev, Timeout => 2, Blocking => 0)
or return ("open of $cul_dev failed: $!");
}
syswrite($socket[$socknum],"X01\n");
syswrite($socket[$socknum],"l01\n"); # LED on
syswrite($socket[$socknum],"V\n"); # LED on
$socksel->add($socket[$socknum]); # add socket to select
$plugin_socket_subscribe{$socket[$socknum]} = $plugname; # subscribe plugin, damit es bei eintreffenden Daten aufgerufen wird
$plugin_info{$plugname.'_cycle'} = 1; # rerun to subscribe GA's
return "opened CU* $cul_dev on socket $socknum";
} elsif ($fh) { # Readline from cul
while (my $buf = <$fh>) {
next if(!$buf || length($buf) < 2); # Bogus messages
my $bufhex = $buf;
$bufhex =~ s/(.)/sprintf("0x%x ",ord($1))/eg;
chomp $buf;
$buf =~ s/\r//;
my $fn = substr($buf,0,1);
my $len = length($buf);
syswrite($socket[$socknum],"V\n") unless $fn eq "V"; # update watchdog
if($fn eq "F" && $len >= 9) # FS20 F53340311
{
my $hauscode = substr($buf,1,4);
my $button = substr($buf,5,2);
my $val = substr($buf,8,1);
if ($fs20_empfang_ga{$hauscode}{$button}) { # nur an KNX senden wenn GA definiert
knx_write($fs20_empfang_ga{$hauscode}{$button},$val,1);
}
return "Debug FS20 recv: $buf Hauscode: $hauscode Button $button Wert $val";
}
elsif($fn eq "T") # FHT
{
return "Debug FHT recv: $buf \n";
}
elsif($fn eq "H" && $len >= 13) # HMS
{
my $type = hex(substr($buf,6,1));
my $stat = $type > 1 ? hex(substr($buf,7,2)) : hex(substr($buf,5,2));
my $prf = $type > 1 ? "02" : "05";
my $bat = $type > 1 ? hex(substr($buf,5,1))+1 : 1;
my $HA = substr($buf,1,4);
my $values = $type > 1 ? "000000" : substr($buf,7);
# RM100: T3
return "HMS recv: $buf T$type Status $stat P$prf Batt:$bat Code:$HA Val:$values";
}
elsif($fn eq "K" && $len == 15) # KS300
{
my @a = split("", $buf);
my $rain = sprintf("%0.1f", hex("$a[14]$a[11]$a[12]") * 255 / 1000);
my $wnd = sprintf("%0.1f", "$a[9]$a[10].$a[7]" + 0);
my $hum = sprintf( "%02d", "$a[8]$a[5]" + 0);
my $tmp = sprintf("%0.1f", ("$a[6]$a[3].$a[4]"+ 0)*
(($a[1] & 0xC) ? -1 : 1));
my $ir = ((hex($a[1]) & 2)) ? 1 : 0;
my $val = "T: $tmp H: $hum W: $wnd R: $rain IR: $ir";
# Add $ks300_interval
knx_write($ks300_temp_ga,$tmp,9);
knx_write($ks300_hum_ga,$hum,5);
knx_write($ks300_wind_ga,$wnd,9);
knx_write($ks300_rain_ga,$rain,9);
knx_write($ks300_israin_ga,$ir,1);
return "KS300 recv: $val";
}
elsif($fn eq "K" && $len == 9) # S300TH
{
my @a = split("", $buf);
my $addr = $a[2]+(hex($a[1])&7);
my $hum = sprintf( "%02d", "$a[7]$a[8].$a[5]" + 0);
my $tmp = sprintf("%0.1f", ("$a[6]$a[3].$a[4]"+ 0)*
((hex($a[1]) & 8) ? -1 : 1));
my $val = "Addr: $addr T: $tmp H: $hum";
# Add $ks300_interval
if ($s300th_temp_ga[$addr]) {
knx_write($s300th_temp_ga[$addr],$tmp,9);
}
if ($s300th_hum_ga[$addr]) {
knx_write($s300th_hum_ga[$addr],$hum,5);
}
return "S300TH recv: $val : $buf :";
}
elsif($fn eq "E" && $len >= 11)
{
# For EM:
# Ettaacc111122223333
# tt:type 01=EM-1000s, 02=EM-100-EM, 03=1000GZ
# aa:address, depending on the type above 01:01-04, 02:05-08, 03:09-12
# cc:counter, will be incremented by one for each message
# 1111: cumulated value
# 2222: last value (Not set for type 2)
# 3333: top value (Not set for type 2)
return "Debug EM recv: $buf";
}
elsif($fn eq "?" or $fn eq "") # empty/error-message
{
return "Unknown message $buf! ($len) $bufhex";
}
elsif($fn eq "V") # watchdog
{
$plugin_info{$plugname.'_watchdog'} = time();
return; # "Watchdog $buf! ($len)";
}
else {
return "Unknown message $buf! ($len) $bufhex";
}
}
} elsif (%msg) {
# write from KNX -> send here
# There is no checking of 1% bandwidth rule here! If saturated it gets lost/not sent!
if ($msg{'apci'} eq "A_GroupValue_Write" and $fs20_sende_ga{$msg{'dst'}}) {
my $cmd = ($msg{'data'}+0) ? "11" : "00";
my $culcmd = "F".$fs20_sende_ga{$msg{'dst'}}.$cmd."\n";
syswrite($socket[$socknum],$culcmd);
}
} else {
# cyclic/init/change
# subscribe GA's
while( my ($k, $v) = each(%fs20_sende_ga) ) {
# Plugin an Gruppenadresse "anmelden"
$plugin_subscribe{$k}{$plugname} = 1;
}
my $res = syswrite($socket[$socknum],"X01\n");
$res = syswrite($socket[$socknum],"V\n");
if (!$res or (($plugin_info{$plugname.'_watchdog'} + $plugin_info{$plugname.'_cycle'}+10) < time())) {
$socksel->remove($socket[$socknum]);
$socket[$socknum]->close();
undef $socket[$socknum];
$plugin_info{$plugname.'_cycle'} = 1;
return "CU* $cul_dev check failed - disconnect";
}
return;
return("CUL return dunno R1 $res T R2 ");
}
Programmiert wird mit dfu-programmer.
Code:
wget http://www.koeniglich.de/culfw/culfw-1.37.tar.gz tar -xzf culfw-1.37.tar.gz apt-get install dfu-programmer dfu-programmer at90usb162 erase dfu-programmer at90usb162 flash culfw-1.37/Devices/CUL/CUL_V2.hex dfu-programmer at90usb162 start
Code:
dfu-programmer atmega32u4 erase dfu-programmer atmega32u4 flash culfw-1.37/Devices/CUL/CUL_V3.hex dfu-programmer atmega32u4 start





Kommentar