|
|
@@ -3,9 +3,12 @@ package netmgrd
|
|
|
import "C"
|
|
|
|
|
|
import (
|
|
|
+ "sync"
|
|
|
"sync/atomic"
|
|
|
+ "syscall"
|
|
|
"time"
|
|
|
|
|
|
+ "github.com/vishvananda/netlink"
|
|
|
modem "hnyfkj.com.cn/rtu/linux/air720u"
|
|
|
"hnyfkj.com.cn/rtu/linux/baseapp"
|
|
|
)
|
|
|
@@ -16,6 +19,19 @@ var (
|
|
|
isOnline atomic.Bool // 标记是否联网
|
|
|
offlineStartTs atomic.Int64 // 离线开始时间
|
|
|
isSyncNTPTimeOK atomic.Bool // 标记本地时间是否已同步成功
|
|
|
+ mu1 sync.Mutex
|
|
|
+ isRunning1 bool
|
|
|
+ exitCh1 chan struct{}
|
|
|
+ wg1 sync.WaitGroup
|
|
|
+ curNetType NetType // 当前使用的网络类型
|
|
|
+)
|
|
|
+
|
|
|
+type NetType int
|
|
|
+
|
|
|
+const (
|
|
|
+ NetNone NetType = iota
|
|
|
+ NetEth // 有线网络
|
|
|
+ NetLTE // 蜂窝网络
|
|
|
)
|
|
|
|
|
|
const (
|
|
|
@@ -29,17 +45,26 @@ func ModuleInit() {
|
|
|
|
|
|
// 联网保持服务
|
|
|
func serviceRun() {
|
|
|
+ // 1, 首次连接网络
|
|
|
+ network_reconnect()
|
|
|
+
|
|
|
+ // 2, 监听有线插拔
|
|
|
+ eth0PlugCycleCh := make(chan bool, 1)
|
|
|
+ done := make(chan struct{})
|
|
|
+ defer close(done)
|
|
|
+ go monitorEth0PlugCycle(eth0PlugCycleCh, done)
|
|
|
+
|
|
|
+ // 3, 循环监控网络
|
|
|
t := time.NewTimer(interval1)
|
|
|
defer t.Stop()
|
|
|
-
|
|
|
for {
|
|
|
select {
|
|
|
case <-t.C:
|
|
|
- // 1, 联网检测-看结果
|
|
|
+ // 3.1, 联网检测-看结果
|
|
|
dnsOK, pingOK, tcpOK, httpOK := CheckNetwork()
|
|
|
baseapp.Logger.Infof("[%s] 联网检测: DNS OK=%v, PING OK=%v, TCP OK=%v, HTTP OK=%v", MODULE_NAME, dnsOK, pingOK, tcpOK, httpOK)
|
|
|
|
|
|
- // 2, 检测成功-在线时
|
|
|
+ // 3.2, 检测成功-在线时
|
|
|
if dnsOK && pingOK && tcpOK {
|
|
|
isOnline.Store(true)
|
|
|
offlineStartTs.Store(0)
|
|
|
@@ -62,19 +87,22 @@ func serviceRun() {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // 3, 检测失败-离线时
|
|
|
+ // 3.3, 检测失败-离线时
|
|
|
if isOnline.Load() { // 状态由"1"变为"0"
|
|
|
isOnline.Store(false)
|
|
|
offlineStartTs.Store(time.Now().UnixNano()) // 记录离线开始时间
|
|
|
}
|
|
|
|
|
|
if OfflineDuration() >= (time.Duration(60) * time.Second) {
|
|
|
- baseapp.Logger.Warnf("[%s] 检测到网络长时间断开, 将重置4G模块!", MODULE_NAME)
|
|
|
- reset4gNetwork()
|
|
|
+ baseapp.Logger.Warnf("[%s] 检测到网络长时间断开, 将重新尝试连接!", MODULE_NAME)
|
|
|
+ network_reconnect()
|
|
|
offlineStartTs.Store(time.Now().UnixNano()) // 重置离线开始时间
|
|
|
}
|
|
|
|
|
|
t.Reset(interval1)
|
|
|
+ case <-eth0PlugCycleCh: // 有线网口插拔事件, 重新连接网络, 有线网优先
|
|
|
+ network_reconnect()
|
|
|
+ continue
|
|
|
case <-baseapp.IsExit2():
|
|
|
return
|
|
|
} // select end
|
|
|
@@ -123,10 +151,146 @@ func OfflineDuration() time.Duration {
|
|
|
return time.Since(time.Unix(0, ts))
|
|
|
}
|
|
|
|
|
|
-// 重启模块联网
|
|
|
-func reset4gNetwork() {
|
|
|
- modem.ModuleExit()
|
|
|
- modem.ModuleInit(true)
|
|
|
+// 连接有线网络
|
|
|
+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 network_reconnect() {
|
|
|
+ // 1, 断开所有网络
|
|
|
+ CloseEth0Net()
|
|
|
+ modem.CloseEth2Net()
|
|
|
+
|
|
|
+ // 2, 尝试有线网络
|
|
|
+ eth0CableOK, _ := isEth0CableConnected()
|
|
|
+ if eth0CableOK && curNetType != NetEth && OpenEth0Net() {
|
|
|
+ curNetType = NetEth
|
|
|
+ baseapp.Logger.Infof("[%s] ✅ 已连接有线网络", MODULE_NAME)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3, 尝试蜂窝网络
|
|
|
+ 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
|
|
|
+ enableEth0() // 保持 eth0 可用, 以便监听网线的插拔, 触发切换网络
|
|
|
+ baseapp.Logger.Infof("[%s] ✅ 已连接蜂窝网络", MODULE_NAME)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 4, 都不可用
|
|
|
+ curNetType = NetNone
|
|
|
+}
|
|
|
+
|
|
|
+// 监控网线插拔
|
|
|
+func monitorEth0PlugCycle(plugCycle chan bool, done chan struct{}) error {
|
|
|
+ updates := make(chan netlink.LinkUpdate)
|
|
|
+ if err := netlink.LinkSubscribe(updates, done); err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+ link, err := netlink.LinkByName("eth0")
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+ isUp := link.Attrs().Flags&syscall.IFF_RUNNING != 0
|
|
|
+ waitingForPlug := false
|
|
|
+
|
|
|
+ for u := range updates {
|
|
|
+ if u.Link.Attrs().Name != "eth0" {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ newUp := u.IfInfomsg.Flags&syscall.IFF_RUNNING != 0
|
|
|
+ if newUp == isUp {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ isUp = newUp
|
|
|
+
|
|
|
+ if !isUp {
|
|
|
+ baseapp.Logger.Warnf("[%s] ❌ eth0 cable unplugged!", MODULE_NAME)
|
|
|
+ waitingForPlug = true
|
|
|
+ } else if waitingForPlug {
|
|
|
+ baseapp.Logger.Infof("[%s] ✅ eth0 cable plugged in", MODULE_NAME)
|
|
|
+ plugCycle <- true
|
|
|
+ waitingForPlug = false
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return nil
|
|
|
}
|
|
|
|
|
|
//export RTU_IsInetAvailable
|