123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337 |
- # -*- 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
|