Skip to content

Commit

Permalink
Fix for usage responses missing more data than intended (#70)
Browse files Browse the repository at this point in the history
* Attempt to set dev versions automatically.

* Run formatter

* Tweak retry on usage to try more times and with bigger gaps between retries. Caller can change settings or disable.

* Don't quit early on missing data, still need to iterate full list.

* Only overwrite data if it's good or we have no more retries
  • Loading branch information
magico13 authored Mar 3, 2024
1 parent 74dd52e commit 493b75e
Show file tree
Hide file tree
Showing 11 changed files with 746 additions and 409 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/publish-to-pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ jobs:
pip install
build
--user
- name: Set development version
run: >-
if [ "${{ github.ref }}" != "refs/heads/master" ]; then
sed -i "s/VERSION = \".*\"/VERSION = \"$(cat pyemvue/__version__.py | grep -oP '(?<=VERSION = \").*(?=\")').dev${{ github.run_number }}\"/" pyemvue/__version__.py
fi
- name: Build a binary wheel and a source tarball
run: python3 -m build
- name: Store the distribution packages
Expand Down
144 changes: 108 additions & 36 deletions pyemvue/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,30 @@
from pyemvue.enums import Scale, Unit
from pyemvue.pyemvue import PyEmVue

def print_recursive(usage_dict: dict[int, VueUsageDevice], info: dict[int, VueDevice], scaleBy: float=1, unit='kWh', depth=0):

def print_recursive(
usage_dict: dict[int, VueUsageDevice],
info: dict[int, VueDevice],
scaleBy: float = 1,
unit="kWh",
depth=0,
):
for gid, device in usage_dict.items():
for channelnum, channel in device.channels.items():
name = channel.name
if name == 'Main':
if name == "Main":
name = info[gid].device_name
usage = channel.usage or 0
print('-'*depth, f'{gid} {channelnum} {name} {usage*scaleBy} {unit}')
print("-" * depth, f"{gid} {channelnum} {name} {usage*scaleBy} {unit}")
if channel.nested_devices:
print_recursive(channel.nested_devices, info, scaleBy=scaleBy, unit=unit, depth=depth+1)
print_recursive(
channel.nested_devices,
info,
scaleBy=scaleBy,
unit=unit,
depth=depth + 1,
)


def main():
errorMsg = 'Please pass a file containing the "email" and "password" as json.'
Expand All @@ -27,7 +41,7 @@ def main():
filepath = sys.argv[1]
vue = PyEmVue()
vue.login(token_storage_file=filepath)
print('Logged in. Authtoken follows:')
print("Logged in. Authtoken follows:")
print(vue.auth.tokens["id_token"])
print()
channelTypes = vue.get_channel_types()
Expand All @@ -38,70 +52,128 @@ def main():
if not device.device_gid in deviceGids:
deviceGids.append(device.device_gid)
deviceInfo[device.device_gid] = device
print(device.device_gid, device.manufacturer_id, device.model, device.firmware)
print(
device.device_gid, device.manufacturer_id, device.model, device.firmware
)
for chan in device.channels:
channelTypeInfo = next((c for c in channelTypes if c.channel_type_gid == chan.channel_type_gid), None)
print('\t', chan.device_gid, chan.name, chan.channel_num, chan.channel_multiplier, channelTypeInfo.description if channelTypeInfo else chan.channel_type_gid)
channelTypeInfo = next(
(
c
for c in channelTypes
if c.channel_type_gid == chan.channel_type_gid
),
None,
)
print(
"\t",
chan.device_gid,
chan.name,
chan.channel_num,
chan.channel_multiplier,
(
channelTypeInfo.description
if channelTypeInfo
else chan.channel_type_gid
),
)
else:
deviceInfo[device.device_gid].channels += device.channels
for chan in device.channels:
channelTypeInfo = next((c for c in channelTypes if c.channel_type_gid == chan.channel_type_gid), None)
print('\t', chan.device_gid, chan.name, chan.channel_num, chan.channel_multiplier, channelTypeInfo.description if channelTypeInfo else chan.channel_type_gid)
channelTypeInfo = next(
(
c
for c in channelTypes
if c.channel_type_gid == chan.channel_type_gid
),
None,
)
print(
"\t",
chan.device_gid,
chan.name,
chan.channel_num,
chan.channel_multiplier,
(
channelTypeInfo.description
if channelTypeInfo
else chan.channel_type_gid
),
)

monthly, start = vue.get_chart_usage(devices[0].channels[0],scale=Scale.MONTH.value)
print(monthly[0], 'kwh used since', start.isoformat())
monthly, start = vue.get_chart_usage(
devices[0].channels[0], scale=Scale.MONTH.value
)
print(monthly[0], "kwh used since", start.isoformat())
now = datetime.datetime.now(datetime.timezone.utc)
midnight=(datetime.datetime
.now(dateutil.tz.gettz(devices[0].time_zone))
.replace(hour=0, minute=0, second=0, microsecond=0)
.astimezone(dateutil.tz.tzutc()))
midnight = (
datetime.datetime.now(dateutil.tz.gettz(devices[0].time_zone))
.replace(hour=0, minute=0, second=0, microsecond=0)
.astimezone(dateutil.tz.tzutc())
)
yesterday = midnight - datetime.timedelta(days=1)
yesterday = yesterday.replace(tzinfo=None)
print('Total usage for today in kwh: ')
print("Total usage for today in kwh: ")

use = vue.get_device_list_usage(deviceGids, now, Scale.DAY.value)
print_recursive(use, deviceInfo)
print('Total usage for yesterday in kwh: ')
print("Total usage for yesterday in kwh: ")
for gid, device in deviceInfo.items():
for chan in device.channels:
usage = vue.get_chart_usage(chan, yesterday, yesterday+datetime.timedelta(hours=23, minutes=59), Scale.DAY.value)
usage = vue.get_chart_usage(
chan,
yesterday,
yesterday + datetime.timedelta(hours=23, minutes=59),
Scale.DAY.value,
)
if usage and usage[0]:
print(f'{chan.device_gid} ({chan.channel_num}): {usage[0][0]} kwh')
print('Average usage over the last minute in watts: ')
print(f"{chan.device_gid} ({chan.channel_num}): {usage[0][0]} kwh")
print("Average usage over the last minute in watts: ")
use = vue.get_device_list_usage(deviceGids, None, Scale.MINUTE.value)
print_recursive(use, deviceInfo, scaleBy=60000, unit='W')
print_recursive(use, deviceInfo, scaleBy=60000, unit="W")

usage_over_time, start_time = vue.get_chart_usage(devices[0].channels[0], datetime.datetime.now(datetime.timezone.utc)-datetime.timedelta(days=7), datetime.datetime.now(datetime.timezone.utc), scale=Scale.DAY.value, unit=Unit.KWH.value)
usage_over_time, start_time = vue.get_chart_usage(
devices[0].channels[0],
datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(days=7),
datetime.datetime.now(datetime.timezone.utc),
scale=Scale.DAY.value,
unit=Unit.KWH.value,
)

print('Usage for the last seven days starting', start_time.isoformat())
print("Usage for the last seven days starting", start_time.isoformat())
for usage in usage_over_time:
print(usage, 'kwh')
print(usage, "kwh")

(outlets, chargers) = vue.get_devices_status(devices)
print('List of Outlets:')
print("List of Outlets:")
for outlet in outlets:
print(f"\t{outlet.device_gid} On? {outlet.outlet_on}")

print('List of Chargers:')
print("List of Chargers:")
for charger in chargers:
print(f"\t{charger.device_gid} On? {charger.charger_on} Charge rate: {charger.charging_rate}/{charger.max_charging_rate} Status: {charger.status}")
print(
f"\t{charger.device_gid} On? {charger.charger_on} Charge rate: {charger.charging_rate}/{charger.max_charging_rate} Status: {charger.status}"
)

try:
vehicles = vue.get_vehicles()
print('List of Vehicles')
print("List of Vehicles")
for vehicle in vehicles:
print(f'\t{vehicle.vehicle_gid} ({vehicle.display_name}) - {vehicle.year} {vehicle.make} {vehicle.model}')
print(
f"\t{vehicle.vehicle_gid} ({vehicle.display_name}) - {vehicle.year} {vehicle.make} {vehicle.model}"
)

print('List of Vehicle Statuses')
print("List of Vehicle Statuses")
for vehicle in vehicles:
vehicleStatus = vue.get_vehicle_status(vehicle.vehicle_gid)
if vehicleStatus:
print(f'\t{vehicleStatus.vehicle_gid} {vehicleStatus.vehicle_state} - Charging: {vehicleStatus.charging_state} Battery level: {vehicleStatus.battery_level}')
print(
f"\t{vehicleStatus.vehicle_gid} {vehicleStatus.vehicle_state} - Charging: {vehicleStatus.charging_state} Battery level: {vehicleStatus.battery_level}"
)
else:
print(f'\t{vehicle.vehicle_gid} - No status available')
print(f"\t{vehicle.vehicle_gid} - No status available")
except Exception as e:
print(f'Error getting vehicles: {e}')
print(f"Error getting vehicles: {e}")

if __name__ == '__main__':
main()

if __name__ == "__main__":
main()
1 change: 1 addition & 0 deletions pyemvue/__version__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
VERSION = "0.18.4"
Loading

0 comments on commit 493b75e

Please sign in to comment.