Skip to content

Commit

Permalink
lots
Browse files Browse the repository at this point in the history
  • Loading branch information
CamDavidsonPilon committed Jun 21, 2023
1 parent 4c7c7ae commit 6d06c6d
Show file tree
Hide file tree
Showing 13 changed files with 150 additions and 17 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
### Upcoming

#### Highlights
-
- The UI now offers a way to upgrade to the bleeding-edge Pioreactor app and UI software, called "development". This software is unstable (and fun!).

#### Everything else
- Fixed `source` in `BackgroundJobContrib` - thanks @odcambc!
- `pio add-pioreactor` will now accept an option that is the password of the RPi being added (default: `raspberry`). Ex: `pio add-pioreactor worker1 -p mypass`
- Improved some warning and error messages.
- Improved watchdog detecting and fixing "lost" Pioreactors.
- Improved temperature inference accuracy.
- Starting to test software against Python 3.11, in anticipation of a Python 3.11 coming to Raspberry Pi OS.
- Improvements to bash scripts to make them more robust.



### 23.6.7
Expand Down
8 changes: 8 additions & 0 deletions pioreactor/background_jobs/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,14 @@ def _callback(client, userdata, message: pt.MQTTMessage) -> t.Optional[T]:
return

def set_state(self, new_state: pt.JobState) -> None:
"""
The preferred way to change states is to use this function (instead of self.state = state). Note:
- no-op if in the same state
- will call the transition callback
"""

if new_state not in {self.INIT, self.READY, self.DISCONNECTED, self.SLEEPING, self.LOST}:
self.logger.error(f"saw {new_state}: not a valid state")
return
Expand Down
1 change: 0 additions & 1 deletion pioreactor/background_jobs/dosing_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,6 @@ def start_dosing_control(
)
@click.option(
"--automation-name",
default="silent",
help="set the automation of the system: turbidostat, morbidostat, silent, etc.",
show_default=True,
)
Expand Down
7 changes: 7 additions & 0 deletions pioreactor/background_jobs/leader/watchdog.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,16 @@ def watch_for_lost_state(self, state_message: MQTTMessage) -> None:
# let's return early.
return

# this is a hack! If the monitor job is in state READY, it will no op any transition.
# so we set to sleeping for a second, and the back to ready.
self.pub_client.publish(
f"pioreactor/{unit}/{UNIVERSAL_EXPERIMENT}/monitor/$state/set", self.SLEEPING
)
time.sleep(1)
self.pub_client.publish(
f"pioreactor/{unit}/{UNIVERSAL_EXPERIMENT}/monitor/$state/set", self.READY
)
###
time.sleep(20)

if self.state != self.READY:
Expand Down
1 change: 0 additions & 1 deletion pioreactor/background_jobs/led_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,6 @@ def start_led_control(
)
@click.option(
"--automation-name",
default="silent",
help="set the automation of the system: silent, etc.",
show_default=True,
)
Expand Down
28 changes: 24 additions & 4 deletions pioreactor/background_jobs/monitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,22 +225,42 @@ def check_for_webserver(self):
if status == "failed" or status == "inactive":
self.logger.error("lighttpd is not running. Check `systemctl status lighttpd`.")
self.flicker_led_with_error_code(error_codes.WEBSERVER_OFFLINE)

elif status == "activating":
# try again
pass

elif status == "active":
# okay
break

else:
raise ValueError(status)

except Exception as e:
self.logger.debug(f"Error checking lighttpd status: {e}", exc_info=True)
self.logger.error(f"Error checking lighttpd status: {e}")

try:
while True:
# Run the command 'systemctl is-active huey' and capture the output
result = subprocess.run(
["systemctl", "is-active", "huey"], capture_output=True, text=True
)
status = result.stdout.strip()

# Check if the output is okay
if status == "failed" or status == "inactive":
self.logger.error("huey is not running. Check `systemctl status huey`.")
self.flicker_led_with_error_code(error_codes.WEBSERVER_OFFLINE)
elif status == "activating":
# try again
pass
elif status == "active":
# okay
break
else:
raise ValueError(status)
except Exception as e:
self.logger.debug(f"Error checking huey status: {e}", exc_info=True)
self.logger.error(f"Error checking huey status: {e}")

try:
# can we ping ourselves? should have a response
res = get("http://localhost")
Expand Down
7 changes: 4 additions & 3 deletions pioreactor/background_jobs/temperature_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,10 @@ class TemperatureController(BackgroundJob):
True if supplying an external thermometer that will publish to MQTT.
"""

MAX_TEMP_TO_REDUCE_HEATING = 61.5 # ~PLA glass transition temp
MAX_TEMP_TO_DISABLE_HEATING = 63.5
MAX_TEMP_TO_REDUCE_HEATING = (
63.0 # ~PLA glass transition temp, and I've gone safely above this an it's not a problem.
)
MAX_TEMP_TO_DISABLE_HEATING = 65.0
MAX_TEMP_TO_SHUTDOWN = 66.0

INFERENCE_SAMPLES_EVERY_T_SECONDS: float = 5.0
Expand Down Expand Up @@ -579,7 +581,6 @@ def start_temperature_control(
)
@click.option(
"--automation-name",
default="only_record_temperature",
help="set the automation of the system",
show_default=True,
)
Expand Down
2 changes: 1 addition & 1 deletion pioreactor/cli/pio.py
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,7 @@ def update_app(branch: Optional[str], source: Optional[str], version: Optional[s
else:
logger.debug(p.stdout)

logger.notice(f"Updated Pioreactor to version {version_installed}.") # type: ignore
logger.notice(f"Updated {whoami.get_unit_name()} to version {version_installed}.") # type: ignore


@update.command(name="firmware")
Expand Down
2 changes: 1 addition & 1 deletion pioreactor/cli/pios.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def sync_config_files(unit: str, shared: bool, specific: bool) -> None:

# move the global config.ini
# there was a bug where if the leader == unit, the config.ini would get wiped
if (get_leader_hostname() != unit) and shared:
if shared and unit != get_leader_hostname():
localpath = "/home/pioreactor/.pioreactor/config.ini"
remotepath = "/home/pioreactor/.pioreactor/config.ini"
cp_file_across_cluster(unit, localpath, remotepath)
Expand Down
94 changes: 94 additions & 0 deletions pioreactor/tests/test_temperature_approximation.py
Original file line number Diff line number Diff line change
Expand Up @@ -980,3 +980,97 @@ def test_temperature_approximation15() -> None:
"only_record_temperature", unit=unit, experiment=experiment
) as t:
assert 28.815 <= t.approximate_temperature(features) <= 29.119


@pytest.mark.xfail
def test_temperature_approximation16() -> None:
unit = get_unit_name()

experiment = "test_temperature_approximation16"
features = {
"previous_heater_dc": 18.156877790712812,
"room_temp": 22.0,
"time_series_of_temp": [
29.625,
29.0625,
28.6125,
28.225,
27.8875,
27.625,
27.375,
27.1875,
27.0,
26.825,
26.6875,
26.5625,
26.4375,
26.325,
26.25,
26.1875,
26.125,
26.05,
26.0,
25.9375,
25.8875,
25.875,
25.8125,
25.7875,
25.75,
25.725,
25.6875,
25.6875,
25.625,
],
}

with temperature_control.TemperatureController(
"only_record_temperature", unit=unit, experiment=experiment
) as t:
assert 25.261 <= t.approximate_temperature(features) <= 25.430


@pytest.mark.xfail
def test_temperature_approximation17() -> None:
unit = get_unit_name()

experiment = "test_temperature_approximation17"
features = {
"previous_heater_dc": 18.518440157554934,
"room_temp": 22.0,
"time_series_of_temp": [
29.75,
29.1875,
28.7125,
28.3125,
28.0,
27.6875,
27.475,
27.25,
27.0625,
26.925,
26.7625,
26.625,
26.55,
26.4375,
26.3125,
26.25,
26.1875,
26.125,
26.0625,
26.0,
25.9875,
25.9375,
25.875,
25.8625,
25.8125,
25.8125,
25.75,
25.725,
25.6875,
],
}

with temperature_control.TemperatureController(
"only_record_temperature", unit=unit, experiment=experiment
) as t:
assert 25.295 <= t.approximate_temperature(features) <= 25.430
2 changes: 1 addition & 1 deletion pioreactor/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

# Append "dev" if a dev version
# Append "rc0" if a rc version
__version__ = "23.6.7"
__version__ = "23.6.7.dev"


def _get_hardware_version() -> tuple[int, int] | tuple[int, int, str]:
Expand Down
5 changes: 3 additions & 2 deletions update_scripts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ Possible update scripts and their sequence:

It's very important that update scripts are idempotent. Some tips:

- Use ChatGPT to assist psuedo-check if a script is idempotent, or making suggestions.
> Use ChatGPT to assist psuedo-check if a script is idempotent, or making suggestions.
### bash specific tips
- use `|| true` if a command may fail, but you want to continue anyways
- use `trap` and `EXIT` semantics (like try / expect) to force some code block to always run.
- https://arslan.io/2019/07/03/how-to-write-idempotent-bash-scripts/
- use `|| true` if a command may fail, but you want to continue


### SQL specific tips
Expand Down
3 changes: 1 addition & 2 deletions update_scripts/upcoming/update.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ set -e

export LC_ALL=C


# new naming for python install dirs/
wget -O /usr/local/bin/install_pioreactor_plugin.sh https://raw.githubusercontent.com/Pioreactor/CustoPiZer/pioreactor/workspace/scripts/files/bash/install_pioreactor_plugin.sh
wget -O /usr/local/bin/uninstall_pioreactor_plugin.sh https://raw.githubusercontent.com/Pioreactor/CustoPiZer/pioreactor/workspace/scripts/files/bash/uninstall_pioreactor_plugin.sh
wget -O /usr/local/bin/add_new_pioreactor_worker_from_leader.sh https://raw.githubusercontent.com/Pioreactor/CustoPiZer/pioreactor/workspace/scripts/files/bash/add_new_pioreactor_worker_from_leader.sh

0 comments on commit 6d06c6d

Please sign in to comment.