mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 07:02:02 +01:00
[pilight] Pilight Binding initial contribution (#9744)
Signed-off-by: Niklas Dörfler <niklas@doerfler-el.de>
This commit is contained in:
parent
2b3e08de43
commit
c0cec8028c
@ -208,6 +208,7 @@
|
||||
/bundles/org.openhab.binding.paradoxalarm/ @theater
|
||||
/bundles/org.openhab.binding.pentair/ @jsjames
|
||||
/bundles/org.openhab.binding.phc/ @gnlpfjh
|
||||
/bundles/org.openhab.binding.pilight/ @stefanroellin @niklasdoerfler
|
||||
/bundles/org.openhab.binding.pioneeravr/ @Stratehm
|
||||
/bundles/org.openhab.binding.pixometer/ @Confectrician
|
||||
/bundles/org.openhab.binding.pjlinkdevice/ @nils
|
||||
|
@ -1026,6 +1026,11 @@
|
||||
<artifactId>org.openhab.binding.phc</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openhab.addons.bundles</groupId>
|
||||
<artifactId>org.openhab.binding.pilight</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openhab.addons.bundles</groupId>
|
||||
<artifactId>org.openhab.binding.pioneeravr</artifactId>
|
||||
|
13
bundles/org.openhab.binding.pilight/NOTICE
Normal file
13
bundles/org.openhab.binding.pilight/NOTICE
Normal file
@ -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
|
119
bundles/org.openhab.binding.pilight/README.md
Normal file
119
bundles/org.openhab.binding.pilight/README.md
Normal file
@ -0,0 +1,119 @@
|
||||
# pilight Binding
|
||||
|
||||
The pilight binding allows openHAB to communicate with a [pilight](http://www.pilight.org/) instance running pilight
|
||||
version 6.0 or greater.
|
||||
|
||||
> pilight is a free open source full fledge domotica solution that runs on a Raspberry Pi, HummingBoard, BananaPi,
|
||||
> Radxa, but also on *BSD and various linuxes (tested on Arch, Ubuntu and Debian). It's open source and freely available
|
||||
> for anyone. pilight works with a great deal of devices and is frequency independent. Therefor, it can control devices
|
||||
> working at 315Mhz, 433Mhz, 868Mhz etc. Support for these devices are dependent on community, because we as developers
|
||||
> don't own them all.
|
||||
|
||||
pilight is a cheap way to control 'Click On Click Off' devices. It started as an application for the Raspberry Pi (using
|
||||
the GPIO interface) but it's also possible now to connect it to any other PC using an Arduino Nano. You will need a
|
||||
cheap 433Mhz transceiver in both cases. See the [Pilight manual](https://manual.pilight.org/electronics/wiring.html) for
|
||||
more information.
|
||||
|
||||
## Supported Things
|
||||
|
||||
| Thing | Type | Description |
|
||||
|-----------|--------|----------------------------------------------------------------------------|
|
||||
| `bridge` | Bridge | Pilight bridge required for the communication with the pilight daemon. |
|
||||
| `contact` | Thing | Pilight contact (read-only). |
|
||||
| `dimmer` | Thing | Pilight dimmer. |
|
||||
| `switch` | Thing | Pilight switch. |
|
||||
| `generic` | Thing | Pilight generic device for which you have to add the channels dynamically. |
|
||||
|
||||
## Binding Configuration
|
||||
|
||||
### `bridge` Thing
|
||||
|
||||
A `bridge` is required for the communication with a pilight daemon. Multiple pilight instances are supported by creating
|
||||
different pilight `bridge` things.
|
||||
|
||||
The `bridge` requires the following configuration parameters:
|
||||
|
||||
| Parameter Label | Parameter ID | Description | Required |
|
||||
|-----------------|--------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|
|
||||
| IP Address | ipAddress | Host name or IP address of the pilight daemon | yes |
|
||||
| Port | port | Port number on which the pilight daemon is listening. Default: 5000 | yes |
|
||||
| Delay | delay | Delay (in millisecond) between consecutive commands. Recommended value without band pass filter: 1000. Recommended value with band pass filter: somewhere between 200-500. Default: 500 | no |
|
||||
|
||||
Important: you must explicitly configure the port in the pilight daemon config or otherwise a random port will be used
|
||||
and the binding will not be able to connect.
|
||||
|
||||
### `contact`, `dimmer`, `switch`, `generic` Things
|
||||
|
||||
These things have all one required parameter:
|
||||
|
||||
| Parameter Label | Parameter ID | Description | Required |
|
||||
|-----------------|--------------|------------------------|----------|
|
||||
| Name | name | Name of pilight device | yes |
|
||||
|
||||
## Channels
|
||||
|
||||
The `bridge` thing has no channels.
|
||||
|
||||
The `contact`, `dimmer` and `switch` things all have one channel:
|
||||
|
||||
| Thing | Channel | Type | Description |
|
||||
|-----------|----------|---------|-------------------------|
|
||||
| `contact` | state | Contact | State of the contact |
|
||||
| `dimmer` | dimlevel | Dimmer | Dim level of the dimmer |
|
||||
| `switch` | state | Switch | State of the switch |
|
||||
|
||||
The `generic` thing has no fixed channels, so you have to add them manually. Currently, only String and Number channels
|
||||
are supported.
|
||||
|
||||
## Auto Discovery
|
||||
|
||||
### Bridge Auto Discovery
|
||||
|
||||
The pilight daemon implements a SSDP interface, which can be used to search for running pilight daemon instances by
|
||||
sending a SSDP request via multicast udp (this mechanism may only work if
|
||||
the [standalone mode](https://manual.pilight.org/configuration/settings.html#standalone) in the pilight daemon is
|
||||
disabled. After loading the binding this bridge discovery is automatically run and scheduled to scan for bridges every
|
||||
10 minutes.
|
||||
|
||||
### Device Auto Discovery
|
||||
|
||||
After a `bridge` thing has been configured in openHAB, it automatically establishes a connection between pilight daemon
|
||||
and openHAB. As soon as the bridge is connected, the devices configured in the pilight daemon are automatically found
|
||||
via autodiscovery in background (or via a manually triggered discovery) and are displayed in the inbox to easily create
|
||||
things from them.
|
||||
|
||||
## Full Example
|
||||
|
||||
things/pilight.things
|
||||
|
||||
```
|
||||
Bridge pilight:bridge:raspi "Pilight Daemon raspi" [ ipAddress="192.168.1.1", port=5000 ] {
|
||||
Thing switch office "Office" [ name="office" ]
|
||||
Thing dimmer piano "Piano" [ name="piano" ]
|
||||
Thing generic weather "Weather" [ name="weather" ] {
|
||||
Channels:
|
||||
State Number : temperature [ property="temperature"]
|
||||
State Number : humidity [ property="humidity"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
items/pilight.items
|
||||
|
||||
```
|
||||
Switch office_switch "Büro" { channel="pilight:switch:raspi:office:state" }
|
||||
Dimmer piano_light "Klavier [%.0f %%]" { channel="pilight:dimmer:raspi:piano:dimlevel" }
|
||||
Number weather_temperature "Aussentemperatur [%.1f °C]" <temperature> { channel="pilight:generic:raspi:weather:temperature" }
|
||||
Number weather_humidity "Feuchtigkeit [%.0f %%]" <humidity> { channel="pilight:generic:raspi:weather:humidity" }
|
||||
|
||||
```
|
||||
|
||||
sitemaps/fragment.sitemap
|
||||
|
||||
```
|
||||
Switch item=office_switch
|
||||
Slider item=piano_light
|
||||
Text item=weather_temperature
|
||||
Text item=weather_humidity
|
||||
```
|
||||
|
17
bundles/org.openhab.binding.pilight/pom.xml
Normal file
17
bundles/org.openhab.binding.pilight/pom.xml
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.openhab.addons.bundles</groupId>
|
||||
<artifactId>org.openhab.addons.reactor.bundles</artifactId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>org.openhab.binding.pilight</artifactId>
|
||||
|
||||
<name>openHAB Add-ons :: Bundles :: Pilight Binding</name>
|
||||
|
||||
</project>
|
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<features name="org.openhab.binding.pilight-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
|
||||
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
|
||||
|
||||
<feature name="openhab-binding-pilight" description="Pilight Binding" version="${project.version}">
|
||||
<feature>openhab-runtime-base</feature>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.pilight/${project.version}</bundle>
|
||||
</feature>
|
||||
</features>
|
@ -0,0 +1,64 @@
|
||||
/**
|
||||
* 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.pilight.internal;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.pilight.internal.dto.Config;
|
||||
import org.openhab.binding.pilight.internal.dto.Status;
|
||||
import org.openhab.binding.pilight.internal.dto.Version;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
|
||||
/**
|
||||
* Callback interface to signal any listeners that an update was received from pilight
|
||||
*
|
||||
* @author Jeroen Idserda - Initial contribution
|
||||
* @author Stefan Röllin - Port to openHAB 2 pilight binding
|
||||
* @author Niklas Dörfler - Port pilight binding to openHAB 3 + add device discovery
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public interface IPilightCallback {
|
||||
|
||||
/**
|
||||
* Update thing status
|
||||
*
|
||||
* @param status status of thing
|
||||
* @param statusDetail status detail of thing
|
||||
* @param description description of thing status
|
||||
*/
|
||||
void updateThingStatus(ThingStatus status, ThingStatusDetail statusDetail, @Nullable String description);
|
||||
|
||||
/**
|
||||
* Update for one or more device received.
|
||||
*
|
||||
* @param allStatus list of Object containing list of devices that were updated and their current state
|
||||
*/
|
||||
void statusReceived(List<Status> allStatus);
|
||||
|
||||
/**
|
||||
* Configuration received.
|
||||
*
|
||||
* @param config Object containing configuration of pilight
|
||||
*/
|
||||
void configReceived(Config config);
|
||||
|
||||
/**
|
||||
* Version information received.
|
||||
*
|
||||
* @param version Object containing software version information of pilight daemon
|
||||
*/
|
||||
void versionReceived(Version version);
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/**
|
||||
* 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.pilight.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
* The {@link PilightBindingConstants} class defines common constants, which are
|
||||
* used across the whole binding.
|
||||
*
|
||||
* @author Stefan Röllin - Initial contribution
|
||||
* @author Niklas Dörfler - Port pilight binding to openHAB 3 + add device discovery
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PilightBindingConstants {
|
||||
|
||||
public static final String BINDING_ID = "pilight";
|
||||
|
||||
// List of all Thing Type UIDs
|
||||
public static final ThingTypeUID THING_TYPE_BRIDGE = new ThingTypeUID(BINDING_ID, "bridge");
|
||||
public static final ThingTypeUID THING_TYPE_CONTACT = new ThingTypeUID(BINDING_ID, "contact");
|
||||
public static final ThingTypeUID THING_TYPE_DIMMER = new ThingTypeUID(BINDING_ID, "dimmer");
|
||||
public static final ThingTypeUID THING_TYPE_SWITCH = new ThingTypeUID(BINDING_ID, "switch");
|
||||
public static final ThingTypeUID THING_TYPE_GENERIC = new ThingTypeUID(BINDING_ID, "generic");
|
||||
|
||||
// List of property names
|
||||
public static final String PROPERTY_IP_ADDRESS = "ipAddress";
|
||||
public static final String PROPERTY_PORT = "port";
|
||||
public static final String PROPERTY_NAME = "name";
|
||||
|
||||
// List of all Channel ids
|
||||
public static final String CHANNEL_STATE = "state";
|
||||
public static final String CHANNEL_DIMLEVEL = "dimlevel";
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/**
|
||||
* 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.pilight.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link PilightBridgeConfiguration} class contains fields mapping thing configuration parameters.
|
||||
*
|
||||
* @author Stefan Röllin - Initial contribution
|
||||
* @author Niklas Dörfler - Port pilight binding to openHAB 3 + add device discovery
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PilightBridgeConfiguration {
|
||||
|
||||
private String ipAddress = "";
|
||||
private int port = 0;
|
||||
private int delay = 500;
|
||||
|
||||
public String getIpAddress() {
|
||||
return ipAddress;
|
||||
}
|
||||
|
||||
public void setIpAddress(String ipAddress) {
|
||||
this.ipAddress = ipAddress;
|
||||
}
|
||||
|
||||
public Integer getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public void setPort(Integer port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public int getDelay() {
|
||||
return delay;
|
||||
}
|
||||
|
||||
public void setDelay(Integer delay) {
|
||||
this.delay = delay;
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/**
|
||||
* 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.pilight.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link PilightChannelConfiguration} class contains fields mapping channel configuration parameters.
|
||||
*
|
||||
* @author Stefan Röllin - Initial contribution
|
||||
* @author Niklas Dörfler - Port pilight binding to openHAB 3 + add device discovery
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PilightChannelConfiguration {
|
||||
private String property = "";
|
||||
|
||||
public String getProperty() {
|
||||
return property;
|
||||
}
|
||||
|
||||
public void setProperty(String property) {
|
||||
this.property = property;
|
||||
}
|
||||
}
|
@ -0,0 +1,264 @@
|
||||
/**
|
||||
* 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.pilight.internal;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.Socket;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.pilight.internal.dto.*;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.databind.MappingJsonFactory;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
/**
|
||||
* This class listens for updates from the pilight daemon. It is also responsible for requesting
|
||||
* and propagating the current pilight configuration.
|
||||
*
|
||||
* @author Jeroen Idserda - Initial contribution
|
||||
* @author Stefan Röllin - Port to openHAB 2 pilight binding
|
||||
* @author Niklas Dörfler - Port pilight binding to openHAB 3 + add device discovery
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PilightConnector implements Runnable, Closeable {
|
||||
|
||||
private static final int RECONNECT_DELAY_MSEC = 10 * 1000; // 10 seconds
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(PilightConnector.class);
|
||||
|
||||
private final PilightBridgeConfiguration config;
|
||||
|
||||
private final IPilightCallback callback;
|
||||
|
||||
private final ObjectMapper inputMapper = new ObjectMapper(
|
||||
new MappingJsonFactory().configure(JsonParser.Feature.AUTO_CLOSE_SOURCE, false));
|
||||
|
||||
private final ObjectMapper outputMapper = new ObjectMapper(
|
||||
new MappingJsonFactory().configure(JsonParser.Feature.AUTO_CLOSE_SOURCE, false))
|
||||
.setDefaultPropertyInclusion(JsonInclude.Include.NON_NULL);
|
||||
|
||||
private @Nullable Socket socket;
|
||||
private @Nullable PrintStream printStream;
|
||||
|
||||
private final ScheduledExecutorService scheduler;
|
||||
private final ConcurrentLinkedQueue<Action> delayedActionQueue = new ConcurrentLinkedQueue<>();
|
||||
private @Nullable ScheduledFuture<?> delayedActionWorkerFuture;
|
||||
|
||||
public PilightConnector(final PilightBridgeConfiguration config, final IPilightCallback callback,
|
||||
final ScheduledExecutorService scheduler) {
|
||||
this.config = config;
|
||||
this.callback = callback;
|
||||
this.scheduler = scheduler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
connect();
|
||||
|
||||
while (!Thread.currentThread().isInterrupted()) {
|
||||
try {
|
||||
final @Nullable Socket socket = this.socket;
|
||||
if (socket != null && !socket.isClosed()) {
|
||||
try (BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
|
||||
String line = in.readLine();
|
||||
while (!Thread.currentThread().isInterrupted() && line != null) {
|
||||
if (!line.isEmpty()) {
|
||||
logger.trace("Received from pilight: {}", line);
|
||||
final ObjectMapper inputMapper = this.inputMapper;
|
||||
if (line.startsWith("{\"message\":\"config\"")) {
|
||||
final @Nullable Message message = inputMapper.readValue(line, Message.class);
|
||||
callback.configReceived(message.getConfig());
|
||||
} else if (line.startsWith("{\"message\":\"values\"")) {
|
||||
final @Nullable AllStatus status = inputMapper.readValue(line, AllStatus.class);
|
||||
callback.statusReceived(status.getValues());
|
||||
} else if (line.startsWith("{\"version\":")) {
|
||||
final @Nullable Version version = inputMapper.readValue(line, Version.class);
|
||||
callback.versionReceived(version);
|
||||
} else if (line.startsWith("{\"status\":")) {
|
||||
// currently unused
|
||||
} else if (line.equals("1")) {
|
||||
throw new IOException("Connection to pilight lost");
|
||||
} else {
|
||||
final @Nullable Status status = inputMapper.readValue(line, Status.class);
|
||||
callback.statusReceived(Collections.singletonList(status));
|
||||
}
|
||||
}
|
||||
|
||||
line = in.readLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (!Thread.currentThread().isInterrupted()) {
|
||||
logger.debug("Error in pilight listener thread: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
logger.debug("Disconnected from pilight server at {}:{}", config.getIpAddress(), config.getPort());
|
||||
|
||||
if (!Thread.currentThread().isInterrupted()) {
|
||||
callback.updateThingStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, null);
|
||||
// empty line received (socket closed) or pilight stopped but binding
|
||||
// is still running, try to reconnect
|
||||
connect();
|
||||
}
|
||||
}
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
logger.debug("Interrupting thread.");
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells the connector to refresh the configuration
|
||||
*/
|
||||
public void refreshConfig() {
|
||||
doSendAction(new Action(Action.ACTION_REQUEST_CONFIG));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells the connector to refresh the status of all devices
|
||||
*/
|
||||
public void refreshStatus() {
|
||||
doSendAction(new Action(Action.ACTION_REQUEST_VALUES));
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the listener
|
||||
*/
|
||||
public void close() {
|
||||
disconnect();
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
|
||||
private void disconnect() {
|
||||
final @Nullable PrintStream printStream = this.printStream;
|
||||
if (printStream != null) {
|
||||
printStream.close();
|
||||
this.printStream = null;
|
||||
}
|
||||
|
||||
final @Nullable Socket socket = this.socket;
|
||||
if (socket != null) {
|
||||
try {
|
||||
socket.close();
|
||||
} catch (IOException e) {
|
||||
logger.debug("Error while closing pilight socket: {}", e.getMessage());
|
||||
}
|
||||
this.socket = null;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isConnected() {
|
||||
final @Nullable Socket socket = this.socket;
|
||||
return socket != null && !socket.isClosed();
|
||||
}
|
||||
|
||||
private void connect() throws InterruptedException {
|
||||
disconnect();
|
||||
|
||||
int delay = 0;
|
||||
|
||||
while (!isConnected()) {
|
||||
try {
|
||||
logger.debug("pilight connecting to {}:{}", config.getIpAddress(), config.getPort());
|
||||
|
||||
Thread.sleep(delay);
|
||||
Socket socket = new Socket(config.getIpAddress(), config.getPort());
|
||||
|
||||
Options options = new Options();
|
||||
options.setConfig(true);
|
||||
|
||||
Identification identification = new Identification();
|
||||
identification.setOptions(options);
|
||||
|
||||
// For some reason, directly using the outputMapper to write to the socket's OutputStream doesn't work.
|
||||
PrintStream printStream = new PrintStream(socket.getOutputStream(), true);
|
||||
printStream.println(outputMapper.writeValueAsString(identification));
|
||||
|
||||
final @Nullable Response response = inputMapper.readValue(socket.getInputStream(), Response.class);
|
||||
|
||||
if (response.getStatus().equals(Response.SUCCESS)) {
|
||||
logger.debug("Established connection to pilight server at {}:{}", config.getIpAddress(),
|
||||
config.getPort());
|
||||
this.socket = socket;
|
||||
this.printStream = printStream;
|
||||
callback.updateThingStatus(ThingStatus.ONLINE, ThingStatusDetail.NONE, null);
|
||||
} else {
|
||||
printStream.close();
|
||||
socket.close();
|
||||
logger.debug("pilight client not accepted: {}", response.getStatus());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
final @Nullable PrintStream printStream = this.printStream;
|
||||
if (printStream != null) {
|
||||
printStream.close();
|
||||
}
|
||||
logger.debug("connect failed: {}", e.getMessage());
|
||||
callback.updateThingStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
|
||||
}
|
||||
|
||||
delay = RECONNECT_DELAY_MSEC;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* send action to pilight daemon
|
||||
*
|
||||
* @param action action to send
|
||||
*/
|
||||
public void sendAction(Action action) {
|
||||
delayedActionQueue.add(action);
|
||||
final @Nullable ScheduledFuture<?> delayedActionWorkerFuture = this.delayedActionWorkerFuture;
|
||||
|
||||
if (delayedActionWorkerFuture == null || delayedActionWorkerFuture.isCancelled()) {
|
||||
this.delayedActionWorkerFuture = scheduler.scheduleWithFixedDelay(() -> {
|
||||
if (!delayedActionQueue.isEmpty()) {
|
||||
doSendAction(delayedActionQueue.poll());
|
||||
} else {
|
||||
final @Nullable ScheduledFuture<?> workerFuture = this.delayedActionWorkerFuture;
|
||||
if (workerFuture != null) {
|
||||
workerFuture.cancel(false);
|
||||
}
|
||||
this.delayedActionWorkerFuture = null;
|
||||
}
|
||||
}, 0, config.getDelay(), TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
private void doSendAction(Action action) {
|
||||
final @Nullable PrintStream printStream = this.printStream;
|
||||
if (printStream != null) {
|
||||
try {
|
||||
printStream.println(outputMapper.writeValueAsString(action));
|
||||
} catch (IOException e) {
|
||||
logger.debug("Error while sending action '{}' to pilight server: {}", action.getAction(),
|
||||
e.getMessage());
|
||||
}
|
||||
} else {
|
||||
logger.debug("Cannot send action '{}', not connected to pilight!", action.getAction());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/**
|
||||
* 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.pilight.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link PilightDeviceConfiguration} class contains fields mapping thing configuration parameters.
|
||||
*
|
||||
* @author Stefan Röllin - Initial contribution
|
||||
* @author Niklas Dörfler - Port pilight binding to openHAB 3 + add device discovery
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PilightDeviceConfiguration {
|
||||
|
||||
private String name = "";
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
/**
|
||||
* 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.pilight.internal;
|
||||
|
||||
import static org.openhab.binding.pilight.internal.PilightBindingConstants.*;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.pilight.internal.handler.PilightBridgeHandler;
|
||||
import org.openhab.binding.pilight.internal.handler.PilightContactHandler;
|
||||
import org.openhab.binding.pilight.internal.handler.PilightDimmerHandler;
|
||||
import org.openhab.binding.pilight.internal.handler.PilightGenericHandler;
|
||||
import org.openhab.binding.pilight.internal.handler.PilightSwitchHandler;
|
||||
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.openhab.core.thing.type.ChannelTypeRegistry;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
|
||||
/**
|
||||
* The {@link PilightHandlerFactory} is responsible for creating things and thing
|
||||
* handlers.
|
||||
*
|
||||
* @author Stefan Röllin - Initial contribution
|
||||
* @author Niklas Dörfler - Port pilight binding to openHAB 3 + add device discovery
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(configurationPid = "binding.pilight", service = ThingHandlerFactory.class)
|
||||
public class PilightHandlerFactory extends BaseThingHandlerFactory {
|
||||
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_BRIDGE, THING_TYPE_CONTACT,
|
||||
THING_TYPE_DIMMER, THING_TYPE_GENERIC, THING_TYPE_SWITCH);
|
||||
|
||||
private final ChannelTypeRegistry channelTypeRegistry;
|
||||
|
||||
@Activate
|
||||
public PilightHandlerFactory(@Reference ChannelTypeRegistry channelTypeRegistry) {
|
||||
this.channelTypeRegistry = channelTypeRegistry;
|
||||
}
|
||||
|
||||
@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_TYPE_BRIDGE.equals(thingTypeUID)) {
|
||||
return new PilightBridgeHandler((Bridge) thing);
|
||||
}
|
||||
|
||||
if (THING_TYPE_CONTACT.equals(thingTypeUID)) {
|
||||
return new PilightContactHandler(thing);
|
||||
}
|
||||
|
||||
if (THING_TYPE_DIMMER.equals(thingTypeUID)) {
|
||||
return new PilightDimmerHandler(thing);
|
||||
}
|
||||
|
||||
if (THING_TYPE_GENERIC.equals(thingTypeUID)) {
|
||||
return new PilightGenericHandler(thing, channelTypeRegistry);
|
||||
}
|
||||
|
||||
if (THING_TYPE_SWITCH.equals(thingTypeUID)) {
|
||||
return new PilightSwitchHandler(thing);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,150 @@
|
||||
/**
|
||||
* 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.pilight.internal.discovery;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.pilight.internal.PilightBindingConstants;
|
||||
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.config.discovery.DiscoveryService;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link PilightBridgeDiscoveryService} is responsible for discovering new pilight daemons on the network
|
||||
* by sending a ssdp multicast request via udp.
|
||||
*
|
||||
* @author Niklas Dörfler - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(service = DiscoveryService.class, immediate = true, configurationPid = "discovery.pilight")
|
||||
public class PilightBridgeDiscoveryService extends AbstractDiscoveryService {
|
||||
|
||||
private static final int AUTODISCOVERY_SEARCH_TIME_SEC = 5;
|
||||
private static final int AUTODISCOVERY_BACKGROUND_SEARCH_INTERVAL_SEC = 60 * 10;
|
||||
|
||||
private static final String SSDP_DISCOVERY_REQUEST_MESSAGE = "M-SEARCH * HTTP/1.1\r\n"
|
||||
+ "Host:239.255.255.250:1900\r\n" + "ST:urn:schemas-upnp-org:service:pilight:1\r\n"
|
||||
+ "Man:\"ssdp:discover\"\r\n" + "MX:3\r\n\r\n";
|
||||
public static final String SSDP_MULTICAST_ADDRESS = "239.255.255.250";
|
||||
public static final int SSDP_PORT = 1900;
|
||||
public static final int SSDP_WAIT_TIMEOUT = 2000; // in milliseconds
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(PilightBridgeDiscoveryService.class);
|
||||
|
||||
private @Nullable ScheduledFuture<?> backgroundDiscoveryJob;
|
||||
|
||||
public PilightBridgeDiscoveryService() throws IllegalArgumentException {
|
||||
super(getSupportedThingTypeUIDs(), AUTODISCOVERY_SEARCH_TIME_SEC, true);
|
||||
}
|
||||
|
||||
public static Set<ThingTypeUID> getSupportedThingTypeUIDs() {
|
||||
return Collections.singleton(PilightBindingConstants.THING_TYPE_BRIDGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startScan() {
|
||||
logger.debug("Pilight bridge discovery scan started");
|
||||
removeOlderResults(getTimestampOfLastScan());
|
||||
try {
|
||||
List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
|
||||
for (NetworkInterface nic : interfaces) {
|
||||
Enumeration<InetAddress> inetAddresses = nic.getInetAddresses();
|
||||
for (InetAddress inetAddress : Collections.list(inetAddresses)) {
|
||||
if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) {
|
||||
DatagramSocket ssdp = new DatagramSocket(
|
||||
new InetSocketAddress(inetAddress.getHostAddress(), 0));
|
||||
byte[] buff = SSDP_DISCOVERY_REQUEST_MESSAGE.getBytes(StandardCharsets.UTF_8);
|
||||
DatagramPacket sendPack = new DatagramPacket(buff, buff.length);
|
||||
sendPack.setAddress(InetAddress.getByName(SSDP_MULTICAST_ADDRESS));
|
||||
sendPack.setPort(SSDP_PORT);
|
||||
ssdp.send(sendPack);
|
||||
ssdp.setSoTimeout(SSDP_WAIT_TIMEOUT);
|
||||
|
||||
boolean loop = true;
|
||||
while (loop) {
|
||||
DatagramPacket recvPack = new DatagramPacket(new byte[1024], 1024);
|
||||
ssdp.receive(recvPack);
|
||||
byte[] recvData = recvPack.getData();
|
||||
|
||||
final Scanner scanner = new Scanner(new ByteArrayInputStream(recvData),
|
||||
StandardCharsets.UTF_8);
|
||||
loop = scanner.findAll("Location:([0-9.]+):(.*)").peek(matchResult -> {
|
||||
final String server = matchResult.group(1);
|
||||
final Integer port = Integer.parseInt(matchResult.group(2));
|
||||
final String bridgeName = server.replace(".", "") + "" + port;
|
||||
|
||||
logger.debug("Found pilight daemon at {}:{}", server, port);
|
||||
|
||||
Map<String, Object> properties = new HashMap<>();
|
||||
properties.put(PilightBindingConstants.PROPERTY_IP_ADDRESS, server);
|
||||
properties.put(PilightBindingConstants.PROPERTY_PORT, port);
|
||||
properties.put(PilightBindingConstants.PROPERTY_NAME, bridgeName);
|
||||
|
||||
ThingUID uid = new ThingUID(PilightBindingConstants.THING_TYPE_BRIDGE, bridgeName);
|
||||
|
||||
DiscoveryResult result = DiscoveryResultBuilder.create(uid).withProperties(properties)
|
||||
.withRepresentationProperty(PilightBindingConstants.PROPERTY_NAME)
|
||||
.withLabel("Pilight Bridge (" + server + ")").build();
|
||||
|
||||
thingDiscovered(result);
|
||||
}).count() == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (e.getMessage() != null && !"Receive timed out".equals(e.getMessage())) {
|
||||
logger.warn("Unable to enumerate the local network interfaces {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected synchronized void stopScan() {
|
||||
super.stopScan();
|
||||
removeOlderResults(getTimestampOfLastScan());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startBackgroundDiscovery() {
|
||||
logger.debug("Start Pilight device background discovery");
|
||||
final @Nullable ScheduledFuture<?> backgroundDiscoveryJob = this.backgroundDiscoveryJob;
|
||||
if (backgroundDiscoveryJob == null || backgroundDiscoveryJob.isCancelled()) {
|
||||
this.backgroundDiscoveryJob = scheduler.scheduleWithFixedDelay(this::startScan, 5,
|
||||
AUTODISCOVERY_BACKGROUND_SEARCH_INTERVAL_SEC, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stopBackgroundDiscovery() {
|
||||
logger.debug("Stop Pilight device background discovery");
|
||||
final @Nullable ScheduledFuture<?> backgroundDiscoveryJob = this.backgroundDiscoveryJob;
|
||||
if (backgroundDiscoveryJob != null) {
|
||||
backgroundDiscoveryJob.cancel(true);
|
||||
this.backgroundDiscoveryJob = null;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,223 @@
|
||||
/**
|
||||
* 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.pilight.internal.discovery;
|
||||
|
||||
import static org.openhab.binding.pilight.internal.PilightBindingConstants.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.pilight.internal.PilightHandlerFactory;
|
||||
import org.openhab.binding.pilight.internal.dto.Config;
|
||||
import org.openhab.binding.pilight.internal.dto.DeviceType;
|
||||
import org.openhab.binding.pilight.internal.dto.Status;
|
||||
import org.openhab.binding.pilight.internal.handler.PilightBridgeHandler;
|
||||
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;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link PilightDeviceDiscoveryService} discovers pilight devices after a bridge thing has been created and
|
||||
* connected to the pilight daemon. Things are discovered periodically in the background or after a manual trigger.
|
||||
*
|
||||
* @author Niklas Dörfler - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PilightDeviceDiscoveryService extends AbstractDiscoveryService implements ThingHandlerService {
|
||||
|
||||
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = PilightHandlerFactory.SUPPORTED_THING_TYPES_UIDS;
|
||||
|
||||
private static final int AUTODISCOVERY_SEARCH_TIME_SEC = 10;
|
||||
private static final int AUTODISCOVERY_BACKGROUND_SEARCH_INTERVAL_SEC = 60 * 10;
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(PilightDeviceDiscoveryService.class);
|
||||
|
||||
private @Nullable PilightBridgeHandler pilightBridgeHandler;
|
||||
private @Nullable ThingUID bridgeUID;
|
||||
|
||||
private @Nullable ScheduledFuture<?> backgroundDiscoveryJob;
|
||||
private CompletableFuture<Config> configFuture;
|
||||
private CompletableFuture<List<Status>> statusFuture;
|
||||
|
||||
public PilightDeviceDiscoveryService() {
|
||||
super(SUPPORTED_THING_TYPES_UIDS, AUTODISCOVERY_SEARCH_TIME_SEC);
|
||||
configFuture = new CompletableFuture<>();
|
||||
statusFuture = new CompletableFuture<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startScan() {
|
||||
if (pilightBridgeHandler != null) {
|
||||
configFuture = new CompletableFuture<>();
|
||||
statusFuture = new CompletableFuture<>();
|
||||
|
||||
configFuture.thenAcceptBoth(statusFuture, (config, allStatus) -> {
|
||||
removeOlderResults(getTimestampOfLastScan(), bridgeUID);
|
||||
config.getDevices().forEach((deviceId, device) -> {
|
||||
if (this.pilightBridgeHandler != null) {
|
||||
final Optional<Status> status = allStatus.stream()
|
||||
.filter(s -> s.getDevices().contains(deviceId)).findFirst();
|
||||
|
||||
final ThingTypeUID thingTypeUID;
|
||||
final String typeString;
|
||||
|
||||
if (status.isPresent()) {
|
||||
if (status.get().getType().equals(DeviceType.SWITCH)) {
|
||||
thingTypeUID = new ThingTypeUID(BINDING_ID, THING_TYPE_SWITCH.getId());
|
||||
typeString = "Switch";
|
||||
} else if (status.get().getType().equals(DeviceType.DIMMER)) {
|
||||
thingTypeUID = new ThingTypeUID(BINDING_ID, THING_TYPE_DIMMER.getId());
|
||||
typeString = "Dimmer";
|
||||
} else if (status.get().getType().equals(DeviceType.VALUE)) {
|
||||
thingTypeUID = new ThingTypeUID(BINDING_ID, THING_TYPE_GENERIC.getId());
|
||||
typeString = "Generic";
|
||||
} else if (status.get().getType().equals(DeviceType.CONTACT)) {
|
||||
thingTypeUID = new ThingTypeUID(BINDING_ID, THING_TYPE_CONTACT.getId());
|
||||
typeString = "Contact";
|
||||
} else {
|
||||
thingTypeUID = new ThingTypeUID(BINDING_ID, THING_TYPE_GENERIC.getId());
|
||||
typeString = "Generic";
|
||||
}
|
||||
} else {
|
||||
thingTypeUID = new ThingTypeUID(BINDING_ID, THING_TYPE_GENERIC.getId());
|
||||
typeString = "Generic";
|
||||
}
|
||||
|
||||
final @Nullable PilightBridgeHandler pilightBridgeHandler = this.pilightBridgeHandler;
|
||||
if (pilightBridgeHandler != null) {
|
||||
final ThingUID thingUID = new ThingUID(thingTypeUID,
|
||||
pilightBridgeHandler.getThing().getUID(), deviceId);
|
||||
|
||||
final Map<String, Object> properties = new HashMap<>();
|
||||
properties.put(PROPERTY_NAME, deviceId);
|
||||
|
||||
DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID)
|
||||
.withThingType(thingTypeUID).withProperties(properties).withBridge(bridgeUID)
|
||||
.withRepresentationProperty(PROPERTY_NAME)
|
||||
.withLabel("Pilight " + typeString + " Device '" + deviceId + "'").build();
|
||||
|
||||
thingDiscovered(discoveryResult);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
final @Nullable PilightBridgeHandler pilightBridgeHandler = this.pilightBridgeHandler;
|
||||
if (pilightBridgeHandler != null) {
|
||||
pilightBridgeHandler.refreshConfigAndStatus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected synchronized void stopScan() {
|
||||
super.stopScan();
|
||||
configFuture.cancel(true);
|
||||
statusFuture.cancel(true);
|
||||
if (bridgeUID != null) {
|
||||
removeOlderResults(getTimestampOfLastScan(), bridgeUID);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startBackgroundDiscovery() {
|
||||
logger.debug("Start Pilight device background discovery");
|
||||
final @Nullable ScheduledFuture<?> backgroundDiscoveryJob = this.backgroundDiscoveryJob;
|
||||
if (backgroundDiscoveryJob == null || backgroundDiscoveryJob.isCancelled()) {
|
||||
this.backgroundDiscoveryJob = scheduler.scheduleWithFixedDelay(this::startScan, 20,
|
||||
AUTODISCOVERY_BACKGROUND_SEARCH_INTERVAL_SEC, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stopBackgroundDiscovery() {
|
||||
logger.debug("Stop Pilight device background discovery");
|
||||
final @Nullable ScheduledFuture<?> backgroundDiscoveryJob = this.backgroundDiscoveryJob;
|
||||
if (backgroundDiscoveryJob != null) {
|
||||
backgroundDiscoveryJob.cancel(true);
|
||||
this.backgroundDiscoveryJob = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setThingHandler(final ThingHandler handler) {
|
||||
if (handler instanceof PilightBridgeHandler) {
|
||||
this.pilightBridgeHandler = (PilightBridgeHandler) handler;
|
||||
final @Nullable PilightBridgeHandler pilightBridgeHandler = this.pilightBridgeHandler;
|
||||
if (pilightBridgeHandler != null) {
|
||||
bridgeUID = pilightBridgeHandler.getThing().getUID();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ThingHandler getThingHandler() {
|
||||
return pilightBridgeHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activate() {
|
||||
super.activate(null);
|
||||
final @Nullable PilightBridgeHandler pilightBridgeHandler = this.pilightBridgeHandler;
|
||||
if (pilightBridgeHandler != null) {
|
||||
pilightBridgeHandler.registerDiscoveryListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deactivate() {
|
||||
if (bridgeUID != null) {
|
||||
removeOlderResults(getTimestampOfLastScan(), bridgeUID);
|
||||
}
|
||||
|
||||
final @Nullable PilightBridgeHandler pilightBridgeHandler = this.pilightBridgeHandler;
|
||||
if (pilightBridgeHandler != null) {
|
||||
pilightBridgeHandler.unregisterDiscoveryListener();
|
||||
}
|
||||
|
||||
super.deactivate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to get pilight device config into the discovery class.
|
||||
*
|
||||
* @param config config to get
|
||||
*/
|
||||
public void setConfig(Config config) {
|
||||
configFuture.complete(config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to get pilight device status list into the discovery class.
|
||||
*
|
||||
* @param status list of status objects
|
||||
*/
|
||||
public void setStatus(List<Status> status) {
|
||||
statusFuture.complete(status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<ThingTypeUID> getSupportedThingTypes() {
|
||||
return SUPPORTED_THING_TYPES_UIDS;
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
/**
|
||||
* 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.pilight.internal.dto;
|
||||
|
||||
/**
|
||||
* This message is sent when we want to change the state of a device or request the
|
||||
* current configuration in pilight.
|
||||
*
|
||||
* @author Jeroen Idserda - Initial contribution
|
||||
* @author Stefan Röllin - Port to openHAB 2 pilight binding
|
||||
* @author Niklas Dörfler - Port pilight binding to openHAB 3 + add device discovery
|
||||
*/
|
||||
public class Action {
|
||||
|
||||
public static final String ACTION_SEND = "send";
|
||||
|
||||
public static final String ACTION_CONTROL = "control";
|
||||
|
||||
public static final String ACTION_REQUEST_CONFIG = "request config";
|
||||
|
||||
public static final String ACTION_REQUEST_VALUES = "request values";
|
||||
|
||||
private String action;
|
||||
|
||||
private Code code;
|
||||
|
||||
private Options options;
|
||||
|
||||
public Action(String action) {
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
public String getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
public void setAction(String action) {
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
public Code getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(Code code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public Options getOptions() {
|
||||
return options;
|
||||
}
|
||||
|
||||
public void setOptions(Options options) {
|
||||
this.options = options;
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/**
|
||||
* 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.pilight.internal.dto;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* All status messages.
|
||||
*
|
||||
* @author Stefan Röllin - Initial contribution
|
||||
* @author Niklas Dörfler - Port pilight binding to openHAB 3 + add device discovery
|
||||
*/
|
||||
public class AllStatus {
|
||||
|
||||
private String message;
|
||||
|
||||
private List<Status> values = new ArrayList<>();
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public List<Status> getValues() {
|
||||
return values;
|
||||
}
|
||||
|
||||
public void setValues(List<Status> values) {
|
||||
this.values = values;
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
/**
|
||||
* 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.pilight.internal.dto;
|
||||
|
||||
/**
|
||||
* Part of the {@link Action} message that is sent to pilight.
|
||||
* This contains the desired state for a single device.
|
||||
*
|
||||
* {@link http://www.pilight.org/development/api/#sender}
|
||||
*
|
||||
* @author Jeroen Idserda - Initial contribution
|
||||
* @author Stefan Röllin - Port to openHAB 2 pilight binding
|
||||
* @author Niklas Dörfler - Port pilight binding to openHAB 3 + add device discovery
|
||||
*/
|
||||
public class Code {
|
||||
|
||||
public static final String STATE_ON = "on";
|
||||
|
||||
public static final String STATE_OFF = "off";
|
||||
|
||||
private String device;
|
||||
|
||||
private String state;
|
||||
|
||||
private Values values;
|
||||
|
||||
public String getDevice() {
|
||||
return device;
|
||||
}
|
||||
|
||||
public void setDevice(String device) {
|
||||
this.device = device;
|
||||
}
|
||||
|
||||
public String getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public void setState(String state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public Values getValues() {
|
||||
return values;
|
||||
}
|
||||
|
||||
public void setValues(Values values) {
|
||||
this.values = values;
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/**
|
||||
* 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.pilight.internal.dto;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
/**
|
||||
* pilight configuration object
|
||||
*
|
||||
* {@link http://www.pilight.org/development/api/#controller}
|
||||
*
|
||||
* @author Jeroen Idserda - Initial contribution
|
||||
* @author Stefan Röllin - Port to openHAB 2 pilight binding
|
||||
* @author Niklas Dörfler - Port pilight binding to openHAB 3 + add device discovery
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class Config {
|
||||
|
||||
private Map<String, Device> devices;
|
||||
|
||||
public Map<String, Device> getDevices() {
|
||||
return devices;
|
||||
}
|
||||
|
||||
public void setDevices(Map<String, Device> devices) {
|
||||
this.devices = devices;
|
||||
}
|
||||
}
|
@ -0,0 +1,140 @@
|
||||
/**
|
||||
* 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.pilight.internal.dto;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAnySetter;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* Class describing a device in pilight
|
||||
*
|
||||
* @author Jeroen Idserda - Initial contribution
|
||||
* @author Stefan Röllin - Port to openHAB 2 pilight binding
|
||||
* @author Niklas Dörfler - Port pilight binding to openHAB 3 + add device discovery
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class Device {
|
||||
|
||||
private String uuid;
|
||||
|
||||
private String origin;
|
||||
|
||||
private String timestamp;
|
||||
|
||||
private List<String> protocol;
|
||||
|
||||
private String state;
|
||||
|
||||
private Integer dimlevel = null;
|
||||
|
||||
// @SerializedName("dimlevel-maximum")
|
||||
private Integer dimlevelMaximum = null;
|
||||
|
||||
private Integer dimlevelMinimum = null;
|
||||
|
||||
private List<Map<String, String>> id;
|
||||
|
||||
private Map<String, String> properties = new HashMap<>();
|
||||
|
||||
public String getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public void setUuid(String uuid) {
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
public String getOrigin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
public void setOrigin(String origin) {
|
||||
this.origin = origin;
|
||||
}
|
||||
|
||||
public String getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public void setTimestamp(String timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
public List<String> getProtocol() {
|
||||
return protocol;
|
||||
}
|
||||
|
||||
public void setProtocol(List<String> protocol) {
|
||||
this.protocol = protocol;
|
||||
}
|
||||
|
||||
public String getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public void setState(String state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public Integer getDimlevel() {
|
||||
return dimlevel;
|
||||
}
|
||||
|
||||
public void setDimlevel(Integer dimlevel) {
|
||||
this.dimlevel = dimlevel;
|
||||
}
|
||||
|
||||
public Integer getDimlevelMaximum() {
|
||||
return dimlevelMaximum;
|
||||
}
|
||||
|
||||
@JsonProperty("dimlevel-maximum")
|
||||
public void setDimlevelMaximum(Integer dimlevelMaximum) {
|
||||
this.dimlevelMaximum = dimlevelMaximum;
|
||||
}
|
||||
|
||||
public Integer getDimlevelMinimum() {
|
||||
return dimlevelMinimum;
|
||||
}
|
||||
|
||||
@JsonProperty("dimlevel-minimum")
|
||||
public void setDimlevelMinimum(Integer dimlevelMinimum) {
|
||||
this.dimlevelMinimum = dimlevelMinimum;
|
||||
}
|
||||
|
||||
public List<Map<String, String>> getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(List<Map<String, String>> id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void setProperties(Map<String, String> properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
public Map<String, String> getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
@JsonAnySetter
|
||||
public void set(String name, Object value) {
|
||||
properties.put(name, value.toString());
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
/**
|
||||
* 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.pilight.internal.dto;
|
||||
|
||||
/**
|
||||
* Different types of devices in pilight
|
||||
*
|
||||
* @author Jeroen Idserda - Initial contribution
|
||||
* @author Stefan Röllin - Port to openHAB 2 pilight binding
|
||||
* @author Niklas Dörfler - Port pilight binding to openHAB 3 + add device discovery
|
||||
*/
|
||||
public class DeviceType {
|
||||
|
||||
public static final Integer SERVER = -1;
|
||||
|
||||
public static final Integer SWITCH = 1;
|
||||
|
||||
public static final Integer DIMMER = 2;
|
||||
|
||||
public static final Integer VALUE = 3;
|
||||
|
||||
public static final Integer CONTACT = 6;
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/**
|
||||
* 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.pilight.internal.dto;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* This object is sent to pilight right after the initial connection. It describes what kind of client we want to be.
|
||||
*
|
||||
* @author Jeroen Idserda - Initial contribution
|
||||
* @author Stefan Röllin - Port to openHAB 2 pilight binding
|
||||
* @author Niklas Dörfler - Port pilight binding to openHAB 3 + add device discovery
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class Identification {
|
||||
|
||||
public static final String ACTION_IDENTIFY = "identify";
|
||||
|
||||
private String action;
|
||||
|
||||
private Options options = new Options();
|
||||
|
||||
public Identification() {
|
||||
this.action = ACTION_IDENTIFY;
|
||||
}
|
||||
|
||||
public String getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
public void setAction(String action) {
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
public Options getOptions() {
|
||||
return options;
|
||||
}
|
||||
|
||||
public void setOptions(Options options) {
|
||||
this.options = options;
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
/**
|
||||
* 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.pilight.internal.dto;
|
||||
|
||||
/**
|
||||
* Wrapper for the {@code Config} object
|
||||
*
|
||||
* @author Jeroen Idserda - Initial contribution
|
||||
* @author Stefan Röllin - Port to openHAB 2 pilight binding
|
||||
* @author Niklas Dörfler - Port pilight binding to openHAB 3 + add device discovery
|
||||
*/
|
||||
public class Message {
|
||||
|
||||
private Config config;
|
||||
|
||||
private String message;
|
||||
|
||||
public Config getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public void setConfig(Config config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
}
|
@ -0,0 +1,116 @@
|
||||
/**
|
||||
* 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.pilight.internal.dto;
|
||||
|
||||
import org.openhab.binding.pilight.internal.serializers.BooleanToIntegerSerializer;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
|
||||
/**
|
||||
* Options that can be set as a pilight client.
|
||||
*
|
||||
* @author Jeroen Idserda - Initial contribution
|
||||
* @author Stefan Röllin - Port to openHAB 2 pilight binding
|
||||
* @author Niklas Dörfler - Port pilight binding to openHAB 3 + add device discovery
|
||||
*/
|
||||
public class Options {
|
||||
|
||||
public static final String MEDIA_ALL = "all";
|
||||
|
||||
public static final String MEDIA_WEB = "web";
|
||||
|
||||
public static final String MEDIA_MOBILE = "mobile";
|
||||
|
||||
public static final String MEDIA_DESKTOP = "desktop";
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@JsonSerialize(using = BooleanToIntegerSerializer.class)
|
||||
private Boolean core;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@JsonSerialize(using = BooleanToIntegerSerializer.class)
|
||||
private Boolean receiver;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@JsonSerialize(using = BooleanToIntegerSerializer.class)
|
||||
private Boolean config;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@JsonSerialize(using = BooleanToIntegerSerializer.class)
|
||||
private Boolean forward;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@JsonSerialize(using = BooleanToIntegerSerializer.class)
|
||||
private Boolean stats;
|
||||
|
||||
private String uuid;
|
||||
|
||||
private String media;
|
||||
|
||||
public Boolean getCore() {
|
||||
return core;
|
||||
}
|
||||
|
||||
public void setCore(Boolean core) {
|
||||
this.core = core;
|
||||
}
|
||||
|
||||
public Boolean getReceiver() {
|
||||
return receiver;
|
||||
}
|
||||
|
||||
public void setReceiver(Boolean receiver) {
|
||||
this.receiver = receiver;
|
||||
}
|
||||
|
||||
public Boolean getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public void setConfig(Boolean config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public Boolean getForward() {
|
||||
return forward;
|
||||
}
|
||||
|
||||
public void setForward(Boolean forward) {
|
||||
this.forward = forward;
|
||||
}
|
||||
|
||||
public Boolean getStats() {
|
||||
return stats;
|
||||
}
|
||||
|
||||
public void setStats(Boolean stats) {
|
||||
this.stats = stats;
|
||||
}
|
||||
|
||||
public String getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public void setUuid(String uuid) {
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
public String getMedia() {
|
||||
return media;
|
||||
}
|
||||
|
||||
public void setMedia(String media) {
|
||||
this.media = media;
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
/**
|
||||
* 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.pilight.internal.dto;
|
||||
|
||||
/**
|
||||
* Response to a connection or state change request
|
||||
*
|
||||
* @author Jeroen Idserda - Initial contribution
|
||||
* @author Stefan Röllin - Port to openHAB 2 pilight binding
|
||||
* @author Niklas Dörfler - Port pilight binding to openHAB 3 + add device discovery
|
||||
*/
|
||||
public class Response {
|
||||
|
||||
public static final String SUCCESS = "success";
|
||||
|
||||
public static final String FAILURE = "failure";
|
||||
|
||||
private String status;
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public boolean isSuccess() {
|
||||
return SUCCESS.equals(status);
|
||||
}
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
/**
|
||||
* 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.pilight.internal.dto;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A Status message is received when a device in pilight changes state.
|
||||
*
|
||||
* @author Jeroen Idserda - Initial contribution
|
||||
* @author Stefan Röllin - Port to openHAB 2 pilight binding
|
||||
* @author Niklas Dörfler - Port pilight binding to openHAB 3 + add device discovery
|
||||
*/
|
||||
public class Status {
|
||||
|
||||
private String origin;
|
||||
|
||||
private Integer type;
|
||||
|
||||
private String uuid;
|
||||
|
||||
private List<String> devices = new ArrayList<>();
|
||||
|
||||
private Map<String, String> values = new HashMap<>();
|
||||
|
||||
public Status() {
|
||||
}
|
||||
|
||||
public String getOrigin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
public void setOrigin(String origin) {
|
||||
this.origin = origin;
|
||||
}
|
||||
|
||||
public Integer getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(Integer type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public void setUuid(String uuid) {
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
public List<String> getDevices() {
|
||||
return devices;
|
||||
}
|
||||
|
||||
public void setDevices(List<String> devices) {
|
||||
this.devices = devices;
|
||||
}
|
||||
|
||||
public Map<String, String> getValues() {
|
||||
return values;
|
||||
}
|
||||
|
||||
public void setValues(Map<String, String> values) {
|
||||
this.values = values;
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
/**
|
||||
* 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.pilight.internal.dto;
|
||||
|
||||
/**
|
||||
* Describes the specific properties of a device
|
||||
*
|
||||
* @author Jeroen Idserda - Initial contribution
|
||||
* @author Stefan Röllin - Port to openHAB 2 pilight binding
|
||||
* @author Niklas Dörfler - Port pilight binding to openHAB 3 + add device discovery
|
||||
*/
|
||||
public class Values {
|
||||
|
||||
private Integer dimlevel;
|
||||
|
||||
public Integer getDimlevel() {
|
||||
return dimlevel;
|
||||
}
|
||||
|
||||
public void setDimlevel(Integer dimlevel) {
|
||||
this.dimlevel = dimlevel;
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/**
|
||||
* 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.pilight.internal.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
/**
|
||||
* pilight version information object
|
||||
*
|
||||
* {@link http://www.pilight.org/development/api/#controller}
|
||||
*
|
||||
* @author Niklas Dörfler - Initial contribution
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class Version {
|
||||
|
||||
private String version;
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(String version) {
|
||||
this.version = version;
|
||||
}
|
||||
}
|
@ -0,0 +1,127 @@
|
||||
/**
|
||||
* 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.pilight.internal.handler;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.pilight.internal.PilightDeviceConfiguration;
|
||||
import org.openhab.binding.pilight.internal.dto.Action;
|
||||
import org.openhab.binding.pilight.internal.dto.Config;
|
||||
import org.openhab.binding.pilight.internal.dto.Device;
|
||||
import org.openhab.binding.pilight.internal.dto.Status;
|
||||
import org.openhab.core.thing.*;
|
||||
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||
import org.openhab.core.thing.binding.BridgeHandler;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link PilightBaseHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Stefan Röllin - Initial contribution
|
||||
* @author Niklas Dörfler - Port pilight binding to openHAB 3 + add device discovery
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public abstract class PilightBaseHandler extends BaseThingHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(PilightBaseHandler.class);
|
||||
|
||||
private String name = "";
|
||||
|
||||
public PilightBaseHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
if (command instanceof RefreshType) {
|
||||
refreshConfigAndStatus();
|
||||
return;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
Action action = createUpdateCommand(channelUID, command);
|
||||
if (action != null) {
|
||||
sendAction(action);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
PilightDeviceConfiguration config = getConfigAs(PilightDeviceConfiguration.class);
|
||||
name = config.getName();
|
||||
|
||||
refreshConfigAndStatus();
|
||||
}
|
||||
|
||||
public void updateFromStatusIfMatches(Status status) {
|
||||
if (status.getDevices() != null && !status.getDevices().isEmpty()) {
|
||||
if (name.equals(status.getDevices().get(0))) {
|
||||
if (!ThingStatus.ONLINE.equals(getThing().getStatus())) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
}
|
||||
updateFromStatus(status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void updateFromConfigIfMatches(Config config) {
|
||||
Device device = config.getDevices().get(getName());
|
||||
if (device != null) {
|
||||
updateFromConfigDevice(device);
|
||||
}
|
||||
}
|
||||
|
||||
abstract void updateFromStatus(Status status);
|
||||
|
||||
abstract void updateFromConfigDevice(Device device);
|
||||
|
||||
abstract @Nullable Action createUpdateCommand(ChannelUID channelUID, Command command);
|
||||
|
||||
protected String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
private void sendAction(Action action) {
|
||||
final @Nullable PilightBridgeHandler handler = getPilightBridgeHandler();
|
||||
if (handler != null) {
|
||||
handler.sendAction(action);
|
||||
} else {
|
||||
logger.warn("No pilight bridge handler found to send action.");
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshConfigAndStatus() {
|
||||
final @Nullable PilightBridgeHandler handler = getPilightBridgeHandler();
|
||||
if (handler != null) {
|
||||
handler.refreshConfigAndStatus();
|
||||
} else {
|
||||
logger.warn("No pilight bridge handler found to refresh config and status.");
|
||||
}
|
||||
}
|
||||
|
||||
private @Nullable PilightBridgeHandler getPilightBridgeHandler() {
|
||||
final @Nullable Bridge bridge = getBridge();
|
||||
if (bridge != null) {
|
||||
@Nullable
|
||||
BridgeHandler handler = bridge.getHandler();
|
||||
if (handler instanceof PilightBridgeHandler) {
|
||||
return (PilightBridgeHandler) handler;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,233 @@
|
||||
/**
|
||||
* 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.pilight.internal.handler;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.pilight.internal.IPilightCallback;
|
||||
import org.openhab.binding.pilight.internal.PilightBridgeConfiguration;
|
||||
import org.openhab.binding.pilight.internal.PilightConnector;
|
||||
import org.openhab.binding.pilight.internal.discovery.PilightDeviceDiscoveryService;
|
||||
import org.openhab.binding.pilight.internal.dto.*;
|
||||
import org.openhab.core.common.NamedThreadFactory;
|
||||
import org.openhab.core.thing.*;
|
||||
import org.openhab.core.thing.binding.BaseBridgeHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerService;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link PilightBridgeHandler} is responsible dispatching commands for the child
|
||||
* things to the Pilight daemon and sending status updates to the child things.
|
||||
*
|
||||
* @author Stefan Röllin - Initial contribution
|
||||
* @author Niklas Dörfler - Port pilight binding to openHAB 3 + add device discovery
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PilightBridgeHandler extends BaseBridgeHandler {
|
||||
|
||||
private static final int REFRESH_CONFIG_MSEC = 500;
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(PilightBridgeHandler.class);
|
||||
|
||||
private @Nullable PilightConnector connector = null;
|
||||
|
||||
private @Nullable ScheduledFuture<?> refreshJob = null;
|
||||
|
||||
private @Nullable PilightDeviceDiscoveryService discoveryService = null;
|
||||
|
||||
private final ExecutorService connectorExecutor = Executors
|
||||
.newSingleThreadExecutor(new NamedThreadFactory(getThing().getUID().getAsString(), true));
|
||||
|
||||
public PilightBridgeHandler(Bridge bridge) {
|
||||
super(bridge);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
logger.debug("Pilight Bridge is read-only and does not handle commands.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
PilightBridgeConfiguration config = getConfigAs(PilightBridgeConfiguration.class);
|
||||
|
||||
final @Nullable PilightDeviceDiscoveryService discoveryService = this.discoveryService;
|
||||
PilightConnector connector = new PilightConnector(config, new IPilightCallback() {
|
||||
@Override
|
||||
public void updateThingStatus(ThingStatus status, ThingStatusDetail statusDetail,
|
||||
@Nullable String description) {
|
||||
updateStatus(status, statusDetail, description);
|
||||
if (status == ThingStatus.ONLINE) {
|
||||
refreshConfigAndStatus();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void statusReceived(List<Status> allStatus) {
|
||||
for (Status status : allStatus) {
|
||||
processStatus(status);
|
||||
}
|
||||
|
||||
if (discoveryService != null) {
|
||||
discoveryService.setStatus(allStatus);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configReceived(Config config) {
|
||||
processConfig(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void versionReceived(Version version) {
|
||||
getThing().setProperty(Thing.PROPERTY_FIRMWARE_VERSION, version.getVersion());
|
||||
}
|
||||
}, scheduler);
|
||||
|
||||
updateStatus(ThingStatus.UNKNOWN);
|
||||
|
||||
connectorExecutor.execute(connector);
|
||||
this.connector = connector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
final @Nullable ScheduledFuture<?> future = this.refreshJob;
|
||||
if (future != null) {
|
||||
future.cancel(true);
|
||||
}
|
||||
|
||||
final @Nullable PilightConnector connector = this.connector;
|
||||
if (connector != null) {
|
||||
connector.close();
|
||||
this.connector = null;
|
||||
}
|
||||
|
||||
connectorExecutor.shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* send action to pilight daemon
|
||||
*
|
||||
* @param action action to send
|
||||
*/
|
||||
public void sendAction(Action action) {
|
||||
final @Nullable PilightConnector connector = this.connector;
|
||||
if (connector != null) {
|
||||
connector.sendAction(action);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* refresh config and status by requesting config and all values from pilight daemon
|
||||
*/
|
||||
public synchronized void refreshConfigAndStatus() {
|
||||
if (thing.getStatus() == ThingStatus.ONLINE) {
|
||||
final @Nullable ScheduledFuture<?> refreshJob = this.refreshJob;
|
||||
if (refreshJob == null || refreshJob.isCancelled() || refreshJob.isDone()) {
|
||||
logger.debug("schedule refresh of config and status");
|
||||
this.refreshJob = scheduler.schedule(this::doRefreshConfigAndStatus, REFRESH_CONFIG_MSEC,
|
||||
TimeUnit.MILLISECONDS);
|
||||
}
|
||||
} else {
|
||||
logger.warn("Bridge is not online - ignoring refresh of config and status.");
|
||||
}
|
||||
}
|
||||
|
||||
private void doRefreshConfigAndStatus() {
|
||||
final @Nullable PilightConnector connector = this.connector;
|
||||
if (connector != null) {
|
||||
// the config is required for dimmers to get the minimum and maximum dim levels
|
||||
connector.refreshConfig();
|
||||
connector.refreshStatus();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a status update received from pilight
|
||||
*
|
||||
* @param status The new Status
|
||||
*/
|
||||
private void processStatus(Status status) {
|
||||
final Integer type = status.getType();
|
||||
logger.trace("processStatus device '{}' type {}", status.getDevices().get(0), type);
|
||||
|
||||
if (!DeviceType.SERVER.equals(type)) {
|
||||
for (Thing thing : getThing().getThings()) {
|
||||
final @Nullable ThingHandler handler = thing.getHandler();
|
||||
if (handler instanceof PilightBaseHandler) {
|
||||
((PilightBaseHandler) handler).updateFromStatusIfMatches(status);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Class<? extends ThingHandlerService>> getServices() {
|
||||
return Collections.singleton(PilightDeviceDiscoveryService.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register discovery service to this bridge instance.
|
||||
*/
|
||||
public boolean registerDiscoveryListener(PilightDeviceDiscoveryService listener) {
|
||||
if (discoveryService == null) {
|
||||
discoveryService = listener;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister discovery service from this bridge instance.
|
||||
*/
|
||||
public boolean unregisterDiscoveryListener() {
|
||||
if (discoveryService != null) {
|
||||
discoveryService = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a config received from pilight
|
||||
*
|
||||
* @param config The new config
|
||||
*/
|
||||
private void processConfig(Config config) {
|
||||
for (Thing thing : getThing().getThings()) {
|
||||
final @Nullable ThingHandler handler = thing.getHandler();
|
||||
if (handler instanceof PilightBaseHandler) {
|
||||
((PilightBaseHandler) handler).updateFromConfigIfMatches(config);
|
||||
}
|
||||
}
|
||||
|
||||
final @Nullable PilightDeviceDiscoveryService discoveryService = this.discoveryService;
|
||||
if (discoveryService != null) {
|
||||
discoveryService.setConfig(config);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
/**
|
||||
* 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.pilight.internal.handler;
|
||||
|
||||
import static org.openhab.binding.pilight.internal.PilightBindingConstants.CHANNEL_STATE;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.pilight.internal.dto.Action;
|
||||
import org.openhab.binding.pilight.internal.dto.Device;
|
||||
import org.openhab.binding.pilight.internal.dto.Status;
|
||||
import org.openhab.binding.pilight.internal.types.PilightContactType;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link PilightContactHandler} is responsible for handling a pilight contact.
|
||||
*
|
||||
* @author Stefan Röllin - Initial contribution
|
||||
* @author Niklas Dörfler - Port pilight binding to openHAB 3 + add device discovery
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PilightContactHandler extends PilightBaseHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(PilightContactHandler.class);
|
||||
|
||||
public PilightContactHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateFromStatus(Status status) {
|
||||
String state = status.getValues().get("state");
|
||||
if (state != null) {
|
||||
updateState(CHANNEL_STATE, PilightContactType.valueOf(state.toUpperCase()).toOpenClosedType());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void updateFromConfigDevice(Device device) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable Action createUpdateCommand(ChannelUID channelUID, Command command) {
|
||||
logger.warn("A contact is a read only device");
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,126 @@
|
||||
/**
|
||||
* 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.pilight.internal.handler;
|
||||
|
||||
import static org.openhab.binding.pilight.internal.PilightBindingConstants.CHANNEL_DIMLEVEL;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.pilight.internal.dto.Action;
|
||||
import org.openhab.binding.pilight.internal.dto.Code;
|
||||
import org.openhab.binding.pilight.internal.dto.Device;
|
||||
import org.openhab.binding.pilight.internal.dto.Status;
|
||||
import org.openhab.binding.pilight.internal.dto.Values;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.PercentType;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.State;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link PilightDimmerHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Stefan Röllin - Initial contribution
|
||||
* @author Niklas Dörfler - Port pilight binding to openHAB 3 + add device discovery
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PilightDimmerHandler extends PilightBaseHandler {
|
||||
|
||||
private static final int MAX_DIM_LEVEL_DEFAULT = 15;
|
||||
private static final BigDecimal BIG_DECIMAL_100 = new BigDecimal(100);
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(PilightDimmerHandler.class);
|
||||
|
||||
private int maxDimLevel = MAX_DIM_LEVEL_DEFAULT;
|
||||
|
||||
public PilightDimmerHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateFromStatus(Status status) {
|
||||
BigDecimal dimLevel = BigDecimal.ZERO;
|
||||
String dimLevelAsString = status.getValues().get("dimlevel");
|
||||
|
||||
if (dimLevelAsString != null) {
|
||||
dimLevel = getPercentageFromDimLevel(dimLevelAsString);
|
||||
} else {
|
||||
// Dimmer items can can also be switched on or off in pilight.
|
||||
// When this happens, the dimmer value is not reported. At least we know it's on or off.
|
||||
String stateAsString = status.getValues().get("state");
|
||||
if (stateAsString != null) {
|
||||
State state = OnOffType.valueOf(stateAsString.toUpperCase());
|
||||
dimLevel = state.equals(OnOffType.ON) ? BIG_DECIMAL_100 : BigDecimal.ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
State state = new PercentType(dimLevel);
|
||||
updateState(CHANNEL_DIMLEVEL, state);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateFromConfigDevice(Device device) {
|
||||
Integer max = device.getDimlevelMaximum();
|
||||
|
||||
if (max != null) {
|
||||
maxDimLevel = max;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable Action createUpdateCommand(ChannelUID unused, Command command) {
|
||||
Code code = new Code();
|
||||
code.setDevice(getName());
|
||||
|
||||
if (command instanceof OnOffType) {
|
||||
code.setState(command.equals(OnOffType.ON) ? Code.STATE_ON : Code.STATE_OFF);
|
||||
} else if (command instanceof PercentType) {
|
||||
setDimmerValue((PercentType) command, code);
|
||||
} else {
|
||||
logger.warn("Only OnOffType and PercentType are supported by a dimmer.");
|
||||
return null;
|
||||
}
|
||||
|
||||
Action action = new Action(Action.ACTION_CONTROL);
|
||||
action.setCode(code);
|
||||
return action;
|
||||
}
|
||||
|
||||
private BigDecimal getPercentageFromDimLevel(String string) {
|
||||
return new BigDecimal(string).setScale(2).divide(new BigDecimal(maxDimLevel), RoundingMode.HALF_UP)
|
||||
.multiply(BIG_DECIMAL_100);
|
||||
}
|
||||
|
||||
private void setDimmerValue(PercentType percent, Code code) {
|
||||
if (PercentType.ZERO.equals(percent)) {
|
||||
// pilight is not responding to commands that set both the dimlevel to 0 and state to off.
|
||||
// So, we're only updating the state for now
|
||||
code.setState(Code.STATE_OFF);
|
||||
} else {
|
||||
BigDecimal dimlevel = percent.toBigDecimal().setScale(2).divide(BIG_DECIMAL_100, RoundingMode.HALF_UP)
|
||||
.multiply(BigDecimal.valueOf(maxDimLevel)).setScale(0, RoundingMode.HALF_UP);
|
||||
|
||||
Values values = new Values();
|
||||
values.setDimlevel(dimlevel.intValue());
|
||||
code.setValues(values);
|
||||
code.setState(dimlevel.compareTo(BigDecimal.ZERO) == 1 ? Code.STATE_ON : Code.STATE_OFF);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,138 @@
|
||||
/**
|
||||
* 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.pilight.internal.handler;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.pilight.internal.PilightChannelConfiguration;
|
||||
import org.openhab.binding.pilight.internal.dto.Action;
|
||||
import org.openhab.binding.pilight.internal.dto.Device;
|
||||
import org.openhab.binding.pilight.internal.dto.Status;
|
||||
import org.openhab.core.library.CoreItemFactory;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.thing.Channel;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.type.ChannelType;
|
||||
import org.openhab.core.thing.type.ChannelTypeRegistry;
|
||||
import org.openhab.core.thing.type.ChannelTypeUID;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.core.types.StateDescription;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link PilightGenericHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Stefan Röllin - Initial contribution
|
||||
* @author Niklas Dörfler - Port pilight binding to openHAB 3 + add device discovery
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PilightGenericHandler extends PilightBaseHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(PilightGenericHandler.class);
|
||||
|
||||
private final ChannelTypeRegistry channelTypeRegistry;
|
||||
|
||||
private final Map<ChannelUID, Boolean> channelReadOnlyMap = new HashMap<>();
|
||||
|
||||
public PilightGenericHandler(Thing thing, ChannelTypeRegistry channelTypeRegistry) {
|
||||
super(thing);
|
||||
this.channelTypeRegistry = channelTypeRegistry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
initializeReadOnlyChannels();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateFromStatus(Status status) {
|
||||
for (Channel channel : thing.getChannels()) {
|
||||
PilightChannelConfiguration config = channel.getConfiguration().as(PilightChannelConfiguration.class);
|
||||
updateState(channel.getUID(),
|
||||
getDynamicChannelState(channel, status.getValues().get(config.getProperty())));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void updateFromConfigDevice(Device device) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable Action createUpdateCommand(ChannelUID channelUID, Command command) {
|
||||
if (isChannelReadOnly(channelUID)) {
|
||||
logger.debug("Can't apply command '{}' to '{}' because channel is readonly.", command, channelUID.getId());
|
||||
return null;
|
||||
}
|
||||
|
||||
logger.debug("Create update command for '{}' not implemented.", channelUID.getId());
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private State getDynamicChannelState(final Channel channel, final @Nullable String value) {
|
||||
final @Nullable String acceptedItemType = channel.getAcceptedItemType();
|
||||
|
||||
if (value == null || acceptedItemType == null) {
|
||||
return UnDefType.UNDEF;
|
||||
}
|
||||
|
||||
switch (acceptedItemType) {
|
||||
case CoreItemFactory.NUMBER:
|
||||
return new DecimalType(value);
|
||||
case CoreItemFactory.STRING:
|
||||
return StringType.valueOf(value);
|
||||
case CoreItemFactory.SWITCH:
|
||||
return OnOffType.from(value);
|
||||
default:
|
||||
logger.trace("Type '{}' for channel '{}' not implemented", channel.getAcceptedItemType(), channel);
|
||||
return UnDefType.UNDEF;
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeReadOnlyChannels() {
|
||||
channelReadOnlyMap.clear();
|
||||
for (Channel channel : thing.getChannels()) {
|
||||
final @Nullable ChannelTypeUID channelTypeUID = channel.getChannelTypeUID();
|
||||
if (channelTypeUID != null) {
|
||||
final @Nullable ChannelType channelType = channelTypeRegistry.getChannelType(channelTypeUID, null);
|
||||
|
||||
if (channelType != null) {
|
||||
logger.debug("initializeReadOnly {} {}", channelType, channelType.getState());
|
||||
}
|
||||
|
||||
if (channelType != null) {
|
||||
final @Nullable StateDescription state = channelType.getState();
|
||||
if (state != null) {
|
||||
channelReadOnlyMap.putIfAbsent(channel.getUID(), state.isReadOnly());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isChannelReadOnly(ChannelUID channelUID) {
|
||||
Boolean isReadOnly = channelReadOnlyMap.get(channelUID);
|
||||
return isReadOnly != null ? isReadOnly : true;
|
||||
}
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.pilight.internal.handler;
|
||||
|
||||
import static org.openhab.binding.pilight.internal.PilightBindingConstants.CHANNEL_STATE;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.pilight.internal.dto.Action;
|
||||
import org.openhab.binding.pilight.internal.dto.Code;
|
||||
import org.openhab.binding.pilight.internal.dto.Device;
|
||||
import org.openhab.binding.pilight.internal.dto.Status;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link PilightSwitchHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Stefan Röllin - Initial contribution
|
||||
* @author Niklas Dörfler - Port pilight binding to openHAB 3 + add device discovery
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PilightSwitchHandler extends PilightBaseHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(PilightSwitchHandler.class);
|
||||
|
||||
public PilightSwitchHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateFromStatus(Status status) {
|
||||
String state = status.getValues().get("state");
|
||||
if (state != null) {
|
||||
updateState(CHANNEL_STATE, OnOffType.valueOf(state.toUpperCase()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void updateFromConfigDevice(Device device) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable Action createUpdateCommand(ChannelUID unused, Command command) {
|
||||
if (command instanceof OnOffType) {
|
||||
Code code = new Code();
|
||||
code.setDevice(getName());
|
||||
code.setState(command.equals(OnOffType.ON) ? Code.STATE_ON : Code.STATE_OFF);
|
||||
|
||||
Action action = new Action(Action.ACTION_CONTROL);
|
||||
action.setCode(code);
|
||||
return action;
|
||||
}
|
||||
|
||||
logger.warn("A pilight switch only accepts OnOffType commands.");
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
/**
|
||||
* 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.pilight.internal.serializers;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
|
||||
/**
|
||||
* Serializer to map boolean values to an integer (1 and 0).
|
||||
*
|
||||
* @author Jeroen Idserda - Initial contribution
|
||||
* @author Stefan Röllin - Port to openHAB 2 pilight binding
|
||||
* @author Niklas Dörfler - Port pilight binding to openHAB 3 + add device discovery
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class BooleanToIntegerSerializer extends JsonSerializer<Boolean> {
|
||||
|
||||
@Override
|
||||
public void serialize(@Nullable Boolean bool, @Nullable JsonGenerator jsonGenerator,
|
||||
@Nullable SerializerProvider serializerProvider) throws IOException {
|
||||
if (bool != null && jsonGenerator != null) {
|
||||
jsonGenerator.writeObject(bool ? 1 : 0);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* 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.pilight.internal.types;
|
||||
|
||||
import org.openhab.core.library.types.OpenClosedType;
|
||||
|
||||
/**
|
||||
* Enum to represent the state of a contact sensor in pilight
|
||||
*
|
||||
* @author Jeroen Idserda - Initial contribution
|
||||
* @author Stefan Röllin - Port to openHAB 2 pilight binding
|
||||
* @author Niklas Dörfler - Port pilight binding to openHAB 3 + add device discovery
|
||||
*/
|
||||
public enum PilightContactType {
|
||||
OPENED,
|
||||
CLOSED;
|
||||
|
||||
public OpenClosedType toOpenClosedType() {
|
||||
return this.equals(PilightContactType.OPENED) ? OpenClosedType.OPEN : OpenClosedType.CLOSED;
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<binding:binding id="pilight" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:binding="https://openhab.org/schemas/binding/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd">
|
||||
|
||||
<name>Pilight Binding</name>
|
||||
<description>The pilight binding allows openHAB to communicate with a pilight instance. Pilight is a service used to
|
||||
control 'Click On Click Off' devices like 433 MHz remote controlled sockets a cheap way, e.g. by using a Raspberry Pi
|
||||
with corresponding 433 MHz sender.</description>
|
||||
|
||||
</binding:binding>
|
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<config-description:config-descriptions
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:config-description="https://openhab.org/schemas/config-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/config-description/v1.0.0
|
||||
https://openhab.org/schemas/config-description-1.0.0.xsd">
|
||||
|
||||
<config-description uri="thing-type:pilight:device">
|
||||
<parameter name="name" type="text" required="true">
|
||||
<label>Name of Device</label>
|
||||
<description>The name of the pilight device.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
</config-description:config-descriptions>
|
@ -0,0 +1,38 @@
|
||||
# binding
|
||||
binding.pilight.name = Pilight Binding
|
||||
binding.pilight.description = Das pilight-Binding ermöglicht openHAB die Kommunikation mit einer pilight-Instanz. Pilight ist ein Dienst, der verwendet wird, um 'Click On Click Off'-Geräte wie bspw. 433 MHz Funksteckdosen auf kostengünstige Weise zu steuern, z.B. durch Verwendung eines Raspberry Pi mit entsprechendem 433 MHz Sender.
|
||||
|
||||
# thing types
|
||||
thing-type.pilight.bridge.label = Pilight Bridge
|
||||
thing-type.pilight.bridge.description = Verbindung zwischen openHAB und einem pilight Daemon.
|
||||
|
||||
thing-type.pilight.contact.label = Pilight Kontakt
|
||||
thing-type.pilight.contact.description = Pilight Kontakt
|
||||
|
||||
thing-type.pilight.dimmer.label = Pilight Dimmer
|
||||
thing-type.pilight.dimmer.description = Pilight Dimmer
|
||||
|
||||
thing-type.pilight.switch.label = Pilight Schalter
|
||||
thing-type.pilight.switch.description = Pilight Schalter
|
||||
|
||||
thing-type.pilight.generic.label = Generisches pilight Gerät
|
||||
thing-type.pilight.generic.description = Gerät bei dem die Kanäle dynamisch hinzugefügt werden.
|
||||
|
||||
# thing type config description
|
||||
thing-type.config.pilight.bridge.ipAddress.label = IP-Adresse
|
||||
thing-type.config.pilight.bridge.ipAddress.description = Lokale IP-Adresse oder Hostname des pilight Daemons.
|
||||
thing-type.config.pilight.bridge.port.label = Port
|
||||
thing-type.config.pilight.bridge.port.description = Port des pilight Daemons.
|
||||
thing-type.config.pilight.bridge.delay.label = Verzögerung
|
||||
thing-type.config.pilight.bridge.delay.description = Verzögerung (in Millisekunden) zwischen zwei Kommandos. Empfohlener Wert ohne Bandpassfilter: 1000 und mit Bandpassfilter zwischen 200 und 500.
|
||||
|
||||
thing-type.config.pilight.device.name.label = Name
|
||||
thing-type.config.pilight.device.name.description = Name des pilight Geräts
|
||||
|
||||
# channel types
|
||||
channel-type.pilight.contact-state.label = Status
|
||||
channel-type.pilight.contact-state.description = Status des pilight Kontakts
|
||||
channel-type.pilight.switch-state.label = Status
|
||||
channel-type.pilight.switch-state.description = Status des pilight Schalters
|
||||
channel-type.pilight.dimlevel.label = Dimmerwert
|
||||
channel-type.pilight.dimlevel.description = Wert des pilight Dimmers
|
@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="pilight"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<bridge-type id="bridge">
|
||||
<label>Pilight Bridge</label>
|
||||
<description>Pilight Bridge which connects to a Pilight instance.</description>
|
||||
|
||||
<properties>
|
||||
<property name="firmwareVersion">-</property>
|
||||
</properties>
|
||||
|
||||
<config-description>
|
||||
<parameter name="ipAddress" type="text" required="true">
|
||||
<label>Network Address</label>
|
||||
<description>The IP or host name of the Pilight instance.</description>
|
||||
<context>network-address</context>
|
||||
</parameter>
|
||||
<parameter name="port" type="integer" required="true" min="1" max="65335">
|
||||
<label>Port</label>
|
||||
<description>Port of the Pilight daemon. You must explicitly configure the port in the Pilight daemon config or
|
||||
otherwise a random port will be used and the binding will not be able to connect.
|
||||
</description>
|
||||
<default>5000</default>
|
||||
</parameter>
|
||||
<parameter name="delay" type="integer" required="false" min="1" max="65335">
|
||||
<label>Delay between Commands</label>
|
||||
<description>Delay (in millisecond) between consecutive commands. Recommended value without band pass filter: 1000.
|
||||
Recommended value with band pass filter: somewhere between 200-500.</description>
|
||||
<default>500</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</bridge-type>
|
||||
|
||||
|
||||
</thing:thing-descriptions>
|
@ -0,0 +1,96 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="pilight"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<thing-type id="switch">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="bridge"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>Pilight Switch</label>
|
||||
<description>Pilight Switch</description>
|
||||
|
||||
<channels>
|
||||
<channel id="state" typeId="system.power"/>
|
||||
</channels>
|
||||
|
||||
<config-description-ref uri="thing-type:pilight:device"/>
|
||||
</thing-type>
|
||||
|
||||
<thing-type id="contact">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="bridge"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>Pilight Contact</label>
|
||||
<description>Pilight Contact</description>
|
||||
|
||||
<channels>
|
||||
<channel id="state" typeId="contact-state"/>
|
||||
</channels>
|
||||
|
||||
<config-description-ref uri="thing-type:pilight:device"/>
|
||||
</thing-type>
|
||||
|
||||
<thing-type id="dimmer">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="bridge"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>Pilight Dimmer</label>
|
||||
<description>Pilight Dimmer</description>
|
||||
|
||||
<channels>
|
||||
<channel id="dimlevel" typeId="system.brightness"/>
|
||||
</channels>
|
||||
|
||||
<config-description-ref uri="thing-type:pilight:device"/>
|
||||
</thing-type>
|
||||
|
||||
<thing-type id="generic" extensible="string,number">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="bridge"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>Pilight Generic Device</label>
|
||||
<description>Pilight Generic Device</description>
|
||||
|
||||
<config-description-ref uri="thing-type:pilight:device"/>
|
||||
</thing-type>
|
||||
|
||||
<channel-type id="contact-state">
|
||||
<item-type>Contact</item-type>
|
||||
<label>State of Contact</label>
|
||||
<description>State of Pilight Contact.</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="string">
|
||||
<item-type>String</item-type>
|
||||
<label>Text Value</label>
|
||||
<state readOnly="true"/>
|
||||
<config-description>
|
||||
<parameter name="property" type="text">
|
||||
<label>Property</label>
|
||||
<description>The Property of the Device.</description>
|
||||
<required>true</required>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="number">
|
||||
<item-type>Number</item-type>
|
||||
<label>Number Value</label>
|
||||
<state readOnly="true"/>
|
||||
<config-description>
|
||||
<parameter name="property" type="text">
|
||||
<label>Property</label>
|
||||
<description>The Property of the Device.</description>
|
||||
<required>true</required>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</channel-type>
|
||||
|
||||
</thing:thing-descriptions>
|
@ -239,6 +239,7 @@
|
||||
<module>org.openhab.binding.paradoxalarm</module>
|
||||
<module>org.openhab.binding.pentair</module>
|
||||
<module>org.openhab.binding.phc</module>
|
||||
<module>org.openhab.binding.pilight</module>
|
||||
<module>org.openhab.binding.pioneeravr</module>
|
||||
<module>org.openhab.binding.pixometer</module>
|
||||
<module>org.openhab.binding.pjlinkdevice</module>
|
||||
|
Loading…
Reference in New Issue
Block a user