[sbus] Add support for STOP command (#18490)

Signed-off-by: Ciprian Pascu <contact@ciprianpascu.ro>
This commit is contained in:
Ciprian Pascu
2025-04-08 11:53:00 +02:00
committed by GitHub
parent 82d572dc9f
commit 965a6bbe0f
4 changed files with 45 additions and 26 deletions
+11 -9
View File
@@ -20,6 +20,8 @@ Auto-discovery is not supported at this moment.
The binding itself does not require any special configuration.
*note* If openHAB is deployed in a Docker container, you must set the `network_mode` to host. Without this setting, messages on the host network will not reach the Docker container's internal networks.
## Thing Configuration
### Bridge Configuration
@@ -72,11 +74,11 @@ The Sbus Bridge has the following configuration parameters:
### 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 | Contact | RW | OPEN/CLOSED state for two paired channels (e.g., curtains)|
| Channel | Type | Read/Write | Description |
|---------|----------------|------------|-----------------------------------------------------------|
| switch | Switch | RW | Basic ON/OFF state control |
| dimmer | Dimmer | RW | ON/OFF state with timer transition |
| paired | Rollershutter | RW | UP/DOWN/STOP control for two paired channels (e.g., rollershutters)|
## Full Example
@@ -99,7 +101,7 @@ Bridge sbus:udp:mybridge [ host="192.168.1.255", port=5000 ] {
Channels:
Type switch-channel : first_switch [ channelNumber=1 ]
Type dimmer-channel : second_switch [ channelNumber=2 ]
Type paired-channel : third_switch [ channelNumber=3 ]
Type paired-channel : third_switch [ channelNumber=3, pairedChannelNumber=4 ]
}
}
```
@@ -113,8 +115,8 @@ Number:Temperature Temp_Sensor "Temperature [%.1f °C]" { channel="sbus:temperat
// Basic Switch
Switch Light_Switch "Switch" { channel="sbus:switch:mybridge:switch1:switch" }
// Paired Channel (e.g., for curtains)
Contact Curtain_Switch "Curtain [%s]" { channel="sbus:switch:mybridge:switch1:third_switch" }
// Paired Channel (e.g., for rollershutters)
Rollershutter Rollershutter_Switch "Rollershutter [%s]" { channel="sbus:switch:mybridge:switch1:third_switch" }
// RGBW Controller with Power Control
Group gLight "RGBW Light" <light> ["Lighting"]
@@ -131,6 +133,6 @@ sitemap sbus label="Sbus Demo"
Colorpicker item=Light_RGB
Text item=Temp_Sensor
Switch item=Light_Switch
Text item=Curtain_Switch
Rollershutter item=Rollershutter_Switch
}
}
+1 -1
View File
@@ -18,7 +18,7 @@
<dependency>
<groupId>ro.ciprianpascu</groupId>
<artifactId>j2sbus</artifactId>
<version>1.5.7</version>
<version>1.5.8</version>
<scope>compile</scope>
</dependency>
</dependencies>
@@ -19,8 +19,9 @@ import org.openhab.binding.sbus.handler.config.SbusDeviceConfig;
import org.openhab.core.i18n.LocaleProvider;
import org.openhab.core.i18n.TranslationProvider;
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.library.types.StopMoveType;
import org.openhab.core.library.types.UpDownType;
import org.openhab.core.thing.Channel;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
@@ -98,10 +99,11 @@ public class SbusSwitchHandler extends AbstractSbusHandler {
} else if (BindingConstants.CHANNEL_TYPE_DIMMER.equals(channelTypeId)) {
updateState(channel.getUID(), new PercentType(statuses[channelConfig.channelNumber - 1]));
} else if (BindingConstants.CHANNEL_TYPE_PAIRED.equals(channelTypeId)) {
updateState(channel.getUID(), isActive ? OpenClosedType.OPEN : OpenClosedType.CLOSED);
updateState(channel.getUID(), isActive ? UpDownType.UP : UpDownType.DOWN);
}
}
}
updateStatus(ThingStatus.ONLINE);
} catch (Exception e) {
Bundle bundle = FrameworkUtil.getBundle(getClass());
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
@@ -136,8 +138,10 @@ public class SbusSwitchHandler extends AbstractSbusHandler {
handleOnOffCommand(onOffCommand, config, channelConfig, channelUID, adapter);
} else if (command instanceof PercentType percentCommand) {
handlePercentCommand(percentCommand, config, channelConfig, channelUID, adapter);
} else if (command instanceof OpenClosedType openClosedCommand) {
handleOpenClosedCommand(openClosedCommand, config, channelConfig, channelUID, adapter);
} else if (command instanceof UpDownType upDownCommand) {
handleUpDownCommand(upDownCommand, config, channelConfig, channelUID, adapter);
} else if (command instanceof StopMoveType stopMoveCommand && stopMoveCommand == StopMoveType.STOP) {
handleStopMoveCommand(config, channelConfig, channelUID, adapter);
}
}
} catch (Exception e) {
@@ -163,20 +167,20 @@ public class SbusSwitchHandler extends AbstractSbusHandler {
updateState(channelUID, command);
}
private void handleOpenClosedCommand(OpenClosedType command, SbusDeviceConfig config,
SbusChannelConfig channelConfig, ChannelUID channelUID, SbusService adapter) throws Exception {
boolean isOpen = command == OpenClosedType.OPEN;
private void handleUpDownCommand(UpDownType command, SbusDeviceConfig config, SbusChannelConfig channelConfig,
ChannelUID channelUID, SbusService adapter) throws Exception {
boolean isUp = command == UpDownType.UP;
// Set main channel
if (getChannelToClose(channelConfig, isOpen) > 0) {
adapter.writeSingleChannel(config.subnetId, config.id, getChannelToClose(channelConfig, isOpen), 0,
if (getChannelToClose(channelConfig, isUp) > 0) {
adapter.writeSingleChannel(config.subnetId, config.id, getChannelToClose(channelConfig, isUp), 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,
if (getChannelToOpen(channelConfig, isUp) > 0) {
adapter.writeSingleChannel(config.subnetId, config.id, getChannelToOpen(channelConfig, isUp), 0x64,
channelConfig.timer);
}
updateState(channelUID, isOpen ? OpenClosedType.OPEN : OpenClosedType.CLOSED);
updateState(channelUID, isUp ? UpDownType.UP : UpDownType.DOWN);
}
private int getChannelToOpen(SbusChannelConfig channelConfig, boolean state) {
@@ -186,4 +190,17 @@ public class SbusSwitchHandler extends AbstractSbusHandler {
private int getChannelToClose(SbusChannelConfig channelConfig, boolean state) {
return state ? channelConfig.pairedChannelNumber : channelConfig.channelNumber;
}
private void handleStopMoveCommand(SbusDeviceConfig config, SbusChannelConfig channelConfig, ChannelUID channelUID,
SbusService adapter) throws Exception {
// For STOP command, we stop both channels by setting them to 0
if (channelConfig.channelNumber > 0) {
adapter.writeSingleChannel(config.subnetId, config.id, channelConfig.channelNumber, 0, channelConfig.timer);
}
if (channelConfig.pairedChannelNumber > 0) {
adapter.writeSingleChannel(config.subnetId, config.id, channelConfig.pairedChannelNumber, 0,
channelConfig.timer);
}
// We don't update the state here as the rollershutter is neither UP nor DOWN after stopping
}
}
@@ -130,10 +130,10 @@
</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>
<item-type>Rollershutter</item-type>
<label>Rollershutter Control</label>
<description>Rollershutter control (UP/DOWN) - controls two opposite channels</description>
<category>Blinds</category>
<config-description>
<parameter name="channelNumber" type="integer" required="true">
<label>Channel Number</label>