utils.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. # -*- coding: utf-8 -*-
  2. # !/usr/bin/env python
  3. import base64
  4. import time
  5. import itsdangerous
  6. import requests
  7. import logging
  8. from django.conf import settings
  9. from apps.web.api.ft_north.models import FengTuTechnologyNorther
  10. from apps.web.constant import DeviceOnlineStatus
  11. from apps.web.device.models import Device, Group
  12. from apps.web.api.ft_north.constant import PORT_WORK_STATUS
  13. from apps.web.api.utils import bd09_to_gcj02, get_coordinates_and_nums
  14. logger = logging.getLogger(__name__)
  15. def get_coding_info_by_device(devNo):
  16. dev = Device.get_dev(devNo)
  17. box = dev.deviceAdapter
  18. try:
  19. devStatusDict = box.get_port_status()
  20. except:
  21. return
  22. codingInfos = list()
  23. for k,v in devStatusDict.items():
  24. codingInfo = {}
  25. codingInfo['coding'] = k
  26. if v['status'] != PORT_WORK_STATUS.PORT_WORKING and v['status'] != PORT_WORK_STATUS.PORT_WORKING:
  27. v['status'] = PORT_WORK_STATUS.PORT_FAULT
  28. codingInfo['status'] = v['status']
  29. codingInfos.append(codingInfo)
  30. return codingInfos
  31. def get_coding_info(devNo):
  32. """
  33. 获取端口状态,先找缓存,缓存中没有直接从设备里拿
  34. :param devNo:
  35. :return:
  36. """
  37. ctrInfo = Device.get_dev_control_cache(devNo)
  38. codingInfo = []
  39. if 'allPorts' not in ctrInfo:
  40. ctrInfo = get_coding_info_by_device(devNo)
  41. if ctrInfo:
  42. return ctrInfo
  43. else:
  44. return [{"coding":"0","status":0}]
  45. else:
  46. allPorts = ctrInfo.get('allPorts', 10)
  47. # allPorts 有的时候会为0, 这个时候强制设置为10
  48. if allPorts == 0:
  49. allPorts = 10
  50. for ii in range(allPorts):
  51. statusDict = {}
  52. tempDict = ctrInfo.get(str(ii + 1), {})
  53. if tempDict.has_key('status'):
  54. statusDict['coding'] = str(ii + 1)
  55. statusDict['status'] = tempDict.get('status')
  56. elif tempDict.has_key('isStart'):
  57. if tempDict['isStart']:
  58. statusDict['coding'] = str(ii + 1)
  59. statusDict['status'] = PORT_WORK_STATUS.PORT_WORKING
  60. else:
  61. statusDict['coding'] = str(ii + 1)
  62. statusDict['status'] = PORT_WORK_STATUS.PORT_IDLE
  63. else:
  64. statusDict['coding'] = str(ii + 1)
  65. statusDict['status'] = PORT_WORK_STATUS.PORT_IDLE
  66. codingInfo.append(statusDict)
  67. return codingInfo
  68. def get_device_status(devNo):
  69. """
  70. 获取设备状态
  71. :param devNo:
  72. :return:
  73. """
  74. dev = Device.get_dev(devNo)
  75. devOnline = dev.online
  76. if devOnline == DeviceOnlineStatus.DEV_STATUS_ONLINE:
  77. devStatus = '1'
  78. elif devOnline == DeviceOnlineStatus.DEV_STATUS_OFFLINE:
  79. devStatus = '0'
  80. else:
  81. devStatus = '-1'
  82. return devStatus
  83. def get_station_Info(groupIds):
  84. """
  85. 推送站点信息
  86. :param groupIds:
  87. :return:
  88. """
  89. stationInfoList = list()
  90. groups = Group.get_groups_by_group_ids(groupIds)
  91. for group in groups.values():
  92. # 获取经纬度 获取设备数量 经纬度使用火星坐标系转换
  93. lng, lat, count = get_coordinates_and_nums(group.groupId)
  94. lng, lat = bd09_to_gcj02(lng, lat)
  95. stationInfoDict = {
  96. "stationId" : group.groupId, # 厂商站点ID
  97. "name" : group.groupName, # 充电站名称
  98. "brand" : "", # 品牌名称
  99. "longitude" : "{:.6f}".format(float(lng)), # 经度(6位小数),
  100. "latitude" : "{:.6f}".format(float(lat)), # 维度(6位小数)
  101. "address" : group.address, # 具体地址
  102. "socketNumber" : 0, # 设备路数
  103. "hasRainshed" : "", # 是否有雨棚
  104. "hasMonitor" : "", # 是否覆盖视频监控
  105. "fireFacilities" : "", # 是否配置消防设施
  106. "buildingTime" : group.get('dateTimeAdded').get('val').split(" ")[0], # 建设时间
  107. "picture" : "", # 站点图片
  108. "deviceList" : get_dev_info([group.groupId],group), # 站点下的设备列表
  109. }
  110. stationInfoList.append(stationInfoDict)
  111. return stationInfoList
  112. def get_dev_info(groupIds,group):
  113. devices = Device.get_devices_by_group(groupIds)
  114. deviceInfo = list()
  115. for devNo,devInfo in devices.items():
  116. devDict = {
  117. 'stationId':groupIds[0], # 厂商站点ID
  118. 'deviceNo':devNo, # 设备编号
  119. 'deviceType':devInfo['devType']["majorDeviceType"], # 设备类型:充电柜、充电桩、桩柜一体、摄像头、烟感、消防器(栓)、喷淋
  120. 'simCardNo':"", # SIM卡号
  121. 'wateringPortNum':"", # 浇水口数量
  122. 'brand':devInfo['devType']["name"], # 品牌名称
  123. 'useStationInfo':1, # 是否与充电站公用一个位置: 0.否, 1.是
  124. 'deviceLocation':group.address, # 设备地址,省市区街道+详细地址
  125. 'longitude':devInfo['lng'], # 径度
  126. 'latitude':devInfo['lat'], # 纬度
  127. 'socketNumber':Device.get_dev_control_cache(devNo).get('allPorts'), # 设备路数,充电口数量
  128. 'buildingYear':devInfo['dateTimeAdded'].split('-')[0] # 建设年份,格式:yyyy
  129. }
  130. deviceInfo.append(devDict)
  131. return deviceInfo
  132. def send_request(url,mode='POST',**kwargs):
  133. """
  134. 主动发送HTTP请求获取数据 密钥及签名
  135. :return:
  136. """
  137. headers = {"Content-Type": "application/json;charset=utf-8"}
  138. token = kwargs.pop("token", None)
  139. if token:headers.update({"Authorization": "Basic {}".format(token)})
  140. timeout = kwargs.pop("timeout", 5)
  141. data = kwargs
  142. try:
  143. if mode == 'POST':
  144. response = requests.post(url=url, json=data, headers=headers, timeout=timeout)
  145. else:
  146. response = requests.get(url=url, headers=headers, timeout=timeout)
  147. except requests.Timeout:
  148. return dict()
  149. except Exception as e:
  150. logger.exception(e)
  151. return dict()
  152. if response.status_code != 200:
  153. return dict()
  154. return response.json()
  155. def get_token(norther):
  156. # if norther.token and norther.tokenExpiredTime > int(time.time()) * 1000:
  157. # return norther.token
  158. timestamp = int(time.time()*1000)
  159. url = norther.join_url("getToken")
  160. sign = norther.get_sig(timestamp)
  161. result = send_request(url,appid=norther.appId,timestamp=timestamp,sign=sign)
  162. ret = result.get("code")
  163. logger.info(ret)
  164. if ret != 200:
  165. return
  166. responseJson = result.get("data")
  167. tokenAvailableTime = responseJson.get("expireTime", 120)
  168. token = responseJson.get("token", "")
  169. # 数据库更新
  170. # norther.update(
  171. # token=token,
  172. # tokenExpiredTime=tokenAvailableTime
  173. # )
  174. #
  175. # norther.save()
  176. return token
  177. def get_station_Info_manage(groupId):
  178. """
  179. 推送站点信息
  180. :param groupId:
  181. :return:
  182. """
  183. group = Group.get_group(groupId)
  184. # 获取经纬度 获取设备数量 经纬度使用火星坐标系转换
  185. lng, lat, count = get_coordinates_and_nums(group.groupId)
  186. lng, lat = bd09_to_gcj02(lng, lat)
  187. stationInfoDict = {
  188. "stationId" : group.groupId, # 厂商站点ID
  189. "name" : group.groupName, # 充电站名称
  190. "chargingType":"", # 充电站类型
  191. "brand":"",
  192. "longitude":lng,
  193. "latitude":lat,
  194. "address":group.address,
  195. "socketNumber":0,
  196. "hasRainshed":"",
  197. "hasMonitor":"",
  198. "fireFacilities":"",
  199. "buildingTime":group.get('dateTimeAdded').strftime('%Y-%m-%d'),
  200. "picture":"",
  201. }
  202. return stationInfoDict
  203. def get_device_info_manage(devNo):
  204. dev = Device.get_dev(devNo)
  205. deviceInfo = {
  206. "stationId":dev["groupId"], # 厂商站点ID
  207. "deviceNo":devNo, # 设备编号
  208. "deviceType":dev['devType']["majorDeviceType"], # 设备类型
  209. "brand":dev['devType']["name"], # 品牌名称
  210. "deviceLocation":Group.get_group(dev["groupId"]).get("address"), # 设备地址
  211. "longitude":dev['lng'], # 经度
  212. "latitude":dev['lat'], # 纬度
  213. "socketNumber":Device.get_dev_control_cache(devNo).get('allPorts',10), # 设备路数
  214. }
  215. return deviceInfo
  216. def get_alarm_report(devNo,alarmType):
  217. dev = Device.get_dev(devNo)
  218. data = {
  219. "stationId":dev.get('groupId'), # 充电站编号
  220. "deviceNo" : devNo,
  221. "codingNo" : "",
  222. "eventId" : base64.b64encode(dev.get('groupId')+devNo+str(time.time())),
  223. "outSourceId" : "",
  224. "alarmType":alarmType
  225. }
  226. return data
  227. def generate_json_token(data, expire=None):
  228. salt = settings.FENG_TU_TOKEN_SECRET
  229. its = itsdangerous.TimedJSONWebSignatureSerializer(salt, expire)
  230. return its.dumps(data)
  231. def parse_json_token(s, expire=None):
  232. salt = settings.FENG_TU_TOKEN_SECRET
  233. its = itsdangerous.TimedJSONWebSignatureSerializer(salt, expire)
  234. try:
  235. result = its.loads(s)
  236. except itsdangerous.BadData:
  237. return dict()
  238. return result
  239. def batchStationInfoReport(groupIds):
  240. """
  241. 主动推送站点信息
  242. :param groupIds:
  243. :return:
  244. """
  245. try:
  246. north = FengTuTechnologyNorther.objects.filter().first()
  247. data = get_station_Info(groupIds)
  248. url = north.join_url("batchStationInfo")
  249. token = get_token(north)
  250. return send_request(url=url, token=token, stationInfoList=data)
  251. except Exception as e:
  252. logger.exception(e)
  253. def addStationReport(groupId):
  254. try:
  255. north = FengTuTechnologyNorther.objects.filter().first()
  256. data = get_station_Info_manage(groupId)
  257. url = north.join_url("station/add")
  258. token = get_token(north)
  259. return send_request(url=url, token=token, **data)
  260. except Exception as e:
  261. logger.exception(e)
  262. def deleteStationReport(groupId):
  263. try:
  264. north = FengTuTechnologyNorther.objects.filter().first()
  265. data = groupId
  266. url = north.join_url("station/delete/{}".format(data))
  267. token = get_token(north)
  268. return send_request(url=url, mode='GET', token=token)
  269. except Exception as e:
  270. logger.exception(e)
  271. def updateStationReport(groupId):
  272. try:
  273. north = FengTuTechnologyNorther.objects.filter().first()
  274. data = get_station_Info_manage(groupId)
  275. url = north.join_url("station/update")
  276. token = get_token(north)
  277. return send_request(url=url, token=token, **data)
  278. except Exception as e:
  279. logger.exception(e)
  280. def addDeviceReport(devNo):
  281. try:
  282. north = FengTuTechnologyNorther.objects.filter().first()
  283. data = get_device_info_manage(devNo)
  284. url = north.join_url("device/add")
  285. token = get_token(north)
  286. return send_request(url=url, token=token, **data)
  287. except Exception as e:
  288. logger.exception(e)
  289. def deleteDeviceReport(devNo):
  290. try:
  291. north = FengTuTechnologyNorther.objects.filter().first()
  292. groupId = Device.get_dev(devNo).get("groupId")
  293. url = north.join_url("device/delete/{}/{}".format(groupId,devNo))
  294. token = get_token(north)
  295. return send_request(url=url, mode='GET', token=token)
  296. except Exception as e:
  297. logger.exception(e)
  298. def updateDeviceReport(devNo):
  299. try:
  300. north = FengTuTechnologyNorther.objects.filter().first()
  301. data = get_device_info_manage(devNo)
  302. url = north.join_url("device/update")
  303. token = get_token(north)
  304. return send_request(url=url, token=token, **data)
  305. except Exception as e:
  306. logger.exception(e)
  307. def devHeartbeatReport(devNo):
  308. try:
  309. data = {
  310. "deviceNo":devNo,
  311. "deviceStatus":get_device_status(devNo),
  312. "codings":get_coding_info(devNo),
  313. "eventId": base64.b64encode(devNo+str(time.time()))
  314. }
  315. north = FengTuTechnologyNorther.objects.filter().first()
  316. url = north.join_url("device/heartbeat")
  317. token = get_token(north)
  318. send_request(url=url, token=token, **data)
  319. except Exception as e:
  320. logger.exception(e)
  321. def alarmReport(devNo,faultName):
  322. try:
  323. north = FengTuTechnologyNorther.objects.filter().first()
  324. data = get_alarm_report(devNo,faultName)
  325. url = north.join_url("alarm")
  326. token = get_token(north)
  327. send_request(url=url, token=token, **data)
  328. except Exception as e:
  329. logger.exception(e)