2021-11-11 12:20:16 +00:00
""" Common helpers for greeneye_monitor tests. """
from __future__ import annotations
from typing import Any
from unittest . mock import AsyncMock , MagicMock
from homeassistant . components . greeneye_monitor import (
CONF_CHANNELS ,
CONF_COUNTED_QUANTITY ,
CONF_COUNTED_QUANTITY_PER_PULSE ,
CONF_MONITORS ,
CONF_NET_METERING ,
CONF_NUMBER ,
CONF_PULSE_COUNTERS ,
CONF_SERIAL_NUMBER ,
CONF_TEMPERATURE_SENSORS ,
CONF_TIME_UNIT ,
CONF_VOLTAGE_SENSORS ,
DOMAIN ,
)
from homeassistant . const import (
CONF_NAME ,
CONF_PORT ,
CONF_SENSORS ,
CONF_TEMPERATURE_UNIT ,
)
from homeassistant . core import HomeAssistant
from homeassistant . helpers . typing import ConfigType
from homeassistant . setup import async_setup_component
SINGLE_MONITOR_SERIAL_NUMBER = 110011
def make_single_monitor_config_with_sensors ( sensors : dict [ str , Any ] ) - > dict [ str , Any ] :
""" Wrap the given sensor config in the boilerplate for a single monitor with serial number SINGLE_MONITOR_SERIAL_NUMBER. """
return {
DOMAIN : {
CONF_PORT : 7513 ,
CONF_MONITORS : [
{
CONF_SERIAL_NUMBER : f " 00 { SINGLE_MONITOR_SERIAL_NUMBER } " ,
* * sensors ,
}
] ,
}
}
SINGLE_MONITOR_CONFIG_NO_SENSORS = make_single_monitor_config_with_sensors ( { } )
SINGLE_MONITOR_CONFIG_PULSE_COUNTERS = make_single_monitor_config_with_sensors (
{
CONF_PULSE_COUNTERS : [
{
CONF_NUMBER : 1 ,
CONF_NAME : " pulse_a " ,
CONF_COUNTED_QUANTITY : " pulses " ,
CONF_COUNTED_QUANTITY_PER_PULSE : 1.0 ,
CONF_TIME_UNIT : " s " ,
} ,
{
CONF_NUMBER : 2 ,
CONF_NAME : " pulse_2 " ,
CONF_COUNTED_QUANTITY : " gal " ,
CONF_COUNTED_QUANTITY_PER_PULSE : 0.5 ,
CONF_TIME_UNIT : " min " ,
} ,
{
CONF_NUMBER : 3 ,
CONF_NAME : " pulse_3 " ,
CONF_COUNTED_QUANTITY : " gal " ,
CONF_COUNTED_QUANTITY_PER_PULSE : 0.5 ,
CONF_TIME_UNIT : " h " ,
} ,
{
CONF_NUMBER : 4 ,
CONF_NAME : " pulse_d " ,
CONF_COUNTED_QUANTITY : " pulses " ,
CONF_COUNTED_QUANTITY_PER_PULSE : 1.0 ,
CONF_TIME_UNIT : " s " ,
} ,
]
}
)
SINGLE_MONITOR_CONFIG_POWER_SENSORS = make_single_monitor_config_with_sensors (
{
CONF_CHANNELS : [
{
CONF_NUMBER : 1 ,
CONF_NAME : " channel 1 " ,
} ,
{
CONF_NUMBER : 2 ,
CONF_NAME : " channel two " ,
CONF_NET_METERING : True ,
} ,
]
}
)
SINGLE_MONITOR_CONFIG_TEMPERATURE_SENSORS = make_single_monitor_config_with_sensors (
{
CONF_TEMPERATURE_SENSORS : {
CONF_TEMPERATURE_UNIT : " F " ,
CONF_SENSORS : [
{ CONF_NUMBER : 1 , CONF_NAME : " temp_a " } ,
{ CONF_NUMBER : 2 , CONF_NAME : " temp_2 " } ,
{ CONF_NUMBER : 3 , CONF_NAME : " temp_c " } ,
{ CONF_NUMBER : 4 , CONF_NAME : " temp_d " } ,
{ CONF_NUMBER : 5 , CONF_NAME : " temp_5 " } ,
{ CONF_NUMBER : 6 , CONF_NAME : " temp_f " } ,
{ CONF_NUMBER : 7 , CONF_NAME : " temp_g " } ,
{ CONF_NUMBER : 8 , CONF_NAME : " temp_h " } ,
] ,
}
}
)
SINGLE_MONITOR_CONFIG_VOLTAGE_SENSORS = make_single_monitor_config_with_sensors (
{
CONF_VOLTAGE_SENSORS : [
{
CONF_NUMBER : 1 ,
CONF_NAME : " voltage 1 " ,
} ,
]
}
)
2022-01-09 07:44:18 +00:00
MULTI_MONITOR_CONFIG = {
DOMAIN : {
CONF_PORT : 7513 ,
CONF_MONITORS : [
{
CONF_SERIAL_NUMBER : " 00000001 " ,
CONF_TEMPERATURE_SENSORS : {
CONF_TEMPERATURE_UNIT : " C " ,
CONF_SENSORS : [ { CONF_NUMBER : 1 , CONF_NAME : " unit_1_temp_1 " } ] ,
} ,
} ,
{
CONF_SERIAL_NUMBER : " 00000002 " ,
CONF_TEMPERATURE_SENSORS : {
CONF_TEMPERATURE_UNIT : " F " ,
CONF_SENSORS : [ { CONF_NUMBER : 1 , CONF_NAME : " unit_2_temp_1 " } ] ,
} ,
} ,
{
CONF_SERIAL_NUMBER : " 00000003 " ,
CONF_TEMPERATURE_SENSORS : {
CONF_TEMPERATURE_UNIT : " C " ,
CONF_SENSORS : [ { CONF_NUMBER : 1 , CONF_NAME : " unit_3_temp_1 " } ] ,
} ,
} ,
] ,
}
}
2021-11-11 12:20:16 +00:00
async def setup_greeneye_monitor_component_with_config (
hass : HomeAssistant , config : ConfigType
) - > bool :
""" Set up the greeneye_monitor component with the given config. Return True if successful, False otherwise. """
result = await async_setup_component (
hass ,
DOMAIN ,
config ,
)
await hass . async_block_till_done ( )
return result
def mock_with_listeners ( ) - > MagicMock :
""" Create a MagicMock with methods that follow the same pattern for working with listeners in the greeneye_monitor API. """
mock = MagicMock ( )
add_listeners ( mock )
return mock
def async_mock_with_listeners ( ) - > AsyncMock :
""" Create an AsyncMock with methods that follow the same pattern for working with listeners in the greeneye_monitor API. """
mock = AsyncMock ( )
add_listeners ( mock )
return mock
def add_listeners ( mock : MagicMock | AsyncMock ) - > None :
""" Add add_listener and remove_listener methods to the given mock that behave like their counterparts on objects from the greeneye_monitor API, plus a notify_all_listeners method that calls all registered listeners. """
mock . listeners = [ ]
mock . add_listener = mock . listeners . append
mock . remove_listener = mock . listeners . remove
def notify_all_listeners ( * args ) :
for listener in list ( mock . listeners ) :
listener ( * args )
mock . notify_all_listeners = notify_all_listeners
def mock_pulse_counter ( ) - > MagicMock :
""" Create a mock GreenEye Monitor pulse counter. """
pulse_counter = mock_with_listeners ( )
pulse_counter . pulses = 1000
pulse_counter . pulses_per_second = 10
return pulse_counter
def mock_temperature_sensor ( ) - > MagicMock :
""" Create a mock GreenEye Monitor temperature sensor. """
temperature_sensor = mock_with_listeners ( )
temperature_sensor . temperature = 32.0
return temperature_sensor
2022-01-06 13:59:56 +00:00
def mock_voltage_sensor ( ) - > MagicMock :
""" Create a mock GreenEye Monitor voltage sensor. """
voltage_sensor = mock_with_listeners ( )
voltage_sensor . voltage = 120.0
return voltage_sensor
2021-11-11 12:20:16 +00:00
def mock_channel ( ) - > MagicMock :
""" Create a mock GreenEye Monitor CT channel. """
channel = mock_with_listeners ( )
channel . absolute_watt_seconds = 1000
channel . polarized_watt_seconds = - 400
channel . watts = None
return channel
def mock_monitor ( serial_number : int ) - > MagicMock :
""" Create a mock GreenEye Monitor. """
monitor = mock_with_listeners ( )
monitor . serial_number = serial_number
2022-01-06 13:59:56 +00:00
monitor . voltage_sensor = mock_voltage_sensor ( )
2021-11-11 12:20:16 +00:00
monitor . pulse_counters = [ mock_pulse_counter ( ) for i in range ( 0 , 4 ) ]
monitor . temperature_sensors = [ mock_temperature_sensor ( ) for i in range ( 0 , 8 ) ]
monitor . channels = [ mock_channel ( ) for i in range ( 0 , 32 ) ]
return monitor
2022-02-23 18:09:12 +00:00
async def connect_monitor (
hass : HomeAssistant , monitors : AsyncMock , serial_number : int
) - > MagicMock :
""" Simulate a monitor connecting to Home Assistant. Returns the mock monitor API object. """
monitor = mock_monitor ( serial_number )
monitors . add_monitor ( monitor )
await hass . async_block_till_done ( )
return monitor