5、登录管理设备类型 + 创建新的设备类型

     登录管理设备类型的默认消息事件在khala框架中由NodeType类实现。目前默认实现了logout 、NodeId两个消息事件,这些消息事件必须登录才能获得相关消息响应,但是又与具体设备类型无关,任何已登录设备都可以获得该类型的消息响应。其中logout涉及到登录生命周期管理,为保留事件,无法对其进行重写操作。其他消息事件都可以由用户根据实际业务需求进行重写,或添加新的相应类型的事件

1、关于重写和新建登录管理设备类型的思考

     在重写和添加临时设备类型消息时,TempNodeType被MyTempNodeType继承和重写。这时之前的login、devType、isLogin等消息类型并未改变,但是由于我们新添加了time消息类型,因此不管临时设备类型还是登录设备类型,都能请求time消息类型。

 

    在之前的测试中,我们在MyTempNodeType中创建的time事件,在登录后,依旧能够被登录设备类型获取消息响应。

 

    但是在登录管理设备类型中,就不能采用类似策略来对NodeType类进行继承和重写。

    如图所示,如果我们希望给NodeType重写或者添加新的消息事件MyEvent,并创建了一个继承于NodeType的新类MyNodeType,并在该新类中实现了MyEvent消息事件。在实际业务中,我们存在三种类型的设备,分别为NewNode1、NewNode2、NewNode3,并且这3种类型都继承NodeType类型的所有消息事件。

    此时虽然我们重写了NodeType,但是从继承的角度,新创建的设备类型并不知道重写的MyNodeType存在,它们是属于NodeType继承树上的不同的分支。因此这三种设备类型只能获取原NodeType中实现的消息类型,而不能获取在新的MyNodeType中实现的MyEvent事件。

 

    正确的做法是将MyNodeType当做用户定制的继承于NodeType类型的“新的设备类型”,而非对NodeType的重写和替代。而新创建的NewNode1、NewNode2、NewNode3类型又是对MyNodeType类型的新的继承。如此NewNode1、NewNode2、NewNode3类型既能够获取MyNodeType中重写和新建的消息事件,也能获取原NodeType中未被重写的默认消息事件。

    因此,我们对于登录管理设备类型进行重写,从本质上讲,就是添加了一个新的继承于登录管理设备的设备类型。并让需要使用到这个新类型实现的消息事件的设备选择继承于这个新的设备类型。

2、创建新的设备类型

    我们可以通过创建新的设备类型来满足具体业务逻辑需求,并通过选择具体继承设备类型,构建设备类型继承树,来对不同设备层级的消息事件进行实现和管理。在此我们通过创建一个继承于NodeType的MyNodeType类型为例进行说明,MyNodeType类型将会继承NodeType实现的所有消息事件,同时自身实现MyEvent消息事件。

    首先同样必须为这个设备添加一个具体的设备名,该设备名必须唯一。同时需要为这个设备的MyEvent消息事件也添加一个具体的消息名,该消息名也必须唯一。可参考./include/khala/ParseKey.h。

//this is my msg type
#define TIME_TYPE "time"
#define MY_EVENT "myEvent"

//this is my node type
#define MY_NODE_TYPE "my_node_type"

    然后我们创建一个继承于NodeType的新类MyNodeType,此处只需属于NodeType的子类即可,并不一定要实际继承NodeType,可以通过继承实现的NodeType的子类来构造设备继承树。

    同时我们在新类中创建onMyEventMsg方法,作为MyEvent消息事件的响应实现。并在消息注册方法中对新创建的onMyEventMsg方法进行注册。

class MyNodeType: public khala::NodeType {
public:
    MyNodeType();
    virtual ~MyNodeType();
    //新创建的MyEvent消息事件
    virtual bool onMyEventMsg(khala::InfoNodePtr& infoNodePtr, Json::Value& msg,
            khala::Timestamp time){
        infoNodePtr->send("this is my new Node !");
        return true;
    }
    //消息注册方法
    virtual void setRegisterMsg(khala::RegisterHandler& handler){
        //通过调用父类的setRegisterMsg方法来获取父类注册的消息事件
        khala::NodeType::setRegisterMsg(handler);
        //注册MyEvent消息事件
        handler.setRegisterMsg(MY_EVENT,
                    boost::bind(&MyNodeType::onMyEventMsg, this, _1, _2, _3));
    }
    //设置该类型名称,必须唯一
    virtual const std::string& getObjectTypeName() {
            static std::string typeStr(MY_NODE_TYPE);
            return typeStr;
        }
};

    不同于之前的创建的MyTempNodeType,我们必须通过getObjectTypeName()接口为MyNodeType类设置一个唯一的类型名。如果该类型名与之前存在的类型名相同将会报错。

    最后在main函数中,我们通过nodeServer.addNodeType()接口向系统注册我们新创建的MyTempNodeType类。

int main() {
    InetAddress listenAddr(USER_PORT);
    NodeServer nodeServer(listenAddr);
    MyNodeType myNodeType;
    //注册新创建的设备类型
    nodeServer.addNodeType(&myNodeType);
    nodeServer.start(USER_SERVER_THREAD_NUM);
    return 0;
}
 

    通过以上步骤,我们就创建了一个继承于NodeType且注册了MyEvent消息事件的设备类型MyNodeType。

    我们可以通过客户端程序(./example/testClient/HelloKhalaClient3.py)对其进行测试。

image

    如果我们在没有登录的情况下,请求myEvent消息事件,将会返回错误的类型。我们选择以myNodeType类型进行登录后,再请求myEvent消息事件,这时我们将返回正确的消息结果。我们再请求devType,这时系统返回我们此时的设备类型为my_node_type,这正是我们通过getObjectTypeName()给MyNodeType设置的设备名!

    如果我们选择以nodeType类型登录,请求myEvent消息事件,此时依旧返回错误的消息类型。

image

 

    读者可以根据创建新的设备类型的方式,构造符合自己业务需求的设备继承树,定制不同设备所需的不同的消息事件。

posted on 2015-12-20 19:54  第五大洋  阅读(724)  评论(0编辑  收藏  举报