2021爱智先行者 - 自动化房屋能源控制核心

本文作者分享了如何构建一个自动化家居能源控制系统,该系统结合光照传感器、人体存在传感器、远程灯控和空调遥控,根据房间人员活动自动控制空调和灯光,减少能源浪费。文章详细介绍了设备工作原理、应用逻辑及代码实现,并提供了代码仓库链接供读者参考。此外,还展示了应用界面和日志功能,方便用户了解房间状态和操作记录。
摘要由CSDN通过智能技术生成

前言

​ 冬天到了,早上醒来懒得出被窝,但是为了大家,我还是抵抗住了寒冷,冒着生命危险给大家准备了这一期的文章,就冲这一点值不值得你们给我一个赞o(´^`)o,当然,这么久了,知道你们不见货是不会点赞的,那我还是先干为敬,你们随意。

​ 之前做了这么多铺垫,现在终于到了收束的时刻!这一定是石头门的选择!在之前的文章里我分别完成了光照传感器,远程灯控开关,人体存在传感器,远程空调遥控器。今天所有的细线已经串成了一条,计划至此进入最终阶段!今天将带大家完成我们的自动化房屋能源控制核心!

我这边的话也已经把我家里的一个房间改造了一下,效果还是不错的。可以根据房间人员检测自动进行控制空调和灯光。当然,冬天了,可能很多人睡觉都不愿意下床去开关灯或者空调啥的,这里应用也提供了手动模式进行控制灯光和空调的功能,让你在被窝里玩手机也可以控制。

设备讲解

涉及到的场景设备之前也已经介绍过了,这里就不再过多介绍,直接给大家放传送门:

光照传感器

灯光开关控制

人体检测传感器

红外学习模块(空调遥控器)

应用讲解

天太冷了,敲着手疼,这里就简短介绍一下。

实现这个场景的目的主要是为了减少一下家里的用电(毕竟家里有好几个空调和大灯)

感兴趣的朋友可以前往:灵感桌面的秘密宝库 下载代码。
或者直接 git clone:

https://gitee.com/inspiration-desktop/eap-energy-conservation.git

应用的实现思路大致就是以下逻辑了:

首先光照传感器会定时去获取最新实时数据,接着当人体感应器检测到人体变化时会进行逻辑处理,如果在控制时间段内,这时候房间内没人了,会去开启关闭空调和灯光的定时器。在定时器时间段内,如果房间再次出现人,则移除定时器处理(因为可能有人去上了个厕所就回来了)。否则在定时器触发时候,房间依然没有人,这时候会先去关掉空调,然后再去比对光照传感器数据,检测当前室内灯是否开启,如果开启,则回去关掉房间内的所有灯设备。

注意:这里需要利用光照传感器,因为我这边的灯光控制设备无法保存状态,所以需要对比光照,同时我这边的灯光控制生效时间一般设置的是晚上的时候,所以说还是有点瑕疵的。

代码分析

​ 由于这个场景比较综合复杂,在写代码时候有很多需要注意的点。这里就简单的讲一下代码。

​ 和之前的一系列一样,用的是JSRE的一个Device模块,主要用来去获取设备传递给爱智的信息,同时也是应用通过爱智向设备发送指令的途径。

​ 首先这边光照和温度传感器的数据不是主动上报的,而是把这部分的逻辑让爱智应用去分担,这样我的设备就可以更加轻便,所以我这边应用后端添加了定时器去定时获取最新的数据状态。

...

switch (type) {   
  case 'illu-sensor':
    // 光照
    times[devid] = setInterval(() => {
      devManager.sendDeviceInfo(devid, { method: 'get', obj: ['illu'] });
    }, 5 * 1000);
  break;
  case 'temp-sensor':
    times[devid] = setInterval(() => {
      devManager.sendDeviceInfo(devid, { method: 'get', obj: ['temp'] });
    }, 30 * 60 * 1000);
  break;
  default:
  break;
}

...

而这边获取到数据之后,就会对数据进行相应的处理,由于代码量比较大,所以处理的代码这边就简单讲一下;

在获取到光照和温度的值后,将数据同步到前端,同时保存日志;

主要逻辑是当检测到人体感应变化时候,会去对空调和灯光进行控制,这里需要进行控制时间段的处理和延迟响应处理。

...

value = data.data['micro_state'] === 'ON';
// 状态存入日志中
if (data.method === 'report') {
   saveLog(room_id, 'operation', `房间【${room.name}】中检测${value ? '有' : '没'}人!`);
}
// 控制空调和灯光
if (value) {
   clearTimeout(roomTimes[`ac-${room_id}`]);
   clearTimeout(roomTimes[`light-${room_id}`]);
   roomTimes[`ac-${room_id}`] = undefined;
   roomTimes[`light-${room_id}`] = undefined;
} else {
   if (dev && roomTimes[`ac-${room_id}`] === undefined && roomTimes[`light-${room_id}`] === undefined) {
      const date = new Date();
      const curTimeMinute = date.getHours() * 60 + date.getMinutes();
      const {devids,settings: { ac_cp, light_cp }} = room;
      const ac_devids = []; // 房间内在线的空调设备
      const light_devids = []; // 房间内在线的灯设备
      devids.map((item) => {
        const d = devManager.devMap.get(item);
        if (d) {
          const type = getDeviceType(d);
          if (type === 'ac-control') {
            ac_devids.push(item);
          } else if (type === 'light-control') {
            light_devids.push(item);
          }
        }
      });
      if (ac_devids.length) {
        const ac_start_times = ac_cp[0].split(':');
        const ac_end_times = ac_cp[1].split(':');
        const ac_start_time_minute = Number(ac_start_times[0]) * 60 + Number(ac_start_times[1]);
        const ac_end_time_minute = Number(ac_end_times[0]) * 60 + Number(ac_end_times[1]);
        if (ac_start_time_minute <= ac_end_time_minute) {
          // 如果开始时间小于等于结束时间,说明没有跨越次日零点
          // 取开始时间-结束时间之间
          if (curTimeMinute >= ac_start_time_minute && curTimeMinute < ac_end_time_minute) {
            // 在空调控制时间内
            // 关闭空调
            // 添加定时器延时
            roomTimes[`ac-${room_id}`] = setTimeout(() => {
              ac_devids.forEach((id) => {
                devManager.sendDeviceInfo(id, { method: 'set', ac: 'OFF' });
              });
              // saveLog(room_id, 'operation', `房间【${room.name}】空调被关掉了!`);
            }, 30 * 1000);
          }
        } else {
          // 如果开始时间大于结束时间,说明跨越了次日零点
          // 去开始时间-23:59 和 00:00-结束时间
          if (curTimeMinute > ac_start_time_minute || curTimeMinute < ac_end_time_minute) {
            // 在空调控制时间内
            // 关闭空调
            // 添加定时器延时
            roomTimes[`ac-${room_id}`] = setTimeout(() => {
              ac_devids.forEach((id) => {
                devManager.sendDeviceInfo(id, { method: 'set', ac: 'OFF' });
              });
              // saveLog(room_id, 'operation', `房间【${room.name}】空调被关掉了!`);
            }, 30 * 1000);
          }
       }
     }
       
     if (light_devids.length) {
       const light_start_times = light_cp[0].split(':');
       const light_end_times = light_cp[1].split(':');
       const light_start_time_minute = Number(light_start_times[0]) * 60 + Number(light_start_times[1]);
       const light_end_time_minute = Number(light_end_times[0]) * 60 + Number(light_end_times[1]);
       if (light_start_time_minute <= light_end_time_minute) {
       // 如果开始时间小于等于结束时间,说明没有跨越次日零点
       // 取开始时间-结束时间之间
         if (curTimeMinute >= light_start_time_minute && curTimeMinute < light_end_time_minute) {
         // 在灯控制时间内
         // 关闭灯
         // 添加定时器延时
           roomTimes[`light-${room_id}`] = setTimeout(() => {
             if (roomRealValue[room_id] &&
                 roomRealValue[room_id]['illu'] &&
                 roomRealValue[room_id]['illu'] > 30
             ) {
               // 光照强度 > 30 判定为开灯状态
               light_devids.forEach((id) => {
                 devManager.sendDeviceInfo(id, { method: 'set', SW_ctrl: 'OFF' });
               });
               // 保存操作日志
               saveLog(room_id, 'operation', `房间【${room.name}】灯被关掉了!`, 'success');
             }
           }, 30 * 1000);
         }
       } else {
         // 如果开始时间大于结束时间,说明跨越了次日零点
         // 去开始时间-23:59 和 00:00-结束时间
         if (curTimeMinute > light_start_time_minute || curTimeMinute < light_end_time_minute) {
           // 在灯控制时间内
           // 关闭灯
           // 添加定时器延时
           roomTimes[`light-${room_id}`] = setTimeout(() => {
             if (roomRealValue[room_id] &&
                 roomRealValue[room_id]['illu'] &&
                 roomRealValue[room_id]['illu'] > 30
              ) {
                // 光照强度 > 30 判定为开灯状态
                light_devids.forEach((id) => {
                  devManager.sendDeviceInfo(id, { method: 'set', SW_ctrl: 'OFF' });
                });
                // 保存操作日志
                saveLog(room_id, 'operation', `房间【${room.name}】灯被关掉了!`, 'success');
              }
            }, 30 * 1000);
          }
        }
      }
   }
}

...

场景演示

这里的话不太方便给大家演示现场,直接给大家看一下实现的应用的场景吧。

  • 房间列表首页
    在这里插入图片描述

  • 房间内部

    这里主要就是添加一下房间的设备,因为逻辑在后端服务里面已经写好了,所以设备加进去就会自动生效运行了。
    在这里插入图片描述

  • 房间配置

    这里主要是配置一些基础信息,比如房间名称、人体感应控制空调和灯光的作用时间。
    在这里插入图片描述

  • 日志

    任何一个应用都离不开日志,当然这里也不例外,这里可以让大家实时了解各个房间的实时日志信息。
    在这里插入图片描述

总结

​ 今天把之前的所有设备给整合到一起了,效果还是不错的。简直是我这种经常忘记关家电的笨蛋,不想起床关灯和空调的懒鬼,但是又舍不得电费的穷鬼的救星,哈哈哈哈。

​ 我的手已经失去知觉了,太冷了,幸好本人养了俩只猫,冬天到了,刚好可以当暖手宝︿( ̄︶ ̄)︿,今天就到这就草草结束吧,我去选个暖手宝暖暖手。

本文仅个人学习使用,如有错误,欢迎指正, ( ੭ ˙ᗜ˙ )੭谢谢老板!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值