Hi all
I started using Fhem a few weeks a go and start to get a hang of, it, already have some FHT,light,fans, electrical heaters running via fhem.
Now I want to integrate my wifi thermostat to switch on and off the Central heating system. I already have a simple version running that collects data from the Thermostat. The only problem is that the GET request blocks fhem for about 3 sec. But I will live with that for the time being.
I am now programing the module and what to start adding the set functionality. There is my problem :-)
In the UI I see with for instance an FHT a lot of possible sets, I also see these sets defined in the code of FHT, but I can figger out
how they go from the module to the UI.
Can any body help me with this ?
Bart
> how they go from the module to the UI.
You have to implement a correct return value for "set device ?"
is that the list that comes out of
return SetExtensions($hash, $list, @a);
Don't see it in FHT, but a lot of other modules uses it
Bart,
SetExtensions is only for additional functions described in http://fhem.de/commandref.html#setExtensions
Your SetFn/GetFn should return the string "Unknown argument ?, choose one of " followed by the space separated list of possible commands. If a possible command is followed by a colon, then you can specify some widgets, see http://fhem.de/commandref.html#webCmd
Thanks,
That now also works, a strange solution but it works, would expect a separate function for this.
I am really starting to like Fhem, I came from Domoticz, there you have to change the holl program to add an extra module. from HTML generation to the module, really a pain in the ass.
And as long as i is not in the repository I need to a difficult merge every time, for the Thermostat and for the CUL, FS20, FHT. So I stopped.
Here just add one module and it starts working.
Ok, the interface is not so nice but that will be fixed with some dedicate HTML5 programs
And I need to get use to perl:-)
Bart,
here is a first version
I only trying to get that you can change desired temperature in the overview of a room?
The FHT has that option.
Logging is not ok , but I would like some feetback, what I did OK and not OK,
The programing data still needs to mad as a parameter, but for me it is now ok.
For people that are interested, it is 4 times times "minutes and temperature in F".
Bart,
##############################################
# $Id: 25_Therm3M50.pm 3738 2013-11-21 14:13:59Z Amigob $
package main;
use strict;
use warnings;
use JSON;
use LWP::UserAgent;
use constant false => 0;
use constant true => 1;
my %sets =
(
"Desire-temp" => "6.0,6.5,7.0,7.5,8.0,8.5,9.0,9.5,10.0,10.5,11.0,11.5,12.0,12.5,13.0,13.5,14.0,14.5,15.0,15.5,16.0,16.5,17.0,17.5,18.0,18.5,19.0,19.5,20.0,20.5,21.0,21.5,22.0,22.5,23.0,23.5,24.0,24.5,25.0,25.5,26.0,26.5,27.0,27.5,28.0,28.5,29.0,29.5,30.0",
"Overrule" => "On,Off",
"Holiday" => "On,Off",
"Away" => "On,Off"
);
my %ReadingsToReadable =
(
"fmode" => "FanMode",
"fstate" => "FanState",
"hold" => "Hold",
"override" => "TemperatueOverruled",
"t_heat" => "DesiredHeatingTemp",
"t_cool" => "DesiredCoolingTemp",
"t_type_post" => "t_type_post",
"temp" => "MeasuredTemprature",
"tmode" => "TemperatureMode",
"tstate" => "TemperatureState"
);
my %wdaytoday =
(
"0" => ["sun",6, "[540,66,600,70,840,70,1410,59]"],
"1" => ["mon",0, "[540,59,600,59,840,70,1410,59]"],
"2" => ["tue",1, "[540,59,600,59,840,70,1410,59]"],
"3" => ["wed",2, "[540,59,600,59,840,70,1410,59]"],
"4" => ["thu",3, "[540,59,600,59,840,70,1410,59]"],
"5" => ["fri",4, "[540,59,600,59,840,70,1410,59]"],
"6" => ["sat",5, "[540,66,600,70,840,70,1410,59]"],
"7" => ["hol",7, "[541,66,601,70,841,70,1411,59]"],
);
my %led_color =
(
"None" => 0,
"Green" => 1,
"Yellow" => 2,
"Red" => 4,
);
sub
Therm3M50_Initialize($)
{
my ($hash) = @_;
$hash->{SetFn} = "Therm3M50_Set";
$hash->{DefFn} = "Therm3M50_Define";
$hash->{UndefFn} = "Therm3M50_Undefine";
$hash->{AttrList} = $readingFnAttributes;
}
###################################
sub
Therm3M50_Set($@)
{
my ($hash, @a) = @_;
my $name = shift @a;
#return "\"set $a[0]\" needs at least two parameters" if(@a < 2);
my $cmdList = join(" ",sort keys %sets);
my @list = map { ($_.".0", $_+0.5) } (6..30);
pop @list;
my $tmpList=join(",",@list);
$cmdList =~ s/-temp/-temp:$tmpList/g; # FHEMWEB sugar
$cmdList =~ s/(Overrule|Away|Holiday)/$1:On,Off/g;
return "Unknown argument ?, choose one of ".$cmdList if($a[0] eq "?");
my $cmd = $a[0];
my $value = $a[1];
if ( $cmd eq "Overrule" )
{
#$hash->{$cmd} = $value;
if ($value eq "On")
{
Therm3M50_Overrule($hash);
}
else
{
Therm3M50_Program($hash);
}
}
elsif( $cmd eq "Holiday" )
{
#$hash->{$cmd} = $value;
if ($value eq "On")
{
Therm3M50_Holiday($hash);
}
else
{
Therm3M50_Program($hash);
}
}
elsif( $cmd eq "Away" )
{
#$hash->{$cmd} = $value;
if ($value eq "On")
{
Therm3M50_Away($hash);
}
else
{
Therm3M50_Program($hash);
}
}
elsif( $cmd eq "Desire-temp" )
{
Therm3M50_Overrule_temp($hash, $value);
}
else
{
return "illegal set value specified";
}
#Log3 $name, 0, "dummy set $name $v";
return undef;
}
sub
Therm3M50_Define($$)
{
my ($hash, $def) = @_;
my @a = split("[ \t][ \t]*", $def);
Therm3M50_Program($hash);
InternalTimer(gettimeofday()+15, "Therm3M50_GetStatus", $hash, 0);
Log3 "Therm3M50", 0, "Therm3M50 Defined";
return "Wrong syntax: use define <name> Therm3M50 <'ip'>" if(int(@a) != 3);
return undef;
}
sub
Therm3M50_Undefine($$)
{
my ($hash, $arg) = @_;
my $name = $hash->{NAME};
RemoveInternalTimer($hash);
Log 0, "$name Undefine complete";
return undef;
}
sub
Therm3M50_Overrule($)
{
my ($hash) = @_;
my $name = $hash->{NAME};
my $response = decode_json(Therm3M50_POST($hash, 'http://192.168.181.112/tstat', '{"a_heat":80}' ));
readingsSingleUpdate($hash,"state","Overrule",1);
Log3 "$name", 0, "Therm3M50 Overrule: $response";
Therm3M50_set_led($hash,"Red");
return undef;
}
sub
Therm3M50_Overrule_temp($$)
{
my ($hash, $temperatureC) = @_;
my $name = $hash->{NAME};
#convert to F and round it of.
my $temperatureF = int((($temperatureC * 9.0) / 5.0) + 32.5);
my $response = decode_json(Therm3M50_POST($hash, 'http://192.168.181.112/tstat', '{"a_heat":'.$temperatureF.'}' ));
readingsSingleUpdate($hash,"state","Overrule",1);
Log3 "$name", 0, "Therm3M50 Overrule: $response";
Therm3M50_set_led($hash,"Red");
return undef;
}
sub
Therm3M50_Holiday($)
{
my ($hash) = @_;
my $name = $hash->{NAME};
my ($sec,$min,$hour,$mday,$month,$year,$wday,$yday,$isdst) = localtime;
# set holiday(7) program for today
my $response = decode_json(Therm3M50_POST($hash, "http://192.168.181.112/tstat/program/heat/".$wdaytoday{$wday}[0], "{\"".$wdaytoday{$wday}[1]."\":".$wdaytoday{7}[2]."}" ) );
readingsSingleUpdate($hash,"state","Holiday",1);
Log3 "$name", 0, "Therm3M50 Holiday: $response";
Therm3M50_set_led($hash, "Yellow");
return undef;
}
sub
Therm3M50_Away($)
{
my ($hash) = @_;
my $name = $hash->{NAME};
my $response = decode_json(Therm3M50_POST($hash, "http://192.168.181.112/tstat", "{\"a_heat\":60,\"hold\":1}" ) );
readingsSingleUpdate($hash,"state","Away",1);
Log3 "$name", 0, "Therm3M50 Holiday: $response";
Therm3M50_set_led($hash, "Yellow");
return undef;
}
sub
Therm3M50_Program($)
{
my ($hash) = @_;
my $name = $hash->{NAME};
my ($sec,$min,$hour,$mday,$month,$year,$wday,$yday,$isdst) = localtime;
my $response = decode_json(Therm3M50_POST($hash, 'http://192.168.181.112/tstat', '{"a_mode":0,"hold":0}' ));
# set correct program can have been overrled by holiday
my $response = decode_json(Therm3M50_POST($hash, "http://192.168.181.112/tstat/program/heat/".$wdaytoday{$wday}[0], "{\"".$wdaytoday{$wday}[1]."\":".$wdaytoday{$wday}[2]."}" ) );
Therm3M50_set_led($hash, "None");
readingsSingleUpdate($hash,"state","Program",1);
Log3 "$name", 0, "Therm3M50 Program: $response";
return undef;
}
sub
Therm3M50_GetStatus($)
{
my ($hash) = @_;
my $ua = LWP::UserAgent->new;
my $result = true;
my $message = decode_json(Therm3M50_GET($hash,"http://192.168.181.112/tstat"));
# check if messages is ook, it can returm -1 voor control values
while( ( my ($k, $v) = each %$message ) && ($result) )
{
if( ($k ne 'time') && ($k ne 't_heat') && ($k ne 't_cool') && ($k ne 'temp' ) )
{
if ( ($v == -1) || ($v eq "nok") )
{
#message not ok
Log3 "Therm3M50", 0, "Therm3M50 error $k $v ";
$result = false;
}
}
}
while(( my ($k, $v) = each %$message ) && ($result) )
{
if( $k ne 'time' )
{
if (( $k eq "t_heat" ) || ( $k eq "t_cool" ) || ( $k eq "temp" ))
{
#convert to C and round it of.
$v = int(((($v - 32.0) * (5/9)) * 10) + 0.5) / 10.0 ;
}
readingsSingleUpdate($hash,$ReadingsToReadable{$k},$v,1);
}
}
InternalTimer(gettimeofday()+15, "Therm3M50_GetStatus", $hash, 0);
}
sub
Therm3M50_set_led($$)
{
my ($hash, $color) = @_;
my $response = decode_json(Therm3M50_POST($hash, 'http://192.168.181.112/tstat/led', '{"energy_led":'.$led_color{$color}.'}' ));
}
sub
Therm3M50_GET($$)
{
my ($hash, $server_endpoint) = @_;
my $message = "";
my $ua = LWP::UserAgent->new;
$ua->timeout(5);
# set custom HTTP request header fields
my $req = HTTP::Request->new(GET => $server_endpoint);
$req->header('content-type' => 'application/json');
$req->header('x-auth-token' => 'kfksj48sdfj4jd9d');
my $resp = $ua->request($req);
if ($resp->is_success)
{
$message = $resp->decoded_content;
if ( trim($message) eq "")
{
$message = '{"result":"nok"}';
}
}
else
{
$message = '{"result":"nok"}';
}
Log3 "Therm3M50", 0, "Therm3M50 GET Response: $message";
return $message;
}
sub
Therm3M50_POST($$$)
{
my ($hash, $server_endpoint, $data) = @_;
my $message = "";
my $ua = LWP::UserAgent->new;
Log3 "Therm3M50", 0, "Therm3M50 POST:$server_endpoint, $data";
# set custom HTTP request header fields
my $req = HTTP::Request->new(POST => $server_endpoint);
$req->header('content-type' => 'application/json');
$req->header('x-auth-token' => 'kfksj48sdfj4jd9d');
# add POST data to HTTP request body
$req->content($data);
my $resp = $ua->request($req);
if ($resp->is_success)
{
$message = $resp->decoded_content;
if ( trim($message) eq "")
{
$message = '{"result":"nok"}';
}
else
{
$message = '{"result":"ok"}';
}
}
else
{
$message = '{"result":"nok"}';
}
Log3 "Therm3M50", 0, "Therm3M50 POST Response: $message";
return $message;
}
1;
=pod
=begin html
<a name="Therm3M50"></a>
<h3>Therm3M50</h3>
<ul>
Define a Therm3M50. A Therm3M50 can take via <a href="#set">set</a> any values.
Used for programming.
<br><br>
<a name="Therm3M50define"></a>
<b>Define</b>
<ul>
<code>define <name> Therm3M50</code>
<br><br>
Example:
<ul>
<code>define myvar Therm3M50</code><br>
<code>set myvar 7</code><br>
</ul>
</ul>
<br>
<a name="Therm3M50set"></a>
<b>Set</b>
<ul>
<code>set <name> <value></code><br>
Set any value.
</ul>
<br>
<a name="Therm3M50get"></a>
<b>Get</b> <ul>N/A</ul><br>
<a name="Therm3M50attr"></a>
<b>Attributes</b>
<ul>
<li><a name="setList">setList</a><br>
Space separated list of commands, which will be returned upon "set name ?",
so the FHEMWEB frontend can construct a dropdown and offer on/off
switches. Example: attr Therm3M50Name setList on off
</li>
<li><a href="#readingFnAttributes">readingFnAttributes</a></li>
</ul>
<br>
</ul>
=end html
=cut
The FHEMWEB overview will show a dropdown automatically, if it is called desired-temp (not "Desire-temp"), and show the "measured-temp" it it exists.
If your wording is different, you have to use webCmd and stateFormat.
Tried with the desired-temp and measured-temp but no success,
Should I put something special in the state, I see that in FHT that they put "measured-temp: 33.0"
Tried that also but no success either.
Bart,
No, nothing special / no further action is needed. AFAIK.
stupid of me, still had a wrong name, 'desired-temp' now working, and added my own status so that I also see if it is overruled or not.
almost time to attach the wifi thermostat to the central heating :-).
Thanks,
So it is integrated now using the wifi thermostat to switch on and off the Central heating, in combination with 3 FHT's. Seems to work pretty good. :-). I still need to add some parameter so that interval of polling the Thermostat can be controlled, is now 60 sec.
I have one small problem with the FHT, the logging of the desired-temp is only done on desire temperature change. That is
a little bit annoying when you what to put it in a graph. :-0.
No, next step is integrate it with a calendar, Holiday ( at home ) and away days. And then I am going to implement that it needs to start heating earlier when the prediction is colder then 5 degrees outside and the wind speed is above 5 Beaufort.
Bart,
Hi Bart,
I have the Filtrete 3M50 too and it would be nice to use it with fhem. Can you attach the code to the thread?
Thanks.
Joost