From b2765a3895efb9d5ae0e0881109d6996f58472d5 Mon Sep 17 00:00:00 2001 From: Conte Andrea Date: Sun, 27 Feb 2022 19:11:45 +0100 Subject: [PATCH] [openwebnet] adding support for central unit (#12062) * - read 'standAlone' flag from thing - send standAlone flag to own4j for setting the temperature on central unit - own4j 0.7.1 required * added localmode and central unit thing * added localOffSet channel to readme.md * added remoteControl, batteryStatus and modeCentralUnit for bus_thermo_cu * added weekly and scenarios to modeCentralUnit * - manual setting of a zone to T temperature (with persistence in central unit) - manual setting of central unit to T temperature (all zones) - set the central unit in OFF mode (all zones) - set central unit in thermal protection (all zones) - set central unit in antifreeze mode (all zones) - weekly program activation command (all zones) - scenario activation command (all zones) * renamed cu's channels name * removed unused channel 'modeCentralUnit" from readme * fix #12298 * - add configuration section (where) for BusThermoCentralUnit - strings ("OK", "KO", "ENABLED", "DISABLED" converted to constants - fix typo Signed-off-by: Conte Andrea Co-authored-by: M Valla <12682715+mvalla@users.noreply.github.com> --- .../org.openhab.binding.openwebnet/README.md | 106 +++++--- .../internal/OpenWebNetBindingConstants.java | 12 +- .../OpenWebNetDeviceDiscoveryService.java | 4 +- .../OpenWebNetThermoregulationHandler.java | 227 +++++++++++++++--- .../handler/OpenWebNetThingHandler.java | 4 +- .../OH-INF/thing/BusThermoCentralUnit.xml | 43 ++++ .../resources/OH-INF/thing/BusThermoZone.xml | 1 + .../main/resources/OH-INF/thing/channels.xml | 98 ++++++++ 8 files changed, 414 insertions(+), 81 deletions(-) create mode 100644 bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusThermoCentralUnit.xml diff --git a/bundles/org.openhab.binding.openwebnet/README.md b/bundles/org.openhab.binding.openwebnet/README.md index 9587f3653..8bf44fa5a 100644 --- a/bundles/org.openhab.binding.openwebnet/README.md +++ b/bundles/org.openhab.binding.openwebnet/README.md @@ -38,23 +38,23 @@ The following Things and OpenWebNet `WHOs` are supported: ### For BUS/SCS -| Category | WHO | Thing Type IDs | Description | Status | -| -------------------- | :----------: | :---------------------------------: | ---------------------------------------------------------------- | ---------------- | -| Gateway Management | `13` | `bus_gateway` | Any IP gateway supporting OpenWebNet protocol should work (e.g. F454 / MyHOMEServer1 / MH202 / F455 / MH200N, ...) | Successfully tested: F454, MyHOMEServer1, MyHOME_Screen10, MyHOME_Screen3,5, F455, F452, F453AV, MH201, MH202, MH200N. Some connection stability issues/gateway resets reported with MH202 | -| Lighting | `1` | `bus_on_off_switch`, `bus_dimmer` | BUS switches and dimmers | Successfully tested: F411/2, F411/4, F411U2, F422, F429. Some discovery issues reported with F429 (DALI Dimmers) | -| Automation | `2` | `bus_automation` | BUS roller shutters, with position feedback and auto-calibration | Successfully tested: LN4672M2 | -| Temperature Control | `4` | `bus_thermo_zone`, `bus_thermo_sensor` | Thermo zones management and temperature sensors (probes). NOTE Central Units (4 or 99 zones) are not fully supported yet. See [Channels - Thermo](#configuring-thermo) for more details. | Successfully tested: H/LN4691, HS4692, KG4691; thermo sensors: L/N/NT4577 + 3455 | -| CEN & CEN+ Scenarios | `15` & `25` | `bus_cen_scenario_control`, `bus_cenplus_scenario_control` | CEN/CEN+ scenarios events and virtual activation | Successfully tested: scenario buttons: HC/HD/HS/L/N/NT4680 | -| Dry Contact and IR Interfaces | `25` | `bus_dry_contact_ir` | Dry Contacts and IR Interfaces | Successfully tested: contact interfaces F428 and 3477; IR sensors: HC/HD/HS/L/N/NT4610 | -| Energy Management | `18` | `bus_energy_meter` | Energy Management | Successfully tested: F520, F521 | +| Category | WHO | Thing Type IDs | Description | Status | +| ----------------------------- | :----------: | :--------------------------------------------------------: | ---------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Gateway Management | `13` | `bus_gateway` | Any IP gateway supporting OpenWebNet protocol should work | Successfully tested: F452, F453, F453AV,F454, F455, MyHOMEServer1, MyHOME_Screen10, MyHOME_Screen3,5, MH201, MH202, MH200N. Some connection stability issues/gateway resets reported with MH202  | +| Lighting | `1` | `bus_on_off_switch`, `bus_dimmer` | BUS switches and dimmers | Successfully tested: F411/2, F411/4, F411U2, F422, F429. Some discovery issues reported with F429 (DALI Dimmers) | +| Automation | `2` | `bus_automation` | BUS roller shutters, with position feedback and auto-calibration | Successfully tested: LN4672M2 | +| Temperature Control | `4` | `bus_thermo_zone`, `bus_thermo_sensor`, `bus_thermo_cu` | Thermo zones management and temperature sensors (probes). | Successfully tested: H/LN4691, HS4692, KG4691; thermo sensors: L/N/NT4577 + 3455; Central Units (4 or 99 zones) are not fully supported yet. See [Channels - Thermo](#configuring-thermo) for more details | +| CEN & CEN+ Scenarios | `15` & `25` | `bus_cen_scenario_control`, `bus_cenplus_scenario_control` | CEN/CEN+ scenarios events and virtual activation | Successfully tested: scenario buttons: HC/HD/HS/L/N/NT4680 | +| Dry Contact and IR Interfaces | `25` | `bus_dry_contact_ir` | Dry Contacts and IR Interfaces | Successfully tested: contact interfaces F428 and 3477; IR sensors: HC/HD/HS/L/N/NT4610 | +| Energy Management | `18` | `bus_energy_meter` | Energy Management | Successfully tested: F520, F521 | ### For ZigBee (Radio) -| Category | WHO | Thing Type IDs | Description | Status | -| -------------------- | :----: | :-------------------------------: | :-------------------------------------------------------------------: | ------------------------------------ | -| Gateway Management | `13` | `zb_gateway` | ZigBee USB Gateway (models: BTI-3578 / LG 088328) | Tested: BTI-3578 and LG 088328 | -| Lighting | `1` | `zb_dimmer`, `zb_on_off_switch`, `zb_on_off_switch2u` | ZigBee dimmers, switches and 2-unit switches | Tested: BTI-4591, BTI-3584, BTI-4585 | -| Automation | `2` | `zb_automation` | ZigBee roller shutters | | +| Category | WHO | Thing Type IDs | Description | Status | +| -------------------- | :----: | :---------------------------------------------------: | :-------------------------------------------------------------------: | ------------------------------------ | +| Gateway Management | `13` | `zb_gateway` | ZigBee USB Gateway (models: BTI-3578 / LG 088328) | Tested: BTI-3578 and LG 088328 | +| Lighting | `1` | `zb_dimmer`, `zb_on_off_switch`, `zb_on_off_switch2u` | ZigBee dimmers, switches and 2-unit switches | Tested: BTI-4591, BTI-3584, BTI-4585 | +| Automation | `2` | `zb_automation` | ZigBee roller shutters | | ## Discovery @@ -150,36 +150,45 @@ Temperature sensors can be configured defining a `bus_thermo_sensor` Thing with - example sensor `5` of external zone `00` --> `where="500"` - example: slave sensor `3` of zone `2` --> `where="302"` -#### NOTE +The (optional) Central Unit can be configured defining a `bus_themo_cu` Thing. -Systems with Central Units (4 or 99 zones) are not fully supported yet. +### Central Unit integration missing points +- Read setPoint temperature and current mode +- Holiday activation command (all zones) +- Discovery ## Channels ### Lighting, Automation, Power meter, CEN/CEN+ Scenario Events and Dry Contact / IR Interfaces channels -| Channel Type ID (channel ID) | Applies to Thing Type IDs | Item Type | Description | Read/Write | -| ---------------------------------------- | ------------------------------------------------------------- | ------------- | ----------------------------------------------------- | :--------: | -| `switch` or `switch_01`/`02` for ZigBee | `bus_on_off_switch`, `zb_on_off_switch`, `zb_on_off_switch2u` | Switch | To switch the device `ON` and `OFF` | R/W | -| `brightness` | `bus_dimmer`, `zb_dimmer` | Dimmer | To adjust the brightness value (Percent, `ON`, `OFF`) | R/W | -| `shutter` | `bus_automation` | Rollershutter | To activate roller shutters (`UP`, `DOWN`, `STOP`, Percent - [see Shutter position](#shutter-position)) | R/W | -| `button#X` | `bus_cen_scenario_control`, `bus_cenplus_scenario_control` | String | Trigger channel for CEN/CEN+ scenario events [see possible values](#cen-cen-channels) | R (TRIGGER) | -| `sensor` | `bus_dry_contact_ir` | Switch | Indicates if a Dry Contact Interface is `ON`/`OFF`, or if a IR Sensor is detecting movement (`ON`), or not (`OFF`) | R | -| `power` | `bus_energy_meter` | Number:Power | The current active power usage from Energy Meter | R | +| Channel Type ID (channel ID) | Applies to Thing Type IDs | Item Type | Description | Read/Write | +| ---------------------------------------- | ------------------------------------------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------- | :---------: | +| `switch` or `switch_01`/`02` for ZigBee | `bus_on_off_switch`, `zb_on_off_switch`, `zb_on_off_switch2u` | Switch | To switch the device `ON` and `OFF` | R/W | +| `brightness` | `bus_dimmer`, `zb_dimmer` | Dimmer | To adjust the brightness value (Percent, `ON`, `OFF`) | R/W | +| `shutter` | `bus_automation` | Rollershutter | To activate roller shutters (`UP`, `DOWN`, `STOP`, Percent - [see Shutter position](#shutter-position)) | R/W | +| `button#X`   | `bus_cen_scenario_control`, `bus_cenplus_scenario_control` | String | Trigger channel for CEN/CEN+ scenario events [see possible values](#cen-cen-channels) | R (TRIGGER) | +| `sensor` | `bus_dry_contact_ir` | Switch | Indicates if a Dry Contact Interface is `ON`/`OFF`, or if a IR Sensor is detecting movement (`ON`), or not (`OFF`) | R | +| `power` | `bus_energy_meter` | Number:Power | The current active power usage from Energy Meter | R | ### Thermo channels -| Channel Type ID (channel ID) | Applies to Thing Type IDs | Item Type | Description | Read/Write | Advanced | -| ---------------------------- | ----------------------------------- | ------------------ | ------------------------------------------------- | :--------: | :------: | -| `temperature` | `bus_thermo_zone`, `bus_thermo_sensor` | Number:Temperature | The zone currently sensed temperature | R | N | -| `setpointTemperature` | `bus_thermo_zone` | Number:Temperature | The zone setpoint temperature | R/W | N | -| `function` | `bus_thermo_zone` | String | The zone set thermo function: `COOLING`, `HEATING` or `GENERIC` (heating + cooling) | R/W | N | -| `mode` | `bus_thermo_zone` | String | The zone set mode: `MANUAL`, `PROTECTION`, `OFF` | R/W | N | -| `speedFanCoil` | `bus_thermo_zone` | String | The zone fancoil speed: `AUTO`, `SPEED_1`, `SPEED_2`, `SPEED_3` | R/W | N | -| `actuators` | `bus_thermo_zone` | String | The zone actuator(s) status: `OFF`, `ON`, `OPENED`, `CLOSED` , `STOP`, `OFF_FAN_COIL`, `ON_SPEED_1`, `ON_SPEED_2`, `ON_SPEED_3`, `OFF_SPEED_1`, `OFF_SPEED_2`, `OFF_SPEED_3` | R | Y | -| `heatingValves` | `bus_thermo_zone` | String | The zone heating valve(s) status: `OFF`, `ON`, `OPENED`, `CLOSED` , `STOP`, `OFF_FAN_COIL`, `ON_SPEED_1`, `ON_SPEED_2`, `ON_SPEED_3`, `OFF_SPEED_1`, `OFF_SPEED_2`, `OFF_SPEED_3` | R | Y | -| `conditioningValves` | `bus_thermo_zone` | String | The zone conditioning valve(s) status: `OFF`, `ON`, `OPENED`, `CLOSED` , `STOP`, `OFF_FAN_COIL`, `ON_SPEED_1`, `ON_SPEED_2`, `ON_SPEED_3`, `OFF_SPEED_1`, `OFF_SPEED_2`, `OFF_SPEED_3` | R | Y | +| Channel Type ID (channel ID) | Applies to Thing Type IDs | Item Type | Description | Read/Write | Advanced | +| ---------------------------- | -------------------------------------- | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------: | :------: | +| `temperature` | `bus_thermo_zone`, `bus_thermo_sensor` | Number:Temperature | The zone currently sensed temperature | R | N | +| `setpointTemperature` | `bus_thermo_zone`, `bus_thermo_cu` | Number:Temperature | The zone or Central Unit setpoint temperature | R/W | N | +| `function` | `bus_thermo_zone` | String | The zone set thermo function: `COOLING`, `HEATING` or `GENERIC` (heating + cooling) | R/W | N | +| `mode` | `bus_thermo_zone`, `bus_thermo_cu` | String | The zone set mode (`MANUAL`, `PROTECTION`, `OFF`) or the Central Unit set mode ( `MANUAL`, `PROTECTION`, `OFF`, `WEEKLY`, `SCENARIO`) | R/W | N | +| `speedFanCoil` | `bus_thermo_zone` | String | The zone fancoil speed: `AUTO`, `SPEED_1`, `SPEED_2`, `SPEED_3` | R/W | N | +| `actuators` | `bus_thermo_zone` | String | The zone actuator(s) status: `OFF`, `ON`, `OPENED`, `CLOSED` , `STOP`, `OFF_FAN_COIL`, `ON_SPEED_1`, `ON_SPEED_2`, `ON_SPEED_3`, `OFF_SPEED_1`, `OFF_SPEED_2`, `OFF_SPEED_3` | R | Y | +| `heatingValves` | `bus_thermo_zone` | String | The zone heating valve(s) status: `OFF`, `ON`, `OPENED`, `CLOSED` , `STOP`, `OFF_FAN_COIL`, `ON_SPEED_1`, `ON_SPEED_2`, `ON_SPEED_3`, `OFF_SPEED_1`, `OFF_SPEED_2`, `OFF_SPEED_3` | R | Y | +| `conditioningValves` | `bus_thermo_zone` | String | The zone conditioning valve(s) status: `OFF`, `ON`, `OPENED`, `CLOSED` , `STOP`, `OFF_FAN_COIL`, `ON_SPEED_1`, `ON_SPEED_2`, `ON_SPEED_3`, `OFF_SPEED_1`, `OFF_SPEED_2`, `OFF_SPEED_3` | R | Y | +| `localOffset` | `bus_thermo_zone` | String | The zone local offset status: `OFF`, `PROTECTION`, `MINUS_3`, `MINUS_2` , `MINUS_1`, `NORMAL`, `PLUS_1`, `PLUS_2`, `PLUS_3` | R | Y | +| `remoteControl` | `bus_thermo_cu` | String | The Central Unit Remote Control status: `ENABLED`, `DISABLED` | R | Y | +| `batteryStatus` | `bus_thermo_cu` | String | The Central Unit Battery status: `OK`, `KO` | R | Y | +| `weeklyProgram` | `bus_thermo_cu` | Number | The program number (`1`, `2`, `3`) when Central Unit mode is `WEEKLY` | R/W | N | +| `scenarioProgram` | `bus_thermo_cu` | Number | The program number (`1`, `2`, .. , `16`) when Central Unit mode is `SCENARIO` | R/W | N | + ### Notes on channels @@ -218,6 +227,15 @@ See [openwebnet.sitemap](#openwebnet-sitemap) & [openwebnet.rules](#openwebnet-r - `EXTENDED_PRESS` - sent after `START_EXTENDED_PRESS` if you keep the button pressed longer; will be sent again every 0,5sec as long as you hold pressed (good for dimming rules) - `RELEASE_EXTENDED_PRESS` - sent once when you finally release the button after having it pressed longer than 0,5sec +#### `mode` for values WEEKLY and SCENARIO (Central Unit) + +There are three WEEKLY and sixteen SCENARIO programs defined for the Central Unit. + +In order to activate one of them you have to use two different channels: +- with `mode` you can set the mode (`WEEKLY` or `SCENARIO`) +- with `weeklyProgram` (if `WEEKLY` was setted) or with `scenarioProgram` (if `SCENARIO` was setted) you can set the program number + +Example: if you want to activate SCENARIO #9 you have to set `mode` = `SCENARIO` and `scenarioProgram` = `9`. ## Full Example @@ -230,10 +248,14 @@ Bridge openwebnet:bus_gateway:mybridge "MyHOMEServer1" [ host="192.168.1.35", pa bus_on_off_switch LR_switch "Living Room Light" [ where="51" ] bus_dimmer LR_dimmer "Living Room Dimmer" [ where="0311#4#01" ] bus_automation LR_shutter "Living Room Shutter" [ where="93", shutterRun="10050"] + bus_energy_meter CENTRAL_Ta "Energy Meter Ta" [ where="51" ] bus_energy_meter CENTRAL_Tb "Energy Meter Tb" [ where="52" ] + + bus_thermo_cu CU_3550 "99 zones central unit" [ where="0" ] bus_thermo_zone LR_zone "Living Room Zone" [ where="2"] bus_thermo_sensor EXT_tempsensor "External Temperature" [ where="500"] + bus_cen_scenario_control LR_CEN_scenario "Living Room CEN" [ where="51", buttons="4,3,8"] bus_cenplus_scenario_control LR_CENplus_scenario "Living Room CEN+" [ where="212", buttons="1,5,18" ] bus_dry_contact_ir LR_IR_sensor "Living Room IR Sensor" [ where="399" ] @@ -255,17 +277,25 @@ Bridge openwebnet:zb_gateway:myZBgateway [ serialPort="COM3" ] { Example items linked to BUS devices: -NOTE: lights, blinds and zones (thermostat) can be handled from personal assistants (Google Home, Alexa). In the following example `Google Assistant` was configured (`ga="..."`) according to the [official documentation](https://www.openhab.org/docs/ecosystem/google-assistant). +NOTE: lights, blinds and zones (thermostat) can be handled from personal assistants (Google Home, Alexa). In the following example `Google Assistant` (`ga="..."`) and `HomeKit` (`homekit="..."`) were configured according to the [Google official documentation](https://www.openhab.org/docs/ecosystem/google-assistant) and [HomeKit official documentation](https://www.openhab.org/addons/integrations/homekit/) ``` -Switch iLR_switch "Light" (gLivingRoom) { channel="openwebnet:bus_on_off_switch:mybridge:LR_switch:switch", ga="Light" } -Dimmer iLR_dimmer "Dimmer [%.0f %%]" (gLivingRoom) { channel="openwebnet:bus_dimmer:mybridge:LR_dimmer:brightness", ga="Light" } +Switch iLR_switch "Light" (gLivingRoom) { channel="openwebnet:bus_on_off_switch:mybridge:LR_switch:switch", ga="Light", homekit="Lighting" } +Dimmer iLR_dimmer "Dimmer [%.0f %%]" (gLivingRoom) { channel="openwebnet:bus_dimmer:mybridge:LR_dimmer:brightness", ga="Light", homekit="Lighting" } -Rollershutter iLR_shutter "Shutter [%.0f %%]" (gShutters, gLivingRoom) { channel="openwebnet:bus_automation:mybridge:LR_shutter:shutter", ga="Blinds" } +Rollershutter iLR_shutter "Shutter [%.0f %%]" (gShutters, gLivingRoom) { channel="openwebnet:bus_automation:mybridge:LR_shutter:shutter", ga="Blinds", homekit = "Window" } Number:Power iCENTRAL_Ta "Power [%.0f %unit%]" { channel="openwebnet:bus_energy_meter:mybridge:CENTRAL_Ta:power" } Number:Power iCENTRAL_Tb "Power [%.0f %unit%]" { channel="openwebnet:bus_energy_meter:mybridge:CENTRAL_Tb:power" } +// 99 zones central unit +Group gCentralUnit "Central Unit" +Number:Temperature iCU_3550_manualset "Temperature" (gCentralUnit) { channel="openwebnet:bus_thermo_cu:mybridge:CU_3550:setpointTemperature", ga="thermostatTemperatureSetpoint" } +String iCU_3550_remote "Remote Control" (gCentralUnit) { channel="openwebnet:bus_thermo_cu:mybridge:CU_3550:remoteControl" } +String iCU_3550_battery "Battery Status" (gCentralUnit) { channel="openwebnet:bus_thermo_cu:mybridge:CU_3550:batteryStatus" } +String iCU_3550_mode "Mode" (gCentralUnit) { channel="openwebnet:bus_thermo_cu:mybridge:CU_3550:mode" } +Number iCU_3550_wpn "Weekly Program" (gCentralUnit) { channel="openwebnet:bus_thermo_cu:mybridge:CU_3550:weeklyProgram" } +Number iCU_3550_spn "Scenario Program" (gCentralUnit) { channel="openwebnet:bus_thermo_cu:mybridge:CU_3550:scenarioProgram" } Group gLivingRoomZone "Living Room Zone" { ga="Thermostat" [ modes="auto=GENERIC,heat=HEATING,cool=COOLING", thermostatTemperatureRange="7,35", useFahrenheit=false ] } Number:Temperature iLR_zone_temp "Temperature [%.1f %unit%]" (gLivingRoomZone) { channel="openwebnet:bus_thermo_zone:mybridge:LR_zone:temperature", ga="thermostatTemperatureAmbient" } diff --git a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/OpenWebNetBindingConstants.java b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/OpenWebNetBindingConstants.java index 997f74318..806a2c404 100644 --- a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/OpenWebNetBindingConstants.java +++ b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/OpenWebNetBindingConstants.java @@ -59,6 +59,8 @@ public class OpenWebNetBindingConstants { public static final String THING_LABEL_BUS_THERMO_SENSOR = "Thermo Sensor"; public static final ThingTypeUID THING_TYPE_BUS_THERMO_ZONE = new ThingTypeUID(BINDING_ID, "bus_thermo_zone"); public static final String THING_LABEL_BUS_THERMO_ZONE = "Thermo Zone"; + public static final ThingTypeUID THING_TYPE_BUS_THERMO_CU = new ThingTypeUID(BINDING_ID, "bus_thermo_cu"); + public static final String THING_LABEL_BUS_THERMO_CU = "Thermo Central Unit"; public static final ThingTypeUID THING_TYPE_BUS_CEN_SCENARIO_CONTROL = new ThingTypeUID(BINDING_ID, "bus_cen_scenario_control"); public static final String THING_LABEL_BUS_CEN_SCENARIO_CONTROL = "CEN Control"; @@ -91,7 +93,7 @@ public class OpenWebNetBindingConstants { THING_TYPE_BUS_AUTOMATION); // ## Thermoregulation public static final Set THERMOREGULATION_SUPPORTED_THING_TYPES = Set.of(THING_TYPE_BUS_THERMO_ZONE, - THING_TYPE_BUS_THERMO_SENSOR); + THING_TYPE_BUS_THERMO_SENSOR, THING_TYPE_BUS_THERMO_CU); // ## Energy Management public static final Set ENERGY_MANAGEMENT_SUPPORTED_THING_TYPES = Set.of(THING_TYPE_BUS_ENERGY_METER); // ## CEN/CEN+ Scenario @@ -126,6 +128,12 @@ public class OpenWebNetBindingConstants { public static final String CHANNEL_CONDITIONING_VALVES = "conditioningValves"; public static final String CHANNEL_HEATING_VALVES = "heatingValves"; public static final String CHANNEL_ACTUATORS = "actuators"; + public static final String CHANNEL_LOCAL_OFFSET = "localOffset"; + public static final String CHANNEL_CU_REMOTE_CONTROL = "remoteControl"; + public static final String CHANNEL_CU_BATTERY_STATUS = "batteryStatus"; + public static final String CHANNEL_CU_WEEKLY_PROGRAM_NUMBER = "weeklyProgram"; + public static final String CHANNEL_CU_SCENARIO_PROGRAM_NUMBER = "scenarioProgram"; + // energy management public static final String CHANNEL_POWER = "power"; // scenario button channels @@ -138,6 +146,8 @@ public class OpenWebNetBindingConstants { public static final String CONFIG_PROPERTY_WHERE = "where"; public static final String CONFIG_PROPERTY_SHUTTER_RUN = "shutterRun"; public static final String CONFIG_PROPERTY_SCENARIO_BUTTONS = "buttons"; + public static final String CONFIG_PROPERTY_STANDALONE = "standAlone"; + // gw config properties public static final String CONFIG_PROPERTY_HOST = "host"; public static final String CONFIG_PROPERTY_SERIAL_PORT = "serialPort"; diff --git a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/discovery/OpenWebNetDeviceDiscoveryService.java b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/discovery/OpenWebNetDeviceDiscoveryService.java index d2548a7f7..3065fbb39 100644 --- a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/discovery/OpenWebNetDeviceDiscoveryService.java +++ b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/discovery/OpenWebNetDeviceDiscoveryService.java @@ -144,7 +144,9 @@ public class OpenWebNetDeviceDiscoveryService extends AbstractDiscoveryService break; } case SCS_THERMO_CENTRAL_UNIT: { - logger.warn("newDiscoveryResult() deviceType={} is not supported yet (WHERE={})", deviceType, where); + thingTypeUID = OpenWebNetBindingConstants.THING_TYPE_BUS_THERMO_CU; + thingLabel = OpenWebNetBindingConstants.THING_LABEL_BUS_THERMO_CU; + deviceWho = Who.THERMOREGULATION; break; } case SCS_ENERGY_METER: { diff --git a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetThermoregulationHandler.java b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetThermoregulationHandler.java index 4dba0b938..340f6a342 100644 --- a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetThermoregulationHandler.java +++ b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetThermoregulationHandler.java @@ -12,7 +12,19 @@ */ package org.openhab.binding.openwebnet.internal.handler; -import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.*; +import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.CHANNEL_ACTUATORS; +import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.CHANNEL_CONDITIONING_VALVES; +import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.CHANNEL_CU_BATTERY_STATUS; +import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.CHANNEL_CU_REMOTE_CONTROL; +import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.CHANNEL_CU_SCENARIO_PROGRAM_NUMBER; +import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.CHANNEL_CU_WEEKLY_PROGRAM_NUMBER; +import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.CHANNEL_FAN_SPEED; +import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.CHANNEL_FUNCTION; +import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.CHANNEL_HEATING_VALVES; +import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.CHANNEL_LOCAL_OFFSET; +import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.CHANNEL_MODE; +import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.CHANNEL_TEMPERATURE; +import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.CHANNEL_TEMP_SETPOINT; import java.util.Set; @@ -25,6 +37,7 @@ import org.openhab.core.library.unit.SIUnits; import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.Thing; import org.openhab.core.thing.ThingStatus; +import org.openhab.core.thing.ThingStatusDetail; import org.openhab.core.thing.ThingStatusInfo; import org.openhab.core.thing.ThingTypeUID; import org.openhab.core.types.Command; @@ -34,6 +47,7 @@ import org.openwebnet4j.message.BaseOpenMessage; import org.openwebnet4j.message.FrameException; import org.openwebnet4j.message.MalformedFrameException; import org.openwebnet4j.message.Thermoregulation; +import org.openwebnet4j.message.Thermoregulation.WhatThermo; import org.openwebnet4j.message.Where; import org.openwebnet4j.message.WhereThermo; import org.openwebnet4j.message.Who; @@ -55,16 +69,49 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler { public static final Set SUPPORTED_THING_TYPES = OpenWebNetBindingConstants.THERMOREGULATION_SUPPORTED_THING_TYPES; - private boolean isTempSensor = false; // is the thing a sensor ? - private double currentSetPointTemp = 11.5d; // 11.5 is the default setTemp used in MyHomeUP mobile app private Thermoregulation.Function currentFunction = Thermoregulation.Function.GENERIC; + private boolean isStandAlone = false; + + private boolean isCentralUnit = false; + + private String programNumber = ""; + + private static final String CU_REMOTE_CONTROL_ENABLED = "ENABLED"; + private static final String CU_REMOTE_CONTROL_DISABLED = "DISABLED"; + private static final String CU_BATTERY_OK = "OK"; + private static final String CU_BATTERY_KO = "KO"; + public OpenWebNetThermoregulationHandler(Thing thing) { super(thing); } + @Override + public void initialize() { + super.initialize(); + + ThingTypeUID thingType = thing.getThingTypeUID(); + isCentralUnit = OpenWebNetBindingConstants.THING_TYPE_BUS_THERMO_CU.equals(thingType); + + if (!isCentralUnit) { + Object standAloneConfig = getConfig().get(OpenWebNetBindingConstants.CONFIG_PROPERTY_STANDALONE); + if (standAloneConfig != null) { + // null in case of thermo_sensor + isStandAlone = Boolean.parseBoolean(standAloneConfig.toString()); + } + } else { + // central unit must have WHERE=0 + if (!deviceWhere.value().equals("0")) { + logger.warn("initialize() Invalid WHERE={} for Central Unit.", deviceWhere.value()); + + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "@text/offline.conf-error-where"); + } + } + } + @Override public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) { super.bridgeStatusChanged(bridgeStatusInfo); @@ -89,6 +136,10 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler { case CHANNEL_FAN_SPEED: handleSetFanSpeed(command); break; + case CHANNEL_CU_WEEKLY_PROGRAM_NUMBER: + case CHANNEL_CU_SCENARIO_PROGRAM_NUMBER: + handleSetProgramNumber(command); + break; default: { logger.warn("handleChannelCommand() Unsupported ChannelUID {}", channel.getId()); } @@ -101,34 +152,9 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler { refreshDevice(false); } - @Override - protected void refreshDevice(boolean refreshAll) { - logger.debug("--- refreshDevice() : refreshing SINGLE... ({})", thing.getUID()); - if (deviceWhere != null) { - String w = deviceWhere.value(); - try { - send(Thermoregulation.requestTemperature(w)); - if (!this.isTempSensor) { - // for bus_thermo_zone request also other single channels updates - send(Thermoregulation.requestSetPointTemperature(w)); - send(Thermoregulation.requestFanCoilSpeed(w)); - send(Thermoregulation.requestMode(w)); - send(Thermoregulation.requestValvesStatus(w)); - send(Thermoregulation.requestActuatorsStatus(w)); - } - } catch (OWNException e) { - logger.warn("refreshDevice() where='{}' returned OWNException {}", w, e.getMessage()); - } - } - } - @Override protected Where buildBusWhere(String wStr) throws IllegalArgumentException { - WhereThermo wt = new WhereThermo(wStr); - if (wt.isProbe()) { - isTempSensor = true; - } - return wt; + return new WhereThermo(wStr); } @Override @@ -156,6 +182,21 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler { } } + private void handleSetProgramNumber(Command command) { + if (command instanceof DecimalType) { + if (!isCentralUnit) { + logger.warn("handleSetProgramNumber() This command can be sent only for a Central Unit."); + return; + } + + programNumber = command.toString(); + logger.debug("handleSetProgramNumber() Program number set to {}", programNumber); + + } else { + logger.warn("handleSetProgramNumber() Unsupported command {} for thing {}", command, getThing().getUID()); + } + } + private void handleSetpoint(Command command) { if (command instanceof QuantityType || command instanceof DecimalType) { Where w = deviceWhere; @@ -170,7 +211,8 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler { newTemp = ((DecimalType) command).doubleValue(); } try { - send(Thermoregulation.requestWriteSetpointTemperature(w.value(), newTemp, currentFunction)); + send(Thermoregulation.requestWriteSetpointTemperature(getWhere(w.value()), newTemp, + currentFunction)); } catch (MalformedFrameException | OWNException e) { logger.warn("handleSetpoint() {}", e.getMessage()); } @@ -185,8 +227,15 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler { Where w = deviceWhere; if (w != null) { try { - Thermoregulation.OperationMode mode = Thermoregulation.OperationMode.valueOf(command.toString()); - send(Thermoregulation.requestWriteMode(w.value(), mode, currentFunction, currentSetPointTemp)); + Thermoregulation.OperationMode new_mode = Thermoregulation.OperationMode.OFF; + + if (isCentralUnit && WhatThermo.isComplex(command.toString())) + new_mode = Thermoregulation.OperationMode.valueOf(command.toString() + "_" + programNumber); + else + new_mode = Thermoregulation.OperationMode.valueOf(command.toString()); + + send(Thermoregulation.requestWriteMode(getWhere(w.value()), new_mode, currentFunction, + currentSetPointTemp)); } catch (OWNException e) { logger.warn("handleMode() {}", e.getMessage()); } catch (IllegalArgumentException e) { @@ -199,6 +248,14 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler { } } + private String getWhere(String where) { + if (isCentralUnit) { + return "#0"; + } else { + return isStandAlone ? where : "#" + where; + } + } + private void handleFunction(Command command) { if (command instanceof StringType) { Where w = deviceWhere; @@ -221,6 +278,23 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler { @Override protected void handleMessage(BaseOpenMessage msg) { super.handleMessage(msg); + + if (isCentralUnit) { + if (msg.isCommand()) { + updateModeAndFunction((Thermoregulation) msg); + } + + if (msg.getWhat() == Thermoregulation.WhatThermo.REMOTE_CONTROL_DISABLED) { + updateCURemoteControlStatus(CU_REMOTE_CONTROL_DISABLED); + } else if (msg.getWhat() == Thermoregulation.WhatThermo.REMOTE_CONTROL_ENABLED) { + updateCURemoteControlStatus(CU_REMOTE_CONTROL_ENABLED); + } else if (msg.getWhat() == Thermoregulation.WhatThermo.BATTERY_KO) { + updateCUBatteryStatus(CU_BATTERY_KO); + } + + return; + } + if (msg.isCommand()) { updateModeAndFunction((Thermoregulation) msg); } else { @@ -239,6 +313,8 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler { updateActuatorStatus((Thermoregulation) msg); } else if (msg.getDim() == Thermoregulation.DimThermo.FAN_COIL_SPEED) { updateFanCoilSpeed((Thermoregulation) msg); + } else if (msg.getDim() == Thermoregulation.DimThermo.OFFSET) { + updateLocalOffset((Thermoregulation) msg); } else { logger.debug("handleMessage() Ignoring unsupported DIM {} for thing {}. Frame={}", msg.getDim(), getThing().getUID(), msg); @@ -252,7 +328,6 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler { tmsg.getFrameValue()); return; } - Thermoregulation.WhatThermo w = Thermoregulation.WhatThermo.fromValue(tmsg.getWhat().value()); if (w.getMode() == null) { @@ -267,14 +342,8 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler { Thermoregulation.OperationMode mode = w.getMode(); Thermoregulation.Function function = w.getFunction(); - if (w == Thermoregulation.WhatThermo.HEATING) { - function = Thermoregulation.Function.HEATING; - } else if (w == Thermoregulation.WhatThermo.CONDITIONING) { - function = Thermoregulation.Function.COOLING; - } - - updateState(CHANNEL_MODE, new StringType(mode.toString())); updateState(CHANNEL_FUNCTION, new StringType(function.toString())); + updateState(CHANNEL_MODE, new StringType(mode.toString())); // store current function currentFunction = function; @@ -336,4 +405,82 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler { updateState(CHANNEL_ACTUATORS, UnDefType.UNDEF); } } + + private void updateLocalOffset(Thermoregulation tmsg) { + try { + Thermoregulation.LocalOffset offset = Thermoregulation.parseLocalOffset(tmsg); + updateState(CHANNEL_LOCAL_OFFSET, new StringType(offset.toString())); + logger.debug("updateLocalOffset() {}: {}", tmsg, offset.toString()); + + } catch (FrameException e) { + logger.warn("updateLocalOffset() FrameException on frame {}: {}", tmsg, e.getMessage()); + updateState(CHANNEL_LOCAL_OFFSET, UnDefType.UNDEF); + } + } + + private void updateCURemoteControlStatus(String status) { + updateState(CHANNEL_CU_REMOTE_CONTROL, new StringType(status)); + logger.debug("updateCURemoteControlStatus(): {}", status); + } + + private void updateCUBatteryStatus(String status) { + updateState(CHANNEL_CU_BATTERY_STATUS, new StringType(status)); + logger.debug("updateCUBatteryStatus(): {}", status); + } + + private Boolean channelExists(String channelID) { + return thing.getChannel("openwebnet:" + channelID) != null; + } + + @Override + protected void refreshDevice(boolean refreshAll) { + logger.debug("--- refreshDevice() : refreshing SINGLE... ({})", thing.getUID()); + if (isCentralUnit) { + // TODO: 4 zone central -> zone #0 CAN be also a zone with its temp.. with 99-zones central no! + // let's assume it's a 99 zone + try { + // there isn't a message used for setting OK for battery status so let's assume + // it's OK and then change to KO if according message is received + updateCUBatteryStatus(CU_BATTERY_OK); + send(Thermoregulation.requestStatus("#0")); + } catch (OWNException e) { + logger.warn("refreshDevice() central unit returned OWNException {}", e.getMessage()); + } + + return; + } + + if (deviceWhere != null) { + + String w = deviceWhere.value(); + try { + send(Thermoregulation.requestTemperature(w)); + + if (!((WhereThermo) deviceWhere).isProbe()) { + // for bus_thermo_zone request also other single channels updates + send(Thermoregulation.requestSetPointTemperature(w)); + send(Thermoregulation.requestMode(w)); + + // refresh ONLY subscribed channels + if (channelExists(CHANNEL_FAN_SPEED)) { + send(Thermoregulation.requestFanCoilSpeed(w)); + } + + if (channelExists(CHANNEL_CONDITIONING_VALVES) || channelExists(CHANNEL_HEATING_VALVES)) { + send(Thermoregulation.requestValvesStatus(w)); + } + + if (channelExists(CHANNEL_ACTUATORS)) { + send(Thermoregulation.requestActuatorsStatus(w)); + } + + if (channelExists(CHANNEL_LOCAL_OFFSET)) { + send(Thermoregulation.requestLocalOffset(w)); + } + } + } catch (OWNException e) { + logger.warn("refreshDevice() where='{}' returned OWNException {}", w, e.getMessage()); + } + } + } } diff --git a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetThingHandler.java b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetThingHandler.java index 3ab7523eb..eac769297 100644 --- a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetThingHandler.java +++ b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetThingHandler.java @@ -12,7 +12,9 @@ */ package org.openhab.binding.openwebnet.internal.handler; -import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.*; +import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.CONFIG_PROPERTY_WHERE; +import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.PROPERTY_OWNID; +import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.THING_STATE_REQ_TIMEOUT_SEC; import java.util.Map; import java.util.concurrent.ScheduledFuture; diff --git a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusThermoCentralUnit.xml b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusThermoCentralUnit.xml new file mode 100644 index 000000000..8f77cedf3 --- /dev/null +++ b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusThermoCentralUnit.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + A OpenWebNet BUS/SCS configured thermo Central Unit. + + + + + + + + + + + + + + BTicino/Legrand + BTicino Central Unit 3550 (99 zones) or BTI-L/NT/HC/4695 (4 zones) + 430 + + + ownId + + + + + The Central Unit can only assume where=0. + 0 + + + + diff --git a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusThermoZone.xml b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusThermoZone.xml index 85032f752..7b8c2562f 100644 --- a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusThermoZone.xml +++ b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusThermoZone.xml @@ -19,6 +19,7 @@ + diff --git a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/channels.xml b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/channels.xml index 9e9cf3fcb..a2b4c2343 100644 --- a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/channels.xml @@ -171,6 +171,104 @@ + + String + + Local knob status (read only) + + + + + + + + + + + + + + + + + String + + Set mode of the Central Unit (read/write) + + + + + + + + + + + + + Number + + Set weekly program number for the Central Unit, valid only with Central Unit mode = "WEEKLY" (read/write) + + + + + + + + + + + Number + + Set scenario program number for the Central Unit, valid only with Central Unit mode = "SCENARIO" + (read/write) + + + + + + + + + + + + + + + + + + + + + + + + String + + Central Unit Remote Control status (read only) + + + + + + + + + + String + + Central Unit Battery status (read only) + + + + + + + + Number:Power