vf107/src/service/mqttService.js
@@ -42,7 +42,7 @@
 */
mqttService.insertPermission = function (event) {
    let payload = JSON.parse(event.payload)
    let data = payload.data
    let data = payload.payload && payload.payload.data ? payload.payload.data : payload.data
    if (data.length > 100) {
        return reply(event, "data length should not be greater than 100", CODE.E_100)
    }
@@ -58,7 +58,7 @@
 */
mqttService.getPermission = function (event) {
    let payload = JSON.parse(event.payload)
    let data = payload.data
    let data = payload.payload && payload.payload.data ? payload.payload.data : payload.data
    let res = api.getPermission(data)
    return reply(event, res)
}
@@ -68,7 +68,7 @@
 */
mqttService.delPermission = function (event) {
    let payload = JSON.parse(event.payload)
    let data = payload.data
    let data = payload.payload && payload.payload.data ? payload.payload.data : payload.data
    let res = api.delPermission(data)
    if (Array.isArray(res)) {
        return reply(event, res, CODE.E_100)
@@ -81,7 +81,7 @@
 */
mqttService.modifyPermission = function (event) {
    let payload = JSON.parse(event.payload)
    let data = payload.data
    let data = payload.payload && payload.payload.data ? payload.payload.data : payload.data
    if (data.length > 100) {
        return reply(event, "data length should not be greater than 100", CODE.E_100)
    }
@@ -111,7 +111,7 @@
 */
mqttService.insertUser = function (event) {
    let payload = JSON.parse(event.payload)
    let data = payload.data
    let data = payload.payload && payload.payload.data ? payload.payload.data : payload.data
    if (data.length > 100) {
        return reply(event, "data length should not be greater than 100", CODE.E_100)
    }
@@ -128,7 +128,7 @@
 */
mqttService.getUser = function (event) {
    let payload = JSON.parse(event.payload)
    let data = payload.data
    let data = payload.payload && payload.payload.data ? payload.payload.data : payload.data
    let res = api.getUser(data)
    return reply(event, res)
}
@@ -138,7 +138,7 @@
 */
mqttService.delUser = function (event) {
    let payload = JSON.parse(event.payload)
    let data = payload.data
    let data = payload.payload && payload.payload.data ? payload.payload.data : payload.data
    let res = api.delUser(data)
    if (Array.isArray(res)) {
        return reply(event, res, CODE.E_100)
@@ -163,7 +163,7 @@
 */
mqttService.modifyUser = function (event) {
    let payload = JSON.parse(event.payload)
    let data = payload.data
    let data = payload.payload && payload.payload.data ? payload.payload.data : payload.data
    if (data.length > 100) {
        return reply(event, "data length should not be greater than 100", CODE.E_100)
    }
@@ -171,7 +171,7 @@
    if (Array.isArray(res)) {
        return reply(event, res, CODE.E_100)
    }
    return reply(event, res)
    return reply(event)
}
// =================================凭证增删改查=================================
@@ -180,7 +180,7 @@
 */
mqttService.insertKey = function (event) {
    let payload = JSON.parse(event.payload)
    let data = payload.data
    let data = payload.payload && payload.payload.data ? payload.payload.data : payload.data
    if (data.length > 100) {
        return reply(event, "data length should not be greater than 100", CODE.E_100)
    }
@@ -196,7 +196,7 @@
 */
mqttService.getKey = function (event) {
    let payload = JSON.parse(event.payload)
    let data = payload.data
    let data = payload.payload && payload.payload.data ? payload.payload.data : payload.data
    let res = api.getKey(data)
    if (typeof res == 'string') {
        return reply(event, res, CODE.E_100)
@@ -209,7 +209,7 @@
 */
mqttService.delKey = function (event) {
    let payload = JSON.parse(event.payload)
    let data = payload.data
    let data = payload.payload && payload.payload.data ? payload.payload.data : payload.data
    let res = api.delKey(data)
    if (Array.isArray(res)) {
        return reply(event, res, CODE.E_100)
@@ -223,7 +223,7 @@
 */
mqttService.clearKey = function (event) {
    let payload = JSON.parse(event.payload)
    let data = payload.data
    let data = payload.payload && payload.payload.data ? payload.payload.data : payload.data
    let ret = api.clearKey(data)
    if (typeof ret == "string") {
        return reply(event, "sql error ret:" + ret, CODE.E_100)
@@ -237,7 +237,7 @@
 */
mqttService.modifyKey = function (event) {
    let payload = JSON.parse(event.payload)
    let data = payload.data
    let data = payload.payload && payload.payload.data ? payload.payload.data : payload.data
    if (data.length > 100) {
        return reply(event, "data length should not be greater than 100", CODE.E_100)
    }
@@ -249,13 +249,163 @@
}
// =================================应急开仓密码增删改查=================================
/**
 * 添加应急开仓密码
 * @param {object} event - MQTT事件对象
 */
mqttService.insertEmergencyPassword = function (event) {
    try {
        logger.info('[mqttService] 接收到insertEmergencyPassword命令:', JSON.stringify(event.topic))
        logger.info('[mqttService] 命令payload:', event.payload)
        let payload = JSON.parse(event.payload)
        let data = payload.payload && payload.payload.data ? payload.payload.data : {}
        logger.info('[mqttService] 解析后的参数:', JSON.stringify(data))
        let res = this.insertEmergencyPasswordAgreement(data)
        if (typeof res == 'string') {
            logger.error('[mqttService] insertEmergencyPassword失败:', res)
            return reply(event, res, CODE.E_100)
        }
        logger.info('[mqttService] insertEmergencyPassword成功')
        return reply(event)
    } catch (error) {
        logger.error('[mqttService] insertEmergencyPassword error:', error)
        return reply(event, { error: error.message }, CODE.E_100)
    }
}
/**
 * 添加应急开仓密码通用协议格式
 * @param {object} data - 应急开仓密码数据对象
 * @returns {boolean|string} true表示成功,string表示错误信息
 */
mqttService.insertEmergencyPasswordAgreement = function (data) {
    // 应急开仓密码在设备中仅有唯一的1个,所以先清空表
    let deleteRet = sqliteService.d1_emergency_password.deleteAll()
    if (deleteRet != 0) {
        return "清空旧密码失败: " + deleteRet
    }
    // 检查密码是否有效
    if (!data.password) {
        return "password cannot be empty"
    }
    // 检查密码长度是否大于等于8位
    if (data.password.length < 8) {
        return "Password length must be at least 8 digits"
    }
    // 构建密码记录
    let record = {}
    record.id = data.id || 'emergency_' + Date.now() // 如果没有id,自动生成
    record.password = data.password
    record.description = "云端下发" // 通过MQTT和HTTP接口设置的应急开仓密码,description填充为"云端下发"
    record.createTime = Date.now()
    record.updateTime = Date.now()
    record.status = data.status || 1
    // 保存密码
    let ret = sqliteService.d1_emergency_password.save(record)
    if (ret == 0) {
        return true
    } else {
        return "sql error ret:" + ret
    }
}
/**
 * 查询应急开仓密码
 * @param {object} event - MQTT事件对象
 */
mqttService.getEmergencyPassword = function (event) {
    try {
        logger.info('[mqttService] 接收到getEmergencyPassword命令:', JSON.stringify(event.topic))
        logger.info('[mqttService] 命令payload:', event.payload)
        let payload = JSON.parse(event.payload)
        let res = this.getEmergencyPasswordAgreement()
        logger.info('[mqttService] 查询结果:', JSON.stringify(res))
        return reply(event, res)
    } catch (error) {
        logger.error('[mqttService] getEmergencyPassword error:', error)
        return reply(event, { error: error.message }, CODE.E_100)
    }
}
/**
 * 查询应急开仓密码通用协议格式
 * @returns {object} 查询结果
 */
mqttService.getEmergencyPasswordAgreement = function () {
    let passwords = sqliteService.d1_emergency_password.findAll()
    if (passwords && passwords.length > 0) {
        let password = passwords[0];
        // 转换时间戳为字符串格式
        if (password.createTime) {
            // 尝试将createTime转换为数字
            const createTimeNum = Number(password.createTime);
            if (!isNaN(createTimeNum)) {
                // 检查时间戳是否为毫秒级(大于等于10位)
                if (createTimeNum.toString().length >= 10) {
                    // 已经是毫秒级,转换为秒级
                    password.createTime = timestampToDateString(createTimeNum / 1000);
                } else {
                    // 秒级,直接使用
                    password.createTime = timestampToDateString(createTimeNum);
                }
            }
        }
        if (password.updateTime) {
            // 尝试将updateTime转换为数字
            const updateTimeNum = Number(password.updateTime);
            if (!isNaN(updateTimeNum)) {
                // 检查时间戳是否为毫秒级(大于等于10位)
                if (updateTimeNum.toString().length >= 10) {
                    // 已经是毫秒级,转换为秒级
                    password.updateTime = timestampToDateString(updateTimeNum / 1000);
                } else {
                    // 秒级,直接使用
                    password.updateTime = timestampToDateString(updateTimeNum);
                }
            }
        }
        return password;
    }
    return {};
}
/**
 * 清空应急开仓密码
 * @param {object} event - MQTT事件对象
 */
mqttService.clearEmergencyPassword = function (event) {
    try {
        logger.info('[mqttService] 接收到clearEmergencyPassword命令:', JSON.stringify(event.topic))
        logger.info('[mqttService] 命令payload:', event.payload)
        let ret = sqliteService.d1_emergency_password.deleteAll()
        if (ret == 0) {
            logger.info('[mqttService] clearEmergencyPassword成功')
            return reply(event)
        } else {
            logger.error('[mqttService] clearEmergencyPassword失败:', "sql error ret:" + ret)
            return reply(event, "sql error ret:" + ret, CODE.E_100)
        }
    } catch (error) {
        logger.error('[mqttService] clearEmergencyPassword error:', error)
        return reply(event, { error: error.message }, CODE.E_100)
    }
}
// =================================密钥增删改查=================================
/**
 * 添加密钥
 */
mqttService.insertSecurity = function (event) {
    let payload = JSON.parse(event.payload)
    let data = payload.data
    let data = payload.payload && payload.payload.data ? payload.payload.data : payload.data
    if (data.length > 100) {
        return reply(event, "data length should not be greater than 100", CODE.E_100)
    }
@@ -271,7 +421,7 @@
 */
mqttService.getSecurity = function (event) {
    let payload = JSON.parse(event.payload)
    let data = payload.data
    let data = payload.payload && payload.payload.data ? payload.payload.data : payload.data
    let res = api.getSecurity(data)
    if (typeof res == 'string') {
        return reply(event, res, CODE.E_100)
@@ -284,7 +434,7 @@
 */
mqttService.delSecurity = function (event) {
    let payload = JSON.parse(event.payload)
    let data = payload.data
    let data = payload.payload && payload.payload.data ? payload.payload.data : payload.data
    let res = api.delSecurity(data)
    if (Array.isArray(res)) {
        return reply(event, res, CODE.E_100)
@@ -304,24 +454,230 @@
    }
}
// =================================应急开仓密码增删改查=================================
/**
 * 添加应急开仓密码
 * @param {object} event - MQTT事件对象
 */
mqttService.insertEmergencyPassword = function (event) {
    try {
        logger.info('[mqttService] 接收到insertEmergencyPassword命令:', JSON.stringify(event.topic))
        logger.info('[mqttService] 命令payload:', event.payload)
        let payload = JSON.parse(event.payload)
        let data = payload.payload && payload.payload.data ? payload.payload.data : {}
        logger.info('[mqttService] 解析后的参数:', JSON.stringify(data))
        let res = this.insertEmergencyPasswordAgreement(data)
        if (typeof res == 'string') {
            logger.error('[mqttService] insertEmergencyPassword失败:', res)
            return reply(event, res, CODE.E_100)
        }
        logger.info('[mqttService] insertEmergencyPassword成功')
        return reply(event)
    } catch (error) {
        logger.error('[mqttService] insertEmergencyPassword error:', error)
        return reply(event, { error: error.message }, CODE.E_100)
    }
}
/**
 * 添加应急开仓密码通用协议格式
 * @param {object} data - 应急开仓密码数据对象
 * @returns {boolean|string} true表示成功,string表示错误信息
 */
mqttService.insertEmergencyPasswordAgreement = function (data) {
    // 应急开仓密码在设备中仅有唯一的1个,所以先清空表
    let deleteRet = sqliteService.d1_emergency_password.deleteAll()
    if (deleteRet != 0) {
        return "清空旧密码失败: " + deleteRet
    }
    // 检查密码是否有效
    if (!data.password) {
        return "password cannot be empty"
    }
    // 检查密码长度是否大于等于8位
    if (data.password.length < 8) {
        return "Password length must be at least 8 digits"
    }
    // 构建密码记录
    let record = {}
    record.id = data.id || 'emergency_' + Date.now() // 如果没有id,自动生成
    record.password = data.password
    record.description = "云端下发" // 通过MQTT和HTTP接口设置的应急开仓密码,description填充为"云端下发"
    record.createTime = Date.now()
    record.updateTime = Date.now()
    record.status = data.status || 1
    // 保存密码
    let ret = sqliteService.d1_emergency_password.save(record)
    if (ret == 0) {
        return true
    } else {
        return "sql error ret:" + ret
    }
}
/**
 * 查询应急开仓密码
 * @param {object} event - MQTT事件对象
 */
mqttService.getEmergencyPassword = function (event) {
    try {
        logger.info('[mqttService] 接收到getEmergencyPassword命令:', JSON.stringify(event.topic))
        logger.info('[mqttService] 命令payload:', event.payload)
        let payload = JSON.parse(event.payload)
        let res = this.getEmergencyPasswordAgreement()
        logger.info('[mqttService] 查询结果:', JSON.stringify(res))
        return reply(event, res)
    } catch (error) {
        logger.error('[mqttService] getEmergencyPassword error:', error)
        return reply(event, { error: error.message }, CODE.E_100)
    }
}
/**
 * 查询应急开仓密码通用协议格式
 * @returns {object} 查询结果
 */
mqttService.getEmergencyPasswordAgreement = function () {
    let passwords = sqliteService.d1_emergency_password.findAll()
    if (passwords && passwords.length > 0) {
        let password = passwords[0];
        // 转换时间戳为字符串格式
        if (password.createTime) {
            // 尝试将createTime转换为数字
            const createTimeNum = Number(password.createTime);
            if (!isNaN(createTimeNum)) {
                // 检查时间戳是否为毫秒级(大于等于10位)
                if (createTimeNum.toString().length >= 10) {
                    // 已经是毫秒级,转换为秒级
                    password.createTime = timestampToDateString(createTimeNum / 1000);
                } else {
                    // 秒级,直接使用
                    password.createTime = timestampToDateString(createTimeNum);
                }
            }
        }
        if (password.updateTime) {
            // 尝试将updateTime转换为数字
            const updateTimeNum = Number(password.updateTime);
            if (!isNaN(updateTimeNum)) {
                // 检查时间戳是否为毫秒级(大于等于10位)
                if (updateTimeNum.toString().length >= 10) {
                    // 已经是毫秒级,转换为秒级
                    password.updateTime = timestampToDateString(updateTimeNum / 1000);
                } else {
                    // 秒级,直接使用
                    password.updateTime = timestampToDateString(updateTimeNum);
                }
            }
        }
        return password;
    }
    return {};
}
/**
 * 清空应急开仓密码
 * @param {object} event - MQTT事件对象
 */
mqttService.clearEmergencyPassword = function (event) {
    try {
        logger.info('[mqttService] 接收到clearEmergencyPassword命令:', JSON.stringify(event.topic))
        logger.info('[mqttService] 命令payload:', event.payload)
        let ret = sqliteService.d1_emergency_password.deleteAll()
        if (ret == 0) {
            logger.info('[mqttService] clearEmergencyPassword成功')
            return reply(event)
        } else {
            logger.error('[mqttService] clearEmergencyPassword失败:', "sql error ret:" + ret)
            return reply(event, "sql error ret:" + ret, CODE.E_100)
        }
    } catch (error) {
        logger.error('[mqttService] clearEmergencyPassword error:', error)
        return reply(event, { error: error.message }, CODE.E_100)
    }
}
/**
 * 远程控制
 * @param {object} event - MQTT事件对象
 */
mqttService.control = function (event) {
    let payload = JSON.parse(event.payload)
    let ret = api.control(payload)
    // 远程抓拍、企业微信解绑,需要等流程完成后才回复,不能立即回复
    if (payload.data.command != 8 && payload.data.command != 11) {
        // 如果是指纹操作,但是设备不支持指纹的话,就直接返回错误
        if(payload.data.command == 12 && !driver.device.finger){
            return reply(event, "finger not supported", CODE.E_100)
        }
        if (typeof ret == "string") {
            return reply(event, "unknown failure", CODE.E_100)
        } else {
    try {
            logger.info('[mqttService] 接收到control命令:', JSON.stringify(event.topic))
            logger.info('[mqttService] 命令payload:', event.payload)
            let payload = JSON.parse(event.payload)
            let data = payload.payload.data || {}
            switch (data.command) {
                case 0:
                    //重启
                    logger.info('[mqttService] 执行重启命令')
                    reply(event)
                    common.asyncReboot(2)
                    return
                case 1:
                    //远程开门
                    logger.info('[mqttService] 执行远程开门命令')
                    driver.gpio.open()
                    break
                case 4:
                    //重置
                    logger.info('[mqttService] 执行重置命令')
                    common.systemBrief("rm -rf /app/data/config/*")
                    common.systemBrief("rm -rf /app/data/db/*")
                    common.systemBrief("rm -rf /app/data/user/*")
                    common.systemBrief("rm -rf /app/data/user/*")
                    common.systemBrief("rm -rf /vgmj.db")
                    reply(event)
                    common.asyncReboot(2)
                    return
                case 5:
                    //播放语音
                    logger.info('[mqttService] 执行播放语音命令')
                    if (data.extra) {
                        let res = common.systemWithRes(`test -e "/app/code/resource/wav/${data.extra.wav}.wav" && echo "OK" || echo "NO"`, 2)
                        if (res.includes('OK')) {
                            driver.alsa.play(`/app/code/resource/wav/${data.extra.wav}.wav`)
                        }
                    }
                    break
                case 6:
                    // 6:屏幕展示图片
                    // TODO
                    logger.info('[mqttService] 执行屏幕展示图片命令')
                    break
                case 7:
                    // 7:屏幕展示文字
                    // TODO
                    logger.info('[mqttService] 执行屏幕展示文字命令')
                    break
                case 10:
                    logger.info('[mqttService] 执行二维码展示命令')
                    if (!isEmpty(data.extra.qrCodeBase64) && typeof data.extra.qrCodeBase64 == 'string') {
                        //base64转图片保存
                        let src = `/app/code/resource/image/app_qrcode.png`
                        std.ensurePathExists(src)
                        common.base64_2binfile(src, data.extra.qrCodeBase64)
                        logger.info('[mqttService] 二维码保存成功')
                        return reply(event)
                    }
                    break
                default:
                    logger.info('[mqttService] 未知命令:', data.command)
                    break
            }
            logger.info('[mqttService] control命令执行完成')
            return reply(event)
        } catch (error) {
            logger.error('[mqttService] control error:', error)
            return reply(event, { error: error.message }, CODE.E_100)
        }
    }
}
/**
@@ -343,7 +699,7 @@
 */
mqttService.setConfig = function (event) {
    let payload = JSON.parse(event.payload)
    let data = payload.data
    let data = payload.payload && payload.payload.data ? payload.payload.data : payload.data
    let res = api.setConfig(data)
    if (typeof res == "string") {
        return reply(event, res, CODE.E_100)
@@ -356,8 +712,9 @@
 * 升级固件
 */
mqttService.upgradeFirmware = function (event) {
    logger.info('[mqttService] 接收到升级固件命令:', JSON.stringify(event.topic))
    let payload = JSON.parse(event.payload)
    let data = payload.data
    let data = payload.payload && payload.payload.data ? payload.payload.data : payload.data
    let res = api.upgradeFirmware(data)
    if (typeof res == "string") {
        return reply(event, res, CODE.E_100)
@@ -371,7 +728,7 @@
 */
mqttService.getRecords = function (event) {
    let payload = JSON.parse(event.payload)
    let data = payload.data
    let data = payload.payload && payload.payload.data ? payload.payload.data : payload.data
    let res = api.getRecords(data, true)
    return reply(event, res)
}
@@ -382,7 +739,7 @@
 */
mqttService.delRecords = function (event) {
    let payload = JSON.parse(event.payload)
    let data = payload.data
    let data = payload.payload && payload.payload.data ? payload.payload.data : payload.data
    let res = api.delRecords(data)
    if (typeof res == 'string') {
        return reply(event, res, CODE.E_100)
@@ -487,6 +844,23 @@
}
mqttService.mqttReply = mqttReply
/**
 * 时间戳转日期字符串
 * @param {number} timestamp - 时间戳(秒级)
 * @returns {string} 日期字符串,格式:YYYY-MM-DD HH:MM:SS
 */
function timestampToDateString(timestamp) {
    const date = new Date(timestamp * 1000);
    const year = date.getFullYear();
    const month = String(date.getMonth() + 1).padStart(2, '0');
    const day = String(date.getDate()).padStart(2, '0');
    const hours = String(date.getHours()).padStart(2, '0');
    const minutes = String(date.getMinutes()).padStart(2, '0');
    const seconds = String(date.getSeconds()).padStart(2, '0');
    return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
mqttService.timestampToDateString = timestampToDateString
// 判空
function isEmpty(value) {
    return value === undefined || value === null || value === ""