diff --git a/README.md b/README.md index b6ac3da..967cdbf 100644 --- a/README.md +++ b/README.md @@ -88,3 +88,19 @@ Press any key in 3 seconds to enter device configuration menu... You can then press any key on your keyboard to enter the configuration menu. After that you'll see a few configuration options that can be altered and persisted within the flash memory for future bootups. + + +# Bulk Tainer Telematics demo + +## Running demo +1. Change branche to `btt_demo` +2. Setup workspace: `mbed deploy` +3. Change your device `endpoint_name` in `mbed_app.json` +4. Mock custom board: `mbedls --mock 0828:BT_01001_V0_2` +5. If using mbed-os 5.X apply AT_Handler patch from https://github.com/Waleed-Elmughrabi/BTTM-IOT-NODE-Master +6. Build&flash: `mbed compile -m BT_01001_V0_2 --profile debug --flash` +7. Add device to Coiote Device Management + * Go to Device Inventory, click `+ Add device` button + * Than Connect your LwM2M device via via the Management server: set `endpoint_name` as `Device ID`, any `Friendly name`, and `Security mode` as `NoSec` than click `Add device` + * Flash device and wait until it get connected then move to next step +8. You have connected device diff --git a/TARGET_BT_01001_V0_2/PinNames.h b/TARGET_BT_01001_V0_2/PinNames.h new file mode 100644 index 0000000..1d0adb2 --- /dev/null +++ b/TARGET_BT_01001_V0_2/PinNames.h @@ -0,0 +1,317 @@ +/* mbed Microcontroller Library + ******************************************************************************* + * Copyright (c) 2018, STMicroelectronics + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************* + */ + +#ifndef MBED_PINNAMES_H +#define MBED_PINNAMES_H + +#include "cmsis.h" +#include "PinNamesTypes.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + ALT0 = 0x100, + ALT1 = 0x200, + ALT2 = 0x300, + ALT3 = 0x400 +} ALTx; + +typedef enum { + PA_0 = 0x00, + PA_0_ALT0 = PA_0 | ALT0, + PA_1 = 0x01, + PA_1_ALT0 = PA_1 | ALT0, + PA_1_ALT1 = PA_1 | ALT1, + PA_2 = 0x02, + PA_2_ALT0 = PA_2 | ALT0, + PA_2_ALT1 = PA_2 | ALT1, + PA_3 = 0x03, + PA_3_ALT0 = PA_3 | ALT0, + PA_3_ALT1 = PA_3 | ALT1, + PA_4 = 0x04, + PA_4_ALT0 = PA_4 | ALT0, + PA_5 = 0x05, + PA_5_ALT0 = PA_5 | ALT0, + PA_6 = 0x06, + PA_6_ALT0 = PA_6 | ALT0, + PA_7 = 0x07, + PA_7_ALT0 = PA_7 | ALT0, + PA_7_ALT1 = PA_7 | ALT1, + PA_7_ALT2 = PA_7 | ALT2, + PA_8 = 0x08, + PA_9 = 0x09, + PA_10 = 0x0A, + PA_11 = 0x0B, + PA_12 = 0x0C, + PA_13 = 0x0D, + PA_14 = 0x0E, + PA_15 = 0x0F, + PA_15_ALT0 = PA_15 | ALT0, + + PB_0 = 0x10, + PB_0_ALT0 = PB_0 | ALT0, + PB_0_ALT1 = PB_0 | ALT1, + PB_1 = 0x11, + PB_1_ALT0 = PB_1 | ALT0, + PB_1_ALT1 = PB_1 | ALT1, + PB_2 = 0x12, + PB_3 = 0x13, + PB_3_ALT0 = PB_3 | ALT0, + PB_4 = 0x14, + PB_4_ALT0 = PB_4 | ALT0, + PB_5 = 0x15, + PB_5_ALT0 = PB_5 | ALT0, + PB_6 = 0x16, + PB_6_ALT0 = PB_6 | ALT0, + PB_7 = 0x17, + PB_7_ALT0 = PB_7 | ALT0, + PB_8 = 0x18, + PB_8_ALT0 = PB_8 | ALT0, + PB_9 = 0x19, + PB_9_ALT0 = PB_9 | ALT0, + PB_10 = 0x1A, + PB_10_ALT0 = PB_10 | ALT0, + PB_11 = 0x1B, + PB_11_ALT0 = PB_11 | ALT0, + PB_12 = 0x1C, + PB_13 = 0x1D, + PB_13_ALT0 = PB_13 | ALT0, + PB_14 = 0x1E, + PB_14_ALT0 = PB_14 | ALT0, + PB_14_ALT1 = PB_14 | ALT1, + PB_15 = 0x1F, + PB_15_ALT0 = PB_15 | ALT0, + PB_15_ALT1 = PB_15 | ALT1, + + PC_0 = 0x20, + PC_0_ALT0 = PC_0 | ALT0, + PC_0_ALT1 = PC_0 | ALT1, + PC_1 = 0x21, + PC_1_ALT0 = PC_1 | ALT0, + PC_1_ALT1 = PC_1 | ALT1, + PC_2 = 0x22, + PC_2_ALT0 = PC_2 | ALT0, + PC_2_ALT1 = PC_2 | ALT1, + PC_3 = 0x23, + PC_3_ALT0 = PC_3 | ALT0, + PC_3_ALT1 = PC_3 | ALT1, + PC_4 = 0x24, + PC_4_ALT0 = PC_4 | ALT0, + PC_5 = 0x25, + PC_5_ALT0 = PC_5 | ALT0, + PC_6 = 0x26, + PC_6_ALT0 = PC_6 | ALT0, + PC_7 = 0x27, + PC_7_ALT0 = PC_7 | ALT0, + PC_8 = 0x28, + PC_8_ALT0 = PC_8 | ALT0, + PC_9 = 0x29, + PC_9_ALT0 = PC_9 | ALT0, + PC_10 = 0x2A, + PC_10_ALT0 = PC_10 | ALT0, + PC_11 = 0x2B, + PC_11_ALT0 = PC_11 | ALT0, + PC_12 = 0x2C, + PC_13 = 0x2D, + PC_14 = 0x2E, + PC_15 = 0x2F, + + PD_0 = 0x30, + PD_1 = 0x31, + PD_2 = 0x32, + PD_3 = 0x33, + PD_4 = 0x34, + PD_5 = 0x35, + PD_6 = 0x36, + PD_7 = 0x37, + PD_8 = 0x38, + PD_9 = 0x39, + PD_10 = 0x3A, + PD_11 = 0x3B, + PD_12 = 0x3C, + PD_13 = 0x3D, + PD_14 = 0x3E, + PD_15 = 0x3F, + + PE_0 = 0x40, + PE_1 = 0x41, + PE_2 = 0x42, + PE_3 = 0x43, + PE_4 = 0x44, + PE_5 = 0x45, + PE_6 = 0x46, + PE_7 = 0x47, + PE_8 = 0x48, + PE_9 = 0x49, + PE_10 = 0x4A, + PE_11 = 0x4B, + PE_12 = 0x4C, + PE_13 = 0x4D, + PE_14 = 0x4E, + PE_15 = 0x4F, + + PF_0 = 0x50, + PF_1 = 0x51, + PF_2 = 0x52, + PF_3 = 0x53, + PF_4 = 0x54, + PF_5 = 0x55, + PF_6 = 0x56, + PF_7 = 0x57, + PF_8 = 0x58, + PF_9 = 0x59, + PF_9_ALT0 = PF_9 | ALT0, + PF_10 = 0x5A, + PF_11 = 0x5B, + PF_12 = 0x5C, + PF_13 = 0x5D, + PF_14 = 0x5E, + PF_15 = 0x5F, + + PG_0 = 0x60, + PG_1 = 0x61, + PG_2 = 0x62, + PG_3 = 0x63, + PG_4 = 0x64, + PG_5 = 0x65, + PG_6 = 0x66, + PG_7 = 0x67, + PG_8 = 0x68, + PG_9 = 0x69, + PG_10 = 0x6A, + PG_11 = 0x6B, + PG_12 = 0x6C, + PG_13 = 0x6D, + PG_14 = 0x6E, + PG_15 = 0x6F, + + PH_0 = 0x70, + PH_1 = 0x71, + + // ADC internal channels + ADC_TEMP = 0xF0, + ADC_VREF = 0xF1, + ADC_VBAT = 0xF2, + + // Arduino pin naming just because some libraries rely on them during compile + A0 = PA_0, + A1 = PA_1, + A2 = PA_2, + A3 = PA_3, + A4 = PA_4, + A5 = PA_5, + D0 = PA_6, + D1 = PA_7, + D2 = PA_8, + D3 = PA_9, + D4 = PA_10, + D5 = PA_11, + D6 = PA_12, + D7 = PA_13, + D8 = PA_14, + D9 = PA_15, + D10 = PB_0, + D11 = PB_1, + D12 = PB_2, + D13 = PB_3, + D14 = PB_4, + D15 = PB_5, + + // STDIO for console print +#ifdef MBED_CONF_TARGET_STDIO_UART_TX + STDIO_UART_TX = MBED_CONF_TARGET_STDIO_UART_TX, +#else + STDIO_UART_TX = PC_1, +#endif +#ifdef MBED_CONF_TARGET_STDIO_UART_RX + STDIO_UART_RX = MBED_CONF_TARGET_STDIO_UART_RX, +#else + STDIO_UART_RX = PC_0, +#endif + + // Generic signals namings + LED1 = PD_2, + + SERIAL_TX = STDIO_UART_TX, // Virtual Com Port + SERIAL_RX = STDIO_UART_RX, // Virtual Com Port + USBTX = STDIO_UART_TX, // Virtual Com Port + USBRX = STDIO_UART_RX, // Virtual Com Port + + /**** USB FS pins ****/ + USB_OTG_FS_DM = PA_11, + USB_OTG_FS_DP = PA_12, + USB_OTG_FS_ID = PA_10, + USB_OTG_FS_NOE = PA_13, + USB_OTG_FS_NOE_ALT0 = PC_9, + USB_OTG_FS_SOF = PA_8, + USB_OTG_FS_SOF_ALT0 = PA_14, + USB_OTG_FS_VBUS = PA_9, + + /**** OSCILLATOR pins ****/ + RCC_OSC32_IN = PC_14, + RCC_OSC32_OUT = PC_15, + RCC_OSC_IN = PH_0, + RCC_OSC_OUT = PH_1, + + /**** DEBUG pins ****/ + SYS_JTCK_SWCLK = PA_14, + SYS_JTDI = PA_15, + SYS_JTDO_SWO = PB_3, + SYS_JTMS_SWDIO = PA_13, + SYS_JTRST = PB_4, + SYS_PVD_IN = PB_7, + SYS_TRACED0_ALT0 = PC_1, + SYS_TRACED1_ALT0 = PC_10, + SYS_TRACED2_ALT0 = PD_2, + SYS_TRACED3_ALT0 = PC_12, + SYS_WKUP1 = PA_0, + SYS_WKUP2 = PC_13, + SYS_WKUP4 = PA_2, + SYS_WKUP5 = PC_5, + + /**** QSPI FLASH pins ****/ + QSPI_FLASH1_IO0 = PB_1, + QSPI_FLASH1_IO1 = PB_0, + QSPI_FLASH1_IO2 = PA_7, + QSPI_FLASH1_IO3 = PA_6, + QSPI_FLASH1_SCK = PA_3, + QSPI_FLASH1_CSN = PB_11, + + // Not connected + NC = (int)0xFFFFFFFF +} PinName; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/custom_targets.json b/custom_targets.json new file mode 100644 index 0000000..9de0fd6 --- /dev/null +++ b/custom_targets.json @@ -0,0 +1,43 @@ +{ + "BT_01001_V0_1": { + "inherits": [ + "NUCLEO_L496ZG" + ], + "detect_code": [ + "0313" + ], + "macros_add": [ + "BT_01001_V0_1" + ] + }, + "BT_01001_V0_2": { + "inherits": [ + "NUCLEO_L496ZG" + ], + "detect_code": [ + "0313" + ], + "macros_add": [ + "BT_01001_V0_2" + ], + "device_has_add": [ + "QSPI" + ], + "extra_labels_add": [ + "MX25R6435F" + ], + "components_add": [ + "QSPIF", + "FLASHIAP" + ], + "overrides": { + "clock_source": "USE_PLL_HSI" + }, + "supported_toolchains": [ + "ARM", + "uARM", + "IAR", + "GCC_ARM" + ] + } +} \ No newline at end of file diff --git a/humidity.cpp b/humidity.cpp index 3b94b99..8f6f301 100644 --- a/humidity.cpp +++ b/humidity.cpp @@ -37,9 +37,9 @@ #include -#ifdef TARGET_DISCO_L496AG +//#ifdef TARGET_DISCO_L496AG -# include +//# include # include "humidity.h" @@ -101,7 +101,7 @@ typedef struct humidity_struct { const anjay_dm_object_def_t *def; - HTS221Sensor *sensor; + //HTS221Sensor *sensor; float min_value; float max_value; float curr_value; @@ -246,6 +246,7 @@ struct ObjDef : public anjay_dm_object_def_t { } const OBJ_DEF; const anjay_dm_object_def_t **humidity_object_create(void) { +#if 0 HTS221Sensor *sensor = XNucleoIKS01A2::instance(D14, D15)->ht_sensor; uint8_t id = 0; float sensor_value; @@ -254,15 +255,15 @@ const anjay_dm_object_def_t **humidity_object_create(void) { HUMIDITY_OBJ_LOG(WARNING, "Failed to initialize humidity sensor"); return NULL; } - +#endif humidity_t *obj = (humidity_t *) avs_calloc(1, sizeof(humidity_t)); if (!obj) { - (void) sensor->disable(); + //(void) sensor->disable(); return NULL; } obj->def = &OBJ_DEF; - obj->sensor = sensor; - obj->curr_value = sensor_value; + //obj->sensor = sensor; + obj->curr_value = 0.0f; reset_min_max_values(obj); return &obj->def; @@ -309,12 +310,17 @@ void humidity_object_update(anjay_t *anjay) { } humidity_t *obj = get_obj(OBJ_DEF_PTR); - float value; + static float value = MIN_RANGE_VALUE; + value += 1.0f; + if (value > MAX_RANGE_VALUE) { + value = MIN_RANGE_VALUE; + } +#if 0 if (obj->sensor->get_humidity(&value)) { HUMIDITY_OBJ_LOG(ERROR, "Failed to get humidity"); return; } - +#endif if (value != obj->curr_value) { obj->curr_value = value; (void) anjay_notify_changed(anjay, HUMIDITY_OID, 0, RID_SENSOR_VALUE); @@ -331,4 +337,4 @@ void humidity_object_update(anjay_t *anjay) { } } -#endif // TARGET_DISCO_L496AG +//#endif // TARGET_DISCO_L496AG diff --git a/humidity.h b/humidity.h index 2c02e68..d6f779d 100644 --- a/humidity.h +++ b/humidity.h @@ -19,7 +19,7 @@ #include -#ifdef TARGET_DISCO_L496AG +//#ifdef TARGET_DISCO_L496AG # define HUMIDITY_OID 3304 @@ -31,6 +31,6 @@ void humidity_object_uninstall(anjay_t *anjay); void humidity_object_update(anjay_t *anjay); -#endif // TARGET_DISCO_L496AG +//#endif // TARGET_DISCO_L496AG #endif // HUMIDITY_OBJECT_H diff --git a/main.cpp b/main.cpp index b38f6b9..a8815fa 100644 --- a/main.cpp +++ b/main.cpp @@ -35,16 +35,19 @@ #include #include +#include "humidity.h" #ifdef TARGET_DISCO_L496AG #include "accelerometer.h" #include "barometer.h" -#include "humidity.h" #include "joystick.h" #include "magnetometer.h" #endif // TARGET_DISCO_L496AG #include "default_config.h" +#include "TransmissionDeviceBG96.h" + +tasks::TransmissionDeviceBG96* bg96 = NULL; namespace { @@ -205,6 +208,7 @@ const char *try_get_modem_imei() { } const char *get_endpoint_name() { +#if 0 static char endpoint_name[64] = ""; if (endpoint_name[0] != '\0') { @@ -219,7 +223,7 @@ const char *get_endpoint_name() { return endpoint_name; } } - +#endif return DEFAULT_ENDPOINT_NAME; } @@ -250,8 +254,9 @@ void lwm2m_serve() { if (setup_security_object() || setup_server_object() || device_object_install(anjay) + || humidity_object_install(anjay) #ifdef TARGET_DISCO_L496AG - || joystick_object_install(anjay) || humidity_object_install(anjay) + || joystick_object_install(anjay) || barometer_object_install(anjay) || magnetometer_object_install(anjay) || accelerometer_object_install(anjay) @@ -278,9 +283,9 @@ void lwm2m_serve() { if (anjay) { conn_monitoring_object_uninstall(anjay); device_object_uninstall(anjay); + humidity_object_uninstall(anjay); #ifdef TARGET_DISCO_L496AG joystick_object_uninstall(anjay); - humidity_object_uninstall(anjay); barometer_object_uninstall(anjay); magnetometer_object_uninstall(anjay); accelerometer_object_uninstall(anjay); @@ -299,8 +304,8 @@ void lwm2m_check_for_notifications(void) { { ScopedLock lock(anjay_mtx); device_object_update(anjay); -#ifdef TARGET_DISCO_L496AG humidity_object_update(anjay); +#ifdef TARGET_DISCO_L496AG barometer_object_update(anjay); joystick_object_update(anjay); magnetometer_object_update(anjay); @@ -411,8 +416,14 @@ class NetworkService { * @returns 0 on success, negative value otherwise. */ int init(Lwm2mConfig &config) { - NetworkInterface *netif = NetworkInterface::get_default_instance(); + NetworkInterface *netif = NULL; + if (bg96) { + netif = bg96->get_network_interface(); + } else { + printf("bg96 device not initialized !!!!!"); + } if (!netif) { + printf("netif device not initialized !!!!!"); return -1; } @@ -484,6 +495,13 @@ int main() { avs_log(mbed_stats, INFO, "All stats disabled"); #endif + bg96 = new tasks::TransmissionDeviceBG96(*Bg96::get_sync_instance()); + if (!bg96) { + printf("bg96 device not initialized !!!!!"); + } else { + bg96->enable(); + } + // See https://github.com/ARMmbed/mbed-os/issues/7069. In general this is // required to initialize hardware RNG used by default. mbedtls_platform_setup(NULL); diff --git a/mbed-os.lib b/mbed-os.lib index 1dc15a8..32c1c7f 100644 --- a/mbed-os.lib +++ b/mbed-os.lib @@ -1 +1 @@ -https://github.com/ARMmbed/mbed-os/#b005bf21337e6ffe5393671b92066c3b09c5204b +https://github.com/ARMmbed/mbed-os/#e4b81f67f939a0c0b11c147ce74aa367271e1279 diff --git a/mbed_app.json b/mbed_app.json index a48b6a9..46b58bc 100644 --- a/mbed_app.json +++ b/mbed_app.json @@ -1,23 +1,39 @@ { "macros": [ "__STDC_FORMAT_MACROS", - "MBED_CPU_STATS_ENABLED=1", - "MBED_HEAP_STATS_ENABLED=1", - "MBED_MEM_TRACING_ENABLED=1", - "MBED_STACK_STATS_ENABLED=1", + "MBED_CPU_STATS_ENABLED=0", + "MBED_HEAP_STATS_ENABLED=0", + "MBED_MEM_TRACING_ENABLED=0", + "MBED_STACK_STATS_ENABLED=0", "MBEDTLS_MD5_C=1" ], "target_overrides": { "*": { - "cellular.radio-access-technology": "CellularNetwork::RadioAccessTechnology::RAT_GSM", "mbed-trace.enable": 1, "mbed-trace.max-level": "TRACE_LEVEL_DEBUG", - "nsapi.default-cellular-apn": "\"Plus\"", + "nsapi.default-cellular-apn": "\"m2m.tele2.com\"", "platform.stdio-baud-rate": 115200, "platform.stdio-convert-newlines": 1, "target.OUTPUT_EXT": "bin", "target.app_offset": "0x10000", - "target.network-default-interface-type": "CELLULAR" + "target.network-default-interface-type": "CELLULAR", + + "nanostack-hal.critical-section-usable-from-interrupt" : true, + "nanostack-hal.event-loop-dispatch-from-application" : false, + "nanostack-hal.event-loop-use-mbed-events" : true, + "nanostack.configuration" : "ethernet_host", + + "nsapi.default-cellular-plmn" : null, + "nsapi.default-cellular-sim-pin" : null, + "nsapi.default-cellular-username" : null, + "nsapi.default-cellular-password" : null, + + "cellular.debug-at" : false, + "cellular.use-apn-lookup" : false, + "cellular.use-sms" : false, + "cellular.clear-on-connect" : true, + "cellular.offload-dns-queries" : null, + "QUECTEL_BG96.provide-default" : false }, "DISCO_L496AG": { "stmod_cellular.provide-default": "true", @@ -31,16 +47,18 @@ } }, "config": { - "endpoint_name": "\"urn:dev:os:anjay-mbedos-test\"", - "rg_nosec_addr": "\"coap://try-anjay.avsystem.com:5683\"", - "rg_dtls_addr": "\"coaps://try-anjay.avsystem.com:5684\"", - "bs_nosec_addr": "\"coap://try-anjay.avsystem.com:5693\"", - "bs_dtls_addr": "\"coaps://try-anjay.avsystem.com:5684\"", - "with_rg_server": false, - "with_bs_server": true, + "endpoint_name": "\"urn:dev:os:BTT_non_secure_01\"", + "__endpoint_name": "\"urn:dev:os:BTT_secure_01\"", + "rg_nosec_addr": "\"coap://lwm2m-test.avsystem.io:5683\"", + "rg_dtls_addr": "\"coaps://lwm2m-test.avsystem.io:5684\"", + "bs_nosec_addr": "\"coap://lwm2m-test.avsystem.io:5693\"", + "bs_dtls_addr": "\"coaps://lwm2m-test.avsystem.io:5684\"", + "with_rg_server": true, + "with_bs_server": false, "with_dtls": false, - "psk_identity": "\"***PLEASE SET PSK IDENTITY HERE***\"", - "psk_key": "\"***PLEASE SET PSK KEY HERE***\"", + "psk_identity": "\"urn:dev:os:BTT_non_secure_01\"", + "__psk_identity": "\"urn:dev:os:BTT_secure\"", + "psk_key": "\"11111111111111111111111111111111111111111111111111111111111111\"", "serial_menu_echo": true } } diff --git a/porting/drivers/bg96/bg96.cpp b/porting/drivers/bg96/bg96.cpp new file mode 100644 index 0000000..3970c1d --- /dev/null +++ b/porting/drivers/bg96/bg96.cpp @@ -0,0 +1,373 @@ +#include "mbed.h" +#include "mbed_trace.h" + +#include "bg96.h" + +#include "QUECTEL_BG96_CellularInformation.h" +#include "CellularDevice.h" +#include "CellularInformation.h" +#include "QUECTEL_BG96.h" + +#include "boards.h" +//#include "storage.h" +#include + +#define BG96_BAUD_RATE 115200 // baud rate for communicating with BG96 +#define BG96_WAIT_MS_PWR_KEY_ON 500 // amount of milliseconds to hold power key pin low to turn on BG96 +#define BG96_WAIT_MS_PWR_KEY_OFF 650// amount of milliseconds to hold power key pin low to turn off BG96 +#define BG96_WAIT_MS_RESET 150 // amount of milliseconds to hold reset pin low to reset BG96 + +#define TWENTY_FOUR_HOURS_IN_MINS 1440 + +#define TRACE_GROUP "BG96" + +//static Watchdog& watchdog = Watchdog::get_instance(); + +AquiredLock::AquiredLock(Bg96& bg96, std::atomic& counter) : _bg96(bg96), _lock_counter(counter) { + _lock_counter++; +} +AquiredLock::~AquiredLock() { + _lock_counter--; + _bg96.try_safe_power_off(); +} + + +misc::Synchronized* Bg96::get_sync_instance() { + static misc::Synchronized* instance = new misc::Synchronized([](){ + auto serial = new UARTSerial(BT_BG96_UART1_TX, BT_BG96_UART1_RX, BG96_BAUD_RATE); + serial->set_flow_control(SerialBase::RTSCTS, BT_BG96_UART1_RTS, BT_BG96_UART1_CTS); + return serial; + }()); + + return instance; +} + +Bg96::Bg96(FileHandle* fh) : QUECTEL_BG96(fh, BT_BG96_PWRKEY, BT_BG96_PIN_ACT_LVL, BT_BG96_RESET), + gps_antenna_power(BT_GPS_ACT_ANT_EN, !BT_GPS_ACT_ANT_ACT_LVL), + shared_poweron_lock(0) { +} + +Bg96::~Bg96() { +} + +std::unique_ptr Bg96::lock_power_on() { + return std::make_unique(*this, shared_poweron_lock); +} + +void Bg96::power_on() { + + if(isPoweredOn) { + tr_debug("already powered on"); + return; + } + + //watchdog.kick(); + + QUECTEL_BG96::soft_power_on(); + + _at->lock(); + _at->flush(); + _at->set_at_timeout(1000); + + _at->at_cmd_discard("&F0", NULL); // restore AT command settings from NVS + _at->at_cmd_discard("E0", NULL); // disable ECHO mode + _at->at_cmd_discard("+IFC", "=2,2");// enable hardware flow control + + _at->at_cmd_discard("+CMEE", "=2"); // enable error messages + _at->at_cmd_discard("+CFUN", "=0"); // disable both radios + _at->at_cmd_discard("+QGPSEND", NULL);// disable gps + _at->at_cmd_discard("+CTZU", "=1"); // enable automatic timezone updates + _at->at_cmd_discard("+CTZR", "=2"); // enable extended time zone reporting + + _at->at_cmd_discard("+QCFG", "=\"nwscanseq\",010302,1"); // GSM/NB/M1 - RAT order + _at->at_cmd_discard("+QCFG", "=\"nwscanmode\",0,1"); // Enable all RATs + _at->at_cmd_discard("+QCFG", "=\"band\",F,400A0E189F,A0E189F,1");// Any frequncey + _at->at_cmd_discard("+QCFG", "=\"ledmode\",0"); // led flicker mode + + _at->restore_at_timeout(); + _at->unlock(); + isPoweredOn = true; + + //watchdog.kick(); +} + +void Bg96::power_off() { + tr_info("Bg96::power_off"); + if(!isPoweredOn) { + // it has to be powered on to send shutdown command to the modem. + power_on(); + } + //watchdog.kick(); + shutdown(); + gps_antenna_power = !BT_GPS_ACT_ANT_ACT_LVL; + + ThisThread::sleep_for(2000); // Wait before soft_power_off - this seems to be necessary to correctly shutdown modem + nsapi_error_t ret = soft_power_off(); + //nsapi_error_t ret = QUECTEL_BG96::soft_power_off(); + //watchdog.kick(); + + if(ret != NSAPI_ERROR_OK) { + tr_error("did not power off module"); + //QUECTEL_BG96::soft_power_off(); + //watchdog.kick(); + } + + isPoweredOn = false; + isGPSAntennaOn = false; + isGSMRadioOn = false; +} + +void Bg96::try_safe_power_off() { + if(shared_poweron_lock) { + tr_debug("Bg96 power is locked. Power off skipped"); + return; + } + power_off(); +} + +bool Bg96::is_powered_on() { + return isPoweredOn; +} + +void Bg96::enable_gsm() { + + if(!isPoweredOn) { + tr_warn("power must be enabled first"); + return; + } + + _at->lock(); + _at->flush(); + _at->set_at_timeout(1000); + _at->at_cmd_discard("+CFUN", "=1"); + _at->restore_at_timeout(); + _at->unlock(); + + return; +} + +void Bg96::disable_gsm() { + if(!isPoweredOn) { + tr_warn("power must be enabled first"); + return; + } + + _at->lock(); + _at->flush(); + _at->set_at_timeout(15000); + _at->at_cmd_discard("+CFUN", "=0"); + _at->restore_at_timeout(); + _at->unlock(); + return; +} + +void Bg96::enable_gps() { + if(!isPoweredOn) { + tr_warn("power must be enabled first"); + return; + } + + if(isGPSAntennaOn) { + tr_debug("gps antenna already on"); + return; + } + + //watchdog.kick(); + + gps_antenna_power = BT_GPS_ACT_ANT_ACT_LVL;// enable active antenna + + _at->lock(); + _at->flush(); + _at->set_at_timeout(1000); + + _at->at_cmd_discard("+QGPSCFG", "=\"outport\",\"uartnmea\""); + _at->at_cmd_discard("+QGPSCFG", "=\"nmeasrc\",1"); + _at->at_cmd_discard("+QGPSCFG", "=\"gpsnmeatype\",31"); + _at->at_cmd_discard("+QGPSCFG", "=\"glonassnmeatype\",4"); + _at->at_cmd_discard("+QGPSCFG", "=\"galileonmeatype\",0"); + _at->at_cmd_discard("+QGPSCFG", "=\"beidounmeatype\",0"); + _at->at_cmd_discard("+QGPSCFG", "=\"gsvextnmeatype\",1"); + + _at->at_cmd_discard("+QGPSCFG", "=\"autogps\",0"); + // _at->at_cmd_discard("+QGPSDEL", "=0");// delete assitence data (almanac) + // _at->at_cmd_discard("+QGPSDEL", "=3");// delete gps extra data + + _at->at_cmd_discard("+QGPSXTRA", "=1"); + _at->cmd_start_stop("+QGPSXTRADATA", "?");// check status of gps extra data + _at->resp_start("+QGPSXTRADATA:"); + int valid_for = _at->read_int(); + + char injection_time[32]; + int read_size = _at->read_string(injection_time, 32); + tr_debug("gps extra data valid time: %d [min]", valid_for); + tr_debug("gps extra data injection time: %s", read_size > 0 ? injection_time : "N/A"); +#if 0 + if(valid_for < TWENTY_FOUR_HOURS_IN_MINS) { + tr_warn("gps extra data no longer valid"); + Storage* storage = Storage::get_instance(); + storage->download_gps_extra_save(true); + } else { + tr_debug("gps extra data valid for %i more minutes", valid_for); + } +#endif + _at->resp_stop(); + + _at->at_cmd_discard("+QGPS", "=1"); + + _at->restore_at_timeout(); + _at->unlock(); + + isGPSAntennaOn = true; + + //watchdog.kick(); + + return; +} + +bool Bg96::is_gps_enabled() { + return isGPSAntennaOn; +} + +void Bg96::disable_gps() { + if(!(isGPSAntennaOn && isPoweredOn)) { + tr_warn("gps antenna and power must be enabled first"); + } + + gps_antenna_power = !BT_GPS_ACT_ANT_ACT_LVL; + + _at->lock(); + _at->flush(); + _at->set_at_timeout(1000); + _at->at_cmd_discard("+QGPSEND", ""); + _at->restore_at_timeout(); + _at->unlock(); + + isGPSAntennaOn = false; + + return; +} + +nsapi_error_t Bg96::get_sim_iccid(char* sim_iccid, size_t buf_size) { + _at->lock(); + mbed::QUECTEL_BG96_CellularInformation cellular_information(*_at); + nsapi_error_t error = cellular_information.get_iccid(sim_iccid, buf_size); + _at->unlock(); + return error; +} + +bool Bg96::gps_lock(char* gps_lock) { + if(!(isGPSAntennaOn && isPoweredOn)) { + tr_warn("gps antenna and power must be enabled first"); + return false; + } + + _at->lock(); + _at->flush(); + _at->set_at_timeout(1000); + _at->set_stop_tag("\r\n"); + + _at->cmd_start_stop("+QGPSLOC", "=2"); + + _at->resp_start("+QGPSLOC: "); + if(_at->info_resp()) { + _at->set_delimiter(':'); + _at->read_string(gps_lock, BG96_GPS_LOCK_SIZE); + _at->set_default_delimiter(); + } + _at->resp_stop(); + + nsapi_error_t error = _at->get_last_error(); + + _at->restore_at_timeout(); + _at->unlock(); + + return (error == NSAPI_ERROR_OK); +} +#if 0 +nsapi_error_t Bg96::download_file_gps_extra_data(void) { + if(!isPoweredOn) { + tr_warn("power must be enabled first"); + return NSAPI_ERROR_DEVICE_ERROR; + } + + //watchdog.kick(); + + bool download_complete = false; + + _at->lock(); + _at->flush(); + + _at->set_at_timeout(3000); + _at->cmd_start_stop("+QHTTPURL", "=40,3", NULL); + _at->resp_start("CONNECT"); + _at->write_string("http://xtrapath1.izatcloud.net/xtra2.bin", false); + _at->resp_stop(); + + _at->set_at_timeout(80000); + _at->at_cmd_discard("+QHTTPGET", "=80", NULL); + + _at->resp_start("+QHTTPGET:"); + if(_at->info_resp()) { + int http_get_error = _at->read_int(); + int http_status_ret = _at->read_int(); + size_t gps_data_size = _at->read_int(); + tr_info("gps extra data, error: %i, https status: %i, size: %i", http_get_error, http_status_ret, gps_data_size); + download_complete = (http_status_ret == 200); + } else { + tr_error("downloading gps extra data"); + } + + nsapi_error_t error = _at->get_last_error(); + + if(download_complete) { + _at->at_cmd_discard("+QHTTPREADFILE", "=", "%s,%d", "xtra2.bin", 80); + _at->resp_start("+QHTTPREADFILE:"); + _at->info_resp(); + int load_file_status = _at->read_int(); + tr_info("load file status %i", load_file_status); + + time_t current_time = time(NULL); + struct tm* inject_time = gmtime(¤t_time); + char bg96_extra_inject_ts[22]; + strftime(bg96_extra_inject_ts, 22, "%G/%m/%d,%H:%M:%S", inject_time); + // before xdata injection we have to disable gps + _at->at_cmd_discard("+QGPSEND", NULL); + + _at->at_cmd_discard("+QGPSXTRA", "=1", NULL); + _at->at_cmd_discard("+QGPSXTRATIME", "=", "%d,%s,%d,%d,%d", 0, bg96_extra_inject_ts, 1, 0, 5000); + _at->at_cmd_discard("+QGPSXTRADATA", "=", "%s", "UFS:xtra2.bin"); + _at->at_cmd_discard("+QFDEL", "=", "%s", "UFS:xtra2.bin"); + _at->at_cmd_discard("+QGPS", "=1"); + Storage* storage = Storage::get_instance(); + storage->download_gps_extra_save(false); + } + + _at->restore_at_timeout(); + _at->unlock(); + + //watchdog.kick(); + + return error; +} +#endif +nsapi_error_t Bg96::soft_power_off() { + _at->lock(); + _at->cmd_start("AT+QPOWD"); + _at->cmd_stop_read_resp(); + + return _at->unlock_return_error(); +} + +nsapi_error_t Bg96::configure_dns(void) { + _at->lock(); + _at->at_cmd_discard("+QIDNSCFG", "=", "%d", 1); + _at->at_cmd_discard("+QIDNSCFG", "=", "%d,%s,%s", 1, "8.8.8.8", "8.8.4.4"); + _at->at_cmd_discard("+QIGETERROR", "", ""); + return _at->unlock_return_error(); +} + +CellularDevice* CellularDevice::get_default_instance() { + return Bg96::get_sync_instance()->non_sync_block([](auto& bg96) { + return static_cast(&bg96); + }); +} \ No newline at end of file diff --git a/porting/drivers/bg96/bg96.h b/porting/drivers/bg96/bg96.h new file mode 100644 index 0000000..52de4d9 --- /dev/null +++ b/porting/drivers/bg96/bg96.h @@ -0,0 +1,101 @@ +#ifndef BG96_H +#define BG96_H + +#include "QUECTEL_BG96.h" +#include "mbed.h" +#include "platform/NonCopyable.h" +#include "Synchronized.h" +#include +#include + + +#define BG96_GPS_LOCK_SIZE 70 + +typedef struct hardware_info_t { + char model[5]; + char rev[32]; + char imei[16]; + char iccid[20]; +} hardware_info; + +class AquiredLock; + +/** + * @brief LTE and GPS modem class. + */ +class Bg96 : public QUECTEL_BG96, private NonCopyable +{ +public: + static misc::Synchronized* get_sync_instance(); + /** + * @brief power on the modem. Does not care about power lock + */ + void power_on(); + /** + * @brief Creates an AquiredLock for the BG96 modem power switch. + * As long as the returned lock instance is alive, the lock counter will no decrement + * @return unique_ptr to lock instance + */ + std::unique_ptr lock_power_on(); + /** + * @brief power off the modem. Does not care about power lock + */ + void power_off(); + /** + * @brief power off the modem only if power lock is released + */ + void try_safe_power_off(); + bool is_powered_on(); + void enable_gsm(); + void disable_gsm(); + void enable_gps(); + bool is_gps_enabled(); + void disable_gps(); + nsapi_error_t get_sim_iccid(char* sim_iccid, size_t buf_size); + bool gps_lock(char* gps_lock); + nsapi_error_t soft_power_off(); + //nsapi_error_t download_file_gps_extra_data(void); + nsapi_error_t configure_dns(void); + + ~Bg96(); + +private: + Bg96(FileHandle* fh); + + DigitalOut gps_antenna_power; + + UARTSerial* serial_connection; + + bool isPoweredOn; + bool isGPSAntennaOn; + bool isGSMRadioOn; + std::atomic shared_poweron_lock; + + friend class QUECTEL_BG96; + friend class CellularDevice; +}; + +using SynchronizedBg96 = misc::Synchronized; + +/** + * @brief Synchronization class for Bg96. Bg96 is a two-in-one device, a GPS and LTE modem. + * Transmission and Location modules are both using the same devie but in different context, hence + * some of the actions will overlap or will be mutually exclusive, such as powering the modem off. + * Every created instance of the AquiredLock will increment the lock_counter (passed by constructor). + * Every deleted instance will decremented the counter. + * A lock is considered released when counter is equal to 0. + */ +class AquiredLock { + Bg96& _bg96; + std::atomic& _lock_counter; +public: + /** + * @brief Constructor + * @param bg96 BG96 driver + * @param counter users counter. Stored in the BG96 driver. + */ + AquiredLock(Bg96& bg96, std::atomic& counter); + ~AquiredLock(); +}; + +#endif// BG96_H \ No newline at end of file diff --git a/porting/drivers/boards/boards.h b/porting/drivers/boards/boards.h new file mode 100644 index 0000000..e041fdb --- /dev/null +++ b/porting/drivers/boards/boards.h @@ -0,0 +1,23 @@ +/** + * @file boards.h + * @author Danius Kalvaitis (danius@ovon.io) + * @brief Board definitions file + * @date 2020-03-05 + * + * @copyright Copyright (c) 2020 Ovon Technologies Limited + */ + +#ifndef BOARDS_H +#define BOARDS_H + +#if defined(BT_01001_V0_0) +#include "bt_01001_v0_0.h" +#elif defined(BT_01001_V0_1) +#include "bt_01001_v0_1.h" +#elif defined(BT_01001_V0_2) +#include "bt_01001_v0_2.h" +#else +#error Board is not defined! +#endif + +#endif // BOARDS_H diff --git a/porting/drivers/boards/bt_01001_v0_1.h b/porting/drivers/boards/bt_01001_v0_1.h new file mode 100644 index 0000000..8b053fd --- /dev/null +++ b/porting/drivers/boards/bt_01001_v0_1.h @@ -0,0 +1,89 @@ +/** + * @file bt_01001_v0_1.h + * @author Danius Kalvaitis (danius@ovon.io) + * @brief Bulk Tainer BT_01001_V0_1 board description file. + * @date 2020-03-05 + * + * @copyright Copyright (c) 2020 Ovon Technologies Limited + */ + +#ifndef BT_01001_V0_1_H +#define BT_01001_V0_1_H + +#include "PinNames.h" + +// Battery level measurement +#define BT_BATTERY_LVL PA_0 +#define BT_BATTERY_LVL_EN PA_5 + +// MAX31855 +#define BT_MAX31855_CS PA_4 +#define BT_MAX31855_SCK PA_1 +#define BT_MAX31855_MISO PA_11 +#define BT_MAX31855_PWR PD_2 + +// UART port reserved for bootloader +#define BT_BOOT_TX PA_2 +#define BT_BOOT_RX PA_3 + +// BG96 +#define BT_BG96_RESET PB_5 +#define BT_BG96_RESET_ACT_LVL 0 +#define BT_BG96_PWRKEY PB_8 +#define BT_BG96_PWRKEY_ACT_LVL 0 +#define BT_BG96_STATUS PB_9 + +#define BT_BG96_UART1_TX PC_4 +#define BT_BG96_UART1_RX PC_5 +#define BT_BG96_UART1_CTS PA_6 +#define BT_BG96_UART1_DCD PA_12 +#define BT_BG96_UART1_DTR PB_0 +#define BT_BG96_UART1_RTS PB_1 +#define BT_BG96_UART1_RI PB_2 + +#define BT_BG96_UART3_TX PA_9 +#define BT_BG96_UART3_RX PA_10 + +#define BT_GPS_ACT_ANT_EN PA_8 + +// EPEAS +#define BT_EPEAS_STATUS1 PA_7 + +// BLE +#define BT_BLE_RESET PC_6 +#define BT_BLE_SOFT_RESET PC_8 +#define BT_BLE_REQ PC_7 +#define BT_BLE_RDY PC_9 + +#define BT_BLE_CS PA_15 +#define BT_BLE_SCK PC_10 +#define BT_BLE_MISO PC_11 +#define BT_BLE_MOSI PC_12 + +// ISM330 +#define BT_SCL PB_6 +#define BT_SDA PB_7 + +#define BT_ISM330_INT1 PC_13 +#define BT_ISM330_INT2 PH_1 + +#define BT_ISM330_I2C_ADDRESS 0xD4 + +// EINK display +#define BT_DISP_BUSY PB_11 +#define BT_DISP_RESET PB_13 +#define BT_DISP_DC PB_14 + +#define BT_DISP_CS PB_12 +#define BT_DISP_SCK PB_10 +#define BT_DISP_MOSI PB_15 + +// Serial interface for debugging +#define BT_DEBUX_RX PC_0 +#define BT_DEBUX_TX PC_1 + +// Temperature sensor +#define BT_TEMP_POS PC_2 +#define BT_TEMP_NEG PC_3 + +#endif // BT_01001_V0_1_H diff --git a/porting/drivers/boards/bt_01001_v0_2.h b/porting/drivers/boards/bt_01001_v0_2.h new file mode 100644 index 0000000..7ec7573 --- /dev/null +++ b/porting/drivers/boards/bt_01001_v0_2.h @@ -0,0 +1,99 @@ +/** + * @file bt_01001_v0_2.h + * @author Danius Kalvaitis (danius@ovon.io) + * @brief Bulk Tainer BT_01001_V0_2 board description file. + * @date 2020-03-31 + * + * @copyright Copyright (c) 2020 Ovon Technologies Limited + */ + +#ifndef BT_01001_V0_2_H +#define BT_01001_V0_2_H + +#include "PinNames.h" +#include "stm32l4xx_hal.h" +#include "stm32l4xx_hal_pwr_ex.h" + +// QSPI Flash +#define BT_QSPI_SCK PA_3 +#define BT_QSPI_CS PB_11 +#define BT_QSPI_IO0 PB_1 +#define BT_QSPI_IO1 PB_0 +#define BT_QSPI_IO2 PA_7 +#define BT_QSPI_IO3 PA_6 + +// SPI instance share by MAX31855, E-Ink and BLE module +#define BT_SCK PB_10 +#define BT_MISO PC_2 +#define BT_MOSI PC_3 + +// Battery level measurement +#define BT_BATTERY_LVL PA_4 +#define BT_BATTERY_LVL_EN PB_12 + +// MAX31855 +#define BT_MAX31855_CS PB_8 +#define BT_MAX31855_PWR PB_5 + +// UART port reserved for bootloader +#define BT_BOOT_TX PC_10 +#define BT_BOOT_RX PC_11 + +// BG96 +#define BT_BG96_RESET PC_7 +#define BT_BG96_PWRKEY PC_8 +#define BT_BG96_PIN_ACT_LVL 1 + +#define BT_BG96_UART1_TX PA_9 +#define BT_BG96_UART1_RX PA_10 +#define BT_BG96_UART1_CTS PA_11 +#define BT_BG96_UART1_DCD PA_15 +#define BT_BG96_UART1_DTR PB_4 +#define BT_BG96_UART1_RTS PA_12 +#define BT_BG96_UART1_RI PA_8 + +#define BT_BG96_UART3_TX PC_12 +#define BT_BG96_UART3_RX PD_2 + +#define BT_GPS_ACT_ANT_EN PC_6 +#define BT_GPS_ACT_ANT_ACT_LVL 0 + +// EPEAS +#define BT_EPEAS_STATUS1 PC_5 + +// BLE +#define BT_BLE_RESET PB_9 +#define BT_BLE_SOFT_RESET PB_15 +#define BT_BLE_REQ PB_14 +#define BT_BLE_RDY PC_9 + +#define BT_BLE_SLEEP PH_0 +#define BT_BLE_CS PH_1 + +// ISM330 +#define BT_SCL PB_6 +#define BT_SDA PB_7 + +#define BT_ISM330_INT1 PC_13 +#define BT_ISM330_PWR_INT1_PORT PWR_GPIO_C +#define BT_ISM330_PWR_INT1_PIN GPIO_PIN_13 +#define BT_ISM330_PWR_INT1_WKUP_PIN PWR_WAKEUP_PIN2_HIGH +#define BT_ISM330_INT2 PA_0 + +#define BT_ISM330_I2C_ADDRESS 0xD4 + +// EINK display +#define BT_DISP_BUSY PA_5 +#define BT_DISP_RESET PC_4 +#define BT_DISP_DC PB_2 + +#define BT_DISP_CS PB_13 + +// Serial interface for debugging +#define BT_DEBUX_RX PC_0 +#define BT_DEBUX_TX PC_1 + +// Temperature sensor +#define BT_THERMOCOUPLE_SWITCH PA_2 + +#endif // BT_01001_V0_2_H diff --git a/porting/drivers/devices/ITransmissionDevice.h b/porting/drivers/devices/ITransmissionDevice.h new file mode 100644 index 0000000..5a5636a --- /dev/null +++ b/porting/drivers/devices/ITransmissionDevice.h @@ -0,0 +1,20 @@ +#ifndef BTTM_TASKS_ITRANSMISSIONDEVICE_H_INCLUDED +#define BTTM_TASKS_ITRANSMISSIONDEVICE_H_INCLUDED + +class NetworkInterface; + +namespace tasks { +class ITransmissionDevice +{ +public: + virtual bool enable() = 0; + virtual bool disable() = 0; + //virtual void download_gps_extra_data() = 0; + virtual NetworkInterface* get_network_interface() = 0; + + virtual ~ITransmissionDevice() {} +}; + +}// namespace tasks + +#endif diff --git a/porting/drivers/devices/TransmissionDeviceBG96.cpp b/porting/drivers/devices/TransmissionDeviceBG96.cpp new file mode 100644 index 0000000..e397452 --- /dev/null +++ b/porting/drivers/devices/TransmissionDeviceBG96.cpp @@ -0,0 +1,44 @@ +#include "TransmissionDeviceBG96.h" +#include "CellularContext.h" + +namespace tasks { +TransmissionDeviceBG96::TransmissionDeviceBG96(SynchronizedBg96& driver) +: m_bg96{driver} { + +} + +bool TransmissionDeviceBG96::enable() { + m_bg96.sync_block([this](auto& bg96) { + m_power_lock = bg96.lock_power_on(); + if(!bg96.is_powered_on()) { + bg96.power_on(); + } + + bg96.enable_gsm(); + }); + + return true; +} + +bool TransmissionDeviceBG96::disable() { + m_bg96.sync_block([this](auto& bg96) { + if(bg96.is_powered_on()) { + bg96.disable_gsm(); + } + + m_power_lock = nullptr; + }); + return true; +} +#if 0 +void TransmissionDeviceBG96::download_gps_extra_data() { + m_bg96.sync_block([this](auto& bg96) { + bg96.download_file_gps_extra_data(); + }); +} +#endif +NetworkInterface* TransmissionDeviceBG96::get_network_interface() { + return CellularContext::get_default_instance(); +} + +} // namespace tasks \ No newline at end of file diff --git a/porting/drivers/devices/TransmissionDeviceBG96.h b/porting/drivers/devices/TransmissionDeviceBG96.h new file mode 100644 index 0000000..8b9b9b6 --- /dev/null +++ b/porting/drivers/devices/TransmissionDeviceBG96.h @@ -0,0 +1,23 @@ + +#ifndef BTTM_TRANSMISSIONDEVICEBG96_H_INCLUDED +#define BTTM_TRANSMISSIONDEVICEBG96_H_INCLUDED +#include "ITransmissionDevice.h" +#include "bg96.h" +#include + +namespace tasks { + +class TransmissionDeviceBG96 : public ITransmissionDevice { +public: + TransmissionDeviceBG96(SynchronizedBg96& driver); + virtual bool enable() override; + virtual bool disable() override; + //virtual void download_gps_extra_data() override; + virtual NetworkInterface* get_network_interface() override; +private: + SynchronizedBg96& m_bg96; + std::unique_ptr m_power_lock; +}; +} // namespace tasks + +#endif // BTTM_TRANSMISSIONDEVICE_H_INCLUDED diff --git a/porting/misc/Synchronized.h b/porting/misc/Synchronized.h new file mode 100644 index 0000000..2e58d97 --- /dev/null +++ b/porting/misc/Synchronized.h @@ -0,0 +1,59 @@ +#ifndef BTTM_SYNCHRONIZED_H +#define BTTM_SYNCHRONIZED_H +#include +#include + +namespace misc { +/// @brief This class is a wrapper for type T that allows only synchronized access +template +struct Synchronized : private T { + // import all constructors from T + using T::T; + + + /// @brief Start synchronized block and call F in it + /// @param f - piecie of code (function or function object) + /// which will be called in the synchronized block + /// signature of F has to be void (T&) + template + void sync_block(F&& f) { + std::lock_guard lock{mx}; + std::forward(f)(static_cast(*this)); + } + + /// @brief Start synchronized block and call F in it + /// @param f - piecie of code (function or function object) + /// which will be called in the synchronized block + /// signature of F has to be void (T const&) + template + void sync_block(F&& f) const { + std::lock_guard lock{mx}; + std::forward(f)(static_cast(*this)); + } + + + /// @brief Allow nonsynchronized access to wrapped T objet + /// @param f - piecie of code (function or function object) which will be called + /// signature of F has to be R (T&) where R can be void or any other type + /// @return result of f + template + auto non_sync_block(F&& f) { + return std::forward(f)(static_cast(*this)); + } + + /// @brief Allow nonsynchronized access to wrapped T objet + /// @param f - piecie of code (function or function object) which will be called + /// signature of F has to be R (T const&) where R can be void or any other type + /// @return result of f + template + auto non_sync_block(F&& f) const { + return std::forward(f)(static_cast(*this)); + } + +private: + mutable Mutex mx; +}; + +} // namespace misc + +#endif // BTTM_SYNCHRONIZED_H