Skip to content

Commit 2252105

Browse files
new mqtt config
1 parent ab3f9fc commit 2252105

File tree

11 files changed

+84
-31
lines changed

11 files changed

+84
-31
lines changed

CHANGELOG.md

+7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
### Upcoming
22
- fixed `datum` bug in the Overview that was crashing the UI. Sorry!
33
- introducing some outlier protection in growth rate calculations. This is tunable with the `ekf_outlier_std_threshold` value under `[growth_rate_calculating.config]`. The default value, 5.0, is pretty conservative, and will still allow some spikes to permeate to the growth rate and nOD. Try a value of 3.5 or 4.0 if you want to see more. Don't put it less than 3.0 - that's silly.
4+
- added options alternative mqtt brokers with the new configuration
5+
```
6+
[mqtt]
7+
mqtt_username=pioreactor
8+
mqtt_password=raspberry
9+
broker_address=
10+
```
411

512

613
### 24.2.11

config.dev.ini

+7
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,13 @@ send_errors_to_Pioreactor=1
111111
send_od_statistics_to_Pioreactor=1
112112

113113

114+
[mqtt]
115+
username=pioreactor
116+
password=raspberry
117+
broker_address=localhost
118+
broker_ws_port=9001
119+
broker_port=1883
120+
ws_protocol=ws
114121

115122
[growth_rate_kalman]
116123
acc_std=0.0008

migration_scripts/import_data.sh

+12-9
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ ARCHIVE_HOSTNAME=$(echo "$ARCHIVE_NAME" | cut -d'_' -f 2)
1616
# Get the current hostname of the system
1717
CURRENT_HOSTNAME=$(hostname)
1818

19+
PIO_DIR=/home/pioreactor/.pioreactor
20+
21+
1922
# the hostname of this system and the archive file should be the same. Exit if not.
2023
if [ "$ARCHIVE_HOSTNAME" != "$CURRENT_HOSTNAME" ]; then
2124
echo "Error: Hostname of the archive does not match this hostname."
@@ -30,32 +33,32 @@ sudo systemctl stop lighttpd.service || true
3033
sudo systemctl stop huey.service || true
3134

3235
# blow away the old .pioreactor
33-
rm -rf /home/pioreactor/.pioreactor/
36+
rm -rf $PIO_DIR/
3437

3538
# create the new .pioreactor/
3639
tar -xzf $ARCHIVE_NAME
3740

3841

39-
leader_hostname=$(crudini --get /home/pioreactor/.pioreactor/config.ini cluster.topology leader_hostname)
42+
leader_hostname=$(crudini --get $PIO_DIR/config.ini cluster.topology leader_hostname)
4043

4144
if [ "$leader_hostname" = "$CURRENT_HOSTNAME" ]; then
4245
# rename the sqlite .backup, if leader
43-
mv /home/pioreactor/.pioreactor/storage/pioreactor.sqlite.backup /home/pioreactor/.pioreactor/storage/pioreactor.sqlite
44-
touch /home/pioreactor/.pioreactor/storage/pioreactor.sqlite-shm
45-
touch /home/pioreactor/.pioreactor/storage/pioreactor.sqlite-wal
46+
mv $PIO_DIR/storage/pioreactor.sqlite.backup $PIO_DIR/storage/pioreactor.sqlite
47+
touch $PIO_DIR/storage/pioreactor.sqlite-shm
48+
touch $PIO_DIR/storage/pioreactor.sqlite-wal
4649

4750
# check integrity, quickly
48-
DB_CHECK=$(sqlite3 /home/pioreactor/.pioreactor/storage/pioreactor.sqlite "PRAGMA quick_check;")
51+
DB_CHECK=$(sqlite3 $PIO_DIR/storage/pioreactor.sqlite "PRAGMA quick_check;")
4952
if [[ "$DB_CHECK" != "ok" ]]; then
5053
echo "Database integrity check failed: $DB_CHECK"
5154
fi
5255

5356
fi
5457

5558
# confirm permissions
56-
chmod -R 770 /home/pioreactor/.pioreactor/storage/
57-
chown -R pioreactor:www-data /home/pioreactor/.pioreactor/storage/
58-
chmod g+s /home/pioreactor/.pioreactor/storage/
59+
chmod -R 770 $PIO_DIR/storage/
60+
chown -R pioreactor:www-data $PIO_DIR/storage/
61+
chmod g+s $PIO_DIR/storage/
5962

6063
echo "Done! Rebooting..."
6164

pioreactor/actions/od_calibration.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
from pioreactor.whoami import is_testing_env
4040

4141

42+
4243
def green(string):
4344
return style(string, fg="green")
4445

@@ -75,6 +76,7 @@ def get_name_from_user() -> str:
7576
default=f"od-cal-{current_utc_datestamp()}",
7677
show_default=False,
7778
).strip()
79+
7880
if name == "":
7981
echo("Name cannot be empty")
8082
continue
@@ -88,7 +90,7 @@ def get_name_from_user() -> str:
8890
return name
8991

9092

91-
def get_metadata_from_user():
93+
def get_metadata_from_user() -> tuple[pt.OD600, pt.OD600, pt.mL, pt.PdAngle, pt.PdChannel]:
9294
initial_od600 = prompt(
9395
green("Provide the OD600 measurement of your initial, high density, culture"),
9496
type=click.FloatRange(min=0.01, clamp=False),
@@ -105,6 +107,7 @@ def get_metadata_from_user():
105107
type=click.FloatRange(min=0, max=initial_od600, clamp=False),
106108
)
107109

110+
assert isinstance(minimum_od600, )
108111
if minimum_od600 == 0:
109112
minimum_od600 = 0.01
110113

@@ -128,6 +131,7 @@ def get_metadata_from_user():
128131

129132
ref_channel = config["od_config.photodiode_channel_reverse"]["REF"]
130133
signal_channel = "1" if ref_channel == "2" else "2"
134+
#assert isinstance(signal_channel, pt.PdChannel)
131135

132136
confirm(
133137
green(
@@ -136,7 +140,8 @@ def get_metadata_from_user():
136140
abort=True,
137141
default=True,
138142
)
139-
angle = str(config["od_config.photodiode_channel"][signal_channel])
143+
angle = config["od_config.photodiode_channel"][signal_channel]
144+
#assert isinstance(angle, pt.PdAngle)
140145
return initial_od600, minimum_od600, dilution_amount, angle, signal_channel
141146

142147

pioreactor/background_jobs/base.py

-4
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
from pioreactor import structs
1717
from pioreactor import types as pt
1818
from pioreactor.config import config
19-
from pioreactor.config import leader_address
2019
from pioreactor.config import leader_hostname
2120
from pioreactor.logging import create_logger
2221
from pioreactor.pubsub import Client
@@ -269,7 +268,6 @@ def __init__(self, unit: str, experiment: str, source: str = "app") -> None:
269268
unit=self.unit,
270269
experiment=self.experiment,
271270
source=self._source,
272-
mqtt_hostname=leader_address,
273271
)
274272

275273
self._check_for_duplicate_activity()
@@ -576,7 +574,6 @@ def _check_published_settings(published_settings: dict[str, pt.PublishableSettin
576574
def _create_pub_client(self) -> Client:
577575
# see note above as to why we split pub and sub.
578576
client = create_client(
579-
hostname=leader_address,
580577
client_id=f"{self.job_name}-pub-{self.unit}-{self.experiment}",
581578
keepalive=15 * 60,
582579
)
@@ -609,7 +606,6 @@ def on_disconnect(client, userdata, rc: int) -> None:
609606
}
610607

611608
client = create_client(
612-
hostname=leader_address,
613609
client_id=f"{self.job_name}-sub-{self.unit}-{self.experiment}",
614610
last_will=last_will,
615611
keepalive=60,

pioreactor/background_jobs/monitor.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from pioreactor.background_jobs.base import BackgroundJob
2222
from pioreactor.config import config
2323
from pioreactor.config import get_config
24-
from pioreactor.config import leader_address
24+
from pioreactor.config import mqtt_address
2525
from pioreactor.config import leader_hostname
2626
from pioreactor.hardware import GPIOCHIP
2727
from pioreactor.hardware import is_HAT_present
@@ -397,7 +397,7 @@ def check_for_mqtt_connection_to_leader(self) -> None:
397397

398398
self.logger.warning(
399399
f"""Not able to connect MQTT clients to leader.
400-
1. Is the leader, {leader_hostname} at {leader_address}, in config.ini correct?
400+
1. Is the {mqtt_address=}, in config.ini correct?
401401
2. Is the Pioreactor leader online and responsive?
402402
"""
403403
) # remember, this doesn't get published to leader...

pioreactor/config.py

+12
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ def __getattr__(attr): # type: ignore
1515
return get_leader_hostname()
1616
elif attr == "leader_address":
1717
return get_leader_address()
18+
elif attr == "mqtt_address":
19+
return get_mqtt_address()
20+
elif attr == "mqtt_port":
21+
return get_mqtt_port()
1822
else:
1923
raise AttributeError
2024

@@ -172,6 +176,14 @@ def get_leader_hostname() -> str:
172176
def get_leader_address() -> str:
173177
return get_config().get("cluster.topology", "leader_address", fallback="localhost")
174178

179+
@cache
180+
def get_mqtt_address() -> str:
181+
return get_config().get("mqtt", "broker_address", fallback=get_leader_address())
182+
183+
@cache
184+
def get_mqtt_port() -> str:
185+
return get_config().getint("mqtt", "broker_port", fallback=1883)
186+
175187

176188
def check_firstboot_successful() -> bool:
177189
from pioreactor.whoami import is_testing_env

pioreactor/logging.py

-2
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,6 @@ def create_logger(
130130
experiment: Optional[str] = None,
131131
source: str = "app",
132132
to_mqtt: bool = True,
133-
mqtt_hostname: Optional[str] = None,
134133
) -> CustomLogger:
135134
"""
136135
@@ -195,7 +194,6 @@ def create_logger(
195194

196195
if to_mqtt:
197196
pub_client = create_client(
198-
hostname=mqtt_hostname,
199197
client_id=f"{name}-logging-{unit}-{experiment}",
200198
max_connection_attempts=2,
201199
keepalive=15 * 60,

pioreactor/pubsub.py

+19-12
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212

1313
from paho.mqtt.client import Client as PahoClient
1414

15-
from pioreactor.config import leader_address
15+
from pioreactor.config import mqtt_address
16+
from pioreactor.config import mqtt_port
17+
from pioreactor.config import config
1618
from pioreactor.types import MQTTMessage
1719

1820

@@ -70,7 +72,7 @@ class QOS:
7072

7173

7274
def create_client(
73-
hostname: Optional[str] = None,
75+
hostname: str = mqtt_address,
7476
last_will: Optional[dict] = None,
7577
client_id: str = "",
7678
keepalive=60,
@@ -80,6 +82,7 @@ def create_client(
8082
on_disconnect: Optional[Callable] = None,
8183
on_message: Optional[Callable] = None,
8284
userdata: Optional[dict] = None,
85+
port: int = mqtt_port
8386
):
8487
"""
8588
Create a MQTT client and connect to a host.
@@ -98,7 +101,10 @@ def default_on_connect(client: Client, userdata, flags, rc: int, properties=None
98101
clean_session=clean_session,
99102
userdata=userdata,
100103
)
101-
client.username_pw_set("pioreactor", "raspberry")
104+
client.username_pw_set(
105+
config.get("mqtt", "username", fallback="pioreactor"),
106+
config.get("mqtt", "password", fallback="raspberry")
107+
)
102108

103109
if on_connect:
104110
client.on_connect = on_connect # type: ignore
@@ -114,12 +120,9 @@ def default_on_connect(client: Client, userdata, flags, rc: int, properties=None
114120
if last_will is not None:
115121
client.will_set(**last_will)
116122

117-
if hostname is None:
118-
hostname = leader_address
119-
120123
for retries in range(1, max_connection_attempts + 1):
121124
try:
122-
client.connect(hostname, keepalive=keepalive)
125+
client.connect(hostname, port, keepalive=keepalive)
123126
except (socket.gaierror, OSError):
124127
if retries == max_connection_attempts:
125128
break
@@ -131,7 +134,7 @@ def default_on_connect(client: Client, userdata, flags, rc: int, properties=None
131134
return client
132135

133136

134-
def publish(topic: str, message, hostname: str = leader_address, retries: int = 10, **mqtt_kwargs) -> None:
137+
def publish(topic: str, message, hostname: str = mqtt_address, retries: int = 10, port: int = mqtt_port, **mqtt_kwargs) -> None:
135138
from paho.mqtt import publish as mqtt_publish
136139
import socket
137140

@@ -141,6 +144,7 @@ def publish(topic: str, message, hostname: str = leader_address, retries: int =
141144
topic,
142145
payload=message,
143146
hostname=hostname,
147+
port=port,
144148
auth={"username": "pioreactor", "password": "raspberry"},
145149
**mqtt_kwargs,
146150
)
@@ -164,11 +168,12 @@ def publish(topic: str, message, hostname: str = leader_address, retries: int =
164168

165169
def subscribe(
166170
topics: str | list[str],
167-
hostname: str = leader_address,
171+
hostname: str = mqtt_address,
168172
retries: int = 5,
169173
timeout: Optional[float] = None,
170174
allow_retained: bool = True,
171175
name: Optional[str] = None,
176+
port: int = mqtt_port,
172177
**mqtt_kwargs,
173178
) -> Optional[MQTTMessage]:
174179
"""
@@ -222,7 +227,7 @@ def on_message(client: Client, userdata, message: MQTTMessage) -> None:
222227
client.username_pw_set("pioreactor", "raspberry")
223228
client.on_connect = on_connect # type: ignore
224229
client.on_message = on_message # type: ignore
225-
client.connect(hostname)
230+
client.connect(hostname, port=port)
226231

227232
if timeout is None:
228233
client.loop_forever()
@@ -255,11 +260,12 @@ def on_message(client: Client, userdata, message: MQTTMessage) -> None:
255260
def subscribe_and_callback(
256261
callback: Callable[[MQTTMessage], Any],
257262
topics: str | list[str],
258-
hostname: str = leader_address,
263+
hostname: str = mqtt_address,
259264
last_will: Optional[dict] = None,
260265
name: Optional[str] = None,
261266
allow_retained: bool = True,
262267
client: Optional[Client] = None,
268+
port: int = mqtt_port,
263269
**mqtt_kwargs,
264270
) -> Client:
265271
"""
@@ -313,6 +319,7 @@ def on_connect(client: Client, userdata: dict, *args):
313319
on_connect=on_connect,
314320
on_message=wrap_callback(callback),
315321
userdata=userdata,
322+
port=port,
316323
**mqtt_kwargs,
317324
)
318325

@@ -325,7 +332,7 @@ def on_connect(client: Client, userdata: dict, *args):
325332
return client
326333

327334

328-
def prune_retained_messages(topics_to_prune: str = "#", hostname=leader_address):
335+
def prune_retained_messages(topics_to_prune: str = "#", hostname=mqtt_address):
329336
topics = []
330337

331338
def on_message(message):

pioreactor/types.py

+1
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ class PublishableSetting(t.TypedDict, total=False):
100100
AnalogValue = t.Union[int, float]
101101
Voltage = float # maybe should be non-negative?
102102
OD = t.Annotated[float, Meta(ge=0)]
103+
OD600 = t.Annotated[float, Meta(ge=0)]
103104

104105
AdcChannel = t.Literal[0, 1, 2, 3]
105106

update_scripts/upcoming/update.sh

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#!/bin/bash
2+
3+
set -x
4+
set -e
5+
6+
export LC_ALL=C
7+
8+
PIO_DIR=/home/pioreactor/.pioreactor
9+
10+
11+
# update MQTT configuration
12+
LEADER_ADDRESS=$(crudini --get $PIO_DIR/config.ini cluster.inventory leader_address)
13+
14+
crudini --ini-options=nospace --set $PIO_DIR/config.ini mqtt username pioreactor \
15+
--set $PIO_DIR/config.ini mqtt password raspberry \
16+
--set $PIO_DIR/config.ini mqtt broker_address "$LEADER_ADDRESS" \
17+
--set $PIO_DIR/config.ini mqtt broker_port 9001

0 commit comments

Comments
 (0)