# coding=utf-8 from apps.web.agent.models import Agent from apps.web.api.utils import bd09_to_gcj02, get_coordinates_and_nums from apps.web.common.models import District from apps.web.constant import Const from apps.web.south_intf.shangdong_platform import ShanDongNorther, GroupIdMap, GB2260 from apps.web.device.models import Part, DeviceDict, GroupDict, Device from apps.web.user.models import ConsumeRecord def get_connector(part, norther): # type:(Part, ShanDongNorther) -> dict """ 获取部件信息 """ return { "ConnectorID": str(part.id), "ConnectorName": part.partName, "ConnectorType": 2, "VoltageUpperLimits": 220, "VoltageLowerLimits": 220, "Current": part.attachParas.get("current", 16), "Power": part.attachParas.get("power", 7), "ParkNo": "-", "NationalStandard": 3, } def get_equipment(dev, norther): # type:(DeviceDict, ShanDongNorther) -> dict agent = Agent.objects.get(id=dev.owner.agentId) ConnectorInfo = list() for part in dev.parts: ConnectorInfo.append(get_connector(part, norther)) data = { "EquipmentID": dev.devNo, "ManufacturerName": agent.productName, "EquipmentModel": dev.get("devType", dict()).get("name", ""), "EquipmentName": dev.get("logicalCode"), "EquipmentType": 2, "EquipmentStatus": 50, "EquipmentPower": 7, "NewNationalStandard": 1, "ConnectorInfos": ConnectorInfo, } return data def get_stations_info(group, norther): # type:(GroupDict, ShanDongNorther) -> dict """ 获取站点的信息 """ # 获取经纬度 获取设备数量 经纬度使用火星坐标系转换 lng, lat, count = get_coordinates_and_nums(group.groupId) lng, lat = bd09_to_gcj02(lng, lat) # 获取设备信息 EquipmentInfos = list() devNos = Device.get_devNos_by_group([group.groupId]) for devNo in devNos: dev = Device.get_dev(devNo) # type: DeviceDict if dev.majorDeviceType != u"汽车充电桩": continue EquipmentInfos.append(get_equipment(dev, norther)) # 充电站信息 stationId = GroupIdMap.get_stationId(group.groupId) dealer = group.owner data = { "StationID": stationId, # 充电站ID 20 "OperatorID": norther.agentOperatorID, # 组织机构代码 9 "EquipmentOwnerID": norther.equipOperatorID, # 设备所属方组织机构代码 9 "StationName": group.groupName, # 充电站名称描述 50 "CountryCode": "CN", # 国家代码 固定 "AreaCode": GB2260.get_code(District.get_area(group.get("districtId"))), # 地区编码 20 "Address": group.address, # 详细地址 50 "StationTel": '-', # 站点责任人电话, "ServiceTel": '-', # 站点服务电话 "StationType": 1, # 站点类型 "StationStatus": 50, # 站点状态 "ParkNums": 0, # 车位数量 0代表未知 "StationLng": "{:.6f}".format(float(lng)), # 精度(6位小数) "StationLat": "{:.6f}".format(float(lat)), # 维度(6位小数) "Construction": 255, # 建设场所 "ParkInfo": "-", "ParkName": "-", "OpenAllDay": 1, # 是否全天开放 "BusineHours": u"24小时全天服务", # 营业时间描述 "MinElectricityPric": 0.0, # 最低充电费率 浮点型 "ElectricityFee": "-", # 充电电费描述, "ServiceFee": "-", # 服务费率描述 "ParkFree": 0, # 是否停车免费 "ParkFee": "-", # 停车费率描述 "SupportOrder": 0, # 是否支持预约 "EquipmentInfos": EquipmentInfos, # 充电站信息, "ElectricityTax": 0.0, "ServiceTax": 0.0 } return data def get_get_station_state(stationID,startTime, endTime): groupId = GroupIdMap.get_groupId(stationID) EquipmentStatsInfos = list() devNos = Device.get_devNos_by_group([groupId]) elec = float(0) for devNo in devNos: tempState = get_equipment_state(devNo, startTime, endTime) elec += tempState.get("EquipmentElectricity", 0.0) EquipmentStatsInfos.append(tempState) data = { "StationElectricity": elec, "EquipmentStatsInfos": EquipmentStatsInfos } return data def get_equipment_state(devNo, startTime, endTime): """ 获取充电设备的 一段时间内的统计信息 主要是电量 :param devNo: :param startTime: :param endTime: :return: """ device = Device.get_dev(devNo) ConnectorStatsInfo = list() parts = Part.objects.filter(logicalCode = device.get("logicalCode")) elec = float(0) for part in parts: tempState = get_part_state(devNo, startTime, endTime, part) elec += tempState.get("ConnectorElectricity", 0.0) ConnectorStatsInfo.append(tempState) return { "EquipmentID": str(devNo), "EquipmentElectricity": elec, "ConnectorStatsInfo": ConnectorStatsInfo } def get_part_state(devNo, startTime, endTime, part): """ 获取充电端口的 一段时间内的统计信息 主要是电量 :param devNo: :param part: :param startTime: :param endTime: :return: """ filters = { "devNo": devNo, "finishedTime__gte": startTime, "finishedTime__lte": endTime, } device = Device.get_dev(devNo) if device.get("devType", dict()).get("code") != Const.DEVICE_TYPE_CODE_CAR_CHARGING_CY: filters.update({"attachParas__chargeIndex": part.partNo}) records = ConsumeRecord.objects.filter(**filters).only("servicedInfo") elec = float(0) for item in records: elec += item.servicedInfo.get("elec", 0.0) return { "ConnectorID": str(part.id), "ConnectorElectricity": float("{:.1f}".format(float(elec))) } def get_station_status(groupId): # type:(DeviceDict, ShanDongNorther) -> dict """ 获取充电站的当前状态 """ ConnectorStatusInfos = list() devNos = Device.get_devNos_by_group([groupId]) for devNo in devNos: device = Device.get_dev(devNo) parts = Part.objects.filter(logicalCode = device.logicalCode) devCache = Device.get_dev_control_cache(devNo) online = device.get("online", True) for part in parts: if device.get("devType", dict()).get("code") not in [ Const.DEVICE_TYPE_CODE_CAR_CHARGING_CY, Const.DEVICE_TYPE_CODE_CAR_CHARGING_CY_V2 ]: partNo = part.partNo if partNo in ['allPorts','usedPorts','usePorts']: continue portCache = devCache.get(part.partNo) or dict() else: portCache = devCache or dict() # 判断端口当前状态 if not online: status = 0 else: status = 3 if portCache.get("isStart") else 1 data = { "ConnectorID": str(part.id), "Status": status, "CurrentA": 0, "VoltageA": 0, "BeginTime": portCache.get("startTime","-"), # 开始时间 "SOC": 0.0, # 剩余电量 "CurrentKwh": 0.0, # 已充电量 "CurrentMeter": 0.0, # 当前电表读数 "BmsReqVoltage": 0.0, # BMS需求电压 "BmsReqCurrent": 0.0 # BMS需求电流 } ConnectorStatusInfos.append(data) return ConnectorStatusInfos def get_policy_info(partId): """ 获取 端口的计费信息 :param partId: :return: """ DEFAULT_ELEC_PRICE = 1.500 ELEC_FUNCS = [get_elec_price_by_package, get_elec_price_by_conf, get_elec_price_by_consume] part = Part.objects.filter(id = partId).first() if not part: return devNo = Device.get_devNo_by_logicalCode(part.logicalCode) for func in ELEC_FUNCS: try: elecPrice = func(devNo) except Exception: elecPrice = None if elecPrice: break else: elecPrice = DEFAULT_ELEC_PRICE data = { "StartTime": "000000", "ElecPrice": elecPrice, "SevicePrice": 0.0, "DiscountElecPrice":elecPrice, # 协议电费价格 "DiscountServicePrice":0.0 # 协议服务费价格 } return data def get_elec_price_by_package(devNo): """ 通过套餐获取电费 :param devNo: :return: """ device = Device.get_dev(devNo) package = device.get("washConfig", dict()).get("1", dict()) if not package: return price = package.get("price") time = package.get("time") unit = package.get("unit") if unit != u"度": return if not all([price, time]): return try: elecPrice = float("{:.4f}".format(float(price) / float(time))) except ZeroDivisionError: return return elecPrice def get_elec_price_by_conf(devNo): """ 通过设备设置设置电费 :param devNo: :return: """ device = Device.get_dev(devNo) elecPrice = device.get("otherConf", dict()).get("elecPrice") return float("{:.4f}".format(float(elecPrice))) def get_elec_price_by_consume(devNo): """ 通过 最近一次的消费记录获取电费 :param devNo: :return: """ record = ConsumeRecord.objects.filter(devNo=devNo).sort("-id").first() if not record or not record.servicedInfo: return elec = record.servicedInfo.get("elec") spend = record.servicedInfo.get("spend") if not all([elec, spend]): return try: elecPrice = float("{:.4f}".format(float(spend) / float(elec))) except ZeroDivisionError: return return elecPrice