66
77from asyncio import Task , create_task , gather , sleep
88from collections .abc import Callable , Coroutine
9- from datetime import datetime , timedelta
9+ from datetime import UTC , datetime , timedelta
1010import logging
1111from typing import Any
1212
1313from ..api import NodeEvent , NodeType , PlugwiseNode , StickEvent
1414from ..connection import StickController
15- from ..constants import UTF8
15+ from ..constants import ENERGY_NODE_TYPES , UTF8
1616from ..exceptions import CacheError , MessageError , NodeError , StickError , StickTimeout
17+ from ..helpers .util import validate_mac
1718from ..messages .requests import (
18- CirclePlusAllowJoiningRequest ,
19+ CircleClockSetRequest ,
1920 CircleMeasureIntervalRequest ,
21+ CirclePlusAllowJoiningRequest ,
2022 NodePingRequest ,
2123)
2224from ..messages .responses import (
@@ -541,6 +543,25 @@ async def allow_join_requests(self, state: bool) -> None:
541543 _LOGGER .debug ("Sent AllowJoiningRequest to Circle+ with state=%s" , state )
542544 self .accept_join_request = state
543545
546+ async def energy_reset_request (self , mac : str ) -> None :
547+ """Send an energy-reset to a Node."""
548+ self ._validate_energy_node (mac )
549+ node_protocols = self ._nodes [mac ].node_protocols
550+ request = CircleClockSetRequest (
551+ self ._controller .send ,
552+ bytes (mac , UTF8 ),
553+ datetime .now (tz = UTC ),
554+ node_protocols .max ,
555+ True ,
556+ )
557+ if (response := await request .send ()) is None :
558+ raise NodeError (f"Energy-reset for { mac } failed" )
559+
560+ if response .ack_id != NodeResponseType .CLOCK_ACCEPTED :
561+ raise MessageError (
562+ f"Unexpected NodeResponseType { response .ack_id !r} received as response to CircleClockSetRequest"
563+ )
564+
544565 async def set_energy_intervals (
545566 self , mac : str , consumption : int , production : int
546567 ) -> None :
@@ -549,7 +570,7 @@ async def set_energy_intervals(
549570 Default: consumption = 60, production = 0.
550571 For logging energy in both directions set both to 60.
551572 """
552- # Validate input parameters
573+ self . _validate_energy_node ( mac )
553574 if consumption <= 0 :
554575 raise ValueError ("Consumption interval must be positive" )
555576 if production < 0 :
@@ -569,6 +590,19 @@ async def set_energy_intervals(
569590 f"Unknown NodeResponseType '{ response .response_type .name } ' received"
570591 )
571592
593+ def _validate_energy_node (self , mac : str ) -> None :
594+ """Validate node for energy operations."""
595+ if not validate_mac (mac ):
596+ raise NodeError (f"MAC '{ mac } ' invalid" )
597+
598+ if mac not in self ._nodes :
599+ raise NodeError (f"Node { mac } not present in network" )
600+
601+ if self ._nodes [mac ].node_info .node_type .value not in ENERGY_NODE_TYPES :
602+ raise NodeError (
603+ f"Energy operations not supported for { self ._nodes [mac ].node_info .node_type .name } "
604+ )
605+
572606 def subscribe_to_node_events (
573607 self ,
574608 node_event_callback : Callable [[NodeEvent , str ], Coroutine [Any , Any , None ]],
0 commit comments