Battery Charting Script

Posted on
Thu Apr 14, 2016 10:22 am
DaveL17 offline
User avatar
Posts: 6755
Joined: Aug 20, 2013
Location: Chicago, IL, USA

Re: Battery Charting Script

matt (support) wrote:
Great script!

Thanks Matt!

I came here to drink milk and kick ass....and I've just finished my milk.

[My Plugins] - [My Forums]

Posted on
Thu Apr 14, 2016 10:27 am
DaveL17 offline
User avatar
Posts: 6755
Joined: Aug 20, 2013
Location: Chicago, IL, USA

Re: Battery Charting Script

Different Computers wrote:
This is pretty amazing work.

Do I have this right that I can just schedule Indigo to run this script in the middle of the night and it's done? Nothing else to install on a Mac running El Capitan?

Thanks for the kind words.

Yes; that's what I do. I run it only once per day because I figure that battery levels aren't changing that much each day. I combine it with another script that emails me a list of only those devices that fall below a set percentage which helps me remember to keep after replacing batteries.

The best way to tell whether you can run the script natively (I recommend using a linked script rather than embedding it) is to open an Indigo scripting shell from the plugins menu and trying to import the two key modules. If you can do this without throwing errors, then you should be fine. It will likely take some tweaking of the settings to work best for each install--number of devices, etc. I might add that I think its best to do this from the Indigo shell because a basic Terminal shell might use different paths depending on your setup.

Code: Select all
import matplotlib
import numpy


Dave

I came here to drink milk and kick ass....and I've just finished my milk.

[My Plugins] - [My Forums]

Posted on
Thu Apr 14, 2016 11:08 am
Different Computers offline
User avatar
Posts: 2544
Joined: Jan 02, 2016
Location: East Coast

Re: Battery Charting Script

OK, that was freakin' amazing.

Never run a python script in my life before.
Tested matplotlib & numpy per your instructions, no problem.
copied script into pico, wrote it out as a .py file.
Pointed Indigo at it, ran it as a test.
Opened a control page, scrolled through the static images and THERE IT IS. Found all my battery devices perfectly. Tremendous. Thank you very much.

SmartThings refugee, so happy to be on Indigo. Monterey on a base M1 Mini w/Harmony Hub, Hue, DomoPad, Dynamic URL, Device Extensions, HomeKitLink, Grafana, Plex, uniFAP, Fantastic Weather, Nanoleaf, LED Simple Effects, Bond Home, Camect.

Posted on
Thu Apr 14, 2016 11:13 am
DaveL17 offline
User avatar
Posts: 6755
Joined: Aug 20, 2013
Location: Chicago, IL, USA

Re: Battery Charting Script

Just wait. Once you get started with this stuff, you won't be able to stop.

The power is intoxicating....


Sent from my iPhone using Tapatalk

I came here to drink milk and kick ass....and I've just finished my milk.

[My Plugins] - [My Forums]

Posted on
Thu Apr 14, 2016 11:15 am
Different Computers offline
User avatar
Posts: 2544
Joined: Jan 02, 2016
Location: East Coast

Re: Battery Charting Script

I'm sure.

But I'm still very much a copypasta, and a long long way away from trying to write any python myself. AppleScript, on the other hand...

Nah, there are a bunch of great ApplesScripts out there, it will be months before I'm doing more than copy/pasting those too.

SmartThings refugee, so happy to be on Indigo. Monterey on a base M1 Mini w/Harmony Hub, Hue, DomoPad, Dynamic URL, Device Extensions, HomeKitLink, Grafana, Plex, uniFAP, Fantastic Weather, Nanoleaf, LED Simple Effects, Bond Home, Camect.

Posted on
Thu Apr 14, 2016 12:29 pm
jay (support) offline
Site Admin
User avatar
Posts: 18220
Joined: Mar 19, 2008
Location: Austin, Texas

Re: Battery Charting Script

Bite the bullet and learn Python (once you get ready to start writing scripts rather than copy/pasting). It's not hard, and it's MUCH better in almost every respect than AppleScript.

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Fri Apr 15, 2016 9:26 am
stuartcolman offline
Posts: 81
Joined: Nov 01, 2015
Location: Essex, United Kingdom

Re: Battery Charting Script

Hi,

I have setup the script to run once an hour, however I am just getting a blank chart. Furthermore I am getting the following error in the event log:

Code: Select all
Error parsing chart data: empty string for float()


I am also using the piBeacons plugin which appears to register the beacon devices with a battery, however these devices don't have a battery level, not even 0%. Is there a way to exclude devices based on their ID from being counted in this script?

Thanks

Stuart

Posted on
Fri Apr 15, 2016 11:32 am
DaveL17 offline
User avatar
Posts: 6755
Joined: Aug 20, 2013
Location: Chicago, IL, USA

Re: Battery Charting Script

This should be a pretty easy fix. Does it give you a line number with the error?


Sent from my iPhone using Tapatalk

I came here to drink milk and kick ass....and I've just finished my milk.

[My Plugins] - [My Forums]

Posted on
Fri Apr 15, 2016 11:39 am
stuartcolman offline
Posts: 81
Joined: Nov 01, 2015
Location: Essex, United Kingdom

Re: Battery Charting Script

No unfortunately not. The line is 'as is' from the event log.


Sent from my iPhone using Tapatalk

Posted on
Fri Apr 15, 2016 11:56 am
DaveL17 offline
User avatar
Posts: 6755
Joined: Aug 20, 2013
Location: Chicago, IL, USA

Re: Battery Charting Script

Thanks. That's a result of inferior code writing.


Sent from my iPhone using Tapatalk

I came here to drink milk and kick ass....and I've just finished my milk.

[My Plugins] - [My Forums]

Posted on
Fri Apr 15, 2016 12:10 pm
DaveL17 offline
User avatar
Posts: 6755
Joined: Aug 20, 2013
Location: Chicago, IL, USA

Re: Battery Charting Script

I have posted a new version of the script which coerces a battery level of zero for those devices that report a battery level as an empty string. This is a short-term fix.

For those that have devices that will always report as an empty string -- and thus you don't want them to appear on the chart -- look for the block of code that looks like this:
Code: Select all
    for dev in indigo.devices.itervalues():
        if dev.batteryLevel is not None:
            device_dict[dev.name] = dev.states['batteryLevel']

and change it to this:
Code: Select all
    for dev in indigo.devices.itervalues():
        if dev.batteryLevel is not None and dev.batteryLevel is not "":
            device_dict[dev.name] = dev.states['batteryLevel']

and see if that works to your liking. I can't test the code as I don't have devices that meet the criteria. Also, I'm hesitant to add this to the "official" script until we get a sense of the consequences for the change (some folks may want these devices reflected...)

Cheers,
Dave

I came here to drink milk and kick ass....and I've just finished my milk.

[My Plugins] - [My Forums]

Posted on
Fri Apr 15, 2016 12:12 pm
stuartcolman offline
Posts: 81
Joined: Nov 01, 2015
Location: Essex, United Kingdom

Re: Battery Charting Script

Thanks for the quick response. I'll give it a try and feedback.


Sent from my iPhone using Tapatalk

Posted on
Fri Apr 15, 2016 1:24 pm
stuartcolman offline
Posts: 81
Joined: Nov 01, 2015
Location: Essex, United Kingdom

Re: Battery Charting Script

Hi,

Code changed and still get the same result.

Stuart

Posted on
Fri Apr 15, 2016 2:30 pm
DaveL17 offline
User avatar
Posts: 6755
Joined: Aug 20, 2013
Location: Chicago, IL, USA

Re: Battery Charting Script

Hi Stuart - I'm just trying to understand what you're seeing--did you change to the code that's listed in the first post to this thread?


Sent from my iPhone using Tapatalk

I came here to drink milk and kick ass....and I've just finished my milk.

[My Plugins] - [My Forums]

Posted on
Fri Apr 15, 2016 4:03 pm
stuartcolman offline
Posts: 81
Joined: Nov 01, 2015
Location: Essex, United Kingdom

Re: Battery Charting Script

I used the original code from the very first post of the thread, and then made the changes you just mentioned:
Code: Select all
#! /usr/bin/env python2.6
# -*- coding: utf-8 -*-

try:
    import sys
    import matplotlib.pyplot as plt
    import numpy as np
except ImportError, e:
    sys.exit(u"The matplotlib and numpy modules are required to use this script.")

# =================== User Settings ===================
output_file = '/Library/Application Support/Perceptive Automation/Indigo 6/IndigoWebServer/images/controls/static/battery_test.png'

chart_title = 'Battery Health'
x_axis_title = ''
y_axis_title = ''

background_color = '#000000'
chart_height = 4.5
chart_width = 6
font_color = '#FFFFFF'
font_name = 'Lato Light'
font_size = 9
grid_color = '#888888'
grid_style = 'dotted'
show_data_labels = True
title_font_size = 9

battery_full_color = '#0000CC'
battery_caution_color = '#FFFF00'
battery_caution_level = 10
battery_low_color = '#FF0000'
battery_low_level = 5

# =================== kwarg Settings ===================
k_bar_fig = {'align': 'center',
             'alpha': 1.0,
             'height': 0.5,
             'zorder': 3
             }

k_grid_fig = {'which': 'major',
              'color': grid_color,
              'linestyle': grid_style,
              'zorder': 0
              }

k_plot_fig = {'bbox_extra_artists': None,
              'bbox_inches': 'tight',
              'dpi': 100,
              'edgecolor': background_color,
              'facecolor': background_color,
              'format': None,
              'frameon': None,
              'orientation': None,
              'pad_inches': 0.1,
              'papertype': None,
              'transparent': True,
              }

k_title_fig = {'fontname': font_name,
               'fontsize': title_font_size,
               'color': font_color,
               'position': (0.35, 1.0)
               }
# =====================================================

bar_colors = []
device_dict = {}
x_values = []
y_values = []

# Create a dict of battery powered devices and their battery levels
try:
    for dev in indigo.devices.itervalues():
        if dev.batteryLevel is not None and dev.batteryLevel is not "":
            device_dict[dev.name] = dev.states['batteryLevel']

    if device_dict == {}:
        device_dict['No Battery Devices'] = '0'

except Exception, e:
    indigo.server.log(u"Error reading battery devices: %s" % e)

# Parse the battery device dict into X and Y values
try:
    for key, value in sorted(device_dict.iteritems(), reverse=True):
        x_values.append(float(value))
        y_values.append(key.replace(' - ', '\n'))  # This line is specific to my install, as I name devices "Room - Device Name"

        # Create a list of colors for the bars based on battery health 
        battery_level = float(value)
        if battery_level <= battery_low_level:
            bar_colors.append(battery_low_color)
        elif battery_low_level < battery_level <= battery_caution_level:
            bar_colors.append(battery_caution_color)
        else:
            bar_colors.append(battery_full_color)
except Exception, e:
    indigo.server.log(u"Error parsing chart data: %s" % e)

# Create a list of values to plot on the Y axis, since we can't plot on device names.
y_axis = np.arange(len(y_values))

# Plot the figure
plt.figure(figsize=(chart_width, chart_height))
# Adding 1 to the y_axis pushes the bar to spot 1 instead of spot 0 -- getting it off the axis.
plt.barh((y_axis + 1), x_values, color=bar_colors, **k_bar_fig)

if show_data_labels:
    for ii in range(len(y_axis)):
        plt.annotate("%3d" % x_values[ii], xy=((x_values[ii] - 5), (y_axis[ii]) + 0.88), xycoords='data', textcoords='data', fontsize=font_size, color=font_color)

# Chart
plt.title(chart_title, **k_title_fig)
plt.grid(**k_grid_fig)

# X Axis
plt.xticks(fontsize=font_size, color=font_color)
plt.xlabel(x_axis_title, fontsize=font_size, color=font_color)
plt.gca().xaxis.grid(True)
plt.xlim(xmin=0, xmax=100)

# Y Axis
# The addition of 0.05 to the y_axis better centers the labels on the bars
# (for 2-line labels.) For 1 line labels, change 1.07 to 1.0.
plt.yticks((y_axis + 1.05), y_values, fontsize=font_size, color=font_color)
plt.ylabel(y_axis_title, fontsize=font_size, color=font_color)
plt.gca().yaxis.grid(False)
plt.ylim(ymin=0)

# Output the file
plt.savefig(output_file, **k_plot_fig)
plt.close()

Page 3 of 8 1, 2, 3, 4, 5, 6 ... 8

Who is online

Users browsing this forum: No registered users and 2 guests