2017-08-05 20:58:40 +00:00
###############################################################################
#
# Developed with Kate
#
# (c) 2017 Copyright: Marko Oldenburg (leongaultier at gmail dot com)
# All rights reserved
#
# 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 ;
my $ missingModul = "" ;
use strict ;
use warnings ;
use Data::Dumper ; #debugging
eval "use Encode qw(encode encode_utf8 decode_utf8);1" or $ missingModul . = "Encode " ;
eval "use JSON;1" or $ missingModul . = "JSON " ;
2017-08-11 19:35:46 +00:00
my $ version = "0.0.48" ;
2017-08-05 20:58:40 +00:00
# Declare functions
sub GardenaSmartDevice_Attr (@) ;
sub GardenaSmartDevice_Define ($$) ;
sub GardenaSmartDevice_Initialize ($) ;
sub GardenaSmartDevice_Set ($@) ;
sub GardenaSmartDevice_Undef ($$) ;
sub GardenaSmartDevice_WriteReadings ($$) ;
sub GardenaSmartDevice_Parse ($$) ;
sub GardenaSmartDevice_Initialize ($) {
my ( $ hash ) = @ _ ;
$ hash - > { Match } = '^{"id":".*' ;
$ hash - > { SetFn } = "GardenaSmartDevice_Set" ;
$ hash - > { DefFn } = "GardenaSmartDevice_Define" ;
$ hash - > { UndefFn } = "GardenaSmartDevice_Undef" ;
$ hash - > { ParseFn } = "GardenaSmartDevice_Parse" ;
$ hash - > { AttrFn } = "GardenaSmartDevice_Attr" ;
$ hash - > { AttrList } = "disable:1 " .
"model " .
$ readingFnAttributes ;
foreach my $ d ( sort keys % { $ modules { GardenaSmartDevice } { defptr } } ) {
my $ hash = $ modules { GardenaSmartDevice } { defptr } { $ d } ;
$ hash - > { VERSION } = $ version ;
}
}
sub GardenaSmartDevice_Define ($$) {
my ( $ hash , $ def ) = @ _ ;
my @ a = split ( "[ \t]+" , $ def ) ;
splice ( @ a , 1 , 1 ) ;
my $ iodev ;
my $ i = 0 ;
foreach my $ param ( @ a ) {
if ( $ param =~ m/IODev=([^\s]*)/ ) {
$ iodev = $ 1 ;
splice ( @ a , $ i , 3 ) ;
last ;
}
$ i + + ;
}
return "too few parameters: define <NAME> GardenaSmartDevice <device_Id> <model>" if ( @ a != 3 ) ;
return "Cannot define Gardena Bridge device. Perl modul $missingModul is missing." if ( $ missingModul ) ;
my ( $ name , $ deviceId , $ category ) = @ a ;
$ hash - > { DEVICEID } = $ deviceId ;
$ hash - > { VERSION } = $ version ;
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 ) ;
$ attr { $ name } { room } = "GardenaSmart" if ( not defined ( $ attr { $ name } { room } ) ) ;
$ attr { $ name } { model } = $ category if ( not defined ( $ attr { $ name } { model } ) ) ;
2017-08-06 07:11:04 +00:00
Log3 $ name , 3 , "GardenaSmartDevice ($name) - defined GardenaSmartDevice with DEVICEID: $deviceId" ;
2017-08-06 19:33:09 +00:00
readingsSingleUpdate ( $ hash , 'state' , 'initialized' , 1 ) ;
2017-08-05 20:58:40 +00:00
$ modules { GardenaSmartDevice } { defptr } { $ deviceId } = $ hash ;
return undef ;
}
sub GardenaSmartDevice_Undef ($$) {
my ( $ hash , $ arg ) = @ _ ;
my $ name = $ hash - > { NAME } ;
my $ deviceId = $ hash - > { DEVICEID } ;
delete $ modules { GardenaSmartDevice } { defptr } { $ deviceId } ;
return undef ;
}
sub GardenaSmartDevice_Attr (@) {
my ( $ cmd , $ name , $ attrName , $ attrVal ) = @ _ ;
my $ hash = $ defs { $ name } ;
2017-08-06 07:11:04 +00:00
2017-08-05 20:58:40 +00:00
return undef ;
}
sub GardenaSmartDevice_Set ($@) {
my ( $ hash , $ name , $ cmd , @ args ) = @ _ ;
my ( $ arg , @ params ) = @ args ;
my $ payload ;
2017-08-07 18:02:15 +00:00
my $ abilities ;
2017-08-05 20:58:40 +00:00
2017-08-07 18:02:15 +00:00
### mower
2017-08-05 20:58:40 +00:00
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 . '}' ;
2017-08-07 18:02:15 +00:00
### watering_computer
2017-08-06 07:11:04 +00:00
} elsif ( lc $ cmd eq 'manualoverride' ) {
my $ duration = join ( " " , @ args ) ;
$ payload = '"name":"manual_override","parameters":{"duration":' . $ duration . '}' ;
2017-08-05 20:58:40 +00:00
2017-08-06 07:11:04 +00:00
} elsif ( lc $ cmd eq 'canceloverride' ) {
2017-08-05 20:58:40 +00:00
2017-08-06 07:11:04 +00:00
$ payload = '"name":"cancel_override"' ;
2017-08-05 20:58:40 +00:00
2017-08-07 18:02:15 +00:00
### Sensors
2017-08-07 11:50:26 +00:00
} elsif ( lc $ cmd eq 'refresh' ) {
my $ sensname = join ( " " , @ args ) ;
2017-08-07 18:02:15 +00:00
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_humidity"' ;
$ abilities = 'humidity' ;
}
2017-08-05 20:58:40 +00:00
} elsif ( lc $ cmd eq '' ) {
} elsif ( lc $ cmd eq '' ) {
} elsif ( lc $ cmd eq '' ) {
} elsif ( lc $ cmd eq '' ) {
} elsif ( lc $ cmd eq '' ) {
} elsif ( lc $ cmd eq '' ) {
} else {
2017-08-06 07:11:04 +00:00
my $ list = '' ;
$ list . = 'parkUntilFurtherNotice:noArg parkUntilNextTimer:noArg startResumeSchedule:noArg startOverrideTimer:slider,0,60,1440' if ( AttrVal ( $ name , 'model' , 'unknown' ) eq 'mower' ) ;
2017-08-07 18:26:56 +00:00
$ list . = 'manualOverride:slider,0,1,59 cancelOverride:noArg' if ( AttrVal ( $ name , 'model' , 'unknown' ) eq 'watering_computer' ) ;
2017-08-11 19:35:46 +00:00
$ list . = 'refresh:temperature,light' if ( AttrVal ( $ name , 'model' , 'unknown' ) eq 'sensor' ) ;
2017-08-05 20:58:40 +00:00
return "Unknown argument $cmd, choose one of $list" ;
}
2017-08-07 18:02:15 +00:00
$ abilities = 'mower' if ( AttrVal ( $ name , 'model' , 'unknown' ) eq 'mower' ) ;
$ abilities = 'outlet' if ( AttrVal ( $ name , 'model' , 'unknown' ) eq 'watering_computer' ) ;
2017-08-10 19:54:34 +00:00
2017-08-10 13:00:29 +00:00
$ hash - > { helper } { deviceAction } = $ payload ;
2017-08-10 20:57:15 +00:00
readingsSingleUpdate ( $ hash , "state" , "send command to gardena cloud" , 1 ) ;
2017-08-07 18:02:15 +00:00
IOWrite ( $ hash , $ payload , $ hash - > { DEVICEID } , $ abilities ) ;
Log3 $ name , 4 , "GardenaSmartBridge ($name) - IOWrite: $payload $hash->{DEVICEID} $abilities IODevHash=$hash->{IODev}" ;
2017-08-05 20:58:40 +00:00
return undef ;
}
sub GardenaSmartDevice_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" ;
2017-08-06 07:11:04 +00:00
Log3 $ name , 5 , "GardenaSmartDevice ($name) - JSON: $json" ;
2017-08-05 20:58:40 +00:00
if ( defined ( $ decode_json - > { id } ) ) {
my $ deviceId = $ decode_json - > { id } ;
if ( my $ hash = $ modules { GardenaSmartDevice } { defptr } { $ deviceId } ) {
my $ name = $ hash - > { NAME } ;
GardenaSmartDevice_WriteReadings ( $ hash , $ decode_json ) ;
2017-08-06 07:11:04 +00:00
Log3 $ name , 4 , "GardenaSmartDevice ($name) - find logical device: $hash->{NAME}" ;
2017-08-05 20:58:40 +00:00
return $ hash - > { NAME } ;
} else {
2017-08-07 15:40:11 +00:00
Log3 $ name , 3 , "GardenaSmartDevice ($name) - autocreate new device " . join ( '' , split ( "[ \t]+" , $ decode_json - > { name } ) ) . " with deviceId $decode_json->{id}, model $decode_json->{category} and IODev IODev=$name" ;
return "UNDEFINED " . join ( '' , split ( "[ \t]+" , $ decode_json - > { name } ) ) . " GardenaSmartDevice $decode_json->{id} $decode_json->{category} IODev=$name" ;
2017-08-05 20:58:40 +00:00
}
}
}
sub GardenaSmartDevice_WriteReadings ($$) {
my ( $ hash , $ decode_json ) = @ _ ;
my $ name = $ hash - > { NAME } ;
my $ abilities = scalar ( @ { $ decode_json - > { abilities } } ) ;
2017-08-06 07:11:04 +00:00
readingsBeginUpdate ( $ hash ) ;
2017-08-05 20:58:40 +00:00
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 } } ) {
2017-08-11 19:35:46 +00:00
readingsBulkUpdateIfChanged ( $ hash , $ decode_json - > { abilities } [ $ abilities ] { name } . '-' . $ propertie - > { name } , $ 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' ) ;
readingsBulkUpdate ( $ hash , $ decode_json - > { abilities } [ $ abilities ] { name } . '-' . $ propertie - > { name } , $ 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' ) ) ;
2017-08-05 20:58:40 +00:00
}
}
$ abilities - - ;
} while ( $ abilities >= 0 ) ;
2017-08-06 19:33:09 +00:00
2017-08-07 16:15:05 +00:00
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 ? "open" : "closed" ) ) if ( AttrVal ( $ name , 'model' , 'unknown' ) eq 'watering_computer' ) ;
2017-08-06 19:33:09 +00:00
2017-08-11 19:35:46 +00:00
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' ) ;
2017-08-06 19:33:09 +00:00
2017-08-06 07:11:04 +00:00
readingsEndUpdate ( $ hash , 1 ) ;
2017-08-05 20:58:40 +00:00
Log3 $ name , 4 , "GardenaSmartDevice ($name) - readings was written}" ;
}
##################################
##################################
#### my little helpers ###########
1 ;
= pod
= item device
= item summary Gardena Smart
= item summary_DE Gardena Smart
= begin html
= end html
= begin html_DE
= end html_DE
= cut