From 56977544dc3627afb722999e4fde5be49a8017f5 Mon Sep 17 00:00:00 2001 From: M Valla <12682715+mvalla@users.noreply.github.com> Date: Mon, 5 Dec 2022 12:57:25 +0100 Subject: [PATCH] [openwebnet] Add support for Alarm (WHO=5) (#13694) * [openwebnet] first changes for Alarm support * [openwebnet] added first version Alarm handler * [openwebnet] added ownIdTest for Alarm * [openwebnet] added things def for Alarm and discovery for alarm zone * [openwebnet] refreshDevice * [openwebnet] fix text formatting * [openwebnet] fixes * [openwebnet] added other alarm channels * [openwebnet] Alarm: codestyle and null checks * [openwebnet] updated Alarm examples in README and some cleanup * [openwebnet] changed zone channel from armed to state, cleaned README Signed-off-by: Massimo Valla --- .../org.openhab.binding.openwebnet/README.md | 215 +++++++++------- .../org.openhab.binding.openwebnet/pom.xml | 2 +- .../internal/OpenWebNetBindingConstants.java | 20 +- .../internal/OpenWebNetHandlerFactory.java | 4 + .../OpenWebNetDeviceDiscoveryService.java | 41 ++- .../handler/OpenWebNetAlarmHandler.java | 233 ++++++++++++++++++ .../handler/OpenWebNetBridgeHandler.java | 36 ++- .../OH-INF/i18n/openwebnet.properties | 61 ++--- .../resources/OH-INF/thing/BusAlarmSystem.xml | 41 +++ .../resources/OH-INF/thing/BusAlarmZone.xml | 38 +++ .../main/resources/OH-INF/thing/channels.xml | 55 +++++ .../internal/handler/OwnIdTest.java | 55 +++-- 12 files changed, 630 insertions(+), 171 deletions(-) create mode 100644 bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetAlarmHandler.java create mode 100644 bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusAlarmSystem.xml create mode 100644 bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusAlarmZone.xml diff --git a/bundles/org.openhab.binding.openwebnet/README.md b/bundles/org.openhab.binding.openwebnet/README.md index 8a14103fcd08a..bac3c09b99adc 100644 --- a/bundles/org.openhab.binding.openwebnet/README.md +++ b/bundles/org.openhab.binding.openwebnet/README.md @@ -43,11 +43,13 @@ The following Things and OpenWebNet `WHOs` are supported: | 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 | -| Auxiliary (AUX) | `9` | `bus_aux` | AUX commands | Successfully tested: AUX configured for bulgrar-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 | +| 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 | +| 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 ZigBee (Radio) @@ -133,9 +135,10 @@ For any manually added device, you must configure: - scenario control module address `53` --> `where="53"` - CEN scenario A=`05`, PL=`12` --> `where="0512"` - CEN+ scenario `5`: add `2` before --> `where="25"` - - Dry Contact or IR Interface `99`: add `3` before --> `where="399"` - - Energy meter F520/F521 numbered `1`: add `5` before --> `where="51"` - - Energy meter F522/F523 numbered `4` add `7` before and `#0` after --> `where="74#0"` + - dry Contact or IR Interface `99`: add `3` before --> `where="399"` + - energy meter F520/F521 numbered `1`: add `5` before --> `where="51"` + - energy meter F522/F523 numbered `4`: add `7` before and `#0` after --> `where="74#0"` + - alarm zone `2` --> `where="2"` - example for ZigBee devices: `where=765432101#9`. The ID of the device (ADDR part) is usually written in hexadecimal on the device itself, for example `ID 0074CBB1`: convert to decimal (`7654321`) and add `01#9` at the end to obtain `where=765432101#9`. For 2-unit switch devices (`zb_on_off_switch2u`), last part should be `00#9`. @@ -157,83 +160,97 @@ Temperature sensors can be configured defining a `bus_thermo_sensor` Thing with The (optional) Central Unit can be configured defining a `bus_themo_cu` Thing with the `where` configuration parameter (`OpenWebNet Address`) set to `where="0"`. -##### Central Unit integration missing points +##### Thermo Central Unit integration missing points - Read setPoint temperature and current mode - Holiday activation command (all zones) - Discovery -#### Configuring Auxiliary (AUX) +#### Configuring Alarm and Auxiliary (AUX) + +**NOTE 1** Receiving AUX messages originating from the BUS is not supported yet, only sending messages to the BUS is supported -**NOTE** Receiving AUX messages originating from the BUS is not supported yet, only sending messages to the BUS is supported. +**NOTE 2** Alarm messages on BUS are not sent by MyHOMEServer1, therfore this gateway cannot be used to integrate the BTicino Alarm system BUS Auxiliary commands (WHO=9) can be used to send on the BUS commands to control, for example, external devices or a BTicino Alarm system. -The BTicino Alarm system **cannot** be controlled directly via the OpenWebNet protocol: the only possibility is to use AUX commands and configure your Alarm Control Panel (Automations section) to execute some commands (e.g. Activate alarm) when it receives a particular AUX OpenWebNet command. -Alarm Control Automations allow you to run an OpenWebNet command when a particular event occurs; in this case, the events are changes of state of the AUX device (WHO=9) and the command to be performed is a burglar alarm command (WHO=5). +The BTicino Alarm system **cannot** be controlled directly via the OpenWebNet protocol: the only possibility is to use AUX commands and configure your Burglar-alarm Unit (`Automations` section) to execute some commands (e.g. Arm alarm) when it receives a particular AUX OpenWebNet command. +Alarm Automations allow you to run an OpenWebNet command when a particular event occurs; in this case, the events are changes of state of the AUX device (WHO=9) and the command to be performed is a burglar alarm command (WHO=5). -To configure Alarm Control Automations go to the menu: +To configure Alarm Automations go to the menu: Antitheft -> Automations -##### Example configuration Automation 1: when AUX-1 goes OFF, then DISENGAGE all Zones +##### Example configuration Automation 1: when AUX-4 goes ON, then ARM all zones -With this configuration when AUX `where=1` goes OFF, the Alarm will execute the automation and send command `*5*9##` to DISENGAGE all zones. +With this configuration when AUX `where=4` goes ON, the Alarm will execute the automation and send command `*5*8##` to ARM all zones: - Name: Disengage all zones - Event: command OPEN = *9*0*1## - OPEN command to execute: *5*9## + Name: Arm all zones + Event: command OPEN = *9*1*4## + OPEN command to execute: *5*8## -##### Example configuration Automation 2: when AUX-2 goes ON, then ENGAGE active Zones +##### Example configuration Automation 2: when AUX-4 goes OFF, then DISARM all zones - Name: Engage active zones - Event: command OPEN = *9*1*2## - OPEN command to execute: *5*8## + Name: Disarm all zones + Event: command OPEN = *9*0*4## + OPEN command to execute: *5*9## -##### Example configuration Automation 3: when AUX-4 goes ON, then ENGAGE Zones 1, 2, 3, 4 +##### Example configuration Automation 3: when AUX-5 goes ON, then ARM zones 1, 3, 4 - Name: Engage zones 1-4 - Event: command OPEN = *9*1*4## - OPEN command to execute: *5*8#1234## + Name: Arm zones 1 3 4 + Event: command OPEN = *9*1*5## + OPEN command to execute: *5*8#134## ## Channels -### Lighting, Automation, Power meter, Basic/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](#scenario-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 | +### 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 | 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 | | `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 | -| `scenario`   | `bus_scenario_control` | String | Trigger channel for Basic scenario events [see possible values](#scenario-channels) | R (TRIGGER) | + + +### Alarm channels + +| Channel Type ID (channel ID) | Applies to Thing Type IDs | Item Type | Description | Read/Write | +|------------------------------|----------------------------------------|-------------|-----------------------------------------------------------------------|:-----------:| +| `state` | `bus_alarm_system`, `bus_alarm_zone` | Switch | Alarm system or zone is active (`ON`) or inactive (`OFF`) | R | +| `network` | `bus_alarm_system` | Switch | Alarm system network state (`ON` = network ok, `OFF` = no network) | R | +| `battery` | `bus_alarm_system` | String | Alarm system battery state (`OK`, `FAULT`, `UNLOADED`) | R | +| `armed` | `bus_alarm_system` | Switch | Alarm system is armed (`ON`) or disarmed (`OFF`) | R | +| `alarm` | `bus_alarm_zone` | String | Current alarm for the zone (`SILENT`, `INTRUSION`, `TAMPERING`, `ANTI_PANIC`) | R | + ### Thermo channels -**NOTE** Channels marked with Advanced=Y can be shown from Thing configuration > Channels tab > check `Show advanced`. +**NOTE** Channels marked in the table with `Advanced = Y` can be shown on the UI from Thing configuration > Channels tab > check `Show advanced`. -| 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`, `bus_thermo_cu` | String | The zone set thermo function (`COOLING`, `HEATING`, `GENERIC`) or the Central Unit thermo function (`COOLING`, `HEATING`) | 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 | +| 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`, `bus_thermo_cu` | String | The zone set thermo function (`COOLING`, `HEATING`, `GENERIC`) or the Central Unit thermo function (`COOLING`, `HEATING`) | 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 | -| `failureDiscovered` | `bus_thermo_cu` | Switch | Indicates if a Failure was discovered by the Central Unit: `ON`, `OFF` | R | Y | -| `atLeastOneProbeOff` | `bus_thermo_cu` | Switch | Indicates if at least one probe is in OFF mode: `ON`, `OFF` | R | Y | -| `atLeastOneProbeProtection` | `bus_thermo_cu` | Switch | Indicates if at least one probe is in PROTECTION mode: `ON`, `OFF` | R | Y | -| `atLeastOneProbeManual` | `bus_thermo_cu` | Switch | Indicates if at least one probe is in MANUAL mode: `ON`, `OFF` | 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 | +| `failureDiscovered` | `bus_thermo_cu` | Switch | Indicates if a Failure was discovered by the Central Unit: `ON`, `OFF` | R | Y | +| `atLeastOneProbeOff` | `bus_thermo_cu` | Switch | Indicates if at least one probe is in OFF mode: `ON`, `OFF` | R | Y | +| `atLeastOneProbeProtection` | `bus_thermo_cu` | Switch | Indicates if at least one probe is in PROTECTION mode: `ON`, `OFF` | R | Y | +| `atLeastOneProbeManual` | `bus_thermo_cu` | Switch | Indicates if at least one probe is in MANUAL mode: `ON`, `OFF` | R | Y | ### Notes on channels @@ -282,7 +299,7 @@ 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 set) or with `scenarioProgram` (if `SCENARIO` was set) you can set the program number -Example: if you want to activate SCENARIO #9 on the thermo Central Unit you have to set `mode` = `SCENARIO` and `scenarioProgram` = `9`. +Example: if you want to activate SCENARIO number 9 on the thermo Central Unit you have to set `mode` = `SCENARIO` and `scenarioProgram` = `9`. ## Full Example @@ -309,7 +326,10 @@ Bridge openwebnet:bus_gateway:mybridge "MyHOMEServer1" [ host="192.168.1.35", pa 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" ] - bus_aux Alarm_activation "Alarm activation" [ where="4" ] + bus_aux Alarm_Control "Alarm control" [ where="4" ] + + bus_alarm_system Alarm_Sys "Alarm System" [ where="0" ] + bus_alarm_zone Alarm_Zone_3 "Alarm Zone 3" [ where="3" ] } ``` @@ -328,32 +348,32 @@ Bridge openwebnet:zb_gateway:myZBgateway [ serialPort="COM3" ] { Example items linked to BUS devices: -NOTE: lights, blinds and zones (thermostat) can be handled from personal assistants (Google Home, Alexa). In the following example `Google Assistant` (`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/) +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", 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", 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" } -String iCU_3550_func "Function" (gCentralUnit) { channel="openwebnet:bus_thermo_cu:mybridge:CU_3550:function" } -Switch iCU_3550_at1off "At least one probe in OFF" (gCentralUnit) { channel="openwebnet:bus_thermo_cu:mybridge:CU_3550:atLeastOneProbeOff" } -Switch iCU_3550_at1pro "At least one probe in PROTECTION" (gCentralUnit) { channel="openwebnet:bus_thermo_cu:mybridge:CU_3550:atLeastOneProbeProtection" } -Switch iCU_3550_at1man "At least one probe in MANUAL" (gCentralUnit) { channel="openwebnet:bus_thermo_cu:mybridge:CU_3550:atLeastOneProbeManual" } -Switch iCU_3550_failure "Failure discovered" (gCentralUnit) { channel="openwebnet:bus_thermo_cu:mybridge:CU_3550:failureDiscovered" } - -Group gLivingRoomZone "Living Room Zone" { ga="Thermostat" [ modes="auto=GENERIC,heat=HEATING,cool=COOLING", thermostatTemperatureRange="7,35", useFahrenheit=false ] } +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", 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 thermo central unit +Group gCentralUnit "Thermo 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" } +String iCU_3550_func "Function" (gCentralUnit) { channel="openwebnet:bus_thermo_cu:mybridge:CU_3550:function" } +Switch iCU_3550_at1off "At least one probe in OFF" (gCentralUnit) { channel="openwebnet:bus_thermo_cu:mybridge:CU_3550:atLeastOneProbeOff" } +Switch iCU_3550_at1pro "At least one probe in PROTECTION" (gCentralUnit) { channel="openwebnet:bus_thermo_cu:mybridge:CU_3550:atLeastOneProbeProtection" } +Switch iCU_3550_at1man "At least one probe in MANUAL" (gCentralUnit) { channel="openwebnet:bus_thermo_cu:mybridge:CU_3550:atLeastOneProbeManual" } +Switch iCU_3550_failure "Failure discovered" (gCentralUnit) { channel="openwebnet:bus_thermo_cu:mybridge:CU_3550:failureDiscovered" } + +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" } Number:Temperature iLR_zone_setTemp "SetPoint Temperature" (gLivingRoomZone) { channel="openwebnet:bus_thermo_zone:mybridge:LR_zone:setpointTemperature", ga="thermostatTemperatureSetpoint" } String iLR_zone_fanSpeed "FanSpeed" (gLivingRoomZone) { channel="openwebnet:bus_thermo_zone:mybridge:LR_zone:speedFanCoil" } @@ -363,15 +383,21 @@ String iLR_zone_actuators "Actuators" (g String iLR_zone_hv "Heating valves" (gLivingRoomZone) { channel="openwebnet:bus_thermo_zone:mybridge:LR_zone:heatingValves" } String iLR_zone_cv "Conditioning valves" (gLivingRoomZone) { channel="openwebnet:bus_thermo_zone:mybridge:LR_zone:conditioningValves" } -Number:Temperature iEXT_temp "Temperature [%.1f %unit%]" (gExternal) { channel="openwebnet:bus_thermo_sensor:mybridge:EXT_tempsensor:temperature" } +Number:Temperature iEXT_temp "Temperature [%.1f %unit%]" (gExternal) { channel="openwebnet:bus_thermo_sensor:mybridge:EXT_tempsensor:temperature" } String iCENPlusProxyItem "CEN+ Proxy Item" -String iAlarm_activation "Alarm Activation" { channel="openwebnet:bus_aux:mybridge:Alarm_activation:aux"} - -Switch iLR_IR_sensor "Sensor" { channel="openwebnet:bus_dry_contact_ir:mybridge:LR_IR_sensor:sensor" } +Switch iLR_IR_sensor "Sensor" { channel="openwebnet:bus_dry_contact_ir:mybridge:LR_IR_sensor:sensor" } +// alarm aux, alarm unit and a zone +String iAlarm_Control "Alarm Control Arm/Disarm" (gAlarm) { channel="openwebnet:bus_aux:mybridge:Alarm_Control:aux"} +Switch iAlarm_System_State "Alarm state" (gAlarm) { channel="openwebnet:bus_alarm_system:mybridge:Alarm_Sys:state" } +Switch iAlarm_System_Armed "Alarm armed" (gAlarm) { channel="openwebnet:bus_alarm_system:mybridge:Alarm_Sys:armed" } +Switch iAlarm_System_Network "Alarm network" (gAlarm) { channel="openwebnet:bus_alarm_system:mybridge:Alarm_Sys:network" } +String iAlarm_System_Battery "Alarm battery" (gAlarm) { channel="openwebnet:bus_alarm_system:mybridge:Alarm_Sys:battery" } +Switch iAlarm_Zone_3_State "Zone 3 state" (gAlarm) { channel="openwebnet:bus_alarm_zone:mybridge:Alarm_Zone_3:state" } +String iAlarm_Zone_3_Alarm "Zone 3 alarm" (gAlarm) { channel="openwebnet:bus_alarm_zone:mybridge:Alarm_Zone_3:alarm" } ``` Example items linked to OpenWebNet ZigBee devices: @@ -419,10 +445,15 @@ sitemap openwebnet label="OpenWebNet Binding Example Sitemap" Switch item=iCENPlusProxyItem label="My CEN+ scenario" icon="movecontrol" mappings=[ON="Activate"] } - Frame label="Alarm activation via AUX command" + Frame label="Alarm" { - Switch item=iAlarm_activation icon="siren" - + Switch item=iAlarm_System_State label="Alarm state" + Switch item=iAlarm_Control label="Arm/Disarm alarm" icon="shield" + Switch item=iAlarm_System_Armed label="Armed" icon="shield" + Switch item=iAlarm_System_Network label="Network" icon="network" + Default item=iAlarm_System_Battery label="Battery" icon="battery" + Switch item=iAlarm_Zone_3_State label="Zone 3 state" + Default item=iAlarm_Zone_3_Alarm label="Zone 3 alarm" icon="siren" } } ``` @@ -467,6 +498,7 @@ when then sendCommand(iLR_dimmer, DECREASE) end + ``` ## Notes @@ -486,5 +518,6 @@ Special thanks for helping on testing this binding go to: [@gabriele.daltoe](https://community.openhab.org/u/gabriele.daltoe), [@feodor](https://community.openhab.org/u/feodor), [@aconte80](https://community.openhab.org/u/aconte80), -[@rubenfuser](https://community.openhab.org/u/rubenfuser) +[@rubenfuser](https://community.openhab.org/u/rubenfuser), +[@stamate_viorel](https://community.openhab.org/u/stamate_viorel) and many others at the fantastic openHAB community! diff --git a/bundles/org.openhab.binding.openwebnet/pom.xml b/bundles/org.openhab.binding.openwebnet/pom.xml index d9bf3e359c476..89dc8c9537e7d 100644 --- a/bundles/org.openhab.binding.openwebnet/pom.xml +++ b/bundles/org.openhab.binding.openwebnet/pom.xml @@ -23,7 +23,7 @@ io.github.openwebnet4j openwebnet4j - 0.9.0 + 0.9.1 compile 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 812f549cbc865..4b7f32ea392b4 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 @@ -22,7 +22,8 @@ import org.openhab.core.thing.ThingTypeUID; /** - * The {@link OpenWebNetBindingConstants} class defines common constants, which are used across the whole binding. + * The {@link OpenWebNetBindingConstants} class defines common constants, which + * are used across the whole binding. * * @author Massimo Valla - Initial contribution, updates * @author Gilberto Cocchi - Thermoregulation @@ -72,6 +73,10 @@ public class OpenWebNetBindingConstants { public static final String THING_LABEL_BUS_CENPLUS_SCENARIO_CONTROL = "CEN+ Scenario Control"; public static final ThingTypeUID THING_TYPE_BUS_SCENARIO = new ThingTypeUID(BINDING_ID, "bus_scenario_control"); public static final String THING_LABEL_BUS_SCENARIO = "Scenario Control"; + public static final ThingTypeUID THING_TYPE_BUS_ALARM_SYSTEM = new ThingTypeUID(BINDING_ID, "bus_alarm_system"); + public static final String THING_LABEL_BUS_ALARM_SYSTEM = "Alarm System"; + public static final ThingTypeUID THING_TYPE_BUS_ALARM_ZONE = new ThingTypeUID(BINDING_ID, "bus_alarm_zone"); + public static final String THING_LABEL_BUS_ALARM_ZONE = "Alarm Zone"; public static final ThingTypeUID THING_TYPE_BUS_AUX = new ThingTypeUID(BINDING_ID, "bus_aux"); public static final String THING_LABEL_BUS_AUX = "Auxiliary"; // ZIGBEE @@ -107,12 +112,16 @@ public class OpenWebNetBindingConstants { public static final Set SCENARIO_BASIC_SUPPORTED_THING_TYPES = Set.of(THING_TYPE_BUS_SCENARIO); // ## Aux public static final Set AUX_SUPPORTED_THING_TYPES = Set.of(THING_TYPE_BUS_AUX); + // ## Alarm + public static final Set ALARM_SUPPORTED_THING_TYPES = Set.of(THING_TYPE_BUS_ALARM_SYSTEM, + THING_TYPE_BUS_ALARM_ZONE); + // ## Groups public static final Set DEVICE_SUPPORTED_THING_TYPES = Stream .of(LIGHTING_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, - GENERIC_SUPPORTED_THING_TYPES) + ALARM_SUPPORTED_THING_TYPES, GENERIC_SUPPORTED_THING_TYPES) .flatMap(Collection::stream).collect(Collectors.toCollection(HashSet::new)); public static final Set BRIDGE_SUPPORTED_THING_TYPES = Set.of(THING_TYPE_ZB_GATEWAY, THING_TYPE_BUS_GATEWAY); @@ -157,6 +166,13 @@ public class OpenWebNetBindingConstants { public static final String CHANNEL_SCENARIO = "scenario"; // aux public static final String CHANNEL_AUX = "aux"; + // alarm + public static final String CHANNEL_ALARM_SYSTEM_STATE = "state"; + public static final String CHANNEL_ALARM_SYSTEM_ARMED = "armed"; + public static final String CHANNEL_ALARM_SYSTEM_NETWORK = "network"; + public static final String CHANNEL_ALARM_SYSTEM_BATTERY = "battery"; + public static final String CHANNEL_ALARM_ZONE_STATE = "state"; + public static final String CHANNEL_ALARM_ZONE_ALARM_STATE = "alarm"; // devices config properties public static final String CONFIG_PROPERTY_WHERE = "where"; 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 4459e9526de8d..5bc6bc7b6e1e7 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 @@ -16,6 +16,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.openwebnet.internal.handler.OpenWebNetAlarmHandler; import org.openhab.binding.openwebnet.internal.handler.OpenWebNetAutomationHandler; import org.openhab.binding.openwebnet.internal.handler.OpenWebNetAuxiliaryHandler; import org.openhab.binding.openwebnet.internal.handler.OpenWebNetBridgeHandler; @@ -83,6 +84,9 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { } else if (OpenWebNetScenarioBasicHandler.SUPPORTED_THING_TYPES.contains(thing.getThingTypeUID())) { logger.debug("Creating NEW BASIC SCENARIO Handler"); return new OpenWebNetScenarioBasicHandler(thing); + } else if (OpenWebNetAlarmHandler.SUPPORTED_THING_TYPES.contains(thing.getThingTypeUID())) { + logger.debug("creating NEW ALARM Handler"); + return new OpenWebNetAlarmHandler(thing); } logger.warn("ThingType {} is not supported by this binding", thing.getThingTypeUID()); return null; 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 ce6264c0fcb52..c14d30c4b70cc 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 @@ -31,6 +31,7 @@ import org.openwebnet4j.OpenDeviceType; import org.openwebnet4j.message.BaseOpenMessage; import org.openwebnet4j.message.Where; +import org.openwebnet4j.message.WhereAlarm; import org.openwebnet4j.message.WhereThermo; import org.openwebnet4j.message.WhereZigBee; import org.openwebnet4j.message.Who; @@ -95,7 +96,8 @@ public void abortScan() { * @param message the OWN message received that identified the device * (optional) */ - public void newDiscoveryResult(Where where, OpenDeviceType deviceType, @Nullable BaseOpenMessage baseMsg) { + public void newDiscoveryResult(@Nullable Where where, OpenDeviceType deviceType, + @Nullable BaseOpenMessage baseMsg) { logger.debug("newDiscoveryResult() WHERE={}, deviceType={}", where, deviceType); ThingTypeUID thingTypeUID = OpenWebNetBindingConstants.THING_TYPE_GENERIC_DEVICE; // generic device String thingLabel = OpenWebNetBindingConstants.THING_LABEL_GENERIC_DEVICE; @@ -189,6 +191,18 @@ public void newDiscoveryResult(Where where, OpenDeviceType deviceType, @Nullable deviceWho = Who.AUX; break; } + case SCS_ALARM_CENTRAL_UNIT: { + thingTypeUID = OpenWebNetBindingConstants.THING_TYPE_BUS_ALARM_SYSTEM; + thingLabel = OpenWebNetBindingConstants.THING_LABEL_BUS_ALARM_SYSTEM; + deviceWho = Who.BURGLAR_ALARM; + break; + } + case SCS_ALARM_ZONE: { + thingTypeUID = OpenWebNetBindingConstants.THING_TYPE_BUS_ALARM_ZONE; + thingLabel = OpenWebNetBindingConstants.THING_LABEL_BUS_ALARM_ZONE; + deviceWho = Who.BURGLAR_ALARM; + break; + } default: logger.warn("Device type {} is not supported, default to GENERIC device (WHERE={})", deviceType, where); if (where instanceof WhereZigBee) { @@ -198,35 +212,46 @@ public void newDiscoveryResult(Where where, OpenDeviceType deviceType, @Nullable deviceWho = baseMsg.getWho(); } } + Where w; + if (where != null) { + w = where; + } else if (OpenWebNetBindingConstants.THING_TYPE_BUS_ALARM_SYSTEM.equals(thingTypeUID)) { + w = new WhereAlarm("0"); + } else { + logger.debug("ignoring newDiscoveryResult with null where: {}", baseMsg); + return; + } - String ownId = bridgeHandler.ownIdFromWhoWhere(deviceWho, where); + String ownId = bridgeHandler.ownIdFromWhoWhere(deviceWho, w); if (OpenWebNetBindingConstants.THING_TYPE_BUS_ON_OFF_SWITCH.equals(thingTypeUID)) { if (bridgeHandler.getRegisteredDevice(ownId) != null) { - logger.debug("dimmer/switch with WHERE={} already registered, skipping this discovery result", where); + logger.debug("dimmer/switch with WHERE={} already registered, skipping this discovery result", w); return; } } - String tId = bridgeHandler.thingIdFromWhere(where); + String tId = bridgeHandler.thingIdFromWhere(w); ThingUID thingUID = new ThingUID(thingTypeUID, bridgeUID, tId); DiscoveryResult discoveryResult = null; - String whereConfig = where.value(); + String whereConfig = w.value(); - // remove # from discovered thermo zone or central unit + // remove # from discovered thermo zone/central unit or alarm zone if (OpenWebNetBindingConstants.THING_TYPE_BUS_THERMO_ZONE.equals(thingTypeUID) || OpenWebNetBindingConstants.THING_TYPE_BUS_THERMO_CU.equals(thingTypeUID)) { whereConfig = "" + ((WhereThermo) where).getZone(); + } else if (OpenWebNetBindingConstants.THING_TYPE_BUS_ALARM_ZONE.equals(thingTypeUID)) { + whereConfig = "" + ((WhereAlarm) where).getZone(); } - if (where instanceof WhereZigBee && WhereZigBee.UNIT_02.equals(((WhereZigBee) where).getUnit())) { + if (w instanceof WhereZigBee && WhereZigBee.UNIT_02.equals(((WhereZigBee) where).getUnit())) { logger.debug("UNIT=02 found (WHERE={}) -> will remove previous result if exists", where); thingRemoved(thingUID); // remove previously discovered thing // re-create thingUID with new type thingTypeUID = OpenWebNetBindingConstants.THING_TYPE_ZB_ON_OFF_SWITCH_2UNITS; thingLabel = OpenWebNetBindingConstants.THING_LABEL_ZB_ON_OFF_SWITCH_2UNITS; thingUID = new ThingUID(thingTypeUID, bridgeUID, tId); - whereConfig = ((WhereZigBee) where).valueWithUnit(WhereZigBee.UNIT_ALL); // replace unit '02' with '00' + whereConfig = ((WhereZigBee) w).valueWithUnit(WhereZigBee.UNIT_ALL); // replace unit '02' with '00' logger.debug("UNIT=02, switching type from {} to {}", OpenWebNetBindingConstants.THING_TYPE_ZB_ON_OFF_SWITCH, OpenWebNetBindingConstants.THING_TYPE_ZB_ON_OFF_SWITCH_2UNITS); 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 new file mode 100644 index 0000000000000..f3361f36fd865 --- /dev/null +++ b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetAlarmHandler.java @@ -0,0 +1,233 @@ +/** + * Copyright (c) 2010-2022 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.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants; +import org.openhab.core.library.types.OnOffType; +import org.openhab.core.library.types.StringType; +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.Alarm; +import org.openwebnet4j.message.Alarm.WhatAlarm; +import org.openwebnet4j.message.BaseOpenMessage; +import org.openwebnet4j.message.Where; +import org.openwebnet4j.message.WhereAlarm; +import org.openwebnet4j.message.Who; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link OpenWebNetAlarmHandler} is responsible for handling + * commands/messages for Alarm system and zones. It extends the abstract + * {@link OpenWebNetThingHandler}. + * + * @author Massimo Valla - Initial contribution + */ +@NonNullByDefault +public class OpenWebNetAlarmHandler extends OpenWebNetThingHandler { + + private final Logger logger = LoggerFactory.getLogger(OpenWebNetAlarmHandler.class); + + public static final Set SUPPORTED_THING_TYPES = OpenWebNetBindingConstants.ALARM_SUPPORTED_THING_TYPES; + + private static long lastAllDevicesRefreshTS = 0; // ts when last all device refresh was sent for this handler + + private static final String BATTERY_OK = "OK"; + private static final String BATTERY_FAULT = "FAULT"; + private static final String BATTERY_UNLOADED = "UNLOADED"; + + private static final String SILENT = "SILENT"; + private static final String INTRUSION = "INTRUSION"; + private static final String ANTI_PANIC = "ANTI_PANIC"; + private static final String TAMPERING = "TAMPERING"; + + public OpenWebNetAlarmHandler(Thing thing) { + super(thing); + } + + @Override + protected void handleChannelCommand(ChannelUID channel, Command command) { + logger.warn("Alarm.handleChannelCommand() Read only channel, unsupported command {}", command); + } + + @Override + protected void requestChannelState(ChannelUID channel) { + super.requestChannelState(channel); + Where w = deviceWhere; + ThingTypeUID thingType = thing.getThingTypeUID(); + try { + if (THING_TYPE_BUS_ALARM_SYSTEM.equals(thingType)) { + send(Alarm.requestSystemStatus()); + lastAllDevicesRefreshTS = System.currentTimeMillis(); + } else { + if (w != null) { + send(Alarm.requestZoneStatus("#" + w.value())); + } else { + logger.debug("null where while requesting state for channel {}", channel); + } + } + } catch (OWNException e) { + logger.debug("Exception while requesting state for channel {}: {} ", channel, e.getMessage()); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); + } + } + + @Override + protected long getRefreshAllLastTS() { + return lastAllDevicesRefreshTS; + }; + + @Override + protected void refreshDevice(boolean refreshAll) { + if (refreshAll) { + logger.debug("--- refreshDevice() : refreshing all via ALARM CENTRAL UNIT... ({})", thing.getUID()); + try { + send(Alarm.requestSystemStatus()); + lastAllDevicesRefreshTS = System.currentTimeMillis(); + } catch (OWNException e) { + logger.warn("Excpetion while requesting alarm system status: {}", e.getMessage()); + } + } else { + logger.debug("--- refreshDevice() : refreshing SINGLE... ({})", thing.getUID()); + requestChannelState(new ChannelUID(thing.getUID(), CHANNEL_ALARM_SYSTEM_STATE)); + } + } + + @Override + protected void handleMessage(BaseOpenMessage msg) { + logger.debug("handleMessage({}) for thing: {}", msg, thing.getUID()); + super.handleMessage(msg); + ThingTypeUID thingType = thing.getThingTypeUID(); + if (THING_TYPE_BUS_ALARM_SYSTEM.equals(thingType)) { + updateSystem((Alarm) msg); + } else { + updateZone((Alarm) msg); + } + } + + private void updateSystem(Alarm msg) { + WhatAlarm w = (WhatAlarm) msg.getWhat(); + if (w == null) { + logger.debug("Alarm.updateSystem() WHAT is null. Frame={}", msg); + return; + } + switch (w) { + case SYSTEM_ACTIVE: + case SYSTEM_INACTIVE: + case SYSTEM_MAINTENANCE: + updateAlarmSystemState(w); + break; + case SYSTEM_DISENGAGED: + case SYSTEM_ENGAGED: + updateAlarmSystemArmed(w); + break; + case SYSTEM_BATTERY_FAULT: + case SYSTEM_BATTERY_OK: + case SYSTEM_BATTERY_UNLOADED: + updateBatteryState(w); + break; + case SYSTEM_NETWORK_ERROR: + case SYSTEM_NETWORK_OK: + updateNetworkState(w); + break; + case START_PROGRAMMING: + case STOP_PROGRAMMING: + case DELAY_END: + case NO_CONNECTION_TO_DEVICE: + default: + logger.debug("Alarm.updateSystem() Ignoring unsupported WHAT {}. Frame={}", msg.getWhat(), msg); + } + } + + private void updateAlarmSystemState(WhatAlarm w) { + updateState(CHANNEL_ALARM_SYSTEM_STATE, OnOffType.from(w == Alarm.WhatAlarm.SYSTEM_ACTIVE)); + } + + private void updateAlarmSystemArmed(WhatAlarm w) { + updateState(CHANNEL_ALARM_SYSTEM_ARMED, OnOffType.from(w == Alarm.WhatAlarm.SYSTEM_ENGAGED)); + } + + private void updateNetworkState(WhatAlarm w) { + updateState(CHANNEL_ALARM_SYSTEM_NETWORK, OnOffType.from(w == Alarm.WhatAlarm.SYSTEM_NETWORK_OK)); + } + + private void updateBatteryState(WhatAlarm w) { + if (w == Alarm.WhatAlarm.SYSTEM_BATTERY_OK) { + updateState(CHANNEL_ALARM_SYSTEM_BATTERY, new StringType(BATTERY_OK)); + } else if (w == Alarm.WhatAlarm.SYSTEM_BATTERY_UNLOADED) { + updateState(CHANNEL_ALARM_SYSTEM_BATTERY, new StringType(BATTERY_UNLOADED)); + } else { + updateState(CHANNEL_ALARM_SYSTEM_BATTERY, new StringType(BATTERY_FAULT)); + } + } + + private void updateZone(Alarm msg) { + WhatAlarm w = (WhatAlarm) msg.getWhat(); + if (w == null) { + logger.debug("Alarm.updateZone() WHAT is null. Frame={}", msg); + return; + } + switch (w) { + case ZONE_DISENGAGED: + case ZONE_ENGAGED: + updateZoneState(w); + break; + case ZONE_ALARM_INTRUSION: + case ZONE_ALARM_TAMPERING: + case ZONE_ALARM_ANTI_PANIC: + case ZONE_ALARM_SILENT: + updateZoneAlarmState(w); + break; + case ZONE_ALARM_TECHNICAL:// not handled for now + case ZONE_ALARM_TECHNICAL_RESET: + default: + logger.debug("Alarm.updateZone() Ignoring unsupported WHAT {}. Frame={}", msg.getWhat(), msg); + } + } + + private void updateZoneState(WhatAlarm w) { + updateState(CHANNEL_ALARM_ZONE_STATE, OnOffType.from(w == Alarm.WhatAlarm.ZONE_ENGAGED)); + } + + private void updateZoneAlarmState(WhatAlarm w) { + if (w == Alarm.WhatAlarm.ZONE_ALARM_SILENT) { + updateState(CHANNEL_ALARM_ZONE_ALARM_STATE, new StringType(SILENT)); + } else if (w == Alarm.WhatAlarm.ZONE_ALARM_INTRUSION) { + updateState(CHANNEL_ALARM_ZONE_ALARM_STATE, new StringType(INTRUSION)); + } else if (w == Alarm.WhatAlarm.ZONE_ALARM_ANTI_PANIC) { + updateState(CHANNEL_ALARM_ZONE_ALARM_STATE, new StringType(ANTI_PANIC)); + } else { + updateState(CHANNEL_ALARM_ZONE_ALARM_STATE, new StringType(TAMPERING)); + } + } + + @Override + protected Where buildBusWhere(String wStr) throws IllegalArgumentException { + return new WhereAlarm(wStr); + } + + @Override + protected String ownIdPrefix() { + return Who.BURGLAR_ALARM.value().toString(); + } +} 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 4c59acd261780..33a47253e7914 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 @@ -48,6 +48,7 @@ import org.openwebnet4j.USBGateway; import org.openwebnet4j.communication.OWNAuthException; import org.openwebnet4j.communication.OWNException; +import org.openwebnet4j.message.Alarm; import org.openwebnet4j.message.Automation; import org.openwebnet4j.message.Auxiliary; import org.openwebnet4j.message.BaseOpenMessage; @@ -67,7 +68,8 @@ import org.slf4j.LoggerFactory; /** - * The {@link OpenWebNetBridgeHandler} is responsible for handling communication with gateways and handling events. + * The {@link OpenWebNetBridgeHandler} is responsible for handling communication + * with gateways and handling events. * * @author Massimo Valla - Initial contribution, Lighting, Automation, Scenario * @author Andrea Conte - Energy management, Thermoregulation @@ -95,7 +97,8 @@ public class OpenWebNetBridgeHandler extends ConfigStatusBridgeHandler implement public static final Set SUPPORTED_THING_TYPES = OpenWebNetBindingConstants.BRIDGE_SUPPORTED_THING_TYPES; // ConcurrentHashMap of devices registered to this BridgeHandler - // association is: ownId (String) -> OpenWebNetThingHandler, with ownId = WHO.WHERE + // association is: ownId (String) -> OpenWebNetThingHandler, with ownId = + // WHO.WHERE private Map registeredDevices = new ConcurrentHashMap<>(); private Map discoveringDevices = new ConcurrentHashMap<>(); @@ -296,10 +299,10 @@ public synchronized void searchDevices() { public void onNewDevice(@Nullable Where w, @Nullable OpenDeviceType deviceType, @Nullable BaseOpenMessage message) { OpenWebNetDeviceDiscoveryService discService = deviceDiscoveryService; if (discService != null) { - if (w != null && deviceType != null) { + if (deviceType != null) { discService.newDiscoveryResult(w, deviceType, message); } else { - logger.warn("onNewDevice with null where/deviceType, msg={}", message); + logger.warn("onNewDevice with null deviceType, msg={}", message); } } else { logger.warn("onNewDevice but null deviceDiscoveryService"); @@ -312,7 +315,8 @@ public void onDiscoveryCompleted() { } /** - * Notifies that the scan has been stopped/aborted by OpenWebNetDeviceDiscoveryService + * Notifies that the scan has been stopped/aborted by + * OpenWebNetDeviceDiscoveryService */ public void scanStopped() { scanIsActive = false; @@ -328,7 +332,8 @@ private void discoverByActivation(BaseOpenMessage baseMsg) { } // we support these types only if (baseMsg instanceof Lighting || baseMsg instanceof Automation || baseMsg instanceof EnergyManagement - || baseMsg instanceof Thermoregulation || baseMsg instanceof CEN || baseMsg instanceof Scenario) { + || baseMsg instanceof Thermoregulation || baseMsg instanceof CEN || baseMsg instanceof Scenario + || baseMsg instanceof Alarm) { BaseOpenMessage bmsg = baseMsg; if (baseMsg instanceof Lighting) { What what = baseMsg.getWhat(); @@ -433,7 +438,8 @@ private void refreshAllBridgeDevices() { return; } } 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 + // a device has been registered with the bridge just now, let's wait for other + // devices: re-schedule // refreshAllDevices logger.debug("--- REGISTER device just called... re-scheduling refreshAllBridgeDevices()"); refreshAllSchedule = scheduler.schedule(this::refreshAllBridgeDevices, REFRESH_ALL_DEVICES_DELAY_MSEC, @@ -501,7 +507,7 @@ public void onEventMessage(@Nullable OpenMessage 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 - || baseMsg instanceof Scenario) { + || baseMsg instanceof Scenario || baseMsg instanceof Alarm) { String ownId = ownIdFromMessage(baseMsg); logger.debug("ownIdFromMessage({}) --> {}", baseMsg, ownId); OpenWebNetThingHandler deviceHandler = registeredDevices.get(ownId); @@ -665,7 +671,16 @@ public String ownIdFromWhoWhere(Who who, Where where) { * @return the ownId String */ public String ownIdFromMessage(BaseOpenMessage baseMsg) { - return baseMsg.getWho().value() + "." + normalizeWhere(baseMsg.getWhere()); + @Nullable + Where w = baseMsg.getWhere(); + if (w != null) { + return baseMsg.getWho().value() + "." + normalizeWhere(w); + } else if (baseMsg instanceof Alarm) { // null and Alarm + return baseMsg.getWho().value() + "." + "0"; // Alarm System --> where=0 + } else { + logger.warn("ownIdFromMessage with null where: {}", baseMsg); + return ""; + } } /** @@ -690,7 +705,8 @@ public String normalizeWhere(Where where) { str = ((WhereZigBee) where).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 + 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) { // 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/resources/OH-INF/i18n/openwebnet.properties b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/i18n/openwebnet.properties index 478ab6c91bf71..390636455ce40 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 @@ -5,6 +5,10 @@ binding.openwebnet.description = The OpenWebNet Binding integrates the BTicino/L # thing types +thing-type.openwebnet.bus_alarm_system.label = Alarm System +thing-type.openwebnet.bus_alarm_system.description = A OpenWebNet BUS/SCS alarm system. +thing-type.openwebnet.bus_alarm_zone.label = Alarm Zone +thing-type.openwebnet.bus_alarm_zone.description = A OpenWebNet BUS/SCS configured alarm zone. thing-type.openwebnet.bus_automation.label = Automation thing-type.openwebnet.bus_automation.description = An OpenWebNet BUS/SCS automation device to control roller shutters, blinds, etc. BTicino models: xxx/yyyy/etc. thing-type.openwebnet.bus_aux.label = Auxiliary @@ -46,6 +50,10 @@ thing-type.openwebnet.zb_on_off_switch2u.description = An OpenWebNet ZigBee 2-un # thing types config +thing-type.config.openwebnet.bus_alarm_system.where.label = OpenWebNet Address (where) +thing-type.config.openwebnet.bus_alarm_system.where.description = The alarm system has no where address (set where to 0 as default). +thing-type.config.openwebnet.bus_alarm_zone.where.label = OpenWebNet Address (where) +thing-type.config.openwebnet.bus_alarm_zone.where.description = Example: alarm zone 2 --> where=2. thing-type.config.openwebnet.bus_automation.shutterRun.label = Shutter Run thing-type.config.openwebnet.bus_automation.shutterRun.description = Time (in ms) to go from max position (e.g. CLOSED) to the other position (e.g. OPEN). Example: 12000 (=12sec). Use AUTO (default) to calibrate the shutter automatically (UP->DOWN->Position%) the first time a Position command (%) is sent. thing-type.config.openwebnet.bus_automation.where.label = OpenWebNet Address (where) @@ -117,6 +125,19 @@ channel-type.openwebnet.actuators.state.option.ON_SPEED_3 = ON speed 3 channel-type.openwebnet.actuators.state.option.OFF_SPEED_1 = OFF speed 1 channel-type.openwebnet.actuators.state.option.OFF_SPEED_2 = OFF speed 2 channel-type.openwebnet.actuators.state.option.OFF_SPEED_3 = OFF speed 3 +channel-type.openwebnet.alarmBattery.label = Battery State +channel-type.openwebnet.alarmBattery.description = Alarm system battery state (read only). +channel-type.openwebnet.alarmBattery.state.option.OK = Ok +channel-type.openwebnet.alarmBattery.state.option.FAULT = Fault +channel-type.openwebnet.alarmBattery.state.option.UNLOADED = Unloaded +channel-type.openwebnet.alarmNetwork.label = Network State +channel-type.openwebnet.alarmNetwork.description = Alarm system network state (ON = network OK, OFF = no network) (read only). +channel-type.openwebnet.alarmSystemState.label = System State +channel-type.openwebnet.alarmSystemState.description = Alarm system is active (ON) or inactive (OFF) (read only). +channel-type.openwebnet.alarmZoneState.label = Alarm Zone State +channel-type.openwebnet.alarmZoneState.description = Alarm zone is active (ON) or inactive (OFF) (read only). +channel-type.openwebnet.armedState.label = Armed State +channel-type.openwebnet.armedState.description = Alarm is armed (ON) or disarmed (OFF) (read only). channel-type.openwebnet.atLeastOneProbeManual.label = At least one probe in MANUAL channel-type.openwebnet.atLeastOneProbeManual.description = At least one probe in MANUAL indicator in Central Unit (read only) channel-type.openwebnet.atLeastOneProbeOff.label = At least one probe OFF @@ -144,20 +165,8 @@ channel-type.openwebnet.brightness.label = Brightness channel-type.openwebnet.brightness.description = Control the brightness and switch the light ON and OFF (read/write) channel-type.openwebnet.cenButtonEvent.label = CEN Button Event channel-type.openwebnet.cenButtonEvent.description = Event corresponding to the button press (read only) - -# channel-type.openwebnet.cenButtonEvent.event.option.START_PRESS = Start press -# channel-type.openwebnet.cenButtonEvent.event.option.SHORT_PRESS = Release after short press -# channel-type.openwebnet.cenButtonEvent.event.option.EXTENDED_PRESS = Extended press (repeated until release) -# channel-type.openwebnet.cenButtonEvent.event.option.RELEASE_EXTENDED_PRESS = Release after extended press - channel-type.openwebnet.cenPlusButtonEvent.label = CEN+ Button Event channel-type.openwebnet.cenPlusButtonEvent.description = Event corresponding to the button press (read only) - -# channel-type.openwebnet.cenPlusButtonEvent.event.option.SHORT_PRESS = Short press -# channel-type.openwebnet.cenPlusButtonEvent.event.option.START_EXTENDED_PRESS = Start of extended press -# channel-type.openwebnet.cenPlusButtonEvent.event.option.EXTENDED_PRESS = Extended press (repeated until release) -# channel-type.openwebnet.cenPlusButtonEvent.event.option.RELEASE_EXTENDED_PRESS = Release after extended press - channel-type.openwebnet.conditioningValves.label = Conditioning Valves channel-type.openwebnet.conditioningValves.description = Conditioning Valves status (read only) channel-type.openwebnet.conditioningValves.state.option.OFF = OFF @@ -230,28 +239,6 @@ channel-type.openwebnet.remoteControl.state.option.DISABLED = DISABLED channel-type.openwebnet.remoteControl.state.option.ENABLED = ENABLED channel-type.openwebnet.scenarioEvent.label = Activated Scenario Event channel-type.openwebnet.scenarioEvent.description = Event corresponding to the number of Basic Scenario that has been activated (read only) - -# channel-type.openwebnet.scenarioEvent.event.option.SCENARIO_01 = Scenario 1 -# channel-type.openwebnet.scenarioEvent.event.option.SCENARIO_02 = Scenario 2 -# channel-type.openwebnet.scenarioEvent.event.option.SCENARIO_03 = Scenario 3 -# channel-type.openwebnet.scenarioEvent.event.option.SCENARIO_04 = Scenario 4 -# channel-type.openwebnet.scenarioEvent.event.option.SCENARIO_05 = Scenario 5 -# channel-type.openwebnet.scenarioEvent.event.option.SCENARIO_06 = Scenario 6 -# channel-type.openwebnet.scenarioEvent.event.option.SCENARIO_07 = Scenario 7 -# channel-type.openwebnet.scenarioEvent.event.option.SCENARIO_08 = Scenario 8 -# channel-type.openwebnet.scenarioEvent.event.option.SCENARIO_09 = Scenario 9 -# channel-type.openwebnet.scenarioEvent.event.option.SCENARIO_10 = Scenario 10 -# channel-type.openwebnet.scenarioEvent.event.option.SCENARIO_11 = Scenario 11 -# channel-type.openwebnet.scenarioEvent.event.option.SCENARIO_12 = Scenario 12 -# channel-type.openwebnet.scenarioEvent.event.option.SCENARIO_13 = Scenario 13 -# channel-type.openwebnet.scenarioEvent.event.option.SCENARIO_14 = Scenario 14 -# channel-type.openwebnet.scenarioEvent.event.option.SCENARIO_15 = Scenario 15 -# channel-type.openwebnet.scenarioEvent.event.option.SCENARIO_16 = Scenario 16 -# channel-type.openwebnet.scenarioEvent.event.option.SCENARIO_17 = Scenario 17 -# channel-type.openwebnet.scenarioEvent.event.option.SCENARIO_18 = Scenario 18 -# channel-type.openwebnet.scenarioEvent.event.option.SCENARIO_19 = Scenario 19 -# channel-type.openwebnet.scenarioEvent.event.option.SCENARIO_20 = Scenario 20 - channel-type.openwebnet.scenarioProgramCentralUnit.label = Scenario Program Number channel-type.openwebnet.scenarioProgramCentralUnit.description = Set scenario program number for the Central Unit, valid only with Central Unit mode = "SCENARIO" (read/write) channel-type.openwebnet.scenarioProgramCentralUnit.state.option.1 = Program 1 @@ -289,6 +276,12 @@ channel-type.openwebnet.weeklyProgramCentralUnit.description = Set weekly progra channel-type.openwebnet.weeklyProgramCentralUnit.state.option.1 = Program 1 channel-type.openwebnet.weeklyProgramCentralUnit.state.option.2 = Program 2 channel-type.openwebnet.weeklyProgramCentralUnit.state.option.3 = Program 3 +channel-type.openwebnet.zoneAlarm.label = Zone Alarm +channel-type.openwebnet.zoneAlarm.description = Current alarm for the zone (read only). +channel-type.openwebnet.zoneAlarm.state.option.INTRUSION = Intrusion +channel-type.openwebnet.zoneAlarm.state.option.TAMPERING = Tampering +channel-type.openwebnet.zoneAlarm.state.option.ANTI_PANIC = Anti Panic +channel-type.openwebnet.zoneAlarm.state.option.SILENT = Silent # thing status descriptions diff --git a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusAlarmSystem.xml b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusAlarmSystem.xml new file mode 100644 index 0000000000000..5f7a06a4ae7fa --- /dev/null +++ b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusAlarmSystem.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + A OpenWebNet BUS/SCS alarm system. + + + + + + + + + + + BTicino/Legrand + BTicino Burglar-alarm Unit 3486 + 5100 + + + ownId + + + + + The alarm system has no where address (set where to 0 as default). + 0 + + + + + diff --git a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusAlarmZone.xml b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusAlarmZone.xml new file mode 100644 index 0000000000000..3a0b84b9b1a5f --- /dev/null +++ b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusAlarmZone.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + A OpenWebNet BUS/SCS configured alarm zone. + + + + + + + + + BTicino/Legrand + Alarm zone as configured in the Alarm System Unit + 5200 + + + ownId + + + + + Example: alarm zone 2 --> where=2. + + + + + diff --git a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/channels.xml b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/channels.xml index aa574766443b0..412bed8c66722 100644 --- a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/channels.xml @@ -409,4 +409,59 @@ + + + Switch + + Alarm system is active (ON) or inactive (OFF) (read only). + + + + + Switch + + Alarm is armed (ON) or disarmed (OFF) (read only). + + + + + Switch + + Alarm system network state (ON = network OK, OFF = no network) (read only). + + + + + String + + Alarm system battery state (read only). + + + + + + + + + + + String + + Current alarm for the zone (read only). + + + + + + + + + + + + Switch + + Alarm zone is active (ON) or inactive (OFF) (read only). + + 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 9b942e5a21da7..d3b25f59dd5a4 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 @@ -22,6 +22,7 @@ import org.openwebnet4j.message.BaseOpenMessage; import org.openwebnet4j.message.FrameException; import org.openwebnet4j.message.Where; +import org.openwebnet4j.message.WhereAlarm; import org.openwebnet4j.message.WhereAuxiliary; import org.openwebnet4j.message.WhereCEN; import org.openwebnet4j.message.WhereEnergyManagement; @@ -33,11 +34,11 @@ import org.slf4j.LoggerFactory; /** - * Test class for {@link OpenWebNetBridgeHandler#ownID} and ThingID - * calculation using {@link OpenWebNetBridgeHandler} - * methods: normalizeWhere(), ownIdFromWhoWhere(), ownIdFromMessage(), thingIdFromWhere() + * Test class for {@link OpenWebNetBridgeHandler#ownID} and ThingID calculation + * using {@link OpenWebNetBridgeHandler} methods: normalizeWhere(), + * ownIdFromWhoWhere(), ownIdFromMessage(), thingIdFromWhere() * - * @author Massimo Valla - Initial contribution + * @author Massimo Valla - Initial contribution, updates * @author Andrea Conte - Energy management * @author Giovanni Fabiani - Auxiliary message support */ @@ -48,7 +49,6 @@ public class OwnIdTest { // @formatter:off /** - * * deviceWhere * (DevAddrParam) * TYPE WHERE = normalizeWhere() ownId ThingID @@ -68,29 +68,34 @@ 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 silent 0 0 5.0 0 + * BUS Alarm system null 0 5.0 0 */ // @formatter:on public enum TEST { // @formatter:off - zb_switch(new WhereZigBee("789309801#9"), Who.fromValue(1), "*1*1*789309801#9##", "789309800h9", "1.789309800h9", "789309800h9"), - zb_switch_2u_1(new WhereZigBee("789301201#9"), Who.fromValue(1), "*1*1*789301201#9##", "789301200h9", "1.789301200h9", "789301200h9"), - zb_switch_2u_2(new WhereZigBee("789301202#9"), Who.fromValue(1), "*1*1*789301202#9##", "789301200h9", "1.789301200h9", "789301200h9"), - bus_switch(new WhereLightAutom("51"), Who.fromValue(1), "*1*1*51##", "51", "1.51", "51"), - bus_localbus(new WhereLightAutom("25#4#01"), Who.fromValue(1), "*1*1*25#4#01##", "25h4h01", "1.25h4h01", "25h4h01"), - bus_autom(new WhereLightAutom("93"), Who.fromValue(2), "*2*0*93##", "93", "2.93", "93"), - bus_thermo_via_cu(new WhereThermo("#1"), Who.fromValue(4),"*#4*#1*0*0020##" ,"1", "4.1", "1"), - bus_thermo(new WhereThermo("1"), Who.fromValue(4),"*#4*1*0*0020##" , "1", "4.1", "1"), - bus_thermo_act(new WhereThermo("1#2"), Who.fromValue(4),"*#4*1#2*20*0##" ,"1", "4.1", "1"), - bus_tempSensor(new WhereThermo("500"), Who.fromValue(4), "*#4*500*15*1*0020*0001##", "500", "4.500", "500"), - bus_energy(new WhereEnergyManagement("51"), Who.fromValue(18), "*#18*51*113##", "51", "18.51", "51"), - bus_cen(new WhereCEN("51"), Who.fromValue(15), "*15*31*51##", "51", "15.51", "51"), - bus_cen_plus(new WhereCEN("212"), Who.fromValue(25), "*25*21#31*212##", "212", "25.212", "212"), - bus_drycontact(new WhereCEN("399"), Who.fromValue(25), "*25*32#1*399##", "399", "25.399", "399"), - bus_aux(new WhereAuxiliary("4"), Who.fromValue(9), "*9*1*4##","4","9.4","4"), - bus_scenario(new WhereLightAutom("05"), Who.fromValue(0), "*0*2*05##","05","0.05","05"); - - + // msg, who, where, normW, ownId, thingId + zb_switch("*1*1*789309801#9##", Who.fromValue(1), new WhereZigBee("789309801#9"), "789309800h9", "1.789309800h9", "789309800h9"), + 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_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_thermo_via_cu("*#4*#1*0*0020##", Who.fromValue(4), new WhereThermo("#1"), "1", "4.1", "1"), + bus_thermo("*#4*1*0*0020##", Who.fromValue(4), new WhereThermo("1"), "1", "4.1", "1"), + bus_thermo_act("*#4*1#2*20*0##", Who.fromValue(4), new WhereThermo("1#2") ,"1", "4.1", "1"), + bus_tempSensor("*#4*500*15*1*0020*0001##",Who.fromValue(4), new WhereThermo("500"), "500", "4.500", "500"), + bus_energy("*#18*51*113##", Who.fromValue(18), new WhereEnergyManagement("51"), "51", "18.51", "51"), + bus_cen("*15*31*51##", Who.fromValue(15), new WhereCEN("51"), "51", "15.51", "51"), + bus_cen_plus("*25*21#31*212##", Who.fromValue(25), new WhereCEN("212"), "212", "25.212", "212"), + 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_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"); // @formatter:on @@ -101,7 +106,7 @@ public enum TEST { public final @Nullable BaseOpenMessage msg; public final String norm, ownId, thingId; - private TEST(Where where, Who who, String msg, String norm, String ownId, String thingId) { + private TEST(String msg, Who who, Where where, String norm, String ownId, String thingId) { this.where = where; this.who = who; BaseOpenMessage bmsg = null; @@ -125,7 +130,7 @@ public void testOwnId() { BaseOpenMessage bmsg; for (int i = 0; i < TEST.values().length; i++) { TEST test = TEST.values()[i]; - logger.info("testing where={}", test.where); + logger.info("testing {} (who={} where={})", test.msg, test.who, test.where); assertEquals(test.norm, brH.normalizeWhere(test.where)); assertEquals(test.ownId, brH.ownIdFromWhoWhere(test.who, test.where)); bmsg = test.msg;