Skip to content

Commit

Permalink
Merge pull request #426 from quartiq/feature/miniconf-bump
Browse files Browse the repository at this point in the history
Feature/miniconf bump
  • Loading branch information
ryan-summers authored Jul 16, 2024
2 parents 13c5f7e + bd39676 commit e1da991
Show file tree
Hide file tree
Showing 11 changed files with 227 additions and 253 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
mainboard flash and will overwrite EEPROM-based settings during device boot. Reversion to older
firmware variants will still be able to use existing EEPROM settings, but the EEPROM contents
are no longer modified when settings are changed.
* [python] Python client has had `TelemetryReader` removed, `BoosterApi` was renamed to `Booster`
and now takes an `aiomqtt-client` as the constructor.

### Fixed
* Heavy network traffic no longer causes Booster to encounter watchdog resets or other spurious
Expand Down
20 changes: 10 additions & 10 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ usbd-serial = "0.2.2"
encdec = { version = "0.9", default-features = false }
crc-any = { version = "2.5.0", default-features = false }
panic-persist = { version = "0.3", features = ["custom-panic-handler", "utf8"] }
miniconf = { version = "0.11.0", features = ["json-core", "derive", "postcard"]}
miniconf_mqtt = "0.11"
miniconf = { version = "0.13", features = ["json-core", "derive", "postcard"]}
miniconf_mqtt = "0.13"
# Note: Keep `py/pyproject.toml` version in sync with the Minimq version used in FW.
minimq = "0.9.0"
w5500 = "0.5"
Expand All @@ -64,7 +64,7 @@ enc424j600 = "0.4"
embedded-hal = "1"
smoltcp-nal = { version = "0.5", features=["shared-stack"] }

serial-settings = {git = "https://github.com/quartiq/stabilizer", rev = "3ef00cbd9"}
serial-settings = {git = "https://github.com/quartiq/stabilizer", rev = "5452272931e1ad70547b578052ffbb186fb72514"}
stm32f4xx-hal = {version = "0.21.0", features = ["stm32f407", "usb_fs"] }

postcard = "1"
Expand Down
84 changes: 57 additions & 27 deletions hitl/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@
import contextlib
import sys
import time
import json
import logging

from booster import BoosterApi, TelemetryReader
from booster import Booster
import miniconf

# The default bias current to tune to.
DEFAULT_BIAS_CURRENT = 0.05
Expand All @@ -33,66 +36,65 @@ async def channel_on(booster, channel, initial_state='Enabled'):
""" Context manager to ensure a channel is disabled upon exit.
Args:
booster: The BoosterApi objct.
booster: The Booster connection
channel: The channel to configure.
initial_state: The state to configure the channel into.
"""
try:
print(f'Commanding channel {channel} into {initial_state}')
await booster.settings_interface.set(f'/channel/{channel}/state', initial_state)
await booster.miniconf.set(f'/channel/{channel}/state', initial_state)
yield
finally:
print(f'Commanding channel {channel} off')
await booster.settings_interface.set(f'/channel/{channel}/state', 'Off')
await booster.miniconf.set(f'/channel/{channel}/state', 'Off')


async def test_channel(booster, channel, prefix, broker):
async def test_channel(booster, channel, tele_queue):
""" Basic testing of a single RF channel.
Args:
booster: The BoosterApi.
booster: The Booster connection.
channel: The channel index to test.
prefix: Booster's miniconf prefix.
broker: The broker IP address.
tele: The received telemetry
"""
print(f'-> Conducting self-test on channel {channel}')

# Start receiving telemetry for the channel under test.
telemetry = await TelemetryReader.create(prefix, broker, channel)

# Tune the bias current on the channel
async with channel_on(booster, channel, 'Powered'):
vgs, ids = await booster.tune_bias(channel, DEFAULT_BIAS_CURRENT)
print(f'Channel {channel} bias tuning: Vgs = {vgs}, Ids = {ids}')

# Disable the channel.
await booster.settings_interface.set(f'/channel/{channel}/state', 'Off')
await booster.miniconf.set(f'/channel/{channel}/state', 'Off')

# Check that telemetry indicates channel is powered off.
async def is_off() -> bool:
_, tlm = await telemetry.get_next_telemetry()
msg = await tele_queue.__anext__()
tlm = json.loads(msg.payload)
return tlm['state'] == 'Off'

await periodic_check(is_off, timeout=5)

# Set the interlock threshold so that it won't trip.
print('Setting output interlock threshold to 30 dB')
await booster.settings_interface.set(f'/channel/{channel}/output_interlock_threshold', 30)
await booster.miniconf.set(f'/channel/{channel}/output_interlock_threshold', 30)

# Enable the channel, verify telemetry indicates it is now enabled.
async with channel_on(booster, channel):
async def is_enabled() -> bool:
_, tlm = await telemetry.get_next_telemetry()
msg = await tele_queue.__anext__()
tlm = json.loads(msg.payload)
return tlm['state'] == 'Enabled'

await periodic_check(is_enabled, timeout=5)

# Lower the interlock threshold so it trips.
print('Setting output interlock threshold to -5 dB, verifying interlock trips')
await booster.settings_interface.set(f'/channel/{channel}/output_interlock_threshold', -5.7)
await booster.miniconf.set(f'/channel/{channel}/output_interlock_threshold', -5.7)

async def is_tripped() -> bool:
_, tlm = await telemetry.get_next_telemetry()
msg = await tele_queue.__anext__()
tlm = json.loads(msg.payload)
return tlm['state'] == 'Tripped(Output)'

# Verify the channel is now tripped.
Expand All @@ -104,8 +106,11 @@ async def is_tripped() -> bool:

def main():
""" Main program entry point. """
parser = argparse.ArgumentParser(description='Loopback tests for Stabilizer HITL testing',)
parser.add_argument('--prefix', type=str, help='The MQTT prefix of the target')
parser = argparse.ArgumentParser(description='Loopback tests for Booster HITL testing')
parser.add_argument('--prefix', default='dt/sinara/booster/+', type=str,
help='The prefix of the booster to test')
parser.add_argument("--no-discover", "-d", action="store_true",
help="Do not discover device prefix.")
parser.add_argument('--broker', '-b', default='mqtt', type=str,
help='The MQTT broker address')
parser.add_argument('--channels', '-c', nargs='+', help='Channels indices to test',
Expand All @@ -115,18 +120,43 @@ def main():

async def test():
""" The actual testing being completed. """
booster = await BoosterApi.create(args.prefix, args.broker)

# Disable configure the telemetry rate.
await booster.settings_interface.set('/telemetry_period', 1, retain=False)

# Test operation of an RF channel
for channel in args.channels:
await test_channel(booster, channel, booster.prefix, args.broker)
async with miniconf.Client(
args.broker,
protocol=miniconf.MQTTv5,
logger=logging.getLogger("aiomqtt-client"),
queue_type=asyncio.LifoQueue,
max_queued_incoming_messages=1,
) as client:
if not args.no_discover:
prefix, _alive = await miniconf.discover_one(client, args.prefix)
else:
prefix = args.prefix

booster = Booster(client, prefix)

# Disable configure the telemetry rate.
await booster.miniconf.set('/telemetry_period', 1)

# Test operation of an RF channel
async with miniconf.Client(
args.broker, protocol=miniconf.MQTTv5,
logger=logging.getLogger("aiomqtt-client")
) as tele:
for channel in args.channels:
await tele.subscribe(f"{prefix}/telemetry/ch{channel}")
await test_channel(booster, channel, tele.messages)
await tele.unsubscribe(f"{prefix}/telemetry/ch{channel}")

loop = asyncio.get_event_loop()
sys.exit(loop.run_until_complete(test()))


if __name__ == '__main__':
import os
import sys
if sys.platform.lower() == "win32" or os.name.lower() == "nt":
from asyncio import set_event_loop_policy, WindowsSelectorEventLoopPolicy

set_event_loop_policy(WindowsSelectorEventLoopPolicy())

main()
Loading

0 comments on commit e1da991

Please sign in to comment.