diff --git a/server/server_comm/device_connection/apps.py b/server/server_comm/device_connection/apps.py
index 990ea51..b0af077 100644
--- a/server/server_comm/device_connection/apps.py
+++ b/server/server_comm/device_connection/apps.py
@@ -2,5 +2,5 @@
class DeviceConnectionConfig(AppConfig):
- default_auto_field = 'django.db.models.BigAutoField'
- name = 'device_connection'
+ default_auto_field = "django.db.models.BigAutoField"
+ name = "device_connection"
diff --git a/server/server_comm/device_connection/urls.py b/server/server_comm/device_connection/urls.py
index dd1122f..fe40fd1 100644
--- a/server/server_comm/device_connection/urls.py
+++ b/server/server_comm/device_connection/urls.py
@@ -3,6 +3,7 @@
from .views import (
AndroidDeviceConnectionView,
APIConnectionView,
+ FlowDeviceConnectionView,
SerialDeviceConnectionView,
)
@@ -18,4 +19,9 @@
name="android-connection",
),
path("api/", APIConnectionView.as_view(), name="api-connection"),
+ path(
+ "connect_flow/",
+ FlowDeviceConnectionView.as_view(),
+ name="flow-connection",
+ ),
]
diff --git a/server/server_comm/device_connection/views.py b/server/server_comm/device_connection/views.py
index 00c5b6a..e8981c4 100644
--- a/server/server_comm/device_connection/views.py
+++ b/server/server_comm/device_connection/views.py
@@ -23,53 +23,53 @@ def check_connection(self, conn_id: str):
device_port = self.get_device_port(conn_id)
serial_device = Serial(device_port, timeout=10)
- serial_device.write(b'ping\n')
+ serial_device.write(b"ping\n")
time.sleep(1)
res = serial_device.readline().strip()
if res:
return JsonResponse(
{
- 'status': 'connected',
- 'message': 'serial device connected',
- 'response': res,
+ "status": "connected",
+ "message": "serial device connected",
+ "response": res,
}
)
else:
return JsonResponse(
{
- 'status': 'no_response',
- 'message': 'serial device did not respond',
- 'response': None,
+ "status": "no_response",
+ "message": "serial device did not respond",
+ "response": None,
}
)
except SerialTimeoutException as e:
return JsonResponse(
{
- 'status': 'error',
- 'message': 'serial device timed out',
- 'response': str(e),
+ "status": "error",
+ "message": "serial device timed out",
+ "response": str(e),
}
)
except Exception as e:
return JsonResponse(
{
- 'status': 'error',
- 'message': 'an error occurred',
- 'response': str(e),
+ "status": "error",
+ "message": "an error occurred",
+ "response": str(e),
}
)
def get(self, request):
- conn_id = request.GET.get('conn_id')
+ conn_id = request.GET.get("conn_id")
if conn_id:
return self.check_connection(conn_id)
else:
return JsonResponse(
{
- 'status': 'error',
- 'message': 'conn_id is required',
- 'response': None,
+ "status": "error",
+ "message": "conn_id is required",
+ "response": None,
}
)
@@ -78,7 +78,7 @@ class AndroidDeviceConnectionView(View):
def get_adb_devices(self):
try:
adb_devices = subprocess.run(
- ['adb', 'devices'], capture_output=True, text=True, check=True
+ ["adb", "devices"], capture_output=True, text=True, check=True
).stdout.splitlines()[1:-1]
adb_devices = [line.split("\t")[0] for line in adb_devices]
return adb_devices
@@ -86,27 +86,27 @@ def get_adb_devices(self):
except subprocess.CalledProcessError as e:
return JsonResponse(
{
- 'status': 'error',
- 'message': 'adb command failed',
- 'response': str(e),
+ "status": "error",
+ "message": "adb command failed",
+ "response": str(e),
}
)
except FileNotFoundError as e:
return JsonResponse(
{
- 'status': 'error',
- 'message': 'adb not found',
- 'response': str(e),
+ "status": "error",
+ "message": "adb not found",
+ "response": str(e),
}
)
except Exception as e:
return JsonResponse(
{
- 'status': 'error',
- 'message': 'an error occurred',
- 'response': str(e),
+ "status": "error",
+ "message": "an error occurred",
+ "response": str(e),
}
)
@@ -116,30 +116,30 @@ def check_connection(self, conn_id: str):
if conn_id in adb_devices:
return JsonResponse(
{
- 'status': 'connected',
- 'message': 'android device connected',
- 'response': None,
+ "status": "connected",
+ "message": "android device connected",
+ "response": None,
}
)
else:
return JsonResponse(
{
- 'status': 'not_connected',
- 'message': 'android device not connected',
- 'response': None,
+ "status": "not_connected",
+ "message": "android device not connected",
+ "response": None,
}
)
def get(self, request):
- conn_id = request.GET.get('conn_id')
+ conn_id = request.GET.get("conn_id")
if conn_id:
return self.check_connection(conn_id)
else:
return JsonResponse(
{
- 'status': 'error',
- 'message': 'conn_id is required',
- 'response': None,
+ "status": "error",
+ "message": "conn_id is required",
+ "response": None,
}
)
@@ -152,56 +152,56 @@ def check_connection(self, api_url: str):
if res.status_code == 200:
return JsonResponse(
{
- 'status': 'connected',
- 'message': 'connected to api',
- 'response': res.json(),
+ "status": "connected",
+ "message": "connected to api",
+ "response": res.json(),
}
)
else:
JsonResponse(
{
- 'status': 'error',
- 'message': (
- f'unexpected api response {res.status_code}'
+ "status": "error",
+ "message": (
+ f"unexpected api response {res.status_code}"
),
- 'response': res.json(),
+ "response": res.json(),
}
)
except requests.exceptions.Timeout as e:
return JsonResponse(
{
- 'status': 'error',
- 'message': 'api request timed out',
- 'response': str(e),
+ "status": "error",
+ "message": "api request timed out",
+ "response": str(e),
}
)
except requests.exceptions.ConnectionError as e:
return JsonResponse(
{
- 'status': 'error',
- 'message': 'could not connect to api',
- 'response': str(e),
+ "status": "error",
+ "message": "could not connect to api",
+ "response": str(e),
}
)
except Exception as e:
return JsonResponse(
{
- 'status': 'error',
- 'message': 'an error occurred',
- 'response': str(e),
+ "status": "error",
+ "message": "an error occurred",
+ "response": str(e),
}
)
def get(self, request):
- api_url = request.GET.get('api_url')
+ api_url = request.GET.get("api_url")
if api_url:
return self.check_connection(api_url)
else:
return JsonResponse(
{
- 'status': 'error',
- 'message': 'api_url is required',
- 'response': None,
+ "status": "error",
+ "message": "api_url is required",
+ "response": None,
}
)
@@ -242,14 +242,14 @@ def connect_devices(self, flow_id: str):
android_view.check_connection(conn_id)
def get(self, request):
- flow_id = request.GET.get('flow_id')
+ flow_id = request.GET.get("flow_id")
if flow_id:
return self.connect_devices(flow_id)
else:
return JsonResponse(
{
- 'status': 'error',
- 'message': 'flow_id is required',
- 'response': None,
+ "status": "error",
+ "message": "flow_id is required",
+ "response": None,
}
)
diff --git a/server/server_comm/server_comm/settings.py b/server/server_comm/server_comm/settings.py
index e8ec7a5..2882ebe 100644
--- a/server/server_comm/server_comm/settings.py
+++ b/server/server_comm/server_comm/settings.py
@@ -82,7 +82,7 @@
WSGI_APPLICATION = "server_comm.wsgi.application"
CORS_ALLOWED_ORIGINS = [
- 'http://localhost:5173',
+ "http://localhost:5173",
]
# Database
diff --git a/server/server_comm/test_runner/apps.py b/server/server_comm/test_runner/apps.py
index f003ce4..c14dc5f 100644
--- a/server/server_comm/test_runner/apps.py
+++ b/server/server_comm/test_runner/apps.py
@@ -2,5 +2,5 @@
class TestRunnerConfig(AppConfig):
- default_auto_field = 'django.db.models.BigAutoField'
- name = 'test_runner'
+ default_auto_field = "django.db.models.BigAutoField"
+ name = "test_runner"
diff --git a/server/server_comm/test_runner/nrf_scripts/check_characteristic.xml b/server/server_comm/test_runner/nrf_scripts/check_characteristic.xml
new file mode 100644
index 0000000..8983715
--- /dev/null
+++ b/server/server_comm/test_runner/nrf_scripts/check_characteristic.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/server/server_comm/test_runner/nrf_scripts/check_service.xml b/server/server_comm/test_runner/nrf_scripts/check_service.xml
new file mode 100644
index 0000000..758a0a1
--- /dev/null
+++ b/server/server_comm/test_runner/nrf_scripts/check_service.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/server/server_comm/test_runner/nrf_scripts/connection.xml b/server/server_comm/test_runner/nrf_scripts/connection.xml
new file mode 100644
index 0000000..d6f43a0
--- /dev/null
+++ b/server/server_comm/test_runner/nrf_scripts/connection.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/server/server_comm/test_runner/nrf_scripts/custom_script.xml b/server/server_comm/test_runner/nrf_scripts/custom_script.xml
new file mode 100644
index 0000000..af67758
--- /dev/null
+++ b/server/server_comm/test_runner/nrf_scripts/custom_script.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/server/server_comm/test_runner/nrf_scripts/nrf_connect.py b/server/server_comm/test_runner/nrf_scripts/nrf_connect.py
new file mode 100644
index 0000000..42037c5
--- /dev/null
+++ b/server/server_comm/test_runner/nrf_scripts/nrf_connect.py
@@ -0,0 +1,155 @@
+import os
+import subprocess
+
+
+def run_command(name, command, filename):
+ try:
+ result = subprocess.run(command, capture_output=True, text=True)
+ stdout, stderr = result.stdout, result.stderr
+ except Exception as e:
+ return {
+ "status": "error",
+ "message": f"Exception occurred while executing command: {name}",
+ "response": str(e),
+ }
+
+ if stderr:
+ return {
+ "status": "error",
+ "message": f"Error occurred while running command: {name}",
+ "response": stderr,
+ }
+
+ if "Error" in stdout:
+ return {
+ "status": "error",
+ "message": f"Error occurred while running command: {name}",
+ "response": stdout,
+ }
+
+ with open(filename, "r") as file:
+ lines = file.readlines()
+
+ if "completed" in lines[-1]:
+ return {
+ "status": "success",
+ "message": f"Command: {name}, ran successfully",
+ "response": "",
+ }
+
+ for i in range(len(lines)):
+ if name in lines[i]:
+ start_idx = i
+ break
+
+ error_lines = []
+ for line in lines[start_idx:]:
+ line = line.split("\t")
+ if line[0] == "E" or line[0] == "W":
+ error_lines.append(line)
+
+ return {
+ "status": "error",
+ "message": f"nRF script: {name}, failed",
+ "response": error_lines,
+ }
+
+
+def run_check_connection(
+ android_device_id,
+ mac_address,
+):
+ script_dir = os.path.dirname(__file__)
+ os.chdir(script_dir)
+
+ command = [
+ "./test.sh",
+ "-d",
+ android_device_id,
+ "-e",
+ "MAC_ADDRESS",
+ mac_address,
+ "connection.xml",
+ ]
+
+ return run_command("Connect", command, "connection_result.txt")
+
+
+def run_check_service(
+ android_device_id,
+ mac_address,
+ service_uuid,
+):
+ script_dir = os.path.dirname(__file__)
+ os.chdir(script_dir)
+
+ command = [
+ "./test.sh",
+ "-d",
+ android_device_id,
+ "-e",
+ "MAC_ADDRESS",
+ mac_address,
+ "-e",
+ "SERVICE_UUID",
+ service_uuid,
+ "check_service.xml",
+ ]
+
+ return run_command(
+ "Check Service UUID", command, "check_service_result.txt"
+ )
+
+
+def run_check_characteristic(
+ android_device_id,
+ mac_address,
+ service_uuid,
+ characteristic_uuid,
+):
+ script_dir = os.path.dirname(__file__)
+ os.chdir(script_dir)
+
+ command = [
+ "./test.sh",
+ "-d",
+ android_device_id,
+ "-e",
+ "MAC_ADDRESS",
+ mac_address,
+ "-e",
+ "SERVICE_UUID",
+ service_uuid,
+ "-e",
+ "CHARACTERISTIC_UUID",
+ characteristic_uuid,
+ "check_characteristic.xml",
+ ]
+
+ return run_command(
+ "Check Characteristic UUID", command, "check_characteristic_result.txt"
+ )
+
+
+def run_custom_script(android_device_id, mac_address, extras):
+ script_dir = os.path.dirname(__file__)
+ os.chdir(script_dir)
+
+ extra_cmd = []
+ for var, value in extras.items():
+ extra_cmd.append("-e")
+ extra_cmd.append(var)
+ extra_cmd.append(value)
+
+ command = [
+ "./test.sh",
+ "-d",
+ android_device_id,
+ "-e",
+ "MAC_ADDRESS",
+ mac_address,
+ ]
+ command.extend(extra_cmd)
+ command.append("custom_script.xml")
+
+ return run_command("Custom script", command, "custom_script_result.txt")
diff --git a/server/server_comm/test_runner/nrf_scripts/test.sh b/server/server_comm/test_runner/nrf_scripts/test.sh
new file mode 100755
index 0000000..96885e3
--- /dev/null
+++ b/server/server_comm/test_runner/nrf_scripts/test.sh
@@ -0,0 +1,172 @@
+#!/bin/bash
+# Copyright (c) 2024, Nordic Semiconductor
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * Neither the name of nRF Toolbox nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Description:
+# ------------
+# The script allows to run automated tests using Android phone.
+# The script may be run on Unix / Mac / Linux.
+#
+# Requirements:
+# -------------
+# 1. Android device with Android version 4.3+ connected by USB cable with the PC
+# 2. The path to Android platform-tools directory must be added to %PATH% environment variable
+# 3. nRF Connect (2.1.0+) application installed on the Android device
+# 4. "Developer options" and "USB debugging" must be enabled on the Android device
+#
+# Usage:
+# ------
+# 1. Open console
+# 2. Type "./test.sh --help" and press ENTER
+#
+# Android Debug Bridge (adb):
+# ---------------------------
+# You must have Android platform tools installed on the computer.
+# Go to http://developer.android.com/sdk/index.html for more information how to install it on the computer.
+# You do not need the whole ADT Bundle (with Eclipse or Android Studio). Only SDK Tools with Platform Tools are required.
+
+# Set variables
+PROGRAM="$0"
+DEVICE=""
+S_DEVICE=""
+EXTRAS=""
+
+# Check ADB
+if ! command -v adb > /dev/null 2>&1; then
+ echo "Error: adb is not recognized as an external command."
+ echo " Add [Android Bundle path]/sdk/platform-tools to \$PATH"
+ exit 1
+fi
+
+# Check help
+if [ -z "$1" ] || [ "$1" = "--help" ]; then
+ echo "Usage: $PROGRAM [-D device_id] [-E key value] script.xml"
+ echo "Info:"
+ echo "device_id - Call: \"adb devices\" to get a list of serial numbers"
+ echo "key value - You may pass 0+ parameters to the Test Service, e.g.,"
+ echo " -E EXTRA_ADDRESS \"AA:BB:CC:DD:EE:FF\" -E SOMETHING \"important\""
+ echo " and use them in the script.xml file as e.g.:"
+ echo " ..address=\"\${EXTRA_ADDRESS}\"..."
+ exit 1
+fi
+
+# Read target device id
+if [ "$1" = "-d" ]; then
+ TARGET_DEVICE_SET=1
+ shift
+ DEVICE="$1"
+ S_DEVICE="-s $1"
+ shift
+fi
+
+# Read optional extra parameters
+while [ "$1" = "-e" ]; do
+ EXTRAS_SET=1
+ shift
+ EXTRAS="$EXTRAS -e $1 \"$2\""
+ shift 2
+done
+
+# Write intro
+echo "================================================="
+echo "Nordic Semiconductor Automated Tests shell script"
+echo "================================================="
+
+# Read file name and fully qualified path name to the XML file
+if [ -z "$1" ]; then
+ echo "Error: Test script file name not specified."
+ exit 1
+fi
+
+XML_FILE=$(basename "$1")
+RESULT_FILE="${1%.*}_result.txt"
+XML_PATH=$(realpath "$1")
+
+if [ ! -e "$XML_PATH" ]; then
+ echo "Error: The given test script file has not been found."
+ exit 1
+fi
+
+# Check if there is only one device connected
+if [ -z "$DEVICE" ]; then
+ DEVICE_COUNT=$(adb devices | grep -v "devices" | grep -c "device\|unauthorized\|emulator")
+ if [ "$DEVICE_COUNT" -eq 0 ]; then
+ echo "Error: No device connected."
+ exit 1
+ elif [ "$DEVICE_COUNT" -gt 1 ]; then
+ echo "Error: More than one device connected."
+ echo " Specify the device serial number using -D option:"
+ adb devices
+ exit 1
+ fi
+else
+ # Check if specified device is connected
+ if ! adb devices | grep -q "$DEVICE"; then
+ echo "Error: Device with serial number \"$DEVICE\" is not connected."
+ adb devices
+ exit 1
+ fi
+fi
+
+# Remove old result file (if exists)
+echo -n "Removing old result file..."
+adb $S_DEVICE shell rm "/sdcard/Android/data/no.nordicsemi.android.mcp/files/Test/$RESULT_FILE" > /dev/null 2>&1
+echo "OK"
+
+# Copy selected file onto the device
+echo -n "Copying \"$XML_FILE\" to /sdcard/Android/data/no.nordicsemi.android.mcp/files/Test..."
+adb $S_DEVICE push "$XML_PATH" "/sdcard/Android/data/no.nordicsemi.android.mcp/files/Test/$XML_FILE" > /dev/null 2>&1
+if [ $? -ne 0 ]; then
+ echo "FAIL"
+ echo "Error: Device not found."
+ exit 1
+else
+ echo "OK"
+fi
+
+# Start test service on the device
+echo -n "Starting test service..."
+adb $S_DEVICE shell am start-foreground-service -a no.nordicsemi.android.action.START_TEST $EXTRAS -e no.nordicsemi.android.test.extra.EXTRA_FILE_PATH "/sdcard/Android/data/no.nordicsemi.android.mcp/files/Test/$XML_FILE" > /dev/null 2>&1
+if [ $? -ne 0 ]; then
+ echo "FAIL"
+ echo "Error: Required application not installed."
+ exit 1
+else
+ echo "OK"
+ echo "Test started...OK"
+fi
+
+# Try to obtain the result. Wait 10 seconds before every try.
+echo -n "Waiting for the result..."
+while true; do
+ # Wait 10 sec, this IP address is reserved and does not exist
+ sleep 10
+ adb $S_DEVICE pull "/sdcard/Android/data/no.nordicsemi.android.mcp/files/Test/$RESULT_FILE" "$RESULT_FILE" > /dev/null 2>&1
+ if [ $? -eq 0 ]; then
+ break
+ fi
+done
+echo "OK"
+echo "Result saved in \"$RESULT_FILE\"."
+exit 0
\ No newline at end of file
diff --git a/server/server_comm/test_runner/urls.py b/server/server_comm/test_runner/urls.py
index 403b2ac..0d1483f 100644
--- a/server/server_comm/test_runner/urls.py
+++ b/server/server_comm/test_runner/urls.py
@@ -3,6 +3,6 @@
from .views import RunTestFlow
urlpatterns = [
- path('run//', RunTestFlow.as_view(), name='run-test-flow'),
- path('run/', RunTestFlow.as_view(), name='run-all-test-flows'),
+ path("run//", RunTestFlow.as_view(), name="run-test-flow"),
+ path("run/", RunTestFlow.as_view(), name="run-all-test-flows"),
]
diff --git a/server/server_comm/test_runner/views.py b/server/server_comm/test_runner/views.py
index a87afe9..e79c0b1 100644
--- a/server/server_comm/test_runner/views.py
+++ b/server/server_comm/test_runner/views.py
@@ -8,6 +8,7 @@
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
+from test_runner.nrf_scripts.nrf_connect import run_check_connection
class RunTestFlow(APIView):
@@ -65,7 +66,7 @@ def check_device_connections(self, flow_id):
protocol = 'https' if self.request.is_secure() else 'http'
base_url = f"{protocol}://{self.request.get_host()}"
check_devices_url = f"""
- {base_url}{reverse('flow-device-connection')}
+ {base_url}{reverse('flow-connection')}
?{urlencode({'flow_id': flow_id})}
"""
response = requests.get(check_devices_url)
@@ -91,16 +92,67 @@ def check_device_connections(self, flow_id):
"message": "Failed to check device connections",
}
+ def get_nrf_devices(self, devices):
+ """
+ Return devices with mac_address field, aka devices to nrf connect
+ """
+ nrf_devices = []
+
+ for device in devices:
+ if "mac_address" in device.communication_ids.keys():
+ nrf_devices.append(device)
+
+ return nrf_devices
+
+ def connect_ble_nrf_devices(self, flow_id):
+ """
+ Connect select device(s) in command nodes to nrf kit
+ """
+ # TODO: does the user need to make category "Android" for this to work
+ # what if they wanna categorize differently?
+ # not all BLE/android devices should be connected, no? who should be?
+ # TODO: how do we check UUIDs? need to know if service/characteristic
+
+ protocol = 'https' if self.request.is_secure() else 'http'
+ base_url = f"{protocol}://{self.request.get_host()}"
+ get_devices_url = f"""
+ {base_url}{reverse('devices')}
+ """
+ response = requests.get(get_devices_url)
+
+ if response.status_code == 200:
+ devices = response.json()
+ else:
+ return {
+ "status": "error",
+ "message": "Failed to get devices",
+ "response": response,
+ }
+
+ nrf_devices = self.get_nrf_devices(devices)
+
+ for device in nrf_devices:
+ dev_id = device.device_id
+ mac = device.communication_ids.get("mac_address")
+ res = run_check_connection(dev_id, mac)
+
+ if res.get("status") == "error":
+ raise RuntimeError(
+ f"{res.get('message')}\n{res.get('response')}"
+ )
+ return {
+ "status": "success",
+ "message": "Connected all nRF devices",
+ "response": "",
+ }
+
def test_setup(self, flow_id):
"""
Set up and assert device connections for the test flow.
"""
- # TODO comment back in when this API is fixed
- # self.check_device_connections(flow_id)
+ self.check_device_connections(flow_id)
- # TODO Connect android device(s) in command nodes to nrf kit (LIL-90)
-
- # TODO Assert that connection is setup (LIL-90)
+ self.connect_ble_nrf_devices(flow_id)
def run_node(self, node):
"""
@@ -112,8 +164,13 @@ def run_node(self, node):
# TODO add code from LIL-91
result = True
elif node.node_type == Node.ACTION:
- # TODO add code from LIL-95
- result = True
+ try:
+ # TODO: HOW DO WE RUN NRF SCRIPTS?
+ exec(node.function)
+ result = True
+ except Exception as e:
+ ex_type = type(e).__name__
+ raise ValueError(f"Invalid Python code, {ex_type}:{e}")
else:
raise ValueError(f"Invalid node type: {node.node_type}")
return {