APSTA모드 추가
This commit is contained in:
@@ -159,6 +159,11 @@ enum MCP2515Mode {
|
||||
char wifiSSID[32] = "Byun_CAN_Logger";
|
||||
char wifiPassword[64] = "12345678";
|
||||
|
||||
// WiFi Station 모드 설정 (추가)
|
||||
bool enableSTAMode = false; // APSTA 모드 활성화 여부
|
||||
char staSSID[32] = ""; // 연결할 WiFi SSID
|
||||
char staPassword[64] = ""; // 연결할 WiFi 비밀번호
|
||||
|
||||
// 전역 변수
|
||||
SPIClass hspi(HSPI);
|
||||
SPIClass vspi(VSPI);
|
||||
@@ -233,10 +238,15 @@ int commentCount = 0;
|
||||
void loadSettings() {
|
||||
preferences.begin("can-logger", false);
|
||||
|
||||
// WiFi 설정 로드
|
||||
// WiFi AP 설정 로드
|
||||
preferences.getString("wifi_ssid", wifiSSID, sizeof(wifiSSID));
|
||||
preferences.getString("wifi_pass", wifiPassword, sizeof(wifiPassword));
|
||||
|
||||
// WiFi STA 모드 설정 로드 (추가)
|
||||
enableSTAMode = preferences.getBool("sta_enable", false);
|
||||
preferences.getString("sta_ssid", staSSID, sizeof(staSSID));
|
||||
preferences.getString("sta_pass", staPassword, sizeof(staPassword));
|
||||
|
||||
// 설정이 없으면 기본값 사용
|
||||
if (strlen(wifiSSID) == 0) {
|
||||
strcpy(wifiSSID, "Byun_CAN_Logger");
|
||||
@@ -260,21 +270,37 @@ void loadSettings() {
|
||||
}
|
||||
|
||||
preferences.end();
|
||||
|
||||
// STA 모드 설정 출력
|
||||
if (enableSTAMode && strlen(staSSID) > 0) {
|
||||
Serial.printf("✓ WiFi STA 모드: 활성화 (SSID: %s)\n", staSSID);
|
||||
}
|
||||
}
|
||||
|
||||
void saveSettings() {
|
||||
preferences.begin("can-logger", false);
|
||||
|
||||
// WiFi 설정 저장
|
||||
// WiFi AP 설정 저장
|
||||
preferences.putString("wifi_ssid", wifiSSID);
|
||||
preferences.putString("wifi_pass", wifiPassword);
|
||||
|
||||
// WiFi STA 모드 설정 저장 (추가)
|
||||
preferences.putBool("sta_enable", enableSTAMode);
|
||||
preferences.putString("sta_ssid", staSSID);
|
||||
preferences.putString("sta_pass", staPassword);
|
||||
|
||||
preferences.end();
|
||||
|
||||
Serial.println("\n✓ 설정 저장 완료:");
|
||||
Serial.println("----------------------------------------");
|
||||
Serial.printf(" WiFi SSID : %s\n", wifiSSID);
|
||||
Serial.printf(" WiFi Password : %s\n", wifiPassword);
|
||||
Serial.printf(" WiFi AP SSID : %s\n", wifiSSID);
|
||||
Serial.printf(" WiFi AP Password : %s\n", wifiPassword);
|
||||
if (enableSTAMode && strlen(staSSID) > 0) {
|
||||
Serial.printf(" STA Mode : 활성화\n");
|
||||
Serial.printf(" STA SSID : %s\n", staSSID);
|
||||
} else {
|
||||
Serial.printf(" STA Mode : 비활성화\n");
|
||||
}
|
||||
Serial.println("----------------------------------------");
|
||||
Serial.println("⚠️ 재부팅 후 WiFi 설정이 적용됩니다.");
|
||||
}
|
||||
@@ -1287,7 +1313,12 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length)
|
||||
// 설정 전송
|
||||
String settings = "{\"type\":\"settings\",";
|
||||
settings += "\"ssid\":\"" + String(wifiSSID) + "\",";
|
||||
settings += "\"password\":\"" + String(wifiPassword) + "\"}";
|
||||
settings += "\"password\":\"" + String(wifiPassword) + "\",";
|
||||
settings += "\"staEnable\":" + String(enableSTAMode ? "true" : "false") + ",";
|
||||
settings += "\"staSSID\":\"" + String(staSSID) + "\",";
|
||||
settings += "\"staPassword\":\"" + String(staPassword) + "\",";
|
||||
settings += "\"staConnected\":" + String(WiFi.status() == WL_CONNECTED ? "true" : "false") + ",";
|
||||
settings += "\"staIP\":\"" + WiFi.localIP().toString() + "\"}";
|
||||
|
||||
webSocket.sendTXT(num, settings);
|
||||
|
||||
@@ -1301,6 +1332,26 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length)
|
||||
int passEnd = message.indexOf("\"", passStart);
|
||||
String password = message.substring(passStart, passEnd);
|
||||
|
||||
// STA 모드 설정 파싱
|
||||
int staEnableIdx = message.indexOf("\"staEnable\":");
|
||||
if (staEnableIdx >= 0) {
|
||||
String staEnableStr = message.substring(staEnableIdx + 12, staEnableIdx + 16);
|
||||
enableSTAMode = (staEnableStr.indexOf("true") >= 0);
|
||||
|
||||
if (enableSTAMode) {
|
||||
int staSSIDStart = message.indexOf("\"staSSID\":\"") + 11;
|
||||
int staSSIDEnd = message.indexOf("\"", staSSIDStart);
|
||||
String staSsid = message.substring(staSSIDStart, staSSIDEnd);
|
||||
|
||||
int staPassStart = message.indexOf("\"staPassword\":\"") + 15;
|
||||
int staPassEnd = message.indexOf("\"", staPassStart);
|
||||
String staPass = message.substring(staPassStart, staPassEnd);
|
||||
|
||||
strncpy(staSSID, staSsid.c_str(), sizeof(staSSID) - 1);
|
||||
strncpy(staPassword, staPass.c_str(), sizeof(staPassword) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
strncpy(wifiSSID, ssid.c_str(), sizeof(wifiSSID) - 1);
|
||||
strncpy(wifiPassword, password.c_str(), sizeof(wifiPassword) - 1);
|
||||
|
||||
@@ -1638,18 +1689,60 @@ void setup() {
|
||||
Serial.println("✗ SD 카드 초기화 실패");
|
||||
}
|
||||
|
||||
// WiFi AP 시작
|
||||
WiFi.softAP(wifiSSID, wifiPassword);
|
||||
// WiFi 설정 - APSTA 모드 지원
|
||||
if (enableSTAMode && strlen(staSSID) > 0) {
|
||||
// APSTA 모드 (AP + Station 동시 동작)
|
||||
Serial.println("\n📶 WiFi APSTA 모드 시작...");
|
||||
|
||||
WiFi.mode(WIFI_AP_STA);
|
||||
|
||||
// AP 모드 시작
|
||||
WiFi.softAP(wifiSSID, wifiPassword);
|
||||
Serial.print("✓ AP SSID: ");
|
||||
Serial.println(wifiSSID);
|
||||
Serial.print("✓ AP IP: ");
|
||||
Serial.println(WiFi.softAPIP());
|
||||
|
||||
// Station 모드로 WiFi 연결 시도
|
||||
Serial.printf("📡 WiFi 연결 시도: %s\n", staSSID);
|
||||
WiFi.begin(staSSID, staPassword);
|
||||
|
||||
// 연결 대기 (최대 10초)
|
||||
int attempts = 0;
|
||||
while (WiFi.status() != WL_CONNECTED && attempts < 20) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
attempts++;
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
Serial.println("✓ WiFi 연결 성공!");
|
||||
Serial.print("✓ STA IP: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
Serial.print("✓ Gateway: ");
|
||||
Serial.println(WiFi.gatewayIP());
|
||||
Serial.print("✓ DNS: ");
|
||||
Serial.println(WiFi.dnsIP());
|
||||
} else {
|
||||
Serial.println("✗ WiFi 연결 실패 (AP 모드는 정상 동작)");
|
||||
}
|
||||
} else {
|
||||
// AP 모드만 사용
|
||||
Serial.println("\n📶 WiFi AP 모드 시작...");
|
||||
WiFi.mode(WIFI_AP);
|
||||
WiFi.softAP(wifiSSID, wifiPassword);
|
||||
|
||||
Serial.print("✓ AP SSID: ");
|
||||
Serial.println(wifiSSID);
|
||||
Serial.print("✓ AP IP: ");
|
||||
Serial.println(WiFi.softAPIP());
|
||||
}
|
||||
|
||||
// WiFi 성능 최적화
|
||||
WiFi.setSleep(false); // WiFi 절전 모드 비활성화 (신호 강도 개선)
|
||||
esp_wifi_set_max_tx_power(84); // TX 출력 최대화 (20.5dBm = 84/4)
|
||||
|
||||
Serial.print("✓ AP SSID: ");
|
||||
Serial.println(wifiSSID);
|
||||
Serial.print("✓ AP IP: ");
|
||||
Serial.println(WiFi.softAPIP());
|
||||
|
||||
// WebSocket 시작
|
||||
webSocket.begin();
|
||||
webSocket.onEvent(webSocketEvent);
|
||||
|
||||
132
settings.h
132
settings.h
@@ -99,11 +99,11 @@ const char settings_html[] PROGMEM = R"rawliteral(
|
||||
input[type="password"] {
|
||||
width: 100%;
|
||||
padding: 12px 15px;
|
||||
border: 2px solid #ddd;
|
||||
border: 2px solid #e1e8ed;
|
||||
border-radius: 8px;
|
||||
font-size: 1em;
|
||||
font-size: 0.95em;
|
||||
transition: all 0.3s;
|
||||
font-family: inherit;
|
||||
background: white;
|
||||
}
|
||||
|
||||
input[type="text"]:focus,
|
||||
@@ -113,6 +113,38 @@ const char settings_html[] PROGMEM = R"rawliteral(
|
||||
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
|
||||
}
|
||||
|
||||
input[type="checkbox"] {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
cursor: pointer;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.checkbox-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.checkbox-group label {
|
||||
margin-bottom: 0;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.sta-settings {
|
||||
background: #f0f4f8;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
margin-top: 15px;
|
||||
border-left: 4px solid #667eea;
|
||||
}
|
||||
|
||||
.sta-settings.disabled {
|
||||
opacity: 0.5;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.button-group {
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
@@ -273,17 +305,49 @@ const char settings_html[] PROGMEM = R"rawliteral(
|
||||
<span>WiFi Configuration</span>
|
||||
</div>
|
||||
|
||||
<h3 style="color: #333; font-size: 1.1em; margin-bottom: 15px;">AP Mode (Access Point)</h3>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="wifi-ssid">WiFi SSID (네트워크 이름)</label>
|
||||
<label for="wifi-ssid">AP SSID (네트워크 이름)</label>
|
||||
<input type="text" id="wifi-ssid" placeholder="Byun_CAN_Logger" maxlength="31">
|
||||
<div class="help-text">ESP32가 생성할 WiFi 네트워크 이름입니다 (최대 31자)</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="wifi-password">WiFi Password (비밀번호)</label>
|
||||
<label for="wifi-password">AP Password (비밀번호)</label>
|
||||
<input type="password" id="wifi-password" placeholder="최소 8자 이상" minlength="8" maxlength="63">
|
||||
<div class="help-text">WiFi 접속 시 필요한 비밀번호입니다 (8-63자)</div>
|
||||
</div>
|
||||
|
||||
<hr style="margin: 25px 0; border: none; border-top: 1px solid #ddd;">
|
||||
|
||||
<h3 style="color: #333; font-size: 1.1em; margin-bottom: 15px;">APSTA Mode (AP + Station)</h3>
|
||||
|
||||
<div class="checkbox-group">
|
||||
<input type="checkbox" id="sta-enable" onchange="toggleSTASettings()">
|
||||
<label for="sta-enable">Station 모드 활성화 (외부 WiFi에 연결)</label>
|
||||
</div>
|
||||
<div class="help-text" style="margin-left: 30px; margin-bottom: 15px;">
|
||||
AP와 Station을 동시에 사용하여 인터넷 접속 가능
|
||||
</div>
|
||||
|
||||
<div id="sta-settings" class="sta-settings disabled">
|
||||
<div class="form-group">
|
||||
<label for="sta-ssid">연결할 WiFi SSID</label>
|
||||
<input type="text" id="sta-ssid" placeholder="공유기 이름 입력" maxlength="31">
|
||||
<div class="help-text">연결할 외부 WiFi 네트워크 이름</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="sta-password">연결할 WiFi Password</label>
|
||||
<input type="password" id="sta-password" placeholder="공유기 비밀번호 입력" maxlength="63">
|
||||
<div class="help-text">외부 WiFi 비밀번호</div>
|
||||
</div>
|
||||
|
||||
<div id="sta-status" style="display: none; margin-top: 15px; padding: 12px; background: #e8f5e9; border-radius: 6px; color: #2e7d32; font-weight: 600;">
|
||||
✓ WiFi 연결됨: <span id="sta-ip"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="button-group">
|
||||
@@ -298,8 +362,9 @@ const char settings_html[] PROGMEM = R"rawliteral(
|
||||
</div>
|
||||
<div class="info-box-text">
|
||||
• WiFi 설정을 변경한 경우, ESP32를 재부팅해야 새 SSID/비밀번호가 적용됩니다.<br>
|
||||
• 시간 설정은 모니터 페이지에서 "Sync from Phone" 버튼을 눌러 핸드폰 시간과 동기화할 수 있습니다.<br>
|
||||
• RTC 모듈이 연결된 경우, 시간이 자동으로 보정됩니다.<br>
|
||||
• <strong>APSTA 모드:</strong> Station 모드를 활성화하면 ESP32가 AP와 Station을 동시에 사용합니다.<br>
|
||||
• Station 모드로 외부 WiFi에 연결하면 인터넷 접속이 가능해집니다.<br>
|
||||
• Station 연결 실패 시에도 AP 모드는 정상 동작합니다.<br>
|
||||
• 설정 저장 후 ESP32의 리셋 버튼을 눌러 재부팅하세요.
|
||||
</div>
|
||||
</div>
|
||||
@@ -335,6 +400,22 @@ const char settings_html[] PROGMEM = R"rawliteral(
|
||||
document.getElementById('wifi-ssid').value = data.ssid || 'Byun_CAN_Logger';
|
||||
document.getElementById('wifi-password').value = data.password || '';
|
||||
|
||||
// STA 모드 설정 로드
|
||||
document.getElementById('sta-enable').checked = data.staEnable || false;
|
||||
document.getElementById('sta-ssid').value = data.staSSID || '';
|
||||
document.getElementById('sta-password').value = data.staPassword || '';
|
||||
|
||||
// STA 설정 표시/숨김
|
||||
toggleSTASettings();
|
||||
|
||||
// STA 연결 상태 표시
|
||||
if (data.staConnected && data.staIP && data.staIP !== '0.0.0.0') {
|
||||
document.getElementById('sta-ip').textContent = data.staIP;
|
||||
document.getElementById('sta-status').style.display = 'block';
|
||||
} else {
|
||||
document.getElementById('sta-status').style.display = 'none';
|
||||
}
|
||||
|
||||
hideAlert('alert-loading');
|
||||
console.log('Settings loaded:', data);
|
||||
} else if (data.type === 'settingsSaved') {
|
||||
@@ -359,6 +440,11 @@ const char settings_html[] PROGMEM = R"rawliteral(
|
||||
const ssid = document.getElementById('wifi-ssid').value.trim();
|
||||
const password = document.getElementById('wifi-password').value;
|
||||
|
||||
// STA 모드 설정
|
||||
const staEnable = document.getElementById('sta-enable').checked;
|
||||
const staSSID = document.getElementById('sta-ssid').value.trim();
|
||||
const staPassword = document.getElementById('sta-password').value;
|
||||
|
||||
// 입력 검증
|
||||
if (ssid.length === 0) {
|
||||
alert('WiFi SSID를 입력하세요.');
|
||||
@@ -380,10 +466,29 @@ const char settings_html[] PROGMEM = R"rawliteral(
|
||||
return;
|
||||
}
|
||||
|
||||
// STA 모드 검증
|
||||
if (staEnable) {
|
||||
if (staSSID.length === 0) {
|
||||
alert('Station 모드를 활성화하려면 WiFi SSID를 입력하세요.');
|
||||
return;
|
||||
}
|
||||
if (staSSID.length > 31) {
|
||||
alert('Station WiFi SSID는 최대 31자까지 입력 가능합니다.');
|
||||
return;
|
||||
}
|
||||
if (staPassword.length > 0 && staPassword.length < 8) {
|
||||
alert('Station WiFi 비밀번호는 최소 8자 이상이어야 합니다.');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const settings = {
|
||||
cmd: 'saveSettings',
|
||||
ssid: ssid,
|
||||
password: password
|
||||
password: password,
|
||||
staEnable: staEnable,
|
||||
staSSID: staSSID,
|
||||
staPassword: staPassword
|
||||
};
|
||||
|
||||
if (ws && ws.readyState === WebSocket.OPEN) {
|
||||
@@ -422,6 +527,17 @@ const char settings_html[] PROGMEM = R"rawliteral(
|
||||
}
|
||||
}
|
||||
|
||||
function toggleSTASettings() {
|
||||
const staEnable = document.getElementById('sta-enable').checked;
|
||||
const staSettings = document.getElementById('sta-settings');
|
||||
|
||||
if (staEnable) {
|
||||
staSettings.classList.remove('disabled');
|
||||
} else {
|
||||
staSettings.classList.add('disabled');
|
||||
}
|
||||
}
|
||||
|
||||
// 페이지 로드 시 WebSocket 연결
|
||||
window.addEventListener('load', function() {
|
||||
initWebSocket();
|
||||
|
||||
Reference in New Issue
Block a user