air720u.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  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. mu1, mu2, mu3 sync.Mutex
  16. isRunning1, isRunning2 bool
  17. exitCh1, exitCh2 chan struct{}
  18. wg1, wg2 sync.WaitGroup
  19. )
  20. // 初始化4G网络模块
  21. func ModuleInit(bForceRepower bool /*是否强制重启*/) bool {
  22. mu1.Lock()
  23. defer mu1.Unlock()
  24. if isRunning1 {
  25. return true
  26. }
  27. var err error
  28. var ret int
  29. var bExists, bReady bool
  30. _, statErr := os.Stat("/dev/ttyUSB0")
  31. bExists = (statErr == nil)
  32. if bExists && !bForceRepower {
  33. ret, err = air720U_ComInit()
  34. if err == nil {
  35. goto openOK
  36. }
  37. switch ret {
  38. case -1, -3: // -1: 串口被占用或不存在(驱动有问题时)
  39. // -3: 设备无应答(初始化时会发送的两条关键配置指令)
  40. if ret == -1 {
  41. freeTTYUSB0()
  42. }
  43. air720U_Repower() // 重新上电
  44. bExists = false // 等待复位, 标记设备已不存在
  45. }
  46. } else { // 设备不存在, 或调用该函数时明确要求强制重启/
  47. air720U_Repower() //// 重新上电
  48. bExists = false //// 等待复位, 标记设备已不存在
  49. }
  50. for range 6 {
  51. if baseapp.IsExit1() {
  52. air720U_ComExit()
  53. return false
  54. }
  55. if !bExists {
  56. time.Sleep(5 * time.Second) // 等待设备文件再次出现
  57. }
  58. ret, err = air720U_ComInit()
  59. if err != nil && ret == -1 && !bExists { // 继续等待
  60. continue
  61. }
  62. break
  63. }
  64. if err != nil {
  65. air720U_ComExit()
  66. baseapp.Logger.Errorf("[%s] 错误: %v!!", MODULE_NAME, err)
  67. return false
  68. }
  69. openOK:
  70. imei, err = air720U_GetIMEI()
  71. if err != nil {
  72. air720U_ComExit()
  73. baseapp.Logger.Errorf("[%s] 错误: %v!!", MODULE_NAME, err)
  74. return false
  75. }
  76. baseapp.Logger.Infof("[%s] 模块IMEI: %s", MODULE_NAME, imei)
  77. for range 30 { // 等待模块完成蜂窝网络注册, 否则RSSI读取不到, 网也不可能不去
  78. if baseapp.IsExit1() {
  79. air720U_ComExit()
  80. return false
  81. }
  82. cs, err := air720U_GetCregState()
  83. if err != nil || cs == 1 /*已注册本地网*/ || cs == 5 /*已注册漫游网*/ {
  84. break
  85. }
  86. time.Sleep(1 * time.Second)
  87. }
  88. rssi, err = air720U_GetRSSIFromCSQ()
  89. if err != nil {
  90. air720U_ComExit()
  91. baseapp.Logger.Errorf("[%s] 错误: %v!!", MODULE_NAME, err)
  92. return false
  93. }
  94. baseapp.Logger.Infof("[%s] 模块RSSI: %s", MODULE_NAME, rssi)
  95. bReady, err = air720U_IsSimCardReady()
  96. if err != nil {
  97. air720U_ComExit()
  98. baseapp.Logger.Errorf("[%s] 错误: %v!!", MODULE_NAME, err)
  99. return false
  100. }
  101. baseapp.Logger.Infof("[%s] SIM卡状态: %v", MODULE_NAME, bReady)
  102. if !bReady { // 未插入SIM卡, 也不影响初始化成功, 可等待之后的热插入
  103. goto initOK
  104. }
  105. iccid, err = air720U_GetSimICCID()
  106. if err != nil {
  107. air720U_ComExit()
  108. baseapp.Logger.Errorf("[%s] 错误: %v!!", MODULE_NAME, err)
  109. return false
  110. }
  111. baseapp.Logger.Infof("[%s] SIM卡ICCID: %s", MODULE_NAME, iccid)
  112. initOK:
  113. exitCh1 = make(chan struct{})
  114. wg1.Add(1)
  115. go func() { // 启动携程循环读取4G模块的信号强度和ICCID号等信息
  116. defer wg1.Done()
  117. monitorAir720uInfo(exitCh1)
  118. }()
  119. isRunning1 = true
  120. return isRunning1
  121. }
  122. // 4G调制解调器退出
  123. func ModuleExit() {
  124. mu1.Lock()
  125. defer mu1.Unlock()
  126. if !isRunning1 {
  127. return
  128. }
  129. close(exitCh1)
  130. wg1.Wait() // 等待循环读取4G模块的信号强度和ICCID号等信息的携程退出
  131. air720U_ComExit()
  132. imei, rssi, iccid = "", "", ""
  133. isRunning1 = false
  134. }
  135. // 获取模块的标识号
  136. func GetIMEI() string {
  137. mu2.Lock()
  138. defer mu2.Unlock()
  139. return imei
  140. }
  141. // 获取当前信号强度
  142. func GetRSSI() string {
  143. mu2.Lock()
  144. defer mu2.Unlock()
  145. return rssi
  146. }
  147. // 获取电话卡标识号
  148. func GetSimICCID() string {
  149. mu2.Lock()
  150. defer mu2.Unlock()
  151. return iccid
  152. }
  153. // 循环读取刷新信息
  154. func monitorAir720uInfo(exitCh <-chan struct{}) {
  155. t := time.NewTicker(time.Duration(5) * time.Second)
  156. defer t.Stop()
  157. for {
  158. select {
  159. case <-t.C:
  160. mu2.Lock()
  161. rssi, _ = air720U_GetRSSIFromCSQ()
  162. if bOK, _ := air720U_IsSimCardReady(); bOK {
  163. iccid, _ = air720U_GetSimICCID()
  164. } else {
  165. iccid = ""
  166. }
  167. mu2.Unlock()
  168. case <-exitCh:
  169. return
  170. } // select end
  171. } // for end
  172. }
  173. // 打开连接到4G网络
  174. func Start4GNetwork() bool {
  175. mu3.Lock()
  176. defer mu3.Unlock()
  177. if isRunning2 {
  178. return true
  179. }
  180. killAllUdhcpc()
  181. err := disableEth0()
  182. if err != nil {
  183. baseapp.Logger.Errorf("[%s] 错误: %v!!", MODULE_NAME, err)
  184. return false
  185. }
  186. bExists, _ := udhcpcEth2Exists()
  187. if bExists {
  188. killEth2Udhcpc()
  189. }
  190. err = dialupEth2()
  191. if err != nil {
  192. baseapp.Logger.Errorf("[%s] 拨号连接\"eth2\"时发生错误: %v!!", MODULE_NAME, err)
  193. return false
  194. }
  195. ipv4, mask, err := getEth2Addr()
  196. if err != nil {
  197. baseapp.Logger.Errorf("[%s] 读取\"eth2\"地址时发生错误: %v!!", MODULE_NAME, err)
  198. return false
  199. }
  200. baseapp.Logger.Infof("[%s] \"eth2\"分配的地址: %s/%s", MODULE_NAME, ipv4, mask)
  201. exitCh2 = make(chan struct{})
  202. wg2.Add(1)
  203. go func() { // 启动携程守护"eth2"网卡上的 "udhcpc"后台服务进程
  204. defer wg2.Done()
  205. monitorEth2Udhcpc(exitCh2)
  206. }()
  207. isRunning2 = true
  208. return isRunning2
  209. }
  210. // 从4G网络断开连接
  211. func Stop4GNetwork() {
  212. mu3.Lock()
  213. defer mu3.Unlock()
  214. if !isRunning2 {
  215. return
  216. }
  217. close(exitCh2)
  218. wg2.Wait() // 等待守护"eth2"网卡上的 "udhcpc"后台服务进程的携程退出
  219. bExists, _ := udhcpcEth2Exists()
  220. if bExists {
  221. killEth2Udhcpc()
  222. }
  223. isRunning2 = false
  224. }