Eric Jung / Mbed OS WIZnet-IoTShield-BG96-Ping
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /* WIZnet IoT Shield Cat.M1 Sample code for Arm MBED
00002  * Copyright (c) 2019 WIZnet Co., Ltd.
00003  * SPDX-License-Identifier: Apache-2.0
00004  */
00005  
00006  /* 
00007  * Licensed under the Apache License, Version 2.0 (the "License");
00008  * you may not use this file except in compliance with the License.
00009  * You may obtain a copy of the License at
00010  *
00011  *     http://www.apache.org/licenses/LICENSE-2.0
00012  *
00013  * Unless required by applicable law or agreed to in writing, software
00014  * distributed under the License is distributed on an "AS IS" BASIS,
00015  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00016  *
00017  * See the License for the specific language governing permissions and
00018  * limitations under the License.
00019  *
00020  */
00021 
00022 
00023 #include <string>
00024 #include "mbed.h"
00025 
00026 #define RET_OK                      1
00027 #define RET_NOK                     -1
00028 #define DEBUG_ENABLE                1
00029 #define DEBUG_DISABLE               0
00030 #define ON                          1
00031 #define OFF                         0
00032 
00033 #define MAX_BUF_SIZE                1024
00034 
00035 #define BG96_APN_PROTOCOL_IPv4      1
00036 #define BG96_APN_PROTOCOL_IPv6      2
00037 #define BG96_DEFAULT_TIMEOUT        1000
00038 #define BG96_CONNECT_TIMEOUT        15000
00039 #define BG96_SEND_TIMEOUT           500
00040 #define BG96_RECV_TIMEOUT           500
00041 
00042 #define BG96_APN_PROTOCOL           BG96_APN_PROTOCOL_IPv6
00043 #define BG96_DEFAULT_BAUD_RATE      115200
00044 #define BG96_PARSER_DELIMITER       "\r\n"
00045 
00046 #define CATM1_APN_SKT               "lte-internet.sktelecom.com"
00047 
00048 #define CATM1_DEVICE_NAME_BG96      "BG96"
00049 #define DEVNAME                     CATM1_DEVICE_NAME_BG96
00050 
00051 #define devlog(f_, ...)             if(CATM1_DEVICE_DEBUG == DEBUG_ENABLE) { pc.printf("\r\n[%s] ", DEVNAME);  pc.printf((f_), ##__VA_ARGS__); }
00052 #define myprintf(f_, ...)           {pc.printf("\r\n[MAIN] ");  pc.printf((f_), ##__VA_ARGS__);}
00053 
00054 /* Pin configuraiton */
00055 // Cat.M1
00056 #define MBED_CONF_IOTSHIELD_CATM1_TX                D8
00057 #define MBED_CONF_IOTSHIELD_CATM1_RX                D2
00058 #define MBED_CONF_IOTSHIELD_CATM1_RESET             D7
00059 #define MBED_CONF_IOTSHIELD_CATM1_PWRKEY            D9
00060 
00061 // Sensors
00062 #define MBED_CONF_IOTSHIELD_SENSOR_CDS              A0
00063 #define MBED_CONF_IOTSHIELD_SENSOR_TEMP             A1
00064 
00065 /* Debug message settings */
00066 #define BG96_PARSER_DEBUG           DEBUG_DISABLE
00067 #define CATM1_DEVICE_DEBUG          DEBUG_ENABLE 
00068 
00069 // Functions: Module Status
00070 void waitCatM1Ready(void);
00071 int8_t setEchoStatus_BG96(bool onoff);
00072 int8_t getUsimStatus_BG96(void);
00073 int8_t getNetworkStatus_BG96(void);
00074 int8_t checknSetApn_BG96(const char * apn);
00075 int8_t getFirmwareVersion_BG96(char * version);
00076 
00077 // Functions: PDP context
00078 int8_t setContextActivate_BG96(void);   // Activate a PDP Context
00079 int8_t setContextDeactivate_BG96(void); // Deactivate a PDP Context
00080 int8_t getIpAddress_BG96(char * ipstr);
00081 
00082 // Functions: Ping test
00083 void printPingToHost_BG96(char * host, int timeout, int pingnum);
00084 
00085 // Example: Ping destinations
00086 char ping_dest_1st[] = "8.8.8.8";
00087 char ping_dest_2nd[] = "www.google.com";
00088 
00089 
00090 Serial pc(USBTX, USBRX);    // USB debug
00091 
00092 UARTSerial *_serial;        // Cat.M1 module    
00093 ATCmdParser *_parser;
00094 
00095 DigitalOut _RESET_BG96(MBED_CONF_IOTSHIELD_CATM1_RESET);
00096 DigitalOut _PWRKEY_BG96(MBED_CONF_IOTSHIELD_CATM1_PWRKEY);
00097 
00098 void serialPcInit(void)
00099 {
00100     pc.baud(115200);
00101     pc.format(8, Serial::None, 1);
00102 }
00103 
00104 void serialDeviceInit(PinName tx, PinName rx, int baudrate) 
00105 {        
00106     _serial = new UARTSerial(tx, rx, baudrate);    
00107 }
00108 
00109 void serialAtParserInit(const char *delimiter, bool debug_en)
00110 {
00111     _parser = new ATCmdParser(_serial);    
00112     _parser->debug_on(debug_en);
00113     _parser->set_delimiter(delimiter);    
00114     _parser->set_timeout(BG96_DEFAULT_TIMEOUT);
00115 }
00116 
00117 void catm1DeviceInit(void)
00118 {
00119     serialDeviceInit(   MBED_CONF_IOTSHIELD_CATM1_TX, 
00120                         MBED_CONF_IOTSHIELD_CATM1_RX, 
00121                         BG96_DEFAULT_BAUD_RATE);
00122                         
00123     serialAtParserInit( BG96_PARSER_DELIMITER, 
00124                         BG96_PARSER_DEBUG);
00125 }
00126 
00127 void catm1DeviceReset_BG96(void)
00128 {
00129     _RESET_BG96 = 1;
00130     _PWRKEY_BG96 = 1;
00131     wait_ms(300);
00132     
00133     _RESET_BG96 = 0;
00134     _PWRKEY_BG96 = 0;
00135     wait_ms(400);
00136     
00137     _RESET_BG96 = 1;    
00138     wait_ms(1000);
00139 }
00140 
00141 // ----------------------------------------------------------------
00142 // Main routine
00143 // ----------------------------------------------------------------
00144 
00145 int main()
00146 {
00147     serialPcInit();    
00148     catm1DeviceInit();
00149     
00150     myprintf("Waiting for Cat.M1 Module Ready...\r\n");
00151     
00152     catm1DeviceReset_BG96();
00153     
00154     waitCatM1Ready();
00155     
00156     wait_ms(5000);
00157             
00158     myprintf("System Init Complete\r\n");
00159         
00160     myprintf("WIZnet IoT Shield for Arm MBED");
00161     myprintf("LTE Cat.M1 Version");
00162     myprintf("=================================================");
00163     myprintf(">> Target Board: WIoT-QC01 (Quectel BG96)");
00164     myprintf(">> Sample Code: Ping Test");
00165     myprintf("=================================================\r\n");
00166     
00167     setEchoStatus_BG96(OFF);
00168    
00169     getUsimStatus_BG96();
00170     
00171     getNetworkStatus_BG96();
00172     
00173     checknSetApn_BG96(CATM1_APN_SKT);
00174     
00175     setContextActivate_BG96();  
00176     
00177     myprintf("[Ping] Host: %s\r\n", ping_dest_1st);
00178     printPingToHost_BG96(ping_dest_1st, 2, 4);    
00179     
00180     wait_ms(2000);
00181     
00182     myprintf("[Ping] Host: %s\r\n", ping_dest_2nd);
00183     printPingToHost_BG96(ping_dest_2nd, 2, 4);
00184         
00185     setContextDeactivate_BG96(); 
00186 }
00187 
00188 // ----------------------------------------------------------------
00189 // Functions: Cat.M1 Status
00190 // ----------------------------------------------------------------
00191 
00192 void waitCatM1Ready(void)
00193 {
00194     while(1) 
00195     {   
00196         if(_parser->recv("RDY")) 
00197         {
00198             myprintf("BG96 ready\r\n");
00199             return ;
00200         }
00201         else if(_parser->send("AT") && _parser->recv("OK"))
00202         {
00203             myprintf("BG96 already available\r\n");
00204             return ;
00205         }        
00206     }        
00207 }
00208 
00209 int8_t setEchoStatus_BG96(bool onoff)
00210 {
00211     int8_t ret = RET_NOK;
00212     char _buf[10];        
00213     
00214     sprintf((char *)_buf, "ATE%d", onoff);    
00215     
00216     if(_parser->send(_buf) && _parser->recv("OK")) {        
00217         devlog("Turn Echo %s success\r\n", onoff?"ON":"OFF");
00218         ret = RET_OK;
00219     } else { 
00220         devlog("Turn Echo %s failed\r\n", onoff?"ON":"OFF");
00221     }    
00222     return ret;
00223 }
00224  
00225 int8_t getUsimStatus_BG96(void)
00226 {
00227     int8_t ret = RET_NOK;
00228     
00229     _parser->send("AT+CPIN?");    
00230     if(_parser->recv("+CPIN: READY") && _parser->recv("OK")) {
00231         devlog("USIM Status: READY\r\n");
00232         ret = RET_OK;
00233     } else { 
00234         devlog("Retrieving USIM Status failed\r\n");        
00235     }
00236     return ret;
00237 }
00238 
00239 int8_t getNetworkStatus_BG96(void)
00240 {
00241     int8_t ret = RET_NOK;    
00242     
00243     if(_parser->send("AT+QCDS") && _parser->recv("+QCDS: \"SRV\"") && _parser->recv("OK")) {
00244         devlog("Network Status: attached\r\n");
00245         ret = RET_OK;
00246     } else if (_parser->send("AT+QCDS") && _parser->recv("+QCDS: \"LIMITED\"") && _parser->recv("OK")) {
00247         devlog("Network Status: limited\r\n");
00248         ret = RET_OK;    
00249     } else { 
00250         devlog("Network Status: Error\r\n");        
00251     }
00252     return ret;
00253 }
00254 
00255 int8_t checknSetApn_BG96(const char * apn) // Configure Parameters of a TCP/IP Context
00256 {       
00257     char resp_str[100];
00258     
00259     uint16_t i = 0;
00260     char * search_pt;
00261     
00262     memset(resp_str, 0, sizeof(resp_str));
00263     
00264     devlog("Checking APN...\r\n");
00265     
00266     _parser->send("AT+QICSGP=1");
00267     
00268     while(1)
00269     {
00270         _parser->read(&resp_str[i++], 1);        
00271         search_pt = strstr(resp_str, "OK\r\n");
00272         if (search_pt != 0)
00273         {
00274             break;
00275         }
00276     }
00277     
00278     search_pt = strstr(resp_str, apn);
00279     if (search_pt == 0)
00280     {
00281         devlog("Mismatched APN: %s\r\n", resp_str);
00282         devlog("Storing APN %s...\r\n", apn);
00283         if(!(_parser->send("AT+QICSGP=1,%d,\"%s\",\"\",\"\",0", BG96_APN_PROTOCOL, apn) && _parser->recv("OK")))
00284         {
00285             return RET_NOK; // failed
00286         }
00287     }    
00288     devlog("APN Check Done\r\n");
00289         
00290     return RET_OK;
00291 }
00292 
00293 int8_t getFirmwareVersion_BG96(char * version)
00294 {
00295     int8_t ret = RET_NOK;
00296     
00297     if(_parser->send("AT+QGMR") && _parser->recv("%s\n", version) && _parser->recv("OK"))
00298     {           
00299         ret = RET_OK;
00300     } 
00301     return ret;
00302 }
00303 
00304 int8_t getImeiNumber_BG96(char * imei)
00305 {
00306     int8_t ret = RET_NOK;    
00307     
00308     if(_parser->send("AT+CGSN") && _parser->recv("%s\n", imei) && _parser->recv("OK"))
00309     { 
00310         ret = RET_OK;
00311     } 
00312     return ret;
00313 }
00314 
00315 // ----------------------------------------------------------------
00316 // Functions: Cat.M1 DNS
00317 // ----------------------------------------------------------------
00318 
00319 int8_t getIpAddressByName_BG96(const char * name, char * ipstr)
00320 {
00321     char buf2[50];
00322     bool ok;
00323     int  err, ipcount, dnsttl;
00324 
00325     int8_t ret = RET_NOK;
00326 
00327     ok = ( _parser->send("AT+QIDNSGIP=1,\"%s\"", name)
00328             && _parser->recv("OK") 
00329             && _parser->recv("+QIURC: \"dnsgip\",%d,%d,%d", &err, &ipcount, &dnsttl) 
00330             && err==0 
00331             && ipcount > 0
00332         ); 
00333 
00334     if( ok ) {        
00335         _parser->recv("+QIURC: \"dnsgip\",\"%[^\"]\"", ipstr);       //use the first DNS value
00336         for( int i=0; i<ipcount-1; i++ )
00337             _parser->recv("+QIURC: \"dnsgip\",\"%[^\"]\"", buf2);   //and discrard the rest  if >1 
00338             
00339         ret = RET_OK;    
00340     }        
00341     return ret;           
00342 }
00343 
00344 // ----------------------------------------------------------------
00345 // Functions: Cat.M1 PDP context activate / deactivate
00346 // ----------------------------------------------------------------
00347 
00348 int8_t setContextActivate_BG96(void) // Activate a PDP Context
00349 {
00350     int8_t ret = RET_NOK;
00351     
00352     _parser->send("AT+QIACT=1");    
00353     if(_parser->recv("OK")) {
00354         devlog("Activate a PDP Context\r\n");
00355         ret = RET_OK;
00356     } else { 
00357         devlog("PDP Context Activation failed\r\n");        
00358     }
00359     return ret;
00360 }
00361 
00362 int8_t setContextDeactivate_BG96(void) // Deactivate a PDP Context
00363 {
00364     int8_t ret = RET_NOK;
00365     
00366     _parser->send("AT+QIDEACT=1");    
00367     if(_parser->recv("OK")) {
00368         devlog("Deactivate a PDP Context\r\n");
00369         ret = RET_OK;
00370     } else { 
00371         devlog("PDP Context Deactivation failed\r\n");        
00372     }
00373     return ret;
00374 }
00375 
00376 
00377 int8_t getIpAddress_BG96(char * ipstr) // IPv4 or IPv6
00378 {
00379     int8_t ret = RET_NOK;    
00380     int id, state, type; // not used    
00381 
00382     _parser->send("AT+QIACT?");
00383     if(_parser->recv("+QIACT: %d,%d,%d,\"%[^\"]\"", &id, &state, &type, ipstr)
00384         && _parser->recv("OK")) {        
00385         ret = RET_OK;
00386     } 
00387     return ret;
00388 }
00389 
00390 // ----------------------------------------------------------------
00391 // Functions: Cat.M1 Ping test
00392 // ----------------------------------------------------------------
00393 
00394 void printPingToHost_BG96(char * host, int timeout, int pingnum)
00395 {   
00396     int i;
00397     char resp_str[50] = {0, };
00398     
00399     if((timeout < 1) || (timeout > 255)) {
00400         devlog("Ping timeout range is 1-255, and the default value is 4 (unit: sec)\r\n");
00401         return;
00402     }
00403     
00404     if((pingnum < 1) || (pingnum > 10)) {
00405         devlog("The maximum number of sending Ping request range is 1-10, and the default value is 4\r\n");
00406         return;
00407     }
00408        
00409     _parser->set_timeout((1000 * timeout) + 2000);
00410     
00411     if(_parser->send("AT+QPING=%d,\"%s\",%d,%d", 1, host, timeout, pingnum) && _parser->recv("OK")) {        
00412         for(i = 0; i < (pingnum); i++) {            
00413             _parser->recv("+QPING: %s\n", resp_str);
00414             devlog("%s: %s\r\n", host, resp_str);
00415         }
00416         
00417     }
00418     
00419     _parser->set_timeout(BG96_DEFAULT_TIMEOUT);
00420     _parser->flush();
00421 }