Using Lua scripts (Part 07): Alarm colors and complex if statements - brndnmtthws/conky GitHub Wiki

vii: Alarm colors and complex if statements

We were jazzing up our bar meter. We added an optional border as feature 1. For feature 2 we will have the bar change color.

To get the color change we I'll need to add a few more settings! Most likely if you are going to set an alarm color, you'll think of red (as I did) so we would have to re-color our background bar also (which is also currently red) I'm feeling a little lazy so I'm going to go for some shorter string names, particularly for all the reds greens blues and alphas coming up :).

-- Set alarm value. This is the value at which bar color will change.
alarm_value = 80

-- Set alarm bar color, 1, 0, 0, 1 = red fully opaque.
ar, ag, ab, aa = 1, 0, 0, 1

We already have a base bar color. We want the bar to be that color unless the cpu% reading equals or goes above 80%.

We are going to be using another IF to get the colors to change. As with most code there are multiple ways we could go about doing things. Lets first remind ourselves of the code that is drawing the indicator part of the bar. It is that part that we will be editing as it is that part which will change color.

-- Set indicator color.
cairo_set_source_rgba (cr, bar_in_red, bar_in_green, bar_in_blue, bar_in_alpha)
scale = bar_height / bar_max_value
indicator_height = scale * bar_value
cairo_rectangle (cr, bar_bottom_left_x, bar_bottom_left_y, bar_width,
		-indicator_height)
cairo_fill (cr)

To apply our if statement to colors we could do the following (remember, bar_value is the name of the string holds the value of cpu% and we set alarm_value above to 80):

if bar_value < alarm_value then
    cairo_set_source_rgba (cr, bar_in_red, bar_in_green, bar_in_blue,
			bar_in_alpha)
else
    cairo_set_source_rgba (cr, ar, ag, ab, aa)
end

If bar_value is less than alarm_value, then we set the color to the base_indicator_color. If not, we set it to the alarm color.

This would have also worked:

if bar_value >= 80 then
    cairo_set_source_rgba (cr, ar, ag, ab, aa)
else
    cairo_set_source_rgba (cr, bar_in_red, bar_in_green, bar_in_blue,
			bar_in_alpha)
end

How do we know its working?

We think that we have our code right and we expect that if our cpu% gets to 80% or more that our bar color will change from white to red, but its always a good idea to check that things are working the way we expect.

We could do something on the computer that would drive the actual CPU% reading up to 80 or above but there is an easier way. In our settings we have the line that sets the value of bar_value, bar_value = tonumber (conky_parse ("${cpu}")).

Just edit that line and "hard code" bar_value to a test value like this bar_value = 80 -- tonumber (conky_parse ("${cpu}")).

I don't like to completely replace the line with our test value as it simply harder to reinstate the line afterwards. With the test value in place and the rest of the line commented out, once we are sure our feature is working we just delete the test value and the comments and everything is back to being operational.

Now, we like the color change, and we want to implement another. We want the bar to be, say green up to 50% and yellow between 50% and 80%.

So, back to the settings. We already have our alarm (or high cpu usage) value and color.

-- Set value for first color change, low cpu usage to mid cpu usage.
mid_value = 50

-- Set "low" cpu usage color and alpha, ie bar color below 50% - 0, 1, 0, 1 =.
-- 		fully opaque green.
lr, lg, lb, la = 0, 1, 0, 1

-- Set "mid" cpu usage color, between 50 and 79 - 1, 1, 0, 1 = fully opaque.
-- 		yellow.
mr, mg, mb, ma = 1, 1, 0, 1

While we could reuse our base bar color settings and just change the numbers to green or yellow, like:

bar_in_red = 1
bar_in_green = 1
bar_in_blue = 1
bar_in_alpha = 1

But since we are making some significant changes to how our colors are working I would just go ahead and delete them and replace them with the new low mid and alarm values. I tend to like to stick to a single naming convention because it helps me to remember what I have named strings (and maybe also because of some mild OCD), but again, that's just me, you can call your string whatever you want to!

So now we need to think about how to set up our if statement. When CPU is between 0 and 49 we want green; when CPU is between 50 and 79 we want yellow; when CPU is 80 or above we want red.

So lets put them into a statement

if bar_value >= mid_value then -- ie if value is greater or equal to 50
    cairo_set_source_rgba (cr, mr, mg, mb, ma) -- Yellow (mid color).
elseif bar_value >= alarm_value then -- ie if bar_value is greater or equal to 80
    cairo_set_source_rgba (cr, ar, ag, ab, aa) -- Red (alarm color).
else
    cairo_set_source_rgba (cr, lr, lg, lb, la) -- Green (low color).
end

We use an elseif, because it is no longer an either or situation -- there are 3 possibilities we need to sort out.

Test the setup by setting bar_value to some test value. We set:

bar_value = 49 and we get a green bar, and it is green for any number below 50 we set. bar_value = 50 and we get a yellow bar. Then try. bar_value = 80 and the bar is still yellow! and it is yellow all the way up to 100.

Our statement seems entirely logical, but this is one of the pitfalls you can get stuck in to understand it we need to think about how our if statement works and we can see that the problem is in the order of our comparisons.

if bar_value >= mid_value then -- ie if value is greater or equal to 50.
    cairo_set_source_rgba (cr, mr, mg, mb, ma)-- yellow (mid color)

This first line does indeed match any number from 50 to 100 and so any cpu value from 50 to 100 will result in a yellow bar.

The script comes to the line, takes the value of bar_value calculates if it is greater or equal to the value of mid_value if it passes the comparison, the script runs the corresponding code and then its done with the if statement.

Only if bar_value is less than 50 then the first comparison will fail and the script will move on to the next comparison. But of course this comparison will fail also as if a value is not greater or equal to 50 then it wont be greater or equal to 80.

Once past the if and the following elseif the script automatically runs the code following else which doesn't require a comparison. Again there are plenty of ways we can fix this we can try and reorder our comparisons like so:

if bar_value >= alarm_value then -- ie if value is greater or equal to 80
    cairo_set_source_rgba (cr, ar, ag, ab, aa)-- Red (alarm color).
elseif bar_value >= mid_value then -- ie if bar_value is greater or equal to 50
    cairo_set_source_rgba (cr, mr, mg, mb, ma)-- Yellow (mid color).
else
    cairo_set_source_rgba (cr, lr, lg, lb, la)-- Green (low color).
end

Take a value of say 90. Check 1: is 90 greater or equal to 80? Yes? Pass the first comparison and run the code to set color to red. Done!

Set a value of 60. Check 1: is 60 greater or equal to 80? No? fail the first comparison, move onto the next. Check 2: is 60 greater or equal to 50? Yes? Pass the second comparison and run the code to set color to yellow. Done!

Set a value of 48. Check 1: is 48 greater or equal to 80? No? Fail the first comparison, move onto the next. Check 2: is 48 greater or equal to 50? No? Fail the second comparison, move onto the next. No more checks, run code following else and set color to green. Done!