' sprint.sb ' ' This runs through the Over-The-Air Service Provisioning procedure ' for the Sprint network on a Sierra Wireless MC5725 CDMA module. ' Usage: ' ' bas sprint.sb ' ' The script automatically works out which ASY ports from the modemcc 0 asy_add and info_asy_add settings ' It also deactivates the PPP instance in case it's in use. ' Progress and final result is reported in the eventlog ' Progress is also logged to a RAM file called sstat.txt ' Web files sstat.asp and sstat1.asp are also generated to allow progress ' to be observed at the web interface ' the following line makes all string comparisons case insensitive ' OPTION COMPARE sbCaseInsensitive ' set up the error handler ' on error goto ErrorLabel const nl = "\r\n" ' Enter an error message in the event log ' Also prints message to console output ' And appends the message to the web log file ' function eventmsg(msg) print #aspout, msg, nl print msg, nl junk = system("setevent \"" & msg & "\"" & " 0") end function ' Appends the message to the web log file ' function logmsg(msg) print #aspout, msg, nl end function ' Generate the log files for monitoring progress at the web interface ' function init_log_files local fh fh = 0 open "sstat.asp" for output as fh print #fh, "\r\n" print #fh, "\r\n" print #fh, "Sprint Provisioning Status\r\n" print #fh, "\r\n" print #fh, "\r\n" print #fh, "\r\n" print #fh, "\r\n" print #fh, "\r\n" print #fh, "\r\n" print #fh, "\r\n" print #fh, "\r\n" print #fh, "\r\n" close fh fh = 0 open "sstat1.asp" for output as fh print #fh, "\r\n" print #fh, "\r\n" print #fh, "Sprint Provisioning Status\r\n" print #fh, "\r\n" print #fh, "\r\n" print #fh, "\r\n" print #fh, "\r\n" print #fh, "
\r\n" print #fh, "

Sprint activation started. See below for progress

\r\n" print #fh, "
\r\n" print #fh, "\r\n" print #fh, "\r\n" close fh aspout=0 open "sstat.txt" for output as aspout end function ' Generate a final status message which can be displayed at the web interface ' This re-writes the top sstat1 frame page function log_status(log_msg) local fh fh = 0 open "sstat1.asp" for output as fh print #fh, "\r\n" print #fh, "\r\n" print #fh, "Sprint Provisioning Status\r\n" print #fh, "\r\n" print #fh, "\r\n" print #fh, "\r\n" print #fh, "\r\n" print #fh, "
\r\n" print #fh, "

" & log_msg & "

\r\n" print #fh, "

Please reboot the router.

" print #fh, "
\r\n" print #fh, "\r\n" print #fh, "\r\n" close fh end function ' Enter an error message in the event log and exit ' Also prints message to console output ' And updates the web status page ' function errexit(msg) log_status(msg) print #aspout, msg, nl print msg, nl junk = system("setevent \"" & msg & "\"" & " 6") stop end function ' Return the value of Sarian parameter in rsp ' strCmd needs to be of form " ?" ' e.g. "ppp 0 ans ?" function getParam(strCmd,rsp) local res, tmp, tmpPos, x, pos2 getParam = false res = execute(strCmd, 0, tmp) if res = true then tmpPos = InStr(tmp, nl & "OK" & nl) if tmpPos > 0 then For x = tmpPos To 1 Step -1 pos2 = InStr(tmp, nl, x - 3) If pos2 > 0 and pos2 <> tmpPos then x = 1 endif next x if pos2 > 0 and pos2 <> tmpPos then rsp = mid(tmp, pos2 + 2, tmpPos - pos2 - 2) getParam = true endif endif endif end function ' find the first PPP instance configured for GPRS ' returns TRUE if we found one, and put the instance number into num ' otherwise returns FALSE ' function get_gprs_ppp_instance(num) local mdmstr, i get_gprs_ppp_instance = false for i = 0 to 4 if getParam("ppp " & i & " use_modem ?", mdmstr) = TRUE then ' print "PPP ", i, " use_modem = ", mdmstr, nl if mdmstr = "1" or mdmstr = "4" or mdmstr = "5" then get_gprs_ppp_instance = true num = i exit function endif else print "Failed to get PPP ", i, " use_modem", nl endif next i end function ' init_mc75io - opens a serial port and initialises a receive buffer for it ' Sets the following GLOBAL vars: ' mc75in - the input file handle ' mc75out - the output file handle ' mc75rxbuf - the receive buffer ' Parameter required is a GLOBAL variable mc75asyport, eg "ASY5" ' function init_mc75io ' open the serial port used for the MC75 ' two handles, one for input and one for output mc75in = 0 open mc75asyport for input as mc75in ' if error() <> 0 then ' print "error opening asy port", nl ' endif mc75out = 0 open mc75asyport for output as mc75out mc75rxbuf = "" junk = setevent(0) junk = setevent(mc75in) end function ' clear the receive buffer ' function clear_mc75io local junk, infobuf, tbuf mx75rxbuf = "" if waitevents(1000) = mc75in then junk = sockinfo(mc75in, infobuf) if infobuf[2] <> 0 then tbuf = input(infobuf[2], mc75in) endif endif end function ' gets a character from mc75in ' timeout is fixed at 10 secs for now ' Return TRUE if successful, otherwise FALSE ' If TRUE, then character is retuned in the rsp parameter ' function getchar(rsp) local tstart, junk getchar = FALSE tstart = ticks while ticks-tstart < 1000 if len(mc75rxbuf) <> 0 then rsp = left(mc75rxbuf, 1) mc75rxbuf = mid(mc75rxbuf, 2) getchar = TRUE exit function endif junk = sockinfo(mc75in, sinfo) ' print "Bytes available = ", sinfo[2], nl if sinfo[2] <> 0 then ' print "Reading ", sinfo[2], " Bytes", nl mc75rxbuf = input(sinfo[2], mc75in) ' else ' sleep(1) endif wend end function ' Get a line from mc75in ' Return TRUE if successful, otherwise FALSE ' If TRUE, then line is retuned in the rsp parameter ' function getline(rsp) local junk, sinfo, tbuf, tchr getline = FALSE tbuf = "" while TRUE if getchar(tchr) <> TRUE then exit function ' see if we received a LF (our end of line) if asc(tchr) = 0x0a then rsp = tbuf getline = TRUE exit function endif ' ignore CR, append all other chars if asc(tchr) <> 0x0d then tbuf = tbuf & tchr endif wend end function function getOKline local i, myline getOKline = FALSE for i = 1 to 10 if getline(myline) <> TRUE then exit function if myline = "OK" then getOKline = TRUE exit function endif next i end function ' ' Collect a number of lines into an array ' Stop at OK, ERROR or timeout ' return the number of lines received. ' function getResplines(rsplines) local nlines, i, myline nlines = 0 getResplines = 0 for i = 1 to 10 if getline(myline) <> TRUE then exit function rsplines[nlines] = myline nlines += 1 getResplines = nlines if (instr(myline, "OK") <> undef) or (instr(myline, "ERROR") <> undef) then exit function endif next i end function ' extract a line from an array obtained from getResplines ' function extract_result(rsp_lines, nlines, search_str) local i extract_result = "" for i = 0 to nlines-1 if instr(rsp_lines[i], search_str) <> undef then extract_result = mid(rsp_lines[i], len(search_str)+1) exit function endif next i end function ' Close i/o handles and try to put the config back the way it was ' If using a TCP socket we only have one handle to close. function restorecfg local res, resstr if socketopened = 0 then close(mc75out) endif close(mc75in) sleep(1) res = execute("modemcc 0 asy_add " & asystr, 0, resstr) res = execute("ppp " & gprs_ppp_instance & " use_modem 1", 0, resstr) res = execute("ppp " & gprs_ppp_instance & " aodion on", 0, resstr) end function function get_modem_model local i, nlines, rsplines get_modem_model = "" print #mc75out, "AT+GMM\r" nlines = getResplines(rsplines) if nlines = 0 then eventmsg "No response to AT+GMM" exit function endif if rsplines[nlines-1] <> "OK" then eventmsg "AT+GMM did not return OK, got " & rsplines[nlines-1] exit function endif ' for i = 0 to nlines-1 ' eventmsg "Got line: " & rsplines[i] ' next i for i = 0 to nlines-1 if rsplines[i] <> "" AND rsplines[i] <> "AT+GMM" then get_modem_model = rsplines[i] exit function endif next i end function ' ******** MAIN PROGRAM STARTS HERE ******** errcnt = 0 socketopened = 0 init_log_files() eventmsg "Sprint activation started" ' Get the required parameters. ' First check the command line, as this can override the configured parameters ' Then check the provisioning config settings ' split command() by " " to msl_str, mdn_str, min_str if isundef(msl_str) or isundef(mdn_str) or isundef(min_str) then if getParam("provision 0 string1 ?", msl_str) = TRUE then if getParam("provision 0 string2 ?", mdn_str) = TRUE then if getParam("provision 0 string3 ?", min_str) = TRUE then else errexit "failed to get min_str\r\n" endif else errexit "failed to get mdn_str\r\n" endif else errexit "failed to get msl_str\r\n" endif ' print "\nUsage: sprint.sb \n" ' errexit "Sprint activation failed: missing parameters" ' exit sub endif print "msl_str=", msl_str, ", mdn_str=", mdn_str, ", min_str=", min_str, "\r\n" ' We allow the MSL to be omitted, but if it is present then the PTN and MSID must also be provided ' if msl_str = "" then eventmsg "MSL parameter not present: MDN and MSID will not be programmed " else if mdn_str = "" then errexit "Sprint activation failed: missing PTN parameter" endif if min_str = "" then errexit "Sprint activation failed: missing MSID parameter" endif endif ' Find out what ASY port is used by modemcc for GPRS ' if getParam("modemcc 0 asy_add ?", asystr) = TRUE then print "modemcc 0 asy_add is: ", asystr, nl else errexit "Sprint activation failed: unable to get modemcc 0 asy_add" endif if asystr = "255" or asystr = "0" or asystr = "" then errexit "Sprint activation failed: invalid modemcc asy_add (try muxon)" endif ' Find out which PPP instance is configured for GPRS ' got_gprs_ppp = get_gprs_ppp_instance(gprs_ppp_instance) if got_gprs_ppp then print "PPP ", gprs_ppp_instance, " is configured for GPRS", nl res = execute("ppp " & gprs_ppp_instance & " deact_rq", 0, resstr) sleep(1) res = execute("ppp " & gprs_ppp_instance & " use_modem !", 0, resstr) res = execute("ppp " & gprs_ppp_instance & " aodion off", 0, resstr) else print "No PPP instances configured for GPRS", nl endif res = execute("modemoff", 0, resstr) sleep(5) res = execute("modemcc 0 asy_add 255", 0, resstr) ' initialise the AT serial port AsyPortName = "ASY" & asystr mc75asyport = AsyPortName print "AsyPortName = ", AsyPortName, nl init_mc75io() ' First make sure we can talk to the device by ATing it ' until we get OK back ' i = 0 GotOK = false while i < 10 and GotOK = false i += 1 print "Sending AT...", nl print #mc75out, "AT\r" if getOKline() = true then GotOK = true wend if GotOK = false then restorecfg() errexit "Sprint activation failed: cannot AT device on " & AsyPortName endif ' Now reconnect to the module via a TCP connection ' We need to do this because the Sprint provisioning process can generate ' large bursts of data (typical outout is 33Kbytes). The serial interface has ' a limited receive buffer size, whereas the TCP interface can handle this. ' close(mc75in) close(mc75out) mc75in = 0 mc75port = 4000 + val(asystr) open "127.0.0.1:" & mc75port for socket as mc75in mc75out = mc75in mc75rxbuf = "" socketopened = 1 junk = setevent(0) junk = setevent(mc75in) eventmsg "Sprint: connected to modem on " & AsyPortName modem_model = get_modem_model() eventmsg "Modem model is: " & modem_model reset_cmd = "AT!RESET" iota_cmd = "AT!IOTASTART" if left(modem_model, 6) = "MC5727" then iota_cmd = "AT!DMDC=2" endif ' only write the account activation data if it was supplied ' if msl_str <> "" then namlck_cmd = "AT~NAMLCK=" & msl_str namval_cmd = "AT~NAMVAL=0," & mdn_str & "," & min_str & ",0,0" namval0_cmd = "AT~NAMVAL=0" ' Enter the MSL to unlock the modem ' eventmsg "Sent " & namlck_cmd print #mc75out, namlck_cmd, "\r" if getOKline() = false then restorecfg() errexit "Sprint activation failed: NAMLCK failed" endif ' Enter phonenumber etc ' eventmsg "Sent " & namval_cmd print #mc75out, namval_cmd, "\r" if getOKline() = false then restorecfg() errexit "Sprint activation failed: NAMVAL failed" endif ' Set the NAM ' eventmsg "Sent " & namval0_cmd print #mc75out, namval0_cmd, "\r" if getOKline() = false then restorecfg() errexit "Sprint activation failed: NAMVAL failed" endif ' Send a reset ' eventmsg "Sent " & reset_cmd print #mc75out, reset_cmd, "\r" if getOKline() = false then restorecfg() errexit "Sprint activation failed: RESET failed" endif ' close the socket while we wait for a reset ' close(mc75in) socketopened = 0 eventmsg "Waiting 30 secs for modem reset" sleep(30) ' now reopen the socket ' mc75in = 0 open "127.0.0.1:" & mc75port for socket as mc75in mc75out = mc75in mc75rxbuf = "" socketopened = 1 junk = setevent(0) junk = setevent(mc75in) ' ' First AT the modem again clear_mc75io() i = 0 GotOK = false while i < 10 and GotOK = false i += 1 print "Sending AT...", nl print #mc75out, "AT\r" if getOKline() = true then GotOK = true wend if GotOK = false then restorecfg() errexit "Sprint activation failed: AT failed after RESET" endif endif ' now start up the IOTA session ' eventmsg "Sent " & iota_cmd print #mc75out, iota_cmd, "\r" ' set the end time. ticks are units of 10ms ' 5 mins normally ticks_end = ticks + 5*60*100 ' 15 secs for debugging ' ticks_end = ticks + 15*100 ' now sit and wait for an OK response ' log all output received ' iota_done = FALSE while ticks <= ticks_end and iota_done = FALSE if getline(iotaline) = TRUE then logmsg iotaline if iotaline = "ERROR" then restorecfg() errexit "Sprint activation failed: ERROR result received" endif if iotaline = "OK" then iota_done = TRUE endif endif wend if iota_done = FALSE then restorecfg() errexit "Sprint activation failed: timeout awaiting OK result" endif ' send a reset command. Don't worry about the reply as we'll be rebooting anyway ' eventmsg "Sent AT!RESET" print #mc75out, "AT!RESET\r" ' Restore the modem connection ' restorecfg() errexit "Sprint activation SUCCESSFUL" stop ErrorLabel: 'print "Got error code: ", error(), "(", error$, ")", nl if error() = 22 and errcnt < 20 then print "Retrying connection ...", nl sleep(1) errcnt = errcnt + 1 on error goto ErrorLabel resume endif restorecfg() errexit(error$)