我如何用 CircuitPython 和開源工具監控溫室
CircuitPython 提供了一種和微控制器板進行交互的革命性方式。這篇文章介紹了如何使用 CircuitPython 來監測溫室的溫度、濕度以及環境光,並且使用 CircuitPython MQTT 客戶端將結果發布到一個 MQTT 中介 。你可以在若干個程序中訂閱 MQTT 隊列並進一步處理信息。
這個項目使用一個簡單的 Python 程序來運行 Web 伺服器,它發布一個 Prometheus 格式的採集端點,拉取監控指標到 Prometheus 進行不間斷的監控。
關於 CircuitPython
CircuitPython 是一個由 Adafruit 創建的開源 Python 發行版,用於運行在低成本微控制器開發板上。CircuitPython 為與 兼容的開發板 的交互提供了簡單的開發體驗。你可以在連接你的開發板時掛載的 CIRCUITPYTHON
根驅動器上創建一個 code.py
文件來啟動你的程序。CircuitPython 還為開發板提供了一個串列連接,包含一個互動式解釋器(REPL)會話,你可以使用 Python 代碼實時和開發板進行交互。
Adafruit 的網站提供了大量的文檔,可以幫助你開始使用 CircuitPython。首先,參考下《歡迎來到 CircuitPython》指南。這份指南能夠幫助你開始使用 CircuitPython 在開發板上運行代碼以及和 REPL 交互。它還記錄了如何安裝 Adafruit 的 CircuitPython 庫合集和範例,可以用在它出售的許多開發板和感測器上。接下來,閱讀《CircuitPython 基礎》指南來學習更多關於其功能的信息,裡面還有鏈接指向在特定及兼容的開發板上使用 CircuitPython 的相關信息。最後,就如所有開源軟體一樣,你可以深入 CircuitPython 的源碼,發布議題,以及做出貢獻。
微控制器設置
微控制器系統非常簡單。要完成這個示例項目,你會需要:
- 樹莓派 4:你需要一台電腦來給微控制器系統編程,我用的是樹莓派 4。
- CircuitPython 兼容的微控制器:我用的是 Adafruit Feather S2,帶有內置 WiFi,環境光感測器,Qwiic 線纜輸入。
- 微控制器 WiFi:Feather S2 內置了 WiFi。如果你的微控制器沒有,你需要給開發板找個 WiFi 擴展板。
- 感測器:Feather S2 有個內置的環境光感測器,所以我還需要一個溫濕度感測器。有很多不同廠商的產品可以選擇,包括 Adafruit、SparkFun、亞馬遜。我用的是一個 Adafruit 感測器,帶有 Feather S2 輸入兼容的 Qwiic 線纜。儘管多數 SparkFun 感測器可以在 Adafruit 庫下工作,但如果你不是從 Adafruit 購買的感測器,你可能還是需要自己去找到它兼容 CircuitPython 的 Python 庫。
- 跳線和線纜:為了避免使用麵包板或焊接,我使用 Adafruit Qwiic 線纜。SparkFun 銷售的包含不同長度的線纜套裝中也有它。
在將微控制器連接到你的電腦之前,將感測器連接到微控制器上。
![將感測器連接到微控制器上](/data/attachment/album/202106/20/152030vahlagmaaytgsr7l.jpg "Connecting sensors to microcontroller")
現在你可以將微控制器用 USB 數據線連接到你的電腦。
MQTT 中介
你可以使用 這份說明 來在樹莓派的系統上安裝 Mosquitto MQTT 中介 和 Mosquitto 客戶端。如果你想把樹莓派做為長期伺服器使用,在你的網路上給樹莓派 4 設置一個靜態 IP 地址。Mosquitto 中介運行起來之後,創建一份 用戶名/密碼文件,設置客戶端向中介發布和訂閱消息時用的認證信息。
你可以用樹莓派上的 Mosquitto 客戶端來測試 MQTT 中介。打開兩個終端(如果你是無界面運行的話打開兩個 SSH 會話):
在終端一輸入:
mosquitto_sub -h localhost -u $user -P $pass -t "mqtt/test"
這條命令會啟動一個持續運行的進程,監聽發布到 mqtt/test
隊列的消息。
在終端二輸入:
mosquitto_pub -h localhost -u $user -P $pass -t "mqtt/test" -m hello`
這條命令會向 mqtt/test
隊列發布一條消息,它應該會顯示在終端一的輸出里。
現在你可以中止終端一運行的 sub
命令了。
Mosquitto 中介允許客戶端發布消息到任何隊列,甚至沒有任何訂閱的隊列也可以。這些消息會永久丟失,但這不會阻止客戶端繼續發布消息。
打開第三個終端,訂閱下列隊列(你的控制器會發布消息到這些隊列上):
- greenhouse/temperature
- greenhouse/light
- greenhouse/humidity
給微控制器編碼
現在你已經準備好給微控制器編碼,發布它的監測指標到樹莓派 4 上運行的 MQTT 中介上了。
Adafruit 有 出色的文檔,指導你使用 CircuitPython 庫合集 的庫來將你的微控制器連接到 WiFi 路由器,並發布監測指標到 MQTT 中介上。
安裝下列庫到 CIRCUITPYTHON/lib
目錄,溫室監控會用到它們。這些庫在 Adafruit 的 CircuitPython 庫合集中都有提供:
adafruit_bus_device
:一個帶有多個 .mpy 文件的 Python 包文件夾(.mpy 是經過壓縮的 Python 文件,用以節省空間)adafruit_requests
:單個 .mpy 文件adafruit_register
:一個包文件夾adafruit_minimqtt
:一個包文件夾adafruit_si7021
:單個 .mpy 文件,用來支持溫濕度感測器
庫裝好了之後,將以下代碼寫入 CIRCUITPYTHON
文件夾的 code.py
文件中:
import time
import ssl
import socketpool
import wifi
import adafruit_minimqtt.adafruit_minimqtt as MQTT
import board
from digitalio import DigitalInOut, Direction, Pull
from analogio import AnalogIn
import adafruit_si7021
# Add a secrets.py to your filesystem that has a dictionary called secrets with "ssid" and
# "password" keys with your WiFi credentials. DO NOT share that file or commit it into Git or other
# source control.
# pylint: disable=no-name-in-module,wrong-import-order
try:
from secrets import secrets
except ImportError:
print("WiFi secrets are kept in secrets.py, please add them there!")
raise
print("Connecting to %s" % secrets["ssid"])
wifi.radio.connect(secrets["ssid"], secrets["password"])
print("Connected to %s!" % secrets["ssid"])
### Feeds ###
light_feed = "greenhouse/light"
temp_feed = "greenhouse/temperature"
humidity_feed = "greenhouse/humidity"
# Define callback methods which are called when events occur
# pylint: disable=unused-argument, redefined-outer-name
def connected(client, userdata, flags, rc):
# This function will be called when the client is connected
# successfully to the broker.
print("Connected to MQTT!")
def disconnected(client, userdata, rc):
# This method is called when the client is disconnected
print("Disconnected from MQTT!")
def get_voltage(pin):
return (pin.value * 3.3) / 65536
# Create a socket pool
pool = socketpool.SocketPool(wifi.radio)
# Set up a MiniMQTT Client
mqtt_client = MQTT.MQTT(
broker=secrets["broker"],
port=secrets["port"],
username=secrets["aio_username"],
password=secrets["aio_key"],
socket_pool=pool,
ssl_context=ssl.create_default_context(),
)
# Setup the callback methods above
mqtt_client.on_connect = connected
mqtt_client.on_disconnect = disconnected
# Connect the client to the MQTT broker.
print("Connecting to MQTT...")
mqtt_client.connect()
# Create library object using our Bus I2C port
sensor = adafruit_si7021.SI7021(board.I2C())
light_pin = AnalogIn(board.IO4)
while True:
# Poll the message queue
mqtt_client.loop()
# get the current temperature
light_val = get_voltage(light_pin)
temp_val = ((sensor.temperature * 9)/5) + 32
humidity_val = sensor.relative_humidity
# Send a new messages
mqtt_client.publish(light_feed, light_val)
mqtt_client.publish(temp_feed, temp_val)
mqtt_client.publish(humidity_feed, humidity_val)
time.sleep(0.5)
保存你的代碼。然後連接到串列監視器,看程序連接到你的 MQTT 中介。你還可以將樹莓派 4 上的終端切換到訂閱了它的發布隊列的終端來查看輸出。
處理監測指標
像 MQTT 這樣的發布/訂閱工作流給微控制器系統提供了諸多好處。你可以有多個微控制器 + 感測器來回報同一個系統的不同指標或並行回報相同指標的若干讀數。你還可以有多個不同進程訂閱各個隊列,並行地對這些消息進行回應。甚至還可以有多個進程訂閱相同的隊列,對消息做出不同的動作,比如數值過高時發送通知郵件或將消息發送到另一個 MQTT 隊列上去。
另一個選項是讓一個微控制器訂閱一個外部隊列,可以發送信號告訴微控制器做出動作,比如關閉或開始一個新會話。最後,發布/訂閱工作流對低功耗微控制器系統更佳(比如那些使用電池或太陽能的系統),因為這些設備可以在更長的延遲周期後批量發布監測指標,並在回報的間隔期間關閉大量消耗電量的 WiFi 廣播。
要處理這些監測指標,我創建了一個 Python 客戶端,使用 Paho Python MQTT 客戶端 訂閱監測指標隊列。我還使用官方的 Prometheus Python 客戶端 創建了一個 Web 伺服器,它產生一個符合 Prometheus 標準的採集端點,使用這些監測指標作為面板信息。Prometheus 伺服器和 Mosquitto MQTT 中介我都是運行在同一個樹莓派 4 上的。
from prometheus_client import start_http_server, Gauge
import random
import time
import paho.mqtt.client as mqtt
gauge = {
"greenhouse/light": Gauge('light','light in lumens'),
"greenhouse/temperature": Gauge('temperature', 'temperature in fahrenheit'),
"greenhouse/humidity": Gauge('humidity','relative % humidity')
}
try:
from mqtt_secrets import mqtt_secrets
except ImportError:
print("WiFi secrets are kept in secrets.py, please add them there!")
raise
def on_connect(client, userdata, flags, rc):
print("Connected with result code "+str(rc))
# Subscribing in on_connect() means that if we lose the connection and
# reconnect then subscriptions will be renewed.
client.subscribe("greenhouse/light")
client.subscribe('greenhouse/temperature')
client.subscribe('greenhouse/humidity')
def on_message(client, userdata, msg):
topic = msg.topic
payload = msg.payload
gauge[topic].set(payload)
client = mqtt.Client()
client.username_pw_set(mqtt_secrets["mqtt_user"],mqtt_secrets['mqtt_password'])
client.on_connect = on_connect
client.on_message = on_message
client.connect('localhost',1883,60)
if __name__ == '__main__':
# Start up the server to expose the metrics.
client = mqtt.Client()
client.username_pw_set('london','abc123')
client.on_connect = on_connect
client.on_message = on_message
client.connect('localhost',1883,60)
start_http_server(8000)
client.loop_forever()
然後我配置 Prometheus 伺服器採集端點數據到 localhost:8000
。
你可以在 Github 上訪問 溫室 MQTT 微控制器 這個項目的代碼,項目採用 MIT 許可證授權。
via: https://opensource.com/article/21/5/monitor-greenhouse-open-source
作者:Darin London 選題:lujun9972 譯者:alim0x 校對:wxy
本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive