[SOLVED] Keep lights below certain threshold

Ok here is today’s latest and greatest script by me the noob :slight_smile:

import appdaemon.appapi as appapi

class keep_light_below(appapi.AppDaemon):

  def initialize(self):

    self.listen_state(self.adjust_light_function,(self.args["lightID"]))

# Found this cool function to convert the brightness to a percentage because well thats easier than doing math
  def brightness_to_percent(self, brightness):
      return 255/100 * int(brightness)

  def adjust_light_function(self, entity, attribute, old, new, kwargs):
      bright_level = self.get_state(self.args["lightID"], "brightness")
      self.log(bright_level)
      bright_level_percent = self.brightness_to_percent(bright_level)
      self.log(bright_level_percent)
      if bright_level_percent > 90:
          brightness90 = self.brightness_to_percent(90)
          self.turn_on(self.args["lightID"], brightness=brightness90)

All I’m trying to do with this is keep a certain light below 90% on the dimmer. If it goes above this the lights flicker. But as long as I keep them at 90 or lower then we’re all good.

Problem is with my math I do believe. I figured I could use that brightness_to_percent to get the value that is being returned to HA and then convert that value into a percentage. Then I could take that value and compare it that if its above 90 then we can act on it otherwise just do nothing. I thought I had this one, I was so sure of it but no luck here. Its like its reading the 90 as the level from HA not the converted to a percentage value.

light/turn_on has a brightness_pct you can use.

1 Like

so are you saying instead of

self.turn_on

use

light.turn_on(entity_id,brightness_pct)?

the problem is probably that your cool function returns a float
and i think that the brightness needs to be an int.

that could be helped by changing this:

      return 255/100 * int(brightness)

to this:

      return int(round(255/100 * int(brightness)))

that way you alway get a rounded INT back

1 Like

I didn’t even think about that being an issue. And I’m sure you’re 100% right since we sometimes get back a number with a decimal in it. Ah see it was my math skills :slight_smile:

1 Like

Hmm still having some math issues here

So its returning back these as the percentage

2018-03-07 17:51:01.682042 INFO basement_wall_lights: 576
2018-03-07 17:51:01.883046 INFO basement_wall_lights: 584

So my math is still screwed up somewhere.

lol. i didnt even look at the formula :wink:

how about:

 return int(round((int(brightness)/255)*100))

if brightness is between 0 and 255 that will return a number between 0 and 100

I kept second guessing myself on the formula I’m like “yeah thats right” then “no you need to do this” then “yeah” sigh

1 Like

Ok and here is the final product

import appdaemon.appapi as appapi

class keep_light_below(appapi.AppDaemon):

  def initialize(self):

    self.listen_state(self.adjust_light_function,(self.args["lightID"]))

# Found this cool function to convert the brightness to a percentage because well thats easier than doing math
  def percent_to_brightness(self, brightness):
      return int(round((int(brightness)/255)*100))

  def brightness_to_percent(self, brightness):
      return 255/100 * int(brightness)

  def adjust_light_function(self, entity, attribute, old, new, kwargs):
      bright_level = self.get_state(self.args["lightID"], "brightness")
      bright_level_percent = self.percent_to_brightness(bright_level)
      self.log(bright_level_percent)
      if bright_level_percent > 90:
          brightness90 = self.brightness_to_percent(90)
          self.turn_on(self.args["lightID"], brightness=brightness90)

I need to add some logic that if the state changes to off to just exit out instead of freaking out because the brightness is null but not a big deal right now

I also had to rename the reverse math function and then add back in the other one but we’re in business now.

1 Like

int(round((int(brightness)/255)*100)) is redundant, (int(brightness)/255)*100 should be fine. int(round( isn’t required. When performing math in python without a decimal point will treat the number as integers. Example:

355/100 will return 3

355.0/100 will return 3.55

Just food for thought

not true.

355/100 will return a float.

i just checked if i am not wrong, but
self.log(355/100)
return 3.55

brightness can be a string, so you need the int there
int(brightness)/255*100 can be with a decimal so you need to round.
the int is needed to make it an integer again.

355/100 will return 3.55
int(355/100) will return 3
int(round(355/100)) will return 4

My mistake, that was changed after python 2.5 related to

355//100 returns 3

355/100 now returns 3.55

so:

int(brightness)//255*100 should work just fine

no still not.
he wants a threshold from 90.
with your formula he got a threshold from 91, because 90.99 would still return 90

That translates to a max difference of 1/255 pot value… and you could just use >=…

wrong again.
231 and 232 both return 90% in your formula where they return 91% in my formula

so your threshold would be at 232, where mine would be at 230
and yeah, its not needed to calculate at all, but that not the point.

Did you read my reply are are you trying to prove a point? I said use >=? How does that not solve that? A threshold is a number. A number can be greater than or greater than or equal to.

but you are still wrong.
your formula would return the same threshold for 230, 231 and 232
so after the calculation you cant make a difference anymore.

you started with saying that it is redundant.
and thats just not true.

the 2 formulas are different and have different results and the results need to be observed different.

i can create 1000 different formulas, with all another result, but the point was to get the closest brightness int that comes to 90 (or any other % if you like)

just compare the outcomes from the 2 formulas

brightness  myfm yourfm
228           89     89
229           90     89
230           90     90
231           91     90
232           91     90

you can never create the same outcome from that.
doesnt matter which you use > or >= the result will be different.

like i said, the easiest way and the most accurate way would be to not use the formula and just use the brightness itselve as threshold, but that was not the point from this formula.

Again: That’s where the 1/255 difference comes into play. Because 0.5% error is equivalent to 1 pot value:

0.5/100 = 0.005
0.005*255 = 1.275.

the .275 will always be truncated because of the integer translation.

I’m starting to suspect that you aren’t reading my responses and you are just trying to get an argument ‘win’, because I gave you the 1/255 error 2 responses ago.

i got the feeling that its you who want to win an argument, with in my eyes wrong statements.

no matter what you try to say, your formula return 90 for 90.99 and 89 for 89.99

you can never truncate when you want to round (there is an obvious reason why there are commands created for both)

to take your own example back.
355/100 will return 3.55
int(355/100) will return 3
355//100 will return 3
int(round(355/100)) will return 4

so there is no way that you can defend saying that round in redundant in this.
redundant means you get the same endresult.

so, is 89.5 >= 90?