邊 寒 ,陳小紅 ,金 芝 ,張 民
1(上海市高可信計算重點實驗室(華東師范大學),上海 200062)
2(北京大學 信息科學技術學院 計算機科學與技術系,北京 100871)
3(高可信軟件技術教育部重點實驗室(北京大學),北京 100871)
物聯網(IoT)系統通過網絡連接的傳感器和執行器監視、調度、管理各種設備,如汽車、交通信號燈、空調、燈等,為用戶提供各種智能服務以滿足用戶服務需求,為用戶的日常生活提供便利.在這樣的系統中,用戶服務需求是智能服務的根本驅動力.近年來提出的物聯網面向用戶編程框架,如IFTTT 和Microsoft Flow[1],就是這種背景下的產物.它們允許用戶使用簡單的“IF trigger,THEN action(稱為觸發-命令編程,TAP)”規則編程.在圖1 所示的智能家居系統中,用戶可以編出這樣的規則:“如果光線亮度超過 50 000lux,則關上窗簾”,這個規則用TAP 描述為“IF Light.brightness>50000lux THEN close the blind”.但是,實際上這種TAP 句法描述的是設備調度程序,通知軟件去關窗簾,既不是用戶服務需求也不是系統行為,服務需求貼近用戶的需要,比如用戶想要窗簾關閉使得光線暗點,系統行為貼近軟件,它關心軟件是否要發出關窗簾的脈沖的事件,但TAP 句法中的“action”是指通知軟件去關窗簾的指令,既不同于狀態“窗簾關閉”,也不同于事件“關窗簾的脈沖”.
一些物聯網系統提出采用面向目標的需求方法,如文獻[2]使用領域模型和UML 圖來捕獲服務需求,支持服務目標的分解,但沒有提出措施來保障物聯網不同服務間的一致性和服務部署的完整性,容易出現一致性和完整性問題.一致性問題是指有兩條或兩條以上的服務需求之間出現沖突[3,4],而完整性問題是指在某些情況下的輸入,軟件無法給出確切的輸出[5].對于軟件系統來說,任何由于不一致、不完整導致的差錯,都可能在現實世界中產生不良后果,甚至對用戶的財產、生命造成威脅[6].在物聯網系統中,使用TAP 進行用戶編程時,用戶并不會去考慮一致性、完整性問題,使得這些問題更加突出.例如,在一個智能家居軟件系統中,如果用戶規定當一氧化碳的濃度高于一定閾值時自動開窗,又規定下雨時自動關窗,那么如果下雨時一氧化碳濃度過高,同時滿足這兩條需求,便會出現一致性問題,在這種情況下,房間的一氧化碳濃度可能會超過200mg/L,這是有害甚至致命的;再比如規定亮度低于一定閾值時開燈,但沒有規定高于這個閾值時的行為,那就會出現完整性問題,導致燈一直開著,嚴重浪費能源.現在已有很多工作提供對TAP 規則的一致性的檢測與修復[7,8],但并沒有在服務需求層面和系統行為層面上的檢測.
為了實現正確的“用戶編程”,本文提出在用戶提供的服務需求的基礎上,從服務需求中自動推導系統行為,并檢測一致性和完整性,最后自動轉換為TAP 形式的設備調度程序.在定義服務需求時,基于環境建模的需求工程思想[9,10],本文認為將服務需求指稱到設備的狀態變化上更合適,比如用戶希望的是燈滅了,而不關心用的是哪種行為使得燈關了.在從服務需求到系統行為的推導過程中,根據文獻[11],必須考慮到環境特性,在檢測一致性、完整性時,也需從設備的角度去考慮,因此,本文提出基于環境建模的物聯網系統TAP 規則生成方法,實現了服務需求到程序的自動化,主要貢獻包括:
(1) 建立了物聯網應用場景的環境本體,提供了環境建模的基本概念和關聯.針對物聯網應用場景環境的特點,定義了被監視實體和被控制實體,并用屬性和狀態機對相應特征進行了建模;
(2) 給出了基于環境的用戶服務需求的定義,將服務需求指稱到狀態變化上,定義了基于環境本體的用戶服務需求描述方法;

Fig.1 An example of smart house圖1 智能家居的例子
(3) 定義了物聯網系統的需求一致性和完整性規則,基于環境本體使用問題圖[12]進行服務需求到系統行為的自動轉換,以及基于規則完成了需求的一致性與完整性的檢測.
本文第1 節介紹系統行為推導中要使用的問題圖.第2 節定義物聯網系統的環境本體.第3 節給出本文的方法.第4 節給出關鍵算法.第5 節設計實驗,對本文方法進行評估.第6 節比較相關工作.第7 節總結全文,展望未來工作.
問題圖是問題框架方法[12]需求描述的結果,在本文中用來承載用戶服務需求和軟件行為.圖2 給出了問題圖的簡單示例,軟件問題就是要指定一個待開發系統(控制機器controller machine)來監視、控制問題領域(空氣air 和空調air conditioner),以滿足需求(調節溫度adjust temperature).問題領域與機器之間的連接稱為接口(一種交互),指明了它們之間共享的現象,如控制機器與空調之間共享現象開脈沖(OnPulse)和關脈沖(OffPulse).接口由一方發起,用“發起者!{內容}”表示,內容可以是現象中的事件、狀態或取值.需求表示為一段自然語言描述的期望,實際指稱為人們期望在問題領域上發生的改變,如期望室溫T>30,或者空調打開(on)或關閉(off)等,這種期望現象稱為需求現象.對那些只能觀察而無法控制的需求現象的引用稱為需求引用:如對于室溫,只能觀察、引用,而不能控制;而對那些可以控制的需求現象的約束稱為需求約束:如對于空調,人們可以控制它的開關.需求引用和需求約束都可以表示為接口交互的形式.

Fig.2 Simple example of a problem digram圖2 問題圖的簡單示例
問題圖的左右兩邊分別承載了用戶服務需求和軟件行為.其中,用戶服務需求用需求現象及其之間的關系來描述,表示在問題圖右邊的需求引用和約束處.如圖2 中右邊虛線處a和c中的需求現象,要求當溫度高于30°、低于20°時,空調要處于打開和關閉狀態,這是用戶需要的,是用戶的服務需求.軟件行為用規約現象及其現象之間的關系來描述,表示在問題圖左邊的接口處.如圖2 左邊實線接口a和b處,共享現象要求當溫度高于30°時,控制器發出開空調的脈沖,而溫度低于20°時則發出關空調的脈沖,這規定了軟件的系統行為.需要注意的是,在問題圖中,從用戶服務需求中導出軟件系統行為需要領域知識,本文使用環境本體來描述這些領域知識.
本體是共享概念模型的明確的形式化規范說明[13].我們定義環境本體來提供環境建模的基本概念和概念間的關聯.根據是否領域相關,將環境本體分為兩類:上層環境本體和領域環境本體.其中,上層環境本體描述通用的環境建模中的概念和關聯,領域環境本體則是針對某個具體的領域的環境建模的結果,是對上層環境本體概念和關聯在特定領域中的實例化.
物聯網系統的環境可以看作是與系統發生交互的一組實體(稱為環境實體)的集合,因此環境實體(environment entity)是環境本體中的最基本的概念.在具體的應用場景中,智能家居中的燈、窗簾、人、空氣等都是環境實體.這些環境實體可以分為兩類.
(1) 被監視的環境實體(monitored entity):這類環境實體僅可被物聯網系統以監視的方式獲取其狀態值,但卻無法直接改變這些實體的狀態,即,實體的狀態是自主變化,不以人的意志為轉移的.例如,智能家居中涉及到的室內空氣、光照等;
(2) 被控制的環境實體(controlled entity):對于這類環境實體,不僅可以獲取其狀態值(即各項屬性值),而且可以向這些環境實體發送事先定義好的指令,以改變其狀態.各種嵌入式設備均屬于該類實體,如智能家居中的日光燈、窗戶、電動窗簾等.而它們的改變既可以是狀態也可以是屬性值,例如,燈既可以用“開、關”來描述,也可以用具體的亮度數值來描述.
對于每個環境實體,都可以用屬性(attribute)來描述其特性,每個屬性都有取值(value).比如被監視的環境實體光線(light),它有屬性亮度,可以用Light.brightness表示,其取值代表光線亮度的大小;再如被控制的環境實體Bulb,它的屬性為BulbST,即燈的狀態,其屬性值可以為bon或boff,表示燈的開關狀態.除了屬性之外,還可以使用狀態機(state machine)來描述一些被控制實體的動態特性,狀態機有狀態(state)、狀態變遷(transition),而狀態變遷由事件(event)觸發.比如可以用帶有狀態bon、boff的狀態機描述燈的動態特性,當燈接收到開燈的脈沖(bonPulse)時狀態轉為bon,而當燈接受到關燈的脈沖(boffPulse)時狀態轉為boff.
這些概念之間還存在著一定的關聯.圖3 給出了這些概念之間的關聯,這些關聯的含義見表1.

Fig.3 Concept association diagram of environment ontology圖3 環境本體的概念關聯圖

Table 1 Relations and meanings of concepts in environment ontology表1 環境本體概念關聯及其含義
以智能家居為例,我們來說明領域環境本體的構造.首先識別領域中的環境實體.假設智能家居領域中包含的被控制環境實體有窗戶(window)、窗簾(blind)和燈(bulb),而被監視環境實體有光照和空氣.這些都是環境實體的實例.窗戶的屬性為WindowST,描述窗戶的開閉,其取值為wopen或wclosed;窗簾的屬性為BlindST,描述窗簾的開閉,其取值是bopen或bclosed;燈的屬性為BulbST,描述燈的開關,其取值是bon或boff;光照的屬性為brightness,表示亮度,其值在理論上可以是大于0 的任意值;空氣的屬性為溫度(temperature)和濕度(humidity),temperature表示氣溫,其值在理論上可以為–273.15 攝氏度到正無窮;humidity表示空氣的相對濕度,其值在理論上可以為0 到正無窮.這些具體的屬性和取值分別是屬性和值這兩個概念的實例.
對于每個被控制實體,需要進一步識別其狀態機.在智能家居領域中,窗戶、窗簾和燈的狀態機如圖4 所示,以燈為例,當其處于bon狀態時,表示燈開著,如果此時收到一個bonPulse事件,則繼續開著,如果收到boffPulse事件,則關閉;當其處于boff狀態時,表示燈關著,如果此時收到一個bonPulse事件,則燈打開,反之,如果收到boffPulse事件,則仍然關閉.這些都是狀態機、事件、狀態、遷移概念的具體實例.

Fig.4 State machine of controlled environment ontology in smart home systems圖4 智能家居系統的被控制環境實體的狀態機圖
在環境本體的支持下,本文提出了生成TAP 規則的方法框架,如圖5 所示.在用戶撰寫服務需求后,首先借助環境本體對系統行為進行推導,得到初始問題圖,然后對其進行一致性、完整性檢測.若通過檢測,則將檢測后的問題圖結合現象指令對照表生成TAP 規則,否則返回給用戶修改服務需求.

Fig.5 Architecture of our approach圖5 本文方法框架
首先,我們來定義用戶的服務需求.本文基于環境建模思想,將服務需求指稱到環境實體變化上,在物聯網系統中,環境實體的變化通常表現為環境實體的不同狀態.例如,在下雨時,窗戶要處于關閉這一狀態.沿用但區別于TAP 規則的“IF trigger THEN action”句法,本文將使用如下句法以供用戶表達服務需求.

其中,
· entity.trigger 有如下表達方式.
? 當entity 為被監視的環境實體時,使用entity.attribute 表示實體的屬性取某個值或屬于某一范圍,例如,光照為3 000lux,則寫作Light.brightness=3000,而光照大于3 000lux,則寫作Light.brightness>3000(為了自動化流程考慮,僅使用數值,省略單位);
? 當entity 為被控制的環境實體時,可以使用entity.state 表示實體處于某個狀態,如Window.wclosed表示窗戶處于關閉狀態,也可以是entity.attribute,其表達方式與上一條類似;
? 另外,trigger 可以是帶有與、或操作符的復雜句子,其中,與關系用&&表示,或關系用符號||表示.
· entity.state 為被控制的環境實體及其狀態.
例如,如果用戶想表達當光線的亮度大于50 000lux 時窗簾處于關閉狀態,則觸發條件中的實體為光線,是被監視實體,亮度大于50 000lux 即光線的屬性“亮度”大于50 000lux,因此,這個服務需求的entity.trigger 就是Light.brightness>50000;為了表達窗簾處于關閉狀態,entity.state 就是Blind.bclosed,因此,這條服務需求為“IFLight.brightness>50000THENBlind.bclosed”.而如果用戶想表達當窗簾關閉時燈打開的服務需求,實體為窗簾,是被控制實體,而trigger,即窗簾關閉的狀態,就是bclosed,因此,這個服務需求的entity.trigger 就是Blind.bclosed;為了表達開燈,entity.state 就是Bulb.bon,因此,這條服務需求為“IFBlind.bclosedTHENBulb.bon”.
對于復雜的服務需求,即含有與或關系的需求,也采用同樣的處理方式.例如,想要表達當氣溫高于25°且亮度大于25 000lux 時窗戶處于打開狀態,這個服務需求有兩個觸發條件,涉及兩個被監視實體:空氣和光線,觸發條件則分別是空氣的屬性溫度大于25°和光線的屬性亮度大于25 000lux,因此,這條需求的前半部分是Air.temperature>25 和Light.brightness>25000 的與;而entity.state 就是窗戶要處于打開狀態,即Window.wopen,因此,這條需求為“IFAir.temperature>25 &&Light.brightness>25000 THENWindow.wopen”.
另外,在用戶書寫服務需求時就需要引入環境本體,讓用戶選擇相應的設備,而不是隨便寫.這么做的好處在于:大多數用戶并不熟悉所有設備的性能和效果,如果讓用戶毫無限制地書寫需求,將會造成大量因不熟悉設備而造成的錯誤或遺漏.而環境本體中包含了各個設備及其狀態、效果,使用環境本體能夠在用戶書寫服務需求時提示他們設備的效果,防止用戶寫出一些荒謬的服務需求,從而減少后期檢測與修改的工作量.
系統行為的推導分為兩步.
第1 步,將第3.1 節定義的服務需求標記到問題圖中.每一條服務需求都能對應一個問題圖,其中的信息可以定義問題圖的右邊部分.具體的對應如下所示:首先是環境實體與問題領域的對應,在“IF 〈entity.trigger〉THEN 〈entity.state〉”中,entity 就是與系統交互的環境實體,它們就是問題圖的問題領域,就像圖6 中的服務需求“IFAir.temperature>30 THENWindow.wopen”的Air和Window可以直接轉換成問題領域Air和Window.其次,trigger 和state 與需求引用和約束中的現象相對應,trigger 作為需求的條件,表示對需求的引用,可以直接畫為需求引用,而state 則是用戶期望看到的現象,是對需求的約束,可以直接畫為需求約束,現象發起者應該是其前面的entity.如圖6 中Air.temperature>30 就可以直接轉為需求引用Air!{temperature>30},Window.wopen可以直接轉為需求約束Window!{wopen}.橢圓形需求里面直接標注標號即可,如圖6 中的Req1.
第2 步則需要根據環境本體推導相應的系統行為,即定義問題圖的左邊接口部分.對于簡單服務需求,即entity.trigger 中沒有與或關系的,考慮trigger 和state 的不同實體類型,分別加以處理.
· 無論entity.trigger 中的entity 是被監視實體還是被控制實體,都將需求引用中的條件直接拷貝過來,就像圖6 中的M和Air之間的接口.
· 對于entity.state 中的實體,則需要通過其狀態機,查找觸發狀態state 的事件,將其作為共享現象放在接口中,而且這個接口必須是軟件發出的,如圖6 所示,Window狀態機里的狀態wopen的觸發事件為wopenPulse,則接口就可以定義為M!{wopenPulse}.
而針對包含與或關系的復雜用戶服務需求,其處理可如下所示.
· 如果是與關系連接了多個entity.trigger,則對于每一個entity.trigger,該entity 對應的問題領域都要與需求通過需求引用相連,然后在需求引用上根據trigger 添加需求現象;
· 如果是或關系連接,即“IFa||bTHENentity.state”形式的需求,則表示若a發生或者b發生,entity 都應該處于state 狀態,那么若將a和b拆開,使得這條需求變為兩條,即“IFaTHENentity.state”和“IFbTHENentity.state”,其代表的含義也是一樣的.比如“IFAir.temperature<25||Air.humidity>25 THENWindow.wclosed”,就可以拆為“IFAir.temperature<25 THENWindow.wclosed”和“IFAir.humidity>25 THENWindow.wclosed”.因此,對這種帶有或關系的需求,我們將其拆解為兩句,分別轉換為問題圖.

Fig.6 Schematic diagram of problem diagram generation圖6 問題圖生成的示意圖
我們從環境實體的角度來定義不一致與不完整,在常規的服務需求不一致的定義的基礎上,根據trigger 和state 的不同情況,本文考慮3 種類型的需求不一致.
(1) 范圍不一致:超過一條需求的trigger 中的范圍有交集,而它們的state 實體相同,內容不同,導致需求發生沖突.例如,智能家居系統的用戶規定“IFLight.brightness<30000 THENWindow.wclosed”和“IFLight.brightness>15000 THENWindow.wopen”,那么,當亮度處于15 000lux 到30 000lux 之間時,這兩條需求同時作用在窗戶上,但state 正好相反,從而導致了范圍不一致的情況;
(2) 與或不一致:一條需求中trigger 復雜的與、或關系所導致上午不一致.例如,如果用戶規定“IF (Air.temperature>25 &&Light.brightness>25000)&&(Air.temperature<25 &&Air.humidity<30)THENWindow.wopen”,該需求前半句要求溫度高于25°而后半句要求溫度低于25°,使用與連接說明需要同時滿足這兩個條件,因此這是永遠也無法達到的,從而導致了與或的不一致.
(3) 覆蓋不一致:多條需求state 中的實體相同、內容不同,于是不同的trigger 導致后執行的state 覆蓋了先執行的state.例如,一條需求要求亮度大于20 000lux 時燈處于關閉狀態,而另一條需求要求窗簾關閉時燈處于打開狀態,假如亮度大于20 000lux 時,窗簾關上了,那么此時根據需求2,燈應該是打開的,于是開燈的狀態覆蓋了關燈的狀態,但其實此時亮度仍然大于20 000lux,根據需求1,燈應該是關閉的,從而導致覆蓋不一致的情況.
從服務需求的定義出發,根據環境實體的性質,本文考慮如下兩種需求不完整的情況.
(1) 狀態不完整:將所有服務需求對應的問題圖合并起來,它們并沒有涉及到環境本體中所有實體的所有狀態,從而導致需求的不完整.例如,在一組需求中,只有窗簾狀態為開的情況,卻并沒有使得窗簾狀態為關的情況(即Blind.bclosed),而這是不完整的;
(2) 屬性不完整:所有需求的trigger 并沒有覆蓋到對應實體屬性可達的全部范圍,導致在某些情況下無法準確地判斷實體該處于的狀態.例如,兩條需求分別規定了Light.brightness>20000 與Light.brightness<15000 時燈應該處于打開和關閉的狀態,但當亮度處于15 000lux 和20 000lux 中間情況時,是否應該保持上一時刻的狀態?還是根據一些其他標準來決定是否改變燈的狀態?這在燈的服務需求中并沒有提到,因此這是不完整的.
TAP 規則的生成分為兩個階段.
(1) 從問題圖生成系統行為:根據檢測過的問題圖,首先確定問題圖中的問題領域中是對應需求引用還是需求約束,若為引用,則其問題領域的接口對應IF 里面的內容,如果有多個引用,則使用“&&”進行連接;若為約束,則其問題領域的接口對應 THEN 里面的內容.如圖 7 所示,問題領域Air是需求引用,則其接口“Air!{temperature>30}”為IF 里的內容,而問題領域Window對應的是需求約束,則其接口“M!{wopenPulse}”為THEN里的內容,由此生成系統行為:IFAir.temperature>30 THENM.wopenPulse,但這并不是最終的TAP 規則.
(2) 從系統行為到TAP 規則:將系統行為與現象指令對照表中的相關條目進行對照后才能生成最終的TAP規則.其中,現象指令對照表是一組軟件行為與指令的對應關系,如圖7 所示,wopenPulse對應指令open the window,這個對照表可以由設備領域專家提供.將系統行為中的“M.wopenPulse”替換為指令open the window,就可以得到TAP 規則“IFAir.temperature>30 THENopen the window”.

Fig.7 Schematic diagram of generating TAP rules圖7 TAP 規則生成示意圖
為了實現第3 節中提出的方法,我們開發了TAP 規則生成工具,可以通過http://re4cps.org/dsigs 對其進行訪問,相應的視頻demo 在http://re4cps.org/examples#DSIGS 給出.本節給出一些關鍵算法,主要包括:服務需求轉換為問題圖的算法、一致性檢測算法和完整性檢測算法以及TAP 生成算法.
服務需求轉換為問題圖算法就是要實現第3.2 節中提到的系統行為的推導,該算法的主要思路是:首先處理服務需求中的與、或關系,然后對于每一條服務需求,依照第3.2 節所述的對應關系,根據服務需求構建問題圖的問題領域和引用,最后借助環境本體構建問題圖的接口.
具體步驟如算法1 所示.其中,第5 行~第7 行對服務需求中的與、或關系進行預處理,第9 行~第13 行循環遍歷需求的entity.trigger(如果沒有與關系連接多個entity.trigger,則循環只進行1 次),構建與trigger 有關的問題領域、需求引用和接口,第14 行~第16 行則處理entity.state,構建與其有關的問題領域、需求約束和接口.假設服務需求的總條數為n,算法中有兩個循環,均與n有關,因此該算法的時間復雜度為O(n2).
算法1.服務需求轉換為問題圖.
輸入:所有服務需求reqs,環境本體eo;
輸出:問題圖集合ProDgms={prodgm1,prodgm2,...,prodgmn}.


根據第3.3 節給出的一致性和完整性定義,我們設計需求的一致性檢測算法和完整性檢測算法.一致性檢測算法的主要思路是:首先根據問題圖的需求引用和需求約束,獲取所有的(trigger,state)對;然后檢測實體相同的state 對應的trigger 是否有重合,從而檢測范圍不一致和覆蓋不一致,將不一致的需求反饋給用戶;最后根據(trigger,state)對中的trigger 檢測是否發生與或不一致,如果發生,則將對應的需求反饋給用戶.
一致性檢測算法的具體步驟如算法2 所示,算法第2 行抽取所有問題圖中的(trigger,state)對,第3 行構造entityMap 存放實體相同、內容不同的state 對應的trigger,根據entityMap,第4 行~第17 行的循環檢測范圍不一致與覆蓋不一致,第18 行~第29 行的循環則根據所有trigger 檢測與或不一致,檢測過程中如果出現了不一致,則輸出不一致的需求,算法返回false,若沒有不一致,則算法最終返回true.算法中最深的嵌套循環有3 個,但2 個循環都執行常數次,因此,算法2 的時間復雜度是O(n).
為了獲取需求引用包含的所有trigger 及對應的state,本文設計了resolveProDgm函數來抽取所有問題圖中的(trigger,state)對,其具體步驟如算法3 所示,算法第3 行遍歷所有問題圖中的需求,第7 行~第9 行的循環讀取需求引用中的現象,獲取trigger,第10 行讀取需求約束中的現象,獲取state.假設需求的條數為n,算法的時間復雜度為O(n).
完整性檢測算法的主要思路是:首先抽取所有問題圖中的(trigger,state)對;然后將涉及到的所有state 與環境本體對比,檢測狀態不完整,將沒有涉及到的狀態反饋回用戶;最后根據擁有相同實體的state 對應的trigger,檢測屬性不完整,將沒有覆蓋到的情況反饋回用戶.其主要步驟如算法4 所示.算法的2 行調用resolveProDgm函數,獲取了所有的(trigger,state)對,第4 行~第6 行的循環初始化states,第7 行~第13 行根據states 和環境本體檢測狀態不完整,第14 行~第24 行的循環則檢測屬性不完整.假設需求數量為n,算法4 的第2 行用到了resolveProDgm函數,其時間復雜度為O(n),而之后的循環都只有1 層,最多只循環n次,因此該算法的時間復雜度為O(n).
根據第3.4 節TAP 規則的生成方法,可以設計具體生成算法,其主要思路為:首先根據問題圖需求引用對應接口中的內容,確定TAP 規則的trigger;然后根據問題圖需求約束對應的接口,構建系統行為;最后根據現象指令對照表,獲取現象對應的指令,將系統行為轉換為TAP 規則.
算法的主要步驟如算法5 所示.第2 行遍歷所有檢測后的問題圖,第6 行獲取所有需求引用對應的問題領域,第7 行~第10 行的循環獲取這些問題領域對應接口中的現象,作為TAP 規則的trigger,第10 行為系統行為,第11 行根據映射table(即現象指令對照表)將系統行為轉換為對應的指令.假設需求條數為n,嵌套的2 個循環,即第6 行的循環執行常數次,因此,該算法的時間復雜度為O(n).
算法2.一致性檢測算法.
輸入:問題圖集合ProDgms={prodgm1,prodgm2,..,prodgmn};
輸出:是否滿足一致性以及不滿足一致性的需求.


算法3.resolveProDgm:解析問題圖,抽取所有trigger 與state.
輸入:問題圖集合ProDgms={prodgm1,prodgm2,...,prodgmn};
輸出:ProDgms 中的所有(trigger,state)對,將其存放在映射map 中.

以智能會議室系統為背景,本節對本文方法進行評估,主要回答以下幾個問題.
(1) 本方法的準確性和效率如何?與人工編寫TAP 規則相比,使用本文方法制定TAP 規則會有更高的準確性和效率嗎?
(2) 本方法的性能如何?是否適用大規模系統?
(3) 環境本體的構建時間是否對方法的使用造成影響?
算法4.完整性檢測算法.
輸入:問題圖集合ProDgms={prodgm1,prodgm2,...,prodgmn},環境本體eo;
輸出:是否滿足完整性,若不滿足,則輸出為何不滿足.


算法5.TAP 生成算法.
輸入:檢測后的問題圖集合ProDgms={prodgm1,prodgm2,...,prodgmn},現象指令對照表table;
輸出:TAP 規則集合rules.

為了回答這個問題,我們設計了一系列對比實驗:首先將用戶分為兩組:本方法組和TAP 組.本方法組首先書寫服務需求,然后通過本文方法,在進行一致性、完整性的檢測和修改后,生成TAP 規則;而TAP 組則由人工直接編寫TAP 規則,并對其進行一致性、完整性的檢測和修改.為了避免用戶背景造成的差異,我們又將用戶分為兩類:專業類和非專業類.其中,專業用戶為軟件工程在讀的學生,他們參加過一些與需求相關的課題,有一定的需求工程方面的知識;非專業用戶為旅游經濟學、醫學或語言學專業的學生,沒有任何計算機或軟件工程方面的學科知識.由此,本方法組和TAP 組又分別分為兩個對照組,共4 組實驗.我們總共邀請了24 名用戶,每組各6 名.
我們請每個用戶對一個限定的物聯網場景書寫10 條需求,規定該場景中的實體只有空氣、光線、人、窗戶、窗簾、投影儀、空調和燈,空氣有溫度和濕度兩個屬性,光線有亮度屬性,人可以按下投影儀的開關,窗戶和窗簾有open和closed的狀態,投影儀和燈有on和off的狀態,而空調的狀態則可以是cold、hot和off.對于專業的本方法組,我們告知他們書寫需求的格式、環境中的實體以及實體的狀態取值;對于非專業的本方法組,由于對領域知識沒有了解,我們直接告訴他們需求句式IF entity.trigger THEN entity.state 中,entity.trigger 和entity.state 的可填內容;對于專業的TAP 組,我們告知他們編寫規則的格式、環境中的實體以及實體的狀態取值,讓他們推測環境本體中的指令;對于非專業的TAP 組,我們直接告訴他們規則句式IF entity.trigger THEN action 中entity.trigger 和action 的可填內容.對于兩個TAP 組,在編寫完規則后,告訴他們一致性、完整性的定義,并要求他們對自己編寫的規則進行手動檢測和修改.
在每組實驗中,我們分別統計本方法組用戶書寫需求所花費的時間,本方法組用戶檢測和修改需求使其滿足一致性與完整性花費的時間,TAP 組用戶編寫規則所花費的時間,TAP 組用戶人工進行一致性與完整性檢測所花費的時間,TAP 組用戶修改規則花費的時間,所有用戶修改前、后的一致性、完整性錯誤數以及所有用戶最終得到的TAP 規則的準確率.在實際記錄時,兩個本方法組由于使用計算機程序自動地對一致性、完整性進行檢測,因此檢測時間很短,在總時間中,我們忽略了這些檢測時間.最終實驗結果見表2.
從表2 中可以得出如下結論:本方法的準確率和效率確實超過可用閾值.首先,觀察修改前、后的不一致和不完整數量可以發現,相比于TAP 組手動檢測和修改錯誤,使用本方法進行檢測和修改大大減少了錯誤的數量,而對比表中各個組的最后一行可以發現,無論是專業組還是非專業組,使用本方法得到的TAP 規則的準確率普遍高于TAP 組;其次,對比表中各個組的前4 行,即與時間相關的數據可以發現,無論是專業組還是非專業組,盡管本方法組書寫需求花費的時間普遍超出TAP 組直接編寫規則的時間,但在對其進行一致性、完整性的檢測與修改后,本方法組花費的總時間基本上都低于TAP 組.由此我們可以回答問題1,與人工編寫TAP 規則相比,使用本文方法生成的TAP 規則確實有更高的準確性和效率.

Table 2 Result of user study表2 調研結果
本方法對非專業用戶更有用.無論是花費的總時間,還是最終的準確率,在非專業組中,本方法組都要明顯好于TAP 組.原因在于,專業組的用戶由于擁有比較豐富的背景知識,在進行人工的一致性、完整性檢測時也能做到比較高的準確率,所以這一現象在專業組并不十分明顯,但這在非專業組則非常明顯.由此我們認為,與人工組相比,使用本文的方法,對非專業用戶來說確實更友好.
我們還注意到,同一組中不同用戶的書寫時間與最終準確率也可能有較大的差異,造成這種差異的原因有二.
其一,用戶所書寫的需求、編寫的規則其復雜程度不同,導致準確率有所不同.如一些用戶書寫的需求或規則的trigger 都不包含與、或連接符,也不包含受控制實體的狀態,僅包含受感知實體的屬性值,這樣的需求或規則就比較簡單,能夠寫出較高的準確率;而另外一些用戶則執著于復雜的需求,這就導致錯誤較多.
其二,其他領域知識的差異導致了書寫時間上的差別.例如,同樣學習軟件工程并對需求工程有一定認識,一名專業用戶僅花費了12 分鐘便寫完了程序,而另一名專業用戶卻花費了30 分鐘才寫完需求,經過詢問發現,其對光照的單位勒克斯(lux)和相對濕度沒有概念,因此花費了較多時間查閱資料才完成了需求撰寫.由此可見,盡管專業背景差距不大,但其他一些影響因素,如生活經驗、其他領域的知識等,也會導致評估的結果出現波動.
與人們普遍認知不同,專業組一些用戶的最終準確率無法達到100%,且專業組的書寫時間大都比非專業組更長.我們探究了其中的原因,準確率無法達到100%是因為他們所寫的一些需求盡管沒有違反一致性、完整性,但需求本身卻是錯誤的.例如,一名專業用戶寫的需求“IFAir.humidity>45 THENWindow.open”,當空氣濕度大于一定數值(下雨了)時窗戶處于打開狀態,這是背離生活實際的,因此這是一條沒有違反一致性、完整性,但卻錯誤的需求;專業組平均花費更長的時間是因為專業組擁有更多的背景知識,在書寫需求時有更多的考量,而非專業組則完全憑借實際經驗.
本節對本文方法的自動化流程進行性能分析.我們設計了5 組實驗,分別評估服務需求轉換為問題圖的算法、一致性檢測算法、完整性檢測算法、TAP 生成算法以及整個本文方法的性能.對于每組實驗,本文都設計了10 個實驗,分別對10 條、30 條、50 條、100 條、200 條、300 條、500 條、800 條、1 000 條、1 200 條需求運行算法,并記錄了所花費的時間.本文的實驗環境為64 位Win10 系統,Intel(R) Core(TM) i7-9700k CPU @3.60 GHZ,32 G RAM.
每個實驗的服務需求都是使用程序自動生成的.當評估服務需求轉換為問題圖的算法以及TAP 生成算法時,我們生成了完全正確的服務需求;當評估一致性、完整性檢測算法以及整個流程時,生成的需求有20%的概率為不一致的需求,20%的概率為不完整的需求,如果生成出不一致的需求,再分別以1/3 的概率隨機生成3 種不一致;如果生成出不完整的需求,再分別以1/4、1/4、1/2 的概率隨機生成狀態不完整、不包含與或的屬性不完整、包含與或的屬性不完整.為了防止隨機性影響評估結果,每個實驗進行了10 次,我們分別記錄了每次實驗的不一致、不完整個數和時間消耗,對10 次結果取平均值作為評估結果.10 組實驗的不一致、不完整的平均個數見表3,最終的性能評估結果如圖8 所示.

Table 3 Average number of inconsistency/incompleteness and their distribution in experiments表3 實驗中的不一致、不完整平均個數及分布情況
由圖8 的趨勢可以看出,本方法的性能超過可用閾值.服務需求到問題圖的轉換算法、TAP 生成算法、一致性檢測算法與完整性檢測算法的用時都在隨著需求條數的增加而增加,且速率并沒有很大,這與前文算法復雜度為O(n)和O(n2)的計算基本符合.由此可以認定,本方法可適用于大規模系統.
從圖8 還可看出,當需求提高到一定數量時,服務需求轉換為問題圖的算法花費的時間明顯超過一致性、完整性檢測算法和TAP 生成算法所花費的時間,其原因在于:假設需求條數為n,則由第4 節可知,一致性檢測算法、完整性檢測算法和TAP 生成算法的時間復雜度都為O(n),但服務需求轉換為問題圖算法的復雜度為O(n2),因此,轉換算法的時間復雜度是高于兩種檢測算法和TAP 生成算法的,隨著需求條數的增加,環境本體中的狀態總數相應地增加后,理應花費更多的時間.
另外,圖8 中一致性檢測算法與完整性檢測算法的時間消耗并不是嚴格的單調遞增.我們認為,這與實驗設計時每組案例的服務需求中不一致與不完整的數量是有關系的,即服務需求一致(完整)和服務需求不一致(不完整)在檢測時所花費的時間是不一樣的.為了證明這一點,我們又設計了4 組實驗進行對比:第1、第2 組實驗分別評估在沒有一致性(完整性)錯誤的情況下運行一致性(完整性)檢測算法的性能,而第3、第4 組實驗分別評估有一致性(完整性)錯誤的情況下運行一致性(完整性)檢測算法的性能,其中,第3、第4 組實驗的一致性、完整性問題的平均個數仍可見表3.每組實驗仍然按服務需求的個數分為10 個實驗,每個實驗做10 次,記錄其所花費的時間,結果取平均值.最終結果如圖9 所示.

Fig.8 Result of performance analysis圖8 性能分析結果

Fig.9 Time cost of consistency and completeness checking圖9 一致性與完整性檢測的時間消耗
由圖9 可以看出,與有錯誤相比,當問題圖中不存在一致性、完整性錯誤時,進行一致性、完整性檢測的時間大為縮短.因此,使用本文方法進行TAP 規則生成時,如果用戶書寫的需求本身質量極高,沒有錯誤,就不會因為一致性、完整性的檢測而增加時間.
與直接書寫TAP 規則相比,使用本方法需要先建立環境本體,本節試圖討論是否值得花費這些時間去建立環境本體:即建立環境本體能否節省更多的其他時間,以及隨著需求數的增多,這些建立環境本體的時間消耗能否忽略不計.
在第5.1 節的準確性與效率的評估實驗中,環境本體包含5 個被控制實體,它們共有11 個狀態、24 個轉換關系.盡管用戶平均花費了7 分鐘來建立和修改環境本體,但與人工檢測相比,本方法自動檢測一致性、完整性錯誤,節省了更多時間,加上本文的方法還會提示錯誤的語句,幫助用戶進行修改.可以看出,在10 條需求的情況下,建立環境本體所花費的時間就已經小于本方法節省的時間了,而如果在需求較多的場合,盡管由于實體增多,建立環境本體的時間也有一定的增加,但這與人工檢測一致性、完整性花費的大量時間相比,一定是利大于弊的.因此我們認為,使用本方法,花費一些額外的時間建立環境本體可節省更多的時間,是值得的.
本文還設計了一組實驗以證明上述結論.我們認為,盡管需求的數量不斷增加,但是如果建立環境本體、書寫需求、推導系統行為、進行一致性/完整性檢測和修改到規則生成完畢,這個過程所花費的總時間漸漸趨于穩定的話,就能夠說明,在需求規模到達一定程度后,就可以基本忽略建立環境本體對效率的影響.因此,我們設計了10 個實驗,編號1 到10,分別統計了在10 條、30 條、50 條、100 條、200 條、300 條、500 條、800條、1 000 條、1 200 條需求的情況下,總時間(建立環境本體的時間與上述步驟時間之和)與需求條數的比值,即平均每條需求需要花費的時間,實驗結果如圖10 所示.

Fig.10 Ratio of total time to number of requirements圖10 建立環境本體與上述步驟總時間和需求數量的比值
由圖10 可以看出,當需求數量上升時,總時間與需求數的比值會逐漸地趨于穩定,也就是說,建立環境本體的時間越來越短,甚至會趨于0,其原因有二:一是領域專家越來越熟悉環境本體的構建,構建環境本體會越來越快;二是同一個領域中很多元素可以復用.例如,一個智能家居物聯網系統,當用戶撰寫10 條需求時,環境本體涉及的被控制實體只有燈、窗戶、窗簾,而當用戶撰寫50 條需求時,環境本體涉及的被控制實體有燈、窗簾、窗戶、空調和電視,那么燈、窗戶、窗簾這部分的環境本體是可以復用的,這就減少了構建環境本體的時間.受這兩方面的影響,建立環境本體的時間被分攤到了越來越多的需求中,逐漸變得可以忽略不計.
需要注意的是,本文方法的正確執行依賴于正確的環境本體.若環境本體出現錯誤,那么本文方法的正確性也將受到影響.如錯誤地添加了一個不該存在的環境實體,則在檢測完整性時,會錯誤地將一些沒有問題的需求判斷為狀態不完整;若環境本體中的遷移出現錯誤,如某個遷移條件寫錯,則在根據環境本體推導系統行為時,有可能會找不到對應的系統行為,導致出錯.事實上,在第5.1 節的用戶調研中,已經出現了這樣的問題.專業組的一名用戶花費了14 分鐘進行需求的修改,這在有本文方法提示錯誤的情況下,已經是很長的時間了.經過詢問發現,其在修改過程中發現自己的環境本體建立錯誤,因此重新建立了環境本體,再對需求進行了更改,所以耗時較長.所以,在構建環境本體時,強調兩點:環境本體應該為領域專家構建;環境本體建好之后應該進行同行審查,盡量降低錯誤的可能性.
與本文相關的工作包括物聯網系統的需求獲取方法、需求的一致性與完整性檢測以及TAP 的一致性與完整性檢測方法.目前已有一些獲取物聯網系統需求的工作.如文獻[2]介紹了一套制定和規范物聯網系統需求的方法,物聯網系統的需求規格說明包括:領域模型、描述目標及其關系的目標視圖以及用UML 圖描述的目標規范(goals’ specification).它采用面向目標的方法理念[14],將需求指稱到目標上,比較主觀,而我們采用的基于環境建模的需求工程理念,將需求指稱到環境設備的狀態變化上,比較客觀.另外,其領域模型與我們的環境本體一樣,都屬于領域知識,但它只用在需求獲取上,沒有用在一致性、完整性的檢測上.還有一些工作側重在物聯網的非功能需求上,例如,文獻[15]基于i*框架[16],在物聯網系統的開發早期對安全與隱私需求進行捕獲.文獻[17]則基于K-model,允許開發者根據模版編寫JSON 形式的代碼,然后通過這些代碼撰寫、修改非功能需求.本文的需求涉及服務需求和功能需求,并未涉及非功能需求.
關于需求的完整性與一致性,也已有很多工作.文獻[18]闡述了不一致、不完整的需求將會給軟件開發帶來的災難性后果,并且給出了度量軟件需求規格說明(SRS)完整性、一致性的指標,但其完整性、一致性需要人工去保障;文獻[19]進行了一致性自動檢測,它將需求表示為SCR 表格符號,將軟件系統表示為有限狀態自動機,并通過靜態分析方法自動檢測其一致性;文獻[20]使用一種基于狀態的需求規范語言——RSML 來表示需求,并利用RSML 的特性,對其進行了完整性與一致性的分析;文獻[21]為了提高需求的完整性,提供了一個自然語言處理工具,撰寫需求時,該工具會自動提示可能會用到的術語或關系,幫助需求工程師發現相關的概念和交互,從而更準確地撰寫需求;文獻[22]基于障礙分析,將模型檢測和機器學習相結合,識別、評估和解決可能阻礙系統目標的異常情況,從而產生符合完整性的需求.這些方法既沒有用在物聯網系統中,不支持用戶編程,也沒有使用環境知識進行檢測.
也有一些工作是基于知識進行需求一致性與完整性檢測的.例如,文獻[8]提出了一種基于知識的需求工程過程方法以保證需求的一致性和完整性.其作者提出一種基于框架本體和生產規則的混合模型來表示系統需求,將本體框架與生產規則結合在一起,從而對需求的一致性、完整性進行檢測;文獻[23]提出的框架使用專家代理來協助用戶進行需求定義,該框架使用知識庫和案例庫來幫助用戶定義一套符合完整性和一致性的系統需求,它允許控制權在用戶和專家代理之間來回切換,為需求編寫提供了協作媒介;文獻[24]給出了一種本體驅動的基于目標的需求工程元模型,該模型基于推理技術,結合了本體一致性檢測與規則驅動的完整性測試,既可以用來捕獲需求,也可以度量演化中的需求模型的正確性與覆蓋度.這些基于知識的方法與本文有相似之處,本文的環境本體其實也是知識,但本文的環境本體是關于物聯網系統的環境知識.
還有很多需求的一致性檢測是基于模式語言的形式化及形式化驗證方法.文獻[25]使用規范模式系統形式的受限制自然語言來描述系統需求,然后自動地將其轉換為時間計算樹邏輯,再轉換為一階邏輯公式,使用Z3對其執行SMT 分析,檢測需求是否一致;文獻[26]使用BTC 模式表示需求[27],為了最小化分析成本,它使用了有界模型檢測方法來檢測一致性;文獻[28]定義了一種名為SafeNL 的安全需求模式語言,以類自然語言的方式表達需求,然后將其自動轉換為時鐘約束規范語言,通過有界模型檢測的方法檢測安全需求的一致性;文獻[29]為簡化通用模式提出了新的形式化一致性概念,即偏序一致性.偏序一致性可識別系統的關鍵案例,并驗證這些案例是否會引起需求之間的沖突.該文首先使用計數自動機對簡化通用模式表示的需求進行形式化建模,然后對偏序一致性進行了形式化的定義,給出了檢測需求模型是否違背偏序一致性的方法;文獻[30]提出了一種針對汽車系統的結構化需求撰寫語言,它使用汽車系統的本體來提供詞法和句法的標準,將需求的一致性檢測轉換為一個布爾命題的證明,然后使用定理證明的方法來檢測需求一致性.這些方法中的模型檢測和定理證明,都是重量級的形式化方法,效率難以保證,且返回結果難以為一般用戶所理解.
現在已有一些工作采用形式化方法對TAP 規則進行一致性檢測.例如,文獻[7]中的AutoTap,允許用戶使用TAP 規則來描述需求,也允許用戶定義系統必須滿足的屬性.AutoTap 將用戶書寫的規則和屬性轉換為LTL 公式,使用模型檢測的方法檢測它們是否有沖突.張秋萍等人開發的工具[31]使用形式化方法,將TAP 規則轉換為CTL 與LTL 公式,然后借助NuSMV 工具檢測其一致性;文獻[32]同樣使用了形式化方法,使用線性混合自動機建模物聯網系統,然后進行可達性分析來檢測其一致性.這些方法都是對TAP 進行檢測,這與本文截然不同,本文檢測的是系統行為之間是否沖突;而且本文方法實際上是基于規則的方法,效率較高,且使用規模較大.
為了實現從服務需求到設備調度程序的自動生成,讓終端用戶參與物聯網系統的開發,本文提出了基于環境建模的TAP 規則生成方法,自動地基于環境模型從服務需求中推導系統行為,檢測系統行為的完整性與一致性,并最后轉換為TAP 規則.本文構建了環境本體,提供了環境建模的概念和關聯,描述了物聯網系統中的各個設備的狀態、屬性、行為以及它們之間的關系.然后,基于環境本體,支持從用戶撰寫的服務需求推導出系統行為,對其進行一致性、完整性檢測以及TAP 規則轉換的全過程.本文還對該方法進行了評估,結果表明,其有較好的性能、效率以及準確性;評估還表明,隨著需求數的增加,建立環境本體的時間變得可以忽略不計,并能節省很多人工檢測一致性、完整性問題的時間.
本文僅關注于物聯網系統的功能需求,并未涉及時間、安全性、隱私性、可信賴度等非功能需求.未來工作將考慮對這些非功能需求進行捕獲和檢測.另外,在環境本體的構建中,目前都還只依賴于領域專家,下一步工作將考慮采用半自動甚至全自動的方法進行構建.