Raspberry Pi

Filo Sağlığı İzleme için Raspberry Pi Sistem İstatistiklerini MQTT ile Yayınlayın

Her Raspberry Pi'den CPU sıcaklığı, yük, bellek, disk kullanımı ve düşük voltaj bayraklarını MQTT'ye yayınlayan, bir Pi çevrim dışı kaldığında last will ile haber veren küçük bir Python servisi.

CPU sıcaklığı ve bellek değerlerini raspberry pi sistem istatistikleri mqtt mesajları olarak merkezi bir broker'a raporlayan birkaç Raspberry Pi kartı
Bunu kendi MQTT broker’ınızda çalıştırınFree planla özel, yönetilen bir MQTT broker alın ve hazır kod örnekleriyle başlayın.
Ücretsiz deneyin Kod örnekleri Kart gerekmez

Raspberry Pi sistem istatistiklerini MQTT mesajları olarak yayınlamak, çalıştırdığınız her Pi'nin sağlıklı olup olmadığını tek bakışta görmenin en basit yoludur. Bu rehberde CPU sıcaklığını, yükü, belleği, disk kullanımını, çalışma süresini ve güç kısıtlama (throttling) bayraklarını sabit aralıklarla raporlayan, retained bir durum mesajıyla kendini çevrim içi ilan eden ve last will sayesinde broker'ın onu çevrim dışı olarak işaretlemesine izin veren bir Python servisi yazacaksınız. Aynı betik tek bir Pi'de de elli Pi'de de değişmeden çalışır.

Raspberry Pi'ler Neden MQTT ile İzlenmeli

Sahadaki Pi'ler öngörülebilir şekillerde arızalanır: SD kartlar loglarla dolar, kasalar ısıyı hapseder ve CPU kendini kısıtlar, ucuz güç adaptörleri düşük voltaja yol açar, Wi-Fi kopmaları da cihazı sessizce erişilemez hale getirir. Geleneksel izleme yığınları her makineyi tek tek sorgular; bu da port açmak ya da gelen erişim gerektiren bir ajan çalıştırmak demektir. MQTT bu düzeni tersine çevirir. Her Pi broker'a tek bir giden bağlantı kurar ve kendi verilerini gönderir; böylece NAT arkasında, mobil router'larda ve kontrolünüzde olmayan ağlarda da çalışır.

Broker ayrıca varlık bilgisini (presence) bedavaya verir. Retained bir online durumu ve offline değerinde bir last will ile abone olan her dashboard, her Pi'nin güncel durumunu anında görür ve bir cihaz kaybolduğunda broker bunu günceller. Mekanizma size yabancıysa önce bir MQTT broker'ın ne yaptığını okuyun.

Metrikler ve Kaynakları

Metrik Kaynak Neden önemli
cpu_temp /sys/class/thermal/thermal_zone0/temp Sıcaklık yükseldikçe kısıtlama başlar
load1, load5 os.getloadavg() Çekirdek sayısının üzerinde süren yük birikmiş iş demektir
cpu_pct psutil.cpu_percent() Kısa vadeli CPU kullanımı
mem_pct psutil.virtual_memory() Uzun süre çalışan servislerdeki bellek sızıntıları
disk_pct psutil.disk_usage("/") Dolu bir kök dosya sistemi her şeyi bozar
uptime_s psutil.boot_time() Beklenmedik yeniden başlatmalar sıfırlanma olarak görünür
throttled vcgencmd get_throttled Düşük voltaj ve termal kısıtlama bayrakları
wifi_rssi /proc/net/wireless Zayıf sinyal kopmaları açıklar

get_throttled değeri bir bit alanıdır. Bit 0 şu anda düşük voltaj olduğunu, bit 2 şu anda kısıtlama yapıldığını, bit 16 ve 18 ise bu durumların açılıştan beri yaşandığını gösterir. Sıfırdan farklı bir değer tek başına alarm sebebidir; çünkü neredeyse her zaman eninde sonunda SD kartı bozacak bir güç kaynağı sorununa işaret eder. Raspberry Pi dokümantasyonu tüm bitleri listeler.

Bir Filo için Topic Tasarımı

Her cihaz için bir alt ağaç kullanın ve cihaz kimliği olarak hostname'i seçin. Ücretsiz genel MQTT broker'ında test ederken, başkalarının verileriyle çakışmaması için rastgele bir segment ekleyin:

connectmq/demo/a9e217/fleet/<hostname>/stats     JSON, every 30 s, not retained
connectmq/demo/a9e217/fleet/<hostname>/status    "online" / "offline", retained, last will

İzleme istemcisi ardından connectmq/demo/a9e217/fleet/+/status ve connectmq/demo/a9e217/fleet/+/stats topic'lerine abone olur ve yeni Pi'leri ilk yayınlarında otomatik olarak keşfeder.

Bağımlılıkları Kurun

Servisin sistem Python paketlerine bağımlı olmaması için her Pi'de bir sanal ortam oluşturun:

sudo apt update && sudo apt install -y python3-venv
python3 -m venv ~/pistats-env
~/pistats-env/bin/pip install "paho-mqtt>=2.0" psutil

Raspberry Pi Sistem İstatistikleri MQTT Yayıncısı

Bunu ~/pistats.py olarak kaydedin:

#!/usr/bin/env python3
"""Publish Raspberry Pi health metrics over MQTT."""
import json
import os
import socket
import ssl
import subprocess
import time

import paho.mqtt.client as mqtt
import psutil

HOST = os.getenv("MQTT_HOST", "broker.connectmq.com")
PORT = int(os.getenv("MQTT_PORT", "1883"))
USERNAME = os.getenv("MQTT_USERNAME")          # üretimde YOUR_USERNAME
PASSWORD = os.getenv("MQTT_PASSWORD")          # üretimde YOUR_PASSWORD
HOSTNAME = socket.gethostname()
CLIENT_ID = os.getenv("MQTT_CLIENT_ID", f"pistats-{HOSTNAME}-a9e217")
PREFIX = os.getenv("MQTT_PREFIX", "connectmq/demo/a9e217/fleet")
INTERVAL = int(os.getenv("INTERVAL", "30"))

STATS_TOPIC = f"{PREFIX}/{HOSTNAME}/stats"
STATUS_TOPIC = f"{PREFIX}/{HOSTNAME}/status"


def cpu_temp():
    try:
        with open("/sys/class/thermal/thermal_zone0/temp") as f:
            return round(int(f.read().strip()) / 1000, 1)
    except (OSError, ValueError):
        return None


def throttled():
    try:
        out = subprocess.run(["vcgencmd", "get_throttled"],
                             capture_output=True, text=True, timeout=2).stdout
        return int(out.strip().split("=")[1], 16)
    except (OSError, IndexError, ValueError, subprocess.TimeoutExpired):
        return None


def wifi_rssi():
    try:
        with open("/proc/net/wireless") as f:
            lines = f.readlines()[2:]
        for line in lines:
            parts = line.split()
            if parts and parts[0].startswith("wlan"):
                return int(float(parts[3]))
    except (OSError, IndexError, ValueError):
        pass
    return None


def collect():
    load1, load5, _ = os.getloadavg()
    t = throttled()
    return {
        "ts": int(time.time()),
        "cpu_temp": cpu_temp(),
        "cpu_pct": psutil.cpu_percent(interval=None),
        "load1": round(load1, 2),
        "load5": round(load5, 2),
        "mem_pct": psutil.virtual_memory().percent,
        "disk_pct": psutil.disk_usage("/").percent,
        "uptime_s": int(time.time() - psutil.boot_time()),
        "throttled": t,
        "undervoltage_now": bool(t & 0x1) if t is not None else None,
        "undervoltage_seen": bool(t & 0x10000) if t is not None else None,
        "wifi_rssi": wifi_rssi(),
    }


def on_connect(client, userdata, flags, reason_code, properties):
    if reason_code.is_failure:
        print(f"Connect failed: {reason_code}")
        return
    print(f"Connected to {HOST}:{PORT} as {CLIENT_ID}")
    client.publish(STATUS_TOPIC, "online", qos=1, retain=True)


def on_disconnect(client, userdata, flags, reason_code, properties):
    print(f"Disconnected: {reason_code}, paho will reconnect")


client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2,
                     client_id=CLIENT_ID, protocol=mqtt.MQTTv5)
if USERNAME:
    client.username_pw_set(USERNAME, PASSWORD)
if PORT == 8883:
    client.tls_set(cert_reqs=ssl.CERT_REQUIRED)
client.will_set(STATUS_TOPIC, "offline", qos=1, retain=True)
client.on_connect = on_connect
client.on_disconnect = on_disconnect
client.reconnect_delay_set(min_delay=2, max_delay=60)

client.connect_async(HOST, PORT, keepalive=60)
client.loop_start()
psutil.cpu_percent(interval=None)  # sayacı hazırla

try:
    while True:
        time.sleep(INTERVAL)
        if client.is_connected():
            client.publish(STATS_TOPIC, json.dumps(collect()), qos=0)
finally:
    client.publish(STATUS_TOPIC, "offline", qos=1, retain=True).wait_for_publish(3)
    client.disconnect()
    client.loop_stop()

Bazı bilinçli tercihler: istatistikler QoS 0 kullanır, çünkü arada bir örneğin kaybolması önemli değildir ve bir sonraki kısa süre içinde gelir. Durum mesajı QoS 1 ve retain kullanır, çünkü varlık bilgisi doğru olmalıdır. connect_async ile loop_start, açılışta ağ henüz hazır olmasa bile betiğin başlamasını sağlar ve paho arka planda yeniden denemeye devam eder. Düzgün bir kapanışta finally bloğu offline mesajını açıkça yayınlar, çünkü last will yalnızca beklenmedik bir bağlantı kopmasında tetiklenir.

Betiği bir kez elle çalıştırın ve çıktıyı başka bir makineden izleyin:

~/pistats-env/bin/python ~/pistats.py
mosquitto_sub -h broker.connectmq.com -p 1883 -i watcher-a9e217 \
  -t 'connectmq/demo/a9e217/fleet/#' -v

Pi'nin ağ kablosunu çekin; yaklaşık bir buçuk keepalive aralığı sonra broker onun adına offline yayınlar. İşini yapan şey MQTT last will özelliğidir.

systemd Servisi Olarak Çalıştırın

Kimlik bilgilerini betiğin dışında tutmak için bir ortam dosyası oluşturun:

sudo tee /etc/pistats.env >/dev/null <<'EOF'
MQTT_HOST=broker.connectmq.com
MQTT_PORT=1883
INTERVAL=30
EOF
sudo chmod 600 /etc/pistats.env
sudo tee /etc/systemd/system/pistats.service >/dev/null <<'EOF'
[Unit]
Description=Publish Raspberry Pi stats over MQTT
After=network-online.target
Wants=network-online.target

[Service]
User=pi
EnvironmentFile=/etc/pistats.env
ExecStart=/home/pi/pistats-env/bin/python /home/pi/pistats.py
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now pistats
journalctl -u pistats -f

Kullanıcıyı ve yolları kendi hesabınıza göre ayarlayın. Açılışta çalışan betiklere dair daha fazla kalıp için Python MQTT betiğini açılışta çalıştırma yazısına bakın.

Filoyu Özel Bir Broker'a Taşımak

Sistem istatistikleri hostname, çalışma süresi ve ağ ayrıntılarını açığa çıkarır; bu yüzden gerçek bir filo genel bir broker'a raporlamamalıdır. Bir bulut MQTT broker'ı olan ConnectMQ ile portalda bir broker oluşturur ve kimlik bilgilerinizi alırsınız. Yalnızca ortam dosyasını değiştirin:

MQTT_HOST=broker.connectmq.com
MQTT_PORT=8883
MQTT_USERNAME=YOUR_USERNAME
MQTT_PASSWORD=YOUR_PASSWORD
MQTT_CLIENT_ID=YOUR_CLIENT_ID
MQTT_PREFIX=site1/fleet

ConnectMQ client ID'leri verilen kimlik bilgilerine bağlar; bu nedenle her Pi'nin portaldan alınmış kendi kimlik bilgisi seti olmalıdır. 8883 portu, Pi'nin zaten güvendiği bir Let's Encrypt sertifikasıyla TLS kullanır. Ücretsiz Serverless planı 25 bağlantıya kadar izin verir; bu, oldukça büyük bir ev veya laboratuvar filosunu karşılar. Ücretli Serverless planı ise çok daha ileri gider.

ConnectMQ portalı ek yazılım gerektirmeden izleme tarafında da yardımcı olur. Canlı topic gezgini her Pi'nin son istatistiklerini gösterir; eşik alarm kuralları da cpu_temp gibi bir değerin bir sınırı aşmasını işaretleyebilir ve sonradan incelemek için bir alarm kaydı tutulur.

Anlamlı Alarm Eşikleri Seçmek

Sayı toplamak kolaydır; hangilerinin bildirimi hak ettiğine karar vermek ise filo izlemenin asıl değer kattığı yerdir. Sürekli çalan alarmlar görmezden gelinir; bu yüzden neredeyse her zaman gerçek bir soruna işaret eden kısa bir koşul listesiyle başlayın:

  • Açılıştan beri düşük voltaj görülmesi. Sıfırdan farklı her undervoltage_seen değeri zayıf bir güç kaynağına veya ince bir USB kablosuna işaret eder. SD kartı bozmadan önce düzeltin.
  • CPU sıcaklığının yüksek kalması. Güncellemeler sırasındaki kısa sıçramalar normaldir. Dakikalarca kısıtlama noktasına yakın kalan bir sıcaklık; tıkalı bir havalandırma, eksik bir soğutucu veya doğrudan güneş alan bir kasa demektir.
  • Yaklaşık yüzde 90'ın üzerinde disk kullanımı. Loglar ve container imajları sessizce büyür. Dolu bir kök dosya sistemi paket güncellemelerini, veritabanlarını ve bazen açılışın kendisini bozar.
  • Çalışma süresinin beklenmedik şekilde sıfırlanması. uptime_s planlı bir yeniden başlatma olmadan düşerse Pi çökmüş ya da gücü kesilmiştir; sebep genellikle güç veya ısıdır.
  • Birkaç aralıktan uzun süre çevrim dışı kalmak. Kısa bir Wi-Fi kesintisi kimseyi alarma geçirmesin diye retained durumu son istatistik mesajının yaşıyla birleştirin.

Yük ortalaması ve bellek, alarm yerine trend olarak izlendiğinde daha faydalıdır. Günler içinde yavaş bir artış, genellikle sızıntı yapan bir servisi sorun çıkarmadan çok önce ortaya çıkarır.

Verileri Kullanmak

Sayılar akmaya başladığında ne kadar araç istediğinize karar verin:

  1. Hızlı bakış: ConnectMQ'nun topic gezgini veya herhangi bir masaüstü MQTT istemcisi.
  2. Duvar ekranı: Raspberry Pi kiosk dashboard'u her Pi için bir kutucuk gösterebilir.
  3. Geçmiş ve grafikler: Raspberry Pi Grafana ve InfluxDB rehberindeki gibi Telegraf'tan InfluxDB'ye, üzerinde Grafana ile.

Sorun Giderme

Belirti Sebep Çözüm
throttled değeri null vcgencmd eksik veya izin yok libraspberrypi-bin kurun, kullanıcıyı video grubuna ekleyin
İlk örnekte cpu_pct hep 0.0 Sayaç hazırlanmamış Betik döngüden önce sayacı hazırlar
Durum sürekli online ve offline arasında gidip geliyor Aynı client ID'ye sahip iki Pi Her Pi'ye benzersiz bir client ID verin
Kablo çekildikten sonra offline hiç gelmiyor Keepalive zaman aşımı bekleniyor Keepalive'ın yaklaşık 1,5 katı kadar bekleyin
Ethernet'te wifi_rssi değeri null Kablosuz arayüz yok Beklenen durum; görmezden gelin veya alanı kaldırın

ConnectMQ ile Başlayın

Her Pi'nin sağlık durumunu tek bir yerde toplayın: app.connectmq.com adresinden kaydolun, kredi kartı olmadan ücretsiz bir Serverless broker oluşturun ve kimlik bilgilerini /etc/pistats.env dosyasına ekleyin. Pi projelerinin tüm serisi için Raspberry Pi MQTT rehberiyle başlayın.

Sık Sorulan Sorular

Bir Raspberry Pi sistem istatistiklerini ne sıklıkla yayınlamalı?

Sağlık izleme için 30 ila 60 saniyede bir yeterlidir. Daha kısa aralıklar fazla bir şey göstermeden trafiği artırır; çünkü sıcaklık ve disk kullanımı yavaş değişir.

İstatistik yayınlamak Raspberry Pi'yi yavaşlatır mı?

Kayda değer ölçüde hayır. Birkaç dosyayı okuyup 30 saniyede bir küçük bir JSON mesajı göndermek, bir Pi Zero 2 W'de bile ihmal edilebilir bir yüktür.

Bir Pi'nin çevrim dışı olduğunu nasıl anlarım?

Retained durum topic'ine abone olun. Betik offline değerinde bir last will ayarlar; böylece Pi beklenmedik şekilde bağlantıyı kopardığında broker bunu otomatik olarak yayınlar.

GPU sıcaklığı veya özel metrikler ekleyebilir miyim?

Evet, collect() sözlüğüne alanlar ekleyin. Güncel Pi modellerinde CPU ve GPU aynı yonga üzerindedir; dolayısıyla termal bölge değeri zaten ikisini birden yansıtır.

İlgili yazılar

RC522 Okuyucu ile Raspberry Pi RFID MQTT Erişim Kaydı

Bir RC522 RFID okuyucuyu Raspberry Pi'ye bağlayın, etiketleri Python ile okuyun, yerel bir izin listesiyle karşılaştırın ve her erişim denemesini kayıt araçlarının, panellerin ve uyarı araçlarının tüketebileceği bir MQTT olayı olarak yayınlayın.

6 dk okuma

Tüm yazılar →

Özel MQTT broker’ınız birkaç tık uzağınızda

Hesabınızı oluşturun, broker kimlik bilgilerinizi alın ve ilk cihazınızı bağlayın — kurulacak, yamalanacak ya da ölçeklendirilecek sunucu yok.