UNPKG

@libs-scripts-mep/daq-fwlink

Version:

Torna capaz o controle do DAQ através do PVI via WebSocket

601 lines (533 loc) 25.3 kB
import FWLink from "./FWLink.js" /** * Abstração de hardware de um DAQ * * # Exemplo * * ⚠️ O código a seguir é apenas um exemplo, não é recomendado inicializar uma instância do DAQ manualmente. * * ```js * const DAQ = new HardwareDAQ("COM3_1") * ``` */ class HardwareDAQ { constructor(id) { this.id = id this.translates = new Object() this.in = { dc1: { value: false, onChange: (newVal) => { } }, dc2: { value: false, onChange: (newVal) => { } }, dc3: { value: false, onChange: (newVal) => { } }, dc4: { value: false, onChange: (newVal) => { } }, dc5: { value: false, onChange: (newVal) => { } }, dc6: { value: false, onChange: (newVal) => { } }, dc7: { value: false, onChange: (newVal) => { } }, dc8: { value: false, onChange: (newVal) => { } }, ac1: { value: false, onChange: (newVal) => { } }, ac2: { value: false, onChange: (newVal) => { } }, ac3: { value: false, onChange: (newVal) => { } }, ac4: { value: false, onChange: (newVal) => { } }, ac5: { value: false, onChange: (newVal) => { } }, ac6: { value: false, onChange: (newVal) => { } }, ac7: { value: false, onChange: (newVal) => { } }, ac8: { value: false, onChange: (newVal) => { } }, ac9: { value: false, onChange: (newVal) => { } }, ac10: { value: false, onChange: (newVal) => { } }, ac11: { value: false, onChange: (newVal) => { } }, ac12: { value: false, onChange: (newVal) => { } }, protectAc: { value: false, onChange: (newVal) => { } }, protectDc: { value: false, onChange: (newVal) => { } }, duty: { value: 0, onChange: (newVal) => { } }, freq: { value: 0, onChange: (newVal) => { } }, duty2: { value: 0, onChange: (newVal) => { } }, freq2: { value: 0, onChange: (newVal) => { } }, duty3: { value: 0, onChange: (newVal) => { } }, freq3: { value: 0, onChange: (newVal) => { } }, voltageOrCurrent1: { value: { value: 0, onChange: (newVal) => { } }, type: { value: "C", onChange: (newVal) => { } } }, voltageOrCurrent2: { value: { value: 0, onChange: (newVal) => { } }, type: { value: "C", onChange: (newVal) => { } } }, voltageOrCurrent3: { value: { value: 0, onChange: (newVal) => { } }, type: { value: "C", onChange: (newVal) => { } } }, out0a1500mvfb1: { value: 0, onChange: (newVal) => { } }, ntc: { value: 0, onChange: (newVal) => { } }, beep: { value: false, onChange: (newVal) => { } }, } this.out = Object.assign( { beep: { value: false, onChange: (newVal) => { }, setValue: (_time, _f) => { this.setBeep(_time, _f) } }, power: { value: "OFF", onChange: (newVal) => { }, setValue: (val, _f) => { this.alimenta(val, _f) } }, calibration: { value: { value: 0, onChange: (newVal) => { } }, state: { value: 0, onChange: (newVal) => { } } }, out0a1500mv1: { value: 0, onChange: (newVal) => { }, setValue: (val, _f) => { this.confMv(val, _f) } }, auxpower1: { value: false, onChange: (newVal) => { }, setValue: (val, _f) => { val ? this.ligaAux220(1, _f) : this.desligaAux220(1, _f) } } }, Object.assign( declareRelay(this), declareFlameSensor(this), declareNtc(this), declarePt100(this), ), Object.assign( declareOut60mv(this), declareOutAnalog(this), declareOutPwm(this) ) ) this.usbState = { value: false, onChange: (newVal) => { } } this.init() FWLink.runInstruction("OBSERVERSUPDATE", [], null, this.id) /** * @typedef {`rl${1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18}`} rl * @param {HardwareDAQ} daqInstance * @returns {{[key in rl]: { * value: boolean, * onChange: (newVal: boolean) => void, * setValue: (val: boolean, _f: () => void) => void * } * }} */ function declareRelay(daqInstance) { let obj = {} for (let i = 0; i < 18; i++) { obj[`rl${i + 1}`] = { value: false, onChange: (newVal) => { }, setValue: (val, _f) => { val ? daqInstance.ligaRele(i + 1, _f) : daqInstance.desligaRele(i + 1, _f) } } daqInstance.translates[`outs.relay_${i + 1}`] = `this.out.rl${i + 1}` } return obj } /** * @typedef {`flamesensor${1|2|3}`} flamesensor * @param {HardwareDAQ} daqInstance * @returns {{[key in flamesensor]: {value: string, onChange: (newVal: string) => void, setValue: (val: string, _f: () => void) => void}}} */ function declareFlameSensor(daqInstance) { let obj = {} for (let i = 0; i < 3; i++) { obj[`flamesensor${i + 1}`] = { value: "30M", onChange: (newVal) => { }, setValue: (val, _f) => { daqInstance.confChama(i + 1, val, _f) } } daqInstance.translates[`outs.flamesensor_${i + 1}`] = `this.out.flamesensor${i + 1}` } return obj } /** * @typedef {`ntc${1|2}`} ntc * @param {HardwareDAQ} daqInstance * @returns {{[key in ntc]: {value: string, onChange: (newVal: string) => void, setValue: (val: string, _f: () => void) => void}}} */ function declareNtc(daqInstance) { let obj = {} for (let i = 0; i < 2; i++) { obj[`ntc${i + 1}`] = { value: "MENOS20GRAUS", onChange: (newVal) => { }, setValue: (val, _f) => { daqInstance.confNtc(i + 1, val, _f) } } daqInstance.translates[`outs.ntc_${i + 1}`] = `this.out.ntc${i + 1}` } return obj } /** * @typedef {`pt100_${1|2}`} pt100 * @param {HardwareDAQ} daqInstance * @returns {{[key in pt100]: { * value: { value: string, onChange: (newVal: string) => void }, * type: { value: string, onChange: (newVal: string) => void }, * onChange: (newVal: string) => void, * setValue: (val: string, type: string, _f: () => void) => void * }}} */ function declarePt100(daqInstance) { let obj = {} for (let i = 0; i < 2; i++) { obj[`pt100_${i + 1}`] = { value: { value: "ZEROGRAU", onChange: (newVal) => { } }, type: { value: "CL", onChange: (newVal) => { } }, onChange: (newVal) => { }, setValue: (val, type, _f) => { daqInstance.confPt100(i + 1, val, type, _f) } } daqInstance.translates[`outs.pt100_${i + 1}_temperature`] = `this.out.pt100_${i + 1}.value` daqInstance.translates[`outs.pt100_${i + 1}_cabletype`] = `this.out.pt100_${i + 1}.type` } return obj } /** * @typedef {`out0a60mv${1|2}`} out60mv * @param {HardwareDAQ} daqInstance * @returns {{[key in out60mv]: {value: number, onChange: (newVal: number) => void, setValue: (val: number, _f: () => void) => void}}} */ function declareOut60mv(daqInstance) { let obj = {} for (let i = 0; i < 2; i++) { obj[`out0a60mv${i + 1}`] = { value: 0, onChange: (newVal) => { }, setValue: (val, _f) => { daqInstance.confMv(i + 1, val, _f) } } daqInstance.translates[`outs.out_0_60_mv_${i + 1}`] = `this.out.out0a60mv${i + 1}` } return obj } /** * @typedef {`dac${1|2}`} dac * @param {HardwareDAQ} daqInstance * @returns {{[key in dac]: { * value: { value: number, onChange: (newVal: number) => void }, * type: { value: string, onChange: (newVal: string) => void }, * setValue: (val: number, type: string, converted: boolean, _f: () => void) => void * }}} */ function declareOutAnalog(daqInstance) { let obj = {} for (let i = 0; i < 2; i++) { obj[`dac${i + 1}`] = { value: { value: 0, onChange: (newVal) => { } }, type: { value: "C", onChange: (newVal) => { } }, setValue: (val, type, converted, _f) => { daqInstance.confAnalog(i + 1, val, converted, type, _f) } } daqInstance.translates[`outs.outa${i + 1}`] = `this.out.dac${i + 1}.value` daqInstance.translates[`outs.a${i + 1}_v_or_c`] = `this.out.dac${i + 1}.type` } return obj } /** * @typedef {`osc${1|2|3}`} osc * @param {HardwareDAQ} daqInstance * @returns {{[key in osc]: { * freq: { value: number, onChange: (newVal: number) => void }, * duty: { value: number, onChange: (newVal: number) => void }, * setValue: (duty: number, freq: number, _f: () => void) => void * }}} */ function declareOutPwm(daqInstance) { let obj = {} for (let i = 0; i < 3; i++) { obj[`osc${i + 1}`] = { freq: { value: 0, onChange: (newVal) => { } }, duty: { value: 0, onChange: (newVal) => { } }, setValue: (duty, freq, _f) => { daqInstance.freqPwm(i + 1, freq, duty, _f) } } daqInstance.translates[`outs.freq_pwm${i + 1}`] = `this.out.osc${i + 1}.freq` daqInstance.translates[`outs.duty_pwm${i + 1}`] = `this.out.osc${i + 1}.duty` } return obj } } get queryId() { return this.id == "" ? null : { daq: this.id } } showHardware() { return FWLink.runInstructionS('show_hw', []) } bloqueiaUsb(assyncFunc = () => { }) { return FWLink.runInstruction("bloqueia_usb", [], assyncFunc, this.queryId) } desbloqueiaUsb(assyncFunc = () => { }) { return FWLink.runInstruction("desbloqueia_usb", [], assyncFunc, this.queryId) } atualizaUsb(assyncFunc = () => { }) { return this.desbloqueiaUsb(assyncFunc) } confMv(int_val, assyncFunc = () => { }) { return FWLink.runInstruction("conf_mv_1", [int_val], assyncFunc, this.queryId) } confMv1(int_val, assyncFunc = () => { }) { return this.confMv(int_val, assyncFunc) } confPot1(int_val, assyncFunc = () => { }) { return FWLink.runInstruction("conf_pot_1", [int_val], assyncFunc, this.queryId) } confPot2(int_val, assyncFunc = () => { }) { return FWLink.runInstruction("conf_pot_2", [int_val], assyncFunc, this.queryId) } confAnalog(int_n, int_val, converted, type, assyncFunc = () => { }) { return FWLink.runInstruction("v_ou_a", [int_n, type, int_val, converted], assyncFunc, this.queryId) } confVan1(int_val, converted = false, assyncFunc = () => { }) { return this.confAnalog(1, int_val, converted, "V", assyncFunc) } confAan1(int_val, converted = false, assyncFunc = () => { }) { return this.confAnalog(1, int_val, converted, "A", assyncFunc) } confVan2(int_val, converted = false, assyncFunc = () => { }) { return this.confAnalog(2, int_val, converted, "V", assyncFunc) } confAan2(int_val, converted = false, assyncFunc = () => { }) { return this.confAnalog(2, int_val, converted, "A", assyncFunc) } confLeVan1(int_val, assyncFunc = () => { }) { return FWLink.runInstruction("LE_V_OU_A_1", ["V", int_val], assyncFunc, this.queryId) } confLeVan2(int_val, assyncFunc = () => { }) { return FWLink.runInstruction("LE_V_OU_A_2", ["V", int_val], assyncFunc, this.queryId) } confLeAan1(int_val, assyncFunc = () => { }) { return FWLink.runInstruction("LE_V_OU_A_1", ["A", int_val], assyncFunc, this.queryId) } confLeAan2(int_val, assyncFunc = () => { }) { return FWLink.runInstruction("LE_V_OU_A_2", ["A", int_val], assyncFunc, this.queryId) } confChama(int_n, chama_val, assyncFunc = () => { }) { return FWLink.runInstruction("chama", [int_n, chama_val], assyncFunc, this.queryId) } confChama1(int_val, assyncFunc = () => { }) { return this.confChama(1, int_val, assyncFunc) } confChama2(int_val, assyncFunc = () => { }) { return this.confChama(2, int_val, assyncFunc) } confChama3(int_val, assyncFunc = () => { }) { return this.confChama(3, int_val, assyncFunc) } alimenta(val, assyncFunc = () => { }) { return FWLink.runInstruction("CONF_TENSAO", [val], assyncFunc, this.queryId) } alimenta12(assyncFunc = () => { }) { return this.alimenta("12VC", assyncFunc) } alimenta24(assyncFunc = () => { }) { return this.alimenta("24VC", assyncFunc) } alimenta110(assyncFunc = () => { }) { return this.alimenta("110VA", assyncFunc) } alimenta220(assyncFunc = () => { }) { return this.alimenta("220VA", assyncFunc) } desligaAlimentacao(assyncFunc = () => { }) { return this.alimenta("OFF", assyncFunc) } ligaAux220(int_val, assyncFunc = () => { }) { return FWLink.runInstruction("CONF_ALIM_AUX", ["ON", int_val], assyncFunc, this.queryId) } desligaAux220(int_val, assyncFunc = () => { }) { return FWLink.runInstruction("CONF_ALIM_AUX", ["OFF", int_val], assyncFunc, this.queryId) } ntc1(int_val, assyncFunc = () => { }) { return FWLink.runInstruction("ntc_1", [int_val], assyncFunc, this.queryId) } ntc2(int_val, assyncFunc = () => { }) { return FWLink.runInstruction("ntc_2", [int_val], assyncFunc, this.queryId) } confNtc(int_n, ntc_val, assyncFunc = () => { }) { return this[`ntc${int_n}`](ntc_val, assyncFunc) } confPt100(int_n, pt100_val, pt100_type, assyncFunc = () => { }) { return FWLink.runInstruction(`PT100_TEMP_${int_n}`, [pt100_val, pt100_type], assyncFunc, this.queryId) } freqPwm(int_outNum, int_freq, int_duty, assyncFunc = () => { }) { return FWLink.runInstruction("freq_pwm", [int_outNum, int_freq, int_duty], assyncFunc, this.queryId) } freqPwm1(int_freq, int_duty, assyncFunc = () => { }) { return this.freqPwm(1, int_freq, int_duty, assyncFunc) } freqPwm2(int_freq, int_duty, assyncFunc = () => { }) { return this.freqPwm(2, int_freq, int_duty, assyncFunc) } freqPwm3(int_freq, int_duty, assyncFunc = () => { }) { return this.freqPwm(3, int_freq, int_duty, assyncFunc) } setBeep(_time, assyncFunc = () => { }) { return FWLink.runInstruction("beep", _time ? [_time] : [], assyncFunc, this.queryId) } ligaRele(int_rele, assyncFunc = () => { }) { return FWLink.runInstruction("liga_rele", ["RL" + int_rele], assyncFunc, this.queryId) } desligaRele(int_rele, assyncFunc = () => { }) { return FWLink.runInstruction("desliga_rele", ["RL" + int_rele], assyncFunc, this.queryId) } /** @param {number[]} reles */ ligaReles(reles) { return FWLink.runInstructionS("LIGA_MULTIPLOS_RELES", [reles.map(r => "RL" + r).join()]) } /** @param {number[]} reles */ desligaReles(reles) { return FWLink.runInstructionS("DESLIGA_MULTIPLOS_RELES", [reles.map(r => "RL" + r).join()]) } init() { this.translates["outs.calibstate"] = "this.out.calibration.state" this.translates["outs.calibval"] = "this.out.calibration.value" this.translates["outs.power"] = "this.out.power" this.translates["outs.beep"] = "this.out.beep" this.translates["ins.ntc"] = "this.in.ntc" this.translates["ins.dc1"] = "this.in.dc1" this.translates["ins.dc2"] = "this.in.dc2" this.translates["ins.dc3"] = "this.in.dc3" this.translates["ins.dc4"] = "this.in.dc4" this.translates["ins.dc5"] = "this.in.dc5" this.translates["ins.dc6"] = "this.in.dc6" this.translates["ins.dc7"] = "this.in.dc7" this.translates["ins.dc8"] = "this.in.dc8" this.translates["ins.ac1"] = "this.in.ac1" this.translates["ins.ac2"] = "this.in.ac2" this.translates["ins.ac3"] = "this.in.ac3" this.translates["ins.ac4"] = "this.in.ac4" this.translates["ins.ac5"] = "this.in.ac5" this.translates["ins.ac6"] = "this.in.ac6" this.translates["ins.ac7"] = "this.in.ac7" this.translates["ins.ac8"] = "this.in.ac8" this.translates["ins.ac9"] = "this.in.ac9" this.translates["ins.beep"] = "this.in.beep" this.translates["ins.ac10"] = "this.in.ac10" this.translates["ins.ac11"] = "this.in.ac11" this.translates["ins.ac12"] = "this.in.ac12" this.translates["ins.vorc1"] = "this.in.voltageOrCurrent1.value" this.translates["ins.vorc2"] = "this.in.voltageOrCurrent2.value" this.translates["ins.vorc3"] = "this.in.voltageOrCurrent3.value" this.translates["ins.a1_v_or_c"] = "this.in.voltageOrCurrent1.type" this.translates["ins.a2_v_or_c"] = "this.in.voltageOrCurrent2.type" this.translates["ins.a3_v_or_c"] = "this.in.voltageOrCurrent3.type" this.translates["ins.dutycicle1"] = "this.in.duty" this.translates["ins.frequency1"] = "this.in.freq" this.translates["ins.dutycicle2"] = "this.in.duty2" this.translates["ins.frequency2"] = "this.in.freq2" this.translates["ins.dutycicle3"] = "this.in.duty3" this.translates["ins.frequency3"] = "this.in.freq3" this.translates["ins.protect_ac"] = "this.in.protectAc" this.translates["ins.protect_dc"] = "this.in.protectDc" this.translates["ins.0_1500_mv_fb_1"] = "this.in.out0a1500mvfb1" this.translates[`outs.out_0_1500_mv_1`] = `this.out.out0a1500mv1` this.translates[`outs.auxpower1`] = `this.out.auxpower1` FWLink.PVIEventObserver.add((message, param) => { message = message.toLowerCase() let subject = message.match(/([o]?[i|u][n|t][s]).(\w+)./) if (param.constructor == Array) { let id = param[1] if (id != this.id && this.id != "") return param = param[0] } if (subject) { let resource = `${subject[1]}.${subject[2]}` if (!this.translates[resource]) { console.log("Nao tinha o objeto: ", resource) } else { eval(this.translates[resource] + ".value=param") eval(this.translates[resource] + ".onChange(param)") } } if (message.indexOf("usbdevice") > -1) { console.log(message) let stateusb = message.indexOf("disconnected") > -1 this.usbState.value = !stateusb this.usbState.onChange(!stateusb) } }, "PVI.DaqScript.DaqHardware", this) FWLink.PVIEventObserver.add((message, param) => { message = message.toLowerCase() let subject = message.match(/([o]?[i|u][n|t][s]).(\w+)./) if (param.constructor == Array) { let id = param[1] if (id != this.id && this.id != "") return param = param[0] } if (subject) { let resource = `${subject[1]}.${subject[2]}` if (!this.translates[resource]) { if (resource != "ins.frequency" && resource != "ins.dutycicle") console.log("Nao tinha o objeto: ", resource) } else { eval(this.translates[resource] + ".value=param") eval(this.translates[resource] + ".onChange(param)") } } if (message.indexOf("usbdevice") > -1) { let stateusb = message.indexOf("disconnected") > -1 this.usbState.value = !stateusb this.usbState.onChange(!stateusb) } }, "HwControl.", this) } } /** * Clase que gerencia DAQ's * * # Exemplos * * Os métodos estáticos da classe ficam disponíveis após a importação. * * ⚠️ O método `mount()` é chamado automaticamente via construtor estático * * ```js * import DAQList from "./module_path/DAQ.js" * * DAQList.mount() * ``` */ export default class DAQList { static List = [] static MAX_CONNECTION_TIMEOUT = 5000 /** * Inicia sincronização de DAQ's conectados e desconectados baseado nos eventos emitidos pelo PVI * * # Exemplos * * ```js * DAQList.pviSync() * ``` */ static pviSync() { FWLink.PVIEventObserver.add((message, params) => { console.log(message, params) if (params[0]) { if (!this.isKnownDaq(params[1])) { this.List.push(new HardwareDAQ(params[1])) } } else { this.removeDaq(params[1]) } }, "usbDevice", this) } /** * Popula a lista de DAQ's baseado nos DAQ's detectados pelo PVI * # Exemplos * * ```js * DAQList.mount() * ``` */ static mount() { this.List = [] let DaqIdList = JSON.parse(FWLink.runInstruction("get_daq_list", [], null)) for (const daqId of DaqIdList) { const id = typeof daqId == "string" ? daqId : daqId.ID if (!this.isKnownDaq(id)) { this.List.push(new HardwareDAQ(id)) } else { this.removeDaq(id) } } console.log("DAQ's encontrados:", this.List) this.pviSync() } /** * Remove uma instância do DAQ da lista * @param {String} id * * # Exemplos * * ```js * DAQList.removeDaq("COM3_1") * ``` */ static removeDaq(id) { let index = 0 for (const daq of this.List) { if (id == daq.id) { this.List.splice(index, 1) } index++ } } /** * Retorna um DAQ baseado no ID * @param {String} id * @returns DAQ * * # Exemplos * * ```js * DAQList.getDaq("COM3_1") * ``` */ static getDaq(id) { let daqFound = false if (this.List.length == 0) { return daqFound } for (const daq of this.List) { if (id == daq.id) { daqFound = daq; break } } return daqFound } /** * Verifica se o ID informado já está na lista de DAQ's conhecidos * @param {String} DaqId * @returns bool * * # Exemplos * ```js * DAQList.isKnownDaq("COM3_1") * ``` */ static isKnownDaq(DaqId) { let known = false if (this.List.length == 0) { return known } for (const daq of this.List) { if (DaqId == daq.id) { known = true } } return known } /** * Verifica se a lista de DAQ's está vazia * * @returns Boolean * * # Exemplos * * ```js * DAQList.isEmpty() ? console.log("Não tem DAQ!") : console.log("Tem DAQ!") * ``` */ static isEmpty() { return this.List.length == 0 } static async waitDAQConnection() { const start = parseInt(performance.now()) while (true) { if (parseInt(performance.now() - start) > DAQList.MAX_CONNECTION_TIMEOUT) { return undefined } else { if (this.List.length > 0 && this.List[0].usbState.value) { return this.List[0] } } await this.delay(100) } } static delay(time) { return new Promise(resolve => setTimeout(resolve, time)) } static { console.log('DAQList is ready!'); DAQList.mount(); window.DAQList = this } } /**@type HardwareDAQ | undefined */ export const DAQ = await DAQList.waitDAQConnection() window.DAQ = DAQ