Purpose

The purpose of these functions is to help developers locate IoT, M2M and other connected devices anywhere in the world without GPS. 


How it Works

With the help of Unwired Labs' Location API, your Foundry Object first sends data about which Cellular networks and WiFi networks it can see nearby to Unwired Labs' API. The API then uses Unwired Labs’ large datasets of Cell towers, WiFi networks backed by numerous algorithms to calculate and return the device’s location. You can also use the API to search for an address using search queries and Longitude and Latitude.


The Unwired API 

 This service uses two main features of Unwired's API. The Geolocation feature, which helps developers locate IoT, M2M and other connected devices anywhere in the world without GPS and the Geocoding feature, which is used to convert back and forth from addresses to Longitude and Latitude. To use these services you will have to create an account and get an API token at https://unwiredlabs.com/trial. For more information of these services check out their API documentation at Unwired Labs API Documentation.


Lambda Function Code

There are two zip files that include the code for two Lambda functions that can be uploaded to AWS's Lambda service with the Runtime as Python 2.7 and the existing role ThingLogixFoundry-lambdaFunctionRole. The get-geolocation.zip file is used for the Geolocation feature of Unwired's API and the geocoding.zip file is used for the Geocoding feature of the API.


Creating Device Type in Foundry

Attached is the setup_object_type.py file is some python code you can use to automatically create the Foundry Object used for interacting with the API. To use this file create a new Lambda function with the Runtime as Python 2.7 and the existing role ThingLogixFoundry-lambdaFunctionRole. With the given code and add a test case with a key/value pair of 'account_id' as the key and your Foundry accountId as the value. Run the test and you will now have the Object type Unwired Device.



Foundry Object Fields Explained:

- Accuracy (Integer): The accuracy of the position is returned in meters.

- Address (String: The physical address of the location.

- Address Flag (Integer): Pass a value of 1 (default) to return address, 2 to return address components - street, city, postcode, etc - separately and 0 to suppress it.

- Balance (Integer): This represents the remaining balance on the API token.

- BT (Integer): Specify the level of strictness to apply to Borders. Use 0 for locations inside land parcels, 1 for locations that land in the range of up to 5 KM, 2 for locations that land in the range of up to 15 KM.

- Cells (String): An array of cell ID objects. Use Cell Field Info for more information.

- Country (String): Country where the device is located.

- Country Code (String): The Country Code where the device is located. Ex US.

- County (String): The county where the device is located.

- IP (String): IP address of the device. 

- Lat (String): The Latitude where the device is located.

- Long (String): The Country Code where the device is located.

- MCC (Integer): Mobile Country Code of your operator’s network represented by an integer.

- MNC (Integer): Mobile Network Code of your operator’s network represented by an integer.

- Postal Code (String): The Postal Code where the device is located.

- Query (String): Query string used for Forward Geocoding.

- Radio (String): Radio type of the device. Supported values are ‘gsm’, ‘cdma’, ‘umts’ and ‘lte’.

- State (String): The State where the device is located.

- Token (String): Your API token you received after signing up for Unwired's API

- Wifi (String):  An array of WiFi objects visible to the device. For more information use Wifi Field Info


Global Actions

There are three Foundry Global Actions which will help you run all the necessary actions associated with the Unwired API. To create a Global Action use the New Object button in your Foundry assets page and when selecting Object Template use, 'Global Action'. Each Global action will have four attributes; Name which can be anything of your choosing, Action Type which is Lambda Function, Lambda ARN which can be found in the top right of the Lambda functions you previously created, and a Payload which is what Foundry sends to the Lambda function.

Geolocation:

Lambda ARN: Use the ARN from your geolocation function.

Payload: {"deviceId": "[deviceId]", "address_flag": [address_flag], "token": "[token]", "radio":"[radio]", "mcc":[mcc], "mnc":[mnc], "cells": "[cells]", "wifi": "[wifi]"}

Forward Geocoding:

Lambda ARN: Use the ARN from your geocoding function.

Payload: {"deviceId": "[deviceId]", "q": "[query]", "token": "[token]", "limit": "5", "forward_geocoding": 1}

Reverse Geocoding:

Lambda ARN: Use the ARN from your geocoding function.

Payload: {"deviceId": "[deviceId]", "token": "[token]", "lon": "[long]", "reverse_geocoding": 1, "lat": "[lat]"}


Setting up Foundry Objects

Now that you have created an Unwired account, Uploaded the Lambda functions to AWS, created the Foundry device type, and created the global actions. You can begin creating Foundry objects and using the different API features.

Geolocation:

To use the Geolocation API first, the device must collect data about which Cellular and WiFi networks it can see nearby. For more info about the different fields use Geolocation API Documentation.

The only fields that are required when using the Geolocation API are your token and data of at least one Cellular or Wifi network nearby. However, the more information that is added the more likely the API will return an address and the more accurate the address will be. Putting the address_flag as 2 returns more detailed information about the address. 

Example Foundry object and the API's response:

Foundry Object before running Global Action:

{
    "token": "[API token]"
    "cells": "[{'lac': 7033,'cid': 17811}]",
    "wifi": "[{'bssid': '00:17:c5:cd:ca:aa','channel': 11,'frequency': 2412,'signal': -51},{'bssid': 'd8:97:ba:c2:f0:5a'}]",
    "address": 1
}

Foundry Object after Running Global Action:

{
    "token": "[API token]"
    "cells": "[{'lac': 7033,'cid': 17811}]",
    "wifi": "[{'bssid': '00:17:c5:cd:ca:aa','channel': 11,'frequency': 2412,'signal': -51},{'bssid': 'd8:97:ba:c2:f0:5a'}]",
    "address": 1
    "balance": 94,
    "lat": 39.56764858,
    "lon": -105.00733121,
    "accuracy": 10,
    "address": "High Line Canal Trail, Littleton, Douglas County, Colorado, 80129, United States of America"
}


Forward Geocoding:

Forward Geocoding is when you need to convert addresses (like a street address) into geographic coordinates (like latitude and longitude). For more info use Unwired Forward Geocoding. With the Global Action Payload we have provided the search will return a maximum of 5 results which will be represented in the fields as an array formatted as a string.

The required fields for this are your API token and an address you want to search for.

Example Foundry object and the API's response:

Foundry Object before running Global Action:

{
    "token": "[API TOKEN]",
    "query": "Statue of Liberty"
}

Foundry Object after Running Global Action:

{
    "token": "[API TOKEN]",
    "query": "Statue of Liberty",
    "long": "[-74.0445405280149,2.3331506,-86.3111795,73.0873796985722,-1.1436219]",
    "lat": "[40.6892474,48.8463756,41.3438945,33.5014307,52.6257841]",
    "country_code": "[us,fr,us,pk,gb]",
    "country": "[United States of America,France,United States of America,Pakistan,United Kingdom]",
    "county": "[New York County,Paris,Marshall County,Rāwalpindi District,City of Leicester]",
    "city": "[New York City,Paris,Plymouth,Rawalpindi,Leicester]",
    "postal_code": "[10004,75006,46563,NA,LE2 7DZ]"
}


Reverse Geocoding:

Reverse geocoding is the process of converting geographic coordinates into a human-readable address. For more info use Unwired Reverse Geocoding

The required fields for using this API are your API token, longitude, and latitude. 

Example Foundry object and the API's response:

Foundry Object before running Global Action:

{
    "token": "[API TOKEN]",
    "long": "-122.416236",
    "lat": "37.793112",
    "address_flag": 1
}

Foundry Object after Running Global Action:

{
    "token": "[API TOKEN]",
    "long": "-122.416236",
    "lat": "37.793112",
    "address_flag": 1,
    "city": "San Francisco",
    "county": "San Francisco City and County",
    "country_code": "us",
    "country": "United States of America",
    "postal_code": "94114"

}



Invoking Global Action and Hitting API

The best way to invoke global actions for Foundry Objects would be to either set up a formula field in the newly created device type to initiate one of the global actions when objects are created, see Formula Fields Info, or invoke them manually in the advanced search manager, see Invoke Global Action Manually.