You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求Shelly Pro 2PM的Espruino脚本:实现指定日出日落关联调度

修正Shelly Pro 2PM的Espruino调度脚本(实现日出日落关联开关逻辑)

原脚本问题分析

  1. 未实现Shelly设备的日出日落获取逻辑,依赖的getSunrise()/getSunset()为空函数
  2. 条件判断逻辑与需求不符,早上触发条件写反
  3. 关闭定时器的时间计算错误(如晚上固定7小时后关闭,而非到当日7点的时间差)
  4. 缺少每日重新调度逻辑,单次执行无法覆盖后续日期
  5. 报错提到的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();

关键说明

  1. 日出日落获取:依赖Shelly设备内置的SunCalc模块,必须先在Shelly后台配置设备的地理位置(经纬度)
  2. 继电器控制:默认控制通道1,如需控制通道2,修改turnOn/turnOff函数中的id:0为id:1
  3. 时间差处理:getTimeout函数自动处理目标时间已过期的情况,自动切换到次日对应时间
  4. 每日调度更新:脚本会在每日凌晨0点1分重新执行调度逻辑,确保适配每天变化的日出日落时间

内容的提问来源于stack exchange,提问作者Alexandra B

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 23:23:14