1). 简介
本文着重展示基于Embedded Linux快速开发Web应用程序访问ARM系统以便于远程操控硬件GPIO或监控其状态.文中演示实例所采用的ARM系统硬件为Toradex 基于NXP Vybrid的产品级ARM核心板Colibri VF61配合其Colibri开发板;软件框架为使用Node代码通过filesystem来访问操控硬件GPIO,创建一个简单UI并使用Express开发框架搭建一个最简web服务器并通过AJAX呼叫和客户端进行通信,最后在客户端使用Javascript配合HTML+CSS/jQuery/AJAX开发一个客户端应用程序.
Node.js是一个用于基于Javascript开发应用的服务器端的runtime环境,自带有管理文件系统模块,而Linux操作系统支持使用文件系统访问硬件设备的特性,因此可以基于Node开发应用来访问操控系统硬件GPIO设备.不过尽管Node也提供了如HTTP等模块可以用来搭建Web服务器,本文还是采用更为简单的利用Express开发框架来搭建.
客户端应用使用Javascript编程语言开发,通过浏览器执行.配合HTML和CSS, Javascript可以实现用户交互的网页开发,也就是响应式设计. 不过直接使用Javascrit进行开发需要一定周期,本文采用一个跨浏览器JavaScript库jQuery来快速实现如DOM操作,事件处理以及AJAX方法(和服务器异步通讯达到动态改变页面内容的一系列技术)使用等
2). 硬件准备
a). Colibri VF61核心板模块以及Colibri开发板载板
b). GPIO以及对应Button和LED设置如下所示, VF61最多支持99个GPIO管脚, 本文使用4个GPIO分别连接Colibri载板上面的两个Button和两个LED.
SW5, X21 Pin9 <-> GPIO-63(SODIMM_106), X11 Pin39
SW6, X21 Pin11 <-> GPIO-89(SODIMM_135), X11 Pin40
LED1, X21 Pin2 <-> GPIO-88(SODIMM_133), X11 Pin41
LED2, X21 Pin4 <-> GPIO-68(SODIMM_127), X11 Pin42
详细的关于管脚定义和GPIO号码请参考VF61手册,Colibri开发板手册以及GPIO号码映射.
3). 软件配置
a). Embedded Linux系统为Toradex官方发布image V2.5, 也可以参考这里基于OpenEmbedded框架自己编译系统image.
b). 在VF61 Embedded Linux中安装node.js并验证运行正常
-------------------
root@colibri-vf:~# opkg update
root@colibri-vf:~# opkg install nodejs
root@colibri-vf:~# node
> process.exit ()
root@colibri-vf:~#
-------------------
c). 在VF61 Embedded Linux中安装nodemon, Express和body-parse
-------------------
root@colibri-vf:~# opkg install tar
root@colibri-vf:~# curl -L https://www.npmjs.com/install.sh | sh
root@colibri-vf:~# npm install express
root@colibri-vf:~# npm install body-parser
root@colibri-vf:~# npm install -g nodemon
-------------------
4). GPIO操作
详细Embedded Linux GPIO操作请见这里,下面只用一个GPIO-63举例
a). 初始化GPIO-63并设置为Input
-------------------
root@colibri-vf:/sys/class/gpio# echo 63 > /sys/class/gpio/export
root@colibri-vf:/sys/class/gpio# echo "in" > /sys/class/gpio/gpio63/direction
-------------------
b). 查看当前GPIO-63电平
-------------------
root@colibri-vf:/sys/class/gpio/gpio63# cat /sys/class/gpio/gpio63/value
0
-------------------
c). 按下GPIO连接的Button同时查看电平
-------------------
root@colibri-vf:/sys/class/gpio/gpio63# cat /sys/class/gpio/gpio63/value
1
-------------------
5). Nodedemo1 - 使用Node.js操控GPIO
完整代码请见这里, 需创建’server.js’文件, 核心部分列出如下:
a). Filesystem 模块
-------------------
/* Modules */
var fs = require('fs'); //module to handle the file system
var debug = require('debug')('myserver'); //debug module
/* VF61 GPIO pins */
const SW5 = '63', // PTD31, 106(SODIMM)
SW6 = '89', // PTD10, 135(SODIMM)
LED1 = '88', // PTD9, 133(SODIMM)
LED2 = '68', // PTD26, 127(SODIMM)
/* Constants */
const HIGH = 1, LOW = 0;
-------------------
b). GPIO配置和操作模块
-------------------
function cfGPIO(pin, direction){......} //export pin if not exported and configure the pin direction
function rdGPIO(pin){......} //read GPIO value and return it
function wrGPIO(pin, value){......} //write value to corresponding GPIO
-------------------
c). LED根据Button状态显示模块
-------------------
function copySwToLed(){......} //Copy the SW values into the LEDs
-------------------
主函数模块,使用setinterval循环函数,第二个参数为循环间隔
-------------------
setImmediate(function cfgOurPins(){
cfGPIO(LED1, 'out'); //call cfGPIO to configure pins
cfGPIO(LED2, 'out');
cfGPIO(SW5, 'in');
cfGPIO(SW6, 'in');
setInterval(copySwToLed, 50); //poll the GPIO and copy switches status to LEDs
});
-------------------
d). 在VF61上面执行’server.js’, 并通过按键来验证LED显示
-------------------
node server.js
-------------------
6). Nodedemo2 - 创建webserver和最简web UI来远程操控GPIO
完整代码请见这里
a). 修改’server.js’, 创建Webserver
-------------------
/* Modules */
var express = require('express'); //webserver module
var bodyParser = require('body-parser'); //parse JSON encoded strings
var app = express();
/* Constants */
const HIGH = 1, LOW = 0, IP_ADDR = '10.20.1.108', PORT_ADDR = 3000;
//Using Express to create a server
app.use(express.static(__dirname));
var server = app.listen(PORT_ADDR, IP_ADDR, function () {
var host = server.address().address;
var port = server.address().port;
var family = server.address().family;
debug('Express server listening at http://%s:%s %s', host, port, family);
});
-------------------
b). 修改’server.js’, 增加HTTP POST接收并处理返回数据部分
-------------------
app.use(bodyParser.urlencoded({ //to support URL-encoded bodies, must come before routing
extended: true
}));
app.route('/gpio') //used to unite all the requst types for the same route
.post(function (req, res) { //handles incoming POST requests
var serverResponse = {status:''};
var btn = req.body.id, val = req.body.val; // get the button id and value
if(val == 'on'){ //if button is clicked, turn on the leds
wrGPIO(LED1, HIGH);
wrGPIO(LED2, HIGH);
debug('Client request to turn LEDs on');
serverResponse.status = 'LEDs turned on.';
res.send(serverResponse); //send response to the server
}
else{ //if button is unclicked, turn off the leds
wrGPIO(LED1, LOW);
wrGPIO(LED2, LOW);
debug('Client request to turn LEDs off');
serverResponse.status = 'LEDs turned off.';
res.send(serverResponse); //send response to the server
}
});
setImmediate(function cfgOurPins(){
......
setInterval(copySwToLed, 50); //poll the GPIO and copy switches status to LEDs
});
-------------------
c). 在当前文件夹创建’index.html’
./ 请从这里下载jQuery库并放在同一文件夹
./ ‘index.html’代码如下
-------------------
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Colibri VF61 node.js webserver</title>
<!-- Add jQuery library -->
<script src="jquery-1.12.3.js"></script>
<script type="text/javascript" src="client.js"></script>
</head>
<body>
<h1>Access to the VF61 GPIO using Node.js and AJAX</h1>
<form>
<input type="checkbox" class="btn" id="btn1">
<label for="btn1" id="btn1l" style="color:red">OFF</label>
</form>
</body>
</html>
-------------------
d). 在当前文件夹创建’client.js’, 用来处理客户端操作
-------------------
$(function(){
$(".btn").click(function clickHandling(){ //if element of class "btn" is clicked
var btn_status = {id:"", val:""}; //data to be sent to the server
if(this.checked){ //check whether button is pressed or not
$(this).siblings().html("ON").css("color","green"); //changes label and color
btn_status.id = $(this).attr("id"); //get which button was clicked
btn_status.val = "on"; //tell the server the button is clicked
}
else{ //if button was unclicked
$(this).siblings().html("OFF").css("color","red"); //changes label and color
btn_status.id = $(this).attr("id"); //get which button was clicked
btn_status.val = "off"; //tell the server the button is unclicked
}
$.post("/gpio", btn_status, function (data, status){ //send data to the server via HTTP POST
if(status == "success"){ //if server responds ok
console.log(data);//print server response to the console
}
},"json"); //server response shuld be in JSON encoded format
});
});
-------------------
e). 在VF61运行’server.js’, 启动服务
-------------------
root@colibri-vf:~# DEBUG=myserver node server.js
myserver Starting VF61 GPIO control +0ms
myserver Express server listening at http://10.20.1.108:3000 IPv4 +711ms
myserver Configuring GPIO88 as out +46ms
myserver Configuring GPIO68 as out +9ms
myserver Configuring GPIO63 as in +3ms
myserver Configuring GPIO89 as in +2ms
-------------------
f). 在客户端浏览器查看
登录http://10.20.1.108:3000,在打开的页面操作checkbox来控制LED灯
7). Nodedemo3 - 升级友好界面客户端UI来远程操控GPIO
完整代码请见这里
a). 修改’index.html’, 使用Bootstrap框架修改显示效果适配移动设备
-------------------
<!-- Using bootstrap -->
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
<script. src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>
<script. type="text/javascript" src="client.js"></script>
</head>
-------------------
b). 对应修改’server.js’和’client.js’
SW 按键点击事件处理, SW1切换当前LED焦点, SW2改变当前LED状态
c). 在VF61上面同上运行server.js启动,在客户端浏览器登录http://10.20.1.108:3000查看
文章评论(0条评论)
登录后参与讨论