[haywardomnilogic] Replacement for Hayward Omnilogic Pool Automation Binding (#8685)

* Initial Contribution

Signed-off-by: Matt Myers <mmyers75@icloud.com>
This commit is contained in:
Matt 2021-01-22 17:32:52 -05:00 committed by GitHub
parent 37bc57f856
commit ab290c5464
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 3150 additions and 0 deletions

View File

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

View File

@ -441,6 +441,11 @@
<artifactId>org.openhab.binding.harmonyhub</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.binding.haywardomnilogic</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.binding.hdanywhere</artifactId>

View File

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

View File

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

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.addons.reactor.bundles</artifactId>
<version>3.1.0-SNAPSHOT</version>
</parent>
<artifactId>org.openhab.binding.haywardomnilogic</artifactId>
<name>openHAB Add-ons :: Bundles :: Hayward OmniLogic Binding</name>
</project>

View File

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

View File

@ -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<ThingTypeUID> BRIDGE_THING_TYPES_UIDS = Set.of(THING_TYPE_BRIDGE);
public static final Set<ThingTypeUID> 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 = "<?xml version=\"1.0\" encoding=\"utf-8\"?><Request>";
public static final String COMMAND_SCHEDULE = "<Parameter name=\"IsCountDownTimer\" dataType=\"bool\">false</Parameter>"
+ "<Parameter name=\"StartTimeHours\" dataType=\"int\">0</Parameter>"
+ "<Parameter name=\"StartTimeMinutes\" dataType=\"int\">0</Parameter>"
+ "<Parameter name=\"EndTimeHours\" dataType=\"int\">0</Parameter>"
+ "<Parameter name=\"EndTimeMinutes\" dataType=\"int\">0</Parameter>"
+ "<Parameter name=\"DaysActive\" dataType=\"int\">0</Parameter>"
+ "<Parameter name=\"Recurring\" dataType=\"bool\">false</Parameter>";
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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<String> systemIDs = new ArrayList<>();
List<String> names = new ArrayList<>();
Map<String, Object> backyardProperties = new HashMap<>();
Map<String, Object> 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<String> filterProperty1 = bridgehandler.evaluateXPath("//Filter/Min-Pump-Speed/text()", xmlResponse);
final List<String> filterProperty2 = bridgehandler.evaluateXPath("//Filter/Max-Pump-Speed/text()", xmlResponse);
final List<String> filterProperty3 = bridgehandler.evaluateXPath("//Filter/Min-Pump-RPM/text()", xmlResponse);
final List<String> 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<String> pumpProperty1 = bridgehandler.evaluateXPath("//Pump/Min-Pump-Speed/text()", xmlResponse);
final List<String> pumpProperty2 = bridgehandler.evaluateXPath("//Pump/Max-Pump-Speed/text()", xmlResponse);
final List<String> pumpProperty3 = bridgehandler.evaluateXPath("//Pump/Min-Pump-RPM/text()", xmlResponse);
final List<String> 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<Map<String, Object>, Integer> additionalPropertyConsumer) {
List<String> systemIDs = bridgehandler.evaluateXPath("//" + xmlSearchTerm + "/System-Id/text()", xmlResponse);
List<String> 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<String> bowID = bridgehandler.evaluateXPath(
"//*[System-Id=" + systemIDs.get(i) + "]/ancestor::Body-of-water/System-Id/text()", xmlResponse);
List<String> 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<String, Object> 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<String, Object> 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;
}
}

View File

@ -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<String> data = new ArrayList<>();
List<String> 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<String> bowID = new ArrayList<>();
List<String> parameter1 = new ArrayList<>();
List<String> 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 = "<?xml version=\"1.0\" encoding=\"utf-8\"?><Request><Name>GetAlarmList</Name><Parameters>"
+ "<Parameter name=\"Token\" dataType=\"String\">" + bridgehandler.account.token
+ "</Parameter>" + "<Parameter name=\"MspSystemID\" dataType=\"int\">"
+ bridgehandler.account.mspSystemID + "</Parameter>"
+ "<Parameter name=\"CultureInfoName\" dataType=\"String\">en-us</Parameter></Parameters></Request>";
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;
}
}
}

View File

@ -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<String> systemIDs = new ArrayList<>();
List<String> 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);
}
}
}
}

View File

@ -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<Class<? extends ThingHandlerService>> 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 = "<?xml version=\"1.0\" encoding=\"utf-8\"?><Request>" + "<Name>Login</Name><Parameters>"
+ "<Parameter name=\"UserName\" dataType=\"String\">" + config.username + "</Parameter>"
+ "<Parameter name=\"Password\" dataType=\"String\">" + config.password + "</Parameter>"
+ "</Parameters></Request>";
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 = "<?xml version=\"1.0\" encoding=\"utf-8\"?><Request><Name>GetAPIDef</Name><Parameters>"
+ "<Parameter name=\"Token\" dataType=\"String\">" + account.token + "</Parameter>"
+ "<Parameter name=\"MspSystemID\" dataType=\"int\">" + account.mspSystemID + "</Parameter>;"
+ "<Parameter name=\"Version\" dataType=\"string\">0.4</Parameter >\r\n"
+ "<Parameter name=\"Language\" dataType=\"string\">en</Parameter >\r\n" + "</Parameters></Request>";
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 = "<?xml version=\"1.0\" encoding=\"utf-8\"?><Request><Name>GetSiteList</Name><Parameters>"
+ "<Parameter name=\"Token\" dataType=\"String\">" + account.token
+ "</Parameter><Parameter name=\"UserID\" dataType=\"String\">" + account.userID
+ "</Parameter></Parameters></Request>";
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 = "<?xml version=\"1.0\" encoding=\"utf-8\"?><Request><Name>GetMspConfigFile</Name><Parameters>"
+ "<Parameter name=\"Token\" dataType=\"String\">" + account.token + "</Parameter>"
+ "<Parameter name=\"MspSystemID\" dataType=\"int\">" + account.mspSystemID
+ "</Parameter><Parameter name=\"Version\" dataType=\"string\">0</Parameter>\r\n"
+ "</Parameters></Request>";
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<String> property1 = new ArrayList<>();
List<String> 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 = "<?xml version=\"1.0\" encoding=\"utf-8\"?><Request><Name>GetTelemetryData</Name><Parameters>"
+ "<Parameter name=\"Token\" dataType=\"String\">" + account.token + "</Parameter>"
+ "<Parameter name=\"MspSystemID\" dataType=\"int\">" + account.mspSystemID
+ "</Parameter></Parameters></Request>";
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<String, String> 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<String, String> 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<String> evaluateXPath(String xpathExp, String xmlResponse) {
List<String> 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<String> 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;
}
}
}

View File

@ -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<String> systemIDs = new ArrayList<>();
List<String> 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
+ "<Name>SetCHLORParams</Name><Parameters>"
+ "<Parameter name=\"Token\" dataType=\"String\">" + bridgehandler.account.token
+ "</Parameter>" + "<Parameter name=\"MspSystemID\" dataType=\"int\">"
+ bridgehandler.account.mspSystemID + "</Parameter>"
+ "<Parameter name=\"PoolID\" dataType=\"int\">" + poolID + "</Parameter>"
+ "<Parameter name=\"ChlorID\" dataType=\"int\" alias=\"EquipmentID\">" + systemID
+ "</Parameter>" + "<Parameter name=\"CfgState\" dataType=\"byte\" alias=\"Data1\">"
+ chlorCfgState + "</Parameter>"
+ "<Parameter name=\"OpMode\" dataType=\"byte\" alias=\"Data2\">1</Parameter>"
+ "<Parameter name=\"BOWType\" dataType=\"byte\" alias=\"Data3\">1</Parameter>"
+ "<Parameter name=\"CellType\" dataType=\"byte\" alias=\"Data4\">4</Parameter>"
+ "<Parameter name=\"TimedPercent\" dataType=\"byte\" alias=\"Data5\">" + chlorTimedPercent
+ "</Parameter>"
+ "<Parameter name=\"SCTimeout\" dataType=\"byte\" unit=\"hour\" alias=\"Data6\">24</Parameter>"
+ "<Parameter name=\"ORPTimout\" dataType=\"byte\" unit=\"hour\" alias=\"Data7\">24</Parameter>"
+ "</Parameters></Request>";
// *****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);
}
}
}
}

View File

@ -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<String> systemIDs = new ArrayList<>();
List<String> 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
+ "<Name>SetUIEquipmentCmd</Name><Parameters>"
+ "<Parameter name=\"Token\" dataType=\"String\">" + bridgehandler.account.token
+ "</Parameter>" + "<Parameter name=\"MspSystemID\" dataType=\"int\">"
+ bridgehandler.account.mspSystemID + "</Parameter>"
+ "<Parameter name=\"PoolID\" dataType=\"int\">" + poolID + "</Parameter>"
+ "<Parameter name=\"EquipmentID\" dataType=\"int\">" + systemID + "</Parameter>"
+ "<Parameter name=\"IsOn\" dataType=\"int\">" + cmdString + "</Parameter>"
+ HaywardBindingConstants.COMMAND_SCHEDULE + "</Parameters></Request>";
break;
case HaywardBindingConstants.CHANNEL_COLORLOGIC_CURRENTSHOW:
cmdURL = HaywardBindingConstants.COMMAND_PARAMETERS
+ "<Name>SetStandAloneLightShow</Name><Parameters>"
+ "<Parameter name=\"Token\" dataType=\"String\">" + bridgehandler.account.token
+ "</Parameter>" + "<Parameter name=\"MspSystemID\" dataType=\"int\">"
+ bridgehandler.account.mspSystemID + "</Parameter>"
+ "<Parameter name=\"PoolID\" dataType=\"int\">" + poolID + "</Parameter>"
+ "<Parameter name=\"LightID\" dataType=\"int\">" + systemID + "</Parameter>"
+ "<Parameter name=\"Show\" dataType=\"int\">" + cmdString + "</Parameter>"
+ "<Parameter name=\"Speed\" dataType=\"byte\">4</Parameter>"
+ "<Parameter name=\"Brightness\" dataType=\"byte\">4</Parameter>"
+ "<Parameter name=\"Reserved\" dataType=\"byte\">0</Parameter>"
+ HaywardBindingConstants.COMMAND_SCHEDULE + "</Parameters></Request>";
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);
}
}
}
}

View File

@ -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<String> systemIDs = new ArrayList<>();
List<String> 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
+ "<Name>SetUIEquipmentCmd</Name><Parameters>"
+ "<Parameter name=\"Token\" dataType=\"String\">" + bridgehandler.account.token
+ "</Parameter>" + "<Parameter name=\"MspSystemID\" dataType=\"int\">"
+ bridgehandler.account.mspSystemID + "</Parameter>"
+ "<Parameter name=\"PoolID\" dataType=\"int\">" + poolID + "</Parameter>"
+ "<Parameter name=\"EquipmentID\" dataType=\"int\">" + systemID + "</Parameter>"
+ "<Parameter name=\"IsOn\" dataType=\"int\">" + cmdString + "</Parameter>"
+ HaywardBindingConstants.COMMAND_SCHEDULE + "</Parameters></Request>";
// *****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);
}
}
}
}

View File

@ -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<String> systemIDs = new ArrayList<>();
List<String> 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);
}
}
}
}

View File

@ -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<String> systemIDs = new ArrayList<>();
List<String> 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
+ "<Name>SetUIEquipmentCmd</Name><Parameters>"
+ "<Parameter name=\"Token\" dataType=\"String\">" + bridgehandler.account.token
+ "</Parameter>" + "<Parameter name=\"MspSystemID\" dataType=\"int\">"
+ bridgehandler.account.mspSystemID + "</Parameter>"
+ "<Parameter name=\"PoolID\" dataType=\"int\">" + poolID + "</Parameter>"
+ "<Parameter name=\"EquipmentID\" dataType=\"int\">" + systemID + "</Parameter>"
+ "<Parameter name=\"IsOn\" dataType=\"int\">" + cmdString + "</Parameter>"
+ HaywardBindingConstants.COMMAND_SCHEDULE + "</Parameters></Request>";
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);
}
}
}
}

View File

@ -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<String> systemIDs = new ArrayList<>();
List<String> 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);
}
}
}
}

View File

@ -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<String> systemIDs = new ArrayList<>();
List<String> 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
+ "<Name>SetHeaterEnable</Name><Parameters>"
+ "<Parameter name=\"Token\" dataType=\"String\">" + bridgehandler.account.token
+ "</Parameter>" + "<Parameter name=\"MspSystemID\" dataType=\"int\">"
+ bridgehandler.account.mspSystemID + "</Parameter>"
+ "<Parameter name=\"PoolID\" dataType=\"int\">" + poolID + "</Parameter>"
+ "<Parameter name=\"HeaterID\" dataType=\"int\">" + systemID + "</Parameter>"
+ "<Parameter name=\"Enabled\" dataType=\"bool\">" + cmdString + "</Parameter>"
+ "</Parameters></Request>";
break;
case HaywardBindingConstants.CHANNEL_VIRTUALHEATER_CURRENTSETPOINT:
cmdURL = HaywardBindingConstants.COMMAND_PARAMETERS
+ "<Name>SetUIHeaterCmd</Name><Parameters>"
+ "<Parameter name=\"Token\" dataType=\"String\">" + bridgehandler.account.token
+ "</Parameter>" + "<Parameter name=\"MspSystemID\" dataType=\"int\">"
+ bridgehandler.account.mspSystemID + "</Parameter>"
+ "<Parameter name=\"PoolID\" dataType=\"int\">" + poolID + "</Parameter>"
+ "<Parameter name=\"HeaterID\" dataType=\"int\">" + systemID + "</Parameter>"
+ "<Parameter name=\"Temp\" dataType=\"int\">" + cmdString + "</Parameter>"
+ "</Parameters></Request>";
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);
}
}
}
}

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<binding:binding id="haywardomnilogic" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:binding="https://openhab.org/schemas/binding/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd">
<name>Hayward OmniLogix Binding</name>
<description>Binding for the Hayward OmniLogix swimming pool automation controller.</description>
<author>Matt Myers</author>
</binding:binding>

View File

@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="haywardomnilogic"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="backyard" listed="false">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
</supported-bridge-type-refs>
<label>Backyard</label>
<description>The Hayward Backyard</description>
<channels>
<channel id="backyardAirTemp" typeId="airTemp"/>
<channel id="backyardStatus" typeId="backyardstatus"/>
<channel id="backyardState" typeId="backyardstate"/>
<channel id="backyardAlarm1" typeId="alarm"/>
<channel id="backyardAlarm2" typeId="alarm"/>
<channel id="backyardAlarm3" typeId="alarm"/>
<channel id="backyardAlarm4" typeId="alarm"/>
<channel id="backyardAlarm5" typeId="alarm"/>
</channels>
<properties>
<property name="Vendor">Hayward</property>
</properties>
<representation-property>systemID</representation-property>
</thing-type>
<channel-type id="airTemp">
<item-type>Number:Temperature</item-type>
<label>Air Temp</label>
<description>Air Temp</description>
<state pattern="%1f %unit%" readOnly="true"/>
</channel-type>
<channel-type id="backyardstatus">
<item-type>String</item-type>
<label>Status</label>
<description>Status</description>
<state readOnly="true">
<options>
<option value="1">Normal</option>
<option value="2">Alarm</option>
<option value="3">Expired</option>
<option value="4">Lost Link</option>
<option value="5">Service Mode</option>
</options>
</state>
</channel-type>
<channel-type id="backyardstate">
<item-type>String</item-type>
<label>State</label>
<description>State</description>
<state readOnly="true">
<options>
<option value="0">Powered Off</option>
<option value="1">Normal</option>
<option value="2">Service Mode</option>
<option value="3">Config Mode</option>
<option value="4">Timed Service Mode</option>
</options>
</state>
</channel-type>
<channel-type id="alarm">
<item-type>String</item-type>
<label>Alarm</label>
<description>Alarm</description>
<state readOnly="true"/>
</channel-type>
</thing:thing-descriptions>

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="haywardomnilogic"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="bow" listed="false">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
</supported-bridge-type-refs>
<label>Body of Water</label>
<description>The Hayward Body of Water</description>
<channels>
<channel id="bowFlow" typeId="waterFlow"/>
<channel id="bowWaterTemp" typeId="waterTemp"/>
</channels>
<properties>
<property name="Vendor">Hayward</property>
</properties>
<representation-property>systemID</representation-property>
</thing-type>
<channel-type id="waterFlow">
<item-type>system.power</item-type>
<label>Flow Sensor</label>
<description>Flow Sensor</description>
<state readOnly="true"/>
</channel-type>
<channel-type id="waterTemp">
<item-type>Number:Temperature</item-type>
<label>Water Temp</label>
<description>Water Temp</description>
<state pattern="%1f %unit%" readOnly="true"/>
</channel-type>
</thing:thing-descriptions>

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="haywardomnilogic"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<!-- The bridge to communicate with Hayward's server -->
<bridge-type id="bridge">
<label>Hayward OmniLogix Connection</label>
<description>Connection to Hayward's Server</description>
<config-description>
<parameter name="endpointUrl" type="text" required="true">
<context>url</context>
<label>Endpoint URL</label>
<default>https://app1.haywardomnilogic.com/HAAPI/HomeAutomation/API.ashx</default>
<description>The URL of the Hayward API Server</description>
</parameter>
<parameter name="username" type="text" required="true">
<label>User Name</label>
<description>The username to connect to the server.</description>
</parameter>
<parameter name="password" type="text" required="true">
<context>password</context>
<label>Password</label>
<description>The password to connect to the server.</description>
</parameter>
<parameter name="telemetryPollTime" type="integer" min="10" max="60" unit="s" required="true">
<label>Telemetry Poll Delay</label>
<default>12</default>
<description>How often to request telemetry data from Hayward Server</description>
</parameter>
<parameter name="alarmPollTime" type="integer" min="0" max="120" unit="s" required="true">
<label>Alarm Poll Delay</label>
<default>60</default>
<description>How often to request alarm data from Hayward Server. Enter 0 to disable.</description>
</parameter>
</config-description>
</bridge-type>
</thing:thing-descriptions>

View File

@ -0,0 +1,103 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="haywardomnilogic"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="chlorinator" listed="false">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
</supported-bridge-type-refs>
<label>Chlorinator</label>
<description>Chlorinator</description>
<channels>
<channel id="chlorEnable" typeId="system.power"/>
<channel id="chlorOperatingMode" typeId="chlorOperatingMode"/>
<channel id="chlorTimedPercent" typeId="timedPercent"/>
<channel id="chlorScMode" typeId="scMode"/>
<channel id="chlorError" typeId="chlorError"/>
<channel id="chlorAlert" typeId="chlorAlert"/>
<channel id="chlorAvgSaltLevel" typeId="avgSaltLevel"/>
<channel id="chlorInstantSaltLevel" typeId="instantSaltLevel"/>
<channel id="chlorStatus" typeId="status"/>
</channels>
<properties>
<property name="Vendor">Hayward</property>
</properties>
<representation-property>systemID</representation-property>
</thing-type>
<channel-type id="chlorOperatingMode">
<item-type>String</item-type>
<label>Operating Mode</label>
<description>Operating Mode</description>
<state readOnly="true">
<options>
<option value="0">Off</option>
<option value="1">Timed Percent</option>
<option value="2">ORP Autosense</option>
</options>
</state>
</channel-type>
<channel-type id="timedPercent">
<item-type>Number:Dimensionless</item-type>
<label>Salt Output (%)</label>
<description>Current salt output setting for the chlorinator (%).</description>
<state min="0" max="100" step="1.0" pattern="%1f %unit%" readOnly="false"/>
</channel-type>
<channel-type id="scMode">
<item-type>String</item-type>
<label>scMode</label>
<description>scMode</description>
<state readOnly="true">
<options>
<option value="0">Off</option>
<option value="1">Super Chlorinating</option>
</options>
</state>
</channel-type>
<channel-type id="chlorError">
<item-type>Number</item-type>
<label>Chlorinator Error</label>
<state readOnly="true"/>
</channel-type>
<channel-type id="chlorAlert">
<item-type>String</item-type>
<label>Chlorinator Alert</label>
<description>Chlorinator Alert</description>
<state readOnly="true">
<options>
<option value="0">None</option>
<option value="16">Low T-Cell Temperature</option>
</options>
</state>
</channel-type>
<channel-type id="avgSaltLevel">
<item-type>Number:Dimensionless</item-type>
<label>Average Salt Level</label>
<description>Average Salt Level</description>
<state pattern="%1f %unit%" readOnly="true"/>
</channel-type>
<channel-type id="instantSaltLevel">
<item-type>Number:Dimensionless</item-type>
<label>Instant Salt Level</label>
<description>Instant Salt Level</description>
<state pattern="%1f %unit%" readOnly="true"/>
</channel-type>
<channel-type id="status">
<item-type>Number</item-type>
<label>Status</label>
<description>Status</description>
<state pattern="%1f" readOnly="true"/>
</channel-type>
</thing:thing-descriptions>

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="haywardomnilogic"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="colorlogic" listed="false">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
</supported-bridge-type-refs>
<label>Color Logic Light</label>
<description>Color Logic Light</description>
<channels>
<channel id="colorLogicLightEnable" typeId="system.power"/>
<channel id="colorLogicLightState" typeId="lightState"/>
<channel id="colorLogicLightCurrentShow" typeId="currentShow"/>
</channels>
<properties>
<property name="Vendor">Hayward</property>
</properties>
<representation-property>systemID</representation-property>
</thing-type>
<channel-type id="lightState">
<item-type>String</item-type>
<label>Light State</label>
<description>Light State</description>
<state readOnly="true">
<options>
<option value="0">Off</option>
<option value="1">On</option>
<option value="4">15 Sec White Light</option>
<option value="7">Powering Off</option>
</options>
</state>
</channel-type>
<channel-type id="currentShow">
<item-type>String</item-type>
<label>Current Show</label>
<description>Current Show</description>
<state readOnly="false">
<options>
<option value="0">Voodoo Lounge</option>
<option value="1">Deep Blue Sea</option>
<option value="2">Royal Blue</option>
<option value="3">Afternoon Sky</option>
<option value="4">Aqua Green</option>
<option value="5">Emerald</option>
<option value="6">Cloud White</option>
<option value="7">Warm Red</option>
<option value="8">Flamingo</option>
<option value="9">Vivid Violet</option>
<option value="10">Sangria</option>
<option value="11">Twilight</option>
<option value="12">Tranquility</option>
<option value="13">Gemstone</option>
<option value="14">USA</option>
<option value="15">Mardi Gras</option>
<option value="16">Cool Cabaret</option>
</options>
</state>
</channel-type>
</thing:thing-descriptions>

View File

@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="haywardomnilogic"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="filter" listed="false">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
</supported-bridge-type-refs>
<label>Filter</label>
<description>Filter Equipment</description>
<channels>
<channel id="filterEnable" typeId="system.power"/>
<channel id="filterValvePosition" typeId="valvePosition"/>
<channel id="filterSpeed" typeId="filterSpeed"/>
<channel id="filterState" typeId="filterState"/>
<channel id="filterLastSpeed" typeId="filterLastSpeed"/>
</channels>
<properties>
<property name="Vendor">Hayward</property>
<property name="Min Pump Percent"></property>
<property name="Max Pump Percent"></property>
<property name="Min Pump RPM"></property>
<property name="Max Pump RPM"></property>
</properties>
<representation-property>systemID</representation-property>
</thing-type>
<channel-type id="valvePosition">
<item-type>String</item-type>
<label>Valve Position</label>
<description>Valve Position</description>
<state readOnly="true">
<options>
<option value="0">Off</option>
<option value="1">Pool Only</option>
<option value="2">Spa Only</option>
<option value="3">Spill Over</option>
</options>
</state>
</channel-type>
<channel-type id="filterSpeed">
<item-type>Number:Dimensionless</item-type>
<label>Filter Speed</label>
<description>Filter Speed in %</description>
<state min="0" max="100" step="1.0" pattern="%1f %unit%" readOnly="false"/>
</channel-type>
<channel-type id="filterState">
<item-type>String</item-type>
<label>Filter State</label>
<description>Filter State</description>
<state readOnly="true">
<options>
<option value="0">Off</option>
<option value="1">Running</option>
<option value="2">Priming</option>
<option value="3">Waiting to Turn Off</option>
<option value="4">Waiting to Turn Off Manual</option>
<option value="5">Heater Extend</option>
<option value="6">Heater Cool Down</option>
<option value="7">Suspended</option>
<option value="8">CSAD Extend</option>
<option value="9">Filter Superchlorinate</option>
<option value="10">Filter Force Priming</option>
<option value="11">Filter Waiting for Pump to Turn Off</option>
</options>
</state>
</channel-type>
<channel-type id="filterLastSpeed">
<item-type>Number:Dimensionless</item-type>
<label>Last Speed</label>
<description>Last Speed</description>
<state pattern="%1f %unit%" readOnly="true"/>
</channel-type>
</thing:thing-descriptions>

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="haywardomnilogic"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="heater" listed="false">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
</supported-bridge-type-refs>
<label>Heater</label>
<description>Heater</description>
<channels>
<channel id="heaterState" typeId="state"/>
<channel id="heaterEnable" typeId="enable"/>
</channels>
<properties>
<property name="Vendor">Hayward</property>
</properties>
<representation-property>systemID</representation-property>
</thing-type>
<channel-type id="state">
<item-type>Number</item-type>
<label>Heater State</label>
<description>Heater State</description>
<state readOnly="true"/>
</channel-type>
<channel-type id="enable">
<item-type>system.power</item-type>
<label>Heater Enable</label>
<description>Heater Enable</description>
<state readOnly="true"/>
</channel-type>
</thing:thing-descriptions>

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="haywardomnilogic"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="pump" listed="false">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
</supported-bridge-type-refs>
<label>Pump</label>
<description>Pump</description>
<channels>
<channel id="pumpEnable" typeId="system.power"/>
<channel id="pumpSpeed" typeId="pumpSpeed"/>
</channels>
<properties>
<property name="Vendor">Hayward</property>
<property name="Min Pump Percent"></property>
<property name="Max Pump Percent"></property>
<property name="Min Pump RPM"></property>
<property name="Max Pump RPM"></property>
</properties>
<representation-property>systemID</representation-property>
</thing-type>
<channel-type id="pumpSpeed">
<item-type>Number:Dimensionless</item-type>
<label>Pump Speed in %</label>
<description>Pump Speed</description>
<state min="0" max="100" step="1.0" pattern="%1f %unit%" readOnly="false"/>
</channel-type>
</thing:thing-descriptions>

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="haywardomnilogic"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="relay" listed="false">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
</supported-bridge-type-refs>
<label>Relay</label>
<description>Relay</description>
<channels>
<channel id="relayState" typeId="system.power"/>
</channels>
<properties>
<property name="Vendor">Hayward</property>
</properties>
<representation-property>systemID</representation-property>
</thing-type>
</thing:thing-descriptions>

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="haywardomnilogic"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="sensor" listed="false">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
</supported-bridge-type-refs>
<label>Sensor</label>
<description>Sensor</description>
<channels>
<channel id="sensorData" typeId="data"/>
</channels>
<properties>
<property name="Vendor">Hayward</property>
</properties>
<representation-property>systemID</representation-property>
</thing-type>
<channel-type id="bow">
<item-type>Number</item-type>
<label>Body of Water</label>
<description>The Body of Water ID</description>
<state readOnly="true"/>
</channel-type>
<channel-type id="data">
<item-type>Number</item-type>
<label>Data</label>
<description>Sensor Data</description>
<state readOnly="true"/>
</channel-type>
</thing:thing-descriptions>

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="haywardomnilogic"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="virtualHeater" listed="false">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
</supported-bridge-type-refs>
<label>Virtual Heater</label>
<description>Virtual Heater</description>
<channels>
<channel id="virtualHeaterEnable" typeId="system.power"/>
<channel id="virtualHeaterCurrentSetpoint" typeId="currentSetpoint"/>
</channels>
<properties>
<property name="Vendor">Hayward</property>
</properties>
<representation-property>systemID</representation-property>
</thing-type>
<channel-type id="currentSetpoint">
<item-type>Number:Temperature</item-type>
<label>Current Setpoint</label>
<description>Current Setpoint</description>
<category>Temperature</category>
<state min="65" max="90" step="1.0" pattern="%1f %unit%" readOnly="false"/>
</channel-type>
</thing:thing-descriptions>

View File

@ -122,6 +122,7 @@
<module>org.openhab.binding.gree</module>
<module>org.openhab.binding.groheondus</module>
<module>org.openhab.binding.harmonyhub</module>
<module>org.openhab.binding.haywardomnilogic</module>
<module>org.openhab.binding.hdanywhere</module>
<module>org.openhab.binding.hdpowerview</module>
<module>org.openhab.binding.helios</module>