Eric Jung / Mbed OS WIZnet-IoTShield-BG96-ThingPlug
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 /* THINGPLUG */
00070 #define THINGPLUG_PROTOCOL              "MQTTS"
00071 #define THINGPLUG_HOST                  "test.sktiot.com"
00072 #define THINGPLUG_PORT                  8883
00073 #define THINGPLUG_KEEPALIVE             300
00074 #define THINGPLUG_CLEANSESSION          1
00075 
00076 #define THINGPLUG_DATA_FORMAT_JSON      0
00077 #define THINGPLUG_DATA_TYPE_TELEMETRY   "telemetry"
00078 #define THINGPLUG_DATA_TYPE_ATTRIBUTE   "attribute"
00079 
00080 #define THINGPLUG_CMD_RES_OK            0
00081 #define THINGPLUG_CMD_RES_NOK           1
00082 #define ESPCAPE_SEQ                     0x1A
00083 
00084 /* THINGPLUG PRIVATE*/
00085 #define THINGPLUG_SVC_NAME              "svc01"
00086 #define THINGPLUG_DEV_ID                "dev02"
00087 #define THINGPLUG_DEV_TOKEN             "a0149f60b*********"
00088 
00089 #define THINGPLUG_TELEMETRY1            "temperature"
00090 #define THINGPLUG_TELEMETRY2            "humidity"
00091 #define THINGPLUG_ATTRIBUTE             "LED"
00092 
00093 
00094 // Functions: Module Status
00095 void waitCatM1Ready(void);
00096 int8_t setEchoStatus_BG96(bool onoff);
00097 int8_t getUsimStatus_BG96(void);
00098 int8_t getNetworkStatus_BG96(void);
00099 int8_t checknSetApn_BG96(const char * apn);
00100 int8_t getFirmwareVersion_BG96(char * version);
00101 
00102 // Functions: ThingPlug send & recv
00103 int8_t connectThingPlug_BG96(char* svc_id, char* dev_id, char* dev_token);
00104 int8_t sendThingPlugData_Json_BG96(char* type, char * data, int len);
00105 int8_t recvThingPlugCmd_BG96(char* cmd_type, unsigned int* rpc_id, char* msg);
00106 int8_t sendThingPlugResp_BG96(char* cmd_type, unsigned int rpc_id, int result, char* result_data, int result_len);
00107 
00108 Serial pc(USBTX, USBRX);    // USB debug
00109 
00110 UARTSerial *_serial;        // Cat.M1 module
00111 ATCmdParser *_parser;
00112 
00113 DigitalOut _RESET_BG96(MBED_CONF_IOTSHIELD_CATM1_RESET);
00114 DigitalOut _PWRKEY_BG96(MBED_CONF_IOTSHIELD_CATM1_PWRKEY);
00115 
00116 void serialPcInit(void)
00117 {
00118     pc.baud(115200);
00119     pc.format(8, Serial::None, 1);
00120 }
00121 
00122 void serialDeviceInit(PinName tx, PinName rx, int baudrate)
00123 {
00124     _serial = new UARTSerial(tx, rx, baudrate);
00125 }
00126 
00127 void serialAtParserInit(const char *delimiter, bool debug_en)
00128 {
00129     _parser = new ATCmdParser(_serial);
00130     _parser->debug_on(debug_en);
00131     _parser->set_delimiter(delimiter);
00132     _parser->set_timeout(BG96_DEFAULT_TIMEOUT);
00133 }
00134 
00135 void catm1DeviceInit(void)
00136 {
00137     serialDeviceInit(   MBED_CONF_IOTSHIELD_CATM1_TX,
00138                         MBED_CONF_IOTSHIELD_CATM1_RX,
00139                         BG96_DEFAULT_BAUD_RATE);
00140 
00141     serialAtParserInit( BG96_PARSER_DELIMITER,
00142                         BG96_PARSER_DEBUG);
00143 }
00144 
00145 void catm1DeviceReset_BG96(void)
00146 {
00147     _RESET_BG96 = 1;
00148     _PWRKEY_BG96 = 1;
00149     wait_ms(300);
00150 
00151     _RESET_BG96 = 0;
00152     _PWRKEY_BG96 = 0;
00153     wait_ms(400);
00154 
00155     _RESET_BG96 = 1;
00156     wait_ms(1000);
00157 }
00158 
00159 
00160 // ----------------------------------------------------------------
00161 // Main routine
00162 // ----------------------------------------------------------------
00163 
00164 int main()
00165 {
00166     serialPcInit();
00167     catm1DeviceInit();
00168 
00169     myprintf("Waiting for Cat.M1 Module Ready...\r\n");
00170 
00171     catm1DeviceReset_BG96();
00172 
00173     waitCatM1Ready();
00174 
00175     wait_ms(5000);
00176 
00177     myprintf("System Init Complete\r\n");
00178 
00179     myprintf("WIZnet IoT Shield for Arm MBED");
00180     myprintf("LTE Cat.M1 Version");
00181     myprintf("=================================================");
00182     myprintf(">> Target Board: WIoT-QC01 (Quectel BG96)");
00183     myprintf(">> Sample Code: ThingPlug Send & Recv");
00184     myprintf("=================================================\r\n");
00185 
00186     setEchoStatus_BG96(OFF);
00187 
00188     getUsimStatus_BG96();
00189 
00190     getNetworkStatus_BG96();
00191 
00192     checknSetApn_BG96(CATM1_APN_SKT);
00193 
00194     // Connect to ThingPlug
00195 
00196 
00197     if(connectThingPlug_BG96(THINGPLUG_SVC_NAME, THINGPLUG_DEV_ID, THINGPLUG_DEV_TOKEN) != RET_OK) {
00198         myprintf("[ThingPlug] Connection failed\r\n");
00199         while(1) {;}
00200     }
00201 
00202     char thingplug_telemetry[128] ={0,};
00203     sprintf(thingplug_telemetry, "{\"%s\":%d, \"%s\":%d}", THINGPLUG_TELEMETRY1, 12, THINGPLUG_TELEMETRY2, 34);
00204     // Send ThingPlug Telemetry test
00205     if(sendThingPlugData_Json_BG96(THINGPLUG_DATA_TYPE_TELEMETRY, thingplug_telemetry, strlen(thingplug_telemetry)) == RET_OK) {
00206         myprintf("[ThingPlug] Send telemetry: \"%s\"\r\n", thingplug_telemetry);
00207     }
00208 
00209 //    wait_ms(400);
00210 //
00211 //    char thingplug_attribute[128] ={0,};
00212 //    sprintf(thingplug_attribute, "{\"%s\":\"%s\"}", THINGPLUG_ATTRIBUTE, "ON");
00213 //    if(sendThingPlugData_Json_BG96(THINGPLUG_DATA_TYPE_ATTRIBUTE, thingplug_attribute, strlen(thingplug_attribute)) == RET_OK) {
00214 //        myprintf("[ThingPlug] Send attribute: \"%s\"\r\n", thingplug_attribute);
00215 //    }
00216     
00217     char recved_cmd_type[32] = {0,};
00218     char recved_rpc_msg[128] = {0,};
00219     unsigned int recved_rpc_id = 0;
00220 
00221     // Recv ThingPlug RPC message test
00222     while(1) {
00223         // ThingPlug RPC received
00224         if(recvThingPlugCmd_BG96(recved_cmd_type, &recved_rpc_id, recved_rpc_msg) == RET_OK) {
00225             myprintf("[ThingPlug] Recieved RPC Type: \"%s\" ID: %d, Message: \"%s\"\r\n", recved_cmd_type, recved_rpc_id, recved_rpc_msg);
00226 
00227             {
00228                 wait_ms(400);
00229                 //RPC Process    
00230             }
00231             
00232             // Send ThingPlug RPC Result
00233             if(sendThingPlugResp_BG96(recved_cmd_type, recved_rpc_id, THINGPLUG_CMD_RES_OK, recved_rpc_msg, strlen(recved_rpc_msg)) == RET_OK) {
00234                 myprintf("[ThingPlug] Send RPC Result, Type: \"%s\" ID: %d, Result: %d\r\n", recved_cmd_type, recved_rpc_id, THINGPLUG_CMD_RES_OK);
00235             }
00236         }
00237     }
00238 }
00239 
00240 
00241 // ----------------------------------------------------------------
00242 // Functions: Cat.M1 Status
00243 // ----------------------------------------------------------------
00244 
00245 void waitCatM1Ready(void)
00246 {
00247     while(1) {
00248         if(_parser->recv("RDY")) {
00249             myprintf("BG96 ready\r\n");
00250             return ;
00251         } else if(_parser->send("AT") && _parser->recv("OK")) {
00252             myprintf("BG96 already available\r\n");
00253             return ;
00254         }
00255     }
00256 }
00257 
00258 int8_t setEchoStatus_BG96(bool onoff)
00259 {
00260     int8_t ret = RET_NOK;
00261     char _buf[10];
00262 
00263     sprintf((char *)_buf, "ATE%d", onoff);
00264 
00265     if(_parser->send(_buf) && _parser->recv("OK")) {
00266         devlog("Turn Echo %s success\r\n", onoff?"ON":"OFF");
00267         ret = RET_OK;
00268     } else {
00269         devlog("Turn Echo %s failed\r\n", onoff?"ON":"OFF");
00270     }
00271     return ret;
00272 }
00273 
00274 int8_t getUsimStatus_BG96(void)
00275 {
00276     int8_t ret = RET_NOK;
00277 
00278     _parser->send("AT+CPIN?");
00279     if(_parser->recv("+CPIN: READY") && _parser->recv("OK")) {
00280         devlog("USIM Status: READY\r\n");
00281         ret = RET_OK;
00282     } else {
00283         devlog("Retrieving USIM Status failed\r\n");
00284     }
00285     return ret;
00286 }
00287 
00288 int8_t getNetworkStatus_BG96(void)
00289 {
00290     int8_t ret = RET_NOK;
00291 
00292     if(_parser->send("AT+QCDS") && _parser->recv("+QCDS: \"SRV\"") && _parser->recv("OK")) {
00293         devlog("Network Status: attached\r\n");
00294         ret = RET_OK;
00295     } else if (_parser->send("AT+QCDS") && _parser->recv("+QCDS: \"LIMITED\"") && _parser->recv("OK")) {
00296         devlog("Network Status: limited\r\n");
00297         ret = RET_OK;
00298     } else {
00299         devlog("Network Status: Error\r\n");
00300     }
00301     return ret;
00302 }
00303 
00304 int8_t checknSetApn_BG96(const char * apn) // Configure Parameters of a TCP/IP Context
00305 {
00306     char resp_str[100];
00307 
00308     uint16_t i = 0;
00309     char * search_pt;
00310 
00311     memset(resp_str, 0, sizeof(resp_str));
00312 
00313     devlog("Checking APN...\r\n");
00314 
00315     _parser->send("AT+QICSGP=1");
00316 
00317     while(1) {
00318         _parser->read(&resp_str[i++], 1);
00319         search_pt = strstr(resp_str, "OK\r\n");
00320         if (search_pt != 0) {
00321             break;
00322         }
00323     }
00324 
00325     search_pt = strstr(resp_str, apn);
00326     if (search_pt == 0) {
00327         devlog("Mismatched APN: %s\r\n", resp_str);
00328         devlog("Storing APN %s...\r\n", apn);
00329         if(!(_parser->send("AT+QICSGP=1,%d,\"%s\",\"\",\"\",0", BG96_APN_PROTOCOL, apn) && _parser->recv("OK"))) {
00330             return RET_NOK; // failed
00331         }
00332     }
00333     devlog("APN Check Done\r\n");
00334 
00335     return RET_OK;
00336 }
00337 
00338 int8_t getFirmwareVersion_BG96(char * version)
00339 {
00340     int8_t ret = RET_NOK;
00341 
00342     if(_parser->send("AT+QGMR") && _parser->recv("%s\n", version) && _parser->recv("OK")) {
00343         ret = RET_OK;
00344     }
00345     return ret;
00346 }
00347 
00348 int8_t getImeiNumber_BG96(char * imei)
00349 {
00350     int8_t ret = RET_NOK;
00351 
00352     if(_parser->send("AT+CGSN") && _parser->recv("%s\n", imei) && _parser->recv("OK")) {
00353         ret = RET_OK;
00354     }
00355     return ret;
00356 }
00357 
00358 // ----------------------------------------------------------------
00359 // Functions: Cat.M1 ThingPlug send & recv
00360 // ----------------------------------------------------------------
00361 
00362 int8_t connectThingPlug_BG96(char* svc_id, char* dev_id, char* dev_token)
00363 {
00364     int8_t ret = RET_NOK;
00365 
00366     _parser->set_timeout(BG96_CONNECT_TIMEOUT);
00367 
00368     if( _parser->send("AT+SKTPCON=1,\"%s\",\"%s\",%d,%d,%d,\"simple_v1\",\"%s\",\"%s\",\"%s\"",\
00369                       THINGPLUG_PROTOCOL, THINGPLUG_HOST, THINGPLUG_PORT, THINGPLUG_KEEPALIVE, THINGPLUG_CLEANSESSION,\
00370                       dev_token, svc_id, dev_id)
00371             && _parser->recv("OK")
00372             && _parser->recv("+SKTPCON: 0")) {
00373         devlog("BG96 Device is connected to ThingPlug successfully\r\n");
00374         ret = RET_OK;
00375     }
00376     _parser->set_timeout(BG96_DEFAULT_TIMEOUT);
00377 
00378     return ret;
00379 }
00380 
00381 int8_t sendThingPlugData_Json_BG96(char* type, char * data, int len)
00382 {
00383     int8_t ret = RET_NOK;
00384     bool done = false;
00385 
00386     if( _parser->send("AT+SKTPDAT=1,\"%s\",%d", type, THINGPLUG_DATA_FORMAT_JSON));
00387 
00388     if( !done && _parser->recv(">") )
00389         done = !(_parser->write(data, len) <= 0) & _parser->send("%c", ESPCAPE_SEQ);
00390 
00391     if( _parser->recv("OK") ) {
00392         devlog("send ThingPlug Data successfully: %s\r\n", data);
00393         if(done) {
00394             ret = RET_OK;
00395         }
00396     }
00397 
00398     _parser->flush();
00399 
00400     return ret;
00401 }
00402 
00403 int8_t sendThingPlugResp_BG96(char* cmd_type, unsigned int rpc_id, int result, char* result_data, int result_len)
00404 {   
00405     int8_t ret = RET_NOK;
00406     bool done = false;
00407 
00408     if( _parser->send("AT+SKTPRES=1,\"%s\",%d,%d", cmd_type, rpc_id, result));
00409 
00410     if( !done && _parser->recv(">") )
00411         done = !(_parser->write(result_data, result_len) <= 0) & _parser->send("%c", ESPCAPE_SEQ);
00412 
00413     if( _parser->recv("OK") ) {
00414         devlog("send Command result successfully %d\r\n", rpc_id);
00415 
00416         if(done) {
00417             ret = RET_OK;
00418         }
00419     }
00420     _parser->flush();
00421     
00422     return ret;
00423 }
00424 
00425 int8_t recvThingPlugCmd_BG96(char* cmd_type, unsigned int* rpc_id, char* msg)
00426 {
00427     int8_t ret = RET_NOK;
00428     unsigned int status;
00429     bool received = false;
00430 
00431     _parser->set_timeout(1);
00432 
00433     received = _parser->recv("+SKTPCMD: %[^\\,],%u,%u,%s\r\n", cmd_type, rpc_id, &status, msg);
00434 //    received = _parser->recv("+SKTPCMD: %[^\,],%u,%u,%s\r\n", cmd_type, rpc_id, &status, msg);
00435     _parser->set_timeout(BG96_DEFAULT_TIMEOUT);
00436 
00437     if(received) ret = RET_OK;
00438     return ret;
00439 }