NinthCode 发表于 2018-1-9 21:54:57

基于树莓派的智能魔镜

本帖最后由 ky123 于 2018-1-31 14:05 编辑

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

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

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

    <div class="news" id = "news">
      <div id="title" class="title"></div>
      <div id="abstract" class="abstract"><div>
    </div>
   
    <!-- javascripts -->
    <script src="//cdn.bootcss.com/jquery/2.1.1/jquery.min.js"></script>
    <script src="//cdn.bootcss.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
    <script src="//cdn.bootcss.com/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>
    <script src="//cdn.bootcss.com/jquery-backstretch/2.0.4/jquery.backstretch.min.js"></script>
    <script src="/javascripts/index.js"></script>
    <script src="/javascripts/socket.io/socket.io.js"></script>
</body>
</html>
JS代码:/*
* @Author: Nicot
* @Date:   2016-03-29 23:12:03
* @Last Modified by:   Nicot
* @Last Modified time: 2018-01-09 20:50:36
*/

//落日时间
var ss = {
    ssh: 18,
    ssm: 0
};

var sr = {
    srh: 6,
    srm: 0
};
jQuery(document).ready(function() {

    $.backstretch("/images/black.png");
    $.updateDateTime(document);
   
    setInterval(function() {
      //更新时间
      $.updateDateTime(document);
    },1000);

    var socket = io();

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

    socket.on('welcome', function(msg) {
      var welcome = document.getElementById('welcome');
      var date = new Date();
      console.log(msg);
      var welcomeMsg = JSON.parse(msg);
      if(welcomeMsg.type == 'come' || welcomeMsg.type == 'connect') {
            if(date.getHours() >= sr.srh && date.getHours() < 9) {
                welcome.innerText = '早上好,' + welcomeMsg.msg + ',开心快乐每一天哦!';
            } else if(date.getHours() >= 12 && date.getHours() < ss.ssh) {
                welcome.innerText = '下午好,' + welcomeMsg.msg + '^_^';
            } else if(date.getHours() >= 9 && date.getHours() < 12) {
                welcome.innerText = '上午好,' + welcomeMsg.msg + '^_^';
            } else {
                welcome.innerText = '晚上好,' + welcomeMsg.msg + '^_^';
            }
      } else {
             welcome.innerText = welcomeMsg.msg;
      }
      
    });

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

    socket.on('news', function(msg) {
      var title = document.getElementById('title');
      var abstract = document.getElementById('abstract');
      var news = JSON.parse(msg);
      title.innerText = '[' + news.type + ']' + news.title;
      abstract.innerText = news.abstract == '' ? '' : news.abstract.substring(0, 100) + '...';
    });
});

(function($){
    Date.prototype.Format = function (fmt) { //author: meizz   
      var o = {
            "M+": this.getMonth() + 1, //月份   
            "d+": this.getDate(), //日   
            "H+": this.getHours(), //小时   
            "m+": this.getMinutes(), //分   
            "s+": this.getSeconds(), //秒   
            "q+": Math.floor((this.getMonth() + 3) / 3), //季度   
            "S": this.getMilliseconds() //毫秒   
      };
      if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
      for (var k in o)
      if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o) : (("00" + o).substr(("" + o).length)));
      return fmt;
    }

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

    $.updateWeather = function(doc, msg) {
      var weather = JSON.parse(msg);
      if(weather.type == 'nowWeather') {
            var nowtemp = doc.getElementById('nowtemp');
            var updateTime = new Date(weather.updateTime);
            nowtemp.innerText = '实时温度:' + weather.weather.tmp + '℃ 天气:' + weather.weather.cond_txt;
      } else if(weather.type == 'nowAir') {
            var airstatus = doc.getElementById('airstatus');
            var qlty = weather.air.qlty == undefined ? '极好': weather.air.qlty;
            airstatus.innerText = '空气质量:' + qlty + '(' + weather.air.aqi + ')';
      } else if(weather.type == 'todayWeather') {
            var todaytemp = doc.getElementById('todaytemp');
            var todayweather = doc.getElementById('todayweather');
            var todaywind = doc.getElementById('todaywind');
            var today = weather.forecast;
            todaytemp.innerText = today.tmp_min + '℃ ~ ' + today.tmp_max + '℃';
            ss.ssh = parseInt(today.ss.split(':'));
            ss.ssm = parseInt(today.ss.split(':'));
            sr.srh = parseInt(today.sr.split(':'));
            sr.srm = parseInt(today.sr.split(':'));
            var date = new Date();
            if(date.getHours() > ss.ssh && date.getMinutes() > ss.ssm) {
                todayweather.innerText = today.cond_txt_n;
            } else {
                todayweather.innerText = today.cond_txt_d;
            }

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

module.exports = {
    random: ['weather', 'festival'],
    connect: [
      {
            expression: 'true',
            characters: ['很高兴见到你!', '你来啦~', '恭喜您成功连接系统'],
            level: -1
      }
    ],
    weather: [
      {
            expression: 'weather.temp < -1',
            characters: ['天气有点冷~,多穿点衣服!', '天气凉,注意保暖哦', 'so cold ~~'],
            level: 2
      },
      {
            expression: 'weather.wind > 4',
            characters: ['今天有大风哦,注意安全!'],
            level: 1
      },
      {
            expression: 'weather.weather == 0',
            characters: ['今天有雨,别忘记带伞!', '今天可能会下雨哦~~'],
            level: 3
      },
      {
            expression: 'true',
            characters: ['今天天气不错,哈哈', '风和日丽啊,祝你开心哦~'],
            level: -1
      }
    ],
    festival: [
      {
            expression: 'date.m == 2 && $.date.d == 18',
            characters: ['祝你生日快乐哦', '生日快乐,哈哈'],
            level: 3
      },
      {
            expression: 'date.m == 2 && $.date.d == 25',
            characters: ['薇薇生日快乐哦!'],
            level: 3
      },
      {
            expression: 'festival.indexOf("元旦") >= 0',
            characters: ['元旦快乐~~'],
            level: 3
      }
    ]
};摄像头人脸识别模块:
人脸识别模块主要代码使用python编写,主要硬件包括:摄像头X1,人体识别模块X1,红外传感器X1(莫名其妙烧坏了。。。。),系统在启动时会启动一个子进程,执行python脚本,并且会定时检验脚本的存活,如果python脚本推出,则会重启脚本,人脸识别使用face++提供的接口,首先根据人体识别模块与红外传感器判断是否有人,如果有人则进行拍照,然后进行人脸识别,如果在系统内置的集合中找到该人脸,则给系统推送一个消息,并将人名推送给前台显示页面进行问候语显示。当检测到人走之后,会显示其他问候语。
4.应用源代码:https://github.com/NinthCode/pandora.git
5.硬件连接图:

6.过程照片:
原子镜

未上镜子前

屏幕

7.作品照片:

8.作品视频:
http://player.youku.com/embed/XMzMwNDY3NDI4MA==
9.源代码压缩包:
**** Hidden Message *****

eefocus_3735213 发表于 2021-5-7 18:23:18

666666666666

zxwycp 发表于 2019-12-19 18:00:58

不错看看

uuzc1 发表于 2019-12-15 13:13:22

基于树莓派的智能魔镜

学员2015 发表于 2019-9-17 07:05:45

学习一下

Chen-380452 发表于 2019-2-26 16:06:19

不错的作品!!

纯天然绿色学渣 发表于 2018-12-28 14:29:08

楼主6666

lyx233 发表于 2018-12-20 08:44:15

很不错的分享。。。。。。

dk6002 发表于 2018-12-3 16:25:27

学习,谢谢!!!

疾风kang 发表于 2018-11-20 16:02:43

牛批哦,,,,,,,,,,,,,,,,,,,,,,,
页: [1] 2
查看完整版本: 基于树莓派的智能魔镜

Baidu
map