//build 20240425 //看门狗组件,用于监控应用是否卡死,设置一个超时时间,如果超过这个时间没有喂狗,会自动触发设备重启 //注意使用看门狗之前可能需要先初始化gpio //依赖组件 dxDriver,dxLogger,dxCommon,dxMap,dxGpio import { watchdogClass } from './libvbar-b-dxwatchdog.so' import dxMap from './dxMap.js' import logger from './dxLogger.js' import dxCommon from './dxCommon.js' const map = dxMap.get("___watchdog") const watchdogObj = new watchdogClass(); const watchdog = {} watchdog.last = new Date().getTime() /** * 打开看门狗设备 * @param {number} type 必填 * @param {string} id 句柄id,非必填(若初始化多个实例需要传入唯一id) */ watchdog.open = function (type, id) { let pointer = watchdogObj.open(type) if (pointer === undefined || pointer === null) { throw new Error("watchdog.open: open failed") } dxCommon.handleId("watchdog", id, pointer) } /** * 控制指定通道开关 * @param {number} chan 通道id,必填 * @param {string} id 句柄id,非必填(需保持和init中的id一致) * @returns true/false */ watchdog.enable = function (chan, id) { let pointer = dxCommon.handleId("watchdog", id) return watchdogObj.enable(pointer, chan) } /** * 开启看门狗总定时器 * @param {*} timeout 必填 * @param {string} id 句柄id,非必填(需保持和init中的id一致) * @returns true/false */ watchdog.start = function (timeout, id) { let pointer = dxCommon.handleId("watchdog", id) return watchdogObj.start(pointer, timeout) } /** * 判断是否是上电复位,看门狗是否已经启动 * @param {string} id 句柄id,非必填(需保持和init中的id一致) * @returns true/false */ watchdog.isPoweron = function (id) { let pointer = dxCommon.handleId("watchdog", id) return watchdogObj.isPoweron(pointer) } /** * 喂狗指定通道 * @param {*} chan 通道id,必填 * @param {string} id 句柄id,非必填(需保持和init中的id一致) * @returns true/false */ watchdog.restart = function (chan, id) { let pointer = dxCommon.handleId("watchdog", id) return watchdogObj.restart(pointer, chan) } /** * 关闭看门狗总定时器 * @param {string} id 句柄id,非必填(需保持和init中的id一致) * @returns true/false */ watchdog.stop = function (id) { let pointer = dxCommon.handleId("watchdog", id) return watchdogObj.stop(pointer) } /** * 关闭看门狗设备 * @param {string} id 句柄id,非必填(需保持和init中的id一致) * @returns true/false */ watchdog.close = function (id) { let pointer = dxCommon.handleId("watchdog", id) return watchdogObj.close(pointer) } /** * 循环检查每个线程的喂狗情况,任何一个线程没有喂狗,则不启动restart * @param {number} chan 通道id,必填 * @param {string} id 句柄id,非必填(需保持和init中的id一致) */ watchdog.loop = function (chan, id) { const now = new Date().getTime() const minus = now - watchdog.last if (minus > 3000 || minus < 0) {//每3秒检查一次或者小于0代表操作了往前改时间 watchdog.last = now let keys = map.keys() let check = true for (let i = 0; i < keys.length; i++) { let key = keys[i] let value = map.get(key) const temp = now - value.now if (temp > value.timeout * 1000 && temp < 1700000000) { logger.error(`The worker ${key} did not feed the dog in time.`, temp) check = false break } } if (check) { this.restart(chan, id) } } } /** * 不同的线程喂狗 * @param {string} flag 线程的标识,必填不能为空 * @param {number} timeout 线程可以多长时间不喂狗(秒),缺省是10秒 */ watchdog.feed = function (flag, timeout = 10) { if (!flag || flag.length <= 0) { return } map.put(flag, { now: new Date().getTime(), timeout: timeout }) } export default watchdog;