############################################################################### # # Developed with Kate # # (c) 2017-2019 Copyright: Marko Oldenburg (leongaultier at gmail dot com) # 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 # # # 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/ # ## ## package main; use strict; use warnings; my $version = "1.4.2"; sub GardenaSmartDevice_Initialize($) { my ($hash) = @_; $hash->{Match} = '^{"id":".*'; $hash->{SetFn} = "FHEM::GardenaSmartDevice::Set"; $hash->{DefFn} = "FHEM::GardenaSmartDevice::Define"; $hash->{UndefFn} = "FHEM::GardenaSmartDevice::Undef"; $hash->{ParseFn} = "FHEM::GardenaSmartDevice::Parse"; $hash->{AttrFn} = "FHEM::GardenaSmartDevice::Attr"; $hash->{AttrList} = "readingValueLanguage:de,en " . "model:watering_computer,sensor,mower,ic24,power " . "IODev " . $readingFnAttributes; foreach my $d ( sort keys %{ $modules{GardenaSmartDevice}{defptr} } ) { my $hash = $modules{GardenaSmartDevice}{defptr}{$d}; $hash->{VERSION} = $version; } } ## unserer packagename package FHEM::GardenaSmartDevice; use GPUtils qw(GP_Import) ; # wird für den Import der FHEM Funktionen aus der fhem.pl benötigt my $missingModul = ""; use strict; use warnings; use POSIX; use Time::Local; eval "use JSON;1" or $missingModul .= "JSON "; ## Import der FHEM Funktionen BEGIN { GP_Import( qw(readingsSingleUpdate readingsBulkUpdate readingsBulkUpdateIfChanged readingsBeginUpdate readingsEndUpdate Log3 CommandAttr AttrVal ReadingsVal AssignIoPort modules IOWrite defs makeDeviceName) ); } sub Define($$) { my ( $hash, $def ) = @_; my @a = split( "[ \t]+", $def ); return "too few parameters: define GardenaSmartDevice " if ( @a < 3 ); return "Cannot define Gardena Bridge device. Perl modul $missingModul is missing." if ($missingModul); my $name = $a[0]; my $deviceId = $a[2]; my $category = $a[3]; $hash->{DEVICEID} = $deviceId; $hash->{VERSION} = $version; $hash->{helper}{STARTINGPOINTID} = ''; 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) and $d->{IODev} == $hash->{IODev} and $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 undef; } sub Undef($$) { my ( $hash, $arg ) = @_; my $name = $hash->{NAME}; my $deviceId = $hash->{DEVICEID}; delete $modules{GardenaSmartDevice}{defptr}{$deviceId}; return undef; } sub Attr(@) { my ( $cmd, $name, $attrName, $attrVal ) = @_; my $hash = $defs{$name}; return undef; } sub Set($@) { my ( $hash, $name, $cmd, @args ) = @_; my $payload; my $abilities = ''; ### mower if ( lc $cmd eq 'parkuntilfurthernotice' ) { $payload = '"name":"park_until_further_notice"'; } elsif ( lc $cmd eq 'parkuntilnexttimer' ) { $payload = '"name":"park_until_next_timer"'; } elsif ( lc $cmd eq 'startresumeschedule' ) { $payload = '"name":"start_resume_schedule"'; } elsif ( lc $cmd eq 'startoverridetimer' ) { my $duration = join( " ", @args ); $payload = '"name":"start_override_timer","parameters":{"duration":' . $duration . '}'; } elsif ( lc $cmd eq 'startpoint' ) { my $err; ( $err, $payload, $abilities ) = SetPredefinedStartPoints( $hash, @args ); return $err if ( defined($err) ); ### watering_computer } elsif ( lc $cmd eq 'manualoverride' ) { my $duration = join( " ", @args ); $payload = '"name":"manual_override","parameters":{"duration":' . $duration . '}'; } elsif ( lc $cmd eq 'canceloverride' ) { $payload = '"name":"cancel_override"'; } elsif ( lc $cmd eq 'on' or lc $cmd eq 'off' or lc $cmd eq 'on-for-timer' ) { my $val = ( defined($args[0]) ? join( " ", @args ) : lc $cmd ); $payload = '"properties":{"value":"' . $val . '"}'; } ### Watering ic24 elsif ( $cmd =~ /manualDurationValve/ ) { my $valve_id; my $duration = join( " ", @args ); if ( $cmd =~ m#(\d)$# ) { $valve_id = $1; } $payload = '"properties":{"name":"watering_timer_' . $valve_id . '","value":{"state":"manual","duration":' . $duration . ',"valve_id":' . $valve_id . '}}'; ### Sensors } elsif ( lc $cmd eq 'refresh' ) { my $sensname = join( " ", @args ); if ( lc $sensname eq 'temperature' ) { $payload = '"name":"measure_ambient_temperature"'; $abilities = 'ambient_temperature'; } elsif ( lc $sensname eq 'light' ) { $payload = '"name":"measure_light"'; $abilities = 'light'; } elsif ( lc $sensname eq 'humidity' ) { $payload = '"name":"measure_soil_humidity"'; $abilities = 'humidity'; } } else { my $list = ''; $list .= 'parkUntilFurtherNotice:noArg parkUntilNextTimer:noArg startResumeSchedule:noArg startOverrideTimer:slider,0,60,1440 startpoint' if ( AttrVal( $name, 'model', 'unknown' ) eq 'mower' ); $list .= 'manualOverride:slider,0,1,59 cancelOverride:noArg' if ( AttrVal( $name, 'model', 'unknown' ) eq 'watering_computer' ); $list .= 'manualDurationValve1:slider,1,1,59 manualDurationValve2:slider,1,1,59 manualDurationValve3:slider,1,1,59 manualDurationValve4:slider,1,1,59 manualDurationValve5:slider,1,1,59 manualDurationValve6:slider,1,1,59' if ( AttrVal( $name, 'model', 'unknown' ) eq 'ic24' ); $list .= 'refresh:temperature,light,humidity' if ( AttrVal( $name, 'model', 'unknown' ) eq 'sensor' ); $list .= 'on:noArg off:noArg on-for-timer:slider,0,1,180' if ( AttrVal( $name, 'model', 'unknown' ) eq 'power' ); return "Unknown argument $cmd, choose one of $list"; } $abilities = 'mower' if ( AttrVal( $name, 'model', 'unknown' ) eq 'mower' ) and $abilities ne 'mower_settings'; $abilities = 'outlet' if ( AttrVal( $name, 'model', 'unknown' ) eq 'watering_computer' ); $abilities = 'watering' if ( AttrVal( $name, 'model', 'unknown' ) eq 'ic24' ); $abilities = 'power' if ( AttrVal( $name, 'model', 'unknown' ) eq 'power' ); $hash->{helper}{deviceAction} = $payload; readingsSingleUpdate( $hash, "state", "send command to gardena cloud", 1 ); IOWrite( $hash, $payload, $hash->{DEVICEID}, $abilities ); Log3 $name, 4, "GardenaSmartBridge ($name) - IOWrite: $payload $hash->{DEVICEID} $abilities IODevHash=$hash->{IODev}"; return undef; } sub Parse($$) { my ( $io_hash, $json ) = @_; my $name = $io_hash->{NAME}; my $decode_json = eval { decode_json($json) }; if ($@) { Log3 $name, 3, "GardenaSmartBridge ($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}"; } } } sub WriteReadings($$) { my ( $hash, $decode_json ) = @_; my $name = $hash->{NAME}; my $abilities = scalar( @{ $decode_json->{abilities} } ); my $settings = scalar( @{ $decode_json->{settings} } ); readingsBeginUpdate($hash); do { if ( ref( $decode_json->{abilities}[$abilities]{properties} ) eq "ARRAY" and scalar( @{ $decode_json->{abilities}[$abilities]{properties} } ) > 0 ) { foreach my $propertie ( @{ $decode_json->{abilities}[$abilities]{properties} } ) { readingsBulkUpdateIfChanged( $hash, $decode_json->{abilities}[$abilities]{name} . '-' . $propertie->{name}, RigRadingsValue( $hash, $propertie->{value} ) ) if ( defined( $propertie->{value} ) and $decode_json->{abilities}[$abilities]{name} . '-' . $propertie->{name} ne 'radio-quality' and $decode_json->{abilities}[$abilities]{name} . '-' . $propertie->{name} ne 'battery-level' and $decode_json->{abilities}[$abilities]{name} . '-' . $propertie->{name} ne 'internal_temperature-temperature' and $decode_json->{abilities}[$abilities]{name} . '-' . $propertie->{name} ne 'ambient_temperature-temperature' and $decode_json->{abilities}[$abilities]{name} . '-' . $propertie->{name} ne 'soil_temperature-temperature' and $decode_json->{abilities}[$abilities]{name} . '-' . $propertie->{name} ne 'humidity-humidity' and $decode_json->{abilities}[$abilities]{name} . '-' . $propertie->{name} ne 'light-light' and ref( $propertie->{value} ) ne "HASH" ); readingsBulkUpdate( $hash, $decode_json->{abilities}[$abilities]{name} . '-' . $propertie->{name}, RigRadingsValue( $hash, $propertie->{value} ) ) if ( defined( $propertie->{value} ) and ( $decode_json->{abilities}[$abilities]{name} . '-' . $propertie->{name} eq 'radio-quality' or $decode_json->{abilities}[$abilities]{name} . '-' . $propertie->{name} eq 'battery-level' or $decode_json->{abilities}[$abilities]{name} . '-' . $propertie->{name} eq 'internal_temperature-temperature' or $decode_json->{abilities}[$abilities]{name} . '-' . $propertie->{name} eq 'ambient_temperature-temperature' or $decode_json->{abilities}[$abilities]{name} . '-' . $propertie->{name} eq 'soil_temperature-temperature' or $decode_json->{abilities}[$abilities]{name} . '-' . $propertie->{name} eq 'humidity-humidity' or $decode_json->{abilities}[$abilities]{name} . '-' . $propertie->{name} eq 'light-light' ) ); readingsBulkUpdateIfChanged( $hash, $decode_json->{abilities}[$abilities]{name} . '-' . $propertie->{name}, join( ',', @{ $propertie->{value} } ) ) if ( defined( $propertie->{value} ) and $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} ) and $decode_json->{abilities}[$abilities]{name} . '-' . $propertie->{name} eq 'ic24-valves_master_config' ); if ( ref( $propertie->{value} ) eq "HASH" ) { while ( my ( $r, $v ) = each %{ $propertie->{value} } ) { readingsBulkUpdate( $hash, $decode_json->{abilities}[$abilities]{name} . '-' . $propertie->{name} . '_' . $r, RigRadingsValue( $hash, $v ) ); } } } } $abilities--; } while ( $abilities >= 0 ); do { if ( ref( $decode_json->{settings}[$settings]{value} ) eq "ARRAY" and $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; foreach my $startingpoint ( @{ $decode_json->{settings}[$settings]{value} } ) { $startpoint_cnt++; readingsBulkUpdateIfChanged( $hash, 'startpoint-' . $startpoint_cnt . '-enabled', $startingpoint->{enabled} ); } } $settings--; } while ( $settings >= 0 ); readingsBulkUpdate( $hash, 'state', ReadingsVal( $name, 'mower-status', 'readingsValError' ) ) if ( AttrVal( $name, 'model', 'unknown' ) eq 'mower' ); readingsBulkUpdate( $hash, 'state', ( ReadingsVal( $name, 'outlet-valve_open', 'readingsValError' ) == 1 ? RigRadingsValue( $hash, 'open' ) : RigRadingsValue( $hash, 'closed' ) ) ) if ( AttrVal( $name, 'model', 'unknown' ) eq 'watering_computer' ); readingsBulkUpdate( $hash, 'state', 'T: ' . ReadingsVal( $name, 'ambient_temperature-temperature', 'readingsValError' ) . '°C, H: ' . ReadingsVal( $name, 'humidity-humidity', 'readingsValError' ) . '%, L: ' . ReadingsVal( $name, 'light-light', 'readingsValError' ) . 'lux' ) if ( AttrVal( $name, 'model', 'unknown' ) eq 'sensor' ); readingsBulkUpdate( $hash, 'state', 'scheduled watering next start: ' . ( ReadingsVal( $name, 'scheduling-scheduled_watering_next_start', 'no timer' ) ) ) if ( AttrVal( $name, 'model', 'unknown' ) eq 'ic24' ); readingsBulkUpdate( $hash, 'state', ReadingsVal( $name, 'power-power_timer', 'no info from power-timer' ) ) if ( AttrVal( $name, 'model', 'unknown' ) eq 'power' ); readingsEndUpdate( $hash, 1 ); Log3 $name, 4, "GardenaSmartDevice ($name) - readings was written}"; } ################################## ################################## #### my little helpers ########### sub ReadingLangGerman($$) { my ( $hash, $readingValue ) = @_; my $name = $hash->{NAME}; my %langGermanMapp = ( 'ok_cutting' => 'mähen', 'paused' => 'pausiert', 'ok_searching' => 'suche Ladestation', 'ok_charging' => 'lädt', 'ok_leaving' => 'mähen', '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' ); if ( defined( $langGermanMapp{$readingValue} ) and ( AttrVal( 'global', 'language', 'none' ) eq 'DE' or AttrVal( $name, 'readingValueLanguage', 'none' ) eq 'de' ) and AttrVal( $name, 'readingValueLanguage', 'none' ) ne 'en' ) { return $langGermanMapp{$readingValue}; } else { return $readingValue; } } sub RigRadingsValue($$) { my ( $hash, $readingValue ) = @_; 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 "illegal year"; } else { return ( sprintf( "%04d-%02d-%02d %02d:%02d", $lyear, $lmonth, $lday, $lhour, substr( $datemin, 0, 2 ) ) ); } } sub SetPredefinedStartPoints($@) { my ( $hash, $startpoint_state, $startpoint_num, @morestartpoints ) = @_; my $name = $hash->{NAME}; my $payload; my $abilities; if ( defined($startpoint_state) and defined($startpoint_num) ) { if ( defined( $hash->{helper}{STARTINGPOINTS} ) and $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) and ( scalar(@morestartpoints) == 2 or 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'; } 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
    • 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
=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
    • 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
=end html_DE =cut