123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933 |
- # -*- coding: utf-8 -*-
- # !/usr/bin/env python
- import datetime
- import logging
- import time
- import uuid
- import re
- from decimal import Decimal
- from apilib.monetary import RMB
- from apilib.utils_datetime import timestamp_to_dt, to_datetime
- from bson import ObjectId
- from apps.web.constant import MQTT_TIMEOUT, DeviceCmdCode, Const
- from apps.web.common.models import TempValues
- from apps.web.core.adapter.base import SmartBox, fill_2_hexByte, start_error_timer
- from apps.web.core.exceptions import ServiceException
- from apps.web.core.networking import MessageSender
- from apps.web.dealer.models import Dealer
- from apps.web.device.models import Device, Group
- from apps.web.user.models import MyUser, Card
- from taskmanager.mediator import task_caller
- logger = logging.getLogger(__name__)
- class ChargingCY6Box(SmartBox):
- def __init__(self, device):
- super(ChargingCY6Box, self).__init__(device)
- @staticmethod
- def encode_str(data, length=2, ratio=1.0, base=16):
- # type:(any,int,float,int) -> str
- if not isinstance(data, Decimal):
- data = Decimal(data)
- if not isinstance(length, str):
- length = str(length)
- if not isinstance(ratio, Decimal):
- ratio = Decimal(ratio)
- end = 'X' if base == 16 else 'd'
- encodeStr = '%.' + length + end
- encodeStr = encodeStr % (data * ratio)
- return encodeStr
- @staticmethod
- def transform_password(password):
- passwordHex = ''
- while password:
- passwordHex += fill_2_hexByte(hex(int(password[: 2])), 2)
- password = password[2:]
- return passwordHex
- @staticmethod
- def check_params_range(params, minData=None, maxData=None, desc=''):
- # type:(str,float,float,str) -> str
- '''
- 检查参数,返回字符串参数
- '''
- if params is None:
- raise ServiceException({'result': 2, 'description': u'参数错误.'})
- if not isinstance(params, Decimal):
- params = Decimal(params)
- if not minData and maxData:
- if not isinstance(maxData, Decimal):
- maxData = Decimal(maxData)
- if params <= maxData:
- return '%g' % params
- else:
- raise ServiceException({'result': 2, 'description': u'%s超出可选范围,可选最大值为%g' % (desc, maxData)})
- if not maxData and minData:
- if not isinstance(minData, Decimal):
- minData = Decimal(minData)
- if minData <= params:
- return '%g' % params
- else:
- raise ServiceException({'result': 2, 'description': u'%s超出可选范围,可选最小值为%g' % (desc, minData)})
- if not minData and not maxData:
- return '%g' % params
- else:
- if not isinstance(minData, Decimal):
- minData = Decimal(minData)
- if not isinstance(maxData, Decimal):
- maxData = Decimal(maxData)
- if minData <= params <= maxData:
- return '%g' % params
- else:
- raise ServiceException(
- {'result': 2, 'description': u'%s参数超出可选范围,可取范围为%g-%g' % (desc, minData, maxData)})
- def __check_device_uart_status(self, devInfo):
- if devInfo['rst'] != 0:
- if devInfo['rst'] == -1:
- raise ServiceException({'result': 2, 'description': u'充电桩正在玩命找网络,请稍候再试'})
- elif devInfo['rst'] == 1:
- raise ServiceException({'result': 2, 'description': u'充电桩主板连接故障'})
- else:
- raise ServiceException({'result': 2, 'description': u'系统错误'})
- def _ack(self, ack_id):
- MessageSender.send(device=self.device, cmd=DeviceCmdCode.OPERATE_DEV_NO_RESPONSE, payload={
- 'IMEI': self.device.devNo,
- 'funCode': 'AK',
- 'data': ack_id
- }, timeout=15)
- def start_device(self, package, openId, attachParas):
- if attachParas is None or 'chargeIndex' not in attachParas:
- raise ServiceException({'result': 2, 'description': u'请您选择合适的端口'})
- rechargeRcdId = str(attachParas.get('linkedRechargeRecordId', ''))
- price = float(package['price'])
- coins = float(package['coins'])
- hexCoins = fill_2_hexByte(hex(int(coins * 100)), 4)
- hexReserveByte = '0000'
- port = hex(int(attachParas['chargeIndex']))
- hexPort = fill_2_hexByte(port, 2)
- devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {
- 'IMEI': self._device['devNo'],
- 'funCode': 'D2',
- 'data': hexCoins + hexReserveByte + hexPort
- }, timeout=15)
- self.__check_device_uart_status(devInfo)
- data = devInfo['data']
- if data[6: 8] != '4F':
- raise ServiceException({'result': 2, 'description': u'启动端口失败,您的金币还在,您重新启动试试看'})
- devCache = Device.get_dev_control_cache(self._device["devNo"])
- portCache = devCache.get(str(attachParas['chargeIndex']))
- start_timestamp = int(time.time())
- devInfo['finishedTime'] = start_timestamp + 12 * 60 * 60
- if portCache is not None and portCache.get('status', '') == Const.DEV_WORK_STATUS_WORKING and portCache.get('openId') == openId:
- payInfo = portCache.get("payInfo", list())
- if not payInfo:
- logger.error("miss payInfo! {}-{}".format(self._device["devNo"], str(attachParas['chargeIndex'])))
- payInfo.append({
- "vCardId": self._vcard_id,
- "coins": float(coins),
- "price": float(price),
- "rechargeRcdId": rechargeRcdId,
- "needTime": 0,
- })
- coins = portCache.get("coins") + float(coins)
- price = portCache.get("price") + float(price)
- cacheDict = {
- "startTime": portCache.get("startTime", ""),
- "status": Const.DEV_WORK_STATUS_WORKING,
- 'finishedTime': devInfo['finishedTime'],
- "coins": coins,
- "price": price,
- "openId": openId,
- 'waitD9': True,
- 'port': str(attachParas['chargeIndex']),
- 'payType': '01'
- }
- if rechargeRcdId != '':
- cacheDict.update({'payInfo': payInfo})
- else:
- cacheDict = {
- "startTime": timestamp_to_dt(start_timestamp).strftime("%Y-%m-%d %H:%M:%S"),
- "status": Const.DEV_WORK_STATUS_WORKING,
- 'finishedTime': devInfo['finishedTime'],
- "coins": float(coins),
- "price": float(price),
- "openId": openId,
- "consumeType": "mobile",
- 'waitD9': True,
- 'port': str(attachParas['chargeIndex']),
- 'payType': '01'
- }
- if rechargeRcdId != '':
- cacheDict.update({'payInfo': [{
- "vCardId": self._vcard_id,
- "coins": float(coins),
- "price": float(price),
- "rechargeRcdId": rechargeRcdId,
- "needTime": 0,
- }]})
- Device.update_dev_control_cache(self._device["devNo"], {str(attachParas['chargeIndex']): cacheDict})
- if openId:
- devInfo['rechargeRcdId'] = rechargeRcdId
- return devInfo
- def get_port_status(self, force=False):
- '''
- 获取设备状态 昌原的状态都是被动获取的
- :param force:
- :return:
- '''
- MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_NO_RESPONSE, {
- 'IMEI': self._device['devNo'],
- 'funCode': 'E1',
- 'data': '0000'
- }, timeout=15)
- # 不修改100267的驱动基础上做延时处理
- time.sleep(1)
- devCache = Device.get_dev_control_cache(self._device['devNo'])
- statusDict = dict()
- allPorts = devCache.get('allPorts', 10)
- for portNum in range(allPorts):
- tempDict = devCache.get(str(portNum + 1), {})
- if 'status' in tempDict:
- statusDict[str(portNum + 1)] = {'status': tempDict.get('status')}
- elif 'isStart' in tempDict:
- if tempDict['isStart']:
- statusDict[str(portNum + 1)] = {'status': Const.DEV_WORK_STATUS_WORKING}
- else:
- statusDict[str(portNum + 1)] = {'status': Const.DEV_WORK_STATUS_IDLE}
- else:
- statusDict[str(portNum + 1)] = {'status': Const.DEV_WORK_STATUS_IDLE}
- allPorts, usedPorts, usePorts = self.get_port_static_info(statusDict)
- Device.update_dev_control_cache(self._device['devNo'],
- {'allPorts': allPorts, 'usedPorts': usedPorts, 'usePorts': usePorts})
- return statusDict
- def get_port_status_from_dev(self):
- return self.get_port_status(False)
- def _async_card_balance(self, cardType, cardNo, asyncMoney):
- """
- 同步卡内余额
- :param cardType:
- :param cardNo:
- :param asyncMoney:
- :return:
- """
- # 如果是预付费的卡 同步的金额需要变换为分
- balance = asyncMoney if cardType == '00' else asyncMoney * 100
- # 获取随机流水号
- sidKey = '{}-{}'.format(self.device.devNo, cardNo)
- sid = TempValues.get(sidKey)
- balanceHex = self.encode_str(int(balance), length=6)
- sidHex = self.encode_str(sid, length=4)
- MessageSender.send(device=self.device, cmd=DeviceCmdCode.OPERATE_DEV_NO_RESPONSE, payload={
- 'IMEI': self.device.devNo,
- 'funCode': 'D3',
- 'data': cardType + balanceHex + sidHex + cardNo
- })
- def get_dev_setting(self):
- devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {
- 'IMEI': self._device['devNo'],
- 'funCode': 'D0',
- 'data': '00'
- }, timeout=15)
- self.__check_device_uart_status(devInfo)
- data = devInfo['data'][6:]
- powerTime1 = str(int(data[0:4], 16))
- powerTime2 = str(int(data[4:8], 16))
- powerTime3 = str(int(data[8:12], 16))
- powerTime4 = str(int(data[12:16], 16))
- power1 = str(int(data[16:20], 16))
- power2 = str(int(data[20:24], 16))
- power3 = str(int(data[24:28], 16))
- power4 = str(int(data[28:32], 16))
- noloadPower = str(int(data[32:34], 16))
- noloadTime = str(int(data[34:36], 16))
- volume = str(int(data[36:38], 16))
- cardFee = str(float(int(data[38:42], 16)) / 100)
- floatPower = str(int(data[42:44], 16))
- floatTime = str(int(data[44:48], 16))
- cardFree = False if data[48:50] == u'00' else True
- powerTime5 = str(int(data[50:54], 16))
- powerTime6 = str(int(data[54:58], 16))
- power5 = str(int(data[58:62], 16))
- power6 = str(int(data[62:66], 16))
- elecPrice = str(float(int(data[66:68], 16)) / 100)
- consumeTypeStr = data[68:70]
- cardRefund = False if data[70:72] == u'00' else True
- if consumeTypeStr == u'00':
- consumeType = 'elec'
- elif consumeTypeStr == u'01':
- consumeType = 'power'
- elif consumeTypeStr == u'02':
- consumeType = 'time'
- else:
- consumeType = 'free'
- devCache = Device.get_dev_control_cache(self._device['devNo'])
- temperature = devCache.get('temperature', '获取中...')
- disable = self.device.get('otherConf', {}).get('disableDevice', False)
- needBindCard = self.device.get("otherConf", {}).get('needBindCard', True)
- vCardTime = self.device.get("otherConf", {}).get('vCardTime', 300)
- return {
- 'noloadPower': noloadPower,
- 'noloadTime': noloadTime,
- 'cardFee': cardFee,
- 'temperature': temperature,
- 'elecPrice': elecPrice,
- 'power5': power5,
- 'power6': power6,
- 'power4': power4,
- 'power3': power3,
- 'power2': power2,
- 'power1': power1,
- 'vCardTime': vCardTime,
- 'disable': disable,
- 'volume': volume,
- 'needBindCard': needBindCard,
- 'powerTime1': powerTime1,
- 'powerTime2': powerTime2,
- 'powerTime3': powerTime3,
- 'powerTime4': powerTime4,
- 'powerTime5': powerTime5,
- 'powerTime6': powerTime6,
- 'floatTime': floatTime,
- 'floatPower': floatPower,
- 'cardFree': cardFree,
- 'consumeType': consumeType,
- 'cardRefund': cardRefund
- }
- def _set_password(self, password):
- """
- 设置设备的小区密码
- 密码是否还需要再校验,以及是否是0开头
- """
- if not password.isdigit():
- raise ServiceException({'result': '2', 'description': u'密码必须必须为0-9数字'})
- if len(password) != 10:
- raise ServiceException({'result': 0, 'description': u'密码长度必须为10位'})
- passwordHex = self.transform_password(password)
- devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {
- 'IMEI': self._device['devNo'],
- 'funCode': 'DB',
- 'data': passwordHex
- }, timeout=15)
- self.__check_device_uart_status(devInfo)
- if 'data' not in devInfo:
- raise ServiceException({'result': '2', 'description': u'设置小区密码失败,请重新试试'})
- return devInfo
- def _set_send_card(self, oldPassword, newPassword, FaKacardType):
- '''
- 设置卡机模式 用于重置 实体卡的小区密码
- '''
- if not oldPassword.isdigit() or not newPassword.isdigit():
- raise ServiceException({'result': '2', 'description': u'密码必须必须为0-9数字'})
- if len(oldPassword) != 10 or len(newPassword) != 10:
- raise ServiceException({'result': 0, 'description': u'密码长度必须为10位'})
- if not FaKacardType:
- raise ServiceException({'result': 0, 'description': u'请选择要发行卡的类型'})
- oldPasswordHex = self.transform_password(oldPassword)
- newPasswordHex = self.transform_password(newPassword)
- FaKacardType = self.encode_str(FaKacardType)
- devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {
- 'IMEI': self._device['devNo'],
- 'funCode': 'DC',
- 'data': oldPasswordHex + newPasswordHex + FaKacardType
- }, timeout=15)
- self.__check_device_uart_status(devInfo)
- if 'data' not in devInfo:
- raise ServiceException({'result': '2', 'description': u'设置发卡机模式失败,请重新试试'})
- return devInfo
- def _set_elec_price(self, elecPrice):
- """
- 设置电量单价 这个参数是模块侧的 只下发到模块驱动 不到主板
- :param elecPrice:
- :return:
- """
- elecPriceHex = "{:0>8X}".format(int(3600 * 1000 * float(elecPrice)))
- devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {
- 'IMEI': self._device['devNo'],
- 'funCode': 'EP',
- 'data': elecPriceHex
- }, timeout=15)
- self.__check_device_uart_status(devInfo)
- # 更新参数设置
- Device.get_collection().update_one({'devNo': self.device['devNo']}, {'$set': {'otherConf.elecPrice': elecPrice}})
- Device.invalid_device_cache(self.device.devNo)
- def _reboot_device(self):
- devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {
- 'IMEI': self._device['devNo'],
- 'funCode': 'D5',
- 'data': '0000'
- }, timeout=15)
- self.__check_device_uart_status(devInfo)
- if 'data' not in devInfo:
- raise ServiceException({'result': '2', 'description': u'设备复位错误,请重新试试'})
- return devInfo
- def set_dev_disable(self, disable):
- if disable:
- status = '00AA'
- else:
- status = '0055'
- devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {
- 'IMEI': self._device['devNo'],
- 'funCode': 'DD',
- 'data': status
- }, timeout=15)
- self.__check_device_uart_status(devInfo)
- if 'data' not in devInfo:
- raise ServiceException({'result': '2', 'description': u'设备停用错误,请联系厂商协助解决'})
- otherConf = self._device.get('otherConf', {})
- otherConf['disableDevice'] = disable
- Device.objects.filter(devNo=self._device['devNo']).update(otherConf=otherConf)
- Device.invalid_device_cache(self._device['devNo'])
- def _set_all_settings(self, settings):
- powerTime1 = settings.get('powerTime1')
- powerTime2 = settings.get('powerTime2')
- powerTime3 = settings.get('powerTime3')
- powerTime4 = settings.get('powerTime4')
- power1 = settings.get('power1')
- power2 = settings.get('power2')
- power3 = settings.get('power3')
- power4 = settings.get('power4')
- noloadPower = settings.get('noloadPower')
- noloadTime = settings.get('noloadTime')
- volume = settings.get('volume')
- cardFee = settings.get('cardFee')
- floatPower = settings.get('floatPower')
- floatTime = settings.get('floatTime')
- cardFree = settings.get('cardFree')
- powerTime5 = settings.get('powerTime5')
- powerTime6 = settings.get('powerTime6')
- power5 = settings.get('power5')
- power6 = settings.get('power6')
- elecPrice = settings.get('elecPrice')
- consumeType = settings.get('consumeType')
- cardRefund = settings.get('cardRefund')
- #
- powerTime1 = self.check_params_range(params=powerTime1, minData=0, maxData=999, desc='第1段功率时间')
- powerTime2 = self.check_params_range(params=powerTime2, minData=0, maxData=999, desc='第2段功率时间')
- powerTime3 = self.check_params_range(params=powerTime3, minData=0, maxData=999, desc='第3段功率时间')
- powerTime4 = self.check_params_range(params=powerTime4, minData=0, maxData=999, desc='第4段功率时间')
- power1 = self.check_params_range(params=power1, minData=0, maxData=999, desc='第1段功率值')
- power2 = self.check_params_range(params=power2, minData=0, maxData=999, desc='第2段功率值')
- power3 = self.check_params_range(params=power3, minData=0, maxData=999, desc='第3段功率值')
- power4 = self.check_params_range(params=power4, minData=0, maxData=999, desc='第4段功率值')
- noloadPower = self.check_params_range(params=noloadPower, minData=0, maxData=50, desc='空载检测功率')
- noloadTime = self.check_params_range(params=noloadTime, minData=0, maxData=255, desc='空载功率检测时间')
- volume = self.check_params_range(params=volume, minData=0, maxData=8, desc='音量')
- cardFee = self.check_params_range(params=cardFee, minData=0, maxData=655, desc='预付卡预扣金额')
- floatPower = self.check_params_range(params=floatPower, minData=0, maxData=50, desc='浮动功率')
- floatTime = self.check_params_range(params=floatTime, minData=0, maxData=60000, desc='浮动功率延长时间')
- powerTime5 = self.check_params_range(params=powerTime5, minData=0, maxData=999, desc='第5段功率时间')
- powerTime6 = self.check_params_range(params=powerTime6, minData=0, maxData=999, desc='第6段功率时间')
- power5 = self.check_params_range(params=power5, minData=0, maxData=999, desc='第5段功率值')
- power6 = self.check_params_range(params=power6, minData=0, maxData=999, desc='第6段功率值')
- elecPrice = self.check_params_range(params=elecPrice, minData=0, maxData=2.5, desc='电价')
- if consumeType == 'elec':
- consumeTypeStr = '00'
- elif consumeType == 'power':
- consumeTypeStr = '01'
- elif consumeType == 'time':
- consumeTypeStr = '02'
- elif consumeType == 'free':
- consumeTypeStr = '03'
- else:
- consumeTypeStr = '00'
- data = ''
- data += self.encode_str(powerTime1, length=4)
- data += self.encode_str(powerTime2, length=4)
- data += self.encode_str(powerTime3, length=4)
- data += self.encode_str(powerTime4, length=4)
- data += self.encode_str(power1, length=4)
- data += self.encode_str(power2, length=4)
- data += self.encode_str(power3, length=4)
- data += self.encode_str(power4, length=4)
- data += self.encode_str(noloadPower, length=2)
- data += self.encode_str(noloadTime, length=2)
- data += self.encode_str(volume, length=2)
- data += self.encode_str(cardFee, length=4, ratio=100)
- data += self.encode_str(floatPower, length=2)
- data += self.encode_str(floatTime, length=4)
- data += "AA" if cardFree is True else "00"
- data += self.encode_str(powerTime5, length=4)
- data += self.encode_str(powerTime6, length=4)
- data += self.encode_str(power5, length=4)
- data += self.encode_str(power6, length=4)
- data += self.encode_str(elecPrice, length=2, ratio=100)
- data += consumeTypeStr
- data += "01" if cardRefund is True else "00"
- devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {
- 'IMEI': self._device['devNo'],
- 'funCode': 'D1',
- 'data': data
- }, timeout=15)
- self.__check_device_uart_status(devInfo)
- if 'data' not in devInfo:
- raise ServiceException({'result': '2', 'description': u'设置设备参数错误,请联系经销商协助解决'})
- return devInfo
- def set_device_function_param(self, request, lastSetConf):
- """设备设备的参数"""
- if "pwd" in request.POST:
- return self._set_password(request.POST["pwd"])
- if "old_pwd" in request.POST:
- old_pwd = request.POST["old_pwd"]
- new_pwd = request.POST["new_pwd"]
- cardType = request.POST["FaKacardType"]
- return self._set_send_card(old_pwd, new_pwd, cardType)
- # 卡券启动时间
- if 'vCardTime' in request.POST:
- vCardTime = int(request.POST.get('vCardTime'))
- if vCardTime != int(self.device['otherConf'].get('vCardTime', 300)):
- Device.get_collection().update_one({'devNo': self.device['devNo']},
- {'$set': {'otherConf.vCardTime': vCardTime}})
- Device.invalid_device_cache(self.device.devNo)
- # 对一下参数的设置
- new_settings = dict()
- for _paramKey, _paramValue in lastSetConf.items():
- if request.POST.get(_paramKey) is not None:
- _paramValue = request.POST[_paramKey]
- new_settings[_paramKey] = _paramValue
- cardFree = "AA" if new_settings["cardFree"] else "00"
- new_settings.update({"cardFree": cardFree})
- self._set_all_settings(new_settings)
- def set_device_function(self, request, lastSetConf):
- """开关类参数配置"""
- if 'disable' in request.POST:
- return self.set_dev_disable(request.POST.get('disable'))
- if 'reboot' in request.POST:
- return self._reboot_device()
- if 'cardFree' in request.POST:
- cardFree = request.POST["cardFree"]
- lastSetConf.update({"cardFree": cardFree})
- return self._set_all_settings(lastSetConf)
- if 'cardRefund' in request.POST:
- cardRefund = request.POST["cardRefund"]
- lastSetConf.update({'cardRefund': cardRefund})
- return self._set_all_settings(lastSetConf)
- if 'needBindCard' in request.POST:
- needBindCard = request.POST.get('needBindCard')
- otherConf = self.device.get('otherConf', dict())
- otherConf.update({'needBindCard': needBindCard})
- Device.objects.get(devNo=self.device.devNo).update(otherConf=otherConf)
- Device.invalid_device_cache(self.device.devNo)
- def analyze_event_data(self, data):
- cmdCode = data[2:4]
- if cmdCode == 'D8':
- tempData = data[6:170]
- portStatusData = tempData[0:20]
- portPowerData = tempData[20:60]
- portLeftMoneyData = tempData[60:100]
- portErrorData = tempData[100:120]
- temperature = tempData[120:124]
- portSpendElecData = tempData[124:164]
- portInfo = {}
- for _ in range(10):
- currentPortStatusData = portStatusData[(_ * 2):(_ + 1) * 2]
- if currentPortStatusData == '00':
- tempPortStatusData = Const.DEV_WORK_STATUS_IDLE
- elif currentPortStatusData in ['01', '11']:
- tempPortStatusData = Const.DEV_WORK_STATUS_WORKING
- else:
- tempPortStatusData = Const.DEV_WORK_STATUS_FAULT
- currentPortErrorMessage = portErrorData[(_ * 2):(_ + 1) * 2]
- if currentPortErrorMessage == '00':
- tempPortErrorMessage = 'normal'
- elif currentPortErrorMessage == '01':
- tempPortErrorMessage = 'elecRelayAdhesion'
- tempPortStatusData = Const.DEV_WORK_STATUS_FAULT
- else:
- tempPortErrorMessage = 'unknownError'
- tempPortStatusData = Const.DEV_WORK_STATUS_FAULT
- portInfo[str(_ + 1)] = {'status': tempPortStatusData}
- portInfo[str(_ + 1)].update({'power': str(int(portPowerData[(_ * 4):(_ + 1) * 4], 16))})
- portInfo[str(_ + 1)].update({'leftMoney': str(float(int(portLeftMoneyData[(_ * 4):(_ + 1) * 4], 16)) / 100)})
- portInfo[str(_ + 1)].update({'errorMessage': tempPortErrorMessage})
- portInfo[str(_ + 1)].update({'spendElec': str(float(int(portSpendElecData[(_ * 4):(_ + 1) * 4], 16)) / 100)})
- # 首先依据上报的状态获取已使用未使用端口数量
- allPorts, usedPorts, usePorts = self.get_port_static_info(portInfo)
- devCache = Device.get_dev_control_cache(self.device.devNo) or dict()
- for portStr, value in devCache.items():
- if not portStr.isdigit() or not isinstance(value, dict):
- continue
- # 更新每个端口的信息
- tempPortInfo = portInfo.get(portStr, dict())
- value.update(tempPortInfo)
- devCache[portStr] = value
- devCache['temperature'] = ('+' if temperature[0:2] == '00' else '-') + str(int(temperature[2:4], 16)) + ' degrees'
- devCache['allPorts'] = allPorts
- devCache['usedPorts'] = usedPorts
- devCache['usePorts'] = usePorts
- Device.update_dev_control_cache(self.device.devNo, devCache)
- return {}
- elif cmdCode == 'DA':
- tempData = data[6:18]
- port = str(int(tempData[0:2], 16))
- reasonCode = tempData[2:4]
- if reasonCode == '01':
- reason = '设备充满自停或拔掉插头'
- elif reasonCode == '02':
- reason = '超功率停止'
- elif reasonCode == '03':
- reason = '时间用完停止'
- elif reasonCode == '04':
- reason = '远程停止'
- elif reasonCode == '05':
- reason = '预付卡的扣费金额用完'
- else:
- reason = '电量超限'
- spendElec = str(float(int(tempData[4:8], 16)) / 100)
- leftMoney = str(float(int(tempData[8:12], 16)) / 100)
- return {'cmdCode': cmdCode, 'port': port, 'reason': reason, 'spendElec': spendElec, 'leftMoney': leftMoney}
- elif cmdCode == 'D9':
- power = str(int(data[20:24], 16))
- coins = float(int(data[24:28], 16)) / 100
- port = str(int(data[28:30], 16))
- payType = data[30:32]
- if payType == '00': # 次卡
- cardNo = data[6:14]
- cardType = '00'
- cardBalance = str(int(data[14:20], 16))
- needTime = int(data[32:36], 16)
- elif payType == '01': # 扫码
- needTime = int(data[32:36], 16)
- elif payType == '02': # 投币
- needTime = int(data[32:36], 16)
- elif payType == '03': # 预付卡
- cardNo = data[6:14]
- cardType = '01'
- cardBalance = str(float(int(data[14:20], 16)) / 100)
- leftMoney = str(float(int(data[32:36], 16)) / 100)
- else:
- pass
- return locals()
- elif cmdCode == 'D4':
- cardType = data[6:8]
- cardNo = data[8:16]
- cardBalance = RMB(int(data[16:22], 16))
- if cardType == '01':
- cardBalance = cardBalance * 0.01
- return {
- "cardType": cardType,
- "cardNo": cardNo,
- "cardBalance": cardBalance,
- 'cmdCode': cmdCode
- }
- elif cmdCode == 'D3':
- cardType = data[6:8]
- cardNo = data[8:16]
- cardBalance = RMB(int(data[16:22], 16))
- result = True if data[22:24] == 'AA' else False
- sid = int(data[24:28], 16)
- if cardType == '01':
- cardBalance = cardBalance * 0.01
- return {
- "cardType": cardType,
- "cardNo": cardNo,
- "cardBalance": cardBalance,
- "result": result,
- "sid": sid,
- 'cmdCode': cmdCode
- }
- elif cmdCode == 'D7':
- return {'data': data[6:8], 'cmdCode': cmdCode}
- elif cmdCode == 'DE':
- cardNo = data[6:14]
- beforeRefund = float(int(data[14:20], 16)) / 100.0
- refund = float(int(data[20:24], 16)) / 100.0
- afterRefund = float(int(data[24:30], 16)) / 100.0
- return {'cardNo': cardNo, 'beforeRefund': beforeRefund, 'refund': refund, 'afterRefund': afterRefund, 'cmdCode': cmdCode}
- @property
- def isHaveStopEvent(self):
- return True
- def stop(self, port=None):
- if not port:
- raise ServiceException({"result": "2", "description": u"请选择停止端口!"})
- self.stop_charging_port(port)
- def stop_charging_port(self, port):
- portHex = fill_2_hexByte(hex(int(port)), 2)
- devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {
- 'IMEI': self._device['devNo'],
- 'funCode': 'D6',
- 'data': portHex
- }, timeout=15)
- self.__check_device_uart_status(devInfo)
- data = devInfo.get('data')
- if data[6: 8] != '4F':
- raise ServiceException({'result': 2, 'description': u'停止充电失败,请重新试试'})
- # 这里只下发命令 不清理端口缓存,等上报事件清除
- # Device.clear_port_control_cache(self.device.devNo, int(port))
- def check_dev_status(self, attachParas = None):
- pass
- def get_port_info(self, port):
- '''
- 获取 端口的详细信息
- :param port:
- :return:
- '''
- time.sleep(2)
- data = fill_2_hexByte(hex(int(port)), 2)
- devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {
- 'IMEI': self._device['devNo'],
- 'funCode': 'E0',
- 'data': '00' + data
- }, timeout=15)
- self.__check_device_uart_status(devInfo)
- data = devInfo['data'][6::]
- line = str(int(data[0:2], 16))
- lineStatus = str(int(data[2:4], 16))
- power = str(int(data[4:8], 16))
- leftMoney = str(float(int(data[8:12], 16)) / 100)
- temperatureStr = data[12:16]
- temperature = ('+' if temperatureStr[0:2] == '00' else '-') + str(int(temperatureStr[2:4], 16)) + ' degrees'
- spendElec = str(float(int(data[16:20], 16)) / 100)
- errorCode = data[20:22]
- return {'port': line, 'portStatus': lineStatus, 'power': power, 'leftMoney': leftMoney, 'temperature': temperature, 'spendElec': spendElec, 'errorCode': errorCode}
- def active_deactive_port(self, port, active):
- if not active:
- self.stop_charging_port(port)
- else:
- raise ServiceException({'result': 2, 'description': u'此设备不支持直接打开端口'})
- def format_port_using_detail(self, detailDict):
- portData = {}
- startTimeStr = detailDict.get('startTime', None)
- if startTimeStr is not None and "usedTime" not in detailDict:
- startTime = to_datetime(startTimeStr)
- usedTime = int(round((datetime.datetime.now() - startTime).total_seconds() / 60.0))
- portData['usedTime'] = usedTime
- elif detailDict.get("usedTime"):
- usedTime = detailDict.get("usedTime")
- portData['usedTime'] = usedTime
- else:
- usedTime = None
- if detailDict.has_key('needTime'):
- if detailDict['needTime'] == 999:
- portData['needTime'] = u'充满自停'
- else:
- portData['needTime'] = detailDict['needTime']
- if detailDict.has_key('leftTime') and (usedTime > 0):
- if detailDict['leftTime'] == 65535:
- portData['leftTime'] = 65535
- detailDict['usedTime'] = 0
- detailDict['actualNeedTime'] = 0
- else:
- portData['actualNeedTime'] = int(detailDict['leftTime']) + int(usedTime)
- if detailDict.has_key('needTime') and portData['actualNeedTime'] > detailDict['needTime']:
- portData['actualNeedTime'] = portData['needTime']
- portData['leftTime'] = detailDict['leftTime']
- if detailDict.has_key('coins'):
- portData['leftMoney'] = detailDict['leftMoney']
- portData['consumeMoney'] = str(float(detailDict['price']) - float(detailDict['leftMoney']))
- elif detailDict.has_key('leftTime'):
- portData['leftTime'] = detailDict['leftTime']
- if (not detailDict.has_key('leftTime')) and (usedTime is not None):
- if detailDict.has_key('needTime'):
- portData['leftTime'] = detailDict['needTime'] - usedTime
- if detailDict.has_key('coins') and float(detailDict['coins']) != 0:
- portData['leftMoney'] = detailDict['leftMoney']
- portData['consumeMoney'] = str(float(detailDict['price']) - float(detailDict['leftMoney']))
- if detailDict.has_key('openId'):
- user = MyUser.objects(openId=detailDict['openId'], groupId=self.device.groupId).first()
- if user:
- portData['nickName'] = user.nickname
- if detailDict.has_key('cardId'):
- if not detailDict.has_key('consumeType'):
- portData['consumeType'] = 'card'
- card = Card.objects.get(id=ObjectId(detailDict['cardId']))
- if card.cardName:
- portData['cardName'] = card.cardName
- portData['cardNo'] = card.cardNo
- # 注意,如果是IC卡,不支持余额回收,这里也不要显示出来
- if card.cardType == 'IC' and portData.has_key('leftMoney'):
- portData.pop('leftMoney')
- elif detailDict.has_key('openId') and (not detailDict.has_key('consumeType')):
- if detailDict.get('vCardId'):
- portData['consumeType'] = 'mobile_vcard'
- else:
- portData['consumeType'] = 'mobile'
- elif detailDict.has_key('consumeType') and detailDict['consumeType'] == 'coin':
- portData['consumeType'] = 'coin' # 硬币的都无法退费
- if portData.has_key('leftMoney'):
- portData.pop('leftMoney')
- # 做个特殊处理
- if portData.has_key('needTime'):
- if portData['needTime'] == '999' or portData['needTime'] == '充满自停':
- portData['needTime'] = u'充满自停'
- else:
- portData['needTime'] = u'%s分钟' % portData['needTime']
- # 如果剩余时间为65535,表示未接插头
- if portData.has_key('leftTime') and portData['leftTime'] == 65535:
- portData['leftTime'] = u'(线路空载)'
- portData['usedTime'] = 0
- portData['needTime'] = 0
- detailDict.update(portData)
- for k, v in detailDict.items():
- if v < 0:
- detailDict.pop(k)
- # 因为前台显示的开始时间如果带年,就显示不下,这里做个切割
- if detailDict.has_key('startTime') and detailDict['startTime'].count('-') == 2:
- detailDict['startTime'] = to_datetime(detailDict['startTime']).strftime('%m-%d %H:%M:%S')
- return detailDict
|