From 8f7289dbb5645f51c67e7e0d35bbf5feb306f8a6 Mon Sep 17 00:00:00 2001 From: M Valla <12682715+mvalla@users.noreply.github.com> Date: Mon, 13 May 2024 07:10:36 +0200 Subject: [PATCH] [openwebnet] add support for lights general/area/group events and Things (#15921) * [openwebnet] initial support for general/area light events Signed-off-by: Massimo Valla Signed-off-by: Ciprian Pascu --- .../org.openhab.binding.openwebnet/README.md | 69 ++++-- .../internal/OpenWebNetBindingConstants.java | 11 +- .../internal/OpenWebNetHandlerFactory.java | 4 + .../OpenWebNetDeviceDiscoveryService.java | 66 +++++- .../handler/LightAutomHandlersMap.java | 148 +++++++++++++ .../handler/OpenWebNetAlarmHandler.java | 4 +- .../handler/OpenWebNetAutomationHandler.java | 4 +- .../handler/OpenWebNetAuxiliaryHandler.java | 4 +- .../handler/OpenWebNetBridgeHandler.java | 101 +++++++-- .../handler/OpenWebNetEnergyHandler.java | 4 +- .../handler/OpenWebNetGenericHandler.java | 5 +- .../OpenWebNetLightingGroupHandler.java | 208 ++++++++++++++++++ .../handler/OpenWebNetLightingHandler.java | 95 +++++++- .../OpenWebNetScenarioBasicHandler.java | 4 +- .../handler/OpenWebNetScenarioHandler.java | 6 +- .../OpenWebNetThermoregulationHandler.java | 4 +- .../handler/OpenWebNetThingHandler.java | 13 +- .../OH-INF/i18n/openwebnet.properties | 4 + .../resources/OH-INF/thing/BusLightGroup.xml | 37 ++++ .../internal/handler/OwnIdTest.java | 24 +- 20 files changed, 731 insertions(+), 84 deletions(-) create mode 100644 bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/LightAutomHandlersMap.java create mode 100644 bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetLightingGroupHandler.java create mode 100644 bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusLightGroup.xml diff --git a/bundles/org.openhab.binding.openwebnet/README.md b/bundles/org.openhab.binding.openwebnet/README.md index 36beca29109..5c5a797fb14 100644 --- a/bundles/org.openhab.binding.openwebnet/README.md +++ b/bundles/org.openhab.binding.openwebnet/README.md @@ -41,17 +41,17 @@ The following Things and OpenWebNet `WHOs` are supported: ### For MyHOME - BUS/SCS -| 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: Thermostats H/LN4691, HS4692, KG4691; sensors (probes): L/N/NT4577 + 3455; Central Units 4-zones (models L/N/NT/HD/HC/HS4695) and 99-zones (model 3550). See [Channels - Thermo](#configuring-thermo) for more details | -| Alarm | `5` | `bus_alarm_system`, `bus_alarm_zone` | BUS Alarm system and zones | Successfully tested: Burglar-alarm Unit 3486 | -| Auxiliary (AUX) | `9` | `bus_aux` | AUX commands | Successfully tested: AUX configured for Burglar-alarm Unit 3486. **Only sending AUX commands is supported** | -| Basic, CEN & CEN+ Scenarios | `0`, `15`, `25` | `bus_scenario_control`, `bus_cen_scenario_control`, `bus_cenplus_scenario_control` | Basic and CEN/CEN+ Scenarios events and virtual activation | Successfully tested: CEN/CEN+ scenario control: HC/HD/HS/L/N/NT4680 and basic scenario modules F420/IR3456 + L4680 (WHO=0) | -| 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. Partially tested: F522, F523 | +| 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_light_group` | BUS switches and dimmers and groups of them | 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: Thermostats H/LN4691, HS4692, KG4691; sensors (probes): L/N/NT4577 + 3455; Central Units 4-zones (models L/N/NT/HD/HC/HS4695) and 99-zones (model 3550). See [Channels - Thermo](#configuring-thermo) for more details | +| Alarm | `5` | `bus_alarm_system`, `bus_alarm_zone` | BUS Alarm system and zones | Successfully tested: Burglar-alarm Unit 3486 | +| Auxiliary (AUX) | `9` | `bus_aux` | AUX commands | Successfully tested: AUX configured for Burglar-alarm Unit 3486. **Only sending AUX commands is supported** | +| Basic, CEN & CEN+ Scenarios | `0`, `15`, `25` | `bus_scenario_control`, `bus_cen_scenario_control`, `bus_cenplus_scenario_control` | Basic and CEN/CEN+ Scenarios events and virtual activation | Successfully tested: CEN/CEN+ scenario control: HC/HD/HS/L/N/NT4680 and basic scenario modules F420/IR3456 + L4680 (WHO=0) | +| 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. Partially tested: F522, F523 | ### For MyHOME Radio - Zigbee @@ -133,8 +133,9 @@ For any manually added device, you must configure: - the associated gateway Thing (`Parent Bridge` menu) - the `where` configuration parameter (`OpenWebNet Address`): this is the OpenWebNet address configured for the device in the BTicino/Legrand system. This address can be found either on the device itself (Physical configuration, using jumpers in case of BUS) or through the MyHOME_Suite software (Virtual configuration). The address can have several formats depending on the device/system: - example for MyHOME - BUS/SCS system: - - light device A=`2` (Area 2), PL=`4` (Light-point 4) --> `where="24"` + - light device A=`2` (room 2), PL=`4` (light-point 4) --> `where="24"` - light device A=`03`, PL=`11` on local bus `01` --> `where="0311#4#01"` + - lights in room 5 (A=`AMB`, PL=`5`) --> `where="5"` - scenario control module address `53` --> `where="53"` - CEN scenario A=`05`, PL=`12` --> `where="0512"` - CEN+ scenario `5`: add `2` before --> `where="25"` @@ -210,22 +211,36 @@ Event: command OPEN = *9*1*5## OPEN command to execute: *5*8#134## ``` +#### Configuring Light Groups (Room/Group/General) + +The `bus_light_group` Thing type represents a set of devices belonging to a room or group in the BUS system: + +- `bus_light_group` with `where="5"` will be associated to all lights configured in room 5 (A=`5`) +- `bus_light_group` with `where="#4"` will be associated to all lights belonging to group 4 (G=`4`) +- `bus_light_group` with `where="0"` will be associated to all lights in the system (General). + +It's not mandatory to define `bus_light_group` Things: however adding them is useful to send commands to a set of lights or to track state of a room/all lights when one of the members changes state. +It's also not mandatory to define `bus_light_group` Things to track state of a light when a room/group/general ON/OFF command is sent on the BUS (the light state will be updated in any case). + +**NOTE 1** +For a `bus_light_group` Thing to be updated properly, at least one light Thing belonging to that room/group must also be configured. + ## Channels ### Lighting, Automation, Basic/CEN/CEN+ Scenario Events, Dry Contact / IR Interfaces, Power and AUX 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 | -| `scenario`   | `bus_scenario_control` | String | Trigger channel for Basic scenario events [see possible values](#scenario-channels) | R (TRIGGER) | -| `button#X` | `bus_cen_scenario_control`, `bus_cenplus_scenario_control` | String | Trigger channel for CEN/CEN+ scenario events [see possible values](#scenario-channels) | R (TRIGGER) | -| `sensor` | `bus_dry_contact_ir` | Switch | If a Dry Contact Interface is `ON`/`OFF`, or if an 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 | -| `energyToday` | `bus_energy_meter` | Number:Energy | Current day energy | R | -| `energyThisMonth` | `bus_energy_meter` | Number:Energy | Current month energy | R | -| `aux` | `bus_aux` | String | Possible commands: `ON`, `OFF`, `TOGGLE`, `STOP`, `UP`, `DOWN`, `ENABLED`, `DISABLED`, `RESET_GEN`, `RESET_BI`, `RESET_TRI`. Only `ON` and `OFF` are supported for now | R/W | +| 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`, `bus_light_group`, `zb_on_off_switch`, `zb_on_off_switch2u` | Switch | To switch the device (or group) `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 | +| `scenario` | `bus_scenario_control` | String | Trigger channel for Basic scenario events [see possible values](#scenario-channels) | R (TRIGGER) | +| `button#X` | `bus_cen_scenario_control`, `bus_cenplus_scenario_control` | String | Trigger channel for CEN/CEN+ scenario events [see possible values](#scenario-channels) | R (TRIGGER) | +| `sensor` | `bus_dry_contact_ir` | Switch | If a Dry Contact Interface is `ON`/`OFF`, or if an 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 | +| `energyToday` | `bus_energy_meter` | Number:Energy | Current day energy | R | +| `energyThisMonth` | `bus_energy_meter` | Number:Energy | Current month energy | R | +| `aux` | `bus_aux` | String | Possible commands: `ON`, `OFF`, `TOGGLE`, `STOP`, `UP`, `DOWN`, `ENABLED`, `DISABLED`, `RESET_GEN`, `RESET_BI`, `RESET_TRI`. Only `ON` and `OFF` are supported for now | R/W | ### Alarm channels @@ -375,6 +390,8 @@ MyHOME BUS/SCS gateway and Things configuration: ```java Bridge openwebnet:bus_gateway:mybridge "MyHOMEServer1" [ host="192.168.1.35", passwd="abcde", port=20000, discoveryByActivation=false ] { + bus_light_group ALL_lights "All lights" [ where="0" ] + bus_light_group LR_room "Living Room" [ where="5" ] 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="20050"] @@ -417,6 +434,8 @@ NOTE: lights, blinds and zones (thermostat) can be handled from personal assista In the following example some `Google Assistant` (`ga="..."`) and `HomeKit` (`homekit="..."`) metadata were added as examples according to the [documentation for Google Assistant integration on openHAB](https://www.openhab.org/docs/ecosystem/google-assistant) and [the openHAB HomeKit Add-on documentation](https://www.openhab.org/addons/integrations/homekit/): see the specific openHAB documentation for updated configurations and more metadata options. ```java +Switch iALL_lights "All Lights" { channel="openwebnet:bus_light_group:mybridge:ALL_lights:switch", ga="Light", homekit="Lighting" } +Switch iLR_room "Living Room" { channel="openwebnet:bus_light_group:mybridge:LR_room:switch", ga="Light", homekit="Lighting" } 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" } @@ -486,6 +505,8 @@ sitemap openwebnet label="OpenWebNet Binding Example Sitemap" { Frame label="Living Room" { + Default item=iALL_lights icon="light" + Default item=iLR_room icon="light" Default item=iLR_switch icon="light" Default item=iLR_dimmer icon="light" Default item=iLR_shutter 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 4fff9f74cc9..add37a0c852 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 @@ -25,10 +25,10 @@ import org.openhab.core.thing.ThingTypeUID; * The {@link OpenWebNetBindingConstants} class defines common constants, which * are used across the whole binding. * - * @author Massimo Valla - Initial contribution, updates + * @author Massimo Valla - Initial contribution, updates. Light groups. * @author Gilberto Cocchi - Thermoregulation * @author Andrea Conte - Energy management, Thermoregulation - * @author Giovanni Fabiani - Aux support + * @author Giovanni Fabiani - AUX support */ @NonNullByDefault @@ -53,6 +53,10 @@ public class OpenWebNetBindingConstants { public static final String THING_LABEL_BUS_ON_OFF_SWITCH = "Switch"; public static final ThingTypeUID THING_TYPE_BUS_DIMMER = new ThingTypeUID(BINDING_ID, "bus_dimmer"); public static final String THING_LABEL_BUS_DIMMER = "Dimmer"; + + public static final ThingTypeUID THING_TYPE_BUS_LIGHT_GROUP = new ThingTypeUID(BINDING_ID, "bus_light_group"); + public static final String THING_LABEL_BUS_LIGHT_GROUP = "Light Group"; + public static final ThingTypeUID THING_TYPE_BUS_AUTOMATION = new ThingTypeUID(BINDING_ID, "bus_automation"); public static final String THING_LABEL_BUS_AUTOMATION = "Automation"; public static final ThingTypeUID THING_TYPE_BUS_ENERGY_METER = new ThingTypeUID(BINDING_ID, "bus_energy_meter"); @@ -97,6 +101,7 @@ public class OpenWebNetBindingConstants { public static final Set LIGHTING_SUPPORTED_THING_TYPES = Set.of(THING_TYPE_ZB_ON_OFF_SWITCH, THING_TYPE_ZB_ON_OFF_SWITCH_2UNITS, THING_TYPE_ZB_DIMMER, THING_TYPE_BUS_ON_OFF_SWITCH, THING_TYPE_BUS_DIMMER); + public static final Set LIGHTING_GROUP_SUPPORTED_THING_TYPES = Set.of(THING_TYPE_BUS_LIGHT_GROUP); // ## Automation public static final Set AUTOMATION_SUPPORTED_THING_TYPES = Set.of(THING_TYPE_ZB_AUTOMATION, THING_TYPE_BUS_AUTOMATION); @@ -118,7 +123,7 @@ public class OpenWebNetBindingConstants { // ## Groups public static final Set DEVICE_SUPPORTED_THING_TYPES = Stream - .of(LIGHTING_SUPPORTED_THING_TYPES, AUTOMATION_SUPPORTED_THING_TYPES, + .of(LIGHTING_SUPPORTED_THING_TYPES, LIGHTING_GROUP_SUPPORTED_THING_TYPES, AUTOMATION_SUPPORTED_THING_TYPES, THERMOREGULATION_SUPPORTED_THING_TYPES, ENERGY_MANAGEMENT_SUPPORTED_THING_TYPES, SCENARIO_SUPPORTED_THING_TYPES, SCENARIO_BASIC_SUPPORTED_THING_TYPES, AUX_SUPPORTED_THING_TYPES, ALARM_SUPPORTED_THING_TYPES, GENERIC_SUPPORTED_THING_TYPES) diff --git a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/OpenWebNetHandlerFactory.java b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/OpenWebNetHandlerFactory.java index cc7aed40ece..bec7a46e5b6 100644 --- a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/OpenWebNetHandlerFactory.java +++ b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/OpenWebNetHandlerFactory.java @@ -22,6 +22,7 @@ import org.openhab.binding.openwebnet.internal.handler.OpenWebNetAuxiliaryHandle import org.openhab.binding.openwebnet.internal.handler.OpenWebNetBridgeHandler; import org.openhab.binding.openwebnet.internal.handler.OpenWebNetEnergyHandler; import org.openhab.binding.openwebnet.internal.handler.OpenWebNetGenericHandler; +import org.openhab.binding.openwebnet.internal.handler.OpenWebNetLightingGroupHandler; import org.openhab.binding.openwebnet.internal.handler.OpenWebNetLightingHandler; import org.openhab.binding.openwebnet.internal.handler.OpenWebNetScenarioBasicHandler; import org.openhab.binding.openwebnet.internal.handler.OpenWebNetScenarioHandler; @@ -66,6 +67,9 @@ public class OpenWebNetHandlerFactory extends BaseThingHandlerFactory { } else if (OpenWebNetLightingHandler.SUPPORTED_THING_TYPES.contains(thing.getThingTypeUID())) { logger.debug("creating NEW LIGHTING Handler --- {}", thing.getUID()); return new OpenWebNetLightingHandler(thing); + } else if (OpenWebNetLightingGroupHandler.SUPPORTED_THING_TYPES.contains(thing.getThingTypeUID())) { + logger.debug("creating NEW LIGHTING GROUP Handler --- {}", thing.getUID()); + return new OpenWebNetLightingGroupHandler(thing); } else if (OpenWebNetAutomationHandler.SUPPORTED_THING_TYPES.contains(thing.getThingTypeUID())) { logger.debug("creating NEW AUTOMATION Handler --- {}", thing.getUID()); return new OpenWebNetAutomationHandler(thing); 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 55333501139..6157d25fffe 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 @@ -29,6 +29,7 @@ import org.openwebnet4j.OpenDeviceType; import org.openwebnet4j.message.BaseOpenMessage; import org.openwebnet4j.message.Where; import org.openwebnet4j.message.WhereAlarm; +import org.openwebnet4j.message.WhereLightAutom; import org.openwebnet4j.message.WhereThermo; import org.openwebnet4j.message.WhereZigBee; import org.openwebnet4j.message.Who; @@ -41,7 +42,7 @@ import org.slf4j.LoggerFactory; * The {@link OpenWebNetDeviceDiscoveryService} is responsible for discovering * OpenWebNet devices connected to a bridge/gateway * - * @author Massimo Valla - Initial contribution + * @author Massimo Valla - Initial contribution. Discovery of BUS light Group * @author Andrea Conte - Energy management, Thermoregulation * @author Gilberto Cocchi - Thermoregulation * @author Giovanni Fabiani - Aux support @@ -56,7 +57,8 @@ public class OpenWebNetDeviceDiscoveryService extends AbstractThingHandlerDiscov private @NonNullByDefault({}) ThingUID bridgeUID; - private boolean cuFound = false; + private boolean thermoCUFound = false; + private boolean lightFound = false; public OpenWebNetDeviceDiscoveryService() { super(OpenWebNetBridgeHandler.class, SUPPORTED_THING_TYPES, SEARCH_TIME_SEC); @@ -71,7 +73,9 @@ public class OpenWebNetDeviceDiscoveryService extends AbstractThingHandlerDiscov protected void startScan() { logger.info("------ SEARCHING for DEVICES on bridge '{}' ({}) ...", thingHandler.getThing().getLabel(), bridgeUID); - cuFound = false; + + thermoCUFound = false; + lightFound = false; thingHandler.searchDevices(); } @@ -223,14 +227,20 @@ public class OpenWebNetDeviceDiscoveryService extends AbstractThingHandlerDiscov } String ownId = thingHandler.ownIdFromWhoWhere(deviceWho, w); - if (OpenWebNetBindingConstants.THING_TYPE_BUS_ON_OFF_SWITCH.equals(thingTypeUID)) { + if (OpenWebNetBindingConstants.THING_TYPE_BUS_ON_OFF_SWITCH.equals(thingTypeUID) + || OpenWebNetBindingConstants.THING_TYPE_BUS_DIMMER.equals(thingTypeUID)) { + WhereLightAutom wla = (WhereLightAutom) w; + discoverBUSGroups(deviceWho, wla); + if (wla.isGroup()) { // group thing has been already discovered in previous line + return; + } if (thingHandler.getRegisteredDevice(ownId) != null) { logger.debug("dimmer/switch with WHERE={} already registered, skipping this discovery result", w); return; } } - String tId = thingHandler.thingIdFromWhere(w); + String tId = thingHandler.thingIdFromWhoWhere(deviceWho, w); ThingUID thingUID = new ThingUID(thingTypeUID, bridgeUID, tId); DiscoveryResult discoveryResult = null; @@ -246,7 +256,7 @@ public class OpenWebNetDeviceDiscoveryService extends AbstractThingHandlerDiscov // detect Thermo CU type if (OpenWebNetBindingConstants.THING_TYPE_BUS_THERMO_CU.equals(thingTypeUID)) { - cuFound = true; + thermoCUFound = true; logger.debug("CU found: {}", w); if (w.value().charAt(0) == '#') { // 99-zone CU thingLabel += " 99-zone"; @@ -258,7 +268,7 @@ public class OpenWebNetDeviceDiscoveryService extends AbstractThingHandlerDiscov logger.debug("@@@@ THERMO CU found 4-zone: where={}, ownId={}, whereConfig={}", w, ownId, whereConfig); } } else if (OpenWebNetBindingConstants.THING_TYPE_BUS_THERMO_ZONE.equals(thingTypeUID)) { - if (cuFound) { + if (thermoCUFound) { // set param standalone = false for thermo zone properties.put(OpenWebNetBindingConstants.CONFIG_PROPERTY_STANDALONE, false); } @@ -292,6 +302,48 @@ public class OpenWebNetDeviceDiscoveryService extends AbstractThingHandlerDiscov thingDiscovered(discoveryResult); } + private void discoverBUSGroups(Who deviceWho, WhereLightAutom where) { + if (!lightFound) { + lightFound = true; + createGroupDiscoveryResult(deviceWho, (WhereLightAutom) WhereLightAutom.GENERAL); + } + if (where.isGroup()) { + createGroupDiscoveryResult(deviceWho, where); + } else { + createGroupDiscoveryResult(deviceWho, new WhereLightAutom(Integer.toString(where.getArea()))); + } + } + + private void createGroupDiscoveryResult(Who deviceWho, WhereLightAutom where) { + Map properties = new HashMap<>(2); + String ownId = thingHandler.ownIdFromWhoWhere(deviceWho, where); + String tId = thingHandler.thingIdFromWhoWhere(deviceWho, where); + + String thingLabel = OpenWebNetBindingConstants.THING_LABEL_BUS_LIGHT_GROUP; + + if (where.isGeneral()) { + thingLabel = "General " + thingLabel; + } else if (where.isArea()) { + thingLabel = "Area " + where.getArea() + " " + thingLabel; + } else { + thingLabel += " " + where.value(); + } + + ThingUID thingUID = new ThingUID(OpenWebNetBindingConstants.THING_TYPE_BUS_LIGHT_GROUP, bridgeUID, tId); + String whereConfig = where.value(); + + properties.put(OpenWebNetBindingConstants.CONFIG_PROPERTY_WHERE, whereConfig); + properties.put(OpenWebNetBindingConstants.PROPERTY_OWNID, ownId); + + thingLabel = thingLabel + " (WHERE=" + whereConfig + ")"; + + DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID) + .withThingType(OpenWebNetBindingConstants.THING_TYPE_BUS_LIGHT_GROUP).withProperties(properties) + .withRepresentationProperty(OpenWebNetBindingConstants.PROPERTY_OWNID).withBridge(bridgeUID) + .withLabel(thingLabel).build(); + thingDiscovered(discoveryResult); + } + @Override public void initialize() { thingHandler.deviceDiscoveryService = this; diff --git a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/LightAutomHandlersMap.java b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/LightAutomHandlersMap.java new file mode 100644 index 00000000000..09e0156bf15 --- /dev/null +++ b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/LightAutomHandlersMap.java @@ -0,0 +1,148 @@ +/** + * Copyright (c) 2010-2024 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.openwebnet.internal.handler; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openwebnet4j.message.WhereLightAutom; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * A map to store handlers for lights and automations. The map is organised by + * Area. + * + * @author Massimo Valla - Initial contribution + */ +@NonNullByDefault +public class LightAutomHandlersMap { + + private final Logger logger = LoggerFactory.getLogger(LightAutomHandlersMap.class); + + private Map> hndlrsMap; + private @Nullable OpenWebNetThingHandler oneHandler = null; + + protected LightAutomHandlersMap() { + hndlrsMap = new ConcurrentHashMap<>(); + } + + protected void add(int area, OpenWebNetThingHandler handler) { + if (!hndlrsMap.containsKey(area)) { + hndlrsMap.put(area, new ConcurrentHashMap<>()); + } + Map areaHndlrs = hndlrsMap.get(Integer.valueOf(area)); + final String handlerOwnId = handler.ownId; + if (areaHndlrs != null && handlerOwnId != null) { + areaHndlrs.put(handlerOwnId, handler); + if (oneHandler == null) { + oneHandler = handler; + } + logger.debug("MAP - Added handler {} to Area {}", handlerOwnId, area); + logger.debug("Map: {}", this.toString()); + } + } + + protected void remove(int area, OpenWebNetThingHandler handler) { + if (hndlrsMap.containsKey(area)) { + Map areaHndlrs = hndlrsMap.get(Integer.valueOf(area)); + if (areaHndlrs != null) { + boolean removed = areaHndlrs.remove(handler.ownId, handler); + OpenWebNetThingHandler oneHandler = this.oneHandler; + // if the removed handler was linked by oneHandler, find another one + if (removed && oneHandler != null && oneHandler.equals(handler)) { + this.oneHandler = getFirst(); + } + logger.debug("MAP - Removed handler {} from Area {}", handler.ownId, area); + logger.debug("Map: {}", this.toString()); + } + } + } + + protected @Nullable List getAreaHandlers(int area) { + Map areaHndlrs = hndlrsMap.get(area); + if (areaHndlrs != null) { + List list = new ArrayList(areaHndlrs.values()); + return list; + } else { + return null; + } + } + + protected @Nullable List getAllHandlers() { + List list = new ArrayList(); + for (Map.Entry> entry : hndlrsMap.entrySet()) { + Map innerMap = entry.getValue(); + for (Map.Entry innerEntry : innerMap.entrySet()) { + OpenWebNetThingHandler hndlr = innerEntry.getValue(); + list.add(hndlr); + } + } + return list; + } + + protected boolean isEmpty() { + return oneHandler == null; + } + + protected @Nullable OpenWebNetThingHandler getOneHandler() { + if (oneHandler == null) { + oneHandler = getFirst(); + } + return oneHandler; + } + + private @Nullable OpenWebNetThingHandler getFirst() { + for (Map.Entry> entry : hndlrsMap.entrySet()) { + Map innerMap = entry.getValue(); + for (Map.Entry innerEntry : innerMap.entrySet()) { + OpenWebNetThingHandler thingHandler = innerEntry.getValue(); + WhereLightAutom whereLightAutom = (WhereLightAutom) thingHandler.deviceWhere; + if (whereLightAutom != null && whereLightAutom.isAPL()) { + return thingHandler; + } + } + } + return null; + } + + @Override + public String toString() { + StringBuilder log = new StringBuilder(); + log.append("\n---- LightAutomHandlersMap ----"); + for (Map.Entry> entry : hndlrsMap.entrySet()) { + log.append("\n- Area: " + entry.getKey() + "\n -"); + Map innerMap = entry.getValue(); + for (Map.Entry innerEntry : innerMap.entrySet()) { + OpenWebNetThingHandler thingHandler = innerEntry.getValue(); + log.append(" " + thingHandler.ownId); + } + } + log.append("\n# getAllHandlers: "); + List allHandlers = getAllHandlers(); + if (allHandlers != null) { + for (OpenWebNetThingHandler singleHandler : allHandlers) { + log.append(" " + singleHandler.ownId); + } + } + OpenWebNetThingHandler oneThingHandler = this.getOneHandler(); + log.append("\n# getOneHandler() = " + (oneThingHandler == null ? "null" : oneThingHandler.ownId)); + log.append("\n-------------------------------"); + + return log.toString(); + } +} diff --git a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetAlarmHandler.java b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetAlarmHandler.java index 0bd59ad0dfc..c1383a8b34f 100644 --- a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetAlarmHandler.java +++ b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetAlarmHandler.java @@ -272,8 +272,8 @@ public class OpenWebNetAlarmHandler extends OpenWebNetThingHandler { } @Override - protected String ownIdPrefix() { - return Who.BURGLAR_ALARM.value().toString(); + protected Who getManagedWho() { + return Who.BURGLAR_ALARM; } @Override diff --git a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetAutomationHandler.java b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetAutomationHandler.java index 75642ab5f2c..bff74f20e37 100644 --- a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetAutomationHandler.java +++ b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetAutomationHandler.java @@ -309,8 +309,8 @@ public class OpenWebNetAutomationHandler extends OpenWebNetThingHandler { } @Override - protected String ownIdPrefix() { - return Who.AUTOMATION.value().toString(); + protected Who getManagedWho() { + return Who.AUTOMATION; } @Override diff --git a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetAuxiliaryHandler.java b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetAuxiliaryHandler.java index 002ceb4c378..07c93d530e5 100644 --- a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetAuxiliaryHandler.java +++ b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetAuxiliaryHandler.java @@ -125,7 +125,7 @@ public class OpenWebNetAuxiliaryHandler extends OpenWebNetThingHandler { } @Override - protected String ownIdPrefix() { - return Who.AUX.value().toString(); + protected Who getManagedWho() { + return Who.AUX; } } diff --git a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetBridgeHandler.java b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetBridgeHandler.java index f64b8f85b75..ac7abe69fd6 100644 --- a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetBridgeHandler.java +++ b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetBridgeHandler.java @@ -66,6 +66,7 @@ import org.openwebnet4j.message.Scenario; import org.openwebnet4j.message.Thermoregulation; import org.openwebnet4j.message.What; import org.openwebnet4j.message.Where; +import org.openwebnet4j.message.WhereLightAutom; import org.openwebnet4j.message.WhereZigBee; import org.openwebnet4j.message.Who; import org.slf4j.Logger; @@ -108,6 +109,9 @@ public class OpenWebNetBridgeHandler extends ConfigStatusBridgeHandler implement private Map registeredDevices = new ConcurrentHashMap<>(); private Map discoveringDevices = new ConcurrentHashMap<>(); + protected @Nullable LightAutomHandlersMap lightsMap; // a LightAutomHandlersMap storing lights handlers organised by + // the AREA they belong to + protected @Nullable OpenGateway gateway; private boolean isBusGateway = false; @@ -432,10 +436,52 @@ public class OpenWebNetBridgeHandler extends ConfigStatusBridgeHandler implement * @param ownId the device OpenWebNet id * @return the registered device Thing handler or null if the id cannot be found */ - public @Nullable OpenWebNetThingHandler getRegisteredDevice(String ownId) { + public @Nullable OpenWebNetThingHandler getRegisteredDevice(@Nullable String ownId) { return registeredDevices.get(ownId); } + /** + * Adds a light handler to the light map for this bridge, grouped by Area + * + * @param area the light area + * @param lightHandler the light handler to be added + */ + protected void addLight(int area, OpenWebNetThingHandler lightHandler) { + if (lightsMap == null) { + lightsMap = new LightAutomHandlersMap(); + } + LightAutomHandlersMap lm = lightsMap; + if (lm != null) { + lm.add(area, lightHandler); + logger.debug("Added APL {} to lightsMap", lightHandler.ownId); + } + } + + /** + * Remove a light handler to the light map for this bridge + * + * @param area the light area + * @param lightHandler the light handler to be removed + */ + protected void removeLight(int area, OpenWebNetThingHandler lightHandler) { + LightAutomHandlersMap lightsMap = this.lightsMap; + if (lightsMap != null) { + lightsMap.remove(area, lightHandler); + logger.debug("Removed APL {} from lightsMap", lightHandler.ownId); + } + } + + @Nullable + protected List getAllLights() { + LightAutomHandlersMap lightsMap = this.lightsMap; + return (lightsMap != null) ? lightsMap.getAllHandlers() : null; + } + + @Nullable + public LightAutomHandlersMap getLightsMap() { + return this.lightsMap; + } + private void refreshAllBridgeDevices() { logger.debug("--- --- ABOUT TO REFRESH ALL devices for bridge {}", thing.getUID()); int howMany = 0; @@ -459,8 +505,7 @@ public class OpenWebNetBridgeHandler extends ConfigStatusBridgeHandler implement } } else if (System.currentTimeMillis() - lastRegisteredDeviceTS < REFRESH_ALL_DEVICES_DELAY_MSEC) { // a device has been registered with the bridge just now, let's wait for other - // devices: re-schedule - // refreshAllDevices + // devices: re-schedule refreshAllDevices logger.debug("--- REGISTER device just called... re-scheduling refreshAllBridgeDevices()"); refreshAllSchedule = scheduler.schedule(this::refreshAllBridgeDevices, REFRESH_ALL_DEVICES_DELAY_MSEC, TimeUnit.MILLISECONDS); @@ -525,7 +570,23 @@ public class OpenWebNetBridgeHandler extends ConfigStatusBridgeHandler implement return; } + // LIGHTING multiple messages for BUS + if (msg instanceof Lighting lmsg && isBusGateway) { + WhereLightAutom whereLightAutom = (WhereLightAutom) lmsg.getWhere(); + if (whereLightAutom != null && (whereLightAutom.isGeneral() || whereLightAutom.isArea())) { + LightAutomHandlersMap lightsMap = this.lightsMap; + if (lightsMap != null && !lightsMap.isEmpty()) { + OpenWebNetLightingHandler lightingHandler = (OpenWebNetLightingHandler) lightsMap.getOneHandler(); + if (lightingHandler != null) { + lightingHandler.handleMultipleMessage(lmsg); + } + } + return; + } + } + BaseOpenMessage baseMsg = (BaseOpenMessage) msg; + // let's try to get the Thing associated with this message... if (baseMsg instanceof Lighting || baseMsg instanceof Automation || baseMsg instanceof EnergyManagement || baseMsg instanceof Thermoregulation || baseMsg instanceof CEN || baseMsg instanceof Auxiliary @@ -697,7 +758,8 @@ public class OpenWebNetBridgeHandler extends ConfigStatusBridgeHandler implement * @return the ownId String */ protected String ownIdFromDeviceWhere(Where where, OpenWebNetThingHandler handler) { - return handler.ownIdPrefix() + "." + normalizeWhere(where); + Who w = handler.getManagedWho(); + return w.value().toString() + "." + normalizeWhere(w, where); } /** @@ -708,7 +770,7 @@ public class OpenWebNetBridgeHandler extends ConfigStatusBridgeHandler implement * @return the ownId String */ public String ownIdFromWhoWhere(Who who, Where where) { - return who.value() + "." + normalizeWhere(where); + return who.value() + "." + normalizeWhere(who, where); } /** @@ -721,7 +783,7 @@ public class OpenWebNetBridgeHandler extends ConfigStatusBridgeHandler implement @Nullable Where w = baseMsg.getWhere(); if (w != null) { - return baseMsg.getWho().value() + "." + normalizeWhere(w); + return baseMsg.getWho().value() + "." + normalizeWhere(baseMsg.getWho(), w); } else if (baseMsg instanceof Alarm) { // null and Alarm return baseMsg.getWho().value() + "." + "0"; // Alarm System --> where=0 } else { @@ -731,32 +793,39 @@ public class OpenWebNetBridgeHandler extends ConfigStatusBridgeHandler implement } /** - * Transform a Where address into a Thing id string + * Given a Who and a Where address, return a Thing id string * + * @param who the Who * @param where the Where address * @return the thing Id string */ - public String thingIdFromWhere(Where where) { - return normalizeWhere(where); // '#' cannot be used in ThingUID; + public String thingIdFromWhoWhere(Who who, Where where) { + return normalizeWhere(who, where); // '#' cannot be used in ThingUID; } /** - * Normalize a Where address to generate ownId and Thing id + * Normalize, based on Who, a Where address. Used to generate ownId and Thing id * + * @param who the Who * @param where the Where address * @return the normalized address as String */ - public String normalizeWhere(Where where) { + public String normalizeWhere(Who who, Where where) { String str = where.value(); if (where instanceof WhereZigBee whereZigBee) { str = whereZigBee.valueWithUnit(WhereZigBee.UNIT_ALL); // 76543210X#9 --> 765432100#9 } else { if (str.indexOf("#4#") == -1) { // skip APL#4#bus case - if (str.indexOf('#') == 0) { // Thermo central unit (#0) or zone via central unit (#Z, Z=[1-99]) --> Z, - // Alarm Zone (#Z) --> Z - str = str.substring(1); - } else if (str.indexOf('#') > 0 && str.charAt(0) != '0') { // Thermo zone Z and actuator N (Z#N, - // Z=[1-99], N=[1-9]) --> Z + if (str.indexOf('#') == 0) { + if (who.equals(Who.THERMOREGULATION) || who.equals(Who.THERMOREGULATION_DIAGNOSTIC) + || who.equals(Who.BURGLAR_ALARM)) { + // Thermo central unit (#0) or zone via central unit (#Z, Z=[1-99]) --> Z + // or Alarm zone #Z --> Z + str = str.substring(1); + } // else leave the initial hash (for example for LightAutomWhere GROUPs #GR --> + // hGR) + } else if (str.indexOf('#') > 0 && str.charAt(0) != '0') { + // Thermo zone Z and actuator N (Z#N, Z=[1-99], N=[1-9]) --> Z) str = str.substring(0, str.indexOf('#')); } } diff --git a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetEnergyHandler.java b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetEnergyHandler.java index 2b34b98a483..3106fcda69d 100644 --- a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetEnergyHandler.java +++ b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetEnergyHandler.java @@ -213,8 +213,8 @@ public class OpenWebNetEnergyHandler extends OpenWebNetThingHandler { } @Override - protected String ownIdPrefix() { - return Who.ENERGY_MANAGEMENT.value().toString(); + protected Who getManagedWho() { + return Who.ENERGY_MANAGEMENT; } @Override diff --git a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetGenericHandler.java b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetGenericHandler.java index 4c0a66742e2..a0cecdb75ba 100644 --- a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetGenericHandler.java +++ b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetGenericHandler.java @@ -23,6 +23,7 @@ import org.openhab.core.types.Command; import org.openwebnet4j.message.BaseOpenMessage; import org.openwebnet4j.message.Where; import org.openwebnet4j.message.WhereLightAutom; +import org.openwebnet4j.message.Who; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -69,8 +70,8 @@ public class OpenWebNetGenericHandler extends OpenWebNetThingHandler { } @Override - protected String ownIdPrefix() { - return "G"; + protected Who getManagedWho() { + return Who.UNKNOWN; } @Override diff --git a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetLightingGroupHandler.java b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetLightingGroupHandler.java new file mode 100644 index 00000000000..0e346185527 --- /dev/null +++ b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetLightingGroupHandler.java @@ -0,0 +1,208 @@ +/** + * Copyright (c) 2010-2024 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.openwebnet.internal.handler; + +import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.*; + +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants; +import org.openhab.core.library.types.OnOffType; +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.ThingTypeUID; +import org.openhab.core.types.Command; +import org.openwebnet4j.communication.OWNException; +import org.openwebnet4j.message.BaseOpenMessage; +import org.openwebnet4j.message.Lighting; +import org.openwebnet4j.message.Where; +import org.openwebnet4j.message.WhereLightAutom; +import org.openwebnet4j.message.Who; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link OpenWebNetLightingGroupHandler} is responsible for handling commands/messages for a Lighting OpenWebNet + * group. + * It extends the abstract {@link OpenWebNetThingHandler}. + * + * @author Massimo Valla - Initial contribution. + */ +@NonNullByDefault +public class OpenWebNetLightingGroupHandler extends OpenWebNetThingHandler { + + private final Logger logger = LoggerFactory.getLogger(OpenWebNetLightingGroupHandler.class); + + public static final Set SUPPORTED_THING_TYPES = OpenWebNetBindingConstants.LIGHTING_GROUP_SUPPORTED_THING_TYPES; + + protected Set listOn = new HashSet(); + + public OpenWebNetLightingGroupHandler(Thing thing) { + super(thing); + } + + @Override + protected void requestChannelState(ChannelUID channel) { + super.requestChannelState(channel); + Where deviceWhere = this.deviceWhere; + if (deviceWhere != null) { + try { + send(Lighting.requestStatus(deviceWhere.value())); + } catch (OWNException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); + } + } + } + + @Override + protected void refreshDevice(boolean refreshAll) { + if (refreshAll) { + logger.debug("--- refreshDevice() : refreshing GENERAL... ({})", thing.getUID()); + try { + send(Lighting.requestStatus(WhereLightAutom.GENERAL.value())); + } catch (OWNException e) { + logger.warn("Excpetion while requesting all devices refresh: {}", e.getMessage()); + } + } else { + logger.debug("--- refreshDevice() : refreshing SINGLE... ({})", thing.getUID()); + + requestChannelState(new ChannelUID(thing.getUID(), CHANNEL_SWITCH_01)); + } + } + + @Override + protected void handleChannelCommand(ChannelUID channel, Command command) { + switch (channel.getId()) { + case CHANNEL_SWITCH: + handleSwitchCommand(channel, command); + break; + default: { + logger.warn("Unsupported ChannelUID {}", channel); + } + } + } + + /** + * Handles Lighting switch command for a channel + * + * @param channel the channel + * @param command the command + */ + private void handleSwitchCommand(ChannelUID channel, Command command) { + logger.debug("handleSwitchCommand() (command={} - channel={})", command, channel); + Where deviceWhere = this.deviceWhere; + if (command instanceof OnOffType && deviceWhere != null) { + try { + if (OnOffType.ON.equals(command)) { + send(Lighting.requestTurnOn(deviceWhere.value())); + } else if (OnOffType.OFF.equals(command)) { + send(Lighting.requestTurnOff(deviceWhere.value())); + } + } catch (OWNException e) { + logger.warn("Exception while processing command {}: {}", command, e.getMessage()); + } + } else { + logger.warn("Unsupported command: {}", command); + } + } + + @Override + protected Who getManagedWho() { + return Who.LIGHTING; + } + + protected void handlePropagatedMessage(Lighting lmsg, @Nullable String oId) { + logger.debug("handlePropagatedMessage({}) for thing: {}", lmsg, thing.getUID()); + + WhereLightAutom deviceWhere = (WhereLightAutom) this.deviceWhere; + if (deviceWhere != null && oId != null) { + int sizeBefore = listOn.size(); + if (!lmsg.isOff()) { + if (listOn.add(oId)) { + logger.debug("ADDED {} to listOn for {}", oId, deviceWhere); + } + } else { + if (listOn.remove(oId)) { + logger.debug("REMOVED {} from listOn for {}", oId, deviceWhere); + } + } + logger.debug("listOn for {}: {}", deviceWhere, listOn); + + boolean listOnChanged = false; + + if (!listOn.isEmpty()) { + // some light still on + logger.debug("some light ON... switching group {} to ON", deviceWhere); + updateState(CHANNEL_SWITCH, OnOffType.ON); + listOnChanged = (sizeBefore == 0); + } else { + // no light is ON anymore + logger.debug("all lights OFF ... switching group {} to OFF ", deviceWhere); + updateState(CHANNEL_SWITCH, OnOffType.OFF); + listOnChanged = (sizeBefore > 0); + } + if (listOnChanged && !deviceWhere.isGeneral()) { + // Area has changed state, propagate APL msg to GEN handler, if exists + OpenWebNetBridgeHandler bridgeHandler = this.bridgeHandler; + if (bridgeHandler != null) { + String genOwnId = this.getManagedWho().value() + ".0"; + OpenWebNetLightingGroupHandler genHandler = (OpenWebNetLightingGroupHandler) bridgeHandler + .getRegisteredDevice(genOwnId); + if (genHandler != null && this.ownId != null) { + logger.debug("device {} is Propagating msg {} to GEN handler", deviceWhere, lmsg); + genHandler.handlePropagatedMessage(lmsg, this.ownId); + } + } + } + + handleMessage(lmsg); // to make handler come online when a light of its group comes online + } + } + + @Override + protected void handleMessage(BaseOpenMessage msg) { + logger.debug("handleMessage({}) for thing: {}", msg, thing.getUID()); + super.handleMessage(msg); + + WhereLightAutom w = (WhereLightAutom) deviceWhere; + if (w != null && w.isGroup()) { + if (((Lighting) msg).isOff()) { + updateState(CHANNEL_SWITCH, OnOffType.OFF); + } else { + updateState(CHANNEL_SWITCH, OnOffType.ON); + } + } + } + + @Override + protected Where buildBusWhere(String wStr) throws IllegalArgumentException { + return new WhereLightAutom(wStr); + } + + @Override + public void dispose() { + if (this.deviceWhere instanceof WhereLightAutom whereLightAutom) { + int area = whereLightAutom.getArea(); + OpenWebNetBridgeHandler bridgeHandler = this.bridgeHandler; + if (bridgeHandler != null) { + bridgeHandler.removeLight(area, this); + } + } + super.dispose(); + } +} diff --git a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetLightingHandler.java b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetLightingHandler.java index 97e3374e788..31f69ea0e85 100644 --- a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetLightingHandler.java +++ b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetLightingHandler.java @@ -14,6 +14,7 @@ package org.openhab.binding.openwebnet.internal.handler; import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.*; +import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; @@ -46,7 +47,7 @@ import org.slf4j.LoggerFactory; * commands/messages for a Lighting OpenWebNet device. * It extends the abstract {@link OpenWebNetThingHandler}. * - * @author Massimo Valla - Initial contribution + * @author Massimo Valla - Initial contribution. Added LightAutomHandlersMap. */ @NonNullByDefault public class OpenWebNetLightingHandler extends OpenWebNetThingHandler { @@ -65,19 +66,33 @@ public class OpenWebNetLightingHandler extends OpenWebNetThingHandler { private static final int UNKNOWN_STATE = 1000; private long lastBrightnessChangeSentTS = 0; // timestamp when last brightness change was sent to the device - private long lastStatusRequestSentTS = 0; // timestamp when last status request was sent to the device - private static long lastAllDevicesRefreshTS = 0; // ts when last all device refresh was sent for this handler - private int brightness = UNKNOWN_STATE; // current brightness percent value for this device - private int brightnessBeforeOff = UNKNOWN_STATE; // latest brightness before device was set to off + @Nullable + String areaOwnId = null; + int area = -1; + public OpenWebNetLightingHandler(Thing thing) { super(thing); } + @Override + public void initialize() { + super.initialize(); + OpenWebNetBridgeHandler bridgeHandler = this.bridgeHandler; + if (this.deviceWhere instanceof WhereLightAutom whereLightAutom && bridgeHandler != null + && bridgeHandler.isBusGateway()) { + area = whereLightAutom.getArea(); + if (area > 0) { + areaOwnId = this.getManagedWho().value() + "." + area; + } + bridgeHandler.addLight(area, this); + } + } + @Override protected void requestChannelState(ChannelUID channel) { super.requestChannelState(channel); @@ -236,20 +251,64 @@ public class OpenWebNetLightingHandler extends OpenWebNetThingHandler { } @Override - protected String ownIdPrefix() { - return Who.LIGHTING.value().toString(); + protected Who getManagedWho() { + return Who.LIGHTING; } @Override protected void handleMessage(BaseOpenMessage msg) { logger.debug("handleMessage({}) for thing: {}", msg, thing.getUID()); super.handleMessage(msg); + ThingTypeUID thingType = thing.getThingTypeUID(); if (THING_TYPE_ZB_DIMMER.equals(thingType) || THING_TYPE_BUS_DIMMER.equals(thingType)) { updateBrightness((Lighting) msg); } else { updateOnOffState((Lighting) msg); } + + OpenWebNetBridgeHandler bridgeHandler = this.bridgeHandler; + if (bridgeHandler != null && bridgeHandler.isBusGateway()) { + if (deviceWhere instanceof WhereLightAutom whereLightAutom && ownId != null && whereLightAutom.isAPL()) { + // Propagate APL msg to AREA handler, if exists + OpenWebNetLightingGroupHandler areaHandler = (OpenWebNetLightingGroupHandler) bridgeHandler + .getRegisteredDevice(areaOwnId); + if (areaHandler != null) { + logger.debug("Light {} is propagating msg {} to AREA handler {}", whereLightAutom, msg, areaOwnId); + areaHandler.handlePropagatedMessage((Lighting) msg, this.ownId); + } else { + // Propagate APL msg to GEN handler, if exists + String genOwnId = this.getManagedWho().value() + ".0"; + OpenWebNetLightingGroupHandler genHandler = (OpenWebNetLightingGroupHandler) bridgeHandler + .getRegisteredDevice(genOwnId); + if (genHandler != null) { + logger.debug("Light {} is propagating msg {} to GEN handler", whereLightAutom, msg); + genHandler.handlePropagatedMessage((Lighting) msg, this.ownId); + } + } + } + } + } + + protected void handleMultipleMessage(Lighting msg) { + logger.debug("handleMultipleMessage {}", msg); + WhereLightAutom whereLightAutom = (WhereLightAutom) msg.getWhere(); + List allLightsHandlers = null; + OpenWebNetBridgeHandler bridgeHandler = this.bridgeHandler; + if (whereLightAutom.isGeneral() && bridgeHandler != null) { + allLightsHandlers = bridgeHandler.getAllLights(); + if (allLightsHandlers != null) { + for (OpenWebNetThingHandler handler : allLightsHandlers) { + handler.handleMessage(msg); + } + } + } else if (whereLightAutom.getArea() > 0) { + try { + send(Lighting.requestStatus(whereLightAutom.getArea() + "")); + } catch (OWNException e) { + logger.warn("Excpetion while requesting refresh for light area: {}", e.getMessage()); + } + } } /** @@ -401,4 +460,26 @@ public class OpenWebNetLightingHandler extends OpenWebNetThingHandler { } throw new OWNException("Cannot select channel from WHERE " + w); } + + @Override + public void dispose() { + OpenWebNetBridgeHandler bridgeHandler = this.bridgeHandler; + if (deviceWhere instanceof WhereLightAutom whereLightAutom && bridgeHandler != null + && bridgeHandler.isBusGateway()) { + int area = whereLightAutom.getArea(); + if (areaOwnId != null) { + // remove light from listOn for Area + OpenWebNetLightingGroupHandler areaHandler = (OpenWebNetLightingGroupHandler) bridgeHandler + .getRegisteredDevice(areaOwnId); + if (areaHandler != null) { + if (areaHandler.listOn.remove(ownId)) { + logger.debug("Removed {} from listOn for {}", ownId, areaOwnId); + } + } + } + // remove light from lightsMap + bridgeHandler.removeLight(area, this); + } + super.dispose(); + } } diff --git a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetScenarioBasicHandler.java b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetScenarioBasicHandler.java index fe3611ef472..334f1294aae 100644 --- a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetScenarioBasicHandler.java +++ b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetScenarioBasicHandler.java @@ -48,8 +48,8 @@ public class OpenWebNetScenarioBasicHandler extends OpenWebNetThingHandler { } @Override - protected String ownIdPrefix() { - return Who.SCENARIO.value().toString(); + protected Who getManagedWho() { + return Who.SCENARIO; } @Override diff --git a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetScenarioHandler.java b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetScenarioHandler.java index fe412291c02..f105cb61e8e 100644 --- a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetScenarioHandler.java +++ b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetScenarioHandler.java @@ -165,11 +165,11 @@ public class OpenWebNetScenarioHandler extends OpenWebNetThingHandler { } @Override - protected String ownIdPrefix() { + protected Who getManagedWho() { if (isCENPlus || isDryContactIR) { - return Who.CEN_PLUS_SCENARIO_SCHEDULER.value().toString(); + return Who.CEN_PLUS_SCENARIO_SCHEDULER; } else { - return Who.CEN_SCENARIO_SCHEDULER.value().toString(); + return Who.CEN_SCENARIO_SCHEDULER; } } 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 2984d571831..c3552dce2ef 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 @@ -164,8 +164,8 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler { } @Override - protected String ownIdPrefix() { - return Who.THERMOREGULATION.value().toString(); + protected Who getManagedWho() { + return Who.THERMOREGULATION; } private void handleSetFanSpeed(Command command) { 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 763097bf187..a4e821e4376 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 @@ -42,6 +42,7 @@ import org.openwebnet4j.message.BaseOpenMessage; import org.openwebnet4j.message.OpenMessage; import org.openwebnet4j.message.Where; import org.openwebnet4j.message.WhereZigBee; +import org.openwebnet4j.message.Who; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -175,15 +176,15 @@ public abstract class OpenWebNetThingHandler extends BaseThingHandler { * * @param msg the OpenMessage to be sent */ - public @Nullable Response send(OpenMessage msg) throws OWNException { + public @Nullable Response send(@Nullable OpenMessage msg) throws OWNException { OpenWebNetBridgeHandler bh = bridgeHandler; - if (bh != null) { + if (msg != null && bh != null) { OpenGateway gw = bh.gateway; if (gw != null) { return gw.send(msg); } } - logger.warn("Couldn't send message {}: handler or gateway is null", msg); + logger.warn("Couldn't send message {}: handler, gateway or message is null", msg); return null; } @@ -330,10 +331,10 @@ public abstract class OpenWebNetThingHandler extends BaseThingHandler { } /** - * Returns a prefix String for ownId specific for each handler. + * Returns the Who managed by the handler. * To be implemented by sub-classes. * - * @return + * @return Who managed by the handler */ - protected abstract String ownIdPrefix(); + protected abstract Who getManagedWho(); } diff --git a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/i18n/openwebnet.properties b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/i18n/openwebnet.properties index 6f973f45dc3..4a3279b5a61 100644 --- a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/i18n/openwebnet.properties +++ b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/i18n/openwebnet.properties @@ -25,6 +25,8 @@ thing-type.openwebnet.bus_energy_meter.label = Energy Meter thing-type.openwebnet.bus_energy_meter.description = An OpenWebNet BUS/SCS Energy Meter. BTicino models: F52x thing-type.openwebnet.bus_gateway.label = BUS Gateway thing-type.openwebnet.bus_gateway.description = This thing allows to connect to an IP BUS/SCS gateway that supports the OpenWebNet protocol (models: F454, MyHOMEServer1, F455, MH200N, F453, etc.) +thing-type.openwebnet.bus_light_group.label = Switch Group +thing-type.openwebnet.bus_light_group.description = An OpenWebNet BUS/SCS group of lights/loads (General, Area or Group BUS addressing). thing-type.openwebnet.bus_on_off_switch.label = Switch thing-type.openwebnet.bus_on_off_switch.description = An OpenWebNet BUS/SCS switch for the control of 1 light/load. BTicino models: xxx/yyyy/etc. thing-type.openwebnet.bus_scenario_control.label = Scenario Control @@ -86,6 +88,8 @@ thing-type.config.openwebnet.bus_gateway.passwd.label = Password thing-type.config.openwebnet.bus_gateway.passwd.description = OpenWebNet gateway password (default: 12345) thing-type.config.openwebnet.bus_gateway.port.label = Port thing-type.config.openwebnet.bus_gateway.port.description = OpenWebNet gateway port (default: 20000) +thing-type.config.openwebnet.bus_light_group.where.label = OpenWebNet Address (where) +thing-type.config.openwebnet.bus_light_group.where.description = Example: General (A=GEN) --> where="0", Room 5 (A=AMB PL=5) --> where="5", Group 25 (A=GR PL=25) --> where="#25" thing-type.config.openwebnet.bus_on_off_switch.where.label = OpenWebNet Address (where) thing-type.config.openwebnet.bus_on_off_switch.where.description = Example: A/PL address: A=1 PL=3 --> where="13". On local bus: where="13#4#01" thing-type.config.openwebnet.bus_scenario_control.where.label = OpenWebNet Address (where) diff --git a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusLightGroup.xml b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusLightGroup.xml new file mode 100644 index 00000000000..155b5d52e7b --- /dev/null +++ b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusLightGroup.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + An OpenWebNet BUS/SCS group of lights/loads (General, Area or Group BUS addressing). + + + + + + + BTicino/Legrand + BTI-xxxx/yyyy/etc. + 1000 + + + ownId + + + + + Example: General (A=GEN) --> where="0", Room 5 (A=AMB PL=5) --> where="5", Group 25 (A=GR PL=25) --> + where="#25" + + + + + diff --git a/bundles/org.openhab.binding.openwebnet/src/test/java/org/openhab/binding/openwebnet/internal/handler/OwnIdTest.java b/bundles/org.openhab.binding.openwebnet/src/test/java/org/openhab/binding/openwebnet/internal/handler/OwnIdTest.java index 7c141ac864e..7f5f9393cc7 100644 --- a/bundles/org.openhab.binding.openwebnet/src/test/java/org/openhab/binding/openwebnet/internal/handler/OwnIdTest.java +++ b/bundles/org.openhab.binding.openwebnet/src/test/java/org/openhab/binding/openwebnet/internal/handler/OwnIdTest.java @@ -57,6 +57,12 @@ public class OwnIdTest { * Zigbee Switch_2u u1 789301201#9 789301200h9 1.789309800h9 789309800h9 * Zigbee Switch_2u u2 789301202#9 789301200h9 1.789309800h9 789309800h9 * BUS Switch 51 51 1.51 51 + * + * BUS Switch Gen 0 0 1.0 0 + * BUS Switch Area 5 5 1.5 5 + * BUS Switch Group #25 h25 1.h25 h25 + * BUS Autom Group #25 h25 2.h25 h25 + * * BUS Local Bus 25#4#01 25h4h01 1.25h4h01 25h4h01 * BUS Autom 93 93 2.93 93 * BUS Thermo zone 1 1 4.1 1 @@ -71,7 +77,8 @@ public class OwnIdTest { * BUS DryContact 399 399 25.399 399 * BUS AUX 4 4 9.4 4 * BUS Scenario 05 05 0.05 05 - * BUS Alarm Zone #2 or 2 2 5.2 2 + * BUS Alarm Zone CU #2 2 5.2 2 + * BUS Alarm Zone 2 2 5.2 2 * BUS Alarm silent 0 0 5.0 0 * BUS Alarm system null 0 5.0 0 */ @@ -84,8 +91,16 @@ public class OwnIdTest { zb_switch_2u_1("*1*1*789301201#9##", Who.fromValue(1), new WhereZigBee("789301201#9"), "789301200h9", "1.789301200h9", "789301200h9"), zb_switch_2u_2("*1*1*789301202#9##", Who.fromValue(1), new WhereZigBee("789301202#9"), "789301200h9", "1.789301200h9", "789301200h9"), bus_switch("*1*1*51##", Who.fromValue(1), new WhereLightAutom("51"),"51", "1.51", "51"), + + bus_switch_gen("*1*1*0##", Who.fromValue(1), new WhereLightAutom("0"),"0", "1.0", "0"), + bus_switch_area("*1*1*5##", Who.fromValue(1), new WhereLightAutom("5"),"5", "1.5", "5"), + bus_switch_group("*1*1*#25##", Who.fromValue(1), new WhereLightAutom("#25"),"h25", "1.h25", "h25"), + bus_localbus("*1*1*25#4#01##", Who.fromValue(1), new WhereLightAutom("25#4#01"), "25h4h01", "1.25h4h01", "25h4h01"), bus_autom("*2*0*93##",Who.fromValue(2), new WhereLightAutom("93"), "93", "2.93", "93"), + + bus_autom_group("*2*1*#25##", Who.fromValue(2), new WhereLightAutom("#25"),"h25", "2.h25", "h25"), + bus_thermo_zone("*#4*1*0*0020##", Who.fromValue(4), new WhereThermo("1"), "1", "4.1", "1"), bus_thermo_zone_via_cu("*#4*#1*0*0020##", Who.fromValue(4), new WhereThermo("#1"), "1", "4.1", "1"), bus_thermo_cu_99("*#4*#0##", Who.fromValue(4), new WhereThermo("#0") ,"0", "4.0", "0"), @@ -98,7 +113,8 @@ public class OwnIdTest { bus_drycontact("*25*32#1*399##", Who.fromValue(25), new WhereCEN("399"), "399", "25.399", "399"), bus_aux( "*9*1*4##", Who.fromValue(9), new WhereAuxiliary("4"),"4","9.4","4"), bus_scenario( "*0*2*05##", Who.fromValue(0), new WhereLightAutom("05"), "05","0.05","05"), - bus_alarm_zh("*#5*#2##", Who.fromValue(5), new WhereAlarm("#2"), "2", "5.2", "2"), + bus_alarm_zone_cu("*#5*#2##", Who.fromValue(5), new WhereAlarm("#2"), "2", "5.2", "2"), + bus_alarm_zone("*#5*2##", Who.fromValue(5), new WhereAlarm("2"), "2", "5.2", "2"), bus_alarm_silent("*5*2*0##", Who.fromValue(5), new WhereAlarm("0"), "0", "5.0", "0"), bus_alarm_system( "*5*7*##", Who.fromValue(5),new WhereAlarm("0"), "0", "5.0", "0"); @@ -136,13 +152,13 @@ public class OwnIdTest { for (int i = 0; i < TEST.values().length; i++) { TEST test = TEST.values()[i]; logger.info("testing {} (who={} where={})", test.msg, test.who, test.where); - assertEquals(test.norm, brH.normalizeWhere(test.where)); + assertEquals(test.norm, brH.normalizeWhere(test.who, test.where)); assertEquals(test.ownId, brH.ownIdFromWhoWhere(test.who, test.where)); bmsg = test.msg; if (bmsg != null) { assertEquals(test.ownId, brH.ownIdFromMessage(bmsg)); } - assertEquals(test.thingId, brH.thingIdFromWhere(test.where)); + assertEquals(test.thingId, brH.thingIdFromWhoWhere(test.who, test.where)); } } }