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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

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(&timestamp);
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