net.lua 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788
  1. ---模块功能:网络管理、信号查询、GSM网络状态查询、网络指示灯控制、临近小区信息查询
  2. -- @module net
  3. -- @author openLuat
  4. -- @license MIT
  5. -- @copyright openLuat
  6. -- @release 2017.02.17
  7. require "sys"
  8. require "ril"
  9. require "pio"
  10. require "sim"
  11. require "log"
  12. require "utils"
  13. module(..., package.seeall)
  14. --加载常用的全局函数至本地
  15. local publish = sys.publish
  16. --netmode define
  17. NetMode_noNet= 0
  18. NetMode_GSM= 1--2G
  19. NetMode_EDGE= 2--2.5G
  20. NetMode_TD= 3--3G
  21. NetMode_LTE= 4--4G
  22. NetMode_WCDMA= 5--3G
  23. local netMode = NetMode_noNet
  24. --网络状态:
  25. --INIT:开机初始化中的状态
  26. --REGISTERED:注册上GSM网络
  27. --UNREGISTER:未注册上GSM网络
  28. local state = "INIT"
  29. --SIM卡状态:true为异常,false或者nil为正常
  30. local simerrsta
  31. -- 飞行模式状态
  32. flyMode = false
  33. --lac:位置区ID
  34. --ci:小区ID
  35. --rssi:信号强度
  36. --rsrp:信号接收功率
  37. local lac, ci, rssi, rsrp, band = "", "", 0, 0, ""
  38. --cellinfo:当前小区和临近小区信息表
  39. --multicellcb:获取多小区的回调函数
  40. local cellinfo, multicellcb = {}
  41. local curCellSeted
  42. local function cops(data)
  43. --+COPS: 0,2,"46000",7
  44. local fmt,oper = data:match('COPS:%s*%d+%s*,(%d+)%s*,"(%d+)"')
  45. log.info("cops",fmt,oper,curCellSeted)
  46. if fmt=="2" and not curCellSeted then
  47. cellinfo[1].mcc = tonumber(oper:sub(1,3),16)
  48. cellinfo[1].mnc = tonumber(oper:sub(4,5),16)
  49. end
  50. end
  51. --[[
  52. 函数名:creg
  53. 功能 :解析CREG信息
  54. 参数 :data:CREG信息字符串,例如+CREG: 2、+CREG: 1,"18be","93e1"、+CREG: 5,"18a7","cb51"
  55. 返回值:无
  56. ]]
  57. local function creg(data)
  58. local p1, s,act
  59. local prefix = (netMode == NetMode_LTE) and "+CEREG: " or (netMode == NetMode_noNet and "+CREG: " or "+CGREG: ")
  60. log.info("net.creg1",netMode,prefix)
  61. if not data:match(prefix) then
  62. --log.info("net.creg2",prefix)
  63. if prefix=="+CREG: " then
  64. --log.info("net.creg3")
  65. prefix = "+CGREG: "
  66. if not data:match("+CGREG: ") then
  67. log.warn("net.creg1","no match",data)
  68. return
  69. end
  70. elseif prefix=="+CGREG: " then
  71. --log.info("net.creg4")
  72. prefix = "+CREG: "
  73. if not data:match("+CREG: ") then
  74. log.warn("net.creg2","no match",data)
  75. return
  76. end
  77. end
  78. end
  79. --获取注册状态
  80. _, _, p1 = data:find(prefix .. "%d,(%d+)")
  81. --log.info("net.creg5",p1 == nil)
  82. if p1 == nil then
  83. _, _, p1 = data:find(prefix .. "(%d+)")
  84. --log.info("net.creg6",p1 == nil)
  85. if p1 == nil then return end
  86. act = data:match(prefix .. "%d+,.-,.-,(%d+)")
  87. else
  88. act = data:match(prefix .. "%d,%d+,.-,.-,(%d+)")
  89. end
  90. log.info("net.creg7",p1,act)
  91. --设置注册状态
  92. s = (p1=="1" or p1=="5") and "REGISTERED" or "UNREGISTER"
  93. --log.info("net.creg8",s,state)
  94. if prefix=="+CGREG: " and s=="UNREGISTER" then
  95. log.info("net.creg9 ignore!!!")
  96. return
  97. end
  98. --注册状态发生了改变
  99. if s ~= state then
  100. --临近小区查询处理
  101. if s == "REGISTERED" then
  102. --产生一个内部消息NET_STATE_CHANGED,表示GSM网络注册状态发生变化
  103. publish("NET_STATE_REGISTERED")
  104. cengQueryPoll()
  105. end
  106. state = s
  107. end
  108. --已注册并且lac或ci发生了变化
  109. if state == "REGISTERED" then
  110. p2, p3 = data:match("\"(%x+)\",\"(%x+)\"")
  111. if p2 and p3 and (lac ~= p2 or ci ~= p3) then
  112. lac = p2
  113. ci = p3
  114. --产生一个内部消息NET_CELL_CHANGED,表示lac或ci发生了变化
  115. publish("NET_CELL_CHANGED")
  116. --cellinfo[1].mcc = tonumber(sim.getMcc(),16)
  117. --cellinfo[1].mnc = tonumber(sim.getMnc(),16)
  118. cellinfo[1].lac = tonumber(lac,16)
  119. cellinfo[1].ci = tonumber(ci,16)
  120. cellinfo[1].rssi = 28
  121. end
  122. if act then
  123. if act=="0" then
  124. UpdNetMode("^MODE: 3,1")
  125. elseif act=="1" then
  126. UpdNetMode("^MODE: 3,2")
  127. elseif act=="3" then
  128. UpdNetMode("^MODE: 3,3")
  129. elseif act=="7" then
  130. UpdNetMode("^MODE: 17,17")
  131. else
  132. UpdNetMode("^MODE: 5,7")
  133. end
  134. end
  135. end
  136. end
  137. --[[
  138. 函数名:resetcellinfo
  139. 功能 :重置当前小区和临近小区信息表
  140. 参数 :无
  141. 返回值:无
  142. ]]
  143. local function resetCellInfo()
  144. local i
  145. cellinfo.cnt = 11 --最大个数
  146. for i = 1, cellinfo.cnt do
  147. cellinfo[i] = {}
  148. cellinfo[i].mcc, cellinfo[i].mnc = nil
  149. cellinfo[i].lac = 0
  150. cellinfo[i].ci = 0
  151. cellinfo[i].rssi = 0
  152. cellinfo[i].ta = 0
  153. end
  154. end
  155. --[[
  156. 函数名:eemMgInfoSvc
  157. 功能 :解析4G网络,当前小区和临近小区信息
  158. 参数 :
  159. data:当前小区和临近小区信息字符串,例如下面中的每一行:
  160. +EEMLTESVC:xx,xx,...
  161. 返回值:无
  162. ]]
  163. local function eemLteSvc(data)
  164. local mcc,mnc,lac,ci,rssi,svcData
  165. if data:match("%+EEMLTESVC:%s*%d+,%s*%d+,%s*%d+,%s*.+") then
  166. svcData = string.match(data, "%+EEMLTESVC:(.+)")
  167. --log.info("eemLteSvc",svcData)
  168. if svcData then
  169. svcDataT = string.split(svcData, ', ')
  170. --log.info("eemLteSvc1",svcDataT[1],svcDataT[3],svcDataT[4],svcDataT[10],svcDataT[15])
  171. if not(svcDataT[1] and svcDataT[3] and svcDataT[4] and svcDataT[10] and svcDataT[15]) then
  172. svcDataT = string.split(svcData, ',')
  173. log.info("eemLteSvc2",svcDataT[1],svcDataT[3],svcDataT[4],svcDataT[10],svcDataT[15])
  174. end
  175. mcc = svcDataT[1]
  176. mnc = svcDataT[3]
  177. lac = svcDataT[4]
  178. ci = svcDataT[10]
  179. band = svcDataT[8]
  180. rssi = (tonumber(svcDataT[15])-(tonumber(svcDataT[15])%3))/3
  181. if rssi>31 then rssi=31 end
  182. if rssi<0 then rssi=0 end
  183. end
  184. log.info("eemLteSvc1",lac,ci,mcc,mnc)
  185. if lac and lac~="0" and ci and ci ~= "0" and mcc and mnc then
  186. --如果是第一条,清除信息表
  187. resetCellInfo()
  188. curCellSeted = true
  189. --保存mcc、mnc、lac、ci、rssi、ta
  190. cellinfo[1].mcc = mcc
  191. cellinfo[1].mnc = mnc
  192. cellinfo[1].lac = tonumber(lac)
  193. cellinfo[1].ci = tonumber(ci)
  194. cellinfo[1].rssi = tonumber(rssi)
  195. --cellinfo[id + 1].ta = tonumber(ta or "0")
  196. --产生一个内部消息CELL_INFO_IND,表示读取到了新的当前小区和临近小区信息
  197. if multicellcb then multicellcb(cellinfo) end
  198. publish("CELL_INFO_IND", cellinfo)
  199. end
  200. elseif data:match("%+EEMLTEINTER") or data:match("%+EEMLTEINTRA") or data:match("%+EEMLTEINTERRAT") then
  201. --data = "+EEMLTEINTRA: 0, 98, 39148, 51, 21, 1120, 0, 6311, 25418539"
  202. --data = "+EEMLTEINTERRAT:0,16,1120,0,6213,26862,627,1,-77"
  203. data = data:gsub(" ","")
  204. if data:match("%+EEMLTEINTERRAT") then
  205. mcc,mnc,lac,ci,rssi = data:match("[-]*%d+,[-]*%d+,([-]*%d+),([-]*%d+),([-]*%d+),([-]*%d+),[-]*%d+,[-]*%d+,([-]*%d+)")
  206. else
  207. rssi,mcc,mnc,lac,ci = data:match("[-]*%d+,[-]*%d+,[-]*%d+,([-]*%d+),[-]*%d+,([-]*%d+),([-]*%d+),([-]*%d+),([-]*%d+)")
  208. end
  209. --print(mcc,mnc,lac,ci,rssi)
  210. if rssi then
  211. rssi = (rssi-(rssi%3))/3
  212. if rssi>31 then rssi=31 end
  213. if rssi<0 then rssi=0 end
  214. end
  215. if lac~="0" and lac~="-1" and ci~="0" and ci~="-1" then
  216. for i = 1, cellinfo.cnt do
  217. --print("cellinfo["..i.."].lac="..cellinfo[i].lac)
  218. if cellinfo[i].lac==0 then
  219. cellinfo[i] =
  220. {
  221. mcc = mcc,
  222. mnc = mnc,
  223. lac = tonumber(lac),
  224. ci = tonumber(ci),
  225. rssi = tonumber(rssi)
  226. }
  227. break
  228. end
  229. end
  230. end
  231. end
  232. end
  233. --[[
  234. 函数名:eemMgInfoSvc
  235. 功能 :解析2G网络,当前小区
  236. 参数 :
  237. data:当前小区信息字符串,例如下面中的每一行:
  238. +EEMGINFOSVC:xx,xx,...
  239. 返回值:无
  240. ]]
  241. local function eemGsmInfoSvc(data)
  242. --只处理有效的CENG信息
  243. if string.find(data, "%+EEMGINFOSVC:%s*%d+,%s*%d+,%s*%d+,%s*.+") then
  244. local mcc,mnc,lac,ci,ta,rssi
  245. local svcData = string.match(data, "%+EEMGINFOSVC:(.+)")
  246. if svcData then
  247. svcDataT = string.split(svcData, ', ')
  248. mcc = svcDataT[1]
  249. mnc = svcDataT[2]
  250. lac = svcDataT[3]
  251. ci = svcDataT[4]
  252. ta = svcDataT[10]
  253. rssi = svcDataT[12]
  254. if tonumber(rssi) >31
  255. then rssi = 31
  256. end
  257. if tonumber(rssi) < 0
  258. then rssi = 0
  259. end
  260. end
  261. if lac and lac~="0" and ci and ci ~= "0" and mcc and mnc then
  262. --如果是第一条,清除信息表
  263. resetCellInfo()
  264. curCellSeted = true
  265. --保存mcc、mnc、lac、ci、rssi、ta
  266. cellinfo[1].mcc = mcc
  267. cellinfo[1].mnc = mnc
  268. cellinfo[1].lac = tonumber(lac)
  269. cellinfo[1].ci = tonumber(ci)
  270. cellinfo[1].rssi = (tonumber(rssi) == 99) and 0 or tonumber(rssi)
  271. cellinfo[1].ta = tonumber(ta or "0")
  272. --产生一个内部消息CELL_INFO_IND,表示读取到了新的当前小区和临近小区信息
  273. if multicellcb then multicellcb(cellinfo) end
  274. publish("CELL_INFO_IND", cellinfo)
  275. end
  276. end
  277. end
  278. --[[
  279. 函数名:eemMgInfoSvc
  280. 功能 :解析2G网络,临近小区信息
  281. 参数 :
  282. data:当前小区和临近小区信息字符串,例如下面中的每一行:
  283. +EEMGINFOSVC:xx,xx,...
  284. 返回值:无
  285. ]]
  286. local function eemGsmNCInfoSvc(data)
  287. if string.find(data, "%+EEMGINFONC: %d+, %d+, %d+, .+") then
  288. local mcc,mnc,lac,ci,ta,rssi,id
  289. local svcData = string.match(data, "%+EEMGINFONC:(.+)")
  290. if svcData then
  291. svcDataT = string.split(svcData, ', ')
  292. id = svcDataT[1]
  293. mcc = svcDataT[2]
  294. mnc = svcDataT[3]
  295. lac = svcDataT[4]
  296. ci = svcDataT[6]
  297. rssi = svcDataT[7]
  298. if tonumber(rssi) >31
  299. then rssi = 31
  300. end
  301. if tonumber(rssi) < 0
  302. then rssi = 0
  303. end
  304. end
  305. if lac and ci and mcc and mnc then
  306. --保存mcc、mnc、lac、ci、rssi、ta
  307. cellinfo[id + 2].mcc = mcc
  308. cellinfo[id + 2].mnc = mnc
  309. cellinfo[id + 2].lac = tonumber(lac)
  310. cellinfo[id + 2].ci = tonumber(ci)
  311. cellinfo[id + 2].rssi = (tonumber(rssi) == 99) and 0 or tonumber(rssi)
  312. --cellinfo[id + 1].ta = tonumber(ta or "0")
  313. end
  314. end
  315. end
  316. --[[
  317. 函数名:eemMgInfoSvc
  318. 功能 :解析3G网络,当前小区和临近小区信息
  319. 参数 :
  320. data:当前小区和临近小区信息字符串,例如下面中的每一行:
  321. +EEMUMTSSVC:xx,xx,...
  322. 返回值:无
  323. ]]
  324. local function eemUMTSInfoSvc(data)
  325. --只处理有效的CENG信息
  326. if string.find(data, "%+EEMUMTSSVC: %d+, %d+, %d+, .+") then
  327. local mcc,mnc,lac,ci,rssi
  328. local svcData = string.match(data, "%+EEMUMTSSVC:(.+)")
  329. local cellMeasureFlag, cellParamFlag = string.match(data, "%+EEMUMTSSVC:%d+, (%d+), (%d+), .+")
  330. local svcDataT = string.split(svcData, ', ')
  331. local offset = 4
  332. if svcData and svcDataT then
  333. if tonumber(cellMeasureFlag) ~= 0 then
  334. offset = offset + 2
  335. rssi = svcDataT[offset]
  336. offset = offset + 4
  337. else
  338. offset = offset + 2
  339. rssi = svcDataT[offset]
  340. offset = offset + 2
  341. end
  342. if tonumber(cellParamFlag) ~= 0 then
  343. offset = offset + 3
  344. mcc = svcDataT[offset]
  345. mnc = svcDataT[offset + 1]
  346. lac = svcDataT[offset + 2]
  347. ci = svcDataT[offset + 3]
  348. offset = offset + 3
  349. end
  350. end
  351. if lac and lac~="0" and ci and ci ~= "0" and mcc and mnc and rssi then
  352. --如果是第一条,清除信息表
  353. resetCellInfo()
  354. curCellSeted = true
  355. --保存mcc、mnc、lac、ci、rssi、ta
  356. cellinfo[1].mcc = mcc
  357. cellinfo[1].mnc = mnc
  358. cellinfo[1].lac = tonumber(lac)
  359. cellinfo[1].ci = tonumber(ci)
  360. cellinfo[1].rssi = tonumber(rssi)
  361. --产生一个内部消息CELL_INFO_IND,表示读取到了新的当前小区和临近小区信息
  362. if multicellcb then multicellcb(cellinfo) end
  363. publish("CELL_INFO_IND", cellinfo)
  364. end
  365. end
  366. end
  367. --[[
  368. 函数名:UpdNetMode
  369. 功能 :解析NetMode
  370. 参数 :data:NetMode信息字符串,例如"^MODE: 17,17"
  371. 返回值:无
  372. ]]
  373. function UpdNetMode(data)
  374. local _, _, SysMainMode,SysMode = string.find(data, "(%d+),(%d+)")
  375. local netMode_cur
  376. log.info("net.UpdNetMode",netMode_cur,netMode, SysMainMode,SysMode)
  377. if SysMainMode and SysMode then
  378. if SysMainMode=="3" then
  379. netMode_cur = NetMode_GSM
  380. elseif SysMainMode=="5" then
  381. netMode_cur = NetMode_WCDMA
  382. elseif SysMainMode=="15" then
  383. netMode_cur = NetMode_TD
  384. elseif SysMainMode=="17" then
  385. netMode_cur = NetMode_LTE
  386. else
  387. netMode_cur = NetMode_noNet
  388. end
  389. if SysMode=="3" then
  390. netMode_cur = NetMode_EDGE
  391. end
  392. end
  393. if netMode ~= netMode_cur then
  394. netMode = netMode_cur
  395. publish("NET_UPD_NET_MODE",netMode)
  396. log.info("net.NET_UPD_NET_MODE",netMode)
  397. ril.request("AT+COPS?")
  398. if netMode == NetMode_LTE then
  399. ril.request("AT+CEREG?")
  400. elseif netMode == NetMode_noNet then
  401. ril.request("AT+CREG?")
  402. else
  403. ril.request("AT+CGREG?")
  404. end
  405. end
  406. end
  407. --[[
  408. 函数名:neturc
  409. 功能 :本功能模块内“注册的底层core通过虚拟串口主动上报的通知”的处理
  410. 参数 :
  411. data:通知的完整字符串信息
  412. prefix:通知的前缀
  413. 返回值:无
  414. ]]
  415. local function neturc(data, prefix)
  416. if prefix=="+COPS" then
  417. cops(data)
  418. elseif prefix == "+CREG" or prefix == "+CGREG" or prefix == "+CEREG" then
  419. --收到网络状态变化时,更新一下信号值
  420. csqQueryPoll()
  421. --解析creg信息
  422. creg(data)
  423. elseif prefix == "+EEMLTESVC" or prefix == "+EEMLTEINTRA" or prefix == "+EEMLTEINTER" or prefix=="+EEMLTEINTERRAT" then
  424. eemLteSvc(data)
  425. elseif prefix == "+EEMUMTSSVC" then
  426. eemUMTSInfoSvc(data)
  427. elseif prefix == "+EEMGINFOSVC" then
  428. eemGsmInfoSvc(data)
  429. elseif prefix == "+EEMGINFONC" then
  430. eemGsmNCInfoSvc(data)
  431. elseif prefix == "^MODE" then
  432. UpdNetMode(data)
  433. end
  434. end
  435. --- 设置飞行模式
  436. -- 注意:如果要测试飞行模式的功耗,开机后不要立即调用此接口进入飞行模式
  437. -- 在模块注册上网络之前,调用此接口进入飞行模式不仅无效,还会导致功耗数据异常
  438. -- 详情参考:http://doc.openluat.com/article/488/0
  439. -- @bool mode true:飞行模式开,false:飞行模式关
  440. -- @return nil
  441. -- @usage net.switchFly(mode)
  442. function switchFly(mode)
  443. if flyMode == mode then return end
  444. flyMode = mode
  445. -- 处理飞行模式
  446. if mode then
  447. ril.request("AT+CFUN=0")
  448. -- 处理退出飞行模式
  449. else
  450. ril.request("AT+CFUN=1")
  451. --处理查询定时器
  452. csqQueryPoll()
  453. cengQueryPoll()
  454. --复位GSM网络状态
  455. neturc("2", "+CREG")
  456. end
  457. end
  458. --- 获取netmode
  459. -- @return number netMode,注册的网络类型
  460. -- 0:未注册
  461. -- 1:2G GSM网络
  462. -- 2:2.5G EDGE数据网络
  463. -- 3:3G TD网络
  464. -- 4:4G LTE网络
  465. -- 5:3G WCDMA网络
  466. -- @usage net.getNetMode()
  467. function getNetMode()
  468. return netMode
  469. end
  470. --- 获取网络注册状态
  471. -- @return string state,GSM网络注册状态,
  472. -- "INIT"表示正在初始化
  473. -- "REGISTERED"表示已注册
  474. -- "UNREGISTER"表示未注册
  475. -- @usage net.getState()
  476. function getState()
  477. return state
  478. end
  479. --- 获取当前小区的mcc
  480. -- @return string mcc,当前小区的mcc,如果还没有注册GSM网络,则返回sim卡的mcc
  481. -- @usage net.getMcc()
  482. function getMcc()
  483. return cellinfo[1].mcc and string.format("%x",cellinfo[1].mcc) or sim.getMcc()
  484. end
  485. --- 获取当前小区的mnc
  486. -- @return string mcn,当前小区的mnc,如果还没有注册GSM网络,则返回sim卡的mnc
  487. -- @usage net.getMnc()
  488. function getMnc()
  489. return cellinfo[1].mnc and string.format("%x",cellinfo[1].mnc) or sim.getMnc()
  490. end
  491. --- 获取当前位置区ID
  492. -- @return string lac,当前位置区ID(16进制字符串,例如"18be"),如果还没有注册GSM网络,则返回""
  493. -- @usage net.getLac()
  494. function getLac()
  495. return lac
  496. end
  497. --- 获取当前注册的网络频段
  498. -- @return string band,当前注册的网络频段,如果还没有注册网络,则返回""
  499. -- @usage net.getBand()
  500. function getBand()
  501. return band
  502. end
  503. --- 获取当前小区ID
  504. -- @return string ci,当前小区ID(16进制字符串,例如"93e1"),如果还没有注册GSM网络,则返回""
  505. -- @usage net.getCi()
  506. function getCi()
  507. return ci
  508. end
  509. --- 获取信号强度
  510. -- 当前注册的是2G网络,就是2G网络的信号强度
  511. -- 当前注册的是4G网络,就是4G网络的信号强度
  512. -- @return number rssi,当前信号强度(取值范围0-31)
  513. -- @usage net.getRssi()
  514. function getRssi()
  515. return rssi
  516. end
  517. --- 4G网络信号接收功率
  518. -- @return number rsrp,当前信号接收功率(取值范围-140 - -40)
  519. -- @usage net.getRsrp()
  520. function getRsrp()
  521. return rsrp
  522. end
  523. function getCell()
  524. local i,ret = 1,""
  525. for i=1,cellinfo.cnt do
  526. if cellinfo[i] and cellinfo[i].lac and cellinfo[i].lac ~= 0 and cellinfo[i].ci and cellinfo[i].ci ~= 0 then
  527. ret = ret..cellinfo[i].ci.."."..cellinfo[i].rssi.."."
  528. end
  529. end
  530. return ret
  531. end
  532. --- 获取当前和临近位置区、小区以及信号强度的拼接字符串
  533. -- @return string cellInfo,当前和临近位置区、小区以及信号强度的拼接字符串,例如:"6311.49234.30;6311.49233.23;6322.49232.18;"
  534. -- @usage net.getCellInfo()
  535. function getCellInfo()
  536. local i, ret = 1, ""
  537. for i = 1, cellinfo.cnt do
  538. if cellinfo[i] and cellinfo[i].lac and cellinfo[i].lac ~= 0 and cellinfo[i].ci and cellinfo[i].ci ~= 0 then
  539. ret = ret .. cellinfo[i].lac .. "." .. cellinfo[i].ci .. "." .. cellinfo[i].rssi .. ";"
  540. end
  541. end
  542. return ret
  543. end
  544. --- 获取当前和临近位置区、小区、mcc、mnc、以及信号的拼接字符串
  545. -- @bool[opt=nil] rssi 信号是否拼接功率,true表示功率,false或者nil表示强度
  546. -- 表示强度时,信号的取值范围是0到31
  547. -- 表示功率时,信号的计算公式为 强度*2-113,取值范围为-113dB到-51dB
  548. -- @return string cellInfo,当前和临近位置区、小区、mcc、mnc、以及信号的拼接字符串,例如:
  549. -- 当rssi参数为true时,"460.01.6311.49234.-73;460.01.6311.49233.-67;460.02.6322.49232.-77;"
  550. -- 当rssi参数为false或者nil时,"460.01.6311.49234.30;460.01.6311.49233.23;460.02.6322.49232.18;"
  551. -- @usage net.getCellInfoExt()
  552. function getCellInfoExt(rssi)
  553. local i, ret = 1, ""
  554. for i = 1, cellinfo.cnt do
  555. if cellinfo[i] and cellinfo[i].mcc and cellinfo[i].mnc and cellinfo[i].lac and cellinfo[i].lac ~= 0 and cellinfo[i].ci and cellinfo[i].ci ~= 0 then
  556. ret = ret .. string.format("%x",cellinfo[i].mcc) .. "." .. string.format("%x",cellinfo[i].mnc) .. "." .. cellinfo[i].lac .. "." .. cellinfo[i].ci .. "." .. (rssi and (cellinfo[i].rssi*2-113) or cellinfo[i].rssi) .. ";"
  557. end
  558. end
  559. return ret
  560. end
  561. --- 获取TA值
  562. -- @return number ta,TA值
  563. -- @usage net.getTa()
  564. function getTa()
  565. return cellinfo[1].ta
  566. end
  567. --[[
  568. 函数名:rsp
  569. 功能 :本功能模块内“通过虚拟串口发送到底层core软件的AT命令”的应答处理
  570. 参数 :
  571. cmd:此应答对应的AT命令
  572. success:AT命令执行结果,true或者false
  573. response:AT命令的应答中的执行结果字符串
  574. intermediate:AT命令的应答中的中间信息
  575. 返回值:无
  576. ]]
  577. local function rsp(cmd, success, response, intermediate)
  578. local prefix = string.match(cmd, "AT(%+%u+)")
  579. if intermediate ~= nil then
  580. if prefix == "+CSQ" then
  581. local s = string.match(intermediate, "+CSQ:%s*(%d+)")
  582. if s ~= nil then
  583. rssi = tonumber(s)
  584. rssi = rssi == 99 and 0 or rssi
  585. --产生一个内部消息GSM_SIGNAL_REPORT_IND,表示读取到了信号强度
  586. publish("GSM_SIGNAL_REPORT_IND", success, rssi)
  587. end
  588. elseif prefix == "+CESQ" then
  589. local s = string.match(intermediate, "+CESQ: %d+,%d+,%d+,%d+,%d+,(%d+)")
  590. if s ~= nil then
  591. rsrp = tonumber(s)
  592. end
  593. elseif prefix == "+CENG" then end
  594. end
  595. if prefix == "+CFUN" then
  596. if success then publish("FLYMODE", flyMode) end
  597. end
  598. end
  599. --- 实时读取“当前和临近小区信息”
  600. -- @function cbFnc 回调函数,当读取到小区信息后,会调用此回调函数,回调函数的调用形式为:
  601. -- cbFnc(cells),其中cells为string类型,格式为:当前和临近位置区、小区、mcc、mnc、以及信号强度的拼接字符串,例如:"460.01.6311.49234.30;460.01.6311.49233.23;460.02.6322.49232.18;"
  602. -- @return nil
  603. function getMultiCell(cbFnc)
  604. multicellcb = cbFnc
  605. --发送AT+CENG?查询
  606. ril.request("AT+EEMGINFO?")
  607. end
  608. --- 发起查询基站信息(当前和临近小区信息)的请求
  609. -- @number period 查询间隔,单位毫秒
  610. -- @return bool result, true:查询成功,false:查询失败
  611. -- @usage net.cengQueryPoll() --查询1次
  612. -- @usage net.cengQueryPoll(60000) --每分钟查询1次
  613. function cengQueryPoll(period)
  614. -- 不是飞行模式 并且 工作模式为完整模式
  615. if not flyMode then
  616. --发送AT+CENG?查询
  617. ril.request("AT+EEMGINFO?")
  618. else
  619. log.warn("net.cengQueryPoll", "flymode:", flyMode)
  620. end
  621. if nil ~= period then
  622. --启动定时器
  623. sys.timerStopAll(cengQueryPoll)
  624. sys.timerStart(cengQueryPoll, period, period)
  625. end
  626. return not flyMode
  627. end
  628. --- 发起查询信号强度的请求
  629. -- @number period 查询间隔,单位毫秒
  630. -- @return bool , true:查询成功,false:查询停止
  631. -- @usage net.csqQueryPoll() --查询1次
  632. -- @usage net.csqQueryPoll(60000) --每分钟查询1次
  633. function csqQueryPoll(period)
  634. --不是飞行模式 并且 工作模式为完整模式
  635. if not flyMode then
  636. --发送AT+CSQ查询
  637. ril.request("AT+CSQ")
  638. ril.request("AT+CESQ")
  639. else
  640. log.warn("net.csqQueryPoll", "flymode:", flyMode)
  641. end
  642. if nil ~= period then
  643. --启动定时器
  644. sys.timerStopAll(csqQueryPoll)
  645. sys.timerStart(csqQueryPoll, period, period)
  646. end
  647. return not flyMode
  648. end
  649. --- 设置查询信号强度和基站信息的间隔
  650. -- @number ... 查询周期,参数可变,参数为nil只查询1次,参数1是信号强度查询周期,参数2是基站查询周期
  651. -- @return bool ,true:设置成功,false:设置失败
  652. -- @usage net.startQueryAll()
  653. -- @usage net.startQueryAll(60000) -- 1分钟查询1次信号强度,只立即查询1次基站信息
  654. -- @usage net.startQueryAll(60000,600000) -- 1分钟查询1次信号强度,10分钟查询1次基站信息
  655. function startQueryAll(...)
  656. local arg = { ... }
  657. csqQueryPoll(arg[1])
  658. cengQueryPoll(arg[2])
  659. if flyMode then
  660. log.info("sim.startQuerAll", "flyMode:", flyMode)
  661. end
  662. return true
  663. end
  664. --- 停止查询信号强度和基站信息
  665. -- @return 无
  666. -- @usage net.stopQueryAll()
  667. function stopQueryAll()
  668. sys.timerStopAll(csqQueryPoll)
  669. sys.timerStopAll(cengQueryPoll)
  670. end
  671. local sEngMode
  672. --- 设置工程模式
  673. -- @number[opt=1] mode 工程模式,目前仅支持0和1
  674. -- mode为0时,不支持临近小区查询,休眠时功耗较低
  675. -- mode为1时,支持临近小区查询,但是休眠时功耗较高
  676. -- @return nil
  677. -- @usage
  678. -- net.setEngMode(0)
  679. function setEngMode(mode)
  680. sEngMode = mode or 1
  681. ril.request("AT+EEMOPT="..sEngMode,nil,function(cmd,success)
  682. function retrySetEngMode()
  683. setEngMode(sEngMode)
  684. end
  685. if success then
  686. sys.timerStop(retrySetEngMode)
  687. else
  688. sys.timerStart(retrySetEngMode,3000)
  689. end
  690. end)
  691. end
  692. -- 处理SIM卡状态消息,SIM卡工作不正常时更新网络状态为未注册
  693. sys.subscribe("SIM_IND", function(para)
  694. log.info("SIM.subscribe", simerrsta, para)
  695. if simerrsta ~= (para ~= "RDY") then
  696. simerrsta = (para ~= "RDY")
  697. end
  698. --sim卡工作不正常
  699. if para ~= "RDY" then
  700. --更新GSM网络状态
  701. state = "UNREGISTER"
  702. --产生内部消息NET_STATE_CHANGED,表示网络状态发生变化
  703. publish("NET_STATE_UNREGISTER")
  704. else
  705. --state = "INIT"
  706. end
  707. end)
  708. --注册+CREG和+CENG通知的处理函数
  709. ril.regUrc("+COPS", neturc)
  710. ril.regUrc("+CREG", neturc)
  711. ril.regUrc("+CGREG", neturc)
  712. ril.regUrc("+CEREG", neturc)
  713. --ril.regUrc("+CENG", neturc)
  714. ril.regUrc("+EEMLTESVC", neturc)
  715. ril.regUrc("+EEMLTEINTER", neturc)
  716. ril.regUrc("+EEMLTEINTRA", neturc)
  717. ril.regUrc("+EEMLTEINTERRAT", neturc)
  718. ril.regUrc("+EEMGINFOSVC", neturc)
  719. ril.regUrc("+EEMGINFONC", neturc)
  720. ril.regUrc("+EEMUMTSSVC", neturc)
  721. ril.regUrc("^MODE", neturc)
  722. --ril.regUrc("+CRSM", neturc)
  723. --注册AT+CCSQ和AT+CENG?命令的应答处理函数
  724. ril.regRsp("+CSQ", rsp)
  725. ril.regRsp("+CESQ",rsp)
  726. --ril.regRsp("+CENG", rsp)
  727. ril.regRsp("+CFUN", rsp)-- 飞行模式
  728. --发送AT命令
  729. ril.request("AT+COPS?")
  730. ril.request("AT+CREG=2")
  731. ril.request("AT+CGREG=2")
  732. ril.request("AT+CEREG=2")
  733. ril.request("AT+CREG?")
  734. ril.request("AT+CGREG?")
  735. ril.request("AT+CEREG?")
  736. ril.request("AT+CALIBINFO?")
  737. ril.request("AT*BAND?")
  738. setEngMode(1)
  739. --重置当前小区和临近小区信息表
  740. resetCellInfo()