Skip to content

Commit

Permalink
update: full implementation of device info section
Browse files Browse the repository at this point in the history
  • Loading branch information
luftaquila committed Aug 2, 2024
1 parent 132c716 commit 8810d56
Show file tree
Hide file tree
Showing 6 changed files with 322 additions and 70 deletions.
129 changes: 95 additions & 34 deletions web/index.html
Original file line number Diff line number Diff line change
@@ -1,37 +1,98 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<meta property="og:title" content="FSK-EEM Console"/>
<meta property="og:url" content="https://fsk-eem.luftaquila.io"/>
<meta property="og:description" content="FSK-EEM Console"/>

<title>FSK-EEM Console</title>

<link rel="apple-touch-icon" sizes="180x180" href="/assets/favicon/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/assets/favicon/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/assets/favicon/favicon-16x16.png">

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css" integrity="sha512-Kc323vGBEqzTmouAECnVceyQqyqdsSiqLQISBL29aUW4U/M7pSPA/gEUZQqv1cwx4OnYxTxve5UMg5GT6L4JJg==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/sweetalert2/11.12.4/sweetalert2.min.css" integrity="sha512-WxRv0maH8aN6vNOcgNFlimjOhKp+CUqqNougXbz0E+D24gP5i+7W/gcc5tenxVmr28rH85XHF5eXehpV2TQhRg==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.css" integrity="sha512-3pIirOrwegjM6erE5gPSwkUzO+3cTjpnV9lexlNZqvupR64iZBnOOTiiLPb9M36zpMScbmUNIcHUqKD47M719g==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<link rel="stylesheet" href="btn.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<button id="connect">connect</button>
<button id="load-list">load-list</button>
<button id="load-all">load-all</button>

<script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js" integrity="sha512-Qlv6VSKh1gDKGoJbnyA5RMXYcvnpIqhO++MhIM2fStMcGT9i2T//tSwYFlcyoRRDcDZ+TYHpH8azBBCyhpSeqw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/sweetalert2/11.12.4/sweetalert2.all.min.js" integrity="sha512-aRyxRCMzAorfKGjEjnSeGTVKrI/2irvvR5DI38LV/JXOkL9VLnZ+rfFkD9i1UTWTB8e8W5vpf7SjDsfMOdNosg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js" integrity="sha512-VEd+nq25CkR676O+pLBnDW09R7VQX9Mdiij052gVCp5yVH3jGtH70Ho/UUv4mJDsEdTvqRCFZg0NKGiojGnUCw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

<script src="strings.js"></script>
<script src="ui.js"></script>
<script src="protocol.js"></script>
<script src="script.js"></script>
</body>

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<meta property="og:title" content="FSK-EEM Console" />
<meta property="og:url" content="https://fsk-eem.luftaquila.io" />
<meta property="og:description" content="FSK-EEM Console" />

<title>FSK-EEM Console</title>

<link rel="apple-touch-icon" sizes="180x180" href="/assets/favicon/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/assets/favicon/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/assets/favicon/favicon-16x16.png">

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css"
integrity="sha512-Kc323vGBEqzTmouAECnVceyQqyqdsSiqLQISBL29aUW4U/M7pSPA/gEUZQqv1cwx4OnYxTxve5UMg5GT6L4JJg=="
crossorigin="anonymous" referrerpolicy="no-referrer" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/sweetalert2/11.12.4/sweetalert2.min.css"
integrity="sha512-WxRv0maH8aN6vNOcgNFlimjOhKp+CUqqNougXbz0E+D24gP5i+7W/gcc5tenxVmr28rH85XHF5eXehpV2TQhRg=="
crossorigin="anonymous" referrerpolicy="no-referrer" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.css"
integrity="sha512-3pIirOrwegjM6erE5gPSwkUzO+3cTjpnV9lexlNZqvupR64iZBnOOTiiLPb9M36zpMScbmUNIcHUqKD47M719g=="
crossorigin="anonymous" referrerpolicy="no-referrer" />
<link rel="stylesheet" href="btn.css">
<link rel="stylesheet" href="style.css">
</head>

<body>
<div id='container'>
<article>
<h1><i class="fa-fw fa-solid fa-cash-register"></i>에너지미터 관리</h1>
<div class="content">
<div>
<h2><i class="fa-fw fa-solid fa-circle-info"></i>장치 정보</h2>
<div class="section">
<div>
<span id="connect" class='btn blue'><i class="fa-fw fa-brands fa-usb"></i>장치 연결</span>
<span id="set-id" class='btn orange'><i class="fa-fw fa-solid fa-car-side"></i>ID 설정</span>
<span id="set-rtc" class='btn orange'><i class="fa-fw fa-regular fa-clock"></i>시계 동기화</span>
</div>
<div style="margin-top: 1rem;">
<span class="device-info">
<i id="connection" class="fa-fw fa-solid fa-circle" style="color: red;"></i>
ID: <span id="device-id">N/A</span>
</span>
<span class="device-info">
<i class="fa-fw fa-solid fa-sd-card"></i>
<span id="storage-free">- GB</span> / <span id="storage-total">- GB</span>
&ensp;(<span id="storage-percent">-</span> %)
</span>
<span class="device-info">
<i class="fa-fw fa-solid fa-clock"></i>
<span id="device-clock">N/A</span>
</span>
</div>
</div>
</div>
<div style="margin-top: 1rem;">
</div>
<div style="margin-top: 1rem;">
<h2><i class="fa-fw fa-solid fa-file-waveform"></i>로그 파일 관리</h2>
<div class="section">
<div>
<span id="load-list" class='btn green'><i class="fa-fw fa-solid fa-arrows-rotate"></i>새로고침</span>
<span id="load-all" class='btn green'><i class="fa-fw fa-solid fa-file-arrow-down"></i>전체 다운로드</span>
<span id="delete-all" class='btn red'><i class="fa-fw fa-regular fa-trash-can"></i>전체 삭제</span>
</div>
<div>
<table id="file-list">
</table>
</div>
</div>
</div>
</div>
</article>
</div>

<script src="https://code.jquery.com/jquery-3.7.1.min.js"
integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js"
integrity="sha512-Qlv6VSKh1gDKGoJbnyA5RMXYcvnpIqhO++MhIM2fStMcGT9i2T//tSwYFlcyoRRDcDZ+TYHpH8azBBCyhpSeqw=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/sweetalert2/11.12.4/sweetalert2.all.min.js"
integrity="sha512-aRyxRCMzAorfKGjEjnSeGTVKrI/2irvvR5DI38LV/JXOkL9VLnZ+rfFkD9i1UTWTB8e8W5vpf7SjDsfMOdNosg=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js"
integrity="sha512-VEd+nq25CkR676O+pLBnDW09R7VQX9Mdiij052gVCp5yVH3jGtH70Ho/UUv4mJDsEdTvqRCFZg0NKGiojGnUCw=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>

<script src="strings.js"></script>
<script src="ui.js"></script>
<script src="protocol.js"></script>
<script src="script.js"></script>
</body>

</html>
9 changes: 7 additions & 2 deletions web/protocol.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ const RESP = {
const USB_VID = 0x1999;
const USB_PID = 0x0512;

const DEVICE_ID_INVALID = 0xFFFF;
const DEVICE_ID_BROADCAST = 0xFFFE;

const QUERY_TIMEOUT = 500;

/******************************************************************************
Expand All @@ -35,12 +38,12 @@ const QUERY_TIMEOUT = 500;
* QUERY: 5-byte decimal integer string(00000 ~ 65535) for a new device id
* RESPONSE: $OK or $ERROR
*****************************************************************************/
async function cmd_set_id(new_id) {
async function cmd_set_id(id) {
if (!await check_connection()) {
return false;
}

let query = `${CMD.SET_ID} ${String(new_id).padStart(5, '0')}`
let query = `${CMD.SET_ID} ${String(id).padStart(5, '0')}`
let res = await transceive(query, RESP.OK);

if (!res) {
Expand Down Expand Up @@ -120,6 +123,8 @@ async function cmd_load_list() {

toastr.success('파일 목록 수신 완료');
ui_load_list(res);

await cmd_load_info();
}

/******************************************************************************
Expand Down
82 changes: 50 additions & 32 deletions web/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,43 @@ document.addEventListener("DOMContentLoaded", (_e) => {
return;
}

document.getElementById("connect").addEventListener("click", connect);
document.getElementById("connect").addEventListener("click", check_connection);
document.getElementById("set-id").addEventListener("click", ui_cmd_set_id);
document.getElementById("set-rtc").addEventListener("click", cmd_set_rtc);
document.getElementById("load-list").addEventListener("click", cmd_load_list);
});

/************************************************************************************
* format bytes to human readable text
***********************************************************************************/
function format_byte(bytes, decimals = 2) {
if (!+bytes) {
return '0 Byte';
}

const k = 1000;
const dm = decimals < 0 ? 0 : decimals;
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];

const i = Math.floor(Math.log(bytes) / Math.log(k));

return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
}

/************************************************************************************
* new Date().format()
***********************************************************************************/
var dateFormat = function () {
var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g,
var dateFormat = function() {
var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g,
timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,
timezoneClip = /[^-+\dA-Z]/g,
pad = function (val, len) {
pad = function(val, len) {
val = String(val);
len = len || 2;
while (val.length < len) val = '0' + val;
return val;
};
return function (date, mask, utc) {
return function(date, mask, utc) {
var dF = dateFormat;
if (arguments.length == 1 && Object.prototype.toString.call(date) == '[object String]' && !/\d/.test(date)) {
mask = date;
Expand All @@ -38,7 +56,7 @@ var dateFormat = function () {
mask = mask.slice(4);
utc = true;
}
var _ = utc ? 'getUTC' : 'get',
var _ = utc ? 'getUTC' : 'get',
d = date[_ + 'Date'](),
D = date[_ + 'Day'](),
m = date[_ + 'Month'](),
Expand All @@ -49,40 +67,40 @@ var dateFormat = function () {
L = date[_ + 'Milliseconds'](),
o = utc ? 0 : date.getTimezoneOffset(),
flags = {
d: d,
dd: pad(d),
ddd: dF.i18n.dayNames[D],
d: d,
dd: pad(d),
ddd: dF.i18n.dayNames[D],
dddd: dF.i18n.dayNames[D + 7],
m: m + 1,
mm: pad(m + 1),
mmm: dF.i18n.monthNames[m],
m: m + 1,
mm: pad(m + 1),
mmm: dF.i18n.monthNames[m],
mmmm: dF.i18n.monthNames[m + 12],
yy: String(y).slice(2),
yy: String(y).slice(2),
yyyy: y,
h: H % 12 || 12,
hh: pad(H % 12 || 12),
H: H,
HH: pad(H),
M: M,
MM: pad(M),
s: s,
ss: pad(s),
l: pad(L, 3),
L: pad(L > 99 ? Math.round(L / 10) : L),
t: H < 12 ? 'a' : 'p',
tt: H < 12 ? 'am' : 'pm',
T: H < 12 ? 'A' : 'P',
TT: H < 12 ? '오전' : '오후',
Z: utc ? 'UTC' : (String(date).match(timezone) || ['']).pop().replace(timezoneClip, ''),
o: (o > 0 ? '-' : '+') + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4),
S: ['th', 'st', 'nd', 'rd'][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10]
h: H % 12 || 12,
hh: pad(H % 12 || 12),
H: H,
HH: pad(H),
M: M,
MM: pad(M),
s: s,
ss: pad(s),
l: pad(L, 3),
L: pad(L > 99 ? Math.round(L / 10) : L),
t: H < 12 ? 'a' : 'p',
tt: H < 12 ? 'am' : 'pm',
T: H < 12 ? 'A' : 'P',
TT: H < 12 ? '오전' : '오후',
Z: utc ? 'UTC' : (String(date).match(timezone) || ['']).pop().replace(timezoneClip, ''),
o: (o > 0 ? '-' : '+') + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4),
S: ['th', 'st', 'nd', 'rd'][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10]
};
return mask.replace(token, function ($0) {
return mask.replace(token, function($0) {
return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1);
});
};
}();
dateFormat.masks = {'default':'ddd mmm dd yyyy HH:MM:ss'};
dateFormat.masks = { 'default': 'ddd mmm dd yyyy HH:MM:ss' };
dateFormat.i18n = {
dayNames: [
'일', '월', '화', '수', '목', '금', '토',
Expand Down
1 change: 1 addition & 0 deletions web/strings.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const html_strings = {
no_webserial: 'WebSerial을 지원하지 않는 브라우저입니다.<br>크롬 등 다른 최신 브라우저를 사용하세요.',
id_error: 'ID 값이 올바르지 않습니다.<br>ID는 0 ~ 65533 이내의 정수입니다.',
};
94 changes: 94 additions & 0 deletions web/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
@import url("https://statics.goorm.io/fonts/GoormSans/v1.0.0/GoormSans.min.css");

html {
font-family: 'Goorm Sans', sans-serif;
background-color: rgb(243, 244, 246);
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}

body {
overflow-y: auto;
}

i.fa-fw {
margin-right: 0.5rem;
}

div#container, div#header {
padding: 1rem;
padding-top: 0rem;
display: flex;
max-width: none;
flex-wrap: wrap;
}

div#container {
justify-content: space-evenly;
}

article {
margin-top: 1.5rem;
padding: 1rem;
background-color: white;
border-radius: 10px;
min-width: 320px;
width: -webkit-fill-available;
}

article h1 {
font-size: 1.5rem;
margin: 0px;
color: rgb(59,130,246);
}

article h2 {
font-size: 1.3rem;
margin: 0px;
color: #333333;
}

article .content {
padding-top: 1.5rem;
padding-left: 1rem;
line-height: 2rem;
}

article .content .section {
margin-top: 0.5rem;
margin-left: 1rem;
margin-bottom: 2rem;
}

.disabled {
opacity: 30%;
pointer-events: none;
}

input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}

input[type=number] {
appearance: textfield;
-moz-appearance: textfield;
}

.btn {
padding: 4px 12px 2px 12px;
}

.connected {
color: green;
}

span.device-info {
margin-left: 0.5rem;
margin-right: 2rem;
}
Loading

0 comments on commit 8810d56

Please sign in to comment.