8、Khala的设备间管理+通信
在之前的文档中,我们都是从单个设备的角度进行介绍,但在实际业务中,不同设备间存在交互行为。我们经常需要在一个设备的生命周期中查询另一个设备信息,或者向另一个设备进行通信。因此我们提供了设备管理模块来对不同设备进行查询与通信等交互管理。
目前设备管理模块提供了如下接口:
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、发布C++实现的TCP网络框架Khala
1.Khala简介 Khala(卡拉)是用C++实现的TCP网络框架.底层采用muduo网络库作为网络IO+线程模型,并封装实现了网络实现与业务逻辑分离的多线程网络框架,具有超时退出.多设备多事件注册 ...
- Intel 80386 微处理器的存储器管理
一.存储器的管理 存储器的管理是一种硬件机制,微处理器在总线地址上对物理存储器进行寻址.但是,为了给程序提供比物理存储器容量更大的空间,就引入了虚拟存储器的概念,它在外存(比如磁盘)的支持 ...
- WebRTC 系列之音频会话管理
WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音对话或视频对话的 API.W3C 和 IETF 在2021年1月26日共同宣布 WebRTC 1. ...
- SPI总线通信电路设计
数据带宽=(总线频率×数据位宽)÷8 B表示带宽,F表示存储器时钟频率,D表示存储器数据总线位数,则带宽为: B(峰值带宽)=F(时钟频率MHz)×D(总线位数bit)/8 例如,PC-100的SDR ...
- 服务器ipmi远程管理
DELL iDRAC (Integrated Dell™ Remote Access Controller )是 Dell PowerEdge 系列服务器上的远程管理方案, 11代 12代服务器已经集 ...
- FPGA和DSP间基于SRIO的高速通信系统设计
作者:陈婷,岳强,汪洋 解放军信息工程大学 摘要: 现代信号处理系统通常需要在不同处理器之间实现高速数据通信,SRIO协议由于高效率.低延时的特性被广泛使用.本文研究了在FPGA和DSP两种处理器之间 ...
- 【新阁教育】基于EtherNet/IP实现欧姆龙NX系列PLC通信
1.引言 工业以太网协议 (Ethernet/IP) 是由ODVA所开发并得到了罗克韦尔自动化的强大支持.它使用已用于ControlNet和DeviceNet的控制和信息协议 (CIP) 为应用层协议 ...
- 开发一个分布式IM(即时通信)系统!
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 这知识学的,根本没有忘的快呀?! 是不是感觉很多资料,点收藏起来爽.看视频时候嗨.读 ...
- CPU与内存的那些事
下面是网上看到的一些关于内存和CPU方面的一些很不错的文章. 整理如下: 转: CPU的等待有多久? 原文标题:What Your Computer Does While You Wait 原文地址: ...
随机推荐
- Linux中的常见配置文件
网络服务端口 /etc/services
- 发送trim值
发送寄存器和地址上的所有值 uart_send(0xa1); uart_send(*((char code*)0x2001)); uart_send(*((char code*)0x2002)); u ...
- web qq 获取好友列表hash算法
web qq 获取好友列表hash算法 在使用web qq的接口进行好友列表获取的时候,需要post一个参数:hash 在对其js文件进行分析之后,发现计算hash的函数位于: http://0.we ...
- Mysql学习(慕课学习笔记3)数据类型
数据类型 数据类型是指.存储过程参数.表达式和局部变量的数据特征, 它决定了数据的存储格式,代表了不同的信息类型. 整型 Tinyint 有符号位 -128到127 无符号位 0到255 ...
- EasyShortcut Easyshortcut easyShortcut 简介
关于EasyShortcut Easyshortcut easyShortcut 简介: 参考: http://chunsheng.me/EasyShortcut/
- Android 操作手机内置存储卡中的文件
场景:需要读取指定文件的内容,此文件是手动存储到手机内置存储卡中的,且手机上不存在SD卡. 对于android通过activity提供的openFileOutput和openFileInput可以直接 ...
- 转:修改类不重启tomcat 自动加载项目
可以修改类不用重启Tomcat加载整个项目(手工启动) 配置reloadable=true(自动重载) 使用Debug模式,前提是仅限于局部修改.(修改类不用重启--热加载) (rel ...
- 用VS2013+VELT进行Linux开发
快乐虾 http://blog.csdn.net/lights_joy/(QQ群:Visual EmbedLinux Tools 375515651) 欢迎转载,但请保留作者信息 1.1.1 什么是 ...
- unix c 09
IPC - 进程间通信 文件/信号/管道/共享内存/消息队列/信号量集/网络 XSI IPC (共享内存.消息队列和信号量集) 使用方式 非常的类似. 共享内存的使用步骤: 1 生 ...
- bwlabel函数的c++实现
实验中需要用到区域联通的算法,就是类似于matlab中bwlabel的函数.网上找了找c++源码未果,bwlabel-python版用python描述了matlab中的实现方法,但是最后对标签的处理部 ...