找回密码
 立即注册

微信扫码登录

搜索
查看: 228|回复: 3

[流程系列] 【阿木制作】分享一个根据季度、温度和光照控制阳台左右窗帘的流

[复制链接]

60

主题

229

回帖

2165

积分

论坛技术达人

积分
2165
金钱
1871
HASS币
20
发表于 2025-10-26 11:15:19 | 显示全部楼层 |阅读模式
本帖最后由 lambilly 于 2025-10-26 13:17 编辑

一个根据季节、天气、温度、光照和时间5个维度制阳台左右窗帘的流,优化了很久,分享给大家。
1、流程图:
     下述流中,中间的两个节点“自动窗帘”和”阳台窗户“主要解决:
     (1)自动窗帘虚拟开关解决有时不需要它太自动就关闭“自动窗帘”虚拟开关;
   (2)阳台窗帘传感器是在阳台窗帘那安装一个阳台开关传感器,解决窗户没关,阳台风大而自动关闭窗帘,乱飞。可自行决定是否加这个节点。

屏幕截图_26-10-2025_111153_home.lamnas.top.jpeg
2、核心函数代码:
// ====================== [数据预处理] ======================
const { 
    topic,          // 当前主题/频道
    temperature,    // 温度传感器数值
    illuminance,    // 光照传感器数值
    weather,        // 天气状态字符串
    weather_data:{
        attributes: {
            condition_cn: weather_cn
        }
    }
} = msg;

const MsgChannel = global.get('noticeText')[topic] || {}; 
const noticeMsgs = MsgChannel;                         // 使用统一的消息模板
const update_time = formatDate(new Date());         // 格式化更新时间

// ====================== [时间与季节判断] ======================
const now = new Date();
const hours = now.getHours();  // 当前小时(0-23)
const month = now.getMonth() + 1;  // 当前月份(1-12)

const isWinter = month >= 11 || month < 5;  // 11月-4月为冬季
const isSummer = month >= 5 && month < 11;  // 5月-10月为夏季
const isSunny = ["sunny","partlycloudy"].includes(weather);  // 晴天判断

// ====================== [规则引擎核心] ======================

const ruleDescription = [
`【窗帘开关规则】`,
`一、夏季(5-10月份)`,
`1.温度>33或光照>400时:`,
`8-11时关闭左窗帘,12-17时关闭右窗帘;`,
`2.温度<30或光照<350时:`,
`9-15时打开左窗帘,12-18时打开右窗帘;`,
`二、冬季(11-4月份)`,
`1.温度>31或光照>450时:`,
`9-11时关闭左窗帘,12-16时关闭右窗帘;`,
`2.温度<30或光照<350时:`,
`10-15时打开左窗帘,12-17时打开右窗帘;`
].join('\n');

const RULE_CONFIG = {
    summer: {
        close: [
            // 左帘关闭规则
            {
                time: 8,
                endTime: 11,
                conditions: [
                    { light: { gt: 400 }, msg: 'noticeMsg1' },  // 强光条件
                    { temp: { gt: 33 }, msg: 'noticeMsg2' }  // 高温条件
                ],
                action: 'left_close',
                dir: '左窗帘'
            },
            // 右帘关闭规则
            {
                time: 12,
                endTime: 17,
                conditions: [
                    { light: { gt: 400 }, msg: 'noticeMsg1' },
                    { temp: { gt: 33 }, msg: 'noticeMsg2' }
                ],
                action: 'right_close',
                dir: '右窗帘'
            }
        ],
        open: [
            // 左帘打开规则
            {
                time: 9,
                endTime: 15,
                conditions: [
                    { light: { lt: 350 }, msg: 'noticeMsg3' },    // 光照<300
                    { temp: { lt: 30 }, msg: 'noticeMsg4' }    // 温度<30
                ],
                action: 'left_open',
                dir: '左窗帘'
            },
            // 右帘打开规则
            {
                time: 12,
                endTime: 18,
                conditions: [
                    { light: { lt: 350 }, msg: 'noticeMsg3' },
                    { temp: { lt: 30 }, msg: 'noticeMsg4' }
                ],
                action: 'right_open',
                dir: '右窗帘'
            }
        ]
    },
    winter: {
        close: [
            // 左帘关闭规则
            {
                time: 9, 
                endTime: 11,
                conditions: [
                    { light: { gt: 450 }, msg: 'noticeMsg1' },  // 强光条件
                    { temp: { gt: 31 }, msg: 'noticeMsg2' }  // 高温条件
                ],
                action: 'left_close',
                dir: '左窗帘'
            },
            // 右帘关闭规则
            {
                time: 12,
                endTime: 16,
                conditions: [
                    { light: { gt: 450 }, msg: 'noticeMsg1' },
                    { temp: { gt: 31 }, msg: 'noticeMsg2' }
                ],
                action: 'right_close',
                dir: '右窗帘'
            }
        ],
        open: [
            // 左帘打开规则
            {
                time: 10,
                endTime: 15,
                conditions: [
                    { light: { lt: 400 }, msg: 'noticeMsg3' },   // 光照<300
                    { temp: { lt: 30 }, msg: 'noticeMsg4' }  // 温度<30
                ],
                action: 'left_open',
                dir: '左窗帘'
            },
            // 右帘打开规则
            {
                time: 12,
                endTime: 17,
                conditions: [
                    { light: { lt: 400 }, msg: 'noticeMsg3' },
                    { temp: { lt: 30 }, msg: 'noticeMsg4' }
                ],
                action: 'right_open',
                dir: '右窗帘'
            }
        ]
    }
};

// ====================== [执行逻辑] ======================
let result = null;
if (isSunny) {
    const rules = isWinter ? RULE_CONFIG.winter.close : 
                 isSummer ? RULE_CONFIG.summer.close : [];
    result = findMatchingRule(rules);
}

if (!result) {
    const rules = isWinter ? RULE_CONFIG.winter.open : 
                 isSummer ? RULE_CONFIG.summer.open : [];
    result = findMatchingRule(rules);
}

// ====================== [输出结构] ======================
msg = {
    notifyTitle: MsgChannel.title || "阳台窗帘",
    voice: result ? `主人,${result.content}` : "",
    notify: result ? `${update_time}\n${result.content}\n\n${ruleDescription}` : "",
    notifyId: MsgChannel.notifyId || 1000,
    action: result ? result.action : ""
};

// 根据action类型返回四元素数组
switch(msg.action) {
    case 'left_close': return [msg, null, null, null];
    case 'right_close': return [null, msg, null, null];
    case 'left_open': return [null, null, msg, null];
    case 'right_open': return [null, null, null, msg];
    default: return [null, null, null, null];
}

// ====================== [工具函数] ======================
// 1.时间范围条件检查函数
function isRuleTimeValid(rule) {
    return hours >= rule.time && hours < (rule.endTime || 24);
}

// 2.温度和光照条件检查函数
function isConditionMet(condition) {
    // (1)光照条件检查
    if (condition.light) {
        if ('gt' in condition.light && illuminance <= condition.light.gt) return false;
        if ('lt' in condition.light && illuminance >= condition.light.lt) return false;
    }
    // (2)温度条件检查
    if (condition.temp) {
        if ('gt' in condition.temp && temperature <= condition.temp.gt) return false;
        if ('lt' in condition.temp && temperature >= condition.temp.lt) return false;
    }
    return true;
}

//  3.规则条件检查函数
function findMatchingRule(rules) {
    for (const rule of rules) {
        if (!isRuleTimeValid(rule)) continue;
        for (const cond of rule.conditions) {
            if (isConditionMet(cond)) {
                // 根据条件类型构建消息参数
                let value;
                if (cond.temp) {
                    // 温度值保留1位小数
                    value = temperature.toFixed(0) ;
                } else if (cond.light) {
                    // 光照值取整
                    value = Math.round(illuminance);
                }
                
                return {
                    action: rule.action,
                    content: formatTemplate(noticeMsgs[cond.msg], weather_cn,value, rule.dir)
                };
            }
        }
    }
    return null;
}


// 4.输出信息格式化函数
function formatTemplate(string, ...args) {
    return string.replace(/%s/g, () => args.shift() || '');
}

// 5.输出时间格式化函数
function formatDate(now) {
    return now.toLocaleString("zh-CN", {
        timeZone: "Asia/Shanghai",
        hour12: false,
        year: "numeric",
        month: "2-digit",
        day: "2-digit",
        hour: "2-digit",
        minute: "2-digit",
        second: "2-digit"
    }).replace(/\//g, "-");
}

3、代码中需要的NoticeMsg,可以自行定义
{
"tempCurtain": {"notifyId":3004,"title":"🧑‍🚀窗帘动态","noticeMsg1":"天气%s,阳台光线%s,有点晒,自动关闭%s。","noticeMsg2":"天气%s,温度%s度,有点热,自动关闭%s。","noticeMsg3":"天气%s,阳台光线减弱到%s,自动打开%s。","noticeMsg4":"天气%s,温度下降到%s度,自动打开%s。"}
}


4、下载地址:
游客,如果您要查看本帖隐藏内容请回复






评分

参与人数 1金钱 +12 收起 理由
隔壁的王叔叔 + 12 论坛有你更精彩!

查看全部评分

回复

使用道具 举报

24

主题

552

回帖

3877

积分

论坛元老

积分
3877
金钱
3301
HASS币
18
发表于 2025-10-26 13:15:09 | 显示全部楼层
非常好的案例,谢谢分享!收藏+学习
回复

使用道具 举报

66

主题

436

回帖

2121

积分

金牌会员

积分
2121
金钱
1619
HASS币
50
发表于 2025-10-26 15:27:39 | 显示全部楼层
谢谢分享!收藏+学习
回复

使用道具 举报

8

主题

307

回帖

3358

积分

论坛元老

积分
3358
金钱
3043
HASS币
0
发表于 2025-10-26 16:43:42 | 显示全部楼层
谢谢分享!收藏+学习
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Hassbian ( 晋ICP备17001384号-1 )

GMT+8, 2025-11-5 03:03 , Processed in 0.162293 second(s), 6 queries , MemCached On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表