final implementation for switch, temperature & rgbw things

Signed-off-by: Ciprian Pascu <contact@ciprianpascu.ro>
This commit is contained in:
Ciprian Pascu 2025-01-02 09:45:46 +02:00
parent a7719c5e33
commit 2b353efdc2
4 changed files with 97 additions and 55 deletions

View File

@ -39,15 +39,21 @@ Please note the broadcast address. This is how Sbus devices communicate with eac
#### RGBW Controller
```
Thing sbus:rgbw:mybridge:light1 [ address=1 ]
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.
}
```
Supported channels:
* `red` - Red component (0-100%)
* `green` - Green component (0-100%)
* `blue` - Blue component (0-100%)
* `white` - White component (0-100%)
* `color` - HSB color picker that controls:
* Red component (0-100%)
* Green component (0-100%)
* Blue component (0-100%)
* White component (0-100%)
* `power` - On/Off control for the RGBW output with optional timer
#### Temperature Sensor
@ -84,11 +90,24 @@ Supported channels:
items/sbus.items:
```
Color Light_RGB "RGB Light" { channel="sbus:rgbw:mybridge:light1:color" }
Number:Temperature Temp_Sensor "Temperature [%.1f °C]" { channel="sbus:temperature:mybridge:temp1:temperature" }
Switch Light_Switch "Switch" { channel="sbus:switch:mybridge:switch1:switch" }
```
Example: RGBW Controller with Power Control
```
// Light Group
Group gLight "RGBW Light" <light> ["Lighting"]
// Color Control
Color rgbwColor "Color" <colorwheel> (gLight) ["Control", "Light"] { channel="sbus:rgbw:mybridge:colorctrl:color" }
// Power Control
Switch rgbwPower "Power" <switch> (gLight) ["Switch", "Light"] { channel="sbus:rgbw:mybridge:colorctrl:power" }
```
sitemap/sbus.sitemap:
```
@ -101,29 +120,3 @@ sitemap sbus label="SBUS Demo"
}
}
```
## Special Case: RGBW Controller with Power Control
Here's how to configure an RGBW controller with both color and power control:
```
// RGBW controller for color
Thing rgbw colorctrl [ id=72, refresh=30 ] {
Channels:
Type color-channel : color [ channelNumber=1 ] // HSB color picker, RGBW values stored at channel 1
}
// Switch for power control
Thing switch powerctrl [ id=72, refresh=30 ] {
Channels:
Type switch-channel : power [ channelNumber=5, timer=-1 ] // On/Off control for the RGBW output. Disable the timer functionality. The device doesn't support it.
}
// Light Group
Group gLight "RGBW Light" <light> ["Lighting"]
// Color Control
Color rgbwColor "Color" <colorwheel> (gLight) ["Control", "Light"] { channel="sbus:rgbw:mybridge:colorctrl:color" }
// Power Control
Switch rgbwPower "Power" <switch> (gLight) ["Switch", "Light"] { channel="sbus:switch:mybridge:powerctrl:power" }

View File

@ -18,7 +18,7 @@
<dependency>
<groupId>ro.ciprianpascu</groupId>
<artifactId>j2sbus</artifactId>
<version>1.5.3-SNAPSHOT</version>
<version>1.5.4</version>
<scope>compile</scope>
</dependency>
</dependencies>

View File

@ -12,12 +12,11 @@
*/
package org.openhab.binding.sbus.handler;
import static org.openhab.binding.sbus.BindingConstants.*;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.sbus.internal.config.SbusChannelConfig;
import org.openhab.binding.sbus.internal.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;
@ -56,7 +55,7 @@ public class SbusRgbwHandler extends AbstractSbusHandler {
* @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]
*/
public static int[] hsbToRgbw(HSBType hsbType) {
private int[] hsbToRgbw(HSBType hsbType) {
if (hsbType == null) {
throw new IllegalArgumentException("HSBType cannot be null.");
}
@ -88,7 +87,7 @@ public class SbusRgbwHandler extends AbstractSbusHandler {
* @param rgbw an int array [R, G, B, W] each in [0..255]
* @return an HSBType (hue [0..360], saturation/brightness [0..100])
*/
public static HSBType rgbwToHsb(int[] rgbw) {
private HSBType rgbwToHsb(int[] rgbw) {
if (rgbw == null || rgbw.length < 4) {
throw new IllegalArgumentException("rgbw must be non-null and have 4 elements: [R, G, B, W].");
}
@ -114,16 +113,49 @@ public class SbusRgbwHandler extends AbstractSbusHandler {
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 == null || rgbw.length < 4) {
return false;
}
for (int value : rgbw) {
if (value > 0) {
return true;
}
}
return false;
}
@Override
protected void initializeChannels() {
// Validate all color channel configurations
int switchChannelCount = 0;
// Validate all channel configurations
for (Channel channel : getThing().getChannels()) {
if ("color-channel".equals(channel.getChannelTypeUID().getId())) {
SbusChannelConfig channelConfig = channel.getConfiguration().as(SbusChannelConfig.class);
SbusChannelConfig channelConfig = channel.getConfiguration().as(SbusChannelConfig.class);
String channelTypeId = channel.getChannelTypeUID().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;
}
}
@ -139,19 +171,26 @@ public class SbusRgbwHandler extends AbstractSbusHandler {
try {
SbusDeviceConfig config = getConfigAs(SbusDeviceConfig.class);
// Update all color channels
// Update all channels
for (Channel channel : getThing().getChannels()) {
if ("color-channel".equals(channel.getChannelTypeUID().getId())) {
SbusChannelConfig channelConfig = channel.getConfiguration().as(SbusChannelConfig.class);
String channelTypeId = channel.getChannelTypeUID().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 != null && 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);
}
}
@ -173,20 +212,24 @@ public class SbusRgbwHandler extends AbstractSbusHandler {
try {
Channel channel = getThing().getChannel(channelUID.getId());
if (channel != null && "color-channel".equals(channel.getChannelTypeUID().getId())
&& command instanceof HSBType hsbCommand) {
if (channel != null) {
String channelTypeId = channel.getChannelTypeUID().getId();
SbusDeviceConfig config = getConfigAs(SbusDeviceConfig.class);
SbusChannelConfig channelConfig = channel.getConfiguration().as(SbusChannelConfig.class);
// Convert HSB to RGBW
int[] rgbw = hsbToRgbw(hsbCommand);
// Write all RGBW values at once using the dedicated method
adapter.writeRgbw(config.subnetId, config.id, channelConfig.channelNumber, rgbw[0], rgbw[1], rgbw[2],
rgbw[3]);
// Update state
updateState(channelUID, hsbCommand);
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);

View File

@ -149,6 +149,12 @@
<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>
<!-- Channel Group Types (unused, but left in case you need them) -->