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

Dependents:   sara-n200-hello-mqtt-sn

Committer:
KeystoneElectronic
Date:
Wed Aug 22 16:37:03 2018 +0200
Revision:
2:9b9276791c59
Parent:
0:87f4169aba8e
Add SIM and IMEA

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