AllJoyn核心应用教程【第二章】:代码结构与设备信息编写

上一篇文章中我使用了几个基本的例子来解释了AllJoyn框架中各个模块的功能。本文我将从代码层面解释如何从零开始搭建一个AllJoyn核心应用

本文中所有的代码都可以从Git中自行下载:代码链接

AllJoyn应用的整体框架

本文所使用的应用可以被切分成三个模块, 从而更好地帮助我们理解AllJoyn框架:

主程序应用代码 - Main主要功能:

  • 处理命令行输入并输出
  • 在代码中创建并放置调用函数, 管理AllJoyn中API的互相通讯

AllJoyn API代码 - MyAllJoynCode主要功能:

  • 表示如何启动AllJoyn框架
  • 为服务层的广播与发现服务使用About Feature属性
  • 为应用绑定一个Session并追踪主机的SessionId值
  • 使用Session的Id来跟踪使用者
  • 通过MyFirstBusObject与其他AllJoyn实体进行互相沟通

总线对象的实现 - MyFirstBusObject主要功能:

  • 创建并实现一个AllJoyn接口
  • 表示如何发送一个总线方法并获得反馈
  • 表示如何发送一个信号以及无会话的信号
  • 表示如何获取信号

如上所示代码不能单独运行,必须与其他两个模块共同启动才能确保应用的正常。 上面的分类只是用于更好的理解使用AllJoyn的API使用方式,从而为开发者提供便利。

模块分析

每个AllJoyn应用都应该创建一个总线附属(BusAttachment), 启动后连接到AllJoyn的路由上(AllJoyn Router)。 总线附属对象可以让应用调用AllJoyn的API, 创建方式如下所示:

mBusAttachment = new BusAttachment("MyFirstApplication", true);
/* Start the msg bus */
if (ER_OK == status) {
    status = mBusAttachment->Start();
} else {
    printf("BusAttachment::Start failed\n");
}
/* Connect to the daemon */
if (ER_OK == status) {
    status = mBusAttachment->Connect();
    if (ER_OK != status) {
        printf("BusAttachment Connect failed.\n");
    }
}

创建好了总线附属后,下一步需要确定应用的基本功能。 这一章所介绍的应用不但是客户端,同时也是服务器端,也就是说,应用是一个P2P结点。 因此为了实现连接功能,我们需要加入BindSession。

/* 将会话绑定到端口,从而接收所有的加入请求 */
SessionOpts opts(SessionOpts::TRAFFIC_MESSAGES, true, SessionOpts::PROXIMITY_ANY, TRANSPORT_ANY);
SessionPort sp = SESSION_PORT_ANY; 
status = mBusAttachment->BindSessionPort(sp, opts, *this);
if (ER_OK != status) {
    printf("无法绑定会话端口\n");
}

由于应用中使用的端口可以为任何端口,因此我们使用SESSION_PORT_ANY。 我们希望AllJoyn框架能够为应用分配端口并传递到About数据中。 与此同时, 为了能够通知其他应用我们的存在, 我们需要设置About特性

/* 设置About数据, 使应用能够广而告知 */
mAboutData = new AboutPropertyStoreImpl();
// 设置一个独一无人的ID, 比如说设备的Mac地址
// 为应用设置一个随机值, 这种方法在商业应用中也很常见
mAboutData->setDeviceId(getDeviceId());
mAboutData->setDeviceName("MyDeviceName");
// AllJoyn应用的全局辨识符 - recommend to use an online GUID generator to create
// use a random value for this application, this should persist in a comercial application
mAboutData->setAppId(getAppId());
std::vector<qcc::String> languages(1);
languages[0] = "en";
mAboutData->setSupportedLangs(languages);
mAboutData->setDefaultLang("en");
mAboutData->setAppName(appName);
mAboutData->setModelNumber("Tutorial5000");
mAboutData->setDateOfManufacture("8/15/2014");
mAboutData->setSoftwareVersion("1.0 build 1");
mAboutData->setAjSoftwareVersion(ajn::GetVersion());
mAboutData->setHardwareVersion("N/A");
mAboutData->setDescription("This is the my first AllJoyn Application!", "en");
mAboutData->setManufacturer("Company", "Me");
mAboutData->setSupportUrl("http://www.allseenalliance.org");

/* Initialize the About feature Service side */
AboutServiceApi::Init(*mBusAttachment, *mAboutData);

/* Register the port with About feature that was set when BindSession called */
status = AboutServiceApi::getInstance()->Register(sp);
/* Register the About feature with AllJoyn */
status = mBusAttachment->RegisterBusObject(*AboutServiceApi::getInstance());

接下来,应用就可以开始集合了。我们已经为其他应用的寻找与互联编写好了平台

/*设置并注册开发者的总线应用*/
/** * Here is where we add the objects we wish to expose. * A developer would modify this section to add different BusObjects. */
mMyFirstBusObject = new MyFirstBusObject(*mBusAttachment);

/* Now register the object with AllJoyn and About */
QStatus status;
status = mBusAttachment->RegisterBusObject(*mMyFirstBusObject);
if (ER_OK != status) {
    printf("Could not register the BusObject with the BusAttachment\n");
}

std::vector<qcc::String> interfaces;
for( int i = 0; i < mMyFirstBusObject->getNumberOfInterfaces(); i++) {
    interfaces.push_back(mMyFirstBusObject->getInterfaceName(i));
}
status = AboutServiceApi::getInstance()->AddObjectDescription(mMyFirstBusObject->GetPath(), interfaces);
if (ER_OK != status) {
    printf("Error returned by AddObjectDescription (%s).\n", QCC_StatusText(status));
}

BusObject与MyFirstBusObject包含了我们互相进行通讯的所有信息,并且将我们事先的所有的API集进行了开放,允许其他应用进行调用

BusAttachment在创建、启动并连接后, 连接的设置就弄好了, 设备的细节也自动设置好, 而且对象也被注册好了。 下一章我们就可以制作注册调用,从而让应用能够找到我们的first_app应用。

你可能感兴趣的:(AllJoyn核心应用教程【第二章】:代码结构与设备信息编写)