Skip to content

Commit

Permalink
Add OVO Plan API (#70)
Browse files Browse the repository at this point in the history
  • Loading branch information
timmo001 committed Nov 14, 2022
1 parent 0340320 commit 5159c55
Show file tree
Hide file tree
Showing 5 changed files with 198 additions and 80 deletions.
78 changes: 0 additions & 78 deletions ovoenergy/__init__.py
Original file line number Diff line number Diff line change
@@ -1,80 +1,2 @@
"""Initialize the package."""
from __future__ import annotations

from datetime import datetime
from typing import Optional

from pydantic import BaseModel, Extra, Field # pylint: disable=no-name-in-module


class OVOBase(BaseModel):
"""Base class for all OVO models."""

class Config:
"""Pydantic config."""

extra = Extra.allow


class OVOInterval(OVOBase):
"""Interval model."""

start: datetime = Field(..., alias="start")
end: datetime = Field(..., alias="end")


class OVOMeterReadings(OVOBase):
"""Meter readings model."""

start: float = Field(..., alias="start")
end: float = Field(..., alias="end")


class OVOCost(OVOBase):
"""Cost model."""

amount: Optional[float] = Field(None, alias="amount")
currency_unit: Optional[str] = Field(None, alias="currencyUnit")


class OVODailyElectricity(OVOBase):
"""Daily electricity model."""

consumption: Optional[float] = Field(None, alias="consumption")
interval: Optional[OVOInterval] = Field(None, alias="interval")
meter_readings: Optional[OVOMeterReadings] = Field(None, alias="meterReadings")
has_half_hour_data: Optional[bool] = Field(None, alias="hasHalfHourData")
cost: Optional[OVOCost] = Field(None, alias="cost")


class OVODailyGas(OVOBase):
"""Daily gas model."""

consumption: Optional[float] = Field(None, alias="consumption")
volume: Optional[float] = Field(None, alias="volume")
interval: Optional[OVOInterval] = Field(None, alias="interval")
meter_readings: Optional[OVOMeterReadings] = Field(None, alias="meterReadings")
has_half_hour_data: Optional[bool] = Field(None, alias="hasHalfHourData")
cost: Optional[OVOCost] = Field(None, alias="cost")


class OVOHalfHour(OVOBase):
"""Half hour model."""

consumption: float = Field(None, alias="consumption")
interval: OVOInterval = Field(None, alias="interval")
unit: str = Field(None, alias="unit")


class OVODailyUsage(OVOBase):
"""Daily usage model."""

electricity: Optional[list[OVODailyElectricity]] = Field(None, alias="electricity")
gas: Optional[list[OVODailyGas]] = Field(None, alias="gas")


class OVOHalfHourUsage(OVOBase):
"""Half hour usage model."""

electricity: Optional[list[OVOHalfHour]] = Field(None, alias="electricity")
gas: Optional[list[OVOHalfHour]] = Field(None, alias="gas")
25 changes: 24 additions & 1 deletion ovoenergy/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@

import typer

from . import OVODailyUsage, OVOHalfHourUsage
from ._version import __version__
from .models import OVODailyUsage, OVOHalfHourUsage
from .models.plan import OVOPlan
from .ovoenergy import OVOEnergy

app = typer.Typer()
Expand Down Expand Up @@ -71,6 +72,28 @@ def half_hourly(
)


@app.command(name="plan", short_help="Get plan from OVO Energy")
def plan(
username: str = typer.Option(..., help="OVO Energy username"),
password: str = typer.Option(..., help="OVO Energy password"),
account: str = typer.Option(None, help="OVO Energy account number"),
) -> None:
"""Get rates from OVO Energy."""
ovo_plan: Optional[OVOPlan] = None

client = OVOEnergy()
authenticated = loop.run_until_complete(
client.authenticate(username, password, account)
)
if authenticated:
ovo_plan = loop.run_until_complete(client.get_plan())

typer.secho(
ovo_plan.json() if ovo_plan is not None else '{"message": "No data"}',
fg=typer.colors.GREEN,
)


@app.command(name="version", short_help="Module Version")
def version() -> None:
"""Module Version"""
Expand Down
88 changes: 88 additions & 0 deletions ovoenergy/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
"""OVO Energy: Models."""
from __future__ import annotations

from datetime import datetime
from typing import Optional

from pydantic import BaseModel, Extra, Field # pylint: disable=no-name-in-module


class OVOBase(BaseModel):
"""Base class for all OVO models."""

class Config:
"""Pydantic config."""

extra = Extra.allow


class OVOInterval(OVOBase):
"""Interval model."""

start: datetime = Field(None, alias="start")
end: datetime = Field(None, alias="end")


class OVOMeterReadings(OVOBase):
"""Meter readings model."""

start: float = Field(None, alias="start")
end: float = Field(None, alias="end")


class OVOCost(OVOBase):
"""Cost model."""

amount: Optional[float] = Field(None, alias="amount")
currency_unit: Optional[str] = Field(None, alias="currencyUnit")


class OVODailyElectricity(OVOBase):
"""Daily electricity model."""

consumption: Optional[float] = Field(None, alias="consumption")
interval: Optional[OVOInterval] = Field(None, alias="interval")
meter_readings: Optional[OVOMeterReadings] = Field(None, alias="meterReadings")
has_half_hour_data: Optional[bool] = Field(None, alias="hasHalfHourData")
cost: Optional[OVOCost] = Field(None, alias="cost")


class OVODailyGas(OVOBase):
"""Daily gas model."""

consumption: Optional[float] = Field(None, alias="consumption")
volume: Optional[float] = Field(None, alias="volume")
interval: Optional[OVOInterval] = Field(None, alias="interval")
meter_readings: Optional[OVOMeterReadings] = Field(None, alias="meterReadings")
has_half_hour_data: Optional[bool] = Field(None, alias="hasHalfHourData")
cost: Optional[OVOCost] = Field(None, alias="cost")


class OVOHalfHour(OVOBase):
"""Half hour model."""

consumption: float = Field(None, alias="consumption")
interval: OVOInterval = Field(None, alias="interval")
unit: str = Field(None, alias="unit")


class OVODailyUsage(OVOBase):
"""Daily usage model."""

electricity: Optional[list[OVODailyElectricity]] = Field(None, alias="electricity")
gas: Optional[list[OVODailyGas]] = Field(None, alias="gas")


class OVOHalfHourUsage(OVOBase):
"""Half hour usage model."""

electricity: Optional[list[OVOHalfHour]] = Field(None, alias="electricity")
gas: Optional[list[OVOHalfHour]] = Field(None, alias="gas")


class OVOPlan(OVOBase):
"""Plan model."""

standing_charge: Optional[float] = Field(None, alias="standingCharge")
unit_rate: Optional[float] = Field(None, alias="unitRate")
tariff: Optional[str] = Field(None, alias="tariff")
73 changes: 73 additions & 0 deletions ovoenergy/models/plan.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
"""OVO Energy: Plan Models."""
from __future__ import annotations

from typing import Any

from pydantic import Field

from . import OVOBase


class OVOPlanRate(OVOBase):
"""Plan rate model."""

amount: float = Field(None, alias="amount")
currency_unit: str = Field(None, alias="currencyUnit")


class OVOPlanStatus(OVOBase):
"""Plan status model."""

active: bool
in_renewal: bool = Field(None, alias="inRenewal")
in_loss: bool = Field(None, alias="inLoss")
loss_complete: bool = Field(None, alias="lossComplete")
has_future_contracts: bool = Field(None, alias="hasFutureContracts")


class OVOPlanUnitRate(OVOBase):
"""Unit rate model."""

name: str = Field(None, alias="name")
unit_rate: OVOPlanRate = Field(None, alias="unitRate")


class OVOPlanElectricity(OVOBase):
"""Plan electricity model."""

name: str = Field(None, alias="name")
exit_fee: OVOPlanRate = Field(None, alias="exitFee")
contract_start_date: str = Field(None, alias="contractStartDate")
contract_end_date: Any = Field(None, alias="contractEndDate")
contract_type: str = Field(None, alias="contractType")
is_in_renewal: bool = Field(None, alias="isInRenewal")
has_future_contracts: bool = Field(None, alias="hasFutureContracts")
mpxn: str = Field(None, alias="mpxn")
msn: str = Field(None, alias="msn")
personal_projection: float = Field(None, alias="personalProjection")
standing_charge: OVOPlanRate = Field(None, alias="standingCharge")
unit_rates: list[OVOPlanUnitRate] = Field(None, alias="unitRates")


class OVOPlanGas(OVOBase):
"""Plan gas model."""

name: str = Field(None, alias="name")
exit_fee: OVOPlanRate = Field(None, alias="exitFee")
contract_start_date: str = Field(None, alias="contractStartDate")
contract_end_date: Any = Field(None, alias="contractEndDate")
contract_type: str = Field(None, alias="contractType")
is_in_renewal: bool = Field(None, alias="isInRenewal")
has_future_contracts: bool = Field(None, alias="hasFutureContracts")
mpxn: str = Field(None, alias="mpxn")
msn: str = Field(None, alias="msn")
personal_projection: float = Field(None, alias="personalProjection")
standing_charge: OVOPlanRate = Field(None, alias="standingCharge")
unit_rates: list[OVOPlanUnitRate] = Field(None, alias="unitRates")


class OVOPlan(OVOBase):
"""Plan model."""

electricity: OVOPlanElectricity = Field(None, alias="electricity")
gas: OVOPlanGas = Field(None, alias="gas")
14 changes: 13 additions & 1 deletion ovoenergy/ovoenergy.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@

import aiohttp

from ovoenergy import (
from .models import (
OVODailyElectricity,
OVODailyGas,
OVODailyUsage,
OVOHalfHour,
OVOHalfHourUsage,
)
from .models.plan import OVOPlan


class OVOEnergy:
Expand Down Expand Up @@ -170,3 +171,14 @@ async def get_half_hourly_usage(
ovo_usage.gas.append(OVOHalfHour(**usage))

return ovo_usage

async def get_plan(self) -> OVOPlan:
"""Get plan."""
async with aiohttp.ClientSession() as session:
response = await session.get(
f"https://smartpaymapi.ovoenergy.com/orex/api/plans/{self._account_id}",
cookies=self._cookies,
)
json_response = await response.json()

return OVOPlan(**json_response)

0 comments on commit 5159c55

Please sign in to comment.