|
|
本帖最后由 lambilly 于 2025-10-26 13:17 编辑
一个根据季节、天气、温度、光照和时间5个维度制阳台左右窗帘的流,优化了很久,分享给大家。
1、流程图:
下述流中,中间的两个节点“自动窗帘”和”阳台窗户“主要解决:
(1)自动窗帘虚拟开关解决有时不需要它太自动就关闭“自动窗帘”虚拟开关;
(2)阳台窗帘传感器是在阳台窗帘那安装一个阳台开关传感器,解决窗户没关,阳台风大而自动关闭窗帘,乱飞。可自行决定是否加这个节点。
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、下载地址:
|
评分
-
查看全部评分
|