@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
JavaScript
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