@@ -307,6 +307,89 @@ async def set_component_power_active( # noqa: DOC502 (raises ApiClientError ind
307307
308308 return None
309309
310+ async def set_component_power_reactive ( # noqa: DOC502 (raises ApiClientError indirectly)
311+ self ,
312+ component : ComponentId | Component ,
313+ power : float ,
314+ * ,
315+ request_lifetime : timedelta | None = None ,
316+ validate_arguments : bool = True ,
317+ ) -> datetime | None :
318+ """Set the reactive power output of a component.
319+
320+ We follow the polarity specified in the IEEE 1459-2010 standard
321+ definitions, where:
322+
323+ - Positive reactive is inductive (current is lagging the voltage)
324+ - Negative reactive is capacitive (current is leading the voltage)
325+
326+ The power output is specified in VAr.
327+
328+ The return value is the timestamp until which the given power command will
329+ stay in effect. After this timestamp, the component's reactive power will
330+ be set to 0, if the API receives no further command to change it before
331+ then. By default, this timestamp will be set to the current time plus 60
332+ seconds.
333+
334+ Note:
335+ The target component may have a resolution of more than 1 VAr. E.g., an
336+ inverter may have a resolution of 88 VAr. In such cases, the magnitude of
337+ power will be floored to the nearest multiple of the resolution.
338+
339+ Performs the following sequence actions for the following component
340+ categories:
341+
342+ * TODO document missing.
343+
344+ Args:
345+ component: The component to set the output reactive power of.
346+ power: The output reactive power level, in VAr. The standard of polarity is
347+ as per the IEEE 1459-2010 standard definitions: positive reactive is
348+ inductive (current is lagging the voltage); negative reactive is
349+ capacitive (current is leading the voltage).
350+ request_lifetime: The duration, until which the request will stay in effect.
351+ This duration has to be between 10 seconds and 15 minutes (including
352+ both limits), otherwise the request will be rejected. It has
353+ a resolution of a second, so fractions of a second will be rounded for
354+ `timedelta` objects, and it is interpreted as seconds for `int` objects.
355+ If not provided, it usually defaults to 60 seconds.
356+ validate_arguments: Whether to validate the arguments before sending the
357+ request. If `True` a `ValueError` will be raised if an argument is
358+ invalid without even sending the request to the server, if `False`, the
359+ request will be sent without validation.
360+
361+ Returns:
362+ The timestamp until which the given power command will stay in effect, or
363+ `None` if it was not provided by the server.
364+
365+ Raises:
366+ ApiClientError: If the are any errors communicating with the Microgrid API,
367+ most likely a subclass of
368+ [GrpcError][frequenz.client.microgrid.GrpcError].
369+ """
370+ lifetime_seconds = _delta_to_seconds (request_lifetime )
371+
372+ if validate_arguments :
373+ _validate_set_power_args (power = power , request_lifetime = lifetime_seconds )
374+
375+ response = await client .call_stub_method (
376+ self ,
377+ lambda : self ._async_stub .SetComponentPowerReactive (
378+ microgrid_pb2 .SetComponentPowerReactiveRequest (
379+ component_id = _get_component_id (component ),
380+ power = power ,
381+ request_lifetime = lifetime_seconds ,
382+ ),
383+ timeout = int (DEFAULT_GRPC_CALL_TIMEOUT ),
384+ ),
385+ method_name = "SetComponentPowerReactive" ,
386+ )
387+
388+ if response .HasField ("valid_until" ):
389+ return conversion .to_datetime (response .valid_until )
390+
391+ return None
392+
310393
311394def _get_component_id (component : ComponentId | Component ) -> int :
312395 """Get the component ID from a component or component ID."""
0 commit comments