utils.py 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. # coding=utf-8
  2. from apps.web.agent.models import Agent
  3. from apps.web.api.utils import bd09_to_gcj02, get_coordinates_and_nums
  4. from apps.web.common.models import District
  5. from apps.web.constant import Const
  6. from apps.web.south_intf.shangdong_platform import ShanDongNorther, GroupIdMap, GB2260
  7. from apps.web.device.models import Part, DeviceDict, GroupDict, Device
  8. from apps.web.user.models import ConsumeRecord
  9. def get_connector(part, norther): # type:(Part, ShanDongNorther) -> dict
  10. """
  11. 获取部件信息
  12. """
  13. return {
  14. "ConnectorID": str(part.id),
  15. "ConnectorName": part.partName,
  16. "ConnectorType": 2,
  17. "VoltageUpperLimits": 220,
  18. "VoltageLowerLimits": 220,
  19. "Current": part.attachParas.get("current", 16),
  20. "Power": part.attachParas.get("power", 7),
  21. "ParkNo": "-",
  22. "NationalStandard": 3,
  23. }
  24. def get_equipment(dev, norther): # type:(DeviceDict, ShanDongNorther) -> dict
  25. agent = Agent.objects.get(id=dev.owner.agentId)
  26. ConnectorInfo = list()
  27. for part in dev.parts:
  28. ConnectorInfo.append(get_connector(part, norther))
  29. data = {
  30. "EquipmentID": dev.devNo,
  31. "ManufacturerName": agent.productName,
  32. "EquipmentModel": dev.get("devType", dict()).get("name", ""),
  33. "EquipmentName": dev.get("logicalCode"),
  34. "EquipmentType": 2,
  35. "EquipmentStatus": 50,
  36. "EquipmentPower": 7,
  37. "NewNationalStandard": 1,
  38. "ConnectorInfos": ConnectorInfo,
  39. }
  40. return data
  41. def get_stations_info(group, norther): # type:(GroupDict, ShanDongNorther) -> dict
  42. """
  43. 获取站点的信息
  44. """
  45. # 获取经纬度 获取设备数量 经纬度使用火星坐标系转换
  46. lng, lat, count = get_coordinates_and_nums(group.groupId)
  47. lng, lat = bd09_to_gcj02(lng, lat)
  48. # 获取设备信息
  49. EquipmentInfos = list()
  50. devNos = Device.get_devNos_by_group([group.groupId])
  51. for devNo in devNos:
  52. dev = Device.get_dev(devNo) # type: DeviceDict
  53. if dev.majorDeviceType != u"汽车充电桩":
  54. continue
  55. EquipmentInfos.append(get_equipment(dev, norther))
  56. # 充电站信息
  57. stationId = GroupIdMap.get_stationId(group.groupId)
  58. dealer = group.owner
  59. data = {
  60. "StationID": stationId, # 充电站ID 20
  61. "OperatorID": norther.agentOperatorID, # 组织机构代码 9
  62. "EquipmentOwnerID": norther.equipOperatorID, # 设备所属方组织机构代码 9
  63. "StationName": group.groupName, # 充电站名称描述 50
  64. "CountryCode": "CN", # 国家代码 固定
  65. "AreaCode": GB2260.get_code(District.get_area(group.get("districtId"))), # 地区编码 20
  66. "Address": group.address, # 详细地址 50
  67. "StationTel": '-', # 站点责任人电话,
  68. "ServiceTel": '-', # 站点服务电话
  69. "StationType": 1, # 站点类型
  70. "StationStatus": 50, # 站点状态
  71. "ParkNums": 0, # 车位数量 0代表未知
  72. "StationLng": "{:.6f}".format(float(lng)), # 精度(6位小数)
  73. "StationLat": "{:.6f}".format(float(lat)), # 维度(6位小数)
  74. "Construction": 255, # 建设场所
  75. "ParkInfo": "-",
  76. "ParkName": "-",
  77. "OpenAllDay": 1, # 是否全天开放
  78. "BusineHours": u"24小时全天服务", # 营业时间描述
  79. "MinElectricityPric": 0.0, # 最低充电费率 浮点型
  80. "ElectricityFee": "-", # 充电电费描述,
  81. "ServiceFee": "-", # 服务费率描述
  82. "ParkFree": 0, # 是否停车免费
  83. "ParkFee": "-", # 停车费率描述
  84. "SupportOrder": 0, # 是否支持预约
  85. "EquipmentInfos": EquipmentInfos, # 充电站信息,
  86. "ElectricityTax": 0.0,
  87. "ServiceTax": 0.0
  88. }
  89. return data
  90. def get_get_station_state(stationID,startTime, endTime):
  91. groupId = GroupIdMap.get_groupId(stationID)
  92. EquipmentStatsInfos = list()
  93. devNos = Device.get_devNos_by_group([groupId])
  94. elec = float(0)
  95. for devNo in devNos:
  96. tempState = get_equipment_state(devNo, startTime, endTime)
  97. elec += tempState.get("EquipmentElectricity", 0.0)
  98. EquipmentStatsInfos.append(tempState)
  99. data = {
  100. "StationElectricity": elec,
  101. "EquipmentStatsInfos": EquipmentStatsInfos
  102. }
  103. return data
  104. def get_equipment_state(devNo, startTime, endTime):
  105. """
  106. 获取充电设备的 一段时间内的统计信息 主要是电量
  107. :param devNo:
  108. :param startTime:
  109. :param endTime:
  110. :return:
  111. """
  112. device = Device.get_dev(devNo)
  113. ConnectorStatsInfo = list()
  114. parts = Part.objects.filter(logicalCode = device.get("logicalCode"))
  115. elec = float(0)
  116. for part in parts:
  117. tempState = get_part_state(devNo, startTime, endTime, part)
  118. elec += tempState.get("ConnectorElectricity", 0.0)
  119. ConnectorStatsInfo.append(tempState)
  120. return {
  121. "EquipmentID": str(devNo),
  122. "EquipmentElectricity": elec,
  123. "ConnectorStatsInfo": ConnectorStatsInfo
  124. }
  125. def get_part_state(devNo, startTime, endTime, part):
  126. """
  127. 获取充电端口的 一段时间内的统计信息 主要是电量
  128. :param devNo:
  129. :param part:
  130. :param startTime:
  131. :param endTime:
  132. :return:
  133. """
  134. filters = {
  135. "devNo": devNo,
  136. "finishedTime__gte": startTime,
  137. "finishedTime__lte": endTime,
  138. }
  139. device = Device.get_dev(devNo)
  140. if device.get("devType", dict()).get("code") != Const.DEVICE_TYPE_CODE_CAR_CHARGING_CY:
  141. filters.update({"attachParas__chargeIndex": part.partNo})
  142. records = ConsumeRecord.objects.filter(**filters).only("servicedInfo")
  143. elec = float(0)
  144. for item in records:
  145. elec += item.servicedInfo.get("elec", 0.0)
  146. return {
  147. "ConnectorID": str(part.id),
  148. "ConnectorElectricity": float("{:.1f}".format(float(elec)))
  149. }
  150. def get_station_status(groupId): # type:(DeviceDict, ShanDongNorther) -> dict
  151. """
  152. 获取充电站的当前状态
  153. """
  154. ConnectorStatusInfos = list()
  155. devNos = Device.get_devNos_by_group([groupId])
  156. for devNo in devNos:
  157. device = Device.get_dev(devNo)
  158. parts = Part.objects.filter(logicalCode = device.logicalCode)
  159. devCache = Device.get_dev_control_cache(devNo)
  160. online = device.get("online", True)
  161. for part in parts:
  162. if device.get("devType", dict()).get("code") not in [
  163. Const.DEVICE_TYPE_CODE_CAR_CHARGING_CY,
  164. Const.DEVICE_TYPE_CODE_CAR_CHARGING_CY_V2
  165. ]:
  166. partNo = part.partNo
  167. if partNo in ['allPorts','usedPorts','usePorts']:
  168. continue
  169. portCache = devCache.get(part.partNo) or dict()
  170. else:
  171. portCache = devCache or dict()
  172. # 判断端口当前状态
  173. if not online:
  174. status = 0
  175. else:
  176. status = 3 if portCache.get("isStart") else 1
  177. data = {
  178. "ConnectorID": str(part.id),
  179. "Status": status,
  180. "CurrentA": 0,
  181. "VoltageA": 0,
  182. "BeginTime": portCache.get("startTime","-"), # 开始时间
  183. "SOC": 0.0, # 剩余电量
  184. "CurrentKwh": 0.0, # 已充电量
  185. "CurrentMeter": 0.0, # 当前电表读数
  186. "BmsReqVoltage": 0.0, # BMS需求电压
  187. "BmsReqCurrent": 0.0 # BMS需求电流
  188. }
  189. ConnectorStatusInfos.append(data)
  190. return ConnectorStatusInfos
  191. def get_policy_info(partId):
  192. """
  193. 获取 端口的计费信息
  194. :param partId:
  195. :return:
  196. """
  197. DEFAULT_ELEC_PRICE = 1.500
  198. ELEC_FUNCS = [get_elec_price_by_package, get_elec_price_by_conf,
  199. get_elec_price_by_consume]
  200. part = Part.objects.filter(id = partId).first()
  201. if not part:
  202. return
  203. devNo = Device.get_devNo_by_logicalCode(part.logicalCode)
  204. for func in ELEC_FUNCS:
  205. try:
  206. elecPrice = func(devNo)
  207. except Exception:
  208. elecPrice = None
  209. if elecPrice:
  210. break
  211. else:
  212. elecPrice = DEFAULT_ELEC_PRICE
  213. data = {
  214. "StartTime": "000000",
  215. "ElecPrice": elecPrice,
  216. "SevicePrice": 0.0,
  217. "DiscountElecPrice":elecPrice, # 协议电费价格
  218. "DiscountServicePrice":0.0 # 协议服务费价格
  219. }
  220. return data
  221. def get_elec_price_by_package(devNo):
  222. """
  223. 通过套餐获取电费
  224. :param devNo:
  225. :return:
  226. """
  227. device = Device.get_dev(devNo)
  228. package = device.get("washConfig", dict()).get("1", dict())
  229. if not package:
  230. return
  231. price = package.get("price")
  232. time = package.get("time")
  233. unit = package.get("unit")
  234. if unit != u"度":
  235. return
  236. if not all([price, time]):
  237. return
  238. try:
  239. elecPrice = float("{:.4f}".format(float(price) / float(time)))
  240. except ZeroDivisionError:
  241. return
  242. return elecPrice
  243. def get_elec_price_by_conf(devNo):
  244. """
  245. 通过设备设置设置电费
  246. :param devNo:
  247. :return:
  248. """
  249. device = Device.get_dev(devNo)
  250. elecPrice = device.get("otherConf", dict()).get("elecPrice")
  251. return float("{:.4f}".format(float(elecPrice)))
  252. def get_elec_price_by_consume(devNo):
  253. """
  254. 通过 最近一次的消费记录获取电费
  255. :param devNo:
  256. :return:
  257. """
  258. record = ConsumeRecord.objects.filter(devNo=devNo).sort("-id").first()
  259. if not record or not record.servicedInfo:
  260. return
  261. elec = record.servicedInfo.get("elec")
  262. spend = record.servicedInfo.get("spend")
  263. if not all([elec, spend]):
  264. return
  265. try:
  266. elecPrice = float("{:.4f}".format(float(spend) / float(elec)))
  267. except ZeroDivisionError:
  268. return
  269. return elecPrice