Dyson AM09 Hot+Cool Steuerung via Logitech Harmony und Homekit

Begonnen von LordVoodoo, 14 Oktober 2020, 16:55:12

Vorheriges Thema - Nächstes Thema

LordVoodoo

Hallo,

möchte hier meine Implementierung teilen, wie ich einen Dyson AM09 per Logitech Harmony steuere und dies auch in HomeBridge abbilden konnte. Lediglich die Heiz-Funktion via Homebridge habe ich nicht geschafft, auch weil die Thermostatabbildung recht kompliziert ist und Home/Eve sich hier deutlicher unterscheiden.

Vielleicht nützt dem ein oder anderen diese Integration. Bin mir sicher, man kann das auch eleganter und mit weniger Source-Code schreiben.

Mit dieser Umsetzung konnte ich:

  • Temperatur zwischen 1°C nd 37°C einstellen
  • Ventilator in 10 Schritten zwischen 1 und 10 einstellen
  • Dynamisch zwischen Hot/Cool wechseln, je nach dem ob ich Temperatur oder Geschwindigkeit anpasste
  • Drehung einschalten / ausschalten (Oszilieren)
  • Regeln implementierung in der Form: "Wenn Temperatur >= 25°C und Bewegung im Wohnzimmer, dann schalte Ventilator ein auf Stufe 2 und aktiviere Drehung."

Es gibt folgende DUMMY-Grundgeräte:


  • Wohnzimmer_Ventilator als Klammer über beide Teilgeräte
  • Wohnzimmer_Dyson_Heizung zur Steuerung der Hot-Funktion
  • Wohnzimmer_Dyson_Ventilator zur Steuerung der Cool-Funktion

Wohnzimmer_Ventilator

define Wohnzimmer_Ventilator dummy
attr Wohnzimmer_Ventilator readingList pct temperature device state
attr Wohnzimmer_Ventilator setList pct:slider,0,10,100 temperature:slider,1,1,37 on off device:PowerToggle,FanSpeedUp,FanSpeedDown,Oscillate,Cool,Heat
attr Wohnzimmer_Ventilator userReadings CoolingHeatingState {if(ReadingsVal($NAME,"state","") eq "off") {return "OFF"} elsif (ReadingsVal($NAME,"currentMode","") eq "Cooling") {return "COOL"} elsif (ReadingsVal($NAME,"currentMode","") eq "Heating") {return "HEAT"} else {return "OFF"}}
attr Wohnzimmer_Ventilator webCmd on:off:pct:temperature
attr Wohnzimmer_Ventilator genericDeviceType Fan


Als Homebridge-Mapping habe ich folgendes hinterlegt:

clear
model=Dyson
homeKitFanType=Fan2
On=state,valueOn=on,valueOff=off,cmdOn=on,cmdOff=off
RotationSpeed=pct,minValue=0,maxValue=100,minStep=10,cmd=pct
SwingMode=oscillating,values=on:SWING_ENABLED;;off:SWING_DISABLED,cmdOn=device+Oscillate,cmdOff=device+Oscillate


Wohnzimmer_Dyson_Ventilator

Die Attribute ir_interface und ir_device enthalten den Logitech Harmony Hub und den Gerätenamen auf Device-Command-Ebene.

define Wohnzimmer_Dyson_Ventilator dummy
attr Wohnzimmer_Dyson_Ventilator userattr ir_device ir_interface
attr Wohnzimmer_Dyson_Ventilator setList on off oscillate target_speed:slider,10,10,100 command:PowerToggle,Cool,FanSpeedDown,FanSpeedUp,Oscillate,AdjustSpeed mode:Heat,Cool
attr Wohnzimmer_Dyson_Ventilator ir_device Dyson
attr Wohnzimmer_Dyson_Ventilator ir_interface Interface_Harmony_Wohnzimmer
attr Wohnzimmer_Dyson_Ventilator readingList state target_speed oscillate command pct
attr Wohnzimmer_Dyson_Ventilator webCmd on:off:oscillate:target_speed:command
attr Wohnzimmer_Dyson_Ventilator genericDeviceType Fan



clear
model=Dyson
homeKitFanType=Fan2
On=state,valueOn=on,valueOff=off,cmdOn=on,cmdOff=off
RotationSpeed=pct,minValue=0,maxValue=100,minStep=10,cmd=pct
SwingMode=oscillating,values=on:SWING_ENABLED;;off:SWING_DISABLED,cmdOn=device+Oscillate,cmdOff=device+Oscillate


Wohnzimmer_Dyson_Heizung

define Wohnzimmer_Dyson_Heizung dummy
attr Wohnzimmer_Dyson_Heizung userattr ir_device ir_interface
attr Wohnzimmer_Dyson_Heizung setList on off target_temperature:slider,1,1,37 command:PowerToggle,Heat,TempCooler,TempHotter,AdjustTemperature mode:Heat,Cool
attr Wohnzimmer_Dyson_Heizung ir_device Dyson
attr Wohnzimmer_Dyson_Heizung ir_interface Interface_Harmony_Wohnzimmer
attr Wohnzimmer_Dyson_Heizung readingList state state target_temperature oscillate command mode
attr Wohnzimmer_Dyson_Heizung webCmd on:off:target_temperature:command
attr Wohnzimmer_Dyson_Heizung genericDeviceType thermostat


=> Damit sind die Grundgeräte fertig, es folgen die Logikgeräte:

Rekursive Steuerung der Einzelgeräte

Es wird ein NOTIFY benötigt, wobei "a" und "b" nur Platzhalter bei der Anlage sind.:

define Wohnzimmer_Dyson_Aktion notify a b

(Wohnzimmer_Dyson_Ventilator:.*|Wohnzimmer_Dyson_Heizung:.*) {
my $source_device = $NAME;
my $heating_device = "Wohnzimmer_Dyson_Heizung";
my $cooling_device = "Wohnzimmer_Dyson_Ventilator";
my $ir_device = AttrVal($source_device, "ir_device", "");
my $ir_interface = AttrVal($source_device, "ir_interface", "");
my $debug_msg;
my $current_state = ReadingsVal($NAME, "state", "");
my $ir_cmd = "initialized";
my $timer1 = 0.1;
my $timer2 = 0.8;
my $timer3 = 1.2;
my $timer4 = 3;

my $current_mode = ReadingsVal($NAME, "mode", "");
my $current_speed = int(ReadingsVal($cooling_device, "pct", 0));
my $target_speed = int(ReadingsVal($cooling_device, "target_speed", 0));
my $current_temp = int(ReadingsVal($heating_device, "temperature", 0));
my $target_temp = int(ReadingsVal($heating_device, "target_temperature", 0));

my $current_state = "off";

if (ReadingsVal($heating_device, "state", "") eq "on" or ReadingsVal($cooling_device, "state", "") eq "on")
{ $current_state = "on"; }

# seperate the EVENT string and cleanse it
my @events = split / /, $EVENT;
my ($event01, $event02) = split / /, $EVENT;
$event01 =~ tr/://d;
if (!length $event02) { $event02 = "none"; }

# for debugging
$debug_msg = "$event01|$event02|$current_state|$current_mode|$NAME";
fhem("setreading $source_device debug $debug_msg");

if ($event01 eq "on")
{
if ($NAME eq $cooling_device and ReadingsVal($NAME, "CoolingHeatingState", "") eq "OFF")
{ fhem("sleep $timer1;set $NAME command OnCool"); }

if ($NAME eq $heating_device and ReadingsVal($NAME, "CoolingHeatingState", "") eq "OFF")
{ fhem("sleep $timer1;set $NAME command OnHeat"); }

if ($NAME eq $cooling_device and $current_mode eq "Heat" and ReadingsVal($heating_device, "state", "") eq "on")
{ fhem("sleep $timer1;set $NAME command SwitchCool;sleep $timer2;setstate $heating_device off"); }

if ($NAME eq $heating_device and $current_mode eq "Cool" and ReadingsVal($cooling_device, "state", "") eq "on")
{ fhem("sleep $timer1;set $NAME command SwitchHeat;sleep $timer2;setstate $cooling_device off"); }
}

if ($event01 eq "off")
{  fhem("sleep $timer1;set $NAME command PowerToggle");
   fhem("setreading $cooling_device CoolingHeatingState OFF;setreading $heating_device CoolingHeatingState OFF;")}

# turn on/off oscillation
if ($event01 eq "oscillate")
{  fhem("sleep $timer1;set $NAME command Oscillate"); }

# changing the fan speed
if ($event01 eq "target_speed")
{
if ($target_speed != $current_speed and $current_state eq "on")
{ fhem("sleep $timer1;set $NAME command AdjustSpeed"); }

if ($current_state eq "off")
{ fhem("sleep $timer1;set $NAME on;sleep $timer3;set $NAME target_speed $target_speed"); }
}

# Switch off oscillating information
if ($event01 eq "CoolingHeatingState" and $event02 ne "COOL" and $NAME eq $cooling_device)
{ fhem("sleep $timer1;set $cooling_device oscillating off"); }

    # changing the temperature
if ($event01 eq "target_temperature")
{
if ($target_temp != $current_temp and $current_state eq "on")
{ fhem("sleep $timer1;set $NAME command AdjustTemperature"); }

if ($current_state eq "off")
{ fhem("sleep $timer1;set $NAME on;sleep $timer3;set $NAME target_temperature $target_temp"); }
}
if ($event01 eq "command")
{
$ir_cmd = "command branch";

if ($event02 eq "OnCool" and $current_state eq "on" and $current_mode eq "Heat")
{ $ir_cmd = "sleep $timer1;set $NAME command PowerToggleCool";
fhem("sleep $timer1;setstate $heating_device off;setreading $heating_device mode Cool;setreading $cooling_device mode Cool;setreading $heating_device CoolingHeatingState COOL;setreading $cooling_device CoolingHeatingState COOL");
}

if ($event02 eq "OnCool" and $current_state eq "on" and $current_mode eq "Cool")
{ $ir_cmd = "sleep $timer1;set $NAME command PowerToggle";
fhem("sleep $timer1;setstate $heating_device off;setreading $heating_device mode Cool;setreading $cooling_device mode Cool;setreading $cooling_device mode Cool;setreading $heating_device CoolingHeatingState COOL;setreading $cooling_device CoolingHeatingState COOL");
}

if ($event02 eq "OnHeat" and $current_state eq "on" and $current_mode eq "Cool")
{ $ir_cmd = "sleep $timer1;set $NAME command PowerToggleCool";
fhem("sleep $timer1;setstate $cooling_device off;setreading $heating_device mode Heat;setreading $cooling_device mode Heatsetreading $cooling_device mode Cool;setreading $heating_device CoolingHeatingState HEAT;setreading $cooling_device CoolingHeatingState HEAT");
}

if ($event02 eq "OnHeat" and $current_state eq "on" and $current_mode eq "Heat")
{ $ir_cmd = "sleep $timer1;set $NAME command PowerToggle";
fhem("sleep $timer1;setstate $cooling_device off;setreading $heating_device mode Heat;setreading $cooling_device mode Heat;setreading $cooling_device mode Cool;setreading $heating_device CoolingHeatingState HEAT;setreading $cooling_device CoolingHeatingState HEAT");
}

if ($event02 eq "SwitchCool")
{
$ir_cmd ="set $ir_interface command $ir_device Cool";
fhem("sleep $timer1;setstate $heating_device off;setreading $heating_device mode Cool;setreading $cooling_device mode Cool;setreading $cooling_device mode Cool;setreading $heating_device CoolingHeatingState COOL;setreading $cooling_device CoolingHeatingState COOL");
}

if ($event02 eq "SwitchHeat")
{
$ir_cmd ="set $ir_interface command $ir_device Cool";
fhem("sleep $timer1;setstate $cooling_device off;setreading $heating_device mode Heat;setreading $cooling_device mode Heat;setreading $cooling_device mode Cool;setreading $heating_device CoolingHeatingState HEAT;setreading $cooling_device CoolingHeatingState HEAT");
}

if ($event02 eq "Cool")
{ $ir_cmd = "set $ir_interface command $ir_device Cool"; }

if ($event02 eq "PowerToggle")
{ $ir_cmd = "set $ir_interface command $ir_device PowerToggle"; }

if ($event02 eq "PowerToggleCool")
{ $ir_cmd = "set $ir_interface command $ir_device PowerToggle";
fhem("sleep $timer3;set $NAME command Cool");
}

if ($event02 eq "Oscillate")
{ $ir_cmd = "set $ir_interface command $ir_device Oscillate";
if (ReadingsVal($NAME, "oscillating", "") eq "off")
{ fhem("sleep $timer1;setreading $cooling_device oscillating on"); }
else
{ fhem("sleep $timer1;setreading $cooling_device oscillating off"); }
}

if ($event02 eq "AdjustSpeed")
{
if ($current_speed < $target_speed)
{ fhem("sleep $timer2;set $NAME command FanSpeedUp"); }

if ($current_speed > $target_speed)
{ fhem("sleep $timer2;set $NAME command FanSpeedDown"); }
}

if ($event02 eq "FanSpeedUp")
{
$ir_cmd = "set $ir_interface command $ir_device FanSpeedUp";

$current_speed = $current_speed + 10;
fhem("setreading $NAME pct $current_speed");

if ($current_speed < ($target_speed + 10))
{ fhem("sleep $timer1;set $NAME command AdjustSpeed;")}
}

if ($event02 eq "FanSpeedDown")
{
$ir_cmd = "set $ir_interface command $ir_device FanSpeedDown";

$current_speed = $current_speed - 10;
fhem("setreading $NAME pct $current_speed");

if ($current_speed != $target_speed)
{ fhem("sleep $timer1;set $NAME command AdjustSpeed;")}

}

if ($event02 eq "AdjustTemperature")
{
if ($current_temp < $target_temp)
{ fhem("sleep $timer2;set $NAME command TempHotter"); }

if ($current_temp > $target_temp)
{ fhem("sleep $timer2;set $NAME command TempCooler"); }
}

if ($event02 eq "TempCooler")
{
$ir_cmd = "set $ir_interface command $ir_device TempCooler";
$current_temp = $current_temp - 1;
fhem("setreading $NAME temperature $current_temp");

if ($current_temp > $target_temp)
{ fhem("sleep $timer2;set $NAME command AdjustTemperature;")}
}
if ($event02 eq "TempHotter")
{
$ir_cmd = "set $ir_interface command $ir_device TempHotter";
$current_temp = $current_temp + 1;
fhem("setreading $NAME temperature $current_temp");

if ($current_temp < $target_temp)
{ fhem("sleep $timer2;set $NAME command AdjustTemperature;")}
}

fhem("$ir_cmd");
}
fhem("setreading $source_device debug $ir_cmd");
}


Es folgen die Logikelemente für das Klammergerät:

Einfaches Notify zur Weitergabe von Ein/Aus sowie Hoch/Runter an das jeweilige Sub-Gerät

define Wohnzimmer_Ventilator_Aktion_EinAusHochRunter notify a b

(Wohnzimmer_Heizung|Wohnzimmer_Ventilator):(on|off|up|down) {
  my $device = "Interface_Harmony_Wohnzimmer";
  my $ir_device = "Dyson";
  my $pct = ReadingsVal($NAME, "pct", 0);

  if ($EVENT eq "on" or $EVENT eq "off")   { fhem("set $device command $ir_device PowerToggle;"); }
  if ($EVENT eq "up")   { fhem("set $NAME pct ".($pct+10)); }
  if ($EVENT eq "down") { fhem("set $NAME pct ".($pct-10)); }
}


Einfaches Notify zur Weitergabe der Fernbedienungsbefehle

define Wohnzimmer_Ventilator_Aktion_Fernbedienung notify a b

(Wohnzimmer_Heizung|Wohnzimmer_Ventilator):device:.(PowerToggle|FanSpeedUp|FanSpeedDown|Oscillate|Cool|Heat) {

  my $device = "Interface_Harmony_Wohnzimmer";
  my $ir_device = "Dyson";
  my $oscillating = ReadingsVal($NAME, "oscillating", "off");
  my $mode = ReadingsVal($NAME, "currentMode", "");
  my $state = ReadingsVal($NAME, "state", "");
 
  if ($EVTPART1 eq "PowerToggle")
  { fhem("set $device command $ir_device PowerToggle"); }
 
  if ($EVTPART1 eq "Oscillate")
  { fhem("set $device command $ir_device Oscillate"); }
 
  if ($EVTPART1 eq "Oscillate" and $oscillating eq "on")
  { fhem("setreading $NAME oscillating off"); }

  if ($EVTPART1 eq "Oscillate" and $oscillating eq "off")
  { fhem("setreading $NAME oscillating on"); }
 
  if ($EVTPART1 eq "Cool" and $state eq "off" and $mode eq "Heating")
  { fhem("set $NAME on;set $device command $ir_device PowerToggle;sleep 1.5;set $device command $ir_device $EVTPART1");
  fhem("setreading $NAME currentMode Cooling"); }
 
  if ($EVTPART1 eq "Cool" and $state eq "off" and $mode eq "Cooling")
  { fhem("set $NAME on;set $device command $ir_device PowerToggle"); }
 
  if ($EVTPART1 eq "Heat" and $state eq "off" and $mode eq "Heating")
  { fhem("set $NAME on;set $device command $ir_device PowerToggle"); }
 
  if ($EVTPART1 eq "Heat" and $state eq "off" and $mode eq "Cooling")
  { fhem("set $NAME on;set $device command $ir_device PowerToggle;sleep 1.5;set $device command $ir_device Cool");
  fhem("setreading $NAME currentMode Heating");
  }
   
  if ($EVTPART1 eq "Cool" and $state eq "on" and $mode eq "Heating")
  { fhem("set $device command $ir_device $EVTPART1;");
  fhem("setreading $NAME currentMode Cooling");
}
     
  if ($EVTPART1 eq "Heat" and $state eq "on" and $mode eq "Cooling")
  { fhem("set $device command $ir_device Cool");
  fhem("setreading $NAME currentMode Heating");
  }
 

}


Einfaches Notify zur Weitergabe der Ventilatorgeschwindigkeit an das Klammergerät

define Wohnzimmer_Ventilator_Aktion_Geschwindigkeit notify a b

(Wohnzimmer_Ventilator|Wohnzimmer_Heizung):pct:.* {

my $current = ReadingsVal($NAME, "currentSpeed", 0);
my $currentMode = ReadingsVal($NAME, "currentMode", "");
my $current_onoff = ReadingsVal($NAME, "state", 0);
my $device = "Interface_Harmony_Wohnzimmer";
my $ir_device = "Dyson";
my $cmd = "";
my $waitcmd = "sleep 0.4";
my $sleeptime = 0.8;
my $extratime = 0;
my $device_command = "FanSpeedUp";
my $start = 0;
my $end = 0;
my $counter = 0;
my $executions = 0;

my $target = 0;

if ($EVTPART0 eq "pct:") { $target = $EVTPART1; }

if ($target eq 0 and $current_onoff eq "on") { $cmd .= "set $NAME off;"; }
if ($target gt 0 and $current_onoff eq "off") { $cmd .= "set $NAME on;"; $extratime = 1.5; }

if ($currentMode ne "Cooling") { fhem("set $device command $ir_device Cool"); $extratime = 1.5; }

if ($target gt 0)
{

if ($target < $current) {
  for (my $i=$target; $i < $current; $i=$i+10) {
    fhem("sleep ($extratime + ($counter+1) * $sleeptime);set $device command $ir_device FanSpeedDown;");
    $counter += 1;
    $extratime = 0;
  }
}

if ($target > $current) {
  for (my $i=$current; $i < $target; $i=$i+10) {
    fhem("sleep ($extratime + ($counter + 1) * $sleeptime);set $device command $ir_device FanSpeedUp;");
    $counter += 1;
    $extratime = 0;
  }
}
  if ($target ne $current) { fhem("setreading $NAME command execute$counter"); }
fhem("setreading $NAME target $target");


}
}



Einfaches Notify zur Weitergabe der Temperatur an das Klammergerät

define Wohnzimmer_Ventilator_Aktion_Temperatur notify a b

(Wohnzimmer_Heizung|Wohnzimmer_Ventilator):temperature:.* {

my $current = ReadingsVal($NAME, "currentTemp", 0);
my $currentMode = ReadingsVal($NAME, "currentMode", "");
my $current_onoff = ReadingsVal($NAME, "state", "off");
my $device = "Interface_Harmony_Wohnzimmer";
my $ir_device = "Dyson";
my $cmd = "";
my $waitcmd = "sleep 0.4";
my $sleeptime = 0.8;
my $extratime = 0;
my $device_command = "FanSpeedUp";
my $start = 0;
my $end = 0;
my $counter = 0;
my $executions = 0;

my $target = 0;

if ($EVTPART0 =~ "temperature.*") { $target = $EVTPART1; }

if ($target eq 0 and $current_onoff eq "on") { fhem("set $NAME off"); }
if ($target >= 0 and $current_onoff eq "off") { $cmd .= "set $NAME on;"; $extratime = 1.5; }

if ($currentMode ne "Heating") { fhem("set $device command $ir_device TempHotter"); $extratime =+ 1.5; }

if ($target gt 0)
{
if ($target < $current) {
  for (my $i=$target; $i < $current; $i=$i+1) {
    fhem("sleep ($extratime + ($counter+1) * $sleeptime);set $device command $ir_device TempCooler;");
    $counter += 1;
    $extratime = 0;
  }
}

if ($target > $current) {
  for (my $i=$current; $i < $target; $i=$i+1) {
    fhem("sleep ($extratime + ($counter + 1) * $sleeptime);set $device command $ir_device TempHotter;");
    $counter += 1;
    $extratime = 0;
  }
}
  if ($target ne $current) { fhem("setreading $NAME command execute$counter"); }

fhem("setreading $NAME target $target");
}

}


Einfaches Notify zur Weitergabe von FB-Befehlen an das Klammergerät

define Wohnzimmer_Ventilator_HochRunter_Auslesen notify a b

Interface_Harmony_Wohnzimmer bezeichnet bei mir den Logitech-Harmony-Hub und muss leider "hart" angegeben werden.    

Interface_Harmony_Wohnzimmer:command.Dyson.FanSpeedDown|Interface_Harmony_Wohnzimmer:command.Dyson.FanSpeedUp|Interface_Harmony_Wohnzimmer:command.Dyson.TempHotter|Interface_Harmony_Wohnzimmer:command.Dyson.TempCooler {
my $device = "Wohnzimmer_Ventilator";
my $currentMode  = ReadingsVal($device, "currentMode", 0);
my $currentSpeed = ReadingsVal($device, "currentSpeed", 0);
my $currentTemp  = ReadingsVal($device, "currentTemp", 0);

my $newValue = "";


if ($EVTPART2 eq "FanSpeedUp" or $EVTPART2 eq "FanSpeedDown")
{
  $newValue = $currentSpeed;
  if ($EVTPART2 eq "FanSpeedUp") { $newValue += 10; }
  if ($EVTPART2 eq "FanSpeedDown") { $newValue -= 10; }
 
  # Maximale Begrenzung
  if ($newValue > 100) { $newValue = 100; }
  if ($newValue < 10) { $newValue = 10; } 
 
  fhem("setreading $device currentSpeed $newValue");
  fhem("setreading $device currentMode Cooling");
 
}

if ($EVTPART2 eq "TempHotter" or $EVTPART2 eq "TempCooler")
{
  $newValue = $currentTemp;
  if ($EVTPART2 eq "TempHotter") { $newValue += 1; }
  if ($EVTPART2 eq "TempCooler") { $newValue -= 1; }
 
  # Maximale Begrenzung
  if ($newValue > 37) { $newValue = 37; }
  if ($newValue < 1) { $newValue = 1; } 
 
  fhem("setreading $device currentTemp $newValue");
  fhem("setreading $device currentMode Heating"); 
 
}

fhem("setreading $device debug $EVTPART2");
}