| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281 |
- package netmgrd
- import "C"
- import (
- "sync"
- "sync/atomic"
- "time"
- modem "hnyfkj.com.cn/rtu/linux/air720u"
- "hnyfkj.com.cn/rtu/linux/baseapp"
- )
- const MODULE_NAME = "NetworkManager"
- var (
- isOnline atomic.Bool // 标记是否联网
- offlineStartTs atomic.Int64 // 离线开始时间
- isSyncNTPTimeOK atomic.Bool // 标记本地时间是否已同步成功
- curNetType NetType // 当前的网络类型: 有线、蜂窝
- mu1 sync.Mutex
- isRunning1 bool
- exitCh1 chan struct{}
- wg1 sync.WaitGroup
- )
- type NetType int
- const (
- NetNone NetType = iota
- NetEth // 有线网络
- NetLTE // 蜂窝网络
- )
- func (n NetType) String() string {
- switch n {
- case NetNone:
- return "无网络"
- case NetEth:
- return "有线网络"
- case NetLTE:
- return "蜂窝网络"
- default:
- return "未知网络"
- }
- }
- const (
- interval1 = time.Duration(1) * time.Second
- interval2 = time.Duration(5) * time.Second
- )
- func ModuleInit() {
- go serviceRun()
- }
- // 联网保持服务
- func serviceRun() {
- // 1, 首次连接网络
- openNetwork()
- // 2, 监控联网状态
- t := time.NewTimer(interval1)
- defer t.Stop()
- for {
- select {
- case <-t.C:
- // 3.1 切换网络-看情况
- eth0CableOK, _ := isEth0CableConnected()
- if (eth0CableOK && curNetType != NetEth) || (!eth0CableOK && curNetType != NetLTE) {
- baseapp.Logger.Warnf("[%s] 网络环境发生变化, 正在切换网络...", MODULE_NAME)
- openNetwork()
- }
- // 3.2, 联网检测-看结果
- dnsOK, pingOK, tcpOK, httpOK := CheckNetwork()
- baseapp.Logger.Infof("[%s] 联网类型: %s, 检测结果: DNS OK=%v, PING OK=%v, TCP OK=%v, HTTP OK=%v", MODULE_NAME, curNetType.String(), dnsOK, pingOK, tcpOK, httpOK)
- // 3.3, 联网成功-在线时
- if dnsOK && pingOK && tcpOK {
- isOnline.Store(true)
- offlineStartTs.Store(0)
- if isSyncNTPTimeOK.Load() {
- t.Reset(interval2)
- continue
- }
- err := SyncNTPTime()
- if err == nil {
- isSyncNTPTimeOK.Store(true)
- baseapp.Logger.Infof("[%s] NTP时间已同步", MODULE_NAME)
- t.Reset(interval2)
- continue
- } else {
- baseapp.Logger.Errorf("[%s] 同步NTP时间时有错误发生: %v!!", MODULE_NAME, err)
- t.Reset(interval1)
- continue
- }
- }
- // 3.4, 联网失败-离线时
- if isOnline.Load() { // 状态由"1"变为"0"
- isOnline.Store(false)
- offlineStartTs.Store(time.Now().UnixNano()) // 记录离线开始时间
- }
- if offlineDuration() >= (time.Duration(60) * time.Second) {
- baseapp.Logger.Warnf("[%s] 网络长时间的断开, 正在重新连接...", MODULE_NAME)
- openNetwork()
- offlineStartTs.Store(time.Now().UnixNano()) // 重置离线开始时间
- }
- t.Reset(interval1)
- case <-baseapp.IsExit2():
- return
- } // select end
- } // for end
- }
- // 返回联网状态
- func IsInetAvailable() bool {
- return isOnline.Load()
- }
- // 时间是否同步
- func IsSyncedNtpTime() bool {
- return isSyncNTPTimeOK.Load()
- }
- // 等待所有成功
- func WaitAllOK(timeout time.Duration) bool {
- deadline := time.Now().Add(timeout)
- tick := 50 * time.Millisecond
- for {
- if IsInetAvailable() && IsSyncedNtpTime() {
- return true
- }
- remaining := time.Until(deadline)
- if remaining <= 0 {
- return false
- }
- sleep := min(tick, remaining)
- time.Sleep(sleep)
- }
- }
- // 返回断网时长
- func offlineDuration() time.Duration {
- if IsInetAvailable() {
- return 0
- }
- ts := offlineStartTs.Load()
- if ts == 0 {
- return 0
- }
- return time.Since(time.Unix(0, ts))
- }
- // 打开有线网络
- func openEth0Net() bool {
- mu1.Lock()
- defer mu1.Unlock()
- if isRunning1 {
- return true
- }
- killAllUdhcpc()
- err := disableEthBut0()
- if err != nil {
- baseapp.Logger.Errorf("[%s] 错误: %v!!", MODULE_NAME, err)
- return false
- }
- bExists, _ := udhcpcEth0Exists()
- if bExists {
- killEth0Udhcpc()
- }
- err = dialupEth0()
- if err != nil {
- baseapp.Logger.Errorf("[%s] 拨号连接\"eth0\"时发生错误: %v!!", MODULE_NAME, err)
- return false
- }
- ipv4, mask, err := getEth0Addr()
- if err != nil {
- baseapp.Logger.Errorf("[%s] 读取\"eth0\"地址时发生错误: %v!!", MODULE_NAME, err)
- return false
- }
- baseapp.Logger.Infof("[%s] \"eth0\"分配的地址: %s/%s", MODULE_NAME, ipv4, mask)
- exitCh1 = make(chan struct{})
- wg1.Add(1)
- go func() { // 启动携程守护"eth0"网卡上的 "udhcpc"后台服务进程
- defer wg1.Done()
- monitorEth0Udhcpc(exitCh1)
- }()
- isRunning1 = true
- return isRunning1
- }
- // 断开有线网络
- func closeEth0Net() {
- mu1.Lock()
- defer mu1.Unlock()
- if !isRunning1 {
- return
- }
- close(exitCh1)
- wg1.Wait() // 等待守护"eth0"网卡上的 "udhcpc"后台服务进程的携程退出
- bExists, _ := udhcpcEth0Exists()
- if bExists {
- killEth0Udhcpc()
- }
- isRunning1 = false
- }
- // 打开连接网络
- func openNetwork() {
- closeEth0Net()
- modem.CloseEth2Net()
- eth0CableOK, _ := isEth0CableConnected()
- if eth0CableOK && openEth0Net() {
- curNetType = NetEth
- baseapp.Logger.Infof("[%s] ✅ 有线网络已连接", MODULE_NAME)
- return
- }
- tryOpenLTE := func() bool {
- if eth2CableOK, _ := modem.IsEth2CableConnected(); eth2CableOK {
- if modem.OpenEth2Net() {
- return true
- }
- // 4G模组重新上电初始化后重试
- modem.ModuleExit()
- modem.ModuleInit(true)
- return modem.OpenEth2Net()
- }
- return false
- }
- if tryOpenLTE() {
- curNetType = NetLTE
- baseapp.Logger.Infof("[%s] ✅ 蜂窝网络已连接", MODULE_NAME)
- return
- }
- curNetType = NetNone
- baseapp.Logger.Warnf("[%s] 没有可用的网络连接!", MODULE_NAME)
- }
- // 得到当前联网类型: 有线、蜂窝
- func GetCurrentNetType() NetType {
- return curNetType
- }
- //export RTU_IsInetAvailable
- func RTU_IsInetAvailable() C.int {
- if IsInetAvailable() {
- return 1
- }
- return 0
- }
- //export RTU_IsSyncedNtpTime
- func RTU_IsSyncedNtpTime() C.int {
- if IsSyncedNtpTime() {
- return 1
- }
- return 0
- }
|