diff --git a/README.md b/README.md index ebcbf1d..7150318 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ The actual flash process is different if you have a debuger unit or are just usi **Also please note** that by flashing these examples you will overwrite the "Sensor Aggregation" firmware which is installed in a fresh XPLR-IOT-1. Should you later want to restore that firmware, [this page](https://github.com/u-blox/XPLR-IOT-1-software) will show you how. -Some of the Bluetooth examples requires at least version 1.2 of ubxlib, to be released in March 2023. +The WiFi captive portal example requires ubxlib version 1.3 or later, to be released July 2023. # Getting started diff --git a/do b/do index 6ccaf75..f83a819 100755 --- a/do +++ b/do @@ -232,7 +232,7 @@ def vscode_files(): with open(templ_dir + "/launch_tmpl.json", "r") as f: launch = f.read() launch = re.sub("\$BUILD_DIR", Path(f"{settings['build_dir']}/{args.example}").as_posix(), launch) - launch = re.sub("\$EXE_FILE", os.path.basename(get_exe_file(args, not args.no_bootloader, has_jlink, False)), launch) + launch = re.sub("\$EXE_FILE", os.path.basename(get_exe_file(args, not args.no_bootloader, True, False)), launch) launch = re.sub("\$TC_DIR", gcc_bin_dir, launch) gdb_exe = sorted(Path(gcc_bin_dir).rglob(f"*gdb{exe_suffix}"))[0].as_posix() launch = re.sub("\$GDB_PATH", gdb_exe, launch) diff --git a/examples/captive_portal/CMakeLists.txt b/examples/captive_portal/CMakeLists.txt new file mode 100644 index 0000000..0b6a2c3 --- /dev/null +++ b/examples/captive_portal/CMakeLists.txt @@ -0,0 +1,17 @@ +# Copyright 2022 u-blox +# +# 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. + +cmake_minimum_required(VERSION 3.13.1) +include(../common.cmake) +project(captive_portal) diff --git a/examples/captive_portal/prj.conf b/examples/captive_portal/prj.conf new file mode 100644 index 0000000..637cca7 --- /dev/null +++ b/examples/captive_portal/prj.conf @@ -0,0 +1,13 @@ +# Copyright 2022 u-blox +# +# 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. + +# No extra configuration needed for this example diff --git a/examples/captive_portal/src/main.c b/examples/captive_portal/src/main.c new file mode 100644 index 0000000..4638274 --- /dev/null +++ b/examples/captive_portal/src/main.c @@ -0,0 +1,154 @@ + +/* + * Copyright 2023 u-blox + * + * 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 example application shows how to use the ubxlib wifi captive + * portal function for initial provisioning of SSID and password. + * + * IMPORTANT! ubxlib version 1.3 or later is required. + * + */ + +#include +#include + +#include "ubxlib.h" + +#include "leds.h" +#include "buttons.h" + + +#define PORTAL_NAME "UBXLIB_PORTAL" + +uDeviceHandle_t gDeviceHandle; +bool gDoReset = false; + +/* Button press callback */ +static void button_pressed(int buttonNo, uint32_t holdTime) +{ + // Clear the current credentials and start the captive + // portal after a long press of first button. + if (buttonNo == 0 && holdTime > 2000) { + gDoReset = true; + } +} + +static bool portalExit(uDeviceHandle_t deviceHandle) +{ + // Exit the portal when in connected mode if reset has been requested + (void)deviceHandle; + return gDoReset; +} + +/* Connect to an access point or start the captive portal */ +void doConnect() +{ + int32_t errorCode = -1; + static uNetworkCfgWifi_t networkCfg = { + .type = U_NETWORK_TYPE_WIFI, + .mode = U_WIFI_MODE_STA, + }; + ledSet(RED_LED, false); + ledSet(GREEN_LED, false); + ledSet(RED_LED, false); + if (uWifiStationHasStoredConfig(gDeviceHandle)) { + // Credentials have been saved earlier, try to connect to the access point. + ledBlink(GREEN_LED, 250, 250); + errorCode = uNetworkInterfaceUp(gDeviceHandle, U_NETWORK_TYPE_WIFI, &networkCfg); + } + if (errorCode != 0) { + printf("- Failed to bring up WiFi, starting captive portal."); + printf("Use a phone or PC to connect to the WiFi access point\n"); + printf("with the name \"%s\".\n", PORTAL_NAME); + ledBlink(BLUE_LED, 250, 250); + errorCode = uWifiCaptivePortal(gDeviceHandle, PORTAL_NAME, NULL, NULL); + } + ledBlink(GREEN_LED, 0, 0); + if (errorCode == 0) { + // Connected + ledSet(BLUE_LED, false); + ledBlink(GREEN_LED, 0, 0); + ledSet(GREEN_LED, true); + int32_t sock = uSockCreate(gDeviceHandle, + U_SOCK_TYPE_STREAM, + U_SOCK_PROTOCOL_TCP); + if (sock >= 0) { + // Show the received ip address + uSockAddress_t localAddr; + char addrStr[15]; + uSockGetLocalAddress(sock, &localAddr); + uSockIpAddressToString(&(localAddr.ipAddress), addrStr, sizeof(addrStr)); + uPortLog("Connected. Local address: %s\n", addrStr); + uSockClose(sock); + // Start the web server also in this mode in order to enable possibility + // to change the selected network also when connected, mainly for testing. + while (uWifiCaptivePortal(gDeviceHandle, NULL, NULL, portalExit) == 0) { + gDoReset = false; + } + gDoReset = true; + } + } + if (errorCode != 0) { + printf("* Captive portal failed: %d\n", errorCode); + ledSet(BLUE_LED, false); + ledSet(GREEN_LED, false); + ledBlink(RED_LED, 100, 100); + uPortTaskBlock(5000); + ledBlink(RED_LED, 0, 0); + gDoReset = true; + } +} + +void main() +{ + if (!buttonsInit(button_pressed)) { + printf("* Failed to initiate buttons\n"); + } + if (!ledsInit()) { + printf("* Failed to initiate leds\n"); + } + + // Remove the line below if you want the log printouts from ubxlib + uPortLogOff(); + // Initiate ubxlib + uPortInit(); + uDeviceInit(); + // And the U-blox module + int32_t errorCode; + static uDeviceCfg_t deviceCfg; + uDeviceGetDefaults(U_DEVICE_TYPE_SHORT_RANGE, &deviceCfg); + printf("\nInitiating the module...\n"); + errorCode = uDeviceOpen(&deviceCfg, &gDeviceHandle); + if (errorCode == 0) { + // First connect + doConnect(); + while (true) { + if (gDoReset) { + gDoReset = false; + printf("Reseting credentials...\n"); + uNetworkInterfaceDown(gDeviceHandle, U_NETWORK_TYPE_WIFI); + uWifiStationStoreConfig(gDeviceHandle, true); + doConnect(); + } else { + uPortTaskBlock(1000); + } + } + } else { + printf("* Failed to start the module: %d\n", errorCode); + } +} diff --git a/examples/common/ble_aoa.c b/examples/common/ble_aoa.c index 8395287..cd67a48 100644 --- a/examples/common/ble_aoa.c +++ b/examples/common/ble_aoa.c @@ -14,6 +14,8 @@ * limitations under the License. */ +#include + #include #include #include @@ -83,7 +85,7 @@ static bool set_adv_params(uint16_t min_ms, uint16_t max_ms) return bt_le_per_adv_set_param(m_ext_adv, &per_adv_param) == 0; } -bool bleAoaInit() +bool bleAoaInit(char *pBleId) { bool ok = bt_enable(NULL) == 0; if (ok) { @@ -100,6 +102,12 @@ bool bleAoaInit() memcpy(id, addr.a.val, EDDYSTONE_INSTANCE_ID_LEN); } memcpy((uint8_t *)&m_adv_data[2].data[ADV_DATA_OFFSET_INSTANCE], id, EDDYSTONE_INSTANCE_ID_LEN); + if (pBleId) { + for (uint8_t i = 0; i < EDDYSTONE_INSTANCE_ID_LEN; i++) { + sprintf(pBleId, "%02X", id[i]); + pBleId += 2; + } + } ok = bt_le_ext_adv_create(&m_adv_param, NULL, &m_ext_adv) == 0; ok = ok && bt_le_ext_adv_set_data(m_ext_adv, m_adv_data, ARRAY_SIZE(m_adv_data), NULL, 0) == 0; diff --git a/examples/common/ble_aoa.h b/examples/common/ble_aoa.h index d94f480..73faca1 100644 --- a/examples/common/ble_aoa.h +++ b/examples/common/ble_aoa.h @@ -18,9 +18,11 @@ #include /** Initiate BLE for angle of arrival advertisements + * @param pBleId String to receive the 12 character BLE id (mac). + * Can be set to NULL. * @return Success or failure. */ -bool bleAoaInit(); +bool bleAoaInit(char *pBleId); /** Start or stop angle of arrival advertisements * @param min_ms Minimum advertisement time in milliseconds.