Integracja PLC: WAGO PFC200 + CODESYS 3.5
Kompletny przewodnik konfiguracji sterownika WAGO PFC200 do wysyłania metryk PV i magazynu energii do EnergyPal przez HTTP POST.
Wymagania
- Sterownik: WAGO PFC200 (750-8212) z e!RUNTIME
- Biblioteki CODESYS:
WagoAppHTTP,WagoTypes— zainstaluj przez Library Manager w środowisku CODESYS IDE - Sieć: sterownik musi mieć dostęp do internetu (port 443/HTTPS). WAGO PFC200 zawiera wbudowane certyfikaty CA.
- Klucz API: Twój
energy_connection_keyod administratora EnergyPal - Skonfigurowane urządzenia: kody urządzeń (np.
PV-1,BESS-1) muszą być zarejestrowane w EnergyPal. Zweryfikuj za pomocą GET /v1/devices.
Krok 1: Deklaracja bloku funkcyjnego FB_EnergyPalSender
Utwórz nowy POU typu FUNCTION_BLOCK w projekcie CODESYS. Wklej poniższą deklarację zmiennych:
FUNCTION_BLOCK FB_EnergyPalSender
VAR_INPUT
rSoC : REAL; (* Stan naladowania BESS [%] *)
rEnergyExported : REAL; (* Licznik rozladowania BESS [kWh] *)
rEnergyImported : REAL; (* Licznik ladowania BESS [kWh] *)
rPvGenerated1 : REAL; (* Licznik produkcji PV-1 [kWh] *)
rPvGenerated2 : REAL; (* Licznik produkcji PV-2 [kWh] *)
rEnergyConsumed : REAL; (* Licznik zuzycia LOAD-0 [kWh] *)
END_VAR
VAR_OUTPUT
bBusy : BOOL; (* Wysylanie w toku *)
bError : BOOL; (* Blad ostatniego wysylania *)
iHttpStatus : INT; (* Kod odpowiedzi HTTP *)
END_VAR
VAR
fbHttpClient : WagoAppHTTP.WagoHTTPClient;
fbTimer : TON;
bSend : BOOL;
bRequestDone : BOOL;
sJson : STRING(2048);
sUrl : STRING(255) := 'https://api.energypal.ai/v1/ingest';
sApiKey : STRING(255) := 'twoj-klucz-api'; (* <- wstaw swoj klucz *)
sContentType : STRING(64) := 'application/json';
sResponse : STRING(1024);
END_VAR
Zmień wartość sApiKey na swój klucz API. Jeśli masz inne kody urządzeń niż PV-1, PV-2, BESS-1, LOAD-0 — dostosuj je w implementacji poniżej.
Krok 2: Implementacja bloku
W zakładce implementacji bloku FB_EnergyPalSender wklej poniższy kod. Blok buduje JSON z aktualnymi wartościami metryk i wysyła go przez HTTP POST co 15 minut:
(* === Cykliczny timer - wysylanie co 15 minut === *)
fbTimer(IN := NOT fbTimer.Q, PT := T#900S);
IF fbTimer.Q AND NOT bBusy THEN
bSend := TRUE;
END_IF
(* === Budowanie JSON === *)
IF bSend THEN
bSend := FALSE;
bBusy := TRUE;
bError := FALSE;
sJson := CONCAT('{"metrics":{',
'"PV-1":{"energy_generated_meter":', REAL_TO_STRING(rPvGenerated1), '},',
'"PV-2":{"energy_generated_meter":', REAL_TO_STRING(rPvGenerated2), '},',
'"BESS-1":{"soc":', REAL_TO_STRING(rSoC),
',"energy_exported_meter":', REAL_TO_STRING(rEnergyExported),
',"energy_imported_meter":', REAL_TO_STRING(rEnergyImported),
'},',
'"LOAD-0":{"energy_consumed_meter":', REAL_TO_STRING(rEnergyConsumed),
'}}}');
(* === Konfiguracja i wysylanie HTTP POST === *)
fbHttpClient.sUrl := sUrl;
fbHttpClient.sContentType := sContentType;
fbHttpClient.sRequestData := sJson;
fbHttpClient.bExecute := TRUE;
(* Dodaj naglowek X-API-Key *)
fbHttpClient.AddHeader('X-API-Key', sApiKey);
END_IF
(* === Obsluga odpowiedzi === *)
fbHttpClient();
IF fbHttpClient.bDone OR fbHttpClient.bError THEN
bBusy := FALSE;
iHttpStatus := fbHttpClient.iStatusCode;
bError := fbHttpClient.bError OR (iHttpStatus <> 200);
sResponse := fbHttpClient.sResponseData;
fbHttpClient.bExecute := FALSE;
END_IF
Krok 3: Wywołanie w PLC_PRG
W głównym programie PLC_PRG utwórz instancję bloku i podłącz zmienne procesowe ze swojej instalacji:
PROGRAM PLC_PRG
VAR
fbSender : FB_EnergyPalSender;
(* --- Wstaw tutaj swoje zmienne procesowe --- *)
rSoC_BMS : REAL; (* np. odczyt z Modbus / wejscia analogowego *)
rExportMeter_BMS : REAL;
rImportMeter_BMS : REAL;
rPvMeter_Inverter1 : REAL;
rPvMeter_Inverter2 : REAL;
rConsumptionMeter : REAL; (* calkowite zuzycie energii [kWh] *)
END_VAR
(* Wywolanie bloku wysylajacego *)
fbSender(
rSoC := rSoC_BMS,
rEnergyExported := rExportMeter_BMS,
rEnergyImported := rImportMeter_BMS,
rPvGenerated1 := rPvMeter_Inverter1,
rPvGenerated2 := rPvMeter_Inverter2,
rEnergyConsumed := rConsumptionMeter
);
(* Opcjonalnie: diagnostyka w wizualizacji *)
(* fbSender.bBusy - czy trwa wysylanie *)
(* fbSender.bError - czy ostatnie wyslanie sie nie powiodlo *)
(* fbSender.iHttpStatus - kod HTTP odpowiedzi (200 = OK) *)
Uwagi konfiguracyjne
- Interwał wysyłania: timer
T#900Soznacza wysyłanie co 15 minut (zgodnie z interwałem agregacji systemu). Zmień naT#300S(5 minut) jeśli chcesz większą redundancję na wypadek błędu połączenia. - Liczniki kumulatywne: wartości
energy_*_metermuszą być zawsze rosnące. Nigdy nie resetuj — system automatycznie oblicza przyrost energii. - Obsługa błędów: jeśli
iHttpStatusjest różny od200, blok automatycznie ponowi wysyłanie przy następnym cyklu timera. System jest idempotentny — duplikaty w 15-minutowym oknie są pomijane. - Kody urządzeń: muszą dokładnie odpowiadać konfiguracji w EnergyPal. Zweryfikuj za pomocą
GET /v1/devices. - Device codes: jeśli masz inną liczbę inwerterów lub magazynów, dostosuj budowanie stringa
sJsonw implementacji. - Diagnostyka: zmienne wyjściowe
bBusy,bError,iHttpStatusmożesz podłączyć do wizualizacji CODESYS, aby monitorować status wysyłania.
Odczyt cen energii
Aby pobierać prognozy cen energii na sterowniku WAGO (do optymalizacji magazynu), zobacz dedykowany przewodnik: Odczyt cen energii (WAGO + CODESYS).
Testowanie za pomocą curl
Przed konfiguracją PLC przetestuj połączenie z API:
# Wysłanie testowych danych
curl -X POST https://api.energypal.ai/v1/ingest \
-H "Content-Type: application/json" \
-H "X-API-Key: twoj-klucz-api" \
-d '{
"metrics": {
"PV-1": {"energy_generated_meter": 12345.0},
"BESS-1": {"soc": 85.5, "energy_exported_meter": 500.0, "energy_imported_meter": 450.0},
"LOAD-0": {"energy_consumed_meter": 98765.0}
}
}'
# Weryfikacja kodów urządzeń
curl -H "X-API-Key: twoj-klucz-api" https://api.energypal.ai/v1/devices