added migrated 2.x add-ons

Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
Kai Kreuzer
2020-09-21 01:58:32 +02:00
parent bbf1a7fd29
commit 6df6783b60
11662 changed files with 1302875 additions and 11 deletions

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<features name="org.openhab.binding.feican-${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-feican" description="Feican Binding" version="${project.version}">
<feature>openhab-runtime-base</feature>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.feican/${project.version}</bundle>
</feature>
</features>

View File

@@ -0,0 +1,137 @@
/**
* 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.feican.internal;
import java.math.BigDecimal;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.library.types.HSBType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.PercentType;
/**
* Creates commands to send to Feican devices.
*
* @author Hilbrand Bouwkamp - Initial contribution
*/
@NonNullByDefault
public class Commands {
private static final byte[] DISCOVER_COMMAND = { 126, 7, 9, -128, -128, -128, -128, -128, -17 };
private static final byte[] ON_COMMAND = { 126, 4, 4, 1, 0, -128, -128, 0, -17 };
private static final byte[] OFF_COMMAND = { 126, 4, 4, 0, 0, -128, -128, 0, -17 };
private static final byte[] RGB_COMMAND = { 126, 7, 5, 3, 0, 0, 0, 0, -17 };
private static final byte[] COLOR_TEMPERATURE_COMMAND = { 126, 6, 5, 2, 0, 0, -128, 8, -17 };
private static final byte[] BRIGHTNESS_COMMAND = { 126, 4, 1, 0, -128, -128, -128, 0, -17 };
private static final byte[] PROGRAM_COMMAND = { 126, 5, 3, 0, 3, -128, -128, 0, -17 };
private static final byte[] PROGRAM_SPEED_COMMAND = { 126, 4, 2, 0, -128, -128, -128, 0, -17 };
/**
* Returns the command to discover devices.
*
* @return discover command
*/
public static byte[] discover() {
return DISCOVER_COMMAND;
}
/**
* Returns the command to switch a device on or off depending on the given parameter.
*
* @param onOff command to be on or off command
* @return the on/off command
*/
public byte[] switchOnOff(OnOffType onOff) {
if (onOff == OnOffType.ON) {
return ON_COMMAND;
} else {
return OFF_COMMAND;
}
}
/**
* Returns the command to set the color.
*
* @param color the color to set
* @return the color command
*/
public byte[] color(HSBType color) {
byte[] command = RGB_COMMAND.clone();
PercentType[] rgb = color.toRGB();
command[4] = convertColorPercentToByte(rgb[0]);
command[5] = convertColorPercentToByte(rgb[1]);
command[6] = convertColorPercentToByte(rgb[2]);
return command;
}
/**
* Converts a percentage (0-100) to a color range value (0-255). This is needed because {@link HSBType} returns
* color values in the 100-range while a 255 range is needed.
*
* @param percent value to be converted.
* @return converted value as a byte value
*/
private byte convertColorPercentToByte(PercentType percent) {
return percent.toBigDecimal().multiply(BigDecimal.valueOf(255))
.divide(BigDecimal.valueOf(100), 2, BigDecimal.ROUND_HALF_UP).byteValue();
}
/**
* Returns the command to set the color temperature to a value between 0 and 100.
*
* @param percentage the color temperature to set
* @return the color temperature command
*/
public byte[] colorTemperature(PercentType percentage) {
byte[] command = COLOR_TEMPERATURE_COMMAND.clone();
command[4] = percentage.byteValue();
command[5] = (byte) (100 - percentage.intValue());
return command;
}
/**
* Returns the command to set the brightness on a bulb running in color, color temperature or program.
*
* @param percentage the brightness to set
* @return the brightness command
*/
public byte[] brightness(PercentType percentage) {
byte[] command = BRIGHTNESS_COMMAND.clone();
command[3] = percentage.byteValue();
return command;
}
/**
* Returns the command to set a preset program. Program codes on the device start with 0x80 and up. Binding maps
* this with values starting with 1.
*
* @param program this binding value representing the preset program
* @return the command to set the program
*/
public byte[] program(int program) {
byte[] command = PROGRAM_COMMAND.clone();
command[3] = (byte) (-129 + program);
return command;
}
/**
* Returns the command to set program speed to a value between 0 and 100.
*
* @param percentage the program speed to set
* @return the program speed command
*/
public byte[] programSpeed(PercentType percentage) {
byte[] command = PROGRAM_SPEED_COMMAND.clone();
command[3] = percentage.byteValue();
return command;
}
}

View File

@@ -0,0 +1,72 @@
/**
* 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.feican.internal;
import java.io.Closeable;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* Manages the connection to a Feican bulb.
*
* @author Hilbrand Bouwkamp - Initial contribution
*/
@NonNullByDefault
public class Connection implements Closeable {
/**
* UDP port to send command.
*/
public static final int FEICAN_SEND_PORT = 5000;
/**
* UDP port devices send discover replies back.
*/
public static final int FEICAN_RECEIVE_PORT = 6000;
private final InetAddress iNetAddress;
private final DatagramSocket socket;
/**
* Initializes a connection to the given IP address.
*
* @param ipAddress IP address of the connection
* @throws UnknownHostException if ipAddress could not be resolved.
* @throws SocketException if no Datagram socket connection could be made.
*/
public Connection(String ipAddress) throws SocketException, UnknownHostException {
iNetAddress = InetAddress.getByName(ipAddress);
socket = new DatagramSocket();
}
/**
* Sends the 9 bytes command to the Feican device.
*
* @param command the 9 bytes command
* @throws IOException Connection to the bulb failed
*/
public void sendCommand(byte[] command) throws IOException {
DatagramPacket sendPkt = new DatagramPacket(command, command.length, iNetAddress, FEICAN_SEND_PORT);
socket.send(sendPkt);
}
@Override
public void close() {
socket.close();
}
}

View File

@@ -0,0 +1,50 @@
/**
* 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.feican.internal;
import java.util.Collections;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.thing.ThingTypeUID;
/**
* The {@link FeicanBindingConstants} class defines common constants, which are
* used across the whole binding.
*
* @author Hilbrand Bouwkamp - Initial contribution
*/
@NonNullByDefault
public final class FeicanBindingConstants {
private static final String BINDING_ID = "feican";
// List of all Thing Type UIDs
public static final ThingTypeUID THING_TYPE_BULB = new ThingTypeUID(BINDING_ID, "bulb");
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_BULB);
// List of all Channel ids
public static final String CHANNEL_COLOR = "color";
public static final String CHANNEL_COLOR_TEMPERATURE = "color_temperature";
public static final String CHANNEL_PROGRAM = "program";
public static final String CHANNEL_PROGRAM_SPEED = "program_speed";
// List of al property ids
public static final String CONFIG_IP = "ipAddress";
public static final String PROPERTY_MAC = "mac";
private FeicanBindingConstants() {
// Constants class.
}
}

View File

@@ -0,0 +1,25 @@
/**
* 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.feican.internal;
/**
* Feican configuration class.
*
* @author Hilbrand Bouwkamp - Initial contribution
*/
public class FeicanConfiguration {
/**
* IP Address of the device.
*/
public String ipAddress;
}

View File

@@ -0,0 +1,194 @@
/**
* 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.feican.internal;
import static org.openhab.binding.feican.internal.FeicanBindingConstants.*;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.TreeMap;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.config.discovery.AbstractDiscoveryService;
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
import org.openhab.core.config.discovery.DiscoveryService;
import org.openhab.core.thing.ThingUID;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Discovery service for Feican Bulbs. When sending a discovery UDP broadcast command on port 5000 to a Feican bulb. The
* bulp will respond with its mac address send via UDP broadcast over port 6000.
*
* @author Hilbrand Bouwkamp - Initial contribution
*/
@NonNullByDefault
@Component(service = DiscoveryService.class, immediate = true, configurationPid = "discovery.feican")
public class FeicanDiscoveryService extends AbstractDiscoveryService {
private static final int DISCOVERY_TIMEOUT_SECONDS = 5;
private static final int RECEIVE_JOB_TIMEOUT = 20000;
private static final int UDP_PACKET_TIMEOUT = RECEIVE_JOB_TIMEOUT - 50;
private static final String FEICAN_NAME_PREFIX = "FC_";
private final Logger logger = LoggerFactory.getLogger(FeicanDiscoveryService.class);
///// Network
private final byte[] buffer = new byte[32];
@Nullable
private DatagramSocket discoverSocket;
public FeicanDiscoveryService() {
super(SUPPORTED_THING_TYPES_UIDS, DISCOVERY_TIMEOUT_SECONDS, false);
}
@Override
protected void startScan() {
logger.debug("Start scan for Feican devices.");
discoverThings();
}
@Override
protected void stopScan() {
logger.debug("Stop scan for Feican devices.");
closeDiscoverSocket();
super.stopScan();
}
/**
* Performs the actual discovery of Feican devices (things).
*/
private void discoverThings() {
try {
final DatagramPacket receivePacket = new DatagramPacket(buffer, buffer.length);
// No need to call close first, because the caller of this method already has done it.
startDiscoverSocket();
// Runs until the socket call gets a time out and throws an exception. When a time out is triggered it means
// no data was present and nothing new to discover.
while (true) {
// Set packet length in case a previous call reduced the size.
receivePacket.setLength(buffer.length);
if (discoverSocket == null) {
break;
} else {
discoverSocket.receive(receivePacket);
}
logger.debug("Feican device discovery returned package with length {}", receivePacket.getLength());
if (receivePacket.getLength() > 0) {
thingDiscovered(receivePacket);
}
}
} catch (SocketTimeoutException e) {
logger.debug("Discovering poller timeout...");
} catch (IOException e) {
logger.debug("Error during discovery: {}", e.getMessage());
} finally {
closeDiscoverSocket();
removeOlderResults(getTimestampOfLastScan());
}
}
/**
* Opens a {@link DatagramSocket} and sends a packet for discovery of Feican devices.
*
* @throws SocketException
* @throws IOException
*/
private void startDiscoverSocket() throws SocketException, IOException {
discoverSocket = new DatagramSocket(new InetSocketAddress(Connection.FEICAN_RECEIVE_PORT));
discoverSocket.setBroadcast(true);
discoverSocket.setSoTimeout(UDP_PACKET_TIMEOUT);
final InetAddress broadcast = InetAddress.getByName("255.255.255.255");
final DatagramPacket discoverPacket = new DatagramPacket(Commands.discover(), Commands.discover().length,
broadcast, Connection.FEICAN_SEND_PORT);
discoverSocket.send(discoverPacket);
if (logger.isTraceEnabled()) {
logger.trace("Discovery package sent: {}", new String(discoverPacket.getData(), StandardCharsets.UTF_8));
}
}
/**
* Closes the discovery socket and cleans the value. No need for synchronization as this method is called from a
* synchronized context.
*/
private void closeDiscoverSocket() {
if (discoverSocket != null) {
discoverSocket.close();
discoverSocket = null;
}
}
/**
* Register a device (thing) with the discovered properties.
*
* @param packet containing data of detected device
*/
private void thingDiscovered(DatagramPacket packet) {
final String ipAddress = packet.getAddress().getHostAddress();
if (packet.getData().length < 12) {
logger.debug(
"Feican device was detected, but the retrieved data is incomplete: '{}'. Device not registered",
new String(packet.getData(), 0, packet.getLength() - 1, StandardCharsets.UTF_8));
} else {
String thingName = createThingName(packet.getData());
ThingUID thingUID = new ThingUID(THING_TYPE_BULB, thingName.toLowerCase());
thingDiscovered(DiscoveryResultBuilder.create(thingUID).withLabel(thingName)
.withProperties(collectProperties(ipAddress, stringToMac(packet.getData(), packet.getLength())))
.build());
}
}
/**
* Creates a name for the Feican device. The name is derived from the mac address (last 4 bytes) and prefixed with
* FC_. This matches the wifi host it starts when not yet configured.
*
* @param byteMac mac address in bytes
* @return the name for the device
*/
private String createThingName(final byte[] byteMac) {
return FEICAN_NAME_PREFIX + new String(byteMac, 8, 4, StandardCharsets.UTF_8);
}
/**
* Converts a byte representation of a mac address to a real mac address.
*
* @param stringMac byte representation of a mac address
* @return real mac address
*/
private String stringToMac(byte[] data, int length) {
return new String(data, 0, length - 1, StandardCharsets.UTF_8).replaceAll("(..)(?!$)", "$1:");
}
/**
* Collects properties into a map.
*
* @param ipAddress IP address of the thing
* @param mac mac address of the thing
* @return map with properties
*/
private Map<String, Object> collectProperties(String ipAddress, String mac) {
final Map<String, Object> properties = new TreeMap<>();
properties.put(CONFIG_IP, ipAddress);
properties.put(PROPERTY_MAC, mac);
return properties;
}
}

View File

@@ -0,0 +1,48 @@
/**
* 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.feican.internal;
import static org.openhab.binding.feican.internal.FeicanBindingConstants.*;
import org.openhab.binding.feican.internal.handler.FeicanHandler;
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 FeicanHandlerFactory} is responsible for creating things and thing handlers.
*
* @author Hilbrand Bouwkamp - Initial contribution
*/
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.feican")
public class FeicanHandlerFactory extends BaseThingHandlerFactory {
@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_BULB)) {
return new FeicanHandler(thing);
}
return null;
}
}

View File

@@ -0,0 +1,216 @@
/**
* 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.feican.internal.handler;
import static org.openhab.binding.feican.internal.FeicanBindingConstants.*;
import java.io.IOException;
import java.net.SocketException;
import java.net.UnknownHostException;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.feican.internal.Commands;
import org.openhab.binding.feican.internal.Connection;
import org.openhab.binding.feican.internal.FeicanConfiguration;
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.library.types.StringType;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingStatus;
import org.openhab.core.thing.ThingStatusDetail;
import org.openhab.core.thing.binding.BaseThingHandler;
import org.openhab.core.types.Command;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link FeicanHandler} is responsible for handling commands, which are sent to one of the channels.
*
* @author Hilbrand Bouwkamp - Initial contribution
*/
@NonNullByDefault
public class FeicanHandler extends BaseThingHandler {
private final Logger logger = LoggerFactory.getLogger(FeicanHandler.class);
private final Commands commands = new Commands();
private @NonNullByDefault({}) Connection connection;
/**
* Creates a new handler for the Feican thing.
*
* @param thing The thing to create the handler for
*/
public FeicanHandler(Thing thing) {
super(thing);
}
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
try {
if (command instanceof OnOffType) {
handleOnOff((OnOffType) command);
} else if (command instanceof HSBType) {
handleColor(channelUID, (HSBType) command);
} else if (command instanceof PercentType) {
handlePercentage(channelUID, (PercentType) command);
} else if (command instanceof StringType) {
handleString(channelUID, (StringType) command);
}
} catch (IOException e) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, e.getMessage());
}
}
@Override
public void initialize() {
final FeicanConfiguration config = getConfigAs(FeicanConfiguration.class);
logger.debug("Initializing Feican Wifi RGWB Bulb on IP address {}", config.ipAddress);
try {
connection = new Connection(config.ipAddress);
updateStatus(ThingStatus.ONLINE);
} catch (UnknownHostException e) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage());
} catch (SocketException e) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
}
}
@Override
public void dispose() {
super.dispose();
if (connection != null) {
connection.close();
}
}
/**
* Handle for {@link OnOffType} commands.
*
* @param onOff value to set: on or off
* @throws IOException Connection to the bulb failed
*/
private void handleOnOff(OnOffType onOff) throws IOException {
connection.sendCommand(commands.switchOnOff(onOff));
}
/**
* Handle for {@link DecimalType} as an {@link OnOffType} command.
*
* @param value value to derive on or off state from
* @throws IOException Connection to the bulb failed
*/
private void handleOnOff(DecimalType value) throws IOException {
handleOnOff(DecimalType.ZERO.equals(value) ? OnOffType.OFF : OnOffType.ON);
}
/**
* Handle setting the color.
*
* The Feican bulb has a separate command for the brightness. This brightness value is applied to any color value
* send. Because in the color command the brightness is also calculated this would mean the brightness will be
* applied twice; first when getting the RGB values and second in the bulb itself when passing a color value a
* earlier set brightness value is applied. To work around this, the brightness value is first send to the bulb and
* the color is send with a 100% brightness. So the brightness is controlled by the bulb. This is also needed for 2
* reasons. First color temperature also works with brightness and thus to set it with color temperature the
* brightness must be set on the bulb. Secondly when setting brightness in the color widget only the brightness
* value is passed and no color value is available, therefore this binding then sets the brightness on the bulb.
*
* @param channelUID Channel the command is for
* @param command color to set
* @throws IOException Connection to the bulb failed
*/
private void handleColor(ChannelUID channelUID, HSBType command) throws IOException {
if (CHANNEL_COLOR.equals(channelUID.getId())) {
handleBrightness(command.getBrightness());
connection.sendCommand(
commands.color(new HSBType(command.getHue(), command.getSaturation(), PercentType.HUNDRED)));
handleOnOff(command);
}
}
/**
* Handle percentType commands. Action depends on what channel send the command. For brightness related channels
* after the brightness command an extra onOff command is send to update the onOff state conform the brightness
* state.
*
* @param channelUID Channel the command is for
* @param command The percentType command
* @throws IOException Connection to the bulb failed
*/
private void handlePercentage(ChannelUID channelUID, PercentType command) throws IOException {
String id = channelUID.getId();
switch (id) {
case CHANNEL_COLOR:
handleBrightness(command);
handleOnOff(command);
break;
case CHANNEL_COLOR_TEMPERATURE:
handleColorTemperature(command);
handleOnOff(OnOffType.ON);
break;
case CHANNEL_PROGRAM_SPEED:
handleProgramSpeed(command);
handleOnOff(OnOffType.ON);
break;
}
}
/**
* Handles the brightness command.
*
* @param command percentage of brightness to set
* @throws IOException Connection to the bulb failed
*/
private void handleBrightness(PercentType command) throws IOException {
connection.sendCommand(commands.brightness(command));
}
/**
* Handles the color temperature command.
*
* @param command color temperature as set a value between 0 and 100
* @throws IOException Connection to the bulb failed
*/
private void handleColorTemperature(PercentType command) throws IOException {
connection.sendCommand(commands.colorTemperature(command));
}
/**
* Handles the speed of a preset program.
*
* @param command the speed as set as a percentage value
* @throws IOException Connection to the bulb failed
*/
private void handleProgramSpeed(PercentType command) throws IOException {
connection.sendCommand(commands.programSpeed(command));
}
/**
* Handles setting a preset program.
*
* @param channelUID works for the program channel
* @param command String value as id of the program to set
* @throws IOException Connection to the bulb failed
*/
private void handleString(ChannelUID channelUID, StringType command) throws NumberFormatException, IOException {
if (CHANNEL_PROGRAM.equals(channelUID.getId())) {
connection.sendCommand(commands.program(Integer.valueOf(command.toFullString())));
}
}
}

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<binding:binding id="feican" 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>Feican Binding</name>
<description>This is the binding for Feican light bulbs.</description>
<author>Hilbrand Bouwkamp</author>
</binding:binding>

View File

@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="feican"
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">
<channel-type id="color">
<item-type>Color</item-type>
<label>Color</label>
<description>This channel supports adjusting the color of a light.
</description>
<category>ColorLight</category>
<tags>
<tag>Lighting</tag>
</tags>
</channel-type>
<channel-type id="color_temperature">
<item-type>Dimmer</item-type>
<label>Color Temperature</label>
<description>This channel supports adjusting the color temperature from cold (0%) to warm (100%).</description>
<category>ColorLight</category>
</channel-type>
<channel-type id="program" advanced="true">
<item-type>String</item-type>
<label>Program</label>
<description>This channel supports setting the bulb to a static, jumping, gradient or flashing light.</description>
<state readOnly="false">
<options>
<option value="1">Static red</option>
<option value="2">Static blue</option>
<option value="3">Static green</option>
<option value="4">Static cyan</option>
<option value="5">Static yellow</option>
<option value="6">Static purple</option>
<option value="7">Static white</option>
<option value="8">Tricolor jump</option>
<option value="9">7-color jump</option>
<option value="10">Tricolor gradient</option>
<option value="11">7-color gradient</option>
<option value="12">Red gradient</option>
<option value="13">Green gradient</option>
<option value="14">Blue gradient</option>
<option value="15">Yellow gradient</option>
<option value="16">Cyan gradient</option>
<option value="17">Purple gradient</option>
<option value="18">White gradient</option>
<option value="19">Red-Green gradient</option>
<option value="20">Red-Blue gradient</option>
<option value="21">Green-Blue gradient</option>
<option value="22">7-color flash</option>
<option value="23">Red flash</option>
<option value="24">Green flash</option>
<option value="25">Blue flash</option>
<option value="26">Yellow flash</option>
<option value="27">Cyan flash</option>
<option value="28">Purple flash</option>
<option value="29">White flash</option>
</options>
</state>
</channel-type>
<channel-type id="program_speed" advanced="true">
<item-type>Dimmer</item-type>
<label>Program Speed</label>
<description>Speed of flash and gradient programs from 0 (slow) to 100 (fast).</description>
</channel-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="feican"
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="bulb">
<label>Wifi RGBW Bulb</label>
<description>A dimmable light with changeable colors.</description>
<channels>
<channel id="color" typeId="color"/>
<channel id="color_temperature" typeId="color_temperature"/>
<channel id="program" typeId="program"/>
<channel id="program_speed" typeId="program_speed"/>
</channels>
<config-description>
<parameter name="ipAddress" type="text" required="true">
<context>network-address</context>
<label>IP Address</label>
<description>IP Address of the device.</description>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>