楊東軒 劉 碩 王 嵩
(北京工商大學(xué)網(wǎng)絡(luò)中心 北京 100048)
目前在一些辦事大廳等場(chǎng)景廣泛使用排隊(duì)叫號(hào)系統(tǒng),不少系統(tǒng)仍采用紙質(zhì)的叫號(hào)方式。這種紙質(zhì)方式既不利于環(huán)境保護(hù)又在內(nèi)容顯示上無(wú)法實(shí)時(shí)更新。有些手機(jī)APP的叫號(hào)方式又有許多使用的局限性,包括可能暴露客戶(hù)信息等情況[1,2]。本文結(jié)合物聯(lián)網(wǎng)技術(shù)和基于低功耗Wi-Fi的電子手持號(hào)牌設(shè)計(jì),給出使用該電子手持號(hào)牌較為完整的叫號(hào)系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn)方法。
系統(tǒng)主要由電子號(hào)牌和服務(wù)器兩部分組成,它們同處于一個(gè)無(wú)線局域網(wǎng)之中。電子號(hào)牌以低功耗Wi-Fi芯片CC3200為核心,接收來(lái)自服務(wù)器端的無(wú)線數(shù)據(jù),提醒用戶(hù)當(dāng)前的業(yè)務(wù)信息。服務(wù)器端由Linux系統(tǒng)及相關(guān)軟件構(gòu)成,負(fù)責(zé)控制電子號(hào)牌的發(fā)放、叫號(hào)信息的數(shù)據(jù)廣播以及與對(duì)外提供系統(tǒng)交互接口。系統(tǒng)架構(gòu)如圖1所示。
圖1 系統(tǒng)架構(gòu)圖
目前市場(chǎng)較為常見(jiàn)的電子號(hào)牌一般都采用315 MHz左右的較低頻率無(wú)線調(diào)頻技術(shù),使用數(shù)碼管顯示號(hào)碼,一般只有一個(gè)信號(hào)發(fā)射端用來(lái)手工發(fā)號(hào)和叫號(hào),不能更改號(hào)牌的號(hào)碼,也不提供二次開(kāi)發(fā)的接口。它們的無(wú)線發(fā)射端和接收端不具備組網(wǎng)功能,且信號(hào)覆蓋范圍固定,僅適用于快餐業(yè)務(wù)領(lǐng)域的叫號(hào)使用。
本文實(shí)現(xiàn)的電子號(hào)牌在系統(tǒng)構(gòu)成方面更加復(fù)雜、應(yīng)用范圍也更為廣泛。號(hào)牌具有文本顯示能力,包括顯示業(yè)務(wù)類(lèi)型、辦理進(jìn)度、時(shí)間和電量等信息。而且還有震動(dòng)功能提醒客戶(hù)。由于服務(wù)器端和客戶(hù)端是使用Wi-Fi進(jìn)行通信的,因此系統(tǒng)的覆蓋范圍可以根據(jù)AP的安裝位置進(jìn)行靈活擴(kuò)展。
系統(tǒng)設(shè)計(jì)初期,將電子號(hào)牌的外觀尺寸限定在普通的銀行卡尺寸大小,這就對(duì)其內(nèi)部的電路設(shè)計(jì)提出了很高的要求。在核心器件低功耗Wi-Fi芯片的選型上,選擇了德州儀器的CC3200芯片,與同一應(yīng)用領(lǐng)域的其他廠家的芯片相比[3-4],它具有外設(shè)接口豐富、工作電壓范圍更寬、開(kāi)發(fā)周期較短等優(yōu)點(diǎn),如表1所示。
表1 同類(lèi)低功耗Wi-Fi芯片對(duì)比
硬件電路包含CC3200最小運(yùn)行系統(tǒng)、OLED點(diǎn)陣顯示屏、振子電機(jī)驅(qū)動(dòng)、霍爾效應(yīng)開(kāi)關(guān)傳感器及充電管理模塊。CC3200最小系統(tǒng)包含了能使該芯片正常運(yùn)行的最少電路設(shè)計(jì)以及能支持其無(wú)線通信的天線電路設(shè)計(jì)。由于該主控芯片集成了一個(gè)ARM-Cortex M4內(nèi)核的處理器和一個(gè)Wi-Fi網(wǎng)絡(luò)處理器[5],因此在電路板的布局和走線方面要嚴(yán)格按照TI公司給出的設(shè)計(jì)手冊(cè)進(jìn)行,其中電源部分和射頻鏈路部分的設(shè)計(jì)尤為重要。為了滿(mǎn)足芯片啟動(dòng)、發(fā)射和接收數(shù)據(jù)時(shí)的電流需求,電源相關(guān)引腳的走線必須滿(mǎn)足表2中的條件。
表2 CC3200引腳通過(guò)電流
射頻部分的布局則會(huì)影響信號(hào)的輸出功率、誤差向量幅度以及頻譜掩模。在射頻電路中,天線起到了將PCB引線中的導(dǎo)波轉(zhuǎn)換為自由空間中電磁輻射的作用,因此在布局中要盡量把陶瓷天線器件放到PCB板的邊緣,確保沒(méi)有其他信號(hào)線穿過(guò)天線底部。由于射頻部分走線要滿(mǎn)足其在2.4 GHz頻段工作時(shí)的阻抗為50 Ω,因此需要選擇適合的傳輸模型。本文選用具有地面結(jié)構(gòu)的共面波導(dǎo)CPW-G(Coplanar Waveguide With GND)模型,該模型結(jié)構(gòu)如圖2所示,其中εr為相對(duì)介電常數(shù),W為間隙寬度,S為走線寬度,h為電解質(zhì)厚度[6]。
圖2 CPW-G模型結(jié)構(gòu)
在顯示功能方面,選用像素尺寸為128×64的OLED點(diǎn)陣顯示屏,該屏幕可以同時(shí)顯示32個(gè)漢字或者64個(gè)半角字符,足以容納叫號(hào)業(yè)務(wù)所需顯示的內(nèi)容。相比目前流行的LCD、QLED和LPD顯示技術(shù),OLED具有自發(fā)光、厚度極薄、響應(yīng)時(shí)間快、低功耗等優(yōu)點(diǎn)[7]。該款屏幕在2.8 V供電情況下,全像素點(diǎn)亮?xí)r的電流為28 mA,休眠狀態(tài)時(shí)則為1 μA。屏幕與主控芯片之間采用SPI串行總線連接,電路原理如圖3所示。
圖3 OLED屏幕電路
振子即微型的震動(dòng)電機(jī),通過(guò)將電能轉(zhuǎn)換為機(jī)械能起到震動(dòng)提醒作用,是整個(gè)電路系統(tǒng)中最為耗電的部分。號(hào)牌采用的振子最大電流為120 mA,為了讓CC3200的GPIO口足以驅(qū)動(dòng)該電機(jī),采用NPN型的三極管作為驅(qū)動(dòng)開(kāi)關(guān)。如圖4所示,將電機(jī)的正負(fù)輸入端分別接到系統(tǒng)電源與三極管的集電極之間,為了防止電機(jī)停止時(shí)產(chǎn)生的反電動(dòng)勢(shì)對(duì)其他電子器件造成損壞,還需要在電機(jī)的兩端并入一個(gè)二極管以作保護(hù)。
圖4 振動(dòng)電機(jī)驅(qū)動(dòng)電路
電子號(hào)牌沒(méi)有任何可供用戶(hù)操作的輸入設(shè)備,因此需要設(shè)計(jì)一個(gè)激活裝置來(lái)將整個(gè)電路系統(tǒng)從關(guān)閉狀態(tài)激活為開(kāi)啟狀態(tài)。采用A3212型的超靈敏霍爾效應(yīng)開(kāi)關(guān)傳感器,可以在不使用物理觸控的條件下,通過(guò)磁場(chǎng)變化就可以改變?cè)搨鞲衅鞯妮敵鲭妷?。將該傳感器布局在PCB的邊緣,有助于更加靈敏地受到磁鐵的感應(yīng)。如圖5所示,OUTPUT輸出引腳通過(guò)上拉電阻連接到主控芯片的GPIO口,該IO口用于將冬眠狀態(tài)的處理器喚醒為運(yùn)行狀態(tài)。當(dāng)垂直通過(guò)該傳感器的磁感應(yīng)強(qiáng)度大于37 T的時(shí)候,輸出為低電平。
圖5 霍爾開(kāi)關(guān)傳感器電路
使用一塊容量為700 mAH的鋰離子電池作為整個(gè)電路的供電來(lái)源,采用USB Micro接口作為號(hào)牌的充電接口,充電管理芯片的型號(hào)為T(mén)P4056。如圖6所示,當(dāng)電路系統(tǒng)接入5 V的USB充電線后,USB接口的VBUS電源引腳通過(guò)限流電阻使NPN三極管CE兩端導(dǎo)通,發(fā)射極觸發(fā)主控芯片的GPIO口從而通知系統(tǒng)已經(jīng)接入充電線。充電管理芯片的STDBY引腳為電池充電狀態(tài),當(dāng)電池充滿(mǎn)電后會(huì)內(nèi)部下拉到低電平。
圖6 充電管理電路
設(shè)備的主要耗電器件是屏幕、震動(dòng)電機(jī)以及主控芯片,由于前兩者在運(yùn)行期間的功耗基本是恒定不變的,因此為主控芯片制定合適的低功耗策略是關(guān)鍵所在。對(duì)于理想化的計(jì)算機(jī)系統(tǒng)而言降低核心處理器CPU的電壓和頻率均可以起到降低功耗的作用[8],如果把CPU看作是一個(gè)基于電容器的系統(tǒng),那么它的功耗滿(mǎn)足如下物理關(guān)系式:
(1)
式中:E為芯片消耗的能量,T為消耗能量所需的時(shí)間,U為運(yùn)行電壓,f為芯片的工作頻率。
對(duì)于CC3200而言,雖然它的工作電壓范圍在1.76 V至3.6 V之間,但是為了簡(jiǎn)化硬件設(shè)計(jì),通常采用恒定的穩(wěn)壓電源,因此只需要通過(guò)改變芯片的運(yùn)行頻率就可以滿(mǎn)足功耗的調(diào)整了,其物理關(guān)系滿(mǎn)足下式:
(2)
式中:Ttask為單個(gè)任務(wù)運(yùn)行的時(shí)間。
而芯片在不同的運(yùn)行頻率下,所處的工作模式也不同。CC3200內(nèi)部包含兩個(gè)獨(dú)立的系統(tǒng),分別是Cortex-M4應(yīng)用處理器(MCU)子系統(tǒng)和網(wǎng)絡(luò)處理器(NWP)子系統(tǒng),每個(gè)子系統(tǒng)都有若干種工作模式。在號(hào)牌的軟件實(shí)現(xiàn)中,分別用到了MCU的激活模式、低功耗深度睡眠模式(LPDS)以及冬眠模式。在激活模式時(shí),它將以80 MHz的頻率運(yùn)行應(yīng)用代碼,此時(shí)MCU的功耗最高;在LPDS模式時(shí),只保留特定寄存器的配置,但可以從網(wǎng)絡(luò)事件中喚醒;在冬眠模式時(shí),功耗最低且僅由頻率最低的實(shí)時(shí)時(shí)鐘驅(qū)動(dòng),僅能由時(shí)鐘定時(shí)器或外部事件觸發(fā)喚醒,喚醒后重新加載串行Flash中的應(yīng)用代碼運(yùn)行。NWP的工作模式由其自身根據(jù)當(dāng)前的網(wǎng)絡(luò)狀態(tài)和MCU的電源策略自動(dòng)控制,分別在激活模式、LPDS模式和冬眠模式中自主切換[9]。
在號(hào)牌的實(shí)際使用過(guò)程中,針對(duì)不同的工作場(chǎng)景切換不同的工作模式,在保障運(yùn)行效率的情況下使芯片功耗降到最低。表3給出了所有工作場(chǎng)景下芯片對(duì)應(yīng)的電源模式以及電路各主要部分的電流使用情況。在號(hào)牌未被發(fā)出時(shí),處于冬眠狀態(tài),此時(shí)功耗最低;當(dāng)號(hào)牌被發(fā)出時(shí),需要從冬眠狀態(tài)被喚醒,由于喚醒時(shí)機(jī)不確定,因此只能使用外部IO作為喚醒源;號(hào)牌在用戶(hù)手中的大部分時(shí)間是保持屏幕畫(huà)面不變的狀態(tài),處于LPDS模式,但是當(dāng)處于接收廣播消息、屏幕時(shí)間定時(shí)刷新等事件時(shí),便會(huì)被喚醒;喚醒狀態(tài)的號(hào)牌處于激活模式,此時(shí)進(jìn)行屏幕刷新、網(wǎng)絡(luò)數(shù)據(jù)處理等業(yè)務(wù)。
表3 電子號(hào)牌電源工作模式
電子號(hào)牌與服務(wù)器之間的通信方案采用無(wú)握手機(jī)制的UDP協(xié)議報(bào)文。軟件整體結(jié)構(gòu)基于FreeRTOS嵌入式實(shí)時(shí)操作系統(tǒng),采用TI官方提供的SimpleLink組件庫(kù)來(lái)實(shí)現(xiàn)網(wǎng)絡(luò)方面的編程,調(diào)用內(nèi)置于芯片ROM的外設(shè)驅(qū)動(dòng)庫(kù)(DriverLib)來(lái)對(duì)SPI、GPIO、ADC和定時(shí)器等外設(shè)進(jìn)行編程。軟件的主函數(shù)運(yùn)行流程如圖7所示。首先對(duì)CC3200的外設(shè)及硬件資源進(jìn)行初始化,如OLED屏幕、外部輸入IO等;然后開(kāi)始SimpleLink的任務(wù)調(diào)度器,該任務(wù)管理主處理器和NWP之間的消息通信;最后創(chuàng)建并執(zhí)行分別用于事件處理、UDP服務(wù)器和UDP客戶(hù)端的子任務(wù)。
圖7 號(hào)牌軟件運(yùn)行流程
大部分工作時(shí)間里號(hào)牌處于接收服務(wù)器發(fā)送UDP廣播數(shù)據(jù)的狀態(tài),因此它將主要扮演UDP 服務(wù)器的角色,僅在第一次連接到服務(wù)器的時(shí)候才需要作為UDP 客戶(hù)端來(lái)向服務(wù)器發(fā)送激活消息。根據(jù)發(fā)送和接收不同的UDP報(bào)文,來(lái)驅(qū)動(dòng)號(hào)牌在不同狀態(tài)之間切換。這些狀態(tài)包括:設(shè)備復(fù)位狀態(tài)、等待業(yè)務(wù)編號(hào)狀態(tài)、等待叫號(hào)狀態(tài)、被叫號(hào)狀態(tài)、過(guò)號(hào)狀態(tài)以及充電狀態(tài)。在大部分狀態(tài)改變的同時(shí),號(hào)牌接收UDP報(bào)文的端口號(hào)也會(huì)隨之改變,在等待叫號(hào)狀態(tài)中,不同業(yè)務(wù)類(lèi)型的號(hào)牌所監(jiān)聽(tīng)的UDP端口也不同。這樣就實(shí)現(xiàn)了以端口號(hào)劃分業(yè)務(wù)類(lèi)型的目的,在服務(wù)器廣播指定端口的UDP報(bào)文的同時(shí),其他業(yè)務(wù)類(lèi)型的號(hào)牌則不會(huì)收到該端口的報(bào)文。不接收?qǐng)?bào)文意味著硬件不會(huì)從LDPS模式中被喚醒,從而節(jié)約了不必要的功耗開(kāi)支。UDP報(bào)文與號(hào)牌狀態(tài)之間切換的流程如圖8所示。
圖8 號(hào)牌狀態(tài)切換流程
號(hào)牌軟件系統(tǒng)中有三個(gè)主要的任務(wù),分別是:Task_MainProcess()(主處理任務(wù)),負(fù)責(zé)系統(tǒng)初始化、外設(shè)控制以及網(wǎng)絡(luò)報(bào)文數(shù)據(jù)處理;Task_UDPServer()(UDP服務(wù)器任務(wù)),負(fù)責(zé)接收來(lái)自服務(wù)器發(fā)送的UDP報(bào)文;Task_UDPClient()(UDP客戶(hù)端任務(wù)),負(fù)責(zé)向服務(wù)器發(fā)送UDP報(bào)文。當(dāng)系統(tǒng)成功連接到指定SSID的AP后,首先會(huì)向服務(wù)器發(fā)送激活消息的數(shù)據(jù)包。在本次發(fā)送的數(shù)據(jù)中,加入該號(hào)牌的MAC地址作為唯一身份識(shí)別,用sl_NetCfgGet()獲取設(shè)備自身的MAC地址。無(wú)論是發(fā)送還是接收UDP數(shù)據(jù)包,都需要首先調(diào)用sl_Socket()創(chuàng)建UDP套接字,之后通過(guò)sl_SendTo()將封裝好的數(shù)據(jù)包發(fā)送出去。為了防止網(wǎng)絡(luò)阻塞、信號(hào)不好等意外情況導(dǎo)致目標(biāo)地址無(wú)法正常收到數(shù)據(jù),在發(fā)送每個(gè)UDP報(bào)文的時(shí)候都連續(xù)發(fā)送N次同樣的數(shù)據(jù),一旦接收到服務(wù)器返回的數(shù)據(jù),則停止發(fā)送并執(zhí)行下一步操作,當(dāng)?shù)贜次還沒(méi)有收到應(yīng)答數(shù)據(jù),則判斷其運(yùn)行狀態(tài)異常,系統(tǒng)調(diào)用rn_setup_power_policy()進(jìn)入冬眠模式以備回收處理。當(dāng)服務(wù)器成功接收到號(hào)牌發(fā)送的激活消息后,會(huì)做出相應(yīng)的回答。號(hào)牌系統(tǒng)通過(guò)sl_RecvFrom()接收UDP報(bào)文,并使用sl_Bind()綁定接收數(shù)據(jù)的端口。如前文所述,UDP客戶(hù)端任務(wù)根據(jù)接收到的報(bào)文類(lèi)型來(lái)使號(hào)牌切換狀態(tài)同時(shí)改變接收?qǐng)?bào)文的端口號(hào),該任務(wù)的運(yùn)行流程如圖9所示。
圖9 UDP客戶(hù)端任務(wù)流程
服務(wù)器端的軟件采用GO語(yǔ)言編寫(xiě)并運(yùn)行于Linux系統(tǒng)之上。該語(yǔ)言編寫(xiě)的代碼在編譯后生成一個(gè)靜態(tài)可執(zhí)行文件,在服務(wù)器上部署時(shí)完全不需要關(guān)心應(yīng)用所需的各種包和庫(kù)的依賴(lài)關(guān)系,大大減輕了維護(hù)的負(fù)擔(dān)。
系統(tǒng)中主要用到了XML數(shù)據(jù)模型和關(guān)系型數(shù)據(jù)模型,前者用來(lái)存儲(chǔ)電子號(hào)牌硬件相關(guān)的數(shù)據(jù),后者用來(lái)存儲(chǔ)業(yè)務(wù)相關(guān)的運(yùn)行數(shù)據(jù)。將每個(gè)電子號(hào)牌的射頻標(biāo)簽EPC編碼和MAC地址存儲(chǔ)在XML文件中,如果需要更換或新增電子號(hào)牌,只需要更新該XML文件即可,該文件的存儲(chǔ)格式如下:
F4:B8:5E:45:EB:82
使用如下代碼將XML數(shù)據(jù)讀入到程序內(nèi)存中:
data, err:=ReadFile(CONFIG_XML)
err=xml.Unmarshal(data, &cardslice)
for _, v:=range cardslice.Item
cardmap[v.Epc]=v.Mac
業(yè)務(wù)數(shù)據(jù)存儲(chǔ)到MySQL數(shù)據(jù)庫(kù)中的“system”表中,該表僅存儲(chǔ)非冬眠狀態(tài)即正在使用中的電子號(hào)牌的業(yè)務(wù)數(shù)據(jù)。每當(dāng)發(fā)出一張新的電子號(hào)牌,使用InsertDB()向表中插入一條新數(shù)據(jù),并寫(xiě)入EPC、MAC地址等基礎(chǔ)數(shù)據(jù);當(dāng)電子號(hào)牌狀態(tài)發(fā)生改變后通過(guò)UpdateDB()改變?cè)撚涗浀臄?shù)據(jù);當(dāng)電子號(hào)牌使用完畢并進(jìn)入冬眠狀態(tài)后,通過(guò)DeleteDB()銷(xiāo)毀對(duì)應(yīng)號(hào)牌的記錄。數(shù)據(jù)表“system”的結(jié)構(gòu)和描述如表4所示。
表4 系統(tǒng)數(shù)據(jù)表結(jié)構(gòu)
服務(wù)器端軟件的業(yè)務(wù)對(duì)象主要面向手牌硬件客戶(hù)端和上層叫號(hào)應(yīng)用的調(diào)用,前者通過(guò)UDP協(xié)議與服務(wù)器端通信,后者通過(guò)HTTP API控制服務(wù)器做出相關(guān)動(dòng)作。軟件開(kāi)始運(yùn)行后,首先初始化HTTP和UDP等網(wǎng)絡(luò)相關(guān)的監(jiān)聽(tīng)接口,并通過(guò)串口檢查硬件發(fā)卡設(shè)備是否工作正常。服務(wù)器端軟件的結(jié)構(gòu)如圖10所示。
圖10 服務(wù)器端軟件結(jié)構(gòu)
GO語(yǔ)言有眾多優(yōu)秀的Web框架[10],但是本系統(tǒng)的HTTP接口僅面向上層應(yīng)用之間的調(diào)用,不需要復(fù)雜的路由配置和HTML模板引擎,因此只使用GO的標(biāo)準(zhǔn)庫(kù)接口便可以實(shí)現(xiàn)功能。使用http.HandleFunc()接口把一個(gè)URL路徑綁定給相應(yīng)的函數(shù),然后通過(guò)http.ListenAndServe()接口監(jiān)聽(tīng)8080端口的HTTP請(qǐng)求。當(dāng)客戶(hù)的應(yīng)用調(diào)用指定的URL訪問(wèn)服務(wù)器后,服務(wù)器會(huì)調(diào)用相應(yīng)的函數(shù)執(zhí)行業(yè)務(wù)功能,同時(shí)以JSON格式的數(shù)據(jù)返回給客戶(hù)應(yīng)用。以號(hào)牌發(fā)放流程為例,當(dāng)HTTP端口收到來(lái)自客戶(hù)應(yīng)用的發(fā)卡請(qǐng)求后會(huì)立即返回結(jié)果,因?yàn)榘l(fā)放操作涉及硬件控制,所以處理結(jié)果需要以異步主動(dòng)查詢(xún)的方式獲取。如果發(fā)號(hào)機(jī)為空閑狀態(tài),則通過(guò)ttyS設(shè)備控制串口做出發(fā)號(hào)操作,此時(shí)客戶(hù)的應(yīng)用可以定期調(diào)用查詢(xún)接口以查詢(xún)操作是否成功。如果以上步驟成功,則號(hào)牌會(huì)自動(dòng)激活并向服務(wù)器發(fā)送相關(guān)UDP報(bào)文來(lái)請(qǐng)求分配業(yè)務(wù)號(hào)碼。
服務(wù)器在監(jiān)聽(tīng)號(hào)牌上報(bào)的UDP報(bào)文的同時(shí),還要根據(jù)HTTP接口調(diào)用的叫號(hào)操作向指定業(yè)務(wù)類(lèi)型的號(hào)牌發(fā)送UDP廣播報(bào)文。使用以下代碼開(kāi)啟UDP服務(wù)器:
addr, err:=net.ResolveUDPAddr(″udp″, ″:″+port)
conn, err=net.ListenUDP(″udp″, addr)
其中port為UDP服務(wù)器需要監(jiān)聽(tīng)的端口號(hào),然后循環(huán)調(diào)用以下代碼監(jiān)聽(tīng)并讀取客戶(hù)端發(fā)送上來(lái)的UDP報(bào)文:
n, remoteAddr, err:=conn.ReadFromUDP(data)
與接收UDP報(bào)文的操作不同,HTTP接口的并發(fā)調(diào)用可能會(huì)引起多個(gè)同時(shí)發(fā)送UDP報(bào)文的操作,為了防止多線程之間在同時(shí)發(fā)送UDP報(bào)文的時(shí)候占用發(fā)送通道而發(fā)生異常,需要定義一個(gè)*sync.Mutex類(lèi)型的互斥鎖來(lái)保證同時(shí)只有一個(gè)線程在發(fā)送報(bào)文,代碼如下所示:
broadipport:=fmt.Sprintf(″%s:%s″, ″192.168.1.255″, cardPort)
addr, err:=net.ResolveUDPAddr(″udp″, broadipport)
locker.Lock()
//阻塞其他發(fā)送報(bào)文的線程
_, err:=conn.WriteToUDP(data, addr)
locker.Unlock()
//釋放阻塞
從代碼可以看出發(fā)送報(bào)文并未指定任何目的IP地址而是使用廣播地址和指定的端口號(hào)來(lái)發(fā)送,因?yàn)橄到y(tǒng)規(guī)定不同的號(hào)碼業(yè)務(wù)對(duì)應(yīng)不同的端口號(hào),所以每次的叫號(hào)操作并不是把報(bào)文發(fā)送給特定IP的號(hào)牌客戶(hù)端,而是以端口號(hào)為分組的廣播發(fā)送。
3.3.1 外部HTTP接口
本系統(tǒng)對(duì)于外部應(yīng)用來(lái)說(shuō)相當(dāng)于一個(gè)黑箱,各種應(yīng)用只需要調(diào)用服務(wù)器提供的HTTP接口便可以操作整個(gè)電子號(hào)牌系統(tǒng)。HTTP接口部分說(shuō)明如表5所示。
表5 HTTP接口
3.3.2 內(nèi)部UDP協(xié)議
服務(wù)器與號(hào)牌客戶(hù)端之間處于一個(gè)內(nèi)部網(wǎng)絡(luò)環(huán)境,不需要對(duì)第三方提供服務(wù),為了簡(jiǎn)化通信,直接使用OSI分層中屬于傳輸層的UDP報(bào)文進(jìn)行通信。自定義報(bào)文的格式共分為幀頭、類(lèi)型和內(nèi)容三個(gè)段。其中幀頭段固定為2個(gè)字節(jié)的0x55和0xAA;類(lèi)型段為1個(gè)字節(jié),用來(lái)區(qū)分當(dāng)前報(bào)文的功能,分別有“設(shè)置號(hào)碼業(yè)務(wù)”類(lèi)型和“叫號(hào)操作”類(lèi)型;內(nèi)容段的長(zhǎng)度根據(jù)類(lèi)型段來(lái)確定,如果類(lèi)型為設(shè)置號(hào)碼業(yè)務(wù),則內(nèi)容段共15字節(jié),包含需要開(kāi)啟的端口號(hào)、業(yè)務(wù)代碼類(lèi)型、需要設(shè)置的號(hào)碼、當(dāng)前叫到的號(hào)碼以及當(dāng)前的時(shí)間戳。如果是叫號(hào)操作類(lèi)型,則內(nèi)容段共12個(gè)字節(jié),包含當(dāng)前叫到的號(hào)碼以及該號(hào)碼的服務(wù)窗口名稱(chēng)。
本文介紹了一種基于低功耗Wi-Fi的電子號(hào)牌系統(tǒng)的設(shè)計(jì)和實(shí)現(xiàn)方法。通過(guò)系統(tǒng)對(duì)外提供便捷的HTTP操作接口,可以與大部分目前的排隊(duì)叫號(hào)場(chǎng)景進(jìn)行對(duì)接。系統(tǒng)的電子號(hào)牌不僅體積小,還可以在極低功耗的狀態(tài)下長(zhǎng)時(shí)間休眠,有較好的使用價(jià)值和用戶(hù)體驗(yàn)。