diff --git a/fhem/FHEM/10_EnOcean.pm b/fhem/FHEM/10_EnOcean.pm index 76aab2bb4..b8392f9cb 100755 --- a/fhem/FHEM/10_EnOcean.pm +++ b/fhem/FHEM/10_EnOcean.pm @@ -360,6 +360,9 @@ my %EnO_eepConfig = ( "D2.20.00" => {attr => {subType => "fanCtrl.00", webCmd => "fanSpeed"}, GPLOT => "EnO_fanSpeed4humi4:FanSpeed/Humi,"}, "D2.32.00" => {attr => {subType => "currentClamp.00"}, GPLOT => "EnO_D2-32-xx:Current,"}, "D2.32.01" => {attr => {subType => "currentClamp.01"}, GPLOT => "EnO_D2-32-xx:Current,"}, + "D2.34.00" => {attr => {subType => "heatingActuator.00", defaultChannel => 0}, GPLOT => "EnO_D2-34-xx:setpointTemp/temperature,"}, + "D2.34.01" => {attr => {subType => "heatingActuator.00", defaultChannel => 0}, GPLOT => "EnO_D2-34-xx:setpointTemp/temperature,"}, + "D2.34.02" => {attr => {subType => "heatingActuator.00", defaultChannel => 0}, GPLOT => "EnO_D2-34-xx:setpointTemp/temperature,"}, "D2.32.02" => {attr => {subType => "currentClamp.02"}, GPLOT => "EnO_D2-32-xx:Current,"}, "D2.40.00" => {attr => {subType => "ledCtrlState.00"}, GPLOT => "EnO_dim4:Dim,"}, "D2.40.01" => {attr => {subType => "ledCtrlState.01"}, GPLOT => "EnO_dim4RGB:DimRGB,"}, @@ -1374,13 +1377,13 @@ sub EnOcean_Get($@) $rorg = "A5"; shift(@a); $updateState = 0; - if ($cmd eq "state") { + if ($cmd eq "status" || $cmd eq "state" ) { # query state Log3 $name, 3, "EnOcean get $name $cmd"; $data = "00000008"; } else { - $cmdList .= "state:noArg"; + $cmdList .= "status:noArg"; return "Unknown argument $cmd, choose one of $cmdList"; } @@ -1390,19 +1393,19 @@ sub EnOcean_Get($@) $rorg = "A5"; shift(@a); $updateState = 0; - if ($cmd eq "state") { + if ($cmd eq "status" || $cmd eq "state") { # query state Log3 $name, 3, "EnOcean get $name $cmd"; $data = "00000008"; } else { - $cmdList .= "state:noArg"; + $cmdList .= "status:noArg"; return "Unknown argument $cmd, choose one of $cmdList"; } } elsif ($st eq "actuator.01") { # Electronic switches and dimmers with Energy Measurement and Local Control - # (D2-01-00 - D2-01-12) + # (D2-01-00 - D2-01-14) $rorg = "D2"; shift(@a); my $channel; @@ -1422,7 +1425,7 @@ sub EnOcean_Get($@) } } - if ($cmd eq "state") { + if ($cmd eq "status" || $cmd eq "state") { $cmdID = 3; Log3 $name, 3, "EnOcean get $name $cmd $channel"; $data = sprintf "%02X%02X", $cmdID, $channel; @@ -1500,9 +1503,9 @@ sub EnOcean_Get($@) } else { if ($manufID =~ m/^033|046$/) { - return "Unknown argument $cmd, choose one of " . $cmdList . "state measurement roomCtrlMode:noArg special settings"; + return "Unknown argument $cmd, choose one of " . $cmdList . "measurement roomCtrlMode:noArg settings special status"; } else { - return "Unknown argument $cmd, choose one of " . $cmdList . "state measurement roomCtrlMode:noArg settings"; + return "Unknown argument $cmd, choose one of " . $cmdList . "measurement roomCtrlMode:noArg settings status"; } } @@ -1597,16 +1600,40 @@ sub EnOcean_Get($@) $rorg = "D2"; shift(@a); $updateState = 0; - if ($cmd eq "state") { + if ($cmd eq "status" || $cmd eq "state") { # query position and angle $data = "F6FFFFFF"; Log3 $name, 3, "EnOcean get $name $cmd DATA: $data"; } else { - $cmdList .= "state:noArg"; + $cmdList .= "status:noArg"; return "Unknown argument $cmd, choose one of $cmdList"; } + } elsif ($st eq "heatingActuator.00") { + # Heating Actuator + # (D2-34-00 - D2-34-02) + $rorg = "D2"; + shift(@a); + my $channel = shift(@a); + $channel = AttrVal($name, "defaultChannel", AttrVal($name, "devChannel", undef)) if (!defined $channel); + if (!defined($channel) || defined($channel) && ($channel eq "all" || $channel + 0 >= 30)) { + $channel = 30; + } elsif ($channel + 0 >= 0 && $channel + 0 <= 29) { + + } else { + return "$cmd wrong, choose 0...29|all."; + } + if ($cmd eq "status") { + $cmdID = 3; + } elsif ($cmd eq "setpoint") { + $cmdID = 6; + } else { + return "Unknown argument $cmd, choose one of " . $cmdList . "setpoint status"; + } + $data = sprintf "%02X%02X", $channel << 3, $cmdID; + Log3 $name, 3, "EnOcean get $name $cmd $channel"; + } elsif ($st eq "heatRecovery.00") { # heat recovery ventilation # (D2-50-00) @@ -1634,7 +1661,7 @@ sub EnOcean_Get($@) $rorg = "D2"; shift(@a); $updateState = 0; - if ($cmd eq "state") { + if ($cmd eq "status" || $cmd eq "state") { # query switch state $data = "00"; readingsSingleUpdate($hash, "state", $cmd, 1); @@ -4403,7 +4430,7 @@ sub EnOcean_Set($@) } elsif ($st eq "actuator.01") { # Electronic switches and dimmers with Energy Measurement and Local Control - # (D2-01-00 - D2-01-12) + # (D2-01-00 - D2-01-14) $rorg = "D2"; #$updateState = 0; my $cmdID; @@ -5998,6 +6025,117 @@ sub EnOcean_Set($@) ($humidityCtrl << 6) | ($roomSizeRef << 4) | $roomSize, $humiThreshold, $fanSpeed; + } elsif ($st eq "heatingActuator.00") { + # Heating Actuator + # (D2-34-00 - D2-34-02) + $rorg = "D2"; + my ($cmdID, $cfg, $channel, $overridePeriod, $setpointTemp, $setpointTempShift) = (5, 0, undef, 0, 20, 0); + + if ($cmd eq "setpointTempRefDev") { + shift(@a); + $cfg = 0; + $channel = shift(@a); + $channel = AttrVal($name, "defaultChannel", AttrVal($name, "devChannel", undef)) if (!defined $channel); + if (!defined($channel) || defined($channel) && ($channel eq "all" || $channel + 0 >= 30)) { + CommandDeleteReading(undef, "$name channel.*"); + CommandDeleteReading(undef, "$name overridePeriod.*"); + CommandDeleteReading(undef, "$name setpointTemp.*"); + CommandDeleteReading(undef, "$name setpointTempRefDev.*"); + CommandDeleteReading(undef, "$name setpointTempShift.*"); + readingsSingleUpdate($hash, "channelAll", "setpointTempRefDev", 1); + $channel = 30; + } elsif ($channel + 0 >= 0 && $channel + 0 <= 29) { + CommandDeleteReading(undef, "$name overridePeriod" . $channel); + CommandDeleteReading(undef, "$name setpointTemp" . $channel); + CommandDeleteReading(undef, "$name setpointTempShift" . $channel); + readingsSingleUpdate($hash, "channel" . $channel, "setpointTempRefDev", 1); + } else { + return "$cmd $channel wrong, choose 0...29|all."; + } + + } elsif ($cmd eq "setpointTemp") { + shift(@a); + $cfg = 1; + $setpointTemp = shift(@a); + if (!defined($setpointTemp) || $setpointTemp !~ m/^[+-]?\d+(\.\d+)?$/ || $setpointTemp < 0 || $setpointTemp > 40) { + return "Usage: $cmd variable is not numeric or out of range."; + } + $channel = shift(@a); + if (defined $channel) { + $overridePeriod = shift(@a); + if (defined $overridePeriod) { + if ($overridePeriod !~ m/^[+-]?\d+$/ || $overridePeriod < 0 || $overridePeriod > 63) { + return "Usage: $cmd $overridePeriod is not numeric or out of range."; + } + } + } else { + $channel = AttrVal($name, "defaultChannel", AttrVal($name, "devChannel", 'all')); + $overridePeriod = 0; + } + if ($channel eq "all" || $channel + 0 >= 30) { + CommandDeleteReading(undef, "$name channel.*"); + CommandDeleteReading(undef, "$name overridePeriod.*"); + CommandDeleteReading(undef, "$name setpointTemp.*"); + CommandDeleteReading(undef, "$name setpointTempRefDev.*"); + CommandDeleteReading(undef, "$name setpointTempShift.*"); + readingsSingleUpdate($hash, "overridePeriodAll", $overridePeriod, 1); + readingsSingleUpdate($hash, "setpointTempAll", sprintf("%0.1f", $setpointTemp), 1); + readingsSingleUpdate($hash, "channelAll", "setpointTemp", 1); + $channel = 30; + } elsif ($channel + 0 >= 0 && $channel + 0 <= 29) { + readingsSingleUpdate($hash, "overridePeriod" . $channel, $overridePeriod, 1); + readingsSingleUpdate($hash, "setpointTemp" . $channel, sprintf("%0.1f", $setpointTemp), 1); + readingsSingleUpdate($hash, "channel" . $channel, "setpointTemp", 1); + } else { + return "Usage: $cmd $channel wrong, choose 0...29|all."; + } + + } elsif ($cmd eq "setpointTempShift") { + shift(@a); + $setpointTempShift = shift(@a); + if (!defined($setpointTempShift) || $setpointTempShift !~ m/^[+-]?\d+(\.\d+)?$/ || $setpointTempShift < -10 || $setpointTempShift > 10) { + return "Usage: $cmd variable is not numeric or out of range."; + } + $channel = shift(@a); + if (defined $channel) { + $overridePeriod = shift(@a); + if (defined $overridePeriod) { + if ($overridePeriod !~ m/^[+-]?\d+$/ || $overridePeriod < 0 || $overridePeriod > 63) { + return "Usage: $cmd $overridePeriod is not numeric or out of range."; + } + } + } else { + $channel = AttrVal($name, "defaultChannel", AttrVal($name, "devChannel", 'all')); + $overridePeriod = 0; + } + if ($channel eq "all" || $channel + 0 >= 30) { + CommandDeleteReading(undef, "$name channel.*"); + CommandDeleteReading(undef, "$name overridePeriod.*"); + CommandDeleteReading(undef, "$name setpointTemp.*"); + CommandDeleteReading(undef, "$name setpointTempRefDev.*"); + CommandDeleteReading(undef, "$name setpointTempShift.*"); + readingsSingleUpdate($hash, "overridePeriodAll", $overridePeriod, 1); + readingsSingleUpdate($hash, "setpointTempShiftAll", sprintf("%0.1f", $setpointTempShift), 1); + readingsSingleUpdate($hash, "channelAll", "setpointTempShift", 1); + $channel = 30; + } elsif ($channel >= 0 && $channel <= 29) { + readingsSingleUpdate($hash, "overridePeriod" . $channel, $overridePeriod, 1); + readingsSingleUpdate($hash, "setpointTempShift" . $channel, sprintf("%0.1f", $setpointTempShift), 1); + readingsSingleUpdate($hash, "channel" . $channel, "setpointTempShift", 1); + } else { + return "Usage: $cmd $channel wrong, choose 0...29|all."; + } + $cfg = $setpointTempShift >= 0 ? 2 : 3; + $setpointTempShift = abs($setpointTempShift * 10); + + } else { + $cmdList .= "setpointTemp setpointTempRefDev setpointTempShift"; + return "Unknown argument $cmd, choose one of $cmdList"; + } + Log3 $name, 3, "EnOcean set $name $cmd"; + $setpointTemp = abs($setpointTemp * 10); + $data = sprintf "%02X%04X%02X%02X", $cfg << 6 | $overridePeriod, $setpointTempShift << 9 | $setpointTemp, $channel << 3, $cmdID; + } elsif ($st eq "heatRecovery.00") { # heat recovery ventilation # (D2-50-00) @@ -11433,6 +11571,51 @@ sub EnOcean_Parse($$) } } + } elsif ($st eq "heatingActuator.00") { + # Heating Actuator + # (D2-34-00 - D2-34-02) + my ($channel, $cmd) = (undef, $db[0] & 0x0F); + if ($cmd == 4) { + # actuator status response + $channel = ((hex substr($data, 4, 4)) & 0x03E0) >> 5; + my @operationMode = ('off', 'temperature_unknown', 'no_heating', 'heating'); + if ($channel == 30) { + $channel = "All"; + CommandDeleteReading(undef, "$name channel.*"); + CommandDeleteReading(undef, "$name operationMode.*"); + CommandDeleteReading(undef, "$name overridePeriod.*"); + CommandDeleteReading(undef, "$name setpointTemp.*"); + CommandDeleteReading(undef, "$name setpointTempRefDev.*"); + CommandDeleteReading(undef, "$name setpointTempShift.*"); + } + push @event, "3:temperature" . $channel . ":" . sprintf("%0.1f", (((hex(substr($data, 0, 4))) & 0xFF80) >> 7) / 10); + push @event, "3:setpointTemp" . $channel . ":" . sprintf("%0.1f", (((hex(substr($data, 2, 4))) & 0x7FC0) >> 6) / 10); + push @event, "3:operationMode" . $channel . ":" . $operationMode[($db[1] & 0x3C) >> 2]; + push @event, "3:state:" . $channel . ': ' . $operationMode[($db[1] & 0x3C) >> 2]; + + } elsif ($cmd == 7) { + # actuator setpoint response + $channel = ($db[1] & 0x7C) >> 2; + my @channel = ('setpointTempRefDev', 'setpointTemp', 'setpointTempShift', 'setpointTempShift'); + if ($channel == 30) { + $channel = "All"; + CommandDeleteReading(undef, "$name channel.*"); + CommandDeleteReading(undef, "$name operationMode.*"); + CommandDeleteReading(undef, "$name overridePeriod.*"); + CommandDeleteReading(undef, "$name setpointTemp.*"); + CommandDeleteReading(undef, "$name setpointTempRefDev.*"); + CommandDeleteReading(undef, "$name setpointTempShift.*"); + } + push @event, "3:channel" . $channel . ":" . $channel[($db[5] & 0xC0) >> 6]; + push @event, "3:overridePeriod" . $channel . ":" . ($db[5] & 0x3F); + push @event, "3:setpointTempRefDev" . $channel . ":" . sprintf("%0.1f", (((hex(substr($data, 2, 4))) & 0xFF80) >> 7) / 10); + push @event, "3:setpointTempShift" . $channel . ":" . sprintf("%0.1f", ($db[3] & 0x7F) / 10 * ((($db[5] & 0xC0) >> 6) == 3 ? -1 : 1)); + push @event, "3:setpointTemp" . $channel . ":" . sprintf("%0.1f", (((hex(substr($data, 6, 4))) & 0xFF80) >> 7) / 10); + + } else { + # unknown response + } + } elsif ($st eq "ledCtrlState.00") { # LED Controller Status (EEP D2-40-00) if ($db[1] & 0x80) { @@ -18569,6 +18752,31 @@ EnOcean_Delete($$)

+
  • Heating Actuator (D2-34-00 - D2-34-02)
    + [AWAG UPS230/10, UPS230/12, REGH12/08M]
    +
      + set <name> <value> +

      + where value is +
    • setpointTemp t/°C [<channel> [<overrideTime/h>]]
      + set the temperatur setpoint
    • +
    • setpointTempRefDev
      + enable the temperature setpoint via room control unit
    • +
    • setpointTempShift t/K [<channel> [<overrideTime/h>]]
      + set the temperatur setpoint shift
    • +

    + [setpointTemp] t = 0 °C ... 40 °C
    + [setpointTempShift] t = Range: t = -10 K ... 10 K
    + [channel] = 0...29|all, all is default
    + The default channel can be specified with the attr defaultChannel.
    + [overrideTime] = 0 h ... 63 h, 0 is default (endless)
    + Duration of the override until fallback to the room control panel setpointTemp value. + The attr subType must be heatingActuator.00. This is done if the device was + created by autocreate. To control the device, it must be bidirectional paired, + see Bidirectional Teach-In / Teach-Out. +
  • +

    +
  • Heat Recovery Ventilation (D2-50-00 - D2-50-11)
    [untested]
      @@ -18747,13 +18955,13 @@ EnOcean_Delete($$) Trigger status messages of the device.

      -
    • Dual Channel Switch Actuator (EEP A5-11-059)
      +
    • Dual Channel Switch Actuator (EEP A5-11-05)
      [untested]
        get <name> <value>

        where value is -
      • state
        +
      • status
        status request

      The attr subType or subTypSet must be switch.05. This is done if the device was created by autocreate. @@ -18766,7 +18974,7 @@ EnOcean_Delete($$) get <name> <value>

      where value is -
    • state
      +
    • status
      status request

    The attr subType or subTypSet must be lightCtrl.01. This is done if the device was created by autocreate.
    @@ -18784,7 +18992,7 @@ EnOcean_Delete($$) get pilot wire mode
  • settings [<channel>]
    get external interface settings
  • -
  • state [<channel>]
    +
  • status [<channel>]
  • measurement <channel> energy|power
  • @@ -18871,7 +19079,7 @@ EnOcean_Delete($$) get <name> <value>

    where value is -
  • state
    +
  • status
    get the state of the room controler

  • The attr subType must be fanCtrl.00. This is done if the device was @@ -18880,6 +19088,23 @@ EnOcean_Delete($$)

    +
  • Heating Actuator (D2-34-00 - D2-34-02)
    + [AWAG UPS230/10, UPS230/12, REGH122/08M]
    +
      + get <name> <value> +

      + where value is +
    • setpoint
      + get the setpoint infos of the heating actuator
    • +
    • status
      + get the state of the heating actuator
    • +

    + The attr subType must be heatingActuator.00. This is done if the device was + created by autocreate. To control the device, it must be bidirectional paired, + see Bidirectional Teach-In / Teach-Out. +
  • +

    +
  • Heat Recovery Ventilation (D2-50-00 - D2-50-11)
    [untested]
      @@ -21310,6 +21535,30 @@ EnOcean_Delete($$)

      +
    • Heating Actuator (D2-34-00 - D2-34-02)
      + [AWAG UPS230/10, UPS230/12, REGH12/08M]
      +
        +
      • <0...29|All>: heating
      • +
      • <0...29|All>: no_heating
      • +
      • <0...29|All>: off
      • +
      • <0...29|All>: temperature_unknown
      • +
      • channel<0...29|All>: setpointTempRefDev|setpointTemp|setpointTempShift
      • +
      • operationMode<1...29|All>: heating|no_heating|off|temperature_unknown
      • +
      • overridePeriod<1...29|All|>: t/h
      • +
      • setpointTemp<1...29|All>: t/°C
      • +
      • setpointTempRefDev<1...29|All>: t/°C
      • +
      • setpointTempShift<1...29|All>: t/K
      • +
      • teach: <result of teach procedure>
      • +
      • temperature<1...29|All>: t/°C
      • +
      • state:<0...29|All>: heating|no_heating|off|temperature_unknownt
      • +
      +
      + The attr subType must be heatingActuator.00. This is done if the device was + created by autocreate. To control the device, it must be bidirectional paired, + see Bidirectional Teach-In / Teach-Out. +
    • +

      +
    • LED Controller Status (EEP D2-40-00 - D2-40-01)
      [untested]