Implementation of the CellularInterface for u-blox C027 and C030 (non-N2xx flavour) modems that uses the IP stack on-board the cellular modem, hence not requiring LWIP (and so less RAM) and allowing any AT command exchanges to be carried out at the same time as data transfers (since the modem remains in AT mode all the time). This library may be used from mbed 5.5 onwards. If you need to use SMS, USSD or access the modem file system at the same time as using the CellularInterface then use ublox-at-cellular-interface-ext instead.
Dependents: example-ublox-cellular-interface example-ublox-cellular-interface_r410M example-ublox-mbed-client example-ublox-cellular-interface ... more
main.cpp
00001 #include "UbloxATCellularInterface.h" 00002 #include "greentea-client/test_env.h" 00003 #include "unity.h" 00004 #include "utest.h" 00005 #include "UDPSocket.h" 00006 #include "mbed_stats.h" 00007 #ifdef FEATURE_COMMON_PAL 00008 #include "mbed_trace.h" 00009 #define TRACE_GROUP "TEST" 00010 #else 00011 #define tr_debug(format, ...) debug(format "\n", ## __VA_ARGS__) 00012 #define tr_info(format, ...) debug(format "\n", ## __VA_ARGS__) 00013 #define tr_warn(format, ...) debug(format "\n", ## __VA_ARGS__) 00014 #define tr_error(format, ...) debug(format "\n", ## __VA_ARGS__) 00015 #endif 00016 00017 using namespace utest::v1; 00018 00019 // IMPORTANT!!! if you make a change to the tests here you should 00020 // check whether the same change should be made to the tests under 00021 // the PPP interface. 00022 00023 // NOTE: these test are only as reliable as UDP across the internet 00024 // over a radio link. The tests expect an NTP server to respond 00025 // to UDP packets and, if configured, an echo server to respond 00026 // to UDP packets. This simply may not happen. Please be patient. 00027 00028 // ---------------------------------------------------------------- 00029 // COMPILE-TIME MACROS 00030 // ---------------------------------------------------------------- 00031 00032 // These macros can be overridden with an mbed_app.json file and 00033 // contents of the following form: 00034 // 00035 //{ 00036 // "config": { 00037 // "default-pin": { 00038 // "value": "\"1234\"" 00039 // } 00040 //} 00041 // 00042 // See the template_mbed_app.txt in this directory for a fuller example. 00043 00044 // Whether we can do the mbed stats tests or not 00045 #ifndef MBED_HEAP_STATS_ENABLED 00046 # define MBED_HEAP_STATS_ENABLED 0 00047 #endif 00048 00049 // Whether debug trace is on 00050 #ifndef MBED_CONF_APP_DEBUG_ON 00051 # define MBED_CONF_APP_DEBUG_ON false 00052 #endif 00053 00054 // The credentials of the SIM in the board. 00055 #ifndef MBED_CONF_APP_DEFAULT_PIN 00056 // Note: if PIN is enabled on your SIM, or you wish to run the SIM PIN change 00057 // tests, you must define the PIN for your SIM (see note above on using 00058 // mbed_app.json to do so). 00059 # define MBED_CONF_APP_DEFAULT_PIN "0000" 00060 #endif 00061 #ifndef MBED_CONF_APP_APN 00062 # define MBED_CONF_APP_APN NULL 00063 #endif 00064 #ifndef MBED_CONF_APP_USERNAME 00065 # define MBED_CONF_APP_USERNAME NULL 00066 #endif 00067 #ifndef MBED_CONF_APP_PASSWORD 00068 # define MBED_CONF_APP_PASSWORD NULL 00069 #endif 00070 00071 // Servers and ports 00072 #ifndef MBED_CONF_APP_NTP_SERVER 00073 # define MBED_CONF_APP_NTP_SERVER "2.pool.ntp.org" 00074 #else 00075 # ifndef MBED_CONF_APP_NTP_PORT 00076 # error "MBED_CONF_APP_NTP_PORT must be defined if MBED_CONF_APP_NTP_SERVER is defined" 00077 # endif 00078 #endif 00079 #ifndef MBED_CONF_APP_NTP_PORT 00080 # define MBED_CONF_APP_NTP_PORT 123 00081 #endif 00082 00083 // UDP packet size limit for testing 00084 #ifndef MBED_CONF_APP_UDP_MAX_PACKET_SIZE 00085 # define MBED_CONF_APP_UDP_MAX_PACKET_SIZE 1024 00086 #endif 00087 00088 // The number of retries for UDP exchanges 00089 #define NUM_UDP_RETRIES 5 00090 00091 // ---------------------------------------------------------------- 00092 // PRIVATE VARIABLES 00093 // ---------------------------------------------------------------- 00094 00095 #ifdef FEATURE_COMMON_PAL 00096 // Lock for debug prints 00097 static Mutex mtx; 00098 #endif 00099 00100 // Connection flag 00101 static bool connection_has_gone_down = false; 00102 00103 // ---------------------------------------------------------------- 00104 // PRIVATE FUNCTIONS 00105 // ---------------------------------------------------------------- 00106 00107 #ifdef FEATURE_COMMON_PAL 00108 // Locks for debug prints 00109 static void lock() 00110 { 00111 mtx.lock(); 00112 } 00113 00114 static void unlock() 00115 { 00116 mtx.unlock(); 00117 } 00118 #endif 00119 00120 // Callback in case the connection goes down 00121 static void connection_down_cb(nsapi_error_t err) 00122 { 00123 connection_has_gone_down = true; 00124 } 00125 00126 // Get NTP time from a socket 00127 static void do_ntp_sock (UDPSocket *sock, SocketAddress ntp_address) 00128 { 00129 char ntp_values[48] = { 0 }; 00130 time_t timestamp = 0; 00131 int len; 00132 bool comms_done = false; 00133 00134 ntp_values[0] = '\x1b'; 00135 00136 // Retry this a few times, don't want to fail due to a flaky link 00137 for (unsigned int x = 0; !comms_done && (x < NUM_UDP_RETRIES); x++) { 00138 sock->sendto(ntp_address, (void*) ntp_values, sizeof(ntp_values)); 00139 len = sock->recvfrom(&ntp_address, (void*) ntp_values, sizeof(ntp_values)); 00140 if (len > 0) { 00141 comms_done = true; 00142 } 00143 } 00144 TEST_ASSERT (comms_done); 00145 00146 tr_debug("UDP: %d byte(s) returned by NTP server.", len); 00147 if (len >= 43) { 00148 struct tm *localTime; 00149 time_t TIME1970 = 2208988800U; 00150 timestamp |= ((int) *(ntp_values + 40)) << 24; 00151 timestamp |= ((int) *(ntp_values + 41)) << 16; 00152 timestamp |= ((int) *(ntp_values + 42)) << 8; 00153 timestamp |= ((int) *(ntp_values + 43)); 00154 timestamp -= TIME1970; 00155 srand (timestamp); 00156 tr_debug("srand() called"); 00157 localTime = localtime(×tamp); 00158 if (localTime) { 00159 char timeString[25]; 00160 if (strftime(timeString, sizeof(timeString), "%a %b %d %H:%M:%S %Y", localTime) > 0) { 00161 printf("NTP timestamp is %s.\n", timeString); 00162 } 00163 } 00164 } 00165 } 00166 00167 // Get NTP time 00168 static void do_ntp(UbloxATCellularInterface *interface) 00169 { 00170 UDPSocket sock; 00171 SocketAddress host_address; 00172 00173 TEST_ASSERT(sock.open(interface) == 0) 00174 00175 TEST_ASSERT(interface->gethostbyname(MBED_CONF_APP_NTP_SERVER, &host_address) == 0); 00176 host_address.set_port(MBED_CONF_APP_NTP_PORT); 00177 00178 tr_debug("UDP: NIST server %s address: %s on port %d.", MBED_CONF_APP_NTP_SERVER, 00179 host_address.get_ip_address(), host_address.get_port()); 00180 00181 sock.set_timeout(10000); 00182 00183 do_ntp_sock(&sock, host_address); 00184 00185 sock.close(); 00186 } 00187 00188 // Use a connection, checking that it is good 00189 static void use_connection(UbloxATCellularInterface *interface) 00190 { 00191 const char * ip_address = interface->get_ip_address (); 00192 const char * net_mask = interface->get_netmask (); 00193 const char * gateway = interface->get_gateway (); 00194 00195 TEST_ASSERT(interface->is_connected()); 00196 00197 TEST_ASSERT(ip_address != NULL); 00198 tr_debug ("IP address %s.", ip_address); 00199 TEST_ASSERT(net_mask == NULL); 00200 tr_debug ("Net mask %s.", net_mask); 00201 TEST_ASSERT(gateway != NULL); 00202 tr_debug ("Gateway %s.", gateway); 00203 00204 do_ntp(interface); 00205 TEST_ASSERT(!connection_has_gone_down); 00206 } 00207 00208 // Drop a connection and check that it has dropped 00209 static void drop_connection(UbloxATCellularInterface *interface) 00210 { 00211 TEST_ASSERT(interface->disconnect() == 0); 00212 TEST_ASSERT(connection_has_gone_down); 00213 connection_has_gone_down = false; 00214 TEST_ASSERT(!interface->is_connected()); 00215 } 00216 00217 // ---------------------------------------------------------------- 00218 // TESTS 00219 // ---------------------------------------------------------------- 00220 00221 // Test that sleep is possible both 00222 // before and after running the driver. 00223 void test_sleep() { 00224 TEST_ASSERT(sleep_manager_can_deep_sleep() == true); 00225 00226 // Create an instance of the cellular interface 00227 UbloxATCellularInterface *interface = 00228 new UbloxATCellularInterface(MDMTXD, MDMRXD, 00229 MBED_CONF_UBLOX_CELL_BAUD_RATE, 00230 MBED_CONF_APP_DEBUG_ON); 00231 interface->connection_status_cb(connection_down_cb); 00232 00233 // Use it 00234 #ifdef TARGET_UBLOX_C030_R41XM 00235 int mno_profile; 00236 if (interface->init(MBED_CONF_APP_DEFAULT_PIN) == false) //init can return false if profile set is SW_DEFAULT 00237 { 00238 TEST_ASSERT(interface->get_mno_profile(&mno_profile)); 00239 if (mno_profile == UbloxATCellularInterface::SW_DEFAULT) { 00240 TEST_ASSERT(interface->set_mno_profile(UbloxATCellularInterface::STANDARD_EU)); 00241 TEST_ASSERT(interface->reboot_modem()); 00242 tr_debug("Reboot successful\n"); 00243 hisThread::sleep_for(5000); 00244 } 00245 } 00246 TEST_ASSERT(interface->init(MBED_CONF_APP_DEFAULT_PIN)); 00247 00248 TEST_ASSERT(interface->disable_power_saving_mode()); 00249 #else 00250 TEST_ASSERT(interface->init(MBED_CONF_APP_DEFAULT_PIN)); 00251 #endif 00252 TEST_ASSERT(interface->connect(MBED_CONF_APP_DEFAULT_PIN, MBED_CONF_APP_APN, 00253 MBED_CONF_APP_USERNAME, MBED_CONF_APP_PASSWORD) == 0); 00254 use_connection(interface); 00255 TEST_ASSERT(sleep_manager_can_deep_sleep() == false); 00256 drop_connection(interface); 00257 00258 // Destroy the instance 00259 delete interface; 00260 00261 TEST_ASSERT(sleep_manager_can_deep_sleep() == true); 00262 } 00263 00264 // Test that if communication with the modem 00265 // fails for some reason that sleeping is possible 00266 // afterwards (specific case found by Rostyslav Y.) 00267 void test_sleep_failed_connection() { 00268 00269 TEST_ASSERT(sleep_manager_can_deep_sleep() == true); 00270 00271 // Create a bad instance of the cellular interface 00272 UbloxATCellularInterface *interface = 00273 new UbloxATCellularInterface(MDMTXD, MDMRXD, 00274 20, /* Silly baud rate */ 00275 MBED_CONF_APP_DEBUG_ON); 00276 00277 // [Fail to] use it 00278 TEST_ASSERT_FALSE(interface->init(MBED_CONF_APP_DEFAULT_PIN)); 00279 TEST_ASSERT(interface->connect(MBED_CONF_APP_DEFAULT_PIN, MBED_CONF_APP_APN, 00280 MBED_CONF_APP_USERNAME, MBED_CONF_APP_PASSWORD) != NSAPI_ERROR_OK); 00281 // Destroy the instance 00282 delete interface; 00283 00284 TEST_ASSERT(sleep_manager_can_deep_sleep() == true); 00285 } 00286 00287 #if MBED_HEAP_STATS_ENABLED 00288 // Test for memory leaks. 00289 void test_memory_leak() { 00290 00291 mbed_stats_heap_t heap_stats_start; 00292 mbed_stats_heap_t heap_stats; 00293 00294 mbed_stats_heap_get(&heap_stats_start); 00295 00296 // Create an instance of the cellular interface 00297 UbloxATCellularInterface *interface = 00298 new UbloxATCellularInterface(MDMTXD, MDMRXD, 00299 MBED_CONF_UBLOX_CELL_BAUD_RATE, 00300 MBED_CONF_APP_DEBUG_ON); 00301 interface->connection_status_cb(connection_down_cb); 00302 00303 // Use it 00304 TEST_ASSERT(interface->init(MBED_CONF_APP_DEFAULT_PIN)); 00305 TEST_ASSERT(interface->connect(MBED_CONF_APP_DEFAULT_PIN, MBED_CONF_APP_APN, 00306 MBED_CONF_APP_USERNAME, MBED_CONF_APP_PASSWORD) == 0); 00307 mbed_stats_heap_get(&heap_stats); 00308 TEST_ASSERT(heap_stats.current_size > heap_stats_start.current_size); 00309 use_connection(interface); 00310 drop_connection(interface); 00311 00312 // Destroy the instance 00313 delete interface; 00314 00315 mbed_stats_heap_get(&heap_stats); 00316 TEST_ASSERT(heap_stats.current_size == heap_stats_start.current_size); 00317 } 00318 #endif 00319 00320 // ---------------------------------------------------------------- 00321 // TEST ENVIRONMENT 00322 // ---------------------------------------------------------------- 00323 00324 // Setup the test environment 00325 utest::v1::status_t test_setup(const size_t number_of_cases) { 00326 // Setup Greentea with a timeout 00327 GREENTEA_SETUP(300, "default_auto"); 00328 return verbose_test_setup_handler(number_of_cases); 00329 } 00330 00331 // IMPORTANT!!! if you make a change to the tests here you should 00332 // check whether the same change should be made to the tests under 00333 // the PPP interface. 00334 00335 // Test cases 00336 Case cases[] = { 00337 Case("Sleep test", test_sleep), 00338 Case("Sleep test with failed modem comms", test_sleep_failed_connection) 00339 #if MBED_HEAP_STATS_ENABLED 00340 , Case("Memory leak test", test_memory_leak) 00341 #endif 00342 }; 00343 00344 Specification specification(test_setup, cases); 00345 00346 // ---------------------------------------------------------------- 00347 // MAIN 00348 // ---------------------------------------------------------------- 00349 00350 int main() { 00351 00352 #ifdef FEATURE_COMMON_PAL 00353 mbed_trace_init(); 00354 00355 mbed_trace_mutex_wait_function_set(lock); 00356 mbed_trace_mutex_release_function_set(unlock); 00357 #endif 00358 00359 // Run tests 00360 return !Harness::run(specification); 00361 } 00362 00363 // End Of File
Generated on Thu Jul 21 2022 04:10:53 by 1.7.2