Files
luminea2mqtt/src/devicebase.js

130 lines
5.1 KiB
JavaScript

const TuyaDevice = require('tuyapi');
const log4js = require('log4js');
const autodiscover = require('./autodiscover')
const configldr = require('./config')
class DeviceBase {
constructor(deviceconfig, mqtt) {
// setup logger
const loggername = deviceconfig.id ? deviceconfig.id : "undef device"
this.logger = log4js.getLogger(loggername);
this.logger.level = deviceconfig.loglevel;
// check device attributes
if (!deviceconfig.id) {
this.logger.error("missing attribute 'id' in device config")
return
}
if (!deviceconfig.key) {
this.logger.error("missing attribute 'key' in device config")
return
}
// define device vars
this.deviceid = deviceconfig.id // tuya device id
this.devicekey = deviceconfig.key // tuya device key
this.mqtt = mqtt // pointer to mqtt client
// name to be displayed. If not set, default to prefixed tuya client id
this.friendlyname = deviceconfig.friendlyname ? deviceconfig.friendlyname : `luminea2mqtt_${this.deviceid}`
// define queue names. Prefix is set globally. Prefer friendly name. If not set, use client id
this.queue_name = deviceconfig.friendlyname ? deviceconfig.friendlyname : this.deviceid
this.topicname = `${configldr.config.mqtt.prefix}/${this.queue_name}`
this.topic_get = `${configldr.config.mqtt.prefix}/${this.queue_name}/get`
this.topic_set = `${configldr.config.mqtt.prefix}/${this.queue_name}/set`
this.topic_state = `${configldr.config.mqtt.prefix}/${this.queue_name}/state`
this.logger.debug(`use topic (all) : ${this.topicname}`)
this.logger.debug(`use topic (get) : ${this.topic_get}`)
this.logger.debug(`use topic (set) : ${this.topic_set}`)
this.logger.debug(`use topic (state) : ${this.topic_state}`)
this.intervall_refresh = deviceconfig.refresh ? deviceconfig.refresh * 1000 : 10000
this.reconnect_timout = deviceconfig.reconnect ? deviceconfig.reconnect * 1000 : 5000
this.logger.debug(`refresh timer (ms) : ${this.intervall_refresh}`)
this.logger.debug(`reconnect timer (ms) : ${this.reconnect_timout}`)
this.lastdata = {}
// call init function
this.init()
// connect to device
try {
this.device = new TuyaDevice({
id: this.deviceid,
key: this.devicekey,
issueRefreshOnConnect: true,
})
this.device.device.ip = undefined
this.reconnect()
} catch (error) {
this.logger.error(`Cannot connect to ${this.deviceid}`)
this.logger.error(error.message)
}
this.device.on('connected', () => {
this.connected = true
this.logger.info(`Connected to tuya id: ${this.deviceid}, ip: ${this.device.device.ip}, prefix: ${this.topicname}`)
// subscribe to topic
this.mqtt.subscribe(this.topic_set, (err) => {
if (err) {
this.logger.error(`Cannot subscribe to ${this.topic_set}`)
} else {
this.logger.info(`Subscribed to ${this.topic_set}`)
}
});
this.logger.debug(`publish ${this.totopic_statepic_get}: "online"`)
this.mqtt.publish(this.topic_state, "online")
this.startWatcher()
});
this.device.on('disconnected', () => {
this.stopWatcher()
this.logger.info(`Disconnected`)
this.logger.debug(`publish ${this.topic_state}: "offline"`)
this.mqtt.publish(this.topic_state, "offline")
setTimeout(() => this.reconnect(), this.reconnect_timout)
this.device.device.ip = undefined // will error without? WHY???
});
this.device.on('error', error => {
this.stopWatcher()
setTimeout(() => this.reconnect(), this.reconnect_timout)
});
}
pushAutodiscover(config){
if (configldr.config.autodiscover.enabled){
autodiscover.publishDevice(this.deviceid,this.friendlyname,config)
}
}
reconnect() {
this.device.find().then(el => {
if (el) {
this.device.connect().catch(el => {
console.log(this.device)
this.logger.debug("Reconnect failed: device offline")
})
} else {
this.logger.debug("Reconnect failed: device offline")
setTimeout(() => this.reconnect(), this.reconnect_timout)
}
}).catch(el => {
this.logger.debug("Reconnect failed: device timed out")
setTimeout(() => this.reconnect(), this.reconnect_timout)
})
}
disconnect() {
this.connected = false
this.stopWatcher()
this.device.disconnect()
this.logger.info(`Disconnected for id: ${this.deviceid}`)
this.reconnect = () => { } // prevent reconnect on exit
}
}
module.exports = DeviceBase