Created
March 17, 2022 09:30
-
-
Save johnlpage/41d4283146c0dab0674975ff6f06cd18 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import aiohttp | |
import pysmartthings | |
import pymongo | |
import json | |
import asyncio | |
from pprint import pprint | |
import datetime | |
with open("/home/pi/.smartthing_token") as f: | |
token = f.readline().strip() | |
interesting_attributes = [ | |
"n", | |
"switch", | |
"powerConsumption", | |
"operatingState", | |
"ovenSetpoint", | |
"temperature", | |
"machineState", | |
] | |
# Try to work out a wattage if we can | |
def estimate_wattage(rec): | |
if rec.get("n") == "Dishwasher" and rec["machineState"] == "run": | |
print("Dishwasher on") | |
return 500 # Average wash is 1500W in 3 hours apparently | |
if "washer" in rec.get("n"): | |
pc = rec.get("powerConsumption") | |
try: | |
if pc: | |
start = datetime.datetime.strptime( | |
pc["start"][:19], "%Y-%m-%dT%H:%M:%S" | |
) | |
end = datetime.datetime.strptime(pc["end"][:19], "%Y-%m-%dT%H:%M:%S") | |
used = pc["deltaEnergy"] | |
seconds = (end - start).total_seconds() | |
if seconds > 0: | |
return (used * 3600) / seconds | |
except Exception as e: | |
print(e) | |
return None | |
return 0 | |
if "oven" in rec.get("n"): | |
if rec.get("operatingState", "ready") != "ready": | |
# Are we heating or holding? | |
if rec["ovenSetpoint"] * 0.95 > rec["temperature"]: | |
return 1200 | |
else: | |
return 400 | |
async def log_devices(): | |
async with aiohttp.ClientSession() as session: | |
api = pysmartthings.SmartThings(session, token) | |
devices = await api.devices() | |
deviceinfo = [] | |
for device in devices: | |
try: | |
name = device.label | |
# Dont record my mobile phone | |
if "Tully" not in name: | |
await device.status.refresh() | |
turned_on = device.status.switch | |
record = {"on": turned_on, "name": name} | |
# if "David" in name: | |
# pprint(device.status.values) | |
for a in interesting_attributes: | |
v = device.status.values.get(a, None) | |
if v != None: | |
record[a] = v | |
watts = estimate_wattage(record) | |
if watts != None: | |
record["watts"] = watts | |
record["on"] = True | |
turned_on = True | |
# Let's not waste space on things that are off | |
if turned_on: | |
deviceinfo.append(record) | |
except Exception as e: | |
# Fridge returns an auth error? | |
print(f"{device.label} not available {e}") | |
return deviceinfo | |
def main(): | |
with open("/home/pi/.mongo_uri.txt") as f: | |
uri = f.readline().strip() | |
mongoclient = pymongo.MongoClient(uri) | |
loop = asyncio.get_event_loop() | |
devices = loop.run_until_complete(log_devices()) | |
loop.close() | |
# Fridge is always running - we can see on its screen and app how much energy | |
# Average is about 2 units a day so we will add that 2KW/(24*6) = 83w | |
devices.append({"n": "fridge", "name": "Fridge", "on": True, "watts": 83}) | |
pprint(devices) | |
if len(devices) > 0: | |
# Append this to an array in the latest electicity reading | |
collection = mongoclient.energy.meter | |
query = {"type": "electric"} | |
sort = [("date", -1)] | |
update = {"$push": {"devices": {"$each": devices}}} | |
collection.find_one_and_update(query, update, sort=sort) | |
if __name__ == "__main__": | |
main() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment