东丽网口版透析机 socket- server 通讯
chenyc
2025-11-21 128d19e054ee5a8f3125e63c15c0a2804548f295
index.js
@@ -1,10 +1,34 @@
// ✅ 正确写法(适用于 pkg 打包环境)
const fs = require('fs');
const path = require('path');
// 获取 exe 所在目录(兼容 pkg 打包后的 __dirname)
const appPath = process.pkg ? path.dirname(process.execPath) : __dirname;
const mqttConfigPath = path.join(appPath, 'mqtt.json');
const aliyunConfigPath = path.join(appPath, 'aliyun.json');
const mqttConfig = JSON.parse(fs.readFileSync(mqttConfigPath, 'utf8'));
const aliyunConfig=JSON.parse(fs.readFileSync(aliyunConfigPath, 'utf8'))
console.log(aliyunConfig)
const { initMqtt, publishMessage } = require('./mqttClient');
const net = require('net');
const logger = require('./logger');
const EventEmitter = require('events');
const aliyunIot = require('aliyun-iot-device-sdk');
const { getAliyunDeviceSecret } = require('./api');
const toModel = require('./Strholp');
const { publishMessage } = require('./mqttClient');
// 初始化 MQTT(独立于阿里云)
initMqtt(mqttConfig);
// ========== 自定义错误类(可选)==========
class CustomError extends Error {
@@ -159,33 +183,52 @@
    async handleData(deviceId, message) {
        const deviceInfo = this.devices.get(deviceId);
        if (!deviceInfo) return;
        deviceInfo.lastAck = Date.now();
        try {
            const masData = toModel(message);
            deviceInfo.iotDeviceNo = masData.n;
            deviceInfo.masData = masData;
            // ✅【核心改动】收到数据立即发 MQTT(不管阿里云)
            if (mqttConfig.enabled) {
                const topic = `${mqttConfig.defaultTopicPrefix}/${masData.n}`;
                const payload = JSON.stringify({
                    ...masData,
                    deviceId: deviceId,
                    timestamp: new Date().toISOString()
                });
                publishMessage(topic, payload);
                logger.info(`📡 已通过 MQTT 发送数据到 ${topic}`);
            }
            if (deviceInfo.status !== 'valid') {
                deviceInfo.status = 'valid';
                this.emit('validResponse', deviceId);
                logger.info(`${deviceId} 首次有效响应,停止重试`);
                this.stopRetryMechanism(deviceId);
                // 成功后固定使用 'K0000' 保活(建议)
                this.startKeepAlive(deviceId, deviceInfo.lastSignal);
                await this.registerDevice(deviceId);
            // 【可选】仅当阿里云启用时才注册并上报
            if (aliyunConfig.enabled) {
                if (deviceInfo.status !== 'valid') {
                    logger.info(`${deviceId} 阿里云设备状态变为有效`);
                    deviceInfo.status = 'valid';
                    this.stopRetryMechanism(deviceId);
                    logger.info(`${deviceId} 停止重试机制`);
                    this.startKeepAlive(deviceId, deviceInfo.lastSignal);
                    logger.info(`${deviceId} 启动保持连接机制`);
                    await this.registerAliyunDevice(deviceId); // 改名避免混淆
                } else {
                    this.postPropsToAliyun(deviceId);
                }
            } else {
                logger.info(`${deviceId} 已注册,直接上报数据到阿里云`);
                this.postPropsToDevice(deviceId);
                // this.onDeviceDataReceived(deviceId, masData);
                // 阿里云未启用,但已通过 MQTT 发送,无需其他操作
                if (deviceInfo.status !== 'valid') {
                    deviceInfo.status = 'valid';
                    this.stopRetryMechanism(deviceId);
                    this.startKeepAlive(deviceId, deviceInfo.lastSignal);
                    logger.info(`${deviceId} 已完成握手(阿里云未启用)`);
                }
            }
        } catch (err) {
            logger.error(`${deviceId} 处理消息出错:`, err.message);
        }
    }
    async registerDevice(deviceId) {
    async registerAliyunDevice(deviceId) {
        const deviceInfo = this.devices.get(deviceId);
        if (!deviceInfo || deviceInfo.iotDevice) return;
@@ -193,7 +236,7 @@
            logger.info(`${deviceId} 请求三元组,设备号: ${deviceInfo.iotDeviceNo}`);
            const { data } = await getDeviceSYZ(deviceInfo.iotDeviceNo);
            logger.info(`${deviceId} 三元组返回: ${JSON.stringify(data)}`);
            const model=data.data
            const model = data.data
            if (model?.productKey && model?.deviceName && model?.deviceSecret) {
                deviceInfo.iotDevice = aliyunIot.device({
                    ProductKey: model.productKey,
@@ -214,33 +257,18 @@
        }
    }
    postPropsToDevice(deviceId) {
    postPropsToAliyun(deviceId) {
        const deviceInfo = this.devices.get(deviceId);
        if (!deviceInfo?.iotDevice || !deviceInfo.masData) return;
        logger.info(`${deviceId} 阿里云上报属性: ${JSON.stringify(deviceInfo.masData)}`);
        const props = deviceInfo.masData;
        deviceInfo.iotDevice.postProps(props, (res) => {
            if (res?.message === 'success') {
                logger.info(`${deviceId} 上报属性成功`);
                logger.info(`${deviceId} 阿里云上报属性成功`);
            } else {
                logger.error(`${deviceId} 上报属性失败:`, res?.message || 'unknown');
                logger.error(`${deviceId} 阿里云上报属性失败:`, res?.message || 'unknown');
            }
        });
    }
    onDeviceDataReceived(deviceId, data) {
        const topic = `touxiji/${data.n}`;
        const payload = JSON.stringify({
            ...data,
            timestamp: new Date().toISOString()
        });
        try {
            logger.info(`发布 MQTT 消息到主题 ${topic}: ${payload}`);
            publishMessage(topic, payload);
        } catch (error) {
            logger.error(`MQTT 发布失败 ${topic}:`, error.message);
        }
    }
    removeDevice(deviceId) {
@@ -291,5 +319,5 @@
const PORT = process.env.PORT || 10961;
server.listen(PORT, () => {
    logger.info(`Socket 服务已启动,监听端口: ${PORT}`);
    logger.info(`Socket 服务已启动,监听超级端口: ${PORT}`);
});