gwhandler.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. package main
  2. import (
  3. "io/ioutil"
  4. "os"
  5. "path/filepath"
  6. "runtime"
  7. "runtime/debug"
  8. "sync"
  9. "time"
  10. "github.com/sirupsen/logrus"
  11. "lc/common/models"
  12. "lc/common/mqtt"
  13. "lc/common/protocol"
  14. "lc/common/util"
  15. )
  16. var _gwHandlerOnce sync.Once
  17. var _gwHandlerSingle *GwHandler
  18. func GetGwHandler() *GwHandler {
  19. _gwHandlerOnce.Do(func() {
  20. _gwHandlerSingle = &GwHandler{
  21. queue: util.NewQueue(10000),
  22. }
  23. })
  24. return _gwHandlerSingle
  25. }
  26. type GwHandler struct {
  27. queue *util.MlQueue
  28. }
  29. func (o *GwHandler) SubscribeTopics() {
  30. GetMQTTMgr().Subscribe(GetVagueTopic(protocol.DT_GATEWAY, protocol.TP_GW_ONLINE), mqtt.AtMostOnce, o.HandlerData)
  31. GetMQTTMgr().Subscribe(GetVagueTopic(protocol.DT_GATEWAY, protocol.TP_GW_WILL), mqtt.AtMostOnce, o.HandlerData)
  32. GetMQTTMgr().Subscribe(GetVagueTopic(protocol.DT_GATEWAY, protocol.TP_GW_APP_ACK), mqtt.AtMostOnce, o.HandlerData)
  33. GetMQTTMgr().Subscribe(GetVagueTopic(protocol.DT_GATEWAY, protocol.TP_GW_SET_APP_ACK), mqtt.AtMostOnce, o.HandlerData)
  34. GetMQTTMgr().Subscribe(GetVagueTopic(protocol.DT_GATEWAY, protocol.TP_GW_SERIAL_ACK), mqtt.AtMostOnce, o.HandlerData)
  35. GetMQTTMgr().Subscribe(GetVagueTopic(protocol.DT_GATEWAY, protocol.TP_GW_SET_SERIAL_ACK), mqtt.AtMostOnce, o.HandlerData)
  36. GetMQTTMgr().Subscribe(GetVagueTopic(protocol.DT_GATEWAY, protocol.TP_GW_RTU_ACK), mqtt.AtMostOnce, o.HandlerData)
  37. GetMQTTMgr().Subscribe(GetVagueTopic(protocol.DT_GATEWAY, protocol.TP_GW_SET_RTU_ACK), mqtt.AtMostOnce, o.HandlerData)
  38. GetMQTTMgr().Subscribe(GetVagueTopic(protocol.DT_GATEWAY, protocol.TP_GW_MODEL_ACK), mqtt.AtMostOnce, o.HandlerData)
  39. GetMQTTMgr().Subscribe(GetVagueTopic(protocol.DT_GATEWAY, protocol.TP_GW_SET_MODEL_ACK), mqtt.AtMostOnce, o.HandlerData)
  40. GetMQTTMgr().Subscribe(GetVagueTopic(protocol.DT_GATEWAY, protocol.TP_GW_LOG_ACK), mqtt.AtMostOnce, o.HandlerData)
  41. GetMQTTMgr().Subscribe(GetVagueTopic(protocol.DT_GATEWAY, protocol.TP_GW_REMOVE_LOG_ACK), mqtt.AtMostOnce, o.HandlerData)
  42. GetMQTTMgr().Subscribe(GetVagueTopic(protocol.DT_GATEWAY, protocol.TP_GW_SYS_ACK), mqtt.AtMostOnce, o.HandlerData)
  43. GetMQTTMgr().Subscribe(GetVagueTopic(protocol.DT_GATEWAY, protocol.TP_GW_ITS_ACK), mqtt.AtMostOnce, o.HandlerData)
  44. GetMQTTMgr().Subscribe(GetVagueTopic(protocol.DT_GATEWAY, protocol.TP_GW_ONVIFDEV_ACK), mqtt.AtMostOnce, o.HandlerData)
  45. }
  46. func (o *GwHandler) HandlerData(m mqtt.Message) {
  47. for {
  48. ok, cnt := o.queue.Put(&m)
  49. if ok {
  50. break
  51. } else {
  52. logrus.Errorf("GwHandler.HandlerData:查询队列失败,队列消息数量:%d", cnt)
  53. runtime.Gosched()
  54. }
  55. }
  56. }
  57. func (o *GwHandler) Handler(args ...interface{}) interface{} {
  58. defer func() {
  59. if err := recover(); err != nil {
  60. time.Sleep(time.Second)
  61. gopool.Add(o.Handler, args)
  62. logrus.Errorf("GwHandler.Handler:%v发生异常:%s", args, string(debug.Stack()))
  63. }
  64. }()
  65. for {
  66. msg, ok, quantity := o.queue.Get()
  67. if !ok {
  68. time.Sleep(10 * time.Millisecond)
  69. continue
  70. } else if quantity > 1000 {
  71. logrus.Warnf("数据队列累积过多,请注意优化,当前队列条数:%d", quantity)
  72. }
  73. m, ok := msg.(*mqtt.Message)
  74. if !ok {
  75. continue
  76. }
  77. Tenant, _, GID, topic, err := ParseTopic(m.Topic())
  78. if err != nil {
  79. continue
  80. }
  81. switch topic {
  82. case protocol.TP_GW_ONLINE: //上线
  83. var obj protocol.Pack_IDObject
  84. if err := obj.DeCode(m.PayloadString()); err == nil { //网关在线
  85. cacheState(obj.Id, obj.Time, 0)
  86. GetEventMgr().PushEvent(&EventObject{ID: obj.Id, EventType: models.ET_ONLINE, Time: util.MlNow()})
  87. }
  88. case protocol.TP_GW_WILL: //下线
  89. var obj protocol.Pack_IDObject
  90. if err := obj.DeCode(m.PayloadString()); err == nil { //网关离线
  91. cacheState(obj.Id, obj.Time, 1)
  92. GetEventMgr().PushEvent(&EventObject{ID: obj.Id, EventType: models.ET_OFFLINE, Time: util.MlNow()})
  93. }
  94. case protocol.TP_GW_SET_APP_ACK, protocol.TP_GW_SET_MODEL_ACK, protocol.TP_GW_SET_RTU_ACK, protocol.TP_GW_SET_SERIAL_ACK, protocol.TP_GW_REMOVE_LOG_ACK:
  95. var obj protocol.Pack_Ack
  96. if err := obj.DeCode(m.PayloadString()); err == nil {
  97. o := models.DeviceCmdRecord{
  98. ID: obj.Seq,
  99. State: 1,
  100. Resp: obj.Data.Error,
  101. }
  102. if err := o.Update(); err != nil {
  103. logrus.Errorf("收到网关[%s]的响应[seq:%d],主题:%s,但更新数据库失败[%s]",
  104. obj.Id, obj.Seq, m.Topic(), err.Error())
  105. }
  106. }
  107. case protocol.TP_GW_APP:
  108. var ret protocol.Pack_MutilFileObject
  109. if err := ret.DeCode(m.PayloadString()); err == nil && len(ret.Data.Files) == 1 {
  110. SaveFile(Tenant, GID, "conf", ret.Data.Files)
  111. var obj protocol.AppConfig
  112. if err := json.UnmarshalFromString(ret.Data.Files[0].Content, &obj); err == nil {
  113. o := models.Gateway{
  114. ID: ret.Id,
  115. Name: obj.Name,
  116. Tenant: obj.Tenant,
  117. Sn: obj.SN,
  118. Upgrade: obj.Upgrade,
  119. MqttEdgeServer: obj.Edge.Mqtt.Server,
  120. MqttEdgeUser: obj.Edge.Mqtt.User,
  121. MqttEdgePassword: obj.Edge.Mqtt.Password,
  122. MqttCloudServer: obj.Cloud.Mqtt.Server,
  123. MqttCloudUser: obj.Cloud.Mqtt.User,
  124. MqttCloudPassword: obj.Cloud.Mqtt.Password,
  125. State: 1,
  126. }
  127. if err := o.SaveFromGateway(); err != nil {
  128. logrus.Errorf("插入数据库失败:%s", err.Error())
  129. }
  130. }
  131. }
  132. case protocol.TP_GW_SERIAL_ACK:
  133. var ret protocol.Pack_MutilFileObject
  134. if err := ret.DeCode(m.PayloadString()); err == nil && len(ret.Data.Files) == 1 {
  135. SaveFile(Tenant, GID, "conf", ret.Data.Files)
  136. var obj protocol.SerialConfig
  137. if err := json.UnmarshalFromString(ret.Data.Files[0].Content, &obj); err == nil {
  138. for _, v := range obj.Serial {
  139. o := models.GatewaySerial{
  140. ID: ret.Id,
  141. ComID: int(v.Code),
  142. Interface: v.Interface,
  143. Address: v.Address,
  144. BaudRate: v.BaudRate,
  145. DataBits: int(v.DataBits),
  146. StopBits: int(v.StopBits),
  147. Parity: v.Parity,
  148. Timeout: int(v.Timeout),
  149. ProtocolType: int(v.ProtocolType),
  150. }
  151. if err := models.G_db.Save(&o).Error; err != nil {
  152. logrus.Errorf("插入数据库失败:%s", err.Error())
  153. }
  154. }
  155. }
  156. }
  157. case protocol.TP_GW_RTU_ACK:
  158. var ret protocol.Pack_MutilFileObject
  159. if err := ret.DeCode(m.PayloadString()); err == nil {
  160. SaveFile(Tenant, GID, "dev", ret.Data.Files)
  161. for _, v := range ret.Data.Files {
  162. var obj protocol.MapDevConfig
  163. if err := json.UnmarshalFromString(v.Content, &obj); err == nil {
  164. for _, v1 := range obj.Rtu {
  165. o := models.GatewayDevice{
  166. ID: v1.DevCode,
  167. Name: v1.Name,
  168. GID: ret.Id,
  169. ComID: int(v1.Code),
  170. RtuID: int(v1.DevID),
  171. TID: int(v1.TID),
  172. SendCloud: v1.SendCloud,
  173. WaitTime: int(v1.WaitTime),
  174. ProtocolType: int(v1.ProtocolType),
  175. DevType: int(v1.DevType),
  176. Tenant: Tenant,
  177. State: 1,
  178. }
  179. if err := o.SaveFromGateway(); err != nil {
  180. logrus.Errorf("插入数据库失败:%s", err.Error())
  181. }
  182. //设备类型,1-灯控类设备 2-环境监测类设备 3-裕明485单灯控制器 4-液位计 5-路面状况传感器
  183. if v1.DevType == 4 || v1.DevType == 5 {
  184. if err := models.UpdateDeviceSensorTID(v1.DevCode, int(v1.TID)); err != nil {
  185. logrus.Errorf("更新传感器物模型失败:%s", err.Error())
  186. }
  187. } else if v1.DevType == 2 { //环境监测设备
  188. if err := models.UpdateDeviceEnvironmentTID(v1.DevCode, int(v1.TID)); err != nil {
  189. logrus.Errorf("更新环境传感器物模型失败:%s", err.Error())
  190. }
  191. } else if v1.DevType == 3 { //裕明单灯控制器
  192. if err := models.UpdateDeviceLampControllerTID(v1.DevCode, int(v1.TID)); err != nil {
  193. logrus.Errorf("更新灯控物模型失败:%s", err.Error())
  194. }
  195. } else if v1.DevType == 1 { //集控器
  196. if err := models.UpdateTID(v1.DevCode, int(v1.TID)); err != nil {
  197. logrus.Errorf("更新单灯集控器物模型失败:%s", err.Error())
  198. }
  199. }
  200. }
  201. }
  202. }
  203. }
  204. case protocol.TP_GW_MODEL_ACK:
  205. var ret protocol.Pack_MutilFileObject
  206. if err := ret.DeCode(m.PayloadString()); err == nil {
  207. SaveFile(Tenant, GID, "model", ret.Data.Files)
  208. }
  209. case protocol.TP_GW_LOG_ACK:
  210. var ret protocol.Pack_MutilFileObject
  211. if err := ret.DeCode(m.PayloadString()); err == nil {
  212. SaveFile(Tenant, GID, "log", ret.Data.Files)
  213. }
  214. case protocol.TP_GW_SYS_ACK:
  215. var ret protocol.Pack_SysInfo
  216. if err := ret.DeCode(m.PayloadString()); err == nil {
  217. o := models.GatewaySysInfo{
  218. GID: GID,
  219. AppName: ret.Data.Appinfo.Name,
  220. AppVersion: ret.Data.Appinfo.Version,
  221. CpuCnt: ret.Data.Cpuinfo.Cpus,
  222. CpuCores: ret.Data.Cpuinfo.Cores,
  223. CpuModelName: ret.Data.Cpuinfo.ModelName,
  224. CpuPercent: ret.Data.Cpuinfo.Percent,
  225. MemTotal: ret.Data.Meminfo.Total,
  226. MemAvailable: ret.Data.Meminfo.Available,
  227. MemUsed: ret.Data.Meminfo.Used,
  228. MemPercent: ret.Data.Meminfo.Percent,
  229. }
  230. if str, err := json.MarshalIndent(&ret.Data.Diskinfos, "", " "); err == nil {
  231. o.DiskInfos = string(str)
  232. }
  233. if str, err := json.MarshalIndent(&ret.Data.Ifs, "", " "); err == nil {
  234. o.NetIfs = string(str)
  235. }
  236. if str, err := json.MarshalIndent(&ret.Data.Pis, "", " "); err == nil {
  237. o.Process = string(str)
  238. }
  239. if str, err := json.MarshalIndent(&ret.Data.TcpListen, "", " "); err == nil {
  240. o.TcpListen = string(str)
  241. }
  242. if str, err := json.MarshalIndent(&ret.Data.TcpConn, "", " "); err == nil {
  243. o.TcpConn = string(str)
  244. }
  245. if str, err := json.MarshalIndent(&ret.Data.Udp, "", " "); err == nil {
  246. o.Udp = string(str)
  247. }
  248. if err := models.G_db.Save(&o).Error; err != nil {
  249. logrus.Errorf("插入数据库失败:%s", err.Error())
  250. }
  251. }
  252. case protocol.TP_GW_ITS_ACK:
  253. var ret protocol.Pack_ITSDev
  254. if err := ret.DeCode(m.PayloadString()); err == nil {
  255. for _, v := range ret.Data.Its {
  256. o := models.ItsDevice{
  257. ID: v.ID,
  258. Name: v.Name,
  259. GID: ret.Gid,
  260. Brand: v.Brand,
  261. Model: v.Model,
  262. DevType: v.DevType,
  263. User: v.User,
  264. Password: v.Password,
  265. IP: v.IP,
  266. Port: v.Port,
  267. HttpAddr: ret.Data.IPAddr,
  268. SuggestSpeed: int(ret.Data.SuggestSpeed),
  269. Duration: ret.Data.Duration,
  270. EnvID: ret.Data.EnvID,
  271. TollgateID: v.TollgateID,
  272. Tenant: Tenant,
  273. State: 1,
  274. }
  275. if err := o.SaveFromGateway(); err != nil {
  276. logrus.Errorf("抓拍单元数据入库失败:%s", err.Error())
  277. logrus.Errorf("抓拍单元数据入库失败:%v", o)
  278. }
  279. }
  280. }
  281. case protocol.TP_GW_ONVIFDEV_ACK:
  282. var ret protocol.Pack_OnvifDev
  283. if err := ret.DeCode(m.PayloadString()); err == nil {
  284. for _, v := range ret.Data {
  285. o := models.CameraDevice{
  286. ID: v.Code,
  287. Name: v.Name,
  288. GID: ret.Id,
  289. IP: v.IP,
  290. SN: v.SN,
  291. Brand: v.Brand,
  292. Model: v.Model,
  293. DevType: v.DevType,
  294. User: v.User,
  295. Password: v.Password,
  296. RtmpServer: v.RtmpServer,
  297. WebServer: v.WebServer,
  298. Event: v.Event,
  299. Gb28181: v.Gb28181,
  300. State: 1,
  301. }
  302. if err := o.SaveFromGateway(); err != nil {
  303. logrus.Errorf("摄像头数据入库失败:%s", err.Error())
  304. logrus.Errorf("摄像头数据入库失败:%v", o)
  305. }
  306. }
  307. }
  308. default:
  309. logrus.Warnf("GwHandler.Handler:收到暂不支持的主题:%s", topic)
  310. }
  311. }
  312. }
  313. func SaveFile(tenant, GID, strType string, fo []protocol.FileObject) {
  314. Dir := tenant + string(filepath.Separator) + GID + string(filepath.Separator) + strType + string(filepath.Separator)
  315. err := os.MkdirAll(Dir, os.ModePerm)
  316. if err != nil {
  317. return
  318. }
  319. for _, v := range fo {
  320. if err := ioutil.WriteFile(Dir+v.File, []byte(v.Content), os.ModePerm); err != nil {
  321. logrus.Errorf("SaveFile:保存模型文件失败,文件名:%s,原因:%s", Dir+v.File, err.Error())
  322. }
  323. }
  324. }