Files
cariflex/tools/EVerest-main/tests/async_api_tests/test_system.py
Eric F d398a6ced2 Add extracted tools: CitrineOS, OpenOCPP, ShapeShifter
- CitrineOS core extracted (CSMS OCPP 2.0.1)
- OpenOCPP extracted (firmware OCPP 1.6J/2.0.1)
- ShapeShifter library installed (pip install -e)
- ShapeShifter specification extracted
- EVerest extracted

TODO updated with progress
2026-06-08 00:38:27 -04:00

176 lines
6.7 KiB
Python

import os
import pytest
import pytest_asyncio
import json
import asyncio
from typing import Callable, Dict
import paho.mqtt.client as mqtt
from everest.testing.core_utils.probe_module import ProbeModule
from everest.testing.core_utils.everest_core import EverestCore
from everest.testing.core_utils.fixtures import *
class AsyncApiMqttHandler:
def __init__(self, broker: str, port: int = 1883, everest_prefix: str = ""):
self.broker = broker
self.port = port
self.everest_prefix = everest_prefix
self.handlers: Dict[str, Callable] = {}
self.client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
self.client.on_connect = self._on_connect
self.client.on_message = self._on_message
self.loop = None
self._connected = None
def register_handler(self, topic: str, handler: Callable):
"""Register a command handler for a topic"""
self.handlers[topic] = handler
self.client.subscribe(topic)
async def publish(self, topic: str, payload: str):
"""Publish data to a topic"""
if self._connected:
await self._connected.wait()
self.client.publish(topic, payload)
def _on_connect(self, client, userdata, flags, reason_code, properties):
"""Subscribe to registered topics on connect"""
for topic in self.handlers:
client.subscribe(topic)
if self._connected:
self.loop.call_soon_threadsafe(self._connected.set)
def _on_message(self, client, userdata, msg):
"""Dispatch message to handler in asyncio loop"""
if msg.topic in self.handlers:
asyncio.run_coroutine_threadsafe(
self.handlers[msg.topic](msg.payload.decode()),
self.loop
)
async def start(self):
"""Start the MQTT client"""
self.loop = asyncio.get_event_loop()
self._connected = asyncio.Event()
self.client.connect(self.broker, self.port)
self.client.loop_start()
try:
await asyncio.wait_for(self._connected.wait(), timeout=5.0)
except asyncio.TimeoutError:
raise TimeoutError("MQTT connection timeout")
async def stop(self):
"""Stop the MQTT client"""
self.client.loop_stop()
self.client.disconnect()
@pytest_asyncio.fixture
async def async_api_mqtt_handler(everest_core: EverestCore) -> AsyncApiMqttHandler:
broker = os.environ.get("MQTT_SERVER_ADDRESS", "localhost")
handler = AsyncApiMqttHandler(broker, 1883, everest_core.mqtt_external_prefix)
await handler.start()
yield handler
await handler.stop()
@pytest.fixture
def probe_module(everest_core: EverestCore) -> ProbeModule:
everest_core.start(standalone_module='probe')
probe_module = ProbeModule(everest_core.get_runtime_session())
probe_module.start()
return probe_module
@pytest.mark.asyncio
@pytest.mark.everest_core_config('probe-system.yaml')
async def test_api_cmds(everest_core: EverestCore, async_api_mqtt_handler: AsyncApiMqttHandler, probe_module: ProbeModule):
mqtt_prefix = everest_core.mqtt_external_prefix
# register mqtt handler for get_boot_reason
async def on_get_boot_reason(payload: str):
request = json.loads(payload)
response_topic = request['headers']['replyTo']
response_payload = "ApplicationReset"
await async_api_mqtt_handler.publish(f"{mqtt_prefix}{response_topic}", json.dumps(response_payload))
# register mqtt handler for set_system_time
async def on_set_system_time(payload: str):
request = json.loads(payload)
response_topic = request['headers']['replyTo']
response_payload = True
await async_api_mqtt_handler.publish(f"{mqtt_prefix}{response_topic}", json.dumps(response_payload))
# register mqtt handler for update_firmware
async def on_update_firmware(payload: str):
request = json.loads(payload)
response_topic = request['headers']['replyTo']
response_payload = "Accepted"
await async_api_mqtt_handler.publish(f"{mqtt_prefix}{response_topic}", json.dumps(response_payload))
# register mqtt handler for upload_logs
async def on_upload_logs(payload: str):
request = json.loads(payload)
response_topic = request['headers']['replyTo']
response_payload = {
"file_name": "test_log.txt",
"upload_logs_status": "Accepted"
}
await async_api_mqtt_handler.publish(f"{mqtt_prefix}{response_topic}", json.dumps(response_payload))
# register mqtt handler for is_reset_allowed
async def on_is_reset_allowed(payload: str):
request = json.loads(payload)
response_topic = request['headers']['replyTo']
response_payload = True
await async_api_mqtt_handler.publish(f"{mqtt_prefix}{response_topic}", json.dumps(response_payload))
async_api_mqtt_handler.register_handler(f"{everest_core.mqtt_external_prefix}everest_api/1/system/system_api/e2m/get_boot_reason", on_get_boot_reason)
async_api_mqtt_handler.register_handler(f"{everest_core.mqtt_external_prefix}everest_api/1/system/system_api/e2m/set_system_time", on_set_system_time)
async_api_mqtt_handler.register_handler(f"{everest_core.mqtt_external_prefix}everest_api/1/system/system_api/e2m/update_firmware", on_update_firmware)
async_api_mqtt_handler.register_handler(f"{everest_core.mqtt_external_prefix}everest_api/1/system/system_api/e2m/upload_logs", on_upload_logs)
async_api_mqtt_handler.register_handler(f"{everest_core.mqtt_external_prefix}everest_api/1/system/system_api/e2m/is_reset_allowed", on_is_reset_allowed)
result = await probe_module.call_command(
'system',
'get_boot_reason',
{}
)
assert result == "ApplicationReset"
result = await probe_module.call_command(
'system',
'set_system_time',
{'timestamp': "2024-01-01T00:00:00Z"}
)
assert result == True
result = await probe_module.call_command(
'system',
'update_firmware',
{
'firmware_update_request': {
'location': 'http://example.com/firmware.bin',
'request_id': 1
}
}
)
assert result == "Accepted"
result = await probe_module.call_command(
'system',
'upload_logs',
{
'upload_logs_request': {
'location': 'http://example.com/logs'
}
}
)
assert result == {"file_name": "test_log.txt", "upload_logs_status": "Accepted"}
result = await probe_module.call_command(
'system',
'is_reset_allowed',
{'type': 'Soft'}
)
assert result == True