github: support bound and symlinked devices (#4163)

* Fix unaccessible flipper for binded access points

workaround to work with symlinked devices

* Fix return None if Flipper not started

* exception handling

* decreased timeouts

* Check environment variables for flipper path
This commit is contained in:
Evgeny E
2025-03-31 14:20:25 +01:00
committed by GitHub
parent 79bb24406e
commit bcbf78a45d
5 changed files with 45 additions and 16 deletions

View File

@@ -21,7 +21,7 @@ jobs:
- name: 'Flash unit tests firmware' - name: 'Flash unit tests firmware'
id: flashing id: flashing
if: success() if: success()
timeout-minutes: 10 timeout-minutes: 5
run: | run: |
source scripts/toolchain/fbtenv.sh source scripts/toolchain/fbtenv.sh
./fbt resources firmware_latest flash LIB_DEBUG=1 FIRMWARE_APP_SET=unit_tests FORCE=1 ./fbt resources firmware_latest flash LIB_DEBUG=1 FIRMWARE_APP_SET=unit_tests FORCE=1
@@ -30,7 +30,7 @@ jobs:
- name: 'Copy assets and unit data, reboot and wait for flipper' - name: 'Copy assets and unit data, reboot and wait for flipper'
id: copy id: copy
if: steps.flashing.outcome == 'success' if: steps.flashing.outcome == 'success'
timeout-minutes: 7 timeout-minutes: 5
run: | run: |
source scripts/toolchain/fbtenv.sh source scripts/toolchain/fbtenv.sh
python3 scripts/testops.py -t=15 await_flipper python3 scripts/testops.py -t=15 await_flipper
@@ -42,7 +42,7 @@ jobs:
- name: 'Run units and validate results' - name: 'Run units and validate results'
id: run_units id: run_units
if: steps.copy.outcome == 'success' if: steps.copy.outcome == 'success'
timeout-minutes: 7 timeout-minutes: 5
run: | run: |
source scripts/toolchain/fbtenv.sh source scripts/toolchain/fbtenv.sh
python3 scripts/testops.py run_units python3 scripts/testops.py run_units

View File

@@ -20,7 +20,7 @@ jobs:
- name: 'Flashing target firmware' - name: 'Flashing target firmware'
id: first_full_flash id: first_full_flash
timeout-minutes: 10 timeout-minutes: 5
run: | run: |
source scripts/toolchain/fbtenv.sh source scripts/toolchain/fbtenv.sh
python3 scripts/testops.py -t=180 await_flipper python3 scripts/testops.py -t=180 await_flipper
@@ -29,7 +29,7 @@ jobs:
- name: 'Validating updater' - name: 'Validating updater'
id: second_full_flash id: second_full_flash
timeout-minutes: 10 timeout-minutes: 5
if: success() if: success()
run: | run: |
source scripts/toolchain/fbtenv.sh source scripts/toolchain/fbtenv.sh

View File

@@ -1,3 +1,4 @@
import os
import serial.tools.list_ports as list_ports import serial.tools.list_ports as list_ports
@@ -15,3 +16,8 @@ def resolve_port(logger, portname: str = "auto"):
logger.error("Failed to find connected Flipper") logger.error("Failed to find connected Flipper")
elif len(flippers) > 1: elif len(flippers) > 1:
logger.error("More than one Flipper is attached") logger.error("More than one Flipper is attached")
env_path = os.environ.get("FLIPPER_PATH")
if env_path:
if os.path.exists(env_path):
logger.info(f"Using FLIPPER_PATH from environment: {env_path}")
return env_path

View File

@@ -3,6 +3,8 @@
import time import time
from typing import Optional from typing import Optional
from serial.serialutil import SerialException
from flipper.app import App from flipper.app import App
from flipper.storage import FlipperStorage from flipper.storage import FlipperStorage
from flipper.utils.cdc import resolve_port from flipper.utils.cdc import resolve_port
@@ -32,11 +34,11 @@ class Main(App):
def _get_flipper(self, retry_count: Optional[int] = 1): def _get_flipper(self, retry_count: Optional[int] = 1):
port = None port = None
self.logger.info(f"Attempting to find flipper with {retry_count} attempts.")
for i in range(retry_count): for i in range(retry_count):
time.sleep(1) time.sleep(1)
self.logger.info(f"Attempting to find flipper #{i}.") self.logger.info(
f"Attempting to find flipper (Attempt {i + 1}/{retry_count})."
)
if port := resolve_port(self.logger, self.args.port): if port := resolve_port(self.logger, self.args.port):
self.logger.info(f"Found flipper at {port}") self.logger.info(f"Found flipper at {port}")
@@ -47,8 +49,16 @@ class Main(App):
return None return None
flipper = FlipperStorage(port) flipper = FlipperStorage(port)
flipper.start() for i in range(retry_count):
return flipper try:
flipper.start()
self.logger.info("Flipper successfully started.")
return flipper
except IOError as e:
self.logger.info(
f"Failed to start flipper (Attempt {i + 1}/{retry_count}): {e}"
)
time.sleep(1)
def power_off(self): def power_off(self):
if not (flipper := self._get_flipper(retry_count=10)): if not (flipper := self._get_flipper(retry_count=10)):

View File

@@ -4,6 +4,8 @@ import time
from datetime import datetime from datetime import datetime
from typing import Optional from typing import Optional
from serial.serialutil import SerialException
from flipper.app import App from flipper.app import App
from flipper.storage import FlipperStorage from flipper.storage import FlipperStorage
from flipper.utils.cdc import resolve_port from flipper.utils.cdc import resolve_port
@@ -34,23 +36,34 @@ class Main(App):
def _get_flipper(self, retry_count: Optional[int] = 1): def _get_flipper(self, retry_count: Optional[int] = 1):
port = None port = None
self.logger.info(f"Attempting to find flipper with {retry_count} attempts.")
for i in range(retry_count): for i in range(retry_count):
time.sleep(1) time.sleep(1)
self.logger.info(f"Attempt to find flipper #{i}.") self.logger.info(
f"Attempting to find flipper (Attempt {i + 1}/{retry_count})."
)
if port := resolve_port(self.logger, self.args.port): if port := resolve_port(self.logger, self.args.port):
self.logger.info(f"Found flipper at {port}") self.logger.info(f"Found flipper at {port}")
break break
if not port: if not port:
self.logger.info(f"Failed to find flipper {port}") self.logger.info(f"Failed to find flipper")
return None return None
flipper = FlipperStorage(port) flipper = FlipperStorage(port)
flipper.start() for i in range(retry_count):
return flipper try:
flipper.start()
self.logger.info("Flipper successfully started.")
return flipper
except IOError as e:
self.logger.info(
f"Failed to start flipper (Attempt {i + 1}/{retry_count}): {e}"
)
time.sleep(1)
self.logger.error("Flipper failed to start after all retries.")
return None
def await_flipper(self): def await_flipper(self):
if not (flipper := self._get_flipper(retry_count=self.args.timeout)): if not (flipper := self._get_flipper(retry_count=self.args.timeout)):