From f26fc8103955d760dc1b60ffa8c520cdb6fa8815 Mon Sep 17 00:00:00 2001 From: dw-8 Date: Sun, 25 Jul 2021 01:11:23 -0400 Subject: [PATCH] Revert "[ipobserver] Weather station binding, Initial contribution. (#10567)" This reverts commit b111382bae834306fc94048f6e878e39a82e7c0f. Signed-off-by: dw-8 --- CODEOWNERS | 1 - bom/openhab-addons/pom.xml | 5 - bundles/org.openhab.binding.ipobserver/NOTICE | 20 - .../org.openhab.binding.ipobserver/README.md | 54 --- .../org.openhab.binding.ipobserver/pom.xml | 24 -- .../src/main/feature/feature.xml | 9 - .../internal/IpObserverBindingConstants.java | 59 --- .../internal/IpObserverConfiguration.java | 27 -- .../internal/IpObserverDiscoveryJob.java | 64 ---- .../internal/IpObserverDiscoveryService.java | 145 -------- .../internal/IpObserverHandler.java | 348 ------------------ .../internal/IpObserverHandlerFactory.java | 68 ---- .../main/resources/OH-INF/binding/binding.xml | 10 - .../resources/OH-INF/thing/thing-types.xml | 249 ------------- bundles/pom.xml | 1 - 15 files changed, 1084 deletions(-) delete mode 100644 bundles/org.openhab.binding.ipobserver/NOTICE delete mode 100644 bundles/org.openhab.binding.ipobserver/README.md delete mode 100644 bundles/org.openhab.binding.ipobserver/pom.xml delete mode 100644 bundles/org.openhab.binding.ipobserver/src/main/feature/feature.xml delete mode 100644 bundles/org.openhab.binding.ipobserver/src/main/java/org/openhab/binding/ipobserver/internal/IpObserverBindingConstants.java delete mode 100644 bundles/org.openhab.binding.ipobserver/src/main/java/org/openhab/binding/ipobserver/internal/IpObserverConfiguration.java delete mode 100644 bundles/org.openhab.binding.ipobserver/src/main/java/org/openhab/binding/ipobserver/internal/IpObserverDiscoveryJob.java delete mode 100644 bundles/org.openhab.binding.ipobserver/src/main/java/org/openhab/binding/ipobserver/internal/IpObserverDiscoveryService.java delete mode 100644 bundles/org.openhab.binding.ipobserver/src/main/java/org/openhab/binding/ipobserver/internal/IpObserverHandler.java delete mode 100644 bundles/org.openhab.binding.ipobserver/src/main/java/org/openhab/binding/ipobserver/internal/IpObserverHandlerFactory.java delete mode 100644 bundles/org.openhab.binding.ipobserver/src/main/resources/OH-INF/binding/binding.xml delete mode 100644 bundles/org.openhab.binding.ipobserver/src/main/resources/OH-INF/thing/thing-types.xml diff --git a/CODEOWNERS b/CODEOWNERS index 7751f544c671..d51cdc116162 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -128,7 +128,6 @@ /bundles/org.openhab.binding.insteon/ @robnielsen /bundles/org.openhab.binding.intesis/ @hmerk /bundles/org.openhab.binding.ipcamera/ @Skinah -/bundles/org.openhab.binding.ipobserver/ @Skinah /bundles/org.openhab.binding.ipp/ @peuter /bundles/org.openhab.binding.irobot/ @Sonic-Amiga /bundles/org.openhab.binding.irtrans/ @kgoderis diff --git a/bom/openhab-addons/pom.xml b/bom/openhab-addons/pom.xml index 7830bf7d35cf..549382d56624 100644 --- a/bom/openhab-addons/pom.xml +++ b/bom/openhab-addons/pom.xml @@ -626,11 +626,6 @@ org.openhab.binding.ipcamera ${project.version} - - org.openhab.addons.bundles - org.openhab.binding.ipobserver - ${project.version} - org.openhab.addons.bundles org.openhab.binding.ipp diff --git a/bundles/org.openhab.binding.ipobserver/NOTICE b/bundles/org.openhab.binding.ipobserver/NOTICE deleted file mode 100644 index 3e2c49e0050b..000000000000 --- a/bundles/org.openhab.binding.ipobserver/NOTICE +++ /dev/null @@ -1,20 +0,0 @@ -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 - -== Third-party Content - -jsoup -* License: MIT License -* Project: https://jsoup.org/ -* Source: https://github.com/jhy/jsoup \ No newline at end of file diff --git a/bundles/org.openhab.binding.ipobserver/README.md b/bundles/org.openhab.binding.ipobserver/README.md deleted file mode 100644 index 4e7e39497ebf..000000000000 --- a/bundles/org.openhab.binding.ipobserver/README.md +++ /dev/null @@ -1,54 +0,0 @@ -# IpObserver Binding - -This binding is for any weather station that sends data to an IP Observer module. -The weather stations that do this are made by a company in China called `Fine Offset` and then re-branded by many distribution companies around the world. -Some of the brands include Aercus (433mhz), Ambient Weather (915mhz), Frogitt, Misol (433mhz), Pantech (433mhz), Sainlogic and many more. -Whilst Ambient Weather has it own cloud based binding, the other brands will not work with that binding and Ambient Weather do not sell outside of the United States. -This binding works fully offline and uses local scraping of the weather station data at 12 second resolution if you wish and is easy to setup. -The other binding worth mentioning is the weather underground binding that allows the data to be intercepted on its way to WU, however many of the weather stations do not allow the redirection of the WU data and require you to know how to do redirections with a custom DNS server on your network. -This binding is by far the easiest method and works for all the brands and will not stop the data still being sent to WU if you wish to do both at the same time. -If your weather station came with a LCD screen instead of the IP Observer, you can add on the unit and the LCD screen will still work in parallel as the RF data is sent 1 way from the outdoor unit to the inside screens and IP Observer units. - -## Supported Things - -There is only one thing that can be added and is called `weatherstation`. - -## Discovery - -Auto discovery is supported and may take a while to complete as it scans all IP addresses on your network one by one. - -## Thing Configuration - -| Parameter | Required | Description | -|-|-|-| -| `address` | Y | Hostname or IP for the IP Observer | -| `pollTime` | Y | Time in seconds between each Scan of the livedata.htm from the IP Observer | -| `autoReboot` | Y | Time in milliseconds to wait for a reply before rebooting the IP Observer. A value of 0 disables this feature allowing you to manually trigger or use a rule to handle the reboots. | - -## Channels - -| channel | type | description | -|-----------------------|-----------------------|------------------------------| -| temperatureIndoor | Number:Temperature | The temperature indoors. | -| temperatureOutdoor | Number:Temperature | The temperature outdoors. | -| humidityIndoor | Number:Dimensionless | The humidity indoors. | -| humidityOutdoor | Number:Dimensionless | The humidity outdoors. | -| pressureAbsolute | Number:Pressure | The atmospheric pressure directly measured by the sensor. | -| pressureRelative | Number:Pressure | The pressure adjusted to sea level to allow easier comparisons between different locations. | -| windDirection | Number:Angle | The angle in degrees that the wind is coming from. | -| windAverageSpeed | Number:Speed | The average wind speed. | -| windSpeed | Number:Speed | The exact wind speed. Not all stations send this data. | -| windGust | Number:Speed | The recent wind gust speed. | -| windMaxGust | Number:Speed | The recent max wind gust speed. | -| solarRadiation | Number:Intensity | Solar radiation. | -| uv | Number | UV measurement. | -| uvIndex | Number | The UV index. | -| rainHourlyRate | Number:Length | The amount of rain that will fall, if it continues to fall at the same rate for an hour. Measures how heavy the current rain is falling. | -| rainToday | Number:Length | Amount of rain since 12:00am. | -| rainForWeek | Number:Length | Amount of rain for the week. | -| rainForMonth | Number:Length | Amount of rain for the month. | -| rainForYear | Number:Length | Amount of rain for the year. | -| batteryIndoor | Switch | Battery status, ON if battery is low. | -| batteryOutdoor | Switch | Battery status, OFF if battery is normal. | -| responseTime | Number:Time | How long it took the weather station to reply to a request for the live data. | -| lastUpdatedTime | DateTime | The time scraped from the weather station when it last read the sensors. | diff --git a/bundles/org.openhab.binding.ipobserver/pom.xml b/bundles/org.openhab.binding.ipobserver/pom.xml deleted file mode 100644 index e7bc2b386589..000000000000 --- a/bundles/org.openhab.binding.ipobserver/pom.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - 4.0.0 - - - org.openhab.addons.bundles - org.openhab.addons.reactor.bundles - 3.2.0-SNAPSHOT - - - org.openhab.binding.ipobserver - - openHAB Add-ons :: Bundles :: IpObserver Binding - - - org.jsoup - jsoup - 1.8.3 - provided - - - diff --git a/bundles/org.openhab.binding.ipobserver/src/main/feature/feature.xml b/bundles/org.openhab.binding.ipobserver/src/main/feature/feature.xml deleted file mode 100644 index f9d25835deff..000000000000 --- a/bundles/org.openhab.binding.ipobserver/src/main/feature/feature.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.jsoup/jsoup/1.8.3 - mvn:org.openhab.addons.bundles/org.openhab.binding.ipobserver/${project.version} - - diff --git a/bundles/org.openhab.binding.ipobserver/src/main/java/org/openhab/binding/ipobserver/internal/IpObserverBindingConstants.java b/bundles/org.openhab.binding.ipobserver/src/main/java/org/openhab/binding/ipobserver/internal/IpObserverBindingConstants.java deleted file mode 100644 index f469c4253f63..000000000000 --- a/bundles/org.openhab.binding.ipobserver/src/main/java/org/openhab/binding/ipobserver/internal/IpObserverBindingConstants.java +++ /dev/null @@ -1,59 +0,0 @@ -/** - * 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.ipobserver.internal; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.openhab.core.thing.ThingTypeUID; - -/** - * The {@link IpObserverBindingConstants} class defines common constants, which are - * used across the whole binding. - * - * @author Matthew Skinner - Initial contribution - */ -@NonNullByDefault -public class IpObserverBindingConstants { - public static final String BINDING_ID = "ipobserver"; - public static final String REBOOT_URL = "/msgreboot.htm"; - public static final String LIVE_DATA_URL = "/livedata.htm"; - public static final String STATION_SETTINGS_URL = "/station.htm"; - public static final int DISCOVERY_THREAD_POOL_SIZE = 15; - - // List of all Thing Type UIDs - public static final ThingTypeUID THING_WEATHER_STATION = new ThingTypeUID(BINDING_ID, "weatherstation"); - - // List of all Channel ids - public static final String TEMP_INDOOR = "temperatureIndoor"; - public static final String TEMP_OUTDOOR = "temperatureOutdoor"; - public static final String INDOOR_HUMIDITY = "humidityIndoor"; - public static final String OUTDOOR_HUMIDITY = "humidityOutdoor"; - public static final String ABS_PRESSURE = "pressureAbsolute"; - public static final String REL_PRESSURE = "pressureRelative"; - public static final String WIND_DIRECTION = "windDirection"; - public static final String WIND_AVERAGE_SPEED = "windAverageSpeed"; - public static final String WIND_SPEED = "windSpeed"; - public static final String WIND_GUST = "windGust"; - public static final String WIND_MAX_GUST = "windMaxGust"; - public static final String SOLAR_RADIATION = "solarRadiation"; - public static final String UV = "uv"; - public static final String UV_INDEX = "uvIndex"; - public static final String HOURLY_RAIN_RATE = "rainHourlyRate"; - public static final String DAILY_RAIN = "rainToday"; - public static final String WEEKLY_RAIN = "rainForWeek"; - public static final String MONTHLY_RAIN = "rainForMonth"; - public static final String YEARLY_RAIN = "rainForYear"; - public static final String INDOOR_BATTERY = "batteryIndoor"; - public static final String OUTDOOR_BATTERY = "batteryOutdoor"; - public static final String RESPONSE_TIME = "responseTime"; - public static final String LAST_UPDATED_TIME = "lastUpdatedTime"; -} diff --git a/bundles/org.openhab.binding.ipobserver/src/main/java/org/openhab/binding/ipobserver/internal/IpObserverConfiguration.java b/bundles/org.openhab.binding.ipobserver/src/main/java/org/openhab/binding/ipobserver/internal/IpObserverConfiguration.java deleted file mode 100644 index c4843238ab1d..000000000000 --- a/bundles/org.openhab.binding.ipobserver/src/main/java/org/openhab/binding/ipobserver/internal/IpObserverConfiguration.java +++ /dev/null @@ -1,27 +0,0 @@ -/** - * 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.ipobserver.internal; - -import org.eclipse.jdt.annotation.NonNullByDefault; - -/** - * The {@link IpObserverConfiguration} class contains fields mapping thing configuration parameters. - * - * @author Matthew Skinner - Initial contribution - */ -@NonNullByDefault -public class IpObserverConfiguration { - public String address = ""; - public int pollTime = 20; - public int autoReboot = 2000; -} diff --git a/bundles/org.openhab.binding.ipobserver/src/main/java/org/openhab/binding/ipobserver/internal/IpObserverDiscoveryJob.java b/bundles/org.openhab.binding.ipobserver/src/main/java/org/openhab/binding/ipobserver/internal/IpObserverDiscoveryJob.java deleted file mode 100644 index ad6236933654..000000000000 --- a/bundles/org.openhab.binding.ipobserver/src/main/java/org/openhab/binding/ipobserver/internal/IpObserverDiscoveryJob.java +++ /dev/null @@ -1,64 +0,0 @@ -/** - * 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.ipobserver.internal; - -import static org.openhab.binding.ipobserver.internal.IpObserverBindingConstants.LIVE_DATA_URL; - -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jetty.client.api.ContentResponse; -import org.eclipse.jetty.client.api.Request; -import org.eclipse.jetty.http.HttpHeader; -import org.eclipse.jetty.http.HttpMethod; - -/** - * The {@link IpObserverDiscoveryJob} class allows auto discovery of - * devices for a single IP address. This is used - * for threading to make discovery faster. - * - * @author Matthew Skinner - Initial contribution - */ -@NonNullByDefault -public class IpObserverDiscoveryJob implements Runnable { - private IpObserverDiscoveryService discoveryClass; - private String ipAddress; - - public IpObserverDiscoveryJob(IpObserverDiscoveryService service, String ip) { - this.discoveryClass = service; - this.ipAddress = ip; - } - - @Override - public void run() { - if (isIpObserverDevice(this.ipAddress)) { - discoveryClass.submitDiscoveryResults(this.ipAddress); - } - } - - private boolean isIpObserverDevice(String ip) { - Request request = discoveryClass.getHttpClient().newRequest("http://" + ip + LIVE_DATA_URL); - request.method(HttpMethod.GET).timeout(5, TimeUnit.SECONDS).header(HttpHeader.ACCEPT_ENCODING, "gzip"); - ContentResponse contentResponse; - try { - contentResponse = request.send(); - if (contentResponse.getStatus() == 200 && contentResponse.getContentAsString().contains("livedata.htm")) { - return true; - } - } catch (InterruptedException | TimeoutException | ExecutionException e) { - } - return false; - } -} diff --git a/bundles/org.openhab.binding.ipobserver/src/main/java/org/openhab/binding/ipobserver/internal/IpObserverDiscoveryService.java b/bundles/org.openhab.binding.ipobserver/src/main/java/org/openhab/binding/ipobserver/internal/IpObserverDiscoveryService.java deleted file mode 100644 index 3d75dc962ec7..000000000000 --- a/bundles/org.openhab.binding.ipobserver/src/main/java/org/openhab/binding/ipobserver/internal/IpObserverDiscoveryService.java +++ /dev/null @@ -1,145 +0,0 @@ -/** - * 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.ipobserver.internal; - -import static org.openhab.binding.ipobserver.internal.IpObserverBindingConstants.*; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.InterfaceAddress; -import java.net.NetworkInterface; -import java.net.SocketException; -import java.nio.ByteBuffer; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.List; -import java.util.Set; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jetty.client.HttpClient; -import org.openhab.core.config.discovery.AbstractDiscoveryService; -import org.openhab.core.config.discovery.DiscoveryResultBuilder; -import org.openhab.core.config.discovery.DiscoveryService; -import org.openhab.core.io.net.http.HttpClientFactory; -import org.openhab.core.thing.ThingTypeUID; -import org.openhab.core.thing.ThingUID; -import org.osgi.service.component.annotations.Activate; -import org.osgi.service.component.annotations.Component; -import org.osgi.service.component.annotations.Reference; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The {@link IpObserverDiscoveryService} is responsible for finding ipObserver devices. - * - * @author Matthew Skinner - Initial contribution. - */ -@Component(service = DiscoveryService.class, configurationPid = "discovery.ipobserver") -@NonNullByDefault -public class IpObserverDiscoveryService extends AbstractDiscoveryService { - private final Logger logger = LoggerFactory.getLogger(this.getClass()); - private static final Set SUPPORTED_THING_TYPES_UIDS = Set.of(THING_WEATHER_STATION); - private ExecutorService discoverySearchPool = Executors.newFixedThreadPool(DISCOVERY_THREAD_POOL_SIZE); - private HttpClient httpClient; - - @Activate - public IpObserverDiscoveryService(@Reference HttpClientFactory httpClientFactory) { - super(SUPPORTED_THING_TYPES_UIDS, 240); - httpClient = httpClientFactory.getCommonHttpClient(); - } - - @Override - public Set getSupportedThingTypes() { - return SUPPORTED_THING_TYPES_UIDS; - } - - protected HttpClient getHttpClient() { - return httpClient; - } - - public void submitDiscoveryResults(String ip) { - ThingUID thingUID = new ThingUID(THING_WEATHER_STATION, ip.replace('.', '_')); - HashMap properties = new HashMap<>(); - properties.put("address", ip); - thingDiscovered(DiscoveryResultBuilder.create(thingUID).withProperties(properties).withLabel("Weather Station") - .withRepresentationProperty("address").build()); - } - - private void scanSingleSubnet(InterfaceAddress hostAddress) { - byte[] broadcastAddress = hostAddress.getBroadcast().getAddress(); - // Create subnet mask from length - int shft = 0xffffffff << (32 - hostAddress.getNetworkPrefixLength()); - byte oct1 = (byte) (((byte) ((shft & 0xff000000) >> 24)) & 0xff); - byte oct2 = (byte) (((byte) ((shft & 0x00ff0000) >> 16)) & 0xff); - byte oct3 = (byte) (((byte) ((shft & 0x0000ff00) >> 8)) & 0xff); - byte oct4 = (byte) (((byte) (shft & 0x000000ff)) & 0xff); - byte[] subnetMask = new byte[] { oct1, oct2, oct3, oct4 }; - // calc first IP to start scanning from on this subnet - byte[] startAddress = new byte[4]; - startAddress[0] = (byte) (broadcastAddress[0] & subnetMask[0]); - startAddress[1] = (byte) (broadcastAddress[1] & subnetMask[1]); - startAddress[2] = (byte) (broadcastAddress[2] & subnetMask[2]); - startAddress[3] = (byte) (broadcastAddress[3] & subnetMask[3]); - // Loop from start of subnet to the broadcast address. - for (int i = ByteBuffer.wrap(startAddress).getInt(); i < ByteBuffer.wrap(broadcastAddress).getInt(); i++) { - try { - InetAddress currentIP = InetAddress.getByAddress(ByteBuffer.allocate(4).putInt(i).array()); - // Try to reach each IP with a timeout of 500ms which is enough for local network - if (currentIP.isReachable(500)) { - String host = currentIP.getHostAddress().toString(); - logger.debug("Unknown device was found at: {}", host); - discoverySearchPool.execute(new IpObserverDiscoveryJob(this, host)); - } - } catch (IOException e) { - } - } - } - - @Override - protected void startScan() { - discoverySearchPool = Executors.newFixedThreadPool(DISCOVERY_THREAD_POOL_SIZE); - try { - ipAddressScan(); - } catch (Exception exp) { - logger.debug("IpObserver discovery service encountered an error while scanning for devices: {}", - exp.getMessage()); - } - } - - @Override - protected void stopScan() { - discoverySearchPool.shutdown(); - super.stopScan(); - } - - private void ipAddressScan() { - try { - for (Enumeration enumNetworks = NetworkInterface.getNetworkInterfaces(); enumNetworks - .hasMoreElements();) { - NetworkInterface networkInterface = enumNetworks.nextElement(); - List list = networkInterface.getInterfaceAddresses(); - for (InterfaceAddress hostAddress : list) { - InetAddress inetAddress = hostAddress.getAddress(); - if (!inetAddress.isLoopbackAddress() && inetAddress.isSiteLocalAddress()) { - logger.debug("Scanning all IP address's that IP {}/{} is on", hostAddress.getAddress(), - hostAddress.getNetworkPrefixLength()); - scanSingleSubnet(hostAddress); - } - } - } - } catch (SocketException ex) { - } - } -} diff --git a/bundles/org.openhab.binding.ipobserver/src/main/java/org/openhab/binding/ipobserver/internal/IpObserverHandler.java b/bundles/org.openhab.binding.ipobserver/src/main/java/org/openhab/binding/ipobserver/internal/IpObserverHandler.java deleted file mode 100644 index 15d947e1c7dd..000000000000 --- a/bundles/org.openhab.binding.ipobserver/src/main/java/org/openhab/binding/ipobserver/internal/IpObserverHandler.java +++ /dev/null @@ -1,348 +0,0 @@ -/** - * 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.ipobserver.internal; - -import static org.openhab.binding.ipobserver.internal.IpObserverBindingConstants.*; - -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeParseException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; -import java.util.TimeZone; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import javax.measure.Unit; - -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.http.HttpHeader; -import org.eclipse.jetty.http.HttpMethod; -import org.jsoup.Jsoup; -import org.jsoup.nodes.Document; -import org.jsoup.nodes.Element; -import org.jsoup.select.Elements; -import org.openhab.core.library.types.DateTimeType; -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.MetricPrefix; -import org.openhab.core.library.unit.SIUnits; -import org.openhab.core.library.unit.Units; -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.ThingStatusDetail; -import org.openhab.core.thing.binding.BaseThingHandler; -import org.openhab.core.types.Command; -import org.openhab.core.types.State; -import org.openhab.core.types.TypeParser; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The {@link IpObserverHandler} is responsible for handling commands, which are - * sent to one of the channels. - * - * @author Thomas Hentschel - Initial contribution. - * @author Matthew Skinner - Full re-write for BND, V3.0 and UOM - */ -@NonNullByDefault -public class IpObserverHandler extends BaseThingHandler { - private final HttpClient httpClient; - private final Logger logger = LoggerFactory.getLogger(IpObserverHandler.class); - private Map channelHandlers = new HashMap(); - private @Nullable ScheduledFuture pollingFuture = null; - private IpObserverConfiguration config = new IpObserverConfiguration(); - // Config settings parsed from weather station. - private boolean imperialTemperature = false; - private boolean imperialRain = false; - // 0=lux, 1=w/m2, 2=fc - private String solarUnit = "0"; - // 0=m/s, 1=km/h, 2=ft/s, 3=bft, 4=mph, 5=knot - private String windUnit = "0"; - // 0=hpa, 1=inhg, 2=mmhg - private String pressureUnit = "0"; - - private class ChannelHandler { - private IpObserverHandler handler; - private Channel channel; - private String previousValue = ""; - private Unit unit; - private final ArrayList> acceptedDataTypes = new ArrayList>(); - - ChannelHandler(IpObserverHandler handler, Channel channel, Class acceptable, Unit unit) { - super(); - this.handler = handler; - this.channel = channel; - this.unit = unit; - acceptedDataTypes.add(acceptable); - } - - public void processValue(String sensorValue) { - if (!sensorValue.equals(previousValue)) { - previousValue = sensorValue; - switch (channel.getUID().getId()) { - case LAST_UPDATED_TIME: - try { - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm MM/dd/yyyy") - .withZone(TimeZone.getDefault().toZoneId()); - ZonedDateTime zonedDateTime = ZonedDateTime.parse(sensorValue, formatter); - this.handler.updateState(this.channel.getUID(), new DateTimeType(zonedDateTime)); - } catch (DateTimeParseException e) { - logger.debug("Could not parse {} as a valid dateTime", sensorValue); - } - return; - case INDOOR_BATTERY: - case OUTDOOR_BATTERY: - if ("1".equals(sensorValue)) { - handler.updateState(this.channel.getUID(), OnOffType.ON); - } else { - handler.updateState(this.channel.getUID(), OnOffType.OFF); - } - return; - } - State state = TypeParser.parseState(this.acceptedDataTypes, sensorValue); - if (state == null) { - return; - } else if (state instanceof QuantityType) { - handler.updateState(this.channel.getUID(), - QuantityType.valueOf(Double.parseDouble(sensorValue), unit)); - } else { - handler.updateState(this.channel.getUID(), state); - } - } - } - } - - public IpObserverHandler(Thing thing, HttpClient httpClient) { - super(thing); - this.httpClient = httpClient; - } - - @Override - public void handleCommand(ChannelUID channelUID, Command command) { - } - - private void parseSettings(String html) { - Document doc = Jsoup.parse(html); - solarUnit = doc.select("select[name=unit_Solar] option[selected]").val(); - windUnit = doc.select("select[name=unit_Wind] option[selected]").val(); - pressureUnit = doc.select("select[name=unit_Pressure] option[selected]").val(); - // 0=degC, 1=degF - if ("1".equals(doc.select("select[name=u_Temperature] option[selected]").val())) { - imperialTemperature = true; - } else { - imperialTemperature = false; - } - // 0=mm, 1=in - if ("1".equals(doc.select("select[name=u_Rainfall] option[selected]").val())) { - imperialRain = true; - } else { - imperialRain = false; - } - } - - private void parseAndUpdate(String html) { - Document doc = Jsoup.parse(html); - String value = doc.select("select[name=inBattSta] option[selected]").val(); - ChannelHandler localUpdater = channelHandlers.get("inBattSta"); - if (localUpdater != null) { - localUpdater.processValue(value); - } - value = doc.select("select[name=outBattSta] option[selected]").val(); - localUpdater = channelHandlers.get("outBattSta"); - if (localUpdater != null) { - localUpdater.processValue(value); - } - - Elements elements = doc.select("input"); - for (Element element : elements) { - String elementName = element.attr("name"); - value = element.attr("value"); - if (!value.isEmpty()) { - logger.trace("Found element {}, value is {}", elementName, value); - localUpdater = channelHandlers.get(elementName); - if (localUpdater != null) { - localUpdater.processValue(value); - } - } - } - } - - private void sendGetRequest(String url) { - Request request = httpClient.newRequest("http://" + config.address + url); - request.method(HttpMethod.GET).timeout(5, TimeUnit.SECONDS).header(HttpHeader.ACCEPT_ENCODING, "gzip"); - String errorReason = ""; - try { - long start = System.currentTimeMillis(); - ContentResponse contentResponse = request.send(); - if (contentResponse.getStatus() == 200) { - long responseTime = (System.currentTimeMillis() - start); - if (!this.getThing().getStatus().equals(ThingStatus.ONLINE)) { - updateStatus(ThingStatus.ONLINE); - logger.debug("Finding out which units of measurement the weather station is using."); - sendGetRequest(STATION_SETTINGS_URL); - } - if (url == STATION_SETTINGS_URL) { - parseSettings(contentResponse.getContentAsString()); - setupChannels(); - } else { - updateState(RESPONSE_TIME, new QuantityType<>(responseTime, MetricPrefix.MILLI(Units.SECOND))); - parseAndUpdate(contentResponse.getContentAsString()); - } - if (config.autoReboot > 0 && responseTime > config.autoReboot) { - logger.debug("An Auto reboot of the IP Observer unit has been triggered as the response was {}ms.", - responseTime); - sendGetRequest(REBOOT_URL); - } - return; - } else { - errorReason = String.format("IpObserver request failed with %d: %s", contentResponse.getStatus(), - contentResponse.getReason()); - } - } catch (TimeoutException e) { - errorReason = "TimeoutException: IpObserver was not reachable on your network"; - } catch (ExecutionException e) { - errorReason = String.format("ExecutionException: %s", e.getMessage()); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - errorReason = String.format("InterruptedException: %s", e.getMessage()); - } - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, errorReason); - } - - private void pollStation() { - sendGetRequest(LIVE_DATA_URL); - } - - private void createChannelHandler(String chanName, Class type, Unit unit, String htmlName) { - @Nullable - Channel channel = this.getThing().getChannel(chanName); - if (channel != null) { - channelHandlers.put(htmlName, new ChannelHandler(this, channel, type, unit)); - } - } - - private void setupChannels() { - if (imperialTemperature) { - logger.debug("Using imperial units of measurement for temperature."); - createChannelHandler(TEMP_INDOOR, QuantityType.class, ImperialUnits.FAHRENHEIT, "inTemp"); - createChannelHandler(TEMP_OUTDOOR, QuantityType.class, ImperialUnits.FAHRENHEIT, "outTemp"); - } else { - logger.debug("Using metric units of measurement for temperature."); - createChannelHandler(TEMP_INDOOR, QuantityType.class, SIUnits.CELSIUS, "inTemp"); - createChannelHandler(TEMP_OUTDOOR, QuantityType.class, SIUnits.CELSIUS, "outTemp"); - } - - if (imperialRain) { - createChannelHandler(HOURLY_RAIN_RATE, QuantityType.class, ImperialUnits.INCH, "rainofhourly"); - createChannelHandler(DAILY_RAIN, QuantityType.class, ImperialUnits.INCH, "rainofdaily"); - createChannelHandler(WEEKLY_RAIN, QuantityType.class, ImperialUnits.INCH, "rainofweekly"); - createChannelHandler(MONTHLY_RAIN, QuantityType.class, ImperialUnits.INCH, "rainofmonthly"); - createChannelHandler(YEARLY_RAIN, QuantityType.class, ImperialUnits.INCH, "rainofyearly"); - } else { - logger.debug("Using metric units of measurement for rain."); - createChannelHandler(HOURLY_RAIN_RATE, QuantityType.class, MetricPrefix.MILLI(SIUnits.METRE), - "rainofhourly"); - createChannelHandler(DAILY_RAIN, QuantityType.class, MetricPrefix.MILLI(SIUnits.METRE), "rainofdaily"); - createChannelHandler(WEEKLY_RAIN, QuantityType.class, MetricPrefix.MILLI(SIUnits.METRE), "rainofweekly"); - createChannelHandler(MONTHLY_RAIN, QuantityType.class, MetricPrefix.MILLI(SIUnits.METRE), "rainofmonthly"); - createChannelHandler(YEARLY_RAIN, QuantityType.class, MetricPrefix.MILLI(SIUnits.METRE), "rainofyearly"); - } - - if ("5".equals(windUnit)) { - createChannelHandler(WIND_AVERAGE_SPEED, QuantityType.class, Units.KNOT, "avgwind"); - createChannelHandler(WIND_SPEED, QuantityType.class, Units.KNOT, "windspeed"); - createChannelHandler(WIND_GUST, QuantityType.class, Units.KNOT, "gustspeed"); - createChannelHandler(WIND_MAX_GUST, QuantityType.class, Units.KNOT, "dailygust"); - } else if ("4".equals(windUnit)) { - createChannelHandler(WIND_AVERAGE_SPEED, QuantityType.class, ImperialUnits.MILES_PER_HOUR, "avgwind"); - createChannelHandler(WIND_SPEED, QuantityType.class, ImperialUnits.MILES_PER_HOUR, "windspeed"); - createChannelHandler(WIND_GUST, QuantityType.class, ImperialUnits.MILES_PER_HOUR, "gustspeed"); - createChannelHandler(WIND_MAX_GUST, QuantityType.class, ImperialUnits.MILES_PER_HOUR, "dailygust"); - } else if ("1".equals(windUnit)) { - createChannelHandler(WIND_AVERAGE_SPEED, QuantityType.class, SIUnits.KILOMETRE_PER_HOUR, "avgwind"); - createChannelHandler(WIND_SPEED, QuantityType.class, SIUnits.KILOMETRE_PER_HOUR, "windspeed"); - createChannelHandler(WIND_GUST, QuantityType.class, SIUnits.KILOMETRE_PER_HOUR, "gustspeed"); - createChannelHandler(WIND_MAX_GUST, QuantityType.class, SIUnits.KILOMETRE_PER_HOUR, "dailygust"); - } else if ("0".equals(windUnit)) { - createChannelHandler(WIND_AVERAGE_SPEED, QuantityType.class, Units.METRE_PER_SECOND, "avgwind"); - createChannelHandler(WIND_SPEED, QuantityType.class, Units.METRE_PER_SECOND, "windspeed"); - createChannelHandler(WIND_GUST, QuantityType.class, Units.METRE_PER_SECOND, "gustspeed"); - createChannelHandler(WIND_MAX_GUST, QuantityType.class, Units.METRE_PER_SECOND, "dailygust"); - } else { - logger.warn( - "The IP Observer is sending a wind format the binding does not support. Select one of the other units."); - } - - if ("1".equals(solarUnit)) { - createChannelHandler(SOLAR_RADIATION, QuantityType.class, Units.IRRADIANCE, "solarrad"); - } else if ("0".equals(solarUnit)) { - createChannelHandler(SOLAR_RADIATION, QuantityType.class, Units.LUX, "solarrad"); - } else { - logger.warn( - "The IP Observer is sending fc (Foot Candles) for the solar radiation. Select one of the other units."); - } - - if ("0".equals(pressureUnit)) { - createChannelHandler(ABS_PRESSURE, QuantityType.class, MetricPrefix.HECTO(SIUnits.PASCAL), "AbsPress"); - createChannelHandler(REL_PRESSURE, QuantityType.class, MetricPrefix.HECTO(SIUnits.PASCAL), "RelPress"); - } else if ("1".equals(pressureUnit)) { - createChannelHandler(ABS_PRESSURE, QuantityType.class, ImperialUnits.INCH_OF_MERCURY, "AbsPress"); - createChannelHandler(REL_PRESSURE, QuantityType.class, ImperialUnits.INCH_OF_MERCURY, "RelPress"); - } else if ("2".equals(pressureUnit)) { - createChannelHandler(ABS_PRESSURE, QuantityType.class, Units.MILLIMETRE_OF_MERCURY, "AbsPress"); - createChannelHandler(REL_PRESSURE, QuantityType.class, Units.MILLIMETRE_OF_MERCURY, "RelPress"); - } - - createChannelHandler(WIND_DIRECTION, QuantityType.class, Units.DEGREE_ANGLE, "windir"); - createChannelHandler(INDOOR_HUMIDITY, DecimalType.class, Units.PERCENT, "inHumi"); - createChannelHandler(OUTDOOR_HUMIDITY, DecimalType.class, Units.PERCENT, "outHumi"); - // The units for the following are ignored as they are not a QuantityType.class - createChannelHandler(UV, DecimalType.class, SIUnits.CELSIUS, "uv"); - createChannelHandler(UV_INDEX, DecimalType.class, SIUnits.CELSIUS, "uvi"); - // was outBattSta1 so some units may use this instead? - createChannelHandler(OUTDOOR_BATTERY, StringType.class, Units.PERCENT, "outBattSta"); - createChannelHandler(OUTDOOR_BATTERY, StringType.class, Units.PERCENT, "outBattSta1"); - createChannelHandler(INDOOR_BATTERY, StringType.class, Units.PERCENT, "inBattSta"); - createChannelHandler(LAST_UPDATED_TIME, DateTimeType.class, SIUnits.CELSIUS, "CurrTime"); - } - - @Override - public void initialize() { - config = getConfigAs(IpObserverConfiguration.class); - updateStatus(ThingStatus.UNKNOWN); - pollingFuture = scheduler.scheduleWithFixedDelay(this::pollStation, 1, config.pollTime, TimeUnit.SECONDS); - } - - @Override - public void dispose() { - channelHandlers.clear(); - ScheduledFuture localFuture = pollingFuture; - if (localFuture != null) { - localFuture.cancel(true); - localFuture = null; - } - } -} diff --git a/bundles/org.openhab.binding.ipobserver/src/main/java/org/openhab/binding/ipobserver/internal/IpObserverHandlerFactory.java b/bundles/org.openhab.binding.ipobserver/src/main/java/org/openhab/binding/ipobserver/internal/IpObserverHandlerFactory.java deleted file mode 100644 index df0bf9fb2b06..000000000000 --- a/bundles/org.openhab.binding.ipobserver/src/main/java/org/openhab/binding/ipobserver/internal/IpObserverHandlerFactory.java +++ /dev/null @@ -1,68 +0,0 @@ -/** - * 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.ipobserver.internal; - -import static org.openhab.binding.ipobserver.internal.IpObserverBindingConstants.THING_WEATHER_STATION; - -import java.util.Set; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.jetty.client.HttpClient; -import org.openhab.core.io.net.http.HttpClientFactory; -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 IpObserverHandlerFactory} is responsible for creating things and thing - * handlers. - * - * @author Matthew Skinner - Initial contribution - */ -@NonNullByDefault -@Component(configurationPid = "binding.ipobserver", service = ThingHandlerFactory.class) -public class IpObserverHandlerFactory extends BaseThingHandlerFactory { - private static final Set SUPPORTED_THING_TYPES_UIDS = Set.of(THING_WEATHER_STATION); - protected final HttpClient httpClient; - - @Activate - public IpObserverHandlerFactory(@Reference HttpClientFactory httpClientFactory) { - this.httpClient = httpClientFactory.getCommonHttpClient(); - } - - protected HttpClient getHttpClient() { - return httpClient; - } - - @Override - public boolean supportsThingType(ThingTypeUID thingTypeUID) { - return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); - } - - @Override - protected @Nullable ThingHandler createHandler(Thing thing) { - ThingTypeUID thingTypeUID = thing.getThingTypeUID(); - - if (THING_WEATHER_STATION.equals(thingTypeUID)) { - return new IpObserverHandler(thing, httpClient); - } - - return null; - } -} diff --git a/bundles/org.openhab.binding.ipobserver/src/main/resources/OH-INF/binding/binding.xml b/bundles/org.openhab.binding.ipobserver/src/main/resources/OH-INF/binding/binding.xml deleted file mode 100644 index 2b25e9bbda34..000000000000 --- a/bundles/org.openhab.binding.ipobserver/src/main/resources/OH-INF/binding/binding.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - IpObserver Binding - This is the binding for weather stations marketed under many brands that come with or have an IpObserver - station connected. - - diff --git a/bundles/org.openhab.binding.ipobserver/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.ipobserver/src/main/resources/OH-INF/thing/thing-types.xml deleted file mode 100644 index 8fdd9f2e3e69..000000000000 --- a/bundles/org.openhab.binding.ipobserver/src/main/resources/OH-INF/thing/thing-types.xml +++ /dev/null @@ -1,249 +0,0 @@ - - - - - - Use for any weather station sold under multiple brands that come with an IP Observer unit. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - network-address - - Hostname or IP for the IP Observer - 192.168.1.243 - - - - Time in seconds between each Scan of the livedata.htm from the ObserverIP - 20 - - - - Time in milliseconds to wait for a reply before rebooting the IP Observer. A value of 0 disables this - feature allowing you to manually trigger or use a rule to handle the reboots - 2000 - - - - - Number:Time - - How many milliseconds it took to fetch the sensor readings from livedata.htm - - - - Number:Temperature - - Current Temperature Indoors - Temperature - - Measurement - Temperature - - - - - Number:Dimensionless - - Current Humidity Indoors - Humidity - - Measurement - Humidity - - - - - Number:Pressure - - Absolute Current Pressure - Pressure - - Measurement - Pressure - - - - - Number:Pressure - - Relative Current Pressure - Pressure - - Measurement - Pressure - - - - - Number:Intensity - - Solar Radiation - Sun - - Measurement - Light - - - - - Number - - UV - Sun - - Measurement - Light - - - - - Number - - UV Index - Sun - - Measurement - Light - - - - - Number:Speed - - Average Wind Speed - Wind - - Measurement - Wind - - - - - Number:Speed - - Wind Speed - Wind - - Measurement - Wind - - - - - Number:Speed - - Wind Gust - Wind - - Measurement - Wind - - - - - Number:Speed - - Max wind gust for today - Wind - - Measurement - Wind - - - - - Number:Length - - How much rain will fall in an Hour if the rate continues - Rain - - Measurement - Rain - - - - - Number:Length - - Rain since Midnight - Rain - - Measurement - Rain - - - - - Number:Length - - Weekly Rain - Rain - - Measurement - Rain - - - - - Number:Length - - Rain since 12:00 on the 1st of this month - Rain - - Measurement - Rain - - - - - Number:Length - - Total rain since 12:00 on 1st Jan - Rain - - Measurement - Rain - - - - - DateTime - - Time of the last livedata scrape - Time - - Measurement - Timestamp - - - - diff --git a/bundles/pom.xml b/bundles/pom.xml index fa0385512abd..a188dc006d72 100644 --- a/bundles/pom.xml +++ b/bundles/pom.xml @@ -159,7 +159,6 @@ org.openhab.binding.innogysmarthome org.openhab.binding.insteon org.openhab.binding.ipcamera - org.openhab.binding.ipobserver org.openhab.binding.intesis org.openhab.binding.ipp org.openhab.binding.irobot