### 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
- 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
- `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
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" ]
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" }
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";
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
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
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";
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: {
*/
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;
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;
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;
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);
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());
}
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
}
}
+ 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;
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());
}
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) {
}
}
+ 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;
@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 {
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);
tmsg.getFrameValue());
return;
}
-
Thermoregulation.WhatThermo w = Thermoregulation.WhatThermo.fromValue(tmsg.getWhat().value());
if (w.getMode() == null) {
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;
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());
+ }
+ }
+ }
}
*/
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;
--- /dev/null
+<?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>
<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"/>
</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>