Library driver for the u-blox SARA-N200 NB-IoT modem
Dependents: sara-n200-hello-mqtt-sn
sara-n2.cpp
- Committer:
- KeystoneElectronic
- Date:
- 2018-08-20
- Revision:
- 0:87f4169aba8e
- Child:
- 2:9b9276791c59
File content as of revision 0:87f4169aba8e:
/* * sara_n2.cpp * * Created on: 08 Aug 2018 * Author: Janus Erasmus */ #include "sara_n2.h" #define INFO_TRACE(_class, _string, ...) printf( "%8s: " _string, _class, ##__VA_ARGS__) #define TRACE(_string, ...) INFO_TRACE( "SARA", _string, ##__VA_ARGS__) SARA_N2::SARA_N2(FileHandle *fh, DigitalOut *reset_pin) : mCMD(fh,"\r"), mReset(reset_pin), mState(MODEM_UNKNOWN) { mBufferFlag = 0; mTimer.start(); mElapsed = mTimer.read_ms(); *mReset = 0; //mCMD.debug_on(1); mCMD.set_timeout(500); mCMD.oob("+NSONMI", callback(SARA_N2::receiveData, this)); } SARA_N2::~SARA_N2() { } void SARA_N2::receiveData(SARA_N2 *_this) { _this->mBufferFlag = 1; } const char *registartionString(int stat) { switch(stat) { case 0: return "Not registered"; case 1: return "Registered"; case 2: return "Searching"; case 3: return "Registration denied"; default: case 4: return "unknown"; case 5: return "Roaming"; case 8: return "Emergency only"; } } void SARA_N2::fsm() { //Execute FSM every 1s int tick = mTimer.read_ms(); if((tick - mElapsed) < 1000) return; mElapsed = tick; switch(mState) { case MODEM_UNKNOWN: TRACE("reset modem\n"); *mReset = 0; wait(1); *mReset = 1; wait(1); mState = MODEM_NEED_SIM; break; case MODEM_NEED_SIM: { mCMD.send("AT+CGMR"); int major, minor; if(!mCMD.recv("%d.%d\n", &major, &minor)) break; mCMD.send("AT+UGPIOC=11,11"); if(!mCMD.recv("OK")) break; mCMD.send("AT+CPSMS=0"); if(!mCMD.recv("OK")) break; mCMD.send("AT+CSCON=1"); if(!mCMD.recv("OK")) break; mCMD.send("AT+NPSMR=1"); if(!mCMD.recv("OK")) break; TRACE("Release: %d.%d\n", major, minor); wait(1); mCMD.send("AT+CGSN=1"); char model[32]; model[0] = 0; if(!mCMD.recv("+CGSN: %32s\n", model)) break; TRACE("IMEA: %s\n", model); mState = MODEM_SIM_PIN; } break; case MODEM_SIM_PIN: { char SIMID[32]; mCMD.send("AT+CCID?"); if(!mCMD.recv("+CCID: %32s\n", SIMID)) break; TRACE("SIM: %s\n", SIMID); // mCMD.send("AT+CFUN=1"); // if(!mCMD.recv("OK")) // break; mState = MODEM_SIGNAL; } break; case MODEM_SIGNAL: { mCMD.send("AT+CSQ"); int power, quality; if(!mCMD.recv("+CSQ: %d,%d\n", &power, &quality)) break; TRACE("CSQ: %d,%d\n", power, quality); if(power == 99) break; if(power > 9) mState = MODEM_REGISTERED; } break; case MODEM_REGISTERED: { mCMD.send("AT+CEREG?"); int mode, status; if(!mCMD.recv("+CEREG: %d,%d\n", &mode, &status)) break; TRACE("Reg Status: %s\n", registartionString(status)); if((status == 1) || (status == 5)) mState = MODEM_ATTACHING; } break; case MODEM_ATTACHING: { mCMD.send("AT+CGATT?"); int att; if(!mCMD.recv("+CGATT: %d\n", &att)) break; TRACE("GPRS ATT: %d\n", att); if(att == 1) mState = MODEM_CONNECTED; } break; case MODEM_CONNECTED: break; } } int SARA_N2::connect(char *hostname, int port) { if(mState < MODEM_CONNECTED) return -1; mCMD.send("AT+NSOCR=\"DGRAM\",17,%d", port); int sock; if(!mCMD.recv("%d\n", &sock)) return -1; TRACE("Socket created %d\n", sock); // mCMD.send("AT+CGACT=%d", sock); // if(mCMD.recv("OK")) // { // // TRACE("Socket activated %d\n", sock); // } return sock; } bool SARA_N2::disconnect(int id) { mCMD.send("AT+NSOCL=%d", id); if(!mCMD.recv("OK")) return false; TRACE("Socket closed %d\n", id); return true; } uint8_t util_parse_params(char *command, char **argv, int *argc, char delimiter) { uint8_t count = 0; *argc -= 2; argv[count] = command; char *ptr = strchr(argv[count], delimiter); while (ptr && (count++ < *argc)) { ptr[0] = 0; ptr++; argv[count] = ptr; ptr = strchr(argv[count], delimiter); } count++; *argc = count; return count; } int SARA_N2::read(int sock_id, char *host, int *port, uint8_t* buff, int len, int timeout) { mCMD.process_oob(); if(mBufferFlag <= 0) return -1; mBufferFlag = 0; mCMD.send("AT+NSORF=%d,%d", sock_id, len * 2); int sock; char textBuffer[256]; if(mCMD.recv("%d,%s\n", &sock, textBuffer)) { //printf("RX %d: %s\n", sock, textBuffer); int hex_len = -1; char *argv[8]; int argc = 8; util_parse_params(textBuffer, argv, &argc, ','); if(argc > 3) { hex_len = atoi(argv[2]); if(hex_len > len) hex_len = len; //printf("Data %s: %s\n", argv[2], argv[3]); char *hex_ptr = argv[3] + 1; for (int k = 0; k < hex_len; ++k) { //printf("%s", hex_ptr); char temp[8]; memcpy(temp, hex_ptr, 2); hex_ptr += 2; temp[2] = 0; buff[k] = strtol(temp, 0, 16); } len = hex_len; //diag_dump_buf(buff, len); } } return len; } int SARA_N2::write(int sock_id, char *host, int port, uint8_t* buff, int len, int timeout) { char textBuffer[256]; textBuffer[0] = 0; for (int k = 0; k < len; ++k) { char temp[8]; sprintf(temp, "%02X", buff[k]); strcat(textBuffer, temp); } //mCMD.set_timeout(timeout); mCMD.send("AT+NSOST=%d,\"%s\",%d,%d,\"%s\"", sock_id, host, port, len, textBuffer); int sock, tx_len; if(!mCMD.recv("%d,%d\n", &sock, &tx_len)) tx_len = -1; return tx_len; }