DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
The Latest "Software Integration: The Intersection of APIs, Microservices, and Cloud-Based Systems" Trend Report
Get the report
  1. DZone
  2. Data Engineering
  3. Big Data
  4. Get Smart Things Talking with AllJoyn and Kii

Get Smart Things Talking with AllJoyn and Kii

German Viscuso user avatar by
German Viscuso
·
Sep. 11, 14 · Interview
Like (0)
Save
Tweet
Share
8.19K Views

Join the DZone community and get the full member experience.

Join For Free

Avoid lower-level network protocols and hardware in your Internet of Things projects with AllJoyn open source software.

As members of the AllSeen Alliance we’re excited about the AllJoyn™ framework for Internet of Things (IoT) projects. The de facto object-oriented approach, AllJoyn reduces development complexity by allowing for proximity peer to peer over various transports. It’s written in C++ at its core, provides multiple language bindings (such as Java, JavaScript, C#, ObjC) and supports complete implementations across various operating systems and chipsets.

Below are the steps to quickly get started with AllJoyn using JavaScript binding (in nodejs) to allow peers to exchange messages. You’ll also learn how to cloud-enable the project by logging received messages on Kii for later processing. In this tutorial we’re sending text messages but Kii can richer data such as music, photo, video, etc so you can be sending songs to smart speakers or photos to a smart TV with cloud-enabled storage and Analytics, for example.

AllJoyn framework overview

Before jumping into code, you should know a few AllJoyn basics. Any peer participating in an AllJoyn conversation must “talk” via a (relatively low level) bus. Think of it as the highway in which all AllJoyn messages travel. First your app needs to attach to the bus by creating a bus attachment. Through a bus a peer can participate in an AllJoyn conversation but it has to be done through a concrete interface. The interface is created in the bus with the purpose of handling shared objects and signals sent to the objects. In our example the peers will share a chat object in the bus and signals sent to it will be relayed to the other peers as messages.

Next you have to decide whether your app wants to join and use an existing service or advertise one for others to join. Assuming you want to advertise a service, give it a recognizable name. Other peers will try to locate your service using it. Then bind a port (e.g. 27) to create a session over the bus. The steps:

  1. Create a BusAttachment and connect to the AllJoyn framework to communicate with other AllJoyn applications
  2. Create an Interface in the Bus and define the Signals that it will handle
  3. Create a BusObject and pair it with the Interface (after starting the Bus)
  4. Define a SignalHandler for signals sent to the BusObject
  5. Register the BusObject with the Bus and connect
  6. If Advertising:
    1. Choose a unique identifier. Create a unique name
    2. Create a Session other applications can join
    3. Tell other applications you’re there by advertising the service name
  7. If Joining:
    1. Find other applications nearby by looking for a name prefix
    2. Define a BusListener to join a Session once a service name is found
    3. Join a session that has been found
  8. Communicate with other applications in your group

Don’t panic. We’ll go through the code needed to achieve all the necessary steps below.

Install and compile AllJoyn

Before taking AllJoyn for a spin let’s install it. You could download the source and compile it yourself (e.g. for a Raspberry Pi) but the easiest way is to use the npm package (thanks Octoblu!) and test the framework with the JavaScript binding (requires nodejs). Installation goes like this:

  1. Install npm and nodejs (alternative install available here)
  2. Install the AllJoyn npm package
  3. Install the node-jquery-xhr npm package (required by the Kii js SDK)
  4. Download the Kii js SDK and place on the same directory where you’ll run your scripts
  5. Test the example-host.js and example-client.js by Octublu to make sure everything works
    1. On Mac the scripts are located on /opt/local/lib/node_modules/alljoyn (if you installed globally with -g) and can be run with the node command

Advertise the chat service

Next take a look at our nodejs script. It can run in host mode to advertise a chat service for other peers to join. Or you can run it as a client, which will look for a service advertised by the host on the network by name, and then connect to it. This setup allows as many clients as you want but there must be only one host. The reason for using a single script for host and client is that 95% of the code is shared (see below).

Once connected all peers (host and clients) have the same behavior listening to and showing incoming messages, and allowing you to type messages for other peers to see. As an add-on all hosts and clients log incoming messages on the cloud with Kii for later analysis.

Initialize and authenticate with Kii

Once you created a Kii app at developer.kii.com, write down the app ID and key to initialize Kii:

require("node-jquery-xhr");
kii = require("./KiiSDK").create();

console.log("Initializing Kii Cloud...");
kii.Kii.initializeWithSite(appid, appkey, kii.KiiSite.US);

Once Kii is initialized a sign-in is attempted with the peer name and password passed via the command line. If this fails a first time registration is attempted against the Kii service:

console.log("Authenticating peer on Kii Cloud...");
// Authenticate the peer
kii.KiiUser.authenticate(uuid, password, {
  // Called on successful authentication
  success: function(peer) {
    // Print some info to the log
    console.log("KiiCloud: Peer authenticated");
    //console.log(peer);
  },
  // Called on a failed authentication
  failure: function(peer, errorString) {
    // Print some info to the log
    console.log("Error authenticating peer: " + errorString);
	console.log("Trying peer registration...");
	// Create the KiiUser object
	var user = kii.KiiUser.userWithUsername(uuid, password);
	// Register the user, defining callbacks for when the process completes
	user.register({
	  // Called on successful registration
	  success: function(peer) {
	    // Print some info to the log
	    console.log("KiiCloud: Peer registered");
	    //console.log(peer);
	  },
	  // Called on a failed registration
	  failure: function(peer, errorString) {
	    // Print some info to the log
	    console.log("Error registering peer: " + errorString);
            process.exit(2);
	  }
	});
  }
})

Note that the Kii API provides async method calls (with callbacks) in its methods, which makes control fairly easy and allows you to keep working on your script while a user signs in or registers.

Set up the AllJoyn bus

Some bus setup has to be done in any chat peer that wants to participate in a conversation using AllJoyn:

console.log("Loading alljoyn bus...");
var sessionId = 0;
var portNumber = 27;
var serviceName = "org.alljoyn.bus.samples.chat.test";
var bus = alljoyn.BusAttachment("chat");
var inter = alljoyn.InterfaceDescription();

// [...] bus listener setup goes here

console.log("CreateInterfaceInBus " + bus.createInterface(serviceName, inter));
console.log("AddingSignal " + inter.addSignal("Chat", "s",  "msg"));
console.log("Registering bus listener...");
bus.registerBusListener(busListener);

console.log("StartingBus " + bus.start());
console.log("Creating chat service object");
var chatObject = alljoyn.BusObject("/chatService");
console.log("AddInterfaceToObject " + chatObject.addInterface(inter));

// [...] signal handler setup go here

console.log("RegisterBusObject " + bus.registerBusObject(chatObject));
console.log("ConnectBus " + bus.connect());

A chat object is used as a common structure between peers to receive signals. The signal handler will interpret signals as messages.

Advertise the service on the host

After hooking up to an AllJoyn bus the host advertises the service name, combining a session, port and port listener callback:

  console.log("BusRequestName " + bus.requestName(serviceName));
  console.log("BusBindSessionPortWithPortListener " + bus.bindSessionPort(27, portListener));
  console.log("BusAdvertiseName " + bus.advertiseName(serviceName));

The host will effectively listen on port 27 for client connections and execute the port listener callback on each connection.

Find the service on the client

The client goes through an identical bus setup as the host. Instead of advertising a service it looks for one (given the same service name):

  console.log("BusFindAdvertisedName " + bus.findAdvertisedName(serviceName));

For the client the bus listener callback is key because it defines what to do when a service name is found. In this case, when the service is found, we tell the client to join a session with the host:

var busListener = alljoyn.BusListener(
  function(name){
    console.log("BusListener: FoundAdvertisedBusName", name);
    sessionId = bus.joinSession(name, portNumber, 0);
    console.log("BusListener: JoinedSession " + sessionId);
  },
  function(name){
    console.log("BusListener: LostAdvertisedBusName", name);
  },
  function(name){
    console.log("BusListener: BusNameOwnerChanged", name);
  }
);

Send, receive and log messages

Sending and receiving messages is done the same way for host and client. First a shared bus object is created on the bus and each peer subscribes to signals sent to it via a signal handler.

figure-10

In order to send messages the peer takes input from stdin and then sends a signal to the shared chat object:

var stdin = process.stdin;
// resume stdin in the parent process (node app won't quit all by itself
// unless an error or process.exit() happens)
stdin.resume();
// avoid binary
stdin.setEncoding( 'utf8' );
// on any data into stdin
stdin.on( 'data', function( key ){
  // ctrl-c ( end of text )
  if ( key === '\u0003' ) {
    process.exit();
  }
  // write the key to stdout all normal like
  process.stdout.write( ":me " + key);
  chatObject.signal(null, sessionId, inter, "Chat", key.replace(/(\r\n|\n|\r)/gm,""));
});

In order to receive a message each peer has a signal handler that interprets the signal as an incoming message, sends it to the console and does the logging on Kii:

console.log("RegisterSignalHandler " + bus.registerSignalHandler(chatObject, function(msg, info){
  // console.log("Signal received: ", msg, info);
  console.log(info["sender"], msg["0"]);
  //log received message on Kii Cloud
  //create an application scope bucket
  var appBucket = kii.Kii.bucketWithName(bucketName);
  // Create the object with key/value pairs
  var obj = appBucket.createObject();
  obj.set("message", msg["0"]);
  obj.set("sender", info["sender"]);
  obj.set("session_id", info["session_id"]);
  obj.set("timestamp", info["timestamp"]);
  obj.set("member_name", info["member_name"]);
  obj.set("object_path", info["object_path"]);
  obj.set("signature", info["signature"]);
  // Save the object
  obj.save({
    success: function(obj) {
      //console.log("Msg logged");
      //console.log(obj);
    },
    failure: function(obj, errorString) {
      console.log("Error logging msg: " + errorString);
    }
  });
}, inter, "Chat"));

Please note: In order to store Kii data you’ll need to create a KiiObject from an application scope bucket and set all the details of the incoming message as in a key/value store. After that you can save the object on Kii with an async call and use the Kii Data Browser available on developer.kii.com to see stored messages:

AllJoyn stored messages

That’s about it. Keep in mind that peers interpret messages as text to display on screen but these exchanged messages could be more complex structures, commands, etc. suitable for all kinds of IoT scenarios. Even binary formats could be exchanged and saved on Kii as files.And of course, besides storing data on Kii Cloud you can retrieve it via a powerful query system as easily.

Wrap up

Getting started with AllJoyn is easy thanks to the npm package with js binding. Since Kii provides JavaScript SDK integration with the binding, you can have an AllJoyn enabled chat service with cloud logging up and running in no time. Keep in mind that peers could easily be IoT devices interpreting the messages as commands to do something meaningful or exchanging richer data such as streaming music (more on that coming to the Kii Blog soon).

Full source code for both the host and client can be found here. Usage is straightforward:

> node peer.js [MODE] [YOUR_APP_ID] [YOUR_APP_KEY] [USERNAME] [PASSWORD]

MODE is either “host” or “client”. Run in host mode first, then open another shell and run the client mode (if you get errors about the address being in use try from another machine on the network since the embedded AllJoyn daemon is then using the same address). Note that you should run only one host but can have as many clients as you want. The parameters YOUR_APP_ID and YOUR_APP_KEY can be obtained by creating an app at developer.kii.com. And you can freely set your username and password, which will be created the first time if credentials don’t exist on Kii. We recommend using a different username for each running script (otherwise all scripts no matter if they are hosts or clients will do the logging as the same Kii user).

Happy coding :)

Host (Unix) IoT Signal application app Joins (concurrency library) Object (computer science) Session (web analytics) Open source

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Configure Kubernetes Health Checks
  • Demystifying the Infrastructure as Code Landscape
  • Java Concurrency: LockSupport
  • Java REST API Frameworks

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: