// 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号 mu sync.Mutex isRunning bool healthCheckExitCh chan struct{} wg sync.WaitGroup ) // 初始化4G网络模块 func ModuleInit(bForceRepower bool /*是否强制重启*/) bool { mu.Lock() defer mu.Unlock() if isRunning { return true } var err error var ret int var bExists bool killAllUdhcpc() err = disableEthBut2() if err != nil { baseapp.Logger.Errorf("[%s] 错误: %v!!", MODULE_NAME, err) return false } bExists, _ = udhcpcEth2Exists() if bExists { killEth2Udhcpc() } _, statErr := os.Stat("/dev/ttyUSB0") bExists = (statErr == nil) if bExists && !bForceRepower { ret, err = air720U_ComInit() if err == nil { goto initOK } switch ret { case -1: // 串口被占用(或不存在, 这里只能是被占用的情况) freeTTYUSB0() case -3: // 设备无应答(初始化时会发送一条关闭回显的指令) 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 } initOK: 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) 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) bOK, err := air720U_IsSimCardReady() if err != nil { air720U_ComExit() baseapp.Logger.Errorf("[%s] 错误: %v!!", MODULE_NAME, err) return false } baseapp.Logger.Infof("[%s] SIM卡状态: %v", MODULE_NAME, bOK) if !bOK { return false } 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) 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) healthCheckExitCh = make(chan struct{}) wg.Add(1) go func() { // 启动携程守护"eth2"网卡上的"udhcpc"后台服务进程 defer wg.Done() monitorEth2Udhcpc(healthCheckExitCh) }() wg.Add(1) go func() { // 启动携程循环读取4G模块的信号强度和ICCID号等信息 defer wg.Done() monitorAir720UInfo(healthCheckExitCh) }() isRunning = true return isRunning } // 4G调制解调器退出 func ModuleExit() { mu.Lock() defer mu.Unlock() if !isRunning { return } close(healthCheckExitCh) wg.Wait() // 等待守护"udhcpc"的携程退出 bExists, _ := udhcpcEth2Exists() if bExists { killEth2Udhcpc() } air720U_ComExit() imei, rssi, iccid = "", "", "" isRunning = false } // 获取模块的标识号 func GetIMEI() string { mu.Lock() defer mu.Unlock() return imei } // 获取当前信号强度 func GetRSSI() string { mu.Lock() defer mu.Unlock() return rssi } // 获取电话卡标识号 func GetSimICCID() string { mu.Lock() defer mu.Unlock() return iccid } // 间隔读取刷新信息 func monitorAir720UInfo(exitCh <-chan struct{}) { t := time.NewTicker(time.Duration(5) * time.Second) defer t.Stop() for { select { case <-t.C: mu.Lock() rssi, _ = air720U_GetRSSIFromCSQ() if bOK, _ := air720U_IsSimCardReady(); bOK { iccid, _ = air720U_GetSimICCID() } else { iccid = "" } mu.Unlock() case <-exitCh: return } // select end } // for end }