utils.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. # -*- coding: utf-8 -*-
  2. # !/usr/bin/env python
  3. import datetime
  4. import logging
  5. from apps.web.south_intf.bj_north.models import BeiJingFengTai
  6. from apps.web.api.utils import get_coordinates_and_nums, bd09_to_gcj02
  7. from apps.web.constant import Const
  8. from apps.web.core.models import DriverCode
  9. from apps.web.dealer.models import Dealer, Group
  10. from apps.web.device.models import Device
  11. from apps.web.user.models import ConsumeRecord
  12. CHARGESTIPTYPE = {
  13. "按照充电服务类型正常停止充电": 0,
  14. "用户本地刷卡停止充电": 1,
  15. "用户远程结束充电": 2,
  16. "平台远程结束充电": 3,
  17. "检测到枪头断开而停止充电": 4,
  18. "检测到充电桩掉电而停止充电": 5,
  19. "检测到充电桩故障而停止充电": 6,
  20. "检测到电动车故障而停止充电": 7,
  21. "其它原因停止充电": 8,
  22. "检测到充满停止充电": 9,
  23. "检测到余额不足而停止充电": 10,
  24. "过载停止": 11,
  25. "过压停止": 12,
  26. "欠压停止": 13,
  27. "整桩实时功率过大停止充电": 14,
  28. "手机蓝牙停止": 15,
  29. "设备接地故障": 16,
  30. "设备温度过高": 17,
  31. "未关闭柜门": 18,
  32. "电池温度异常": 19,
  33. "电池电压异常": 20,
  34. "电池温差超过阈值": 21,
  35. "电池压差超过阈值": 22,
  36. "功率异常浮动停止充电": 23,
  37. "超时结束充电": 24, # (电量充电时超时(720分 钟))
  38. }
  39. ERRORCODE = {
  40. "设备未回复电压电流功率": 1001,
  41. "设备未回复错误状态": 1002,
  42. "电表故障": 1003,
  43. "设备故障": 1004,
  44. "欠压告警": 1005,
  45. "过压告警": 1006,
  46. "过流保护": 1007,
  47. "离线告警": 1008,
  48. "漏电流异常告警": 1009,
  49. "输出短路告警": 1010,
  50. "电表异常": 1011,
  51. "无效回应": 1012,
  52. "无效参数": 1013,
  53. "接收超时": 1014,
  54. "过温报警": 1015,
  55. "超过最大功率": 1016,
  56. "设备离线": 1017,
  57. "BID错误": 2001,
  58. "风扇故障": 2002,
  59. "风扇信号故障": 2003,
  60. "电源模块故障": 2004,
  61. "电源模块校准错误": 2005,
  62. "ACC故障": 2006,
  63. "高温报警": 2007,
  64. "烟雾报警": 2008,
  65. "电流波动异常": 2009,
  66. "电流采样故障": 2010,
  67. "电源故障": 2011,
  68. "测试模块失败": 2012,
  69. "测试继电器故障": 2013,
  70. "测试风扇异常": 2014,
  71. "测试开门失败": 2015,
  72. "测试温度异常": 2016,
  73. "异常开门": 2017,
  74. "门锁故障": 2018,
  75. "电池拔出": 2019,
  76. "回应失效": 2020,
  77. "未知类型电池": 2021,
  78. "电池未连接": 2022,
  79. "开门失败": 2023,
  80. "无此订单": 2024,
  81. "充电电压小于电池电压": 2025,
  82. "充电故障": 2026,
  83. "电池电压小于充电电压": 2027,
  84. "电池未连接2": 2028,
  85. "恒流阶段电压异常": 2029,
  86. "恒压阶段电流异常": 2030,
  87. "禁止充电时段": 2031,
  88. "订单无效": 2033,
  89. "设备繁忙": 2034,
  90. "初始状态": 2035,
  91. "灭火装置报警": 2036
  92. }
  93. logger = logging.getLogger(__name__)
  94. def get_dealer_info(dealerId):
  95. dealer = Dealer.objects.filter(id=dealerId).first()
  96. data = {
  97. "OperatorID": dealerId,
  98. "OperatorName": dealer.nickname,
  99. "OperatorTel1": dealer.username,
  100. }
  101. return data
  102. def get_station_info(groupId,operatorId):
  103. group = Group.objects.filter(id=groupId).first() # type: Group
  104. ownerId = group.ownerId
  105. lng, lat, count = get_coordinates_and_nums(group.groupId)
  106. lng, lat = bd09_to_gcj02(lng, lat)
  107. deviceDict = Device.get_devices_by_group([groupId])
  108. dealer = Dealer.objects.filter(id=ownerId).first()
  109. data = {
  110. "stationId": groupId, # 充电站ID
  111. "operatorId":operatorId, # 运营商ID
  112. "equipmentOwnerId": group.ownerId, # 设备所属方ID
  113. "stationName": group.groupName, # 充电站名称
  114. "areaCode": group.districtId, # 充电站省市辖区编码
  115. "district ": "", # 所属区县
  116. "street": "", # 所属街道
  117. "community": "", # 所属社区
  118. "village": group.address, # 所属小区
  119. "address": group.address, # 详细地址
  120. "serviceTel": dealer.username, # 服务电话
  121. "stationType": 50, # 站点类型
  122. "stationStatus": 50, # 站点状态
  123. "chargingNums": get_charge_numbers(deviceDict), # 充电口数量
  124. "stationLng": lng, # 经度
  125. "stationLat": lat, # 纬度
  126. "canopy": 3, # 是否带雨棚
  127. "camera": 3, # 是否有摄像头
  128. "smokeSensation": 3, # 是否有烟感
  129. "fireControl": 3, # 是否有消防器材
  130. "feeType": 1, # 收费方式
  131. "electricityFee": group.otherConf.get('devElec',0), # 充电电费率
  132. "serviceFee": group.otherConf.get('elecFee',0), # 服务费率
  133. "createDate": group.dateTimeAdded, # 建成日期
  134. "operationDate": group.dateTimeAdded, # 投运日期
  135. }
  136. return data
  137. def get_equipment_info(devNo,operatorId):
  138. dev = Device.get_dev(devNo) # type: Device
  139. group = Group.get_group(dev.groupId)
  140. lng, lat, count = get_coordinates_and_nums(group.groupId)
  141. lng, lat = bd09_to_gcj02(lng, lat)
  142. chargingNums = get_charge_nums([devNo])
  143. data = {
  144. "equipmentId": str(dev.logicalCode), # 设备编码
  145. "stationId": str(dev.groupId), # 所属站点
  146. "operatorId": operatorId, # 所属运营商ID
  147. "equipmentName": str(dev.devType.get('name')), # 设备名称
  148. "manufacturerBrand": str(dev.mf), # 设备品牌
  149. "equipmentModel":str(dev.devType.get('majorDeviceType')),
  150. "manufacturerId": "", # 生产商ID
  151. "productionDate":str(dev.dateTimeBinded),
  152. "equipmentType": 1, # 设备类别
  153. "equipmentCategory": 1, # 设备类型
  154. "validateConnectorCount": chargingNums, # 有效充电口数量
  155. "ratedVoltage": 220.0, # 整机额定电压
  156. "ratedCurrent": "", # 整机额定电流
  157. "ratedPower": "", # 整机额定功率
  158. "equipmentLng": lng, # 充电设备经度
  159. "equipmentLat": lat, # 充电设备纬度
  160. "operationDate": str(dev.get('dateTimeAdded')), # 投运日期
  161. "camera": 3 # 是否有摄像头
  162. }
  163. return data
  164. def get_port_normal_info(devNo, port,operatorId):
  165. dev = Device.get_dev(devNo)
  166. electricityFee = dev.devType.get('features',{}).get('billAsService',{}).get('elecCharge',0)
  167. serviceFee = dev.devType.get('features',{}).get('billAsService',{}).get('serviceCharge',0)
  168. data = {
  169. "cellId": str(dev.logicalCode) + '_' + str(port), # 充电设备接口ID
  170. "equipmentId": str(dev.logicalCode), # 所属充电设施ID
  171. "operatorId": operatorId, # 所属充电设施ID
  172. "cellType": 3, # 充电设备接口类型
  173. "cellStandard": "", # 接口标准
  174. "ratedVoltageUpperLimit": 220.0, # 额定电压上限
  175. "ratedVoltageLowerLimit": 0, # 额定电压下限
  176. "ratedCurrent": "", # 额定电流
  177. "ratedPower": "", # 额定功率
  178. "electricityFee": str(electricityFee), # 充电电费率描述
  179. "serviceFee": str(serviceFee), # 服务费率
  180. "fireControl": 3, # 是否有灭火装置
  181. "smokeSensation": 3 # 是否有烟感
  182. }
  183. return data
  184. def get_order_info(orderNo,operatorId):
  185. order = ConsumeRecord.objects.filter(orderNo=orderNo).first() # type: ConsumeRecord
  186. if not order:
  187. return {}
  188. serviceInfo = order.servicedInfo
  189. data = {
  190. "startChargeSeq": orderNo, # 充电订单号
  191. "cellId": order.logicalCode + '_' + str(order.used_port), # 充电设备接口编码
  192. "operatorId": operatorId,
  193. "startDatetime": order.created_date.strftime("%Y-%m-%d %H:%M:%S") or "", # 开始充电时间
  194. "endDatetime": order.finishedTime.strftime("%Y-%m-%d %H:%M:%S") or "", # 结束充电时间
  195. "totalPower": serviceInfo.get('elec') or 0, # 充电量
  196. "totalElecMoney": serviceInfo.get('elecFee') or 0, # 总电费
  197. "totalServiceMoney": serviceInfo.get('serviceFee') or 0, # 总服务费
  198. "StartTpye": 0, # 启动方式
  199. "StopReason": 0, # 结束原因
  200. "averagePower": 0 # 平均功率
  201. }
  202. return data
  203. def get_port_charge_info(devNo, port,operatorId):
  204. box = relo(devNo)
  205. rv = {
  206. "cellId": str(Device.get_logicalCode_by_devNo(devNo) + '_' + str(port)), # 充电设备接口ID
  207. "equipmentId": Device.get_logicalCode_by_devNo(devNo), # 所属充电设施ID
  208. "operatorId":operatorId, # 运营商ID
  209. "updateDatetime":datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), # 本次数据在充电桩硬件上生成上报的时间
  210. "cellStatus": "",
  211. "doorStatus": 0,
  212. "errorCode": 0,
  213. "current": 0.0,
  214. "voltage": 0.0,
  215. "power": 0.0,
  216. "quantity": 0.0,
  217. "envTemperature": 0.0,
  218. "cirTemperature": 0.0,
  219. }
  220. try:
  221. portInfo = box.get_port_info(str(port))
  222. portCacheInfo = Device.get_port_control_cache(devNo,port)
  223. needElec = portCacheInfo.get('needElec',0.0)
  224. leftElec = portCacheInfo.get('leftElec',0.0)
  225. quantity = float(needElec)-float(leftElec)
  226. rv["quantity"] = quantity if quantity >= 0 else 0.0
  227. rv["cellStatus"] = portInfo['status']
  228. rv["power"] = portInfo['power']
  229. except:
  230. pass
  231. return rv
  232. def get_charge_numbers(devDict):
  233. portTotalNum = 0
  234. for devNo in devDict.keys():
  235. try:
  236. box = relo(devNo)
  237. portStatus = box.get_port_status()
  238. portNum = len(portStatus) or 10
  239. except:
  240. portNum = 10
  241. portTotalNum += portNum
  242. return portTotalNum
  243. def get_charge_nums(devList):
  244. portTotalNum = 0
  245. for devNo in devList:
  246. try:
  247. box = relo(devNo)
  248. portStatus = box.get_port_status()
  249. portNum = len(portStatus) or 10
  250. except:
  251. portNum = 10
  252. portTotalNum += portNum
  253. return portTotalNum
  254. def relo(devNo):
  255. devNo = str(devNo)
  256. dev = Device.get_dev(devNo)
  257. code = dev.driverCode
  258. dc = DriverCode.objects.get(code=code)
  259. smartBox = None
  260. exec ('import apps.web.core.adapter.{} as smartBox'.format(dc.adapterFile))
  261. if not smartBox:
  262. raise str('no this adapter')
  263. else:
  264. reload(smartBox)
  265. return getattr(smartBox, dc.adapter)(dev)
  266. def get_token(norther):
  267. url = norther.join_url("platform/management/operatorAPIToken")
  268. timeDate = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
  269. sig = norther.make_signature(timeDate)
  270. result = norther.send_request(url=url,mode="GET", sig=sig, timeDate=timeDate)
  271. status = result.get("status")
  272. logger.info(status)
  273. if status != 200:
  274. return
  275. token = result.get("data", "")
  276. return token
  277. def get_port_status(devNo):
  278. """
  279. 获取端口状态
  280. :param devNo:
  281. :return:
  282. """
  283. workingPorts = []
  284. box = relo(devNo)
  285. portStatus = box.get_port_status()
  286. for port,status in portStatus.items():
  287. if status == Const.DEV_WORK_STATUS_WORKING:
  288. workingPorts.append(port)
  289. return workingPorts
  290. def delete_device_info(devNo):
  291. """
  292. 删除一个充电设施信息
  293. :param devNo:
  294. :return:
  295. """
  296. equipmentID = str(Device.get_logicalCode_by_devNo(devNo))
  297. try:
  298. norther = BeiJingFengTai.objects.filter().first()
  299. operatorId = norther.operatorId
  300. url = norther.join_url("platform/management/equipment?equipmentId={}&operatorId={}".format(equipmentID,operatorId))
  301. token = get_token(norther)
  302. timeDate = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
  303. sig = norther.make_signature(timeDate,token)
  304. return norther.send_request(url=url, mode='DELETE',sig=sig, timeDate=timeDate, token=token)
  305. except:
  306. pass