69 lines
2.3 KiB
Python
69 lines
2.3 KiB
Python
DOMAIN = "easee_solar_charging"
|
||
|
||
CONF_CHARGER_ID = "charger_id"
|
||
CONF_DEVICE_ID = "device_id"
|
||
CONF_SITE_ID = "site_id"
|
||
CONF_SOLAR_PRODUCTION_SENSOR = "solar_production_sensor"
|
||
CONF_HOUSE_LOAD_SENSOR = "house_load_sensor"
|
||
CONF_EV_CHARGING_SENSOR = "ev_charging_sensor"
|
||
|
||
ROLLING_AVERAGE_SECONDS = 30
|
||
|
||
EASEE_DOMAIN = "easee"
|
||
EASEE_SERVICE_SET_DYNAMIC_LIMIT = "set_charger_dynamic_limit"
|
||
EASEE_CONTROLLABLE_STATES = {"awaiting_start", "ready_to_charge", "charging"}
|
||
# States where the session is finished/sleeping: set current to 0 once, then idle.
|
||
EASEE_SLEEPING_STATES = {"completed", "awaiting_authorization", "awaiting_schedule"}
|
||
|
||
DEFAULT_SCAN_INTERVAL = 30 # seconds
|
||
|
||
# Charging current constraints
|
||
VOLTAGE_V = 230
|
||
PHASES = 3
|
||
MIN_CHARGER_CURRENT_A = 6
|
||
MAX_CHARGER_CURRENT_A = 16
|
||
|
||
# Hysteresis
|
||
HYSTERESIS_A = 2 # dead-band within the charging range (fixed)
|
||
|
||
CONF_STOP_GRACE_MINUTES = "stop_grace_minutes"
|
||
DEFAULT_STOP_GRACE_MINUTES = 5
|
||
|
||
CONF_CHARGING_PROFILE = "charging_profile"
|
||
CHARGING_PROFILE_CONSERVATIVE = "conservative"
|
||
CHARGING_PROFILE_ALL_SURPLUS = "all_surplus"
|
||
CHARGING_PROFILE_FORECAST = "forecast"
|
||
CHARGING_PROFILE_FORECAST_CONSERVATIVE = "forecast_conservative"
|
||
DEFAULT_CHARGING_PROFILE = CHARGING_PROFILE_CONSERVATIVE
|
||
|
||
# Forecast profile settings
|
||
CONF_FORECAST_SENSOR = "forecast_sensor"
|
||
CONF_FORECAST_CONFIDENCE = "forecast_confidence" # percent, 0-100
|
||
CONF_FORECAST_LOOKAHEAD_MINUTES = "forecast_lookahead_minutes"
|
||
|
||
DEFAULT_FORECAST_CONFIDENCE = 80 # percent
|
||
DEFAULT_FORECAST_LOOKAHEAD_MINUTES = 30
|
||
|
||
CONF_DEAD_BAND_RESYNC_MINUTES = "dead_band_resync_minutes"
|
||
DEFAULT_DEAD_BAND_RESYNC_MINUTES = 1
|
||
|
||
CONF_NOTIFY_TARGET = "notify_target"
|
||
|
||
# Watts available at each valid current step on a 3-phase 230V system (P = 3 × V × I)
|
||
AMPS_TO_POWER_W: dict[int, int] = {
|
||
a: PHASES * VOLTAGE_V * a
|
||
for a in range(MIN_CHARGER_CURRENT_A, MAX_CHARGER_CURRENT_A + 1)
|
||
}
|
||
|
||
|
||
def solar_excess_to_charger_current(excess_w: float) -> int:
|
||
"""Return the highest valid charger current (A) that fits within excess_w.
|
||
|
||
Returns 0 if excess is below the minimum charging threshold (6 A).
|
||
Steps are 1 A increments between 6 A and 16 A on a 3-phase 230 V system.
|
||
"""
|
||
amps = int(excess_w / (PHASES * VOLTAGE_V))
|
||
if amps < MIN_CHARGER_CURRENT_A:
|
||
return 0
|
||
return min(amps, MAX_CHARGER_CURRENT_A)
|