From 598dc3a4f88ed8e9a8ffc7111265e28a8b7134e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9B=90=ED=98=95?= <147372294+blissyou@users.noreply.github.com> Date: Tue, 1 Jul 2025 17:12:21 +0900 Subject: [PATCH] =?UTF-8?q?=ED=94=84=EB=A1=A0=ED=8A=B8=20=EB=B2=84?= =?UTF-8?q?=ED=8A=BC=20ux=20=EA=B5=AC=ED=98=84,=20=EB=B2=84=EA=B7=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/Controller.java | 8 ++ .../model/device/subDTO/CanBus.java | 2 + .../model/device/subDTO/Ethernet.java | 2 + .../model/device/subDTO/Imu.java | 2 + .../model/device/subDTO/Lte.java | 7 ++ .../model/device/subDTO/Rs485.java | 6 +- .../model/device/subDTO/Server.java | 12 ++- .../model/device/subDTO/Wifi.java | 2 + .../model/device/{ => subDTO}/WifiSSIDS.java | 6 +- .../service/SettingService.java | 14 +-- src/main/resources/static/index.html | 93 ++++++++++--------- src/main/resources/static/style.css | 86 +++++++++++++++-- 12 files changed, 168 insertions(+), 72 deletions(-) rename src/main/java/org/mobidgim/mobidigimproject/model/device/{ => subDTO}/WifiSSIDS.java (69%) diff --git a/src/main/java/org/mobidgim/mobidigimproject/controller/Controller.java b/src/main/java/org/mobidgim/mobidigimproject/controller/Controller.java index 69f75b7..0e3e642 100644 --- a/src/main/java/org/mobidgim/mobidigimproject/controller/Controller.java +++ b/src/main/java/org/mobidgim/mobidigimproject/controller/Controller.java @@ -12,6 +12,14 @@ import java.io.IOException; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.core.io.Resource; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + @RestController @RequestMapping("/setting") diff --git a/src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/CanBus.java b/src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/CanBus.java index 2208384..0da8eec 100644 --- a/src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/CanBus.java +++ b/src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/CanBus.java @@ -1,6 +1,7 @@ package org.mobidgim.mobidigimproject.model.device.subDTO; +import com.fasterxml.jackson.annotation.JsonInclude; import lombok.Getter; import lombok.Setter; import org.mobidgim.mobidigimproject.model.device.enums.CanBusType; @@ -8,6 +9,7 @@ import org.mobidgim.mobidigimproject.model.device.enums.CanSpeed; @Getter @Setter +@JsonInclude(JsonInclude.Include.NON_NULL) public class CanBus { private CanBusType canBusType; private CanSpeed canBaudrate; diff --git a/src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/Ethernet.java b/src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/Ethernet.java index 0000e09..cc74fe6 100644 --- a/src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/Ethernet.java +++ b/src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/Ethernet.java @@ -1,10 +1,12 @@ package org.mobidgim.mobidigimproject.model.device.subDTO; +import com.fasterxml.jackson.annotation.JsonInclude; import lombok.Getter; import lombok.Setter; @Getter @Setter +@JsonInclude(JsonInclude.Include.NON_NULL) public class Ethernet { private String ethIp; private String ethNetmask; diff --git a/src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/Imu.java b/src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/Imu.java index ce42060..8f7a630 100644 --- a/src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/Imu.java +++ b/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.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; import lombok.Setter; @@ -8,6 +9,7 @@ import org.mobidgim.mobidigimproject.model.device.enums.ImuRemapSign; @Getter @Setter +@JsonInclude(JsonInclude.Include.NON_NULL) public class Imu { @JsonProperty("imu_remap_x") private ImuRemap imuRemapX; diff --git a/src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/Lte.java b/src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/Lte.java index 001821e..8d0a0e9 100644 --- a/src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/Lte.java +++ b/src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/Lte.java @@ -1,7 +1,14 @@ package org.mobidgim.mobidigimproject.model.device.subDTO; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@JsonInclude(JsonInclude.Include.NON_NULL) public class Lte { @JsonProperty("lte_ip") private String LTEip; diff --git a/src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/Rs485.java b/src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/Rs485.java index e356dda..d730030 100644 --- a/src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/Rs485.java +++ b/src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/Rs485.java @@ -1,5 +1,6 @@ package org.mobidgim.mobidigimproject.model.device.subDTO; +import com.fasterxml.jackson.annotation.JsonInclude; import lombok.Getter; import lombok.Setter; import org.mobidgim.mobidigimproject.model.device.enums.Rs485Parity; @@ -8,15 +9,16 @@ import org.mobidgim.mobidigimproject.model.device.enums.Rs485Mode; @Getter @Setter +@JsonInclude(JsonInclude.Include.NON_NULL) public class Rs485 { private Rs485Mode rs485Mode; private Rs485Baudrate rs485Baudrate; - private int rs485DataBits; + private Integer rs485DataBits; private Rs485Parity rs485Parity; - private int rs485StopBits; + private Integer rs485StopBits; } diff --git a/src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/Server.java b/src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/Server.java index f1d97e3..3ea4c74 100644 --- a/src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/Server.java +++ b/src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/Server.java @@ -1,18 +1,20 @@ package org.mobidgim.mobidigimproject.model.device.subDTO; +import com.fasterxml.jackson.annotation.JsonInclude; import lombok.*; @Getter @Setter +@JsonInclude(JsonInclude.Include.NON_NULL) public class Server { private String protocolServerIp; - private int protocolServerPort; + private Integer protocolServerPort; private String updateServerIp; - private int updateServerPort; + private Integer updateServerPort; private String rtcmServerIp; - private int rtcmServerPort; + private Integer rtcmServerPort; private String opcUaServerIp; - private int opcUaServerPort; + private Integer opcUaServerPort; private String modbusServerIp; - private int modbusServerPort; + private Integer modbusServerPort; } diff --git a/src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/Wifi.java b/src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/Wifi.java index 93f9dc9..be61b11 100644 --- a/src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/Wifi.java +++ b/src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/Wifi.java @@ -1,11 +1,13 @@ package org.mobidgim.mobidigimproject.model.device.subDTO; +import com.fasterxml.jackson.annotation.JsonInclude; import lombok.Getter; import lombok.Setter; import org.mobidgim.mobidigimproject.model.device.enums.WifiStatic; @Getter @Setter +@JsonInclude(JsonInclude.Include.NON_NULL) public class Wifi { private WifiStatic wifiStatic; private String wifiIp; diff --git a/src/main/java/org/mobidgim/mobidigimproject/model/device/WifiSSIDS.java b/src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/WifiSSIDS.java similarity index 69% rename from src/main/java/org/mobidgim/mobidigimproject/model/device/WifiSSIDS.java rename to src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/WifiSSIDS.java index 3485fd7..5e81ce0 100644 --- a/src/main/java/org/mobidgim/mobidigimproject/model/device/WifiSSIDS.java +++ b/src/main/java/org/mobidgim/mobidigimproject/model/device/subDTO/WifiSSIDS.java @@ -1,13 +1,13 @@ -package org.mobidgim.mobidigimproject.model.device; +package org.mobidgim.mobidigimproject.model.device.subDTO; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonValue; import lombok.Data; import org.mobidgim.mobidigimproject.model.device.enums.WiFiSecurity; - @Data +@JsonInclude(JsonInclude.Include.NON_NULL) public class WifiSSIDS { diff --git a/src/main/java/org/mobidgim/mobidigimproject/service/SettingService.java b/src/main/java/org/mobidgim/mobidigimproject/service/SettingService.java index b064f2d..796f090 100644 --- a/src/main/java/org/mobidgim/mobidigimproject/service/SettingService.java +++ b/src/main/java/org/mobidgim/mobidigimproject/service/SettingService.java @@ -1,6 +1,7 @@ package org.mobidgim.mobidigimproject.service; -import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.annotation.JsonInclude; + import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.PropertyNamingStrategies; @@ -8,22 +9,14 @@ import org.mobidgim.mobidigimproject.model.device.DeviceDTO; import org.mobidgim.mobidigimproject.model.register.RegisterDTO; import org.mobidgim.mobidigimproject.model.register.enums.CanInput; import org.mobidgim.mobidigimproject.model.register.enums.Protocol; -import org.mobidgim.mobidigimproject.model.register.sebDTO.CanField; -import org.mobidgim.mobidigimproject.model.register.sebDTO.ModbusField; -import org.mobidgim.mobidigimproject.model.register.sebDTO.OpcUaField; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import javax.swing.text.html.parser.Parser; import java.io.File; import java.io.IOException; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; import java.nio.file.Path; -import java.util.Arrays; -import java.util.List; -import java.util.Map; @Service public class SettingService { @@ -37,9 +30,9 @@ public class SettingService { } - public void saveFileWithDevice(DeviceDTO request) throws IOException { mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(request); String directoryPath = "./temp"; @@ -49,7 +42,6 @@ public class SettingService { Files.createDirectory(dirPath); } - String filename = "./temp/deviceConfig.json"; Files.writeString(Paths.get(filename), json); } diff --git a/src/main/resources/static/index.html b/src/main/resources/static/index.html index ec059f9..852aa48 100644 --- a/src/main/resources/static/index.html +++ b/src/main/resources/static/index.html @@ -54,8 +54,7 @@
- - +
- +
@@ -93,15 +92,15 @@

Server

IPPort
-
TIoT Server TIoT Server
-
Update ServerUpdate Server
-
DGPS Server DGPS Server
-
OPC-UA OPC-UA
-
MODBUS MODBUS
@@ -113,7 +112,7 @@
- + @@ -140,12 +139,12 @@
IP:
+
PORT:
NETMASK:
GATEWAY:
-
PORT:
@@ -245,7 +244,7 @@ - + @@ -394,7 +393,7 @@ - + @@ -482,7 +481,7 @@ - + @@ -563,7 +562,7 @@ - + @@ -653,7 +652,7 @@ const ssidTmpl = document.getElementById('ssid-template'); const data = { /* Wi-Fi */ - wifi_static: 'off', wifi_ip: '', wifi_netmask: '', wifi_gateway: '', wifi_dns1: '', wifi_dns2: '', + wifi_static: '', wifi_ip: '', wifi_netmask: '', wifi_gateway: '', wifi_dns1: '', wifi_dns2: '', /* Ethernet */ eth_ip: '', eth_netmask: '', eth_gateway: '', @@ -1257,18 +1256,6 @@ //ssid 행 추가 버튼 document.getElementById('add-ssid').addEventListener('click', addSsidRow); - //ssid 행 삭제 버튼 - document.getElementById('delete-ssid').addEventListener('click', () => { - if (ssidList.children.length > 1) { - ssidList.removeChild(ssidList.lastElementChild); - } else if (ssidList.children.length === 1) { - const firstRow = ssidList.firstElementChild; - firstRow.querySelector('.ssid-name').value = ''; - firstRow.querySelector('.ssid-pw').value = ''; - firstRow.querySelector('select').value = 'none'; - } - }) - /*-----device input데이터 받는 함수------*/ function collectDeviceData() { const res = { ...data }; @@ -1276,12 +1263,10 @@ 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) { const val = el.value.trim(); - // can_baudrate, rs485_baudrate는 숫자 or null if (['can_baudrate', 'rs485_baudrate'].includes(k)) { res[k] = val === '' ? null : Number(val); } else { @@ -1289,18 +1274,27 @@ } } } - - // IMU select → 축·부호 분리 + //x,y,z,부호 처리 ['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; + //null, 공백 없이 데이터 전처리 + const filtered = {}; + for (const [k, v] of Object.entries(res)) { + if ( + v !== null && + !(typeof v === 'string' && v.trim() === '') + ) { + filtered[k] = v; + } + } + + return filtered; } /*-----------------------------------------------------*/ @@ -1429,7 +1423,7 @@ /*-----------------------------------------------------*/ /*-----Device에 설정 데이터를 deviceConfig.json 파일로 변경하여 유저가 다운로드 할수 있게 하는 함수-----*/ - function downloadDeviceJson(obj, filename = 'deviceConfig.json') { + function downloadDeviceJson(obj, filename='deviceConfig.json') { const json = JSON.stringify(obj, null, 2); // 보기 좋게 들여쓰기 2칸 const blob = new Blob([json], {type: 'application/json'}); const url = URL.createObjectURL(blob); @@ -1445,7 +1439,7 @@ /*-----------------------------------------------------*/ /*-----protocol에 설정 데이터를 protocolConfig.json 파일로 변경하여 유저가 다운로드 할수 있게 하는 함수-----*/ - function downloadProtocolJson(obj, filename = 'protocolConfig.json') { + function downloadProtocolJson(obj, filename='protocolConfig.json') { const json = JSON.stringify(obj, null, 2); // 보기 좋게 들여쓰기 2칸 const blob = new Blob([json], {type: 'application/json'}); const url = URL.createObjectURL(blob); @@ -1495,15 +1489,26 @@ 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(); + + const deleteBtn = document.createElement('button'); + deleteBtn.textContent = '➖'; + deleteBtn.dataset.action = 'delete-ssid'; + deleteBtn.title = 'delete ssid'; + deleteBtn.classList.add('delete-ssid'); + + node.appendChild(deleteBtn); + return node; } /*-----------------------------------------------------*/ - /*-------ssid 데이터 리스트 추가 함수-----------*/ + /*-------ssid password 숨김 함수-----------*/ function addSsidRow() { ssidList.appendChild(createSsidRow()); } - + function removeSsidRow(row) { + row.remove(); + } ssidList.addEventListener('click', e => { if (e.target.classList.contains('toggle-pw')) { const pw = e.target.closest('.ssid-row').querySelector('.ssid-pw'); @@ -1525,9 +1530,10 @@ const ssid = row.querySelector('.ssid-name').value.trim(); const pw = row.querySelector('.ssid-pw').value.trim(); const sec = row.querySelector('select').value; + if (ssid === '' && pw === '') return; if (ssid) arr.push({wifi_ssid: ssid, wifi_password: pw, wifi_security: sec}); }); - return arr.length ? arr : [{wifi_ssid: '', wifi_password: '', wifi_security: 'none'}]; + return arr } /*-----------------------------------------------------*/ @@ -1717,9 +1723,10 @@ /*-------imu-remap 정수와 부호 분리 함수-------------*/ function axisValueToPair(val) { + if (!val || val === '') return { axis: '', sign: '' }; return val.startsWith('-') - ? {axis: val.slice(1), sign: 'minus'} - : {axis: val, sign: 'plus'}; + ? { axis: val.slice(1), sign: 'minus' } + : { axis: val, sign: 'plus' }; } function pairToAxisValue(axis, sign) { @@ -1740,8 +1747,8 @@ /* IMU select 값 재구성 */ ['x', 'y', 'z'].forEach(a => { - const axis = obj[`imu_remap_${a}`] || 'x'; - const sign = obj[`imu_remap_${a}_sign`] || 'plus'; + const axis = obj[`imu_remap_${a}`] || ''; + const sign = obj[`imu_remap_${a}_sign`] || ''; document.getElementById(`imu_remap_${a}`).value = pairToAxisValue(axis, sign); }); diff --git a/src/main/resources/static/style.css b/src/main/resources/static/style.css index 1bfc913..b92ac57 100644 --- a/src/main/resources/static/style.css +++ b/src/main/resources/static/style.css @@ -91,18 +91,62 @@ details.nav { /* SSID rows */ .ssid-row { - display: grid; - grid-template-columns:220px 220px 60px 120px; - gap: 16px; - margin-bottom: 12px + display: flex; + align-items: center; + gap: 8px; + margin-bottom: 8px; +} + +.ssid-row input.ssid-name, +.ssid-row input.ssid-pw { + width: 200px; + padding: 6px 8px; + font-size: 16px; + border: 1px solid #aaa; + border-radius: 4px; } -.ssid-row input, .ssid-row select { +.ssid-row .toggle-pw { + padding: 6px 10px; + font-size: 14px; + border: 1px solid #aaa; + background-color: #eee; + border-radius: 4px; + cursor: pointer; + min-width: 60px; + text-align: center; +} +.ssid-row .toggle-pw:hover { + background-color: #cecece; +} +.ssid-row .toggle-pw:active { + background-color: #bdbdbd; + transform: scale(0.97); +} + +.ssid-row select { + width: 100px; padding: 6px 8px; font-size: 16px; border: 1px solid #aaa; border-radius: 4px; - width: 100% +} + +.ssid-row .delete-ssid { + padding: 6px 10px; + font-size: 14px; + background-color: #ffdddd; + border: 1px solid #aaa; + border-radius: 4px; + cursor: pointer; +} + +.ssid-row .delete-ssid:hover { + background-color: #ffaaaa; +} +.ssid-row .delete-ssid:active{ + background-color: #fd9e9e; + transform: scale(0.97); } .icon-button { @@ -123,8 +167,25 @@ details.nav { background-color: #c0c0c0; } /* 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%} +.grid-3-col { + display: grid; + grid-template-columns: 180px 220px 100px; /* SSID와 유사하게 축소 */ + align-items: center; + gap: 12px; + margin: 8px 0; +} + +.grid-3-col input { + padding: 6px 8px; + font-size: 16px; + border: 1px solid #aaa; + border-radius: 4px; /* 기존 1px → 4px 통일 */ + width: 100%; /* grid item 내에서만 퍼지므로 유지 가능 */ +} + +.grid-3-col input::placeholder { + color: #999; +} /* radio */ .radio-group {display: flex;align-items: center;gap: 24px} @@ -158,6 +219,8 @@ details.nav { /* Footer Buttons */ .actions {display: flex;gap: 24px;justify-content: center;padding: 20px} .actions button {min-width: 140px;padding: 10px 18px;font-size: 16px;border: 1px solid #bbb;background: #d9d9d9;border-radius: 4px;cursor: pointer} +.actions button:hover {background-color: #bdbdbd;} +.actions button:active {background-color: #bdbdbd; transform: scale(0.97);} .config-actions{display: flex;gap: 24px;justify-content: center;background: #f7f7f7;border: 1px solid #bbb;border-radius: 4px;margin: 24px 0 0 0;padding: 20px 0;} .config-actions button{min-width:140px;padding:10px 18px;font-size:16px;border:1px solid #bbb;background:#d9d9d9;border-radius:4px;cursor:pointer} .topbar { @@ -181,6 +244,13 @@ details.nav { border-radius: 4px; cursor: pointer; } +.save-file:hover { + background-color: #45a049;; +} +.save-file:active { + background-color: #3e8e41; + transform: scale(0.97); +} /* MODBUS 화면 심플 스타일 */ #page-modbus .card {background: #f7f7f7;border: 1px solid #bbb;box-shadow: none;padding: 24px;border-radius: 4px;display: flex;flex-direction: column;} #page-modbus table {width: 100%;border-collapse: collapse;background: #fff;border: 1px solid #bbb;}