luat_lib_mobile.c 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026
  1. /*
  2. @module mobile
  3. @summary 蜂窝网络
  4. @version 1.0
  5. @date 2022.8.9
  6. @demo mobile
  7. @tag LUAT_USE_MOBILE
  8. @usage
  9. -- 简单演示
  10. log.info("imei", mobile.imei())
  11. log.info("imsi", mobile.imsi())
  12. local sn = mobile.sn()
  13. if sn then
  14. log.info("sn", sn:toHex())
  15. end
  16. log.info("muid", mobile.muid())
  17. log.info("iccid", mobile.iccid())
  18. log.info("csq", mobile.csq())
  19. log.info("rssi", mobile.rssi())
  20. log.info("rsrq", mobile.rsrq())
  21. log.info("rsrp", mobile.rsrp())
  22. log.info("snr", mobile.snr())
  23. log.info("simid", mobile.simid())
  24. */
  25. #include "luat_base.h"
  26. #include "luat_malloc.h"
  27. #include "luat_rtos.h"
  28. #include "luat_msgbus.h"
  29. #include "luat_mobile.h"
  30. #include "luat_network_adapter.h"
  31. #define LUAT_LOG_TAG "mobile"
  32. #include "luat_log.h"
  33. /**
  34. 获取IMEI
  35. @api mobile.imei(index)
  36. @int 编号,默认0. 在支持双卡的模块上才会出现0或1的情况
  37. @return string 当前的IMEI值,若失败返回nil
  38. */
  39. static int l_mobile_imei(lua_State* L) {
  40. char buff[24] = {0};
  41. // size_t len = 0;
  42. // size_t wlen = 0;
  43. int ret = 0;
  44. int index = luaL_optinteger(L, 1, 0);
  45. ret = luat_mobile_get_imei(index, buff, 24);
  46. // if (lua_isstring(L, 2)) {
  47. // const char* wbuff = luaL_checklstring(L, 2, &wlen);
  48. // if (wlen >= 15) {
  49. // ret = luat_mobile_set_imei(index, wbuff, wlen);
  50. // LLOGI("IMEI write %d %s ret %d", index, wbuff, ret);
  51. // }
  52. // }
  53. if (ret > 0) {
  54. buff[23] = 0x00; // 确保能结束
  55. lua_pushlstring(L, buff, strlen(buff));
  56. }
  57. else
  58. lua_pushnil(L);
  59. return 1;
  60. }
  61. /**
  62. 获取IMSI
  63. @api mobile.imsi(index)
  64. @int 编号,默认0. 在支持双卡的模块上才会出现0或1的情况
  65. @return string 当前的IMSI值,若失败返回nil
  66. */
  67. static int l_mobile_imsi(lua_State* L) {
  68. char buff[24] = {0};
  69. // size_t len = 0;
  70. // size_t wlen = 0;
  71. int ret = 0;
  72. int index = luaL_optinteger(L, 1, 0);
  73. ret = luat_mobile_get_imsi(index, buff, 24);
  74. // if (lua_isstring(L, 2)) {
  75. // const char* wbuff = luaL_checklstring(L, 2, &wlen);
  76. // if (wlen >= 1) {
  77. // ret = luat_mobile_set_imsi(index, wbuff, wlen);
  78. // LLOGI("IMSI write %d %s ret %d", index, wbuff, ret);
  79. // }
  80. // }
  81. if (ret > 0){
  82. buff[23] = 0x00; // 确保能结束
  83. lua_pushlstring(L, buff, strlen(buff));
  84. }
  85. else
  86. lua_pushnil(L);
  87. return 1;
  88. }
  89. /**
  90. 获取SN
  91. @api mobile.sn()
  92. @return string 当前的SN值,若失败返回nil. 注意, SN可能包含不可见字符
  93. */
  94. static int l_mobile_sn(lua_State* L) {
  95. char buff[32] = {0};
  96. // size_t len = 0;
  97. // size_t wlen = 0;
  98. int ret = 0;
  99. ret = luat_mobile_get_sn(buff, 32);
  100. // if (lua_isstring(L, 1)) {
  101. // const char* wbuff = luaL_checklstring(L, 1, &wlen);
  102. // if (wlen >= 1) {
  103. // ret = luat_mobile_set_sn(wbuff, wlen);
  104. // LLOGI("SN write %d %s ret %d", index, wbuff, ret);
  105. // }
  106. // }
  107. if (ret > 0) {
  108. //buff[63] = 0x00; // 确保能结束
  109. lua_pushlstring(L, buff, ret);
  110. }
  111. else
  112. lua_pushnil(L);
  113. return 1;
  114. }
  115. /**
  116. 获取MUID
  117. @api mobile.muid()
  118. @return string 当前的MUID值,若失败返回nil
  119. */
  120. static int l_mobile_muid(lua_State* L) {
  121. char buff[33] = {0};
  122. // size_t len = 0;
  123. // size_t wlen = 0;
  124. int ret = 0;
  125. ret = luat_mobile_get_muid(buff, 32);
  126. if (lua_isstring(L, 1)) {
  127. // const char* wbuff = luaL_checklstring(L, 1, &wlen);
  128. // if (wlen >= 15) {
  129. // ret = luat_mobile_set_muid(index, wbuff, wlen);
  130. // LLOGI("SN write %d %s ret %d", index, wbuff, ret);
  131. // }
  132. }
  133. if (ret > 0) {
  134. lua_pushlstring(L, buff, strlen(buff));
  135. }
  136. else
  137. lua_pushnil(L);
  138. return 1;
  139. }
  140. /**
  141. 获取或设置ICCID
  142. @api mobile.iccid(id)
  143. @int SIM卡的编号, 例如0, 1, 默认0
  144. @return string ICCID值,若失败返回nil
  145. */
  146. static int l_mobile_iccid(lua_State* L) {
  147. char buff[24] = {0};
  148. // size_t len = 0;
  149. // size_t wlen = 0;
  150. int ret = 0;
  151. int index = luaL_optinteger(L, 1, 0);
  152. ret = luat_mobile_get_iccid(index, buff, 24);
  153. if (ret > 0) {
  154. buff[23] = 0x00; // 确保能结束
  155. lua_pushlstring(L, buff, strlen(buff));
  156. }
  157. else
  158. lua_pushnil(L);
  159. return 1;
  160. }
  161. /**
  162. 获取手机卡号,注意,只有写入了手机号才能读出,因此有可能读出来是空的
  163. @api mobile.number(id)
  164. @int SIM卡的编号, 例如0, 1, 默认0
  165. @return string number值,若失败返回nil
  166. */
  167. static int l_mobile_number(lua_State* L) {
  168. char buff[24] = {0};
  169. // size_t len = 0;
  170. // size_t wlen = 0;
  171. int ret = 0;
  172. int index = luaL_optinteger(L, 1, 0);
  173. ret = luat_mobile_get_sim_number(index, buff, 24);
  174. if (ret > 0) {
  175. buff[23] = 0x00; // 确保能结束
  176. lua_pushlstring(L, buff, strlen(buff));
  177. }
  178. else
  179. lua_pushnil(L);
  180. return 1;
  181. }
  182. /**
  183. 获取当前SIM卡槽,或者切换卡槽
  184. @api mobile.simid(id)
  185. @int SIM卡的编号, 例如0, 1, 如果支持双卡,比如EC618,可以填2来自适应,但是会占用掉4个IO(gpio4/5/6/23)。如果不填就直接读取当前卡槽
  186. @boolean 是否优先用SIM0,只有SIM卡编号写2自适应才有用!!!。true优先用SIM0,false则优先用上一次探测到的,默认是false,必须在开机就配置,否则就无效了
  187. @return int 当前sim卡槽编号,若失败返回-1
  188. @usage
  189. -- 注意, SIM1会占用GPIO4/5/6/23
  190. mobile.simid(0) -- 固定使用SIM0
  191. mobile.simid(1) -- 固件使用SIM1
  192. mobile.simid(2) -- 自动识别SIM0, SIM1, 且SIM0优先
  193. mobile.simid(2, true) -- -- 自动识别SIM0, SIM1, 且SIM1优先
  194. -- 提醒, 自动识别是会增加时间的
  195. */
  196. static int l_mobile_simid(lua_State* L) {
  197. // char buff[24] = {0};
  198. int ret = 0;
  199. int id = 0;
  200. if (lua_isinteger(L, 1)) {
  201. ret = luat_mobile_set_sim_id(lua_tointeger(L, 1));
  202. LLOGI("sim set to %d , ret %d", lua_tointeger(L, 1), ret);
  203. }
  204. if (LUA_TBOOLEAN == lua_type(L, 2)) {
  205. if (lua_toboolean(L, 2)) {
  206. luat_mobile_set_sim_detect_sim0_first();
  207. }
  208. }
  209. ret = luat_mobile_get_sim_id(&id);
  210. if (ret == 0) {
  211. lua_pushinteger(L, id);
  212. }
  213. else {
  214. lua_pushinteger(L, -1);
  215. }
  216. return 1;
  217. }
  218. /**
  219. 检测当前SIM卡是否准备好,对SIM卡的PIN码做相关操作
  220. @api mobile.simPin(id,operation,pin1,pin2)
  221. @int SIM卡的编号, 例如0, 1, 支持双卡双待的才需要选择
  222. @int PIN码操作类型,只能是mobile.PIN_XXXX,不操作就留空
  223. @string 更换pin时操作的pin码,或者验证操作的pin码,或者解锁pin码时的PUK,4~8字节
  224. @string 更换pin码操作时的新的pin码,解锁pin码时的新PIN,4~8字节
  225. @return boolean 当无PIN操作时,返回SIM卡是否准备好,有PIN操作时,返回是否成功
  226. @usage
  227. local cpin_is_ready = mobile.simPin() -- 当前sim卡是否准备好,一般返回false就是没卡
  228. local succ = mobile.simPin(0, mobile.PIN_VERIFY, "1234") -- 输入pin码验证
  229. */
  230. static int l_mobile_sim_pin(lua_State* L) {
  231. char old[9] = {0};
  232. char new[9] = {0};
  233. int id = luaL_optinteger(L, 1, 0);
  234. int operation = luaL_optinteger(L, 2, -1);
  235. size_t old_len, new_len;
  236. if (lua_isstring(L, 3))
  237. {
  238. const char *old_pin = lua_tolstring(L, 3, &old_len);
  239. memcpy(old, old_pin, (old_len > 8)?8:old_len);
  240. }
  241. if (lua_isstring(L, 4))
  242. {
  243. const char *new_pin = lua_tolstring(L, 4, &new_len);
  244. memcpy(new, new_pin, (new_len > 8)?8:new_len);
  245. }
  246. if (operation != -1)
  247. {
  248. lua_pushboolean(L, (luat_mobile_set_sim_pin(id, operation, old, new) == 0));
  249. }
  250. else
  251. {
  252. lua_pushboolean(L, (luat_mobile_get_sim_ready(id) == 1));
  253. }
  254. return 1;
  255. }
  256. /**
  257. 设置RRC自动释放时间间隔,当开启时后,遇到极弱信号+频繁数据操作可能会引起网络严重故障,因此需要额外设置自动重启协议栈
  258. @api mobile.rtime(time, auto_reset_stack)
  259. @int RRC自动释放时间,等同于Air724的AT+RTIME,单位秒,写0或者不写则是停用,不要超过20秒,没有意义
  260. @boolean 网络遇到严重故障时尝试自动恢复,和飞行模式/SIM卡切换冲突,true开启,false关闭,留空时,如果设置了时间则自动开启
  261. @return nil 无返回值
  262. */
  263. static int l_mobile_set_rrc_auto_release_time(lua_State* L) {
  264. luat_mobile_set_rrc_auto_release_time(luaL_optinteger(L, 1, 0));
  265. if (LUA_TBOOLEAN == lua_type(L, 2)) {
  266. luat_mobile_fatal_error_auto_reset_stack(lua_toboolean(L, 2));
  267. }
  268. else
  269. {
  270. if (luaL_optinteger(L, 1, 0))
  271. {
  272. luat_mobile_fatal_error_auto_reset_stack(1);
  273. }
  274. }
  275. return 0;
  276. }
  277. /**
  278. 设置一些辅助周期性或者自动功能,目前支持SIM卡暂时脱离后恢复,周期性获取小区信息,网络遇到严重故障时尝试自动恢复
  279. @api mobile.setAuto(check_sim_period, get_cell_period, search_cell_time, auto_reset_stack)
  280. @int SIM卡自动恢复时间,单位毫秒,建议5000~10000,和飞行模式/SIM卡切换冲突,不能再同一时间使用,必须错开执行。写0或者不写则是关闭功能
  281. @int 周期性获取小区信息的时间间隔,单位毫秒。获取小区信息会增加部分功耗。写0或者不写则是关闭功能
  282. @int 每次搜索小区时最大搜索时间,单位秒。不要超过8秒
  283. @boolean 网络遇到严重故障时尝试自动恢复,和飞行模式/SIM卡切换冲突,true开启,false关闭,开始状态是false,留空则不做改变
  284. @int 设置定时检测网络是否正常并且在检测到长时间无网时通过重启协议栈来恢复,无网恢复时长,单位ms,建议60000以上,为网络搜索网络保留足够的时间,留空则不做更改
  285. @return nil 无返回值
  286. */
  287. static int l_mobile_set_auto_work(lua_State* L) {
  288. luat_mobile_set_period_work(luaL_optinteger(L, 2, 0), luaL_optinteger(L, 1, 0), luaL_optinteger(L, 3, 0));
  289. if (LUA_TBOOLEAN == lua_type(L, 4)) {
  290. luat_mobile_fatal_error_auto_reset_stack(lua_toboolean(L, 4));
  291. }
  292. if (lua_isinteger(L, 5)) {
  293. luat_mobile_set_check_network_period(luaL_optinteger(L, 5, 0));
  294. }
  295. return 0;
  296. }
  297. /**
  298. 获取或设置APN,设置APN必须在入网前就设置好,比如在SIM卡识别完成前就设置好
  299. @api mobile.apn(index, cid, new_apn_name, user_name, password, ip_type, protocol)
  300. @int 编号,默认0. 在支持双卡的模块上才会出现0或1的情况
  301. @int cid, 默认0,如果要用非默认APN来激活,必须>0
  302. @string 新的APN,不填就是获取APN, 填了就是设置APN, 是否支持设置取决于底层实现
  303. @string 新的APN的username,可以为nil
  304. @string 新的APN的password,可以为nil
  305. @int 激活APN时的IP TYPE,1=IPV4 2=IPV6 3=IPV4V6,默认是1
  306. @int 激活APN时,如果需要username和password,就要写鉴权协议类型,1~3,默认3,代表1和2都尝试一下
  307. @boolean 是否删除APN,true是,其他都否,只有参数3新的APN不是string的时候才有效果
  308. @return string 获取到的默认APN值,失败返回nil
  309. */
  310. static int l_mobile_apn(lua_State* L) {
  311. char buff[64] = {0};
  312. size_t len = 0;
  313. size_t wlen = 0;
  314. int ret = 0;
  315. int index = luaL_optinteger(L, 1, 0);
  316. int cid = luaL_optinteger(L, 2, 0);
  317. ret = luat_mobile_get_apn(index, cid, buff, sizeof(buff) - 1);
  318. if (lua_isstring(L, 3)) {
  319. const char* wbuff = luaL_checklstring(L, 3, &wlen);
  320. size_t user_name_len = 0;
  321. size_t password_len = 0;
  322. const char* user_name = luaL_checklstring(L, 4, &user_name_len);
  323. const char* password = luaL_checklstring(L, 5, &password_len);
  324. uint8_t ip_type = luaL_optinteger(L, 6, 1);
  325. uint8_t protocol = luaL_optinteger(L, 7, 3);
  326. if (!user_name_len && !password_len)
  327. {
  328. protocol = 0;
  329. }
  330. if (wlen) {
  331. luat_mobile_user_apn_auto_active(index, cid, ip_type, protocol, wbuff, wlen, user_name, user_name_len, password, password_len);
  332. }
  333. else
  334. {
  335. luat_mobile_user_apn_auto_active(index, cid, ip_type, 0xff, NULL, 0, NULL, 0, NULL, 0);
  336. }
  337. }
  338. else
  339. {
  340. if (lua_isboolean(L, 8) && lua_toboolean(L, 8))
  341. {
  342. luat_mobile_del_apn(index, cid, 0);
  343. }
  344. }
  345. if (ret > 0) {
  346. lua_pushlstring(L, buff, strlen(buff));
  347. }
  348. else
  349. lua_pushnil(L);
  350. return 1;
  351. }
  352. /**
  353. 是否默认开启IPV6功能,必须在LTE网络连接前就设置好
  354. @api mobile.ipv6(onff)
  355. @boolean 开关 true开启 false 关闭
  356. @return boolean true 当前是开启的,false 当前是关闭的
  357. */
  358. static int l_mobile_ipv6(lua_State* L) {
  359. // char buff[24] = {0};
  360. // uint8_t onoff;
  361. if (LUA_TBOOLEAN == lua_type(L, 1)) {
  362. luat_mobile_set_default_pdn_ipv6(lua_toboolean(L, 1));
  363. }
  364. lua_pushboolean(L, luat_mobile_get_default_pdn_ipv6());
  365. return 1;
  366. }
  367. /**
  368. 获取csq
  369. @api mobile.csq()
  370. @return int 当前CSQ值, 若失败返回0
  371. */
  372. static int l_mobile_csq(lua_State* L) {
  373. // luat_mobile_signal_strength_info_t info = {0};
  374. uint8_t csq = 0;
  375. if (luat_mobile_get_signal_strength(&csq) == 0) {
  376. lua_pushinteger(L, (int)csq);
  377. }
  378. else {
  379. lua_pushinteger(L, 0);
  380. }
  381. return 1;
  382. }
  383. /**
  384. 获取rssi
  385. @api mobile.rssi()
  386. @return int 当前rssi值,若失败返回0
  387. */
  388. static int l_mobile_rssi(lua_State* L) {
  389. luat_mobile_signal_strength_info_t info = {0};
  390. if (luat_mobile_get_signal_strength_info(&info) == 0) {
  391. lua_pushinteger(L, info.lte_signal_strength.rssi);
  392. }
  393. else {
  394. lua_pushinteger(L, 0);
  395. }
  396. return 1;
  397. }
  398. /**
  399. 获取rsrp
  400. @api mobile.rsrp()
  401. @return int 当前rsrp值,若失败返回0
  402. */
  403. static int l_mobile_rsrp(lua_State* L) {
  404. luat_mobile_signal_strength_info_t info = {0};
  405. if (luat_mobile_get_signal_strength_info(&info) == 0) {
  406. lua_pushinteger(L, info.lte_signal_strength.rsrp);
  407. }
  408. else {
  409. lua_pushinteger(L, 0);
  410. }
  411. return 1;
  412. }
  413. /**
  414. 获取rsrq
  415. @api mobile.rsrq()
  416. @return int 当前rsrq值,若失败返回0
  417. */
  418. static int l_mobile_rsrq(lua_State* L) {
  419. luat_mobile_signal_strength_info_t info = {0};
  420. if (luat_mobile_get_signal_strength_info(&info) == 0) {
  421. lua_pushinteger(L, info.lte_signal_strength.rsrq);
  422. }
  423. else {
  424. lua_pushinteger(L, 0);
  425. }
  426. return 1;
  427. }
  428. /**
  429. 获取snr
  430. @api mobile.snr()
  431. @return int 当前snq值,若失败返回0
  432. */
  433. static int l_mobile_snr(lua_State* L) {
  434. luat_mobile_signal_strength_info_t info = {0};
  435. if (luat_mobile_get_signal_strength_info(&info) == 0) {
  436. lua_pushinteger(L, info.lte_signal_strength.snr);
  437. }
  438. else {
  439. lua_pushinteger(L, 0);
  440. }
  441. return 1;
  442. }
  443. /**
  444. 获取当前服务小区的ECI(E-UTRAN Cell Identifier)
  445. @api mobile.eci()
  446. @return int 当前eci值,若失败返回-1
  447. */
  448. static int l_mobile_eci(lua_State* L) {
  449. uint32_t eci;
  450. if (luat_mobile_get_service_cell_identifier(&eci) == 0) {
  451. lua_pushinteger(L, eci);
  452. }
  453. else {
  454. lua_pushinteger(L, -1);
  455. }
  456. return 1;
  457. }
  458. /**
  459. 获取当前服务小区的eNBID(eNodeB Identifier)
  460. @api mobile.enbid()
  461. @return int 当前enbid值,若失败返回-1
  462. */
  463. static int l_mobile_enbid(lua_State* L) {
  464. uint32_t eci;
  465. if (luat_mobile_get_service_cell_identifier(&eci) == 0) {
  466. lua_pushinteger(L, eci>>8);
  467. }
  468. else {
  469. lua_pushinteger(L, -1);
  470. }
  471. return 1;
  472. }
  473. /**
  474. 进出飞行模式
  475. @api mobile.flymode(index, enable)
  476. @int 编号,默认0. 在支持双卡的模块上才会出现0或1的情况
  477. @bool 是否设置为飞行模式,true为设置, false为退出,可选
  478. @return bool 原飞行模式的状态
  479. */
  480. static int l_mobile_flymode(lua_State* L) {
  481. int index = luaL_optinteger(L, 1, 0);
  482. int flymode = luat_mobile_get_flymode(index);
  483. if (lua_isboolean(L, 2)) {
  484. luat_mobile_set_flymode(index, lua_toboolean(L, 2));
  485. }
  486. lua_pushboolean(L, flymode == 0 ? 0 : 1);
  487. return 1;
  488. }
  489. /**
  490. 获取网络状态
  491. @api mobile.status()
  492. @return int 当前网络状态,0:网络未注册;1:网络已注册;2:正在搜网中;3:网络注册被拒绝
  493. */
  494. static int l_mobile_status(lua_State* L) {
  495. int LUAT_MOBILE_REGISTER_STATUS_E = luat_mobile_get_register_status();
  496. lua_pushinteger(L, LUAT_MOBILE_REGISTER_STATUS_E);
  497. return 1;
  498. }
  499. static inline uint16_t u162bcd(uint16_t src) {
  500. uint8_t high = (src >> 8) & 0xFF;
  501. uint8_t low = src & 0xFF;
  502. uint16_t dst = 0;
  503. dst += (low & 0x0F) + (low >> 4) * 10;
  504. dst += ((high & 0x0F) + (high >> 4) * 10) * 100;
  505. //LLOGD("src %04X dst %d", src, dst);
  506. return dst;
  507. }
  508. /**
  509. 获取机制信息
  510. @api mobile.getCellInfo()
  511. @return table 包含基站数据的数组
  512. @usage
  513. --示例输出
  514. --[[
  515. [
  516. {"rsrq":-10,"rssi":-55,"cid":124045360,"mnc":17,"pci":115,"earfcn":1850,"snr":15,"rsrp":-85,"mcc":1120,"tdd":0},
  517. {"pci":388,"rsrq":-11,"mnc":17,"earfcn":2452,"snr":5,"rsrp":-67,"mcc":1120,"cid":124045331},
  518. {"pci":100,"rsrq":-9,"mnc":17,"earfcn":75,"snr":17,"rsrp":-109,"mcc":1120,"cid":227096712}
  519. ]
  520. ]]
  521. -- 订阅式
  522. sys.subscribe("CELL_INFO_UPDATE", function()
  523. log.info("cell", json.encode(mobile.getCellInfo()))
  524. end)
  525. -- 定期轮训式
  526. sys.taskInit(function()
  527. sys.wait(3000)
  528. while 1 do
  529. mobile.reqCellInfo(15)
  530. sys.waitUntil("CELL_INFO_UPDATE", 15000)
  531. log.info("cell", json.encode(mobile.getCellInfo()))
  532. end
  533. end)
  534. */
  535. static int l_mobile_get_cell_info(lua_State* L) {
  536. lua_newtable(L);
  537. luat_mobile_cell_info_t* info = luat_heap_malloc(sizeof(luat_mobile_cell_info_t));
  538. if (info == NULL) {
  539. LLOGE("out of memory when malloc cell_info");
  540. return 1;
  541. }
  542. int ret = luat_mobile_get_last_notify_cell_info(info);
  543. if (ret != 0) {
  544. LLOGI("none cell info found %d", ret);
  545. goto exit;
  546. }
  547. //LLOGD("cid %d neighbor %d", info->lte_service_info.cid, info->lte_neighbor_info_num);
  548. // 当前仅返回lte信息
  549. if (info->lte_info_valid == 0 || info->lte_service_info.cid == 0) {
  550. LLOGI("lte cell info not found");
  551. goto exit;
  552. }
  553. lua_newtable(L);
  554. lua_pushinteger(L, info->lte_service_info.pci);
  555. lua_setfield(L, -2, "pci");
  556. lua_pushinteger(L, info->lte_service_info.cid);
  557. lua_setfield(L, -2, "cid");
  558. lua_pushinteger(L, info->lte_service_info.earfcn);
  559. lua_setfield(L, -2, "earfcn");
  560. lua_pushinteger(L, info->lte_service_info.rsrp);
  561. lua_setfield(L, -2, "rsrp");
  562. lua_pushinteger(L, info->lte_service_info.rsrq);
  563. lua_setfield(L, -2, "rsrq");
  564. lua_pushinteger(L, info->lte_service_info.rssi);
  565. lua_setfield(L, -2, "rssi");
  566. lua_pushinteger(L, info->lte_service_info.is_tdd);
  567. lua_setfield(L, -2, "tdd");
  568. lua_pushinteger(L, info->lte_service_info.snr);
  569. lua_setfield(L, -2, "snr");
  570. lua_pushinteger(L, u162bcd(info->lte_service_info.mcc));
  571. lua_setfield(L, -2, "mcc");
  572. lua_pushinteger(L, u162bcd(info->lte_service_info.mnc));
  573. lua_setfield(L, -2, "mnc");
  574. lua_pushinteger(L, info->lte_service_info.tac);
  575. lua_setfield(L, -2, "tac");
  576. lua_pushinteger(L, info->lte_service_info.band);
  577. lua_setfield(L, -2, "band");
  578. lua_seti(L, -2, 1);
  579. if (info->lte_neighbor_info_num > 0) {
  580. for (size_t i = 0; i < info->lte_neighbor_info_num; i++)
  581. {
  582. lua_settop(L, 1);
  583. //LLOGD("add neighbor %d", i);
  584. lua_newtable(L);
  585. lua_pushinteger(L, info->lte_info[i].pci);
  586. lua_setfield(L, -2, "pci");
  587. lua_pushinteger(L, info->lte_info[i].cid);
  588. lua_setfield(L, -2, "cid");
  589. lua_pushinteger(L, info->lte_info[i].earfcn);
  590. lua_setfield(L, -2, "earfcn");
  591. lua_pushinteger(L, info->lte_info[i].rsrp);
  592. lua_setfield(L, -2, "rsrp");
  593. lua_pushinteger(L, info->lte_info[i].rsrq);
  594. lua_setfield(L, -2, "rsrq");
  595. lua_pushinteger(L, u162bcd(info->lte_info[i].mcc));
  596. lua_setfield(L, -2, "mcc");
  597. lua_pushinteger(L, u162bcd(info->lte_info[i].mnc));
  598. lua_setfield(L, -2, "mnc");
  599. lua_pushinteger(L, info->lte_info[i].snr);
  600. lua_setfield(L, -2, "snr");
  601. lua_pushinteger(L, info->lte_info[i].tac);
  602. lua_setfield(L, -2, "tac");
  603. lua_seti(L, -2, i + 2);
  604. }
  605. }
  606. lua_settop(L, 1);
  607. exit:
  608. luat_heap_free(info);
  609. return 1;
  610. }
  611. /**
  612. 发起基站信息查询,含临近小区
  613. @api mobile.reqCellInfo(timeout)
  614. @int 超时时长,单位秒,默认15. 最少5, 最高60
  615. @return nil 无返回值
  616. @usage
  617. -- 参考 mobile.getCellInfo 函数
  618. */
  619. static int l_mobile_request_cell_info(lua_State* L) {
  620. int timeout = luaL_optinteger(L, 1, 15);
  621. if (timeout > 60)
  622. timeout = 60;
  623. else if (timeout < 5)
  624. timeout = 5;
  625. luat_mobile_get_cell_info_async(timeout);
  626. return 0;
  627. }
  628. /**
  629. 重启协议栈
  630. @api mobile.reset()
  631. @usage
  632. -- 重启LTE协议栈
  633. mobile.reset()
  634. */
  635. static int l_mobile_reset(lua_State* L) {
  636. luat_mobile_reset_stack();
  637. return 0;
  638. }
  639. /**
  640. 数据量流量处理
  641. @api mobile.dataTraffic(clearUplink, clearDownlink)
  642. @boolean 清空上行流量累计值,true清空,其他忽略
  643. @boolean 清空下行流量累计值,true清空,其他忽略
  644. @return int 上行流量GB
  645. @return int 上行流量B
  646. @return int 下行流量GB
  647. @return int 下行流量B
  648. @usage
  649. -- 获取上下行流量累计值
  650. -- 上行流量值Byte = uplinkGB * 1024 * 1024 * 1024 + uplinkB
  651. -- 下行流量值Byte = downlinkGB * 1024 * 1024 * 1024 + downlinkB
  652. local uplinkGB, uplinkB, downlinkGB, downlinkB = mobile.dataTraffic()
  653. -- 清空上下行流量累计值
  654. mobile.dataTraffic(true, true)
  655. */
  656. static int l_mobile_data_traffic(lua_State* L) {
  657. uint64_t uplink;
  658. uint64_t downlink;
  659. uint8_t clear_uplink = 0;
  660. uint8_t clear_downlink = 0;
  661. volatile uint32_t temp;
  662. if (LUA_TBOOLEAN == lua_type(L, 1)) {
  663. clear_uplink = lua_toboolean(L, 1);
  664. }
  665. if (LUA_TBOOLEAN == lua_type(L, 2)) {
  666. clear_downlink = lua_toboolean(L, 2);
  667. }
  668. luat_mobile_get_ip_data_traffic(&uplink, &downlink);
  669. if (clear_uplink || clear_downlink) {
  670. luat_mobile_clear_ip_data_traffic(clear_uplink, clear_downlink);
  671. }
  672. temp = (uint32_t)(uplink >> 30);
  673. lua_pushinteger(L, temp);
  674. temp = (((uint32_t)uplink) & 0x3FFFFFFF);
  675. lua_pushinteger(L, temp);
  676. temp = (uint32_t)(downlink >> 30);
  677. lua_pushinteger(L, temp);
  678. temp = (((uint32_t)downlink) & 0x3FFFFFFF);
  679. lua_pushinteger(L, temp);
  680. return 4;
  681. }
  682. extern int luat_mobile_config(uint8_t item, uint32_t value);
  683. /**
  684. 网络特殊配置,针对不同平台有不同的配置,谨慎使用,目前只有EC618
  685. @api mobile.config(item, value)
  686. @int 配置项目,看mobile.CONF_XXX
  687. @int 配置值
  688. @return boolean 是否成功
  689. @usage
  690. -- EC618配置小区重选信号差值门限,不能大于15dbm,必须在飞行模式下才能用
  691. mobile.flymode(0,true)
  692. mobile.config(mobile.CONF_RESELTOWEAKNCELL, 15)
  693. mobile.config(mobile.CONF_STATICCONFIG, 1) --开启网络静态优化
  694. mobile.flymode(0,false)
  695. */
  696. static int l_mobile_config(lua_State* L) {
  697. uint8_t item = luaL_optinteger(L, 1, 0);
  698. uint32_t value = luaL_optinteger(L, 2, 0);
  699. if (!item)
  700. {
  701. lua_pushboolean(L, 0);
  702. }
  703. else
  704. {
  705. lua_pushboolean(L, !luat_mobile_config(item, value));
  706. }
  707. return 1;
  708. }
  709. #include "rotable2.h"
  710. static const rotable_Reg_t reg_mobile[] = {
  711. {"status", ROREG_FUNC(l_mobile_status)},
  712. {"imei", ROREG_FUNC(l_mobile_imei)},
  713. {"imsi", ROREG_FUNC(l_mobile_imsi)},
  714. {"sn", ROREG_FUNC(l_mobile_sn)},
  715. {"iccid", ROREG_FUNC(l_mobile_iccid)},
  716. {"number", ROREG_FUNC(l_mobile_number)},
  717. {"muid", ROREG_FUNC(l_mobile_muid)},
  718. {"apn", ROREG_FUNC(l_mobile_apn)},
  719. {"ipv6", ROREG_FUNC(l_mobile_ipv6)},
  720. {"csq", ROREG_FUNC(l_mobile_csq)},
  721. {"rssi", ROREG_FUNC(l_mobile_rssi)},
  722. {"rsrq", ROREG_FUNC(l_mobile_rsrq)},
  723. {"rsrp", ROREG_FUNC(l_mobile_rsrp)},
  724. {"snr", ROREG_FUNC(l_mobile_snr)},
  725. {"eci", ROREG_FUNC(l_mobile_eci)},
  726. {"enbid", ROREG_FUNC(l_mobile_enbid)},
  727. {"flymode", ROREG_FUNC(l_mobile_flymode)},
  728. {"simid", ROREG_FUNC(l_mobile_simid)},
  729. {"simPin", ROREG_FUNC(l_mobile_sim_pin)},
  730. {"rtime", ROREG_FUNC(l_mobile_set_rrc_auto_release_time)},
  731. {"setAuto", ROREG_FUNC(l_mobile_set_auto_work)},
  732. {"getCellInfo", ROREG_FUNC(l_mobile_get_cell_info)},
  733. {"reqCellInfo", ROREG_FUNC(l_mobile_request_cell_info)},
  734. {"reset", ROREG_FUNC(l_mobile_reset)},
  735. {"dataTraffic", ROREG_FUNC(l_mobile_data_traffic)},
  736. {"config", ROREG_FUNC(l_mobile_config)},
  737. //@const UNREGISTER number 未注册
  738. {"UNREGISTER", ROREG_INT(LUAT_MOBILE_STATUS_UNREGISTER)},
  739. //@const REGISTERED number 已注册
  740. {"REGISTERED", ROREG_INT(LUAT_MOBILE_STATUS_REGISTERED)},
  741. //@const SEARCH number 正在搜索中
  742. {"SEARCH", ROREG_INT(LUAT_MOBILE_STATUS_SEARCHING)},
  743. //@const DENIED number 注册被拒绝
  744. {"DENIED", ROREG_INT(LUAT_MOBILE_STATUS_DENIED)},
  745. //@const UNKNOW number 未知
  746. {"UNKNOW", ROREG_INT(LUAT_MOBILE_STATUS_UNKNOW)},
  747. //@const REGISTERED_ROAMING number 已注册,漫游
  748. {"REGISTERED_ROAMING", ROREG_INT(LUAT_MOBILE_STATUS_REGISTERED_ROAMING)},
  749. //@const SMS_ONLY_REGISTERED number 已注册,仅SMS
  750. {"SMS_ONLY_REGISTERED", ROREG_INT(LUAT_MOBILE_STATUS_SMS_ONLY_REGISTERED)},
  751. //@const SMS_ONLY_REGISTERED_ROAMING number 已注册,漫游,仅SMS
  752. {"SMS_ONLY_REGISTERED_ROAMING", ROREG_INT(LUAT_MOBILE_STATUS_SMS_ONLY_REGISTERED_ROAMING)},
  753. //@const EMERGENCY_REGISTERED number 已注册,紧急服务
  754. {"EMERGENCY_REGISTERED", ROREG_INT(LUAT_MOBILE_STATUS_EMERGENCY_REGISTERED)},
  755. //@const CSFB_NOT_PREFERRED_REGISTERED number 已注册,非主要服务
  756. {"CSFB_NOT_PREFERRED_REGISTERED", ROREG_INT(LUAT_MOBILE_STATUS_CSFB_NOT_PREFERRED_REGISTERED)},
  757. //@const CSFB_NOT_PREFERRED_REGISTERED_ROAMING number 已注册,非主要服务,漫游
  758. {"CSFB_NOT_PREFERRED_REGISTERED_ROAMING", ROREG_INT(LUAT_MOBILE_STATUS_CSFB_NOT_PREFERRED_REGISTERED_ROAMING)},
  759. //@const CONF_RESELTOWEAKNCELL number 小区重选信号差值门限,需要飞行模式设置
  760. {"CONF_RESELTOWEAKNCELL", ROREG_INT(MOBILE_CONF_RESELTOWEAKNCELL)},
  761. //@const CONF_STATICCONFIG number 网络静态模式优化,需要飞行模式设置
  762. {"CONF_STATICCONFIG", ROREG_INT(MOBILE_CONF_STATICCONFIG)},
  763. //@const CONF_QUALITYFIRST number 网络切换以信号质量优先,需要飞行模式设置
  764. {"CONF_QUALITYFIRST", ROREG_INT(MOBILE_CONF_QUALITYFIRST)},
  765. //@const CONF_USERDRXCYCLE number LTE跳paging,需要飞行模式设置,谨慎使用,0是不设置,1~7增大或减小DrxCycle周期倍数,1:1/8倍 2:1/4倍 3:1/2倍 4:2倍 5:4倍 6:8倍 7:16倍,8~12配置固定的DrxCycle周期,仅当该周期大于网络分配的DrxCycle周期时该配置才会生效,8:320ms 9:640ms 10:1280ms 11:2560ms 12:5120ms
  766. {"CONF_USERDRXCYCLE", ROREG_INT(MOBILE_CONF_USERDRXCYCLE)},
  767. //@const CONF_T3324MAXVALUE number PSM模式中的T3324时间,单位S
  768. {"CONF_T3324MAXVALUE", ROREG_INT(MOBILE_CONF_T3324MAXVALUE)},
  769. //@const CONF_PSM_MODE number PSM模式开关,0关,1开
  770. {"CONF_PSM_MODE", ROREG_INT(MOBILE_CONF_PSM_MODE)},
  771. //@const CONF_CE_MODE number attach模式,0为EPS ONLY 2为混合,遇到IMSI detach脱网问题,设置为0,注意设置为EPS ONLY时会取消短信功能
  772. {"CONF_CE_MODE", ROREG_INT(MOBILE_CONF_CE_MODE)},
  773. //@const PIN_VERIFY number 验证PIN码操作
  774. {"PIN_VERIFY", ROREG_INT(LUAT_SIM_PIN_VERIFY)},
  775. //@const PIN_CHANGE number 更换PIN码操作
  776. {"PIN_CHANGE", ROREG_INT(LUAT_SIM_PIN_CHANGE)},
  777. //@const PIN_ENABLE number 使能PIN码验证
  778. {"PIN_ENABLE", ROREG_INT(LUAT_SIM_PIN_ENABLE)},
  779. //@const PIN_DISABLE number 关闭PIN码验证
  780. {"PIN_DISABLE", ROREG_INT(LUAT_SIM_PIN_DISABLE)},
  781. //@const PIN_UNBLOCK number 解锁PIN码
  782. {"PIN_UNBLOCK", ROREG_INT(LUAT_SIM_PIN_UNBLOCK)},
  783. {NULL, ROREG_INT(0)}
  784. };
  785. LUAMOD_API int luaopen_mobile( lua_State *L ) {
  786. luat_newlib2(L, reg_mobile);
  787. return 1;
  788. }
  789. static int l_mobile_event_handle(lua_State* L, void* ptr) {
  790. LUAT_MOBILE_EVENT_E event;
  791. uint8_t index;
  792. uint8_t status;
  793. int ret;
  794. rtos_msg_t* msg = (rtos_msg_t*)lua_topointer(L, -1);
  795. event = msg->arg1;
  796. index = msg->arg2 >> 8;
  797. status = msg->arg2 & 0xFF;
  798. // luat_mobile_cell_info_t cell_info;
  799. // luat_mobile_signal_strength_info_t signal_info;
  800. // uint8_t csq, i;
  801. // char imsi[20];
  802. // char iccid[24] = {0};
  803. if (lua_getglobal(L, "sys_pub") != LUA_TFUNCTION) {
  804. return 0;
  805. };
  806. switch(event)
  807. {
  808. case LUAT_MOBILE_EVENT_CFUN:
  809. break;
  810. case LUAT_MOBILE_EVENT_SIM:
  811. /*
  812. @sys_pub mobile
  813. sim卡状态变化
  814. SIM_IND
  815. @usage
  816. sys.subscribe("SIM_IND", function(status)
  817. -- status的取值有:
  818. -- RDY SIM卡就绪
  819. -- NORDY 无SIM卡
  820. -- SIM_PIN 需要输入PIN
  821. -- GET_NUMBER 获取到电话号码(不一定有值)
  822. log.info("sim status", status)
  823. end)
  824. */
  825. switch (status)
  826. {
  827. case LUAT_MOBILE_SIM_READY:
  828. lua_pushstring(L, "SIM_IND");
  829. lua_pushstring(L, "RDY");
  830. lua_call(L, 2, 0);
  831. break;
  832. case LUAT_MOBILE_NO_SIM:
  833. lua_pushstring(L, "SIM_IND");
  834. lua_pushstring(L, "NORDY");
  835. lua_call(L, 2, 0);
  836. break;
  837. case LUAT_MOBILE_SIM_NEED_PIN:
  838. lua_pushstring(L, "SIM_IND");
  839. lua_pushstring(L, "SIM_PIN");
  840. lua_call(L, 2, 0);
  841. break;
  842. case LUAT_MOBILE_SIM_NUMBER:
  843. lua_pushstring(L, "SIM_IND");
  844. lua_pushstring(L, "GET_NUMBER");
  845. lua_call(L, 2, 0);
  846. break;
  847. default:
  848. break;
  849. }
  850. break;
  851. case LUAT_MOBILE_EVENT_REGISTER_STATUS:
  852. break;
  853. case LUAT_MOBILE_EVENT_CELL_INFO:
  854. switch (status)
  855. {
  856. case LUAT_MOBILE_CELL_INFO_UPDATE:
  857. /*
  858. @sys_pub mobile
  859. 基站数据已更新
  860. CELL_INFO_UPDATE
  861. @usage
  862. -- 订阅式, 模块本身会周期性查询基站信息,但通常不包含临近小区
  863. sys.subscribe("CELL_INFO_UPDATE", function()
  864. log.info("cell", json.encode(mobile.getCellInfo()))
  865. end)
  866. */
  867. lua_pushstring(L, "CELL_INFO_UPDATE");
  868. lua_call(L, 1, 0);
  869. break;
  870. default:
  871. break;
  872. }
  873. break;
  874. case LUAT_MOBILE_EVENT_PDP:
  875. LLOGD("cid%d, state%d", index, status);
  876. break;
  877. case LUAT_MOBILE_EVENT_NETIF:
  878. switch (status)
  879. {
  880. case LUAT_MOBILE_NETIF_LINK_ON:
  881. LLOGD("NETIF_LINK_ON -> IP_READY");
  882. /*
  883. @sys_pub mobile
  884. 已联网
  885. IP_READY
  886. @usage
  887. -- 联网后会发一次这个消息
  888. sys.subscribe("IP_READY", function(ip, adapter)
  889. log.info("mobile", "IP_READY", ip, (adapter or -1) == socket.LWIP_GP)
  890. end)
  891. */
  892. lua_pushstring(L, "IP_READY");
  893. luat_ip_addr_t local_ip, net_mask, gate_way, ipv6;
  894. #ifdef LUAT_USE_LWIP
  895. ipv6.type = 0xff;
  896. int ret = network_get_full_local_ip_info(NULL, NW_ADAPTER_INDEX_LWIP_GPRS, &local_ip, &net_mask, &gate_way, &ipv6);
  897. #else
  898. void* userdata = NULL;
  899. network_adapter_info* info = network_adapter_fetch(NW_ADAPTER_INDEX_LWIP_GPRS, &userdata);
  900. if (info == NULL)
  901. ret = -1;
  902. else
  903. ret = info->get_local_ip_info(&local_ip, &net_mask, &gate_way, userdata);
  904. #endif
  905. if (ret == 0) {
  906. #ifdef LUAT_USE_LWIP
  907. lua_pushfstring(L, "%s", ipaddr_ntoa(&local_ip));
  908. #else
  909. lua_pushfstring(L, "%d.%d.%d.%d", (local_ip.ipv4 >> 24) & 0xFF, (local_ip.ipv4 >> 16) & 0xFF, (local_ip.ipv4 >> 8) & 0xFF, (local_ip.ipv4 >> 0) & 0xFF);
  910. #endif
  911. }
  912. else {
  913. lua_pushliteral(L, "0.0.0.0");
  914. }
  915. lua_pushinteger(L, NW_ADAPTER_INDEX_LWIP_GPRS);
  916. lua_call(L, 3, 0);
  917. break;
  918. case LUAT_MOBILE_NETIF_LINK_OFF:
  919. LLOGD("NETIF_LINK_OFF -> IP_LOSE");
  920. /*
  921. @sys_pub mobile
  922. 已断网
  923. IP_LOSE
  924. @usage
  925. -- 断网后会发一次这个消息
  926. sys.subscribe("IP_LOSE", function(adapter)
  927. log.info("mobile", "IP_LOSE", (adapter or -1) == socket.LWIP_GP)
  928. end)
  929. */
  930. lua_pushstring(L, "IP_LOSE");
  931. lua_pushinteger(L, NW_ADAPTER_INDEX_LWIP_GPRS);
  932. lua_call(L, 2, 0);
  933. break;
  934. default:
  935. break;
  936. }
  937. break;
  938. case LUAT_MOBILE_EVENT_TIME_SYNC:
  939. /*
  940. @sys_pub mobile
  941. 时间已经同步
  942. NTP_UPDATE
  943. @usage
  944. -- 对于电信/移动的卡, 联网后,基站会下发时间,但联通卡不会,务必留意
  945. sys.subscribe("NTP_UPDATE", function()
  946. log.info("mobile", "time", os.date())
  947. end)
  948. */
  949. LLOGD("TIME_SYNC %d", status);
  950. lua_pushstring(L, "NTP_UPDATE");
  951. lua_call(L, 1, 0);
  952. break;
  953. case LUAT_MOBILE_EVENT_CSCON:
  954. LLOGD("CSCON %d", status);
  955. break;
  956. case LUAT_MOBILE_EVENT_BEARER:
  957. LLOGD("bearer act %d, result %d",status, index);
  958. break;
  959. default:
  960. break;
  961. }
  962. return 0;
  963. }
  964. // 给luat_mobile_event_register_handler 注册用, 给lua层发消息
  965. void luat_mobile_event_cb(LUAT_MOBILE_EVENT_E event, uint8_t index, uint8_t status) {
  966. rtos_msg_t msg = {
  967. .handler = l_mobile_event_handle,
  968. .arg1 = event,
  969. .arg2 = (index << 8) + status ,
  970. .ptr = NULL
  971. };
  972. luat_msgbus_put(&msg, 0);
  973. }