mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-03-03 16:56:54 +00:00
70_PylonLowVoltage: contrib V0.1.8
git-svn-id: https://svn.fhem.de/fhem/trunk@27991 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
487b265bab
commit
1e4f1458d6
@ -122,6 +122,7 @@ BEGIN {
|
||||
|
||||
# Versions History intern (Versions history by Heiko Maaz)
|
||||
my %vNotesIntern = (
|
||||
"0.1.8" => "23.09.2023 new Attr userBatterytype, change manufacturerInfo command hash to LENID=0 ",
|
||||
"0.1.7" => "20.09.2023 extend possible number of bats from 6 to 8 ",
|
||||
"0.1.6" => "19.09.2023 rework of _callAnalogValue, support of more than 15 cells ",
|
||||
"0.1.5" => "19.09.2023 internal code change ",
|
||||
@ -141,6 +142,7 @@ my $invalid = 'unknown'; # default v
|
||||
my $definterval = 30; # default Abrufintervall der Batteriewerte
|
||||
my $defto = 0.5; # default connection Timeout zum RS485 Gateway
|
||||
my @blackl = qw(state nextCycletime); # Ausnahmeliste deleteReadingspec
|
||||
my $age1def = 60; # default Zyklus Abrufklasse statische Werte (s)
|
||||
|
||||
# Steuerhashes
|
||||
###############
|
||||
@ -212,23 +214,24 @@ my %hrsnb = ( # Codierung
|
||||
# ADR: n=Batterienummer (2-x), m=Group Nr. (0-8), ADR = 0x0n + (0x10 * m) -> f. Batterie 1 = 0x02 + (0x10 * 0) = 0x02
|
||||
# CID1: Kommando spezifisch, hier 46H
|
||||
# CID2: Kommando spezifisch, hier 51H
|
||||
# LENGTH: LENID + LCHKSUM -> Pylon LFP V2.8 Doku
|
||||
# INFO: muß hier mit ADR übereinstimmen
|
||||
# CHKSUM: 32+30+30+32+34+36+35+31+45+30+30+32+30+32 = 02CDH -> modulo 65536 = 02CDH -> bitweise invert = 1111 1101 0011 0010 -> +1 = 1111 1101 0011 0011 -> FD33H
|
||||
# LENGTH: LENID + LCHKSUM -> Pylon LFP V3.3 Doku
|
||||
# LENID = 0 -> LENID = 0000B + 0000B + 0000B = 0000B -> modulo 16 -> 0000B -> bitweise invert = 1111 -> +1 = 0001 0000 -> LCHKSUM = 0000B -> LENGTH = 0000 0000 0000 0000 -> 0000H
|
||||
# wenn LENID = 0, dann ist INFO empty (Doku LFP V3.3 S.8)
|
||||
# CHKSUM: 32+30+30+33+34+36+35+31+30+30+30+30 = 0255H -> modulo 65536 = 0255H -> bitweise invert = 1111 1101 1010 1010 -> +1 = 1111 1101 1010 1011 -> FDABH
|
||||
#
|
||||
# SOI VER ADR CID1 CID2 LENGTH INFO CHKSUM
|
||||
# ~ 20 02 46 51 E0 02 02 FD 33
|
||||
# 7E 32 30 30 32 34 36 35 31 45 30 30 32 30 32 46 44 32 44
|
||||
# ~ 20 02 46 51 00 00 empty FD AC
|
||||
# 7E 32 30 30 33 34 36 35 31 30 30 30 30 - - 46 44 41 43
|
||||
#
|
||||
my %hrmfi = ( # Codierung Abruf manufacturerInfo, mlen = Mindestlänge Antwortstring
|
||||
1 => { cmd => "~20024651E00202FD33\x{0d}", mlen => 82 },
|
||||
2 => { cmd => "~20034651E00203FD31\x{0d}", mlen => 82 },
|
||||
3 => { cmd => "~20044651E00204FD2F\x{0d}", mlen => 82 },
|
||||
4 => { cmd => "~20054651E00205FD2D\x{0d}", mlen => 82 },
|
||||
5 => { cmd => "~20064651E00206FD2B\x{0d}", mlen => 82 },
|
||||
6 => { cmd => "~20074651E00207FD29\x{0d}", mlen => 82 },
|
||||
7 => { cmd => "~20084651E00208FD27\x{0d}", mlen => 82 },
|
||||
8 => { cmd => "~20094651E00209FD25\x{0d}", mlen => 82 },
|
||||
1 => { cmd => "~200246510000FDAC\x{0d}", mlen => 82 },
|
||||
2 => { cmd => "~200346510000FDAB\x{0d}", mlen => 82 },
|
||||
3 => { cmd => "~200446510000FDAA\x{0d}", mlen => 82 },
|
||||
4 => { cmd => "~200546510000FDA9\x{0d}", mlen => 82 },
|
||||
5 => { cmd => "~200646510000FDA8\x{0d}", mlen => 82 },
|
||||
6 => { cmd => "~200746510000FDA7\x{0d}", mlen => 82 },
|
||||
7 => { cmd => "~200846510000FDA6\x{0d}", mlen => 82 },
|
||||
8 => { cmd => "~200946510000FDA5\x{0d}", mlen => 82 },
|
||||
);
|
||||
|
||||
# request command für '1': ~20024651E00202FD33 + CR
|
||||
@ -326,6 +329,7 @@ sub Initialize {
|
||||
$hash->{AttrList} = "disable:1,0 ".
|
||||
"interval ".
|
||||
"timeout ".
|
||||
"userBatterytype ".
|
||||
$readingFnAttributes;
|
||||
|
||||
eval { FHEM::Meta::InitMod( __FILE__, $hash ) }; ## no critic 'eval'
|
||||
@ -443,15 +447,20 @@ sub Attr {
|
||||
}
|
||||
}
|
||||
|
||||
if ($aName eq "interval") {
|
||||
if ($aName eq 'interval') {
|
||||
if (!looks_like_number($aVal)) {
|
||||
return qq{The value for $aName is invalid, it must be numeric!};
|
||||
}
|
||||
|
||||
InternalTimer(gettimeofday()+1.0, "FHEM::PylonLowVoltage::manageUpdate", $hash, 0);
|
||||
}
|
||||
|
||||
if ($aName eq 'userBatterytype') {
|
||||
$hash->{HELPER}{AGE1} = 0;
|
||||
InternalTimer(gettimeofday()+1.0, "FHEM::PylonLowVoltage::manageUpdate", $hash, 0);
|
||||
}
|
||||
|
||||
if ($aName eq "timeout") {
|
||||
if ($aName eq 'timeout') {
|
||||
if (!looks_like_number($aVal)) {
|
||||
return qq{The value for $aName is invalid, it must be numeric!};
|
||||
}
|
||||
@ -465,7 +474,9 @@ return;
|
||||
###############################################################
|
||||
sub manageUpdate {
|
||||
my $hash = shift;
|
||||
|
||||
my $name = $hash->{NAME};
|
||||
my $age1 = delete $hash->{HELPER}{AGE1} // $age1def;
|
||||
|
||||
RemoveInternalTimer ($hash);
|
||||
|
||||
@ -497,7 +508,7 @@ sub manageUpdate {
|
||||
if ($timeout < 1.0) {
|
||||
BlockingKill ($hash->{HELPER}{BKRUNNING}) if(defined $hash->{HELPER}{BKRUNNING});
|
||||
Log3 ($name, 4, qq{$name - Cycle started in main process});
|
||||
startUpdate ({ name => $name, timeout => $timeout, readings => $readings});
|
||||
startUpdate ({name => $name, timeout => $timeout, readings => $readings, age1 => $age1});
|
||||
}
|
||||
else {
|
||||
delete $hash->{HELPER}{BKRUNNING} if(defined $hash->{HELPER}{BKRUNNING} && $hash->{HELPER}{BKRUNNING}{pid} =~ /DEAD/xs);
|
||||
@ -511,7 +522,7 @@ sub manageUpdate {
|
||||
my $blto = sprintf "%.0f", ($timeout + 10);
|
||||
|
||||
$hash->{HELPER}{BKRUNNING} = BlockingCall ( "FHEM::PylonLowVoltage::startUpdate",
|
||||
{block => 1, name => $name, timeout => $timeout, readings => $readings},
|
||||
{name => $name, timeout => $timeout, readings => $readings, age1 => $age1, block => 1},
|
||||
"FHEM::PylonLowVoltage::finishUpdate",
|
||||
$blto, # Blocking Timeout höher als INET-Timeout!
|
||||
"FHEM::PylonLowVoltage::abortUpdate",
|
||||
@ -539,6 +550,7 @@ sub startUpdate {
|
||||
my $timeout = $paref->{timeout};
|
||||
my $readings = $paref->{readings};
|
||||
my $block = $paref->{block} // 0;
|
||||
my $age1 = $paref->{age1};
|
||||
|
||||
my $hash = $defs{$name};
|
||||
my $success = 0;
|
||||
@ -556,7 +568,7 @@ sub startUpdate {
|
||||
$block ? return ($serial) : return \&finishUpdate ($serial);
|
||||
}
|
||||
|
||||
if (ReadingsAge ($name, "serialNumber", 601) >= 60) { # Abrufklasse statische Werte
|
||||
if (ReadingsAge ($name, "serialNumber", 6000) >= $age1) { # Abrufklasse statische Werte
|
||||
for my $idx (sort keys %fns1) {
|
||||
if (&{$fns1{$idx}{fn}} ($hash, $socket, $readings)) {
|
||||
$serial = encode_base64 (Serialize ( {name => $name, readings => $readings} ), "");
|
||||
@ -786,13 +798,15 @@ sub _callManufacturerInfo {
|
||||
}
|
||||
|
||||
__resultLog ($hash, $res);
|
||||
|
||||
my $BatteryHex = substr ($res, 13, 20);
|
||||
|
||||
my $name = $hash->{NAME};
|
||||
my $ubtt = AttrVal ($name, 'userBatterytype', ''); # evtl. Batterietyp manuell überschreiben
|
||||
my $BatteryHex = substr ($res, 13, 20);
|
||||
# my $softwareVersion = 'V'.hex (substr ($res, 33, 2)).'.'.hex (substr ($res, 35, 2)); # unklare Bedeutung
|
||||
my $ManufacturerHex = substr ($res, 37, 40);
|
||||
my $ManufacturerHex = substr ($res, 37, 40);
|
||||
|
||||
$readings->{batteryType} = pack ("H*", $BatteryHex);
|
||||
$readings->{Manufacturer} = pack ("H*", $ManufacturerHex);
|
||||
$readings->{batteryType} = $ubtt ? $ubtt.' (adapted)' : pack ("H*", $BatteryHex);
|
||||
$readings->{Manufacturer} = pack ("H*", $ManufacturerHex);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -906,7 +920,7 @@ sub _callSystemParameters {
|
||||
$readings->{paramModuleUnderVoltLimit} = sprintf "%.3f", (hex substr ($res, 47, 4)) / 1000; # Schutz Limit
|
||||
$readings->{paramDischargeHighTempLimit} = sprintf "%.1f", ((hex substr ($res, 51, 4)) - 2731) / 10;
|
||||
$readings->{paramDischargeLowTempLimit} = sprintf "%.1f", ((hex substr ($res, 55, 4)) - 2731) / 10;
|
||||
$readings->{paramDischargeCurrentLimit} = sprintf "%.3f", (65535 - (hex substr ($res, 59, 4))) * 100 / 1000; # mit Symbol (-)
|
||||
$readings->{paramDischargeCurrentLimit} = sprintf "%.3f", (65535 - (hex substr ($res, 59, 4))) * 100 / 1000; # mit Symbol (-)
|
||||
|
||||
return;
|
||||
}
|
||||
@ -1036,18 +1050,14 @@ sub _callAnalogValue {
|
||||
my $pcc = hex (substr($res, $bpos, 2)); # Anzahl Zellen (15 od. 16)
|
||||
$bpos += 2; # Pos 19
|
||||
|
||||
$readings->{packCellcount} = $pcc;
|
||||
|
||||
for my $z (0..$pcc-1) {
|
||||
my $fz = sprintf "%02d", ($z + 1); # formatierter Zähler
|
||||
my $pos = $bpos + ($z * 4); # Startposition
|
||||
$readings->{'cellVoltage_'.$fz} = sprintf "%.3f", hex(substr($res, $pos, 4)) / 1000; # Pos 19 - 75 bei 15 Zellen
|
||||
for my $z (1..$pcc) {
|
||||
my $fz = sprintf "%02d", $z; # formatierter Zähler
|
||||
$readings->{'cellVoltage_'.$fz} = sprintf "%.3f", hex(substr($res, $bpos, 4)) / 1000; # Pos 19 - 75 bei 15 Zellen
|
||||
$bpos += 4; # letzter Durchlauf: Pos 79 bei 15 Zellen, Pos 83 bei 16 Zellen
|
||||
}
|
||||
|
||||
$bpos += $pcc * 4; # Pos 79 bei 15 Zellen, Pos 83 bei 16 Zellen
|
||||
|
||||
$readings->{numberTempPos} = hex(substr($res, $bpos, 2)); # Anzahl der jetzt folgenden Teperaturpositionen -> 5
|
||||
$bpos += 2;
|
||||
$bpos += 2;
|
||||
|
||||
$readings->{bmsTemperature} = (hex (substr($res, $bpos, 4)) - 2731) / 10; # Pos 81 bei 15 Zellen
|
||||
$bpos += 4;
|
||||
@ -1112,8 +1122,9 @@ sub _callAnalogValue {
|
||||
if ($current & 0x8000) {
|
||||
$current = $current - 0x10000;
|
||||
}
|
||||
|
||||
$readings->{packCurrent} = sprintf "%.3f", $current / 10;
|
||||
|
||||
$readings->{packCellcount} = $pcc;
|
||||
$readings->{packCurrent} = sprintf "%.3f", $current / 10;
|
||||
|
||||
return;
|
||||
}
|
||||
@ -1472,6 +1483,12 @@ management system via the RS485 interface.
|
||||
(BlockingCall) so that write or read delays on the RS485 interface do not lead to blocking states in FHEM.
|
||||
</li>
|
||||
<br>
|
||||
|
||||
<a id="PylonLowVoltage-attr-userBatterytype"></a>
|
||||
<li><b>userBatterytype</b><br>
|
||||
The automatically determined battery type (Reading batteryType) is replaced by the specified string.
|
||||
</li>
|
||||
<br>
|
||||
</ul>
|
||||
|
||||
<a id="PylonLowVoltage-readings"></a>
|
||||
@ -1643,6 +1660,12 @@ Batteriemanagementsystem über die RS485-Schnittstelle zur Verfügung stellt.
|
||||
blockierenden Zuständen in FHEM führen.
|
||||
</li>
|
||||
<br>
|
||||
|
||||
<a id="PylonLowVoltage-attr-userBatterytype"></a>
|
||||
<li><b>userBatterytype</b><br>
|
||||
Der automatisch ermittelte Batterietyp (Reading batteryType) durch die angegebene Zeichenfolge ersetzt.
|
||||
</li>
|
||||
<br>
|
||||
</ul>
|
||||
|
||||
<a id="PylonLowVoltage-readings"></a>
|
||||
|
Loading…
x
Reference in New Issue
Block a user