[XMOVE自主设计的体感方案] XMove Studio管理系统(二)应用开发API简要介绍
一. XMove的開放式應(yīng)用開發(fā)框架簡(jiǎn)介
XMove4.0以開放式的結(jié)構(gòu)滿足擴(kuò)展性的要求。所有無線協(xié)議,底層算法和控制邏輯全部上移到PC端。節(jié)點(diǎn)只根據(jù)接受的控制邏輯返回傳感器數(shù)據(jù)。新的架構(gòu)使得開發(fā)新應(yīng)用非常方便。
本節(jié)將主要介紹XMove應(yīng)用開發(fā)API及其使用。
二. 注冊(cè)新應(yīng)用
我們將以開發(fā)“空中鼠標(biāo)”應(yīng)用為例,介紹開發(fā)應(yīng)用的方法。
空中鼠標(biāo)是通過陀螺儀傳感器采集的旋轉(zhuǎn)數(shù)據(jù),傳遞給PC機(jī),在空中旋轉(zhuǎn)節(jié)點(diǎn)即可控制PC鼠標(biāo)的功能。由于需要鼠標(biāo)左右鍵,因此最低節(jié)點(diǎn)需求是含鍵盤的節(jié)點(diǎn)。
1.環(huán)境搭建
在VS中新建C#類庫(kù)工程,引用XFrmWork.XMove.Interface 基類庫(kù)的dll文件。該文件包含了XMove的核心基類和抽象邏輯。若您曾經(jīng)做過這步,可以跳過。添加功能時(shí)僅需在該工程中添加新的類即可。
注意,需將該工程的dll輸出路徑修改為XMove應(yīng)用插件文件夾XMovePlugin。這樣就可以不用手動(dòng)拷貝了。
2. 繼承基類
XMove應(yīng)用基類是AbstractApp,它提供基礎(chǔ)的服務(wù)和接口。新應(yīng)用從AbstractApp繼承。
[XFrmWorkAttribute("空中鼠標(biāo)", "IProgramWPF", "利用陀螺儀實(shí)現(xiàn)的空中鼠標(biāo)系統(tǒng)", "/XFrmWork.XMove.Program;component/Images/空中鼠標(biāo).jpg")]public class SkyMouse : AbstractApp{//在此處添加代碼邏輯}為了能被XFrmWork插件搜索器搜索到,需要添加XFrmWorkAttribute插件標(biāo)記。四個(gè)參數(shù)分別是: APP名稱,接口約束(應(yīng)用固定為IProgramWPF), 說明介紹,和圖片資源地址(方便主框架顯示應(yīng)用Logo)、
3. 查看效果
生成工程,運(yùn)行XMove主程序,如下圖所示,XFrmWork已經(jīng)成功加載該應(yīng)用。
三.節(jié)點(diǎn)映射和配置節(jié)點(diǎn)工作狀態(tài)
1. 節(jié)點(diǎn)映射配置
要想獲取節(jié)點(diǎn)傳遞來的信息,首先要配置應(yīng)用程序節(jié)點(diǎn)映射。節(jié)點(diǎn)映射一般在默認(rèn)情況下給出映射到哪個(gè)節(jié)點(diǎn)組的哪個(gè)節(jié)點(diǎn),并給出其名稱和最低節(jié)點(diǎn)功能需求。
在應(yīng)用程序啟動(dòng)時(shí),首先嘗試讀取硬盤中存儲(chǔ)的節(jié)點(diǎn)映射表,否則嘗試重建默認(rèn)映射表。因此必須重寫重建函數(shù):
public override void RebuildNodeRelation(){myProgramRoutedNode = new NodeRoutedCollection();myProgramRoutedNode.Add(new ProgramNodeRegeistration(){Name = "手持設(shè)備",GroupID = 0,SelectedID = NodeID.LeftHandNode,MinRequiredNodeType= XMoveStaticsHelper.QueryAbstractNodeString(typeof(XNodeHID))});}
如上案例所示,只增加一個(gè)節(jié)點(diǎn),名稱是手持設(shè)備,默認(rèn)組別為0,組內(nèi)ID是左手節(jié)點(diǎn)。最低要求是XNodeHID(包含鍵盤的MEMS節(jié)點(diǎn))
若您允許用戶在應(yīng)用中修改映射表的表項(xiàng)數(shù)量,需要重寫以下屬性:
由于空中鼠標(biāo)只需一個(gè)節(jié)點(diǎn),因此不需要改變節(jié)點(diǎn)映射項(xiàng)數(shù)量,return false. 默認(rèn)是return false的。此時(shí),用戶在運(yùn)行時(shí)修改數(shù)量的按鈕將不可用。
public override bool isMountChangedeable{get { return false; }}?
基類已經(jīng)將從外部讀取映射表,和結(jié)束程序時(shí)存儲(chǔ)映射表的功能實(shí)現(xiàn),作為開發(fā)者的您可以不關(guān)心這些問題。您只需關(guān)心重建函數(shù)和isMountChangedeable屬性。
2. 配置節(jié)點(diǎn)工作狀態(tài)
為了盡可能降低節(jié)點(diǎn)工作功耗,應(yīng)該給出應(yīng)用程序所需的節(jié)點(diǎn)刷新速率,是否需要陀螺儀等屬性。節(jié)點(diǎn)工作狀態(tài)的描述類為:
其中NodeWorkMode類描述了節(jié)點(diǎn)當(dāng)前的工作狀態(tài),而NodeControlledWorkMode類從NodeWorkMode繼承,描述當(dāng)前對(duì)該節(jié)點(diǎn)所有工作狀態(tài)需求的匯總。
NodeControlledWorkMode類會(huì)自動(dòng)匯總所有應(yīng)用對(duì)該節(jié)點(diǎn)需求,求出能滿足所有應(yīng)用的最低需求。從而在應(yīng)用發(fā)生改變時(shí),控制節(jié)點(diǎn)切換到相應(yīng)模式。
public override void ConfigNodeWorkMode(){LeftHandXNodeHID.neededWorkMode.SetWorkMode(this,true, NodeFreshSpeed.一秒32次);}?
其中函數(shù)的定義為:
public void SetWorkMode(IProgramWPF program,bool gyroEnable, NodeFreshSpeed speed){myNeededList.Add(program, new Tuple<bool, NodeFreshSpeed>(gyroEnable, speed));RefreshData();}?
參數(shù)分別為該程序的引用,是否能開啟陀螺儀和刷新速度。 ?由于陀螺儀是傳感器中的耗電大戶,因此應(yīng)該在不需要的情形下盡可能關(guān)閉之。
四.獲取傳感器數(shù)據(jù)
應(yīng)用一般有兩種類型:
- 隔一段時(shí)間獲取傳感器數(shù)據(jù),實(shí)現(xiàn)刷新,但并不關(guān)心數(shù)據(jù)是否是最新的
- 只有當(dāng)新數(shù)據(jù)到來時(shí)才會(huì)觸發(fā)應(yīng)用事件。
我們分別將將它們稱作定時(shí)器型應(yīng)用和事件型應(yīng)用。對(duì)于空中鼠標(biāo)而言,應(yīng)屬于事件型應(yīng)用。
首先必須獲得映射表定義的節(jié)點(diǎn)的引用:
LeftHandXNodeHID = XNodeGroupManager.Instance[myProgramRoutedNode[0]] as XNodeHID;XNodeGroupManager是節(jié)點(diǎn)管理器類,通過單例模式提供方便的訪問權(quán)限,索引器中,可以按上述格式,獲取節(jié)點(diǎn)引用。
1. 定時(shí)器型應(yīng)用
定時(shí)器型應(yīng)用不關(guān)心數(shù)據(jù)是否是最新的,但需要穩(wěn)定的定時(shí)實(shí)現(xiàn)刷新。要想實(shí)現(xiàn)定時(shí)刷新,需要重寫以下字段:
public override int ProcessPerSecond{get{return 25;}}?
應(yīng)用程序管理器會(huì)為重寫該字段的每個(gè)應(yīng)用提供定時(shí)器支持,在點(diǎn)擊開啟按鈕后,會(huì)自動(dòng)啟動(dòng)定時(shí)器,按下停止后關(guān)閉。應(yīng)用程序可不關(guān)心其具體實(shí)現(xiàn)。
至于在定時(shí)到來時(shí)要處理的邏輯,可以通過重寫DataProcess()函數(shù):
public override bool DataProcess(){VirtualKey.VKMouse(1, (int)(-LeftHandXNodeHID.GyroZ / 20), (int)(LeftHandXNodeHID.GyroY / 20), 0, 0);switch (LeftHandXNodeHID.thisKeyChanged){case KeyBoardChanged.KEYUP_DOWN: //左鍵 VirtualKey.VKMouse(0x0002, 0, 0, 0, 0); //按下break;case KeyBoardChanged.KEYUP_UP:VirtualKey.VKMouse(0x0004, 0, 0, 0, 0); //彈起break;case KeyBoardChanged.KEYDOWN_DOWN: //右鍵 VirtualKey.VKMouse(0x0008, 0, 0, 0, 0); //按下break;case KeyBoardChanged.KEYDOWN_UP: //右鍵VirtualKey.VKMouse(0x0010, 0, 0, 0, 0); //彈起break;case KeyBoardChanged.KEYLEFT_DOWN: //滾輪移動(dòng)VirtualKey.VKMouse(0x0800, 0, 0, -(int)(LeftHandXNodeHID.GyroX), 0); // break;}return true;}?
? ? 值得注意的是,LeftHandXNodeHID是該類的節(jié)點(diǎn)引用持有者。這樣,系統(tǒng)會(huì)在每隔1/25秒執(zhí)行該函數(shù)。
2. 事件型應(yīng)用
另外一種類型是事件型應(yīng)用,它對(duì)處理性能的要求更低,也更靈活。應(yīng)用應(yīng)該通過事件的方式訂閱節(jié)點(diǎn)管理器發(fā)出的通知:如節(jié)點(diǎn)獲取新數(shù)據(jù),建立新連接或斷開連接等。
要想配置成事件型應(yīng)用,您需要將ProcessPerSecond屬性中返回值改為0,這樣系統(tǒng)就不會(huì)提供定時(shí)器了。
對(duì)于空中鼠標(biāo)應(yīng)用,可以只關(guān)心節(jié)點(diǎn)傳遞來的新數(shù)據(jù)通知。在開啟時(shí),需要將處理方法掛接在該事件上,如下程序所示:
public override bool InitProcess(){LeftHandXNodeHID = XNodeGroupManager.Instance[myProgramRoutedNode[0]] as XNodeHID;LeftHandXNodeHID.OnXNodeEvent += LeftHandXNodeHID_OnProgramEvent;//除此之外,您可以添加其他初始化的函數(shù)return true;}?
關(guān)閉應(yīng)用時(shí),將該事件取消掛接:
public override bool CloseProcess(){LeftHandXNodeHID.OnXNodeEvent -= LeftHandXNodeHID_OnProgramEvent;return true;}LeftHandXNodeHID_OnProgramEvent是處理事件,其功能與上述DataProcess()描述完全一致,此處從略。
3. 混合型應(yīng)用
若您同時(shí)需要定時(shí)器和事件,可以將ProcessPerSecond設(shè)置成需要的值,同時(shí)掛載事件,與1,2描述一致,此處從略。
五. 開發(fā)有UI控件的應(yīng)用
在很多情形下,您可能需要開發(fā)帶UI控件的應(yīng)用。此時(shí)的開發(fā)要比一般情形復(fù)雜。具體實(shí)現(xiàn)方法和您的具體設(shè)計(jì)有關(guān)。目前僅提供WPF內(nèi)置的UserControl控件的支持。
1. 使用MVVM結(jié)構(gòu)開發(fā)
若您對(duì)MVVM結(jié)構(gòu)很熟悉,則推薦采用這種開發(fā)方式,此時(shí),需要讓您開發(fā)的類實(shí)現(xiàn)IView接口:
我們假設(shè)您對(duì)MVVM模式已經(jīng)很熟悉,需要另外設(shè)計(jì)ViewModel,該類中是DynIdentityTrainnerUI, 在構(gòu)造函數(shù)中,實(shí)現(xiàn)數(shù)據(jù)上下文綁定。
public class DynIdentityTrainner : AbstractApp, IView{DynIdentityTrainner() {myDynIdentityTrainnerUI.DataContext = this; //實(shí)現(xiàn)綁定 }DynIdentityTrainnerUI myDynIdentityTrainnerUI = new DynIdentityTrainnerUI();public UserControl thisUserControl //IView接口成員:返回要顯示的UI控件{get { return myDynIdentityTrainnerUI; }}public FrmState thisFrmState //IView接口成員:返回要放置的位置{get { return FrmState.Large; } } }?
2. 不使用MVVM開發(fā)
若您對(duì)MVVM不熟悉,通常的解決辦法是從UserControl類繼承。但是C#只支持單繼承,通常的辦法是實(shí)現(xiàn)XMove基本應(yīng)用的所有接口,這對(duì)于開發(fā)者是不合適的,因此我提供了一個(gè)UI類,解決了這一問題:
public class AbstractUIApp : UserControl, IProgramWPF, IProgramNodeChangeable, IView, IRelationComputeable{//實(shí)現(xiàn)代碼}?
在開發(fā)時(shí),您需要從AbstractUIApp類繼承,此時(shí)可獲得界面設(shè)計(jì)器的支持,其他的開發(fā)方式和上述一致,此處不贅述。
六. 其他注意點(diǎn)
1.可能要重寫的其他函數(shù)
除了以上可能要修改的屬性和重寫函數(shù)外,還有兩個(gè)函數(shù)可能需要重寫:
? ?LoadMainResource函數(shù)在用戶將其拖到應(yīng)用列表時(shí)執(zhí)行,若加載大型資源時(shí)必須重寫該函數(shù),而不是定義在InitProcess函數(shù)中,因?yàn)橛脩綦S時(shí)都可能開啟或關(guān)閉程序,不應(yīng)該在此函數(shù)中過分耗時(shí)。
例如空中鼠標(biāo),它需要在第一次初始化時(shí)加載SVM識(shí)別模型。用于手勢(shì)識(shí)別。
public override bool LoadMainResource(){mySVMMethod = new SVMMethod();mySVMMethod.LoadSVMModel(PublicName);return true;}? ?除此之外,還有對(duì)應(yīng)的釋放函數(shù)。和初始化需要的注意點(diǎn)一致:
public override bool ReleaseMainResource(){//釋放所需的非托管資源}
? ?2. 兩個(gè)輔助外部管理器
一些管理型應(yīng)用,不僅需要獲取節(jié)點(diǎn)的數(shù)據(jù),還需要知悉整個(gè)系統(tǒng)的工作狀態(tài),此時(shí)就需要獲得一些擴(kuò)展功能。
系統(tǒng)提供在基類中提供了兩個(gè)服務(wù)者,解決了以上問題:
public AbstractCommManager thisCommManager { get; set; }public IProgramManager thisProgramManager { get; set; }? ? ? 分別是通信管理器接口和程序管理器接口,它封裝了和限制了應(yīng)用對(duì)管理器的控制權(quán)限,提供了可讀的一些有用信息。
例如,在thisProgramManager的幫助下,應(yīng)用可以開啟或關(guān)閉另外一個(gè)應(yīng)用,可以在界面上添加或刪除新的UI組件,
/// <summary>/// 應(yīng)用程序管理器/// </summary>public interface IProgramManager{bool BeginOneProcess(IProgramWPF rc);bool StopOneProcess(IProgramWPF rc);void AddUserControl(UserControl value, FrmState thisState, string title);void RemoveUserControl(UserControl value);IEnumerable<NodeEnumKeyPair> GetAllEnumerable { get; }IEnumerable<IProgramWPF> GetActivePrograms { get; }}? ? ?與其類似的是,可以開啟或關(guān)閉通信方法,或獲取已開啟通信方法的枚舉等。
3. 安全性
由于系統(tǒng)使用和開發(fā)環(huán)境都是基于專業(yè)用戶的,因此以開放的精神,API提供的接口的權(quán)限都達(dá)到甚至超過了實(shí)際應(yīng)用的最大需求。在開發(fā)應(yīng)用時(shí),您應(yīng)該考慮只讀取數(shù)據(jù),而不非法寫入或修改核心狀態(tài)數(shù)據(jù),這可能會(huì)導(dǎo)致系統(tǒng)崩潰或出現(xiàn)不可預(yù)見的問題。
4. 其他API
XMove開發(fā)環(huán)境內(nèi)置了XFrmWork的全部功能集合,同時(shí)有.NET FrameWork作為支持,您所需的大部分函數(shù)和功能類都可以在其中找到,這包括網(wǎng)絡(luò)通信,數(shù)據(jù)庫(kù),圖形UI等。您可以參考詳細(xì)開發(fā)文檔,此處不進(jìn)行詳細(xì)描述。
5.發(fā)布
您可以將您的工程編譯為dll,提供給用戶。在目前框架下,無法實(shí)現(xiàn)自動(dòng)升級(jí),因此需要手動(dòng)拷貝。未來框架會(huì)加入自動(dòng)升級(jí)功能。
七. 總結(jié)
本文較詳細(xì)的介紹了在XMove框架下開發(fā)新應(yīng)用的方法和注意事項(xiàng)。目前XMove框架已經(jīng)支持多達(dá)20多種應(yīng)用,涉及節(jié)點(diǎn)管理,人機(jī)交互,虛擬現(xiàn)實(shí)等應(yīng)用,我會(huì)在后續(xù)文章中繼續(xù)介紹。
若您感興趣,歡迎聯(lián)系我 ?buptzym@bupt.edu.cn
?
總結(jié)
以上是生活随笔為你收集整理的[XMOVE自主设计的体感方案] XMove Studio管理系统(二)应用开发API简要介绍的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: .net Reflection(反射)-
- 下一篇: win10系统下使用大漠插件后台截图卡住