[XMOVE自主设计的体感方案] XMove Studio管理系统(二)应用开发API简要介绍

一. XMove的开放式应用开发框架简介

  XMove4.0以开放式的结构满足扩展性的要求。所有无线协议,底层算法和控制逻辑全部上移到PC端。节点只根据接受的控制逻辑返回传感器数据。新的架构使得开发新应用非常方便。

  本节将主要介绍XMove应用开发API及其使用。

二. 注册新应用  

  我们将以开发“空中鼠标”应用为例,介绍开发应用的方法。

  空中鼠标是通过陀螺仪传感器采集的旋转数据,传递给PC机,在空中旋转节点即可控制PC鼠标的功能。由于需要鼠标左右键,因此最低节点需求是含键盘的节点。

  1.环境搭建

  在VS中新建C#类库工程,引用XFrmWork.XMove.Interface 基类库的dll文件。该文件包含了XMove的核心基类和抽象逻辑。若您曾经做过这步,可以跳过。添加功能时仅需在该工程中添加新的类即可。

  注意,需将该工程的dll输出路径修改为XMove应用插件文件夹XMovePlugin。这样就可以不用手动拷贝了。

  2. 继承基类

  XMove应用基类是AbstractApp,它提供基础的服务和接口。新应用从AbstractApp继承。

    [XFrmWorkAttribute("空中鼠标", "IProgramWPF", "利用陀螺仪实现的空中鼠标系统", "/XFrmWork.XMove.Program;component/Images/空中鼠标.jpg")]public class SkyMouse : AbstractApp{//在此处添加代码逻辑}

  为了能被XFrmWork插件搜索器搜索到,需要添加XFrmWorkAttribute插件标记。四个参数分别是: APP名称,接口约束(应用固定为IProgramWPF), 说明介绍,和图片资源地址(方便主框架显示应用Logo)、

  3. 查看效果

  生成工程,运行XMove主程序,如下图所示,XFrmWork已经成功加载该应用。

 

三.节点映射和配置节点工作状态

 1. 节点映射配置

   要想获取节点传递来的信息,首先要配置应用程序节点映射。节点映射一般在默认情况下给出映射到哪个节点组的哪个节点,并给出其名称和最低节点功能需求。

  在应用程序启动时,首先尝试读取硬盘中存储的节点映射表,否则尝试重建默认映射表。因此必须重写重建函数:

  

   public override void RebuildNodeRelation(){myProgramRoutedNode = new NodeRoutedCollection();myProgramRoutedNode.Add(new ProgramNodeRegeistration(){Name = "手持设备",GroupID = 0,SelectedID = NodeID.LeftHandNode,MinRequiredNodeType= XMoveStaticsHelper.QueryAbstractNodeString(typeof(XNodeHID))});}

  如上案例所示,只增加一个节点,名称是手持设备,默认组别为0,组内ID是左手节点。最低要求是XNodeHID(包含键盘的MEMS节点)

  若您允许用户在应用中修改映射表的表项数量,需要重写以下属性:

  由于空中鼠标只需一个节点,因此不需要改变节点映射项数量,return false. 默认是return false的。此时,用户在运行时修改数量的按钮将不可用。

        public override bool isMountChangedeable{get { return false; }}

 

   基类已经将从外部读取映射表,和结束程序时存储映射表的功能实现,作为开发者的您可以不关心这些问题。您只需关心重建函数和isMountChangedeable属性。

  2. 配置节点工作状态

  为了尽可能降低节点工作功耗,应该给出应用程序所需的节点刷新速率,是否需要陀螺仪等属性。节点工作状态的描述类为:

  其中NodeWorkMode类描述了节点当前的工作状态,而NodeControlledWorkMode类从NodeWorkMode继承,描述当前对该节点所有工作状态需求的汇总。

  NodeControlledWorkMode类会自动汇总所有应用对该节点需求,求出能满足所有应用的最低需求。从而在应用发生改变时,控制节点切换到相应模式。

  public override void ConfigNodeWorkMode(){LeftHandXNodeHID.neededWorkMode.SetWorkMode(this,true, NodeFreshSpeed.一秒32次);}

 

  其中函数的定义为:

   public  void SetWorkMode(IProgramWPF program,bool gyroEnable, NodeFreshSpeed speed){myNeededList.Add(program, new Tuple<bool, NodeFreshSpeed>(gyroEnable, speed));RefreshData();}

 

  参数分别为该程序的引用,是否能开启陀螺仪和刷新速度。  由于陀螺仪是传感器中的耗电大户,因此应该在不需要的情形下尽可能关闭之。

四.获取传感器数据

  应用一般有两种类型:

  •   隔一段时间获取传感器数据,实现刷新,但并不关心数据是否是最新的
  • 只有当新数据到来时才会触发应用事件。

   我们分别将将它们称作定时器型应用和事件型应用。对于空中鼠标而言,应属于事件型应用。

  首先必须获得映射表定义的节点的引用:

     LeftHandXNodeHID = XNodeGroupManager.Instance[myProgramRoutedNode[0]] as XNodeHID;

  XNodeGroupManager是节点管理器类,通过单例模式提供方便的访问权限,索引器中,可以按上述格式,获取节点引用。

 1. 定时器型应用

  定时器型应用不关心数据是否是最新的,但需要稳定的定时实现刷新。要想实现定时刷新,需要重写以下字段:

   public override int ProcessPerSecond{get{return 25;}}

 

  应用程序管理器会为重写该字段的每个应用提供定时器支持,在点击开启按钮后,会自动启动定时器,按下停止后关闭。应用程序可不关心其具体实现。

  至于在定时到来时要处理的逻辑,可以通过重写DataProcess()函数:

 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:  //滚轮移动VirtualKey.VKMouse(0x0800, 0, 0, -(int)(LeftHandXNodeHID.GyroX), 0);  //
                    break;}return true;}

 

    值得注意的是,LeftHandXNodeHID是该类的节点引用持有者。这样,系统会在每隔1/25秒执行该函数。

 2. 事件型应用

   另外一种类型是事件型应用,它对处理性能的要求更低,也更灵活。应用应该通过事件的方式订阅节点管理器发出的通知:如节点获取新数据,建立新连接或断开连接等。

  要想配置成事件型应用,您需要将ProcessPerSecond属性中返回值改为0,这样系统就不会提供定时器了。

  对于空中鼠标应用,可以只关心节点传递来的新数据通知。在开启时,需要将处理方法挂接在该事件上,如下程序所示:

   public override bool InitProcess(){LeftHandXNodeHID = XNodeGroupManager.Instance[myProgramRoutedNode[0]] as XNodeHID;LeftHandXNodeHID.OnXNodeEvent += LeftHandXNodeHID_OnProgramEvent;//除此之外,您可以添加其他初始化的函数return true;}

 

  关闭应用时,将该事件取消挂接:  

  public override bool CloseProcess(){LeftHandXNodeHID.OnXNodeEvent -= LeftHandXNodeHID_OnProgramEvent;return true;}

  LeftHandXNodeHID_OnProgramEvent是处理事件,其功能与上述DataProcess()描述完全一致,此处从略。

  3. 混合型应用

  若您同时需要定时器和事件,可以将ProcessPerSecond设置成需要的值,同时挂载事件,与1,2描述一致,此处从略。

五. 开发有UI控件的应用

  在很多情形下,您可能需要开发带UI控件的应用。此时的开发要比一般情形复杂。具体实现方法和您的具体设计有关。目前仅提供WPF内置的UserControl控件的支持。

  1. 使用MVVM结构开发

  若您对MVVM结构很熟悉,则推荐采用这种开发方式,此时,需要让您开发的类实现IView接口:

  我们假设您对MVVM模式已经很熟悉,需要另外设计ViewModel,该类中是DynIdentityTrainnerUI, 在构造函数中,实现数据上下文绑定。

   public class DynIdentityTrainner : AbstractApp, IView{DynIdentityTrainner()
{myDynIdentityTrainnerUI.DataContext = this;   //实现绑定
}DynIdentityTrainnerUI myDynIdentityTrainnerUI = new DynIdentityTrainnerUI();public UserControl thisUserControl  //IView接口成员:返回要显示的UI控件{get { return myDynIdentityTrainnerUI; }}public FrmState thisFrmState  //IView接口成员:返回要放置的位置{get { return FrmState.Large; }  }
}

 

  2. 不使用MVVM开发

  若您对MVVM不熟悉,通常的解决办法是从UserControl类继承。但是C#只支持单继承,通常的办法是实现XMove基本应用的所有接口,这对于开发者是不合适的,因此我提供了一个UI类,解决了这一问题:  

 public class AbstractUIApp : UserControl, IProgramWPF, IProgramNodeChangeable, IView, IRelationComputeable{//实现代码}

 

  在开发时,您需要从AbstractUIApp类继承,此时可获得界面设计器的支持,其他的开发方式和上述一致,此处不赘述。

六. 其他注意点

  1.可能要重写的其他函数

  除了以上可能要修改的属性和重写函数外,还有两个函数可能需要重写:

     LoadMainResource函数在用户将其拖到应用列表时执行,若加载大型资源时必须重写该函数,而不是定义在InitProcess函数中,因为用户随时都可能开启或关闭程序,不应该在此函数中过分耗时。

  例如空中鼠标,它需要在第一次初始化时加载SVM识别模型。用于手势识别。

 public override bool LoadMainResource(){mySVMMethod = new SVMMethod();mySVMMethod.LoadSVMModel(PublicName);return true;}

   除此之外,还有对应的释放函数。和初始化需要的注意点一致:

  

 public override bool ReleaseMainResource(){//释放所需的非托管资源}

   2. 两个辅助外部管理器

  一些管理型应用,不仅需要获取节点的数据,还需要知悉整个系统的工作状态,此时就需要获得一些扩展功能。

  系统提供在基类中提供了两个服务者,解决了以上问题:  

    public AbstractCommManager thisCommManager { get; set; }public IProgramManager thisProgramManager { get; set; }

      分别是通信管理器接口和程序管理器接口,它封装了和限制了应用对管理器的控制权限,提供了可读的一些有用信息。

  例如,在thisProgramManager的帮助下,应用可以开启或关闭另外一个应用,可以在界面上添加或删除新的UI组件,

  /// <summary>/// 应用程序管理器/// </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; }}

     与其类似的是,可以开启或关闭通信方法,或获取已开启通信方法的枚举等。

  3. 安全性

  由于系统使用和开发环境都是基于专业用户的,因此以开放的精神,API提供的接口的权限都达到甚至超过了实际应用的最大需求。在开发应用时,您应该考虑只读取数据,而不非法写入或修改核心状态数据,这可能会导致系统崩溃或出现不可预见的问题。

  4. 其他API

  XMove开发环境内置了XFrmWork的全部功能集合,同时有.NET FrameWork作为支持,您所需的大部分函数和功能类都可以在其中找到,这包括网络通信,数据库,图形UI等。您可以参考详细开发文档,此处不进行详细描述。

  5.发布

  您可以将您的工程编译为dll,提供给用户。在目前框架下,无法实现自动升级,因此需要手动拷贝。未来框架会加入自动升级功能。

七. 总结

  本文较详细的介绍了在XMove框架下开发新应用的方法和注意事项。目前XMove框架已经支持多达20多种应用,涉及节点管理,人机交互,虚拟现实等应用,我会在后续文章中继续介绍。  

  若您感兴趣,欢迎联系我  buptzym@bupt.edu.cn

  

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/266971.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

搭建服务器Apache+PHP+MySql需要注意的问题

参见https://www.cnblogs.com/bytebull/p/7927542.html 一、软件下载的都是用zip压缩文件&#xff0c;三个软件均需手动配置&#xff0c;若想省事&#xff0c;可考虑phpstudy&#xff0c;一键安装。 我的服务器文件目录&#xff1a; 二、安装PHP时需注意&#xff0c;新版本的PH…

php行为日志,利用ThinkPHP的行为扩展做系统日志

1&#xff1a;模块配置&#xff1a;return array(action_end > array(Admin\\Behaviors\\LogBehavior),);2&#xff1a;数据库建表&#xff1a;create table logs(id int(11) primary key auto_increment,url char(30) not null,operator int(11) not null,description char…

nagios搭建(一):nagios3.2的搭建

此文章的大多地方采用的是elain的博客内容&#xff1a;http://elain.blog.51cto.com/3339379/711549小部分内容是自己的从别的文章总结过来的&#xff0c;已经试验过了1.需要的软件包&#xff1a;nagios-3.2.0.tar.gz nagios的主软件包nagios-cn-3.2.0.tar.…

0530JavaScript基础2

常用内置对象 所谓内置对象就是ECMAScript提供出来的一些对象&#xff0c;我们知道对象都是有相应的属性和方法 数组Array&#xff08;部分相当于列表&#xff09; 1.数组的创建方式 var colors [red,color,yellow]; 使用构造函数&#xff08;后面会讲&#xff09;的方式创建 …

.net mvc 超过了最大请求长度 限制文件上传大小

在我们的项目中遇到"超过了最大请求长度"如下图所示,是因为IIS默认请求长度4M,当请求长度大于这个值的时候报错,下面是解决方案. 解决方案:修改web.config文件 1、注意在mvc中有两个web.config文件&#xff0c;如下图&#xff0c;一个位于Views下&#xff0c;是用来控…

分布式之缓存击穿

什么是缓存击穿 在谈论缓存击穿之前&#xff0c;我们先来回忆下从缓存中加载数据的逻辑&#xff0c;如下图所示 因此&#xff0c;如果黑客每次故意查询一个在缓存内必然不存在的数据&#xff0c;导致每次请求都要去存储层去查询&#xff0c;这样缓存就失去了意义。如果在大流量…

(转)VS2010 快捷键

之前写代码很少用到快捷键&#xff0c;感觉用鼠标也一样&#xff0c;但是还是觉得能熟练用快捷键的人很牛一样的&#xff0c;相信很多人也有我一样的想法的&#xff0c;现在我还是觉得记些快捷键还是很有必要的(或者是为了看起来更牛点吧 )&#xff0c; 所以这样转载下VS2010快…

arcgis建立拓扑分析(检验矢量图)

目的&#xff1a;矢量图画好后&#xff0c;检查是否有伪节点&#xff0c;悬挂节点等&#xff0c;线要素和面要素都可以检查。伪节点&#xff0c;两条线应该相交但是画的没相交&#xff1b;悬挂节点&#xff0c;两条线看似相交了但是没有节点&#xff0c;因此路径不同&#xff0…

oracle11g导出dmp文件 少表,Oracle11g导出dmp并导入Oracle10g的操作记录

Oracle11g导出dmp并导入Oracle10g的操作记录。操作环境说明&#xff1a;Oracle11g环境&#xff1a;Windows7&#xff0c;Oracle Database 11g Enterprise Edition Release 11.2.0.1.0&#xff0c;ZHS16GBK。Oracle10g环境&#xff1a;中标麒麟&#xff0c;Oracle Database 10g …

完整国内城市js级联选择

js代码: View Code var china [//直辖市[北京市],[上海市],[天津市],[重庆市],//华北地区[河北省,石家庄,唐山,秦皇岛,邯郸,邢台,保定,张家口,承德,沧州,廊坊,衡水],[山西省,太原,大同,阳泉,长治,晋城,朔州,晋中,运城,忻州,临汾,吕梁],[内蒙古自治区,呼和浩特,包头,乌海,赤峰…

302重定向问题

在把原有的项目迭代以后出现了访问原有域名&#xff1a; abc.dex 不能访问的情况&#xff08;注意&#xff1a;这种情况时而能访问&#xff0c;时而不能访问&#xff09; 必须访问&#xff1a;abc.dex /login.index才能登陆 下面是抓取网络状态的截图&#xff1a; SLB在做…

2017级面向对象程序设计——团队作业1

这是一股来自青青草原的神秘力量 团队信息 团队名称 青青草原战队队伍成员 阮君曦 031702116(队长)史恩泽 031702122蓝飞鹏 031702112张凌昕 031702105林鑫 031702138团队合照人物属性 阮君曦&#xff08;懒羊羊&#xff09; 风格&#xff1a; 一旦进入学习状态便一发不可收拾。…

雅礼集训 2017 Day1

T1&#xff1a;loj 6029 市场 题目大意&#xff1a; 维护一个数据结构支持区间加 区间除法 区间求最小值 区间求和 思路&#xff1a; 用线段树维护区间加 区间求最小值 区间和 对于区间除法 注意到除数d很大而加法的w很小 尝试将区间除法变成区间减法 可以转化成减法的情况就是…

多行文本框

2019独角兽企业重金招聘Python工程师标准>>> #-*- coding: UTF-8 -*- import wxclass TextFrame(wx.Frame):def __init__(self):wx.Frame.__init__(self,None,-1,u多行文本框,size(250,150))panelwx.Panel(self,-1)multiTextwx.TextCtrl(panel,-1,"Python is a…

Directx11教程(55) 建立球形和锥形物体

本教程中&#xff0c;我们新建2个model class&#xff0c;SphereModelClass以及CylinderModelClass,分别用来表示球形和锥形物体。 程序执行后的界面如下&#xff1a; 线框模式界面如下&#xff1a; 从线框模式可以看出&#xff0c;球形是由三个因素决定&#xff1a;半径、经度…

JAVA基础学习之路(十一)引用传递

引用传递&#xff1a; 不同栈内存可以指向同一块堆内存&#xff0c;不同栈内存可以对一块堆内存进行修改 范例一&#xff1a; class Message {private int num 10;public Message(int num) {this.num num;}public void setNum(int num) {this.num num;}public int getNum() …

php常见数据类型转换与判断

2019独角兽企业重金招聘Python工程师标准>>> 强制类型转换问题&#xff1a; &#xff08;array&#xff09; false > array(0>) &#xff08;array&#xff09; true > array(0>1) &#xff08;array&#xff09; null >array( ) 进行类型转…

Maven deploy部署jar到远程私服仓库

一、配置私服账号密码 修改maven配置文件&#xff0c;在$MAVEN_HOME/conf/setting.xml中增加如下配置&#xff1a; 注意&#xff0c;这里配置的id为releases何snapshots&#xff0c;当然可以改为其他&#xff0c;先记得这里有过id的配置&#xff0c;后面有用 二、配置远程发布到…

linux系统etc什么意思,etc.是什么意思 linux下的etc是什么意思

Etc是Electronic the collection的缩写&#xff0c;指电子不停车收费系统&#xff0c;是指车辆在通过收费站时通过车上安装的Etc车载系统与收费站之间微波通讯&#xff0c;进行车辆识别&#xff0c;再联合网络和银行进行自动扣费的一种新型收费模式。电子不停车收费系统(英语&a…

万里长征,始于足下——菜鸟程序员的学习总结

最近一直的谈论如何学习&#xff0c;如何做笔记&#xff0c;学习方法是否正确&#xff1f;&#xff08;发现问题——创新的原动力&#xff09;为什么开始系统化学习了&#xff0c;反而暴露许许多多的问题&#xff1f;细想也并不是很多&#xff0c;这都是过去的遗留问题&#xf…