Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[opensprinkler] Improvements: Remove apache.commons, fix bugs and warnings #9869

Merged
merged 47 commits into from
Jul 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
2507250
Fix: current channel would not get added.
Skinah Jan 15, 2021
b654680
Fix: online and offline now detect correctly.
Skinah Jan 16, 2021
c148107
Improve discovery.
Skinah Jan 16, 2021
8e371f3
Bug fixes.
Skinah Jan 17, 2021
660c58b
Misc Improvements and log cleanup.
Skinah Jan 18, 2021
f8d2c9d
Make current sensor channel dynamically get removed if not supported.
Skinah Jan 20, 2021
4aa3a3c
fix compiler warning.
Skinah Jan 20, 2021
a7ee3fe
readme updates.
Skinah Jan 21, 2021
a88b342
Shift refresh()
Skinah Jan 21, 2021
ec8594f
Add RSSI and water flow meter count channels.
Skinah Jan 23, 2021
51fdc83
Change to flowSensorCount
Skinah Jan 23, 2021
29d2d27
Fix bug
Skinah Jan 23, 2021
774aa10
Fix NPE on parsing jsReplies.
Skinah Jan 24, 2021
1de2b12
Add new programs channel.
Skinah Jan 25, 2021
ebf3911
Fix wrong api use.
Skinah Jan 25, 2021
ee229be
Change to using max time if the time is null.
Skinah Jan 25, 2021
3cbc19f
Add device withRepresentationProperty
Skinah Jan 25, 2021
6980aa9
update readme
Skinah Jan 26, 2021
3285857
Fix rain sensor not working in 219 firmware.
Skinah Jan 26, 2021
5c8bd34
Spotless fixes.
Skinah Jan 26, 2021
ec8aeef
fix gson double up error.
Skinah Jan 26, 2021
9791bb4
Add more channels
Skinah Jan 28, 2021
475159c
refresh completed before bridge goes online.
Skinah Jan 28, 2021
406b094
Simplify.
Skinah Jan 29, 2021
f36588f
Allow non default password to not stop discovery.
Skinah Jan 29, 2021
385d6ba
Add ignoresRain channel
Skinah Jan 30, 2021
78ed10a
Simplify commands in station handler.
Skinah Jan 30, 2021
694fb53
Add new rainDelay channel.
Skinah Jan 30, 2021
d8078f7
Make constants consistent.
Skinah Jan 30, 2021
78bb2fa
Add categories.
Skinah Feb 1, 2021
4e341ae
Changes requested by FlorianSW
Skinah Feb 25, 2021
fcffd0a
Stop catching and throwing new exp.
Skinah Feb 27, 2021
3e933f1
Create a state class.
Skinah Feb 27, 2021
aa83d13
Update bundles/org.openhab.binding.opensprinkler/src/main/java/org/op…
Skinah Mar 13, 2021
0280571
Fix for EOF exception that stops polling with bad wifi.
Skinah Mar 23, 2021
4242f3b
Change signal strength over to 0-4 range
Skinah Jun 2, 2021
290c5c5
Handle toUnit null returns.
Skinah Jun 2, 2021
6b5d435
Support discovery on subnets that are not /24
Skinah Jun 5, 2021
120119b
update readme for recent changes to signalStrength channel.
Skinah Jun 5, 2021
b76d76c
Fix code anal issue and readme.
Skinah Jun 6, 2021
710c0ee
Remove info logging.
Skinah Jun 6, 2021
fd67b5a
remove traces of old dependancy.
Skinah Jun 6, 2021
6ec36a3
Changes for fwolter
Skinah Jun 6, 2021
6f2709b
support RSSI and rssi
Skinah Jun 6, 2021
ae2a253
Update after new command sent.
Skinah Jun 8, 2021
f470809
improve delayedRefresh
Skinah Jun 26, 2021
7b90d86
Remove supressWarnings
Skinah Jul 3, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 40 additions & 31 deletions bundles/org.openhab.binding.opensprinkler/README.md
Original file line number Diff line number Diff line change
@@ -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.

## 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.
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.

## Thing Configuration
## Discovery

OpenSprinkler using the HTTP interface
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.

```
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.
Expand All @@ -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. |

## Example

demo.Things:
| 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. |

## Textual Example

demo.things:

```
Bridge opensprinkler:http:http [hostname="127.0.0.1", port=81, password="opendoor"] {
Expand Down
13 changes: 0 additions & 13 deletions bundles/org.openhab.binding.opensprinkler/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,4 @@

<name>openHAB Add-ons :: Bundles :: OpenSprinkler Binding</name>

<properties>
<dep.noembedding>commons-net</dep.noembedding>
</properties>

<dependencies>
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>${commons.net.version}</version>
<scope>compile</scope>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<features name="org.openhab.binding.opensprinkler-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>

<feature name="openhab-binding-opensprinkler" description="OpenSprinkler Binding" version="${project.version}">
<feature>openhab-runtime-base</feature>
<feature dependency="true">openhab.tp-commons-net</feature>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.opensprinkler/${project.version}</bundle>
</feature>
</features>
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -25,6 +27,32 @@
@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";
Skinah marked this conversation as resolved.
Show resolved Hide resolved
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";
Expand All @@ -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";
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
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;
Expand All @@ -40,14 +42,18 @@
* @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<ThingTypeUID> 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
Expand All @@ -56,15 +62,15 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) {
}

@Override
protected ThingHandler createHandler(Thing thing) {
protected @Nullable ThingHandler createHandler(Thing thing) {
ThingTypeUID thingTypeUID = thing.getThingTypeUID();

if (thingTypeUID.equals(OPENSPRINKLER_HTTP_BRIDGE)) {
return new OpenSprinklerHttpBridgeHandler((Bridge) thing, this.apiFactory);
} 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;
Expand Down
Original file line number Diff line number Diff line change
@@ -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<StateOption> programs = new ArrayList<>();
public List<StateOption> 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<List<Integer>> 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<String> snames = new ArrayList<>();
@SerializedName(value = "ignore_rain", alternate = "ignoreRain")
public byte[] ignoreRain = { 0 };
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
}
Loading