123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966 |
- # -*- coding: utf-8 -*-
- # !/usr/bin/env python
- import binascii
- import datetime
- import logging
- import os
- import random
- import time
- import simplejson as json
- from apilib.monetary import VirtualCoin, RMB
- from apps.web.common.proxy import ClientConsumeModelProxy
- from apps.web.constant import DeviceCmdCode, Const, MQTT_TIMEOUT
- from apps.web.core.adapter.base import SmartBox, reverse_hex, fill_2_hexByte
- from apps.web.core.device_define.ywt_chongdiangui import Calculater
- from apps.web.core.exceptions import ServiceException
- from apps.web.core.networking import MessageSender
- from apps.web.device.models import DevicePortReport, Group, Device, DeviceType
- from apps.web.user.models import ConsumeRecord, ServiceProgress, MyUser
- from apps.web.core.device_define.ywt_chongdiangui import DefaultParams
- from apps.web.utils import concat_user_login_entry_url
- from taskmanager.mediator import task_caller
- logger = logging.getLogger(__name__)
- class ChargeCabinet(SmartBox):
- def __init__(self, *args, **kwargs):
- super(ChargeCabinet, self).__init__(*args, **kwargs)
- # 主要用于计算费用
- self.devNo = self.device.devNo
- @property
- def password(self):
- return random.randint(0x2710, 0xFFFF)
- def _send_data(self, funCode, sendData, cmd=None, timeout=MQTT_TIMEOUT.NORMAL, orderNo=None):
- """
- 发送报文封装
- :param funCode:
- :param sendData:
- :param cmd:
- :param timeout:
- :param orderNo:
- :return:
- """
- if cmd is None:
- cmd = DeviceCmdCode.OPERATE_DEV_SYNC
- result = MessageSender.send(device = self.device, cmd = cmd, payload = {
- "IMEI": self._device["devNo"],
- "funCode": funCode,
- "data": sendData
- }, timeout = timeout)
- if result.has_key("rst"):
- if result["rst"] == -1:
- raise ServiceException({'result': 2, 'description': u'充电桩正在玩命找网络,请稍候再试'})
- elif result["rst"] == 1:
- raise ServiceException({'result': 2, 'description': u'充电桩主板连接故障'})
- elif result["rst"] == 0:
- return result
- else:
- raise ServiceException({'result': 2, 'description': u'系统错误'})
- else:
- raise ServiceException({'result': 2, 'description': u'系统错误'})
- @staticmethod
- def _to_str(data):
- return binascii.unhexlify(data)
- @staticmethod
- def _to_ascii(data):
- return binascii.hexlify(data)
- def _notify_user_service_over(self, managerialOpenId, port, chargeTime, stayTime, money, isPaid=True):
- group = Group.get_group(self.device.get("groupId"))
- notifyData = {
- "title": u"\\n\\n设备编号:\\t\\t{logicalCode}-{port}\\n\\n服务地址:\\t\\t{group}\\n\\n使用时长:\\t\\t{chargeTime}分钟\\n\\n占位时长:\\t\\t{stayTime}分钟\\n\\n本单消费:\\t\\t{money}".format(
- logicalCode=self._device["logicalCode"],
- port=port,
- group=group["address"],
- chargeTime=chargeTime,
- stayTime=stayTime,
- money=str(money),
- ),
- "service": u"已使用账户余额自动结算此次消费" if isPaid else u"您的账户余额已不足以抵扣此次消费,请前往账单中心进行支付",
- "finishTime": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
- "remark": u'谢谢您的支持'
- }
- task_caller(
- func_name='report_to_user_via_wechat',
- openId=managerialOpenId,
- dealerId=self.device.get("ownerId"),
- templateName="service_complete",
- **notifyData
- )
- @staticmethod
- def _parse_event_A1(data):
- return dict()
- @staticmethod
- def _parse_event_A2(data):
- return dict()
- @staticmethod
- def _parse_event_B0(data):
- cardPre = ChargeCabinet._to_str(data[8: 16])
- cardNo = ChargeCabinet._to_str(data[16: 32])
- portStr = str(int(data[32: 34], 16))
- return {
- "cardPre": cardPre,
- "cardNo": cardNo,
- "cardNoHex": data[8: 32], # zjl 16->8
- "portStr": portStr,
- "portHex": data[32: 34] # zjl new
- }
- @staticmethod
- def _parse_event_B1(data):
- cardPre = ChargeCabinet._to_str(data[8: 16])
- cardNo = ChargeCabinet._to_str(data[16: 32])
- portStr = str(int(data[32: 34], 16))
- orderNoHex = data[34: 48]
- orderNo = str(int(reverse_hex(orderNoHex), 16))
- return {
- "cardPre": cardPre,
- "cardNo": cardNo,
- "cardNoHex": data[8: 32], # zjl 16->8
- "portStr": portStr,
- "portHex": data[32:34], # zjl
- "orderNoHex": orderNoHex,
- "orderNo": orderNo
- }
- @staticmethod
- def _parse_event_C0(data):
- orderNoHex = data[8: 22]
- orderNo = str(int(reverse_hex(orderNoHex), 16))
- portStr = str(int(data[22: 24], 16))
- voltage = int(reverse_hex(data[24: 28]), 16)
- power = int(reverse_hex(data[32: 36]), 16)
- elec = int(reverse_hex(data[36: 44]), 16) / 1000.0
- chargeTime = int(reverse_hex(data[44: 48]), 16)
- stayTime = int(reverse_hex(data[48:52]), 16)
- temperature = int(reverse_hex(data[52: 56]), 16)
- status = DefaultParams.STATUS_MAP.get(data[56: 58], Const.DEV_WORK_STATUS_IDLE)
- return {
- "orderNo": orderNo,
- "orderNoHex": orderNoHex,
- "portStr": portStr,
- "voltage": voltage,
- "power": power,
- "elec": elec,
- "chargeTime": chargeTime,
- "temperature": temperature,
- "status": status,
- "stayTime": stayTime
- }
- @staticmethod
- def _parse_event_E0(data):
- portStr = str(int(data[8: 10], 16))
- faultHex = data[10: 14]
- fault = str(int(faultHex[2: 4] + faultHex[:2], 16))
- faultReason = DefaultParams.FAULT_MAP.get(fault)
- return {
- "portHex": data[8: 10],
- "portStr": portStr,
- "faultCode": fault,
- "statusInfo": faultReason
- }
- @staticmethod
- def _parse_event_C1(data):
- orderNoHex = data[8: 22]
- orderNo = str(int(reverse_hex(orderNoHex), 16))
- portHex = data[22: 24]
- portStr = str(int(data[22: 24], 16))
- voltage = int(reverse_hex(data[24: 28]), 16)
- power = int(reverse_hex(data[32: 36]), 16)
- elec = int(reverse_hex(data[36: 44]), 16) / 1000.0
- chargeTime = int(reverse_hex(data[44: 48]), 16)
- stayTime = int(reverse_hex(data[48:52]), 16)
- temperature = int(reverse_hex(data[52: 56]), 16)
- reasonCode = data[56: 58]
- reason = DefaultParams.STOP_REASON_MAP.get(reasonCode)
- return {
- "orderNoHex": orderNoHex,
- "orderNo": orderNo,
- "portHex": portHex,
- "portStr": portStr,
- "voltage": voltage,
- "power": power,
- "elec": elec,
- "chargeTime": chargeTime,
- "temperature": temperature,
- "reasonCode": reasonCode,
- "reason": reason,
- "stayTime": stayTime
- }
- @staticmethod
- def _parse_result_B2(data):
- orderNoHex = data[8: 22]
- orderNo = str(int(reverse_hex(orderNoHex), 16))
- portHex = data[22: 24]
- portStr = str(int(data[22: 24], 16))
- voltage = int(reverse_hex(data[24: 28]), 16)
- power = int(reverse_hex(data[32: 36]), 16)
- elec = int(reverse_hex(data[36: 44]), 16) / 1000.0
- chargeTime = int(reverse_hex(data[44: 48]), 16)
- stayTime = int(reverse_hex(data[48:52]), 16)
- return {
- "orderNoHex": orderNoHex,
- "orderNo": orderNo,
- "portHex": portHex,
- "portStr": portStr,
- "voltage": voltage,
- "power": power,
- "elec": elec,
- "chargeTime": chargeTime,
- "stayTime": stayTime
- }
- @staticmethod
- def _parse_event_CA(data):
- data = data[8: -4]
- result = list()
- while data:
- orderNoHex = data[: 14]
- orderNo = str(int(reverse_hex(data[:14]), 16))
- portStr = str(int(data[14: 16], 16))
- voltage = int(reverse_hex(data[16: 20]), 16)
- power = int(reverse_hex(data[24: 28]), 16)
- elec = int(reverse_hex(data[28: 36]), 16) / 1000.0
- chargeTime = int(reverse_hex(data[36: 40]), 16)
- stayTime = int(reverse_hex(data[40: 44]), 16)
- temperature = int(reverse_hex(data[44: 48]), 16)
- status = DefaultParams.STATUS_MAP.get(data[48: 50], Const.DEV_WORK_STATUS_IDLE)
- data = data[50: ]
- result.append({
- "orderNo": orderNo,
- "orderNoHex": orderNoHex,
- "portStr": portStr,
- "voltage": voltage,
- "power": power,
- "elec": elec,
- "chargeTime": chargeTime,
- "temperature": temperature,
- "status": status,
- "stayTime": stayTime
- })
- return {"subChargeList": result}
- def _start(self, port, orderNo, pw, operate, chargeTime=0xFFFF):
- """
- :param port:
- :param orderNo:
- :param pw:
- :param chargeTime:
- :return:
- """
- orderNoHex = fill_2_hexByte(hex(int(orderNo)), 14, reverse=True)
- portHex = fill_2_hexByte(hex(int(port)), 2, reverse=True)
- chargeTimeHex = fill_2_hexByte(hex(int(chargeTime)), 4, reverse=True)
- operateHex = operate
- pwHex = fill_2_hexByte(hex(int(pw)), 4, reverse=True)
- data = orderNoHex+portHex+chargeTimeHex+operateHex+pwHex
- result = self._send_data("B2", data, timeout=120)
- result.update({"pw": pw})
- return result
- def _open(self, port, orderNo, pw, operate):
- """
- :param port:
- :param orderNo:
- :param pw:
- :return:
- """
- orderNoHex = fill_2_hexByte(hex(int(orderNo)), 14, reverse=True)
- portHex = fill_2_hexByte(hex(int(port)), 2, reverse=True)
- chargeTimeHex = '0000'
- operateHex = operate
- pwHex = fill_2_hexByte(hex(int(pw)), 4, reverse=True)
- data = orderNoHex+portHex+chargeTimeHex+operateHex+pwHex
- result = self._send_data("B2", data, timeout=120)
- result.update({"pw": pw})
- return result
- def _stop(self, port, orderNo, door=True):
- orderNoHex = fill_2_hexByte(hex(int(orderNo)), 14, reverse=True)
- portHex = fill_2_hexByte(hex(int(port)), 2, reverse=True)
- operateHex = "12" if door else "11"
- data = "{}{}0000{}0000".format(orderNoHex, portHex, operateHex)
- result = self._send_data("B2", data)
- return result
- def _get_port_status(self):
- result = self._send_data("B3", "00")
- data = result.get("data", "")[8: -4]
- portInfo = dict()
- while data:
- tempPort = str(int(data[0: 2], 16))
- tempStatus = DefaultParams.STATUS_MAP.get(data[2:4])
- portInfo.update({tempPort: tempStatus})
- data = data[4: ]
- return portInfo
- def _get_port_status_detail(self):
- result = self._send_data("B4", "00")
- data = result.get("data", "")[8: -4]
- portInfo = dict()
- while data:
- tempPort = str(int(data[0: 2], 16))
- tempVoltage = int(reverse_hex(data[2: 6]), 16)
- tempAmpere = int(reverse_hex(data[6:10]), 16) / 1000.0
- tempPower = int(reverse_hex(data[10: 14]), 16)
- tempElec = int(reverse_hex(data[14: 22]), 16) / 1000.0
- tempTime = int(reverse_hex(data[22: 26]), 16)
- tempOccTime = int(reverse_hex(data[26:30]), 16)
- tempTemper = int(reverse_hex(data[30: 34]), 16)
- tempStatus = DefaultParams.STATUS_MAP.get(data[34:36])
- portInfo.update({
- tempPort: {
- "voltage": tempVoltage,
- "elec": tempElec,
- "ampere": tempAmpere,
- "power": tempPower,
- "chargeTime": tempTime,
- "temperature": tempTemper,
- "status": tempStatus,
- "occTime": tempOccTime
- }
- })
- data = data[36: ]
- return portInfo
- def _reboot_device(self):
- return self._send_data("B5", "00")
- def _lock_device(self):
- operateHex = "01"
- return self._send_data("B6", operateHex)
- def _unlock_device(self):
- operateHex = "00"
- return self._send_data("B6", operateHex)
- def _sync_device_time(self):
- nowTime = datetime.datetime.now()
- yearHex = fill_2_hexByte(hex(nowTime.year), 4, reverse=True)
- monthHex = fill_2_hexByte(hex(nowTime.month), 2)
- dayHex = fill_2_hexByte(hex(nowTime.day), 2)
- hourHex = fill_2_hexByte(hex(nowTime.hour), 2)
- minuteHex = fill_2_hexByte(hex(nowTime.minute), 2)
- secondHex = fill_2_hexByte(hex(nowTime.second), 2)
- sendData = yearHex + monthHex + dayHex + hourHex + minuteHex + secondHex + "00"
- self._send_data("A1", sendData=sendData, cmd=DeviceCmdCode.OPERATE_DEV_NO_RESPONSE)
- def _sync_device_settings(self):
- domain = os.environ.get("MY_DOMAIN")
- otherConf = self._device.get("otherConf", dict())
- qr_code_url = concat_user_login_entry_url(l = self._device["logicalCode"])
- snCode = otherConf.get("snCode", self._device["logicalCode"].replace("G", ""))
- minPower = otherConf.get("minPower", DefaultParams.DEFAULT_MIN_POWER)
- maxPower = otherConf.get("maxPower", DefaultParams.DEFAULT_MAX_POWER)
- floatTime = otherConf.get("floatTime", DefaultParams.DEFAULT_FLOAT_TIME)
- ICSetupCode = otherConf.get("ICSetupCode", DefaultParams.DEFAULT_IC_CODE)
- qrCodeLenHex = fill_2_hexByte(hex(len(qr_code_url)), 2)
- minPowerHex = fill_2_hexByte(hex(int(minPower)), 4, reverse=True)
- maxPowerHex = fill_2_hexByte(hex(int(maxPower)), 4, reverse=True)
- floatTimeHex = fill_2_hexByte(hex(int(floatTime)), 4, reverse=True)
- qrCodeHex = self._to_ascii(qr_code_url)
- snCodeHex = self._to_ascii(snCode)
- ICSetupCodeHex = self._to_ascii(ICSetupCode)
- sendData = snCodeHex + minPowerHex + maxPowerHex + floatTimeHex + ICSetupCodeHex + qrCodeLenHex + qrCodeHex
- self._send_data("A2", sendData=sendData, cmd=DeviceCmdCode.OPERATE_DEV_NO_RESPONSE)
- # 添加特性 去掉前台的金额显示按钮
- otherConf.update({"payAfterUse": True})
- Device.objects.filter(devNo=self.device.devNo).update(otherConf=otherConf)
- Device.invalid_device_cache(self.device.devNo)
- def _update_device_conf(self, data):
- minAfterStartCoins = data.get("minAfterStartCoins", DefaultParams.DEFAULT_MIN_START_COINS)
- minPower = data.get("minPower", DefaultParams.DEFAULT_MIN_POWER)
- maxPower = data.get("maxPower", DefaultParams.DEFAULT_MAX_POWER)
- floatTime = data.get("floatTime", DefaultParams.DEFAULT_FLOAT_TIME)
- ICSetupCode = data.get("ICSetupCode", DefaultParams.DEFAULT_IC_CODE)
- actualPortNum = data.get("actualPortNum", DefaultParams.DEFAULT_PORT_NUM)
- chargeType = data.get("chargeType", DefaultParams.DEFAULT_CHARGE_TYPE)
- timeUnitPrice = data.get("timeUnitPrice", DefaultParams.DEFAULT_TIME_UNIT_PRICE)
- stayTimeUnitPrice = data.get("stayTimeUnitPrice", DefaultParams.DEFAULT_STAY_TIME_UNIT_PRICE)
- freeStayTime = data.get("freeStayTime", DefaultParams.DEFAULT_FREE_STAY_TIME)
- minConsume = data.get("minConsume", DefaultParams.DEFAULT_MIN_CONSUME)
- maxConsume = data.get("maxConsume", DefaultParams.DEFAULT_MAX_CONSUME)
- powerPackage = data.get("powerPackage", DefaultParams.DEFAULT_POWER_PACKAGE)
- otherConf = self._device.get("otherConf", {})
- otherConf.update({
- "minAfterStartCoins": int(minAfterStartCoins),
- "minPower": int(minPower),
- "maxPower": int(maxPower),
- "floatTime": int(floatTime),
- "ICSetupCode": ICSetupCode,
- "actualPortNum": int(actualPortNum),
- "chargeType": chargeType,
- "timeUnitPrice": float(timeUnitPrice),
- "stayTimeUnitPrice": float(stayTimeUnitPrice),
- "freeStayTime": float(freeStayTime),
- "minConsume": float(minConsume),
- "maxConsume": float(maxConsume),
- "powerPackage": powerPackage,
- })
- devNo = self._device["devNo"]
- try:
- Device.objects.filter(devNo=devNo).update(otherConf=otherConf)
- except Exception as e:
- logger.error(e)
- raise ServiceException({'result': 2, 'description': u'设置错误,请重新操作试试'})
- Device.invalid_device_cache(devNo)
- def _ack(self, ack_id):
- self._send_data(funCode='AK', sendData=ack_id, cmd=DeviceCmdCode.OPERATE_DEV_NO_RESPONSE)
- def check_order_state(self, openId):
- """
- 通过 openId 以及设备来鉴别 订单
- :param openId:
- :return:
- """
- dealerId = self.device.ownerId
- devTypeCode = self.device.devType.get("code")
- return ClientConsumeModelProxy.get_not_finished_record(ownerId = dealerId,
- openId = openId,
- devTypeCode = devTypeCode)
- def analyze_event_data(self, data):
- cmdCode = data[6:8]
- funcName = "_parse_event_{}".format(cmdCode.upper())
- func = getattr(ChargeCabinet, funcName, None)
- if func and callable(func):
- eventData = func(data)
- eventData.update({"cmdCode": cmdCode})
- return eventData
- else:
- logger.warning("<{}> device receive an undefined cmd <{}>, data is <{}>".format(self.devNo, cmdCode, data))
- def get_dev_setting(self):
- otherConf = self._device.get("otherConf", {})
- return {
- "minAfterStartCoins": otherConf.get("minAfterStartCoins", DefaultParams.DEFAULT_MIN_START_COINS),
- "minPower": otherConf.get("minPower", DefaultParams.DEFAULT_MIN_POWER),
- "maxPower": otherConf.get("maxPower", DefaultParams.DEFAULT_MAX_POWER),
- "floatTime": otherConf.get("floatTime", DefaultParams.DEFAULT_FLOAT_TIME),
- "ICSetupCode": otherConf.get("ICSetupCode", DefaultParams.DEFAULT_IC_CODE),
- "actualPortNum": otherConf.get("actualPortNum", DefaultParams.DEFAULT_PORT_NUM),
- "chargeType": otherConf.get("chargeType", DefaultParams.DEFAULT_CHARGE_TYPE),
- "timeUnitPrice": otherConf.get("timeUnitPrice", DefaultParams.DEFAULT_TIME_UNIT_PRICE),
- "stayTimeUnitPrice": otherConf.get("stayTimeUnitPrice", DefaultParams.DEFAULT_STAY_TIME_UNIT_PRICE),
- "freeStayTime": otherConf.get("freeStayTime", DefaultParams.DEFAULT_FREE_STAY_TIME),
- "minConsume": otherConf.get("minConsume", DefaultParams.DEFAULT_MIN_CONSUME),
- "maxConsume": otherConf.get("maxConsume", DefaultParams.DEFAULT_MAX_CONSUME),
- "powerPackage": otherConf.get("powerPackage", DefaultParams.DEFAULT_POWER_PACKAGE),
- }
- def set_device_function_param(self, request, lastSetConf):
- actualPortNum = request.POST.get("actualPortNum", None)
- if actualPortNum is not None and int(actualPortNum) > 30:
- raise ServiceException({"result": 2, "description": u"实际端口数量最大30"})
- chargeType = request.POST.get("chargeType")
- if chargeType not in ("time", "power"):
- raise ServiceException({"result": 2, "description": u"暂不支持此消费模式"})
- minPower = int(request.POST.get("minPower"))
- maxPower = int(request.POST.get("maxPower"))
- # 校验功率计费套餐
- powerPackage = request.POST.get("powerPackage", None)
- if powerPackage is not None:
- if len(powerPackage) > 3:
- raise ServiceException({"result": 2, "description": u"功率计费不得大于三档"})
- checkNum = None
- for index, item in enumerate(powerPackage):
- tempMin = int(item.get("lowLimit"))
- tempMax = int(item.get("upLimit"))
- if checkNum is not None and checkNum != tempMin:
- raise ServiceException({"result": 2, "description": u"功率计费区间不连续"})
- if tempMin >= tempMax:
- raise ServiceException({"result": 2, "description": u"第{}功率计费区间最小值大于最大值".format(index+1)})
- if tempMin < minPower:
- raise ServiceException({"result": 2, "description": u"第{}功率计费区间最小值小于功率最小值".format(index+1)})
- if tempMax > maxPower:
- raise ServiceException({"result": 2, "description": u"第{}功率计费区间最大值大于功率最大值".format(index+1)})
- # 校验计费套餐
- maxConsume = request.POST.get("maxConsume")
- minConsume = request.POST.get("minConsume")
- if float(minConsume) < 0 or float(maxConsume) < 0:
- raise ServiceException({"result": 2, "description": u"最低消费金额和最高消费金额不能小于0"})
- if float(minConsume) > float(maxConsume):
- raise ServiceException({"result": 2, "description": u"最低消费金额不得大于最高消费金额"})
- self._update_device_conf(request.POST)
- def set_device_function(self, request, lastSetConf):
- lockDevice = request.POST.get("lockDevice", None)
- rebootDevice = request.POST.get("rebootDevice", None)
- setToDevice = request.POST.get("setToDevice", None)
- if rebootDevice is not None:
- self._reboot_device()
- return
- if lockDevice is not None and lockDevice in ("false", "true"):
- lockDevice = json.loads(lockDevice)
- self._lock_device() if lockDevice else self._unlock_device()
- return
- # 下发所有参数到设备,这个地方做一个保护 ,设备正在工作的时候不让设置参数
- actualPortNum = self.device.get("otherConf", dict()).get("actualPortNum")
- if setToDevice is not None:
- devCache = Device.get_dev_control_cache(self._device["devNo"])
- for _key, value in devCache.items():
- if _key.isdigit() and int(_key) > actualPortNum:
- continue
- if isinstance(value, dict) and value.get("status", Const.DEV_WORK_STATUS_IDLE) == Const.DEV_WORK_STATUS_WORKING:
- break
- elif isinstance(value, dict) and value.get("isStart", False):
- break
- else:
- continue
- else:
- return self._sync_device_settings()
- raise ServiceException({'result': 2, 'description': u'设备正在工作中,无法下发参数,请等待设备空闲时设置!'})
- def get_port_status(self, force=False):
- if force:
- self.get_port_status_from_dev()
- devCache = Device.get_dev_control_cache(self._device["devNo"])
- if "allPorts" not in devCache:
- self.get_port_status_from_dev()
- devCache = Device.get_dev_control_cache(self._device["devNo"])
- allPorts = devCache.get("allPorts")
- if allPorts is None:
- raise ServiceException({'result': 2, 'description': u'充电端口信息获取失败'})
- # 获取显示端口的数量 客户要求可以设置 显示给用户多少个端口
- showPortNum = self._device.get("otherConf", {}).get("actualPortNum", DefaultParams.DEFAULT_PORT_NUM)
- statusDict = dict()
- showStatusDict = dict()
- for portNum in xrange(allPorts):
- portStr = str(portNum + 1)
- tempDict = devCache.get(portStr, {})
- if "status" in tempDict:
- statusDict[portStr] = {"status": tempDict["status"]}
- elif "isStart" in tempDict:
- if tempDict["isStart"]:
- statusDict[portStr] = {"status": Const.DEV_WORK_STATUS_WORKING}
- else:
- statusDict[portStr] = {"status": Const.DEV_WORK_STATUS_IDLE}
- else:
- statusDict[portStr] = {"status": Const.DEV_WORK_STATUS_IDLE}
- if int(portStr) <= int(showPortNum):
- showStatusDict[portStr] = {"status": statusDict[portStr]["status"]}
- allPorts, usedPorts, usePorts = self.get_port_static_info(statusDict)
- portsDict = {"allPorts": allPorts, "usedPorts": usedPorts, "usePorts": usePorts}
- Device.update_dev_control_cache(self._device["devNo"], portsDict)
- # 返还的是要显示的端口数量
- return showStatusDict
- def get_port_status_from_dev(self):
- portInfo = self._get_port_status()
- portDict = dict()
- for portStr, status in portInfo.items():
- portDict[portStr] = {"status": status}
- # 更新可用端口数量
- allPorts, usedPorts, usePorts = self.get_port_static_info(portDict)
- Device.update_dev_control_cache(
- self._device["devNo"],
- {
- "allPorts": allPorts,
- "usedPorts": usedPorts,
- "usePorts": usePorts
- }
- )
- # 更新端口状态
- devCache = Device.get_dev_control_cache(self._device["devNo"])
- for port, info in portDict.items():
- if port in devCache and isinstance(info, dict):
- devCache[port].update({"status": info["status"]})
- else:
- devCache[port] = info
- Device.update_dev_control_cache(self._device["devNo"], devCache)
- return portDict
- def start_device(self, package, openId, attachParas):
- portStr = attachParas.get("chargeIndex")
- orderNo = attachParas.get("orderNo")
- if portStr is None:
- raise ServiceException({'result': 2, 'description': u'未知端口'})
- # 发送指令
- pw = self.password
- result = self._start(orderNo=orderNo, port=portStr, pw=pw, operate="02")
- portDict = {
- "status": Const.DEV_WORK_STATUS_WORKING,
- "vCardId": self._vcard_id,
- "isStart": True,
- "openId": openId,
- "orderNo": orderNo,
- "startTime": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
- "pw": pw
- }
- Device.update_dev_control_cache(self._device["devNo"], {str(portStr): portDict})
- otherConf = self.device.get("otherConf") or dict()
- result["consumeOrderNo"] = orderNo
- result["servicedInfo"] = {"pw": pw, "chargeType": otherConf.get("chargeType", DefaultParams.DEFAULT_CHARGE_TYPE)}
- result["finishedTime"] = int(time.time()) + 7 * 24 * 60 * 60
- return result
- def stop(self, port=None):
- """
- 端口停止功能 用户主动停止了该端口
- 对于充电柜的业务来说 结束充电就意味着 需要打开柜门 同时结算订单
- 收到停止指令之后
- 服务器首先下发B2-12指令
- 然后根据返还的信息进行扣费处理
- 最后结存订单
- :param port:
- :return:
- """
- portStr = str(port)
- devCache = Device.get_dev_control_cache(self.device.devNo)
- portCache = devCache.get(portStr, dict())
- # 校验订单状态 非正在运行的订单不能结束 考虑 是否 加锁
- if not portCache:
- return
- if portCache.get("cardNo"):
- raise ServiceException({"result": 2, "description": u"刷卡启动的设备请使用刷卡结束"})
- orderNo = portCache.get("orderNo", "")
- consumeOrder = ConsumeRecord.objects.filter(orderNo=orderNo).first()
- if consumeOrder is None or not consumeOrder.is_running():
- return
- pw = portCache.get("pw")
- openId = portCache.get("openId")
- # 这个时候已经告诉主板停止了
- result = self._start(port, orderNo, pw, "12")
- # 然后去读取主板的的最后一次的数据
- data = result.get("data")
- curInfo = ChargeCabinet._parse_result_B2(data)
- DevicePortReport.create(
- devNo=self.device.devNo,
- port=curInfo.get("portStr"),
- orderNo=curInfo.get("orderNo"),
- openId=openId,
- voltage=curInfo.get("voltage"),
- power=curInfo.get("power"),
- elec=curInfo.get("elec"),
- chargeTime=curInfo.get("chargeTime"),
- stayTime=curInfo.get("stayTime"),
- isBilling=portCache.get("status", Const.DEV_WORK_STATUS_IDLE) == Const.DEV_WORK_STATUS_WORKING
- )
- consumeMoney = Calculater(self.device, consumeOrder).result
- consumeOrder.update(money=RMB(consumeMoney).mongo_amount, coin=VirtualCoin(consumeMoney).mongo_amount)
- consumeOrder.reload()
- consumeOrder.s_to_e()
- consumeDict = {
- "chargeIndex": portStr,
- 'actualNeedTime':curInfo.get("chargeTime"),
- 'elec': curInfo.get("elec"),
- 'stayTime': curInfo.get("stayTime"),
- 'chargeTime': curInfo.get("chargeTime")
- }
- if consumeOrder.servicedInfo and isinstance(consumeOrder.servicedInfo, dict):
- consumeDict.update(consumeOrder.servicedInfo)
- ServiceProgress.update_progress_and_consume_rcd(
- self._device["ownerId"],
- {
- "open_id": consumeOrder.openId,
- "device_imei": self.device["devNo"],
- "port": int(portStr),
- "isFinished": False
- },
- consumeDict
- )
- # 通知用户充电柜业务结束 如果订单并没有使用余额结算 还需要通知用户及时去付款
- try:
- openId = portCache.get("openId")
- user = MyUser.objects.filter(openId=openId, groupId=self.device.get("groupId")).first()
- self._notify_user_service_over(user.managerialOpenId, portStr, curInfo.get("chargeTime"), curInfo.get("stayTime"), consumeMoney, consumeOrder.is_finished())
- except Exception as e:
- logger.exception(e)
- Device.clear_port_control_cache(self.device.devNo, portStr)
- return
- @property
- def isHaveStopEvent(self):
- return True
- def dealer_get_port_status(self):
- showPortNum = self._device.get("otherConf", {}).get("actualPortNum", DefaultParams.DEFAULT_PORT_NUM)
- showStatusDict = dict()
- portInfo = self._get_port_status_detail()
- devCache = Device.get_dev_control_cache(self.device.devNo)
- for port, item in portInfo.items():
- if int(port) > showPortNum:
- continue
- portCache = devCache.get(port, dict())
- item.update(portCache)
- if item.get("status", Const.DEV_WORK_STATUS_IDLE) in (Const.DEV_WORK_STATUS_WORKING, Const.DEV_WORK_STATUS_OCCUPY):
- item["status"] = Const.DEV_WORK_STATUS_WORKING
- item["usedTime"] = item.get("chargeTime")
- showStatusDict[port] = item
- else:
- showStatusDict[port] = {"status": item["status"]}
- return showStatusDict
- def get_current_use(self, order): # type: (ConsumeRecord) -> dict
- group = Group.get_group(order.groupId)
- item = ServiceProgress.objects.filter(
- device_imei=order.devNo,
- open_id=order.openId,
- attachParas__orderNo=order.orderNo,
- isFinished=False
- ).first()
- if not item:
- return dict()
- data = {
- 'startTime': time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(item.start_time)),
- 'order': item.consumeOrder,
- 'address': group.get('address', ''),
- 'groupName': group.get('groupName', ''),
- 'devType': self.device['devType'].get('name'),
- 'devTypeCode': self.device['devType'].get('code'),
- 'logicalCode': self.device['logicalCode'],
- 'status': Const.DEV_WORK_STATUS_WORKING,
- 'devNo': self.devNo,
- "port": item.port
- }
- data.update(DeviceType.get_services_button(self.device['devType']['id']))
- devCache = Device.get_dev_control_cache(self.devNo)
- portCache = devCache.get(str(item.port)) or dict()
- data.update(portCache)
- return data
- def apiOpenCabinetDoor(self, record):
- portStr = record['chargeIndex']
- orderNo = record['orderNo']
- # 发送指令
- pw = self.password
- result = self._open(orderNo=orderNo, port=portStr, pw=pw, operate="03")
- result["consumeOrderNo"] = orderNo
- result["servicedInfo"] = {"pw": pw}
- if result['rst'] == 0:
- result["description"] = u'开门成功'
- else:
- result["description"] = u'开门失败'
- result.pop('cmd')
- result.pop('IMEI')
- result.pop('servicedInfo')
- result.pop('data')
- return result
- def apiStartCharging(self, record):
- portStr = record['chargeIndex']
- orderNo = record['orderNo']
- chargeTime = record['chargeTime']
- # 发送指令
- pw = self.password
- result = self._start(orderNo=orderNo, port=portStr, pw=pw, operate="01", chargeTime=chargeTime)
- result["consumeOrderNo"] = orderNo
- result["servicedInfo"] = {"pw": pw}
- if result['rst'] == 0:
- result["description"] = u'启动成功'
- else:
- result["description"] = u'启动失败'
- result.pop('cmd')
- result.pop('IMEI')
- result.pop('servicedInfo')
- result.pop('data')
- return result
- def apiOpenAndStartCharging(self, record):
- portStr = record['chargeIndex']
- orderNo = record['orderNo']
- chargeTime = record['chargeTime']
- # 发送指令
- pw = self.password
- result = self._start(orderNo=orderNo, port=portStr, pw=pw, operate="02", chargeTime=chargeTime)
- result["consumeOrderNo"] = orderNo
- result["servicedInfo"] = {"pw": pw}
- if result['rst'] == 0:
- result["description"] = u'启动成功'
- else:
- result["description"] = u'启动失败'
- result.pop('cmd')
- result.pop('IMEI')
- result.pop('servicedInfo')
- result.pop('data')
- return result
- def apiGetDevicePortInfo(self, record):
- result = self.get_port_status_from_dev()
- # 0 代表 空闲
- # 1 代表 繁忙
- # 2 代表 故障
- # 10 代表 占位
- return result
- def apiStopChargingWithOpenDoor(self, record):
- portStr = record['chargeIndex']
- orderNo = record['orderNo']
- # 发送指令
- pw = self.password
- result = self._stop(orderNo=orderNo, port=portStr, door=True)
- result["consumeOrderNo"] = orderNo
- result["servicedInfo"] = {"pw": pw}
- if result['rst'] == 0:
- result["description"] = u'停止充电成功'
- else:
- result["description"] = u'停止充电失败'
- result.pop('cmd')
- result.pop('IMEI')
- result.pop('servicedInfo')
- result.pop('data')
- return result
- def apiStopChargingWithCloseDoor(self, record):
- portStr = record['chargeIndex']
- orderNo = record['orderNo']
- # 发送指令
- pw = self.password
- result = self._stop(orderNo=orderNo, port=portStr, door=False)
- result["consumeOrderNo"] = orderNo
- result["servicedInfo"] = {"pw": pw}
- if result['rst'] == 0:
- result["description"] = u'停止充电成功'
- else:
- result["description"] = u'停止充电失败'
- result.pop('cmd')
- result.pop('IMEI')
- result.pop('servicedInfo')
- result.pop('data')
- return result
- def apiGetPortInfoYwt(self, record):
- return self._get_port_status_detail()
|