查看: 13526|回复: 15

[大赛作品提交] 基于树莓派的智能魔镜

  [复制链接]
  • TA的每日心情
    无聊
    2021-7-15 17:25
  • 签到天数: 21 天

    连续签到: 1 天

    [LV.4]偶尔看看III

    发表于 2018-1-9 21:54:57 | 显示全部楼层 |阅读模式
    分享到:
    本帖最后由 ky123 于 2018-1-31 14:05 编辑

    首先,感谢E络盟官方提供的树莓派,谢谢大佬~~给大佬鞠躬,哈哈哈
    ---------------------------------无耻之极的分割线-----------------------------------------------
    一、项目名称:pandora,基于树莓派的智能魔镜
    1.原理介绍:(其实原理很简单~~)
        树莓派魔镜显示原理其实很简单,就是一块原子镜,也就是双面镜,后面放上一块屏幕,因为屏幕上面现实的字的亮度高于前面,所以,字就透过来了,同时,没有字的地方设置为黑色背景,于是人们还可以把他当作一面普通的镜子。至于显示的东西,是使用chrome浏览器的kiosk模式,(该模式说白了就是全屏模式,没有了上面的状态栏。),开机启用kiosk模式,并打开一个网页,网页的指向的地址,是本机部署的一个NodeJS服务器。
        系统架构图:
        Image 1.png
    现在网上有很多的魔镜帖子,但是大多数服务器用的都是老外写的那个代码,神烦(不过写的很D),所以就打算自己撸一个,于是就开始了苦逼的代码之路。
    2.功能介绍:
        1)显示时间,天气的信息
        2)根据编写的问候语规则,动态生成问候语,比如节日问候、天气转凉穿衣提醒、日常问候等。
        3)人脸识别功能,系统已知的人员使用镜子时,摄像头会对使用者进行人脸识别生成动态问候语,例如,你好,薇薇
        4)实时新闻抓取,支持自己编写新闻抓取插件,系统现内置OSChina新闻,新浪科技新闻,历史上的今天三种。
        5)屏幕休眠唤醒,使用时唤醒屏幕。
    3.模块介绍:
        NodeJS服务器使用ExpressJS框架,前端模板使用EJS,系统分为:前端模块、新闻模块、JOB任务模块、问候语生成器、摄像头人脸识别模块。
    前端模块:前端模块最为简单,主要是编写显示样式,使用的是bootstrap前端框架,EJS代码较少,主要是JS逻辑比较多,主要代码:
    EJS模板代码:
    1. <!DOCTYPE html>
    2. <html>
    3.   <head>
    4.     <title><%= title %></title>
    5.     <meta name="viewport" content="width=device-width, initial-scale=1">
    6.     <link href="//cdn.bootcss.com/bootstrap/3.3.0/css/bootstrap.min.css" rel="stylesheet">
    7.     <link rel='stylesheet' href='/stylesheets/style.css' />
    8.   </head>
    9.   <body>
    10.     <div>
    11.       <div class="clock">
    12.         <div id="clock-date" class="clock-fonts-color-size-date">星期* ****年**月**日</div>
    13.         <div id="clock-hm" class="clock-fonts-color-size-hm">** : **</div>
    14.         <div id="clock-sec" class="clock-fonts-color-size-sec">**</div>
    15.       </div>

    16.       <div class="weather">
    17.         <div id="todaytemp" class="weather-today">*℃~*℃</div>
    18.         <div id="todayweather" class="weather-today">多云</div>
    19.         <div id="todaywind" class="weather-today">西北风 3-4级</div>
    20.         <div id="nowtemp" class="weather-today">实时温度:5℃(5分钟前更新)</div>
    21.         <div id="airstatus" class="weather-today">空气质量:优(30)</div>
    22.       </div>
    23.     </div>

    24.     <div class="welcome" id = "welcome">
    25.       你好,陌生人。
    26.     </div>

    27.     <div class="news" id = "news">
    28.       <div id="title" class="title"></div>
    29.       <div id="abstract" class="abstract"><div>
    30.     </div>
    31.    
    32.     <!-- javascripts -->
    33.     <script src="//cdn.bootcss.com/jquery/2.1.1/jquery.min.js"></script>
    34.     <script src="//cdn.bootcss.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
    35.     <script src="//cdn.bootcss.com/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>
    36.     <script src="//cdn.bootcss.com/jquery-backstretch/2.0.4/jquery.backstretch.min.js"></script>
    37.     <script src="/javascripts/index.js"></script>
    38.     <script src="/javascripts/socket.io/socket.io.js"></script>
    39.   </body>
    40. </html>
    复制代码
    JS代码:
    1. /*
    2. * @Author: Nicot
    3. * @Date:   2016-03-29 23:12:03
    4. * @Last Modified by:   Nicot
    5. * @Last Modified time: 2018-01-09 20:50:36
    6. */

    7. //落日时间
    8. var ss = {
    9.     ssh: 18,
    10.     ssm: 0
    11. };

    12. var sr = {
    13.     srh: 6,
    14.     srm: 0
    15. };
    16. jQuery(document).ready(function() {

    17.     $.backstretch("/images/black.png");
    18.     $.updateDateTime(document);
    19.    
    20.     setInterval(function() {
    21.         //更新时间
    22.         $.updateDateTime(document);
    23.     },1000);

    24.     var socket = io();

    25.     socket.on('connect', function() {
    26.         socket.emit('hello', '你大爷');
    27.     });

    28.     socket.on('welcome', function(msg) {
    29.         var welcome = document.getElementById('welcome');
    30.         var date = new Date();
    31.         console.log(msg);
    32.         var welcomeMsg = JSON.parse(msg);
    33.         if(welcomeMsg.type == 'come' || welcomeMsg.type == 'connect') {
    34.             if(date.getHours() >= sr.srh && date.getHours() < 9) {
    35.                 welcome.innerText = '早上好,' + welcomeMsg.msg + ',开心快乐每一天哦!';
    36.             } else if(date.getHours() >= 12 && date.getHours() < ss.ssh) {
    37.                 welcome.innerText = '下午好,' + welcomeMsg.msg + '^_^';
    38.             } else if(date.getHours() >= 9 && date.getHours() < 12) {
    39.                 welcome.innerText = '上午好,' + welcomeMsg.msg + '^_^';
    40.             } else {
    41.                 welcome.innerText = '晚上好,' + welcomeMsg.msg + '^_^';
    42.             }
    43.         } else {
    44.              welcome.innerText = welcomeMsg.msg;
    45.         }
    46.         
    47.     });

    48.     socket.on('weather', function(msg) {
    49.         $.updateWeather(document, msg);
    50.     });

    51.     socket.on('news', function(msg) {
    52.         var title = document.getElementById('title');
    53.         var abstract = document.getElementById('abstract');
    54.         var news = JSON.parse(msg);
    55.         title.innerText = '[' + news.type + ']' + news.title;
    56.         abstract.innerText = news.abstract == '' ? '' : news.abstract.substring(0, 100) + '...';
    57.     });
    58. });

    59. (function($){
    60.     Date.prototype.Format = function (fmt) { //author: meizz   
    61.         var o = {  
    62.             "M+": this.getMonth() + 1, //月份   
    63.             "d+": this.getDate(), //日   
    64.             "H+": this.getHours(), //小时   
    65.             "m+": this.getMinutes(), //分   
    66.             "s+": this.getSeconds(), //秒   
    67.             "q+": Math.floor((this.getMonth() + 3) / 3), //季度   
    68.             "S": this.getMilliseconds() //毫秒   
    69.         };  
    70.         if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));  
    71.         for (var k in o)  
    72.         if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));  
    73.         return fmt;  
    74.     }

    75.     $.updateDateTime = function(doc) {
    76.         var clockhm = doc.getElementById('clock-hm');
    77.         var clocksec = doc.getElementById('clock-sec');
    78.         var clockdate = doc.getElementById('clock-date');
    79.         var weekArr = ['一', '二', '三', '四', '五', '六', '日'];
    80.         var week = weekArr[new Date().getDay()];
    81.         clockdate.innerText = new Date().Format("yyyy年MM月dd日") + " " + "星期"  + week;
    82.         clockhm.innerText = new Date().Format("HH:mm");
    83.         clocksec.innerText = new Date().Format("ss");
    84.     }

    85.     $.updateWeather = function(doc, msg) {
    86.         var weather = JSON.parse(msg);
    87.         if(weather.type == 'nowWeather') {
    88.             var nowtemp = doc.getElementById('nowtemp');
    89.             var updateTime = new Date(weather.updateTime);
    90.             nowtemp.innerText = '实时温度:' + weather.weather.tmp + '℃ 天气:' + weather.weather.cond_txt;
    91.         } else if(weather.type == 'nowAir') {
    92.             var airstatus = doc.getElementById('airstatus');
    93.             var qlty = weather.air.qlty == undefined ? '极好': weather.air.qlty;
    94.             airstatus.innerText = '空气质量:' + qlty + '(' + weather.air.aqi + ')';
    95.         } else if(weather.type == 'todayWeather') {
    96.             var todaytemp = doc.getElementById('todaytemp');
    97.             var todayweather = doc.getElementById('todayweather');
    98.             var todaywind = doc.getElementById('todaywind');
    99.             var today = weather.forecast[0];
    100.             todaytemp.innerText = today.tmp_min + '℃ ~ ' + today.tmp_max + '℃';
    101.             ss.ssh = parseInt(today.ss.split(':')[0]);
    102.             ss.ssm = parseInt(today.ss.split(':')[1]);
    103.             sr.srh = parseInt(today.sr.split(':')[0]);
    104.             sr.srm = parseInt(today.sr.split(':')[1]);
    105.             var date = new Date();
    106.             if(date.getHours() > ss.ssh && date.getMinutes() > ss.ssm) {
    107.                 todayweather.innerText = today.cond_txt_n;
    108.             } else {
    109.                 todayweather.innerText = today.cond_txt_d;
    110.             }

    111.             todaywind.innerText = today.wind_dir + ' ' + today.wind_sc + '级';
    112.         }
    113.     }
    114. })(jQuery);
    复制代码
    JS代码还引入了了socket.io的客户端,用于实时通信。
    新闻模块:
    新闻模块先包含三种新闻抓取,分别是OSChina、新浪科技、历史上的今天,新闻模块可扩展,只要添加相应的抓取代码即可。网页爬虫使用:cheerio插件。
    JOB任务模块:
    任务模块主要是系统的一些功能的定时任务,如:定时天气情况、空气情况、实时天气的获取与推送,问候语的定时生成与推送、新闻的定时抓取与推送、摄像头模块的检测与重启等,定时任务使用:node-schedule模块。
    问候语生成器:
    问候语生成器使用vm模块,动态编译用户定义的规则,生成问候语,用于支持节日问候、天气提醒等功能。规则代码例子:
    1. /*
    2. * @Author: Nicot
    3. * @Date:   2018-01-03 00:25:31
    4. * @Last Modified by:   Nicot
    5. * @Last Modified time: 2018-01-07 15:28:56
    6. */

    7. module.exports = {
    8.     random: ['weather', 'festival'],
    9.     connect: [
    10.         {
    11.             expression: 'true',
    12.             characters: ['很高兴见到你!', '你来啦~', '恭喜您成功连接系统'],
    13.             level: -1
    14.         }
    15.     ],
    16.     weather: [
    17.         {
    18.             expression: 'weather.temp < -1',
    19.             characters: ['天气有点冷~,多穿点衣服!', '天气凉,注意保暖哦', 'so cold ~~'],
    20.             level: 2
    21.         },
    22.         {
    23.             expression: 'weather.wind > 4',
    24.             characters: ['今天有大风哦,注意安全!'],
    25.             level: 1
    26.         },
    27.         {
    28.             expression: 'weather.weather == 0',
    29.             characters: ['今天有雨,别忘记带伞!', '今天可能会下雨哦~~'],
    30.             level: 3
    31.         },
    32.         {
    33.             expression: 'true',
    34.             characters: ['今天天气不错,哈哈', '风和日丽啊,祝你开心哦~'],
    35.             level: -1
    36.         }
    37.     ],
    38.     festival: [
    39.         {
    40.             expression: 'date.m == 2 && $.date.d == 18',
    41.             characters: ['祝你生日快乐哦', '生日快乐,哈哈'],
    42.             level: 3
    43.         },
    44.         {
    45.             expression: 'date.m == 2 && $.date.d == 25',
    46.             characters: ['薇薇生日快乐哦!'],
    47.             level: 3
    48.         },
    49.         {
    50.             expression: 'festival.indexOf("元旦") >= 0',
    51.             characters: ['元旦快乐~~'],
    52.             level: 3
    53.         }
    54.     ]
    55. };
    复制代码
    摄像头人脸识别模块:
    人脸识别模块主要代码使用python编写,主要硬件包括:摄像头X1,人体识别模块X1,红外传感器X1(莫名其妙烧坏了。。。。),系统在启动时会启动一个子进程,执行python脚本,并且会定时检验脚本的存活,如果python脚本推出,则会重启脚本,人脸识别使用face++提供的接口,首先根据人体识别模块与红外传感器判断是否有人,如果有人则进行拍照,然后进行人脸识别,如果在系统内置的集合中找到该人脸,则给系统推送一个消息,并将人名推送给前台显示页面进行问候语显示。当检测到人走之后,会显示其他问候语。
    4.应用源代码:https://github.com/NinthCode/pandora.git
    5.硬件连接图:
    微信图片_20180102232521.jpg
    6.过程照片:
    原子镜

    原子镜

    原子镜

    未上镜子前
    微信图片_20180102232539.jpg
    屏幕
    微信图片_20180102232536.jpg
    7.作品照片:
    微信图片_20180109211713.jpg 微信图片_20180102232514.jpg 微信图片_20180102232518.jpg 微信图片_20180109211621.jpg 微信图片_20180109211709.jpg 微信图片_20180109211716.jpg 微信图片_20180109211719.jpg 微信图片_20180102232431.jpg 微信图片_20180102232437.jpg
    8.作品视频:
    http://player.youku.com/embed/XMzMwNDY3NDI4MA==
    9.源代码压缩包:
    游客,如果您要查看本帖隐藏内容请回复
    回复

    使用道具 举报

    该用户从未签到

    发表于 2018-1-10 10:10:02 | 显示全部楼层
    晚饭必吃,还会吃很多。
    天冷,你也多穿点
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    发表于 2018-2-1 19:39:59 | 显示全部楼层
    大哥 能交个朋友吗 我自从看了你的帖子 也想做一个 材料都买到了 就差动手了+_+
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    发表于 2018-3-12 20:22:07 | 显示全部楼层
    学习了  大神能否留个QQ  我在做毕业设计  就是这个 能指导下我不
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    难过
    1 小时前
  • 签到天数: 3240 天

    连续签到: 10 天

    [LV.Master]伴坛终老

    发表于 2018-9-21 20:34:45 | 显示全部楼层
    原子镜?哪里有卖,能给个链接吗  谢谢
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    发表于 2018-10-17 12:45:16 | 显示全部楼层
    你好,这个就是传说中的老变小 那个设计模型吗?谢谢
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    发表于 2018-12-20 08:44:15 来自手机 | 显示全部楼层
    很不错的分享。。。。。。
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /2 下一条



    手机版|小黑屋|与非网

    GMT+8, 2024-4-20 12:09 , Processed in 0.206525 second(s), 36 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2020, Tencent Cloud.