mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 07:02:02 +01:00
Merge d1fa64fb69
into d36b2a8d82
This commit is contained in:
commit
fe8bc9b233
@ -331,6 +331,7 @@
|
||||
/bundles/org.openhab.binding.salus/ @magx2
|
||||
/bundles/org.openhab.binding.samsungtv/ @NickWaterton
|
||||
/bundles/org.openhab.binding.satel/ @druciak
|
||||
/bundles/org.openhab.binding.sbus/ @cipianpascu
|
||||
/bundles/org.openhab.binding.semsportal/ @itb3
|
||||
/bundles/org.openhab.binding.senechome/ @vctender @KorbinianP @eguib
|
||||
/bundles/org.openhab.binding.seneye/ @nikotanghe
|
||||
|
13
bundles/org.openhab.binding.sbus/NOTICE
Normal file
13
bundles/org.openhab.binding.sbus/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
|
132
bundles/org.openhab.binding.sbus/README.md
Normal file
132
bundles/org.openhab.binding.sbus/README.md
Normal file
@ -0,0 +1,132 @@
|
||||
# Sbus Binding
|
||||
|
||||
This binding integrates Sbus devices with openHAB, allowing control and monitoring of Sbus-compatible devices over UDP.
|
||||
Sbus is a protocol used for home automation devices that communicate over UDP networks.
|
||||
The binding supports various device types including RGB/RGBW controllers, temperature sensors, and switch controllers.
|
||||
|
||||
## Supported Things
|
||||
|
||||
* `udp` - Sbus Bridge for UDP communication
|
||||
* `rgbw` - RGB/RGBW Controllers for color and brightness control
|
||||
* `temperature` - Temperature Sensors for monitoring environmental conditions
|
||||
* `switch` - Switch Controllers for basic on/off and dimming control
|
||||
|
||||
## Discovery
|
||||
|
||||
Sbus devices communicate via UDP broadcast, but manual configuration is required to set up the devices in openHAB.
|
||||
Auto-discovery is not supported at this moment.
|
||||
|
||||
## Binding Configuration
|
||||
|
||||
The binding itself does not require any special configuration.
|
||||
|
||||
## Thing Configuration
|
||||
|
||||
### Bridge Configuration
|
||||
|
||||
The Sbus Bridge requires the following configuration parameters:
|
||||
|
||||
| Name | Type | Description | Default | Required | Advanced |
|
||||
|---------|---------|------------------------------------------------------|---------|----------|-----------|
|
||||
| host | text | IP address of the Sbus device (typically broadcast) | N/A | yes | no |
|
||||
| port | integer | UDP port number | 6000 | no | no |
|
||||
|
||||
### RGBW Controller Configuration
|
||||
|
||||
| Name | Type | Description | Default | Required | Advanced |
|
||||
|---------|---------|------------------------------------------------------|---------|----------|-----------|
|
||||
| subnetId| integer | Subnet ID the RGBW controller is part of | N/A | yes | no |
|
||||
| id | integer | Device ID of the RGBW controller | N/A | yes | no |
|
||||
| refresh | integer | Refresh interval in seconds | 30 | no | yes |
|
||||
|
||||
### Temperature Sensor Configuration
|
||||
|
||||
| Name | Type | Description | Default | Required | Advanced |
|
||||
|---------|---------|------------------------------------------------------|---------|----------|-----------|
|
||||
| subnetId| integer | Subnet ID the temperature sensor is part of | N/A | yes | no |
|
||||
| id | integer | Device ID of the temperature sensor | N/A | yes | no |
|
||||
| refresh | integer | Refresh interval in seconds | 30 | no | yes |
|
||||
|
||||
### Switch Controller Configuration
|
||||
|
||||
| Name | Type | Description | Default | Required | Advanced |
|
||||
|---------|---------|------------------------------------------------------|---------|----------|-----------|
|
||||
| subnetId| integer | Subnet ID the switch controller is part of | N/A | yes | no |
|
||||
| id | integer | Device ID of the switch controller | N/A | yes | no |
|
||||
| refresh | integer | Refresh interval in seconds | 30 | no | yes |
|
||||
|
||||
## Channels
|
||||
|
||||
### RGBW Controller Channels
|
||||
|
||||
| Channel | Type | Read/Write | Description |
|
||||
|---------|--------|------------|------------------------------------------------------------|
|
||||
| color | Color | RW | HSB color picker that controls RGBW components (0-100%) |
|
||||
| switch | Switch | RW | On/Off control for the RGBW output with optional timer |
|
||||
|
||||
### Temperature Sensor Channels
|
||||
|
||||
| Channel | Type | Read/Write | Description |
|
||||
|-------------|---------------------|------------|--------------------------------|
|
||||
| temperature | Number:Temperature | R | Current temperature reading. Can be configured to use Celsius (default) or Fahrenheit units |
|
||||
|
||||
### Switch Controller Channels
|
||||
|
||||
| Channel | Type | Read/Write | Description |
|
||||
|---------|--------|------------|-----------------------------------------------------------|
|
||||
| switch | Switch | RW | Basic ON/OFF state control |
|
||||
| dimmer | Dimmer | RW | ON/OFF state with timer transition |
|
||||
| paired | Paired | RW | ON/OFF state for two paired channels (e.g., curtains) |
|
||||
|
||||
## Full Example
|
||||
|
||||
### Thing Configuration
|
||||
|
||||
```
|
||||
Bridge sbus:udp:mybridge [ host="192.168.1.255", port=5000 ] {
|
||||
Thing rgbw colorctrl [ id=72, refresh=30 ] {
|
||||
Channels:
|
||||
Type color-channel : color [ channelNumber=1 ] // HSB color picker, RGBW values stored at channel 1
|
||||
Type switch-channel : power [ channelNumber=1 ] // On/Off control for the RGBW output For complex scenes, one Sbus color controller can keep up to 40 color states. The switch channelNumber has to fall into this range.
|
||||
}
|
||||
|
||||
Thing temperature temp1 [ id=62, refresh=30 ] {
|
||||
Channels:
|
||||
Type temperature-channel : temperature [ channelNumber=1 ]
|
||||
}
|
||||
|
||||
Thing switch switch1 [ id=75, refresh=30 ] {
|
||||
Channels:
|
||||
Type switch-channel : first_switch [ channelNumber=1 ]
|
||||
Type dimmer-channel : second_switch [ channelNumber=2 ]
|
||||
Type paired-channel : third_switch [ channelNumber=3 ]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Item Configuration
|
||||
|
||||
```
|
||||
// Temperature Sensor
|
||||
Number:Temperature Temp_Sensor "Temperature [%.1f °C]" { channel="sbus:temperature:mybridge:temp1:temperature" }
|
||||
|
||||
// Basic Switch
|
||||
Switch Light_Switch "Switch" { channel="sbus:switch:mybridge:switch1:switch" }
|
||||
|
||||
// RGBW Controller with Power Control
|
||||
Group gLight "RGBW Light" <light> ["Lighting"]
|
||||
Color rgbwColor "Color" <colorwheel> (gLight) ["Control", "Light"] { channel="sbus:rgbw:mybridge:colorctrl:color" }
|
||||
Switch rgbwPower "Power" <switch> (gLight) ["Switch", "Light"] { channel="sbus:rgbw:mybridge:colorctrl:power" }
|
||||
```
|
||||
|
||||
### Sitemap Configuration
|
||||
|
||||
```
|
||||
sitemap sbus label="Sbus Demo"
|
||||
{
|
||||
Frame label="Sbus Controls" {
|
||||
Colorpicker item=Light_RGB
|
||||
Text item=Temp_Sensor
|
||||
Switch item=Light_Switch
|
||||
}
|
||||
}
|
46
bundles/org.openhab.binding.sbus/pom.xml
Normal file
46
bundles/org.openhab.binding.sbus/pom.xml
Normal file
@ -0,0 +1,46 @@
|
||||
<?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 https://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>5.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>org.openhab.binding.sbus</artifactId>
|
||||
|
||||
<name>openHAB Add-ons :: Bundles :: Sbus Binding</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>ro.ciprianpascu</groupId>
|
||||
<artifactId>j2sbus</artifactId>
|
||||
<version>1.5.4</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<version>6.0.0</version>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<Import-Package>
|
||||
ro.ciprianpascu.sbus.facade,
|
||||
*
|
||||
</Import-Package>
|
||||
<Embed-Dependency>j2sbus;scope=compile</Embed-Dependency>
|
||||
</instructions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
</project>
|
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<features name="org.openhab.binding.sbus-${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-sbus" description="Sbus Binding" version="${project.version}">
|
||||
<feature>openhab-runtime-base</feature>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.sbus/${project.version}</bundle>
|
||||
</feature>
|
||||
</features>
|
@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2025 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.sbus;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
* The {@link BindingConstants} class defines common constants used across the Sbus binding.
|
||||
*
|
||||
* @author Ciprian Pascu - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class BindingConstants {
|
||||
|
||||
private BindingConstants() {
|
||||
// Prevent instantiation
|
||||
}
|
||||
|
||||
public static final String BINDING_ID = "sbus";
|
||||
|
||||
// Bridge Type
|
||||
public static final ThingTypeUID THING_TYPE_UDP_BRIDGE = new ThingTypeUID(BINDING_ID, "udp");
|
||||
|
||||
// Thing Types
|
||||
public static final ThingTypeUID THING_TYPE_SWITCH = new ThingTypeUID(BINDING_ID, "switch");
|
||||
public static final ThingTypeUID THING_TYPE_TEMPERATURE = new ThingTypeUID(BINDING_ID, "temperature");
|
||||
public static final ThingTypeUID THING_TYPE_RGBW = new ThingTypeUID(BINDING_ID, "rgbw");
|
||||
|
||||
// Channel IDs for Switch Device
|
||||
public static final String CHANNEL_SWITCH_STATE = "state";
|
||||
|
||||
// Channel IDs for Temperature Device
|
||||
public static final String CHANNEL_TEMPERATURE = "temperature";
|
||||
|
||||
// Channel IDs for RGBW Device
|
||||
public static final String CHANNEL_RED = "red";
|
||||
public static final String CHANNEL_GREEN = "green";
|
||||
public static final String CHANNEL_BLUE = "blue";
|
||||
public static final String CHANNEL_WHITE = "white";
|
||||
public static final String CHANNEL_COLOR = "color";
|
||||
}
|
@ -0,0 +1,151 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2025 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.sbus.handler;
|
||||
|
||||
import static org.openhab.binding.sbus.BindingConstants.BINDING_ID;
|
||||
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.sbus.handler.config.SbusDeviceConfig;
|
||||
import org.openhab.core.config.core.Configuration;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.Channel;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||
import org.openhab.core.thing.binding.builder.ChannelBuilder;
|
||||
import org.openhab.core.thing.binding.builder.ThingBuilder;
|
||||
import org.openhab.core.thing.type.ChannelTypeUID;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link AbstractSbusHandler} is the base class for all Sbus device handlers.
|
||||
* It provides common functionality for device initialization, channel management, and polling.
|
||||
*
|
||||
* @author Ciprian Pascu - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public abstract class AbstractSbusHandler extends BaseThingHandler {
|
||||
|
||||
protected final Logger logger = LoggerFactory.getLogger(getClass());
|
||||
protected @Nullable SbusService sbusAdapter;
|
||||
protected @Nullable ScheduledFuture<?> pollingJob;
|
||||
|
||||
public AbstractSbusHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void initialize() {
|
||||
logger.debug("Initializing Sbus handler for thing {}", getThing().getUID());
|
||||
|
||||
initializeChannels();
|
||||
|
||||
Bridge bridge = getBridge();
|
||||
if (bridge == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "No bridge configured");
|
||||
return;
|
||||
}
|
||||
|
||||
SbusBridgeHandler bridgeHandler = (SbusBridgeHandler) bridge.getHandler();
|
||||
if (bridgeHandler == null || bridgeHandler.getThing().getStatus() != ThingStatus.ONLINE) {
|
||||
updateStatus(ThingStatus.UNKNOWN, ThingStatusDetail.BRIDGE_OFFLINE, "Bridge is not online");
|
||||
return;
|
||||
}
|
||||
|
||||
sbusAdapter = bridgeHandler.getSbusConnection();
|
||||
if (sbusAdapter == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED,
|
||||
"Bridge connection not initialized");
|
||||
return;
|
||||
}
|
||||
|
||||
startPolling();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize channels for this device based on its configuration.
|
||||
* This method should be implemented by concrete handlers to set up their specific channels.
|
||||
*/
|
||||
protected abstract void initializeChannels();
|
||||
|
||||
/**
|
||||
* Create or update a channel with the specified ID and type.
|
||||
*
|
||||
* @param channelId The ID of the channel to create/update
|
||||
* @param channelTypeId The type ID of the channel
|
||||
*/
|
||||
protected void createChannel(String channelId, String channelTypeId) {
|
||||
ThingBuilder thingBuilder = ThingBuilder.create(getThing().getThingTypeUID(), getThing().getUID())
|
||||
.withConfiguration(getThing().getConfiguration()).withBridge(getThing().getBridgeUID());
|
||||
|
||||
// Add all existing channels except the one we're creating/updating
|
||||
ChannelUID newChannelUID = new ChannelUID(getThing().getUID(), channelId);
|
||||
for (Channel existingChannel : getThing().getChannels()) {
|
||||
if (!existingChannel.getUID().equals(newChannelUID)) {
|
||||
thingBuilder.withChannel(existingChannel);
|
||||
}
|
||||
}
|
||||
|
||||
// Add the new channel
|
||||
Channel channel = ChannelBuilder.create(newChannelUID).withType(new ChannelTypeUID(BINDING_ID, channelTypeId))
|
||||
.withConfiguration(new Configuration()).build();
|
||||
thingBuilder.withChannel(channel);
|
||||
|
||||
// Update the thing with the new channel configuration
|
||||
updateThing(thingBuilder.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Start polling the device for updates based on the configured refresh interval.
|
||||
*/
|
||||
protected void startPolling() {
|
||||
SbusDeviceConfig config = getConfigAs(SbusDeviceConfig.class);
|
||||
if (config.refresh > 0) {
|
||||
pollingJob = scheduler.scheduleWithFixedDelay(() -> {
|
||||
try {
|
||||
pollDevice();
|
||||
} catch (Exception e) {
|
||||
logger.error("Error polling Sbus device", e);
|
||||
}
|
||||
}, 0, config.refresh, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Poll the device for updates. This method should be implemented by concrete handlers
|
||||
* to update their specific channel states.
|
||||
*/
|
||||
protected abstract void pollDevice();
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
ScheduledFuture<?> job = pollingJob;
|
||||
if (job != null) {
|
||||
job.cancel(true);
|
||||
}
|
||||
final SbusService adapter = sbusAdapter;
|
||||
if (adapter != null) {
|
||||
adapter.close();
|
||||
}
|
||||
pollingJob = null;
|
||||
sbusAdapter = null;
|
||||
super.dispose();
|
||||
}
|
||||
}
|
@ -0,0 +1,104 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2025 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.sbus.handler;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.sbus.handler.config.SbusBridgeConfig;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.binding.BaseBridgeHandler;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link SbusBridgeHandler} is responsible for handling communication with the Sbus bridge.
|
||||
*
|
||||
* @author Ciprian Pascu - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class SbusBridgeHandler extends BaseBridgeHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(SbusBridgeHandler.class);
|
||||
|
||||
@Reference
|
||||
private @Nullable SbusService sbusService;
|
||||
|
||||
/**
|
||||
* Constructs a new SbusBridgeHandler.
|
||||
*
|
||||
* @param bridge the bridge
|
||||
*/
|
||||
public SbusBridgeHandler(Bridge bridge) {
|
||||
super(bridge);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the Sbus bridge handler by establishing a connection to the Sbus network.
|
||||
*/
|
||||
@Override
|
||||
public void initialize() {
|
||||
logger.debug("Initializing Sbus bridge handler for bridge {}", getThing().getUID());
|
||||
|
||||
// Get configuration using the config class
|
||||
SbusBridgeConfig config = getConfigAs(SbusBridgeConfig.class);
|
||||
if (config.host.isBlank()) {
|
||||
updateStatus(ThingStatus.UNKNOWN, ThingStatusDetail.CONFIGURATION_ERROR, "Host address not configured");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
// Initialize Sbus service with the configuration parameters
|
||||
final SbusService service = sbusService;
|
||||
if (service == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.HANDLER_INITIALIZING_ERROR,
|
||||
"Sbus service not available");
|
||||
return;
|
||||
}
|
||||
service.initialize(config.host, config.port);
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} catch (Exception e) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Sbus service.
|
||||
*
|
||||
* @return the Sbus service
|
||||
*/
|
||||
public @Nullable SbusService getSbusConnection() {
|
||||
return sbusService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disposes the handler by closing the Sbus connection.
|
||||
*/
|
||||
@Override
|
||||
public void dispose() {
|
||||
logger.debug("Disposing Sbus bridge handler");
|
||||
final SbusService service = sbusService;
|
||||
if (service != null) {
|
||||
service.close();
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
// Bridge doesn't handle commands directly
|
||||
}
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2025 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.sbus.handler;
|
||||
|
||||
import static org.openhab.binding.sbus.BindingConstants.*;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerFactory;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link SbusHandlerFactory} is responsible for creating things and thing handlers.
|
||||
*
|
||||
* @author Ciprian Pascu - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.sbus")
|
||||
public class SbusHandlerFactory extends BaseThingHandlerFactory {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(SbusHandlerFactory.class);
|
||||
|
||||
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_UDP_BRIDGE, THING_TYPE_SWITCH,
|
||||
THING_TYPE_TEMPERATURE, THING_TYPE_RGBW);
|
||||
|
||||
@Override
|
||||
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
||||
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable ThingHandler createHandler(Thing thing) {
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
|
||||
if (thingTypeUID.equals(THING_TYPE_UDP_BRIDGE)) {
|
||||
logger.debug("Creating Sbus UDP bridge handler for thing {}", thing.getUID());
|
||||
return new SbusBridgeHandler((Bridge) thing);
|
||||
}
|
||||
|
||||
if (thingTypeUID.equals(THING_TYPE_SWITCH)) {
|
||||
logger.debug("Creating Sbus switch handler for thing {}", thing.getUID());
|
||||
return new SbusSwitchHandler(thing);
|
||||
} else if (thingTypeUID.equals(THING_TYPE_TEMPERATURE)) {
|
||||
logger.debug("Creating Sbus temperature handler for thing {}", thing.getUID());
|
||||
return new SbusTemperatureHandler(thing);
|
||||
} else if (thingTypeUID.equals(THING_TYPE_RGBW)) {
|
||||
logger.debug("Creating Sbus RGBW handler for thing {}", thing.getUID());
|
||||
return new SbusRgbwHandler(thing);
|
||||
}
|
||||
|
||||
logger.debug("Unknown thing type: {}", thingTypeUID);
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,246 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2025 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.sbus.handler;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.sbus.handler.config.SbusChannelConfig;
|
||||
import org.openhab.binding.sbus.handler.config.SbusDeviceConfig;
|
||||
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.Channel;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.util.ColorUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link SbusRgbwHandler} is responsible for handling commands for Sbus RGBW devices.
|
||||
* It supports reading and controlling red, green, blue, and white color channels.
|
||||
*
|
||||
* @author Ciprian Pascu - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class SbusRgbwHandler extends AbstractSbusHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(SbusRgbwHandler.class);
|
||||
|
||||
public SbusRgbwHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an openHAB HSBType into an RGBW array ([R, G, B, W]),
|
||||
* with each channel in [0..255].
|
||||
*
|
||||
* We extract 'white' by taking the minimum of R, G, B and
|
||||
* subtracting it from each color channel.
|
||||
*
|
||||
* @param hsbType the openHAB HSBType (hue [0..360], sat [0..100], bri [0..100])
|
||||
* @return an int array [R, G, B, W] each in [0..255]
|
||||
*/
|
||||
private int[] hsbToRgbw(HSBType hsbType) {
|
||||
// Convert HSBType to standard RGB [0..255]
|
||||
PercentType[] rgb = ColorUtil.hsbToRgbPercent(hsbType);
|
||||
// Convert each channel from 0..100 to 0..255
|
||||
int r = (int) Math.round(rgb[0].floatValue() * 2.55);
|
||||
int g = (int) Math.round(rgb[1].floatValue() * 2.55);
|
||||
int b = (int) Math.round(rgb[2].floatValue() * 2.55);
|
||||
|
||||
// Determine the white component as the min of R, G, B
|
||||
int w = Math.min(r, Math.min(g, b));
|
||||
|
||||
// Subtract W from each
|
||||
r -= w;
|
||||
g -= w;
|
||||
b -= w;
|
||||
|
||||
return new int[] { r, g, b, w };
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an RGBW array ([R, G, B, W]) back to an openHAB HSBType.
|
||||
*
|
||||
* We add the W channel back into R, G, and B, then clamp to [0..255].
|
||||
* Finally, we create an HSBType via fromRGB().
|
||||
*
|
||||
* @param rgbw an int array [R, G, B, W] each in [0..255]
|
||||
* @return an HSBType (hue [0..360], saturation/brightness [0..100])
|
||||
*/
|
||||
private HSBType rgbwToHsb(int[] rgbw) {
|
||||
if (rgbw.length < 4) {
|
||||
throw new IllegalArgumentException("rgbw must have 4 elements: [R, G, B, W].");
|
||||
}
|
||||
|
||||
int r = rgbw[0];
|
||||
int g = rgbw[1];
|
||||
int b = rgbw[2];
|
||||
int w = rgbw[3];
|
||||
|
||||
// Restore the combined R, G, B
|
||||
int rTotal = r + w;
|
||||
int gTotal = g + w;
|
||||
int bTotal = b + w;
|
||||
|
||||
// Clamp to [0..255]
|
||||
rTotal = Math.min(255, Math.max(0, rTotal));
|
||||
gTotal = Math.min(255, Math.max(0, gTotal));
|
||||
bTotal = Math.min(255, Math.max(0, bTotal));
|
||||
|
||||
// Convert back to an HSBType via fromRGB
|
||||
HSBType hsbType = HSBType.fromRGB(rTotal, gTotal, bTotal);
|
||||
|
||||
return hsbType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if any RGBW value is greater than 0.
|
||||
*
|
||||
* @param rgbw an int array [R, G, B, W] each in [0..255]
|
||||
* @return true if any value is greater than 0, false otherwise
|
||||
*/
|
||||
private boolean isAnyRgbwValueActive(int[] rgbw) {
|
||||
if (rgbw.length < 4) {
|
||||
return false;
|
||||
}
|
||||
for (int value : rgbw) {
|
||||
if (value > 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initializeChannels() {
|
||||
int switchChannelCount = 0;
|
||||
|
||||
// Validate all channel configurations
|
||||
for (Channel channel : getThing().getChannels()) {
|
||||
SbusChannelConfig channelConfig = channel.getConfiguration().as(SbusChannelConfig.class);
|
||||
var channelTypeUID = channel.getChannelTypeUID();
|
||||
if (channelTypeUID == null) {
|
||||
logger.warn("Channel {} has no channel type", channel.getUID());
|
||||
continue;
|
||||
}
|
||||
String channelTypeId = channelTypeUID.getId();
|
||||
if ("color-channel".equals(channelTypeId)) {
|
||||
if (channelConfig.channelNumber <= 0) {
|
||||
logger.warn("Channel {} has invalid channel number configuration", channel.getUID());
|
||||
}
|
||||
}
|
||||
if ("switch-channel".equals(channelTypeId)) {
|
||||
switchChannelCount++;
|
||||
if (channelConfig.channelNumber <= 0) {
|
||||
logger.warn("Channel {} has invalid channel number configuration", channel.getUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (switchChannelCount > 1) {
|
||||
logger.error("Only one switch channel is allowed for RGBW thing {}", getThing().getUID());
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"Only one switch channel is allowed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void pollDevice() {
|
||||
final SbusService adapter = super.sbusAdapter;
|
||||
if (adapter == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Sbus adapter not initialized");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
SbusDeviceConfig config = getConfigAs(SbusDeviceConfig.class);
|
||||
|
||||
// Update all channels
|
||||
for (Channel channel : getThing().getChannels()) {
|
||||
var channelTypeUID = channel.getChannelTypeUID();
|
||||
if (channelTypeUID == null) {
|
||||
logger.warn("Channel {} has no channel type", channel.getUID());
|
||||
continue;
|
||||
}
|
||||
String channelTypeId = channelTypeUID.getId();
|
||||
SbusChannelConfig channelConfig = channel.getConfiguration().as(SbusChannelConfig.class);
|
||||
|
||||
if ("color-channel".equals(channelTypeId)) {
|
||||
// Read RGBW values for this channel
|
||||
int[] rgbwValues = adapter.readRgbw(config.subnetId, config.id, channelConfig.channelNumber);
|
||||
if (rgbwValues.length >= 4) {
|
||||
// Convert RGBW to HSB using our custom conversion
|
||||
HSBType hsbType = rgbwToHsb(rgbwValues);
|
||||
updateState(channel.getUID(), hsbType);
|
||||
}
|
||||
} else if ("switch-channel".equals(channelTypeId)) {
|
||||
// Read status channels for switch states
|
||||
int[] statuses = adapter.readStatusChannels(config.subnetId, config.id);
|
||||
|
||||
// Update switch state
|
||||
boolean isActive = isAnyRgbwValueActive(statuses);
|
||||
updateState(channel.getUID(), isActive ? OnOffType.ON : OnOffType.OFF);
|
||||
}
|
||||
}
|
||||
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} catch (Exception e) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Error reading device state");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
final SbusService adapter = super.sbusAdapter;
|
||||
if (adapter == null) {
|
||||
logger.warn("Sbus adapter not initialized");
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Sbus adapter not initialized");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Channel channel = getThing().getChannel(channelUID.getId());
|
||||
if (channel != null) {
|
||||
var channelTypeUID = channel.getChannelTypeUID();
|
||||
if (channelTypeUID == null) {
|
||||
logger.warn("Channel {} has no channel type", channel.getUID());
|
||||
return;
|
||||
}
|
||||
String channelTypeId = channelTypeUID.getId();
|
||||
SbusDeviceConfig config = getConfigAs(SbusDeviceConfig.class);
|
||||
SbusChannelConfig channelConfig = channel.getConfiguration().as(SbusChannelConfig.class);
|
||||
|
||||
if ("color-channel".equals(channelTypeId) && command instanceof HSBType hsbCommand) {
|
||||
// Handle color command
|
||||
int[] rgbw = hsbToRgbw(hsbCommand);
|
||||
adapter.writeRgbw(config.subnetId, config.id, channelConfig.channelNumber, rgbw[0], rgbw[1],
|
||||
rgbw[2], rgbw[3]);
|
||||
updateState(channelUID, hsbCommand);
|
||||
} else if ("switch-channel".equals(channelTypeId) && command instanceof OnOffType onOffCommand) {
|
||||
// Handle switch command
|
||||
boolean isOn = onOffCommand == OnOffType.ON;
|
||||
adapter.writeSingleChannel(config.subnetId, config.id, channelConfig.channelNumber, isOn ? 100 : 0,
|
||||
-1);
|
||||
updateState(channelUID, isOn ? OnOffType.ON : OnOffType.OFF);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Error handling command", e);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Error sending command to device");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2025 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.sbus.handler;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link SbusService} defines the interface for handling Sbus communication.
|
||||
*
|
||||
* @author Ciprian Pascu - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public interface SbusService {
|
||||
|
||||
/**
|
||||
* Reads temperature values from a device.
|
||||
*
|
||||
* @param subnetId the subnet ID of the device
|
||||
* @param id the device ID
|
||||
* @return array of temperature values in Celsius
|
||||
* @throws Exception if reading fails
|
||||
*/
|
||||
float[] readTemperatures(int subnetId, int id) throws Exception;
|
||||
|
||||
/**
|
||||
* Reads RGBW values from a device channel.
|
||||
*
|
||||
* @param subnetId the subnet ID of the device
|
||||
* @param id the device ID
|
||||
* @param channelNumber the channel number to read
|
||||
* @return array of RGBW values [R, G, B, W]
|
||||
* @throws Exception if reading fails
|
||||
*/
|
||||
int[] readRgbw(int subnetId, int id, int channelNumber) throws Exception;
|
||||
|
||||
/**
|
||||
* Reads status values from device channels.
|
||||
*
|
||||
* @param subnetId the subnet ID of the device
|
||||
* @param id the device ID
|
||||
* @return array of channel status values
|
||||
* @throws Exception if reading fails
|
||||
*/
|
||||
int[] readStatusChannels(int subnetId, int id) throws Exception;
|
||||
|
||||
/**
|
||||
* Writes RGBW values to a device channel.
|
||||
*
|
||||
* @param subnetId the subnet ID of the device
|
||||
* @param id the device ID
|
||||
* @param channelNumber the channel number to write to
|
||||
* @param r red value (0-255)
|
||||
* @param g green value (0-255)
|
||||
* @param b blue value (0-255)
|
||||
* @param w white value (0-255)
|
||||
* @throws Exception if writing fails
|
||||
*/
|
||||
void writeRgbw(int subnetId, int id, int channelNumber, int r, int g, int b, int w) throws Exception;
|
||||
|
||||
/**
|
||||
* Writes a value to a single channel.
|
||||
*
|
||||
* @param subnetId the subnet ID of the device
|
||||
* @param id the device ID
|
||||
* @param channelNumber the channel number to write to
|
||||
* @param value the value to write
|
||||
* @param timer timer value (-1 for no timer)
|
||||
* @throws Exception if writing fails
|
||||
*/
|
||||
void writeSingleChannel(int subnetId, int id, int channelNumber, int value, int timer) throws Exception;
|
||||
|
||||
/**
|
||||
* Closes the service and releases resources.
|
||||
*/
|
||||
void close();
|
||||
|
||||
void initialize(String host, int port) throws Exception;
|
||||
}
|
@ -0,0 +1,167 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2025 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.sbus.handler;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.sbus.handler.config.SbusChannelConfig;
|
||||
import org.openhab.binding.sbus.handler.config.SbusDeviceConfig;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.OpenClosedType;
|
||||
import org.openhab.core.library.types.PercentType;
|
||||
import org.openhab.core.thing.Channel;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link SbusSwitchHandler} is responsible for handling commands for Sbus switch devices.
|
||||
* It supports reading the current state and switching the device on/off.
|
||||
*
|
||||
* @author Ciprian Pascu - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class SbusSwitchHandler extends AbstractSbusHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(SbusSwitchHandler.class);
|
||||
|
||||
public SbusSwitchHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initializeChannels() {
|
||||
// Get all channel configurations from the thing
|
||||
for (Channel channel : getThing().getChannels()) {
|
||||
// Channels are already defined in thing-types.xml, just validate their configuration
|
||||
SbusChannelConfig channelConfig = channel.getConfiguration().as(SbusChannelConfig.class);
|
||||
if (channelConfig.channelNumber <= 0) {
|
||||
logger.warn("Channel {} has invalid channel number configuration", channel.getUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void pollDevice() {
|
||||
final SbusService adapter = super.sbusAdapter;
|
||||
if (adapter == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Sbus adapter not initialized");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
SbusDeviceConfig config = getConfigAs(SbusDeviceConfig.class);
|
||||
int[] statuses = adapter.readStatusChannels(config.subnetId, config.id);
|
||||
|
||||
// Iterate over all channels and update their states
|
||||
for (Channel channel : getThing().getChannels()) {
|
||||
SbusChannelConfig channelConfig = channel.getConfiguration().as(SbusChannelConfig.class);
|
||||
if (channelConfig.channelNumber > 0 && channelConfig.channelNumber <= statuses.length) {
|
||||
var channelTypeUID = channel.getChannelTypeUID();
|
||||
if (channelTypeUID == null) {
|
||||
logger.warn("Channel {} has no channel type", channel.getUID());
|
||||
continue;
|
||||
}
|
||||
String channelTypeId = channelTypeUID.getId();
|
||||
// 100 when on, something else when off
|
||||
boolean isActive = statuses[channelConfig.channelNumber - 1] == 0x64;
|
||||
|
||||
if ("switch-channel".equals(channelTypeId)) {
|
||||
updateState(channel.getUID(), isActive ? OnOffType.ON : OnOffType.OFF);
|
||||
} else if ("dimmer-channel".equals(channelTypeId)) {
|
||||
updateState(channel.getUID(), new PercentType(statuses[channelConfig.channelNumber - 1]));
|
||||
} else if ("paired-channel".equals(channelTypeId)) {
|
||||
updateState(channel.getUID(), isActive ? OpenClosedType.OPEN : OpenClosedType.CLOSED);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Error reading device state");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
final SbusService adapter = super.sbusAdapter;
|
||||
if (adapter == null) {
|
||||
logger.warn("Sbus adapter not initialized");
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Sbus adapter not initialized");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Channel channel = getThing().getChannel(channelUID);
|
||||
if (channel != null) {
|
||||
SbusChannelConfig channelConfig = channel.getConfiguration().as(SbusChannelConfig.class);
|
||||
if (channelConfig.channelNumber <= 0) {
|
||||
logger.warn("Invalid channel number for {}", channelUID);
|
||||
return;
|
||||
}
|
||||
|
||||
SbusDeviceConfig config = getConfigAs(SbusDeviceConfig.class);
|
||||
|
||||
if (command instanceof OnOffType) {
|
||||
handleOnOffCommand((OnOffType) command, config, channelConfig, channelUID, adapter);
|
||||
} else if (command instanceof PercentType) {
|
||||
handlePercentCommand((PercentType) command, config, channelConfig, channelUID, adapter);
|
||||
} else if (command instanceof OpenClosedType) {
|
||||
handleOpenClosedCommand((OpenClosedType) command, config, channelConfig, channelUID, adapter);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Error handling command", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleOnOffCommand(OnOffType command, SbusDeviceConfig config, SbusChannelConfig channelConfig,
|
||||
ChannelUID channelUID, SbusService adapter) throws Exception {
|
||||
boolean isOn = command == OnOffType.ON;
|
||||
adapter.writeSingleChannel(config.subnetId, config.id, channelConfig.channelNumber, isOn ? 100 : 0,
|
||||
channelConfig.timer);
|
||||
updateState(channelUID, isOn ? OnOffType.ON : OnOffType.OFF);
|
||||
}
|
||||
|
||||
private void handlePercentCommand(PercentType command, SbusDeviceConfig config, SbusChannelConfig channelConfig,
|
||||
ChannelUID channelUID, SbusService adapter) throws Exception {
|
||||
adapter.writeSingleChannel(config.subnetId, config.id, channelConfig.channelNumber, command.intValue(),
|
||||
channelConfig.timer);
|
||||
updateState(channelUID, command);
|
||||
}
|
||||
|
||||
private void handleOpenClosedCommand(OpenClosedType command, SbusDeviceConfig config,
|
||||
SbusChannelConfig channelConfig, ChannelUID channelUID, SbusService adapter) throws Exception {
|
||||
boolean isOpen = command == OpenClosedType.OPEN;
|
||||
// Set main channel
|
||||
if (getChannelToClose(channelConfig, isOpen) > 0) {
|
||||
adapter.writeSingleChannel(config.subnetId, config.id, getChannelToClose(channelConfig, isOpen), 0,
|
||||
channelConfig.timer);
|
||||
}
|
||||
// Set paired channel to opposite state if configured
|
||||
if (getChannelToOpen(channelConfig, isOpen) > 0) {
|
||||
adapter.writeSingleChannel(config.subnetId, config.id, getChannelToOpen(channelConfig, isOpen), 0x64,
|
||||
channelConfig.timer);
|
||||
}
|
||||
updateState(channelUID, isOpen ? OpenClosedType.OPEN : OpenClosedType.CLOSED);
|
||||
}
|
||||
|
||||
private int getChannelToOpen(SbusChannelConfig channelConfig, boolean state) {
|
||||
return state ? channelConfig.channelNumber : channelConfig.pairedChannelNumber;
|
||||
}
|
||||
|
||||
private int getChannelToClose(SbusChannelConfig channelConfig, boolean state) {
|
||||
return state ? channelConfig.pairedChannelNumber : channelConfig.channelNumber;
|
||||
}
|
||||
}
|
@ -0,0 +1,100 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2025 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.sbus.handler;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.sbus.handler.config.SbusDeviceConfig;
|
||||
import org.openhab.binding.sbus.handler.config.TemperatureChannelConfig;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.unit.ImperialUnits;
|
||||
import org.openhab.core.library.unit.SIUnits;
|
||||
import org.openhab.core.thing.Channel;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link SbusTemperatureHandler} is responsible for handling commands for Sbus temperature sensors.
|
||||
* It supports reading temperature values in Celsius.
|
||||
*
|
||||
* @author Ciprian Pascu - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class SbusTemperatureHandler extends AbstractSbusHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(SbusTemperatureHandler.class);
|
||||
|
||||
public SbusTemperatureHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initializeChannels() {
|
||||
// Get all channel configurations from the thing
|
||||
for (Channel channel : getThing().getChannels()) {
|
||||
// Channels are already defined in thing-types.xml, just validate their configuration
|
||||
TemperatureChannelConfig channelConfig = channel.getConfiguration().as(TemperatureChannelConfig.class);
|
||||
if (!channelConfig.isValid()) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"Invalid channel configuration: " + channel.getUID());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void pollDevice() {
|
||||
final SbusService adapter = super.sbusAdapter;
|
||||
if (adapter == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Sbus adapter not initialized");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
SbusDeviceConfig config = getConfigAs(SbusDeviceConfig.class);
|
||||
|
||||
// Read temperatures in Celsius from device
|
||||
float[] temperatures = adapter.readTemperatures(config.subnetId, config.id);
|
||||
|
||||
// Iterate over all channels and update their states with corresponding temperatures
|
||||
for (Channel channel : getThing().getChannels()) {
|
||||
TemperatureChannelConfig channelConfig = channel.getConfiguration().as(TemperatureChannelConfig.class);
|
||||
if (channelConfig.channelNumber > 0 && channelConfig.channelNumber <= temperatures.length) {
|
||||
float temperatureCelsius = temperatures[channelConfig.channelNumber - 1];
|
||||
if (channelConfig.isFahrenheit()) {
|
||||
// Convert Celsius to Fahrenheit
|
||||
float temperatureFahrenheit = (temperatureCelsius * 9 / 5) + 32;
|
||||
updateState(channel.getUID(),
|
||||
new QuantityType<>(temperatureFahrenheit, ImperialUnits.FAHRENHEIT));
|
||||
} else {
|
||||
updateState(channel.getUID(), new QuantityType<>(temperatureCelsius, SIUnits.CELSIUS));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} catch (Exception e) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Error reading device state");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
// Temperature sensors are read-only
|
||||
logger.debug("Temperature device is read-only, ignoring command");
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2025 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.sbus.handler.config;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
import ro.ciprianpascu.sbus.Sbus;
|
||||
|
||||
/**
|
||||
* The {@link SbusBridgeConfig} class contains fields mapping bridge configuration parameters.
|
||||
*
|
||||
* @author Ciprian Pascu - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class SbusBridgeConfig {
|
||||
/**
|
||||
* The host address of the Sbus bridge
|
||||
*/
|
||||
public String host = "localhost";
|
||||
|
||||
/**
|
||||
* The port number for Sbus communication
|
||||
*/
|
||||
public int port = Sbus.DEFAULT_PORT;
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2025 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.sbus.handler.config;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link SbusChannelConfig} class contains fields mapping channel configuration parameters.
|
||||
*
|
||||
* @author Ciprian Pascu - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class SbusChannelConfig {
|
||||
/**
|
||||
* The physical channel number on the Sbus device.
|
||||
*/
|
||||
public int channelNumber;
|
||||
|
||||
/**
|
||||
* The paired channel number for OpenClosedType channels.
|
||||
* When the main channel is opened, this channel will be closed and vice versa.
|
||||
*/
|
||||
public int pairedChannelNumber;
|
||||
|
||||
/**
|
||||
* Timer in seconds to automatically turn off the switch (-1 = disabled).
|
||||
*/
|
||||
public int timer = 0;
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2025 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.sbus.handler.config;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
import ro.ciprianpascu.sbus.Sbus;
|
||||
|
||||
/**
|
||||
* The {@link SbusDeviceConfig} class contains fields mapping thing configuration parameters.
|
||||
*
|
||||
* @author Ciprian Pascu - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class SbusDeviceConfig {
|
||||
/**
|
||||
* The ID of the Sbus device
|
||||
*/
|
||||
public int id = Sbus.DEFAULT_UNIT_ID;
|
||||
|
||||
/**
|
||||
* The subnet ID for Sbus communication
|
||||
*/
|
||||
public int subnetId = Sbus.DEFAULT_SUBNET_ID;
|
||||
|
||||
/**
|
||||
* Refresh interval in seconds
|
||||
*/
|
||||
public int refresh = 30; // Default value from thing-types.xml
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2025 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.sbus.handler.config;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* Configuration class for the temperature channel.
|
||||
*
|
||||
* @author Ciprian Pascu - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class TemperatureChannelConfig {
|
||||
|
||||
/**
|
||||
* The physical channel number on the Sbus device
|
||||
*/
|
||||
public int channelNumber = 1;
|
||||
|
||||
/**
|
||||
* The unit to use for temperature readings (CELSIUS or FAHRENHEIT)
|
||||
*/
|
||||
public String unit = "CELSIUS";
|
||||
|
||||
/**
|
||||
* Validates the configuration parameters.
|
||||
*
|
||||
* @return true if the configuration is valid
|
||||
*/
|
||||
public boolean isValid() {
|
||||
return channelNumber > 0 && ("CELSIUS".equals(unit) || "FAHRENHEIT".equals(unit));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the configured unit is Fahrenheit
|
||||
*
|
||||
* @return true if Fahrenheit is configured, false otherwise
|
||||
*/
|
||||
public boolean isFahrenheit() {
|
||||
return "FAHRENHEIT".equals(unit);
|
||||
}
|
||||
}
|
@ -0,0 +1,108 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2025 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.sbus.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.sbus.handler.SbusService;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Deactivate;
|
||||
|
||||
import ro.ciprianpascu.sbus.facade.SbusAdapter;
|
||||
|
||||
/**
|
||||
* The {@link SbusServiceImpl} implements the SbusService interface by delegating to SbusAdapter.
|
||||
*
|
||||
* @author Ciprian Pascu - Initial contribution
|
||||
*/
|
||||
@Component(service = SbusService.class)
|
||||
@NonNullByDefault
|
||||
public class SbusServiceImpl implements SbusService {
|
||||
private @Nullable SbusAdapter adapter;
|
||||
|
||||
@Activate
|
||||
public SbusServiceImpl() {
|
||||
// Service is activated but adapter is initialized later with connection parameters
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the underlying SbusAdapter with connection parameters.
|
||||
*
|
||||
* @param host the host address of the Sbus device
|
||||
* @param port the port number to use
|
||||
* @throws Exception if initialization fails
|
||||
*/
|
||||
public void initialize(String host, int port) throws Exception {
|
||||
this.adapter = new SbusAdapter(host, port);
|
||||
}
|
||||
|
||||
@Deactivate
|
||||
public void deactivate() {
|
||||
close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float[] readTemperatures(int subnetId, int id) throws Exception {
|
||||
final SbusAdapter adapter = this.adapter;
|
||||
if (adapter == null) {
|
||||
throw new IllegalStateException("SbusAdapter not initialized");
|
||||
}
|
||||
return adapter.readTemperatures(subnetId, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] readRgbw(int subnetId, int id, int channelNumber) throws Exception {
|
||||
final SbusAdapter adapter = this.adapter;
|
||||
if (adapter == null) {
|
||||
throw new IllegalStateException("SbusAdapter not initialized");
|
||||
}
|
||||
return adapter.readRgbw(subnetId, id, channelNumber);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] readStatusChannels(int subnetId, int id) throws Exception {
|
||||
final SbusAdapter adapter = this.adapter;
|
||||
if (adapter == null) {
|
||||
throw new IllegalStateException("SbusAdapter not initialized");
|
||||
}
|
||||
return adapter.readStatusChannels(subnetId, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeRgbw(int subnetId, int id, int channelNumber, int r, int g, int b, int w) throws Exception {
|
||||
final SbusAdapter adapter = this.adapter;
|
||||
if (adapter == null) {
|
||||
throw new IllegalStateException("SbusAdapter not initialized");
|
||||
}
|
||||
adapter.writeRgbw(subnetId, id, channelNumber, r, g, b, w);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeSingleChannel(int subnetId, int id, int channelNumber, int value, int timer) throws Exception {
|
||||
final SbusAdapter adapter = this.adapter;
|
||||
if (adapter == null) {
|
||||
throw new IllegalStateException("SbusAdapter not initialized");
|
||||
}
|
||||
adapter.writeSingleChannel(subnetId, id, channelNumber, value, timer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
final SbusAdapter adapter = this.adapter;
|
||||
if (adapter != null) {
|
||||
adapter.close();
|
||||
this.adapter = null;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<addon:addon id="sbus" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:addon="https://openhab.org/schemas/addon/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/addon/v1.0.0 https://openhab.org/schemas/addon-1.0.0.xsd">
|
||||
<type>binding</type>
|
||||
<name>Sbus Binding</name>
|
||||
<description>Binding for Sbus</description>
|
||||
<connection>local</connection>
|
||||
|
||||
</addon:addon>
|
@ -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="profile:sbus:gainOffset">
|
||||
<parameter name="pre-gain-offset" type="decimal">
|
||||
<label>Pre-gain Offset</label>
|
||||
<description>Offset to add to raw value towards the item (before the gain). The negative
|
||||
offset will be applied in the
|
||||
reverse direction (before inverting the gain). If omitted, zero offset is used.</description>
|
||||
</parameter>
|
||||
<parameter name="gain" type="text">
|
||||
<label>Gain</label>
|
||||
<description>Gain to apply to the state towards the item. One can also specify the unit to declare resulting unit.
|
||||
This is used as divisor for values in the reverse direction. If omitted, gain of 1 is used.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</config-description:config-descriptions>
|
@ -0,0 +1,95 @@
|
||||
# add-on
|
||||
|
||||
addon.sbus.name = Sbus Binding
|
||||
addon.sbus.description = Binding for Sbus
|
||||
|
||||
# thing types
|
||||
|
||||
thing-type.sbus.rgbw.label = Sbus RGBW Controller
|
||||
thing-type.sbus.rgbw.description = Sbus RGBW lighting controller
|
||||
thing-type.sbus.switch.label = Sbus Switch
|
||||
thing-type.sbus.switch.description = Sbus switch device
|
||||
thing-type.sbus.temperature.label = Sbus Temperature Sensor
|
||||
thing-type.sbus.temperature.description = Sbus temperature sensor device
|
||||
thing-type.sbus.udp.label = Sbus UDP Slave
|
||||
thing-type.sbus.udp.description = Endpoint for Sbus UDP slaves
|
||||
|
||||
# thing types config
|
||||
|
||||
thing-type.config.sbus.rgbw.id.label = Device ID
|
||||
thing-type.config.sbus.rgbw.id.description = The ID of the Sbus device
|
||||
thing-type.config.sbus.rgbw.refresh.label = Refresh Interval
|
||||
thing-type.config.sbus.rgbw.refresh.description = Refresh interval in seconds
|
||||
thing-type.config.sbus.rgbw.subnetId.label = SubnetId
|
||||
thing-type.config.sbus.rgbw.subnetId.description = Slave subnet id. Can take any value between 0 and 255.
|
||||
thing-type.config.sbus.switch.id.label = Device ID
|
||||
thing-type.config.sbus.switch.id.description = The ID of the Sbus device
|
||||
thing-type.config.sbus.switch.refresh.label = Refresh Interval
|
||||
thing-type.config.sbus.switch.refresh.description = Refresh interval in seconds
|
||||
thing-type.config.sbus.switch.subnetId.label = SubnetId
|
||||
thing-type.config.sbus.switch.subnetId.description = Slave subnet id. Can take any value between 0 and 255.
|
||||
thing-type.config.sbus.temperature.id.label = Device ID
|
||||
thing-type.config.sbus.temperature.id.description = The ID of the Sbus device
|
||||
thing-type.config.sbus.temperature.refresh.label = Refresh Interval
|
||||
thing-type.config.sbus.temperature.refresh.description = Refresh interval in seconds
|
||||
thing-type.config.sbus.temperature.subnetId.label = SubnetId
|
||||
thing-type.config.sbus.temperature.subnetId.description = Slave subnet id. Can take any value between 0 and 255.
|
||||
thing-type.config.sbus.udp.afterConnectionDelayMillis.label = Connection warm-up time
|
||||
thing-type.config.sbus.udp.afterConnectionDelayMillis.description = Connection warm-up time. Additional time which is spent on preparing connection which should be spent waiting while end device is getting ready to answer first sbus call. In milliseconds.
|
||||
thing-type.config.sbus.udp.connectMaxTries.label = Maximum Connection Tries
|
||||
thing-type.config.sbus.udp.connectMaxTries.description = How many times we try to establish the connection. Should be at least 1.
|
||||
thing-type.config.sbus.udp.connectTimeoutMillis.label = Timeout for Establishing the Connection
|
||||
thing-type.config.sbus.udp.connectTimeoutMillis.description = The maximum time that is waited when establishing the connection. Value of zero means that system/OS default is respected. In milliseconds.
|
||||
thing-type.config.sbus.udp.enableDiscovery.label = Discovery Enabled
|
||||
thing-type.config.sbus.udp.enableDiscovery.description = When enabled we try to find a device specific handler. Turn this on if you're using one of the supported devices.
|
||||
thing-type.config.sbus.udp.host.label = IP Address or Hostname
|
||||
thing-type.config.sbus.udp.host.description = Network address of the device
|
||||
thing-type.config.sbus.udp.port.label = Port
|
||||
thing-type.config.sbus.udp.port.description = Port of the slave
|
||||
thing-type.config.sbus.udp.reconnectAfterMillis.label = Reconnect Again After
|
||||
thing-type.config.sbus.udp.reconnectAfterMillis.description = The connection is kept open at least the time specified here. Value of zero means that connection is disconnected after every Sbus transaction. In milliseconds.
|
||||
thing-type.config.sbus.udp.rtuEncoded.label = RTU Encoding
|
||||
thing-type.config.sbus.udp.rtuEncoded.description = Use RTU Encoding over IP
|
||||
thing-type.config.sbus.udp.timeBetweenReconnectMillis.label = Time Between Reconnections
|
||||
thing-type.config.sbus.udp.timeBetweenReconnectMillis.description = How long to wait to before trying to establish a new connection after the previous one has been disconnected. In milliseconds.
|
||||
thing-type.config.sbus.udp.timeBetweenTransactionsMillis.label = Time Between Transactions
|
||||
thing-type.config.sbus.udp.timeBetweenTransactionsMillis.description = How long to delay we must have at minimum between two consecutive Sbus transactions. In milliseconds.
|
||||
|
||||
# channel group types
|
||||
|
||||
channel-group-type.sbus.colors.label = Color Channels
|
||||
channel-group-type.sbus.colors.description = Group of RGBW color channels
|
||||
channel-group-type.sbus.sensors.label = Temperature Sensors
|
||||
channel-group-type.sbus.sensors.description = Group of temperature sensors
|
||||
channel-group-type.sbus.switches.label = Switch Channels
|
||||
channel-group-type.sbus.switches.description = Group of switch channels
|
||||
|
||||
# channel types
|
||||
|
||||
channel-type.sbus.color-channel.label = Color
|
||||
channel-type.sbus.color-channel.description = Color control
|
||||
channel-type.sbus.dimmer-channel.label = Dimmer State
|
||||
channel-type.sbus.dimmer-channel.description = Dimmer state (0-100%)
|
||||
channel-type.sbus.paired-channel.label = Paired Channel State
|
||||
channel-type.sbus.paired-channel.description = Paired channel state (OPEN/CLOSED) - controls two opposite channels
|
||||
channel-type.sbus.switch-channel.label = Switch State
|
||||
channel-type.sbus.switch-channel.description = Switch state (ON/OFF)
|
||||
channel-type.sbus.temperature-channel.label = Temperature
|
||||
channel-type.sbus.temperature-channel.description = Temperature reading from the device
|
||||
|
||||
# channel types config
|
||||
|
||||
channel-type.config.sbus.color-channel.channelNumber.label = Channel Number
|
||||
channel-type.config.sbus.color-channel.channelNumber.description = The physical channel number on the Sbus device
|
||||
channel-type.config.sbus.dimmer-channel.channelNumber.label = Channel Number
|
||||
channel-type.config.sbus.dimmer-channel.channelNumber.description = The physical channel number on the Sbus device
|
||||
channel-type.config.sbus.dimmer-channel.timer.label = Timer
|
||||
channel-type.config.sbus.dimmer-channel.timer.description = Timer in seconds to automatically turn off the switch (0 = disabled)
|
||||
channel-type.config.sbus.paired-channel.channelNumber.label = Channel Number
|
||||
channel-type.config.sbus.paired-channel.channelNumber.description = The physical channel number on the Sbus device
|
||||
channel-type.config.sbus.paired-channel.pairedChannelNumber.label = Paired Channel Number
|
||||
channel-type.config.sbus.paired-channel.pairedChannelNumber.description = The physical channel number of the paired channel (will be set to opposite state)
|
||||
channel-type.config.sbus.switch-channel.channelNumber.label = Channel Number
|
||||
channel-type.config.sbus.switch-channel.channelNumber.description = The physical channel number on the Sbus device
|
||||
channel-type.config.sbus.temperature-channel.channelNumber.label = Channel Number
|
||||
channel-type.config.sbus.temperature-channel.channelNumber.description = The physical channel number on the Sbus device
|
@ -0,0 +1,78 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="sbus"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
<bridge-type id="udp">
|
||||
<label>Sbus UDP Bridge</label>
|
||||
<description>Endpoint for Sbus UDP slaves</description>
|
||||
<config-description>
|
||||
<parameter name="host" type="text" required="true">
|
||||
<label>IP Address or Hostname</label>
|
||||
<description>Network address of the device</description>
|
||||
<default>localhost</default>
|
||||
<context>network-address</context>
|
||||
</parameter>
|
||||
<parameter name="port" type="integer">
|
||||
<label>Port</label>
|
||||
<description>Port of the slave</description>
|
||||
<default>6000</default>
|
||||
</parameter>
|
||||
|
||||
<parameter name="enableDiscovery" type="boolean">
|
||||
<label>Discovery Enabled</label>
|
||||
<description>When enabled we try to find a device specific handler. Turn this on if you're using one of the
|
||||
supported devices.</description>
|
||||
<default>false</default>
|
||||
</parameter>
|
||||
|
||||
<parameter name="rtuEncoded" type="boolean">
|
||||
<label>RTU Encoding</label>
|
||||
<description>Use RTU Encoding over IP</description>
|
||||
<default>false</default>
|
||||
</parameter>
|
||||
|
||||
<!-- connection handling -->
|
||||
<parameter name="timeBetweenTransactionsMillis" type="integer" min="0" unit="ms">
|
||||
<label>Time Between Transactions</label>
|
||||
<description>How long to delay we must have at minimum between two consecutive Sbus transactions. In milliseconds.
|
||||
</description>
|
||||
<default>60</default>
|
||||
</parameter>
|
||||
<parameter name="timeBetweenReconnectMillis" type="integer" min="0" unit="ms">
|
||||
<label>Time Between Reconnections</label>
|
||||
<description>How long to wait to before trying to establish a new connection after the previous one has been
|
||||
disconnected. In milliseconds.</description>
|
||||
<default>0</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="connectMaxTries" type="integer" min="1">
|
||||
<label>Maximum Connection Tries</label>
|
||||
<description>How many times we try to establish the connection. Should be at least 1.</description>
|
||||
<default>1</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="afterConnectionDelayMillis" type="integer" min="0" unit="ms">
|
||||
<label>Connection warm-up time</label>
|
||||
<description>Connection warm-up time. Additional time which is spent on preparing connection which should be spent
|
||||
waiting while end device is getting ready to answer first sbus call. In milliseconds.</description>
|
||||
<default>0</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="reconnectAfterMillis" type="integer" min="0" unit="ms">
|
||||
<label>Reconnect Again After</label>
|
||||
<description>The connection is kept open at least the time specified here. Value of zero means that connection is
|
||||
disconnected after every Sbus transaction. In milliseconds.</description>
|
||||
<default>0</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="connectTimeoutMillis" type="integer" min="0" unit="ms">
|
||||
<label>Timeout for Establishing the Connection</label>
|
||||
<description>The maximum time that is waited when establishing the connection. Value of zero means that system/OS
|
||||
default is respected. In milliseconds.</description>
|
||||
<default>10000</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</bridge-type>
|
||||
</thing:thing-descriptions>
|
@ -0,0 +1,185 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="sbus"
|
||||
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">
|
||||
|
||||
<!-- Switch Device -->
|
||||
<thing-type id="switch">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="udp"/>
|
||||
</supported-bridge-type-refs>
|
||||
<label>Sbus Switch</label>
|
||||
<description>Sbus switch device</description>
|
||||
<config-description>
|
||||
<parameter name="subnetId" type="integer">
|
||||
<label>SubnetId</label>
|
||||
<description>Slave subnet id. Can take any value between 1 and 255. 255 for broadcast.</description>
|
||||
<default>1</default>
|
||||
<options>
|
||||
<option value="1">1</option>
|
||||
<option value="255">255</option>
|
||||
</options>
|
||||
</parameter>
|
||||
<parameter name="id" type="integer" required="true">
|
||||
<label>Device ID</label>
|
||||
<description>The ID of the Sbus device</description>
|
||||
</parameter>
|
||||
<parameter name="refresh" type="integer">
|
||||
<label>Refresh Interval</label>
|
||||
<description>Refresh interval in seconds</description>
|
||||
<default>30</default>
|
||||
<unitLabel>s</unitLabel>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
<!-- Temperature Device -->
|
||||
<thing-type id="temperature">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="udp"/>
|
||||
</supported-bridge-type-refs>
|
||||
<label>Sbus Temperature Sensor</label>
|
||||
<description>Sbus temperature sensor device</description>
|
||||
<config-description>
|
||||
<parameter name="subnetId" type="integer">
|
||||
<label>SubnetId</label>
|
||||
<description>Slave subnet id. Can take any value between 1 and 255. 255 for broadcast.</description>
|
||||
<default>1</default>
|
||||
<options>
|
||||
<option value="1">1</option>
|
||||
<option value="255">255</option>
|
||||
</options>
|
||||
</parameter>
|
||||
<parameter name="id" type="integer" required="true">
|
||||
<label>Device ID</label>
|
||||
<description>The ID of the Sbus device</description>
|
||||
</parameter>
|
||||
<parameter name="refresh" type="integer">
|
||||
<label>Refresh Interval</label>
|
||||
<description>Refresh interval in seconds</description>
|
||||
<default>30</default>
|
||||
<unitLabel>s</unitLabel>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
<!-- RGBW Device -->
|
||||
<thing-type id="rgbw">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="udp"/>
|
||||
</supported-bridge-type-refs>
|
||||
<label>Sbus RGBW Controller</label>
|
||||
<description>Sbus RGBW lighting controller</description>
|
||||
<config-description>
|
||||
<parameter name="subnetId" type="integer">
|
||||
<label>SubnetId</label>
|
||||
<description>Slave subnet id. Can take any value between 1 and 255. 255 for broadcast.</description>
|
||||
<default>1</default>
|
||||
<options>
|
||||
<option value="1">1</option>
|
||||
<option value="255">255</option>
|
||||
</options>
|
||||
</parameter>
|
||||
<parameter name="id" type="integer" required="true">
|
||||
<label>Device ID</label>
|
||||
<description>The ID of the Sbus device</description>
|
||||
</parameter>
|
||||
<parameter name="refresh" type="integer">
|
||||
<label>Refresh Interval</label>
|
||||
<description>Refresh interval in seconds</description>
|
||||
<default>30</default>
|
||||
<unitLabel>s</unitLabel>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
<!-- Channel Types -->
|
||||
<channel-type id="switch-channel">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Switch State</label>
|
||||
<description>Switch state (ON/OFF)</description>
|
||||
<category>Switch</category>
|
||||
<config-description>
|
||||
<parameter name="channelNumber" type="integer" required="true">
|
||||
<label>Channel Number</label>
|
||||
<description>The physical channel number on the Sbus device</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="dimmer-channel">
|
||||
<item-type>Dimmer</item-type>
|
||||
<label>Dimmer State</label>
|
||||
<description>Dimmer state (0-100%)</description>
|
||||
<category>DimmableLight</category>
|
||||
<config-description>
|
||||
<parameter name="channelNumber" type="integer" required="true">
|
||||
<label>Channel Number</label>
|
||||
<description>The physical channel number on the Sbus device</description>
|
||||
</parameter>
|
||||
<parameter name="timer" type="integer">
|
||||
<label>Timer</label>
|
||||
<description>Timer in seconds to automatically turn off the switch (0 = disabled)</description>
|
||||
<default>0</default>
|
||||
<advanced>true</advanced>
|
||||
<unitLabel>s</unitLabel>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="paired-channel">
|
||||
<item-type>Contact</item-type>
|
||||
<label>Paired Channel State</label>
|
||||
<description>Paired channel state (OPEN/CLOSED) - controls two opposite channels</description>
|
||||
<category>Contact</category>
|
||||
<config-description>
|
||||
<parameter name="channelNumber" type="integer" required="true">
|
||||
<label>Channel Number</label>
|
||||
<description>The physical channel number on the Sbus device</description>
|
||||
</parameter>
|
||||
<parameter name="pairedChannelNumber" type="integer" required="true">
|
||||
<label>Paired Channel Number</label>
|
||||
<description>The physical channel number of the paired channel (will be set to opposite state)</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="temperature-channel">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>Temperature</label>
|
||||
<description>Temperature reading from the device</description>
|
||||
<category>Temperature</category>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
<config-description>
|
||||
<parameter name="channelNumber" type="integer" required="true">
|
||||
<label>Channel Number</label>
|
||||
<description>The physical channel number on the Sbus device</description>
|
||||
</parameter>
|
||||
<parameter name="unit" type="text">
|
||||
<label>Temperature Unit</label>
|
||||
<description>The unit to use for temperature readings (°C or °F)</description>
|
||||
<options>
|
||||
<option value="CELSIUS">Celsius</option>
|
||||
<option value="FAHRENHEIT">Fahrenheit</option>
|
||||
</options>
|
||||
<default>CELSIUS</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="color-channel">
|
||||
<item-type>Color</item-type>
|
||||
<label>Color</label>
|
||||
<description>Color control</description>
|
||||
<category>ColorLight</category>
|
||||
<config-description>
|
||||
<parameter name="channelNumber" type="integer" required="true">
|
||||
<label>Channel Number</label>
|
||||
<description>The physical channel number on the Sbus device</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</channel-type>
|
||||
|
||||
</thing:thing-descriptions>
|
@ -364,6 +364,7 @@
|
||||
<module>org.openhab.binding.salus</module>
|
||||
<module>org.openhab.binding.samsungtv</module>
|
||||
<module>org.openhab.binding.satel</module>
|
||||
<module>org.openhab.binding.sbus</module>
|
||||
<module>org.openhab.binding.semsportal</module>
|
||||
<module>org.openhab.binding.senechome</module>
|
||||
<module>org.openhab.binding.seneye</module>
|
||||
|
@ -48,6 +48,7 @@
|
||||
<include name="*/src/main/feature/feature.xml"/>
|
||||
<exclude name="**/org.openhab.binding.bluetooth*/**/feature.xml"/>
|
||||
<exclude name="**/org.openhab.binding.modbus*/**/feature.xml"/>
|
||||
<exclude name="**/org.openhab.binding.sbus*/**/feature.xml"/>
|
||||
<exclude name="**/org.openhab.binding.mqtt*/**/feature.xml"/>
|
||||
</fileset>
|
||||
<filterchain>
|
||||
@ -73,6 +74,7 @@
|
||||
<features>
|
||||
<feature>openhab-binding-bluetooth</feature>
|
||||
<feature>openhab-binding-modbus</feature>
|
||||
<feature>openhab-binding-sbus</feature>
|
||||
<feature>openhab-binding-mqtt</feature>
|
||||
</features>
|
||||
</configuration>
|
||||
|
@ -48,5 +48,4 @@
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.modbus.sungrow/${project.version}</bundle>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.modbus.sunspec/${project.version}</bundle>
|
||||
</feature>
|
||||
|
||||
</features>
|
||||
|
Loading…
Reference in New Issue
Block a user