Visualize weather forecast with RGB color lamp

Hey everyone,

I built an indirect weather forecast signalling and thought some of you may like this. Basically it reads the weather forecast and then changes the color of a color light.

I’ve set this up in my bathroom whenever I enter it in the morning, the color lamp shows me a basic weather forecast for one minute and then changes back to a more “usable” light.

Required:

  • OH 2.x
  • A RGBW / color lamp (it’s way nicer if it also supports (warm) white
  • A configured weather plugin that provides a String item for the forecast (I’m using weatherunderground)

In this example, LampColor is the RGB part of the lamp, while LampDimmer controls the W warm-white part.

rule "Weather Forecast Light"
when
    // Your method of activating the light, I'm using presence detection
    Item BathroomPresence changed to ON
then
    // Change regular warm white light to a low setting
    LampDimmer.sendCommand(20)
    // Check if the WeatherForecast Item String contains key words to decide the color
    if (WeatherForecast.state.toString.contains("Rain") ||  WeatherForecast.state.toString.contains("Sleet")) {
	LampColor.sendCommand("240,100,100") //blue
    }
    else if (WeatherForecast.state.toString.contains("Sun") ||  WeatherForecast.state.toString.contains("Clear")) {
	LampColor.sendCommand("60,100,100") //yellow
    }
    else if (WeatherForecast.state.toString.contains("Cloud")) {
	LampColor.sendCommand("120,100,100") //green
    }
    else if (WeatherForecast.state.toString.contains("Snow")) {
	LampColor.sendCommand("0,0,100") //white
    }
    else if (WeatherForecast.state.toString.contains("Overcast") ||  WeatherForecast.state.toString.contains("storm") ||  WeatherForecast.state.toString.contains("Fog") ||  Weather_Today.state.toString.contains("Haze")) {
	LampColor.sendCommand("0,0,60") //grey
    }
    else {
    	LampDimmer.sendCommand(70)
    }
	
    // wait two minutes
    createTimer(now.plusMinutes(2), [|
    LampColor.sendCommand("0,0,0") // Turn of color
    LampDimmer.sendCommand(70) // Turn on regular warm white light
    ])

end
3 Likes

Excellent tutorial. Thanks for posting!

I can see all sorts of ways to expand this (e.g. a couple of flashes for thunderstorm).

For me, the temperature is as important if not more so than whether it will rain or snow. You could represent that by using blues, yellows, and reds and transition from the appropriate color for the forecast temp for each hour (not sure if the Wunderground API provides hourly forecasts in its API calls, I’d have to check).

There is one big thing though which should be changed. Thread::sleeps of more than a few hundred milliseconds are a very bad idea. If you have more thread sleeps of this Rule can potentially be triggered more than once in that two minute time frame it is possible to run out of rule execution threads and ALL of your Rules will come to a hault for up to two minutes.

Instead use

createTimer(now.plusMinutes(2), [|
    LampColor.sendCommand("0,0,0")
    LampDimmer.sendCommand(70)
]

A few other comments that are advice that will help potential problems in general, not necessarily this Rule:

  • Always use the method on the Item instead of the actions to sendCommand or postUpdate (see my example code above). postUpdate is less effecient because it can only accept a String for the state and therefore it has to, using the last line of the Rule as an example, convert the Number 70 to the String “70”, pass the “70” to the Dimmer Item, parse the String “70” back to the Number 70, and finally set the Dimmer’s state. Often, particularly when dealing with Numbers, this conversion back and forth fails. When you use the methods you can pass the Number 70 directly to the Item and all it has to do is set the Dimmer’s state.

  • I’m not sure this adds anything but I’ll recommend it anyway. One thing you can do is create a .map file that maps ALL of the potential forecast states to the HSV color String. Then in your Rule you would just have to replace the if else if stuff with:

    LampColor.sendCommand(transform(“MAP”, “weatherColors.map”, WeatherForecast.state.toString)

  • I’m assuming that LampColor and LampDimmer are the same light bulb. If that is the case, you don’t need LampDimmer at all as Color Items can receive PercentType commands. so LampDimmer.sendCommand(20) can become LampColor.sendCommand(20) or if that doesn’t work LampColor.sendCommand(new PercentType(20)) which will let you eliminate the LampDimmer Item entirely.

Great posting, I’m already getting some ideas. I may get a color light bulb after all.

2 Likes

Thanks for the feedback!

I’ll update the post above with your recommendations, learned a bit through this.

I feel a MAP is a bit of overkill for this, so I’m not going to change it.

As I have an RGBW lamp, it makes sense to differentiate between the dimmer and the color in this example. If there is only an RGB light, your recommendation is valid!

Cheers
David

I don’t understand. Why does it make sense? You can send dimmer commands to a Color Item. You can treat a Color Item as if it were a Dimmer. I’m pretty sure in your Rules you can actually cast a ColorItem to a DimmerItem. For all intents and purposes, a ColorItem IS a DimmerItem. And the Binding itself is supposed to handle the differences with RGB verses HSB versus RGBW, versus HSV, etc.

You can still have the same ColorItem and differentiate it on your sitemap if that is your concern. Just use

Slider item=LampColor

and you can control the brightness separately as if it were just a Dimmer.

So why do you need a separate Item to differentiate them. Are you controlling something other than brightness with the LampDimmer? If so, you should change the name of the Item to reflect what you are actually changing when you command that Item.

Perhaps I still don’t understand.

Translating runtime-logic (if-else) into configuration (map) is always brilliant. This is always correct in my opinion. :wink:

It’s also much better for customization and localization.

The LampDimmer controls only the W of the RGBW lamp. The W white is much nicer to the eye than a combination of the RGB.

Does that make sense?

What you say makes sense, but either I’m missing some information or I’m still convinced that you don’t need a separate dimmer Item.

If the binding is implemented correctly, when you send a brightness command to a ColorItem it should adjust the W channel of the bulb. In short, there is no difference between creating a separate Dimmer Item or sending a Dimmer command to a Color Item.