Python 物聯網(IoT)與邊緣計算開發實戰(1)

Python 物聯網(IoT)與邊緣計算開發實戰
https://www.python.org/static/community_logos/python-logo-master-v3-TM.png

物聯網基礎與硬件交互
Raspberry Pi GPIO控制
python
import RPi.GPIO as GPIO
import time

# 設置GPIO模式
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

# 定義引腳
LED_PIN = 17
BUTTON_PIN = 18

# 初始化引腳
GPIO.setup(LED_PIN, GPIO.OUT)
GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)

def blink_led(times, speed=0.5):
? ? """LED閃爍效果"""
? ? for _ in range(times):
? ? ? ? GPIO.output(LED_PIN, GPIO.HIGH)
? ? ? ? time.sleep(speed)
? ? ? ? GPIO.output(LED_PIN, GPIO.LOW)
? ? ? ? time.sleep(speed)

try:
? ? print("按下按鈕控制LED (Ctrl+C退出)")
? ? while True:
? ? ? ? if GPIO.input(BUTTON_PIN) == GPIO.LOW:
? ? ? ? ? ? print("按鈕按下 - LED閃爍")
? ? ? ? ? ? blink_led(3, 0.3)
? ? ? ? ? ? time.sleep(0.5) ?# 防抖延遲
finally:
? ? GPIO.cleanup() ?# 清理GPIO設置
https://www.raspberrypi.com/documentation/computers/images/GPIO-Pinout-Diagram-2.png

傳感器數據采集
python
import Adafruit_DHT
import time

# 設置傳感器類型和引腳
DHT_SENSOR = Adafruit_DHT.DHT22
DHT_PIN = 4

def read_sensor():
? ? """讀取溫濕度傳感器數據"""
? ? humidity, temperature = Adafruit_DHT.read_retry(DHT_SENSOR, DHT_PIN)
? ? if humidity is not None and temperature is not None:
? ? ? ? return {
? ? ? ? ? ? 'temperature': round(temperature, 1),
? ? ? ? ? ? 'humidity': round(humidity, 1),
? ? ? ? ? ? 'timestamp': time.strftime('%Y-%m-%d %H:%M:%S')
? ? ? ? }
? ? else:
? ? ? ? print("傳感器讀取失敗!")
? ? ? ? return None

# 每5秒讀取一次數據
while True:
? ? sensor_data = read_sensor()
? ? if sensor_data:
? ? ? ? print(f"溫度: {sensor_data['temperature']}°C, 濕度: {sensor_data['humidity']}%")
? ? time.sleep(5)
物聯網通信協議
MQTT協議實現
python
import paho.mqtt.client as mqtt
import json
import time

# MQTT配置
MQTT_BROKER = "broker.example.com"
MQTT_PORT = 1883
MQTT_TOPIC_PUB = "sensor/data"
MQTT_TOPIC_SUB = "sensor/control"
CLIENT_ID = "python-iot-client"

# 傳感器模擬數據
def get_sensor_data():
? ? return {
? ? ? ? "device_id": CLIENT_ID,
? ? ? ? "temperature": 25.5 + (time.time() % 3),
? ? ? ? "humidity": 50 + (time.time() % 10),
? ? ? ? "timestamp": int(time.time())
? ? }

# 連接回調
def on_connect(client, userdata, flags, rc):
? ? print(f"連接MQTT服務器,返回碼: {rc}")
? ? client.subscribe(MQTT_TOPIC_SUB)

# 消息接收回調
def on_message(client, userdata, msg):
? ? payload = msg.payload.decode()
? ? print(f"收到消息 [{msg.topic}]: {payload}")
? ??
? ? try:
? ? ? ? command = json.loads(payload)
? ? ? ? if command.get('action') == 'reboot':
? ? ? ? ? ? print("執行重啟指令...")
? ? ? ? ? ? # 這里添加重啟邏輯

? ? except json.JSONDecodeError:
? ? ? ? print("無效的JSON消息")

# 創建MQTT客戶端
client = mqtt.Client(CLIENT_ID)
client.on_connect = on_connect
client.on_message = on_message

# 連接并啟動循環
client.connect(MQTT_BROKER, MQTT_PORT, 60)
client.loop_start()

try:
? ? while True:
? ? ? ? # 發布傳感器數據
? ? ? ? sensor_data = get_sensor_data()
? ? ? ? client.publish(MQTT_TOPIC_PUB, json.dumps(sensor_data))
? ? ? ? print(f"發布數據: {sensor_data}")
? ? ? ? time.sleep(10)
except KeyboardInterrupt:
? ? print("斷開連接...")
? ? client.loop_stop()
? ? client.disconnect()
https://mqtt.org/assets/img/mqtt-publish-subscribe.png

CoAP協議實現
python
from aiocoap import *
import asyncio
import time

async def coap_server():
? ? """CoAP服務器實現"""
? ? protocol = await Context.create_server_context(CoAPServer())

? ? # 持續運行
? ? print("CoAP服務器啟動...")
? ? await asyncio.get_running_loop().create_future()

class CoAPServer(Resource):
? ? """CoAP資源處理"""
? ??
? ? def __init__(self):
? ? ? ? super().__init__()
? ? ? ? self.sensor_data = {
? ? ? ? ? ? "temperature": 25.0,
? ? ? ? ? ? "humidity": 50.0
? ? ? ? }
? ??
? ? async def render_get(self, request):
? ? ? ? """處理GET請求"""
? ? ? ? self.update_sensor_data()
? ? ? ? payload = json.dumps(self.sensor_data).encode('utf-8')
? ? ? ? return Message(payload=payload)
? ??
? ? async def render_post(self, request):
? ? ? ? """處理POST請求"""
? ? ? ? try:
? ? ? ? ? ? payload = json.loads(request.payload.decode('utf-8'))
? ? ? ? ? ? if 'set_temp' in payload:
? ? ? ? ? ? ? ? self.sensor_data['temperature'] = payload['set_temp']
? ? ? ? ? ? if 'set_humidity' in payload:
? ? ? ? ? ? ? ? self.sensor_data['humidity'] = payload['set_humidity']
? ? ? ? ? ??
? ? ? ? ? ? return Message(code=CHANGED,?
? ? ? ? ? ? ? ? ? ? ? ? ?payload=b"Settings updated")
? ? ? ? except:
? ? ? ? ? ? return Message(code=BAD_REQUEST,?
? ? ? ? ? ? ? ? ? ? ? ? ?payload=b"Invalid request")

? ? def update_sensor_data(self):
? ? ? ? """更新傳感器數據(模擬)"""
? ? ? ? self.sensor_data = {
? ? ? ? ? ? "temperature": 25.0 + (time.time() % 3),
? ? ? ? ? ? "humidity": 50.0 + (time.time() % 10),
? ? ? ? ? ? "timestamp": int(time.time())
? ? ? ? }

async def coap_client():
? ? """CoAP客戶端實現"""
? ? protocol = await Context.create_client_context()
? ??
? ? # 獲取數據
? ? request = Message(code=GET, uri='coap://localhost/sensor')
? ? try:
? ? ? ? response = await protocol.request(request).response
? ? ? ? print(f"收到響應: {response.payload.decode()}")
? ? except Exception as e:
? ? ? ? print(f"請求失敗: {e}")
? ??
? ? # 設置數據
? ? payload = {"set_temp": 26.5, "set_humidity": 55.0}
? ? request = Message(code=POST,?
? ? ? ? ? ? ? ? ? ? ?payload=json.dumps(payload).encode(),
? ? ? ? ? ? ? ? ? ? ?uri='coap://localhost/sensor')
? ? try:
? ? ? ? response = await protocol.request(request).response
? ? ? ? print(f"設置響應: {response.payload.decode()}")
? ? except Exception as e:
? ? ? ? print(f"設置失敗: {e}")

# 運行示例
async def main():
? ? server_task = asyncio.create_task(coap_server())
? ? await asyncio.sleep(1) ?# 等待服務器啟動
? ? await coap_client()
? ? server_task.cancel()

asyncio.run(main())
邊緣計算框架
使用MicroPython
python
# ESP32 MicroPython示例
import machine
import network
import urequests
import ujson
from time import sleep

# 配置WiFi
WIFI_SSID = "your_wifi"
WIFI_PASS = "your_password"

def connect_wifi():
? ? sta_if = network.WLAN(network.STA_IF)
? ? if not sta_if.isconnected():
? ? ? ? print("連接WiFi...")
? ? ? ? sta_if.active(True)
? ? ? ? sta_if.connect(WIFI_SSID, WIFI_PASS)
? ? ? ? while not sta_if.isconnected():
? ? ? ? ? ? pass
? ? print("網絡配置:", sta_if.ifconfig())

# 讀取傳感器(模擬)
def read_sensor():
? ? return {
? ? ? ? "temp": 25 + machine.rng() % 5,
? ? ? ? "humidity": 50 + machine.rng() % 10
? ? }

# 邊緣計算處理
def process_data(data):
? ? # 簡單異常檢測
? ? if data['temp'] > 30 or data['humidity'] > 80:
? ? ? ? data['alert'] = True
? ? else:
? ? ? ? data['alert'] = False
? ? return data

# 主循環
connect_wifi()
while True:
? ? sensor_data = read_sensor()
? ? processed_data = process_data(sensor_data)
? ??
? ? if processed_data['alert']:
? ? ? ? print("警報狀態! 發送數據...")
? ? ? ? response = urequests.post(
? ? ? ? ? ? "api.example.com/alerts",
? ? ? ? ? ? json=processed_data,
? ? ? ? ? ? headers={'Content-Type': 'application/json'}
? ? ? ? )
? ? ? ? print("響應:", response.text)
? ? ? ? response.close()
? ??
? ? sleep(60) ?# 每分鐘檢查一次
使用EdgeX Foundry
python
import requests
import json
import time

# EdgeX配置
EDGEX_URL = "localhost:48080/api/v1"
DEVICE_NAME = "temperature-sensor"

def register_device():
? ? """注冊設備到EdgeX"""
? ? device = {
? ? ? ? "name": DEVICE_NAME,
? ? ? ? "description": "Python IoT溫度傳感器",
? ? ? ? "adminState": "UNLOCKED",
? ? ? ? "operatingState": "ENABLED",
? ? ? ? "protocols": {
? ? ? ? ? ? "other": {
? ? ? ? ? ? ? ? "Address": "virtual01",
? ? ? ? ? ? ? ? "Protocol": "300"
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ??
? ? response = requests.post(
? ? ? ? f"{EDGEX_URL}/device",
? ? ? ? json=device,
? ? ? ? headers={"Content-Type": "application/json"}
? ? )
? ? return response.json()

def send_reading(value):
? ? """發送傳感器讀數"""
? ? reading = {
? ? ? ? "device": DEVICE_NAME,
? ? ? ? "readings": [
? ? ? ? ? ? {
? ? ? ? ? ? ? ? "name": "Temperature",
? ? ? ? ? ? ? ? "value": str(value)
? ? ? ? ? ? }
? ? ? ? ]
? ? }
? ??
? ? response = requests.post(
? ? ? ? f"{EDGEX_URL}/reading",
? ? ? ? json=reading,
? ? ? ? headers={"Content-Type": "application/json"}
? ? )
? ? return response.status_code == 200

# 模擬設備運行
print("注冊設備...")
register_device()

print("開始發送傳感器數據...")
while True:
? ? temp = 20 + (time.time() % 10) ?# 模擬溫度波動
? ? if send_reading(temp):
? ? ? ? print(f"發送溫度數據: {temp}°C")
? ? else:
? ? ? ? print("發送數據失敗")
? ? time.sleep(5)
https://docs.edgexfoundry.org/1.3/_images/EdgeX_arch.png

物聯網數據處理
實時數據流處理
python
import pyarrow.flight as flight
import pandas as pd
import numpy as np

class FlightServer(flight.FlightServerBase):
? ? """Arrow Flight服務器實現"""
? ??
? ? def __init__(self, location):
? ? ? ? super().__init__(location)
? ? ? ? self.data = pd.DataFrame({
? ? ? ? ? ? 'timestamp': pd.date_range('2023-01-01', periods=100, freq='s'),
? ? ? ? ? ? 'value': np.random.randn(100)
? ? ? ? })
? ??
? ? def do_get(self, context, ticket):
? ? ? ? """處理數據獲取請求"""
? ? ? ? df = self.data[self.data['timestamp'] > pd.Timestamp.now() - pd.Timedelta('1min')]
? ? ? ? table = pa.Table.from_pandas(df)
? ? ? ? return flight.RecordBatchStream(table)

class DataProcessor:
? ? """實時數據處理"""
? ??
? ? def __init__(self, server_url):
? ? ? ? self.client = flight.FlightClient(server_url)
? ??
? ? def process_stream(self):
? ? ? ? """處理實時數據流"""
? ? ? ? while True:
? ? ? ? ? ? try:
? ? ? ? ? ? ? ? # 獲取最近1分鐘數據
? ? ? ? ? ? ? ? descriptor = flight.FlightDescriptor.for_command(b"latest_data")
? ? ? ? ? ? ? ? flight_info = self.client.get_flight_info(descriptor)
? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? for endpoint in flight_info.endpoints:
? ? ? ? ? ? ? ? ? ? for location in endpoint.locations:
? ? ? ? ? ? ? ? ? ? ? ? reader = self.client.do_get(location.ticket)
? ? ? ? ? ? ? ? ? ? ? ? batch = reader.read_all()
? ? ? ? ? ? ? ? ? ? ? ? df = batch.to_pandas()
? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? ? ? ? ? # 實時分析
? ? ? ? ? ? ? ? ? ? ? ? if not df.empty:
? ? ? ? ? ? ? ? ? ? ? ? ? ? avg = df['value'].mean()
? ? ? ? ? ? ? ? ? ? ? ? ? ? max_val = df['value'].max()
? ? ? ? ? ? ? ? ? ? ? ? ? ? print(f"平均值: {avg:.2f}, 最大值: {max_val:.2f}")
? ? ? ? ? ??
? ? ? ? ? ? except Exception as e:
? ? ? ? ? ? ? ? print(f"處理錯誤: {e}")
? ? ? ? ? ??
? ? ? ? ? ? time.sleep(10)

# 啟動服務器
server = FlightServer("grpc://0.0.0.0:8815")
server_thread = threading.Thread(target=server.serve)
server_thread.start()

# 啟動客戶端處理
processor = DataProcessor("grpc://localhost:8815")
processor.process_stream()
時序數據庫集成
python
import influxdb_client
from influxdb_client.client.write_api import SYNCHRONOUS

class InfluxDBManager:
? ? """InfluxDB時序數據庫管理"""
? ??
? ? def __init__(self, url, token, org, bucket):
? ? ? ? self.client = influxdb_client.InfluxDBClient(
? ? ? ? ? ? url=url,
? ? ? ? ? ? token=token,
? ? ? ? ? ? org=org
? ? ? ? )
? ? ? ? self.bucket = bucket
? ? ? ? self.write_api = self.client.write_api(write_options=SYNCHRONOUS)
? ? ? ? self.query_api = self.client.query_api()
? ??
? ? def write_data(self, measurement, tags, fields):
? ? ? ? """寫入數據點"""
? ? ? ? point = influxdb_client.Point(measurement)
? ? ? ??
? ? ? ? # 添加標簽
? ? ? ? for tag_key, tag_value in tags.items():
? ? ? ? ? ? point.tag(tag_key, tag_value)
? ? ? ??
? ? ? ? # 添加字段
? ? ? ? for field_key, field_value in fields.items():
? ? ? ? ? ? point.field(field_key, field_value)
? ? ? ??
? ? ? ? # 寫入數據庫
? ? ? ? self.write_api.write(bucket=self.bucket, record=point)
? ??
? ? def query_data(self, query):
? ? ? ? """查詢數據"""
? ? ? ? result = self.query_api.query(query)
? ? ? ? records = []
? ? ? ??
? ? ? ? for table in result:
? ? ? ? ? ? for record in table.records:
? ? ? ? ? ? ? ? records.append({
? ? ? ? ? ? ? ? ? ? 'time': record.get_time(),
? ? ? ? ? ? ? ? ? ? 'measurement': record.get_measurement(),
? ? ? ? ? ? ? ? ? ? **record.values
? ? ? ? ? ? ? ? })
? ? ? ??
? ? ? ? return records

# 使用示例
influx_mgr = InfluxDBManager(
? ? url="localhost:8086",
? ? token="your-token",
? ? org="your-org",
? ? bucket="iot-data"
)

# 寫入傳感器數據
influx_mgr.write_data(
? ? measurement="temperature",
? ? tags={"location": "room1", "device": "sensor1"},
? ? fields={"value": 25.3}
)

# 查詢最近1小時數據
query = """
from(bucket: "iot-data")
? |> range(start: -1h)
? |> filter(fn: (r) => r._measurement == "temperature")
"""
data = influx_mgr.query_data(query)
print("查詢結果:", data)
物聯網安全
設備認證與加密
python
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
from cryptography.hazmat.backends import default_backend
import os

class IoTDeviceSecurity:
? ? """物聯網設備安全類"""
? ??
? ? def __init__(self):
? ? ? ? # 生成ECDSA密鑰對
? ? ? ? self.private_key = ec.generate_private_key(
? ? ? ? ? ? ec.SECP256R1(), default_backend()
? ? ? ? )
? ? ? ? self.public_key = self.private_key.public_key()
? ? ? ??
? ? ? ? # 預共享密鑰(實際應用中應從安全存儲獲取)
? ? ? ? self.shared_secret = os.urandom(32)
? ??
? ? def get_public_key_pem(self):
? ? ? ? """獲取PEM格式的公鑰"""
? ? ? ? return self.public_key.public_bytes(
? ? ? ? ? ? encoding=serialization.Encoding.PEM,
? ? ? ? ? ? format=serialization.PublicFormat.SubjectPublicKeyInfo
? ? ? ? )
? ??
? ? def sign_data(self, data):
? ? ? ? """簽名數據"""
? ? ? ? if isinstance(data, str):
? ? ? ? ? ? data = data.encode('utf-8')
? ? ? ??
? ? ? ? signature = self.private_key.sign(
? ? ? ? ? ? data,
? ? ? ? ? ? ec.ECDSA(hashes.SHA256())
? ? ? ? )
? ? ? ? return signature
? ??
? ? def verify_signature(self, public_key_pem, data, signature):
? ? ? ? """驗證簽名"""
? ? ? ? public_key = serialization.load_pem_public_key(
? ? ? ? ? ? public_key_pem,
? ? ? ? ? ? backend=default_backend()
? ? ? ? )
? ? ? ??
? ? ? ? if isinstance(data, str):
? ? ? ? ? ? data = data.encode('utf-8')
? ? ? ??
? ? ? ? try:
? ? ? ? ? ? public_key.verify(
? ? ? ? ? ? ? ? signature,
? ? ? ? ? ? ? ? data,
? ? ? ? ? ? ? ? ec.ECDSA(hashes.SHA256())
? ? ? ? ? ? )
? ? ? ? ? ? return True
? ? ? ? except:
? ? ? ? ? ? return False
? ??
? ? def derive_session_key(self, peer_public_key_pem):
? ? ? ? """派生會話密鑰"""
? ? ? ? peer_public_key = serialization.load_pem_public_key(
? ? ? ? ? ? peer_public_key_pem,
? ? ? ? ? ? backend=default_backend()
? ? ? ? )
? ? ? ??
? ? ? ? shared_key = self.private_key.exchange(
? ? ? ? ? ? ec.ECDH(), peer_public_key
? ? ? ? )
? ? ? ??
? ? ? ? # 使用HKDF派生密鑰
? ? ? ? derived_key = HKDF(
? ? ? ? ? ? algorithm=hashes.SHA256(),
? ? ? ? ? ? length=32,
? ? ? ? ? ? salt=None,
? ? ? ? ? ? info=b'session-key',
? ? ? ? ? ? backend=default_backend()
? ? ? ? ).derive(shared_key)
? ? ? ??
? ? ? ? return derived_key

# 使用示例
device1 = IoTDeviceSecurity()
device2 = IoTDeviceSecurity()

# 交換公鑰
device1_pubkey = device1.get_public_key_pem()
device2_pubkey = device2.get_public_key_pem()

# 派生會話密鑰
session_key1 = device1.derive_session_key(device2_pubkey)
session_key2 = device2.derive_session_key(device1_pubkey)

print("會話密鑰匹配:", session_key1 == session_key2)
安全固件更新
python
import hashlib
import hmac
import requests
import tempfile
import subprocess

class SecureFirmwareUpdater:
? ? """安全固件更新"""
? ??
? ? def __init__(self, device_id, secret_key, update_server):
? ? ? ? self.device_id = device_id
? ? ? ? self.secret_key = secret_key.encode('utf-8')
? ? ? ? self.update_server = update_server
? ??
? ? def check_update(self):
? ? ? ? """檢查更新"""
? ? ? ? # 創建認證簽名
? ? ? ? nonce = os.urandom(16).hex()
? ? ? ? message = f"{self.device_id}:{nonce}".encode('utf-8')
? ? ? ? signature = hmac.new(
? ? ? ? ? ? self.secret_key,?
? ? ? ? ? ? message,?
? ? ? ? ? ? hashlib.sha256
? ? ? ? ).hexdigest()
? ? ? ??
? ? ? ? # 發送認證請求
? ? ? ? response = requests.get(
? ? ? ? ? ? f"{self.update_server}/check-update",
? ? ? ? ? ? headers={
? ? ? ? ? ? ? ? "Device-ID": self.device_id,
? ? ? ? ? ? ? ? "Nonce": nonce,
? ? ? ? ? ? ? ? "Signature": signature
? ? ? ? ? ? }
? ? ? ? )
? ? ? ??
? ? ? ? if response.status_code == 200:
? ? ? ? ? ? return response.json()
? ? ? ? else:
? ? ? ? ? ? print(f"檢查更新失敗: {response.text}")
? ? ? ? ? ? return None
? ??
? ? def download_firmware(self, version, checksum):
? ? ? ? """下載固件"""
? ? ? ? # 創建臨時文件
? ? ? ? temp_file = tempfile.NamedTemporaryFile(delete=False)
? ? ? ??
? ? ? ? try:
? ? ? ? ? ? # 流式下載固件
? ? ? ? ? ? response = requests.get(
? ? ? ? ? ? ? ? f"{self.update_server}/firmware/{version}",
? ? ? ? ? ? ? ? stream=True
? ? ? ? ? ? )
? ? ? ? ? ??
? ? ? ? ? ? # 計算下載文件的哈希
? ? ? ? ? ? sha256 = hashlib.sha256()
? ? ? ? ? ??
? ? ? ? ? ? for chunk in response.iter_content(chunk_size=8192):
? ? ? ? ? ? ? ? temp_file.write(chunk)
? ? ? ? ? ? ? ? sha256.update(chunk)
? ? ? ? ? ??
? ? ? ? ? ? temp_file.close()
? ? ? ? ? ??
? ? ? ? ? ? # 驗證校驗和
? ? ? ? ? ? if sha256.hexdigest() != checksum:
? ? ? ? ? ? ? ? os.unlink(temp_file.name)
? ? ? ? ? ? ? ? raise ValueError("固件校驗和不匹配")
? ? ? ? ? ??
? ? ? ? ? ? return temp_file.name
? ? ? ? except:
? ? ? ? ? ? os.unlink(temp_file.name)
? ? ? ? ? ? raise
? ??
? ? def apply_update(self, firmware_path):
? ? ? ? """應用更新"""
? ? ? ? # 驗證固件簽名(示例)
? ? ? ? if not self.verify_firmware(firmware_path):
? ? ? ? ? ? raise ValueError("固件簽名驗證失敗")
? ? ? ??
? ? ? ? # 執行更新腳本(實際實現依平臺而定)
? ? ? ? result = subprocess.run(
? ? ? ? ? ? ["/bin/sh", firmware_path],
? ? ? ? ? ? capture_output=True,
? ? ? ? ? ? text=True
? ? ? ? )
? ? ? ??
? ? ? ? if result.returncode != 0:
? ? ? ? ? ? print(f"更新失敗: {result.stderr}")
? ? ? ? ? ? return False
? ? ? ??
? ? ? ? print("固件更新成功!")
? ? ? ? return True
? ??
? ? def verify_firmware(self, firmware_path):
? ? ? ? """驗證固件簽名"""
? ? ? ? # 這里應實現實際的簽名驗證邏輯
? ? ? ? # 示例中僅檢查文件大小
? ? ? ? return os.path.getsize(firmware_path) > 0

# 使用示例
updater = SecureFirmwareUpdater(
? ? device_id="device-123",
? ? secret_key="your-secret-key",
? ? update_server="firmware.example.com"
)

update_info = updater.check_update()
if update_info and update_info['available']:
? ? print(f"發現新版本: {update_info['version']}")
? ? try:
? ? ? ? firmware_path = updater.download_firmware(
? ? ? ? ? ? update_info['version'],
? ? ? ? ? ? update_info['checksum']
? ? ? ? )
? ? ? ? if updater.apply_update(firmware_path):
? ? ? ? ? ? print("設備需要重啟以完成更新")
? ? except Exception as e:
? ? ? ? print(f"更新失敗: {str(e)}")
else:
? ? print("設備固件已是最新")
物聯網可視化
實時儀表盤
python
import dash
from dash import dcc, html
from dash.dependencies import Input, Output
import plotly.graph_objs as go
import pandas as pd
import random
from datetime import datetime

# 創建Dash應用
app = dash.Dash(__name__)

# 初始數據
initial_data = pd.DataFrame({
? ? 'timestamp': [datetime.now()],
? ? 'temperature': [25.0],
? ? 'humidity': [50.0]
})

# 應用布局
app.layout = html.Div([
? ? html.H1("物聯網設備監控儀表盤"),
? ??
? ? dcc.Interval(
? ? ? ? id='interval-component',
? ? ? ? interval=5*1000, ?# 5秒
? ? ? ? n_intervals=0
? ? ),
? ??
? ? html.Div([
? ? ? ? html.Div([
? ? ? ? ? ? dcc.Graph(id='temp-gauge'),
? ? ? ? ? ? html.H3("當前溫度", style={'text-align': 'center'})
? ? ? ? ], className="six columns"),
? ? ? ??
? ? ? ? html.Div([
? ? ? ? ? ? dcc.Graph(id='humidity-gauge'),
? ? ? ? ? ? html.H3("當前濕度", style={'text-align': 'center'})
? ? ? ? ], className="six columns")
? ? ], className="row"),
? ??
? ? dcc.Graph(id='temp-trend'),
? ??
? ? html.Div(id='alerts-container')
], className="container")

# 回調函數 - 更新數據
@app.callback(
? ? Output('temp-gauge', 'figure'),
? ? Output('humidity-gauge', 'figure'),
? ? Output('temp-trend', 'figure'),
? ? Output('alerts-container', 'children'),
? ? Input('interval-component', 'n_intervals')
)
def update_metrics(n):
? ? # 模擬新數據
? ? new_data = {
? ? ? ? 'timestamp': datetime.now(),
? ? ? ? 'temperature': 25 + random.uniform(-2, 2),
? ? ? ? 'humidity': 50 + random.uniform(-5, 5)
? ? }
? ??
? ? # 更新數據集
? ? global initial_data
? ? initial_data = initial_data.append(new_data, ignore_index=True)
? ??
? ? # 溫度儀表
? ? temp_gauge = go.Figure(go.Indicator(
? ? ? ? mode="gauge+number",
? ? ? ? value=new_data['temperature'],
? ? ? ? domain={'x': [0, 1], 'y': [0, 1]},
? ? ? ? gauge={
? ? ? ? ? ? 'axis': {'range': [None, 40]},
? ? ? ? ? ? 'steps': [
? ? ? ? ? ? ? ? {'range': [0, 20], 'color': "lightgray"},
? ? ? ? ? ? ? ? {'range': [20, 30], 'color': "gray"},
? ? ? ? ? ? ? ? {'range': [30, 40], 'color': "red"}
? ? ? ? ? ? ],
? ? ? ? ? ? 'threshold': {
? ? ? ? ? ? ? ? 'line': {'color': "black", 'width': 4},
? ? ? ? ? ? ? ? 'thickness': 0.75,
? ? ? ? ? ? ? ? 'value': 30
? ? ? ? ? ? }
? ? ? ? }
? ? ))
? ? temp_gauge.update_layout(height=300, margin=dict(t=0, b=0))
? ??
? ? # 濕度儀表
? ? humidity_gauge = go.Figure(go.Indicator(
? ? ? ? mode="gauge+number",
? ? ? ? value=new_data['humidity'],
? ? ? ? domain={'x': [0, 1], 'y': [0, 1]},
? ? ? ? gauge={
? ? ? ? ? ? 'axis': {'range': [0, 100]},
? ? ? ? ? ? 'steps': [
? ? ? ? ? ? ? ? {'range': [0, 30], 'color': "red"},
? ? ? ? ? ? ? ? {'range': [30, 70], 'color': "lightgray"},
? ? ? ? ? ? ? ? {'range': [70, 100], 'color': "blue"}
? ? ? ? ? ? ],
? ? ? ? ? ? 'threshold': {
? ? ? ? ? ? ? ? 'line': {'color': "black", 'width': 4},
? ? ? ? ? ? ? ? 'thickness': 0.75,
? ? ? ? ? ? ? ? 'value': 70
? ? ? ? ? ? }
? ? ? ? }
? ? ))
? ? humidity_gauge.update_layout(height=300, margin=dict(t=0, b=0))
? ??
? ? # 溫度趨勢圖
? ? temp_trend = go.Figure()
? ? temp_trend.add_trace(go.Scatter(
? ? ? ? x=initial_data['timestamp'],
? ? ? ? y=initial_data['temperature'],
? ? ? ? name='溫度',
? ? ? ? line=dict(color='red', width=2)
? ? ))
? ? temp_trend.add_trace(go.Scatter(
? ? ? ? x=initial_data['timestamp'],
? ? ? ? y=initial_data['humidity'],
? ? ? ? name='濕度',
? ? ? ? yaxis='y2',
? ? ? ? line=dict(color='blue', width=2)
? ? ))
? ? temp_trend.update_layout(
? ? ? ? yaxis=dict(title='溫度 (°C)'),
? ? ? ? yaxis2=dict(
? ? ? ? ? ? title='濕度 (%)',
? ? ? ? ? ? overlaying='y',
? ? ? ? ? ? side='right'
? ? ? ? ),
? ? ? ? hovermode="x unified"
? ? )
? ??
? ? # 警報信息
? ? alerts = []
? ? if new_data['temperature'] > 28:
? ? ? ? alerts.append(html.Div(
? ? ? ? ? ? f"高溫警報! 當前溫度: {new_data['temperature']:.1f}°C",
? ? ? ? ? ? style={
? ? ? ? ? ? ? ? 'color': 'white',
? ? ? ? ? ? ? ? 'background': 'red',
? ? ? ? ? ? ? ? 'padding': '10px',
? ? ? ? ? ? ? ? 'margin': '10px 0',
? ? ? ? ? ? ? ? 'border-radius': '5px'
? ? ? ? ? ? }
? ? ? ? ))
? ? if new_data['humidity'] > 70:
? ? ? ? alerts.append(html.Div(
? ? ? ? ? ? f"高濕度警報! 當前濕度: {new_data['humidity']:.1f}%",
? ? ? ? ? ? style={
? ? ? ? ? ? ? ? 'color': 'white',
? ? ? ? ? ? ? ? 'background': 'blue',
? ? ? ? ? ? ? ? 'padding': '10px',
? ? ? ? ? ? ? ? 'margin': '10px 0',
? ? ? ? ? ? ? ? 'border-radius': '5px'
? ? ? ? ? ? }
? ? ? ? ))
? ??
? ? return temp_gauge, humidity_gauge, temp_trend, alerts

# 運行應用
if __name__ == '__main__':
? ? app.run_server(debug=True, host='0.0.0.0')
https://plotly.com/python/static/images/dash-dashboards/iot-dashboard.png

結語與學習路徑
https://www.python.org/static/community_logos/python-logo-master-v3-TM.png

通過這十一篇系列教程,你已經掌握了:

物聯網硬件交互與傳感器集成

物聯網通信協議(MQTT/CoAP)

邊緣計算框架與應用

物聯網數據處理與分析

物聯網安全實踐

實時可視化儀表盤開發

進階學習方向:

專業領域深入:

工業物聯網(IIoT)平臺開發

智能家居系統集成

智慧城市解決方案

技術棧擴展:

5G與物聯網融合應用

AIoT(人工智能物聯網)開發

數字孿生技術實現

認證體系:

AWS IoT認證

Cisco IoT認證

工業物聯網專業認證

開源貢獻:

參與主流IoT框架開發

貢獻邊緣計算項目

開發物聯網安全工具

Python在物聯網領域的應用前景廣闊,持續探索和實踐將助你成為這一變革性技術的引領者!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/912908.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/912908.shtml
英文地址,請注明出處:http://en.pswp.cn/news/912908.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

高通SG882G平臺(移遠):1、編譯腳本

文檔提供的編譯,有點問題。所以我重新整理了腳本。 build-lib.sh #!/bin/bashfunction prepare_build() {if [ ! -d download ]; thenmkdir downloadfilocal MODIFIED_DIRfile-replacelocal FILE_NAMEset_bb_env.shcp ${MODIFIED_DIR}/${FILE_NAME} \poky/qti-con…

Mac電腦 觸摸板增強工具 BetterTouchTool

BetterTouchTool mac版,是一款觸摸板增強工具,允許用戶使用各種手勢來控制其計算機。 Bettertouchtool mac是一個小而高效的macOS應用程序,旨在幫助您為手勢定義快捷方式。 此外,Bettertouchtool可用于使用常規鼠標和鍵盤快捷鍵…

LSTM(Long Short-Term Memory)模型的深度解析

在6.28號我發了一個博客《RNN(循環神經網絡)與LSTM(長短期記憶網絡)輸出的詳細對比分析》,但是我并未詳細講解LSTM,LSTM是循環神經網絡中的一個模型,然而通過這篇博客給大家深度解析一下LSTM&am…

WebRTC 安全性分析研究

一、概述 本文著重分析 WebRTC 的安全性,分析其安全性考慮及安全性實現,回答了以下問題: WebRTC 加密過程需要或依賴 CA (Certificate Authority)嗎? 不需要 CA, 但可能依賴 CA.DTLS-SRTP 加密機制中, DTLS 與 SRTP 的關系是什么? DTLS 實現秘鑰交換…

阿里云操作系統控制臺如何解決三大OS運維難題?

背景 操作系統運維常常遇到以下問題: 1.問題定界浪費大量人力:當業務出現問題時,客戶在不清楚是操作系統問題還是業務問題時,往往會拉上所有相關團隊一起排查,浪費人力。 2.問題定位時間長:通過操作系統…

自由學習記錄(65)

其他腳本語言也可以熱更新,但 Lua 特別適合,游戲主程序通常是 C,Lua 只是邏輯腳本,改 Lua 不影響主程序運行 語言應用場景PythonWeb 后端 / 數據處理服務JavaScript瀏覽器端熱重載 / React HMRC#Unity 的 ILRuntime / HybridCLR …

抗輻照芯片在核電廠火災探測器中的應用優勢與性能解析

一、引言 核電廠作為能源供應的關鍵設施,其安全性備受關注。火災是威脅核電廠安全運行的重要風險因素之一。在核電廠的特殊環境下,火災探測器肩負著及時發現火情、保障核電廠安全運行的重任。然而,核電廠存在高能輻射等復雜環境因素&#xf…

FastAPI+Sqlite+HTML的登錄注冊與文件上傳系統:完整實現指南

作為一名開發者,你是否曾想過親手搭建一個包含用戶注冊、登錄認證和文件上傳功能的完整 Web 系統?今天,我將帶大家一步步拆解一個基于FastAPI(后端)和原生 JavaScript(前端)的前后端分離項目&am…

【動態規劃】P11188 「KDOI-10」商店砍價|普及+

本文涉及知識點 C動態規劃 P11188 「KDOI-10」商店砍價 題目背景 English Statement. You must submit your code at the Chinese version of the statement. 您可以點擊 這里 下載本場比賽的選手文件。 You can click here to download all tasks and examples of the c…

國產LHR3040芯片是REF5040的代替品

LHR3040是一款噪聲低、漂移低、精度高的電壓基準產品系列。這些基準同時支持灌電流和拉電流,并且具有出色的線性和負載調節性能。采用專有的設計技術實現了出色的溫漂(3ppm/℃)和高精度(0.05%)。這些特性與極低噪聲相結合,使LHR30XX系列成為高精度數據采…

專題:2025AI營銷市場發展研究報告|附400+份報告PDF匯總下載

原文鏈接:https://tecdat.cn/?p42800 在數字化浪潮席卷全球的當下,AI營銷正成為驅動企業增長的核心動力。 從市場規模來看,AI營銷正經歷著爆發式增長,生成式AI的出現更是為其注入了強大活力。在應用層面,AI已滲透到營…

深入對比 Python 中的 `__repr__` 與 `__str__`:選擇正確的對象表示方法

文章目錄 核心概念對比1. 根本目的差異2. 調用場景對比深入解析:何時使用哪種方法場景 1:開發者調試 vs 用戶展示場景 2:技術表示 vs 簡化視圖高級對比:特殊場景處理1. 容器中的對象表示2. 日志記錄的最佳實踐3. 異常信息展示最佳實踐指南1. 何時實現哪個方法?2. 實現原則…

萬能公式基分析重構補丁復分析和歐拉公式原理推導

基分析, x11 x2-1 x3i 存在加法法則 x1x20 所以x1-x2 存在鏈式基乘法法則 x1x1*x1x2*x2 x2x3*x3 x3x1*x3 -x1x2x3 將鏈式基乘法操作 二次,三次,直至n次化簡得 一次 x1 -x1 x3 矩陣 x1 x1 x2 x2 x3 …

OpenCV 4.10.0 移植

OpenCV 4.10.0 移植使用 概述移植編譯下載解壓編譯環境編譯 編譯完成OpenCV 庫文件及其作用 使用實例參考代碼 參考 概述 OpenCV(Open Source Computer Vision Library)是計算機視覺領域最廣泛使用的開源庫之一,提供了豐富的功能模塊&#xf…

Tomcat10.0以上版本編譯成功但報錯HTTP狀態 404

Tomcat正常啟動且項目已成功部署,但出現404錯誤。 HTTP狀態 404 - 未找到package org.example;import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpSer…

在Flask項目中用Git LFS管理大文件(PDF)的完整實踐

在Flask項目中用Git LFS高效管理大文件(以農機說明書PDF為例) 背景與需求 在農機管理系統等實際項目中,經常需要上傳和管理大量超大文件(如200MB以上的PDF說明書、圖片等)。如果直接用Git管理這些大文件,不僅會導致倉庫膨脹、clone/pull速度變慢,還可能遇到推送失敗等…

樸素貝葉斯算法案例演示及Python實現

目錄 一、基本原理二、案例演示2.1 未平滑處理2.2 Laplace平滑處理 三、Python實現 一、基本原理 樸素貝葉斯思想:依靠特征概率去預測分類,針對于代分類的樣本,會求解在該樣本出現的條件下,各個類別出現的概率,哪個類…

RAG從入門到高階(二):Retrieve-and-Rerank

在上一篇教程中,我們了解了 Naive RAG 的基本原理和實現。它就像一個剛剛學會查找資料的新手,雖然能找到一些信息,但有時候找到的并不夠精準,甚至會有一些無關的干擾。 今天,我們將介紹 Retrieve-and-Rerank RAG&…

【腳本】Linux磁盤目錄掛載腳本(不分區)

以下是一個不帶分區,直接掛載整個磁盤到指定目錄的腳本。該腳本會檢查磁盤是否已掛載,自動創建文件系統(可選),并配置開機自動掛載: #!/bin/bash# 磁盤直接掛載腳本(不分區) # 使用…