jezs00 / pycasso

A system to send AI generated art to an E-Paper display through a Raspberry PI unit
MIT License
74 stars 6 forks source link

Feature Request: Battery level #4

Closed jezs00 closed 1 year ago

jezs00 commented 1 year ago

Option to show battery level faintly on screen

Could be represented by numerals or bars

recrudesce commented 1 year ago

ok, I've worked out how to do this. You could probably clean up the python a little.

Anyway, download some icons from FlatIcons, I used the battery icons from https://www.flaticon.com/packs/miscellaneous-11 and place them in ~/pycasso/images/icons folder

in your pijuice_handler.py file, pass the charge_level back to the instance - i did this in the low battery icon try block, just before the instance.run() call.

        try:
            # Set icon if PiJuice has lower battery
            if charge_level < charge_display:
                logging.info("Displaying icon due to low battery")
                instance.icon_shape = DisplayShapeConst.SQUARE.value

            instance.charge_level = charge_level

            instance.run()

in pycasso.py, add the following function

    @staticmethod
    def add_battery_status(draw, battery_percent, width, height):

        empty = range(0,20)
        low = range(21,40)
        half = range(41-60)
        good = range(61-80)

        if battery_percent in empty:
            battery_icon = 'empty-battery.png'
        elif battery_percent in low:
            battery_icon = 'low-battery.png'
        elif battery_percent in half:
            battery_icon = 'half-battery.png'
        elif battery_percent in good:
            battery_icon = 'battery.png'
        else: #battery percent full
            battery_icon = 'full-battery.png'

        battery_status = Image.open('images/icons/' + battery_icon)
        battery_status = battery_status.convert("RGBA")
        draw.paste(battery_status, (width-66, height-66), battery_status)
        return draw

then just before you draw the status shape, but after the image crop, you need to call the function to add the battery icon


            # Crop and prepare image
            image_base = image_base.crop(image_crop)
            draw = ImageDraw.Draw(image_base, "RGBA")

            logging.info(self.charge_level)
            # Draw battery status
            if self.charge_level is not None:
                logging.info("Putting battery icon on")
                draw = self.add_battery_status(image_base, numpy.ceil(self.charge_level), epd.width, epd.height)

            # Draw status shape if provided
            if self.icon_shape is not None:
                draw = ImageFunctions.add_status_icon(draw, self.icon_shape, self.config.icon_padding,
                                                      self.config.icon_size, self.config.icon_width,
                                                      self.config.icon_opacity)

This then results in a battery icon in the bottom corner of the image image

Now the battery status will be added to the image every time it's created. There are 5 states - 100-81%, 80-61%, 60-41%, 40-21%, and 20-0%.

jezs00 commented 1 year ago

Great idea! Looks very good on the screen too. I can see about implementing this on the weekend, but feel free to make a branch and commit your code. I'm not sure about github permissions, would you like me to add you as a collaborator?

TODO- Python looks fine but I think we should initialize charge_level in pycasso init as None just so that the variable itself exists no matter what.

Alongside implementing this I will config out and add logic for the following: Show/hide battery icon Battery icon location (bottom right may not work with people adding text on the bottom of the screen) Opacity (will need to look into pillows ability to add an image with opacity, but I'm almost certain this will be possible)

The directory structure in images is intended to be the default but optional place for images to be generated and loaded from, just thinking about it I might prefer to restructure the folders a little and place fonts and icons in a 'resources' directory to keep working folders and constant resources separate. Not 100% on that, what are your thoughts?

And a reminder to myself to write a unit test or two for this function.

On Fri, 20 Jan 2023, 8:01 am recrudesce, @.***> wrote:

ok, I've worked out how to do this. You could probably clean up the python a little.

Anyway, download some icons from FlatIcons, I used the battery icons from https://www.flaticon.com/packs/miscellaneous-11 and place them in ~/pycasso/images/icons folder

in your pijuice_handler.py file, pass the charge_level back to the instance - i did this in the low battery icon try block, just before the instance.run() call.

    try:
        # Set icon if PiJuice has lower battery
        if charge_level < charge_display:
            logging.info("Displaying icon due to low battery")
            instance.icon_shape = DisplayShapeConst.SQUARE.value

        instance.charge_level = charge_level

        instance.run()

in pycasso.py, add the following function

@staticmethod
def add_battery_status(draw, battery_percent, width, height):

    empty = range(0,20)
    low = range(20,40)
    half = range(40-60)
    good = range(60-80)

    if battery_percent in empty:
        battery_icon = 'empty-battery.png'
    elif battery_percent in low:
        battery_icon = 'low-battery.png'
    elif battery_percent in half:
        battery_icon = 'half-battery.png'
    elif battery_percent in good:
        battery_icon = 'battery.png'
    else: #battery percent full
        battery_icon = 'full-battery.png'

    battery_status = Image.open('images/icons/' + battery_icon)
    battery_status = battery_status.convert("RGBA")
    draw.paste(battery_status, (width-66, height-66), battery_status)
    return draw

then just before you draw the status shape, but after the image crop, you need to call the function to add the battery icon

        # Crop and prepare image
        image_base = image_base.crop(image_crop)
        draw = ImageDraw.Draw(image_base, "RGBA")

        logging.info(self.charge_level)
        # Draw battery status
        if self.charge_level is not None:
            logging.info("Putting battery icon on")
            draw = self.add_battery_status(image_base, self.charge_level, epd.width, epd.height)

        # Draw status shape if provided
        if self.icon_shape is not None:
            draw = ImageFunctions.add_status_icon(draw, self.icon_shape, self.config.icon_padding,
                                                  self.config.icon_size, self.config.icon_width,
                                                  self.config.icon_opacity)

This then results in a battery icon in the bottom corner of the image [image: image] https://user-images.githubusercontent.com/6450799/213558646-c6699e65-31f9-4b47-aedc-3ff272c23abb.png

— Reply to this email directly, view it on GitHub https://github.com/jezs00/pycasso/issues/4#issuecomment-1397606236, or unsubscribe https://github.com/notifications/unsubscribe-auth/AUTEK7BBFNAVSX24NSLW3OTWTGTTTANCNFSM6AAAAAASBWAVNA . You are receiving this because you authored the thread.Message ID: @.***>

jezs00 commented 1 year ago

Flaticon is good but I think I might use some icons from this repo just because the license matches (MIT). Easier for attribution and distribution.

https://github.com/tabler/tabler-icons

jezs00 commented 1 year ago

A fun idea might be to get each provider to dream up its own icon. I've tried a little and honestly am not getting very good results. Might give them placeholders and update later on.

jezs00 commented 1 year ago

With images fully filling frame, always using a black image or a white image might cause problems depending on the brightness of the image.

Look into this to calculate average brightness and pick black or white accordingly: https://stackoverflow.com/questions/3490727/what-are-some-methods-to-analyze-image-brightness-using-python