mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-01-31 06:39:11 +00:00
e88c7419ae
git-svn-id: https://svn.fhem.de/fhem/trunk@18728 2b470e98-0d58-463d-a4d8-8e2adae1ed80
1471 lines
80 KiB
Perl
1471 lines
80 KiB
Perl
# $Id: 73_UpsPico.pm 15394 2017-11-05 15:29:05Z Sailor $
|
|
########################################################################################################################
|
|
#
|
|
# 73_UpsPico.pm
|
|
# Creates the possibility to access the UPS PIco Uninterrupteable Power Supply
|
|
#
|
|
# Author : Matthias Deeke
|
|
# e-mail : matthias.deeke(AT)deeke(PUNKT)eu
|
|
# Fhem Forum : https://forum.fhem.de/index.php/topic,77000.0.html
|
|
# Fhem Wiki :
|
|
#
|
|
# 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 <http://www.gnu.org/licenses/>.
|
|
#
|
|
# fhem.cfg: define <devicename> UpsPico <IPv4-address> <UpsOnPiUser> <UpsOnPiPassword>
|
|
#
|
|
# Example 1 - Bare Credentials:
|
|
# define myUpsPico UpsPico 192.168.178.200 User Geheim
|
|
#
|
|
# Example 2 - base64 encoded Credentials: Both, username and password, may be pre-encode with base64 if attribute CredentialsEncrypted is set
|
|
# define myUpsPico UpsPico 192.168.178.200 VXNlcm5hbWU= UGFzc3dvcmQ=
|
|
#
|
|
########################################################################################################################
|
|
|
|
########################################################################################################################
|
|
# List of open Problems:
|
|
#
|
|
# Set - command not yet implemented
|
|
#
|
|
########################################################################################################################
|
|
|
|
package main;
|
|
|
|
use strict;
|
|
use warnings;
|
|
|
|
use Net::OpenSSH;
|
|
use Data::Dumper qw(Dumper);
|
|
use Math::Expression::Evaluator;
|
|
use Digest::MD5 qw(md5 md5_hex md5_base64);
|
|
|
|
use constant false => 0;
|
|
use constant true => 1;
|
|
|
|
sub UpsPico_Attr(@);
|
|
sub UpsPico_Get($@);
|
|
sub UpsPico_Set($@);
|
|
sub UpsPico_Define($$);
|
|
sub UpsPico_Undefine($$);
|
|
sub UpsPico_Initialize($);
|
|
sub UpsPico_GetAllData($@);
|
|
sub UpsPico_DbLog_splitFn($$);
|
|
sub UpsPico_CheckConnection($@);
|
|
|
|
###START###### Initialize module ##############################################################################START####
|
|
sub UpsPico_Initialize($)
|
|
{
|
|
my ($hash) = @_;
|
|
|
|
$hash->{STATE} = "Init";
|
|
$hash->{DefFn} = "UpsPico_Define";
|
|
$hash->{UndefFn} = "UpsPico_Undefine";
|
|
$hash->{SetFn} = "UpsPico_Set";
|
|
$hash->{GetFn} = "UpsPico_Get";
|
|
$hash->{AttrFn} = "UpsPico_Attr";
|
|
$hash->{DbLog_splitFn} = "UpsPico_DbLog_splitFn";
|
|
|
|
$hash->{AttrList} = "do_not_notify:0,1 " .
|
|
"header " .
|
|
"Port " .
|
|
"WriteCritical:0,1 " .
|
|
"disable:1,0 " .
|
|
"loglevel:0,1,2,3,4,5 " .
|
|
"PollingInterval " .
|
|
"CredentialsEncrypted:0,1 " .
|
|
$readingFnAttributes;
|
|
}
|
|
####END####### Initialize module ###############################################################################END#####
|
|
|
|
|
|
###START###### Activate module after module has been used via fhem command "define" ##########################START####
|
|
sub UpsPico_Define($$)
|
|
{
|
|
my ($hash, $def) = @_;
|
|
my @a = split("[ \t][ \t]*", $def);
|
|
my $name = $a[0];
|
|
#$a[1] just contains the "UpsPico" module name and we already know that! :-)
|
|
my $url = $a[2];
|
|
my $RemotePiUser = $a[3];
|
|
my $RemotePiPass = $a[4];
|
|
|
|
$hash->{NAME} = $name;
|
|
$hash->{STATE} = "define";
|
|
|
|
Log3 $name, 4, $name. " : UpsPico_Define - Starting to define module";
|
|
|
|
###START###### Reset fullResponse error message ############################################################START####
|
|
readingsSingleUpdate( $hash, "fullResponse", "Initialising...", 1);
|
|
####END####### Reset fullResponse error message #############################################################END#####
|
|
|
|
### Stop the current timer if one exists errornous
|
|
RemoveInternalTimer($hash);
|
|
Log3 $name, 4, $name. " : UpsPico_Define - InternalTimer has been removed.";
|
|
|
|
###START### Check whether all variables are available #####################################################START####
|
|
if (int(@a) == 5)
|
|
{
|
|
###START### Check whether IPv4 address is valid
|
|
if ($url =~ m/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/)
|
|
{
|
|
Log3 $name, 4, $name. " : UpsPico_Define - IPv4-address is valid : " . $url;
|
|
}
|
|
else
|
|
{
|
|
return $name .": Error - IPv4 address is not valid \n Please use \"define <devicename> UpsPico <IPv4-address> <interval/[s]> <Username> <Password>\" instead";
|
|
}
|
|
####END#### Check whether IPv4 address is valid
|
|
}
|
|
else
|
|
{
|
|
return $name .": UpsPico - Error - Not enough or too much parameter provided." . "\n" . "Gateway IPv4 address, Username and Password must be provided" ."\n". "Please use \"define <devicename> UpsPico <IPv4-address> <Username> <Password>\" instead";
|
|
}
|
|
####END#### Check whether all variables are available ######################################################END#####
|
|
|
|
|
|
###START### Decode Username and Password if base 64 coded #################################################START####
|
|
if (defined($attr{$name}{CredentialsEncrypted}))
|
|
{
|
|
if ($attr{$name}{CredentialsEncrypted} == 1)
|
|
{
|
|
$RemotePiUser = decode_base64($RemotePiUser);
|
|
$RemotePiPass = decode_base64($RemotePiPass);
|
|
}
|
|
}
|
|
####END#### Decode Username and Password if base 64 coded ##################################################END#####
|
|
|
|
|
|
###START###### Provide basic Information for all register #################################################START####
|
|
my %RegisterInfo;
|
|
$RegisterInfo{"mode"} = {RegisterBlockName => "Status", RegisterAddress => 0x00, DataType => "Byte", Writeable => false, Reset => false, Critical => false, Factor => undef, Unit => undef, SelectionList => {0x01 => "RPI_MODE", 0x02 => "BAT_MODE", Default => "ERROR"} };
|
|
$RegisterInfo{"batlevel"} = {RegisterBlockName => "Status", RegisterAddress => 0x08, DataType => "WordBCD", Writeable => false, Reset => false, Critical => false, Factor => 0.01, Unit => "V", SelectionList => undef };
|
|
$RegisterInfo{"rpilevel"} = {RegisterBlockName => "Status", RegisterAddress => 0x0a, DataType => "WordBCD", Writeable => false, Reset => false, Critical => false, Factor => 0.01, Unit => "V", SelectionList => undef };
|
|
$RegisterInfo{"eprlevel"} = {RegisterBlockName => "Status", RegisterAddress => 0x0c, DataType => "WordBCD", Writeable => false, Reset => false, Critical => false, Factor => 0.01, Unit => "V", SelectionList => undef };
|
|
$RegisterInfo{"aEXT0level"} = {RegisterBlockName => "Status", RegisterAddress => 0x14, DataType => "WordBCD", Writeable => false, Reset => false, Critical => false, Factor => 0.01, Unit => "V", SelectionList => undef };
|
|
$RegisterInfo{"aEXT1level"} = {RegisterBlockName => "Status", RegisterAddress => 0x16, DataType => "WordBCD", Writeable => false, Reset => false, Critical => false, Factor => 0.01, Unit => "V", SelectionList => undef };
|
|
$RegisterInfo{"aEXT2level"} = {RegisterBlockName => "Status", RegisterAddress => 0x18, DataType => "WordBCD", Writeable => false, Reset => false, Critical => false, Factor => 0.01, Unit => "V", SelectionList => undef };
|
|
$RegisterInfo{"key"} = {RegisterBlockName => "Status", RegisterAddress => 0x1a, DataType => "Byte", Writeable => true, Reset => true, Critical => false, Factor => undef, Unit => undef, SelectionList => {0x00 => "No Key pressed", 0x01 => "Key A pressed", 0x02 => "Key B pressed", 0x03 => "Key C pressed", Default => "ERROR"} };
|
|
$RegisterInfo{"ntc"} = {RegisterBlockName => "Status", RegisterAddress => 0x1b, DataType => "Byte", Writeable => false, Reset => false, Critical => false, Factor => 1.00, Unit => "°C", SelectionList => undef };
|
|
$RegisterInfo{"TO92"} = {RegisterBlockName => "Status", RegisterAddress => 0x1c, DataType => "Byte", Writeable => false, Reset => false, Critical => false, Factor => 1.00, Unit => "°C", SelectionList => undef };
|
|
$RegisterInfo{"charger"} = {RegisterBlockName => "Status", RegisterAddress => 0x20, DataType => "Byte", Writeable => false, Reset => false, Critical => false, Factor => undef, Unit => undef, SelectionList => {0x00 => "Charger OFF", 0x01 => "Charging Batt", Default => "ERROR"} };
|
|
$RegisterInfo{"pico_is_running"} = {RegisterBlockName => "Status", RegisterAddress => 0x22, DataType => "WordHex", Writeable => false, Reset => false, Critical => false, Factor => 1.00, Unit => "ms", SelectionList => undef };
|
|
$RegisterInfo{"pv"} = {RegisterBlockName => "Status", RegisterAddress => 0x24, DataType => "ASCII", Writeable => false, Reset => false, Critical => false, Factor => undef, Unit => undef, SelectionList => undef };
|
|
$RegisterInfo{"bv"} = {RegisterBlockName => "Status", RegisterAddress => 0x25, DataType => "ASCII", Writeable => false, Reset => false, Critical => false, Factor => undef, Unit => undef, SelectionList => undef };
|
|
$RegisterInfo{"fv"} = {RegisterBlockName => "Status", RegisterAddress => 0x26, DataType => "Byte", Writeable => false, Reset => false, Critical => false, Factor => undef, Unit => undef, SelectionList => undef };
|
|
$RegisterInfo{"RTC_seconds"} = {RegisterBlockName => "RTC", RegisterAddress => 0x00, DataType => "Byte", Writeable => false, Reset => false, Critical => false, Factor => 1.00, Unit => "s", SelectionList => undef };
|
|
$RegisterInfo{"RTC_minutes"} = {RegisterBlockName => "RTC", RegisterAddress => 0x01, DataType => "Byte", Writeable => false, Reset => false, Critical => false, Factor => 1.00, Unit => "min", SelectionList => undef };
|
|
$RegisterInfo{"RTC_hours"} = {RegisterBlockName => "RTC", RegisterAddress => 0x02, DataType => "Byte", Writeable => false, Reset => false, Critical => false, Factor => 1.00, Unit => "h", SelectionList => undef };
|
|
$RegisterInfo{"RTC_wday"} = {RegisterBlockName => "RTC", RegisterAddress => 0x03, DataType => "Byte", Writeable => false, Reset => false, Critical => false, Factor => 1.00, Unit => " ", SelectionList => undef };
|
|
$RegisterInfo{"RTC_mday"} = {RegisterBlockName => "RTC", RegisterAddress => 0x04, DataType => "Byte", Writeable => false, Reset => false, Critical => false, Factor => 1.00, Unit => " ", SelectionList => undef };
|
|
$RegisterInfo{"RTC_month"} = {RegisterBlockName => "RTC", RegisterAddress => 0x05, DataType => "Byte", Writeable => false, Reset => false, Critical => false, Factor => 1.00, Unit => " ", SelectionList => undef };
|
|
$RegisterInfo{"RTC_year"} = {RegisterBlockName => "RTC", RegisterAddress => 0x06, DataType => "Byte", Writeable => false, Reset => false, Critical => false, Factor => 1.00, Unit => " ", SelectionList => undef };
|
|
$RegisterInfo{"pico_state"} = {RegisterBlockName => "Command", RegisterAddress => 0x00, DataType => "Byte", Writeable => true, Reset => false, Critical => true, Factor => undef, Unit => undef, SelectionList => {0x00 => "OK", 0x80 => "OK", 0xcc => "Shutdown", 0xdd => "Factory Reset", 0xee => "CPU Reset", 0xff => "Bootloader", 0xa0 => "DEFAULT", 0xa1 => "NO_RTC", 0xa2 => "ALTERNATE", Default => "ERROR"}};
|
|
$RegisterInfo{"bat_run_time"} = {RegisterBlockName => "Command", RegisterAddress => 0x01, DataType => "Byte", Writeable => true, Reset => false, Critical => false, Factor => 1.00, Unit => "s", SelectionList => {0xff => "BattLive", Default => "Function: 60+RegisterValue*60"} };
|
|
$RegisterInfo{"rs232_rate"} = {RegisterBlockName => "Command", RegisterAddress => 0x02, DataType => "Byte", Writeable => true, Reset => false, Critical => false, Factor => undef, Unit => undef, SelectionList => {0x00 => "Disabled", 0x01 => "4800bps", 0x02 => "9600bps", 0x03 => "19200bps", 0x04 => "34600bps", 0x05 => "57600bps", 0x0f => "115200bps",Default => "ERROR"} };
|
|
$RegisterInfo{"STA_timer"} = {RegisterBlockName => "Command", RegisterAddress => 0x05, DataType => "Byte", Writeable => true, Reset => false, Critical => false, Factor => 1.00, Unit => "s", SelectionList => {0xff => "Disabled", Default => "Function: RegisterValue"} };
|
|
$RegisterInfo{"enable5V"} = {RegisterBlockName => "Command", RegisterAddress => 0x06, DataType => "Byte", Writeable => true, Reset => false, Critical => false, Factor => undef, Unit => undef, SelectionList => {0x00 => "Disabled", 0x01 => "Enabled", Default => "ERROR"} };
|
|
$RegisterInfo{"battype"} = {RegisterBlockName => "Command", RegisterAddress => 0x07, DataType => "Byte", Writeable => true, Reset => false, Critical => false, Factor => undef, Unit => undef, SelectionList => {0x46 => "LiFePO4 - F", 0x51 => "LiFePO4 - Q", 0x53 => "LiPO - S", 0x50 => "LiPO - P", Default => "ERROR"} };
|
|
$RegisterInfo{"setA_D"} = {RegisterBlockName => "Command", RegisterAddress => 0x08, DataType => "Byte", Writeable => true, Reset => false, Critical => true, Factor => undef, Unit => undef, SelectionList => {0x00 => "AEXT1: 05.2V; AEXT2: 05.2V;", 0x01 => "AEXT1: 05.2V; AEXT2: 10.0V;", 0x02 => "AEXT1: 05.2V; AEXT2: 20.0V;", 0x03 => "AEXT1: 05.2V; AEXT2: 30.0V;", 0x10 => "AEXT1: 10.0V; AEXT2: 05.2V;", 0x11 => "AEXT1: 10.0V; AEXT2: 10.0V;", 0x12 => "AEXT1: 10.0V; AEXT2: 20.0V;", 0x13 => "AEXT1: 10.0V; AEXT2: 30.0V;", 0x20 => "AEXT1: 20.0V; AEXT2: 05.2V;", 0x21 => "AEXT1: 20.0V; AEXT2: 10.0V;", 0x22 => "AEXT1: 20.0V; AEXT2: 20.0V;", 0x23 => "AEXT1: 20.0V; AEXT2: 30.0V;", 0x30 => "AEXT1: 30.0V; AEXT2: 05.2V;", 0x31 => "AEXT1: 30.0V; AEXT2: 10.0V;", 0x32 => "AEXT1: 30.0V; AEXT2: 20.0V;", 0x33 => "AEXT1: 30.0V; AEXT2: 30.0V;", Default => "ERROR"} };
|
|
$RegisterInfo{"User_LED_Orange"} = {RegisterBlockName => "Command", RegisterAddress => 0x09, DataType => "Byte", Writeable => true, Reset => false, Critical => false, Factor => undef, Unit => undef, SelectionList => {0x00 => "OFF", 0x01 => "ON", Default => "ERROR"} };
|
|
$RegisterInfo{"User_LED_Green"} = {RegisterBlockName => "Command", RegisterAddress => 0x0a, DataType => "Byte", Writeable => true, Reset => false, Critical => false, Factor => undef, Unit => undef, SelectionList => {0x00 => "OFF", 0x01 => "ON", Default => "ERROR"} };
|
|
$RegisterInfo{"User_LED_Blue"} = {RegisterBlockName => "Command", RegisterAddress => 0x0b, DataType => "Byte", Writeable => true, Reset => false, Critical => false, Factor => undef, Unit => undef, SelectionList => {0x00 => "OFF", 0x01 => "ON", Default => "ERROR"} };
|
|
$RegisterInfo{"brelay"} = {RegisterBlockName => "Command", RegisterAddress => 0x0c, DataType => "Byte", Writeable => true, Reset => false, Critical => false, Factor => undef, Unit => undef, SelectionList => {0x00 => "Reset", 0x01 => "Set", Default => "ERROR"} };
|
|
$RegisterInfo{"bmode"} = {RegisterBlockName => "Command", RegisterAddress => 0x0d, DataType => "Byte", Writeable => true, Reset => false, Critical => false, Factor => undef, Unit => undef, SelectionList => {0x00 => "Disabled", 0x01 => "Enabled", Default => "ERROR"} };
|
|
$RegisterInfo{"bfreq"} = {RegisterBlockName => "Command", RegisterAddress => 0x0e, DataType => "WordBCD", Writeable => true, Reset => false, Critical => false, Factor => 1.00, Unit => "Hz", SelectionList => undef };
|
|
$RegisterInfo{"bdur"} = {RegisterBlockName => "Command", RegisterAddress => 0x10, DataType => "Byte", Writeable => true, Reset => false, Critical => false, Factor => 10, Unit => "ms", SelectionList => undef };
|
|
$RegisterInfo{"fmode"} = {RegisterBlockName => "Command", RegisterAddress => 0x11, DataType => "Byte", Writeable => true, Reset => false, Critical => false, Factor => undef, Unit => undef, SelectionList => {0x00 => "Disabled", 0x01 => "Enabled", 0x02 => "Auto", Default => "ERROR"} };
|
|
$RegisterInfo{"fspeed"} = {RegisterBlockName => "Command", RegisterAddress => 0x12, DataType => "Hex", Writeable => true, Reset => false, Critical => false, Factor => 1.00, Unit => "%", SelectionList => undef };
|
|
$RegisterInfo{"fstat"} = {RegisterBlockName => "Command", RegisterAddress => 0x13, DataType => "Byte", Writeable => true, Reset => false, Critical => false, Factor => undef, Unit => undef, SelectionList => {0x00 => "OFF", 0x01 => "ON", Default => "ERROR"} };
|
|
$RegisterInfo{"fttemp"} = {RegisterBlockName => "Command", RegisterAddress => 0x14, DataType => "Byte", Writeable => true, Reset => false, Critical => false, Factor => 1.00, Unit => "°C", SelectionList => undef };
|
|
$RegisterInfo{"LED_OFF"} = {RegisterBlockName => "Command", RegisterAddress => 0x15, DataType => "Byte", Writeable => true, Reset => false, Critical => false, Factor => undef, Unit => undef, SelectionList => {0x00 => "All LEDs forced OFF", 0x01 => "All LED manual", Default => "ERROR"} };
|
|
$RegisterInfo{"STS_active"} = {RegisterBlockName => "StartTS", RegisterAddress => 0x00, DataType => "Byte", Writeable => true, Reset => false, Critical => false, Factor => undef, Unit => undef, SelectionList => {0x00 => "Inactive", 0xff => "Active", Default => "ERROR"} };
|
|
$RegisterInfo{"STS_minute"} = {RegisterBlockName => "StartTS", RegisterAddress => 0x01, DataType => "Byte", Writeable => true, Reset => false, Critical => false, Factor => 1.00, Unit => "min", SelectionList => undef };
|
|
$RegisterInfo{"STS_hour"} = {RegisterBlockName => "StartTS", RegisterAddress => 0x02, DataType => "Byte", Writeable => true, Reset => false, Critical => false, Factor => 1.00, Unit => "h", SelectionList => undef };
|
|
$RegisterInfo{"STS_mday"} = {RegisterBlockName => "StartTS", RegisterAddress => 0x03, DataType => "Byte", Writeable => true, Reset => false, Critical => false, Factor => 1.00, Unit => "d", SelectionList => undef };
|
|
$RegisterInfo{"STS_month"} = {RegisterBlockName => "StartTS", RegisterAddress => 0x04, DataType => "Byte", Writeable => true, Reset => false, Critical => false, Factor => 1.00, Unit => "m", SelectionList => undef };
|
|
$RegisterInfo{"STS_year"} = {RegisterBlockName => "StartTS", RegisterAddress => 0x05, DataType => "Byte", Writeable => true, Reset => false, Critical => false, Factor => 1.00, Unit => "y", SelectionList => undef };
|
|
$RegisterInfo{"D_repetition"} = {RegisterBlockName => "RunTS", RegisterAddress => 0x00, DataType => "Byte", Writeable => true, Reset => false, Critical => false, Factor => 1.00, Unit => "d", SelectionList => {0xff => "Disabled", Default => "Function: RegisterValue"} };
|
|
$RegisterInfo{"H_repetition"} = {RegisterBlockName => "RunTS", RegisterAddress => 0x01, DataType => "Byte", Writeable => true, Reset => false, Critical => false, Factor => 1.00, Unit => "h", SelectionList => {0xff => "Disabled", Default => "Function: RegisterValue"} };
|
|
$RegisterInfo{"M_repetition"} = {RegisterBlockName => "RunTS", RegisterAddress => 0x02, DataType => "Byte", Writeable => true, Reset => false, Critical => false, Factor => 1.00, Unit => "min", SelectionList => {0xff => "Disabled", Default => "Function: RegisterValue"} };
|
|
$RegisterInfo{"H_duration"} = {RegisterBlockName => "RunTS", RegisterAddress => 0x03, DataType => "Byte", Writeable => true, Reset => false, Critical => false, Factor => 1.00, Unit => "h", SelectionList => {0xff => "Disabled", Default => "Function: RegisterValue"} };
|
|
$RegisterInfo{"M_duration"} = {RegisterBlockName => "RunTS", RegisterAddress => 0x04, DataType => "Byte", Writeable => true, Reset => false, Critical => false, Factor => 1.00, Unit => "min", SelectionList => {0xff => "Disabled", Default => "Function: RegisterValue"} };
|
|
# $RegisterInfo{"??????????"} = {RegisterBlockName => "EventS", RegisterAddress => 0x00, DataType => "Byte", Writeable => true, Reset => false, Critical => false, Factor => undef, Unit => undef, SelectionList => undef };
|
|
# $RegisterInfo{"??????????"} = {RegisterBlockName => "ActionS", RegisterAddress => 0x00, DataType => "Byte", Writeable => true, Reset => false, Critical => false, Factor => undef, Unit => undef, SelectionList => undef };
|
|
####END####### Provide basic Information for all register ##################################################END#####
|
|
|
|
###START###### Provide charging information for batteries #################################################START####
|
|
my %BattChargingInfo;
|
|
$BattChargingInfo{"LiFePO4 - F"} = {Volt0Percent => 2.9, Volt100Percent => 3.6};
|
|
$BattChargingInfo{"LiFePO4 - Q"} = {Volt0Percent => 2.9, Volt100Percent => 3.6};
|
|
$BattChargingInfo{"LiPO - S"} = {Volt0Percent => 3.4, Volt100Percent => 4.3};
|
|
$BattChargingInfo{"LiPO - P"} = {Volt0Percent => 3.4, Volt100Percent => 4.3};
|
|
####END####### Provide charging information for batteries ##################################################END#####
|
|
|
|
###START###### Writing values to global hash ##############################################################START####
|
|
$hash->{NAME} = $name;
|
|
$hash->{URL} = $url;
|
|
$hash->{temp}{FIRSTTIME} = true;
|
|
$hash->{temp}{RemotePiUser} = $RemotePiUser;
|
|
$hash->{temp}{RemotePiPass} = $RemotePiPass;
|
|
%{$hash->{temp}{RegisterInfo}} = %RegisterInfo;
|
|
%{$hash->{temp}{BattChargingInfo}} = %BattChargingInfo;
|
|
####END####### Writing values to global hash ###############################################################END#####
|
|
|
|
###START###### For Debugging purpose only #################################################################START####
|
|
Log3 $name, 4, $name. " : UpsPico_Define Hash : " . $hash;
|
|
Log3 $name, 4, $name. " : UpsPico_Define Def : " . $def;
|
|
Log3 $name, 4, $name. " : UpsPico_Define Array : " . @a;
|
|
Log3 $name, 4, $name. " : UpsPico_Define Name : " . $name;
|
|
Log3 $name, 4, $name. " : UpsPico_Define Address : " . $url;
|
|
Log3 $name, 5, $name. " : UpsPico -----------------------------------------------------------------------------";
|
|
Log3 $name, 5, $name. " : UpsPico - RegisterInfo in fhem-hash : \n" . Dumper \%$hash;
|
|
Log3 $name, 5, $name. " : UpsPico -----------------------------------------------------------------------------";
|
|
####END####### For Debugging purpose only ##################################################################END#####
|
|
|
|
###Initiate the timer for first check of connection towards RasPi with UpsPico but wait 30s
|
|
InternalTimer(gettimeofday()+30, "UpsPico_CheckConnection", $hash, 0);
|
|
|
|
return undef;
|
|
}
|
|
####END####### Activate module after module has been used via fhem command "define" ############################END#####
|
|
|
|
|
|
###START###### To bind unit of value to DbLog entries #########################################################START####
|
|
sub UpsPico_DbLog_splitFn($$)
|
|
{
|
|
my ($event, $name) = @_;
|
|
my $hash = $defs{$name};
|
|
my %RegisterInfo = %{$hash->{temp}{RegisterInfo}};
|
|
my @argument = split("[ \t][ \t]*", $event);
|
|
|
|
#### Delete ":" and everything behind in readings name
|
|
$argument[0] =~ s/:.*//;
|
|
|
|
### Pre-Define variables
|
|
my $reading = $argument[0];
|
|
my $value = $argument[1];
|
|
my $unit = undef;
|
|
|
|
### Log entries for debugging
|
|
Log3 $name, 5, $name. " : UpsPico_DbLog_splitFn - Content of event : " . $event;
|
|
Log3 $name, 5, $name. " : UpsPico_DbLog_splitFn - Content of argument[0] : " . $argument[0];
|
|
Log3 $name, 5, $name. " : UpsPico_DbLog_splitFn - Content of argument[1] : " . $argument[1];
|
|
|
|
|
|
### Split Reading in RegisterI2CBlock and RegisterName
|
|
my @SplitRegisterReading = split(/\//,$argument[0]);
|
|
# $SplitRegisterReading[0] is an empty field
|
|
my $RegisterI2CBlockNameEvent = $SplitRegisterReading[1];
|
|
my $RegisterNameEvent = $SplitRegisterReading[2];
|
|
Log3 $name, 5, $name. " : UpsPico_DbLog_splitFn - Content of RegisterI2CBlockNameEvent : " . $RegisterI2CBlockNameEvent;
|
|
Log3 $name, 5, $name. " : UpsPico_DbLog_splitFn - Content of RegisterNameEvent : " . $RegisterNameEvent;
|
|
|
|
### Set I2CBlockAddressnames
|
|
my %I2CAddress;
|
|
$I2CAddress{Status} = undef;
|
|
$I2CAddress{RTC} = undef;
|
|
$I2CAddress{Command} = undef;
|
|
$I2CAddress{StartTS} = undef;
|
|
$I2CAddress{RunTS} = undef;
|
|
$I2CAddress{EventS} = undef;
|
|
$I2CAddress{ActionS} = undef;
|
|
|
|
### For all specified RegisterI2CBlocks and registers: Search for unit
|
|
SearchLoop:
|
|
{
|
|
foreach my $RegisterI2CBlock (keys %I2CAddress)
|
|
{
|
|
### If the RegisterI2CBlock to be changed is identical to the RegisterI2CBlock in the loop
|
|
if ($RegisterI2CBlockNameEvent eq $RegisterI2CBlock)
|
|
{
|
|
### For all specified Register
|
|
foreach my $RegisterName (keys %RegisterInfo)
|
|
{
|
|
### If the RegisterName to be changed is identical to the RegisterName in the loop
|
|
if ($RegisterNameEvent eq $RegisterName)
|
|
{
|
|
Log3 $name, 5, $name. " : UpsPico_DbLog_splitFn - Found Register for reading : " . $reading;
|
|
|
|
### Extract value and unit
|
|
$unit = $RegisterInfo{$RegisterName}{Unit};
|
|
last SearchLoop;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
### Log entries for debugging
|
|
Log3 $name, 5, $name. " : UpsPico_DbLog_splitFn - Content of reading : " . $reading;
|
|
Log3 $name, 5, $name. " : UpsPico_DbLog_splitFn - Content of value : " . $value;
|
|
Log3 $name, 5, $name. " : UpsPico_DbLog_splitFn - Content of unit : " . $unit;
|
|
|
|
return ($reading, $value, $unit);
|
|
}
|
|
####END####### To bind unit of value to DbLog entries ##########################################################END#####
|
|
|
|
|
|
###START###### Deactivate module module after "undefine" command by fhem ######################################START####
|
|
sub UpsPico_Undefine($$)
|
|
{
|
|
my ($hash, $def) = @_;
|
|
my $name = $hash->{NAME};
|
|
my $url = $hash->{URL};
|
|
|
|
### Stop the internal timer for this module
|
|
RemoveInternalTimer($hash);
|
|
|
|
Log3 $name, 3, $name. " - UpsPico has been undefined. The KM unit at $url will no longer polled.";
|
|
|
|
return undef;
|
|
}
|
|
####END####### Deactivate module module after "undefine" command by fhem #######################################END#####
|
|
|
|
|
|
###START###### Handle attributes after changes via fhem GUI ###################################################START####
|
|
sub UpsPico_Attr(@)
|
|
{
|
|
my @a = @_;
|
|
my $name = $a[1];
|
|
my $hash = $defs{$name};
|
|
|
|
### Check whether disable attribute has been provided
|
|
if ($a[2] eq "disable")
|
|
{
|
|
###START### Check whether device shall be disabled
|
|
if ($a[3] == 1)
|
|
{
|
|
### Set new status
|
|
$hash->{STATE} = "Disabled";
|
|
|
|
### Stop the current timer
|
|
RemoveInternalTimer($hash);
|
|
Log3 $name, 4, $name. " : UpsPico_Attr - InternalTimer has been removed.";
|
|
### Delete all Readings
|
|
fhem( "deletereading $name .*" );
|
|
|
|
Log3 $name, 3, $name. " : UpsPico_Attr - Device disabled as per attribute.";
|
|
}
|
|
else
|
|
{
|
|
### Initiate the timer for first time polling of values from UpsPico but wait 10s
|
|
$hash->{temp}{FIRSTTIME} = true;
|
|
RemoveInternalTimer($hash);
|
|
InternalTimer(gettimeofday()+180, "UpsPico_CheckConnection", $hash, 0);
|
|
Log3 $name, 4, $name. " : UpsPico_Attr - Internal timer for Initialisation of services re-started.";
|
|
Log3 $name, 4, $name. " : UpsPico_Attr - Device enabled as per attribute.";
|
|
}
|
|
####END#### Check whether device shall be disabled
|
|
}
|
|
### Check whether polling interval attribute for all data has been provided
|
|
elsif ($a[2] eq "PollingInterval")
|
|
{
|
|
my $PollingInterval = $a[3];
|
|
###START### Check whether polling interval is not too short
|
|
if ($PollingInterval > 19)
|
|
{
|
|
### Initiate the timer for first time polling of values from UpsPico but wait 10s
|
|
$hash->{temp}{FIRSTTIME} = true;
|
|
RemoveInternalTimer($hash);
|
|
InternalTimer(gettimeofday()+180, "UpsPico_CheckConnection", $hash, 0);
|
|
Log3 $name, 4, $name. " : UpsPico_Attr - Interval for all data set to attribute value :" . $PollingInterval ." s";
|
|
Log3 $name, 4, $name. " : UpsPico_Attr - Internal timer for Initialisation of services re-started.";
|
|
}
|
|
else
|
|
{
|
|
return $name .": Error - Polling interval too small - server response time greater than defined interval, please use something >=20, default is 90";
|
|
}
|
|
####END#### Check whether polling interval is not too short
|
|
}
|
|
### If no attributes of the above mentioned ones have been selected
|
|
else
|
|
{
|
|
# Do nothing
|
|
}
|
|
return undef;
|
|
}
|
|
####END####### Handle attributes after changes via fhem GUI ####################################################END#####
|
|
|
|
|
|
###START###### Obtain value after "get" command by fhem #######################################################START####
|
|
sub UpsPico_Get($@)
|
|
{
|
|
my ( $hash, @a ) = @_;
|
|
|
|
### If not enough arguments have been provided
|
|
if ( @a < 2 )
|
|
{
|
|
return "\"UpsPico_Get\" needs at least one argument";
|
|
}
|
|
|
|
my $name = shift @a;
|
|
my $reading = shift @a;
|
|
my $host = $hash->{URL};
|
|
my $user = $hash->{temp}{RemotePiUser};
|
|
my $pass = $hash->{temp}{RemotePiPass};
|
|
my %RegisterInfo = %{$hash->{temp}{RegisterInfo}};
|
|
|
|
|
|
### Pre-Define variables
|
|
my $ReturnMessage;
|
|
|
|
|
|
### Log entries for debugging
|
|
Log3 $name, 5, $name. " : UpsPico_Get ------------------- Definition ----------------------------------------------";
|
|
Log3 $name, 5, $name. " : UpsPico_Get - name : " . $name;
|
|
Log3 $name, 5, $name. " : UpsPico_Get - reading : " . $reading;
|
|
|
|
|
|
### Prepare list of readings to be selected
|
|
if(!$hash->{READINGS}{$reading})
|
|
{
|
|
my @cList = sort keys %{$hash->{READINGS}};
|
|
return "Unknown argument $reading, choose one of " . join(" ", @cList);
|
|
}
|
|
|
|
|
|
### Split Reading in RegisterI2CBlock and RegisterName
|
|
my @SplitRegisterReading = split(/\//,$reading);
|
|
# $SplitRegisterReading[0] is an empty field
|
|
my $RegisterI2CBlockNameEvent = $SplitRegisterReading[1];
|
|
my $RegisterNameEvent = $SplitRegisterReading[2];
|
|
|
|
|
|
Log3 $name, 5, $name. " : UpsPico_Get - Content of RegisterI2CBlockNameEvent : " . $RegisterI2CBlockNameEvent;
|
|
Log3 $name, 5, $name. " : UpsPico_Get - Content of RegisterNameEvent : " . $RegisterNameEvent;
|
|
|
|
|
|
### Set I2C address block hash
|
|
my %I2CAddress;
|
|
$I2CAddress{Status} = undef;
|
|
$I2CAddress{RTC} = undef;
|
|
$I2CAddress{Command} = undef;
|
|
$I2CAddress{StartTS} = undef;
|
|
$I2CAddress{RunTS} = undef;
|
|
$I2CAddress{EventS} = undef;
|
|
$I2CAddress{ActionS} = undef;
|
|
|
|
|
|
### For all specified RegisterI2CBlocks and registers: Search for unit and register address
|
|
SearchLoop:
|
|
{
|
|
foreach my $RegisterI2CBlock (keys %I2CAddress)
|
|
{
|
|
### If the RegisterI2CBlock to be changed is identical to the RegisterI2CBlock in the loop
|
|
if ($RegisterI2CBlockNameEvent eq $RegisterI2CBlock)
|
|
{
|
|
### For all specified Register
|
|
foreach my $RegisterName (keys %RegisterInfo)
|
|
{
|
|
### If the RegisterName to be changed is identical to the RegisterName in the loop
|
|
if ($RegisterNameEvent eq $RegisterName)
|
|
{
|
|
Log3 $name, 5, $name. " : UpsPico_Get - Found Register for reading : " . $reading;
|
|
|
|
### Call Download
|
|
UpsPico_GetAllData($hash, @a);
|
|
|
|
### Log entries for debugging
|
|
Log3 $name, 5, $name. " : UpsPico_Get ------------------- Final Handover ------------------------------------------";
|
|
Log3 $name, 5, $name. " : UpsPico_Get - reading : " . $reading;
|
|
Log3 $name, 5, $name. " : UpsPico_Get - RegisterName : " . $RegisterName;
|
|
Log3 $name, 5, $name. " : UpsPico_Get - RegisterInfo{RegisterName}{Value} : " . $RegisterInfo{$RegisterName}{Value};
|
|
Log3 $name, 5, $name. " : UpsPico_Get - RegisterInfo{RegisterName}{Unit} : " . $RegisterInfo{$RegisterName}{Unit};
|
|
Log3 $name, 5, $name. " : UpsPico_Get ==============================================================================";
|
|
|
|
### Prepare the message
|
|
$ReturnMessage = $reading . " = " . $RegisterInfo{$RegisterName}{Value} . " " . $RegisterInfo{$RegisterName}{Unit};
|
|
|
|
### Break the loop since the job is done
|
|
last SearchLoop;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
### Return value
|
|
return($ReturnMessage);
|
|
}
|
|
####END####### Obtain value after "get" command by fhem ########################################################END#####
|
|
|
|
|
|
###START###### Manipulate service after "set" command by fhem #################################################START####
|
|
sub UpsPico_Set($@)
|
|
{
|
|
my ( $hash, @a ) = @_;
|
|
|
|
### If not enough arguments have been provided
|
|
if ( @a < 2 )
|
|
{
|
|
return "\"set UpsPico\" needs at least one argument";
|
|
}
|
|
|
|
my $name = shift @a;
|
|
my $register = shift @a;
|
|
my $value = join(" ", @a);
|
|
my %UpsPico_sets;
|
|
my $ReturnMessage;
|
|
|
|
return($ReturnMessage);
|
|
|
|
### DO NOT FORGET TO CHECK ATTRIBUTE "WriteCritical"!!!
|
|
### DO NOT FORGET TO RESET ATTRIBUTE "WriteCritical" after every single reading!!! Use fhem command "save"
|
|
}
|
|
####END####### Manipulate service after "Set" command by fhem ##################################################END#####
|
|
|
|
###START###### Check connection towards remote RasPi via SSH ##################################################START####
|
|
sub UpsPico_CheckConnection($@)
|
|
{
|
|
my ($hash, $def) = @_;
|
|
my $name = $hash->{NAME};
|
|
my $url = $hash->{URL};
|
|
|
|
Log3 $name, 5, $name. " : UpsPico - CheckConnection-------------------------------------------------------------------------------------------------";
|
|
|
|
### Stop the internal timer for this module
|
|
RemoveInternalTimer($hash);
|
|
Log3 $name, 4, $name. " : UpsPico - CheckConnection - Internal Timer has been removed";
|
|
|
|
###START###### Try to access UpsPIco to get I2C address range ##############################################START####
|
|
my $port = $attr{$name}{Port};
|
|
my $stderr = 0;
|
|
my $RemotePiUser = $hash->{temp}{RemotePiUser};
|
|
my $RemotePiPass = $hash->{temp}{RemotePiPass};
|
|
my $stdout;
|
|
my $exit;
|
|
my $cmd;
|
|
my $ssh;
|
|
|
|
###START###### Reset fullResponse error message ############################################################START####
|
|
readingsSingleUpdate( $hash, "fullResponse", "Checking Connection...", 1);
|
|
####END####### Reset fullResponse error message #############################################################END#####
|
|
|
|
eval {$ssh = Net::SSH::Perl->new($url);};
|
|
if( $@ )
|
|
{
|
|
###Set warning for log file
|
|
Log3 $name, 1, $name. " : UpsPico - CheckConnection - SSH Connection to RasPi with UPS-PIco could not be established since network connection failed. Retrying in 300s";
|
|
|
|
### Stop the internal timer for this module and re-initiate the timer for another check of connection towards RasPi with UpsPico but wait 300s
|
|
RemoveInternalTimer($hash);
|
|
$hash->{temp}{FIRSTTIME} = true;
|
|
InternalTimer(gettimeofday()+30, "UpsPico_CheckConnection", $hash, 0);
|
|
Log3 $name, 4, $name. " : UpsPico - CheckConnection - Internal Timer has been removed and restarted to check connection again in 300s";
|
|
|
|
undef $ssh;
|
|
return undef;
|
|
}
|
|
else
|
|
{
|
|
eval {$ssh->login($RemotePiUser, $RemotePiPass);};
|
|
if( $@ )
|
|
{
|
|
###Set warning for log file
|
|
Log3 $name, 1, $name. " : UpsPico - CheckConnection - SSH Login to RasPi with UPS-PIco could not be established due to wrong credentials. Retrying in 300s";
|
|
|
|
### Stop the internal timer for this module and re-initiate the timer for another check of connection towards RasPi with UpsPico but wait 10s
|
|
RemoveInternalTimer($hash);
|
|
$hash->{temp}{FIRSTTIME} = true;
|
|
InternalTimer(gettimeofday()+30, "UpsPico_CheckConnection", $hash, 0);
|
|
Log3 $name, 4, $name. " : UpsPico - CheckConnection - Internal Timer has been removed and restarted to check connection again in 300s";
|
|
|
|
undef $ssh;
|
|
return undef;
|
|
}
|
|
else
|
|
{
|
|
#### Try out with factory default address
|
|
$cmd = "sudo i2cget -y 1 0x69 0x00 b";
|
|
($stdout, $stderr, $exit) = $ssh->cmd($cmd);
|
|
if(defined($stderr)) { Log3 $name, 2, $name. " : UpsPico - CheckConnection - Obtain I2C range with 0x69 - stderr : " . $stderr;}
|
|
if(defined($exit)) { Log3 $name, 5, $name. " : UpsPico - CheckConnection - Obtain I2C range with 0x69 - exit : " . $exit; }
|
|
if(defined($stdout)) { Log3 $name, 5, $name. " : UpsPico - CheckConnection - Obtain I2C range with 0x69 - stdout : " . $stdout;}
|
|
Log3 $name, 5, $name. " : UpsPico - CheckConnection ----------------------------------------------------------";
|
|
|
|
### If connection with status register on I2C address 0x69 was successfully
|
|
if ($stdout ne "")
|
|
{
|
|
|
|
#### Try out whether RTC register are available
|
|
$cmd = "sudo i2cget -y 1 0x6A 0x00 b";
|
|
($stdout, $stderr, $exit) = $ssh->cmd($cmd);
|
|
if(defined($stderr)) { Log3 $name, 2, $name. " : UpsPico - CheckConnection - Obtain I2C range with 0x6A - stderr : " . $stderr;}
|
|
if(defined($exit)) { Log3 $name, 5, $name. " : UpsPico - CheckConnection - Obtain I2C range with 0x6A - exit : " . $exit; }
|
|
if(defined($stdout)) { Log3 $name, 5, $name. " : UpsPico - CheckConnection - Obtain I2C range with 0x6A - stdout : " . $stdout;}
|
|
Log3 $name, 5, $name. " : UpsPico - CheckConnection ----------------------------------------------------------";
|
|
|
|
### If connection with RTC register on I2C address 0x6A was successfully
|
|
if ($stdout ne "")
|
|
{
|
|
### Set I2CRegisterRange to "NORMAL"
|
|
$hash->{I2cRegisterRange} = "NORMAL";
|
|
}
|
|
else
|
|
{
|
|
### Set I2CRegisterRange to "NO_RTC"
|
|
$hash->{I2cRegisterRange} = "NO_RTC";
|
|
}
|
|
|
|
###Initiate the timer for first time polling of values from UpsPico but wait 10s
|
|
RemoveInternalTimer($hash);
|
|
$hash->{temp}{FIRSTTIME} = true;
|
|
InternalTimer(gettimeofday()+10, "UpsPico_GetAllData", $hash, 0);
|
|
Log3 $name, 3, $name. " : UpsPico - CheckConnection - I2C range has been set to : " . $hash->{I2cRegisterRange};
|
|
Log3 $name, 4, $name. " : UpsPico - CheckConnection - Internal timer for Initialisation of services started for the first time.";
|
|
|
|
###Set fullResponse error message
|
|
readingsSingleUpdate( $hash, "fullResponse", "OK", 1);
|
|
}
|
|
### If connection was not successfully
|
|
else
|
|
{
|
|
#### Try out with alternate address
|
|
$cmd = "sudo i2cget -y 1 0x59 0x00 b";
|
|
($stdout, $stderr, $exit) = $ssh->cmd($cmd);
|
|
if(defined($stderr)) { Log3 $name, 2, $name. " : UpsPico - CheckConnection - Obtain I2C range with 0x5A - stderr : " . $stderr;}
|
|
if(defined($exit)) { Log3 $name, 5, $name. " : UpsPico - CheckConnection - Obtain I2C range with 0x5A - exit : " . $exit; }
|
|
if(defined($stdout)) { Log3 $name, 5, $name. " : UpsPico - CheckConnection - Obtain I2C range with 0x5A - stdout : " . $stdout;}
|
|
Log3 $name, 5, $name. " : UpsPico - CheckConnection ----------------------------------------------------------";
|
|
|
|
### If connection with status register on I2C address 0x59 was successfully
|
|
if ($stdout ne "")
|
|
{
|
|
$hash->{I2cRegisterRange} = "ALTERNATE";
|
|
|
|
###Initiate the timer for first time polling of values from UpsPico but wait 10s
|
|
RemoveInternalTimer($hash);
|
|
$hash->{temp}{FIRSTTIME} = true;
|
|
InternalTimer(gettimeofday()+10, "UpsPico_GetAllData", $hash, 0);
|
|
Log3 $name, 3, $name. " : UpsPico - CheckConnection - I2C range has been set to : " . $hash->{I2cRegisterRange};
|
|
Log3 $name, 4, $name. " : UpsPico - CheckConnection - Internal timer for Initialisation of services started for the first time.";
|
|
|
|
###Set fullResponse error message
|
|
readingsSingleUpdate( $hash, "fullResponse", "OK", 1);
|
|
}
|
|
### Otherwise there is no UpsPIco connection available
|
|
else
|
|
{
|
|
Log3 $name, 2, $name. " : UpsPico - CheckConnection - Connection to UPS-PIco could not be established. Terminating Initialisation!";
|
|
###Set fullResponse error message
|
|
readingsSingleUpdate( $hash, "fullResponse", "Error I2C-connection failed. Check connection and re-define device.", 1);
|
|
|
|
### Stop the internal timer for this module and re-initiate the timer for another check of connection towards RasPi with UpsPico but wait 10s
|
|
RemoveInternalTimer($hash);
|
|
$hash->{temp}{FIRSTTIME} = true;
|
|
InternalTimer(gettimeofday()+10, "UpsPico_CheckConnection", $hash, 0);
|
|
Log3 $name, 4, $name. " : UpsPico - CheckConnection - Internal Timer has been removed and restarted to check connection again in 10s";
|
|
return undef;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Log3 $name, 5, $name. " : UpsPico ----------------------------------------------------------------------------------------------------------------";
|
|
return undef;
|
|
}
|
|
####END####### Check connection towards remote RasPi via SSH ###################################################END#####
|
|
|
|
###START###### Download all register ##########################################################################START####
|
|
sub UpsPico_GetAllData($@)
|
|
{
|
|
my ($hash, $def) = @_;
|
|
my $host = $hash->{URL};
|
|
my $name = $hash->{NAME} ;
|
|
my $user = $hash->{temp}{RemotePiUser};
|
|
my $pass = $hash->{temp}{RemotePiPass};
|
|
my $PollingInterval = $attr{$name}{PollingInterval};
|
|
my %RegisterInfo = %{$hash->{temp}{RegisterInfo}};
|
|
my %BattChargingInfo = %{$hash->{temp}{BattChargingInfo}};
|
|
my $port = $attr{$name}{Port};
|
|
my $ssh;
|
|
my $ReturnMessage;
|
|
|
|
### Stop the current timer
|
|
RemoveInternalTimer($hash);
|
|
|
|
###START###### Reset fullResponse error message ############################################################START####
|
|
readingsSingleUpdate( $hash, "fullResponse", "Downloading...", 1);
|
|
####END####### Reset fullResponse error message #############################################################END#####
|
|
|
|
|
|
###START###### Set I2C address accordingly ###############################################################START####
|
|
my %I2CAddress;
|
|
|
|
if ($hash->{I2cRegisterRange} eq "NORMAL")
|
|
{
|
|
Log3 $name, 4, $name. " : UpsPico_GetAllData - I2CRegisterRange has been set to NORMAL";
|
|
$I2CAddress{Status} = 0x69;
|
|
$I2CAddress{RTC} = 0x6a;
|
|
$I2CAddress{Command} = 0x6b;
|
|
$I2CAddress{StartTS} = 0x6c;
|
|
$I2CAddress{RunTS} = 0x6d;
|
|
$I2CAddress{EventS} = 0x6e;
|
|
$I2CAddress{ActionS} = 0x6f;
|
|
}
|
|
elsif ($hash->{I2cRegisterRange} eq "NO_RTC")
|
|
{
|
|
Log3 $name, 4, $name. " : UpsPico_GetAllData - I2CRegisterRange has been set to NO_RTC";
|
|
$I2CAddress{Status} = 0x69;
|
|
$I2CAddress{RTC} = undef;
|
|
$I2CAddress{Command} = 0x6b;
|
|
$I2CAddress{StartTS} = undef;
|
|
$I2CAddress{RunTS} = undef;
|
|
$I2CAddress{EventS} = undef;
|
|
$I2CAddress{ActionS} = undef;
|
|
}
|
|
elsif ($hash->{I2cRegisterRange} eq "ALTERNATE")
|
|
{
|
|
Log3 $name, 4, $name. " : UpsPico_GetAllData - I2CRegisterRange has been set to ALTERNATE";
|
|
$I2CAddress{Status} = 0x59;
|
|
$I2CAddress{RTC} = 0x5a;
|
|
$I2CAddress{Command} = 0x5b;
|
|
$I2CAddress{StartTS} = 0x5c;
|
|
$I2CAddress{RunTS} = 0x5d;
|
|
$I2CAddress{EventS} = 0x5e;
|
|
$I2CAddress{ActionS} = 0x5f;
|
|
}
|
|
####END####### Set I2C address accordingly #################################################################END#####
|
|
|
|
###START###### Check whether all required attributes exists otherwise create them with standard values ###BEGIN####
|
|
if(!defined($attr{$name}{Port}))
|
|
{
|
|
### Set attribute with standard value since it is not available
|
|
$attr{$name}{Port} = 22;
|
|
|
|
### Writing log entry
|
|
Log3 $name, 3, $name. " : UpsPico - The attribute SSH-Port was missing and has been set to " . $attr{$name}{Port};
|
|
}
|
|
if(!defined($attr{$name}{PollingInterval}))
|
|
{
|
|
### Set attribute with standard value since it is not available
|
|
$attr{$name}{PollingInterval} = 300;
|
|
|
|
### Writing log entry
|
|
Log3 $name, 3, $name. " : UpsPico - The attribute PollingInterval was missing and has been set to " . $attr{$name}{PollingInterval};
|
|
}
|
|
if(!defined($attr{$name}{room}))
|
|
{
|
|
### Set attribute with standard value since it is not available
|
|
$attr{$name}{room} = "UpsPIco";
|
|
|
|
### Writing log entry
|
|
Log3 $name, 3, $name. " : UpsPico - The attribute for room was missing and has been set to " . $attr{$name}{room};
|
|
}
|
|
if(!defined($attr{$name}{WriteCritical}))
|
|
{
|
|
### Set attribute with standard value since it is not available
|
|
$attr{$name}{WriteCritical} = 0;
|
|
|
|
### Writing log entry
|
|
Log3 $name, 3, $name. " : UpsPico - The attribute for allowing to write critical register was missing and has been set to " . $attr{$name}{WriteCritical};
|
|
}
|
|
if(!defined($attr{$name}{CredentialsEncrypted}))
|
|
{
|
|
### Set attribute with standard value since it is not available
|
|
$attr{$name}{CredentialsEncrypted} = 0;
|
|
|
|
### Writing log entry
|
|
Log3 $name, 3, $name. " : UpsPico - The attribute for the Credentials being encrypted has been set to " . $attr{$name}{CredentialsEncrypted};
|
|
}
|
|
if(!defined($attr{$name}{DbLogExclude}))
|
|
{
|
|
### Set attribute with standard value since it is not available
|
|
$attr{$name}{DbLogExclude} = "/Status/pico_is_running";
|
|
|
|
### Writing log entry
|
|
Log3 $name, 3, $name. " : UpsPico - The attribute for excluding the logging of the pico_is_running - status has been set.";
|
|
}
|
|
if(!defined($attr{$name}{"event-on-change-reading"}))
|
|
{
|
|
### Set attribute with standard value since it is not available
|
|
$attr{$name}{"event-on-change-reading"} = ".*";
|
|
|
|
### Writing log entry
|
|
Log3 $name, 3, $name. " : UpsPico - The attribute for logging only on changed values has been set to all readings.";
|
|
}
|
|
####END####### Check whether all required attributes exists otherwise create them with standard values ####END#####
|
|
|
|
###START###### Check connection ###########################################################################START####
|
|
|
|
### Check whether the network connection still exists
|
|
eval {$ssh = Net::SSH::Perl->new($host);};
|
|
if( $@ )
|
|
{
|
|
###Set warning for log file
|
|
Log3 $name, 1, $name. " : UpsPico_GetAllData - SSH Connection to RasPi with UPS-PIco could not be established. Terminating Initialisation!";
|
|
|
|
###Set fullResponse error message
|
|
readingsSingleUpdate( $hash, "fullResponse", "Error: SSH-connection failed", 1);
|
|
|
|
### Stop the internal timer for this module and re-initiate the timer for another check of connection towards RasPi with UpsPico but wait 10s
|
|
RemoveInternalTimer($hash);
|
|
$hash->{temp}{FIRSTTIME} = true;
|
|
InternalTimer(gettimeofday()+10, "UpsPico_CheckConnection", $hash, 0);
|
|
Log3 $name, 4, $name. " : UpsPico_GetAllData - Error SSH-connection failed.";
|
|
|
|
undef $ssh;
|
|
return undef;
|
|
}
|
|
|
|
### Check whether the credentials are still valid
|
|
eval {$ssh->login($user, $pass);};
|
|
if( $@ )
|
|
{
|
|
###Set warning for log file
|
|
Log3 $name, 1, $name. " : UpsPico_GetAllData - SSH Login to RasPi with UPS-PIco could not be established. Terminating Initialisation!";
|
|
|
|
###Set fullResponse error message
|
|
readingsSingleUpdate( $hash, "fullResponse", "Error SSH-Login failed - Check Credentials", 1);
|
|
|
|
### Stop the internal timer for this module and re-initiate the timer for another check of connection towards RasPi with UpsPico but wait 10s
|
|
RemoveInternalTimer($hash);
|
|
$hash->{temp}{FIRSTTIME} = true;
|
|
InternalTimer(gettimeofday()+10, "UpsPico_CheckConnection", $hash, 0);
|
|
Log3 $name, 1, $name. " : UpsPico_GetAllData - Error SSH-Login failed - Check Credentials";
|
|
|
|
undef $ssh;
|
|
return undef;
|
|
}
|
|
####END####### Check connection ############################################################################END#####
|
|
|
|
###START###### Download register block from UPS PIco via ssh command ######################################START####
|
|
foreach my $RegisterI2CBlock (keys %I2CAddress)
|
|
{
|
|
###START##### Download Register #######################################################################START####
|
|
if (defined($I2CAddress{$RegisterI2CBlock}))
|
|
{
|
|
Log3 $name, 4, $name. " : UpsPico_GetAllData - working on Registerblock: " . $RegisterI2CBlock;
|
|
|
|
my @RegisterBlock;
|
|
my $stdout;
|
|
my $stderr = 0;
|
|
my $exit;
|
|
my $SshCmd = "sudo i2cdump -y -r 0-255 1 " . int($I2CAddress{$RegisterI2CBlock}) . " b";
|
|
($stdout, $stderr, $exit) = $ssh->cmd($SshCmd);
|
|
|
|
### For debugging purposes only
|
|
if(defined($stderr)) { Log3 $name, 2, $name. " : UpsPico_GetAllData - stderr " . $RegisterI2CBlock . " : " . $stderr; }
|
|
if(defined($exit)) { Log3 $name, 5, $name. " : UpsPico_GetAllData - exit " . $RegisterI2CBlock . " : " . $exit; }
|
|
if(defined($stdout)) { Log3 $name, 5, $name. " : UpsPico_GetAllData - stdout " . $RegisterI2CBlock . " : \n" . $stdout; }
|
|
Log3 $name, 5, $name. " : UpsPico_GetAllData ------------------------------------------------------------------------------------";
|
|
|
|
my @BlockRegister = split(/ /, $stdout);
|
|
Log3 $name, 5, $name. " : UpsPico_GetAllData - BlockRegister" . $RegisterI2CBlock . " : \n" . Dumper \@BlockRegister;
|
|
Log3 $name, 5, $name. " : UpsPico_GetAllData ------------------------------------------------------------------------------------";
|
|
|
|
my $LineNumber;
|
|
for ($LineNumber = 19; $LineNumber < 530; $LineNumber = $LineNumber + 2)
|
|
{
|
|
my @TempRegister = split(/ /, $BlockRegister[$LineNumber]);
|
|
splice(@TempRegister, 0, 1);
|
|
push(@RegisterBlock,@TempRegister);
|
|
}
|
|
Log3 $name, 4, $name. " : UpsPico_GetAllData - RegisterBlock " . $RegisterI2CBlock . " successfully downloaded";
|
|
Log3 $name, 5, $name. " : UpsPico_GetAllData - RegisterBlock " . $RegisterI2CBlock . " : \n" . Dumper \@RegisterBlock;
|
|
Log3 $name, 5, $name. " : UpsPico_GetAllData ------------------------------------------------------------------------------------";
|
|
|
|
foreach my $RegisterName (keys %RegisterInfo)
|
|
{
|
|
### If the Register-Information belongs to the current Register
|
|
if ($RegisterInfo{$RegisterName}{RegisterBlockName} eq $RegisterI2CBlock)
|
|
{
|
|
if ($RegisterInfo{$RegisterName}{DataType} eq "Byte")
|
|
{
|
|
### Mark SelectionList Item as not yet found
|
|
my $FoundSelectionListItem = false;
|
|
|
|
### If SelectionList exists for this Register
|
|
if ($RegisterInfo{$RegisterName}{SelectionList} ne undef)
|
|
{
|
|
### Extract Selectionlist from hash
|
|
my %SelectionList = %{$RegisterInfo{$RegisterName}{SelectionList}};
|
|
|
|
### For debugging purposes only
|
|
Log3 $name, 5, $name. " : UpsPico_GetAllData -----------------Finding the Selection List entries for " . $RegisterName . "--------------------------------------------------------";
|
|
Log3 $name, 5, $name. " : UpsPico_GetAllData - Register to be searched in SeletionListEntry : " . ($RegisterBlock[$RegisterInfo{$RegisterName}{RegisterAddress}]);
|
|
Log3 $name, 5, $name. " : UpsPico_GetAllData - Register to be searched in SeletionListEntry hex : " . hex($RegisterBlock[$RegisterInfo{$RegisterName}{RegisterAddress}]);
|
|
|
|
### Search for the correct alias in the SelectionList
|
|
foreach my $SeletionListEntry (keys %SelectionList)
|
|
{
|
|
Log3 $name, 5, $name. " : UpsPico_GetAllData - SeletionListEntry : " . ($SeletionListEntry);
|
|
|
|
### If the RegisterValue matches with the Key of the Selectionlist
|
|
if ((($SeletionListEntry) eq hex($RegisterBlock[$RegisterInfo{$RegisterName}{RegisterAddress}])) && ($SeletionListEntry ne "Default"))
|
|
{
|
|
Log3 $name, 5, $name. " : UpsPico_GetAllData - Found matching SeletionListEntry for : " . $SeletionListEntry . ". The value is: " . $SelectionList{$SeletionListEntry};
|
|
|
|
### Save the alias as value into the Register - hash
|
|
$RegisterInfo{$RegisterName}{Value} = $SelectionList{$SeletionListEntry};
|
|
Log3 $name, 4, $name. " : UpsPico_GetAllData - SelectionList Alias from " . $RegisterI2CBlock . " Register stored in Register-Hash for " . $RegisterName;
|
|
|
|
### Mark SelectionList Item as bein already found
|
|
$FoundSelectionListItem = true;
|
|
}
|
|
### If there is no match
|
|
else
|
|
{
|
|
Log3 $name, 5, $name. " : UpsPico_GetAllData - Found NO matching SeletionListEntry for : " . $SeletionListEntry;
|
|
|
|
### Only set default value if the SelectionList item has not been found yet
|
|
if ($FoundSelectionListItem == false)
|
|
{
|
|
### Save the default value as value into the Register - hash
|
|
$RegisterInfo{$RegisterName}{Value} = $SelectionList{Default};
|
|
Log3 $name, 4, $name. " : UpsPico_GetAllData - SelectionList Default from " . $RegisterI2CBlock . " Register stored in Register-Hash for " . $RegisterName;
|
|
}
|
|
}
|
|
}
|
|
Log3 $name, 4, $name. " : UpsPico_GetAllData - Byte Value with SelectionList formation from " . $RegisterI2CBlock . " Register stored in Register-Hash for " . $RegisterName;
|
|
|
|
### If the SelectionList Vaulue is a mathematical function which needs to be calculated
|
|
if (index($RegisterInfo{$RegisterName}{Value}, "Function: ") != -1)
|
|
{
|
|
### Transform RegisterValue from hex into integer
|
|
my $RegisterValue = hex($RegisterBlock[$RegisterInfo{$RegisterName}{RegisterAddress}]);
|
|
|
|
### Extract formula from SelectionList
|
|
my $MathExpression = $RegisterInfo{$RegisterName}{Value};
|
|
|
|
### Remove the keyword "Function " from the function string
|
|
$MathExpression =~ s/Function: //;
|
|
|
|
### Create Parsing object for mathematical expression
|
|
my $MathParsingObject = Math::Expression::Evaluator->new;
|
|
|
|
### Perform parsing and do calculation
|
|
my $TempCalcResult = $MathParsingObject->parse("RegisterValue = " . $RegisterValue . "; " . $MathExpression)->val();
|
|
|
|
### Save the default value as value into the Register - hash
|
|
$RegisterInfo{$RegisterName}{Value} = $TempCalcResult;
|
|
|
|
### For debugging purposes only
|
|
Log3 $name, 5, $name. " : UpsPico_GetAllData - A mathematical formula has been found in the selection list.";
|
|
Log3 $name, 5, $name. " : UpsPico_GetAllData - RegisterValue : " . $RegisterValue;
|
|
Log3 $name, 5, $name. " : UpsPico_GetAllData - Expression of formula in SeletctionList : " . $MathExpression;
|
|
Log3 $name, 5, $name. " : UpsPico_GetAllData - Result of formula in TempCalcResult : " . $TempCalcResult;
|
|
}
|
|
}
|
|
### If SelectionList does not exists for this Register
|
|
else
|
|
{
|
|
### If the Byte Value is bound to a unit and shown as hex corresponds to BCD
|
|
if ($RegisterInfo{$RegisterName}{Unit} ne undef)
|
|
{
|
|
### Just write Register-Value into Hash
|
|
$RegisterInfo{$RegisterName}{Value} = $RegisterBlock[$RegisterInfo{$RegisterName}{RegisterAddress}];
|
|
Log3 $name, 4, $name. " : UpsPico_GetAllData - Byte Value as BCD from " . $RegisterI2CBlock . " Register stored in Register-Hash for " . $RegisterName;
|
|
}
|
|
### If the Byte Value is not bound to a unit so do not transform it
|
|
else
|
|
{
|
|
### Just write Register-Value into Hash
|
|
$RegisterInfo{$RegisterName}{Value} = "0x" . sprintf("%02d", $RegisterBlock[$RegisterInfo{$RegisterName}{RegisterAddress}]);
|
|
Log3 $name, 4, $name. " : UpsPico_GetAllData - Byte Value as hex from " . $RegisterI2CBlock . " Register stored in Register-Hash for " . $RegisterName;
|
|
}
|
|
}
|
|
}
|
|
elsif ($RegisterInfo{$RegisterName}{DataType} eq "WordBCD")
|
|
{
|
|
$RegisterInfo{$RegisterName}{Value} = int($RegisterBlock[$RegisterInfo{$RegisterName}{RegisterAddress} + 1] . $RegisterBlock[$RegisterInfo{$RegisterName}{RegisterAddress}]) * $RegisterInfo{$RegisterName}{Factor};
|
|
|
|
Log3 $name, 4, $name. " : UpsPico_GetAllData - Word Value from " . $RegisterI2CBlock . " Register stored in Register-Hash for " . $RegisterName;
|
|
|
|
Log3 $name, 5, $name. " : UpsPico_GetAllData - Word Value - RegisterBlock[RegisterInfo{RegisterName}{RegisterAddress} + 0 : " . $RegisterBlock[$RegisterInfo{$RegisterName}{RegisterAddress} ] ;
|
|
Log3 $name, 5, $name. " : UpsPico_GetAllData - Word Value - RegisterBlock[RegisterInfo{RegisterName}{RegisterAddress} + 1 : " . $RegisterBlock[$RegisterInfo{$RegisterName}{RegisterAddress} + 1] ;
|
|
Log3 $name, 5, $name. " : UpsPico_GetAllData - Word Value - RegisterBlock[RegisterInfo{RegisterName}{RegisterAddress} + 1 & +0 : " . $RegisterBlock[$RegisterInfo{$RegisterName}{RegisterAddress} + 1] . $RegisterBlock[$RegisterInfo{$RegisterName}{RegisterAddress}];
|
|
Log3 $name, 5, $name. " : UpsPico_GetAllData - Word Value - RegisterInfo{RegisterName}{Factor} : " . $RegisterInfo{$RegisterName}{Factor};
|
|
Log3 $name, 5, $name. " : UpsPico_GetAllData - Word Value - RegisterInfo{RegisterName}{Value} : " . $RegisterInfo{$RegisterName}{Value};
|
|
}
|
|
elsif ($RegisterInfo{$RegisterName}{DataType} eq "WordHex")
|
|
{
|
|
$RegisterInfo{$RegisterName}{Value} = hex($RegisterBlock[$RegisterInfo{$RegisterName}{RegisterAddress} + 1] . $RegisterBlock[$RegisterInfo{$RegisterName}{RegisterAddress}]) * $RegisterInfo{$RegisterName}{Factor};
|
|
|
|
Log3 $name, 4, $name. " : UpsPico_GetAllData - Word Value from " . $RegisterI2CBlock . " Register stored in Register-Hash for " . $RegisterName;
|
|
|
|
Log3 $name, 5, $name. " : UpsPico_GetAllData - Word Value - RegisterBlock[RegisterInfo{RegisterName}{RegisterAddress} + 0 : " . $RegisterBlock[$RegisterInfo{$RegisterName}{RegisterAddress} ] ;
|
|
Log3 $name, 5, $name. " : UpsPico_GetAllData - Word Value - RegisterBlock[RegisterInfo{RegisterName}{RegisterAddress} + 1 : " . $RegisterBlock[$RegisterInfo{$RegisterName}{RegisterAddress} + 1] ;
|
|
Log3 $name, 5, $name. " : UpsPico_GetAllData - Word Value - RegisterBlock[RegisterInfo{RegisterName}{RegisterAddress} + 1 & +0 : " . $RegisterBlock[$RegisterInfo{$RegisterName}{RegisterAddress} + 1] . $RegisterBlock[$RegisterInfo{$RegisterName}{RegisterAddress}];
|
|
Log3 $name, 5, $name. " : UpsPico_GetAllData - Word Value - RegisterInfo{RegisterName}{Factor} : " . $RegisterInfo{$RegisterName}{Factor};
|
|
Log3 $name, 5, $name. " : UpsPico_GetAllData - Word Value - RegisterInfo{RegisterName}{Value} : " . $RegisterInfo{$RegisterName}{Value};
|
|
}
|
|
elsif ($RegisterInfo{$RegisterName}{DataType} eq "ASCII")
|
|
{
|
|
$RegisterInfo{$RegisterName}{Value} = chr(hex($RegisterBlock[$RegisterInfo{$RegisterName}{RegisterAddress}]));
|
|
Log3 $name, 4, $name. " : UpsPico_GetAllData - ASCII Value from " . $RegisterI2CBlock . " Register stored in Register-Hash for " . $RegisterName;
|
|
}
|
|
elsif ($RegisterInfo{$RegisterName}{DataType} eq "Hex")
|
|
{
|
|
$RegisterInfo{$RegisterName}{Value} = hex($RegisterBlock[$RegisterInfo{$RegisterName}{RegisterAddress}]);
|
|
Log3 $name, 4, $name. " : UpsPico_GetAllData - Hex Value from " . $RegisterI2CBlock . " Register transformed into Integer and stored in Register-Hash for " . $RegisterName;
|
|
}
|
|
else
|
|
{
|
|
$RegisterInfo{$RegisterName}{Value} = "ERROR";
|
|
Log3 $name, 2, $name. " : UpsPico_GetAllData - ERROR - No Data Type found in Register-Hash for " . $RegisterName;
|
|
}
|
|
|
|
### If the Register needs to be reset after reading, write 0x00 into register.
|
|
if(($RegisterInfo{$RegisterName}{Reset} == true))
|
|
{
|
|
my $SshCmdStatus = "sudo i2cset -y 1 " . $I2CAddress{$RegisterI2CBlock} . " " . $RegisterInfo{$RegisterName}{RegisterAddress} . " 0";
|
|
($stdout, $stderr, $exit) = $ssh->cmd($SshCmdStatus);
|
|
Log3 $name, 4, $name. " : UpsPico_GetAllData - Resetting Register to 0x00 for : " . $RegisterName;
|
|
Log3 $name, 5, $name. " : UpsPico_GetAllData - SshCmdStatus : " . $SshCmdStatus;
|
|
if(defined($stderr)) { Log3 $name, 2, $name. " : UpsPico_GetAllData - stderr Reset : " . $stderr; }
|
|
if(defined($exit)) { Log3 $name, 5, $name. " : UpsPico_GetAllData - exit Reset : " . $exit; }
|
|
if(defined($stdout)) { Log3 $name, 5, $name. " : UpsPico_GetAllData - stdout Reset : \n" . $stdout; }
|
|
Log3 $name, 5, $name. " : UpsPico_GetAllData ------------------------------------------------------------------------------------";
|
|
|
|
}
|
|
### Write current value
|
|
readingsSingleUpdate($hash, "/" . $RegisterI2CBlock . "/" . $RegisterName, $RegisterInfo{$RegisterName}{Value},1);
|
|
}
|
|
}
|
|
}
|
|
####END###### Download Register ########################################################################END#####
|
|
}
|
|
####END####### Download register block from UPS PIco via ssh command #######################################END#####
|
|
|
|
###START###### Calculate and save Battery charging status #################################################START####
|
|
Log3 $name, 5, $name. " : UpsPico_GetAllData - charge status - battype value : " . $RegisterInfo{"battype"}{Value};
|
|
|
|
if ($RegisterInfo{"battype"}{Value} ne undef)
|
|
{
|
|
my $ChargeState;
|
|
my $BattType = $RegisterInfo{"battype"}{Value};
|
|
my $FoundBatteryItem = false;
|
|
my $BattChargingState = "ERROR - No Battery found";
|
|
|
|
### Search for the correct alias in the SelectionList
|
|
foreach my $BattInfoEntry (keys %BattChargingInfo)
|
|
{
|
|
Log3 $name, 5, $name. " : UpsPico_GetAllData - charge status - BattInfoEntry : " . $RegisterInfo{"battype"}{Value};
|
|
|
|
### If the entry has been found
|
|
if ($BattInfoEntry eq $BattType)
|
|
{
|
|
### For debugging purpose only
|
|
Log3 $name, 5, $name. " : UpsPico_GetAllData - charge status - Found battype! ";
|
|
Log3 $name, 5, $name. " : UpsPico_GetAllData - charge status - BattType : " . $BattInfoEntry;
|
|
Log3 $name, 5, $name. " : UpsPico_GetAllData - charge status - 0 Percent Voltage : " . $BattChargingInfo{$BattInfoEntry}{Volt0Percent};
|
|
Log3 $name, 5, $name. " : UpsPico_GetAllData - charge status - 100 Percent Voltage : " . $BattChargingInfo{$BattInfoEntry}{Volt100Percent};
|
|
Log3 $name, 5, $name. " : UpsPico_GetAllData - charge status - Measured Voltage : " . $RegisterInfo{"batlevel"}{Value};
|
|
|
|
my $BatVoltageLevel = $RegisterInfo{"batlevel"}{Value};
|
|
|
|
### Limit Voltagelevel to maximum to avoid indication of temporary overcharging
|
|
if ($BatVoltageLevel > $BattChargingInfo{$BattInfoEntry}{Volt100Percent})
|
|
{
|
|
$BatVoltageLevel = $BattChargingInfo{$BattInfoEntry}{Volt100Percent}
|
|
}
|
|
|
|
### Calculate Battery state of charging
|
|
$BattChargingState = sprintf("%02d", ((($BatVoltageLevel - $BattChargingInfo{$BattInfoEntry}{Volt0Percent}) / ($BattChargingInfo{$BattInfoEntry}{Volt100Percent} - $BattChargingInfo{$BattInfoEntry}{Volt0Percent})) * 100));
|
|
}
|
|
}
|
|
|
|
### Write current value to reading and STATE
|
|
readingsSingleUpdate($hash, "BattCharge", $BattChargingState,1);
|
|
$hash->{STATE} = $BattChargingState;
|
|
|
|
Log3 $name, 4, $name. " : UpsPico_GetAllData - charge status - BattChargingState : " . $BattChargingState;
|
|
}
|
|
####END####### Calculate and save Battery charging status ##################################################END#####
|
|
|
|
|
|
### For Debugging purpose only
|
|
Log3 $name, 5, $name. " : UpsPico_GetAllData - RegisterInfo in fhem-hash : \n" . Dumper \$hash->{temp}{RegisterInfo};
|
|
Log3 $name, 5, $name. " : UpsPico_GetAllData -----------------------------------------------------------------";
|
|
|
|
### Close SSH session
|
|
undef $ssh;
|
|
Log3 $name, 4, $name. " : UpsPico_GetAllData - SSH session closed";
|
|
Log3 $name, 5, $name. " : UpsPico_GetAllData ----------------------------------------------------------------------------------------------------------------";
|
|
####END####### Download register block from UPS PIco via ssh command #######################################END#####
|
|
|
|
#### Initiate the timer for continuous polling of all data from UpsPico
|
|
InternalTimer(gettimeofday()+$PollingInterval, "UpsPico_GetAllData", $hash, 0);
|
|
Log3 $name, 4, $name. " : UpsPico_GetAllData - Define: InternalTimer for GettAllData re-started with interval of: " . $PollingInterval . " s";
|
|
|
|
###START###### Reset fullResponse error message ############################################################START####
|
|
readingsSingleUpdate( $hash, "fullResponse", "Standby", 1);
|
|
####END####### Reset fullResponse error message #############################################################END#####
|
|
}
|
|
####END####### Download all register ###########################################################################END#####
|
|
1;
|
|
=pod
|
|
=item device
|
|
=item summary Connects fhem to UpsPIco on remote RasPi
|
|
=item summary_DE Verbindet fhem mit einem UpsPIco auf einem entfernten RasPi
|
|
|
|
=begin html
|
|
|
|
<a name="UpsPico"></a>
|
|
<h3>UpsPico</h3>
|
|
<ul>
|
|
<table>
|
|
<tr>
|
|
<td>
|
|
The UpsPIco is an interruptible Power Supply for the Raspberry Pi from PiModules. This module is written for the Firmware Version 0x38 and above and has been tested on the "UPS PIco HV3.0A Stack Plus" only.<BR>
|
|
This module provides all the internal data written in the UpsPIco register which are accessible via I2C - Bus. The set command is able to change the values in accordance to the specifications.<BR>
|
|
For details to the Information contained in the register, please consult the internal register specification published in the latest manual. (See below)<BR>
|
|
<BR>
|
|
<u>References:</u><BR>
|
|
<a href="http://www.pimodulescart.com/shop/item.aspx?itemid=29">UPS PIco HV3.0A Stack Plus</a><BR>
|
|
<a href="http://www.forum.pimodules.com/viewforum.php?f=25">UPS PIco HV3.0A : Internal Register Specification, Manuals and Firmware Updates</a><BR>
|
|
<BR>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<table>
|
|
<tr><td><a name="UpsPicodefine"></a><b>Define</b></td></tr>
|
|
</table>
|
|
|
|
<table><tr><td><ul><code>define <name> UpsPico <IPv4-address> <Username> <Password></code></ul></td></tr></table>
|
|
|
|
<ul><ul>
|
|
<table>
|
|
<tr><td><code><name></code> : </td><td>The name of the device. Recommendation: "myUpsPico".</td></tr>
|
|
<tr><td><code><IPv4-address></code> : </td><td>A valid IPv4 address of the Raspberry Pi with UpsPIco. You might look into your router which DHCP address has been given to the RasPi.</td></tr>
|
|
<tr><td><code><GatewayPassword></code> : </td><td>The username of the remote Raspberry Pi.</td></tr>
|
|
<tr><td><code><PrivatePassword></code> : </td><td>The password of the remote Raspberry Pi.</td></tr>
|
|
</table>
|
|
</ul></ul>
|
|
|
|
<BR>
|
|
|
|
<table>
|
|
<tr><td><a name="UpsPicoSet"></a><b>Set</b></td></tr>
|
|
<tr><td>
|
|
<ul>
|
|
The set function is able to change a value which is marked as writeable.<BR>
|
|
If the register is considered as a critical setting (e.g. a wrong value might result in permanent damage), the attribute "WriteCritical" must be set to "1" = yes beforehand.
|
|
</ul>
|
|
</td></tr>
|
|
</table>
|
|
|
|
<table><tr><td><ul><code>set <name> <register> <value></code></ul></td></tr></table>
|
|
|
|
<ul><ul>
|
|
<table>
|
|
<tr><td><code><name></code> : </td><td>The name of the defined UpsPico device<BR></td></tr>
|
|
<tr><td><code><register></code> : </td><td>The name of the register which value shall be set. E.g.: "<code>/Status/key</code>"<BR></td></tr>
|
|
<tr><td><code><value></code> : </td><td>A valid value for this register.<BR></td></tr>
|
|
</table>
|
|
</ul></ul>
|
|
|
|
<BR>
|
|
|
|
<table>
|
|
<tr><td><a name="UpsPicoGet"></a><b>Get</b></td></tr>
|
|
<tr><td>
|
|
<ul>
|
|
The get function is able to obtain a value of a register.<BR>
|
|
It returns only the value but not the unit or the range or list of allowed values possible.<BR>
|
|
</ul>
|
|
</td></tr>
|
|
</table>
|
|
|
|
<table><tr><td><ul><code>get <name> <register></code></ul></td></tr></table>
|
|
|
|
<ul><ul>
|
|
<table>
|
|
<tr><td><code><name></code> : </td><td>The name of the defined UpsPico device<BR></td></tr>
|
|
<tr><td><code><register></code> : </td><td>The name of the register which value shall be obtained. E.g.: "<code>/Status/key</code>"<BR></td></tr>
|
|
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</ul></ul>
|
|
|
|
<BR>
|
|
|
|
<table>
|
|
<tr><td><a name="UpsPicoAttr"></a><b>Attributes</b></td></tr>
|
|
<tr><td>
|
|
<ul>
|
|
<BR>
|
|
The following user attributes can be used with the UpsPico module in addition to the general ones e.g. <a href="#room">room</a>.<BR>
|
|
</ul>
|
|
</td></tr>
|
|
</table>
|
|
|
|
<table>
|
|
<td>
|
|
<ul><ul>
|
|
<tr>
|
|
<td>
|
|
<BR>
|
|
<tr><td><ul><li><code>PollingInterval</code> : </li></td><td>A valid polling interval for the values of the UPS PIco. The value must be >=20s to allow the UpsPico module to perform a full polling procedure. <BR>
|
|
The default value is 300s.<BR>
|
|
</ul></td></tr>
|
|
</td>
|
|
</tr>
|
|
</ul></ul>
|
|
|
|
<ul><ul>
|
|
|
|
<tr>
|
|
<td>
|
|
<BR>
|
|
<tr><td><ul><li><code>WriteCritical</code> : </li></td><td>Prevents acidential damaging of the UpsPico hardware by change of critical register with wrong values.<BR>
|
|
The attribute must be re-activated for every single set-command.<BR>
|
|
The default value is 0 = deactivated<BR>
|
|
</ul></td></tr>
|
|
</td>
|
|
</tr>
|
|
|
|
</ul></ul>
|
|
|
|
<ul><ul>
|
|
<tr>
|
|
<td>
|
|
<BR>
|
|
<tr><td><ul><li><code>Port</code> : </li></td><td>The port number for the SSH access on the remote system.<BR>
|
|
The default value is 22 = Standard SSH port<BR>
|
|
</ul></td></tr>
|
|
</td>
|
|
</tr>
|
|
</ul></ul>
|
|
|
|
<ul><ul>
|
|
<tr>
|
|
<td>
|
|
<BR>
|
|
<tr><td><ul><li><code>CredentialsEncrypted</code> : </li></td><td>This attributes will swap from plain text to base64 encrypted credentials in the definition.<BR>
|
|
The default value is 0 = Plain Text Credentials<BR>
|
|
</ul></td></tr>
|
|
</td>
|
|
</tr>
|
|
</ul></ul>
|
|
|
|
<ul><ul>
|
|
<tr>
|
|
<td>
|
|
<BR>
|
|
<tr><td><ul><li><code>DbLogExclude</code> : </li></td><td>This general attribute will be set automatically to the reading "/Status/pico_is_running" which is a continously counting WatchDog register.<BR>
|
|
It makes no sense to log this reading.<BR>
|
|
The default exclusion from logging is "/Status/pico_is_running" <BR>
|
|
</ul></td></tr>
|
|
</td>
|
|
</tr>
|
|
</ul></ul>
|
|
|
|
<ul><ul>
|
|
<tr>
|
|
<td>
|
|
<BR>
|
|
<tr><td><ul><li><code>event-on-change-reading</code> : </li></td><td>This general attribute will be set automatically to ".*" which prevents unchanged but updated readings to be logged.<BR>
|
|
The default value is ".*" = Apply to all readings.<BR>
|
|
</ul></td></tr>
|
|
</td>
|
|
</tr>
|
|
</ul></ul>
|
|
|
|
<ul><ul>
|
|
<tr>
|
|
<td>
|
|
<BR>
|
|
<tr><td><ul><li><code>room</code> : </li></td><td>This general attribute will be set automatically to "UpsPIco" which prevents the device getting lost in the "Everything" room.<BR>
|
|
The default value is "UpsPIco".<BR>
|
|
</ul></td></tr>
|
|
</td>
|
|
</tr>
|
|
</ul></ul>
|
|
</td>
|
|
</table>
|
|
</ul>
|
|
=end html
|
|
|
|
=begin html_DE
|
|
|
|
<a name="UpsPico"></a>
|
|
<h3>UpsPico</h3>
|
|
<ul>
|
|
<table>
|
|
<tr>
|
|
<td>
|
|
Der UpsPIco ist eine unterbrechungsfreie Stroimversorgung für den Raspberry Pi von PiModules. Dieses Modul wurde für die Firmware ab Version 0x38 und höher geschrieben und wurde nur auf dem "UPS PIco HV3.0A Stack Plus" getestet.<BR>
|
|
Dieses Modul stellt alle internen Daten zur Verfügung, welche in die UpsPIco Register geschrieben und über den I2C - Bus ausgelesen werden. Der set-Befehl ist darüber hinaus in der Lage die Werte der Register entsprechend Ihrer Spezifikation zu ändern.<BR>
|
|
Detailierte Informationen zu den einzelnen Registern stehen in den Register Spezifikationen in der letzten veröffentlichten Anleitung. (Siehe unten)<BR>
|
|
<BR>
|
|
<u>Referenzen:</u><BR>
|
|
<a href="http://www.pimodulescart.com/shop/item.aspx?itemid=29">UPS PIco HV3.0A Stack Plus</a><BR>
|
|
<a href="http://www.forum.pimodules.com/viewforum.php?f=25">UPS PIco HV3.0A : Interne Register Spezification, Anleitung and Firmware Updates</a><BR>
|
|
<BR>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<table>
|
|
<tr><td><a name="UpsPicodefine"></a><b>Define</b></td></tr>
|
|
</table>
|
|
|
|
<table><tr><td><ul><code>define <name> UpsPico <IPv4-address> <Username> <Password></code></ul></td></tr></table>
|
|
|
|
<ul><ul>
|
|
<table>
|
|
<tr><td><code><name></code> : </td><td>Der Name des Device. Empfehlung: "myUpsPico".</td></tr>
|
|
<tr><td><code><IPv4-address></code> : </td><td>Eine gültige IPv4 Adresse des Raspberry Pi mit UpsPIco. Gegebenenfalls muss der Router für die an den Raspberry Pi vergebene DHCP Adresse konsultiert werden.</td></tr>
|
|
<tr><td><code><GatewayPassword></code> : </td><td>Der Username des entfernten Raspberry Pi.</td></tr>
|
|
<tr><td><code><PrivatePassword></code> : </td><td>Das Passwort des entfernten Raspberry Pi.</td></tr>
|
|
</table>
|
|
</ul></ul>
|
|
|
|
<BR>
|
|
|
|
<table>
|
|
<tr><td><a name="UpsPicoSet"></a><b>Set</b></td></tr>
|
|
<tr><td>
|
|
<ul>
|
|
Diese Funktion verändert die Werte der register, welche als beschreibbar definiert sind.<BR>
|
|
Sind die entsprechenden Register als kritisch (critical) spezifiziert (Ein falscher Wert könnte zur Beschädigung des UpsPIco führen), muss das Atttribut "WriteCritical" vorher auf "1" gesetzt werden.
|
|
</ul>
|
|
</td></tr>
|
|
</table>
|
|
|
|
<table><tr><td><ul><code>set <name> <register> <value></code></ul></td></tr></table>
|
|
|
|
<ul><ul>
|
|
<table>
|
|
<tr><td><code><name></code> : </td><td>Der name des definierten UpsPico Device<BR></td></tr>
|
|
<tr><td><code><register></code> : </td><td>Der name des Registers welches verändert werden soll. E.g.: "<code>/Status/key</code>"<BR></td></tr>
|
|
<tr><td><code><value></code> : </td><td>Ein gültiger Wert für das Register.<BR></td></tr>
|
|
</table>
|
|
</ul></ul>
|
|
|
|
<BR>
|
|
|
|
<table>
|
|
<tr><td><a name="UpsPicoGet"></a><b>Get</b></td></tr>
|
|
<tr><td>
|
|
<ul>
|
|
Die get Funktion liest einzelne Register aus und schreibt sie in das entsprechende Reading.<BR>
|
|
Es wird nur der Wert, aber nicht die Einheit oder der gültige Wertebereich zurückgegeben.<BR>
|
|
</ul>
|
|
</td></tr>
|
|
</table>
|
|
|
|
<table><tr><td><ul><code>get <name> <register></code></ul></td></tr></table>
|
|
|
|
<ul><ul>
|
|
<table>
|
|
<tr><td><code><name></code> : </td><td>Der name des definierten UpsPico Device<BR></td></tr>
|
|
<tr><td><code><register></code> : </td><td>Der name des Registers welches ausgelesen werden soll. E.g.: "<code>/Status/key</code>"<BR></td></tr>
|
|
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</ul></ul>
|
|
|
|
<BR>
|
|
|
|
<table>
|
|
<tr><td><a name="UpsPicoAttr"></a><b>Attributes</b></td></tr>
|
|
<tr><td>
|
|
<ul>
|
|
<BR>
|
|
Die folgenden Attribute können neben den allgemeinen Attributen wie <a href="#room">room</a> vergeben werden.<BR>
|
|
</ul>
|
|
</td></tr>
|
|
</table>
|
|
|
|
<table>
|
|
<td>
|
|
<ul><ul>
|
|
<tr>
|
|
<td>
|
|
<BR>
|
|
<tr><td><ul><li><code>PollingInterval</code> : </li></td><td>Abrageinterval für den UPS PIco. Der Wert muss >=20s sein um einen vollen Polling Zyklus zu erlauben.<BR>
|
|
Der Defaul Wert ist 300s.<BR>
|
|
</ul></td></tr>
|
|
</td>
|
|
</tr>
|
|
</ul></ul>
|
|
|
|
<ul><ul>
|
|
|
|
<tr>
|
|
<td>
|
|
<BR>
|
|
<tr><td><ul><li><code>WriteCritical</code> : </li></td><td>Verhindert versehentliche Beschädigungen durch Beschreiben der kritischen Register mit falschen Werten.<BR>
|
|
Musz für jeden einzelnen Schreibvorgang erneut gesetzt werden da dieser zurückgesetzt wird..<BR>
|
|
Der Default Wert ist 0 = Deaktiviert.<BR>
|
|
</ul></td></tr>
|
|
</td>
|
|
</tr>
|
|
|
|
</ul></ul>
|
|
|
|
<ul><ul>
|
|
<tr>
|
|
<td>
|
|
<BR>
|
|
<tr><td><ul><li><code>Port</code> : </li></td><td>Port Nummer für den SSH Zugang am entfernten Raspberry Pi.<BR>
|
|
Der Default Wert ist 22 = Standard SSH Port<BR>
|
|
</ul></td></tr>
|
|
</td>
|
|
</tr>
|
|
</ul></ul>
|
|
|
|
<ul><ul>
|
|
<tr>
|
|
<td>
|
|
<BR>
|
|
<tr><td><ul><li><code>CredentialsEncrypted</code> : </li></td><td>Definiert ob die Anmeldedaten in lesbarer Form (PlainText) oder als base64 verschlüsselt vorliegen.<BR>
|
|
Der Default Wert ist 0 = Anmeldedaten liegen in PlainText vor.<BR>
|
|
</ul></td></tr>
|
|
</td>
|
|
</tr>
|
|
</ul></ul>
|
|
|
|
<ul><ul>
|
|
<tr>
|
|
<td>
|
|
<BR>
|
|
<tr><td><ul><li><code>DbLogExclude</code> : </li></td><td>Generelles Attribut um Readings von Loggen auszuschließen. Das Attribut wird automatisch auf "/Status/pico_is_running" gesetzt welchen den kontinuierlichen Watchdog Zähler vom loggen ausnimmt.<BR>
|
|
Es ergibt keinen Sinn dieses Reading zu loggen.<BR>
|
|
Der Default Wert für die Ausnahme vom loggen liegt auf dem Reading "/Status/pico_is_running" <BR>
|
|
</ul></td></tr>
|
|
</td>
|
|
</tr>
|
|
</ul></ul>
|
|
|
|
<ul><ul>
|
|
<tr>
|
|
<td>
|
|
<BR>
|
|
<tr><td><ul><li><code>event-on-change-reading</code> : </li></td><td>Generelles Attribut um Events nur bei änderungen von Readings zu erzeugen. Das Attribut wird automatisch auf ".*" gesetzt, was alle Readings nur bei änderungen loggt.<BR>
|
|
Der Default Wert ist ".*" = Alle Readings.<BR>
|
|
</ul></td></tr>
|
|
</td>
|
|
</tr>
|
|
</ul></ul>
|
|
|
|
<ul><ul>
|
|
<tr>
|
|
<td>
|
|
<BR>
|
|
<tr><td><ul><li><code>room</code> : </li></td><td>Generelles Attribut zum setzen des Raumes. Das Attribut wird automatisch auf "UpsPIco" gesetzt, damit das device nicht im "Everthing" Raum verschwindet.<BR>
|
|
Der Default Wert ist "UpsPIco".<BR>
|
|
</ul></td></tr>
|
|
</td>
|
|
</tr>
|
|
</ul></ul>
|
|
</td>
|
|
</table>
|
|
</ul>
|
|
=end html_DE |