added migrated 2.x add-ons
Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
32
bundles/org.openhab.binding.yeelight/.classpath
Normal file
32
bundles/org.openhab.binding.yeelight/.classpath
Normal file
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
<attribute name="test" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
23
bundles/org.openhab.binding.yeelight/.project
Normal file
23
bundles/org.openhab.binding.yeelight/.project
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>org.openhab.binding.yeelight</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
13
bundles/org.openhab.binding.yeelight/NOTICE
Normal file
13
bundles/org.openhab.binding.yeelight/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
|
||||
75
bundles/org.openhab.binding.yeelight/README.md
Normal file
75
bundles/org.openhab.binding.yeelight/README.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# Yeelight Binding
|
||||
|
||||
This binding integrates the [Yeelight Lighting Product](https://www.yeelight.com/).
|
||||
|
||||
## Supported Things
|
||||
|
||||
- [Yeelight LED White Bulb](https://www.yeelight.com/zh_CN/product/wifi-led-w) (Thing type `dolphin`)
|
||||
- [Yeelight LED Color Bulb](https://www.yeelight.com/zh_CN/product/wifi-led-c) (Thing type `wonder`)
|
||||
- [Yeelight LED Color Stripe](https://www.yeelight.com/zh_CN/product/pitaya) (Thing type `stripe`)
|
||||
- [Yeelight LED Ceiling Light](https://www.yeelight.com/en_US/product/luna) (Thing type `ceiling`)
|
||||
|
||||
## Preconditions
|
||||
|
||||
To control Yeelight devices with this binding, you need to connect the device to your local network at first with the Yeelight app.
|
||||
This app is available in the iOS AppStore and on Google Play.
|
||||
|
||||
Then you need to activate LAN control mode by enable Developer Mode in device settings, after which it will become discoverable by openHAB.
|
||||
|
||||
## Discovery
|
||||
|
||||
Yeelight smart LED devices announce themselves on the network through UPnP, so that they can be discovered.
|
||||
|
||||
## Thing Configuration
|
||||
|
||||
All Yeelight things require the `deviceId` from the device as a configuration parameter. This table shows all available parameters:
|
||||
|
||||
| Parameter | Values | Mandatory |
|
||||
|---------------------|------------------------------------------------|-----------|
|
||||
| deviceId | ID of the Yeelight device | Yes |
|
||||
| duration | Duration for changing between different states | No |
|
||||
|
||||
## Channels
|
||||
|
||||
All devices support some of the following channels:
|
||||
|
||||
| Channel | Item Type | Description |
|
||||
|--------|------|------|
|
||||
|`brightness` | `Dimmer` | This channel supports adjusting the brightness value, it is available on `dolphin` and `ceiling`.|
|
||||
|`color` | `Color` | This channel supports color control, it is available on `wonder` and `stripe`.|
|
||||
|`colorTemperature` | `Dimmer` | This channel supports adjusting the color temperature, it is available on `wonder` and `stripe` and `ceiling`.|
|
||||
|`command` | `String` | This channel sends a command directly to the device, it is available on all Yeelight Things.|
|
||||
|`backgroundColor` | `Color` or `Dimmer` | This channel supports color control for the ambient light, it is available on `ceiling4`.|
|
||||
|`nightlight` | `Switch` | This supports switching to nightlight mode, it is available on `ceiling1` or `ceiling4`.|
|
||||
|
||||
|
||||
## Full Example
|
||||
|
||||
Things:
|
||||
|
||||
```
|
||||
Thing yeelight:stripe:1 [ deviceId="0x000000000321a1bc", duration=1000 ]
|
||||
```
|
||||
|
||||
Items:
|
||||
|
||||
```
|
||||
Color YeelightLEDColor { channel="yeelight:stripe:1:color" }
|
||||
Switch YeelightLEDSwitch { channel="yeelight:stripe:1:color" }
|
||||
String YeelightLEDCommand { channel="yeelight:stripe:1:command" }
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
```
|
||||
rule "Yeelight Custom Command"
|
||||
when
|
||||
Time is noon
|
||||
then
|
||||
YeelightLEDCommand.sendCommand("set_power;\"on\",\"smooth\",2000")
|
||||
end
|
||||
```
|
||||
|
||||
Note that `set_power` is the command, then a separator `;` must be used. `\"on\",\"smooth\",2000` are the parameters.
|
||||
|
||||
Full list of commands can be found [here](https://www.yeelight.com/download/Yeelight_Inter-Operation_Spec.pdf).
|
||||
21
bundles/org.openhab.binding.yeelight/about_files/LICENSE
Normal file
21
bundles/org.openhab.binding.yeelight/about_files/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2016 coasterli
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
17
bundles/org.openhab.binding.yeelight/pom.xml
Normal file
17
bundles/org.openhab.binding.yeelight/pom.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
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.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>org.openhab.binding.yeelight</artifactId>
|
||||
|
||||
<name>openHAB Add-ons :: Bundles :: Yeelight Binding</name>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<features name="org.openhab.binding.yeelight-${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-yeelight" description="Yeelight Binding" version="${project.version}">
|
||||
<feature>openhab-runtime-base</feature>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.yeelight/${project.version}</bundle>
|
||||
</feature>
|
||||
</features>
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal;
|
||||
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
* The {@link YeelightBindingConstants} class defines common constants, which are
|
||||
* used across the whole binding.
|
||||
*
|
||||
* @author Coaster Li - Initial contribution
|
||||
* @author Joe Ho - Added Duration / Added command channel
|
||||
*/
|
||||
public class YeelightBindingConstants {
|
||||
|
||||
public static final String BINDING_ID = "yeelight";
|
||||
|
||||
// List of all Thing Type UIDs
|
||||
public static final ThingTypeUID THING_TYPE_CEILING = new ThingTypeUID(BINDING_ID, "ceiling");
|
||||
public static final ThingTypeUID THING_TYPE_CEILING1 = new ThingTypeUID(BINDING_ID, "ceiling1");
|
||||
public static final ThingTypeUID THING_TYPE_CEILING3 = new ThingTypeUID(BINDING_ID, "ceiling3");
|
||||
public static final ThingTypeUID THING_TYPE_CEILING4 = new ThingTypeUID(BINDING_ID, "ceiling4");
|
||||
public static final ThingTypeUID THING_TYPE_DOLPHIN = new ThingTypeUID(BINDING_ID, "dolphin");
|
||||
public static final ThingTypeUID THING_TYPE_CTBULB = new ThingTypeUID(BINDING_ID, "ct_bulb");
|
||||
public static final ThingTypeUID THING_TYPE_WONDER = new ThingTypeUID(BINDING_ID, "wonder");
|
||||
public static final ThingTypeUID THING_TYPE_STRIPE = new ThingTypeUID(BINDING_ID, "stripe");
|
||||
public static final ThingTypeUID THING_TYPE_DESKLAMP = new ThingTypeUID(BINDING_ID, "desklamp");
|
||||
|
||||
// List of thing Parameters names
|
||||
public static final String PARAMETER_DEVICE_ID = "deviceId";
|
||||
public static final String PARAMETER_DURATION = "duration";
|
||||
|
||||
// List of all Channel ids
|
||||
public static final String CHANNEL_BRIGHTNESS = "brightness";
|
||||
public static final String CHANNEL_COLOR = "color";
|
||||
public static final String CHANNEL_COLOR_TEMPERATURE = "colorTemperature";
|
||||
public static final String CHANNEL_COMMAND = "command";
|
||||
public static final String CHANNEL_BACKGROUND_COLOR = "backgroundColor";
|
||||
public static final String CHANNEL_NIGHTLIGHT = "nightlight";
|
||||
|
||||
// Constants used
|
||||
public static final int COLOR_TEMPERATURE_MINIMUM = 1700;
|
||||
public static final int COLOR_TEMPERATURE_STEP = 48;
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal;
|
||||
|
||||
import static org.openhab.binding.yeelight.internal.YeelightBindingConstants.*;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.openhab.binding.yeelight.internal.handler.*;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerFactory;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
|
||||
/**
|
||||
* The {@link YeelightHandlerFactory} is responsible for returning supported things and handlers for the devices.
|
||||
*
|
||||
* @author Coaster Li - Initial contribution
|
||||
* @author Nikita Pogudalov - Added YeelightCeilingWithNightHandler for Ceiling 1
|
||||
*/
|
||||
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.yeelight")
|
||||
public class YeelightHandlerFactory extends BaseThingHandlerFactory {
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = new HashSet<>();
|
||||
|
||||
static {
|
||||
SUPPORTED_THING_TYPES_UIDS.add(THING_TYPE_CEILING);
|
||||
SUPPORTED_THING_TYPES_UIDS.add(THING_TYPE_CEILING1);
|
||||
SUPPORTED_THING_TYPES_UIDS.add(THING_TYPE_CEILING3);
|
||||
SUPPORTED_THING_TYPES_UIDS.add(THING_TYPE_CEILING4);
|
||||
SUPPORTED_THING_TYPES_UIDS.add(THING_TYPE_DOLPHIN);
|
||||
SUPPORTED_THING_TYPES_UIDS.add(THING_TYPE_CTBULB);
|
||||
SUPPORTED_THING_TYPES_UIDS.add(THING_TYPE_WONDER);
|
||||
SUPPORTED_THING_TYPES_UIDS.add(THING_TYPE_STRIPE);
|
||||
SUPPORTED_THING_TYPES_UIDS.add(THING_TYPE_DESKLAMP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
||||
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ThingHandler createHandler(Thing thing) {
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
|
||||
if (thingTypeUID.equals(THING_TYPE_DOLPHIN) || thingTypeUID.equals(THING_TYPE_CTBULB)) {
|
||||
return new YeelightWhiteHandler(thing);
|
||||
} else if (thingTypeUID.equals(THING_TYPE_WONDER)) {
|
||||
return new YeelightColorHandler(thing);
|
||||
} else if (thingTypeUID.equals(THING_TYPE_STRIPE)) {
|
||||
return new YeelightStripeHandler(thing);
|
||||
} else if (thingTypeUID.equals(THING_TYPE_CEILING) || thingTypeUID.equals(THING_TYPE_CEILING3)
|
||||
|| thingTypeUID.equals(THING_TYPE_DESKLAMP)) {
|
||||
return new YeelightCeilingHandler(thing);
|
||||
} else if (thingTypeUID.equals(THING_TYPE_CEILING1)) {
|
||||
return new YeelightCeilingWithNightHandler(thing);
|
||||
} else if (thingTypeUID.equals(THING_TYPE_CEILING4)) {
|
||||
return new YeelightCeilingWithAmbientHandler(thing);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.discovery;
|
||||
|
||||
import org.openhab.binding.yeelight.internal.YeelightBindingConstants;
|
||||
import org.openhab.binding.yeelight.internal.YeelightHandlerFactory;
|
||||
import org.openhab.binding.yeelight.internal.lib.device.DeviceBase;
|
||||
import org.openhab.binding.yeelight.internal.lib.listeners.DeviceListener;
|
||||
import org.openhab.binding.yeelight.internal.lib.services.DeviceManager;
|
||||
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 YeelightDiscoveryService} is responsible for search and discovery of new devices.
|
||||
*
|
||||
* @author Coaster Li - Initial contribution
|
||||
*/
|
||||
@Component(service = DiscoveryService.class, immediate = true, configurationPid = "discovery.yeelight")
|
||||
public class YeelightDiscoveryService extends AbstractDiscoveryService implements DeviceListener {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(YeelightDiscoveryService.class.getSimpleName());
|
||||
|
||||
public YeelightDiscoveryService() {
|
||||
super(YeelightHandlerFactory.SUPPORTED_THING_TYPES_UIDS, 2, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startScan() {
|
||||
logger.debug("Starting Scan");
|
||||
DeviceManager.getInstance().registerDeviceListener(this);
|
||||
DeviceManager.getInstance().startDiscovery();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected synchronized void stopScan() {
|
||||
logger.debug(": stopScan");
|
||||
DeviceManager.getInstance().stopDiscovery();
|
||||
DeviceManager.getInstance().unregisterDeviceListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceFound(DeviceBase device) {
|
||||
logger.info("onDeviceFound, id: {}", device.getDeviceId());
|
||||
ThingUID thingUID = getThingUID(device);
|
||||
|
||||
if (thingUID == null) {
|
||||
// We don't know about this thing type
|
||||
logger.info("Skipping device {}, unknown type.", device.getDeviceId());
|
||||
return;
|
||||
}
|
||||
|
||||
ThingTypeUID thingTypeUID = getThingTypeUID(device);
|
||||
String deviceName = device.getDeviceName().isEmpty() ? DeviceManager.getDefaultName(device)
|
||||
: device.getDeviceName();
|
||||
|
||||
DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withThingType(thingTypeUID)
|
||||
.withLabel(deviceName).withProperties(device.getBulbInfo())
|
||||
.withProperty(YeelightBindingConstants.PARAMETER_DEVICE_ID, device.getDeviceId()).build();
|
||||
|
||||
thingDiscovered(discoveryResult);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceLost(DeviceBase device) {
|
||||
logger.debug("onDeviceLost, id: {}", device.getDeviceId());
|
||||
}
|
||||
|
||||
private ThingUID getThingUID(DeviceBase device) {
|
||||
switch (device.getDeviceType()) {
|
||||
case ceiling:
|
||||
case ceiling3:
|
||||
return new ThingUID(YeelightBindingConstants.THING_TYPE_CEILING, device.getDeviceId());
|
||||
case ceiling1:
|
||||
return new ThingUID(YeelightBindingConstants.THING_TYPE_CEILING1, device.getDeviceId());
|
||||
case ceiling4:
|
||||
return new ThingUID(YeelightBindingConstants.THING_TYPE_CEILING4, device.getDeviceId());
|
||||
case color:
|
||||
return new ThingUID(YeelightBindingConstants.THING_TYPE_WONDER, device.getDeviceId());
|
||||
case mono:
|
||||
return new ThingUID(YeelightBindingConstants.THING_TYPE_DOLPHIN, device.getDeviceId());
|
||||
case ct_bulb:
|
||||
return new ThingUID(YeelightBindingConstants.THING_TYPE_CTBULB, device.getDeviceId());
|
||||
case stripe:
|
||||
return new ThingUID(YeelightBindingConstants.THING_TYPE_STRIPE, device.getDeviceId());
|
||||
case desklamp:
|
||||
return new ThingUID(YeelightBindingConstants.THING_TYPE_DESKLAMP, device.getDeviceId());
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private ThingTypeUID getThingTypeUID(DeviceBase device) {
|
||||
switch (device.getDeviceType()) {
|
||||
case ceiling:
|
||||
return YeelightBindingConstants.THING_TYPE_CEILING;
|
||||
case ceiling1:
|
||||
return YeelightBindingConstants.THING_TYPE_CEILING1;
|
||||
case ceiling3:
|
||||
return YeelightBindingConstants.THING_TYPE_CEILING3;
|
||||
case ceiling4:
|
||||
return YeelightBindingConstants.THING_TYPE_CEILING4;
|
||||
case color:
|
||||
return YeelightBindingConstants.THING_TYPE_WONDER;
|
||||
case mono:
|
||||
return YeelightBindingConstants.THING_TYPE_DOLPHIN;
|
||||
case ct_bulb:
|
||||
return YeelightBindingConstants.THING_TYPE_CTBULB;
|
||||
case stripe:
|
||||
return YeelightBindingConstants.THING_TYPE_STRIPE;
|
||||
case desklamp:
|
||||
return YeelightBindingConstants.THING_TYPE_DESKLAMP;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.handler;
|
||||
|
||||
import static org.openhab.binding.yeelight.internal.YeelightBindingConstants.*;
|
||||
|
||||
import org.openhab.binding.yeelight.internal.YeelightBindingConstants;
|
||||
import org.openhab.binding.yeelight.internal.lib.device.DeviceStatus;
|
||||
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;
|
||||
|
||||
/**
|
||||
* The {@link YeelightCeilingHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Coaster Li - Initial contribution
|
||||
*/
|
||||
public class YeelightCeilingHandler extends YeelightHandlerBase {
|
||||
|
||||
public YeelightCeilingHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
handleCommandHelper(channelUID, command, "Handle Ceiling Command");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateUI(DeviceStatus status) {
|
||||
super.updateUI(status);
|
||||
if (status.isPowerOff()) {
|
||||
updateState(YeelightBindingConstants.CHANNEL_BRIGHTNESS, PercentType.ZERO);
|
||||
} else {
|
||||
updateState(YeelightBindingConstants.CHANNEL_BRIGHTNESS, new PercentType(status.getBrightness()));
|
||||
updateState(YeelightBindingConstants.CHANNEL_COLOR_TEMPERATURE,
|
||||
new PercentType((status.getCt() - COLOR_TEMPERATURE_MINIMUM) / COLOR_TEMPERATURE_STEP));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.handler;
|
||||
|
||||
import org.openhab.binding.yeelight.internal.YeelightBindingConstants;
|
||||
import org.openhab.binding.yeelight.internal.lib.device.DeviceStatus;
|
||||
import org.openhab.binding.yeelight.internal.lib.enums.ActiveMode;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.HSBType;
|
||||
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;
|
||||
|
||||
/**
|
||||
* The {@link YeelightCeilingWithAmbientHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Viktor Koop - Initial contribution
|
||||
*/
|
||||
public class YeelightCeilingWithAmbientHandler extends YeelightCeilingHandler {
|
||||
|
||||
public YeelightCeilingWithAmbientHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
handleCommandHelper(channelUID, command, "Handle ceiling ambient light command");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateUI(DeviceStatus status) {
|
||||
super.updateUI(status);
|
||||
|
||||
if (status.isBackgroundIsPowerOff()) {
|
||||
updateState(YeelightBindingConstants.CHANNEL_BACKGROUND_COLOR, PercentType.ZERO);
|
||||
} else {
|
||||
final HSBType hsbType = new HSBType(new DecimalType(status.getBackgroundHue()),
|
||||
new PercentType(status.getBackgroundSat()), new PercentType(status.getBackgroundBrightness()));
|
||||
|
||||
updateState(YeelightBindingConstants.CHANNEL_BACKGROUND_COLOR, hsbType);
|
||||
}
|
||||
|
||||
updateState(YeelightBindingConstants.CHANNEL_NIGHTLIGHT,
|
||||
(status.getActiveMode() == ActiveMode.MOONLIGHT_MODE) ? OnOffType.ON : OnOffType.OFF);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.handler;
|
||||
|
||||
import org.openhab.binding.yeelight.internal.YeelightBindingConstants;
|
||||
import org.openhab.binding.yeelight.internal.lib.device.DeviceStatus;
|
||||
import org.openhab.binding.yeelight.internal.lib.enums.ActiveMode;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.thing.Thing;
|
||||
|
||||
/**
|
||||
* The {@link YeelightCeilingWithNightHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Nikita Pogudalov - Initial contribution
|
||||
*/
|
||||
public class YeelightCeilingWithNightHandler extends YeelightCeilingHandler {
|
||||
|
||||
public YeelightCeilingWithNightHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateUI(DeviceStatus status) {
|
||||
super.updateUI(status);
|
||||
|
||||
updateState(YeelightBindingConstants.CHANNEL_NIGHTLIGHT,
|
||||
(status.getActiveMode() == ActiveMode.MOONLIGHT_MODE) ? OnOffType.ON : OnOffType.OFF);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.handler;
|
||||
|
||||
import org.openhab.binding.yeelight.internal.lib.device.DeviceStatus;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.types.Command;
|
||||
|
||||
/**
|
||||
* The {@link YeelightColorHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Coaster Li - Initial contribution
|
||||
*/
|
||||
public class YeelightColorHandler extends YeelightHandlerBase {
|
||||
|
||||
public YeelightColorHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
handleCommandHelper(channelUID, command, "Handle Color Command");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateUI(DeviceStatus status) {
|
||||
super.updateUI(status);
|
||||
updateBrightnessAndColorUI(status);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,346 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.handler;
|
||||
|
||||
import static org.openhab.binding.yeelight.internal.YeelightBindingConstants.*;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.openhab.binding.yeelight.internal.lib.device.ConnectState;
|
||||
import org.openhab.binding.yeelight.internal.lib.device.DeviceBase;
|
||||
import org.openhab.binding.yeelight.internal.lib.device.DeviceFactory;
|
||||
import org.openhab.binding.yeelight.internal.lib.device.DeviceStatus;
|
||||
import org.openhab.binding.yeelight.internal.lib.enums.DeviceAction;
|
||||
import org.openhab.binding.yeelight.internal.lib.enums.DeviceMode;
|
||||
import org.openhab.binding.yeelight.internal.lib.enums.DeviceType;
|
||||
import org.openhab.binding.yeelight.internal.lib.listeners.DeviceConnectionStateListener;
|
||||
import org.openhab.binding.yeelight.internal.lib.listeners.DeviceStatusChangeListener;
|
||||
import org.openhab.binding.yeelight.internal.lib.services.DeviceManager;
|
||||
import org.openhab.core.library.types.*;
|
||||
import org.openhab.core.thing.*;
|
||||
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link YeelightHandlerBase} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Coaster Li - Initial contribution
|
||||
* @author Joe Ho - Added Duration Thing parameter
|
||||
* @author Nikita Pogudalov - Added DeviceType for ceiling 1
|
||||
*/
|
||||
public abstract class YeelightHandlerBase extends BaseThingHandler
|
||||
implements DeviceConnectionStateListener, DeviceStatusChangeListener {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(YeelightHandlerBase.class);
|
||||
protected DeviceBase mDevice;
|
||||
|
||||
// Reading the deviceId from the properties map.
|
||||
private String deviceId = getThing().getConfiguration().get(PARAMETER_DEVICE_ID).toString();
|
||||
|
||||
public YeelightHandlerBase(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
protected void updateUI(DeviceStatus status) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
logger.debug("Initializing, Device ID: {}", deviceId);
|
||||
mDevice = DeviceFactory.build(getDeviceModel(getThing().getThingTypeUID()).name(), deviceId);
|
||||
mDevice.setDeviceName(getThing().getLabel());
|
||||
mDevice.setAutoConnect(true);
|
||||
DeviceManager.getInstance().addDevice(mDevice);
|
||||
mDevice.registerConnectStateListener(this);
|
||||
mDevice.registerStatusChangedListener(this);
|
||||
updateStatusHelper(mDevice.getConnectionState());
|
||||
DeviceManager.getInstance().startDiscovery(15 * 1000);
|
||||
}
|
||||
|
||||
private DeviceType getDeviceModel(ThingTypeUID typeUID) {
|
||||
if (typeUID.equals(THING_TYPE_CEILING)) {
|
||||
return DeviceType.ceiling;
|
||||
} else if (typeUID.equals(THING_TYPE_CEILING1)) {
|
||||
return DeviceType.ceiling1;
|
||||
} else if (typeUID.equals(THING_TYPE_CEILING3)) {
|
||||
return DeviceType.ceiling3;
|
||||
} else if (typeUID.equals(THING_TYPE_CEILING4)) {
|
||||
return DeviceType.ceiling4;
|
||||
} else if (typeUID.equals(THING_TYPE_WONDER)) {
|
||||
return DeviceType.color;
|
||||
} else if (typeUID.equals(THING_TYPE_DOLPHIN)) {
|
||||
return DeviceType.mono;
|
||||
} else if (typeUID.equals(THING_TYPE_CTBULB)) {
|
||||
return DeviceType.ct_bulb;
|
||||
} else if (typeUID.equals(THING_TYPE_STRIPE)) {
|
||||
return DeviceType.stripe;
|
||||
} else if (typeUID.equals(THING_TYPE_DESKLAMP)) {
|
||||
return DeviceType.desklamp;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectionStateChanged(ConnectState connectState) {
|
||||
logger.debug("onConnectionStateChanged -> {}", connectState.name());
|
||||
updateStatusHelper(connectState);
|
||||
}
|
||||
|
||||
public void updateStatusHelper(ConnectState connectState) {
|
||||
switch (connectState) {
|
||||
case DISCONNECTED:
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, "Device is offline!");
|
||||
if (mDevice.isAutoConnect()) {
|
||||
DeviceManager.sInstance.startDiscovery(5 * 1000);
|
||||
logger.debug("Thing OFFLINE. Initiated discovery");
|
||||
}
|
||||
break;
|
||||
case CONNECTED:
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
mDevice.queryStatus();
|
||||
break;
|
||||
default:
|
||||
updateStatus(ThingStatus.UNKNOWN);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelLinked(ChannelUID channelUID) {
|
||||
logger.debug("ChannelLinked -> {}", channelUID.getId());
|
||||
super.channelLinked(channelUID);
|
||||
|
||||
Runnable task = () -> {
|
||||
mDevice.queryStatus();
|
||||
};
|
||||
scheduler.schedule(task, 500, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
public void handleCommandHelper(ChannelUID channelUID, Command command, String logInfo) {
|
||||
logger.debug("{}: {}", logInfo, command);
|
||||
|
||||
// If device is disconnected, start discovery to reconnect.
|
||||
if (mDevice.isAutoConnect() && mDevice.getConnectionState() != ConnectState.CONNECTED) {
|
||||
DeviceManager.getInstance().startDiscovery(5 * 1000);
|
||||
}
|
||||
if (command instanceof RefreshType) {
|
||||
logger.debug("Refresh channel: {} Command: {}", channelUID, command);
|
||||
|
||||
DeviceManager.getInstance().startDiscovery(5 * 1000);
|
||||
DeviceStatus s = mDevice.getDeviceStatus();
|
||||
|
||||
switch (channelUID.getId()) {
|
||||
case CHANNEL_BRIGHTNESS:
|
||||
updateState(channelUID, new PercentType(s.getBrightness()));
|
||||
break;
|
||||
case CHANNEL_COLOR:
|
||||
updateState(channelUID, HSBType.fromRGB(s.getR(), s.getG(), s.getB()));
|
||||
break;
|
||||
case CHANNEL_COLOR_TEMPERATURE:
|
||||
updateState(channelUID, new PercentType(s.getCt()));
|
||||
break;
|
||||
case CHANNEL_BACKGROUND_COLOR:
|
||||
final HSBType hsbType = new HSBType(new DecimalType(s.getHue()), new PercentType(s.getSat()),
|
||||
new PercentType(s.getBackgroundBrightness()));
|
||||
updateState(channelUID, hsbType);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
switch (channelUID.getId()) {
|
||||
case CHANNEL_BRIGHTNESS:
|
||||
if (command instanceof PercentType) {
|
||||
handlePercentMessage((PercentType) command);
|
||||
} else if (command instanceof OnOffType) {
|
||||
handleOnOffCommand((OnOffType) command);
|
||||
} else if (command instanceof IncreaseDecreaseType) {
|
||||
handleIncreaseDecreaseBrightnessCommand((IncreaseDecreaseType) command);
|
||||
}
|
||||
break;
|
||||
case CHANNEL_COLOR:
|
||||
if (command instanceof HSBType) {
|
||||
HSBType hsbCommand = (HSBType) command;
|
||||
if (hsbCommand.getBrightness().intValue() == 0) {
|
||||
handleOnOffCommand(OnOffType.OFF);
|
||||
} else {
|
||||
handleHSBCommand(hsbCommand);
|
||||
}
|
||||
} else if (command instanceof PercentType) {
|
||||
handlePercentMessage((PercentType) command);
|
||||
} else if (command instanceof OnOffType) {
|
||||
handleOnOffCommand((OnOffType) command);
|
||||
} else if (command instanceof IncreaseDecreaseType) {
|
||||
handleIncreaseDecreaseBrightnessCommand((IncreaseDecreaseType) command);
|
||||
}
|
||||
break;
|
||||
case CHANNEL_COLOR_TEMPERATURE:
|
||||
if (command instanceof PercentType) {
|
||||
handleColorTemperatureCommand((PercentType) command);
|
||||
} else if (command instanceof IncreaseDecreaseType) {
|
||||
handleIncreaseDecreaseBrightnessCommand((IncreaseDecreaseType) command);
|
||||
}
|
||||
break;
|
||||
|
||||
case CHANNEL_BACKGROUND_COLOR:
|
||||
if (command instanceof HSBType) {
|
||||
HSBType hsbCommand = (HSBType) command;
|
||||
handleBackgroundHSBCommand(hsbCommand);
|
||||
} else if (command instanceof PercentType) {
|
||||
handleBackgroundBrightnessPercentMessage((PercentType) command);
|
||||
} else if (command instanceof OnOffType) {
|
||||
handleBackgroundOnOffCommand((OnOffType) command);
|
||||
}
|
||||
break;
|
||||
case CHANNEL_NIGHTLIGHT:
|
||||
if (command instanceof OnOffType) {
|
||||
DeviceAction pAction = command == OnOffType.ON ? DeviceAction.nightlight_on
|
||||
: DeviceAction.nightlight_off;
|
||||
pAction.putDuration(getDuration());
|
||||
DeviceManager.getInstance().doAction(deviceId, pAction);
|
||||
}
|
||||
break;
|
||||
case CHANNEL_COMMAND:
|
||||
if (!command.toString().isEmpty()) {
|
||||
String[] tokens = command.toString().split(";");
|
||||
String methodAction = tokens[0];
|
||||
String methodParams = "";
|
||||
if (tokens.length > 1) {
|
||||
methodParams = tokens[1];
|
||||
}
|
||||
logger.debug("{}: {} {}", logInfo, methodAction, methodParams);
|
||||
handleCustomCommand(methodAction, methodParams);
|
||||
updateState(channelUID, new StringType(""));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void handlePercentMessage(PercentType brightness) {
|
||||
DeviceAction pAction;
|
||||
if (brightness.intValue() == 0) {
|
||||
pAction = DeviceAction.close;
|
||||
pAction.putDuration(getDuration());
|
||||
DeviceManager.getInstance().doAction(deviceId, pAction);
|
||||
} else {
|
||||
if (mDevice.getDeviceStatus().isPowerOff()) {
|
||||
pAction = DeviceAction.open;
|
||||
// hard coded to fast open, the duration should apply to brightness increase only
|
||||
pAction.putDuration(0);
|
||||
DeviceManager.getInstance().doAction(deviceId, pAction);
|
||||
}
|
||||
pAction = DeviceAction.brightness;
|
||||
pAction.putValue(brightness.intValue());
|
||||
pAction.putDuration(getDuration());
|
||||
DeviceManager.getInstance().doAction(deviceId, pAction);
|
||||
}
|
||||
}
|
||||
|
||||
void handleIncreaseDecreaseBrightnessCommand(IncreaseDecreaseType increaseDecrease) {
|
||||
DeviceAction idbAcation = increaseDecrease == IncreaseDecreaseType.INCREASE ? DeviceAction.increase_bright
|
||||
: DeviceAction.decrease_bright;
|
||||
idbAcation.putDuration(getDuration());
|
||||
DeviceManager.getInstance().doAction(deviceId, idbAcation);
|
||||
}
|
||||
|
||||
void handleIncreaseDecreaseColorTemperatureCommand(IncreaseDecreaseType increaseDecrease) {
|
||||
DeviceAction idctAcation = increaseDecrease == IncreaseDecreaseType.INCREASE ? DeviceAction.increase_ct
|
||||
: DeviceAction.decrease_ct;
|
||||
idctAcation.putDuration(getDuration());
|
||||
DeviceManager.getInstance().doAction(deviceId, idctAcation);
|
||||
}
|
||||
|
||||
void handleOnOffCommand(OnOffType onoff) {
|
||||
DeviceAction ofAction = onoff == OnOffType.ON ? DeviceAction.open : DeviceAction.close;
|
||||
ofAction.putDuration(getDuration());
|
||||
DeviceManager.getInstance().doAction(deviceId, ofAction);
|
||||
}
|
||||
|
||||
void handleHSBCommand(HSBType color) {
|
||||
DeviceAction cAction = DeviceAction.color;
|
||||
cAction.putValue(color.getRGB() & 0xFFFFFF);
|
||||
cAction.putDuration(getDuration());
|
||||
DeviceManager.getInstance().doAction(deviceId, cAction);
|
||||
}
|
||||
|
||||
void handleBackgroundHSBCommand(HSBType color) {
|
||||
DeviceAction cAction = DeviceAction.background_color;
|
||||
|
||||
// TODO: actions seem to be an insufficiant abstraction.
|
||||
cAction.putValue(color.getHue() + "," + color.getSaturation());
|
||||
cAction.putDuration(getDuration());
|
||||
DeviceManager.getInstance().doAction(deviceId, cAction);
|
||||
}
|
||||
|
||||
void handleBackgroundBrightnessPercentMessage(PercentType brightness) {
|
||||
DeviceAction pAction;
|
||||
|
||||
pAction = DeviceAction.background_brightness;
|
||||
pAction.putValue(brightness.intValue());
|
||||
pAction.putDuration(getDuration());
|
||||
DeviceManager.getInstance().doAction(deviceId, pAction);
|
||||
}
|
||||
|
||||
private void handleBackgroundOnOffCommand(OnOffType command) {
|
||||
DeviceAction pAction = command == OnOffType.ON ? DeviceAction.background_on : DeviceAction.background_off;
|
||||
pAction.putDuration(getDuration());
|
||||
DeviceManager.getInstance().doAction(deviceId, pAction);
|
||||
}
|
||||
|
||||
void handleColorTemperatureCommand(PercentType ct) {
|
||||
DeviceAction ctAction = DeviceAction.colortemperature;
|
||||
ctAction.putValue(COLOR_TEMPERATURE_STEP * ct.intValue() + COLOR_TEMPERATURE_MINIMUM);
|
||||
ctAction.putDuration(getDuration());
|
||||
DeviceManager.getInstance().doAction(deviceId, ctAction);
|
||||
}
|
||||
|
||||
void handleCustomCommand(String action, String params) {
|
||||
DeviceManager.getInstance().doCustomAction(deviceId, action, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStatusChanged(DeviceStatus status) {
|
||||
logger.debug("UpdateState->{}", status);
|
||||
updateUI(status);
|
||||
}
|
||||
|
||||
void updateBrightnessAndColorUI(DeviceStatus status) {
|
||||
PercentType brightness = status.isPowerOff() ? PercentType.ZERO : new PercentType(status.getBrightness());
|
||||
|
||||
HSBType tempHsbType = HSBType.fromRGB(status.getR(), status.getG(), status.getB());
|
||||
HSBType hsbType = status.getMode() == DeviceMode.MODE_HSV
|
||||
? new HSBType(new DecimalType(status.getHue()), new PercentType(status.getSat()), brightness)
|
||||
: new HSBType(tempHsbType.getHue(), tempHsbType.getSaturation(), brightness);
|
||||
|
||||
logger.debug("Update Color->{}", hsbType);
|
||||
updateState(CHANNEL_COLOR, hsbType);
|
||||
|
||||
logger.debug("Update CT->{}", status.getCt());
|
||||
updateState(CHANNEL_COLOR_TEMPERATURE,
|
||||
new PercentType((status.getCt() - COLOR_TEMPERATURE_MINIMUM) / COLOR_TEMPERATURE_STEP));
|
||||
}
|
||||
|
||||
int getDuration() {
|
||||
// Duration should not be null, but just in case do a null check.
|
||||
return getThing().getConfiguration().get(PARAMETER_DURATION) == null ? 500
|
||||
: ((Number) getThing().getConfiguration().get(PARAMETER_DURATION)).intValue();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.handler;
|
||||
|
||||
import org.openhab.binding.yeelight.internal.lib.device.DeviceStatus;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.types.Command;
|
||||
|
||||
/**
|
||||
* The {@link YeelightStripeHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Coaster Li - Initial contribution
|
||||
*/
|
||||
public class YeelightStripeHandler extends YeelightHandlerBase {
|
||||
|
||||
public YeelightStripeHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
handleCommandHelper(channelUID, command, "Handle Stripe Command");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateUI(DeviceStatus status) {
|
||||
super.updateUI(status);
|
||||
updateBrightnessAndColorUI(status);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.handler;
|
||||
|
||||
import org.openhab.binding.yeelight.internal.YeelightBindingConstants;
|
||||
import org.openhab.binding.yeelight.internal.lib.device.DeviceStatus;
|
||||
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.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link YeelightWhiteHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Coaster Li - Initial contribution
|
||||
*/
|
||||
public class YeelightWhiteHandler extends YeelightHandlerBase {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(YeelightWhiteHandler.class);
|
||||
|
||||
public YeelightWhiteHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
handleCommandHelper(channelUID, command, "Handle White Command");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateUI(DeviceStatus status) {
|
||||
super.updateUI(status);
|
||||
if (status.isPowerOff()) {
|
||||
logger.debug("Device is powered off!");
|
||||
updateState(YeelightBindingConstants.CHANNEL_BRIGHTNESS, PercentType.ZERO);
|
||||
} else {
|
||||
logger.debug("Device is powered on!");
|
||||
updateState(YeelightBindingConstants.CHANNEL_BRIGHTNESS, new PercentType(status.getBrightness()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.lib;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* The {@link CommonLogger} is responsible for logging.
|
||||
*
|
||||
* @author Coaster Li - Initial contribution
|
||||
*/
|
||||
public class CommonLogger {
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
private static Logger sLogger = Logger.getLogger("YeelightLib");
|
||||
|
||||
public static void debug(String tag, String msg) {
|
||||
if (DEBUG) {
|
||||
sLogger.log(Level.INFO, tag + ":" + msg);
|
||||
}
|
||||
}
|
||||
|
||||
public static void debug(String msg) {
|
||||
if (DEBUG) {
|
||||
sLogger.log(Level.INFO, msg);
|
||||
}
|
||||
}
|
||||
|
||||
public static void warning(String msg) {
|
||||
if (DEBUG) {
|
||||
sLogger.warning(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.lib.device;
|
||||
|
||||
import org.openhab.binding.yeelight.internal.lib.device.connection.WifiConnection;
|
||||
import org.openhab.binding.yeelight.internal.lib.enums.DeviceType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
/**
|
||||
* The {@link CeilingDevice} contains methods for handling the ceiling device.
|
||||
*
|
||||
* @author Coaster Li - Initial contribution
|
||||
*/
|
||||
public class CeilingDevice extends DeviceBase {
|
||||
private final Logger logger = LoggerFactory.getLogger(CeilingDevice.class);
|
||||
|
||||
public CeilingDevice(String id) {
|
||||
super(id);
|
||||
mDeviceType = DeviceType.ceiling;
|
||||
mConnection = new WifiConnection(this);
|
||||
mMinCt = 2700;
|
||||
mMaxCt = 6500;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNotify(String msg) {
|
||||
JsonObject result = new JsonParser().parse(msg).getAsJsonObject();
|
||||
try {
|
||||
if (result.has("id")) {
|
||||
String id = result.get("id").getAsString();
|
||||
// for cmd transaction.
|
||||
|
||||
if (mQueryList.contains(id)) {
|
||||
mQueryList.remove(id);
|
||||
// DeviceMethod(MethodAction.PROP, new Object[] { "power", "name", "bright", "ct" });
|
||||
JsonArray status = result.get("result").getAsJsonArray();
|
||||
|
||||
// power:
|
||||
if (status.get(0).toString().equals("\"off\"")) {
|
||||
mDeviceStatus.setPowerOff(true);
|
||||
} else if (status.get(0).toString().equals("\"on\"")) {
|
||||
mDeviceStatus.setPowerOff(false);
|
||||
}
|
||||
|
||||
// name:
|
||||
mDeviceStatus.setName(status.get(1).getAsString());
|
||||
|
||||
// brightness:
|
||||
mDeviceStatus.setBrightness(status.get(2).getAsInt());
|
||||
|
||||
// ct:
|
||||
mDeviceStatus.setCt(status.get(3).getAsInt());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.debug("Problem setting values", e);
|
||||
}
|
||||
|
||||
super.onNotify(msg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.lib.device;
|
||||
|
||||
import org.openhab.binding.yeelight.internal.lib.enums.ActiveMode;
|
||||
import org.openhab.binding.yeelight.internal.lib.enums.DeviceType;
|
||||
import org.openhab.binding.yeelight.internal.lib.enums.MethodAction;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
/**
|
||||
* The {@link CeilingDeviceWithAmbientDevice} contains methods for handling the ceiling device with ambient light.
|
||||
*
|
||||
* @author Viktor Koop - Initial contribution
|
||||
*/
|
||||
public class CeilingDeviceWithAmbientDevice extends CeilingDevice
|
||||
implements DeviceWithAmbientLight, DeviceWithNightlight {
|
||||
private final Logger logger = LoggerFactory.getLogger(CeilingDeviceWithAmbientDevice.class);
|
||||
|
||||
public CeilingDeviceWithAmbientDevice(String id) {
|
||||
super(id);
|
||||
|
||||
mDeviceType = DeviceType.ceiling4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNotify(String msg) {
|
||||
logger.debug("Got state: {}", msg);
|
||||
|
||||
JsonObject result = new JsonParser().parse(msg).getAsJsonObject();
|
||||
|
||||
if (result.has("id")) {
|
||||
String id = result.get("id").getAsString();
|
||||
// for cmd transaction.
|
||||
|
||||
if (mQueryList.contains(id)) {
|
||||
JsonArray status = result.get("result").getAsJsonArray();
|
||||
|
||||
final String backgroundPowerState = status.get(4).toString();
|
||||
if ("\"off\"".equals(backgroundPowerState)) {
|
||||
mDeviceStatus.setBackgroundIsPowerOff(true);
|
||||
} else if ("\"on\"".equals(backgroundPowerState)) {
|
||||
mDeviceStatus.setBackgroundIsPowerOff(false);
|
||||
}
|
||||
|
||||
final int backgroundBrightness = status.get(5).getAsInt();
|
||||
mDeviceStatus.setBackgroundBrightness(backgroundBrightness);
|
||||
|
||||
final int backgroundHue = status.get(6).getAsInt();
|
||||
mDeviceStatus.setBackgroundHue(backgroundHue);
|
||||
|
||||
final int backgroundSaturation = status.get(7).getAsInt();
|
||||
mDeviceStatus.setBackgroundSat(backgroundSaturation);
|
||||
|
||||
final int activeMode = status.get(8).getAsInt();
|
||||
mDeviceStatus.setActiveMode(ActiveMode.values()[activeMode]);
|
||||
}
|
||||
}
|
||||
|
||||
super.onNotify(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackgroundColor(int hue, int saturation, int duration) {
|
||||
mConnection
|
||||
.invoke(MethodFactory.buildBackgroundHSVMethod(hue, saturation, DeviceMethod.EFFECT_SMOOTH, duration));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackgroundBrightness(int brightness, int duration) {
|
||||
mConnection
|
||||
.invoke(MethodFactory.buildBackgroundBrightnessMethd(brightness, DeviceMethod.EFFECT_SMOOTH, duration));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackgroundPower(boolean on, int duration) {
|
||||
mConnection.invoke(new DeviceMethod(MethodAction.BG_SWITCH,
|
||||
new Object[] { on ? "on" : "off", DeviceMethod.EFFECT_SMOOTH, duration }));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toggleNightlightMode(boolean turnOn) {
|
||||
if (turnOn) {
|
||||
mConnection.invoke(
|
||||
new DeviceMethod(MethodAction.SCENE, new Object[] { "nightlight", mDeviceStatus.getBrightness() }));
|
||||
} else {
|
||||
mConnection.invoke(MethodFactory.buildCTMethod(mDeviceStatus.getCt(), DeviceMethod.EFFECT_SMOOTH, 500));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.lib.device;
|
||||
|
||||
import org.openhab.binding.yeelight.internal.lib.enums.ActiveMode;
|
||||
import org.openhab.binding.yeelight.internal.lib.enums.DeviceType;
|
||||
import org.openhab.binding.yeelight.internal.lib.enums.MethodAction;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
/**
|
||||
* The {@link CeilingDeviceWithNightDevice} contains methods for handling the ceiling device with ambient light.
|
||||
*
|
||||
* @author Nikita Pogudalov - Initial contribution
|
||||
*/
|
||||
public class CeilingDeviceWithNightDevice extends CeilingDevice implements DeviceWithNightlight {
|
||||
private final Logger logger = LoggerFactory.getLogger(CeilingDeviceWithNightDevice.class);
|
||||
|
||||
public CeilingDeviceWithNightDevice(String id) {
|
||||
super(id);
|
||||
|
||||
mDeviceType = DeviceType.ceiling1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNotify(String msg) {
|
||||
logger.debug("Got state: {}", msg);
|
||||
|
||||
JsonObject result = new JsonParser().parse(msg).getAsJsonObject();
|
||||
|
||||
if (result.has("id")) {
|
||||
String id = result.get("id").getAsString();
|
||||
// for cmd transaction.
|
||||
|
||||
if (mQueryList.contains(id)) {
|
||||
JsonArray status = result.get("result").getAsJsonArray();
|
||||
|
||||
final int activeMode = status.get(8).getAsInt();
|
||||
mDeviceStatus.setActiveMode(ActiveMode.values()[activeMode]);
|
||||
}
|
||||
}
|
||||
|
||||
super.onNotify(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toggleNightlightMode(boolean turnOn) {
|
||||
if (turnOn) {
|
||||
mConnection.invoke(
|
||||
new DeviceMethod(MethodAction.SCENE, new Object[] { "nightlight", mDeviceStatus.getBrightness() }));
|
||||
} else {
|
||||
mConnection.invoke(MethodFactory.buildCTMethod(mDeviceStatus.getCt(), DeviceMethod.EFFECT_SMOOTH, 500));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.lib.device;
|
||||
|
||||
/**
|
||||
* @author Coaster Li - Initial contribution
|
||||
*/
|
||||
public class ColorFlowItem {
|
||||
public int duration;
|
||||
public int mode;
|
||||
public int value;
|
||||
public int brightness;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ColorFlowItem [duration=" + duration + ", mode=" + mode + ", value=" + value + ", brightness="
|
||||
+ brightness + "]";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.lib.device;
|
||||
|
||||
/**
|
||||
* The {@link ConnectState} lists different connection states.
|
||||
*
|
||||
* @author Coaster Li - Initial contribution
|
||||
*/
|
||||
public enum ConnectState {
|
||||
|
||||
DISCONNECTED,
|
||||
|
||||
CONNECTTING,
|
||||
|
||||
CONNECTED
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.lib.device;
|
||||
|
||||
import org.openhab.binding.yeelight.internal.lib.device.connection.WifiConnection;
|
||||
import org.openhab.binding.yeelight.internal.lib.enums.DeviceType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
/**
|
||||
* The {@link CtBulbDevice} contains methods for handling the CT bulb device.
|
||||
*
|
||||
* @author Claudius Ellsel - Initial contribution
|
||||
*/
|
||||
public class CtBulbDevice extends DeviceBase {
|
||||
private final Logger logger = LoggerFactory.getLogger(CtBulbDevice.class);
|
||||
|
||||
public CtBulbDevice(String id) {
|
||||
super(id);
|
||||
mDeviceType = DeviceType.ct_bulb;
|
||||
mConnection = new WifiConnection(this);
|
||||
mMinCt = 2700;
|
||||
mMaxCt = 6500;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNotify(String msg) {
|
||||
JsonObject result = new JsonParser().parse(msg).getAsJsonObject();
|
||||
try {
|
||||
if (result.has("id")) {
|
||||
String id = result.get("id").getAsString();
|
||||
// for cmd transaction.
|
||||
|
||||
if (mQueryList.contains(id)) {
|
||||
mQueryList.remove(id);
|
||||
// DeviceMethod(MethodAction.PROP, new Object[] { "power", "name", "bright", "ct" });
|
||||
JsonArray status = result.get("result").getAsJsonArray();
|
||||
|
||||
// power:
|
||||
if (status.get(0).toString().equals("\"off\"")) {
|
||||
mDeviceStatus.setPowerOff(true);
|
||||
} else if (status.get(0).toString().equals("\"on\"")) {
|
||||
mDeviceStatus.setPowerOff(false);
|
||||
}
|
||||
|
||||
// name:
|
||||
mDeviceStatus.setName(status.get(1).getAsString());
|
||||
|
||||
// brightness:
|
||||
mDeviceStatus.setBrightness(status.get(2).getAsInt());
|
||||
|
||||
// ct:
|
||||
mDeviceStatus.setCt(status.get(3).getAsInt());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.debug("Problem setting values", e);
|
||||
}
|
||||
|
||||
super.onNotify(msg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.lib.device;
|
||||
|
||||
import org.openhab.binding.yeelight.internal.lib.device.connection.WifiConnection;
|
||||
import org.openhab.binding.yeelight.internal.lib.enums.DeviceType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
/**
|
||||
* The {@link DesklampDevice} contains methods for handling the desklamp device.
|
||||
*
|
||||
* @author Sebastian Rakel - Initial contribution
|
||||
*/
|
||||
public class DesklampDevice extends DeviceBase {
|
||||
private final Logger logger = LoggerFactory.getLogger(DesklampDevice.class);
|
||||
|
||||
public DesklampDevice(String id) {
|
||||
super(id);
|
||||
mDeviceType = DeviceType.desklamp;
|
||||
mConnection = new WifiConnection(this);
|
||||
mMinCt = 2700;
|
||||
mMaxCt = 6500;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNotify(String msg) {
|
||||
JsonObject result = new JsonParser().parse(msg).getAsJsonObject();
|
||||
try {
|
||||
if (result.has("id")) {
|
||||
String id = result.get("id").getAsString();
|
||||
// for cmd transaction.
|
||||
|
||||
if (mQueryList.contains(id)) {
|
||||
mQueryList.remove(id);
|
||||
// DeviceMethod(MethodAction.PROP, new Object[] { "power", "name", "bright", "ct" });
|
||||
JsonArray status = result.get("result").getAsJsonArray();
|
||||
|
||||
// power:
|
||||
if (status.get(0).toString().equals("\"off\"")) {
|
||||
mDeviceStatus.setPowerOff(true);
|
||||
} else if (status.get(0).toString().equals("\"on\"")) {
|
||||
mDeviceStatus.setPowerOff(false);
|
||||
}
|
||||
|
||||
// name:
|
||||
mDeviceStatus.setName(status.get(1).getAsString());
|
||||
|
||||
// brightness:
|
||||
mDeviceStatus.setBrightness(status.get(2).getAsInt());
|
||||
|
||||
// ct:
|
||||
mDeviceStatus.setCt(status.get(3).getAsInt());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.debug("Problem setting values", e);
|
||||
}
|
||||
|
||||
super.onNotify(msg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,433 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.lib.device;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.openhab.binding.yeelight.internal.lib.device.connection.ConnectionBase;
|
||||
import org.openhab.binding.yeelight.internal.lib.enums.ActiveMode;
|
||||
import org.openhab.binding.yeelight.internal.lib.enums.DeviceMode;
|
||||
import org.openhab.binding.yeelight.internal.lib.enums.DeviceType;
|
||||
import org.openhab.binding.yeelight.internal.lib.enums.MethodAction;
|
||||
import org.openhab.binding.yeelight.internal.lib.listeners.DeviceConnectionStateListener;
|
||||
import org.openhab.binding.yeelight.internal.lib.listeners.DeviceStatusChangeListener;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
/**
|
||||
* The {@link DeviceBase} is a generic class for all devices.
|
||||
*
|
||||
* @author Coaster Li - Initial contribution
|
||||
* @author Daniel Walters - Correct handling of brightness
|
||||
* @author Joe Ho - Added duration to some commands
|
||||
*/
|
||||
public abstract class DeviceBase {
|
||||
private final Logger logger = LoggerFactory.getLogger(DeviceBase.class);
|
||||
|
||||
private static final String TAG = DeviceBase.class.getSimpleName();
|
||||
|
||||
protected String mDeviceId;
|
||||
protected String mDeviceName;
|
||||
protected DeviceType mDeviceType;
|
||||
protected String mAddress;
|
||||
private String[] mSupportProps;
|
||||
protected int mPort;
|
||||
private int mFwVersion;
|
||||
protected boolean bIsOnline;
|
||||
protected boolean bIsAutoConnect;
|
||||
protected ConnectionBase mConnection;
|
||||
protected ConnectState mConnectState = ConnectState.DISCONNECTED;
|
||||
protected DeviceStatus mDeviceStatus;
|
||||
private Map<String, Object> mBulbInfo = null;
|
||||
protected List<String> mQueryList = new ArrayList<>();
|
||||
|
||||
protected int mMinCt, mMaxCt;
|
||||
|
||||
List<DeviceConnectionStateListener> mConnectionListeners = new ArrayList<>();
|
||||
List<DeviceStatusChangeListener> mStatusChangeListeners = new ArrayList<>();
|
||||
|
||||
public DeviceBase(String id) {
|
||||
mDeviceId = id;
|
||||
mDeviceStatus = new DeviceStatus();
|
||||
}
|
||||
|
||||
public DeviceBase(String id, boolean isAutoConnect) {
|
||||
mDeviceId = id;
|
||||
this.bIsAutoConnect = isAutoConnect;
|
||||
}
|
||||
|
||||
public void onNotify(String response) {
|
||||
boolean needNotify = true;
|
||||
JsonObject message = new JsonParser().parse(response).getAsJsonObject();
|
||||
try {
|
||||
if (message.has("method")) {
|
||||
String method = message.get("method").toString().replace("\"", "");
|
||||
if (method.equals("props")) {// Property notify
|
||||
String params = message.get("params").toString();
|
||||
JsonObject propsObject = new JsonParser().parse(params).getAsJsonObject();
|
||||
for (Entry<String, JsonElement> prop : propsObject.entrySet()) {
|
||||
final YeelightDeviceProperty property = YeelightDeviceProperty.fromString(prop.getKey());
|
||||
if (null == property) {
|
||||
logger.debug("Unhandled property: {}", prop.getKey());
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (property) {
|
||||
case POWER:
|
||||
if (prop.getValue().toString().equals("\"off\"")) {
|
||||
mDeviceStatus.setPowerOff(true);
|
||||
} else if (prop.getValue().toString().equals("\"on\"")) {
|
||||
mDeviceStatus.setPowerOff(false);
|
||||
}
|
||||
break;
|
||||
case BRIGHT:
|
||||
mDeviceStatus.setBrightness(prop.getValue().getAsInt());
|
||||
break;
|
||||
case CT:
|
||||
mDeviceStatus.setCt(prop.getValue().getAsInt());
|
||||
mDeviceStatus.setMode(DeviceMode.MODE_SUNHINE);
|
||||
break;
|
||||
case RGB: {
|
||||
mDeviceStatus.setMode(DeviceMode.MODE_COLOR);
|
||||
int color = prop.getValue().getAsInt();
|
||||
mDeviceStatus.setColor(color);
|
||||
|
||||
mDeviceStatus.setR((color >> 16) & 0xFF);
|
||||
mDeviceStatus.setG((color >> 8) & 0xFF);
|
||||
mDeviceStatus.setB(color & 0xFF);
|
||||
break;
|
||||
}
|
||||
case HUE:
|
||||
mDeviceStatus.setMode(DeviceMode.MODE_HSV);
|
||||
mDeviceStatus.setHue(prop.getValue().getAsInt());
|
||||
break;
|
||||
case SAT:
|
||||
mDeviceStatus.setMode(DeviceMode.MODE_HSV);
|
||||
mDeviceStatus.setSat(prop.getValue().getAsInt());
|
||||
break;
|
||||
case COLOR_MODE:
|
||||
switch (prop.getValue().getAsInt()) {
|
||||
case DeviceStatus.MODE_COLOR:
|
||||
mDeviceStatus.setMode(DeviceMode.MODE_COLOR);
|
||||
break;
|
||||
case DeviceStatus.MODE_COLORTEMPERATURE:
|
||||
mDeviceStatus.setMode(DeviceMode.MODE_SUNHINE);
|
||||
break;
|
||||
case DeviceStatus.MODE_HSV:
|
||||
mDeviceStatus.setMode(DeviceMode.MODE_HSV);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case FLOWING:
|
||||
mDeviceStatus.setIsFlowing(prop.getValue().getAsInt() == 1);
|
||||
break;
|
||||
case FLOW_PARAMS:
|
||||
// {"method":"props","params":{"flow_params":"0,0,1000,1,15935488,31,1000,1,13366016,31,1000,1,62370,31,1000,1,7995635,31"}}
|
||||
String[] flowStrs = prop.getValue().toString().replace("\"", "").split(",");
|
||||
if (flowStrs.length > 2 && (flowStrs.length - 2) % 4 == 0) {
|
||||
mDeviceStatus.setFlowCount(Integer.parseInt(flowStrs[0]));
|
||||
mDeviceStatus.setFlowEndAction(Integer.parseInt(flowStrs[1]));
|
||||
if (mDeviceStatus.getFlowItems() == null) {
|
||||
mDeviceStatus.setFlowItems(new ArrayList<>());
|
||||
}
|
||||
mDeviceStatus.getFlowItems().clear();
|
||||
for (int i = 0; i < ((flowStrs.length - 2) / 4); i++) {
|
||||
ColorFlowItem item = new ColorFlowItem();
|
||||
item.duration = Integer.valueOf(flowStrs[4 * i + 2]);
|
||||
item.mode = Integer.valueOf(flowStrs[4 * i + 3]);
|
||||
item.value = Integer.valueOf(flowStrs[4 * i + 4]);
|
||||
item.brightness = Integer.valueOf(flowStrs[4 * i + 5]);
|
||||
mDeviceStatus.getFlowItems().add(item);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DELAYOFF:
|
||||
int delayOff = prop.getValue().getAsInt();
|
||||
if (delayOff > 0 && delayOff <= 60) {
|
||||
mDeviceStatus.setDelayOff(delayOff);
|
||||
} else {
|
||||
mDeviceStatus.setDelayOff(DeviceStatus.DEFAULT_NO_DELAY);
|
||||
}
|
||||
break;
|
||||
case MUSIC_ON:
|
||||
mDeviceStatus.setMusicOn(prop.getValue().getAsInt() == 1);
|
||||
break;
|
||||
case NAME:
|
||||
mDeviceName = prop.getValue().toString();
|
||||
break;
|
||||
case BG_RGB: {
|
||||
int color = prop.getValue().getAsInt();
|
||||
mDeviceStatus.setBackgroundR((color >> 16) & 0xFF);
|
||||
mDeviceStatus.setBackgroundG((color >> 8) & 0xFF);
|
||||
mDeviceStatus.setBackgroundB(color & 0xFF);
|
||||
break;
|
||||
}
|
||||
case BG_HUE:
|
||||
mDeviceStatus.setBackgroundHue(prop.getValue().getAsInt());
|
||||
|
||||
break;
|
||||
case BG_SAT:
|
||||
mDeviceStatus.setBackgroundSat(prop.getValue().getAsInt());
|
||||
break;
|
||||
case BG_BRIGHT:
|
||||
mDeviceStatus.setBackgroundBrightness(prop.getValue().getAsInt());
|
||||
break;
|
||||
case BG_POWER:
|
||||
if ("\"off\"".equals(prop.getValue().toString())) {
|
||||
mDeviceStatus.setBackgroundIsPowerOff(true);
|
||||
} else if ("\"on\"".equals(prop.getValue().toString())) {
|
||||
mDeviceStatus.setBackgroundIsPowerOff(false);
|
||||
}
|
||||
break;
|
||||
case NL_BR:
|
||||
// when the light is switched from nightlight-mode to sunlight-mode it will send nl_br:0
|
||||
// therefore we have to ignore the case.
|
||||
final int intValue = prop.getValue().getAsInt();
|
||||
if (intValue > 0) {
|
||||
mDeviceStatus.setBrightness(intValue);
|
||||
}
|
||||
break;
|
||||
case ACTIVE_MODE:
|
||||
int activeModeInt = prop.getValue().getAsInt();
|
||||
final ActiveMode activeMode = ActiveMode.values()[activeModeInt];
|
||||
mDeviceStatus.setActiveMode(activeMode);
|
||||
break;
|
||||
default:
|
||||
logger.debug("Maybe unsupported property: {} - {}", property, prop.getKey());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if (message.has("id") && message.has("result")) {
|
||||
// no method, but result : ["ok"]
|
||||
JsonArray result = message.get("result").getAsJsonArray();
|
||||
if (result.get(0).toString().equals("\"ok\"")) {
|
||||
logger.info("######### this is control command response, don't need to notify status change!");
|
||||
needNotify = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (needNotify) {
|
||||
logger.info("status = {}", mDeviceStatus);
|
||||
for (DeviceStatusChangeListener statusChangeListener : mStatusChangeListeners) {
|
||||
statusChangeListener.onStatusChanged(mDeviceStatus);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.debug("Exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void open(int duration) {
|
||||
mConnection.invoke(
|
||||
new DeviceMethod(MethodAction.SWITCH, new Object[] { "on", DeviceMethod.EFFECT_SMOOTH, duration }));
|
||||
}
|
||||
|
||||
public void close(int duration) {
|
||||
mConnection.invoke(
|
||||
new DeviceMethod(MethodAction.SWITCH, new Object[] { "off", DeviceMethod.EFFECT_SMOOTH, duration }));
|
||||
}
|
||||
|
||||
public void decreaseBrightness(int duration) {
|
||||
int bright = getDeviceStatus().getBrightness() - 10;
|
||||
if (bright <= 0) {
|
||||
close(duration);
|
||||
} else {
|
||||
setBrightness(bright, duration);
|
||||
}
|
||||
}
|
||||
|
||||
public void increaseBrightness(int duration) {
|
||||
int bright = getDeviceStatus().getBrightness() + 10;
|
||||
if (bright > 100) {
|
||||
bright = 100;
|
||||
}
|
||||
setBrightness(bright, duration);
|
||||
}
|
||||
|
||||
public void setBrightness(int brightness, int duration) {
|
||||
mConnection.invoke(MethodFactory.buildBrightnessMethd(brightness, DeviceMethod.EFFECT_SMOOTH, duration));
|
||||
}
|
||||
|
||||
public void setColor(int color, int duration) {
|
||||
mConnection.invoke(MethodFactory.buildRgbMethod(color, DeviceMethod.EFFECT_SMOOTH, duration));
|
||||
}
|
||||
|
||||
public void increaseCt(int duration) {
|
||||
int ct = getDeviceStatus().getCt() - ((mMaxCt - mMinCt) / 10);
|
||||
if (ct < mMinCt) {
|
||||
ct = mMinCt;
|
||||
}
|
||||
setCT(ct, duration);
|
||||
}
|
||||
|
||||
public void decreaseCt(int duration) {
|
||||
int ct = getDeviceStatus().getCt() + ((mMaxCt - mMinCt) / 10);
|
||||
if (ct > mMaxCt) {
|
||||
ct = mMaxCt;
|
||||
}
|
||||
setCT(ct, duration);
|
||||
}
|
||||
|
||||
public void setCT(int ct, int duration) {
|
||||
mConnection.invoke(MethodFactory.buildCTMethod(ct, DeviceMethod.EFFECT_SMOOTH, duration));
|
||||
}
|
||||
|
||||
public void connect() {
|
||||
setConnectionState(ConnectState.CONNECTTING);
|
||||
mConnection.connect();
|
||||
}
|
||||
|
||||
public void setConnectionState(ConnectState connectState) {
|
||||
logger.debug("{}: set connection state to: {}", TAG, connectState.name());
|
||||
if (connectState == ConnectState.DISCONNECTED) {
|
||||
setOnline(false);
|
||||
}
|
||||
if (mConnectState != connectState) {
|
||||
mConnectState = connectState;
|
||||
if (mConnectionListeners != null) {
|
||||
for (DeviceConnectionStateListener listener : mConnectionListeners) {
|
||||
listener.onConnectionStateChanged(mConnectState);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void sendCustomCommand(String action, String params) {
|
||||
mConnection.invokeCustom(new DeviceMethod(action, params));
|
||||
}
|
||||
|
||||
// ===================== setter and getter=====================
|
||||
|
||||
public String getDeviceId() {
|
||||
return mDeviceId;
|
||||
}
|
||||
|
||||
public void setDeviceName(String name) {
|
||||
mDeviceName = name;
|
||||
}
|
||||
|
||||
public String getDeviceName() {
|
||||
return mDeviceName;
|
||||
}
|
||||
|
||||
public DeviceType getDeviceType() {
|
||||
return mDeviceType;
|
||||
}
|
||||
|
||||
public String getDeviceModel() {
|
||||
return mDeviceType.name();
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return mAddress;
|
||||
}
|
||||
|
||||
public void setAddress(String address) {
|
||||
this.mAddress = address;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return mPort;
|
||||
}
|
||||
|
||||
public void setPort(int port) {
|
||||
this.mPort = port;
|
||||
}
|
||||
|
||||
public boolean isAutoConnect() {
|
||||
return bIsAutoConnect;
|
||||
}
|
||||
|
||||
public int getFwVersion() {
|
||||
return mFwVersion;
|
||||
}
|
||||
|
||||
public void setFwVersion(int fwVersion) {
|
||||
this.mFwVersion = fwVersion;
|
||||
}
|
||||
|
||||
public Map<String, Object> getBulbInfo() {
|
||||
return mBulbInfo;
|
||||
}
|
||||
|
||||
public void setBulbInfo(Map<String, Object> bulbInfo) {
|
||||
this.mBulbInfo = bulbInfo;
|
||||
}
|
||||
|
||||
public String[] getSupportProps() {
|
||||
return mSupportProps;
|
||||
}
|
||||
|
||||
public void setSupportProps(String[] supportProps) {
|
||||
this.mSupportProps = supportProps;
|
||||
}
|
||||
|
||||
public void setAutoConnect(boolean isAutoConnect) {
|
||||
if (bIsAutoConnect != isAutoConnect) {
|
||||
this.bIsAutoConnect = isAutoConnect;
|
||||
checkAutoConnect();
|
||||
}
|
||||
}
|
||||
|
||||
public DeviceStatus getDeviceStatus() {
|
||||
return mDeviceStatus;
|
||||
}
|
||||
|
||||
public void registerConnectStateListener(DeviceConnectionStateListener listener) {
|
||||
mConnectionListeners.add(listener);
|
||||
}
|
||||
|
||||
public void registerStatusChangedListener(DeviceStatusChangeListener listener) {
|
||||
mStatusChangeListeners.add(listener);
|
||||
}
|
||||
|
||||
public void setOnline(boolean isOnline) {
|
||||
bIsOnline = isOnline;
|
||||
checkAutoConnect();
|
||||
}
|
||||
|
||||
public boolean isOnline() {
|
||||
return bIsOnline;
|
||||
}
|
||||
|
||||
public ConnectState getConnectionState() {
|
||||
return mConnectState;
|
||||
}
|
||||
|
||||
public void queryStatus() {
|
||||
DeviceMethod cmd = MethodFactory.buildQuery(this);
|
||||
mQueryList.add(cmd.getCmdId());
|
||||
mConnection.invoke(cmd);
|
||||
}
|
||||
|
||||
private void checkAutoConnect() {
|
||||
logger.debug(
|
||||
"{}: CheckAutoConnect: online: {}, autoConnect: {}, connection state: {}, device = {}, device id: {}",
|
||||
TAG, bIsOnline, bIsAutoConnect, mConnectState.name(), this, this.getDeviceId());
|
||||
if (bIsOnline && bIsAutoConnect && mConnectState == ConnectState.DISCONNECTED) {
|
||||
connect();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.lib.device;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.openhab.binding.yeelight.internal.lib.enums.DeviceType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link DeviceFactory} creates device handler classes.
|
||||
*
|
||||
* @author Coaster Li - Initial contribution
|
||||
* @author Nikita Pogudalov - Added CeilingDeviceWithNightDevice for Ceiling 1
|
||||
*/
|
||||
public class DeviceFactory {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(DeviceFactory.class);
|
||||
|
||||
private static final String TAG = DeviceFactory.class.getSimpleName();
|
||||
|
||||
public static DeviceBase build(String model, String id) {
|
||||
DeviceType type = DeviceType.valueOf(model);
|
||||
switch (type) {
|
||||
case ceiling:
|
||||
case ceiling3:
|
||||
return new CeilingDevice(id);
|
||||
case ceiling1:
|
||||
return new CeilingDeviceWithNightDevice(id);
|
||||
case ceiling4:
|
||||
return new CeilingDeviceWithAmbientDevice(id);
|
||||
case color:
|
||||
return new WonderDevice(id);
|
||||
case mono:
|
||||
return new MonoDevice(id);
|
||||
case ct_bulb:
|
||||
return new CtBulbDevice(id);
|
||||
case stripe:
|
||||
return new PitayaDevice(id);
|
||||
case desklamp:
|
||||
return new DesklampDevice(id);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static DeviceBase build(Map<String, String> bulbInfo) {
|
||||
DeviceBase device = build(bulbInfo.get("model"), bulbInfo.get("id"));
|
||||
if (null == device) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Map<String, Object> infos = new HashMap<>(bulbInfo);
|
||||
device.setBulbInfo(infos);
|
||||
LOGGER.debug("{}: DeviceFactory Device = {}", TAG, bulbInfo.get("Location"));
|
||||
// TODO enhancement!!!
|
||||
String[] addressInfo = bulbInfo.get("Location").split(":");
|
||||
device.setAddress(addressInfo[1].substring(2));
|
||||
device.setPort(Integer.parseInt(addressInfo[2]));
|
||||
device.setOnline(true);
|
||||
LOGGER.debug("{}: DeviceFactory Device info = {}, port = {}", TAG, device.getAddress(), device.getPort());
|
||||
return device;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.lib.device;
|
||||
|
||||
import org.openhab.binding.yeelight.internal.lib.enums.MethodAction;
|
||||
|
||||
/**
|
||||
* @author Coaster Li - Initial contribution
|
||||
*/
|
||||
public class DeviceMethod {
|
||||
|
||||
public static final String EFFECT_SMOOTH = "smooth";
|
||||
public static final String EFFECT_SUDDEN = "sudden";
|
||||
|
||||
public static final int CF_END_STATE_RECOVER = 0;
|
||||
public static final int CF_END_STATE_STAY = 1;
|
||||
public static final int CF_END_STATE_TURNOFF = 2;
|
||||
|
||||
public static final int CF_ITEM_MODE_COLOR = 1;
|
||||
public static final int CF_ITEM_MODE_CT = 2;
|
||||
public static final int CF_ITEM_MODE_SLEEP = 7;
|
||||
|
||||
public static final String SCENE_TYPE_COLOR = "color";
|
||||
public static final String SCENE_TYPE_HSV = "hsv";
|
||||
public static final String SCENE_TYPE_CT = "ct";
|
||||
public static final String SCENE_TYPE_CF = "cf";
|
||||
public static final String SCENE_TYPE_DELAY = "auto_delay_off";
|
||||
|
||||
public static final String ADJUST_ACTION_INCREASE = "increase";
|
||||
public static final String ADJUST_ACTION_DECREASE = "decrease";
|
||||
public static final String ADJUST_ACTION_CIRCLE = "circle";
|
||||
|
||||
public static final String ADJUST_PROP_BRIGHT = "bright";
|
||||
public static final String ADJUST_PROP_CT = "ct";
|
||||
public static final String ADJUST_PROP_COLOR = "color";
|
||||
|
||||
public static final int MUSIC_ACTION_ON = 1;
|
||||
public static final int MUSIC_ACTION_OFF = 0;
|
||||
|
||||
private static int sIndex = 0;
|
||||
|
||||
private String mMethodAction;
|
||||
private Object[] mMethodParams;
|
||||
private String mCustomMethodParams;
|
||||
private int mIndex;
|
||||
|
||||
public DeviceMethod(MethodAction action, Object[] params) {
|
||||
this.mMethodAction = action.action;
|
||||
this.mMethodParams = params;
|
||||
this.mCustomMethodParams = "";
|
||||
mIndex = ++sIndex;
|
||||
}
|
||||
|
||||
public DeviceMethod(String action, String params) {
|
||||
this.mMethodAction = action;
|
||||
this.mMethodParams = null;
|
||||
this.mCustomMethodParams = params;
|
||||
mIndex = ++sIndex;
|
||||
}
|
||||
|
||||
public String getParamsStr() {
|
||||
StringBuilder cmdBuilder = new StringBuilder();
|
||||
cmdBuilder.append("{\"id\":").append(mIndex).append(",");
|
||||
cmdBuilder.append("\"method\":\"").append(mMethodAction).append("\",");
|
||||
cmdBuilder.append("\"params\":[");
|
||||
if (mMethodParams != null && mMethodParams.length > 0) {
|
||||
for (Object param : mMethodParams) {
|
||||
if (param instanceof String) {
|
||||
cmdBuilder.append("\"" + param.toString() + "\"");
|
||||
} else {
|
||||
cmdBuilder.append(Integer.parseInt(param.toString()));
|
||||
}
|
||||
cmdBuilder.append(",");
|
||||
}
|
||||
// delete last ","
|
||||
cmdBuilder.deleteCharAt(cmdBuilder.length() - 1);
|
||||
}
|
||||
cmdBuilder.append("]}\r\n");
|
||||
return cmdBuilder.toString();
|
||||
}
|
||||
|
||||
public String getCustomParamsStr() {
|
||||
StringBuilder cmdBuilder = new StringBuilder();
|
||||
cmdBuilder.append("{\"id\":").append(mIndex).append(",");
|
||||
cmdBuilder.append("\"method\":\"").append(mMethodAction).append("\",");
|
||||
cmdBuilder.append("\"params\":[").append(mCustomMethodParams).append("]}\r\n");
|
||||
return cmdBuilder.toString();
|
||||
}
|
||||
|
||||
public String getCmdId() {
|
||||
return String.valueOf(mIndex);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,269 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.lib.device;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.openhab.binding.yeelight.internal.lib.enums.ActiveMode;
|
||||
import org.openhab.binding.yeelight.internal.lib.enums.DeviceMode;
|
||||
|
||||
/**
|
||||
* @author Coaster Li - Initial contribution
|
||||
*/
|
||||
public class DeviceStatus {
|
||||
|
||||
public static final int MODE_COLOR = 1;
|
||||
public static final int MODE_COLORTEMPERATURE = 2;
|
||||
public static final int MODE_HSV = 3;
|
||||
|
||||
public static final int DEFAULT_NO_DELAY = -1;
|
||||
|
||||
private boolean isPowerOff;
|
||||
private int r;
|
||||
private int g;
|
||||
private int b;
|
||||
private int color;
|
||||
private int brightness;
|
||||
private int ct;
|
||||
private int hue;
|
||||
private int sat;
|
||||
private boolean isFlowing;
|
||||
private int delayOff = DEFAULT_NO_DELAY;
|
||||
private List<ColorFlowItem> mFlowItems;
|
||||
private DeviceMode mode;
|
||||
private boolean isMusicOn;
|
||||
private String name;
|
||||
private int flowEndAction;
|
||||
private int flowCount;
|
||||
|
||||
private int backgroundBrightness;
|
||||
private boolean backgroundIsPowerOff;
|
||||
private int backgroundR;
|
||||
private int backgroundG;
|
||||
private int backgroundB;
|
||||
private int backgroundHue;
|
||||
private int backgroundSat;
|
||||
|
||||
private ActiveMode activeMode;
|
||||
|
||||
public int getR() {
|
||||
return r;
|
||||
}
|
||||
|
||||
public void setR(int r) {
|
||||
this.r = r;
|
||||
}
|
||||
|
||||
public int getG() {
|
||||
return g;
|
||||
}
|
||||
|
||||
public void setG(int g) {
|
||||
this.g = g;
|
||||
}
|
||||
|
||||
public int getB() {
|
||||
return b;
|
||||
}
|
||||
|
||||
public void setB(int b) {
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public int getBrightness() {
|
||||
return brightness;
|
||||
}
|
||||
|
||||
public void setBrightness(int brightness) {
|
||||
this.brightness = brightness;
|
||||
}
|
||||
|
||||
public int getCt() {
|
||||
return ct;
|
||||
}
|
||||
|
||||
public void setCt(int ct) {
|
||||
this.ct = ct;
|
||||
}
|
||||
|
||||
public int getHue() {
|
||||
return hue;
|
||||
}
|
||||
|
||||
public void setHue(int hue) {
|
||||
this.hue = hue;
|
||||
}
|
||||
|
||||
public int getSat() {
|
||||
return sat;
|
||||
}
|
||||
|
||||
public void setSat(int sat) {
|
||||
this.sat = sat;
|
||||
}
|
||||
|
||||
public DeviceMode getMode() {
|
||||
return mode;
|
||||
}
|
||||
|
||||
public void setMode(DeviceMode mode) {
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
public boolean isPowerOff() {
|
||||
return isPowerOff;
|
||||
}
|
||||
|
||||
public void setPowerOff(boolean isPowerOff) {
|
||||
this.isPowerOff = isPowerOff;
|
||||
}
|
||||
|
||||
public int getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
public void setColor(int color) {
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public boolean getIsFlowing() {
|
||||
return isFlowing;
|
||||
}
|
||||
|
||||
public void setIsFlowing(boolean isFlowing) {
|
||||
this.isFlowing = isFlowing;
|
||||
}
|
||||
|
||||
public List<ColorFlowItem> getFlowItems() {
|
||||
return mFlowItems;
|
||||
}
|
||||
|
||||
public void setFlowItems(List<ColorFlowItem> mFlowItems) {
|
||||
this.mFlowItems = mFlowItems;
|
||||
}
|
||||
|
||||
public boolean isMusicOn() {
|
||||
return isMusicOn;
|
||||
}
|
||||
|
||||
public void setMusicOn(boolean isMusicOn) {
|
||||
this.isMusicOn = isMusicOn;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getDelayOff() {
|
||||
return delayOff;
|
||||
}
|
||||
|
||||
public void setDelayOff(int delayOff) {
|
||||
this.delayOff = delayOff;
|
||||
}
|
||||
|
||||
public boolean isBackgroundIsPowerOff() {
|
||||
return backgroundIsPowerOff;
|
||||
}
|
||||
|
||||
public void setBackgroundIsPowerOff(boolean backgroundIsPowerOff) {
|
||||
this.backgroundIsPowerOff = backgroundIsPowerOff;
|
||||
}
|
||||
|
||||
public int getBackgroundR() {
|
||||
return backgroundR;
|
||||
}
|
||||
|
||||
public void setBackgroundR(int backgroundR) {
|
||||
this.backgroundR = backgroundR;
|
||||
}
|
||||
|
||||
public int getBackgroundG() {
|
||||
return backgroundG;
|
||||
}
|
||||
|
||||
public void setBackgroundG(int backgroundG) {
|
||||
this.backgroundG = backgroundG;
|
||||
}
|
||||
|
||||
public int getBackgroundB() {
|
||||
return backgroundB;
|
||||
}
|
||||
|
||||
public void setBackgroundB(int backgroundB) {
|
||||
this.backgroundB = backgroundB;
|
||||
}
|
||||
|
||||
public int getBackgroundHue() {
|
||||
return backgroundHue;
|
||||
}
|
||||
|
||||
public void setBackgroundHue(int backgroundHue) {
|
||||
this.backgroundHue = backgroundHue;
|
||||
}
|
||||
|
||||
public int getBackgroundBrightness() {
|
||||
return backgroundBrightness;
|
||||
}
|
||||
|
||||
public void setBackgroundBrightness(int backgroundBrightness) {
|
||||
this.backgroundBrightness = backgroundBrightness;
|
||||
}
|
||||
|
||||
public int getBackgroundSat() {
|
||||
return backgroundSat;
|
||||
}
|
||||
|
||||
public void setBackgroundSat(int backgroundSat) {
|
||||
this.backgroundSat = backgroundSat;
|
||||
}
|
||||
|
||||
public ActiveMode getActiveMode() {
|
||||
return activeMode;
|
||||
}
|
||||
|
||||
public void setActiveMode(ActiveMode activeMode) {
|
||||
this.activeMode = activeMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DeviceStatus [isPowerOff=" + isPowerOff + ", r=" + r + ", g=" + g + ", b=" + b + ", color=" + color
|
||||
+ ", brightness=" + brightness + ", ct=" + ct + ", hue=" + hue + ", sat=" + sat + ", isFlowing="
|
||||
+ isFlowing + ", delayOff=" + delayOff + ", mFlowItems=" + mFlowItems + ", mode=" + mode
|
||||
+ ", isMusicOn=" + isMusicOn + ", name=" + name + ", backgroundIsPowerOff=" + backgroundIsPowerOff
|
||||
+ ", backgroundR=" + backgroundR + ", backgroundG=" + backgroundG + ", backgroundB=" + backgroundB
|
||||
+ ", backgroundHue=" + backgroundHue + ", backgroundBrightness=" + backgroundBrightness
|
||||
+ ", backgroundSat=" + backgroundSat + ", activeMode=" + activeMode + "]";
|
||||
}
|
||||
|
||||
public int getFlowCount() {
|
||||
return flowCount;
|
||||
}
|
||||
|
||||
public void setFlowCount(int flowCount) {
|
||||
this.flowCount = flowCount;
|
||||
}
|
||||
|
||||
public int getFlowEndAction() {
|
||||
return flowEndAction;
|
||||
}
|
||||
|
||||
public void setFlowEndAction(int flowEndAction) {
|
||||
this.flowEndAction = flowEndAction;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.lib.device;
|
||||
|
||||
/**
|
||||
* Interface for devices with background light.
|
||||
*
|
||||
* @author Viktor Koop - Initial contribution
|
||||
*/
|
||||
public interface DeviceWithAmbientLight {
|
||||
void setBackgroundColor(int hue, int saturation, int duration);
|
||||
|
||||
void setBackgroundBrightness(int brightness, int duration);
|
||||
|
||||
void setBackgroundPower(boolean on, int intDuration);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.lib.device;
|
||||
|
||||
/**
|
||||
* Implemented by devices with the possibility to enable nightlight mode.
|
||||
*
|
||||
* @author Viktor Koop - Initial contribution
|
||||
*/
|
||||
public interface DeviceWithNightlight {
|
||||
|
||||
/**
|
||||
* Toggle the nightlight mode on or off.
|
||||
*
|
||||
* @param mode
|
||||
*/
|
||||
void toggleNightlightMode(boolean mode);
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.lib.device;
|
||||
|
||||
import org.openhab.binding.yeelight.internal.lib.enums.DeviceType;
|
||||
import org.openhab.binding.yeelight.internal.lib.enums.MethodAction;
|
||||
|
||||
/**
|
||||
* @author Coaster Li - Initial contribution
|
||||
* @author Nikita Pogudalov - Added DeviceMethod for Ceiling 1
|
||||
*/
|
||||
public class MethodFactory {
|
||||
public static DeviceMethod buildBrightnessMethd(int brightness, String effect, int duration) {
|
||||
return new DeviceMethod(MethodAction.BRIGHTNESS, new Object[] { brightness, effect, duration });
|
||||
}
|
||||
|
||||
public static DeviceMethod buildRgbMethod(int color, String effect, int duration) {
|
||||
return new DeviceMethod(MethodAction.RGB, new Object[] { color, effect, duration });
|
||||
}
|
||||
|
||||
public static DeviceMethod buildCTMethod(int colorTemperature, String effect, int duration) {
|
||||
return new DeviceMethod(MethodAction.COLORTEMPERATURE, new Object[] { colorTemperature, effect, duration });
|
||||
}
|
||||
|
||||
public static DeviceMethod buildHsvMethod(int hue, int sat, String effect, int duration) {
|
||||
return new DeviceMethod(MethodAction.HSV, new Object[] { hue, sat, effect, duration });
|
||||
}
|
||||
|
||||
public static DeviceMethod buildToggle() {
|
||||
return new DeviceMethod(MethodAction.HSV, null);
|
||||
}
|
||||
|
||||
public static DeviceMethod buildSetDefault() {
|
||||
return new DeviceMethod(MethodAction.DEFAULT, null);
|
||||
}
|
||||
|
||||
public static DeviceMethod buildStartCF(int count, int endAction, ColorFlowItem[] items) {
|
||||
if (items == null || items.length < 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String itemStr = "\"";
|
||||
StringBuilder builder;
|
||||
for (int i = 0; i < items.length; i++) {
|
||||
builder = new StringBuilder();
|
||||
ColorFlowItem item = items[i];
|
||||
builder.append(item.duration).append(",").append(item.mode).append(item.value).append(item.brightness);
|
||||
if (i < items.length - 1) {
|
||||
builder.append(",");
|
||||
}
|
||||
}
|
||||
itemStr += "\"";
|
||||
|
||||
return new DeviceMethod(MethodAction.STARTCF, new Object[] { count, endAction, itemStr });
|
||||
}
|
||||
|
||||
public static DeviceMethod buildStopCf() {
|
||||
return new DeviceMethod(MethodAction.STOPCF, null);
|
||||
}
|
||||
|
||||
public static DeviceMethod buildScnene(String type, int value, int brightness) {
|
||||
return buildScene(type, value, brightness, 0, 0, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param type scene type {@link DeviceMethod#SCENE_TYPE_COLOR}
|
||||
* {@link DeviceMethod#SCENE_TYPE_CT}
|
||||
* {@link DeviceMethod#SCENE_TYPE_DELAY}
|
||||
* {@link DeviceMethod#SCENE_TYPE_HSV}
|
||||
* {@link DeviceMethod#SCENE_TYPE_CF}
|
||||
*
|
||||
*/
|
||||
public static DeviceMethod buildScene(String type, int value, int brightness, int count, int endAction,
|
||||
ColorFlowItem[] items) {
|
||||
if (DeviceMethod.SCENE_TYPE_CF.equals(type) && items == null) {
|
||||
throw new IllegalArgumentException("Type is colorFlow, but no flow tuples given");
|
||||
}
|
||||
Object[] params = null;
|
||||
switch (type) {
|
||||
case DeviceMethod.SCENE_TYPE_COLOR:
|
||||
params = new Object[] { "color", value, brightness };
|
||||
break;
|
||||
case DeviceMethod.SCENE_TYPE_CT:
|
||||
params = new Object[] { "ct", value, brightness };
|
||||
break;
|
||||
case DeviceMethod.SCENE_TYPE_DELAY:
|
||||
params = new Object[] { "auto_delay_off", brightness, value };
|
||||
break;
|
||||
case DeviceMethod.SCENE_TYPE_HSV:
|
||||
params = new Object[] { "hsv", value, brightness };
|
||||
break;
|
||||
case DeviceMethod.SCENE_TYPE_CF:
|
||||
String itemStr = "\"";
|
||||
StringBuilder builder;
|
||||
for (int i = 0; i < items.length; i++) {
|
||||
builder = new StringBuilder();
|
||||
ColorFlowItem item = items[i];
|
||||
builder.append(item.duration).append(",").append(item.mode).append(item.value)
|
||||
.append(item.brightness);
|
||||
if (i < items.length - 1) {
|
||||
builder.append(",");
|
||||
}
|
||||
}
|
||||
itemStr += "\"";
|
||||
params = new Object[] { "cf", count, endAction, itemStr };
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
return new DeviceMethod(MethodAction.SCENE, params);
|
||||
}
|
||||
|
||||
public static DeviceMethod buildCronAdd(int value) {
|
||||
return new DeviceMethod(MethodAction.CRON_ADD, new Object[] { 0, value });
|
||||
}
|
||||
|
||||
public static DeviceMethod buildCronGet() {
|
||||
return new DeviceMethod(MethodAction.CRON_ADD, new Object[] { 0 });
|
||||
}
|
||||
|
||||
public static DeviceMethod buildCronDel() {
|
||||
return new DeviceMethod(MethodAction.CRON_DEL, new Object[] { 0 });
|
||||
}
|
||||
|
||||
public static DeviceMethod buildAdjust(String action, String prop) {
|
||||
if (DeviceMethod.ADJUST_PROP_COLOR.equals(prop) && !DeviceMethod.ADJUST_ACTION_CIRCLE.equals(action)) {
|
||||
throw new IllegalArgumentException("When prop is COLOR, the action can only be CIRCLE!!!");
|
||||
}
|
||||
return new DeviceMethod(MethodAction.ADJUST, new Object[] { action, prop });
|
||||
}
|
||||
|
||||
public static DeviceMethod buildMusic(int action, String ipAddress, int port) {
|
||||
if (action == DeviceMethod.MUSIC_ACTION_ON) {
|
||||
return new DeviceMethod(MethodAction.MUSIC, new Object[] { action, ipAddress, port });
|
||||
} else {
|
||||
return new DeviceMethod(MethodAction.MUSIC, new Object[] { action });
|
||||
}
|
||||
}
|
||||
|
||||
public static DeviceMethod buildName(String name) {
|
||||
return new DeviceMethod(MethodAction.NAME, new Object[] { name });
|
||||
}
|
||||
|
||||
public static DeviceMethod buildBackgroundHSVMethod(int hue, int sat, String effect, int duration) {
|
||||
return new DeviceMethod(MethodAction.BG_HSV, new Object[] { hue, sat, effect, duration });
|
||||
}
|
||||
|
||||
public static DeviceMethod buildBackgroundBrightnessMethd(int brightness, String effect, int duration) {
|
||||
return new DeviceMethod(MethodAction.BG_BRIGHTNESS, new Object[] { brightness, effect, duration });
|
||||
}
|
||||
|
||||
public static DeviceMethod buildQuery(DeviceBase device) {
|
||||
DeviceType type = device.getDeviceType();
|
||||
switch (type) {
|
||||
case mono:
|
||||
return new DeviceMethod(MethodAction.PROP, new Object[] { "power", "name", "bright" });
|
||||
case color:
|
||||
case stripe:
|
||||
return new DeviceMethod(MethodAction.PROP,
|
||||
new Object[] { "power", "name", "bright", "ct", "rgb", "hue", "sat" });
|
||||
case ceiling:
|
||||
case desklamp:
|
||||
case ct_bulb:
|
||||
return new DeviceMethod(MethodAction.PROP, new Object[] { "power", "name", "bright", "ct" });
|
||||
case ceiling1:
|
||||
case ceiling4:
|
||||
return new DeviceMethod(MethodAction.PROP, new Object[] { "power", "name", "bright", "ct", "bg_power",
|
||||
"bg_bright", "bg_hue", "bg_sat", "active_mode" });
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.lib.device;
|
||||
|
||||
import org.openhab.binding.yeelight.internal.lib.device.connection.WifiConnection;
|
||||
import org.openhab.binding.yeelight.internal.lib.enums.DeviceType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
/**
|
||||
* The {@link MonoDevice} contains methods for handling the mono color device.
|
||||
*
|
||||
* @author Coaster Li - Initial contribution
|
||||
*/
|
||||
public class MonoDevice extends DeviceBase {
|
||||
private final Logger logger = LoggerFactory.getLogger(MonoDevice.class);
|
||||
|
||||
public MonoDevice(String id) {
|
||||
super(id);
|
||||
mDeviceType = DeviceType.mono;
|
||||
mConnection = new WifiConnection(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNotify(String msg) {
|
||||
JsonObject result = new JsonParser().parse(msg).getAsJsonObject();
|
||||
try {
|
||||
if (result.has("id")) {
|
||||
String id = result.get("id").getAsString();
|
||||
// for cmd transaction.
|
||||
|
||||
if (mQueryList.contains(id)) {
|
||||
mQueryList.remove(id);
|
||||
// DeviceMethod(MethodAction.PROP, new Object[] { "power", "name", "bright" });
|
||||
JsonArray status = result.get("result").getAsJsonArray();
|
||||
|
||||
// power:
|
||||
if (status.get(0).toString().equals("\"off\"")) {
|
||||
mDeviceStatus.setPowerOff(true);
|
||||
} else if (status.get(0).toString().equals("\"on\"")) {
|
||||
mDeviceStatus.setPowerOff(false);
|
||||
}
|
||||
|
||||
// name:
|
||||
mDeviceStatus.setName(status.get(1).getAsString());
|
||||
|
||||
// brightness:
|
||||
mDeviceStatus.setBrightness(status.get(2).getAsInt());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.debug("Exception", e);
|
||||
}
|
||||
|
||||
super.onNotify(msg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.lib.device;
|
||||
|
||||
import org.openhab.binding.yeelight.internal.lib.device.connection.WifiConnection;
|
||||
import org.openhab.binding.yeelight.internal.lib.enums.DeviceType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
/**
|
||||
* The {@link PitayaDevice} contains methods for handling the light strip device.
|
||||
*
|
||||
* @author Coaster Li - Initial contribution
|
||||
*/
|
||||
public class PitayaDevice extends DeviceBase {
|
||||
private final Logger logger = LoggerFactory.getLogger(PitayaDevice.class);
|
||||
|
||||
public PitayaDevice(String id) {
|
||||
super(id);
|
||||
mDeviceType = DeviceType.stripe;
|
||||
mConnection = new WifiConnection(this);
|
||||
mMinCt = 1700;
|
||||
mMaxCt = 6500;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNotify(String msg) {
|
||||
JsonObject result = new JsonParser().parse(msg).getAsJsonObject();
|
||||
try {
|
||||
if (result.has("id")) {
|
||||
String id = result.get("id").getAsString();
|
||||
// for cmd transaction.
|
||||
|
||||
if (mQueryList.contains(id)) {
|
||||
mQueryList.remove(id);
|
||||
// DeviceMethod(MethodAction.PROP,
|
||||
// new Object[] { "power", "name", "bright", "ct", "rgb", "hue", "sat" });
|
||||
JsonArray status = result.get("result").getAsJsonArray();
|
||||
|
||||
// power:
|
||||
if (status.get(0).toString().equals("\"off\"")) {
|
||||
mDeviceStatus.setPowerOff(true);
|
||||
} else if (status.get(0).toString().equals("\"on\"")) {
|
||||
mDeviceStatus.setPowerOff(false);
|
||||
}
|
||||
|
||||
// name:
|
||||
mDeviceStatus.setName(status.get(1).getAsString());
|
||||
|
||||
// brightness:
|
||||
mDeviceStatus.setBrightness(status.get(2).getAsInt());
|
||||
|
||||
// ct:
|
||||
mDeviceStatus.setCt(status.get(3).getAsInt());
|
||||
|
||||
// color:
|
||||
int color = status.get(4).getAsInt();
|
||||
mDeviceStatus.setColor(color);
|
||||
mDeviceStatus.setR((color >> 16) & 0xFF);
|
||||
mDeviceStatus.setG((color >> 8) & 0xFF);
|
||||
mDeviceStatus.setB(color & 0xFF);
|
||||
mDeviceStatus.setColor(color);
|
||||
mDeviceStatus.setHue(status.get(5).getAsInt());
|
||||
mDeviceStatus.setSat(status.get(6).getAsInt());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.debug("Exception", e);
|
||||
}
|
||||
|
||||
super.onNotify(msg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.lib.device;
|
||||
|
||||
import org.openhab.binding.yeelight.internal.lib.device.connection.WifiConnection;
|
||||
import org.openhab.binding.yeelight.internal.lib.enums.DeviceType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
/**
|
||||
* The {@link WonderDevice} contains methods for handling the color bulb device.
|
||||
*
|
||||
* @author Coaster Li - Initial contribution
|
||||
*/
|
||||
public class WonderDevice extends DeviceBase {
|
||||
private final Logger logger = LoggerFactory.getLogger(WonderDevice.class);
|
||||
|
||||
public WonderDevice(String id) {
|
||||
super(id);
|
||||
mDeviceType = DeviceType.color;
|
||||
mConnection = new WifiConnection(this);
|
||||
mMinCt = 1700;
|
||||
mMaxCt = 6500;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNotify(String msg) {
|
||||
JsonObject result = new JsonParser().parse(msg).getAsJsonObject();
|
||||
try {
|
||||
if (result.has("id")) {
|
||||
String id = result.get("id").getAsString();
|
||||
// for cmd transaction.
|
||||
|
||||
if (mQueryList.contains(id)) {
|
||||
mQueryList.remove(id);
|
||||
// DeviceMethod(MethodAction.PROP,
|
||||
// new Object[] { "power", "name", "bright", "ct", "rgb", "hue", "sat" });
|
||||
JsonArray status = result.get("result").getAsJsonArray();
|
||||
|
||||
// power:
|
||||
if (status.get(0).toString().equals("\"off\"")) {
|
||||
mDeviceStatus.setPowerOff(true);
|
||||
} else if (status.get(0).toString().equals("\"on\"")) {
|
||||
mDeviceStatus.setPowerOff(false);
|
||||
}
|
||||
|
||||
// name:
|
||||
mDeviceStatus.setName(status.get(1).getAsString());
|
||||
|
||||
// brightness:
|
||||
mDeviceStatus.setBrightness(status.get(2).getAsInt());
|
||||
|
||||
// ct:
|
||||
mDeviceStatus.setCt(status.get(3).getAsInt());
|
||||
|
||||
// color:
|
||||
int color = status.get(4).getAsInt();
|
||||
mDeviceStatus.setColor(color);
|
||||
mDeviceStatus.setR((color >> 16) & 0xFF);
|
||||
mDeviceStatus.setG((color >> 8) & 0xFF);
|
||||
mDeviceStatus.setB(color & 0xFF);
|
||||
mDeviceStatus.setColor(color);
|
||||
mDeviceStatus.setHue(status.get(5).getAsInt());
|
||||
mDeviceStatus.setSat(status.get(6).getAsInt());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.debug("Exception", e);
|
||||
}
|
||||
|
||||
super.onNotify(msg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.lib.device;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Properties of yeelight devices as described in the specification.
|
||||
*
|
||||
* @see <a href="https://www.yeelight.com/download/Yeelight_Inter-Operation_Spec.pdf"></a>
|
||||
*
|
||||
* @author Viktor Koop - Initial contribution
|
||||
*/
|
||||
public enum YeelightDeviceProperty {
|
||||
POWER("power"),
|
||||
BRIGHT("bright"),
|
||||
CT("ct"),
|
||||
RGB("rgb"),
|
||||
HUE("hue"),
|
||||
SAT("sat"),
|
||||
COLOR_MODE("color_mode"),
|
||||
FLOWING("flowing"),
|
||||
DELAYOFF("delayoff"),
|
||||
FLOW_PARAMS("flow_params"),
|
||||
MUSIC_ON("music_on"),
|
||||
NAME("name"),
|
||||
BG_POWER("bg_power"),
|
||||
BG_FLOWING("bg_flowing"),
|
||||
BG_FLOW_PARAMS("bg_flow_params"),
|
||||
BG_CT("bg_ct"),
|
||||
BG_LMODE("bg_lmode"),
|
||||
BG_BRIGHT("bg_bright"),
|
||||
BG_RGB("bg_rgb"),
|
||||
BG_HUE("bg_hue"),
|
||||
BG_SAT("bg_sat"),
|
||||
NL_BR("nl_br"),
|
||||
ACTIVE_MODE("active_mode"),
|
||||
MAIN_POWER("main_power");
|
||||
|
||||
private String value;
|
||||
|
||||
private static final Map<String, YeelightDeviceProperty> ENUM_MAP;
|
||||
|
||||
static {
|
||||
final Map<String, YeelightDeviceProperty> tempMap = new HashMap<>();
|
||||
for (YeelightDeviceProperty property : YeelightDeviceProperty.values()) {
|
||||
tempMap.put(property.value, property);
|
||||
}
|
||||
|
||||
ENUM_MAP = Collections.unmodifiableMap(tempMap);
|
||||
}
|
||||
|
||||
YeelightDeviceProperty(String stringValue) {
|
||||
this.value = stringValue;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public static YeelightDeviceProperty fromString(String value) {
|
||||
return ENUM_MAP.get(value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.lib.device.connection;
|
||||
|
||||
import org.openhab.binding.yeelight.internal.lib.device.DeviceMethod;
|
||||
|
||||
/**
|
||||
* Created by jiang on 16/10/21.
|
||||
*
|
||||
* @author Coaster Li - Initial contribution
|
||||
*/
|
||||
public interface ConnectionBase {
|
||||
|
||||
boolean invoke(DeviceMethod method);
|
||||
|
||||
boolean invokeCustom(DeviceMethod method);
|
||||
|
||||
boolean connect();
|
||||
|
||||
boolean disconnect();
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.lib.device.connection;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.Socket;
|
||||
|
||||
import org.openhab.binding.yeelight.internal.lib.device.ConnectState;
|
||||
import org.openhab.binding.yeelight.internal.lib.device.DeviceBase;
|
||||
import org.openhab.binding.yeelight.internal.lib.device.DeviceMethod;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Created by jiang on 16/10/25.
|
||||
*
|
||||
* @author Coaster Li - Initial contribution
|
||||
*/
|
||||
|
||||
public class WifiConnection implements ConnectionBase {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(WifiConnection.class);
|
||||
|
||||
private static final String TAG = WifiConnection.class.getSimpleName();
|
||||
|
||||
private Socket mSocket;
|
||||
private BufferedReader mReader;
|
||||
private BufferedOutputStream mWriter;
|
||||
private Thread mConnectThread;
|
||||
private DeviceBase mDevice;
|
||||
private boolean mCmdRun = false;
|
||||
|
||||
public WifiConnection(DeviceBase device) {
|
||||
mDevice = device;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean invoke(DeviceMethod method) {
|
||||
if (mWriter != null) {
|
||||
try {
|
||||
mWriter.write(method.getParamsStr().getBytes());
|
||||
mWriter.flush();
|
||||
logger.debug("{}: Write Success!", TAG);
|
||||
} catch (Exception e) {
|
||||
logger.debug("{}: write exception, set device to disconnected!", TAG);
|
||||
logger.debug("Exception", e);
|
||||
mDevice.setConnectionState(ConnectState.DISCONNECTED);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean invokeCustom(DeviceMethod method) {
|
||||
if (mWriter != null) {
|
||||
try {
|
||||
mWriter.write(method.getCustomParamsStr().getBytes());
|
||||
mWriter.flush();
|
||||
logger.debug("{}: Write Success!", TAG);
|
||||
} catch (Exception e) {
|
||||
logger.debug("{}: write exception, set device to disconnected!", TAG);
|
||||
logger.debug("Exception", e);
|
||||
mDevice.setConnectionState(ConnectState.DISCONNECTED);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean connect() {
|
||||
logger.debug("{}: connect() entering!", TAG);
|
||||
if (mSocket != null && mSocket.isConnected()) {
|
||||
logger.debug("{}: socket not null, return!", TAG);
|
||||
return true;
|
||||
}
|
||||
mConnectThread = new Thread(() -> {
|
||||
try {
|
||||
mCmdRun = true;
|
||||
logger.debug("{}: connect device! {}, {}", TAG, mDevice.getAddress(), mDevice.getPort());
|
||||
mSocket = new Socket(mDevice.getAddress(), mDevice.getPort());
|
||||
mSocket.setKeepAlive(true);
|
||||
mWriter = new BufferedOutputStream(mSocket.getOutputStream());
|
||||
mReader = new BufferedReader(new InputStreamReader(mSocket.getInputStream()));
|
||||
mDevice.setConnectionState(ConnectState.CONNECTED);
|
||||
while (mCmdRun) {
|
||||
try {
|
||||
String value = mReader.readLine();
|
||||
logger.debug("{}: get response: {}", TAG, value);
|
||||
if (value == null) {
|
||||
mCmdRun = false;
|
||||
} else {
|
||||
mDevice.onNotify(value);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.debug("Exception", e);
|
||||
mCmdRun = false;
|
||||
}
|
||||
}
|
||||
mSocket.close();
|
||||
} catch (Exception e) {
|
||||
logger.debug("{}: connect device! ERROR! {}", TAG, e.getMessage());
|
||||
logger.debug("Exception", e);
|
||||
} finally {
|
||||
mDevice.setConnectionState(ConnectState.DISCONNECTED);
|
||||
mSocket = null;
|
||||
}
|
||||
});
|
||||
mConnectThread.start();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean disconnect() {
|
||||
mDevice.setAutoConnect(false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.lib.enums;
|
||||
|
||||
/**
|
||||
* Yeelight Ceiling lights have to different modes: daylight and moonlight.
|
||||
*
|
||||
* @author Viktor Koop - Initial contribution
|
||||
*/
|
||||
public enum ActiveMode {
|
||||
DAYLIGHT_MODE,
|
||||
MOONLIGHT_MODE
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.lib.enums;
|
||||
|
||||
/**
|
||||
* @author Coaster Li - Initial contribution
|
||||
* @author Joe Ho - Added duration
|
||||
*/
|
||||
public enum DeviceAction {
|
||||
open,
|
||||
close,
|
||||
brightness,
|
||||
color,
|
||||
colortemperature,
|
||||
increase_bright,
|
||||
decrease_bright,
|
||||
increase_ct,
|
||||
decrease_ct,
|
||||
background_color,
|
||||
background_brightness,
|
||||
background_on,
|
||||
background_off,
|
||||
nightlight_off,
|
||||
nightlight_on;
|
||||
|
||||
private String mStrValue;
|
||||
private int mIntValue;
|
||||
private int mIntDuration;
|
||||
|
||||
public void putValue(String value) {
|
||||
this.mStrValue = value;
|
||||
}
|
||||
|
||||
public void putValue(int value) {
|
||||
this.mIntValue = value;
|
||||
}
|
||||
|
||||
public void putDuration(int duration) {
|
||||
this.mIntDuration = duration;
|
||||
}
|
||||
|
||||
public String strValue() {
|
||||
return mStrValue;
|
||||
}
|
||||
|
||||
public int intValue() {
|
||||
return mIntValue;
|
||||
}
|
||||
|
||||
public int intDuration() {
|
||||
return mIntDuration;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.lib.enums;
|
||||
|
||||
/**
|
||||
* @author Coaster Li - Initial contribution
|
||||
*/
|
||||
public enum DeviceMode {
|
||||
|
||||
/*
|
||||
* color temperature mode
|
||||
*/
|
||||
MODE_SUNHINE,
|
||||
|
||||
/*
|
||||
* color mode
|
||||
*/
|
||||
MODE_COLOR,
|
||||
|
||||
/*
|
||||
* color mode
|
||||
*/
|
||||
MODE_HSV,
|
||||
|
||||
/*
|
||||
* color flow mode
|
||||
*/
|
||||
MODE_COLORFLOW,
|
||||
|
||||
/*
|
||||
* device is off.
|
||||
*/
|
||||
MODE_OFF
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.lib.enums;
|
||||
|
||||
/**
|
||||
* The {@link DeviceType} lists the available device/model types.
|
||||
*
|
||||
* @author Coaster Li - Initial contribution
|
||||
*/
|
||||
public enum DeviceType {
|
||||
mono,
|
||||
ct_bulb,
|
||||
color,
|
||||
ceiling,
|
||||
ceiling1,
|
||||
ceiling3,
|
||||
ceiling4,
|
||||
stripe,
|
||||
desklamp
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.lib.enums;
|
||||
|
||||
/**
|
||||
* @author Coaster Li - Initial contribution
|
||||
*/
|
||||
public enum MethodAction {
|
||||
|
||||
PROP("get_prop"),
|
||||
SWITCH("set_power"),
|
||||
TOGGLE("toggle"),
|
||||
BRIGHTNESS("set_bright"),
|
||||
COLORTEMPERATURE("set_ct_abx"),
|
||||
HSV("set_hsv"),
|
||||
RGB("set_rgb"),
|
||||
DEFAULT("set_default"),
|
||||
STARTCF("start_cf"),
|
||||
STOPCF("setop_cf"),
|
||||
SCENE("set_scene"),
|
||||
CRON_ADD("cron_add"),
|
||||
CRON_GET("cron_get"),
|
||||
CRON_DEL("cron_del"),
|
||||
ADJUST("set_adjust"),
|
||||
MUSIC("set_music"),
|
||||
NAME("set_name"),
|
||||
BG_HSV("bg_set_hsv"),
|
||||
BG_RGB("bg_set_rgb"),
|
||||
BG_BRIGHTNESS("bg_set_bright"),
|
||||
BG_SWITCH("bg_set_power");
|
||||
|
||||
public String action;
|
||||
|
||||
MethodAction(String action) {
|
||||
this.action = action;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.lib.listeners;
|
||||
|
||||
import org.openhab.binding.yeelight.internal.lib.device.ConnectState;
|
||||
|
||||
/**
|
||||
* @author Coaster Li - Initial contribution
|
||||
*/
|
||||
public interface DeviceConnectionStateListener {
|
||||
void onConnectionStateChanged(ConnectState connectState);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.lib.listeners;
|
||||
|
||||
import org.openhab.binding.yeelight.internal.lib.device.DeviceBase;
|
||||
|
||||
/**
|
||||
* @author Coaster Li - Initial contribution
|
||||
*/
|
||||
public interface DeviceListener {
|
||||
void onDeviceFound(DeviceBase device);
|
||||
|
||||
void onDeviceLost(DeviceBase device);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.lib.listeners;
|
||||
|
||||
import org.openhab.binding.yeelight.internal.lib.device.DeviceStatus;
|
||||
|
||||
/**
|
||||
* @author Coaster Li - Initial contribution
|
||||
*/
|
||||
public interface DeviceStatusChangeListener {
|
||||
void onStatusChanged(DeviceStatus status);
|
||||
}
|
||||
@@ -0,0 +1,343 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.lib.services;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.MulticastSocket;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.openhab.binding.yeelight.internal.lib.device.DeviceBase;
|
||||
import org.openhab.binding.yeelight.internal.lib.device.DeviceFactory;
|
||||
import org.openhab.binding.yeelight.internal.lib.device.DeviceStatus;
|
||||
import org.openhab.binding.yeelight.internal.lib.device.DeviceWithAmbientLight;
|
||||
import org.openhab.binding.yeelight.internal.lib.device.DeviceWithNightlight;
|
||||
import org.openhab.binding.yeelight.internal.lib.enums.DeviceAction;
|
||||
import org.openhab.binding.yeelight.internal.lib.listeners.DeviceListener;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link DeviceManager} is a class for managing all devices.
|
||||
*
|
||||
* @author Coaster Li - Initial contribution
|
||||
* @author Joe Ho - Added duration
|
||||
* @author Nikita Pogudalov - Added name for Ceiling 1
|
||||
*/
|
||||
public class DeviceManager {
|
||||
private final Logger logger = LoggerFactory.getLogger(DeviceManager.class);
|
||||
|
||||
private static final String TAG = DeviceManager.class.getSimpleName();
|
||||
|
||||
private static final String MULTI_CAST_HOST = "239.255.255.250";
|
||||
private static final int MULTI_CAST_PORT = 1982;
|
||||
private static final String DISCOVERY_MSG = "M-SEARCH * HTTP/1.1\r\n" + "HOST:" + MULTI_CAST_HOST + ":"
|
||||
+ MULTI_CAST_PORT + "\r\n" + "MAN:\"ssdp:discover\"\r\n" + "ST:wifi_bulb\r\n";
|
||||
|
||||
private static final int TIMEOUT = 10000;
|
||||
|
||||
public static final DeviceManager sInstance = new DeviceManager();
|
||||
public volatile boolean mSearching = false;
|
||||
|
||||
public Map<String, DeviceBase> mDeviceList = new HashMap<>();
|
||||
public List<DeviceListener> mListeners = new ArrayList<>();
|
||||
|
||||
private ExecutorService executorService = Executors.newCachedThreadPool();
|
||||
|
||||
private DeviceManager() {
|
||||
}
|
||||
|
||||
public static DeviceManager getInstance() {
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
public void registerDeviceListener(DeviceListener listener) {
|
||||
if (!mListeners.contains(listener)) {
|
||||
mListeners.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
public void unregisterDeviceListener(DeviceListener listener) {
|
||||
mListeners.remove(listener);
|
||||
}
|
||||
|
||||
public void startDiscovery() {
|
||||
startDiscovery(-1);
|
||||
}
|
||||
|
||||
public void startDiscovery(long timeToStop) {
|
||||
searchDevice();
|
||||
if (timeToStop > 0) {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
Thread.sleep(timeToStop);
|
||||
} catch (InterruptedException e) {
|
||||
logger.debug("Interrupted while sleeping", e);
|
||||
} finally {
|
||||
stopDiscovery();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
|
||||
public void stopDiscovery() {
|
||||
mSearching = false;
|
||||
}
|
||||
|
||||
private void searchDevice() {
|
||||
if (mSearching) {
|
||||
logger.debug("{}: Already in discovery, return!", TAG);
|
||||
return;
|
||||
}
|
||||
|
||||
logger.debug("Starting Discovery");
|
||||
|
||||
try {
|
||||
final InetAddress multicastAddress = InetAddress.getByName(MULTI_CAST_HOST);
|
||||
final List<NetworkInterface> networkInterfaces = getNetworkInterfaces();
|
||||
|
||||
mSearching = true;
|
||||
for (final NetworkInterface networkInterface : networkInterfaces) {
|
||||
logger.debug("Starting Discovery on: {}", networkInterface.getDisplayName());
|
||||
|
||||
executorService.execute(() -> {
|
||||
try (MulticastSocket multiSocket = new MulticastSocket(MULTI_CAST_PORT)) {
|
||||
multiSocket.setSoTimeout(TIMEOUT);
|
||||
multiSocket.setNetworkInterface(networkInterface);
|
||||
multiSocket.joinGroup(multicastAddress);
|
||||
|
||||
DatagramPacket dpSend = new DatagramPacket(DISCOVERY_MSG.getBytes(),
|
||||
DISCOVERY_MSG.getBytes().length, multicastAddress, MULTI_CAST_PORT);
|
||||
multiSocket.send(dpSend);
|
||||
|
||||
while (mSearching) {
|
||||
byte[] buf = new byte[1024];
|
||||
|
||||
DatagramPacket dpRecv = new DatagramPacket(buf, buf.length);
|
||||
|
||||
try {
|
||||
multiSocket.receive(dpRecv);
|
||||
byte[] bytes = dpRecv.getData();
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
for (int i = 0; i < dpRecv.getLength(); i++) {
|
||||
// parse /r
|
||||
if (bytes[i] == Character.LINE_SEPARATOR) {
|
||||
continue;
|
||||
}
|
||||
buffer.append((char) bytes[i]);
|
||||
}
|
||||
|
||||
String receivedMessage = buffer.toString();
|
||||
|
||||
logger.debug("{}: got message: {}", TAG, receivedMessage);
|
||||
// we can skip the request because we aren't interested in our own search broadcast
|
||||
// message.
|
||||
if (receivedMessage.startsWith("M-SEARCH")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String[] infos = receivedMessage.split("\n");
|
||||
Map<String, String> bulbInfo = new HashMap<>();
|
||||
for (String info : infos) {
|
||||
int index = info.indexOf(':');
|
||||
if (index == -1) {
|
||||
continue;
|
||||
}
|
||||
String key = info.substring(0, index).trim();
|
||||
String value = info.substring(index + 1).trim();
|
||||
|
||||
bulbInfo.put(key, value);
|
||||
}
|
||||
logger.debug("{}: got bulbInfo: {}", TAG, bulbInfo);
|
||||
if (bulbInfo.containsKey("model") && bulbInfo.containsKey("id")) {
|
||||
DeviceBase device = DeviceFactory.build(bulbInfo);
|
||||
|
||||
if (null == device) {
|
||||
logger.warn("Found unsupported device.");
|
||||
continue;
|
||||
}
|
||||
device.setDeviceName(bulbInfo.getOrDefault("name", ""));
|
||||
|
||||
if (mDeviceList.containsKey(device.getDeviceId())) {
|
||||
updateDevice(mDeviceList.get(device.getDeviceId()), bulbInfo);
|
||||
}
|
||||
notifyDeviceFound(device);
|
||||
}
|
||||
} catch (SocketTimeoutException e) {
|
||||
logger.debug("Error timeout: {}", e.getMessage(), e);
|
||||
}
|
||||
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (!e.getMessage().contains("No IP addresses bound to interface")) {
|
||||
logger.debug("Error getting ip addresses: {}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.debug("Error getting ip addresses: {}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private List<NetworkInterface> getNetworkInterfaces() throws SocketException {
|
||||
return Collections.list(NetworkInterface.getNetworkInterfaces()).stream().filter(device -> {
|
||||
try {
|
||||
return device.isUp() && !device.isLoopback();
|
||||
} catch (SocketException e) {
|
||||
logger.debug("Failed to get device information", e);
|
||||
return false;
|
||||
}
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private void notifyDeviceFound(DeviceBase device) {
|
||||
for (DeviceListener listener : mListeners) {
|
||||
listener.onDeviceFound(device);
|
||||
}
|
||||
}
|
||||
|
||||
public void doAction(String deviceId, DeviceAction action) {
|
||||
DeviceBase device = mDeviceList.get(deviceId);
|
||||
if (device != null) {
|
||||
switch (action) {
|
||||
case open:
|
||||
device.open(action.intDuration());
|
||||
break;
|
||||
case close:
|
||||
device.close(action.intDuration());
|
||||
break;
|
||||
case brightness:
|
||||
device.setBrightness(action.intValue(), action.intDuration());
|
||||
break;
|
||||
case color:
|
||||
device.setColor(action.intValue(), action.intDuration());
|
||||
break;
|
||||
case colortemperature:
|
||||
device.setCT(action.intValue(), action.intDuration());
|
||||
break;
|
||||
case increase_bright:
|
||||
device.increaseBrightness(action.intDuration());
|
||||
break;
|
||||
case decrease_bright:
|
||||
device.decreaseBrightness(action.intDuration());
|
||||
break;
|
||||
case increase_ct:
|
||||
device.increaseCt(action.intDuration());
|
||||
break;
|
||||
case decrease_ct:
|
||||
device.decreaseCt(action.intDuration());
|
||||
break;
|
||||
case background_color:
|
||||
if (device instanceof DeviceWithAmbientLight) {
|
||||
final String[] split = action.strValue().split(",");
|
||||
|
||||
((DeviceWithAmbientLight) device).setBackgroundColor(Integer.parseInt(split[0]),
|
||||
Integer.parseInt(split[1]), action.intDuration());
|
||||
}
|
||||
break;
|
||||
case background_brightness:
|
||||
if (device instanceof DeviceWithAmbientLight) {
|
||||
((DeviceWithAmbientLight) device).setBackgroundBrightness(action.intValue(),
|
||||
action.intDuration());
|
||||
}
|
||||
break;
|
||||
case background_on:
|
||||
if (device instanceof DeviceWithAmbientLight) {
|
||||
((DeviceWithAmbientLight) device).setBackgroundPower(true, action.intDuration());
|
||||
}
|
||||
break;
|
||||
case background_off:
|
||||
if (device instanceof DeviceWithAmbientLight) {
|
||||
((DeviceWithAmbientLight) device).setBackgroundPower(false, action.intDuration());
|
||||
}
|
||||
break;
|
||||
case nightlight_off:
|
||||
if (device instanceof DeviceWithNightlight) {
|
||||
((DeviceWithNightlight) device).toggleNightlightMode(false);
|
||||
}
|
||||
break;
|
||||
case nightlight_on:
|
||||
if (device instanceof DeviceWithNightlight) {
|
||||
((DeviceWithNightlight) device).toggleNightlightMode(true);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void doCustomAction(String deviceId, String action, String params) {
|
||||
DeviceBase device = mDeviceList.get(deviceId);
|
||||
device.sendCustomCommand(action, params);
|
||||
}
|
||||
|
||||
public void addDevice(DeviceBase device) {
|
||||
mDeviceList.put(device.getDeviceId(), device);
|
||||
}
|
||||
|
||||
public void updateDevice(DeviceBase device, Map<String, String> bulbInfo) {
|
||||
String[] addressInfo = bulbInfo.get("Location").split(":");
|
||||
device.setAddress(addressInfo[1].substring(2));
|
||||
device.setPort(Integer.parseInt(addressInfo[2]));
|
||||
device.setOnline(true);
|
||||
Color color = new Color(Integer.parseInt(bulbInfo.get("rgb")));
|
||||
DeviceStatus status = device.getDeviceStatus();
|
||||
status.setR(color.getRed());
|
||||
status.setG(color.getGreen());
|
||||
status.setB(color.getBlue());
|
||||
status.setCt(Integer.parseInt(bulbInfo.get("ct")));
|
||||
status.setHue(Integer.parseInt(bulbInfo.get("hue")));
|
||||
status.setSat(Integer.parseInt(bulbInfo.get("sat")));
|
||||
}
|
||||
|
||||
public static String getDefaultName(DeviceBase device) {
|
||||
if (device.getDeviceModel() != null && !device.getDeviceName().equals("")) {
|
||||
return device.getDeviceName();
|
||||
}
|
||||
switch (device.getDeviceType()) {
|
||||
case ceiling:
|
||||
case ceiling3:
|
||||
return "Yeelight LED Ceiling";
|
||||
case ceiling1:
|
||||
return "Yeelight LED Ceiling with night mode";
|
||||
case ceiling4:
|
||||
return "Yeelight LED Ceiling with ambient light";
|
||||
case color:
|
||||
return "Yeelight Color LED Bulb";
|
||||
case mono:
|
||||
return "Yeelight White LED Bulb";
|
||||
case ct_bulb:
|
||||
return "Yeelight White LED Bulb v2";
|
||||
case stripe:
|
||||
return "Yeelight Color LED Stripe";
|
||||
case desklamp:
|
||||
return "Yeelight Mi LED Desk Lamp";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<binding:binding id="yeelight" 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>Yeelight Binding</name>
|
||||
<description>This is the binding for Yeelight products.</description>
|
||||
|
||||
</binding:binding>
|
||||
@@ -0,0 +1,21 @@
|
||||
<?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:device:base">
|
||||
<parameter name="deviceId" type="text" required="true">
|
||||
<label>Device ID</label>
|
||||
<description>Id of the Yeelight device to connect with.</description>
|
||||
</parameter>
|
||||
<parameter name="duration" type="integer" unit="ms" min="50" max="10000">
|
||||
<label>Duration</label>
|
||||
<description>Duration of transition of events such as on/off, change of brightness and change of color, in
|
||||
milliseconds.</description>
|
||||
<unitLabel>milliseconds</unitLabel>
|
||||
<default>500</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</config-description:config-descriptions>
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="yeelight"
|
||||
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="ceiling">
|
||||
<label>Yeelight LED Ceiling</label>
|
||||
<description>Yeelight LED Ceiling lamp</description>
|
||||
|
||||
<channels>
|
||||
<channel id="brightness" typeId="brightness"/>
|
||||
<channel id="colorTemperature" typeId="colorTemperature"/>
|
||||
<channel id="command" typeId="command"/>
|
||||
</channels>
|
||||
|
||||
<config-description-ref uri="thing-type:device:base"/>
|
||||
</thing-type>
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="yeelight"
|
||||
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="ceiling1">
|
||||
<label>Yeelight LED Ceiling (v1)</label>
|
||||
<description>Yeelight LED Ceiling lamp with Night Mode</description>
|
||||
|
||||
<channels>
|
||||
<channel id="brightness" typeId="brightness"/>
|
||||
<channel id="colorTemperature" typeId="colorTemperature"/>
|
||||
<channel id="nightlight" typeId="nightlight"/>
|
||||
<channel id="command" typeId="command"/>
|
||||
</channels>
|
||||
|
||||
<config-description-ref uri="thing-type:device:base"/>
|
||||
</thing-type>
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="yeelight"
|
||||
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="ceiling4">
|
||||
<label>Yeelight LED Ceiling (v4)</label>
|
||||
<description>Yeelight LED Ceiling with ambient light</description>
|
||||
<channels>
|
||||
<channel id="brightness" typeId="brightness"/>
|
||||
<channel id="colorTemperature" typeId="colorTemperature"/>
|
||||
<channel id="backgroundColor" typeId="backgroundColor"/>
|
||||
<channel id="nightlight" typeId="nightlight"/>
|
||||
<channel id="command" typeId="command"/>
|
||||
</channels>
|
||||
<config-description-ref uri="thing-type:device:base"/>
|
||||
</thing-type>
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="yeelight"
|
||||
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">
|
||||
|
||||
<!-- Brightness Channel -->
|
||||
<channel-type id="brightness">
|
||||
<item-type>Dimmer</item-type>
|
||||
<label>Brightness</label>
|
||||
<description>The brightness channel allows to control the brightness of a light.
|
||||
It is also possible to switch the
|
||||
light on and off.
|
||||
</description>
|
||||
<category>DimmableLight</category>
|
||||
<tags>
|
||||
<tag>Lighting</tag>
|
||||
</tags>
|
||||
</channel-type>
|
||||
|
||||
<!-- Color Channel -->
|
||||
<channel-type id="color">
|
||||
<item-type>Color</item-type>
|
||||
<label>Color</label>
|
||||
<description>The color channel allows to control the color of a light.</description>
|
||||
<category>ColorLight</category>
|
||||
<tags>
|
||||
<tag>Lighting</tag>
|
||||
</tags>
|
||||
</channel-type>
|
||||
|
||||
<!-- Color Temperature Channel -->
|
||||
<channel-type id="colorTemperature">
|
||||
<item-type>Dimmer</item-type>
|
||||
<label>Color Temperature</label>
|
||||
<description>The CT channel allows to control the CT of a light.</description>
|
||||
<category>DimmableCT</category>
|
||||
<tags>
|
||||
<tag>ColorTemperature</tag>
|
||||
</tags>
|
||||
</channel-type>
|
||||
|
||||
<!-- Command Channel -->
|
||||
<channel-type id="command">
|
||||
<item-type>String</item-type>
|
||||
<label>Command</label>
|
||||
<description>Send a command directly to the device. For advanced users only.</description>
|
||||
</channel-type>
|
||||
|
||||
<!-- Background Color Channel -->
|
||||
<channel-type id="backgroundColor">
|
||||
<item-type>Color</item-type>
|
||||
<label>Background Color</label>
|
||||
<description>The color channel allows to control the color of a light.</description>
|
||||
<category>ColorLight</category>
|
||||
<tags>
|
||||
<tag>Lighting</tag>
|
||||
</tags>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="nightlight">
|
||||
<item-type>Switch</item-type>
|
||||
<label>nightlight</label>
|
||||
<description>The nightlight channel allows to switch to nightlight mode.
|
||||
</description>
|
||||
<tags>
|
||||
<tag>Lighting</tag>
|
||||
</tags>
|
||||
</channel-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="yeelight"
|
||||
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="ct_bulb">
|
||||
<label>Yeelight White LED Bulb v2</label>
|
||||
<description>Yeelight White LED Bulb v2</description>
|
||||
|
||||
<channels>
|
||||
<channel id="brightness" typeId="brightness"/>
|
||||
<channel id="colorTemperature" typeId="colorTemperature"/>
|
||||
<channel id="command" typeId="command"/>
|
||||
</channels>
|
||||
|
||||
<config-description-ref uri="thing-type:device:base"/>
|
||||
</thing-type>
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="yeelight"
|
||||
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="desklamp">
|
||||
<label>Yeelight MI LED Desk Lamp</label>
|
||||
<description>Yeelight MI LED Desk Lamp</description>
|
||||
|
||||
<channels>
|
||||
<channel id="brightness" typeId="brightness"/>
|
||||
<channel id="colorTemperature" typeId="colorTemperature"/>
|
||||
<channel id="command" typeId="command"/>
|
||||
</channels>
|
||||
|
||||
<config-description-ref uri="thing-type:device:base"/>
|
||||
</thing-type>
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="yeelight"
|
||||
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="dolphin">
|
||||
<label>Yeelight White LED Bulb</label>
|
||||
<description>Yeelight White LED Bulb</description>
|
||||
|
||||
<channels>
|
||||
<channel id="brightness" typeId="brightness"/>
|
||||
<channel id="command" typeId="command"/>
|
||||
</channels>
|
||||
|
||||
<config-description-ref uri="thing-type:device:base"/>
|
||||
</thing-type>
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="yeelight"
|
||||
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="stripe">
|
||||
<label>Yeelight Color LED Stripe</label>
|
||||
<description>Yeelight Color LED Stripe</description>
|
||||
|
||||
<channels>
|
||||
<channel id="color" typeId="color"/>
|
||||
<channel id="colorTemperature" typeId="colorTemperature"/>
|
||||
<channel id="command" typeId="command"/>
|
||||
</channels>
|
||||
|
||||
<config-description-ref uri="thing-type:device:base"/>
|
||||
</thing-type>
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="yeelight"
|
||||
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="wonder">
|
||||
<label>Yeelight Color LED Bulb</label>
|
||||
<description>Yeelight Color LED Bulb</description>
|
||||
|
||||
<channels>
|
||||
<channel id="color" typeId="color"/>
|
||||
<channel id="colorTemperature" typeId="colorTemperature"/>
|
||||
<channel id="command" typeId="command"/>
|
||||
</channels>
|
||||
|
||||
<config-description-ref uri="thing-type:device:base"/>
|
||||
</thing-type>
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.MockitoAnnotations.initMocks;
|
||||
import static org.openhab.binding.yeelight.internal.YeelightBindingConstants.PARAMETER_DEVICE_ID;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
import org.mockito.Mock;
|
||||
import org.openhab.binding.yeelight.internal.handler.*;
|
||||
import org.openhab.core.config.core.Configuration;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link YeelightHandlerFactory}
|
||||
*
|
||||
* @author Viktor Koop - Initial contribution
|
||||
* @author Nikita Pogudalov - Added YeelightCeilingWithNightHandler for Ceiling 1
|
||||
*/
|
||||
@RunWith(value = Parameterized.class)
|
||||
public class YeelightHandlerFactoryTest {
|
||||
|
||||
private static final List<Object[]> TESTS = Arrays.asList(
|
||||
new Object[][] { { "dolphin", YeelightWhiteHandler.class }, { "ct_bulb", YeelightWhiteHandler.class },
|
||||
{ "wonder", YeelightColorHandler.class }, { "stripe", YeelightStripeHandler.class },
|
||||
{ "ceiling", YeelightCeilingHandler.class }, { "ceiling3", YeelightCeilingHandler.class },
|
||||
{ "ceiling1", YeelightCeilingWithNightHandler.class }, { "desklamp", YeelightCeilingHandler.class },
|
||||
{ "ceiling4", YeelightCeilingWithAmbientHandler.class }, { "unknown", null } });
|
||||
|
||||
private final YeelightHandlerFactory factory = new YeelightHandlerFactory();
|
||||
|
||||
@Mock
|
||||
private Thing thing;
|
||||
|
||||
private final String name;
|
||||
private final Class<?> clazz;
|
||||
|
||||
public YeelightHandlerFactoryTest(String name, Class<?> clazz) {
|
||||
this.name = name;
|
||||
this.clazz = clazz;
|
||||
}
|
||||
|
||||
@Parameters(name = "{0} - {1}")
|
||||
public static List<Object[]> data() {
|
||||
return TESTS;
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
initMocks(this);
|
||||
Configuration configuration = new Configuration();
|
||||
configuration.put(PARAMETER_DEVICE_ID, "");
|
||||
|
||||
when(thing.getConfiguration()).thenReturn(configuration);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCorrectClass() {
|
||||
when(thing.getThingTypeUID()).thenReturn(new ThingTypeUID(YeelightBindingConstants.BINDING_ID, name));
|
||||
ThingHandler handler = factory.createHandler(thing);
|
||||
|
||||
if (null == clazz) {
|
||||
assertNull(name + " should not return any handler but null", handler);
|
||||
} else {
|
||||
assertNotNull(name + " should no return null handler", handler);
|
||||
assertEquals(" should be correct matcher", clazz, handler.getClass());
|
||||
|
||||
assertEquals(thing, handler.getThing());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.yeelight.internal.lib.device;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.openhab.binding.yeelight.internal.lib.enums.ActiveMode;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link DeviceBase}
|
||||
*
|
||||
* @author Viktor Koop - Initial contribution
|
||||
*/
|
||||
public class DeviceBaseTest {
|
||||
|
||||
private DeviceBase deviceBase;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
deviceBase = new DeviceBase("myid") {
|
||||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetColorTemp() {
|
||||
String json = "{\"method\":\"props\",\"params\":{\"ct\":4013}}";
|
||||
deviceBase.onNotify(json);
|
||||
|
||||
final DeviceStatus deviceStatus = deviceBase.getDeviceStatus();
|
||||
assertEquals(4013, deviceStatus.getCt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSwitchToNightlightMode() {
|
||||
deviceBase.onNotify("{\"method\":\"props\",\"params\":{\"nl_br\":96,\"active_mode\":1,\"active_bright\":96}}");
|
||||
final DeviceStatus deviceStatus = deviceBase.getDeviceStatus();
|
||||
|
||||
assertEquals(ActiveMode.MOONLIGHT_MODE, deviceStatus.getActiveMode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNightlightBrightnessUpdate() {
|
||||
String json = "{\"method\":\"props\",\"params\":{\"nl_br\":61,\"active_bright\":61}}";
|
||||
deviceBase.onNotify(json);
|
||||
|
||||
final DeviceStatus deviceStatus = deviceBase.getDeviceStatus();
|
||||
assertEquals(61, deviceStatus.getBrightness());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user