[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 <andrea@conte.com>

Co-authored-by: M Valla <12682715+mvalla@users.noreply.github.com>
This commit is contained in:
Conte Andrea 2022-02-27 19:11:45 +01:00 committed by GitHub
parent 339df2cb3a
commit b2765a3895
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 414 additions and 81 deletions

View File

@ -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" }

View File

@ -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<ThingTypeUID> 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<ThingTypeUID> 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";

View File

@ -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: {

View File

@ -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<ThingTypeUID> 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());
}
}
}
}

View File

@ -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;

View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="openwebnet"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<!-- Thing for BUS Thermo Central Unit -->
<thing-type id="bus_thermo_cu">
<supported-bridge-type-refs>
<bridge-type-ref id="bus_gateway"/>
</supported-bridge-type-refs>
<label>Thermo Central Unit</label>
<description>A OpenWebNet BUS/SCS configured thermo Central Unit.</description>
<channels>
<!-- read only -->
<channel id="remoteControl" typeId="remoteControl"/>
<channel id="batteryStatus" typeId="batteryStatus"/>
<!-- read/write -->
<channel id="setpointTemperature" typeId="setpointTemperature"/>
<channel id="mode" typeId="modeCentralUnit"/>
<channel id="weeklyProgram" typeId="weeklyProgramCentralUnit"/>
<channel id="scenarioProgram" typeId="scenarioProgramCentralUnit"/>
</channels>
<properties>
<property name="vendor">BTicino/Legrand</property>
<property name="model">BTicino Central Unit 3550 (99 zones) or BTI-L/NT/HC/4695 (4 zones) </property>
<property name="ownDeviceType">430</property>
</properties>
<representation-property>ownId</representation-property>
<config-description>
<parameter name="where" type="text" readOnly="true">
<label>OpenWebNet Address (where)</label>
<description>The Central Unit can only assume where=0.</description>
<default>0</default>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>

View File

@ -19,6 +19,7 @@
<channel id="conditioningValves" typeId="conditioningValves"/>
<channel id="heatingValves" typeId="heatingValves"/>
<channel id="actuators" typeId="actuators"/>
<channel id="localOffset" typeId="localOffset"/>
<!-- read/write -->
<channel id="setpointTemperature" typeId="setpointTemperature"/>
<channel id="function" typeId="function"/>

View File

@ -171,6 +171,104 @@
</state>
</channel-type>
<channel-type id="localOffset" advanced="true">
<item-type>String</item-type>
<label>Local Offset</label>
<description>Local knob status (read only)</description>
<state readOnly="true">
<options>
<option value="OFF">OFF</option>
<option value="PROTECTION">PROTECTION</option>
<option value="PLUS_3">+3</option>
<option value="PLUS_2">+2</option>
<option value="PLUS_1">+1</option>
<option value="NORMAL">0</option>
<option value="MINUS_1">-1</option>
<option value="MINUS_2">-2</option>
<option value="MINUS_3">-3</option>
</options>
</state>
</channel-type>
<channel-type id="modeCentralUnit">
<item-type>String</item-type>
<label>Central Unit Mode</label>
<description>Set mode of the Central Unit (read/write)</description>
<state>
<options>
<option value="MANUAL">Manual</option>
<option value="PROTECTION">Protection</option>
<option value="OFF">Off</option>
<option value="WEEKLY">Weekly</option>
<option value="SCENARIO">Scenario</option>
</options>
</state>
</channel-type>
<channel-type id="weeklyProgramCentralUnit">
<item-type>Number</item-type>
<label>Weekly Program Number</label>
<description>Set weekly program number for the Central Unit, valid only with Central Unit mode = "WEEKLY" (read/write)</description>
<state>
<options>
<option value="1">Program 1</option>
<option value="2">Program 2</option>
<option value="3">Program 3</option>
</options>
</state>
</channel-type>
<channel-type id="scenarioProgramCentralUnit">
<item-type>Number</item-type>
<label>Scenario Program Number</label>
<description>Set scenario program number for the Central Unit, valid only with Central Unit mode = "SCENARIO"
(read/write)</description>
<state>
<options>
<option value="1">Program 1</option>
<option value="2">Program 2</option>
<option value="3">Program 3</option>
<option value="4">Program 4</option>
<option value="5">Program 5</option>
<option value="6">Program 6</option>
<option value="7">Program 7</option>
<option value="8">Program 8</option>
<option value="9">Program 9</option>
<option value="10">Program 10</option>
<option value="11">Program 11</option>
<option value="12">Program 12</option>
<option value="13">Program 13</option>
<option value="14">Program 14</option>
<option value="15">Program 15</option>
<option value="16">Program 16</option>
</options>
</state>
</channel-type>
<channel-type id="remoteControl" advanced="true">
<item-type>String</item-type>
<label>Remote Control</label>
<description>Central Unit Remote Control status (read only)</description>
<state readOnly="true">
<options>
<option value="DISABLED">DISABLED</option>
<option value="ENABLED">ENABLED</option>
</options>
</state>
</channel-type>
<channel-type id="batteryStatus" advanced="true">
<item-type>String</item-type>
<label>Battery Status</label>
<description>Central Unit Battery status (read only)</description>
<state readOnly="true">
<options>
<option value="OK">OK</option>
<option value="KO">KO</option>
</options>
</state>
</channel-type>
<!-- Energy channels -->
<channel-type id="power">
<item-type>Number:Power</item-type>