您的位置:首页 > 运维架构

智能家居通用管理平台(九) – 监控程序的设计

2014-08-13 18:56 309 查看

智能家居监控程序SHM(SmartHomeMonitor),是真正与设备系统打交道的程序。它由服务程序SHS启动,以独立的进程运行。这也是PNP机制要求的。SHM需要动态加载设备系统的驱动程序(SHDD)来监控设备,SHDD再与“硬件设备”交互。也就是说SHM实际上由两个部分组成(监控管理线程SHMM,驱动程序SHDD);所以通信比较复杂。先理清楚通信的流程,根据不同的通信方式,有两种不同的通信结构。下图是用用串口、USB、PCI等方式直接与服务器电脑通信时的情况,所有信息都是在进程间交换数据。



如果设备系统是通过TCP/IP方式如服务器交互,则使用下图所示的有些诡异的通信方式:



为什么这样?因为设备系统运行在其他硬件系统上,无法与服务器进行直接的IPC通信。为减轻驱动程序的编写难度,我们把接收设备发来的数据,直接在SHMM中处理:首先把收到的信息转发给SHS(IPC方式),再把信息直接交给ISmartHome接口的ProcessDeviceStateData方法处理,由于ISmartHomes实现了事件响应机制,当数据有变化时,再通知SHM,否则不通知。而SHDD收到SHMM传来的通知时( json =smarthomeshareMemory.GetNotify();,ProcessNotifyData(json);
),用TCP/IP通信对象转发给设备系统:

public void ProcessNotifyData(stringJson json) //★★驱动程序处理服务器发来的指令

{

if (json == null) return;

string cmd = json.GetValume("cmd");

if (cmd == null) return;

else if (cmd == SHProtocol.DEVSTATE)

this.TCPNotifyDevice(json); //直接转发给设备系统

else if (cmd == SHProtocol.SHACTRL)

this.TCPNotifyDevice(json); //直接转发给设备系统

……

}

SHM业务类图相对简单,见下图:



只增加了一个窗口通信对象CommParameter。IPC、TCP/IP 通信对象在接口说明的类库中定义了。编写SHM程序的困难之处有两个:处理三种不同的通信方式,动态使用驱动程序。大部分时间花在通信调试上,以及编写设备驱动程序。大约花了2个月时间,开始由于自己编写驱动不熟练,来回修改接口,耽误较多时间。

这里介绍如何电台使用驱动程序。SHS启动SHM时,传递了驱动程序的文件名给SHM,所以SHM启动后,要负责加载驱动程序,获取设备系统的详细信息:设备状态信息和控制信息。

//★★动态加载智能家居程序集,事件响应机制!★★

Assembly asm = null;

ISmartHome SmartHome; //智能家居程序集接口

string classType = "";

private bool LoadAssembly(string dll) //动态加载厂家的智能家居程序集

{

string fn = Application.StartupPath + "\\" + dll + ".dll";

if (!File.Exists(fn)) return false;

try

{

if (asm == null)

asm = Assembly.LoadFrom(dll + ".dll"); //动态加载程序集

}

catch { return false; }

if (asm == null) return false;

classType = System.IO.Path.GetFileNameWithoutExtension(dll) + ".SmartHome"; //类名:EagleSmartHome.SmartHome

Type smarthome = asm.GetType(classType); //获取指定对象类型

if (smarthome == null) Application.Exit(); //连接库不是合法驱动

object obj = Activator.CreateInstance(smarthome, new object[] { AppDataDir + "\\SmartHome.smh" }); //创建SH对象,构造函数有两个参数

SmartHome = (ISmartHome)obj;

SetDeviceEvent(); //★★设置设备开始工作,并且设置每个设备的数据变化响应事件

ShowDevices(); //显示所有设备

return true;

}

可以看到,关键之处在Activator.CreateInstance方法,创建了一个对象,正是该对象实现了ISmartHome接口,拿到了该接口,什么都知道了。事件响应机制,在该对象中实现了,但没有编写具体处理代码,这里编写一个通用的处理方法SetDeviceEvent:

private void SetDeviceEvent() //★★★设置每个设备的数据变化响应事件

{

if (SmartHome != null)

{ //★★★初始化通信,不调用IninComm接口方法,驱动程序不开始工作工作,只有内存数据

SmartHome.InitComm(new object[] { comm, Clients, smarthomeshareMemory2dev, smarthomechannel2dev });

tbInfo.Text = SmartHome.HomeName;

for (int n = 0; n < SmartHome.HomeDevices.Count; n++) //设置每个设备的数据变化响应事件

{

#region 设置每个设备的数据变化响应事件

for (int i = 0; i < SmartHome.HomeDevices
.DODevices.Count; i++) //每个DO子设备

{

IDeviceDO dv = (IDeviceDO)(SmartHome.HomeDevices
.DODevices[i]);

dv.OnDigitalDataChanged += DigitalDataChanged;

}

for (int i = 0; i < SmartHome.HomeDevices
.DIDevices.Count; i++) //每个DI子设备

{

IDeviceDI dv = (IDeviceDI)(SmartHome.HomeDevices
.DIDevices[i]);

dv.OnDigitalDataChanged += DigitalDataChanged;

}

for (int i = 0; i < SmartHome.HomeDevices
.AODevices.Count; i++) //每个AO子设备

{

IDeviceAO dv = (IDeviceAO)(SmartHome.HomeDevices
.AODevices[i]);

dv.OnAnalogDataChanged += AnalogDataChanged;

}

for (int i = 0; i < SmartHome.HomeDevices
.AIDevices.Count; i++) //每个AI子设备

{

IDeviceAI dv = (IDeviceAI)(SmartHome.HomeDevices
.AIDevices[i]);

dv.OnAnalogDataChanged += AnalogDataChanged;

}

for (int i = 0; i < SmartHome.HomeDevices
.SODevices.Count; i++) //每个SO子设备

{

IDeviceSO dv = (SmartHome.HomeDevices
.SODevices[i]);

dv.OnStreamDataChanged += StreamDataChanged;

}

for (int i = 0; i < SmartHome.HomeDevices
.SIDevices.Count; i++) //每个SI子设备

{

IDeviceSI dv = (SmartHome.HomeDevices
.SIDevices[i]);

dv.OnStreamDataChanged += StreamDataChanged;

}

#endregion

}

}

}

就这么简单?确是就是这样。重担都落在驱动程序的编写上了。 SHM大部分时间在处理通信事件。只是想在SHM的UI界面显示和控制设备,所以程序才稍微变得复杂了。如果没有UI界面,那确实是一个很小的程序。

下篇介绍WindowsPhone客户端程序的设计。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐