Skip to content

Commit

Permalink
ipv4 to pulbished settings
Browse files Browse the repository at this point in the history
  • Loading branch information
CamDavidsonPilon committed Aug 15, 2023
1 parent ae9adf8 commit 682fcb7
Show file tree
Hide file tree
Showing 10 changed files with 84 additions and 19 deletions.
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ repos:
hooks:
- id: mypy
additional_dependencies: [
msgspec==0.17.0,
msgspec==0.18.0,
types-pkg_resources==0.1.3,
types-paho-mqtt==1.6.0.6
]
Expand Down
1 change: 1 addition & 0 deletions pioreactor/actions/od_blank.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
from __future__ import annotations

from collections import defaultdict
Expand Down
5 changes: 4 additions & 1 deletion pioreactor/automations/dosing/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,10 @@ def execute_io_action(
self.remove_waste_from_bioreactor(
unit=self.unit,
experiment=self.experiment,
ml=waste_ml * 2,
ml=waste_ml
* config.getfloat(
"dosing_automation", "waste_removal_multiplier", fallback=2.0
),
source_of_event=source_of_event,
)
briefer_pause()
Expand Down
27 changes: 21 additions & 6 deletions pioreactor/background_jobs/monitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from pioreactor import version
from pioreactor import whoami
from pioreactor.background_jobs.base import BackgroundJob
from pioreactor.hardware import is_HAT_present
from pioreactor.hardware import PCB_BUTTON_PIN as BUTTON_PIN
from pioreactor.hardware import PCB_LED_PIN as LED_PIN
from pioreactor.hardware import TEMP
Expand Down Expand Up @@ -77,6 +78,7 @@ def off(): # functions don't take any arguments, nothing is passed in
"button_down": {"datatype": "boolean", "settable": False},
"versions": {"datatype": "json", "settable": False},
"voltage_on_pwm_rail": {"datatype": "Voltage", "settable": False},
"ipv4": {"datatype": "string", "settable": False},
}
computer_statistics: Optional[dict] = None
led_in_use: bool = False
Expand Down Expand Up @@ -178,12 +180,19 @@ def _setup_GPIO(self) -> None:
self.logger.warning("Failed to add button detect.")

def check_for_network(self) -> None:
ip = get_ip()
while (not whoami.is_testing_env()) and ((ip == "127.0.0.1") or (ip is None)):
# no wifi connection? Sound the alarm.
self.logger.warning("Unable to connect to network...")
self.flicker_led_with_error_code(error_codes.NO_NETWORK_CONNECTION)
ip = get_ip()
if whoami.is_testing_env():
self.ipv4 = "127.0.0.1"
else:
ipv4 = get_ip()
while ipv4 == "127.0.0.1" or ipv4 is None:
# no wifi connection? Sound the alarm.
self.logger.warning("Unable to connect to network...")
self.flicker_led_with_error_code(error_codes.NO_NETWORK_CONNECTION)
ipv4 = get_ip()

self.ipv4 = ipv4

self.logger.debug(f"IPv4 address: {self.ipv4}")

def self_checks(self) -> None:
# check active network connection
Expand All @@ -202,6 +211,7 @@ def self_checks(self) -> None:
self.check_for_webserver()

if whoami.am_I_active_worker():
self.check_for_HAT()
# check the PCB temperature
self.check_heater_pcb_temperature()

Expand Down Expand Up @@ -276,6 +286,10 @@ def check_for_required_jobs_running(self):
"watchdog and mqtt_to_db_streaming should be running on leader. Double check."
)

def check_for_HAT(self) -> None:
if not is_HAT_present():
self.logger.warning("HAT is not detected.")

def check_heater_pcb_temperature(self) -> None:
"""
Originally from #220
Expand All @@ -296,6 +310,7 @@ def check_heater_pcb_temperature(self) -> None:
tmp_driver = TMP1075(address=TEMP)
except ValueError:
# No PCB detected using i2c - fine to exit.
self.logger.warning("Heater PCB is not detected.")
return

observed_tmp = tmp_driver.get_temperature()
Expand Down
9 changes: 6 additions & 3 deletions pioreactor/background_jobs/stirring.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from pioreactor.utils import clamp
from pioreactor.utils import is_pio_job_running
from pioreactor.utils import local_persistant_storage
from pioreactor.utils import retry
from pioreactor.utils.gpio_helpers import set_gpio_availability
from pioreactor.utils.pwm import PWM
from pioreactor.utils.streaming_calculations import PID
Expand Down Expand Up @@ -73,9 +74,11 @@ def setup(self) -> None:

# ignore any changes that occur within 15ms - at 1000rpm (very fast), the
# delta between changes is ~60ms, so 15ms is good enough.
# TODO: sometimes this fails with `RuntimeError: Failed to add edge detection`
self.GPIO.add_event_detect(
self.hall_sensor_pin, self.GPIO.FALLING, callback=self.callback, bouncetime=15
# sometimes this fails with `RuntimeError: Failed to add edge detection`, so we retry.
retry(
self.GPIO.add_event_detect,
args=(self.hall_sensor_pin, self.GPIO.FALLING),
kwargs={"callback": self.callback, "bouncetime": 15},
)
self.turn_off_collection()

Expand Down
9 changes: 3 additions & 6 deletions pioreactor/cli/pio.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,6 @@ def log(message: str, level: str, name: str, local_only: bool):
)
getattr(logger, level)(message)

# flush and close handlers
for handler in logger.logger.handlers:
handler.flush()
handler.close()

except Exception as e:
# don't let a logging error bring down a script...
print(e)
Expand Down Expand Up @@ -465,7 +460,9 @@ def update_app(

if source is not None:
version_installed = source
commands_and_priority.append((f"sudo pip3 install -U --force-reinstall {source}", 1))
commands_and_priority.append(
(f"sudo pip3 install --force-reinstall --no-index {source}", 1)
)

elif branch is not None:
version_installed = quote(branch)
Expand Down
45 changes: 45 additions & 0 deletions pioreactor/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
import os
import signal
import tempfile
import time
from contextlib import contextmanager
from functools import wraps
from threading import Event
from typing import Callable
from typing import cast
Expand Down Expand Up @@ -375,3 +377,46 @@ def __getitem__(self, key):
return 0
else:
return dict.__getitem__(self, key)


def retry(func: Callable, retries=3, delay=0.5, args=(), kwargs={}):
"""
Retries a function upon encountering an exception until it succeeds or the maximum number of retries is exhausted.
This function executes the provided function and handles any exceptions it raises. If an exception is raised,
the function will wait for a specified delay before attempting to execute the function again. This process repeats
until either the function execution is successful or the specified maximum number of retries is exhausted.
On the final attempt, if the function still raises an exception, that exception will be re-raised to the caller.
Parameters
-----------
func (callable): The function to be retried.
retries (int, optional): The maximum number of times to retry the function. Defaults to 3.
delay (float, optional): The number of seconds to wait between retries. Defaults to 0.5.
args (tuple, optional): The positional arguments to pass to the function. Defaults to an empty tuple.
kwargs (dict, optional): The keyword arguments to pass to the function. Defaults to an empty dictionary.
Returns
--------
The return value of the function call, if the function call is successful.
Raises
--------
Exception: The exception raised by the function call if the function call is unsuccessful after the specified number of retries.
Example
--------
> def risky_function(x, y):
> return x / y
>
> # Call the function with retry
> result = retry(risky_function, retries=5, delay=1, args=(10, 0))
"""
for i in range(retries):
try:
return func(*args, **kwargs)
except Exception as e:
if i == retries - 1: # If this was the last attempt
raise e
time.sleep(delay)
1 change: 1 addition & 0 deletions pioreactor/utils/networking.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ def is_connected_to_network() -> bool:


def get_ip() -> Optional[str]:
# TODO: is this always ipv4??
from psutil import net_if_addrs # type: ignore

# Check for IP address of wireless network interface 'wlan0'
Expand Down
2 changes: 1 addition & 1 deletion requirements/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ sh==1.14.2
JSON-log-formatter==0.4.0
rpi_hardware_pwm==0.1.3
colorlog==6.6.0
msgspec==0.17.0
msgspec==0.18.0
diskcache==5.6.1
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"sh==1.14.3",
"JSON-log-formatter==0.5.1",
"colorlog==6.7.0",
"msgspec==0.17.0",
"msgspec==0.18.0",
"diskcache==5.6.1",
"wheel==0.38.4",
"crudini==0.9.4",
Expand Down

0 comments on commit 682fcb7

Please sign in to comment.