本帖最后由 左岸cpx 于 2016-8-31 10:06 编辑
前言:首先对 论坛表达一下歉意,因为八月份在忙全国大学生物联网设计竞赛的事情,所以试用报告总共才更新了 6篇,希望见谅,不过并不会影响顺利结项,后面我会抓紧时间跟进的。在西安总决赛的时候,在会场上居然看到了爱迪生的身影,是成都大学的一支队伍将爱迪生用到了飞行器上,做视频回传的。看来,我们的爱迪生在高校大学生中还是比较有影响力的。OK ,进入正题。上一节讲了如何让爱迪生实现数字频率计的功能,这一节我要讲一下如何实现socket通信和web界面。这两节内容都是为了我结项做准备的,所以后面的结项报告需要对照组这两篇试用报告来看。这一节涉及到的编程知识,客户端方面:html, javascript, css。服务器方面:node.js和一个叫做express的框架。基础知识还是蛮多的,可能有读者会问,我没学过这些语言怎么办。我在这里告诉大家,没关系的,我也是初学者,对这些语言知识了解个大概,根据XDK里面提供的Demo程序来学习并修改就行了。 报告5:频率计:
- https://bbs.elecfans.com/forum.php?mod=viewthread&tid=929223&extra=
复制代码
步骤1:客户端通过html语言写一个静态网页,是这个样子的。
相当于web前端开发,所以我们还需要用CSS和JavaScript来写两个文件。文件是在XDK的Demo程序里面改的,附件里可以看到工程文件。 步骤2:服务器服务器这边我们用node.js语言开发,XDK里面有个Web Sockets的Demo,如下图所示,一次点击3个红色方框,就可以建立起一个Socket通信程序。
在这个Demo中修改,来实现自己的功能。
1、修改这一段,改成控制继电器的功能
- var mraa = require('mraa'); //require mraa
- var myOnboardLed = new mraa.Gpio(13); //LED hooked up to digital pin 13 (or built in pin on Intel Galileo Gen2 as well as Intel Edison)
- myOnboardLed.dir(mraa.DIR_OUT); //set the gpio direction to output
- var ledState = true; //Boolean to hold the state of Led
复制代码
2、这一段添加了express框架,有了框架,方便了服务器开发速度
- var express = require('express');
- var app = express();
- var path = require('path');
- var http = require('http').Server(app);
- var io = require('socket.io')(http);
复制代码
3、这一段是socket通信的服务器方面程序,和下面的4相对应
- app.get('/', function(req, res) {
- //Join all arguments together and normalize the resulting path.
- res.sendFile(path.join(__dirname + '/client', 'index.html'));
- });
- //Allow use of files in client folder
- app.use(express.static(__dirname + '/client'));
- app.use('/client', express.static(__dirname + '/client'));
- //Socket.io Event handlers
- io.on('connection', function(socket) {
- console.log("n Add new User: u"+connectedUsersArray.length);
- if(connectedUsersArray.length > 0) {
- var element = connectedUsersArray[connectedUsersArray.length-1];
- userId = 'u' + (parseInt(element.replace("u", ""))+1);
- }
- else {
- userId = "u0";
- }
- console.log('a user connected: '+userId);
- io.emit('user connect', userId);
- connectedUsersArray.push(userId);
- console.log('Number of Users Connected ' + connectedUsersArray.length);
- console.log('User(s) Connected: ' + connectedUsersArray);
- io.emit('connected users', connectedUsersArray);
-
- socket.on('user disconnect', function(msg) {
- console.log('remove: ' + msg);
- connectedUsersArray.splice(connectedUsersArray.lastIndexOf(msg), 1);
- io.emit('user disconnect', msg);
- });
-
- socket.on('chat message', function(msg) {
- io.emit('chat message', msg);
- console.log('message: ' + msg.value);
- });
-
- socket.on('toogle led', function(msg) {
- myOnboardLed.write(ledState?1:0); //if ledState is true then write a '1' (high) otherwise write a '0' (low)
- msg.value = ledState;
- io.emit('toogle led', msg);
- ledState = !ledState; //invert the ledState
- });
-
- startSensorWatch(socket);
-
- });
- http.listen(3000, function(){
- console.log('Web server Active listening on *:3000');
- });
复制代码
4、这一段是socket通信的客户端方面程序,和上面的3对应
- var socket = io();
- var userId = "user";
- $('form').submit(function() {
- socket.emit('chat message', {value: $('#m').val(), userId: userId});
- $('#m').val('');
- return false;
- });
- $("#led-link").on('click', function(e){
- socket.emit('toogle led', {value: 0, userId: userId});
- });
- socket.on('toogle led', function(msg) {
- if(msg.value === false) {
- $('#messages').prepend($('
- Toogle LED: OFF - '+msg.userId+'
'));
- $("#led-container").removeClass("on");
- $("#led-container").addClass("off");
- $("#led-container span").text("OFF");
- }
- else if(msg.value === true) {
- $('#messages').prepend($('
- Toogle LED: ON - '+msg.userId+'
'));
- $("#led-container").removeClass("off");
- $("#led-container").addClass("on");
- $("#led-container span").text("ON");
- }
- });
- socket.on('chat message', function(msg) {
- $('#messages').prepend($('
- '+msg.value+' - '+msg.userId+'
'));
- });
- socket.on('connected users', function(msg) {
- $('#user-container').html("");
- for(var i = 0; i < msg.length; i++) {
- //console.log(msg[i]+" )msg[i] == userId( "+userId);
- if(msg[i] == userId)
- $('#user-container').append($("
"+msg[i]+" "));
- else
- $('#user-container').append($("
"+msg[i]+" "));
- }
- });
- socket.on('user connect', function(msg) {
- if(userId === "user"){
- console.log("Client side userId: "+msg);
- userId = msg;
- }
- });
- socket.on('user disconnect', function(msg) {
- console.log("user disconnect: " + msg);
- var element = '#'+msg;
- console.log(element)
- $(element).remove();
- });
- window.onunload = function(e) {
- socket.emit("user disconnect", userId);
- }
复制代码
5、这一段是我们试用报告5提到的频率计功能的实现
- var front_time = 0;
- var back_time = 0;
- var interval = 0;
- var freq = 0;
- var wave_begin = true;
- var wave = new mraa.Gpio(8);
- wave.dir(mraa.DIR_IN);
- //中断服务函数
- wave.isr(mraa.EDGE_RISING, function(){
- if(wave_begin){
- var d = new Date();
- front_time = d.getTime();
- wave_begin = false;
- }else{
- var d = new Date();
- back_time = d.getTime();
- wave_begin = true;
- interval = back_time - front_time;
- }
- });
- function startSensorWatch(socket) {
- 'use strict';
- setInterval(function () {
- var d = new Date();
- var time_now = d.getTime();
- if(time_now - back_time > 1500){
- //1.5秒超时,认为无信号,freq = 0 Hz
- interval = 0;
- }
- //计算频率
- if(0 == interval){
- freq = 0;
- }else{
- freq = 1000/interval;
- }
-
- var power = 4.0 * freq;
- console.log("power: " + power + " W");
- socket.emit("chat message", {value: power+' W', userId: userId});
- }, 2000);
- }
复制代码
步骤3:实验现象
用户连接:可以显示当前和服务器(爱迪生)连接的客户端(网页)数量,从u0, u1, u2...以此类推。 开关状态:通过鼠标点击蓝色方框内的“开关”来切换开关状态。ON或者OFF。 实时功率:测量用电器的实时功率。
所以,我们的爱迪生完成了两个工作,1:采集用电器功率。2:充当socket通信服务器。监听它的某一个端口(本文设置为3000),浏览器访问爱迪生所在ip的3000端口,即可获取此页面。
最后,本文并不是一个完整的项目,这是作为结题项目的准备工作。后面的结项报告会把试用报告5:频率计和本片试用报告6结合在一起,完成一个完成的项目(家庭电能管家:硬件+软件),敬请期待!
https://bbs.elecfans.com/forum.php?mod=viewthread&tid=929223&extra=
|