王風(fēng)雷+秦會斌+崔佳冬
摘 要:為了改善共享單車機(jī)械鎖密碼不安全、電子鎖成本高的不足,設(shè)計(jì)并實(shí)現(xiàn)了基于藍(lán)牙控制的共享單車系統(tǒng)。單車車鎖采用藍(lán)牙與Android客戶端通信,客戶端App請求云服務(wù)器獲得對車鎖的開關(guān)控制,將用戶信息、單車信息上傳至云服務(wù)器,云服務(wù)器將信息持久化到數(shù)據(jù)庫中。針對手機(jī)的高并發(fā)訪問量,云服務(wù)器搭載Nginx,實(shí)現(xiàn)負(fù)載均衡和反向代理。測試結(jié)果表明,該共享單車系統(tǒng)成本低、安全性高,通過該系統(tǒng),用戶可以請求云服務(wù)器實(shí)現(xiàn)對單車車鎖的控制。
關(guān)鍵詞:共享單車;云服務(wù)器;Android;藍(lán)牙
中圖分類號:TP311 文獻(xiàn)標(biāo)識碼:A 文章編號:2095-1302(2018)02-00-04
0 引 言
共享單車是中國互聯(lián)網(wǎng)創(chuàng)新的應(yīng)用實(shí)踐,解決了“最后一公里”的問題,緩解了交通擁堵,真正實(shí)現(xiàn)了綠色出行,利國利民[1]。目前,共享單車機(jī)械車鎖的密碼由用戶通過App獲取,密碼不可改變,安全性低;電子車鎖需要連接云服務(wù)器,安全性高,但是硬件設(shè)計(jì)復(fù)雜、成本較高、耗電量高。針對以上問題,本文提出了基于藍(lán)牙控制的共享單車系統(tǒng)設(shè)計(jì)方案。通過Android手機(jī)匹配單車藍(lán)牙車鎖,請求云服務(wù)器獲取“鑰匙”,實(shí)現(xiàn)對車鎖的開關(guān)控制。同時(shí),云服務(wù)器將用戶和單車的信息持久化到數(shù)據(jù)庫中。
1 系統(tǒng)總體設(shè)計(jì)
系統(tǒng)由Android客戶端、網(wǎng)頁后臺管理中心、云服務(wù)器和藍(lán)牙單車車鎖組成。系統(tǒng)框架如圖1所示。
云服務(wù)器是整個(gè)系統(tǒng)的調(diào)控計(jì)算平臺[2],為管理人員與手機(jī)App提供服務(wù),響應(yīng)用戶與管理人員的操作。手機(jī)App發(fā)送HTTP請求到云服務(wù)器,解析云服務(wù)器返回的JSON數(shù)據(jù),下發(fā)藍(lán)牙控制信息,經(jīng)車鎖藍(lán)牙MCU處理后,最終達(dá)到控制車鎖開閉的功能。藍(lán)牙車鎖也可通過串口向藍(lán)牙模塊輸出藍(lán)牙信息,手機(jī)App響應(yīng)藍(lán)牙信息,最終實(shí)現(xiàn)手機(jī)App與硬件控制部分的雙向通信。
用戶在注冊登錄成功后,進(jìn)入用車界面;打開手機(jī)藍(lán)牙,匹配車鎖藍(lán)牙,App后臺將用戶信息和車鎖信息上傳到云端服務(wù)器;用戶點(diǎn)擊開始用車,云服務(wù)器接收到請求后,記錄用戶信息和車鎖信息,并返回“鑰匙”給App,通過藍(lán)牙與車鎖通信打開車鎖。當(dāng)車鎖關(guān)閉后,藍(lán)牙將已鎖狀態(tài)發(fā)送給App,App界面結(jié)束用車,若中途斷開藍(lán)牙,則結(jié)束用車后用車界面無法進(jìn)行操作。手機(jī)端用車的業(yè)務(wù)流程如圖2所示。
2 云服務(wù)器的設(shè)計(jì)與實(shí)現(xiàn)
2.1 云服務(wù)器架構(gòu)
云服務(wù)器架構(gòu)圖如圖3所示。
本文采用阿里云作為云計(jì)算中心,提供簡單高效、處理能力可彈性伸縮的計(jì)算服務(wù)。阿里云上搭載Nginx、Tomcat、Redis和MySQL,Nginx 作為反向代理,將 App 端或者瀏覽器端的請求根據(jù)權(quán)重分配給兩臺Tomcat,Redis作為兩臺Tomcat的共享session數(shù)據(jù)服務(wù)器,緩存已驗(yàn)證的用戶信息。
Tomcat1的IP地址為106.15.90.190,Tomcat2的IP地址為106.14.9.111,在106.15.90.190的云服務(wù)器上搭載Nginx,配置Nginx,具體的配置如下[3]:
worker_processes 2;
events {
worker_connections 1024;}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
//配置被代理的服務(wù)器
upstream live_node {
server 106.15.90.190:8080;
server 106.14.9.111:8080;}
server {
//配置訪問域名及監(jiān)聽80端口
listen 80;
server_name 106.15.90.190;
//指定被代理目標(biāo)
location / {
proxy_pass http://live_node;}
//配置錯(cuò)誤頁面
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;}
}
}
當(dāng)有請求時(shí),通過Nginx將請求進(jìn)行轉(zhuǎn)發(fā)[4],保證一個(gè)入口將所有請求轉(zhuǎn)發(fā)到Tomcat1或Tomcat2,同時(shí)減輕這兩臺Tomcat的負(fù)載壓力。將Tomcat1和Tomcat2的session緩存到Redis中[5],確保訪問的是同一個(gè)session,配置Tomcat conf目錄下的context.xml。
redissessins.RedisSessionHandlerValve” /> host=“106.15.90.190” port=“6379” database=“0” maxInactiveInterval=“1800”/> <!--redis過期時(shí)間默認(rèn)是60 s,設(shè)置session過期時(shí)間為1 800 s-->
Redis是鍵值對類型的內(nèi)存數(shù)據(jù)庫。同時(shí),用Redis作為MySQL的緩存數(shù)據(jù)庫,能夠減小MySQL的壓力。服務(wù)器先查找Redis服務(wù)器中是否有登錄用戶的信息,有則取出使用,無則查詢數(shù)據(jù)庫,查看是否可以驗(yàn)證,將驗(yàn)證后的用戶緩存到Redis服務(wù)器中,從而減少對數(shù)據(jù)庫的訪問。實(shí)現(xiàn)的部分代碼如下:
//先查詢緩存
try {
String json = jedisClient.hget(INDEX_USER, uid + “”);
//查詢到結(jié)果,把json轉(zhuǎn)換成對象返回
if (StringUtils.isNotBlank(json)) {
User findUser = JsonUtils.
jsonToPojo(json, User.class);
return findUser;}
} catch (Exception e) {
e.printStackTrace();}
//緩存中沒有,需要查詢數(shù)據(jù)庫
User findUser = userService.login(telphone,password);
//把結(jié)果添加到緩存
try {
jedisClient.hset(INDEX_“USER”, uid + “”,JsonUtils.objectToJson(findUser));}
catch (Exception e) {
e.printStackTrace();}
return findUser;
2.2 云服務(wù)器框架
云服務(wù)器系統(tǒng)開發(fā)框架采用Struts+Spring+Hibernate,該框架從職責(zé)上分為Web層、業(yè)務(wù)層、DAO層和持久層。其中,使用Struts作為系統(tǒng)的整體基礎(chǔ)架構(gòu),負(fù)責(zé)MVC的分離,在Struts框架的模型部分控制業(yè)務(wù)跳轉(zhuǎn)。利用Hibernate框架對持久層提供支持。Spring做管理,管理Struts和Hibernate。
系統(tǒng)的基本業(yè)務(wù)流程為:在Web層中,通過JSP頁面實(shí)現(xiàn)交互界面,負(fù)責(zé)接收請求和傳送響應(yīng),然后Struts根據(jù)配置文件(struts-config.xml)將ActionServlet接收到的Request委派給相應(yīng)的Action處理;在業(yè)務(wù)層中,管理服務(wù)組件的Spring IoC容器負(fù)責(zé)向Action提供業(yè)務(wù)模型(Model)組件和該組件的協(xié)作對象數(shù)據(jù)處理(DAO)組件完成業(yè)務(wù)邏輯,并提供事務(wù)處理、緩沖池等容器組件以提升系統(tǒng)性能和保證數(shù)據(jù)的完整性;而在持久層中則依賴于Hibernate的對象化映射和數(shù)據(jù)庫交互,處理DAO組件請求的數(shù)據(jù),并返回處理結(jié)果[6]。
該開發(fā)模型不僅實(shí)現(xiàn)了視圖、控制器與模型的徹底分離,而且可以實(shí)現(xiàn)業(yè)務(wù)邏輯層與持久層的分離。不同層之間耦合度小,大大提高了開發(fā)效率。
2.3 云服務(wù)器功能的實(shí)現(xiàn)
云服務(wù)器系統(tǒng)主要分為網(wǎng)頁后臺服務(wù)和用戶App服務(wù),管理人員通過瀏覽器訪問,查看用戶及藍(lán)牙車鎖的信息。App服務(wù)為Android客戶端提供接口,根據(jù)App提供的信息對用戶和藍(lán)牙車鎖信息進(jìn)行記錄,并持久化到MySQL中。系統(tǒng)服務(wù)圖如圖4所示。
App與云服務(wù)器的通信主要通過發(fā)送HTTP請求,使用輕量級的JSON數(shù)據(jù)交換格式實(shí)現(xiàn)。云服務(wù)器為App提供5個(gè)接口:用戶注冊、用戶登錄、打開車鎖、獲取用戶當(dāng)前是否打開車鎖、關(guān)閉車鎖。
網(wǎng)頁的后臺服務(wù)中,為防止非登錄認(rèn)證的管理員直接訪問某些頁面、功能菜單項(xiàng)或action名,使用Struts自定義攔截器,繼承Method Filter Interceptor類,并在Struts的配置文件中放行登錄方法,登錄后將所驗(yàn)證的登錄名和密碼放到Redis服務(wù)器中。若攔截器查詢到Redis服務(wù)器中有驗(yàn)證過的登錄名,則放行;否則,跳轉(zhuǎn)到登錄頁面。根據(jù)Ajax的請求查詢數(shù)據(jù)庫,將前臺頁面不需要的數(shù)據(jù)排除在外,再將數(shù)據(jù)以JSON格式返回,前臺Ajax的回調(diào)函數(shù)解析數(shù)據(jù)并進(jìn)行地圖上的顯示。
3 客戶端的設(shè)計(jì)與實(shí)現(xiàn)
3.1 客戶端功能說明
客戶端各功能模塊如圖5所示。
(1) 登錄模塊:注冊時(shí),本地校驗(yàn)是否為正確的手機(jī)號,并向云服務(wù)器驗(yàn)證是否已經(jīng)注冊過,經(jīng)過驗(yàn)證后,向手機(jī)號發(fā)送驗(yàn)證碼,填寫驗(yàn)證碼進(jìn)行注冊。一經(jīng)登錄,下次使用時(shí)App會自動登錄。
(2) 用戶使用模塊:在車輛使用方面,采用手機(jī)應(yīng)用和藍(lán)牙模塊建立雙向通信達(dá)到控制車鎖的目的。需要用車時(shí),使用手機(jī)藍(lán)牙適配器[7]連接藍(lán)牙模塊建立Socket通信通道。只要藍(lán)牙不關(guān)閉或者不超過最大通信距離,該通道將會保持,直到手動關(guān)閉。通信建立后,手機(jī)端通過Socket攜帶控制命令到藍(lán)牙模塊,也可以控制單片機(jī)通過串口發(fā)送數(shù)據(jù)到藍(lán)牙模塊與手機(jī)通信。對于車輛行程監(jiān)控,需要用戶開啟后才能進(jìn)入工作,該功能集成的是百度地圖API,調(diào)用百度地圖的定位功能,通過實(shí)時(shí)監(jiān)聽手機(jī)位置定位車輛。在用戶結(jié)束用車后會將車輛最后的坐標(biāo)位置通過手機(jī)App上傳到云服務(wù)器。在車輛使用過程中,若用戶開啟了路徑監(jiān)控模式,則可以描繪出運(yùn)行軌跡,同時(shí)計(jì)算車輛的行駛速度、路程和騎行時(shí)間;若用戶未開啟該模式,則不會進(jìn)入路徑監(jiān)聽模式,百度地圖只進(jìn)行定位。
(3)藍(lán)牙車鎖控制模塊:手機(jī)藍(lán)牙與車鎖藍(lán)牙通信后,向云服務(wù)器發(fā)送HTTP請求,通過解析返回的JSON數(shù)據(jù),拿到“鑰匙”,從而對車鎖進(jìn)行開關(guān)控制。同時(shí),藍(lán)牙車鎖端監(jiān)測到車鎖關(guān)閉后,向手機(jī)發(fā)送當(dāng)前狀態(tài),App監(jiān)聽到狀態(tài)改變,向云服務(wù)器請求結(jié)束計(jì)費(fèi),App可以結(jié)束用車。
3.2 客戶端框架endprint
在Android Studio開發(fā)環(huán)境下,采用MVC開發(fā)架構(gòu)。視圖層接收輸入和顯示結(jié)果,生成App界面;控制層用來處理用戶交互的部分,接收到用戶的輸入后向模型發(fā)送數(shù)據(jù);模型層調(diào)用程序的數(shù)據(jù)邏輯部分,定義了HTTP通信模塊、藍(lán)牙通信模塊、數(shù)據(jù)解析模塊等[8,9]。
手機(jī)App與車鎖藍(lán)牙建立Socket通信,開啟一個(gè)子線程不斷輪詢,通過套接字Socket獲取字節(jié)輸入流,解析并獲取數(shù)據(jù)流,將數(shù)據(jù)使用廣播發(fā)送給主線程處理。接收藍(lán)牙信息的代碼如下:
class ServiceReceiveThread extends Thread{
@Override
public void run(){
byte[] buf=new byte[10];
while (btSocket != null){
BufferedInputStream bis=new BufferedInputStream( btSocket.getInputStream());
int read = bis.read(buf);//接收藍(lán)牙發(fā)送的數(shù)據(jù)
int r=(int)buf[0];
if(r==21){
//發(fā)送數(shù)據(jù)到主線程
handler.sendEmptyMessage(1);
sendBroadcast(newIntent
(“SERVICE_DISCONNECT”));}
sleep(2000);}}
客戶端與云服務(wù)器通信采用http連接,使用Apache異步網(wǎng)絡(luò)請求框架AsyncHttpClient,首先在父類Activity中新建該類的實(shí)例,子類Activity使用該類向云服務(wù)器發(fā)送post請求,云服務(wù)器返回JSON數(shù)據(jù)至App[10]。
protected void SendMsgToServer(){
RequestParams params=new RequestParams();
params.put(“telephone”, MyApplication.tel);
params.put(“bluetoothId”,MyUtils.getStrValue(getContext(), “device_addr”));
client.post(GloubleConst.MAIN+GloubleConst.START_CHARGE, params,new AsyncHttpResponseHandler(){
@Override
public void onSuccess(final String content){
if(content.equals(“1”)){
//車輛可以使用
handler.sendEmptyMessage(CAN_USE_BIKE);}
else if(content.equals(“0”)){
//已經(jīng)在使用
handler.sendEmptyMessage(CANNOT_USE_BIKE)} });}
@Override
public void onFailure(Throwable error, String content){...}//網(wǎng)絡(luò)連接失敗處理
});}
onSuccess()和onFailure()方法接收請求成功或失敗的消息,onSuccess()方法的參數(shù)content為云服務(wù)器返回的JSON數(shù)據(jù)。
4 藍(lán)牙車鎖
藍(lán)牙車鎖控制器使用MSP430單片機(jī),內(nèi)置2.4 G無線發(fā)射天線的HC-06藍(lán)牙模塊。該藍(lán)牙模塊支持兩種模式:一種是上電后只能接受命令的從機(jī)模式;另一種是主從機(jī)一體模式。該系統(tǒng)在主從機(jī)一體模式下,通過串口調(diào)試工具,利用AT指令修改默認(rèn)屬性。當(dāng)手機(jī)端應(yīng)用成功連接藍(lán)牙后,即可建立通信。同時(shí),手機(jī)端通過套接字向模塊寫入數(shù)據(jù)。另外,控制單元也可通過串口發(fā)送數(shù)據(jù)到手機(jī)應(yīng)用端,實(shí)現(xiàn)雙向通信。
5 客戶端和后臺中心界面展示
Android客戶端以精簡、靈活為前提,主要為用戶注冊登錄、匹配車鎖、開始/結(jié)束用車、行程記錄和個(gè)人信息界面,Android客戶端部分界面如圖6所示。
后臺管理中心主要包括登錄界面、用戶信息、車鎖信息和車鎖地圖顯示界面。其中,用戶信息界面和車鎖信息界面可以進(jìn)行搜索。車鎖地圖顯示界面如圖7所示。
6 結(jié) 語
本文介紹了基于藍(lán)牙控制的共享單車系統(tǒng)設(shè)計(jì)和技術(shù),該系統(tǒng)結(jié)合云平臺、Android平臺和藍(lán)牙技術(shù),基于Android手機(jī)獲取經(jīng)緯度,并持久化到云服務(wù)器中,便于對單車進(jìn)行維護(hù),為共享單車市場提供一種安全、易實(shí)施的設(shè)計(jì)參考。
參考文獻(xiàn)
[1]徐鑫垚.共享單車App后臺管理系統(tǒng)的優(yōu)化[J]. 電子技術(shù)與軟件工程,2017(4):80-81.
[2]王偉,章民融.基于云架構(gòu)的智能警務(wù)協(xié)同指揮系統(tǒng)研究與應(yīng)用[J].計(jì)算機(jī)應(yīng)用與軟件,2014, 31(8):67-70.
[3]徐鸝,王耀,王偉聰,等.Moodle系統(tǒng)的集群方案與案例分析[J].計(jì)算機(jī)應(yīng)用與軟件,2012,29(1):224-229.
[4]杜星.輕量級Web服務(wù)器Nginx的理論與技術(shù)研究[D]. 南京:南京郵電大學(xué),2016.
[5]曾泉勻.基于Redis的分布式消息服務(wù)的設(shè)計(jì)與實(shí)現(xiàn)[D]. 北京:北京郵電大學(xué), 2014.
[6]高蓓蕾.基于ISO管理體系的設(shè)備管理系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn)[D]. 南京:南京郵電大學(xué), 2014.
[7]葛會會.基于Android 藍(lán)牙考勤系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)[D].撫州:東華理工大學(xué),2016.
[8]陳鈺琨,馬忠梅,曾禮.Android系統(tǒng)的藍(lán)牙遠(yuǎn)程控制研究[J].單片機(jī)與嵌入式系統(tǒng)應(yīng)用,2015, 15(1):16-19.
[9]郭健儐,蔡雪松.基于Android平臺的公交信息發(fā)布終端軟件的設(shè)計(jì)與實(shí)現(xiàn)[J].計(jì)算機(jī)應(yīng)用與軟件,2014,31(9):322-324.
[10]陳瑋,秦會斌,曹曙光,等.基于Android平臺的智能家居系統(tǒng)設(shè)計(jì)[J].電子技術(shù)應(yīng)用,2014, 41(10):158-160.endprint