使用 Grafana + Prometheus 監測智慧插座用電量 (含 Docker 容器編譯技巧)
| | | 8 | |
事發總有原因,先來個前情提要:
- 2022-05 我入手可以量測插座耗電量的智慧延長線,為了長時間監測電器用電狀況,還自己寫程式定期收資料寫進 SQLite 再用 Highchart 畫線圖

- 2024-11 為了要觀察 Docker CPU/RAM 使用狀況,我學會使用 Prometheus + Grafana 豪華全家桶
- 2025-09 家用迷你伺服器從 CentOS 7 升級到 Debian 12 重生,原本有一堆事卡在作業系統太舊不能做,這下子封印解除
- 2025-10 在迷你伺服器跑的容器愈來愈多,三年前研究過的 cAdvisor + Prometheus + Grafana 全家桶正式登場
- 2025-11 想想,既然都架好 Grafana + Prometheus,幹嘛還自己收資料寫 DB 畫線圖?該交給專業的來啊~
因此我打算研究一下,怎麼把智慧插座用電量餵給 Prometheus,用 Grafana 看圖表,如此用 SQLite 收資料跟畫圖表的土砲服務就能功成身退了。
Prometheus 抓資料的原理是在 prometheus.yaml 設定檔加入一段,指定作業名稱跟抓資料的網址:
scrape_configs:
- job_name: "hs300"
static_configs:
- targets: ["localhost:9300"]
而 localhost:9300/metrics 要吐回類似以下格式的資料:

/metrics 的資料格式一望便知,其中定義了名為 hs300_stats 的 Gauge (儀表,會上下波動的度量數字) ,而這個 Gauge 包含了六種資料,插座 1 到插座 6,每次存取時會顯示各插座的耗電量(以瓦為單位)。
Promethues 有提供官方建議的 C# 程式庫,寫出以上服務簡單到像吃豆腐,建個 Console 專案,用 dotnet add package prometheus-net 及 dotnet add package TPLinkSmartDevice.NETCore" 安裝 Prometheus 及 TPLink 智慧插座通訊程式庫,50 行搞定:
using Prometheus;
using System.Diagnostics;
using TPLinkSmartDevices.Devices;
// 讀取設定,提供預設值
var host = Environment.GetEnvironmentVariable("HS300_DeviceIP") ?? throw new ArgumentNullException("HS300_DeviceIP", "請提供 HS300 裝置的 IP 位址");
var metricServer = new MetricServer(port: 9999); // 指定 Exposure Port
metricServer.Start();
Metrics.SuppressDefaultMetrics(); // 停用預設指標
// 建立自訂指標
var myGauge = Metrics.CreateGauge("hs300_stats", "HS300 插座耗電量(w)", new GaugeConfiguration
{
LabelNames = new[] { "type" }
});
// 以背景執行方式更新指標
await Task.Run(async () =>
{
var rand = new Random();
while (true)
{
double[] data = new double[6];
long waitMs = 10_000;
try
{
Console.Write(DateTime.Now.ToString("MM-dd HH:mm:ss "));
var sw = Stopwatch.StartNew();
var hs300 = new TPLinkSmartStrip(host);
for (int i = 0; i < 6; i++)
{
var powerData = hs300.ReadRealtimePowerData(i + 1);
data[i] = powerData.Power;
myGauge.WithLabels($"插座{i + 1}").Set(powerData.Power);
}
sw.Stop();
waitMs = Math.Max(waitMs - (int)sw.ElapsedMilliseconds, 0);
Console.WriteLine($"Read data: {string.Join(",", data)} ({sw.ElapsedMilliseconds:n0}ms)");
}
catch (Exception ex)
{
Console.WriteLine($"錯誤: {ex.Message}");
}
await Task.Delay(TimeSpan.FromMilliseconds(waitMs));
}
});
程式要包成 Docker Image 送到 Linux 跑容器,我順便溫習了 Dockerfile 建 Image 的技巧。Copilot 是好老師,生成了一個很專業的 Dockerfile,我不懂就問,學到一些 Docker Image 製作技巧,整理在後面。
# 使用 .NET 9 SDK 作為建置環境
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
WORKDIR /src
# 複製專案檔並還原相依套件 (利用快取機制,csproj 檔沒變動時,不需要重複還原)
COPY hs300-exporter.csproj .
RUN dotnet restore
# 專案只有一個 Program.cs 檔案
# 有很多檔案時,可使用 COPY . . 指令並配合 .dockerignore 檔案排除不要複製的檔案
COPY Program.cs .
# --no-restore 跳過前面已做過的 Package 還原步驟,加速建置
# /p:PublishSingleFile=false 不打包成單一檔,執行前不需解壓,啟動速度較快
# /p:PublishTrimmed=false 不進行程式碼修剪,加快建置減少出錯風險
RUN dotnet publish -c Release -o /app/publish \
--no-restore \
/p:PublishSingleFile=false \
/p:PublishTrimmed=false
# 使用 .NET 9 Runtime 作為執行環境(較小的 Image)
FROM mcr.microsoft.com/dotnet/runtime:9.0
WORKDIR /app
# 複製建置輸出
COPY --from=build /app/publish .
# 宣告使用 Port (Metadata 性質,不影響編譯或執行)
EXPOSE 9999
# 執行應用程式
ENTRYPOINT ["dotnet", "hs300-exporter.dll"]
# 建置與執行
# docker build -t hs300-exporter .
# docker save -o hs300-exporter.tar hs300-exporter
# scp .\hs300-exporter.tar user@remotehost:/path/to/
以下是這次學到的 .NET 編譯 Dockerfile 技巧:
- 兩次 FROM 切分成 Build Stage 及 Runtime Stage,兩次用的基底不同,Build 要用含完整 SDK 的 Image (730MB),Runtime 只需用 .NET Runtime Image (190MB) 即可。
- Dockerfile 編譯過程產生 7 個 Layer (不含兩次 FROM 帶入的基底):
- WORKDIR /src 建立工作目錄
- COPY hs300-exporter.csproj . 複製專案檔
- RUN dotnet restore 執行套件還原
- COPY Program.cs . 複製原始碼檔案
- RUN dotnet publish... 發佈檔案
- WORKDIR /app 建立工作目錄
- COPY --from=build /app/publish . 複製編譯結果
(註:EXPOSE 及 ENTRYPOINT 為 Metadata 不產生 Layer)
docker build最終產生的 Image 只會包含 .NET Runtime Image 及 6, 7 Layer- 先 COPY .csproj、dotnet restore,之後 dotnet publish --no-restore 的原因是,Layer 可被 Cache,若 .csproj 沒變動,編譯時 1 到 3 層可以用快取內容,不需要重新執行。
- /p:PublishSingleFile=false、/p:PublishTrimmed=false 有其考慮,但預設沒加註解(學長說:這不是常識嗎? XD),但問 Copilot 才知答案。
以上拆 .csproj 跟 dotnet restore 善用 Layer Cache 加速編譯的小訣竅官方教學沒講,謝謝 AI 不藏私帶我飛~
在 Linux 上用 docker-compose.yaml 啟動 hs300-exporter 容器並將 9999 Port 對應到本機的 9300 Port,Prometheus 會依 prometheus.yaml 指示到 http://localhost:9300/metrics 定期讀資料並寫入資料庫,要查詢最新 12 小時到最近五年的資料都不是問題。(註:Prometheus 要配合設定資料保存年限)
services:
hs300-exporter:
image: hs300-exporter:latest
container_name: hs300-exporter
restart: unless-stopped
ports:
- "9300:9999"
environment:
- TZ=Asia/Taipei
- HS300_DeviceIP=192.168.50.80
network_mode: bridge
另外,我使用的 cAdvisor/Prometheus/Grafana 範例沒有設定 Prometheus 資料長期保存,我調整了 docker-compose.yml 設定:
prometheus:
container_name: prometheus
image: prom/prometheus:latest
network_mode: "host"
# ports:
# - "9090:9090"
volumes:
- "./prometheus.yml:/etc/prometheus/prometheus.yml"
- "./prometheus-data:/prometheus"
command:
- "--config.file=/etc/prometheus/prometheus.yml"
- "--storage.tsdb.path=/prometheus"
- "--storage.tsdb.retention.time=5y"
privileged: true
depends_on:
- cadvisor
設定妥當後,在 Granfana 新增一個 Dashboard,指定接入 hs300_stats 資料,透過 Label Filter 指定 type = '插座1' 到 '插座6' 新增六個 Query,得到六個插座瓦數的折線圖:

Grafana 的圖表精美,設定介面挺直覺,最重要的是它的功能非常完整,你想得到的需求一應俱全。

像是指定查詢區期、設定篩選條件、詳細分析檢視... 等都難不倒它,用來管插座算是大材小用,Prometheus + Grafana 不愧是當前 DevOps 監測平台的一哥。


此刻,我也算摸到了 DevOps 的邊,感覺又更專業了一點,但這塊東西很多,未來有機會再繼續深入。
Migrated smart socket power monitoring from custom project to Prometheus + Grafana for advanced, automated charting and data management.
Comments
# by Elan
我想要去監控冷氣、熱水器等高耗電家電的使用量,但是他們的電路通常是獨立的,好像沒有適當的解決方案可以監控
# by Jeffrey
to Elan, 有種是用勾表原理測單線電流的產品(關鍵字 WIFi 能源監控器 80A 鉗),但多半是搭配 App 使用,不確定能程式整合。
# by GregYu
to Elan, Tapo P110 / Tapo P115 兩個插頭可與 Alexa 和 Google Home 運作, 某方面來說,也支援 Home Assistant 通訊 可以從這方面入手 另外,也有專門的設備, 安裝在 配電箱 直接監控電力使用狀況 https://www.youtube.com/watch?v=3iMe2N_pv0o
# by yoyo
exporter 能不能發佈成Native AOT,就不用 .NET Runtime了
# by Felix
Tapo 的智慧插座,似乎都不支援冷氣的 220V 有能支援 220V 的智慧插座嗎? WiFi 或 Matter 通訊皆可
# by Jeffrey
to yoyo, 嘿,被爆雷了,後面會有一篇討論精簡版 Image 及 AOT。
# by Neo Yao
黑大自己寫監控真厲害,前年因夏月電費破萬後就從亞馬遜入手了電力監測系統emporia 8迴路,分析用電大部份都是在晚上冷氣,就改申請台電的時間電價(免費換數位表電),冬夏月用電平均每度快4.x元回到3.x元.(老舊定頻冷氣和電暖器真的耗電,平均800-1000W,但無奈裝潢限制換掉要大工程)
# by Jeffrey
to Neo Yao, 原來是 Emporia,之前看過有人分享但忘了關鍵字一直沒查到。監控用電,Sensor 這段還是要靠現有產品,聽你提起 Emporia 有點想入手了。