169 lines
5.0 KiB
Arduino
169 lines
5.0 KiB
Arduino
#include <Arduino.h>
|
|
#include <esp_wifi.h>
|
|
#include "config.h"
|
|
#include "modbus.h"
|
|
#include "mqtt_handler.h"
|
|
|
|
// --- [G1] Wi-Fi 연결 설정 ---
|
|
void setup_wifi() {
|
|
delay(10);
|
|
Serial.println();
|
|
Serial.print("[WIFI] Connecting to ");
|
|
Serial.println(ssid);
|
|
|
|
WiFi.disconnect(true, true);
|
|
delay(500);
|
|
WiFi.mode(WIFI_STA);
|
|
delay(500);
|
|
|
|
esp_wifi_set_ps(WIFI_PS_NONE);
|
|
|
|
WiFi.begin(ssid, password);
|
|
|
|
int attempts = 0;
|
|
while (WiFi.status() != WL_CONNECTED) {
|
|
delay(500);
|
|
Serial.print(".");
|
|
attempts++;
|
|
|
|
if (attempts >= 20) {
|
|
Serial.println("\n[WIFI] 연결 지연 발생. 무선 재시작 중...");
|
|
WiFi.disconnect();
|
|
delay(500);
|
|
WiFi.begin(ssid, password);
|
|
attempts = 0;
|
|
}
|
|
}
|
|
|
|
Serial.println("");
|
|
Serial.println("[WIFI] connected");
|
|
Serial.print("[WIFI] IP address: ");
|
|
Serial.println(WiFi.localIP());
|
|
}
|
|
|
|
// --- [G7] 부팅 초기화 루틴 제어 함수 ---
|
|
void handle_init_sequence() {
|
|
if (!initSequenceStarted) {
|
|
initSequenceStarted = true;
|
|
setup_buffers();
|
|
|
|
Serial.println("[EVENT] id=999 Full-Sync 시작");
|
|
|
|
if (client.connected()) {
|
|
client.publish("/line1/event", "{\"id\":999,\"val\":1}");
|
|
}
|
|
}
|
|
}
|
|
|
|
// --- [G8] PLC 재부팅 감지 이벤트 처리 함수 ---
|
|
void trigger_plc_reboot_event() {
|
|
Serial.println("[EVENT] id=998 PLC_REBOOT 감지");
|
|
if (client.connected()) {
|
|
client.publish("/line1/event", "{\"id\":998,\"val\":1}");
|
|
}
|
|
|
|
currentState = STATE_INIT;
|
|
lastStateChange = millis();
|
|
initSequenceStarted = false;
|
|
}
|
|
|
|
// --- [G8] PLC 통신 복구 감지 처리 함수 ---
|
|
void trigger_plc_recovery() {
|
|
Serial.println("[EVENT] PLC 통신 복구 감지 -> Full-Sync 재수행 준비");
|
|
currentState = STATE_INIT;
|
|
lastStateChange = millis();
|
|
initSequenceStarted = false;
|
|
}
|
|
|
|
void setup() {
|
|
Serial.begin(115200);
|
|
Serial.printf("[SYS] Firmware version: %s\n", FIRMWARE_VERSION);
|
|
setup_buffers();
|
|
setup_wifi();
|
|
setup_mqtt();
|
|
setup_modbus();
|
|
lastStateChange = millis();
|
|
Serial.println("[SYS] Setup 완료.");
|
|
}
|
|
|
|
// --- [G2] 타이밍 스케줄러 메인 루프 ---
|
|
void loop() {
|
|
maintain_mqtt();
|
|
|
|
unsigned long now = millis();
|
|
|
|
switch (currentState) {
|
|
case STATE_INIT:
|
|
// 초기화 시퀀스 핸들링 (버퍼 클리어 및 999 이벤트 송신)
|
|
handle_init_sequence();
|
|
|
|
// 정상 주기적 PLC 읽기를 진행하지 않고 대기 (정상 로직 일시 중단)
|
|
if (now - lastStateChange >= INIT_DURATION) {
|
|
Serial.println("[STATE] INIT 완료 -> PLC 상태 조회 및 Full-Sync 데이터 전송 개시");
|
|
|
|
// 1회 PLC 데이터를 가져와 plcOnline 여부 및 버퍼 업데이트
|
|
run_plc_read();
|
|
|
|
if (plcOnline) {
|
|
// full_sync_pending 플래그가 설정되어 있으므로 전체 스냅샷이 송신됨
|
|
if (process_read_changes()) {
|
|
bool pub_ok = false;
|
|
Serial.println("[EVENT] id=997 Full-Sync 완료 이벤트 발행 시도...");
|
|
if (client.connected()) {
|
|
pub_ok = client.publish("/line1/event", "{\"id\":997,\"val\":1}");
|
|
}
|
|
|
|
if (pub_ok) {
|
|
full_sync_pending = false; // Full-Sync 완료 이벤트 발행 성공 시에만 일반 운전 상태로 전환
|
|
currentState = STATE_READ;
|
|
lastStateChange = now;
|
|
readExecuted = false;
|
|
Serial.println("[EVENT] id=997 Full-Sync 완료 이벤트 발행 성공, 정상 루틴 진입");
|
|
} else {
|
|
Serial.println("[WARN] Full-Sync 완료 이벤트(997) 발행 실패. 다음 주기에서 재발행을 재시도합니다.");
|
|
// 상태 전환을 하지 않고 STATE_INIT 대기 유지하여 다음 주기에서 재시도
|
|
}
|
|
} else {
|
|
Serial.println("[WARN] Full-Sync 전송 실패. 다음 주기에서 재동기화 재시도합니다.");
|
|
// 상태 전환을 하지 않고 STATE_INIT 대기 유지하여 다음 주기에서 재시도
|
|
}
|
|
} else {
|
|
Serial.println("[WARN] PLC 오프라인 상태 - Full-Sync 보류, 정상 루틴 진입");
|
|
full_sync_pending = false; // 오프라인이어도 플래그는 일단 정리하여 일반 모드 진입 준비
|
|
|
|
currentState = STATE_READ;
|
|
lastStateChange = now;
|
|
readExecuted = false;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case STATE_READ:
|
|
if (now - lastStateChange >= SLOT_DURATION) {
|
|
currentState = STATE_WRITE;
|
|
lastStateChange = now;
|
|
writeExecuted = false;
|
|
} else {
|
|
if (!readExecuted) {
|
|
run_plc_read();
|
|
process_read_changes();
|
|
readExecuted = true;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case STATE_WRITE:
|
|
if (now - lastStateChange >= SLOT_DURATION) {
|
|
currentState = STATE_READ;
|
|
lastStateChange = now;
|
|
readExecuted = false;
|
|
} else {
|
|
if (!writeExecuted) {
|
|
run_plc_write();
|
|
writeExecuted = true;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|