simple example of scanning wifi AP and sending to geolocation resolver on cloud

Dependencies:   mbed-http lr1110 sx12xx_hal

test Wifi geolocation with resolving using HTTP POST.

Use with mbed board with internet access and arduino form factor.
With HTTPS, the RAM requirement is minimum 128Kbytes.

and, use with radio shield for europe
or radio shield for USA
which is programmed with trx firmware from updater tool.

This project presents to user mbed STDIO serial port at 115200bps, which lets you perform wifi access point scan on LR1110 and send the resulting access point list to a geolocation provider on the cloud.

Use the project by itself to run wifi scan on the serial terminal (at 115200bps), or use with lr1110_wifi_geolocation_device to receive wifi list from remote device (over LoRa) to resolve location of that device using gelocation provider on cloud.

On serial terminal, use ? question mark to see list of commands. ws to run wifi scan, or ws p to wifi scan and resolve location with cloud provider via HTTP POST.

project setup

Edit main.h to uncomment which geolocation provider you wish to use, and get API key from them:

notice

This project is not using LoRaWAN, instead just LoRa transceiver directly to geolocation provider

Committer:
Wayne Roberts
Date:
Tue Feb 09 10:49:02 2021 -0800
Revision:
1:4a05f91c9c38
add source files

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Wayne Roberts 1:4a05f91c9c38 1 #include "main.h"
Wayne Roberts 1:4a05f91c9c38 2 #if (GEOLOCATION_PROVIDER == COMBAIN)
Wayne Roberts 1:4a05f91c9c38 3 #include "radio.h"
Wayne Roberts 1:4a05f91c9c38 4
Wayne Roberts 1:4a05f91c9c38 5 char my_copy[128];
Wayne Roberts 1:4a05f91c9c38 6
Wayne Roberts 1:4a05f91c9c38 7 const char COMBAIN_SSL_CA_PEM[] = "-----BEGIN CERTIFICATE-----\n"
Wayne Roberts 1:4a05f91c9c38 8 "MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/\n"
Wayne Roberts 1:4a05f91c9c38 9 "MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\n"
Wayne Roberts 1:4a05f91c9c38 10 "DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow\n"
Wayne Roberts 1:4a05f91c9c38 11 "PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD\n"
Wayne Roberts 1:4a05f91c9c38 12 "Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\n"
Wayne Roberts 1:4a05f91c9c38 13 "AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O\n"
Wayne Roberts 1:4a05f91c9c38 14 "rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq\n"
Wayne Roberts 1:4a05f91c9c38 15 "OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b\n"
Wayne Roberts 1:4a05f91c9c38 16 "xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw\n"
Wayne Roberts 1:4a05f91c9c38 17 "7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD\n"
Wayne Roberts 1:4a05f91c9c38 18 "aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV\n"
Wayne Roberts 1:4a05f91c9c38 19 "HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG\n"
Wayne Roberts 1:4a05f91c9c38 20 "SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69\n"
Wayne Roberts 1:4a05f91c9c38 21 "ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr\n"
Wayne Roberts 1:4a05f91c9c38 22 "AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz\n"
Wayne Roberts 1:4a05f91c9c38 23 "R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5\n"
Wayne Roberts 1:4a05f91c9c38 24 "JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo\n"
Wayne Roberts 1:4a05f91c9c38 25 "Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ\n"
Wayne Roberts 1:4a05f91c9c38 26 "-----END CERTIFICATE-----\n";
Wayne Roberts 1:4a05f91c9c38 27
Wayne Roberts 1:4a05f91c9c38 28 /* parse_json: get result sent from server */
Wayne Roberts 1:4a05f91c9c38 29 void parse_json(const char *body, float *lat, float *lng, int *accuracy)
Wayne Roberts 1:4a05f91c9c38 30 {
Wayne Roberts 1:4a05f91c9c38 31 bool in_location = false;
Wayne Roberts 1:4a05f91c9c38 32 bool get_lat = false;
Wayne Roberts 1:4a05f91c9c38 33 bool get_lng = false;
Wayne Roberts 1:4a05f91c9c38 34 bool get_accuracy = false;
Wayne Roberts 1:4a05f91c9c38 35 unsigned n;
Wayne Roberts 1:4a05f91c9c38 36 strncpy(my_copy, body, sizeof(my_copy));
Wayne Roberts 1:4a05f91c9c38 37 strtok(my_copy, "\"");
Wayne Roberts 1:4a05f91c9c38 38 for (n = 0; n < 10; n++) {
Wayne Roberts 1:4a05f91c9c38 39 char *t = strtok(NULL, "\":");
Wayne Roberts 1:4a05f91c9c38 40 if (!t)
Wayne Roberts 1:4a05f91c9c38 41 break;
Wayne Roberts 1:4a05f91c9c38 42 if (in_location) {
Wayne Roberts 1:4a05f91c9c38 43 if (get_lat) {
Wayne Roberts 1:4a05f91c9c38 44 sscanf(t, "%f", lat);
Wayne Roberts 1:4a05f91c9c38 45 get_lat = false;
Wayne Roberts 1:4a05f91c9c38 46 } else if (get_lng) {
Wayne Roberts 1:4a05f91c9c38 47 sscanf(t, "%f", lng);
Wayne Roberts 1:4a05f91c9c38 48 get_lng = false;
Wayne Roberts 1:4a05f91c9c38 49 }
Wayne Roberts 1:4a05f91c9c38 50 if (strchr(t, '}'))
Wayne Roberts 1:4a05f91c9c38 51 in_location = false;
Wayne Roberts 1:4a05f91c9c38 52 else if (strcmp(t, "lat") == 0)
Wayne Roberts 1:4a05f91c9c38 53 get_lat = true;
Wayne Roberts 1:4a05f91c9c38 54 else if (strcmp(t, "lng") == 0)
Wayne Roberts 1:4a05f91c9c38 55 get_lng = true;
Wayne Roberts 1:4a05f91c9c38 56 } else {
Wayne Roberts 1:4a05f91c9c38 57 if (get_accuracy) {
Wayne Roberts 1:4a05f91c9c38 58 sscanf(t, "%d", accuracy);
Wayne Roberts 1:4a05f91c9c38 59 get_accuracy = false;
Wayne Roberts 1:4a05f91c9c38 60 }
Wayne Roberts 1:4a05f91c9c38 61 if (strcmp(t, "location") == 0)
Wayne Roberts 1:4a05f91c9c38 62 in_location = true;
Wayne Roberts 1:4a05f91c9c38 63 else if (strcmp(t, "accuracy") == 0)
Wayne Roberts 1:4a05f91c9c38 64 get_accuracy = true;
Wayne Roberts 1:4a05f91c9c38 65 }
Wayne Roberts 1:4a05f91c9c38 66 }
Wayne Roberts 1:4a05f91c9c38 67 }
Wayne Roberts 1:4a05f91c9c38 68
Wayne Roberts 1:4a05f91c9c38 69 int post_scan_result(const char *body, float *lat, float *lng, int *accuracy)
Wayne Roberts 1:4a05f91c9c38 70 {
Wayne Roberts 1:4a05f91c9c38 71 HttpsRequest* post_req = new HttpsRequest(network, COMBAIN_SSL_CA_PEM, HTTP_POST, "https://apiv2.combain.com?key=YOUR_API_KEY");
Wayne Roberts 1:4a05f91c9c38 72
Wayne Roberts 1:4a05f91c9c38 73 post_req->set_header("Content-Type", "application/json");
Wayne Roberts 1:4a05f91c9c38 74
Wayne Roberts 1:4a05f91c9c38 75 HttpResponse* post_res = post_req->send(body, strlen(body));
Wayne Roberts 1:4a05f91c9c38 76 if (!post_res) {
Wayne Roberts 1:4a05f91c9c38 77 printf("HttpRequest failed (error code %d)\n", post_req->get_error());
Wayne Roberts 1:4a05f91c9c38 78 return -1;
Wayne Roberts 1:4a05f91c9c38 79 }
Wayne Roberts 1:4a05f91c9c38 80
Wayne Roberts 1:4a05f91c9c38 81 dump_response(post_res);
Wayne Roberts 1:4a05f91c9c38 82 parse_json(post_res->get_body_as_string().c_str(), lat, lng, accuracy);
Wayne Roberts 1:4a05f91c9c38 83 delete post_req;
Wayne Roberts 1:4a05f91c9c38 84
Wayne Roberts 1:4a05f91c9c38 85 return 0;
Wayne Roberts 1:4a05f91c9c38 86 }
Wayne Roberts 1:4a05f91c9c38 87
Wayne Roberts 1:4a05f91c9c38 88 /*
Wayne Roberts 1:4a05f91c9c38 89 * https://combain.com/api/#request-body
Wayne Roberts 1:4a05f91c9c38 90 */
Wayne Roberts 1:4a05f91c9c38 91
Wayne Roberts 1:4a05f91c9c38 92 void wifi_result_to_json(bool first, const uint8_t *result, unsigned macStart, unsigned rssi_idx)
Wayne Roberts 1:4a05f91c9c38 93 {
Wayne Roberts 1:4a05f91c9c38 94 char str[8];
Wayne Roberts 1:4a05f91c9c38 95 unsigned i;
Wayne Roberts 1:4a05f91c9c38 96
Wayne Roberts 1:4a05f91c9c38 97 if (!first)
Wayne Roberts 1:4a05f91c9c38 98 strcat(json, ","); // end previous wifiAccessPoint
Wayne Roberts 1:4a05f91c9c38 99
Wayne Roberts 1:4a05f91c9c38 100 strcat(json, "{\"macAddress\": \"");
Wayne Roberts 1:4a05f91c9c38 101 for (i = 0; i < 6; i++) {
Wayne Roberts 1:4a05f91c9c38 102 sprintf(str, "%02x", result[i + macStart]);
Wayne Roberts 1:4a05f91c9c38 103 strcat(json, str);
Wayne Roberts 1:4a05f91c9c38 104 if (i < 5)
Wayne Roberts 1:4a05f91c9c38 105 strcat(json, ":");
Wayne Roberts 1:4a05f91c9c38 106 }
Wayne Roberts 1:4a05f91c9c38 107 strcat(json, "\",\"signalStrength\": ");
Wayne Roberts 1:4a05f91c9c38 108 sprintf(str, "%d", (int8_t)result[rssi_idx]);
Wayne Roberts 1:4a05f91c9c38 109 strcat(json, str);
Wayne Roberts 1:4a05f91c9c38 110 /* TODO: combain takes channel and/or frequency of access point */
Wayne Roberts 1:4a05f91c9c38 111
Wayne Roberts 1:4a05f91c9c38 112 strcat(json, "}");
Wayne Roberts 1:4a05f91c9c38 113 }
Wayne Roberts 1:4a05f91c9c38 114
Wayne Roberts 1:4a05f91c9c38 115 void json_start()
Wayne Roberts 1:4a05f91c9c38 116 {
Wayne Roberts 1:4a05f91c9c38 117 strcpy(json, "{\"considerIp\": \"false\",");
Wayne Roberts 1:4a05f91c9c38 118 strcat(json, "\"wifiAccessPoints\": [");
Wayne Roberts 1:4a05f91c9c38 119 }
Wayne Roberts 1:4a05f91c9c38 120
Wayne Roberts 1:4a05f91c9c38 121 void json_end()
Wayne Roberts 1:4a05f91c9c38 122 {
Wayne Roberts 1:4a05f91c9c38 123 strcat(json, "]");
Wayne Roberts 1:4a05f91c9c38 124 strcat(json, "}");
Wayne Roberts 1:4a05f91c9c38 125 }
Wayne Roberts 1:4a05f91c9c38 126
Wayne Roberts 1:4a05f91c9c38 127 #endif /* GEOLOCATION_PROVIDER == COMBAIN */