diff --git a/custom_components/fpl/AverageDailySensor.py b/custom_components/fpl/AverageDailySensor.py deleted file mode 100644 index d0f4778..0000000 --- a/custom_components/fpl/AverageDailySensor.py +++ /dev/null @@ -1,20 +0,0 @@ -from .FplSensor import FplSensor - - -class FplAverageDailySensor(FplSensor): - def __init__(self, hass, config, account): - FplSensor.__init__(self, hass, config, account, "Average Daily") - - @property - def state(self): - try: - if "daily_avg" in self.data: - self._state = self.data["daily_avg"] - except: - pass - return self._state - - @property - def device_state_attributes(self): - """Return the state attributes.""" - return self.attr \ No newline at end of file diff --git a/custom_components/fpl/DailyUsageSensor.py b/custom_components/fpl/DailyUsageSensor.py deleted file mode 100644 index 255e0e7..0000000 --- a/custom_components/fpl/DailyUsageSensor.py +++ /dev/null @@ -1,31 +0,0 @@ -from .FplSensor import FplSensor - - -class FplDailyUsageSensor(FplSensor): - def __init__(self, hass, config, account): - FplSensor.__init__(self, hass, config, account, "Daily Usage") - - @property - def state(self): - try: - if "daily_usage" in self.data: - if len(self.data["daily_usage"]) > 0: - if "cost" in self.data["daily_usage"][-1]: - self._state = self.data["daily_usage"][-1]["cost"] - except: - pass - - return self._state - - @property - def device_state_attributes(self): - """Return the state attributes.""" - try: - if "daily_usage" in self.data: - if len(self.data["daily_usage"]) > 0: - if "date" in self.data["daily_usage"][-1]: - self.attr["date"] = self.data["daily_usage"][-1]["date"] - except: - pass - - return self.attr diff --git a/custom_components/fpl/ProjectedBillSensor.py b/custom_components/fpl/ProjectedBillSensor.py deleted file mode 100644 index bf14a32..0000000 --- a/custom_components/fpl/ProjectedBillSensor.py +++ /dev/null @@ -1,37 +0,0 @@ -from .FplSensor import FplSensor - - -class FplProjectedBillSensor(FplSensor): - def __init__(self, hass, config, account): - FplSensor.__init__(self, hass, config, account, "Projected Bill") - - @property - def state(self): - data = self.data - try: - if "budget_bill" in data.keys(): - if data["budget_bill"]: - if "budget_billing_projected_bill" in data.keys(): - self._state = data["budget_billing_projected_bill"] - else: - if "projected_bill" in data.keys(): - self._state = data["projected_bill"] - except: - pass - - return self._state - - @property - def device_state_attributes(self): - """Return the state attributes.""" - try: - if "budget_bill" in self.data.keys(): - self.attr["budget_bill"] = self.data["budget_bill"] - except: - pass - - return self.attr - - @property - def icon(self): - return "mdi:currency-usd" \ No newline at end of file diff --git a/custom_components/fpl/fplEntity.py b/custom_components/fpl/fplEntity.py index 7b30d27..1680931 100644 --- a/custom_components/fpl/fplEntity.py +++ b/custom_components/fpl/fplEntity.py @@ -1,10 +1,20 @@ """BlueprintEntity class""" +from homeassistant.components.sensor import SensorEntity, STATE_CLASS_MEASUREMENT from homeassistant.helpers.update_coordinator import CoordinatorEntity +from homeassistant.const import ( + CURRENCY_DOLLAR, + DEVICE_CLASS_ENERGY, + ENERGY_KILO_WATT_HOUR, + DEVICE_CLASS_MONETARY, + DEVICE_CLASS_TIMESTAMP, +) + +from datetime import datetime, timedelta from .const import DOMAIN, VERSION, ATTRIBUTION -class FplEntity(CoordinatorEntity): +class FplEntity(CoordinatorEntity, SensorEntity): def __init__(self, coordinator, config_entry, account, sensorName): super().__init__(coordinator) self.config_entry = config_entry @@ -47,3 +57,69 @@ class FplEntity(CoordinatorEntity): def getData(self, field): return self.coordinator.data.get(self.account).get(field) + + +class FplEnergyEntity(FplEntity): + def __init__(self, coordinator, config_entry, account, sensorName): + super().__init__(coordinator, config_entry, account, sensorName) + + @property + def state_class(self) -> str: + """Return the state class of this entity, from STATE_CLASSES, if any.""" + + return STATE_CLASS_MEASUREMENT + + @property + def last_reset(self) -> datetime: + """Return the time when the sensor was last reset, if any.""" + + today = datetime.today() + yesterday = today - timedelta(days=1) + return datetime.combine(yesterday, datetime.min.time()) + + @property + def device_class(self) -> str: + """Return the class of this device, from component DEVICE_CLASSES.""" + return DEVICE_CLASS_ENERGY + + @property + def unit_of_measurement(self) -> str: + """Return the unit of measurement of this entity, if any.""" + return ENERGY_KILO_WATT_HOUR + + @property + def icon(self): + return "mdi:flash" + + +class FplMoneyEntity(FplEntity): + def __init__(self, coordinator, config_entry, account, sensorName): + super().__init__(coordinator, config_entry, account, sensorName) + + @property + def icon(self): + return "mdi:currency-usd" + + @property + def device_class(self) -> str: + """Return the class of this device, from component DEVICE_CLASSES.""" + return DEVICE_CLASS_MONETARY + + @property + def unit_of_measurement(self) -> str: + """Return the unit of measurement of this entity, if any.""" + return CURRENCY_DOLLAR + + +class FplDateEntity(FplEntity): + def __init__(self, coordinator, config_entry, account, sensorName): + super().__init__(coordinator, config_entry, account, sensorName) + + # @property + # def device_class(self) -> str: + # """Return the class of this device, from component DEVICE_CLASSES.""" + # return DEVICE_CLASS_TIMESTAMP + + @property + def icon(self): + return "mdi:calendar" \ No newline at end of file diff --git a/custom_components/fpl/fplapi.py b/custom_components/fpl/fplapi.py index 3265f81..a2c2a67 100644 --- a/custom_components/fpl/fplapi.py +++ b/custom_components/fpl/fplapi.py @@ -1,7 +1,5 @@ -import asyncio import logging -import re -from datetime import timedelta, datetime, date as dt +from datetime import datetime import aiohttp import async_timeout @@ -9,7 +7,7 @@ import json import sys -from bs4 import BeautifulSoup +# from bs4 import BeautifulSoup STATUS_CATEGORY_OPEN = "OPEN" # Api login result @@ -57,7 +55,7 @@ class FplApi(object): async def login(self): _LOGGER.info("Logging in") - """login and get account information""" + # login and get account information result = LOGIN_RESULT_OK try: async with async_timeout.timeout(TIMEOUT): diff --git a/custom_components/fpl/manifest.json b/custom_components/fpl/manifest.json index 805319d..0397962 100644 --- a/custom_components/fpl/manifest.json +++ b/custom_components/fpl/manifest.json @@ -9,9 +9,8 @@ "@dotKrad" ], "requirements": [ - "bs4", "integrationhelper" ], - "homeassistant": "0.96.0", - "version": "1.0.0" + "version": "1.0.0", + "issue_tracker": "https://github.com/dotKrad/hass-fpl/issues" } \ No newline at end of file diff --git a/custom_components/fpl/sensor.py b/custom_components/fpl/sensor.py index a868e1e..64d651a 100644 --- a/custom_components/fpl/sensor.py +++ b/custom_components/fpl/sensor.py @@ -28,7 +28,6 @@ from .sensor_AverageDailySensor import ( from .sensor_DailyUsageSensor import FplDailyUsageKWHSensor, FplDailyUsageSensor from .const import DOMAIN -from .sensor_AllData import AllDataSensor from .TestSensor import TestSensor @@ -42,8 +41,6 @@ async def async_setup_entry(hass, entry, async_add_devices): for account in accounts: # Test Sensor # fpl_accounts.append(TestSensor(coordinator, entry, account)) - # All data sensor - # fpl_accounts.append(AllDataSensor(coordinator, entry, account)) # bill sensors fpl_accounts.append(FplProjectedBillSensor(coordinator, entry, account)) @@ -71,4 +68,7 @@ async def async_setup_entry(hass, entry, async_add_devices): fpl_accounts.append(DailyAverageKWHSensor(coordinator, entry, account)) fpl_accounts.append(BillToDateKWHSensor(coordinator, entry, account)) + fpl_accounts.append(NetReceivedKWHSensor(coordinator, entry, account)) + fpl_accounts.append(NetDeliveredKWHSensor(coordinator, entry, account)) + async_add_devices(fpl_accounts) diff --git a/custom_components/fpl/sensor_AllData.py b/custom_components/fpl/sensor_AllData.py deleted file mode 100644 index 98044b3..0000000 --- a/custom_components/fpl/sensor_AllData.py +++ /dev/null @@ -1,24 +0,0 @@ -from .fplEntity import FplEntity - - -class AllDataSensor(FplEntity): - def __init__(self, coordinator, config, account): - super().__init__(coordinator, config, account, "") - - @property - def state(self): - budget = self.getData("budget_bill") - budget_billing_projected_bill = self.getData("budget_billing_projected_bill") - - if budget == True and budget_billing_projected_bill is not None: - return self.getData("budget_billing_projected_bill") - - return self.getData("projected_bill") - - def defineAttributes(self): - """Return the state attributes.""" - return self.coordinator.data.get(self.account) - - @property - def icon(self): - return "mdi:currency-usd" diff --git a/custom_components/fpl/sensor_AverageDailySensor.py b/custom_components/fpl/sensor_AverageDailySensor.py index 66d25f1..3399ded 100644 --- a/custom_components/fpl/sensor_AverageDailySensor.py +++ b/custom_components/fpl/sensor_AverageDailySensor.py @@ -1,7 +1,7 @@ -from .fplEntity import FplEntity +from .fplEntity import FplMoneyEntity -class FplAverageDailySensor(FplEntity): +class FplAverageDailySensor(FplMoneyEntity): def __init__(self, coordinator, config, account): super().__init__(coordinator, config, account, "Daily Average") @@ -15,12 +15,8 @@ class FplAverageDailySensor(FplEntity): return self.getData("daily_avg") - @property - def icon(self): - return "mdi:currency-usd" - -class BudgetDailyAverageSensor(FplEntity): +class BudgetDailyAverageSensor(FplMoneyEntity): def __init__(self, coordinator, config, account): super().__init__(coordinator, config, account, "Budget Daily Average") @@ -28,19 +24,11 @@ class BudgetDailyAverageSensor(FplEntity): def state(self): return self.getData("budget_billing_daily_avg") - @property - def icon(self): - return "mdi:currency-usd" - -class ActualDailyAverageSensor(FplEntity): +class ActualDailyAverageSensor(FplMoneyEntity): def __init__(self, coordinator, config, account): super().__init__(coordinator, config, account, "Actual Daily Average") @property def state(self): return self.getData("daily_avg") - - @property - def icon(self): - return "mdi:currency-usd" diff --git a/custom_components/fpl/sensor_DailyUsageSensor.py b/custom_components/fpl/sensor_DailyUsageSensor.py index 299188e..8bfa90e 100644 --- a/custom_components/fpl/sensor_DailyUsageSensor.py +++ b/custom_components/fpl/sensor_DailyUsageSensor.py @@ -1,7 +1,7 @@ -from .fplEntity import FplEntity +from .fplEntity import FplEnergyEntity, FplMoneyEntity -class FplDailyUsageSensor(FplEntity): +class FplDailyUsageSensor(FplMoneyEntity): def __init__(self, coordinator, config, account): super().__init__(coordinator, config, account, "Daily Usage") @@ -23,12 +23,8 @@ class FplDailyUsageSensor(FplEntity): return {} - @property - def icon(self): - return "mdi:currency-usd" - -class FplDailyUsageKWHSensor(FplEntity): +class FplDailyUsageKWHSensor(FplEnergyEntity): def __init__(self, coordinator, config, account): super().__init__(coordinator, config, account, "Daily Usage KWH") @@ -49,7 +45,3 @@ class FplDailyUsageKWHSensor(FplEntity): return {"date": data[-1]["date"]} return {} - - @property - def icon(self): - return "mdi:currency-usd" diff --git a/custom_components/fpl/sensor_DatesSensor.py b/custom_components/fpl/sensor_DatesSensor.py index b0414d7..b2f2fdb 100644 --- a/custom_components/fpl/sensor_DatesSensor.py +++ b/custom_components/fpl/sensor_DatesSensor.py @@ -1,7 +1,7 @@ -from .fplEntity import FplEntity +from .fplEntity import FplDateEntity -class CurrentBillDateSensor(FplEntity): +class CurrentBillDateSensor(FplDateEntity): def __init__(self, coordinator, config, account): super().__init__(coordinator, config, account, "Current Bill Date") @@ -9,12 +9,8 @@ class CurrentBillDateSensor(FplEntity): def state(self): return self.getData("current_bill_date") - @property - def icon(self): - return "mdi:calendar" - -class NextBillDateSensor(FplEntity): +class NextBillDateSensor(FplDateEntity): def __init__(self, coordinator, config, account): super().__init__(coordinator, config, account, "Next Bill Date") @@ -22,12 +18,8 @@ class NextBillDateSensor(FplEntity): def state(self): return self.getData("next_bill_date") - @property - def icon(self): - return "mdi:calendar" - -class ServiceDaysSensor(FplEntity): +class ServiceDaysSensor(FplDateEntity): def __init__(self, coordinator, config, account): super().__init__(coordinator, config, account, "Service Days") @@ -35,12 +27,8 @@ class ServiceDaysSensor(FplEntity): def state(self): return self.getData("service_days") - @property - def icon(self): - return "mdi:calendar" - -class AsOfDaysSensor(FplEntity): +class AsOfDaysSensor(FplDateEntity): def __init__(self, coordinator, config, account): super().__init__(coordinator, config, account, "As Of Days") @@ -48,19 +36,11 @@ class AsOfDaysSensor(FplEntity): def state(self): return self.getData("as_of_days") - @property - def icon(self): - return "mdi:calendar" - -class RemainingDaysSensor(FplEntity): +class RemainingDaysSensor(FplDateEntity): def __init__(self, coordinator, config, account): super().__init__(coordinator, config, account, "Remaining Days") @property def state(self): return self.getData("remaining_days") - - @property - def icon(self): - return "mdi:calendar" diff --git a/custom_components/fpl/sensor_KWHSensor.py b/custom_components/fpl/sensor_KWHSensor.py index ba2d24a..6d48d03 100644 --- a/custom_components/fpl/sensor_KWHSensor.py +++ b/custom_components/fpl/sensor_KWHSensor.py @@ -1,7 +1,8 @@ -from .fplEntity import FplEntity +from homeassistant.components.sensor import STATE_CLASS_TOTAL_INCREASING +from .fplEntity import FplEnergyEntity -class ProjectedKWHSensor(FplEntity): +class ProjectedKWHSensor(FplEnergyEntity): def __init__(self, coordinator, config, account): super().__init__(coordinator, config, account, "Projected KWH") @@ -9,12 +10,8 @@ class ProjectedKWHSensor(FplEntity): def state(self): return self.getData("projectedKWH") - @property - def icon(self): - return "mdi:flash" - -class DailyAverageKWHSensor(FplEntity): +class DailyAverageKWHSensor(FplEnergyEntity): def __init__(self, coordinator, config, account): super().__init__(coordinator, config, account, "Daily Average KWH") @@ -22,12 +19,8 @@ class DailyAverageKWHSensor(FplEntity): def state(self): return self.getData("dailyAverageKWH") - @property - def icon(self): - return "mdi:flash" - -class BillToDateKWHSensor(FplEntity): +class BillToDateKWHSensor(FplEnergyEntity): def __init__(self, coordinator, config, account): super().__init__(coordinator, config, account, "Bill To Date KWH") @@ -36,10 +29,11 @@ class BillToDateKWHSensor(FplEntity): return self.getData("billToDateKWH") @property - def icon(self): - return "mdi:flash" + def state_class(self) -> str: + """Return the state class of this entity, from STATE_CLASSES, if any.""" -class NetReceivedKWHSensor(FplEntity): + +class NetReceivedKWHSensor(FplEnergyEntity): def __init__(self, coordinator, config, account): super().__init__(coordinator, config, account, "Received Meter Reading KWH") @@ -51,7 +45,8 @@ class NetReceivedKWHSensor(FplEntity): def icon(self): return "mdi:flash" -class NetDeliveredKWHSensor(FplEntity): + +class NetDeliveredKWHSensor(FplEnergyEntity): def __init__(self, coordinator, config, account): super().__init__(coordinator, config, account, "Delivered Meter Reading KWH") diff --git a/custom_components/fpl/sensor_ProjectedBillSensor.py b/custom_components/fpl/sensor_ProjectedBillSensor.py index acf7482..7f6a515 100644 --- a/custom_components/fpl/sensor_ProjectedBillSensor.py +++ b/custom_components/fpl/sensor_ProjectedBillSensor.py @@ -1,7 +1,7 @@ -from .fplEntity import FplEntity +from .fplEntity import FplMoneyEntity -class FplProjectedBillSensor(FplEntity): +class FplProjectedBillSensor(FplMoneyEntity): def __init__(self, coordinator, config, account): super().__init__(coordinator, config, account, "Projected Bill") @@ -26,13 +26,9 @@ class FplProjectedBillSensor(FplEntity): return attributes - @property - def icon(self): - return "mdi:currency-usd" - # Defered Amount -class DeferedAmountSensor(FplEntity): +class DeferedAmountSensor(FplMoneyEntity): def __init__(self, coordinator, config, account): super().__init__(coordinator, config, account, "Defered Amount") @@ -42,12 +38,8 @@ class DeferedAmountSensor(FplEntity): return self.getData("defered_amount") return 0 - @property - def icon(self): - return "mdi:currency-usd" - -class ProjectedBudgetBillSensor(FplEntity): +class ProjectedBudgetBillSensor(FplMoneyEntity): def __init__(self, coordinator, config, account): super().__init__(coordinator, config, account, "Projected Budget Bill") @@ -55,19 +47,11 @@ class ProjectedBudgetBillSensor(FplEntity): def state(self): return self.getData("budget_billing_projected_bill") - @property - def icon(self): - return "mdi:currency-usd" - -class ProjectedActualBillSensor(FplEntity): +class ProjectedActualBillSensor(FplMoneyEntity): def __init__(self, coordinator, config, account): super().__init__(coordinator, config, account, "Projected Actual Bill") @property def state(self): return self.getData("projected_bill") - - @property - def icon(self): - return "mdi:currency-usd" diff --git a/hacs.json b/hacs.json new file mode 100644 index 0000000..c1a4266 --- /dev/null +++ b/hacs.json @@ -0,0 +1,8 @@ +{ + "name": "FPL", + "country": "US", + "domains": [ + "sensor" + ], + "homeassistant": "2021.12.0" +} \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 7019fc7..e69de29 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +0,0 @@ -integrationhelper -sampleclient \ No newline at end of file diff --git a/requirements_test.txt b/requirements_test.txt new file mode 100644 index 0000000..e69de29