[opensprinkler] Fix Program names and add new features for firmware 2.2.0 (#15410)
* Fix Program names are not parsed correctly in firmware 2.2.0 --------- Signed-off-by: Matthew Skinner <matt@pcmus.com>
This commit is contained in:
parent
d791e7900a
commit
a950f19e60
|
@ -61,22 +61,25 @@ NOTE: Some channels will only show up if the hardware has the required sensor an
|
|||
|
||||
| Channel Type ID | Item Type | | Description |
|
||||
|-----------------|------------------------|----|------------------------------------------------------------------------------------|
|
||||
| rainsensor | Switch | RO | This channel indicates whether rain is detected by the device or not. |
|
||||
| sensor2 | Switch | RO | This channel is for the second sensor (if your hardware supports it). |
|
||||
| cloudConnected | Switch | RO | If the device is fully connected to the OpenSprinkler cloud this will show as 'ON'.|
|
||||
| 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. |
|
||||
| enablePrograms | Switch | RW | Allow programs to auto run. When OFF, manually started stations will still work. |
|
||||
| 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. |
|
||||
| pausePrograms | Number:Time | RW | Sets/Shows the amount of time that programs will be paused for. |
|
||||
| programs | String | RW | Displays a list of the programs that are setup in your OpenSprinkler and when |
|
||||
| | | | selected will start that program for you. |
|
||||
| rainDelay | Number:Time | RW | Sets/Shows the amount of time (hours) that rain has caused programs to be delayed. |
|
||||
| rainsensor | Switch | RO | This channel indicates whether rain is detected by the device or not. |
|
||||
| resetStations | Switch | RW | The ON command will stop all stations immediately, including those waiting to run. |
|
||||
| sensor2 | Switch | RO | This channel is for the second sensor (if your hardware supports it). |
|
||||
| signalStrength | Number | RO | Shows how strong the WiFi Signal is. |
|
||||
| stations | String | RW | Display a list of stations that can be run when selected to the length of time set |
|
||||
| | | | in the `nextDuration` channel. |
|
||||
| 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. |
|
||||
| queuedZones | Number | RO | A count of how many zones are running and also waiting to run in the queue. |
|
||||
|
||||
## Textual Example
|
||||
|
||||
|
|
|
@ -13,5 +13,4 @@
|
|||
<artifactId>org.openhab.binding.opensprinkler</artifactId>
|
||||
|
||||
<name>openHAB Add-ons :: Bundles :: OpenSprinkler Binding</name>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -82,4 +82,7 @@ public class OpenSprinklerBindingConstants {
|
|||
public static final String NEXT_DURATION = "nextDuration";
|
||||
public static final String CHANNEL_IGNORE_RAIN = "ignoreRain";
|
||||
public static final String CHANNEL_RAIN_DELAY = "rainDelay";
|
||||
public static final String CHANNEL_QUEUED_ZONES = "queuedZones";
|
||||
public static final String CHANNEL_CLOUD_CONNECTED = "cloudConnected";
|
||||
public static final String CHANNEL_PAUSE_PROGRAMS = "pausePrograms";
|
||||
}
|
||||
|
|
|
@ -63,6 +63,9 @@ public class OpenSprinklerState {
|
|||
public int rssi = 1;
|
||||
public int flcrt = -1;
|
||||
public int curr = -1;
|
||||
public int pt = -1;
|
||||
public int nq = -1;
|
||||
public int otcs = -1;
|
||||
}
|
||||
|
||||
public static class JnResponse {
|
||||
|
|
|
@ -253,4 +253,34 @@ public interface OpenSprinklerApi {
|
|||
* @return {@code QuantityType<Time>}
|
||||
*/
|
||||
QuantityType<Time> getRainDelay();
|
||||
|
||||
/**
|
||||
* Returns the Number of zones in the queue as an int.
|
||||
*
|
||||
* @return Number of zones in the queue as an int.
|
||||
*/
|
||||
int getQueuedZones();
|
||||
|
||||
/**
|
||||
* Returns the connection status of the OpenSprinkler Cloud.
|
||||
*
|
||||
* @return Connection state 0: not enabled, 1: connecting, 2: disconnected, 3: connected
|
||||
*/
|
||||
int getCloudConnected();
|
||||
|
||||
/**
|
||||
* Returns the paused status of the OpenSprinkler.
|
||||
*
|
||||
* @return int 0 to 600 seconds
|
||||
*/
|
||||
int getPausedState();
|
||||
|
||||
/**
|
||||
* Sets the amount of time that the OpenSprinkler will stop/pause zones.
|
||||
*
|
||||
* @param seconds for the pause duration in seconds (0 to 600)
|
||||
* @throws UnauthorizedApiException
|
||||
* @throws CommunicationApiException
|
||||
*/
|
||||
void setPausePrograms(int seconds) throws UnauthorizedApiException, CommunicationApiException;
|
||||
}
|
||||
|
|
|
@ -70,8 +70,10 @@ public class OpenSprinklerApiFactory {
|
|||
return new OpenSprinklerHttpApiV213(this.httpClient, config);
|
||||
} else if (version >= 217 && version < 219) {
|
||||
return new OpenSprinklerHttpApiV217(this.httpClient, config);
|
||||
} else if (version >= 219) {
|
||||
} else if (version >= 219 && version < 220) {
|
||||
return new OpenSprinklerHttpApiV219(this.httpClient, config);
|
||||
} else if (version >= 220) {
|
||||
return new OpenSprinklerHttpApiV220(this.httpClient, config);
|
||||
} else {
|
||||
/* Need to make sure we have an older OpenSprinkler device by checking the first station. */
|
||||
try {
|
||||
|
|
|
@ -432,4 +432,23 @@ class OpenSprinklerHttpApiV100 implements OpenSprinklerApi {
|
|||
return response.getContentAsString();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getQueuedZones() {
|
||||
return state.jcReply.nq;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCloudConnected() {
|
||||
return state.jcReply.otcs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPausedState() {
|
||||
return state.jcReply.pt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPausePrograms(int seconds) throws UnauthorizedApiException, CommunicationApiException {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ import org.openhab.binding.opensprinkler.internal.config.OpenSprinklerHttpInterf
|
|||
|
||||
/**
|
||||
* The {@link OpenSprinklerHttpApiV219} class is used for communicating with
|
||||
* the firmware versions 2.1.9 and up.
|
||||
* the firmware versions 2.1.9
|
||||
*
|
||||
* @author Matthew Skinner - Initial contribution
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
/**
|
||||
* Copyright (c) 2010-2023 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.api;
|
||||
|
||||
import static org.openhab.binding.opensprinkler.internal.OpenSprinklerBindingConstants.CMD_PROGRAM_DATA;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.openhab.binding.opensprinkler.internal.OpenSprinklerState.JpResponse;
|
||||
import org.openhab.binding.opensprinkler.internal.api.exception.CommunicationApiException;
|
||||
import org.openhab.binding.opensprinkler.internal.api.exception.GeneralApiException;
|
||||
import org.openhab.binding.opensprinkler.internal.api.exception.UnauthorizedApiException;
|
||||
import org.openhab.binding.opensprinkler.internal.config.OpenSprinklerHttpInterfaceConfig;
|
||||
import org.openhab.core.types.StateOption;
|
||||
|
||||
import com.google.gson.JsonParseException;
|
||||
|
||||
/**
|
||||
* The {@link OpenSprinklerHttpApiV220} class is used for communicating with
|
||||
* the firmware versions 2.2.0 and up.
|
||||
*
|
||||
* @author Matthew Skinner - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class OpenSprinklerHttpApiV220 extends OpenSprinklerHttpApiV219 {
|
||||
|
||||
OpenSprinklerHttpApiV220(HttpClient httpClient, OpenSprinklerHttpInterfaceConfig config)
|
||||
throws GeneralApiException, CommunicationApiException {
|
||||
super(httpClient, config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getProgramData() throws CommunicationApiException, UnauthorizedApiException {
|
||||
String returnContent;
|
||||
try {
|
||||
returnContent = http.sendHttpGet(getBaseUrl() + CMD_PROGRAM_DATA, getRequestRequiredOptions());
|
||||
} catch (CommunicationApiException exp) {
|
||||
throw new CommunicationApiException(
|
||||
"There was a problem in the HTTP communication with the OpenSprinkler API: " + exp.getMessage());
|
||||
}
|
||||
try {
|
||||
JpResponse resp = gson.fromJson(returnContent, JpResponse.class);
|
||||
if (resp != null && resp.pd.length > 0) {
|
||||
state.programs = new ArrayList<>();
|
||||
int counter = 0;
|
||||
for (Object x : resp.pd) {
|
||||
String temp = x.toString();
|
||||
logger.trace("Program Data:{}", temp);
|
||||
int end = temp.lastIndexOf('[') - 2;
|
||||
int start = temp.lastIndexOf((','), end - 1) + 2;
|
||||
if (start > -1 && end > -1) {
|
||||
temp = temp.substring(start, end);
|
||||
state.programs.add(new StateOption(Integer.toString(counter++), temp));
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (JsonParseException e) {
|
||||
logger.debug("Following json could not be parsed:{}", returnContent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPausePrograms(int seconds) throws UnauthorizedApiException, CommunicationApiException {
|
||||
http.sendHttpGet(getBaseUrl() + "pq", getRequestRequiredOptions() + "&dur=" + seconds);
|
||||
}
|
||||
}
|
|
@ -116,6 +116,15 @@ public class OpenSprinklerDeviceHandler extends OpenSprinklerBaseHandler {
|
|||
break;
|
||||
case CHANNEL_RESET_STATIONS:
|
||||
break;
|
||||
case CHANNEL_QUEUED_ZONES:
|
||||
updateState(channel, new DecimalType(localAPI.getQueuedZones()));
|
||||
break;
|
||||
case CHANNEL_CLOUD_CONNECTED:
|
||||
updateState(channel, OnOffType.from(localAPI.getCloudConnected() == 3));
|
||||
break;
|
||||
case CHANNEL_PAUSE_PROGRAMS:
|
||||
updateState(channel, new QuantityType<>(localAPI.getPausedState(), Units.SECOND));
|
||||
break;
|
||||
default:
|
||||
logger.debug("Can not update the unknown channel {}", channel);
|
||||
}
|
||||
|
@ -145,6 +154,18 @@ public class OpenSprinklerDeviceHandler extends OpenSprinklerBaseHandler {
|
|||
if (localAPI.getSensor2State() == -1 && channel != null) {
|
||||
removeChannels.add(channel);
|
||||
}
|
||||
channel = thing.getChannel(CHANNEL_QUEUED_ZONES);
|
||||
if (localAPI.getQueuedZones() == -1 && channel != null) {
|
||||
removeChannels.add(channel);
|
||||
}
|
||||
channel = thing.getChannel(CHANNEL_CLOUD_CONNECTED);
|
||||
if (localAPI.getCloudConnected() == -1 && channel != null) {
|
||||
removeChannels.add(channel);
|
||||
}
|
||||
channel = thing.getChannel(CHANNEL_PAUSE_PROGRAMS);
|
||||
if (localAPI.getPausedState() == -1 && channel != null) {
|
||||
removeChannels.add(channel);
|
||||
}
|
||||
if (!removeChannels.isEmpty()) {
|
||||
ThingBuilder thingBuilder = editThing();
|
||||
thingBuilder.withoutChannels(removeChannels);
|
||||
|
@ -233,6 +254,23 @@ public class OpenSprinklerDeviceHandler extends OpenSprinklerBaseHandler {
|
|||
case CHANNEL_RAIN_DELAY:
|
||||
handleRainDelayCommand(channelUID, command, api);
|
||||
break;
|
||||
case CHANNEL_PAUSE_PROGRAMS:
|
||||
if (command == OnOffType.OFF) {
|
||||
api.setPausePrograms(0);
|
||||
} else if (command instanceof DecimalType) {
|
||||
api.setPausePrograms(((BigDecimal) command).intValue());
|
||||
} else if (command instanceof QuantityType<?>) {
|
||||
QuantityType<?> quantity = (QuantityType<?>) command;
|
||||
quantity = quantity.toUnit(Units.SECOND);
|
||||
if (quantity != null) {
|
||||
api.setPausePrograms(quantity.toBigDecimal().intValue());
|
||||
}
|
||||
} else {
|
||||
logger.warn(
|
||||
"The CHANNEL_PAUSE_PROGRAMS only supports QuanityType in seconds, DecimalType and OFF");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
localBridge.delayedRefresh();// update sensors and controls after command is sent
|
||||
}
|
||||
|
|
|
@ -31,6 +31,8 @@ thing-type.config.opensprinkler.station.stationIndex.description = The index of
|
|||
|
||||
# channel types
|
||||
|
||||
channel-type.opensprinkler.cloudConnected.label = Cloud Connected
|
||||
channel-type.opensprinkler.cloudConnected.description = If the device is fully connected to the OpenSprinkler cloud this will show as 'ON'.
|
||||
channel-type.opensprinkler.currentDraw.label = Current Draw
|
||||
channel-type.opensprinkler.currentDraw.description = The current draw in mA
|
||||
channel-type.opensprinkler.enablePrograms.label = Enable Programs
|
||||
|
@ -56,10 +58,23 @@ channel-type.opensprinkler.nextDuration.state.option.90min = 1.5 Hours
|
|||
channel-type.opensprinkler.nextDuration.state.option.2h = 2 Hours
|
||||
channel-type.opensprinkler.nextDuration.state.option.3h = 3 Hours
|
||||
channel-type.opensprinkler.nextDuration.state.option.4h = 4 Hours
|
||||
channel-type.opensprinkler.pausePrograms.label = Pause Programs
|
||||
channel-type.opensprinkler.pausePrograms.description = The duration that all zones will be paused for before resuming the watering.
|
||||
channel-type.opensprinkler.pausePrograms.state.option.0s = Not Paused
|
||||
channel-type.opensprinkler.pausePrograms.state.option.15s = 15 Seconds
|
||||
channel-type.opensprinkler.pausePrograms.state.option.30s = 30 Seconds
|
||||
channel-type.opensprinkler.pausePrograms.state.option.1min = 1 Minute
|
||||
channel-type.opensprinkler.pausePrograms.state.option.2min = 2 Minutes
|
||||
channel-type.opensprinkler.pausePrograms.state.option.3min = 3 Minutes
|
||||
channel-type.opensprinkler.pausePrograms.state.option.4min = 4 Minutes
|
||||
channel-type.opensprinkler.pausePrograms.state.option.5min = 5 Minutes
|
||||
channel-type.opensprinkler.pausePrograms.state.option.10min = 10 Minutes
|
||||
channel-type.opensprinkler.programs.label = Run Program
|
||||
channel-type.opensprinkler.programs.description = Run a program that is saved inside the OpenSprinkler Device.
|
||||
channel-type.opensprinkler.queued.label = Queued
|
||||
channel-type.opensprinkler.queued.description = Indicates if the station is queued to be turned on. Can be removed from the queue by turning off. ON is read-only.
|
||||
channel-type.opensprinkler.queuedZones.label = Number Of Queued Zones
|
||||
channel-type.opensprinkler.queuedZones.description = A count of how many zones are running and also waiting to run in the queue.
|
||||
channel-type.opensprinkler.rainDelay.label = Rain Delay
|
||||
channel-type.opensprinkler.rainDelay.description = The amount of time in hours to delay the running of any program.
|
||||
channel-type.opensprinkler.rainDelay.state.option.0s = Off
|
||||
|
|
|
@ -89,7 +89,15 @@
|
|||
<channel id="resetStations" typeId="resetStations"></channel>
|
||||
<channel id="enablePrograms" typeId="enablePrograms"></channel>
|
||||
<channel id="rainDelay" typeId="rainDelay"></channel>
|
||||
<channel id="queuedZones" typeId="queuedZones"></channel>
|
||||
<channel id="cloudConnected" typeId="cloudConnected"></channel>
|
||||
<channel id="pausePrograms" typeId="pausePrograms"></channel>
|
||||
</channels>
|
||||
|
||||
<properties>
|
||||
<property name="thingTypeVersion">1</property>
|
||||
</properties>
|
||||
|
||||
</thing-type>
|
||||
|
||||
<channel-type id="rainsensor">
|
||||
|
@ -108,6 +116,14 @@
|
|||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="cloudConnected">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Cloud Connected</label>
|
||||
<description>If the device is fully connected to the OpenSprinkler cloud this will show as 'ON'.</description>
|
||||
<category>Sensor</category>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="waterlevel">
|
||||
<item-type>Number:Dimensionless</item-type>
|
||||
<label>Water Level</label>
|
||||
|
@ -123,6 +139,13 @@
|
|||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="queuedZones">
|
||||
<item-type>Number</item-type>
|
||||
<label>Number Of Queued Zones</label>
|
||||
<description>A count of how many zones are running and also waiting to run in the queue.</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="currentDraw">
|
||||
<item-type>Number:ElectricCurrent</item-type>
|
||||
<label>Current Draw</label>
|
||||
|
@ -176,6 +199,26 @@
|
|||
<state readOnly="true" pattern="%.0f min"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="pausePrograms">
|
||||
<item-type>Number:Time</item-type>
|
||||
<label>Pause Programs</label>
|
||||
<description>The duration that all zones will be paused for before resuming the watering.</description>
|
||||
<category>Time</category>
|
||||
<state>
|
||||
<options>
|
||||
<option value="0s">Not Paused</option>
|
||||
<option value="15s">15 Seconds</option>
|
||||
<option value="30s">30 Seconds</option>
|
||||
<option value="1min">1 Minute</option>
|
||||
<option value="2min">2 Minutes</option>
|
||||
<option value="3min">3 Minutes</option>
|
||||
<option value="4min">4 Minutes</option>
|
||||
<option value="5min">5 Minutes</option>
|
||||
<option value="10min">10 Minutes</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="nextDuration">
|
||||
<item-type>Number:Time</item-type>
|
||||
<label>Next Duration</label>
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||
<update:update-descriptions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:update="https://openhab.org/schemas/update-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/update-description/v1.0.0 https://openhab.org/schemas/update-description-1.0.0.xsd">
|
||||
|
||||
<thing-type uid="opensprinkler:device">
|
||||
|
||||
<instruction-set targetVersion="1">
|
||||
<add-channel id="queuedZones">
|
||||
<type>opensprinkler:queuedZones</type>
|
||||
</add-channel>
|
||||
<add-channel id="cloudConnected">
|
||||
<type>opensprinkler:cloudConnected</type>
|
||||
</add-channel>
|
||||
<add-channel id="pausePrograms">
|
||||
<type>opensprinkler:pausePrograms</type>
|
||||
</add-channel>
|
||||
</instruction-set>
|
||||
|
||||
</thing-type>
|
||||
|
||||
</update:update-descriptions>
|
Loading…
Reference in New Issue