Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RE: Support for new Home Assistant Energy Managment and Stats #16 #49

Merged
merged 2 commits into from
Apr 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 98 additions & 8 deletions custom_components/fpl/FplMainRegionApiClient.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import json
import logging
from datetime import datetime
from datetime import datetime, timedelta
import aiohttp
import async_timeout

Expand Down Expand Up @@ -125,6 +125,8 @@ async def update(self, account) -> dict:
premise = account_data.get("premiseNumber").zfill(9)

data["meterSerialNo"] = account_data["meterSerialNo"]
#data["meterNo"] = account_data["meterNo"]
meterno = account_data["meterNo"]

# currentBillDate
currentBillDate = datetime.strptime(
Expand Down Expand Up @@ -175,15 +177,11 @@ def hasProgram(programName) -> bool:

# Get data from energy service
data.update(
await self.__getDataFromEnergyService(account, premise, currentBillDate)
await self.__getDataFromEnergyService(account, premise, currentBillDate, meterno)
)

# Get data from energy service ( hourly )
# data.update(
# await self.__getDataFromEnergyServiceHourly(
# account, premise, currentBillDate
# )
# )
# data.update(await self.__getDataFromEnergyServiceHourly(account, premise, meterno))

data.update(await self.__getDataFromApplianceUsage(account, currentBillDate))
data.update(await self.__getDataFromBalance(account))
Expand Down Expand Up @@ -273,7 +271,7 @@ async def __getBBL_async(self, account, projectedBillData) -> dict:
return data

async def __getDataFromEnergyService(
self, account, premise, lastBilledDate
self, account, premise, lastBilledDate, meterno
) -> dict:
_LOGGER.info("Getting energy service data")

Expand All @@ -286,6 +284,7 @@ async def __getDataFromEnergyService(
"accountType": "RESIDENTIAL",
"revCode": "1",
"premiseNumber": premise,
"meterNo": meterno,
"projectedBillFlag": True,
"billComparisionFlag": True,
"monthlyFlag": True,
Expand Down Expand Up @@ -341,6 +340,12 @@ async def __getDataFromEnergyService(
"netReceivedKwh": daily["netReceivedKwh"]
if "netReceivedKwh" in daily.keys()
else 0,
"netDeliveredReading": daily["netDeliveredReading"]
if "netDeliveredReading" in daily.keys()
else 0,
"netReceivedReading": daily["netReceivedReading"]
if "netReceivedReading" in daily.keys()
else 0,
"readTime": datetime.fromisoformat(
daily[
"readTime"
Expand All @@ -365,6 +370,91 @@ async def __getDataFromEnergyService(

return data

async def __getDataFromEnergyServiceHourly(account, premise, meterno) -> dict:
_LOGGER.info("Getting energy service hourly data")

today = str(datetime.now().strftime("%m%d%Y"))
JSON = {
"status": 2,
"channel": "WEB",
"amrFlag": "Y",
"accountType": "RESIDENTIAL",
"revCode": "1",
"premiseNumber": premise,
"meterNo": meterno,
"projectedBillFlag": False,
"billComparisionFlag": False,
"monthlyFlag": False,
"frequencyType": "Hourly",
"applicationPage": "resDashBoard",
"startDate": today,
"endDate":"",
}

URL_ENERGY_SERVICE = (
API_HOST
+ "/dashboard-api/resources/account/{account}/energyService/{account}"
)

data = {}
try:
async with async_timeout.timeout(TIMEOUT):
response = await self.session.post(
URL_ENERGY_SERVICE.format(account=account), json=JSON
)
if response.status == 200:
rd = await response.json()
if "data" not in rd.keys():
return []

r = rd["data"]
hourlyUsage = []

# totalPowerUsage = 0
if (
"data" in rd.keys()
and "HourlyUsage" in rd["data"]
and "data" in rd["data"]["HourlyUsage"]
):
hourlyData = rd["data"]["HourlyUsage"]["data"]
for hourly in hourlyData:
hourlyUsage.append(
{
"usage": hourly["kwhUsed"]
if "kwhUsed" in hourly.keys()
else None,
"cost": hourly["billingCharged"]
if "billingCharged" in hourly.keys()
else None,
"temperature": hourly["temperature"]
if "temperature" in hourly.keys()
else None,
"netDelivered": hourly["netDelivered"]
if "netDelivered" in hourly.keys()
else 0,
"netReceived": hourly["netReceived"]
if "netReceived" in hourly.keys()
else 0,
"reading": hourly["reading"]
if "reading" in hourly.keys()
else 0,
"kwhActual": hourly["kwhActual"]
if "kwhActual" in hourly.keys()
else 0,
"readTime": datetime.fromisoformat(
hourly[
"readTime"
] # 2022-02-25T00:00:00.000-05:00
),
}
)

data["hourly_usage"] = hourlyUsage
except Exception as e:
_LOGGER.error(e)

return data

async def __getDataFromApplianceUsage(self, account, lastBilledDate) -> dict:
"""get data from appliance usage"""
_LOGGER.info("Getting appliance usage data")
Expand Down
10 changes: 10 additions & 0 deletions custom_components/fpl/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@
from homeassistant.core import Config, HomeAssistant
from homeassistant.config_entries import ConfigEntry
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.util import Throttle
from homeassistant.const import CONF_USERNAME, CONF_PASSWORD

from .fplapi import FplApi
from .const import (
DOMAIN,
DOMAIN_DATA,
NAME,
PLATFORMS,
STARTUP_MESSAGE,
)
Expand All @@ -25,6 +27,14 @@

_LOGGER = logging.getLogger(__package__)

def get_device_info():
return DeviceInfo(
identifiers={
("id", NAME),
},
name=NAME,
manufacturer=NAME,
)

class FplData:
"""This class handle communication and stores the data."""
Expand Down
18 changes: 18 additions & 0 deletions custom_components/fpl/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,16 @@
FplDailyUsageSensor,
FplDailyDeliveredKWHSensor,
FplDailyReceivedKWHSensor,
FplDailyDeliveredReading,
FplDailyReceivedReading,
)
#from .sensor_HourlyUsageSensor import (
# FplHourlyUsageSensor,
# FplHourlyUsageKWHSensor,
# FplHourlyReceivedKWHSensor,
# FplHourlyDeliveredKWHSensor,
# FplHourlyReadingKWHSensor
#)

from .sensor_BalanceSensor import BalanceSensor

Expand Down Expand Up @@ -85,6 +94,15 @@ def registerSensor(sensor, regions):
registerSensor(NetDeliveredKWHSensor, ONLY_MAINREGION)
registerSensor(FplDailyReceivedKWHSensor, ONLY_MAINREGION)
registerSensor(FplDailyDeliveredKWHSensor, ONLY_MAINREGION)
registerSensor(FplDailyDeliveredReading, ONLY_MAINREGION)
registerSensor(FplDailyReceivedReading, ONLY_MAINREGION)

#hourly sensors
# registerSensor(FplHourlyUsageSensor, ONLY_MAINREGION)
# registerSensor(FplHourlyUsageKWHSensor, ONLY_MAINREGION)
# registerSensor(FplHourlyReceivedKWHSensor, ONLY_MAINREGION)
# registerSensor(FplHourlyDeliveredKWHSensor, ONLY_MAINREGION)
# registerSensor(FplHourlyReadingKWHSensor, ONLY_MAINREGION)

# Balance sensors
registerSensor(BalanceSensor, ONLY_MAINREGION)
Expand Down
68 changes: 65 additions & 3 deletions custom_components/fpl/sensor_DailyUsageSensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from datetime import timedelta, datetime
from homeassistant.components.sensor import (
STATE_CLASS_TOTAL_INCREASING,
STATE_CLASS_TOTAL,
DEVICE_CLASS_ENERGY,
)
from .fplEntity import FplEnergyEntity, FplMoneyEntity
Expand Down Expand Up @@ -39,7 +40,7 @@ class FplDailyUsageKWHSensor(FplEnergyEntity):
def __init__(self, coordinator, config, account):
super().__init__(coordinator, config, account, "Daily Usage KWH")

_attr_state_class = STATE_CLASS_TOTAL_INCREASING
_attr_state_class = STATE_CLASS_TOTAL
_attr_device_class = DEVICE_CLASS_ENERGY

@property
Expand Down Expand Up @@ -81,7 +82,8 @@ class FplDailyReceivedKWHSensor(FplEnergyEntity):
def __init__(self, coordinator, config, account):
super().__init__(coordinator, config, account, "Daily Received KWH")

# _attr_state_class = STATE_CLASS_TOTAL_INCREASING
_attr_state_class = STATE_CLASS_TOTAL
_attr_device_class = DEVICE_CLASS_ENERGY

@property
def native_value(self):
Expand All @@ -92,6 +94,17 @@ def native_value(self):

return self._attr_native_value

@property
def last_reset(self) -> datetime | None:
data = self.getData("daily_usage")
if data is not None and len(data) > 0 and "netReceivedKwh" in data[-1].keys():
date = data[-1]["readTime"]
_attr_last_reset = date - timedelta(days=1)
else:
_attr_last_reset = None

return _attr_last_reset

def customAttributes(self):
"""Return the state attributes."""
data = self.getData("daily_usage")
Expand All @@ -108,7 +121,8 @@ def customAttributes(self):
class FplDailyDeliveredKWHSensor(FplEnergyEntity):
"""daily delivered Kwh sensor"""

# _attr_state_class = STATE_CLASS_TOTAL_INCREASING
_attr_state_class = STATE_CLASS_TOTAL
_attr_device_class = DEVICE_CLASS_ENERGY

def __init__(self, coordinator, config, account):
super().__init__(coordinator, config, account, "Daily Delivered KWH")
Expand All @@ -121,6 +135,17 @@ def native_value(self):
self._attr_native_value = data[-1]["netDeliveredKwh"]

return self._attr_native_value

@property
def last_reset(self) -> datetime | None:
data = self.getData("daily_usage")
if data is not None and len(data) > 0 and "netDeliveredKwh" in data[-1].keys():
date = data[-1]["readTime"]
_attr_last_reset = date - timedelta(days=1)
else:
_attr_last_reset = None

return _attr_last_reset

def customAttributes(self):
"""Return the state attributes."""
Expand All @@ -132,3 +157,40 @@ def customAttributes(self):
attributes["date"] = date
# attributes["last_reset"] = last_reset
return attributes

#jf changes below
class FplDailyReceivedReading(FplEnergyEntity):
"""daily received reading"""

_attr_state_class = STATE_CLASS_TOTAL_INCREASING
_attr_device_class = DEVICE_CLASS_ENERGY

def __init__(self, coordinator, config, account):
super().__init__(coordinator, config, account, "Daily Received reading")

@property
def native_value(self):
data = self.getData("daily_usage")

if data is not None and len(data) > 0 and "netReceivedReading" in data[-1].keys():
self._attr_native_value = data[-1]["netReceivedReading"]

return self._attr_native_value

class FplDailyDeliveredReading(FplEnergyEntity):
"""daily delivered reading"""

_attr_state_class = STATE_CLASS_TOTAL_INCREASING
_attr_device_class = DEVICE_CLASS_ENERGY

def __init__(self, coordinator, config, account):
super().__init__(coordinator, config, account, "Daily Delivered reading")

@property
def native_value(self):
data = self.getData("daily_usage")

if data is not None and len(data) > 0 and "netDeliveredReading" in data[-1].keys():
self._attr_native_value = data[-1]["netDeliveredReading"]

return self._attr_native_value
Loading
Loading