2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-01-31 18:59:33 +00:00

MAX: implement deassociate and fake

git-svn-id: https://svn.fhem.de/fhem/trunk@2504 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
mgehre 2013-01-13 14:53:03 +00:00
parent f7578af68d
commit 25da3ea364
2 changed files with 52 additions and 8 deletions

View File

@ -313,7 +313,32 @@ MAX_Set($@)
readingsSingleUpdate($hash, $setting, $args[0], 0);
return ($hash->{IODev}{Send})->($hash->{IODev},"SetDisplayActualTemperature",$hash->{addr},sprintf("%02x",$args[0] ? 4 : 0));
} elsif($setting eq "associate") {
} elsif($setting eq "fake") {
#Resolve first argument to address
return "Invalid number of arguments" if(@args == 0);
my $dest = $args[0];
if(exists($defs{$dest})) {
return "Destination is not a MAX device" if($defs{$dest}{TYPE} ne "MAX");
$dest = $defs{$dest}{addr};
} else {
return "No MAX device with address $dest" if(!exists($modules{MAX}{defptr}{$dest}));
}
if($hash->{type} eq "ShutterContact") {
return "Invalid number of arguments" if(@args != 2);
my $state = $args[1] ? "12" : "10";
return ($hash->{IODev}{Send})->($hash->{IODev},"ShutterContactState",$dest,$state,"06",undef,undef,$hash->{addr});
} elsif($hash->{type} eq "WallMountedThermostat") {
return "Invalid number of arguments" if(@args != 3);
my $desiredTemperature = $args[1];
my $measuredTemperature = $args[2];
return ($hash->{IODev}{Send})->($hash->{IODev},"WallThermostatState",$dest,
sprintf("%02x%02x",int($desiredTemperature*2),int($measuredTemperature*10)),"04",undef,undef,$hash->{addr});
} else {
return "fake does not work for device type $hash->{type}";
}
} elsif($setting ~~ ["associate", "deassociate"]) {
my $dest = $args[0];
if(exists($defs{$dest})) {
return "Destination is not a MAX device" if($defs{$dest}{TYPE} ne "MAX");
@ -325,7 +350,12 @@ MAX_Set($@)
my $destType = MAX_TypeToTypeId($modules{MAX}{defptr}{$dest}{type});
Log 2, "Warning: Device do not have same groupid" if($hash->{groupid} != $modules{MAX}{defptr}{groupid});
Log 5, "Using dest $dest, destType $destType";
return ($hash->{IODev}{Send})->($hash->{IODev},"AddLinkPartner",$hash->{addr},sprintf("%02x%s%02x",$hash->{groupid}, $dest, $destType));
if($setting eq "associate") {
return ($hash->{IODev}{Send})->($hash->{IODev},"AddLinkPartner",$hash->{addr},sprintf("%s%02x", $dest, $destType));
} else {
return ($hash->{IODev}{Send})->($hash->{IODev},"RemoveLinkPartner",$hash->{addr},sprintf("%s%02x", $dest, $destType));
}
} elsif($setting eq "factoryReset") {
@ -356,12 +386,12 @@ MAX_Set($@)
#Create numbers from 4.5 to 30.5
my $templistOffset = join(",",map { sprintf("%2.1f",($_-7)/2) } (0..14));
my $boostDurVal = join(",", values(%boost_durations));
return "$ret associate:$assoclist desiredTemperature:eco,comfort,boost,auto,$templist ecoTemperature:$templist comfortTemperature:$templist measurementOffset:$templistOffset maximumTemperature:$templist minimumTemperature:$templist windowOpenTemperature:$templist windowOpenDuration boostDuration:$boostDurVal boostValveposition decalcification maxValveSetting valveOffset";
return "$ret associate:$assoclist deassociate:$assoclist desiredTemperature:eco,comfort,boost,auto,$templist ecoTemperature:$templist comfortTemperature:$templist measurementOffset:$templistOffset maximumTemperature:$templist minimumTemperature:$templist windowOpenTemperature:$templist windowOpenDuration boostDuration:$boostDurVal boostValveposition decalcification maxValveSetting valveOffset";
} elsif($hash->{type} eq "WallMountedThermostat") {
return "$ret associate:$assoclist displayActualTemperature:0,1 desiredTemperature:eco,comfort,boost,auto,$templist ecoTemperature:$templist comfortTemperature:$templist maximumTemperature:$templist";
return "$ret associate:$assoclist deassociate:$assoclist displayActualTemperature:0,1 desiredTemperature:eco,comfort,boost,auto,$templist ecoTemperature:$templist comfortTemperature:$templist maximumTemperature:$templist";
} elsif($hash->{type} eq "ShutterContact") {
return "$ret associate:$assoclist";
return "$ret associate:$assoclist deassociate:$assoclist";
} else {
return $ret;
}
@ -608,7 +638,12 @@ MAX_Parse($$)
}
} elsif($msgtype eq "Ack") {
#The payload of an Ack is a 2-digit hex number (I just saw it being "01")
#The payload of an Ack is a 2-digit hex number (being "01" for okey and "81" for "invalid command/argument"
if($isToMe and (unpack("C",pack("H*",$args[0])) & 0x80)) {
my $device = $addr;
$device = $modules{MAX}{defptr}{$device}{NAME} if(exists($modules{MAX}{defptr}{$device}));
Log 1, "Device $device answered with: Invalid command/argument";
}
#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" ) {
@ -733,6 +768,12 @@ MAX_Parse($$)
Associating a ShutterContact to a {Heating,WallMounted}Thermostat makes it send message to that device to automatically lower temperature to windowOpenTemperature while the shutter is opened. The thermostat must be associated to the ShutterContact, too, to accept those messages.
Associating HeatingThermostat and WallMountedThermostat makes them sync their desiredTemperature and uses the measured temperature of the
WallMountedThermostat for control.</li>
<li>deassociate &lt;value&gt;<br>
Removes the association set by associate.</li>
<li>fake &lt;device&gt; &lt;parameters...&gt;<br>
Sends a fake state message of this device over the air to &lt;device&gt;. Works only with CUL_MAX as IODev. For ShutterContacts, sends
a ShutterContactState message; &lt;parameters...&gt; must be 0 or 1 for "window closed" or "window opened". For WallMountedThermostats.
sends a WallThermostatState message; &lt;parameters...&gt; must be "$desiredTemperature $measuredTemperature" (both may have one digit after the decimal point, for desiredTemperature it may only by 0 or 5). Make sure you associate the target device with the source device beforehand.</li>
</ul>
<br>

View File

@ -260,12 +260,14 @@ sub
CUL_MAX_Send(@)
{
# $cmd is one of
my ($hash, $cmd, $dst, $payload, $flags, $groupId, $msgcnt) = @_;
my ($hash, $cmd, $dst, $payload, $flags, $groupId, $msgcnt, $src) = @_;
CUL_MAX_Check($hash);
$flags = "00" if(!$flags);
$groupId = "00" if(!defined($groupId));
$src = $hash->{addr} if(!defined($src));
if(!defined($msgcnt)) {
my $dhash = CUL_MAX_DeviceHash($dst);
#replace message counter if not already set
@ -274,7 +276,7 @@ CUL_MAX_Send(@)
$msgcnt = sprintf("%02x",$dhash->{READINGS}{msgcnt}{VAL});
}
my $packet = $msgcnt . $flags . $msgCmd2Id{$cmd} . $hash->{addr} . $dst . $groupId . $payload;
my $packet = $msgcnt . $flags . $msgCmd2Id{$cmd} . $src . $dst . $groupId . $payload;
#prefix length in bytes
$packet = sprintf("%02x",length($packet)/2) . $packet;
@ -284,6 +286,7 @@ CUL_MAX_Send(@)
#Schedule checking for Ack
return undef if($cmd eq "Ack"); #we don't get an Ack for an Ack
return undef if($src ne $hash->{addr}); #we don't handle Ack's for fake messages
my $timeout = gettimeofday()+$ackTimeout;
$waitForAck[@waitForAck] = { "packet" => $packet,
"dest" => $dst,