mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-03-13 17:26:34 +00:00
98_weekprofile: new module to manage week profiles
git-svn-id: https://svn.fhem.de/fhem/trunk@10244 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
ce92adc00a
commit
905fb5b73f
@ -1,5 +1,6 @@
|
|||||||
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
|
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
|
||||||
# Do not insert empty lines here, update check depends on it.
|
# Do not insert empty lines here, update check depends on it.
|
||||||
|
- feature: 98_weekprofile: new module to manage week profiles
|
||||||
- feature: 49_SSCam: function "enable" and "disable" for SS-Cams added
|
- feature: 49_SSCam: function "enable" and "disable" for SS-Cams added
|
||||||
- change: 49_SSCam: changed timout of Http-calls to a higher value,
|
- change: 49_SSCam: changed timout of Http-calls to a higher value,
|
||||||
commandref enhanced
|
commandref enhanced
|
||||||
|
750
fhem/FHEM/98_weekprofile.pm
Normal file
750
fhem/FHEM/98_weekprofile.pm
Normal file
@ -0,0 +1,750 @@
|
|||||||
|
##############################################
|
||||||
|
# $Id: 98_weekprofile.pm 0.01 2015-12-23 Risiko $
|
||||||
|
#
|
||||||
|
# Usage
|
||||||
|
#
|
||||||
|
# define <name> weekprofile <device>
|
||||||
|
#
|
||||||
|
# Changelog
|
||||||
|
#
|
||||||
|
# V 0.01 2015-12-23 - first version
|
||||||
|
##############################################
|
||||||
|
|
||||||
|
package main;
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use JSON; #libjson-perl
|
||||||
|
|
||||||
|
use vars qw(%defs);
|
||||||
|
use vars qw($FW_ME);
|
||||||
|
use vars qw($FW_wname);
|
||||||
|
use vars qw($FW_subdir);
|
||||||
|
|
||||||
|
my @shortDays = ("Mon","Tue","Wed","Thu","Fri","Sat","Sun");
|
||||||
|
|
||||||
|
my %DEV_READINGS;
|
||||||
|
# MAX
|
||||||
|
$DEV_READINGS{"Mon"}{"MAX"} = "weekprofile-2-Mon";
|
||||||
|
$DEV_READINGS{"Tue"}{"MAX"} = "weekprofile-3-Tue";
|
||||||
|
$DEV_READINGS{"Wed"}{"MAX"} = "weekprofile-4-Wed";
|
||||||
|
$DEV_READINGS{"Thu"}{"MAX"} = "weekprofile-5-Thu";
|
||||||
|
$DEV_READINGS{"Fri"}{"MAX"} = "weekprofile-6-Fri";
|
||||||
|
$DEV_READINGS{"Sat"}{"MAX"} = "weekprofile-0-Sat";
|
||||||
|
$DEV_READINGS{"Sun"}{"MAX"} = "weekprofile-1-Sun";
|
||||||
|
|
||||||
|
# HM-CC-RT-DN
|
||||||
|
$DEV_READINGS{"Mon"}{"HM-CC-RT-DN"} = "R_2_tempListMon";
|
||||||
|
$DEV_READINGS{"Tue"}{"HM-CC-RT-DN"} = "R_3_tempListTue";
|
||||||
|
$DEV_READINGS{"Wed"}{"HM-CC-RT-DN"} = "R_4_tempListWed";
|
||||||
|
$DEV_READINGS{"Thu"}{"HM-CC-RT-DN"} = "R_5_tempListThu";
|
||||||
|
$DEV_READINGS{"Fri"}{"HM-CC-RT-DN"} = "R_6_tempListFri";
|
||||||
|
$DEV_READINGS{"Sat"}{"HM-CC-RT-DN"} = "R_0_tempListSat";
|
||||||
|
$DEV_READINGS{"Sun"}{"HM-CC-RT-DN"} = "R_1_tempListSun";
|
||||||
|
|
||||||
|
# HM-CC-TC
|
||||||
|
$DEV_READINGS{"Mon"}{"HM-CC-TC"} = "R_2_tempListMon";
|
||||||
|
$DEV_READINGS{"Tue"}{"HM-CC-TC"} = "R_3_tempListTue";
|
||||||
|
$DEV_READINGS{"Wed"}{"HM-CC-TC"} = "R_4_tempListWed";
|
||||||
|
$DEV_READINGS{"Thu"}{"HM-CC-TC"} = "R_5_tempListThu";
|
||||||
|
$DEV_READINGS{"Fri"}{"HM-CC-TC"} = "R_6_tempListFri";
|
||||||
|
$DEV_READINGS{"Sat"}{"HM-CC-TC"} = "R_0_tempListSat";
|
||||||
|
$DEV_READINGS{"Sun"}{"HM-CC-TC"} = "R_1_tempListSun";
|
||||||
|
|
||||||
|
# HM-TC-IT-WM-W-EU
|
||||||
|
$DEV_READINGS{"Mon"}{"HM-TC-IT-WM-W-EU"} = "R_P1_2_tempListMon";
|
||||||
|
$DEV_READINGS{"Tue"}{"HM-TC-IT-WM-W-EU"} = "R_P1_3_tempListTue";
|
||||||
|
$DEV_READINGS{"Wed"}{"HM-TC-IT-WM-W-EU"} = "R_P1_4_tempListWed";
|
||||||
|
$DEV_READINGS{"Thu"}{"HM-TC-IT-WM-W-EU"} = "R_P1_5_tempListThu";
|
||||||
|
$DEV_READINGS{"Fri"}{"HM-TC-IT-WM-W-EU"} = "R_P1_6_tempListFri";
|
||||||
|
$DEV_READINGS{"Sat"}{"HM-TC-IT-WM-W-EU"} = "R_P1_0_tempListSat";
|
||||||
|
$DEV_READINGS{"Sun"}{"HM-TC-IT-WM-W-EU"} = "R_P1_1_tempListSun";
|
||||||
|
|
||||||
|
##############################################
|
||||||
|
sub weekprofile_getDeviceType($)
|
||||||
|
{
|
||||||
|
my ($device) = @_;
|
||||||
|
|
||||||
|
# determine device type
|
||||||
|
my $devHash = $main::defs{$device};
|
||||||
|
|
||||||
|
my $type = undef;
|
||||||
|
|
||||||
|
if ($devHash->{TYPE} =~ /CUL_HM/){
|
||||||
|
$type = AttrVal($device,"model","");
|
||||||
|
}
|
||||||
|
elsif ($devHash->{TYPE} =~ /MAX/){
|
||||||
|
$type = "MAX";
|
||||||
|
}
|
||||||
|
elsif ($devHash->{TYPE} =~ /dummy/){
|
||||||
|
$type = "MAX" if ($device =~ /.*MAX.*/); #dummy (FAKE WT) with name MAX inside for testing
|
||||||
|
}
|
||||||
|
return $type;
|
||||||
|
}
|
||||||
|
|
||||||
|
##############################################
|
||||||
|
sub weekprofile_readDayProfile($@)
|
||||||
|
{
|
||||||
|
my ($device,$day,$type,$me) = @_;
|
||||||
|
|
||||||
|
my @times;
|
||||||
|
my @temps;
|
||||||
|
|
||||||
|
$type = weekprofile_getDeviceType($device) if (!defined($type));
|
||||||
|
return if (!defined($type));
|
||||||
|
|
||||||
|
my $reading = $DEV_READINGS{$day}{$type};
|
||||||
|
|
||||||
|
#Log3 $me, 5, "$me(ReadDayProfile): $reading";
|
||||||
|
|
||||||
|
if($type eq "MAX") {
|
||||||
|
@temps = split('/',ReadingsVal($device,"$reading-temp",""));
|
||||||
|
@times = split('/',ReadingsVal($device,"$reading-time",""));
|
||||||
|
# only use to to interval 'from-to'
|
||||||
|
for(my $i = 0; $i < scalar(@times); $i+=1){
|
||||||
|
my $interval = $times[$i];
|
||||||
|
my @parts = split('-',$interval);
|
||||||
|
$times[$i] = ($parts[1] ne "00:00") ? $parts[1] : "24:00";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
# Homatic
|
||||||
|
# get temp list for the day
|
||||||
|
my $prf = ReadingsVal($device,$reading,"");
|
||||||
|
# split into time temp time temp etc.
|
||||||
|
# 06:00 17.0 22:00 21.0 24:00 17.0
|
||||||
|
my @timeTemp = split(' ', $prf);
|
||||||
|
|
||||||
|
for(my $i = 0; $i < scalar(@timeTemp); $i += 2) {
|
||||||
|
push(@times, $timeTemp[$i]);
|
||||||
|
push(@temps, $timeTemp[$i+1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(my $i = 0; $i < scalar(@temps); $i+=1){
|
||||||
|
$temps[$i] =~s/[^\d.]//g; #only numbers
|
||||||
|
}
|
||||||
|
|
||||||
|
for(my $i = 0; $i < scalar(@times); $i+=1){
|
||||||
|
$times[$i] =~ s/^\s+|\s+$//g; #trim whitespace both ends
|
||||||
|
}
|
||||||
|
return (\@times, \@temps);
|
||||||
|
}
|
||||||
|
##############################################
|
||||||
|
sub weekprofile_readDevProfile(@)
|
||||||
|
{
|
||||||
|
my ($device,$type,$me) = @_;
|
||||||
|
$type = weekprofile_getDeviceType($device) if (!defined($type));
|
||||||
|
return "" if (!defined ($type));
|
||||||
|
|
||||||
|
my $prf = {};
|
||||||
|
foreach my $day (@shortDays){
|
||||||
|
my ($dayTimes, $dayTemps) = weekprofile_readDayProfile($device,$day,$type,$me);
|
||||||
|
$prf->{$day}->{"temp"} = $dayTemps;
|
||||||
|
$prf->{$day}->{"time"} = $dayTimes;
|
||||||
|
}
|
||||||
|
return $prf;
|
||||||
|
}
|
||||||
|
##############################################
|
||||||
|
sub weekprofile_createDefaultPofile(@)
|
||||||
|
{
|
||||||
|
my ($hash) = @_;
|
||||||
|
my $prf = {};
|
||||||
|
|
||||||
|
foreach my $day (@shortDays){
|
||||||
|
my @times; push(@times, "24:00");
|
||||||
|
my @temps; push(@temps, "18.0");
|
||||||
|
|
||||||
|
$prf->{$day}->{"temp"} = \@temps;
|
||||||
|
$prf->{$day}->{"time"} = \@times;
|
||||||
|
}
|
||||||
|
return $prf;
|
||||||
|
}
|
||||||
|
##############################################
|
||||||
|
sub weekprofile_sendDevProfile(@)
|
||||||
|
{
|
||||||
|
my ($device,$prf,$me) = @_;
|
||||||
|
my $type = weekprofile_getDeviceType($device);
|
||||||
|
return "Error device type not supported" if (!defined ($type));
|
||||||
|
|
||||||
|
my $devPrf = weekprofile_readDevProfile($device,$type,$me);
|
||||||
|
|
||||||
|
# only send changed days
|
||||||
|
my @dayToTransfer = ();
|
||||||
|
foreach my $day (@shortDays){
|
||||||
|
my $tmpCnt = scalar(@{$prf->{$day}->{"temp"}});
|
||||||
|
next if ($tmpCnt <= 0);
|
||||||
|
|
||||||
|
if ($tmpCnt != scalar(@{$devPrf->{$day}->{"temp"}})) {
|
||||||
|
push @dayToTransfer , $day;
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $equal = 1;
|
||||||
|
for (my $i = 0; $i < $tmpCnt; $i++) {
|
||||||
|
if ( ($prf->{$day}->{"temp"}[$i] ne $devPrf->{$day}->{"temp"}[$i] ) ||
|
||||||
|
$prf->{$day}->{"time"}[$i] ne $devPrf->{$day}->{"time"}[$i] ) {
|
||||||
|
$equal = 0;
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($equal == 0) {
|
||||||
|
push @dayToTransfer , $day;
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scalar(@dayToTransfer) <=0) {
|
||||||
|
Log3 $me, 4, "$me(sendDevProfile): nothing to do";
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $cmd;
|
||||||
|
if($type eq "MAX") {
|
||||||
|
$cmd = "set $device weekProfile ";
|
||||||
|
foreach my $day (@dayToTransfer){
|
||||||
|
my $tmpCnt = scalar(@{$prf->{$day}->{"temp"}});
|
||||||
|
|
||||||
|
$cmd.=$day.' ';
|
||||||
|
|
||||||
|
for (my $i = 0; $i < $tmpCnt; $i++) {
|
||||||
|
my $endTime = $prf->{$day}->{"time"}[$i];
|
||||||
|
|
||||||
|
$endTime = ($endTime eq "24:00") ? ' ' : ','.$endTime.',';
|
||||||
|
$cmd.=$prf->{$day}->{"temp"}[$i].$endTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { #Homatic
|
||||||
|
my $k=0;
|
||||||
|
my $dayCnt = scalar(@dayToTransfer);
|
||||||
|
foreach my $day (@dayToTransfer){
|
||||||
|
$cmd .= "set $device tempList";
|
||||||
|
$cmd .= $day;
|
||||||
|
$cmd .= ($k < $dayCnt-1) ? " prep": " exec";
|
||||||
|
|
||||||
|
my $tmpCnt = scalar(@{$prf->{$day}->{"temp"}});
|
||||||
|
for (my $i = 0; $i < $tmpCnt; $i++) {
|
||||||
|
$cmd .= " ".$prf->{$day}->{"time"}[$i]." ".$prf->{$day}->{"temp"}[$i];
|
||||||
|
}
|
||||||
|
$cmd .= ($k < $dayCnt-1) ? ";;": "";
|
||||||
|
$k++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$cmd =~ s/^\s+|\s+$//g;
|
||||||
|
Log3 $me, 4, "$me(sendDevProfile): $cmd";
|
||||||
|
fhem($cmd);
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
##############################################
|
||||||
|
sub weekprofile_assignDev($)
|
||||||
|
{
|
||||||
|
my ($hash) = @_;
|
||||||
|
my $me = $hash->{NAME};
|
||||||
|
|
||||||
|
my $prf = undef;
|
||||||
|
if ($hash->{MASTERDEV}->{NAME}) {
|
||||||
|
my $type = weekprofile_getDeviceType($hash->{MASTERDEV}->{NAME});
|
||||||
|
return if (!defined($type));
|
||||||
|
|
||||||
|
$hash->{MASTERDEV}->{TYPE} = $type;
|
||||||
|
|
||||||
|
my $prfDev = weekprofile_readDevProfile($hash->{MASTERDEV}->{NAME},$type, $me);
|
||||||
|
|
||||||
|
if(defined($prfDev)) {
|
||||||
|
$prf = {};
|
||||||
|
$prf->{DATA} = $prfDev;
|
||||||
|
$prf->{NAME} = 'master';
|
||||||
|
}
|
||||||
|
$hash->{STATE} = "assigned";
|
||||||
|
} else {
|
||||||
|
my $prfDev = weekprofile_createDefaultPofile($hash);
|
||||||
|
if(defined($prfDev)) {
|
||||||
|
$prf = {};
|
||||||
|
$prf->{DATA} = $prfDev;
|
||||||
|
$prf->{NAME} = 'default';
|
||||||
|
}
|
||||||
|
$hash->{STATE} = "created";
|
||||||
|
}
|
||||||
|
|
||||||
|
if(defined($prf)) {
|
||||||
|
push @{$hash->{PROFILES}} , $prf;
|
||||||
|
}
|
||||||
|
|
||||||
|
readingsBeginUpdate($hash);
|
||||||
|
readingsBulkUpdate($hash,"state",$hash->{STATE});
|
||||||
|
readingsEndUpdate($hash, 1);
|
||||||
|
}
|
||||||
|
##############################################
|
||||||
|
sub weekprofile_updateReadings($)
|
||||||
|
{
|
||||||
|
my ($hash) = @_;
|
||||||
|
|
||||||
|
my $prfCnt = scalar(@{$hash->{PROFILES}});
|
||||||
|
|
||||||
|
readingsBeginUpdate($hash);
|
||||||
|
readingsBulkUpdate($hash,"profile_count",$prfCnt);
|
||||||
|
|
||||||
|
#readings with profile names???
|
||||||
|
#my $idx = 1;
|
||||||
|
#foreach my $prf (@{$hash->{PROFILES}}){
|
||||||
|
#my $str = sprintf("profile_name_%02d",$idx);
|
||||||
|
#readingsBulkUpdate($hash,$str,$prf->{NAME});
|
||||||
|
#$idx++;
|
||||||
|
#}
|
||||||
|
readingsEndUpdate($hash, 1);
|
||||||
|
}
|
||||||
|
##############################################
|
||||||
|
sub weekprofile_Initialize($)
|
||||||
|
{
|
||||||
|
my ($hash) = @_;
|
||||||
|
|
||||||
|
$hash->{DefFn} = "weekprofile_Define";
|
||||||
|
$hash->{SetFn} = "weekprofile_Set";
|
||||||
|
$hash->{GetFn} = "weekprofile_Get";
|
||||||
|
$hash->{SetFn} = "weekprofile_Set";
|
||||||
|
$hash->{StateFn} = "weekprofile_State";
|
||||||
|
$hash->{NotifyFn} = "weekprofile_Notify";
|
||||||
|
$hash->{AttrList} = "widgetWeekdays configFile".$readingFnAttributes;
|
||||||
|
|
||||||
|
$hash->{FW_summaryFn} = "weekprofile_SummaryFn";
|
||||||
|
|
||||||
|
$hash->{FW_atPageEnd} = 1;
|
||||||
|
}
|
||||||
|
##############################################
|
||||||
|
sub weekprofile_Define($$)
|
||||||
|
{
|
||||||
|
my ($hash, $def) = @_;
|
||||||
|
my @a = split("[ \t][ \t]*", $def);
|
||||||
|
|
||||||
|
if(@a < 1) {
|
||||||
|
my $msg = "wrong syntax: define <name> weekprofile [device]";
|
||||||
|
Log3 undef, 2, $msg;
|
||||||
|
return $msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $me = $a[0];
|
||||||
|
|
||||||
|
$hash->{MASTERDEV}->{NAME} = undef;
|
||||||
|
$hash->{MASTERDEV}->{NAME} = $a[2] if (@a > 1);
|
||||||
|
|
||||||
|
$hash->{STATE} = "defined";
|
||||||
|
my @profiles = ();
|
||||||
|
$hash->{PROFILES} = \@profiles;
|
||||||
|
|
||||||
|
#$attr{$me}{verbose} = 5;
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
##############################################
|
||||||
|
sub weekprofile_Get($$@)
|
||||||
|
{
|
||||||
|
my ($hash, $name, $cmd, @params) = @_;
|
||||||
|
|
||||||
|
my $list = '';
|
||||||
|
|
||||||
|
my $prfCnt = scalar(@{$hash->{PROFILES}});
|
||||||
|
$list.= 'profile_data:' if ($prfCnt > 0);
|
||||||
|
|
||||||
|
foreach my $prf (@{$hash->{PROFILES}}){
|
||||||
|
$list.= $prf->{NAME}.",";
|
||||||
|
}
|
||||||
|
|
||||||
|
$list = substr($list, 0, -1) if ($prfCnt > 0);
|
||||||
|
|
||||||
|
if($cmd eq "profile_data") {
|
||||||
|
return "no profile" if ($prfCnt <= 0);
|
||||||
|
|
||||||
|
my $prf = undef;
|
||||||
|
my $idx=0;
|
||||||
|
if($params[0]){
|
||||||
|
foreach my $prf (@{$hash->{PROFILES}}){
|
||||||
|
last if ( $prf->{NAME} eq $params[0]);
|
||||||
|
$idx++;
|
||||||
|
}
|
||||||
|
return "profile $params[0] not found" if ($idx >= $prfCnt);
|
||||||
|
}
|
||||||
|
$prf = $hash->{PROFILES}[$idx];
|
||||||
|
|
||||||
|
my $json = JSON->new;
|
||||||
|
my $json_text = $json->encode($prf->{DATA});
|
||||||
|
return $json_text;
|
||||||
|
}
|
||||||
|
|
||||||
|
$list.= ' profile_names:noArg';
|
||||||
|
if($cmd eq "profile_names") {
|
||||||
|
my $names = '';
|
||||||
|
foreach my $prf (@{$hash->{PROFILES}}){
|
||||||
|
$names .=$prf->{NAME}.",";
|
||||||
|
}
|
||||||
|
$names = substr($names, 0, -1);
|
||||||
|
return $names;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$list =~ s/ $//;
|
||||||
|
return "Unknown argument $cmd choose one of $list";
|
||||||
|
}
|
||||||
|
##############################################
|
||||||
|
sub weekprofile_Set($$@)
|
||||||
|
{
|
||||||
|
my ($hash, $me, $cmd, @params) = @_;
|
||||||
|
|
||||||
|
my $prfCnt = scalar(@{$hash->{PROFILES}});
|
||||||
|
my $list = '';
|
||||||
|
|
||||||
|
$list.= "profile_data";
|
||||||
|
if ($cmd eq 'profile_data') {
|
||||||
|
return 'usage: profile_data <name> <json data>' if(@params < 2);
|
||||||
|
|
||||||
|
my $json = JSON->new;
|
||||||
|
my $data = undef;
|
||||||
|
eval { $data = $json->decode($params[1]); };
|
||||||
|
if ($@) {
|
||||||
|
Log3 $me, 1, "$me(Set): Error parsing profile data.";
|
||||||
|
return "Error parsing profile data. No valid json format";
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach my $prf (@{$hash->{PROFILES}}){
|
||||||
|
if ( $prf->{NAME} eq $params[0]){
|
||||||
|
$prf->{DATA} = $data;
|
||||||
|
# automatic we send master profile to master device
|
||||||
|
if ($params[0] eq "master"){
|
||||||
|
weekprofile_sendDevProfile($hash->{MASTERDEV}->{NAME},$prf->{DATA},$me);
|
||||||
|
} else {
|
||||||
|
weekprofile_writeProfilesToFile($hash);
|
||||||
|
}
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
my $prfNew = {};
|
||||||
|
$prfNew->{NAME} = $params[0];
|
||||||
|
$prfNew->{DATA} = $data;
|
||||||
|
push @{$hash->{PROFILES}}, $prfNew;
|
||||||
|
weekprofile_updateReadings($hash);
|
||||||
|
weekprofile_writeProfilesToFile($hash);
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
#----------------------------------------------------------
|
||||||
|
$list.= ' send_to_device' if ($prfCnt > 0);
|
||||||
|
|
||||||
|
if ($cmd eq 'send_to_device') {
|
||||||
|
return 'usage: send_to_device <profile name> [device]' if(@params < 1);
|
||||||
|
|
||||||
|
my $profile = $params[0];
|
||||||
|
my $device = $hash->{MASTERDEV}->{NAME};
|
||||||
|
|
||||||
|
if (@params == 2){
|
||||||
|
$device = $params[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Error no master device" unless (defined($device));
|
||||||
|
|
||||||
|
my $found = undef;
|
||||||
|
foreach my $prf (@{$hash->{PROFILES}}){
|
||||||
|
if ( $prf->{NAME} eq $profile){
|
||||||
|
$found = $prf;
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$found) {
|
||||||
|
Log3 $me, 1, "$me(Set): Error unknown profile $profile";
|
||||||
|
return "Error unknown profile $profile";
|
||||||
|
}
|
||||||
|
|
||||||
|
my $ret = weekprofile_sendDevProfile($device,$found->{DATA},$me);
|
||||||
|
Log3 $me, 1, "$me(Set): $ret" if ($ret);
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
#----------------------------------------------------------
|
||||||
|
$list.= " copy_profile";
|
||||||
|
if ($cmd eq 'copy_profile') {
|
||||||
|
return 'usage: copy_profile <source> <target>' if(@params < 2);
|
||||||
|
|
||||||
|
my $srcName = $params[0];
|
||||||
|
my $destName= $params[1];
|
||||||
|
my $prfSrc = undef;
|
||||||
|
my $prfDest = undef;
|
||||||
|
foreach my $prf (@{$hash->{PROFILES}}){
|
||||||
|
$prfSrc = $prf if ($prf->{NAME} eq $srcName);
|
||||||
|
$prfDest = $prf if ($prf->{NAME} eq $destName);
|
||||||
|
}
|
||||||
|
return "Error unknown profile $srcName" unless($prfSrc);
|
||||||
|
Log3 $me, 4, "$me(Set): override profile $destName" if ($prfDest);
|
||||||
|
|
||||||
|
if ($prfDest){
|
||||||
|
$prfDest->{DATA} = $prfSrc->{DATA}
|
||||||
|
} else {
|
||||||
|
$prfDest = {};
|
||||||
|
$prfDest->{NAME} = $destName;
|
||||||
|
$prfDest->{DATA} = $prfSrc->{DATA};
|
||||||
|
push @{$hash->{PROFILES}}, $prfDest;
|
||||||
|
}
|
||||||
|
weekprofile_writeProfilesToFile($hash);
|
||||||
|
weekprofile_updateReadings($hash);
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
#----------------------------------------------------------
|
||||||
|
$list.= " remove_profile";
|
||||||
|
if ($cmd eq 'remove_profile') {
|
||||||
|
return 'usage: remove_profile <name>' if(@params < 1);
|
||||||
|
return 'Error master profile can not removed' if($params[0] eq "master");
|
||||||
|
|
||||||
|
my $delprf = undef;
|
||||||
|
my $idx = 0;
|
||||||
|
foreach my $prf (@{$hash->{PROFILES}}){
|
||||||
|
if ( $prf->{NAME} eq $params[0]){
|
||||||
|
$delprf = $prf;
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
$idx++;
|
||||||
|
}
|
||||||
|
return "Error unknown profile $params[0]" unless($delprf);
|
||||||
|
|
||||||
|
splice(@{$hash->{PROFILES}},$idx, 1);
|
||||||
|
weekprofile_writeProfilesToFile($hash);
|
||||||
|
weekprofile_updateReadings($hash);
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
$list =~ s/ $//;
|
||||||
|
return "Unknown argument $cmd, choose one of $list";
|
||||||
|
}
|
||||||
|
##############################################
|
||||||
|
sub weekprofile_State($$$$)
|
||||||
|
{
|
||||||
|
my ($hash, $time, $name, $val) = @_;
|
||||||
|
my $me = $hash->{NAME};
|
||||||
|
}
|
||||||
|
##############################################
|
||||||
|
sub weekprofile_Notify($$)
|
||||||
|
{
|
||||||
|
my ($own, $dev) = @_;
|
||||||
|
my $me = $own->{NAME}; # own name / hash
|
||||||
|
my $devName = $dev->{NAME}; # Device that created the events
|
||||||
|
|
||||||
|
return undef if ($devName ne "global");
|
||||||
|
|
||||||
|
my $max = int(@{$dev->{CHANGED}}); # number of events / changes
|
||||||
|
for (my $i = 0; $i < $max; $i++) {
|
||||||
|
my $s = $dev->{CHANGED}[$i];
|
||||||
|
|
||||||
|
next if(!defined($s));
|
||||||
|
my ($what,$who) = split(' ',$s);
|
||||||
|
|
||||||
|
if ($what =~ m/INITIALIZED/) {
|
||||||
|
Log3 $me, 5, "$me(Notify): assign to device $own->{MASTERDEV}->{NAME}" if (defined($own->{MASTERDEV}->{NAME}));
|
||||||
|
weekprofile_assignDev($own);
|
||||||
|
weekprofile_readProfilesFromFile($own);
|
||||||
|
weekprofile_updateReadings($own);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
##############################################
|
||||||
|
sub weekprofile_writeProfilesToFile(@)
|
||||||
|
{
|
||||||
|
my ($hash) = @_;
|
||||||
|
my $me = $hash->{NAME};
|
||||||
|
|
||||||
|
my $filename = "./log/weekprofile-$me.cfg";
|
||||||
|
$filename = AttrVal($me,"configFile",$filename);
|
||||||
|
|
||||||
|
Log3 $me, 5, "$me(writeProfileToFile): write profiles to $filename";
|
||||||
|
my $ret = open(my $fh, '>', $filename);
|
||||||
|
if (!$ret){
|
||||||
|
Log3 $me, 1, "Could not open file '$filename' $!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $json = JSON->new;
|
||||||
|
my $start = (defined($hash->{MASTERDEV}->{NAME})) ? 1:0;
|
||||||
|
my $prfCnt = scalar(@{$hash->{PROFILES}});
|
||||||
|
for (my $i = $start; $i < $prfCnt; $i++) {
|
||||||
|
print $fh $hash->{PROFILES}[$i]->{NAME}."=".$json->encode($hash->{PROFILES}[$i]->{DATA})."\n";
|
||||||
|
}
|
||||||
|
close $fh;
|
||||||
|
}
|
||||||
|
##############################################
|
||||||
|
sub weekprofile_readProfilesFromFile(@)
|
||||||
|
{
|
||||||
|
my ($hash) = @_;
|
||||||
|
my $me = $hash->{NAME};
|
||||||
|
|
||||||
|
my $filename = "./log/weekprofile-$me.cfg";
|
||||||
|
$filename = AttrVal($me,"configFile",$filename);
|
||||||
|
|
||||||
|
Log3 $me, 5, "$me(readProfilesFromFile): read profiles from $filename";
|
||||||
|
|
||||||
|
unless (-e $filename) {
|
||||||
|
Log3 $me, 5, "$me(readProfilesFromFile): file do not exist '$filename'";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $ret = open(my $fh, '<:encoding(UTF-8)', $filename);
|
||||||
|
if (!$ret){
|
||||||
|
Log3 $me, 1, "$me(readProfilesFromFile): Could not open file '$filename' $!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
my $json = JSON->new;
|
||||||
|
my $rowCnt = 0;
|
||||||
|
while (my $row = <$fh>) {
|
||||||
|
chomp $row;
|
||||||
|
Log3 $me, 5, "$me(readProfilesFromFile): data row $row";
|
||||||
|
my @data = split('=',$row);
|
||||||
|
if(@data<2){
|
||||||
|
Log3 $me, 1, "$me(readProfilesFromFile): incorrect data row";
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
my $prfData=undef;
|
||||||
|
eval { $prfData = $json->decode($data[1]); };
|
||||||
|
if ($@) {
|
||||||
|
Log3 $me, 1, "$me(readProfilesFromFile): Error parsing profile data $data[1]";
|
||||||
|
next;
|
||||||
|
};
|
||||||
|
|
||||||
|
my $prfNew = {};
|
||||||
|
$prfNew->{NAME} = $data[0];
|
||||||
|
$prfNew->{DATA} = $prfData;
|
||||||
|
|
||||||
|
if (!$hash->{MASTERDEV}->{NAME} && $rowCnt == 0) {
|
||||||
|
$hash->{PROFILES}[0] = $prfNew; # replace default
|
||||||
|
} else {
|
||||||
|
push @{$hash->{PROFILES}}, $prfNew;
|
||||||
|
}
|
||||||
|
$rowCnt++;
|
||||||
|
}
|
||||||
|
close $fh;
|
||||||
|
}
|
||||||
|
|
||||||
|
##############################################
|
||||||
|
sub weekprofile_SummaryFn()
|
||||||
|
{
|
||||||
|
my ($FW_wname, $d, $room, $extPage) = @_;
|
||||||
|
my $hash = $defs{$d};
|
||||||
|
|
||||||
|
my $show_links = 1;
|
||||||
|
$show_links = 0 if($FW_hiddenroom{detail});
|
||||||
|
|
||||||
|
my $html;
|
||||||
|
|
||||||
|
my $iconName = AttrVal($d, "icon", "edit_settings");
|
||||||
|
my $icon = FW_iconName($iconName) ? FW_makeImage($iconName,$iconName,"icon") : "";
|
||||||
|
$icon = "<a name=\"$d.edit\" onclick=\"weekprofile_DoEditWeek('$d')\" href=\"javascript:void(0)\">$icon</a>";
|
||||||
|
|
||||||
|
my $lnk = AttrVal($d, "alias", $d);
|
||||||
|
$lnk = "<a name=\"$d.detail\" href=\"$FW_ME$FW_subdir?detail=$d\">$lnk</a>" if($show_links);
|
||||||
|
|
||||||
|
my $args = "weekprofile";
|
||||||
|
my $curr = $hash->{PROFILES}[0]->{NAME};
|
||||||
|
|
||||||
|
$html .= "<table>";
|
||||||
|
$html .= "<tr><td>";
|
||||||
|
$html .= "<div class=\"devType\" id=\"weekprofile.$d.header\">";
|
||||||
|
$html .= "<div class=\"devType\" id=\"weekprofile.menu.base\">";
|
||||||
|
$html .= $icon." ".$lnk;
|
||||||
|
$html .= "</di></div></td></tr>";
|
||||||
|
$html .= "<tr><td>";
|
||||||
|
$html .= "<div class=\"fhemWidget\" informId=\"$d\" cmd=\"\" arg=\"$args\" current=\"$curr\" dev=\"$d\">"; # div tag to support inform updates
|
||||||
|
$html .= "</div>";
|
||||||
|
$html .= "</td></tr>";
|
||||||
|
$html .= "</table>";
|
||||||
|
return $html;
|
||||||
|
}
|
||||||
|
1;
|
||||||
|
|
||||||
|
=pod
|
||||||
|
|
||||||
|
=begin html
|
||||||
|
|
||||||
|
<a name="weekprofile"></a>
|
||||||
|
<h3>weekprofile</h3>
|
||||||
|
<ul>
|
||||||
|
<b>ToDo: Übersetzung</b><br>
|
||||||
|
|
||||||
|
Mit dem Modul 'weekprofile' können mehrere Wochenprofile verwaltet und an unterschiedliche Geräte
|
||||||
|
übertragen werden. Aktuell werden folgende Hardware unterstützt:
|
||||||
|
<li>alle MAX Thermostate</li>
|
||||||
|
<li>Homatic HM-CC-RT-DN </li>
|
||||||
|
<li>Homatic HM-CC-TC </li>
|
||||||
|
<li>Homatic HM-TC-IT-WM-W-EU</li>
|
||||||
|
|
||||||
|
Im Standardfall wird das Modul mit einem Geräte = 'Master-Gerät' assoziiert,
|
||||||
|
um das Wochenprofil vom Gerät grafisch bearbeiten zu können und andere Profile auf das Gerät zu bringen.
|
||||||
|
<br>
|
||||||
|
<b>Achtung:</b> Das Übertragen von Wochenprofilen erfordet eine Menge an Credits.
|
||||||
|
Dies wird vom Modul nicht berücksichtigt. So kann es sein, dass nach dem
|
||||||
|
Setzen\Aktualisieren eines Profils das Proil im Modul nicht mit dem Profil im Gerät
|
||||||
|
übereinstimmt.
|
||||||
|
<br><br>
|
||||||
|
<a name="weekprofiledefine"></a>
|
||||||
|
<b>Define</b>
|
||||||
|
<ul>
|
||||||
|
<code>define <name> weekprofile [master device]</code><br>
|
||||||
|
<br>
|
||||||
|
Aktiviert das Modul. Bei der Angabe eines 'Master-Gerätes' wird das Profil 'master'
|
||||||
|
entprechende dem Wochenrofil vom Gerät angelegt.
|
||||||
|
Sonderbehandlung des 'master' Profils:
|
||||||
|
<li>Kann nicht gelöscht werden</li>
|
||||||
|
<li>Bei Ändern\Setzen des Proils wird es automatisch an das 'Master-Geräte' gesendet</li>
|
||||||
|
<li>Es wird sind mit abgespeicht</li>
|
||||||
|
<br>
|
||||||
|
Wird kein 'Master-Gerätes' angegeben, wird ein 'default' Profil angelegt.
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<a name="weekprofileset"></a>
|
||||||
|
<b>Set</b>
|
||||||
|
<ul>
|
||||||
|
<li>profile_data<br>
|
||||||
|
<code>set <name> profile_data <profilname> <json data> </code><br>
|
||||||
|
Es wird das Profil 'profilname' geändert. Die Profildaten müssen im json-Format übergeben werden.
|
||||||
|
</li>
|
||||||
|
<li>send_to_device<br>
|
||||||
|
<code>set <name> send_to_device <profilname> [device] </code><br>
|
||||||
|
Das Profil wird an ein Gerät übertragen. Wird kein Gerät angegeben, wird das 'Master-Gerät' verwendet.
|
||||||
|
</li>
|
||||||
|
<li>copy_profile<br>
|
||||||
|
<code>set <name> copy_profile <quelle> <ziel> </code><br>
|
||||||
|
Kopiert das Profil 'quelle' auf 'ziel'. 'ziel' wird überschrieben oder neu angelegt.
|
||||||
|
</li>
|
||||||
|
<li>remove_profile<br>
|
||||||
|
<code>set <name> remove_profile <profilname> </code><br>
|
||||||
|
Das Profil 'profilname' wird gelöscht.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<a name="weekprofileget"></a>
|
||||||
|
<b>Get</b>
|
||||||
|
<ul>
|
||||||
|
<li>profile_data<br>
|
||||||
|
<code>get <name> profile_data <profilname> </code><br>
|
||||||
|
Liefert die Profildaten von 'profilname' im json-Format
|
||||||
|
</li>
|
||||||
|
<li>profile_names<br>
|
||||||
|
<code>set <name> profile_names</code><br>
|
||||||
|
Liefert alle Profilnamen getrennt durch ','
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<a name="weekprofileattr"></a>
|
||||||
|
<b>Attribute</b>
|
||||||
|
<ul>
|
||||||
|
<li>widgetWeekdays<br>
|
||||||
|
Liste von Wochentagen getrennt durch ',' welche im Widget angzeigt werden.
|
||||||
|
Beginnend bei Montag. z.B.
|
||||||
|
<code>attr name widgetWeekdays Montag,Dienstag,Mittwoch,Donnerstag,Freitag,Samstag,Sonntag</code>
|
||||||
|
</li>
|
||||||
|
<li>configFile<br>
|
||||||
|
Pfad und Dateiname wo die Profile gespeichert werden sollen.
|
||||||
|
Default: ./log/weekprofile-<name>.cfg
|
||||||
|
</li>
|
||||||
|
<li>icon<br>
|
||||||
|
Änders des Icons zum Bearbeiten
|
||||||
|
Default: edit_settings
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
=end html
|
||||||
|
|
||||||
|
=cut
|
@ -664,3 +664,6 @@
|
|||||||
- added new function for running terms
|
- added new function for running terms
|
||||||
- improved commandref
|
- improved commandref
|
||||||
|
|
||||||
|
- Wed Dec 23 2015 (risiko)
|
||||||
|
- added new module 98_weekprofile to manage week profiles
|
||||||
|
|
||||||
|
@ -329,6 +329,7 @@ FHEM/98_structure.pm rudolfkoenig http://forum.fhem.de Automatis
|
|||||||
FHEM/98_telnet.pm rudolfkoenig http://forum.fhem.de Automatisierung
|
FHEM/98_telnet.pm rudolfkoenig http://forum.fhem.de Automatisierung
|
||||||
FHEM/98_update.pm rudolfkoenig http://forum.fhem.de Sonstiges
|
FHEM/98_update.pm rudolfkoenig http://forum.fhem.de Sonstiges
|
||||||
FHEM/98_weblink.pm rudolfkoenig http://forum.fhem.de Frontends
|
FHEM/98_weblink.pm rudolfkoenig http://forum.fhem.de Frontends
|
||||||
|
FHME/98_weekprofile.pm risiko http://forum.fhem.de Frontends
|
||||||
FHEM/99_SUNRISE_EL.pm rudolfkoenig http://forum.fhem.de Automatisierung
|
FHEM/99_SUNRISE_EL.pm rudolfkoenig http://forum.fhem.de Automatisierung
|
||||||
FHEM/99_Utils.pm rudolfkoenig http://forum.fhem.de Automatisierung
|
FHEM/99_Utils.pm rudolfkoenig http://forum.fhem.de Automatisierung
|
||||||
FHEM/Blocking.pm rudolfkoenig http://forum.fhem.de Automatisierung
|
FHEM/Blocking.pm rudolfkoenig http://forum.fhem.de Automatisierung
|
||||||
@ -380,6 +381,7 @@ www/pgm2/fhemweb_readingsHistory.js justme1968 http://forum.fhem.de Frontends
|
|||||||
www/pgm2/fhemweb_sortable.js markusbloch http://forum.fhem.de Frontends
|
www/pgm2/fhemweb_sortable.js markusbloch http://forum.fhem.de Frontends
|
||||||
www/pgm2/fhemweb_fbcalllist.js markusbloch http://forum.fhem.de Frontends
|
www/pgm2/fhemweb_fbcalllist.js markusbloch http://forum.fhem.de Frontends
|
||||||
www/pgm2/fhemweb_uzsu.js justme1968 http://forum.fhem.de Frontends
|
www/pgm2/fhemweb_uzsu.js justme1968 http://forum.fhem.de Frontends
|
||||||
|
www/pgm2/fhemweb_weekprofile.js risiko http://forum.fhem.de Frontends
|
||||||
www/pgm2/* rudolfkoenig http://forum.fhem.de Frontends
|
www/pgm2/* rudolfkoenig http://forum.fhem.de Frontends
|
||||||
www/jscolor/* justme1968 http://forum.fhem.de Frontends
|
www/jscolor/* justme1968 http://forum.fhem.de Frontends
|
||||||
www/frontend/* johannnes http://forum.fhem.de Frontends
|
www/frontend/* johannnes http://forum.fhem.de Frontends
|
||||||
|
466
fhem/www/pgm2/fhemweb_weekprofile.js
Normal file
466
fhem/www/pgm2/fhemweb_weekprofile.js
Normal file
@ -0,0 +1,466 @@
|
|||||||
|
//fhemweb_weekprofile.js 0.01 2015-12-23 Risiko
|
||||||
|
|
||||||
|
//for tooltip
|
||||||
|
$(document).ready(function(){
|
||||||
|
$('[data-toggle="tooltip"]').tooltip();
|
||||||
|
});
|
||||||
|
|
||||||
|
var shortDays = ["Mon","Tue","Wed","Thu","Fri","Sat","Sun"];
|
||||||
|
|
||||||
|
function FW_weekprofileInputDialog(title,inp,parent, callback)
|
||||||
|
{
|
||||||
|
var div = $("<div id='FW_weekprofileInputDiolog'>");
|
||||||
|
var content = $('<input type="'+inp+'">').get(0);
|
||||||
|
$(div).append(title);
|
||||||
|
$(div).append(content);
|
||||||
|
$("body").append(div);
|
||||||
|
$(div).dialog({
|
||||||
|
dialogClass:"no-close",modal:true, width:"auto", closeOnEscape:true,
|
||||||
|
maxWidth:$(window).width()*0.9, maxHeight:$(window).height()*0.9,
|
||||||
|
title: title,
|
||||||
|
buttons: [{text:"OK", click:function(){
|
||||||
|
$(this).dialog("close");
|
||||||
|
$(div).remove();
|
||||||
|
if(callback)
|
||||||
|
callback(content.value,1);
|
||||||
|
}},{text:"CANCEL", click:function(){
|
||||||
|
$(this).dialog("close");
|
||||||
|
$(div).remove();
|
||||||
|
content.value = null;
|
||||||
|
if(callback)
|
||||||
|
callback(content.value,0);
|
||||||
|
}}]
|
||||||
|
});
|
||||||
|
|
||||||
|
if(parent)
|
||||||
|
$(div).dialog( "option", "position", {
|
||||||
|
my: "left top", at: "right bottom",
|
||||||
|
of: parent, collision: "flipfit"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function weekprofile_DoEditWeek(devName)
|
||||||
|
{
|
||||||
|
var widget = $('div[informid="'+devName+'"]').get(0);
|
||||||
|
widget.MODE = 'EDIT';
|
||||||
|
|
||||||
|
$(widget.MENU.BASE).hide();
|
||||||
|
|
||||||
|
widget.setValueFn("REUSEPRF");
|
||||||
|
}
|
||||||
|
|
||||||
|
function FW_weekprofilePRFCached(devName,select)
|
||||||
|
{
|
||||||
|
var widget = $('div[informid="'+devName+'"]').get(0)
|
||||||
|
|
||||||
|
var prfName = select.options[select.selectedIndex].value;
|
||||||
|
|
||||||
|
widget.CURPRF = prfName;
|
||||||
|
widget.PROFILE = null;
|
||||||
|
FW_queryValue('get '+devName+' profile_data '+prfName, widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
function FW_weekprofileSendToDev(devName,lnk)
|
||||||
|
{
|
||||||
|
var widget = $('div[informid="'+devName+'"]').get(0)
|
||||||
|
|
||||||
|
FW_weekprofileInputDialog("<span>Device:</span>","text",lnk,function(device,ok){
|
||||||
|
if (!device || device.length <=0)
|
||||||
|
return;
|
||||||
|
FW_cmd(FW_root+"?cmd=set "+widget.DEVICE+" send_to_device "+widget.CURPRF+" "+device+"&XHR=1",function(arg) {FW_weekprofileSendCallback(widget.DEVICE,arg);});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function FW_weekprofileCopyPrf(devName,lnk)
|
||||||
|
{
|
||||||
|
var widget = $('div[informid="'+devName+'"]').get(0)
|
||||||
|
|
||||||
|
FW_weekprofileInputDialog("<span>Name:</span>","text",lnk,function(name,ok){
|
||||||
|
if (!name || name.length <=0)
|
||||||
|
return;
|
||||||
|
FW_cmd(FW_root+"?cmd=set "+widget.DEVICE+" copy_profile "+widget.CURPRF+" "+name+"&XHR=1",function(arg) {FW_weekprofileSendCallback(widget.DEVICE,arg);});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function FW_weekprofileRemovePrf(devName,lnk)
|
||||||
|
{
|
||||||
|
var widget = $('div[informid="'+devName+'"]').get(0)
|
||||||
|
|
||||||
|
FW_weekprofileInputDialog("<p>Delete Profile: '"+widget.CURPRF+"' ?</p>","hidden",lnk,function(name,ok){
|
||||||
|
if (ok < 1)
|
||||||
|
return;
|
||||||
|
FW_cmd(FW_root+"?cmd=set "+widget.DEVICE+" remove_profile "+widget.CURPRF+"&XHR=1",function(arg) {FW_weekprofileSendCallback(widget.DEVICE,arg);});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function FW_weekprofileShow(widget)
|
||||||
|
{
|
||||||
|
$(widget.MENU.BASE).show();
|
||||||
|
$(widget.MENU.CONTENT).empty();
|
||||||
|
|
||||||
|
var html='';
|
||||||
|
|
||||||
|
if (widget.PROFILENAMES) {
|
||||||
|
html += " "
|
||||||
|
html += "<select name=\"PROFILES\" onchange=\"FW_weekprofilePRFCached('"+widget.DEVICE+"',this)\">";
|
||||||
|
for (var k=0; k < widget.PROFILENAMES.length; k++)
|
||||||
|
{
|
||||||
|
var selected = (widget.CURPRF == widget.PROFILENAMES[k]) ? "selected " : "";
|
||||||
|
html += "<option "+selected+"value=\""+widget.PROFILENAMES[k]+"\">"+widget.PROFILENAMES[k]+"</option>";
|
||||||
|
}
|
||||||
|
html += "</select>";
|
||||||
|
|
||||||
|
html += " "
|
||||||
|
html += "<button type=\"button\"onclick=\"FW_weekprofileCopyPrf('"+widget.DEVICE+"',this)\" data-toggle=\"tooltip\" title=\"copy profile\">+</button>";
|
||||||
|
|
||||||
|
html += " "
|
||||||
|
html += "<button type=\"button\" onclick=\"FW_weekprofileRemovePrf('"+widget.DEVICE+"',this)\" data-toggle=\"tooltip\" title=\"remove profile\">-</button>";
|
||||||
|
|
||||||
|
html += " "
|
||||||
|
html += "<button type=\"button\" onclick=\"FW_weekprofileSendToDev('"+widget.DEVICE+"',this)\" data-toggle=\"tooltip\" title=\"send to device\">--></button>";
|
||||||
|
|
||||||
|
$(widget.MENU.CONTENT).append(html);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!widget.PROFILE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var table = widget.CONTENT;
|
||||||
|
for (var i = 0; i < shortDays.length; ++i) {
|
||||||
|
$(table).append('<tr class="'+ ( (i+1)%2==0 ? 'even':'odd')+ '"><td>'+shortDays[i]+'</td></tr>');
|
||||||
|
|
||||||
|
var tr = $(table).find("tr").get(i);
|
||||||
|
|
||||||
|
for (var k = 0; k < widget.PROFILE[shortDays[i]]['temp'].length; ++k) {
|
||||||
|
|
||||||
|
var str = '';
|
||||||
|
k>0 ? str = widget.PROFILE[shortDays[i]]['time'][k-1] : str = '00:00';
|
||||||
|
str = str + '-' + widget.PROFILE[shortDays[i]]['time'][k];
|
||||||
|
|
||||||
|
$(tr).append('<td>'+str+ '</td>');
|
||||||
|
|
||||||
|
str = widget.PROFILE[shortDays[i]]['temp'][k]+' °C';
|
||||||
|
$(tr).append('<td>'+str+ '</td>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function FW_weekprofileEditTimeChanged(inp)
|
||||||
|
{
|
||||||
|
if (inp == null) {return;}
|
||||||
|
var times = inp.value.split(':');
|
||||||
|
if (times.length == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var hour = parseInt(times[0]);
|
||||||
|
var min = (times.length==2) ? parseInt(times[1]): 0;
|
||||||
|
|
||||||
|
inp.value = ((hour<10)?("0"+hour):hour) +":"+ ((min<10)?("0"+min):min);
|
||||||
|
|
||||||
|
//set new end time as new start time for the next interval
|
||||||
|
var nexttr = inp.parentNode.parentNode.nextSibling;
|
||||||
|
if (nexttr!=null){
|
||||||
|
nexttr.firstChild.firstChild.innerHTML=inp.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function FW_weekprofileEditRowStyle(table)
|
||||||
|
{
|
||||||
|
var alltr = $(table).find("tr");
|
||||||
|
for (var i = 0; i < alltr.length; ++i){
|
||||||
|
var delButton = $(alltr[i]).find('input[name="DEL"]');
|
||||||
|
var addButton = $(alltr[i]).find('input[name="ADD"]');
|
||||||
|
var inp = $(alltr[i]).find('input[name="ENDTIME"]');
|
||||||
|
|
||||||
|
$(alltr[i]).attr('class',(i%2==0)? "odd":"even");
|
||||||
|
delButton.attr('type',"button");
|
||||||
|
addButton.attr('type',"button");
|
||||||
|
inp.removeAttr('style');
|
||||||
|
inp.removeAttr('readonly');
|
||||||
|
|
||||||
|
FW_weekprofileEditTimeChanged(inp.get(0));
|
||||||
|
|
||||||
|
if (i==0){
|
||||||
|
$(alltr[i]).find('span[name="STARTTIME"]').get(0).innerHTML = "00:00";
|
||||||
|
if (alltr.length == 1){
|
||||||
|
delButton.attr('type',"hidden");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i==alltr.length-1){
|
||||||
|
if (alltr.length > 1){
|
||||||
|
addButton.attr('type',"hidden");
|
||||||
|
}
|
||||||
|
inp.attr('style',"border:none;background:transparent;box-shadow:none");
|
||||||
|
inp.get(0).value = "24:00";
|
||||||
|
inp.attr('readonly',true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function FW_weekprofileEditAddInterval(tr)
|
||||||
|
{
|
||||||
|
var newtr = $(tr).clone(true);
|
||||||
|
|
||||||
|
var alltr = $(tr).parent().children();
|
||||||
|
for (var i = 0; i < alltr.length; ++i) {
|
||||||
|
if ( $(alltr[i]).is($(tr))) {
|
||||||
|
newtr.insertAfter($(alltr[i]));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FW_weekprofileEditRowStyle($(tr).parent());
|
||||||
|
|
||||||
|
var timSel = newtr.find('input[name="ENDTIME"]');
|
||||||
|
|
||||||
|
if (alltr.length == 1)
|
||||||
|
timSel = $(tr).find('input[name="ENDTIME"]');
|
||||||
|
|
||||||
|
timSel.focus();
|
||||||
|
timSel.select();
|
||||||
|
}
|
||||||
|
|
||||||
|
function FW_weekprofileEditDelInterval(tr)
|
||||||
|
{
|
||||||
|
var parent = $(tr).parent();
|
||||||
|
$(tr).remove();
|
||||||
|
FW_weekprofileEditRowStyle(parent)
|
||||||
|
}
|
||||||
|
|
||||||
|
function FW_weekprofileEditDay(widget,day)
|
||||||
|
{
|
||||||
|
var div = $("<div>").get(0);
|
||||||
|
$(div).append("<div style=\"margin-left:10px;margin:5px\">"+widget.WEEKDAYS[day]+"</div>");
|
||||||
|
|
||||||
|
var table = $("<table>").get(0);
|
||||||
|
$(table).attr('id',"weekprofile."+widget.DEVICE+"."+shortDays[day]);
|
||||||
|
$(table).attr('class',"block wide weekprofile");
|
||||||
|
|
||||||
|
var html;
|
||||||
|
var times = widget.PROFILE[shortDays[day]]['time'];
|
||||||
|
var temps = widget.PROFILE[shortDays[day]]['temp'];
|
||||||
|
|
||||||
|
for (var i = 0; i < times.length; ++i) {
|
||||||
|
var startTime = (i>0) ? times[i-1] : "00:00";
|
||||||
|
var endTime = (i<times.length-1) ? times[i] : "24:00";
|
||||||
|
|
||||||
|
html += "<tr>";
|
||||||
|
//from
|
||||||
|
html += "<td><span name=\"STARTTIME\">"+startTime+"</span></td>";
|
||||||
|
|
||||||
|
html += "<td>-</td>";
|
||||||
|
//to
|
||||||
|
html += "<td><input type=\"text\" name=\"ENDTIME\" size=\"5\" maxlength=\"5\" align=\"center\" value=\""+endTime+"\" onblur=\"FW_weekprofileEditTimeChanged(this)\"/></td>";
|
||||||
|
|
||||||
|
//temp
|
||||||
|
html += "<td><select name=\"TEMP\" size=\"1\">";
|
||||||
|
for (var k=5; k <= 30; k+=.5)
|
||||||
|
{
|
||||||
|
var selected = (k == temps[i]) ? "selected " : "";
|
||||||
|
html += "<option "+selected+"value=\""+k.toFixed(1)+"\">"+k.toFixed(1)+"</option>";
|
||||||
|
}
|
||||||
|
html += "</select></td>";
|
||||||
|
//ADD-Button
|
||||||
|
html += "<td><input type=\"button\" name=\"ADD\" value=\"+\" onclick=\"FW_weekprofileEditAddInterval(this.parentNode.parentNode)\"></td>";
|
||||||
|
//DEL-Button
|
||||||
|
html += "<td><input type=\"button\" name=\"DEL\" value=\"-\" onclick=\"FW_weekprofileEditDelInterval(this.parentNode.parentNode)\"></td>";
|
||||||
|
html += "</tr>";
|
||||||
|
}
|
||||||
|
$(table).append(html);
|
||||||
|
$(div).append(table);
|
||||||
|
FW_weekprofileEditRowStyle(table);
|
||||||
|
return div;
|
||||||
|
}
|
||||||
|
|
||||||
|
function FW_weekprofileEditWeek(widget)
|
||||||
|
{
|
||||||
|
var table = widget.CONTENT;
|
||||||
|
var daysInRow = 2;
|
||||||
|
|
||||||
|
$(table).append('<tr>');
|
||||||
|
var tr = $(table).find("tr:last");
|
||||||
|
|
||||||
|
for (var i = 0; i < shortDays.length; ++i) {
|
||||||
|
tr.append('<td>');
|
||||||
|
tr.find('td:last').append(FW_weekprofileEditDay(widget,i));
|
||||||
|
|
||||||
|
if ((i+1)%daysInRow == 0){
|
||||||
|
$('<tr>').insertAfter(tr);
|
||||||
|
tr = $(table).find("tr:last");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tr.append("<td><table><tr>");
|
||||||
|
tr = tr.find("tr:last");
|
||||||
|
tr.append("<td><input type=\"button\" value=\"Speichern\" onclick=\"FW_weekprofilePrepAndSendProf('"+widget.DEVICE+"')\">");
|
||||||
|
tr.append("<td><input type=\"button\" value=\"Abbrechen\" onclick=\"FW_weekprofileEditAbort('"+widget.DEVICE+"')\">");
|
||||||
|
}
|
||||||
|
|
||||||
|
function FW_weekprofileSendCallback(devName, data)
|
||||||
|
{
|
||||||
|
var widget = $('div[informid="'+devName+'"]').get(0);
|
||||||
|
if(!data.match(/^[\r\n]*$/)) // ignore empty answers
|
||||||
|
FW_okDialog('<pre>'+data+'</pre>',widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
function FW_weekprofilePrepAndSendProf(devName)
|
||||||
|
{
|
||||||
|
var widget = $('div[informid="'+devName+'"]').get(0);
|
||||||
|
|
||||||
|
var tableDay = $(widget).find("table[id*=\"weekprofile."+devName+"\"]");
|
||||||
|
|
||||||
|
if (tableDay.length == 0){
|
||||||
|
FW_errmsg(widget.DEVICE+" internal error ",10000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var prf=new Object();
|
||||||
|
for (var i = 0; i < tableDay.length; ++i) {
|
||||||
|
var timeEL = $(tableDay[i]).find('input[name="ENDTIME"]');
|
||||||
|
var tempEL = $(tableDay[i]).find('select[name="TEMP"]');
|
||||||
|
|
||||||
|
if (timeEL.length != tempEL.length){
|
||||||
|
FW_errmsg(widget.DEVICE+" internal error ",10000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var id = $(tableDay[i]).attr('id').split('.');
|
||||||
|
var day = id[2];
|
||||||
|
|
||||||
|
prf[day] = new Object();
|
||||||
|
prf[day]['time'] = new Array();
|
||||||
|
prf[day]['temp'] = new Array();
|
||||||
|
|
||||||
|
for (var k = 0; k < timeEL.length; ++k) {
|
||||||
|
prf[day]['time'].push(timeEL[k].value);
|
||||||
|
prf[day]['temp'].push(tempEL[k].value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
var data=JSON.stringify(prf);
|
||||||
|
FW_cmd(FW_root+"?cmd=set "+widget.DEVICE+" profile_data "+widget.CURPRF+" "+data+"&XHR=1",function(arg) {FW_weekprofileSendCallback(widget.DEVICE,arg);});
|
||||||
|
} catch(e){
|
||||||
|
FW_errmsg(devName+" Parameter "+e,5000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < shortDays.length; ++i) {
|
||||||
|
var day = shortDays[i];
|
||||||
|
if (prf[day] != null){
|
||||||
|
widget.PROFILE[day] = prf[day];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
widget.MODE = "SHOW";
|
||||||
|
widget.setValueFn("REUSEPRF");
|
||||||
|
}
|
||||||
|
|
||||||
|
function FW_weekprofileEditAbort(devName)
|
||||||
|
{
|
||||||
|
var widget = $('div[informid="'+devName+'"]').get(0);
|
||||||
|
widget.MODE = "SHOW";
|
||||||
|
widget.setValueFn("REUSEPRF");
|
||||||
|
}
|
||||||
|
|
||||||
|
function FW_weekprofileSetValue(devName,data)
|
||||||
|
{
|
||||||
|
var widget = $('div[informid="'+devName+'"]').get(0);
|
||||||
|
$(widget.CONTENT).empty();
|
||||||
|
|
||||||
|
var prf={};
|
||||||
|
try {
|
||||||
|
(data == "REUSEPRF") ? prf = widget.PROFILE : prf=JSON.parse(data);
|
||||||
|
} catch(e){
|
||||||
|
console.log(devName+" error parsing json '" +data+"'");
|
||||||
|
FW_errmsg(devName+" Parameter "+e,5000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
widget.PROFILE = prf;
|
||||||
|
if (widget.MODE == 'SHOW' || widget.MODE == 'CREATE')
|
||||||
|
{
|
||||||
|
FW_weekprofileShow(widget);
|
||||||
|
}
|
||||||
|
else if (widget.MODE == 'EDIT')
|
||||||
|
{
|
||||||
|
FW_weekprofileEditWeek(widget);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FW_errmsg(devName+" unknown Mode",10000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function FW_weekprofileGetValues(devName,what,data)
|
||||||
|
{
|
||||||
|
if(data.match(/^[\r\n]*$/)) {return;}
|
||||||
|
|
||||||
|
var widget = $('div[informid="'+devName+'"]').get(0);
|
||||||
|
|
||||||
|
if (what == "WEEKDAYS"){
|
||||||
|
widget.WEEKDAYS = data.split(',');
|
||||||
|
} else if (what == "PROFILENAMES") {
|
||||||
|
widget.PROFILENAMES = data.split(',');
|
||||||
|
if (widget.MODE != 'EDIT') {
|
||||||
|
widget.setValueFn("REUSEPRF");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function
|
||||||
|
FW_weekprofileCreate(elName, devName, vArr, currVal, set, params, cmd)
|
||||||
|
{
|
||||||
|
if( 0 ) {
|
||||||
|
console.log( "elName: "+elName );
|
||||||
|
console.log( "devName: "+devName );
|
||||||
|
console.log( "vArr: "+vArr );
|
||||||
|
console.log( "currVal: "+currVal );
|
||||||
|
console.log( "set: "+set );
|
||||||
|
console.log( "params: "+params );
|
||||||
|
console.log( "cmd: "+cmd );
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!vArr.length || vArr[0] != "weekprofile")
|
||||||
|
return undefined;
|
||||||
|
|
||||||
|
var widget = $('div[informid="'+devName+'"]').get(0);
|
||||||
|
|
||||||
|
var content = $('<table class="block wide weekprofile" id="weekprofile_content">').get(0);
|
||||||
|
$(widget).append(content);
|
||||||
|
|
||||||
|
widget.CONTENT = content;
|
||||||
|
widget.HEADER = $('div[id="weekprofile.'+devName+'.header"]').get(0);
|
||||||
|
|
||||||
|
widget.MENU = new Object();
|
||||||
|
widget.MENU.BASE = $(widget.HEADER).find('div[id*="menu.base"]').get(0);
|
||||||
|
|
||||||
|
var menu = $('<div class="devType" id="weekprofile.menu.content" style="display:inline;padding:0px;margin:0px;">').get(0);
|
||||||
|
$(widget.MENU.BASE).append(menu);
|
||||||
|
widget.MENU.CONTENT = menu;
|
||||||
|
|
||||||
|
//inform profile_count changed
|
||||||
|
var prfCnt = $('<div informid="'+devName+'-profile_count" style="display:none">').get(0);
|
||||||
|
prfCnt.setValueFn = function(arg){
|
||||||
|
FW_cmd(FW_root+'?cmd=get '+devName+' profile_names&XHR=1',function(data){FW_weekprofileGetValues(devName,"PROFILENAMES",data);});
|
||||||
|
}
|
||||||
|
$(widget.HEADER).append(prfCnt);
|
||||||
|
|
||||||
|
widget.MODE = 'CREATE';
|
||||||
|
widget.DEVICE = devName;
|
||||||
|
widget.WEEKDAYS = shortDays.slice();
|
||||||
|
widget.CURPRF = currVal;
|
||||||
|
|
||||||
|
widget.setValueFn = function(arg){FW_weekprofileSetValue(devName,arg);}
|
||||||
|
widget.activateFn = function(arg){
|
||||||
|
FW_queryValue('get '+devName+' profile_data '+widget.CURPRF, widget);
|
||||||
|
FW_cmd(FW_root+'?cmd={AttrVal("'+devName+'","widgetWeekdays","")}&XHR=1',function(data){FW_weekprofileGetValues(devName,"WEEKDAYS",data);});
|
||||||
|
FW_cmd(FW_root+'?cmd=get '+devName+' profile_names&XHR=1',function(data){FW_weekprofileGetValues(devName,"PROFILENAMES",data);});
|
||||||
|
};
|
||||||
|
return widget;
|
||||||
|
}
|
||||||
|
|
||||||
|
FW_widgets['weekprofile'] = {
|
||||||
|
createFn:FW_weekprofileCreate,
|
||||||
|
};
|
Loading…
x
Reference in New Issue
Block a user