Here’s a solution for integrating a Sonoff B1 bulb into OpenHAB. Consider it a work in progress, it’s functional as it stands but I would welcome any and all feedback/improvements.
B1 support in Sonoff-Tasmota is still in development so things will probably change there too, although probably extending features rather than breaking changes.
What’s needed:
- Sonoff B1 WiFi Bulb(s), flashed with Sonoff-Tasmota, set up with a unique MQTT root topic (“light1” in this example), and connected to your WiFi network and MQTT server.
- MQTT server such as Mosquitto.
- OpenHAB installation. (I’m working with 2.1 here)
- MQTT binding and action.
- JSONPATH transformation.
The B1 bulbs are RGBCW LED lamps of moderate brightness that can be had for <$20 from iTead. Inside the lamp is an array of RGB LEDs along with Cool White and Warm White LEDs that can be mixed in any amount desired. They’re based on the ESP8285, a stablemate of the ever-popular ESP8266 WiFi SoC. I have never used the eWeLink app that iTead offers because Sonoff-Tasmota and MQTT provides a far more flexible solution. The colour output string is expressed as 5 bytes of hex in the format RRGGBBCCWW, which presents a slight problem to integrate with the controls and formats provided by OpenHAB.
Items:
Dimmer dBedroom_Lamp "Bedroom Lamp" <dimmablelight> ["Lighting"] {mqtt=">[MQTT:cmnd/light1/DIMMER:command:*:default],<[MQTT:stat/light1/RESULT:state:JSONPATH($.Dimmer)]",autoupdate="false"}
Switch sBedroom_Lamp "Bedroom Lamp Switch" <light> (gAllLights) {mqtt=">[MQTT:cmnd/light1/POWER:command:*:default],<[MQTT:stat/light1/RESULT:state:JSONPATH($.POWER)]",autoupdate="false"}
Color cBedroom_Lamp "Bedroom Lamp Colour" <colorlight> {autoupdate="false"}
Dimmer ctBedroom_Lamp "Bedroom Lamp Colour Temperature" <light> {autoupdate="false"}
String mqBR_Lamp_Colour "Bedroom Lamp Colour MQTT Target" <colorlight> {mqtt=">[MQTT:cmnd/light1/COLOR:command:*:default],<[MQTT:stat/light1/RESULT:state:JSONPATH($.Color)]",autoupdate="false"}
Here we see the main controls exposed to MQTT, Dimmer, Power and Color. Additionally the CT (colour temperature) command is used via the action in the rules:
import java.awt.Color
import java.util.List
rule "Bedroom Lamp Colour Return"
when
Item mqBR_Lamp_Colour changed
then
var String RGB = mqBR_Lamp_Colour.state.toString
var String red_s = RGB.charAt(0).toString + RGB.charAt(1).toString
var Number red = Integer::parseInt(red_s, 16)
var String green_s = RGB.charAt(2).toString + RGB.charAt(3).toString
var Number green = Integer::parseInt(green_s, 16)
var String blue_s = RGB.charAt(4).toString + RGB.charAt(5).toString
var Number blue = Integer::parseInt(blue_s, 16)
val List<Float> hsb = Color.RGBtoHSB(red.intValue, green.intValue, blue.intValue, null)
var float hue = hsb.get(0)
hue *= 360
var float sat = hsb.get(1)
sat *= 100
var float bri = hsb.get(2)
bri *= 100
val String hsbString = hue + "," + sat + "," + bri
var HSBType HSB = new HSBType(hsbString)
cBedroom_Lamp.postUpdate(HSB)
var String ww_s = RGB.charAt(8).toString + RGB.charAt(9).toString
var Number ww = Integer::parseInt(ww_s, 16)
var String cc_s = RGB.charAt(6).toString + RGB.charAt(7).toString
var Number cc = Integer::parseInt(cc_s, 16)
var Number ct
if (ww == 0 && cc == 0) {
ct = 50
} else if (ww == 0) {
ct = 0
} else if (cc == 0) {
ct = 100
} else {
ct = ww / (ww + cc) * 100
}
ctBedroom_Lamp.postUpdate(ct)
end
rule "Bedroom Lamp Colour Output"
when
Item cBedroom_Lamp received command
then
if (receivedCommand instanceof HSBType) {
var red_n = receivedCommand.red * 2.55
var green_n = receivedCommand.green * 2.55
var blue_n = receivedCommand.blue * 2.55
var String hex = Integer::toHexString(red_n.intValue)
if (hex.length < 2) hex = "0" + hex
var String output = hex
hex = Integer::toHexString(green_n.intValue)
if (hex.length < 2) hex = "0" + hex
output = output + hex
hex = Integer::toHexString(blue_n.intValue)
if (hex.length < 2) hex = "0" + hex
output = output + hex
var String whites = mqBR_Lamp_Colour.state.toString
var String whitelevels
try {
whitelevels = whites.charAt(6).toString + whites.charAt(7).toString + whites.charAt(8).toString + whites.charAt(9).toString
} catch(Throwable t) {
whitelevels = "0000"
}
logInfo("BRColour","BR Colour: " + output + whitelevels)
mqBR_Lamp_Colour.sendCommand(output + whitelevels)
}
else if (receivedCommand == ON){
sBedroom_Lamp.sendCommand(ON)
}
else if (receivedCommand == OFF){
sBedroom_Lamp.sendCommand(OFF)
}
end
rule "Bedroom Colour Temperature"
when
Item ctBedroom_Lamp received command
then
val Number ctValue = (receivedCommand as Number * 3.47) + 153
publish("MQTT","cmnd/light1/CT",ctValue.intValue.toString)
end
Here we see the engine room of the integration. The “Colour Return” rule parses the string read from the MQTT status reports and feeds it back into the HSBType item representing colour and the PercentType item representing colour temperature.
The “Colour Output” rule takes the colour commands from the colourpicker and converts them into RGBCW strings for the bulb.
Finally the “Colour Temperature” rule just translates the PercentType command from the Dimmer widget into a CT value that the bulb understands.
The bulb is quite smart with the way it responds to the various commands. Of course if you send OFF and ON it will resume at the same colour and brightness it was at, but you can also send Dimmer commands and it will scale up or down both the colour LEDs and the white LEDs by the same amount.
You can also independently control the colour and white LEDs using either the colourpicker or the colour temperature slider.
You could also
publish("MQTT","cmnd/light1/Color", <Your String Here>)
to control the colour totally manually. (eg. “FF00C17F7F”)
Sitemaps:
Switch item=sBedroom_Lamp label="Lamp [%s]"
Slider item=dBedroom_Lamp label="Dimmer [%d]"
Slider item=ctBedroom_Lamp label="Colour Temp [%.1f]"
Colorpicker item=cBedroom_Lamp label="Lamp Colour [%s]"
Straightforward. Just remember to tap on the colourpicker rather than dragging your finger around, otherwise it tends to spam MQTT messages and things can get overwhelmed.
Some other useful commands exist which I will look to integrate soon, such as automatic fading of configurable speed, wake up fading, etc.
Overall, a pretty great set of features in an open and accessible framework and at a very low price. A+