Library driver for the u-blox SARA-N200 NB-IoT modem

Dependents:   sara-n200-hello-mqtt-sn

Committer:
KeystoneElectronic
Date:
Mon Aug 20 12:58:21 2018 +0000
Revision:
0:87f4169aba8e
Child:
2:9b9276791c59
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
KeystoneElectronic 0:87f4169aba8e 1 /*
KeystoneElectronic 0:87f4169aba8e 2 * sara_n2.cpp
KeystoneElectronic 0:87f4169aba8e 3 *
KeystoneElectronic 0:87f4169aba8e 4 * Created on: 08 Aug 2018
KeystoneElectronic 0:87f4169aba8e 5 * Author: Janus Erasmus
KeystoneElectronic 0:87f4169aba8e 6 */
KeystoneElectronic 0:87f4169aba8e 7
KeystoneElectronic 0:87f4169aba8e 8 #include "sara_n2.h"
KeystoneElectronic 0:87f4169aba8e 9
KeystoneElectronic 0:87f4169aba8e 10 #define INFO_TRACE(_class, _string, ...) printf( "%8s: " _string, _class, ##__VA_ARGS__)
KeystoneElectronic 0:87f4169aba8e 11 #define TRACE(_string, ...) INFO_TRACE( "SARA", _string, ##__VA_ARGS__)
KeystoneElectronic 0:87f4169aba8e 12
KeystoneElectronic 0:87f4169aba8e 13 SARA_N2::SARA_N2(FileHandle *fh, DigitalOut *reset_pin) :
KeystoneElectronic 0:87f4169aba8e 14 mCMD(fh,"\r"),
KeystoneElectronic 0:87f4169aba8e 15 mReset(reset_pin),
KeystoneElectronic 0:87f4169aba8e 16 mState(MODEM_UNKNOWN)
KeystoneElectronic 0:87f4169aba8e 17 {
KeystoneElectronic 0:87f4169aba8e 18 mBufferFlag = 0;
KeystoneElectronic 0:87f4169aba8e 19 mTimer.start();
KeystoneElectronic 0:87f4169aba8e 20 mElapsed = mTimer.read_ms();
KeystoneElectronic 0:87f4169aba8e 21 *mReset = 0;
KeystoneElectronic 0:87f4169aba8e 22
KeystoneElectronic 0:87f4169aba8e 23 //mCMD.debug_on(1);
KeystoneElectronic 0:87f4169aba8e 24 mCMD.set_timeout(500);
KeystoneElectronic 0:87f4169aba8e 25 mCMD.oob("+NSONMI", callback(SARA_N2::receiveData, this));
KeystoneElectronic 0:87f4169aba8e 26 }
KeystoneElectronic 0:87f4169aba8e 27
KeystoneElectronic 0:87f4169aba8e 28 SARA_N2::~SARA_N2()
KeystoneElectronic 0:87f4169aba8e 29 {
KeystoneElectronic 0:87f4169aba8e 30 }
KeystoneElectronic 0:87f4169aba8e 31
KeystoneElectronic 0:87f4169aba8e 32 void SARA_N2::receiveData(SARA_N2 *_this)
KeystoneElectronic 0:87f4169aba8e 33 {
KeystoneElectronic 0:87f4169aba8e 34 _this->mBufferFlag = 1;
KeystoneElectronic 0:87f4169aba8e 35 }
KeystoneElectronic 0:87f4169aba8e 36
KeystoneElectronic 0:87f4169aba8e 37
KeystoneElectronic 0:87f4169aba8e 38 const char *registartionString(int stat)
KeystoneElectronic 0:87f4169aba8e 39 {
KeystoneElectronic 0:87f4169aba8e 40 switch(stat)
KeystoneElectronic 0:87f4169aba8e 41 {
KeystoneElectronic 0:87f4169aba8e 42 case 0:
KeystoneElectronic 0:87f4169aba8e 43 return "Not registered";
KeystoneElectronic 0:87f4169aba8e 44 case 1:
KeystoneElectronic 0:87f4169aba8e 45 return "Registered";
KeystoneElectronic 0:87f4169aba8e 46 case 2:
KeystoneElectronic 0:87f4169aba8e 47 return "Searching";
KeystoneElectronic 0:87f4169aba8e 48 case 3:
KeystoneElectronic 0:87f4169aba8e 49 return "Registration denied";
KeystoneElectronic 0:87f4169aba8e 50 default:
KeystoneElectronic 0:87f4169aba8e 51 case 4:
KeystoneElectronic 0:87f4169aba8e 52 return "unknown";
KeystoneElectronic 0:87f4169aba8e 53 case 5:
KeystoneElectronic 0:87f4169aba8e 54 return "Roaming";
KeystoneElectronic 0:87f4169aba8e 55 case 8:
KeystoneElectronic 0:87f4169aba8e 56 return "Emergency only";
KeystoneElectronic 0:87f4169aba8e 57 }
KeystoneElectronic 0:87f4169aba8e 58 }
KeystoneElectronic 0:87f4169aba8e 59
KeystoneElectronic 0:87f4169aba8e 60 void SARA_N2::fsm()
KeystoneElectronic 0:87f4169aba8e 61 {
KeystoneElectronic 0:87f4169aba8e 62 //Execute FSM every 1s
KeystoneElectronic 0:87f4169aba8e 63 int tick = mTimer.read_ms();
KeystoneElectronic 0:87f4169aba8e 64 if((tick - mElapsed) < 1000)
KeystoneElectronic 0:87f4169aba8e 65 return;
KeystoneElectronic 0:87f4169aba8e 66
KeystoneElectronic 0:87f4169aba8e 67 mElapsed = tick;
KeystoneElectronic 0:87f4169aba8e 68
KeystoneElectronic 0:87f4169aba8e 69 switch(mState)
KeystoneElectronic 0:87f4169aba8e 70 {
KeystoneElectronic 0:87f4169aba8e 71 case MODEM_UNKNOWN:
KeystoneElectronic 0:87f4169aba8e 72 TRACE("reset modem\n");
KeystoneElectronic 0:87f4169aba8e 73 *mReset = 0;
KeystoneElectronic 0:87f4169aba8e 74 wait(1);
KeystoneElectronic 0:87f4169aba8e 75 *mReset = 1;
KeystoneElectronic 0:87f4169aba8e 76 wait(1);
KeystoneElectronic 0:87f4169aba8e 77 mState = MODEM_NEED_SIM;
KeystoneElectronic 0:87f4169aba8e 78 break;
KeystoneElectronic 0:87f4169aba8e 79 case MODEM_NEED_SIM:
KeystoneElectronic 0:87f4169aba8e 80 {
KeystoneElectronic 0:87f4169aba8e 81 mCMD.send("AT+CGMR");
KeystoneElectronic 0:87f4169aba8e 82 int major, minor;
KeystoneElectronic 0:87f4169aba8e 83 if(!mCMD.recv("%d.%d\n", &major, &minor))
KeystoneElectronic 0:87f4169aba8e 84 break;
KeystoneElectronic 0:87f4169aba8e 85
KeystoneElectronic 0:87f4169aba8e 86 mCMD.send("AT+UGPIOC=11,11");
KeystoneElectronic 0:87f4169aba8e 87 if(!mCMD.recv("OK"))
KeystoneElectronic 0:87f4169aba8e 88 break;
KeystoneElectronic 0:87f4169aba8e 89
KeystoneElectronic 0:87f4169aba8e 90 mCMD.send("AT+CPSMS=0");
KeystoneElectronic 0:87f4169aba8e 91 if(!mCMD.recv("OK"))
KeystoneElectronic 0:87f4169aba8e 92 break;
KeystoneElectronic 0:87f4169aba8e 93
KeystoneElectronic 0:87f4169aba8e 94 mCMD.send("AT+CSCON=1");
KeystoneElectronic 0:87f4169aba8e 95 if(!mCMD.recv("OK"))
KeystoneElectronic 0:87f4169aba8e 96 break;
KeystoneElectronic 0:87f4169aba8e 97
KeystoneElectronic 0:87f4169aba8e 98 mCMD.send("AT+NPSMR=1");
KeystoneElectronic 0:87f4169aba8e 99 if(!mCMD.recv("OK"))
KeystoneElectronic 0:87f4169aba8e 100 break;
KeystoneElectronic 0:87f4169aba8e 101
KeystoneElectronic 0:87f4169aba8e 102 TRACE("Release: %d.%d\n", major, minor);
KeystoneElectronic 0:87f4169aba8e 103 wait(1);
KeystoneElectronic 0:87f4169aba8e 104
KeystoneElectronic 0:87f4169aba8e 105 mCMD.send("AT+CGSN=1");
KeystoneElectronic 0:87f4169aba8e 106 char model[32];
KeystoneElectronic 0:87f4169aba8e 107 model[0] = 0;
KeystoneElectronic 0:87f4169aba8e 108 if(!mCMD.recv("+CGSN: %32s\n", model))
KeystoneElectronic 0:87f4169aba8e 109 break;
KeystoneElectronic 0:87f4169aba8e 110
KeystoneElectronic 0:87f4169aba8e 111 TRACE("IMEA: %s\n", model);
KeystoneElectronic 0:87f4169aba8e 112
KeystoneElectronic 0:87f4169aba8e 113 mState = MODEM_SIM_PIN;
KeystoneElectronic 0:87f4169aba8e 114 }
KeystoneElectronic 0:87f4169aba8e 115 break;
KeystoneElectronic 0:87f4169aba8e 116 case MODEM_SIM_PIN:
KeystoneElectronic 0:87f4169aba8e 117 {
KeystoneElectronic 0:87f4169aba8e 118 char SIMID[32];
KeystoneElectronic 0:87f4169aba8e 119 mCMD.send("AT+CCID?");
KeystoneElectronic 0:87f4169aba8e 120 if(!mCMD.recv("+CCID: %32s\n", SIMID))
KeystoneElectronic 0:87f4169aba8e 121 break;
KeystoneElectronic 0:87f4169aba8e 122
KeystoneElectronic 0:87f4169aba8e 123 TRACE("SIM: %s\n", SIMID);
KeystoneElectronic 0:87f4169aba8e 124
KeystoneElectronic 0:87f4169aba8e 125 // mCMD.send("AT+CFUN=1");
KeystoneElectronic 0:87f4169aba8e 126 // if(!mCMD.recv("OK"))
KeystoneElectronic 0:87f4169aba8e 127 // break;
KeystoneElectronic 0:87f4169aba8e 128
KeystoneElectronic 0:87f4169aba8e 129 mState = MODEM_SIGNAL;
KeystoneElectronic 0:87f4169aba8e 130
KeystoneElectronic 0:87f4169aba8e 131 }
KeystoneElectronic 0:87f4169aba8e 132 break;
KeystoneElectronic 0:87f4169aba8e 133 case MODEM_SIGNAL:
KeystoneElectronic 0:87f4169aba8e 134 {
KeystoneElectronic 0:87f4169aba8e 135 mCMD.send("AT+CSQ");
KeystoneElectronic 0:87f4169aba8e 136 int power, quality;
KeystoneElectronic 0:87f4169aba8e 137 if(!mCMD.recv("+CSQ: %d,%d\n", &power, &quality))
KeystoneElectronic 0:87f4169aba8e 138 break;
KeystoneElectronic 0:87f4169aba8e 139
KeystoneElectronic 0:87f4169aba8e 140 TRACE("CSQ: %d,%d\n", power, quality);
KeystoneElectronic 0:87f4169aba8e 141
KeystoneElectronic 0:87f4169aba8e 142 if(power == 99)
KeystoneElectronic 0:87f4169aba8e 143 break;
KeystoneElectronic 0:87f4169aba8e 144
KeystoneElectronic 0:87f4169aba8e 145 if(power > 9)
KeystoneElectronic 0:87f4169aba8e 146 mState = MODEM_REGISTERED;
KeystoneElectronic 0:87f4169aba8e 147 }
KeystoneElectronic 0:87f4169aba8e 148 break;
KeystoneElectronic 0:87f4169aba8e 149 case MODEM_REGISTERED:
KeystoneElectronic 0:87f4169aba8e 150 {
KeystoneElectronic 0:87f4169aba8e 151 mCMD.send("AT+CEREG?");
KeystoneElectronic 0:87f4169aba8e 152 int mode, status;
KeystoneElectronic 0:87f4169aba8e 153 if(!mCMD.recv("+CEREG: %d,%d\n", &mode, &status))
KeystoneElectronic 0:87f4169aba8e 154 break;
KeystoneElectronic 0:87f4169aba8e 155
KeystoneElectronic 0:87f4169aba8e 156 TRACE("Reg Status: %s\n", registartionString(status));
KeystoneElectronic 0:87f4169aba8e 157
KeystoneElectronic 0:87f4169aba8e 158 if((status == 1) || (status == 5))
KeystoneElectronic 0:87f4169aba8e 159 mState = MODEM_ATTACHING;
KeystoneElectronic 0:87f4169aba8e 160 }
KeystoneElectronic 0:87f4169aba8e 161 break;
KeystoneElectronic 0:87f4169aba8e 162 case MODEM_ATTACHING:
KeystoneElectronic 0:87f4169aba8e 163 {
KeystoneElectronic 0:87f4169aba8e 164 mCMD.send("AT+CGATT?");
KeystoneElectronic 0:87f4169aba8e 165 int att;
KeystoneElectronic 0:87f4169aba8e 166 if(!mCMD.recv("+CGATT: %d\n", &att))
KeystoneElectronic 0:87f4169aba8e 167 break;
KeystoneElectronic 0:87f4169aba8e 168
KeystoneElectronic 0:87f4169aba8e 169 TRACE("GPRS ATT: %d\n", att);
KeystoneElectronic 0:87f4169aba8e 170
KeystoneElectronic 0:87f4169aba8e 171 if(att == 1)
KeystoneElectronic 0:87f4169aba8e 172 mState = MODEM_CONNECTED;
KeystoneElectronic 0:87f4169aba8e 173 }
KeystoneElectronic 0:87f4169aba8e 174 break;
KeystoneElectronic 0:87f4169aba8e 175 case MODEM_CONNECTED:
KeystoneElectronic 0:87f4169aba8e 176 break;
KeystoneElectronic 0:87f4169aba8e 177 }
KeystoneElectronic 0:87f4169aba8e 178 }
KeystoneElectronic 0:87f4169aba8e 179
KeystoneElectronic 0:87f4169aba8e 180 int SARA_N2::connect(char *hostname, int port)
KeystoneElectronic 0:87f4169aba8e 181 {
KeystoneElectronic 0:87f4169aba8e 182 if(mState < MODEM_CONNECTED)
KeystoneElectronic 0:87f4169aba8e 183 return -1;
KeystoneElectronic 0:87f4169aba8e 184
KeystoneElectronic 0:87f4169aba8e 185 mCMD.send("AT+NSOCR=\"DGRAM\",17,%d", port);
KeystoneElectronic 0:87f4169aba8e 186 int sock;
KeystoneElectronic 0:87f4169aba8e 187 if(!mCMD.recv("%d\n", &sock))
KeystoneElectronic 0:87f4169aba8e 188 return -1;
KeystoneElectronic 0:87f4169aba8e 189
KeystoneElectronic 0:87f4169aba8e 190 TRACE("Socket created %d\n", sock);
KeystoneElectronic 0:87f4169aba8e 191
KeystoneElectronic 0:87f4169aba8e 192 // mCMD.send("AT+CGACT=%d", sock);
KeystoneElectronic 0:87f4169aba8e 193 // if(mCMD.recv("OK"))
KeystoneElectronic 0:87f4169aba8e 194 // {
KeystoneElectronic 0:87f4169aba8e 195 //
KeystoneElectronic 0:87f4169aba8e 196 // TRACE("Socket activated %d\n", sock);
KeystoneElectronic 0:87f4169aba8e 197 // }
KeystoneElectronic 0:87f4169aba8e 198 return sock;
KeystoneElectronic 0:87f4169aba8e 199 }
KeystoneElectronic 0:87f4169aba8e 200
KeystoneElectronic 0:87f4169aba8e 201 bool SARA_N2::disconnect(int id)
KeystoneElectronic 0:87f4169aba8e 202 {
KeystoneElectronic 0:87f4169aba8e 203 mCMD.send("AT+NSOCL=%d", id);
KeystoneElectronic 0:87f4169aba8e 204 if(!mCMD.recv("OK"))
KeystoneElectronic 0:87f4169aba8e 205 return false;
KeystoneElectronic 0:87f4169aba8e 206
KeystoneElectronic 0:87f4169aba8e 207 TRACE("Socket closed %d\n", id);
KeystoneElectronic 0:87f4169aba8e 208 return true;
KeystoneElectronic 0:87f4169aba8e 209 }
KeystoneElectronic 0:87f4169aba8e 210
KeystoneElectronic 0:87f4169aba8e 211 uint8_t util_parse_params(char *command, char **argv, int *argc, char delimiter)
KeystoneElectronic 0:87f4169aba8e 212 {
KeystoneElectronic 0:87f4169aba8e 213 uint8_t count = 0;
KeystoneElectronic 0:87f4169aba8e 214 *argc -= 2;
KeystoneElectronic 0:87f4169aba8e 215 argv[count] = command;
KeystoneElectronic 0:87f4169aba8e 216 char *ptr = strchr(argv[count], delimiter);
KeystoneElectronic 0:87f4169aba8e 217
KeystoneElectronic 0:87f4169aba8e 218 while (ptr && (count++ < *argc))
KeystoneElectronic 0:87f4169aba8e 219 {
KeystoneElectronic 0:87f4169aba8e 220 ptr[0] = 0;
KeystoneElectronic 0:87f4169aba8e 221 ptr++;
KeystoneElectronic 0:87f4169aba8e 222
KeystoneElectronic 0:87f4169aba8e 223 argv[count] = ptr;
KeystoneElectronic 0:87f4169aba8e 224
KeystoneElectronic 0:87f4169aba8e 225 ptr = strchr(argv[count], delimiter);
KeystoneElectronic 0:87f4169aba8e 226 }
KeystoneElectronic 0:87f4169aba8e 227
KeystoneElectronic 0:87f4169aba8e 228 count++;
KeystoneElectronic 0:87f4169aba8e 229
KeystoneElectronic 0:87f4169aba8e 230 *argc = count;
KeystoneElectronic 0:87f4169aba8e 231
KeystoneElectronic 0:87f4169aba8e 232 return count;
KeystoneElectronic 0:87f4169aba8e 233 }
KeystoneElectronic 0:87f4169aba8e 234
KeystoneElectronic 0:87f4169aba8e 235 int SARA_N2::read(int sock_id, char *host, int *port, uint8_t* buff, int len, int timeout)
KeystoneElectronic 0:87f4169aba8e 236 {
KeystoneElectronic 0:87f4169aba8e 237 mCMD.process_oob();
KeystoneElectronic 0:87f4169aba8e 238
KeystoneElectronic 0:87f4169aba8e 239 if(mBufferFlag <= 0)
KeystoneElectronic 0:87f4169aba8e 240 return -1;
KeystoneElectronic 0:87f4169aba8e 241
KeystoneElectronic 0:87f4169aba8e 242 mBufferFlag = 0;
KeystoneElectronic 0:87f4169aba8e 243
KeystoneElectronic 0:87f4169aba8e 244 mCMD.send("AT+NSORF=%d,%d", sock_id, len * 2);
KeystoneElectronic 0:87f4169aba8e 245 int sock;
KeystoneElectronic 0:87f4169aba8e 246 char textBuffer[256];
KeystoneElectronic 0:87f4169aba8e 247 if(mCMD.recv("%d,%s\n", &sock, textBuffer))
KeystoneElectronic 0:87f4169aba8e 248 {
KeystoneElectronic 0:87f4169aba8e 249 //printf("RX %d: %s\n", sock, textBuffer);
KeystoneElectronic 0:87f4169aba8e 250 int hex_len = -1;
KeystoneElectronic 0:87f4169aba8e 251 char *argv[8];
KeystoneElectronic 0:87f4169aba8e 252 int argc = 8;
KeystoneElectronic 0:87f4169aba8e 253 util_parse_params(textBuffer, argv, &argc, ',');
KeystoneElectronic 0:87f4169aba8e 254
KeystoneElectronic 0:87f4169aba8e 255 if(argc > 3)
KeystoneElectronic 0:87f4169aba8e 256 {
KeystoneElectronic 0:87f4169aba8e 257 hex_len = atoi(argv[2]);
KeystoneElectronic 0:87f4169aba8e 258 if(hex_len > len)
KeystoneElectronic 0:87f4169aba8e 259 hex_len = len;
KeystoneElectronic 0:87f4169aba8e 260
KeystoneElectronic 0:87f4169aba8e 261 //printf("Data %s: %s\n", argv[2], argv[3]);
KeystoneElectronic 0:87f4169aba8e 262
KeystoneElectronic 0:87f4169aba8e 263 char *hex_ptr = argv[3] + 1;
KeystoneElectronic 0:87f4169aba8e 264 for (int k = 0; k < hex_len; ++k)
KeystoneElectronic 0:87f4169aba8e 265 {
KeystoneElectronic 0:87f4169aba8e 266 //printf("%s", hex_ptr);
KeystoneElectronic 0:87f4169aba8e 267 char temp[8];
KeystoneElectronic 0:87f4169aba8e 268 memcpy(temp, hex_ptr, 2);
KeystoneElectronic 0:87f4169aba8e 269 hex_ptr += 2;
KeystoneElectronic 0:87f4169aba8e 270 temp[2] = 0;
KeystoneElectronic 0:87f4169aba8e 271 buff[k] = strtol(temp, 0, 16);
KeystoneElectronic 0:87f4169aba8e 272 }
KeystoneElectronic 0:87f4169aba8e 273
KeystoneElectronic 0:87f4169aba8e 274 len = hex_len;
KeystoneElectronic 0:87f4169aba8e 275
KeystoneElectronic 0:87f4169aba8e 276 //diag_dump_buf(buff, len);
KeystoneElectronic 0:87f4169aba8e 277 }
KeystoneElectronic 0:87f4169aba8e 278 }
KeystoneElectronic 0:87f4169aba8e 279
KeystoneElectronic 0:87f4169aba8e 280 return len;
KeystoneElectronic 0:87f4169aba8e 281 }
KeystoneElectronic 0:87f4169aba8e 282
KeystoneElectronic 0:87f4169aba8e 283 int SARA_N2::write(int sock_id, char *host, int port, uint8_t* buff, int len, int timeout)
KeystoneElectronic 0:87f4169aba8e 284 {
KeystoneElectronic 0:87f4169aba8e 285 char textBuffer[256];
KeystoneElectronic 0:87f4169aba8e 286 textBuffer[0] = 0;
KeystoneElectronic 0:87f4169aba8e 287 for (int k = 0; k < len; ++k)
KeystoneElectronic 0:87f4169aba8e 288 {
KeystoneElectronic 0:87f4169aba8e 289 char temp[8];
KeystoneElectronic 0:87f4169aba8e 290 sprintf(temp, "%02X", buff[k]);
KeystoneElectronic 0:87f4169aba8e 291 strcat(textBuffer, temp);
KeystoneElectronic 0:87f4169aba8e 292 }
KeystoneElectronic 0:87f4169aba8e 293 //mCMD.set_timeout(timeout);
KeystoneElectronic 0:87f4169aba8e 294 mCMD.send("AT+NSOST=%d,\"%s\",%d,%d,\"%s\"", sock_id, host, port, len, textBuffer);
KeystoneElectronic 0:87f4169aba8e 295 int sock, tx_len;
KeystoneElectronic 0:87f4169aba8e 296 if(!mCMD.recv("%d,%d\n", &sock, &tx_len))
KeystoneElectronic 0:87f4169aba8e 297 tx_len = -1;
KeystoneElectronic 0:87f4169aba8e 298
KeystoneElectronic 0:87f4169aba8e 299 return tx_len;
KeystoneElectronic 0:87f4169aba8e 300 }