Spaces:
Sleeping
Sleeping
| /** | |
| * Copyright (c) 2017~2023, OBCon Inc. | |
| * All rights reserved. | |
| */ | |
| /** | |
| * @file | |
| * @copyright 2017~2023, OBCon Inc. | |
| * @author gye hyun james kim [pnuskgh@gmail.com] | |
| */ | |
| const fs = require('fs'); | |
| const path = require('path'); | |
| const crypto = require('crypto'); | |
| const moment = require('moment'); //--- format : YYYYMMDDHHmmss.SSS ZZ - 20191220172919.083 +0900 | |
| const UtilityPrev = require('./UtilityPrev.js'); | |
| class Utility { | |
| constructor() { | |
| this.initialize(); | |
| } | |
| get module() { | |
| return new UtilityPrev(); | |
| } | |
| get type() { | |
| return { | |
| //--- typeof : string (String), bigint (BigInt), number (Number), boolean (Boolean), object (Null), symbol (Symbol), function, undefined (Undefined) | |
| //--- string, number, bigint, boolean, function, undefined, symbol | |
| //--- object : null, object, array | |
| typeof: (param) => Object.prototype.toString.call(param).replace(/\[object /g, '').replace(/\]/g, '').toLowerCase(), | |
| isNull: (param) => ((typeof(param) === 'undefined') || (param == null)), | |
| isNone: (param) => typeof(param) === 'undefined', | |
| isString: (param) => typeof(param) == 'string', | |
| isNumber: (param) => typeof(param) == 'number', | |
| isArray: (param) => this.type.typeof(param) == 'array', | |
| Null: this.type_Null | |
| }; | |
| } | |
| type_Null(value) { | |
| return ((typeof(value) === 'undefined') || (value == null)) ? '':value; | |
| } | |
| get link() { | |
| return { | |
| join: this.link_join, | |
| fullUrl: (url) => this.link.join(config.http.baseUrl, url) | |
| } | |
| } | |
| link_join(...paths) { | |
| if (paths.length == 0) { | |
| return ''; | |
| } | |
| const links = [ paths[0] ]; | |
| let pathPrev = paths[0]; | |
| for (let idx = 1;idx < paths.length;idx++) { | |
| if ((paths[idx] != '') && (paths[idx] != null) && (typeof(paths[idx]) == 'string')) { | |
| if ((pathPrev.endsWith('/')) && (paths[idx].startsWith('/'))) { | |
| pathPrev = paths[idx].substring(1); | |
| links.push(pathPrev); | |
| } else if ((pathPrev.endsWith('/') == false) && (paths[idx].startsWith('/') == false)) { | |
| pathPrev = paths[idx]; | |
| links.push('/' + pathPrev); | |
| } else { | |
| pathPrev = paths[idx]; | |
| links.push(pathPrev); | |
| } | |
| } | |
| } | |
| return links.join(''); | |
| } | |
| async _sleep(miliseconds) { | |
| const promise = new Promise(function(resolve, reject) { | |
| setTimeout(function() { | |
| resolve(); | |
| }, miliseconds); | |
| }); | |
| await promise; | |
| } | |
| async _wait(funcCondition, miliseconds) { | |
| const times = Math.ceil(miliseconds / 100); //--- ceil. 올림, floor. 버림 | |
| for (let idx = 0; idx < times; idx++) { | |
| await this._sleep(100); | |
| if (funcCondition()) { | |
| break; | |
| } | |
| } | |
| } | |
| async fetchFile(url, filename) { | |
| try { | |
| const file = path.join(appl.root, 'files', filename); | |
| const folder = path.dirname(file); | |
| if (fs.existsSync(folder) == false) { | |
| fs.mkdirSync(folder); | |
| } | |
| if (fs.existsSync(file)) { | |
| fs.unlinkSync(file); | |
| } | |
| const response = await fetch(url); | |
| const streamPipeline = promisify(pipeline); //--- Callback 함수를 Promise 함수로 변환 한다. | |
| await streamPipeline(response.body, createWriteStream(file)); | |
| return true; | |
| } catch (err) { | |
| utils.obj.loggerError(err); | |
| return false; | |
| } | |
| } | |
| async unzip(filename) { | |
| try { | |
| const file = path.join(appl.root, 'files', filename); | |
| const folder = path.join(appl.root, 'files', filename.replace(/\.zip$/, '')); | |
| if (fs.existsSync(folder)) { | |
| fs.rmSync(folder, { recursive: true, force: true }); | |
| } | |
| fs.mkdirSync(folder); | |
| await decompress(file, folder); | |
| return true; | |
| } catch (err) { | |
| utils.obj.loggerError(err); | |
| return false; | |
| } | |
| } | |
| get string() { | |
| return { | |
| charLen: this._charLen, | |
| substring_byte: this._substring_byte | |
| }; | |
| } | |
| _charLen(str, idx) { | |
| return (128 < str.charCodeAt(idx) ? 2:1); | |
| } | |
| _substring_byte(str, start, end) { | |
| const size = end - start; | |
| let idxByte = 0; | |
| let idxFr = 0; | |
| let idxTo = 0; | |
| for (let idx = 0; idx < str.length; idx++) { | |
| if (idxByte <= start) { | |
| idxFr = idx; | |
| } | |
| if (idxByte <= end) { | |
| idxTo = idx; | |
| } | |
| idxByte = idxByte + ((128 < str.charCodeAt(idx)) ? 2 : 1); | |
| } | |
| // for (let idx = 0; idxTo < end; idx++) { | |
| // idxTo = idxTo + ((128 < str.charCodeAt(idx)) ? 2 : 1); | |
| // } | |
| return str.substring(idxFr, idxTo); | |
| } | |
| decode(val, conditions, defaultValue = null) { | |
| for (let idx = 0; idx < conditions.length / 2; idx++) { | |
| const condition = conditions[idx * 2]; | |
| const value = conditions[idx * 2 + 1] || defaultValue; | |
| if (utils.typeof(condition) == 'array') { | |
| if (condition.includes(val)) { | |
| return value; | |
| } | |
| } else { | |
| if (val == condition) { | |
| return value; | |
| } | |
| } | |
| } | |
| return defaultValue; | |
| } | |
| initialize() { | |
| this.getPath = this.module.getPath.bind(this); | |
| this.getCustomPath = this.module.getCustomPath.bind(this); | |
| this.existFile = this.module.existFile.bind(this); | |
| this.getClass = this.module.getClass.bind(this); | |
| this.getModule = this.module.getModule.bind(this); | |
| this.Null = this.type.Null.bind(this); | |
| this.typeof = this.type.typeof.bind(this); | |
| this.isNone = this.type.isNone.bind(this); | |
| this.isNull = this.type.isNull.bind(this); | |
| this.isString = this.type.isString.bind(this); | |
| this.isNumber = this.type.isNumber.bind(this); | |
| this.isArray = this.type.isArray.bind(this); | |
| this.sleep = this._sleep.bind(this); | |
| this.wait = this._wait.bind(this); | |
| this.getFullUrl = this.link.fullUrl.bind(this); //--- Utility class에는 없는 함수 (이름이 다름) | |
| this.getTemplateFullPath = getTemplateFullPath; | |
| this.getTemplateUrl = getTemplateUrl; | |
| this.getHash = getHash; | |
| this.stringFormat = stringFormat; | |
| this.stringLength = stringLength; | |
| this.integerFormat = integerFormat; | |
| this.floatFormat = floatFormat; | |
| this.floatFormat2 = floatFormat2; | |
| this.existField = existField; | |
| this.existIdxField = existIdxField; | |
| this.getObjectValue = getObjectValue; | |
| this.deepCopy = deepCopy; | |
| this.datetimeFormatter = datetimeFormatter; | |
| this.initFlagString = initFlagString; | |
| this.getFlagString = getFlagString; | |
| this.setFlagString = setFlagString; | |
| this.getFlagNumber = getFlagNumber; | |
| this.setFlagNumber = setFlagNumber; | |
| this.checkHacking = checkHacking; | |
| this.randomInteger = randomInteger; | |
| this.randomFloat = randomFloat; | |
| this.isNetworkError = isNetworkError; | |
| this.saveNotificationNormal = saveNotificationNormal; | |
| this.saveNotificationError = saveNotificationError; | |
| this.stringToHex = stringToHex; | |
| this.hexToString = hexToString; | |
| this.isWindows = isWindows; | |
| this.isLinux = isLinux; | |
| this.makeHelp = makeHelp; | |
| this.makeSetting = makeSetting; | |
| this.getClientIp = getClientIp; | |
| this.obj = this.module.getModule('include', 'obconObject.js'); | |
| } | |
| } | |
| const zzUtil = new Utility(); | |
| //--- 전체 URL을 반환 한다. | |
| function getFullUrl(url='') { | |
| // let rturl = config.http.baseUrl + config.http.path.substring(1); | |
| // return (url == '') ? config.http.baseUrl:zzUtil.link.join(config.http.baseUrl, url); | |
| return zzUtil.link.join(config.http.baseUrl, url); | |
| } | |
| function _getTemplateFile(siteId, ...args) { | |
| const filePath = path.join.apply(this, args); | |
| let files = []; | |
| if ((siteId != null) && (siteId != -1)) { | |
| files.push(zzUtil.getPath('themes', config.service.name, config.theme.name, 'layout', `site_${siteId}`, filePath)); | |
| files.push(zzUtil.getPath('themes', config.service.name, config.theme.defaultName, 'layout', `site_${siteId}`,filePath)); | |
| files.push(zzUtil.getPath('themes', config.theme.name, 'layout', `site_${siteId}`,filePath)); | |
| files.push(zzUtil.getPath('themes', config.theme.defaultName, 'layout', `site_${siteId}`,filePath)); | |
| } | |
| files.push(zzUtil.getPath('themes', config.service.name, config.theme.name, 'layout', filePath)); | |
| files.push(zzUtil.getPath('themes', config.service.name, config.theme.defaultName, 'layout', filePath)); | |
| files.push(zzUtil.getPath('themes', config.theme.name, 'layout', filePath)); | |
| files.push(zzUtil.getPath('themes', config.theme.defaultName, 'layout', filePath)); | |
| if ((siteId != null) && (siteId != -1)) { | |
| files.push(zzUtil.getPath('themes', config.service.name, config.theme.name, `site_${siteId}`, filePath)); | |
| files.push(zzUtil.getPath('themes', config.service.name, config.theme.defaultName, `site_${siteId}`, filePath)); | |
| files.push(zzUtil.getPath('themes', config.theme.name, `site_${siteId}`, filePath)); | |
| files.push(zzUtil.getPath('themes', config.theme.defaultName, `site_${siteId}`, filePath)); | |
| } | |
| files.push(zzUtil.getPath('themes', config.service.name, config.theme.name, filePath)); | |
| files.push(zzUtil.getPath('themes', config.service.name, config.theme.defaultName, filePath)); | |
| files.push(zzUtil.getPath('themes', config.theme.name, filePath)); | |
| files.push(zzUtil.getPath('themes', config.theme.defaultName, filePath)); | |
| let rtPath = zzUtil.getPath('themes', config.theme.defaultName, filePath); | |
| for (let idx = 0; idx < files.length; idx++) { | |
| if (fs.existsSync(files[idx])) { | |
| rtPath = files[idx]; | |
| break; | |
| } | |
| } | |
| rtPath = rtPath.replace(/\\/g, '/').replace(`${config.folder_root}/themes/`, ''); | |
| return rtPath; | |
| } | |
| function getTemplateFullPath(siteId, ...args) { | |
| args.unshift(siteId); | |
| return `${config.folder_root}/themes/${_getTemplateFile.apply(this, args)}` | |
| } | |
| function getTemplateUrl(siteId, ... args) { | |
| if ((args.length == 1) && (args[0].startsWith('http'))) { | |
| return args[0]; | |
| } | |
| // Many view modules push static assets with a leading "/" (e.g. "/js/moment.min.js"). | |
| // `_getTemplateFile()` treats leading "/" as an absolute path which breaks theme lookup, | |
| // causing 404s for scripts/styles and blank SPA pages. | |
| args = args.map((v) => (typeof v === 'string' && v.startsWith('/')) ? v.replace(/^\/+/, '') : v); | |
| args.unshift(siteId); | |
| if (config.http.useFullUrl) { | |
| return `${config.http.baseUrl}${config.http.path}/${_getTemplateFile.apply(this, args)}` | |
| } else { | |
| return `${config.http.path}/${_getTemplateFile.apply(this, args)}` | |
| } | |
| } | |
| function stringFormat(valStr, len, pad=' ') { | |
| let rtStr = valStr; | |
| while (rtStr.length < len) { | |
| rtStr = pad + rtStr; | |
| } | |
| return rtStr; | |
| } | |
| function stringLength(str) { | |
| let len = 0; | |
| for (let idx = 0; idx < str.length; idx++) { | |
| if (escape(str.charAt(idx)).length == 6) { | |
| len++; | |
| } | |
| len++; | |
| } | |
| return len; | |
| } | |
| function integerFormat(valInt, len, pad=' ', abs=true) { | |
| let rtStr = valInt.toString(); | |
| if (-1 < rtStr.indexOf('.')) { | |
| rtStr = rtStr.split('.')[0]; | |
| } | |
| while (rtStr.length < len) { | |
| rtStr = pad + rtStr; | |
| } | |
| if ((abs) && (len < rtStr.length)) { | |
| rtStr = rtStr.slice(rtStr.length - len, rtStr.length); | |
| } | |
| return rtStr; | |
| } | |
| //--- To-Do : 향후 개선 한다. | |
| //--- abs : true. 소수점 아래와 소수점 위의 길이를 지킨다. | |
| function floatFormat(valFloat, lenFirst=5, lenSecond=2, padFirst=' ', padSecond='0', abs=true) { | |
| let rtStr = valFloat.toString(); | |
| let tmpFirst = null; | |
| let tmpSecond = null; | |
| if (-1 < rtStr.indexOf('.')) { | |
| let items = rtStr.split('.'); | |
| tmpFirst = items[0]; | |
| tmpSecond = items[1]; | |
| if (abs) { | |
| if (lenSecond < tmpSecond.length) { | |
| tmpSecond = tmpSecond.slice(0, lenSecond); | |
| } | |
| } | |
| } else { | |
| tmpFirst = rtStr; | |
| tmpSecond = ''; | |
| } | |
| while (tmpSecond.length < lenSecond) { | |
| tmpSecond = tmpSecond + padSecond; | |
| } | |
| rtStr = tmpFirst + '.' + tmpSecond; | |
| while (rtStr.length < (lenFirst + 1 + lenSecond)) { | |
| rtStr = padFirst + rtStr; | |
| } | |
| if ((abs) && ((lenFirst + 1 + lenSecond) < rtStr.length)) { | |
| rtStr = rtStr.slice(rtStr.length - (lenFirst + 1 + lenSecond), rtStr.length); | |
| } | |
| return rtStr; | |
| } | |
| //--- 소수점 아래 자리만 확정 한다. | |
| function floatFormat2(valFloat, lenSecond=2, padSecond='0') { | |
| let rtStr = valFloat.toString(); | |
| let tmpFirst = null; | |
| let tmpSecond = null; | |
| if (-1 < rtStr.indexOf('.')) { | |
| let items = rtStr.split('.'); | |
| tmpFirst = items[0]; | |
| tmpSecond = items[1]; | |
| if (lenSecond < tmpSecond.length) { | |
| tmpSecond = tmpSecond.slice(0, lenSecond); | |
| } | |
| } else { | |
| tmpFirst = rtStr; | |
| tmpSecond = ''; | |
| } | |
| while (tmpSecond.length < lenSecond) { | |
| tmpSecond = tmpSecond + padSecond; | |
| } | |
| rtStr = tmpFirst + '.' + tmpSecond; | |
| return rtStr; | |
| } | |
| function getHash(plainText) { | |
| let hash = crypto.createHash('md5'); | |
| hash.update(plainText); | |
| return hash.digest('hex').toLowerCase(); | |
| } | |
| function existField(paramObject, paramField) { | |
| if ((paramObject == null) || (typeof(paramObject) == 'undefined')) { | |
| return false; | |
| } | |
| return typeof(paramObject[paramField]) != 'undefined'; | |
| // return Object.getOwnPropertyNames(paramObject).includes(paramField); | |
| // return -1 < Object.getOwnPropertyNames(paramObject).indexOf(paramField); | |
| } | |
| function existIdxField(paramObject, paramField) { | |
| if ((paramObject == null) || (typeof(paramObject) == 'undefined')) { | |
| return false; | |
| } | |
| return typeof(paramObject[`idx_${paramField}`]) != 'undefined'; | |
| // return Object.getOwnPropertyNames(paramObject).includes(paramField); | |
| // return -1 < Object.getOwnPropertyNames(paramObject).indexOf(paramField); | |
| } | |
| function getObjectValue(paramObject, paramField, paramDefault) { | |
| return existField(paramObject, paramField) ? paramObject[paramField]:paramDefault; | |
| } | |
| function deepCopy(obj) { | |
| return JSON.parse(JSON.stringify(obj)); | |
| } | |
| function randomInteger(min, max) { | |
| return Math.floor(Math.random() * (max - min + 1)) + min; | |
| } | |
| function randomFloat(min, max) { | |
| return Math.random() * (max - min) + min; | |
| } | |
| //--- pos : 1(첫번째 문자), 2(두번째 문자), ..., 32 | |
| let maxPos = 32; | |
| function initFlagString(source) { | |
| let tmpStr = source + '0000000000000000000000000000000000000000'; | |
| return tmpStr.substring(0, maxPos); | |
| } | |
| function getFlagString(source, pos) { | |
| let tmpStr = initFlagString(source); | |
| tmpStr = tmpStr.substring(pos - 1, pos); | |
| return tmpStr; | |
| } | |
| function setFlagString(source, pos, set) { | |
| let tmpStr = initFlagString(source); | |
| tmpStr = tmpStr.substring(0, pos - 1) + set + tmpStr.substring(pos, maxPos); | |
| return tmpStr; | |
| } | |
| //--- pos : 1(일자리), 2(십자리), ..., 32 | |
| function getFlagNumber(source, pos) { | |
| let tmpStr = '0000000000000000' + Math.abs(source); | |
| tmpStr = tmpStr.substring(tmpStr.length - 16); | |
| tmpStr = tmpStr.substring(16 - pos, 16 - pos + 1); | |
| return parseInt(tmpStr); | |
| } | |
| function setFlagNumber(source, pos, set) { | |
| let tmpStr = '0000000000000000' + Math.abs(source); | |
| tmpStr = tmpStr.substring(tmpStr.length - 16); | |
| tmpStr = tmpStr.substring(0, 16 - pos) + set + tmpStr.substring(16 - pos + 1); | |
| return parseInt(tmpStr); | |
| } | |
| function checkHacking(param) { | |
| if (!param) { | |
| return false; | |
| } | |
| if ((-1 < param.indexOf(';')) || (-1 < param.indexOf('\''))) { | |
| return true; | |
| } | |
| return false; | |
| } | |
| //--- 박광서의 요청에 따라 현재 시간이 아니라, 전달되는 데이터의 시간으로 체크 한다. 2019.03.31 | |
| //--- 통신 이상 검사 : true. 통신 이상, false. 통신 정상 | |
| //--- | |
| //--- 한번도 데이터를 받은 적이 없으면 통신 이상 | |
| //--- 1. 정류기: 설정한 시간(Default 60초) 이상 데이터가 입력되지 않으면 통신 이상 | |
| //--- 2. 원격TB: 통신 주기 * 3 보다 통신이 되지 않은 시간이 클 경우 통신 이상 | |
| //--- 3. 배관링크: 통신 주기 * 3 보다 통신이 되지 않은 시간이 클 경우 통신 이상 | |
| //--- 4. 수위센서: 통신 주기 * 3 보다 통신이 되지 않은 시간이 클 경우 통신 이상 | |
| //--- 5. 관말압력 | |
| //--- 피크타임 모드인 경우 | |
| //--- 피크타임인 경우 - 통신 주기 * 3 보다 통신이 되지 않은 시간이 클 경우 통신 이상 | |
| //--- 피크타임이 아닌 경우 - 항상 통신 정상 | |
| //--- 피크타임 모드가 아닌 경우 - 통신 주기 * 3 보다 통신이 되지 않은 시간이 클 경우 통신 이상 | |
| //--- 6. 특정정압기: 통신 주기 * 3 보다 통신이 되지 않은 시간이 클 경우 통신 이상 | |
| //--- 7. 수신감도: 통신 주기 * 3 보다 통신이 되지 않은 시간이 클 경우 통신 이상 | |
| // function isNetworkError(deviceIndex, type, networkCycle, networkCycleUnit, statusDatetime) { | |
| function isNetworkError(siteKey, device, statusDatetime) { | |
| const deviceIndex = siteKey + '_' + device.type + '_' + device.deviceKey; | |
| let type = device.type; | |
| let networkCycle = device.networkCycle; | |
| let networkCycleUnit = utils.decode(device.networkCycleUnit, [ '1', '초', '2', '분', '3', '시' ], device.networkCycleUnit) ; | |
| if (type == '5') { //--- 5. 관말압력 | |
| if (device.networkMode == '4') { //--- 4. 피크타임 모드 | |
| networkCycle = device.peakNetworkCycle; | |
| networkCycleUnit = '분'; | |
| //--- 설정된 피크타임 시간이 아니면, statusDatetime을 현재 시간으로 설정하여 항상 통신 이상이 발생하지 않도록 한다. | |
| let isPeak = false; | |
| let hour = parseInt(moment().format('HH')); //--- 현재 시간 (0 ~ 24) | |
| if ((device.peakTimeStart1 <= hour) && (hour < device.peakTimeEnd1)) { | |
| isPeak = true; | |
| } | |
| if ((device.peakTimeStart2 <= hour) && (hour < device.peakTimeEnd2)) { | |
| isPeak = true; | |
| } | |
| if (isPeak == false) { | |
| statusDatetime = moment(); | |
| } | |
| } | |
| } | |
| //--- 통신 이상 여부를 검사 한다. | |
| let rtcd = true; | |
| if (statusDatetime == null) { //--- 한번도 데이터를 받은 적이 없으면 통신 이상 처리 | |
| return true; | |
| } | |
| let datetimeFr = statusDatetime; //--- 최종 도착한 데이터의 시간 | |
| let datetimeTo = moment(); //--- 현재 시간 | |
| let duration = 0; | |
| let unit = '분'; | |
| switch (type) { | |
| case '1' : | |
| unit = '초'; | |
| duration = moment.duration(datetimeTo.diff(datetimeFr)).asSeconds(); | |
| //--- 정류기는 60초 이상 데이터가 입력되지 않으면 통신 이상 처리 -> 설정한 시간으로 비교 | |
| // rtcd = (60 < duration); | |
| rtcd = (device.networkCheckTime < duration); | |
| // logger.info(`include/Utility.js :: ${deviceIndex} : Duration - ${floatFormat(duration, 7, 2)} ${unit}, networkCycle : ${device.networkCheckTime} :: ${rtcd}`); | |
| break; | |
| case '2' : | |
| case '3' : | |
| case '4' : | |
| case '5' : | |
| case '6' : | |
| case '7' : | |
| unit = '분'; | |
| duration = moment.duration(datetimeTo.diff(datetimeFr)).asMinutes(); | |
| if (networkCycleUnit == '시') { | |
| networkCycle = networkCycle * 60; | |
| } | |
| //--- 박광서의 요청으로 임시로 통신 주기 * 3 보다 통신이 되지 않은 시간이 클 경우 오류 처리 (2019-03-11) | |
| rtcd = (3 * networkCycle < duration); | |
| // logger.info(`include/Utility.js :: ${deviceIndex} : Duration - ${floatFormat(duration, 7, 2)} ${unit}, 3 * networkCycle : ${3 * networkCycle} :: ${rtcd}`); | |
| break; | |
| case '8': | |
| case 'A': | |
| case 'B': | |
| default: | |
| switch (networkCycleUnit) { | |
| case '초': | |
| unit = '초'; | |
| duration = moment.duration(datetimeTo.diff(datetimeFr)).asSeconds(); | |
| break; | |
| case '분': | |
| unit = '분'; | |
| duration = moment.duration(datetimeTo.diff(datetimeFr)).asMinutes(); | |
| break; | |
| case '시': | |
| unit = '분'; | |
| duration = moment.duration(datetimeTo.diff(datetimeFr)).asMinutes(); | |
| networkCycle = networkCycle * 60; | |
| break; | |
| } | |
| rtcd = (3 * networkCycle < duration); | |
| // logger.info(`include/global_utils.js :: ${deviceIndex} : Duration - ${floatFormat(duration, 7, 2)} ${unit}, 3 * networkCycle : ${3 * networkCycle} :: ${rtcd}`); | |
| break; | |
| } | |
| return rtcd; | |
| } | |
| function saveNotificationNormal(device, datetimeTo) { | |
| let noti = {}; | |
| noti.name = '통신 정상'; | |
| noti.site = device.site; | |
| noti.device = device.id; | |
| noti.deviceKey = device.deviceKey; | |
| noti.deviceName = device.name; | |
| noti.branch = -1; | |
| noti.branchName = ''; | |
| noti.type = device.type; | |
| noti.eventDatetime = datetimeTo.format('YYYY-MM-DD HH:mm:ss'); | |
| noti.level = 'Info'; | |
| noti.description = '통신 정상'; | |
| //--- branch로 branch 이름을 가져 온다. | |
| let query = { where: { id: device.branch, deleted: false } }; | |
| modules.branches.model.table.findOne(query) | |
| .then(function(branch) { | |
| if (branch != null) { | |
| noti.branch = branch.id; | |
| noti.branchName = branch.name; | |
| } | |
| modules.notifications.model.table.create(noti) | |
| .then(function(results) { | |
| // logger.info(JSON.stringify(results)); | |
| }).catch(utils.obj.loggerError); | |
| }).catch(function(err) { | |
| logger.error(JSON.stringify(err)); | |
| modules.notifications.model.table.create(noti) | |
| .then(function(results) { | |
| // logger.info(JSON.stringify(results)); | |
| }).catch(utils.obj.loggerError); | |
| }); | |
| } | |
| function saveNotificationError(device, datetimeTo) { | |
| let noti = {}; | |
| noti.name = '통신 이상'; | |
| noti.site = device.site; | |
| noti.device = device.id; | |
| noti.deviceKey = device.deviceKey; | |
| noti.deviceName = device.name; | |
| noti.branch = -1; | |
| noti.branchName = ''; | |
| noti.type = device.type; | |
| noti.eventDatetime = datetimeTo.format('YYYY-MM-DD HH:mm:ss'); | |
| noti.level = 'Error'; | |
| noti.description = '통신 이상'; | |
| //--- branch로 branch 이름을 가져 온다. | |
| let query = { where: { id: device.branch, deleted: false } }; | |
| modules.branches.model.table.findOne(query) | |
| .then(function(branch) { | |
| if (branch != null) { | |
| noti.branch = branch.id; | |
| noti.branchName = branch.name; | |
| } | |
| modules.notifications.model.table.create(noti) | |
| .then(function(results) { | |
| // logger.info(JSON.stringify(results)); | |
| }).catch(utils.obj.loggerError); | |
| }).catch(function(err) { | |
| logger.error(JSON.stringify(err)); | |
| modules.notifications.model.table.create(noti) | |
| .then(function(results) { | |
| // logger.info(JSON.stringify(results)); | |
| }).catch(utils.obj.loggerError); | |
| }); | |
| } | |
| function stringToHex(str) { | |
| const buf = Buffer.from(str, 'utf8'); | |
| return buf.toString('hex'); | |
| } | |
| function hexToString(str) { | |
| const buf = new Buffer(str, 'hex'); | |
| return buf.toString('utf8'); | |
| } | |
| function isWindows() { | |
| return (process.env.HOMEDRIVE) ? true:false; | |
| } | |
| function isLinux() { | |
| return (process.env.HOME) ? true:false; | |
| } | |
| //--- To-Do : LocalStorage, Cookie 등을 사용하여 설정 관리 | |
| function makeSetting(id='iconSetting') { | |
| // if ((!config.func) || (!config.func.page) || (!config.func.page.setting)) { | |
| // return ''; | |
| // } | |
| // if (config.func.page.setting == false) { | |
| // return ''; | |
| // } | |
| //--- https://icons.getbootstrap.com/ | |
| // <i class="bi-alarm" style="${config.theme.font.help} color: cornflowerblue; cursor: pointer;" | |
| // onclick="window.alert('Reserved');"></i> | |
| // return `<i id="${id}" class="bi-gear" style="${config.theme.font.help} color: cornflowerblue; cursor: pointer; display: none;" | |
| // onclick="nsOBCon.pageSettings.display();"></i>`; | |
| return `<span id="${id}" class="material-icons-outlined" style="${config.theme.font.help} color: cornflowerblue; cursor: pointer; display: none;" | |
| onclick="nsOBCon.pageSettings.display();">settings</span>`; | |
| } | |
| //--- options.helpPage = 'url'; | |
| //--- options.helpPage = [ { name: '', url: '' } ]; //--- To-Do : 선택 목록을 보여준 후 선택시 도움말 화면 표시 | |
| function makeHelp(id='iconHelp') { | |
| // if ((!config.func) || (!config.func.page) || (!config.func.page.setting)) { | |
| // return ''; | |
| // } | |
| // if (config.func.page.setting == false) { | |
| // return ''; | |
| // } | |
| //--- https://icons.getbootstrap.com/ | |
| // return `<i class="bi-question-square" style="${config.theme.font.help} color: cornflowerblue; cursor: pointer;" | |
| // onclick="window.open('https://www.obcon.biz/cms/${options.helpPage}', '_blank');"></i>`; | |
| // return `<i id="${id}" class="bi-question-square" style="${config.theme.font.help} color: cornflowerblue; cursor: pointer; display: none;" | |
| // onclick="nsOBCon.pageHelps.display('${config.service.name}');"></i>`; | |
| return `<span id="${id}" class="material-icons-outlined" style="${config.theme.font.help} color: cornflowerblue; cursor: pointer; display: none;" | |
| onclick="nsOBCon.pageHelps.display('${config.service.name}');">help_center</span>`; | |
| } | |
| function getClientIp(req) { | |
| var clientIp = req.body.clientIp || | |
| req.headers['x-forwarded-for'] || | |
| req.connection.remoteAddress || | |
| req.socket.remoteAddress || | |
| req.connection.socket.remoteAddress || ''; | |
| clientIp = clientIp.split(',')[0]; | |
| clientIp = clientIp.split(':').slice(-1)[0]; | |
| return clientIp; | |
| } | |
| function datetimeFormatter(str, formatFr = 'YYYYMMDDHHmmss', formatTo = 'YYYY-MM-DD HH:mm:ss') { | |
| return (str == '') ? '': moment(str, formatFr).format(formatTo); | |
| } | |
| // async function sleep(miliseconds) { | |
| // let promise = new Promise(function(resolve, reject) { | |
| // setTimeout(function() { | |
| // resolve(); | |
| // }, miliseconds); | |
| // }); | |
| // await promise; | |
| // } | |
| module.exports = Utility; | |