IoT Hackathon with the Intel Galileo

*Windows 10 RTM update: you can now use the Visual Studio extension for AllJoyn and Windows 10 to generate AllJoyn code from Windows 10 interfaces. Many of the steps listed in this article are no longer necessary. Please see the following blog post for more information.
AllJoyn was created to empower the Internet of Things. Because AllJoyn support is built into Windows 10, you can easily take advantage of AllJoyn to "IoT-enable" your Windows 10 apps. This article will outline the steps required to build apps for Windows 10 Public Preview using the Universal Windows Platform (UWP) AllJoyn APIs and Visual Studio 2015. Note that most of the steps outlined in this post will not be required when Windows 10 RTM is available, because Visual Studio 2015 will offer full AllJoyn integration when Windows 10 is released.
This blog post is a companion to the AllJoyn session presented at //build/ 2015 where you can learn AllJoyn fundamentals, understand how Windows 10 incorporates AllJoyn, and watch an end-to-end coding demo which will guide you through the same coding scenario outlined in this post:
Building apps for Windows 10 using UWP AllJoyn APIs involves three categories of code:
The following diagram shows the layout for an example AllJoyn UWP project:
AllJoyn-enabled UWP apps can be either Producers (implement and expose interfaces, typically a device), Consumers (call interfaces, typically apps), or both. While this article will focus on the AllJoyn Consumer scenario, the steps required to implement an AllJoyn Producer are the same for the most part. If you want to implement an AllJoyn producer UWP app, at the bottom of this post, you'll find a link to a sample project which includes code for a UWP producer app and a UWP consumer app.
Developing AllJoyn-enabled UWP apps for Windows 10 Public Preview involves the following steps: (explained in detail later in this document)
The Windows 10 Public Preview build and related tools include all of the resources that you'll need to write AllJoyn-enabled UWP apps.
Here's what you'll need to do before you get started writing code:
There are three ways that you can obtain the AllJoyn interface definitions that you will need to start your project:
You can use the getajxml command line application (included in the download attached to this post) to get introspection XML from AllJoyn devices running on your network. Running the tool without command line parameters will list all AllJoyn apps on the network.
When you run getajxml without parameters, you will see a list of all the AllJoyn devices on the network, each of the interfaces exposed by each device, and other AllJoyn metadata like the unique name, the session port, and the object path.
At //build 2015, an AllJoyn-enabled toaster device was shown which will serve as the example for this post, and the corresponding code that you can download. This toaster exposes controls for starting and stopping the toasting sequence, setting the "darkness", and notifications when toast is done.
The AllJoyn toaster hardware sample in action
The following output is obtained from the AllJoyn toaster device running on a network when you run the getajxml tool:
----------------------------------------------------------------------
Discovery : About Announcement
Manufacturer: Microsoft
Model # : 070773
Device Name : Raspberry Pi Toaster
Device ID : 41d9a124-6913-40c5-a20a-9d1b20f8121b
App Name : Toaster Producer
Bus Name Port Object Path
============================== ===== ===============================
:3yZG_wu1.2 25 /emergency
:3yZG_wu1.2 25 /info
:3yZG_wu1.2 25 /notificationDismisser
:3yZG_wu1.2 25 /notificationProducer
:3yZG_wu1.2 25 /toaster
:3yZG_wu1.2 25 /warning
...
----------------------------------------------------------------------
In this case, we're interested in obtaining the introspection XML for the toaster interface which has a unique name of ":3yZG_wu1.2", a session port value of "25", and an object path with value "/toaster".
In order to obtain the introspection XML, we pass these values to the getajxml tool as shown here:
getajxml.exe :3yZG_wu1.2 25 /toaster > toaster.xml
When the above command was run, the following was included in the XML which was output to the file:
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://standards.freedesktop.org/dbus/introspect-1.0.dtd"> <node> <interface name="com.microsoft.sample.toaster"> <method name="startToasting"> </method> <method name="stopToasting"> </method> <signal name="toastDone"> <arg name="status" type="i" direction="out"/> </signal> <property name="Darkness" type="u" access="readwrite"/> </interface> </node>
The AllJoyn code generator takes in an XML file containing one or more AllJoyn introspection interfaces and generates C++ code that implements APIs for the AllJoyn interface(s) described in the XML.
The AllJoyn code generator tool is included in the Windows 10 Public Preview build, and is located in the following directory: [Windows Kits Directory]\10\bin\x64\
Example directory: C:\Program Files (x86)\Windows Kits\10\bin\x64\
Using the AllJoyn code generator tool involves supplying two command line arguments: an input introspection XML file, and an output directory:
alljoyncodegen.exe -i <input xml file> -o <output folder>
The following example shows the AllJoyn code generator in use:
alljoyncodegen.exe -i c:\alljoyn\toaster\toaster.xml -o c:\alljoyn\toaster\toaster-uwp-component
This example assumes that the "c:\alljoyn\toaster\toaster-uwp-component" directory already exists.
After running the code generator you'll see a number of files in the output directory. For the toaster example, the following files are generated:
Once the C++ files are generated, it's then time to create a UWP Windows Runtime Component project that will contain these files.
In Visual Studio 2015, add a new "Windows Runtime Component (Windows Universal)" project to the solution containing your UWP app (You can do this easily by right clicking on the solution, then selecting Add New->Project). Once this project has been created, you will need to perform the following steps:
If you are using AllJoyn interfaces that don't share the same root namespace, you'll need to generate code for each root namespace used. The steps in this section need to be performed for each collection of code that is generated. In the end, you should have one UWP component project for each AllJoyn root namespace used by your UWP app.
At this point, you should have a Visual Studio solution that includes a UWP app project, and one or more UWP Windows Runtime Component projects. Before you embark on writing your AllJoyn consumer code, there's a few last things to take care of.
In each UWP component project, make the following updates/changes:
In the UWP app project, make the following updates/changes:
After completing these steps, build and run the UWP app project. Your builds should succeed, and the app should run. If you have build or deployment errors, investigate and fix before continuing on.
If you've navigated all of the instructions in this document and followed all of the steps correctly, you are ready to start writing AllJoyn consumer code in your app. The good news is, most of the steps outlined in this document will be replaced by AllJoyn integration in Visual Studio 2015 which will be available at the time Windows 10 is released. This means you'll be able to start writing AllJoyn consumer and/or producer code in just a few minutes.
The attached toaster sample project contains sample code for both a toaster producer (simulates a toaster device) and a toaster consumer (a toaster control app).
For a detailed walkthrough of how to create an AllJoyn consumer UWP application, please watch the AllJoyn session 623 from //build 2015:
"AllJoyn: Building Windows apps that discover, connect and interact with other devices and cloud services using AllJoyn".
We have also provided all of the code and tools that you will need to walkthrough the toaster UWP app development exercise demonstrated at //build and in this post:
Git Repo: AllJoyn Toaster Producer and Consumer Sample for Windows 10 Public Preview
In addition, here are some resources that will help you get up to speed with AllJoyn an AllJoyn support in Windows 10:
Thanks,
Gavin
Great stuff, but where can I get the getajxml.exe application?
Ken- the getajxml.exe tool is now included in the Git Repo that we linked to. Let us know if you have any issues with it.
Hi Gavin,
I'm creating a simple AllJoyn Led for excersing and I change a little the commands sequence you provided.
I didn't delete pch.cpp and pch.h from created runtime component but override them with the auto generated version (I saw in your toaster example that you have autogenerated pch.h and pch.cpp in the runtime project). However, if you try to compile ... it fails of course, becase it doesn't have all dependencies needed from step "Editing Project Settings and Dependencies".
My advice is to change in the following way :
override pch.h and pch.cpp with autogenerated
before trying to compile, the user can execute "Editing Project Settings and Dependencies" and then the build will work fine.
Does it make sense for you ?
Paolo
Thanks Paolo- my directions could have been more clear. I meant "leave the project references to pch.h and pch.cpp", but didn't directly state to overwrite the actual files with the generated ones. I've simplified the instructions now. Yes, you do want the pch.h and pch.cpp that are generated by the AllJoyn code generator.
It seems that a first compilation before copying all generated files is needed because I receive error regarding missing precompiled header pch.pch (in the Debug folder).
If I compile the runtime component just created before replacing all generated files, it works.
Another point ...
In general, when you don't have a capability in the package manifest file but use it at runtime, an exception is raised. In my example application, I forgot to set the AllJoyn capability in the consumer app but no exception is raised. The only result is that the added watcher event isn't called.
Paolo.
Thanks Paolo! We are fixing the exception issue, and I updated the steps to start with a build of the UWP component project before modifying it.
There is another main step that drove me crazy !
To use toaster on the Raspberry Pi 2, it's needed to disable the firewall on the board with :
netsh advfirewall set allprofiles state off
It's documented in the ZWave DSB guide. I didn't read the guide because I didn't need to implement a DSB bridge so I lost this mandatory step.
However, I think that it could be better to open only AllJoyn ports and not disable the firewall.
Paolo
I can't seem to get getajxml.exe to run on Windows 10 preview..I get the following message:
This version of C:\temp\getajxml.exe is not compatible with the version of Windows you're running. Check your computer's system information and then contact the software publisher.
Any Ideas?
I'm attempting to use this instead of alljoyn explorer due to issues I am encountering. Alljoyn explorer is showing two different bus objects having identical interfaces (com.microsoft.zwaveadapter.xxxx.interface_1). They therefore generate identical introspection XML. When connecting via my UWP app it is connecting to the wrong bus. I can't seem to figure out how to differentiate between the two. I'm hoping to see different XML generated by the getajxml tool.
I think that there may be an issue with current getajxml.exe and alljoyncodegen.exe, when there are interfaces with the same name under 2 different object paths.
My scenario is to write a Win UWP AllJoyn Client app that controls Aeon Lab Smart Switch via Device System Bridge. The Aeon Lab Smart Switch is used as a demo/sample codes for Device System Bridge.
The main control interface is "com.microsoft.ZWaveAdapter.HomeID25504235Node2.interface_1". However, both /Switch object path and /Enable_Wattage_Reports object path have the same interface.
Issue 1: When I use "getajxml.exe" to generate the introspection xml, the "node" does not specify which object path to use. Therefore, I got the same xaml for 2 different object paths.
Issue 2: Even when I manually add name="/Switch" to node and use "alljoyncodegen.exe", the resulting codes generated (I believe) do not consider the object path.
In auto generated AllJoynHelpers::GetObjectPath(), it only returns the first object path for that interface name. Therefore, I alwasy got /Enable_Wattage_Reports object path, not the intended /Switch object path.
Can some one shed some light about these issues?
Thanks,
Chih-fan Hsin.
Chihfan,
I am running into the exact same issue and have not been able to work around it. Please keep me updated if you find a solution.
Thanks!
Joe
Joe,
To workaround this issue, I modified the auto-generated codes at AllJoynHelpers::GetObjectPath(). You need to return multiple object paths that have the same interfaces. Then you need to loop through them, and get the object path you want, and return that object path.
Currently, the auto-generated codes only return the 1st object path with a matching interface. I also reported this issue at https://github.com/MS-brock/AllJoynToasterDemo/issues/1 .
Chih-fan