BG96 Cat.M1 PSM setting sample for WIZnet IoT Shield

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 
00070 // Functions: Module Status
00071 void waitCatM1Ready(void);
00072 int8_t setEchoStatus_BG96(bool onoff);
00073 int8_t getUsimStatus_BG96(void);
00074 int8_t getNetworkStatus_BG96(void);
00075 int8_t checknSetApn_BG96(const char * apn);
00076 int8_t getFirmwareVersion_BG96(char * version);
00077 
00078 // Functions: PSM (Power Saving Mode)
00079 int8_t setPsmActivate_BG96(char * Requested_Periodic_TAU, char * Requested_Active_Time);
00080 int8_t setPsmDeactivate_BG96(void);
00081 int8_t getPsmSetting_BG96(bool * enable, int * Requested_Periodic_TAU, int * Requested_Active_Time);
00082 
00083 // Functions: Network time
00084 int8_t getNetworkTimeGMT_BG96(char * timestr);
00085 int8_t getNetworkTimeLocal_BG96(char * timestr);
00086 void setFlagGettime(void);
00087 void clearFlagGettime(void);
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 Ticker flip;
00099 bool flag_gettime = false;
00100 
00101 void serialPcInit(void)
00102 {
00103     pc.baud(115200);
00104     pc.format(8, Serial::None, 1);
00105 }
00106 
00107 void serialDeviceInit(PinName tx, PinName rx, int baudrate) 
00108 {        
00109     _serial = new UARTSerial(tx, rx, baudrate);    
00110 }
00111 
00112 void serialAtParserInit(const char *delimiter, bool debug_en)
00113 {
00114     _parser = new ATCmdParser(_serial);    
00115     _parser->debug_on(debug_en);
00116     _parser->set_delimiter(delimiter);    
00117     _parser->set_timeout(BG96_DEFAULT_TIMEOUT);
00118 }
00119 
00120 void catm1DeviceInit(void)
00121 {
00122     serialDeviceInit(   MBED_CONF_IOTSHIELD_CATM1_TX, 
00123                         MBED_CONF_IOTSHIELD_CATM1_RX, 
00124                         BG96_DEFAULT_BAUD_RATE);
00125                         
00126     serialAtParserInit( BG96_PARSER_DELIMITER, 
00127                         BG96_PARSER_DEBUG);
00128 }
00129 
00130 void catm1DeviceReset_BG96(void)
00131 {
00132     _RESET_BG96 = 1;
00133     _PWRKEY_BG96 = 1;
00134     wait_ms(300);
00135     
00136     _RESET_BG96 = 0;
00137     _PWRKEY_BG96 = 0;
00138     wait_ms(400);
00139     
00140     _RESET_BG96 = 1;    
00141     wait_ms(1000);
00142 }
00143 
00144 
00145 // ----------------------------------------------------------------
00146 // Main routine
00147 // ----------------------------------------------------------------
00148 
00149 int main()
00150 {
00151     serialPcInit();    
00152     catm1DeviceInit();
00153     
00154     myprintf("Waiting for Cat.M1 Module Ready...\r\n");
00155     
00156     catm1DeviceReset_BG96();
00157     
00158     waitCatM1Ready();
00159     
00160     wait_ms(5000);
00161             
00162     myprintf("System Init Complete\r\n");
00163         
00164     myprintf("WIZnet IoT Shield for Arm MBED");
00165     myprintf("LTE Cat.M1 Version");
00166     myprintf("=================================================");
00167     myprintf(">> Target Board: WIoT-QC01 (Quectel BG96)");
00168     myprintf(">> Sample Code: PSM (Power Saving Mode)");
00169     myprintf("=================================================\r\n");
00170     
00171     setEchoStatus_BG96(OFF);
00172    
00173     getUsimStatus_BG96();
00174     
00175     getNetworkStatus_BG96();
00176     
00177     checknSetApn_BG96(CATM1_APN_SKT);
00178     
00179     Timer t;
00180     float elapsed_time_sec = 0;       
00181     bool psm_en = false;
00182     int psm_tau = 0;
00183     int psm_active = 0;
00184     
00185     // PSM enable
00186 #if 0    
00187     setPsmDeactivate_BG96();
00188 #endif    
00189     if(getPsmSetting_BG96(&psm_en, &psm_tau, &psm_active) == RET_OK) {
00190         if(psm_en != true) {
00191             if(setPsmActivate_BG96("10100101", "00100100") == RET_OK) {
00192                 myprintf("Cat.M1 PSM enable, Device reboot");
00193                 
00194                 // Cat.M1 reboot
00195                 catm1DeviceReset_BG96();
00196                 waitCatM1Ready();
00197             } else {
00198                 myprintf("Cat.M1 PSM enable failed");
00199             }            
00200         }
00201     }
00202     
00203     myprintf("Cat.M1 PSM Config: %s, TAU time: %dsec, Active time: %dsec", psm_en?"Enabled":"Disabled", psm_tau, psm_active);
00204     
00205     // Timer event callback       
00206     flip.attach(callback(&setFlagGettime), 1.0);
00207 
00208     while(1)
00209     {
00210         if(flag_gettime) {
00211             char nettime[30] = {0, };
00212             if(getNetworkTimeLocal_BG96(nettime) == RET_OK) {
00213                 if(elapsed_time_sec > 0) {
00214                     t.stop();
00215                     myprintf("Cat.M1 Active, Sleep time: %.2fsec", elapsed_time_sec);                    
00216                     elapsed_time_sec = 0;   
00217                 }                
00218                 myprintf("%s", nettime);
00219             } else {
00220                 if(elapsed_time_sec == 0) {                    
00221                     t.start();         
00222                     myprintf("%s", "Sleep Start");               
00223                 }
00224                 elapsed_time_sec = t.read();
00225                 myprintf("Cat.M1 PSM, %.2f", elapsed_time_sec);               
00226             }
00227             clearFlagGettime();
00228         }
00229     }
00230            
00231     /*    
00232     // Set HTTP request URL
00233     if(setHttpRequest_BG96(request_url, strlen(request_url)-1) != RET_OK) {   
00234         myprintf("[HTTP] setHttpRequest failed\r\n");
00235         while(1){;}
00236     }
00237     
00238     int http_response_code = 0;
00239     int http_response_len = 0;
00240     
00241     if(sendHttpRequest_BG96(20, &http_response_code, &http_response_len)) {
00242         if(http_response_code == HTTP_STATUS_CODE_OK) {
00243             myprintf("[HTTP] 200 OK, Response content length: %d\r\n", http_response_len);
00244             
00245             char * http_buf;
00246             http_buf = (char*)calloc(http_response_len+2, sizeof(char)); // memory allocation
00247                         
00248             if(getHttpResponse_BG96(20, http_buf, http_response_len+2)) {
00249                 dumpHttpRespones_BG96(http_buf);        
00250             }
00251             
00252             free(http_buf); // release
00253             
00254             myprintf("[HTTP] getHttpResponse success\r\n");
00255         } else {
00256             myprintf("[HTTP] sendHttpRequest failed - HTTP response code: %d\r\n", http_response_code);
00257         }
00258     }
00259     */
00260 }
00261 
00262 
00263 // ----------------------------------------------------------------
00264 // Functions: Cat.M1 Status
00265 // ----------------------------------------------------------------
00266 
00267 void waitCatM1Ready(void)
00268 {
00269     while(1) 
00270     {   
00271         if(_parser->recv("RDY")) 
00272         {
00273             myprintf("BG96 ready\r\n");
00274             return ;
00275         }
00276         else if(_parser->send("AT") && _parser->recv("OK"))
00277         {
00278             myprintf("BG96 already available\r\n");
00279             return ;
00280         }        
00281     }        
00282 }
00283 
00284 int8_t setEchoStatus_BG96(bool onoff)
00285 {
00286     int8_t ret = RET_NOK;
00287     char _buf[10];        
00288     
00289     sprintf((char *)_buf, "ATE%d", onoff);    
00290     
00291     if(_parser->send(_buf) && _parser->recv("OK")) {        
00292         devlog("Turn Echo %s success\r\n", onoff?"ON":"OFF");
00293         ret = RET_OK;
00294     } else { 
00295         devlog("Turn Echo %s failed\r\n", onoff?"ON":"OFF");
00296     }    
00297     return ret;
00298 }
00299  
00300 int8_t getUsimStatus_BG96(void)
00301 {
00302     int8_t ret = RET_NOK;
00303     
00304     _parser->send("AT+CPIN?");    
00305     if(_parser->recv("+CPIN: READY") && _parser->recv("OK")) {
00306         devlog("USIM Status: READY\r\n");
00307         ret = RET_OK;
00308     } else { 
00309         devlog("Retrieving USIM Status failed\r\n");        
00310     }
00311     return ret;
00312 }
00313 
00314 int8_t getNetworkStatus_BG96(void)
00315 {
00316     int8_t ret = RET_NOK;    
00317     
00318     if(_parser->send("AT+QCDS") && _parser->recv("+QCDS: \"SRV\"") && _parser->recv("OK")) {
00319         devlog("Network Status: attached\r\n");
00320         ret = RET_OK;
00321     } else if (_parser->send("AT+QCDS") && _parser->recv("+QCDS: \"LIMITED\"") && _parser->recv("OK")) {
00322         devlog("Network Status: limited\r\n");
00323         ret = RET_OK;    
00324     } else { 
00325         devlog("Network Status: Error\r\n");        
00326     }
00327     return ret;
00328 }
00329 
00330 int8_t checknSetApn_BG96(const char * apn) // Configure Parameters of a TCP/IP Context
00331 {       
00332     char resp_str[100];
00333     
00334     uint16_t i = 0;
00335     char * search_pt;
00336     
00337     memset(resp_str, 0, sizeof(resp_str));
00338     
00339     devlog("Checking APN...\r\n");
00340     
00341     _parser->send("AT+QICSGP=1");
00342     
00343     while(1)
00344     {
00345         _parser->read(&resp_str[i++], 1);        
00346         search_pt = strstr(resp_str, "OK\r\n");
00347         if (search_pt != 0)
00348         {
00349             break;
00350         }
00351     }
00352     
00353     search_pt = strstr(resp_str, apn);
00354     if (search_pt == 0)
00355     {
00356         devlog("Mismatched APN: %s\r\n", resp_str);
00357         devlog("Storing APN %s...\r\n", apn);
00358         if(!(_parser->send("AT+QICSGP=1,%d,\"%s\",\"\",\"\",0", BG96_APN_PROTOCOL, apn) && _parser->recv("OK")))
00359         {
00360             return RET_NOK; // failed
00361         }
00362     }    
00363     devlog("APN Check Done\r\n");
00364         
00365     return RET_OK;
00366 }
00367 
00368 int8_t getFirmwareVersion_BG96(char * version)
00369 {
00370     int8_t ret = RET_NOK;
00371     
00372     if(_parser->send("AT+QGMR") && _parser->recv("%s\n", version) && _parser->recv("OK"))
00373     {           
00374         ret = RET_OK;
00375     } 
00376     return ret;
00377 }
00378 
00379 int8_t getImeiNumber_BG96(char * imei)
00380 {
00381     int8_t ret = RET_NOK;    
00382     
00383     if(_parser->send("AT+CGSN") && _parser->recv("%s\n", imei) && _parser->recv("OK"))
00384     { 
00385         ret = RET_OK;
00386     } 
00387     return ret;
00388 }
00389 
00390 // ----------------------------------------------------------------
00391 // Functions: Cat.M1 PSM activate / deactivate
00392 // ----------------------------------------------------------------
00393 
00394 int8_t setPsmActivate_BG96(char *Requested_Periodic_TAU, char *Requested_Active_Time)
00395 {
00396     int8_t ret = RET_NOK;
00397     
00398     if (_parser->send("AT+CPSMS=1,,,\"%s\",\"%s\"", Requested_Periodic_TAU, Requested_Active_Time)
00399         && _parser->recv("OK")) 
00400     {
00401         devlog("PSM activate success\r\n");
00402         ret = RET_OK;
00403     }
00404     return ret;
00405 }
00406 
00407 int8_t setPsmDeactivate_BG96(void)
00408 {
00409     int8_t ret = RET_NOK;
00410     
00411     if (_parser->send("AT+CPSMS=0") && _parser->recv("OK")) {
00412         devlog("PSM deactivate success\r\n");
00413     }
00414     return ret;
00415 }
00416 
00417 int8_t getPsmSetting_BG96(bool * enable, int * Requested_Periodic_TAU, int * Requested_Active_Time)
00418 {
00419     int8_t ret = RET_NOK;
00420     int en = 0;
00421     
00422     if (_parser->send("AT+QPSMS?") // BG96 only
00423         && _parser->recv("+QPSMS: %d,,,\"%d\",\"%d\"", &en, Requested_Periodic_TAU, Requested_Active_Time)
00424         && _parser->recv("OK")) 
00425     {
00426         if(en != 0) 
00427             *enable = true;
00428         else
00429             *enable = false;
00430         
00431         devlog("Get PSM setting success\r\n");
00432         ret = RET_OK;
00433     }
00434     return ret;
00435 }
00436 
00437 
00438 // ----------------------------------------------------------------
00439 // Functions: Cat.M1 Network time
00440 // ----------------------------------------------------------------
00441 
00442 int8_t getNetworkTimeGMT_BG96(char * timestr)
00443 {    
00444     int8_t ret = RET_NOK;
00445     if (_parser->send("AT+QLTS=1") 
00446         && _parser->recv("+QLTS: \"%[^\"]\"", timestr)
00447         && _parser->recv("OK")) 
00448     {
00449         //devlog("Get current GMT time success\r\n");        
00450         ret = RET_OK;
00451     }
00452     return ret;
00453 }
00454 
00455 int8_t getNetworkTimeLocal_BG96(char * timestr)
00456 {
00457     int8_t ret = RET_NOK;
00458     if (_parser->send("AT+QLTS=2") 
00459         && _parser->recv("+QLTS: \"%[^\"]\"", timestr)
00460         && _parser->recv("OK")) 
00461     {
00462         //devlog("Get current local time success\r\n");        
00463         ret = RET_OK;
00464     }
00465     return ret;
00466 }
00467 
00468 void setFlagGettime(void)
00469 {
00470     flag_gettime = true;
00471 }
00472 
00473 void clearFlagGettime(void)
00474 {
00475     flag_gettime = false;
00476 }
00477 
00478 // ----------------------------------------------------------------
00479 // Functions: Cat.M1 HTTP send & recv
00480 // ----------------------------------------------------------------
00481 /*
00482 int8_t setHttpRequest_BG96(char * req, int len)
00483 {
00484     int8_t ret = RET_NOK;    
00485     bool done = false;
00486     
00487     _parser->set_timeout(BG96_CONNECT_TIMEOUT);
00488     
00489     _parser->send("AT+QHTTPURL=%d,%d", len, 5);    
00490     if( !done && _parser->recv("CONNECT\r\n") )
00491         done = (_parser->write(req, len) <= 0);
00492         
00493         if( !done ) {        
00494         done = (_parser->recv("OK"));        
00495         if(done) {
00496             devlog("Set HTTP request URL success: %s\r\n", req);
00497             ret = RET_OK;
00498         }
00499     }
00500     _parser->set_timeout(BG96_DEFAULT_TIMEOUT); 
00501     
00502     return ret;
00503 }
00504 
00505 
00506 
00507 int8_t sendHttpRequest_BG96(int timeout, int * rsp_code, int * content_len)
00508 {
00509     int8_t ret = RET_NOK;
00510     int err;
00511     
00512     _parser->set_timeout(BG96_DEFAULT_TIMEOUT + (timeout * 1000));
00513     
00514     if( _parser->send("AT+QHTTPGET=%d", timeout) 
00515         && _parser->recv("+QHTTPGET: %d,%d,%d\r\n", &err, rsp_code, content_len)
00516         && (err == 0)) 
00517     {        
00518         devlog("The HTTP request is sent and the response is successful\r\n");        
00519         ret = RET_OK;            
00520     }    
00521     _parser->set_timeout(BG96_DEFAULT_TIMEOUT); 
00522     
00523     return ret;
00524 }
00525 
00526 
00527 int8_t getHttpResponse_BG96(int timeout, char * buf, int len)
00528 {
00529     int8_t ret = RET_NOK;
00530     bool done = false;
00531     
00532     if( _parser->send("AT+QHTTPREAD=%d", timeout) && _parser->recv("CONNECT\r\n")) {
00533         done = _parser->read(buf, len);
00534     }
00535     
00536     if(done) {
00537         if( _parser->recv("OK") && _parser->recv("+QHTTPREAD: 0")) {
00538             ret = RET_OK;
00539         }
00540     }            
00541     return ret;
00542 }
00543 
00544 void dumpHttpRespones_BG96(char * buf)
00545 {
00546     myprintf("%s", buf);   
00547 }
00548 */