mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-04-25 22:09:21 +00:00
MAX: allow setting weekProfile
git-svn-id: https://svn.fhem.de/fhem/trunk@2696 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
4ed8e3f5e9
commit
f5951b562a
@ -36,6 +36,7 @@ sub validBoostDuration { return $_[0] ~~ /^\d+$/ && exists($boost_durationsInv{$
|
|||||||
sub validValveposition { return $_[0] ~~ /^\d+$/ && $_[0] >= 0 && $_[0] <= 100; }
|
sub validValveposition { return $_[0] ~~ /^\d+$/ && $_[0] >= 0 && $_[0] <= 100; }
|
||||||
sub validDecalcification { my ($decalcDay, $decalcHour) = ($_[0] =~ /^(...) (\d{1,2}):00$/);
|
sub validDecalcification { my ($decalcDay, $decalcHour) = ($_[0] =~ /^(...) (\d{1,2}):00$/);
|
||||||
return defined($decalcDay) && defined($decalcHour) && exists($decalcDaysInv{$decalcDay}) && 0 <= $decalcHour && $decalcHour < 24; }
|
return defined($decalcDay) && defined($decalcHour) && exists($decalcDaysInv{$decalcDay}) && 0 <= $decalcHour && $decalcHour < 24; }
|
||||||
|
sub validWeekProfile { return length($_[0]) == 4*13*7; }
|
||||||
|
|
||||||
my %readingDef = ( #min/max/default
|
my %readingDef = ( #min/max/default
|
||||||
"maximumTemperature" => [ \&validTemperature, 30.5],
|
"maximumTemperature" => [ \&validTemperature, 30.5],
|
||||||
@ -50,6 +51,7 @@ my %readingDef = ( #min/max/default
|
|||||||
"decalcification" => [ \&validDecalcification, "Sat 12:00" ],
|
"decalcification" => [ \&validDecalcification, "Sat 12:00" ],
|
||||||
"maxValveSetting" => [ \&validValveposition, 100 ],
|
"maxValveSetting" => [ \&validValveposition, 100 ],
|
||||||
"valveOffset" => [ \&validValveposition, 00 ],
|
"valveOffset" => [ \&validValveposition, 00 ],
|
||||||
|
".weekProfile" => [ \&validWeekProfile, $defaultWeekProfile ],
|
||||||
);
|
);
|
||||||
|
|
||||||
my %interfaces = (
|
my %interfaces = (
|
||||||
@ -347,6 +349,40 @@ MAX_Set($@)
|
|||||||
} elsif($setting eq "wakeUp") {
|
} elsif($setting eq "wakeUp") {
|
||||||
return ($hash->{IODev}{Send})->($hash->{IODev},"WakeUp",$hash->{addr}, 0x3F);
|
return ($hash->{IODev}{Send})->($hash->{IODev},"WakeUp",$hash->{addr}, 0x3F);
|
||||||
|
|
||||||
|
} elsif($setting eq "weekProfile" and $hash->{type} ~~ ["HeatingThermostat","WallMountedThermostat"]) {
|
||||||
|
return "Number of arguments must be even" if(@args%2 == 1);
|
||||||
|
|
||||||
|
my $curWeekProfile = MAX_ReadingsVal($hash, ".weekProfile");
|
||||||
|
|
||||||
|
for(my $i = 0; $i < @args; $i += 2) {
|
||||||
|
return "Expected day, got $args[$i]" if(!exists($decalcDaysInv{$args[$i]}));
|
||||||
|
my $day = $decalcDaysInv{$args[$i]};
|
||||||
|
my @controlpoints = split(',',$args[$i+1]);
|
||||||
|
return "Not more than 13 control points are allowed!" if(@controlpoints > 13*2);
|
||||||
|
my $newWeekprofilePart = "";
|
||||||
|
for(my $j = 0; $j < @controlpoints; $j += 2) {
|
||||||
|
my ($hour, $min);
|
||||||
|
if($j + 1 == @controlpoints) {
|
||||||
|
$hour = 0; $min = 0;
|
||||||
|
} else {
|
||||||
|
($hour, $min) = ($controlpoints[$j+1] =~ /^(\d{1,2}):(\d{1,2})$/);
|
||||||
|
}
|
||||||
|
my $temperature = $controlpoints[$j];
|
||||||
|
return "Invalid time: $controlpoints[$j+1]" if(!defined($hour) || !defined($min) || $hour > 23 || $min > 59);
|
||||||
|
return "Invalid temperature" if(!validTemperature($temperature));
|
||||||
|
$temperature = 4.5 if($temperature eq "off");
|
||||||
|
$temperature = 30.5 if($temperature eq "on");
|
||||||
|
$newWeekprofilePart .= sprintf("%04x", (int($temperature*2) << 9) | int(($hour * 60 + $min)/5));
|
||||||
|
Log 5, "add part $newWeekprofilePart for $hour:$min $temperature C ($controlpoints[$j],$controlpoints[$j+1])";
|
||||||
|
}
|
||||||
|
Log 5, "New Temperature part for $day: $newWeekprofilePart";
|
||||||
|
#Each day has 2 bytes * 13 controlpoints = 26 bytes = 52 hex characters
|
||||||
|
#we don't have to update the rest, because the active part is terminated by the time 0:00
|
||||||
|
substr($curWeekProfile, $day*52, length($newWeekprofilePart)) = $newWeekprofilePart;
|
||||||
|
}
|
||||||
|
readingsSingleUpdate($hash, ".weekProfile", $curWeekProfile, 0);
|
||||||
|
Log 5, "New weekProfile: " . MAX_ReadingsVal($hash, ".weekProfile");
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
my $templist = "off,".join(",",map { sprintf("%2.1f",$_/2) } (10..60)) . ",on";
|
my $templist = "off,".join(",",map { sprintf("%2.1f",$_/2) } (10..60)) . ",on";
|
||||||
my $ret = "Unknown argument $setting, choose one of wakeUp factoryReset groupid";
|
my $ret = "Unknown argument $setting, choose one of wakeUp factoryReset groupid";
|
||||||
@ -567,17 +603,25 @@ MAX_Parse($$)
|
|||||||
readingsBulkUpdate($shash, "maxValveSetting", $args[9]);
|
readingsBulkUpdate($shash, "maxValveSetting", $args[9]);
|
||||||
readingsBulkUpdate($shash, "valveOffset", $args[10]);
|
readingsBulkUpdate($shash, "valveOffset", $args[10]);
|
||||||
readingsBulkUpdate($shash, "decalcification", "$decalcDays{$args[11]} $args[12]:00");
|
readingsBulkUpdate($shash, "decalcification", "$decalcDays{$args[11]} $args[12]:00");
|
||||||
$shash->{internal}{weekProfile} = $args[13];
|
readingsBulkUpdate($shash, ".weekProfile", $args[13]);
|
||||||
} else {
|
} else {
|
||||||
$shash->{internal}{weekProfile} = $args[4];
|
readingsBulkUpdate($shash, ".weekProfile", $args[4]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Format of weekprofile: 16 bit integer (high byte first) for every control point, 13 control points for every day
|
||||||
|
# each 16 bit integer value is parsed as
|
||||||
|
# int time = (value & 0x1FF) * 5;
|
||||||
|
# int hour = (time / 60) % 24;
|
||||||
|
# int minute = time % 60;
|
||||||
|
# int temperature = ((value >> 9) & 0x3F) / 2;
|
||||||
|
|
||||||
|
my $curWeekProfile = MAX_ReadingsVal($shash, ".weekProfile");
|
||||||
#parse weekprofiles for each day
|
#parse weekprofiles for each day
|
||||||
for (my $i=0;$i<7;$i++) {
|
for (my $i=0;$i<7;$i++) {
|
||||||
my (@time_prof, @temp_prof);
|
my (@time_prof, @temp_prof);
|
||||||
for(my $j=0;$j<13;$j++) {
|
for(my $j=0;$j<13;$j++) {
|
||||||
$time_prof[$j] = (hex(substr($shash->{internal}{weekProfile},($i*52)+ 4*$j,4))& 0x1FF) * 5;
|
$time_prof[$j] = (hex(substr($curWeekProfile,($i*52)+ 4*$j,4))& 0x1FF) * 5;
|
||||||
$temp_prof[$j] = (hex(substr($shash->{internal}{weekProfile},($i*52)+ 4*$j,4))>> 9 & 0x3F ) / 2;
|
$temp_prof[$j] = (hex(substr($curWeekProfile,($i*52)+ 4*$j,4))>> 9 & 0x3F ) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
my @hours;
|
my @hours;
|
||||||
@ -750,6 +794,14 @@ MAX_Parse($$)
|
|||||||
Sends a fake state message of this device over the air to <device>. Works only with CUL_MAX as IODev. For ShutterContacts, sends
|
Sends a fake state message of this device over the air to <device>. Works only with CUL_MAX as IODev. For ShutterContacts, sends
|
||||||
a ShutterContactState message; <parameters...> must be 0 or 1 for "window closed" or "window opened". For WallMountedThermostats.
|
a ShutterContactState message; <parameters...> must be 0 or 1 for "window closed" or "window opened". For WallMountedThermostats.
|
||||||
sends a WallThermostatState message; <parameters...> 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>
|
sends a WallThermostatState message; <parameters...> 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>
|
||||||
|
<li>weekprofile [<day> <temp1>,<until1>,<temp2>,<until2>] [<day> <temp1>,<until1>,<temp2>,<until2>] ...<br>
|
||||||
|
Allows setting the week profile. For devices of type HeatingThermostat or WallMountedThermostat only. Example:<br>
|
||||||
|
<code>set MAX_12345 weekprofile Fri 24.5,6:00,12,15:00,5 Sat 7,4:30,19,12:55,6</code><br>
|
||||||
|
sets the profile <br>
|
||||||
|
<code>Friday: 24.5 C for 0:00 - 6:00, 12 C for 6:00 - 15:00, 5 C for 15:00 - 0:00<br>
|
||||||
|
Saturday: 7 C for 0:00 - 4:30, 19 C for 4:30 - 12:55, 6 C for 12:55 - 0:00</code><br>
|
||||||
|
while keeping the old profile for all other days.
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
|
@ -22,8 +22,6 @@ my $resendRetries = 0; #how often resend before giving up?
|
|||||||
|
|
||||||
my $ackTimeout = 3; #seconds
|
my $ackTimeout = 3; #seconds
|
||||||
|
|
||||||
my $defaultWeekprofile = "444855084520452045204520452045204520452045204520452044485508452045204520452045204520452045204520452045204448546c44cc55144520452045204520452045204520452045204448546c44cc55144520452045204520452045204520452045204448546c44cc55144520452045204520452045204520452045204448546c44cc55144520452045204520452045204520452045204448546c44cc5514452045204520452045204520452045204520";
|
|
||||||
|
|
||||||
sub
|
sub
|
||||||
CUL_MAX_Initialize($)
|
CUL_MAX_Initialize($)
|
||||||
{
|
{
|
||||||
@ -230,9 +228,9 @@ CUL_MAX_Parse($$)
|
|||||||
|
|
||||||
#This are the default values that a device has after factory reset or pairing
|
#This are the default values that a device has after factory reset or pairing
|
||||||
if($device_types{$type} eq "HeatingThermostat") {
|
if($device_types{$type} eq "HeatingThermostat") {
|
||||||
Dispatch($shash, "MAX,$isToMe,HeatingThermostatConfig,$src,17,21,30.5,4.5,80,5,0,12,15,100,0,0,12,$defaultWeekprofile", {RAWMSG => $rmsg});
|
Dispatch($shash, "MAX,$isToMe,HeatingThermostatConfig,$src,17,21,30.5,4.5,80,5,0,12,15,100,0,0,12,$defaultWeekProfile", {RAWMSG => $rmsg});
|
||||||
} elsif($device_types{$type} eq "WallMountedThermostat") {
|
} elsif($device_types{$type} eq "WallMountedThermostat") {
|
||||||
Dispatch($shash, "MAX,$isToMe,WallThermostatConfig,$src,17,21,30.5,4.5,$defaultWeekprofile", {RAWMSG => $rmsg});
|
Dispatch($shash, "MAX,$isToMe,WallThermostatConfig,$src,17,21,30.5,4.5,$defaultWeekProfile", {RAWMSG => $rmsg});
|
||||||
}
|
}
|
||||||
#Todo: CUL_MAX_SendTimeInformation($shash, $src); on Ack for our PairPong
|
#Todo: CUL_MAX_SendTimeInformation($shash, $src); on Ack for our PairPong
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ package MaxCommon;
|
|||||||
|
|
||||||
require Exporter;
|
require Exporter;
|
||||||
@ISA = qw(Exporter);
|
@ISA = qw(Exporter);
|
||||||
@EXPORT = qw(%device_types %msgId2Cmd %msgCmd2Id);
|
@EXPORT = qw(%device_types %msgId2Cmd %msgCmd2Id $defaultWeekProfile);
|
||||||
#@EXPORT_OK = qw($Zeitstempel @Logdaten Besteller_ermitteln);
|
#@EXPORT_OK = qw($Zeitstempel @Logdaten Besteller_ermitteln);
|
||||||
|
|
||||||
%device_types = (
|
%device_types = (
|
||||||
@ -53,4 +53,6 @@ require Exporter;
|
|||||||
);
|
);
|
||||||
%msgCmd2Id = reverse %msgId2Cmd;
|
%msgCmd2Id = reverse %msgId2Cmd;
|
||||||
|
|
||||||
|
$defaultWeekProfile = "444855084520452045204520452045204520452045204520452044485508452045204520452045204520452045204520452045204448546c44cc55144520452045204520452045204520452045204448546c44cc55144520452045204520452045204520452045204448546c44cc55144520452045204520452045204520452045204448546c44cc55144520452045204520452045204520452045204448546c44cc5514452045204520452045204520452045204520";
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user