From 197c314120db2c1ff86982c194fee8fecccd76ea Mon Sep 17 00:00:00 2001 From: Matthias Sandmann Date: Fri, 18 Mar 2022 22:44:22 +0100 Subject: [PATCH] filled new skeleton with basic data --- 98_EaseeWallbox.pm | 1187 ++++++++++++++------------------------------ 1 file changed, 383 insertions(+), 804 deletions(-) diff --git a/98_EaseeWallbox.pm b/98_EaseeWallbox.pm index 13583dd..fb2356c 100644 --- a/98_EaseeWallbox.pm +++ b/98_EaseeWallbox.pm @@ -1,4 +1,5 @@ -package main; +package FHEM::EaseeWallbox; +use GPUtils qw(GP_Import GP_Export); use strict; use warnings; @@ -8,12 +9,101 @@ use Encode qw( encode_utf8 ); use HttpUtils; use JSON; -my %EaseeWallbox_gets = ( - update => { - args => "noArg", - urlTemplate => "", - callback => \&EaseeWallbox_httpSimpleOperationCallback - }, +# 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 von Funktionen und/oder Variablen aus der FHEM main +# man kann ::Funktionaname wählen und sich so den Import schenken. Variablen sollten aber +# sauber importiert werden +use GPUtils qw(GP_Import); + +## Import der FHEM Funktionen +#-- Run before package compilation +BEGIN { + # Import from main context + GP_Import( + qw( + readingFnAttributes + Log3 + readingsBeginUpdate + readingsEndUpdate + readingsBulkUpdate + readingsSingleUpdate + InternalVal + ReadingsVal + RemoveInternalTimer + InternalTimer + HttpUtils_NonblockingGet + HttpUtils_BlockingGet + gettimeofday + getUniqueId + Attr + ) + ); +} + +#-- Export to main context with different name +GP_Export( + qw( + Initialize + ) +); + + +my %gets = ( + update => "noArg", health => "noArg", baseData => "noArg", chargers => "noArg", @@ -22,7 +112,7 @@ my %EaseeWallbox_gets = ( config => "noArg", ); -my %EaseeWallbox_sets = ( +my %sets = ( startCharging => "", stopCharging => "", pauseCharging => "", @@ -41,56 +131,37 @@ my %EaseeWallbox_sets = ( deactivateTimer => "", ); -my %EaseeWallbox_urls = ( - getOAuthToken => 'https://api.easee.cloud/api/accounts/login', - getRefreshToken => 'https://api.easee.cloud/api/accounts/refresh_token', - getProfile => 'https://api.easee.cloud/api/accounts/profile', - getChargingSession => - 'https://api.easee.cloud/api/chargers/#ChargerID#/sessions/ongoing', - getChargers => 'https://api.easee.cloud/api/accounts/chargers', - getProducts => - 'https://api.easee.cloud/api/accounts/products?userId=#UserId#', - getChargerSite => 'https://api.easee.cloud/api/chargers/#ChargerID#/site', - getChargerDetails => - 'https://api.easee.cloud/api/chargers/#ChargerID#/details', - getChargerConfiguration => - 'https://api.easee.cloud/api/chargers/#ChargerID#/config', - getChargerSessionsMonthly => - 'https://api.easee.cloud/api/sessions/charger/#ChargerID#/monthly', - getChargerSessionsDaily => - 'https://api.easee.cloud/api/sessions/charger/#ChargerID#/daily', - getChargerState => - 'https://api.easee.cloud/api/chargers/#ChargerID#/state', - getCurrentSession => - 'https://api.easee.cloud/api/chargers/#ChargerID#/sessions/ongoing', - setCableLockState => - 'https://api.easee.cloud/api/chargers/#ChargerID#/commands/lock_state', - setReboot => - 'https://api.easee.cloud/api/chargers/#ChargerID#/commands/reboot', - setUpdateFirmware => - 'https://api.easee.cloud/api/chargers/#ChargerID#/commands/update_firmware', - setEnableSmartCharging => - 'https://api.easee.cloud/api/chargers/#ChargerID#/commands/smart_charging', - setStartCharging => - 'https://api.easee.cloud/api/chargers/#ChargerID#/commands/start_charging', - setStopCharging => - 'https://api.easee.cloud/api/chargers/#ChargerID#/commands/stop_charging', - setPauseCharging => - 'https://api.easee.cloud/api/chargers/#ChargerID#/commands/pause_charging', - setResumeCharging => - 'https://api.easee.cloud/api/chargers/#ChargerID#/commands/resume_charging', - setToggleCharging => - 'https://api.easee.cloud/api/chargers/#ChargerID#/commands/toggle_charging', - setOverrideChargingSchedule => - 'https://api.easee.cloud/api/chargers/#ChargerID#/commands/override_schedule', - setPairRFIDTag => - 'https://api.easee.cloud/api/chargers/#ChargerID#/commands/set_rfid_pairing_mode_async', - changeChargerSettings => - 'https://api.easee.cloud/api/chargers/#ChargerID#/settings', - setChargingPrice => 'https://api.easee.cloud/api/sites/#SiteID#/price', -); -my %EaseeWallbox_reasonsForNoCurrent = ( +## Datapoint, all behind API URI +my %dpoints = ( + getOAuthToken => 'accounts/login', + getRefreshToken => 'accounts/refresh_token', + getProfile => 'accounts/profile', + getChargingSession => 'chargers/#ChargerID#/sessions/ongoing', + getChargers => 'accounts/chargers', + getProducts => 'accounts/products?userId=#UserId#', + getChargerSite => 'chargers/#ChargerID#/site', + getChargerDetails => 'chargers/#ChargerID#/details', + getChargerConfiguration => 'chargers/#ChargerID#/config', + getChargerSessionsMonthly => 'sessions/charger/#ChargerID#/monthly', + getChargerSessionsDaily => 'sessions/charger/#ChargerID#/daily', + getChargerState => 'chargers/#ChargerID#/state', + getCurrentSession => 'chargers/#ChargerID#/sessions/ongoing', + setCableLockState => 'chargers/#ChargerID#/commands/lock_state', + setReboot => 'chargers/#ChargerID#/commands/reboot', + setUpdateFirmware => 'chargers/#ChargerID#/commands/update_firmware', + setEnableSmartCharging => 'chargers/#ChargerID#/commands/smart_charging', + setStartCharging => 'chargers/#ChargerID#/commands/start_charging', + setStopCharging => 'chargers/#ChargerID#/commands/stop_charging', + setPauseCharging => 'chargers/#ChargerID#/commands/pause_charging', + setResumeCharging => 'chargers/#ChargerID#/commands/resume_charging', + setToggleCharging => 'chargers/#ChargerID#/commands/toggle_charging', + setOverrideChargingSchedule => 'chargers/#ChargerID#/commands/override_schedule', + setPairRFIDTag => 'chargers/#ChargerID#/commands/set_rfid_pairing_mode_async', + changeChargerSettings => 'chargers/#ChargerID#/settings', + setChargingPrice => 'sites/#SiteID#/price', +); +my %reasonsForNoCurrent = ( 0 => 'OK', #charger is allocated current 1 => 'MaxCircuitCurrentTooLow', 2 => 'MaxDynamicCircuitCurrentTooLow', @@ -110,13 +181,12 @@ my %EaseeWallbox_reasonsForNoCurrent = ( 56 => 'ChargerInErrorState', 100 => 'Undefined' ); -my %EaseeWallbox_phaseModes = ( +my %phaseModes = ( 1 => 'Locked to single phase', 2 => 'Auto', 3 => 'Locked to three phase', ); - -my %EaseeWallbox_operationModes = ( +my %operationModes = ( 1 => "Standby", 2 => "Paused", 3 => 'Charging', @@ -126,8 +196,10 @@ my %EaseeWallbox_operationModes = ( ); #Private function to evaluate command-lists +# private funktionen beginnen immer mit _ + ############################# -sub EaseeWallbox_getCmdList ($$$) { +sub _GetCmdList { my ( $hash, $cmd, $commands ) = @_; my %cmdArray = %$commands; @@ -163,32 +235,35 @@ sub EaseeWallbox_getCmdList ($$$) { return $retVal; } -sub EaseeWallbox_Initialize($) { +sub Initialize { my ($hash) = @_; - $hash->{DefFn} = 'EaseeWallbox_Define'; - $hash->{UndefFn} = 'EaseeWallbox_Undef'; - $hash->{SetFn} = 'EaseeWallbox_Set'; - $hash->{GetFn} = 'EaseeWallbox_Get'; - $hash->{AttrFn} = 'EaseeWallbox_Attr'; - $hash->{ReadFn} = 'EaseeWallbox_Read'; - $hash->{WriteFn} = 'EaseeWallbox_Write'; - $hash->{Clients} = ':EaseeWallbox:'; - $hash->{MatchList} = { '1:EaseeWallbox' => '^EaseeWallbox;.*' }; - $hash->{AttrList} - = 'expertMode:yes,no ' - . 'ledStuff:yes,no ' - . 'SmartCharging:true,false ' - . $readingFnAttributes; + $hash->{DefFn} = \&Define; + $hash->{UndefFn} = \&Undef; + $hash->{SetFn} = \&Set; + $hash->{GetFn} = \&Get; + $hash->{AttrFn} = \&Attr; + $hash->{ReadFn} = \&Read; + $hash->{WriteFn} = \&Write; - Log 3, "EaseeWallbox module initialized."; + $hash->{AttrList} = + 'expertMode:yes,no ' + . 'ledStuff:yes,no ' + . 'SmartCharging:true,false ' + . $readingFnAttributes; + + #Log3, 'EaseeWallbox', 3, "EaseeWallbox module initialized."; + return; } -sub EaseeWallbox_Define($$) { +sub Define { my ( $hash, $def ) = @_; my @param = split( "[ \t]+", $def ); my $name = $hash->{NAME}; + # set API URI as Internal Key + $hash->{APIURI} = 'https://api.easee.cloud/api/'; + Log3 $name, 3, "EaseeWallbox_Define $name: called "; my $errmsg = ''; @@ -215,7 +290,7 @@ sub EaseeWallbox_Define($$) { #Take password and use custom encryption. # Encryption is taken from fitbit / withings module - my $password = EaseeWallbox_encrypt( $param[3] ); + my $password = _encrypt( $param[3] ); $hash->{Password} = $password; @@ -252,22 +327,22 @@ sub EaseeWallbox_Define($$) { readingsSingleUpdate( $hash, 'state', 'Undefined', 0 ); #Initial load of data - EaseeWallbox_UpdateBaseData($hash); - EaseeWallbox_RefreshData($hash); + #EaseeWallbox_UpdateBaseData($hash); + #EaseeWallbox_RefreshData($hash); Log3 $name, 1, sprintf("EaseeWallbox_Define %s: Starting timer with interval %s", $name, InternalVal($name,'INTERVAL', undef)); - InternalTimer(gettimeofday()+ InternalVal($name,'INTERVAL', undef), "EaseeWallbox_UpdateDueToTimer", $hash) if (defined $hash); + #InternalTimer(gettimeofday()+ InternalVal($name,'INTERVAL', undef), "EaseeWallbox_UpdateDueToTimer", $hash) if (defined $hash); return undef; } -sub EaseeWallbox_Undef($$) { +sub Undef { my ( $hash, $arg ) = @_; RemoveInternalTimer($hash); return undef; } -sub EaseeWallbox_Get($@) { +sub Get { my ( $hash, $name, @args ) = @_; return '"get EaseeWallbox" needs at least one argument' @@ -276,20 +351,20 @@ sub EaseeWallbox_Get($@) { my $opt = shift @args; #create response, if cmd is wrong or gui asks - my $cmdTemp = EaseeWallbox_getCmdList( $hash, $opt, \%EaseeWallbox_gets ); + my $cmdTemp = _GetCmdList( $hash, $opt, \%gets ); return $cmdTemp if ( defined($cmdTemp) ); $hash->{LOCAL} = 1; - EaseeWallbox_GetChargers($hash) if $opt eq "chargers"; - EaseeWallbox_GetChargerConfig($hash) if $opt eq "config"; - EaseeWallbox_GetChargerSite($hash) if $opt eq "sites"; - EaseeWallbox_RefreshData($hash) if $opt eq "update"; - EaseeWallbox_UpdateBaseData($hash) if $opt eq 'baseData'; + WriteToCloudAPI($hash, 'getChargers', 'GET') if $opt eq "chargers"; + WriteToCloudAPI($hash, 'getChargers', 'GET') if $opt eq "config"; + WriteToCloudAPI($hash, 'getChargers', 'GET') if $opt eq "sites"; + WriteToCloudAPI($hash, 'getChargers', 'GET') if $opt eq "update"; + WriteToCloudAPI($hash, 'getChargers', 'GET') if $opt eq 'baseData'; delete $hash->{LOCAL}; - return undef; + return undef; } -sub EaseeWallbox_Set($@) { +sub Set { my ( $hash, $name, @param ) = @_; return '"set $name" needs at least one argument' if ( int(@param) < 1 ); @@ -298,73 +373,219 @@ sub EaseeWallbox_Set($@) { my $value = join( "", @param ); #create response, if cmd is wrong or gui asks - my $cmdTemp = EaseeWallbox_getCmdList( $hash, $opt, \%EaseeWallbox_sets ); + my $cmdTemp = _GetCmdList( $hash, $opt, \%sets ); return $cmdTemp if ( defined($cmdTemp) ); +} - if ( $opt eq "deactivateTimer" ) { - RemoveInternalTimer($hash); - Log3 $name, 1, - "EaseeWallbox_Set $name: Stopped the timer to automatically update readings"; - readingsSingleUpdate( $hash, 'state', 'Initialized', 0 ); +sub Attr { + my ( $cmd, $name, $attrName, $attrVal ) = @_; + return; +} + +sub WriteToCloudAPI { + my $hash = shift; + my $dpoint = shift; + my $method = shift; + my $name = $hash->{NAME}; + my $url = $hash->{APIURI} . $dpoints{$dpoint}; + + ######### + # CHANGE THIS + my $payload = ''; + my $deviceId = "WC1"; + + if ( not defined $hash ) { + my $msg = "Error on EaseeWallbox_WriteToCloudAPI. Missing hash variable"; + Log3 'EaseeWallbox', 1, $msg; + return $msg; + } + + #Check if chargerID is required in URL and replace or alert. + if ( $url =~ m/#ChargerID#/ ) { + my $chargerId = ReadingsVal( $name, 'charger_id', undef ); + if ( not defined $chargerId ) { + my $error = "Error on EaseeWallbox_WriteToCloudAPI. Missing charger_id. Please ensure basic data is available."; + Log3 'EaseeWallbox', 1, $error; + return $error; + } + $url =~ s/#ChargerID#/$chargerId/g; + } + + #Check if siteID is required in URL and replace or alert. + if ( $url =~ m/#SiteID#/ ) { + my $siteId = ReadingsVal( $name, 'site_id', undef ); + if ( not defined $siteId ) { + my $error = "Error on EaseeWallbox_WriteToCloudAPI. Missing site_id. Please ensure basic data is available."; + Log3 'EaseeWallbox', 1, $error; + return $error; + } + $url =~ s/#SiteID#/$siteId/g; + } + + my $CurrentTokenData = _loadToken($hash); + my $header = + { + "Content-Type" => "application/json;charset=UTF-8", + "Authorization" => + "$CurrentTokenData->{'tokenType'} $CurrentTokenData->{'accessToken'}" + }; + + # $method ist GET oder POST + # bei POST ist $payload gleich data + + HttpUtils_NonblockingGet( + { + url => $url, + timeout => 15, + incrementalTimeout => 1, + hash => $hash, + dpoint => $dpoint, + device_id => $deviceId, + data => $payload, + method => $method, + header => $header, + callback => \&ResponseHandling + } + ); + return; +} + +sub ResponseHandling { + my $param = shift; + my $err = shift; + my $data = shift; + my $hash = $param->{hash}; + my $name = $hash->{NAME}; + + Log3 $name, 4, "Callback received." . $param->{url}; + + if ( $err ne "" ) # wenn ein Fehler bei der HTTP Abfrage aufgetreten ist + { + Log3 $name, 3,"error while requesting ". $param->{url}. " - $err"; # Eintrag fürs Log + readingsSingleUpdate( $hash, "lastResponse", "ERROR $err", 1 ); return undef; } - elsif ( $opt eq "activateTimer" ) { - #Update once manually and then start the timer - RemoveInternalTimer($hash); - $hash->{LOCAL} = 1; - EaseeWallbox_RefreshData($hash); - delete $hash->{LOCAL}; - InternalTimer(gettimeofday()+ InternalVal($name,'INTERVAL', undef), "EaseeWallbox_UpdateDueToTimer", $hash); - readingsSingleUpdate($hash,'state','Started',0); - Log3 $name, 1, sprintf("EaseeWallbox_Set %s: Updated readings and started timer to automatically update readings with interval %s", $name, InternalVal($name,'INTERVAL', undef)); + + my $code = $param->{code}; + if ($code >= 400){ + Log3 $name, 3,"HTTPS error while requesting ". $param->{url}. " - $code"; # Eintrag fürs Log + readingsSingleUpdate( $hash, "lastResponse", "ERROR: HTTP Code $code", 1 ); + return undef; } - elsif ( $opt eq "interval" ) { - my $interval = shift @param; - $interval = 60 unless defined($interval); - if ( $interval < 5 ) { $interval = 5; } + Log3 $name, 3, + "Received non-blocking data from EaseeWallbox regarding current session "; - Log3 $name, 1, "EaseeWallbox_Set $name: Set interval to" . $interval; - $hash->{INTERVAL} = $interval; - } else { - $hash->{LOCAL} = 1; - EaseeWallbox_ExecuteParameterlessCommand( $hash, "setStartCharging" ) if $opt eq "startCharging"; - EaseeWallbox_ExecuteParameterlessCommand( $hash, "setStopCharging" ) if $opt eq 'stopCharging'; - EaseeWallbox_ExecuteParameterlessCommand( $hash, "setPauseCharging" ) if $opt eq 'pauseCharging'; - EaseeWallbox_ExecuteParameterlessCommand( $hash, "setResumeCharging" ) if $opt eq 'resumeCharging'; - EaseeWallbox_ExecuteParameterlessCommand( $hash, "setToggleCharging" ) if $opt eq 'toggleCharging'; - EaseeWallbox_ExecuteParameterlessCommand( $hash, "setUpdateFirmware" ) if $opt eq 'updateFirmware'; - EaseeWallbox_ExecuteParameterlessCommand( $hash, "setOverrideChargingSchedule" ) if $opt eq 'overrideChargingSchedule'; - EaseeWallbox_ExecuteParameterlessCommand( $hash, "setPairRFIDTag" ) if $opt eq 'pairRfidTag'; + Log3 $name, 4, "FHEM -> EaseeWallbox: " . $param->{url}; + Log3 $name, 4, "FHEM -> EaseeWallbox: " . $param->{message} + if ( defined $param->{message} ); + Log3 $name, 4, "EaseeWallbox -> FHEM: " . $data; + Log3 $name, 5, '$err: ' . $err; + Log3 $name, 5, "method: " . $param->{method}; + Log3 $name, 2, "Something gone wrong" + if ( $data =~ "/EaseeWallboxMode/" ); + + my $d; + eval { + my $d = decode_json($data); + Log3 $name, 5, 'Decoded: ' . Dumper($d); + if ( defined $d and $d ne '') { - EaseeWallbox_ExecuteParameterlessCommand( $hash, "setReboot" ) if $opt eq 'reboot'; - EaseeWallbox_ExecuteParameterlessCommand( $hash, "toBeDone" ) if $opt eq 'enableSmartCharging'; - EaseeWallbox_SetCableLock( $hash, shift @param ) if $opt eq 'cableLock'; - EaseeWallbox_SetPrice( $hash, shift @param ) if $opt eq 'pricePerKWH'; - EaseeWallbox_LoadToken($hash) if $opt eq 'refreshToken'; - delete $hash->{LOCAL}; - } - readingsSingleUpdate( $hash, 'state', 'Initialized', 0 ); - return undef; + if($param->{dpoint} eq 'getChargers') + { + my $site = $d->[0]; + my $circuit = $site->{circuits}->[0]; + my $charger = $circuit->{chargers}->[0]; + + readingsBeginUpdate($hash); + my $chargerId = $charger->{id}; + readingsBulkUpdate( $hash, "site_id", $site->{id} ); + readingsBulkUpdate( $hash, "charger_id", $chargerId ); + readingsBulkUpdate( $hash, "charger_name", $charger->{name} ); + readingsBulkUpdate( $hash, "lastResponse", 'OK - getReaders', 1); + readingsEndUpdate( $hash, 1 ); + WriteToCloudAPI($hash, 'getChargerConfiguration', 'GET'); + return; + } + + if($param->{dpoint} eq 'getChargerConfiguration') + { + readingsBeginUpdate($hash); + readingsBulkUpdate( $hash, "charger_isEnabled", $d->{isEnabled} ); + readingsBulkUpdate( $hash, "lockCablePermanently", $d->{lockCablePermanently} ); + readingsBulkUpdate($hash, "authorizationRequired", $d->{authorizationRequired}); + readingsBulkUpdate( $hash, "remoteStartRequired", $d->{remoteStartRequired} ); + readingsBulkUpdate( $hash, "smartButtonEnabled", $d->{smartButtonEnabled} ); + readingsBulkUpdate( $hash, "wiFiSSID", $d->{wiFiSSID} ); + readingsBulkUpdate( $hash, "charger_phaseModeId", $d->{phaseMode} ); + readingsBulkUpdate( $hash, "charger_phaseMode",$phaseModes{ $d->{phaseMode} } ); + readingsBulkUpdate($hash, "localAuthorizationRequired",$d->{localAuthorizationRequired}); + readingsBulkUpdate( $hash, "maxChargerCurrent", $d->{maxChargerCurrent} ); + readingsBulkUpdate( $hash, "ledStripBrightness", $d->{ledStripBrightness} ); + #readingsBulkUpdate( $hash, "charger_offlineChargingMode", + # $d->{offlineChargingMode} ); + #readingsBulkUpdate( $hash, "charger_circuitMaxCurrentP1", + # $d->{circuitMaxCurrentP1} ); + #readingsBulkUpdate( $hash, "charger_circuitMaxCurrentP2", + # $d->{circuitMaxCurrentP2} ); + #readingsBulkUpdate( $hash, "charger_circuitMaxCurrentP3", + # $d->{circuitMaxCurrentP3} ); + #readingsBulkUpdate( $hash, "charger_enableIdleCurrent", + # $d->{enableIdleCurrent} ); + #readingsBulkUpdate( + # $hash, + # "charger_limitToSinglePhaseCharging", + # $d->{limitToSinglePhaseCharging} + #); + + #readingsBulkUpdate( $hash, "charger_localNodeType", + # $d->{localNodeType} ); + + #readingsBulkUpdate( $hash, "charger_localRadioChannel", + # $d->{localRadioChannel} ); + #readingsBulkUpdate( $hash, "charger_localShortAddress", + # $d->{localShortAddress} ); + #readingsBulkUpdate( + # $hash, + # "charger_localParentAddrOrNumOfNodes", + # $d->{localParentAddrOrNumOfNodes} + #); + #readingsBulkUpdate( + # $hash, + # "charger_localPreAuthorizeEnabled", + # $d->{localPreAuthorizeEnabled} + #); + #readingsBulkUpdate( + # $hash, + # "charger_allowOfflineTxForUnknownId", + # $d->{allowOfflineTxForUnknownId} + #); + #readingsBulkUpdate( $hash, "chargingSchedule", + # $d->{chargingSchedule} ); + readingsBulkUpdate( $hash, "lastResponse", 'OK - getReaderConfig', 1); + readingsEndUpdate( $hash, 1 ); + + return undef; + } + + readingsSingleUpdate( $hash, "lastResponse", 'OK - Action '. $d->{commandId}, 1 ) if defined $d->{commandId}; + readingsSingleUpdate( $hash, "lastResponse", 'ERROR: '. $d->{title}.' ('.$d->{status}.')', 1 ) if defined $d->{status} and defined $d->{title}; + return undef; + } else { + readingsSingleUpdate( $hash, "lastResponse", 'OK - empty', 1); + return undef; + } + }; + if ($@) { + readingsSingleUpdate( $hash, "lastResponse", 'ERROR while deconding response: '. $@, 1 ); + Log3 $name, 5, 'Failure decoding: ' . $@; + } + + return; } -sub EaseeWallbox_RefreshData($){ - my $hash = shift; - my $name = $hash->{NAME}; - EaseeWallbox_GetChargerSite($hash); - EaseeWallbox_RequestChargerState($hash); - EaseeWallbox_RequestCurrentSession($hash); - readingsSingleUpdate( $hash, "state", sprintf('%s (%.2f)
Current Session: %.2f kWH (%.2f€)', ReadingsVal($name,"operationMode","N/A"), ReadingsVal($name,"power","0"), ReadingsVal($name,"kWhInSession","0"), ReadingsVal($name,"session_chargingCost","0")), 1 ); -} -sub EaseeWallbox_UpdateBaseData($){ - my $hash = shift; - EaseeWallbox_GetChargers($hash); - EaseeWallbox_GetChargerConfig($hash); - EaseeWallbox_RefreshData($hash); -} - -sub EaseeWallbox_LoadToken { +sub _loadToken { my $hash = shift; my $name = $hash->{NAME}; my $tokenLifeTime = $hash->{TOKEN_LIFETIME}; @@ -382,7 +603,7 @@ sub EaseeWallbox_LoadToken { "EaseeWallbox $name" . ": " . "Token is expired, requesting new one" if $tokenLifeTime < gettimeofday(); - $Token = EaseeWallbox_NewTokenRequest($hash); + $Token = _newTokenRequest($hash); } else { Log3 $name, 5, @@ -395,17 +616,17 @@ sub EaseeWallbox_LoadToken { Log3 $name, 5, "EaseeWallbox $name" . ": " . "Token will expire soon, refreshing"; - $Token = EaseeWallbox_TokenRefresh($hash); + $Token = _tokenRefresh($hash); } } return $Token if $Token; } -sub EaseeWallbox_NewTokenRequest { +sub _newTokenRequest { my $hash = shift; my $name = $hash->{NAME}; my $password - = EaseeWallbox_decrypt( InternalVal( $name, 'Password', undef ) ); + = _decrypt( InternalVal( $name, 'Password', undef ) ); my $username = InternalVal( $name, 'Username', undef ); Log3 $name, 5, "EaseeWallbox $name" . ": " . "calling NewTokenRequest()"; @@ -416,7 +637,7 @@ sub EaseeWallbox_NewTokenRequest { }; my $param = { - url => $EaseeWallbox_urls{getOAuthToken}, + url => $hash->{APIURI} . $dpoints{getOAuthToken}, header => { "Content-Type" => "application/json" }, method => 'POST', timeout => 5, @@ -466,7 +687,7 @@ sub EaseeWallbox_NewTokenRequest { return; } -sub EaseeWallbox_TokenRefresh { +sub _tokenRefresh { my $hash = shift; my $name = $hash->{NAME}; @@ -481,7 +702,7 @@ sub EaseeWallbox_TokenRefresh { }; my $param = { - url => $EaseeWallbox_urls{getRefreshToken}, + url => $hash->{APIURI} . $dpoints{getRefreshToken}, header => { "Content-Type" => "application/json" }, method => 'POST', timeout => 5, @@ -537,654 +758,7 @@ sub EaseeWallbox_TokenRefresh { return; } -sub EaseeWallbox_httpSimpleOperationCallback { - my ( $param, $err, $data ) = @_; - my $hash = $param->{hash}; - my $name = $hash->{NAME}; - - Log3 $name, 4, "Callback received." . $param->{url}; - - if ( $err ne "" ) # wenn ein Fehler bei der HTTP Abfrage aufgetreten ist - { - Log3 $name, 3,"error while requesting ". $param->{url}. " - $err"; # Eintrag fürs Log - readingsSingleUpdate( $hash, "lastResponse", "ERROR $err", 1 ); - return undef; - } - - my $code = $param->{code}; - if ($code >= 400){ - Log3 $name, 3,"HTTPS error while requesting ". $param->{url}. " - $code"; # Eintrag fürs Log - readingsSingleUpdate( $hash, "lastResponse", "ERROR: HTTP Code $code", 1 ); - return undef; - } - - Log3 $name, 3, - "Received non-blocking data from EaseeWallbox regarding current session "; - - Log3 $name, 4, "FHEM -> EaseeWallbox: " . $param->{url}; - Log3 $name, 4, "FHEM -> EaseeWallbox: " . $param->{message} - if ( defined $param->{message} ); - Log3 $name, 4, "EaseeWallbox -> FHEM: " . $data; - Log3 $name, 5, '$err: ' . $err; - Log3 $name, 5, "method: " . $param->{method}; - Log3 $name, 2, "Something gone wrong" - if ( $data =~ "/EaseeWallboxMode/" ); - eval { - my $d = decode_json($data) if ( !$err ); - Log3 $name, 5, 'Decoded: ' . Dumper($d); - if ( defined $d and not $d eq '') { - readingsSingleUpdate( $hash, "lastResponse", 'OK - Action '. $d->{commandId}, 1 ) if defined $d->{commandId}; - readingsSingleUpdate( $hash, "lastResponse", 'ERROR: '. $d->{title}.' ('.$d->{status}.')', 1 ) if defined $d->{status} and defined $d->{title}; - return undef; - } else { - readingsSingleUpdate( $hash, "lastResponse", 'OK', 1); - return undef; - } - }; - if ($@) { - readingsSingleUpdate( $hash, "lastResponse", 'ERROR while deconding response: '. $@, 1 ); - Log3 $name, 5, 'Failure decoding: ' . $@; - } -} - -sub EaseeWallbox_httpSimpleOperationOAuth { - my ( $hash, $url, $operation, $message, $callback ) = @_; - my ( $json, $err, $data, $decoded ); - my $name = $hash->{NAME}; - my $CurrentTokenData = EaseeWallbox_LoadToken($hash); - - Log3 $name, 3, - "$CurrentTokenData->{'tokenType'} $CurrentTokenData->{'accessToken'}"; - - my $request = { - url => $url, - header => { - "Content-Type" => "application/json;charset=UTF-8", - "Authorization" => - "$CurrentTokenData->{'tokenType'} $CurrentTokenData->{'accessToken'}" - }, - callback => \&EaseeWallbox_httpSimpleOperationCallback, - method => $operation, - timeout => 6, - hideurl => 1, - }; - - $request->{callback} = $callback if defined $callback; - $request->{data} = $message if ( defined $message ); - - Log3 $name, 5, 'Request: ' . Dumper($request); - $request->{hash} = $hash; - - HttpUtils_NonblockingGet($request); - Log3 $name, 3, - "Async call executed. Waiting for callback..."; -} - -sub EaseeWallbox_ExecuteParameterlessCommand($$) { - my ( $hash, $template ) = @_; - EaseeWallbox_ExecuteCommand($hash, 'POST', $template, undef) -} - -sub EaseeWallbox_ExecuteCommand($@) { - my ( $hash, $method, $template, $message ) = @_; - my $name = $hash->{NAME}; - my $urlTemplate = $EaseeWallbox_urls{$template}; - - if ( not defined $hash ) { - Log3 'EaseeWallbox', 1, - "Error on EaseeWallbox_ExecuteCommand. Missing hash variable"; - return undef; - } - - #Check if chargerID is required in URL and replace or alert. - if ( $urlTemplate =~ m/#ChargerID#/ ) { - my $chargerId = ReadingsVal( $name, 'charger_id', undef ); - if ( not defined $chargerId ) { - Log3 'EaseeWallbox', 1, - "Error on EaseeWallbox_ExecuteCommand. Missing charger_id. Please ensure basic data is available."; - return undef; - } - $urlTemplate =~ s/#ChargerID#/$chargerId/g; - } - - #Check if siteID is required in URL and replace or alert. - if ( $urlTemplate =~ m/#SiteID#/ ) { - my $siteId = ReadingsVal( $name, 'site_id', undef ); - if ( not defined $siteId ) { - Log3 'EaseeWallbox', 1, - "Error on EaseeWallbox_ExecuteCommand. Missing site_id. Please ensure basic data is available."; - return undef; - } - $urlTemplate =~ s/#SiteID#/$siteId/g; - } - - Log3 $name, 4, "EaseeWallbox_ExecuteCommand will call Easee API for blocking value update. Name: $name"; - my $d = EaseeWallbox_httpSimpleOperationOAuth( $hash, $urlTemplate, $method, encode_json \%$message ); -} - -sub EaseeWallbox_SetCableLock($$) { - my ( $hash, $value ) = @_; - my %message; - $message{'state'} = $value; - EaseeWallbox_ExecuteCommand($hash, "POST", "setCableLockState", \%message); -} - -sub EaseeWallbox_SetPrice($$) { - my ( $hash, $value ) = @_; - my %message; - $message{'currencyId'} = "EUR"; - $message{'vat'} = "19"; - $message{'costPerKWh'} = $value; - EaseeWallbox_ExecuteCommand($hash, "POST", "setChargingPrice", \%message); -} - -sub EaseeWallbox_Attr(@) { - return undef; -} - -sub EaseeWallbox_GetChargersCallback(){ - - my ( $param, $err, $data ) = @_; - my $hash = $param->{hash}; - my $name = $hash->{NAME}; - my $d; - - Log3 $name, 4, "Callback received." . $param->{url}; - - if ( $err ne "" ) # wenn ein Fehler bei der HTTP Abfrage aufgetreten ist - { - Log3 $name, 3,"error while requesting ". $param->{url}. " - $err"; # Eintrag fürs Log - readingsSingleUpdate( $hash, "lastResponse", "ERROR $err", 1 ); - return undef; - } - - my $code = $param->{code}; - if ($code >= 400){ - Log3 $name, 3,"HTTPS error while requesting ". $param->{url}. " - $code"; # Eintrag fürs Log - readingsSingleUpdate( $hash, "lastResponse", "ERROR: HTTP Code $code", 1 ); - return undef; - } - - Log3 $name, 3, - "Received non-blocking data from EaseeWallbox regarding current session "; - - Log3 $name, 4, "FHEM -> EaseeWallbox: " . $param->{url}; - Log3 $name, 4, "FHEM -> EaseeWallbox: " . $param->{message} - if ( defined $param->{message} ); - Log3 $name, 4, "EaseeWallbox -> FHEM: " . $data; - Log3 $name, 5, '$err: ' . $err; - Log3 $name, 5, "method: " . $param->{method}; - Log3 $name, 2, "Something gone wrong" - if ( $data =~ "/EaseeWallboxMode/" ); - eval { - $d = decode_json($data) if ( !$err ); - Log3 $name, 5, 'Decoded: ' . Dumper($d); - }; - if ($@) { - readingsSingleUpdate( $hash, "lastResponse", 'ERROR while deconding response: '. $@, 1 ); - Log3 $name, 5, 'Failure decoding: ' . $@; - return undef; - } - - if ( defined $d && ref($d) eq "HASH" && defined $d->{errors} ) { - log 1, Dumper $d; - readingsSingleUpdate( $hash, - "Error: $d->{errors}[0]->{code} / $d->{errors}[0]->{title}", - 'Undefined', 1 ); - return undef; - - } - else { - - readingsBeginUpdate($hash); - - my $site = $d->[0]; - my $circuit = $site->{circuits}->[0]; - my $charger = $circuit->{chargers}->[0]; - - readingsBeginUpdate($hash); - my $chargerId = $charger->{id}; - readingsBulkUpdate( $hash, "charger_id", $chargerId ); - readingsBulkUpdate( $hash, "charger_name", $charger->{name} ); - #readingsBulkUpdate( $hash, "charger_isTemporary", $charger->{isTemporary} ); - #readingsBulkUpdate( $hash, "charger_createdOn", $charger->{createdOn} ); - readingsEndUpdate( $hash, 1 ); - - # $readTemplate = $EaseeWallbox_urls{"getChargerDetails"}; - # $readTemplate =~ s/#ChargerID#/$chargerId/g; - # $d = EaseeWallbox_httpSimpleOperationOAuth( $hash, $readTemplate, - # 'GET' ); - - # if ( defined $d && ref($d) eq "HASH" && defined $d->{errors} ) { - # log 1, Dumper $d; - # readingsSingleUpdate( $hash, - # "Error: $d->{errors}[0]->{code} / $d->{errors}[0]->{title}", - # 'Undefined', 1 ); - # return undef; - # } - # else { - # readingsBeginUpdate($hash); - # readingsBulkUpdate( $hash, "product", $d->{product} ); - # readingsBulkUpdate( $hash, "pincode", $d->{pinCode} ); - # readingsBulkUpdate( $hash, "unitType", $d->{unitType} ); - # readingsEndUpdate( $hash, 1 ); - # } - readingsSingleUpdate( $hash, "lastResponse", 'OK', 1); - return undef; - } -} - -sub EaseeWallbox_GetChargers($) { - - my ($hash) = @_; - my $name = $hash->{NAME}; - - if ( not defined $hash ) { - my $msg = "Error on EaseeWallbox_GetChargers. Missing hash variable"; - Log3 'EaseeWallbox', 1, $msg; - return $msg; - } - - my $readTemplate = $EaseeWallbox_urls{"getChargers"}; - - EaseeWallbox_httpSimpleOperationOAuth( $hash, $readTemplate, 'GET', '', \&EaseeWallbox_GetChargersCallback ); - return undef; - - -} - -sub EaseeWallbox_GetChargerConfig($) { - - my ($hash) = @_; - my $name = $hash->{NAME}; - - my $chargerId = ReadingsVal( $name, "charger_id", undef ); - if ( not defined $chargerId ) { - my $msg - = "Error on EaseeWallbox_GetDevices. Missing Charger ID. Please get Chargers first."; - Log3 'EaseeWallbox', 1, $msg; - return $msg; - } - - my $readTemplate = $EaseeWallbox_urls{"getChargerConfiguration"}; - $readTemplate =~ s/#ChargerID#/$chargerId/g; - my $d = EaseeWallbox_httpSimpleOperationOAuth( $hash, $readTemplate, - 'GET' ); - - if ( defined $d && ref($d) eq "HASH" && defined $d->{errors} ) { - log 1, Dumper $d; - readingsSingleUpdate( $hash, 'state', - "Error: $d->{errors}[0]->{code} / $d->{errors}[0]->{title}", 1 ); - return undef; - - } - else { - - readingsBeginUpdate($hash); - readingsBulkUpdate( $hash, "charger_isEnabled", $d->{isEnabled} ); - readingsBulkUpdate( - $hash, - "lockCablePermanently", - $d->{lockCablePermanently} - ); - readingsBulkUpdate( - $hash, - "authorizationRequired", - $d->{authorizationRequired} - ); - readingsBulkUpdate( $hash, "remoteStartRequired", - $d->{remoteStartRequired} ); - readingsBulkUpdate( $hash, "smartButtonEnabled", - $d->{smartButtonEnabled} ); - readingsBulkUpdate( $hash, "wiFiSSID", $d->{wiFiSSID} ); - #readingsBulkUpdate( $hash, "charger_offlineChargingMode", - # $d->{offlineChargingMode} ); - #readingsBulkUpdate( $hash, "charger_circuitMaxCurrentP1", - # $d->{circuitMaxCurrentP1} ); - #readingsBulkUpdate( $hash, "charger_circuitMaxCurrentP2", - # $d->{circuitMaxCurrentP2} ); - #readingsBulkUpdate( $hash, "charger_circuitMaxCurrentP3", - # $d->{circuitMaxCurrentP3} ); - #readingsBulkUpdate( $hash, "charger_enableIdleCurrent", - # $d->{enableIdleCurrent} ); - #readingsBulkUpdate( - # $hash, - # "charger_limitToSinglePhaseCharging", - # $d->{limitToSinglePhaseCharging} - #); - readingsBulkUpdate( $hash, "charger_phaseModeId", $d->{phaseMode} ); - readingsBulkUpdate( $hash, "charger_phaseMode", - $EaseeWallbox_phaseModes{ $d->{phaseMode} } ); - #readingsBulkUpdate( $hash, "charger_localNodeType", - # $d->{localNodeType} ); - readingsBulkUpdate( - $hash, - "localAuthorizationRequired", - $d->{localAuthorizationRequired} - ); - #readingsBulkUpdate( $hash, "charger_localRadioChannel", - # $d->{localRadioChannel} ); - #readingsBulkUpdate( $hash, "charger_localShortAddress", - # $d->{localShortAddress} ); - #readingsBulkUpdate( - # $hash, - # "charger_localParentAddrOrNumOfNodes", - # $d->{localParentAddrOrNumOfNodes} - #); - #readingsBulkUpdate( - # $hash, - # "charger_localPreAuthorizeEnabled", - # $d->{localPreAuthorizeEnabled} - #); - #readingsBulkUpdate( - # $hash, - # "charger_allowOfflineTxForUnknownId", - # $d->{allowOfflineTxForUnknownId} - #); - readingsBulkUpdate( $hash, "maxChargerCurrent", - $d->{maxChargerCurrent} ); - readingsBulkUpdate( $hash, "ledStripBrightness", - $d->{ledStripBrightness} ); - #readingsBulkUpdate( $hash, "chargingSchedule", - # $d->{chargingSchedule} ); - - readingsEndUpdate( $hash, 1 ); - - return undef; - } - - EaseeWallbox_RequestDeviceUpdate($hash); -} - -sub EaseeWallbox_GetChargerSite($) { - - my ($hash) = @_; - my $name = $hash->{NAME}; - - my $chargerId = ReadingsVal( $name, "charger_id", undef ); - if ( not defined $chargerId ) { - my $msg - = "Error on EaseeWallbox_GetChargerSite. Missing Charger ID. Please get Chargers first."; - Log3 'EaseeWallbox', 1, $msg; - return $msg; - } - - my $readTemplate = $EaseeWallbox_urls{"getChargerSite"}; - $readTemplate =~ s/#ChargerID#/$chargerId/g; - my $d = EaseeWallbox_httpSimpleOperationOAuth( $hash, $readTemplate, - 'GET' ); - - if ( defined $d && ref($d) eq "HASH" && defined $d->{errors} ) { - log 1, Dumper $d; - readingsSingleUpdate( $hash, 'state', - "Error: $d->{errors}[0]->{code} / $d->{errors}[0]->{title}", 1 ); - return undef; - - } - else { - readingsBeginUpdate($hash); - readingsBulkUpdate( $hash, "site_key", $d->{siteKey} ); - readingsBulkUpdate( $hash, "site_id", $d->{id} ); - readingsBulkUpdate( $hash, "cost_perKWh", $d->{costPerKWh} ); - readingsBulkUpdate( $hash, "cost_perKwhExcludeVat", - $d->{costPerKwhExcludeVat} ); - readingsBulkUpdate( $hash, "cost_vat", $d->{vat} ); - readingsBulkUpdate( $hash, "cost_currency", $d->{currencyId} ); - #readingsBulkUpdate( $hash, "site_ratedCurrent", $d->{ratedCurrent} ); - #readingsBulkUpdate( $hash, "site_createdOn", $d->{createdOn} ); - #readingsBulkUpdate( $hash, "site_updatedOn", $d->{updatedOn} ); - readingsEndUpdate( $hash, 1 ); - return undef; - } - - EaseeWallbox_RequestDeviceUpdate($hash); -} - -sub EaseeWallbox_RequestCurrentSessionCallback($) { - - my ( $param, $err, $data ) = @_; - my $hash = $param->{hash}; - my $name = $hash->{NAME}; - - if ( $err ne "" ) # wenn ein Fehler bei der HTTP Abfrage aufgetreten ist - { - Log3 $name, 3, - "error while requesting " - . $param->{url} - . " - $err"; # Eintrag fürs Log - readingsSingleUpdate( $hash, "state", "ERROR", 1 ); - return undef; - } - - Log3 $name, 3, - "Received non-blocking data from EaseeWallbox regarding current session "; - - Log3 $name, 4, "FHEM -> EaseeWallbox: " . $param->{url}; - Log3 $name, 4, "FHEM -> EaseeWallbox: " . $param->{message} - if ( defined $param->{message} ); - Log3 $name, 4, "EaseeWallbox -> FHEM: " . $data; - Log3 $name, 5, '$err: ' . $err; - Log3 $name, 5, "method: " . $param->{method}; - Log3 $name, 2, "Something gone wrong" - if ( $data =~ "/EaseeWallboxMode/" ); - eval { - my $d = decode_json($data) if ( !$err ); - Log3 $name, 5, 'Decoded: ' . Dumper($d); - - readingsBeginUpdate($hash); - readingsBulkUpdate( $hash, "session_energy", $d->{sessionEnergy} ); - readingsBulkUpdate( $hash, "session_start", $d->{sessionStart} ); - readingsBulkUpdate( $hash, "session_end", $d->{sessionEnd} ); - readingsBulkUpdate( - $hash, - "session_chargeDurationInSeconds", - $d->{chargeDurationInSeconds} - ); - readingsBulkUpdate( $hash, "session_firstEnergyTransfer", - $d->{firstEnergyTransferPeriodStart} ); - readingsBulkUpdate( $hash, "session_lastEnergyTransfer", - $d->{lastEnergyTransferPeriodStart} ); - readingsBulkUpdate( $hash, "session_pricePerKWH", - $d->{pricePrKwhIncludingVat} ); - readingsBulkUpdate( $hash, "session_chargingCost", - $d->{costIncludingVat} ); - readingsBulkUpdate( $hash, "session_id", $d->{sessionId} ); - readingsEndUpdate( $hash, 1 ); - - return undef; - } or do { - Log3 $name, 5, 'Failure decoding: ' . $@; - return undef; - } -} - -sub EaseeWallbox_RequestChargerStateCallback($) { - - my ( $param, $err, $data ) = @_; - my $hash = $param->{hash}; - my $name = $hash->{NAME}; - - if ( $err ne "" ) # wenn ein Fehler bei der HTTP Abfrage aufgetreten ist - { - Log3 $name, 3, - "error while requesting " - . $param->{url} - . " - $err"; # Eintrag fürs Log - readingsSingleUpdate( $hash, "state", "ERROR", 1 ); - return undef; - } - - Log3 $name, 3, - "Received non-blocking data from EaseeWallbox regarding current state "; - - Log3 $name, 4, "FHEM -> EaseeWallbox: " . $param->{url}; - Log3 $name, 4, "FHEM -> EaseeWallbox: " . $param->{message} - if ( defined $param->{message} ); - Log3 $name, 4, "EaseeWallbox -> FHEM: " . $data; - Log3 $name, 5, '$err: ' . $err; - Log3 $name, 5, "method: " . $param->{method}; - Log3 $name, 2, "Something gone wrong" - if ( $data =~ "/EaseeWallboxMode/" ); - eval { - my $d = decode_json($data) if ( !$err ); - Log3 $name, 5, 'Decoded: ' . Dumper($d); - - readingsBeginUpdate($hash); - readingsBulkUpdate( $hash, "operationModeCode", - $d->{chargerOpMode} ); - readingsBulkUpdate( $hash, "operationMode", - $EaseeWallbox_operationModes{ $d->{chargerOpMode} } ); - - readingsBulkUpdate( $hash, "power", $d->{totalPower} ); - readingsBulkUpdate( $hash, "kWhInSession", - $d->{sessionEnergy} ); - readingsBulkUpdate( $hash, "phase", $d->{outputPhase} ); - readingsBulkUpdate( $hash, "latestPulse", $d->{latestPulse} ); - readingsBulkUpdate( $hash, "current", $d->{outputCurrent} ); - readingsBulkUpdate( $hash, "dynamicCurrent", - $d->{dynamicChargerCurrent} ); - - readingsBulkUpdate( - $hash, - "reasonCodeForNoCurrent", - $d->{reasonForNoCurrent} - ); - readingsBulkUpdate( $hash, "reasonForNoCurrent", - $EaseeWallbox_reasonsForNoCurrent{ $d->{reasonForNoCurrent} } ); - - readingsBulkUpdate( $hash, "errorCode", $d->{errorCode} ); - readingsBulkUpdate( $hash, "fatalErrorCode", $d->{fatalErrorCode} ); - - readingsBulkUpdate( $hash, "lifetimeEnergy", $d->{lifetimeEnergy} ); - readingsBulkUpdate( $hash, "online", $d->{isOnline} ); - readingsBulkUpdate( $hash, "voltage", $d->{voltage} ); - readingsBulkUpdate( $hash, "wifi_rssi", $d->{wiFiRSSI} ); - readingsBulkUpdate( $hash, "wifi_apEnabled", $d->{wiFiAPEnabled} ); - readingsBulkUpdate( $hash, "cell_rssi", $d->{cellRSSI} ); - readingsEndUpdate( $hash, 1 ); - return undef; - } or do { - Log3 $name, 5, 'Failure decoding: ' . $@; - return undef; - } -} - -sub EaseeWallbox_UpdateDueToTimer($) { - - my ($hash) = @_; - my $name = $hash->{NAME}; - - #local allows call of function without adding new timer. - #must be set before call ($hash->{LOCAL} = 1) and removed after (delete $hash->{LOCAL};) - if ( !$hash->{LOCAL} ) { - RemoveInternalTimer($hash); - - #Log3 "Test", 1, Dumper($hash); - InternalTimer( - gettimeofday() + InternalVal( $name, 'INTERVAL', undef ), - "EaseeWallbox_UpdateDueToTimer", $hash ); - readingsSingleUpdate( $hash, 'state', 'Polling', 0 ); - } - EaseeWallbox_RefreshData($hash); -} - -sub EaseeWallbox_RequestCurrentSession($) { - my ($hash) = @_; - my $name = $hash->{NAME}; - - if ( not defined $hash ) { - Log3 'EaseeWallbox', 1, - "Error on EaseeWallbox_RequestCurrentSession. Missing hash variable"; - return undef; - } - - if ( not defined ReadingsVal( $name, 'charger_id', undef ) ) { - Log3 'EaseeWallbox', 1, - "Error on EaseeWallbox_RequestCurrentSession. Missing charger_id. Please fetch basic data first."; - return undef; - } - my $chargerId = ReadingsVal( $name, "charger_id", undef ); - - $hash->{charger} = $chargerId; - - Log3 $name, 4, - "EaseeWallbox_RequestCurrentSession Called for non-blocking value update. Name: $name"; - - my $readTemplate = $EaseeWallbox_urls{"getCurrentSession"}; - $readTemplate =~ s/#ChargerID#/$chargerId/g; - - my $CurrentTokenData = EaseeWallbox_LoadToken($hash); - my $token - = "$CurrentTokenData->{'tokenType'} $CurrentTokenData->{'accessToken'}"; - Log3 $name, 4, "token beeing used: " . $token; - - my $request = { - url => $readTemplate, - header => { - "Content-Type" => "application/json;charset=UTF-8", - "Authorization" => $token, - }, - method => 'GET', - timeout => 5, - hideurl => 1, - callback => \&EaseeWallbox_RequestCurrentSessionCallback, - hash => $hash - }; - - Log3 $name, 5, 'NonBlocking Request: ' . Dumper($request); - - HttpUtils_NonblockingGet($request); -} - -sub EaseeWallbox_RequestChargerState($) { - my ($hash) = @_; - my $name = $hash->{NAME}; - - if ( not defined $hash ) { - Log3 'EaseeWallbox', 1, - "Error on EaseeWallbox_RequestChargerState. Missing hash variable"; - return undef; - } - - if ( not defined ReadingsVal( $name, 'charger_id', undef ) ) { - Log3 'EaseeWallbox', 1, - "Error on EaseeWallbox_RequestChargerState. Missing charger_id. Please fetch basic data first."; - return undef; - } - my $chargerId = ReadingsVal( $name, "charger_id", undef ); - - $hash->{charger} = $chargerId; - - Log3 $name, 4, - "EaseeWallbox_RequestChargerState Called for non-blocking value update. Name: $name"; - - my $readTemplate = $EaseeWallbox_urls{"getChargerState"}; - $readTemplate =~ s/#ChargerID#/$chargerId/g; - - my $CurrentTokenData = EaseeWallbox_LoadToken($hash); - my $token - = "$CurrentTokenData->{'tokenType'} $CurrentTokenData->{'accessToken'}"; - Log3 $name, 4, "token beeing used: " . $token; - - my $request = { - url => $readTemplate, - header => { - "Content-Type" => "application/json;charset=UTF-8", - "Authorization" => $token, - }, - method => 'GET', - timeout => 5, - hideurl => 1, - callback => \&EaseeWallbox_RequestChargerStateCallback, - hash => $hash - }; - - Log3 $name, 5, 'NonBlocking Request: ' . Dumper($request); - - HttpUtils_NonblockingGet($request); -} - -sub EaseeWallbox_encrypt($) { +sub _encrypt($) { my ($decoded) = @_; my $key = getUniqueId(); my $encoded; @@ -1200,7 +774,7 @@ sub EaseeWallbox_encrypt($) { return 'crypt:' . $encoded; } -sub EaseeWallbox_decrypt($) { +sub _decrypt($) { my ($encoded) = @_; my $key = getUniqueId(); my $decoded; @@ -1220,6 +794,11 @@ sub EaseeWallbox_decrypt($) { 1; + + + + + =pod =begin html