.
Hallo an alle Nutzer dieses Treibers,
der seinerzeit für mich selbst entwickelte TP-Link-Treiber wird inzwischen scheinbar doch von mehr Usern genutzt, als ursprünglich vermutet. Deshalb finde ich es gut, dass einige von euch, diesen für ihre Bedürfnisse angepasst haben - was mit etwas Programmierwissen ja auch kein Hexenwerk ist.
Da ich aktl. keine Zeit habe, um diesen Treiber weiter zu entwickeln und zu supporten, möchte ich die User bitten, die hier Anpassungen vornehmen, diese auch der Allgemeinheit zur Verfügung zu stellen. Entweder in dem sie ihre Änderungen hier posten oder am besten gleich ihr komplettes TCL-Skript als neue Treiberversion hier zur Verfügung stellen.
Dabei viel Erfolg - Gruß
Thomas M.
HM-Anbindung für TP-Link-WLAN-Steckdosen HS1xx und -Leuchtmittel LB1xx (V5.3)
Moderator: Co-Administratoren
-
- Beiträge: 18
- Registriert: 02.10.2021, 18:04
- System: CCU und Access Point
- Hat sich bedankt: 3 Mal
Re: Anpassung / Weiterentwicklung der HM-Anbindung für TP-Link-WLAN-Steckdosen HS1xx und -Leuchtmittel LB1xx
Leider kann ich so garnix dazu beitragen, da ich was programmieren angeht es gerade so hinbekommen habe die beschriebenen Details anzupassen. Bei mir laufen derzeit 2 TP Link HS100 und 2 TP Link KP115 (Die scheint es ja auch nicht mehr zu geben) Eine der beiden KP115 fällt auch mindestens einmal am Tag aus dem Wlan dann geht nix mehr außer ausstecken Moment warten und wieder einstecken.HM42 hat geschrieben: ↑23.08.2022, 13:02.
Hallo an alle Nutzer dieses Treibers,
der seinerzeit für mich selbst entwickelte TP-Link-Treiber wird inzwischen scheinbar doch von mehr Usern genutzt, als ursprünglich vermutet. Deshalb finde ich es gut, dass einige von euch, diesen für ihre Bedürfnisse angepasst haben - was mit etwas Programmierwissen ja auch kein Hexenwerk ist.
Da ich aktl. keine Zeit habe, um diesen Treiber weiter zu entwickeln und zu supporten, möchte ich die User bitten, die hier Anpassungen vornehmen, diese auch der Allgemeinheit zur Verfügung zu stellen. Entweder in dem sie ihre Änderungen hier posten oder am besten gleich ihr komplettes TCL-Skript als neue Treiberversion hier zur Verfügung stellen.
Dabei viel Erfolg - Gruß
Thomas M.
Auch aus diesem grunde werde ich in absehbarer Zeit die TP Link steckdosen durch Hmip-PS und PSM ersetzen
Meine derzeitige TCL sieht so aus:
Code: Alles auswählen
#******************************************************************************
# tplsh.tcl (TP-Link SmartHome)
#******************************************************************************
#.... Author : Marquard, Thomas - alias: HM42
#.... Version : see: scriptVersInfo
#.... Comment : TCL script for data exchange between Homematic CCUs
# and TP-Link Wi-Fi Smart Home devices,
# e.g.: HS100, HS110, LB130 (tested)
#
#.... History : 2018-11-25, Vers. 1.0, basic version
#
# 2018-12-03, Vers. 2.0, change from button to
# switch mode; reading ("readdata") of current
# voltage, power, energy values from
# HS110, HW version 1
#
# 2019-01-01, Vers. 3.0, extension for
# HS110, HW version 2
#
# 2019-02-14, Vers. 4.0 beta, extension and reprogramming
# for TP-Link bulbs LB100, LB110, LB120, LB130
#
# 2020-05-02, Vers. 5.2, error handling optimized
# 2020-05-04, Vers. 5.3, relay_state for HS1XX always read
# when script is called from CUxD; so 'info' command called via
# CUxD timer updates the switch state in CUXD
#
# Based on Python script from Lubomir Stroetmann
# Copyright 2016 softScheck GmbH
# see: https://www.softscheck.com/en/
# reverse-engineering-tp-link-hs110/
#
# Licensed under the Apache License,
# Version 2.0 (the "License");
# you may not use this file except in compliance
# with the License.
#
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to
# in writing, software distributed under the License
# is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
# either express or implied.
# See the License for the specific language governing
# permissions and limitations under the License.
#
#******************************************************************************
load tclrega.so
global scriptVersInfo
global copyRight
global env
set versInfo {Script: 'tplsh.tcl', Version: 5.3, 2020-05-04}
set copyright {Copyright: Thomas Marquard / Lubomir Stroetmann, softScheck GmbH (...2020)}
exec clear >@ stdout
puts ""
puts $versInfo
puts $copyright
puts ""
proc usagePuts {} {
puts ""
puts "USAGE: tclsh /usr/local/etc/config/addons/tplsh/tplsh.tcl <hostname or ip-address> <command> <bulb_para>"
puts ""
puts "COMMAND (plug sockets): \[info|on|off|toggle|readdata\]"
puts "COMMAND (bulbs): \[info|dim|hue|on|off|sat|toggle|setdata <bulb_para>\]"
puts "BULB_PARA: \[o:<0|1>,h:<0...360>,s:<0...100>,d:<0...100>,c:<0|2500...9000>\]"
puts ""
} ; # usagePuts
proc handleErrorMessage {message} {
set regaCmd "
object objVar = dom.GetObject(ID_SYSTEM_VARIABLES).Get(\"FehlerMeldung\");
if (!objVar) \{
object objSysVarIDs = dom.GetObject(ID_SYSTEM_VARIABLES);
objVar = dom.CreateObject(OT_VARDP);
objSysVarIDs.Add(objVar.ID());
objVar.Name(\"FehlerMeldung\");
objVar.ValueUnit(\"\");
objVar.DPInfo(\"\");
objVar.ValueType(ivtString);
objVar.ValueSubType(istChar8859);
dom.RTUpdate(false);
\}
if (dom.GetObject(\"FehlerMeldung\").State() <> \"tplsh.tcl, $message\")
\{
dom.GetObject(\"FehlerMeldung\").State(\"tplsh.tcl, $message\");
\}
"
rega_script $regaCmd
} ; # handleErrorMessage
# Encryption and Decryption of TP-Link Smart Home Protocol
# XOR Autokey Cipher with starting key = 171
proc encrypt {message} {
set key 171
set result [binary format I [string length $message]]
for {set charIdx 0} {$charIdx < [string length $message]} {incr charIdx} {
set char [string index $message $charIdx]
scan $char %c ascii
set a [expr $key ^ $ascii]
set key $a
append result [binary format c $a]
}
return $result
} ; # encrypt
proc decrypt {message} {
set key 171
set result ""
for {set charIdx 4} {$charIdx < [string length $message]} {incr charIdx} {
set char [string index $message $charIdx]
scan $char %c ascii
set a [expr $key ^ $ascii]
set key $ascii
append result [binary format c $a]
}
return $result
} ; # decrypt
proc extractFromJsonString {answer valueName valueFormat} {
set startIdx [expr [string first \"$valueName\": $answer] + 1]
set startValueIdx [expr [string first ":" $answer $startIdx] + 1]
set commaIdx [expr [string first "," $answer $startValueIdx]]
set closeBraceIdx [expr [string first "\}" $answer $startValueIdx]]
if {$commaIdx > -1} {
if {$commaIdx > $closeBraceIdx} {
set endValueIdx [expr $closeBraceIdx - 1]
} else {
set endValueIdx [expr $commaIdx - 1]
}
} else {
set endValueIdx [expr $closeBraceIdx - 1]
}
if {$startIdx > 0 && $startValueIdx > 0 && $endValueIdx >= $startValueIdx} {
set returnValue [string range $answer $startValueIdx $endValueIdx]
} else {
set returnValue ""
}
regsub -all "\"" $returnValue "" returnValue
if {[string is double -strict $returnValue] && [string length $valueFormat] > 0} {
if { [catch {set returnValue [format $valueFormat $returnValue]}] } {
set msg "INTERNAL ERROR: Wrong format `$valueFormat` for value `$valueName` !"
handleErrorMessage $msg
puts ""
puts $msg
puts ""
usagePuts
exit
}
}
puts "$valueName= $returnValue"
return "set $valueName \"$returnValue\""
} ; # extractFromJsonString
proc writeAndReadTplDevice {hostnameOrIpAddressT commandStringT} {
set port 9999
if { [catch {set sock [socket $hostnameOrIpAddressT $port]}] } {
set msg "ERROR: Cannot open port `$port` at `$hostnameOrIpAddressT` !"
handleErrorMessage $msg
puts ""
puts $msg
puts ""
usagePuts
exit
}
fconfigure $sock -encoding binary -blocking 0
set encryptedCommandString [encrypt $commandStringT]
puts -nonewline $sock $encryptedCommandString
flush $sock
puts ""
puts "MESSAGE SENT:"
puts $commandStringT
set answerT ""
for {set waitIdx 0} {$waitIdx < 20} {incr waitIdx} {
append answerT [read $sock]
if { [string length $answerT] > 4 } {
break
}
set vwaitEnd 0
after 50 set vwaitEnd 1
vwait vwaitEnd
}
close $sock
set answerT [decrypt $answerT]
puts ""
puts "MESSAGE RECEIVED:"
puts $answerT
puts ""
return $answerT
} ; # writeAndReadTplDevice
########## MAIN SCRIPT ######################################################################
set para_error 0
if {$argc >= 2} {
set hostnameOrIpAddress [string trim [lindex $argv 0]]
set command [string trim [lindex $argv 1]]
if {$command == ""} {
set para_error 1
}
if {$argc > 2} {
set cmdParas [string trim [lindex $argv 2]]
regsub -all "," $cmdParas " " cmdParas
} else {
set cmdParas ""
}
} else {
set para_error 1
}
if {$para_error} {
set msg "ERROR: One or two program parameters missing !"
handleErrorMessage $msg
puts ""
puts $msg
puts ""
usagePuts
exit
}
if {[catch {set cuxdDevice $::env(CUXD_DEVICE)}]} {
set cuxdDevice ""
}
if {[catch {set cuxdChannel $::env(CUXD_CHANNEL)}]} {
set cuxdChannel ""
}
if {[catch {set cuxdTrigChnIdx $::env(CUXD_TRIGGER_CH)}]} {
set cuxdTrigChnIdx 0
}
set answer [writeAndReadTplDevice $hostnameOrIpAddress {{"system":{"get_sysinfo":{}}}}]
puts "EXTRACTED DEVICE VALUES:"
eval [extractFromJsonString $answer sw_ver ""]
eval [extractFromJsonString $answer hw_ver ""]
eval [extractFromJsonString $answer model ""]
eval [extractFromJsonString $answer alias ""]
eval [extractFromJsonString $answer on_off "%d"]
eval [extractFromJsonString $answer hue "%d"]
eval [extractFromJsonString $answer saturation "%d"]
eval [extractFromJsonString $answer brightness "%d"]
eval [extractFromJsonString $answer color_temp "%d"]
eval [extractFromJsonString $answer relay_state "%d"]
if {($cuxdChannel != "") && (($relay_state == 0) || ($relay_state == 1))} {
set regaCmd "
dom.GetObject(\"CUxD.${cuxdChannel}.SET_STATE\").State($relay_state);
"
rega_script $regaCmd
}
if {$command == "info"} {
usagePuts
exit
}
set modelShort [string range $model 0 4]
set commandString ""
if {$modelShort == "HS100" || $modelShort == "HS110"|| $modelShort == "KP115"} {
if {($relay_state != 0) && ($relay_state != 1)} {
set msg "ERROR: Bad value `$relay_state` for `relay_state` read from device !"
handleErrorMessage $msg
puts ""
puts $msg
puts ""
exit
}
set relay_state_new -1
switch $command {
on {
set relay_state_new 1
}
off {
set relay_state_new 0
}
readdata {
set commandString "{\"emeter\":{\"get_realtime\":{}}}"
set relay_state_new $relay_state
}
toggle {
switch $relay_state {
0 {
set relay_state_new 1
}
1 {
set relay_state_new 0
}
}
}
}
if {($relay_state_new == 0) || ($relay_state_new == 1)} {
if {$cuxdChannel != ""} {
set regaCmd "
dom.GetObject(\"CUxD.${cuxdChannel}.SET_STATE\").State($relay_state_new);
"
rega_script $regaCmd
}
if {$command != "readdata"} {
if {$relay_state_new != $relay_state} {
set commandString "{\"system\":{\"set_relay_state\":{\"state\":$relay_state_new}}}"
set relay_state $relay_state_new
} else {
puts ""
puts "NOTHING TO DO !"
puts ""
exit
}
}
}
} else {
if {$modelShort == "LB100" || $modelShort == "LB110" || $modelShort == "LB120" || $modelShort == "LB130"} {
set forceOnFirst 0
set switchOff 0
switch $command {
colortemp {
set color_temp [expr $color_temp + 500]
if {$color_temp < 2500 || $color_temp > 9000} {
set color_temp 2500
}
set forceOnFirst 1
set commandString "{\"smartlife.iot.smartbulb.lightingservice\":{\"transition_light_state\":{\"color_temp\":$color_temp}}}"
}
dim {
set brightness [expr $brightness + 10]
if {$brightness > 100} {
set brightness 10
}
if {$brightness == 0} {
set commandString "{\"smartlife.iot.smartbulb.lightingservice\":{\"transition_light_state\":{\"on_off\":0}}}"
} else {
set forceOnFirst 1
set commandString "{\"smartlife.iot.smartbulb.lightingservice\":{\"transition_light_state\":{\"brightness\":$brightness}}}"
}
}
hue {
set hue [expr $hue + 36]
if {$hue > 360} {
set hue 36
}
set forceOnFirst 1
set commandString "{\"smartlife.iot.smartbulb.lightingservice\":{\"transition_light_state\":{\"hue\":$hue,\"color_temp\":0}}}"
}
on {
set commandString "{\"smartlife.iot.smartbulb.lightingservice\":{\"transition_light_state\":{\"on_off\":1}}}"
}
off {
set commandString "{\"smartlife.iot.smartbulb.lightingservice\":{\"transition_light_state\":{\"on_off\":0}}}"
}
sat {
set saturation [expr $saturation + 10]
if {$saturation > 100} {
set saturation 10
}
set forceOnFirst 1
set commandString "{\"smartlife.iot.smartbulb.lightingservice\":{\"transition_light_state\":{\"saturation\":$saturation,\"color_temp\":0}}}"
}
setdata {
set cmdSubString ""
if {[string length $cmdParas] == 0} {
set msg "ERROR: third parameter (BULB_PARA) for `setdata` command missing !"
handleErrorMessage $msg
puts ""
puts $msg
puts ""
usagePuts
exit
} else {
set color_temp_T -1
foreach {cmdPara} $cmdParas {
if {[string length $cmdPara] > 2} {
set cmdParaId [string range $cmdPara 0 1]
set cmdParaVal [string range $cmdPara 2 255]
if {[string is double -strict $cmdParaVal]} {
switch $cmdParaId {
c: {
if {$cmdParaVal <= 0} {
set cmdParaVal 0
} else {
if {$cmdParaVal < 2500} {
set cmdParaVal 2500
} else {
if {$cmdParaVal > 9000} {
set cmdParaVal 9000
}
}
}
set forceOnFirst 1
set color_temp_T $cmdParaVal
}
d: {
if {$cmdParaVal < 0 || $cmdParaVal > 100} {
set cmdParaVal 100
}
set brightness $cmdParaVal
if {$brightness == 0} {
set switchOff 1
} else {
set forceOnFirst 1
append cmdSubString "\"brightness\":$brightness,"
}
}
h: {
if {$cmdParaVal < 0 || $cmdParaVal > 360} {
set cmdParaVal 0
}
set forceOnFirst 1
append cmdSubString "\"hue\":$cmdParaVal,"
set color_temp_T 0
}
o: {
if {$cmdParaVal < 0 || $cmdParaVal > 1} {
set cmdParaVal 1
}
append cmdSubString "\"on_off\":$cmdParaVal,"
}
s: {
if {$cmdParaVal < 0 || $cmdParaVal > 100} {
set cmdParaVal 0
}
set forceOnFirst 1
append cmdSubString "\"saturation\":$cmdParaVal,"
set color_temp_T 0
}
}
}
}
}
if {$color_temp_T >= 0} {
append cmdSubString "\"color_temp\":$color_temp_T,"
}
if {[string length $cmdSubString] > 0} {
set lastCharIdx [expr [string length $cmdSubString] - 1]
if {[string range $cmdSubString $lastCharIdx $lastCharIdx] == ","} {
set cmdSubString [string range $cmdSubString 0 [expr $lastCharIdx - 1]]
}
set commandString "{\"smartlife.iot.smartbulb.lightingservice\":{\"transition_light_state\":{"
append commandString $cmdSubString
append commandString "}}}"
}
}
}
toggle {
switch $on_off {
0 {
set commandString "{\"smartlife.iot.smartbulb.lightingservice\":{\"transition_light_state\":{\"on_off\":1}}}"
}
1 {
set commandString "{\"smartlife.iot.smartbulb.lightingservice\":{\"transition_light_state\":{\"on_off\":0}}}"
}
default {
set commandString ""
}
}
}
}
if {$forceOnFirst && !$on_off} {
puts ""
puts "Need to switch bulb ON before bulb parameter setting..."
set onCommandString "{\"smartlife.iot.smartbulb.lightingservice\":{\"transition_light_state\":{\"on_off\":1}}}"
set answer [writeAndReadTplDevice $hostnameOrIpAddress $onCommandString]
}
# switch off when setdata dim value = 0 ...
if {$switchOff} {
set commandString "{\"smartlife.iot.smartbulb.lightingservice\":{\"transition_light_state\":{\"on_off\":0}}}"
}
}
}
if {$commandString == ""} {
set msg "ERROR: Missing or wrong command `$command` !"
handleErrorMessage $msg
puts ""
puts $msg
puts ""
usagePuts
exit
}
set answer [writeAndReadTplDevice $hostnameOrIpAddress $commandString]
if {$command == "readdata"} {
if {[catch {set sourceChnName $::env(CUXD_CHANNEL)}]} {
set msg "ERROR: No channel specified in environment variable `CUXD_CHANNEL` (script not called from CUxD) !"
handleErrorMessage $msg
puts ""
puts $msg
puts ""
exit
}
if {$modelShort == "KP115"} {
# readdata for HS110, HW version 1 ...
eval [extractFromJsonString $answer current "%.2f"]
eval [extractFromJsonString $answer voltage "%.2f"]
eval [extractFromJsonString $answer power "%.2f"]
eval [extractFromJsonString $answer total "%.3f"]
# readdata for HS110, HW version 2 ...
eval [extractFromJsonString $answer current_ma "%f"]
eval [extractFromJsonString $answer voltage_mv "%f"]
eval [extractFromJsonString $answer power_mw "%f"]
eval [extractFromJsonString $answer total_wh "%f"]
if {[string is double -strict $current_ma]} {
# scale data for HS110, HW version 2 ...
set current [format "%.2f" [expr $current_ma / 1000.]]
set voltage [format "%.2f" [expr $voltage_mv / 1000.]]
set power [format "%.2f" [expr $power_mw / 1000.]]
set total [format "%.3f" [expr $total_wh / 1000.]]
}
puts "Voltage: $voltage V / Current: $current A / Power: $power W / Energy: $total Wh"
puts ""
set regaCmd "
string strQuellKanalBez;
object objDP = dom.GetObject(\"CUxD.${sourceChnName}.CMD_RETS\");
strQuellKanalBez = (dom.GetObject(objDP.Channel())).Name();
object objVar = dom.GetObject(ID_SYSTEM_VARIABLES).Get(\"Strom_\" # strQuellKanalBez);
if (!objVar) \{
object objSysVarIDs = dom.GetObject(ID_SYSTEM_VARIABLES);
objVar = dom.CreateObject(OT_VARDP);
objSysVarIDs.Add(objVar.ID());
objVar.Name(\"Strom_\" # strQuellKanalBez);
objVar.ValueUnit(\"A\");
objVar.ValueType(ivtFloat);
objVar.ValueSubType(istGeneric);
objVar.DPInfo(\"tp-Link Steckdose\");
objVar.ValueMin(0);
objVar.ValueMax(20);
objVar.State(0);
dom.RTUpdate(false);
\}
objVar.State($current);
object objVar = dom.GetObject(ID_SYSTEM_VARIABLES).Get(\"Spannung_\" # strQuellKanalBez);
if (!objVar) \{
object objSysVarIDs = dom.GetObject(ID_SYSTEM_VARIABLES);
objVar = dom.CreateObject(OT_VARDP);
objSysVarIDs.Add(objVar.ID());
objVar.Name(\"Spannung_\" # strQuellKanalBez);
objVar.ValueUnit(\"V\");
objVar.ValueType(ivtFloat);
objVar.ValueSubType(istGeneric);
objVar.DPInfo(\"tp-Link Steckdose\");
objVar.ValueMin(0);
objVar.ValueMax(250);
objVar.State(0);
dom.RTUpdate(false);
\}
objVar.State($voltage);
object objVar = dom.GetObject(ID_SYSTEM_VARIABLES).Get(\"Leistung_\" # strQuellKanalBez);
if (!objVar) \{
object objSysVarIDs = dom.GetObject(ID_SYSTEM_VARIABLES);
objVar = dom.CreateObject(OT_VARDP);
objSysVarIDs.Add(objVar.ID());
objVar.Name(\"Leistung_\" # strQuellKanalBez);
objVar.ValueUnit(\"W\");
objVar.ValueType(ivtFloat);
objVar.ValueSubType(istGeneric);
objVar.DPInfo(\"tp-Link Steckdose\");
objVar.ValueMin(0);
objVar.ValueMax(100000);
objVar.State(0);
dom.RTUpdate(false);
\}
objVar.State($power);
object objVar = dom.GetObject(ID_SYSTEM_VARIABLES).Get(\"Energie_\" # strQuellKanalBez);
if (!objVar) \{
object objSysVarIDs = dom.GetObject(ID_SYSTEM_VARIABLES);
objVar = dom.CreateObject(OT_VARDP);
objSysVarIDs.Add(objVar.ID());
objVar.Name(\"Energie_\" # strQuellKanalBez);
objVar.ValueUnit(\"kWh\");
objVar.ValueType(ivtFloat);
objVar.ValueSubType(istGeneric);
objVar.DPInfo(\"tp-Link Steckdose\");
objVar.ValueMin(0);
objVar.ValueMax(100000);
objVar.State(0);
dom.RTUpdate(false);
\}
objVar.State($total);
"
rega_script $regaCmd
}
}
# end
Re: HM-Anbindung für TP-Link-WLAN-Steckdosen HS1xx und -Leuchtmittel LB1xx (V5.3)
Guten Morgen!
Ist es möglich eine TP-Link P115 Steckdose ebenfalls mit der CCU3, auf die selbe Art und Weise zu koppeln?
https://www.amazon.de/TP-Link-Tapo-P115 ... NrPXRydWU=
MFG
Ist es möglich eine TP-Link P115 Steckdose ebenfalls mit der CCU3, auf die selbe Art und Weise zu koppeln?
https://www.amazon.de/TP-Link-Tapo-P115 ... NrPXRydWU=
MFG
-
- Beiträge: 221
- Registriert: 31.07.2011, 17:37
- System: CCU
- Wohnort: Czech Rep.
- Hat sich bedankt: 85 Mal
- Danksagung erhalten: 14 Mal
Re: HM-Anbindung für TP-Link-WLAN-Steckdosen HS1xx und -Leuchtmittel LB1xx (V5.3)
Hallo, haben Sie (oder jemand anderes) es endlich geschafft, die Tapo P100 Steckdosen mit diesem Skript zum Laufen zu bringen?Micki hat geschrieben: ↑27.08.2020, 16:00Hallo zusammen,
ich bin der Installationsanleitung gefolgt, scheitere ich aber immer noch an einer Fehlermeldung:
tplsh.tcl, ERROR: Cannot open port `9999` at 192.168.0.183
Ich muss allerdings zugeben, das die Steckdosen die ich einsetze P100 sind.
Die Steckdosen lassen sich anpingen und sind im Netzwerk erreichbar. Mit der zugehörigen App sind diese auch voll funktionsfähig.
Ich habe im Forum Beiträge gefunden die besagen, das diese Fehlermeldung nur bedeutet, dass das Gerät nicht erreichbar ist.
Nutzen diese Steckdose evtl einen anderen Port? Hat hier vielleicht schon mal jemand probiert diese anzusteuern?
Micki
Ich habe jahrelang HS100- und HS110-Steckdosen in Homemtic verwendet, aber sie sind nicht mehr erhältlich, und die Ausgangsrelais einiger dieser Steckdosen begannen zu kleben".