聚豐項目 > 家庭網(wǎng)關(guān)模擬
所謂的網(wǎng)關(guān),其實也可以叫中央控制器(IOT HUB),主要是收集各離散節(jié)點的信息,在終端上顯示;另外就是通過手持終端來發(fā)出各種指令控制,控制各離散節(jié)點設(shè)備的運行。
netlhx
netlhx
團(tuán)隊成員
劉紅新 老師
溫度傳感器連接到擴(kuò)展板的A1
光照傳感器連接到擴(kuò)展板的A2
PWM輸出連接到擴(kuò)展板的D5
舵機(jī)連接到擴(kuò)展板的D3
LCD連接到I2C接口
整體連接效果如圖
在原來的計劃中,舵機(jī)控制是準(zhǔn)備實現(xiàn)的。只是可惜在實驗中,舵機(jī)被燒壞了。
燒壞的舵機(jī),估計是在試驗的時候,正反轉(zhuǎn)設(shè)置的時候參數(shù)有問題,可惜!
實現(xiàn)關(guān)鍵代碼
程序代碼使用NODE.JS來實現(xiàn),調(diào)用底層的MRAA及UPM庫來實現(xiàn)相關(guān)操作。
完整控制代碼如下
var http = require('http');
var query = require('querystring');
var mraa = require('mraa');
var grove = require('jsupm_grove');
var LCD = require('jsupm_i2clcd');
var SERVO = require('jsupm_servo');
var os = require('os');
var lcd = new LCD.Jhd1313m1(6, 0x3E, 0x62);
var hostname = os.hostname().toString();
var ipaddr = os.networkInterfaces()['wlan0'][0]['address'].toString();
var light = new grove.GroveLight(2);
var temp = new grove.GroveTemp(1);
var lightValue = light.value();
var tempValue = temp.value();
//var servo = new SERVO.ES08A(3);
var led_pwm = new mraa.Pwm(6);
led_pwm.enable(true); //must enable
var ds2 = new mraa.Gpio(13);
ds2.dir(mraa.DIR_OUT);
ds2.write(1);
led_pwm.write(0);
//servo.setAngle(90);
lcd.clear();
lcd.setCursor(0, 0);
lcd.write('Intel Edison IoT');
var status = {};
status['host'] = hostname;
status['ipaddr'] = ipaddr;
status['title'] = 'Intel Edison IoT';
setInterval(function() {
status['temp'] = temp.value().toString();
status['light'] = light.value().toString();
}, 2000);
var server = http.createServer(function(req, res) {
switch(req.method) {
case 'GET':
//res.writeHead(200, {'Content-Type': 'application/json'});
//res.end(JSON.stringify(status));
break;
case 'POST':
var content = "";
req.setEncoding('utf8');
req.on('data', function(chunk) {
content += chunk;
});
req.on('end', function() {
console.log(content);
status['title'] = JSON.parse(content)['title'];
status['pwm'] = JSON.parse(content)['pwm'];
status['ds2'] = JSON.parse(content)['ds2'];
console.log(status);
lcd.clear();
lcd.setCursor(0, 0);
lcd.write(status['title'].toString());
led_pwm.write(Number(status['pwm']) / 100);
ds2.write(Number(status['ds2']));
});
break;
default:
break;
}
res.writeHead(200, {'Content-Type': 'application/json'});
res.end(JSON.stringify(status));
});
server.listen(8000);
復(fù)制代碼
目前代碼測試正常,不過不排除潛在的BUG,希望各位有時間的話測試。
客戶端使用ANDROID,編寫一個簡單APP來顯示及控制節(jié)點。部分關(guān)鍵代碼如下
host = (TextView)findViewById(R.id.host);
ipAddr = (TextView)findViewById(R.id.ipAddr);
light = (TextView)findViewById(R.id.light);
temp = (TextView)findViewById(R.id.temp);
pwm = (SeekBar)findViewById(R.id.pwmSeekBar);
lcd = (EditText)findViewById(R.id.lcd);
ds2 = (Button)findViewById(R.id.switchButton);
postButton = (Button)findViewById(R.id.postButton);
info = new JSONObject();
postButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
info.put("pwm", "" + pwm.getProgress());
info.put("title", lcd.getText().toString());
//info.put("ds2", String.valueOf(0));
} catch (JSONException e) {
e.printStackTrace();
}
new SendJsonTask().execute(info);
}
});
ds2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
if(ds2.getText() == "關(guān)") {
info.put("ds2", "0");
ds2.setText("開");
}
else {
info.put("ds2", "1");
ds2.setText("關(guān)");
}
} catch (JSONException e) {
e.printStackTrace();
}
ds2.setEnabled(false);
}
});
}
class SendJsonTask extends AsyncTask<JSONObject, Void, String>
{
@Override
protected String doInBackground(JSONObject... params) {
StringBuilder sb = new StringBuilder();
String http = "http://192.168.99.221:8000/";
HttpURLConnection urlConnection=null;
try {
URL url = new URL(http);
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
urlConnection.setRequestMethod("POST");
urlConnection.setUseCaches(false);
urlConnection.setConnectTimeout(10000);
urlConnection.setReadTimeout(10000);
urlConnection.setRequestProperty("Content-Type","application/json");
urlConnection.connect();
OutputStreamWriter out = new OutputStreamWriter(urlConnection.getOutputStream());
Log.d("JSON", params[0].toString());
out.write(params[0].toString());
out.close();
int HttpResult =urlConnection.getResponseCode();
if(HttpResult == HttpURLConnection.HTTP_OK){
BufferedReader br = new BufferedReader(new InputStreamReader(
urlConnection.getInputStream(),"utf-8"));
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line );
}
br.close();
Log.d("JSON", sb.toString());
return sb.toString();
}else{
System.out.println(urlConnection.getResponseMessage());
}
} catch (MalformedURLException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
finally{
if(urlConnection!=null)
urlConnection.disconnect();
}
return null;
}
@Override
protected void onPostExecute(String data)
{
super.onPostExecute(data);
try {
JSONObject receivedInfo = new JSONObject(data.toString());
host.setText(receivedInfo.get("host").toString());
ipAddr.setText(receivedInfo.get("ipaddr").toString());
light.setText(receivedInfo.get("light").toString());
temp.setText(receivedInfo.get("temp").toString());
lcd.setText(receivedInfo.get("title").toString());
//if(Integer.parseInt(receivedInfo.get("ds2").toString()) == 1)
//ds2.setText("關(guān)");
//else
//ds2.setText("開");
ds2.setEnabled(true);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
復(fù)制代碼
網(wǎng)絡(luò)訪問部分使用了異步任務(wù),在接收到JSON數(shù)據(jù)之后,刷新APP界面元素。
功能概括
INTEL EDISON作為中央控制節(jié)點,收集及接收來自終端節(jié)點的信息,并執(zhí)行相應(yīng)的控制指令
溫度傳感器收集溫度信息
光照傳感器收集光照強(qiáng)度,光照強(qiáng)度值可以用來控制燈光的強(qiáng)弱
無級調(diào)光,通過PWM來控制燈的亮度(通過LED燈來模擬)
舵機(jī)控制,比如調(diào)整自動澆花器的位置
開關(guān)控制,打開或關(guān)閉指定位置的照明燈(通過LED燈來模擬)
LCD顯示,模擬家中的LED顯示屏
設(shè)計思路
程序設(shè)計語言使用NODE.JS做為服務(wù)端控制語言,這也是INTEL主推的一個物聯(lián)網(wǎng)應(yīng)用中的開發(fā)語言。NODE.JS調(diào)用底層的MRAA及UPM庫來控制硬件。硬件控制GROVE的實驗請參考http://bbs.elecfans.com/forum.ph ... d&tid=919288&extra=。
INTEL官方提供的諸多IDE中,XDK實在太臃腫,加上使用NODE.JS只需要一個VIM即可實現(xiàn)編程、調(diào)試。另外C/C++類編程語言在調(diào)試過程中需要反復(fù)修改、編譯、調(diào)試,步驟略顯繁瑣。所以這里使用輕便的NODE.JS來實現(xiàn)服務(wù)端功能。
服務(wù)器端使用比較原生的HTTP模塊搭建了一個簡單的WEB服務(wù)器,客戶端可以使用HTTP請求來獲取或者上傳相應(yīng)控制指令。
數(shù)據(jù)通信格式
服務(wù)器與客戶端之前使用JSON來進(jìn)行通信,一次典型的通信數(shù)據(jù)如下
{"ds2":"1","title":"Hello, world","pwm":"51"}
復(fù)制代碼
上述JSON數(shù)據(jù)中,第一部分是客戶端通過HTTP POST方法上傳的要求服務(wù)器執(zhí)行的信息
"ds2":"1" 請求EDISON打開板載的DS2指示燈,起到模擬開燈/關(guān)燈的效果
"title":"Hello, world" 請求將LCD的顯示內(nèi)容設(shè)置為HELLO, WORLD
"pwm":"51" 請求將連接在D5上的LED燈亮度值設(shè)置為51%
下面一部分JSON數(shù)據(jù)是將EDISON上的一些信息反饋給客戶端,用戶可以使用HTTP來顯示這些內(nèi)容,如下圖
簡易的客戶端APP實現(xiàn)
除了可以使用瀏覽器之外,專門設(shè)計了一個簡單的ANDROID客戶端程序,界面很簡單,如下圖
APP上面是顯示區(qū)域,顯示從服務(wù)器端獲取的數(shù)據(jù)信息;中間為控制區(qū)域,只設(shè)計了控制EDISON的部分接口;最下面是刷新按鈕,用來刷新數(shù)據(jù)。
效果及簡單總結(jié)
本貼實現(xiàn)了一個典型的C/S通信控制。
服務(wù)端SERVER使用了大名鼎鼎的NODE.JS,主要提供兩方面的內(nèi)容:基于RESTFULL的服務(wù);結(jié)合MRAA及UPM提供硬件訪問控制
客戶端實現(xiàn)了WEB/APP雙訪問機(jī)制,不過出于安全考慮,WEB訪問只提供了只讀式的訪問方式。要想控制設(shè)備,需要通過APP來實現(xiàn)
本項目雖然功能還比較簡單,但是通信/控制的基本框架已基本具備,添加新的功能已非常簡單
基于C/S通信架構(gòu)的調(diào)試,比單機(jī)設(shè)備調(diào)試需要考慮的因素更多,過程也更復(fù)雜
附:
部分運行效果圖
LCD顯示效果,可以通過APP來實時改變顯示內(nèi)容
舵機(jī)調(diào)試
外接的WIFI天線,以增強(qiáng)遠(yuǎn)距離通信效果
動心忍性1234: 您好我是無線電雜志的編輯,我們對您的項目十分感興趣,請問您有興趣投稿嗎?成為我們的作者除稿費外還有其他優(yōu)厚條件。敬請參與。投稿請聯(lián)系QQ260534978.
回復(fù)