# -*- coding: utf-8 -*- # !/usr/bin/env python import datetime import logging from apps.web.south_intf.bj_north.models import BeiJingFengTai from apps.web.api.utils import get_coordinates_and_nums, bd09_to_gcj02 from apps.web.constant import Const from apps.web.core.models import DriverCode from apps.web.dealer.models import Dealer, Group from apps.web.device.models import Device from apps.web.user.models import ConsumeRecord CHARGESTIPTYPE = { "按照充电服务类型正常停止充电": 0, "用户本地刷卡停止充电": 1, "用户远程结束充电": 2, "平台远程结束充电": 3, "检测到枪头断开而停止充电": 4, "检测到充电桩掉电而停止充电": 5, "检测到充电桩故障而停止充电": 6, "检测到电动车故障而停止充电": 7, "其它原因停止充电": 8, "检测到充满停止充电": 9, "检测到余额不足而停止充电": 10, "过载停止": 11, "过压停止": 12, "欠压停止": 13, "整桩实时功率过大停止充电": 14, "手机蓝牙停止": 15, "设备接地故障": 16, "设备温度过高": 17, "未关闭柜门": 18, "电池温度异常": 19, "电池电压异常": 20, "电池温差超过阈值": 21, "电池压差超过阈值": 22, "功率异常浮动停止充电": 23, "超时结束充电": 24, # (电量充电时超时(720分 钟)) } ERRORCODE = { "设备未回复电压电流功率": 1001, "设备未回复错误状态": 1002, "电表故障": 1003, "设备故障": 1004, "欠压告警": 1005, "过压告警": 1006, "过流保护": 1007, "离线告警": 1008, "漏电流异常告警": 1009, "输出短路告警": 1010, "电表异常": 1011, "无效回应": 1012, "无效参数": 1013, "接收超时": 1014, "过温报警": 1015, "超过最大功率": 1016, "设备离线": 1017, "BID错误": 2001, "风扇故障": 2002, "风扇信号故障": 2003, "电源模块故障": 2004, "电源模块校准错误": 2005, "ACC故障": 2006, "高温报警": 2007, "烟雾报警": 2008, "电流波动异常": 2009, "电流采样故障": 2010, "电源故障": 2011, "测试模块失败": 2012, "测试继电器故障": 2013, "测试风扇异常": 2014, "测试开门失败": 2015, "测试温度异常": 2016, "异常开门": 2017, "门锁故障": 2018, "电池拔出": 2019, "回应失效": 2020, "未知类型电池": 2021, "电池未连接": 2022, "开门失败": 2023, "无此订单": 2024, "充电电压小于电池电压": 2025, "充电故障": 2026, "电池电压小于充电电压": 2027, "电池未连接2": 2028, "恒流阶段电压异常": 2029, "恒压阶段电流异常": 2030, "禁止充电时段": 2031, "订单无效": 2033, "设备繁忙": 2034, "初始状态": 2035, "灭火装置报警": 2036 } logger = logging.getLogger(__name__) def get_dealer_info(dealerId): dealer = Dealer.objects.filter(id=dealerId).first() data = { "OperatorID": dealerId, "OperatorName": dealer.nickname, "OperatorTel1": dealer.username, } return data def get_station_info(groupId,operatorId): group = Group.objects.filter(id=groupId).first() # type: Group ownerId = group.ownerId lng, lat, count = get_coordinates_and_nums(group.groupId) lng, lat = bd09_to_gcj02(lng, lat) deviceDict = Device.get_devices_by_group([groupId]) dealer = Dealer.objects.filter(id=ownerId).first() data = { "stationId": groupId, # 充电站ID "operatorId":operatorId, # 运营商ID "equipmentOwnerId": group.ownerId, # 设备所属方ID "stationName": group.groupName, # 充电站名称 "areaCode": group.districtId, # 充电站省市辖区编码 "district ": "", # 所属区县 "street": "", # 所属街道 "community": "", # 所属社区 "village": group.address, # 所属小区 "address": group.address, # 详细地址 "serviceTel": dealer.username, # 服务电话 "stationType": 50, # 站点类型 "stationStatus": 50, # 站点状态 "chargingNums": get_charge_numbers(deviceDict), # 充电口数量 "stationLng": lng, # 经度 "stationLat": lat, # 纬度 "canopy": 3, # 是否带雨棚 "camera": 3, # 是否有摄像头 "smokeSensation": 3, # 是否有烟感 "fireControl": 3, # 是否有消防器材 "feeType": 1, # 收费方式 "electricityFee": group.otherConf.get('devElec',0), # 充电电费率 "serviceFee": group.otherConf.get('elecFee',0), # 服务费率 "createDate": group.dateTimeAdded, # 建成日期 "operationDate": group.dateTimeAdded, # 投运日期 } return data def get_equipment_info(devNo,operatorId): dev = Device.get_dev(devNo) # type: Device group = Group.get_group(dev.groupId) lng, lat, count = get_coordinates_and_nums(group.groupId) lng, lat = bd09_to_gcj02(lng, lat) chargingNums = get_charge_nums([devNo]) data = { "equipmentId": str(dev.logicalCode), # 设备编码 "stationId": str(dev.groupId), # 所属站点 "operatorId": operatorId, # 所属运营商ID "equipmentName": str(dev.devType.get('name')), # 设备名称 "manufacturerBrand": str(dev.mf), # 设备品牌 "equipmentModel":str(dev.devType.get('majorDeviceType')), "manufacturerId": "", # 生产商ID "productionDate":str(dev.dateTimeBinded), "equipmentType": 1, # 设备类别 "equipmentCategory": 1, # 设备类型 "validateConnectorCount": chargingNums, # 有效充电口数量 "ratedVoltage": 220.0, # 整机额定电压 "ratedCurrent": "", # 整机额定电流 "ratedPower": "", # 整机额定功率 "equipmentLng": lng, # 充电设备经度 "equipmentLat": lat, # 充电设备纬度 "operationDate": str(dev.get('dateTimeAdded')), # 投运日期 "camera": 3 # 是否有摄像头 } return data def get_port_normal_info(devNo, port,operatorId): dev = Device.get_dev(devNo) electricityFee = dev.devType.get('features',{}).get('billAsService',{}).get('elecCharge',0) serviceFee = dev.devType.get('features',{}).get('billAsService',{}).get('serviceCharge',0) data = { "cellId": str(dev.logicalCode) + '_' + str(port), # 充电设备接口ID "equipmentId": str(dev.logicalCode), # 所属充电设施ID "operatorId": operatorId, # 所属充电设施ID "cellType": 3, # 充电设备接口类型 "cellStandard": "", # 接口标准 "ratedVoltageUpperLimit": 220.0, # 额定电压上限 "ratedVoltageLowerLimit": 0, # 额定电压下限 "ratedCurrent": "", # 额定电流 "ratedPower": "", # 额定功率 "electricityFee": str(electricityFee), # 充电电费率描述 "serviceFee": str(serviceFee), # 服务费率 "fireControl": 3, # 是否有灭火装置 "smokeSensation": 3 # 是否有烟感 } return data def get_order_info(orderNo,operatorId): order = ConsumeRecord.objects.filter(orderNo=orderNo).first() # type: ConsumeRecord if not order: return {} serviceInfo = order.servicedInfo data = { "startChargeSeq": orderNo, # 充电订单号 "cellId": order.logicalCode + '_' + str(order.used_port), # 充电设备接口编码 "operatorId": operatorId, "startDatetime": order.created_date.strftime("%Y-%m-%d %H:%M:%S") or "", # 开始充电时间 "endDatetime": order.finishedTime.strftime("%Y-%m-%d %H:%M:%S") or "", # 结束充电时间 "totalPower": serviceInfo.get('elec') or 0, # 充电量 "totalElecMoney": serviceInfo.get('elecFee') or 0, # 总电费 "totalServiceMoney": serviceInfo.get('serviceFee') or 0, # 总服务费 "StartTpye": 0, # 启动方式 "StopReason": 0, # 结束原因 "averagePower": 0 # 平均功率 } return data def get_port_charge_info(devNo, port,operatorId): box = relo(devNo) rv = { "cellId": str(Device.get_logicalCode_by_devNo(devNo) + '_' + str(port)), # 充电设备接口ID "equipmentId": Device.get_logicalCode_by_devNo(devNo), # 所属充电设施ID "operatorId":operatorId, # 运营商ID "updateDatetime":datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), # 本次数据在充电桩硬件上生成上报的时间 "cellStatus": "", "doorStatus": 0, "errorCode": 0, "current": 0.0, "voltage": 0.0, "power": 0.0, "quantity": 0.0, "envTemperature": 0.0, "cirTemperature": 0.0, } try: portInfo = box.get_port_info(str(port)) portCacheInfo = Device.get_port_control_cache(devNo,port) needElec = portCacheInfo.get('needElec',0.0) leftElec = portCacheInfo.get('leftElec',0.0) quantity = float(needElec)-float(leftElec) rv["quantity"] = quantity if quantity >= 0 else 0.0 rv["cellStatus"] = portInfo['status'] rv["power"] = portInfo['power'] except: pass return rv def get_charge_numbers(devDict): portTotalNum = 0 for devNo in devDict.keys(): try: box = relo(devNo) portStatus = box.get_port_status() portNum = len(portStatus) or 10 except: portNum = 10 portTotalNum += portNum return portTotalNum def get_charge_nums(devList): portTotalNum = 0 for devNo in devList: try: box = relo(devNo) portStatus = box.get_port_status() portNum = len(portStatus) or 10 except: portNum = 10 portTotalNum += portNum return portTotalNum def relo(devNo): devNo = str(devNo) dev = Device.get_dev(devNo) code = dev.driverCode dc = DriverCode.objects.get(code=code) smartBox = None exec ('import apps.web.core.adapter.{} as smartBox'.format(dc.adapterFile)) if not smartBox: raise str('no this adapter') else: reload(smartBox) return getattr(smartBox, dc.adapter)(dev) def get_token(norther): url = norther.join_url("platform/management/operatorAPIToken") timeDate = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") sig = norther.make_signature(timeDate) result = norther.send_request(url=url,mode="GET", sig=sig, timeDate=timeDate) status = result.get("status") logger.info(status) if status != 200: return token = result.get("data", "") return token def get_port_status(devNo): """ 获取端口状态 :param devNo: :return: """ workingPorts = [] box = relo(devNo) portStatus = box.get_port_status() for port,status in portStatus.items(): if status == Const.DEV_WORK_STATUS_WORKING: workingPorts.append(port) return workingPorts def delete_device_info(devNo): """ 删除一个充电设施信息 :param devNo: :return: """ equipmentID = str(Device.get_logicalCode_by_devNo(devNo)) try: norther = BeiJingFengTai.objects.filter().first() operatorId = norther.operatorId url = norther.join_url("platform/management/equipment?equipmentId={}&operatorId={}".format(equipmentID,operatorId)) token = get_token(norther) timeDate = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") sig = norther.make_signature(timeDate,token) return norther.send_request(url=url, mode='DELETE',sig=sig, timeDate=timeDate, token=token) except: pass