[19/04/2026, 20:17:57] [FHEM] esp_klima_gaeste is thermostat
[19/04/2026, 20:17:57] [FHEM] esp_klima_gaeste has
[19/04/2026, 20:17:57] [FHEM] Custom Power [power]
[19/04/2026, 20:17:57] [FHEM] TargetTemperature [desired-temp]
[19/04/2026, 20:17:57] [FHEM] CurrentTemperature [measured-temp]
[19/04/2026, 20:17:57] [FHEM] CurrentHeatingCoolingState [mode]
[19/04/2026, 20:17:57] [FHEM] On [mode;mode auto,mode off]
[19/04/2026, 20:17:57] [FHEM] TargetHeatingCoolingState [mode]
[19/04/2026, 20:17:57] [FHEM] esp_klima_gaeste will try to send proactive events
[19/04/2026, 20:17:57] [FHEM] esp_klima_gaeste uses ID: 69c9027a-f33f-18b8-40fe-8f5803560ed5a2e7
2026-04-19 20:17:57 caching: esp_klima_gaeste-power: 8
[19/04/2026, 20:17:57] [FHEM] caching: Custom Power: 8 (as number; from '8')
2026-04-19 20:17:57 caching: esp_klima_gaeste-desired-temp: 23.0
2026-04-19 20:17:57 caching: esp_klima_gaeste-measured-temp: 20.8
2026-04-19 20:17:57 caching: esp_klima_gaeste-mode: off userattr EvalRead:textField-long
EvalRead
{
my $x= json2nameValue($EVENT);
my $mttqID ="StatusSNS_DS18B20-";
my %didH = ("000000505B1A" => "WPRaum"
,"00000051CAD9" => "WP_ein"
,"000000526D95" => "WP_aus"
,"000000544C2C" => "Wasser"
,"0000005310E3" => "Boiler");
my (%midH,%resH);
for my $n (grep/_Id$/,keys %{$x}) {
$n =~ m/.*-(.*?)_Id/;
$midH{$1."_Id"}= defined $didH{%{$x}{$n}} ? $didH{%{$x}{$n}} : $1."_undef"};
for my $n (grep/_Temperature$/,keys %{$x}){
$n =~ m/.*-(.*?)_Temp/;
$resH{"temp_".$midH{$1."_Id"}}= %{$x}{$n}};
\%resH}
readingList DVES_FB81CC:stat/tasmota_FB81CC/STATUS8:.* {eval AttrVal($NAME,"EvalRead","")}[19/04/2026, 19:37:47] [FHEM] esp_klima_gaeste is thermostat
[19/04/2026, 19:37:47] [FHEM] esp_klima_gaeste has
[19/04/2026, 19:37:47] [FHEM] esp_klima_gaeste will try to send proactive events
[19/04/2026, 19:37:47] [FHEM] esp_klima_gaeste uses ID: 69c9027a-f33f-18b8-40fe-8f5803560ed5a2e7
2026-04-19 19:37:47 caching: esp_klima_gaeste-mode: off
2026-04-19 19:37:47 caching: esp_klima_gaeste-measured-temp: 20.7
2026-04-19 19:39:20 caching: esp_klima_gaeste-measured-temp: 20.82026.04.19 19:46:08 5: alexa: read: [19/04/2026, 19:46:08] {
2026.04.19 19:46:08 5: alexa: read: On: {
2026.04.19 19:46:08 5: alexa: read: reading: 'mode',
2026.04.19 19:46:08 5: alexa: read: valueOn: '/heat|cool|auto/',
2026.04.19 19:46:08 5: alexa: read: valueOff: 'off',
2026.04.19 19:46:08 5: alexa: read: cmdOn: 'mode auto',
2026.04.19 19:46:08 5: alexa: read: cmdOff: 'mode off',
2026.04.19 19:46:08 5: alexa: read: device: 'esp_klima_gaeste',
2026.04.19 19:46:08 5: alexa: read: informId: 'esp_klima_gaeste-mode',
2026.04.19 19:46:08 5: alexa: read: characteristic_type: 'On',
2026.04.19 19:46:08 5: alexa: read: log: [Function: bound ] {
2026.04.19 19:46:08 5: alexa: read: debug: [Function (anonymous)],
2026.04.19 19:46:08 5: alexa: read: info: [Function (anonymous)],
2026.04.19 19:46:08 5: alexa: read: warn: [Function (anonymous)],
2026.04.19 19:46:08 5: alexa: read: error: [Function (anonymous)],
2026.04.19 19:46:08 5: alexa: read: log: [Function (anonymous)],
2026.04.19 19:46:08 5: alexa: read: prefix: 'FHEM'
2026.04.19 19:46:08 5: alexa: read: },
2026.04.19 19:46:08 5: alexa: read: characteristic: undefined
2026.04.19 19:46:08 5: alexa: read: },
2026.04.19 19:46:08 5: alexa: read: CurrentTemperature: {
2026.04.19 19:46:08 5: alexa: read: reading: 'measured-temp',
2026.04.19 19:46:08 5: alexa: read: device: 'esp_klima_gaeste',
2026.04.19 19:46:08 5: alexa: read: informId: 'esp_klima_gaeste-measured-temp',
2026.04.19 19:46:08 5: alexa: read: characteristic_type: 'CurrentTemperature',
2026.04.19 19:46:08 5: alexa: read: log: [Function: bound ] {
2026.04.19 19:46:08 5: alexa: read: debug: [Function (anonymous)],
2026.04.19 19:46:08 5: alexa: read: info: [Function (anonymous)],
2026.04.19 19:46:08 5: alexa: read: warn: [Function (anonymous)],
2026.04.19 19:46:08 5: alexa: read: error: [Function (anonymous)],
2026.04.19 19:46:08 5: alexa: read: log: [Function (anonymous)],
2026.04.19 19:46:08 5: alexa: read: prefix: 'FHEM'
2026.04.19 19:46:08 5: alexa: read: },
2026.04.19 19:46:08 5: alexa: read: characteristic: undefined,
2026.04.19 19:46:08 5: alexa: read: last_update: 1776620420,
2026.04.19 19:46:08 5: alexa: read: cached: 20.7
2026.04.19 19:46:08 5: alexa: read: },
2026.04.19 19:46:08 5: alexa: read: TargetTemperature: {
2026.04.19 19:46:08 5: alexa: read: reading: 'target',
2026.04.19 19:46:08 5: alexa: read: cmd: 'desired-temp',
2026.04.19 19:46:08 5: alexa: read: minValue: 16,
2026.04.19 19:46:08 5: alexa: read: maxValue: 30,
2026.04.19 19:46:08 5: alexa: read: device: 'esp_klima_gaeste',
2026.04.19 19:46:08 5: alexa: read: informId: 'esp_klima_gaeste-target',
2026.04.19 19:46:08 5: alexa: read: characteristic_type: 'TargetTemperature',
2026.04.19 19:46:08 5: alexa: read: log: [Function: bound ] {
2026.04.19 19:46:08 5: alexa: read: debug: [Function (anonymous)],
2026.04.19 19:46:08 5: alexa: read: info: [Function (anonymous)],
2026.04.19 19:46:08 5: alexa: read: warn: [Function (anonymous)],
2026.04.19 19:46:08 5: alexa: read: error: [Function (anonymous)],
2026.04.19 19:46:08 5: alexa: read: log: [Function (anonymous)],
2026.04.19 19:46:08 5: alexa: read: prefix: 'FHEM'
2026.04.19 19:46:08 5: alexa: read: },
2026.04.19 19:46:08 5: alexa: read: characteristic: undefined
2026.04.19 19:46:08 5: alexa: read: },
2026.04.19 19:46:08 5: alexa: read: CurrentHeatingCoolingState: {
2026.04.19 19:46:08 5: alexa: read: reading: 'mode',
2026.04.19 19:46:08 5: alexa: read: values: [ 'off:OFF', 'cool:COOL', 'heat:HEAT', 'auto:AUTO' ],
2026.04.19 19:46:08 5: alexa: read: device: 'esp_klima_gaeste',
2026.04.19 19:46:08 5: alexa: read: informId: 'esp_klima_gaeste-mode',
2026.04.19 19:46:08 5: alexa: read: characteristic_type: 'CurrentHeatingCoolingState',
2026.04.19 19:46:08 5: alexa: read: log: [Function: bound ] {
2026.04.19 19:46:08 5: alexa: read: debug: [Function (anonymous)],
2026.04.19 19:46:08 5: alexa: read: info: [Function (anonymous)],
2026.04.19 19:46:08 5: alexa: read: warn: [Function (anonymous)],
2026.04.19 19:46:08 5: alexa: read: error: [Function (anonymous)],
2026.04.19 19:46:08 5: alexa: read: log: [Function (anonymous)],
2026.04.19 19:46:08 5: alexa: read: prefix: 'FHEM'
2026.04.19 19:46:08 5: alexa: read: },
2026.04.19 19:46:08 5: alexa: read: value2homekit: { off: 'OFF', cool: 'COOL', heat: 'HEAT', auto: 'AUTO' },
2026.04.19 19:46:08 5: alexa: read: value2homekit_re: [],
2026.04.19 19:46:08 5: alexa: read: characteristic: undefined
2026.04.19 19:46:08 5: alexa: read: },
2026.04.19 19:46:08 5: alexa: read: TargetHeatingCoolingState: {
2026.04.19 19:46:08 5: alexa: read: reading: 'mode',
2026.04.19 19:46:08 5: alexa: read: values: [ 'off:OFF', 'cool:COOL', 'heat:HEAT', 'auto:AUTO' ],
2026.04.19 19:46:08 5: alexa: read: cmds: [
2026.04.19 19:46:08 5: alexa: read: 'OFF:mode+off',
2026.04.19 19:46:08 5: alexa: read: 'COOL:mode+cool',
2026.04.19 19:46:08 5: alexa: read: 'HEAT:mode+heat',
2026.04.19 19:46:08 5: alexa: read: 'AUTO:mode+auto'
2026.04.19 19:46:08 5: alexa: read: ],
2026.04.19 19:46:08 5: alexa: read: device: 'esp_klima_gaeste',
2026.04.19 19:46:08 5: alexa: read: informId: 'esp_klima_gaeste-mode',
2026.04.19 19:46:08 5: alexa: read: characteristic_type: 'TargetHeatingCoolingState',
2026.04.19 19:46:08 5: alexa: read: log: [Function: bound ] {
2026.04.19 19:46:08 5: alexa: read: debug: [Function (anonymous)],
2026.04.19 19:46:08 5: alexa: read: info: [Function (anonymous)],
2026.04.19 19:46:08 5: alexa: read: warn: [Function (anonymous)],
2026.04.19 19:46:08 5: alexa: read: error: [Function (anonymous)],
2026.04.19 19:46:08 5: alexa: read: log: [Function (anonymous)],
2026.04.19 19:46:08 5: alexa: read: prefix: 'FHEM'
2026.04.19 19:46:08 5: alexa: read: },
2026.04.19 19:46:08 5: alexa: read: value2homekit: { off: 'OFF', cool: 'COOL', heat: 'HEAT', auto: 'AUTO' },
2026.04.19 19:46:08 5: alexa: read: value2homekit_re: [],
2026.04.19 19:46:08 5: alexa: read: homekit2cmd: {
2026.04.19 19:46:08 5: alexa: read: OFF: 'mode off',
2026.04.19 19:46:08 5: alexa: read: COOL: 'mode cool',
2026.04.19 19:46:08 5: alexa: read: HEAT: 'mode heat',
2026.04.19 19:46:08 5: alexa: read: AUTO: 'mode auto'
2026.04.19 19:46:08 5: alexa: read: },
2026.04.19 19:46:08 5: alexa: read: homekit2cmd_re: [],
2026.04.19 19:46:08 5: alexa: read: characteristic: undefined
2026.04.19 19:46:08 5: alexa: read: }
2026.04.19 19:46:08 5: alexa: read: }
2026.04.19 19:46:08 5: alexa: read: [19/04/2026, 19:46:08] {"event":{"header":{"namespace":"Alexa.Discovery","name":"AddOrUpdateReport","payloadVersion":"3","messageId":"f14c132b-5ce3-48c3-98b5-ca71f056b61f"},"payload":{"endpoints":[{"endpointId":"69c9027a-f33f-18b8-40fe-8f5803560ed5a2e7","manufacturerName":"MQTT2_DEVICE","description":"n: esp_klima_gaeste, r: regeln","friendlyName":"klima gäste","displayCategories":["THERMOSTAT"],"additionalAttributes":{"manufacturer":"FHEM","model":""},"capabilities":[{"type":"AlexaInterface","interface":"Alexa","version":"3"},{"type":"AlexaInterface","interface":"Alexa.ThermostatController","version":"3","properties":{"supported":[{"name":"targetSetpoint"},{"name":"thermostatMode"}],"configuration":{"supportsScheduling":false,"supportedModes":["OFF","COOL","HEAT","AUTO"]},"proactivelyReported":true,"retrievable":true}},{"type":"AlexaInterface","interface":"Alexa.TemperatureSensor","version":"3","properties":{"supported":[{"name":"temperature"}],"proactivelyReported":true,"retrievable":true}},{"type":"AlexaInterface","interface":"Alexa.PowerController","version":"3","properties":{"supported":[{"name":"powerState"}],"proactivelyReported":true,"retrievable":true}}],"cookie":{"device":"esp_klima_gaeste","fuuid":"69c9027a-f33f-18b8-40fe-8f5803560ed5a2e7"}}],"scope":{"type":"BearerToken","token":"access-token-from-Amazon"}}}}
2026.04.19 19:46:08 5: alexa: read: [19/04/2026, 19:46:08] posting skill event
2026.04.19 19:46:08 5: alexa: read: [19/04/2026, 19:46:08] posted skill event: 202: Zitat von: betateilchen am 19 April 2026, 17:07:09Wenn ich mich recht erinnere, gibt es entweder hier im Forum oder im Wiki einen Artikel, der beschreibt, was man bei der Umstellung beachten und anpassen muss.
######################################################################
# 99_Marstek.pm
# FHEM Modul für Marstek Geräte (Venus C/E/D)
# Liest SOC, Bat-Power, PV-Power, Lade-/Entladeleistung
# Unterstützt Startwert für SOC (soc_start) und Polling
######################################################################
package main;
use strict;
use warnings;
use IO::Socket::INET;
use JSON::PP;
use Time::HiRes qw(gettimeofday);
##########################
# Modul-Initialisierung
##########################
sub Marstek_Initialize {
my ($hash) = @_;
$hash->{DefFn} = "Marstek_Define";
$hash->{UndefFn} = "Marstek_Undef";
$hash->{AttrFn} = "Marstek_Attr";
$hash->{GetFn} = "Marstek_Get";
$hash->{NotifyFn} = "Marstek_Notify";
$hash->{AttrList} = "interval";
}
##########################
# Define
##########################
sub Marstek_Define {
my ($hash, $def) = @_;
my @args = split(" ", $def);
return "Usage: define <name> Marstek <IP> <PORT>" unless @args == 4;
$hash->{IP} = $args[2];
$hash->{PORT} = $args[3];
$hash->{INTERVAL} = 60;
InternalTimer(gettimeofday()+1, sub { Marstek_Poll($hash) }, 0);
return undef;
}
##########################
# Undef
##########################
sub Marstek_Undef {
my ($hash) = @_;
RemoveInternalTimer($hash);
return undef;
}
##########################
# Attribute
##########################
sub Marstek_Attr {
my ($cmd, $name, $attrName, $attrValue) = @_;
my $hash = $defs{$name};
if ($attrName eq "interval" && $attrValue =~ /^\d+$/) {
$hash->{INTERVAL} = $attrValue;
}
return undef;
}
##########################
# Notify
##########################
sub Marstek_Notify {
my ($hash, $dev) = @_;
return undef;
}
##########################
# Gemeinsame Request-Funktion
##########################
sub Marstek_DoRequest {
my ($hash, $method, $units) = @_;
my $success = 0;
my $sock = IO::Socket::INET->new(
PeerAddr => $hash->{IP},
PeerPort => $hash->{PORT},
Proto => 'udp',
Timeout => 2
);
if ($sock) {
my $req = {
id => 1,
method => $method,
params => { id => 0 }
};
my $json = encode_json($req);
$sock->send($json);
my $resp = "";
eval {
local $SIG{ALRM} = sub { die "Timeout\n" };
alarm 2;
$sock->recv($resp, 4096);
alarm 0;
};
if ($@ && $@ ne "Timeout\n") {
Log 3, "Marstek Poll recv error ($method): $@";
}
my $data;
eval { $data = decode_json($resp) };
if ($@) {
Log 3, "Marstek JSON decode error ($method): $@";
}
if ($data && $data->{result}) {
for my $key (keys %{$units}) {
if (exists $data->{result}{$key}) {
readingsSingleUpdate(
$hash,
$key,
$data->{result}{$key} . " " . $units->{$key},
1
);
$success = 1; # mark success if at least one reading updated
}
}
}
close($sock);
}
else {
readingsSingleUpdate($hash, "state", "timeout", 1);
}
return $success;
}
##########################
# Polling
##########################
sub Marstek_Poll {
my ($hash) = @_;
return unless $hash;
my $success = 0;
eval {
$success ||= Marstek_DoRequest($hash, "ES.GetStatus", {
bat_soc => "%",
bat_cap => "Wh",
pv_power => "W",
ongrid_power => "W",
offgrid_power => "W",
total_pv_energy => "Wh",
total_grid_output_energy => "Wh",
total_grid_input_energy => "Wh",
total_load_energy => "Wh",
});
$success ||= Marstek_DoRequest($hash, "Bat.GetStatus", {
id => "",
soc => "%",
charge_flag => "",
dischrg_flag => "",
bat_temp => "C",
bat_capacity => "Wh",
rated_capacity => "Wh",
});
$success ||= Marstek_DoRequest($hash, "Wifi.GetStatus", {
id => "",
wifi_mac => "",
ssid => "",
rssi => "",
sta_ip => "",
});
$success ||= Marstek_DoRequest($hash, "ES.GetMode", {
id => "",
mode => "",
ct_state => "",
total_power => "W",
input_energy => "Wh",
output_energy => "Wh",
});
};
if ($@) {
Log 3, "Marstek Poll error: $@";
}
# State korrekt setzen
readingsSingleUpdate($hash, "state", $success ? "ok" : "timeout", 1);
InternalTimer(
gettimeofday() + ($hash->{INTERVAL} // 60),
sub { Marstek_Poll($hash) },
0
);
}
##########################
# Get
##########################
sub Marstek_Get {
my ($hash, $name, $opt, @args) = @_;
return "\"get $name\" needs at least one argument" unless(defined($opt));
if ($opt eq "update") {
Marstek_Poll($hash);
return "Update triggered";
}else {
# IMPORTANT! This defines the list of possible commands
my $list = "update:noArg";
return "Unknown argument $opt, choose one of $list";
}
return -1;
}
1;