This blog outlines the REST and JSON code used in the SysInfo Universal App that mimics the Web Portal to Windows 10 IoT devices. This portal is a web service running on the devices that permits examination of the aspects of a currently running system.
Project on GitHub: https://github.com/djaus2/IoTSysInfo
Original blog post on the app: Win 10-IoT: SysInfo: A Windows Universal App to get system info (as per the web portal)
Development Requirements: Windows 10, Visual Studio 2015 RTM, Windows 10 IoT device (eg Raspberry Pi 2)
The basis of this app (wrt REST and the Web Portal API) came for a blog by Bruce Eitman:
Windows 10 IoT Core: Getting the MAC Address from Raspberry Pi.
In the code blocks that follow, only an outline is shown. Inspect the actual project code to see the full implementation.
For an understanding of JSON visit http://json.org
A JSON object is a name-value pair. The value can be a simple type, an object or an array of values (which can be a simple type, an object or an array …
An array is an ordered collection of values.
A value can be a string in double quotes, or a number, or true or false or null, or an object or an array. These structures can be nested.
A REST call will return the JSON data as a textual string which can be parsed into .NET JSON class objects.
{"DeviceModel" : "Raspberry Pi 2 Model B", "DeviceName" : "minwinpc", "OSVersion" : "10.0.10240"}
Displays as:
The REST calls use a URL made up of the target name or IPAddress, the port (8080) and an API path:
These API paths are of the form /api/Service/Info. There are determined by examining the JavaScript files that the various web port tab pages use.
The following are the APIs used in the app.
IpConfig
/api/networking/ipconfig
SysInfo
/api/iot/deviceinformation
OSAPI
/api/os/info
Devices
/api/devicemanager/devices
Processes
/api/resourcemanager/processes
DefaulApp
/api/iot/appx/getdefault
Providers
/api/etw/providers
The method GetJsonStreamData takes one of these truncates URLs and generates the REST call to the IoT device’s portal web service:
private static async Task<StreamReader> GetJsonStreamData(String URL) { //Form full REST url by joining Device(name or IPAddress) + :Port + URL string url = "http://" + Device + ":" + Port +"/"+ URL; try { //Set up REST call with the URL and Credentials (wrGetURL) //Make the REST call and await the response HttpWebResponse Response = (HttpWebResponse)(await wrGETURL.GetResponseAsync()); if (Response.StatusCode == HttpStatusCode.OK) { //If OK then get reader to return: //Get the response stream from the response //Get the reader from the response stream } } catch() { } //return the reader }
Outline of the REST call function
Call the REST method GetJsonStreamData () (as above) with the command’s truncated URL.(Call GetJsonStreamData() )
Read the response stream as text..
Turn into a JSON object.
Parse the JSON object for Name-Value Pairs etc (Call GetNameValues() )
public async static Task<bool> DoQuery(string url) { //Clear the list //Do REST call for the command (as per the URL) StreamReader SR = await GetJsonStreamData(url); if (SR==null) { return false; } //Process the JSON stream data JsonObject ResultData = null; try { String JSONData; //Get the complete stream as text. //Convert to JSON object //Call GetNameValues() to recursively process the JSON data } catch (Exception ex) { return false; } return true; }
Outline of the Query function.
Recursively get all name-value pairs in the object:
public static void GetNameValues(JsonObject oJson) { foreach (Name-Vakue-Pair in oJson) { //Get name-value-pair type as string if (typ == "object") { //Recursively call this function with this name-value } else if (typ == "array") { //Turn into array of JSON objects (ja) //foreach JSON object in array (actually use indexed for loop) for(uint index = 0; index < ja.Count; index++) { //Recursively call this function with each name-value in the array } } else { //Got a value to add to list NameValue nv = new NameValue(oJson_KVP); //Note: The NameValue constructor automatically adds new instances to the list } } }
Outline of the JSON parsing function
Some aspects of code outlines above were simplifications. See the actual project code for details.
In the latest version of the app, JSON file for the commands, commands.json now contains two sets of commands that can be switched between. This occurs when you select and deselect the latest version of the OS. It was simple to implement this. When converting the JSON string to a JSON object, you get a named array. The two sets of commands have a different name: { "Commands": [ ... ... ], "CommandsV2": [ { "command": "localhost", "url": "", "id": "", "icon": "OneBar" }, ... ... }