From f61e9d327b77c9e2ecbc79d3685b4a89459afe45 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Tue, 19 Jul 2022 20:20:20 +0200 Subject: [PATCH 01/29] cleanup code, fix start up defined string --- CHANGED | 2 +- FHEM/74_GardenaSmartDevice.pm | 150 ++++---------------------------- controls_GardenaSmartDevice.txt | 2 +- 3 files changed, 19 insertions(+), 135 deletions(-) diff --git a/CHANGED b/CHANGED index edb2815..37eb437 100644 --- a/CHANGED +++ b/CHANGED @@ -1 +1 @@ - [Ticket: no] + Reviewed-by: Marko Oldenburg diff --git a/FHEM/74_GardenaSmartDevice.pm b/FHEM/74_GardenaSmartDevice.pm index ec8973d..a68b12b 100644 --- a/FHEM/74_GardenaSmartDevice.pm +++ b/FHEM/74_GardenaSmartDevice.pm @@ -921,9 +921,10 @@ sub WriteReadings { $winter_mode = $decode_json->{settings}[$settings]{value}; } } - - if ($decode_json->{settings}[$settings]{name} eq 'valve_names' - && ref( $decode_json->{settings}[$settings]{value} ) eq "ARRAY" ) { # or HASH ? + + if ( defined( $decode_json->{settings}[$settings]{name} ) + && $decode_json->{settings}[$settings]{name} eq 'valve_names' + && ref( $decode_json->{settings}[$settings]{value} ) eq "ARRAY" ) { # or HASH ? my @valves = @{$decode_json->{settings}[$settings]{value}}; foreach my $valve( @valves ) { Log3 $name, 4, "GardenaSmartDevice ($name) valve_name $valve->{'name'}"; @@ -1000,12 +1001,15 @@ sub setState { my @opened_valves; my $state_string = ''; my $nearst_irrigation = '2999-12-12 12:00'; my $has_schedule = 0; my $longest_duration = 0; my $processed_item = ''; + my $error_type = 'ok'; my @valves_connected = AttrVal( $name, 'model', 'unknown' ) eq 'ic24' ? split(',', ReadingsVal( $name, 'ic24-valves_connected', '')) : '1'; $has_schedule = 1 if ( ReadingsVal($name, 'scheduling-schedules_events_count', '') ne '' ); for (@valves_connected){ # valves 1 or 1..6 ## add to opened ventils, if watering active push @opened_valves, $_ if ( ( ( ReadingsVal( $name, "watering-watering_timer_".$_."_duration", 0 ) =~ m{\A[1-9]([0-9]+)?\z}xms ) ? $_ : 0 ) > 0 ); + ## set error type (pumpe required) + $error_type = ReadingsVal( $name, 'error-valve_error_'.$_.'_type', 'ok' ) if (ReadingsVal( $name, 'error-valve_error_'.$_.'_type', 'ok' ) ne 'ok'); ## find longest irrigation duration $longest_duration = ReadingsVal( $name, "watering-watering_timer_".$_."_irrigation_left", 0 ) if ( ( ReadingsVal( $name, "watering-watering_timer_".$_."_duration", 0 ) =~ m{\A[1-9]([0-9]+)?\z}xms @@ -1017,13 +1021,13 @@ sub setState { ? RigReadingsValue($hash, ReadingsVal($name, 'scheduling-schedules_paused_until_'.$_, '')) : RigReadingsValue($hash, ReadingsVal($name, 'scheduling-schedules_paused_until', '')); - Log3 $name, 3, "[DEBUG] - process: $processed_item"; - Log3 $name, 3, "[DEBUG] - next_start: ". ReadingsVal($name, 'scheduling-scheduled_watering_next_start', ''); # n/a RigReadingsValue( $hash, 'n/a') + Log3 $name, 5, "[DEBUG] - process: $processed_item"; + Log3 $name, 5, "[DEBUG] - next_start: ". ReadingsVal($name, 'scheduling-scheduled_watering_next_start', ''); # n/a RigReadingsValue( $hash, 'n/a') # $nearst_irrigation = RigReadingsValue($hash, ReadingsVal($name, 'scheduling-schedules_paused_until_'.$_, '')) if ( ReadingsVal($name, 'scheduling-scheduled_watering_next_start', '') eq RigReadingsValue( $hash, 'n/a') ) { # non next start, schedules paused permanently or next schedule > 1 year; get nearst paused_until - Log3 $name, 3, "[DEBUG] - next_start: empty "; - Log3 $name, 3, "[DEBUG] - empty pro item ".Time::Piece->strptime( $processed_item, "%Y-%m-%d %H:%M:%S"); - Log3 $name, 3, "[DEBUG] - empty nearst ".Time::Piece->strptime( $nearst_irrigation, "%Y-%m-%d %H:%M:%S"); + Log3 $name, 5, "[DEBUG] - next_start: empty "; + Log3 $name, 5, "[DEBUG] - empty pro item ".Time::Piece->strptime( $processed_item, "%Y-%m-%d %H:%M:%S"); + Log3 $name, 5, "[DEBUG] - empty nearst ".Time::Piece->strptime( $nearst_irrigation, "%Y-%m-%d %H:%M:%S"); $nearst_irrigation = $processed_item if ( Time::Piece->strptime( $processed_item, "%Y-%m-%d %H:%M:%S") < Time::Piece->strptime( $nearst_irrigation, "%Y-%m-%d %H:%M:%S") @@ -1034,7 +1038,7 @@ sub setState { } else { $nearst_irrigation = ReadingsVal($name, 'scheduling-scheduled_watering_next_start', ''); } - Log3 $name, 3, "[DEBUG] - choosed nearst: $nearst_irrigation"; + Log3 $name, 5, "[DEBUG] - choosed nearst: $nearst_irrigation"; ###### @@ -1091,7 +1095,7 @@ sub setState { ' ) if ( AttrVal( $name, 'stateFormat', 'none' ) eq 'none' ); } else { - Log3 $name, 3, "[DEBUG] - Offene Ventile :".scalar(@opened_valves)." laengste bewaesserung: $longest_duration . hat Zeitplan: $has_schedule Naechster Zeitplan: $nearst_irrigation"; + Log3 $name, 5, "[DEBUG] - Offene Ventile :".scalar(@opened_valves)." laengste bewaesserung: $longest_duration . hat Zeitplan: $has_schedule Naechster Zeitplan: $nearst_irrigation"; $state_string = scalar(@opened_valves) > 0 # offen ? sprintf( (RigReadingsValue($hash, 'will be irrigated %.f minutes remaining.')), $longest_duration/60) @@ -1113,101 +1117,14 @@ sub setState { ; # state offline | override $state_string = 'offline' if ($online_state eq 'offline'); + $state_string = ( $error_type ne 'ok' ) ? $error_type : $state_string; } - - ## check ob ws offen ist - # ja -> dann zeig alle offene an ( durch api max. 2 ) - ## - # nein -> dann nur closed - # - ## check ob ein zeitplan aktiv - # ja -> zeig nur den nächsten an - ## - # nein -> permanent geschlosen - #### - # ### eventuell auf binare bits und shiften - # $state_string .= $activ_watering > 0 - # # offen - # ? - # ( ReadingsVal($name, 'scheduling-schedules_paused_until_'.$activ_watering, '' ) eq '' ) - # # leer ( zeitplan aktiv ... ) - # ? sprintf('V'.$activ_watering.' '.(RigReadingsValue($hash, 'will be irrigated %.f minutes remaining.').' '.RigReadingsValue($hash, 'next watering: %s')), (ReadingsVal( $name, 'watering-watering_timer_'.$activ_watering.'_duration', 0 )/60), RigReadingsValue($hash, ReadingsVal($name, 'scheduling-scheduled_watering_next_start_'.$activ_watering, '')) ) - # # zeitplan pausiert - # : - # ( ReadingsVal($name, 'scheduling-schedules_paused_until_'.$activ_watering , '') eq '2038-01-18T00:00:00.000Z') - # # pause bis dauerhaft - # ? sprintf('V'.$activ_watering.' '. (RigReadingsValue($hash, 'will be irrigated %.f minutes remaining.').' '.RigReadingsValue($hash , 'schedule permanently paused')), (ReadingsVal( $name, 'watering-watering_timer_'.$activ_watering.'_duration', 0 )/60) ) - # # naechter termin - # : sprintf('V'.$activ_watering.' '. RigReadingsValue($hash , 'paused until %s'), RigReadingsValue($hash, ReadingsVal($name, 'scheduling-schedules_paused_until_'.$activ_watering , '')) ) - # # zu - # : - # ( ReadingsVal($name, 'scheduling-schedules_paused_until_'.$activ_watering , '' ) eq '' ) - # # zeitplan aktiv - # ? sprintf( (RigReadingsValue($hash, 'closed') .'. '.RigReadingsValue($hash, 'next watering: %s')), RigReadingsValue($hash, ReadingsVal($name, 'scheduling-scheduled_watering_next_start_'.$activ_watering, '') ) ) - # # zeitplan pausiert - # : RigReadingsValue($hash, 'closed') - # ; - - #} FOR valvces_connected - # if ($activ_watering > 0) - # { - # # ein ventil offen - # my $state_string = "ein ventil offen" - # } readingsBulkUpdate( $hash, 'state', RigReadingsValue( $hash, $state_string ) ); } - #online state water control - # zeitplan -> dauert pausiert wenn 2038-01-18T00:00:00.000Z - - # watering-watering_timer_1_state idle | scheduled | manual - # watering-watering_timer_1_duration 0 in sec - # scheduling-scheduled_watering_next_start XXX - # scheduling-scheduled_watering_end | end < NOW && duration = 0 => abbruch manuell - # scheduling-schedules_paused_until - - - # 1. Ventil geschlossen, Zeitplan pausiert. - # App zeigt: nichts (wenn vorher ein Zeitplan abgebrochen wurde, steht da "Unterbrochen xx:yy - zz:aa") - # 2. Ventil geschlossen, Zeitplan aktiv. - # App zeigt: "Nächste Bewässerung heute um xx:yy Uhr" (wenn vorher ein Zeitplan abgebrochen wurde, steht da vorher auch "Unterbrochen xx:yy - zz:aa") - # 3. Ventil manuell geoeffnet, späterer Zeitplan aktiv. - # Wird bewässert xx Minuten verbleibend" und "Nächste Bewässerung heute um xx:yy Uhr" - # 4. Ventil manuell geoeffnet, Zeitpläne deaktiviert. - # App zeigt: "Wird bewässert xx Minuten verbleibend" - ### CHANGE to one - # if ( AttrVal( $name, 'model', 'unknown' ) eq 'watering_computer' ){ - - # my $state_string = ReadingsVal( $name, 'watering-watering_timer_1_duration', 0 ) =~ - # m{\A[1-9]([0-9]+)?\z}xms - # # offen - # ? - # ( ReadingsVal($name, 'scheduling-schedules_paused_until', '' ) eq '' ) - # # leer ( zeitplan aktiv ... ) - # ? sprintf( (RigReadingsValue($hash, 'will be irrigated %.f minutes remaining.').' '.RigReadingsValue($hash, 'next watering: %s')), (ReadingsVal( $name, 'watering-watering_timer_1_irrigation_left', 0 )/60), RigReadingsValue($hash, ReadingsVal($name, 'scheduling-scheduled_watering_next_start', '')) ) - # # zeitplan pausiert - # : - # ( ReadingsVal($name, 'scheduling-schedules_paused_until', '') eq '2038-01-18T00:00:00.000Z') - # # pause bis dauerhaft - # ? sprintf( (RigReadingsValue($hash, 'will be irrigated %.f minutes remaining.').' '.RigReadingsValue($hash , 'schedule permanently paused')), (ReadingsVal( $name, 'watering-watering_timer_1_irrigation_left', 0 )/60) ) - # # naechter termin - # : sprintf( RigReadingsValue($hash , 'paused until %s'), RigReadingsValue($hash, ReadingsVal($name, 'scheduling-schedules_paused_until', '')) ) - # # zu - # : - # ( ReadingsVal($name, 'scheduling-schedules_paused_until', '' ) eq '' ) - # # zeitplan aktiv - # ? sprintf( (RigReadingsValue($hash, 'closed') .'. '.RigReadingsValue($hash, 'next watering: %s')), RigReadingsValue($hash, ReadingsVal($name, 'scheduling-scheduled_watering_next_start', '') ) ) - # # zeitplan pausiert - # : RigReadingsValue($hash, 'closed') - # ; - # # state offline | override - # $state_string = 'offline' if ($online_state eq 'offline'); - - # readingsBulkUpdate( - # $hash, 'state', RigReadingsValue( $hash, $state_string ) ); - # } + # Sensor / Sensor 2 if ( AttrVal( $name, 'model', 'unknown' ) =~ /sensor.?/ ) { my $state_string = ( ReadingsVal( $name, 'device_info-category', 'unknown' ) eq @@ -1241,39 +1158,6 @@ sub setState { ReadingsVal( $name, 'power-power_timer', 'no info from power-timer' ) ) if ( AttrVal( $name, 'model', 'unknown' ) eq 'power' ); - # #electronic water pump - # if ( AttrVal( $name, 'model', 'unknown' ) eq 'electronic_pressure_pump' ) { # | ok | pump_not_filled (Pumpe nicht gefüllt) - # my $state_string = ReadingsVal( $name, 'watering-watering_timer_1_duration', 0 ) =~ - # m{\A[1-9]([0-9]+)?\z}xms - # # offen - # ? - # ( ReadingsVal($name, 'scheduling-schedules_paused_until', '' ) eq '' ) - # # leer ( zeitplan aktiv ... ) - # ? sprintf( (RigReadingsValue($hash, 'will be irrigated %.f minutes remaining.').' '.RigReadingsValue($hash, 'next watering: %s')), (ReadingsVal( $name, 'watering-watering_timer_1_duration', 0 )/60), RigReadingsValue($hash, ReadingsVal($name, 'scheduling-scheduled_watering_next_start', '')) ) - # # zeitplan pausiert - # : - # ( ReadingsVal($name, 'scheduling-schedules_paused_until', '') eq '2038-01-18T00:00:00.000Z') - # # pause bis dauerhaft - # ? sprintf( (RigReadingsValue($hash, 'will be irrigated %.f minutes remaining.').' '.RigReadingsValue($hash , 'schedule permanently paused')), (ReadingsVal( $name, 'watering-watering_timer_1_duration', 0 )/60) ) - # # naechter termin - # : sprintf( RigReadingsValue($hash , 'paused until %s'), RigReadingsValue($hash, ReadingsVal($name, 'scheduling-schedules_paused_until', '')) ) - # # zu - # : - # ( ReadingsVal($name, 'scheduling-schedules_paused_until', '' ) eq '' ) - # # zeitplan aktiv - # ? sprintf( (RigReadingsValue($hash, 'closed') .'. '.RigReadingsValue($hash, 'next watering: %s')), RigReadingsValue($hash, ReadingsVal($name, 'scheduling-scheduled_watering_next_start', '') ) ) - # # zeitplan pausiert - # : RigReadingsValue($hash, 'closed') - # ; - # # state offline | override - # $state_string = 'offline' if ($online_state eq 'offline'); - # # check valv error, override state - # my $error_type = ReadingsVal( $name, 'error-valve_error_1_type', 'ok' ); - # $state_string = ( $error_type ne 'ok' ) ? $error_type : $state_string; - - # readingsBulkUpdate( - # $hash, 'state', RigReadingsValue( $hash, $state_string ) ); - # } return; } @@ -1870,7 +1754,7 @@ sub SetPredefinedStartPoints { ], "release_status": "stable", "license": "GPL_2", - "version": "v2.5.4", + "version": "v2.5.5", "author": [ "Marko Oldenburg " ], diff --git a/controls_GardenaSmartDevice.txt b/controls_GardenaSmartDevice.txt index 69e96c8..af773db 100644 --- a/controls_GardenaSmartDevice.txt +++ b/controls_GardenaSmartDevice.txt @@ -1,2 +1,2 @@ UPD 2022-07-12_20:03:00 49634 FHEM/73_GardenaSmartBridge.pm -UPD 2022-07-13_20:56:14 81987 FHEM/74_GardenaSmartDevice.pm +UPD 2022-07-19_20:20:03 71804 FHEM/74_GardenaSmartDevice.pm From abcccefeb4771059c04ae7ee0b19a0f3f5320097 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Wed, 20 Jul 2022 12:15:53 +0200 Subject: [PATCH 02/29] cleanup --- CHANGED | 2 +- FHEM/74_GardenaSmartDevice.pm | 3535 +++++++++++++++---------------- controls_GardenaSmartDevice.txt | 2 +- 3 files changed, 1752 insertions(+), 1787 deletions(-) diff --git a/CHANGED b/CHANGED index 37eb437..af74819 100644 --- a/CHANGED +++ b/CHANGED @@ -1 +1 @@ - Reviewed-by: Marko Oldenburg + cleanup code, fix start up defined string diff --git a/FHEM/74_GardenaSmartDevice.pm b/FHEM/74_GardenaSmartDevice.pm index a68b12b..363f97d 100644 --- a/FHEM/74_GardenaSmartDevice.pm +++ b/FHEM/74_GardenaSmartDevice.pm @@ -1,1785 +1,1750 @@ -############################################################################### -# -# Developed with VSCodium and richterger perl plugin. -# -# (c) 2017-2022 Copyright: Marko Oldenburg (fhemdevelopment at cooltux dot net) -# All rights reserved -# -# Special thanks goes to comitters: -# - Michael (mbrak) Thanks for Commandref -# - Matthias (Kenneth) Thanks for Wiki entry -# - BioS Thanks for predefined start points Code -# - fettgu Thanks for Debugging Irrigation Control data flow -# - Sebastian (BOFH) Thanks for new Auth Code after API Change -# -# -# This script 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 -# any later version. -# -# The GNU General Public License can be found at -# http://www.gnu.org/copyleft/gpl.html. -# A copy is found in the textfile GPL.txt and important notices to the license -# from the author is found in LICENSE.txt distributed with these scripts. -# -# This script 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. -# -# -# $Id$ -# -############################################################################### -## -## -## Das JSON Modul immer in einem eval aufrufen -# $data = eval{decode_json($data)}; -# -# if($@){ -# Log3($SELF, 2, "$TYPE ($SELF) - error while request: $@"); -# -# readingsSingleUpdate($hash, "state", "error", 1); -# -# return; -# } -# -# -###### Wichtige Notizen -# -# apt-get install libio-socket-ssl-perl -# http://www.dxsdata.com/de/2016/07/php-class-for-gardena-smart-system-api/ -# -## -## - -## unserer packagename -package FHEM::GardenaSmartDevice; -use GPUtils qw(GP_Import GP_Export); - -use strict; -use warnings; -use POSIX; -use FHEM::Meta; -use Time::Local; -use Time::Piece; -use Time::Seconds; - -# try to use JSON::MaybeXS wrapper -# for chance of better performance + open code -eval { - require JSON::MaybeXS; - import JSON::MaybeXS qw( decode_json encode_json ); - 1; -} or do { - - # try to use JSON wrapper - # for chance of better performance - eval { - # JSON preference order - local $ENV{PERL_JSON_BACKEND} = - 'Cpanel::JSON::XS,JSON::XS,JSON::PP,JSON::backportPP' - unless ( defined( $ENV{PERL_JSON_BACKEND} ) ); - - require JSON; - import JSON qw( decode_json encode_json ); - 1; - } or do { - - # In rare cases, Cpanel::JSON::XS may - # be installed but JSON|JSON::MaybeXS not ... - eval { - require Cpanel::JSON::XS; - import Cpanel::JSON::XS qw(decode_json encode_json); - 1; - } or do { - - # In rare cases, JSON::XS may - # be installed but JSON not ... - eval { - require JSON::XS; - import JSON::XS qw(decode_json encode_json); - 1; - } or do { - - # Fallback to built-in JSON which SHOULD - # be available since 5.014 ... - eval { - require JSON::PP; - import JSON::PP qw(decode_json encode_json); - 1; - } or do { - - # Fallback to JSON::backportPP in really rare cases - require JSON::backportPP; - import JSON::backportPP qw(decode_json encode_json); - 1; - }; - }; - }; - }; -}; - -## Import der FHEM Funktionen -#-- Run before package compilation -BEGIN { - - # Import from main context - GP_Import( - qw(readingsSingleUpdate - readingsBulkUpdate - readingsBulkUpdateIfChanged - readingsBeginUpdate - readingsEndUpdate - Log3 - CommandAttr - AttrVal - ReadingsVal - readingFnAttributes - AssignIoPort - modules - IOWrite - defs - makeDeviceName) - ); -} - -#-- Export to main context with different name -GP_Export( - qw( - Initialize - ) -); - -sub Initialize { - my $hash = shift; - - $hash->{Match} = '^{"id":".*'; - - $hash->{SetFn} = \&Set; - $hash->{DefFn} = \&Define; - $hash->{UndefFn} = \&Undef; - $hash->{ParseFn} = \&Parse; - - $hash->{AttrFn} = \&Attr; - $hash->{AttrList} = - "readingValueLanguage:de,en " - . "model:watering_computer,sensor,sensor2,mower,ic24,power,electronic_pressure_pump " - . "extendedState:0,1 " - . "IODev " - . $readingFnAttributes; - $hash->{parseParams} = 1; - - return FHEM::Meta::InitMod( __FILE__, $hash ); -} - -sub Define { - my $hash = shift // return; - my $aArg = shift // return; - - return $@ unless ( FHEM::Meta::SetInternals($hash) ); - use version 0.60; our $VERSION = FHEM::Meta::Get( $hash, 'version' ); - - return - "too few parameters: define GardenaSmartDevice " - if ( scalar( @{$aArg} ) < 3 ); - - my $name = $aArg->[0]; - my $deviceId = $aArg->[2]; - my $category = $aArg->[3]; - - $hash->{DEVICEID} = $deviceId; - $hash->{VERSION} = version->parse($VERSION)->normal; - $hash->{helper}{STARTINGPOINTID} = ''; - $hash->{helper}{schedules_paused_until_id} = ''; - $hash->{helper}{eco_mode_id} = ''; - $hash->{helper}{button_config_time_id} = ''; - $hash->{helper}{winter_mode_id} = ''; - # Electroni Pressure Pump - $hash->{helper}{operating_mode_id} = ''; - $hash->{helper}{leakage_detection_id} = ''; - $hash->{helper}{turn_on_pressure_id} = ''; - - - $hash->{helper}{_id} = ''; - - # IrrigationControl valve control max 6 - $hash->{helper}{schedules_paused_until_1_id} = ''; - $hash->{helper}{schedules_paused_until_2_id} = ''; - $hash->{helper}{schedules_paused_until_3_id} = ''; - $hash->{helper}{schedules_paused_until_4_id} = ''; - $hash->{helper}{schedules_paused_until_5_id} = ''; - $hash->{helper}{schedules_paused_until_6_id} = ''; - - CommandAttr( undef, - "$name IODev $modules{GardenaSmartBridge}{defptr}{BRIDGE}->{NAME}" ) - if ( AttrVal( $name, 'IODev', 'none' ) eq 'none' ); - - my $iodev = AttrVal( $name, 'IODev', 'none' ); - - AssignIoPort( $hash, $iodev ) if ( !$hash->{IODev} ); - - if ( defined( $hash->{IODev}->{NAME} ) ) { - Log3 $name, 3, "GardenaSmartDevice ($name) - I/O device is " - . $hash->{IODev}->{NAME}; - } - else { - Log3 $name, 1, "GardenaSmartDevice ($name) - no I/O device"; - } - - $iodev = $hash->{IODev}->{NAME}; - - my $d = $modules{GardenaSmartDevice}{defptr}{$deviceId}; - - return -"GardenaSmartDevice device $name on GardenaSmartBridge $iodev already defined." - if ( defined($d) - && $d->{IODev} == $hash->{IODev} - && $d->{NAME} ne $name ); - - CommandAttr( undef, $name . ' room GardenaSmart' ) - if ( AttrVal( $name, 'room', 'none' ) eq 'none' ); - - CommandAttr( undef, $name . ' model ' . $category ) - if ( AttrVal( $name, 'model', 'none' ) eq 'none' ); - - Log3 $name, 3, -"GardenaSmartDevice ($name) - defined GardenaSmartDevice with DEVICEID: $deviceId"; - readingsSingleUpdate( $hash, 'state', 'initialized', 1 ); - - $modules{GardenaSmartDevice}{defptr}{$deviceId} = $hash; - - return; -} - -sub Undef { - my $hash = shift; - my $arg = shift; - - my $name = $hash->{NAME}; - my $deviceId = $hash->{DEVICEID}; - - delete $modules{GardenaSmartDevice}{defptr}{$deviceId}; - - return; -} - -sub Attr { - - my ( $cmd, $name, $attrName, $attrVal ) = @_; - my $hash = $defs{$name}; - - return; -} - -sub Set { - my $hash = shift // return; - my $aArg = shift // return; - - my $name = shift @$aArg; - my $cmd = shift @$aArg - // return qq{"set $name" needs at least one argument}; - - my $payload; - my $abilities; - my $service_id; - my $mainboard_version = - ReadingsVal( $name, 'mower_type-mainboard_version', 0.0 ); - - my ($Sekunden, $Minuten, $Stunden, $Monatstag, $Monat, - $Jahr, $Wochentag, $Jahrestag, $Sommerzeit) = localtime(time); - - my $timezone_offset = $Sommerzeit ? 0 : ( Time::Piece->new )->tzoffset; - - #set default abilitie ... overwrite in cmd to change - $abilities = 'mower' - if ( AttrVal( $name, 'model', 'unknown' ) eq 'mower' ); - $abilities = 'watering' - if ( AttrVal( $name, 'model', 'unknown' ) eq 'ic24' - || AttrVal( $name, 'model', 'unknown' ) eq 'watering_computer' ); - $abilities = 'power' - if ( AttrVal( $name, 'model', 'unknown' ) eq 'power' ); - $abilities = 'watering' - if ( AttrVal( $name, 'model', 'unknown' ) eq 'electronic_pressure_pump' ); - - ### mower - # service_id (eco, parkuntilfurhternotice, startpoints) - if ( lc $cmd eq 'parkuntilfurthernotice' ) { - $payload = '"name":"park_until_further_notice"'; - if ( $mainboard_version > 10.30 ) { - $payload = -' "settings":{"name":"schedules_paused_until","value":"2038-01-18T00:00:00.000Z","device":"' - . $hash->{DEVICEID} . '"}'; - $abilities = 'mower_settings'; - $service_id = $hash->{helper}{schedules_paused_until_id}; - } - } - elsif ( lc $cmd eq 'parkuntilnexttimer' ) { - $payload = '"name":"park_until_next_timer"'; - if ( $mainboard_version > 10.30 ) { - $payload = '"properties":{"name":"mower_timer","value":0}'; - $abilities = 'mower_timer'; - } - } - elsif ( lc $cmd eq 'startresumeschedule' ) { - $payload = '"name":"start_resume_schedule"'; - if ( $mainboard_version > 10.30 ) { - $payload = -' "settings":{"name":"schedules_paused_until","value":"","device":"' - . $hash->{DEVICEID} . '"}'; - $abilities = 'mower_settings'; - $service_id = $hash->{helper}{schedules_paused_until_id}; - } - } - elsif ( lc $cmd eq 'startoverridetimer' ) { - $payload = '"name":"start_override_timer","parameters":{"duration":' - . $aArg->[0] * 60 . '}'; - if ( $mainboard_version > 10.30 ) { - $payload = '"properties":{"name":"mower_timer","value":' - . $aArg->[0] * 60 . '}'; - $abilities = 'mower_timer'; - } - - } - elsif ( lc $cmd eq 'startpoint' ) { - my $err; - ( $err, $payload, $abilities ) = - SetPredefinedStartPoints( $hash, $aArg ); - $service_id = $hash->{helper}{STARTINGPOINTID}; - return $err if ( defined($err) ); - } - elsif ( lc $cmd eq 'eco' ) { - $payload = - '"settings": {"name": "eco_mode", "value": ' - . $aArg->[0] - . ', "device": "' - . $hash->{DEVICEID} . '"}'; - $abilities = 'mower_settings' if ( $mainboard_version > 10.30 ); - $service_id = $hash->{helper}{eco_mode_id}; - -#$abilities['service_id'] = $hash->{helper}{SCHEDULESID} if ( $mainboard_version > 10.30 ); - } - ### electronic_pressure_pump - # elsif ( lc $cmd eq 'pumptimer' ) { - # $payload = - # '"name":"pump_manual_watering_timer","parameters":{"duration":' - # . $aArg->[0] . '}'; - # } - ### watering_computer & electronic pump - elsif ( lc $cmd eq 'manualoverride' ) { - $payload = - '"properties":{"name":"watering_timer_1' - . '","value":{"state":"manual","duration":' - . $aArg->[0] * 60 - . ',"valve_id":1}}'; - } - elsif ( lc $cmd eq 'manualbuttontime' ) { - $service_id = $hash->{helper}{button_config_time_id}; - $payload = - '"properties":{"name":"button_config_time",' - . '"value":' - . $aArg->[0] * 60 - . ',"timestamp":"2021-05-26T19:06:23.680Z"' - . ',"at_bound":null,"unit":"seconds","ability":"' - . $service_id . '"}'; - $abilities = 'watering_button_config'; - } - elsif ( $cmd =~ m{\AcancelOverride}xms ) { - - my $valve_id = 1; - - if ( $cmd =~ m{\AcancelOverrideValve(\d)\z}xms ) { - $valve_id = $1; - } - - $payload = - '"properties":{"name":"watering_timer_' - . $valve_id - . '","value":{"state":"idle","duration":' - . 0 - . ',"valve_id":' - . $valve_id . '}}'; - } - elsif ( $cmd =~ /.*Schedule$/ ) { - my $duration = ( - ( - defined( $aArg->[0] ) - ? ( - ( - ( Time::Piece->new ) + - ( ONE_HOUR * $aArg->[0] ) - - $timezone_offset - )->datetime - ) - . '.000Z' - : '2038-01-18T00:00:00.000Z' - ) - ); - - $abilities = 'wateringcomputer_settings'; - $service_id = $hash->{helper}->{'schedules_paused_until_id'}; - $payload = - '"settings":{"name":"schedules_paused_until"' - . ', "value":"' - . ( $cmd eq 'resumeSchedule' ? '' : $duration ) - . '","device":"' - . $hash->{DEVICEID} . '"}'; - } - elsif ( lc $cmd eq 'on' || lc $cmd eq 'off' || lc $cmd eq 'on-for-timer' ) { - my $val = ( - scalar( !@$aArg == 0 ) && ref($aArg) eq 'ARRAY' - ? $aArg->[0] * 60 - : lc $cmd - ); - - $payload = - '"properties":{"name":"power_timer", "value":"' . $val . '"}'; - } - ### Watering ic24 - elsif ( $cmd =~ m{\AmanualDurationValve\d\z}xms ) { - my $valve_id; - - if ( $cmd =~ m{\AmanualDurationValve(\d)\z}xms ) { - $valve_id = $1; - } - - $payload = - '"properties":{"name":"watering_timer_' - . $valve_id - . '","value":{"state":"manual","duration":' - . $aArg->[0] * 60 - . ',"valve_id":' - . $valve_id . '}}'; - } - elsif ( $cmd eq 'closeAllValves' ) { - $payload = '"name":"close_all_valves","parameters":{}'; - } - elsif ( $cmd =~ /.*ScheduleValve$/ ) { - my $valve_id = $aArg->[0]; - my $duration = ( - ( - defined( $aArg->[1] ) - ? ( - ( - ( Time::Piece->new ) + - ( ONE_HOUR * $aArg->[1] ) - - $timezone_offset - )->datetime - ) - . '.000Z' - : '2038-01-18T00:00:00.000Z' - ) - ); - - $abilities = 'irrigation_settings'; - $service_id = - $hash->{helper}->{ 'schedules_paused_until_' . $valve_id . '_id' }; - $payload = - '"settings":{"name":"schedules_paused_until_' - . $valve_id - . '", "value":"' - . ( $cmd eq 'resumeScheduleValve' ? '' : $duration ) - . '","device":"' - . $hash->{DEVICEID} . '"}'; - } - ### Watering_pressure_pump - elsif ( lc $cmd eq 'operating_mode') { - my $op_mode = $aArg->[0]; - $payload = '"settings":{"name":"operating_mode",' - .'"value":"'.$op_mode.'",' - .'"device":"' - . $hash->{DEVICEID}.'"}'; - $abilities = 'watering_pressure_pump_settings'; - $service_id = $hash->{helper}->{ 'operating_mode_id' }; - } - elsif ( lc $cmd eq 'leakage_detection') { - my $leakdetection_mode = $aArg->[0]; - $payload = '"settings":{"name":"leakage_detection",' - .'"value":"'.$leakdetection_mode.'",' - .'"device":"' - . $hash->{DEVICEID}.'"}'; - $abilities = 'watering_pressure_pump_settings'; - $service_id = $hash->{helper}->{ 'leakage_detection_id' }; - } - elsif ( lc $cmd eq 'turn_on_pressure') { - my $turnonpressure = $aArg->[0]; - $payload = '"settings":{"name":"turn_on_pressure",' - .'"value":"'.$turnonpressure.'",' - .'"device":"' - . $hash->{DEVICEID}.'"}'; - $abilities = 'watering_pressure_pump_settings'; - $service_id = $hash->{helper}->{ 'turn_on_pressure_id' }; - } - elsif ( lc $cmd eq 'resetvalveerrors') { - $payload = '"name":"reset_valve_errors",' - .' "parameters": {}'; - $abilities = 'error'; - } - - ### Sensors - elsif ( lc $cmd eq 'refresh' ) { - - my $sensname = $aArg->[0]; - if ( lc $sensname eq 'temperature' ) { - if ( ReadingsVal( $name, 'device_info-category', 'sensor' ) eq - 'sensor' ) - { - $payload = '"name":"measure_ambient_temperature"'; - $abilities = 'ambient_temperature'; - } - else { - $payload = '"name":"measure_soil_temperature"'; - $abilities = 'soil_temperature'; - } - } - elsif ( lc $sensname eq 'light' ) { - $payload = '"name":"measure_light"'; - $abilities = 'light'; - - } - elsif ( lc $sensname eq 'humidity' ) { - $payload = '"name":"measure_soil_humidity"'; - $abilities = 'humidity'; - } - } - ## winter sleep - elsif ( lc $cmd eq 'winter_mode' ) { - $payload = - '"settings":{"name":"winter_mode","value":"' - . $aArg->[0] - . '","device":"' - . $hash->{DEVICEID} . '"}'; - $abilities = 'winter_settings'; - $service_id = $hash->{helper}->{'winter_mode_id'}; - } - else { - - my $list = ''; - - $list .= -'parkUntilFurtherNotice:noArg parkUntilNextTimer:noArg startResumeSchedule:noArg startOverrideTimer:slider,0,1,240 startpoint' - if ( AttrVal( $name, 'model', 'unknown' ) eq 'mower' ); - - $list .= -'manualOverride:slider,1,1,59 cancelOverride:noArg resumeSchedule:noArg stopSchedule manualButtonTime:slider,0,2,100' - if ( AttrVal( $name, 'model', 'unknown' ) eq 'watering_computer' ); - - - $list .= 'manualOverride:slider,1,1,90 cancelOverride:noArg operating_mode:automatic,scheduled leakage_detection:watering,washing_machine,domestic_water_supply,off turn_on_pressure:slider,2,0.2,3.0,1 resetValveErrors:noArg' - if ( AttrVal( $name, 'model', 'unknown' ) eq 'electronic_pressure_pump' ); - - $list .= -'closeAllValves:noArg stopScheduleValve:select,'.ReadingsVal( $name, 'ic24-valves_connected', '1' ).' resumeScheduleValve:select,'.ReadingsVal( $name, 'ic24-valves_connected', '1' ) - if ( AttrVal( $name, 'model', 'unknown' ) eq 'ic24' ); - - foreach my $valve (split(',', ReadingsVal( $name, 'ic24-valves_connected', '1'))) { - $list .= ' manualDurationValve'.$valve.':slider,1,1,90 ' - if ( AttrVal( $name, 'model', 'unknown' ) eq 'ic24' ); - } - - foreach my $valve (split(',', ReadingsVal( $name, 'ic24-valves_connected', '1'))) { - $list .= ' cancelOverrideValve'.$valve.':noArg ' - if ( AttrVal( $name, 'model', 'unknown' ) eq 'ic24' ); - } - - $list .= 'refresh:temperature,humidity' - if ( AttrVal( $name, 'model', 'unknown' ) =~ /sensor.?/ ); - - # add light for old sensors - $list .= ',light' - if ( AttrVal( $name, 'model', 'unknown' ) eq 'sensor' - && ReadingsVal( $name, 'device_info-category', 'unknown' ) eq - 'sensor' ); - - $list .= 'on:noArg off:noArg on-for-timer:slider,0,1,720' - if ( AttrVal( $name, 'model', 'unknown' ) eq 'power' ); - - # all devices has abilitie to fall a sleep - $list .= ' winter_mode:awake,hibernate'; - return "Unknown argument $cmd, choose one of $list"; - } - - $hash->{helper}{deviceAction} = $payload; - readingsSingleUpdate( $hash, "state", "send command to gardena cloud", 1 ); - - IOWrite( $hash, $payload, $hash->{DEVICEID}, $abilities, $service_id ); - Log3 $name, 4, -"GardenaSmartBridge ($name) - IOWrite: $payload $hash->{DEVICEID} $abilities IODevHash=$hash->{IODev}"; - - return; -} - -sub Parse { - my $io_hash = shift; - my $json = shift; - - my $name = $io_hash->{NAME}; - - my $decode_json = eval { decode_json($json) }; - if ($@) { - Log3 $name, 3, - "GardenaSmartDevice ($name) - JSON error while request: $@"; - } - - Log3 $name, 4, "GardenaSmartDevice ($name) - ParseFn was called"; - Log3 $name, 4, "GardenaSmartDevice ($name) - JSON: $json"; - - if ( defined( $decode_json->{id} ) ) { - - my $deviceId = $decode_json->{id}; - - if ( my $hash = $modules{GardenaSmartDevice}{defptr}{$deviceId} ) { - my $name = $hash->{NAME}; - - WriteReadings( $hash, $decode_json ); - Log3 $name, 4, - "GardenaSmartDevice ($name) - find logical device: $hash->{NAME}"; - - return $hash->{NAME}; - - } - else { - - Log3 $name, 3, - "GardenaSmartDevice ($name) - autocreate new device " - . makeDeviceName( $decode_json->{name} ) - . " with deviceId $decode_json->{id}, model $decode_json->{category}"; - return - "UNDEFINED " - . makeDeviceName( $decode_json->{name} ) - . " GardenaSmartDevice $decode_json->{id} $decode_json->{category}"; - } - } - - return; -} - -sub WriteReadings { - my $hash = shift; - my $decode_json = shift; - - my $name = $hash->{NAME}; - my $abilities = scalar( @{ $decode_json->{abilities} } ); - my $settings = scalar( @{ $decode_json->{settings} } ); - my $scheduled_events = scalar( @{ $decode_json->{scheduled_events} } ); - - readingsBeginUpdate($hash); - - do { - - if ( - ref( $decode_json->{abilities}[$abilities]{properties} ) eq "ARRAY" - && scalar( @{ $decode_json->{abilities}[$abilities]{properties} } ) - > 0 ) - { - for my $propertie ( - @{ $decode_json->{abilities}[$abilities]{properties} } ) - { - if ( - exists( $decode_json->{abilities}[$abilities]{name} ) - && ( $decode_json->{abilities}[$abilities]{name} eq - 'watering' ) - ) - { - - if ( $propertie->{name} eq 'button_config_time' ) { - if ( $hash->{helper}{ $propertie->{name} . '_id' } ne - $decode_json->{abilities}[$abilities]{id} ) - { - $hash->{helper}{ $propertie->{name} . '_id' } = - $decode_json->{abilities}[$abilities]{id}; - } - readingsBulkUpdateIfChanged( - $hash, - 'manualButtonTime', - ( - RigReadingsValue( - $hash, $propertie->{value} / 60 - ) - ) - ); - next; - } - } - - readingsBulkUpdateIfChanged( - $hash, - $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name}, - ($propertie->{value} eq '') ? RigReadingsValue( $hash, 'n/a') : RigReadingsValue( $hash, $propertie->{value} ) - ) - if ( exists( $propertie->{value} ) # defined ignored 'value':null - && $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} ne 'radio-quality' - && $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} ne 'battery-level' - && $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} ne 'internal_temperature-temperature' - && $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} ne 'ambient_temperature-temperature' - && $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} ne 'soil_temperature-temperature' - && $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} ne 'humidity-humidity' - && $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} ne 'light-light' - && ref( $propertie->{value} ) ne "HASH" ); - - readingsBulkUpdateIfChanged( - $hash, - $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name}, - RigReadingsValue( $hash, $propertie->{value} ) - ) - if ( - defined( $propertie->{value} ) - && ( $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} eq 'radio-quality' - || $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} eq 'battery-level' - || $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} eq - 'internal_temperature-temperature' - || $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} eq - 'ambient_temperature-temperature' - || $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} eq 'soil_temperature-temperature' - || $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} eq 'humidity-humidity' - || $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} eq 'light-light' ) - ); - - readingsBulkUpdateIfChanged( - $hash, - $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} - . '_timestamp', - Time::Piece->strptime( - RigReadingsValue( $hash, $propertie->{timestamp} ), - "%Y-%m-%d %H:%M:%S" )->strftime('%s') - - ) - if ( - defined( $propertie->{value} ) - && ( $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} eq 'mower_timer-mower_timer' ) - ); - - readingsBulkUpdateIfChanged( - $hash, - $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name}, - join( ',', @{ $propertie->{value} } ) - ) - if ( defined( $propertie->{value} ) - && $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} eq 'ic24-valves_connected' ); - - readingsBulkUpdateIfChanged( - $hash, - $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name}, - join( ',', @{ $propertie->{value} } ) - ) - if ( defined( $propertie->{value} ) - && $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} eq 'ic24-valves_master_config' ); - - if ( ref( $propertie->{value} ) eq "HASH" ) { - my $sub_state = 0; my $sub_value = 0; - while ( my ( $r, $v ) = each %{ $propertie->{value} } ) { - if ( ref( $v ) ne "HASH" ) { - readingsBulkUpdate( - $hash, - $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} . '_' - . $r, - RigReadingsValue( $hash, $v ) - ); - } else { - while ( my ( $i_r, $i_v ) = each %{ $v } ) { - readingsBulkUpdate( - $hash, - $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} . '_' - . $r . '_' . $i_r, - RigReadingsValue( $hash, $i_v ) - ); - } - } - } - } - # ic24 and other watering devices calc irrigation left in sec - readingsBulkUpdateIfChanged( - $hash, - $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} - . '_irrigation_left', - ( $propertie->{value}{duration} > 0 ) ? (Time::Piece::localtime->strptime( - RigReadingsValue($hash, $propertie->{timestamp}), "%Y-%m-%d %H:%M:%S") - + ($propertie->{value}{duration} + 3 ) - Time::Piece::localtime->new) : 0 - ) - if ( defined( $propertie->{value} ) - && $decode_json->{abilities}[$abilities]{name} eq 'watering' - ); - } - } - - $abilities--; - } while ( $abilities >= 0 ); - - - if ( - exists( $decode_json->{scheduled_events} ) - # && scalar ($decode_json->{scheduled_events} ) > 0 - && ref ($decode_json->{scheduled_events}) eq 'ARRAY' ) { - readingsBulkUpdateIfChanged( $hash, 'scheduling-schedules_events_count', - scalar( @{$decode_json->{scheduled_events} } ) ); - my $valve_id =1; my $event_id = 1; # ic24 [1..6] | wc, pump [1] - - for my $event_schedules ( @{ $decode_json->{scheduled_events} } ) { - $valve_id = $event_schedules->{valve_id} if ( exists($event_schedules->{valve_id} ) ); #ic24 - $event_id++; # event id - - while ( my ( $r, $v ) = each %{ $event_schedules } ) { - readingsBulkUpdateIfChanged( $hash, 'scheduling-schedules_event_' - . $event_id - . '_valve_' - . $valve_id - . '_' - . $r, - $v) if (ref($v) ne 'HASH' ); - readingsBulkUpdateIfChanged( $hash, 'scheduling-schedules_event_' - . $event_id - . '_valve_' - . $valve_id - . '_' - . $v->{type}, - join(',', @ { $v->{weekdays}}) ) if (ref($v) eq 'HASH' ); - }; - }; - - }; # fi scheduled_events - - my $winter_mode; - - do { -#Log3 $name, 1, "Settings pro Device : ".$decode_json->{settings}[$settings]{name}; -#Log3 $name, 1, " - KEIN ARRAY" if ( ref( $decode_json->{settings}[$settings]{value} ) ne "ARRAY"); -#Log3 $name, 1, " - IST ARRAY" if ( ref( $decode_json->{settings}[$settings]{value} ) eq "ARRAY"); - - if ( - exists( $decode_json->{settings}[$settings]{name} ) - && ( $decode_json->{settings}[$settings]{name} =~ - /schedules_paused_until_?\d?$/ - || $decode_json->{settings}[$settings]{name} eq 'eco_mode' - || $decode_json->{settings}[$settings]{name} eq 'winter_mode' - || $decode_json->{settings}[$settings]{name} eq 'operating_mode' - || $decode_json->{settings}[$settings]{name} eq 'leakage_detection' - || $decode_json->{settings}[$settings]{name} eq 'turn_on_pressure' ) - ) - { - if ( $hash->{helper} - { $decode_json->{settings}[$settings]{name} . '_id' } ne - $decode_json->{settings}[$settings]{id} ) - { - $hash->{helper} - { $decode_json->{settings}[$settings]{name} . '_id' } = - $decode_json->{settings}[$settings]{id}; - } - # check watering controler single schedules pause until - if ( $decode_json->{settings}[$settings]{name} eq 'schedules_paused_until' ) { - readingsBulkUpdateIfChanged( $hash, 'scheduling-schedules_paused_until', - $decode_json->{settings}[$settings]{value} ); - } - ##### - #ic24 schedules pause until - if ($decode_json->{settings}[$settings]{name} =~ /schedules_paused_until_?(\d)?$/) { - #my $ventil = substr($decode_json->{settings}[$settings]{name}, -1); # => 1 - 6 - # check if empty, clear scheduling-scheduled_watering_next_start_x - readingsBulkUpdateIfChanged( $hash, 'scheduling-'.$decode_json->{settings}[$settings]{name}, - $decode_json->{settings}[$settings]{value} ); - # CommandAttr( undef, $name . " scheduling-scheduled_watering_next_start_") if ($decode_json->{settings}[$settings]{value} eq '' ) - } - - # save electronid pressure pump settings as readings - if ( $decode_json->{settings}[$settings]{name} eq 'operating_mode' - || $decode_json->{settings}[$settings]{name} eq 'leakage_detection' - || $decode_json->{settings}[$settings]{name} eq 'turn_on_pressure' ) { - readingsBulkUpdateIfChanged( $hash, $decode_json->{settings}[$settings]{name}, - $decode_json->{settings}[$settings]{value} ); - - } - # save winter mode as reading - if ( $decode_json->{settings}[$settings]{name} eq 'winter_mode' ) { - readingsBulkUpdateIfChanged( $hash, 'winter_mode', - $decode_json->{settings}[$settings]{value} ); - - $winter_mode = $decode_json->{settings}[$settings]{value}; - } - } - - if ( defined( $decode_json->{settings}[$settings]{name} ) - && $decode_json->{settings}[$settings]{name} eq 'valve_names' - && ref( $decode_json->{settings}[$settings]{value} ) eq "ARRAY" ) { # or HASH ? - my @valves = @{$decode_json->{settings}[$settings]{value}}; - foreach my $valve( @valves ) { - Log3 $name, 4, "GardenaSmartDevice ($name) valve_name $valve->{'name'}"; - readingsBulkUpdateIfChanged( $hash, 'valve-valve_name_'.$valve->{"id"}, - $valve->{"name"} ); - } - } - - if ( ref( $decode_json->{settings}[$settings]{value} ) eq "ARRAY" - && $decode_json->{settings}[$settings]{name} eq 'starting_points' ) - { - #save the startingpointid needed to update the startingpoints - if ( $hash->{helper}{STARTINGPOINTID} ne - $decode_json->{settings}[$settings]{id} ) - { - $hash->{helper}{STARTINGPOINTID} = - $decode_json->{settings}[$settings]{id}; - } - - $hash->{helper}{STARTINGPOINTS} = - '{ "name": "starting_points", "value": ' - . encode_json( $decode_json->{settings}[$settings]{value} ) . '}'; - my $startpoint_cnt = 0; - - for my $startingpoint ( - @{ $decode_json->{settings}[$settings]{value} } ) - { - $startpoint_cnt++; - readingsBulkUpdateIfChanged( - $hash, - 'startpoint-' . $startpoint_cnt . '-enabled', - $startingpoint->{enabled} - ); - } - } - - $settings--; - } while ( $settings >= 0 ); - - if ( $winter_mode ne 'hibernate' ) { - setState($hash); - } - else { - readingsBulkUpdate( $hash, 'state', - RigReadingsValue( $hash, 'hibernate' ) ); - } - - readingsEndUpdate( $hash, 1 ); - - Log3 $name, 4, "GardenaSmartDevice ($name) - readings was written"; - - return; -} - -sub setState { - my $hash = shift; - my $name = $hash->{NAME}; - - my $online_state = - ReadingsVal( $name, 'device_info-connection_status', 'unknown' ); - - #online state mower - readingsBulkUpdate( $hash, 'state', - $online_state eq 'online' - ? ReadingsVal( $name, 'mower-status', 'readingsValError' ) - : 'offline' ) - if ( AttrVal( $name, 'model', 'unknown' ) eq 'mower' ); - - # ic24 / wc / electronic pump - - if ( AttrVal( $name, 'model', 'unknown' ) eq 'ic24' - || AttrVal( $name, 'model', 'unknown' ) eq 'watering_computer' - || AttrVal( $name, 'model', 'unknown' ) eq 'electronic_pressure_pump' ){ - my @opened_valves; - my $state_string = ''; my $nearst_irrigation = '2999-12-12 12:00'; - my $has_schedule = 0; my $longest_duration = 0; my $processed_item = ''; - my $error_type = 'ok'; - my @valves_connected = AttrVal( $name, 'model', 'unknown' ) eq 'ic24' ? split(',', ReadingsVal( $name, 'ic24-valves_connected', '')) : '1'; - - $has_schedule = 1 if ( ReadingsVal($name, 'scheduling-schedules_events_count', '') ne '' ); - for (@valves_connected){ # valves 1 or 1..6 - ## add to opened ventils, if watering active - push @opened_valves, $_ if ( ( ( ReadingsVal( $name, "watering-watering_timer_".$_."_duration", 0 ) =~ m{\A[1-9]([0-9]+)?\z}xms ) ? $_ : 0 ) > 0 ); - ## set error type (pumpe required) - $error_type = ReadingsVal( $name, 'error-valve_error_'.$_.'_type', 'ok' ) if (ReadingsVal( $name, 'error-valve_error_'.$_.'_type', 'ok' ) ne 'ok'); - ## find longest irrigation duration - $longest_duration = ReadingsVal( $name, "watering-watering_timer_".$_."_irrigation_left", 0 ) if ( - ( ReadingsVal( $name, "watering-watering_timer_".$_."_duration", 0 ) =~ m{\A[1-9]([0-9]+)?\z}xms - && ReadingsVal( $name, "watering-watering_timer_".$_."_duration", 0 ) > 0 - && ReadingsVal( $name, "watering-watering_timer_".$_."_duration", 0 ) > $longest_duration ) ); - - # y-m-d h:m - $processed_item = AttrVal( $name, 'model', 'unknown' ) eq 'ic24' - ? RigReadingsValue($hash, ReadingsVal($name, 'scheduling-schedules_paused_until_'.$_, '')) - : RigReadingsValue($hash, ReadingsVal($name, 'scheduling-schedules_paused_until', '')); - - Log3 $name, 5, "[DEBUG] - process: $processed_item"; - Log3 $name, 5, "[DEBUG] - next_start: ". ReadingsVal($name, 'scheduling-scheduled_watering_next_start', ''); # n/a RigReadingsValue( $hash, 'n/a') - # $nearst_irrigation = RigReadingsValue($hash, ReadingsVal($name, 'scheduling-schedules_paused_until_'.$_, '')) - if ( ReadingsVal($name, 'scheduling-scheduled_watering_next_start', '') eq RigReadingsValue( $hash, 'n/a') ) { # non next start, schedules paused permanently or next schedule > 1 year; get nearst paused_until - Log3 $name, 5, "[DEBUG] - next_start: empty "; - Log3 $name, 5, "[DEBUG] - empty pro item ".Time::Piece->strptime( $processed_item, "%Y-%m-%d %H:%M:%S"); - Log3 $name, 5, "[DEBUG] - empty nearst ".Time::Piece->strptime( $nearst_irrigation, "%Y-%m-%d %H:%M:%S"); - $nearst_irrigation = $processed_item - if ( Time::Piece->strptime( $processed_item, "%Y-%m-%d %H:%M:%S") - < Time::Piece->strptime( $nearst_irrigation, "%Y-%m-%d %H:%M:%S") - && $has_schedule - && Time::Piece->strptime( $processed_item, "%Y-%m-%d %H:%M:%S") - > Time::Piece->new - ) - } else { - $nearst_irrigation = ReadingsVal($name, 'scheduling-scheduled_watering_next_start', ''); - } - Log3 $name, 5, "[DEBUG] - choosed nearst: $nearst_irrigation"; - - -###### -###### -###### $has_scheduling = 1 if ( ReadingsVal($name, 'scheduling-schedules_paused_until_'.$_ , '') ne '2038-01-18T00:00:00.000Z' ); #&& ReadingsVal($name, 'scheduling-schedules_paused_until_'.$_ , '') eq '' ); -###### #$has_scheduling = 1 if ( ReadingsVal($name, 'scheduling-schedules_paused_until_'.$_ , 'n/a') eq '' ); -###### -###### # if ( ReadingsVal($name, 'scheduling-scheduled_watering_next_start_'.$_, '') ne '' -###### # --- wenn next_start_x ne 'na' && paused_until_x eq '' -> start_x -###### ## scheduling-schedules_paused_until_* = leer oder n/a -> keine zeitpläne -###### -###### if ( ReadingsVal($name, 'scheduling-schedules_paused_until_'.$_ , '') ne '2038-01-18T00:00:00.000Z' ) { -###### # $nearst_irrigation = ReadingsVal($name, 'scheduling-scheduled_watering_next_start', ''); -###### Log3 $name, 3, "[DEBUG] - "; -###### -###### # $nearst_irrigation = RigReadingsValue($hash, ReadingsVal($name, 'scheduling-schedules_paused_until_'.$_, '')) -###### # if ( -###### # Time::Piece->strptime( RigReadingsValue($hash, ReadingsVal($name, 'scheduling-schedules_paused_until_'.$_, '')), "%Y-%m-%d %H:%M") < Time::Piece->strptime( $nearst_irrigation, "%Y-%m-%d %H:%M") -###### # && $has_scheduling && Time::Piece->strptime( RigReadingsValue($hash, ReadingsVal($name, 'scheduling-schedules_paused_until_'.$_, '')), "%Y-%m-%d %H:%M") > Time::Piece->new -###### # ) -###### if ( ReadingsVal($name, 'scheduling-scheduled_watering_next_start', '') eq '' ) { # non next start, schedules paused permanently or next schedule > 1 year; get nearst paused_until -###### $nearst_irrigation = RigReadingsValue($hash, ReadingsVal($name, 'scheduling-schedules_paused_until_'.$_, '')) -###### if ( Time::Piece->strptime( RigReadingsValue($hash, ReadingsVal($name, 'scheduling-schedules_paused_until_'.$_, '')), "%Y-%m-%d %H:%M") -###### < Time::Piece->strptime( $nearst_irrigation, "%Y-%m-%d %H:%M") -###### && $has_scheduling -###### && Time::Piece->strptime( RigReadingsValue($hash, ReadingsVal($name, 'scheduling-schedules_paused_until_'.$_, '')), "%Y-%m-%d %H:%M") -###### > Time::Piece->new -###### ) -###### } else { -###### $nearst_irrigation = ReadingsVal($name, 'scheduling-scheduled_watering_next_start', ''); -###### } -###### } # fi -###### -###### #$nearst_irrigation = ReadingsVal($name, 'scheduling-scheduled_watering_next_start', ''); -###### # if ( ReadingsVal($name, 'scheduling-scheduled_watering_next_start_'.$_, 'n/a') ne 'n/a' ); -###### - } # for - # override state 4 extendedstates - if ( AttrVal( $name, "extendedState", 0 ) == 1) { - if (scalar(@opened_valves) > 0){ - ## valve 1 will be ir.. 23 minutes remaining - for (@valves_connected){ - $state_string .= sprintf(RigReadingsValue($hash,'valve').' '.$_.' '.(RigReadingsValue($hash, 'will be irrigated %.f minutes remaining.') .'
'), (ReadingsVal( $name, 'watering-watering_timer_'.$_.'_duration', 0 )/60)); - } # /for - } else { - $state_string .= RigReadingsValue($hash, 'closed'); - } - $state_string .= ($has_schedule) ? sprintf( RigReadingsValue($hash, 'next watering: %s'), RigReadingsValue($hash, ReadingsVal($name, 'scheduling-scheduled_watering_next_start', ''))) : sprintf( RigReadingsValue($hash, 'paused until %s') , $nearst_irrigation); - #TODO: Write state format for ventil 1-@valces_connected -> map ? - CommandAttr( undef, $name . ' stateFormat - { - - } - ' ) - if ( AttrVal( $name, 'stateFormat', 'none' ) eq 'none' ); - } else { - Log3 $name, 5, "[DEBUG] - Offene Ventile :".scalar(@opened_valves)." laengste bewaesserung: $longest_duration . hat Zeitplan: $has_schedule Naechster Zeitplan: $nearst_irrigation"; - $state_string = scalar(@opened_valves) > 0 - # offen - ? sprintf( (RigReadingsValue($hash, 'will be irrigated %.f minutes remaining.')), $longest_duration/60) - # zu - : - ( $has_schedule - && $nearst_irrigation ne '2999-12-12 12:00') - # zeitplan aktiv - # ? ( $nearst_irrigation eq '2038-01-18 00:00') sprintf( RigReadingsValue($hash, 'paused until %s') , $nearst_irrigation) - ? ( $nearst_irrigation eq RigReadingsValue( $hash, 'n/a') || $nearst_irrigation =~ '2038-01-18.*') - # dauerhaft pausiert - ? sprintf( (RigReadingsValue($hash, 'closed') .'. '.RigReadingsValue($hash , 'schedule permanently paused')) ) - # naechster zeutplan - : (ReadingsVal($name, 'scheduling-scheduled_watering_next_start', '') eq RigReadingsValue($hash, 'n/a')) - ? sprintf( RigReadingsValue($hash, 'paused until %s') , $nearst_irrigation) - : sprintf( (RigReadingsValue($hash, 'closed') .'. '.RigReadingsValue($hash, 'next watering: %s')), $nearst_irrigation ) - # zeitplan pausiert - : RigReadingsValue($hash, 'closed') - ; - # state offline | override - $state_string = 'offline' if ($online_state eq 'offline'); - $state_string = ( $error_type ne 'ok' ) ? $error_type : $state_string; - - } - readingsBulkUpdate( - $hash, 'state', RigReadingsValue( $hash, $state_string ) ); - } - - # Sensor / Sensor 2 - if ( AttrVal( $name, 'model', 'unknown' ) =~ /sensor.?/ ) { - my $state_string = - ( ReadingsVal( $name, 'device_info-category', 'unknown' ) eq - 'sensor' ) - ? 'T: ' - . ReadingsVal( $name, 'ambient_temperature-temperature', - 'readingsValError' ) - . '°C, ' - : 'T: ' - . ReadingsVal( $name, 'soil_temperature-temperature', - 'readingsValError' ) - . '°C, '; - $state_string .= 'H: ' - . ReadingsVal( $name, 'humidity-humidity', 'readingsValError' ) . '%'; - $state_string .= ', L: ' - . ReadingsVal( $name, 'light-light', 'readingsValError' ) . 'lux' - if ( ReadingsVal( $name, 'device_info-category', 'unknown' ) eq - 'sensor' ); - -# if ( $online_state eq 'offline') { -# readingsBulkUpdate( $hash, 'humidity-humidity', '-1' ); -# readingsBulkUpdate( $hash, 'ambient_temperature-temperature', '-1' ) if (ReadingsVal($name, 'device_info-category', 'unknown') eq 'sensor'); -# readingsBulkUpdate( $hash, 'light-light', '-1' ) if (ReadingsVal($name, 'device_info-category', 'unknown') eq 'sensor'); -# } - #online state sensor I II - readingsBulkUpdate( $hash, 'state', - $online_state eq 'online' ? RigReadingsValue( $hash, $state_string) : RigReadingsValue( $hash, 'offline') ); - } - - readingsBulkUpdate( $hash, 'state', - ReadingsVal( $name, 'power-power_timer', 'no info from power-timer' ) ) - if ( AttrVal( $name, 'model', 'unknown' ) eq 'power' ); - - return; -} - -################################## -################################## -#### my little helpers ########### - -sub ReadingLangGerman { - my $hash = shift; - my $readingValue = shift; - - my $name = $hash->{NAME}; - my %langGermanMapp = ( - 'ok_cutting' => 'mähen', - 'paused' => 'pausiert', - 'ok_searching' => 'suche Ladestation', - 'ok_charging' => 'lädt', - 'ok_leaving' => 'unterwegs zum Startpunkt', - 'wait_updating' => 'wird aktualisiert ...', - 'wait_power_up' => 'wird eingeschaltet ...', - 'parked_timer' => 'geparkt nach Zeitplan', - 'parked_park_selected' => 'geparkt', - 'off_disabled' => 'der Mäher ist ausgeschaltet', - 'off_hatch_open' => 'deaktiviert. Abdeckung ist offen oder PIN-Code erforderlich', - 'unknown' => 'unbekannter Status', - 'error' => 'Fehler', - 'error_at_power_up' => 'Neustart ...', - 'off_hatch_closed' => 'Deaktiviert. Manueller Start erforderlich', - 'ok_cutting_timer_overridden' => 'manuelles mähen', - 'parked_autotimer' => 'geparkt durch SensorControl', - 'parked_daily_limit_reached' => 'abgeschlossen', - 'no_message' => 'kein Fehler', - 'outside_working_area' => 'außerhalb des Arbeitsbereichs', - 'no_loop_signal' => 'kein Schleifensignal', - 'wrong_loop_signal' => 'falsches Schleifensignal', - 'loop_sensor_problem_front' => 'Problem Schleifensensor, vorne', - 'loop_sensor_problem_rear' => 'Problem Schleifensensor, hinten', - 'trapped' => 'eingeschlossen', - 'upside_down' => 'steht auf dem Kopf', - 'low_battery' => 'niedriger Batteriestand', - 'empty_battery' => 'Batterie leer', - 'no_drive' => 'fährt nicht', - 'lifted' => 'angehoben', - 'stuck_in_charging_station' => 'eingeklemmt in Ladestation', - 'charging_station_blocked' => 'Ladestation blockiert', - 'collision_sensor_problem_rear' => 'Problem Stoßsensor hinten', - 'collision_sensor_problem_front' => 'Problem Stoßsensor vorne', - 'wheel_motor_blocked_right' => 'Radmotor rechts blockiert', - 'wheel_motor_blocked_left' => 'Radmotor links blockiert', - 'wheel_drive_problem_right' => 'Problem Antrieb, rechts', - 'wheel_drive_problem_left' => 'Problem Antrieb, links', - 'cutting_system_blocked' => 'Schneidsystem blockiert', - 'invalid_sub_device_combination' => 'fehlerhafte Verbindung', - 'settings_restored' => 'Standardeinstellungen', - 'electronic_problem' => 'elektronisches Problem', - 'charging_system_problem' => 'Problem Ladesystem', - 'tilt_sensor_problem' => 'Kippsensor Problem', - 'wheel_motor_overloaded_right' => 'rechter Radmotor überlastet', - 'wheel_motor_overloaded_left' => 'linker Radmotor überlastet', - 'charging_current_too_high' => 'Ladestrom zu hoch', - 'temporary_problem' => 'vorübergehendes Problem', - 'guide_1_not_found' => 'SK 1 nicht gefunden', - 'guide_2_not_found' => 'SK 2 nicht gefunden', - 'guide_3_not_found' => 'SK 3 nicht gefunden', - 'difficult_finding_home' => 'Problem die Ladestation zu finden', - 'guide_calibration_accomplished' => 'Kalibrierung des Suchkabels beendet', - 'guide_calibration_failed' => 'Kalibrierung des Suchkabels fehlgeschlagen', - 'temporary_battery_problem' => 'kurzzeitiges Batterieproblem', - 'battery_problem' => 'Batterieproblem', - 'alarm_mower_switched_off' => 'Alarm! Mäher ausgeschalten', - 'alarm_mower_stopped' => 'Alarm! Mäher gestoppt', - 'alarm_mower_lifted' => 'Alarm! Mäher angehoben', - 'alarm_mower_tilted' => 'Alarm! Mäher gekippt', - 'connection_changed' => 'Verbindung geändert', - 'connection_not_changed' => 'Verbindung nicht geändert', - 'com_board_not_available' => 'COM Board nicht verfügbar', - 'slipped' => 'rutscht', - 'out_of_operation' => 'ausser Betrieb', - 'replace_now' => 'kritischer Batteriestand, wechseln Sie jetzt', - 'low' => 'niedrig', - 'ok' => 'ok', - 'no_source' => 'ok', - 'mower_charging' => 'Mäher wurde geladen', - 'completed_cutting_autotimer' => 'Sensor Control erreicht', - 'week_timer' => 'Wochentimer erreicht', - 'countdown_timer' => 'Stoppuhr Timer', - 'undefined' => 'unklar', - 'unknown' => 'unklar', - 'status_device_unreachable' => 'Gerät ist nicht in Reichweite', - 'status_device_alive' => 'Gerät ist in Reichweite', - 'bad' => 'schlecht', - 'poor' => 'schwach', - 'good' => 'gut', - 'undefined' => 'unklar', - 'idle' => 'nichts zu tun', - 'firmware_cancel' => 'Firmwareupload unterbrochen', - 'firmware_upload' => 'Firmwareupload', - 'unsupported' => 'nicht unterstützt', - 'up_to_date' => 'auf dem neusten Stand', - 'mower' => 'Mäher', - 'watering_computer' => 'Bewässerungscomputer', - 'no_frost' => 'kein Frost', - 'open' => 'offen', - 'closed' => 'geschlossen', - 'included' => 'inbegriffen', - 'active' => 'aktiv', - 'inactive' => 'nicht aktiv', - 'hibernate' => 'Winterschlaf', - 'awake' => 'Aufgewacht', - 'schedule permanently paused' => 'Zeitplan dauerhaft pausiert', - 'paused until %s' => 'pausiert bis %s', - 'will be irrigated %.f minutes remaining.'=> 'Wird bewässert. %.f Minuten verbleibend.', - 'next watering: %s' => 'Nächste Bewässerung: %s', - 'n/a' => 'nicht verfügbar', - 'pump_not_filled' => 'Pumpe nicht gefüllt', - ); - - if ( - defined( $langGermanMapp{$readingValue} ) - && ( AttrVal( 'global', 'language', 'none' ) eq 'DE' - || AttrVal( $name, 'readingValueLanguage', 'none' ) eq 'de' ) - && AttrVal( $name, 'readingValueLanguage', 'none' ) ne 'en' - ) - { - return $langGermanMapp{$readingValue}; - } - else { - return $readingValue; - } - - return; -} - -sub RigReadingsValue { - my $hash = shift; - my $readingValue = shift; - - my $rigReadingValue; - - if ( $readingValue =~ /^(\d+)-(\d\d)-(\d\d)T(\d\d)/ ) { - $rigReadingValue = Zulu2LocalString($readingValue); - } - else { - $rigReadingValue = ReadingLangGerman( $hash, $readingValue ); - } - - return $rigReadingValue; -} - -sub Zulu2LocalString { - my $t = shift; - - my ( $datehour, $datemin, $rest ) = split( /:/, $t, 3 ); - - my ( $year, $month, $day, $hour, $min ) = - $datehour =~ /(\d+)-(\d\d)-(\d\d)T(\d\d)/; - my $epoch = timegm( 0, 0, $hour, $day, $month - 1, $year ); - - my ( $lyear, $lmonth, $lday, $lhour, $isdst ) = - ( localtime($epoch) )[ 5, 4, 3, 2, -1 ]; - - $lyear += 1900; # year is 1900 based - $lmonth++; # month number is zero based - - if ( defined($rest) ) { - return ( - sprintf( - "%04d-%02d-%02d %02d:%02d:%s", - $lyear, $lmonth, $lday, - $lhour, $datemin, substr( $rest, 0, 2 ) - ) - ); - } - elsif ( $lyear < 2000 ) { - return 'temporarily unavailable'; - } - else { - return ( - sprintf( - "%04d-%02d-%02d %02d:%02d", - $lyear, $lmonth, $lday, $lhour, substr( $datemin, 0, 2 ) - ) - ); - } - - return; -} - -sub SetPredefinedStartPoints { - my $hash = shift; - my $aArg = shift; - - my ( $startpoint_state, $startpoint_num, @morestartpoints ) = @{$aArg}; - - my $name = $hash->{NAME}; - my $payload; - my $abilities; - - if ( defined($startpoint_state) && defined($startpoint_num) ) { - if ( defined( $hash->{helper}{STARTINGPOINTS} ) - && $hash->{helper}{STARTINGPOINTS} ne '' ) - { -# add needed parameters to saved settings config and change the value in request - my $decode_json_settings = - eval { decode_json( $hash->{helper}{STARTINGPOINTS} ) }; - if ($@) { - Log3 $name, 3, -"GardenaSmartBridge ($name) - JSON error while setting startpoint: $@"; - } - - $decode_json_settings->{device} = $hash->{DEVICEID}; - my $setval = $startpoint_state eq 'disable' ? \0 : \1; - $decode_json_settings->{value}[ $startpoint_num - 1 ]{enabled} = - $setval; - - #set more startpoints - if ( - defined scalar(@morestartpoints) - && ( scalar(@morestartpoints) == 2 - || scalar(@morestartpoints) == 4 ) - ) - { - if ( scalar(@morestartpoints) == 2 ) { - $setval = $morestartpoints[0] eq 'disable' ? \0 : \1; - $decode_json_settings->{value}[ $morestartpoints[1] - 1 ] - {enabled} = $setval; - - } - elsif ( scalar(@morestartpoints) == 4 ) { - $setval = $morestartpoints[0] eq 'disable' ? \0 : \1; - $decode_json_settings->{value}[ $morestartpoints[1] - 1 ] - {enabled} = $setval; - $setval = $morestartpoints[2] eq 'disable' ? \0 : \1; - $decode_json_settings->{value}[ $morestartpoints[3] - 1 ] - {enabled} = $setval; - } - } - - $payload = '"settings": ' . encode_json($decode_json_settings); - $abilities = 'mower_settings'; - - #$abilities['service_id'] = $hash->{helper}{STARTINGPOINTID}; - } - else { - return - "startingpoints not loaded yet, please wait a couple of minutes", - undef, undef; - } - } - else { - return - "startpoint usage: set " - . $hash->{NAME} - . " startpoint disable 1 [enable 2] [disable 3]", undef, undef; - } - - return undef, $payload, $abilities; -} - -1; - -=pod - -=item device -=item summary Modul to control GardenaSmart Devices -=item summary_DE Modul zur Steuerung von GardenaSmartgeräten - -=begin html - - -

GardenaSmartDevice

-
    - In combination with GardenaSmartBridge this FHEM Module controls the GardenaSmart Device using the GardenaCloud -

    - Once the Bridge device is created, the connected devices are automatically recognized and created in FHEM.
    - From now on the devices can be controlled and changes in the GardenaAPP are synchronized with the state and readings of the devices. - -


    - Readings -
      -
    • battery-charging - Indicator if the Battery is charged (0/1) or with newer Firmware (false/true)
    • -
    • battery-level - load percentage of the Battery
    • -
    • battery-rechargeable_battery_status - healthyness of the battery (out_of_operation/replace_now/low/ok)
    • -
    • device_info-category - category of device (mower/watering_computer)
    • -
    • device_info-last_time_online - timestamp of last radio contact
    • -
    • device_info-manufacturer - manufacturer
    • -
    • device_info-product - product type
    • -
    • device_info-serial_number - serial number
    • -
    • device_info-sgtin -
    • -
    • device_info-version - firmware version
    • -
    • firmware-firmware_command - firmware command (idle/firmware_cancel/firmware_upload/unsupported)
    • -
    • firmware-firmware_status - firmware status
    • -
    • firmware-firmware_update_start - indicator when a firmwareupload is started
    • -
    • firmware-firmware_upload_progress - progress indicator of firmware update
    • -
    • firmware-inclusion_status - inclusion status
    • -
    • internal_temperature-temperature - internal device temperature
    • -
    • mower-error - actual error message -
        -
      • no_message
      • -
      • outside_working_area
      • -
      • no_loop_signal
      • -
      • wrong_loop_signal
      • -
      • loop_sensor_problem_front
      • -
      • loop_sensor_problem_rear
      • -
      • trapped
      • -
      • upside_down
      • -
      • low_battery
      • -
      • empty_battery
      • -
      • no_drive
      • -
      • lifted
      • -
      • stuck_in_charging_station
      • -
      • charging_station_blocked
      • -
      • collision_sensor_problem_rear
      • -
      • collision_sensor_problem_front
      • -
      • wheel_motor_blocked_right
      • -
      • wheel_motor_blocked_left
      • -
      • wheel_drive_problem_right
      • -
      • wheel_drive_problem_left
      • -
      • cutting_system_blocked
      • -
      • invalid_sub_device_combination
      • -
      • settings_restored
      • -
      • electronic_problem
      • -
      • charging_system_problem
      • -
      • tilt_sensor_problem
      • -
      • wheel_motor_overloaded_right
      • -
      • wheel_motor_overloaded_left
      • -
      • charging_current_too_high
      • -
      • temporary_problem
      • -
      • guide_1_not_found
      • -
      • guide_2_not_found
      • -
      • guide_3_not_found
      • -
      • difficult_finding_home
      • -
      • guide_calibration_accomplished
      • -
      • guide_calibration_failed
      • -
      • temporary_battery_problem
      • -
      • battery_problem
      • -
      • alarm_mower_switched_off
      • -
      • alarm_mower_stopped
      • -
      • alarm_mower_lifted
      • -
      • alarm_mower_tilted
      • -
      • connection_changed
      • -
      • connection_not_changed
      • -
      • com_board_not_available
      • -
      • slipped
      • -
      -
    • -
    • mower-manual_operation - (0/1) or with newer Firmware (false/true)
    • -
    • mower-override_end_time - manual override end time
    • -
    • mower-source_for_next_start - source for the next start -
        -
      • no_source
      • -
      • mower_charging
      • -
      • completed_cutting_autotimer
      • -
      • week_timer
      • -
      • countdown_timer
      • -
      • undefined
      • -
      -
    • -
    • mower-status - mower state (see state)
    • -
    • mower-timestamp_next_start - timestamp of next scheduled start
    • -
    • radio-connection_status - state of connection
    • -
    • radio-quality - percentage of the radio quality
    • -
    • radio-state - radio state (bad/poor/good/undefined)
    • -
    • state - state of the mower -
        -
      • paused
      • -
      • ok_cutting
      • -
      • ok_searching
      • -
      • ok_charging
      • -
      • ok_leaving
      • -
      • wait_updating
      • -
      • wait_power_up
      • -
      • parked_timer
      • -
      • parked_park_selected
      • -
      • off_disabled
      • -
      • off_hatch_open
      • -
      • unknown
      • -
      • error
      • -
      • error_at_power_up
      • -
      • off_hatch_closed
      • -
      • ok_cutting_timer_overridden
      • -
      • parked_autotimer
      • -
      • parked_daily_limit_reached
      • -
      -
    • -
    -

    - - Attributes -
      -
    • readingValueLanguage - Change the Language of Readings (de,en/if not set the default is english and the global language is not set at german)
    • -
    • model -
    • -
    -

    - - set -
      -
    • winter_mode - awake | hibernate
    • -
    -
      -

      mower

      -
    • parkUntilFurtherNotice
    • -
    • parkUntilNextTimer
    • -
    • startOverrideTimer - (in minutes, 60 = 1h, 1440 = 24h, 4320 = 72h)
    • -
    • startResumeSchedule
    • -
    • startpoint enable|disable 1|2|3 - enables or disables one or more predefined start points
    • -
        -
      • set NAME startpoint enable 1
      • -
      • set NAME startpoint disable 3 enable 1
      • -
      -

      irrigation control

      -
    • resumeScheduleValve - start schedule irrigation on valve n
    • -
    • stopScheduleValve - stop schedule irrigation on valve n (Default: 2038-01-18T00:00:00.000Z) | optional params hours (now + hours)
    • -
    • closeAllValves - close all valves
    • -

      water control

      -
    • manualButtonTime - set manual time for button press (in minutes) 0 disable button
    • -
    • stopSchedule - stop schedule for now + n hours (Default: 2038-01-18T00:00:00.000Z)
    • -
    • resumeSchedule - resume schedule
    • -
    -
- -=end html -=begin html_DE - - -

GardenaSmartDevice

-
    - Zusammen mit dem Device GardenaSmartDevice stellt dieses FHEM Modul die Kommunikation zwischen der GardenaCloud und Fhem her. -

    - Wenn das GardenaSmartBridge Device erzeugt wurde, werden verbundene Geräte automatisch erkannt und in Fhem angelegt.
    - Von nun an können die eingebundenen Geräte gesteuert werden. Änderungen in der APP werden mit den Readings und dem Status syncronisiert. - -
-
-
    - Readings -
      -
    • battery-charging - Ladeindikator (0/1) oder mit neuerer Firmware (false/true)
    • -
    • battery-level - Ladezustand der Batterie in Prozent
    • -
    • battery-rechargeable_battery_status - Zustand der Batterie (Ausser Betrieb/Kritischer Batteriestand, wechseln Sie jetzt/Niedrig/oK)
    • -
    • device_info-category - Eigenschaft des Gerätes (Mäher/Bewässerungscomputer/Bodensensor)
    • -
    • device_info-last_time_online - Zeitpunkt der letzten Funkübertragung
    • -
    • device_info-manufacturer - Hersteller
    • -
    • device_info-product - Produkttyp
    • -
    • device_info-serial_number - Seriennummer
    • -
    • device_info-sgtin -
    • -
    • device_info-version - Firmware Version
    • -
    • firmware-firmware_command - Firmware Kommando (Nichts zu tun/Firmwareupload unterbrochen/Firmwareupload/nicht unterstützt)
    • -
    • firmware-firmware_status - Firmware Status
    • -
    • firmware-firmware_update_start - Firmwareupdate (0/1) oder mit neuerer Firmware (false/true)
    • -
    • firmware-firmware_upload_progress - Firmwareupdatestatus in Prozent
    • -
    • firmware-inclusion_status - Einbindungsstatus
    • -
    • internal_temperature-temperature - Interne Geräte Temperatur
    • -
    • mower-error - Aktuelle Fehler Meldung -
        -
      • Kein Fehler
      • -
      • Außerhalb des Arbeitsbereichs
      • -
      • Kein Schleifensignal
      • -
      • Falsches Schleifensignal
      • -
      • Problem Schleifensensor, vorne
      • -
      • Problem Schleifensensor, hinten
      • -
      • Eingeschlossen
      • -
      • Steht auf dem Kopf
      • -
      • Niedriger Batteriestand
      • -
      • Batterie ist leer
      • -
      • Kein Antrieb
      • -
      • Angehoben
      • -
      • Eingeklemmt in Ladestation
      • -
      • Ladestation blockiert
      • -
      • Problem Stoßsensor hinten
      • -
      • Problem Stoßsensor vorne
      • -
      • Radmotor rechts blockiert
      • -
      • Radmotor links blockiert
      • -
      • Problem Antrieb, rechts
      • -
      • Problem Antrieb, links
      • -
      • Schneidsystem blockiert
      • -
      • Fehlerhafte Verbindung
      • -
      • Standardeinstellungen
      • -
      • Elektronisches Problem
      • -
      • Problem Ladesystem
      • -
      • Kippsensorproblem
      • -
      • Rechter Radmotor überlastet
      • -
      • Linker Radmotor überlastet
      • -
      • Ladestrom zu hoch
      • -
      • Vorübergehendes Problem
      • -
      • SK 1 nicht gefunden
      • -
      • SK 2 nicht gefunden
      • -
      • SK 3 nicht gefunden
      • -
      • Problem die Ladestation zu finden
      • -
      • Kalibration des Suchkabels beendet
      • -
      • Kalibration des Suchkabels fehlgeschlagen
      • -
      • Kurzzeitiges Batterieproblem
      • -
      • Batterieproblem
      • -
      • Alarm! Mäher ausgeschalten
      • -
      • Alarm! Mäher gestoppt
      • -
      • Alarm! Mäher angehoben
      • -
      • Alarm! Mäher gekippt
      • -
      • Verbindung geändert
      • -
      • Verbindung nicht geändert
      • -
      • COM board nicht verfügbar
      • -
      • Rutscht
      • -
      -
    • -
    • mower-manual_operation - Manueller Betrieb (0/1) oder mit neuerer Firmware (false/true)
    • -
    • mower-override_end_time - Zeitpunkt wann der manuelle Betrieb beendet ist
    • -
    • mower-source_for_next_start - Grund für den nächsten Start -
        -
      • Kein Grund
      • -
      • Mäher wurde geladen
      • -
      • SensorControl erreicht
      • -
      • Wochentimer erreicht
      • -
      • Stoppuhr Timer
      • -
      • Undefiniert
      • -
      -
    • -
    • mower-status - Mäher Status (siehe state)
    • -
    • mower-timestamp_next_start - Zeitpunkt des nächsten geplanten Starts
    • -
    • radio-connection_status - Status der Funkverbindung
    • -
    • radio-quality - Indikator für die Funkverbindung in Prozent
    • -
    • radio-state - radio state (schlecht/schwach/gut/Undefiniert)
    • -
    • state - Staus des Mähers -
        -
      • Pausiert
      • -
      • Mähen
      • -
      • Suche Ladestation
      • -
      • Lädt
      • -
      • Mähen
      • -
      • Wird aktualisiert ...
      • -
      • Wird eingeschaltet ...
      • -
      • Geparkt nach Zeitplan
      • -
      • Geparkt
      • -
      • Der Mäher ist ausgeschaltet
      • -
      • Deaktiviert. Abdeckung ist offen oder PIN-Code erforderlich
      • -
      • Unbekannter Status
      • -
      • Fehler
      • -
      • Neustart ...
      • -
      • Deaktiviert. Manueller Start erforderlich
      • -
      • Manuelles Mähen
      • -
      • Geparkt durch SensorControl
      • -
      • Abgeschlossen
      • -
      -
    • -
    -

    - - Attribute -
      -
    • readingValueLanguage - Änderung der Sprache der Readings (de,en/wenn nichts gesetzt ist, dann Englisch es sei denn deutsch ist als globale Sprache gesetzt)
    • -
    • model -
    • -
    - - set -
      -
    • winter_mode - aufwäcken (awake)| winterschlaf (hibernate)
    • -
    -
      -

      mäher

      -
    • parkUntilFurtherNotice - Parken des Mähers unter Umgehung des Zeitplans
    • -
    • parkUntilNextTimer - Parken bis zum nächsten Zeitplan
    • -
    • startOverrideTimer - Manuelles mähen (in Minuten, 60 = 1h, 1440 = 24h, 4320 = 72h)
    • -
    • startResumeSchedule - Weiterführung des Zeitplans
    • -
    • startpoint enable|disable 1|2|3 - Aktiviert oder deaktiviert einen vordefinierten Startbereich
    • -
        -
      • set NAME startpoint enable 1
      • -
      • set NAME startpoint disable 3 enable 1
      • -
      -

      irrigation control

      -
    • resumeScheduleValve - Startet Bew&aauml;sserung am Ventil n nach Zeitplan
    • -
    • stopScheduleValve - Setzt Bew&aauml;sserung am Ventil n aus (Default: 2038-01-18T00:00:00.000Z) | Optionaler Parameter Stunden (Jetzt + Stunden)
    • -
    • closeAllValves - Stopt Bew&aauml;sserung an allen Ventilen
    • -

      water control

      -
    • manualButtonTime - setzt die Dauer für den manuellen Knopf (in Minuten) 0 Schaltet den Knopf aus
    • -
    • stopSchedule - Halte Zeitplan an für x Stunden - (Default: 2038-01-18T00:00:00.000Z)
    • -
    • resumeSchedule - Weiterführung des Zeitplans
    • -
    -
- -=end html_DE - -=for :application/json;q=META.json 74_GardenaSmartDevice.pm -{ - "abstract": "Modul to control GardenaSmart Devices", - "x_lang": { - "de": { - "abstract": "Modul zur Steuerung von Gardena Smart Geräten" - } - }, - "keywords": [ - "fhem-mod-device", - "fhem-core", - "Garden", - "Gardena", - "Smart" - ], - "release_status": "stable", - "license": "GPL_2", - "version": "v2.5.5", - "author": [ - "Marko Oldenburg " - ], - "x_fhem_maintainer": [ - "CoolTux" - ], - "x_fhem_maintainer_github": [ - "LeonGaultier" - ], - "prereqs": { - "runtime": { - "requires": { - "FHEM": 5.00918799, - "perl": 5.016, - "Meta": 0, - "JSON": 0, - "Time::Local": 0 - }, - "recommends": { - }, - "suggests": { - } - } - } -} -=end :application/json;q=META.json - -=cut +############################################################################### +# +# Developed with VSCodium and richterger perl plugin. +# +# (c) 2017-2022 Copyright: Marko Oldenburg (fhemdevelopment at cooltux dot net) +# All rights reserved +# +# Special thanks goes to comitters: +# - Michael (mbrak) Thanks for Commandref +# - Matthias (Kenneth) Thanks for Wiki entry +# - BioS Thanks for predefined start points Code +# - fettgu Thanks for Debugging Irrigation Control data flow +# - Sebastian (BOFH) Thanks for new Auth Code after API Change +# +# +# This script 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 +# any later version. +# +# The GNU General Public License can be found at +# http://www.gnu.org/copyleft/gpl.html. +# A copy is found in the textfile GPL.txt and important notices to the license +# from the author is found in LICENSE.txt distributed with these scripts. +# +# This script 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. +# +# +# $Id$ +# +############################################################################### +## +## +## Das JSON Modul immer in einem eval aufrufen +# $data = eval{decode_json($data)}; +# +# if($@){ +# Log3($SELF, 2, "$TYPE ($SELF) - error while request: $@"); +# +# readingsSingleUpdate($hash, "state", "error", 1); +# +# return; +# } +# +# +###### Wichtige Notizen +# +# apt-get install libio-socket-ssl-perl +# http://www.dxsdata.com/de/2016/07/php-class-for-gardena-smart-system-api/ +# +## +## + +## unserer packagename +package FHEM::GardenaSmartDevice; +use GPUtils qw(GP_Import GP_Export); + +use strict; +use warnings; +use POSIX; +use FHEM::Meta; +use Time::Local; +use Time::Piece; +use Time::Seconds; + +# try to use JSON::MaybeXS wrapper +# for chance of better performance + open code +eval { + require JSON::MaybeXS; + import JSON::MaybeXS qw( decode_json encode_json ); + 1; +} or do { + + # try to use JSON wrapper + # for chance of better performance + eval { + # JSON preference order + local $ENV{PERL_JSON_BACKEND} = + 'Cpanel::JSON::XS,JSON::XS,JSON::PP,JSON::backportPP' + unless ( defined( $ENV{PERL_JSON_BACKEND} ) ); + + require JSON; + import JSON qw( decode_json encode_json ); + 1; + } or do { + + # In rare cases, Cpanel::JSON::XS may + # be installed but JSON|JSON::MaybeXS not ... + eval { + require Cpanel::JSON::XS; + import Cpanel::JSON::XS qw(decode_json encode_json); + 1; + } or do { + + # In rare cases, JSON::XS may + # be installed but JSON not ... + eval { + require JSON::XS; + import JSON::XS qw(decode_json encode_json); + 1; + } or do { + + # Fallback to built-in JSON which SHOULD + # be available since 5.014 ... + eval { + require JSON::PP; + import JSON::PP qw(decode_json encode_json); + 1; + } or do { + + # Fallback to JSON::backportPP in really rare cases + require JSON::backportPP; + import JSON::backportPP qw(decode_json encode_json); + 1; + }; + }; + }; + }; +}; + +## Import der FHEM Funktionen +#-- Run before package compilation +BEGIN { + + # Import from main context + GP_Import( + qw(readingsSingleUpdate + readingsBulkUpdate + readingsBulkUpdateIfChanged + readingsBeginUpdate + readingsEndUpdate + Log3 + CommandAttr + AttrVal + ReadingsVal + readingFnAttributes + AssignIoPort + modules + IOWrite + defs + makeDeviceName) + ); +} + +#-- Export to main context with different name +GP_Export( + qw( + Initialize + ) +); + +sub Initialize { + my $hash = shift; + + $hash->{Match} = '^{"id":".*'; + + $hash->{SetFn} = \&Set; + $hash->{DefFn} = \&Define; + $hash->{UndefFn} = \&Undef; + $hash->{ParseFn} = \&Parse; + + $hash->{AttrFn} = \&Attr; + $hash->{AttrList} = + "readingValueLanguage:de,en " + . "model:watering_computer,sensor,sensor2,mower,ic24,power,electronic_pressure_pump " + . "extendedState:0,1 " + . "IODev " + . $readingFnAttributes; + $hash->{parseParams} = 1; + + return FHEM::Meta::InitMod( __FILE__, $hash ); +} + +sub Define { + my $hash = shift // return; + my $aArg = shift // return; + + return $@ unless ( FHEM::Meta::SetInternals($hash) ); + use version 0.60; our $VERSION = FHEM::Meta::Get( $hash, 'version' ); + + return + "too few parameters: define GardenaSmartDevice " + if ( scalar( @{$aArg} ) < 3 ); + + my $name = $aArg->[0]; + my $deviceId = $aArg->[2]; + my $category = $aArg->[3]; + + $hash->{DEVICEID} = $deviceId; + $hash->{VERSION} = version->parse($VERSION)->normal; + $hash->{helper}{STARTINGPOINTID} = ''; + $hash->{helper}{schedules_paused_until_id} = ''; + $hash->{helper}{eco_mode_id} = ''; + $hash->{helper}{button_config_time_id} = ''; + $hash->{helper}{winter_mode_id} = ''; + # Electroni Pressure Pump + $hash->{helper}{operating_mode_id} = ''; + $hash->{helper}{leakage_detection_id} = ''; + $hash->{helper}{turn_on_pressure_id} = ''; + + + $hash->{helper}{_id} = ''; + + # IrrigationControl valve control max 6 + $hash->{helper}{schedules_paused_until_1_id} = ''; + $hash->{helper}{schedules_paused_until_2_id} = ''; + $hash->{helper}{schedules_paused_until_3_id} = ''; + $hash->{helper}{schedules_paused_until_4_id} = ''; + $hash->{helper}{schedules_paused_until_5_id} = ''; + $hash->{helper}{schedules_paused_until_6_id} = ''; + + CommandAttr( undef, + "$name IODev $modules{GardenaSmartBridge}{defptr}{BRIDGE}->{NAME}" ) + if ( AttrVal( $name, 'IODev', 'none' ) eq 'none' ); + + my $iodev = AttrVal( $name, 'IODev', 'none' ); + + AssignIoPort( $hash, $iodev ) if ( !$hash->{IODev} ); + + if ( defined( $hash->{IODev}->{NAME} ) ) { + Log3 $name, 3, "GardenaSmartDevice ($name) - I/O device is " + . $hash->{IODev}->{NAME}; + } + else { + Log3 $name, 1, "GardenaSmartDevice ($name) - no I/O device"; + } + + $iodev = $hash->{IODev}->{NAME}; + + my $d = $modules{GardenaSmartDevice}{defptr}{$deviceId}; + + return +"GardenaSmartDevice device $name on GardenaSmartBridge $iodev already defined." + if ( defined($d) + && $d->{IODev} == $hash->{IODev} + && $d->{NAME} ne $name ); + + CommandAttr( undef, $name . ' room GardenaSmart' ) + if ( AttrVal( $name, 'room', 'none' ) eq 'none' ); + + CommandAttr( undef, $name . ' model ' . $category ) + if ( AttrVal( $name, 'model', 'none' ) eq 'none' ); + + Log3 $name, 3, +"GardenaSmartDevice ($name) - defined GardenaSmartDevice with DEVICEID: $deviceId"; + readingsSingleUpdate( $hash, 'state', 'initialized', 1 ); + + $modules{GardenaSmartDevice}{defptr}{$deviceId} = $hash; + + return; +} + +sub Undef { + my $hash = shift; + my $arg = shift; + + my $name = $hash->{NAME}; + my $deviceId = $hash->{DEVICEID}; + + delete $modules{GardenaSmartDevice}{defptr}{$deviceId}; + + return; +} + +sub Attr { + + my ( $cmd, $name, $attrName, $attrVal ) = @_; + my $hash = $defs{$name}; + + return; +} + +sub Set { + my $hash = shift // return; + my $aArg = shift // return; + + my $name = shift @$aArg; + my $cmd = shift @$aArg + // return qq{"set $name" needs at least one argument}; + + my $payload; + my $abilities; + my $service_id; + my $mainboard_version = + ReadingsVal( $name, 'mower_type-mainboard_version', 0.0 ); + + my ($Sekunden, $Minuten, $Stunden, $Monatstag, $Monat, + $Jahr, $Wochentag, $Jahrestag, $Sommerzeit) = localtime(time); + + my $timezone_offset = $Sommerzeit ? 0 : ( Time::Piece->new )->tzoffset; + + #set default abilitie ... overwrite in cmd to change + $abilities = 'mower' + if ( AttrVal( $name, 'model', 'unknown' ) eq 'mower' ); + $abilities = 'watering' + if ( AttrVal( $name, 'model', 'unknown' ) eq 'ic24' + || AttrVal( $name, 'model', 'unknown' ) eq 'watering_computer' ); + $abilities = 'power' + if ( AttrVal( $name, 'model', 'unknown' ) eq 'power' ); + $abilities = 'watering' + if ( AttrVal( $name, 'model', 'unknown' ) eq 'electronic_pressure_pump' ); + + ### mower + # service_id (eco, parkuntilfurhternotice, startpoints) + if ( lc $cmd eq 'parkuntilfurthernotice' ) { + $payload = '"name":"park_until_further_notice"'; + if ( $mainboard_version > 10.30 ) { + $payload = +' "settings":{"name":"schedules_paused_until","value":"2038-01-18T00:00:00.000Z","device":"' + . $hash->{DEVICEID} . '"}'; + $abilities = 'mower_settings'; + $service_id = $hash->{helper}{schedules_paused_until_id}; + } + } + elsif ( lc $cmd eq 'parkuntilnexttimer' ) { + $payload = '"name":"park_until_next_timer"'; + if ( $mainboard_version > 10.30 ) { + $payload = '"properties":{"name":"mower_timer","value":0}'; + $abilities = 'mower_timer'; + } + } + elsif ( lc $cmd eq 'startresumeschedule' ) { + $payload = '"name":"start_resume_schedule"'; + if ( $mainboard_version > 10.30 ) { + $payload = +' "settings":{"name":"schedules_paused_until","value":"","device":"' + . $hash->{DEVICEID} . '"}'; + $abilities = 'mower_settings'; + $service_id = $hash->{helper}{schedules_paused_until_id}; + } + } + elsif ( lc $cmd eq 'startoverridetimer' ) { + $payload = '"name":"start_override_timer","parameters":{"duration":' + . $aArg->[0] * 60 . '}'; + if ( $mainboard_version > 10.30 ) { + $payload = '"properties":{"name":"mower_timer","value":' + . $aArg->[0] * 60 . '}'; + $abilities = 'mower_timer'; + } + + } + elsif ( lc $cmd eq 'startpoint' ) { + my $err; + ( $err, $payload, $abilities ) = + SetPredefinedStartPoints( $hash, $aArg ); + $service_id = $hash->{helper}{STARTINGPOINTID}; + return $err if ( defined($err) ); + } + elsif ( lc $cmd eq 'eco' ) { + $payload = + '"settings": {"name": "eco_mode", "value": ' + . $aArg->[0] + . ', "device": "' + . $hash->{DEVICEID} . '"}'; + $abilities = 'mower_settings' if ( $mainboard_version > 10.30 ); + $service_id = $hash->{helper}{eco_mode_id}; + +#$abilities['service_id'] = $hash->{helper}{SCHEDULESID} if ( $mainboard_version > 10.30 ); + } + ### electronic_pressure_pump + # elsif ( lc $cmd eq 'pumptimer' ) { + # $payload = + # '"name":"pump_manual_watering_timer","parameters":{"duration":' + # . $aArg->[0] . '}'; + # } + ### watering_computer & electronic pump + elsif ( lc $cmd eq 'manualoverride' ) { + $payload = + '"properties":{"name":"watering_timer_1' + . '","value":{"state":"manual","duration":' + . $aArg->[0] * 60 + . ',"valve_id":1}}'; + } + elsif ( lc $cmd eq 'manualbuttontime' ) { + $service_id = $hash->{helper}{button_config_time_id}; + $payload = + '"properties":{"name":"button_config_time",' + . '"value":' + . $aArg->[0] * 60 + . ',"timestamp":"2021-05-26T19:06:23.680Z"' + . ',"at_bound":null,"unit":"seconds","ability":"' + . $service_id . '"}'; + $abilities = 'watering_button_config'; + } + elsif ( $cmd =~ m{\AcancelOverride}xms ) { + + my $valve_id = 1; + + if ( $cmd =~ m{\AcancelOverrideValve(\d)\z}xms ) { + $valve_id = $1; + } + + $payload = + '"properties":{"name":"watering_timer_' + . $valve_id + . '","value":{"state":"idle","duration":' + . 0 + . ',"valve_id":' + . $valve_id . '}}'; + } + elsif ( $cmd =~ /.*Schedule$/ ) { + my $duration = ( + ( + defined( $aArg->[0] ) + ? ( + ( + ( Time::Piece->new ) + + ( ONE_HOUR * $aArg->[0] ) - + $timezone_offset + )->datetime + ) + . '.000Z' + : '2038-01-18T00:00:00.000Z' + ) + ); + + $abilities = 'wateringcomputer_settings'; + $service_id = $hash->{helper}->{'schedules_paused_until_id'}; + $payload = + '"settings":{"name":"schedules_paused_until"' + . ', "value":"' + . ( $cmd eq 'resumeSchedule' ? '' : $duration ) + . '","device":"' + . $hash->{DEVICEID} . '"}'; + } + elsif ( lc $cmd eq 'on' || lc $cmd eq 'off' || lc $cmd eq 'on-for-timer' ) { + my $val = ( + scalar( !@$aArg == 0 ) && ref($aArg) eq 'ARRAY' + ? $aArg->[0] * 60 + : lc $cmd + ); + + $payload = + '"properties":{"name":"power_timer", "value":"' . $val . '"}'; + } + ### Watering ic24 + elsif ( $cmd =~ m{\AmanualDurationValve\d\z}xms ) { + my $valve_id; + + if ( $cmd =~ m{\AmanualDurationValve(\d)\z}xms ) { + $valve_id = $1; + } + + $payload = + '"properties":{"name":"watering_timer_' + . $valve_id + . '","value":{"state":"manual","duration":' + . $aArg->[0] * 60 + . ',"valve_id":' + . $valve_id . '}}'; + } + elsif ( $cmd eq 'closeAllValves' ) { + $payload = '"name":"close_all_valves","parameters":{}'; + } + elsif ( $cmd =~ /.*ScheduleValve$/ ) { + my $valve_id = $aArg->[0]; + my $duration = ( + ( + defined( $aArg->[1] ) + ? ( + ( + ( Time::Piece->new ) + + ( ONE_HOUR * $aArg->[1] ) - + $timezone_offset + )->datetime + ) + . '.000Z' + : '2038-01-18T00:00:00.000Z' + ) + ); + + $abilities = 'irrigation_settings'; + $service_id = + $hash->{helper}->{ 'schedules_paused_until_' . $valve_id . '_id' }; + $payload = + '"settings":{"name":"schedules_paused_until_' + . $valve_id + . '", "value":"' + . ( $cmd eq 'resumeScheduleValve' ? '' : $duration ) + . '","device":"' + . $hash->{DEVICEID} . '"}'; + } + ### Watering_pressure_pump + elsif ( lc $cmd eq 'operating_mode') { + my $op_mode = $aArg->[0]; + $payload = '"settings":{"name":"operating_mode",' + .'"value":"'.$op_mode.'",' + .'"device":"' + . $hash->{DEVICEID}.'"}'; + $abilities = 'watering_pressure_pump_settings'; + $service_id = $hash->{helper}->{ 'operating_mode_id' }; + } + elsif ( lc $cmd eq 'leakage_detection') { + my $leakdetection_mode = $aArg->[0]; + $payload = '"settings":{"name":"leakage_detection",' + .'"value":"'.$leakdetection_mode.'",' + .'"device":"' + . $hash->{DEVICEID}.'"}'; + $abilities = 'watering_pressure_pump_settings'; + $service_id = $hash->{helper}->{ 'leakage_detection_id' }; + } + elsif ( lc $cmd eq 'turn_on_pressure') { + my $turnonpressure = $aArg->[0]; + $payload = '"settings":{"name":"turn_on_pressure",' + .'"value":"'.$turnonpressure.'",' + .'"device":"' + . $hash->{DEVICEID}.'"}'; + $abilities = 'watering_pressure_pump_settings'; + $service_id = $hash->{helper}->{ 'turn_on_pressure_id' }; + } + elsif ( lc $cmd eq 'resetvalveerrors') { + $payload = '"name":"reset_valve_errors",' + .' "parameters": {}'; + $abilities = 'error'; + } + + ### Sensors + elsif ( lc $cmd eq 'refresh' ) { + + my $sensname = $aArg->[0]; + if ( lc $sensname eq 'temperature' ) { + if ( ReadingsVal( $name, 'device_info-category', 'sensor' ) eq + 'sensor' ) + { + $payload = '"name":"measure_ambient_temperature"'; + $abilities = 'ambient_temperature'; + } + else { + $payload = '"name":"measure_soil_temperature"'; + $abilities = 'soil_temperature'; + } + } + elsif ( lc $sensname eq 'light' ) { + $payload = '"name":"measure_light"'; + $abilities = 'light'; + + } + elsif ( lc $sensname eq 'humidity' ) { + $payload = '"name":"measure_soil_humidity"'; + $abilities = 'humidity'; + } + } + ## winter sleep + elsif ( lc $cmd eq 'winter_mode' ) { + $payload = + '"settings":{"name":"winter_mode","value":"' + . $aArg->[0] + . '","device":"' + . $hash->{DEVICEID} . '"}'; + $abilities = 'winter_settings'; + $service_id = $hash->{helper}->{'winter_mode_id'}; + } + else { + + my $list = ''; + + $list .= +'parkUntilFurtherNotice:noArg parkUntilNextTimer:noArg startResumeSchedule:noArg startOverrideTimer:slider,0,1,240 startpoint' + if ( AttrVal( $name, 'model', 'unknown' ) eq 'mower' ); + + $list .= +'manualOverride:slider,1,1,59 cancelOverride:noArg resumeSchedule:noArg stopSchedule manualButtonTime:slider,0,2,100' + if ( AttrVal( $name, 'model', 'unknown' ) eq 'watering_computer' ); + + + $list .= 'manualOverride:slider,1,1,90 cancelOverride:noArg operating_mode:automatic,scheduled leakage_detection:watering,washing_machine,domestic_water_supply,off turn_on_pressure:slider,2,0.2,3.0,1 resetValveErrors:noArg' + if ( AttrVal( $name, 'model', 'unknown' ) eq 'electronic_pressure_pump' ); + + $list .= +'closeAllValves:noArg stopScheduleValve:select,'.ReadingsVal( $name, 'ic24-valves_connected', '1' ).' resumeScheduleValve:select,'.ReadingsVal( $name, 'ic24-valves_connected', '1' ) + if ( AttrVal( $name, 'model', 'unknown' ) eq 'ic24' ); + + foreach my $valve (split(',', ReadingsVal( $name, 'ic24-valves_connected', '1'))) { + $list .= ' manualDurationValve'.$valve.':slider,1,1,90 ' + if ( AttrVal( $name, 'model', 'unknown' ) eq 'ic24' ); + } + + foreach my $valve (split(',', ReadingsVal( $name, 'ic24-valves_connected', '1'))) { + $list .= ' cancelOverrideValve'.$valve.':noArg ' + if ( AttrVal( $name, 'model', 'unknown' ) eq 'ic24' ); + } + + $list .= 'refresh:temperature,humidity' + if ( AttrVal( $name, 'model', 'unknown' ) =~ /sensor.?/ ); + + # add light for old sensors + $list .= ',light' + if ( AttrVal( $name, 'model', 'unknown' ) eq 'sensor' + && ReadingsVal( $name, 'device_info-category', 'unknown' ) eq + 'sensor' ); + + $list .= 'on:noArg off:noArg on-for-timer:slider,0,1,720' + if ( AttrVal( $name, 'model', 'unknown' ) eq 'power' ); + + # all devices has abilitie to fall a sleep + $list .= ' winter_mode:awake,hibernate'; + return "Unknown argument $cmd, choose one of $list"; + } + + $hash->{helper}{deviceAction} = $payload; + readingsSingleUpdate( $hash, "state", "send command to gardena cloud", 1 ); + + IOWrite( $hash, $payload, $hash->{DEVICEID}, $abilities, $service_id ); + Log3 $name, 4, +"GardenaSmartBridge ($name) - IOWrite: $payload $hash->{DEVICEID} $abilities IODevHash=$hash->{IODev}"; + + return; +} + +sub Parse { + my $io_hash = shift; + my $json = shift; + + my $name = $io_hash->{NAME}; + + my $decode_json = eval { decode_json($json) }; + if ($@) { + Log3 $name, 3, + "GardenaSmartDevice ($name) - JSON error while request: $@"; + } + + Log3 $name, 4, "GardenaSmartDevice ($name) - ParseFn was called"; + Log3 $name, 4, "GardenaSmartDevice ($name) - JSON: $json"; + + if ( defined( $decode_json->{id} ) ) { + + my $deviceId = $decode_json->{id}; + + if ( my $hash = $modules{GardenaSmartDevice}{defptr}{$deviceId} ) { + my $name = $hash->{NAME}; + + WriteReadings( $hash, $decode_json ); + Log3 $name, 4, + "GardenaSmartDevice ($name) - find logical device: $hash->{NAME}"; + + return $hash->{NAME}; + + } + else { + + Log3 $name, 3, + "GardenaSmartDevice ($name) - autocreate new device " + . makeDeviceName( $decode_json->{name} ) + . " with deviceId $decode_json->{id}, model $decode_json->{category}"; + return + "UNDEFINED " + . makeDeviceName( $decode_json->{name} ) + . " GardenaSmartDevice $decode_json->{id} $decode_json->{category}"; + } + } + + return; +} + +sub WriteReadings { + my $hash = shift; + my $decode_json = shift; + + my $name = $hash->{NAME}; + my $abilities = scalar( @{ $decode_json->{abilities} } ); + my $settings = scalar( @{ $decode_json->{settings} } ); + my $scheduled_events = scalar( @{ $decode_json->{scheduled_events} } ); + + readingsBeginUpdate($hash); + + do { + + if ( + ref( $decode_json->{abilities}[$abilities]{properties} ) eq "ARRAY" + && scalar( @{ $decode_json->{abilities}[$abilities]{properties} } ) + > 0 ) + { + for my $propertie ( + @{ $decode_json->{abilities}[$abilities]{properties} } ) + { + if ( + exists( $decode_json->{abilities}[$abilities]{name} ) + && ( $decode_json->{abilities}[$abilities]{name} eq + 'watering' ) + ) + { + + if ( $propertie->{name} eq 'button_config_time' ) { + if ( $hash->{helper}{ $propertie->{name} . '_id' } ne + $decode_json->{abilities}[$abilities]{id} ) + { + $hash->{helper}{ $propertie->{name} . '_id' } = + $decode_json->{abilities}[$abilities]{id}; + } + readingsBulkUpdateIfChanged( + $hash, + 'manualButtonTime', + ( + RigReadingsValue( + $hash, $propertie->{value} / 60 + ) + ) + ); + next; + } + } + + readingsBulkUpdateIfChanged( + $hash, + $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name}, + ($propertie->{value} eq '') ? RigReadingsValue( $hash, 'n/a') : RigReadingsValue( $hash, $propertie->{value} ) + ) + if ( exists( $propertie->{value} ) # defined ignored 'value':null + && $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} ne 'radio-quality' + && $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} ne 'battery-level' + && $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} ne 'internal_temperature-temperature' + && $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} ne 'ambient_temperature-temperature' + && $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} ne 'soil_temperature-temperature' + && $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} ne 'humidity-humidity' + && $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} ne 'light-light' + && ref( $propertie->{value} ) ne "HASH" ); + + readingsBulkUpdateIfChanged( + $hash, + $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name}, + RigReadingsValue( $hash, $propertie->{value} ) + ) + if ( + defined( $propertie->{value} ) + && ( $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} eq 'radio-quality' + || $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} eq 'battery-level' + || $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} eq + 'internal_temperature-temperature' + || $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} eq + 'ambient_temperature-temperature' + || $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} eq 'soil_temperature-temperature' + || $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} eq 'humidity-humidity' + || $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} eq 'light-light' ) + ); + + readingsBulkUpdateIfChanged( + $hash, + $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} + . '_timestamp', + Time::Piece->strptime( + RigReadingsValue( $hash, $propertie->{timestamp} ), + "%Y-%m-%d %H:%M:%S" )->strftime('%s') + + ) + if ( + defined( $propertie->{value} ) + && ( $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} eq 'mower_timer-mower_timer' ) + ); + + readingsBulkUpdateIfChanged( + $hash, + $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name}, + join( ',', @{ $propertie->{value} } ) + ) + if ( defined( $propertie->{value} ) + && $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} eq 'ic24-valves_connected' ); + + readingsBulkUpdateIfChanged( + $hash, + $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name}, + join( ',', @{ $propertie->{value} } ) + ) + if ( defined( $propertie->{value} ) + && $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} eq 'ic24-valves_master_config' ); + + if ( ref( $propertie->{value} ) eq "HASH" ) { + my $sub_state = 0; my $sub_value = 0; + while ( my ( $r, $v ) = each %{ $propertie->{value} } ) { + if ( ref( $v ) ne "HASH" ) { + readingsBulkUpdate( + $hash, + $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} . '_' + . $r, + RigReadingsValue( $hash, $v ) + ); + } else { + while ( my ( $i_r, $i_v ) = each %{ $v } ) { + readingsBulkUpdate( + $hash, + $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} . '_' + . $r . '_' . $i_r, + RigReadingsValue( $hash, $i_v ) + ); + } + } + } + } + # ic24 and other watering devices calc irrigation left in sec + readingsBulkUpdateIfChanged( + $hash, + $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} + . '_irrigation_left', + ( $propertie->{value}{duration} > 0 ) ? (Time::Piece::localtime->strptime( + RigReadingsValue($hash, $propertie->{timestamp}), "%Y-%m-%d %H:%M:%S") + + ($propertie->{value}{duration} + 3 ) - Time::Piece::localtime->new) : 0 + ) + if ( defined( $propertie->{value} ) + && $decode_json->{abilities}[$abilities]{name} eq 'watering' + ); + } + } + + $abilities--; + } while ( $abilities >= 0 ); + + + if ( + exists( $decode_json->{scheduled_events} ) + # && scalar ($decode_json->{scheduled_events} ) > 0 + && ref ($decode_json->{scheduled_events}) eq 'ARRAY' ) { + readingsBulkUpdateIfChanged( $hash, 'scheduling-schedules_events_count', + scalar( @{$decode_json->{scheduled_events} } ) ); + my $valve_id =1; my $event_id = 1; # ic24 [1..6] | wc, pump [1] + + for my $event_schedules ( @{ $decode_json->{scheduled_events} } ) { + $valve_id = $event_schedules->{valve_id} if ( exists($event_schedules->{valve_id} ) ); #ic24 + $event_id++; # event id + + while ( my ( $r, $v ) = each %{ $event_schedules } ) { + readingsBulkUpdateIfChanged( $hash, 'scheduling-schedules_event_' + . $event_id + . '_valve_' + . $valve_id + . '_' + . $r, + $v) if (ref($v) ne 'HASH' ); + readingsBulkUpdateIfChanged( $hash, 'scheduling-schedules_event_' + . $event_id + . '_valve_' + . $valve_id + . '_' + . $v->{type}, + join(',', @ { $v->{weekdays}}) ) if (ref($v) eq 'HASH' ); + }; + }; + + }; # fi scheduled_events + + my $winter_mode; + + do { +#Log3 $name, 1, "Settings pro Device : ".$decode_json->{settings}[$settings]{name}; +#Log3 $name, 1, " - KEIN ARRAY" if ( ref( $decode_json->{settings}[$settings]{value} ) ne "ARRAY"); +#Log3 $name, 1, " - IST ARRAY" if ( ref( $decode_json->{settings}[$settings]{value} ) eq "ARRAY"); + + if ( + exists( $decode_json->{settings}[$settings]{name} ) + && ( $decode_json->{settings}[$settings]{name} =~ + /schedules_paused_until_?\d?$/ + || $decode_json->{settings}[$settings]{name} eq 'eco_mode' + || $decode_json->{settings}[$settings]{name} eq 'winter_mode' + || $decode_json->{settings}[$settings]{name} eq 'operating_mode' + || $decode_json->{settings}[$settings]{name} eq 'leakage_detection' + || $decode_json->{settings}[$settings]{name} eq 'turn_on_pressure' ) + ) + { + if ( $hash->{helper} + { $decode_json->{settings}[$settings]{name} . '_id' } ne + $decode_json->{settings}[$settings]{id} ) + { + $hash->{helper} + { $decode_json->{settings}[$settings]{name} . '_id' } = + $decode_json->{settings}[$settings]{id}; + } + # check watering controler single schedules pause until + if ( $decode_json->{settings}[$settings]{name} eq 'schedules_paused_until' ) { + readingsBulkUpdateIfChanged( $hash, 'scheduling-schedules_paused_until', + $decode_json->{settings}[$settings]{value} ); + } + ##### + #ic24 schedules pause until + if ($decode_json->{settings}[$settings]{name} =~ /schedules_paused_until_?(\d)?$/) { + #my $ventil = substr($decode_json->{settings}[$settings]{name}, -1); # => 1 - 6 + # check if empty, clear scheduling-scheduled_watering_next_start_x + readingsBulkUpdateIfChanged( $hash, 'scheduling-'.$decode_json->{settings}[$settings]{name}, + $decode_json->{settings}[$settings]{value} ); + # CommandAttr( undef, $name . " scheduling-scheduled_watering_next_start_") if ($decode_json->{settings}[$settings]{value} eq '' ) + } + + # save electronid pressure pump settings as readings + if ( $decode_json->{settings}[$settings]{name} eq 'operating_mode' + || $decode_json->{settings}[$settings]{name} eq 'leakage_detection' + || $decode_json->{settings}[$settings]{name} eq 'turn_on_pressure' ) { + readingsBulkUpdateIfChanged( $hash, $decode_json->{settings}[$settings]{name}, + $decode_json->{settings}[$settings]{value} ); + + } + # save winter mode as reading + if ( $decode_json->{settings}[$settings]{name} eq 'winter_mode' ) { + readingsBulkUpdateIfChanged( $hash, 'winter_mode', + $decode_json->{settings}[$settings]{value} ); + + $winter_mode = $decode_json->{settings}[$settings]{value}; + } + } + + if ( defined( $decode_json->{settings}[$settings]{name} ) + && $decode_json->{settings}[$settings]{name} eq 'valve_names' + && ref( $decode_json->{settings}[$settings]{value} ) eq "ARRAY" ) { # or HASH ? + my @valves = @{$decode_json->{settings}[$settings]{value}}; + foreach my $valve( @valves ) { + Log3 $name, 4, "GardenaSmartDevice ($name) valve_name $valve->{'name'}"; + readingsBulkUpdateIfChanged( $hash, 'valve-valve_name_'.$valve->{"id"}, + $valve->{"name"} ); + } + } + + if ( ref( $decode_json->{settings}[$settings]{value} ) eq "ARRAY" + && $decode_json->{settings}[$settings]{name} eq 'starting_points' ) + { + #save the startingpointid needed to update the startingpoints + if ( $hash->{helper}{STARTINGPOINTID} ne + $decode_json->{settings}[$settings]{id} ) + { + $hash->{helper}{STARTINGPOINTID} = + $decode_json->{settings}[$settings]{id}; + } + + $hash->{helper}{STARTINGPOINTS} = + '{ "name": "starting_points", "value": ' + . encode_json( $decode_json->{settings}[$settings]{value} ) . '}'; + my $startpoint_cnt = 0; + + for my $startingpoint ( + @{ $decode_json->{settings}[$settings]{value} } ) + { + $startpoint_cnt++; + readingsBulkUpdateIfChanged( + $hash, + 'startpoint-' . $startpoint_cnt . '-enabled', + $startingpoint->{enabled} + ); + } + } + + $settings--; + } while ( $settings >= 0 ); + + if ( $winter_mode ne 'hibernate' ) { + setState($hash); + } + else { + readingsBulkUpdate( $hash, 'state', + RigReadingsValue( $hash, 'hibernate' ) ); + } + + readingsEndUpdate( $hash, 1 ); + + Log3 $name, 4, "GardenaSmartDevice ($name) - readings was written"; + + return; +} + +sub setState { + my $hash = shift; + my $name = $hash->{NAME}; + + my $online_state = + ReadingsVal( $name, 'device_info-connection_status', 'unknown' ); + + #online state mower + readingsBulkUpdate( $hash, 'state', + $online_state eq 'online' + ? ReadingsVal( $name, 'mower-status', 'readingsValError' ) + : 'offline' ) + if ( AttrVal( $name, 'model', 'unknown' ) eq 'mower' ); + + # ic24 / wc / electronic pump + + if ( AttrVal( $name, 'model', 'unknown' ) eq 'ic24' + || AttrVal( $name, 'model', 'unknown' ) eq 'watering_computer' + || AttrVal( $name, 'model', 'unknown' ) eq 'electronic_pressure_pump' ){ + my @opened_valves; + my $state_string = ''; my $nearst_irrigation = '2999-12-12 12:00'; + my $has_schedule = 0; my $longest_duration = 0; my $processed_item = ''; + my $error_type = 'ok'; + my @valves_connected = AttrVal( $name, 'model', 'unknown' ) eq 'ic24' ? split(',', ReadingsVal( $name, 'ic24-valves_connected', '')) : '1'; + + $has_schedule = 1 if ( ReadingsVal($name, 'scheduling-schedules_events_count', '') ne '' ); + for (@valves_connected){ # valves 1 or 1..6 + ## add to opened ventils, if watering active + push @opened_valves, $_ if ( ( ( ReadingsVal( $name, "watering-watering_timer_".$_."_duration", 0 ) =~ m{\A[1-9]([0-9]+)?\z}xms ) ? $_ : 0 ) > 0 ); + ## set error type (pumpe required) + $error_type = ReadingsVal( $name, 'error-valve_error_'.$_.'_type', 'ok' ) if (ReadingsVal( $name, 'error-valve_error_'.$_.'_type', 'ok' ) ne 'ok'); + ## find longest irrigation duration + $longest_duration = ReadingsVal( $name, "watering-watering_timer_".$_."_irrigation_left", 0 ) if ( + ( ReadingsVal( $name, "watering-watering_timer_".$_."_duration", 0 ) =~ m{\A[1-9]([0-9]+)?\z}xms + && ReadingsVal( $name, "watering-watering_timer_".$_."_duration", 0 ) > 0 + && ReadingsVal( $name, "watering-watering_timer_".$_."_duration", 0 ) > $longest_duration ) ); + + # y-m-d h:m + $processed_item = AttrVal( $name, 'model', 'unknown' ) eq 'ic24' + ? RigReadingsValue($hash, ReadingsVal($name, 'scheduling-schedules_paused_until_'.$_, '')) + : RigReadingsValue($hash, ReadingsVal($name, 'scheduling-schedules_paused_until', '')); + + Log3 $name, 5, "[DEBUG] - process: $processed_item"; + Log3 $name, 5, "[DEBUG] - next_start: ". ReadingsVal($name, 'scheduling-scheduled_watering_next_start', ''); # n/a RigReadingsValue( $hash, 'n/a') + # $nearst_irrigation = RigReadingsValue($hash, ReadingsVal($name, 'scheduling-schedules_paused_until_'.$_, '')) + if ( ReadingsVal($name, 'scheduling-scheduled_watering_next_start', '') eq RigReadingsValue( $hash, 'n/a') ) { # non next start, schedules paused permanently or next schedule > 1 year; get nearst paused_until + Log3 $name, 5, "[DEBUG] - next_start: empty "; + Log3 $name, 5, "[DEBUG] - empty pro item ".Time::Piece->strptime( $processed_item, "%Y-%m-%d %H:%M:%S"); + Log3 $name, 5, "[DEBUG] - empty nearst ".Time::Piece->strptime( $nearst_irrigation, "%Y-%m-%d %H:%M:%S"); + $nearst_irrigation = $processed_item + if ( Time::Piece->strptime( $processed_item, "%Y-%m-%d %H:%M:%S") + < Time::Piece->strptime( $nearst_irrigation, "%Y-%m-%d %H:%M:%S") + && $has_schedule + && Time::Piece->strptime( $processed_item, "%Y-%m-%d %H:%M:%S") + > Time::Piece->new + ) + } else { + $nearst_irrigation = ReadingsVal($name, 'scheduling-scheduled_watering_next_start', ''); + } + Log3 $name, 5, "[DEBUG] - choosed nearst: $nearst_irrigation"; + + } # for + # override state 4 extendedstates + if ( AttrVal( $name, "extendedState", 0 ) == 1) { + if (scalar(@opened_valves) > 0){ + ## valve 1 will be ir.. 23 minutes remaining + for (@valves_connected){ + $state_string .= sprintf(RigReadingsValue($hash,'valve').' '.$_.' '.(RigReadingsValue($hash, 'will be irrigated %.f minutes remaining.') .'
'), (ReadingsVal( $name, 'watering-watering_timer_'.$_.'_duration', 0 )/60)); + } # /for + } else { + $state_string .= RigReadingsValue($hash, 'closed'); + } + $state_string .= ($has_schedule) ? sprintf( RigReadingsValue($hash, 'next watering: %s'), RigReadingsValue($hash, ReadingsVal($name, 'scheduling-scheduled_watering_next_start', ''))) : sprintf( RigReadingsValue($hash, 'paused until %s') , $nearst_irrigation); + #TODO: Write state format for ventil 1-@valces_connected -> map ? + CommandAttr( undef, $name . ' stateFormat + { + + } + ' ) + if ( AttrVal( $name, 'stateFormat', 'none' ) eq 'none' ); + } else { + Log3 $name, 5, "[DEBUG] - Offene Ventile :".scalar(@opened_valves)." laengste bewaesserung: $longest_duration . hat Zeitplan: $has_schedule Naechster Zeitplan: $nearst_irrigation"; + $state_string = scalar(@opened_valves) > 0 + # offen + ? sprintf( (RigReadingsValue($hash, 'will be irrigated %.f minutes remaining.')), $longest_duration/60) + # zu + : + ( $has_schedule + && $nearst_irrigation ne '2999-12-12 12:00') + # zeitplan aktiv + # ? ( $nearst_irrigation eq '2038-01-18 00:00') sprintf( RigReadingsValue($hash, 'paused until %s') , $nearst_irrigation) + ? ( $nearst_irrigation eq RigReadingsValue( $hash, 'n/a') || $nearst_irrigation =~ '2038-01-18.*') + # dauerhaft pausiert + ? sprintf( (RigReadingsValue($hash, 'closed') .'. '.RigReadingsValue($hash , 'schedule permanently paused')) ) + # naechster zeutplan + : (ReadingsVal($name, 'scheduling-scheduled_watering_next_start', '') eq RigReadingsValue($hash, 'n/a')) + ? sprintf( RigReadingsValue($hash, 'paused until %s') , $nearst_irrigation) + : sprintf( (RigReadingsValue($hash, 'closed') .'. '.RigReadingsValue($hash, 'next watering: %s')), $nearst_irrigation ) + # zeitplan pausiert + : RigReadingsValue($hash, 'closed') + ; + # state offline | override + $state_string = 'offline' if ($online_state eq 'offline'); + $state_string = ( $error_type ne 'ok' ) ? $error_type : $state_string; + + } + readingsBulkUpdate( + $hash, 'state', RigReadingsValue( $hash, $state_string ) ); + } + + # Sensor / Sensor 2 + if ( AttrVal( $name, 'model', 'unknown' ) =~ /sensor.?/ ) { + my $state_string = + ( ReadingsVal( $name, 'device_info-category', 'unknown' ) eq + 'sensor' ) + ? 'T: ' + . ReadingsVal( $name, 'ambient_temperature-temperature', + 'readingsValError' ) + . '°C, ' + : 'T: ' + . ReadingsVal( $name, 'soil_temperature-temperature', + 'readingsValError' ) + . '°C, '; + $state_string .= 'H: ' + . ReadingsVal( $name, 'humidity-humidity', 'readingsValError' ) . '%'; + $state_string .= ', L: ' + . ReadingsVal( $name, 'light-light', 'readingsValError' ) . 'lux' + if ( ReadingsVal( $name, 'device_info-category', 'unknown' ) eq + 'sensor' ); + +# if ( $online_state eq 'offline') { +# readingsBulkUpdate( $hash, 'humidity-humidity', '-1' ); +# readingsBulkUpdate( $hash, 'ambient_temperature-temperature', '-1' ) if (ReadingsVal($name, 'device_info-category', 'unknown') eq 'sensor'); +# readingsBulkUpdate( $hash, 'light-light', '-1' ) if (ReadingsVal($name, 'device_info-category', 'unknown') eq 'sensor'); +# } + #online state sensor I II + readingsBulkUpdate( $hash, 'state', + $online_state eq 'online' ? RigReadingsValue( $hash, $state_string) : RigReadingsValue( $hash, 'offline') ); + } + + readingsBulkUpdate( $hash, 'state', + ReadingsVal( $name, 'power-power_timer', 'no info from power-timer' ) ) + if ( AttrVal( $name, 'model', 'unknown' ) eq 'power' ); + + return; +} + +################################## +################################## +#### my little helpers ########### + +sub ReadingLangGerman { + my $hash = shift; + my $readingValue = shift; + + my $name = $hash->{NAME}; + my %langGermanMapp = ( + 'ok_cutting' => 'mähen', + 'paused' => 'pausiert', + 'ok_searching' => 'suche Ladestation', + 'ok_charging' => 'lädt', + 'ok_leaving' => 'unterwegs zum Startpunkt', + 'wait_updating' => 'wird aktualisiert ...', + 'wait_power_up' => 'wird eingeschaltet ...', + 'parked_timer' => 'geparkt nach Zeitplan', + 'parked_park_selected' => 'geparkt', + 'off_disabled' => 'der Mäher ist ausgeschaltet', + 'off_hatch_open' => 'deaktiviert. Abdeckung ist offen oder PIN-Code erforderlich', + 'unknown' => 'unbekannter Status', + 'error' => 'Fehler', + 'error_at_power_up' => 'Neustart ...', + 'off_hatch_closed' => 'Deaktiviert. Manueller Start erforderlich', + 'ok_cutting_timer_overridden' => 'manuelles mähen', + 'parked_autotimer' => 'geparkt durch SensorControl', + 'parked_daily_limit_reached' => 'abgeschlossen', + 'no_message' => 'kein Fehler', + 'outside_working_area' => 'außerhalb des Arbeitsbereichs', + 'no_loop_signal' => 'kein Schleifensignal', + 'wrong_loop_signal' => 'falsches Schleifensignal', + 'loop_sensor_problem_front' => 'Problem Schleifensensor, vorne', + 'loop_sensor_problem_rear' => 'Problem Schleifensensor, hinten', + 'trapped' => 'eingeschlossen', + 'upside_down' => 'steht auf dem Kopf', + 'low_battery' => 'niedriger Batteriestand', + 'empty_battery' => 'Batterie leer', + 'no_drive' => 'fährt nicht', + 'lifted' => 'angehoben', + 'stuck_in_charging_station' => 'eingeklemmt in Ladestation', + 'charging_station_blocked' => 'Ladestation blockiert', + 'collision_sensor_problem_rear' => 'Problem Stoßsensor hinten', + 'collision_sensor_problem_front' => 'Problem Stoßsensor vorne', + 'wheel_motor_blocked_right' => 'Radmotor rechts blockiert', + 'wheel_motor_blocked_left' => 'Radmotor links blockiert', + 'wheel_drive_problem_right' => 'Problem Antrieb, rechts', + 'wheel_drive_problem_left' => 'Problem Antrieb, links', + 'cutting_system_blocked' => 'Schneidsystem blockiert', + 'invalid_sub_device_combination' => 'fehlerhafte Verbindung', + 'settings_restored' => 'Standardeinstellungen', + 'electronic_problem' => 'elektronisches Problem', + 'charging_system_problem' => 'Problem Ladesystem', + 'tilt_sensor_problem' => 'Kippsensor Problem', + 'wheel_motor_overloaded_right' => 'rechter Radmotor überlastet', + 'wheel_motor_overloaded_left' => 'linker Radmotor überlastet', + 'charging_current_too_high' => 'Ladestrom zu hoch', + 'temporary_problem' => 'vorübergehendes Problem', + 'guide_1_not_found' => 'SK 1 nicht gefunden', + 'guide_2_not_found' => 'SK 2 nicht gefunden', + 'guide_3_not_found' => 'SK 3 nicht gefunden', + 'difficult_finding_home' => 'Problem die Ladestation zu finden', + 'guide_calibration_accomplished' => 'Kalibrierung des Suchkabels beendet', + 'guide_calibration_failed' => 'Kalibrierung des Suchkabels fehlgeschlagen', + 'temporary_battery_problem' => 'kurzzeitiges Batterieproblem', + 'battery_problem' => 'Batterieproblem', + 'alarm_mower_switched_off' => 'Alarm! Mäher ausgeschalten', + 'alarm_mower_stopped' => 'Alarm! Mäher gestoppt', + 'alarm_mower_lifted' => 'Alarm! Mäher angehoben', + 'alarm_mower_tilted' => 'Alarm! Mäher gekippt', + 'connection_changed' => 'Verbindung geändert', + 'connection_not_changed' => 'Verbindung nicht geändert', + 'com_board_not_available' => 'COM Board nicht verfügbar', + 'slipped' => 'rutscht', + 'out_of_operation' => 'ausser Betrieb', + 'replace_now' => 'kritischer Batteriestand, wechseln Sie jetzt', + 'low' => 'niedrig', + 'ok' => 'ok', + 'no_source' => 'ok', + 'mower_charging' => 'Mäher wurde geladen', + 'completed_cutting_autotimer' => 'Sensor Control erreicht', + 'week_timer' => 'Wochentimer erreicht', + 'countdown_timer' => 'Stoppuhr Timer', + 'undefined' => 'unklar', + 'unknown' => 'unklar', + 'status_device_unreachable' => 'Gerät ist nicht in Reichweite', + 'status_device_alive' => 'Gerät ist in Reichweite', + 'bad' => 'schlecht', + 'poor' => 'schwach', + 'good' => 'gut', + 'undefined' => 'unklar', + 'idle' => 'nichts zu tun', + 'firmware_cancel' => 'Firmwareupload unterbrochen', + 'firmware_upload' => 'Firmwareupload', + 'unsupported' => 'nicht unterstützt', + 'up_to_date' => 'auf dem neusten Stand', + 'mower' => 'Mäher', + 'watering_computer' => 'Bewässerungscomputer', + 'no_frost' => 'kein Frost', + 'open' => 'offen', + 'closed' => 'geschlossen', + 'included' => 'inbegriffen', + 'active' => 'aktiv', + 'inactive' => 'nicht aktiv', + 'hibernate' => 'Winterschlaf', + 'awake' => 'Aufgewacht', + 'schedule permanently paused' => 'Zeitplan dauerhaft pausiert', + 'paused until %s' => 'pausiert bis %s', + 'will be irrigated %.f minutes remaining.'=> 'Wird bewässert. %.f Minuten verbleibend.', + 'next watering: %s' => 'Nächste Bewässerung: %s', + 'n/a' => 'nicht verfügbar', + 'pump_not_filled' => 'Pumpe nicht gefüllt', + ); + + if ( + defined( $langGermanMapp{$readingValue} ) + && ( AttrVal( 'global', 'language', 'none' ) eq 'DE' + || AttrVal( $name, 'readingValueLanguage', 'none' ) eq 'de' ) + && AttrVal( $name, 'readingValueLanguage', 'none' ) ne 'en' + ) + { + return $langGermanMapp{$readingValue}; + } + else { + return $readingValue; + } + + return; +} + +sub RigReadingsValue { + my $hash = shift; + my $readingValue = shift; + + my $rigReadingValue; + + if ( $readingValue =~ /^(\d+)-(\d\d)-(\d\d)T(\d\d)/ ) { + $rigReadingValue = Zulu2LocalString($readingValue); + } + else { + $rigReadingValue = ReadingLangGerman( $hash, $readingValue ); + } + + return $rigReadingValue; +} + +sub Zulu2LocalString { + my $t = shift; + + my ( $datehour, $datemin, $rest ) = split( /:/, $t, 3 ); + + my ( $year, $month, $day, $hour, $min ) = + $datehour =~ /(\d+)-(\d\d)-(\d\d)T(\d\d)/; + my $epoch = timegm( 0, 0, $hour, $day, $month - 1, $year ); + + my ( $lyear, $lmonth, $lday, $lhour, $isdst ) = + ( localtime($epoch) )[ 5, 4, 3, 2, -1 ]; + + $lyear += 1900; # year is 1900 based + $lmonth++; # month number is zero based + + if ( defined($rest) ) { + return ( + sprintf( + "%04d-%02d-%02d %02d:%02d:%s", + $lyear, $lmonth, $lday, + $lhour, $datemin, substr( $rest, 0, 2 ) + ) + ); + } + elsif ( $lyear < 2000 ) { + return 'temporarily unavailable'; + } + else { + return ( + sprintf( + "%04d-%02d-%02d %02d:%02d", + $lyear, $lmonth, $lday, $lhour, substr( $datemin, 0, 2 ) + ) + ); + } + + return; +} + +sub SetPredefinedStartPoints { + my $hash = shift; + my $aArg = shift; + + my ( $startpoint_state, $startpoint_num, @morestartpoints ) = @{$aArg}; + + my $name = $hash->{NAME}; + my $payload; + my $abilities; + + if ( defined($startpoint_state) && defined($startpoint_num) ) { + if ( defined( $hash->{helper}{STARTINGPOINTS} ) + && $hash->{helper}{STARTINGPOINTS} ne '' ) + { +# add needed parameters to saved settings config and change the value in request + my $decode_json_settings = + eval { decode_json( $hash->{helper}{STARTINGPOINTS} ) }; + if ($@) { + Log3 $name, 3, +"GardenaSmartBridge ($name) - JSON error while setting startpoint: $@"; + } + + $decode_json_settings->{device} = $hash->{DEVICEID}; + my $setval = $startpoint_state eq 'disable' ? \0 : \1; + $decode_json_settings->{value}[ $startpoint_num - 1 ]{enabled} = + $setval; + + #set more startpoints + if ( + defined scalar(@morestartpoints) + && ( scalar(@morestartpoints) == 2 + || scalar(@morestartpoints) == 4 ) + ) + { + if ( scalar(@morestartpoints) == 2 ) { + $setval = $morestartpoints[0] eq 'disable' ? \0 : \1; + $decode_json_settings->{value}[ $morestartpoints[1] - 1 ] + {enabled} = $setval; + + } + elsif ( scalar(@morestartpoints) == 4 ) { + $setval = $morestartpoints[0] eq 'disable' ? \0 : \1; + $decode_json_settings->{value}[ $morestartpoints[1] - 1 ] + {enabled} = $setval; + $setval = $morestartpoints[2] eq 'disable' ? \0 : \1; + $decode_json_settings->{value}[ $morestartpoints[3] - 1 ] + {enabled} = $setval; + } + } + + $payload = '"settings": ' . encode_json($decode_json_settings); + $abilities = 'mower_settings'; + + #$abilities['service_id'] = $hash->{helper}{STARTINGPOINTID}; + } + else { + return + "startingpoints not loaded yet, please wait a couple of minutes", + undef, undef; + } + } + else { + return + "startpoint usage: set " + . $hash->{NAME} + . " startpoint disable 1 [enable 2] [disable 3]", undef, undef; + } + + return undef, $payload, $abilities; +} + +1; + +=pod + +=item device +=item summary Modul to control GardenaSmart Devices +=item summary_DE Modul zur Steuerung von GardenaSmartgeräten + +=begin html + + +

GardenaSmartDevice

+
    + In combination with GardenaSmartBridge this FHEM Module controls the GardenaSmart Device using the GardenaCloud +

    + Once the Bridge device is created, the connected devices are automatically recognized and created in FHEM.
    + From now on the devices can be controlled and changes in the GardenaAPP are synchronized with the state and readings of the devices. + +


    + Readings +
      +
    • battery-charging - Indicator if the Battery is charged (0/1) or with newer Firmware (false/true)
    • +
    • battery-level - load percentage of the Battery
    • +
    • battery-rechargeable_battery_status - healthyness of the battery (out_of_operation/replace_now/low/ok)
    • +
    • device_info-category - category of device (mower/watering_computer)
    • +
    • device_info-last_time_online - timestamp of last radio contact
    • +
    • device_info-manufacturer - manufacturer
    • +
    • device_info-product - product type
    • +
    • device_info-serial_number - serial number
    • +
    • device_info-sgtin -
    • +
    • device_info-version - firmware version
    • +
    • firmware-firmware_command - firmware command (idle/firmware_cancel/firmware_upload/unsupported)
    • +
    • firmware-firmware_status - firmware status
    • +
    • firmware-firmware_update_start - indicator when a firmwareupload is started
    • +
    • firmware-firmware_upload_progress - progress indicator of firmware update
    • +
    • firmware-inclusion_status - inclusion status
    • +
    • internal_temperature-temperature - internal device temperature
    • +
    • mower-error - actual error message +
        +
      • no_message
      • +
      • outside_working_area
      • +
      • no_loop_signal
      • +
      • wrong_loop_signal
      • +
      • loop_sensor_problem_front
      • +
      • loop_sensor_problem_rear
      • +
      • trapped
      • +
      • upside_down
      • +
      • low_battery
      • +
      • empty_battery
      • +
      • no_drive
      • +
      • lifted
      • +
      • stuck_in_charging_station
      • +
      • charging_station_blocked
      • +
      • collision_sensor_problem_rear
      • +
      • collision_sensor_problem_front
      • +
      • wheel_motor_blocked_right
      • +
      • wheel_motor_blocked_left
      • +
      • wheel_drive_problem_right
      • +
      • wheel_drive_problem_left
      • +
      • cutting_system_blocked
      • +
      • invalid_sub_device_combination
      • +
      • settings_restored
      • +
      • electronic_problem
      • +
      • charging_system_problem
      • +
      • tilt_sensor_problem
      • +
      • wheel_motor_overloaded_right
      • +
      • wheel_motor_overloaded_left
      • +
      • charging_current_too_high
      • +
      • temporary_problem
      • +
      • guide_1_not_found
      • +
      • guide_2_not_found
      • +
      • guide_3_not_found
      • +
      • difficult_finding_home
      • +
      • guide_calibration_accomplished
      • +
      • guide_calibration_failed
      • +
      • temporary_battery_problem
      • +
      • battery_problem
      • +
      • alarm_mower_switched_off
      • +
      • alarm_mower_stopped
      • +
      • alarm_mower_lifted
      • +
      • alarm_mower_tilted
      • +
      • connection_changed
      • +
      • connection_not_changed
      • +
      • com_board_not_available
      • +
      • slipped
      • +
      +
    • +
    • mower-manual_operation - (0/1) or with newer Firmware (false/true)
    • +
    • mower-override_end_time - manual override end time
    • +
    • mower-source_for_next_start - source for the next start +
        +
      • no_source
      • +
      • mower_charging
      • +
      • completed_cutting_autotimer
      • +
      • week_timer
      • +
      • countdown_timer
      • +
      • undefined
      • +
      +
    • +
    • mower-status - mower state (see state)
    • +
    • mower-timestamp_next_start - timestamp of next scheduled start
    • +
    • radio-connection_status - state of connection
    • +
    • radio-quality - percentage of the radio quality
    • +
    • radio-state - radio state (bad/poor/good/undefined)
    • +
    • state - state of the mower +
        +
      • paused
      • +
      • ok_cutting
      • +
      • ok_searching
      • +
      • ok_charging
      • +
      • ok_leaving
      • +
      • wait_updating
      • +
      • wait_power_up
      • +
      • parked_timer
      • +
      • parked_park_selected
      • +
      • off_disabled
      • +
      • off_hatch_open
      • +
      • unknown
      • +
      • error
      • +
      • error_at_power_up
      • +
      • off_hatch_closed
      • +
      • ok_cutting_timer_overridden
      • +
      • parked_autotimer
      • +
      • parked_daily_limit_reached
      • +
      +
    • +
    +

    + + Attributes +
      +
    • readingValueLanguage - Change the Language of Readings (de,en/if not set the default is english and the global language is not set at german)
    • +
    • model -
    • +
    +

    + + set +
      +
    • winter_mode - awake | hibernate
    • +
    +
      +

      mower

      +
    • parkUntilFurtherNotice
    • +
    • parkUntilNextTimer
    • +
    • startOverrideTimer - (in minutes, 60 = 1h, 1440 = 24h, 4320 = 72h)
    • +
    • startResumeSchedule
    • +
    • startpoint enable|disable 1|2|3 - enables or disables one or more predefined start points
    • +
        +
      • set NAME startpoint enable 1
      • +
      • set NAME startpoint disable 3 enable 1
      • +
      +

      irrigation control

      +
    • resumeScheduleValve - start schedule irrigation on valve n
    • +
    • stopScheduleValve - stop schedule irrigation on valve n (Default: 2038-01-18T00:00:00.000Z) | optional params hours (now + hours)
    • +
    • closeAllValves - close all valves
    • +

      water control

      +
    • manualButtonTime - set manual time for button press (in minutes) 0 disable button
    • +
    • stopSchedule - stop schedule for now + n hours (Default: 2038-01-18T00:00:00.000Z)
    • +
    • resumeSchedule - resume schedule
    • +
    +
+ +=end html +=begin html_DE + + +

GardenaSmartDevice

+
    + Zusammen mit dem Device GardenaSmartDevice stellt dieses FHEM Modul die Kommunikation zwischen der GardenaCloud und Fhem her. +

    + Wenn das GardenaSmartBridge Device erzeugt wurde, werden verbundene Geräte automatisch erkannt und in Fhem angelegt.
    + Von nun an können die eingebundenen Geräte gesteuert werden. Änderungen in der APP werden mit den Readings und dem Status syncronisiert. + +
+
+
    + Readings +
      +
    • battery-charging - Ladeindikator (0/1) oder mit neuerer Firmware (false/true)
    • +
    • battery-level - Ladezustand der Batterie in Prozent
    • +
    • battery-rechargeable_battery_status - Zustand der Batterie (Ausser Betrieb/Kritischer Batteriestand, wechseln Sie jetzt/Niedrig/oK)
    • +
    • device_info-category - Eigenschaft des Gerätes (Mäher/Bewässerungscomputer/Bodensensor)
    • +
    • device_info-last_time_online - Zeitpunkt der letzten Funkübertragung
    • +
    • device_info-manufacturer - Hersteller
    • +
    • device_info-product - Produkttyp
    • +
    • device_info-serial_number - Seriennummer
    • +
    • device_info-sgtin -
    • +
    • device_info-version - Firmware Version
    • +
    • firmware-firmware_command - Firmware Kommando (Nichts zu tun/Firmwareupload unterbrochen/Firmwareupload/nicht unterstützt)
    • +
    • firmware-firmware_status - Firmware Status
    • +
    • firmware-firmware_update_start - Firmwareupdate (0/1) oder mit neuerer Firmware (false/true)
    • +
    • firmware-firmware_upload_progress - Firmwareupdatestatus in Prozent
    • +
    • firmware-inclusion_status - Einbindungsstatus
    • +
    • internal_temperature-temperature - Interne Geräte Temperatur
    • +
    • mower-error - Aktuelle Fehler Meldung +
        +
      • Kein Fehler
      • +
      • Außerhalb des Arbeitsbereichs
      • +
      • Kein Schleifensignal
      • +
      • Falsches Schleifensignal
      • +
      • Problem Schleifensensor, vorne
      • +
      • Problem Schleifensensor, hinten
      • +
      • Eingeschlossen
      • +
      • Steht auf dem Kopf
      • +
      • Niedriger Batteriestand
      • +
      • Batterie ist leer
      • +
      • Kein Antrieb
      • +
      • Angehoben
      • +
      • Eingeklemmt in Ladestation
      • +
      • Ladestation blockiert
      • +
      • Problem Stoßsensor hinten
      • +
      • Problem Stoßsensor vorne
      • +
      • Radmotor rechts blockiert
      • +
      • Radmotor links blockiert
      • +
      • Problem Antrieb, rechts
      • +
      • Problem Antrieb, links
      • +
      • Schneidsystem blockiert
      • +
      • Fehlerhafte Verbindung
      • +
      • Standardeinstellungen
      • +
      • Elektronisches Problem
      • +
      • Problem Ladesystem
      • +
      • Kippsensorproblem
      • +
      • Rechter Radmotor überlastet
      • +
      • Linker Radmotor überlastet
      • +
      • Ladestrom zu hoch
      • +
      • Vorübergehendes Problem
      • +
      • SK 1 nicht gefunden
      • +
      • SK 2 nicht gefunden
      • +
      • SK 3 nicht gefunden
      • +
      • Problem die Ladestation zu finden
      • +
      • Kalibration des Suchkabels beendet
      • +
      • Kalibration des Suchkabels fehlgeschlagen
      • +
      • Kurzzeitiges Batterieproblem
      • +
      • Batterieproblem
      • +
      • Alarm! Mäher ausgeschalten
      • +
      • Alarm! Mäher gestoppt
      • +
      • Alarm! Mäher angehoben
      • +
      • Alarm! Mäher gekippt
      • +
      • Verbindung geändert
      • +
      • Verbindung nicht geändert
      • +
      • COM board nicht verfügbar
      • +
      • Rutscht
      • +
      +
    • +
    • mower-manual_operation - Manueller Betrieb (0/1) oder mit neuerer Firmware (false/true)
    • +
    • mower-override_end_time - Zeitpunkt wann der manuelle Betrieb beendet ist
    • +
    • mower-source_for_next_start - Grund für den nächsten Start +
        +
      • Kein Grund
      • +
      • Mäher wurde geladen
      • +
      • SensorControl erreicht
      • +
      • Wochentimer erreicht
      • +
      • Stoppuhr Timer
      • +
      • Undefiniert
      • +
      +
    • +
    • mower-status - Mäher Status (siehe state)
    • +
    • mower-timestamp_next_start - Zeitpunkt des nächsten geplanten Starts
    • +
    • radio-connection_status - Status der Funkverbindung
    • +
    • radio-quality - Indikator für die Funkverbindung in Prozent
    • +
    • radio-state - radio state (schlecht/schwach/gut/Undefiniert)
    • +
    • state - Staus des Mähers +
        +
      • Pausiert
      • +
      • Mähen
      • +
      • Suche Ladestation
      • +
      • Lädt
      • +
      • Mähen
      • +
      • Wird aktualisiert ...
      • +
      • Wird eingeschaltet ...
      • +
      • Geparkt nach Zeitplan
      • +
      • Geparkt
      • +
      • Der Mäher ist ausgeschaltet
      • +
      • Deaktiviert. Abdeckung ist offen oder PIN-Code erforderlich
      • +
      • Unbekannter Status
      • +
      • Fehler
      • +
      • Neustart ...
      • +
      • Deaktiviert. Manueller Start erforderlich
      • +
      • Manuelles Mähen
      • +
      • Geparkt durch SensorControl
      • +
      • Abgeschlossen
      • +
      +
    • +
    +

    + + Attribute +
      +
    • readingValueLanguage - Änderung der Sprache der Readings (de,en/wenn nichts gesetzt ist, dann Englisch es sei denn deutsch ist als globale Sprache gesetzt)
    • +
    • model -
    • +
    + + set +
      +
    • winter_mode - aufwäcken (awake)| winterschlaf (hibernate)
    • +
    +
      +

      mäher

      +
    • parkUntilFurtherNotice - Parken des Mähers unter Umgehung des Zeitplans
    • +
    • parkUntilNextTimer - Parken bis zum nächsten Zeitplan
    • +
    • startOverrideTimer - Manuelles mähen (in Minuten, 60 = 1h, 1440 = 24h, 4320 = 72h)
    • +
    • startResumeSchedule - Weiterführung des Zeitplans
    • +
    • startpoint enable|disable 1|2|3 - Aktiviert oder deaktiviert einen vordefinierten Startbereich
    • +
        +
      • set NAME startpoint enable 1
      • +
      • set NAME startpoint disable 3 enable 1
      • +
      +

      irrigation control

      +
    • resumeScheduleValve - Startet Bew&aauml;sserung am Ventil n nach Zeitplan
    • +
    • stopScheduleValve - Setzt Bew&aauml;sserung am Ventil n aus (Default: 2038-01-18T00:00:00.000Z) | Optionaler Parameter Stunden (Jetzt + Stunden)
    • +
    • closeAllValves - Stopt Bew&aauml;sserung an allen Ventilen
    • +

      water control

      +
    • manualButtonTime - setzt die Dauer für den manuellen Knopf (in Minuten) 0 Schaltet den Knopf aus
    • +
    • stopSchedule - Halte Zeitplan an für x Stunden - (Default: 2038-01-18T00:00:00.000Z)
    • +
    • resumeSchedule - Weiterführung des Zeitplans
    • +
    +
+ +=end html_DE + +=for :application/json;q=META.json 74_GardenaSmartDevice.pm +{ + "abstract": "Modul to control GardenaSmart Devices", + "x_lang": { + "de": { + "abstract": "Modul zur Steuerung von Gardena Smart Geräten" + } + }, + "keywords": [ + "fhem-mod-device", + "fhem-core", + "Garden", + "Gardena", + "Smart" + ], + "release_status": "stable", + "license": "GPL_2", + "version": "v2.5.5", + "author": [ + "Marko Oldenburg " + ], + "x_fhem_maintainer": [ + "CoolTux" + ], + "x_fhem_maintainer_github": [ + "LeonGaultier" + ], + "prereqs": { + "runtime": { + "requires": { + "FHEM": 5.00918799, + "perl": 5.016, + "Meta": 0, + "JSON": 0, + "Time::Local": 0 + }, + "recommends": { + }, + "suggests": { + } + } + } +} +=end :application/json;q=META.json + +=cut diff --git a/controls_GardenaSmartDevice.txt b/controls_GardenaSmartDevice.txt index af773db..280e02b 100644 --- a/controls_GardenaSmartDevice.txt +++ b/controls_GardenaSmartDevice.txt @@ -1,2 +1,2 @@ UPD 2022-07-12_20:03:00 49634 FHEM/73_GardenaSmartBridge.pm -UPD 2022-07-19_20:20:03 71804 FHEM/74_GardenaSmartDevice.pm +UPD 2022-07-20_12:15:45 73554 FHEM/74_GardenaSmartDevice.pm From 33a10d3756c9642662c8ced5f05c807ff3935364 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Fri, 22 Jul 2022 21:08:02 +0200 Subject: [PATCH 03/29] [fix] - exists gegen defined --- CHANGED | 2 +- FHEM/74_GardenaSmartDevice.pm | 4 ++-- controls_GardenaSmartDevice.txt | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGED b/CHANGED index af74819..649a414 100644 --- a/CHANGED +++ b/CHANGED @@ -1 +1 @@ - cleanup code, fix start up defined string + cleanup diff --git a/FHEM/74_GardenaSmartDevice.pm b/FHEM/74_GardenaSmartDevice.pm index 363f97d..1790f6a 100644 --- a/FHEM/74_GardenaSmartDevice.pm +++ b/FHEM/74_GardenaSmartDevice.pm @@ -709,7 +709,7 @@ sub WriteReadings { . $propertie->{name}, ($propertie->{value} eq '') ? RigReadingsValue( $hash, 'n/a') : RigReadingsValue( $hash, $propertie->{value} ) ) - if ( exists( $propertie->{value} ) # defined ignored 'value':null + if ( defined( $propertie->{value} ) && $decode_json->{abilities}[$abilities]{name} . '-' . $propertie->{name} ne 'radio-quality' && $decode_json->{abilities}[$abilities]{name} . '-' @@ -904,7 +904,7 @@ sub WriteReadings { $decode_json->{settings}[$settings]{value} ); # CommandAttr( undef, $name . " scheduling-scheduled_watering_next_start_") if ($decode_json->{settings}[$settings]{value} eq '' ) } - +#TODO: Readings und Setter ?! # save electronid pressure pump settings as readings if ( $decode_json->{settings}[$settings]{name} eq 'operating_mode' || $decode_json->{settings}[$settings]{name} eq 'leakage_detection' diff --git a/controls_GardenaSmartDevice.txt b/controls_GardenaSmartDevice.txt index 280e02b..d496860 100644 --- a/controls_GardenaSmartDevice.txt +++ b/controls_GardenaSmartDevice.txt @@ -1,2 +1,2 @@ -UPD 2022-07-12_20:03:00 49634 FHEM/73_GardenaSmartBridge.pm -UPD 2022-07-20_12:15:45 73554 FHEM/74_GardenaSmartDevice.pm +UPD 2022-07-21_19:43:48 49634 FHEM/73_GardenaSmartBridge.pm +UPD 2022-07-22_21:07:48 73554 FHEM/74_GardenaSmartDevice.pm From f3d153726b5cdc966d2f6935c0c2eb5bf1decf87 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Sun, 24 Jul 2022 20:25:21 +0200 Subject: [PATCH 04/29] [fix] - uninitialized 727 --- CHANGED | 2 +- FHEM/74_GardenaSmartDevice.pm | 4 ++-- controls_GardenaSmartDevice.txt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGED b/CHANGED index 649a414..3698c2b 100644 --- a/CHANGED +++ b/CHANGED @@ -1 +1 @@ - cleanup + [fix] - exists gegen defined diff --git a/FHEM/74_GardenaSmartDevice.pm b/FHEM/74_GardenaSmartDevice.pm index 1790f6a..b5c2bca 100644 --- a/FHEM/74_GardenaSmartDevice.pm +++ b/FHEM/74_GardenaSmartDevice.pm @@ -707,9 +707,9 @@ sub WriteReadings { $hash, $decode_json->{abilities}[$abilities]{name} . '-' . $propertie->{name}, - ($propertie->{value} eq '') ? RigReadingsValue( $hash, 'n/a') : RigReadingsValue( $hash, $propertie->{value} ) + (defined ($propertie->{value} ) eq '') ? RigReadingsValue( $hash, 'n/a') : RigReadingsValue( $hash, $propertie->{value} ) ) - if ( defined( $propertie->{value} ) + if ( exists( $propertie->{value} ) && $decode_json->{abilities}[$abilities]{name} . '-' . $propertie->{name} ne 'radio-quality' && $decode_json->{abilities}[$abilities]{name} . '-' diff --git a/controls_GardenaSmartDevice.txt b/controls_GardenaSmartDevice.txt index d496860..6f4e17d 100644 --- a/controls_GardenaSmartDevice.txt +++ b/controls_GardenaSmartDevice.txt @@ -1,2 +1,2 @@ UPD 2022-07-21_19:43:48 49634 FHEM/73_GardenaSmartBridge.pm -UPD 2022-07-22_21:07:48 73554 FHEM/74_GardenaSmartDevice.pm +UPD 2022-07-24_20:24:56 73564 FHEM/74_GardenaSmartDevice.pm From df33172650a30448e9f32c434805c346adf20229 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Sun, 24 Jul 2022 20:29:15 +0200 Subject: [PATCH 05/29] [add] - translation pumpe filter --- CHANGED | 2 +- FHEM/74_GardenaSmartDevice.pm | 1 + controls_GardenaSmartDevice.txt | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGED b/CHANGED index 3698c2b..9fedf86 100644 --- a/CHANGED +++ b/CHANGED @@ -1 +1 @@ - [fix] - exists gegen defined + [fix] - uninitialized 727 diff --git a/FHEM/74_GardenaSmartDevice.pm b/FHEM/74_GardenaSmartDevice.pm index b5c2bca..3b83cbb 100644 --- a/FHEM/74_GardenaSmartDevice.pm +++ b/FHEM/74_GardenaSmartDevice.pm @@ -1238,6 +1238,7 @@ sub ReadingLangGerman { 'next watering: %s' => 'Nächste Bewässerung: %s', 'n/a' => 'nicht verfügbar', 'pump_not_filled' => 'Pumpe nicht gefüllt', + 'clean_fine_filter' => 'Filter reinigen', ); if ( diff --git a/controls_GardenaSmartDevice.txt b/controls_GardenaSmartDevice.txt index 6f4e17d..3280213 100644 --- a/controls_GardenaSmartDevice.txt +++ b/controls_GardenaSmartDevice.txt @@ -1,2 +1,2 @@ UPD 2022-07-21_19:43:48 49634 FHEM/73_GardenaSmartBridge.pm -UPD 2022-07-24_20:24:56 73564 FHEM/74_GardenaSmartDevice.pm +UPD 2022-07-24_20:29:03 73628 FHEM/74_GardenaSmartDevice.pm From a13c42f08c644237212a1b3dd4cd5dd02076bfcb Mon Sep 17 00:00:00 2001 From: Sebastian Date: Wed, 27 Jul 2022 22:31:53 +0200 Subject: [PATCH 06/29] [add] - translations/commandref --- CHANGED | 2 +- FHEM/74_GardenaSmartDevice.pm | 3677 ++++++++++++++++--------------- controls_GardenaSmartDevice.txt | 2 +- 3 files changed, 1928 insertions(+), 1753 deletions(-) diff --git a/CHANGED b/CHANGED index 9fedf86..af3012d 100644 --- a/CHANGED +++ b/CHANGED @@ -1 +1 @@ - [fix] - uninitialized 727 + [add] - translation pumpe filter diff --git a/FHEM/74_GardenaSmartDevice.pm b/FHEM/74_GardenaSmartDevice.pm index 3b83cbb..c5fa25d 100644 --- a/FHEM/74_GardenaSmartDevice.pm +++ b/FHEM/74_GardenaSmartDevice.pm @@ -1,1751 +1,1926 @@ -############################################################################### -# -# Developed with VSCodium and richterger perl plugin. -# -# (c) 2017-2022 Copyright: Marko Oldenburg (fhemdevelopment at cooltux dot net) -# All rights reserved -# -# Special thanks goes to comitters: -# - Michael (mbrak) Thanks for Commandref -# - Matthias (Kenneth) Thanks for Wiki entry -# - BioS Thanks for predefined start points Code -# - fettgu Thanks for Debugging Irrigation Control data flow -# - Sebastian (BOFH) Thanks for new Auth Code after API Change -# -# -# This script 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 -# any later version. -# -# The GNU General Public License can be found at -# http://www.gnu.org/copyleft/gpl.html. -# A copy is found in the textfile GPL.txt and important notices to the license -# from the author is found in LICENSE.txt distributed with these scripts. -# -# This script 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. -# -# -# $Id$ -# -############################################################################### -## -## -## Das JSON Modul immer in einem eval aufrufen -# $data = eval{decode_json($data)}; -# -# if($@){ -# Log3($SELF, 2, "$TYPE ($SELF) - error while request: $@"); -# -# readingsSingleUpdate($hash, "state", "error", 1); -# -# return; -# } -# -# -###### Wichtige Notizen -# -# apt-get install libio-socket-ssl-perl -# http://www.dxsdata.com/de/2016/07/php-class-for-gardena-smart-system-api/ -# -## -## - -## unserer packagename -package FHEM::GardenaSmartDevice; -use GPUtils qw(GP_Import GP_Export); - -use strict; -use warnings; -use POSIX; -use FHEM::Meta; -use Time::Local; -use Time::Piece; -use Time::Seconds; - -# try to use JSON::MaybeXS wrapper -# for chance of better performance + open code -eval { - require JSON::MaybeXS; - import JSON::MaybeXS qw( decode_json encode_json ); - 1; -} or do { - - # try to use JSON wrapper - # for chance of better performance - eval { - # JSON preference order - local $ENV{PERL_JSON_BACKEND} = - 'Cpanel::JSON::XS,JSON::XS,JSON::PP,JSON::backportPP' - unless ( defined( $ENV{PERL_JSON_BACKEND} ) ); - - require JSON; - import JSON qw( decode_json encode_json ); - 1; - } or do { - - # In rare cases, Cpanel::JSON::XS may - # be installed but JSON|JSON::MaybeXS not ... - eval { - require Cpanel::JSON::XS; - import Cpanel::JSON::XS qw(decode_json encode_json); - 1; - } or do { - - # In rare cases, JSON::XS may - # be installed but JSON not ... - eval { - require JSON::XS; - import JSON::XS qw(decode_json encode_json); - 1; - } or do { - - # Fallback to built-in JSON which SHOULD - # be available since 5.014 ... - eval { - require JSON::PP; - import JSON::PP qw(decode_json encode_json); - 1; - } or do { - - # Fallback to JSON::backportPP in really rare cases - require JSON::backportPP; - import JSON::backportPP qw(decode_json encode_json); - 1; - }; - }; - }; - }; -}; - -## Import der FHEM Funktionen -#-- Run before package compilation -BEGIN { - - # Import from main context - GP_Import( - qw(readingsSingleUpdate - readingsBulkUpdate - readingsBulkUpdateIfChanged - readingsBeginUpdate - readingsEndUpdate - Log3 - CommandAttr - AttrVal - ReadingsVal - readingFnAttributes - AssignIoPort - modules - IOWrite - defs - makeDeviceName) - ); -} - -#-- Export to main context with different name -GP_Export( - qw( - Initialize - ) -); - -sub Initialize { - my $hash = shift; - - $hash->{Match} = '^{"id":".*'; - - $hash->{SetFn} = \&Set; - $hash->{DefFn} = \&Define; - $hash->{UndefFn} = \&Undef; - $hash->{ParseFn} = \&Parse; - - $hash->{AttrFn} = \&Attr; - $hash->{AttrList} = - "readingValueLanguage:de,en " - . "model:watering_computer,sensor,sensor2,mower,ic24,power,electronic_pressure_pump " - . "extendedState:0,1 " - . "IODev " - . $readingFnAttributes; - $hash->{parseParams} = 1; - - return FHEM::Meta::InitMod( __FILE__, $hash ); -} - -sub Define { - my $hash = shift // return; - my $aArg = shift // return; - - return $@ unless ( FHEM::Meta::SetInternals($hash) ); - use version 0.60; our $VERSION = FHEM::Meta::Get( $hash, 'version' ); - - return - "too few parameters: define GardenaSmartDevice " - if ( scalar( @{$aArg} ) < 3 ); - - my $name = $aArg->[0]; - my $deviceId = $aArg->[2]; - my $category = $aArg->[3]; - - $hash->{DEVICEID} = $deviceId; - $hash->{VERSION} = version->parse($VERSION)->normal; - $hash->{helper}{STARTINGPOINTID} = ''; - $hash->{helper}{schedules_paused_until_id} = ''; - $hash->{helper}{eco_mode_id} = ''; - $hash->{helper}{button_config_time_id} = ''; - $hash->{helper}{winter_mode_id} = ''; - # Electroni Pressure Pump - $hash->{helper}{operating_mode_id} = ''; - $hash->{helper}{leakage_detection_id} = ''; - $hash->{helper}{turn_on_pressure_id} = ''; - - - $hash->{helper}{_id} = ''; - - # IrrigationControl valve control max 6 - $hash->{helper}{schedules_paused_until_1_id} = ''; - $hash->{helper}{schedules_paused_until_2_id} = ''; - $hash->{helper}{schedules_paused_until_3_id} = ''; - $hash->{helper}{schedules_paused_until_4_id} = ''; - $hash->{helper}{schedules_paused_until_5_id} = ''; - $hash->{helper}{schedules_paused_until_6_id} = ''; - - CommandAttr( undef, - "$name IODev $modules{GardenaSmartBridge}{defptr}{BRIDGE}->{NAME}" ) - if ( AttrVal( $name, 'IODev', 'none' ) eq 'none' ); - - my $iodev = AttrVal( $name, 'IODev', 'none' ); - - AssignIoPort( $hash, $iodev ) if ( !$hash->{IODev} ); - - if ( defined( $hash->{IODev}->{NAME} ) ) { - Log3 $name, 3, "GardenaSmartDevice ($name) - I/O device is " - . $hash->{IODev}->{NAME}; - } - else { - Log3 $name, 1, "GardenaSmartDevice ($name) - no I/O device"; - } - - $iodev = $hash->{IODev}->{NAME}; - - my $d = $modules{GardenaSmartDevice}{defptr}{$deviceId}; - - return -"GardenaSmartDevice device $name on GardenaSmartBridge $iodev already defined." - if ( defined($d) - && $d->{IODev} == $hash->{IODev} - && $d->{NAME} ne $name ); - - CommandAttr( undef, $name . ' room GardenaSmart' ) - if ( AttrVal( $name, 'room', 'none' ) eq 'none' ); - - CommandAttr( undef, $name . ' model ' . $category ) - if ( AttrVal( $name, 'model', 'none' ) eq 'none' ); - - Log3 $name, 3, -"GardenaSmartDevice ($name) - defined GardenaSmartDevice with DEVICEID: $deviceId"; - readingsSingleUpdate( $hash, 'state', 'initialized', 1 ); - - $modules{GardenaSmartDevice}{defptr}{$deviceId} = $hash; - - return; -} - -sub Undef { - my $hash = shift; - my $arg = shift; - - my $name = $hash->{NAME}; - my $deviceId = $hash->{DEVICEID}; - - delete $modules{GardenaSmartDevice}{defptr}{$deviceId}; - - return; -} - -sub Attr { - - my ( $cmd, $name, $attrName, $attrVal ) = @_; - my $hash = $defs{$name}; - - return; -} - -sub Set { - my $hash = shift // return; - my $aArg = shift // return; - - my $name = shift @$aArg; - my $cmd = shift @$aArg - // return qq{"set $name" needs at least one argument}; - - my $payload; - my $abilities; - my $service_id; - my $mainboard_version = - ReadingsVal( $name, 'mower_type-mainboard_version', 0.0 ); - - my ($Sekunden, $Minuten, $Stunden, $Monatstag, $Monat, - $Jahr, $Wochentag, $Jahrestag, $Sommerzeit) = localtime(time); - - my $timezone_offset = $Sommerzeit ? 0 : ( Time::Piece->new )->tzoffset; - - #set default abilitie ... overwrite in cmd to change - $abilities = 'mower' - if ( AttrVal( $name, 'model', 'unknown' ) eq 'mower' ); - $abilities = 'watering' - if ( AttrVal( $name, 'model', 'unknown' ) eq 'ic24' - || AttrVal( $name, 'model', 'unknown' ) eq 'watering_computer' ); - $abilities = 'power' - if ( AttrVal( $name, 'model', 'unknown' ) eq 'power' ); - $abilities = 'watering' - if ( AttrVal( $name, 'model', 'unknown' ) eq 'electronic_pressure_pump' ); - - ### mower - # service_id (eco, parkuntilfurhternotice, startpoints) - if ( lc $cmd eq 'parkuntilfurthernotice' ) { - $payload = '"name":"park_until_further_notice"'; - if ( $mainboard_version > 10.30 ) { - $payload = -' "settings":{"name":"schedules_paused_until","value":"2038-01-18T00:00:00.000Z","device":"' - . $hash->{DEVICEID} . '"}'; - $abilities = 'mower_settings'; - $service_id = $hash->{helper}{schedules_paused_until_id}; - } - } - elsif ( lc $cmd eq 'parkuntilnexttimer' ) { - $payload = '"name":"park_until_next_timer"'; - if ( $mainboard_version > 10.30 ) { - $payload = '"properties":{"name":"mower_timer","value":0}'; - $abilities = 'mower_timer'; - } - } - elsif ( lc $cmd eq 'startresumeschedule' ) { - $payload = '"name":"start_resume_schedule"'; - if ( $mainboard_version > 10.30 ) { - $payload = -' "settings":{"name":"schedules_paused_until","value":"","device":"' - . $hash->{DEVICEID} . '"}'; - $abilities = 'mower_settings'; - $service_id = $hash->{helper}{schedules_paused_until_id}; - } - } - elsif ( lc $cmd eq 'startoverridetimer' ) { - $payload = '"name":"start_override_timer","parameters":{"duration":' - . $aArg->[0] * 60 . '}'; - if ( $mainboard_version > 10.30 ) { - $payload = '"properties":{"name":"mower_timer","value":' - . $aArg->[0] * 60 . '}'; - $abilities = 'mower_timer'; - } - - } - elsif ( lc $cmd eq 'startpoint' ) { - my $err; - ( $err, $payload, $abilities ) = - SetPredefinedStartPoints( $hash, $aArg ); - $service_id = $hash->{helper}{STARTINGPOINTID}; - return $err if ( defined($err) ); - } - elsif ( lc $cmd eq 'eco' ) { - $payload = - '"settings": {"name": "eco_mode", "value": ' - . $aArg->[0] - . ', "device": "' - . $hash->{DEVICEID} . '"}'; - $abilities = 'mower_settings' if ( $mainboard_version > 10.30 ); - $service_id = $hash->{helper}{eco_mode_id}; - -#$abilities['service_id'] = $hash->{helper}{SCHEDULESID} if ( $mainboard_version > 10.30 ); - } - ### electronic_pressure_pump - # elsif ( lc $cmd eq 'pumptimer' ) { - # $payload = - # '"name":"pump_manual_watering_timer","parameters":{"duration":' - # . $aArg->[0] . '}'; - # } - ### watering_computer & electronic pump - elsif ( lc $cmd eq 'manualoverride' ) { - $payload = - '"properties":{"name":"watering_timer_1' - . '","value":{"state":"manual","duration":' - . $aArg->[0] * 60 - . ',"valve_id":1}}'; - } - elsif ( lc $cmd eq 'manualbuttontime' ) { - $service_id = $hash->{helper}{button_config_time_id}; - $payload = - '"properties":{"name":"button_config_time",' - . '"value":' - . $aArg->[0] * 60 - . ',"timestamp":"2021-05-26T19:06:23.680Z"' - . ',"at_bound":null,"unit":"seconds","ability":"' - . $service_id . '"}'; - $abilities = 'watering_button_config'; - } - elsif ( $cmd =~ m{\AcancelOverride}xms ) { - - my $valve_id = 1; - - if ( $cmd =~ m{\AcancelOverrideValve(\d)\z}xms ) { - $valve_id = $1; - } - - $payload = - '"properties":{"name":"watering_timer_' - . $valve_id - . '","value":{"state":"idle","duration":' - . 0 - . ',"valve_id":' - . $valve_id . '}}'; - } - elsif ( $cmd =~ /.*Schedule$/ ) { - my $duration = ( - ( - defined( $aArg->[0] ) - ? ( - ( - ( Time::Piece->new ) + - ( ONE_HOUR * $aArg->[0] ) - - $timezone_offset - )->datetime - ) - . '.000Z' - : '2038-01-18T00:00:00.000Z' - ) - ); - - $abilities = 'wateringcomputer_settings'; - $service_id = $hash->{helper}->{'schedules_paused_until_id'}; - $payload = - '"settings":{"name":"schedules_paused_until"' - . ', "value":"' - . ( $cmd eq 'resumeSchedule' ? '' : $duration ) - . '","device":"' - . $hash->{DEVICEID} . '"}'; - } - elsif ( lc $cmd eq 'on' || lc $cmd eq 'off' || lc $cmd eq 'on-for-timer' ) { - my $val = ( - scalar( !@$aArg == 0 ) && ref($aArg) eq 'ARRAY' - ? $aArg->[0] * 60 - : lc $cmd - ); - - $payload = - '"properties":{"name":"power_timer", "value":"' . $val . '"}'; - } - ### Watering ic24 - elsif ( $cmd =~ m{\AmanualDurationValve\d\z}xms ) { - my $valve_id; - - if ( $cmd =~ m{\AmanualDurationValve(\d)\z}xms ) { - $valve_id = $1; - } - - $payload = - '"properties":{"name":"watering_timer_' - . $valve_id - . '","value":{"state":"manual","duration":' - . $aArg->[0] * 60 - . ',"valve_id":' - . $valve_id . '}}'; - } - elsif ( $cmd eq 'closeAllValves' ) { - $payload = '"name":"close_all_valves","parameters":{}'; - } - elsif ( $cmd =~ /.*ScheduleValve$/ ) { - my $valve_id = $aArg->[0]; - my $duration = ( - ( - defined( $aArg->[1] ) - ? ( - ( - ( Time::Piece->new ) + - ( ONE_HOUR * $aArg->[1] ) - - $timezone_offset - )->datetime - ) - . '.000Z' - : '2038-01-18T00:00:00.000Z' - ) - ); - - $abilities = 'irrigation_settings'; - $service_id = - $hash->{helper}->{ 'schedules_paused_until_' . $valve_id . '_id' }; - $payload = - '"settings":{"name":"schedules_paused_until_' - . $valve_id - . '", "value":"' - . ( $cmd eq 'resumeScheduleValve' ? '' : $duration ) - . '","device":"' - . $hash->{DEVICEID} . '"}'; - } - ### Watering_pressure_pump - elsif ( lc $cmd eq 'operating_mode') { - my $op_mode = $aArg->[0]; - $payload = '"settings":{"name":"operating_mode",' - .'"value":"'.$op_mode.'",' - .'"device":"' - . $hash->{DEVICEID}.'"}'; - $abilities = 'watering_pressure_pump_settings'; - $service_id = $hash->{helper}->{ 'operating_mode_id' }; - } - elsif ( lc $cmd eq 'leakage_detection') { - my $leakdetection_mode = $aArg->[0]; - $payload = '"settings":{"name":"leakage_detection",' - .'"value":"'.$leakdetection_mode.'",' - .'"device":"' - . $hash->{DEVICEID}.'"}'; - $abilities = 'watering_pressure_pump_settings'; - $service_id = $hash->{helper}->{ 'leakage_detection_id' }; - } - elsif ( lc $cmd eq 'turn_on_pressure') { - my $turnonpressure = $aArg->[0]; - $payload = '"settings":{"name":"turn_on_pressure",' - .'"value":"'.$turnonpressure.'",' - .'"device":"' - . $hash->{DEVICEID}.'"}'; - $abilities = 'watering_pressure_pump_settings'; - $service_id = $hash->{helper}->{ 'turn_on_pressure_id' }; - } - elsif ( lc $cmd eq 'resetvalveerrors') { - $payload = '"name":"reset_valve_errors",' - .' "parameters": {}'; - $abilities = 'error'; - } - - ### Sensors - elsif ( lc $cmd eq 'refresh' ) { - - my $sensname = $aArg->[0]; - if ( lc $sensname eq 'temperature' ) { - if ( ReadingsVal( $name, 'device_info-category', 'sensor' ) eq - 'sensor' ) - { - $payload = '"name":"measure_ambient_temperature"'; - $abilities = 'ambient_temperature'; - } - else { - $payload = '"name":"measure_soil_temperature"'; - $abilities = 'soil_temperature'; - } - } - elsif ( lc $sensname eq 'light' ) { - $payload = '"name":"measure_light"'; - $abilities = 'light'; - - } - elsif ( lc $sensname eq 'humidity' ) { - $payload = '"name":"measure_soil_humidity"'; - $abilities = 'humidity'; - } - } - ## winter sleep - elsif ( lc $cmd eq 'winter_mode' ) { - $payload = - '"settings":{"name":"winter_mode","value":"' - . $aArg->[0] - . '","device":"' - . $hash->{DEVICEID} . '"}'; - $abilities = 'winter_settings'; - $service_id = $hash->{helper}->{'winter_mode_id'}; - } - else { - - my $list = ''; - - $list .= -'parkUntilFurtherNotice:noArg parkUntilNextTimer:noArg startResumeSchedule:noArg startOverrideTimer:slider,0,1,240 startpoint' - if ( AttrVal( $name, 'model', 'unknown' ) eq 'mower' ); - - $list .= -'manualOverride:slider,1,1,59 cancelOverride:noArg resumeSchedule:noArg stopSchedule manualButtonTime:slider,0,2,100' - if ( AttrVal( $name, 'model', 'unknown' ) eq 'watering_computer' ); - - - $list .= 'manualOverride:slider,1,1,90 cancelOverride:noArg operating_mode:automatic,scheduled leakage_detection:watering,washing_machine,domestic_water_supply,off turn_on_pressure:slider,2,0.2,3.0,1 resetValveErrors:noArg' - if ( AttrVal( $name, 'model', 'unknown' ) eq 'electronic_pressure_pump' ); - - $list .= -'closeAllValves:noArg stopScheduleValve:select,'.ReadingsVal( $name, 'ic24-valves_connected', '1' ).' resumeScheduleValve:select,'.ReadingsVal( $name, 'ic24-valves_connected', '1' ) - if ( AttrVal( $name, 'model', 'unknown' ) eq 'ic24' ); - - foreach my $valve (split(',', ReadingsVal( $name, 'ic24-valves_connected', '1'))) { - $list .= ' manualDurationValve'.$valve.':slider,1,1,90 ' - if ( AttrVal( $name, 'model', 'unknown' ) eq 'ic24' ); - } - - foreach my $valve (split(',', ReadingsVal( $name, 'ic24-valves_connected', '1'))) { - $list .= ' cancelOverrideValve'.$valve.':noArg ' - if ( AttrVal( $name, 'model', 'unknown' ) eq 'ic24' ); - } - - $list .= 'refresh:temperature,humidity' - if ( AttrVal( $name, 'model', 'unknown' ) =~ /sensor.?/ ); - - # add light for old sensors - $list .= ',light' - if ( AttrVal( $name, 'model', 'unknown' ) eq 'sensor' - && ReadingsVal( $name, 'device_info-category', 'unknown' ) eq - 'sensor' ); - - $list .= 'on:noArg off:noArg on-for-timer:slider,0,1,720' - if ( AttrVal( $name, 'model', 'unknown' ) eq 'power' ); - - # all devices has abilitie to fall a sleep - $list .= ' winter_mode:awake,hibernate'; - return "Unknown argument $cmd, choose one of $list"; - } - - $hash->{helper}{deviceAction} = $payload; - readingsSingleUpdate( $hash, "state", "send command to gardena cloud", 1 ); - - IOWrite( $hash, $payload, $hash->{DEVICEID}, $abilities, $service_id ); - Log3 $name, 4, -"GardenaSmartBridge ($name) - IOWrite: $payload $hash->{DEVICEID} $abilities IODevHash=$hash->{IODev}"; - - return; -} - -sub Parse { - my $io_hash = shift; - my $json = shift; - - my $name = $io_hash->{NAME}; - - my $decode_json = eval { decode_json($json) }; - if ($@) { - Log3 $name, 3, - "GardenaSmartDevice ($name) - JSON error while request: $@"; - } - - Log3 $name, 4, "GardenaSmartDevice ($name) - ParseFn was called"; - Log3 $name, 4, "GardenaSmartDevice ($name) - JSON: $json"; - - if ( defined( $decode_json->{id} ) ) { - - my $deviceId = $decode_json->{id}; - - if ( my $hash = $modules{GardenaSmartDevice}{defptr}{$deviceId} ) { - my $name = $hash->{NAME}; - - WriteReadings( $hash, $decode_json ); - Log3 $name, 4, - "GardenaSmartDevice ($name) - find logical device: $hash->{NAME}"; - - return $hash->{NAME}; - - } - else { - - Log3 $name, 3, - "GardenaSmartDevice ($name) - autocreate new device " - . makeDeviceName( $decode_json->{name} ) - . " with deviceId $decode_json->{id}, model $decode_json->{category}"; - return - "UNDEFINED " - . makeDeviceName( $decode_json->{name} ) - . " GardenaSmartDevice $decode_json->{id} $decode_json->{category}"; - } - } - - return; -} - -sub WriteReadings { - my $hash = shift; - my $decode_json = shift; - - my $name = $hash->{NAME}; - my $abilities = scalar( @{ $decode_json->{abilities} } ); - my $settings = scalar( @{ $decode_json->{settings} } ); - my $scheduled_events = scalar( @{ $decode_json->{scheduled_events} } ); - - readingsBeginUpdate($hash); - - do { - - if ( - ref( $decode_json->{abilities}[$abilities]{properties} ) eq "ARRAY" - && scalar( @{ $decode_json->{abilities}[$abilities]{properties} } ) - > 0 ) - { - for my $propertie ( - @{ $decode_json->{abilities}[$abilities]{properties} } ) - { - if ( - exists( $decode_json->{abilities}[$abilities]{name} ) - && ( $decode_json->{abilities}[$abilities]{name} eq - 'watering' ) - ) - { - - if ( $propertie->{name} eq 'button_config_time' ) { - if ( $hash->{helper}{ $propertie->{name} . '_id' } ne - $decode_json->{abilities}[$abilities]{id} ) - { - $hash->{helper}{ $propertie->{name} . '_id' } = - $decode_json->{abilities}[$abilities]{id}; - } - readingsBulkUpdateIfChanged( - $hash, - 'manualButtonTime', - ( - RigReadingsValue( - $hash, $propertie->{value} / 60 - ) - ) - ); - next; - } - } - - readingsBulkUpdateIfChanged( - $hash, - $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name}, - (defined ($propertie->{value} ) eq '') ? RigReadingsValue( $hash, 'n/a') : RigReadingsValue( $hash, $propertie->{value} ) - ) - if ( exists( $propertie->{value} ) - && $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} ne 'radio-quality' - && $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} ne 'battery-level' - && $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} ne 'internal_temperature-temperature' - && $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} ne 'ambient_temperature-temperature' - && $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} ne 'soil_temperature-temperature' - && $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} ne 'humidity-humidity' - && $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} ne 'light-light' - && ref( $propertie->{value} ) ne "HASH" ); - - readingsBulkUpdateIfChanged( - $hash, - $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name}, - RigReadingsValue( $hash, $propertie->{value} ) - ) - if ( - defined( $propertie->{value} ) - && ( $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} eq 'radio-quality' - || $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} eq 'battery-level' - || $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} eq - 'internal_temperature-temperature' - || $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} eq - 'ambient_temperature-temperature' - || $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} eq 'soil_temperature-temperature' - || $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} eq 'humidity-humidity' - || $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} eq 'light-light' ) - ); - - readingsBulkUpdateIfChanged( - $hash, - $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} - . '_timestamp', - Time::Piece->strptime( - RigReadingsValue( $hash, $propertie->{timestamp} ), - "%Y-%m-%d %H:%M:%S" )->strftime('%s') - - ) - if ( - defined( $propertie->{value} ) - && ( $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} eq 'mower_timer-mower_timer' ) - ); - - readingsBulkUpdateIfChanged( - $hash, - $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name}, - join( ',', @{ $propertie->{value} } ) - ) - if ( defined( $propertie->{value} ) - && $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} eq 'ic24-valves_connected' ); - - readingsBulkUpdateIfChanged( - $hash, - $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name}, - join( ',', @{ $propertie->{value} } ) - ) - if ( defined( $propertie->{value} ) - && $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} eq 'ic24-valves_master_config' ); - - if ( ref( $propertie->{value} ) eq "HASH" ) { - my $sub_state = 0; my $sub_value = 0; - while ( my ( $r, $v ) = each %{ $propertie->{value} } ) { - if ( ref( $v ) ne "HASH" ) { - readingsBulkUpdate( - $hash, - $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} . '_' - . $r, - RigReadingsValue( $hash, $v ) - ); - } else { - while ( my ( $i_r, $i_v ) = each %{ $v } ) { - readingsBulkUpdate( - $hash, - $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} . '_' - . $r . '_' . $i_r, - RigReadingsValue( $hash, $i_v ) - ); - } - } - } - } - # ic24 and other watering devices calc irrigation left in sec - readingsBulkUpdateIfChanged( - $hash, - $decode_json->{abilities}[$abilities]{name} . '-' - . $propertie->{name} - . '_irrigation_left', - ( $propertie->{value}{duration} > 0 ) ? (Time::Piece::localtime->strptime( - RigReadingsValue($hash, $propertie->{timestamp}), "%Y-%m-%d %H:%M:%S") - + ($propertie->{value}{duration} + 3 ) - Time::Piece::localtime->new) : 0 - ) - if ( defined( $propertie->{value} ) - && $decode_json->{abilities}[$abilities]{name} eq 'watering' - ); - } - } - - $abilities--; - } while ( $abilities >= 0 ); - - - if ( - exists( $decode_json->{scheduled_events} ) - # && scalar ($decode_json->{scheduled_events} ) > 0 - && ref ($decode_json->{scheduled_events}) eq 'ARRAY' ) { - readingsBulkUpdateIfChanged( $hash, 'scheduling-schedules_events_count', - scalar( @{$decode_json->{scheduled_events} } ) ); - my $valve_id =1; my $event_id = 1; # ic24 [1..6] | wc, pump [1] - - for my $event_schedules ( @{ $decode_json->{scheduled_events} } ) { - $valve_id = $event_schedules->{valve_id} if ( exists($event_schedules->{valve_id} ) ); #ic24 - $event_id++; # event id - - while ( my ( $r, $v ) = each %{ $event_schedules } ) { - readingsBulkUpdateIfChanged( $hash, 'scheduling-schedules_event_' - . $event_id - . '_valve_' - . $valve_id - . '_' - . $r, - $v) if (ref($v) ne 'HASH' ); - readingsBulkUpdateIfChanged( $hash, 'scheduling-schedules_event_' - . $event_id - . '_valve_' - . $valve_id - . '_' - . $v->{type}, - join(',', @ { $v->{weekdays}}) ) if (ref($v) eq 'HASH' ); - }; - }; - - }; # fi scheduled_events - - my $winter_mode; - - do { -#Log3 $name, 1, "Settings pro Device : ".$decode_json->{settings}[$settings]{name}; -#Log3 $name, 1, " - KEIN ARRAY" if ( ref( $decode_json->{settings}[$settings]{value} ) ne "ARRAY"); -#Log3 $name, 1, " - IST ARRAY" if ( ref( $decode_json->{settings}[$settings]{value} ) eq "ARRAY"); - - if ( - exists( $decode_json->{settings}[$settings]{name} ) - && ( $decode_json->{settings}[$settings]{name} =~ - /schedules_paused_until_?\d?$/ - || $decode_json->{settings}[$settings]{name} eq 'eco_mode' - || $decode_json->{settings}[$settings]{name} eq 'winter_mode' - || $decode_json->{settings}[$settings]{name} eq 'operating_mode' - || $decode_json->{settings}[$settings]{name} eq 'leakage_detection' - || $decode_json->{settings}[$settings]{name} eq 'turn_on_pressure' ) - ) - { - if ( $hash->{helper} - { $decode_json->{settings}[$settings]{name} . '_id' } ne - $decode_json->{settings}[$settings]{id} ) - { - $hash->{helper} - { $decode_json->{settings}[$settings]{name} . '_id' } = - $decode_json->{settings}[$settings]{id}; - } - # check watering controler single schedules pause until - if ( $decode_json->{settings}[$settings]{name} eq 'schedules_paused_until' ) { - readingsBulkUpdateIfChanged( $hash, 'scheduling-schedules_paused_until', - $decode_json->{settings}[$settings]{value} ); - } - ##### - #ic24 schedules pause until - if ($decode_json->{settings}[$settings]{name} =~ /schedules_paused_until_?(\d)?$/) { - #my $ventil = substr($decode_json->{settings}[$settings]{name}, -1); # => 1 - 6 - # check if empty, clear scheduling-scheduled_watering_next_start_x - readingsBulkUpdateIfChanged( $hash, 'scheduling-'.$decode_json->{settings}[$settings]{name}, - $decode_json->{settings}[$settings]{value} ); - # CommandAttr( undef, $name . " scheduling-scheduled_watering_next_start_") if ($decode_json->{settings}[$settings]{value} eq '' ) - } -#TODO: Readings und Setter ?! - # save electronid pressure pump settings as readings - if ( $decode_json->{settings}[$settings]{name} eq 'operating_mode' - || $decode_json->{settings}[$settings]{name} eq 'leakage_detection' - || $decode_json->{settings}[$settings]{name} eq 'turn_on_pressure' ) { - readingsBulkUpdateIfChanged( $hash, $decode_json->{settings}[$settings]{name}, - $decode_json->{settings}[$settings]{value} ); - - } - # save winter mode as reading - if ( $decode_json->{settings}[$settings]{name} eq 'winter_mode' ) { - readingsBulkUpdateIfChanged( $hash, 'winter_mode', - $decode_json->{settings}[$settings]{value} ); - - $winter_mode = $decode_json->{settings}[$settings]{value}; - } - } - - if ( defined( $decode_json->{settings}[$settings]{name} ) - && $decode_json->{settings}[$settings]{name} eq 'valve_names' - && ref( $decode_json->{settings}[$settings]{value} ) eq "ARRAY" ) { # or HASH ? - my @valves = @{$decode_json->{settings}[$settings]{value}}; - foreach my $valve( @valves ) { - Log3 $name, 4, "GardenaSmartDevice ($name) valve_name $valve->{'name'}"; - readingsBulkUpdateIfChanged( $hash, 'valve-valve_name_'.$valve->{"id"}, - $valve->{"name"} ); - } - } - - if ( ref( $decode_json->{settings}[$settings]{value} ) eq "ARRAY" - && $decode_json->{settings}[$settings]{name} eq 'starting_points' ) - { - #save the startingpointid needed to update the startingpoints - if ( $hash->{helper}{STARTINGPOINTID} ne - $decode_json->{settings}[$settings]{id} ) - { - $hash->{helper}{STARTINGPOINTID} = - $decode_json->{settings}[$settings]{id}; - } - - $hash->{helper}{STARTINGPOINTS} = - '{ "name": "starting_points", "value": ' - . encode_json( $decode_json->{settings}[$settings]{value} ) . '}'; - my $startpoint_cnt = 0; - - for my $startingpoint ( - @{ $decode_json->{settings}[$settings]{value} } ) - { - $startpoint_cnt++; - readingsBulkUpdateIfChanged( - $hash, - 'startpoint-' . $startpoint_cnt . '-enabled', - $startingpoint->{enabled} - ); - } - } - - $settings--; - } while ( $settings >= 0 ); - - if ( $winter_mode ne 'hibernate' ) { - setState($hash); - } - else { - readingsBulkUpdate( $hash, 'state', - RigReadingsValue( $hash, 'hibernate' ) ); - } - - readingsEndUpdate( $hash, 1 ); - - Log3 $name, 4, "GardenaSmartDevice ($name) - readings was written"; - - return; -} - -sub setState { - my $hash = shift; - my $name = $hash->{NAME}; - - my $online_state = - ReadingsVal( $name, 'device_info-connection_status', 'unknown' ); - - #online state mower - readingsBulkUpdate( $hash, 'state', - $online_state eq 'online' - ? ReadingsVal( $name, 'mower-status', 'readingsValError' ) - : 'offline' ) - if ( AttrVal( $name, 'model', 'unknown' ) eq 'mower' ); - - # ic24 / wc / electronic pump - - if ( AttrVal( $name, 'model', 'unknown' ) eq 'ic24' - || AttrVal( $name, 'model', 'unknown' ) eq 'watering_computer' - || AttrVal( $name, 'model', 'unknown' ) eq 'electronic_pressure_pump' ){ - my @opened_valves; - my $state_string = ''; my $nearst_irrigation = '2999-12-12 12:00'; - my $has_schedule = 0; my $longest_duration = 0; my $processed_item = ''; - my $error_type = 'ok'; - my @valves_connected = AttrVal( $name, 'model', 'unknown' ) eq 'ic24' ? split(',', ReadingsVal( $name, 'ic24-valves_connected', '')) : '1'; - - $has_schedule = 1 if ( ReadingsVal($name, 'scheduling-schedules_events_count', '') ne '' ); - for (@valves_connected){ # valves 1 or 1..6 - ## add to opened ventils, if watering active - push @opened_valves, $_ if ( ( ( ReadingsVal( $name, "watering-watering_timer_".$_."_duration", 0 ) =~ m{\A[1-9]([0-9]+)?\z}xms ) ? $_ : 0 ) > 0 ); - ## set error type (pumpe required) - $error_type = ReadingsVal( $name, 'error-valve_error_'.$_.'_type', 'ok' ) if (ReadingsVal( $name, 'error-valve_error_'.$_.'_type', 'ok' ) ne 'ok'); - ## find longest irrigation duration - $longest_duration = ReadingsVal( $name, "watering-watering_timer_".$_."_irrigation_left", 0 ) if ( - ( ReadingsVal( $name, "watering-watering_timer_".$_."_duration", 0 ) =~ m{\A[1-9]([0-9]+)?\z}xms - && ReadingsVal( $name, "watering-watering_timer_".$_."_duration", 0 ) > 0 - && ReadingsVal( $name, "watering-watering_timer_".$_."_duration", 0 ) > $longest_duration ) ); - - # y-m-d h:m - $processed_item = AttrVal( $name, 'model', 'unknown' ) eq 'ic24' - ? RigReadingsValue($hash, ReadingsVal($name, 'scheduling-schedules_paused_until_'.$_, '')) - : RigReadingsValue($hash, ReadingsVal($name, 'scheduling-schedules_paused_until', '')); - - Log3 $name, 5, "[DEBUG] - process: $processed_item"; - Log3 $name, 5, "[DEBUG] - next_start: ". ReadingsVal($name, 'scheduling-scheduled_watering_next_start', ''); # n/a RigReadingsValue( $hash, 'n/a') - # $nearst_irrigation = RigReadingsValue($hash, ReadingsVal($name, 'scheduling-schedules_paused_until_'.$_, '')) - if ( ReadingsVal($name, 'scheduling-scheduled_watering_next_start', '') eq RigReadingsValue( $hash, 'n/a') ) { # non next start, schedules paused permanently or next schedule > 1 year; get nearst paused_until - Log3 $name, 5, "[DEBUG] - next_start: empty "; - Log3 $name, 5, "[DEBUG] - empty pro item ".Time::Piece->strptime( $processed_item, "%Y-%m-%d %H:%M:%S"); - Log3 $name, 5, "[DEBUG] - empty nearst ".Time::Piece->strptime( $nearst_irrigation, "%Y-%m-%d %H:%M:%S"); - $nearst_irrigation = $processed_item - if ( Time::Piece->strptime( $processed_item, "%Y-%m-%d %H:%M:%S") - < Time::Piece->strptime( $nearst_irrigation, "%Y-%m-%d %H:%M:%S") - && $has_schedule - && Time::Piece->strptime( $processed_item, "%Y-%m-%d %H:%M:%S") - > Time::Piece->new - ) - } else { - $nearst_irrigation = ReadingsVal($name, 'scheduling-scheduled_watering_next_start', ''); - } - Log3 $name, 5, "[DEBUG] - choosed nearst: $nearst_irrigation"; - - } # for - # override state 4 extendedstates - if ( AttrVal( $name, "extendedState", 0 ) == 1) { - if (scalar(@opened_valves) > 0){ - ## valve 1 will be ir.. 23 minutes remaining - for (@valves_connected){ - $state_string .= sprintf(RigReadingsValue($hash,'valve').' '.$_.' '.(RigReadingsValue($hash, 'will be irrigated %.f minutes remaining.') .'
'), (ReadingsVal( $name, 'watering-watering_timer_'.$_.'_duration', 0 )/60)); - } # /for - } else { - $state_string .= RigReadingsValue($hash, 'closed'); - } - $state_string .= ($has_schedule) ? sprintf( RigReadingsValue($hash, 'next watering: %s'), RigReadingsValue($hash, ReadingsVal($name, 'scheduling-scheduled_watering_next_start', ''))) : sprintf( RigReadingsValue($hash, 'paused until %s') , $nearst_irrigation); - #TODO: Write state format for ventil 1-@valces_connected -> map ? - CommandAttr( undef, $name . ' stateFormat - { - - } - ' ) - if ( AttrVal( $name, 'stateFormat', 'none' ) eq 'none' ); - } else { - Log3 $name, 5, "[DEBUG] - Offene Ventile :".scalar(@opened_valves)." laengste bewaesserung: $longest_duration . hat Zeitplan: $has_schedule Naechster Zeitplan: $nearst_irrigation"; - $state_string = scalar(@opened_valves) > 0 - # offen - ? sprintf( (RigReadingsValue($hash, 'will be irrigated %.f minutes remaining.')), $longest_duration/60) - # zu - : - ( $has_schedule - && $nearst_irrigation ne '2999-12-12 12:00') - # zeitplan aktiv - # ? ( $nearst_irrigation eq '2038-01-18 00:00') sprintf( RigReadingsValue($hash, 'paused until %s') , $nearst_irrigation) - ? ( $nearst_irrigation eq RigReadingsValue( $hash, 'n/a') || $nearst_irrigation =~ '2038-01-18.*') - # dauerhaft pausiert - ? sprintf( (RigReadingsValue($hash, 'closed') .'. '.RigReadingsValue($hash , 'schedule permanently paused')) ) - # naechster zeutplan - : (ReadingsVal($name, 'scheduling-scheduled_watering_next_start', '') eq RigReadingsValue($hash, 'n/a')) - ? sprintf( RigReadingsValue($hash, 'paused until %s') , $nearst_irrigation) - : sprintf( (RigReadingsValue($hash, 'closed') .'. '.RigReadingsValue($hash, 'next watering: %s')), $nearst_irrigation ) - # zeitplan pausiert - : RigReadingsValue($hash, 'closed') - ; - # state offline | override - $state_string = 'offline' if ($online_state eq 'offline'); - $state_string = ( $error_type ne 'ok' ) ? $error_type : $state_string; - - } - readingsBulkUpdate( - $hash, 'state', RigReadingsValue( $hash, $state_string ) ); - } - - # Sensor / Sensor 2 - if ( AttrVal( $name, 'model', 'unknown' ) =~ /sensor.?/ ) { - my $state_string = - ( ReadingsVal( $name, 'device_info-category', 'unknown' ) eq - 'sensor' ) - ? 'T: ' - . ReadingsVal( $name, 'ambient_temperature-temperature', - 'readingsValError' ) - . '°C, ' - : 'T: ' - . ReadingsVal( $name, 'soil_temperature-temperature', - 'readingsValError' ) - . '°C, '; - $state_string .= 'H: ' - . ReadingsVal( $name, 'humidity-humidity', 'readingsValError' ) . '%'; - $state_string .= ', L: ' - . ReadingsVal( $name, 'light-light', 'readingsValError' ) . 'lux' - if ( ReadingsVal( $name, 'device_info-category', 'unknown' ) eq - 'sensor' ); - -# if ( $online_state eq 'offline') { -# readingsBulkUpdate( $hash, 'humidity-humidity', '-1' ); -# readingsBulkUpdate( $hash, 'ambient_temperature-temperature', '-1' ) if (ReadingsVal($name, 'device_info-category', 'unknown') eq 'sensor'); -# readingsBulkUpdate( $hash, 'light-light', '-1' ) if (ReadingsVal($name, 'device_info-category', 'unknown') eq 'sensor'); -# } - #online state sensor I II - readingsBulkUpdate( $hash, 'state', - $online_state eq 'online' ? RigReadingsValue( $hash, $state_string) : RigReadingsValue( $hash, 'offline') ); - } - - readingsBulkUpdate( $hash, 'state', - ReadingsVal( $name, 'power-power_timer', 'no info from power-timer' ) ) - if ( AttrVal( $name, 'model', 'unknown' ) eq 'power' ); - - return; -} - -################################## -################################## -#### my little helpers ########### - -sub ReadingLangGerman { - my $hash = shift; - my $readingValue = shift; - - my $name = $hash->{NAME}; - my %langGermanMapp = ( - 'ok_cutting' => 'mähen', - 'paused' => 'pausiert', - 'ok_searching' => 'suche Ladestation', - 'ok_charging' => 'lädt', - 'ok_leaving' => 'unterwegs zum Startpunkt', - 'wait_updating' => 'wird aktualisiert ...', - 'wait_power_up' => 'wird eingeschaltet ...', - 'parked_timer' => 'geparkt nach Zeitplan', - 'parked_park_selected' => 'geparkt', - 'off_disabled' => 'der Mäher ist ausgeschaltet', - 'off_hatch_open' => 'deaktiviert. Abdeckung ist offen oder PIN-Code erforderlich', - 'unknown' => 'unbekannter Status', - 'error' => 'Fehler', - 'error_at_power_up' => 'Neustart ...', - 'off_hatch_closed' => 'Deaktiviert. Manueller Start erforderlich', - 'ok_cutting_timer_overridden' => 'manuelles mähen', - 'parked_autotimer' => 'geparkt durch SensorControl', - 'parked_daily_limit_reached' => 'abgeschlossen', - 'no_message' => 'kein Fehler', - 'outside_working_area' => 'außerhalb des Arbeitsbereichs', - 'no_loop_signal' => 'kein Schleifensignal', - 'wrong_loop_signal' => 'falsches Schleifensignal', - 'loop_sensor_problem_front' => 'Problem Schleifensensor, vorne', - 'loop_sensor_problem_rear' => 'Problem Schleifensensor, hinten', - 'trapped' => 'eingeschlossen', - 'upside_down' => 'steht auf dem Kopf', - 'low_battery' => 'niedriger Batteriestand', - 'empty_battery' => 'Batterie leer', - 'no_drive' => 'fährt nicht', - 'lifted' => 'angehoben', - 'stuck_in_charging_station' => 'eingeklemmt in Ladestation', - 'charging_station_blocked' => 'Ladestation blockiert', - 'collision_sensor_problem_rear' => 'Problem Stoßsensor hinten', - 'collision_sensor_problem_front' => 'Problem Stoßsensor vorne', - 'wheel_motor_blocked_right' => 'Radmotor rechts blockiert', - 'wheel_motor_blocked_left' => 'Radmotor links blockiert', - 'wheel_drive_problem_right' => 'Problem Antrieb, rechts', - 'wheel_drive_problem_left' => 'Problem Antrieb, links', - 'cutting_system_blocked' => 'Schneidsystem blockiert', - 'invalid_sub_device_combination' => 'fehlerhafte Verbindung', - 'settings_restored' => 'Standardeinstellungen', - 'electronic_problem' => 'elektronisches Problem', - 'charging_system_problem' => 'Problem Ladesystem', - 'tilt_sensor_problem' => 'Kippsensor Problem', - 'wheel_motor_overloaded_right' => 'rechter Radmotor überlastet', - 'wheel_motor_overloaded_left' => 'linker Radmotor überlastet', - 'charging_current_too_high' => 'Ladestrom zu hoch', - 'temporary_problem' => 'vorübergehendes Problem', - 'guide_1_not_found' => 'SK 1 nicht gefunden', - 'guide_2_not_found' => 'SK 2 nicht gefunden', - 'guide_3_not_found' => 'SK 3 nicht gefunden', - 'difficult_finding_home' => 'Problem die Ladestation zu finden', - 'guide_calibration_accomplished' => 'Kalibrierung des Suchkabels beendet', - 'guide_calibration_failed' => 'Kalibrierung des Suchkabels fehlgeschlagen', - 'temporary_battery_problem' => 'kurzzeitiges Batterieproblem', - 'battery_problem' => 'Batterieproblem', - 'alarm_mower_switched_off' => 'Alarm! Mäher ausgeschalten', - 'alarm_mower_stopped' => 'Alarm! Mäher gestoppt', - 'alarm_mower_lifted' => 'Alarm! Mäher angehoben', - 'alarm_mower_tilted' => 'Alarm! Mäher gekippt', - 'connection_changed' => 'Verbindung geändert', - 'connection_not_changed' => 'Verbindung nicht geändert', - 'com_board_not_available' => 'COM Board nicht verfügbar', - 'slipped' => 'rutscht', - 'out_of_operation' => 'ausser Betrieb', - 'replace_now' => 'kritischer Batteriestand, wechseln Sie jetzt', - 'low' => 'niedrig', - 'ok' => 'ok', - 'no_source' => 'ok', - 'mower_charging' => 'Mäher wurde geladen', - 'completed_cutting_autotimer' => 'Sensor Control erreicht', - 'week_timer' => 'Wochentimer erreicht', - 'countdown_timer' => 'Stoppuhr Timer', - 'undefined' => 'unklar', - 'unknown' => 'unklar', - 'status_device_unreachable' => 'Gerät ist nicht in Reichweite', - 'status_device_alive' => 'Gerät ist in Reichweite', - 'bad' => 'schlecht', - 'poor' => 'schwach', - 'good' => 'gut', - 'undefined' => 'unklar', - 'idle' => 'nichts zu tun', - 'firmware_cancel' => 'Firmwareupload unterbrochen', - 'firmware_upload' => 'Firmwareupload', - 'unsupported' => 'nicht unterstützt', - 'up_to_date' => 'auf dem neusten Stand', - 'mower' => 'Mäher', - 'watering_computer' => 'Bewässerungscomputer', - 'no_frost' => 'kein Frost', - 'open' => 'offen', - 'closed' => 'geschlossen', - 'included' => 'inbegriffen', - 'active' => 'aktiv', - 'inactive' => 'nicht aktiv', - 'hibernate' => 'Winterschlaf', - 'awake' => 'Aufgewacht', - 'schedule permanently paused' => 'Zeitplan dauerhaft pausiert', - 'paused until %s' => 'pausiert bis %s', - 'will be irrigated %.f minutes remaining.'=> 'Wird bewässert. %.f Minuten verbleibend.', - 'next watering: %s' => 'Nächste Bewässerung: %s', - 'n/a' => 'nicht verfügbar', - 'pump_not_filled' => 'Pumpe nicht gefüllt', - 'clean_fine_filter' => 'Filter reinigen', - ); - - if ( - defined( $langGermanMapp{$readingValue} ) - && ( AttrVal( 'global', 'language', 'none' ) eq 'DE' - || AttrVal( $name, 'readingValueLanguage', 'none' ) eq 'de' ) - && AttrVal( $name, 'readingValueLanguage', 'none' ) ne 'en' - ) - { - return $langGermanMapp{$readingValue}; - } - else { - return $readingValue; - } - - return; -} - -sub RigReadingsValue { - my $hash = shift; - my $readingValue = shift; - - my $rigReadingValue; - - if ( $readingValue =~ /^(\d+)-(\d\d)-(\d\d)T(\d\d)/ ) { - $rigReadingValue = Zulu2LocalString($readingValue); - } - else { - $rigReadingValue = ReadingLangGerman( $hash, $readingValue ); - } - - return $rigReadingValue; -} - -sub Zulu2LocalString { - my $t = shift; - - my ( $datehour, $datemin, $rest ) = split( /:/, $t, 3 ); - - my ( $year, $month, $day, $hour, $min ) = - $datehour =~ /(\d+)-(\d\d)-(\d\d)T(\d\d)/; - my $epoch = timegm( 0, 0, $hour, $day, $month - 1, $year ); - - my ( $lyear, $lmonth, $lday, $lhour, $isdst ) = - ( localtime($epoch) )[ 5, 4, 3, 2, -1 ]; - - $lyear += 1900; # year is 1900 based - $lmonth++; # month number is zero based - - if ( defined($rest) ) { - return ( - sprintf( - "%04d-%02d-%02d %02d:%02d:%s", - $lyear, $lmonth, $lday, - $lhour, $datemin, substr( $rest, 0, 2 ) - ) - ); - } - elsif ( $lyear < 2000 ) { - return 'temporarily unavailable'; - } - else { - return ( - sprintf( - "%04d-%02d-%02d %02d:%02d", - $lyear, $lmonth, $lday, $lhour, substr( $datemin, 0, 2 ) - ) - ); - } - - return; -} - -sub SetPredefinedStartPoints { - my $hash = shift; - my $aArg = shift; - - my ( $startpoint_state, $startpoint_num, @morestartpoints ) = @{$aArg}; - - my $name = $hash->{NAME}; - my $payload; - my $abilities; - - if ( defined($startpoint_state) && defined($startpoint_num) ) { - if ( defined( $hash->{helper}{STARTINGPOINTS} ) - && $hash->{helper}{STARTINGPOINTS} ne '' ) - { -# add needed parameters to saved settings config and change the value in request - my $decode_json_settings = - eval { decode_json( $hash->{helper}{STARTINGPOINTS} ) }; - if ($@) { - Log3 $name, 3, -"GardenaSmartBridge ($name) - JSON error while setting startpoint: $@"; - } - - $decode_json_settings->{device} = $hash->{DEVICEID}; - my $setval = $startpoint_state eq 'disable' ? \0 : \1; - $decode_json_settings->{value}[ $startpoint_num - 1 ]{enabled} = - $setval; - - #set more startpoints - if ( - defined scalar(@morestartpoints) - && ( scalar(@morestartpoints) == 2 - || scalar(@morestartpoints) == 4 ) - ) - { - if ( scalar(@morestartpoints) == 2 ) { - $setval = $morestartpoints[0] eq 'disable' ? \0 : \1; - $decode_json_settings->{value}[ $morestartpoints[1] - 1 ] - {enabled} = $setval; - - } - elsif ( scalar(@morestartpoints) == 4 ) { - $setval = $morestartpoints[0] eq 'disable' ? \0 : \1; - $decode_json_settings->{value}[ $morestartpoints[1] - 1 ] - {enabled} = $setval; - $setval = $morestartpoints[2] eq 'disable' ? \0 : \1; - $decode_json_settings->{value}[ $morestartpoints[3] - 1 ] - {enabled} = $setval; - } - } - - $payload = '"settings": ' . encode_json($decode_json_settings); - $abilities = 'mower_settings'; - - #$abilities['service_id'] = $hash->{helper}{STARTINGPOINTID}; - } - else { - return - "startingpoints not loaded yet, please wait a couple of minutes", - undef, undef; - } - } - else { - return - "startpoint usage: set " - . $hash->{NAME} - . " startpoint disable 1 [enable 2] [disable 3]", undef, undef; - } - - return undef, $payload, $abilities; -} - -1; - -=pod - -=item device -=item summary Modul to control GardenaSmart Devices -=item summary_DE Modul zur Steuerung von GardenaSmartgeräten - -=begin html - - -

GardenaSmartDevice

-
    - In combination with GardenaSmartBridge this FHEM Module controls the GardenaSmart Device using the GardenaCloud -

    - Once the Bridge device is created, the connected devices are automatically recognized and created in FHEM.
    - From now on the devices can be controlled and changes in the GardenaAPP are synchronized with the state and readings of the devices. - -


    - Readings -
      -
    • battery-charging - Indicator if the Battery is charged (0/1) or with newer Firmware (false/true)
    • -
    • battery-level - load percentage of the Battery
    • -
    • battery-rechargeable_battery_status - healthyness of the battery (out_of_operation/replace_now/low/ok)
    • -
    • device_info-category - category of device (mower/watering_computer)
    • -
    • device_info-last_time_online - timestamp of last radio contact
    • -
    • device_info-manufacturer - manufacturer
    • -
    • device_info-product - product type
    • -
    • device_info-serial_number - serial number
    • -
    • device_info-sgtin -
    • -
    • device_info-version - firmware version
    • -
    • firmware-firmware_command - firmware command (idle/firmware_cancel/firmware_upload/unsupported)
    • -
    • firmware-firmware_status - firmware status
    • -
    • firmware-firmware_update_start - indicator when a firmwareupload is started
    • -
    • firmware-firmware_upload_progress - progress indicator of firmware update
    • -
    • firmware-inclusion_status - inclusion status
    • -
    • internal_temperature-temperature - internal device temperature
    • -
    • mower-error - actual error message -
        -
      • no_message
      • -
      • outside_working_area
      • -
      • no_loop_signal
      • -
      • wrong_loop_signal
      • -
      • loop_sensor_problem_front
      • -
      • loop_sensor_problem_rear
      • -
      • trapped
      • -
      • upside_down
      • -
      • low_battery
      • -
      • empty_battery
      • -
      • no_drive
      • -
      • lifted
      • -
      • stuck_in_charging_station
      • -
      • charging_station_blocked
      • -
      • collision_sensor_problem_rear
      • -
      • collision_sensor_problem_front
      • -
      • wheel_motor_blocked_right
      • -
      • wheel_motor_blocked_left
      • -
      • wheel_drive_problem_right
      • -
      • wheel_drive_problem_left
      • -
      • cutting_system_blocked
      • -
      • invalid_sub_device_combination
      • -
      • settings_restored
      • -
      • electronic_problem
      • -
      • charging_system_problem
      • -
      • tilt_sensor_problem
      • -
      • wheel_motor_overloaded_right
      • -
      • wheel_motor_overloaded_left
      • -
      • charging_current_too_high
      • -
      • temporary_problem
      • -
      • guide_1_not_found
      • -
      • guide_2_not_found
      • -
      • guide_3_not_found
      • -
      • difficult_finding_home
      • -
      • guide_calibration_accomplished
      • -
      • guide_calibration_failed
      • -
      • temporary_battery_problem
      • -
      • battery_problem
      • -
      • alarm_mower_switched_off
      • -
      • alarm_mower_stopped
      • -
      • alarm_mower_lifted
      • -
      • alarm_mower_tilted
      • -
      • connection_changed
      • -
      • connection_not_changed
      • -
      • com_board_not_available
      • -
      • slipped
      • -
      -
    • -
    • mower-manual_operation - (0/1) or with newer Firmware (false/true)
    • -
    • mower-override_end_time - manual override end time
    • -
    • mower-source_for_next_start - source for the next start -
        -
      • no_source
      • -
      • mower_charging
      • -
      • completed_cutting_autotimer
      • -
      • week_timer
      • -
      • countdown_timer
      • -
      • undefined
      • -
      -
    • -
    • mower-status - mower state (see state)
    • -
    • mower-timestamp_next_start - timestamp of next scheduled start
    • -
    • radio-connection_status - state of connection
    • -
    • radio-quality - percentage of the radio quality
    • -
    • radio-state - radio state (bad/poor/good/undefined)
    • -
    • state - state of the mower -
        -
      • paused
      • -
      • ok_cutting
      • -
      • ok_searching
      • -
      • ok_charging
      • -
      • ok_leaving
      • -
      • wait_updating
      • -
      • wait_power_up
      • -
      • parked_timer
      • -
      • parked_park_selected
      • -
      • off_disabled
      • -
      • off_hatch_open
      • -
      • unknown
      • -
      • error
      • -
      • error_at_power_up
      • -
      • off_hatch_closed
      • -
      • ok_cutting_timer_overridden
      • -
      • parked_autotimer
      • -
      • parked_daily_limit_reached
      • -
      -
    • -
    -

    - - Attributes -
      -
    • readingValueLanguage - Change the Language of Readings (de,en/if not set the default is english and the global language is not set at german)
    • -
    • model -
    • -
    -

    - - set -
      -
    • winter_mode - awake | hibernate
    • -
    -
      -

      mower

      -
    • parkUntilFurtherNotice
    • -
    • parkUntilNextTimer
    • -
    • startOverrideTimer - (in minutes, 60 = 1h, 1440 = 24h, 4320 = 72h)
    • -
    • startResumeSchedule
    • -
    • startpoint enable|disable 1|2|3 - enables or disables one or more predefined start points
    • -
        -
      • set NAME startpoint enable 1
      • -
      • set NAME startpoint disable 3 enable 1
      • -
      -

      irrigation control

      -
    • resumeScheduleValve - start schedule irrigation on valve n
    • -
    • stopScheduleValve - stop schedule irrigation on valve n (Default: 2038-01-18T00:00:00.000Z) | optional params hours (now + hours)
    • -
    • closeAllValves - close all valves
    • -

      water control

      -
    • manualButtonTime - set manual time for button press (in minutes) 0 disable button
    • -
    • stopSchedule - stop schedule for now + n hours (Default: 2038-01-18T00:00:00.000Z)
    • -
    • resumeSchedule - resume schedule
    • -
    -
- -=end html -=begin html_DE - - -

GardenaSmartDevice

-
    - Zusammen mit dem Device GardenaSmartDevice stellt dieses FHEM Modul die Kommunikation zwischen der GardenaCloud und Fhem her. -

    - Wenn das GardenaSmartBridge Device erzeugt wurde, werden verbundene Geräte automatisch erkannt und in Fhem angelegt.
    - Von nun an können die eingebundenen Geräte gesteuert werden. Änderungen in der APP werden mit den Readings und dem Status syncronisiert. - -
-
-
    - Readings -
      -
    • battery-charging - Ladeindikator (0/1) oder mit neuerer Firmware (false/true)
    • -
    • battery-level - Ladezustand der Batterie in Prozent
    • -
    • battery-rechargeable_battery_status - Zustand der Batterie (Ausser Betrieb/Kritischer Batteriestand, wechseln Sie jetzt/Niedrig/oK)
    • -
    • device_info-category - Eigenschaft des Gerätes (Mäher/Bewässerungscomputer/Bodensensor)
    • -
    • device_info-last_time_online - Zeitpunkt der letzten Funkübertragung
    • -
    • device_info-manufacturer - Hersteller
    • -
    • device_info-product - Produkttyp
    • -
    • device_info-serial_number - Seriennummer
    • -
    • device_info-sgtin -
    • -
    • device_info-version - Firmware Version
    • -
    • firmware-firmware_command - Firmware Kommando (Nichts zu tun/Firmwareupload unterbrochen/Firmwareupload/nicht unterstützt)
    • -
    • firmware-firmware_status - Firmware Status
    • -
    • firmware-firmware_update_start - Firmwareupdate (0/1) oder mit neuerer Firmware (false/true)
    • -
    • firmware-firmware_upload_progress - Firmwareupdatestatus in Prozent
    • -
    • firmware-inclusion_status - Einbindungsstatus
    • -
    • internal_temperature-temperature - Interne Geräte Temperatur
    • -
    • mower-error - Aktuelle Fehler Meldung -
        -
      • Kein Fehler
      • -
      • Außerhalb des Arbeitsbereichs
      • -
      • Kein Schleifensignal
      • -
      • Falsches Schleifensignal
      • -
      • Problem Schleifensensor, vorne
      • -
      • Problem Schleifensensor, hinten
      • -
      • Eingeschlossen
      • -
      • Steht auf dem Kopf
      • -
      • Niedriger Batteriestand
      • -
      • Batterie ist leer
      • -
      • Kein Antrieb
      • -
      • Angehoben
      • -
      • Eingeklemmt in Ladestation
      • -
      • Ladestation blockiert
      • -
      • Problem Stoßsensor hinten
      • -
      • Problem Stoßsensor vorne
      • -
      • Radmotor rechts blockiert
      • -
      • Radmotor links blockiert
      • -
      • Problem Antrieb, rechts
      • -
      • Problem Antrieb, links
      • -
      • Schneidsystem blockiert
      • -
      • Fehlerhafte Verbindung
      • -
      • Standardeinstellungen
      • -
      • Elektronisches Problem
      • -
      • Problem Ladesystem
      • -
      • Kippsensorproblem
      • -
      • Rechter Radmotor überlastet
      • -
      • Linker Radmotor überlastet
      • -
      • Ladestrom zu hoch
      • -
      • Vorübergehendes Problem
      • -
      • SK 1 nicht gefunden
      • -
      • SK 2 nicht gefunden
      • -
      • SK 3 nicht gefunden
      • -
      • Problem die Ladestation zu finden
      • -
      • Kalibration des Suchkabels beendet
      • -
      • Kalibration des Suchkabels fehlgeschlagen
      • -
      • Kurzzeitiges Batterieproblem
      • -
      • Batterieproblem
      • -
      • Alarm! Mäher ausgeschalten
      • -
      • Alarm! Mäher gestoppt
      • -
      • Alarm! Mäher angehoben
      • -
      • Alarm! Mäher gekippt
      • -
      • Verbindung geändert
      • -
      • Verbindung nicht geändert
      • -
      • COM board nicht verfügbar
      • -
      • Rutscht
      • -
      -
    • -
    • mower-manual_operation - Manueller Betrieb (0/1) oder mit neuerer Firmware (false/true)
    • -
    • mower-override_end_time - Zeitpunkt wann der manuelle Betrieb beendet ist
    • -
    • mower-source_for_next_start - Grund für den nächsten Start -
        -
      • Kein Grund
      • -
      • Mäher wurde geladen
      • -
      • SensorControl erreicht
      • -
      • Wochentimer erreicht
      • -
      • Stoppuhr Timer
      • -
      • Undefiniert
      • -
      -
    • -
    • mower-status - Mäher Status (siehe state)
    • -
    • mower-timestamp_next_start - Zeitpunkt des nächsten geplanten Starts
    • -
    • radio-connection_status - Status der Funkverbindung
    • -
    • radio-quality - Indikator für die Funkverbindung in Prozent
    • -
    • radio-state - radio state (schlecht/schwach/gut/Undefiniert)
    • -
    • state - Staus des Mähers -
        -
      • Pausiert
      • -
      • Mähen
      • -
      • Suche Ladestation
      • -
      • Lädt
      • -
      • Mähen
      • -
      • Wird aktualisiert ...
      • -
      • Wird eingeschaltet ...
      • -
      • Geparkt nach Zeitplan
      • -
      • Geparkt
      • -
      • Der Mäher ist ausgeschaltet
      • -
      • Deaktiviert. Abdeckung ist offen oder PIN-Code erforderlich
      • -
      • Unbekannter Status
      • -
      • Fehler
      • -
      • Neustart ...
      • -
      • Deaktiviert. Manueller Start erforderlich
      • -
      • Manuelles Mähen
      • -
      • Geparkt durch SensorControl
      • -
      • Abgeschlossen
      • -
      -
    • -
    -

    - - Attribute -
      -
    • readingValueLanguage - Änderung der Sprache der Readings (de,en/wenn nichts gesetzt ist, dann Englisch es sei denn deutsch ist als globale Sprache gesetzt)
    • -
    • model -
    • -
    - - set -
      -
    • winter_mode - aufwäcken (awake)| winterschlaf (hibernate)
    • -
    -
      -

      mäher

      -
    • parkUntilFurtherNotice - Parken des Mähers unter Umgehung des Zeitplans
    • -
    • parkUntilNextTimer - Parken bis zum nächsten Zeitplan
    • -
    • startOverrideTimer - Manuelles mähen (in Minuten, 60 = 1h, 1440 = 24h, 4320 = 72h)
    • -
    • startResumeSchedule - Weiterführung des Zeitplans
    • -
    • startpoint enable|disable 1|2|3 - Aktiviert oder deaktiviert einen vordefinierten Startbereich
    • -
        -
      • set NAME startpoint enable 1
      • -
      • set NAME startpoint disable 3 enable 1
      • -
      -

      irrigation control

      -
    • resumeScheduleValve - Startet Bew&aauml;sserung am Ventil n nach Zeitplan
    • -
    • stopScheduleValve - Setzt Bew&aauml;sserung am Ventil n aus (Default: 2038-01-18T00:00:00.000Z) | Optionaler Parameter Stunden (Jetzt + Stunden)
    • -
    • closeAllValves - Stopt Bew&aauml;sserung an allen Ventilen
    • -

      water control

      -
    • manualButtonTime - setzt die Dauer für den manuellen Knopf (in Minuten) 0 Schaltet den Knopf aus
    • -
    • stopSchedule - Halte Zeitplan an für x Stunden - (Default: 2038-01-18T00:00:00.000Z)
    • -
    • resumeSchedule - Weiterführung des Zeitplans
    • -
    -
- -=end html_DE - -=for :application/json;q=META.json 74_GardenaSmartDevice.pm -{ - "abstract": "Modul to control GardenaSmart Devices", - "x_lang": { - "de": { - "abstract": "Modul zur Steuerung von Gardena Smart Geräten" - } - }, - "keywords": [ - "fhem-mod-device", - "fhem-core", - "Garden", - "Gardena", - "Smart" - ], - "release_status": "stable", - "license": "GPL_2", - "version": "v2.5.5", - "author": [ - "Marko Oldenburg " - ], - "x_fhem_maintainer": [ - "CoolTux" - ], - "x_fhem_maintainer_github": [ - "LeonGaultier" - ], - "prereqs": { - "runtime": { - "requires": { - "FHEM": 5.00918799, - "perl": 5.016, - "Meta": 0, - "JSON": 0, - "Time::Local": 0 - }, - "recommends": { - }, - "suggests": { - } - } - } -} -=end :application/json;q=META.json - -=cut +############################################################################### +# +# Developed with VSCodium and richterger perl plugin. +# +# (c) 2017-2022 Copyright: Marko Oldenburg (fhemdevelopment at cooltux dot net) +# All rights reserved +# +# Special thanks goes to comitters: +# - Michael (mbrak) Thanks for Commandref +# - Christian (zife) Thanks for Commandref +# - Matthias (Kenneth) Thanks for Wiki entry +# - BioS Thanks for predefined start points Code +# - fettgu Thanks for Debugging Irrigation Control data flow +# - Sebastian (BOFH) Thanks for new Auth Code after API Change +# +# +# This script 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 +# any later version. +# +# The GNU General Public License can be found at +# http://www.gnu.org/copyleft/gpl.html. +# A copy is found in the textfile GPL.txt and important notices to the license +# from the author is found in LICENSE.txt distributed with these scripts. +# +# This script 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. +# +# +# $Id$ +# +############################################################################### +## +## +## Das JSON Modul immer in einem eval aufrufen +# $data = eval{decode_json($data)}; +# +# if($@){ +# Log3($SELF, 2, "$TYPE ($SELF) - error while request: $@"); +# +# readingsSingleUpdate($hash, "state", "error", 1); +# +# return; +# } +# +# +###### Wichtige Notizen +# +# apt-get install libio-socket-ssl-perl +# http://www.dxsdata.com/de/2016/07/php-class-for-gardena-smart-system-api/ +# +## +## + +## unserer packagename +package FHEM::GardenaSmartDevice; +use GPUtils qw(GP_Import GP_Export); + +use strict; +use warnings; +use POSIX; +use FHEM::Meta; +use Time::Local; +use Time::Piece; +use Time::Seconds; + +# try to use JSON::MaybeXS wrapper +# for chance of better performance + open code +eval { + require JSON::MaybeXS; + import JSON::MaybeXS qw( decode_json encode_json ); + 1; +} or do { + + # try to use JSON wrapper + # for chance of better performance + eval { + # JSON preference order + local $ENV{PERL_JSON_BACKEND} = + 'Cpanel::JSON::XS,JSON::XS,JSON::PP,JSON::backportPP' + unless ( defined( $ENV{PERL_JSON_BACKEND} ) ); + + require JSON; + import JSON qw( decode_json encode_json ); + 1; + } or do { + + # In rare cases, Cpanel::JSON::XS may + # be installed but JSON|JSON::MaybeXS not ... + eval { + require Cpanel::JSON::XS; + import Cpanel::JSON::XS qw(decode_json encode_json); + 1; + } or do { + + # In rare cases, JSON::XS may + # be installed but JSON not ... + eval { + require JSON::XS; + import JSON::XS qw(decode_json encode_json); + 1; + } or do { + + # Fallback to built-in JSON which SHOULD + # be available since 5.014 ... + eval { + require JSON::PP; + import JSON::PP qw(decode_json encode_json); + 1; + } or do { + + # Fallback to JSON::backportPP in really rare cases + require JSON::backportPP; + import JSON::backportPP qw(decode_json encode_json); + 1; + }; + }; + }; + }; +}; + +## Import der FHEM Funktionen +#-- Run before package compilation +BEGIN { + + # Import from main context + GP_Import( + qw(readingsSingleUpdate + readingsBulkUpdate + readingsBulkUpdateIfChanged + readingsBeginUpdate + readingsEndUpdate + Log3 + CommandAttr + AttrVal + ReadingsVal + readingFnAttributes + AssignIoPort + modules + IOWrite + defs + makeDeviceName) + ); +} + +#-- Export to main context with different name +GP_Export( + qw( + Initialize + ) +); + +sub Initialize { + my $hash = shift; + + $hash->{Match} = '^{"id":".*'; + + $hash->{SetFn} = \&Set; + $hash->{DefFn} = \&Define; + $hash->{UndefFn} = \&Undef; + $hash->{ParseFn} = \&Parse; + + $hash->{AttrFn} = \&Attr; + $hash->{AttrList} = + "readingValueLanguage:de,en " + . "model:watering_computer,sensor,sensor2,mower,ic24,power,electronic_pressure_pump " + . "extendedState:0,1 " + . "IODev " + . $readingFnAttributes; + $hash->{parseParams} = 1; + + return FHEM::Meta::InitMod( __FILE__, $hash ); +} + +sub Define { + my $hash = shift // return; + my $aArg = shift // return; + + return $@ unless ( FHEM::Meta::SetInternals($hash) ); + use version 0.60; our $VERSION = FHEM::Meta::Get( $hash, 'version' ); + + return + "too few parameters: define GardenaSmartDevice " + if ( scalar( @{$aArg} ) < 3 ); + + my $name = $aArg->[0]; + my $deviceId = $aArg->[2]; + my $category = $aArg->[3]; + + $hash->{DEVICEID} = $deviceId; + $hash->{VERSION} = version->parse($VERSION)->normal; + $hash->{helper}{STARTINGPOINTID} = ''; + $hash->{helper}{schedules_paused_until_id} = ''; + $hash->{helper}{eco_mode_id} = ''; + $hash->{helper}{button_config_time_id} = ''; + $hash->{helper}{winter_mode_id} = ''; + # Electroni Pressure Pump + $hash->{helper}{operating_mode_id} = ''; + $hash->{helper}{leakage_detection_id} = ''; + $hash->{helper}{turn_on_pressure_id} = ''; + + + $hash->{helper}{_id} = ''; + + # IrrigationControl valve control max 6 + $hash->{helper}{schedules_paused_until_1_id} = ''; + $hash->{helper}{schedules_paused_until_2_id} = ''; + $hash->{helper}{schedules_paused_until_3_id} = ''; + $hash->{helper}{schedules_paused_until_4_id} = ''; + $hash->{helper}{schedules_paused_until_5_id} = ''; + $hash->{helper}{schedules_paused_until_6_id} = ''; + + CommandAttr( undef, + "$name IODev $modules{GardenaSmartBridge}{defptr}{BRIDGE}->{NAME}" ) + if ( AttrVal( $name, 'IODev', 'none' ) eq 'none' ); + + my $iodev = AttrVal( $name, 'IODev', 'none' ); + + AssignIoPort( $hash, $iodev ) if ( !$hash->{IODev} ); + + if ( defined( $hash->{IODev}->{NAME} ) ) { + Log3 $name, 3, "GardenaSmartDevice ($name) - I/O device is " + . $hash->{IODev}->{NAME}; + } + else { + Log3 $name, 1, "GardenaSmartDevice ($name) - no I/O device"; + } + + $iodev = $hash->{IODev}->{NAME}; + + my $d = $modules{GardenaSmartDevice}{defptr}{$deviceId}; + + return +"GardenaSmartDevice device $name on GardenaSmartBridge $iodev already defined." + if ( defined($d) + && $d->{IODev} == $hash->{IODev} + && $d->{NAME} ne $name ); + + CommandAttr( undef, $name . ' room GardenaSmart' ) + if ( AttrVal( $name, 'room', 'none' ) eq 'none' ); + + CommandAttr( undef, $name . ' model ' . $category ) + if ( AttrVal( $name, 'model', 'none' ) eq 'none' ); + + Log3 $name, 3, +"GardenaSmartDevice ($name) - defined GardenaSmartDevice with DEVICEID: $deviceId"; + readingsSingleUpdate( $hash, 'state', 'initialized', 1 ); + + $modules{GardenaSmartDevice}{defptr}{$deviceId} = $hash; + + return; +} + +sub Undef { + my $hash = shift; + my $arg = shift; + + my $name = $hash->{NAME}; + my $deviceId = $hash->{DEVICEID}; + + delete $modules{GardenaSmartDevice}{defptr}{$deviceId}; + + return; +} + +sub Attr { + + my ( $cmd, $name, $attrName, $attrVal ) = @_; + my $hash = $defs{$name}; + + return; +} + +sub Set { + my $hash = shift // return; + my $aArg = shift // return; + + my $name = shift @$aArg; + my $cmd = shift @$aArg + // return qq{"set $name" needs at least one argument}; + + my $payload; + my $abilities; + my $service_id; + my $mainboard_version = + ReadingsVal( $name, 'mower_type-mainboard_version', 0.0 ); + + my ($Sekunden, $Minuten, $Stunden, $Monatstag, $Monat, + $Jahr, $Wochentag, $Jahrestag, $Sommerzeit) = localtime(time); + + my $timezone_offset = $Sommerzeit ? 0 : ( Time::Piece->new )->tzoffset; + + #set default abilitie ... overwrite in cmd to change + $abilities = 'mower' + if ( AttrVal( $name, 'model', 'unknown' ) eq 'mower' ); + $abilities = 'watering' + if ( AttrVal( $name, 'model', 'unknown' ) eq 'ic24' + || AttrVal( $name, 'model', 'unknown' ) eq 'watering_computer' ); + $abilities = 'power' + if ( AttrVal( $name, 'model', 'unknown' ) eq 'power' ); + $abilities = 'watering' + if ( AttrVal( $name, 'model', 'unknown' ) eq 'electronic_pressure_pump' ); + + ### mower + # service_id (eco, parkuntilfurhternotice, startpoints) + if ( lc $cmd eq 'parkuntilfurthernotice' ) { + $payload = '"name":"park_until_further_notice"'; + if ( $mainboard_version > 10.30 ) { + $payload = +' "settings":{"name":"schedules_paused_until","value":"2038-01-18T00:00:00.000Z","device":"' + . $hash->{DEVICEID} . '"}'; + $abilities = 'mower_settings'; + $service_id = $hash->{helper}{schedules_paused_until_id}; + } + } + elsif ( lc $cmd eq 'parkuntilnexttimer' ) { + $payload = '"name":"park_until_next_timer"'; + if ( $mainboard_version > 10.30 ) { + $payload = '"properties":{"name":"mower_timer","value":0}'; + $abilities = 'mower_timer'; + } + } + elsif ( lc $cmd eq 'startresumeschedule' ) { + $payload = '"name":"start_resume_schedule"'; + if ( $mainboard_version > 10.30 ) { + $payload = +' "settings":{"name":"schedules_paused_until","value":"","device":"' + . $hash->{DEVICEID} . '"}'; + $abilities = 'mower_settings'; + $service_id = $hash->{helper}{schedules_paused_until_id}; + } + } + elsif ( lc $cmd eq 'startoverridetimer' ) { + $payload = '"name":"start_override_timer","parameters":{"duration":' + . $aArg->[0] * 60 . '}'; + if ( $mainboard_version > 10.30 ) { + $payload = '"properties":{"name":"mower_timer","value":' + . $aArg->[0] * 60 . '}'; + $abilities = 'mower_timer'; + } + + } + elsif ( lc $cmd eq 'startpoint' ) { + my $err; + ( $err, $payload, $abilities ) = + SetPredefinedStartPoints( $hash, $aArg ); + $service_id = $hash->{helper}{STARTINGPOINTID}; + return $err if ( defined($err) ); + } + elsif ( lc $cmd eq 'eco' ) { + $payload = + '"settings": {"name": "eco_mode", "value": ' + . $aArg->[0] + . ', "device": "' + . $hash->{DEVICEID} . '"}'; + $abilities = 'mower_settings' if ( $mainboard_version > 10.30 ); + $service_id = $hash->{helper}{eco_mode_id}; + +#$abilities['service_id'] = $hash->{helper}{SCHEDULESID} if ( $mainboard_version > 10.30 ); + } + ### electronic_pressure_pump + # elsif ( lc $cmd eq 'pumptimer' ) { + # $payload = + # '"name":"pump_manual_watering_timer","parameters":{"duration":' + # . $aArg->[0] . '}'; + # } + ### watering_computer & electronic pump + elsif ( lc $cmd eq 'manualoverride' ) { + $payload = + '"properties":{"name":"watering_timer_1' + . '","value":{"state":"manual","duration":' + . $aArg->[0] * 60 + . ',"valve_id":1}}'; + } + elsif ( lc $cmd eq 'manualbuttontime' ) { + $service_id = $hash->{helper}{button_config_time_id}; + $payload = + '"properties":{"name":"button_config_time",' + . '"value":' + . $aArg->[0] * 60 + . ',"timestamp":"2021-05-26T19:06:23.680Z"' + . ',"at_bound":null,"unit":"seconds","ability":"' + . $service_id . '"}'; + $abilities = 'watering_button_config'; + } + elsif ( $cmd =~ m{\AcancelOverride}xms ) { + + my $valve_id = 1; + + if ( $cmd =~ m{\AcancelOverrideValve(\d)\z}xms ) { + $valve_id = $1; + } + + $payload = + '"properties":{"name":"watering_timer_' + . $valve_id + . '","value":{"state":"idle","duration":' + . 0 + . ',"valve_id":' + . $valve_id . '}}'; + } + elsif ( $cmd =~ /.*Schedule$/ ) { + my $duration = ( + ( + defined( $aArg->[0] ) + ? ( + ( + ( Time::Piece->new ) + + ( ONE_HOUR * $aArg->[0] ) - + $timezone_offset + )->datetime + ) + . '.000Z' + : '2038-01-18T00:00:00.000Z' + ) + ); + + $abilities = 'wateringcomputer_settings'; + $service_id = $hash->{helper}->{'schedules_paused_until_id'}; + $payload = + '"settings":{"name":"schedules_paused_until"' + . ', "value":"' + . ( $cmd eq 'resumeSchedule' ? '' : $duration ) + . '","device":"' + . $hash->{DEVICEID} . '"}'; + } + elsif ( lc $cmd eq 'on' || lc $cmd eq 'off' || lc $cmd eq 'on-for-timer' ) { + my $val = ( + scalar( !@$aArg == 0 ) && ref($aArg) eq 'ARRAY' + ? $aArg->[0] * 60 + : lc $cmd + ); + + $payload = + '"properties":{"name":"power_timer", "value":"' . $val . '"}'; + } + ### Watering ic24 + elsif ( $cmd =~ m{\AmanualDurationValve\d\z}xms ) { + my $valve_id; + + if ( $cmd =~ m{\AmanualDurationValve(\d)\z}xms ) { + $valve_id = $1; + } + + $payload = + '"properties":{"name":"watering_timer_' + . $valve_id + . '","value":{"state":"manual","duration":' + . $aArg->[0] * 60 + . ',"valve_id":' + . $valve_id . '}}'; + } + elsif ( $cmd eq 'closeAllValves' ) { + $payload = '"name":"close_all_valves","parameters":{}'; + } + elsif ( $cmd =~ /.*ScheduleValve$/ ) { + my $valve_id = $aArg->[0]; + my $duration = ( + ( + defined( $aArg->[1] ) + ? ( + ( + ( Time::Piece->new ) + + ( ONE_HOUR * $aArg->[1] ) - + $timezone_offset + )->datetime + ) + . '.000Z' + : '2038-01-18T00:00:00.000Z' + ) + ); + + $abilities = 'irrigation_settings'; + $service_id = + $hash->{helper}->{ 'schedules_paused_until_' . $valve_id . '_id' }; + $payload = + '"settings":{"name":"schedules_paused_until_' + . $valve_id + . '", "value":"' + . ( $cmd eq 'resumeScheduleValve' ? '' : $duration ) + . '","device":"' + . $hash->{DEVICEID} . '"}'; + } + ### Watering_pressure_pump + elsif ( lc $cmd eq 'operating_mode') { + my $op_mode = $aArg->[0]; + $payload = '"settings":{"name":"operating_mode",' + .'"value":"'.$op_mode.'",' + .'"device":"' + . $hash->{DEVICEID}.'"}'; + $abilities = 'watering_pressure_pump_settings'; + $service_id = $hash->{helper}->{ 'operating_mode_id' }; + } + elsif ( lc $cmd eq 'leakage_detection') { + my $leakdetection_mode = $aArg->[0]; + $payload = '"settings":{"name":"leakage_detection",' + .'"value":"'.$leakdetection_mode.'",' + .'"device":"' + . $hash->{DEVICEID}.'"}'; + $abilities = 'watering_pressure_pump_settings'; + $service_id = $hash->{helper}->{ 'leakage_detection_id' }; + } + elsif ( lc $cmd eq 'turn_on_pressure') { + my $turnonpressure = $aArg->[0]; + $payload = '"settings":{"name":"turn_on_pressure",' + .'"value":"'.$turnonpressure.'",' + .'"device":"' + . $hash->{DEVICEID}.'"}'; + $abilities = 'watering_pressure_pump_settings'; + $service_id = $hash->{helper}->{ 'turn_on_pressure_id' }; + } + elsif ( lc $cmd eq 'resetvalveerrors') { + $payload = '"name":"reset_valve_errors",' + .' "parameters": {}'; + $abilities = 'error'; + } + + ### Sensors + elsif ( lc $cmd eq 'refresh' ) { + + my $sensname = $aArg->[0]; + if ( lc $sensname eq 'temperature' ) { + if ( ReadingsVal( $name, 'device_info-category', 'sensor' ) eq + 'sensor' ) + { + $payload = '"name":"measure_ambient_temperature"'; + $abilities = 'ambient_temperature'; + } + else { + $payload = '"name":"measure_soil_temperature"'; + $abilities = 'soil_temperature'; + } + } + elsif ( lc $sensname eq 'light' ) { + $payload = '"name":"measure_light"'; + $abilities = 'light'; + + } + elsif ( lc $sensname eq 'humidity' ) { + $payload = '"name":"measure_soil_humidity"'; + $abilities = 'humidity'; + } + } + ## winter sleep + elsif ( lc $cmd eq 'winter_mode' ) { + $payload = + '"settings":{"name":"winter_mode","value":"' + . $aArg->[0] + . '","device":"' + . $hash->{DEVICEID} . '"}'; + $abilities = 'winter_settings'; + $service_id = $hash->{helper}->{'winter_mode_id'}; + } + else { + + my $list = ''; + + $list .= +'parkUntilFurtherNotice:noArg parkUntilNextTimer:noArg startResumeSchedule:noArg startOverrideTimer:slider,0,1,240 startpoint' + if ( AttrVal( $name, 'model', 'unknown' ) eq 'mower' ); + + $list .= +'manualOverride:slider,1,1,59 cancelOverride:noArg resumeSchedule:noArg stopSchedule manualButtonTime:slider,0,2,100' + if ( AttrVal( $name, 'model', 'unknown' ) eq 'watering_computer' ); + + + $list .= 'manualOverride:slider,1,1,90 cancelOverride:noArg operating_mode:automatic,scheduled leakage_detection:watering,washing_machine,domestic_water_supply,off turn_on_pressure:slider,2,0.2,3.0,1 resetValveErrors:noArg' + if ( AttrVal( $name, 'model', 'unknown' ) eq 'electronic_pressure_pump' ); + + $list .= +'closeAllValves:noArg stopScheduleValve:select,'.ReadingsVal( $name, 'ic24-valves_connected', '1' ).' resumeScheduleValve:select,'.ReadingsVal( $name, 'ic24-valves_connected', '1' ) + if ( AttrVal( $name, 'model', 'unknown' ) eq 'ic24' ); + + foreach my $valve (split(',', ReadingsVal( $name, 'ic24-valves_connected', '1'))) { + $list .= ' manualDurationValve'.$valve.':slider,1,1,90 ' + if ( AttrVal( $name, 'model', 'unknown' ) eq 'ic24' ); + } + + foreach my $valve (split(',', ReadingsVal( $name, 'ic24-valves_connected', '1'))) { + $list .= ' cancelOverrideValve'.$valve.':noArg ' + if ( AttrVal( $name, 'model', 'unknown' ) eq 'ic24' ); + } + + $list .= 'refresh:temperature,humidity' + if ( AttrVal( $name, 'model', 'unknown' ) =~ /sensor.?/ ); + + # add light for old sensors + $list .= ',light' + if ( AttrVal( $name, 'model', 'unknown' ) eq 'sensor' + && ReadingsVal( $name, 'device_info-category', 'unknown' ) eq + 'sensor' ); + + $list .= 'on:noArg off:noArg on-for-timer:slider,0,1,720' + if ( AttrVal( $name, 'model', 'unknown' ) eq 'power' ); + + # all devices has abilitie to fall a sleep + $list .= ' winter_mode:awake,hibernate'; + return "Unknown argument $cmd, choose one of $list"; + } + + $hash->{helper}{deviceAction} = $payload; + readingsSingleUpdate( $hash, "state", "send command to gardena cloud", 1 ); + + IOWrite( $hash, $payload, $hash->{DEVICEID}, $abilities, $service_id ); + Log3 $name, 4, +"GardenaSmartBridge ($name) - IOWrite: $payload $hash->{DEVICEID} $abilities IODevHash=$hash->{IODev}"; + + return; +} + +sub Parse { + my $io_hash = shift; + my $json = shift; + + my $name = $io_hash->{NAME}; + + my $decode_json = eval { decode_json($json) }; + if ($@) { + Log3 $name, 3, + "GardenaSmartDevice ($name) - JSON error while request: $@"; + } + + Log3 $name, 4, "GardenaSmartDevice ($name) - ParseFn was called"; + Log3 $name, 4, "GardenaSmartDevice ($name) - JSON: $json"; + + if ( defined( $decode_json->{id} ) ) { + + my $deviceId = $decode_json->{id}; + + if ( my $hash = $modules{GardenaSmartDevice}{defptr}{$deviceId} ) { + my $name = $hash->{NAME}; + + WriteReadings( $hash, $decode_json ); + Log3 $name, 4, + "GardenaSmartDevice ($name) - find logical device: $hash->{NAME}"; + + return $hash->{NAME}; + + } + else { + + Log3 $name, 3, + "GardenaSmartDevice ($name) - autocreate new device " + . makeDeviceName( $decode_json->{name} ) + . " with deviceId $decode_json->{id}, model $decode_json->{category}"; + return + "UNDEFINED " + . makeDeviceName( $decode_json->{name} ) + . " GardenaSmartDevice $decode_json->{id} $decode_json->{category}"; + } + } + + return; +} + +sub WriteReadings { + my $hash = shift; + my $decode_json = shift; + + my $name = $hash->{NAME}; + my $abilities = scalar( @{ $decode_json->{abilities} } ); + my $settings = scalar( @{ $decode_json->{settings} } ); + my $scheduled_events = scalar( @{ $decode_json->{scheduled_events} } ); + + readingsBeginUpdate($hash); + + do { + + if ( + ref( $decode_json->{abilities}[$abilities]{properties} ) eq "ARRAY" + && scalar( @{ $decode_json->{abilities}[$abilities]{properties} } ) + > 0 ) + { + for my $propertie ( + @{ $decode_json->{abilities}[$abilities]{properties} } ) + { + if ( + exists( $decode_json->{abilities}[$abilities]{name} ) + && ( $decode_json->{abilities}[$abilities]{name} eq + 'watering' ) + ) + { + + if ( $propertie->{name} eq 'button_config_time' ) { + if ( $hash->{helper}{ $propertie->{name} . '_id' } ne + $decode_json->{abilities}[$abilities]{id} ) + { + $hash->{helper}{ $propertie->{name} . '_id' } = + $decode_json->{abilities}[$abilities]{id}; + } + readingsBulkUpdateIfChanged( + $hash, + 'manualButtonTime', + ( + RigReadingsValue( + $hash, $propertie->{value} / 60 + ) + ) + ); + next; + } + } + + readingsBulkUpdateIfChanged( + $hash, + $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name}, + (defined ($propertie->{value} ) eq '') ? RigReadingsValue( $hash, 'n/a') : RigReadingsValue( $hash, $propertie->{value} ) + ) + if ( exists( $propertie->{value} ) + && $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} ne 'radio-quality' + && $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} ne 'battery-level' + && $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} ne 'internal_temperature-temperature' + && $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} ne 'ambient_temperature-temperature' + && $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} ne 'soil_temperature-temperature' + && $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} ne 'humidity-humidity' + && $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} ne 'light-light' + && ref( $propertie->{value} ) ne "HASH" ); + + readingsBulkUpdateIfChanged( + $hash, + $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name}, + RigReadingsValue( $hash, $propertie->{value} ) + ) + if ( + defined( $propertie->{value} ) + && ( $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} eq 'radio-quality' + || $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} eq 'battery-level' + || $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} eq + 'internal_temperature-temperature' + || $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} eq + 'ambient_temperature-temperature' + || $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} eq 'soil_temperature-temperature' + || $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} eq 'humidity-humidity' + || $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} eq 'light-light' ) + ); + + readingsBulkUpdateIfChanged( + $hash, + $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} + . '_timestamp', + Time::Piece->strptime( + RigReadingsValue( $hash, $propertie->{timestamp} ), + "%Y-%m-%d %H:%M:%S" )->strftime('%s') + + ) + if ( + defined( $propertie->{value} ) + && ( $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} eq 'mower_timer-mower_timer' ) + ); + + readingsBulkUpdateIfChanged( + $hash, + $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name}, + join( ',', @{ $propertie->{value} } ) + ) + if ( defined( $propertie->{value} ) + && $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} eq 'ic24-valves_connected' ); + + readingsBulkUpdateIfChanged( + $hash, + $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name}, + join( ',', @{ $propertie->{value} } ) + ) + if ( defined( $propertie->{value} ) + && $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} eq 'ic24-valves_master_config' ); + + if ( ref( $propertie->{value} ) eq "HASH" ) { + my $sub_state = 0; my $sub_value = 0; + while ( my ( $r, $v ) = each %{ $propertie->{value} } ) { + if ( ref( $v ) ne "HASH" ) { + readingsBulkUpdate( + $hash, + $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} . '_' + . $r, + RigReadingsValue( $hash, $v ) + ); + } else { + while ( my ( $i_r, $i_v ) = each %{ $v } ) { + readingsBulkUpdate( + $hash, + $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} . '_' + . $r . '_' . $i_r, + RigReadingsValue( $hash, $i_v ) + ); + } + } + } + } + # ic24 and other watering devices calc irrigation left in sec + readingsBulkUpdateIfChanged( + $hash, + $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} + . '_irrigation_left', + ( $propertie->{value}{duration} > 0 ) ? (Time::Piece::localtime->strptime( + RigReadingsValue($hash, $propertie->{timestamp}), "%Y-%m-%d %H:%M:%S") + + ($propertie->{value}{duration} + 3 ) - Time::Piece::localtime->new) : 0 + ) + if ( defined( $propertie->{value} ) + && $decode_json->{abilities}[$abilities]{name} eq 'watering' + ); + } + } + + $abilities--; + } while ( $abilities >= 0 ); + + + if ( + exists( $decode_json->{scheduled_events} ) + # && scalar ($decode_json->{scheduled_events} ) > 0 + && ref ($decode_json->{scheduled_events}) eq 'ARRAY' ) { + readingsBulkUpdateIfChanged( $hash, 'scheduling-schedules_events_count', + scalar( @{$decode_json->{scheduled_events} } ) ); + my $valve_id =1; my $event_id = 1; # ic24 [1..6] | wc, pump [1] + + for my $event_schedules ( @{ $decode_json->{scheduled_events} } ) { + $valve_id = $event_schedules->{valve_id} if ( exists($event_schedules->{valve_id} ) ); #ic24 + $event_id++; # event id + + while ( my ( $r, $v ) = each %{ $event_schedules } ) { + readingsBulkUpdateIfChanged( $hash, 'scheduling-schedules_event_' + . $event_id + . '_valve_' + . $valve_id + . '_' + . $r, + $v) if (ref($v) ne 'HASH' ); + readingsBulkUpdateIfChanged( $hash, 'scheduling-schedules_event_' + . $event_id + . '_valve_' + . $valve_id + . '_' + . $v->{type}, + join(',', @ { $v->{weekdays}}) ) if (ref($v) eq 'HASH' ); + }; + }; + + }; # fi scheduled_events + + my $winter_mode; + + do { +#Log3 $name, 1, "Settings pro Device : ".$decode_json->{settings}[$settings]{name}; +#Log3 $name, 1, " - KEIN ARRAY" if ( ref( $decode_json->{settings}[$settings]{value} ) ne "ARRAY"); +#Log3 $name, 1, " - IST ARRAY" if ( ref( $decode_json->{settings}[$settings]{value} ) eq "ARRAY"); + + if ( + exists( $decode_json->{settings}[$settings]{name} ) + && ( $decode_json->{settings}[$settings]{name} =~ + /schedules_paused_until_?\d?$/ + || $decode_json->{settings}[$settings]{name} eq 'eco_mode' + || $decode_json->{settings}[$settings]{name} eq 'winter_mode' + || $decode_json->{settings}[$settings]{name} eq 'operating_mode' + || $decode_json->{settings}[$settings]{name} eq 'leakage_detection' + || $decode_json->{settings}[$settings]{name} eq 'turn_on_pressure' ) + ) + { + if ( $hash->{helper} + { $decode_json->{settings}[$settings]{name} . '_id' } ne + $decode_json->{settings}[$settings]{id} ) + { + $hash->{helper} + { $decode_json->{settings}[$settings]{name} . '_id' } = + $decode_json->{settings}[$settings]{id}; + } + # check watering controler single schedules pause until + if ( $decode_json->{settings}[$settings]{name} eq 'schedules_paused_until' ) { + readingsBulkUpdateIfChanged( $hash, 'scheduling-schedules_paused_until', + $decode_json->{settings}[$settings]{value} ); + } + ##### + #ic24 schedules pause until + if ($decode_json->{settings}[$settings]{name} =~ /schedules_paused_until_?(\d)?$/) { + #my $ventil = substr($decode_json->{settings}[$settings]{name}, -1); # => 1 - 6 + # check if empty, clear scheduling-scheduled_watering_next_start_x + readingsBulkUpdateIfChanged( $hash, 'scheduling-'.$decode_json->{settings}[$settings]{name}, + $decode_json->{settings}[$settings]{value} ); + # CommandAttr( undef, $name . " scheduling-scheduled_watering_next_start_") if ($decode_json->{settings}[$settings]{value} eq '' ) + } +#TODO: Readings und Setter ?! + # save electronid pressure pump settings as readings + if ( $decode_json->{settings}[$settings]{name} eq 'operating_mode' + || $decode_json->{settings}[$settings]{name} eq 'leakage_detection' + || $decode_json->{settings}[$settings]{name} eq 'turn_on_pressure' ) { + readingsBulkUpdateIfChanged( $hash, $decode_json->{settings}[$settings]{name}, + $decode_json->{settings}[$settings]{value} ); + + } + # save winter mode as reading + if ( $decode_json->{settings}[$settings]{name} eq 'winter_mode' ) { + readingsBulkUpdateIfChanged( $hash, 'winter_mode', + $decode_json->{settings}[$settings]{value} ); + + $winter_mode = $decode_json->{settings}[$settings]{value}; + } + } + + if ( defined( $decode_json->{settings}[$settings]{name} ) + && $decode_json->{settings}[$settings]{name} eq 'valve_names' + && ref( $decode_json->{settings}[$settings]{value} ) eq "ARRAY" ) { # or HASH ? + my @valves = @{$decode_json->{settings}[$settings]{value}}; + foreach my $valve( @valves ) { + Log3 $name, 4, "GardenaSmartDevice ($name) valve_name $valve->{'name'}"; + readingsBulkUpdateIfChanged( $hash, 'valve-valve_name_'.$valve->{"id"}, + $valve->{"name"} ); + } + } + + if ( ref( $decode_json->{settings}[$settings]{value} ) eq "ARRAY" + && $decode_json->{settings}[$settings]{name} eq 'starting_points' ) + { + #save the startingpointid needed to update the startingpoints + if ( $hash->{helper}{STARTINGPOINTID} ne + $decode_json->{settings}[$settings]{id} ) + { + $hash->{helper}{STARTINGPOINTID} = + $decode_json->{settings}[$settings]{id}; + } + + $hash->{helper}{STARTINGPOINTS} = + '{ "name": "starting_points", "value": ' + . encode_json( $decode_json->{settings}[$settings]{value} ) . '}'; + my $startpoint_cnt = 0; + + for my $startingpoint ( + @{ $decode_json->{settings}[$settings]{value} } ) + { + $startpoint_cnt++; + readingsBulkUpdateIfChanged( + $hash, + 'startpoint-' . $startpoint_cnt . '-enabled', + $startingpoint->{enabled} + ); + } + } + + $settings--; + } while ( $settings >= 0 ); + + if ( $winter_mode ne 'hibernate' ) { + setState($hash); + } + else { + readingsBulkUpdate( $hash, 'state', + RigReadingsValue( $hash, 'hibernate' ) ); + } + + readingsEndUpdate( $hash, 1 ); + + Log3 $name, 4, "GardenaSmartDevice ($name) - readings was written"; + + return; +} + +sub setState { + my $hash = shift; + my $name = $hash->{NAME}; + + my $online_state = + ReadingsVal( $name, 'device_info-connection_status', 'unknown' ); + + #online state mower + readingsBulkUpdate( $hash, 'state', + $online_state eq 'online' + ? ReadingsVal( $name, 'mower-status', 'readingsValError' ) + : 'offline' ) + if ( AttrVal( $name, 'model', 'unknown' ) eq 'mower' ); + + # ic24 / wc / electronic pump + + if ( AttrVal( $name, 'model', 'unknown' ) eq 'ic24' + || AttrVal( $name, 'model', 'unknown' ) eq 'watering_computer' + || AttrVal( $name, 'model', 'unknown' ) eq 'electronic_pressure_pump' ){ + my @opened_valves; + my $state_string = ''; my $nearst_irrigation = '2999-12-12 12:00'; + my $has_schedule = 0; my $longest_duration = 0; my $processed_item = ''; + my $error_type = 'ok'; + my @valves_connected = AttrVal( $name, 'model', 'unknown' ) eq 'ic24' ? split(',', ReadingsVal( $name, 'ic24-valves_connected', '')) : '1'; + + $has_schedule = 1 if ( ReadingsVal($name, 'scheduling-schedules_events_count', '') ne '' ); + for (@valves_connected){ # valves 1 or 1..6 + ## add to opened ventils, if watering active + push @opened_valves, $_ if ( ( ( ReadingsVal( $name, "watering-watering_timer_".$_."_duration", 0 ) =~ m{\A[1-9]([0-9]+)?\z}xms ) ? $_ : 0 ) > 0 ); + ## set error type (pumpe required) + $error_type = ReadingsVal( $name, 'error-valve_error_'.$_.'_type', 'ok' ) if (ReadingsVal( $name, 'error-valve_error_'.$_.'_type', 'ok' ) ne 'ok'); + ## find longest irrigation duration + $longest_duration = ReadingsVal( $name, "watering-watering_timer_".$_."_irrigation_left", 0 ) if ( + ( ReadingsVal( $name, "watering-watering_timer_".$_."_duration", 0 ) =~ m{\A[1-9]([0-9]+)?\z}xms + && ReadingsVal( $name, "watering-watering_timer_".$_."_duration", 0 ) > 0 + && ReadingsVal( $name, "watering-watering_timer_".$_."_duration", 0 ) > $longest_duration ) ); + + # y-m-d h:m + $processed_item = AttrVal( $name, 'model', 'unknown' ) eq 'ic24' + ? RigReadingsValue($hash, ReadingsVal($name, 'scheduling-schedules_paused_until_'.$_, '')) + : RigReadingsValue($hash, ReadingsVal($name, 'scheduling-schedules_paused_until', '')); + + Log3 $name, 5, "[DEBUG] - process: $processed_item"; + Log3 $name, 5, "[DEBUG] - next_start: ". ReadingsVal($name, 'scheduling-scheduled_watering_next_start', ''); # n/a RigReadingsValue( $hash, 'n/a') + # $nearst_irrigation = RigReadingsValue($hash, ReadingsVal($name, 'scheduling-schedules_paused_until_'.$_, '')) + if ( ReadingsVal($name, 'scheduling-scheduled_watering_next_start', '') eq RigReadingsValue( $hash, 'n/a') ) { # non next start, schedules paused permanently or next schedule > 1 year; get nearst paused_until + Log3 $name, 5, "[DEBUG] - next_start: empty "; + Log3 $name, 5, "[DEBUG] - empty pro item ".Time::Piece->strptime( $processed_item, "%Y-%m-%d %H:%M:%S"); + Log3 $name, 5, "[DEBUG] - empty nearst ".Time::Piece->strptime( $nearst_irrigation, "%Y-%m-%d %H:%M:%S"); + $nearst_irrigation = $processed_item + if ( Time::Piece->strptime( $processed_item, "%Y-%m-%d %H:%M:%S") + < Time::Piece->strptime( $nearst_irrigation, "%Y-%m-%d %H:%M:%S") + && $has_schedule + && Time::Piece->strptime( $processed_item, "%Y-%m-%d %H:%M:%S") + > Time::Piece->new + ) + } else { + $nearst_irrigation = ReadingsVal($name, 'scheduling-scheduled_watering_next_start', ''); + } + Log3 $name, 5, "[DEBUG] - choosed nearst: $nearst_irrigation"; + + } # for + # override state 4 extendedstates + if ( AttrVal( $name, "extendedState", 0 ) == 1) { + if (scalar(@opened_valves) > 0){ + ## valve 1 will be ir.. 23 minutes remaining + for (@valves_connected){ + $state_string .= sprintf(RigReadingsValue($hash,'valve').' '.$_.' '.(RigReadingsValue($hash, 'will be irrigated %.f minutes remaining.') .'
'), (ReadingsVal( $name, 'watering-watering_timer_'.$_.'_duration', 0 )/60)); + } # /for + } else { + $state_string .= RigReadingsValue($hash, 'closed'); + } + $state_string .= ($has_schedule) ? sprintf( RigReadingsValue($hash, 'next watering: %s'), RigReadingsValue($hash, ReadingsVal($name, 'scheduling-scheduled_watering_next_start', ''))) : sprintf( RigReadingsValue($hash, 'paused until %s') , $nearst_irrigation); + #TODO: Write state format for ventil 1-@valces_connected -> map ? + CommandAttr( undef, $name . ' stateFormat + { + + } + ' ) + if ( AttrVal( $name, 'stateFormat', 'none' ) eq 'none' ); + } else { + Log3 $name, 5, "[DEBUG] - Offene Ventile :".scalar(@opened_valves)." laengste bewaesserung: $longest_duration . hat Zeitplan: $has_schedule Naechster Zeitplan: $nearst_irrigation"; + $state_string = scalar(@opened_valves) > 0 + # offen + ? sprintf( (RigReadingsValue($hash, 'will be irrigated %.f minutes remaining.')), $longest_duration/60) + # zu + : + ( $has_schedule + && $nearst_irrigation ne '2999-12-12 12:00') + # zeitplan aktiv + # ? ( $nearst_irrigation eq '2038-01-18 00:00') sprintf( RigReadingsValue($hash, 'paused until %s') , $nearst_irrigation) + ? ( $nearst_irrigation eq RigReadingsValue( $hash, 'n/a') || $nearst_irrigation =~ '2038-01-18.*') + # dauerhaft pausiert + ? sprintf( (RigReadingsValue($hash, 'closed') .'. '.RigReadingsValue($hash , 'schedule permanently paused')) ) + # naechster zeutplan + : (ReadingsVal($name, 'scheduling-scheduled_watering_next_start', '') eq RigReadingsValue($hash, 'n/a')) + ? sprintf( RigReadingsValue($hash, 'paused until %s') , $nearst_irrigation) + : sprintf( (RigReadingsValue($hash, 'closed') .'. '.RigReadingsValue($hash, 'next watering: %s')), $nearst_irrigation ) + # zeitplan pausiert + : RigReadingsValue($hash, 'closed') + ; + # state offline | override + $state_string = 'offline' if ($online_state eq 'offline'); + $state_string = ( $error_type ne 'ok' ) ? $error_type : $state_string; + + } + readingsBulkUpdate( + $hash, 'state', RigReadingsValue( $hash, $state_string ) ); + } + + # Sensor / Sensor 2 + if ( AttrVal( $name, 'model', 'unknown' ) =~ /sensor.?/ ) { + my $state_string = + ( ReadingsVal( $name, 'device_info-category', 'unknown' ) eq + 'sensor' ) + ? 'T: ' + . ReadingsVal( $name, 'ambient_temperature-temperature', + 'readingsValError' ) + . '°C, ' + : 'T: ' + . ReadingsVal( $name, 'soil_temperature-temperature', + 'readingsValError' ) + . '°C, '; + $state_string .= 'H: ' + . ReadingsVal( $name, 'humidity-humidity', 'readingsValError' ) . '%'; + $state_string .= ', L: ' + . ReadingsVal( $name, 'light-light', 'readingsValError' ) . 'lux' + if ( ReadingsVal( $name, 'device_info-category', 'unknown' ) eq + 'sensor' ); + +# if ( $online_state eq 'offline') { +# readingsBulkUpdate( $hash, 'humidity-humidity', '-1' ); +# readingsBulkUpdate( $hash, 'ambient_temperature-temperature', '-1' ) if (ReadingsVal($name, 'device_info-category', 'unknown') eq 'sensor'); +# readingsBulkUpdate( $hash, 'light-light', '-1' ) if (ReadingsVal($name, 'device_info-category', 'unknown') eq 'sensor'); +# } + #online state sensor I II + readingsBulkUpdate( $hash, 'state', + $online_state eq 'online' ? RigReadingsValue( $hash, $state_string) : RigReadingsValue( $hash, 'offline') ); + } + + readingsBulkUpdate( $hash, 'state', + ReadingsVal( $name, 'power-power_timer', 'no info from power-timer' ) ) + if ( AttrVal( $name, 'model', 'unknown' ) eq 'power' ); + + return; +} + +################################## +################################## +#### my little helpers ########### + +sub ReadingLangGerman { + my $hash = shift; + my $readingValue = shift; + + my $name = $hash->{NAME}; + my %langGermanMapp = ( + 'ok_cutting' => 'mähen', + 'paused' => 'pausiert', + 'ok_searching' => 'suche Ladestation', + 'ok_charging' => 'lädt', + 'ok_leaving' => 'unterwegs zum Startpunkt', + 'wait_updating' => 'wird aktualisiert ...', + 'wait_power_up' => 'wird eingeschaltet ...', + 'parked_timer' => 'geparkt nach Zeitplan', + 'parked_park_selected' => 'geparkt', + 'off_disabled' => 'der Mäher ist ausgeschaltet', + 'off_hatch_open' => 'deaktiviert. Abdeckung ist offen oder PIN-Code erforderlich', + 'unknown' => 'unbekannter Status', + 'error' => 'Fehler', + 'error_at_power_up' => 'Neustart ...', + 'off_hatch_closed' => 'Deaktiviert. Manueller Start erforderlich', + 'ok_cutting_timer_overridden' => 'manuelles mähen', + 'parked_autotimer' => 'geparkt durch SensorControl', + 'parked_daily_limit_reached' => 'abgeschlossen', + 'no_message' => 'kein Fehler', + 'outside_working_area' => 'außerhalb des Arbeitsbereichs', + 'no_loop_signal' => 'kein Schleifensignal', + 'wrong_loop_signal' => 'falsches Schleifensignal', + 'loop_sensor_problem_front' => 'Problem Schleifensensor, vorne', + 'loop_sensor_problem_rear' => 'Problem Schleifensensor, hinten', + 'trapped' => 'eingeschlossen', + 'upside_down' => 'steht auf dem Kopf', + 'low_battery' => 'niedriger Batteriestand', + 'empty_battery' => 'Batterie leer', + 'no_drive' => 'fährt nicht', + 'lifted' => 'angehoben', + 'stuck_in_charging_station' => 'eingeklemmt in Ladestation', + 'charging_station_blocked' => 'Ladestation blockiert', + 'collision_sensor_problem_rear' => 'Problem Stoßsensor hinten', + 'collision_sensor_problem_front' => 'Problem Stoßsensor vorne', + 'wheel_motor_blocked_right' => 'Radmotor rechts blockiert', + 'wheel_motor_blocked_left' => 'Radmotor links blockiert', + 'wheel_drive_problem_right' => 'Problem Antrieb, rechts', + 'wheel_drive_problem_left' => 'Problem Antrieb, links', + 'cutting_system_blocked' => 'Schneidsystem blockiert', + 'invalid_sub_device_combination' => 'fehlerhafte Verbindung', + 'settings_restored' => 'Standardeinstellungen', + 'electronic_problem' => 'elektronisches Problem', + 'charging_system_problem' => 'Problem Ladesystem', + 'tilt_sensor_problem' => 'Kippsensor Problem', + 'wheel_motor_overloaded_right' => 'rechter Radmotor überlastet', + 'wheel_motor_overloaded_left' => 'linker Radmotor überlastet', + 'charging_current_too_high' => 'Ladestrom zu hoch', + 'temporary_problem' => 'vorübergehendes Problem', + 'guide_1_not_found' => 'SK 1 nicht gefunden', + 'guide_2_not_found' => 'SK 2 nicht gefunden', + 'guide_3_not_found' => 'SK 3 nicht gefunden', + 'difficult_finding_home' => 'Problem die Ladestation zu finden', + 'guide_calibration_accomplished' => 'Kalibrierung des Suchkabels beendet', + 'guide_calibration_failed' => 'Kalibrierung des Suchkabels fehlgeschlagen', + 'temporary_battery_problem' => 'kurzzeitiges Batterieproblem', + 'battery_problem' => 'Batterieproblem', + 'alarm_mower_switched_off' => 'Alarm! Mäher ausgeschalten', + 'alarm_mower_stopped' => 'Alarm! Mäher gestoppt', + 'alarm_mower_lifted' => 'Alarm! Mäher angehoben', + 'alarm_mower_tilted' => 'Alarm! Mäher gekippt', + 'connection_changed' => 'Verbindung geändert', + 'connection_not_changed' => 'Verbindung nicht geändert', + 'com_board_not_available' => 'COM Board nicht verfügbar', + 'slipped' => 'rutscht', + 'out_of_operation' => 'ausser Betrieb', + 'replace_now' => 'kritischer Batteriestand, wechseln Sie jetzt', + 'low' => 'niedrig', + 'ok' => 'ok', + 'no_source' => 'ok', + 'mower_charging' => 'Mäher wurde geladen', + 'completed_cutting_autotimer' => 'Sensor Control erreicht', + 'week_timer' => 'Wochentimer erreicht', + 'countdown_timer' => 'Stoppuhr Timer', + 'undefined' => 'unklar', + 'unknown' => 'unklar', + 'status_device_unreachable' => 'Gerät ist nicht in Reichweite', + 'status_device_alive' => 'Gerät ist in Reichweite', + 'bad' => 'schlecht', + 'poor' => 'schwach', + 'good' => 'gut', + 'undefined' => 'unklar', + 'idle' => 'nichts zu tun', + 'firmware_cancel' => 'Firmwareupload unterbrochen', + 'firmware_upload' => 'Firmwareupload', + 'unsupported' => 'nicht unterstützt', + 'up_to_date' => 'auf dem neusten Stand', + 'mower' => 'Mäher', + 'watering_computer' => 'Bewässerungscomputer', + 'no_frost' => 'kein Frost', + 'open' => 'offen', + 'closed' => 'geschlossen', + 'included' => 'inbegriffen', + 'active' => 'aktiv', + 'inactive' => 'nicht aktiv', + 'hibernate' => 'Winterschlaf', + 'awake' => 'Aufgewacht', + 'schedule permanently paused' => 'Zeitplan dauerhaft pausiert', + 'paused until %s' => 'pausiert bis %s', + 'watering. %.f minutes left' => 'Wird bewässert. %.f Minuten verbleibend.', + 'next watering: %s' => 'Nächste Bewässerung: %s', + 'n/a' => 'nicht verfügbar', + 'pump_not_filled' => 'Pumpe nicht gefüllt', + 'clean_fine_filter' => 'Filter reinigen', + ); + + if ( + defined( $langGermanMapp{$readingValue} ) + && ( AttrVal( 'global', 'language', 'none' ) eq 'DE' + || AttrVal( $name, 'readingValueLanguage', 'none' ) eq 'de' ) + && AttrVal( $name, 'readingValueLanguage', 'none' ) ne 'en' + ) + { + return $langGermanMapp{$readingValue}; + } + else { + return $readingValue; + } + + return; +} + +sub RigReadingsValue { + my $hash = shift; + my $readingValue = shift; + + my $rigReadingValue; + + if ( $readingValue =~ /^(\d+)-(\d\d)-(\d\d)T(\d\d)/ ) { + $rigReadingValue = Zulu2LocalString($readingValue); + } + else { + $rigReadingValue = ReadingLangGerman( $hash, $readingValue ); + } + + return $rigReadingValue; +} + +sub Zulu2LocalString { + my $t = shift; + + my ( $datehour, $datemin, $rest ) = split( /:/, $t, 3 ); + + my ( $year, $month, $day, $hour, $min ) = + $datehour =~ /(\d+)-(\d\d)-(\d\d)T(\d\d)/; + my $epoch = timegm( 0, 0, $hour, $day, $month - 1, $year ); + + my ( $lyear, $lmonth, $lday, $lhour, $isdst ) = + ( localtime($epoch) )[ 5, 4, 3, 2, -1 ]; + + $lyear += 1900; # year is 1900 based + $lmonth++; # month number is zero based + + if ( defined($rest) ) { + return ( + sprintf( + "%04d-%02d-%02d %02d:%02d:%s", + $lyear, $lmonth, $lday, + $lhour, $datemin, substr( $rest, 0, 2 ) + ) + ); + } + elsif ( $lyear < 2000 ) { + return 'temporarily unavailable'; + } + else { + return ( + sprintf( + "%04d-%02d-%02d %02d:%02d", + $lyear, $lmonth, $lday, $lhour, substr( $datemin, 0, 2 ) + ) + ); + } + + return; +} + +sub SetPredefinedStartPoints { + my $hash = shift; + my $aArg = shift; + + my ( $startpoint_state, $startpoint_num, @morestartpoints ) = @{$aArg}; + + my $name = $hash->{NAME}; + my $payload; + my $abilities; + + if ( defined($startpoint_state) && defined($startpoint_num) ) { + if ( defined( $hash->{helper}{STARTINGPOINTS} ) + && $hash->{helper}{STARTINGPOINTS} ne '' ) + { +# add needed parameters to saved settings config and change the value in request + my $decode_json_settings = + eval { decode_json( $hash->{helper}{STARTINGPOINTS} ) }; + if ($@) { + Log3 $name, 3, +"GardenaSmartBridge ($name) - JSON error while setting startpoint: $@"; + } + + $decode_json_settings->{device} = $hash->{DEVICEID}; + my $setval = $startpoint_state eq 'disable' ? \0 : \1; + $decode_json_settings->{value}[ $startpoint_num - 1 ]{enabled} = + $setval; + + #set more startpoints + if ( + defined scalar(@morestartpoints) + && ( scalar(@morestartpoints) == 2 + || scalar(@morestartpoints) == 4 ) + ) + { + if ( scalar(@morestartpoints) == 2 ) { + $setval = $morestartpoints[0] eq 'disable' ? \0 : \1; + $decode_json_settings->{value}[ $morestartpoints[1] - 1 ] + {enabled} = $setval; + + } + elsif ( scalar(@morestartpoints) == 4 ) { + $setval = $morestartpoints[0] eq 'disable' ? \0 : \1; + $decode_json_settings->{value}[ $morestartpoints[1] - 1 ] + {enabled} = $setval; + $setval = $morestartpoints[2] eq 'disable' ? \0 : \1; + $decode_json_settings->{value}[ $morestartpoints[3] - 1 ] + {enabled} = $setval; + } + } + + $payload = '"settings": ' . encode_json($decode_json_settings); + $abilities = 'mower_settings'; + + #$abilities['service_id'] = $hash->{helper}{STARTINGPOINTID}; + } + else { + return + "startingpoints not loaded yet, please wait a couple of minutes", + undef, undef; + } + } + else { + return + "startpoint usage: set " + . $hash->{NAME} + . " startpoint disable 1 [enable 2] [disable 3]", undef, undef; + } + + return undef, $payload, $abilities; +} + +1; + +=pod + +=item device +=item summary Modul to control GardenaSmart Devices +=item summary_DE Modul zur Steuerung von GardenaSmartgeräten +=begin html + + +

GardenaSmartDevice

+
    + In combination with Fhem device GardenaSmartBridge this Fhem module enables communication between GardenaCloud and + fhem. +

    + Once the bridge device is created, the connected Gardena devices will be recognized and created in Fhem + automatically.
    + From now on these devices can be controlled via Fhem. Changes in the Gardena App are synchronized with state and + redings of the devices. +

    + So far, known devices are mower, smart water control, irrigation control, smart sensors, power plug and pressure + pump. Schedules can be disabled/enabled via fhem, defining or deleting them must be done via the Gardena App.
    + +
+
+
    + Readings (model = mower) +
      +
    • battery-charging - Indicator if the Battery is charged (0/1) or with newer Firmware (false/true)
    • +
    • battery-level - load percentage of the Battery
    • +
    • battery-rechargeable_battery_status - healthyness of the battery (out_of_operation/replace_now/low/ok)
    • +
    • device_info-category - category of device (mower/watering_computer)
    • +
    • device_info-last_time_online - timestamp of last radio contact
    • +
    • device_info-manufacturer - manufacturer
    • +
    • device_info-product - product type
    • +
    • device_info-serial_number - serial number
    • +
    • device_info-sgtin -
    • +
    • device_info-version - firmware version
    • +
    • firmware-firmware_command - firmware command (idle/firmware_cancel/firmware_upload/unsupported)
    • +
    • firmware-firmware_status - firmware status
    • +
    • firmware-firmware_update_start - indicator when a firmwareupload is started
    • +
    • firmware-firmware_upload_progress - progress indicator of firmware update
    • +
    • firmware-inclusion_status - inclusion status
    • +
    • internal_temperature-temperature - internal device temperature
    • +
    • mower-error - actual error message +
        +
      • no_message
      • +
      • outside_working_area
      • +
      • no_loop_signal
      • +
      • wrong_loop_signal
      • +
      • loop_sensor_problem_front
      • +
      • loop_sensor_problem_rear
      • +
      • trapped
      • +
      • upside_down
      • +
      • low_battery
      • +
      • empty_battery
      • +
      • no_drive
      • +
      • lifted
      • +
      • stuck_in_charging_station
      • +
      • charging_station_blocked
      • +
      • collision_sensor_problem_rear
      • +
      • collision_sensor_problem_front
      • +
      • wheel_motor_blocked_right
      • +
      • wheel_motor_blocked_left
      • +
      • wheel_drive_problem_right
      • +
      • wheel_drive_problem_left
      • +
      • cutting_system_blocked
      • +
      • invalid_sub_device_combination
      • +
      • settings_restored
      • +
      • electronic_problem
      • +
      • charging_system_problem
      • +
      • tilt_sensor_problem
      • +
      • wheel_motor_overloaded_right
      • +
      • wheel_motor_overloaded_left
      • +
      • charging_current_too_high
      • +
      • temporary_problem
      • +
      • guide_1_not_found
      • +
      • guide_2_not_found
      • +
      • guide_3_not_found
      • +
      • difficult_finding_home
      • +
      • guide_calibration_accomplished
      • +
      • guide_calibration_failed
      • +
      • temporary_battery_problem
      • +
      • battery_problem
      • +
      • alarm_mower_switched_off
      • +
      • alarm_mower_stopped
      • +
      • alarm_mower_lifted
      • +
      • alarm_mower_tilted
      • +
      • connection_changed
      • +
      • connection_not_changed
      • +
      • com_board_not_available
      • +
      • slipped
      • +
      +
    • +
    • mower-manual_operation - (0/1) or with newer Firmware (false/true)
    • +
    • mower-override_end_time - manual override end time
    • +
    • mower-source_for_next_start - source for the next start +
        +
      • no_source
      • +
      • mower_charging
      • +
      • completed_cutting_autotimer
      • +
      • week_timer
      • +
      • countdown_timer
      • +
      • undefined
      • +
      +
    • +
    • mower-status - mower state (see state)
    • +
    • mower-timestamp_next_start - timestamp of next scheduled start
    • +
    • radio-connection_status - state of connection
    • +
    • radio-quality - percentage of the radio quality
    • +
    • radio-state - radio state (bad/poor/good/undefined)
    • +
    • state - state of the mower +
        +
      • paused
      • +
      • ok_cutting
      • +
      • ok_searching
      • +
      • ok_charging
      • +
      • ok_leaving
      • +
      • wait_updating
      • +
      • wait_power_up
      • +
      • parked_timer
      • +
      • parked_park_selected
      • +
      • off_disabled
      • +
      • off_hatch_open
      • +
      • unknown
      • +
      • error
      • +
      • error_at_power_up
      • +
      • off_hatch_closed
      • +
      • ok_cutting_timer_overridden
      • +
      • parked_autotimer
      • +
      • parked_daily_limit_reached
      • +
      +
    • +
    +

    + Readings (model = watering_computer) +
      +
    • [tbd.]
    • +
    +

    + Readings (model = ic24) +
      +
    • [tbd.]
    • +
    +

    + Readings (model = sensor) +
      +
    • [tbd.]
    • +
    +

    + Readings (model = sensor2) +
      +
    • [tbd.]
    • +
    +

    + Readings (model = power) +
      +
    • [tbd.]
    • +
    +

    + Readings (model = electronic_pressure_pump) +
      +
    • [tbd.]
    • +
    +

    + + Attribute +
      +
    • IODev - Name of GardenaSmartBridge device
    • +
    • extendedState 0|1 - [tbd.]
    • +
    • model watering_computer|sensor|sensor2|mower|ic24|power|electronic_pressure_pump - model of + GardenaSmartDevice
    • +
    • readingValueLanguage en|de - Reading language enlish or german (default: english, if global language is not + set to german)
    • +
    +

    + + set (model = mower) +
      +
    • parkUntilFurtherNotice - park mower and disable schedule
    • +
    • parkUntilNextTimer - park mower until next schedule
    • +
    • startOverrideTimer n - manual mowing for n minutes (e.g. 60 = 1h, 1440 = 24h, 4320 = 72h)
    • +
    • startResumeSchedule - enable schedule
    • +
    • startPoint enable|disable 1|2|3 - enable or disable pre-defined starting points
    • +
        +
      • set NAME startpoint enable 1
      • +
      • set NAME startpoint disable 3 enable 1
      • +
      +
    • winter_mode awake|hibernate - Disable or enable winter mode
    • +
    +

    + set (model = watering_computer) +
      +
    • cancelOverride - stop (manual) watering
    • +
    • manualButtonTime n - set watering time for manual button (0 disables button)
    • +
    • manualOverride n - manual watering for n minutes
    • +
    • resumeSchedule - enable schedule
    • +
    • stopSchedule n - disable schedule for n hours (Default: 2038-01-18T00:00:00.000Z, Gardena App reads it as + "permanently")
    • +
    • winter_mode awake|hibernate - Disable or enable winter mode
    • +
    +

    + set (model = ic24) +
      +
    • cancelOverrideValve1 - stop (manual) watering for valve 1
    • +
    • cancelOverrideValve2 - stop (manual) watering for valve 2
    • +
    • cancelOverrideValve3 - stop (manual) watering for valve 3
    • +
    • cancelOverrideValve4 - stop (manual) watering for valve 4
    • +
    • cancelOverrideValve5 - stop (manual) watering for valve 5
    • +
    • cancelOverrideValve6 - stop (manual) watering for valve 6
    • +
    • closeAllValves - close all valves
    • +
    • manualDurationValve1 n - open valve 1 for n minutes
    • +
    • manualDurationValve2 n - open valve 2 for n minutes
    • +
    • manualDurationValve3 n - open valve 3 for n minutes
    • +
    • manualDurationValve4 n - open valve 4 for n minutes
    • +
    • manualDurationValve5 n - open valve 5 for n minutes
    • +
    • manualDurationValve6 n - open valve 6 for n minutes
    • +
    • resumeScheduleValve n - enable schedule for valve n
    • +
    • stopScheduleValve n m - disable schedule for valve n for m hours (Default: 2038-01-18T00:00:00.000Z, Gardena + App reads it as "permanently")
    • +
    • winter_mode awake|hibernate - Disable or enable winter mode
    • +
    +

    + set (model = sensor) +
      +
    • refresh temperature|humidity|light - refresh sensor reading for temperature, humidity or daylight
    • +
    • winter_mode awake|hibernate - Disable or enable winter mode
    • +
    +

    + set (model = sensor2) +
      +
    • refresh temperature|humidity - refresh sensor reading for temperature or humidity
    • +
    • winter_mode awake|hibernate - Disable or enable winter mode
    • +
    +

    + set (model = power) +
      +
    • [tbd.]
    • +
    +

    + set (model = electronic_pressure_pump) +
      +
    • [tbd.]
    • +
    +
+ +=end html + +=begin html_DE + + +

GardenaSmartDevice

+
    + Zusammen mit dem Device GardenaSmartBridge stellt dieses Fhem-Modul die Kommunikation zwischen der GardenaCloud und + Fhem her. +

    + Wenn das GardenaSmartBridge Device erzeugt wurde, werden verbundene Geräte automatisch erkannt und in Fhem angelegt. +
    + Von nun an können die eingebundenen Geräte gesteuert werden. Änderungen in der App werden mit den Readings und dem + Status synchronisiert. +

    + Bekannte Gardena-Geräte umfassen Rasenmäher, Smart Water Control, Irrigation Control, Smart Sensoren, + Steckdosen-Adapter und Pumpe. Zeitpläne können über fhem pausiert/aktiviert werden, das Anlegen oder Löschen erfolgt + derzeit nur über die App. + +
+
+
    + Readings (model = mower) +
      +
    • battery-charging - Ladeindikator (0/1) oder mit neuerer Firmware (false/true)
    • +
    • battery-level - Ladezustand der Batterie in Prozent
    • +
    • battery-rechargeable_battery_status - Zustand der Batterie (Ausser Betrieb/Kritischer Batteriestand, + wechseln Sie jetzt/Niedrig/oK)
    • +
    • device_info-category - Eigenschaft des Gerätes (Mäher/Bewässerungscomputer/Bodensensor)
    • +
    • device_info-last_time_online - Zeitpunkt der letzten Funkübertragung
    • +
    • device_info-manufacturer - Hersteller
    • +
    • device_info-product - Produkttyp
    • +
    • device_info-serial_number - Seriennummer
    • +
    • device_info-sgtin -
    • +
    • device_info-version - Firmware Version
    • +
    • firmware-firmware_command - Firmware Kommando (Nichts zu tun/Firmwareupload + unterbrochen/Firmwareupload/nicht unterstützt)
    • +
    • firmware-firmware_status - Firmware Status
    • +
    • firmware-firmware_update_start - Firmwareupdate (0/1) oder mit neuerer Firmware (false/true)
    • +
    • firmware-firmware_upload_progress - Firmwareupdatestatus in Prozent
    • +
    • firmware-inclusion_status - Einbindungsstatus
    • +
    • internal_temperature-temperature - Interne Geräte Temperatur
    • +
    • mower-error - Aktuelle Fehler Meldung +
        +
      • Kein Fehler
      • +
      • Außerhalb des Arbeitsbereichs
      • +
      • Kein Schleifensignal
      • +
      • Falsches Schleifensignal
      • +
      • Problem Schleifensensor, vorne
      • +
      • Problem Schleifensensor, hinten
      • +
      • Eingeschlossen
      • +
      • Steht auf dem Kopf
      • +
      • Niedriger Batteriestand
      • +
      • Batterie ist leer
      • +
      • Kein Antrieb
      • +
      • Angehoben
      • +
      • Eingeklemmt in Ladestation
      • +
      • Ladestation blockiert
      • +
      • Problem Stoßsensor hinten
      • +
      • Problem Stoßsensor vorne
      • +
      • Radmotor rechts blockiert
      • +
      • Radmotor links blockiert
      • +
      • Problem Antrieb, rechts
      • +
      • Problem Antrieb, links
      • +
      • Schneidsystem blockiert
      • +
      • Fehlerhafte Verbindung
      • +
      • Standardeinstellungen
      • +
      • Elektronisches Problem
      • +
      • Problem Ladesystem
      • +
      • Kippsensorproblem
      • +
      • Rechter Radmotor überlastet
      • +
      • Linker Radmotor überlastet
      • +
      • Ladestrom zu hoch
      • +
      • Vorübergehendes Problem
      • +
      • SK 1 nicht gefunden
      • +
      • SK 2 nicht gefunden
      • +
      • SK 3 nicht gefunden
      • +
      • Problem die Ladestation zu finden
      • +
      • Kalibration des Suchkabels beendet
      • +
      • Kalibration des Suchkabels fehlgeschlagen
      • +
      • Kurzzeitiges Batterieproblem
      • +
      • Batterieproblem
      • +
      • Alarm! Mäher ausgeschalten
      • +
      • Alarm! Mäher gestoppt
      • +
      • Alarm! Mäher angehoben
      • +
      • Alarm! Mäher gekippt
      • +
      • Verbindung geändert
      • +
      • Verbindung nicht geändert
      • +
      • COM board nicht verfügbar
      • +
      • Rutscht
      • +
      +
    • +
    • mower-manual_operation - Manueller Betrieb (0/1) oder mit neuerer Firmware (false/true)
    • +
    • mower-override_end_time - Zeitpunkt wann der manuelle Betrieb beendet ist
    • +
    • mower-source_for_next_start - Grund für den nächsten Start +
        +
      • Kein Grund
      • +
      • Mäher wurde geladen
      • +
      • SensorControl erreicht
      • +
      • Wochentimer erreicht
      • +
      • Stoppuhr Timer
      • +
      • Undefiniert
      • +
      +
    • +
    • mower-status - Mäher Status (siehe state)
    • +
    • mower-timestamp_next_start - Zeitpunkt des nächsten geplanten Starts
    • +
    • radio-connection_status - Status der Funkverbindung
    • +
    • radio-quality - Indikator für die Funkverbindung in Prozent
    • +
    • radio-state - radio state (schlecht/schwach/gut/Undefiniert)
    • +
    • state - Staus des Mähers +
        +
      • Pausiert
      • +
      • Mähen
      • +
      • Suche Ladestation
      • +
      • Lädt
      • +
      • Mähen
      • +
      • Wird aktualisiert ...
      • +
      • Wird eingeschaltet ...
      • +
      • Geparkt nach Zeitplan
      • +
      • Geparkt
      • +
      • Der Mäher ist ausgeschaltet
      • +
      • Deaktiviert. Abdeckung ist offen oder PIN-Code erforderlich
      • +
      • Unbekannter Status
      • +
      • Fehler
      • +
      • Neustart ...
      • +
      • Deaktiviert. Manueller Start erforderlich
      • +
      • Manuelles Mähen
      • +
      • Geparkt durch SensorControl
      • +
      • Abgeschlossen
      • +
      +
    • +
    +

    + Readings (model = watering_computer) +
      +
    • [tbd.]
    • +
    +

    + Readings (model = ic24) +
      +
    • [tbd.]
    • +
    +

    + Readings (model = sensor) +
      +
    • [tbd.]
    • +
    +

    + Readings (model = sensor2) +
      +
    • [tbd.]
    • +
    +

    + Readings (model = power) +
      +
    • [tbd.]
    • +
    +

    + Readings (model = electronic_pressure_pump) +
      +
    • [tbd.]
    • +
    +

    + + Attribute +
      +
    • IODev - Name des GardenaSmartBridge Devices
    • +
    • extendedState 0|1 - [tbd.]
    • +
    • model watering_computer|sensor|sensor2|mower|ic24|power|electronic_pressure_pump - Modell des + GardenaSmartDevice
    • +
    • readingValueLanguage en|de - Sprache der Readings englisch oder deutsch (default: englisch, es sei denn, + Deutsch ist als globale Sprache gesetzt)
    • +
    +

    + + set (model = mower) +
      +
    • parkUntilFurtherNotice - Parken des Mähers und Aussetzen des Zeitplans
    • +
    • parkUntilNextTimer - Parken bis zum nächsten Start nach Zeitplan
    • +
    • startOverrideTimer n - Manuelles Mähen für n Minuten (z.B. 60 = 1h, 1440 = 24h, 4320 = 72h)
    • +
    • startResumeSchedule - Zeitplan wieder aktivieren
    • +
    • startPoint enable|disable 1|2|3 - Aktiviert oder deaktiviert einen vordefinierten Startbereich
    • +
        +
      • set NAME startpoint enable 1
      • +
      • set NAME startpoint disable 3 enable 1
      • +
      +
    • winter_mode awake|hibernate - Winterschlaf aktivieren oder Gerät aufwecken
    • +
    +

    + set (model = watering_computer) +
      +
    • cancelOverride - (Manuelle) Bewässerung stoppen
    • +
    • manualButtonTime n - Bewässerungsdauer für manuellen Knopf auf n Minuten setzen (0 schaltet den Knopf aus) +
    • +
    • manualOverride n - Manuelle Bewässerung für n Minuten
    • +
    • resumeSchedule - Zeitplan wieder aktivieren
    • +
    • stopSchedule n - Zeitplan anhalten für n Stunden (Default: 2038-01-18T00:00:00.000Z, durch Gardena-App als + "dauerhaft" interpretiert)
    • +
    • winter_mode awake|hibernate - Winterschlaf aktivieren oder Gerät aufwecken
    • +
    +

    + set (model = ic24) +
      +
    • cancelOverrideValve1 - (Manuelle) Bewässerung an Ventil 1 stoppen
    • +
    • cancelOverrideValve2 - (Manuelle) Bewässerung an Ventil 2 stoppen
    • +
    • cancelOverrideValve3 - (Manuelle) Bewässerung an Ventil 3 stoppen
    • +
    • cancelOverrideValve4 - (Manuelle) Bewässerung an Ventil 4 stoppen
    • +
    • cancelOverrideValve5 - (Manuelle) Bewässerung an Ventil 5 stoppen
    • +
    • cancelOverrideValve6 - (Manuelle) Bewässerung an Ventil 6 stoppen
    • +
    • closeAllValves - Alle Ventile schließen
    • +
    • manualDurationValve1 n - Ventil 1 für n Minuten öffnen
    • +
    • manualDurationValve2 n - Ventil 2 für n Minuten öffnen
    • +
    • manualDurationValve3 n - Ventil 3 für n Minuten öffnen
    • +
    • manualDurationValve4 n - Ventil 4 für n Minuten öffnen
    • +
    • manualDurationValve5 n - Ventil 5 für n Minuten öffnen
    • +
    • manualDurationValve6 n - Ventil 6 für n Minuten öffnen
    • +
    • resumeScheduleValve n - Zeitplan für Ventil n wieder aktivieren
    • +
    • stopScheduleValve n m - Zeitplan für Ventil n anhalten für m Stunden (Default: 2038-01-18T00:00:00.000Z, + durch Gardena-App als "dauerhaft" interpretiert)
    • +
    • winter_mode awake|hibernate - Winterschlaf aktivieren oder Gerät aufwecken
    • +
    +

    + set (model = sensor) +
      +
    • refresh temperature|humidity|light - Sensorwert für Temperatur, Feuchtigkeit oder Helligkeit aktualisieren +
    • +
    • winter_mode awake|hibernate - Winterschlaf aktivieren oder Gerät aufwecken
    • +
    +

    + set (model = sensor2) +
      +
    • refresh temperature|humidity - Sensorwert für Temperatur oder Feuchtigkeit aktualisieren
    • +
    • winter_mode awake|hibernate - Winterschlaf aktivieren oder Gerät aufwecken
    • +
    +

    + set (model = power) +
      +
    • [tbd.]
    • +
    +

    + set (model = electronic_pressure_pump) +
      +
    • [tbd.]
    • +
    +
+ +=end html_DE + +=for :application/json;q=META.json 74_GardenaSmartDevice.pm +{ + "abstract": "Modul to control GardenaSmart Devices", + "x_lang": { + "de": { + "abstract": "Modul zur Steuerung von Gardena Smart Geräten" + } + }, + "keywords": [ + "fhem-mod-device", + "fhem-core", + "Garden", + "Gardena", + "Smart" + ], + "release_status": "stable", + "license": "GPL_2", + "version": "v2.5.6", + "author": [ + "Marko Oldenburg " + ], + "x_fhem_maintainer": [ + "CoolTux" + ], + "x_fhem_maintainer_github": [ + "LeonGaultier" + ], + "prereqs": { + "runtime": { + "requires": { + "FHEM": 5.00918799, + "perl": 5.016, + "Meta": 0, + "JSON": 0, + "Time::Local": 0 + }, + "recommends": { + }, + "suggests": { + } + } + } +} +=end :application/json;q=META.json + +=cut diff --git a/controls_GardenaSmartDevice.txt b/controls_GardenaSmartDevice.txt index 3280213..e713269 100644 --- a/controls_GardenaSmartDevice.txt +++ b/controls_GardenaSmartDevice.txt @@ -1,2 +1,2 @@ UPD 2022-07-21_19:43:48 49634 FHEM/73_GardenaSmartBridge.pm -UPD 2022-07-24_20:29:03 73628 FHEM/74_GardenaSmartDevice.pm +UPD 2022-07-27_22:30:06 78954 FHEM/74_GardenaSmartDevice.pm From e108afda5a92be43d775b66c0c4c8638baeb157e Mon Sep 17 00:00:00 2001 From: Sebastian Date: Fri, 29 Jul 2022 12:49:27 +0200 Subject: [PATCH 07/29] add translation --- CHANGED | 2 +- FHEM/74_GardenaSmartDevice.pm | 4 ++-- controls_GardenaSmartDevice.txt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGED b/CHANGED index af3012d..7a4cc7a 100644 --- a/CHANGED +++ b/CHANGED @@ -1 +1 @@ - [add] - translation pumpe filter + [add] - translations/commandref diff --git a/FHEM/74_GardenaSmartDevice.pm b/FHEM/74_GardenaSmartDevice.pm index c5fa25d..8ead950 100644 --- a/FHEM/74_GardenaSmartDevice.pm +++ b/FHEM/74_GardenaSmartDevice.pm @@ -1601,8 +1601,8 @@ sub SetPredefinedStartPoints {
  • manualDurationValve4 n - open valve 4 for n minutes
  • manualDurationValve5 n - open valve 5 for n minutes
  • manualDurationValve6 n - open valve 6 for n minutes
  • -
  • resumeScheduleValve n - enable schedule for valve n
  • -
  • stopScheduleValve n m - disable schedule for valve n for m hours (Default: 2038-01-18T00:00:00.000Z, Gardena +
  • resumeScheduleValve n - (re)start irrigation schedule for valve n
  • +
  • stopScheduleValve n m - stop irrigation schedule for valve n (Default: 2038-01-18T00:00:00.000Z, Gardena App reads it as "permanently")
  • winter_mode awake|hibernate - Disable or enable winter mode
  • diff --git a/controls_GardenaSmartDevice.txt b/controls_GardenaSmartDevice.txt index e713269..b80a8f0 100644 --- a/controls_GardenaSmartDevice.txt +++ b/controls_GardenaSmartDevice.txt @@ -1,2 +1,2 @@ UPD 2022-07-21_19:43:48 49634 FHEM/73_GardenaSmartBridge.pm -UPD 2022-07-27_22:30:06 78954 FHEM/74_GardenaSmartDevice.pm +UPD 2022-07-29_12:49:22 78965 FHEM/74_GardenaSmartDevice.pm From 7f6c7bc265642f08e65f26bcb6ce99e192aa791b Mon Sep 17 00:00:00 2001 From: Sebastian Date: Sat, 30 Jul 2022 20:31:59 +0200 Subject: [PATCH 08/29] [log] - removed valve_names log line --- CHANGED | 2 +- FHEM/74_GardenaSmartDevice.pm | 2 +- controls_GardenaSmartDevice.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGED b/CHANGED index 7a4cc7a..1bd692d 100644 --- a/CHANGED +++ b/CHANGED @@ -1 +1 @@ - [add] - translations/commandref + add translation diff --git a/FHEM/74_GardenaSmartDevice.pm b/FHEM/74_GardenaSmartDevice.pm index 8ead950..180630c 100644 --- a/FHEM/74_GardenaSmartDevice.pm +++ b/FHEM/74_GardenaSmartDevice.pm @@ -928,7 +928,7 @@ sub WriteReadings { && ref( $decode_json->{settings}[$settings]{value} ) eq "ARRAY" ) { # or HASH ? my @valves = @{$decode_json->{settings}[$settings]{value}}; foreach my $valve( @valves ) { - Log3 $name, 4, "GardenaSmartDevice ($name) valve_name $valve->{'name'}"; + #Log3 $name, 4, "GardenaSmartDevice ($name) valve_name $valve->{'name'}"; readingsBulkUpdateIfChanged( $hash, 'valve-valve_name_'.$valve->{"id"}, $valve->{"name"} ); } diff --git a/controls_GardenaSmartDevice.txt b/controls_GardenaSmartDevice.txt index b80a8f0..bafc0bd 100644 --- a/controls_GardenaSmartDevice.txt +++ b/controls_GardenaSmartDevice.txt @@ -1,2 +1,2 @@ UPD 2022-07-21_19:43:48 49634 FHEM/73_GardenaSmartBridge.pm -UPD 2022-07-29_12:49:22 78965 FHEM/74_GardenaSmartDevice.pm +UPD 2022-07-30_20:31:34 78966 FHEM/74_GardenaSmartDevice.pm From 4b998d19ab6bf373ed679771b8a65eb8f9631672 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Tue, 2 Aug 2022 14:52:52 +0200 Subject: [PATCH 09/29] [fix] - show schedules_events_count fot non sensor devices [fix] - remove _valve_ in non valve devices fpr schedules --- CHANGED | 2 +- FHEM/74_GardenaSmartDevice.pm | 9 ++++----- controls_GardenaSmartDevice.txt | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/CHANGED b/CHANGED index 1bd692d..bf024b8 100644 --- a/CHANGED +++ b/CHANGED @@ -1 +1 @@ - add translation + [log] - removed valve_names log line diff --git a/FHEM/74_GardenaSmartDevice.pm b/FHEM/74_GardenaSmartDevice.pm index 180630c..784eeaf 100644 --- a/FHEM/74_GardenaSmartDevice.pm +++ b/FHEM/74_GardenaSmartDevice.pm @@ -836,7 +836,8 @@ sub WriteReadings { if ( exists( $decode_json->{scheduled_events} ) # && scalar ($decode_json->{scheduled_events} ) > 0 - && ref ($decode_json->{scheduled_events}) eq 'ARRAY' ) { + && ref ($decode_json->{scheduled_events}) eq 'ARRAY' + && AttrVal( $name, 'model', 'unknown' ) !~ /sensor.?/ ) { readingsBulkUpdateIfChanged( $hash, 'scheduling-schedules_events_count', scalar( @{$decode_json->{scheduled_events} } ) ); my $valve_id =1; my $event_id = 1; # ic24 [1..6] | wc, pump [1] @@ -848,15 +849,13 @@ sub WriteReadings { while ( my ( $r, $v ) = each %{ $event_schedules } ) { readingsBulkUpdateIfChanged( $hash, 'scheduling-schedules_event_' . $event_id - . '_valve_' - . $valve_id + . ( ReadingsVal($name,'error-valve_error_1_valve_id','') ne '' ? "_valve_$valve_id" : '') . '_' . $r, $v) if (ref($v) ne 'HASH' ); readingsBulkUpdateIfChanged( $hash, 'scheduling-schedules_event_' . $event_id - . '_valve_' - . $valve_id + . ( ReadingsVal($name,'error-valve_error_1_valve_id','') ne '' ? "_valve_$valve_id" : '') . '_' . $v->{type}, join(',', @ { $v->{weekdays}}) ) if (ref($v) eq 'HASH' ); diff --git a/controls_GardenaSmartDevice.txt b/controls_GardenaSmartDevice.txt index bafc0bd..626551b 100644 --- a/controls_GardenaSmartDevice.txt +++ b/controls_GardenaSmartDevice.txt @@ -1,2 +1,2 @@ UPD 2022-07-21_19:43:48 49634 FHEM/73_GardenaSmartBridge.pm -UPD 2022-07-30_20:31:34 78966 FHEM/74_GardenaSmartDevice.pm +UPD 2022-08-02_14:51:12 79067 FHEM/74_GardenaSmartDevice.pm From 11c5e6650dbbba90f4e08c5c0a0c26add98bcb63 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Tue, 2 Aug 2022 14:58:59 +0200 Subject: [PATCH 10/29] [fix] - update event handled --- CHANGED | 2 +- FHEM/74_GardenaSmartDevice.pm | 9 ++------- controls_GardenaSmartDevice.txt | 2 +- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/CHANGED b/CHANGED index bf024b8..d5effd0 100644 --- a/CHANGED +++ b/CHANGED @@ -1 +1 @@ - [log] - removed valve_names log line + [fix] - remove _valve_ in non valve devices fpr schedules diff --git a/FHEM/74_GardenaSmartDevice.pm b/FHEM/74_GardenaSmartDevice.pm index 784eeaf..ca65089 100644 --- a/FHEM/74_GardenaSmartDevice.pm +++ b/FHEM/74_GardenaSmartDevice.pm @@ -793,7 +793,7 @@ sub WriteReadings { my $sub_state = 0; my $sub_value = 0; while ( my ( $r, $v ) = each %{ $propertie->{value} } ) { if ( ref( $v ) ne "HASH" ) { - readingsBulkUpdate( + readingsBulkUpdateIfChanged( $hash, $decode_json->{abilities}[$abilities]{name} . '-' . $propertie->{name} . '_' @@ -802,7 +802,7 @@ sub WriteReadings { ); } else { while ( my ( $i_r, $i_v ) = each %{ $v } ) { - readingsBulkUpdate( + readingsBulkUpdateIfChanged( $hash, $decode_json->{abilities}[$abilities]{name} . '-' . $propertie->{name} . '_' @@ -1109,11 +1109,6 @@ sub setState { if ( ReadingsVal( $name, 'device_info-category', 'unknown' ) eq 'sensor' ); -# if ( $online_state eq 'offline') { -# readingsBulkUpdate( $hash, 'humidity-humidity', '-1' ); -# readingsBulkUpdate( $hash, 'ambient_temperature-temperature', '-1' ) if (ReadingsVal($name, 'device_info-category', 'unknown') eq 'sensor'); -# readingsBulkUpdate( $hash, 'light-light', '-1' ) if (ReadingsVal($name, 'device_info-category', 'unknown') eq 'sensor'); -# } #online state sensor I II readingsBulkUpdate( $hash, 'state', $online_state eq 'online' ? RigReadingsValue( $hash, $state_string) : RigReadingsValue( $hash, 'offline') ); diff --git a/controls_GardenaSmartDevice.txt b/controls_GardenaSmartDevice.txt index 626551b..3dc18d2 100644 --- a/controls_GardenaSmartDevice.txt +++ b/controls_GardenaSmartDevice.txt @@ -1,2 +1,2 @@ UPD 2022-07-21_19:43:48 49634 FHEM/73_GardenaSmartBridge.pm -UPD 2022-08-02_14:51:12 79067 FHEM/74_GardenaSmartDevice.pm +UPD 2022-08-02_14:58:44 78714 FHEM/74_GardenaSmartDevice.pm From e363b4586242388f661a9b9dffad66761946a615 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Thu, 4 Aug 2022 10:31:11 +0200 Subject: [PATCH 11/29] [fix] - eventhandler ic24 --- CHANGED | 2 +- FHEM/74_GardenaSmartDevice.pm | 4 ++++ controls_GardenaSmartDevice.txt | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGED b/CHANGED index d5effd0..fd24b06 100644 --- a/CHANGED +++ b/CHANGED @@ -1 +1 @@ - [fix] - remove _valve_ in non valve devices fpr schedules + [fix] - update event handled diff --git a/FHEM/74_GardenaSmartDevice.pm b/FHEM/74_GardenaSmartDevice.pm index ca65089..e327630 100644 --- a/FHEM/74_GardenaSmartDevice.pm +++ b/FHEM/74_GardenaSmartDevice.pm @@ -725,6 +725,10 @@ sub WriteReadings { . $propertie->{name} ne 'humidity-humidity' && $decode_json->{abilities}[$abilities]{name} . '-' . $propertie->{name} ne 'light-light' + && $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} ne 'ic24-valves_connected' + && $decode_json->{abilities}[$abilities]{name} . '-' + . $propertie->{name} ne 'ic24-valves_master_config' && ref( $propertie->{value} ) ne "HASH" ); readingsBulkUpdateIfChanged( diff --git a/controls_GardenaSmartDevice.txt b/controls_GardenaSmartDevice.txt index 3dc18d2..3cc2108 100644 --- a/controls_GardenaSmartDevice.txt +++ b/controls_GardenaSmartDevice.txt @@ -1,2 +1,2 @@ UPD 2022-07-21_19:43:48 49634 FHEM/73_GardenaSmartBridge.pm -UPD 2022-08-02_14:58:44 78714 FHEM/74_GardenaSmartDevice.pm +UPD 2022-08-04_10:30:59 79000 FHEM/74_GardenaSmartDevice.pm From 1c7097e476a11eb514135fed56991a9e8a6165e8 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Thu, 4 Aug 2022 10:34:48 +0200 Subject: [PATCH 12/29] [fix] - schedules_event incrementation --- CHANGED | 2 +- FHEM/74_GardenaSmartDevice.pm | 2 +- controls_GardenaSmartDevice.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGED b/CHANGED index fd24b06..c935054 100644 --- a/CHANGED +++ b/CHANGED @@ -1 +1 @@ - [fix] - update event handled + [fix] - eventhandler ic24 diff --git a/FHEM/74_GardenaSmartDevice.pm b/FHEM/74_GardenaSmartDevice.pm index e327630..390144d 100644 --- a/FHEM/74_GardenaSmartDevice.pm +++ b/FHEM/74_GardenaSmartDevice.pm @@ -844,7 +844,7 @@ sub WriteReadings { && AttrVal( $name, 'model', 'unknown' ) !~ /sensor.?/ ) { readingsBulkUpdateIfChanged( $hash, 'scheduling-schedules_events_count', scalar( @{$decode_json->{scheduled_events} } ) ); - my $valve_id =1; my $event_id = 1; # ic24 [1..6] | wc, pump [1] + my $valve_id =1; my $event_id = 0; # ic24 [1..6] | wc, pump [1] for my $event_schedules ( @{ $decode_json->{scheduled_events} } ) { $valve_id = $event_schedules->{valve_id} if ( exists($event_schedules->{valve_id} ) ); #ic24 diff --git a/controls_GardenaSmartDevice.txt b/controls_GardenaSmartDevice.txt index 3cc2108..0ae6bb6 100644 --- a/controls_GardenaSmartDevice.txt +++ b/controls_GardenaSmartDevice.txt @@ -1,2 +1,2 @@ UPD 2022-07-21_19:43:48 49634 FHEM/73_GardenaSmartBridge.pm -UPD 2022-08-04_10:30:59 79000 FHEM/74_GardenaSmartDevice.pm +UPD 2022-08-04_10:33:44 79000 FHEM/74_GardenaSmartDevice.pm From 658f40e97998a04c3d573b6c65a8bcb6d9f5ca11 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Thu, 4 Aug 2022 14:39:44 +0200 Subject: [PATCH 13/29] [enhancemend] - commandref --- CHANGED | 2 +- FHEM/74_GardenaSmartDevice.pm | 528 +++++++++++++++++++++++++++----- controls_GardenaSmartDevice.txt | 2 +- 3 files changed, 448 insertions(+), 84 deletions(-) diff --git a/CHANGED b/CHANGED index c935054..7862540 100644 --- a/CHANGED +++ b/CHANGED @@ -1 +1 @@ - [fix] - eventhandler ic24 + [fix] - schedules_event incrementation diff --git a/FHEM/74_GardenaSmartDevice.pm b/FHEM/74_GardenaSmartDevice.pm index 390144d..b029290 100644 --- a/FHEM/74_GardenaSmartDevice.pm +++ b/FHEM/74_GardenaSmartDevice.pm @@ -845,7 +845,12 @@ sub WriteReadings { readingsBulkUpdateIfChanged( $hash, 'scheduling-schedules_events_count', scalar( @{$decode_json->{scheduled_events} } ) ); my $valve_id =1; my $event_id = 0; # ic24 [1..6] | wc, pump [1] - + ## valcid zahlen. readings mit valvid aber + for my $event_schedules ( @{ $decode_json->{scheduled_events} } ) { + while ( my ( $r, $v ) = each %{ $event_schedules } ) { + push $cloud $v; # cloud hat SOLL + } + } for my $event_schedules ( @{ $decode_json->{scheduled_events} } ) { $valve_id = $event_schedules->{valve_id} if ( exists($event_schedules->{valve_id} ) ); #ic24 $event_id++; # event id @@ -1394,38 +1399,40 @@ sub SetPredefinedStartPoints {

    GardenaSmartDevice

      - In combination with Fhem device GardenaSmartBridge this Fhem module enables communication between GardenaCloud and + In combination with Fhem device GardenaSmartBridge this Fhem module enables communication between GardenaCloud and fhem.

      Once the bridge device is created, the connected Gardena devices will be recognized and created in Fhem automatically.
      From now on these devices can be controlled via Fhem. Changes in the Gardena App are synchronized with state and - redings of the devices. + readings of the devices.

      So far, known devices are mower, smart water control, irrigation control, smart sensors, power plug and pressure - pump. Schedules can be disabled/enabled via fhem, defining or deleting them must be done via the Gardena App.
      + pump. Schedules can be disabled/enabled via fhem, defining or deleting them must be done via Gardena App or its web interface.

      Readings (model = mower)
        -
      • battery-charging - Indicator if the Battery is charged (0/1) or with newer Firmware (false/true)
      • -
      • battery-level - load percentage of the Battery
      • -
      • battery-rechargeable_battery_status - healthyness of the battery (out_of_operation/replace_now/low/ok)
      • +
      • Readings are based on Sileno, other models might have different/additional readings depending on their functions (tbd.)
      • +
        +
      • battery-charging - Indicator if battery is charged (0/1)
      • +
      • battery-level - load percentage of battery
      • +
      • battery-rechargeable_battery_status - healthyness of the battery (out_of_operation/replace_now/low/ok), not all models
      • device_info-category - category of device (mower/watering_computer)
      • +
      • device_info-connection_status - connection status (online/offline/unknown)
      • device_info-last_time_online - timestamp of last radio contact
      • device_info-manufacturer - manufacturer
      • device_info-product - product type
      • device_info-serial_number - serial number
      • -
      • device_info-sgtin -
      • +
      • device_info-sgtin - (tbd.)
      • device_info-version - firmware version
      • firmware-firmware_command - firmware command (idle/firmware_cancel/firmware_upload/unsupported)
      • firmware-firmware_status - firmware status
      • -
      • firmware-firmware_update_start - indicator when a firmwareupload is started
      • firmware-firmware_upload_progress - progress indicator of firmware update
      • firmware-inclusion_status - inclusion status
      • -
      • internal_temperature-temperature - internal device temperature
      • +
      • internal_temperature-temperature - internal device temperature, not all models
      • mower-error - actual error message
        • no_message
        • @@ -1476,8 +1483,7 @@ sub SetPredefinedStartPoints {
        • slipped
      • -
      • mower-manual_operation - (0/1) or with newer Firmware (false/true)
      • -
      • mower-override_end_time - manual override end time
      • +
      • mower-last_error_code - code of last error
      • mower-source_for_next_start - source for the next start
        • no_source
        • @@ -1488,11 +1494,31 @@ sub SetPredefinedStartPoints {
        • undefined
      • -
      • mower-status - mower state (see state)
      • +
      • mower-status - mower status (see state reading)
      • +
      • mower-timestamp_last_error_code - timestamp of last error
      • mower-timestamp_next_start - timestamp of next scheduled start
      • -
      • radio-connection_status - state of connection
      • +
      • mower_stats-charging_cycles - number of charging cycles
      • +
      • mower_stats-collisions - number of collisions
      • +
      • mower_stats-cutting_time - cutting time in hours
      • +
      • mower_stats-running_time - running time in hours (including cutting time)
      • +
      • mower_timer-mower_timer - (tbd.)
      • +
      • mower_timer-mower_timer_timestamp - (tbd.)
      • +
      • mower_type-base_software_up_to_date - latest software (0/1)
      • +
      • mower_type-device_type - device type
      • +
      • mower_type-device_variant - device variant
      • +
      • mower_type-mainboard_version - mainboard version
      • +
      • mower_type-mmi_version - mmi version
      • +
      • mower_type-serial_number - serial number
      • radio-quality - percentage of the radio quality
      • radio-state - radio state (bad/poor/good/undefined)
      • +
      • scheduling-schedules_event_1_end_at - ending time of schedule 1
      • +
      • scheduling-schedules_event_1_id - ID of schedule 1
      • +
      • scheduling-schedules_event_1_start_at - starting time of schedule 1
      • +
      • scheduling-schedules_event_1_weekly - weekdays of schedule 1(comma-separated)
      • +
      • ...more readings for additional schedules (if defined)
      • +
      • scheduling-schedules_events_count - number of pre-defined schedules
      • +
      • startpoint-1-enabled - starpoint 1 enabled (0/1)
      • +
      • ...more readings for additional startpoints
      • state - state of the mower
        • paused
        • @@ -1513,45 +1539,216 @@ sub SetPredefinedStartPoints {
        • ok_cutting_timer_overridden
        • parked_autotimer
        • parked_daily_limit_reached
        • +
        • hibernate - winter mode)
      • +
      • winter_mode - status of winter mode (awake/hibernate)


      Readings (model = watering_computer)
        -
      • [tbd.]
      • +
      • ambient_temperature-temperature - ambient temperature in Celsius
      • +
      • battery-disposable_battery_status - healthyness of the battery (ok/low/replace_now/out_of_operation/no_battery/unknown)
      • +
      • battery-level - energy level of battery in percent
      • +
      • device_info-category - category of device (mower/watering_computer/sensor/etc.)
      • +
      • device_info-connection_status - connection status (online/offline/unknown)
      • +
      • device_info-last_time_online - timestamp of last radio contact
      • +
      • device_info-manufacturer - manufacturer
      • +
      • device_info-product - product type
      • +
      • device_info-serial_number - serial number
      • +
      • device_info-sgtin - tbd.
      • +
      • device_info-version - firmware version
      • +
      • error-error - error message (tbd.)
      • +
      • error-valve_error_1_severity - (tbd.)
      • +
      • error-valve_error_1_type - (tbd.)
      • +
      • error-valve_error_1_valve_id - id of valve with error
      • +
      • firmware-firmware_available_version - new available firmware (only if available)
      • +
      • firmware-firmware_command - firmware command (idle/firmware_cancel/firmware_upload/unsupported)
      • +
      • firmware-firmware_status - firmware status
      • +
      • firmware-firmware_upload_progress - progress indicator of firmware update
      • +
      • firmware-inclusion_status - inclusion status
      • +
      • manualButtonTime - watering time for manual button on device in minutes
      • +
      • radio-quality - percentage of the radio quality
      • +
      • radio-state - radio state (bad/poor/good/undefined)
      • +
      • scheduling-scheduled_watering_end - next schedule ending time
      • +
      • scheduling-scheduled_watering_next_start - next schedule starting time
      • +
      • scheduling-schedules_event_1_valve_1_end_at - ending time of schedule 1
      • +
      • scheduling-schedules_event_1_valve_1_id - ID of schedule 1
      • +
      • scheduling-schedules_event_1_valve_1_start_at - starting time of schedule 1
      • +
      • scheduling-schedules_event_1_valve_1_weekly - weekdays of schedule 1
      • +
      • scheduling-schedules_events_count - number of pre-defined schedules
      • +
      • scheduling-schedules_paused_until - date/time until schedule is paused (2038-01-18T00:00:00.000Z is defined as permanently by Gardena cloud)
      • +
      • state - state of device
      • +
          +
        • closed - valve closed, no schedules available
        • +
        • closed. schedule permanently paused - valve closed, schedule disabled
        • +
        • closed. next watering: YYYY-MM-DD HH:MM - valve closed, next scheduled start at YYYY-MM-DDTHH:MM:00.000Z
        • +
        • watering. n minutes remaining. - watering, n minutes remaining (depending on manual button time or on pre-defined schedule)
        • +
        • offline - device is disabled/not connected
        • +
        • hibernate - winter mode)
        • +
        +
      • watering-watering_timer_1_duration - duration of current watering in seconds
      • +
      • watering-watering_timer_1_irrigation_left - remaining watering time in minutes
      • +
      • watering-watering_timer_1_state - state of schedule
      • +
      • watering-watering_timer_1_valve_id - valve id of schedule
      • +
      • winter_mode - status of winter mode (awake/hibernate)


      Readings (model = ic24) +
    • device_info-category - category of device (mower/watering_computer/sensor/etc.)
    • +
    • device_info-connection_status - connection status (online/offline/unknown)
    • +
    • device_info-last_time_online - timestamp of last radio contact
    • +
    • device_info-manufacturer - manufacturer
    • +
    • device_info-product - product type
    • +
    • device_info-serial_number - serial number
    • +
    • device_info-sgtin - tbd.
    • +
    • device_info-version - firmware version
    • +
    • error-error - error message (tbd.)
    • +
    • error-valve_error_0_severity - (tbd.)
    • +
    • error-valve_error_0_type - (tbd.)
    • +
    • error-valve_error_0_valve_id - id of valve with error
    • +
    • ...more error readings
    • +
    • firmware-firmware_available_version - new available firmware (only if available)
    • +
    • firmware-firmware_command - firmware command (idle/firmware_cancel/firmware_upload/unsupported)
    • +
    • firmware-firmware_status - firmware status
    • +
    • firmware-firmware_upload_progress - progress indicator of firmware update
    • +
    • firmware-inclusion_status - inclusion status
    • +
    • ic24-valves_connected - connected valves (comma separated)
    • +
    • ic24-valves_master_config - master valve (only if defined in Gardena app)
    • +
    • radio-quality - percentage of the radio quality
    • +
    • radio-state - radio state (bad/poor/good/undefined)
    • +
    • scheduling-scheduled_watering_end - next schedule ending time
    • +
    • scheduling-scheduled_watering_end_1 - next schedule ending time for valve 1
    • +
    • ...more readings for valves 2-6
    • +
    • scheduling-scheduled_watering_next_start - next schedule starting time
    • +
    • scheduling-scheduled_watering_next_start_1 - next schedule starting time for valve 1
    • +
    • ...more readings for valves 2-6
    • +
    • scheduling-schedules_event_1_valve_1_end_at - ending time of schedule 1
    • +
    • scheduling-schedules_event_1_valve_1_id - ID of schedule 1
    • +
    • scheduling-schedules_event_1_valve_1_start_at - starting time of schedule 1
    • +
    • scheduling-schedules_event_1_valve_1_weekly - weekdays of schedule 1
    • +
    • scheduling-schedules_events_count - number of pre-defined schedules
    • +
    • ...more readings for further schedules/valves
    • +
    • scheduling-schedules_paused_until_1 - date/time until schedule is paused (2038-01-18T00:00:00.000Z is defined as permanently by Gardena cloud)
    • +
    • ...more readings for valves 2-6
    • +
    • state - state of device
    • +
        +
      • closed - valve closed, no schedules available
      • +
      • closed. schedule permanently paused - valve closed, all schedules disabled/paused
      • +
      • closed. next watering: YYYY-MM-DD HH:MM - valve closed, next scheduled start at YYYY-MM-DDTHH:MM:00.000Z
      • +
      • watering. n minutes remaining. - watering, n minutes remaining. If more than one schedule is active, the longer remaining time is shown.
      • +
      • offline - device is disabled/not connected
      • +
      +
    • valve-valve_name_1 - individual name for valve 1
    • +
    • ...more readings for valves 2-6 (if installed)
    • +
    • watering-watering_timer_1_duration - duration of current watering in seconds
    • +
    • watering-watering_timer_1_irrigation_left - remaining watering time in minutes
    • +
    • watering-watering_timer_1_state - state of schedule
    • +
    • watering-watering_timer_1_valve_id - valve id of schedule
    • +
    • ...more readings for further valves/schedules
    • +
    • winter_mode - status of winter mode (awake/hibernate)
    • +

      + Readings (model = sensor)
        -
      • [tbd.]
      • +
      • ambient_temperature-frost_warning - frost warning
      • +
      • ambient_temperature-temperature - ambient temperature in Celsius
      • +
      • battery-disposable_battery_status - healthyness of the battery (ok/low/replace_now/out_of_operation/no_battery/unknown)
      • +
      • battery-level - energy level of battery in percent
      • +
      • device_info-category - category of device (mower/watering_computer/sensor/etc.)
      • +
      • device_info-connection_status - connection status (online/offline/unknown)
      • +
      • device_info-last_time_online - timestamp of last radio contact
      • +
      • device_info-manufacturer - manufacturer
      • +
      • device_info-product - product type
      • +
      • device_info-serial_number - serial number
      • +
      • device_info-sgtin - tbd.
      • +
      • device_info-version - firmware version
      • +
      • firmware-firmware_available_version - new available firmware (only if available)
      • +
      • firmware-firmware_command - firmware command (idle/firmware_cancel/firmware_upload/unsupported)
      • +
      • firmware-firmware_status - firmware status
      • +
      • firmware-firmware_upload_progress - progress indicator of firmware update
      • +
      • firmware-inclusion_status - inclusion status
      • +
      • humidity-humidity - humidity in percent
      • +
      • light-light - brightness in lux
      • +
      • radio-quality - percentage of the radio quality
      • +
      • radio-state - radio state (bad/poor/good/undefined)
      • +
      • soil_temperature-temperature - soil temperature in Celsius
      • +
      • state - state of sensor (temperature (T:), humidity (H:), brightness/light (L:)
      • +
      • winter_mode - status of winter mode (awake/hibernate)


      Readings (model = sensor)
        -
      • [tbd.]
      • +
      • ambient_temperature-frost_warning - frost warning
      • +
      • ambient_temperature-temperature - ambient temperature in Celsius
      • +
      • battery-disposable_battery_status - healthyness of the battery (ok/low/replace_now/out_of_operation/no_battery/unknown)
      • +
      • battery-level - energy level of battery in percent
      • +
      • device_info-category - category of device (mower/watering_computer/sensor/etc.)
      • +
      • device_info-connection_status - connection status (online/offline/unknown)
      • +
      • device_info-last_time_online - timestamp of last radio contact
      • +
      • device_info-manufacturer - manufacturer
      • +
      • device_info-product - product type
      • +
      • device_info-serial_number - serial number
      • +
      • device_info-sgtin - tbd.
      • +
      • device_info-version - firmware version
      • +
      • firmware-firmware_available_version - new available firmware (only if available)
      • +
      • firmware-firmware_command - firmware command (idle/firmware_cancel/firmware_upload/unsupported)
      • +
      • firmware-firmware_status - firmware status
      • +
      • firmware-firmware_upload_progress - progress indicator of firmware update
      • +
      • firmware-inclusion_status - inclusion status
      • +
      • humidity-humidity - humidity in percent
      • +
      • light-light - brightness in lux
      • +
      • radio-quality - percentage of the radio quality
      • +
      • radio-state - radio state (bad/poor/good/undefined)
      • +
      • soil_temperature-temperature - soil temperature in Celsius
      • +
      • state - state of sensor (temperature (T:), humidity (H:), brightness/light (L:)|offline|hibernate)
      • +
      • winter_mode - status of winter mode (awake/hibernate)


      Readings (model = sensor2)
        -
      • [tbd.]
      • +
      • "sensor2" does not measure brightness or ambient temperature, and it has another reading for frost warning. Other than that, it seems to be more or less identical to "sensor".
      • +
        +
      • battery-disposable_battery_status - healthyness of the battery (ok/low/replace_now/out_of_operation/no_battery/unknown)
      • +
      • battery-level - energy level of battery in percent
      • +
      • device_info-category - category of device (mower/watering_computer/sensor/etc.)
      • +
      • device_info-connection_status - connection status (online/offline/unknown)
      • +
      • device_info-last_time_online - timestamp of last radio contact
      • +
      • device_info-manufacturer - manufacturer
      • +
      • device_info-product - product type
      • +
      • device_info-serial_number - serial number
      • +
      • device_info-sgtin - tbd.
      • +
      • device_info-version - firmware version
      • +
      • firmware-firmware_available_version - new available firmware (only if available)
      • +
      • firmware-firmware_command - firmware command (idle/firmware_cancel/firmware_upload/unsupported)
      • +
      • firmware-firmware_status - firmware status
      • +
      • firmware-firmware_upload_progress - progress indicator of firmware update
      • +
      • firmware-inclusion_status - inclusion status
      • +
      • humidity-humidity - humidity in percent
      • +
      • radio-quality - percentage of the radio quality
      • +
      • radio-state - radio state (bad/poor/good/undefined)
      • +
      • soil_model-model_definition - tbd.
      • +
      • soil_model-model_status - tbd.
      • +
      • soil_temperature-frost-warning - frost warning
      • +
      • soil_temperature-temperature - soil temperature in Celsius
      • +
      • state - state of sensor (temperature (T:), humidity (H:)|offline|hibernate)
      • +
      • winter_mode - status of winter mode (awake/hibernate)


      Readings (model = power)
        -
      • [tbd.]
      • +
      • (tbd.)


      Readings (model = electronic_pressure_pump)
        -
      • [tbd.]
      • +
      • (tbd.)


      Attribute
      • IODev - Name of GardenaSmartBridge device
      • -
      • extendedState 0|1 - [tbd.]
      • +
      • extendedState 0|1 - (tbd.)
      • model watering_computer|sensor|sensor2|mower|ic24|power|electronic_pressure_pump - model of GardenaSmartDevice
      • readingValueLanguage en|de - Reading language enlish or german (default: english, if global language is not @@ -1619,12 +1816,12 @@ sub SetPredefinedStartPoints {

        set (model = power)
          -
        • [tbd.]
        • +
        • (tbd.)


        set (model = electronic_pressure_pump)
          -
        • [tbd.]
        • +
        • (tbd.)
      @@ -1638,42 +1835,44 @@ sub SetPredefinedStartPoints { Zusammen mit dem Device GardenaSmartBridge stellt dieses Fhem-Modul die Kommunikation zwischen der GardenaCloud und Fhem her.

      - Wenn das GardenaSmartBridge Device erzeugt wurde, werden verbundene Geräte automatisch erkannt und in Fhem angelegt. + Wenn das GardenaSmartBridge Device erzeugt wurde, werden verbundene Geräte automatisch erkannt und in Fhem angelegt.
      - Von nun an können die eingebundenen Geräte gesteuert werden. Änderungen in der App werden mit den Readings und dem + Von nun an können die eingebundenen Geräte gesteuert werden. änderungen in der App werden mit den Readings und dem Status synchronisiert.

      - Bekannte Gardena-Geräte umfassen Rasenmäher, Smart Water Control, Irrigation Control, Smart Sensoren, - Steckdosen-Adapter und Pumpe. Zeitpläne können über fhem pausiert/aktiviert werden, das Anlegen oder Löschen erfolgt - derzeit nur über die App. + Bekannte Gardena-Geräte umfassen Rasenmäher, Smart Water Control, Irrigation Control, Smart Sensoren, + Steckdosen-Adapter und Pumpe. Zeitpläne können über fhem pausiert/aktiviert werden, das Anlegen oder Löschen erfolgt + derzeit nur über die App oder deren Web-Frontend.

      - Readings (model = mower) + Readings (model = mower/Mäher)
        -
      • battery-charging - Ladeindikator (0/1) oder mit neuerer Firmware (false/true)
      • +
      • Readings basieren auf dem Modell Sileno, andere Modelle haben abweichende/zusätzliche Readings abhängig von ihren Funktionen (tbd.)
      • +
        +
      • battery-charging - Ladeindikator (0/1)
      • battery-level - Ladezustand der Batterie in Prozent
      • battery-rechargeable_battery_status - Zustand der Batterie (Ausser Betrieb/Kritischer Batteriestand, - wechseln Sie jetzt/Niedrig/oK)
      • + wechseln Sie jetzt/Niedrig/oK), nicht bei allen Modellen +
      • device_info-connection_status - Verbindungs-Status (online/offline/unknown)
      • device_info-category - Eigenschaft des Gerätes (Mäher/Bewässerungscomputer/Bodensensor)
      • device_info-last_time_online - Zeitpunkt der letzten Funkübertragung
      • device_info-manufacturer - Hersteller
      • device_info-product - Produkttyp
      • device_info-serial_number - Seriennummer
      • -
      • device_info-sgtin -
      • +
      • device_info-sgtin - (tbd.)
      • device_info-version - Firmware Version
      • firmware-firmware_command - Firmware Kommando (Nichts zu tun/Firmwareupload unterbrochen/Firmwareupload/nicht unterstützt)
      • firmware-firmware_status - Firmware Status
      • -
      • firmware-firmware_update_start - Firmwareupdate (0/1) oder mit neuerer Firmware (false/true)
      • firmware-firmware_upload_progress - Firmwareupdatestatus in Prozent
      • firmware-inclusion_status - Einbindungsstatus
      • -
      • internal_temperature-temperature - Interne Geräte Temperatur
      • +
      • internal_temperature-temperature - Interne Geräte Temperatur, nicht bei allen Modellen
      • mower-error - Aktuelle Fehler Meldung
        • Kein Fehler
        • -
        • Außerhalb des Arbeitsbereichs
        • +
        • Ausserhalb des Arbeitsbereichs
        • Kein Schleifensignal
        • Falsches Schleifensignal
        • Problem Schleifensensor, vorne
        • @@ -1686,8 +1885,8 @@ sub SetPredefinedStartPoints {
        • Angehoben
        • Eingeklemmt in Ladestation
        • Ladestation blockiert
        • -
        • Problem Stoßsensor hinten
        • -
        • Problem Stoßsensor vorne
        • +
        • Problem Stosssensor hinten
        • +
        • Problem Stosssensor vorne
        • Radmotor rechts blockiert
        • Radmotor links blockiert
        • Problem Antrieb, rechts
        • @@ -1714,13 +1913,12 @@ sub SetPredefinedStartPoints {
        • Alarm! Mäher gestoppt
        • Alarm! Mäher angehoben
        • Alarm! Mäher gekippt
        • -
        • Verbindung geändert
        • +
        • Verbindung geändert
        • Verbindung nicht geändert
        • COM board nicht verfügbar
        • Rutscht
      • -
      • mower-manual_operation - Manueller Betrieb (0/1) oder mit neuerer Firmware (false/true)
      • mower-override_end_time - Zeitpunkt wann der manuelle Betrieb beendet ist
      • mower-source_for_next_start - Grund für den nächsten Start
          @@ -1733,11 +1931,31 @@ sub SetPredefinedStartPoints {
      • mower-status - Mäher Status (siehe state)
      • +
      • mower-timestamp_last_error_code - Zeitpunkt des letzten Fehlers
      • mower-timestamp_next_start - Zeitpunkt des nächsten geplanten Starts
      • -
      • radio-connection_status - Status der Funkverbindung
      • +
      • mower_stats-charging_cycles - Anzahl Ladezyklen
      • +
      • mower_stats-collisions - Anzahl Zusammenstösse
      • +
      • mower_stats-cutting_time - Schnittzeit in Stunden
      • +
      • mower_stats-running_time - Laufzeit in Stunden (inkl. Schnittzeit)
      • +
      • mower_timer-mower_timer - (tbd.)
      • +
      • mower_timer-mower_timer_timestamp - (tbd.)
      • +
      • mower_type-base_software_up_to_date - Software aktuell (0/1)
      • +
      • mower_type-device_type - Gerätetyp
      • +
      • mower_type-device_variant - Gerätevariante
      • +
      • mower_type-mainboard_version - Mainboard-Version
      • +
      • mower_type-mmi_version - MMI-Version
      • +
      • mower_type-serial_number - Seriennummer
      • radio-quality - Indikator für die Funkverbindung in Prozent
      • -
      • radio-state - radio state (schlecht/schwach/gut/Undefiniert)
      • -
      • state - Staus des Mähers +
      • radio-state - Verbindungsqualität (schlecht/schwach/gut/Undefiniert)
      • +
      • scheduling-schedules_event_1_end_at - Endzeit des Zeitplans 1
      • +
      • scheduling-schedules_event_1_id - ID des Zeitplans 1
      • +
      • scheduling-schedules_event_1_start_at - Startzeit des Zeitplans 1
      • +
      • scheduling-schedules_event_1_weekly - Wochentage des Zeitplans 1 (kommagetrennt)
      • +
      • ...weitere Readings für zusätzliche Zeitpläne (falls angelegt)
      • +
      • scheduling-schedules_events_count - Anzahl angelegter Zeitpläne
      • +
      • startpoint-1-enabled - starpoint 1 enabled (0/1)
      • +
      • ...weitere Readings für zusätzliche Startpunkte (falls angelegt)
      • +
      • state - Status des Mähers
        • Pausiert
        • Mähen
        • @@ -1757,38 +1975,183 @@ sub SetPredefinedStartPoints {
        • Manuelles Mähen
        • Geparkt durch SensorControl
        • Abgeschlossen
        • +
        • Winterschlaf - Gerät ist im Winterschlaf
        -
      • +
      • winter_mode - Status Winterschlaf (awake/hibernate)


      - Readings (model = watering_computer) + Readings (model = watering_computer/Bewässerungscomputer)
        -
      • [tbd.]
      • +
      • ambient_temperature-temperature - Umgebungstemperatur in Celsius
      • +
      • battery-disposable_battery_status - Batteriezustand
      • +
      • battery-level - Ladezustand der Batterie in Prozent
      • +
      • device_info-category - Art des Geräts
      • +
      • device_info-connection_status - Verbindungsstatus (online/offline/unknown)
      • +
      • device_info-last_time_online - Zeitpunkt der letzten Funkübertragung
      • +
      • device_info-manufacturer - Hersteller
      • +
      • device_info-product - Produkttyp
      • +
      • device_info-serial_number - Seriennummer
      • +
      • device_info-sgtin - (tbd.)
      • +
      • device_info-version - Firmware Version
      • +
      • error-error - Fehlermeldung (tbd.)
      • +
      • error-valve_error_1_severity - (tbd.)
      • +
      • error-valve_error_1_type - (tbd.)
      • +
      • error-valve_error_1_valve_id - ID des fehlerhaften Ventils
      • +
      • firmware-firmware_available_version - Neue Firmware (nur wenn verfügbar)
      • +
      • firmware-firmware_command - Firmware-Kommando (idle/firmware_cancel/firmware_upload/unsupported)
      • +
      • firmware-firmware_status - Firmware Status
      • +
      • firmware-firmware_upload_progress - Firmwareupdatestatus in Prozent
      • +
      • firmware-inclusion_status - Einbindungsstatus
      • +
      • manualButtonTime - Bewässerungszeit für den Geräte-Knopf in Minuten
      • +
      • radio-quality - Indikator für die Funkverbindung in Prozent
      • +
      • radio-state - Verbindungsqualität (schlecht/schwach/gut/Undefiniert)
      • +
      • scheduling-scheduled_watering_end - Endzeit des nächsten Zeitplans
      • +
      • scheduling-scheduled_watering_next_start - Startzeit des nächsten Zeitplans
      • +
      • scheduling-schedules_event_1_valve_1_end_at - Endzeit von Zeitplan 1
      • +
      • scheduling-schedules_event_1_valve_1_id - ID von Zeitplan 1
      • +
      • scheduling-schedules_event_1_valve_1_start_at - Startzeit von Zeitplan 1
      • +
      • scheduling-schedules_event_1_valve_1_weekly - Wochentage von Zeitplan 1
      • +
      • scheduling-schedules_events_count - Anzahl angelegter Zeitpläne
      • +
      • scheduling-schedules_paused_until - Datum/Uhrzeit, bis wann Zeitplan pausiert ist (2038-01-18T00:00:00.000Z wird von Gardena-Cloud als dauerhaft angesehen)
      • +
      • state - Status des Geräts
      • +
          +
        • geschossen - Ventil geschlossen, keine Zeitpläne definiert
        • +
        • geschlossen. Zeitplan dauerhaft pausiert - Ventil geschlossen, Zeitplan dauerhaft pausiert
        • +
        • geschlossen. Nächste Bewässerung: YYYY-MM-DD HH:MM - Ventil geschlossen, nächster Zeitplan-Start YYYY-MM-DDTHH:MM:00.000Z
        • +
        • will be irrigated n minutes remaining. - watering, n minutes remaining (depending on manual button time or on pre-defined schedule)
        • +
        • offline - Gerät ist ausgeschaltet/hat keine Verbindung
        • +
        • Winterschlaf - Gerät ist im Winterschlaf
        • +
        +
      • watering-watering_timer_1_duration - Gesamt-Dauer der aktuellen Bewässerung in Sekunden
      • +
      • watering-watering_timer_1_irrigation_left - Verbleibende Bewässerungszeit in Minuten
      • +
      • watering-watering_timer_1_state - Status des Zeitplans
      • +
      • watering-watering_timer_1_valve_id - Ventil-ID des Zeitplans
      • +
      • winter_mode - Status Winterschlaf (awake/hibernate)


      Readings (model = ic24) -
        -
      • [tbd.]
      • +
          +
        • device_info-category - Art des Geräts
        • +
        • device_info-connection_status - Verbindungsstatus (online/offline/unknown)
        • +
        • device_info-last_time_online - Zeitpunkt der letzten Funkübertragung
        • +
        • device_info-manufacturer - Hersteller
        • +
        • device_info-product - Produkttyp
        • +
        • device_info-serial_number - Seriennummer
        • +
        • device_info-sgtin - (tbd.)
        • +
        • device_info-version - Firmware Version
        • +
        • error-error - Fehlermeldung (tbd.)
        • +
        • error-valve_error_0_severity - (tbd.)
        • +
        • error-valve_error_0_type - (tbd.)
        • +
        • error-valve_error_0_valve_id - ID des fehlerhaften Ventils
        • +
        • ...ggf. weitere Error-Readings
        • +
        • firmware-firmware_available_version - Neue Firmware (nur wenn verfügbar)
        • +
        • firmware-firmware_command - Firmware-Kommando (idle/firmware_cancel/firmware_upload/unsupported)
        • +
        • firmware-firmware_status - Firmware Status
        • +
        • firmware-firmware_upload_progress - Firmwareupdatestatus in Prozent
        • +
        • firmware-inclusion_status - Einbindungsstatus
        • +
        • ic24-valves_connected - Verbundene Ventile (ID, kommagetrennt)
        • +
        • ic24-valves_master_config - Masterventil (nur, wenn in Gardena-App definiert)
        • +
        • radio-quality - Indikator für die Funkverbindung in Prozent
        • +
        • radio-state - Verbindungsqualität (schlecht/schwach/gut/Undefiniert)
        • +
        • scheduling-scheduled_watering_end - Endzeit des nächsten Zeitplans
        • +
        • scheduling-scheduled_watering_end_1 - Endzeit des nächsten Zeitplans für Ventil 1
        • +
        • ...weitere Readings für Ventile 2-6
        • +
        • scheduling-scheduled_watering_next_start - Startzeit des nächsten Zeitplans
        • +
        • scheduling-scheduled_watering_next_start_1 - Startzeit des nächsten Zeitplans für Ventil 1
        • +
        • ...weitere Readings für Ventile 2-6
        • +
        • scheduling-schedules_event_1_valve_n_end_at - Endzeit des ersten definierten Zeitplans für Ventil n
        • +
        • scheduling-schedules_event_1_valve_n_id - ID des ersten definierten Zeitplans für Ventil n
        • +
        • scheduling-schedules_event_1_valve_n_start_at - Startzeit des ersten definierten Zeitplans für Ventil n
        • +
        • scheduling-schedules_event_1_valve_n_weekly - Wochentage des ersten definierten Zeitplans für Ventil n
        • +
        • scheduling-schedules_events_count - Anzahl angelegter Zeitpläne
        • +
        • ...weitere Readings für zusätzliche Zeitpläne/Ventile
        • +
        • scheduling-schedules_paused_until_1 - Datum/Uhrzeit, bis wann Zeitplan pausiert ist (2038-01-18T00:00:00.000Z wird von Gardena-Cloud als dauerhaft angesehen)
        • +
        • ...weitere Readings für Ventile 2-6
        • +
        • state - Status des Geräts
        • +
            +
          • geschossen - Ventil geschlossen, keine Zeitpläne definiert
          • +
          • geschlossen. Zeitplan dauerhaft pausiert - Ventil geschlossen, Zeitplan dauerhaft pausiert
          • +
          • geschlossen. Nächste Bewässerung: YYYY-MM-DD HH:MM - Ventil geschlossen, nächster Zeitplan-Start YYYY-MM-DDTHH:MM:00.000Z
          • +
          • wird bewässert. n Minuten verbleibend - Bewässerung aktiv, n Minuten verbleibend (wenn 2 Ventile geöffnet sind, wird die längere Dauer angezeigt)
          • +
          • offline - Gerät ist ausgeschaltet/hat keine Verbindung
          • +
          • Winterschlaf - Gerät ist im Winterschlaf
          • +
          +
        • valve-valve_name_1 - Eigener Name für Ventil 1
        • +
        • ...weitere Readings für Ventile 2-6 (if installed)
        • +
        • watering-watering_timer_1_duration - Gesamt-Dauer der aktuellen Bewässerung in Sekunden
        • +
        • watering-watering_timer_1_irrigation_left - Verbleibende Dauer der aktuellen Bewässerung in Minuten
        • +
        • watering-watering_timer_1_state - Status des Timers
        • +
        • watering-watering_timer_1_valve_id - Ventil-ID des Timers
        • +
        • ...weitere Readings für weitere Ventile/Zeitpläne
        • +
        • winter_mode - Status Winterschlaf (awake/hibernate)


        Readings (model = sensor)
          -
        • [tbd.]
        • +
        • ambient_temperature-frost_warning - Frostwarnung
        • +
        • ambient_temperature-temperature - Umgebungstemperatur in Celsius
        • +
        • battery-disposable_battery_status - Batteriezustand
        • +
        • battery-level - Ladezustand der Batterie in Prozent
        • +
        • device_info-category - Art des Geräts
        • +
        • device_info-connection_status - Verbindungsstatus (online/offline/unknown)
        • +
        • device_info-last_time_online - Zeitpunkt der letzten Funkübertragung
        • +
        • device_info-manufacturer - Hersteller
        • +
        • device_info-product - Produkttyp
        • +
        • device_info-serial_number - Seriennummer
        • +
        • device_info-sgtin - (tbd.)
        • +
        • device_info-version - Firmware Version
        • +
        • firmware-firmware_available_version - Neue Firmware (nur wenn verfügbar)
        • +
        • firmware-firmware_command - Firmware-Kommando (idle/firmware_cancel/firmware_upload/unsupported)
        • +
        • firmware-firmware_status - Firmware Status
        • +
        • firmware-firmware_upload_progress - Firmwareupdatestatus in Prozent
        • +
        • firmware-inclusion_status - Einbindungsstatus
        • +
        • humidity-humidity - Feuchtigkeit in Prozent
        • +
        • light-light - Helligkeit in Lux
        • +
        • radio-quality - Indikator für die Funkverbindung in Prozent
        • +
        • radio-state - Verbindungsqualität (schlecht/schwach/gut/Undefiniert)
        • +
        • soil_temperature-temperature - Erd-Temperatur in Celsius
        • +
        • state - Status (Temperatur (T:), Feuchtigkeit (H:), Helligkeit (L:)|offline|Winterschlaf)
        • +
        • winter_mode - Status Winterschlaf (awake/hibernate)


        Readings (model = sensor2)
          -
        • [tbd.]
        • +
        • "sensor2" hat keine Helligkeitsmessung oder Umgebungstemperatur, und es legt die Frost-Warnung in einem anderen Reading ab. Ansonsten ist er mehr oder weniger identisch zum "sensor".
        • +
          +
        • battery-disposable_battery_status - Batteriezustand
        • +
        • battery-level - Ladezustand der Batterie in Prozent
        • +
        • device_info-category - Art des Geräts
        • +
        • device_info-connection_status - Verbindungsstatus (online/offline/unknown)
        • +
        • device_info-last_time_online - Zeitpunkt der letzten Funkübertragung
        • +
        • device_info-manufacturer - Hersteller
        • +
        • device_info-product - Produkttyp
        • +
        • device_info-serial_number - Seriennummer
        • +
        • device_info-sgtin - (tbd.)
        • +
        • device_info-version - Firmware Version
        • +
        • firmware-firmware_available_version - Neue Firmware (nur wenn verfügbar)
        • +
        • firmware-firmware_command - Firmware-Kommando (idle/firmware_cancel/firmware_upload/unsupported)
        • +
        • firmware-firmware_status - Firmware Status
        • +
        • firmware-firmware_upload_progress - Firmwareupdatestatus in Prozent
        • +
        • firmware-inclusion_status - Einbindungsstatus
        • +
        • humidity-humidity - Feuchtigkeit in Prozent
        • +
        • radio-quality - Indikator für die Funkverbindung in Prozent
        • +
        • radio-state - Verbindungsqualität (schlecht/schwach/gut/Undefiniert)
        • +
        • soil_model-model_definition - (tbd.)
        • +
        • soil_model-model_status - (tbd.)
        • +
        • soil_temperature-frost-warning - Frostwarnung
        • +
        • soil_temperature-temperature - Erd-Temperatur in Celsius
        • +
        • state - Status (Temperatur (T:), Feuchtigkeit (H:), Helligkeit (L:)|offline|Winterschlaf)
        • +
        • winter_mode - Status Winterschlaf (awake/hibernate)


        Readings (model = power)
          -
        • [tbd.]
        • +
        • (tbd.)


        Readings (model = electronic_pressure_pump)
          -
        • [tbd.]
        • +
        • (tbd.)


        @@ -1805,77 +2168,78 @@ sub SetPredefinedStartPoints { set (model = mower)
          -
        • parkUntilFurtherNotice - Parken des Mähers und Aussetzen des Zeitplans
        • -
        • parkUntilNextTimer - Parken bis zum nächsten Start nach Zeitplan
        • -
        • startOverrideTimer n - Manuelles Mähen für n Minuten (z.B. 60 = 1h, 1440 = 24h, 4320 = 72h)
        • +
        • parkUntilFurtherNotice - Parken des Mähers und Aussetzen des Zeitplans
        • +
        • parkUntilNextTimer - Parken bis zum nächsten Start nach Zeitplan
        • +
        • startOverrideTimer n - Manuelles Mähen für n Minuten (z.B. 60 = 1h, 1440 = 24h, 4320 = 72h)
        • startResumeSchedule - Zeitplan wieder aktivieren
        • startPoint enable|disable 1|2|3 - Aktiviert oder deaktiviert einen vordefinierten Startbereich
          • set NAME startpoint enable 1
          • set NAME startpoint disable 3 enable 1
          -
        • winter_mode awake|hibernate - Winterschlaf aktivieren oder Gerät aufwecken
        • +
        • winter_mode awake|hibernate - Winterschlaf aktivieren oder Gerät aufwecken


        set (model = watering_computer)
          -
        • cancelOverride - (Manuelle) Bewässerung stoppen
        • -
        • manualButtonTime n - Bewässerungsdauer für manuellen Knopf auf n Minuten setzen (0 schaltet den Knopf aus) +
        • cancelOverride - (Manuelle) Bewässerung stoppen
        • +
        • manualButtonTime n - Bewässerungsdauer für manuellen Knopf auf n Minuten setzen (0 schaltet den Knopf aus)
        • -
        • manualOverride n - Manuelle Bewässerung für n Minuten
        • +
        • manualOverride n - Manuelle Bewässerung für n Minuten
        • resumeSchedule - Zeitplan wieder aktivieren
        • -
        • stopSchedule n - Zeitplan anhalten für n Stunden (Default: 2038-01-18T00:00:00.000Z, durch Gardena-App als +
        • stopSchedule n - Zeitplan anhalten für n Stunden (Default: 2038-01-18T00:00:00.000Z, durch Gardena-App als "dauerhaft" interpretiert)
        • -
        • winter_mode awake|hibernate - Winterschlaf aktivieren oder Gerät aufwecken
        • +
        • winter_mode awake|hibernate - Winterschlaf aktivieren oder Gerät aufwecken


        set (model = ic24)
          -
        • cancelOverrideValve1 - (Manuelle) Bewässerung an Ventil 1 stoppen
        • -
        • cancelOverrideValve2 - (Manuelle) Bewässerung an Ventil 2 stoppen
        • -
        • cancelOverrideValve3 - (Manuelle) Bewässerung an Ventil 3 stoppen
        • -
        • cancelOverrideValve4 - (Manuelle) Bewässerung an Ventil 4 stoppen
        • -
        • cancelOverrideValve5 - (Manuelle) Bewässerung an Ventil 5 stoppen
        • -
        • cancelOverrideValve6 - (Manuelle) Bewässerung an Ventil 6 stoppen
        • -
        • closeAllValves - Alle Ventile schließen
        • -
        • manualDurationValve1 n - Ventil 1 für n Minuten öffnen
        • -
        • manualDurationValve2 n - Ventil 2 für n Minuten öffnen
        • -
        • manualDurationValve3 n - Ventil 3 für n Minuten öffnen
        • -
        • manualDurationValve4 n - Ventil 4 für n Minuten öffnen
        • -
        • manualDurationValve5 n - Ventil 5 für n Minuten öffnen
        • -
        • manualDurationValve6 n - Ventil 6 für n Minuten öffnen
        • -
        • resumeScheduleValve n - Zeitplan für Ventil n wieder aktivieren
        • -
        • stopScheduleValve n m - Zeitplan für Ventil n anhalten für m Stunden (Default: 2038-01-18T00:00:00.000Z, +
        • cancelOverrideValve1 - (Manuelle) Bewässerung an Ventil 1 stoppen
        • +
        • cancelOverrideValve2 - (Manuelle) Bewässerung an Ventil 2 stoppen
        • +
        • cancelOverrideValve3 - (Manuelle) Bewässerung an Ventil 3 stoppen
        • +
        • cancelOverrideValve4 - (Manuelle) Bewässerung an Ventil 4 stoppen
        • +
        • cancelOverrideValve5 - (Manuelle) Bewässerung an Ventil 5 stoppen
        • +
        • cancelOverrideValve6 - (Manuelle) Bewässerung an Ventil 6 stoppen
        • +
        • closeAllValves - Alle Ventile schliessen
        • +
        • manualDurationValve1 n - Ventil 1 für n Minuten öffnen
        • +
        • manualDurationValve2 n - Ventil 2 für n Minuten öffnen
        • +
        • manualDurationValve3 n - Ventil 3 für n Minuten öffnen
        • +
        • manualDurationValve4 n - Ventil 4 für n Minuten öffnen
        • +
        • manualDurationValve5 n - Ventil 5 für n Minuten öffnen
        • +
        • manualDurationValve6 n - Ventil 6 für n Minuten öffnen
        • +
        • resumeScheduleValve n - Zeitplan für Ventil n wieder aktivieren
        • +
        • stopScheduleValve n m - Zeitplan für Ventil n anhalten für m Stunden (Default: 2038-01-18T00:00:00.000Z, durch Gardena-App als "dauerhaft" interpretiert)
        • -
        • winter_mode awake|hibernate - Winterschlaf aktivieren oder Gerät aufwecken
        • +
        • winter_mode awake|hibernate - Winterschlaf aktivieren oder Gerät aufwecken


        set (model = sensor)
          -
        • refresh temperature|humidity|light - Sensorwert für Temperatur, Feuchtigkeit oder Helligkeit aktualisieren +
        • refresh temperature|humidity|light - Sensorwert für Temperatur, Feuchtigkeit oder Helligkeit aktualisieren
        • -
        • winter_mode awake|hibernate - Winterschlaf aktivieren oder Gerät aufwecken
        • +
        • winter_mode awake|hibernate - Winterschlaf aktivieren oder Gerät aufwecken


        set (model = sensor2)
          -
        • refresh temperature|humidity - Sensorwert für Temperatur oder Feuchtigkeit aktualisieren
        • -
        • winter_mode awake|hibernate - Winterschlaf aktivieren oder Gerät aufwecken
        • +
        • refresh temperature|humidity - Sensorwert für Temperatur oder Feuchtigkeit aktualisieren
        • +
        • winter_mode awake|hibernate - Winterschlaf aktivieren oder Gerät aufwecken


        set (model = power)
          -
        • [tbd.]
        • +
        • (tbd.)


        set (model = electronic_pressure_pump)
          -
        • [tbd.]
        • +
        • (tbd.)
      =end html_DE + =for :application/json;q=META.json 74_GardenaSmartDevice.pm { "abstract": "Modul to control GardenaSmart Devices", diff --git a/controls_GardenaSmartDevice.txt b/controls_GardenaSmartDevice.txt index 0ae6bb6..5f78179 100644 --- a/controls_GardenaSmartDevice.txt +++ b/controls_GardenaSmartDevice.txt @@ -1,2 +1,2 @@ UPD 2022-07-21_19:43:48 49634 FHEM/73_GardenaSmartBridge.pm -UPD 2022-08-04_10:33:44 79000 FHEM/74_GardenaSmartDevice.pm +UPD 2022-08-04_14:38:54 107236 FHEM/74_GardenaSmartDevice.pm From ada7e2875c8dfc4dc075fcd62646793aaf3e5fa0 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Thu, 4 Aug 2022 14:44:35 +0200 Subject: [PATCH 14/29] [fix] - fix --- CHANGED | 2 +- FHEM/74_GardenaSmartDevice.pm | 11 ++++++----- controls_GardenaSmartDevice.txt | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/CHANGED b/CHANGED index 7862540..6883ea6 100644 --- a/CHANGED +++ b/CHANGED @@ -1 +1 @@ - [fix] - schedules_event incrementation + [enhancemend] - commandref diff --git a/FHEM/74_GardenaSmartDevice.pm b/FHEM/74_GardenaSmartDevice.pm index b029290..331d9df 100644 --- a/FHEM/74_GardenaSmartDevice.pm +++ b/FHEM/74_GardenaSmartDevice.pm @@ -846,11 +846,12 @@ sub WriteReadings { scalar( @{$decode_json->{scheduled_events} } ) ); my $valve_id =1; my $event_id = 0; # ic24 [1..6] | wc, pump [1] ## valcid zahlen. readings mit valvid aber - for my $event_schedules ( @{ $decode_json->{scheduled_events} } ) { - while ( my ( $r, $v ) = each %{ $event_schedules } ) { - push $cloud $v; # cloud hat SOLL - } - } + # my @soll = (); + # for my $event_schedules ( @{ $decode_json->{scheduled_events} } ) { + # while ( my ( $r, $v ) = each %{ $event_schedules } ) { + # push @soll, $v; # cloud hat SOLL + # } + # } for my $event_schedules ( @{ $decode_json->{scheduled_events} } ) { $valve_id = $event_schedules->{valve_id} if ( exists($event_schedules->{valve_id} ) ); #ic24 $event_id++; # event id diff --git a/controls_GardenaSmartDevice.txt b/controls_GardenaSmartDevice.txt index 5f78179..917fe46 100644 --- a/controls_GardenaSmartDevice.txt +++ b/controls_GardenaSmartDevice.txt @@ -1,2 +1,2 @@ UPD 2022-07-21_19:43:48 49634 FHEM/73_GardenaSmartBridge.pm -UPD 2022-08-04_14:38:54 107236 FHEM/74_GardenaSmartDevice.pm +UPD 2022-08-04_14:44:27 107271 FHEM/74_GardenaSmartDevice.pm From 6a7083f6eaa60e6aacf67f522383525a6c298f03 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Thu, 4 Aug 2022 14:54:44 +0200 Subject: [PATCH 15/29] [fix] - translation --- CHANGED | 2 +- FHEM/74_GardenaSmartDevice.pm | 17 +++++++++-------- controls_GardenaSmartDevice.txt | 2 +- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/CHANGED b/CHANGED index 6883ea6..7646245 100644 --- a/CHANGED +++ b/CHANGED @@ -1 +1 @@ - [enhancemend] - commandref + [fix] - fix diff --git a/FHEM/74_GardenaSmartDevice.pm b/FHEM/74_GardenaSmartDevice.pm index 331d9df..23c33a1 100644 --- a/FHEM/74_GardenaSmartDevice.pm +++ b/FHEM/74_GardenaSmartDevice.pm @@ -846,12 +846,13 @@ sub WriteReadings { scalar( @{$decode_json->{scheduled_events} } ) ); my $valve_id =1; my $event_id = 0; # ic24 [1..6] | wc, pump [1] ## valcid zahlen. readings mit valvid aber - # my @soll = (); - # for my $event_schedules ( @{ $decode_json->{scheduled_events} } ) { - # while ( my ( $r, $v ) = each %{ $event_schedules } ) { - # push @soll, $v; # cloud hat SOLL - # } - # } + my @soll = (); + for my $event_schedules ( @{ $decode_json->{scheduled_events} } ) { + while ( my ( $r, $v ) = each %{ $event_schedules } ) { + push @soll, $v if $r eq 'id'; # cloud hat SOLL + } + } + for my $event_schedules ( @{ $decode_json->{scheduled_events} } ) { $valve_id = $event_schedules->{valve_id} if ( exists($event_schedules->{valve_id} ) ); #ic24 $event_id++; # event id @@ -1056,7 +1057,7 @@ sub setState { if (scalar(@opened_valves) > 0){ ## valve 1 will be ir.. 23 minutes remaining for (@valves_connected){ - $state_string .= sprintf(RigReadingsValue($hash,'valve').' '.$_.' '.(RigReadingsValue($hash, 'will be irrigated %.f minutes remaining.') .'
      '), (ReadingsVal( $name, 'watering-watering_timer_'.$_.'_duration', 0 )/60)); + $state_string .= sprintf(RigReadingsValue($hash,'valve').' '.$_.' '.(RigReadingsValue($hash, 'watering. %.f minutes left') .'
      '), (ReadingsVal( $name, 'watering-watering_timer_'.$_.'_duration', 0 )/60)); } # /for } else { $state_string .= RigReadingsValue($hash, 'closed'); @@ -1073,7 +1074,7 @@ sub setState { Log3 $name, 5, "[DEBUG] - Offene Ventile :".scalar(@opened_valves)." laengste bewaesserung: $longest_duration . hat Zeitplan: $has_schedule Naechster Zeitplan: $nearst_irrigation"; $state_string = scalar(@opened_valves) > 0 # offen - ? sprintf( (RigReadingsValue($hash, 'will be irrigated %.f minutes remaining.')), $longest_duration/60) + ? sprintf( (RigReadingsValue($hash, 'watering. %.f minutes left')), $longest_duration/60) # zu : ( $has_schedule diff --git a/controls_GardenaSmartDevice.txt b/controls_GardenaSmartDevice.txt index 917fe46..70c4d7e 100644 --- a/controls_GardenaSmartDevice.txt +++ b/controls_GardenaSmartDevice.txt @@ -1,2 +1,2 @@ UPD 2022-07-21_19:43:48 49634 FHEM/73_GardenaSmartBridge.pm -UPD 2022-08-04_14:44:27 107271 FHEM/74_GardenaSmartDevice.pm +UPD 2022-08-04_14:54:35 107246 FHEM/74_GardenaSmartDevice.pm From 47804c996b63fe7f11ad72dacdd1fd0e9ca0e46e Mon Sep 17 00:00:00 2001 From: Sebastian Date: Thu, 4 Aug 2022 15:47:10 +0200 Subject: [PATCH 16/29] [enhancement] - commandref --- CHANGED | 2 +- FHEM/74_GardenaSmartDevice.pm | 85 +++++++++++++-------------------- controls_GardenaSmartDevice.txt | 2 +- 3 files changed, 36 insertions(+), 53 deletions(-) diff --git a/CHANGED b/CHANGED index 7646245..bf176ba 100644 --- a/CHANGED +++ b/CHANGED @@ -1 +1 @@ - [fix] - fix + [fix] - translation diff --git a/FHEM/74_GardenaSmartDevice.pm b/FHEM/74_GardenaSmartDevice.pm index 23c33a1..492aefe 100644 --- a/FHEM/74_GardenaSmartDevice.pm +++ b/FHEM/74_GardenaSmartDevice.pm @@ -1416,14 +1416,15 @@ sub SetPredefinedStartPoints {
        Readings (model = mower) +

        + Readings are based on Sileno, other models might have different/additional readings depending on their functions (tbd.) +

          -
        • Readings are based on Sileno, other models might have different/additional readings depending on their functions (tbd.)
        • -
        • battery-charging - Indicator if battery is charged (0/1)
        • battery-level - load percentage of battery
        • battery-rechargeable_battery_status - healthyness of the battery (out_of_operation/replace_now/low/ok), not all models
        • device_info-category - category of device (mower/watering_computer)
        • -
        • device_info-connection_status - connection status (online/offline/unknown) +
        • device_info-connection_status - connection status (online/offline/unknown)
        • device_info-last_time_online - timestamp of last radio contact
        • device_info-manufacturer - manufacturer
        • device_info-product - product type
        • @@ -1558,7 +1559,7 @@ sub SetPredefinedStartPoints {
        • device_info-manufacturer - manufacturer
        • device_info-product - product type
        • device_info-serial_number - serial number
        • -
        • device_info-sgtin - tbd.
        • +
        • device_info-sgtin - (tbd.)
        • device_info-version - firmware version
        • error-error - error message (tbd.)
        • error-valve_error_1_severity - (tbd.)
        • @@ -1580,15 +1581,16 @@ sub SetPredefinedStartPoints {
        • scheduling-schedules_event_1_valve_1_weekly - weekdays of schedule 1
        • scheduling-schedules_events_count - number of pre-defined schedules
        • scheduling-schedules_paused_until - date/time until schedule is paused (2038-01-18T00:00:00.000Z is defined as permanently by Gardena cloud)
        • -
        • state - state of device
        • +
        • state - state of device
          • closed - valve closed, no schedules available
          • closed. schedule permanently paused - valve closed, schedule disabled
          • closed. next watering: YYYY-MM-DD HH:MM - valve closed, next scheduled start at YYYY-MM-DDTHH:MM:00.000Z
          • -
          • watering. n minutes remaining. - watering, n minutes remaining (depending on manual button time or on pre-defined schedule)
          • +
          • watering. n minutes left. - watering, n minutes remaining (depending on manual button time or on pre-defined schedule)
          • offline - device is disabled/not connected
          • hibernate - winter mode)
          +
        • watering-watering_timer_1_duration - duration of current watering in seconds
        • watering-watering_timer_1_irrigation_left - remaining watering time in minutes
        • watering-watering_timer_1_state - state of schedule
        • @@ -1597,6 +1599,7 @@ sub SetPredefinedStartPoints {


        Readings (model = ic24) +
        • device_info-category - category of device (mower/watering_computer/sensor/etc.)
        • device_info-connection_status - connection status (online/offline/unknown)
        • device_info-last_time_online - timestamp of last radio contact
        • @@ -1633,14 +1636,15 @@ sub SetPredefinedStartPoints {
        • ...more readings for further schedules/valves
        • scheduling-schedules_paused_until_1 - date/time until schedule is paused (2038-01-18T00:00:00.000Z is defined as permanently by Gardena cloud)
        • ...more readings for valves 2-6
        • -
        • state - state of device
        • +
        • state - state of device
          • closed - valve closed, no schedules available
          • closed. schedule permanently paused - valve closed, all schedules disabled/paused
          • closed. next watering: YYYY-MM-DD HH:MM - valve closed, next scheduled start at YYYY-MM-DDTHH:MM:00.000Z
          • -
          • watering. n minutes remaining. - watering, n minutes remaining. If more than one schedule is active, the longer remaining time is shown.
          • +
          • watering. n minutes left. - watering, n minutes remaining. If more than one schedule is active, the longer remaining time is shown.
          • offline - device is disabled/not connected
          +
        • valve-valve_name_1 - individual name for valve 1
        • ...more readings for valves 2-6 (if installed)
        • watering-watering_timer_1_duration - duration of current watering in seconds
        • @@ -1648,35 +1652,8 @@ sub SetPredefinedStartPoints {
        • watering-watering_timer_1_state - state of schedule
        • watering-watering_timer_1_valve_id - valve id of schedule
        • ...more readings for further valves/schedules
        • -
        • winter_mode - status of winter mode (awake/hibernate)
        • -

          - Readings (model = sensor) -
            -
          • ambient_temperature-frost_warning - frost warning
          • -
          • ambient_temperature-temperature - ambient temperature in Celsius
          • -
          • battery-disposable_battery_status - healthyness of the battery (ok/low/replace_now/out_of_operation/no_battery/unknown)
          • -
          • battery-level - energy level of battery in percent
          • -
          • device_info-category - category of device (mower/watering_computer/sensor/etc.)
          • -
          • device_info-connection_status - connection status (online/offline/unknown)
          • -
          • device_info-last_time_online - timestamp of last radio contact
          • -
          • device_info-manufacturer - manufacturer
          • -
          • device_info-product - product type
          • -
          • device_info-serial_number - serial number
          • -
          • device_info-sgtin - tbd.
          • -
          • device_info-version - firmware version
          • -
          • firmware-firmware_available_version - new available firmware (only if available)
          • -
          • firmware-firmware_command - firmware command (idle/firmware_cancel/firmware_upload/unsupported)
          • -
          • firmware-firmware_status - firmware status
          • -
          • firmware-firmware_upload_progress - progress indicator of firmware update
          • -
          • firmware-inclusion_status - inclusion status
          • -
          • humidity-humidity - humidity in percent
          • -
          • light-light - brightness in lux
          • -
          • radio-quality - percentage of the radio quality
          • -
          • radio-state - radio state (bad/poor/good/undefined)
          • -
          • soil_temperature-temperature - soil temperature in Celsius
          • -
          • state - state of sensor (temperature (T:), humidity (H:), brightness/light (L:)
          • winter_mode - status of winter mode (awake/hibernate)
          • -
          +


        Readings (model = sensor)
          @@ -1707,9 +1684,10 @@ sub SetPredefinedStartPoints {


        Readings (model = sensor2) +

        + "sensor2" does not measure brightness or ambient temperature, and it has another reading for frost warning. Other than that, it seems to be more or less identical to "sensor". +

          -
        • "sensor2" does not measure brightness or ambient temperature, and it has another reading for frost warning. Other than that, it seems to be more or less identical to "sensor".
        • -
        • battery-disposable_battery_status - healthyness of the battery (ok/low/replace_now/out_of_operation/no_battery/unknown)
        • battery-level - energy level of battery in percent
        • device_info-category - category of device (mower/watering_computer/sensor/etc.)
        • @@ -1745,9 +1723,9 @@ sub SetPredefinedStartPoints {
          • (tbd.)
          -

          +


          - Attribute + Attribute (all models)
          • IODev - Name of GardenaSmartBridge device
          • extendedState 0|1 - (tbd.)
          • @@ -1756,7 +1734,7 @@ sub SetPredefinedStartPoints {
          • readingValueLanguage en|de - Reading language enlish or german (default: english, if global language is not set to german)
          -

          +


          set (model = mower)
            @@ -1850,9 +1828,10 @@ sub SetPredefinedStartPoints {
              Readings (model = mower/Mäher) +

              + Readings basieren auf dem Modell Sileno, andere Modelle haben abweichende/zusätzliche Readings abhängig von ihren Funktionen (tbd.) +

                -
              • Readings basieren auf dem Modell Sileno, andere Modelle haben abweichende/zusätzliche Readings abhängig von ihren Funktionen (tbd.)
              • -
              • battery-charging - Ladeindikator (0/1)
              • battery-level - Ladezustand der Batterie in Prozent
              • battery-rechargeable_battery_status - Zustand der Batterie (Ausser Betrieb/Kritischer Batteriestand, @@ -1979,6 +1958,7 @@ sub SetPredefinedStartPoints {
              • Abgeschlossen
              • Winterschlaf - Gerät ist im Winterschlaf
              +
            • winter_mode - Status Winterschlaf (awake/hibernate)


            @@ -2015,7 +1995,7 @@ sub SetPredefinedStartPoints {
          • scheduling-schedules_event_1_valve_1_weekly - Wochentage von Zeitplan 1
          • scheduling-schedules_events_count - Anzahl angelegter Zeitpläne
          • scheduling-schedules_paused_until - Datum/Uhrzeit, bis wann Zeitplan pausiert ist (2038-01-18T00:00:00.000Z wird von Gardena-Cloud als dauerhaft angesehen)
          • -
          • state - Status des Geräts
          • +
          • state - Status des Geräts
            • geschossen - Ventil geschlossen, keine Zeitpläne definiert
            • geschlossen. Zeitplan dauerhaft pausiert - Ventil geschlossen, Zeitplan dauerhaft pausiert
            • @@ -2024,6 +2004,7 @@ sub SetPredefinedStartPoints {
            • offline - Gerät ist ausgeschaltet/hat keine Verbindung
            • Winterschlaf - Gerät ist im Winterschlaf
            +
          • watering-watering_timer_1_duration - Gesamt-Dauer der aktuellen Bewässerung in Sekunden
          • watering-watering_timer_1_irrigation_left - Verbleibende Bewässerungszeit in Minuten
          • watering-watering_timer_1_state - Status des Zeitplans
          • @@ -2045,7 +2026,7 @@ sub SetPredefinedStartPoints {
          • error-valve_error_0_severity - (tbd.)
          • error-valve_error_0_type - (tbd.)
          • error-valve_error_0_valve_id - ID des fehlerhaften Ventils
          • -
          • ...ggf. weitere Error-Readings
          • +
          • ...ggf. weitere Error-Readings
          • firmware-firmware_available_version - Neue Firmware (nur wenn verfügbar)
          • firmware-firmware_command - Firmware-Kommando (idle/firmware_cancel/firmware_upload/unsupported)
          • firmware-firmware_status - Firmware Status
          • @@ -2069,7 +2050,7 @@ sub SetPredefinedStartPoints {
          • ...weitere Readings für zusätzliche Zeitpläne/Ventile
          • scheduling-schedules_paused_until_1 - Datum/Uhrzeit, bis wann Zeitplan pausiert ist (2038-01-18T00:00:00.000Z wird von Gardena-Cloud als dauerhaft angesehen)
          • ...weitere Readings für Ventile 2-6
          • -
          • state - Status des Geräts
          • +
          • state - Status des Geräts
            • geschossen - Ventil geschlossen, keine Zeitpläne definiert
            • geschlossen. Zeitplan dauerhaft pausiert - Ventil geschlossen, Zeitplan dauerhaft pausiert
            • @@ -2078,6 +2059,7 @@ sub SetPredefinedStartPoints {
            • offline - Gerät ist ausgeschaltet/hat keine Verbindung
            • Winterschlaf - Gerät ist im Winterschlaf
            +
          • valve-valve_name_1 - Eigener Name für Ventil 1
          • ...weitere Readings für Ventile 2-6 (if installed)
          • watering-watering_timer_1_duration - Gesamt-Dauer der aktuellen Bewässerung in Sekunden
          • @@ -2117,9 +2099,10 @@ sub SetPredefinedStartPoints {


          Readings (model = sensor2) +

          + "sensor2" hat keine Helligkeitsmessung oder Umgebungstemperatur, und es legt die Frost-Warnung in einem anderen Reading ab. Ansonsten ist er mehr oder weniger identisch zum "sensor". +

            -
          • "sensor2" hat keine Helligkeitsmessung oder Umgebungstemperatur, und es legt die Frost-Warnung in einem anderen Reading ab. Ansonsten ist er mehr oder weniger identisch zum "sensor".
          • -
          • battery-disposable_battery_status - Batteriezustand
          • battery-level - Ladezustand der Batterie in Prozent
          • device_info-category - Art des Geräts
          • @@ -2155,9 +2138,9 @@ sub SetPredefinedStartPoints {
            • (tbd.)
            -

            +


            - Attribute + Attribute (alle Modelle)
            • IODev - Name des GardenaSmartBridge Devices
            • extendedState 0|1 - [tbd.]
            • @@ -2166,7 +2149,7 @@ sub SetPredefinedStartPoints {
            • readingValueLanguage en|de - Sprache der Readings englisch oder deutsch (default: englisch, es sei denn, Deutsch ist als globale Sprache gesetzt)
            -

            +


            set (model = mower)
              diff --git a/controls_GardenaSmartDevice.txt b/controls_GardenaSmartDevice.txt index 70c4d7e..d576ed3 100644 --- a/controls_GardenaSmartDevice.txt +++ b/controls_GardenaSmartDevice.txt @@ -1,2 +1,2 @@ UPD 2022-07-21_19:43:48 49634 FHEM/73_GardenaSmartBridge.pm -UPD 2022-08-04_14:54:35 107246 FHEM/74_GardenaSmartDevice.pm +UPD 2022-08-04_15:46:35 105511 FHEM/74_GardenaSmartDevice.pm From bae27c39c12afd90417a619c0b2cc405d21ac059 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Sat, 6 Aug 2022 13:13:43 +0200 Subject: [PATCH 17/29] [enhancement] - delete unused scheuldes from readings --- CHANGED | 2 +- FHEM/74_GardenaSmartDevice.pm | 55 ++++++++++++++++++++++++++++++--- controls_GardenaSmartDevice.txt | 2 +- 3 files changed, 53 insertions(+), 6 deletions(-) diff --git a/CHANGED b/CHANGED index bf176ba..2de9fa3 100644 --- a/CHANGED +++ b/CHANGED @@ -1 +1 @@ - [fix] - translation + [enhancement] - commandref diff --git a/FHEM/74_GardenaSmartDevice.pm b/FHEM/74_GardenaSmartDevice.pm index 492aefe..c85ac36 100644 --- a/FHEM/74_GardenaSmartDevice.pm +++ b/FHEM/74_GardenaSmartDevice.pm @@ -845,14 +845,61 @@ sub WriteReadings { readingsBulkUpdateIfChanged( $hash, 'scheduling-schedules_events_count', scalar( @{$decode_json->{scheduled_events} } ) ); my $valve_id =1; my $event_id = 0; # ic24 [1..6] | wc, pump [1] - ## valcid zahlen. readings mit valvid aber - my @soll = (); - for my $event_schedules ( @{ $decode_json->{scheduled_events} } ) { - while ( my ( $r, $v ) = each %{ $event_schedules } ) { + + ## + # validiere schedules + my @soll = ();my @ist=(); + for my $cloud_schedules ( @{ $decode_json->{scheduled_events} } ) { + while ( my ( $r, $v ) = each %{ $cloud_schedules } ) { push @soll, $v if $r eq 'id'; # cloud hat SOLL } } + +use Data::Dumper; + foreach my $dev_schedules ( sort keys %{ $hash->{READINGS} } ) { + my $dev_reading = ReadingsVal( $name, $dev_schedules, "error" ); + push @ist, $dev_reading if $dev_schedules =~ /.*_id/; # push reading _id + push @ist, $1 if $dev_schedules =~ /.*_(\d)_id/; # push readigs d from x_id + + Log3 $name, 5, "[DEBUG] - Key ist : $dev_schedules "; + Log3 $name, 5, "[DDDDD] - ID FOUND $dev_reading" if $dev_schedules =~ /.*_id/; # cloud hat SOLL + } + Log3 $name, 5, "[OOOU] Cloud ".Dumper(@soll) . "- Ist:". Dumper(@ist); + + ## delete only if cloud != (ist/2) + if (scalar(@soll) != scalar(@ist/2) + && scalar(@soll) > 0 + && scalar(@ist) > 0){ + + while(my $element = shift(@soll)) { + my $schedule_step_int = 0; + + foreach my $sist (@ist) { + my $step = scalar(@ist) > 1 ? 2:1; + if ($element eq $sist){ + # splice(@ist, $schedule_step_int, 1); # more than 2 items del them, otherwise 1 + splice(@ist, $schedule_step_int, $step); # more than 2 items del them, otherwise 1 + #$schedule_step_int++; + } + # $schedule_step_int++; + $schedule_step_int += $step; + } + } + } + Log3 $name, 5, "[REST] ". Dumper(@ist); + if (scalar(@ist) > 0){ + while (my $old_schedule_id = shift(@ist)) { + if (length($old_schedule_id) == 1) { + foreach (keys %{$hash->{READINGS}}) { + delete $hash->{READINGS}->{$_} if($_ =~ /scheduling-schedules_event_$old_schedule_id.*/); + } + }# fi + Log3 $name, 5, "[DEBUG] - $name : deletereading scheduling-schedules_event_$old_schedule_id.*" if length($old_schedule_id) == 1; + } + } + #### /validiere schedules + for my $event_schedules ( @{ $decode_json->{scheduled_events} } ) { $valve_id = $event_schedules->{valve_id} if ( exists($event_schedules->{valve_id} ) ); #ic24 $event_id++; # event id diff --git a/controls_GardenaSmartDevice.txt b/controls_GardenaSmartDevice.txt index d576ed3..84761da 100644 --- a/controls_GardenaSmartDevice.txt +++ b/controls_GardenaSmartDevice.txt @@ -1,2 +1,2 @@ UPD 2022-07-21_19:43:48 49634 FHEM/73_GardenaSmartBridge.pm -UPD 2022-08-04_15:46:35 105511 FHEM/74_GardenaSmartDevice.pm +UPD 2022-08-06_13:11:33 107424 FHEM/74_GardenaSmartDevice.pm From 0ee95be7be4831e2d98d1e3024acd3d4cf56a33f Mon Sep 17 00:00:00 2001 From: Sebastian Date: Sat, 6 Aug 2022 20:20:04 +0200 Subject: [PATCH 18/29] [fix] - delete unused schedules --- CHANGED | 2 +- FHEM/74_GardenaSmartDevice.pm | 22 +++++++++++++--------- controls_GardenaSmartDevice.txt | 2 +- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/CHANGED b/CHANGED index 2de9fa3..10ab08b 100644 --- a/CHANGED +++ b/CHANGED @@ -1 +1 @@ - [enhancement] - commandref + [enhancement] - delete unused scheuldes from readings diff --git a/FHEM/74_GardenaSmartDevice.pm b/FHEM/74_GardenaSmartDevice.pm index c85ac36..79db63f 100644 --- a/FHEM/74_GardenaSmartDevice.pm +++ b/FHEM/74_GardenaSmartDevice.pm @@ -848,7 +848,7 @@ sub WriteReadings { ## # validiere schedules - my @soll = ();my @ist=(); + my @soll = ();my @ist=(); my @tmp_ist=(); for my $cloud_schedules ( @{ $decode_json->{scheduled_events} } ) { while ( my ( $r, $v ) = each %{ $cloud_schedules } ) { push @soll, $v if $r eq 'id'; # cloud hat SOLL @@ -862,27 +862,31 @@ use Data::Dumper; push @ist, $dev_reading if $dev_schedules =~ /.*_id/; # push reading _id push @ist, $1 if $dev_schedules =~ /.*_(\d)_id/; # push readigs d from x_id - Log3 $name, 5, "[DEBUG] - Key ist : $dev_schedules "; - Log3 $name, 5, "[DDDDD] - ID FOUND $dev_reading" if $dev_schedules =~ /.*_id/; # cloud hat SOLL + Log3 $name, 5, "[DEBUG] $name - Key ist : $dev_schedules "; + Log3 $name, 5, "[DDDDD] $name - ID FOUND $dev_reading" if $dev_schedules =~ /.*_id/; # cloud hat SOLL } Log3 $name, 5, "[OOOU] Cloud ".Dumper(@soll) . "- Ist:". Dumper(@ist); ## delete only if cloud != (ist/2) - if (scalar(@soll) != scalar(@ist/2) + if ((scalar(@soll) != scalar(@ist/2) && scalar(@soll) > 0 - && scalar(@ist) > 0){ - + && scalar(@ist) > 0) + || (scalar(@ist) eq 2 && scalar(@soll) eq 1 )){ + @tmp_ist = @ist; while(my $element = shift(@soll)) { my $schedule_step_int = 0; - foreach my $sist (@ist) { + foreach my $sist (@tmp_ist) { my $step = scalar(@ist) > 1 ? 2:1; + #print "step laenge $step \n"; + + print "check $element = $sist\n"; if ($element eq $sist){ - # splice(@ist, $schedule_step_int, 1); # more than 2 items del them, otherwise 1 + #splice(@ist, $schedule_step_int, 1); # more than 2 items del them, otherwise 1 splice(@ist, $schedule_step_int, $step); # more than 2 items del them, otherwise 1 #$schedule_step_int++; } - # $schedule_step_int++; + #$schedule_step_int++; $schedule_step_int += $step; } } diff --git a/controls_GardenaSmartDevice.txt b/controls_GardenaSmartDevice.txt index 84761da..041545f 100644 --- a/controls_GardenaSmartDevice.txt +++ b/controls_GardenaSmartDevice.txt @@ -1,2 +1,2 @@ UPD 2022-07-21_19:43:48 49634 FHEM/73_GardenaSmartBridge.pm -UPD 2022-08-06_13:11:33 107424 FHEM/74_GardenaSmartDevice.pm +UPD 2022-08-06_20:17:48 107633 FHEM/74_GardenaSmartDevice.pm From 78b5731bbf4f97c79bc868ff781f851232f8da5b Mon Sep 17 00:00:00 2001 From: Sebastian Date: Sun, 7 Aug 2022 20:20:17 +0200 Subject: [PATCH 19/29] [fix] - cast all propertie as string - fixed bulkupdateifchanged --- CHANGED | 2 +- FHEM/74_GardenaSmartDevice.pm | 6 +++--- controls_GardenaSmartDevice.txt | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGED b/CHANGED index 10ab08b..a171be1 100644 --- a/CHANGED +++ b/CHANGED @@ -1 +1 @@ - [enhancement] - delete unused scheuldes from readings + [fix] - delete unused schedules diff --git a/FHEM/74_GardenaSmartDevice.pm b/FHEM/74_GardenaSmartDevice.pm index 79db63f..8e15369 100644 --- a/FHEM/74_GardenaSmartDevice.pm +++ b/FHEM/74_GardenaSmartDevice.pm @@ -708,7 +708,7 @@ sub WriteReadings { $hash, $decode_json->{abilities}[$abilities]{name} . '-' . $propertie->{name}, - (defined ($propertie->{value} ) eq '') ? RigReadingsValue( $hash, 'n/a') : RigReadingsValue( $hash, $propertie->{value} ) + (defined ($propertie->{value} ) eq '') ? RigReadingsValue( $hash, 'n/a') : "".RigReadingsValue( $hash, $propertie->{value} ) # cast all data to string with "" ) if ( exists( $propertie->{value} ) && $decode_json->{abilities}[$abilities]{name} . '-' @@ -735,7 +735,7 @@ sub WriteReadings { $hash, $decode_json->{abilities}[$abilities]{name} . '-' . $propertie->{name}, - RigReadingsValue( $hash, $propertie->{value} ) + "".RigReadingsValue( $hash, $propertie->{value} ) # cast all data to string with "" ) if ( defined( $propertie->{value} ) @@ -762,7 +762,7 @@ sub WriteReadings { $decode_json->{abilities}[$abilities]{name} . '-' . $propertie->{name} . '_timestamp', - Time::Piece->strptime( + "".Time::Piece->strptime( RigReadingsValue( $hash, $propertie->{timestamp} ), "%Y-%m-%d %H:%M:%S" )->strftime('%s') diff --git a/controls_GardenaSmartDevice.txt b/controls_GardenaSmartDevice.txt index 041545f..843e6c1 100644 --- a/controls_GardenaSmartDevice.txt +++ b/controls_GardenaSmartDevice.txt @@ -1,2 +1,2 @@ UPD 2022-07-21_19:43:48 49634 FHEM/73_GardenaSmartBridge.pm -UPD 2022-08-06_20:17:48 107633 FHEM/74_GardenaSmartDevice.pm +UPD 2022-08-07_20:12:20 107711 FHEM/74_GardenaSmartDevice.pm From 8a32c9f21522f9154ed10f5a1eb4d1cae5ca5b78 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Mon, 8 Aug 2022 20:47:19 +0200 Subject: [PATCH 20/29] [fix] - removed "valveid" from reading --- CHANGED | 2 +- FHEM/74_GardenaSmartDevice.pm | 6 +++--- controls_GardenaSmartDevice.txt | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGED b/CHANGED index a171be1..5b8f37a 100644 --- a/CHANGED +++ b/CHANGED @@ -1 +1 @@ - [fix] - delete unused schedules + [fix] - cast all propertie as string - fixed bulkupdateifchanged diff --git a/FHEM/74_GardenaSmartDevice.pm b/FHEM/74_GardenaSmartDevice.pm index 8e15369..5f209bf 100644 --- a/FHEM/74_GardenaSmartDevice.pm +++ b/FHEM/74_GardenaSmartDevice.pm @@ -877,7 +877,7 @@ use Data::Dumper; my $schedule_step_int = 0; foreach my $sist (@tmp_ist) { - my $step = scalar(@ist) > 1 ? 2:1; + my $step = scalar(@tmp_ist) > 1 ? 2:1; #print "step laenge $step \n"; print "check $element = $sist\n"; @@ -911,13 +911,13 @@ use Data::Dumper; while ( my ( $r, $v ) = each %{ $event_schedules } ) { readingsBulkUpdateIfChanged( $hash, 'scheduling-schedules_event_' . $event_id - . ( ReadingsVal($name,'error-valve_error_1_valve_id','') ne '' ? "_valve_$valve_id" : '') + #. ( ReadingsVal($name,'error-valve_error_1_valve_id','') ne '' ? "_valve_$valve_id" : '') . '_' . $r, $v) if (ref($v) ne 'HASH' ); readingsBulkUpdateIfChanged( $hash, 'scheduling-schedules_event_' . $event_id - . ( ReadingsVal($name,'error-valve_error_1_valve_id','') ne '' ? "_valve_$valve_id" : '') + #. ( ReadingsVal($name,'error-valve_error_1_valve_id','') ne '' ? "_valve_$valve_id" : '') . '_' . $v->{type}, join(',', @ { $v->{weekdays}}) ) if (ref($v) eq 'HASH' ); diff --git a/controls_GardenaSmartDevice.txt b/controls_GardenaSmartDevice.txt index 843e6c1..9b94dbc 100644 --- a/controls_GardenaSmartDevice.txt +++ b/controls_GardenaSmartDevice.txt @@ -1,2 +1,2 @@ UPD 2022-07-21_19:43:48 49634 FHEM/73_GardenaSmartBridge.pm -UPD 2022-08-07_20:12:20 107711 FHEM/74_GardenaSmartDevice.pm +UPD 2022-08-08_20:47:00 107717 FHEM/74_GardenaSmartDevice.pm From ade45510ac4ee91df053d91116d892468d7e0317 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Mon, 8 Aug 2022 20:59:57 +0200 Subject: [PATCH 21/29] [fix] - checkmethode delete reading if ist = soll --- CHANGED | 2 +- FHEM/74_GardenaSmartDevice.pm | 8 +++++--- controls_GardenaSmartDevice.txt | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/CHANGED b/CHANGED index 5b8f37a..3e6c01a 100644 --- a/CHANGED +++ b/CHANGED @@ -1 +1 @@ - [fix] - cast all propertie as string - fixed bulkupdateifchanged + [fix] - removed "valveid" from reading diff --git a/FHEM/74_GardenaSmartDevice.pm b/FHEM/74_GardenaSmartDevice.pm index 5f209bf..ce17c8b 100644 --- a/FHEM/74_GardenaSmartDevice.pm +++ b/FHEM/74_GardenaSmartDevice.pm @@ -859,8 +859,8 @@ sub WriteReadings { use Data::Dumper; foreach my $dev_schedules ( sort keys %{ $hash->{READINGS} } ) { my $dev_reading = ReadingsVal( $name, $dev_schedules, "error" ); - push @ist, $dev_reading if $dev_schedules =~ /.*_id/; # push reading _id - push @ist, $1 if $dev_schedules =~ /.*_(\d)_id/; # push readigs d from x_id + push @ist, $dev_reading if $dev_schedules =~ /schedule.*_id/; # push reading _id + push @ist, $1 if $dev_schedules =~ /schedule.*_(\d)_id/; # push readigs d from x_id Log3 $name, 5, "[DEBUG] $name - Key ist : $dev_schedules "; Log3 $name, 5, "[DDDDD] $name - ID FOUND $dev_reading" if $dev_schedules =~ /.*_id/; # cloud hat SOLL @@ -892,7 +892,9 @@ use Data::Dumper; } } Log3 $name, 5, "[REST] ". Dumper(@ist); - if (scalar(@ist) > 0){ + # delete only if count soll != count ist. cos the will be overwritten + if (scalar(@ist) > 0 + && scalar(@soll) != scalar(@ist/2) ){ while (my $old_schedule_id = shift(@ist)) { if (length($old_schedule_id) == 1) { foreach (keys %{$hash->{READINGS}}) { diff --git a/controls_GardenaSmartDevice.txt b/controls_GardenaSmartDevice.txt index 9b94dbc..a015f49 100644 --- a/controls_GardenaSmartDevice.txt +++ b/controls_GardenaSmartDevice.txt @@ -1,2 +1,2 @@ UPD 2022-07-21_19:43:48 49634 FHEM/73_GardenaSmartBridge.pm -UPD 2022-08-08_20:47:00 107717 FHEM/74_GardenaSmartDevice.pm +UPD 2022-08-08_20:59:37 107858 FHEM/74_GardenaSmartDevice.pm From 0d2972111168797260e13e630e44d17e2e70571a Mon Sep 17 00:00:00 2001 From: Sebastian Date: Mon, 8 Aug 2022 21:03:29 +0200 Subject: [PATCH 22/29] [fix] - commandref --- CHANGED | 2 +- FHEM/74_GardenaSmartDevice.pm | 4 +--- controls_GardenaSmartDevice.txt | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/CHANGED b/CHANGED index 3e6c01a..29d1171 100644 --- a/CHANGED +++ b/CHANGED @@ -1 +1 @@ - [fix] - removed "valveid" from reading + [fix] - checkmethode delete reading if ist = soll diff --git a/FHEM/74_GardenaSmartDevice.pm b/FHEM/74_GardenaSmartDevice.pm index ce17c8b..7d4ea97 100644 --- a/FHEM/74_GardenaSmartDevice.pm +++ b/FHEM/74_GardenaSmartDevice.pm @@ -1781,7 +1781,6 @@ sub SetPredefinedStartPoints { Attribute (all models)
              • IODev - Name of GardenaSmartBridge device
              • -
              • extendedState 0|1 - (tbd.)
              • model watering_computer|sensor|sensor2|mower|ic24|power|electronic_pressure_pump - model of GardenaSmartDevice
              • readingValueLanguage en|de - Reading language enlish or german (default: english, if global language is not @@ -2196,7 +2195,6 @@ sub SetPredefinedStartPoints { Attribute (alle Modelle)
                • IODev - Name des GardenaSmartBridge Devices
                • -
                • extendedState 0|1 - [tbd.]
                • model watering_computer|sensor|sensor2|mower|ic24|power|electronic_pressure_pump - Modell des GardenaSmartDevice
                • readingValueLanguage en|de - Sprache der Readings englisch oder deutsch (default: englisch, es sei denn, @@ -2295,7 +2293,7 @@ sub SetPredefinedStartPoints { ], "release_status": "stable", "license": "GPL_2", - "version": "v2.5.6", + "version": "v2.5.7", "author": [ "Marko Oldenburg " ], diff --git a/controls_GardenaSmartDevice.txt b/controls_GardenaSmartDevice.txt index a015f49..47fd397 100644 --- a/controls_GardenaSmartDevice.txt +++ b/controls_GardenaSmartDevice.txt @@ -1,2 +1,2 @@ UPD 2022-07-21_19:43:48 49634 FHEM/73_GardenaSmartBridge.pm -UPD 2022-08-08_20:59:37 107858 FHEM/74_GardenaSmartDevice.pm +UPD 2022-08-08_21:03:14 107770 FHEM/74_GardenaSmartDevice.pm From 8ce29803563c436dc798993062c7a862ffcd12d2 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Tue, 9 Aug 2022 10:04:43 +0200 Subject: [PATCH 23/29] [fix] - corret debug output --- CHANGED | 2 +- FHEM/74_GardenaSmartDevice.pm | 2 +- controls_GardenaSmartDevice.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGED b/CHANGED index 29d1171..bb0e9f3 100644 --- a/CHANGED +++ b/CHANGED @@ -1 +1 @@ - [fix] - checkmethode delete reading if ist = soll + [fix] - commandref diff --git a/FHEM/74_GardenaSmartDevice.pm b/FHEM/74_GardenaSmartDevice.pm index 7d4ea97..7eed766 100644 --- a/FHEM/74_GardenaSmartDevice.pm +++ b/FHEM/74_GardenaSmartDevice.pm @@ -863,7 +863,7 @@ use Data::Dumper; push @ist, $1 if $dev_schedules =~ /schedule.*_(\d)_id/; # push readigs d from x_id Log3 $name, 5, "[DEBUG] $name - Key ist : $dev_schedules "; - Log3 $name, 5, "[DDDDD] $name - ID FOUND $dev_reading" if $dev_schedules =~ /.*_id/; # cloud hat SOLL + Log3 $name, 5, "[DDDDD] $name - ID FOUND $dev_reading" if $dev_schedules =~ /schedule.*_id/; # cloud hat SOLL } Log3 $name, 5, "[OOOU] Cloud ".Dumper(@soll) . "- Ist:". Dumper(@ist); diff --git a/controls_GardenaSmartDevice.txt b/controls_GardenaSmartDevice.txt index 47fd397..82bcffe 100644 --- a/controls_GardenaSmartDevice.txt +++ b/controls_GardenaSmartDevice.txt @@ -1,2 +1,2 @@ UPD 2022-07-21_19:43:48 49634 FHEM/73_GardenaSmartBridge.pm -UPD 2022-08-08_21:03:14 107770 FHEM/74_GardenaSmartDevice.pm +UPD 2022-08-09_09:51:51 107778 FHEM/74_GardenaSmartDevice.pm From c86cae74e69c54e00c11574378531ed1d8f8b886 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Tue, 9 Aug 2022 10:13:57 +0200 Subject: [PATCH 24/29] [fix] - debug output --- CHANGED | 2 +- FHEM/74_GardenaSmartDevice.pm | 2 +- controls_GardenaSmartDevice.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGED b/CHANGED index bb0e9f3..c6c6e24 100644 --- a/CHANGED +++ b/CHANGED @@ -1 +1 @@ - [fix] - commandref + [fix] - corret debug output diff --git a/FHEM/74_GardenaSmartDevice.pm b/FHEM/74_GardenaSmartDevice.pm index 7eed766..3e52112 100644 --- a/FHEM/74_GardenaSmartDevice.pm +++ b/FHEM/74_GardenaSmartDevice.pm @@ -863,7 +863,7 @@ use Data::Dumper; push @ist, $1 if $dev_schedules =~ /schedule.*_(\d)_id/; # push readigs d from x_id Log3 $name, 5, "[DEBUG] $name - Key ist : $dev_schedules "; - Log3 $name, 5, "[DDDDD] $name - ID FOUND $dev_reading" if $dev_schedules =~ /schedule.*_id/; # cloud hat SOLL + Log3 $name, 5, "[DDDDD] $name - ID FOUND $dev_reading" if $dev_schedules =~ /schedule.*_\d_id/; # cloud hat SOLL } Log3 $name, 5, "[OOOU] Cloud ".Dumper(@soll) . "- Ist:". Dumper(@ist); diff --git a/controls_GardenaSmartDevice.txt b/controls_GardenaSmartDevice.txt index 82bcffe..498a408 100644 --- a/controls_GardenaSmartDevice.txt +++ b/controls_GardenaSmartDevice.txt @@ -1,2 +1,2 @@ UPD 2022-07-21_19:43:48 49634 FHEM/73_GardenaSmartBridge.pm -UPD 2022-08-09_09:51:51 107778 FHEM/74_GardenaSmartDevice.pm +UPD 2022-08-09_10:13:50 107781 FHEM/74_GardenaSmartDevice.pm From 71b435d90b7ee3effef5cd236cde0872409fd982 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Tue, 9 Aug 2022 10:34:04 +0200 Subject: [PATCH 25/29] [fix] - schedules + debug --- CHANGED | 2 +- FHEM/74_GardenaSmartDevice.pm | 2 +- controls_GardenaSmartDevice.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGED b/CHANGED index c6c6e24..7c17e12 100644 --- a/CHANGED +++ b/CHANGED @@ -1 +1 @@ - [fix] - corret debug output + [fix] - debug output diff --git a/FHEM/74_GardenaSmartDevice.pm b/FHEM/74_GardenaSmartDevice.pm index 3e52112..f6b4cb2 100644 --- a/FHEM/74_GardenaSmartDevice.pm +++ b/FHEM/74_GardenaSmartDevice.pm @@ -859,7 +859,7 @@ sub WriteReadings { use Data::Dumper; foreach my $dev_schedules ( sort keys %{ $hash->{READINGS} } ) { my $dev_reading = ReadingsVal( $name, $dev_schedules, "error" ); - push @ist, $dev_reading if $dev_schedules =~ /schedule.*_id/; # push reading _id + push @ist, $dev_reading if $dev_schedules =~ /schedule.*\d_id/; # push reading _id push @ist, $1 if $dev_schedules =~ /schedule.*_(\d)_id/; # push readigs d from x_id Log3 $name, 5, "[DEBUG] $name - Key ist : $dev_schedules "; diff --git a/controls_GardenaSmartDevice.txt b/controls_GardenaSmartDevice.txt index 498a408..3f407bb 100644 --- a/controls_GardenaSmartDevice.txt +++ b/controls_GardenaSmartDevice.txt @@ -1,2 +1,2 @@ UPD 2022-07-21_19:43:48 49634 FHEM/73_GardenaSmartBridge.pm -UPD 2022-08-09_10:13:50 107781 FHEM/74_GardenaSmartDevice.pm +UPD 2022-08-09_10:33:55 107783 FHEM/74_GardenaSmartDevice.pm From 8b9ce793cd0992fbeb82db1b0b9f24497ea3ef7c Mon Sep 17 00:00:00 2001 From: Sebastian Date: Tue, 9 Aug 2022 14:52:34 +0200 Subject: [PATCH 26/29] [final] - removed debug print lines, cleanup code --- CHANGED | 2 +- FHEM/74_GardenaSmartDevice.pm | 16 ++++------------ controls_GardenaSmartDevice.txt | 2 +- 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/CHANGED b/CHANGED index 7c17e12..4cbe437 100644 --- a/CHANGED +++ b/CHANGED @@ -1 +1 @@ - [fix] - debug output + [fix] - schedules + debug diff --git a/FHEM/74_GardenaSmartDevice.pm b/FHEM/74_GardenaSmartDevice.pm index f6b4cb2..ed8724d 100644 --- a/FHEM/74_GardenaSmartDevice.pm +++ b/FHEM/74_GardenaSmartDevice.pm @@ -855,17 +855,15 @@ sub WriteReadings { } } - -use Data::Dumper; foreach my $dev_schedules ( sort keys %{ $hash->{READINGS} } ) { my $dev_reading = ReadingsVal( $name, $dev_schedules, "error" ); push @ist, $dev_reading if $dev_schedules =~ /schedule.*\d_id/; # push reading _id push @ist, $1 if $dev_schedules =~ /schedule.*_(\d)_id/; # push readigs d from x_id - Log3 $name, 5, "[DEBUG] $name - Key ist : $dev_schedules "; - Log3 $name, 5, "[DDDDD] $name - ID FOUND $dev_reading" if $dev_schedules =~ /schedule.*_\d_id/; # cloud hat SOLL + Log3 $name, 5, "[DEBUG] $name - Schedule - Key ist : $dev_schedules "; + Log3 $name, 5, "[DEBUG] $name - Schedule - ID FOUND $dev_reading" if $dev_schedules =~ /schedule.*_\d_id/; # cloud hat SOLL } - Log3 $name, 5, "[OOOU] Cloud ".Dumper(@soll) . "- Ist:". Dumper(@ist); + #Log3 $name, 5, "[DEBUG] Cloud:".Dumper(@soll) . "- Internal:". Dumper(@ist); ## delete only if cloud != (ist/2) if ((scalar(@soll) != scalar(@ist/2) @@ -878,20 +876,14 @@ use Data::Dumper; foreach my $sist (@tmp_ist) { my $step = scalar(@tmp_ist) > 1 ? 2:1; - #print "step laenge $step \n"; - - print "check $element = $sist\n"; if ($element eq $sist){ - #splice(@ist, $schedule_step_int, 1); # more than 2 items del them, otherwise 1 splice(@ist, $schedule_step_int, $step); # more than 2 items del them, otherwise 1 - #$schedule_step_int++; } - #$schedule_step_int++; $schedule_step_int += $step; } } } - Log3 $name, 5, "[REST] ". Dumper(@ist); + Log3 $name, 5, "[DEBUG] $name - Schedule - Rest ". Dumper(@ist); # delete only if count soll != count ist. cos the will be overwritten if (scalar(@ist) > 0 && scalar(@soll) != scalar(@ist/2) ){ diff --git a/controls_GardenaSmartDevice.txt b/controls_GardenaSmartDevice.txt index 3f407bb..0f062cc 100644 --- a/controls_GardenaSmartDevice.txt +++ b/controls_GardenaSmartDevice.txt @@ -1,2 +1,2 @@ UPD 2022-07-21_19:43:48 49634 FHEM/73_GardenaSmartBridge.pm -UPD 2022-08-09_10:33:55 107783 FHEM/74_GardenaSmartDevice.pm +UPD 2022-08-09_14:51:26 107551 FHEM/74_GardenaSmartDevice.pm From d660366aea354959ec73ce2333138a03d1884a02 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Tue, 9 Aug 2022 15:03:38 +0200 Subject: [PATCH 27/29] [final 2] - removed debug dumper code --- CHANGED | 2 +- FHEM/74_GardenaSmartDevice.pm | 2 +- controls_GardenaSmartDevice.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGED b/CHANGED index 4cbe437..80f8911 100644 --- a/CHANGED +++ b/CHANGED @@ -1 +1 @@ - [fix] - schedules + debug + [final] - removed debug print lines, cleanup code diff --git a/FHEM/74_GardenaSmartDevice.pm b/FHEM/74_GardenaSmartDevice.pm index ed8724d..ab4b2bc 100644 --- a/FHEM/74_GardenaSmartDevice.pm +++ b/FHEM/74_GardenaSmartDevice.pm @@ -883,7 +883,7 @@ sub WriteReadings { } } } - Log3 $name, 5, "[DEBUG] $name - Schedule - Rest ". Dumper(@ist); + #Log3 $name, 5, "[DEBUG] $name - Schedule - Rest ". Dumper(@ist); # delete only if count soll != count ist. cos the will be overwritten if (scalar(@ist) > 0 && scalar(@soll) != scalar(@ist/2) ){ diff --git a/controls_GardenaSmartDevice.txt b/controls_GardenaSmartDevice.txt index 0f062cc..4fc77d0 100644 --- a/controls_GardenaSmartDevice.txt +++ b/controls_GardenaSmartDevice.txt @@ -1,2 +1,2 @@ UPD 2022-07-21_19:43:48 49634 FHEM/73_GardenaSmartBridge.pm -UPD 2022-08-09_14:51:26 107551 FHEM/74_GardenaSmartDevice.pm +UPD 2022-08-09_15:03:22 107552 FHEM/74_GardenaSmartDevice.pm From 388ae1635ee179273a527ff370bd0b7e45ccf13d Mon Sep 17 00:00:00 2001 From: Sebastian Date: Thu, 11 Aug 2022 12:40:13 +0200 Subject: [PATCH 28/29] [enhancement] - add resetvalveerrors ic24 --- CHANGED | 2 +- FHEM/74_GardenaSmartDevice.pm | 5 ++++- controls_GardenaSmartDevice.txt | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGED b/CHANGED index 80f8911..816fbc9 100644 --- a/CHANGED +++ b/CHANGED @@ -1 +1 @@ - [final] - removed debug print lines, cleanup code + [final 2] - removed debug dumper code diff --git a/FHEM/74_GardenaSmartDevice.pm b/FHEM/74_GardenaSmartDevice.pm index ab4b2bc..4e5f3b3 100644 --- a/FHEM/74_GardenaSmartDevice.pm +++ b/FHEM/74_GardenaSmartDevice.pm @@ -571,7 +571,7 @@ sub Set { if ( AttrVal( $name, 'model', 'unknown' ) eq 'electronic_pressure_pump' ); $list .= -'closeAllValves:noArg stopScheduleValve:select,'.ReadingsVal( $name, 'ic24-valves_connected', '1' ).' resumeScheduleValve:select,'.ReadingsVal( $name, 'ic24-valves_connected', '1' ) +'closeAllValves:noArg resetvalveerrors:noArg stopScheduleValve:select,'.ReadingsVal( $name, 'ic24-valves_connected', '1' ).' resumeScheduleValve:select,'.ReadingsVal( $name, 'ic24-valves_connected', '1' ) if ( AttrVal( $name, 'model', 'unknown' ) eq 'ic24' ); foreach my $valve (split(',', ReadingsVal( $name, 'ic24-valves_connected', '1'))) { @@ -1290,6 +1290,7 @@ sub ReadingLangGerman { 'n/a' => 'nicht verfügbar', 'pump_not_filled' => 'Pumpe nicht gefüllt', 'clean_fine_filter' => 'Filter reinigen', + 'concurrent_limit_reached' => 'Grenze gleichzeitig geöffneter Ventile erreicht', ); if ( @@ -1820,6 +1821,7 @@ sub SetPredefinedStartPoints {
                • manualDurationValve4 n - open valve 4 for n minutes
                • manualDurationValve5 n - open valve 5 for n minutes
                • manualDurationValve6 n - open valve 6 for n minutes
                • +
                • resetvalveerrors n - reset valve errormessage
                • resumeScheduleValve n - (re)start irrigation schedule for valve n
                • stopScheduleValve n m - stop irrigation schedule for valve n (Default: 2038-01-18T00:00:00.000Z, Gardena App reads it as "permanently")
                • @@ -2235,6 +2237,7 @@ sub SetPredefinedStartPoints {
                • manualDurationValve4 n - Ventil 4 für n Minuten öffnen
                • manualDurationValve5 n - Ventil 5 für n Minuten öffnen
                • manualDurationValve6 n - Ventil 6 für n Minuten öffnen
                • +
                • resetvalveerrors n - Ventilfehler zurücksetzen
                • resumeScheduleValve n - Zeitplan für Ventil n wieder aktivieren
                • stopScheduleValve n m - Zeitplan für Ventil n anhalten für m Stunden (Default: 2038-01-18T00:00:00.000Z, durch Gardena-App als "dauerhaft" interpretiert)
                • diff --git a/controls_GardenaSmartDevice.txt b/controls_GardenaSmartDevice.txt index 4fc77d0..2167974 100644 --- a/controls_GardenaSmartDevice.txt +++ b/controls_GardenaSmartDevice.txt @@ -1,2 +1,2 @@ UPD 2022-07-21_19:43:48 49634 FHEM/73_GardenaSmartBridge.pm -UPD 2022-08-09_15:03:22 107552 FHEM/74_GardenaSmartDevice.pm +UPD 2022-08-11_12:40:06 107803 FHEM/74_GardenaSmartDevice.pm From 76a7eeb4e5bfb46ea2be6f9e5bae8c3e4162af7e Mon Sep 17 00:00:00 2001 From: Sebastian Date: Thu, 11 Aug 2022 14:25:19 +0200 Subject: [PATCH 29/29] [fix] - upper/lower case --- CHANGED | 2 +- FHEM/74_GardenaSmartDevice.pm | 6 +++--- controls_GardenaSmartDevice.txt | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGED b/CHANGED index 816fbc9..b612008 100644 --- a/CHANGED +++ b/CHANGED @@ -1 +1 @@ - [final 2] - removed debug dumper code + [enhancement] - add resetvalveerrors ic24 diff --git a/FHEM/74_GardenaSmartDevice.pm b/FHEM/74_GardenaSmartDevice.pm index 4e5f3b3..6429842 100644 --- a/FHEM/74_GardenaSmartDevice.pm +++ b/FHEM/74_GardenaSmartDevice.pm @@ -571,7 +571,7 @@ sub Set { if ( AttrVal( $name, 'model', 'unknown' ) eq 'electronic_pressure_pump' ); $list .= -'closeAllValves:noArg resetvalveerrors:noArg stopScheduleValve:select,'.ReadingsVal( $name, 'ic24-valves_connected', '1' ).' resumeScheduleValve:select,'.ReadingsVal( $name, 'ic24-valves_connected', '1' ) +'closeAllValves:noArg resetValveErrors:noArg stopScheduleValve:select,'.ReadingsVal( $name, 'ic24-valves_connected', '1' ).' resumeScheduleValve:select,'.ReadingsVal( $name, 'ic24-valves_connected', '1' ) if ( AttrVal( $name, 'model', 'unknown' ) eq 'ic24' ); foreach my $valve (split(',', ReadingsVal( $name, 'ic24-valves_connected', '1'))) { @@ -1821,7 +1821,7 @@ sub SetPredefinedStartPoints {
                • manualDurationValve4 n - open valve 4 for n minutes
                • manualDurationValve5 n - open valve 5 for n minutes
                • manualDurationValve6 n - open valve 6 for n minutes
                • -
                • resetvalveerrors n - reset valve errormessage
                • +
                • resetValveErrors n - reset valve errormessage
                • resumeScheduleValve n - (re)start irrigation schedule for valve n
                • stopScheduleValve n m - stop irrigation schedule for valve n (Default: 2038-01-18T00:00:00.000Z, Gardena App reads it as "permanently")
                • @@ -2237,7 +2237,7 @@ sub SetPredefinedStartPoints {
                • manualDurationValve4 n - Ventil 4 für n Minuten öffnen
                • manualDurationValve5 n - Ventil 5 für n Minuten öffnen
                • manualDurationValve6 n - Ventil 6 für n Minuten öffnen
                • -
                • resetvalveerrors n - Ventilfehler zurücksetzen
                • +
                • resetValveErrors n - Ventilfehler zurücksetzen
                • resumeScheduleValve n - Zeitplan für Ventil n wieder aktivieren
                • stopScheduleValve n m - Zeitplan für Ventil n anhalten für m Stunden (Default: 2038-01-18T00:00:00.000Z, durch Gardena-App als "dauerhaft" interpretiert)
                • diff --git a/controls_GardenaSmartDevice.txt b/controls_GardenaSmartDevice.txt index 2167974..32327a6 100644 --- a/controls_GardenaSmartDevice.txt +++ b/controls_GardenaSmartDevice.txt @@ -1,2 +1,2 @@ UPD 2022-07-21_19:43:48 49634 FHEM/73_GardenaSmartBridge.pm -UPD 2022-08-11_12:40:06 107803 FHEM/74_GardenaSmartDevice.pm +UPD 2022-08-11_14:24:26 107803 FHEM/74_GardenaSmartDevice.pm