libnetif.lua 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  1. --[[
  2. @module libnetif
  3. @summary libnetif 控制网络优先级(以太网->WIFI->4G)根据优先级选择上网的网卡。简化开启多网融合的操作,4G作为数据出口给WIFI,以太网设备上网,以太网作为数据出口给WIFI,Air8000上网,WIFI作为数据出口给Air8000,以太网上网。
  4. @version 1.0
  5. @date 2025.06.26
  6. @author wjq
  7. @usage
  8. 本文件的对外接口有4个:
  9. 1、libnetif.set_priority_order(networkConfigs):设置网络优先级顺序并初始化对应网络
  10. 2、libnetif.notify_status(cb_fnc):设置网络状态变化回调函数
  11. 3、libnetif.setproxy(adapter, main_adapter,other_configs):配置网络代理实现多网融合
  12. 4、libnetif.check_network_status(interval),检测间隔时间ms(选填),不填时只检测一次,填写后将根据间隔时间循环检测,会提高模块功耗
  13. ]]
  14. local libnetif = {}
  15. dnsproxy = require("dnsproxy")
  16. dhcpsrv = require("dhcpsrv")
  17. httpdns = require("httpdns")
  18. -- 设置pingip
  19. local wifi_ping_ip
  20. local eth_ping_ip
  21. local ping_time = 10000
  22. -- 连接状态
  23. local connection_states = {
  24. DISCONNECTED = 0,
  25. CONNECTING = 1,
  26. CONNECTED = 2,
  27. OPENED = 3
  28. }
  29. -- 状态回调函数
  30. local states_cbfnc = function(net_type) end
  31. -- 当前优先级
  32. local current_priority = { socket.LWIP_ETH, socket.LWIP_STA, socket.LWIP_GP }
  33. -- 连接状态
  34. local available = {
  35. [socket.LWIP_STA] = connection_states.DISCONNECTED,
  36. [socket.LWIP_ETH] = connection_states.DISCONNECTED,
  37. [socket.LWIP_GP] = connection_states.DISCONNECTED,
  38. [socket.LWIP_USER1] = connection_states.DISCONNECTED
  39. }
  40. -- 当前使用的网卡
  41. local current_active = socket.LWIP_USER0
  42. -- 网络类型转字符串
  43. local function type_to_string(net_type)
  44. local type_map = {
  45. [socket.LWIP_STA] = "WiFi",
  46. [socket.LWIP_ETH] = "Ethernet",
  47. [socket.LWIP_GP] = "4G",
  48. [socket.LWIP_USER1] = "8101SPIETH"
  49. }
  50. return type_map[net_type] or "Unknown"
  51. end
  52. -- 状态更改后重新设置默认网卡
  53. local function apply_priority()
  54. local usable = false
  55. -- 查找优先级最高的可用网络
  56. for _, net_type in ipairs(current_priority) do
  57. -- log.info("网卡顺序",type_to_string(net_type),available[net_type])
  58. if available[net_type] == connection_states.CONNECTED then
  59. usable = true
  60. -- 设置优先级高的网卡
  61. if current_active ~= net_type then
  62. log.info("设置网卡", type_to_string(net_type))
  63. if current_active ~= socket.LWIP_USER0 then
  64. states_cbfnc(type_to_string(net_type), net_type) -- 默认网卡改变的回调函数
  65. end
  66. socket.dft(net_type)
  67. current_active = net_type
  68. end
  69. break
  70. end
  71. end
  72. if usable == false then
  73. states_cbfnc(nil, -1)
  74. end
  75. end
  76. --打开以太网Wan功能
  77. local function setup_eth(config)
  78. eth_ping_ip = config.ping_ip
  79. if type(config.ping_time) == "number" then
  80. ping_time = config.ping_time
  81. end
  82. log.info("初始化以太网")
  83. available[socket.LWIP_ETH] = connection_states.OPENED
  84. -- 打开CH390供电
  85. gpio.setup(config.pwrpin, 1, gpio.PULLUP)
  86. sys.wait(100)
  87. if config.tp == nil then
  88. log.info("8101以太网")
  89. netdrv.setup(socket.LWIP_ETH)
  90. else
  91. log.info("config.opts.spi",config.opts.spi,",config.type",config.tp)
  92. -- 配置SPI和初始化网络驱动
  93. local result = spi.setup(config.opts.spi, -- spi id
  94. nil, 0, -- CPHA
  95. 0, -- CPOL
  96. 8, -- 数据宽度
  97. 51200000 -- ,--波特率
  98. )
  99. log.info("main", "open spi", result)
  100. if result ~= 0 then -- 返回值为0,表示打开成功
  101. log.info("main", "spi open error", result)
  102. gpio.close(config.pwrpin)
  103. return false
  104. end
  105. -- 初始化指定netdrv设备,
  106. -- socket.LWIP_ETH 网络适配器编号
  107. -- netdrv.CH390外挂CH390
  108. -- SPI ID 1, 片选 GPIO12
  109. netdrv.setup(socket.LWIP_ETH, config.tp, config.opts)
  110. end
  111. netdrv.dhcp(socket.LWIP_ETH, true)
  112. log.info("以太网初始化完成")
  113. return true
  114. end
  115. --打开8101spi以太网Wan功能
  116. local function setup_eth_user1(config)
  117. eth_ping_ip = config.ping_ip
  118. if type(config.ping_time) == "number" then
  119. ping_time = config.ping_time
  120. end
  121. log.info("初始化以太网")
  122. available[socket.LWIP_USER1] = connection_states.OPENED
  123. -- 打开CH390供电
  124. gpio.setup(config.pwrpin, 1, gpio.PULLUP)
  125. sys.wait(100)
  126. log.info("config.opts.spi", config.opts.spi, ",config.type", config.tp)
  127. -- 配置SPI和初始化网络驱动
  128. local result = spi.setup(config.opts.spi, -- spi id
  129. nil, 0, -- CPHA
  130. 0, -- CPOL
  131. 8, -- 数据宽度
  132. 51200000 -- ,--波特率
  133. )
  134. log.info("main", "open spi", result)
  135. if result ~= 0 then -- 返回值为0,表示打开成功
  136. log.info("main", "spi open error", result)
  137. gpio.close(config.pwrpin)
  138. return false
  139. end
  140. -- 初始化指定netdrv设备,
  141. -- socket.LWIP_ETH 网络适配器编号
  142. -- netdrv.CH390外挂CH390
  143. -- SPI ID 1, 片选 GPIO12
  144. netdrv.setup(socket.LWIP_USER1, config.tp, config.opts)
  145. netdrv.dhcp(socket.LWIP_USER1, true)
  146. log.info("以太网初始化完成")
  147. return true
  148. end
  149. --连接wifi(STA模式)
  150. local function set_wifi_info(config)
  151. wifi_ping_ip = config.ping_ip
  152. if type(config.ping_time) == "number" then
  153. ping_time = config.ping_time
  154. end
  155. log.info("WiFi名称:", config.ssid)
  156. log.info("密码 :", config.password)
  157. log.info("ping_ip :", config.ping_ip)
  158. wlan.init()
  159. available[socket.LWIP_STA] = connection_states.OPENED
  160. -- 尝试连接Wi-Fi,并处理可能出现的错误
  161. local success = wlan.connect(config.ssid, config.password)
  162. if not success then
  163. log.error("WiFi连接失败")
  164. return false
  165. end
  166. log.info("WiFi STA初始化完成")
  167. return true
  168. end
  169. --[[
  170. 设置网络优先级,相应网卡获取到ip且网络正常视为网卡可用,丢失ip视为网卡不可用.
  171. 例:插入网线且能够dns域名解析获取到baidu.com的ip,网卡状态切换为可用。拔掉网线网卡状态切换为不可用
  172. @api libnetif.set_priority_order(new_priority)
  173. @table 网络优先级列表
  174. @return boolean 成功返回true,失败返回false
  175. @usage
  176. libnetif.set_priority_order({
  177. { -- 最高优先级网络
  178. WIFI = { -- WiFi配置
  179. ssid = "your_ssid", -- WiFi名称(string)
  180. password = "your_pwd", -- WiFi密码(string)
  181. ping_ip = "112.125.89.8", -- 连通性检测IP(选填参数),默认使用httpdns获取baidu.com的ip作为判断条件,
  182. -- 注:如果填写ip,则ping通作为判断网络是否可用的条件,
  183. -- 所以需要根据网络环境填写内网或者外网ip,
  184. -- 填写外网ip的话要保证外网ip始终可用,
  185. -- 填写局域网ip的话要确保相应ip固定且能够被ping通
  186. ping_time = 10000 -- 填写ping_ip且未ping通时的检测间隔(ms, 可选,默认为10秒)
  187. -- 定时ping将会影响模块功耗,使用低功耗模式的话可以适当延迟间隔时间
  188. }
  189. },
  190. { -- 次优先级网络
  191. ETHERNET = { -- 以太网配置
  192. pwrpin = 140, -- 供电使能引脚(number)
  193. ping_ip = "112.125.89.8", -- 连通性检测IP(选填参数),默认使用httpdns获取baidu.com的ip作为判断条件,
  194. -- 注:如果填写ip,则ping通作为判断网络是否可用的条件,
  195. -- 所以需要根据网络环境填写内网或者外网ip,
  196. -- 填写外网ip的话要保证外网ip始终可用,
  197. -- 填写局域网ip的话要确保相应ip固定且能够被ping通
  198. ping_time = 10000 -- 填写ping_ip且未ping通时的检测间隔(ms, 可选,默认为10秒)
  199. -- 定时ping将会影响模块功耗,使用低功耗模式的话可以适当延迟间隔时间
  200. tp = netdrv.CH390 -- 网卡芯片型号(选填参数),仅spi方式外挂以太网时需要填写。
  201. opts = { spi = 1, cs = 12 } -- 外挂方式,需要额外的参数(选填参数),仅spi方式外挂以太网时需要填写。
  202. }
  203. },
  204. { -- 最低优先级网络
  205. LWIP_GP = true -- 启用4G网络
  206. }
  207. })
  208. ]]
  209. function libnetif.set_priority_order(networkConfigs)
  210. --判断表中数据个数
  211. if #networkConfigs <2 then
  212. log.error("请至少添加两个网络")
  213. return false
  214. end
  215. local new_priority = {}
  216. for _, config in ipairs(networkConfigs) do
  217. if type(config.WIFI) == "table" then
  218. --开启wifi
  219. local res = set_wifi_info(config.WIFI)
  220. if res == false then
  221. log.error("wifi连接失败")
  222. return false
  223. end
  224. table.insert(new_priority, socket.LWIP_STA)
  225. end
  226. if type(config.ETHUSER1) == "table" then
  227. --开启以太网
  228. local res = setup_eth_user1(config.ETHUSER1)
  229. if res == false then
  230. log.error("以太网打开失败")
  231. return false
  232. end
  233. table.insert(new_priority, socket.LWIP_USER1)
  234. end
  235. if type(config.ETHERNET) == "table" then
  236. --开启以太网
  237. local res = setup_eth(config.ETHERNET)
  238. if res == false then
  239. log.error("以太网打开失败")
  240. return false
  241. end
  242. table.insert(new_priority, socket.LWIP_ETH)
  243. end
  244. if config.LWIP_GP then
  245. --开启4G
  246. table.insert(new_priority, socket.LWIP_GP)
  247. available[socket.LWIP_GP] = connection_states.CONNECTING
  248. end
  249. end
  250. -- 设置新优先级
  251. current_priority = new_priority
  252. apply_priority()
  253. return true
  254. end
  255. --[[
  256. 设置网络状态变化回调函数
  257. 触发条件是 网卡切换或者所有网卡都断网
  258. 返回值为:
  259. 1. 当有可用网络的时候,返回当前使用网卡、网卡id;
  260. 2. 当没有可用网络的时候,返回 nil、-1 。
  261. @api libnetif.notify_status(cb_fnc)
  262. @function 回调函数
  263. @usage
  264. libnetif.notify_status(function(net_type,adapter)
  265. log.info("可以使用优先级更高的网络:", net_type,adapter)
  266. end)
  267. ]]
  268. function libnetif.notify_status(cb_fnc)
  269. log.info("notify_status", type(cb_fnc))
  270. if type(cb_fnc) ~= "function" then
  271. log.error("notify_status设置错误,请传入一个函数")
  272. return
  273. end
  274. states_cbfnc = cb_fnc
  275. end
  276. --[[
  277. 设置多网融合模式,例如4G作为数据出口给WIFI或以太网设备上网
  278. @api libnetif.setproxy(adapter, main_adapter,other_configs)
  279. @adapter 需要使用网络的网卡,例如socket.LWIP_ETH
  280. @adapter 提供网络的网卡,例如socket.LWIP_GP
  281. @table 其他设置参数(选填参数),
  282. {
  283. ssid = "Hotspot", -- WiFi名称(string),网卡包含wifi时填写
  284. password = "password123", -- WiFi密码(string),网卡包含wifi时填写
  285. tp = netdrv.CH390, -- 网卡芯片型号(选填参数),仅spi方式外挂以太网时需要填写。
  286. opts = { spi = 1, cs = 12}, -- 外挂方式,需要额外的参数(选填参数),仅spi方式外挂以太网时需要填写。
  287. ethpower_en = 140, -- 以太网模块的pwrpin引脚(gpio编号)
  288. adapter_addr = "192.168.5.1", -- adapter网卡的ip地址(选填),需要自定义ip和网关ip时填写
  289. adapter_gw= { 192, 168, 5, 1 }, -- adapter网卡的网关地址(选填),需要自定义ip和网关ip时填写
  290. ap_opts={ -- AP模式下配置项(选填参数)
  291. hidden = false, -- 是否隐藏SSID, 默认false,不隐藏
  292. max_conn = 4 }, -- 最大客户端数量, 默认4
  293. channel=6 -- AP建立的通道, 默认6
  294. }
  295. @usage
  296. --典型应用:
  297. -- 4G作为出口供WiFi和以太网设备上网
  298. libnetif.setproxy(socket.LWIP_AP, socket.LWIP_GP, {
  299. ssid = "Hotspot", -- WiFi名称(string),网卡包含wifi时填写
  300. password = "password123", -- WiFi密码(string),网卡包含wifi时填写
  301. adapter_addr = "192.168.5.1", -- adapter网卡的ip地址(选填),需要自定义ip和网关ip时填写
  302. adapter_gw= { 192, 168, 5, 1 }, -- adapter网卡的网关地址(选填),需要自定义ip和网关ip时填写
  303. ap_opts={ -- AP模式下配置项(选填参数)
  304. hidden = false, -- 是否隐藏SSID, 默认false,不隐藏
  305. max_conn = 4 }, -- 最大客户端数量, 默认4
  306. channel=6 -- AP建立的通道, 默认6
  307. })
  308. libnetif.setproxy(socket.LWIP_ETH, socket.LWIP_GP, {
  309. tp = netdrv.CH390, -- 网卡芯片型号(选填参数),仅spi方式外挂以太网时需要填写。
  310. opts = { spi = 1, cs = 12}, -- 外挂方式,需要额外的参数(选填参数),仅spi方式外挂以太网时需要填写。
  311. ethpower_en = 140, -- 以太网模块的pwrpin引脚(gpio编号)
  312. adapter_addr = "192.168.5.1", -- adapter网卡的ip地址(选填),需要自定义ip和网关ip时填写
  313. adapter_gw= { 192, 168, 5, 1 }, -- adapter网卡的网关地址(选填),需要自定义ip和网关ip时填写
  314. })
  315. -- 以太网作为出口供WiFi设备上网
  316. libnetif.setproxy(socket.LWIP_AP, socket.LWIP_ETH, {
  317. ssid = "Hotspot", -- WiFi名称(string),网卡包含wifi时填写
  318. password = "password123", -- WiFi密码(string),网卡包含wifi时填写
  319. tp = netdrv.CH390, -- 网卡芯片型号(选填参数),仅spi方式外挂以太网时需要填写。
  320. opts = { spi = 1, cs = 12}, -- 外挂方式,需要额外的参数(选填参数),仅spi方式外挂以太网时需要填写。
  321. ethpower_en = 140, -- 以太网模块的pwrpin引脚(gpio编号)
  322. })
  323. -- 4G作为出口供以太网设备上网
  324. libnetif.setproxy(socket.LWIP_ETH, socket.LWIP_GP, {
  325. tp = netdrv.CH390, -- 网卡芯片型号(选填参数),仅spi方式外挂以太网时需要填写。
  326. opts = { spi = 1, cs = 12}, -- 外挂方式,需要额外的参数(选填参数),仅spi方式外挂以太网时需要填写。
  327. ethpower_en = 140, -- 以太网模块的pwrpin引脚(gpio编号)
  328. })
  329. ]]
  330. function libnetif.setproxy(adapter, main_adapter, other_configs)
  331. if adapter == socket.LWIP_ETH then
  332. log.info("ch390", "打开LDO供电", other_configs.ethpower_en)
  333. gpio.setup(other_configs.ethpower_en, 1, gpio.PULLUP)
  334. -- 打开LAN功能
  335. -- 配置 SPI 参数,Air8000 使用 SPI 接口与以太网模块进行通信。
  336. if other_configs.tp then
  337. log.info("netdrv spi挂载以太网", "初始化LAN功能")
  338. local result = spi.setup(
  339. other_configs.opts.spi, -- spi id
  340. nil, 0, -- CPHA
  341. 0, -- CPOL
  342. 8, -- 数据宽度
  343. 51200000 -- ,--波特率
  344. )
  345. log.info("main", "open spi", result)
  346. if result ~= 0 then -- 返回值为 0,表示打开成功
  347. log.error("main", "spi open error", result)
  348. gpio.close(other_configs.ethpower_en)
  349. return false
  350. end
  351. end
  352. -- 初始化以太网,Air8000 指定使用 CH390 芯片。
  353. log.info("netdrv", "初始化以太网", other_configs.tp, other_configs.opts)
  354. netdrv.setup(socket.LWIP_ETH, other_configs.tp, other_configs.opts)
  355. log.info("netdrv", "等待以太网就绪")
  356. sys.wait(1000)
  357. -- 设置以太网的 IP 地址、子网掩码、网关地址
  358. log.info("netdrv", "自定义以太网IP地址", other_configs.adapter_addr, "网关地址", other_configs.adapter_gw)
  359. netdrv.ipv4(socket.LWIP_ETH, other_configs.adapter_addr or "192.168.5.1", "255.255.255.0", "0.0.0.0")
  360. -- 获取以太网网络状态,连接后返回 true,否则返回 false,如果不存在就返回 nil。
  361. local count = 1
  362. while netdrv.ready(socket.LWIP_ETH) ~= true do
  363. if count > 600 then
  364. log.error("以太网连接超时,请检查配置")
  365. gpio.close(other_configs.ethpower_en)
  366. return false
  367. end
  368. count = count + 1
  369. -- log.info("netdrv", "等待以太网就绪") -- 若以太网设备没有连上,可打开此处注释排查。
  370. sys.wait(100)
  371. end
  372. log.info("netdrv", "以太网就绪")
  373. -- 创建 DHCP 服务器,为连接到以太网的设备分配 IP 地址。
  374. log.info("netdrv", "创建dhcp服务器, 供以太网使用")
  375. if other_configs.adapter_gw then
  376. dhcpsrv.create({ adapter = socket.LWIP_ETH, gw = other_configs.adapter_gw })
  377. else
  378. dhcpsrv.create({ adapter = socket.LWIP_ETH, gw = { 192, 168, 5, 1 } })
  379. end
  380. -- 创建 DNS 代理服务,使得以太网接口上的设备可以通过 4G 网络访问互联网。
  381. log.info("netdrv", "创建dns代理服务, 供以太网使用")
  382. elseif adapter == socket.LWIP_AP then
  383. wlan.setMode(wlan.APSTA)
  384. -- 打开AP功能,设置混合模式
  385. log.info("执行AP创建操作", airlink.ready(), "正常吗?")
  386. wlan.createAP(other_configs.ssid, other_configs.password, other_configs.adapter_addr or "192.168.4.1",
  387. "255.255.255.0",
  388. other_configs.channel, other_configs.ap_opts)
  389. -- 设置 AP 的 IP 地址、子网掩码、网关地址
  390. netdrv.ipv4(socket.LWIP_AP, other_configs.adapter_addr or "192.168.4.1", "255.255.255.0", "0.0.0.0")
  391. -- 获取 WiFi AP 网络状态,连接后返回 true,否则返回 false,如果不存在就返回 nil。
  392. log.info("netdrv", "等待AP就绪")
  393. local count = 1
  394. while netdrv.ready(socket.LWIP_AP) ~= true do
  395. -- log.info("netdrv", "等待AP就绪")
  396. if count > 600 then
  397. log.error("AP创建超时,请检查配置")
  398. return false
  399. end
  400. sys.wait(100)
  401. count = count + 1
  402. end
  403. -- 创建 DHCP 服务器,为连接到 WiFi AP 的设备分配 IP 地址。
  404. log.info("netdrv", "创建dhcp服务器, 供AP使用")
  405. if other_configs.adapter_gw then
  406. dhcpsrv.create({ adapter = socket.LWIP_AP, gw = other_configs.adapter_gw })
  407. else
  408. dhcpsrv.create({ adapter = socket.LWIP_AP })
  409. end
  410. elseif adapter == socket.LWIP_USER1 then
  411. log.info("ch390", "打开LDO供电", other_configs.ethpower_en)
  412. gpio.setup(other_configs.ethpower_en, 1, gpio.PULLUP)
  413. -- 打开LAN功能
  414. -- 配置 SPI 参数,Air8101 使用 SPI 接口与以太网模块进行通信。
  415. log.info("netdrv spi挂载以太网", "初始化LAN功能")
  416. local result = spi.setup(
  417. other_configs.opts.spi, -- spi id
  418. nil, 0, -- CPHA
  419. 0, -- CPOL
  420. 8, -- 数据宽度
  421. 51200000 -- ,--波特率
  422. )
  423. log.info("main", "open spi", result)
  424. if result ~= 0 then -- 返回值为 0,表示打开成功
  425. log.error("main", "spi open error", result)
  426. gpio.close(other_configs.ethpower_en)
  427. return false
  428. end
  429. -- 初始化以太网,Air8000 指定使用 CH390 芯片。
  430. log.info("netdrv", "初始化以太网", other_configs.tp, other_configs.opts)
  431. netdrv.setup(socket.LWIP_USER1, other_configs.tp, other_configs.opts)
  432. log.info("netdrv", "等待以太网就绪")
  433. sys.wait(1000)
  434. -- 设置以太网的 IP 地址、子网掩码、网关地址
  435. log.info("netdrv", "自定义以太网IP地址", other_configs.adapter_addr, "网关地址", other_configs.adapter_gw)
  436. netdrv.ipv4(socket.LWIP_USER1, other_configs.adapter_addr or "192.168.5.1", "255.255.255.0", "0.0.0.0")
  437. -- 获取以太网网络状态,连接后返回 true,否则返回 false,如果不存在就返回 nil。
  438. local count = 1
  439. while netdrv.ready(socket.LWIP_USER1) ~= true do
  440. if count > 600 then
  441. log.error("以太网连接超时,请检查配置")
  442. gpio.close(other_configs.ethpower_en)
  443. return false
  444. end
  445. count = count + 1
  446. -- log.info("netdrv", "等待以太网就绪") -- 若以太网设备没有连上,可打开此处注释排查。
  447. sys.wait(100)
  448. end
  449. log.info("netdrv", "以太网就绪")
  450. -- 创建 DHCP 服务器,为连接到以太网的设备分配 IP 地址。
  451. log.info("netdrv", "创建dhcp服务器, 供以太网使用")
  452. if other_configs.adapter_gw then
  453. dhcpsrv.create({ adapter = socket.LWIP_USER1, gw = other_configs.adapter_gw })
  454. else
  455. dhcpsrv.create({ adapter = socket.LWIP_USER1, gw = { 192, 168, 5, 1 } })
  456. end
  457. -- 创建 DNS 代理服务,使得以太网接口上的设备可以通过 4G 网络访问互联网。
  458. log.info("netdrv", "创建dns代理服务, 供以太网使用")
  459. end
  460. if main_adapter == socket.LWIP_ETH and available[socket.LWIP_ETH] == connection_states.DISCONNECTED then
  461. -- 打开WAN功能
  462. log.info("ch390", "打开LDO供电", other_configs.ethpower_en)
  463. available[socket.LWIP_ETH] = connection_states.OPENED
  464. -- 打开CH390供电
  465. gpio.setup(other_configs.ethpower_en, 1, gpio.PULLUP)
  466. sys.wait(100)
  467. if other_configs.tp == nil then
  468. log.info("8101以太网")
  469. netdrv.setup(socket.LWIP_ETH)
  470. else
  471. log.info("config.opts.spi", other_configs.opts.spi, ",config.type", other_configs.tp)
  472. -- 配置SPI和初始化网络驱动
  473. local result = spi.setup(other_configs.opts.spi, -- spi id
  474. nil, 0, -- CPHA
  475. 0, -- CPOL
  476. 8, -- 数据宽度
  477. 51200000 -- ,--波特率
  478. )
  479. log.info("main", "open spi", result)
  480. if result ~= 0 then -- 返回值为0,表示打开成功
  481. log.info("main", "spi open error", result)
  482. gpio.close(other_configs.ethpower_en)
  483. return false
  484. end
  485. -- 初始化指定netdrv设备,
  486. local success = netdrv.setup(socket.LWIP_ETH, other_configs.tp, other_configs.opts)
  487. if not success then
  488. log.error("以太网初始化失败")
  489. return false
  490. end
  491. end
  492. netdrv.dhcp(socket.LWIP_ETH, true)
  493. local count = 1
  494. while 1 do
  495. local ip = netdrv.ipv4(socket.LWIP_ETH)
  496. if ip and ip ~= "0.0.0.0" then break end
  497. if count > 600 then
  498. log.error("以太网连接超时,请检查配置")
  499. gpio.close(other_configs.ethpower_en)
  500. return false
  501. end
  502. sys.wait(100)
  503. count = count + 1
  504. end
  505. elseif main_adapter == socket.LWIP_USER1 and available[socket.LWIP_USER1] == connection_states.DISCONNECTED then
  506. log.info("初始化以太网")
  507. -- 打开CH390供电
  508. gpio.setup(other_configs.ethpower_en, 1, gpio.PULLUP)
  509. sys.wait(100)
  510. log.info("config.opts.spi", other_configs.opts.spi, ",config.type", other_configs.tp)
  511. available[socket.LWIP_USER1] = connection_states.OPENED
  512. -- 配置SPI和初始化网络驱动
  513. local result = spi.setup(other_configs.opts.spi, -- spi id
  514. nil, 0, -- CPHA
  515. 0, -- CPOL
  516. 8, -- 数据宽度
  517. 51200000 -- ,--波特率
  518. )
  519. log.info("main", "open spi", result)
  520. if result ~= 0 then -- 返回值为0,表示打开成功
  521. log.info("main", "spi open error", result)
  522. gpio.close(other_configs.ethpower_en)
  523. return false
  524. end
  525. -- 初始化指定netdrv设备,
  526. -- socket.LWIP_ETH 网络适配器编号
  527. -- netdrv.CH390外挂CH390
  528. -- SPI ID 1, 片选 GPIO12
  529. netdrv.setup(socket.LWIP_USER1, other_configs.tp, other_configs.opts)
  530. netdrv.dhcp(socket.LWIP_USER1, true)
  531. log.info("以太网初始化完成")
  532. local count = 1
  533. while 1 do
  534. local ip = netdrv.ipv4(socket.LWIP_USER1)
  535. if ip and ip ~= "0.0.0.0" then break end
  536. if count > 600 then
  537. log.error("以太网连接超时,请检查配置")
  538. gpio.close(other_configs.ethpower_en)
  539. return false
  540. end
  541. sys.wait(100)
  542. count = count + 1
  543. end
  544. elseif main_adapter == socket.LWIP_STA and available[socket.LWIP_STA] == connection_states.DISCONNECTED then
  545. -- 打开STA功能,设置混合模式
  546. wlan.init()
  547. wlan.setMode(wlan.APSTA)
  548. available[socket.LWIP_STA] = connection_states.OPENED
  549. -- 尝试连接Wi-Fi,并处理可能出现的错误
  550. wlan.connect(other_configs.ssid, other_configs.password)
  551. -- 等待获取IP地址
  552. local count = 1
  553. while 1 do
  554. local ip = netdrv.ipv4(socket.LWIP_STA)
  555. if ip and ip ~= "0.0.0.0" then
  556. log.info("WiFi STA已连接,IP:", ip)
  557. break
  558. end
  559. if count > 600 then
  560. log.error("WiFi STA连接超时,请检查配置")
  561. return false
  562. end
  563. sys.wait(100)
  564. count = count + 1
  565. end
  566. log.info("WiFi STA初始化完成")
  567. end
  568. dnsproxy.setup(adapter, main_adapter)
  569. netdrv.napt(main_adapter)
  570. return true
  571. end
  572. --httpdns域名解析测试
  573. local function http_dnstest(adaptertest)
  574. local ip = httpdns.ali("baidu.com", { adapter = adaptertest, timeout = 3000 })
  575. if ip ~= nil then
  576. available[adaptertest] = connection_states.CONNECTED
  577. end
  578. log.info("httpdns", "baidu.com", ip)
  579. end
  580. -- ping操作
  581. local function ping_request(adaptertest)
  582. log.info("dns_request",type_to_string(adaptertest))
  583. if adaptertest == socket.LWIP_ETH or adaptertest == socket.LWIP_USER1 then
  584. if eth_ping_ip == nil then
  585. http_dnstest(adaptertest)
  586. else
  587. icmp.setup(adaptertest)
  588. icmp.ping(adaptertest, eth_ping_ip)
  589. end
  590. end
  591. if adaptertest == socket.LWIP_STA then
  592. if wifi_ping_ip == nil then
  593. http_dnstest(adaptertest)
  594. else
  595. icmp.setup(adaptertest)
  596. icmp.ping(adaptertest, wifi_ping_ip)
  597. end
  598. end
  599. if adaptertest == socket.LWIP_GP then
  600. if eth_ping_ip ~= nil then
  601. icmp.setup(adaptertest)
  602. icmp.ping(adaptertest, eth_ping_ip)
  603. elseif wifi_ping_ip ~= nil then
  604. icmp.setup(adaptertest)
  605. icmp.ping(adaptertest, wifi_ping_ip)
  606. else
  607. http_dnstest(adaptertest)
  608. end
  609. end
  610. apply_priority()
  611. end
  612. -- 网卡上线回调函数
  613. local function ip_ready_handle(ip, adapter)
  614. log.info("ip_ready_handle", ip, type_to_string(adapter),"state",available[adapter])
  615. -- 需要ping操作,ping通后认为网络可用
  616. if available[adapter] == connection_states.OPENED then
  617. available[adapter] = connection_states.CONNECTING
  618. end
  619. -- ping_request(adapter)
  620. end
  621. -- 网卡下线回调函数
  622. local function ip_lose_handle(adapter)
  623. log.info("ip_lose_handle", type_to_string(adapter))
  624. available[adapter] = connection_states.OPENED
  625. if current_active == adapter then
  626. log.info(type_to_string(adapter) .. " 失效,切换到其他网络")
  627. apply_priority()
  628. end
  629. end
  630. --CONNECTING的网卡需要定时ping
  631. sys.taskInit(function()
  632. while true do
  633. for _, net_type in ipairs(current_priority) do
  634. -- log.info("网卡顺序",type_to_string(net_type),available[net_type])
  635. if available[net_type] == connection_states.CONNECTING then
  636. ping_request(net_type)
  637. log.info(type_to_string(net_type) .. "网卡未ping通,需要定时ping")
  638. sys.wait(ping_time)
  639. end
  640. end
  641. sys.wait(1000)
  642. end
  643. end)
  644. local interval_time = nil
  645. --[[
  646. 对正常状态的网卡进行ping测试
  647. @api libnetif.check_network_status(interval),
  648. @int 检测间隔时间ms(选填),不填时只检测一次,填写后将根据间隔时间循环检测,会提高模块功耗
  649. ]]
  650. function libnetif.check_network_status(interval)
  651. if interval ~= nil then
  652. interval_time = interval
  653. end
  654. for _, net_type in ipairs(current_priority) do
  655. if available[net_type] == connection_states.CONNECTED then
  656. available[net_type] = connection_states.CONNECTING
  657. end
  658. end
  659. end
  660. --循环ping检测任务,默认不启用
  661. sys.taskInit(function()
  662. while true do
  663. if interval_time ~= nil then
  664. sys.wait(interval_time)
  665. libnetif.check_network_status()
  666. end
  667. sys.wait(1000)
  668. end
  669. end)
  670. sys.subscribe("PING_RESULT", function(id, time, dst)
  671. log.info("ping", type_to_string(id), time, dst);
  672. available[id] = connection_states.CONNECTED
  673. apply_priority()
  674. end)
  675. -- 订阅网络状态变化的消息
  676. sys.subscribe("IP_READY", ip_ready_handle)
  677. sys.subscribe("IP_LOSE", ip_lose_handle)
  678. return libnetif