IntelligentGate.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. import time
  2. import requests
  3. from NetSDK.SDK_Callback import fDisConnect, fHaveReConnect
  4. from NetSDK.NetSDK import NetClient
  5. from NetSDK.SDK_Enum import *
  6. from NetSDK.SDK_Struct import *
  7. from ctypes import *
  8. import socket
  9. class GateInfo:
  10. HOST = "http://192.168.1.6:3080/upload" # "https://huatong.ifarmcloud.com/secureApi/bill-access-door/getDoorData"
  11. MAP = {
  12. 0: "未知方式", 1: "密码开锁", 2: "刷卡开锁", 3: "先刷卡后密码开锁", 4: "先密码后刷卡开锁", 5: "远程开锁,如通过室内机或者平台对门口机开锁",
  13. 6: "开锁按钮进行开锁", 7: "开锁", 8: "密码+刷卡+组合开锁", 10: "密码+组合开锁", 11: "刷卡+组合开锁", 12: "多人开锁",
  14. 13: "钥匙开门", 14: "胁迫密码开门", 15: "二维码开门", 16: "目标识别开门", 18: "人证对比", 19: "证件+人证比对",
  15. 20: "蓝牙开门", 21: "个性化密码开门", 22: "UserID+密码", 23: "人脸+密码开锁", 24: "+密码开锁", 25: "+人脸开锁",
  16. 26: "刷卡+人脸开锁", 27: "人脸或密码开锁", 28: "或密码开锁", 29: "或人脸开锁", 30: "刷卡或人脸开锁", 31: "刷卡或开锁",
  17. 32: "+人脸+密码开锁", 33: "刷卡+人脸+密码开锁", 34: "刷卡++密码开锁", 35: "卡++人脸组合开锁", 36: "或人脸或密码",
  18. 37: "卡或人脸或密码开锁", 38: "卡或人脸开锁", 39: "卡++人脸+密码组合开锁", 40: "卡或人脸或密码开锁", 41: "(证件+人证比对)或刷卡或人脸",
  19. 42: "人证比对或刷卡(二维码)或人脸", 43: "DTMF开锁(包括SIPINFO,RFC2833,INBAND)", 44: "远程二维码开门", 45: "远程人脸开门",
  20. 46: "人证比对开门()", 47: "临时密码开门", 48: "健康码开门", 49: "目标识别开锁", 50: "目标+密码组合开锁", 51: "人脸+目标组合开锁",
  21. 52: "卡+目标组合开锁", 53: "目标或密码开锁", 54: "人脸或目标开锁", 55: "卡或目标开锁", 56: "人脸+目标+密码组合开锁",
  22. 57: "卡+人脸+目标组合开锁", 58: "卡+目标+密码组合开锁", 59: "人脸或目标或密码开锁", 60: "卡或人脸或目标开锁", 61: "卡或目标或密码开锁",
  23. 62: "卡+人脸+目标+密码组合开锁", 63: "卡或人脸或目标或密码开锁"
  24. }
  25. def __init__(self, mac, seq):
  26. self.mac, self.seq = mac, seq
  27. self.time, self.result = "", 0
  28. self.userId, self.method = "", ""
  29. def parse(self, src, img_buf, buf_size):
  30. self.time = (
  31. f"{src.UTC.dwYear}-{src.UTC.dwMonth:02d}-{src.UTC.dwDay:02d} "
  32. f"{src.UTC.dwHour + 8:02d}:{src.UTC.dwMinute:02d}:{src.UTC.dwSecond:02d}"
  33. )
  34. self.result = src.bStatus
  35. self.method = f"{self.MAP[0]}, code={src.emOpenMethod}"
  36. if src.emOpenMethod in self.MAP.keys():
  37. self.method = self.MAP[src.emOpenMethod]
  38. self.userId = src.szUserID.decode()
  39. image = b""
  40. if src.stuObject.bPicEnble:
  41. image = cast(img_buf, POINTER(c_ubyte * src.stuObject.stPicInfo.dwOffSet)).contents
  42. with open("./image.jpg", "wb") as fp:
  43. fp.write(image)
  44. elif buf_size > 0:
  45. image = cast(img_buf, POINTER(c_ubyte * buf_size)).contents
  46. with open("./image.jpg", "wb") as fp:
  47. fp.write(image)
  48. print(self.__dict__)
  49. resp = requests.request("POST", self.HOST, data=self.__dict__, files={"image": ("image.jpg", image)})
  50. if resp.status_code == 200:
  51. print("data push success:", resp.json())
  52. else:
  53. print("data push error:", resp.text)
  54. class IG:
  55. DEVICES, ATTACH2MAC = {}, {}
  56. INFO, LOGIN_ID, ATTACH_ID, CHANNELS = "Info", "LoginId", "AttachId", "Channels"
  57. USER, PASS = "admin", "hmkj6688"
  58. def __init__(self):
  59. sdk = NetClient()
  60. sdk.InitEx(fDisConnect(self.__disconnect))
  61. sdk.SetAutoReconnect(fHaveReConnect(self.__reconnect))
  62. self.__searchHandler = []
  63. self.__sdk = sdk
  64. @staticmethod
  65. def __disconnect(lLoginID, pchDVRIP, nDVRPort, dwUser):
  66. print(
  67. f"Disconnect: lLoginID: {lLoginID}, pchDVRIP: {pchDVRIP}, "
  68. f"nDVRPort: {nDVRPort}, dwUser{dwUser}"
  69. )
  70. @staticmethod
  71. def __reconnect(lLoginID, pchDVRIP, nDVRPort, dwUser):
  72. print(
  73. f"Reconnect: lLoginID: {lLoginID}, pchDVRIP: {pchDVRIP}, "
  74. f"nDVRPort: {nDVRPort}, dwUser{dwUser}"
  75. )
  76. @staticmethod
  77. def __getIPAddrs():
  78. IPlist = []
  79. ip_list = socket.gethostbyname_ex(socket.gethostname())
  80. for ips in ip_list:
  81. if type(ips) == list and len(ips) != 0:
  82. IPlist = ips[0:]
  83. del ip_list
  84. return IPlist
  85. @staticmethod
  86. @CB_FUNCTYPE(None, C_LLONG, POINTER(DEVICE_NET_INFO_EX2), c_void_p)
  87. def __search_device_callback(lSearchHandle, pDevNetInfo, pUserData):
  88. try:
  89. buf = cast(pDevNetInfo, POINTER(DEVICE_NET_INFO_EX2)).contents
  90. dev = (
  91. buf.stuDevInfo.byInitStatus, buf.stuDevInfo.iIPVersion, buf.stuDevInfo.szIP, buf.stuDevInfo.nPort,
  92. buf.stuDevInfo.szSubmask, buf.stuDevInfo.szGateway, buf.stuDevInfo.szMac, buf.stuDevInfo.szDeviceType,
  93. buf.stuDevInfo.szDetailType, buf.stuDevInfo.nHttpPort, buf.stuDevInfo.byPwdResetWay, buf.szLocalIP,
  94. buf.stuDevInfo.szSerialNo
  95. )
  96. # 0 1 2 3 4 5 6 7 8 9 10 11 12
  97. # (150, 4, b'192.168.1.108', 37777, b'255.255.255.0', b'192.168.1.1', b'f4:b1:c2:d5:46:48', b'BSC', b'DH-ASI31A-MW', 80, 5, b'192.168.1.6', b'9G0487EPAJ87DBF')
  98. # (150, b'192.168.1.108', 37777, b'f4:b1:c2:d5:46:48', 5, b'192.168.1.6', b'9G0487EPAJ87DBF')
  99. if dev[1] == 4 and dev[6] not in IG.DEVICES.keys():
  100. IG.DEVICES[dev[6]] = {
  101. IG.INFO: (dev[0], dev[2], dev[3], dev[6], dev[10], dev[11], dev[12]),
  102. IG.LOGIN_ID: -1, IG.ATTACH_ID: -1, IG.CHANNELS: -1
  103. }
  104. print("device found:", dev)
  105. except Exception as e:
  106. print(e)
  107. def __start_search_device(self):
  108. IPList = self.__getIPAddrs()
  109. for i in range(IPList.__len__()):
  110. startsearch_in = NET_IN_STARTSERACH_DEVICE()
  111. startsearch_in.dwSize = sizeof(NET_IN_STARTSERACH_DEVICE)
  112. startsearch_in.emSendType = EM_SEND_SEARCH_TYPE.MULTICAST_AND_BROADCAST
  113. startsearch_in.cbSearchDevices = self.__search_device_callback
  114. startsearch_in.szLocalIp = IPList[i].encode()
  115. startsearch_out = NET_OUT_STARTSERACH_DEVICE()
  116. startsearch_out.dwSize = sizeof(NET_OUT_STARTSERACH_DEVICE)
  117. lSearchHandle = self.__sdk.StartSearchDevicesEx(startsearch_in, startsearch_out)
  118. if lSearchHandle != 0:
  119. self.__searchHandler.append(lSearchHandle)
  120. def __stop_search_device(self):
  121. for handler in self.__searchHandler:
  122. self.__sdk.StopSearchDevices(handler)
  123. self.__searchHandler.clear()
  124. def __init_device(self, device_mac: bytes):
  125. info = self.DEVICES[device_mac][IG.INFO]
  126. init_Account_In = NET_IN_INIT_DEVICE_ACCOUNT()
  127. init_Account_In.dwSize = sizeof(init_Account_In)
  128. init_Account_In.szMac = device_mac
  129. init_Account_In.szUserName = self.USER.encode()
  130. init_Account_In.szPwd = self.PASS.encode()
  131. init_Account_In.byPwdResetWay = info[4]
  132. init_Account_Out = NET_OUT_INIT_DEVICE_ACCOUNT()
  133. init_Account_Out.dwSize = sizeof(init_Account_Out)
  134. result = self.__sdk.InitDevAccount(init_Account_In, init_Account_Out, 5000, info[5])
  135. if result:
  136. print(f"init device success: {device_mac}")
  137. else:
  138. print(f"init device error: {self.__sdk.GetLastError()}")
  139. def __login(self, device_mac: bytes):
  140. info = self.DEVICES[device_mac][IG.INFO]
  141. stuInParam = NET_IN_LOGIN_WITH_HIGHLEVEL_SECURITY()
  142. stuInParam.dwSize = sizeof(NET_IN_LOGIN_WITH_HIGHLEVEL_SECURITY)
  143. stuInParam.szIP = info[1]
  144. stuInParam.nPort = info[2]
  145. stuInParam.szUserName = self.USER.encode()
  146. stuInParam.szPassword = self.PASS.encode()
  147. stuInParam.emSpecCap = EM_LOGIN_SPAC_CAP_TYPE.TCP
  148. stuInParam.pCapParam = None
  149. stuOutParam = NET_OUT_LOGIN_WITH_HIGHLEVEL_SECURITY()
  150. stuOutParam.dwSize = sizeof(NET_OUT_LOGIN_WITH_HIGHLEVEL_SECURITY)
  151. loginID, result, error = self.__sdk.LoginWithHighLevelSecurity(stuInParam, stuOutParam)
  152. if loginID != 0:
  153. self.DEVICES[device_mac][IG.LOGIN_ID] = loginID
  154. self.DEVICES[device_mac][IG.CHANNELS] = result.nChanNum
  155. print(f"login <{device_mac}> success: loginID={loginID}, device_channels={result.nChanNum}")
  156. else:
  157. print(f"login <{device_mac}> failed: {error}")
  158. def __logout(self, device_mac: bytes):
  159. login = self.DEVICES[device_mac][IG.LOGIN_ID]
  160. if login == -1:
  161. return
  162. res = self.__sdk.Logout(login)
  163. if res:
  164. print(f"logout <{device_mac}.{login}> success")
  165. self.DEVICES[device_mac][IG.LOGIN_ID] = -1
  166. self.DEVICES[device_mac][IG.CHANNELS] = -1
  167. else:
  168. print(f"logout <{device_mac}.{login}> failed")
  169. @staticmethod
  170. @CB_FUNCTYPE(None, C_LLONG, C_DWORD, c_void_p, POINTER(c_ubyte), C_DWORD, C_LDWORD, c_int, c_void_p)
  171. def __subscribe_callback(lAnalyzerHandle, dwAlarmType, pAlarmInfo, pBuffer, dwBufSize, dwUser, nSequence, reserved):
  172. mac = IG.ATTACH2MAC[lAnalyzerHandle] or b"unknown"
  173. if mac == b"unknown":
  174. seq = b"unknown"
  175. else:
  176. seq = IG.DEVICES[mac][IG.INFO][-1]
  177. if dwAlarmType == EM_EVENT_IVS_TYPE.ACCESS_CTL:
  178. gate_info = GateInfo(mac.decode(), seq.decode())
  179. data = cast(pAlarmInfo, POINTER(DEV_EVENT_ACCESS_CTL_INFO)).contents
  180. gate_info.parse(data, pBuffer, dwBufSize)
  181. def __subscribe(self, device_mac: bytes):
  182. loginId = self.DEVICES[device_mac][IG.LOGIN_ID]
  183. channel = self.DEVICES[device_mac][IG.CHANNELS]
  184. if channel == -1:
  185. print(f"device <{device_mac}> owns no channel")
  186. return
  187. bNeedPicFile, dwUser = 1, 0
  188. attachId = self.__sdk.RealLoadPictureEx(
  189. loginId, 0, EM_EVENT_IVS_TYPE.ACCESS_CTL,
  190. bNeedPicFile, self.__subscribe_callback, dwUser, None
  191. )
  192. if not attachId:
  193. print(f"subscribe <{loginId}> error: {self.__sdk.GetLastError()}")
  194. else:
  195. self.DEVICES[device_mac][IG.ATTACH_ID] = attachId
  196. IG.ATTACH2MAC[attachId] = device_mac
  197. print(f"subscribe <{loginId}> success")
  198. def __unsubscribe(self, device_mac: bytes):
  199. attachId = self.DEVICES[device_mac][IG.ATTACH_ID]
  200. if attachId == -1:
  201. return
  202. self.__sdk.StopLoadPic(attachId)
  203. self.DEVICES[device_mac][IG.ATTACH_ID] = -1
  204. del IG.ATTACH2MAC[attachId]
  205. def start_search(self):
  206. print("search devices for 5s")
  207. self.__stop_search_device()
  208. self.__start_search_device()
  209. time.sleep(5)
  210. print("\n === stop search, try init/login/subscribe ===")
  211. self.__stop_search_device()
  212. for mac, device in self.DEVICES.items():
  213. info = device[IG.INFO]
  214. inited = info[0] & 3 != 1
  215. print(f"device: {mac}, inited: {inited}")
  216. if not inited:
  217. self.__init_device(mac)
  218. self.__login(mac)
  219. self.__subscribe(mac)
  220. while True:
  221. time.sleep(60)
  222. def close(self):
  223. self.__stop_search_device()
  224. for mac in self.DEVICES.keys():
  225. self.__unsubscribe(mac)
  226. self.__logout(mac)
  227. self.__sdk.Cleanup()
  228. print("program exit")
  229. # transformer
  230. if __name__ == '__main__':
  231. ig = IG()
  232. try:
  233. ig.start_search()
  234. finally:
  235. ig.close()