Skip to content

Commit

Permalink
tests: on_target: add ppk test
Browse files Browse the repository at this point in the history
Add ppk test and update badge accordingly.

Signed-off-by: Giacomo Dematteis <[email protected]>
  • Loading branch information
DematteisGiacomo committed Nov 14, 2024
1 parent 4220a68 commit e1dd5e4
Show file tree
Hide file tree
Showing 7 changed files with 271 additions and 3 deletions.
61 changes: 60 additions & 1 deletion .github/workflows/on_target.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,22 @@ on:
type: boolean
required: true
default: false
run_wifi_location_tests:
type: boolean
required: true
default: false
run_ppk_tests:
type: boolean
required: true
default: false

jobs:
target_test:
name: Target Test
runs-on: self-hosted
environment: production
container:
image: ghcr.io/hello-nrfcloud/firmware:docker-v1.0.0
image: ghcr.io/hello-nrfcloud/firmware:docker-v1.0.2
options: --privileged
volumes:
- /dev:/dev:rw
Expand Down Expand Up @@ -183,6 +191,7 @@ jobs:
LOG_FILENAME: oob_conn_bridge_test_log

- name: Run Wi-Fi location tests
if: ${{ inputs.run_wifi_location_tests }}
working-directory: thingy91x-oob/tests/on_target
run: |
mkdir -p results
Expand All @@ -192,6 +201,56 @@ jobs:
env:
SEGGER: ${{ secrets.SEGGER_DUT_1 }}

- name: Run PPK tests
if: ${{ inputs.run_ppk_tests }}
id: ppk_test
working-directory: thingy91x-oob/tests/on_target
run: |
mkdir -p results
pytest -s -v -m dut_ppk \
--junit-xml=results/test-results-ppk.xml \
tests
env:
SEGGER: ${{ secrets.SEGGER_DUT_PPK }}

- name: Mock Power Badge JSON Creation
working-directory: thingy91x-oob/tests/on_target
run: |
# Write the JSON content to power_badge.json in the correct location
echo '{ "label": "psm_current uA", "message": "15", "schemaVersion": 1, "color": "yellow" }' > power_badge.json
shell: bash

- name: Commit and Push Badge File to custom_badges Branch
if: always()
working-directory: thingy91x-oob/tests/on_target
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Configure Git to trust the current working directory
git config --global --add safe.directory /__w/firmware/firmware
# Set Git user name and email for commits in the GitHub Actions environment
git config --global user.email "[email protected]"
git config --global user.name "GitHub Actions"
# Check if the badge file exists at the specified location
if [ -f power_badge.json ]; then
echo "Badge file found, proceeding to commit."
else
echo "Badge file not found. Exiting..."
exit 1
fi
# Ensure the custom_badges branch exists and switch to it
git fetch origin custom_badges || git checkout -b custom_badges
git checkout custom_badges
# Stage, commit, and push changes to the branch
ls
git add power_badge.json
git commit -m "Update power badge"
git push origin custom_badges
- name: Results
if: always()
uses: pmeier/[email protected]
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@
#### Nightly:
[![Target_tests](https://github.com/hello-nrfcloud/firmware/actions/workflows/test.yml/badge.svg?event=schedule)](https://github.com/hello-nrfcloud/firmware/actions/workflows/test.yml?query=branch%3Amain+event%3Aschedule)


#### Nightly PPK2 measures:
![](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/hello-nrfcloud/firmware/refs/heads/ppk_test/tests/on_target/badge.json)
![](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/hello-nrfcloud/firmware/refs/heads/custom_badges/tests/on_target/power_badge.json)


This project is based on the
[NCS Example Application](https://github.com/nrfconnect/ncs-example-application).

Expand Down
2 changes: 1 addition & 1 deletion app/src/modules/trigger/Kconfig.trigger
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ config APP_TRIGGER_TIMEOUT_SECONDS

config FREQUENT_POLL_DURATION_INTERVAL_SEC
int "Poll mode duration"
default 600
default 90

module = APP_TRIGGER
module-str = Trigger
Expand Down
1 change: 1 addition & 0 deletions tests/on_target/badge.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"label":"psm_current uA","message":"4","schemaVersion":1,"color":"green"}
1 change: 1 addition & 0 deletions tests/on_target/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ pyusb
imgtool
requests
memfault-cli
ppk2-api
2 changes: 1 addition & 1 deletion tests/on_target/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def t91x_board():
def hex_file():
# Search for the firmware hex file in the artifacts folder
artifacts_dir = "artifacts"
hex_pattern = r"hello\.nrfcloud\.com-[a-f0-9]+-thingy91x-nrf91\.hex"
hex_pattern = r"hello\.nrfcloud\.com-[a-z.0-9]+-thingy91x-nrf91\.hex"

for file in os.listdir(artifacts_dir):
if re.match(hex_pattern, file):
Expand Down
201 changes: 201 additions & 0 deletions tests/on_target/tests/test_power.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
##########################################################################################
# Copyright (c) 2024 Nordic Semiconductor
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
##########################################################################################

import pytest
import time
import os
import json
import types
from tests.conftest import get_uarts
from ppk2_api.ppk2_api import PPK2_API
from utils.uart import Uart
from utils.flash_tools import flash_device, reset_device, recover_device
import sys
sys.path.append(os.getcwd())
from utils.logger import get_logger

logger = get_logger()

UART_TIMEOUT = 60 * 30
POWER_TIMEOUT = 60 * 5
MAX_CURRENT_PSM_UA = 10

SEGGER = os.getenv('SEGGER')
UART_ID = os.getenv('UART_ID', SEGGER)

def get_uarts():
base_path = "/dev/serial/by-id"
try:
serial_paths = [os.path.join(base_path, entry) for entry in os.listdir(base_path)]
except (FileNotFoundError, PermissionError) as e:
logger.error(e)
return False

uarts = []

for path in sorted(serial_paths):
logger.warning(path)
logger.warning(UART_ID)
if UART_ID in path:
uarts.append(path)
else:
continue
return uarts

def save_badge_data(average):
logger.info(f"Minimum average current measured: {average}uA")
if average <= 10:
color = "green"
elif average <= 50:
color = "yellow"
else:
color = "red"

badge_data = {
"label": "psm_current uA",
"message": f"{average}",
"schemaVersion": 1,
"color": f"{color}"
}

# Save the JSON data to a file
with open('power_badge.json', 'w') as json_file:
json.dump(badge_data, json_file)

logger.info(f"Minimum average current saved to 'power_badge.json'")


@pytest.fixture(scope="module")
def ppk2():
'''
This fixture sets up ppk measurement tool.
'''
ppk2s_connected = PPK2_API.list_devices()
ppk2s_connected.sort()
if len(ppk2s_connected) == 2:
ppk2_port = ppk2s_connected[0]
print(f"Found PPK2 at {ppk2_port}")
elif len(ppk2s_connected) == 0:
pytest.fail("No ppk found")
else:
pytest.fail(f"Multiple PPks found")

ppk2_test = PPK2_API(ppk2_port, timeout=1, write_timeout=1, exclusive=True)

# get modifier might fail, retry 15 times
for _ in range(15):
try:
ppk2_test.get_modifiers()
break
except Exception as e:
logger.error(f"Failed to get modifiers: {e}")
time.sleep(5)
else:
pytest.fail("Failed to get ppk modifiers after 10 attempts")


ppk2_test.set_source_voltage(3300)

ppk2_test.use_ampere_meter() # set ampere meter mode

ppk2_test.toggle_DUT_power("ON") # enable DUT power


time.sleep(10)

for i in range(10):
try:
all_uarts = get_uarts()
if not all_uarts:
logger.error("No UARTs found")
log_uart_string = all_uarts[0]
break
except Exception:
ppk2_test.toggle_DUT_power("OFF") # disable DUT power
time.sleep(2)
ppk2_test.toggle_DUT_power("ON") # enable DUT power
time.sleep(5)
continue
else:
pytest.fail("NO uart after 10 attempts")

uart = Uart(log_uart_string, timeout=UART_TIMEOUT)

yield types.SimpleNamespace(ppk2_test=ppk2_test, uart=uart,)

uart.stop()
# recover_device()
ppk2_test.stop_measuring()

@pytest.mark.dut_ppk
def test_power(ppk2, hex_file):
# flash_device(os.path.abspath(hex_file))
reset_device()
time.sleep(5)
ppk2.uart.xfactoryreset()
patterns_boot = [
"Network connectivity established",
"Connected to Cloud",
"trigger: frequent_poll_entry: frequent_poll_entry",
"trigger: trigger_work_fn: Sending data sample trigger",
"environmental_module: sample: temp:",
"transport: state_connected_ready_run: Payload",
"Location search done"
]

ppk2.ppk2_test.start_measuring()

# Boot
ppk2.uart.flush()
reset_device()
# ppk2.uart.wait_for_str(patterns_boot, timeout=120)

# ppk2.uart.wait_for_str("Disabling UARTs", timeout=120)

start = time.time()
min_average = float('inf')
average = None
sampling_interval = 0.01
averages = []
average_of_averages = 0
last_log_time = start
while time.time() < start + POWER_TIMEOUT:
try:
read_data = ppk2.ppk2_test.get_data()
if read_data != b'':
samples, _ = ppk2.ppk2_test.get_samples(read_data)
average = sum(samples)/len(samples)

# Store the average for rolling calculation
averages.append(average)
# Keep only the averages from the last 3 seconds
if len(averages) > int(3 / sampling_interval):
averages.pop(0)

# Calculate the average of averages
average_of_averages = sum(averages) / len(averages) if averages else 0

# Log every 5 seconds
current_time = time.time()
if current_time - last_log_time >= 5:
logger.info(f"Average of {len(samples)} samples is: {average} uA")
logger.info(f"Average of averages: {average_of_averages} uA")
last_log_time = current_time # Update the last log time

if average_of_averages < min_average:
min_average = average_of_averages

except Exception as e:
logger.error(f"Catching exception: {e}")
pytest.skip("Something went wrong, unable to perform power measurements")

if average_of_averages < MAX_CURRENT_PSM_UA:
logger.info("psm target reached for more than 3 secs")
break
time.sleep(sampling_interval) # lower time between sampling -> less samples read in one sampling period
else:
save_badge_data(min_average)
pytest.fail(f"PSM target not reached after {POWER_TIMEOUT} seconds, only reached {min_average} uA")
save_badge_data(min_average)

0 comments on commit e1dd5e4

Please sign in to comment.