Engineer & Coder
Hey, I've been thinking about setting up a small autonomous monitoring system for our lab. It would use a temperature sensor and a microcontroller to trigger an alert if it goes beyond a threshold, and I want to tie that into a notification system that your code can listen to. Do you have any experience with that?
Sounds like a solid idea. Iāve built a few projects like that before ā usually a cheap MCU like an ESP32, a DS18B20 or LM35 for temperature, and then a small server that listens for a webhook. You can push the data over MQTT or even HTTP POST to a Python listener that fires off an email or Slack message when the thresholdās crossed. Let me know what platform youāre using and I can sketch out the code for you.
Great, Iām running the monitoring unit on a RaspberryāÆPi running Raspbian. Iāll use a DS18B20 sensor on a 1āWire bus, connect it to the Piās GPIO, and write a small Python script that polls the sensor every minute. Once the reading exceeds the set threshold I want the script to send an HTTP POST to my central serverās /alert endpoint. The server will parse the payload and trigger an email. Let me know what library or framework youād recommend for the Pi side, and I can start putting the code together.
Iād just use the builtāin w1ātherm kernel support and a tiny Python script. Enable the 1āwire interface in raspiāconfig, then in Python use the w1thermsensor package to read the DS18B20. For the POST just import requests and send a JSON payload. Something like:
```python
from w1thermsensor import W1ThermSensor
import requests, time
sensor = W1ThermSensor()
threshold = 30.0 # degrees C
url = 'https://yourāserver/alert'
while True:
temp = sensor.get_temperature()
if temp > threshold:
payload = {'temp': temp, 'time': time.time()}
try:
requests.post(url, json=payload, timeout=5)
except requests.RequestException:
pass # maybe log the failure
time.sleep(60)
```
Thatās itāno heavy frameworks needed, just the two libs. If you want more resilience you can add a small retry loop or log to a file. Let me know if you need the server side too.
Sounds solid. On the server side Iāll just set up a tiny Flask route that accepts the JSON and fires an email via SMTP. Iāll keep it stateless and add a quick retry if the network hiccups. Let me know if you need a sample or help with the mail part.
Sure thing. Hereās a minimal Flask route that pulls the temp, logs it, and sends an email with smtplib. If the send fails it retries a couple of times. Adjust the host/port/password for your SMTP server.
```python
from flask import Flask, request, jsonify
import smtplib
from email.message import EmailMessage
import time
app = Flask(__name__)
SMTP_HOST = 'smtp.example.com'
SMTP_PORT = 587
SMTP_USER = 'user@example.com'
SMTP_PASS = 'secret'
ALERT_TO = 'alert-recipient@example.com'
def send_mail(subject, body):
msg = EmailMessage()
msg['From'] = SMTP_USER
msg['To'] = ALERT_TO
msg['Subject'] = subject
msg.set_content(body)
for attempt in range(3):
try:
with smtplib.SMTP(SMTP_HOST, SMTP_PORT) as s:
s.starttls()
s.login(SMTP_USER, SMTP_PASS)
s.send_message(msg)
return True
except Exception as e:
if attempt < 2:
time.sleep(5) # small backāoff
else:
print('Failed to send email:', e)
return False
@app.route('/alert', methods=['POST'])
def alert():
data = request.get_json()
temp = data.get('temp')
ts = data.get('time')
subject = f'Temperature alert: {temp:.1f}°C'
body = f'Alert triggered at {time.ctime(ts)} with reading {temp:.1f}°C.'
send_mail(subject, body)
return jsonify({'status': 'sent'}), 200
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
```
That should get you up and running. Let me know if you hit any snags.
Looks good, but Iāll add a quick log file so I can see when alerts are received. Also, Iāll catch JSON errors in the Flask route to avoid crashes if the Pi sends malformed data. Let me know if you need the logger setup.
Add a standard Python logger and wrap the JSON parsing in a try/except. Something like:
```python
import logging
logging.basicConfig(filename='alert.log',
level=logging.INFO,
format='%(asctime)s %(levelname)s: %(message)s')
@app.route('/alert', methods=['POST'])
def alert():
try:
data = request.get_json(force=True)
except Exception as e:
logging.warning('Malformed payload received')
return jsonify({'error': 'invalid json'}), 400
temp = data.get('temp')
ts = data.get('time')
if temp is None or ts is None:
logging.warning('Missing fields in payload')
return jsonify({'error': 'missing data'}), 400
# ā¦send mail, log success
logging.info(f'Alert processed: {temp}°C at {ts}')
return jsonify({'status': 'sent'}), 200
```
That keeps the server tidy and gives you a history of every hit. Let me know if you need more tweaks.