diff --git a/fhem/contrib/ch.eick/Klimaanlage/99_MHI_Heavy.pm b/fhem/contrib/ch.eick/Klimaanlage/99_MHI_Heavy.pm new file mode 100644 index 000000000..1db437bce --- /dev/null +++ b/fhem/contrib/ch.eick/Klimaanlage/99_MHI_Heavy.pm @@ -0,0 +1,203 @@ +# === Initialize === +sub MHI_Heavy_Initialize { +} + +# Enter your functions below _this_ line. +################################################### + +package MHI_Heavy; +use strict; +use warnings; +use MIME::Base64 qw(decode_base64 encode_base64); +use List::Util qw(first); + +# === statische Tabellen === +our @outdoorTempList = (-50.0, -50.0, -50.0, -50.0, -50.0, -48.9, -46.0, -44.0, -42.0, -41.0, -39.0, -38.0, -37.0, -36.0, -35.0, -34.0, -33.0, -32.0, -31.0, -30.0, -29.0, -28.5, -28.0, -27.0, -26.0, -25.5, -25.0, -24.0, -23.5, -23.0, -22.5, -22.0, -21.5, -21.0, -20.5, -20.0, -19.5, -19.0, -18.5, -18.0, -17.5, -17.0, -16.5, -16.0, -15.5, -15.0, -14.6, -14.3, -14.0, -13.5, -13.0, -12.6, -12.3, -12.0, -11.5, -11.0, -10.6, -10.3, -10.0, -9.6, -9.3, -9.0, -8.6, -8.3, -8.0, -7.6, -7.3, -7.0, -6.6, -6.3, -6.0, -5.6, -5.3, -5.0, -4.6, -4.3, -4.0, -3.7, -3.5, -3.2, -3.0, -2.6, -2.3, -2.0, -1.7, -1.5, -1.2, -1.0, -0.6, -0.3, 0.0, 0.2, 0.5, 0.7, 1.0, 1.3, 1.6, 2.0, 2.2, 2.5, 2.7, 3.0, 3.2, 3.5, 3.7, 4.0, 4.2, 4.5, 4.7, 5.0, 5.2, 5.5, 5.7, 6.0, 6.2, 6.5, 6.7, 7.0, 7.2, 7.5, 7.7, 8.0, 8.2, 8.5, 8.7, 9.0, 9.2, 9.5, 9.7, 10.0, 10.2, 10.5, 10.7, 11.0, 11.2, 11.5, 11.7, 12.0, 12.2, 12.5, 12.7, 13.0, 13.2, 13.5, 13.7, 14.0, 14.2, 14.4, 14.6, 14.8, 15.0, 15.2, 15.5, 15.7, 16.0, 16.2, 16.5, 16.7, 17.0, 17.2, 17.5, 17.7, 18.0, 18.2, 18.5, 18.7, 19.0, 19.2, 19.4, 19.6, 19.8, 20.0, 20.2, 20.5, 20.7, 21.0, 21.2, 21.5, 21.7, 22.0, 22.2, 22.5, 22.7, 23.0, 23.2, 23.5, 23.7, 24.0, 24.2, 24.5, 24.7, 25.0, 25.2, 25.5, 25.7, 26.0, 26.2, 26.5, 26.7, 27.0, 27.2, 27.5, 27.7, 28.0, 28.2, 28.5, 28.7, 29.0, 29.2, 29.5, 29.7, 30.0, 30.2, 30.5, 30.7, 31.0, 31.3, 31.6, 32.0, 32.2, 32.5, 32.7, 33.0, 33.2, 33.5, 33.7, 34.0, 34.3, 34.6, 35.0, 35.2, 35.5, 35.7, 36.0, 36.3, 36.6, 37.0, 37.2, 37.5, 37.7, 38.0, 38.3, 38.6, 39.0, 39.3, 39.6, 40.0, 40.3, 40.6, 41.0, 41.3, 41.6, 42.0, 42.3, 42.6, 43.0); + +our @indoorTempList = (-30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -29.0, -28.0, -27.0, -26.0, -25.0, -24.0, -23.0, -22.5, -22.0, -21.0, -20.0, -19.5, -19.0, -18.0, -17.5, -17.0, -16.5, -16.0, -15.0, -14.5, -14.0, -13.5, -13.0, -12.5, -12.0, -11.5, -11.0, -10.5, -10.0, -9.5, -9.0, -8.6, -8.3, -8.0, -7.5, -7.0, -6.5, -6.0, -5.6, -5.3, -5.0, -4.5, -4.0, -3.6, -3.3, -3.0, -2.6, -2.3, -2.0, -1.6, -1.3, -1.0, -0.5, 0.0, 0.3, 0.6, 1.0, 1.3, 1.6, 2.0, 2.3, 2.6, 3.0, 3.2, 3.5, 3.7, 4.0, 4.3, 4.6, 5.0, 5.3, 5.6, 6.0, 6.3, 6.6, 7.0, 7.2, 7.5, 7.7, 8.0, 8.3, 8.6, 9.0, 9.2, 9.5, 9.7, 10.0, 10.3, 10.6, 11.0, 11.2, 11.5, 11.7, 12.0, 12.3, 12.6, 13.0, 13.2, 13.5, 13.7, 14.0, 14.2, 14.5, 14.7, 15.0, 15.3, 15.6, 16.0, 16.2, 16.5, 16.7, 17.0, 17.2, 17.5, 17.7, 18.0, 18.2, 18.5, 18.7, 19.0, 19.2, 19.5, 19.7, 20.0, 20.2, 20.5, 20.7, 21.0, 21.2, 21.5, 21.7, 22.0, 22.2, 22.5, 22.7, 23.0, 23.2, 23.5, 23.7, 24.0, 24.2, 24.5, 24.7, 25.0, 25.2, 25.5, 25.7, 26.0, 26.2, 26.5, 26.7, 27.0, 27.2, 27.5, 27.7, 28.0, 28.2, 28.5, 28.7, 29.0, 29.2, 29.5, 29.7, 30.0, 30.2, 30.5, 30.7, 31.0, 31.3, 31.6, 32.0, 32.2, 32.5, 32.7, 33.0, 33.2, 33.5, 33.7, 34.0, 34.2, 34.5, 34.7, 35.0, 35.3, 35.6, 36.0, 36.2, 36.5, 36.7, 37.0, 37.2, 37.5, 37.7, 38.0, 38.3, 38.6, 39.0, 39.2, 39.5, 39.7, 40.0, 40.3, 40.6, 41.0, 41.2, 41.5, 41.7, 42.0, 42.3, 42.6, 43.0, 43.2, 43.5, 43.7, 44.0, 44.3, 44.6, 45.0, 45.3, 45.6, 46.0, 46.2, 46.5, 46.7, 47.0, 47.3, 47.6, 48.0, 48.3, 48.6, 49.0, 49.3, 49.6, 50.0, 50.3, 50.6, 51.0, 51.3, 51.6, 52.0); + +# === Mappings für die Ausgabe === +our %POWER_MODES = ( + 0 => 'on', + 1 => 'off'); + +our %OPERATION_MODES = ( + 0 => 'auto', + 1 => 'cool', + 2 => 'heat', + 3 => 'fan', + 4 => 'dry' +); + +# Betriebsmodus +our %COOLHOTJUDGE_MODES = ( + 0 => 'auto', + 1 => 'cooling', + 2 => 'haeting'); + +our %AIRFLOW = ( + 0 => 'auto', + 1 => 'lowest', + 2 => 'low', + 3 => 'high', + 4 => 'highest' +); + +our %HORIZONTAL_POSITIONS = ( + 0 => 'auto', + 1 => 'left-left', + 2 => 'left-center', + 3 => 'center-center', + 4 => 'center-right', + 5 => 'right-right', + 6 => 'left-right', + 7 => 'right-left' +); + +our %VERTICAL_POSITIONS = ( + 0 => 'auto', + 1 => 'highest', + 2 => 'middle', + 3 => 'normal', + 4 => 'lowest' +); + + +# === Konstruktor === +sub new { + my ($class) = @_; + my $self = { + airFlow => -1, + coolHotJudge => 0, + electric => 0, + entrust => 0, + errorCode => '', + indoorTemp => undef, + isAutoHeating => 0, + isSelfCleanOperation=> 0, + isSelfCleanReset => 0, + isVacantProperty => 0, + modelNo => 0, + operation => 0, + operationMode => undef, + outdoorTemp => undef, + presetTemp => undef, + windDirectionLR => -1, + windDirectionUD => -1 + }; + bless $self, $class; + return $self; +} + +# === Hilfsfunktionen === +sub zeroPad { + my ($num, $places) = @_; + return sprintf("%0${places}d", $num); +} + +sub wosoFindMatch { + my ($value, $posVals, $p) = @_; + $p //= 0; + for (my $i = 0; $i < @$posVals; $i++) { + return $i + $p if $posVals->[$i] == $value; + } + return -1; +} + +# === CRC16-CCITT === +sub crc16ccitt { + my ($data_ref) = @_; + my $crc = 0xFFFF; + foreach my $b (@$data_ref) { + $b += 256 if $b < 0; + for my $bit (0 .. 7) { + my $z = (($crc >> 15) & 1) == 1; + my $z2 = (($b >> (7 - $bit)) & 1) == 1; + $crc <<= 1; + $crc &= 0xFFFF; + $crc ^= 0x1021 if ($z != $z2); + } + } + return $crc & 0xFFFF; +} + +# === Base64 → Objekt === +sub fromBase64 { + my ($class, $base64) = @_; + $base64 =~ s/\n//g; + my $binary = decode_base64($base64); + my @bytes = map { + my $h = ord($_); + ($h > 127) ? -1 * (256 - $h) : $h; + } split //, $binary; + + my $self = $class->new(); + + my $r3 = 18; + my $dataStart = $bytes[$r3] * 4 + 21; + my $dataLength = scalar(@bytes) - 2; + my @data = @bytes[$dataStart .. $dataLength - 1]; + my $code = $data[6] & 127; + + $self->{operation} = $POWER_MODES{((3 & $data[2]) == 1) ? 1 : 0}; + $self->{presetTemp} = $data[4] / 2.0; + $self->{operationMode} = $OPERATION_MODES{wosoFindMatch((60 & $data[2]), [8,16,12,4], 1)}; + $self->{airFlow} = $AIRFLOW{wosoFindMatch((15 & $data[3]), [7,0,1,2,6])}; + $self->{windDirectionUD}= $VERTICAL_POSITIONS{((192 & $data[2]) == 64) ? 0 : + wosoFindMatch((240 & $data[3]), [0,16,32,48], 1)}; + $self->{windDirectionLR}= $HORIZONTAL_POSITIONS{((3 & $data[12]) == 1) ? 0 : + wosoFindMatch((31 & $data[11]), [0,1,2,3,4,5,6], 1)}; + $self->{entrust} = ((12 & $data[12]) == 4) ? 1 : 0; + $self->{coolHotJudge} = $COOLHOTJUDGE_MODES{((8 & $data[8]) <= 0) ? 1 : 0}; + $self->{modelNo} = wosoFindMatch((127 & $data[0]), [0,1,2]); + $self->{isVacantProperty}= (1 & $data[10]); + + if ($code == 0) { + $self->{errorCode} = "00"; + } elsif (($data[6] & -128) <= 0) { + $self->{errorCode} = "M" . zeroPad($code, 2); + } else { + $self->{errorCode} = "E" . $code; + } + + # … hier folgt noch die Temperatur- und Electric-Verarbeitung aus JS … +my $c = 0; +my @vals; + +# Kopiere Werte aus bytes in vals (wie im JS-Code) +for (my $i = $dataStart + 19; $i < scalar(@bytes) - 2; $i++) { + $vals[$c] = $bytes[$i]; +# print "Value $c : $vals[$c]\n"; + $c++; +} + +for (my $i = 0; $i < scalar(@vals); $i += 4) { + + # Outdoor-Temperatur + if ($vals[$i] == -128 && $vals[$i + 1] == 16) { + my $index = $vals[$i + 2] & 0xFF; +# print "Index outdoorTemp : $index\n"; + $self->{outdoorTemp} = $outdoorTempList[$index]; + } + + # Indoor-Temperatur + if ($vals[$i] == -128 && $vals[$i + 1] == 32) { + my $index = $vals[$i + 2] & 0xFF; +# print "Index indoorTemp : $index\n"; + $self->{indoorTemp} = $indoorTempList[$index]; + } + + # Elektrizität (Watt oder ähnlicher Messwert) + if ($vals[$i] == -108 && $vals[$i + 1] == 16) { + my @bytes = ($vals[$i + 2], $vals[$i + 3], 0, 0); + # Bytes in eine 32-Bit-Zahl umwandeln (Little Endian) + my $uint = unpack('L', pack('C4', @bytes)); + $self->{electric} = $uint * 0.25; + } +} + + return $self; +} + +# Beende das Modul und kehre zum globalen Paket zurück +1; # Dies ist notwendig, damit das Modul korrekt geladen wird diff --git a/fhem/contrib/ch.eick/Klimaanlage/MHI_Heavy_old.txt b/fhem/contrib/ch.eick/Klimaanlage/MHI_Heavy_old.txt new file mode 100644 index 000000000..16a2c0779 --- /dev/null +++ b/fhem/contrib/ch.eick/Klimaanlage/MHI_Heavy_old.txt @@ -0,0 +1,263 @@ +defmod MHI_Heavy HTTPMOD none 0 +attr MHI_Heavy DbLogExclude .* +attr MHI_Heavy disable 0 +attr MHI_Heavy enableControlSet 0 +attr MHI_Heavy get01-1Name info_apiVer +attr MHI_Heavy get01-2Name info_command +attr MHI_Heavy get01-3Name info_deviceId +attr MHI_Heavy get01-4Name info_result +attr MHI_Heavy get01-5Name contents_airconId +attr MHI_Heavy get01-6Name contents_macAddress +attr MHI_Heavy get01-7Name info_operatorId +attr MHI_Heavy get01-8Name contents_apMode +attr MHI_Heavy get01-9Name info_timestamp +attr MHI_Heavy get01CheckAllReadings 1 +attr MHI_Heavy get01Data {"apiVer":"1.0","command":"getDeviceInfo","deviceId":"%deviceId%","operatorId":"%operatorId%","timestamp":%TIME%} +attr MHI_Heavy get01JSON . +attr MHI_Heavy get01Name 01_getDeviceInfo +attr MHI_Heavy get01URL http://%IP-MHI_Heavy%:51443/beaver/command +attr MHI_Heavy get02-10Name contents_logStat +attr MHI_Heavy get02-11Name contents_lowTemp +attr MHI_Heavy get02-12Name contents_wireless_firmVer +attr MHI_Heavy get02-13Name contents_numOfAccount +attr MHI_Heavy get02-14Name contents_remoteList_0 +attr MHI_Heavy get02-15Name contents_remoteList_1 +attr MHI_Heavy get02-16Name contents_remoteList_2 +attr MHI_Heavy get02-17Name contents_remoteList_3 +attr MHI_Heavy get02-18Name contents_timezone +attr MHI_Heavy get02-19Name contents_updatedBy +attr MHI_Heavy get02-1Name info_apiVer +attr MHI_Heavy get02-20Name contents_mcu_firmVer +attr MHI_Heavy get02-21Name contents_airconId +attr MHI_Heavy get02-22Name info_operatorId +attr MHI_Heavy get02-23Name contents_ledStat +attr MHI_Heavy get02-24Name info_timestamp +attr MHI_Heavy get02-2Name info_command +attr MHI_Heavy get02-3Name info_deviceId +attr MHI_Heavy get02-4Name contents_airconStat +attr MHI_Heavy get02-5Name contents_autoHeating +attr MHI_Heavy get02-6Name contents_expires +attr MHI_Heavy get02-7Name contents_firmType +attr MHI_Heavy get02-8Name contents_highTemp +attr MHI_Heavy get02-9Name info_result +attr MHI_Heavy get02CheckAllReadings 1 +attr MHI_Heavy get02Data {"apiVer":"1.0","command":"getAirconStat","deviceId":"%deviceId%","operatorId":"%operatorId%","timestamp":%TIME%} +attr MHI_Heavy get02JSON . +attr MHI_Heavy get02Name 02_getAirconStat +attr MHI_Heavy get02URL http://%IP-MHI_Heavy%:51443/beaver/command +attr MHI_Heavy get03CheckAllReadings 1 +attr MHI_Heavy get03Data {"apiVer":"1.0","command":"getAccountInfo","deviceId":"%deviceId%","operatorId":"%operatorId%","timestamp":%TIME%} +attr MHI_Heavy get03JSON . +attr MHI_Heavy get03Name 03_getAccountInfo +attr MHI_Heavy get03URL http://%IP-MHI_Heavy%:51443/beaver/command +attr MHI_Heavy group PV Eigenverbrauch +attr MHI_Heavy icon sani_solar +attr MHI_Heavy replacement01Mode text +attr MHI_Heavy replacement01Regex %IP-MHI_Heavy% +attr MHI_Heavy replacement01Value < MHI_Heavy IP-Address > +attr MHI_Heavy replacement02Mode text +attr MHI_Heavy replacement02Regex %deviceId% +attr MHI_Heavy replacement02Value +attr MHI_Heavy replacement03Mode text +attr MHI_Heavy replacement03Regex %operatorId% +attr MHI_Heavy replacement03Value +attr MHI_Heavy replacement04Mode expression +attr MHI_Heavy replacement04Regex %TIME% +attr MHI_Heavy replacement04Value {round(time(),0)} +attr MHI_Heavy replacement05Mode reading +attr MHI_Heavy replacement05Regex %AIRCONSTAT% +attr MHI_Heavy replacement05Value contents_airconStat +attr MHI_Heavy room Neu +attr MHI_Heavy set02-10Name contents_logStat +attr MHI_Heavy set02-11Name contents_lowTemp +attr MHI_Heavy set02-12Name contents_wireless_firmVer +attr MHI_Heavy set02-13Name contents_numOfAccount +attr MHI_Heavy set02-14Name contents_remoteList_0 +attr MHI_Heavy set02-15Name contents_remoteList_1 +attr MHI_Heavy set02-16Name contents_remoteList_2 +attr MHI_Heavy set02-17Name contents_remoteList_3 +attr MHI_Heavy set02-18Name contents_timezone +attr MHI_Heavy set02-19Name contents_updatedBy +attr MHI_Heavy set02-1Name info_apiVer +attr MHI_Heavy set02-20Name contents_mcu_firmVer +attr MHI_Heavy set02-21Name contents_airconId +attr MHI_Heavy set02-22Name info_operatorId +attr MHI_Heavy set02-23Name contents_ledStat +attr MHI_Heavy set02-24Name info_timestamp +attr MHI_Heavy set02-2Name info_command +attr MHI_Heavy set02-3Name info_deviceId +attr MHI_Heavy set02-4Name contents_airconStat +attr MHI_Heavy set02-5Name contents_autoHeating +attr MHI_Heavy set02-6Name contents_expires +attr MHI_Heavy set02-7Name contents_firmType +attr MHI_Heavy set02-8Name contents_highTemp +attr MHI_Heavy set02-9Name info_result +attr MHI_Heavy set02CheckAllReadings 1 +attr MHI_Heavy set02Data {"apiVer":"1.0","command":"setAirconStat","operatorId":"%operatorId%","deviceId":"%deviceId%","timestamp":%TIME%,"contents":{"airconId":"%operatorId%","airconStat":"%AIRCONSTAT%"}} +attr MHI_Heavy set02JSON . +attr MHI_Heavy set02Name 02_setAirconStat +attr MHI_Heavy set02NoArg 1 +attr MHI_Heavy set02ParseResponse 1 +attr MHI_Heavy set02URL http://%IP-MHI_Heavy%:51443/beaver/command +attr MHI_Heavy set03-1Name info_apiVer +attr MHI_Heavy set03-2Name info_command +attr MHI_Heavy set03-3Name info_deviceId +attr MHI_Heavy set03-4Name info_operatorId +attr MHI_Heavy set03-5Name info_result +attr MHI_Heavy set03-6Name info_timestamp +attr MHI_Heavy set03CheckAllReadings 1 +attr MHI_Heavy set03Data {"apiVer":"1.0","command":"updateAccountInfo","deviceId":"%deviceId%","operatorId":"%operatorId%","timestamp":%TIME%} +attr MHI_Heavy set03JSON . +attr MHI_Heavy set03Method PUT +attr MHI_Heavy set03Name 03_updateAccountInfo +attr MHI_Heavy set03NoArg 1 +attr MHI_Heavy set03ParseResponse 1 +attr MHI_Heavy set03URL http://%IP-MHI_Heavy%:51443/beaver/command +attr MHI_Heavy showBody 1 +attr MHI_Heavy showError 1 +attr MHI_Heavy sortby 212 +attr MHI_Heavy timeout 7 +attr MHI_Heavy userReadings contents_airconStat_Status:contents_airconStat:.* {\ + use MIME::Base64;;\ +\ + my $dev = "MHI_Heavy";;\ + my $hash = $defs{$dev};;\ +\ + # Rohdaten aus Reading holen\ + my $raw = ReadingsVal($dev,"contents_airconStat","");;\ + return if($raw eq "");;\ +\ + # Base64 decodieren\ + my $bytes = decode_base64($raw);;\ + my @b = unpack("C*", $bytes);;\ +\ + # --- Debug: Alle Bytes anzeigen ---\ + my $hex = join " ", map { sprintf "%02X", $_ } @b;;\ + Log 1, "Aircon Debug Bytes: $hex";;\ +\ + # --- Power: Byte 2, Bit 0 ---\ + my $power = ($b[2] & 0x01) ? "On" : "Off";;\ +\ + # --- Mode ---\ + # Mode aus Byte 26\ + my ($index) = grep { $b[$_] == 0x81 && $b[$_+1] == 0x04 } 0..$#b-1;;\ + my $modeByte = $b[$index+2];;\ + my %modeMap = (\ + 0x01 => "Auto",\ + 0x09 => "Cool",\ + 0x11 => "Heat",\ + 0x0D => "Fan",\ + 0x05 => "Dry",\ +);;\ +my $mode = exists $modeMap{$modeByte} ? $modeMap{$modeByte} : "Unknown";;\ +\ + # === Temperaturen ===\ + my $setTemp = $b[29] / 2;; # Solltemperatur\ +\ +\ + # === RoomTemp (Bytes 45+46 Little Endian) ===\ + my $roomTemp = (($b[46] << 8) + $b[45]) / 1585;; # Skalierung passend für App-Werte\ +\ + # === Außentemperatur (Bytes 30,31) ===\ + my $outTemp = (($b[31] << 8) + $b[33]) / 10;; # Zehntelgrad °C\ +\ + # --- Fan ---\ + my $fanbyte = $b[3] & 0x0F;;\ + my %fanmap = (\ + 0x0F => "Auto",\ + 0x08 => "1",\ + 0x09 => "2",\ + 0x0A => "3",\ + 0x0E => "4"\ +);;\ +my $fan = $fanmap{$fanbyte} // "Unknown";;\ +\ + # --- Swing / Lamellen ---\ + #-------- Vertikal------\ + my $b2 = $b[2];;\ + my $b3 = $b[3];;\ +\ +my %vertical_map = (\ + 0 => 'auto',\ + 1 => 'highest',\ + 2 => 'middle',\ + 3 => 'normal',\ + 4 => 'lowest',\ +);;\ +\ +my $vert;;\ +\ +# Erkennen anhand von Byte 2 & 3\ +if ( ($b2 & 0xC0) == 0xC0 && ($b3 & 0x80) == 0x80 ) {\ + $vert = $vertical_map{0};;\ +} else {\ + my $pos;;\ + if ( ($b3 & 0xB0) == 0x80 ) { $pos = 1;; } # highest\ + elsif ( ($b3 & 0xB0) == 0x90 ) { $pos = 2;; } # middle\ + elsif ( ($b3 & 0xB0) == 0xA0 ) { $pos = 3;; } # normal\ + elsif ( ($b3 & 0xB0) == 0xB0 ) { $pos = 4;; } # lowest\ + else { $pos = -1;; }\ +\ + $vert = defined $vertical_map{$pos} ? $vertical_map{$pos} : "unknown";;\ +}\ +\ +# ----- Horizontal ---------\ +\ +#Horizontale Lamellenstellung aus Bytes dekodieren\ +# Byte 11 und 12 enthalten die horizontale Windrichtung\ +my $b11 = $b[11];;\ +my $b12 = $b[12];;\ +\ +my %horizontal_map = (\ + 0 => 'auto',\ + 1 => 'left-left',\ + 2 => 'left-center',\ + 3 => 'center-center',\ + 4 => 'center-right',\ + 5 => 'right-right',\ + 6 => 'left-right',\ + 7 => 'right-left',\ +);;\ +\ +my $hor;;\ +\ +# Prüfen, ob Auto/Swing aktiv ist\ +if ( ($b12 & 0x03) == 0x03 ) {\ + $hor = $horizontal_map{0};; # auto\ +} else {\ + # untere 4 Bits von Byte 11 enthalten Positionscode (0x10–0x16)\ + my $pos = ($b11 & 0x0F);;\ + # 0x10 -> 0, 0x11 -> 1, ..., 0x16 -> 6\ + $hor = $horizontal_map{$pos} // "unknown";;\ +}\ + \ +# ab hier muss noch weiteres Reverseenginnering betrieben werden.\ + \ +\ + # --- Humidity ---\ + my $humidity = $b[5];; # direktes Byte, %\ +\ + # --- LED ---\ + my $led = $b[6];;\ +\ + # --- Energie kWh ---\ + my $energy = ($b[10]<<8 | $b[11])/10;; # Beispielberechnung\ +\ + # --- Readings setzen ---\ + readingsBeginUpdate($hash);;\ + readingsBulkUpdate($hash,"contents_airconStat_Power",$power);;\ + readingsBulkUpdate($hash,"contents_airconStat_Mode",$mode);;\ + readingsBulkUpdate($hash,"contents_airconStat_Fan",$fan);;\ + readingsBulkUpdate($hash,"contents_airconStat_LamelleVert",$vert);;\ + readingsBulkUpdate($hash,"contents_airconStat_LamelleHor",$hor);;\ + readingsBulkUpdate($hash,"contents_airconStat_TempRoom",sprintf("%.1f",$roomTemp));;\ + readingsBulkUpdate($hash,"contents_airconStat_TempOut",sprintf("%.1f",$outTemp));;\ + readingsBulkUpdate($hash,"contents_airconStat_TempSet",sprintf("%.1f",$setTemp));;\ + readingsBulkUpdate($hash,"contents_airconStat_Humidity",$humidity);;\ + readingsBulkUpdate($hash,"contents_airconStat_LED",$led);;\ + readingsBulkUpdate($hash,"contents_airconStat_Energy_kWh",sprintf("%.1f",$energy));;\ + readingsEndUpdate($hash,1);;\ +\ + return 1;;\ +} +attr MHI_Heavy verbose 5 \ No newline at end of file