2025年8月21日星期四

吉利银河任务脚本(2025年8月版)

1.购买服务器阿里云:服务器购买地址https://t.aliyun.com/U/W9mv4W若失效,可用地址

1.购买服务器

阿里云:

服务器购买地址

https://t.aliyun.com/U/W9mv4W

若失效,可用地址

https://www.aliyun.com/minisite/goods?source=5176.29345612&userCode=49hts92d

腾讯云:

https://curl.qcloud.com/wJpWmSfU

若失效,可用地址

https://cloud.tencent.com/act/cps/redirect?redirect=2446&cps_key=ad201ee2ef3b771157f72ee5464b1fea&from=console

华为云

https://activity.huaweicloud.com/cps.html?fromacct=64b5cf7cc11b4840bb4ed2ea0b2f4468&utm_source=V1g3MDY4NTY=&utm_medium=cps&utm_campaign=201905

2.部署教程

2024年最新青龙面板跑脚本教程(一)持续更新中

3.代码如下

let Notify = 0let defaultRunAll = false;  // 默认执行模式:false 表示默认只执行信息获取,true 表示默认执行所有功能let defaultEnableMqtt = true// 默认MQTT模式:false 表示默认不启动MQTT监听,true 表示默认启动let showInfoLogs = false// 控制是否在执行功能时显示信息获取相关的日志,默认如果执行功能则不显示const ckName = "jlyh";const $ = new Env("吉利银河");let msg = "";
// MQTT配置const mqttConfig = {    host'mqtt://192.168.0.5'// MQTT服务器地址    port1884,                 // MQTT服务器端口    username'',               // MQTT用户名    password'',               // MQTT密码    clientId'jlyh_geely_galaxy'// 固定客户端ID    updateInterval60         // MQTT状态更新间隔,单位:秒};
class UserInfo {
    // 车主信息相关变量构造    constructor(str) {        this.ckStatus = true;        this.token = '';        this.refreshToken = str.split('&')[0]; // 分隔符        this.articleId = '';        this.deviceSN = str.split('&')[1];        this.switchStatus = {};  // 用于存储所有功能开关状态        this.vehicleInfo = {};   // 用于存储车辆信息        this.vehicleStatus = {}; // 用于存储车辆状态信息        this.firstTokenRefresh = true// 添加标记,用于跟踪是否是首次刷新token        // 功能名称映射        this.featureNames = {            'sign''签到',            'opensentry''打开哨兵',            'closesentry''关闭哨兵',            'opendoor''打开车锁',            'closedoor''关闭车锁',            'search''闪灯鸣笛',            'windowslightopen''微开车窗',            'windowfullopen''全开车窗',            'windowclose''关闭车窗',            'sunroofopen''打开天窗',            'sunroofclose''关闭天窗',            'sunshadeopen''打开遮阳帘',            'sunshadeclose''关闭遮阳帘',            'purifieropen''打开净化',            'purifierclose''关闭净化',            'defrostopen''打开除霜',            'defrostclose''关闭除霜',            'aconopen''打开空调',            'aconclose''关闭空调',            'rapidheat''极速升温',            'rapidcool''极速降温'            // 如果要新增功能,在这里添加新功能的映射即可,不添加则会直接显示函数名        };        // 功能开关状态映射        this.switchStatusNames = {            'vstdModeStatus': { name'哨兵模式' },            'strangerModeActive': { name'陌生人预警' },            'campingModeActive': { name'露营模式' },            'jouIntVal': { name'智能巡航' },            'copActive': { name'舒适泊车' },            'parkingComfortStatus': { name'泊车舒适性' },            'ldacStatus': { name'高清音频' },            'driftModeActive': { name'漂移模式' },            'carLocatorStatUploadEn': { name'车辆定位' },            'prkgCameraActive': { name'泊车影像' }        };        // 车辆信息映射        this.vehicleInfoNames = {            'vin': { name'车架号' },            'seriesNameVs': { name'车型' },            'colorCode': { name'车身颜色' },            'engineNo': { name'电机编号' }        };        // 车辆状态映射        this.vehicleStatusNames = {            basicVehicleStatus: {                name'基础状态',                fields: {                    distanceToEmptyOnBatteryOnly: { name'续航里程'formatv => `${v}公里` },                    odometer: { name'总里程'formatv => `${Math.round(v)}公里` },                    usageMode: { name'使用模式'formatv => v === '1' ? '正常模式' : `模式${v}` }                }            },            vehicleLocationStatus: {                name'位置信息',                fields: {                    longitude: { name'经度'formatv => (v / 3600000).toFixed(6) },                    latitude: { name'纬度'formatv => (v / 3600000).toFixed(6) },                    altitude: { name'海拔'formatv => `${v}米` }                }            },            vehicleMaintainStatus: {                name'保养信息',                fields: {                    distanceToService: { name'剩余保养里程'formatv => `${v}公里` },                    daysToService: { name'剩余保养天数'formatv => `${v}天` }                }            },            vehicleRunningStatus: {                name'行驶状态',                fields: {                    speed: { name'当前速度'formatv => `${v}km/h` },                    avgSpeed: { name'近期平均速度'formatv => `${v}km/h` },                    averPowerConsumption: { name'近期平均能耗'formatv => `${v}kWh/100km` },                    tripMeter1: { name'行程1'formatv => `${v}km` },                    tripMeter2: { name'行程2'formatv => `${v}km` },                    averTraPowerConsumption: { name'行程平均能耗'formatv => `${v}kWh/100km` },                    electricParkBrakeStatus: { name'电子手刹'formatv => v === 1 ? '启用' : '未启用' },                    gearAutoStatus: { name'自动挡位'formatv => v }                }            },
            vehicleEnvironmentStatus: {                name'环境状态',                fields: {                    interiorTemp: { name'车内温度'formatv => `${v}°C` },                    exteriorTemp: { name'车外温度'formatv => `${v}°C` },                    interiorPM25Level: { name'车内PM2.5'formatv => `${v}μg/m³` }                }            },            vehicleBatteryStatus: {                name'电池状态',                fields: {                    chargeLevel: { name'当前电量'formatv => `${v}%` },                    timeToFullyCharged: { name'充满时间'formatv => v === '2047' ? '未充电' : `${(v/60).toFixed(1)}小时` },                    dcChargeIAct: { name'充电电流'formatv => `${v}A` }                }            },            vehicleDoorCoverStatus: {                name'车门状态',                fields: {                    doorLockStatusDriver: { name'门锁'formatv => v === '2' ? '已锁定' : '已解锁' },                    sunroofStatus: { name'天窗状态'formatv => v === '1' ? '打开' : '关闭' },                    sunshadeStatus: { name'遮阳帘状态'formatv => v === '1' ? '打开' : '关闭' },                    trunkLockStatus: { name'后备箱锁'formatv => v === '1' ? '解锁' : '锁定' }                }            },            vehicleEngineStatus: {                name'电机状态',                fields: {                    engineStatus: { name'电机'formatv => v === 'engine-off' ? '关闭' : '开启' }                }            },            vehicleClimateStatus: {                name'空调状态',                fields: {                    preClimateActive: { name'空调'formatv => v ? '开启' : '关闭' },                    defrostActive: { name'除霜'formatv => v ? '开启' : '关闭' },                    airBlowerActive: { name'净化'formatv => v ? '开启' : '关闭' }                }            }        };        this.mqttClient = null// 添加MQTT客户端实例变量
        // 添加状态检测映射        this.statusChecks = {            sentry() => this.switchStatus.vstdModeStatus === '1',            door() => this.vehicleStatus.vehicleDoorCoverStatus?.doorLockStatusDriver === '1',  // 1表示解锁(ON),2表示锁定(OFF)            ac() => this.vehicleStatus.vehicleClimateStatus?.preClimateActive === true,            defrost() => this.vehicleStatus.vehicleClimateStatus?.defrostActive === true,            purifier() => this.vehicleStatus.vehicleClimateStatus?.airBlowerActive === true,            sunroof() => this.vehicleStatus.vehicleDoorCoverStatus?.sunroofStatus === '1',  // 1表示打开(ON),2表示关闭(OFF)            sunshade() => this.vehicleStatus.vehicleDoorCoverStatus?.sunshadeStatus === '1'  // 1表示打开(ON),2表示关闭(OFF)        };    }
    // *********************************************************    // 加密解密等后端功能相关
    // 获取UTC时间    formatDate(date, hourOffset = 0, minuteOffset = 0) {        const daysOfWeek = ['Sun''Mon''Tue''Wed''Thu''Fri''Sat'];        const months = ['Jan''Feb''Mar''Apr''May''Jun''Jul''Aug''Sep''Oct''Nov''Dec'];        const adjustedDate = new Date(date);        adjustedDate.setUTCHours(adjustedDate.getUTCHours() + hourOffset);        adjustedDate.setUTCMinutes(adjustedDate.getUTCMinutes() + minuteOffset);        const dayOfWeek = daysOfWeek[adjustedDate.getUTCDay()];        const day = ('0' + adjustedDate.getUTCDate()).slice(-2);        const month = months[adjustedDate.getUTCMonth()];        const year = adjustedDate.getUTCFullYear();        const hours = ('0' + adjustedDate.getUTCHours()).slice(-2);        const minutes = ('0' + adjustedDate.getUTCMinutes()).slice(-2);        const seconds = ('0' + adjustedDate.getUTCSeconds()).slice(-2);        return `${dayOfWeek} ${month} ${day} ${year} ${hours}:${minutes}:${seconds} GMT`;    }
    // 请求头加密参数处理    calculateHmacSha256(method, accept, content_md5, content_type, date, key, nonce, timestamp, path) {        const crypto = require('crypto');        // 构建待加密的字符串        let e = `POST\n` +// method            `application/json; charset=utf-8\n` +// accept            `9qH9eCwn+tkcAKIMmnzdnQ==\n` +// content_md5            `application/json; charset=utf-8\n` +// content_type            `Thu, 13 Jul 2023 01:27:46 GMT\n` +// date            `x-ca-key:204453306\n` +            `x-ca-nonce:a2b33525-ca82-4e3a-b7ff-643f1775a999\n` +// nonce            `x-ca-timestamp:1689211666058\n` +// timestamp            `/app/v1/version/checkVersion`// path        let ee = `${method}\n` +// method            `${accept}\n` +// accept            `${content_md5}\n` +// content_md5            `${content_type}\n` +// content_type            `${date}\n` +// date            `x-ca-key:${key}\n` +            `x-ca-nonce:${nonce}\n` +// nonce            `x-ca-timestamp:${timestamp}\n` +// timestamp            `${path}`// path          // console.log(ee);
        // app的Key对应的不同加密编码        let sercetKey        if (key == 204453306) {            sercetKey = `uUwSi6m9m8Nx3Grx7dQghyxMpOXJKDGu`        } else if (key == 204373120) {            sercetKey = `XfH7OiOe07vorWwvGQdCqh6quYda9yGW`        } else if (key == 204167276) {            sercetKey = `5XfsfFBrUEF0fFiAUmAFFQ6lmhje3iMZ`        } else if (key == 204168364) {            sercetKey = `NqYVmMgH5HXol8RB8RkOpl8iLCBakdRo`        } else if (key == 204179735) {            sercetKey = `UhmsX3xStU4vrGHGYtqEXahtkYuQncMf`        }        // 生成 HMAC-SHA256 加密结果          const hmacSha256 = crypto.createHmac('sha256', sercetKey);        hmacSha256.update(ee);        const encryptedData = hmacSha256.digest();        // 返回 Base64 编码的结果        // console.log(`加密结果` + encryptedData.toString('base64'));        return encryptedData.toString('base64');    }
    // UUID生成    generateUUID() {        const alphanumeric = "0123456789abcdef";        const sections = [844412];        let uuid = "";        for (let i = 0; i < sections.length; i++) {            for (let j = 0; j < sections[i]; j++) {                uuid += alphanumeric[Math.floor(Math.random() * alphanumeric.length)];            }            if (i !== sections.length - 1) {                uuid += "-";            }        }        return uuid;    }
    // Post请求构建    getPostHeader(key, path, body) {        const crypto = require('crypto');        function calculateContentMD5(requestBody) {            // 将请求体内容转换为字节数组            const byteArray = Buffer.from(requestBody, 'utf8');            // 计算字节数组的MD5摘要            const md5Digest = crypto.createHash('md5').update(byteArray).digest();            // 将MD5摘要转换为Base64编码的字符串            const md5Base64 = md5Digest.toString('base64');            // 返回Content-MD5值            return md5Base64;        }        let currentDate = new Date();        let formattedDate = this.formatDate(currentDate, 0); // 格林尼治时间  如果是8则是北京时间        // console.log(formattedDate);        let parts = formattedDate.split(" ");        formattedDate = `${parts[0]}${parts[2]} ${parts[1]} ${parts[3]} ${parts[4]} GMT`;        let date = new Date(formattedDate)        let timestamp = date.getTime(); // 获取时间戳        // console.log(timestamp);        let content_md5 = calculateContentMD5(body);        let uuid = this.generateUUID();        let signature = this.calculateHmacSha256("POST""application/json; charset=utf-8", content_md5, "application/json; charset=utf-8", formattedDate, key, uuid, timestamp, path)        let headers = {            'date': formattedDate,            'x-ca-signature': signature,            'x-ca-appcode''SWGeelyCode',            'x-ca-nonce': uuid,            'x-ca-key': key,            'ca_version'1,            'accept''application/json; charset=utf-8',            'usetoken'1,            'content-md5': content_md5,            'x-ca-timestamp': timestamp,            'x-ca-signature-headers''x-ca-nonce,x-ca-timestamp,x-ca-key',            'x-refresh-token'true,            'user-agent''ALIYUN-ANDROID-UA',            'token'this.token,            'deviceSN'this.deviceSN,            'txCookie''',            'appId''galaxy-app',            'appVersion''1.27.0',            'platform''Android',            'Cache-Control''no-cache',            'sweet_security_info''{"appVersion":"1.27.0","platform":"android"}' ,            'methodtype''6',            'contenttype''application/json',            'Content-Type''application/json; charset=utf-8',           'Content-Length''87',            'Connection''Keep-Alive',            'Accept-Encoding''gzip',

        }        if (key == 204179735) {            // 安卓端            headers["usetoken"] = true            headers["host"] = `galaxy-user-api.geely.com`            delete headers["x-refresh-token"]            headers["taenantid"] = 569001701001            headers["svcsid"] = ""        } else {            // h5端            headers["usetoken"] = 1            headers["host"] = `galaxy-app.geely.com`            headers["x-refresh-token"] = true        }        return headers;
    }
    // Get请求构建    getGetHeader(key, path) {        let currentDate = new Date();        let formattedDate = this.formatDate(currentDate, 0); // 格林尼治时间  如果是8则是北京时间        // console.log(formattedDate);        let parts = formattedDate.split(" ");        formattedDate = `${parts[0]}${parts[2]} ${parts[1]} ${parts[3]} ${parts[4]} GMT`;        let date = new Date(formattedDate)        let timestamp = date.getTime(); // 获取时间戳        // console.log(timestamp);        let uuid = this.generateUUID();        let signature = this.calculateHmacSha256("GET""application/json; charset=utf-8""""application/x-www-form-urlencoded; charset=utf-8", formattedDate, key, uuid, timestamp, path)        let headers = {            'date': formattedDate,            'x-ca-signature': signature,            'x-ca-nonce': uuid,            'x-ca-key': key,            'ca_version'1,            'accept''application/json; charset=utf-8',            'usetoken'1,            'x-ca-timestamp': timestamp,            'x-ca-signature-headers''x-ca-nonce,x-ca-timestamp,x-ca-key',            'x-refresh-token'true,            'content-type''application/x-www-form-urlencoded; charset=utf-8',            'user-agent''ALIYUN-ANDROID-UA',            'token'this.token,// '',            'deviceSN'this.deviceSN,            'txCookie''',            'appId''galaxy-app',            'appVersion''1.27.0',            'platform''Android',            'Cache-Control''no-cache',            'Connection''Keep-Alive',            'Accept-Encoding''gzip',
        }        if (key == 204179735) {            // 安卓端            headers["usetoken"] = true            headers["host"] = `galaxy-user-api.geely.com`            delete headers["x-refresh-token"]            headers["taenantid"] = 569001701001            headers["svcsid"] = ""        } else {            headers["usetoken"] = 1            headers["host"] = `galaxy-app.geely.com`            headers["x-refresh-token"] = true
        }        return headers
    }
    /**     * -------主函数-------     */    async main(features = []) {        $.DoubleLog(`⌛️ ${new Date().toLocaleString('en-GB', { timeZone: 'Asia/Shanghai', hour12: false }).replace(',''').slice(016).replace(/-/g, '/')}`);        // 设置是否显示信息获取日志        showInfoLogs = this.shouldShowInfoLogs(features);        // 检查是否需要启动MQTT        const isMqttMode = features.length === 0 ? defaultEnableMqtt : features.length === 1 && features.includes('mqtt');        // 如果参数包含info,则只执行信息获取        if (features.includes('info')) {            features = [];  // 清空功能列表,只执行信息获取        }        // 否则,按照defaultRunAll的设置处理        else if (features.length === 0 && defaultRunAll) {            features = ['all'];        }        // 显示运行功能说明        this.logRunningFeatures(features);        // 刷新token并获取基本信息        await this.refresh_token();        if (!this.ckStatus) {            $.DoubleLog(`❌账号CK失效`);            Notify = 1;            return;        }        // 获取各种车辆信息        await this.getVehicleInfo();        // 根据配置决定是否初始化MQTT连接        if (isMqttMode) {            await this.initMqtt();            // 保持脚本运行            return new Promise(() => {                $.DoubleLog(`✅MQTT监听已启动,等待命令中...`);            });        }        // 执行功能        await this.executeFeatures(features);    }
    // 记录运行的功能    logRunningFeatures(features) {        if (features.length === 0) {            $.DoubleLog(`🔄 正在获取车辆信息`);        } else if (features.includes('all')) {            $.DoubleLog(`🔄 正在运行全部功能`);        } else {            const runningFeatures = features                .map(f => this.featureNames[f.toLowerCase()] || f)                .filter(name => name);            if (runningFeatures.length > 0) {                $.DoubleLog(`🔄 正在运行${runningFeatures.join('、')}功能`);            }        }    }
    // 获取车辆信息    async getVehicleInfo() {        // 只在显示信息日志时显示分割线        if (showInfoLogs) {            $.DoubleLog(`🚗🚗🚗🚗🚗🚗🚗🚗🚗🚗`);        }        await this.mylist();        // 获取车辆信息        await this.controlstatus(); // 获取车辆状态信息        await this.switchstatus();  // 获取车辆功能开关信息    }
    // 执行功能    async executeFeatures(features) {        if (features.length === 0) {            return// 如果是仅查询信息,直接返回        }        $.DoubleLog(`🚗🚗🚗🚗🚗🚗🚗🚗🚗🚗`);        if (features.includes('all')) {            $.DoubleLog(`🔄 正在执行所有功能...`);            await this.sign();            await this.opensentry();            // 只在MQTT启用时发送状态            if (defaultEnableMqtt || features.includes('mqtt')) {                await this.sendVehicleStatusMqtt();            }        } else {            $.DoubleLog(`🔄 正在执行功能...`);            for (const feature of features) {                const methodName = feature.toLowerCase();                if (methodName && typeof this[methodName] === 'function') {                    await this[methodName]();                    // 只在MQTT启用且执行特定功能时发送状态                    if ((defaultEnableMqtt || features.includes('mqtt')) && ['controlstatus''info'].includes(methodName)) {                        await this.sendVehicleStatusMqtt();                    }                } else {                    $.DoubleLog(`❌未知的功能参数: ${feature}`);                    Notify = 1;                }            }        }    }
    // *********************************************************    // 信息获取类函数
    // 刷新Key函数    async refresh_token() {        try {            let options = {                url`https://www.galaxy-geely.com/api/v1/login/refresh?refreshToken=${this.refreshToken}`,                headersthis.getGetHeader(204179735`/api/v1/login/refresh?refreshToken=${this.refreshToken}`),            },                result = await httpRequest(options);
            if (result.code == 'success') {                // 简化成功消息,不再输出token详情                this.ckStatus = true;                this.token = result.data.centerTokenDto.token;
                // 只在首次刷新token时显示日志                if (this.firstTokenRefresh) {                    const randomId = Math.random().toString(36).substring(210) + Math.random().toString(36).substring(210);                    $.DoubleLog(`✅接口调用成功: ${randomId}`);                    $.DoubleLog(`🆗刷新KEY:${result.data.centerTokenDto.refreshToken}`);                    this.firstTokenRefresh = false// 标记已经不是首次刷新了                }            } else {                $.DoubleLog(`❌ ${result.message}`);                this.ckStatus = false;                console.log(result);                Notify = 1;            }        } catch (e) {            console.log(e)        }    }
    //获取车辆信息函数    async mylist() {        try {            // 准备请求体            const body = {};
            // 使用getPostHeader生成请求头            let options = {                url`https://www.galaxy-geely.com/vc/app/v1/vehicle/control/myList`,                headersthis.getPostHeader(204373120`/vc/app/v1/vehicle/control/myList`JSON.stringify(body)),                bodyJSON.stringify(body)            };
            let result = await httpRequest(options);
            if (result.code == 0) {                if (showInfoLogs) $.DoubleLog(`✅获取车辆基本信息成功!`);                // 显示原始返回信息                if (showInfoLogs) $.DoubleLog(`🔍车辆信息原始数据: ${JSON.stringify(result.data)}`);
                if (result.data && result.data.length > 0) {                    this.vehicleInfo = result.data[0];  // 保存车辆信息
                    // 格式化显示车辆信息                    if (showInfoLogs) {                        $.DoubleLog(`🚗车辆基本信息:`);                        for (const [key, value] of Object.entries(this.vehicleInfoNames)) {                            if (this.vehicleInfo[key]) {                                $.DoubleLog(`  ${value.name}${this.vehicleInfo[key]}`);                            }                        }                    }                } else {                    $.DoubleLog(`❌获取车辆信息失败,未找到车辆数据!`);                    Notify = 1;                }            } else {                $.DoubleLog(`❌获取车辆基本信息失败!`);                console.log("⚠️失败原因:", result);                Notify = 1;            }        } catch (e) {            console.log(e);        }    }
    // 查询车辆状态函数    async controlstatus() {        try {            // 准备请求体            const body = {                "clientType"2,                "statusType""local",                "dataTypeList": [                    "all"                ],                "vin"this.vehicleInfo.vin            };            // 使用getPostHeader生成请求头            let options = {                url`https://www.galaxy-geely.com/vc/app/v1/vehicle/control/status`,                headersthis.getPostHeader(204373120`/vc/app/v1/vehicle/control/status`JSON.stringify(body)),                bodyJSON.stringify(body)            };
            let result = await httpRequest(options);
            if (result.code == 0) {                if (showInfoLogs) $.DoubleLog(`✅查询车辆状态成功!`);                // 显示原始返回信息                if (showInfoLogs) $.DoubleLog(`🔍车辆状态原始数据: ${JSON.stringify(result.data)}`);
                // 保存车辆状态信息                this.vehicleStatus = result.data;
                // 格式化显示车辆状态信息                if (showInfoLogs) {                    for (const [category, config] of Object.entries(this.vehicleStatusNames)) {                        if (this.vehicleStatus[category]) {                            $.DoubleLog(`📱${config.name}:`);                            for (const [field, fieldConfig] of Object.entries(config.fields)) {                                const value = this.vehicleStatus[category][field];                                if (value !== undefined && value !== '') {                                    $.DoubleLog(`  ${fieldConfig.name}${fieldConfig.format(value)}`);                                }                            }                        }                    }                }            } else {                $.DoubleLog(`❌查询车辆状态失败!`);                console.log("⚠️失败原因:", result);                Notify = 1;            }        } catch (e) {            console.log(e);        }    }
    // 查询车辆功能开关函数    async switchstatus() {        try {            // 通用的状态配置            const commonStatus = {                status: {'0''关闭''1''开启'},                isEnabled(value) => value === '1'            };
            // 准备请求体            const body = {                "clientType"2,                "udid"null,                "vin"this.vehicleInfo.vin            };            // 使用getPostHeader生成请求头            let options = {                url`https://www.galaxy-geely.com/vc/app/v1/vehicle/switch/status`,                headersthis.getPostHeader(204373120`/vc/app/v1/vehicle/switch/status`JSON.stringify(body)),                bodyJSON.stringify(body)            };
            // 查询车辆功能开关            let result = await httpRequest(options);
            if (result.code == 0) {                if (showInfoLogs) $.DoubleLog(`✅查询车辆功能开关成功!`);                // 显示原始返回信息                if (showInfoLogs) $.DoubleLog(`🔍功能开关原始数据: ${JSON.stringify(result.data)}`);
                // 保存所有功能开关状态                this.switchStatus = result.data;
                // 格式化显示功能开关状态                if (showInfoLogs) {                    $.DoubleLog(`📱功能开关状态:`);                    for (const [key, value] of Object.entries(result.data)) {                        if (this.switchStatusNames[key]) {                            const statusInfo = { ...this.switchStatusNames[key], ...commonStatus };                            $.DoubleLog(`  ${statusInfo.name}${statusInfo.status[value] || value}`);                        }                    }                }            } else {                $.DoubleLog(`❌查询车辆功能开关失败!`);                console.log("⚠️失败原因:",result);                Notify = 1;            }        } catch (e) {            console.log(e);        }    }
    //查询积分函数    async points() {        try {            let options = {                url`https://www.galaxy-geely.com/h5/v1/points/get`,                headersthis.getGetHeader(204453306`/h5/v1/points/get`),            },                result = await httpRequest(options);            // console.log(options);            // console.log(result);            if (result.code == 0) {                $.DoubleLog(`✅剩余积分: ${result.data.availablePoints}`);            } else {                $.DoubleLog(`❌剩余积分查询: 失败`);                console.log(result);                Notify = 1;            }        } catch (e) {            console.log(e);        }    }

    // 签到状态查询函数    async signstate() {        try {            let options = {                url`https://www.galaxy-geely.com/app/v1/sign/state`,                headersthis.getGetHeader(204453306`/app/v1/sign/state`),            };
            // 执行签到状态查询请求            let result = await httpRequest(options);
            if (result.code == 0) {                if (result.data === true) {                    $.DoubleLog(`✅今日已经签到啦!`);                    return true;                } else {                    return false;                }            } else {                $.DoubleLog(`❌查询签到状态失败!`);                console.log("⚠️失败原因:", result);                Notify = 1;                return false;            }        } catch (e) {            console.log(e);            return false;        }    }
    // *********************************************************    // 功能完成类函数
    //签到函数    async sign() {        try {            // 先检查签到状态            const hasSignedToday = await this.signstate();            if (hasSignedToday) {                // 即使已经签到,也查询一下积分                await this.points();                return;            }
            // 准备请求体            const body = {                "signType"0            };
            // 使用getPostHeader生成请求头            let options = {                url`https://www.galaxy-geely.com/app/v1/sign/add`,                headersthis.getPostHeader(204453306`/app/v1/sign/add`JSON.stringify(body)),                bodyJSON.stringify(body)            };
            // 执行签到请求            let result = await httpRequest(options);
            // 检查返回结果            if (result.code == 0) {                $.DoubleLog(`✅签到成功!`);                // 签到成功后查询积分                await this.points();                Notify = 1;            } else {                $.DoubleLog(`❌签到失败!`);                console.log("⚠️失败原因:", result);                Notify = 1;            }        } catch (e) {            console.log(e);        }    }

    //打开哨兵模式函数    async opensentry() {        try {            // 检查哨兵模式是否已开启            if (this.switchStatus.vstdModeStatus === '1') {                $.DoubleLog(`ℹ️哨兵模式开着呢!`);                return;            }
            // 从车辆状态中获取电量            const batteryLevel = parseFloat(this.vehicleStatus.vehicleBatteryStatus?.chargeLevel || 0);            if (batteryLevel <= 20) {                $.DoubleLog(`ℹ️电量低,别开哨兵了!`);                return;            }
            // 准备请求体            const body = {                "clientType"2,                "command""1",                "password"null,                "tspUid"null,                "type"6,                "udId"null,                "vin"this.vehicleInfo.vin            };
            // 使用getPostHeader生成请求头            let options = {                url`https://galaxy-geely.com/vc/app/v1/vehicle/control/switch`,                headersthis.getPostHeader(204373120`/vc/app/v1/vehicle/control/switch`JSON.stringify(body)),                bodyJSON.stringify(body)            };
            // 执行哨兵请求            let result = await httpRequest(options);
            if (result.code == 0) {                $.DoubleLog(`✅打开哨兵模式成功!`);                Notify = 1;            } else {                $.DoubleLog(`❌打开哨兵模式失败!`);                console.log("⚠️失败原因:", result);                Notify = 1;            }        } catch (e) {            console.log(e);        }    }
    //关闭哨兵模式函数    async closesentry() {        try {            // 准备请求体            const body = {                "clientType"2,                "command""2",                "password"null,                "tspUid"null,                "type"6,                "udId"null,                "vin"this.vehicleInfo.vin            };
            // 使用getPostHeader生成请求头            let options = {                url`https://galaxy-geely.com/vc/app/v1/vehicle/control/switch`,                headersthis.getPostHeader(204373120`/vc/app/v1/vehicle/control/switch`JSON.stringify(body)),                bodyJSON.stringify(body)            };
            // 执行关闭哨兵请求            let result = await httpRequest(options);
            if (result.code == 0) {                $.DoubleLog(`✅关闭哨兵模式成功!`);                Notify = 1;            } else {                $.DoubleLog(`❌关闭哨兵模式失败!`);                console.log("⚠️失败原因:", result);                Notify = 1;            }        } catch (e) {            console.log(e);        }    }
    //车锁控制通用函数    async controlDoor(action) {        try {            // 根据动作设置参数            const params = {                'opendoor': { type1name'打开' },                'closedoor': { type2name'关闭' }            }[action];
            if (!params) {                $.DoubleLog(`❌无效的车锁控制命令!`);                return;            }
            // 准备请求体            const body = {                "clientType"2,                "lockPassword"null,                "password"null,                "platform""2.0",                "position"0,                "target"null,                "type": params.type,                "udId"null,                "vin"this.vehicleInfo.vin            };
            // 使用getPostHeader生成请求头            let options = {                url`https://galaxy-geely.com/vc/app/v1/vehicle/control/door`,                headersthis.getPostHeader(204373120`/vc/app/v1/vehicle/control/door`JSON.stringify(body)),                bodyJSON.stringify(body)            };
            // 执行车锁控制请求            let result = await httpRequest(options);
            if (result.code == 0) {                $.DoubleLog(`✅${params.name}车锁成功!`);                Notify = 1;            } else {                $.DoubleLog(`❌${params.name}车锁失败!`);                console.log("⚠️失败原因:", result);                Notify = 1;            }        } catch (e) {            console.log(e);        }    }
    //打开车锁函数    async opendoor() {await this.controlDoor('opendoor');}    //关闭车锁函数    async closedoor() {await this.controlDoor('closedoor');}
    //闪灯鸣笛函数    async search() {        try {            // 准备请求体            const body = {                "clientType"2,                "password"null,                "platform""2.0",                "udId"null,                "value""3",                "vin"this.vehicleInfo.vin            };
            // 使用getPostHeader生成请求头            let options = {                url`https://galaxy-geely.com/vc/app/v1/vehicle/control/search`,                headersthis.getPostHeader(204373120`/vc/app/v1/vehicle/control/search`JSON.stringify(body)),                bodyJSON.stringify(body)            };
            // 执行闪灯鸣笛请求            let result = await httpRequest(options);
            if (result.code == 0) {                $.DoubleLog(`✅闪灯鸣笛执行成功!`);                Notify = 1;            } else {                $.DoubleLog(`❌闪灯鸣笛执行失败!`);                console.log("⚠️失败原因:", result);                Notify = 1;            }        } catch (e) {            console.log(e);        }    }
    //车窗控制通用函数    async controlWindow(action) {        try {            // 根据动作设置参数            const params = {                'windowslightopen': { position: [4], type1name'微开车窗' },                'windowfullopen': { position: [1], type1name'全开车窗' },                'windowclose': { position: [1], type2name'关闭车窗' },                'sunroofopen': { position: [2], type1name'打开天窗' },                'sunroofclose': { position: [2], type2name'关闭天窗' },                'sunshadeopen': { position: [3], type1name'打开遮阳帘' },                'sunshadeclose': { position: [3], type2name'关闭遮阳帘' }            }[action];
            if (!params) {                $.DoubleLog(`❌无效的车窗控制命令!`);                return;            }
            // 准备请求体            const body = {                "clientType"2,                "password"null,                "percent"null,                "platform""2.0",                "position": params.position,                "type": params.type,                "udId"null,                "vin"this.vehicleInfo.vin            };
            // 使用getPostHeader生成请求头            let options = {                url`https://galaxy-geely.com/vc/app/v1/vehicle/control/window`,                headersthis.getPostHeader(204373120`/vc/app/v1/vehicle/control/window`JSON.stringify(body)),                bodyJSON.stringify(body)            };
            // 执行车窗控制请求            let result = await httpRequest(options);
            if (result.code == 0) {                $.DoubleLog(`✅${params.name}执行成功!`);                Notify = 1;            } else {                $.DoubleLog(`❌${params.name}执行失败!`);                console.log("⚠️失败原因:", result);                Notify = 1;            }        } catch (e) {            console.log(e);        }    }
    // 微开车窗函数    async windowslightopen() {await this.controlWindow('windowslightopen');}    // 全开车窗函数    async windowfullopen() {await this.controlWindow('windowfullopen');}    // 关闭车窗函数    async windowclose() {await this.controlWindow('windowclose');}    // 打开天窗函数    async sunroofopen() {await this.controlWindow('sunroofopen');}    // 关闭天窗函数    async sunroofclose() {await this.controlWindow('sunroofclose');}    // 打开遮阳帘函数    async sunshadeopen() {await this.controlWindow('sunshadeopen');}    // 关闭遮阳帘函数    async sunshadeclose() {await this.controlWindow('sunshadeclose');}
    //空气净化控制通用函数    async controlPurifier(action) {        try {            // 根据动作设置参数            const params = {                'purifieropen': { type1name'打开' },                'purifierclose': { type2name'关闭' }            }[action];
            if (!params) {                $.DoubleLog(`❌无效的净化控制命令!`);                return;            }
            // 准备请求体            const body = {                "clientType"2,                "conditioner"null,                "dayOfWeek"null,                "duration"null,                "endTimeOfDay"null,                "heat"null,                "level"null,                "password"null,                "platform""2.0",                "scheduledTime"null,                "startTimeOfDay"null,                "target"null,                "temp"null,                "timerId"null,                "type": params.type,                "udId"null,                "ventilation"99,                "vin"this.vehicleInfo.vin            };
            // 使用getPostHeader生成请求头            let options = {                url`https://galaxy-geely.com/vc/app/v1/vehicle/control/noEngine`,                headersthis.getPostHeader(204373120`/vc/app/v1/vehicle/control/noEngine`JSON.stringify(body)),                bodyJSON.stringify(body)            };
            // 执行净化控制请求            let result = await httpRequest(options);
            if (result.code == 0) {                $.DoubleLog(`✅${params.name}净化成功!`);                Notify = 1;            } else {                $.DoubleLog(`❌${params.name}净化失败!`);                console.log("⚠️失败原因:", result);                Notify = 1;            }        } catch (e) {            console.log(e);        }    }
    // 打开净化函数    async purifieropen() {await this.controlPurifier('purifieropen');}    // 关闭净化函数    async purifierclose() {await this.controlPurifier('purifierclose');}
    //空调控制通用函数(包括除霜和空调)    async controlClimate(action, temperature = 25) {        try {            // 根据动作设置参数            const params = {                'defrostopen': { type1conditioner2name'打开除霜' },                'defrostclose': { type2conditioner2name'关闭除霜' },                'aconopen': { type1conditioner1name'打开空调' },                'aconclose': { type2conditioner1name'关闭空调' }            }[action];
            if (!params) {                $.DoubleLog(`❌无效的空调控制命令!`);                return;            }
            // 准备请求体            const body = {                "clientType"2,                "conditioner": params.conditioner,                "dayOfWeek"null,                "duration"90,                "endTimeOfDay"null,                "heat"null,                "heatLevel"null,                "password"null,                "platform""2.0",                "scheduledTime"null,                "startTimeOfDay"null,                "temp": temperature.toString(),                "timerId"null,                "type": params.type,                "udId"null,                "ventilation"null,                "ventilationLevel"null,                "vin"this.vehicleInfo.vin            };
            // 使用getPostHeader生成请求头            let options = {                url`https://galaxy-geely.com/vc/app/v1/vehicle/control/climate`,                headersthis.getPostHeader(204373120`/vc/app/v1/vehicle/control/climate`JSON.stringify(body)),                bodyJSON.stringify(body)            };
            // 执行空调控制请求            let result = await httpRequest(options);
            if (result.code == 0) {                $.DoubleLog(`✅${params.name}成功!${action === 'aconopen' ? `温度设置为${temperature}°C` : ''}`);                if (action === 'aconopen') {                    this.acTemp = temperature;  // 保存设置的温度                }                Notify = 1;            } else {                $.DoubleLog(`❌${params.name}失败!`);                console.log("⚠️失败原因:", result);                Notify = 1;            }        } catch (e) {            console.log(e);        }    }
    // 打开空调函数    async aconopen(temperature = null) {        await this.controlClimate('aconopen', temperature || this.acTemp || 25);    }
    // 关闭空调函数    async aconclose() {        await this.controlClimate('aconclose');    }
    // 打开除霜函数    async defrostopen() {        await this.controlClimate('defrostopen');    }
    // 关闭除霜函数    async defrostclose() {        await this.controlClimate('defrostclose');    }
    //温度控制通用函数    async controlTemperature(action) {        try {            // 根据动作设置参数            const params = {                'rapidheat': {                     type3,                    temp28.5,                    heat: [12],                    heatValue3,                    ventilationnull,                    ventilationValuenull,                    name'极速升温'                },                'rapidcool': {                     type3,                    temp15.5,                    heatnull,                    heatValuenull,                    ventilation: [12],                    ventilationValue3,                    name'极速降温'                }            }[action];
            if (!params) {                $.DoubleLog(`❌无效的温度控制命令!`);                return;            }
            // 准备请求体            const body = {                "clientType"2,                "dayOfWeek"null,                "duration"90,                "paa"0,                "paaAc"true,                "paaAcTemp": params.temp,                "paaHeat": params.heat,                "paaHeatValue": params.heatValue,                "paaSw"null,                "paaVentilation": params.ventilation,                "paaVentilationValue": params.ventilationValue,                "paaVlt": params.ventilation !== null,                "paaVltDuration"60,                "paaVltPos"null,                "password"null,                "platform""2.0",                "scheduledTime"Date.now(),                "startTimeOfDay"null,                "timerActivation"null,                "timerId"null,                "type": params.type,                "udId"null,                "vin"this.vehicleInfo.vin            };
            // 使用getPostHeader生成请求头            let options = {                url`https://galaxy-geely.com/vc/app/v1/vehicle/control/temperature`,                headersthis.getPostHeader(204373120`/vc/app/v1/vehicle/control/temperature`JSON.stringify(body)),                bodyJSON.stringify(body)            };
            // 执行温度控制请求            let result = await httpRequest(options);
            if (result.code == 0) {                $.DoubleLog(`✅${params.name}成功!`);                Notify = 1;            } else {                $.DoubleLog(`❌${params.name}失败!`);                console.log("⚠️失败原因:", result);                Notify = 1;            }        } catch (e) {            console.log(e);        }    }
    // 极速升温函数    async rapidheat() {        await this.controlTemperature('rapidheat');    }
    // 极速降温函数    async rapidcool() {        await this.controlTemperature('rapidcool');    }
    // 判断是否显示信息获取日志的函数    shouldShowInfoLogs(features) {        return (features.length === 0 || features.includes('info')) && !features.includes('mqtt');    }
    // MQTT消息发送函数    async sendMqttMessage(topic, message) {        try {            if (!this.mqttClient) {                await this.initMqtt();            }
            return new Promise((resolve, reject) => {                this.mqttClient.publish(topic, JSON.stringify(message), (err) => {                    if (err) {                        $.DoubleLog(`❌MQTT消息发送失败: ${err.message}`);                        reject(err);                    } else {                        //$.DoubleLog(`✅MQTT消息发送成功: ${topic}`);                        resolve();                    }                });            });        } catch (e) {            $.DoubleLog(`❌MQTT错误: ${e.message}`);            console.log(e);        }    }
    // 发送车辆状态到MQTT    async sendVehicleStatusMqtt() {        // 如果MQTT未启用,直接返回        if (!defaultEnableMqtt && !process.argv.slice(2).includes('mqtt')) {            return;        }        try {            if (!this.vehicleStatus) {                $.DoubleLog(`❌没有车辆状态数据可发送`);                return;            }
            // 准备传感器数据            const sensorData = {                temperaturethis.vehicleStatus.vehicleEnvironmentStatus?.interiorTemp,                exterior_temperaturethis.vehicleStatus.vehicleEnvironmentStatus?.exteriorTemp,                batterythis.vehicleStatus.vehicleBatteryStatus?.chargeLevel,                pm25this.vehicleStatus.vehicleEnvironmentStatus?.interiorPM25Level,                mileageMath.round(this.vehicleStatus.basicVehicleStatus?.odometer),                rangethis.vehicleStatus.basicVehicleStatus?.distanceToEmptyOnBatteryOnly,                longitudeparseFloat((this.vehicleStatus.vehicleLocationStatus?.longitude / 3600000).toFixed(6)),                latitudeparseFloat((this.vehicleStatus.vehicleLocationStatus?.latitude / 3600000).toFixed(6)),                charging_timethis.vehicleStatus.vehicleBatteryStatus?.timeToFullyCharged === '2047' ? 0 : parseFloat((this.vehicleStatus.vehicleBatteryStatus?.timeToFullyCharged / 60).toFixed(1)),                // 使用统一的状态检测方法                sentry_modethis.checkStatus('sentry'),                door_statethis.checkStatus('door'),                ac_statethis.checkStatus('ac'),                defrost_statethis.checkStatus('defrost'),                purifier_statethis.checkStatus('purifier'),                sunroof_statethis.checkStatus('sunroof'),                sunshade_statethis.checkStatus('sunshade'),                ac_tempthis.acTemp || 25,  // 添加空调温度状态
                // 添加新的状态字段                usage_modethis.vehicleStatus.basicVehicleStatus?.usageMode,                current_speedthis.vehicleStatus.vehicleRunningStatus?.speed,                e_brake_statusthis.vehicleStatus.vehicleRunningStatus?.electricParkBrakeStatus,                gear_statusthis.vehicleStatus.vehicleRunningStatus?.gearAutoStatus,                trip_power_consumptionthis.vehicleStatus.vehicleRunningStatus?.averTraPowerConsumption,                avg_power_consumptionthis.vehicleStatus.vehicleRunningStatus?.averPowerConsumption,
                // 添加电机状态和后备箱锁状态                engine_statusthis.vehicleStatus.vehicleEngineStatus?.engineStatus,                trunk_lock_statusthis.vehicleStatus.vehicleDoorCoverStatus?.trunkLockStatus            };
            // 保存最后的传感器数据用于后续更新            this.lastSensorData = sensorData;
            // 发送状态数据            const stateTopic = `homeassistant/sensor/geely_${this.vehicleInfo.vin}/state`;            await this.sendMqttMessage(stateTopic, sensorData);
            // 发送位置数据            const locationData = {                latitude: sensorData.latitude,                longitude: sensorData.longitude,                gps_accuracy100,                battery_level: sensorData.battery            };            const locationTopic = `homeassistant/device_tracker/geely_${this.vehicleInfo.vin}/state`;            // 直接发送对象,不要再次使用 JSON.stringify            await this.sendMqttMessage(locationTopic, locationData);
            // 设备追踪器配置            const deviceTrackerConfig = {                name"车辆位置",                unique_id`geely_${this.vehicleInfo.vin}_tracker`,                state_topic`homeassistant/device_tracker/geely_${this.vehicleInfo.vin}/state`,                json_attributes_topic`homeassistant/device_tracker/geely_${this.vehicleInfo.vin}/state`,                payload_home"home",                payload_not_home"not_home",                source_type"gps",                icon"mdi:car",                device: {                    identifiers: [`geely_${this.vehicleInfo.vin}`],                    name"吉利银河",                    modelthis.vehicleInfo.seriesNameVs,                    manufacturer"Geely"                }            };
            // 发送设备追踪器配置时,确保 payload 是 JSON 格式            const trackerConfigTopic = `homeassistant/device_tracker/geely_${this.vehicleInfo.vin}/config`;            await this.sendMqttMessage(trackerConfigTopic, deviceTrackerConfig);
            // 添加传感器配置            const sensorConfigs = {                temperature: {                    name"车内温度",                    state_topic`homeassistant/sensor/geely_${this.vehicleInfo.vin}/state`,                    value_template"{{ value_json.temperature }}",                    unit_of_measurement"°C",                    unique_id`geely_${this.vehicleInfo.vin}_temperature`,                    device: {                        identifiers: [`geely_${this.vehicleInfo.vin}`],                        name"吉利银河",                        modelthis.vehicleInfo.seriesNameVs,                        manufacturer"Geely"                    }                },                exterior_temperature: {                    name"车外温度",                    state_topic`homeassistant/sensor/geely_${this.vehicleInfo.vin}/state`,                    value_template"{{ value_json.exterior_temperature }}",                    unit_of_measurement"°C",                    unique_id`geely_${this.vehicleInfo.vin}_exterior_temperature`,                    device: {                        identifiers: [`geely_${this.vehicleInfo.vin}`]                    }                },                battery: {                    name"电池电量",                    state_topic`homeassistant/sensor/geely_${this.vehicleInfo.vin}/state`,                    value_template"{{ value_json.battery }}",                    unit_of_measurement"%",                    unique_id`geely_${this.vehicleInfo.vin}_battery`,                    device: {                        identifiers: [`geely_${this.vehicleInfo.vin}`]                    }                },                pm25: {                    name"车内PM2.5",                    state_topic`homeassistant/sensor/geely_${this.vehicleInfo.vin}/state`,                    value_template"{{ value_json.pm25 }}",                    unit_of_measurement"μg/m³",                    unique_id`geely_${this.vehicleInfo.vin}_pm25`,                    device: {                        identifiers: [`geely_${this.vehicleInfo.vin}`]                    }                },                mileage: {                    name"总里程",                    state_topic`homeassistant/sensor/geely_${this.vehicleInfo.vin}/state`,                    value_template"{{ value_json.mileage }}",                    unit_of_measurement"km",                    unique_id`geely_${this.vehicleInfo.vin}_mileage`,                    device: {                        identifiers: [`geely_${this.vehicleInfo.vin}`]                    }                },                range: {                    name"续航里程",                    state_topic`homeassistant/sensor/geely_${this.vehicleInfo.vin}/state`,                    value_template"{{ value_json.range }}",                    unit_of_measurement"km",                    unique_id`geely_${this.vehicleInfo.vin}_range`,                    device: {                        identifiers: [`geely_${this.vehicleInfo.vin}`]                    }                },                charging_time: {                    name"充满时间",                    state_topic`homeassistant/sensor/geely_${this.vehicleInfo.vin}/state`,                    value_template"{{ value_json.charging_time }}",                    unit_of_measurement"h",                    unique_id`geely_${this.vehicleInfo.vin}_charging_time`,                    device: {                        identifiers: [`geely_${this.vehicleInfo.vin}`]                    }                },                location: {                    name"车辆位置",                    state_topic`homeassistant/sensor/geely_${this.vehicleInfo.vin}/state`,                    value_template"{{ value_json.latitude }},{{ value_json.longitude }}",                    unique_id`geely_${this.vehicleInfo.vin}_location`,                    device: {                        identifiers: [`geely_${this.vehicleInfo.vin}`]                    }                },                // 添加新的传感器配置                usage_mode: {                    name"使用模式",                    state_topic`homeassistant/sensor/geely_${this.vehicleInfo.vin}/state`,                    value_template"{{ value_json.usage_mode }}",                    unique_id`geely_${this.vehicleInfo.vin}_usage_mode`,                    device: {                        identifiers: [`geely_${this.vehicleInfo.vin}`]                    }                },                current_speed: {                    name"当前车速",                    state_topic`homeassistant/sensor/geely_${this.vehicleInfo.vin}/state`,                    value_template"{{ value_json.current_speed }}",                    unit_of_measurement"km/h",                    unique_id`geely_${this.vehicleInfo.vin}_current_speed`,                    device: {                        identifiers: [`geely_${this.vehicleInfo.vin}`]                    }                },                e_brake_status: {                    name"电子手刹状态",                    state_topic`homeassistant/sensor/geely_${this.vehicleInfo.vin}/state`,                    value_template"{{ value_json.e_brake_status }}",                    unique_id`geely_${this.vehicleInfo.vin}_e_brake_status`,                    device: {                        identifiers: [`geely_${this.vehicleInfo.vin}`]                    }                },                gear_status: {                    name"挡位状态",                    state_topic`homeassistant/sensor/geely_${this.vehicleInfo.vin}/state`,                    value_template"{{ value_json.gear_status }}",                    unique_id`geely_${this.vehicleInfo.vin}_gear_status`,                    device: {                        identifiers: [`geely_${this.vehicleInfo.vin}`]                    }                },                trip_power_consumption: {                    name"行程平均能耗",                    state_topic`homeassistant/sensor/geely_${this.vehicleInfo.vin}/state`,                    value_template"{{ value_json.trip_power_consumption }}",                    unit_of_measurement"kWh/100km",                    unique_id`geely_${this.vehicleInfo.vin}_trip_power_consumption`,                    device: {                        identifiers: [`geely_${this.vehicleInfo.vin}`]                    }                },                avg_power_consumption: {                    name"近期平均能耗",                    state_topic`homeassistant/sensor/geely_${this.vehicleInfo.vin}/state`,                    value_template"{{ value_json.avg_power_consumption }}",                    unit_of_measurement"kWh/100km",                    unique_id`geely_${this.vehicleInfo.vin}_avg_power_consumption`,                    device: {                        identifiers: [`geely_${this.vehicleInfo.vin}`]                    }                },                engine_status: {                    name"电机状态",                    state_topic`homeassistant/sensor/geely_${this.vehicleInfo.vin}/state`,                    value_template"{{ value_json.engine_status }}",                    unique_id`geely_${this.vehicleInfo.vin}_engine_status`,                    device: {                        identifiers: [`geely_${this.vehicleInfo.vin}`]                    }                },                trunk_lock_status: {                    name"后备箱锁状态",                    state_topic`homeassistant/sensor/geely_${this.vehicleInfo.vin}/state`,                    value_template"{{ value_json.trunk_lock_status }}",                    unique_id`geely_${this.vehicleInfo.vin}_trunk_lock_status`,                    device: {                        identifiers: [`geely_${this.vehicleInfo.vin}`]                    }                }            };
            // 发送传感器配置            for (const [sensorName, config] of Object.entries(sensorConfigs)) {                const configTopic = `homeassistant/sensor/geely_${this.vehicleInfo.vin}/${sensorName}/config`;                await this.sendMqttMessage(configTopic, config);            }
            // 添加空调温度滑动条配置            const climateConfigs = {                ac_temp: {                    name"空调温度",                    command_topic`homeassistant/number/geely_${this.vehicleInfo.vin}/ac_temp/set`,                    state_topic`homeassistant/sensor/geely_${this.vehicleInfo.vin}/state`,                    value_template"{{ value_json.ac_temp }}",                    min16,                    max32,                    step0.5,                    unit_of_measurement"°C",                    unique_id`geely_${this.vehicleInfo.vin}_ac_temp`,                    device: {                        identifiers: [`geely_${this.vehicleInfo.vin}`],                        name"吉利银河",                        modelthis.vehicleInfo.seriesNameVs,                        manufacturer"Geely"                    }                }            };
            // 发送空调温度滑动条配置            for (const [name, config] of Object.entries(climateConfigs)) {                const configTopic = `homeassistant/number/geely_${this.vehicleInfo.vin}/${name}/config`;                await this.sendMqttMessage(configTopic, config);            }
            // 添加开关配置            const switchConfigs = {                sentry: {                    name"哨兵模式",                    command_topic`homeassistant/switch/geely_${this.vehicleInfo.vin}/sentry/set`,                    state_topic`homeassistant/sensor/geely_${this.vehicleInfo.vin}/state`,                    value_template"{{ value_json.sentry_mode }}",                    payload_on"ON",                    payload_off"OFF",                    state_on"ON",                    state_off"OFF",                    unique_id`geely_${this.vehicleInfo.vin}_sentry`,                    device: {                        identifiers: [`geely_${this.vehicleInfo.vin}`],                        name"吉利银河",                        modelthis.vehicleInfo.seriesNameVs,                        manufacturer"Geely"                    }                },                door: {                    name"车门锁",                    command_topic`homeassistant/switch/geely_${this.vehicleInfo.vin}/door/set`,                    state_topic`homeassistant/sensor/geely_${this.vehicleInfo.vin}/state`,                    value_template"{{ value_json.door_state }}",                    payload_on"ON",                    payload_off"OFF",                    state_on"ON",                    state_off"OFF",                    unique_id`geely_${this.vehicleInfo.vin}_door`,                    device: {                        identifiers: [`geely_${this.vehicleInfo.vin}`]                    }                },                ac: {                    name"空调",                    command_topic`homeassistant/switch/geely_${this.vehicleInfo.vin}/ac/set`,                    state_topic`homeassistant/sensor/geely_${this.vehicleInfo.vin}/state`,                    value_template"{{ value_json.ac_state }}",                    payload_on"ON",                    payload_off"OFF",                    state_on"ON",                    state_off"OFF",                    unique_id`geely_${this.vehicleInfo.vin}_ac`,                    device: {                        identifiers: [`geely_${this.vehicleInfo.vin}`]                    }                },                defrost: {                    name"除霜",                    command_topic`homeassistant/switch/geely_${this.vehicleInfo.vin}/defrost/set`,                    state_topic`homeassistant/sensor/geely_${this.vehicleInfo.vin}/state`,                    value_template"{{ value_json.defrost_state }}",                    payload_on"ON",                    payload_off"OFF",                    state_on"ON",                    state_off"OFF",                    unique_id`geely_${this.vehicleInfo.vin}_defrost`,                    device: {                        identifiers: [`geely_${this.vehicleInfo.vin}`]                    }                },                purifier: {                    name"空气净化",                    command_topic`homeassistant/switch/geely_${this.vehicleInfo.vin}/purifier/set`,                    state_topic`homeassistant/sensor/geely_${this.vehicleInfo.vin}/state`,                    value_template"{{ value_json.purifier_state }}",                    payload_on"ON",                    payload_off"OFF",                    state_on"ON",                    state_off"OFF",                    unique_id`geely_${this.vehicleInfo.vin}_purifier`,                    device: {                        identifiers: [`geely_${this.vehicleInfo.vin}`]                    }                },                sunroof: {                    name"天窗",                    command_topic`homeassistant/switch/geely_${this.vehicleInfo.vin}/sunroof/set`,                    state_topic`homeassistant/sensor/geely_${this.vehicleInfo.vin}/state`,                    value_template"{{ value_json.sunroof_state }}",                    payload_on"ON",                    payload_off"OFF",                    state_on"ON",                    state_off"OFF",                    unique_id`geely_${this.vehicleInfo.vin}_sunroof`,                    device: {                        identifiers: [`geely_${this.vehicleInfo.vin}`]                    }                },                sunshade: {                    name"遮阳帘",                    command_topic`homeassistant/switch/geely_${this.vehicleInfo.vin}/sunshade/set`,                    state_topic`homeassistant/sensor/geely_${this.vehicleInfo.vin}/state`,                    value_template"{{ value_json.sunshade_state }}",                    payload_on"ON",                    payload_off"OFF",                    state_on"ON",                    state_off"OFF",                    unique_id`geely_${this.vehicleInfo.vin}_sunshade`,                    device: {                        identifiers: [`geely_${this.vehicleInfo.vin}`]                    }                }            };
            // 发送开关配置            for (const [switchName, config] of Object.entries(switchConfigs)) {                const configTopic = `homeassistant/switch/geely_${this.vehicleInfo.vin}/${switchName}/config`;                await this.sendMqttMessage(configTopic, config);
            }
            // 添加按钮配置            const buttonConfigs = {                rapidheat: {                    name"极速升温",                    command_topic`homeassistant/button/geely_${this.vehicleInfo.vin}/rapidheat/press`,                    unique_id`geely_${this.vehicleInfo.vin}_rapidheat`,                    device: {                        identifiers: [`geely_${this.vehicleInfo.vin}`],                        name"吉利银河",                        modelthis.vehicleInfo.seriesNameVs,                        manufacturer"Geely"                    }                },                rapidcool: {                    name"极速降温",                    command_topic`homeassistant/button/geely_${this.vehicleInfo.vin}/rapidcool/press`,                    unique_id`geely_${this.vehicleInfo.vin}_rapidcool`,                    device: {                        identifiers: [`geely_${this.vehicleInfo.vin}`]                    }                },                search: {                    name"闪灯鸣笛",                    command_topic`homeassistant/button/geely_${this.vehicleInfo.vin}/search/press`,                    unique_id`geely_${this.vehicleInfo.vin}_search`,                    device: {                        identifiers: [`geely_${this.vehicleInfo.vin}`]                    }                },                windowslightopen: {                    name"微开车窗",                    command_topic`homeassistant/button/geely_${this.vehicleInfo.vin}/windowslightopen/press`,                    unique_id`geely_${this.vehicleInfo.vin}_windowslightopen`,                    device: {                        identifiers: [`geely_${this.vehicleInfo.vin}`]                    }                },                windowfullopen: {                    name"全开车窗",                    command_topic`homeassistant/button/geely_${this.vehicleInfo.vin}/windowfullopen/press`,                    unique_id`geely_${this.vehicleInfo.vin}_windowfullopen`,                    device: {                        identifiers: [`geely_${this.vehicleInfo.vin}`]                    }                },                windowclose: {                    name"关闭车窗",                    command_topic`homeassistant/button/geely_${this.vehicleInfo.vin}/windowclose/press`,                    unique_id`geely_${this.vehicleInfo.vin}_windowclose`,                    device: {                        identifiers: [`geely_${this.vehicleInfo.vin}`]                    }                }            };
            // 发送按钮配置            for (const [buttonName, config] of Object.entries(buttonConfigs)) {                const configTopic = `homeassistant/button/geely_${this.vehicleInfo.vin}/${buttonName}/config`;                await this.sendMqttMessage(configTopic, config);            }
            // 删除成功日志,将由updateAndSendStatus统一输出        } catch (e) {            $.DoubleLog(`❌发送车辆状态到MQTT失败: ${e.message}`);            console.log(e);        }    }
    // 初始化MQTT连接    async initMqtt() {        try {            if (this.mqttClient) {                // 如果已经有连接,先断开旧连接                this.mqttClient.end(true);                await new Promise(resolve => setTimeout(resolve, 1000));                this.mqttClient = null;                $.DoubleLog(`🔄断开旧MQTT连接,准备重新连接`);            }
            const mqtt = require('mqtt');
            // 添加基础的重连配置            const connectConfig = {                port: mqttConfig.port,                username: mqttConfig.username,                password: mqttConfig.password,                clientId: mqttConfig.clientId// 固定使用配置中的客户端ID                reconnectPeriod5000,   // 重连间隔5秒                cleantrue,             // 清除会话                connectTimeout10000,   // 连接超时时间                rejectUnauthorizedfalse // 不验证服务器证书            };
            // 输出连接信息            $.DoubleLog(`🔄正在连接MQTT服务器: ${mqttConfig.host}:${mqttConfig.port}`);            $.DoubleLog(`🔑使用客户端ID: ${mqttConfig.clientId}`);
            this.mqttClient = mqtt.connect(mqttConfig.host, connectConfig);
            // 连接成功事件            this.mqttClient.on('connect'async () => {                $.DoubleLog(`✅MQTT连接成功`);
                // 订阅主题                const topics = [                    `homeassistant/switch/geely_${this.vehicleInfo.vin}/+/set`,                    `homeassistant/button/geely_${this.vehicleInfo.vin}/+/press`,                    `homeassistant/number/geely_${this.vehicleInfo.vin}/ac_temp/set`                ];
                topics.forEach(topic => {                    this.mqttClient.subscribe(topic, (err) => {                        if (err) {                            $.DoubleLog(`❌MQTT订阅失败: ${err.message}`);                        } else {                            $.DoubleLog(`✅MQTT订阅成功: ${topic}`);                        }                    });                });
                // 立即执行一次状态更新                await this.updateAndSendStatus();                // 启动定时更新                this.startStatusUpdateInterval();            });
            // 重连事件            this.mqttClient.on('reconnect'() => {                $.DoubleLog(`🔄MQTT正在重连...使用客户端ID: ${mqttConfig.clientId}`);            });
            // 错误处理            this.mqttClient.on('error'(err) => {                $.DoubleLog(`❌MQTT连接错误: ${err.message}`);            });
            // 断开连接处理            this.mqttClient.on('close'() => {                $.DoubleLog(`MQTT连接关闭`);
                // 清理定时器                if (this.statusUpdateInterval) {                    clearInterval(this.statusUpdateInterval);                    this.statusUpdateInterval = null;                }            });
            // 连接结束事件            this.mqttClient.on('end'() => {                $.DoubleLog(`MQTT连接已结束`);                this.mqttClient = null;            });
            // 消息处理(保持原有逻辑)            this.mqttClient.on('message'async (topic, message) => {                try {                    const topicParts = topic.split('/');                    const deviceType = topicParts[1];  // 'switch' 或 'button' 或 'number'                    const command = topicParts[3];     // 命令类型                    const action = topicParts[4];      // 'set' 或 'press'                    const state = message.toString();
                    // 处理温度设置                    if (deviceType === 'number' && command === 'ac_temp' && action === 'set') {                        const temp = parseFloat(state);                        if (!isNaN(temp) && temp >= 16 && temp <= 32) {                            this.acTemp = temp;  // 保存设置的温度                            $.DoubleLog(`✅空调温度设置为: ${temp}°C`);
                            // 如果空调已开启,则使用新温度重新设置                            if (this.vehicleStatus.vehicleClimateStatus?.preClimateActive) {                                await this.aconopen(temp);                            }
                            // 更新状态                            const sensorTopic = `homeassistant/sensor/geely_${this.vehicleInfo.vin}/state`;                            await this.sendMqttMessage(sensorTopic, {                                ...this.lastSensorData,                                ac_temp: temp                            });                        }                        return;                    }
                    // 处理按钮按下事件                    if (deviceType === 'button' && action === 'press') {                        let success = false;                        switch(command) {                            case 'rapidheat':                                await this.rapidheat();                                success = true;                                break;                            case 'rapidcool':                                await this.rapidcool();                                success = true;                                break;                            case 'search':                                await this.search();                                success = true;                                break;                            case 'windowslightopen':                                await this.windowslightopen();                                success = true;                                break;                            case 'windowfullopen':                                await this.windowfullopen();                                success = true;                                break;                            case 'windowclose':                                await this.windowclose();                                success = true;                                break;                        }
                        if (success) {                            $.DoubleLog(`✅按钮命令执行成功: ${command}`);                            // 重新启动状态更新定时器                            await this.startStatusUpdateInterval();
                            // 等待车辆状态更新                            await new Promise(resolve => setTimeout(resolve, 2000));                            // 更新并发送状态                            await this.updateAndSendStatus();                        }                        return;                    }
                    // 原有的开关处理逻辑保持不变                    if (deviceType === 'switch' && action === 'set') {                        // ... 现有的开关处理代码 ...                    }
                    // 刷新token                    await this.refresh_token();                    if (!this.ckStatus) {                        $.DoubleLog(`❌账号CK失效,无法执行命令`);                        return;                    }
                    // 执行命令                    let success = false;                    if (state === 'ON') {                        switch(command) {                            case 'sentry':                                await this.opensentry();                                success = true;                                break;                            case 'door':                                await this.opendoor();                                success = true;                                break;                            case 'ac':                                await this.aconopen();                                success = true;                                break;                            case 'defrost':                                await this.defrostopen();                                success = true;                                break;                            case 'purifier':                                await this.purifieropen();                                success = true;                                break;                            case 'sunroof':                                await this.sunroofopen();                                success = true;                                break;                            case 'sunshade':                                await this.sunshadeopen();                                success = true;                                break;                        }                    } else if (state === 'OFF') {                        switch(command) {                            case 'sentry':                                await this.closesentry();                                success = true;                                break;                            case 'door':                                await this.closedoor();                                success = true;                                break;                            case 'ac':                                await this.aconclose();                                success = true;                                break;                            case 'defrost':                                await this.defrostclose();                                success = true;                                break;                            case 'purifier':                                await this.purifierclose();                                success = true;                                break;                            case 'sunroof':                                await this.sunroofclose();                                success = true;                                break;                            case 'sunshade':                                await this.sunshadeclose();                                success = true;                                break;                        }                    }
                    if (success) {                        $.DoubleLog(`✅命令执行成功: ${command} ${state}`);                        // 重新启动状态更新定时器                        await this.startStatusUpdateInterval();
                        // 更新传感器状态                        const sensorTopic = `homeassistant/sensor/geely_${this.vehicleInfo.vin}/state`;                        const currentStatus = {                            // 使用统一的状态检测方法,但当前命令使用临时状态                            sentry_mode: command === 'sentry' ? state : this.checkStatus('sentry'),                            door_state: command === 'door' ? state : this.checkStatus('door'),                            ac_state: command === 'ac' ? state : this.checkStatus('ac'),                            defrost_state: command === 'defrost' ? state : this.checkStatus('defrost'),                            purifier_state: command === 'purifier' ? state : this.checkStatus('purifier'),                            sunroof_state: command === 'sunroof' ? state : this.checkStatus('sunroof'),                            sunshade_state: command === 'sunshade' ? state : this.checkStatus('sunshade')                        };                        await this.sendMqttMessage(sensorTopic, currentStatus);
                        // 等待车辆状态更新                        await new Promise(resolve => setTimeout(resolve, 5000));                        // 更新并发送状态                        await this.updateAndSendStatus();                    } else {                        $.DoubleLog(`❌未知命令或状态: ${command} ${state}`);                    }                } catch (e) {                    $.DoubleLog(`❌处理命令失败: ${e.message}`);                    console.log(e);                }            });
        } catch (e) {            $.DoubleLog(`❌MQTT初始化失败: ${e.message}`);            console.log(e);        }    }
    // 启动状态更新定时器    async startStatusUpdateInterval() {        // 如果已经有定时器在运行,先清除        if (this.statusUpdateInterval) {            clearInterval(this.statusUpdateInterval);        }
        // 立即执行一次状态更新        await this.updateAndSendStatus();
        // 设置定时器,按照配置的间隔时间更新状态        this.statusUpdateInterval = setInterval(async () => {            await this.updateAndSendStatus();        }, mqttConfig.updateInterval * 1000); // 将秒转换为毫秒
        $.DoubleLog(`✅信息更新定时器已启动,每${mqttConfig.updateInterval}秒更新一次`);    }
    // 更新并发送状态的函数    async updateAndSendStatus() {        try {            // 刷新token            await this.refresh_token();            if (!this.ckStatus) {                // 在输出错误信息前先换行,以免覆盖状态行                process.stdout.write('');                $.DoubleLog(`❌账号CK失效,无法更新状态`);                return;            }
            // 获取车辆各种信息            await this.getVehicleInfo();            // 发送状态到MQTT            await this.sendVehicleStatusMqtt();
            // 使用 process.stdout.write 和 '\r' 实现单行更新日志            const currentTime = new Date().toLocaleString('en-GB', { timeZone'Asia/Shanghai'hour12false }).replace(',''').slice(016).replace(/-/g'/');            process.stdout.write(`✅ ${currentTime} 车辆状态已更新并发送到MQTT\r`);        } catch (e) {            // 在输出错误信息前先换行,以免覆盖状态行            process.stdout.write('');            $.DoubleLog(`❌获取车辆信息失败: ${e.message}`);            console.log(e);        }    }

    // 添加统一的状态检测方法    checkStatus(type) {        const check = this.statusChecks[type];        if (!check) {            $.DoubleLog(`❌未知的状态检测类型: ${type}`);            return false;        }        return check() ? 'ON' : 'OFF';    }
}


// *********************************************************// 变量检查与处理!(async () => {    const userCookie = ($.isNode() ? process.env[ckName] : $.getdata(ckName)) || "";    if (!userCookie) {        console.log("未找到CK");        return;    }    // 获取命令行参数    const args = process.argv.slice(2);    const user = new UserInfo(userCookie);    await user.main(args);  // 直接传入参数数组,可能为空    await $.SendMsg(msg);})().catch((e) => console.log(e)).finally(() => $.done());
// ********************************************************function httpRequest(options, method = null) {    method = options.method ? options.method.toLowerCase() : options.body ? "post" : "get";    return new Promise((resolve) => {        $[method](options, (err, resp, data) => {            if (err) {                console.log(`${method}请求失败`);                $.logErr(err);            } else {                if (data) {                    try { data = JSON.parse(data); } catch (error) { }                    resolve(data);                } else {                    console.log(`请求api返回数据为空,请检查自身原因`);                }            }            resolve();        });    });}// ==================== API ==================== // function Env(t, e) { class s { constructor(t) { this.env = t } send(t, e = "GET") { t = "string" == typeof t ? { url: t } : t; let s = this.getreturn ("POST" === e && (s = this.post), new Promise((e, a) => { s.call(this, t, (t, s, r) => { t ? a(t) : e(s) }) })) } get(t) { return this.send.call(this.env, t) } post(t) { return this.send.call(this.env, t, "POST") } } return new (class { constructor(t, e) { this.userList = []; this.userIdx = 0; (this.name = t), (this.http = new s(this)), (this.data = null), (this.dataFile = "box.dat"), (this.logs = []), (this.isMute = !1), (this.isNeedRewrite = !1), (this.logSeparator = "\n"), (this.encoding = "utf-8"), (this.startTime = new Date().getTime()), Object.assign(this, e), this.log(""`🔔${this.name},开始!`) } getEnv() { return "undefined" != typeof $environment && $environment["surge-version"] ? "Surge" : "undefined" != typeof $environment && $environment["stash-version"] ? "Stash" : "undefined" != typeof module && module.exports ? "Node.js" : "undefined" != typeof $task ? "Quantumult X" : "undefined" != typeof $loon ? "Loon" : "undefined" != typeof $rocket ? "Shadowrocket" : void 0 } isNode() { return "Node.js" === this.getEnv() } isQuanX() { return "Quantumult X" === this.getEnv() } isSurge() { return "Surge" === this.getEnv() } isLoon() { return "Loon" === this.getEnv() } isShadowrocket() { return "Shadowrocket" === this.getEnv() } isStash() { return "Stash" === this.getEnv() } toObj(t, e = null) { try { return JSON.parse(t) } catch { return e } } toStr(t, e = null) { try { return JSON.stringify(t) } catch { return e } } getjson(t, e) { let s = e; const a = this.getdata(t); if (a) try { s = JSON.parse(this.getdata(t)) } catch { } return s } setjson(t, e) { try { return this.setdata(JSON.stringify(t), e) } catch { return !1 } } getScript(t) { return new Promise((e) => { this.get({ url: t }, (t, s, a) => e(a)) }) } runScript(t, e) { return new Promise((s) => { let a = this.getdata("@chavy_boxjs_userCfgs.httpapi"); a = a ? a.replace(/\n/g"").trim() : a; let r = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout"); (r = r ? 1 * r : 20), (r = e && e.timeout ? e.timeout : r); const [i, o] = a.split("@"), n = { url`http:// ${o}/v1/scripting/evaluate`body: { script_text: t, mock_type"cron"timeout: r }, headers: { "X-Key": i, Accept"*/*" }, timeout: r, }; this.post(n, (t, e, a) => s(a)) }).catch((t) => this.logErr(t)) } loaddata() { if (!this.isNode()) return {}; { (this.fs = this.fs ? this.fs : require("fs")), (this.path = this.path ? this.path : require("path")); const t = this.path.resolve(this.dataFile), e = this.path.resolve(process.cwd(), this.dataFile), s = this.fs.existsSync(t), a = !s && this.fs.existsSync(e); if (!s && !a) return {}; { const a = s ? t : e; try { return JSON.parse(this.fs.readFileSync(a)) } catch (t) { return {} } } } } writedata() { if (this.isNode()) { (this.fs = this.fs ? this.fs : require("fs")), (this.path = this.path ? this.path : require("path")); const t = this.path.resolve(this.dataFile), e = this.path.resolve(process.cwd(), this.dataFile), s = this.fs.existsSync(t), a = !s && this.fs.existsSync(e), r = JSON.stringify(this.data); s ? this.fs.writeFileSync(t, r) : a ? this.fs.writeFileSync(e, r) : this.fs.writeFileSync(t, r) } } lodash_get(t, e, s) { const a = e.replace(/\[(\d+)\]/g".$1").split("."); let r = t; for (const t of a) if (((r = Object(r)[t]), void 0 === r)) return s; return r } lodash_set(t, e, s) { return Object(t) !== t ? t : (Array.isArray(e) || (e = e.toString().match(/[^.[\]]+/g) || []), (e.slice(0, -1).reduce((t, s, a) => Object(t[s]) === t[s] ? t[s] : (t[s] = Math.abs(e[a + 1]) >> 0 == +e[a + 1] ? [] : {}), t)[e[e.length - 1]] = s), t) } getdata(t) { let e = this.getval(t); if (/^@/.test(t)) { const [, s, a] = /^@(.*?)\.(.*?)$/.exec(t), r = s ? this.getval(s) : ""if (r) try { const t = JSON.parse(r); e = t ? this.lodash_get(t, a, "") : e } catch (t) { e = "" } } return e } setdata(t, e) { let s = !1if (/^@/.test(e)) { const [, a, r] = /^@(.*?)\.(.*?)$/.exec(e), i = this.getval(a), o = a ? ("null" === i ? null : i || "{}") : "{}"try { const e = JSON.parse(o); this.lodash_set(e, r, t), (s = this.setval(JSON.stringify(e), a)) } catch (e) { const i = {}; this.lodash_set(i, r, t), (s = this.setval(JSON.stringify(i), a)) } } else s = this.setval(t, e); return s } getval(t) { switch (this.getEnv()) { case "Surge"case "Loon"case "Stash"case "Shadowrocket"return $persistentStore.read(t); case "Quantumult X"return $prefs.valueForKey(t); case "Node.js"return (this.data = this.loaddata()), this.data[t]; defaultreturn (this.data && this.data[t]) || null } } setval(t, e) { switch (this.getEnv()) { case "Surge"case "Loon"case "Stash"case "Shadowrocket"return $persistentStore.write(t, e); case "Quantumult X"return $prefs.setValueForKey(t, e); case "Node.js"return ((this.data = this.loaddata()), (this.data[e] = t), this.writedata(), !0); defaultreturn (this.data && this.data[e]) || null } } initGotEnv(t) { (this.got = this.got ? this.got : require("got")), (this.cktough = this.cktough ? this.cktough : require("tough-cookie")), (this.ckjar = this.ckjar ? this.ckjar : new this.cktough.CookieJar()), t && ((t.headers = t.headers ? t.headers : {}), void 0 === t.headers.Cookie && void 0 === t.cookieJar && (t.cookieJar = this.ckjar)) } get(t, e = () => { }) { switch ((t.headers && (delete t.headers[""]), this.getEnv())) { case "Surge"case "Loon"case "Stash"case "Shadowrocket"defaultthis.isSurge() && this.isNeedRewrite && ((t.headers = t.headers || {}), Object.assign(t.headers, { "X-Surge-Skip-Scripting": !1 })), $httpClient.get(t, (t, s, a) => { !t && s && ((s.body = a), (s.statusCode = s.status ? s.status : s.statusCode), (s.status = s.statusCode)), e(t, s, a) }); breakcase "Quantumult X"this.isNeedRewrite && ((t.opts = t.opts || {}), Object.assign(t.opts, { hints: !1 })), $task.fetch(t).then((t) => { const { statusCode: s, statusCode: a, headers: r, body: i, bodyBytes: o, } = t; e(null, { status: s, statusCode: a, headers: r, body: i, bodyBytes: o, }, i, o) }, (t) => e((t && t.error) || "UndefinedError")); breakcase "Node.js"let s = require("iconv-lite"); this.initGotEnv(t), this.got(t).on("redirect"(t, e) => { try { if (t.headers["set-cookie"]) { const s = t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString(); s && this.ckjar.setCookieSync(s, null), (e.cookieJar = this.ckjar) } } catch (t) { this.logErr(t) } }).then((t) => { const { statusCode: a, statusCode: r, headers: i, rawBody: o, } = t, n = s.decode(o, this.encoding); e(null, { status: a, statusCode: r, headers: i, rawBody: o, body: n, }, n) }, (t) => { const { message: a, response: r } = t; e(a, r, r && s.decode(r.rawBodythis.encoding)) }) } } post(t, e = () => { }) { const s = t.method ? t.method.toLocaleLowerCase() : "post"switch ((t.body && t.headers && !t.headers["Content-Type"] && !t.headers["content-type"] && (t.headers["content-type"] = "application/x-www-form-urlencoded"), t.headers && (delete t.headers["Content-Length"], delete t.headers["content-length"]), this.getEnv())) { case "Surge"case "Loon"case "Stash"case "Shadowrocket"defaultthis.isSurge() && this.isNeedRewrite && ((t.headers = t.headers || {}), Object.assign(t.headers, { "X-Surge-Skip-Scripting": !1 })), $httpClient[s](t, (t, s, a) => { !t && s && ((s.body = a), (s.statusCode = s.status ? s.status : s.statusCode), (s.status = s.statusCode)), e(t, s, a) }); breakcase "Quantumult X": (t.method = s), this.isNeedRewrite && ((t.opts = t.opts || {}), Object.assign(t.opts, { hints: !1 })), $task.fetch(t).then((t) => { const { statusCode: s, statusCode: a, headers: r, body: i, bodyBytes: o, } = t; e(null, { status: s, statusCode: a, headers: r, body: i, bodyBytes: o, }, i, o) }, (t) => e((t && t.error) || "UndefinedError")); breakcase "Node.js"let a = require("iconv-lite"); this.initGotEnv(t); const { url: r, ...i } = t; this.got[s](r, i).then((t) => { const { statusCode: s, statusCode: r, headers: i, rawBody: o, } = t, n = a.decode(o, this.encoding); e(null, { status: s, statusCode: r, headers: i, rawBody: o, body: n }, n) }, (t) => { const { message: s, response: r } = t; e(s, r, r && a.decode(r.rawBodythis.encoding)) }) } } time(t, e = null) { const s = e ? new Date(e) : new Date(); let a = { "M+": s.getMonth() + 1"d+": s.getDate(), "H+": s.getHours(), "m+": s.getMinutes(), "s+": s.getSeconds(), "q+"Math.floor((s.getMonth() + 3) / 3), S: s.getMilliseconds(), }; /(y+)/.test(t) && (t = t.replace(RegExp.$1, (s.getFullYear() + "").substr(4 - RegExp.$1.length))); for (let e in a) new RegExp("(" + e + ")").test(t) && (t = t.replace(RegExp.$11 == RegExp.$1.length ? a[e] : ("00" + a[e]).substr(("" + a[e]).length))); return t } queryStr(t) { let e = ""for (const s in t) { let a = t[s]; null != a && "" !== a && ("object" == typeof a && (a = JSON.stringify(a)), (e += `${s}=${a}&`)) } return (e = e.substring(0, e.length - 1)), e } msg(e = t, s = "", a = "", r) { const i = (t) => { switch (typeof t) { case void 0return t; case "string"switch (this.getEnv()) { case "Surge"case "Stash"defaultreturn { url: t }; case "Loon"case "Shadowrocket"return t; case "Quantumult X"return { "open-url": t }; case "Node.js"return }case "object"switch (this.getEnv()) { case "Surge"case "Stash"case "Shadowrocket"default: { let e = t.url || t.openUrl || t["open-url"]; return { url: e } } case "Loon": { let e = t.openUrl || t.url || t["open-url"], s = t.mediaUrl || t["media-url"]; return { openUrl: e, mediaUrl: s } } case "Quantumult X": { let e = t["open-url"] || t.url || t.openUrl, s = t["media-url"] || t.mediaUrl, a = t["update-pasteboard"] || t.updatePasteboardreturn { "open-url": e, "media-url": s, "update-pasteboard": a, } } case "Node.js"return }defaultreturn } }; if (!this.isMuteswitch (this.getEnv()) { case "Surge"case "Loon"case "Stash"case "Shadowrocket"default: $notification.post(e, s, a, i(r)); breakcase "Quantumult X": $notify(e, s, a, i(r)); breakcase "Node.js": }if (!this.isMuteLog) { let t = ["""==============📣系统通知📣==============",]; t.push(e), s && t.push(s), a && t.push(a), console.log(t.join("\n")), (this.logs = this.logs.concat(t)) } } log(...t) { t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(t.join(this.logSeparator)) } logErr(t, e) { switch (this.getEnv()) { case "Surge"case "Loon"case "Stash"case "Shadowrocket"case "Quantumult X"defaultthis.log(""`❗️${this.name},错误!`, t); breakcase "Node.js"this.log(""`❗️${this.name},错误!`, t.stack) } } wait(t) { return new Promise((e) => setTimeout(e, t)) } DoubleLog(d) { if (this.isNode()) { if (d) { console.log(`${d}`); msg += `\n ${d}` } } else { console.log(`${d}`); msg += `\n ${d}` } } async SendMsg(m) { if (!m) returnif (Notify > 0) { if (this.isNode()) { var notify = require("./sendNotify"); await notify.sendNotify(this.name, m) } else { this.msg(this.name"", m) } } else { console.log(m) } } done(t = {}) { const e = new Date().getTime(), s = (e - this.startTime) / 1e3switch ((this.log(""`🔔${this.name},结束!🕛${s}秒`), this.log(), this.getEnv())) { case "Surge"case "Loon"case "Stash"case "Shadowrocket"case "Quantumult X"default: $done(t); breakcase "Node.js": process.exit(1) } } })(t, e) }// Env rewrite:smallfawn Update-time:23-6-30 newAdd:DoubleLog & SendMsg

解析

该脚本为吉利银河定时签到脚本,主要功能为:

  • 基于抓取到的 refreshToken 与 deviceSN,调用吉利银河官方接口完成:

    • 车辆信息/状态查询(定位、电量、空调、门锁、车窗、天窗等)

    • 签到与积分查询

    • 远程控制(开/关哨兵、开/关门锁、闪灯鸣笛、开/关车窗/天窗/遮阳帘、净化、除霜、空调、极速升降温)

  • 支持 MQTT:把车辆状态以 HomeAssistant 友好的实体/配置发布到 MQTT,且可通过 MQTT 控制上述功能(开关与按钮)。

依赖:mqtt[email protected]tough-cookiecrypto-js
必备环境变量:jlyh="refreshToken&deviceSN"(两段用 & 连接)
通知控制:Notify=0/1/2(默认/全部开启/全部关闭)
运行方式:无参按默认;或传参如 jlyh.js all|mqtt|info|sign|opensentry ...

主要方法

一、认证与请求封装

  • refresh_token()
    用 refreshToken 向 galaxy-user-api 刷新中心 token,存入 this.token,并标记 CK 是否有效。

  • getPostHeader(key, path, body) / getGetHeader(key, path)
    统一组装请求头(含 Content-MD5、时间戳、x-ca-* 签名等),适配不同 x-ca-key(安卓/H5)。

  • calculateHmacSha256(...)formatDate(...)generateUUID()
    用于签名串拼接、GMT 时间格式、随机 nonce 生成。

二、信息查询

  • mylist()
    调用 /vc/app/v1/vehicle/control/myList,获取车辆基本信息(VIN、车型、颜色等),存入 this.vehicleInfo

  • controlstatus()
    调用 /vc/app/v1/vehicle/control/status,获取车辆状态(位置、里程、电量、车内外温度、空调、电机、门锁等),存入 this.vehicleStatus

  • switchstatus()
    调用 /vc/app/v1/vehicle/switch/status,获取功能开关状态(哨兵、遮阳帘、漂移模式等),存入 this.switchStatus

  • points() / signstate()
    查询积分与当日签到状态。

三、业务动作(远程控制)

  • sign()
    先查 signstate(),未签到则 /app/v1/sign/add 执行签到,并调用 points() 回显积分。

  • 哨兵:opensentry() / closesentry()
    /vc/app/v1/vehicle/control/switch 开关哨兵,开之前会校验电量、当前开关状态。

  • 车锁:opendoor() / closedoor()(底层 controlDoor(action)
    /vc/app/v1/vehicle/control/door 开/关门锁。

  • 闪灯鸣笛:search()
    /vc/app/v1/vehicle/control/search

  • 车窗/天窗/遮阳帘:windowslightopen()windowfullopen()windowclose()sunroofopen()sunroofclose()sunshadeopen()sunshadeclose()(底层 controlWindow(action)
    /vc/app/v1/vehicle/control/window

  • 空气净化:purifieropen() / purifierclose()(底层 controlPurifier(action)
    /vc/app/v1/vehicle/control/noEngine

  • 空调/除霜:aconopen(temperature)aconclose()defrostopen()defrostclose()(底层 controlClimate(action, temperature)
    /vc/app/v1/vehicle/control/climate

  • 极速温控:rapidheat() / rapidcool()(底层 controlTemperature(action)
    /vc/app/v1/vehicle/control/temperature,一键升/降温并设置风量/加热参数。

四、MQTT 集成(对接 HomeAssistant)

  • initMqtt()
    连接 MQTT,订阅三类主题:

    • switch/.../set(哨兵/门锁/空调/除霜/净化/天窗/遮阳帘)

    • button/.../press(极速升温/极速降温/闪灯鸣笛/车窗动作)

    • number/.../ac_temp/set(空调温度滑杆)
      收到消息后路由到对应控制方法,并触发状态更新。

  • sendVehicleStatusMqtt()
    发布 HomeAssistant 需要的 config 与 state

    • sensor:车内外温度、电量、PM2.5、里程、续航、充满时间、位置、当前车速、能耗等

    • device_tracker:车辆 GPS

    • switch:哨兵、门锁、空调、除霜、净化、天窗、遮阳帘

    • number:空调温度滑动条

    • button:极速升温/降温、闪灯鸣笛、车窗操作

  • startStatusUpdateInterval() / updateAndSendStatus()
    定时刷新 token、拉取车辆信息并发布到 MQTT(间隔由 mqttConfig.updateInterval 设置,默认 60 秒)。

  • sendMqttMessage(topic, message)
    统一 MQTT 发布。

  • checkStatus(type)
    将车辆/开关状态统一转成 ON/OFF,便于 HomeAssistant 显示。

五、脚本入口与调度

  • main(features = [])
    流程总控:根据传参决定只查信息、执行指定功能、或启动 MQTT;先 refresh_token 与 getVehicleInfo(),再 executeFeatures(features),或进入 MQTT 监听模式。

  • 通知:Notify 级别控制,重要事件(如签到、哨兵开关、执行控制)可强制通知。

  • httpRequest(...) 与 Env 封装:适配 Node/Surge/QuanX 等环境调用与通知。

提示

  • CK 有效性与异地登录:APP 异地登录会顶下线,需要重新抓包获取 refreshTokendeviceSN 必须与设备一致。

  • 风控与频率:远程控制动作建议合理间隔,避免触发风控;MQTT 更新频率建议 ≥60s。

  • 安全refreshToken/deviceSN 属敏感信息,请妥善保管;仅用于个人自控设备与合规用途。


注意

本文部分变量已做脱敏处理,仅用于测试和学习研究,禁止用于商业用途,不能保证其合法性,准确性,完整性和有效性,请根据情况自行判断。技术层面需要提供帮助,可以通过打赏的方式进行探讨。


历史脚本txt文件获取>>
服务器搭建,人工服务咨询>>

【相关文章】

吉利银河任务脚本

没有评论:

发表评论

一天收入900+,分享3个听歌赚钱平台,不上班也能养活自己(附操作方法)

经济下行,搞钱这个话题越来越火,也有很多人抱怨,钱越来越难赚了。 但是,每个时代都有人赚到钱,会赚钱的人,什么时候都能闷声发大财。 我们常说, 认知到了,钱就来了,我们永远赚不到认知以外的钱。 赚钱,永远讲究认知、思路、方法和执行。 这些道理,从古至今,一直没有变。 我就比较...