TrafficDemo.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. # coding=utf-8
  2. import sys
  3. from PyQt5.QtWidgets import QMainWindow, QApplication, QTableWidgetItem, QMessageBox
  4. from PyQt5.QtCore import Qt
  5. from PyQt5.QtGui import QPixmap
  6. from PyQt5.QtCore import QThread, pyqtSignal
  7. from IntelligentTrafficUI import Ui_MainWindow
  8. from NetSDK.NetSDK import NetClient
  9. from NetSDK.SDK_Struct import *
  10. from NetSDK.SDK_Enum import *
  11. from NetSDK.SDK_Callback import *
  12. import time
  13. from queue import Queue
  14. global wnd
  15. callback_num = 0
  16. class TrafficCallBackAlarmInfo:
  17. def __init__(self):
  18. self.time_str = ""
  19. self.plate_number_str = ""
  20. self.plate_color_str = ""
  21. self.object_subType_str = ""
  22. self.vehicle_color_str = ""
  23. def get_alarm_info(self, alarm_info):
  24. self.time_str = '{}-{}-{} {}:{}:{}'.format(alarm_info.UTC.dwYear, alarm_info.UTC.dwMonth, alarm_info.UTC.dwDay,
  25. alarm_info.UTC.dwHour, alarm_info.UTC.dwMinute,
  26. alarm_info.UTC.dwSecond)
  27. self.plate_number_str = str(alarm_info.stTrafficCar.szPlateNumber.decode('gb2312'))
  28. self.plate_color_str = str(alarm_info.stTrafficCar.szPlateColor, 'utf-8')
  29. self.object_subType_str = str(alarm_info.stuVehicle.szObjectSubType, 'utf-8')
  30. self.vehicle_color_str = str(alarm_info.stTrafficCar.szVehicleColor, 'utf-8')
  31. class BackUpdateUIThread(QThread):
  32. # 通过类成员对象定义信号
  33. update_date = pyqtSignal(int, object, int, bool, bool)
  34. # 处理业务逻辑
  35. def run(self):
  36. pass
  37. @CB_FUNCTYPE(None, C_LLONG, C_DWORD, c_void_p, POINTER(c_ubyte), C_DWORD, C_LDWORD, c_int, c_void_p)
  38. def AnalyzerDataCallBack(lAnalyzerHandle, dwAlarmType, pAlarmInfo, pBuffer, dwBufSize, dwUser, nSequence, reserved):
  39. print('Enter AnalyzerDataCallBack')
  40. # 当报警类型是交通卡口事件时在界面上进行显示相关信息
  41. if (lAnalyzerHandle == wnd.attachID) and (dwAlarmType == EM_EVENT_IVS_TYPE.TRAFFICJUNCTION):
  42. global callback_num
  43. local_path = os.path.abspath('.')
  44. is_global = False
  45. is_small = False
  46. show_info = TrafficCallBackAlarmInfo()
  47. callback_num += 1
  48. alarm_info = cast(pAlarmInfo, POINTER(DEV_EVENT_TRAFFICJUNCTION_INFO)).contents
  49. show_info.get_alarm_info(alarm_info)
  50. if alarm_info.stuObject.bPicEnble:
  51. is_global = True
  52. GlobalScene_buf = cast(pBuffer, POINTER(c_ubyte * alarm_info.stuObject.stPicInfo.dwOffSet)).contents
  53. if not os.path.isdir(os.path.join(local_path, 'Global')):
  54. os.mkdir(os.path.join(local_path, 'Global'))
  55. with open('./Global/Global_Img' + str(callback_num) + '.jpg', 'wb+') as global_pic:
  56. global_pic.write(bytes(GlobalScene_buf))
  57. if (alarm_info.stuObject.stPicInfo.dwFileLenth > 0):
  58. is_small = True
  59. small_buf = pBuffer[alarm_info.stuObject.stPicInfo.dwOffSet:alarm_info.stuObject.stPicInfo.dwOffSet +
  60. alarm_info.stuObject.stPicInfo.dwFileLenth]
  61. if not os.path.isdir(os.path.join(local_path, 'Small')):
  62. os.mkdir(os.path.join(local_path, 'Small'))
  63. with open('./Small/Small_Img' + str(callback_num) + '.jpg', 'wb+') as small_pic:
  64. small_pic.write(bytes(small_buf))
  65. elif (dwBufSize > 0):
  66. is_global = True
  67. GlobalScene_buf = cast(pBuffer, POINTER(c_ubyte * dwBufSize)).contents
  68. if not os.path.isdir(os.path.join(local_path, 'Global')):
  69. os.mkdir(os.path.join(local_path, 'Global'))
  70. with open('./Global/Global_Img' + str(callback_num) + '.jpg', 'wb+') as global_pic:
  71. global_pic.write(bytes(GlobalScene_buf))
  72. wnd.backthread.update_date.emit(dwAlarmType, show_info, callback_num, is_global, is_small)
  73. return
  74. class TrafficWnd(QMainWindow, Ui_MainWindow):
  75. def __init__(self, parent=None):
  76. super(TrafficWnd, self).__init__(parent)
  77. self.setupUi(self)
  78. # 界面初始化
  79. self._init_ui()
  80. # NetSDK用到的相关变量和回调
  81. self.loginID = C_LLONG()
  82. self.playID = C_LLONG()
  83. self.freePort = c_int()
  84. self.attachID = C_LLONG()
  85. self.m_DisConnectCallBack = fDisConnect(self.DisConnectCallBack)
  86. self.m_ReConnectCallBack = fHaveReConnect(self.ReConnectCallBack)
  87. self.m_DecodingCallBack = fDecCBFun(self.DecodingCallBack)
  88. self.m_RealDataCallBack = fRealDataCallBackEx2(self.RealDataCallBack)
  89. # 获取NetSDK对象并初始化
  90. self.sdk = NetClient()
  91. self.sdk.InitEx(self.m_DisConnectCallBack)
  92. self.sdk.SetAutoReconnect(self.m_ReConnectCallBack)
  93. # 创建线程
  94. self.backthread = BackUpdateUIThread()
  95. # 连接信号
  96. self.backthread.update_date.connect(self.update_UItable)
  97. self.thread = QThread()
  98. self.backthread.moveToThread(self.thread)
  99. # 开始线程
  100. self.thread.started.connect(self.backthread.run)
  101. self.thread.start()
  102. # 初始化界面
  103. def _init_ui(self):
  104. self.row = 0
  105. self.column = 0
  106. self.Login_pushButton.setEnabled(True)
  107. self.Play_pushButton.setEnabled(False)
  108. self.Logout_pushButton.setEnabled(False)
  109. self.StopPlay_pushButton.setEnabled(False)
  110. self.Attach_pushButton.setEnabled(False)
  111. self.Detach_pushButton.setEnabled(False)
  112. self.IP_lineEdit.setText('192.168.128.61')
  113. self.Port_lineEdit.setText('37777')
  114. self.User_lineEdit.setText('admin')
  115. self.Pwd_lineEdit.setText('admin123')
  116. self.setWindowFlag(Qt.WindowMinimizeButtonHint)
  117. self.setWindowFlag(Qt.WindowCloseButtonHint)
  118. self.setFixedSize(self.width(), self.height())
  119. self.Login_pushButton.clicked.connect(self.login_btn_onclick)
  120. self.Logout_pushButton.clicked.connect(self.logout_btn_onclick)
  121. self.Play_pushButton.clicked.connect(self.play_btn_onclick)
  122. self.StopPlay_pushButton.clicked.connect(self.stop_play_btn_onclick)
  123. self.Attach_pushButton.clicked.connect(self.attach_btn_onclick)
  124. self.Detach_pushButton.clicked.connect(self.detach_btn_onclick)
  125. # 登录设备
  126. def login_btn_onclick(self):
  127. self.Attach_tableWidget.setHorizontalHeaderLabels(
  128. ['时间(Time)', '事件(Event)', '车牌号(Plate No.)', '车牌颜色(Plate Color)', '车型类型(Vehicle Type)',
  129. '车身颜色(Vehicle Color)'])
  130. ip = self.IP_lineEdit.text()
  131. port = int(self.Port_lineEdit.text())
  132. username = self.User_lineEdit.text()
  133. password = self.Pwd_lineEdit.text()
  134. stuInParam = NET_IN_LOGIN_WITH_HIGHLEVEL_SECURITY()
  135. stuInParam.dwSize = sizeof(NET_IN_LOGIN_WITH_HIGHLEVEL_SECURITY)
  136. stuInParam.szIP = ip.encode()
  137. stuInParam.nPort = port
  138. stuInParam.szUserName = username.encode()
  139. stuInParam.szPassword = password.encode()
  140. stuInParam.emSpecCap = EM_LOGIN_SPAC_CAP_TYPE.TCP
  141. stuInParam.pCapParam = None
  142. stuOutParam = NET_OUT_LOGIN_WITH_HIGHLEVEL_SECURITY()
  143. stuOutParam.dwSize = sizeof(NET_OUT_LOGIN_WITH_HIGHLEVEL_SECURITY)
  144. self.loginID, device_info, error_msg = self.sdk.LoginWithHighLevelSecurity(stuInParam, stuOutParam)
  145. if self.loginID:
  146. self.setWindowTitle('智能交通(IntelligentTraffic)-在线(OnLine)')
  147. self.Logout_pushButton.setEnabled(True)
  148. self.Login_pushButton.setEnabled(False)
  149. self.Play_pushButton.setEnabled(True)
  150. self.Attach_pushButton.setEnabled(True)
  151. for i in range(int(device_info.nChanNum)):
  152. self.Channel_comboBox.addItem(str(i))
  153. else:
  154. QMessageBox.about(self, '提示(prompt)', error_msg)
  155. # 登出设备
  156. def logout_btn_onclick(self):
  157. # 停止拉流
  158. if self.playID:
  159. self.sdk.StopRealPlayEx(self.playID)
  160. self.playID = 0
  161. self.Video_label.repaint()
  162. self.sdk.SetDecCallBack(self.freePort, None)
  163. self.sdk.Stop(self.freePort)
  164. self.sdk.CloseStream(self.freePort)
  165. self.sdk.ReleasePort(self.freePort)
  166. # 停止订阅
  167. if self.attachID:
  168. self.sdk.StopLoadPic(self.attachID)
  169. self.attachID = 0
  170. # 登出
  171. result = self.sdk.Logout(self.loginID)
  172. self.Login_pushButton.setEnabled(True)
  173. self.Logout_pushButton.setEnabled(False)
  174. self.Play_pushButton.setEnabled(False)
  175. self.StopPlay_pushButton.setEnabled(False)
  176. self.Attach_pushButton.setEnabled(False)
  177. self.Detach_pushButton.setEnabled(False)
  178. self.setWindowTitle("智能交通(IntelligentTraffic)-离线(OffLine)")
  179. self.loginID = C_LLONG(0)
  180. self.Channel_comboBox.clear()
  181. self.Attach_tableWidget.clear()
  182. self.Attach_tableWidget.setRowCount(0)
  183. self.Video_label.clear()
  184. self.GlobalScene_label.clear()
  185. self.SmallScene_label.clear()
  186. self.row = 0
  187. self.column = 0
  188. self.Attach_tableWidget.setHorizontalHeaderLabels(
  189. ['时间(Time)', '事件(Event)', '车牌号(Plate No.)', '车牌颜色(Plate Color)', '车型类型(Vehicle Type)',
  190. '车身颜色(Vehicle Color)'])
  191. # 开始实施预览
  192. def play_btn_onclick(self):
  193. result, self.freePort = self.sdk.GetFreePort()
  194. if not result:
  195. pass
  196. self.sdk.OpenStream(self.freePort)
  197. self.sdk.Play(self.freePort, self.Video_label.winId())
  198. channel = self.Channel_comboBox.currentIndex()
  199. self.playID = self.sdk.RealPlayEx(self.loginID, channel, 0)
  200. if self.playID:
  201. self.Play_pushButton.setEnabled(False)
  202. self.StopPlay_pushButton.setEnabled(True)
  203. self.sdk.SetRealDataCallBackEx2(self.playID, self.m_RealDataCallBack, None, EM_REALDATA_FLAG.RAW_DATA)
  204. self.sdk.SetDecCallBack(self.freePort, self.m_DecodingCallBack)
  205. else:
  206. QMessageBox.about(self, '提示(prompt)', 'error:' + str(self.sdk.GetLastError()))
  207. # 停止拉流
  208. def stop_play_btn_onclick(self):
  209. if self.playID:
  210. self.sdk.StopRealPlayEx(self.playID)
  211. self.Play_pushButton.setEnabled(True)
  212. self.StopPlay_pushButton.setEnabled(False)
  213. self.playID = 0
  214. self.Video_label.repaint()
  215. self.sdk.SetDecCallBack(self.freePort, None)
  216. self.sdk.Stop(self.freePort)
  217. self.sdk.CloseStream(self.freePort)
  218. self.sdk.ReleasePort(self.freePort)
  219. # 智能交通卡口事件订阅
  220. def attach_btn_onclick(self):
  221. self.GlobalScene_label.clear()
  222. self.SmallScene_label.clear()
  223. self.Attach_tableWidget.setHorizontalHeaderLabels(
  224. ['时间(Time)', '事件(Event)', '车牌号(Plate No.)', '车牌颜色(Plate Color)', '车型类型(Vehicle Type)',
  225. '车身颜色(Vehicle Color)'])
  226. channel = self.Channel_comboBox.currentIndex()
  227. bNeedPicFile = 1
  228. dwUser = 0
  229. self.attachID = self.sdk.RealLoadPictureEx(self.loginID, channel, EM_EVENT_IVS_TYPE.TRAFFICJUNCTION,
  230. bNeedPicFile, AnalyzerDataCallBack, dwUser, None)
  231. if not self.attachID:
  232. QMessageBox.about(self, '提示(prompt)', 'error:' + str(self.sdk.GetLastError()))
  233. else:
  234. self.Attach_pushButton.setEnabled(False)
  235. self.Detach_pushButton.setEnabled(True)
  236. QMessageBox.about(self, '提示(prompt)', "订阅成功(Subscribe success)")
  237. # 取消订阅
  238. def detach_btn_onclick(self):
  239. if (self.attachID == 0):
  240. return
  241. self.sdk.StopLoadPic(self.attachID)
  242. self.GlobalScene_label.clear()
  243. self.SmallScene_label.clear()
  244. self.attachID = 0
  245. self.Attach_pushButton.setEnabled(True)
  246. self.Detach_pushButton.setEnabled(False)
  247. self.Attach_tableWidget.setHorizontalHeaderLabels(
  248. ['时间(Time)', '事件(Event)', '车牌号(Plate No.)', '车牌颜色(Plate Color)', '车型类型(Vehicle Type)',
  249. '车身颜色(Vehicle Color)'])
  250. def update_UItable(self, dwAlarmType, show_info, detect_object_id, is_global, is_small):
  251. self.GlobalScene_label.clear()
  252. self.SmallScene_label.clear()
  253. if (dwAlarmType == EM_EVENT_IVS_TYPE.TRAFFICJUNCTION):
  254. if (self.row > 499):
  255. self.Attach_tableWidget.clear()
  256. self.Attach_tableWidget.setRowCount(0)
  257. self.Attach_tableWidget.setHorizontalHeaderLabels(
  258. ['时间(Time)', '事件(Event)', '车牌号(Plate No.)', '车牌颜色(Plate Color)', '车型类型(Vehicle Type)',
  259. '车身颜色(Vehicle Color)'])
  260. self.row = 0
  261. # ui更新
  262. self.Attach_tableWidget.viewport().update()
  263. self.Attach_tableWidget.setRowCount(self.row + 1)
  264. item1 = QTableWidgetItem(show_info.time_str)
  265. self.Attach_tableWidget.setItem(self.row, self.column, item1)
  266. item2 = QTableWidgetItem('交通路口事件(Traffic junction event)')
  267. self.Attach_tableWidget.setItem(self.row, self.column + 1, item2)
  268. item3 = QTableWidgetItem(show_info.plate_number_str)
  269. self.Attach_tableWidget.setItem(self.row, self.column + 2, item3)
  270. item4 = QTableWidgetItem(show_info.plate_color_str)
  271. self.Attach_tableWidget.setItem(self.row, self.column + 3, item4)
  272. item5 = QTableWidgetItem(show_info.object_subType_str)
  273. self.Attach_tableWidget.setItem(self.row, self.column + 4, item5)
  274. item6 = QTableWidgetItem(show_info.vehicle_color_str)
  275. self.Attach_tableWidget.setItem(self.row, self.column + 5, item6)
  276. if (self.attachID != 0):
  277. if is_global:
  278. image = QPixmap('./Global/Global_Img' + str(detect_object_id) + '.jpg').scaled(
  279. self.GlobalScene_label.width(),
  280. self.GlobalScene_label.height())
  281. self.GlobalScene_label.setPixmap(image)
  282. if is_small:
  283. image = QPixmap('./Small/Small_Img' + str(detect_object_id) + '.jpg').scaled(
  284. self.SmallScene_label.width(),
  285. self.SmallScene_label.height())
  286. self.SmallScene_label.setPixmap(image)
  287. self.row += 1
  288. self.Attach_tableWidget.viewport().update()
  289. # 实现断线回调函数功能
  290. def DisConnectCallBack(self, lLoginID, pchDVRIP, nDVRPort, dwUser):
  291. self.setWindowTitle("智能交通(IntelligentTraffic)-离线(OffLine)")
  292. # 实现断线重连回调函数功能
  293. def ReConnectCallBack(self, lLoginID, pchDVRIP, nDVRPort, dwUser):
  294. self.setWindowTitle('智能交通(IntelligentTraffic)-在线(OnLine)')
  295. # 拉流回调函数功能
  296. def RealDataCallBack(self, lRealHandle, dwDataType, pBuffer, dwBufSize, param, dwUser):
  297. if lRealHandle == self.playID:
  298. data_buffer = cast(pBuffer, POINTER(c_ubyte * dwBufSize)).contents
  299. with open('./data.dav', 'ab+') as data_file:
  300. data_file.write(data_buffer)
  301. self.sdk.InputData(self.freePort, pBuffer, dwBufSize)
  302. # PLAYSDK解码回调函数功能
  303. def DecodingCallBack(self, nPort, pBuf, nSize, pFrameInfo, pUserData, nReserved2):
  304. # here get YUV data, pBuf is YUV data IYUV/YUV420 ,size is nSize, pFrameInfo is frame info with height, width.
  305. data = cast(pBuf, POINTER(c_ubyte * nSize)).contents
  306. info = pFrameInfo.contents
  307. # info.nType == 3 is YUV data,others ard audio data.
  308. # you can parse YUV420 data to RGB
  309. if info.nType == 3:
  310. pass
  311. # 关闭主窗口时清理资源
  312. def closeEvent(self, event):
  313. event.accept()
  314. if self.attachID:
  315. self.sdk.StopLoadPic(self.attachID)
  316. self.attachID = 0
  317. if self.playID:
  318. self.sdk.StopRealPlayEx(self.playID)
  319. self.playID = 0
  320. if self.loginID:
  321. self.sdk.Logout(self.loginID)
  322. self.loginID = 0
  323. self.sdk.Cleanup()
  324. self.Video_label.repaint()
  325. self.Attach_tableWidget.clear()
  326. self.Attach_tableWidget.setRowCount(0)
  327. if __name__ == '__main__':
  328. app = QApplication(sys.argv)
  329. my_wnd = TrafficWnd()
  330. wnd = my_wnd
  331. my_wnd.show()
  332. sys.exit(app.exec_())