From 6fc24e4aa4491342cc0cc02761ae842c654f615f Mon Sep 17 00:00:00 2001 From: Matthew Skinner Date: Sun, 11 Jul 2021 17:40:29 +1000 Subject: [PATCH] [opensprinkler] Improvements: Remove apache.commons, fix bugs and warnings (#9869) * Fix: current channel would not get added. Signed-off-by: Matthew Skinner * Fix: online and offline now detect correctly. Signed-off-by: Matthew Skinner * Improve discovery. Signed-off-by: Matthew Skinner * Bug fixes. Signed-off-by: Matthew Skinner * Misc Improvements and log cleanup. Signed-off-by: Matthew Skinner * Make current sensor channel dynamically get removed if not supported. Signed-off-by: Matthew Skinner * fix compiler warning. Signed-off-by: Matthew Skinner * readme updates. Signed-off-by: Matthew Skinner * Shift refresh() Signed-off-by: Matthew Skinner * Add RSSI and water flow meter count channels. Signed-off-by: Matthew Skinner * Change to flowSensorCount Signed-off-by: Matthew Skinner * Fix bug Signed-off-by: Matthew Skinner * Fix NPE on parsing jsReplies. Signed-off-by: Matthew Skinner * Add new programs channel. Signed-off-by: Matthew Skinner * Fix wrong api use. Signed-off-by: Matthew Skinner * Change to using max time if the time is null. Signed-off-by: Matthew Skinner * Add device withRepresentationProperty Signed-off-by: Matthew Skinner * update readme Signed-off-by: Matthew Skinner * Fix rain sensor not working in 219 firmware. Signed-off-by: Matthew Skinner * Spotless fixes. Signed-off-by: Matthew Skinner * fix gson double up error. Signed-off-by: Matthew Skinner * Add more channels Signed-off-by: Matthew Skinner * refresh completed before bridge goes online. Signed-off-by: Matthew Skinner * Simplify. Signed-off-by: Matthew Skinner * Allow non default password to not stop discovery. Signed-off-by: Matthew Skinner * Add ignoresRain channel Signed-off-by: Matthew Skinner * Simplify commands in station handler. Signed-off-by: Matthew Skinner * Add new rainDelay channel. Signed-off-by: Matthew Skinner * Make constants consistent. Signed-off-by: Matthew Skinner * Add categories. Signed-off-by: Matthew Skinner * Changes requested by FlorianSW Signed-off-by: Matthew Skinner * Stop catching and throwing new exp. Signed-off-by: Matthew Skinner * Create a state class. Signed-off-by: Matthew Skinner * Update bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/discovery/OpenSprinklerDiscoveryService.java Signed-off-by: Matthew Skinner Co-authored-by: Connor Petty * Fix for EOF exception that stops polling with bad wifi. Signed-off-by: Matthew Skinner * Change signal strength over to 0-4 range Signed-off-by: Matthew Skinner * Handle toUnit null returns. Signed-off-by: Matthew Skinner * Support discovery on subnets that are not /24 Signed-off-by: Matthew Skinner * update readme for recent changes to signalStrength channel. Signed-off-by: Matthew Skinner * Fix code anal issue and readme. Signed-off-by: Matthew Skinner * Remove info logging. Signed-off-by: Matthew Skinner * remove traces of old dependancy. Signed-off-by: Matthew Skinner * Changes for fwolter Signed-off-by: Matthew Skinner * support RSSI and rssi Signed-off-by: Matthew Skinner * Update after new command sent. Signed-off-by: Matthew Skinner * improve delayedRefresh Signed-off-by: Matthew Skinner * Remove supressWarnings Signed-off-by: Matthew Skinner Co-authored-by: Connor Petty --- .../README.md | 67 ++-- .../org.openhab.binding.opensprinkler/pom.xml | 13 - .../src/main/feature/feature.xml | 2 - .../OpenSprinklerBindingConstants.java | 44 ++- .../internal/OpenSprinklerHandlerFactory.java | 12 +- .../internal/OpenSprinklerState.java | 73 ++++ ...OpenSprinklerStateDescriptionProvider.java | 37 ++ .../internal/api/OpenSprinklerApi.java | 154 +++++++- .../api/OpenSprinklerApiConstants.java | 50 --- .../internal/api/OpenSprinklerApiFactory.java | 20 +- .../api/OpenSprinklerHttpApiV100.java | 357 ++++++++++-------- .../api/OpenSprinklerHttpApiV210.java | 72 ++-- .../api/OpenSprinklerHttpApiV213.java | 16 +- .../api/OpenSprinklerHttpApiV217.java | 41 ++ .../api/OpenSprinklerHttpApiV219.java | 57 +++ .../exception/CommunicationApiException.java | 3 + .../DataFormatErrorApiException.java | 3 + .../exception/DataMissingApiException.java | 3 + .../api/exception/GeneralApiException.java | 3 + .../api/exception/MismatchApiException.java | 3 + .../exception/NotPermittedApiException.java | 3 + .../api/exception/OutOfRangeApiException.java | 3 + .../exception/PageNotFoundApiException.java | 3 + .../exception/UnauthorizedApiException.java | 3 + .../api/exception/UnknownApiException.java | 3 + .../OpenSprinklerHttpInterfaceConfig.java | 16 +- .../config/OpenSprinklerPiConfig.java | 6 +- .../config/OpenSprinklerStationConfig.java | 5 +- .../discovery/OpenSprinklerDiscoveryJob.java | 61 +-- .../OpenSprinklerDiscoveryService.java | 122 +++--- .../OpenSprinklerBaseBridgeHandler.java | 105 ------ .../handler/OpenSprinklerBaseHandler.java | 70 ++-- .../handler/OpenSprinklerDeviceHandler.java | 236 +++++++++--- .../OpenSprinklerHttpBridgeHandler.java | 138 +++++-- .../handler/OpenSprinklerStationHandler.java | 136 +++---- .../model/NoCurrentDrawSensorException.java | 22 -- .../internal/model/StationProgram.java | 3 + .../opensprinkler/internal/util/Hash.java | 6 +- .../opensprinkler/internal/util/Parse.java | 9 +- .../resources/OH-INF/thing/thing-types.xml | 100 ++++- 40 files changed, 1313 insertions(+), 767 deletions(-) create mode 100644 bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/OpenSprinklerState.java create mode 100644 bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/OpenSprinklerStateDescriptionProvider.java delete mode 100644 bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/api/OpenSprinklerApiConstants.java create mode 100644 bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/api/OpenSprinklerHttpApiV217.java create mode 100644 bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/api/OpenSprinklerHttpApiV219.java delete mode 100644 bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/handler/OpenSprinklerBaseBridgeHandler.java delete mode 100644 bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/model/NoCurrentDrawSensorException.java diff --git a/bundles/org.openhab.binding.opensprinkler/README.md b/bundles/org.openhab.binding.opensprinkler/README.md index 4d8ddf544..6ecd67925 100644 --- a/bundles/org.openhab.binding.opensprinkler/README.md +++ b/bundles/org.openhab.binding.opensprinkler/README.md @@ -1,31 +1,28 @@ # OpenSprinkler Binding -This binding allows allows basic control of the OpenSprinkler devices. -Stations can be controlled to be turned on or off and rain sensor state can be read. +This binding allows good and flexible control over your OpenSprinkler devices. +You can choose to manually start, stop or delay the stand alone watering programs that are stored and run fully from the OpenSprinkler device. +Alternatively you can setup openHAB rules to control everything in more depth by setting up multiple `station` things for each watering zone to gain more in depth control. +By using the internal programs and sensors of the OpenSprinkler device, it can remove the complexity of what happens to the watering if openHAB crashes, is rebooted, or drops out of WiFi range in the middle of your watering rules. +Mixing the two concepts can also be done, the choice is yours. ## Supported Bridges -* HTTP (`http`) - The http bridge allows to communicate with an OpenSprinkler device through the network +* `OpenSprinkler HTTP Bridge` is required to communicate with an OpenSprinkler device through the network and should be added first. ## Supported Things -* OpenSprinkler Station (`station`) - to control a single station of a device, e.g. to turn it on or off -* OpenSprinkler Device (`device`) - for getting device-specific infos, e.g. if rain was detected +* `OpenSprinkler Station` is for gaining advanced controls and status information over a single station (zone) of a device, e.g. to turn it on or off, or the time remaining. +* `OpenSprinkler Device` is for device-specific controls that usually apply to multiple stations or main unit sensors, e.g. if rain was detected. + +Recommend that you first add a single `device` thing and then if you need the extra controls, add as many of the `station` things as you wish. ## Discovery -OpenSprinkler devices can be manually discovered by sending a request to every IP on the network. -Discovery needs to be run manually as this is a brute force method of finding devices that can saturate network or device available bandwidth. +OpenSprinkler devices can be discovered by the binding sending requests to every IP on your network. +Due to this method used, it is very slow at finding devices and can saturate network bandwidth. -## Thing Configuration - -OpenSprinkler using the HTTP interface - -``` -Bridge opensprinkler:http:http [hostname="127.0.0.1", port=80, password="opendoor", refresh=60] { - Thing station 01 [stationIndex=1] -} -``` +## Bridge ('http') Configuration - hostname: Hostname or IP address of the OpenSprinkler HTTP API. - port: Port the OpenSprinkler device is listening on. Usually 80. @@ -36,42 +33,54 @@ Bridge opensprinkler:http:http [hostname="127.0.0.1", port=80, password="opendoo ### Station Thing Configuration -The `station` thing can be used with both bridge and has the following configuration properties: +The `station` thing must be used with a `http` bridge and has the following configuration properties: - stationIndex: The index of the station to communicate with, starting with 0 for the first station ## Channels -The following channel is supported by the `station` thing. +The following channels are supported by the `station` thing. | Channel Type ID | Item Type | | Description | |--------------------|-------------|----|----------------------------------------------------------| -| stationState | Switch | RW | This channel indicates whether station 01 is on or off. | +| stationState | Switch | RW | This channel indicates whether the station is on or off. | | remainingWaterTime | Number:Time | R | The time the station remains to be open. | -| nextDuration | Number:Time | RW | A configuration item, which time, if linked, will be | -| | | | used as the time the station will be kept open when | -| | | | switched on. It is advised to add persistence for items | -| | | | linked to this channel, the binding does not persist | -| | | | values of it. | +| nextDuration | Number:Time | RW | The amount of time that will be used to keep the station | +| | | | open when next manually switched on. If not set, this | +| | | | value will default to 18 hours which is the maximum time | +| | | | supported. | | queued | Switch | RW | Indicates that the station is queued to be turned on. | | | | | The channel cannot be turned on, only turning it off is | | | | | supported (which removes the station from the queue). | +| ignoreRain | Switch | RW | This channel makes the station ignore the rain delay. | When using the `nextDuration` channel, it is advised to setup persistence (e.g. MapDB) in order to persist the value through restarts. -The following is supported by the `device` thing, but only when connected using the http interface. +The following channels are supported by the `device` thing. +NOTE: Some channels will only show up if the hardware has the required sensor and is setup correctly. | Channel Type ID | Item Type | | Description | |-----------------|------------------------|----|------------------------------------------------------------------------------------| | rainsensor | Switch | RO | This channel indicates whether rain is detected by the device or not. | -| currentDraw | Number:ElectricCurrent | RO | Shows the current draw of the device. If the device does not have sensors | -| | | | for this metric, the channel will not be available. | +| sensor2 | Switch | RO | This channel is for the second sensor (if your hardware supports it). | +| currentDraw | Number:ElectricCurrent | RO | Shows the current draw of the device. | | waterlevel | Number:Dimensionless | RO | This channel shows the current water level in percent (0-250%). The water level is | | | | | calculated based on the weather and influences the duration of the water programs. | +| signalStrength | Number | RO | Shows how strong the WiFi Signal is. | +| flowSensorCount | Number:Dimensionless | RO | Shows the number of pulses the optional water flow sensor has reported. | +| programs | String | RW | Displays a list of the programs that are setup in your OpenSprinkler and when | +| | | | selected will start that program for you. | +| stations | String | RW | Display a list of stations that can be run when selected to the length of time set | +| | | | in the `nextDuration` channel. | +| nextDuration | Number:Time | RW | The time the station will open for when any stations are selected from the | +| | | | `stations` channel. Defaults to 30 minutes if not set. | +| resetStations | Switch | RW | The ON command will stop all stations immediately, including those waiting to run. | +| enablePrograms | Switch | RW | Allow programs to auto run. When OFF, manually started stations will still work. | +| rainDelay | Number:Time | RW | Sets/Shows the amount of time (hours) that rain has caused programs to be delayed. | -## Example +## Textual Example -demo.Things: +demo.things: ``` Bridge opensprinkler:http:http [hostname="127.0.0.1", port=81, password="opendoor"] { diff --git a/bundles/org.openhab.binding.opensprinkler/pom.xml b/bundles/org.openhab.binding.opensprinkler/pom.xml index c7f33ad68..486f74bdd 100644 --- a/bundles/org.openhab.binding.opensprinkler/pom.xml +++ b/bundles/org.openhab.binding.opensprinkler/pom.xml @@ -14,17 +14,4 @@ openHAB Add-ons :: Bundles :: OpenSprinkler Binding - - commons-net - - - - - commons-net - commons-net - ${commons.net.version} - compile - - - diff --git a/bundles/org.openhab.binding.opensprinkler/src/main/feature/feature.xml b/bundles/org.openhab.binding.opensprinkler/src/main/feature/feature.xml index 4a62ecf85..853e6eece 100644 --- a/bundles/org.openhab.binding.opensprinkler/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.opensprinkler/src/main/feature/feature.xml @@ -1,10 +1,8 @@ mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - openhab-runtime-base - openhab.tp-commons-net mvn:org.openhab.addons.bundles/org.openhab.binding.opensprinkler/${project.version} diff --git a/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/OpenSprinklerBindingConstants.java b/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/OpenSprinklerBindingConstants.java index 6cc890c5b..4a32278a7 100644 --- a/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/OpenSprinklerBindingConstants.java +++ b/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/OpenSprinklerBindingConstants.java @@ -12,6 +12,8 @@ */ package org.openhab.binding.opensprinkler.internal; +import java.math.BigDecimal; + import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.core.thing.ThingTypeUID; @@ -25,6 +27,32 @@ import org.openhab.core.thing.ThingTypeUID; @NonNullByDefault public class OpenSprinklerBindingConstants { public static final String BINDING_ID = "opensprinkler"; + public static final String DEFAULT_ADMIN_PASSWORD = "opendoor"; + public static final int DEFAULT_STATION_COUNT = 8; + public static final String HTTP_REQUEST_URL_PREFIX = "http://"; + public static final String HTTPS_REQUEST_URL_PREFIX = "https://"; + public static final String CMD_ENABLE_MANUAL_MODE = "mm=1"; + public static final String CMD_DISABLE_MANUAL_MODE = "mm=0"; + public static final String CMD_PASSWORD = "pw="; + public static final String CMD_STATION = "sid="; + public static final String CMD_STATION_ENABLE = "en=1"; + public static final String CMD_STATION_DISABLE = "en=0"; + public static final String CMD_STATUS_INFO = "jc"; + public static final String CMD_OPTIONS_INFO = "jo"; + public static final String CMD_STATION_INFO = "js"; + public static final String CMD_PROGRAM_DATA = "jp"; + public static final String CMD_STATION_CONTROL = "cm"; + public static final String JSON_OPTION_FIRMWARE_VERSION = "fwv"; + public static final String JSON_OPTION_RAINSENSOR = "rs"; + public static final String JSON_OPTION_STATION = "sn"; + public static final String JSON_OPTION_STATION_COUNT = "nstations"; + public static final String JSON_OPTION_RESULT = "result"; + public static final int DEFAULT_REFRESH_RATE = 60; + public static final int DISCOVERY_THREAD_POOL_SIZE = 15; + public static final boolean DISCOVERY_DEFAULT_AUTO_DISCOVER = false; + public static final int DISCOVERY_DEFAULT_TIMEOUT_RATE = 500; + public static final int DISCOVERY_DEFAULT_IP_TIMEOUT_RATE = 750; + public static final BigDecimal MAX_TIME_SECONDS = new BigDecimal(64800); // List of all Thing ids public static final String HTTP_BRIDGE = "http"; @@ -37,19 +65,21 @@ public class OpenSprinklerBindingConstants { public static final ThingTypeUID OPENSPRINKLER_STATION = new ThingTypeUID(BINDING_ID, STATION_THING); public static final ThingTypeUID OPENSPRINKLER_DEVICE = new ThingTypeUID(BINDING_ID, DEVICE_THING); - public static final int DEFAULT_WAIT_BEFORE_INITIAL_REFRESH = 30; - public static final int DEFAULT_REFRESH_RATE = 60; - public static final int DISCOVERY_THREAD_POOL_SIZE = 15; - public static final boolean DISCOVERY_DEFAULT_AUTO_DISCOVER = false; - public static final int DISCOVERY_DEFAULT_TIMEOUT_RATE = 500; - public static final int DISCOVERY_DEFAULT_IP_TIMEOUT_RATE = 750; - // List of all Channel ids + public static final String SENSOR_SIGNAL_STRENGTH = "signalStrength"; + public static final String SENSOR_FLOW_COUNT = "flowSensorCount"; public static final String SENSOR_RAIN = "rainsensor"; + public static final String SENSOR_2 = "sensor2"; public static final String SENSOR_WATERLEVEL = "waterlevel"; public static final String SENSOR_CURRENT_DRAW = "currentDraw"; + public static final String CHANNEL_PROGRAMS = "programs"; + public static final String CHANNEL_ENABLE_PROGRAMS = "enablePrograms"; + public static final String CHANNEL_STATIONS = "stations"; + public static final String CHANNEL_RESET_STATIONS = "resetStations"; public static final String STATION_STATE = "stationState"; public static final String STATION_QUEUED = "queued"; public static final String REMAINING_WATER_TIME = "remainingWaterTime"; public static final String NEXT_DURATION = "nextDuration"; + public static final String CHANNEL_IGNORE_RAIN = "ignoreRain"; + public static final String CHANNEL_RAIN_DELAY = "rainDelay"; } diff --git a/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/OpenSprinklerHandlerFactory.java b/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/OpenSprinklerHandlerFactory.java index 06dd806c3..9b1eb7b6a 100644 --- a/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/OpenSprinklerHandlerFactory.java +++ b/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/OpenSprinklerHandlerFactory.java @@ -18,6 +18,8 @@ import java.util.Arrays; import java.util.HashSet; import java.util.Set; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.opensprinkler.internal.api.OpenSprinklerApiFactory; import org.openhab.binding.opensprinkler.internal.handler.OpenSprinklerDeviceHandler; import org.openhab.binding.opensprinkler.internal.handler.OpenSprinklerHttpBridgeHandler; @@ -40,14 +42,18 @@ import org.osgi.service.component.annotations.Reference; * @author Florian Schmidt - Split channels to their own things */ @Component(service = ThingHandlerFactory.class, configurationPid = "binding.opensprinkler") +@NonNullByDefault public class OpenSprinklerHandlerFactory extends BaseThingHandlerFactory { private static final Set SUPPORTED_THING_TYPES_UIDS = new HashSet<>( Arrays.asList(OPENSPRINKLER_HTTP_BRIDGE, OPENSPRINKLER_STATION, OPENSPRINKLER_DEVICE)); + private final OpenSprinklerStateDescriptionProvider stateDescriptionProvider; private OpenSprinklerApiFactory apiFactory; @Activate - public OpenSprinklerHandlerFactory(@Reference OpenSprinklerApiFactory apiFactory) { + public OpenSprinklerHandlerFactory(@Reference OpenSprinklerApiFactory apiFactory, + final @Reference OpenSprinklerStateDescriptionProvider stateDescriptionProvider) { this.apiFactory = apiFactory; + this.stateDescriptionProvider = stateDescriptionProvider; } @Override @@ -56,7 +62,7 @@ public class OpenSprinklerHandlerFactory extends BaseThingHandlerFactory { } @Override - protected ThingHandler createHandler(Thing thing) { + protected @Nullable ThingHandler createHandler(Thing thing) { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); if (thingTypeUID.equals(OPENSPRINKLER_HTTP_BRIDGE)) { @@ -64,7 +70,7 @@ public class OpenSprinklerHandlerFactory extends BaseThingHandlerFactory { } else if (thingTypeUID.equals(OPENSPRINKLER_STATION)) { return new OpenSprinklerStationHandler(thing); } else if (thingTypeUID.equals(OPENSPRINKLER_DEVICE)) { - return new OpenSprinklerDeviceHandler(thing); + return new OpenSprinklerDeviceHandler(thing, stateDescriptionProvider); } return null; diff --git a/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/OpenSprinklerState.java b/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/OpenSprinklerState.java new file mode 100644 index 000000000..33e89c238 --- /dev/null +++ b/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/OpenSprinklerState.java @@ -0,0 +1,73 @@ +/** + * 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.opensprinkler.internal; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.core.types.StateOption; + +import com.google.gson.annotations.SerializedName; + +/** + * The {@link OpenSprinklerState} class holds the state and replies for an OpenSprinkler device. + * + * @author Matthew Skinner - Initial contribution + */ +@NonNullByDefault +public class OpenSprinklerState { + public JcResponse jcReply = new JcResponse(); + public JoResponse joReply = new JoResponse(); + public JsResponse jsReply = new JsResponse(); + public JpResponse jpReply = new JpResponse(); + public JnResponse jnReply = new JnResponse(); + public List programs = new ArrayList<>(); + public List stations = new ArrayList<>(); + + public static class JsResponse { + public int sn[] = new int[8]; + public int nstations = 8; + } + + public static class JpResponse { + public int nprogs = 0; + public Object[] pd = {}; + } + + public static class JoResponse { + public int wl; + public int fwv = -1; + } + + public static class JcResponse { + public @Nullable List> ps; + @SerializedName(value = "sn1", alternate = "rs") + public int rs; + public long devt = 0; + public long rdst = 0; + public int en = 1; + public int sn2 = -1; + @SerializedName(value = "RSSI", alternate = "rssi") // json reply uses all uppercase + public int rssi = 1; + public int flcrt = -1; + public int curr = -1; + } + + public static class JnResponse { + public List snames = new ArrayList<>(); + @SerializedName(value = "ignore_rain", alternate = "ignoreRain") + public byte[] ignoreRain = { 0 }; + } +} diff --git a/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/OpenSprinklerStateDescriptionProvider.java b/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/OpenSprinklerStateDescriptionProvider.java new file mode 100644 index 000000000..dd61584dc --- /dev/null +++ b/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/OpenSprinklerStateDescriptionProvider.java @@ -0,0 +1,37 @@ +/** + * 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.opensprinkler.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.core.thing.binding.BaseDynamicStateDescriptionProvider; +import org.openhab.core.thing.i18n.ChannelTypeI18nLocalizationService; +import org.openhab.core.thing.type.DynamicStateDescriptionProvider; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; + +/** + * The {@link OpenSprinklerStateDescriptionProvider} Allows the dynamic updating of Programs that can be run from an + * Opensprinkler Device + * + * @author Matthew Skinner - Initial contribution + */ +@Component(service = { DynamicStateDescriptionProvider.class, OpenSprinklerStateDescriptionProvider.class }) +@NonNullByDefault +public class OpenSprinklerStateDescriptionProvider extends BaseDynamicStateDescriptionProvider { + @Activate + public OpenSprinklerStateDescriptionProvider( + final @Reference ChannelTypeI18nLocalizationService channelTypeI18nLocalizationService) { + this.channelTypeI18nLocalizationService = channelTypeI18nLocalizationService; + } +} diff --git a/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/api/OpenSprinklerApi.java b/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/api/OpenSprinklerApi.java index 36a7a7aa7..5f365299b 100644 --- a/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/api/OpenSprinklerApi.java +++ b/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/api/OpenSprinklerApi.java @@ -13,19 +13,30 @@ package org.openhab.binding.opensprinkler.internal.api; import java.math.BigDecimal; +import java.util.List; +import javax.measure.quantity.Time; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.opensprinkler.internal.OpenSprinklerState.JnResponse; import org.openhab.binding.opensprinkler.internal.api.exception.CommunicationApiException; import org.openhab.binding.opensprinkler.internal.api.exception.GeneralApiException; -import org.openhab.binding.opensprinkler.internal.model.NoCurrentDrawSensorException; +import org.openhab.binding.opensprinkler.internal.api.exception.UnauthorizedApiException; import org.openhab.binding.opensprinkler.internal.model.StationProgram; +import org.openhab.core.library.types.QuantityType; +import org.openhab.core.types.Command; +import org.openhab.core.types.StateOption; /** * The {@link OpenSprinklerApi} interface defines the functions which are * controllable on the OpenSprinkler API interface. * * @author Chris Graham - Initial contribution + * @author Florian Schmidt - Refactoring */ +@NonNullByDefault public interface OpenSprinklerApi { + /** * Whether the device entered manual mode and accepts API requests to control the stations. * @@ -38,14 +49,14 @@ public interface OpenSprinklerApi { * * @throws Exception */ - public abstract void enterManualMode() throws CommunicationApiException; + public abstract void enterManualMode() throws CommunicationApiException, UnauthorizedApiException; /** * Disables the manual mode, if it is enabled. * * @throws Exception */ - public abstract void leaveManualMode() throws CommunicationApiException; + public abstract void leaveManualMode() throws CommunicationApiException, UnauthorizedApiException; /** * Starts a station on the OpenSprinkler device for the specified duration. @@ -72,7 +83,7 @@ public interface OpenSprinklerApi { * @return True if the station is open, false if it is closed or cannot determine. * @throws Exception */ - public abstract boolean isStationOpen(int station) throws GeneralApiException, CommunicationApiException; + public abstract boolean isStationOpen(int station) throws CommunicationApiException, GeneralApiException; /** * Returns the current program data of the requested station. @@ -89,34 +100,63 @@ public interface OpenSprinklerApi { * @return True if rain is detected, false if not or cannot determine. * @throws Exception */ - public abstract boolean isRainDetected() throws CommunicationApiException; + public abstract boolean isRainDetected(); /** * Returns the current draw of all connected zones of the OpenSprinkler device in milliamperes. * - * @return current draw in milliamperes - * @throws CommunicationApiException - * @throws + * @return current draw in milliamperes or -1 if sensor not supported */ - public abstract int currentDraw() throws CommunicationApiException, NoCurrentDrawSensorException; + public abstract int currentDraw(); + + /** + * Returns the state of the second sensor. + * + * @return 1: sensor is active; 0: sensor is inactive; -1: no sensor. + */ + public abstract int getSensor2State(); + + /** + * + * @return The Wifi signal strength in -dB or 0 if not supported by firmware + */ + public abstract int signalStrength(); + + /** + * + * @return The pulses that the flow sensor has given in the last time period, -1 if not supported. + */ + public abstract int flowSensorCount(); + + /** + * CLOSES all stations turning them all off. + * + */ + public abstract void resetStations() throws UnauthorizedApiException, CommunicationApiException; + + /** + * Returns true if the internal programs are allowed to auto start. + * + * @return true if enabled + */ + public abstract boolean getIsEnabled(); + + public abstract void enablePrograms(Command command) throws UnauthorizedApiException, CommunicationApiException; /** * Returns the water level in %. * * @return waterLevel in % - * @throws CommunicationApiException - * @throws */ - public abstract int waterLevel() throws CommunicationApiException; + public abstract int waterLevel(); /** * Returns the number of total stations that are controllable from the OpenSprinkler * device. * * @return Number of stations as an int. - * @throws Exception */ - public abstract int getNumberOfStations() throws Exception; + public abstract int getNumberOfStations(); /** * Returns the firmware version number. @@ -124,5 +164,89 @@ public interface OpenSprinklerApi { * @return The firmware version of the OpenSprinkler device as an int. * @throws Exception */ - public abstract int getFirmwareVersion() throws CommunicationApiException; + public abstract int getFirmwareVersion() throws CommunicationApiException, UnauthorizedApiException; + + /** + * Sends all the GET requests and stores/cache the responses for use by the API to prevent the need for multiple + * requests. + * + * @throws CommunicationApiException + * @throws UnauthorizedApiException + */ + public abstract void refresh() throws CommunicationApiException, UnauthorizedApiException; + + /** + * Ask the OpenSprinkler for the program names and store these for future use in a List. + * + * @throws CommunicationApiException + * @throws UnauthorizedApiException + */ + public abstract void getProgramData() throws CommunicationApiException, UnauthorizedApiException; + + /** + * Returns a list of all internal programs as a list of StateOptions. + * + * @return List + */ + public abstract List getPrograms(); + + /** + * Return a list of all the stations the device has as List of StateOptions + * + * @return List + */ + public abstract List getStations(); + + /** + * Runs a Program that is setup and stored inside the OpenSprinkler + * + * @param Program index number that you wish to run. + * + * @throws CommunicationApiException + * @throws UnauthorizedApiException + */ + public abstract void runProgram(Command command) throws CommunicationApiException, UnauthorizedApiException; + + /** + * Fetch the station names and place them in a list of List. + * Use getStations() to retrieve this list. + * + * @throws CommunicationApiException + * @throws UnauthorizedApiException + */ + public abstract JnResponse getStationNames() throws CommunicationApiException, UnauthorizedApiException; + + /** + * Tells a single station to ignore the rain delay. + * + * @param station + * @param command + * @throws CommunicationApiException + * @throws UnauthorizedApiException + */ + public void ignoreRain(int station, boolean command) throws CommunicationApiException, UnauthorizedApiException; + + /** + * Asks if a single station is set to ignore rain delays. + * + * @param station + * @return + */ + public abstract boolean isIgnoringRain(int station); + + /** + * Sets how long the OpenSprinkler device will stop running programs for. + * + * @param hours + * @throws UnauthorizedApiException + * @throws CommunicationApiException + */ + public abstract void setRainDelay(int hours) throws UnauthorizedApiException, CommunicationApiException; + + /** + * Gets the rain delay in hours from the OpenSprinkler device. + * + * @return QuantityType