123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574 |
- # coding=utf-8
- import json
- import logging
- import datetime,time
- from mongoengine import DoesNotExist
- from apilib.monetary import VirtualCoin,RMB
- from django.views.decorators.http import require_POST
- from apilib.utils_datetime import to_datetime
- from apilib.utils_json import JsonResponse
- from apps.web.api.jn_north.constant import RESPONSE_CODE
- from apps.web.api.utils import AES_CBC_PKCS5padding_encrypt, AES_CBC_PKCS5padding_decrypt, generate_json_token, parse_json_token
- from apps.web.device.models import Group, Device, SwapGroup,Part
- from apps.web.south_intf.swap_carcharger import SwapContract
- from apps.web.dealer.models import Dealer
- from apps.web.agent.models import Agent
- from apps.web.core.helpers import ActionDeviceBuilder
- from apps.web.core.utils import async_operation
- from apps.web.user.models import ConsumeRecord, RechargeRecord,ServiceProgress
- from apps.web.user.utils import RechargeRecordBuilder
- logger = logging.getLogger(__name__)
- def queryToken(request):
- """
- 通过账号密码获取token
- """
- logger.debug("[queryToken] request body = {}".format(request.body))
- if not request.body:
- return JsonResponse({"Ret": RESPONSE_CODE.ERROR_POST, "Msg": u"请求参数错误(1001)"})
-
- # 根据路径获取norther
- swapLabel = request.path.split('/')[3]
- norther = SwapContract.get_norther_by_label(swapLabel)
- if not norther:
- return None, JsonResponse({"Ret": RESPONSE_CODE.ERROR_PARAM, "Msg": u"请求的URL路径错误"})
-
- try:
- Data = json.loads(request.body).get("Data")
- data = json.loads(AES_CBC_PKCS5padding_decrypt(Data,norther.dataSecret2Us,norther.dataSecretIV2Us))
- except Exception as e:
- logger.exception(e)
- return JsonResponse({"Ret": RESPONSE_CODE.ERROR_POST, "Msg": u"请求参数错误(1002)"})
- OperatorID = data.get("OperatorID")
- OperatorSecret = data.get("OperatorSecret")
- logger.debug("[queryToken] OperatorID = {}, OperatorSecret = {}".format(OperatorID, OperatorSecret))
- if not all((OperatorID, OperatorSecret)):
- return JsonResponse({"Ret": RESPONSE_CODE.ERROR_POST, "Msg": u"请求参数错误(1003)"})
- try:
- norther = SwapContract.objects.filter(operatorId2Us=OperatorID, secret2Us=OperatorSecret).first() # type: SwapContract
- except DoesNotExist:
- return JsonResponse({"Ret": RESPONSE_CODE.ERROR_POST, "Msg": u"请求参数错误(1004)"})
- except Exception as e:
- return JsonResponse({"Ret": RESPONSE_CODE.SYS_ERROR, "Msg": u"系统错误"})
- expire = 60 * 60 * 24 * 7
- result = {
- "OperatorID": norther.OperatorId,
- "SuccStat": 0,
- "AccessToken": norther.generate_json_token(data=norther.get_token_data(), expire=expire),
- "TokenAvailableTime": expire,
- "FailReason": None
- }
- logger.debug("[queryToken] return result = {}".format(result))
- # 拉取的时候加密 显式指明加密秘钥为 pull
- resultData = AES_CBC_PKCS5padding_encrypt(
- json.dumps(result),
- dataSecret=norther.dataSecret2Us,
- dataSecretIV=norther.dataSecretIV2Us
- )
- sig = norther.get_sig(resultData)
- return JsonResponse({
- "Ret": RESPONSE_CODE.SUCCESS,
- "Msg": u"请求成功",
- "Data": resultData,
- "Sig": sig
- })
- def check_and_get_norther(request):
- token = request.META.get('HTTP_AUTHORIZATION', "").replace("Bearer", "").strip()
- logger.info('[queryStationsInfo] , token = {}'.format(token))
-
- # 根据路径获取norther
- swapLabel = request.path.split('/')[3]
- norther = SwapContract.get_norther_by_label(swapLabel)
- if not norther:
- return None, JsonResponse({"Ret": RESPONSE_CODE.ERROR_PARAM, "Msg": u"请求的URL路径错误"})
-
- # 验证身份
- tokenData = norther.parse_json_token(token)
- if not tokenData:
- return None,JsonResponse({"Ret": RESPONSE_CODE.ERROR_TOKEN, "Msg": u"请求参数错误(1001)"})
- # 获取这个平台下面的所有的northers记录
- northers = SwapContract.get_norther(**tokenData)
- if not northers:
- return None,JsonResponse({"Ret": RESPONSE_CODE.ERROR_PARAM, "Msg": u"请求参数错误(1002)"})
- # 准备token所获取的参数信息
- if norther.id != northers.first().id:
- return None,JsonResponse({"Ret": RESPONSE_CODE.ERROR_TOKEN, "Msg": u"根据token获取数据和实际请求路径不一致(1002)"})
-
- return norther, None
- def get_request_data(request,norther):
- dataSecret2Us = norther.dataSecret2Us
- dataSecretIV2Us = norther.dataSecretIV2Us
- # 验证参数
- logger.debug("[queryStationsInfo] request body = {}".format(request.body))
- if not request.body:
- return None,JsonResponse({"Ret": RESPONSE_CODE.ERROR_POST, "Msg": u"请求参数错误(1003)"})
- try:
- Data = json.loads(request.body).get("Data")
- data = json.loads(AES_CBC_PKCS5padding_decrypt(
- Data,
- dataSecret=dataSecret2Us,
- dataSecretIV=dataSecretIV2Us
- ))
- except Exception as e:
- logger.exception(e)
- return None,JsonResponse({"Ret": RESPONSE_CODE.ERROR_POST, "Msg": u"请求参数错误(1004)"})
-
- return data,None
- def get_reply_reponse(result,norther):
- resultData = AES_CBC_PKCS5padding_encrypt(
- json.dumps(result),
- dataSecret=norther.dataSecret2Us,
- dataSecretIV=norther.dataSecretIV2Us
- )
- sig = norther.get_sig(resultData)
- return JsonResponse({"Ret": 0,"Msg": u"请求成功","Data": resultData,"Sig": sig})
-
- def queryStationsInfo(request):
- """
- 查询充电站的信息
- """
- logger.info('function into [queryStationsInfo]')
-
- norther,response = check_and_get_norther(request)
- if not norther:
- return response
-
- data,response = get_request_data(request, norther)
- if not data:
- return response
-
- # 分页以及查询参数
- pageNo = int(data.get('PageNo', 1))
- pageSize = int(data.get('PageSize', 10))
- lastQueryTime = data.get("LastQueryTime")
-
- logger.info('[queryStationsInfo],pageNo=%s,pageSize=%s,lastQueryTime=%s' % (pageNo,pageSize,lastQueryTime))
-
- # 查找出所有符合条件的信息
- dealerIds = []
- if norther.operatorType == 'dealer':
- dealerIds = [norther.operatorInnerId]
- elif norther.operatorType == 'agent':
- dealerIds = [str(dealer.id) for dealer in Dealer.objects(agentId = norther.operatorInnerId) ]
- elif norther.operatorType == 'manager':
- agentIds = [str(agent.id) for agent in Agent.objects(managerId = norther.operatorInnerId)]
- dealerIds = [str(dealer.id) for dealer in Dealer.objects(agentId__in = agentIds) ]
-
-
- if lastQueryTime:
- dateTime = to_datetime(lastQueryTime)
- swaps = SwapGroup.objects.filter(ownerId__in=dealerIds,swapFlag=True,deviceChangedTime__gte = dateTime,deviceNum__gt = 0)
- else:
- swaps = SwapGroup.objects.filter(ownerId__in=dealerIds,swapFlag=True,deviceNum__gt = 0)
-
- StationInfos = []
- for swap in swaps[(pageNo - 1) * pageSize:pageNo * pageSize]:
- StationInfos.append(norther.get_station(swap))
-
- result = {
- "PageNo": pageNo,
- "ItemSize": pageSize,
- "PageCount": swaps.count(),
- "StationInfos": StationInfos
- }
- logger.debug("[queryStationsInfo] return result = {}".format(result))
- return get_reply_reponse(result,norther)
- def queryStationStatus(request):
- logger.info('function into [queryStationStatus]')
- norther,response = check_and_get_norther(request)
- if not norther:
- return response
-
- data,response = get_request_data(request, norther)
- if not data:
- return response
-
- stationIDs = data.get("StationIDs")
-
- logger.info('[queryStationStatus],stationIDs=%s' % (','.join(stationIDs)))
-
- if not isinstance(stationIDs, list):
- return JsonResponse({"Ret": 4004, "Msg": u"系统错误"})
- StationStatusInfos = []
- for stationID in stationIDs:
- StationStatusInfos.append(
- {
- "StationID": stationID,
- "ConnectorStatusInfos": norther.get_connector_status_infos(stationID)
- }
- )
- result = {
- "StationStatusInfos": StationStatusInfos
- }
-
- logger.debug("[queryStationStatus] return result = {}".format(result))
-
- return get_reply_reponse(result, norther)
- def queryStationStats(request):
- """
- 取每个充电站在某个周期内的统计信息
- :param request:
- :return:
- """
- logger.info('function into [queryStationStats]')
-
- norther,response = check_and_get_norther(request)
- if not norther:
- return response
-
- data,response = get_request_data(request, norther)
- if not data:
- return response
- stationID = data.get("StationID")
- startTime = data.get("StartTime")
- endTime = data.get("EndTime")
- logger.info('[queryStationStats],stationID=%s,startTime=%s,endTime=%s' % (stationID,startTime,endTime))
-
- startTimeObj = datetime.datetime.strptime(startTime, "%Y-%m-%d")
- endTimeObj = datetime.datetime.strptime(endTime, "%Y-%m-%d")
- res = norther.get_station_state(stationID,startTimeObj, endTimeObj)
- res.update({
- "StationID": stationID,
- "StartTime": startTime,
- "EndTime": endTime
- })
- result = {"StationStats": res}
-
- logger.debug("[queryStationStats] return result = {}".format(result))
-
- return get_reply_reponse(result, norther)
- def queryEquipAuth(request):
- logger.info('function into [queryEquipAuth]')
-
- norther,response = check_and_get_norther(request)
- if not norther:
- return response
-
- data,response = get_request_data(request, norther)
- if not data:
- return response
-
- EquipAuthSeq = data.get('EquipAuthSeq')
- ConnectorID = data.get('ConnectorID')
-
- logger.info('[queryEquipAuth],EquipAuthSeq=%s,ConnectorID=%s' % (EquipAuthSeq,ConnectorID))
-
- part = Part.objects(id = ConnectorID).first()
- if not part:
- return JsonResponse({"Ret": RESPONSE_CODE.ERROR_POST, "Msg": u"请求参数错误,没有找到对应的设备接口"})
-
- dev = Device.get_dev_by_l(part.logicalCode)
- box = ActionDeviceBuilder.create_action_device(dev)
- FailReason = 0
- SuccStat = 0
- try:
- devInfo = box.get_port_status_from_dev()
- portInfo = devInfo.get(str(part.partNo),{})
-
- if portInfo['isPlugin'] == 'no':
- FailReason = 1
- except Exception,e:
- FailReason = 2
-
- if FailReason != 0:
- SuccStat = 1
-
- result = {
- 'EquipAuthSeq':EquipAuthSeq,
- 'ConnectorID':ConnectorID,
- 'SuccStat':SuccStat,
- 'FailReason':FailReason
- }
-
- logger.debug("[queryEquipAuth] return result = {}".format(result))
-
- return get_reply_reponse(result, norther)
- def queryEquipBusinessPolicy(request):
- """
- 用于查询运营商的充电设备接口计费模型信息
- :param request:
- :return:
- """
- logger.info('function into [queryEquipBusinessPolicy]')
-
- norther,response = check_and_get_norther(request)
- if not norther:
- return response
-
- data,response = get_request_data(request, norther)
- if not data:
- return response
- equipBizSeq = data.get("EquipBizSeq")
- connectorID = data.get("ConnectorID")
-
- logger.info('[queryEquipBusinessPolicy],equipBizSeq=%s,connectorID=%s' % (equipBizSeq,connectorID))
-
- part = Part.objects(id = connectorID).first()
- if not part:
- return JsonResponse({"Ret": RESPONSE_CODE.ERROR_POST, "Msg": u"请求参数错误,没有找到对应的设备接口"})
-
- dev = Device.get_dev_by_l(part.logicalCode)
- devObj = Device.objects.get(devNo = dev['devNo'])
-
- feeMode = devObj.otherConf.get('feeMode',{})
- shiduan = feeMode.get('shiduan','000000000000000000000000000000000000000000000000')
- elecFeeDict = {'0':feeMode.get('jianFee',0),'1':feeMode.get('fengFee',0),'2':feeMode.get('pingFee',0),'3':feeMode.get('guFee',0)}
- serveFeeDict = {'0':feeMode.get('jianServeFee',0),'1':feeMode.get('fengServeFee',0),'2':feeMode.get('pingServeFee',0),'3':feeMode.get('guServeFee',0)}
-
- PolicyInfos = []
- for ii in range(48):
- startHour = 0 + ii/2
- startMin = '00' if ii%2==0 else '30'
- startTime = '%02d%s00' % (startHour,startMin)
- if (ii == 0) or (ii > 0 and shiduan[ii] != shiduan[ii-1]):
- PolicyInfos.append({'StartTime':startTime,'ElecPrice':elecFeeDict.get(shiduan[ii]),'SevicePrice':serveFeeDict.get(shiduan[ii])})
-
- result = {
- "EquipBizSeq": equipBizSeq,
- "ConnectorID": connectorID,
- "SuccStat": 0 if PolicyInfos else 1,
- "FailReason": 0 if PolicyInfos else 1,
- "SumPeriod": 1,
- "PolicyInfos": PolicyInfos
- }
-
- logger.debug("[queryEquipBusinessPolicy] return result = {}".format(result))
-
- return get_reply_reponse(result, norther)
- def query_start_charge(request):
- logger.info('function into [query_start_charge]' )
-
- norther,response = check_and_get_norther(request)
- if not norther:
- return response
-
- data,response = get_request_data(request, norther)
- if not data:
- return response
- StartChargeSeq = data.get("StartChargeSeq")
- connectorID = data.get("ConnectorID")
-
- logger.info('[query_start_charge],StartChargeSeq=%s,connectorID=%s' % (StartChargeSeq,connectorID))
-
- part = Part.objects(id = connectorID).first()
- if not part:
- return JsonResponse({"Ret": RESPONSE_CODE.ERROR_POST, "Msg": u"请求参数错误,没有找到对应的设备接口"})
- dev = Device.get_dev_by_l(part.logicalCode)
- if not dev:
- return JsonResponse({"Ret": RESPONSE_CODE.ERROR_POST, "Msg": u"请求参数错误,没有找到对应的设备接口"})
- group = Group.get_group(dev['groupId'])
-
- # 启动设备,这里以能湃的
- box = ActionDeviceBuilder.create_action_device(dev)
- SuccStat,FailReason,orderNo = box.start_device_swap(part.partNo)
-
- if SuccStat != 0:
- result = {
- "StartChargeSeq": StartChargeSeq,
- "StartChargeSeqStat": 5,
- "connectorID": connectorID,
- "SuccStat": SuccStat,
- "FailReason": FailReason,
- }
-
- # 异步通知北向
- async_operation(norther.notification_start_charge_result,result)
-
- logger.debug("[query_start_charge] return result = {}".format(result))
-
- return get_reply_reponse(result, norther)
- # 新建一条充值订单
- rechargeOrder = RechargeRecordBuilder.new_swap_recharge(norther.swapLabel,dev,group,part.partNo,StartChargeSeq,orderNo)
-
- # 记录consume rcd
- newRecord = {
- 'orderNo': orderNo,
- 'openId': '',
- 'nickname': '',
- 'coin': VirtualCoin(0),
- 'money': RMB(0),
- 'devNo': dev['devNo'],
- 'logicalCode': dev['logicalCode'],
- 'groupId': dev['groupId'],
- 'ownerId': dev['ownerId'],
- 'address': group['address'],
- 'groupNumber': dev['groupNumber'],
- 'groupName': group['groupName'],
- 'devTypeName': dev.devTypeName,
- 'devTypeCode': dev.devTypeCode,
- 'startKey': '',
- 'isNormal': True,
- 'errorDesc': '',
- 'sequanceNo': orderNo,
- 'status': ConsumeRecord.Status.CREATED,
- 'package': {},
- 'remarks':u'互联互通',
- 'rechargeRcdId':str(rechargeOrder.id)
- }
-
- consumeOrder = ConsumeRecord(**newRecord)
- consumeOrder.save() # type: ConsumeRecord
-
- result = {
- "StartChargeSeq": StartChargeSeq,
- "StartChargeSeqStat": 2,
- "connectorID": connectorID,
- "SuccStat": SuccStat,
- "FailReason": FailReason,
- }
-
- new_service_progress = ServiceProgress(
- device_imei = dev['devNo'],
- devTypeCode = dev['devType']['code'],
- port = part.partNo,
- attachParas = {'StartChargeSeq':StartChargeSeq,'connectorID':connectorID},
- start_time = int(time.time()),
- finished_time = int(time.time()) + 3600*24,
- status = 'waiting', # 等充电事件上报后,再刷新此状态
- consumeOrder = {},
- weifuleOrderNo = orderNo,
- expireAt = datetime.datetime.now() + datetime.timedelta(days = 91))
- new_service_progress.save()
-
- # 异步通知北向
- async_operation(norther.notification_start_charge_result,result)
-
- logger.debug("[query_start_charge] return result = {}".format(result))
-
- return get_reply_reponse(result, norther)
- def query_equip_charge_status(request):
- logger.info('function into [query_equip_charge_status]' )
- norther,response = check_and_get_norther(request)
- if not norther:
- return response
-
- data,response = get_request_data(request, norther)
- if not data:
- return response
- StartChargeSeq = data.get("StartChargeSeq")
-
- logger.info('[query_equip_charge_status],StartChargeSeq=%s' % (StartChargeSeq))
-
- rechargeRcd = RechargeRecord.objects(wxOrderNo = StartChargeSeq).first()
- if not rechargeRcd:
- return JsonResponse({"Ret": RESPONSE_CODE.ERROR_POST, "Msg": u"请求参数错误,没有找到对应的设备接口"})
-
- part = Part.objects(logicalCode = rechargeRcd.logicalCode,partNo = rechargeRcd.extraInfo['portNo']).first()
- if not part:
- return JsonResponse({"Ret": RESPONSE_CODE.ERROR_POST, "Msg": u"请求参数错误,没有找到对应的设备接口"})
- dev = Device.get_dev_by_l(part.logicalCode)
- if not dev:
- return JsonResponse({"Ret": RESPONSE_CODE.ERROR_POST, "Msg": u"请求参数错误,没有找到对应的设备接口"})
-
- box = ActionDeviceBuilder.create_action_device(dev)
- result = box.get_charge_status_for_swap(part.partNo,str(part.id))
- result.update({
- 'StartChargeSeq':StartChargeSeq,
- 'ConnectorId':str(part.id),
- 'StartTime':rechargeRcd.time,
- 'EndTime':datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
- })
-
- logger.debug("[query_equip_charge_status] return result = {}".format(result))
-
- return get_reply_reponse(result, norther)
- def query_stop_charge(request):
- logger.info('function into [query_stop_charge]' )
- norther,response = check_and_get_norther(request)
- if not norther:
- return response
-
- data,response = get_request_data(request, norther)
- if not data:
- return response
-
- StartChargeSeq = data.get("StartChargeSeq")
- connectorID = data.get("ConnectorID")
-
- logger.info('[query_stop_charge],StartChargeSeq=%s,connectorID=%s' % (StartChargeSeq,connectorID))
-
- part = Part.objects(id = connectorID).first()
- if not part:
- return JsonResponse({"Ret": RESPONSE_CODE.ERROR_POST, "Msg": u"请求参数错误,没有找到对应的设备接口"})
- dev = Device.get_dev_by_l(part.logicalCode)
- if not dev:
- return JsonResponse({"Ret": RESPONSE_CODE.ERROR_POST, "Msg": u"请求参数错误,没有找到对应的设备接口"})
- group = Group.get_group(dev['groupId'])
-
- # 首先检查下数据库订单情况,是否已经停止了
- rechargeRcd = RechargeRecord.objects(wxOrderNo = StartChargeSeq).first()
- if not rechargeRcd:
- return JsonResponse({"Ret": RESPONSE_CODE.ERROR_PARAM, "Msg": u"请求参数错误,没有找到对应的充值订单"})
- consumeRcd = ConsumeRecord.objects(orderNo = rechargeRcd.extraInfo['consumeOrderNo']).first()
- if not consumeRcd:
- return JsonResponse({"Ret": RESPONSE_CODE.ERROR_PARAM, "Msg": u"请求参数错误,没有找到对应的消费订单"})
- if consumeRcd.status == ConsumeRecord.Status.FINISHED:
- result = {
- "StartChargeSeq": StartChargeSeq,
- "StartChargeSeqStat": 4, # 已经结束
- "connectorID": connectorID,
- "SuccStat": 0,
- "FailReason": 0,
- }
- # 启动异步,通知启动设备成功
- async_operation(norther.notification_stop_charge_result,result)
- return get_reply_reponse(result, norther)
- box = ActionDeviceBuilder.create_action_device(dev)
- SuccStat,FailReason = box.stop_device_swap(part.partNo)
-
- result = {
- "StartChargeSeq": StartChargeSeq,
- "StartChargeSeqStat": 4,
- "connectorID": connectorID,
- "SuccStat": SuccStat,
- "FailReason": FailReason,
- }
-
- # 启动异步,通知启动设备成功
- async_operation(norther.notification_stop_charge_result,result)
-
- logger.debug("[query_stop_charge] return result = {}".format(result))
-
- return get_reply_reponse(result, norther)
|