' manual.sb
'
' This runs through the provisioning commands on a Sierra Wireless MC5725 CDMA module.
' Usage:
'
' bas manual.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 mstat.txt
' Web files mstat.asp and mstat1.asp are also generated to allow progress
' to be observed at the web interface
'
' Parameter values are obtained from the "provision 0 stringx ..." configuration values, as follows:
' string4: MSL/SPC
' string5: MDN
' string6: MIN/MSID
' string7: MIP profile number
' string8: NAI
' string9: MIP home address
' string10: Primary home agent
' string11: Secondary home agent
' string12: HA shared secret
' string13: AAA shared secret
' string14: HA SPI
' string15: AAA SPI
' string16: Reverse tunneling
' 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 "mstat.asp" for output as fh
print #fh, "\r\n"
print #fh, "
\r\n"
print #fh, "\r\n"
print #fh, "\r\n"
print #fh, "\r\n"
close fh
aspout=0
open "mstat.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 mstat1 frame page
function log_status(log_msg)
local fh
fh = 0
open "mstat1.asp" for output as fh
print #fh, "\r\n"
print #fh, "\r\n"
print #fh, "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, "
"
print #fh, "\r\n"
print #fh, "\r\n"
print #fh, "\r\n"
close fh
end function
' Close i/o handles and try to put the config back the way it was
'
function restorecfg
local res, resstr
close(mc75out)
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
' Enter an error message in the event log and exit
' Also prints message to console output
' And updates the web status page
'
function errexit(dorestore, msg)
if dorestore <> 0 then restorecfg()
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
' Return the value of a parameter from a list such as
' string1: value1
' string2: value2
'
function getParamFromList(strdata, strname)
local pos, pos1
getParamFromList = ""
pos = instr(strdata, strname)
if pos > 0 then
pos1 = instr(strdata,nl,pos)
if pos1 > 0 then
getParamFromList = mid(strData,pos + len(strname) + 1,pos1 - pos - len(strname) - 1)
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
if waitevents(1000) = mc75in then
junk = sockinfo(mc75in, sinfo)
' print "Bytes available = ", sinfo[2], nl
if sinfo[2] <> 0 then
mc75rxbuf = input(sinfo[2], mc75in)
endif
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 15
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
' sends a command to the modem and returns the first reponse line
'
function modem_cmd(cmd_str)
local i, nlines, rsplines
modem_cmd = ""
print #mc75out, cmd_str & "\r"
nlines = getResplines(rsplines)
if nlines = 0 then
eventmsg "No response to " & cmd_str
exit function
endif
if rsplines[nlines-1] <> "OK" then
eventmsg cmd_str & " 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] <> cmd_str then
modem_cmd = rsplines[i]
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
' hex and ascii dump of a string
'
function dump_packet(pkt)
local i, j, n, ll, chval, astr
n = len(pkt)
print "Received ", n, " bytes\r\n"
i = 1
while n > 0
if n >= 16 then
ll = 16
else
ll = n
endif
for j = i to i+ll-1
print format("%02X", asc(mid(pkt,j,1))), " "
next j
astr = string((16-ll)*3+4, " ")
for j = i to i+ll-1
chval = asc(mid(pkt,j,1))
if chval >= 0x20 and chval <= 0x7e then
astr = astr & mid(pkt,j,1)
else
astr = astr & "."
endif
next j
print astr, "\r\n"
n -= 16
i += 16
wend
end function
' ******** MAIN PROGRAM STARTS HERE ********
errcnt = 0
init_log_files()
eventmsg "Manual provisioning script started"
' Get the required parameters by checking the provisioning config settings
'
junk = execute("provision 0 ?", 0, p_str)
if instr(p_str, "\r\nOK\r\n") <> undef then
for i = 1 to 16
cfg_strings[i] = getParamFromList(p_str, "string" & i & ":")
' print "String" & i & " value = \"" & cfg_strings[i] & "\"\r\n"
next i
else
' dump_packet(p_str)
errexit 0, "Failed to get provisioning prameters: provision 0 ? command failed"
endif
' MSL, MDN and MIN are now optional
' if cfg_strings[4] = "" then errexit 0, "Failed: missing MSL parameter"
' if cfg_strings[5] = "" then errexit 0, "Failed: missing MDN parameter"
' if cfg_strings[6] = "" then errexit 0, "Failed: missing MIN/MSID parameter"
' prv_strings[1] = "AT~NAMLCK=%s"
' prv_strings[2] = "AT~NAMVAL=0,%s,%s,%s,%s"
' eventmsg "Output1 = " & format(prv_strings[1], cfg_strings[4])
' eventmsg "Output2 = " & format(prv_strings[2], cfg_strings[5], cfg_strings[6], "0", "0")
' 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 0, "Provisioning failed: unable to get modemcc 0 asy_add"
endif
' if asystr = "255" or asystr = "0" or asystr = "" then
' errexit 0, "Provisioning failed: invalid modemcc asy_add (try muxon)"
' endif
if asystr = "255" or asystr = "" then
errexit 0, "Provisioning 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("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 errexit 1, "Provisioning failed: cannot AT device on " & AsyPortName
eventmsg "Connected to modem on " & AsyPortName
' Query the ESN, which might be used for part of the NAI
'
esn = modem_cmd("AT+GSN")
if esn = "" then errexit "Provisioning failed: unable to read the ESN"
eventmsg "ESN = " & esn
' First query the MIN/MDN/SID/NID
' We should get something like this:
'
' at~namval?0
' MDN: 2023292944
' MIN: 2023292944
' SID: 18
' NID: 65535
print #mc75out, "AT~NAMVAL?0\r"
nrsplines = getResplines(rsplines)
if nrsplines <> 0 then
if rsplines[nrsplines-1] = "OK" then
sid = extract_result(rsplines, nrsplines, "SID: ")
nid = extract_result(rsplines, nrsplines, "NID: ")
if sid = "" or nid = "" then errexit 1, "Failed to get SID/NID: NAMVAL command failed"
else
errexit 1, "Failed to get SID/NID: NAMVAL command failed"
endif
else
errexit 1, "Failed: no response to NAMVAL command"
endif
reset_cmd = "AT!RESET"
' we now only program the MDN and MIN if the MSL is provided
'
if cfg_strings[4] <> "" then
namlck_cmd = "AT~NAMLCK=" & cfg_strings[4]
namval_cmd = "AT~NAMVAL=0," & cfg_strings[5] & "," & cfg_strings[6] & "," & sid & "," & nid
' Enter the MSL to unlock the modem
'
eventmsg "Sent " & namlck_cmd
print #mc75out, namlck_cmd, "\r"
if getOKline() = false then errexit 1, "Provisioning failed: NAMLCK failed"
' Enter phonenumber etc
'
eventmsg "Sent " & namval_cmd
print #mc75out, namval_cmd, "\r"
if getOKline() = false then errexit 1, "Provisioning failed: NAMVAL failed"
' We finish the process here if the MIP profile number and NAI are empty
'
if cfg_strings[7] = "" and cfg_strings[8] = "" then
eventmsg "Sent " & reset_cmd
print #mc75out, reset_cmd, "\r"
if getOKline() = false then errexit 1, "Provisioning failed: RESET failed"
errexit 1, "Manual provisioning complete"
endif
endif
' Continue to program the MIP parameters.
' Check that the MIP profile number and NAI both present
'
if cfg_strings[7] = "" then errexit 1, "Failed: Mobile IP profile number is missing"
if cfg_strings[8] = "" then errexit 1, "Failed: NAI is missing"
' MIP profile:
mip_cmd = "AT$QCMIPP=" & cfg_strings[7]
eventmsg "Sent " & mip_cmd
print #mc75out, mip_cmd, "\r"
if getOKline() = false then errexit 1, "Provisioning failed: bad response to " & mip_cmd
' construct the NAI, substituting the ESN if it begins with ESN
'
if left(cfg_strings[8], 3) = "ESN" then
nai_str = mid(esn, 3) & mid(cfg_strings[8], 4)
else
nai_str = cfg_strings[8]
endif
' NAI:
mip_cmd = "AT$QCMIPNAI=" & nai_str & ",1"
eventmsg "Sent " & mip_cmd
print #mc75out, mip_cmd, "\r"
if getOKline() = false then errexit 1, "Provisioning failed: bad response to " & mip_cmd
' MIP Home Address (optional):
if cfg_strings[9] <> "" then
mip_cmd = "AT$QCMIPHA=" & cfg_strings[9] & ",1"
eventmsg "Sent " & mip_cmd
print #mc75out, mip_cmd, "\r"
if getOKline() = false then errexit 1, "Provisioning failed: bad response to " & mip_cmd
endif
' Primary Home Agent Address (optional):
if cfg_strings[10] <> "" then
mip_cmd = "AT$QCMIPPHA=" & cfg_strings[10] & ",1"
eventmsg "Sent " & mip_cmd
print #mc75out, mip_cmd, "\r"
if getOKline() = false then errexit 1, "Provisioning failed: bad response to " & mip_cmd
endif
' Secondary Home Agent Address (optional):
if cfg_strings[11] <> "" then
mip_cmd = "AT$QCMIPSHA=" & cfg_strings[11] & ",1"
eventmsg "Sent " & mip_cmd
print #mc75out, mip_cmd, "\r"
if getOKline() = false then errexit 1, "Provisioning failed: bad response to " & mip_cmd
endif
' HA shared secret (optional):
if cfg_strings[12] <> "" then
if left(cfg_strings[12], 2) = "0x" then
mip_cmd = "AT$QCMIPMHSSX=" & mid(cfg_strings[12], 3) & ",1"
else
mip_cmd = "AT$QCMIPMHSS=" & cfg_strings[12] & ",1"
endif
eventmsg "Sent " & mip_cmd
print #mc75out, mip_cmd, "\r"
if getOKline() = false then errexit 1, "Provisioning failed: bad response to " & mip_cmd
endif
' AAA shared secret (optional):
if cfg_strings[13] <> "" then
if left(cfg_strings[13], 2) = "0x" then
mip_cmd = "AT$QCMIPMASSX=" & mid(cfg_strings[13], 3) & ",1"
else
mip_cmd = "AT$QCMIPMASS=" & cfg_strings[13] & ",1"
endif
eventmsg "Sent " & mip_cmd
print #mc75out, mip_cmd, "\r"
if getOKline() = false then errexit 1, "Provisioning failed: bad response to " & mip_cmd
endif
' HA SPI (optional):
if cfg_strings[14] <> "" then
mip_cmd = "AT$QCMIPMHSPI=" & cfg_strings[14] & ",1"
eventmsg "Sent " & mip_cmd
print #mc75out, mip_cmd, "\r"
if getOKline() = false then errexit 1, "Provisioning failed: bad response to " & mip_cmd
endif
' AAA SPI (optional):
if cfg_strings[15] <> "" then
mip_cmd = "AT$QCMIPMASPI=" & cfg_strings[15] & ",1"
eventmsg "Sent " & mip_cmd
print #mc75out, mip_cmd, "\r"
if getOKline() = false then errexit 1, "Provisioning failed: bad response to " & mip_cmd
endif
' Reverse tunneling (optional):
if cfg_strings[16] <> "" then
if cfg_strings[16] <> "no" and cfg_strings[16] <> "0" and cfg_strings[16] <> "off" then
mip_cmd = "AT$QCMIPRT=1"
else
mip_cmd = "AT$QCMIPRT=0"
endif
eventmsg "Sent " & mip_cmd
print #mc75out, mip_cmd, "\r"
if getOKline() = false then errexit 1, "Provisioning failed: bad response to " & mip_cmd
endif
' enable the profile
mip_cmd = "AT$QCMIPEP=1"
eventmsg "Sent " & mip_cmd
print #mc75out, mip_cmd, "\r"
if getOKline() = false then errexit 1, "Provisioning failed: bad response to " & mip_cmd
' Now query the currently active MIP Profile
' We should get something like this:
'
' at$qcmipgetp
' Profile:0 Enabled
' NAI:5555001883@iusamipevo.com
' Home Addr:0.0.0.0
' Primary HA:255.255.255.255
' Secondary HA:207.83.200.222
' MN-AAA SPI:2
' MN-HA SPI:257
' Rev Tun:1
' MN-AAA SS:Set
' MN-HA SS:Set
'
print #mc75out, "AT$QCMIPGETP\r"
nrsplines = getResplines(rsplines)
if nrsplines <> 0 then
if rsplines[nrsplines-1] = "OK" then
for i = 0 to nrsplines-1
eventmsg rsplines[i]
next i
else
errexit 1, "Failed to read back MIP profile: QCMIPGETP command failed"
endif
else
errexit 1, "Failed: no response to QCMIPGETP command"
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
'
errexit 1, "Manual provisioning commands completed successfully"
stop
ErrorLabel:
'print "Got error code: ", error(), "(", error$, ")", nl
if error() = 22 and errcnt < 10 then
print "Retrying connection ...", nl
sleep(1)
errcnt = errcnt + 1
on error goto ErrorLabel
resume
endif
errexit(1, error$)