exnetif.lua 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135
  1. --[[
  2. @module exnetif
  3. @summary exnetif 控制网络优先级(以太网->WIFI->4G)根据优先级选择上网的网卡。简化开启多网融合的操作,4G作为数据出口给WIFI,以太网设备上网,以太网作为数据出口给WIFI,Air8000上网,WIFI作为数据出口给Air8000,以太网上网。
  4. @version 1.0
  5. @date 2025.06.26
  6. @author wjq
  7. @usage
  8. 本文件的对外接口有5个:
  9. 1、exnetif.set_priority_order(networkConfigs):设置网络优先级顺序并初始化对应网络(需要在task中调用)
  10. 2、exnetif.notify_status(cb_fnc):设置网络状态变化回调函数
  11. 3、exnetif.setproxy(adapter, main_adapter,other_configs):配置网络代理实现多网融合(需要在task中调用)
  12. 4、exnetif.check_network_status(interval),检测间隔时间ms(选填),不填时只检测一次,填写后将根据间隔时间循环检测,会提高模块功耗
  13. 5、exnetif.close(type, adapter):关闭指定网卡,内核固件版本号需>=2020
  14. ]]
  15. local exnetif = {}
  16. dnsproxy = require("dnsproxy")
  17. dhcpsrv = require("dhcpsrv")
  18. httpdns = require("httpdns")
  19. -- 设置pingip
  20. local wifi_ping_ip
  21. local eth_ping_ip
  22. -- 局域网模式
  23. local local_network_mode
  24. -- 是否需要通过ping来测试网络的连通性
  25. local need_ping = true
  26. -- 使用单网卡模式
  27. local single_network_mode = false
  28. -- 是否自动关闭非当前网卡socket连接
  29. local auto_socket_switch = true
  30. -- ping检测间隔时间
  31. local ping_time = 10000
  32. -- 连接状态
  33. local connection_states = {
  34. DISCONNECTED = 0,
  35. CONNECTING = 1,
  36. CONNECTED = 2,
  37. OPENED = 3,
  38. SINGLE_NETWORK = 4,
  39. STOPED = 5
  40. }
  41. -- 状态回调函数
  42. local states_cbfnc = function(net_type)
  43. end
  44. -- 当前优先级
  45. local current_priority = {socket.LWIP_ETH, socket.LWIP_STA, socket.LWIP_GP}
  46. -- 连接状态
  47. local available = {
  48. [socket.LWIP_STA] = connection_states.DISCONNECTED,
  49. [socket.LWIP_ETH] = connection_states.DISCONNECTED,
  50. [socket.LWIP_GP] = connection_states.DISCONNECTED,
  51. [socket.LWIP_USER1] = connection_states.DISCONNECTED
  52. }
  53. -- 当前使用的网卡
  54. local current_active = nil
  55. -- 网络类型转字符串
  56. local function type_to_string(net_type)
  57. local type_map = {
  58. [socket.LWIP_STA] = "WiFi",
  59. [socket.LWIP_ETH] = "Ethernet",
  60. [socket.LWIP_GP] = "4G",
  61. [socket.LWIP_USER1] = "8101SPIETH"
  62. }
  63. return type_map[net_type] or "Unknown"
  64. end
  65. -- 保存以太网网卡参数,用于关闭spi和供电使能
  66. local eth_cfg = {
  67. [socket.LWIP_ETH] = {},
  68. [socket.LWIP_USER1] = {}
  69. }
  70. -- 订阅socket连接状态变化事件,socket出现异常时修改网卡状态
  71. local function socket_state_detection(adapter)
  72. if netdrv.on then
  73. log.info("netdrv", "订阅socket连接状态变化事件", type_to_string(adapter))
  74. -- 订阅socket连接状态变化事件
  75. netdrv.on(adapter, netdrv.EVT_SOCKET, function(id, event, params)
  76. if event == "timeout" or event == "error" then
  77. if available[adapter] == connection_states.CONNECTED then
  78. available[adapter] = connection_states.CONNECTING
  79. end
  80. end
  81. -- log.info("netdrv", "socket event", id, event, json.encode(params or {}))
  82. -- if params then
  83. -- -- params里会有remote_ip, remote_port等信息, 可按需获取
  84. -- local remote_ip = params.remote_ip
  85. -- local remote_port = params.remote_port
  86. -- local domain_name = params.domain_name
  87. -- log.info("netdrv", "socket event", "remote_ip", remote_ip, "remote_port", remote_port, "domain_name", domain_name)
  88. -- end
  89. end)
  90. end
  91. end
  92. -- 状态更改后重新设置默认网卡
  93. local function apply_priority()
  94. local usable = false
  95. -- 查找优先级最高的可用网络
  96. for _, net_type in ipairs(current_priority) do
  97. -- log.info("网卡顺序",type_to_string(net_type),available[net_type])
  98. if available[net_type] == connection_states.CONNECTED then
  99. usable = true
  100. -- 设置优先级高的网卡
  101. if current_active ~= net_type then
  102. log.info("设置网卡", type_to_string(net_type))
  103. states_cbfnc(type_to_string(net_type), net_type) -- 默认网卡改变的回调函数
  104. socket.dft(net_type)
  105. if auto_socket_switch and socket.close_all then
  106. socket.close_all(current_active)
  107. end
  108. current_active = net_type
  109. end
  110. break
  111. end
  112. end
  113. -- 从存在可用网卡到没有可用网卡,才通知回调
  114. if usable == false and current_active ~= nil then
  115. -- 避免重复通知
  116. current_active = nil
  117. states_cbfnc(nil, -1)
  118. end
  119. end
  120. -- httpdns域名解析测试
  121. local function http_dnstest(adaptertest)
  122. local ip = httpdns.ali("baidu.com", {
  123. adapter = adaptertest,
  124. timeout = 3000
  125. })
  126. if ip ~= nil then
  127. available[adaptertest] = connection_states.CONNECTED
  128. log.info(type_to_string(adaptertest) .. "网卡httpdns域名解析成功")
  129. else
  130. log.info(type_to_string(adaptertest) .. "网卡httpdns域名解析失败")
  131. end
  132. log.info("httpdns", "baidu.com", ip)
  133. end
  134. -- ping操作
  135. local function ping_request(adaptertest)
  136. log.info("dns_request", type_to_string(adaptertest), need_ping)
  137. if need_ping then
  138. if adaptertest == socket.LWIP_ETH or adaptertest == socket.LWIP_USER1 then
  139. if eth_ping_ip == nil then
  140. http_dnstest(adaptertest)
  141. else
  142. icmp.setup(adaptertest)
  143. icmp.ping(adaptertest, eth_ping_ip)
  144. end
  145. end
  146. if adaptertest == socket.LWIP_STA then
  147. if wifi_ping_ip == nil then
  148. http_dnstest(adaptertest)
  149. else
  150. icmp.setup(adaptertest)
  151. icmp.ping(adaptertest, wifi_ping_ip)
  152. end
  153. end
  154. if adaptertest == socket.LWIP_GP then
  155. if eth_ping_ip ~= nil then
  156. icmp.setup(adaptertest)
  157. icmp.ping(adaptertest, eth_ping_ip)
  158. elseif wifi_ping_ip ~= nil then
  159. icmp.setup(adaptertest)
  160. icmp.ping(adaptertest, wifi_ping_ip)
  161. else
  162. http_dnstest(adaptertest)
  163. end
  164. end
  165. else
  166. log.info(type_to_string(adaptertest) .. "配置了不需要ping,直接切换为CONNECTED状态")
  167. available[adaptertest] = connection_states.CONNECTED
  168. end
  169. apply_priority()
  170. end
  171. -- 网卡上线回调函数
  172. local function ip_ready_handle(ip, adapter)
  173. local _, _, gw = socket.localIP(adapter)
  174. log.info("ip_ready_handle", ip, type_to_string(adapter), "state", available[adapter], "gw", gw)
  175. if local_network_mode then
  176. if adapter == socket.LWIP_ETH or adapter == socket.LWIP_USER1 then
  177. eth_ping_ip = gw
  178. elseif adapter == socket.LWIP_STA then
  179. wifi_ping_ip = gw
  180. end
  181. end
  182. log.info("eth_ping_ip", eth_ping_ip, "wifi_ping_ip", wifi_ping_ip)
  183. -- 需要ping操作,ping通后认为网络可用
  184. if available[adapter] == connection_states.OPENED then
  185. available[adapter] = connection_states.CONNECTING
  186. end
  187. -- ping_request(adapter)
  188. end
  189. -- 网卡下线回调函数
  190. local function ip_lose_handle(adapter)
  191. log.info("ip_lose_handle", type_to_string(adapter))
  192. if available[adapter] == connection_states.CONNECTING or available[adapter] == connection_states.CONNECTED then
  193. available[adapter] = connection_states.OPENED
  194. end
  195. if current_active == adapter then
  196. log.info(type_to_string(adapter) .. " 失效,切换到其他网络")
  197. apply_priority()
  198. end
  199. end
  200. local interval_time = nil
  201. --[[
  202. 对正常状态的网卡进行ping测试
  203. @api exnetif.check_network_status(interval),
  204. @int 检测间隔时间ms(选填),不填时只检测一次,填写后将根据间隔时间循环检测,会提高模块功耗
  205. ]]
  206. function exnetif.check_network_status(interval)
  207. if interval ~= nil then
  208. interval_time = interval
  209. end
  210. for _, net_type in ipairs(current_priority) do
  211. if available[net_type] == connection_states.CONNECTED then
  212. available[net_type] = connection_states.CONNECTING
  213. end
  214. end
  215. end
  216. -- 打开以太网Wan功能
  217. local function setup_eth(config)
  218. if config.local_network_mode then
  219. local_network_mode = true
  220. end
  221. if config.need_ping ~= nil then
  222. need_ping = config.need_ping
  223. end
  224. if config.auto_socket_switch ~= nil then
  225. auto_socket_switch = config.auto_socket_switch
  226. -- log.info("设置自动关闭非当前网卡socket连接", auto_socket_switch)
  227. end
  228. eth_ping_ip = config.ping_ip
  229. if type(config.ping_time) == "number" then
  230. ping_time = config.ping_time
  231. end
  232. log.info("初始化以太网")
  233. if not single_network_mode then
  234. available[socket.LWIP_ETH] = connection_states.OPENED
  235. else
  236. available[socket.LWIP_ETH] = connection_states.SINGLE_NETWORK
  237. end
  238. -- 打开CH390供电
  239. if config.pwrpin then
  240. gpio.setup(config.pwrpin, 1, gpio.PULLUP)
  241. end
  242. -- sys.wait(100) -- 等待以太网模块上电稳定
  243. if config.tp == nil then
  244. log.info("8101以太网")
  245. if netdrv.setup(socket.LWIP_ETH) == false then
  246. log.error("以太网初始化失败")
  247. if config.pwrpin then
  248. gpio.close(config.pwrpin)
  249. end
  250. return false
  251. end
  252. else
  253. log.info("config.opts.spi", config.opts.spi, ",config.type", config.tp)
  254. -- 配置SPI和初始化网络驱动
  255. local result = spi.setup(config.opts.spi, -- spi id
  256. nil, 0, -- CPHA
  257. 0, -- CPOL
  258. 8, -- 数据宽度
  259. 25600000 -- ,--波特率
  260. )
  261. log.info("main", "open spi", result)
  262. if result ~= 0 then -- 返回值为0,表示打开成功
  263. log.info("main", "spi open error", result)
  264. if config.pwrpin then
  265. gpio.close(config.pwrpin)
  266. end
  267. return false
  268. end
  269. -- 初始化指定netdrv设备,
  270. -- socket.LWIP_ETH 网络适配器编号
  271. -- netdrv.CH390外挂CH390
  272. -- SPI ID 1, 片选 GPIO12
  273. if netdrv.setup(socket.LWIP_ETH, config.tp, config.opts) == false then
  274. log.error("以太网初始化失败")
  275. if config.pwrpin then
  276. gpio.close(config.pwrpin)
  277. end
  278. return false
  279. end
  280. end
  281. if config.static_ip then
  282. sys.wait(1000) -- 等待以太网模块初始化完成,去掉会导致以太网初始化失败
  283. log.info("netdrv", "自定义以太网IP地址", config.static_ip.ipv4)
  284. log.info("静态ip",
  285. netdrv.ipv4(socket.LWIP_ETH, config.static_ip.ipv4, config.static_ip.mark, config.static_ip.gw))
  286. else
  287. netdrv.dhcp(socket.LWIP_ETH, true)
  288. end
  289. log.info("以太网初始化完成")
  290. socket_state_detection(socket.LWIP_ETH)
  291. return true
  292. end
  293. -- 打开8101spi以太网Wan功能
  294. local function setup_eth_user1(config)
  295. if config.local_network_mode then
  296. local_network_mode = true
  297. end
  298. if config.need_ping ~= nil then
  299. need_ping = config.need_ping
  300. end
  301. if config.auto_socket_switch ~= nil then
  302. auto_socket_switch = config.auto_socket_switch
  303. -- log.info("设置自动关闭非当前网卡socket连接", auto_socket_switch)
  304. end
  305. eth_ping_ip = config.ping_ip
  306. if type(config.ping_time) == "number" then
  307. ping_time = config.ping_time
  308. end
  309. log.info("初始化以太网")
  310. if not single_network_mode then
  311. available[socket.LWIP_USER1] = connection_states.OPENED
  312. else
  313. available[socket.LWIP_USER1] = connection_states.SINGLE_NETWORK
  314. end
  315. -- 打开CH390供电
  316. if config.pwrpin then
  317. gpio.setup(config.pwrpin, 1, gpio.PULLUP)
  318. end
  319. -- sys.wait(100)-- 等待以太网模块上电稳定
  320. log.info("config.opts.spi", config.opts.spi, ",config.type", config.tp)
  321. -- 配置SPI和初始化网络驱动
  322. local result = spi.setup(config.opts.spi, -- spi id
  323. nil, 0, -- CPHA
  324. 0, -- CPOL
  325. 8, -- 数据宽度
  326. 25600000 -- ,--波特率
  327. )
  328. log.info("main", "open spi", result)
  329. if result ~= 0 then -- 返回值为0,表示打开成功
  330. log.info("main", "spi open error", result)
  331. if config.pwrpin then
  332. gpio.close(config.pwrpin)
  333. end
  334. return false
  335. end
  336. -- 初始化指定netdrv设备,
  337. -- socket.LWIP_ETH 网络适配器编号
  338. -- netdrv.CH390外挂CH390
  339. -- SPI ID 1, 片选 GPIO12
  340. if netdrv.setup(socket.LWIP_USER1, config.tp, config.opts) == false then
  341. log.error("以太网初始化失败")
  342. if config.pwrpin then
  343. gpio.close(config.pwrpin)
  344. end
  345. return false
  346. end
  347. if config.static_ip then
  348. sys.wait(1000) -- 等待以太网模块初始化完成,去掉会导致以太网初始化失败
  349. log.info("netdrv", "自定义以太网IP地址", config.static_ip.ipv4)
  350. log.info("静态ip",
  351. netdrv.ipv4(socket.LWIP_USER1, config.static_ip.ipv4, config.static_ip.mark, config.static_ip.gw))
  352. else
  353. netdrv.dhcp(socket.LWIP_USER1, true)
  354. end
  355. log.info("以太网初始化完成")
  356. socket_state_detection(socket.LWIP_USER1)
  357. return true
  358. end
  359. -- 连接wifi(STA模式)
  360. local function set_wifi_info(config)
  361. if config.local_network_mode then
  362. local_network_mode = true
  363. end
  364. if config.need_ping ~= nil then
  365. need_ping = config.need_ping
  366. end
  367. if config.auto_socket_switch ~= nil then
  368. auto_socket_switch = config.auto_socket_switch
  369. -- log.info("设置自动关闭非当前网卡socket连接", auto_socket_switch)
  370. end
  371. wifi_ping_ip = config.ping_ip
  372. if type(config.ping_time) == "number" then
  373. ping_time = config.ping_time
  374. end
  375. log.info("WiFi名称:", config.ssid)
  376. log.info("密码 :", config.password)
  377. log.info("ping_ip :", config.ping_ip)
  378. wlan.init()
  379. if not single_network_mode then
  380. available[socket.LWIP_STA] = connection_states.OPENED
  381. else
  382. available[socket.LWIP_STA] = connection_states.SINGLE_NETWORK
  383. end
  384. -- 尝试连接Wi-Fi,并处理可能出现的错误
  385. local success = wlan.connect(config.ssid, config.password)
  386. if not success then
  387. log.error("WiFi连接失败")
  388. return false
  389. end
  390. log.info("WiFi STA初始化完成")
  391. socket_state_detection(socket.LWIP_STA)
  392. return true
  393. end
  394. -- 以太网处于stop状态,重启以太网
  395. local function eth_net_restart(adapter)
  396. log.info("以太网处于stop状态,重启下")
  397. if not single_network_mode then
  398. available[adapter] = connection_states.OPENED
  399. else
  400. available[adapter] = connection_states.SINGLE_NETWORK
  401. end
  402. -- 打开CH390供电
  403. if eth_cfg[adapter].pwrpin then
  404. log.info("打开以太网供电引脚:", eth_cfg[adapter].pwrpin)
  405. gpio.setup(eth_cfg[adapter].pwrpin, 1, gpio.PULLUP)
  406. end
  407. -- sys.wait(100) -- 等待以太网模块上电稳定
  408. if eth_cfg[adapter].tp == nil then
  409. log.info("8101以太网")
  410. else
  411. log.info("config.opts.spi", eth_cfg[adapter].opts.spi, ",config.type", eth_cfg[adapter].tp)
  412. -- 配置SPI和初始化网络驱动
  413. local result = spi.setup(eth_cfg[adapter].opts.spi, -- spi id
  414. nil, 0, -- CPHA
  415. 0, -- CPOL
  416. 8, -- 数据宽度
  417. 25600000 -- ,--波特率
  418. )
  419. log.info("main", "open spi", result)
  420. if result ~= 0 then -- 返回值为0,表示打开成功
  421. log.info("main", "spi open error", result)
  422. if eth_cfg[adapter].pwrpin then
  423. gpio.close(eth_cfg[adapter].pwrpin)
  424. end
  425. return false
  426. end
  427. end
  428. netdrv.ctrl(adapter, netdrv.CTRL_UPDOWN, 1)
  429. end
  430. -- ping测试循环
  431. local function ping_test_loop()
  432. while true do
  433. for _, net_type in ipairs(current_priority) do
  434. -- log.info("网卡顺序",type_to_string(net_type),available[net_type])
  435. if available[net_type] == connection_states.CONNECTING then
  436. log.info(type_to_string(net_type) .. "网卡开始PING")
  437. ping_request(net_type)
  438. sys.wait(ping_time)
  439. end
  440. end
  441. sys.wait(1000) -- 避免死循环
  442. end
  443. end
  444. -- 正常状态网卡的检测任务
  445. local function normal_network_test()
  446. while true do
  447. if interval_time ~= nil then
  448. sys.wait(interval_time)
  449. exnetif.check_network_status()
  450. end
  451. sys.wait(1000) -- 避免死循环
  452. end
  453. end
  454. -- PING结果处理函数
  455. local function ping_res(id, time, dst)
  456. log.info("ping", id, time, dst)
  457. log.info(type_to_string(id) .. "网卡PING测试成功")
  458. available[id] = connection_states.CONNECTED
  459. apply_priority()
  460. end
  461. --[[
  462. 设置网络优先级,相应网卡获取到ip且网络正常视为网卡可用,丢失ip视为网卡不可用.(需要在task中调用)
  463. @api exnetif.set_priority_order(new_priority)
  464. @table 网络优先级列表,优先级从高到低对应table中的第一个参数到最后一个参数
  465. @return boolean 成功返回true,失败返回false
  466. @usage
  467. 多网优先级模式:
  468. exnetif.set_priority_order({
  469. { -- 最高优先级网络
  470. WIFI = { -- WiFi配置
  471. ssid = "your_ssid", -- WiFi名称(string)
  472. password = "your_pwd", -- WiFi密码(string)
  473. need_ping = true, -- 是否需要通过ping来测试网络的连通性
  474. -- 在没有ping测试环境的项目中,需要将这个参数设置为false,表示不需要ping测试网络连通,
  475. -- 仅根据IP READY消息(即获取到了ip地址)来判断网络环境准备就绪,是否网络连通性则无法保证
  476. -- 如果没有设置此参数,默认为true
  477. -- 在有ping测试环境的项目中,建议不要将这个参数设置为true
  478. local_network_mode = true,-- 局域网模式(选填参数),设置为true时,exnetif会自动将ping_ip设置为网卡的网关ip。
  479. -- 用户不需要传入ping_ip参数,即使传入了,也无效。
  480. -- 这个模式的使用场景,仅适用于局域网环境;可以访问外网时,不要使用
  481. ping_ip = "112.125.89.8", -- 连通性检测IP(选填参数),默认使用httpdns获取baidu.com的ip作为判断条件,
  482. -- 注:如果填写ip,则ping通作为判断网络是否可用的条件,
  483. -- 所以需要根据网络环境填写内网或者外网ip,
  484. -- 填写外网ip的话要保证外网ip始终可用,
  485. -- 填写局域网ip的话要确保相应ip固定且能够被ping通
  486. ping_time = 10000 -- 填写ping_ip且未ping通时的检测间隔(ms, 可选,默认为10秒)
  487. -- 定时ping将会影响模块功耗,使用低功耗模式的话可以适当延迟间隔时间
  488. }
  489. },
  490. { -- 次优先级网络
  491. ETHERNET = { -- 以太网配置
  492. pwrpin = 140, -- 供电使能引脚(number)
  493. need_ping = true, -- 是否需要通过ping来测试网络的连通性
  494. -- 在没有ping测试环境的项目中,需要将这个参数设置为false,表示不需要ping测试网络连通,
  495. -- 仅根据IP READY消息(即获取到了ip地址)来判断网络环境准备就绪,是否网络连通性则无法保证
  496. -- 如果没有设置此参数,默认为true
  497. -- 在有ping测试环境的项目中,建议不要将这个参数设置为true
  498. local_network_mode = true, -- 局域网模式(选填参数),设置为true时,exnetif会自动将ping_ip设置为网卡的网关ip。
  499. -- 用户不需要传入ping_ip参数,即使传入了,也无效。
  500. -- 这个模式的使用场景,仅适用于局域网环境;可以访问外网时,不要使用
  501. ping_ip = "112.125.89.8", -- 连通性检测IP(选填参数),默认使用httpdns获取baidu.com的ip作为判断条件,
  502. -- 注:如果填写ip,则ping通作为判断网络是否可用的条件,
  503. -- 所以需要根据网络环境填写内网或者外网ip,
  504. -- 填写外网ip的话要保证外网ip始终可用,
  505. -- 填写局域网ip的话要确保相应ip固定且能够被ping通
  506. ping_time = 10000, -- 填写ping_ip且未ping通时的检测间隔(ms, 可选,默认为10秒)
  507. -- 定时ping将会影响模块功耗,使用低功耗模式的话可以适当延迟间隔时间
  508. tp = netdrv.CH390, -- 网卡芯片型号(选填参数),仅spi方式外挂以太网时需要填写。
  509. opts = { spi = 1, cs = 12 }, -- 外挂方式,需要额外的参数(选填参数),仅spi方式外挂以太网时需要填写。
  510. static_ip = { -- 静态ip配置(选填参数),不填写则使用dhcp获取ip
  511. ipv4 = "192.168.5.100", -- ip地址(string)
  512. mark = "255.255.255.0", -- 子网掩码(string)
  513. gw = "192.168.5.1" -- 网关地址(string)
  514. }
  515. }
  516. },
  517. { -- 最低优先级网络
  518. LWIP_GP = true -- 启用4G网络
  519. }
  520. })
  521. 单网络模式:
  522. -- 单网络模式下只使用WIFI网络
  523. exnetif.set_priority_order({
  524. { -- 单网络,打开wifi
  525. WIFI = { -- WiFi配置
  526. ssid = "test", -- WiFi名称(string)
  527. password = "HZ88888888", -- WiFi密码(string)
  528. }
  529. }
  530. })
  531. -- Air8000系列和780EXX系列单网络模式下只使用SPI以太网网络
  532. exnetif.set_priority_order({
  533. {
  534. ETHERNET = { -- 以太网配置
  535. pwrpin = 140, -- 供电使能引脚(number)
  536. tp = netdrv.CH390, -- 网卡芯片型号(选填参数),仅spi方式外挂以太网时需要填写。
  537. opts = {spi = 1, cs = 12}, -- 外挂方式,需要额外的参数(选填参数),仅spi方式外挂以太网时需要填写。
  538. }
  539. }
  540. })
  541. -- Air8101单网络模式下只使用SPI以太网网络
  542. exnetif.set_priority_order({
  543. {
  544. ETHUSER1 = { -- 以太网配置
  545. pwrpin = 13, -- 供电使能引脚(number)
  546. tp = netdrv.CH390, -- 网卡芯片型号(选填参数),仅spi方式外挂以太网时需要填写。
  547. opts = {spi = 0, cs = 15}, -- 外挂方式,需要额外的参数(选填参数),仅spi方式外挂以太网时需要填写。
  548. static_ip = { -- 静态ip配置(选填参数),不填写则使用dhcp获取ip
  549. ipv4 = "192.168.5.100", -- ip地址(string)
  550. mark = "255.255.255.0", -- 子网掩码(string)
  551. gw = "192.168.5.1" -- 网关地址(string)
  552. }
  553. }
  554. }
  555. })
  556. -- 单网络模式下只使用RMII以太网网络
  557. exnetif.set_priority_order({
  558. {
  559. ETHERNET = { -- 以太网配置
  560. pwrpin = 13, -- 供电使能引脚(number)
  561. }
  562. }
  563. })
  564. -- 4G单网模式下,不需要require "exnetif",减少不必要的功能模块加载
  565. ]]
  566. function exnetif.set_priority_order(networkConfigs)
  567. -- 判断表中数据个数
  568. if #networkConfigs < 1 then
  569. log.error("网络配置为空")
  570. return false
  571. end
  572. if #networkConfigs == 1 then
  573. single_network_mode = true
  574. end
  575. if not single_network_mode then
  576. -- CONNECTING的网卡需要定时ping
  577. sys.taskInit(ping_test_loop)
  578. -- 循环ping检测正常网卡的任务,默认不启用
  579. sys.taskInit(normal_network_test)
  580. sys.subscribe("PING_RESULT", ping_res)
  581. -- 订阅网络状态变化的消息
  582. sys.subscribe("IP_READY", ip_ready_handle)
  583. sys.subscribe("IP_LOSE", ip_lose_handle)
  584. end
  585. local new_priority = {}
  586. -- 只有关闭状态的网卡需要初始化
  587. for _, config in ipairs(networkConfigs) do
  588. if type(config.WIFI) == "table" then
  589. if available[socket.LWIP_STA] == connection_states.DISCONNECTED then
  590. -- 开启wifi
  591. local res = set_wifi_info(config.WIFI)
  592. if res == false then
  593. log.error("wifi连接失败")
  594. return false
  595. end
  596. else
  597. log.info("wifi不是关闭状态,跳过初始化")
  598. end
  599. table.insert(new_priority, socket.LWIP_STA)
  600. end
  601. if type(config.ETHUSER1) == "table" then
  602. eth_cfg[socket.LWIP_USER1] = config.ETHUSER1
  603. if available[socket.LWIP_USER1] == connection_states.DISCONNECTED then
  604. -- 开启以太网
  605. local res = setup_eth_user1(config.ETHUSER1)
  606. if res == false then
  607. log.error("以太网打开失败")
  608. return false
  609. end
  610. elseif available[socket.LWIP_USER1] == connection_states.STOPED then
  611. eth_net_restart(socket.LWIP_USER1)
  612. else
  613. log.info("8101spi以太网不是关闭状态,跳过初始化")
  614. end
  615. table.insert(new_priority, socket.LWIP_USER1)
  616. end
  617. if type(config.ETHERNET) == "table" then
  618. eth_cfg[socket.LWIP_ETH] = config.ETHERNET
  619. if available[socket.LWIP_ETH] == connection_states.DISCONNECTED then
  620. -- 开启以太网
  621. local res = setup_eth(config.ETHERNET)
  622. if res == false then
  623. log.error("以太网打开失败")
  624. return false
  625. end
  626. elseif available[socket.LWIP_ETH] == connection_states.STOPED then
  627. eth_net_restart(socket.LWIP_ETH)
  628. else
  629. log.info("以太网不是关闭状态,跳过初始化")
  630. end
  631. table.insert(new_priority, socket.LWIP_ETH)
  632. end
  633. if config.LWIP_GP then
  634. -- 退出飞行模式
  635. mobile.flymode(nil, false)
  636. -- 开启4G
  637. table.insert(new_priority, socket.LWIP_GP)
  638. available[socket.LWIP_GP] = connection_states.CONNECTING
  639. if config.auto_socket_switch ~= nil then
  640. auto_socket_switch = config.auto_socket_switch
  641. -- log.info("设置自动关闭非当前网卡socket连接", auto_socket_switch)
  642. end
  643. end
  644. end
  645. -- 设置新优先级
  646. current_priority = new_priority
  647. -- 此处按照用户期望的配置,先设置优先级最高的默认网卡
  648. -- 防止出现以下问题:
  649. -- 例如Air8000内核固件运行起来之后,默认网卡是socket.LWIP_GP,如果用户调用exnetif.set_priority_order接口配置最高优先级网卡为socket.LWIP_ETH
  650. -- 在socket.LWIP_ETH网卡准备就绪之前,socket.LWIP_GP可能已经准备就绪,此时默认网卡仍然是socket.LWIP_GP;
  651. -- 而网络应用层(例如socket,mqtt等)有关的demo,我们编写时,不关心具体网卡,直接使用默认网卡(这样符合正常逻辑);
  652. -- 就可能会出现“网络应用在这段时间内直接使用socket.LWIP_GP,而不是用户期望的网卡socket.LWIP_ETH来上网”的问题;
  653. socket.dft(new_priority[1])
  654. apply_priority()
  655. return true
  656. end
  657. --[[
  658. 设置网络状态变化回调函数。触发条件:网卡切换或者所有网卡都断网。回调函数的输入参数: 1. 当有可用网络的时候,返回当前使用网卡、网卡id;2. 当没有可用网络的时候,返回 nil、-1 。
  659. @api exnetif.notify_status(cb_fnc)
  660. @function 回调函数
  661. @usage
  662. exnetif.notify_status(function(net_type,adapter)
  663. log.info("可以使用优先级更高的网络:", net_type,adapter)
  664. end)
  665. ]]
  666. function exnetif.notify_status(cb_fnc)
  667. log.info("notify_status", type(cb_fnc))
  668. if type(cb_fnc) ~= "function" then
  669. log.error("notify_status设置错误,请传入一个函数")
  670. return
  671. end
  672. states_cbfnc = cb_fnc
  673. end
  674. --[[
  675. 设置多网融合模式,例如4G作为数据出口给WIFI或以太网设备上网(需要在task中调用)
  676. @api exnetif.setproxy(adapter, main_adapter,other_configs)
  677. @adapter 需要使用网络的网卡,例如socket.LWIP_ETH
  678. @adapter 提供网络的网卡,例如socket.LWIP_GP
  679. @table 其他设置参数(选填参数),
  680. @usage
  681. 典型应用:
  682. -- 以太网WAN提供网络其他设备连接以太网LAN口上网
  683. exnetif.setproxy(socket.LWIP_ETH, socket.LWIP_USER1, {
  684. ethpower_en = 20,-- 以太网模块的pwrpin引脚(gpio编号)
  685. tp = netdrv.CH390, -- 网卡芯片型号(选填参数),仅spi方式外挂以太网时需要填写。
  686. opts = {spi = 0, cs = 8}, -- 外挂方式,需要额外的参数(选填参数),仅spi方式外挂以太网时需要填写。
  687. main_adapter = {
  688. ethpower_en = 21,-- 以太网模块的pwrpin引脚(gpio编号)
  689. tp = netdrv.CH390, -- 网卡芯片型号(选填参数),仅spi方式外挂以太网时需要填写。
  690. opts = {spi = 1, cs = 12}
  691. }
  692. }) then
  693. -- wifi_sta提供网络开启wifi_ap热点供设备上网
  694. exnetif.setproxy(socket.LWIP_AP, socket.LWIP_STA, {
  695. ssid = "test2", -- AP热点名称(string),网卡包含wifi时填写
  696. password = "HZ88888888", -- AP热点密码(string),网卡包含wifi时填写
  697. ap_opts = { -- AP模式下配置项(选填参数)
  698. hidden = false, -- 是否隐藏SSID, 默认false,不隐藏
  699. max_conn = 4 }, -- 最大客户端数量, 默认4
  700. channel = 6, -- AP建立的通道, 默认6
  701. main_adapter = {
  702. ssid = "test", -- 提供网络的网卡开启参数
  703. password = "HZ88888888"
  704. }
  705. })
  706. -- 4G提供网络开启wifi_ap热点供设备上网,其他设备连接以太网LAN口上网
  707. exnetif.setproxy(socket.LWIP_AP, socket.LWIP_GP, {
  708. ssid = "Hotspot", -- WiFi名称(string),网卡包含wifi时填写
  709. password = "password123", -- WiFi密码(string),网卡包含wifi时填写
  710. adapter_addr = "192.168.5.1", -- adapter网卡的ip地址(选填),需要自定义ip和网关ip时填写
  711. adapter_gw= { 192, 168, 5, 1 }, -- adapter网卡的网关地址(选填),需要自定义ip和网关ip时填写
  712. ap_opts={ -- AP模式下配置项(选填参数)
  713. hidden = false, -- 是否隐藏SSID, 默认false,不隐藏
  714. max_conn = 4 }, -- 最大客户端数量, 默认4
  715. channel=6 -- AP建立的通道, 默认6
  716. })
  717. exnetif.setproxy(socket.LWIP_ETH, socket.LWIP_GP, {
  718. tp = netdrv.CH390, -- 网卡芯片型号(选填参数),仅spi方式外挂以太网时需要填写。
  719. opts = { spi = 1, cs = 12}, -- 外挂方式,需要额外的参数(选填参数),仅spi方式外挂以太网时需要填写。
  720. ethpower_en = 140, -- 以太网模块的pwrpin引脚(gpio编号)
  721. adapter_addr = "192.168.5.1", -- adapter网卡的ip地址(选填),需要自定义ip和网关ip时填写
  722. adapter_gw= { 192, 168, 5, 1 }, -- adapter网卡的网关地址(选填),需要自定义ip和网关ip时填写
  723. })
  724. -- 以太网提供网络供WiFi设备上网
  725. exnetif.setproxy(socket.LWIP_AP, socket.LWIP_ETH, {
  726. ssid = "Hotspot", -- WiFi名称(string),网卡包含wifi时填写
  727. password = "password123", -- WiFi密码(string),网卡包含wifi时填写
  728. main_adapter={
  729. tp = netdrv.CH390, -- 网卡芯片型号(选填参数),仅spi方式外挂以太网时需要填写。
  730. opts = { spi = 1, cs = 12}, -- 外挂方式,需要额外的参数(选填参数),仅spi方式外挂以太网时需要填写。
  731. ethpower_en = 140, -- 以太网模块的pwrpin引脚(gpio编号)
  732. }
  733. })
  734. -- WIFI提供网络供以太网设备上网
  735. exnetif.setproxy(socket.LWIP_ETH, socket.LWIP_STA, {
  736. tp = netdrv.CH390, -- 网卡芯片型号(选填参数),仅spi方式外挂以太网时需要填写。
  737. opts = { spi = 1, cs = 12}, -- 外挂方式,需要额外的参数(选填参数),仅spi方式外挂以太网时需要填写。
  738. ethpower_en = 140, -- 以太网模块的pwrpin引脚(gpio编号)
  739. main_adapter = {
  740. ssid = "test", -- 提供网络的网卡开启参数
  741. password = "HZ88888888"
  742. }
  743. })
  744. ]]
  745. function exnetif.setproxy(adapter, main_adapter, other_configs)
  746. if main_adapter == socket.LWIP_ETH and available[socket.LWIP_ETH] == connection_states.DISCONNECTED then
  747. -- 打开WAN功能
  748. log.info("ch390", "打开LDO供电", other_configs.main_adapter.ethpower_en)
  749. available[socket.LWIP_ETH] = connection_states.OPENED
  750. -- 打开CH390供电
  751. if other_configs.main_adapter.ethpower_en then
  752. gpio.setup(other_configs.main_adapter.ethpower_en, 1, gpio.PULLUP)
  753. end
  754. -- sys.wait(100) -- 等待以太网模块上电稳定
  755. if other_configs.main_adapter.tp == nil then
  756. log.info("8101以太网")
  757. if netdrv.setup(socket.LWIP_ETH) == false then
  758. log.error("以太网初始化失败")
  759. if other_configs.main_adapter.ethpower_en then
  760. gpio.close(other_configs.main_adapter.ethpower_en)
  761. end
  762. return false
  763. end
  764. else
  765. log.info("config.opts.spi", other_configs.main_adapter.opts.spi, ",config.type",
  766. other_configs.main_adapter.tp)
  767. -- 配置SPI和初始化网络驱动
  768. local result = spi.setup(other_configs.main_adapter.opts.spi, -- spi id
  769. nil, 0, -- CPHA
  770. 0, -- CPOL
  771. 8, -- 数据宽度
  772. 25600000 -- ,--波特率
  773. )
  774. log.info("main", "open spi", result)
  775. if result ~= 0 then -- 返回值为0,表示打开成功
  776. log.info("main", "spi open error", result)
  777. if other_configs.main_adapter.ethpower_en then
  778. gpio.close(other_configs.main_adapter.ethpower_en)
  779. end
  780. return false
  781. end
  782. -- 初始化指定netdrv设备,
  783. local success =
  784. netdrv.setup(socket.LWIP_ETH, other_configs.main_adapter.tp, other_configs.main_adapter.opts)
  785. if not success then
  786. log.error("以太网初始化失败")
  787. if other_configs.main_adapter.ethpower_en then
  788. gpio.close(other_configs.main_adapter.ethpower_en)
  789. end
  790. return false
  791. end
  792. end
  793. netdrv.dhcp(socket.LWIP_ETH, true)
  794. local count = 1
  795. while 1 do
  796. local ip = netdrv.ipv4(socket.LWIP_ETH)
  797. if ip and ip ~= "0.0.0.0" then
  798. break
  799. end
  800. if count > 600 then
  801. log.error("以太网连接超时,请检查配置")
  802. if other_configs.main_adapter.ethpower_en then
  803. gpio.close(other_configs.main_adapter.ethpower_en)
  804. end
  805. return false
  806. end
  807. sys.wait(100)
  808. count = count + 1
  809. end
  810. elseif main_adapter == socket.LWIP_USER1 and available[socket.LWIP_USER1] == connection_states.DISCONNECTED then
  811. log.info("初始化以太网")
  812. -- 打开CH390供电
  813. if other_configs.main_adapter.ethpower_en then
  814. gpio.setup(other_configs.main_adapter.ethpower_en, 1, gpio.PULLUP)
  815. end
  816. -- sys.wait(100) -- 等待以太网模块上电稳定
  817. log.info("config.opts.spi", other_configs.main_adapter.opts.spi, ",config.type", other_configs.main_adapter.tp)
  818. available[socket.LWIP_USER1] = connection_states.OPENED
  819. -- 配置SPI和初始化网络驱动
  820. local result = spi.setup(other_configs.main_adapter.opts.spi, -- spi id
  821. nil, 0, -- CPHA
  822. 0, -- CPOL
  823. 8, -- 数据宽度
  824. 25600000 -- ,--波特率
  825. )
  826. log.info("main", "open spi", result)
  827. if result ~= 0 then -- 返回值为0,表示打开成功
  828. log.info("main", "spi open error", result)
  829. if other_configs.main_adapter.ethpower_en then
  830. gpio.close(other_configs.main_adapter.ethpower_en)
  831. end
  832. return false
  833. end
  834. -- 初始化指定netdrv设备,
  835. -- socket.LWIP_ETH 网络适配器编号
  836. -- netdrv.CH390外挂CH390
  837. -- SPI ID 1, 片选 GPIO12
  838. if netdrv.setup(socket.LWIP_USER1, other_configs.main_adapter.tp, other_configs.main_adapter.opts) == false then
  839. log.error("以太网初始化失败")
  840. if other_configs.main_adapter.ethpower_en then
  841. gpio.close(other_configs.main_adapter.ethpower_en)
  842. end
  843. return false
  844. end
  845. netdrv.dhcp(socket.LWIP_USER1, true)
  846. log.info("以太网初始化完成")
  847. local count = 1
  848. while 1 do
  849. local ip = netdrv.ipv4(socket.LWIP_USER1)
  850. if ip and ip ~= "0.0.0.0" then
  851. break
  852. end
  853. if count > 600 then
  854. log.error("以太网连接超时,请检查配置")
  855. if other_configs.main_adapter.ethpower_en then
  856. gpio.close(other_configs.main_adapter.ethpower_en)
  857. end
  858. return false
  859. end
  860. sys.wait(100)
  861. count = count + 1
  862. end
  863. elseif main_adapter == socket.LWIP_STA and available[socket.LWIP_STA] == connection_states.DISCONNECTED then
  864. -- 打开STA功能,设置混合模式
  865. wlan.init()
  866. wlan.setMode(wlan.APSTA)
  867. available[socket.LWIP_STA] = connection_states.OPENED
  868. -- 尝试连接Wi-Fi,并处理可能出现的错误
  869. wlan.connect(other_configs.main_adapter.ssid, other_configs.main_adapter.password)
  870. -- 等待获取IP地址
  871. local count = 1
  872. while 1 do
  873. local ip = netdrv.ipv4(socket.LWIP_STA)
  874. if ip and ip ~= "0.0.0.0" then
  875. log.info("WiFi STA已连接,IP:", ip)
  876. break
  877. end
  878. if count > 600 then
  879. log.error("WiFi STA连接超时,请检查配置")
  880. return false
  881. end
  882. sys.wait(100)
  883. count = count + 1
  884. end
  885. log.info("WiFi STA初始化完成")
  886. end
  887. if adapter == socket.LWIP_ETH then
  888. log.info("ch390", "打开LDO供电", other_configs.ethpower_en)
  889. if other_configs.ethpower_en then
  890. gpio.setup(other_configs.ethpower_en, 1, gpio.PULLUP)
  891. end
  892. -- 打开LAN功能
  893. -- 配置 SPI 参数,Air8000 使用 SPI 接口与以太网模块进行通信。
  894. if other_configs.tp then
  895. log.info("netdrv spi挂载以太网", "初始化LAN功能")
  896. local result = spi.setup(other_configs.opts.spi, -- spi id
  897. nil, 0, -- CPHA
  898. 0, -- CPOL
  899. 8, -- 数据宽度
  900. 25600000 -- ,--波特率
  901. )
  902. log.info("main", "open spi", result)
  903. if result ~= 0 then -- 返回值为 0,表示打开成功
  904. log.error("main", "spi open error", result)
  905. if other_configs.ethpower_en then
  906. gpio.close(other_configs.ethpower_en)
  907. end
  908. return false
  909. end
  910. end
  911. -- 初始化以太网,Air8000 指定使用 CH390 芯片。
  912. log.info("netdrv", "初始化以太网", other_configs.tp, other_configs.opts)
  913. if netdrv.setup(socket.LWIP_ETH, other_configs.tp, other_configs.opts) == false then
  914. log.error("初始化以太网失败")
  915. if other_configs.ethpower_en then
  916. gpio.close(other_configs.ethpower_en)
  917. end
  918. return false
  919. end
  920. sys.wait(1000) -- 等待以太网模块初始化完成,去掉会导致以太网初始化失败
  921. -- 设置以太网的 IP 地址、子网掩码、网关地址
  922. log.info("netdrv", "自定义以太网IP地址", other_configs.adapter_addr, "网关地址",
  923. other_configs.adapter_gw)
  924. netdrv.ipv4(socket.LWIP_ETH, other_configs.adapter_addr or "192.168.5.1", "255.255.255.0", "0.0.0.0")
  925. -- 获取以太网网络状态,连接后返回 true,否则返回 false,如果不存在就返回 nil。
  926. local count = 1
  927. while netdrv.ready(socket.LWIP_ETH) ~= true do
  928. if count > 600 then
  929. log.error("以太网连接超时,请检查配置")
  930. if other_configs.ethpower_en then
  931. gpio.close(other_configs.ethpower_en)
  932. end
  933. return false
  934. end
  935. count = count + 1
  936. -- log.info("netdrv", "等待以太网就绪") -- 若以太网设备没有连上,可打开此处注释排查。
  937. sys.wait(100)
  938. end
  939. log.info("netdrv", "以太网就绪")
  940. -- 创建 DHCP 服务器,为连接到以太网的设备分配 IP 地址。
  941. log.info("netdrv", "创建dhcp服务器, 供以太网使用")
  942. if other_configs.adapter_gw then
  943. dhcpsrv.create({
  944. adapter = socket.LWIP_ETH,
  945. gw = other_configs.adapter_gw
  946. })
  947. else
  948. dhcpsrv.create({
  949. adapter = socket.LWIP_ETH,
  950. gw = {192, 168, 5, 1}
  951. })
  952. end
  953. -- 创建 DNS 代理服务,使得以太网接口上的设备可以通过 4G 网络访问互联网。
  954. log.info("netdrv", "创建dns代理服务, 供以太网使用")
  955. elseif adapter == socket.LWIP_AP then
  956. wlan.setMode(wlan.APSTA)
  957. -- 打开AP功能,设置混合模式
  958. log.info("执行AP创建操作", airlink.ready(), "正常吗?")
  959. wlan.createAP(other_configs.ssid, other_configs.password, other_configs.adapter_addr or "192.168.4.1",
  960. "255.255.255.0", other_configs.channel, other_configs.ap_opts)
  961. -- 设置 AP 的 IP 地址、子网掩码、网关地址
  962. netdrv.ipv4(socket.LWIP_AP, other_configs.adapter_addr or "192.168.4.1", "255.255.255.0", "0.0.0.0")
  963. -- 获取 WiFi AP 网络状态,连接后返回 true,否则返回 false,如果不存在就返回 nil。
  964. log.info("netdrv", "等待AP就绪")
  965. local count = 1
  966. while netdrv.ready(socket.LWIP_AP) ~= true do
  967. -- log.info("netdrv", "等待AP就绪")
  968. if count > 600 then
  969. log.error("AP创建超时,请检查配置")
  970. return false
  971. end
  972. sys.wait(100)
  973. count = count + 1
  974. end
  975. -- 创建 DHCP 服务器,为连接到 WiFi AP 的设备分配 IP 地址。
  976. log.info("netdrv", "创建dhcp服务器, 供AP使用")
  977. if other_configs.adapter_gw then
  978. dhcpsrv.create({
  979. adapter = socket.LWIP_AP,
  980. gw = other_configs.adapter_gw
  981. })
  982. else
  983. dhcpsrv.create({
  984. adapter = socket.LWIP_AP
  985. })
  986. end
  987. elseif adapter == socket.LWIP_USER1 then
  988. log.info("ch390", "打开LDO供电", other_configs.ethpower_en)
  989. if other_configs.ethpower_en then
  990. gpio.setup(other_configs.ethpower_en, 1, gpio.PULLUP)
  991. end
  992. -- 打开LAN功能
  993. -- 配置 SPI 参数,Air8101 使用 SPI 接口与以太网模块进行通信。
  994. log.info("netdrv spi挂载以太网", "初始化LAN功能")
  995. local result = spi.setup(other_configs.opts.spi, -- spi id
  996. nil, 0, -- CPHA
  997. 0, -- CPOL
  998. 8, -- 数据宽度
  999. 25600000 -- ,--波特率
  1000. )
  1001. log.info("main", "open spi", result)
  1002. if result ~= 0 then -- 返回值为 0,表示打开成功
  1003. log.error("main", "spi open error", result)
  1004. if other_configs.ethpower_en then
  1005. gpio.close(other_configs.ethpower_en)
  1006. end
  1007. return false
  1008. end
  1009. -- 初始化以太网,Air8000 指定使用 CH390 芯片。
  1010. log.info("netdrv", "初始化以太网", other_configs.tp, other_configs.opts)
  1011. if netdrv.setup(socket.LWIP_USER1, other_configs.tp, other_configs.opts) == false then
  1012. log.error("初始化以太网失败")
  1013. if other_configs.ethpower_en then
  1014. gpio.close(other_configs.ethpower_en)
  1015. end
  1016. return false
  1017. end
  1018. sys.wait(1000) -- 等待以太网模块初始化完成,去掉会导致以太网初始化失败
  1019. -- 设置以太网的 IP 地址、子网掩码、网关地址
  1020. log.info("netdrv", "自定义以太网IP地址", other_configs.adapter_addr, "网关地址",
  1021. other_configs.adapter_gw)
  1022. netdrv.ipv4(socket.LWIP_USER1, other_configs.adapter_addr or "192.168.5.1", "255.255.255.0", "0.0.0.0")
  1023. -- 获取以太网网络状态,连接后返回 true,否则返回 false,如果不存在就返回 nil。
  1024. local count = 1
  1025. while netdrv.ready(socket.LWIP_USER1) ~= true do
  1026. if count > 600 then
  1027. log.error("以太网连接超时,请检查配置")
  1028. if other_configs.ethpower_en then
  1029. gpio.close(other_configs.ethpower_en)
  1030. end
  1031. return false
  1032. end
  1033. count = count + 1
  1034. -- log.info("netdrv", "等待以太网就绪") -- 若以太网设备没有连上,可打开此处注释排查。
  1035. sys.wait(100)
  1036. end
  1037. log.info("netdrv", "以太网就绪")
  1038. -- 创建 DHCP 服务器,为连接到以太网的设备分配 IP 地址。
  1039. log.info("netdrv", "创建dhcp服务器, 供以太网使用")
  1040. if other_configs.adapter_gw then
  1041. dhcpsrv.create({
  1042. adapter = socket.LWIP_USER1,
  1043. gw = other_configs.adapter_gw
  1044. })
  1045. else
  1046. dhcpsrv.create({
  1047. adapter = socket.LWIP_USER1,
  1048. gw = {192, 168, 5, 1}
  1049. })
  1050. end
  1051. -- 创建 DNS 代理服务,使得以太网接口上的设备可以通过 4G 网络访问互联网。
  1052. log.info("netdrv", "创建dns代理服务, 供以太网使用")
  1053. end
  1054. dnsproxy.setup(adapter, main_adapter)
  1055. netdrv.napt(main_adapter)
  1056. return true
  1057. end
  1058. --[[
  1059. 关闭网卡功能。(内核固件版本号需>=2020)
  1060. @api exnetif.close(type,adapter)
  1061. @param type boolean 是否为多网融合
  1062. @param adapter number 需要关闭的网卡
  1063. @return boolean 操作结果
  1064. @usage
  1065. exnetif.close(true) --关闭多网融合功能
  1066. exnetif.close(false,socket.LWIP_ETH) --关闭优先级中的以太网网卡
  1067. ]]
  1068. function exnetif.close(type, adapter)
  1069. if type == true then
  1070. -- TODO: 目前dhcpsrv扩展库,dnsproxy扩展库和napt没有关闭接口
  1071. else
  1072. if adapter == nil then
  1073. log.error("请指定需要关闭的网卡")
  1074. return false
  1075. end
  1076. -- 处理关闭操作,以太网关闭spi和供电使能。WLAN部分AP可以关闭,STA可以断开连接。4G的话就是进出飞行模式。并设置网卡为关闭状态。
  1077. available[adapter] = connection_states.DISCONNECTED
  1078. if adapter == socket.LWIP_AP then
  1079. wlan.stopAP()
  1080. elseif adapter == socket.LWIP_ETH or adapter == socket.LWIP_USER1 then
  1081. if netdrv.CTRL_UPDOWN == nil then
  1082. log.error("当前固件不支持关闭接口,请使用最新固件测试")
  1083. return false
  1084. end
  1085. if eth_cfg[adapter] and eth_cfg[adapter].pwrpin then
  1086. gpio.set(eth_cfg[adapter].pwrpin, 0)
  1087. gpio.close(eth_cfg[adapter].pwrpin)
  1088. end
  1089. -- 关闭spi
  1090. spi.close(eth_cfg[adapter].opts.spi)
  1091. netdrv.ctrl(adapter, netdrv.CTRL_UPDOWN, 0)
  1092. available[adapter] = connection_states.STOPED
  1093. elseif adapter == socket.LWIP_STA then
  1094. wlan.disconnect()
  1095. elseif adapter == socket.LWIP_GP then
  1096. mobile.flymode(nil, true)
  1097. end
  1098. log.info("exnetif", "关闭网卡功能", type_to_string(adapter))
  1099. apply_priority()
  1100. return true
  1101. end
  1102. end
  1103. return exnetif