Have you wanted to know where your cellular connected project is in the worldat any given time? Now you can!
In the same way that a Wi-Fi device can find itself by looking up access points, you can find your cellular device by getting the ID of the cell tower you’re connected to, and looking up the location of that cell tower. This will give you an estimate of your location based on the quality of the tower info, and the area that it supports.
This is a much less complex approach than Trilateration. If we scanned for nearby towers, we could send that information via the same hook (with some small changes). The cellular radio module on the Electron also supports a built-in trilateration feature called CELL LOCATE, but it’s hard to see how much data that sends, or who it’s making the request to, and it’s not always super accurate, so I wanted a manual approach for this demo. For completeness I’ll include the cell locate firmware as well in the project repository.
We’re going to demonstrate how to ask your Electron for it’s current tower, and how to create a webhook to hit a Browser Location API endpoint to get your current location! There are lots of ways to find out where your cell tower is too if you don’t want to hit a Browser Location API.
Ready? Lets go!
You can jump ahead to the source file here, but lets go through it piece by piece:
79: Serial.println("requesting cell tower info...");
80: Cellular.command(_cbCELLINFO, &ourTowerInfo, 15000, "AT+UCELLINFO=1\r\n");
This code sends the command “AT+UCELLINFO=1” to the cellular module. We’re giving it 15 seconds (15000 ms) to respond, and as we get replies we want our callback function _cbCELLINFO to be called.
We need to check the messages passed into the callback since we’ll be hearing other messages coming back from the module and not just our response. We can do that using sscanf to only parse the message if its a good match. sscanf returns a count of how many parameters it managed to fill out.
That looks something like this:
183: int count = sscanf(buf, "\r\n+UCELLINFO: %d, %d, %d, %d, %x, %x, %d, %d, %d, %d\r\n",
...
199:
200: if ( count <= 0 ) {
return WAIT;
}
Now, behind the scenes, we need to keep reminding the firmware that we’re waiting on a response. We can accomplish that by periodically prompting for more responses.
68: Cellular.command(_cbCELLINFO, &ourTowerInfo, 1000, "");
Once we get the cell tower information from the module, we can publish that data to the cloud, where the webhook will transform it into a secure web request to get the location. We’ll encode our data in JSON, so we can parse it back out in the webhook.
99: Serial.println("Publishing data so the hook can hit the browser location API");
100: String json = String::format("{\"id\":\"%d\",\"lac\":\"%d\",\"mcc\":\"%d\",\"mnc\":\"%d\"}",
101: towerInfo->cellId,
102: towerInfo->locationAreaCode,
103: towerInfo->mobileCountryCode,
104: towerInfo->mobileNetworkCode
105: );
106:
107: Particle.publish("get_location", json, PRIVATE);
You can find a template for the cellular location hook here. Make sure you get an API key, and update the hook url with your key where it says YOUR_KEY_HERE. Those JSON properties we set (id, lac, mcc, mnc), we can break them back out in our hook for our request.
8: "cellTowers": [{
9: "cellId": "{{id}}",
10: "locationAreaCode": "{{lac}}",
11: "mobileCountryCode": "{{mcc}}",
12: "mobileNetworkCode": "{{mnc}}"
13: }]
You can create the webhook by filling out the integrations form in the Particle Console, or you can edit the file in place and create it using the Particle CLI
particle webhook create google_locate.json
If you prefer point-and-click interfaces, open the console here, and paste in the values like this:
Now that we have our webhook, lets flash the firmware to your device! You can paste it into the Web IDE and flash from there, but I like the command line.
cd cellular-geolocation-demo/tree/master/firmware/single-tower/singleFile
particle compile electron . --saveTo firmware.bin
particle flash your_device_name firmware.bin
If you watch your events in the console, you should see something like this when it’s all working:
And if you’re watching the serial output (CLI: particle serial monitor), you should see something like this:
Current Cell Tower Information:
Tower ID:91957100
Location Area Code:32527
Mobile Country Code:320
Mobile Network Code:420
Publishing data so the hook can hit the browser location API
got location back 25.0000,-71.0000,924
Parsed into 25.0000, -71.0000, 924.000000
You're on a map! https://www.google.com/maps/place/25.0000,-75.0000
Go forth and locate your cellular projects!