|
|
@ -771,8 +771,6 @@ |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
const selectedDeviceFile = event.target.files[0]; |
|
|
const selectedDeviceFile = event.target.files[0]; |
|
|
const DeviceFileName = selectedDeviceFile.name; |
|
|
|
|
|
|
|
|
|
|
|
const reader = new FileReader(); |
|
|
const reader = new FileReader(); |
|
|
|
|
|
|
|
|
reader.onload = async (e) => { |
|
|
reader.onload = async (e) => { |
|
|
@ -780,50 +778,10 @@ |
|
|
const DeviceFileContent = e.target.result; |
|
|
const DeviceFileContent = e.target.result; |
|
|
const jsonData = JSON.parse(DeviceFileContent); |
|
|
const jsonData = JSON.parse(DeviceFileContent); |
|
|
|
|
|
|
|
|
// 백엔드 저장 API 호출 (data-upload-url 사용) |
|
|
loadFromData(jsonData); |
|
|
const response = await fetch(uploadDeviceUrl, { |
|
|
console.log(`Loaded ${DeviceFileType} data from local file`, jsonData); |
|
|
method: 'POST', |
|
|
|
|
|
headers: { |
|
|
|
|
|
'Content-Type': 'application/json' |
|
|
|
|
|
}, |
|
|
|
|
|
body: JSON.stringify(jsonData) |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
if (!response.ok) { |
|
|
|
|
|
const errorText = await response.text(); |
|
|
|
|
|
throw new Error(`File upload failed: ${response.status} ${response.statusText} - ${errorText}`); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const result = await response.json(); |
|
|
uploadDeviceFileInput.value = ''; |
|
|
|
|
|
|
|
|
if (result.result && result.result.result_code === 200) { |
|
|
|
|
|
alert(`File uploaded to Device successfully (${DeviceFileType})`); |
|
|
|
|
|
console.log(`Upload successful for ${DeviceFileType}:`, result); |
|
|
|
|
|
|
|
|
|
|
|
// 업로드 성공 후 최신 데이터를 Device에서 다시 불러와 UI 업데이트 (data-get-url 사용) |
|
|
|
|
|
// loadFromRegisterJson은 Register 데이터만 처리하는 함수이므로, |
|
|
|
|
|
// 만약 Modbus/OPCUA/CAN 데이터 로드 함수가 별도로 있다면 여기서 조건부 호출 필요 |
|
|
|
|
|
fetch(getDeviceUrl) |
|
|
|
|
|
.then(res => res.json()) |
|
|
|
|
|
.then(apiResponseData => { |
|
|
|
|
|
if (apiResponseData && apiResponseData.body) { |
|
|
|
|
|
// 여기도 fileType에 따라 다른 load 함수를 호출해야 할 수 있습니다. |
|
|
|
|
|
// 현재는 모든 파일이 Register 설정이라고 가정하여 loadFromRegisterJson 호출 |
|
|
|
|
|
loadFromData(apiResponseData.body); |
|
|
|
|
|
console.log(`UI updated with newly uploaded ${DeviceFileType} data.`); |
|
|
|
|
|
} else { |
|
|
|
|
|
console.warn(`Failed to reload ${DeviceFileType} data after upload: no response body`); |
|
|
|
|
|
} |
|
|
|
|
|
}) |
|
|
|
|
|
.catch(err => console.error(`Error reloading ${DeviceFileType} data after upload:`, err)); |
|
|
|
|
|
|
|
|
|
|
|
uploadDeviceFileInput.value = ''; // input 초기화 (다음 업로드 위함) |
|
|
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
alert(`File upload failed: ${result.result ? result.result.result_message : 'Unknown error'} (${DeviceFileType})`); |
|
|
|
|
|
console.error(`Upload failed for ${DeviceFileType} with backend error:`, result); |
|
|
|
|
|
uploadDeviceFileInput.value = ''; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} catch (error) { |
|
|
} catch (error) { |
|
|
console.error(`Error uploading file (${DeviceFileType}):`, error); |
|
|
console.error(`Error uploading file (${DeviceFileType}):`, error); |
|
|
@ -852,7 +810,6 @@ |
|
|
const selectFileBtn = wrapper.querySelector('.select-file-btn-protocol'); |
|
|
const selectFileBtn = wrapper.querySelector('.select-file-btn-protocol'); |
|
|
|
|
|
|
|
|
// 해당 래퍼의 data 속성들을 가져옵니다. |
|
|
// 해당 래퍼의 data 속성들을 가져옵니다. |
|
|
const expectedFileName = wrapper.dataset.expectedFilename; |
|
|
|
|
|
const uploadUrl = wrapper.dataset.uploadUrl; |
|
|
const uploadUrl = wrapper.dataset.uploadUrl; |
|
|
const getUrl = wrapper.dataset.getUrl; |
|
|
const getUrl = wrapper.dataset.getUrl; |
|
|
const fileType = wrapper.dataset.fileType; // 'protocol', 'modbus', 'opcua', 'can' |
|
|
const fileType = wrapper.dataset.fileType; // 'protocol', 'modbus', 'opcua', 'can' |
|
|
@ -872,7 +829,6 @@ |
|
|
// 파일 선택 시 (change 이벤트 발생) 바로 업로드 로직 시작 |
|
|
// 파일 선택 시 (change 이벤트 발생) 바로 업로드 로직 시작 |
|
|
uploadFileInput.addEventListener('change', async (event) => { |
|
|
uploadFileInput.addEventListener('change', async (event) => { |
|
|
const selectedFile = event.target.files[0]; |
|
|
const selectedFile = event.target.files[0]; |
|
|
const fileName = selectedFile.name; |
|
|
|
|
|
const reader = new FileReader(); |
|
|
const reader = new FileReader(); |
|
|
|
|
|
|
|
|
if (event.target.files.length === 0) { |
|
|
if (event.target.files.length === 0) { |
|
|
@ -884,54 +840,14 @@ |
|
|
const fileContent = e.target.result; |
|
|
const fileContent = e.target.result; |
|
|
const jsonData = JSON.parse(fileContent); |
|
|
const jsonData = JSON.parse(fileContent); |
|
|
|
|
|
|
|
|
// 백엔드 저장 API 호출 (data-upload-url 사용) |
|
|
|
|
|
const response = await fetch(uploadUrl, { |
|
|
|
|
|
method: 'POST', |
|
|
|
|
|
headers: { |
|
|
|
|
|
'Content-Type': 'application/json' |
|
|
|
|
|
}, |
|
|
|
|
|
body: JSON.stringify(jsonData) |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
const result = await response.json(); |
|
|
|
|
|
// 업로드 유효성 검사 로직 |
|
|
// 업로드 유효성 검사 로직 |
|
|
if (!isValidRegisterConfig(jsonData)){ // 예를 들어, isValidModbusConfig(jsonData) 등 |
|
|
if (!isValidRegisterConfig(jsonData)){ // 예를 들어, isValidModbusConfig(jsonData) 등 |
|
|
alert(`The contents of the selected file are not in a valid ${fileType} setting file format.`); |
|
|
alert(`The contents of the selected file are not in a valid ${fileType} setting file format.`); |
|
|
uploadFileInput.value = ''; |
|
|
uploadFileInput.value = ''; |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
loadFromRegisterJson(jsonData,fileType); |
|
|
if (!response.ok) { |
|
|
console.log(`Loaded ${fileType} data from local file (not saved).`, jsonData); |
|
|
const errorText = await response.text(); |
|
|
|
|
|
throw new Error(`File upload failed: ${response.status} ${response.statusText} - ${errorText}`); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (result.result && result.result.result_code === 200) { |
|
|
|
|
|
alert(`File uploaded to Device successfully (${fileType})`); |
|
|
|
|
|
console.log(`Upload successful for ${fileType}:`, result); |
|
|
|
|
|
|
|
|
|
|
|
// 업로드 성공 후 최신 데이터를 Device에서 다시 불러와 UI 업데이트 (data-get-url 사용) |
|
|
|
|
|
fetch(getUrl) |
|
|
|
|
|
.then(res => res.json()) |
|
|
|
|
|
.then(apiResponseData => { |
|
|
|
|
|
if (apiResponseData && apiResponseData.body) { |
|
|
|
|
|
// 여기도 fileType에 따라 다른 load 함수를 호출해야 할 수 있습니다. |
|
|
|
|
|
// 현재는 모든 파일이 Register 설정이라고 가정하여 loadFromRegisterJson 호출 |
|
|
|
|
|
loadFromRegisterJson(apiResponseData.body); |
|
|
|
|
|
console.log(`UI updated with newly uploaded ${fileType} data.`); |
|
|
|
|
|
} else { |
|
|
|
|
|
console.warn(`Failed to reload ${fileType} data after upload: no response body`); |
|
|
|
|
|
} |
|
|
|
|
|
}) |
|
|
|
|
|
.catch(err => console.error(`업로드 후 ${fileType} 데이터 재로드 중 오류 발생:`, err)); |
|
|
|
|
|
|
|
|
|
|
|
uploadFileInput.value = ''; // input 초기화 (다음 업로드 위함) |
|
|
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
alert(`File upload failed: ${result.result?result.result_message: 'unknown error'} (${fileType})`); |
|
|
|
|
|
console.error(`Upload failed for ${fileType} with backend error:`, result); |
|
|
|
|
|
uploadFileInput.value = ''; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} catch (error) { |
|
|
} catch (error) { |
|
|
alert(`Error uploading file: ${error.message} (${fileType})`); |
|
|
alert(`Error uploading file: ${error.message} (${fileType})`); |
|
|
@ -1457,65 +1373,6 @@ |
|
|
URL.revokeObjectURL(url); |
|
|
URL.revokeObjectURL(url); |
|
|
} |
|
|
} |
|
|
/*-----------------------------------------------------*/ |
|
|
/*-----------------------------------------------------*/ |
|
|
// localStorage 자동 저장 (Device) |
|
|
|
|
|
function autoSaveToLocal() { |
|
|
|
|
|
const data = collectDeviceData(); |
|
|
|
|
|
localStorage.setItem('deviceConfigAutoSave', JSON.stringify(data)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// localStorage 자동 저장 (Protocol) |
|
|
|
|
|
function autoSaveProtocolToLocal() { |
|
|
|
|
|
const config = collectProtocolData(); |
|
|
|
|
|
localStorage.setItem('protocolConfigAutoSave', JSON.stringify(config)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// localStorage에서 불러오기 |
|
|
|
|
|
function loadFromLocalIfExists() { |
|
|
|
|
|
const saved = localStorage.getItem('deviceConfigAutoSave'); |
|
|
|
|
|
if (saved) { |
|
|
|
|
|
try { |
|
|
|
|
|
loadFromData(JSON.parse(saved)); |
|
|
|
|
|
console.log('localStorage에서 자동 저장된 Device 설정을 불러왔습니다.'); |
|
|
|
|
|
return true; |
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
console.warn('localStorage Device 설정 파싱 실패:', e); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// localStorage에서 불러오기 (Protocol) |
|
|
|
|
|
function loadProtocolFromLocalIfExists() { |
|
|
|
|
|
const saved = localStorage.getItem('protocolConfigAutoSave'); |
|
|
|
|
|
if (saved) { |
|
|
|
|
|
try { |
|
|
|
|
|
loadFromRegisterJson(JSON.parse(saved)); |
|
|
|
|
|
console.log('localStorage에서 자동 저장된 Protocol 설정을 불러왔습니다.'); |
|
|
|
|
|
return true; |
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
console.warn('localStorage Protocol 설정 파싱 실패:', e); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// input, select 등 값이 바뀔 때마다 자동 저장 (Device) |
|
|
|
|
|
function bindAutoSaveEvents() { |
|
|
|
|
|
document.querySelectorAll('input, select').forEach(el => { |
|
|
|
|
|
el.addEventListener('change', autoSaveToLocal); |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// input, select 등 값이 바뀔 때마다 자동 저장 (Protocol) |
|
|
|
|
|
function bindAutoSaveProtocolEvents() { |
|
|
|
|
|
// reg, modbus, opcua, can 페이지 내의 input/select만 |
|
|
|
|
|
const protocolSections = ['#page-reg', '#page-modbus', '#page-opcua', '#page-can']; |
|
|
|
|
|
protocolSections.forEach(section => { |
|
|
|
|
|
document.querySelectorAll(section + ' input, ' + section + ' select').forEach(el => { |
|
|
|
|
|
el.addEventListener('change', autoSaveProtocolToLocal); |
|
|
|
|
|
}); |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/*-----protocol에 설정 데이터를 protocolConfig.json 파일로 변경하여 유저가 다운로드 할수 있게 하는 함수-----*/ |
|
|
/*-----protocol에 설정 데이터를 protocolConfig.json 파일로 변경하여 유저가 다운로드 할수 있게 하는 함수-----*/ |
|
|
function downloadProtocolJson(obj, filename='protocolConfig.json') { |
|
|
function downloadProtocolJson(obj, filename='protocolConfig.json') { |
|
|
@ -1535,85 +1392,40 @@ |
|
|
|
|
|
|
|
|
/*-------페이지 로드시 서버에 있는 데이터를 불러오는 함수---------*/ |
|
|
/*-------페이지 로드시 서버에 있는 데이터를 불러오는 함수---------*/ |
|
|
async function loadInitialData() { |
|
|
async function loadInitialData() { |
|
|
// 1. localStorage 우선 적용 (Device) |
|
|
// 서버에서 파일 목록 조회 및 로드 (Device) |
|
|
let deviceLoadedFromLocal = loadFromLocalIfExists(); |
|
|
try { |
|
|
// 2. 서버에서 파일 목록 조회 및 로드 (Device) |
|
|
const deviceResponse = await fetch('http://localhost:8080/setting/get-device'); |
|
|
if (!deviceLoadedFromLocal) { |
|
|
if (deviceResponse.ok) { |
|
|
try { |
|
|
const deviceData = await deviceResponse.json(); |
|
|
// 사용 가능한 Device 파일 목록 조회 |
|
|
if (deviceData && deviceData.body) { |
|
|
const deviceFilesResponse = await fetch('http://localhost:8080/setting/device-files'); |
|
|
loadFromData(deviceData.body); |
|
|
if (deviceFilesResponse.ok) { |
|
|
console.log('Device Load completed (Default file: deviceConfig.json)'); |
|
|
const deviceFilesData = await deviceFilesResponse.json(); |
|
|
} else { |
|
|
if (deviceFilesData && deviceFilesData.body && deviceFilesData.body.length > 0) { |
|
|
console.warn('Device response received, but no body found.'); |
|
|
// 첫 번째 유효한 Device 파일 로드 |
|
|
|
|
|
const firstDeviceFile = deviceFilesData.body[0]; |
|
|
|
|
|
console.log(`Device 파일 발견: ${firstDeviceFile}`); |
|
|
|
|
|
|
|
|
|
|
|
const deviceResponse = await fetch(`http://localhost:8080/setting/get-device/${firstDeviceFile}`); |
|
|
|
|
|
if (deviceResponse.ok) { |
|
|
|
|
|
const deviceData = await deviceResponse.json(); |
|
|
|
|
|
if (deviceData && deviceData.body) { |
|
|
|
|
|
loadFromData(deviceData.body); |
|
|
|
|
|
console.log(`Device 설정 자동 로드 완료: ${firstDeviceFile}`); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
// 기본 파일명으로 시도 |
|
|
|
|
|
const deviceResponse = await fetch('http://localhost:8080/setting/get-device'); |
|
|
|
|
|
if (deviceResponse.ok) { |
|
|
|
|
|
const deviceData = await deviceResponse.json(); |
|
|
|
|
|
if (deviceData && deviceData.body) { |
|
|
|
|
|
loadFromData(deviceData.body); |
|
|
|
|
|
console.log('Device 설정 자동 로드 완료 (기본 파일)'); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
} catch (error) { |
|
|
} else { |
|
|
console.log('Device 설정 파일이 없거나 로드 실패, 기본값 사용:', error.message); |
|
|
console.warn(`Device load failed: HTTP ${deviceResponse.status}`); |
|
|
} |
|
|
} |
|
|
|
|
|
} catch (error) { |
|
|
|
|
|
console.error('Device load failed:', error.message); |
|
|
} |
|
|
} |
|
|
bindAutoSaveEvents(); |
|
|
|
|
|
|
|
|
try { |
|
|
// 1. localStorage 우선 적용 (Protocol) |
|
|
const protocolResponse = await fetch('http://localhost:8080/setting/get-protocol'); |
|
|
let protocolLoadedFromLocal = loadProtocolFromLocalIfExists(); |
|
|
if (protocolResponse.ok) { |
|
|
// 2. 서버에서 파일 목록 조회 및 로드 (Protocol) |
|
|
const protocolData = await protocolResponse.json(); |
|
|
if (!protocolLoadedFromLocal) { |
|
|
if (protocolData && protocolData.body) { |
|
|
try { |
|
|
loadFromRegisterJson(protocolData.body); |
|
|
// 사용 가능한 Protocol 파일 목록 조회 |
|
|
console.log('Protocol Load completed (Default file: protocolConfig.json)'); |
|
|
const protocolFilesResponse = await fetch('http://localhost:8080/setting/protocol-files'); |
|
|
} else { |
|
|
if (protocolFilesResponse.ok) { |
|
|
console.warn('Protocol response received, but no body found.'); |
|
|
const protocolFilesData = await protocolFilesResponse.json(); |
|
|
|
|
|
if (protocolFilesData && protocolFilesData.body && protocolFilesData.body.length > 0) { |
|
|
|
|
|
// 첫 번째 유효한 Protocol 파일 로드 |
|
|
|
|
|
const firstProtocolFile = protocolFilesData.body[0]; |
|
|
|
|
|
console.log(`Protocol 파일 발견: ${firstProtocolFile}`); |
|
|
|
|
|
|
|
|
|
|
|
const protocolResponse = await fetch(`http://localhost:8080/setting/get-protocol/${firstProtocolFile}`); |
|
|
|
|
|
if (protocolResponse.ok) { |
|
|
|
|
|
const protocolData = await protocolResponse.json(); |
|
|
|
|
|
if (protocolData && protocolData.body) { |
|
|
|
|
|
loadFromRegisterJson(protocolData.body); |
|
|
|
|
|
console.log(`Protocol 설정 자동 로드 완료: ${firstProtocolFile}`); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
// 기본 파일명으로 시도 |
|
|
|
|
|
const protocolResponse = await fetch('http://localhost:8080/setting/get-protocol'); |
|
|
|
|
|
if (protocolResponse.ok) { |
|
|
|
|
|
const protocolData = await protocolResponse.json(); |
|
|
|
|
|
if (protocolData && protocolData.body) { |
|
|
|
|
|
loadFromRegisterJson(protocolData.body); |
|
|
|
|
|
console.log('Protocol 설정 자동 로드 완료 (기본 파일)'); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
} catch (error) { |
|
|
} else { |
|
|
console.log('Protocol 설정 파일이 없거나 로드 실패, 기본값 사용:', error.message); |
|
|
console.warn(`Protocol load failed: HTTP ${protocolResponse.status}`); |
|
|
} |
|
|
} |
|
|
|
|
|
} catch (error) { |
|
|
|
|
|
console.error('Protocol load failed:', error.message); |
|
|
} |
|
|
} |
|
|
bindAutoSaveProtocolEvents(); |
|
|
|
|
|
} |
|
|
} |
|
|
/*-----------------------------------------------------*/ |
|
|
/*-----------------------------------------------------*/ |
|
|
|
|
|
|
|
|
|