mirror of
https://github.com/Akkudoktor-EOS/EOS.git
synced 2026-03-16 03:26:18 +00:00
fix: energy charts bidding zone in request (#948)
Some checks are pending
Bump Version / Bump Version Workflow (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (python) (push) Waiting to run
docker-build / platform-excludes (push) Waiting to run
docker-build / build (push) Blocked by required conditions
docker-build / merge (push) Blocked by required conditions
pre-commit / pre-commit (push) Waiting to run
Run Pytest on Pull Request / test (push) Waiting to run
Some checks are pending
Bump Version / Bump Version Workflow (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (python) (push) Waiting to run
docker-build / platform-excludes (push) Waiting to run
docker-build / build (push) Blocked by required conditions
docker-build / merge (push) Blocked by required conditions
pre-commit / pre-commit (push) Waiting to run
Run Pytest on Pull Request / test (push) Waiting to run
Ensure that the bidding zone in the request is correctly set to a string value (not an enum). This seems to be also an issue with python version < 3.11. Add safeguards to only use python >= 3.11. Still keep a regression test for the enum conversion to string. Signed-off-by: Bobby Noelte <b0661n0e17e@gmail.com>
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
import sys
|
||||
|
||||
MIN_VERSION = (3, 11)
|
||||
|
||||
if sys.version_info < MIN_VERSION:
|
||||
min_version = ".".join(map(str, MIN_VERSION))
|
||||
raise RuntimeError(
|
||||
f"EOS requires Python {min_version} or newer. "
|
||||
f"Current version: {sys.version.split()[0]}. "
|
||||
f"Please upgrade your Python installation or Home Assistant."
|
||||
)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import calendar
|
||||
import os
|
||||
import sys
|
||||
from typing import Any, ClassVar, Iterator, Optional, Union
|
||||
|
||||
import numpy as np
|
||||
@@ -27,6 +28,28 @@ def is_home_assistant_addon() -> bool:
|
||||
return "HASSIO_TOKEN" in os.environ or "SUPERVISOR_TOKEN" in os.environ
|
||||
|
||||
|
||||
def runtime_environment() -> str:
|
||||
"""Return a human-readable description of the runtime environment."""
|
||||
python_version = sys.version.split()[0]
|
||||
|
||||
# Home Assistant add-on
|
||||
if is_home_assistant_addon():
|
||||
ha_version = os.getenv("HOMEASSISTANT_VERSION", "unknown")
|
||||
return f"Home Assistant add-on (HA {ha_version}, Python {python_version})"
|
||||
|
||||
# Home Assistant Core integration
|
||||
if "HOMEASSISTANT_CONFIG" in os.environ:
|
||||
ha_version = os.getenv("HOMEASSISTANT_VERSION", "unknown")
|
||||
return f"Home Assistant Core (HA {ha_version}, Python {python_version})"
|
||||
|
||||
# Docker container
|
||||
if os.path.exists("/.dockerenv"):
|
||||
return f"Docker container (Python {python_version})"
|
||||
|
||||
# Default
|
||||
return f"Standalone Python (Python {python_version})"
|
||||
|
||||
|
||||
class SettingsBaseModel(PydanticBaseModel):
|
||||
"""Base model class for all settings configurations."""
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ Demand Driven Based Control.
|
||||
import uuid
|
||||
from abc import ABC, abstractmethod
|
||||
from collections import defaultdict
|
||||
from enum import Enum
|
||||
from enum import StrEnum
|
||||
from typing import Annotated, Literal, Optional, Union
|
||||
|
||||
from loguru import logger
|
||||
@@ -35,7 +35,7 @@ ID = str
|
||||
# S2 Enumerations
|
||||
|
||||
|
||||
class RoleType(str, Enum):
|
||||
class RoleType(StrEnum):
|
||||
"""Enumeration of energy resource roles in the system."""
|
||||
|
||||
ENERGY_PRODUCER = "ENERGY_PRODUCER"
|
||||
@@ -43,7 +43,7 @@ class RoleType(str, Enum):
|
||||
ENERGY_STORAGE = "ENERGY_STORAGE"
|
||||
|
||||
|
||||
class Commodity(str, Enum):
|
||||
class Commodity(StrEnum):
|
||||
"""Enumeration of energy commodities supported in the system."""
|
||||
|
||||
GAS = "GAS"
|
||||
@@ -52,7 +52,7 @@ class Commodity(str, Enum):
|
||||
OIL = "OIL"
|
||||
|
||||
|
||||
class CommodityQuantity(str, Enum):
|
||||
class CommodityQuantity(StrEnum):
|
||||
"""Enumeration of specific commodity quantities and measurement types."""
|
||||
|
||||
ELECTRIC_POWER_L1 = "ELECTRIC.POWER.L1"
|
||||
@@ -89,7 +89,7 @@ class CommodityQuantity(str, Enum):
|
||||
"""Currency-related quantity."""
|
||||
|
||||
|
||||
class Currency(str, Enum):
|
||||
class Currency(StrEnum):
|
||||
"""Enumeration of currency codes following ISO 4217 standard."""
|
||||
|
||||
AED = "AED"
|
||||
@@ -255,7 +255,7 @@ class Currency(str, Enum):
|
||||
ZWL = "ZWL"
|
||||
|
||||
|
||||
class InstructionStatus(str, Enum):
|
||||
class InstructionStatus(StrEnum):
|
||||
"""Enumeration of possible instruction status values."""
|
||||
|
||||
NEW = "NEW" # Instruction was newly created
|
||||
@@ -267,7 +267,7 @@ class InstructionStatus(str, Enum):
|
||||
ABORTED = "ABORTED" # Instruction was aborted
|
||||
|
||||
|
||||
class ControlType(str, Enum):
|
||||
class ControlType(StrEnum):
|
||||
"""Enumeration of different control types supported by the system."""
|
||||
|
||||
POWER_ENVELOPE_BASED_CONTROL = (
|
||||
@@ -289,28 +289,28 @@ class ControlType(str, Enum):
|
||||
NO_SELECTION = "NO_SELECTION" # Used if no control type is/has been selected
|
||||
|
||||
|
||||
class PEBCPowerEnvelopeLimitType(str, Enum):
|
||||
class PEBCPowerEnvelopeLimitType(StrEnum):
|
||||
"""Enumeration of power envelope limit types for Power Envelope Based Control."""
|
||||
|
||||
UPPER_LIMIT = "UPPER_LIMIT" # Indicates the upper limit of a Power Envelope
|
||||
LOWER_LIMIT = "LOWER_LIMIT" # Indicates the lower limit of a Power Envelope
|
||||
|
||||
|
||||
class PEBCPowerEnvelopeConsequenceType(str, Enum):
|
||||
class PEBCPowerEnvelopeConsequenceType(StrEnum):
|
||||
"""Enumeration of consequences when power is limited for Power Envelope Based Control."""
|
||||
|
||||
VANISH = "VANISH" # Limited load or generation will be lost and not reappear
|
||||
DEFER = "DEFER" # Limited load or generation will be postponed to a later moment
|
||||
|
||||
|
||||
class ReceptionStatusValues(str, Enum):
|
||||
class ReceptionStatusValues(StrEnum):
|
||||
"""Enumeration of status values for data reception."""
|
||||
|
||||
SUCCEEDED = "SUCCEEDED" # Data received, complete, and consistent
|
||||
REJECTED = "REJECTED" # Data could not be parsed or was incomplete/inconsistent
|
||||
|
||||
|
||||
class PPBCPowerSequenceStatus(str, Enum):
|
||||
class PPBCPowerSequenceStatus(StrEnum):
|
||||
"""Enumeration of status values for Power Profile Based Control sequences."""
|
||||
|
||||
NOT_SCHEDULED = "NOT_SCHEDULED" # No PowerSequence is scheduled
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import traceback
|
||||
from asyncio import Lock, get_running_loop
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from enum import Enum
|
||||
from enum import StrEnum
|
||||
from functools import partial
|
||||
from typing import ClassVar, Optional
|
||||
|
||||
@@ -30,7 +30,7 @@ from akkudoktoreos.utils.datetimeutil import DateTime, to_datetime
|
||||
executor = ThreadPoolExecutor(max_workers=1)
|
||||
|
||||
|
||||
class EnergyManagementStage(Enum):
|
||||
class EnergyManagementStage(StrEnum):
|
||||
"""Enumeration of the main stages in the energy management lifecycle."""
|
||||
|
||||
IDLE = "IDLE"
|
||||
@@ -39,10 +39,6 @@ class EnergyManagementStage(Enum):
|
||||
OPTIMIZATION = "OPTIMIZATION"
|
||||
CONTROL_DISPATCH = "CONTROL_DISPATCH"
|
||||
|
||||
def __str__(self) -> str:
|
||||
"""Return the string representation of the stage."""
|
||||
return self.value
|
||||
|
||||
|
||||
async def ems_manage_energy() -> None:
|
||||
"""Repeating task for managing energy.
|
||||
@@ -193,7 +189,7 @@ class EnergyManagement(
|
||||
None
|
||||
"""
|
||||
# Ensure there is only one optimization/ energy management run at a time
|
||||
if not EnergyManagementMode.is_valid(mode):
|
||||
if not mode in EnergyManagementMode._value2member_map_:
|
||||
raise ValueError(f"Unknown energy management mode {mode}.")
|
||||
if mode == EnergyManagementMode.DISABLED:
|
||||
return
|
||||
|
||||
@@ -3,38 +3,20 @@
|
||||
Kept in an extra module to avoid cyclic dependencies on package import.
|
||||
"""
|
||||
|
||||
from enum import Enum
|
||||
from typing import Optional, Union
|
||||
from enum import StrEnum
|
||||
|
||||
from pydantic import Field
|
||||
|
||||
from akkudoktoreos.config.configabc import SettingsBaseModel, is_home_assistant_addon
|
||||
|
||||
|
||||
class EnergyManagementMode(str, Enum):
|
||||
class EnergyManagementMode(StrEnum):
|
||||
"""Energy management mode."""
|
||||
|
||||
DISABLED = "DISABLED"
|
||||
PREDICTION = "PREDICTION"
|
||||
OPTIMIZATION = "OPTIMIZATION"
|
||||
|
||||
@classmethod
|
||||
def is_valid(cls, mode: Union[str, "EnergyManagementMode"]) -> bool:
|
||||
"""Check if value is a valid mode."""
|
||||
try:
|
||||
cls(mode)
|
||||
return True
|
||||
except (ValueError, TypeError):
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def from_value(cls, value: str) -> Optional["EnergyManagementMode"]:
|
||||
"""Safely convert string to enum, return None if invalid."""
|
||||
try:
|
||||
return cls(value)
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
|
||||
def ems_default_mode() -> EnergyManagementMode:
|
||||
"""Provide default EMS mode.
|
||||
|
||||
@@ -7,7 +7,7 @@ format, enabling consistent access to forecasted and historical electricity pric
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
from enum import Enum
|
||||
from enum import StrEnum
|
||||
from typing import Any, List, Optional, Union
|
||||
|
||||
import numpy as np
|
||||
@@ -24,7 +24,7 @@ from akkudoktoreos.prediction.elecpriceabc import ElecPriceProvider
|
||||
from akkudoktoreos.utils.datetimeutil import to_datetime, to_duration
|
||||
|
||||
|
||||
class EnergyChartsBiddingZones(str, Enum):
|
||||
class EnergyChartsBiddingZones(StrEnum):
|
||||
"""Energy Charts Bidding Zones."""
|
||||
|
||||
AT = "AT"
|
||||
|
||||
@@ -2,6 +2,7 @@ from typing import Any
|
||||
|
||||
from fasthtml.common import Div
|
||||
|
||||
from akkudoktoreos.config.configabc import runtime_environment
|
||||
from akkudoktoreos.core.version import __version__
|
||||
from akkudoktoreos.server.dash.markdown import Markdown
|
||||
|
||||
@@ -23,7 +24,9 @@ Documentation can be found at [Akkudoktor-EOS](https://akkudoktor-eos.readthedoc
|
||||
|
||||
## Version Information
|
||||
|
||||
**Current Version:** {__version__}
|
||||
**Akkudoktor-EOS:** {__version__}
|
||||
|
||||
**Environment:** {runtime_environment()}
|
||||
|
||||
**License:** Apache License
|
||||
|
||||
|
||||
Reference in New Issue
Block a user