# $Id: 74_THINKINGCLEANER.pm 13389 2017-02-11 13:34:44Z loredo $
##############################################################################
#
# 74_THINKINGCLEANER.pm
# An FHEM Perl module for controlling ThinkingCleaner connected
# Roomba vacuum cleaning robot.
#
# Copyright by Julian Pawlowski
# e-mail: julian.pawlowski at gmail.com
#
# This file is part of fhem.
#
# Fhem is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# Fhem is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with fhem. If not, see .
#
##############################################################################
package main;
use strict;
use warnings;
use vars qw(%data);
use HttpUtils;
use Encode;
use Data::Dumper;
no warnings "all";
sub THINKINGCLEANER_Set($@);
sub THINKINGCLEANER_GetStatus($;$);
sub THINKINGCLEANER_Attr($@);
sub THINKINGCLEANER_Define($$);
sub THINKINGCLEANER_Undefine($$);
###################################
sub THINKINGCLEANER_Initialize($) {
my ($hash) = @_;
Log3 $hash, 5, "THINKINGCLEANER_Initialize: Entering";
my $webhookFWinstance =
join( ",", devspec2array('TYPE=FHEMWEB:FILTER=TEMPORARY!=1') );
$hash->{SetFn} = "THINKINGCLEANER_Set";
$hash->{DefFn} = "THINKINGCLEANER_Define";
$hash->{AttrFn} = "THINKINGCLEANER_Attr";
$hash->{UndefFn} = "THINKINGCLEANER_Undefine";
$hash->{parseParams} = 1;
$hash->{AttrList} =
"disable:0,1 timeout:1,2,3,4,5 pollInterval:30,45,60,75,90 pollMultiplierWebhook pollMultiplierCleaning model webhookHttpHostname webhookPort webhookFWinstance:$webhookFWinstance restart:noArg "
. $readingFnAttributes;
# 98_powerMap.pm support
$hash->{powerMap} = {
model => 'modelid', # fallback to attribute
modelid => {
'Roomba_700_Series' => {
rname_E => 'energy',
rname_P => 'consumption',
map => {
presence => {
absent => 0,
},
deviceStatus => {
base => 0.1,
plug => 0.1,
base_recon => 33,
plug_recon => 33,
base_full => 33,
plug_full => 33,
base_trickle => 5,
plug_trickle => 5,
base_wait => 0.1,
plug_wait => 0.1,
'*' => 0,
},
},
},
},
};
return;
}
#####################################
sub THINKINGCLEANER_GetStatus($;$) {
my ( $hash, $delay ) = @_;
my $name = $hash->{NAME};
$hash->{INTERVAL_MULTIPLIER} = (
ReadingsVal( $name, "state", "off" ) ne "off"
&& ReadingsVal( $name, "state", "absent" ) ne "absent"
&& ReadingsVal( $name, "state", "standby" ) ne "standby"
? AttrVal( $name, "pollMultiplierCleaning", "0.5" )
: (
$hash->{WEBHOOK_REGISTER} eq "success"
? AttrVal( $name, "pollMultiplierWebhook", "2" )
: "1"
)
);
$hash->{INTERVAL} =
AttrVal( $name, "pollInterval", "45" ) * $hash->{INTERVAL_MULTIPLIER};
my $interval = (
$delay
? $delay
: $hash->{INTERVAL}
);
Log3 $name, 5,
"THINKINGCLEANER $name: called function THINKINGCLEANER_GetStatus()";
RemoveInternalTimer($hash);
InternalTimer( gettimeofday() + $interval,
"THINKINGCLEANER_GetStatus", $hash, 0 );
return
if ( $delay || AttrVal( $name, "disable", 0 ) == 1 );
THINKINGCLEANER_SendCommand( $hash, "full_status.json" );
return;
}
###################################
sub THINKINGCLEANER_Set($$$) {
my ( $hash, $a, $h ) = @_;
my $name = $hash->{NAME};
my $state = ReadingsVal( $name, "state", "absent" );
my $deviceStatus = ReadingsVal( $name, "deviceStatus", "off" );
my $presence = ReadingsVal( $name, "presence", "absent" );
my $power = ReadingsVal( $name, "power", "off" );
Log3 $name, 5,
"THINKINGCLEANER $name: called function THINKINGCLEANER_Set()";
return "Argument is missing" if ( int(@$a) < 1 );
my $usage =
"Unknown argument "
. @$a[1]
. ", choose one of statusRequest:noArg toggle:noArg on:noArg on-spot:noArg on-max:noArg off:noArg power:off,on dock:noArg undock:noArg locate:noArg on-delayed:noArg cleaningDelay remoteControl:forward,backward,left,left-spin,right,right-spin,stop,drive scheduleAdd name damageProtection:off,on reboot:noArg autoUpdate:on,off vacuumDrive:off,on restartAC:on,off alwaysMAX:on,off autoDock:on,off keepAwakeOnDock:on,off songSubmit songReset:noArg dockAt stopAt";
my $cmd = '';
my $result;
# find existing schedules and offer set commands
my $sd0 = ReadingsVal( $name, "schedule0", "" );
my $sd1 = ReadingsVal( $name, "schedule1", "" );
my $sd2 = ReadingsVal( $name, "schedule2", "" );
my $sd3 = ReadingsVal( $name, "schedule3", "" );
my $sd4 = ReadingsVal( $name, "schedule4", "" );
my $sd5 = ReadingsVal( $name, "schedule5", "" );
my $sd6 = ReadingsVal( $name, "schedule6", "" );
my $schedules = "";
my $si = "0";
foreach ( $sd0, $sd1, $sd2, $sd3, $sd4, $sd5, $sd6 ) {
if ( $_ ne "" ) {
$schedules .= "," if ( $schedules ne "" );
$_ =~ s/(\d+)_(\d{2}:\d{2}:\d{2})_(([A-Za-z]+),?)/$si\_$1_$2_$3/g;
$schedules .= $_;
}
$si++;
}
$usage .= " scheduleDel:$schedules scheduleMod:$schedules"
if ( $schedules ne "" );
# statusRequest
if ( lc( @$a[1] ) eq "statusrequest" ) {
Log3 $name, 3, "THINKINGCLEANER set $name " . @$a[1];
THINKINGCLEANER_GetStatus($hash);
}
# scheduleAdd
elsif ( lc( @$a[1] ) eq "scheduleadd" ) {
if ( $state ne "absent" ) {
Log3 $name, 3,
"THINKINGCLEANER set $name "
. @$a[1] . " "
. @$a[2] . " "
. @$a[3] . " "
. @$a[4];
return
"Missing arguments. Usage: scheduleAdd