In the first part of this article series we have described the main concepts of Near Field communication and how Microsoft has provided support for this technology in Windows 8. Then we have seen how to set up two Windows 8 virtual machines with a proximity driver, i.e something which allows us to simulate a tap gesture. In this second part we will learn how to use the sample proximity driver and explore the functionalities exposed by the Proximity API.
NetNfpControl: a testing tool to simulate a proximity event
As already described in the first part, we can use a sample proximity driver to simulate a tap gesture. We found the sample netnfp solution in the Windows 8 Driver Samples package. In this solution, together with the driver and the package for the driver projects, there is also a project, NetNfpControl, containing a testing tool to simulate proximity hardware.
This project creates a command-line app “NetNfpControl.exe” with three operating modes depending on the command-line parameter used.
1) NetNfpControl.exe [<remoteMachine>]
→ this operating mode allows us to specify either a remote machine name or an IpV6 address which the local machine can connect with and simulate a proximity event.
2) NetNfpControl.exe [/k]
→ in this operating mode the app registers a Ctrl-F1 hotkey at the startup. Since there is no remote machine specified, you have to run the app on both the machines you want to be in proximity. The two machines know each other by using a private share where they have written its network name in a file. Since the file lifetime is 2 seconds, you have to press CTRL-F1 more or less at the same time on both machines. The share is hardcoded, as you may see in the code snippet below. This means you have to change it and recompile it in order to use your share.
void Proximity()
{
wprintf(L"Checking For Proximate Device\n");
SYSTEMTIME sysTime = {};
GetLocalTime(&sysTime);
wchar_t szDirectory[MAX_PATH];
StringCchPrintf(szDirectory, MAX_PATH, L"\\\\scratch2\\scratch\\travm\\proxrendezvous\\%u%02u%02u-%02u",
sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour);
CreateDirectory(szDirectory, NULL);
wchar_t szLockPath[MAX_PATH];
StringCchPrintf(szLockPath, MAX_PATH, L"%s\\lock.txt", szDirectory);
HANDLE hLock = AcquireFileLock(szLockPath);
wchar_t szOtherMachine[MAX_PATH] = {};
if (hLock != INVALID_HANDLE_VALUE)
{
wprintf(L"looking for available devices in proximity.\n");
wchar_t szFindPath[MAX_PATH];
StringCchPrintf(szFindPath, MAX_PATH, L"%s\\*.available", szDirectory);
WIN32_FIND_DATA findData;
HANDLE hFind = FindFirstFile(szFindPath, &findData);
wchar_t szFilePath[MAX_PATH];
bool fClient;
if (hFind != INVALID_HANDLE_VALUE)
{
fClient = true;
wprintf(L"Proximate device found: ");
StringCchPrintf(szFilePath, MAX_PATH, L"%s\\%s", szDirectory, findData.cFileName);
HANDLE hFile = CreateFile(szFilePath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
DWORD ignore;
(void)ReadFile(hFile, szOtherMachine, sizeof(szOtherMachine) - sizeof(wchar_t), &ignore, NULL);
szOtherMachine[MAX_PATH-1] = L'\0';
CloseHandle(hFile);
}
3) NetNfpControl.exe [<remoteMachine>] [/k]
→ this operating mode allows us to simulate a near-field proximity event with the remote machine specified by pressing CTRL-F1, even if the app is in the background. The proximity is simulated for 1 second, then the app exits proximity.
Since these operating modes don’t seem to be very comfortable for my needs I slightly modified the code to allow a fourth operating mode:
4) NetNfpControl.exe [<remoteMachine>] [/k]
→ this modified operating mode allows us to simulate a near-field proximity event with the remote machine by pressing CTRL-F1, the proximity keeps on until you press CTRl-F1 again. You can re-enter proximity by pressing CTRL-F1 once again. In this way it is very easy to simulate the arrival or departure of a proximity device. The modified solution is available here
To recap, if you follow the steps in part 1 of the article you should have two VMs with Windows 8 with the proximity sample driver installed and working on both. The two VMs should be in the same network to allow communication. Having checked this, you can emulate the proximity event by launching NetNfpControl on one of the two VMs as shown below:
NetNfpControl.exe remoteVM_name /k
and press CTRL-F1 when you run your (proximity enabled) Metro app on the other VM (or both VMs if it is the case).
Building Metro apps “proximity enabled”
To enable your Metro app to use proximity classes, simply add the following capability in the Package.appxmanifest file:
and add the appropriate using directive in your code files:
using Windows.Networking.Proximity;
That’s all: you are now ready to use the Proximity API. In the next paragraphs we will learn how to use the classes in the API by simulating some of the “Tap And Do” scenarios that Microsoft described in its “Windows 8 Near Field Proximity Implementation Specification”.
Simulating Tap And Use
In the “Tap And Use” use case (see first part of the article for further details), a user running an app on his PC will be able to trigger collaboration with the same app running on another machine when the two users tap their machines.
First of all, what we need is something which notifies us when a device is in proximity. The ProximityDevice class contains all the necessary elements to accomplish that. In the code snippet below we obtain a reference to the default proximity device installed in our machine and we use that reference to create two event handlers for the device arrived and departed events.
proximityDevice = ProximityDevice.GetDefault();
if (proximityDevice != null)
{
proximityDevice.DeviceArrived += ProximityDeviceArrived;
proximityDevice.DeviceDeparted += ProximityDeviceDeparted;
WriteMessageText("Proximity device initialized.\n");
}
else
{
WriteMessageText("Failed to initialized proximity device.\n");
}
Since a machine can potentially contain more than one proximity device (i.e. 2 devices positioned on two diagonally opposite corners of a tablet) there are also methods to enumerate the devices but it is not our case since we are using a proximity sample driver.
Now that we know how to be notified of devices in close proximity, we need to know when one of the two users initiated a tap gesture. To learn this, we can use the PeerFinder static class which exposes some useful methods and properties. First of all, let’s see which discovery options are available in our machine. The PeerFinder.SupportedDiscoveryTypes() method suits us: it can return None if we don’t have any proximity device installed, Browse if we have a WiFI-Direct enabled device, or Triggered if we have a proximity device on board. In our VM with the proximity sample driver installed this method returns the third option, Triggered. This means that we can use the PeerFinder.TriggeredConnectionStateChanged event to intercept a Tap gesture but we cannot use the PeerFinder.PeerFinder.FindAllPeersAsync() for browsing for Peers in the neighborhood.
In the code snippet below we attach the callback handler and start listening for proximate devices.
if(PeerFinder.SupportedDiscoveryTypes == PeerDiscoveryTypes.Triggered)
PeerFinder.TriggeredConnectionStateChanged += PeerFinder_TriggeredConnectionStateChanged;
PeerFinder.Start();
In the TriggeredConnectionStateChanged event handler we can check what is going on through the State property of the TriggeredConnectionStateChangedEventArgs object. This property can assume five values: PeerFound, Listening, Connecting, Completed, Failed. The image below shows the progress of a proximity connection when a tap gesture is made on one of the two devices in proximity.
When a user makes a tap gesture on one of the two devices in proximity, a first event is triggered and the state property assumes the “PeerFound” value. After this stage it is no longer necessary for the two devices to be in the proximity range since the incoming connection will be established over TCP/IP or Bluetooth. By the way, this is exactly one of the features of NFC, i.e. a technology that can act as an enabler agent for more capable wireless connections.
In the following event triggered, the State property can be “Connecting” if the tap gesture occurs on your device or “Listening” otherwise. The final event indicates us whether the connection was established or not. If it is, then we can get a reference to a StreamSocket object to communicate with the other device.
That’s all: our app can be a game (for instance, a battleship game) , a chat or whatsoever that requires exchange of information between the two devices. With a StreamSocket we can manage this kind of requirements.
Returning to the title of this section, how can we simulate the scenario above using the two virtual machines we have configured in the first part of the article?
I prepared an application skeleton which I called “Tap And Do”: it collects four Tap And Do use cases as shown in the image below:
You can find the source code here.
Follow the steps below to simulate this scenario:
1. Run the virtual Machines. For simplicity, let’s suppose that their network name is VM1 and VM2.
2. Build the NetNfpControl app using the source code modified as described in the previous section and launch it on one of the two VM, for instance VM1 using the following command-line parameters:
NetNfpControl.exe /k VM2
3. Open the Tap And Do solution on both VMs, compile and launch the app
4. Click on “Tap And Use” title on both VM, the apps are ready to communicate
5. Press CTRL-F1 on VM1 (remember this is a hotkey registered by NetNfpControl) to simulate a tap gesture from VM2
6. If it is all OK, you should see an output similar to the two below for VM1 and VM2:
The log in yellow is particularly interesting because it reveals the temporal sequence of the events. First, the local proximity device is initialized, then the simulated tap gesture is caught by the “device arrived” event handler. In this handler we launch PeerFinder.Start() as we have seen in the previous paragraph. The TriggeredConnectionStateChanged event is then triggered twice, one for “PeerFound” and one for “Listening” or “connecting” depending on which device initiated the gesture. At this stage it is interesting to notice that I pressed CTRL-F1 again to exit proximity and this happened before the connection was fully established. This did not hinder the completion of the connection on both devices, because as we have already seen, after the “PeerFound” message the connection is performed over TCP/IP (or Bluetooth).
Simulating Tap And Launch
In the “Tap And Launch” use case (see first part of the article for further details), the user running an app can invite another user to run the same app by tapping his PC to another device. The second user will be invited to launch the same app.
This use case is simpler to simulate than the previous one. The steps are the same as above except for step 4 where you have to start the TapAndDo app just in one of the two VMs. If you do so and PRESS CTRL-F1, you should see an invitation popup asking you to start the TapAndDo app as appears below:
If you look at the log in yellow on VM1 you notice the “Device arrived” event and then the “PeerFound” and “Listening” states of the TriggeredConnectionStateChanged event. If at this stage you press CTRL-F1 again to exit proximity, you will notice that the connection will not be lost until either a timeout is reached or the user of VM2 clicks on the invitation to launch the app.
When the app in VM2 starts, it receives a TriggeredConnectionStateChanged event with a reference to the socket created by the app in VM1. At this stage the two VMs are connected and can start the information exchange. In the yellow log of the image below you can see some details of the streamsocket created on both VMs.
Simulating Tap And Acquire
Tap And Acquire use case regards the case where one user invites a friend to start the same app, but his friend does not have the app installed and he is invited to acquire the app (maybe from the Windows Store). Simulating this is fairly simple with the tools described in the previous paragraphs, therefore it is left to the reader as a challenge (see the dedicated box below).
Simulating Tap And Share and Tap And Receive
Tap and Share describes the case when a user taps his device to another device to share content such as the URL of a webpage or a document. Tap And Receive is similar: in this case the user taps his device to another device (such as a PC or phone) or object (such as a tag) to receive its shared content upon user confirmation. In both cases the communication is established by using a publish/subscribe model. When an app publishes a message, it is put at the disposal of other apps in other devices. When these devices enter proximity, they can subscribe to that message and receive it. Both the publisher and the subscriber have to use the same message type. The ProximityDevice class exposes some methods to use this model such as PublishMessage(..) and SubscribeForMessage(...).
Simulating these scenarios is left to the reader as a challenge (see the dedicated box below).
Conclusion
In this second part of the “Windows Near Field Communication in Windows 8” we have learned how to use the proximity sample driver described in part one and we have simulated some scenarios included in the “Tap And Do” Microsoft interpretation.
Want to test your understanding of this article? Walter Ferrari challenges you to prove you got it all right! Take the two challenges below:
|
Establish a proximity connection
between virtual machines
|
|
|
Simulate a "Tap and Share"
scenario
|
Challenges powered by
|