Browse Source

Read minutely usage data for the last 7 days

Jason Tarka 11 months ago
parent
commit
ef058e92cd
3 changed files with 67 additions and 52 deletions
  1. 1 0
      .gitignore
  2. 16 1
      README.md
  3. 50 51
      main.py

+ 1 - 0
.gitignore

@@ -1,2 +1,3 @@
 keys.json
 env/
+*.tsv

+ 16 - 1
README.md

@@ -18,4 +18,19 @@ pip install -r requirements.txt
 
 # Update set of required packages
 pip freeze > requirements.txt
-```
+```
+
+## Authentication
+
+Create a `keys.json` file in this directory containing your
+username & password:
+
+```json
+{
+	"username": "<your username>",
+	"password": "<your password>"
+}
+```
+
+After the first time the script is run, the file will automatically
+be updated to use access tokens, rather than your password.

+ 50 - 51
main.py

@@ -1,36 +1,58 @@
+# This script will find all devices in your installation and
+# output their per-minute usage for the previous DAYS_BACK days.
+# Per-minute data is stored for a maximum of 7 days.
+#
+# To change the timing, update the DAYS_BACK variable below.
+#
+# Reads credentials from `keys.json`
+
 import pyemvue
 import json
-import datetime
+
 from pyemvue.enums import Scale, Unit
+from pyemvue import PyEmVue
+from pprint import pprint
+from datetime import datetime, timezone, timedelta
+
+NOW = datetime.now(timezone.utc)
+DAYS_BACK = 7 # Number of days in the past to get per-minute data for.
+MAX_HOURS = 12 # The maxinum number of hours that can be retrieved at once.
 
-def printRecursive(usageDict, info, depth=0):
-	for gid, device in usageDict.items():
-		for channelNum, channel in device.channels.items():
-			name = channel.name
-			if name == 'Main':
-				name = info[gid].device_name
-			print('-'*depth, f'{gid}\t{channelNum}\t{name}\t{channel.usage}\tkWh')
-			if channel.nested_devices:
-				printRecursive(channel.nested_devices, info, depth+1)
+# Get & display minutely data for all devices.
+def allUsageOverTime(vue: PyEmVue):
+	devices = vue.get_devices()
+	print(f'time\tdevice_gid\tchannel_num\twH\twatts\tmultiplier\tname')
 
-def usageOverTime(vue, device):
-	now = datetime.datetime.now(datetime.timezone.utc)
-	search_end = now
-	# search_end = now - datetime.timedelta(hours=12)
-	search_start = search_end - datetime.timedelta(hours=12)
+	for device in devices:
+		# print('=== Device ===')
+		# pprint(vars(device))
+		for channel in device.channels:
+			# pprint(vars(channel))
+			if not channel.name is None:
+				channelUsageOverTime(vue, channel)
 
-	usage_over_time, start_time = vue.get_chart_usage(
-			device.channels[0],
-			search_start,
-			search_end,
-			scale=Scale.MINUTE.value,
-			unit=Unit.KWH.value
-		)
-	print('Usage for the last 7 days, starting', start_time.isoformat())
-	currTime = start_time
-	for usage in usage_over_time:
-		print(currTime, usage*1000, 'Wh')
-		currTime += datetime.timedelta(minutes=1)
+def channelUsageOverTime(vue: PyEmVue, c):
+	start_time = NOW - timedelta(days=DAYS_BACK)
+	end_time = start_time + timedelta(hours=MAX_HOURS)
+	while start_time < NOW:
+		usage_over_time, start = vue.get_chart_usage(
+				c,
+				start_time, end_time,
+				scale=Scale.MINUTE.value,
+				unit=Unit.KWH.value
+			)
+		time = start
+		for kwh in usage_over_time:
+			if kwh is None:
+				continue
+			wattHours = kwh * 1000
+			watts = wattHours * 60
+			print(f'{time}\t{c.device_gid}\t{c.channel_num}\t{wattHours}\t{watts}\t{c.channel_multiplier}\t{c.name}')
+			time += timedelta(minutes=1)
+		
+		# Jump to the next start time.
+		start_time = end_time
+		end_time += timedelta(hours=MAX_HOURS)
 
 if __name__ == '__main__':
 	with open('keys.json') as f:
@@ -53,27 +75,4 @@ if __name__ == '__main__':
 				token_storage_file='keys.json'
 			)
 	
-	devices = vue.get_devices()
-
-	# Show current usage for all devices.
-	deviceGIDs = []
-	deviceInfo = {}
-	for device in devices:
-		gid = device.device_gid
-		if not gid in deviceGIDs:
-			deviceGIDs.append(gid)
-			deviceInfo[gid] = device
-		else:
-			deviceInfo[gid].channels += device.channels
-	
-	usageDict = vue.get_device_list_usage(
-			deviceGids=deviceGIDs,
-			instant=None,
-			scale=Scale.MINUTE.value,
-			unit=Unit.KWH.value
-		)
-	print(f'device_gid\tchannel_num\tname\tusage\tunit')
-	printRecursive(usageDict, deviceInfo)
-
-	# Show previous usage for the first device.
-	usageOverTime(vue, devices[0])
+	allUsageOverTime(vue)