// Author: NiuJiuRu // Email: niujiuru@qq.com package ec200u import ( "os" "sync" "time" "hnyfkj.com.cn/rtu/linux/baseapp" ) const MODULE_NAME = "EC200U" var ( imei string // EC200U模块的IMEI号, 唯一标识 rssi string // EC200U模块当前信号强度(RSSI) iccid string // EC200U模块插入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 = ec200U_ComInit() if err == nil { goto openOK } switch ret { case -1, -3, -4, -5, -100: // -1: 串口被占用或不存在(驱动有问题时) // -3, -4, -5, -100: 设备无应答(初始化时会发送的四条关键配置指令) if ret == -1 { freeTTYUSB0() } ec200U_Repower() // 重新上电 bExists = false // 等待复位, 标记设备已不存在 } } else { ///// 设备不存在, 或调用该函数时明确要求强制重启 //// ec200U_Repower() //// 重新上电 bExists = false //// 等待复位, 标记设备已不存在 } for range 6 { if baseapp.IsExit1() { ec200U_ComExit() return false } if !bExists { time.Sleep(5 * time.Second) // 等待设备文件再次出现 } ret, err = ec200U_ComInit() if err != nil && ret == -1 && !bExists { // 继续等待 continue } break } if err != nil { ec200U_ComExit() baseapp.Logger.Errorf("[%s] 错误: %v!!", MODULE_NAME, err) return false } openOK: imei, err = ec200U_GetIMEI() if err != nil { ec200U_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() { ec200U_ComExit() return false } cs, err := ec200U_GetCregState() if err != nil || cs == 1 /*已注册本地网*/ || cs == 5 /*已注册漫游网*/ { break } time.Sleep(1 * time.Second) } rssi, err = ec200U_GetRSSIFromCSQ() if err != nil { ec200U_ComExit() baseapp.Logger.Errorf("[%s] 错误: %v!!", MODULE_NAME, err) return false } baseapp.Logger.Infof("[%s] 模块RSSI: %s", MODULE_NAME, rssi) bReady, err = ec200U_IsSimCardReady() if err != nil { ec200U_ComExit() baseapp.Logger.Errorf("[%s] 错误: %v!!", MODULE_NAME, err) return false } baseapp.Logger.Infof("[%s] SIM卡状态: %v", MODULE_NAME, bReady) if !bReady { // 未插入SIM卡, 也不影响初始化成功, 可等待之后的热插入 goto initOK } iccid, err = ec200U_GetSimICCID() if err != nil { ec200U_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() monitorEC200UInfo(exitCh1) }() isRunning1 = true return isRunning1 } // 4G调制解调器退出 func ModuleExit() { mu1.Lock() defer mu1.Unlock() if !isRunning1 { return } close(exitCh1) wg1.Wait() // 等待循环读取4G模块的信号强度和ICCID号等信息的携程退出 ec200U_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 monitorEC200UInfo(exitCh <-chan struct{}) { t := time.NewTicker(time.Duration(5) * time.Second) defer t.Stop() for { select { case <-t.C: mu2.Lock() rssi, _ = ec200U_GetRSSIFromCSQ() if bOK, _ := ec200U_IsSimCardReady(); bOK { iccid, _ = ec200U_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, _ := udhcpcUSB0Exists() if bExists { killUSB0Udhcpc() } err = dialupUSB0() if err != nil { baseapp.Logger.Errorf("[%s] 拨号连接\"eth2\"时发生错误: %v!!", MODULE_NAME, err) return false } ipv4, mask, err := getUSB0Addr() 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() monitorUSB0Udhcpc(exitCh2) }() isRunning2 = true return isRunning2 } // 从4G网络断开连接 func Stop4GNetwork() { mu3.Lock() defer mu3.Unlock() if !isRunning2 { return } close(exitCh2) wg2.Wait() // 等待守护"eth2"网卡上的 "udhcpc"后台服务进程的携程退出 bExists, _ := udhcpcUSB0Exists() if bExists { killUSB0Udhcpc() } isRunning2 = false }