求Shelly Pro 2PM的Espruino脚本:实现指定日出日落关联调度
修正Shelly Pro 2PM的Espruino调度脚本(实现日出日落关联开关逻辑)
原脚本问题分析
- 未实现Shelly设备的日出日落获取逻辑,依赖的
getSunrise()/getSunset()为空函数 - 条件判断逻辑与需求不符,早上触发条件写反
- 关闭定时器的时间计算错误(如晚上固定7小时后关闭,而非到当日7点的时间差)
- 缺少每日重新调度逻辑,单次执行无法覆盖后续日期
- 报错提到的
let TurnOnTime - new Date();属于语法错误(应为赋值运算符=而非减号-)
修正后的完整脚本
// 获取当天日出/日落时间(调用Shelly内置API) function getSunEvents() { const sysConfig = Shelly.getComponentConfig("sys"); // 从设备系统配置中读取经纬度(需先在Shelly后台设置位置) const lat = sysConfig.location.lat; const lon = sysConfig.location.lon; if (!lat || !lon) { print("请先在Shelly配置界面设置设备地理位置!"); return null; } // 调用内置SunCalc模块获取当日日出日落时间 const sunEvents = SunCalc.getSunEvents(new Date(), lat, lon); return { sunrise: new Date(sunEvents.sunrise), sunset: new Date(sunEvents.sunset) }; } // 控制Shelly Pro 2PM通道1开启(控制通道2请将id改为1) function turnOn() { Shelly.call("Switch.Set", { id: 0, on: true }, function (res, err) { err ? print("开启失败:", err) : print("设备已开启"); }); } // 控制Shelly Pro 2PM通道1关闭 function turnOff() { Shelly.call("Switch.Set", { id: 0, on: false }, function (res, err) { err ? print("关闭失败:", err) : print("设备已关闭"); }); } // 计算目标时间与当前时间的差值,若目标时间已过则自动计算次日时间差 function getTimeout(targetTime) { const now = Date.now(); let diff = targetTime.getTime() - now; if (diff <= 0) { targetTime.setDate(targetTime.getDate() + 1); diff = targetTime.getTime() - now; } return diff; } // 执行核心调度逻辑 function scheduleJobs() { const sunEvents = getSunEvents(); if (!sunEvents) return; const { sunrise, sunset } = sunEvents; const now = new Date(); // 早上逻辑:5点开启,日出+15分钟关闭(仅当日出+15分晚于5点时执行) const morningOnTime = new Date(now); morningOnTime.setHours(5, 0, 0, 0); const morningOffTime = new Date(sunrise.getTime() + 15 * 60 * 1000); if (morningOffTime.getTime() > morningOnTime.getTime()) { setTimeout(turnOn, getTimeout(morningOnTime)); // 计算关闭定时器的时间差(区分是否已过开启时间) const offDelay = morningOffTime.getTime() - (morningOnTime > now ? morningOnTime.getTime() : now); offDelay > 0 && setTimeout(turnOff, offDelay); } // 晚上逻辑:日落-15分钟开启,7点关闭(仅当日落-15分早于7点时执行) const eveningOnTime = new Date(sunset.getTime() - 15 * 60 * 1000); const eveningOffTime = new Date(now); eveningOffTime.setHours(19, 0, 0, 0); if (eveningOnTime.getTime() < eveningOffTime.getTime()) { setTimeout(turnOn, getTimeout(eveningOnTime)); // 计算关闭定时器的时间差(区分是否已过开启时间) const offDelay = eveningOffTime.getTime() - (eveningOnTime > now ? eveningOnTime.getTime() : now); offDelay > 0 && setTimeout(turnOff, offDelay); } // 每日凌晨0点1分重新调度,适配每日变化的日出日落时间 const nextSchedule = new Date(now); nextSchedule.setHours(0, 1, 0, 0); setTimeout(scheduleJobs, getTimeout(nextSchedule)); } // 启动调度 scheduleJobs();
关键说明
- 日出日落获取:依赖Shelly设备内置的
SunCalc模块,必须先在Shelly后台配置设备的地理位置(经纬度) - 继电器控制:默认控制通道1,如需控制通道2,修改
turnOn/turnOff函数中的id:0为id:1 - 时间差处理:
getTimeout函数自动处理目标时间已过期的情况,自动切换到次日对应时间 - 每日调度更新:脚本会在每日凌晨0点1分重新执行调度逻辑,确保适配每天变化的日出日落时间
内容的提问来源于stack exchange,提问作者Alexandra B
相关产品推荐
相关产品推荐

