From a50bee7978b8bbde85057cf4a9d90425ae3614d9 Mon Sep 17 00:00:00 2001 From: mgehre Date: Sun, 9 Dec 2012 15:03:06 +0000 Subject: [PATCH] MAX: automatically determine correct IODev git-svn-id: https://fhem.svn.sourceforge.net/svnroot/fhem/trunk/fhem@2303 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- FHEM/00_MAXLAN.pm | 38 +++++++++++++++++++++++++------------- FHEM/10_MAX.pm | 13 ++++++++----- FHEM/14_CUL_MAX.pm | 16 +++++++++++----- 3 files changed, 44 insertions(+), 23 deletions(-) diff --git a/FHEM/00_MAXLAN.pm b/FHEM/00_MAXLAN.pm index 7425db015..f9d61ec5e 100755 --- a/FHEM/00_MAXLAN.pm +++ b/FHEM/00_MAXLAN.pm @@ -150,6 +150,14 @@ MAXLAN_Connect($) #Read initial configuration data MAXLAN_ExpectAnswer($hash,"H:"); MAXLAN_ExpectAnswer($hash,"M:"); + + #We first reset the IODev for all MAX devices using this MAXLAN as a backend. + #Parsing the "C:" responses later on will set IODev correctly again. + #This effectively removes IODev from all devices that are not longer paired to our Cube. + foreach (%{$modules{MAX}{defptr}}) { + $modules{MAX}{defptr}{$_}{IODev} = undef if($modules{MAX}{defptr}{$_}{IODev} == $hash); + } + my $rmsg; do { @@ -209,7 +217,7 @@ MAXLAN_Set($@) my $time = time()-946684774; my $rmsg = "v:".$timezones.",".sprintf("%08x",$time); my $ret = MAXLAN_Write($hash,$rmsg, "A:"); - Dispatch($hash, "MAX,CubeClockState,$hash->{rfaddr},1", {RAWMSG => $rmsg}) if(!$ret); + Dispatch($hash, "MAX,1,CubeClockState,$hash->{rfaddr},1", {RAWMSG => $rmsg}) if(!$ret); return $ret; }elsif($setting eq "factoryReset") { @@ -435,9 +443,9 @@ MAXLAN_Parse($$) $hash->{cubeTimeDifference} = $difference; } - Dispatch($hash, "MAX,define,$hash->{rfaddr},Cube,$hash->{serial},0,1", {RAWMSG => $rmsg}); - Dispatch($hash, "MAX,CubeConnectionState,$hash->{rfaddr},1", {RAWMSG => $rmsg}); - Dispatch($hash, "MAX,CubeClockState,$hash->{rfaddr},$clockset", {RAWMSG => $rmsg}); + Dispatch($hash, "MAX,1,define,$hash->{rfaddr},Cube,$hash->{serial},0,1", {RAWMSG => $rmsg}); + Dispatch($hash, "MAX,1,CubeConnectionState,$hash->{rfaddr},1", {RAWMSG => $rmsg}); + Dispatch($hash, "MAX,1,CubeClockState,$hash->{rfaddr},$clockset", {RAWMSG => $rmsg}); Log $ll5, "MAXLAN_Parse: Got hello, connection ip $args[4], duty cycle $dutycycle, freememory $freememory, clockset $clockset"; } elsif($cmd eq 'M') { @@ -482,7 +490,6 @@ MAXLAN_Parse($$) $hash->{devices}[-1]->{serial} = $groupsdevices[$i+2]; $hash->{devices}[-1]->{name} = $groupsdevices[$i+3]; $hash->{devices}[-1]->{groupid} = $groupsdevices[$i+4]; - #Dispatch($hash, "MAX,define,$hash->{devices}[-1]->{addr},$device_types{$hash->{devices}[-1]->{type}},$hash->{devices}[-1]->{serial},$hash->{devices}[-1]->{groupid},1", {RAWMSG => $rmsg}); } #Log $ll5, "Got Metadata, hash: ".Dumper($hash); @@ -502,10 +509,10 @@ MAXLAN_Parse($$) $len = $len+1; #The len field itself was not counted - Dispatch($hash, "MAX,define,$addr,$device_types{$devicetype},$serial,$groupid,1", {RAWMSG => $rmsg}); + Dispatch($hash, "MAX,1,define,$addr,$device_types{$devicetype},$serial,$groupid,1", {RAWMSG => $rmsg}); if($len != length($bindata)) { - Dispatch($hash, "MAX,Error,$addr,Parts of configuration are missing", {RAWMSG => $rmsg}); + Dispatch($hash, "MAX,1,Error,$addr,Parts of configuration are missing", {RAWMSG => $rmsg}); return "Invalid C: response, len does not match"; } @@ -527,7 +534,7 @@ MAXLAN_Parse($$) $windowopentemp=$windowopentemp/2.0; $windowopendur=$windowopendur*5; Log $ll5, "comfortemp $comforttemp, ecotemp $ecotemp, boostValve $boostValve, boostDuration $boostDuration, tempoffset $tempoffset, $minsetpointtemp minsetpointtemp, maxsetpointtemp $maxsetpointtemp, windowopentemp $windowopentemp, windowopendur $windowopendur"; - Dispatch($hash, "MAX,ThermostatConfig,$addr,$ecotemp,$comforttemp,$boostValve,$boostDuration,$tempoffset,$maxsetpointtemp,$minsetpointtemp,$windowopentemp,$windowopendur", {RAWMSG => $rmsg}); + Dispatch($hash, "MAX,1,ThermostatConfig,$addr,$ecotemp,$comforttemp,$boostValve,$boostDuration,$tempoffset,$maxsetpointtemp,$minsetpointtemp,$windowopentemp,$windowopendur", {RAWMSG => $rmsg}); }elsif($devicetype == 4){#ShutterContact Log 2, "ShutterContact send some configuration, but none was expected" if($len > 18); @@ -536,7 +543,7 @@ MAXLAN_Parse($$) } #Clear Error - Dispatch($hash, "MAX,Error,$addr", {RAWMSG => $rmsg}); + Dispatch($hash, "MAX,1,Error,$addr", {RAWMSG => $rmsg}); #Check if it is already recorded in devices my $found = 0; @@ -576,9 +583,9 @@ MAXLAN_Parse($$) if(!$shash) { Log 2, "Got List response for undefined device with addr $addr"; }elsif($shash->{type} eq "HeatingThermostat" or $shash->{type} eq "WallMountedThermostat"){ - Dispatch($hash, "MAX,ThermostatState,$addr,$payload", {RAWMSG => $rmsg}); + Dispatch($hash, "MAX,1,ThermostatState,$addr,$payload", {RAWMSG => $rmsg}); }elsif($shash->{type} eq "ShutterContact"){ - Dispatch($hash, "MAX,ShutterContactState,$addr,$payload", {RAWMSG => $rmsg}); + Dispatch($hash, "MAX,1,ShutterContactState,$addr,$payload", {RAWMSG => $rmsg}); }else{ Log 2, "Got status for unimplemented device type $shash->{type}"; } @@ -594,7 +601,7 @@ MAXLAN_Parse($$) } my ($type, $addr, $serial) = unpack("CH6a[10]", decode_base64($args[0])); Log 2, "Paired new device, type $device_types{$type}, addr $addr, serial $serial"; - Dispatch($hash, "MAX,define,$addr,$device_types{$type},$serial,0,1", {RAWMSG => $rmsg}); + Dispatch($hash, "MAX,1,define,$addr,$device_types{$type},$serial,0,1", {RAWMSG => $rmsg}); #After a device has been paired, it automatically appears in the "L" and "C" commands, MAXLAN_RequestConfiguration($hash,$addr); @@ -726,7 +733,12 @@ MAXLAN_RemoveDevice($$) { my ($hash,$addr) = @_; #This does a factoryReset on the Device - return MAXLAN_Write($hash,"t:1,1,".encode_base64(pack("H6",$addr),""), "A:"); + my $ret = MAXLAN_Write($hash,"t:1,1,".encode_base64(pack("H6",$addr),""), "A:"); + if(!defined($ret)) { #success + #The device is not longer accessable by the Cube + $modules{MAX}{defptr}{$addr}{IODev} = undef; + } + return $ret; } 1; diff --git a/FHEM/10_MAX.pm b/FHEM/10_MAX.pm index 3adf737da..6d94706ac 100755 --- a/FHEM/10_MAX.pm +++ b/FHEM/10_MAX.pm @@ -95,7 +95,6 @@ MAX_Define($$) $hash->{type} = $type; $hash->{addr} = $addr; $hash->{STATE} = "waiting for data"; - $hash->{usingCube} = 0; $modules{MAX}{defptr}{$addr} = $hash; $hash->{internals}{interfaces} = $interfaces{$type}; @@ -306,7 +305,9 @@ sub MAX_Parse($$) { my ($hash, $msg) = @_; - my ($MAX,$msgtype,$addr,@args) = split(",",$msg); + my ($MAX,$isToMe,$msgtype,$addr,@args) = split(",",$msg); + #$isToMe is 1 if the message was direct at the device $hash, and 0 + #if we just snooped a message directed at a different device (by CUL_MAX). return if($MAX ne "MAX"); Log 5, "MAX_Parse $msg"; @@ -327,6 +328,9 @@ MAX_Parse($$) } } + #if $isToMe is true, then the message was directed at device $hash, thus we can also use it for sending + $shash->{IODev} = $hash if($isToMe); + if($msgtype eq "define"){ my $devicetype = $args[0]; Log 1, "Device changed type from $shash->{type} to $devicetype" if($shash->{type} ne $devicetype); @@ -336,7 +340,6 @@ MAX_Parse($$) $shash->{serial} = $serial; } $shash->{groupid} = $args[2]; - $shash->{usingCube} = $args[3]; $shash->{IODev} = $hash; } elsif($msgtype eq "ThermostatState") { @@ -444,9 +447,9 @@ MAX_Parse($$) #with unknown meaning plus the data of a State broadcast from the same device #For HeatingThermostats, it does not contain the last three "until" bytes (or measured temperature) if($shash->{type} ~~ ["HeatingThermostat", "WallMountedThermostat"] ) { - return MAX_Parse($hash, "MAX,ThermostatState,$addr,". substr($args[0],2)); + return MAX_Parse($hash, "MAX,$isToMe,ThermostatState,$addr,". substr($args[0],2)); } elsif($shash->{type} eq "ShutterContact") { - return MAX_Parse($hash, "MAX,ShutterContactState,$addr,". substr($args[0],2)); + return MAX_Parse($hash, "MAX,$isToMe,ShutterContactState,$addr,". substr($args[0],2)); } elsif($shash->{type} eq "Cube") { ; #Payload is always "00" } else { diff --git a/FHEM/14_CUL_MAX.pm b/FHEM/14_CUL_MAX.pm index bef031bb1..9a1c0b1c9 100644 --- a/FHEM/14_CUL_MAX.pm +++ b/FHEM/14_CUL_MAX.pm @@ -138,9 +138,15 @@ CUL_MAX_Parse($$) $dst = lc($dst); my $msgType = exists($msgId2Cmd{$msgTypeRaw}) ? $msgId2Cmd{$msgTypeRaw} : $msgTypeRaw; Log 5, "CUL_MAX_Parse: len $len, msgcnt $msgcnt, msgflag $msgFlag, msgTypeRaw $msgType, src $src, dst $dst, groupid $groupid, payload $payload"; + my $isToMe = ($dst eq $shash->{addr}) ? 1 : 0; # $isToMe is true if that packet was directed at us + if(exists($msgId2Cmd{$msgTypeRaw})) { + if($msgType eq "Ack") { - Dispatch($shash, "MAX,Ack,$src,$payload", {RAWMSG => $rmsg}); + Dispatch($shash, "MAX,$isToMe,Ack,$src,$payload", {RAWMSG => $rmsg}); + + return undef if(!$isToMe); + my $i = 0; while ($i < @waitForAck) { my $packet = $waitForAck[$i]; @@ -154,7 +160,7 @@ CUL_MAX_Parse($$) } } elsif($msgType eq "TimeInformation") { - if($dst eq $shash->{addr}) { + if($isToMe) { #This is a request for TimeInformation send to us Log 5, "Got request for TimeInformation, sending it"; CUL_MAX_SendTimeInformation($shash, $src); @@ -188,16 +194,16 @@ CUL_MAX_Parse($$) Log 3, "CUL_MAX_Parse: Pairing device $src of type $device_types{$type} with serial $serial"; CUL_MAX_Send($shash, "PairPong", $src, "00"); #TODO: wait for Ack - Dispatch($shash, "MAX,define,$src,$device_types{$type},$serial,0,0", {RAWMSG => $rmsg}); + Dispatch($shash, "MAX,$isToMe,define,$src,$device_types{$type},$serial,0,0", {RAWMSG => $rmsg}); if($device_types{$type} eq "HeatingThermostat" or $device_types{$type} eq "WallMountedThermostat") { #This are the default values that a device has after factory reset or pairing - Dispatch($shash, "MAX,ThermostatConfig,$src,17,21,80,5,0,30.5,4.5,12,15", {RAWMSG => $rmsg}); + Dispatch($shash, "MAX,$isToMe,ThermostatConfig,$src,17,21,80,5,0,30.5,4.5,12,15", {RAWMSG => $rmsg}); } #TODO: send TimeInformation } } elsif($msgType ~~ ["ShutterContactState", "WallThermostatState", "ThermostatState"]) { - Dispatch($shash, "MAX,$msgType,$src,$payload", {RAWMSG => $rmsg}); + Dispatch($shash, "MAX,$isToMe,$msgType,$src,$payload", {RAWMSG => $rmsg}); #Only ShutterContactState needs ack if($msgType eq "ShutterContactState" and $dst eq $shash->{addr}) { CUL_MAX_SendAck($shash,$msgcnt,$dst);