在之前的文档中,我们都是从单个设备的角度进行介绍,但在实际业务中,不同设备间存在交互行为。我们经常需要在一个设备的生命周期中查询另一个设备信息,或者向另一个设备进行通信。因此我们提供了设备管理模块来对不同设备进行查询与通信等交互管理。

  目前设备管理模块提供了如下接口:

bool hasNode(uint id);

查询某个id的设备是否已经登录。

bool find(uint id, InfoNodePtr& infoNodePtr);

查询某个id的设备节点对象信息,我们可以通过InfoNodePtr节点对象查询具体节点设备的信息,或者通过InfoNodePtr.send()接口向该设备对象发送消息。

std::vector<uint> getNodeIDs(ObjectType* objectType);

查询符合该类型的所有已登录的设备节点ID,只查询该类型,不支持该类型的派生类型的查询。

std::vector<uint> getNodeIDs(const std::string& type);
查询符合该类型的所有已登录的设备节点ID,只查询该类型,不支持该类型的派生类型的查询。

template<class Type>
std::vector<uint> getAllNodeIDs(Type objectType);

查询符合该类型,或者为该类型的派生类型的所有已登录的设备节点ID,比如灯节点类型LightType,派生了日光灯DayLightType类型,调用getAllNodeIDs(LightType)将会获得所有直接为灯节点类型的ID,和派生于灯节点,如日光灯类型的ID。

template<class Type>
std::vector<uint> getAllNodeIDs(Type* objectType);

查询符合该类型,或者为该类型的派生类型的所有已登录的设备节点ID,传入类型为该类型的指针。

  getAllNodeIDs()接口中,参数为ObjectType的派生类型对象或指针,实际只需获得具体的对象类型。因为C++的RTTI机制并不能实现:已知两个对象,判断这两个对象是否存在派生关系。而只能实现已知一个对象和一个具体类型,判断这个对象是否派生于这个具体类型(通过dynamic_cast<Type*>判断指针是否为空)。当然也可以通过反射和RTTI机制实现获取对象的具体类型,但是C++也不支持反射/(ㄒoㄒ)/~~。因此该接口的实现采用泛型的形式,必须通过参数传入具体的类型。所以我尝试实现很久的参数为字符串类型的std::vector<uint> getAllNodeIDs(const std::string& type)接口只能胎死腹中。当然RTTI肯定效率感人,但目前本学渣只会这种实现了/(ㄒoㄒ)/~~。

  我们通过建立一个MyManageType的设备类型来测试以上接口。在ObjectType的派生类中,我们通过this->getNodeManager()接口即可获得设备管理模块,并使用以上接口。

  在MyManageType类型中,我们实现onGetIDByType的消息事件,通过测试getNodeIDs来获取所有同类型的设备ID,具体实现如下:

bool MyManageType::onGetIDByType(khala::InfoNodePtr& infoNodePtr,
Json::Value& msg, khala::Timestamp time) {
//通过getNodeIDs获得所有与该设备类型相同的ID
std::vector<uint> v = this->getNodeManager()->getNodeIDs(
infoNodePtr->getNodeType());
std::stringstream ss;
ss << "Get ID By Type:Ask type:" << infoNodePtr->getNodeType()
<< " . Get ID:";
for (std::vector<uint>::iterator it = v.begin(); it != v.end(); ++it) {
ss << *it << " ";
}
infoNodePtr->send(ss.str());
return true;
}

  我们通过客户端进行测试(./example/testClient/HelloKhalaClient4.py)。我们开启两个客户端,进行login操作,并在其中一个客户端测试idByType消息事件。

  此时显示存在两个设备类型为my_manage_type的设备,id分别为(懒得抄)…

  我们实现onGetAllIDByObject的消息事件,通过测试getAllNodeIDs来获取所有派生于该类型的设备的ID,具体实现如下:

bool MyManageType::onGetAllIDByObject(khala::InfoNodePtr& infoNodePtr,
Json::Value& msg, khala::Timestamp time) {
//创建NodeType类型的对象
NodeType* tmp = new NodeType();
//传入NodeType类型,parameter is NodeType Object
std::vector<uint> v = this->getNodeManager()->getAllNodeIDs(*tmp);
std::stringstream ss;
ss << "Get All ID By Object:Ask Object type:" << tmp->getObjectTypeName()
<< " . Get ID:";
for (std::vector<uint>::iterator it = v.begin(); it != v.end(); ++it) {
ss << *it << " ";
}
infoNodePtr->send(ss.str());
//记得delete
delete tmp;
return true;
}

  同样我们在其中一个客户端测试aIdByObject消息事件。

  因为我们查询的是NodeType类型,而我们创建的MyManageType类型继承于NodeType类型,因此依旧会显示这两个my_manage_type类型的id。

  我们实现askLogin的消息事件,不同于系统默认的isLogin消息事件,askLogin通过测试hasNode来判断任意指定的id设备是否登录。

bool MyManageType::onAskLogin(khala::InfoNodePtr& infoNodePtr, Json::Value& msg,
khala::Timestamp time){
//获得指定id
uint friendId = msg[KEY_FRIEND_ID].asUInt();
std::stringstream ss;
ss<<"Node ID:"<<friendId;
//查询该id是否登录
if(this->getNodeManager()->hasNode(friendId)){
ss<<" is login!";
}else{
ss<<" is not login!";
}
infoNodePtr->send(ss.str());
return true;
}

  同样我们在其中一个客户端测试askLogin消息事件。

  我们自身的id为2075756572,因此我们查询另一个客户端的id:313508835,此时显示该id已经登录。

  最后我们实现sendMsg消息事件,通过测试find接口,并发送消息进行通信。

bool MyManageType::onSendtoNode(khala::InfoNodePtr& infoNodePtr,
Json::Value& msg, khala::Timestamp time){
//懒得输入id了,直接获取自身id
uint myId = infoNodePtr->getId();
khala::InfoNodePtr myInfoNodePtr;
if(this->getNodeManager()->find(myId, myInfoNodePtr)){
//如果自身id已登录(废话),则获取的myInfoNodePtr对象有效,通过该对象发送消息
myInfoNodePtr->send("test manager find success");
}
return true;
}

  偷个小懒,自己给自己发消息,通过客户端进行测试。

  接收消息成功。实际不同设备间进行通信,只需传入实际设备的id,在根据id调用find()接口,最后通过获取的InfoNodePtr调用send()即可,不同设备间进行通信就这么简单。

8、Khala的设备间管理+通信的更多相关文章

  1. 1、发布C++实现的TCP网络框架Khala

    1.Khala简介 Khala(卡拉)是用C++实现的TCP网络框架.底层采用muduo网络库作为网络IO+线程模型,并封装实现了网络实现与业务逻辑分离的多线程网络框架,具有超时退出.多设备多事件注册 ...

  2. Intel 80386 微处理器的存储器管理

    一.存储器的管理       存储器的管理是一种硬件机制,微处理器在总线地址上对物理存储器进行寻址.但是,为了给程序提供比物理存储器容量更大的空间,就引入了虚拟存储器的概念,它在外存(比如磁盘)的支持 ...

  3. WebRTC 系列之音频会话管理

    WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音对话或视频对话的 API.W3C 和 IETF 在2021年1月26日共同宣布 WebRTC 1. ...

  4. SPI总线通信电路设计

    数据带宽=(总线频率×数据位宽)÷8 B表示带宽,F表示存储器时钟频率,D表示存储器数据总线位数,则带宽为: B(峰值带宽)=F(时钟频率MHz)×D(总线位数bit)/8 例如,PC-100的SDR ...

  5. 服务器ipmi远程管理

    DELL iDRAC (Integrated Dell™ Remote Access Controller )是 Dell PowerEdge 系列服务器上的远程管理方案, 11代 12代服务器已经集 ...

  6. FPGA和DSP间基于SRIO的高速通信系统设计

    作者:陈婷,岳强,汪洋 解放军信息工程大学 摘要: 现代信号处理系统通常需要在不同处理器之间实现高速数据通信,SRIO协议由于高效率.低延时的特性被广泛使用.本文研究了在FPGA和DSP两种处理器之间 ...

  7. 【新阁教育】基于EtherNet/IP实现欧姆龙NX系列PLC通信

    1.引言 工业以太网协议 (Ethernet/IP) 是由ODVA所开发并得到了罗克韦尔自动化的强大支持.它使用已用于ControlNet和DeviceNet的控制和信息协议 (CIP) 为应用层协议 ...

  8. 开发一个分布式IM(即时通信)系统!

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 这知识学的,根本没有忘的快呀?! 是不是感觉很多资料,点收藏起来爽.看视频时候嗨.读 ...

  9. CPU与内存的那些事

    下面是网上看到的一些关于内存和CPU方面的一些很不错的文章. 整理如下: 转: CPU的等待有多久? 原文标题:What Your Computer Does While You Wait 原文地址: ...

随机推荐

  1. (原).cc 和 .cpp 后缀结尾的文件的区别

    This caused a few problems the first time C++ was ported to a system where case wasn't significant i ...

  2. [Search Engine] Compression in Inverted Index

    最近在学一些搜索引擎的内容,感觉挺费劲,所以就用博客当做自己的笔记,遇到一些需要整理的部分,就在这里整理一下. 今天的内容是对inverted index进行压缩.核心思想,用我自己的话来总结,就是“ ...

  3. CSS的权重(转)

    CSS写的渐渐多了,他的权重问题就不得不昂首面对,之前一直得过且过的将就用着,直到最近遇到了几个大坑,一直割刺着我对前端的热情,得了得了,蒙不过去了,就发点时间记下来吧,当然还是一片转载的文章,有时候 ...

  4. BufferedInputStream实现原理分析

    原文地址:http://blog.sina.com.cn/s/blog_67f995260101huxz.html BufferedInputStream是一个带有缓冲区的输入流,通常使用它可以提高我 ...

  5. Effective Java2读书笔记-类和接口(五)

    第21条:用函数对象表示策略 这一条其实也没说啥,就是策略模式.碰到这种场景时,定义一个策略接口,然后不同策略子类实现它,主类包含这个接口的引用就可以了. 第22条:优先考虑静态成员类 嵌套类是指被定 ...

  6. BZOJ 1068 (区间DP)

    题意:字符串的压缩,f[l][r][0]代表还没M,f[l][r][1]代表有M. #include<cstdio> #include<cmath> #include<c ...

  7. Android高德地图自定义Markers的例子

    下文为各位重点介绍关于Android高德地图自定义Markers的例子,希望这篇文章能够让各位理解到Android高德地图自定义Markers的方法. 之前的博客里说了地图的嵌入和定位,今天就说说在地 ...

  8. Non-unique Elements

    Non-unique Elements You are given a non-empty list of integers (X). For this task, you should return ...

  9. Find Median from Data Stream 解答

    Question Median is the middle value in an ordered integer list. If the size of the list is even, the ...

  10. POJ-2533最长上升子序列(DP+二分)(优化版)

    Longest Ordered Subsequence Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 41944   Acc ...