From ee3e271ab6c58128392a978204154fa7949fc2bc Mon Sep 17 00:00:00 2001 From: andi291 <> Date: Fri, 15 May 2015 18:46:52 +0000 Subject: [PATCH] Various modifications according the following thread: http://forum.fhem.de/index.php/topic,34578.0.html - Added / modified the following DPT: dpt10 dpt10_no_seconds, dpt12, dpt14, dpt16 - Fixed log-spam - implemented userReadings (event-on-*) git-svn-id: https://svn.fhem.de/fhem/trunk@8584 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/FHEM/10_EIB.pm | 267 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 223 insertions(+), 44 deletions(-) diff --git a/fhem/FHEM/10_EIB.pm b/fhem/FHEM/10_EIB.pm index bb636fb68..f726ef38c 100644 --- a/fhem/FHEM/10_EIB.pm +++ b/fhem/FHEM/10_EIB.pm @@ -70,6 +70,7 @@ my %eib_dpttypes = ( # Time of Day "dpt10" => {"CODE"=>"dpt10", "UNIT"=>""}, + "dpt10_no_seconds" => {"CODE"=>"dpt10_ns", "UNIT"=>""}, "time" => {"CODE"=>"dpt10", "UNIT"=>""}, # Date @@ -77,10 +78,16 @@ my %eib_dpttypes = ( "date" => {"CODE"=>"dpt11", "UNIT"=>""}, # 4-Octet unsigned value (handled as dpt7) - "dpt12" => {"CODE"=>"dpt7", "UNIT"=>""}, + "dpt12" => {"CODE"=>"dpt12", "UNIT"=>""}, # 4-Octet single precision float "dpt14" => {"CODE"=>"dpt14", "UNIT"=>""}, + + # 14-Octet String + "dpt16" => {"CODE"=>"dpt16", "UNIT"=>""}, + + + ); @@ -97,9 +104,9 @@ EIB_Initialize($) $hash->{DefFn} = "EIB_Define"; $hash->{UndefFn} = "EIB_Undef"; $hash->{ParseFn} = "EIB_Parse"; - $hash->{AttrList} = "IODev do_not_notify:1,0 ignore:0,1 dummy:1,0 showtime:1,0 loglevel:0,1,2,3,4,5,6 model:" - . join(",", keys %eib_dpttypes); - + $hash->{AttrList} = "IODev do_not_notify:1,0 ignore:0,1 dummy:1,0 showtime:1,0 loglevel:0,1,2,3,4,5,6 ". + "$readingFnAttributes " . + "model:".join(",", keys %eib_dpttypes); } @@ -164,7 +171,7 @@ EIB_SetState($$$$) Log(5,"EIB setState tim: $tim vt: $vt val: $val"); $val = $1 if($val =~ m/^(.*) \d+$/); - return "Undefined value $val" if(!defined($eib_c2b{$val})); + #return "Undefined value $val" if(!defined($eib_c2b{$val})); return undef; } @@ -216,7 +223,8 @@ EIB_Set($@) return "groupnr $groupnr not known." if(!$hash->{CODE}{$groupnr}); my $v = join(" ", @a); - Log GetLogLevel($name,2), "EIB set $v"; + #Log GetLogLevel($name,2), "EIB set $v"; + Log 5, "EIB set $v"; (undef, $v) = split(" ", $v, 2); # Not interested in the name... if($value eq "raw" && defined($arg1)) { @@ -232,7 +240,15 @@ EIB_Set($@) } my $groupcode = $hash->{CODE}{$groupnr}; - IOWrite($hash, "B", "w" . $groupcode . $c); + #IOWrite($hash, "B", "w" . $groupcode . $c); + my $model = $attr{$name}{"model"}; + my $code = $eib_dpttypes{"$model"}{"CODE"}; + if ($code eq 'dpt7') { + IOWrite($hash, "B", "b" . $groupcode . $c); + } + else { + IOWrite($hash, "B", "w" . $groupcode . $c); + } ########################################### # Delete any timer for on-for_timer @@ -285,13 +301,20 @@ EIB_Set($@) # Look for all devices with the same code, and set state, timestamp my $code = "$hash->{GROUP}"; my $tn = TimeNow(); - foreach my $n (keys %{ $modules{EIB}{defptr}{$code} }) { + #foreach my $n (keys %{ $modules{EIB}{defptr}{$code} }) { + + # my $lh = $modules{EIB}{defptr}{$code}{$n}; + # $lh->{CHANGED}[0] = $v; + # $lh->{STATE} = $v; + # $lh->{READINGS}{state}{TIME} = $tn; + # $lh->{READINGS}{state}{VAL} = $v; - my $lh = $modules{EIB}{defptr}{$code}{$n}; - $lh->{CHANGED}[0] = $v; - $lh->{STATE} = $v; - $lh->{READINGS}{state}{TIME} = $tn; - $lh->{READINGS}{state}{VAL} = $v; + # readingsSingleUpdate($lh,"state",$v,1); + #} + + my $defptr = $modules{EIB}{defptr}{$code}; + foreach my $n (keys %{ $defptr }) { + readingsSingleUpdate($defptr->{$n}, "state", $v, 1); } return $ret; } @@ -340,14 +363,17 @@ EIB_Parse($$) # parse/translate by datapoint type $v = EIB_ParseByDatapointType($lh,$n,$rawv); - $lh->{CHANGED}[0] = $v; - $lh->{STATE} = $v; + #$lh->{CHANGED}[0] = $v; + #$lh->{STATE} = $v; $lh->{RAWSTATE} = $rawv; $lh->{LASTGROUP} = $dev; - $lh->{READINGS}{state}{TIME} = TimeNow(); - $lh->{READINGS}{state}{VAL} = $v; - Log 2, "EIB $n $v"; - + #$lh->{READINGS}{state}{TIME} = TimeNow(); + #$lh->{READINGS}{state}{VAL} = $v; + + readingsSingleUpdate($lh,"state",$v,1); + + Log 5, "EIB $n $v"; + push(@list, $n); $found = 1; } @@ -383,6 +409,7 @@ EIB_EncodeByDatapointType($$$) my $code = $eib_dpttypes{"$model"}{"CODE"}; my $unit = $eib_dpttypes{"$model"}{"UNIT"}; my $transval = undef; + my $adjustment = $eib_dpttypes{"$model"}{"ADJUSTMENT"}; Log(4,"EIB encode $value for $name model: $model dpt: $code unit: $unit"); @@ -398,23 +425,32 @@ EIB_EncodeByDatapointType($$$) { my $fullval = sprintf("00%.2x",$value); $transval = $fullval; + if($adjustment eq "255") { + $transval = ($fullval / 2.55); + $transval = sprintf("%.0f",$transval); + } else { + $transval = $fullval; + } Log(5,"EIB $code encode $value = $fullval translated: $transval"); } elsif($code eq "dpt9") { - my $sign = $value<0?-1:1; - my $absval = abs($value); - my $exp = $absval==0?0:int(log($absval)/log(2)); - my $mant = $absval / (2**$exp) *100; - $mant = ((~($mant+1))&0x07FF) if($sign<0); + #my $sign = $value<0?-1:1; + #my $absval = abs($value); + #my $exp = $absval==0?0:int(log($absval)/log(2)); + #my $mant = $absval / (2**$exp) *100; + #$mant = ((~($mant+1))&0x07FF) if($sign<0); - my $fullval = $mant+2048*$exp; - $fullval |=0x8000 if($sign<0); + #my $fullval = $mant+2048*$exp; + #$fullval |=0x8000 if($sign<0); - $transval = sprintf("00%.4x",$fullval); + #$transval = sprintf("00%.4x",$fullval); - Log(5,"EIB $code encode $value = $fullval sign: $sign mant: $mant exp: $exp translated: $transval"); + #Log(5,"EIB $code encode $value = $fullval sign: $sign mant: $mant exp: $exp translated: $transval"); + + $transval = encode_dpt9($value); + Log(5,"EIB $code encode $value translated: $transval"); } elsif ($code eq "dpt10") { @@ -423,7 +459,36 @@ EIB_EncodeByDatapointType($$$) $year+=1900; $mon++; - my $fullval = $secs + ($mins<<8) + ($hours<<16); + # calculate offset for weekday + if ($wday eq "0") { + $wday = 7; + } + my $hoffset = 32*$wday; + + #my $fullval = $secs + ($mins<<8) + ($hours<<16); + my $fullval = $secs + ($mins<<8) + (($hoffset + $hours)<<16); + + $transval = sprintf("00%.6x",$fullval); + + Log(5,"EIB $code encode $value = $fullval hours: $hours mins: $mins secs: $secs translated: $transval"); + + } elsif ($code eq "dpt10_ns") + { + # set current Time + my ($secs,$mins,$hours,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); + my $secZero = 0; + $year+=1900; + $mon++; + + # calculate offset for weekday + if ($wday eq "0") { + $wday = 7; + } + my $hoffset = 32*$wday; + + #my $fullval = $secs + ($mins<<8) + ($hours<<16); + my $fullval = $secZero + ($mins<<8) + (($hoffset + $hours)<<16); + $transval = sprintf("00%.6x",$fullval); Log(5,"EIB $code encode $value = $fullval hours: $hours mins: $mins secs: $secs translated: $transval"); @@ -440,6 +505,18 @@ EIB_EncodeByDatapointType($$$) Log(5,"EIB $code encode $value = $fullval day: $day month: $month year: $year translated: $transval"); + } elsif ($code eq "dpt12") + { + my $fullval = sprintf("00%.8x",$value); + $transval = $fullval; + + Log(5,"EIB $code encode $value = $fullval translated: $transval"); + + } elsif($code eq "dpt14") + { + $transval = encode_dpt14($value); + Log(5,"EIB $code encode $value translated: $transval"); + } elsif ($code eq "dptxx") { } @@ -483,6 +560,11 @@ EIB_ParseByDatapointType($$$) if ($code eq "dpt5") { + if ($value eq "on") + { + $value = "1"; + } + my $dpt5factor = $eib_dpttypes{"$model"}{"factor"}; my $fullval = hex($value); $transval = $fullval; @@ -522,6 +604,17 @@ EIB_ParseByDatapointType($$$) Log(5,"EIB $code parse $value = $fullval hours: $hours mins: $mins secs: $secs translated: $transval"); + } elsif ($code eq "dpt10_ns") + { + # Time + my $fullval = hex($value); + my $hours = ($fullval & 0x1F0000)>>16; + my $mins = ($fullval & 0x3F00)>>8; + my $secs = ($fullval & 0x3F); + $transval = sprintf("%02d:%02d",$hours,$mins); + + Log(5,"EIB $code parse $value = $fullval hours: $hours mins: $mins translated: $transval"); + } elsif ($code eq "dpt11") { # Date @@ -536,22 +629,33 @@ EIB_ParseByDatapointType($$$) Log(5,"EIB $code parse $value = $fullval day: $day month: $month year: $year translated: $transval"); + } elsif ($code eq "dpt12") + { + my $fullval = hex($value); + $transval = $fullval; + + Log(5,"EIB $code parse $value = $fullval translated: $transval"); + } elsif ($code eq "dpt14") # contributed by Olaf - { - # 4 byte single precision float - my $byte0 = hex(substr($value,0,2)); - my $sign = ($byte0 & 0x80) ? -1 : 1; + { + # 4 byte single precision float + my $byte0 = hex(substr($value,0,2)); + my $sign = ($byte0 & 0x80) ? -1 : 1; - my $bytee = hex(substr($value,0,4)); - my $expo = (($bytee & 0x7F80) >> 7) - 127; + my $bytee = hex(substr($value,0,4)); + my $expo = (($bytee & 0x7F80) >> 7) - 127; - my $bytem = hex(substr($value,2,6)); - my $mant = ($bytem & 0x7FFFFF | 0x800000); + my $bytem = hex(substr($value,2,6)); + my $mant = ($bytem & 0x7FFFFF | 0x800000); - $transval = $sign * (2 ** $expo) * ($mant / (1 <<23)); + $transval = $sign * (2 ** $expo) * ($mant / (1 <<23)); - Log(5,"EIB $code parse $value translated: $transval"); - + Log(5,"EIB $code parse $value translated: $transval"); + } elsif ($code eq "dpt16") { + + $transval= decode_dpt16($value); + + Log(5,"EIB $code parse $value translated: $transval"); } elsif ($code eq "dptxx") { } @@ -570,6 +674,23 @@ EIB_ParseByDatapointType($$$) return $value; } +############################# +sub decode_dpt16($) +{ + # 14byte char + my $val = shift; + my $res = ""; + + for (my $i=0;$i<14;$i++) { + my $c = hex(substr($val,$i*2,2)); + if ($c eq 0) { + $i = 14; + } else { + $res .= sprintf("%c", $c); + } + } + return sprintf("%s","$res"); +} ############################# sub eib_hex2name($) @@ -601,6 +722,43 @@ eib_name2hex($) return $r; } +############################# +# 2byte signed float +sub encode_dpt9 { + my $state = shift; + my $data; + my $retVal; + + 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); + + #Log(1,"State: $state Sign: $sign Exp: $exp Mant: $mant Data: $data"); + + $retVal = sprintf("00%.4x",$data); + + return $retVal; +} + +############################# +# 4byte signed float +sub encode_dpt14 { + + my $real = shift; + my $packed_float = pack "f", $real; + my $data = sprintf("%04X", unpack("L", pack("f", $real))); + + #Log(1,"Shift: $real Value: $data"); + + return $data +} 1; @@ -712,14 +870,32 @@ eib_name2hex($) Attributes +