I thought I’d share here how I get data from my CurrentCost EnviR.
First of all, credits were credits are due, the original code comes from Robin Wilson
Now that this is out of the way, here is what you’ll need:
- CurrentCost EnviR or a CurrentCost CC128 (though the latter only allows 1 energy monitor device connected)
- RJ45 to USB data Cable
- MQTT Setup and running. Check HA’s docs
You will most likely need to install a few libraries for this to work:
sudo pip install requests untangle simplejson pyserial
Now copy both scripts below.
The first file calls the main script, ensuring only 1 script is running at a time (since we’re reading data from a serial port)
#!/usr/bin/python
# -*- coding: utf-8 -*-
# CurrentCost.py
import time
import subprocess
# Kill reader program in case it's running since we're reading over a serial port
cmd1 = "echo INSERT_SU_PASSWORD_HERE | sudo -S pkill -9 -f CurrentCostReader"
try:
ps = subprocess.Popen(cmd1, shell=True)
except:
pass
time.sleep(1)
cmd2 = "echo INSERT_SU_PASSWORD_HERE | sudo -S FULL_PATH_TO_FILE/CurrentCostReader.py"
print "Starting CurrentCostReader..."
ps = subprocess.Popen(cmd2, shell=True)
# Ensures main reader program gets killed if main program stops
def Goodbye():
print "Killing CurrentCostReader..."
try:
ps = subprocess.Popen(cmd1, shell=True)
except:
pass
import atexit
atexit.register(Goodbye)
while(True):
time.sleep(1)
The 2nd file does all the work:
#!/usr/bin/python
# -*- coding: utf-8 -*-
# CurrentCostReader.py
# there may be a few libraries that need installing.
import untangle
import serial
import json, requests, simplejson
import paho.mqtt.client as mqtt
MQTT_Host = "INSERT_MQTT_HOST_HERE"
MQTT_Port = "INSERT_PORT_HERE"
MQTT_User = "INSERT_USERNAME_HERE"
MQTT_Password = "INSERT_PASSWORD_HERE"
degree_sign= u'\u2103' #don't touch, this is the code for 'º'
# Appliances Definitions, 1 definition by if block below
# Set to 0.1 to force the program to send an initial status at first run
Temperature = 0.1
Total = 0.1
Dehumidifier = 0.1
def get_data(port='/dev/serial/by-id/usb-Prolific_Technology_Inc._USB-Serial_Controller-if00-port0', verbose=False):
# port: the port that the CurrentCost meter is attached to. Something like /dev/ttyUSB0 or COM1 or /dev/serial/by-id/usb-Prolific_Technology_Inc._USB-Serial_Controller-if00-port0
# Returns:
# (sensor, temperature, usage), with sensor as the number of the interface a device is assigned to, temperature in degrees C, and usage in Watts
ser = serial.Serial(port, 57600)
xmldata = ser.readline()
if verbose:
print(xmldata)
ser.close()
p = untangle.parse(xmldata)
temperature = float(p.msg.tmpr.cdata)
watts = int(p.msg.ch1.watts.cdata)
sensor = int(p.msg.sensor.cdata)
return [sensor, watts, temperature]
client = mqtt.Client("P1") # must be unique on MQTT network
client.username_pw_set(str(MQTT_User),str(MQTT_Password))
client.connect(MQTT_Host, port=str(MQTT_Port))
while(True):
try:
CCData = get_data()
CCData[2] = CCData[2] - 2.5 # CCData[2] is the temperature. I'm adjusting as my CurrentCost is 2.5ºC higher than real temp
# If block for Temperature
if (Temperature != CCData[2]):
print ("Temperature: %s" % CCData[2])
Temperature = CCData[2]
client.publish('CurrentCost/Temperature','{"state":"'+str(Temperature)+'","unit_of_measurement":"'+degree_sign+'"}', qos=0, retain=True)
# If block for Appliance connected to channel #0
if (CCData[0] == 0):
if (Total != CCData[1]):
print ("Total: %s" % CCData[1])
Total = CCData[1]
client.publish('CurrentCost/TTL_Power','{"state":"'+str(Total)+'","unit_of_measurement":"Wh"}', qos=0, retain=True)
# If block for Appliance connected to channel #2
if (CCData[0] == 2):
if (Dehumidifier != CCData[1]):
print ("Dehumidifier: %s" % CCData[1])
Dehumidifier = CCData[1]
client.publish('CurrentCost/Dehumidifier_Power','{"state":"'+str(Dehumidifier)+'","unit_of_measurement":"Wh"}', qos=0, retain=True)
# Add if blocks here for other appliances, as shown on the CurrentCost display on the bottom right.
# If adding a block add name under definitions and assign 0.1 to initialise
# To see the acutal output, do not start this program and instead run below command in terminal, changin the ttyUSB with the one of the CurrentCost
# minicom -D /dev/ttyUSB0 -b 57600
except:
pass
I have hopefully added enough comments in the scripts to help with the local settings, so be sure to read them
Now add a shell_command to your configuration,yaml:
shell_command:
getcurrentcost: /FULL_PATH_TO_FILE/CurrentCost.py
and add sensors to your configuration.yaml:
sensor:
- platform: mqtt
state_topic: "CurrentCost/Temperature"
name: "CurrentCost_Temperature"
unit_of_measurement: '°C'
value_template: '{{ value_json.state }}'
- platform: mqtt
state_topic: "CurrentCost/TTL_Power"
name: "CurrentCost_Power"
unit_of_measurement: "Wh"
value_template: '{{ value_json.state }}'
Add an automation so the script starts when HA starts:
automation:
- alias: HASS Start CurrentCost
trigger:
- platform: homeassistant
event: start
action:
- service: shell_command.getcurrentcost
That should be it
[EDIT] Amended code to make it python3 compatible.
If nothing gets displayed you may have to edit /usr/local/lib/python3.x/dist-packages/untangle.py
(replace x
with your python3 version):
- Replace
parser.parse(StringIO(filename))
withparser.parse(StringIO(filename.decode('utf-8')))
- Replace
return string.startswith('http://') or string.startswith('https://')
withreturn string.startswith(b'http://') or string.startswith(b'https://')