跳到內容
返回官網

案例:充電樁叢集負載平衡

本案例演示如何僅用 Edge-EMS Builder 的通用能力——動態資料掃描、運算式計算、觸發方案、限頻控制——搭建出一套具備“裝置數量可變、無需改指令碼”能力的負載平衡策略。文中裝置品牌、命名前綴均為示意,請替換為你專案中的實際命名。

配電箱同時接入若干臺充電樁(協定不限,可為 OCPP 或廠商私有協定)與其他必要負載(如照明、空調)。配電箱的電網側進線容量固定,當所有充電樁同時全功率充電時,總用電量可能超過進線額定容量,導致跳閘或超容罰款。

目標:在保證必要負載優先獲得供電的前提下,讓所有線上充電樁共享剩餘可用容量,動態調整每臺樁的充電電流,任何一臺樁上下線都能在數秒內完成再平衡,且新增充電樁不需要修改任何策略指令碼。

系統中有兩個關鍵測量點:

  • Grid_total_power:電網側即時輸入總功率(含配電箱內所有負載:必要負載 + 充電樁 + 其他);
  • 必要負載已經體現在這個實測值裡,因此只需要控制充電樁的總消耗,就能保證配電箱總輸入不超過額定功率,必要負載自然被優先滿足。
-- 可分配餘量(kW)= (額定功率 - 實測電網總功率) × 安全係數
-- 10% 安全裕量防止功率超調,實測值已含必要負載,無需單獨扣除
local avail_kw = (rated_kw - grid_kw) * 0.9
local per_A = (avail_kw / n) * 1000 / voltage_V -- 均分為電流(A)

三、動態裝置發現:新增充電樁無需改指令碼

Section titled “三、動態裝置發現:新增充電樁無需改指令碼”

策略不預設充電樁數量。每次執行時,透過按前綴+後綴批次掃描的方式,自動發現所有線上充電樁:

local online = {}
-- 逐個品牌前綴掃描,可按需增減
for _, brandPrefix in ipairs({"VENDORA", "VENDORB"}) do
local statusMap = getLatestDataValuesByPrefixAndSuffix("Collection", brandPrefix, "_status")
if statusMap then
-- 回傳值是以 dataKey 為鍵的 Table,用 pairs() 遍歷;判空比較哨兵字串 "__Null__"
for dataKey, dto in pairs(statusMap) do
if dto.DataValue ~= "__Null__" then
table.insert(online, dto)
end
end
end
end

只要新充電樁的擷取點位按約定的命名規則接入(見下方“命名規則”),下一次觸發時就會被自動納入均分計算,不需要修改指令碼、不需要重新啟動服務。這正是 資料模型 與 Lua引擎 組合出來的能力,而非某個專屬功能。

四、觸發模型:資料重新整理 + 指令碼內限頻

Section titled “四、觸發模型:資料重新整理 + 指令碼內限頻”

如果單純用固定週期輪詢,會造成“資料沒變也執行一次”的冗餘寫入;如果把限頻條件也放進觸發器,又會讓條件設定變複雜。這裡採用更簡潔的模式:

資料重新整理觸發 + 指令碼內時間戳限頻:觸發器只負責感知資料重新整理,實際的指令下發頻率由指令碼自主控制。

資料重新整理 → 滿足條件 → 觸發指令碼 → 讀取聚合點位 last_ctrl_ms(上次執行時間戳)
→ 距今 < 5000ms:直接回傳,不下發指令
→ 距今 ≥ 5000ms:執行控制 → 寫入指令 → 重新整理時間戳

部署前置步驟:需要先手動建立一個聚合點位,作為指令碼的“記憶”:

{
"dataKey": "last_ctrl_ms",
"dataName": "充电控制上次执行时间戳",
"expression": "return 0",
"collectionCycle": -1
}

每次觸發後,指令碼按順序執行:讀取電網參數 → 限頻檢查 → 掃描線上充電樁 → 計算可用電流 → 逐樁決策 → 重新整理時間戳 → 回傳指令清單。逐樁決策規則:

條件 充電樁狀態 執行動作
超載 或 均分電流 < 最小電流 充電中 停止充電(stop_transaction)
超載 或 均分電流 < 最小電流 其他 跳過
未超載 且 均分電流 ≥ 最小電流 充電中 下發新的限流值(set_charging_profile)
未超載 且 均分電流 ≥ 最小電流 非充電中 啟動充電(start_transaction,需授權 Tag 有效)

對應的核心指令碼片段(觸發動作,回傳寫入描述陣列):

local OffsetDateTime = require("OffsetDateTime")
local ratedKw = tonumber(${Grid_current} or 0) * tonumber(${Grid_voltage} or 0) * 0.001
local gridKw = tonumber(${Grid_total_power} or 0)
local overload = gridKw >= ratedKw
local voltage = tonumber(${Grid_voltage} or 1)
local minChargePower = tonumber(${min_charge_power} or 4200)
local resultList = {}
if #online > 0 then
local availKw = (ratedKw - gridKw) * 0.9
local perA = math.floor((availKw / #online) * 1000 / voltage)
local minA = math.floor(minChargePower / voltage)
for _, pile in ipairs(online) do
local prefix = pile.DataKey:gsub("_status$", "") -- 從 dataKey 還原出充電樁前綴,如 VENDORA01
if overload or perA < minA then
if pile.DataValue == "Charging" then
table.insert(resultList, buildCommonWriteMap("Collection", prefix .. "_type", "stop_transaction", nil, nil, false))
end
else
if pile.DataValue == "Charging" then
table.insert(resultList, buildCommonWriteMap("Collection", prefix .. "_periods", '[{"start":0,"limit":' .. perA .. '}]', nil, nil, false))
elseif ${id_tag} ~= "__Null__" then
table.insert(resultList, buildCommonWriteMap("Collection", prefix .. "_type", "start_transaction", nil, nil, false))
end
end
end
end
table.insert(resultList, buildCommonWriteMap("Aggregation", "last_ctrl_ms", OffsetDateTime.now():unixMilli(), nil, nil, false))
return resultList

六、命名規則:批次識別的前提

Section titled “六、命名規則:批次識別的前提”

指令碼按 {品牌前缀}{两位编号}_{属性} 的格式批次掃描充電樁擷取點位,必須嚴格遵守:

部分 規則 示例
品牌前綴 全大寫、不含底線 VENDORA、VENDORB(請替換為你實際使用的裝置品牌標識)
編號 兩位零填充 01、02…10
屬性 見下表 status、type

每臺充電樁需要具備的擷取點位(部分示例):

屬性 完整 dataKey 示例 讀/寫 說明
_status VENDORA01_status 讀 充電樁狀態,掃描依據,缺失則該樁不被發現
_transaction_id VENDORA01_transaction_id 讀 目前交易 ID
_type VENDORA01_type 寫 指令型別:start/stop/set_charging_profile
_periods VENDORA01_periods 寫 限額週期 JSON,如 [{"start":0,"limit":16}]

新增第 6 臺該品牌充電樁時,只需按上述命名接入其擷取點位——VENDORA06_status、VENDORA06_type……即可自動被納入均分邏輯。

場景 是否需要改指令碼 操作
新增同品牌充電樁 否 按命名規則新增擷取點位即可
調整額定容量上限 否 修改聚合點位 Grid_current 的值
調整最小充電功率 否 修改聚合點位 min_charge_power 的值
充電樁臨時下線 否 斷開後 _status 變空,自動從線上清單排除
新增充電樁品牌 是 掃描清單新增一個前綴,如 {"VENDORA", "VENDORB", "VENDORC"}
安全裕量係數可設定化 是(一次性) 新增聚合點位承載該係數,指令碼改為讀取該點位

這張表本身也說明了 設計理念 裡強調的一點:大部分業務變化只是改設定,只有少數結構性變化才需要改指令碼,而且改動範圍是可預期、可控的。

  • 若充電樁叢集分佈在多個子配電箱,可透過 裝置協作 把各子配電箱的電網實測功率共享到主控裝置,在主控上統一做全域均分。
  • 若充電樁品牌型號會隨專案不斷增加,且不同專案的樁群結構相似,可透過 裝置單元動態擴充 把“品牌前綴 + 命名規則 + 關聯點位”沉澱為範本,縮短新專案的搭建時間。
  • 若需要雲端下發限流閾值、檢視整體負載平衡狀態,透過 雲端與邊緣協作 定期回報電網餘量、各樁下發指令記錄。
充電樁負載平衡的擷取、計算、分配與執行流程

本圖根據本頁設定邏輯繪製,展示資料與控制流程。具體操作欄位請參照文中的設定與指令碼。