| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825 |
- #################################################################################
- #
- # $Id: 89_VCONTROL.pm 11776 2016-07-10 13:57:22Z adamwit $
- #
- # FHEM Module for Viessman Vitotronic200 / Typ KW1 und KW2
- #
- # Derived from 89_VCONTROL.pm: Copyright (C) Adam WItalla
- #
- #
- # This program is free software; you can redistribute it and/or
- # modify it under the terms of the GNU General Public License
- # as published by the Free Software Foundation; either version 2
- # of the License, or (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program; if not, write to the Free Software
- # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- #
- # The GNU General Public License may also be found at http://www.gnu.org/licenses/gpl-2.0.html .
- #
- ###########################
- #package main;
- use strict;
- use warnings;
- use Time::HiRes qw(gettimeofday);
- use Time::Local;
- # Helper Constants
- use constant NO_SEND => 9999;
- use constant POLL_ACTIVE => 1;
- use constant POLL_PAUSED => 0;
- use constant READ_ANSWER => 1;
- use constant READ_UNDEF => 0;
- use constant GET_TIMER_ACTIVE => 1;
- use constant GET_TIMER_PAUSED => 0;
- use constant GET_CONFIG_ACTIVE => 1;
- use constant GET_CONFIG_PAUSED => 0;
- use constant PROTOCOL_KW => 1;
- use constant PROTOCOL_GWG => 2;
- use constant PROTOCOL_300 => 3;
- my $viess_protocol = PROTOCOL_KW;
- #Poll Parameter
- my $defaultPollInterval = 180;
- my $last_cmd = 0;
- my $poll_now = POLL_PAUSED;
- my $get_timer_now = GET_TIMER_PAUSED;
- my $get_config_now = GET_CONFIG_PAUSED;
- my $command_config_file = "";
- my $poll_duration = 0;
- #Send Parameter
- my $send_now = NO_SEND;
- my $send_additonal_param="";
- #Get Parameter
- #Answer Parameter
- my $read_now = READ_UNDEF;
- #actually used command list
- my @cmd_list;
- my @poll_cmd_list;
- my @write_cmd_list;
- my @timer_cmd_list;
- my @set_cmd_list;
- my @get_timer_cmd_list;
- #remember days for daystart values
- my %DayHash;
- #States the Heater can be set to
- my @mode = ("WW","RED","NORM","H+WW","H+WW FS","ABSCHALT");
- my $temp_mode=0;
- #define TCP Connection (1) or USB device (0)
- my $TCP_CONNECTION = 0;
- ######################################################################################
- sub VCONTROL_1ByteUParse($$);
- sub VCONTROL_1ByteU2Parse($$);
- sub VCONTROL_1ByteSParse($$);
- sub VCONTROL_2ByteSParse($$);
- sub VCONTROL_2ByteUParse($$);
- sub VCONTROL_1ByteHexParse($);
- sub VCONTROL_2ByteHexParse($);
- sub VCONTROL_2BytePercentParse($$);
- sub VCONTROL_4ByteParse($$);
- sub VCONTROL_timerParse($);
- sub VCONTROL_ModusParse($);
- sub VCONTROL_DateParse($);
- sub VCONTROL_1ByteUConv($$);
- sub VCONTROL_1ByteSConv($$);
- sub VCONTROL_1ByteUx10Conv($);
- sub VCONTROL_2ByteUConv($$);
- sub VCONTROL_2ByteSConv($$);
- sub VCONTROL_DateConv($);
- sub VCONTROL_TimerConv($$);
- sub VCONTROL_RegisterConv($);
- sub VCONTROL_Clear($);
- sub VCONTROL_Read($);
- sub VCONTROL_Ready($);
- sub VCONTROL_Parse($$$$);
- sub VCONTROL_Poll($);
- sub VCONTROL_CmdConfig($);
- sub VCONTROL_ReInit($);
- sub VCONTROL_Initialize($)
- {
- my ($hash) = @_;
- require "$attr{global}{modpath}/FHEM/DevIo.pm";
- $hash->{ReadFn} = "VCONTROL_Read";
- #$hash->{WriteFn} = "VCONTROL_Write";
- $hash->{ReadyFn} = "VCONTROL_Ready";
- $hash->{DefFn} = "VCONTROL_Define";
- $hash->{UndefFn} = "VCONTROL_Undef";
- $hash->{SetFn} = "VCONTROL_Set";
- $hash->{GetFn} = "VCONTROL_Get";
- $hash->{StateFn} = "VCONTROL_SetState";
- $hash->{ShutdownFn} = "VCONTROL_Shutdown";
- $hash->{AttrList} = "disable:0,1 init_every_poll:0,1 update_only_changes:0,1 setList closedev:0,1 ". $readingFnAttributes;
- }
- #####################################
- # define <name> VIESSMANN <port> <command_config> [<interval>]
- sub VCONTROL_Define($$)
- {
- my ($hash, $def) = @_;
- my @a = split("[ \t][ \t]*", $def);
- my $po;
-
- if (@a != 4 && @a != 5) {
- my $msg = "wrong syntax: define <name> VCONTROL <port> <command_config> [<interval>]";
- Log3 undef, 2, $msg;
- return $msg;
- }
- #Determine if USB device or TCP Connection is used
-
- if (index($a[2], ':') == -1) {
- ###USB
- delete $hash->{USBDev};
- delete $hash->{FD};
- }
- else {
- ###TCP Connection
- $TCP_CONNECTION = 1;
- }
- #Close Device to initialize properly
- DevIo_CloseDev($hash);
- my $name = $a[0];
- my $dev = $a[2];
- #check existence of config_file
- if($a[3]){
- $command_config_file = $a[3];
-
- if(-e $command_config_file){
- Log3 $name, 3, "VCONTROL: Define open DATEI '$command_config_file'";
- VCONTROL_CmdConfig($command_config_file);
- }
- else {
- my $msg = "config file $command_config_file does not exist";
- Log3 undef, 2, $msg;
- return $msg;
- }
- }
-
- #set command list to poll list
- @cmd_list = @poll_cmd_list;
-
- #use configured Pollinterval if given
- if($a[4]){
- $hash->{INTERVAL} = $a[4];
- }
- else {
- $hash->{INTERVAL} = $defaultPollInterval;
- }
- $hash->{STATE} = "defined";
- $hash->{DeviceName} = $dev;
- $hash->{PARTIAL} = "";
-
- #Opening USB Device
- Log3($name, 3, "VCONTROL opening VCONTROL device $dev");
-
- my $ret = undef;
-
- if ($TCP_CONNECTION == 0) {
- ###USB
- if ($^O=~/Win/) {
- require Win32::SerialPort;
- $po = new Win32::SerialPort ($dev);
- } else {
- require Device::SerialPort;
- $po = new Device::SerialPort ($dev);
- }
- if(!$po) {
- my $msg = "Can't open $dev: $!";
- Log3($name, 3, $msg) if($hash->{MOBILE});
- return $msg if(!$hash->{MOBILE});
- $readyfnlist{"$name.$dev"} = $hash;
- return "";
- }
- Log3($name, 3, "VCONTROL opened VCONTROL device $dev");
- $hash->{USBDev} = $po;
- if( $^O =~ /Win/ ) {
- $readyfnlist{"$name.$dev"} = $hash;
- } else {
- $hash->{FD} = $po->FILENO;
- delete($readyfnlist{"$name.$dev"});
- $selectlist{"$name.$dev"} = $hash;
- }
-
- #Initialize to be able to receive data
- VCONTROL_DoInit($hash, $po);
-
- }
- else {
- ###TCP Connection
- $ret = DevIo_OpenDev($hash, 0, "VCONTROL_DoInit");
- }
-
- #set Internal Timer on Polling Interval
- my $timer = gettimeofday()+1;
- Log3($name, 5, "VCONTROL set InternalTimer +1 to $timer");
- RemoveInternalTimer($hash);
- InternalTimer(gettimeofday()+1, "VCONTROL_Poll", $hash, 0);
- return $ret;
- }
- #####################################
- # Input is hexstring
- ## This function will not be used until now!
- #sub VCONTROL_Write($$)
- #{
- # my ($hash,$fn,$msg) = @_;
- # my $name = $hash->{NAME};
- #
- # return if(!defined($fn));
- #
- # my $bstring;
- # $bstring = "$fn$msg";
- # Log3 $name, 5, "$hash->{NAME} sending $bstring";
- #
- # DevIo_SimpleWrite($hash, $bstring, 1);
- #}
- #####################################
- sub VCONTROL_Undef($$)
- {
- my ($hash, $arg) = @_;
- my $name = $hash->{NAME};
- foreach my $d (sort keys %defs) {
- if(defined($defs{$d}) &&
- defined($defs{$d}{IODev}) &&
- $defs{$d}{IODev} == $hash)
- {
- my $lev = ($reread_active ? 4 : 2);
- Log3 $name, $lev, "deleting port for $d";
- delete $defs{$d}{IODev};
- }
- }
- RemoveInternalTimer($hash);
- DevIo_CloseDev($hash);
- return undef;
- }
- #####################################
- sub VCONTROL_Poll($)
- {
- my $hash = shift;
- my $name = $hash->{NAME};
- #global Module Trigger that Polling is started
- if( AttrVal($name, "disable", 0 ) == 1 )
- {
- $poll_now = POLL_PAUSED;
- Log3 $name, 5, "VCONTROL: Poll disabled!";
- }
- else
- { $poll_now = POLL_ACTIVE;
- if( AttrVal($name, "init_every_poll", 0 ) == 1 )
- {
- VCONTROL_ReInit($hash);
- }
- }
- $poll_duration = gettimeofday();
- Log3 $name, 4, "VCONTROL: Start of Poll !";
- my $timer = gettimeofday()+$hash->{INTERVAL};
- Log3($name, 5, "VCONTROL: set InternalTimer to $timer");
- InternalTimer(gettimeofday()+$hash->{INTERVAL}, "VCONTROL_Poll", $hash, 0);
- }
- #####################################
- sub VCONTROL_Shutdown($)
- {
- my ($hash) = @_;
- return undef;
- }
- #####################################
- sub VCONTROL_SetState($$$$)
- {
- my ($hash, $tim, $vt, $val) = @_;
- return undef;
- }
- #####################################
- sub VCONTROL_Clear($)
- {
- my $hash = shift;
- my $buf;
- # clear buffer:
- if($hash->{USBDev}) {
- while ($hash->{USBDev}->lookfor()) {
- $buf = DevIo_SimpleRead($hash);
- }
- }
- if($hash->{TCPDev}) {
- # TODO
- return $buf;
- }
- }
- #####################################
- sub VCONTROL_DoInit($$)
- {
- #Initialisation -> Send one 0x04 so the heating started to send 0x05 Synchronity-Bytes
- my ($hash,$po) = @_;
- my $name = $hash->{NAME};
- my $init = pack('H*', "04");
- if ($po)
- {
- #set USB Device Parameter
- $po->reset_error();
- $po->baudrate(4800);
- $po->databits(8);
- $po->parity('even');
- $po->stopbits(2);
- $po->handshake('none');
- $po->write_settings;
- }
- $defs{$name}{STATE} = "Initialized";
- DevIo_SimpleWrite($hash, $init, 0);
-
- Log3 $name, 3,"VCONTROL: Initialization";
-
- return undef;
- }
- #####################################
- # called from the global loop, when the select for hash->{FD} reports data
- sub VCONTROL_Read($)
- {
- my ($hash) = @_;
- my $name = $hash->{NAME};
- Log3 $name, 5,"VCONTROL_READ";
- # count the commands to send for complete poll sequence
- my $cmdcount = @cmd_list;
- #Read on Device
- my $mybuf = DevIo_SimpleRead($hash);
- if(!defined($mybuf) || length($mybuf) == 0) {
- #Lost connection to the device
- if ($TCP_CONNECTION == 0) {
- #USB device
- my $dev = $hash->{DeviceName};
- Log3 $name, 3,"VCONTROL: USB device $dev disconnected, waiting to reappear";
- #$hash->{USBDev}->close();
- DoTrigger($name, "DISCONNECTED");
- DevIo_Disconnected($hash);
- delete($hash->{USBDev});
- delete($selectlist{"$name.$dev"});
- $readyfnlist{"$name.$dev"} = $hash; # Start polling
- $hash->{STATE} = "disconnected";
- # Without the following sleep the open of the device causes a SIGSEGV,
- # and following opens block infinitely. Only a reboot helps.
- sleep(5);
- return "";
- }
- else {
- #TCP Connection
- my $dev = $hash->{DeviceName};
- Log3 $name, 3,"VCONTROL: LAN device $dev disconnected, waiting to reappear";
- DevIo_Disconnected($hash);
- $hash->{STATE} = "disconnected";
- return "";
- }
- }
- #msg read on device
- my $hexline = unpack('H*', $mybuf);
- Log3 $name, 5,"VCONTROL: VCONTROL_Read '$hexline'";
-
- #Append data to partial data we got before
- #ADW: 05 muss auch angehängt werden!
- if ( $read_now == READ_ANSWER && $poll_now == POLL_ACTIVE ){
- # if ( $read_now == READ_ANSWER && $poll_now == POLL_ACTIVE && $hexline ne "05"){
- $hexline = $hash->{PARTIAL}.$hexline;
- #if not received all bytes exit an read next
-
- my $receive_len = 0;
- if ($viess_protocol == PROTOCOL_KW ) {
- $receive_len = hex(substr($cmd_list[$last_cmd][1],8,2))*2;
- } elsif ($viess_protocol == PROTOCOL_GWG ) {
- $receive_len = hex(substr($cmd_list[$last_cmd][1],6,2))*2;
- }
- if ( length($hexline) < $receive_len ){
- Log3 $name, 5,"VCONTROL: VCONTROL_Read receive_len < $receive_len, $hexline";
- $hash->{PARTIAL} = $hexline;
- return"";
- }
- if ( length($hexline) > $receive_len ){
- Log3 $name, 5,"VCONTROL: VCONTROL_Read receive_len > $receive_len, $hexline : Repeat Command";
- $hash->{PARTIAL} = "";
- $read_now = READ_UNDEF;
- return"";
- }
- }
- #exit if no poll period
- #exit if no set command send
- if ($poll_now == POLL_PAUSED && $send_now == NO_SEND ){
- return "";
- }
-
- my $sendbuf="";
- #End of Poll Interval
- if ($poll_now == POLL_ACTIVE && $last_cmd == $cmdcount)
- {
- $poll_duration = (gettimeofday() - $poll_duration);
- my $duration = sprintf("%.2f", $poll_duration);
- $hash->{DURATION} = "$duration";
- Log3 $name, 4, "VCONTROL: End of Poll ! Duration: $duration";
- $poll_now = POLL_PAUSED;
- $last_cmd = 0;
- @cmd_list = @poll_cmd_list;
- $hash->{PARTIAL} = "";
- #activate timer get list if questioned
- if ($get_timer_now == GET_TIMER_ACTIVE && $send_now == NO_SEND ){
- @cmd_list = @get_timer_cmd_list;
- Log3 $name, 5, "VCONTROL: Poll TIMER!";
- RemoveInternalTimer($hash);
- VCONTROL_Poll($hash);
- $get_timer_now = GET_TIMER_PAUSED;
- }
-
- #reload config file if questioned
- if ($get_config_now == GET_CONFIG_ACTIVE ){
- VCONTROL_CmdConfig($command_config_file);
- @cmd_list = @poll_cmd_list;
- $get_config_now = GET_CONFIG_PAUSED;
- }
-
- my $closeAfterPoll = AttrVal($name, "closedev", "0");
- ###if Attribut to close after poll -> close
- if ($closeAfterPoll == 1) {
- if ($TCP_CONNECTION == 0) {
- ###USB
- delete $hash->{USBDev};
- delete $hash->{FD};
- Log3 $name, 3, "VCONTROL: USB device closed";
- }
- else {
- ###TCP Connection
- DevIo_CloseDev($hash);
- Log3 $name, 3, "VCONTROL: TCP connection closed";
- }
- }
-
- return "";
- };
- #exit if buffer just filled with 0x05 but not for mode (0x05 is a definde mode state)
- my $bufflen = length($hexline);
- my $buffhalflen = $bufflen/2;
-
- if ( $bufflen > 2 && $hexline =~ /(05){$buffhalflen,}/
- && $cmd_list[$last_cmd][2] ne "mode"
- && $cmd_list[$last_cmd][2] ne "1ByteU"
- && $cmd_list[$last_cmd][2] ne "1ByteU2"
- && $cmd_list[$last_cmd][2] ne "1ByteS"
- && $cmd_list[$last_cmd][2] ne "1ByteH"
- ){
- Log3 $name, 5, "VCONTROL: exit if buffer just filled with 0x05";
- $hash->{PARTIAL} = "";
- $read_now = READ_UNDEF;
- return "";
- }
-
- #if one 05 received we can send command
- if ( length($hexline) == 2 && $hexline eq "05" && $read_now == READ_UNDEF)
- {
- my $sendstr ="";
- #set next poll command
- if ($poll_now == POLL_ACTIVE ){
- Log3 $name, 5, "VCONTROL: Setze sendstr";
- $sendstr = $cmd_list[$last_cmd][1];
- }
-
- # no polling active but set command was given
- if ($poll_now == POLL_PAUSED && $send_now != NO_SEND ){
- $sendstr = $write_cmd_list[$send_now][2]."$send_additonal_param";
- }
-
- if ( $sendstr && $sendstr ne "" ){
- Log3 $name, 5, "VCONTROL: send '$sendstr'";
- $sendbuf = pack('H*', "$sendstr");
- #Send on Device
- DevIo_SimpleWrite($hash, $sendbuf, 0);
-
- #we have send cmd next receive should be answer
- $read_now = READ_ANSWER;
- }
- else { #wenn wir hier reinrutschen ist etwas mit den listen durcheinander geraten, workaround reset der liste und der commands!
- Log3 $name, 5, "VCONTROL: List reset!";
- $poll_now = POLL_PAUSED;
- $last_cmd = 0;
- @cmd_list = @poll_cmd_list;
- $hash->{PARTIAL} = "";
- $get_timer_now = GET_TIMER_PAUSED;
- $get_config_now = GET_CONFIG_PAUSED;
- }
- }
- elsif ( $read_now == READ_ANSWER) #we expect answer on before send command
- {
- if ($poll_now == POLL_ACTIVE && $hexline ne "05"){
- VCONTROL_Parse($hash,$last_cmd,$hexline,0);
- $last_cmd++;
- $temp_mode = 0;
- }
- #if the mode is requestet and 0x05 is received
- #try again to be sure that 0x05 is not the sync byte
- elsif ( $poll_now == POLL_ACTIVE
- && substr("$hexline",0,2) eq "05"
- && ( $cmd_list[$last_cmd][2] eq "mode"
- || $cmd_list[$last_cmd][2] eq "1ByteU"
- || $cmd_list[$last_cmd][2] eq "1ByteU2"
- || $cmd_list[$last_cmd][2] eq "1ByteS"
- || $cmd_list[$last_cmd][2] eq "1ByteH"
- )
- ){
- Log3 $name, 5, "VCONTROL: check temp_mode";
- if ($temp_mode < 5){
- $temp_mode++;
- Log3 $name, 5, "VCONTROL: set temp_mode = $temp_mode";
- }
- elsif ($temp_mode == 5){
- $temp_mode = 0;
- VCONTROL_Parse($hash,$last_cmd,$hexline,0);
- Log3 $name, 5, "VCONTROL: set mode = ABSCHALT";
- $last_cmd++;
- }
- }
- #parse answer on set command
- if ($poll_now == POLL_PAUSED && $send_now != NO_SEND ){
- VCONTROL_Parse($hash,$send_now,$hexline,1) if ($hexline ne "05");
- }
- $read_now = READ_UNDEF;
- $hash->{PARTIAL} = "";
- }
- }
- #####################################
- sub VCONTROL_Parse($$$$)
- {
- my ($hash, $cmd, $hexline,$answer) = @_;
- my $value = "";
- my $valuename = "";
- my $pn = $hash->{NAME};
- if ($answer == 0){
- if ($cmd_list[$cmd][2] eq "1ByteU"){
- $value = VCONTROL_1ByteUParse(substr($hexline, 0, 2),$cmd_list[$cmd][3]) if (length($hexline) > 1);
- } elsif ($cmd_list[$cmd][2] eq "1ByteU2"){
- $value = VCONTROL_1ByteU2Parse(substr($hexline, 0, 2),$cmd_list[$cmd][3]) if (length($hexline) > 1);
- } elsif ($cmd_list[$cmd][2] eq "1ByteS"){
- $value = VCONTROL_1ByteSParse(substr($hexline, 0, 2),$cmd_list[$cmd][3]) if (length($hexline) > 1);
- } elsif ($cmd_list[$cmd][2] eq "2ByteS"){
- $value = VCONTROL_2ByteSParse($hexline,$cmd_list[$cmd][3]) if (length($hexline) > 3);
- } elsif ($cmd_list[$cmd][2] eq "2ByteU"){
- $value = VCONTROL_2ByteUParse($hexline,$cmd_list[$cmd][3]) if (length($hexline) > 3);
- } elsif ($cmd_list[$cmd][2] eq "1ByteH"){
- $value = VCONTROL_1ByteHexParse($hexline) if (length($hexline) > 1);
- } elsif ($cmd_list[$cmd][2] eq "2ByteH"){
- $value = VCONTROL_2ByteHexParse($hexline) if (length($hexline) > 3);
- } elsif ($cmd_list[$cmd][2] eq "2BytePercent"){
- $value = VCONTROL_2BytePercentParse($hexline,$cmd_list[$cmd][3]) if (length($hexline) > 1);
- } elsif ($cmd_list[$cmd][2] eq "4Byte"){
- $value = VCONTROL_4ByteParse($hexline,$cmd_list[$cmd][3]) if (length($hexline) > 7);
- } elsif ($cmd_list[$cmd][2] eq "mode"){
- $value = VCONTROL_ModeParse($hexline) if (length($hexline) > 1);
- } elsif ($cmd_list[$cmd][2] eq "timer"){
- $value = VCONTROL_timerParse($hexline) if (length($hexline) > 7);
- } elsif ($cmd_list[$cmd][2] eq "date"){
- $value = VCONTROL_DateParse($hexline) if (length($hexline) > 7);
- }
-
- #this will be the name of the Reading
- $valuename = "$cmd_list[$cmd][4]";
- Log3 $pn, 5,"VCONTROL: receive '$valuename : $value'";
-
- return $pn if ($value eq "");
-
- if ( $cmd_list[$cmd][2]
- && $cmd_list[$cmd][2] ne "mode"
- && $cmd_list[$cmd][2] ne "timer"
- && $cmd_list[$cmd][3] ne "state"
- && $cmd_list[$cmd][3] > 99){
- $value = sprintf("%.2f", $value);
- }
-
- #TODO config Min and Max Values ????
- if ( substr($valuename,0,4) eq "Temp"){
- if ( $value < -30 || $value > 199 ){
- $value = ReadingsVal($pn,"$valuename",0);
- }
- }
-
- #get systemtime
- my ($sec,$min,$hour,$mday,$mon,$year) = localtime;
- $year+=1900;
- $mon = $mon+1;
- my $plotmonth = $mon;
- my $plotmday = $mday;
- my $plothour = $hour;
- my $plotmin = $min;
- my $plotsec = $sec;
- if ($mon < 10) {$plotmonth = "0$mon"};
- if ($mday < 10) {$plotmday = "0$mday"};
- if ($hour < 10) {$plothour = "0$hour"};
- if ($min < 10) {$plotmin = "0$min"};
- if ($sec < 10) {$plotsec = "0$sec"};
- my $systime="$year-$plotmonth-$plotmday"."_"."$plothour:$plotmin:$plotsec";
-
- #Start Update Readings
- my $update_only_changes = AttrVal($pn, "update_only_changes", "0");
- readingsBeginUpdate ($hash);
- if ( $update_only_changes == 0 || ($update_only_changes == 1 && (ReadingsVal($pn,"$valuename",0) ne $value)))
- { readingsBulkUpdate ($hash, "$valuename", $value)};
-
- #calculate Kumulation Readings and Day Readings
-
- if ("$cmd_list[$cmd][5]" eq "day" ){
- my $start_of_the_day;
- if ( $value < 0 ){
- $value = ReadingsVal($pn,"$valuename",0);
- }
-
- $value = sprintf("%.2f", $value);
- $start_of_the_day = ReadingsVal($pn,"$valuename"."DayStart",$value);
- my $kumul_day = $value - $start_of_the_day;
- $kumul_day = sprintf("%.2f", $kumul_day);
- readingsBulkUpdate ($hash, "$valuename"."Today", $kumul_day);
-
- #Next Day for this value is reached
- my $debug_day= $DayHash{$valuename};
- Log3 $pn, 5, "VCONTROL: DEBUG nextday $mday <-> $debug_day";
- if ($mday != $DayHash{$valuename}){
- $start_of_the_day = $value;
- $start_of_the_day = sprintf("%.2f", $start_of_the_day);
- readingsBulkUpdate ($hash, "$valuename"."LastDay" , $kumul_day);
- $kumul_day = 0;
- $DayHash{$valuename} = $mday;
- }
- readingsBulkUpdate ($hash, "$valuename"."DayStart" , $start_of_the_day);
- }
- #if all polling commands are send, update Reading UpdateTime
- my $all_cmd = @cmd_list -1;
- if ( $cmd == $all_cmd){
- readingsBulkUpdate ($hash, "UpdateTime", $systime );
- }
- #End Update Reading
- readingsEndUpdate ($hash, 1);
- }
- else #answer on set request
- {
- #Start Poll to refresh readings if send of set request was answered with 00
- # and no additional send has to be done
- if (substr($hexline, 0, 2) == "00")
- {
- # it may be configured that another command has to be send
- my $next_send = NO_SEND;
- foreach(@write_cmd_list) {
- if ($$_[0] eq "SET" && $$_[1] eq $write_cmd_list[$send_now][4]){
- $next_send=$$_[5];
- }
- }
-
- if ($next_send == NO_SEND){
- #activate timer get list if questioned
- if ($get_timer_now == GET_TIMER_ACTIVE ){
- @cmd_list = @get_timer_cmd_list;
- $get_timer_now = GET_TIMER_PAUSED;
- }
-
- if (substr($hexline, 0, 2) == "00"){
- Log3 $pn, 5, "VCONTROL: Poll SET!";
- RemoveInternalTimer($hash);
- VCONTROL_Poll($hash);
- }
- }
- $send_now = $next_send;
- }
- }
- return $pn;
- }
- #####################################
- sub VCONTROL_Ready($)
- {
- my ($hash) = @_;
- my $dev = $hash->{DeviceName};
- my $name = $hash->{NAME};
- my $po;
- if ($TCP_CONNECTION==0) {
- ###USB
- $po=$hash->{USBDev};
- if(!$po) { # Looking for the device
- if ($^O=~/Win/) {
- $po = new Win32::SerialPort ($dev);
- }
- else {
- $po = new Device::SerialPort ($dev);
- }
- return undef if(!$po);
- Log3 $name, 3, "VCONTROL: USB device $dev reappeared";
- $hash->{USBDev} = $po;
- if( $^O !~ /Win/ ) {
- $hash->{FD} = $po->FILENO;
- delete($readyfnlist{"$name.$dev"});
- $selectlist{"$name.$dev"} = $hash;
- }
- else {
- $readyfnlist{"$name.$dev"} = $hash;
- }
- $hash->{PARTIAL} = "";
- VCONTROL_DoInit($hash, $po);
- DoTrigger($name, "CONNECTED");
- $hash->{STATE} = "connected";
- }
- return undef if !$po;
- my ($BlockingFlags, $InBytes, $OutBytes, $ErrorFlags)=$po->status;
- return ($InBytes>0);
- }
- else {
- ###TCP Connection
- $hash->{PARTIAL} = "";
- return DevIo_OpenDev($hash, 1, "VCONTROL_DoInit") if($hash->{STATE} eq "disconnected");
- }
- }
- #####################################
- sub VCONTROL_Set($@)
- {
- my ($hash, @a) = @_;
- my $pn = $hash->{NAME};
- my $arg = $a[1];
- my $value = (defined $a[2]) ? $a[2] : "";
- my $setList = AttrVal($pn, "setList", " ");
-
- #return "Unknown argument ?, choose one of HWW ABSCHALT SPAR-ON SPAR-OFF PARTY-ON PARTY-OFF" if( $arg eq "?");
- return "Unknown argument ?, choose one of $setList" if( $arg eq "?");
-
- #needed if cmd in config_file is just a prefix, e.g. set of an timer value
- $send_additonal_param="";
-
- #set write commands to send
- foreach(@write_cmd_list) {
- my $debug_info0=$$_[0];
- my $debug_info1=$$_[1];
- Log3 $pn, 5, "VCONTROL: DEBUG SET <-> $debug_info0 / $arg <-> $debug_info1";
- if ($$_[0] eq "SET" && $$_[1] eq $arg){
- $send_now=$$_[5];
-
- if ($$_[3] eq "1ByteU"){
- $send_additonal_param=VCONTROL_1ByteUConv($value,$$_[4]);
- }
- elsif ($$_[3] eq "1ByteS"){
- $send_additonal_param=VCONTROL_1ByteSConv($value,$$_[4]);
- }
- elsif ($$_[3] eq "1ByteUx10"){
- $send_additonal_param=VCONTROL_1ByteUx10Conv($value);
- }
- elsif ($$_[3] eq "2ByteU"){
- $send_additonal_param=VCONTROL_2ByteUConv($value,$$_[4]);
- }
- elsif ($$_[3] eq "2ByteS"){
- $send_additonal_param=VCONTROL_2ByteSConv($value,$$_[4]);
- }
- elsif ($$_[3] eq "date"){
- my $strtemp = VCONTROL_DateConv($value);
- Log3 $pn, 5, "VCONTROL: DEBUG Timestr: $strtemp";
- $send_additonal_param=$strtemp;
- }
- elsif ($$_[3] eq "timer"){
- my $tempday = $$_[4];
- $send_additonal_param=VCONTROL_TimerConv($tempday,$value);
- @get_timer_cmd_list = @timer_cmd_list;
- $get_timer_now = GET_TIMER_ACTIVE;
- }
- elsif ($$_[3] eq "Register"){
- $send_additonal_param=VCONTROL_RegisterConv($value);
- if ($send_additonal_param eq "")
- {
- Log3 $pn, 1, "VCONTROL: Register falsch eingegeben: $value";
- return "";
- }
- else {
- Log3 $pn, 1, "VCONTROL: Register gesetzt: $value (01F427$send_additonal_param)";
- }
- }
- return "";
- }
- }
-
- # possible to correct DayStart Values
- if(index($arg,"DayStart") >= 0){
- if ( $value ne "" )
- {
- readingsBeginUpdate ($hash);
- readingsBulkUpdate ($hash, $arg, $value);
- readingsEndUpdate ($hash, 1);
- }
- }
- #else {
- # print "not data_ready: $arg \n";
- #}
- return "";
- }
- #####################################
- sub VCONTROL_Get($@) {
- my ($hash, @a) = @_;
- return "no get value specified" if(@a < 2);
-
- my $pn = $hash->{NAME};
- my $arg = $a[1];
- my $value = (defined $a[2]) ? $a[2] : "";
-
- return "Unknown argument ?, choose one of TIMER CONFIG" if( $arg eq "?");
- if ($arg eq "TIMER" )
- {
- @get_timer_cmd_list = @timer_cmd_list;
- }
- elsif ($arg eq "CONFIG" )
- {
- if ($poll_now == POLL_PAUSED ){
- VCONTROL_CmdConfig($command_config_file);
- @cmd_list = @poll_cmd_list;
- }
- else {
- $get_config_now = GET_CONFIG_ACTIVE;
- }
- return "";
- }
- if ($poll_now == POLL_PAUSED ){
- @cmd_list = @get_timer_cmd_list;
- Log3 $pn, 5, "VCONTROL: Poll GET!";
- RemoveInternalTimer($hash);
- VCONTROL_Poll($hash);
- }
- else {
- $get_timer_now = GET_TIMER_ACTIVE;
- }
-
- return "";
- }
- #####################################
- sub VCONTROL_ReInit($)
- {
- my $hash = shift;
- my $name = $hash->{NAME};
- my $dev = $hash->{DeviceName};
- delete $hash->{USBDev};
- delete $hash->{FD};
- DevIo_CloseDev($hash);
- $hash->{PARTIAL} = "";
-
- #Opening USB Device
- Log3($name, 3, "VCONTROL ReInit VCONTROL device $dev");
-
- if ($TCP_CONNECTION==0) {
- ###USB
- my $po;
- if ($^O=~/Win/) {
- require Win32::SerialPort;
- $po = new Win32::SerialPort ($dev);
- }
- else {
- require Device::SerialPort;
- $po = new Device::SerialPort ($dev);
- }
- if(!$po) {
- my $msg = "Can't open $dev: $!";
- Log3($name, 3, $msg) if($hash->{MOBILE});
- return $msg if(!$hash->{MOBILE});
- $readyfnlist{"$name.$dev"} = $hash;
- return undef;
- }
- Log3($name, 3, "VCONTROL opened VCONTROL device $dev");
- $hash->{USBDev} = $po;
- if( $^O =~ /Win/ ) {
- $readyfnlist{"$name.$dev"} = $hash;
- }
- else {
- $hash->{FD} = $po->FILENO;
- delete($readyfnlist{"$name.$dev"});
- $selectlist{"$name.$dev"} = $hash;
- }
-
- #Initialize to be able to receive data
- VCONTROL_DoInit($hash, $po);
- }
- else {
- ###TCP COnnection
- DevIo_OpenDev($hash, 0, "VCONTROL_DoInit");
- }
- }
- #####################################
- #####################################
- ## Load Config
- #####################################
- #####################################
- sub VCONTROL_CmdConfig($)
- {
-
- my $cmd_config_file = shift;
-
- my ($sec,$min,$hour,$mday,$mon,$year) = localtime;
- my $write_idx=0;
- Log3 undef, 3, "VCONTROL: open DATEI '$cmd_config_file'";
- open(CMDDATEI,"<$cmd_config_file") || die "problem opening $cmd_config_file\n" ;
- undef @poll_cmd_list;
- undef @write_cmd_list;
- undef @timer_cmd_list;
- # undef @timer_ww_cmd_list;
-
- $viess_protocol = PROTOCOL_KW;
-
- while(<CMDDATEI>){
- my $zeile=trim($_);
- Log3 undef, 5, "VCONTROL: CmdConfig-Zeile $zeile";
- if ( length($zeile) > 0 && substr($zeile,0,1) ne "#")
- {
- my @cfgarray = split(",",$zeile);
- foreach(@cfgarray) {
- $_ = trim($_);
- }
- if ($cfgarray[0] eq "PROTOCOL"){
- if ( $cfgarray[1] eq "GWG" ){
- $viess_protocol = PROTOCOL_GWG;
- }
- elsif ( $cfgarray[1] eq "300" ){
- $viess_protocol = PROTOCOL_300;
- }
- }
- #TODO: CHECK IF CONFIG PARAMS are allowed!!!
- elsif ($cfgarray[0] eq "POLL"){
- if ( $cfgarray[2] ne "1ByteU"
- && $cfgarray[2] ne "1ByteU2"
- && $cfgarray[2] ne "1ByteS"
- && $cfgarray[2] ne "2ByteS"
- && $cfgarray[2] ne "2ByteU"
- && $cfgarray[2] ne "1ByteH"
- && $cfgarray[2] ne "2ByteH"
- && $cfgarray[2] ne "2BytePercent"
- && $cfgarray[2] ne "4Byte"
- && $cfgarray[2] ne "mode"
- && $cfgarray[2] ne "date"
- && $cfgarray[2] ne "timer"
- ){
- Log3 undef, 3, "VCONTROL: unknown parse method '$cfgarray[2]' in '$cmd_config_file'";
- }
- elsif( (($viess_protocol == PROTOCOL_KW) && (index($cfgarray[1],"01F7") == -1 || length($cfgarray[1]) < 10 ))
- || (($viess_protocol == PROTOCOL_GWG) && (index($cfgarray[1],"01CB") == -1 || length($cfgarray[1]) < 10 ))
- )
- {
- Log3 undef, 3, "VCONTROL: wrong Address '$cfgarray[1]' in '$cmd_config_file'";
- }
- else {
- if ($cfgarray[2] eq "timer")
- {
- my @timercmd = ($cfgarray[0],$cfgarray[1],$cfgarray[2],$cfgarray[3],$cfgarray[4],$cfgarray[5]);
- push(@timer_cmd_list,\@timercmd);
- }
- else {
- my @pollcmd = ($cfgarray[0],$cfgarray[1],$cfgarray[2],$cfgarray[3],$cfgarray[4],$cfgarray[5]);
- push(@poll_cmd_list,\@pollcmd);
- if ("$cfgarray[5]" eq "day"){
- $DayHash{$cfgarray[4]} = $mday;
- }
- }
- }
- }
- elsif ($cfgarray[0] eq "SET"){
- if ($cfgarray[3] eq "timer")
- {
- if ( $cfgarray[4] ne "MO"
- && $cfgarray[4] ne "DI"
- && $cfgarray[4] ne "MI"
- && $cfgarray[4] ne "DO"
- && $cfgarray[4] ne "FR"
- && $cfgarray[4] ne "SA"
- && $cfgarray[4] ne "SO"
- )
- { Log3 undef, 1, "VCONTROL: wrong Day '$cfgarray[4]' in '$cmd_config_file'";
- }
- else {
- my @setcmd = ($cfgarray[0],$cfgarray[1],$cfgarray[2],$cfgarray[3],$cfgarray[4],$write_idx);
- push(@write_cmd_list,\@setcmd);
- $write_idx++;
- }
- }
- else {
- my @setcmd = ($cfgarray[0],$cfgarray[1],$cfgarray[2],$cfgarray[3],$cfgarray[4],$write_idx);
- push(@write_cmd_list,\@setcmd);
- $write_idx++;
- }
- }
- else {
- Log3 undef, 3, "VCONTROL: unknown command '$cfgarray[0]' in '$cmd_config_file'";
- }
- }
- };
- close (CMDDATEI);
- Log3 undef, 3, "VCONTROL: DATEI '$cmd_config_file' refreshed";
- }
- ###########################################################################
- ###########################################################################
- ### PARSE ROUTINES
- ###########################################################################
- ###########################################################################
- sub VCONTROL_1ByteUParse($$)
- {
- my $hexvalue = shift;
- my $divisor = shift;
- my $retstr="";
-
- if (!$divisor || length($divisor) == 0 || $divisor eq "state"){
- $retstr = ($hexvalue eq "00") ? "off" : "on";
- }
- else{
- #check if divisor is numeric and not 0
- if ( $divisor =~ /^\d+$/ && $divisor != 0){
- $retstr = hex($hexvalue)/$divisor;
- }
- else {
- Log3 undef, 3, "VCONTROL: divisor not numeric '$divisor' or 0, it will be ignored";
- $retstr = hex($hexvalue)
- }
- }
- return $retstr;
- }
- #####################################
- sub VCONTROL_1ByteU2Parse($$)
- {
- my $hexvalue = shift;
- my $divisor = shift;
- return hex(substr($hexvalue,0,2))/$divisor;
- }
- #####################################
- sub VCONTROL_1ByteSParse($$)
- {
- my $hexvalue = shift;
- my $divisor = shift;
- return unpack('c', pack('C',hex(substr($hexvalue,0,2))))/$divisor;
- }
- #####################################
- sub VCONTROL_1ByteHexParse($)
- {
- my $hexvalue = shift;
-
- return (substr($hexvalue,0,2));
- }
- #####################################
- sub VCONTROL_2ByteUParse($$)
- {
- my $hexvalue = shift;
- my $divisor = shift;
- return hex(substr($hexvalue,2,2).substr($hexvalue,0,2))/$divisor;
- }
- #####################################
- sub VCONTROL_2ByteSParse($$)
- {
- my $hexvalue = shift;
- my $divisor = shift;
- return unpack('s', pack('S',hex(substr($hexvalue,2,2).substr($hexvalue,0,2))))/$divisor;
- }
- #####################################
- sub VCONTROL_2BytePercentParse($$)
- {
- my $hexvalue = shift;
- my $divisor = shift;
- return hex(substr($hexvalue,2,2))/$divisor;
- }
- #####################################
- sub VCONTROL_2ByteHexParse($)
- {
- my $hexvalue = shift;
-
- return (substr($hexvalue,0,2).substr($hexvalue,2,2));
- }
- #####################################
- sub VCONTROL_4ByteParse($$)
- {
- my $hexvalue = shift;
- my $divisor = shift;
- return hex(substr($hexvalue,6,2).substr($hexvalue,4,2).substr($hexvalue,2,2).substr($hexvalue,0,2))/$divisor;
- }
- #####################################
- sub VCONTROL_ModeParse($)
- {
- my $index = hex(shift);
- return "$mode[$index]" if ($mode[$index]);
-
- return "";
- }
- #####################################
- sub VCONTROL_timerParse($)
- {
- my $binvalue = shift;
- $binvalue = pack('H*', "$binvalue");
-
- my ($h1,$h2,$h3,$h4,$h5,$h6,$h7,$h8) = unpack ("CCCCCCCC",$binvalue);
- my @bytes = ($h1,$h2,$h3,$h4,$h5,$h6,$h7,$h8);
- my $timer_str;
- for ( $a = 0; $a < 8; $a = $a+1){
- my $delim = "-";
- if ( $a % 2 ){
- $delim = "/";
- }
-
- my $byte = $bytes[$a];
- if ($byte == 0xff){
- $timer_str = $timer_str."--$delim";
- }
- else{
- my $hour = ($byte & 0xF8)>>3;
- my $min = ($byte & 7)*10;
- $hour = "0$hour" if ( $hour < 10 );
- $min = "0$min" if ( $min < 10 );
- $timer_str = $timer_str."$hour:$min$delim";
- }
- }
-
- return "$timer_str";
-
- }
- #####################################
- sub VCONTROL_DateParse($){
-
- my $hexvalue = shift;
- my $vcday;
- #0011223344556677
- #01 23 45 67 89 01 23 45
- $vcday = "So" if ( substr($hexvalue,8,2) eq "00" );
- $vcday = "Mo" if ( substr($hexvalue,8,2) eq "01" );
- $vcday = "Di" if ( substr($hexvalue,8,2) eq "02" );
- $vcday = "Mi" if ( substr($hexvalue,8,2) eq "03" );
- $vcday = "Do" if ( substr($hexvalue,8,2) eq "04" );
- $vcday = "Fr" if ( substr($hexvalue,8,2) eq "05" );
- $vcday = "Sa" if ( substr($hexvalue,8,2) eq "06" );
- $vcday = "So" if ( substr($hexvalue,8,2) eq "07" );
- return $vcday.",".substr($hexvalue,6,2).".".substr($hexvalue,4,2).".".substr($hexvalue,0,4)." ".substr($hexvalue,10,2).":".substr($hexvalue,12,2).":".substr($hexvalue,14,2);
- }
- ###########################################################################
- ###########################################################################
- ## CONV ROUTINES
- ###########################################################################
- ###########################################################################
- sub VCONTROL_1ByteUConv($$)
- {
- my $convvalue = shift;
- my $multiplicator = shift;
- if ( $multiplicator =~ /^\d+$/) {
- return (sprintf "%02X", $convvalue*$multiplicator);
- }
- else
- { return (sprintf "%02X", $convvalue); }
- }
- #####################################
- sub VCONTROL_1ByteSConv($$)
- {
- my $convvalue = shift;
- my $multiplicator = shift;
- my $cnvstrvalue;
- if ( $multiplicator =~ /^\d+$/) {
- $cnvstrvalue = (sprintf "%02X", $convvalue*$multiplicator);
- }
- else
- {$cnvstrvalue = (sprintf "%02X", $convvalue);}
- if ($convvalue <0){
- return substr($cnvstrvalue,length($cnvstrvalue)-2,2);
- }
- else {
- return $cnvstrvalue;
- }
- }
- #####################################
- sub VCONTROL_1ByteUx10Conv($)
- {
- my $convvalue = shift;
- return (sprintf "%02X", $convvalue*10);
- }
- #####################################
- sub VCONTROL_2ByteUConv($$)
- {
- my $convvalue = shift;
- my $multiplicator = shift;
- my $hexstr;
- if ( $multiplicator =~ /^\d+$/) {
- $hexstr = (sprintf "%04X", $convvalue*$multiplicator);
- }
- else {
- $hexstr = (sprintf "%04X", $convvalue);
- }
- return substr($hexstr,2,2).substr($hexstr,0,2);
- }
- #####################################
- sub VCONTROL_2ByteSConv($$)
- {
- my $convvalue = shift;
- my $multiplicator = shift;
- my $cnvstrvalue;
- if ( $multiplicator =~ /^\d+$/) {
- $cnvstrvalue = (sprintf "%04X", $convvalue*$multiplicator);
- }
- else {
- $cnvstrvalue = (sprintf "%04X", $convvalue);
- }
- if ($convvalue <0){
- return substr($cnvstrvalue,6,2).substr($cnvstrvalue,4,2);
- }
- else {
- return substr($cnvstrvalue,2,2).substr($cnvstrvalue,0,2);
- }
- }
- #####################################
- sub VCONTROL_DateConv($){
- #Eingabe
- #dd.mm.yyyy_hh:mm:ss
- #Ziel
- #yyyymmddwwhhmmss
-
- #dd.mm.yyyy
- my $date = shift;
- my $vcday = substr($date,0,2);
- my $vcmonth = substr($date,3,2);
- my $vcyear = substr($date,6,4);
- #hh:mm:ss
- my $vchour = substr($date,11,2);
- my $vcmin = substr($date,14,2);
- my $vcsec = substr($date,17,2);
- my $wday;
- my $tmp;
- my $hlptime = timelocal($vcsec, $vcmin, $vchour, $vcday, $vcmonth -1 , $vcyear - 1900);
- ($tmp, $tmp, $tmp, $tmp, $tmp, $tmp, $wday) = localtime $hlptime;
-
- my @Wochentage = ("00","01","02","03","04","05","06");
- $wday = $Wochentage[$wday];
-
- #0011223344556677
- #01 23 45 67 89 01 23 45
- return $vcyear.$vcmonth.$vcday.$wday.$vchour.$vcmin.$vcsec;
- }
- #####################################
- sub VCONTROL_TimerConv($$){
- my $timer_day = shift;
- my $value = shift;
- my @timerarray = split(",",$value);
- return "" if (@timerarray != 8);
-
- my @hextimerdata;
- foreach(@timerarray) {
- if ($_ eq "--"){
- push(@hextimerdata,"FF");
- }
- else{
- my ($timerhour, $timermin) = split(":",$_,2);
- if (length($timerhour) != 2 || length($timermin) != 2 ){
- {return "";}
- }
-
- if ( $timerhour < "00" || $timerhour > "24" ){
- {return "";}
- }
- if ( $timermin ne "00" && $timermin ne "10" && $timermin ne "20" && $timermin ne "30" && $timermin ne "40" && $timermin ne "50"){
- {return "";}
- }
-
- my $helpvalue = (($timerhour <<3) + ($timermin/10)) & 0xff;
- push(@hextimerdata, (sprintf "%02X", $helpvalue));
- }
- }
-
- my $suffix="";
- foreach (@hextimerdata){
- $suffix = "$suffix"."$_";
- }
-
- return $suffix;
- }
- #####################################
- sub VCONTROL_RegisterConv($)
- {
- my $convvalue = shift;
- if (length($convvalue)==4 || (length($convvalue)==5 && substr($convvalue,2,1)eq"-"))
- {
- my $register=substr($convvalue,0,2);
- my $value=substr($convvalue,2,3);
- my $hexvalue=sprintf "%02X", $value;
- if ($value <0)
- {
- $hexvalue = substr($hexvalue,length($hexvalue)-2,2);
- }
- return $register."01".$hexvalue;
- }
- else
- {
- return "";
- }
- }
- 1;
- =pod
- =begin html
- <a name="VCONTROL"></a>
- <h3>VCONTROL</h3>
- <ul>
- VCONTROL is a fhem-Modul to control and read information from a VIESSMANN heating via Optolink-adapter.<br><br>
-
- An Optolink-Adapter is necessary (USB or LAN), you will find information here:<br>
- <a href="http://openv.wikispaces.com/">http://openv.wikispaces.com/</a><br><br>
-
- Additionaly you need to know Memory-Adresses for the div. heating types (e.g. V200KW1, VScotHO1, VPlusHO1 ....),<br>
- that will be read by the module to get the measurements or to set the actual state.<br>
- Additional information you will find in the forum <a href="http://forum.fhem.de/index.php/topic,20280.0.html">http://forum.fhem.de/index.php/topic,20280.0.html</a> und auf der wiki Seite <a href="http://www.fhemwiki.de/wiki/Vitotronic_200_%28Viessmann_Heizungssteuerung%29">http://www.fhemwiki.de/wiki/Vitotronic_200_%28Viessmann_Heizungssteuerung%29</a><br><br><br>
-
- <a name="VCONTROLdefine"><b>Define</b></a>
- <ul>
- <code>define <name> VCONTROL <serial-device/LAN-Device:port> <configfile> [<intervall>] </code><br>
- <br>
- <li><b><serial-device/LAN-Device:port></b><br>
- USB Port (e.g. com4, /dev/ttyUSB3) or TCPIP:portnumber<br>
- </li>
- <li><b><intervall></b><br>
- Poll Intervall in seconds (default 180)<br>
- </li>
-
- <li><b><configfile></b><br>
- path to the configuration file, containing the memory addresses<br>
- </li>
- <br>
- Example:<br><br>
-
- serial device com4, every 3 minutes will be polled, configuration file name is 99_VCONTROL.cfg, existing in the fhem root directory<br><br>
- Windows:<br>
- define Heizung VCONTROL com4 99_VCONTROL.cfg 180<br><br>
-
- Linux:<br>
- define Heizung VCONTROL /dev/ttyUSB3 99_VCONTROL.cfg 180<br>
- </ul>
- <br><br>
- <a name="VCONTROLset"><b>Set</b></a>
- <ul>
- These commands will be configured in the configuartion file.
- </ul>
- <br><br>
- <a name="VCONTROLget"><b>Get</b></a>
- <ul>
- get <name> CONFIG<br><br>
- reload the module specific configfile<br><br>
- More commands will be configured in the configuration file.
- </ul>
- <br><br>
- <a name="VCONTROLparameter"><b>configfile</b></a>
- <ul>
- You will find example configuration files for the heating types V200KW1, VScotHO1, VPlusHO1 on the wiki page <a href="http://www.fhemwiki.de/wiki/Vitotronic_200_%28Viessmann_Heizungssteuerung%29">http://www.fhemwiki.de/wiki/Vitotronic_200_%28Viessmann_Heizungssteuerung%29</a>.<br><br>
- The lines of the configuration file can have the following structure:<br><br>
- <li>lines beginning with "#" are comments!<br></li>
- <li>Polling Commands (POLL) to read values.<br></li>
- <li>Set Commands (SET) to set values.<br></li>
- <br>
- <b>Polling Commands have the following structure:<br><br></b>
- POLL, ADDRESSE, PARSEMETHODE, DIVISOR, READING-NAME, KUMULATION<br><br>
-
- <ul>
- <li><b>POLL</b><br>
- is fix POLL<br>
- </li>
- <br>
- <li><b>ADDRESSE</b><br>
- Memory Address leading to the value, the will be read in the memory on the heating.<br>
- It is subdivided in 3 parts:<br>
- <ul>
- <li> Beginning is fix 01F7 (defines a reading command)</li>
- <li> followed by actuak address<br></li>
- <li> followed by number of Bytes to be read.<br></li>
- </ul>
- </li>
- <br>
- <li><b>PARSEMETHODE</b><br>
- Method how to parse the read bytes.<br>
- methods so far:<br>
- <ul>
- <li>1ByteU :<br> Read value is 1 Byte without algebraic sign (if column Divisor set to state -> only 0 / 1 or off / on)<br></li>
- <li>1ByteS :<br> Read value is 1 Byte with algebraic sign (wenn Spalte Divisor state ist -> nur 0 / 1 also off / on)<br></li>
- <li>2ByteS :<br> Read value is 2 Byte with algebraic sign<br></li>
- <li>2ByteU :<br> Read value is 2 Byte without algebraic sign<br></li>
- <li>2BytePercent :<br> Read value is 2 Byte in percent<br></li>
- <li>4Byte :<br> Read value is 4 Byte<br></li>
- <li>mode :<br> Read value is the actual operating status<br></li>
- <li>timer :<br> Read value is an 8 Byte timer value<br></li>
- <li>date :<br> Read value is an 8 Byte timestamp<br></li>
- POLL Commands unsing the method timer will not be polled permanent, they have to be read by a GET Commando explicitly.<br>
- GET <devicename> TIMER<br>
- </ul>
- </li>
- <br>
- <li><b>DIVISOR</b><br>
- If the parsed value is multiplied by a factor, you can configure a divisor.<br>
- Additionally for values, that just deliver 0 or 1, you can configure state in this column.<br>
- This will force the reading to off and on, instead of 0 and 1.<br>
- </li>
- <br>
- <li><b>READING-NAME</b><br>
- The read and parsed value will be stored in a reading with this name in the device.
- </li>
- <br>
- <li><b>KUMULATION</b><br>
- Accumulated Day values will be automatically stored for polling commands with the value day in the column KUMULATION.<br>
- Futhermore there will be stored the values of the last day in additional readings after 00:00.<br>
- So you have the chance to plot daily values.<br>
- The reading names will be supplemented by DayStart, Today and LastDay!<br>
- </li>
-
- <br>
- Examples:<br><br>
- <code>POLL, 01F7080402, 2ByteS, 10 , Temp-WarmWater-Actual , -<br></code>
- <code>POLL, 01F7088A02, 2ByteU, 1 , BurnerStarts , day<br></code>
- </ul>
- <br><br>
- <b>Set Commands have the following structure:<br><br></b>
- SET,SETCMD, ADRESSE, CONVMETHODE, NEXT_CMD or DAY for timer<br><br>
-
- <ul>
- <li><b>SET</b><br>
- is fix SET<br>
- </li>
- <br>
- <li><b>SETCMD</b><br>
- SETCMD are commands that will be used in FHEM to set a value of a device<br>
- set <devicename> <setcmd><br>
- e.g. SET <devicename> WW to set the actual operational status to Warm Water processing<br>
- </li>
- <br>
-
- <li><b>ADDRESSE</b><br>
- Memory Address where the value has to be written in the memory of the heating.<br>
- It is subdivided in 4 parts:<br>
- <ul>
- <li> Beginning is fix 01F4 (defines a writing command)</li>
- <li> followed by actual address<br></li>
- <li> followed by number of data-bytes to be written<br></li>
- <li> followed by the data-bytes themselves<br></li>
- </ul>
- <br>
- There are two Address versions:<br>
- <li>Version 1: Value to be set is fix, e.g. Spar Mode on is fix 01<br></li>
- <li>Version 2: Value has to be passed, e.g. warm water temperature<br></li>
- </li>
- <br>
- <li><b>CONVMETHODE</b><br>
- Method how to convert the value with Version 2 in Bytes.<br>
- For Version 1 you can use - here.<br>
- Methods so far:<br>
- <ul>
- <li>1ByteU :<br> Value to be written in 1 Byte without algebraic sign<br>with Version 2 it has to be a number<br></li>
- <li>1ByteS :<br> Value to be written in 1 Byte with algebraic sign<br>with Version 2 it has to be a number<br></li>
- <li>2ByteS :<br> Value to be written in 2 Byte with algebraic sign<br>with Version 2 it has to be a number<br></li>
- <li>2ByteU :<br> Value to be written in 2 Byte without algebraic sign<br>with Version 2 it has to be a number<br></li>
- <li>timer :<br> Value to be written is an 8 Byte Timer value<br>with Version 2 it has to be a string with this structure:<br>
- 8 times of day comma separeted. (ON1,OFF1,ON2,OFF2,ON3,OFF3,ON4,OFF4)<br>
- no time needed ha to be specified with -- .<br>
- Minutes of the times are just allowed to thi values: 00,10,20,30,40 or 50<br>
- Example: 06:10,12:00,16:00,23:00,--,--,--,--</li>
- <li>date :<br> Value to be written is an 8 Byte timestamp<br>with Version 2 it has to be a string with this structure:<br>
- format specified is DD.MM.YYYY_HH:MM:SS<br>
- Example: 21.03.2014_21:35:00</li>
- </ul>
- </li>
- <br>
- <li><b>NEXT_CMD or DAY</b><br>
- This column has three functions:
- <ul>
- <li> If this columns is configured with a name of another SETCMD, it will be processed directly afterwards.<br>
- Example: after setting Spar Mode on (S-ON), you have to set Party Mode off (P-OFF) <br></li>
- <li> Using a CONVMETHODE 1ByteU or 1ByteS or 2ByteS or 2ByteU , you can use the column as an multiplicator,<br>
- which will be multiplied to the value in the SET command<br>
- Example: <code>SET, TEMPNHK1 , 01F4200002 , 2ByteU , 10</code>
- With <code>SET DEVICE TEMPNHK1 21</code> 210 will be send to the heating.
- </li>
- <li>Using timer as CONVMETHODE, so it has to be specified a week day in this columns.<br>
- possible values: MO DI MI DO FR SA SO<br></li>
- </li>
- <br>
- </ul>
- Examples:<br><br>
- <code>SET, WW , 01F423010100, state , -<br></code>
- <code>SET, S-ON , 01F423020101, state_spar , P-OFF<br></code>
- <code>SET, WWTEMP , 01F4630001 , 1ByteU , -<br></code>
- <code>SET, TIMER_2_MO, 01F4200008 , timer , MO<br></code>
- </ul>
- </ul>
- <br>
- <a name="VCONTROLreadings"><b>Readings</b></a>
- <ul>The values read will be stored in readings, that will be configured as described above.</ul>
- </ul>
- =end html
- =begin html_DE
- <a name="VCONTROL"></a>
- <h3>VCONTROL</h3>
- <ul>
- Das VCONTROL ist das fhem-Modul eine VIESSMANN Heizung via Optolink-Schnittstelle auszulesen und zu steuern.<br><br>
-
- Notwendig ist dazu ein Optolink-Adapter (USB oder LAN), zu dem hier Informationen zu finden sind:<br>
- <a href="http://http://openv.wikispaces.com/">http://openv.wikispaces.com/</a><br><br>
-
- Zusätzlich müssen für die verschiedenen Heizungstypen (z.B. V200KW1, VScotHO1, VPlusHO1 ....) Speicher-Adressen bekannt sein,<br>
- unter denen die Messwerte abgefragt oder aber auch Stati gesetzt werden können.<br>
- Informationen hierzu findet man im Forum <a href="http://http://openv.wikispaces.com/">http://openv.wikispaces.com/</a> und auf der wiki Seite <a href="http://http://openv.wikispaces.com/">http://openv.wikispaces.com/</a><br><br><br>
-
- <a name="VCONTROLdefine"><b>Define</b></a>
- <ul>
- <code>define <name> VCONTROL <serial-device/LAN-Device:port> <configfile> [<intervall>] </code><br>
- <br>
- <li><b><serial-device/LAN-Device:port></b><br>
- USB Port (z.B. com4, /dev/ttyUSB3) oder aber TCPIP:portnummer<br>
- </li>
- <li><b><intervall></b><br>
- Anzahl Sekunden wie oft die Heizung ausgelesen werden soll (default 180)<br>
- </li>
-
- <li><b><configfile></b><br>
- Pfad wo die Konfigurationsdatei für das Modul zu finden ist, die die Adressen beinhaltet<br>
- </li>
- <br>
- Beispiel:<br><br>
-
- serielle Schnittstelle über com4, alle 3 Minuten wird gepollt, configfile heisst 99_VCONTROL.cfg und liegt im fhem root Verzeichnis<br><br>
- Windows:<br>
- define Heizung VCONTROL com4 99_VCONTROL.cfg 180<br><br>
-
- Linux:<br>
- define Heizung VCONTROL /dev/ttyUSB3 99_VCONTROL.cfg 180<br>
- </ul>
- <br><br>
- <a name="VCONTROLset"><b>Set</b></a>
- <ul>
- Diese müssen über das configfile konfiguriert werden.
- </ul>
- <br><br>
- <a name="VCONTROLget"><b>Get</b></a>
- <ul>
- get <name> CONFIG<br><br>
- Mit diesem Befehl wird das Modul spezifische configfile nachgeladen.<br><br>
-
- Diese anderen Befehler müssen über das configfile konfiguriert werden.
- </ul>
- <br><br>
- <a name="VCONTROLparameter"><b>configfile</b></a>
- <ul>
- Im configfile hat man nun die folgenden Konfigurations Möglichkeiten.<br><br>
-
- Beispieldateien f¨r die Geräte-Typen V200KW1, VScotHO1, VPlusHO1 sind auf der wiki Seite <a href="http://www.fhemwiki.de/wiki/Vitotronic_200_%28Viessmann_Heizungssteuerung%29">http://www.fhemwiki.de/wiki/Vitotronic_200_%28Viessmann_Heizungssteuerung%29</a> zu finden.<br><br>
- <li>Zeilen die mit "#" beginnen sind Kommentar!<br></li>
- <li>Polling Commandos (POLL) zum Lesen von Werten können konfiguriert werden.<br></li>
- <li>Set Commandos (SET) zum setzen von Werten können konfiguriert werden.<br></li>
- <br>
- <b>Polling Commandos haben den folgenden Aufbau:<br><br></b>
- POLL, ADDRESSE, PARSEMETHODE, DIVISOR, READING-NAME, KUMULATION<br><br>
-
- <ul>
- <li><b>POLL</b><br>
- muss fest auf POLL stehen<br>
- </li>
- <br>
- <li><b>ADDRESSE</b><br>
- Adresse, an der der auszulesende Wert im Speicher zu finden ist.<br>
- Sie besteht aus 3 Teilen:<br>
- <ul>
- <li> beginnt immer mit 01F7 (Kommando zum Lesen)</li>
- <li> danach folgt die eigentliche Addresse<br></li>
- <li> danach muss die Anzahl der zu lesenden Bytes noch an die Adresse angehängt werden.<br></li>
- </ul>
- </li>
- <br>
- <li><b>PARSEMETHODE</b><br>
- Methode wie die gelesenen Bytes interpretiert werden müssen.<br>
- Bisher mögliche Parsemethoden:<br>
- <ul>
- <li>1ByteU :<br> Empfangener Wert in 1 Byte ohne Vorzeichen (wenn Spalte Divisor state ist -> nur 0 / 1 also off / on)<br></li>
- <li>1ByteU2 :<br> Empfangener Wert in 1 Byte ohne Vorzeichen (wenn Spalte Divisor state ist -> nur 0 / 1 also off / on)<br></li>
- <li>1ByteS :<br> Empfangener Wert in 1 Byte mit Vorzeichen (wenn Spalte Divisor state ist -> nur 0 / 1 also off / on)<br></li>
- <li>2ByteS :<br> Empfangener Wert in 2 Byte mit Vorzeichen<br></li>
- <li>2ByteU :<br> Empfangener Wert in 2 Byte ohne Vorzeichen<br></li>
- <li>2BytePercent :<br> Empfangener Wert in 2 Byte als Prozent Wert<br></li>
- <li>2ByteH :<br> Empfangener Wert in 2 Byte als Hex Wert<br></li>
- <li>4Byte :<br> Empfangener Wert in 4 Byte<br></li>
- <li>mode :<br> Empfangener Wert ist der Betriebsstatus<br></li>
- <li>timer :<br> Empfangener Wert ist ein 8 Byte Timer Werte<br></li>
- <li>date :<br> Empfangener Wert ist ein 8 Byte Zeitstempel<br></li>
- POLL Commandos die die Parsemethode timer enthalten werden nicht ständig gelesen, sondern müssen mit einem GET Commando geholt werden.<br>
- GET <devicename> TIMER<br>
- </ul>
- </li>
- <br>
- <li><b>DIVISOR</b><br>
- Wenn der interpretierte Wert noch um einen Faktor zu hoch ist, kann hier ein Divisor angegeben werden.<br>
- Zusätzlich hat man hier bei Werten, die nur 0 oder 1 liefern die möglich state einzutragen.<br>
- Dies führt dazu, dass das Reading mit off (0) und on (1) belegt wird, statt mit dem Wert.<br>
- </li>
- <br>
- <li><b>READING-NAME</b><br>
- Der gelesene und interpretierte Wert wird unter diesem Reading abgelegt.
- </li>
- <br>
- <li><b>KUMULATION</b><br>
- Bei den Polling Commandos mit dem Wert day bei der Spalte KUMULATION werden Tageswerte Kumuliert.<br>
- Es werden dann jeweils nach 00:00 Uhr die Werte des letzten Tages ebenfalls als Readings im Device eingetragen,<br>
- so dass man die Werte pro Tag auch plotten oder auswerten kann.<br>
- Beim Readingnamen wird dann jeweils: DayStart,Today und LastDay angehangen!<br>
- </li>
-
- <br>
- Beispiel:<br><br>
- <code>POLL, 01F7080402, 2ByteS, 10 , Temp-WarmWasser-Ist , -<br></code>
- <code>POLL, 01F7088A02, 2ByteU, 1 , BrennerStarts , day<br></code>
- </ul>
- <br><br>
- <b>Set Commandos haben den folgenden Aufbau:<br><br></b>
- SET,SETCMD, ADRESSE, CONVMETHODE, NEXT_CMD or DAY for timer<br><br>
-
- <ul>
- <li><b>SET</b><br>
- muss fest auf SET stehen<br>
- </li>
- <br>
- <li><b>SETCMD</b><br>
- Die SETCMD sind die Commandos die man in FHEM zum setzen angeben muss<br>
- set <devicename> <setcmd><br>
- z.B. SET <devicename> WW zum setzen auf den Status nur Warm Wasser Aufbereitung<br>
- </li>
- <br>
-
- <li><b>ADDRESSE</b><br>
- Adresse, an der der zu setzende Wert im Speicher zu schreiben ist.<br>
- Sie besteht aus 4 Teilen:<br>
- <ul>
- <li> beginnt immer mit 01F4 (Kommando zum Lesen)</li>
- <li> danach folgt die eigentliche Addresse<br></li>
- <li> danach folgt die Anzahl der zu schreibenden Daten-Bytes<br></li>
- <li> danach müssen die Daten-Bytes selber noch an die Adresse angehängt werden.<br></li>
- </ul>
- <br>
- Es gibt zwei Varianten bei den Adressen:<br>
- <li>Variante 1: Wert steht bereits fest, z.B. Spar Modus einschalten ist fix 01<br></li>
- <li>Variante 2: Wert muss übergeben werden, z.B. Warm Wasser Temperatur<br></li>
- </li>
- <br>
- <li><b>CONVMETHODE</b><br>
- Methode wie der zu schreibende Wert bei Variante 2 in Bytes konvertiert werden muss.<br>
- Bei Variante 1 kann man - eintragen.<br>
- Bisher mögliche Convmethoden:<br>
- <ul>
- <li>1ByteU :<br> Zu sendender Wert in 1 Byte ohne Vorzeichen<br>bei Variante 2 muss eine Zahl übergeben werden<br></li>
- <li>1ByteS :<br> Zu sendender Wert in 1 Byte mit Vorzeichen<br>bei Variante 2 muss eine Zahl übergeben werden<br></li>
- <li>2ByteS :<br> Zu sendender Wert in 2 Byte mit Vorzeichen<br>bei Variante 2 muss eine Zahl übergeben werden<br></li>
- <li>2ByteU :<br> Zu sendender Wert in 2 Byte ohne Vorzeichen<br>bei Variante 2 muss eine Zahl übergeben werden<br></li>
- <li>timer :<br> Zu sendender Wert ist ein 8 Byte Timer Werte<br>bei Variante 2 muss folgender String uebergeben werden:<br>
- 8 Uhrzeiten mit Komma getrennt. (AN1,AUS1,AN2,AUS2,AN3,AUS3,AN4,AUS4)<br>
- Keine Uhrzeit muss als -- angegeben werden.<br>
- Minuten der Uhrzeiten dürfen nur 00,10,20,30,40 oder 50 sein<br>
- Beispiel: 06:10,12:00,16:00,23:00,--,--,--,--</li>
- <li>date :<br> Zu sendender Wert ist ein 8 Byte Zeitstempel<br>bei Variante 2 muss folgender String uebergeben werden:<br>
- es muss das Format DD.MM.YYYY_HH:MM:SS eingehalten werden<br>
- Beispiel: 21.03.2014_21:35:00</li>
- </ul>
- </li>
- <br>
- <li><b>NEXT_CMD or DAY</b><br>
- Diese Spalte erfüllt drei Funktionen:
- <ul>
- <li>Gibt man in dieser Spalte ein anderes konfiguriertes SETCMD an, so wird dies anschließend ausgeführt.<br>
- Beispiel: nach dem Spar Modus (S-ON) gesetzt wurde, muss der Party Modus (P-OFF) ausgeschaltet werden<br>
- </li>
- <li> Ist als CONVMETHODE 1ByteU oder 1ByteS oder 2ByteS oder 2ByteU angegeben, so kann hier ein Faktor angegeben,<br>
- der beim SET auf den angegeben multipliziert wird<br>
- Beispiel: <code>SET, TEMPNHK1 , 01F4200002 , 2ByteU , 10</code>
- Bei <code>SET DEVICE TEMPNHK1 21</code> wird 210 an die Heizung gesendet.
- </li>
- <li>Ist als CONVMETHODE timer angegeben, so muss man in dieser Spalte den Wochentag angeben, für den der Timer gilt.<br>
- Mögliche Werte: MO DI MI DO FR SA SO<br></li>
- </li>
- <br>
- </ul>
- Beispiele:<br><br>
- <code>SET, WW , 01F423010100, state , -<br></code>
- <code>SET, S-ON , 01F423020101, state_spar , P-OFF<br></code>
- <code>SET, WWTEMP , 01F4630001 , 1ByteU , -<br></code>
- <code>SET, TIMER_2_MO, 01F4200008 , timer , MO<br></code>
- </ul>
- </ul>
- <br>
- <a name="VCONTROLreadings"><b>Readings</b></a>
- <ul>Die eingelesenen Werte werden wie oben beschrieben in selbst konfigurierten Readings abgelegt.</ul>
- </ul>
- =end html_DE
- =cut
|