From ab290c54641fe0ff7106f44eeb29f449843c536e Mon Sep 17 00:00:00 2001 From: Matt Date: Fri, 22 Jan 2021 17:32:52 -0500 Subject: [PATCH] [haywardomnilogic] Replacement for Hayward Omnilogic Pool Automation Binding (#8685) * Initial Contribution Signed-off-by: Matt Myers --- CODEOWNERS | 1 + bom/openhab-addons/pom.xml | 5 + .../NOTICE | 14 + .../README.md | 171 +++++++ .../pom.xml | 17 + .../internal/HaywardAccount.java | 35 ++ .../internal/HaywardBindingConstants.java | 134 +++++ .../internal/HaywardException.java | 40 ++ .../internal/HaywardHandlerFactory.java | 110 ++++ .../internal/HaywardThingHandler.java | 121 +++++ .../internal/HaywardThingProperties.java | 27 + .../internal/HaywardTypeToRequest.java | 35 ++ .../internal/config/HaywardConfig.java | 30 ++ .../discovery/HaywardDiscoveryService.java | 230 +++++++++ .../handler/HaywardBackyardHandler.java | 135 +++++ .../internal/handler/HaywardBowHandler.java | 68 +++ .../handler/HaywardBridgeHandler.java | 475 ++++++++++++++++++ .../handler/HaywardChlorinatorHandler.java | 187 +++++++ .../handler/HaywardColorLogicHandler.java | 154 ++++++ .../handler/HaywardFilterHandler.java | 159 ++++++ .../handler/HaywardHeaterHandler.java | 74 +++ .../internal/handler/HaywardRelayHandler.java | 123 +++++ .../handler/HaywardSensorHandler.java | 62 +++ .../handler/HaywardVirtualHeaterHandler.java | 150 ++++++ .../main/resources/OH-INF/binding/binding.xml | 9 + .../main/resources/OH-INF/thing/backyard.xml | 76 +++ .../src/main/resources/OH-INF/thing/bow.xml | 40 ++ .../main/resources/OH-INF/thing/bridge.xml | 40 ++ .../resources/OH-INF/thing/chlorinator.xml | 103 ++++ .../resources/OH-INF/thing/colorlogic.xml | 67 +++ .../main/resources/OH-INF/thing/filter.xml | 83 +++ .../main/resources/OH-INF/thing/heater.xml | 39 ++ .../src/main/resources/OH-INF/thing/pump.xml | 37 ++ .../src/main/resources/OH-INF/thing/relay.xml | 25 + .../main/resources/OH-INF/thing/sensor.xml | 39 ++ .../resources/OH-INF/thing/virtualHeater.xml | 34 ++ bundles/pom.xml | 1 + 37 files changed, 3150 insertions(+) create mode 100644 bundles/org.openhab.binding.haywardomnilogic/NOTICE create mode 100644 bundles/org.openhab.binding.haywardomnilogic/README.md create mode 100644 bundles/org.openhab.binding.haywardomnilogic/pom.xml create mode 100644 bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/HaywardAccount.java create mode 100644 bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/HaywardBindingConstants.java create mode 100644 bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/HaywardException.java create mode 100644 bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/HaywardHandlerFactory.java create mode 100644 bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/HaywardThingHandler.java create mode 100644 bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/HaywardThingProperties.java create mode 100644 bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/HaywardTypeToRequest.java create mode 100644 bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/config/HaywardConfig.java create mode 100644 bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/discovery/HaywardDiscoveryService.java create mode 100644 bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardBackyardHandler.java create mode 100644 bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardBowHandler.java create mode 100644 bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardBridgeHandler.java create mode 100644 bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardChlorinatorHandler.java create mode 100644 bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardColorLogicHandler.java create mode 100644 bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardFilterHandler.java create mode 100644 bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardHeaterHandler.java create mode 100644 bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardRelayHandler.java create mode 100644 bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardSensorHandler.java create mode 100644 bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardVirtualHeaterHandler.java create mode 100644 bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/binding/binding.xml create mode 100644 bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/backyard.xml create mode 100644 bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/bow.xml create mode 100644 bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/bridge.xml create mode 100644 bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/chlorinator.xml create mode 100644 bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/colorlogic.xml create mode 100644 bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/filter.xml create mode 100644 bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/heater.xml create mode 100644 bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/pump.xml create mode 100644 bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/relay.xml create mode 100644 bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/sensor.xml create mode 100644 bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/virtualHeater.xml diff --git a/CODEOWNERS b/CODEOWNERS index 1f5619a95051f..adc1b1474d378 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -91,6 +91,7 @@ /bundles/org.openhab.binding.gree/ @markus7017 /bundles/org.openhab.binding.groheondus/ @FlorianSW /bundles/org.openhab.binding.harmonyhub/ @digitaldan +/bundles/org.openhab.binding.haywardomnilogic/ @matchews /bundles/org.openhab.binding.hdanywhere/ @kgoderis /bundles/org.openhab.binding.hdpowerview/ @beowulfe /bundles/org.openhab.binding.helios/ @kgoderis diff --git a/bom/openhab-addons/pom.xml b/bom/openhab-addons/pom.xml index b8219428eec77..d418a1638e82c 100644 --- a/bom/openhab-addons/pom.xml +++ b/bom/openhab-addons/pom.xml @@ -441,6 +441,11 @@ org.openhab.binding.harmonyhub ${project.version} + + org.openhab.addons.bundles + org.openhab.binding.haywardomnilogic + ${project.version} + org.openhab.addons.bundles org.openhab.binding.hdanywhere diff --git a/bundles/org.openhab.binding.haywardomnilogic/NOTICE b/bundles/org.openhab.binding.haywardomnilogic/NOTICE new file mode 100644 index 0000000000000..c5ec8e3e4864f --- /dev/null +++ b/bundles/org.openhab.binding.haywardomnilogic/NOTICE @@ -0,0 +1,14 @@ + +This content is produced and maintained by the openHAB project. + +* Project home: https://www.openhab.org + +== Declared Project Licenses + +This program and the accompanying materials are made available under the terms +of the Eclipse Public License 2.0 which is available at +https://www.eclipse.org/legal/epl-2.0/. + +== Source Code + +https://github.com/openhab/openhab-addons \ No newline at end of file diff --git a/bundles/org.openhab.binding.haywardomnilogic/README.md b/bundles/org.openhab.binding.haywardomnilogic/README.md new file mode 100644 index 0000000000000..0d7fa6dc3470b --- /dev/null +++ b/bundles/org.openhab.binding.haywardomnilogic/README.md @@ -0,0 +1,171 @@ +# Hayward Omnilogic Binding + +The Hayward Omnilogic binding integrates the Omnilogic pool controller using the Hayward API. + +The Hayward Omnilogic API interacts with Hayward's cloud server requiring a connection with the Internet for sending and receiving information. + +## Supported Things + +The table below lists the Hayward OmniLogic binding thing types: + +| Things | Description | Thing Type | +|------------------------------|---------------------------------------------------------------------------------|---------------| +| Hayward OmniLogix Connection | Connection to Hayward's Server | bridge | +| Backyard | Backyard | backyard | +| Body of Water | Body of Water | bow | +| Chlorinator | Chlorinator | chlorinator | +| Colorlogic Light | Colorlogic Light | colorlogic | +| Filter | Filter control | filter | +| Heater Equipment | Actual heater (i.e. gas, solar, electric) | heater | +| Pump | Auxillary pump control (i.e. spillover) | pump | +| Relay | Accessory relay control (deck jet sprinklers, lights, etc.) | relay | +| Virtaul Heater | A Virtual Heater that can control all of the heater equipment based on priority | virtualHeater | + +## Discovery + +The binding will automatically discover the Omnilogic pool things from the cloud server using your Hayward Omnilogic credentials. + +## Thing Configuration + +Hayward OmniLogic Connection Parameters: + +| Property | Default | Required | Description | +|----------------------|----------------------------------------------------------------|----------|----------------------------------------------| +| Host Name | https://app1.haywardomnilogic.com/HAAPI/HomeAutomation/API.ash | Yes | Host name of the Hayward API server | +| User Name | None | Yes | Your Hayward User Name (not email address) | +| Password | None | Yes | Your Hayward User Password | +| Telemetry Poll Delay | 12 | Yes | Telemetry Poll Delay (10-60 seconds) | +| Alarm Poll Delay | 60 | Yes | Alarm Poll Delay (0-120 seconds, 0 disabled) | + +## Channels + +### Backyard Channels + +| backyardAirTemp | Number:Temperature | Backyard air temp sensor reading | R | +|-----------------|--------------------|----------------------------------|:-:| +| backyardStatus | String | Backyard status | R | +| backyardState | String | Backyard state | R | +| backyardAlarm1 | String | Backyard alarm #1 | R | +| backyardAlarm2 | String | Backyard alarm #2 | R | +| backyardAlarm3 | String | Backyard alarm #3 | R | +| backyardAlarm4 | String | Backyard alarm #4 | R | +| backyardAlarm5 | String | Backyard alarm #5 | R | + +### Body of Water Channels + +| Channel Type ID | Item Type | Description | Read Write | +|-----------------|--------------------|------------------------------------|:----------:| +| bowFlow | Switch | Body of Water flow sensor feedback | R | +| bowWaterTemp | Number:Temperature | Body of Water temperature | R | + +### Chlorinator Channels + +| Channel Type ID | Item Type | Description | Read Write | +|-----------------------|----------------------|----------------------------------------------------------|:----------:| +| chlorEnable | Switch | Chlorinator enable | R/W | +| chlorOperatingMode | String | Chlorinator operating mode | R | +| chlorTimedPercent | Number:Dimensionless | Chlorinator timed percent | R/W | +| chlorOperatingState | Number | Chlorinator operating state | R | +| chlorScMode | String | Chlorinator super chlorinate mode | R | +| chlorError | Number | Chlorinator error | R | +| chlorAlert | String | Chlorinator alert | R | +| chlorAvgSaltLevel | Number:Dimensionless | Chlorinator average salt level in Part per Million (ppm) | R | +| chlorInstantSaltLevel | Number:Dimensionless | Chlorinator instant salt level in Part per Million (ppm) | R | +| chlorStatus | Number | Chlorinator K1/K2 relay status | R | + +### Colorlogic Light Channels + +| Channel Type ID | Item Type | Description | Read Write | +|----------------------------|-----------|-------------------------------|:----------:| +| colorLogicLightEnable | Switch | Colorlogic Light enable | R/W | +| colorLogicLightState | String | Colorlogic Light state | R | +| colorLogicLightCurrentShow | String | Colorlogic Light current show | R/W | + +### Filter Channels + +| Channel Type ID | Item Type | Description | Read Write | +|---------------------|----------------------|------------------------|:----------:| +| filterEnable | Switch | Filter enable | R/W | +| filterValvePosition | String | Filter valve position | R | +| filterSpeed | Number:Dimensionless | Filter speed in % | R/W | +| filterState | String | Filter state | R | +| filterLastSpeed | Number:Dimensionless | Filter last speed in % | R | + +### Heater Channels + +| Channel Type ID | Item Type | Description | Read Write | +|-----------------|-----------|---------------|:----------:| +| heaterState | Number | Heater state | R | +| heaterEnable | Switch | Heater enable | R | + +### Pump Channels + +| Channel Type ID | Item Type | Description | Read Write | +|-----------------|----------------------|-----------------|:----------:| +| pumpEnable | Switch | Pump enable | R | +| pumpSpeed | Number:Dimensionless | Pump speed in % | R | + +### Relay Channels + +| Channel Type ID | Item Type | Description | Read Write | +|-----------------|-----------|-------------|:----------:| +| relayState | Switch | Relay state | R/W | + +### Virtual Heater Channels + +| Channel Type ID | Item Type | Description | Read Write | +|-----------------------|--------------------|-------------------------|:----------:| +| heaterEnable | Number | Heater enable | R | +| heaterCurrentSetpoint | Number:Temperature | Heater Current Setpoint | R/W | + +## Full Example + +After installing the binding, you will need to manually add the Hayward Connection thing and enter your credentials. +All pool items can be autmatically discovered by scanning the bridge +Goto the inbox and add the things. + +### demo.items: + +```text +Group gPool "Pool" ["Location"] + +Group gHaywardChlorinator "Hayward Chlorinator" (gPool) ["Equipment"] +Switch HaywardChlorinator_Power "Power" (gHaywardChlorinator) ["Point"] { channel="haywardomnilogic:chlorinator:3766402f00:34:chlorEnable" } +String HaywardChlorinator_OperatingMode "Operating Mode" (gHaywardChlorinator) ["Point"] { channel="haywardomnilogic:chlorinator:3766402f00:34:chlorOperatingMode" } +Number:Dimensionless HaywardChlorinator_SaltOutput "Salt Output (%)" (gHaywardChlorinator) ["Point"] { channel="haywardomnilogic:chlorinator:3766402f00:34:chlorTimedPercent" } +String HaywardChlorinator_scMode "scMode" (gHaywardChlorinator) ["Point"] { channel="haywardomnilogic:chlorinator:3766402f00:34:chlorScMode" } +Number HaywardChlorinator_ChlorinatorError "Chlorinator Error" (gHaywardChlorinator) ["Point"] { channel="haywardomnilogic:chlorinator:3766402f00:34:chlorError" } +String HaywardChlorinator_ChlorinatorAlert "Chlorinator Alert" (gHaywardChlorinator) ["Point"] { channel="haywardomnilogic:chlorinator:3766402f00:34:chlorAlert" } +Number:Dimensionless HaywardChlorinator_AverageSaltLevel "Average Salt Level" (gHaywardChlorinator) ["Point"] { channel="haywardomnilogic:chlorinator:3766402f00:34:chlorAvgSaltLevel" } +Number:Dimensionless HaywardChlorinator_InstantSaltLevel "Instant Salt Level" (gHaywardChlorinator) ["Point"] { channel="haywardomnilogic:chlorinator:3766402f00:34:chlorInstantSaltLevel" } +Number HaywardChlorinator_Status "Status" (gHaywardChlorinator) ["Point"] { channel="haywardomnilogic:chlorinator:3766402f00:34:chlorStatus" } + + +Group gHaywardBackyard "Hayward Backyard" (gPool) ["Equipment"] +Number:Temperature HaywardBackyard_AirTemp "Air Temp" (gHaywardBackyard) ["Point"] { channel="haywardomnilogic:backyard:3766402f00:35940:backyardAirTemp" } +String HaywardBackyard_Status "Status" (gHaywardBackyard) ["Point"] { channel="haywardomnilogic:backyard:3766402f00:35940:backyardStatus" } +String HaywardBackyard_State "State" (gHaywardBackyard) ["Point"] { channel="haywardomnilogic:backyard:3766402f00:35940:backyardState" } +String HaywardBackyard_BackyardAlarm1 "Alarm" (gHaywardBackyard) ["Point"] { channel="haywardomnilogic:backyard:3766402f00:35940:backyardAlarm1" } +String HaywardBackyard_BackyardAlarm2 "Alarm" (gHaywardBackyard) ["Point"] { channel="haywardomnilogic:backyard:3766402f00:35940:backyardAlarm2" } +String HaywardBackyard_BackyardAlarm3 "Alarm" (gHaywardBackyard) ["Point"] { channel="haywardomnilogic:backyard:3766402f00:35940:backyardAlarm3" } +String HaywardBackyard_BackyardAlarm4 "Alarm" (gHaywardBackyard) ["Point"] { channel="haywardomnilogic:backyard:3766402f00:35940:backyardAlarm4" } +String HaywardBackyard_BackyardAlarm5 "Alarm" (gHaywardBackyard) ["Point"] { channel="haywardomnilogic:backyard:3766402f00:35940:backyardAlarm5" } + +Group gHaywardGas "Hayward Gas" (gPool) ["Equipment"] +Number HaywardGas_HeaterState "Heater State" (gHaywardGas) ["Point"] { channel="haywardomnilogic:heater:3766402f00:33:heaterState" } +Switch HaywardGas_HeaterEnable "Heater Enable" (gHaywardGas) ["Point"] { channel="haywardomnilogic:heater:3766402f00:33:heaterEnable" } + +Group gHaywardJets "Hayward Jets" (gPool) ["Equipment"] +Switch HaywardJets_Power "Power" (gHaywardJets) ["Point"] { channel="haywardomnilogic:relay:3766402f00:37:relayState" } + +Group gHaywardPool "Hayward Pool" (gPool) ["Equipment"] +Switch HaywardPool_FlowSensor "Flow Sensor" (gHaywardPool) ["Point"] { channel="haywardomnilogic:bow:3766402f00:30:bowFlow" } +Number:Temperature HaywardPool_WaterTemp "Water Temp" (gHaywardPool) ["Point"] { channel="haywardomnilogic:bow:3766402f00:30:bowWaterTemp" } + +Group gHaywardPoolLight "Hayward Pool Light" (gPool) ["Equipment"] +Switch HaywardPoolLight_Power "Power" (gHaywardPoolLight) ["Point"] { channel="haywardomnilogic:colorlogic:3766402f00:38:colorLogicLightEnable" } +String HaywardPoolLight_LightState "Light State" (gHaywardPoolLight) ["Point"] { channel="haywardomnilogic:colorlogic:3766402f00:38:colorLogicLightState" } +String HaywardPoolLight_CurrentShow "Current Show" (gHaywardPoolLight) ["Point"] { channel="haywardomnilogic:colorlogic:3766402f00:38:colorLogicLightCurrentShow" } + +``` + diff --git a/bundles/org.openhab.binding.haywardomnilogic/pom.xml b/bundles/org.openhab.binding.haywardomnilogic/pom.xml new file mode 100644 index 0000000000000..68bb5c0031187 --- /dev/null +++ b/bundles/org.openhab.binding.haywardomnilogic/pom.xml @@ -0,0 +1,17 @@ + + + + 4.0.0 + + + org.openhab.addons.bundles + org.openhab.addons.reactor.bundles + 3.1.0-SNAPSHOT + + + org.openhab.binding.haywardomnilogic + + openHAB Add-ons :: Bundles :: Hayward OmniLogic Binding + + diff --git a/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/HaywardAccount.java b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/HaywardAccount.java new file mode 100644 index 0000000000000..6b60270e8c6db --- /dev/null +++ b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/HaywardAccount.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2010-2021 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.haywardomnilogic.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link HaywardAccount} class contains fields mapping thing configuration parameters. + * + * @author Matt Myers - Initial contribution + */ + +@NonNullByDefault +public class HaywardAccount { + public String token = ""; + public String mspSystemID = ""; + public String userID = ""; + public String backyardName = ""; + public String address = ""; + public String firstName = ""; + public String lastName = ""; + public String roleType = ""; + public String units = ""; + public String vspSpeedFormat = ""; +} diff --git a/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/HaywardBindingConstants.java b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/HaywardBindingConstants.java new file mode 100644 index 0000000000000..2346547e93e39 --- /dev/null +++ b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/HaywardBindingConstants.java @@ -0,0 +1,134 @@ +/** + * Copyright (c) 2010-2021 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.haywardomnilogic.internal; + +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.core.thing.ThingTypeUID; + +/** + * The {@link HaywardBindingConstants} class defines common constants, which are + * used across the whole binding. + * + * @author Matt Myers - Initial contribution + */ +@NonNullByDefault +public class HaywardBindingConstants { + + private static final String BINDING_ID = "haywardomnilogic"; + + // List of all Thing Type UIDs + public static final ThingTypeUID THING_TYPE_BACKYARD = new ThingTypeUID(BINDING_ID, "backyard"); + public static final ThingTypeUID THING_TYPE_BOW = new ThingTypeUID(BINDING_ID, "bow"); + public static final ThingTypeUID THING_TYPE_BRIDGE = new ThingTypeUID(BINDING_ID, "bridge"); + public static final ThingTypeUID THING_TYPE_CHLORINATOR = new ThingTypeUID(BINDING_ID, "chlorinator"); + public static final ThingTypeUID THING_TYPE_COLORLOGIC = new ThingTypeUID(BINDING_ID, "colorlogic"); + public static final ThingTypeUID THING_TYPE_FILTER = new ThingTypeUID(BINDING_ID, "filter"); + public static final ThingTypeUID THING_TYPE_HEATER = new ThingTypeUID(BINDING_ID, "heater"); + public static final ThingTypeUID THING_TYPE_PUMP = new ThingTypeUID(BINDING_ID, "pump"); + public static final ThingTypeUID THING_TYPE_RELAY = new ThingTypeUID(BINDING_ID, "relay"); + public static final ThingTypeUID THING_TYPE_SENSOR = new ThingTypeUID(BINDING_ID, "sensor"); + public static final ThingTypeUID THING_TYPE_VIRTUALHEATER = new ThingTypeUID(BINDING_ID, "virtualHeater"); + + public static final Set BRIDGE_THING_TYPES_UIDS = Set.of(THING_TYPE_BRIDGE); + + public static final Set THING_TYPES_UIDS = Set.of(HaywardBindingConstants.THING_TYPE_BACKYARD, + HaywardBindingConstants.THING_TYPE_BOW, HaywardBindingConstants.THING_TYPE_BRIDGE, + HaywardBindingConstants.THING_TYPE_CHLORINATOR, HaywardBindingConstants.THING_TYPE_COLORLOGIC, + HaywardBindingConstants.THING_TYPE_FILTER, HaywardBindingConstants.THING_TYPE_HEATER, + HaywardBindingConstants.THING_TYPE_PUMP, HaywardBindingConstants.THING_TYPE_RELAY, + HaywardBindingConstants.THING_TYPE_SENSOR, HaywardBindingConstants.THING_TYPE_VIRTUALHEATER); + + // List of all Channel ids (bridge) + // No Channels + + // List of all Channel ids (backyard) + public static final String CHANNEL_BACKYARD_AIRTEMP = "backyardAirTemp"; + public static final String CHANNEL_BACKYARD_STATUS = "backyardStatus"; + public static final String CHANNEL_BACKYARD_STATE = "backyardState"; + + // List of all Channel ids (bow) + public static final String CHANNEL_BOW_WATERTEMP = "bowWaterTemp"; + public static final String CHANNEL_BOW_FLOW = "bowFlow"; + + // List of all Channel ids (chlorinator) + public static final String CHANNEL_CHLORINATOR_ENABLE = "chlorEnable"; + public static final String CHANNEL_CHLORINATOR_OPERATINGMODE = "chlorOperatingMode"; + public static final String CHANNEL_CHLORINATOR_TIMEDPERCENT = "chlorTimedPercent"; + public static final String CHANNEL_CHLORINATOR_SCMODE = "chlorScMode"; + public static final String CHANNEL_CHLORINATOR_ERROR = "chlorError"; + public static final String CHANNEL_CHLORINATOR_ALERT = "chlorAlert"; + public static final String CHANNEL_CHLORINATOR_AVGSALTLEVEL = "chlorAvgSaltLevel"; + public static final String CHANNEL_CHLORINATOR_INSTANTSALTLEVEL = "chlorInstantSaltLevel"; + public static final String CHANNEL_CHLORINATOR_STATUS = "chlorStatus"; + + // List of all Channel ids (colorlogic) + public static final String CHANNEL_COLORLOGIC_ENABLE = "colorLogicLightEnable"; + public static final String CHANNEL_COLORLOGIC_LIGHTSTATE = "colorLogicLightState"; + public static final String CHANNEL_COLORLOGIC_CURRENTSHOW = "colorLogicLightCurrentShow"; + + // List of all Channel ids (filter) + public static final String CHANNEL_FILTER_ENABLE = "filterEnable"; + public static final String CHANNEL_FILTER_VALVEPOSITION = "filterValvePosition"; + public static final String CHANNEL_FILTER_SPEED = "filterSpeed"; + public static final String CHANNEL_FILTER_STATE = "filterState"; + public static final String CHANNEL_FILTER_LASTSPEED = "filterLastSpeed"; + + public static final String PROPERTY_FILTER_MINPUMPSPEED = "Min Pump Percent"; + public static final String PROPERTY_FILTER_MAXPUMPSPEED = "Max Pump Percent"; + public static final String PROPERTY_FILTER_MINPUMPRPM = "Min Pump RPM"; + public static final String PROPERTY_FILTER_MAXPUMPRPM = "Max Pump RPM"; + + // List of all Channel ids (heater) + public static final String CHANNEL_HEATER_STATE = "heaterState"; + public static final String CHANNEL_HEATER_TEMP = "heaterTemp"; + public static final String CHANNEL_HEATER_ENABLE = "heaterEnable"; + + // List of all Channel ids (pump) + public static final String CHANNEL_PUMP_ENABLE = "pumpEnable"; + public static final String CHANNEL_PUMP_SPEED = "pumpSpeed"; + + public static final String PROPERTY_PUMP_MINPUMPSPEED = "Min Pump Speed"; + public static final String PROPERTY_PUMP_MAXPUMPSPEED = "Min Pump Speed"; + public static final String PROPERTY_PUMP_MINPUMPRPM = "Min Pump RPM"; + public static final String PROPERTY_PUMP_MAXPUMPRPM = "Max Pump RPM"; + + // List of all Channel ids (relay) + public static final String CHANNEL_RELAY_STATE = "relayState"; + + // List of all Channel ids (sensor) + public static final String CHANNEL_SENSOR_DATA = "sensorData"; + + // List of all Channel ids (virtualHeater) + public static final String CHANNEL_VIRTUALHEATER_CURRENTSETPOINT = "virtualHeaterCurrentSetpoint"; + public static final String CHANNEL_VIRTUALHEATER_ENABLE = "virtualHeaterEnable"; + + // The properties associated with all things + public static final String PROPERTY_SYSTEM_ID = "Property system ID"; + public static final String PROPERTY_TYPE = "propertyType"; + public static final String PROPERTY_BOWNAME = "BOW Name"; + public static final String PROPERTY_BOWID = "BOW ID"; + + // Hayward Command html + public static final String COMMAND_PARAMETERS = ""; + + public static final String COMMAND_SCHEDULE = "false" + + "0" + + "0" + + "0" + + "0" + + "0" + + "false"; +} diff --git a/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/HaywardException.java b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/HaywardException.java new file mode 100644 index 0000000000000..4553a4c22ac2a --- /dev/null +++ b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/HaywardException.java @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2010-2021 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.haywardomnilogic.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link HaywardException} is thrown during the getMspConfig, mspConfigDiscovery, getTelemetry, + * evaluateXPath and httpXmlResponse methods + * + * @author Matt Myers - Initial contribution + */ +@NonNullByDefault +public class HaywardException extends Exception { + + /** + * The {@link HaywardException} is thrown by getMspConfig() and mspConfigDiscovery() + * + */ + private static final long serialVersionUID = 1L; + + /** + * Constructor. + * + * @param message Hayward error message + */ + public HaywardException(String message) { + super(message); + } +} diff --git a/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/HaywardHandlerFactory.java b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/HaywardHandlerFactory.java new file mode 100644 index 0000000000000..cba37b0749df3 --- /dev/null +++ b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/HaywardHandlerFactory.java @@ -0,0 +1,110 @@ +/** + * Copyright (c) 2010-2021 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.haywardomnilogic.internal; + +import static org.openhab.binding.haywardomnilogic.internal.HaywardBindingConstants.*; + +import java.util.Collections; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jetty.client.HttpClient; +import org.openhab.binding.haywardomnilogic.internal.handler.HaywardBackyardHandler; +import org.openhab.binding.haywardomnilogic.internal.handler.HaywardBowHandler; +import org.openhab.binding.haywardomnilogic.internal.handler.HaywardBridgeHandler; +import org.openhab.binding.haywardomnilogic.internal.handler.HaywardChlorinatorHandler; +import org.openhab.binding.haywardomnilogic.internal.handler.HaywardColorLogicHandler; +import org.openhab.binding.haywardomnilogic.internal.handler.HaywardFilterHandler; +import org.openhab.binding.haywardomnilogic.internal.handler.HaywardHeaterHandler; +import org.openhab.binding.haywardomnilogic.internal.handler.HaywardRelayHandler; +import org.openhab.binding.haywardomnilogic.internal.handler.HaywardSensorHandler; +import org.openhab.binding.haywardomnilogic.internal.handler.HaywardVirtualHeaterHandler; +import org.openhab.core.io.net.http.HttpClientFactory; +import org.openhab.core.thing.Bridge; +import org.openhab.core.thing.Thing; +import org.openhab.core.thing.ThingTypeUID; +import org.openhab.core.thing.binding.BaseThingHandlerFactory; +import org.openhab.core.thing.binding.ThingHandler; +import org.openhab.core.thing.binding.ThingHandlerFactory; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; + +/** + * The {@link HaywardHandlerFactory} is responsible for creating things and thing + * handlers. + * + * @author Matt Myers - Initial contribution + */ + +@Component(service = ThingHandlerFactory.class, configurationPid = "binding.haywardomnilogic") +@NonNullByDefault +public class HaywardHandlerFactory extends BaseThingHandlerFactory { + + private static final Set SUPPORTED_THING_TYPES_UIDS = Collections.unmodifiableSet( + Stream.concat(BRIDGE_THING_TYPES_UIDS.stream(), THING_TYPES_UIDS.stream()).collect(Collectors.toSet())); + private final HttpClient httpClient; + + @Override + public boolean supportsThingType(ThingTypeUID thingTypeUID) { + return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); + } + + @Activate + public HaywardHandlerFactory(@Reference HttpClientFactory httpClientFactory) { + this.httpClient = httpClientFactory.getCommonHttpClient(); + } + + /** + * Creates the specific handler for this thing. + */ + @Override + protected @Nullable ThingHandler createHandler(Thing thing) { + ThingTypeUID thingTypeUID = thing.getThingTypeUID(); + + if (thingTypeUID.equals(HaywardBindingConstants.THING_TYPE_BRIDGE)) { + return new HaywardBridgeHandler((Bridge) thing, httpClient); + } + if (thingTypeUID.equals(HaywardBindingConstants.THING_TYPE_BACKYARD)) { + return new HaywardBackyardHandler(thing); + } + if (thingTypeUID.equals(HaywardBindingConstants.THING_TYPE_BOW)) { + return new HaywardBowHandler(thing); + } + if (thingTypeUID.equals(HaywardBindingConstants.THING_TYPE_CHLORINATOR)) { + return new HaywardChlorinatorHandler(thing); + } + if (thingTypeUID.equals(HaywardBindingConstants.THING_TYPE_COLORLOGIC)) { + return new HaywardColorLogicHandler(thing); + } + if (thingTypeUID.equals(HaywardBindingConstants.THING_TYPE_FILTER)) { + return new HaywardFilterHandler(thing); + } + if (thingTypeUID.equals(HaywardBindingConstants.THING_TYPE_HEATER)) { + return new HaywardHeaterHandler(thing); + } + if (thingTypeUID.equals(HaywardBindingConstants.THING_TYPE_RELAY)) { + return new HaywardRelayHandler(thing); + } + if (thingTypeUID.equals(HaywardBindingConstants.THING_TYPE_SENSOR)) { + return new HaywardSensorHandler(thing); + } + if (thingTypeUID.equals(HaywardBindingConstants.THING_TYPE_VIRTUALHEATER)) { + return new HaywardVirtualHeaterHandler(thing); + } + return null; + } +} diff --git a/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/HaywardThingHandler.java b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/HaywardThingHandler.java new file mode 100644 index 0000000000000..89f311fccffeb --- /dev/null +++ b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/HaywardThingHandler.java @@ -0,0 +1,121 @@ +/** + * Copyright (c) 2010-2021 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.haywardomnilogic.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.haywardomnilogic.internal.handler.HaywardBridgeHandler; +import org.openhab.core.library.types.DecimalType; +import org.openhab.core.library.types.OnOffType; +import org.openhab.core.library.types.QuantityType; +import org.openhab.core.library.types.StringType; +import org.openhab.core.library.unit.ImperialUnits; +import org.openhab.core.library.unit.SIUnits; +import org.openhab.core.library.unit.Units; +import org.openhab.core.thing.Bridge; +import org.openhab.core.thing.Channel; +import org.openhab.core.thing.ChannelUID; +import org.openhab.core.thing.Thing; +import org.openhab.core.thing.ThingStatus; +import org.openhab.core.thing.binding.BaseThingHandler; +import org.openhab.core.types.Command; +import org.openhab.core.types.State; + +/** + * The {@link HaywarThingHandler} is a subclass of the BaseThingHandler and a Super + * Class to each Hayward Thing Handler + * + * @author Matt Myers - Initial contribution + */ + +@NonNullByDefault +public abstract class HaywardThingHandler extends BaseThingHandler { + + public HaywardThingHandler(Thing thing) { + super(thing); + } + + @Override + public void initialize() { + updateStatus(ThingStatus.ONLINE); + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + } + + public abstract void getTelemetry(String xmlResponse) throws HaywardException; + + public State toState(String type, String channelID, String value) throws NumberFormatException { + switch (type) { + case "Number": + return new DecimalType(value); + case "Switch": + case "system.power": + return Integer.parseInt(value) > 0 ? OnOffType.ON : OnOffType.OFF; + case "Number:Dimensionless": + switch (channelID) { + case "chlorTimedPercent": + case "filterSpeed": + case "pumpSpeed": + case "filterLastSpeed": + return new QuantityType<>(Integer.parseInt(value), Units.PERCENT); + case "chlorAvgSaltLevel": + case "chlorInstantSaltLevel": + return new QuantityType<>(Integer.parseInt(value), Units.PARTS_PER_MILLION); + } + return StringType.valueOf(value); + case "Number:Temperature": + Bridge bridge = getBridge(); + if (bridge != null) { + HaywardBridgeHandler bridgehandler = (HaywardBridgeHandler) bridge.getHandler(); + if (bridgehandler != null) { + if (bridgehandler.account.units.equals("Standard")) { + return new QuantityType<>(Integer.parseInt(value), ImperialUnits.FAHRENHEIT); + } else { + return new QuantityType<>(Integer.parseInt(value), SIUnits.CELSIUS); + } + } + } + // default to imperial if no bridge + return new QuantityType<>(Integer.parseInt(value), ImperialUnits.FAHRENHEIT); + default: + return StringType.valueOf(value); + } + } + + public String cmdToString(Command command) { + if (command == OnOffType.OFF) { + return "0"; + } else if (command == OnOffType.ON) { + return "1"; + } else if (command instanceof DecimalType) { + return ((DecimalType) command).toString(); + } else if (command instanceof QuantityType) { + return ((QuantityType) command).format("%1.0f"); + } else { + return command.toString(); + } + } + + public void updateData(String channelID, String data) { + Channel chan = getThing().getChannel(channelID); + if (chan != null) { + String acceptedItemType = chan.getAcceptedItemType(); + if (acceptedItemType != null) { + State state = toState(acceptedItemType, channelID, data); + updateState(chan.getUID(), state); + } + } + } +} diff --git a/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/HaywardThingProperties.java b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/HaywardThingProperties.java new file mode 100644 index 0000000000000..06692f98bf43d --- /dev/null +++ b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/HaywardThingProperties.java @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2010-2021 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.haywardomnilogic.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link HaywardThingProperties} class contains fields mapping thing configuration parameters. + * + * @author Matt Myers - Initial contribution + */ + +@NonNullByDefault +public class HaywardThingProperties { + public String systemID = ""; + public String poolID = ""; +} diff --git a/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/HaywardTypeToRequest.java b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/HaywardTypeToRequest.java new file mode 100644 index 0000000000000..6eaff765e2472 --- /dev/null +++ b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/HaywardTypeToRequest.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2010-2021 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.haywardomnilogic.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The type to request. + * + * @author Matt Myers - Initial contribution + */ +@NonNullByDefault +public enum HaywardTypeToRequest { + BACKYARD, + BOW, + CHLORINATOR, + COLORLOGIC, + CSAD, + FILTER, + HEATER, + PUMP, + RELAY, + SENSOR, + VIRTUALHEATER +} diff --git a/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/config/HaywardConfig.java b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/config/HaywardConfig.java new file mode 100644 index 0000000000000..8b8a749018b06 --- /dev/null +++ b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/config/HaywardConfig.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2010-2021 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.haywardomnilogic.internal.config; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link HaywardConfig} class contains fields mapping thing configuration parameters. + * + * @author Matt Myers - Initial contribution + */ + +@NonNullByDefault +public class HaywardConfig { + public String endpointUrl = ""; + public String username = ""; + public String password = ""; + public int alarmPollTime = 60; + public int telemetryPollTime = 10; +} diff --git a/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/discovery/HaywardDiscoveryService.java b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/discovery/HaywardDiscoveryService.java new file mode 100644 index 0000000000000..93fe883f06b16 --- /dev/null +++ b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/discovery/HaywardDiscoveryService.java @@ -0,0 +1,230 @@ +/** + * Copyright (c) 2010-2021 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.haywardomnilogic.internal.discovery; + +import static org.openhab.binding.haywardomnilogic.internal.HaywardBindingConstants.THING_TYPES_UIDS; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.BiConsumer; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.haywardomnilogic.internal.HaywardBindingConstants; +import org.openhab.binding.haywardomnilogic.internal.HaywardException; +import org.openhab.binding.haywardomnilogic.internal.HaywardTypeToRequest; +import org.openhab.binding.haywardomnilogic.internal.handler.HaywardBridgeHandler; +import org.openhab.core.config.discovery.AbstractDiscoveryService; +import org.openhab.core.config.discovery.DiscoveryResult; +import org.openhab.core.config.discovery.DiscoveryResultBuilder; +import org.openhab.core.config.discovery.DiscoveryService; +import org.openhab.core.thing.ThingTypeUID; +import org.openhab.core.thing.ThingUID; +import org.openhab.core.thing.binding.ThingHandler; +import org.openhab.core.thing.binding.ThingHandlerService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Sets up the discovery results and details + * + * @author Matt Myers - Initial contribution + */ + +@NonNullByDefault +public class HaywardDiscoveryService extends AbstractDiscoveryService implements DiscoveryService, ThingHandlerService { + private final Logger logger = LoggerFactory.getLogger(HaywardDiscoveryService.class); + private @Nullable HaywardBridgeHandler discoveryBridgehandler; + + public HaywardDiscoveryService() { + super(THING_TYPES_UIDS, 0, false); + } + + @Override + public void activate() { + super.activate(null); + } + + @Override + public void deactivate() { + super.deactivate(); + } + + @Override + protected void startScan() { + HaywardBridgeHandler bridgehandler = discoveryBridgehandler; + try { + if (bridgehandler != null) { + String xmlResults = bridgehandler.getMspConfig(); + mspConfigDiscovery(xmlResults); + } + } catch (HaywardException e) { + logger.warn("Exception during discovery scan: {}", e.getMessage()); + } catch (InterruptedException e) { + return; + } + } + + public synchronized void mspConfigDiscovery(String xmlResponse) { + List systemIDs = new ArrayList<>(); + List names = new ArrayList<>(); + Map backyardProperties = new HashMap<>(); + Map bowProperties = new HashMap<>(); + HaywardBridgeHandler bridgehandler = discoveryBridgehandler; + + if (bridgehandler == null) { + return; + } + + // Find Backyard + names = bridgehandler.evaluateXPath("//Backyard/Name/text()", xmlResponse); + + for (int i = 0; i < names.size(); i++) { + backyardProperties.put(HaywardBindingConstants.PROPERTY_TYPE, HaywardTypeToRequest.BACKYARD); + backyardProperties.put(HaywardBindingConstants.PROPERTY_SYSTEM_ID, bridgehandler.account.mspSystemID); + + onDeviceDiscovered(HaywardBindingConstants.THING_TYPE_BACKYARD, names.get(i), backyardProperties); + } + + // Find Bodies of Water + systemIDs = bridgehandler.evaluateXPath("//Body-of-water/System-Id/text()", xmlResponse); + names = bridgehandler.evaluateXPath("//Body-of-water/Name/text()", xmlResponse); + + for (int i = 0; i < systemIDs.size(); i++) { + bowProperties.put(HaywardBindingConstants.PROPERTY_TYPE, HaywardTypeToRequest.BOW); + bowProperties.put(HaywardBindingConstants.PROPERTY_SYSTEM_ID, systemIDs.get(i)); + + onDeviceDiscovered(HaywardBindingConstants.THING_TYPE_BOW, names.get(i), bowProperties); + } + + // Find Chlorinators + discoverDevices(bridgehandler, xmlResponse, "Chlorinator", HaywardTypeToRequest.CHLORINATOR, + HaywardBindingConstants.THING_TYPE_CHLORINATOR, null); + + // Find ColorLogic Lights + discoverDevices(bridgehandler, xmlResponse, "ColorLogic-Light", HaywardTypeToRequest.COLORLOGIC, + HaywardBindingConstants.THING_TYPE_COLORLOGIC, null); + + // Find Filters + final List filterProperty1 = bridgehandler.evaluateXPath("//Filter/Min-Pump-Speed/text()", xmlResponse); + final List filterProperty2 = bridgehandler.evaluateXPath("//Filter/Max-Pump-Speed/text()", xmlResponse); + final List filterProperty3 = bridgehandler.evaluateXPath("//Filter/Min-Pump-RPM/text()", xmlResponse); + final List filterProperty4 = bridgehandler.evaluateXPath("//Filter/Max-Pump-RPM/text()", xmlResponse); + + discoverDevices(bridgehandler, xmlResponse, "Filter", HaywardTypeToRequest.FILTER, + HaywardBindingConstants.THING_TYPE_FILTER, (props, i) -> { + props.put(HaywardBindingConstants.PROPERTY_FILTER_MINPUMPSPEED, filterProperty1.get(i)); + props.put(HaywardBindingConstants.PROPERTY_FILTER_MAXPUMPSPEED, filterProperty2.get(i)); + props.put(HaywardBindingConstants.PROPERTY_FILTER_MINPUMPRPM, filterProperty3.get(i)); + props.put(HaywardBindingConstants.PROPERTY_FILTER_MAXPUMPRPM, filterProperty4.get(i)); + }); + + // Find Heaters + discoverDevices(bridgehandler, xmlResponse, "Heater-Equipment", HaywardTypeToRequest.HEATER, + HaywardBindingConstants.THING_TYPE_HEATER, null); + + // Find Pumps + final List pumpProperty1 = bridgehandler.evaluateXPath("//Pump/Min-Pump-Speed/text()", xmlResponse); + final List pumpProperty2 = bridgehandler.evaluateXPath("//Pump/Max-Pump-Speed/text()", xmlResponse); + final List pumpProperty3 = bridgehandler.evaluateXPath("//Pump/Min-Pump-RPM/text()", xmlResponse); + final List pumpProperty4 = bridgehandler.evaluateXPath("//Pump/Max-Pump-RPM/text()", xmlResponse); + + discoverDevices(bridgehandler, xmlResponse, "Pump", HaywardTypeToRequest.PUMP, + HaywardBindingConstants.THING_TYPE_FILTER, (props, i) -> { + props.put(HaywardBindingConstants.PROPERTY_FILTER_MINPUMPSPEED, pumpProperty1.get(i)); + props.put(HaywardBindingConstants.PROPERTY_FILTER_MAXPUMPSPEED, pumpProperty2.get(i)); + props.put(HaywardBindingConstants.PROPERTY_FILTER_MINPUMPRPM, pumpProperty3.get(i)); + props.put(HaywardBindingConstants.PROPERTY_FILTER_MAXPUMPRPM, pumpProperty4.get(i)); + }); + + // Find Relays + discoverDevices(bridgehandler, xmlResponse, "Relay", HaywardTypeToRequest.RELAY, + HaywardBindingConstants.THING_TYPE_RELAY, null); + + // Find Virtual Heaters + discoverDevices(bridgehandler, xmlResponse, "Heater", HaywardTypeToRequest.VIRTUALHEATER, + HaywardBindingConstants.THING_TYPE_VIRTUALHEATER, null); + + // Find Sensors + discoverDevices(bridgehandler, xmlResponse, "Sensor", HaywardTypeToRequest.SENSOR, + HaywardBindingConstants.THING_TYPE_SENSOR, null); + } + + private void discoverDevices(HaywardBridgeHandler bridgehandler, String xmlResponse, String xmlSearchTerm, + HaywardTypeToRequest type, ThingTypeUID thingType, + @Nullable BiConsumer, Integer> additionalPropertyConsumer) { + List systemIDs = bridgehandler.evaluateXPath("//" + xmlSearchTerm + "/System-Id/text()", xmlResponse); + List names; + + // Set Virtual Heater Name + if (thingType == HaywardBindingConstants.THING_TYPE_VIRTUALHEATER) { + names = new ArrayList<>(systemIDs); + Collections.fill(names, "Heater"); + } else { + names = bridgehandler.evaluateXPath("//" + xmlSearchTerm + "/Name/text()", xmlResponse); + } + + for (int i = 0; i < systemIDs.size(); i++) { + // get Body of Water for each item + List bowID = bridgehandler.evaluateXPath( + "//*[System-Id=" + systemIDs.get(i) + "]/ancestor::Body-of-water/System-Id/text()", xmlResponse); + List bowName = bridgehandler.evaluateXPath( + "//*[System-Id=" + systemIDs.get(i) + "]/ancestor::Body-of-water/Name/text()", xmlResponse); + + // skip system sensors with no BOW + if (bowID.isEmpty()) { + continue; + } + + Map properties = new HashMap<>(); + properties.put(HaywardBindingConstants.PROPERTY_TYPE, type); + properties.put(HaywardBindingConstants.PROPERTY_SYSTEM_ID, systemIDs.get(i)); + properties.put(HaywardBindingConstants.PROPERTY_BOWID, bowID.get(0)); + properties.put(HaywardBindingConstants.PROPERTY_BOWNAME, bowName.get(0)); + if (additionalPropertyConsumer != null) { + additionalPropertyConsumer.accept(properties, i); + } + onDeviceDiscovered(thingType, names.get(i), properties); + } + } + + public void onDeviceDiscovered(ThingTypeUID thingType, String label, Map properties) { + HaywardBridgeHandler bridgehandler = discoveryBridgehandler; + String systemID = (String) properties.get(HaywardBindingConstants.PROPERTY_SYSTEM_ID); + if (bridgehandler != null) { + if (systemID != null) { + ThingUID thingUID = new ThingUID(thingType, bridgehandler.getThing().getUID(), systemID); + DiscoveryResult result = DiscoveryResultBuilder.create(thingUID) + .withBridge(bridgehandler.getThing().getUID()) + .withRepresentationProperty(HaywardBindingConstants.PROPERTY_SYSTEM_ID) + .withLabel("Hayward " + label).withProperties(properties).build(); + thingDiscovered(result); + } + } + } + + @Override + public void setThingHandler(@Nullable ThingHandler handler) { + if (handler instanceof HaywardBridgeHandler) { + this.discoveryBridgehandler = (HaywardBridgeHandler) handler; + } + } + + @Override + public @Nullable ThingHandler getThingHandler() { + return discoveryBridgehandler; + } +} diff --git a/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardBackyardHandler.java b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardBackyardHandler.java new file mode 100644 index 0000000000000..0419770ea47be --- /dev/null +++ b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardBackyardHandler.java @@ -0,0 +1,135 @@ +/** + * Copyright (c) 2010-2021 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.haywardomnilogic.internal.handler; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.haywardomnilogic.internal.HaywardBindingConstants; +import org.openhab.binding.haywardomnilogic.internal.HaywardException; +import org.openhab.binding.haywardomnilogic.internal.HaywardThingHandler; +import org.openhab.core.thing.Bridge; +import org.openhab.core.thing.Thing; +import org.openhab.core.thing.ThingStatus; +import org.openhab.core.thing.ThingStatusDetail; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The Backyard Handler + * + * @author Matt Myers - Initial contribution + */ +@NonNullByDefault +public class HaywardBackyardHandler extends HaywardThingHandler { + private final Logger logger = LoggerFactory.getLogger(HaywardBackyardHandler.class); + + public HaywardBackyardHandler(Thing thing) { + super(thing); + } + + @Override + public void getTelemetry(String xmlResponse) throws HaywardException { + List data = new ArrayList<>(); + List systemIDs = new ArrayList<>(); + + Bridge bridge = getBridge(); + if (bridge != null) { + HaywardBridgeHandler bridgehandler = (HaywardBridgeHandler) bridge.getHandler(); + if (bridgehandler != null) { + systemIDs = bridgehandler.evaluateXPath("//Backyard/@systemId", xmlResponse); + String thingSystemID = getThing().getUID().getId(); + for (int i = 0; i < systemIDs.size(); i++) { + if (systemIDs.get(i).equals(thingSystemID)) { + // Air temp + data = bridgehandler.evaluateXPath("//Backyard/@airTemp", xmlResponse); + updateData(HaywardBindingConstants.CHANNEL_BACKYARD_AIRTEMP, data.get(0)); + + // Status + data = bridgehandler.evaluateXPath("//Backyard/@status", xmlResponse); + updateData(HaywardBindingConstants.CHANNEL_BACKYARD_STATUS, data.get(0)); + + // State + data = bridgehandler.evaluateXPath("//Backyard/@state", xmlResponse); + updateData(HaywardBindingConstants.CHANNEL_BACKYARD_STATE, data.get(0)); + } + } + this.updateStatus(ThingStatus.ONLINE); + } else { + this.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED); + } + } + } + + public boolean getAlarmList(String systemID) throws HaywardException { + List bowID = new ArrayList<>(); + List parameter1 = new ArrayList<>(); + List message = new ArrayList<>(); + String alarmStr; + + Bridge bridge = getBridge(); + if (bridge != null) { + HaywardBridgeHandler bridgehandler = (HaywardBridgeHandler) bridge.getHandler(); + if (bridgehandler != null) { + // *****Request Alarm List from Hayward server + String urlParameters = "GetAlarmList" + + "" + bridgehandler.account.token + + "" + "" + + bridgehandler.account.mspSystemID + "" + + "en-us"; + + try { + String xmlResponse = bridgehandler.httpXmlResponse(urlParameters); + + if (xmlResponse.isEmpty()) { + logger.debug("Hayward getAlarmList XML response was empty"); + return false; + } + + String status = bridgehandler + .evaluateXPath("/Response/Parameters//Parameter[@name='Status']/text()", xmlResponse) + .get(0); + + if (!(status.equals("0"))) { + logger.trace("Hayward getAlarm XML response: {}", xmlResponse); + return false; + } + + bowID = bridgehandler.evaluateXPath("//Property[@name='BowID']/text()", xmlResponse); + parameter1 = bridgehandler.evaluateXPath("//Property[@name='Parameter1']/text()", xmlResponse); + message = bridgehandler.evaluateXPath("//Property[@name='Message']/text()", xmlResponse); + + for (int i = 0; i < 5; i++) { + if (i < bowID.size()) { + alarmStr = parameter1.get(i) + ": " + message.get(i); + } else { + alarmStr = ""; + } + updateData("backyardAlarm" + String.format("%01d", i + 1), alarmStr); + } + this.updateStatus(ThingStatus.ONLINE); + return true; + } catch (InterruptedException e) { + return false; + } + } else { + this.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED); + return false; + } + } else { + this.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED); + return false; + } + } +} diff --git a/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardBowHandler.java b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardBowHandler.java new file mode 100644 index 0000000000000..117411776673f --- /dev/null +++ b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardBowHandler.java @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2010-2021 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.haywardomnilogic.internal.handler; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.haywardomnilogic.internal.HaywardBindingConstants; +import org.openhab.binding.haywardomnilogic.internal.HaywardException; +import org.openhab.binding.haywardomnilogic.internal.HaywardThingHandler; +import org.openhab.core.thing.Bridge; +import org.openhab.core.thing.Thing; +import org.openhab.core.thing.ThingStatus; +import org.openhab.core.thing.ThingStatusDetail; + +/** + * The Body of Water Handler + * + * @author Matt Myers - Initial contribution + */ +@NonNullByDefault +public class HaywardBowHandler extends HaywardThingHandler { + + public HaywardBowHandler(Thing thing) { + super(thing); + } + + @Override + public void getTelemetry(String xmlResponse) throws HaywardException { + List systemIDs = new ArrayList<>(); + List data = new ArrayList<>(); + + Bridge bridge = getBridge(); + if (bridge != null) { + HaywardBridgeHandler bridgehandler = (HaywardBridgeHandler) bridge.getHandler(); + if (bridgehandler != null) { + systemIDs = bridgehandler.evaluateXPath("//BodyOfWater/@systemId", xmlResponse); + + String thingSystemID = getThing().getUID().getId(); + for (int i = 0; i < systemIDs.size(); i++) { + if (systemIDs.get(i).equals(thingSystemID)) { + // Flow + data = bridgehandler.evaluateXPath("//BodyOfWater/@flow", xmlResponse); + updateData(HaywardBindingConstants.CHANNEL_BOW_FLOW, data.get(i)); + + // Water Temp + data = bridgehandler.evaluateXPath("//BodyOfWater/@waterTemp", xmlResponse); + updateData(HaywardBindingConstants.CHANNEL_BOW_WATERTEMP, data.get(i)); + } + } + this.updateStatus(ThingStatus.ONLINE); + } else { + this.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED); + } + } + } +} diff --git a/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardBridgeHandler.java b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardBridgeHandler.java new file mode 100644 index 0000000000000..ebaba9f9e3c79 --- /dev/null +++ b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardBridgeHandler.java @@ -0,0 +1,475 @@ +/** + * Copyright (c) 2010-2021 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.haywardomnilogic.internal.handler; + +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.api.ContentResponse; +import org.eclipse.jetty.client.api.Request; +import org.eclipse.jetty.client.util.StringContentProvider; +import org.eclipse.jetty.http.HttpHeader; +import org.eclipse.jetty.http.HttpMethod; +import org.eclipse.jetty.http.HttpVersion; +import org.openhab.binding.haywardomnilogic.internal.HaywardAccount; +import org.openhab.binding.haywardomnilogic.internal.HaywardBindingConstants; +import org.openhab.binding.haywardomnilogic.internal.HaywardException; +import org.openhab.binding.haywardomnilogic.internal.HaywardThingHandler; +import org.openhab.binding.haywardomnilogic.internal.HaywardTypeToRequest; +import org.openhab.binding.haywardomnilogic.internal.config.HaywardConfig; +import org.openhab.binding.haywardomnilogic.internal.discovery.HaywardDiscoveryService; +import org.openhab.core.library.types.OnOffType; +import org.openhab.core.thing.Bridge; +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.binding.BaseBridgeHandler; +import org.openhab.core.thing.binding.ThingHandlerService; +import org.openhab.core.types.Command; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; + +/** + * The {@link HaywardBridgeHandler} is responsible for handling commands, which are + * sent to one of the channels. + * + * @author Matt Myers - Initial contribution + */ + +@NonNullByDefault +public class HaywardBridgeHandler extends BaseBridgeHandler { + private final Logger logger = LoggerFactory.getLogger(HaywardBridgeHandler.class); + private final HttpClient httpClient; + private @Nullable ScheduledFuture initializeFuture; + private @Nullable ScheduledFuture pollTelemetryFuture; + private @Nullable ScheduledFuture pollAlarmsFuture; + private int commFailureCount; + public HaywardConfig config = getConfig().as(HaywardConfig.class); + public HaywardAccount account = getConfig().as(HaywardAccount.class); + + @Override + public Collection> getServices() { + return Collections.singleton(HaywardDiscoveryService.class); + } + + public HaywardBridgeHandler(Bridge bridge, HttpClient httpClient) { + super(bridge); + this.httpClient = httpClient; + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + } + + @Override + public void dispose() { + clearPolling(initializeFuture); + clearPolling(pollTelemetryFuture); + clearPolling(pollAlarmsFuture); + logger.trace("Hayward polling cancelled"); + super.dispose(); + } + + @Override + public void initialize() { + updateStatus(ThingStatus.UNKNOWN); + initializeFuture = scheduler.schedule(this::scheduledInitialize, 1, TimeUnit.SECONDS); + return; + } + + public void scheduledInitialize() { + config = getConfigAs(HaywardConfig.class); + + try { + clearPolling(pollTelemetryFuture); + clearPolling(pollAlarmsFuture); + + if (!(login())) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "Unable to Login to Hayward's server"); + clearPolling(pollTelemetryFuture); + clearPolling(pollAlarmsFuture); + commFailureCount = 50; + initPolling(60); + return; + } + + if (!(getSiteList())) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "Unable to getMSP from Hayward's server"); + clearPolling(pollTelemetryFuture); + clearPolling(pollAlarmsFuture); + commFailureCount = 50; + initPolling(60); + return; + } + + if (!(mspConfigUnits())) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "Unable to getMSPConfigUnits from Hayward's server"); + clearPolling(pollTelemetryFuture); + clearPolling(pollAlarmsFuture); + commFailureCount = 50; + initPolling(60); + return; + } + + updateStatus(ThingStatus.ONLINE); + logger.debug("Succesfully opened connection to Hayward's server: {} Username:{}", config.endpointUrl, + config.username); + + initPolling(0); + logger.trace("Hayward Telemetry polling scheduled"); + + if (config.alarmPollTime > 0) { + initAlarmPolling(1); + } + } catch (HaywardException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.HANDLER_INITIALIZING_ERROR, + "scheduledInitialize exception: " + e.getMessage()); + clearPolling(pollTelemetryFuture); + clearPolling(pollAlarmsFuture); + commFailureCount = 50; + initPolling(60); + return; + } catch (InterruptedException e) { + return; + } + } + + public synchronized boolean login() throws HaywardException, InterruptedException { + String xmlResponse; + String status; + + // *****Login to Hayward server + String urlParameters = "" + "Login" + + "" + config.username + "" + + "" + config.password + "" + + ""; + + xmlResponse = httpXmlResponse(urlParameters); + + if (xmlResponse.isEmpty()) { + return false; + } + + status = evaluateXPath("/Response/Parameters//Parameter[@name='Status']/text()", xmlResponse).get(0); + + if (!(status.equals("0"))) { + logger.debug("Hayward Connection thing: Login XML response: {}", xmlResponse); + return false; + } + + account.token = evaluateXPath("/Response/Parameters//Parameter[@name='Token']/text()", xmlResponse).get(0); + account.userID = evaluateXPath("/Response/Parameters//Parameter[@name='UserID']/text()", xmlResponse).get(0); + return true; + } + + public synchronized boolean getApiDef() throws HaywardException, InterruptedException { + String xmlResponse; + + // *****getConfig from Hayward server + String urlParameters = "GetAPIDef" + + "" + account.token + "" + + "" + account.mspSystemID + ";" + + "0.4\r\n" + + "en\r\n" + ""; + + xmlResponse = httpXmlResponse(urlParameters); + + if (xmlResponse.isEmpty()) { + logger.debug("Hayward Connection thing: Login XML response was null"); + return false; + } + return true; + } + + public synchronized boolean getSiteList() throws HaywardException, InterruptedException { + String xmlResponse; + String status; + + // *****Get MSP + String urlParameters = "GetSiteList" + + "" + account.token + + "" + account.userID + + ""; + + xmlResponse = httpXmlResponse(urlParameters); + + if (xmlResponse.isEmpty()) { + logger.debug("Hayward Connection thing: getSiteList XML response was null"); + return false; + } + + status = evaluateXPath("/Response/Parameters//Parameter[@name='Status']/text()", xmlResponse).get(0); + + if (!(status.equals("0"))) { + logger.debug("Hayward Connection thing: getSiteList XML response: {}", xmlResponse); + return false; + } + + account.mspSystemID = evaluateXPath("/Response/Parameters/Parameter/Item//Property[@name='MspSystemID']/text()", + xmlResponse).get(0); + account.backyardName = evaluateXPath( + "/Response/Parameters/Parameter/Item//Property[@name='BackyardName']/text()", xmlResponse).get(0); + account.address = evaluateXPath("/Response/Parameters/Parameter/Item//Property[@name='Address']/text()", + xmlResponse).get(0); + return true; + } + + public synchronized String getMspConfig() throws HaywardException, InterruptedException { + // *****getMspConfig from Hayward server + String urlParameters = "GetMspConfigFile" + + "" + account.token + "" + + "" + account.mspSystemID + + "0\r\n" + + ""; + + String xmlResponse = httpXmlResponse(urlParameters); + + // Debug: Inject xml file for testing + // String path = + // "C:/Users/Controls/openhab-2-5-x/git/openhab-addons/bundles/org.openhab.binding.haywardomnilogic/getConfig.xml"; + // xmlResponse = new String(Files.readAllBytes(Paths.get(path))); + + if (xmlResponse.isEmpty()) { + logger.debug("Hayward Connection thing: requestConfig XML response was null"); + return "Fail"; + } + + if (evaluateXPath("//Backyard/Name/text()", xmlResponse).isEmpty()) { + logger.debug("Hayward Connection thing: requestConfiguration XML response: {}", xmlResponse); + return "Fail"; + } + return xmlResponse; + } + + public synchronized boolean mspConfigUnits() throws HaywardException, InterruptedException { + List property1 = new ArrayList<>(); + List property2 = new ArrayList<>(); + + String xmlResponse = getMspConfig(); + + // Get Units (Standard, Metric) + property1 = evaluateXPath("//System/Units/text()", xmlResponse); + account.units = property1.get(0); + + // Get Variable Speed Pump Units (percent, RPM) + property2 = evaluateXPath("//System/Msp-Vsp-Speed-Format/text()", xmlResponse); + account.vspSpeedFormat = property2.get(0); + + return true; + } + + public synchronized boolean getTelemetryData() throws HaywardException, InterruptedException { + // *****getTelemetry from Hayward server + String urlParameters = "GetTelemetryData" + + "" + account.token + "" + + "" + account.mspSystemID + + ""; + + String xmlResponse = httpXmlResponse(urlParameters); + + if (xmlResponse.isEmpty()) { + logger.debug("Hayward Connection thing: getTelemetry XML response was null"); + return false; + } + + if (!evaluateXPath("/Response/Parameters//Parameter[@name='StatusMessage']/text()", xmlResponse).isEmpty()) { + logger.debug("Hayward Connection thing: getTelemetry XML response: {}", xmlResponse); + return false; + } + + for (Thing thing : getThing().getThings()) { + if (thing.getHandler() instanceof HaywardThingHandler) { + HaywardThingHandler handler = (HaywardThingHandler) thing.getHandler(); + if (handler != null) { + handler.getTelemetry(xmlResponse); + } + } + } + return true; + } + + public synchronized boolean getAlarmList() throws HaywardException { + for (Thing thing : getThing().getThings()) { + Map properties = thing.getProperties(); + if ("BACKYARD".equals(properties.get(HaywardBindingConstants.PROPERTY_TYPE))) { + HaywardBackyardHandler handler = (HaywardBackyardHandler) thing.getHandler(); + if (handler != null) { + String systemID = properties.get(HaywardBindingConstants.PROPERTY_SYSTEM_ID); + if (systemID != null) { + return handler.getAlarmList(systemID); + } + } + } + } + return false; + } + + private synchronized void initPolling(int initalDelay) { + pollTelemetryFuture = scheduler.scheduleWithFixedDelay(() -> { + try { + if (commFailureCount >= 5) { + commFailureCount = 0; + clearPolling(pollTelemetryFuture); + clearPolling(pollAlarmsFuture); + initialize(); + return; + } + if (!(getTelemetryData())) { + commFailureCount++; + return; + } + } catch (HaywardException e) { + logger.debug("Hayward Connection thing: Exception during poll: {}", e.getMessage()); + } catch (InterruptedException e) { + return; + } + }, initalDelay, config.telemetryPollTime, TimeUnit.SECONDS); + return; + } + + private synchronized void initAlarmPolling(int initalDelay) { + pollAlarmsFuture = scheduler.scheduleWithFixedDelay(() -> { + try { + getAlarmList(); + } catch (HaywardException e) { + logger.debug("Hayward Connection thing: Exception during poll: {}", e.getMessage()); + } + }, initalDelay, config.alarmPollTime, TimeUnit.SECONDS); + } + + private void clearPolling(@Nullable ScheduledFuture pollJob) { + if (pollJob != null) { + pollJob.cancel(false); + } + } + + @Nullable + Thing getThingForType(HaywardTypeToRequest type, int num) { + for (Thing thing : getThing().getThings()) { + Map properties = thing.getProperties(); + if (Integer.toString(num).equals(properties.get(HaywardBindingConstants.PROPERTY_SYSTEM_ID))) { + if (type.toString().equals(properties.get(HaywardBindingConstants.PROPERTY_TYPE))) { + return thing; + } + } + } + return null; + } + + public List evaluateXPath(String xpathExp, String xmlResponse) { + List values = new ArrayList<>(); + try { + InputSource inputXML = new InputSource(new StringReader(xmlResponse)); + XPath xPath = XPathFactory.newInstance().newXPath(); + NodeList nodes = (NodeList) xPath.evaluate(xpathExp, inputXML, XPathConstants.NODESET); + + for (int i = 0; i < nodes.getLength(); i++) { + values.add(nodes.item(i).getNodeValue()); + } + } catch (XPathExpressionException e) { + logger.warn("XPathExpression exception: {}", e.getMessage()); + } + return values; + } + + private Request sendRequestBuilder(String url, HttpMethod method) { + return this.httpClient.newRequest(url).agent("NextGenForIPhone/16565 CFNetwork/887 Darwin/17.0.0") + .method(method).header(HttpHeader.ACCEPT_LANGUAGE, "en-us").header(HttpHeader.ACCEPT, "*/*") + .header(HttpHeader.ACCEPT_ENCODING, "gzip, deflate").version(HttpVersion.HTTP_1_1) + .header(HttpHeader.CONNECTION, "keep-alive").header(HttpHeader.HOST, "www.haywardomnilogic.com:80") + .timeout(10, TimeUnit.SECONDS); + } + + public synchronized String httpXmlResponse(String urlParameters) throws HaywardException, InterruptedException { + String urlParameterslength = Integer.toString(urlParameters.length()); + String statusMessage; + + try { + ContentResponse httpResponse = sendRequestBuilder(config.endpointUrl, HttpMethod.POST) + .content(new StringContentProvider(urlParameters), "text/xml; charset=utf-8") + .header(HttpHeader.CONTENT_LENGTH, urlParameterslength).send(); + + int status = httpResponse.getStatus(); + String xmlResponse = httpResponse.getContentAsString(); + + List statusMessages = evaluateXPath("/Response/Parameters//Parameter[@name='StatusMessage']/text()", + xmlResponse); + if (!(statusMessages.isEmpty())) { + statusMessage = statusMessages.get(0); + } else { + statusMessage = httpResponse.getReason(); + } + + if (status == 200) { + if (logger.isTraceEnabled()) { + logger.trace("Hayward Connection thing: {} Hayward http command: {}", getCallingMethod(), + urlParameters); + logger.trace("Hayward Connection thing: {} Hayward http response: {} {}", getCallingMethod(), + statusMessage, xmlResponse); + } + return xmlResponse; + } else { + if (logger.isDebugEnabled()) { + logger.debug("Hayward Connection thing: {} Hayward http command: {}", getCallingMethod(), + urlParameters); + logger.debug("Hayward Connection thing: {} Hayward http response: {}", getCallingMethod(), status); + } + return ""; + } + } catch (ExecutionException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "Unable to resolve host. Check Hayward hostname and your internet connection. " + e); + return ""; + } catch (TimeoutException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "Connection Timeout. Check Hayward hostname and your internet connection. " + e); + return ""; + } + } + + private String getCallingMethod() { + StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace(); + StackTraceElement e = stacktrace[3]; + return e.getMethodName(); + } + + public int convertCommand(Command command) { + if (command == OnOffType.ON) { + return 1; + } else { + return 0; + } + } +} diff --git a/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardChlorinatorHandler.java b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardChlorinatorHandler.java new file mode 100644 index 0000000000000..0d1e12f7aa32e --- /dev/null +++ b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardChlorinatorHandler.java @@ -0,0 +1,187 @@ +/** + * Copyright (c) 2010-2021 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.haywardomnilogic.internal.handler; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.haywardomnilogic.internal.HaywardBindingConstants; +import org.openhab.binding.haywardomnilogic.internal.HaywardException; +import org.openhab.binding.haywardomnilogic.internal.HaywardThingHandler; +import org.openhab.core.thing.Bridge; +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.types.Command; +import org.openhab.core.types.RefreshType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The Chlorinator Handler + * + * @author Matt Myers - Initial contribution + */ +@NonNullByDefault +public class HaywardChlorinatorHandler extends HaywardThingHandler { + private final Logger logger = LoggerFactory.getLogger(HaywardChlorinatorHandler.class); + public String chlorTimedPercent = ""; + public String chlorState = ""; + + public HaywardChlorinatorHandler(Thing thing) { + super(thing); + } + + @Override + public void getTelemetry(String xmlResponse) throws HaywardException { + List systemIDs = new ArrayList<>(); + List data = new ArrayList<>(); + + Bridge bridge = getBridge(); + if (bridge != null) { + HaywardBridgeHandler bridgehandler = (HaywardBridgeHandler) bridge.getHandler(); + if (bridgehandler != null) { + systemIDs = bridgehandler.evaluateXPath("//Chlorinator/@systemId", xmlResponse); + String thingSystemID = getThing().getUID().getId(); + for (int i = 0; i < systemIDs.size(); i++) { + if (systemIDs.get(i).equals(thingSystemID)) { + // Operating Mode + data = bridgehandler.evaluateXPath("//Chlorinator/@operatingMode", xmlResponse); + updateData(HaywardBindingConstants.CHANNEL_CHLORINATOR_OPERATINGMODE, data.get(i)); + + // Timed Percent + data = bridgehandler.evaluateXPath("//Chlorinator/@Timed-Percent", xmlResponse); + updateData(HaywardBindingConstants.CHANNEL_CHLORINATOR_TIMEDPERCENT, data.get(i)); + this.chlorTimedPercent = data.get(0); + + // scMode + data = bridgehandler.evaluateXPath("//Chlorinator/@scMode", xmlResponse); + updateData(HaywardBindingConstants.CHANNEL_CHLORINATOR_SCMODE, data.get(i)); + + // Error + data = bridgehandler.evaluateXPath("//Chlorinator/@chlrError", xmlResponse); + updateData(HaywardBindingConstants.CHANNEL_CHLORINATOR_ERROR, data.get(i)); + + // Alert + data = bridgehandler.evaluateXPath("//Chlorinator/@chlrAlert", xmlResponse); + updateData(HaywardBindingConstants.CHANNEL_CHLORINATOR_ALERT, data.get(i)); + + // Average Salt Level + data = bridgehandler.evaluateXPath("//Chlorinator/@avgSaltLevel", xmlResponse); + updateData(HaywardBindingConstants.CHANNEL_CHLORINATOR_AVGSALTLEVEL, data.get(i)); + + // Instant Salt Level + data = bridgehandler.evaluateXPath("//Chlorinator/@instantSaltLevel", xmlResponse); + updateData(HaywardBindingConstants.CHANNEL_CHLORINATOR_INSTANTSALTLEVEL, data.get(i)); + + // Status + data = bridgehandler.evaluateXPath("//Chlorinator/@status", xmlResponse); + updateData(HaywardBindingConstants.CHANNEL_CHLORINATOR_STATUS, data.get(i)); + + if (data.get(i).equals("0")) { + updateData(HaywardBindingConstants.CHANNEL_CHLORINATOR_ENABLE, "0"); + // chlorState is used to set the chlorinator cfgState in the timedPercent command + this.chlorState = "2"; + } else { + updateData(HaywardBindingConstants.CHANNEL_CHLORINATOR_ENABLE, "1"); + // chlorState is used to set the chlorinator cfgState in the timedPercent command + this.chlorState = "3"; + } + } + } + this.updateStatus(ThingStatus.ONLINE); + } else { + this.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED); + } + } + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + if ((command instanceof RefreshType)) { + return; + } + + String chlorCfgState = null; + String chlorTimedPercent = "0"; + + String systemID = getThing().getProperties().get(HaywardBindingConstants.PROPERTY_SYSTEM_ID); + String poolID = getThing().getProperties().get(HaywardBindingConstants.PROPERTY_BOWID); + + Bridge bridge = getBridge(); + if (bridge != null) { + HaywardBridgeHandler bridgehandler = (HaywardBridgeHandler) bridge.getHandler(); + if (bridgehandler != null) { + String cmdString = this.cmdToString(command); + try { + switch (channelUID.getId()) { + case HaywardBindingConstants.CHANNEL_CHLORINATOR_ENABLE: + if (cmdString.equals("1")) { + chlorCfgState = "3"; + chlorTimedPercent = this.chlorTimedPercent; + } else { + chlorCfgState = "2"; + chlorTimedPercent = this.chlorTimedPercent; + } + break; + case HaywardBindingConstants.CHANNEL_CHLORINATOR_TIMEDPERCENT: + chlorCfgState = this.chlorState; + chlorTimedPercent = cmdString; + break; + default: + logger.warn("haywardCommand Unsupported type {}", channelUID); + return; + } + + String cmdURL = HaywardBindingConstants.COMMAND_PARAMETERS + + "SetCHLORParams" + + "" + bridgehandler.account.token + + "" + "" + + bridgehandler.account.mspSystemID + "" + + "" + poolID + "" + + "" + systemID + + "" + "" + + chlorCfgState + "" + + "1" + + "1" + + "4" + + "" + chlorTimedPercent + + "" + + "24" + + "24" + + ""; + + // *****Send Command to Hayward server + String xmlResponse = bridgehandler.httpXmlResponse(cmdURL); + String status = bridgehandler.evaluateXPath("//Parameter[@name='Status']/text()", xmlResponse) + .get(0); + + if (!(status.equals("0"))) { + logger.debug("haywardCommand XML response: {}", xmlResponse); + return; + } + } catch (HaywardException e) { + logger.debug("Unable to send command to Hayward's server {}:{}:{}", + bridgehandler.config.endpointUrl, bridgehandler.config.username, e.getMessage()); + } catch (InterruptedException e) { + return; + } + this.updateStatus(ThingStatus.ONLINE); + } else { + this.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED); + } + } + } +} diff --git a/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardColorLogicHandler.java b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardColorLogicHandler.java new file mode 100644 index 0000000000000..bb42b06eb97c1 --- /dev/null +++ b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardColorLogicHandler.java @@ -0,0 +1,154 @@ +/** + * Copyright (c) 2010-2021 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.haywardomnilogic.internal.handler; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.haywardomnilogic.internal.HaywardBindingConstants; +import org.openhab.binding.haywardomnilogic.internal.HaywardException; +import org.openhab.binding.haywardomnilogic.internal.HaywardThingHandler; +import org.openhab.core.library.types.OnOffType; +import org.openhab.core.thing.Bridge; +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.types.Command; +import org.openhab.core.types.RefreshType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The ColorLogic Handler + * + * @author Matt Myers - Initial contribution + */ +@NonNullByDefault +public class HaywardColorLogicHandler extends HaywardThingHandler { + private final Logger logger = LoggerFactory.getLogger(HaywardColorLogicHandler.class); + + public HaywardColorLogicHandler(Thing thing) { + super(thing); + } + + @Override + public void getTelemetry(String xmlResponse) throws HaywardException { + List systemIDs = new ArrayList<>(); + List data = new ArrayList<>(); + + Bridge bridge = getBridge(); + if (bridge != null) { + HaywardBridgeHandler bridgehandler = (HaywardBridgeHandler) bridge.getHandler(); + if (bridgehandler != null) { + systemIDs = bridgehandler.evaluateXPath("//ColorLogic-Light/@systemId", xmlResponse); + String thingSystemID = getThing().getUID().getId(); + for (int i = 0; i < systemIDs.size(); i++) { + if (systemIDs.get(i).equals(thingSystemID)) { + // Light State + data = bridgehandler.evaluateXPath("//ColorLogic-Light/@lightState", xmlResponse); + updateData(HaywardBindingConstants.CHANNEL_COLORLOGIC_LIGHTSTATE, data.get(i)); + + if (data.get(i).equals("0")) { + updateData(HaywardBindingConstants.CHANNEL_COLORLOGIC_ENABLE, "0"); + } else { + updateData(HaywardBindingConstants.CHANNEL_COLORLOGIC_ENABLE, "1"); + } + + // Current Show + data = bridgehandler.evaluateXPath("//ColorLogic-Light/@currentShow", xmlResponse); + updateData(HaywardBindingConstants.CHANNEL_COLORLOGIC_CURRENTSHOW, data.get(0)); + } + } + this.updateStatus(ThingStatus.ONLINE); + } else { + this.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED); + } + } + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + if ((command instanceof RefreshType)) { + return; + } + + String systemID = getThing().getProperties().get(HaywardBindingConstants.PROPERTY_SYSTEM_ID); + String poolID = getThing().getProperties().get(HaywardBindingConstants.PROPERTY_BOWID); + + Bridge bridge = getBridge(); + if (bridge != null) { + HaywardBridgeHandler bridgehandler = (HaywardBridgeHandler) bridge.getHandler(); + if (bridgehandler != null) { + String cmdString = this.cmdToString(command); + String cmdURL = null; + try { + switch (channelUID.getId()) { + case HaywardBindingConstants.CHANNEL_COLORLOGIC_ENABLE: + if (command == OnOffType.ON) { + cmdString = "1"; + } else { + cmdString = "0"; + } + cmdURL = HaywardBindingConstants.COMMAND_PARAMETERS + + "SetUIEquipmentCmd" + + "" + bridgehandler.account.token + + "" + "" + + bridgehandler.account.mspSystemID + "" + + "" + poolID + "" + + "" + systemID + "" + + "" + cmdString + "" + + HaywardBindingConstants.COMMAND_SCHEDULE + ""; + break; + case HaywardBindingConstants.CHANNEL_COLORLOGIC_CURRENTSHOW: + cmdURL = HaywardBindingConstants.COMMAND_PARAMETERS + + "SetStandAloneLightShow" + + "" + bridgehandler.account.token + + "" + "" + + bridgehandler.account.mspSystemID + "" + + "" + poolID + "" + + "" + systemID + "" + + "" + cmdString + "" + + "4" + + "4" + + "0" + + HaywardBindingConstants.COMMAND_SCHEDULE + ""; + break; + default: + logger.warn("haywardCommand Unsupported type {}", channelUID); + return; + } + + // *****Send Command to Hayward server + String xmlResponse = bridgehandler.httpXmlResponse(cmdURL); + String status = bridgehandler.evaluateXPath("//Parameter[@name='Status']/text()", xmlResponse) + .get(0); + + if (!(status.equals("0"))) { + logger.debug("haywardCommand XML response: {}", xmlResponse); + return; + } + } catch (HaywardException e) { + logger.debug("Unable to send command to Hayward's server {}:{}:{}", + bridgehandler.config.endpointUrl, bridgehandler.config.username, e.getMessage()); + } catch (InterruptedException e) { + return; + } + this.updateStatus(ThingStatus.ONLINE); + } else { + this.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED); + } + } + } +} diff --git a/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardFilterHandler.java b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardFilterHandler.java new file mode 100644 index 0000000000000..b39740cd8d38d --- /dev/null +++ b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardFilterHandler.java @@ -0,0 +1,159 @@ +/** + * Copyright (c) 2010-2021 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.haywardomnilogic.internal.handler; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.haywardomnilogic.internal.HaywardBindingConstants; +import org.openhab.binding.haywardomnilogic.internal.HaywardException; +import org.openhab.binding.haywardomnilogic.internal.HaywardThingHandler; +import org.openhab.core.library.types.OnOffType; +import org.openhab.core.thing.Bridge; +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.types.Command; +import org.openhab.core.types.RefreshType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The Filter Handler + * + * @author Matt Myers - Initial contribution + */ +@NonNullByDefault +public class HaywardFilterHandler extends HaywardThingHandler { + private final Logger logger = LoggerFactory.getLogger(HaywardFilterHandler.class); + + public HaywardFilterHandler(Thing thing) { + super(thing); + } + + @Override + public void initialize() { + updateStatus(ThingStatus.ONLINE); + } + + @Override + public void getTelemetry(String xmlResponse) throws HaywardException { + List systemIDs = new ArrayList<>(); + List data = new ArrayList<>(); + + Bridge bridge = getBridge(); + if (bridge != null) { + HaywardBridgeHandler bridgehandler = (HaywardBridgeHandler) bridge.getHandler(); + if (bridgehandler != null) { + systemIDs = bridgehandler.evaluateXPath("//Filter/@systemId", xmlResponse); + String thingSystemID = getThing().getUID().getId(); + for (int i = 0; i < systemIDs.size(); i++) { + if (systemIDs.get(i).equals(thingSystemID)) { + // Operating Mode + data = bridgehandler.evaluateXPath("//Chlorinator/@operatingMode", xmlResponse); + updateData(HaywardBindingConstants.CHANNEL_CHLORINATOR_OPERATINGMODE, data.get(i)); + + // Valve Position + data = bridgehandler.evaluateXPath("//Filter/@valvePosition", xmlResponse); + updateData(HaywardBindingConstants.CHANNEL_FILTER_VALVEPOSITION, data.get(i)); + + // Speed + data = bridgehandler.evaluateXPath("//Filter/@filterSpeed", xmlResponse); + updateData(HaywardBindingConstants.CHANNEL_FILTER_SPEED, data.get(i)); + + if (data.get(i).equals("0")) { + updateData(HaywardBindingConstants.CHANNEL_FILTER_ENABLE, "0"); + } else { + updateData(HaywardBindingConstants.CHANNEL_FILTER_ENABLE, "1"); + } + + // State + data = bridgehandler.evaluateXPath("//Filter/@filterState", xmlResponse); + updateData(HaywardBindingConstants.CHANNEL_FILTER_STATE, data.get(i)); + + // lastSpeed + data = bridgehandler.evaluateXPath("//Filter/@lastSpeed", xmlResponse); + updateData(HaywardBindingConstants.CHANNEL_FILTER_LASTSPEED, data.get(i)); + } + } + this.updateStatus(ThingStatus.ONLINE); + } else { + this.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED); + } + } + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + if ((command instanceof RefreshType)) { + return; + } + + String systemID = getThing().getProperties().get(HaywardBindingConstants.PROPERTY_SYSTEM_ID); + String poolID = getThing().getProperties().get(HaywardBindingConstants.PROPERTY_BOWID); + + Bridge bridge = getBridge(); + if (bridge != null) { + HaywardBridgeHandler bridgehandler = (HaywardBridgeHandler) bridge.getHandler(); + if (bridgehandler != null) { + String cmdString = this.cmdToString(command); + try { + switch (channelUID.getId()) { + case HaywardBindingConstants.CHANNEL_FILTER_ENABLE: + if (command == OnOffType.ON) { + cmdString = "100"; + } else { + cmdString = "0"; + } + break; + case HaywardBindingConstants.CHANNEL_FILTER_SPEED: + break; + default: + logger.warn("haywardCommand Unsupported type {}", channelUID); + return; + } + + String cmdURL = HaywardBindingConstants.COMMAND_PARAMETERS + + "SetUIEquipmentCmd" + + "" + bridgehandler.account.token + + "" + "" + + bridgehandler.account.mspSystemID + "" + + "" + poolID + "" + + "" + systemID + "" + + "" + cmdString + "" + + HaywardBindingConstants.COMMAND_SCHEDULE + ""; + + // *****Send Command to Hayward server + String xmlResponse = bridgehandler.httpXmlResponse(cmdURL); + String status = bridgehandler.evaluateXPath("//Parameter[@name='Status']/text()", xmlResponse) + .get(0); + + if (!(status.equals("0"))) { + logger.debug("haywardCommand XML response: {}", xmlResponse); + return; + } + } catch (HaywardException e) { + logger.debug("Unable to send command to Hayward's server {}:{}:{}", + bridgehandler.config.endpointUrl, bridgehandler.config.username, e.getMessage()); + } catch (InterruptedException e) { + return; + } + this.updateStatus(ThingStatus.ONLINE); + } else { + this.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED); + } + } + } +} diff --git a/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardHeaterHandler.java b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardHeaterHandler.java new file mode 100644 index 0000000000000..bf469f0fa92fc --- /dev/null +++ b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardHeaterHandler.java @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2010-2021 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.haywardomnilogic.internal.handler; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.haywardomnilogic.internal.HaywardBindingConstants; +import org.openhab.binding.haywardomnilogic.internal.HaywardException; +import org.openhab.binding.haywardomnilogic.internal.HaywardThingHandler; +import org.openhab.binding.haywardomnilogic.internal.config.HaywardConfig; +import org.openhab.core.thing.Bridge; +import org.openhab.core.thing.Thing; +import org.openhab.core.thing.ThingStatus; +import org.openhab.core.thing.ThingStatusDetail; + +/** + * The Heater Handler + * + * @author Matt Myers - Initial contribution + */ +@NonNullByDefault +public class HaywardHeaterHandler extends HaywardThingHandler { + + HaywardConfig config = getConfig().as(HaywardConfig.class); + + public HaywardHeaterHandler(Thing thing) { + super(thing); + } + + @Override + public void getTelemetry(String xmlResponse) throws HaywardException { + List systemIDs = new ArrayList<>(); + List data = new ArrayList<>(); + + Bridge bridge = getBridge(); + if (bridge != null) { + HaywardBridgeHandler bridgehandler = (HaywardBridgeHandler) bridge.getHandler(); + if (bridgehandler != null) { + systemIDs = bridgehandler.evaluateXPath("//Heater/@systemId", xmlResponse); + String thingSystemID = getThing().getUID().getId(); + for (int i = 0; i < systemIDs.size(); i++) { + if (systemIDs.get(i).equals(thingSystemID)) { + // State + data = bridgehandler.evaluateXPath("//Heater/@heaterState", xmlResponse); + updateData(HaywardBindingConstants.CHANNEL_HEATER_STATE, data.get(i)); + + // Enable + data = bridgehandler.evaluateXPath("//Heater/@enable", xmlResponse); + if (data.get(i).equals("0")) { + updateData(HaywardBindingConstants.CHANNEL_HEATER_ENABLE, "0"); + } else { + updateData(HaywardBindingConstants.CHANNEL_HEATER_ENABLE, "1"); + } + } + } + this.updateStatus(ThingStatus.ONLINE); + } else { + this.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED); + } + } + } +} diff --git a/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardRelayHandler.java b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardRelayHandler.java new file mode 100644 index 0000000000000..f890cd8e708c2 --- /dev/null +++ b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardRelayHandler.java @@ -0,0 +1,123 @@ +/** + * Copyright (c) 2010-2021 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.haywardomnilogic.internal.handler; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.haywardomnilogic.internal.HaywardBindingConstants; +import org.openhab.binding.haywardomnilogic.internal.HaywardException; +import org.openhab.binding.haywardomnilogic.internal.HaywardThingHandler; +import org.openhab.core.thing.Bridge; +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.types.Command; +import org.openhab.core.types.RefreshType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The Relay Handler + * + * @author Matt Myers - Initial contribution + */ +@NonNullByDefault +public class HaywardRelayHandler extends HaywardThingHandler { + private final Logger logger = LoggerFactory.getLogger(HaywardRelayHandler.class); + + public HaywardRelayHandler(Thing thing) { + super(thing); + } + + @Override + public void getTelemetry(String xmlResponse) throws HaywardException { + List systemIDs = new ArrayList<>(); + List data = new ArrayList<>(); + + Bridge bridge = getBridge(); + if (bridge != null) { + HaywardBridgeHandler bridgehandler = (HaywardBridgeHandler) bridge.getHandler(); + if (bridgehandler != null) { + systemIDs = bridgehandler.evaluateXPath("//Relay/@systemId", xmlResponse); + data = bridgehandler.evaluateXPath("//Relay/@relayState", xmlResponse); + String thingSystemID = getThing().getUID().getId(); + for (int i = 0; i < systemIDs.size(); i++) { + if (systemIDs.get(i).equals(thingSystemID)) { + updateData(HaywardBindingConstants.CHANNEL_RELAY_STATE, data.get(i)); + } + } + this.updateStatus(ThingStatus.ONLINE); + } else { + this.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED); + } + } + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + if ((command instanceof RefreshType)) { + return; + } + + String systemID = getThing().getProperties().get(HaywardBindingConstants.PROPERTY_SYSTEM_ID); + String poolID = getThing().getProperties().get(HaywardBindingConstants.PROPERTY_BOWID); + + Bridge bridge = getBridge(); + if (bridge != null) { + HaywardBridgeHandler bridgehandler = (HaywardBridgeHandler) bridge.getHandler(); + if (bridgehandler != null) { + String cmdString = this.cmdToString(command); + String cmdURL = null; + try { + switch (channelUID.getId()) { + case HaywardBindingConstants.CHANNEL_RELAY_STATE: + cmdURL = HaywardBindingConstants.COMMAND_PARAMETERS + + "SetUIEquipmentCmd" + + "" + bridgehandler.account.token + + "" + "" + + bridgehandler.account.mspSystemID + "" + + "" + poolID + "" + + "" + systemID + "" + + "" + cmdString + "" + + HaywardBindingConstants.COMMAND_SCHEDULE + ""; + break; + default: + logger.warn("haywardCommand Unsupported type {}", channelUID); + return; + } + + // *****Send Command to Hayward server + String xmlResponse = bridgehandler.httpXmlResponse(cmdURL); + String status = bridgehandler.evaluateXPath("//Parameter[@name='Status']/text()", xmlResponse) + .get(0); + + if (!(status.equals("0"))) { + logger.debug("haywardCommand XML response: {}", xmlResponse); + return; + } + } catch (HaywardException e) { + logger.debug("Unable to send command to Hayward's server {}:{}:{}", + bridgehandler.config.endpointUrl, bridgehandler.config.username, e.getMessage()); + } catch (InterruptedException e) { + return; + } + this.updateStatus(ThingStatus.ONLINE); + } else { + this.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED); + } + } + } +} diff --git a/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardSensorHandler.java b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardSensorHandler.java new file mode 100644 index 0000000000000..a811e69607995 --- /dev/null +++ b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardSensorHandler.java @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2010-2021 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.haywardomnilogic.internal.handler; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.haywardomnilogic.internal.HaywardBindingConstants; +import org.openhab.binding.haywardomnilogic.internal.HaywardException; +import org.openhab.binding.haywardomnilogic.internal.HaywardThingHandler; +import org.openhab.core.thing.Bridge; +import org.openhab.core.thing.Thing; +import org.openhab.core.thing.ThingStatus; +import org.openhab.core.thing.ThingStatusDetail; + +/** + * The Sensor Handler + * + * @author Matt Myers - Initial contribution + */ +@NonNullByDefault +public class HaywardSensorHandler extends HaywardThingHandler { + + public HaywardSensorHandler(Thing thing) { + super(thing); + } + + @Override + public void getTelemetry(String xmlResponse) throws HaywardException { + List systemIDs = new ArrayList<>(); + List data = new ArrayList<>(); + + Bridge bridge = getBridge(); + if (bridge != null) { + HaywardBridgeHandler bridgehandler = (HaywardBridgeHandler) bridge.getHandler(); + if (bridgehandler != null) { + systemIDs = bridgehandler.evaluateXPath("//Sensor/@systemId", xmlResponse); + data = bridgehandler.evaluateXPath("//Sensor/@relayState", xmlResponse); + String thingSystemID = getThing().getUID().getId(); + for (int i = 0; i < systemIDs.size(); i++) { + if (systemIDs.get(i).equals(thingSystemID)) { + updateData(HaywardBindingConstants.CHANNEL_RELAY_STATE, data.get(i)); + } + } + this.updateStatus(ThingStatus.ONLINE); + } else { + this.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED); + } + } + } +} diff --git a/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardVirtualHeaterHandler.java b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardVirtualHeaterHandler.java new file mode 100644 index 0000000000000..6ee8246a85628 --- /dev/null +++ b/bundles/org.openhab.binding.haywardomnilogic/src/main/java/org/openhab/binding/haywardomnilogic/internal/handler/HaywardVirtualHeaterHandler.java @@ -0,0 +1,150 @@ +/** + * Copyright (c) 2010-2021 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.haywardomnilogic.internal.handler; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.haywardomnilogic.internal.HaywardBindingConstants; +import org.openhab.binding.haywardomnilogic.internal.HaywardException; +import org.openhab.binding.haywardomnilogic.internal.HaywardThingHandler; +import org.openhab.core.library.types.OnOffType; +import org.openhab.core.thing.Bridge; +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.types.Command; +import org.openhab.core.types.RefreshType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The Virtual Heater Handler + * + * @author Matt Myers - Initial contribution + */ +@NonNullByDefault +public class HaywardVirtualHeaterHandler extends HaywardThingHandler { + private final Logger logger = LoggerFactory.getLogger(HaywardVirtualHeaterHandler.class); + + public HaywardVirtualHeaterHandler(Thing thing) { + super(thing); + } + + @Override + public void getTelemetry(String xmlResponse) throws HaywardException { + List systemIDs = new ArrayList<>(); + List data = new ArrayList<>(); + + Bridge bridge = getBridge(); + if (bridge != null) { + HaywardBridgeHandler bridgehandler = (HaywardBridgeHandler) bridge.getHandler(); + if (bridgehandler != null) { + systemIDs = bridgehandler.evaluateXPath("//VirtualHeater/@systemId", xmlResponse); + String thingSystemID = getThing().getUID().getId(); + for (int i = 0; i < systemIDs.size(); i++) { + if (systemIDs.get(i).equals(thingSystemID)) { + data = bridgehandler.evaluateXPath("//VirtualHeater/@Current-Set-Point", xmlResponse); + updateData(HaywardBindingConstants.CHANNEL_VIRTUALHEATER_CURRENTSETPOINT, data.get(i)); + + data = bridgehandler.evaluateXPath("//VirtualHeater/@enable", xmlResponse); + if (data.get(i).equals("yes")) { + updateData(HaywardBindingConstants.CHANNEL_VIRTUALHEATER_ENABLE, "1"); + } else if (data.get(i).equals("no")) { + updateData(HaywardBindingConstants.CHANNEL_VIRTUALHEATER_ENABLE, "0"); + } + } + } + this.updateStatus(ThingStatus.ONLINE); + } else { + this.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED); + } + } + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + if ((command instanceof RefreshType)) { + return; + } + + String systemID = getThing().getProperties().get(HaywardBindingConstants.PROPERTY_SYSTEM_ID); + String poolID = getThing().getProperties().get(HaywardBindingConstants.PROPERTY_BOWID); + + Bridge bridge = getBridge(); + if (bridge != null) { + HaywardBridgeHandler bridgehandler = (HaywardBridgeHandler) bridge.getHandler(); + if (bridgehandler != null) { + String cmdString = this.cmdToString(command); + String cmdURL = null; + + if (command == OnOffType.ON) { + cmdString = "True"; + } else if (command == OnOffType.OFF) { + cmdString = "False"; + } + + try { + switch (channelUID.getId()) { + case HaywardBindingConstants.CHANNEL_VIRTUALHEATER_ENABLE: + cmdURL = HaywardBindingConstants.COMMAND_PARAMETERS + + "SetHeaterEnable" + + "" + bridgehandler.account.token + + "" + "" + + bridgehandler.account.mspSystemID + "" + + "" + poolID + "" + + "" + systemID + "" + + "" + cmdString + "" + + ""; + break; + + case HaywardBindingConstants.CHANNEL_VIRTUALHEATER_CURRENTSETPOINT: + cmdURL = HaywardBindingConstants.COMMAND_PARAMETERS + + "SetUIHeaterCmd" + + "" + bridgehandler.account.token + + "" + "" + + bridgehandler.account.mspSystemID + "" + + "" + poolID + "" + + "" + systemID + "" + + "" + cmdString + "" + + ""; + break; + default: + logger.warn("haywardCommand Unsupported type {}", channelUID); + return; + } + + // *****Send Command to Hayward server + String xmlResponse = bridgehandler.httpXmlResponse(cmdURL); + String status = bridgehandler.evaluateXPath("//Parameter[@name='Status']/text()", xmlResponse) + .get(0); + + if (!(status.equals("0"))) { + logger.debug("haywardCommand XML response: {}", xmlResponse); + return; + } + } catch (HaywardException e) { + logger.debug("Unable to send command to Hayward's server {}:{}:{}", + bridgehandler.config.endpointUrl, bridgehandler.config.username, e.getMessage()); + } catch (InterruptedException e) { + return; + } + this.updateStatus(ThingStatus.ONLINE); + } else { + this.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED); + } + } + } +} diff --git a/bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/binding/binding.xml b/bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/binding/binding.xml new file mode 100644 index 0000000000000..2c6eab0bf76a9 --- /dev/null +++ b/bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/binding/binding.xml @@ -0,0 +1,9 @@ + + + + Hayward OmniLogix Binding + Binding for the Hayward OmniLogix swimming pool automation controller. + Matt Myers + diff --git a/bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/backyard.xml b/bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/backyard.xml new file mode 100644 index 0000000000000..c947bc3077633 --- /dev/null +++ b/bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/backyard.xml @@ -0,0 +1,76 @@ + + + + + + + + + + The Hayward Backyard + + + + + + + + + + + + + Hayward + + systemID + + + + + Number:Temperature + + Air Temp + + + + + String + + Status + + + + + + + + + + + + + String + + State + + + + + + + + + + + + + String + + Alarm + + + + diff --git a/bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/bow.xml b/bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/bow.xml new file mode 100644 index 0000000000000..aa594741bb4c3 --- /dev/null +++ b/bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/bow.xml @@ -0,0 +1,40 @@ + + + + + + + + + + The Hayward Body of Water + + + + + + + Hayward + + systemID + + + + + system.power + + Flow Sensor + + + + + Number:Temperature + + Water Temp + + + + diff --git a/bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/bridge.xml b/bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/bridge.xml new file mode 100644 index 0000000000000..1b5c8f9534bfd --- /dev/null +++ b/bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/bridge.xml @@ -0,0 +1,40 @@ + + + + + + + Connection to Hayward's Server + + + + url + + https://app1.haywardomnilogic.com/HAAPI/HomeAutomation/API.ashx + The URL of the Hayward API Server + + + + The username to connect to the server. + + + password + + The password to connect to the server. + + + + 12 + How often to request telemetry data from Hayward Server + + + + 60 + How often to request alarm data from Hayward Server. Enter 0 to disable. + + + + diff --git a/bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/chlorinator.xml b/bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/chlorinator.xml new file mode 100644 index 0000000000000..4b77e92ca29a3 --- /dev/null +++ b/bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/chlorinator.xml @@ -0,0 +1,103 @@ + + + + + + + + + + Chlorinator + + + + + + + + + + + + + + Hayward + + systemID + + + + + String + + Operating Mode + + + + + + + + + + + Number:Dimensionless + + Current salt output setting for the chlorinator (%). + + + + + String + + scMode + + + + + + + + + + Number + + + + + + String + + Chlorinator Alert + + + + + + + + + + Number:Dimensionless + + Average Salt Level + + + + + Number:Dimensionless + + Instant Salt Level + + + + + Number + + Status + + + diff --git a/bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/colorlogic.xml b/bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/colorlogic.xml new file mode 100644 index 0000000000000..25d882eb2445f --- /dev/null +++ b/bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/colorlogic.xml @@ -0,0 +1,67 @@ + + + + + + + + + + Color Logic Light + + + + + + + + Hayward + + systemID + + + + + String + + Light State + + + + + + + + + + + + String + + Current Show + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/filter.xml b/bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/filter.xml new file mode 100644 index 0000000000000..00529184bb7f9 --- /dev/null +++ b/bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/filter.xml @@ -0,0 +1,83 @@ + + + + + + + + + + Filter Equipment + + + + + + + + + + Hayward + + + + + + systemID + + + + + String + + Valve Position + + + + + + + + + + + + Number:Dimensionless + + Filter Speed in % + + + + + String + + Filter State + + + + + + + + + + + + + + + + + + + + Number:Dimensionless + + Last Speed + + + + diff --git a/bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/heater.xml b/bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/heater.xml new file mode 100644 index 0000000000000..960d9a9f72046 --- /dev/null +++ b/bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/heater.xml @@ -0,0 +1,39 @@ + + + + + + + + + + Heater + + + + + + + Hayward + + systemID + + + + Number + + Heater State + + + + + system.power + + Heater Enable + + + + diff --git a/bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/pump.xml b/bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/pump.xml new file mode 100644 index 0000000000000..16f1a094b6e20 --- /dev/null +++ b/bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/pump.xml @@ -0,0 +1,37 @@ + + + + + + + + + + Pump + + + + + + + Hayward + + + + + + systemID + + + + + Number:Dimensionless + + Pump Speed + + + + diff --git a/bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/relay.xml b/bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/relay.xml new file mode 100644 index 0000000000000..5c2b70e3b304a --- /dev/null +++ b/bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/relay.xml @@ -0,0 +1,25 @@ + + + + + + + + + + Relay + + + + + + Hayward + + systemID + + + + diff --git a/bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/sensor.xml b/bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/sensor.xml new file mode 100644 index 0000000000000..d33fc562a7064 --- /dev/null +++ b/bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/sensor.xml @@ -0,0 +1,39 @@ + + + + + + + + + + Sensor + + + + + + Hayward + + systemID + + + + + Number + + The Body of Water ID + + + + + Number + + Sensor Data + + + + diff --git a/bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/virtualHeater.xml b/bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/virtualHeater.xml new file mode 100644 index 0000000000000..89d7d410c17ed --- /dev/null +++ b/bundles/org.openhab.binding.haywardomnilogic/src/main/resources/OH-INF/thing/virtualHeater.xml @@ -0,0 +1,34 @@ + + + + + + + + + + Virtual Heater + + + + + + + + Hayward + + systemID + + + + Number:Temperature + + Current Setpoint + Temperature + + + + diff --git a/bundles/pom.xml b/bundles/pom.xml index 087005fe3c82d..13f4e56e17d3f 100644 --- a/bundles/pom.xml +++ b/bundles/pom.xml @@ -122,6 +122,7 @@ org.openhab.binding.gree org.openhab.binding.groheondus org.openhab.binding.harmonyhub + org.openhab.binding.haywardomnilogic org.openhab.binding.hdanywhere org.openhab.binding.hdpowerview org.openhab.binding.helios