// Author: NiuJiuRu // Email: niujiuru@qq.com package air720u import ( "os" "sync" "time" "hnyfkj.com.cn/rtu/linux/baseapp" ) const MODULE_NAME = "Air720U" var ( imei string // Air720U模块的IMEI号, 唯一标识 rssi string // Air720U模块当前信号强度(RSSI) iccid string // Air720U模块插入SIM卡的ICCID号 mu1, mu2, mu3 sync.Mutex isRunning1, isRunning2 bool exitCh1, exitCh2 chan struct{} wg1, wg2 sync.WaitGroup ) // 初始化4G网络模块 func ModuleInit(bForceRepower bool /*是否强制重启*/) bool { mu1.Lock() defer mu1.Unlock() if isRunning1 { return true } var err error var ret int var bExists, bReady bool _, statErr := os.Stat("/dev/ttyUSB0") bExists = (statErr == nil) if bExists && !bForceRepower { ret, err = air720U_ComInit() if err == nil { goto openOK } switch ret { case -1, -3, -100: // -1: 串口被占用或不存在(驱动有问题时) // -3, -100: 设备无应答(初始化时会发送的两条关键配置指令) if ret == -1 { freeTTYUSB0() } air720U_Repower() // 重新上电 bExists = false // 等待复位, 标记设备已不存在 } } else { // 设备不存在, 或调用该函数时明确要求强制重启/ air720U_Repower() //// 重新上电 bExists = false //// 等待复位, 标记设备已不存在 } for range 6 { if baseapp.IsExit1() { air720U_ComExit() return false } if !bExists { time.Sleep(5 * time.Second) // 等待设备文件再次出现 } ret, err = air720U_ComInit() if err != nil && ret == -1 && !bExists { // 继续等待 continue } break } if err != nil { air720U_ComExit() baseapp.Logger.Errorf("[%s] 错误: %v!!", MODULE_NAME, err) return false } openOK: imei, err = air720U_GetIMEI() if err != nil { air720U_ComExit() baseapp.Logger.Errorf("[%s] 错误: %v!!", MODULE_NAME, err) return false } baseapp.Logger.Infof("[%s] 模块IMEI: %s", MODULE_NAME, imei) bReady, _ = air720U_IsSimCardReady() baseapp.Logger.Infof("[%s] SIM卡状态: %v", MODULE_NAME, bReady) if !bReady { goto initOK } for range 30 { // 等待模块完成蜂窝网络注册, 否则RSSI读取不到, 网也不可能不去 if baseapp.IsExit1() { air720U_ComExit() return false } cs, err := air720U_GetCregState() if err != nil || cs == 1 /*已注册本地网*/ || cs == 5 /*已注册漫游网*/ { break } time.Sleep(1 * time.Second) } rssi, err = air720U_GetRSSIFromCSQ() if err != nil { air720U_ComExit() baseapp.Logger.Errorf("[%s] 错误: %v!!", MODULE_NAME, err) return false } baseapp.Logger.Infof("[%s] 模块RSSI: %s", MODULE_NAME, rssi) iccid, err = air720U_GetSimICCID() if err != nil { air720U_ComExit() baseapp.Logger.Errorf("[%s] 错误: %v!!", MODULE_NAME, err) return false } baseapp.Logger.Infof("[%s] SIM卡ICCID: %s", MODULE_NAME, iccid) initOK: exitCh1 = make(chan struct{}) wg1.Add(1) go func() { // 启动携程循环读取4G模块的信号强度和ICCID号等信息 defer wg1.Done() monitorAir720UInfo(exitCh1) }() isRunning1 = true return isRunning1 } // 4G调制解调器退出 func ModuleExit() { mu1.Lock() defer mu1.Unlock() if !isRunning1 { return } close(exitCh1) wg1.Wait() // 等待循环读取4G模块的信号强度和ICCID号等信息的携程退出 air720U_ComExit() imei, rssi, iccid = "", "", "" isRunning1 = false } // 获取模块的标识号 func GetIMEI() string { mu2.Lock() defer mu2.Unlock() return imei } // 获取当前信号强度 func GetRSSI() string { mu2.Lock() defer mu2.Unlock() return rssi } // 获取电话卡标识号 func GetSimICCID() string { mu2.Lock() defer mu2.Unlock() return iccid } // 循环读取刷新信息 func monitorAir720UInfo(exitCh <-chan struct{}) { t := time.NewTicker(time.Duration(5) * time.Second) defer t.Stop() for { select { case <-t.C: mu2.Lock() rssi, _ = air720U_GetRSSIFromCSQ() if bOK, _ := air720U_IsSimCardReady(); bOK { iccid, _ = air720U_GetSimICCID() } else { iccid = "" } mu2.Unlock() case <-exitCh: return } // select end } // for end } // 打开连接到4G网络 func Start4GNetwork() bool { mu3.Lock() defer mu3.Unlock() if isRunning2 { return true } killAllUdhcpc() err := disableEth0() if err != nil { baseapp.Logger.Errorf("[%s] 错误: %v!!", MODULE_NAME, err) return false } bExists, _ := udhcpcEth2Exists() if bExists { killEth2Udhcpc() } err = dialupEth2() if err != nil { baseapp.Logger.Errorf("[%s] 拨号连接\"eth2\"时发生错误: %v!!", MODULE_NAME, err) return false } ipv4, mask, err := getEth2Addr() if err != nil { baseapp.Logger.Errorf("[%s] 读取\"eth2\"地址时发生错误: %v!!", MODULE_NAME, err) return false } baseapp.Logger.Infof("[%s] \"eth2\"分配的地址: %s/%s", MODULE_NAME, ipv4, mask) exitCh2 = make(chan struct{}) wg2.Add(1) go func() { // 启动携程守护"eth2"网卡上的 "udhcpc"后台服务进程 defer wg2.Done() monitorEth2Udhcpc(exitCh2) }() isRunning2 = true return isRunning2 } // 从4G网络断开连接 func Stop4GNetwork() { mu3.Lock() defer mu3.Unlock() if !isRunning2 { return } close(exitCh2) wg2.Wait() // 等待守护"eth2"网卡上的 "udhcpc"后台服务进程的携程退出 bExists, _ := udhcpcEth2Exists() if bExists { killEth2Udhcpc() } isRunning2 = false }