Efergy Engage energy monitor

Posted on
Sat Apr 11, 2015 4:09 am
lochnesz offline
Posts: 370
Joined: Oct 01, 2014
Location: Stockholm, Sweden

Efergy Engage energy monitor

A python script to get energy monitor values from Efergy Engage http://efergy.com/
Thanks to autolog, DaveL17, RogueProeliator and kw123 for your help.
(I am not very good at python, so there is probably room for improvement.)

Code: Select all
#!/usr/bin/env python
#get energy monitor data from efergy engage http://www.efergy.com
#by lochnesz
#version 1.0
#create variables in indigo before running this script (use variable id's instead of names if you'd prefer):
#"efergy_dev1_age"
#"efergy_dev1_reading"
#"efergy_dev1_battery"
#"efergy_dev1_falseBattery"
#"efergy_dev1_mac"
#"efergy_dev1_last_reading_time"
#create variable "efergy_dev1_token" in indigo with correct token before running this script
#to get token: https://engage.efergy.com/mobile/get_token?username=*username*&password=*password*&device=*token_name*
#alternative api url (example): http://www.energyhive.com/mobile_proxy/getStatus?token=xxxxxxxxxx

import simplejson as json
import urllib2
import time
import datetime
timeout = 3

#import token value from indigo variable
token=indigo.variables["efergy_dev1_token"].value

#debug to indigo log
#localtime = time.asctime( time.localtime(time.time()) )
#indigo.server.log ("Efergy monitor collector script started: " + localtime)

#get data in json from api url
url1Returned = urllib2.urlopen('https://engage.efergy.com/mobile_proxy/getStatus?token=' + token)
url2Returned = urllib2.urlopen('https://engage.efergy.com/mobile_proxy/getInstant?token=' + token)

#format api returned data
data_getStatus = url1Returned.read()
data_getInstant = url2Returned.read()

#interpret json
dict1 = json.loads(data_getStatus)
dict2 = json.loads(data_getInstant)

#get json variables to python variables
battery=str(dict1['listOfMacs'][0]['listofchannels'][0]['type']['battery']) #battery level
falseBattery=str(dict1['listOfMacs'][0]['listofchannels'][0]['type']['falseBattery'])
last_reading_ts=float(dict2['last_reading_time']) #value of checked date and time in ticks
mac=str(dict1['listOfMacs'][0]['mac']) #device mac address
age=str(dict2['age']) #age of last reading in seconds
reading=str(round(float(dict2['reading']),1)) #round float value of reading to one decimal and convert to string

#convert last_reading_ts ticks to local time
last_reading_time = datetime.datetime.fromtimestamp(last_reading_ts/1000).strftime('%Y-%m-%d %H:%M:%S')

#update indigo variables
indigo.variable.updateValue("efergy_dev1_battery", value=battery)
indigo.variable.updateValue("efergy_dev1_falseBattery", value= falseBattery)
indigo.variable.updateValue("efergy_dev1_last_reading_time", value= last_reading_time)
indigo.variable.updateValue("efergy_dev1_mac", value= mac)
indigo.variable.updateValue("efergy_dev1_age", value= age)
indigo.variable.updateValue("efergy_dev1_reading", value= reading)

#debug to indigo log
#indigo.server.log ("Battery: " + battery)
#indigo.server.log ("False battery: " + falseBattery)
#indigo.server.log ("Device MAC: " + mac)
#indigo.server.log ("Reading age: " + age)
#indigo.server.log ("Reading value (watts): " + reading)
#indigo.server.log ("Time for reading (local time): " + last_reading_time)

#debug to indigo log
#localtime = time.asctime( time.localtime(time.time()) )
#indigo.server.log ("Efergy monitor collector script finished: " + localtime)

Posted on
Sat Apr 11, 2015 5:48 am
DaveL17 offline
User avatar
Posts: 6753
Joined: Aug 20, 2013
Location: Chicago, IL, USA

Re: Efergy Engage energy monitor

Looking good! Two suggestions you might try for your next version:

1) Run a test to see if the variables you need exist already and, if not, create them automatically (and set their default values..)

Code: Select all
if not ("variableName" in indigo.variables):
    indigo.variable.create("variableName", "defaultValue")
That way, your users don't have to create the variables on their own (an possibly do something wrong in the process.) This will also cover the situation where a variable is accidentally deleted later on. see: Create a New Indigo Variable, Change Its Value, and Delete It

2) Run a test to see if the required token variable has a proper value and if not send a message to the user to fix the problem:
Code: Select all
if indigo.variables["efergy_dev1_token"].value == "defaultValue" or not indigo.variables["efergy_dev1_token"].value:
   # do some things here to tell the user to fix the problem.
Also, it's often recommended to wrap your code in a "try block" to provide some safety in case something goes wrong.
Code: Select all
try:
    # This.
except:
    # This instead.

Good luck, and keep going!
Dave

(all code is untested but should be pretty close.)

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

[My Plugins] - [My Forums]

Posted on
Sat Apr 11, 2015 5:55 am
lochnesz offline
Posts: 370
Joined: Oct 01, 2014
Location: Stockholm, Sweden

Re: Efergy Engage energy monitor

Thanks Dave for really good suggestions! :D

Cheers!
Peter

Posted on
Sat Apr 11, 2015 2:13 pm
lochnesz offline
Posts: 370
Joined: Oct 01, 2014
Location: Stockholm, Sweden

Re: Efergy Engage energy monitor

A little update based on Dave's suggestions.
Also, new indigo variable names in this version.

Code: Select all
#!/usr/bin/env python
#get energy monitor data from efergy engage http://www.efergy.com
#by lochnesz
#version 1.1
#create variable "efergyDev1_token" in indigo with correct token before running this script
#to get token from api: https://engage.efergy.com/mobile/get_token?username=*username*&password=*password*&device=*token_name*
#alternative api url (example): http://www.energyhive.com/mobile_proxy/getStatus?token=xxxxxxxxxx

import simplejson as json
import urllib2
import time
import datetime
timeout = 3

#create variables in indigo if doesn't exist
if not ("efergyDev1_age" in indigo.variables):
    indigo.variable.create("efergyDev1_age", "defaultValue")
if not ("efergyDev1_reading" in indigo.variables):
    indigo.variable.create("efergyDev1_reading", "defaultValue")
if not ("efergyDev1_battery" in indigo.variables):
    indigo.variable.create("efergyDev1_battery", "defaultValue")
if not ("efergyDev1_falseBattery" in indigo.variables):
    indigo.variable.create("efergyDev1_falseBattery", "defaultValue")
if not ("efergyDev1_mac" in indigo.variables):
    indigo.variable.create("efergyDev1_mac", "defaultValue")
if not ("efergyDev1_last_reading_time" in indigo.variables):
    indigo.variable.create("efergyDev1_last_reading_time", "defaultValue")
if not ("efergyDev1_token" in indigo.variables):
    indigo.variable.create("efergyDev1_token", "defaultValue")
if not ("efergyDev1_status_message" in indigo.variables):
    indigo.variable.create("efergyDev1_status_message", "defaultValue")

#reset status message
indigo.variable.updateValue("efergyDev1_status_message", value= "")

#check if token exists
if indigo.variables["efergyDev1_token"].value == "defaultValue" or not indigo.variables["efergyDev1_token"].value:
   indigo.variable.updateValue("efergyDev1_status_message", value= "NoValidToken")
   indigo.server.log ("Efergy data collection script error: NoValidToken")

#import token value from indigo variable
token=indigo.variables["efergyDev1_token"].value

#debug to indigo log
#localtime = time.asctime( time.localtime(time.time()) )
#indigo.server.log ("Efergy monitor collector script started: " + localtime)

#get data in json from api url
try:
   url1Returned = urllib2.urlopen('https://engage.efergy.com/mobile_proxy/getStatus?token=' + token)
   url2Returned = urllib2.urlopen('https://engage.efergy.com/mobile_proxy/getInstant?token=' + token)
except:
   indigo.variable.updateValue("efergyDev1_status_message", value= "Could not fetch data from Efergy")
   indigo.server.log ("Efergy data collection script error: Could not fetch data from Efergy")

#format api returned data
data_getStatus = url1Returned.read()
data_getInstant = url2Returned.read()

#interpret json
dict1 = json.loads(data_getStatus)
dict2 = json.loads(data_getInstant)

#get json variables to python variables
try:
   battery=str(dict1['listOfMacs'][0]['listofchannels'][0]['type']['battery']) #battery level
   falseBattery=str(dict1['listOfMacs'][0]['listofchannels'][0]['type']['falseBattery'])
   last_reading_ts=float(dict2['last_reading_time']) #value of checked date and time in ticks
   mac=str(dict1['listOfMacs'][0]['mac']) #device mac address
   age=str(dict2['age']) #age of last reading in seconds
   reading=str(round(float(dict2['reading']),1)) #round float value of reading to one decimal and convert to string
except:
   indigo.variable.updateValue("efergyDev1_status_message", value= "Error parsing data from Efergy")
   indigo.server.log ("Efergy data collection script: Error parsing data from Efergy")

#convert last_reading_ts ticks to local time
last_reading_time = datetime.datetime.fromtimestamp(last_reading_ts/1000).strftime('%Y-%m-%d %H:%M:%S')

#update indigo variables
indigo.variable.updateValue("efergyDev1_battery", value=battery)
indigo.variable.updateValue("efergyDev1_falseBattery", value= falseBattery)
indigo.variable.updateValue("efergyDev1_last_reading_time", value= last_reading_time)
indigo.variable.updateValue("efergyDev1_mac", value= mac)
indigo.variable.updateValue("efergyDev1_age", value= age)
indigo.variable.updateValue("efergyDev1_reading", value= reading)

#debug to indigo log
#indigo.server.log ("Battery: " + battery)
#indigo.server.log ("False battery: " + falseBattery)
#indigo.server.log ("Device MAC: " + mac)
#indigo.server.log ("Reading age: " + age)
#indigo.server.log ("Reading value (watts): " + reading)
#indigo.server.log ("Time for reading (local time): " + last_reading_time)

#debug to indigo log
#localtime = time.asctime( time.localtime(time.time()) )
#indigo.server.log ("Efergy monitor collector script finished: " + localtime)

Posted on
Sat Apr 11, 2015 2:31 pm
DaveL17 offline
User avatar
Posts: 6753
Joined: Aug 20, 2013
Location: Chicago, IL, USA

Re: Efergy Engage energy monitor

Looking good!
Dave

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

[My Plugins] - [My Forums]

Posted on
Sat Apr 11, 2015 2:40 pm
RogueProeliator offline
User avatar
Posts: 2501
Joined: Nov 13, 2012
Location: Baton Rouge, LA

Re: Efergy Engage energy monitor

Looking good, but a couple of quick suggestions for you (well, same one, twice); nothing major, but might help out later if there is a problem with the feed.

Code: Select all
try:
   url1Returned = urllib2.urlopen('https://engage.efergy.com/mobile_proxy/getStatus?token=' + token)
   url2Returned = urllib2.urlopen('https://engage.efergy.com/mobile_proxy/getInstant?token=' + token)
except:
   indigo.variable.updateValue("efergyDev1_status_message", value= "Could not fetch data from Efergy")
   indigo.server.log ("Efergy data collection script error: Could not fetch data from Efergy")

...

#get json variables to python variables
try:
   battery=str(dict1['listOfMacs'][0]['listofchannels'][0]['type']['battery']) #battery level
   falseBattery=str(dict1['listOfMacs'][0]['listofchannels'][0]['type']['falseBattery'])
   last_reading_ts=float(dict2['last_reading_time']) #value of checked date and time in ticks
   mac=str(dict1['listOfMacs'][0]['mac']) #device mac address
   age=str(dict2['age']) #age of last reading in seconds
   reading=str(round(float(dict2['reading']),1)) #round float value of reading to one decimal and convert to string
except:
   indigo.variable.updateValue("efergyDev1_status_message", value= "Error parsing data from Efergy")
   indigo.server.log ("Efergy data collection script: Error parsing data from Efergy")

These are well done, properly wrapped in exception handling; the problem is that if there is an exception it is going to show the error message and then continue on processing -- attempting to use the variables that failed to set. This could lead to errors or unintended data values. You should probably exit the script upon a fatal error or prevent subsequent code from executing (moving it all within the try blocks or just check for a value before using it to set variables, or one of several other ways).

May not be a big concern, but might prevent getting python errors in the log when you clearly "knew" the error was there already.

Adam

Posted on
Sat Apr 11, 2015 2:48 pm
lochnesz offline
Posts: 370
Joined: Oct 01, 2014
Location: Stockholm, Sweden

Re: Efergy Engage energy monitor

Thanks, I appreciate all comments and suggestions!

Cheers!
Peter

Posted on
Fri Mar 18, 2016 5:47 pm
jaknudsen offline
User avatar
Posts: 41
Joined: Nov 16, 2015

Re: Efergy Engage energy monitor

Thanks for this script! Now to find out how to log and accumulate the data …

Page 1 of 1

Who is online

Users browsing this forum: No registered users and 5 guests