Browse Source

front 개발 완

v2
원형 1 year ago
parent
commit
26ad02a1ad
  1. 18
      src/main/java/org/mobidgim/mobidigimproject/config/filterconfig/FilterConfig.java
  2. 11
      src/main/java/org/mobidgim/mobidigimproject/controller/Controller.java
  3. 63
      src/main/java/org/mobidgim/mobidigimproject/filter/LoggerFilter.java
  4. 4
      src/main/java/org/mobidgim/mobidigimproject/model/device/DeviceDTO.java
  5. 3
      src/main/java/org/mobidgim/mobidigimproject/model/device/WifiSSIDS.java
  6. 3
      src/main/java/org/mobidgim/mobidigimproject/model/device/enums/ImuRemap.java
  7. 2
      src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/CanBus.java
  8. 18
      src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/Imu.java
  9. 6
      src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/Rs485.java
  10. 8
      src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/Wifi.java
  11. 4
      src/main/java/org/mobidgim/mobidigimproject/model/register/RegisterDTO.java
  12. 23
      src/main/java/org/mobidgim/mobidigimproject/service/SettingService.java
  13. 410
      src/main/resources/static/index.html

18
src/main/java/org/mobidgim/mobidigimproject/config/filterconfig/FilterConfig.java

@ -0,0 +1,18 @@
package org.mobidgim.mobidigimproject.config.filterconfig;
import org.mobidgim.mobidigimproject.filter.LoggerFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<LoggerFilter> loggerFilter() {
FilterRegistrationBean<LoggerFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new LoggerFilter());
registration.addUrlPatterns("/*");
registration.setOrder(1);
return registration;
}
}

11
src/main/java/org/mobidgim/mobidigimproject/controller/Controller.java

@ -4,7 +4,6 @@ import jakarta.servlet.ServletResponse;
import lombok.AllArgsConstructor;
import org.mobidgim.mobidigimproject.common.api.Api;
import org.mobidgim.mobidigimproject.model.device.DeviceDTO;
import org.mobidgim.mobidigimproject.model.register.RegisterDTO;
import org.mobidgim.mobidigimproject.service.SettingService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@ -26,9 +25,9 @@ public class Controller {
return Api.OK(request);
}
@PostMapping("/register")
public Api<RegisterDTO> settingRegister(@RequestBody RegisterDTO request)throws IOException{
settingService.saveFileWithRegister(request);
return Api.OK(request);
}
// @PostMapping("/register")
// public Api<RegisterDTO> settingRegister(@RequestBody RegisterDTO request)throws IOException{
// settingService.saveFileWithRegister(request);
// return Api.OK(request);
// }
}

63
src/main/java/org/mobidgim/mobidigimproject/filter/LoggerFilter.java

@ -0,0 +1,63 @@
package org.mobidgim.mobidigimproject.filter;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.util.ContentCachingRequestWrapper;
import org.springframework.web.util.ContentCachingResponseWrapper;
import java.io.IOException;
@Slf4j
public class LoggerFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
var req = new ContentCachingRequestWrapper((HttpServletRequest) request);
var res = new ContentCachingResponseWrapper((HttpServletResponse) response);
log.info("INIT URI: {}", req.getRequestURI());
chain.doFilter(req,res);
var headersNames = req.getHeaderNames();
var headersValues = new StringBuilder();
headersNames.asIterator().forEachRemaining(headerKey->{
var headerValue = req.getHeader(headerKey);
headersValues.append("[")
.append(headerKey)
.append(":")
.append(headerValue)
.append("]");
});
var requestBody = new String(req.getContentAsByteArray());
var uri = req.getRequestURI();
var method = req.getMethod();
log.info(">>>> uri: {}, method: {}, header: {}, body: {}",uri,method,headersValues,requestBody);
var responseHeadersValues = new StringBuilder();
res.getHeaderNames().forEach(headerKey ->{
var headerValue = req.getHeader(headerKey);
responseHeadersValues.append("[")
.append(headerKey)
.append(":")
.append(headerValue)
.append("]");
});
var responseBody = new String(res.getContentAsByteArray());
log.info("<<<< uri: {}, method: {}, header: {}, body: {}",uri,method,responseHeadersValues,responseBody);
res.copyBodyToResponse();
}
}

4
src/main/java/org/mobidgim/mobidigimproject/model/device/DeviceDTO.java

@ -1,6 +1,7 @@
package org.mobidgim.mobidigimproject.model.device;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonUnwrapped;
import lombok.Getter;
import lombok.Setter;
@ -32,5 +33,6 @@ public class DeviceDTO {
@JsonUnwrapped
private Imu imuConfig;
private List<WifiSSIDS> wifiSSID;
@JsonProperty("WIFI_SSID")
private List<WifiSSIDS> wifiSsid;
}

3
src/main/java/org/mobidgim/mobidigimproject/model/device/WifiSSIDS.java

@ -7,7 +7,8 @@ import org.mobidgim.mobidigimproject.model.device.enums.WiFiSecurity;
@Data
public class WifiSSIDS {
private String wifiSSID;
private String wifiSsid;
private String wifiPassword;
private WiFiSecurity wifiSecurity;
}

3
src/main/java/org/mobidgim/mobidigimproject/model/device/enums/ImuRemap.java

@ -7,7 +7,8 @@ import lombok.AllArgsConstructor;
@AllArgsConstructor
public enum ImuRemap {
X("x"),
Y("y");
Y("y"),
Z("z");
private final String remap;
@JsonValue

2
src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/CanBus.java

@ -9,5 +9,5 @@ import org.mobidgim.mobidigimproject.model.device.enums.CanBusType;
@Setter
public class CanBus {
private CanBusType canBusType;
private int baudrate;
private int canBudrate;
}

18
src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/Imu.java

@ -1,5 +1,6 @@
package org.mobidgim.mobidigimproject.model.device.subDTO;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
import org.mobidgim.mobidigimproject.model.device.enums.ImuRemap;
@ -8,10 +9,21 @@ import org.mobidgim.mobidigimproject.model.device.enums.ImuRemapSign;
@Getter
@Setter
public class Imu {
private ImuRemap imuRempaX;
private ImuRemap imuRempaY;
private ImuRemap imuRempaZ;
@JsonProperty("imu_remap_x")
private ImuRemap imuRemapX;
@JsonProperty("imu_remap_y")
private ImuRemap imuRemapY;
@JsonProperty("imu_remap_z")
private ImuRemap imuRemapZ;
@JsonProperty("imu_remap_x_sign")
private ImuRemapSign imuRemapXSign;
@JsonProperty("imu_remap_y_sign")
private ImuRemapSign imuRemapYSign;
@JsonProperty("imu_remap_z_sign")
private ImuRemapSign imuRemapZSign;
}

6
src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/Rs485.java

@ -8,8 +8,8 @@ import org.mobidgim.mobidigimproject.model.device.enums.Rs485Mode;
@Setter
public class Rs485 {
private Rs485Mode rs485Mode;
private int rs485baudrate;
private int rs485dataBits;
private String rs485parity;
private int rs485Baudrate;
private int rs485DataBits;
private String rs485Parity;
private int rs485StopBits;
}

8
src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/Wifi.java

@ -9,8 +9,8 @@ import org.mobidgim.mobidigimproject.model.device.enums.WifiStatic;
public class Wifi {
private WifiStatic wifiStatic;
private String wifiIp;
private String netmask;
private String gateway;
private String dns1;
private String dns2;
private String wifiNetmask;
private String wifiGateway;
private String wifiDns1;
private String wifiDns2;
}

4
src/main/java/org/mobidgim/mobidigimproject/model/register/RegisterDTO.java

@ -1,4 +0,0 @@
package org.mobidgim.mobidigimproject.model.register;
public class RegisterDTO {
}

23
src/main/java/org/mobidgim/mobidigimproject/service/SettingService.java

@ -3,8 +3,7 @@ package org.mobidgim.mobidigimproject.service;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import org.mobidgim.mobidigimproject.model.device.DeviceDTO;
import org.mobidgim.mobidigimproject.model.register.RegisterDTO;
import org.springframework.boot.context.config.ConfigData;
import org.springframework.stereotype.Service;
import java.io.IOException;
@ -14,23 +13,21 @@ import java.nio.file.Paths;
@Service
public class SettingService {
public DeviceDTO saveFileWithDevice(DeviceDTO request) throws IOException {
public void saveFileWithDevice(DeviceDTO request) throws IOException {
ObjectMapper mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(request);
String filename = "./temp/deviceConfig.json";
Files.writeString(Paths.get(filename), json);
return request;
}
public RegisterDTO saveFileWithRegister(RegisterDTO request) throws IOException {
ObjectMapper mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(request);
String filename = "./temp/registerConfig.json";
return request;
}
// public RegisterDTO saveFileWithRegister(RegisterDTO request) throws IOException {
// ObjectMapper mapper = new ObjectMapper();
// mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
// String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(request);
// String filename = "./temp/registerConfig.json";
//
// return request;
// }
}

410
src/main/resources/static/index.html

@ -0,0 +1,410 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Device Configuration UI</title>
<style>
*{margin:0;padding:0;box-sizing:border-box}
body{font-family:"Pretendard",sans-serif;min-height:100vh;display:flex;background:#fff;color:#111}
/* ───── Sidebar ───── */
.sidebar{width:260px;border-right:1px solid #ddd;padding:32px 24px;display:flex;flex-direction:column}
.sidebar h2{font-size:24px;margin-bottom:32px}
details.nav{margin-bottom:24px}
.nav>summary{list-style:none;cursor:pointer;display:flex;align-items:center;font-size:20px}
.nav>summary::before{content:"";width:8px;height:8px;margin-right:8px;
border-left:2px solid #111;border-bottom:2px solid #111;transform:rotate(-45deg);transition:.2s}
.nav[open]>summary::before{transform:rotate(45deg)}
.nav-items{display:flex;flex-direction:column;margin-top:10px;padding-left:16px;gap:6px}
.nav-items button{background:none;border:none;cursor:pointer;font-size:16px;text-align:left;padding:4px 0}
/* ───── Top-bar ───── */
.topbar{height:68px;background:#d9d9d9;display:flex;align-items:center;
padding:0 32px;font-size:28px;font-weight:500;box-shadow:0 2px 4px rgba(0,0,0,.15) inset}
/* ───── Main Board ───── */
.content{flex:1;display:flex;flex-direction:column}
.board{flex:1;overflow:auto;padding:40px;display:flex;flex-direction:column;gap:32px}
.card{background:#fff;border:1px solid #e5e5e5;box-shadow:0 2px 4px rgba(0,0,0,.15) inset;
padding:32px;border-radius:8px}
.card h3{font-size:24px;margin-bottom:24px}
/* SSID rows */
.ssid-row{display:grid;grid-template-columns:1fr 1fr 1fr 72px;gap:16px;margin-bottom:12px}
.ssid-row input,.ssid-row select{padding:6px 8px;font-size:16px;border:1px solid #aaa;border-radius:4px;width:100%}
.ssid-row button{padding:6px 10px;font-size:14px;background:#f1f1f1;border:1px solid #777;border-radius:4px;cursor:pointer}
/* 3-column grids (Network / Server) */
.grid-3-col{display:grid;grid-template-columns:180px 240px 120px;align-items:center;gap:16px}
.grid-3-col input{padding:6px 8px;font-size:16px;border:1px solid #aaa;border-radius:1px;width:100%}
/* radio */
.radio-group{display:flex;align-items:center;gap:24px}
.radio-label{display:inline-flex;align-items:center;gap:4px;cursor:pointer}
.radio-label input{margin:0}
/* I/O */
.io-top{display:grid;grid-template-columns:repeat(auto-fit,minmax(360px,1fr));gap:40px;margin-bottom:32px}
.io-bot{display:grid;grid-template-columns:repeat(auto-fit,minmax(360px,1fr));gap:40px}
.io-group h4{font-size:20px;font-weight:600;margin-bottom:16px;display:flex;align-items:center;gap:8px}
.io-group h4::before{content:"";width:8px;height:8px;background:#aaa;display:inline-block}
.io-fieldset{border:1px solid #bbb;padding:24px 32px;border-radius:4px;display:flex;flex-direction:column;gap:16px;width:100%}
.io-row{display:grid;grid-template-columns:120px 12px 1fr;align-items:center;gap:8px}
.io-row input,.io-row select{padding:4px 6px;border:1px solid #aaa;border-radius:4px;font-size:14px;width:100%}
/* 비활성 input 시각화 */
.disabled{background:#f5f5f5;cursor:not-allowed}
/* Footer Buttons */
.actions{display:flex;gap:24px;justify-content:center}
.actions button{min-width:140px;padding:10px 18px;font-size:16px;border:1px solid #bbb;background:#d9d9d9;border-radius:4px;cursor:pointer}
</style>
</head>
<body>
<!-- ───── Sidebar ───── -->
<aside class="sidebar">
<h2>Configuration</h2>
<details class="nav" open>
<summary>Device configuration</summary>
<div class="nav-items">
<button data-page="ssid">SSID</button>
<button data-page="network">Network &amp; Server</button>
<button data-page="io">I/O</button>
</div>
</details>
<details class="nav">
<summary>Register configuration</summary>
<div class="nav-items"><button data-page="reg">Config</button></div>
</details>
</aside>
<!-- ───── Content ───── -->
<div class="content">
<header class="topbar" id="page-title">SSID</header>
<main class="board">
<!-- ▽ SSID PAGE ▽ -->
<section id="page-ssid" class="page">
<div class="card">
<h3>SSID List</h3>
<template id="ssid-template">
<div class="ssid-row">
<input class="ssid-name" placeholder="Name" />
<input class="ssid-pw" type="password" placeholder="Password" />
<select>
<option value="none">NONE</option>
<option value="wpa/wpa2">WPA/WPA2</option>
</select>
<button type="button" class="toggle-pw">show</button>
</div>
</template>
<div id="ssid-list"></div>
<button id="add-ssid" style="margin-top:12px">Add SSID</button>
</div>
</section>
<!-- ▽ NETWORK PAGE ▽ -->
<section id="page-network" class="page" style="display:none">
<div class="card" style="margin-bottom:32px">
<h3>Network</h3>
<div class="grid-3-col" style="margin-bottom:16px">
<div class="radio-group">
<label class="radio-label"><input type="radio" name="ipMode" value="static"> Static</label>
<label class="radio-label"><input type="radio" name="ipMode" value="dhcp"> DHCP</label>
</div>
</div>
<div class="grid-3-col"><span>IP</span><input id="wifi_ip" placeholder="000.000.000.000" /></div>
<div class="grid-3-col"><span>SUBNET</span><input id="wifi_netmask" placeholder="255.255.255.0" /></div>
<div class="grid-3-col"><span>GATEWAY</span><input id="wifi_gateway" placeholder="000.000.000.001" /></div>
<div class="grid-3-col"><span>DNS #1</span><input id="wifi_dns1" placeholder="008.008.008.008" /></div>
<div class="grid-3-col"><span>DNS #2</span><input id="wifi_dns2" placeholder="008.008.004.004" /></div>
</div>
<div class="card">
<h3>Server</h3>
<div class="grid-3-col"><strong></strong><span style="text-align:center">IP</span><span style="text-align:center">Port</span></div>
<div class="grid-3-col"><span>TIoT Server</span> <input id="protocol_server_ip"/><input id="protocol_server_port"/></div>
<div class="grid-3-col"><span>Update Server</span><input id="update_server_ip" /><input id="update_server_port" /></div>
<div class="grid-3-col"><span>DGPS Server</span> <input id="rtcm_server_ip" /><input id="rtcm_server_port" /></div>
<div class="grid-3-col"><span>OPC-UA</span> <input id="opc_ua_server_ip" /><input id="opc_ua_server_port"/></div>
</div>
</section>
<!-- ▽ I/O PAGE ▽ -->
<section id="page-io" class="page" style="display:none">
<div class="card">
<div class="io-top">
<!-- Ethernet -->
<div class="io-group">
<h4>Ethernet</h4>
<div class="io-fieldset">
<div class="io-row"><span>IP</span><span>:</span><input id="eth_ip"></div>
<div class="io-row"><span>SUBNET</span><span>:</span><input id="eth_netmask"></div>
<div class="io-row"><span>GATEWAY</span><span>:</span><input id="eth_gateway"></div>
<div class="io-row"><span>SERVER IP</span><span>:</span><input id="protocol_server_ip"></div>
<div class="io-row"><span>SERVER PORT</span><span>:</span><input id="protocol_server_port"></div>
</div>
</div>
<!-- LTE -->
<div class="io-group">
<h4>LTE</h4>
<div class="io-fieldset">
<div class="io-row"><span>IP</span><span>:</span><input id="lte_ip"></div>
<div class="io-row"><span>SUBNET</span><span>:</span><input id="lte_netmask"></div>
<div class="io-row"><span>GATEWAY</span><span>:</span><input id="lte_gateway"></div>
<div class="io-row"><span>Port</span><span>:</span><input id="lte_port"></div>
</div>
</div>
</div>
<div class="io-bot">
<!-- RS-485 -->
<div class="io-group">
<h4>MODBUS 422 / 485</h4>
<div class="io-row"><span>Mode</span><span>:</span>
<select id="rs485_mode">
<option value="half">half</option>
<option value="full">full</option>
</select>
</div>
<div class="io-row"><span>Speed</span><span>:</span><input id="rs485_baudrate"></div>
<div class="io-row"><span>Parity</span><span>:</span><input id="rs485_parity"></div>
</div>
<!-- CAN -->
<div class="io-group">
<h4>CAN</h4>
<div class="io-row"><span>Type</span><span>:</span>
<select id="can_bus_type">
<option value="extended">extended</option>
<option value="standard">standard</option>
</select>
</div>
<div class="io-row"><span>Speed</span><span>:</span><input id="can_baudrate"></div>
</div>
<!-- IMU -->
<div class="io-group">
<h4>IMU Re-map</h4>
<div class="io-row"><span>X</span><span>:</span>
<select id="imu_remap_x">
<option value="x">x</option>
<option value="y">y</option>
<option value="z">z</option>
<option value="-x">-x</option>
<option value="-y">-y</option>
<option value="-z">-z</option>
</select>
</div>
<div class="io-row"><span>Y</span><span>:</span><select id="imu_remap_y">
<option value="x">x</option>
<option value="y">y</option>
<option value="z">z</option>
<option value="-x">-x</option>
<option value="-y">-y</option>
<option value="-z">-z</option>
</select></div>
<div class="io-row"><span>Z</span><span>:</span><select id="imu_remap_z">
<option value="x">x</option>
<option value="y">y</option>
<option value="z">z</option>
<option value="-x">-x</option>
<option value="-y">-y</option>
<option value="-z">-z</option>
</select></div>
</div>
</div>
</div>
</section>
<!-- ▽ Register PAGE (placeholder) ▽ -->
<section id="page-reg" class="page" style="display:none">
<div class="card"><h3>Register Config (준비중)</h3></div>
</section>
<!-- 공통 액션 버튼 -->
<div class="actions">
<button id="load-local">Load Local File</button>
<button id="save-local">Save Local File</button>
<button id="save-device">Save to Device</button>
</div>
</main>
</div>
<!-- ───── Script ───── -->
<script>
/* ───────────── 1. 기본 데이터 구조 ───────────── */
const data = {
/* Wi-Fi */
wifi_static : 'off', wifi_ip:'', wifi_netmask:'', wifi_gateway:'', wifi_dns1:'', wifi_dns2:'',
/* Ethernet */
eth_ip:'', eth_netmask:'', eth_gateway:'',
/* 서버들 */
protocol_server_ip:'', protocol_server_port:null,
update_server_ip :'',
update_server_port:null,
rtcm_server_ip :'',
rtcm_server_port :null,
opc_ua_server_ip :'',
opc_ua_server_port:null,
modbus_server_ip :'',
modbus_server_port:null,
/* CAN / RS-485 */
can_bus_type:'', can_baudrate:null,
rs485_mode:'', rs485_baudrate:null, rs485_databits:null,
rs485_parity:'', rs485_stopbits:null,
/* IMU (축 + 부호) */
imu_remap_x:'', imu_remap_y:'', imu_remap_z:'',
imu_remap_x_sign:'', imu_remap_y_sign:'', imu_remap_z_sign:'',
/* SSID 목록 */
WIFI_SSID:[{wifi_ssid:'',wifi_password:'',wifi_security:'none'}]
};
/* ───────────── 2. 페이지 전환 ───────────── */
const pages = {
ssid : document.getElementById('page-ssid'),
network: document.getElementById('page-network'),
io : document.getElementById('page-io'),
reg : document.getElementById('page-reg')
};
const titleEl = document.getElementById('page-title');
document.querySelectorAll('.nav-items button').forEach(btn=>{
btn.addEventListener('click',()=>{
Object.values(pages).forEach(p=>p.style.display='none');
pages[btn.dataset.page].style.display='block';
titleEl.textContent = btn.textContent;
});
});
/* ───────────── 3. SSID 행 생성 / 수집 ───────────── */
const ssidList = document.getElementById('ssid-list');
const ssidTmpl = document.getElementById('ssid-template');
function createSsidRow(obj={wifi_ssid:'',wifi_password:'',wifi_security:'none'}){
const node = ssidTmpl.content.firstElementChild.cloneNode(true);
node.querySelector('.ssid-name').value = obj.wifi_ssid ?? '';
node.querySelector('.ssid-pw' ).value = obj.wifi_password ?? '';
node.querySelector('select').value = (obj.wifi_security ?? 'none').toLowerCase();
return node;
}
function addSsidRow(){ ssidList.appendChild(createSsidRow()); }
document.getElementById('add-ssid').addEventListener('click', addSsidRow);
ssidList.addEventListener('click',e=>{
if(e.target.classList.contains('toggle-pw')){
const pw = e.target.closest('.ssid-row').querySelector('.ssid-pw');
pw.type = pw.type==='password' ? 'text' : 'password';
e.target.textContent = pw.type==='password' ? 'show' : 'hide';
}
});
function gatherSsidRows(){
const arr=[];
ssidList.querySelectorAll('.ssid-row').forEach(row=>{
const ssid = row.querySelector('.ssid-name').value.trim();
const pw = row.querySelector('.ssid-pw' ).value.trim();
const sec = row.querySelector('select' ).value;
if(ssid) arr.push({wifi_ssid:ssid, wifi_password:pw, wifi_security:sec});
});
return arr.length ? arr : [{wifi_ssid:'',wifi_password:'',wifi_security:'none'}];
}
/* ───────────── 4. DHCP ↔ Static 전환 입력 잠금 ───────────── */
const netFields = ['wifi_ip','wifi_netmask','wifi_gateway','wifi_dns1','wifi_dns2']
.map(id=>document.getElementById(id));
function toggleNetInputs(){
const isStatic = document.querySelector('input[name="ipMode"]:checked')?.value === 'static';
netFields.forEach(el=>{
el.disabled = !isStatic;
el.classList.toggle('disabled', !isStatic);
});
}
document.querySelectorAll('input[name="ipMode"]').forEach(r=>r.addEventListener('change', toggleNetInputs));
/* ───────────── 5. IMU Re-map 보조 함수 ───────────── */
function axisValueToPair(val){
return val.startsWith('-')
? {axis:val.slice(1), sign:'minus'}
: {axis:val, sign:'plus'};
}
function pairToAxisValue(axis, sign){
return sign==='minus' ? `-${axis}` : axis;
}
/* ───────────── 6. 데이터 → 화면 로딩 ───────────── */
function loadFromData(obj){
/* Wi-Fi 모드 radio */
document.querySelector(`input[name="ipMode"][value="${obj.wifi_static==='on'?'static':'dhcp'}"]`).checked = true;
/* 일반 input/select */
for(const k in obj){
const el = document.getElementById(k);
if(el) el.value = obj[k] ?? '';
}
/* IMU select 값 재구성 */
['x','y','z'].forEach(a=>{
const axis = obj[`imu_remap_${a}`] || 'x';
const sign = obj[`imu_remap_${a}_sign`] || 'plus';
document.getElementById(`imu_remap_${a}`).value = pairToAxisValue(axis, sign);
});
/* SSID */
ssidList.innerHTML='';
(obj.WIFI_SSID||[]).forEach(o=>ssidList.appendChild(createSsidRow(o)));
if(!ssidList.children.length) addSsidRow();
toggleNetInputs(); // 초기 잠금 상태
}
loadFromData(data);
/* ───────────── 7. 화면 → 데이터 수집 ───────────── */
function collectData(){
const res = {...data};
res.wifi_static = document.querySelector('input[name="ipMode"]:checked')?.value === 'static'
? 'on' : 'off';
/* 일반 input/select */
for(const k in res){
const el = document.getElementById(k);
if(el) res[k] = el.value.trim();
}
/* IMU select → 축·부호 분리 */
['x','y','z'].forEach(a=>{
const {axis, sign} = axisValueToPair(document.getElementById(`imu_remap_${a}`).value);
res[`imu_remap_${a}`] = axis;
res[`imu_remap_${a}_sign`] = sign;
});
/* SSID 배열 */
res.WIFI_SSID = gatherSsidRows();
return res;
}
/* ───────────── 8. 저장 버튼 POST ───────────── */
document.getElementById('save-device').addEventListener('click', ()=>{
fetch('http://localhost:8080/setting/device',{
method :'POST',
headers:{'Content-Type':'application/json'},
body : JSON.stringify(collectData())
})
.then(()=>alert('전송 완료'))
.catch(console.error);
});
</script>
</body>
</html>
Loading…
Cancel
Save