air720u.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. // Author: NiuJiuRu
  2. // Email: niujiuru@qq.com
  3. package air720u
  4. import (
  5. "os"
  6. "sync"
  7. "time"
  8. "hnyfkj.com.cn/rtu/linux/baseapp"
  9. )
  10. const MODULE_NAME = "Air720U"
  11. var (
  12. imei string // Air720U模块的IMEI号, 唯一标识
  13. rssi string // Air720U模块当前信号强度(RSSI)
  14. iccid string // Air720U模块插入SIM卡的ICCID号
  15. mu sync.Mutex
  16. isRunning bool
  17. healthCheckExitCh chan struct{}
  18. wg sync.WaitGroup
  19. )
  20. // 初始化4G网络模块
  21. func ModuleInit(bForceRepower bool /*是否强制重启*/) bool {
  22. mu.Lock()
  23. defer mu.Unlock()
  24. if isRunning {
  25. return true
  26. }
  27. var err error
  28. var ret int
  29. var bExists bool
  30. killAllUdhcpc()
  31. err = disableEthBut2()
  32. if err != nil {
  33. baseapp.Logger.Errorf("[%s] 错误: %v!!", MODULE_NAME, err)
  34. return false
  35. }
  36. bExists, _ = udhcpcEth2Exists()
  37. if bExists {
  38. killEth2Udhcpc()
  39. }
  40. _, statErr := os.Stat("/dev/ttyUSB0")
  41. bExists = (statErr == nil)
  42. if bExists && !bForceRepower {
  43. ret, err = air720U_ComInit()
  44. if err == nil {
  45. goto initOK
  46. }
  47. switch ret {
  48. case -1: // 串口被占用(或不存在, 这里只能是被占用的情况)
  49. freeTTYUSB0()
  50. case -3: // 设备无应答(初始化时会发送一条关闭回显的指令)
  51. air720U_Repower() // 重新上电
  52. bExists = false // 等待复位, 标记设备已不存在
  53. }
  54. } else { // 设备不存在或函数调用明确要求强制模块重新启动时
  55. air720U_Repower() //// 重新上电
  56. bExists = false //// 等待复位, 标记设备已不存在
  57. }
  58. for range 6 {
  59. if baseapp.IsExit1() {
  60. air720U_ComExit()
  61. return false
  62. }
  63. if !bExists {
  64. time.Sleep(5 * time.Second) // 等待设备文件再次出现
  65. }
  66. ret, err = air720U_ComInit()
  67. if err != nil && ret == -1 && !bExists { // 继续等待
  68. continue
  69. }
  70. break
  71. }
  72. if err != nil {
  73. air720U_ComExit()
  74. baseapp.Logger.Errorf("[%s] 错误: %v!!", MODULE_NAME, err)
  75. return false
  76. }
  77. initOK:
  78. imei, err = air720U_GetIMEI()
  79. if err != nil {
  80. air720U_ComExit()
  81. baseapp.Logger.Errorf("[%s] 错误: %v!!", MODULE_NAME, err)
  82. return false
  83. }
  84. baseapp.Logger.Infof("[%s] 模块IMEI: %s", MODULE_NAME, imei)
  85. for range 30 { // 等待模块完成蜂窝网络注册, 否则RSSI读取不到, 网也不可能不去
  86. if baseapp.IsExit1() {
  87. air720U_ComExit()
  88. return false
  89. }
  90. cs, err := air720U_GetCregState()
  91. if err != nil || cs == 1 /*已注册本地网*/ || cs == 5 /*已注册漫游网*/ {
  92. break
  93. }
  94. time.Sleep(1 * time.Second)
  95. }
  96. rssi, err = air720U_GetRSSIFromCSQ()
  97. if err != nil {
  98. air720U_ComExit()
  99. baseapp.Logger.Errorf("[%s] 错误: %v!!", MODULE_NAME, err)
  100. return false
  101. }
  102. baseapp.Logger.Infof("[%s] 模块RSSI: %s", MODULE_NAME, rssi)
  103. bOK, err := air720U_IsSimCardReady()
  104. if err != nil {
  105. air720U_ComExit()
  106. baseapp.Logger.Errorf("[%s] 错误: %v!!", MODULE_NAME, err)
  107. return false
  108. }
  109. baseapp.Logger.Infof("[%s] SIM卡状态: %v", MODULE_NAME, bOK)
  110. if !bOK {
  111. return false
  112. }
  113. iccid, err = air720U_GetSimICCID()
  114. if err != nil {
  115. air720U_ComExit()
  116. baseapp.Logger.Errorf("[%s] 错误: %v!!", MODULE_NAME, err)
  117. return false
  118. }
  119. baseapp.Logger.Infof("[%s] SIM卡ICCID: %s", MODULE_NAME, iccid)
  120. err = dialupEth2()
  121. if err != nil {
  122. baseapp.Logger.Errorf("[%s] 拨号连接\"eth2\"时发生错误: %v!!", MODULE_NAME, err)
  123. return false
  124. }
  125. ipv4, mask, err := getEth2Addr()
  126. if err != nil {
  127. baseapp.Logger.Errorf("[%s] 读取\"eth2\"地址时发生错误: %v!!", MODULE_NAME, err)
  128. return false
  129. }
  130. baseapp.Logger.Infof("[%s] \"eth2\"分配的地址: %s/%s", MODULE_NAME, ipv4, mask)
  131. healthCheckExitCh = make(chan struct{})
  132. wg.Add(1)
  133. go func() { // 启动携程守护"eth2"网卡上的"udhcpc"后台服务进程
  134. defer wg.Done()
  135. monitorEth2Udhcpc(healthCheckExitCh)
  136. }()
  137. wg.Add(1)
  138. go func() { // 启动携程循环读取4G模块的信号强度和ICCID号等信息
  139. defer wg.Done()
  140. monitorAir720UInfo(healthCheckExitCh)
  141. }()
  142. isRunning = true
  143. return isRunning
  144. }
  145. // 4G调制解调器退出
  146. func ModuleExit() {
  147. mu.Lock()
  148. defer mu.Unlock()
  149. if !isRunning {
  150. return
  151. }
  152. close(healthCheckExitCh)
  153. wg.Wait() // 等待守护"udhcpc"的携程退出
  154. bExists, _ := udhcpcEth2Exists()
  155. if bExists {
  156. killEth2Udhcpc()
  157. }
  158. air720U_ComExit()
  159. imei, rssi, iccid = "", "", ""
  160. isRunning = false
  161. }
  162. // 获取模块的标识号
  163. func GetIMEI() string {
  164. mu.Lock()
  165. defer mu.Unlock()
  166. return imei
  167. }
  168. // 获取当前信号强度
  169. func GetRSSI() string {
  170. mu.Lock()
  171. defer mu.Unlock()
  172. return rssi
  173. }
  174. // 获取电话卡标识号
  175. func GetSimICCID() string {
  176. mu.Lock()
  177. defer mu.Unlock()
  178. return iccid
  179. }
  180. // 间隔读取刷新信息
  181. func monitorAir720UInfo(exitCh <-chan struct{}) {
  182. t := time.NewTicker(time.Duration(5) * time.Second)
  183. defer t.Stop()
  184. for {
  185. select {
  186. case <-t.C:
  187. mu.Lock()
  188. rssi, _ = air720U_GetRSSIFromCSQ()
  189. if bOK, _ := air720U_IsSimCardReady(); bOK {
  190. iccid, _ = air720U_GetSimICCID()
  191. } else {
  192. iccid = ""
  193. }
  194. mu.Unlock()
  195. case <-exitCh:
  196. return
  197. } // select end
  198. } // for end
  199. }