Intel物联网开发者专区
直播中

netlhx

10年用户 156经验值
擅长:嵌入式技术
私信 关注
[讨论]

【Intel Edison试用体验】家庭网关模拟(项目结贴)

本帖最后由 netlhx 于 2016-8-10 08:45 编辑

INTEL EDISON实现家庭网关模拟(结题篇)

本贴实现申请开发板提出的任务:将EDISON打造成一个家用IOT网关。

所谓的网关,其实也可以叫中央控制器(IOT HUB),主要是收集各离散节点的信息,在终端上显示;另外就是通过手持终端来发出各种指令控制,控制各离散节点设备的运行。

另外这里所说的模拟,是因为笔者的现实生活还没有实现智能家居化,所以家里也没有智能家居相关设备,相关实现均是在EDISON上使用GROVE的部分元器件实现。

一、功能概述
  • INTEL EDISON作为中央控制节点,收集及接收来自终端节点的信息,并执行相应的控制指令
  • 温度传感器收集温度信息
  • 光照传感器收集光照强度,光照强度值可以用来控制灯光的强弱
  • 无级调光,通过PWM来控制灯的亮度(通过LED灯来模拟)
  • 舵机控制,比如调整自动浇花器的位置
  • 开关控制,打开或关闭指定位置的照明灯(通过LED灯来模拟)
  • LCD显示,模拟家中的LED显示屏

二、硬件连接
  • 温度传感器连接到扩展板的A1
  • 光照传感器连接到扩展板的A2
  • PWM输出连接到扩展板的D5
  • 舵机连接到扩展板的D3
  • LCD连接到I2C接口


整体连接效果如图

IMG_20160720_110150.jpg

在原来的计划中,舵机控制是准备实现的。只是可惜在实验中,舵机被烧坏了。

IMG_20160720_110841.jpg

烧坏的舵机,估计是在试验的时候,正反转设置的时候参数有问题,可惜!

三、设计思路

程序设计语言使用NODE.JS做为服务端控制语言,这也是INTEL主推的一个物联网应用中的开发语言。NODE.JS调用底层的MRAA及UPM库来控制硬件。硬件控制GROVE的实验请参考https://bbs.elecfans.com/forum.ph ... d&tid=919288&extra=

INTEL官方提供的诸多IDE中,XDK实在太臃肿,加上使用NODE.JS只需要一个VIM即可实现编程、调试。另外C/C++类编程语言在调试过程中需要反复修改、编译、调试,步骤略显繁琐。所以这里使用轻便的NODE.JS来实现服务端功能。

服务器端使用比较原生的HTTP模块搭建了一个简单的WEB服务器,客户端可以使用HTTP请求来获取或者上传相应控制指令。

数据通信格式

服务器与客户端之前使用JSON来进行通信,一次典型的通信数据如下
  1. {"ds2":"1","title":"Hello, world","pwm":"51"}
上述JSON数据中,第一部分是客户端通过HTTP POST方法上传的要求服务器执行的信息
  • "ds2":"1" 请求EDISON打开板载的DS2指示灯,起到模拟开灯/关灯的效果
  • "title":"Hello, world" 请求将LCD的显示内容设置为HELLO, WORLD
  • "pwm":"51" 请求将连接在D5上的LED灯亮度值设置为51%


下面一部分JSON数据是将EDISON上的一些信息反馈给客户端,用户可以使用HTTP来显示这些内容,如下图

QQ截图20160721211050.png

简易的客户端APP实现

除了可以使用浏览器之外,专门设计了一个简单的ANDROID客户端程序,界面很简单,如下图

QQ截图20160721211334.png

APP上面是显示区域,显示从服务器端获取的数据信息;中间为控制区域,只设计了控制EDISON的部分接口;最下面是刷新按钮,用来刷新数据。

四、实现关键代码

程序代码使用NODE.JS来实现,调用底层的MRAA及UPM库来实现相关操作。
完整控制代码如下
  1. var http = require('http');
  2. var query = require('querystring');
  3. var mraa = require('mraa');
  4. var grove = require('jsupm_grove');
  5. var LCD = require('jsupm_i2clcd');
  6. var SERVO = require('jsupm_servo');
  7. var os = require('os');

  8. var lcd = new LCD.Jhd1313m1(6, 0x3E, 0x62);
  9. var hostname = os.hostname().toString();
  10. var ipaddr = os.networkInterfaces()['wlan0'][0]['address'].toString();

  11. var light = new grove.GroveLight(2);
  12. var temp = new grove.GroveTemp(1);

  13. var lightValue = light.value();
  14. var tempValue = temp.value();

  15. //var servo = new SERVO.ES08A(3);
  16. var led_pwm = new mraa.Pwm(6);
  17. led_pwm.enable(true); //must enable

  18. var ds2 = new mraa.Gpio(13);
  19. ds2.dir(mraa.DIR_OUT);
  20. ds2.write(1);

  21. led_pwm.write(0);
  22. //servo.setAngle(90);

  23. lcd.clear();
  24. lcd.setCursor(0, 0);
  25. lcd.write('Intel Edison IoT');

  26. var status = {};

  27. status['host'] = hostname;
  28. status['ipaddr'] = ipaddr;
  29. status['title'] = 'Intel Edison IoT';

  30. setInterval(function() {
  31.         status['temp'] = temp.value().toString();
  32.         status['light'] = light.value().toString();
  33. }, 2000);

  34. var server = http.createServer(function(req, res) {
  35.         switch(req.method) {
  36.                 case 'GET':
  37.                         //res.writeHead(200, {'Content-Type': 'application/json'});
  38.                         //res.end(JSON.stringify(status));
  39.                         break;

  40.                 case 'POST':
  41.                         var content = "";
  42.                         req.setEncoding('utf8');
  43.                         req.on('data', function(chunk) {
  44.                                 content += chunk;
  45.                         });

  46.                         req.on('end', function() {
  47.                                 console.log(content);
  48.                                 status['title'] = JSON.parse(content)['title'];
  49.                                 status['pwm'] = JSON.parse(content)['pwm'];
  50.                                 status['ds2'] = JSON.parse(content)['ds2'];
  51.                                 console.log(status);
  52.                                 lcd.clear();
  53.                                 lcd.setCursor(0, 0);
  54.                                 lcd.write(status['title'].toString());

  55.                                 led_pwm.write(Number(status['pwm']) / 100);
  56.                                 ds2.write(Number(status['ds2']));



  57.                         });
  58.                         break;

  59.                 default:
  60.                         break;
  61.         }
  62.         res.writeHead(200, {'Content-Type': 'application/json'});
  63.         res.end(JSON.stringify(status));
  64. });

  65. server.listen(8000);
目前代码测试正常,不过不排除潜在的BUG,希望各位有时间的话测试。

客户端使用ANDROID,编写一个简单APP来显示及控制节点。部分关键代码如下
  1. host = (TextView)findViewById(R.id.host);
  2.         ipAddr = (TextView)findViewById(R.id.ipAddr);
  3.         light = (TextView)findViewById(R.id.light);
  4.         temp = (TextView)findViewById(R.id.temp);

  5.         pwm = (SeekBar)findViewById(R.id.pwmSeekBar);
  6.         lcd = (EditText)findViewById(R.id.lcd);
  7.         ds2 = (Button)findViewById(R.id.switchButton);

  8.         postButton = (Button)findViewById(R.id.postButton);

  9.         info = new JSONObject();



  10.         postButton.setOnClickListener(new View.OnClickListener() {
  11.             @Override
  12.             public void onClick(View v) {
  13.                 try {
  14.                     info.put("pwm", "" + pwm.getProgress());
  15.                     info.put("title", lcd.getText().toString());
  16.                     //info.put("ds2", String.valueOf(0));
  17.                 } catch (JSONException e) {
  18.                     e.printStackTrace();
  19.                 }
  20.                 new SendJsonTask().execute(info);

  21.             }
  22.         });

  23.         ds2.setOnClickListener(new View.OnClickListener() {
  24.             @Override
  25.             public void onClick(View v) {

  26.                 try {
  27.                     if(ds2.getText() == "关") {
  28.                         info.put("ds2", "0");
  29.                         ds2.setText("开");

  30.                     }
  31.                     else {
  32.                         info.put("ds2", "1");
  33.                         ds2.setText("关");
  34.                     }
  35.                 } catch (JSONException e) {
  36.                     e.printStackTrace();
  37.                 }

  38.                 ds2.setEnabled(false);

  39.             }
  40.         });

  41.     }

  42.    class SendJsonTask extends AsyncTask
  43.    {

  44.        @Override
  45.        protected String doInBackground(JSONObject... params) {

  46.            StringBuilder *** = new StringBuilder();

  47.            String http = "http://192.168.99.221:8000/";


  48.            HttpURLConnection urlConnection=null;
  49.            try {
  50.                URL url = new URL(http);
  51.                urlConnection = (HttpURLConnection) url.openConnection();
  52.                urlConnection.setDoInput(true);
  53.                urlConnection.setDoOutput(true);
  54.                urlConnection.setRequestMethod("POST");
  55.                urlConnection.setUseCaches(false);
  56.                urlConnection.setConnectTimeout(10000);
  57.                urlConnection.setReadTimeout(10000);
  58.                urlConnection.setRequestProperty("Content-Type","application/json");

  59.                urlConnection.connect();


  60.                OutputStreamWriter out = new   OutputStreamWriter(urlConnection.getOutputStream());
  61.                Log.d("JSON", params[0].toString());

  62.                out.write(params[0].toString());
  63.                out.close();

  64.                int HttpResult =urlConnection.getResponseCode();
  65.                if(HttpResult == HttpURLConnection.HTTP_OK){
  66.                    BufferedReader br = new BufferedReader(new InputStreamReader(
  67.                            urlConnection.getInputStream(),"utf-8"));
  68.                    String line = null;
  69.                    while ((line = br.readLine()) != null) {
  70.                        ***.append(line );
  71.                    }
  72.                    br.close();

  73.                    Log.d("JSON", ***.toString());

  74.                    return ***.toString();

  75.                }else{
  76.                    System.out.println(urlConnection.getResponseMessage());
  77.                }
  78.            } catch (MalformedURLException e) {

  79.                e.printStackTrace();
  80.            }
  81.            catch (IOException e) {

  82.                e.printStackTrace();
  83.            }

  84.            finally{
  85.                if(urlConnection!=null)
  86.                    urlConnection.disconnect();
  87.            }

  88.            return null;
  89.        }

  90.        @Override
  91.        protected void onPostExecute(String data)
  92.        {
  93.            super.onPostExecute(data);
  94.            try {
  95.                JSONObject receivedInfo = new JSONObject(data.toString());
  96.                host.setText(receivedInfo.get("host").toString());
  97.                ipAddr.setText(receivedInfo.get("ipaddr").toString());
  98.                light.setText(receivedInfo.get("light").toString());
  99.                temp.setText(receivedInfo.get("temp").toString());
  100.                lcd.setText(receivedInfo.get("title").toString());
  101.                //if(Integer.parseInt(receivedInfo.get("ds2").toString()) == 1)
  102.                    //ds2.setText("关");
  103.                //else
  104.                    //ds2.setText("开");

  105.                ds2.setEnabled(true);

  106.            } catch (JSONException e) {
  107.                e.printStackTrace();
  108.            }
  109.        }
  110.    }


网络访问部分使用了异步任务,在接收到JSON数据之后,刷新APP界面元素。

五、效果及简单总结

本贴实现了一个典型的C/S通信控制。

  • 服务端SERVER使用了大名鼎鼎的NODE.JS,主要提供两方面的内容:基于RESTFULL的服务;结合MRAA及UPM提供硬件访问控制
  • 客户端实现了WEB/APP双访问机制,不过出于安全考虑,WEB访问只提供了只读式的访问方式。要想控制设备,需要通过APP来实现
  • 本项目虽然功能还比较简单,但是通信/控制的基本框架已基本具备,添加新的功能已非常简单
  • 基于C/S通信架构的调试,比单机设备调试需要考虑的因素更多,过程也更复杂

附:

部分运行效果图

2016-08-10_081921.png
LCD显示效果,可以通过APP来实时改变显示内容

2016-08-10_082009.png
舵机调试

2016-08-10_081952.png
外接的WIFI天线,以增强远距离通信效果

本次试用的主题贴






谢谢!



回帖(4)

windworld

2016-9-14 12:50:01
不错 挺有意思的,要是能把相关的智能设备或是家居控制接入而非模拟,就更吸引人了
举报

birdinskydzfsy

2016-11-16 15:23:12
本帖最后由 birdinskyd***sy 于 2016-11-16 17:01 编辑

原来可以用外接天线加强wifi啊  又偷窥了一招  楼主拆了个pad的天线麽
举报

kkx

2016-12-21 13:51:03
楼主大才!!!让我获益良多!!!
举报

吕朝飞

2016-12-27 22:52:06
不错!看来以后得多拆才行!
举报

更多回帖

发帖
×
20
完善资料,
赚取积分