From f96ebfdfc18c8f48facd32fde7d352cf3eb6105c Mon Sep 17 00:00:00 2001 From: CamDavidsonPilon Date: Fri, 25 Oct 2024 22:07:33 -0400 Subject: [PATCH] fixes --- CHANGELOG.md | 1 + pioreactor/actions/self_test.py | 2 ++ pioreactor/background_jobs/base.py | 5 +--- pioreactor/background_jobs/monitor.py | 41 ++++++++++++++++++--------- pioreactor/cli/pio.py | 12 ++++---- 5 files changed, 38 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 04216fe8..4652e65e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ - fix for updating over the internet when a Pioreactor is on a `A.devX` or `B.rcY` release - `pio kill --all-jobs` will no longer kill long-running jobs from plugins (specifically, `logs2x` jobs.) - updating the UI software won't prematurely stop any currently running activities + - correct eth mac address on RPi5s ### 24.10.1 diff --git a/pioreactor/actions/self_test.py b/pioreactor/actions/self_test.py index a47dc8e6..cc0cf056 100644 --- a/pioreactor/actions/self_test.py +++ b/pioreactor/actions/self_test.py @@ -269,6 +269,8 @@ def test_ambient_light_interference(managed_state, logger: CustomLogger, unit: s def test_REF_is_lower_than_0_dot_256_volts( managed_state, logger: CustomLogger, unit: str, experiment: str ) -> None: + assert is_HAT_present(), "HAT is not detected." + reference_channel = cast(PdChannel, config.get("od_config.photodiode_channel_reverse", REF_keyword)) ir_channel = cast(LedChannel, config["leds_reverse"][IR_keyword]) config_ir_intensity = config.get("od_reading.config", "ir_led_intensity") diff --git a/pioreactor/background_jobs/base.py b/pioreactor/background_jobs/base.py index ab89db7c..49194f09 100644 --- a/pioreactor/background_jobs/base.py +++ b/pioreactor/background_jobs/base.py @@ -773,8 +773,6 @@ def lost(self) -> None: def disconnected(self) -> None: # set state to disconnect - # call this first to make sure that it gets published to the broker. - self.state = self.DISCONNECTED # call job specific on_disconnected to clean up subjobs, etc. # however, if it fails, nothing below executes, so we don't get a clean @@ -789,9 +787,8 @@ def disconnected(self) -> None: self.logger.debug("Error in on_disconnected:") self.logger.debug(e, exc_info=True) - # remove attrs from MQTT self._clear_caches() - + self.state = self.DISCONNECTED self._log_state(self.state) # we "set" the internal event, which will cause any event.waits to finishing blocking. diff --git a/pioreactor/background_jobs/monitor.py b/pioreactor/background_jobs/monitor.py index 9ab281dc..5575961e 100644 --- a/pioreactor/background_jobs/monitor.py +++ b/pioreactor/background_jobs/monitor.py @@ -7,6 +7,7 @@ from time import sleep from typing import Callable from typing import Optional +from pathlib import Path import click @@ -210,17 +211,33 @@ def did_find_network() -> bool: utils.boolean_retry(did_find_network, retries=3, sleep_for=2) self.ipv4 = get_ip() - try: - with open("/sys/class/net/wlan0/address", "r") as f: - self.wlan_mac_address = f.read().strip() - except FileNotFoundError: - self.wlan_mac_address = "Not available" - - try: - with open("/sys/class/net/eth0/address", "r") as f: - self.eth_mac_address = f.read().strip() - except FileNotFoundError: - self.eth_mac_address = "Not available" + def get_first_mac(interface_type: str) -> Optional[str]: + """ + Finds the first network interface of the given type (wireless or wired) and retrieves its MAC address. + """ + net_path = Path("/sys/class/net") + for iface_path in net_path.iterdir(): + if iface_path.is_dir(): + try: + # Check the type of the interface using 'type' and presence of 'wireless' directory. + iface_type_path = iface_path / "type" + is_wireless = (iface_path / "wireless").exists() + + if iface_type_path.exists(): + iface_type = iface_type_path.read_text().strip() + + # Match the interface type: '1' means Ethernet, and the presence of 'wireless' means Wi-Fi. + if interface_type == "wireless" and is_wireless: + return (iface_path / "address").read_text().strip() + elif interface_type == "wired" and iface_type == "1" and not is_wireless: + return (iface_path / "address").read_text().strip() + except (FileNotFoundError, ValueError): + continue + return None + + # Get the MAC addresses for the first wireless and wired interfaces + self.wlan_mac_address = get_first_mac("wireless") or "Not available" + self.eth_mac_address = get_first_mac("wired") or "Not available" self.logger.debug(f"IPv4 address: {self.ipv4}") self.logger.debug(f"WLAN MAC address: {self.wlan_mac_address}") @@ -498,9 +515,7 @@ def check_and_publish_self_statistics(self) -> None: return def flicker_led_response_okay_and_publish_state(self, *args) -> None: - # force the job to publish it's state, so that users can use this to "reset" state. self.flicker_led_response_okay() - self._republish_state() def _republish_state(self) -> None: self._publish_setting("state") diff --git a/pioreactor/cli/pio.py b/pioreactor/cli/pio.py index fb224312..613d4e02 100644 --- a/pioreactor/cli/pio.py +++ b/pioreactor/cli/pio.py @@ -9,10 +9,10 @@ from msgspec.json import decode as loads from msgspec.json import encode as dumps -from pioreactor import config from pioreactor import exc from pioreactor import whoami from pioreactor.cli.lazy_group import LazyGroup +from pioreactor.config import config from pioreactor.logging import create_logger from pioreactor.mureq import get from pioreactor.mureq import HTTPException @@ -78,8 +78,8 @@ def logs(n: int) -> None: """ Tail & stream the logs from this unit to the terminal. CTRL-C to exit. """ - log_file = config.config.get("logging", "log_file", fallback="/var/log/pioreactor.log") - ui_log_file = config.config.get("logging", "ui_log_file", fallback="/var/log/pioreactor.log") + log_file = config.get("logging", "log_file", fallback="/var/log/pioreactor.log") + ui_log_file = config.get("logging", "ui_log_file", fallback="/var/log/pioreactor.log") if whoami.am_I_leader(): log_files = list(set([log_file, ui_log_file])) # deduping @@ -413,7 +413,7 @@ def update_app( if whoami.am_I_leader(): commands_and_priority.extend([ (f"sudo pip install --no-index --find-links={tmp_rls_dir}/wheels/ {tmp_rls_dir}/pioreactor-{version_installed}-py3-none-any.whl[leader,worker]", 3), - (f'sudo sqlite3 {config.config["storage"]["database"]} < {tmp_rls_dir}/update.sql', 10), + (f'sudo sqlite3 {config.get("storage", "database")} < {tmp_rls_dir}/update.sql', 10), ]) else: commands_and_priority.extend([ @@ -497,7 +497,7 @@ def update_app( [ (f"wget -O {tmp_rls_dir}/update.sql {url}", 5), ( - f'sudo sqlite3 {config.config["storage"]["database"]} < {tmp_rls_dir}/update.sql || :', + f'sudo sqlite3 {config.get("storage", "database")} < {tmp_rls_dir}/update.sql || :', 6, ), # or True at the end, since this may run on workers, that's okay. ] @@ -667,7 +667,7 @@ def update_ui(branch: Optional[str], repo: str, source: Optional[str], version: def db() -> None: import os - os.system(f"sqlite3 {config.config['storage']['database']} -column -header") + os.system(f"sqlite3 {config.get('storage','database')} -column -header") @pio.command(short_help="tail MQTT") @click.option("--topic", "-t", default="pioreactor/#")