Example reading temperature probes
Below is a example application that reads internal and external termperature sensors.
Module to initialise the SCSmartDevice instance
See the example config page for the YAML configuration used by this example.
"""Manual testing code for the ShellyControl class."""
import threading
from mergedeep import merge
from sc_foundation import (
SCCommon,
SCConfigManager,
SCLogger,
)
from validation_extras import smart_switch_extra_validation
from sc_smart_device import SCSmartDevice, smart_devices_validator
CONFIG_FILE = "examples/switch_config.yaml"
def switch_init(wake_event: threading.Event | None = None, extra_validation: dict | None = None) -> tuple[SCConfigManager, SCLogger, SCSmartDevice]:
"""Create an instance of the SCConfigManager, SCLogger and SCSmartDevice class.
Args:
wake_event (threading.Event | None): Optional threading event to signal webhook events.
extra_validation (dict | None): Optional extra validation schema to merge with the default schema.
Returns:
tuple[SCConfigManager, SCLogger, SCSmartDevice]: A tuple containing the initialized SCConfigManager, SCLogger, and SCSmartDevice instances.
Raises:
RuntimeError: If there is an error with the configuration file, logger initialization, or SCSmartDevice initialization.
"""
# Merge the SmartDevices validation schema with the default validation schema
merged_schema = merge({}, smart_devices_validator, smart_switch_extra_validation, extra_validation or {})
assert isinstance(merged_schema, dict), "Merged schema should be type dict"
# Initialize the SC_ConfigManager class
try:
config = SCConfigManager(
config_file=CONFIG_FILE,
validation_schema=merged_schema,
)
except RuntimeError as e:
error_msg = f"Configuration file error: {e}"
raise RuntimeError(error_msg) from e
# Initialize the SC_Logger class
try:
logger_settings = config.get_logger_settings()
logger = SCLogger(logger_settings)
except RuntimeError as e:
error_msg = f"Logger initialisation error: {e}"
raise RuntimeError(error_msg) from e
# Test internet connection
if not SCCommon.check_internet_connection():
logger.log_message("No internet connection detected.", "error")
smart_switch_settings = config.get("SCSmartDevices")
if smart_switch_settings is None:
error_msg = "No SmartDevices settings found in the configuration file."
raise RuntimeError(error_msg)
# Initialize the SCSmartDevice class
try:
smart_switch_control = SCSmartDevice(logger, smart_switch_settings, wake_event)
except RuntimeError as e:
error_msg = f"SCSmartDevice initialization error: {e}"
raise RuntimeError(error_msg) from e
logger.log_message(f"SCSmartDevice initialized successfully with {len(smart_switch_control.devices)} devices.", "summary")
return config, logger, smart_switch_control
Example application
"""Example of using the SmartDevice control to read temperature sensors."""
import platform
import sys
import time
from sc_foundation import SCLogger
from switch_init import switch_init
from sc_smart_device import SCSmartDevice
# ------- Uncomment the relevant section below to test different devices and meters -------
# Test a Shelly switch with add-on temperature probes
device_name = "Sydney Dev A"
output_name = "Sydney Dev A O1"
has_external_probes = False
ext_temp_probe_name1 = "Temp Roof"
ext_temp_probe_name2 = "Temp Pool Water"
# Test a Tasmota switch including internal temperature probe
# device_name = "Sydney Dev B"
# output_name = "Sydney Dev B O1"
# has_external_probes = False
# ext_temp_probe_name1 = ""
# ext_temp_probe_name2 = ""
def test_temperature(logger: SCLogger, smart_switch_control: SCSmartDevice): # noqa: PLR0914
"""Test function for temperature SmartDevices control."""
loop_delay = 5
loop_count = 0
max_loops = 20
logger.log_message(f"\n\n\nTesting temperature functionality for device: {device_name}", "summary")
# Get the device and components
try:
device = smart_switch_control.get_device(device_name)
output = smart_switch_control.get_device_component("output", output_name)
internal_probe = smart_switch_control.get_device_component("temp_probe", device_name)
if has_external_probes:
temp_probe1 = smart_switch_control.get_device_component("temp_probe", ext_temp_probe_name1)
temp_probe2 = smart_switch_control.get_device_component("temp_probe", ext_temp_probe_name2)
except RuntimeError as e:
print(f"Error getting device: {e}", file=sys.stderr)
sys.exit(1)
except TimeoutError as e:
print(f"Timeout error getting device: {e}", file=sys.stderr)
sys.exit(1)
else:
while loop_count < max_loops:
# Refresh the status of all devices
logger.log_message(f"Refreshing device statuses... (Loop {loop_count + 1}/{max_loops})", "detailed")
smart_switch_control.refresh_all_device_statuses()
device_temp = device.get("Temperature", None)
output_state = output.get("State")
internal_probe_reading = internal_probe.get("Temperature", None)
logger.log_message(f"{device_name} Temperature: {device_temp}°C.", "detailed")
logger.log_message(f"{output_name} State: {output_state}.", "detailed")
logger.log_message(f" {device_name} Internal Probe reading: {internal_probe_reading}°C", "detailed")
if has_external_probes:
temp_probe1_id = temp_probe1.get("ProbeID", None)
temp_probe1_reading = temp_probe1.get("Temperature", None)
temp_probe1_time = temp_probe1.get("LastReadingTime", None)
temp_probe2_id = temp_probe2.get("ProbeID", None)
temp_probe2_reading = temp_probe2.get("Temperature", None)
temp_probe2_time = temp_probe2.get("LastReadingTime", None)
logger.log_message(f" {ext_temp_probe_name1} (ID: {temp_probe1_id}) reading: {temp_probe1_reading}°C last updated at {temp_probe1_time}", "detailed")
logger.log_message(f" {ext_temp_probe_name2} (ID: {temp_probe2_id}) reading: {temp_probe2_reading}°C last updated at {temp_probe2_time}", "detailed")
time.sleep(loop_delay)
loop_count += 1
def main():
"""Main function to run the example code."""
print(f"Hello from switch_temperature running on {platform.system()}")
# Initialize the configuration manager, logger, and SmartDevices control
try:
_config, logger, smart_switch_control = switch_init()
except RuntimeError as e:
print(f"Initialization error: {e}", file=sys.stderr)
sys.exit(1)
test_temperature(logger, smart_switch_control)
if __name__ == "__main__":
main()