From 3c1cbaa769c9fafa7b5f1bd6dd07f46bc262b19d Mon Sep 17 00:00:00 2001 From: Jacob Laursen Date: Fri, 2 Jun 2023 12:29:42 +0200 Subject: [PATCH 01/41] [surepetcare] Adapt blocked user agent (#15047) * Adapt blocked user agent Fixes #15046 Signed-off-by: Jacob Laursen --- .../surepetcare/internal/SurePetcareAPIHelper.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/SurePetcareAPIHelper.java b/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/SurePetcareAPIHelper.java index 9328713d8d8de..e9a1747384e30 100644 --- a/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/SurePetcareAPIHelper.java +++ b/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/SurePetcareAPIHelper.java @@ -63,8 +63,6 @@ public class SurePetcareAPIHelper { private final Logger logger = LoggerFactory.getLogger(SurePetcareAPIHelper.class); - private static final String API_USER_AGENT = "Mozilla/5.0 (Linux; Android 7.0; SM-G930F Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/64.0.3282.137 Mobile Safari/537.36"; - private static final String API_URL = "https://app.api.surehub.io/api"; private static final String TOPOLOGY_URL = API_URL + "/me/start"; private static final String PET_BASE_URL = API_URL + "/pet"; @@ -78,9 +76,15 @@ public class SurePetcareAPIHelper { private String username = ""; private String password = ""; + private final String userAgent; + private @NonNullByDefault({}) HttpClient httpClient; private SurePetcareTopology topologyCache = new SurePetcareTopology(); + public SurePetcareAPIHelper() { + userAgent = "openHAB/" + org.openhab.core.OpenHAB.getVersion(); + } + /** * Sets the httpClient object to be used for API calls to Sure Petcare. * @@ -369,7 +373,7 @@ private void setConnectionHeaders(Request request) throws ProtocolException { request.header(HttpHeader.AUTHORIZATION, "Bearer " + authenticationToken); request.header(HttpHeader.CONNECTION, "keep-alive"); request.header(HttpHeader.CONTENT_TYPE, "application/json; utf-8"); - request.header(HttpHeader.USER_AGENT, API_USER_AGENT); + request.header(HttpHeader.USER_AGENT, userAgent); request.header(HttpHeader.REFERER, "https://surepetcare.io/"); request.header("Origin", "https://surepetcare.io"); request.header("Referer", "https://surepetcare.io"); From 93b888ad31bb97caa30adb0bd0218050d5773959 Mon Sep 17 00:00:00 2001 From: Karel Goderis Date: Fri, 2 Jun 2023 21:57:32 +0200 Subject: [PATCH 02/41] [oceanic] Remove dependency on RXTX for serial communication (#15044) Signed-off-by: Karel Goderis --- bundles/org.openhab.binding.oceanic/pom.xml | 4 - .../internal/OceanicHandlerFactory.java | 12 +- .../handler/NetworkOceanicThingHandler.java | 10 +- .../handler/SerialOceanicThingHandler.java | 122 ++++++++---------- 4 files changed, 69 insertions(+), 79 deletions(-) diff --git a/bundles/org.openhab.binding.oceanic/pom.xml b/bundles/org.openhab.binding.oceanic/pom.xml index da59973c9a305..de8af3662dd11 100644 --- a/bundles/org.openhab.binding.oceanic/pom.xml +++ b/bundles/org.openhab.binding.oceanic/pom.xml @@ -14,8 +14,4 @@ openHAB Add-ons :: Bundles :: Oceanic Binding - - gnu.io;version="[3.12,6)" - - diff --git a/bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/OceanicHandlerFactory.java b/bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/OceanicHandlerFactory.java index 6e4dfee7faa9b..7496b00bc2076 100644 --- a/bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/OceanicHandlerFactory.java +++ b/bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/OceanicHandlerFactory.java @@ -21,12 +21,15 @@ import org.openhab.binding.oceanic.internal.handler.NetworkOceanicThingHandler; import org.openhab.binding.oceanic.internal.handler.SerialOceanicThingHandler; +import org.openhab.core.io.transport.serial.SerialPortManager; 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 OceanicHandlerFactory} is responsible for creating things and @@ -40,6 +43,13 @@ public class OceanicHandlerFactory extends BaseThingHandlerFactory { private static final Set SUPPORTED_THING_TYPES_UIDS = Collections .unmodifiableSet(Stream.of(THING_TYPE_SERIAL, THING_TYPE_NETWORK).collect(Collectors.toSet())); + private final SerialPortManager serialPortManager; + + @Activate + public OceanicHandlerFactory(final @Reference SerialPortManager serialPortManager) { + this.serialPortManager = serialPortManager; + } + @Override public boolean supportsThingType(ThingTypeUID thingTypeUID) { return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); @@ -50,7 +60,7 @@ protected ThingHandler createHandler(Thing thing) { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); if (thingTypeUID.equals(THING_TYPE_SERIAL)) { - return new SerialOceanicThingHandler(thing); + return new SerialOceanicThingHandler(thing, serialPortManager); } if (thingTypeUID.equals(THING_TYPE_NETWORK)) { return new NetworkOceanicThingHandler(thing); diff --git a/bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/handler/NetworkOceanicThingHandler.java b/bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/handler/NetworkOceanicThingHandler.java index 1722a082fd70a..a2def1158e571 100644 --- a/bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/handler/NetworkOceanicThingHandler.java +++ b/bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/handler/NetworkOceanicThingHandler.java @@ -63,10 +63,12 @@ public void initialize() { try { socket = new Socket(config.ipAddress, config.portNumber); - socket.setSoTimeout(REQUEST_TIMEOUT); - outputStream = socket.getOutputStream(); - inputStream = socket.getInputStream(); - updateStatus(ThingStatus.ONLINE); + if (socket != null) { + socket.setSoTimeout(REQUEST_TIMEOUT); + outputStream = socket.getOutputStream(); + inputStream = socket.getInputStream(); + updateStatus(ThingStatus.ONLINE); + } } catch (UnknownHostException e) { logger.error("An exception occurred while resolving host {}:{} : '{}'", config.ipAddress, config.portNumber, e.getMessage()); diff --git a/bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/handler/SerialOceanicThingHandler.java b/bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/handler/SerialOceanicThingHandler.java index b2444bcbcba02..125747e2bb356 100644 --- a/bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/handler/SerialOceanicThingHandler.java +++ b/bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/handler/SerialOceanicThingHandler.java @@ -17,45 +17,47 @@ import java.io.OutputStream; import java.text.SimpleDateFormat; import java.util.Arrays; -import java.util.Enumeration; +import java.util.TooManyListenersException; +import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; import org.openhab.binding.oceanic.internal.SerialOceanicBindingConfiguration; import org.openhab.binding.oceanic.internal.Throttler; +import org.openhab.core.io.transport.serial.PortInUseException; +import org.openhab.core.io.transport.serial.SerialPort; +import org.openhab.core.io.transport.serial.SerialPortEvent; +import org.openhab.core.io.transport.serial.SerialPortEventListener; +import org.openhab.core.io.transport.serial.SerialPortIdentifier; +import org.openhab.core.io.transport.serial.SerialPortManager; +import org.openhab.core.io.transport.serial.UnsupportedCommOperationException; import org.openhab.core.thing.Thing; import org.openhab.core.thing.ThingStatus; import org.openhab.core.thing.ThingStatusDetail; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import gnu.io.CommPortIdentifier; -import gnu.io.NoSuchPortException; -import gnu.io.PortInUseException; -import gnu.io.RXTXCommDriver; -import gnu.io.SerialPort; -import gnu.io.UnsupportedCommOperationException; - /** * The {@link SerialOceanicThingHandler} implements {@link OceanicThingHandler} for an Oceanic water softener that is * directly connected to a serial port of the openHAB host * * @author Karel Goderis - Initial contribution */ -public class SerialOceanicThingHandler extends OceanicThingHandler { +public class SerialOceanicThingHandler extends OceanicThingHandler implements SerialPortEventListener { private static final long REQUEST_TIMEOUT = 10000; private static final int BAUD = 19200; private final Logger logger = LoggerFactory.getLogger(SerialOceanicThingHandler.class); + private final SerialPortManager serialPortManager; private SerialPort serialPort; - private CommPortIdentifier portId; private InputStream inputStream; private OutputStream outputStream; private SerialPortReader readerThread; - public SerialOceanicThingHandler(Thing thing) { + public SerialOceanicThingHandler(Thing thing, SerialPortManager serialPortManager) { super(thing); + this.serialPortManager = serialPortManager; } @Override @@ -65,73 +67,46 @@ public void initialize() { SerialOceanicBindingConfiguration config = getConfigAs(SerialOceanicBindingConfiguration.class); if (serialPort == null && config.port != null) { - if (portId == null) { - try { - RXTXCommDriver rxtxCommDriver = new RXTXCommDriver(); - rxtxCommDriver.initialize(); - CommPortIdentifier.addPortName(config.port, CommPortIdentifier.PORT_RAW, rxtxCommDriver); - portId = CommPortIdentifier.getPortIdentifier(config.port); - } catch (NoSuchPortException e) { - logger.error("An exception occurred while setting up serial port '{}' : '{}'", config.port, - e.getMessage(), e); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, - "Could not setup serial port " + serialPort + ": " + e.getMessage()); - return; - } - } - if (portId != null) { - try { - serialPort = portId.open(this.getThing().getUID().getBindingId(), 2000); - } catch (PortInUseException e) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, - "Could not open serial port " + serialPort + ": " + e.getMessage()); - return; - } + SerialPortIdentifier portIdentifier = serialPortManager.getIdentifier(config.port); - try { - inputStream = serialPort.getInputStream(); - } catch (IOException e) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, - "Could not open serial port " + serialPort + ": " + e.getMessage()); - return; - } + if (portIdentifier == null) { + String availablePorts = serialPortManager.getIdentifiers().map(id -> id.getName()) + .collect(Collectors.joining(System.lineSeparator())); + String description = String.format("Serial port '%s' could not be found. Available ports are:%n%s", + config.port, availablePorts); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, description); + return; + } - serialPort.notifyOnDataAvailable(true); + try { + logger.info("Connecting to the Oceanic water softener using {}.", config.port); + serialPort = portIdentifier.open(this.getThing().getUID().getBindingId(), 2000); - try { - serialPort.setSerialPortParams(BAUD, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, - SerialPort.PARITY_NONE); - serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_NONE); - } catch (UnsupportedCommOperationException e) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, - "Could not configure serial port " + serialPort + ": " + e.getMessage()); - return; - } + serialPort.setSerialPortParams(BAUD, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, + SerialPort.PARITY_NONE); + serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_NONE); + serialPort.enableReceiveThreshold(1); + serialPort.disableReceiveTimeout(); - try { - outputStream = serialPort.getOutputStream(); - updateStatus(ThingStatus.ONLINE); - } catch (IOException e) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, - "Could not communicate with the serial port " + serialPort + ": " + e.getMessage()); - return; - } + inputStream = serialPort.getInputStream(); + outputStream = serialPort.getOutputStream(); + + serialPort.addEventListener(this); + serialPort.notifyOnDataAvailable(true); readerThread = new SerialPortReader(inputStream); readerThread.start(); - } else { - StringBuilder sb = new StringBuilder(); - @SuppressWarnings("rawtypes") - Enumeration portList = CommPortIdentifier.getPortIdentifiers(); - while (portList.hasMoreElements()) { - CommPortIdentifier id = (CommPortIdentifier) portList.nextElement(); - if (id.getPortType() == CommPortIdentifier.PORT_SERIAL) { - sb.append(id.getName() + "\n"); - } - } - logger.error("Serial port '{}' could not be found. Available ports are:\n {}", config.port, sb); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR); + + updateStatus(ThingStatus.ONLINE); + + } catch (PortInUseException portInUseException) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Port in use: " + config.port); + } catch (UnsupportedCommOperationException | IOException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Communication error"); + } catch (TooManyListenersException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "Too many listeners to serial port."); } } } @@ -217,6 +192,13 @@ protected String requestResponse(String commandAsString) { } } + @Override + public void serialEvent(SerialPortEvent serialPortEvent) { + if (logger.isTraceEnabled()) { + logger.trace("Received a serial port event : {}", serialPortEvent.getEventType()); + } + } + public class SerialPortReader extends Thread { private boolean interrupted = false; From 8d0c9f27f81c23d33670fb6cfab64b8198bee502 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=B8=D0=BB=D1=8F=D0=BD=20=D0=9F=D0=B0=D0=BB=D0=B0?= =?UTF-8?q?=D1=83=D0=B7=D0=BE=D0=B2?= Date: Mon, 5 Jun 2023 18:51:19 +0200 Subject: [PATCH 03/41] [systeminfo] README: spell unlinked channels do not get updates (#15035) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit typos: insert space after comma cf. https://github.com/openhab/openhab-addons/issues/15007 Co-authored-by: Дилян Палаузов --- bundles/org.openhab.binding.systeminfo/README.md | 4 +++- .../systeminfo/internal/model/SysteminfoInterface.java | 2 +- .../src/main/resources/OH-INF/i18n/systeminfo.properties | 2 +- .../src/main/resources/OH-INF/thing/channels.xml | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/bundles/org.openhab.binding.systeminfo/README.md b/bundles/org.openhab.binding.systeminfo/README.md index 4731686e4c1d0..3904626d7a2da 100644 --- a/bundles/org.openhab.binding.systeminfo/README.md +++ b/bundles/org.openhab.binding.systeminfo/README.md @@ -11,7 +11,7 @@ The system information binding provides operating system and hardware informatio - Battery information - estimated remaining time, capacity, name; - Sensors information - CPU voltage and temperature, fan speeds; - Display information; -- Network IP,name and adapter name, mac, data sent and received, packets sent and received; +- Network IP, name and adapter name, mac, data sent and received, packets sent and received; - Process information - size of RAM memory used, CPU load, process name, path, number of threads. The binding uses the [OSHI](https://github.com/oshi/oshi) library to access this information regardless of the underlying OS and hardware. @@ -51,6 +51,8 @@ That means that by default configuration: - channels with priority set to 'Medium' are updated every minute - channels with priority set to 'Low' are updated only at initialization or if the `REFRESH` command is sent to the channel. +Channels, not linked to an item, do not get updates, and do not periodically consume resources. + For more info see [channel configuration](#channel-configuration) ## Channels diff --git a/bundles/org.openhab.binding.systeminfo/src/main/java/org/openhab/binding/systeminfo/internal/model/SysteminfoInterface.java b/bundles/org.openhab.binding.systeminfo/src/main/java/org/openhab/binding/systeminfo/internal/model/SysteminfoInterface.java index fbe53cd253334..9668ae18d8c09 100644 --- a/bundles/org.openhab.binding.systeminfo/src/main/java/org/openhab/binding/systeminfo/internal/model/SysteminfoInterface.java +++ b/bundles/org.openhab.binding.systeminfo/src/main/java/org/openhab/binding/systeminfo/internal/model/SysteminfoInterface.java @@ -42,7 +42,7 @@ public interface SysteminfoInterface { // Operating system info /** - * Get the Family of the operating system /e.g. Windows,Unix,.../ + * Get the Family of the operating system /e.g. Windows, Unix,.../ */ StringType getOsFamily(); diff --git a/bundles/org.openhab.binding.systeminfo/src/main/resources/OH-INF/i18n/systeminfo.properties b/bundles/org.openhab.binding.systeminfo/src/main/resources/OH-INF/i18n/systeminfo.properties index 3cfbf63da7d8a..2768da5b39931 100644 --- a/bundles/org.openhab.binding.systeminfo/src/main/resources/OH-INF/i18n/systeminfo.properties +++ b/bundles/org.openhab.binding.systeminfo/src/main/resources/OH-INF/i18n/systeminfo.properties @@ -67,7 +67,7 @@ channel-type.systeminfo.ip.description = Host IP address of the network channel-type.systeminfo.load.label = Load channel-type.systeminfo.load.description = Load in percent channel-type.systeminfo.loadAverage.label = Load Average -channel-type.systeminfo.loadAverage.description = Load as a number of processes for the last 1,5 or 15 minutes +channel-type.systeminfo.loadAverage.description = Load as a number of processes for the last 1, 5 or 15 minutes channel-type.systeminfo.load_process.label = Load channel-type.systeminfo.load_process.description = Load in percent channel-type.systeminfo.mac.label = Mac Address diff --git a/bundles/org.openhab.binding.systeminfo/src/main/resources/OH-INF/thing/channels.xml b/bundles/org.openhab.binding.systeminfo/src/main/resources/OH-INF/thing/channels.xml index 150075edc5682..193a734d0d45b 100644 --- a/bundles/org.openhab.binding.systeminfo/src/main/resources/OH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.systeminfo/src/main/resources/OH-INF/thing/channels.xml @@ -327,7 +327,7 @@ Number - Load as a number of processes for the last 1,5 or 15 minutes + Load as a number of processes for the last 1, 5 or 15 minutes From 214e31b1b384b50e08400def6661036f4a92d63e Mon Sep 17 00:00:00 2001 From: openhab-bot Date: Wed, 7 Jun 2023 22:43:29 +0200 Subject: [PATCH 04/41] New translations shelly.properties (German) (#15055) --- .../OH-INF/i18n/shelly_de.properties | 33 ++++++++++++++++--- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/i18n/shelly_de.properties b/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/i18n/shelly_de.properties index 2cc80c8fcf98a..2c0b185e267d8 100644 --- a/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/i18n/shelly_de.properties +++ b/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/i18n/shelly_de.properties @@ -88,24 +88,29 @@ thing-type.shelly.shellytrv.description = Shelly TRV (Heizungsventil, batteriebe thing-type.shelly.shellyix3.description = Shelly ix3 (Steuergerät mit 3 Eingängen) thing-type.shelly.shellypludht.description = Regal Plus HT - Temperatur und Feuchtigkeitssensor -# Plus/Pro devices +# Plus Devices thing-type.shelly.shellyplus1.description = Shelly Plus 1 - 1x Relay thing-type.shelly.shellyplus1pm.description = Shelly Plus 1PM - 1xRelais + Strommesser thing-type.shelly.shellyplus2-relay.description = Shelly Plus 2PM - 2x Relais mit Strommesser thing-type.shelly.shellyplus2pm-roller.description = Shepply Plus 2PM im Rollladenmodus +thing-type.shelly.shellyplusplug.description = Shelly Plus Plug S/IT/UK/US . Steckdose mit Strommesser thing-type.shelly.shellyplusht.description = Shelly Plus HT - Feuchtigkeits- und Temperatursensor mit Anzeigefeld thing-type.shelly.shellyplusi4.description = Shelly Plus i4 mit 4 Analog-Eingängen thing-type.shelly.shellyplusi4dc.description = Shelly Plus i4DC mit 4 Gleichstrom-Eingängen + +# Pro Devices thing-type.shelly.shellypro1.description = Shelly Pro 1 mit 1xRelais thing-type.shelly.shellypro1pm.description = Shelly Pro 1PM mit 1xRelais und Strommesser thing-type.shelly.shellypro2-relay.description = Shelly Pro 2 mit 2xRelais thing-type.shelly.shellypro2pm-relay.description= Shelly Pro 2PM mit 2xRelais und Strommesser thing-type.shelly.shellypro2pm-roller.description = Shelly Pro 2PM im Rollladenmodus thing-type.shelly.shellypro3.description = Shelly Pro 3 mit 3 Relais +thing-type.shelly.shellypro3em.description = Shelly Pro 3EM - 3-fach Relais mit Strommesser thing-type.shelly.shellypro4pm.description = Shelly Pro 4PM mit 4 Relais und Strommesser # Plus/Pro devices +thing-type.shelly.shellyplussmoke.description = Shelly Plus Smoke - Rauchmelder mit Alarm thing-type.shelly.shellypro2-roller.description = Shelly Pro 2 im Rollladenmodus # thing config - shellydevice @@ -218,6 +223,10 @@ channel-type.shelly.temperature2.label = Temperatur 2 channel-type.shelly.temperature2.description = Temperatur des externen Sensors 2 channel-type.shelly.temperature3.label = Temperatur 3 channel-type.shelly.temperature3.description = Temperatur des externen Sensors 3 +channel-type.shelly.temperature4.label = Temperatur 4 +channel-type.shelly.temperature4.description = Temperatur des externen Sensors \#4 +channel-type.shelly.temperature5.label = Temperatur 5 +channel-type.shelly.temperature6.description = Temperatur des externen Sensors \#5 channel-type.shelly.targetTemp.label = Zieltemperatur channel-type.shelly.targetTemp.description = Zieltemperatur in °C, die im Auto-Temperaturmodus erreicht werden soll channel-type.shelly.humidity.label = Luftfeuchtigkeit @@ -272,6 +281,8 @@ channel-type.shelly.lastPower1.label = Schnitt letzte Minunte channel-type.shelly.lastPower1.description = Stromverbrauch der letzten Minute, gerundet channel-type.shelly.meterTotal.label = Gesamtverbrauch channel-type.shelly.meterTotal.description = Gesamtverbrauch in kWh seit das Gerät eingeschaltet wurde (wird beim Neustart zurückgesetzt) +channel-type.shelly.meterResetTotals.label = Gesamtwerte zurücksetzen +channel-type.shelly.meterResetTotals.description = Setzt die gesammelten Messwerte zurück channel-type.shelly.meterReturned.label = Einspeisung channel-type.shelly.meterReturned.description = Einspeisung in kWh channel-type.shelly.meterVoltage.label = Spannung @@ -324,16 +335,14 @@ channel-type.shelly.colorEffectRGBW2.option.2 = Studuale Änderung channel-type.shelly.colorEffectRGBW2.option.3 = Blitz channel-type.shelly.sensorTemp.label = Temperatur channel-type.shelly.sensorTemp.description = Die vom Sensor gelesene Temperatur -channel-type.shelly.sensorExtTemp.label = Temperatur -channel-type.shelly.sensorExtTemp.description = Die vom Sensor gelesene Temperatur -channel-type.shelly.sensorExtHum.label = Luftfeuchtigkeit -channel-type.shelly.sensorExtHum.description = Relative Luftfeuchtigkeit in Prozent (0..100%) vom externen Sensor channel-type.shelly.sensorHumidity.label = Luftfeuchtigkeit channel-type.shelly.sensorHumidity.description = Relative Luftfeuchtigkeit (0..100%) channel-type.shelly.sensorFlood.label = Feuchtigkeitsalarm channel-type.shelly.sensorFlood.description = Zeigt Flut-/Wassererkennung beim Einschalten an channel-type.shelly.sensorSmoke.label = Rauchmelder channel-type.shelly.sensorSmoke.description = Zeigt die Raucherkennung beim Einschalten an +channel-type.shelly.sensorMute.label = Alarm Stummschaltung +channel-type.shelly.sensorMute.description = Aktivieret/deaktiviert den akkustischen Alarm (ON\=stummgeschaltet) channel-type.shelly.sensorLux.label = Lux channel-type.shelly.sensorLux.description = Helligkeit vom Sensor (Lux) channel-type.shelly.sensorIllumination.label = Lichtintensität @@ -354,6 +363,16 @@ channel-type.shelly.sensorVibration.label = Vibration channel-type.shelly.sensorVibration.description = Vibration beim Einschalten erkannt channel-type.shelly.sensorMotion.label = Bewegung channel-type.shelly.sensorMotion.description = Vibration beim Einschalten erkannt +channel-type.shelly.sensorExtTemp.label = Temperatur +channel-type.shelly.sensorExtTemp.description = Die vom Sensor gelesene Temperatur +channel-type.shelly.sensorExtHum.label = Luftfeuchtigkeit +channel-type.shelly.sensorExtHum.description = Relative Luftfeuchtigkeit in Prozent (0..100%) vom externen Sensor +channel-type.shelly.sensorExtVolt.label = Spannung +channel-type.shelly.sensorExtVolt.description = Spannung vom externen Sensor +channel-type.shelly.sensorExtDigitalInput.label = Digitaler Eingang +channel-type.shelly.sensorExtDigitalInput.description = Status des digitalen Eingangs mit Add-on verbunden +channel-type.shelly.sensorExtAnalogInput.label = Analoger Eingang +channel-type.shelly.sensorExtAnalogInput.description = Prozentsatz des Analogeingangs vom externen Sensor channel-type.shelly.motionActive.label = Bewegungssensor aktiv channel-type.shelly.motionActive.description = Zeigt an, ob die Bewegungserkennung aktiv oder pausiert ist channel-type.shelly.motionTimestamp.label = Letzte Bewegung @@ -374,6 +393,10 @@ channel-type.shelly.sensorContact.label = Zustand channel-type.shelly.sensorContact.description = Status des Kontakts (offen/geschlossen) channel-type.shelly.sensorContact.state.option.OPEN = Offen channel-type.shelly.sensorContact.state.option.CLOSED = Geschlossen +channel-type.shelly.sensorOpen.label = Offen +channel-type.shelly.sensorOpen.description = OPEN oder CLOSED +channel-type.shelly.sensorOpen.state.option.OPEN = Offen +channel-type.shelly.sensorOpen.state.option.CLOSED = Geschlossen channel-type.shelly.sensorState.label = Sensorstatus channel-type.shelly.sensorState.description = Sensorstatus (Warm-Up/Normal/Fault/Unknown) channel-type.shelly.sensorState.state.option.warmup = Aufwärmen From ddffda3522e9eecbba66e8b227c51ca5c9a90529 Mon Sep 17 00:00:00 2001 From: Matthew Skinner Date: Thu, 8 Jun 2023 23:56:27 +1000 Subject: [PATCH 05/41] Bump Netty version to 4.1.92.Final (#14878) Update to latest netty to ensure latest improvements and security patches are applied. https://netty.io/news/2023/04/25/4-1-92-Final.html * Adapt itests to new netty release Signed-off-by: Matthew Skinner Also-by: Holger Friedrich --- .../itest.bndrun | 24 +++++++++--------- .../itest.bndrun | 24 +++++++++--------- .../itest.bndrun | 25 +++++++++---------- pom.xml | 2 +- 4 files changed, 37 insertions(+), 38 deletions(-) diff --git a/itests/org.openhab.binding.mqtt.homeassistant.tests/itest.bndrun b/itests/org.openhab.binding.mqtt.homeassistant.tests/itest.bndrun index 22b815aed12d7..ddf645d624d13 100644 --- a/itests/org.openhab.binding.mqtt.homeassistant.tests/itest.bndrun +++ b/itests/org.openhab.binding.mqtt.homeassistant.tests/itest.bndrun @@ -37,18 +37,8 @@ Import-Package: \ org.apache.servicemix.specs.activation-api-1.2.1;version='[1.2.1,1.2.2)',\ com.google.dagger;version='[2.27.0,2.27.1)',\ com.hivemq.client.mqtt;version='[1.2.2,1.2.3)',\ - io.netty.buffer;version='[4.1.72,4.1.73)',\ - io.netty.codec;version='[4.1.72,4.1.73)',\ io.netty.codec-http;version='[4.1.59,4.1.60)',\ - io.netty.codec-socks;version='[4.1.72,4.1.73)',\ - io.netty.common;version='[4.1.72,4.1.73)',\ - io.netty.handler;version='[4.1.72,4.1.73)',\ - io.netty.handler-proxy;version='[4.1.72,4.1.73)',\ - io.netty.resolver;version='[4.1.72,4.1.73)',\ - io.netty.tcnative-classes;version='[2.0.46,2.0.47)',\ - io.netty.transport;version='[4.1.72,4.1.73)',\ io.netty.transport-native-epoll;version='[4.1.59,4.1.60)',\ - io.netty.transport-native-unix-common;version='[4.1.59,4.1.60)',\ io.reactivex.rxjava2.rxjava;version='[2.2.19,2.2.20)',\ jakarta.annotation-api;version='[2.0.0,2.0.1)',\ jakarta.inject.jakarta.inject-api;version='[2.0.0,2.0.1)',\ @@ -66,7 +56,6 @@ Import-Package: \ com.h2database.mvstore;version='[1.4.199,1.4.200)',\ com.zaxxer.HikariCP;version='[2.4.7,2.4.8)',\ io.dropwizard.metrics.core;version='[3.2.2,3.2.3)',\ - io.netty.codec-mqtt;version='[4.1.72,4.1.73)',\ ch.qos.logback.classic;version='[1.2.11,1.2.12)',\ ch.qos.logback.core;version='[1.2.11,1.2.12)',\ biz.aQute.tester.junit-platform;version='[6.4.0,6.4.1)',\ @@ -108,4 +97,15 @@ Import-Package: \ org.mockito.junit-jupiter;version='[4.11.0,4.11.1)',\ org.mockito.mockito-core;version='[4.11.0,4.11.1)',\ org.objenesis;version='[3.3.0,3.3.1)',\ - xstream;version='[1.4.20,1.4.21)' + xstream;version='[1.4.20,1.4.21)',\ + org.osgi.service.cm;version='[1.6.0,1.6.1)',\ + io.netty.buffer;version='[4.1.92,4.1.93)',\ + io.netty.codec;version='[4.1.92,4.1.93)',\ + io.netty.codec-mqtt;version='[4.1.92,4.1.93)',\ + io.netty.codec-socks;version='[4.1.92,4.1.93)',\ + io.netty.common;version='[4.1.92,4.1.93)',\ + io.netty.handler;version='[4.1.92,4.1.93)',\ + io.netty.handler-proxy;version='[4.1.92,4.1.93)',\ + io.netty.resolver;version='[4.1.92,4.1.93)',\ + io.netty.transport;version='[4.1.92,4.1.93)',\ + io.netty.transport-native-unix-common;version='[4.1.92,4.1.93)' diff --git a/itests/org.openhab.binding.mqtt.homie.tests/itest.bndrun b/itests/org.openhab.binding.mqtt.homie.tests/itest.bndrun index bfe7c6171b4ef..857ebf73d8fc9 100644 --- a/itests/org.openhab.binding.mqtt.homie.tests/itest.bndrun +++ b/itests/org.openhab.binding.mqtt.homie.tests/itest.bndrun @@ -37,18 +37,8 @@ Import-Package: \ org.apache.servicemix.specs.activation-api-1.2.1;version='[1.2.1,1.2.2)',\ com.google.dagger;version='[2.27.0,2.27.1)',\ com.hivemq.client.mqtt;version='[1.2.2,1.2.3)',\ - io.netty.buffer;version='[4.1.72,4.1.73)',\ - io.netty.codec;version='[4.1.72,4.1.73)',\ io.netty.codec-http;version='[4.1.59,4.1.60)',\ - io.netty.codec-socks;version='[4.1.72,4.1.73)',\ - io.netty.common;version='[4.1.72,4.1.73)',\ - io.netty.handler;version='[4.1.72,4.1.73)',\ - io.netty.handler-proxy;version='[4.1.72,4.1.73)',\ - io.netty.resolver;version='[4.1.72,4.1.73)',\ - io.netty.tcnative-classes;version='[2.0.46,2.0.47)',\ - io.netty.transport;version='[4.1.72,4.1.73)',\ io.netty.transport-native-epoll;version='[4.1.59,4.1.60)',\ - io.netty.transport-native-unix-common;version='[4.1.59,4.1.60)',\ io.reactivex.rxjava2.rxjava;version='[2.2.19,2.2.20)',\ jakarta.annotation-api;version='[2.0.0,2.0.1)',\ jakarta.inject.jakarta.inject-api;version='[2.0.0,2.0.1)',\ @@ -66,7 +56,6 @@ Import-Package: \ com.h2database.mvstore;version='[1.4.199,1.4.200)',\ com.zaxxer.HikariCP;version='[2.4.7,2.4.8)',\ io.dropwizard.metrics.core;version='[3.2.2,3.2.3)',\ - io.netty.codec-mqtt;version='[4.1.72,4.1.73)',\ ch.qos.logback.classic;version='[1.2.11,1.2.12)',\ ch.qos.logback.core;version='[1.2.11,1.2.12)',\ biz.aQute.tester.junit-platform;version='[6.4.0,6.4.1)',\ @@ -108,5 +97,16 @@ Import-Package: \ org.mockito.junit-jupiter;version='[4.11.0,4.11.1)',\ org.mockito.mockito-core;version='[4.11.0,4.11.1)',\ org.objenesis;version='[3.3.0,3.3.1)',\ - xstream;version='[1.4.20,1.4.21)' + xstream;version='[1.4.20,1.4.21)',\ + org.osgi.service.cm;version='[1.6.0,1.6.1)',\ + io.netty.buffer;version='[4.1.92,4.1.93)',\ + io.netty.codec;version='[4.1.92,4.1.93)',\ + io.netty.codec-mqtt;version='[4.1.92,4.1.93)',\ + io.netty.codec-socks;version='[4.1.92,4.1.93)',\ + io.netty.common;version='[4.1.92,4.1.93)',\ + io.netty.handler;version='[4.1.92,4.1.93)',\ + io.netty.handler-proxy;version='[4.1.92,4.1.93)',\ + io.netty.resolver;version='[4.1.92,4.1.93)',\ + io.netty.transport;version='[4.1.92,4.1.93)',\ + io.netty.transport-native-unix-common;version='[4.1.92,4.1.93)' diff --git a/itests/org.openhab.binding.mqtt.ruuvigateway.tests/itest.bndrun b/itests/org.openhab.binding.mqtt.ruuvigateway.tests/itest.bndrun index de5cf456acd75..29d6efc723f0e 100644 --- a/itests/org.openhab.binding.mqtt.ruuvigateway.tests/itest.bndrun +++ b/itests/org.openhab.binding.mqtt.ruuvigateway.tests/itest.bndrun @@ -38,23 +38,11 @@ Import-Package: \ com.zaxxer.HikariCP;version='[2.4.7,2.4.8)',\ io.dropwizard.metrics.core;version='[3.2.2,3.2.3)',\ io.methvin.directory-watcher;version='[0.17.1,0.17.2)',\ - io.netty.buffer;version='[4.1.72,4.1.73)',\ - io.netty.codec;version='[4.1.72,4.1.73)',\ io.netty.codec-http;version='[4.1.59,4.1.60)',\ - io.netty.codec-mqtt;version='[4.1.72,4.1.73)',\ - io.netty.codec-socks;version='[4.1.72,4.1.73)',\ - io.netty.common;version='[4.1.72,4.1.73)',\ - io.netty.handler;version='[4.1.72,4.1.73)',\ - io.netty.handler-proxy;version='[4.1.72,4.1.73)',\ - io.netty.resolver;version='[4.1.72,4.1.73)',\ - io.netty.tcnative-classes;version='[2.0.46,2.0.47)',\ - io.netty.transport;version='[4.1.72,4.1.73)',\ io.netty.transport-native-epoll;version='[4.1.59,4.1.60)',\ - io.netty.transport-native-unix-common;version='[4.1.59,4.1.60)',\ io.reactivex.rxjava2.rxjava;version='[2.2.19,2.2.20)',\ jakarta.annotation-api;version='[2.0.0,2.0.1)',\ jakarta.inject.jakarta.inject-api;version='[2.0.0,2.0.1)',\ - jakarta.ws.rs-api;version='[2.1.6,2.1.7)',\ jakarta.xml.bind-api;version='[2.3.3,2.3.4)',\ javax.measure.unit-api;version='[2.1.2,2.1.3)',\ junit-jupiter-api;version='[5.9.2,5.9.3)',\ @@ -105,4 +93,15 @@ Import-Package: \ si.uom.si-quantity;version='[2.1.0,2.1.1)',\ tech.units.indriya;version='[2.1.2,2.1.3)',\ uom-lib-common;version='[2.1.0,2.1.1)',\ - xstream;version='[1.4.20,1.4.21)' \ No newline at end of file + xstream;version='[1.4.20,1.4.21)',\ + io.netty.buffer;version='[4.1.92,4.1.93)',\ + io.netty.codec;version='[4.1.92,4.1.93)',\ + io.netty.codec-mqtt;version='[4.1.92,4.1.93)',\ + io.netty.codec-socks;version='[4.1.92,4.1.93)',\ + io.netty.common;version='[4.1.92,4.1.93)',\ + io.netty.handler;version='[4.1.92,4.1.93)',\ + io.netty.handler-proxy;version='[4.1.92,4.1.93)',\ + io.netty.resolver;version='[4.1.92,4.1.93)',\ + io.netty.transport;version='[4.1.92,4.1.93)',\ + io.netty.transport-native-unix-common;version='[4.1.92,4.1.93)',\ + org.osgi.service.cm;version='[1.6.0,1.6.1)' \ No newline at end of file diff --git a/pom.xml b/pom.xml index f0531b413c007..fc5f63b5965cc 100644 --- a/pom.xml +++ b/pom.xml @@ -74,7 +74,7 @@ 2.2.1 2.14.1 4.4.3 - 4.1.72.Final + 4.1.92.Final 3.14.9 0.15.0 2.35.0 From 44a78b99f59069d9c57cd5affd3902e11f5e0f18 Mon Sep 17 00:00:00 2001 From: mlobstein Date: Sat, 10 Jun 2023 00:22:02 -0500 Subject: [PATCH 06/41] [plex] Initial contribution (#15057) * aronbeurskens plex baseline Signed-off-by: Michael Lobstein * review changes Signed-off-by: Michael Lobstein * Clean-up PlexApiConnector exception handling Signed-off-by: Michael Lobstein * Additional clean-up Signed-off-by: Michael Lobstein * review changes Signed-off-by: Michael Lobstein * review changes Signed-off-by: Michael Lobstein --------- Signed-off-by: Michael Lobstein --- CODEOWNERS | 1 + bom/openhab-addons/pom.xml | 5 + bundles/org.openhab.binding.plex/NOTICE | 13 + bundles/org.openhab.binding.plex/README.md | 167 ++++++++ bundles/org.openhab.binding.plex/pom.xml | 17 + .../src/main/feature/feature.xml | 10 + .../plex/discovery/PlexDiscoveryService.java | 58 +++ .../plex/internal/PlexBindingConstants.java | 77 ++++ .../plex/internal/PlexHandlerFactory.java | 91 ++++ .../PlexStateDescriptionOptionProvider.java | 41 ++ .../config/PlexPlayerConfiguration.java | 27 ++ .../config/PlexServerConfiguration.java | 33 ++ .../plex/internal/dto/MediaContainer.java | 277 +++++++++++++ .../internal/dto/NotificationContainer.java | 166 ++++++++ .../plex/internal/dto/PlexPlayerState.java | 40 ++ .../plex/internal/dto/PlexSession.java | 177 ++++++++ .../binding/plex/internal/dto/User.java | 53 +++ .../internal/handler/PlexApiConnector.java | 392 ++++++++++++++++++ .../internal/handler/PlexPlayerHandler.java | 192 +++++++++ .../internal/handler/PlexServerHandler.java | 323 +++++++++++++++ .../internal/handler/PlexUpdateListener.java | 24 ++ .../src/main/resources/OH-INF/addon/addon.xml | 11 + .../main/resources/OH-INF/config/config.xml | 52 +++ .../resources/OH-INF/i18n/plex.properties | 57 +++ .../resources/OH-INF/thing/thing-types.xml | 108 +++++ .../handler/PlexApiConnectorTest.java | 64 +++ bundles/pom.xml | 1 + 27 files changed, 2477 insertions(+) create mode 100644 bundles/org.openhab.binding.plex/NOTICE create mode 100644 bundles/org.openhab.binding.plex/README.md create mode 100644 bundles/org.openhab.binding.plex/pom.xml create mode 100644 bundles/org.openhab.binding.plex/src/main/feature/feature.xml create mode 100644 bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/discovery/PlexDiscoveryService.java create mode 100644 bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/internal/PlexBindingConstants.java create mode 100644 bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/internal/PlexHandlerFactory.java create mode 100644 bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/internal/PlexStateDescriptionOptionProvider.java create mode 100644 bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/internal/config/PlexPlayerConfiguration.java create mode 100644 bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/internal/config/PlexServerConfiguration.java create mode 100644 bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/internal/dto/MediaContainer.java create mode 100644 bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/internal/dto/NotificationContainer.java create mode 100644 bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/internal/dto/PlexPlayerState.java create mode 100644 bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/internal/dto/PlexSession.java create mode 100644 bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/internal/dto/User.java create mode 100644 bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/internal/handler/PlexApiConnector.java create mode 100644 bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/internal/handler/PlexPlayerHandler.java create mode 100644 bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/internal/handler/PlexServerHandler.java create mode 100644 bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/internal/handler/PlexUpdateListener.java create mode 100644 bundles/org.openhab.binding.plex/src/main/resources/OH-INF/addon/addon.xml create mode 100644 bundles/org.openhab.binding.plex/src/main/resources/OH-INF/config/config.xml create mode 100644 bundles/org.openhab.binding.plex/src/main/resources/OH-INF/i18n/plex.properties create mode 100644 bundles/org.openhab.binding.plex/src/main/resources/OH-INF/thing/thing-types.xml create mode 100644 bundles/org.openhab.binding.plex/src/test/java/org.openhab.binding.plex/internal/handler/PlexApiConnectorTest.java diff --git a/CODEOWNERS b/CODEOWNERS index 51ca14a5bd2cc..899c818aa135f 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -267,6 +267,7 @@ /bundles/org.openhab.binding.pjlinkdevice/ @nils /bundles/org.openhab.binding.playstation/ @FluBBaOfWard /bundles/org.openhab.binding.plclogo/ @falkena +/bundles/org.openhab.binding.plex/ @aronbeurskens /bundles/org.openhab.binding.plugwise/ @wborn /bundles/org.openhab.binding.plugwiseha/ @lsiepel /bundles/org.openhab.binding.powermax/ @lolodomo diff --git a/bom/openhab-addons/pom.xml b/bom/openhab-addons/pom.xml index d55708c7fb970..54802e935c9db 100644 --- a/bom/openhab-addons/pom.xml +++ b/bom/openhab-addons/pom.xml @@ -1326,6 +1326,11 @@ org.openhab.binding.plclogo ${project.version} + + org.openhab.addons.bundles + org.openhab.binding.plex + ${project.version} + org.openhab.addons.bundles org.openhab.binding.plugwise diff --git a/bundles/org.openhab.binding.plex/NOTICE b/bundles/org.openhab.binding.plex/NOTICE new file mode 100644 index 0000000000000..38d625e349232 --- /dev/null +++ b/bundles/org.openhab.binding.plex/NOTICE @@ -0,0 +1,13 @@ +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 diff --git a/bundles/org.openhab.binding.plex/README.md b/bundles/org.openhab.binding.plex/README.md new file mode 100644 index 0000000000000..8a48f8f1c114f --- /dev/null +++ b/bundles/org.openhab.binding.plex/README.md @@ -0,0 +1,167 @@ +# PLEX Binding + +This binding can read information from multiple PLEX players connected to a PLEX server. + +It can be used for multiple scenarios: + +* Drive light changes based on player status. For instances turn off the lights when movie starts playing and turn them back on when movie is stopped/paused +* Create a page that displays currently played media of one or more player connected to the server. +* Send social media messages when player plays new media +* Inform what the end time of the currently played media is + +The binding can also control `PLAY/PAUSE/NEXT/PREVIOUS` the players which can be used for: + +* Start playing some music when someone enters a room +* Pause the movie when motion is detected + +## Supported Things + +This binding supports 2 things. + +- `server`: The PLEX server will act as a bridge to read out the information from all connected players +- `player`: A PLEX client of any type / os connected to the server. + +## Discovery + +For the auto discovery to work correctly you first need to configure and add the `PLEX Server` Thing. +Next step is to *PLAY* something on the desired player. Only when media is played on the player it will show up in the auto discovery! + +## Thing Configuration + +The PLEX Server needs to be configured first. The hostname of the PLEX server is mandatory and the either the PLEX token (recommended) or the username/password of the PLEX server (not recommended). + +Then find the PLEX token please follow the instructions from the PLEX support forum: + +1. Sign in to your Plex account in Plex Web App +2. Browse to a library item and view the XML for it +3. Look in the URL and find the token as the X-Plex-Token value + +### `PLEX Server` Thing Configuration + +| Name | Type | Description | Default | Required | Advanced | +|-------------|---------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|----------|---------| +| host | text | PLEX host name or IP address | N/A | yes | no | +| portNumber | integer | Port Number (leave blank if PLEX installed on default port) | 32400 | no | no | +| refreshRate | integer | Interval in seconds at which PLEX server status is polled | 5 | no | no | +| username | text | If you're using Plex Home you need to supply the username and password of your Plex account here. If you don't want to enter your credentials you can also directly set your account token below instead. | N/A | no | no | +| password | text | If you're using Plex Home you need to supply the username and password of your Plex account here. If you don't want to enter your credentials you can also directly set your account token below instead. | N/A | no | no | +| token | text | The authentication token when username/password is left blank | N/A | no | no | + +### `PLEX Player` Thing Configuration + +You can add multiple PLEX players. You can choose to find the player by autodiscovery or add them manually. + +#### Autodiscovery + +Turn on the player you want to add and *play* some media on it. Navigate to `/settings/things/add/plex` and start the auto discover. +The player will be found and you can add it. + +#### Manual adding a player Thing + +When you want to add them manually go to the following url [https://plex.tv/devices.xml] and login when needed. + +It will display the following XML file. + +```xml + + + + + + + + + + + + + + + + + + + + + + +``` + +Find the `Device` block of the player you want to add and fill in the `clientIdentifier` as `playerID` + +| Name | Type | Description | Default | Required | Advanced | +|-------------|---------|--------------------------------------------------------------------------------------------|---------|----------|---------| +| playerID | text | The unique identifier of the player. `clientIdentifier` from [https://plex.tv/devices.xml] | N/A | yes | no | + +## Channels + +The PLEX Player supports the following channels: + +| Channel | Type | Read/Write | Description | +|----------------------|----------|------------|-----------------------------------------------------------------------| +| currentPlayers | Number | RO | The number of players currently configured to watch on PLEX | +| currentPlayersActive | Number | RO | The number of players currently being used on PLEX | +| state | String | RO | The current state of the Player (BUFFERING, PLAYING, PAUSED, STOPPED) | +| power | Switch | RO | The power status of the player | +| title | String | RO | The title of media that is playing | +| type | String | RO | The current type of playing media | +| endtime | DateTime | RO | Time at which the media that is playing will end | +| progress | Dimmer | RO | The current progress of playing media | +| art | String | RO | The URL of the background art for currently playing media | +| thumb | String | RO | The URL of the cover art for currently playing media | +| player | Player | RW | The control channel for the player `PLAY/PAUSE/NEXT/PREVIOUS` | + +## Full Example + +`.things` file: + +```java +Bridge plex:server:plexrServer "Bridge Plex : Plex" [host="IP.Address.Or.Hostname", token="SadhjsajjA3AG", refreshRate=5] +{ + Thing plex:player:MyViewerName01 "My Viewer Name 01" [playerID="ClientIdentifierFromDevices.XML1"] + Thing plex:player:MyViewerName02 "My Viewer Name 02" [playerID="ClientIdentifierFromDevices.XML2"] +} +``` + +`.items` file + +```java +String BridgePlexCurrent "Current players" {channel="plex:server:plexrServer:currentPlayers"} +String BridgePlexCurrentActive "Current players active" {channel="plex:server:plexrServer:currentPlayersActive"} +Switch PlexTVPower01 "Power" {channel="plex:player:MyViewerName01:power"} +String PlexTVStatus01 "Status [%s]" {channel="plex:player:MyViewerName01:state"} +String PlexTVTitle01 "Title [%s]" {channel="plex:player:MyViewerName01:title"} +String PlexTVType01 "Type [%s]" {channel="plex:player:MyViewerName01:type"} +String PlexTVEndTime01 "End time" {channel="plex:player:MyViewerName01:endtime"} +Dimmer PlexTVProgress01 "Progress [%.1f%%]" {channel="plex:player:MyViewerName01:progress"} +String PlexTVCover1 "Cover" {channel="plex:player:MyViewerName01:thumb"} +String ShellArt01 "Background art" {channel="plex:player:MyViewerName01:art"} +Switch PlexTVPower02 "Power" {channel="plex:player:MyViewerName02:power"} +String PlexTVStatus02 "Status [%s]" {channel="plex:player:MyViewerName02:state"} +String PlexTVTitle02 "Title [%s]" {channel="plex:player:MyViewerName02:title"} +String PlexTVType02 "Type [%s]" {channel="plex:player:MyViewerName02:type"} +String PlexTVEndTime02 "End time" {channel="plex:player:MyViewerName02:endtime"} +Dimmer PlexTVProgress02 "Progress [%.1f%%]" {channel="plex:player:MyViewerName02:progress"} +String PlexTVCover2 "Cover" {channel="plex:player:MyViewerName02:thumb"} +String ShellArt02 "Background art" {channel="plex:player:MyViewerName02:art"} +``` + +`.rules` file + +```java +rule "Send telegram with title for My Viewer Name 01" +when + Item PlexTVTitle01 changed +then + val telegramActionPlexBot = getActions("telegram","telegram:telegramBot:PlexBot") + telegramActionPlexBot.sendTelegram("Bedroom Roku is watching %s", PlexTVTitle01.state.toString) +end + +rule "Send telegram with title for My Viewer Name 02" +when + Item PlexTVTitle02 changed +then + val telegramActionPlexBot = getActions("telegram","telegram:telegramBot:PlexBot") + telegramActionPlexBot.sendTelegram("Bedroom Roku is watching %s", PlexTVTitle02.state.toString) +end +``` diff --git a/bundles/org.openhab.binding.plex/pom.xml b/bundles/org.openhab.binding.plex/pom.xml new file mode 100644 index 0000000000000..d37438f757a02 --- /dev/null +++ b/bundles/org.openhab.binding.plex/pom.xml @@ -0,0 +1,17 @@ + + + + 4.0.0 + + + org.openhab.addons.bundles + org.openhab.addons.reactor.bundles + 4.0.0-SNAPSHOT + + + org.openhab.binding.plex + + openHAB Add-ons :: Bundles :: Plex Binding + + diff --git a/bundles/org.openhab.binding.plex/src/main/feature/feature.xml b/bundles/org.openhab.binding.plex/src/main/feature/feature.xml new file mode 100644 index 0000000000000..892b597a003a7 --- /dev/null +++ b/bundles/org.openhab.binding.plex/src/main/feature/feature.xml @@ -0,0 +1,10 @@ + + + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + + + openhab-runtime-base + openhab.tp-jaxb + mvn:org.openhab.addons.bundles/org.openhab.binding.plex/${project.version} + + diff --git a/bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/discovery/PlexDiscoveryService.java b/bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/discovery/PlexDiscoveryService.java new file mode 100644 index 0000000000000..a7b3659da55db --- /dev/null +++ b/bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/discovery/PlexDiscoveryService.java @@ -0,0 +1,58 @@ +/** + * 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.plex.discovery; + +import static org.openhab.binding.plex.internal.PlexBindingConstants.*; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.plex.internal.handler.PlexServerHandler; +import org.openhab.core.config.discovery.AbstractDiscoveryService; +import org.openhab.core.config.discovery.DiscoveryResult; +import org.openhab.core.config.discovery.DiscoveryResultBuilder; +import org.openhab.core.thing.ThingTypeUID; +import org.openhab.core.thing.ThingUID; + +/** + * @author Brian Homeyer - Initial contribution + * @author Aron Beurskens - Binding development + */ +@NonNullByDefault +public class PlexDiscoveryService extends AbstractDiscoveryService { + private final PlexServerHandler bridgeHandler; + + public PlexDiscoveryService(PlexServerHandler bridgeHandler) { + super(SUPPORTED_THING_TYPES_UIDS, 10, false); + this.bridgeHandler = bridgeHandler; + } + + @Override + protected void startScan() { + for (String machineId : bridgeHandler.getAvailablePlayers()) { + ThingUID bridgeUID = bridgeHandler.getThing().getUID(); + ThingTypeUID thingTypeUID = UID_PLAYER; + ThingUID playerThingUid = new ThingUID(UID_PLAYER, bridgeUID, machineId); + + Map properties = new HashMap<>(); + properties.put(CONFIG_PLAYER_ID, machineId); + + DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(playerThingUid).withThingType(thingTypeUID) + .withProperties(properties).withBridge(bridgeUID).withRepresentationProperty(CONFIG_PLAYER_ID) + .withLabel("PLEX Player (" + machineId + ")").build(); + + thingDiscovered(discoveryResult); + } + } +} diff --git a/bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/internal/PlexBindingConstants.java b/bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/internal/PlexBindingConstants.java new file mode 100644 index 0000000000000..33e4f37cb3a16 --- /dev/null +++ b/bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/internal/PlexBindingConstants.java @@ -0,0 +1,77 @@ +/** + * 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.plex.internal; + +import java.util.Collections; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.core.thing.ThingTypeUID; + +/** + * The {@link PlexBindingConstants} class defines common constants, which are + * used across the whole binding. + * + * @author Brian Homeyer - Initial contribution + * @author Aron Beurskens - Binding development + */ +@NonNullByDefault +public class PlexBindingConstants { + private static final String BINDING_ID = "plex"; + + // Bridge thing + public static final String THING_TYPE_SERVER = "server"; + public static final ThingTypeUID UID_SERVER = new ThingTypeUID(BINDING_ID, THING_TYPE_SERVER); + public static final Set SUPPORTED_SERVER_THING_TYPES_UIDS = Set.of(UID_SERVER); + + // Monitor things + public static final String THING_TYPE_PLAYER = "player"; + public static final ThingTypeUID UID_PLAYER = new ThingTypeUID(BINDING_ID, THING_TYPE_PLAYER); + + // Collection of monitor thing types + public static final Set SUPPORTED_PLAYER_THING_TYPES_UIDS = Set.of(UID_PLAYER); + + // Collection of all supported thing types + public static final Set SUPPORTED_THING_TYPES_UIDS = Collections.unmodifiableSet( + Stream.concat(SUPPORTED_PLAYER_THING_TYPES_UIDS.stream(), SUPPORTED_SERVER_THING_TYPES_UIDS.stream()) + .collect(Collectors.toSet())); + // General purpose stuff + public static final int DEFAULT_REFRESH_PERIOD_SEC = 5; + // Config parameters + // Server + public static final String CONFIG_HOST = "host"; + public static final String CONFIG_PORT_NUMBER = "portNumber"; + public static final String CONFIG_TOKEN = "token"; + public static final String CONFIG_REFRESH_RATE = "refreshRate"; + // Player parameters + public static final String CONFIG_PLAYER_ID = "playerID"; + public static final String CONFIG_PLAYER_NAME = "playerName"; + + // List of all Channel ids + // Server + public static final String CHANNEL_SERVER_COUNT = "currentPlayers"; + public static final String CHANNEL_SERVER_COUNTACTIVE = "currentPlayersActive"; + // Player + public static final String CHANNEL_PLAYER_STATE = "state"; + public static final String CHANNEL_PLAYER_TITLE = "title"; + public static final String CHANNEL_PLAYER_TYPE = "type"; + public static final String CHANNEL_PLAYER_POWER = "power"; + public static final String CHANNEL_PLAYER_ART = "art"; + public static final String CHANNEL_PLAYER_THUMB = "thumb"; + public static final String CHANNEL_PLAYER_PROGRESS = "progress"; + public static final String CHANNEL_PLAYER_ENDTIME = "endtime"; + public static final String CHANNEL_PLAYER_CONTROL = "player"; + public static final String CHANNEL_PLAYER_USER = "user"; +} diff --git a/bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/internal/PlexHandlerFactory.java b/bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/internal/PlexHandlerFactory.java new file mode 100644 index 0000000000000..8bd642cfc534c --- /dev/null +++ b/bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/internal/PlexHandlerFactory.java @@ -0,0 +1,91 @@ +/** + * 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.plex.internal; + +import static org.openhab.binding.plex.internal.PlexBindingConstants.*; + +import java.util.Hashtable; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.plex.discovery.PlexDiscoveryService; +import org.openhab.binding.plex.internal.handler.PlexPlayerHandler; +import org.openhab.binding.plex.internal.handler.PlexServerHandler; +import org.openhab.core.config.discovery.DiscoveryService; +import org.openhab.core.io.net.http.HttpClientFactory; +import org.openhab.core.thing.Bridge; +import org.openhab.core.thing.Thing; +import org.openhab.core.thing.ThingTypeUID; +import org.openhab.core.thing.binding.BaseThingHandlerFactory; +import org.openhab.core.thing.binding.ThingHandler; +import org.openhab.core.thing.binding.ThingHandlerFactory; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; + +/** + * The {@link PlexHandlerFactory} is responsible for creating things and thing + * handlers. + * + * @author Brian Homeyer - Initial contribution + * @author Aron Beurskens - Binding development + */ +@NonNullByDefault +@Component(configurationPid = "binding.plex", service = ThingHandlerFactory.class) +public class PlexHandlerFactory extends BaseThingHandlerFactory { + private final HttpClientFactory httpClientFactory; + private @Nullable ServiceRegistration plexDiscoveryServiceRegistration; + + @Activate + public PlexHandlerFactory(final @Reference HttpClientFactory httpClientFactory) { + this.httpClientFactory = httpClientFactory; + } + + @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 (SUPPORTED_SERVER_THING_TYPES_UIDS.contains(thingTypeUID)) { + PlexServerHandler handler = new PlexServerHandler((Bridge) thing, httpClientFactory); + registerPlexDiscoveryService(handler); + return handler; + } else if (SUPPORTED_PLAYER_THING_TYPES_UIDS.contains(thingTypeUID)) { + return new PlexPlayerHandler(thing); + } + return null; + } + + @Override + protected synchronized void removeHandler(ThingHandler thingHandler) { + if (thingHandler instanceof PlexServerHandler) { + ServiceRegistration plexDiscoveryServiceRegistration = this.plexDiscoveryServiceRegistration; + if (plexDiscoveryServiceRegistration != null) { + // remove discovery service, if bridge handler is removed + plexDiscoveryServiceRegistration.unregister(); + } + } + } + + private void registerPlexDiscoveryService(PlexServerHandler handler) { + PlexDiscoveryService discoveryService = new PlexDiscoveryService(handler); + if (bundleContext != null) { + this.plexDiscoveryServiceRegistration = bundleContext.registerService(DiscoveryService.class.getName(), + discoveryService, new Hashtable<>()); + } + } +} diff --git a/bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/internal/PlexStateDescriptionOptionProvider.java b/bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/internal/PlexStateDescriptionOptionProvider.java new file mode 100644 index 0000000000000..22025910e5d91 --- /dev/null +++ b/bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/internal/PlexStateDescriptionOptionProvider.java @@ -0,0 +1,41 @@ +/** + * 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.plex.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.Component; +import org.osgi.service.component.annotations.Reference; + +/** + * Dynamic provider of state options while leaving other state description fields as original. + * + * @author Brian Homeyer - Initial contribution + * @author Aron Beurskens - Binding development + */ +@Component(service = { DynamicStateDescriptionProvider.class, PlexStateDescriptionOptionProvider.class }) +@NonNullByDefault +public class PlexStateDescriptionOptionProvider extends BaseDynamicStateDescriptionProvider { + @Reference + protected void setChannelTypeI18nLocalizationService( + final ChannelTypeI18nLocalizationService channelTypeI18nLocalizationService) { + this.channelTypeI18nLocalizationService = channelTypeI18nLocalizationService; + } + + protected void unsetChannelTypeI18nLocalizationService( + final ChannelTypeI18nLocalizationService channelTypeI18nLocalizationService) { + this.channelTypeI18nLocalizationService = null; + } +} diff --git a/bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/internal/config/PlexPlayerConfiguration.java b/bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/internal/config/PlexPlayerConfiguration.java new file mode 100644 index 0000000000000..cb18fb3ee479e --- /dev/null +++ b/bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/internal/config/PlexPlayerConfiguration.java @@ -0,0 +1,27 @@ +/** + * 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.plex.internal.config; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link PlexPlayerConfiguration} is the class used to match the + * thing configuration. + * + * @author Brian Homeyer - Initial contribution + * @author Aron Beurskens - Binding development + */ +@NonNullByDefault +public class PlexPlayerConfiguration { + public String playerID = ""; +} diff --git a/bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/internal/config/PlexServerConfiguration.java b/bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/internal/config/PlexServerConfiguration.java new file mode 100644 index 0000000000000..27ae78f014c95 --- /dev/null +++ b/bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/internal/config/PlexServerConfiguration.java @@ -0,0 +1,33 @@ +/** + * 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.plex.internal.config; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link PlexServerConfiguration} is the class used to match the + * bridge configuration. + * + * @author Brian Homeyer - Initial contribution + * @author Aron Beurskens - Binding development + */ +@NonNullByDefault +public class PlexServerConfiguration { + public String host = ""; + public Integer portNumber = 32400; + public String token = ""; + public Integer refreshRate = 5; + public String username = ""; + public String password = ""; + public String scheme = ""; +} diff --git a/bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/internal/dto/MediaContainer.java b/bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/internal/dto/MediaContainer.java new file mode 100644 index 0000000000000..f4caa7eac86d1 --- /dev/null +++ b/bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/internal/dto/MediaContainer.java @@ -0,0 +1,277 @@ +/** + * 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.plex.internal.dto; + +import java.util.List; + +import com.thoughtworks.xstream.annotations.XStreamAlias; +import com.thoughtworks.xstream.annotations.XStreamAsAttribute; +import com.thoughtworks.xstream.annotations.XStreamImplicit; + +/** + * + * @author Brian Homeyer - Initial contribution + * @author Aron Beurskens - Binding development + */ +@XStreamAlias("MediaContainer") +public class MediaContainer { + @XStreamAsAttribute + private Integer size; + @XStreamImplicit + @XStreamAsAttribute + private List