Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed-http lr1110 sx12xx_hal
Revision 1:4a05f91c9c38, committed 2021-02-09
- Comitter:
- Wayne Roberts
- Date:
- Tue Feb 09 10:49:02 2021 -0800
- Parent:
- 0:fd6707e25c57
- Commit message:
- add source files
Changed in this revision
diff -r fd6707e25c57 -r 4a05f91c9c38 combain.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/combain.cpp Tue Feb 09 10:49:02 2021 -0800
@@ -0,0 +1,127 @@
+#include "main.h"
+#if (GEOLOCATION_PROVIDER == COMBAIN)
+#include "radio.h"
+
+char my_copy[128];
+
+const char COMBAIN_SSL_CA_PEM[] = "-----BEGIN CERTIFICATE-----\n"
+"MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/\n"
+"MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\n"
+"DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow\n"
+"PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD\n"
+"Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\n"
+"AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O\n"
+"rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq\n"
+"OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b\n"
+"xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw\n"
+"7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD\n"
+"aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV\n"
+"HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG\n"
+"SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69\n"
+"ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr\n"
+"AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz\n"
+"R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5\n"
+"JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo\n"
+"Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ\n"
+"-----END CERTIFICATE-----\n";
+
+/* parse_json: get result sent from server */
+void parse_json(const char *body, float *lat, float *lng, int *accuracy)
+{
+ bool in_location = false;
+ bool get_lat = false;
+ bool get_lng = false;
+ bool get_accuracy = false;
+ unsigned n;
+ strncpy(my_copy, body, sizeof(my_copy));
+ strtok(my_copy, "\"");
+ for (n = 0; n < 10; n++) {
+ char *t = strtok(NULL, "\":");
+ if (!t)
+ break;
+ if (in_location) {
+ if (get_lat) {
+ sscanf(t, "%f", lat);
+ get_lat = false;
+ } else if (get_lng) {
+ sscanf(t, "%f", lng);
+ get_lng = false;
+ }
+ if (strchr(t, '}'))
+ in_location = false;
+ else if (strcmp(t, "lat") == 0)
+ get_lat = true;
+ else if (strcmp(t, "lng") == 0)
+ get_lng = true;
+ } else {
+ if (get_accuracy) {
+ sscanf(t, "%d", accuracy);
+ get_accuracy = false;
+ }
+ if (strcmp(t, "location") == 0)
+ in_location = true;
+ else if (strcmp(t, "accuracy") == 0)
+ get_accuracy = true;
+ }
+ }
+}
+
+int post_scan_result(const char *body, float *lat, float *lng, int *accuracy)
+{
+ HttpsRequest* post_req = new HttpsRequest(network, COMBAIN_SSL_CA_PEM, HTTP_POST, "https://apiv2.combain.com?key=YOUR_API_KEY");
+
+ post_req->set_header("Content-Type", "application/json");
+
+ HttpResponse* post_res = post_req->send(body, strlen(body));
+ if (!post_res) {
+ printf("HttpRequest failed (error code %d)\n", post_req->get_error());
+ return -1;
+ }
+
+ dump_response(post_res);
+ parse_json(post_res->get_body_as_string().c_str(), lat, lng, accuracy);
+ delete post_req;
+
+ return 0;
+}
+
+/*
+ * https://combain.com/api/#request-body
+ */
+
+void wifi_result_to_json(bool first, const uint8_t *result, unsigned macStart, unsigned rssi_idx)
+{
+ char str[8];
+ unsigned i;
+
+ if (!first)
+ strcat(json, ","); // end previous wifiAccessPoint
+
+ strcat(json, "{\"macAddress\": \"");
+ for (i = 0; i < 6; i++) {
+ sprintf(str, "%02x", result[i + macStart]);
+ strcat(json, str);
+ if (i < 5)
+ strcat(json, ":");
+ }
+ strcat(json, "\",\"signalStrength\": ");
+ sprintf(str, "%d", (int8_t)result[rssi_idx]);
+ strcat(json, str);
+ /* TODO: combain takes channel and/or frequency of access point */
+
+ strcat(json, "}");
+}
+
+void json_start()
+{
+ strcpy(json, "{\"considerIp\": \"false\",");
+ strcat(json, "\"wifiAccessPoints\": [");
+}
+
+void json_end()
+{
+ strcat(json, "]");
+ strcat(json, "}");
+}
+
+#endif /* GEOLOCATION_PROVIDER == COMBAIN */
diff -r fd6707e25c57 -r 4a05f91c9c38 google_geolocation.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/google_geolocation.cpp Tue Feb 09 10:49:02 2021 -0800
@@ -0,0 +1,128 @@
+#include "main.h"
+#if (GEOLOCATION_PROVIDER == GOOGLE)
+#include "radio.h"
+
+const char GOOGLE_SSL_CA_PEM[] = "-----BEGIN CERTIFICATE-----\n"
+"MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G\n"
+"A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp\n"
+"Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1\n"
+"MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG\n"
+"A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI\n"
+"hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL\n"
+"v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8\n"
+"eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq\n"
+"tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd\n"
+"C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa\n"
+"zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB\n"
+"mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH\n"
+"V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n\n"
+"bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG\n"
+"3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs\n"
+"J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO\n"
+"291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS\n"
+"ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd\n"
+"AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7\n"
+"TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==\n"
+"-----END CERTIFICATE-----\n";
+
+char my_copy[128];
+
+/* parse_json: get result sent from server */
+void parse_json(const char *body, float *lat, float *lng, int *accuracy)
+{
+ bool in_location = false;
+ bool get_lat = false;
+ bool get_lng = false;
+ bool get_accuracy = false;
+ unsigned n;
+ strncpy(my_copy, body, sizeof(my_copy));
+ strtok(my_copy, "\"");
+ for (n = 0; n < 10; n++) {
+ char *t = strtok(NULL, "\":");
+ if (!t)
+ break;
+ if (in_location) {
+ if (get_lat) {
+ sscanf(t, "%f", lat);
+ get_lat = false;
+ } else if (get_lng) {
+ sscanf(t, "%f", lng);
+ get_lng = false;
+ }
+ if (strchr(t, '}'))
+ in_location = false;
+ else if (strcmp(t, "lat") == 0)
+ get_lat = true;
+ else if (strcmp(t, "lng") == 0)
+ get_lng = true;
+ } else {
+ if (get_accuracy) {
+ sscanf(t, "%d", accuracy);
+ get_accuracy = false;
+ }
+ if (strcmp(t, "location") == 0)
+ in_location = true;
+ else if (strcmp(t, "accuracy") == 0)
+ get_accuracy = true;
+ }
+ }
+}
+
+/*
+ * https://developers.google.com/maps/documentation/geolocation/overview
+ */
+int post_scan_result(const char *body, float *lat, float *lng, int *accuracy)
+{
+ HttpsRequest* post_req = new HttpsRequest(network, GOOGLE_SSL_CA_PEM, HTTP_POST, "https://www.googleapis.com/geolocation/v1/geolocate?key=YOUR-API-KEY");
+
+ post_req->set_header("Content-Type", "application/json");
+
+ HttpResponse* post_res = post_req->send(body, strlen(body));
+ if (!post_res) {
+ printf("HttpRequest failed (error code %d)\n", post_req->get_error());
+ return -1;
+ }
+
+ dump_response(post_res);
+ parse_json(post_res->get_body_as_string().c_str(), lat, lng, accuracy);
+ delete post_req;
+
+ return 0;
+}
+
+void json_start()
+{
+ strcpy(json, "{\"considerIp\": \"false\",");
+ strcat(json, "\"wifiAccessPoints\": [");
+}
+
+void json_end()
+{
+ strcat(json, "]");
+ strcat(json, "}");
+}
+
+void wifi_result_to_json(bool first, const uint8_t *result, unsigned macStart, unsigned rssi_idx)
+{
+ char str[8];
+ unsigned i;
+
+ if (!first)
+ strcat(json, ","); // end previous wifiAccessPoint
+
+ strcat(json, "{\"macAddress\": \"");
+ for (i = 0; i < 6; i++) {
+ sprintf(str, "%02x", result[i + macStart]);
+ strcat(json, str);
+ if (i < 5)
+ strcat(json, ":");
+ }
+ strcat(json, "\",\"signalStrength\": ");
+ sprintf(str, "%d", (int8_t)result[rssi_idx]);
+ strcat(json, str);
+ strcat(json, ",\"signalToNoiseRatio\": 0");
+
+ strcat(json, "}");
+}
+
+#endif /* GEOLOCATION_PROVIDER == GOOGLE */
diff -r fd6707e25c57 -r 4a05f91c9c38 main.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp Tue Feb 09 10:49:02 2021 -0800
@@ -0,0 +1,555 @@
+#include "main.h"
+#include "network-helper.h"
+#include "radio.h"
+
+#define TX_DBM 20
+#define BW_KHZ 500
+#define SPREADING_FACTOR 11
+#define CF_HZ 919000000
+
+/* geolocation provider wont operate with less than 3 wifi access points */
+#define MINIMUM_REQUIRED_ACCESS_POINTS 2
+
+bool wifiResultFormatBasic;
+
+struct location {
+ float lat, lng;
+ int accuracy;
+};
+
+typedef struct {
+ const char* const cmd;
+ void (*handler)(uint8_t args_at);
+ const char* const arg_descr;
+ const char* const description;
+} menu_item_t;
+
+EventQueue queue(4 * EVENTS_EVENT_SIZE);
+
+RawSerial pc(USBTX, USBRX, MBED_CONF_PLATFORM_STDIO_BAUD_RATE); // speed from mbed_app.json
+char pcbuf[64];
+int pcbuf_len;
+
+NetworkInterface* network;
+
+event_callback_t serialEventCb;
+
+uint8_t wifiScan_buf[9];
+uint64_t wifi_start_at, wifi_scan_dur;
+bool post_enable;
+bool send_reply;
+
+void cmd_help(uint8_t);
+
+struct location geoloc_result;
+
+uint8_t remote_chip_eui[8];
+
+struct wifidr {
+ const char *txt;
+ float Mbps;
+};
+
+const struct wifidr wifiDatarates[] = {
+ /* 0 */ { NULL, 0},
+ /* 1 */ { "DBPSK", 1},
+ /* 2 */ { "DQPSK", 2},
+ /* 3 */ { "BPSK", 6},
+ /* 4 */ { "BPSK", 9},
+ /* 5 */ { "QPSK", 12},
+ /* 6 */ { "QPSK", 18},
+ /* 7 */ { "16-QAM", 24},
+ /* 8 */ { "16-QAM", 36},
+ /* 9 */ { "(9)", 0},
+ /* 10 */ { "(10)", 0},
+ /* 11 */ { "BPSK", 6.5},
+ /* 12 */ { "QPSK", 13},
+ /* 13 */ { "QPSK", 19.5},
+ /* 14 */ { "16-QAM", 26},
+ /* 15 */ { "16-QAM", 39},
+ /* 16 */ { "(16)", 0},
+ /* 17 */ { "(17)", 0},
+ /* 18 */ { "(18)", 0},
+ /* 19 */ { "BPSK", 7.2},
+ /* 20 */ { "QPSK", 14.4},
+ /* 21 */ { "QPSK", 21.7},
+ /* 22 */ { "16-QAM", 28.9},
+ /* 23 */ { "16-QAM", 43.3},
+};
+
+char json[1536];
+
+void dump_response(HttpResponse* res)
+{
+ printf("Status: %d - %s\n", res->get_status_code(), res->get_status_message().c_str());
+
+ printf("Headers:\n");
+ for (size_t ix = 0; ix < res->get_headers_length(); ix++) {
+ printf("\t%s: %s\n", res->get_headers_fields()[ix]->c_str(), res->get_headers_values()[ix]->c_str());
+ }
+ printf("\nBody (%lu bytes):\n\n%s\n", res->get_body_length(), res->get_body_as_string().c_str());
+}
+
+void cfg_lora()
+{
+ Radio::LoRaModemConfig(BW_KHZ, SPREADING_FACTOR, 1);
+ Radio::SetChannel(CF_HZ);
+ Radio::set_tx_dbm(TX_DBM);
+ // preambleLen, fixLen, crcOn, invIQ
+ Radio::LoRaPacketConfig(8, false, true, false);
+}
+
+void cmd_wifi_scan(uint8_t idx)
+{
+ Radio::radio.xfer(OPCODE_WIFI_SCAN, 9, 0, wifiScan_buf);
+ wifi_start_at = Kernel::get_ms_count();
+ printf("wifiScan...\r\n");
+
+ post_enable = pcbuf[idx] == 'p';
+ send_reply = false;
+}
+
+/* List of trusted root CA certificates
+ * currently two: Amazon, the CA for os.mbed.com and Let's Encrypt, the CA for httpbin.org
+ *
+ * To add more root certificates, just concatenate them.
+ */
+const char HTTBIN_ORG_SSL_CA_PEM[] = "-----BEGIN CERTIFICATE-----\n"
+ "MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF\n"
+ "ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6\n"
+ "b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL\n"
+ "MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv\n"
+ "b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj\n"
+ "ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM\n"
+ "9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw\n"
+ "IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6\n"
+ "VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L\n"
+ "93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm\n"
+ "jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC\n"
+ "AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA\n"
+ "A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI\n"
+ "U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs\n"
+ "N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv\n"
+ "o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU\n"
+ "5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy\n"
+ "rqXRfboQnoZsG4q5WTP468SQvvG5\n"
+ "-----END CERTIFICATE-----\n"
+ "-----BEGIN CERTIFICATE-----\n"
+ "MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/\n"
+ "MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\n"
+ "DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow\n"
+ "SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT\n"
+ "GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC\n"
+ "AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF\n"
+ "q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8\n"
+ "SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0\n"
+ "Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA\n"
+ "a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj\n"
+ "/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T\n"
+ "AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG\n"
+ "CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv\n"
+ "bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k\n"
+ "c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw\n"
+ "VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC\n"
+ "ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz\n"
+ "MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu\n"
+ "Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF\n"
+ "AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo\n"
+ "uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/\n"
+ "wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu\n"
+ "X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG\n"
+ "PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6\n"
+ "KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==\n"
+ "-----END CERTIFICATE-----\n";
+
+
+void cmd_httpbin_post(uint8_t idx)
+{
+ const char body[] = "{\"hello\":\"world\"}";
+
+#if DEMO == DEMO_HTTPS
+ printf("\n----- HTTPS POST request -----\n");
+ HttpsRequest* post_req = new HttpsRequest(network, HTTBIN_ORG_SSL_CA_PEM, HTTP_POST, "https://httpbin.org/post");
+#elif DEMO == DEMO_HTTP
+ printf("\n----- HTTP POST request -----\n");
+ HttpRequest* post_req = new HttpRequest(network, HTTP_POST, "http://httpbin.org/post");
+#endif
+
+ post_req->set_header("Content-Type", "application/json");
+
+ HttpResponse* post_res = post_req->send(body, strlen(body));
+ if (!post_res) {
+ printf("HttpRequest failed (error code %d)\n", post_req->get_error());
+ return;
+ }
+
+ dump_response(post_res);
+ delete post_req;
+}
+
+
+void cmd_print_status(uint8_t idx)
+{
+ stat_t stat;
+ uint8_t buf[4];
+ printf("[NWKH] IP address: %s\n", network->get_ip_address());
+
+ stat.word = Radio::radio.xfer(OPCODE_GET_VERSION, 0, 0, NULL);
+ stat.word = Radio::radio.xfer(0x0000, 0, 4, buf);
+ if (stat.bits.cmdStatus == CMD_DAT) {
+ printf("LR1110 chip:%02x use:%02x fw-v%u.%u\r\n",
+ buf[0], /* silicon rev */
+ buf[1], /* use case */
+ buf[2], /* firmware major */
+ buf[3] /* firmware minor */
+ );
+ }
+
+ stat.word = Radio::radio.xfer(OPCODE_GET_STATUS, 4, 0, buf);
+ printf("chipMode:%d, cmdStatus:%d\r\n", stat.bits.chipMode, stat.bits.cmdStatus);
+}
+
+const menu_item_t menu_items[] =
+{
+ { "phb", cmd_httpbin_post, "","test post to httpbin.org"},
+ { "ws", cmd_wifi_scan, "","local wifi scan"},
+ { ".", cmd_print_status, "","print status"},
+ { "?", cmd_help, "","this list of commands"},
+ { NULL, NULL, NULL, NULL }
+};
+
+void
+console()
+{
+ int i;
+ uint8_t user_cmd_len;
+
+ if (pcbuf_len < 0) {
+ printf("abort\r\n");
+ pcbuf_len = 0;
+ return;
+ }
+
+ printf("\r\n");
+
+ if (pcbuf_len > 0) {
+ /* get end of user-entered command */
+ user_cmd_len = 1; // first character can be any character
+ for (i = 1; i <= pcbuf_len; i++) {
+ if (pcbuf[i] < 'A' || (pcbuf[i] > 'Z' && pcbuf[i] < 'a') || pcbuf[i] > 'z') {
+ user_cmd_len = i;
+ break;
+ }
+ }
+
+
+ for (i = 0; menu_items[i].cmd != NULL ; i++) {
+ int mi_len = strlen(menu_items[i].cmd);
+ if (menu_items[i].handler && user_cmd_len == mi_len && (strncmp(pcbuf, menu_items[i].cmd, mi_len) == 0)) {
+ while (pcbuf[mi_len] == ' ') // skip past spaces
+ mi_len++;
+ menu_items[i].handler(mi_len);
+ break;
+ }
+ }
+ }
+
+ pcbuf_len = 0;
+ printf("> ");
+ fflush(stdout);
+}
+
+void echo(char c)
+{
+ if (c == 8) {
+ pc.putc(8);
+ pc.putc(' ');
+ pc.putc(8);
+ } else
+ pc.putc(c);
+}
+
+uint8_t serial_rx_buf;
+
+void serialCb(int events)
+{
+ if (events & SERIAL_EVENT_RX_COMPLETE) {
+ char c = serial_rx_buf;
+ static uint8_t pcbuf_idx = 0;
+ static uint8_t prev_len = 0;;
+ if (c == 8) {
+ if (pcbuf_idx > 0) {
+ queue.call(echo, 8);
+ pcbuf_idx--;
+ }
+ } else if (c == 3) { // ctrl-C
+ pcbuf_len = -1;
+ queue.call(console);
+ } else if (c == '\r') {
+ if (pcbuf_idx == 0) {
+ pcbuf_len = prev_len;
+ } else {
+ pcbuf[pcbuf_idx] = 0; // null terminate
+ prev_len = pcbuf_idx;
+ pcbuf_idx = 0;
+ pcbuf_len = prev_len;
+ }
+ queue.call(console);
+ } else if (pcbuf_idx < sizeof(pcbuf)) {
+ pcbuf[pcbuf_idx++] = c;
+ queue.call(echo, c);
+ }
+ }
+
+ if (pc.read(&serial_rx_buf, 1, serialCb) != 0)
+ printf("Serial-Read-Fail\r\n");
+}
+
+void cmd_help(uint8_t args_at)
+{
+ int i;
+
+ for (i = 0; menu_items[i].cmd != NULL ; i++) {
+ printf("%s%s\t%s\r\n", menu_items[i].cmd, menu_items[i].arg_descr, menu_items[i].description);
+ }
+}
+
+
+void print_wifi_result(const uint8_t *result)
+{
+ char out[96];
+ char str[24];
+ unsigned n, macStart;
+ wifiType_t wt;
+ wifiChanInfo_t ci;
+ wt.octet = result[0];
+ ci.octet = result[1];
+ out[0] = 0;
+ strcat(out, "802.11");
+ switch (wt.bits.signal) {
+ case 1: strcat(out, "b"); break;
+ case 2: strcat(out, "g"); break;
+ case 3: strcat(out, "n"); break;
+ }
+ sprintf(str, " %s %.1fMbps", wifiDatarates[wt.bits.datarate].txt, wifiDatarates[wt.bits.datarate].Mbps);
+ strcat(out, str);
+ strcat(out, " ");
+
+ sprintf(str, "ch%u ", ci.bits.channelID);
+ strcat(out, str);
+ switch (ci.bits.channelID) {
+ // table 10-5
+ }
+ strcat(out, " ");
+ sprintf(str, "mv:%u ", ci.bits.macValidationID);
+ strcat(out, str);
+ switch (ci.bits.macValidationID) {
+ case 1: strcat(out, "gateway"); break;
+ case 2: strcat(out, "phone"); break;
+ case 3: strcat(out, "?"); break;
+ // table 10.8
+ }
+
+ strcat(out, " ");
+
+ if (wifiResultFormatBasic) {
+ macStart = 3;
+ } else {
+ macStart = 4;
+ }
+ for (n = 0; n < 6; n++) {
+ sprintf(str, "%02x", result[n+macStart]);
+ strcat(out, str);
+ if (n < 5)
+ strcat(out, ":");
+ }
+
+ sprintf(str, " rssi:%d ", (int8_t)result[2]);
+ strcat(out, str);
+
+ if (!wifiResultFormatBasic) {
+ sprintf(str, "frameCtrl:%02x ", result[3]);
+ strcat(out, str);
+ }
+ printf("%s\r\n", out);
+}
+
+void take_result()
+{
+ printf("result %f, %f, %d\r\n",
+ geoloc_result.lat,
+ geoloc_result.lng,
+ geoloc_result.accuracy
+ );
+
+ /* TODO: store result to database and show on map */
+
+ if (send_reply) {
+ unsigned len;
+ memcpy(Radio::radio.tx_buf, remote_chip_eui, 8);
+ Radio::radio.tx_buf[8] = 0; // rfu
+ Radio::radio.tx_buf[9] = 0; // rfu
+ len = sprintf((char*)(Radio::radio.tx_buf + HEADER_LENGTH), "%f, %f, %u",
+ geoloc_result.lat,
+ geoloc_result.lng,
+ geoloc_result.accuracy
+ );
+ Radio::Send(len + HEADER_LENGTH, 0, 0, 0); /* begin transmission */
+ send_reply = false; // sent
+ }
+}
+
+void service()
+{
+ irq_t irq;
+ irq.dword = Radio::radio.service();
+ if (irq.bits.WifiDone) {
+ stat_t stat;
+ uint8_t nbResults;
+ json_start();
+ stat.word = Radio::radio.xfer(OPCODE_GET_WIFI_NB_RESULTS, 0, 0, NULL);
+ stat.word = Radio::radio.xfer(0x0000, 0, 1, &nbResults);
+ if (stat.bits.cmdStatus == CMD_DAT) {
+ unsigned n;
+ printf("%ums nbResults:%u\r\n", (unsigned)wifi_scan_dur, nbResults);
+ for (n = 0; n < nbResults; n++) {
+ uint8_t buf[3];
+ uint8_t resultBuf[22];
+ buf[0] = n;
+ buf[1] = 1; // number of results in this read
+ buf[2] = wifiResultFormatBasic ? 4 : 1;
+ stat.word = Radio::radio.xfer(OPCODE_WIFI_READ_RESULTS, 3, 0, buf);
+ // basic = 9byte length
+ // full = 22byte length
+ stat.word = Radio::radio.xfer(0x0000, 0, wifiResultFormatBasic ? 9 : 22, resultBuf);
+ if (stat.bits.cmdStatus == CMD_DAT) {
+ wifiChanInfo_t ci;
+ print_wifi_result(resultBuf);
+ ci.octet = resultBuf[1];
+ if (ci.bits.macValidationID == 1) // 1 is AP
+ wifi_result_to_json(n == 0, resultBuf, wifiResultFormatBasic ? 3 : 4, 2);
+ } else
+ printf("readResult:%s\r\n", Radio::radio.cmdStatus_toString(stat.bits.cmdStatus));
+ }
+ }
+ json_end();
+ //printf("JSON %s\r\n", json);
+ if (post_enable) {
+ printf("post_enabled\r\n");
+ if (nbResults > MINIMUM_REQUIRED_ACCESS_POINTS) {
+ post_scan_result(json, &geoloc_result.lat, &geoloc_result.lng, &geoloc_result.accuracy);
+ queue.call(take_result);
+ } else
+ printf("only %u access points\r\n", nbResults);
+ }
+
+ cfg_lora();
+ Radio::Rx(0);
+ } // ..if (irq.bits.WifiDone)
+}
+
+void radio_irq_handler()
+{
+ wifi_scan_dur = Kernel::get_ms_count() - wifi_start_at;
+ queue.call(service);
+}
+
+void txDoneCB()
+{
+ Radio::Rx(0);
+}
+
+void parse_remote_wifi_scan(uint8_t pktLen)
+{
+ uint8_t ap_cnt = 0;
+ uint8_t pkt_idx = HEADER_LENGTH;
+ json_start();
+ while (pkt_idx < pktLen) {
+ wifi_result_to_json(pkt_idx == HEADER_LENGTH, Radio::radio.rx_buf + pkt_idx, 0, 6);
+ if (strlen(json) >= sizeof(json)) {
+ printf("json-overrun\r\n");
+ return;
+ }
+ pkt_idx += 7;
+ ap_cnt++;
+ }
+ json_end();
+
+ if (ap_cnt > MINIMUM_REQUIRED_ACCESS_POINTS) {
+ post_scan_result(json, &geoloc_result.lat, &geoloc_result.lng, &geoloc_result.accuracy);
+ queue.call(take_result);
+ } else
+ printf("only %u access points\r\n", ap_cnt);
+
+ send_reply = true;
+}
+
+void rxDoneCB(uint8_t size, float rssi, float snr)
+{
+ unsigned i;
+ printf("%.1fdBm snr:%.1fdB\t", rssi, snr);
+
+ for (i = 0; i < size; i++) {
+ printf("%02x ", Radio::radio.rx_buf[i]);
+ }
+ printf("\r\n");
+
+ for (i = 0; i < 8; i++)
+ remote_chip_eui[i] = Radio::radio.rx_buf[i];
+
+ parse_remote_wifi_scan(size);
+}
+
+const RadioEvents_t rev = {
+ /* Dio0_top_half */ radio_irq_handler,
+ /* TxDone_topHalf */ NULL,
+ /* TxDone_botHalf */ txDoneCB,
+ /* TxTimeout */ NULL,
+ /* RxDone */ rxDoneCB,
+ /* RxTimeout */ NULL,
+ /* RxError */ NULL,
+ /* FhssChangeChannel */NULL,
+ /* CadDone */ NULL
+};
+
+int main()
+{
+ { /* wifi scan defaults, see LR1110 user manual section 10.2 */
+ unsigned chanmask = 0x0421; // ch1, ch6, ch11
+ unsigned timeout = 105; // in milliseconds, 100 wifi TUs (beacon interval)
+
+ wifiScan_buf[0] = 0x01; // wifi type
+ wifiScan_buf[2] = chanmask; // chanmask-lo
+ chanmask >>= 8;
+ wifiScan_buf[1] = chanmask; // chanmask-hi
+ wifiScan_buf[3] = 0x02; // acqMode
+ wifiScan_buf[4] = 0x0a; // NbMaxRes
+ wifiScan_buf[5] = 0x10; // NbScanPerChan
+ wifiScan_buf[7] = timeout; // Timeout-lo
+ timeout >>= 8;
+ wifiScan_buf[6] = timeout; // Timeout-hi
+ wifiScan_buf[8] = 0x00; // AbortOnTimeout
+ }
+
+ serialEventCb = serialCb;
+
+ if (pc.read(&serial_rx_buf, 1, serialCb) != 0)
+ printf("serial-read-fail\r\n");
+
+ // Connect to the network with the default networking interface
+ // if you use WiFi: see mbed_app.json for the credentials
+ network = connect_to_default_network_interface();
+ if (!network) {
+ printf("Cannot connect to the network, see serial output\n");
+ return 1;
+ }
+
+ Radio::Init(&rev);
+
+ Radio::Standby();
+ cfg_lora();
+ Radio::Rx(0);
+
+ queue.dispatch();
+}
+
diff -r fd6707e25c57 -r 4a05f91c9c38 main.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.h Tue Feb 09 10:49:02 2021 -0800 @@ -0,0 +1,25 @@ +#include "select-demo.h" + +#include "mbed.h" +#if DEMO == DEMO_HTTPS + #include "https_request.h" +#elif DEMO == DEMO_HTTP + #include "http_request.h" +#endif + +#define GOOGLE 1 +#define COMBAIN 2 +//#define GEOLOCATION_PROVIDER GOOGLE +//#define GEOLOCATION_PROVIDER COMBAIN + +#define HEADER_LENGTH 10 /* for chipEUI and extra reserved */ + +int post_scan_result(const char*, float*, float*, int*); +void wifi_result_to_json(bool first, const uint8_t *result, unsigned macStart, unsigned rssi_idx); +void json_start(void); +void json_end(void); +extern char json[]; +extern bool wifiResultFormatBasic; +extern NetworkInterface* network; +void dump_response(HttpResponse* res); +
diff -r fd6707e25c57 -r 4a05f91c9c38 mbed_app.json
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed_app.json Tue Feb 09 10:49:02 2021 -0800
@@ -0,0 +1,31 @@
+{
+ "config": {
+ "main-stack-size": {
+ "value": 8192
+ }
+ },
+ "macros": [
+ "MBEDTLS_MPI_MAX_SIZE=1024",
+ "MBEDTLS_MPI_WINDOW_SIZE=1",
+ "MBEDTLS_USER_CONFIG_FILE=\"mbedtls_entropy_config.h\"",
+ "MBEDTLS_TEST_NULL_ENTROPY",
+ "MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES",
+ "MBED_HEAP_STATS_ENABLED=1"
+ ],
+ "target_overrides": {
+ "*": {
+ "platform.stdio-baud-rate": 115200,
+ "platform.stdio-convert-newlines": true,
+ "mbed-mesh-api.6lowpan-nd-channel-page": 0,
+ "mbed-mesh-api.6lowpan-nd-channel": 12,
+ "mbed-trace.enable": null,
+ "mbed-http.http-buffer-size": 2048,
+ "nsapi.default-wifi-security": "WPA_WPA2",
+ "nsapi.default-wifi-ssid": "\"SSID\"",
+ "nsapi.default-wifi-password": "\"Password\""
+ },
+ "DISCO_L475VG_IOT01A": {
+ "target.network-default-interface-type" : "WIFI"
+ }
+ }
+}
diff -r fd6707e25c57 -r 4a05f91c9c38 mbedtls_entropy_config.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbedtls_entropy_config.h Tue Feb 09 10:49:02 2021 -0800 @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#include "select-demo.h" + +/* Enable entropy for devices with TRNG. This means entropy is disabled for all other targets. */ +/* Do **NOT** deploy this code in production on other targets! */ +/* See https://tls.mbed.org/kb/how-to/add-entropy-sources-to-entropy-pool */ +#if defined(DEVICE_TRNG) +#undef MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES +#undef MBEDTLS_TEST_NULL_ENTROPY +#endif
diff -r fd6707e25c57 -r 4a05f91c9c38 network-helper.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/network-helper.h Tue Feb 09 10:49:02 2021 -0800
@@ -0,0 +1,34 @@
+#ifndef _MBED_HTTP_EXAMPLE_H_
+#define _MBED_HTTP_EXAMPLE_H_
+
+#include "mbed.h"
+#include "NetworkInterface.h"
+
+/**
+ * Connect to the network using the default networking interface,
+ * you can also swap this out with a driver for a different networking interface
+ * if you use WiFi: see mbed_app.json for the credentials
+ */
+NetworkInterface *connect_to_default_network_interface() {
+ printf("[NWKH] Connecting to network...\n");
+
+ NetworkInterface* network = NetworkInterface::get_default_instance();
+
+ if (!network) {
+ printf("[NWKH] No network interface found, select an interface in 'network-helper.h'\n");
+ return NULL;
+ }
+
+ nsapi_error_t connect_status = network->connect();
+
+ if (connect_status != NSAPI_ERROR_OK) {
+ printf("[NWKH] Failed to connect to network (%d)\n", connect_status);
+ return NULL;
+ }
+
+ printf("[NWKH] Connected to the network\n");
+ printf("[NWKH] IP address: %s\n", network->get_ip_address());
+ return network;
+}
+
+#endif // _MBED_HTTP_EXAMPLE_H_
diff -r fd6707e25c57 -r 4a05f91c9c38 source/select-demo.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/select-demo.h Tue Feb 09 10:49:02 2021 -0800 @@ -0,0 +1,14 @@ +#ifndef _SELECT_METHOD_H_ +#define _SELECT_METHOD_H_ + +#define DEMO_HTTP 1 +#define DEMO_HTTP_SOCKET_REUSE 2 +#define DEMO_HTTP_IPV6 3 +#define DEMO_HTTPS 4 +#define DEMO_HTTPS_SOCKET_REUSE 5 +#define DEMO_HTTPS_CHUNKED_REQUEST 6 +#define DEMO_TESTS 7 + +#define DEMO DEMO_HTTPS + +#endif // _SELECT_METHOD_H_