Browse Source

feat: wpa3 개발

v2
최원형 1 month ago
parent
commit
55f70b8ea3
  1. 22
      src/main/java/org/mobidgim/mobidigimproject/MobidigimProjectApplication.java
  2. 24
      src/main/java/org/mobidgim/mobidigimproject/config/DatabaseInitializer.java
  3. 15
      src/main/java/org/mobidgim/mobidigimproject/model/device/enums/WiFiSecurity.java
  4. 4
      src/main/resources/static/css/style.css
  5. 7
      src/main/resources/static/index.html
  6. 7
      src/main/resources/static/js/device/deviceData.js
  7. 29
      src/main/resources/static/js/device/ssid.js
  8. 64
      src/main/resources/static/js/main.js

22
src/main/java/org/mobidgim/mobidigimproject/MobidigimProjectApplication.java

@ -2,13 +2,6 @@ package org.mobidgim.mobidigimproject;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@SpringBootApplication
// (exclude = {
// DataSourceAutoConfiguration.class,
@ -18,21 +11,6 @@ import java.nio.file.Paths;
public class MobidigimProjectApplication {
public static void main(String[] args) {
ensureDbDirectory();
SpringApplication.run(MobidigimProjectApplication.class, args);
}
private static void ensureDbDirectory() {
try {
Path dbDir = Paths.get(System.getProperty("user.home"), "db");
Files.createDirectories(dbDir);
Path dbFile = dbDir.resolve("dynamic_data.db");
if (Files.notExists(dbFile)) {
Files.createFile(dbFile);
}
} catch (Exception e) {
throw new IllegalStateException("Failed to prepare SQLite DB file", e);
}
}
}

24
src/main/java/org/mobidgim/mobidigimproject/config/DatabaseInitializer.java

@ -1,24 +0,0 @@
package org.mobidgim.mobidigimproject.config;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
public class DatabaseInitializer implements ApplicationRunner {
private final JdbcTemplate jdbcTemplate;
@Override
public void run(ApplicationArguments args) {
jdbcTemplate.execute(
"CREATE TABLE IF NOT EXISTS board_config (" +
"\"key\" TEXT PRIMARY KEY, " +
"\"value\" TEXT NOT NULL" +
")"
);
}
}

15
src/main/java/org/mobidgim/mobidigimproject/model/device/enums/WiFiSecurity.java

@ -1,14 +1,27 @@
package org.mobidgim.mobidigimproject.model.device.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.AllArgsConstructor;
@AllArgsConstructor
public enum WiFiSecurity {
NONE("none"),
WPA_WPA2("wpa/wpa2");
WPA_WPA2("wpa/wpa2"),
WPA3("wpa3");
private final String value;
@JsonCreator
public static WiFiSecurity fromValue(String value) {
for (WiFiSecurity security : values()) {
if (security.value.equalsIgnoreCase(String.valueOf(value).trim())) {
return security;
}
}
throw new IllegalArgumentException("Invalid wifiSecurity value: " + value);
}
@JsonValue
public String getValue() {
return value;

4
src/main/resources/static/css/style.css

@ -210,7 +210,9 @@ details.nav {
}
.ssid-row select {
width: 100px;
width: 140px;
min-width: 140px;
flex: 0 0 140px;
padding: 6px 8px;
font-size: 16px;
border: 1px solid #aaa;

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

@ -75,6 +75,7 @@
<select>
<option value="none">NONE</option>
<option value="wpa/wpa2">WPA/WPA2</option>
<option value="wpa3">WPA3</option>
</select>
</div>
</template>
@ -170,7 +171,7 @@
<div class="io-fieldset">
<div class="io-row"><span class="label-inline">Mode</span><span class="colon">:</span>
<select id="rs485_mode">
<option value="">NONE</option>
<option value="" selected disabled hidden></option>
<option value="half">half</option>
<option value="full">full</option>
</select>
@ -199,7 +200,7 @@
<div class="io-fieldset">
<div class="io-row"><span class="label-inline">Can Type</span><span class="colon">:</span>
<select id="can_bus_type">
<option value="">NONE</option>
<option value="" selected disabled hidden></option>
<option value="extended">extended</option>
<option value="standard">standard</option>
</select>
@ -207,7 +208,7 @@
<div class="io-row"><span class="label-inline">Can Speed</span><span class="colon">:</span>
<select id="can_baudrate">
<option value="">NONE</option>
<option value="">AUTO</option>
<option value="100">100kb/s</option>
<option value="250">250kb/s</option>
<option value="500">500kb/s</option>

7
src/main/resources/static/js/device/deviceData.js

@ -48,6 +48,10 @@ export function createDeviceDataController({ ssidController }) {
toggleNetInputs();
}
function loadDefaults() {
loadFromData(cloneDeviceDefaults());
}
function collectDeviceData() {
const result = cloneDeviceDefaults();
@ -87,12 +91,13 @@ export function createDeviceDataController({ ssidController }) {
function initialize() {
bindEvents();
loadFromData();
toggleNetInputs();
}
return {
collectDeviceData,
initialize,
loadDefaults,
loadFromData,
toggleNetInputs,
};

29
src/main/resources/static/js/device/ssid.js

@ -1,12 +1,32 @@
import { cloneTemplateRow } from '../utils/dom.js';
export function createSsidController({ listElement, templateElement, addButton, countryCodeInput }) {
function syncPasswordState(row) {
const passwordInput = row.querySelector('.ssid-pw');
const toggleButton = row.querySelector('.toggle-pw');
const securitySelect = row.querySelector('select');
const isNoneSecurity = (securitySelect?.value ?? 'none').toLowerCase() === 'none';
passwordInput.disabled = isNoneSecurity;
if (isNoneSecurity) {
passwordInput.value = '';
passwordInput.type = 'password';
}
if (toggleButton) {
toggleButton.disabled = isNoneSecurity;
toggleButton.textContent = 'show';
}
}
function createRow(values = { wifi_ssid: '', wifi_passwd: '', wifi_security: 'none' }) {
const row = cloneTemplateRow(templateElement);
row.querySelector('.ssid-name').value = values.wifi_ssid ?? '';
row.querySelector('.ssid-pw').value = values.wifi_passwd ?? '';
row.querySelector('select').value = (values.wifi_security ?? 'none').toLowerCase();
syncPasswordState(row);
const deleteButton = document.createElement('button');
deleteButton.type = 'button';
@ -61,6 +81,9 @@ export function createSsidController({ listElement, templateElement, addButton,
listElement.addEventListener('click', (event) => {
if (event.target.classList.contains('toggle-pw')) {
const passwordInput = event.target.closest('.ssid-row').querySelector('.ssid-pw');
if (passwordInput.disabled) {
return;
}
passwordInput.type = passwordInput.type === 'password' ? 'text' : 'password';
event.target.textContent = passwordInput.type === 'password' ? 'show' : 'hide';
return;
@ -71,6 +94,12 @@ export function createSsidController({ listElement, templateElement, addButton,
}
});
listElement.addEventListener('change', (event) => {
if (event.target.matches('.ssid-row select')) {
syncPasswordState(event.target.closest('.ssid-row'));
}
});
countryCodeInput?.addEventListener('input', () => {
countryCodeInput.value = countryCodeInput.value
.replace(/[^a-zA-Z]/g, '')

64
src/main/resources/static/js/main.js

@ -11,6 +11,56 @@ import { createProtocolDataController } from './protocol/protocolData.js';
import { getRegisterConfigValidationError, isValidRegisterConfig } from './protocol/protocolValidation.js';
import { byId, queryAll } from './utils/dom.js';
function notifyLoadFailure(target, error) {
const statusMatch = /Request failed: (\d+)/.exec(String(error?.message ?? ''));
const statusText = statusMatch ? ` (HTTP ${statusMatch[1]})` : '';
const message = `${target} settings could not be loaded${statusText}. Please check the saved data on the backend.`;
console.error(message, error);
alert(message);
}
function isLegacySuccessMessage(data) {
return String(data?.message ?? '').trim().toLowerCase() === 'success';
}
function isLegacyProtocolPayload(data) {
if (!data || typeof data !== 'object' || Array.isArray(data)) {
return false;
}
return [
'protocol',
'dev_type',
'can_input',
'dr_on',
'odo_on',
'MEID',
'MODBUS',
'OPC_UA',
'CAN',
].some((key) => Object.prototype.hasOwnProperty.call(data, key));
}
function isSaveSuccessful(type, response) {
if (!response.ok) {
return false;
}
if (response.data?.success === true) {
return true;
}
if (type === 'device' && isLegacySuccessMessage(response.data)) {
return true;
}
if (type === 'protocol' && isLegacyProtocolPayload(response.data)) {
return true;
}
return false;
}
async function initializeApp() {
const navigation = createNavigation();
const ssidController = createSsidController({
@ -49,7 +99,9 @@ async function initializeApp() {
protocolController.loadFromRegisterJson(data);
},
getDownloadData: () => protocolController.collectProtocolData(),
getDownloadData: () => protocolController.normalizeRegisterForPost(
protocolController.collectProtocolData(),
),
});
queryAll('.save-file').forEach((button) => {
@ -71,8 +123,8 @@ async function initializeApp() {
saveProtocolConfig(protocolPayload),
]);
const isDeviceSaved = deviceResponse.ok && deviceResponse.data?.success === true;
const isProtocolSaved = protocolResponse.ok && protocolResponse.data?.success === true;
const isDeviceSaved = isSaveSuccessful('device', deviceResponse);
const isProtocolSaved = isSaveSuccessful('protocol', protocolResponse);
if (isDeviceSaved && isProtocolSaved) {
alert('saved successfully');
@ -97,9 +149,11 @@ async function initializeApp() {
const deviceData = await loadDeviceConfig();
if (deviceData) {
deviceController.loadFromData(deviceData);
} else {
deviceController.loadDefaults();
}
} catch (error) {
console.error('Device load failed:', error);
notifyLoadFailure('Device', error);
}
try {
@ -108,7 +162,7 @@ async function initializeApp() {
protocolController.loadFromRegisterJson(protocolData);
}
} catch (error) {
console.error('Protocol load failed:', error);
notifyLoadFailure('Protocol', error);
}
}

Loading…
Cancel
Save