12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886 |
- # -*- coding: utf-8 -*-
- # !/usr/bin/env python
- import datetime
- import logging
- import random
- import time
- from typing import Optional, Dict, TYPE_CHECKING
- from apilib.monetary import RMB
- from apilib.utils_datetime import timestamp_to_dt
- from apps.web.agent.models import Agent
- from apps.web.constant import DeviceCmdCode, Const, MQTT_TIMEOUT, DeviceErrorCodeDesc, ErrorCode
- from apps.web.core.adapter.base import SmartBox, fill_2_hexByte, start_error_timer
- from apps.web.core.device_define.jndz import CMD_CODE
- from apps.web.core.exceptions import ServiceException, InvalidParameter
- from apps.web.core.networking import MessageSender
- from apps.web.dealer.models import Dealer
- from apps.web.device.models import Device, Group, DeviceType, GroupDict
- from apps.web.eventer.base import AckEvent
- from apps.web.user.models import ConsumeRecord
- from taskmanager.mediator import task_caller
- from apps.web.common.models import ExceptionLog
- if TYPE_CHECKING:
- from apps.web.api.models import APIStartDeviceRecord
- logger = logging.getLogger(__name__)
- class ChargingJNDZBox(SmartBox):
- """
- 久恒协议和劲能一致,业务修改和功能扩充需要确定是否两边都修改
- """
- def __init__(self, device):
- super(ChargingJNDZBox, self).__init__(device)
- def async_update_portinfo_from_dev(self):
- """
- 避免频繁刷新状态,并且是并发的。状态如果不对,用户可以强制刷新
- :return:
- """
- pass
- @property
- def isHaveStopEvent(self):
- return True
- def translate_funcode(self, funCode):
- funCodeDict = {
- '01': u'获取端口数量',
- '02': u'获取端口数据',
- '14': u'移动支付',
- '07': u'获取刷卡投币统计数据',
- '15': u'获取设备端口详情',
- '0F': u'获取端口状态',
- '0C': u'端口锁操作',
- '0D': u'端口开关',
- '1E': u'获取设备设置',
- '18': u'设置设备参数',
- '10': u'回复卡余额',
- }
- return funCodeDict.get(funCode, '')
- def translate_event_cmdcode(self, cmdCode):
- cmdDict = {
- '06': u'充电结束',
- '16': u'充电结束',
- '0A': u'故障',
- '10': u'刷卡上报',
- '20': u'启动设备',
- }
- return cmdDict.get(cmdCode, '')
- def check_dev_status(self, attachParas=None):
- """
- 如果超过两个心跳周期没有报心跳,并且最后一次更新时间在2个小时内,需要从设备获取状态
- 否则以缓存状态为准。
- :param attachParas:
- :return:
- """
- if attachParas is None:
- raise ServiceException({'result': 0, 'description': u'请您选择合适的充电端口、电池类型信息'})
- if 'chargeIndex' not in attachParas:
- raise ServiceException({'result': 0, 'description': u'请您选择合适的充电端口'})
- if not self.device.need_fetch_online:
- raise ServiceException(
- {'result': 2, 'description': DeviceErrorCodeDesc.get(ErrorCode.DEVICE_CONN_CHECK_FAIL)})
- group = self.device.group # type: GroupDict
- if group.is_free:
- logger.debug('{} is free. no need to check continue pay.'.format(repr(self.device)))
- return
- port = str(attachParas['chargeIndex'])
- rv = self.get_port_info(port)
- # isCanAdd = self.device['devType'].get('payableWhileBusy', False)
- if rv['status'] == Const.DEV_WORK_STATUS_IDLE:
- return
- elif rv['status'] == Const.DEV_WORK_STATUS_FAULT:
- raise ServiceException({'result': 0, 'description': u'该端口故障,暂时不能使用'})
- elif rv['status'] == Const.DEV_WORK_STATUS_WORKING:
- # if isCanAdd:
- # return
- # raise ServiceException({'result': 0, 'description': u'该端口正在工作不能使用,请您使用其他端口'})
- return
- def is_port_can_use(self, port, canAdd = False):
- return True, ''
- def test(self, coins,port=1):
- hexElec = fill_2_hexByte(hex(0), 4)
- hexPort = fill_2_hexByte(hex(port), 2)
- hexCoins = fill_2_hexByte(hex(1))
- hexTime = fill_2_hexByte(hex(60))
- devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
- {'IMEI': self._device['devNo'], "funCode": '14',
- 'data': hexPort + hexCoins + hexTime + hexElec})
- return devInfo
- def stop(self, port = None):
- infoDict = self.stop_charging_port(port)
- infoDict['remainder_time'] = infoDict['leftTime']
- return infoDict
- def check_serial_port_for_startcmd(self, port):
- data = fill_2_hexByte(hex(int(port)), 2)
- devInfo = MessageSender.send(self.device, self.make_random_cmdcode(),
- {'IMEI': self._device['devNo'], "funCode": '15', 'data': data})
- if devInfo['rst'] != 0:
- raise ServiceException(
- {'result': 2, 'description': u'设备忙无响应。本次操作没有扣除您的金额,您可以稍后重试或者试试附近其他设备。'})
- data = devInfo['data'][6::]
- ExceptionLog.log(user = self.device.devNo, exception = '',
- extra = {
- 'action': 'check_serial_port_for_startcmd:get_port_status_from_dev',
- 'data': data
- })
- if data[0:2] == '01': # 表示成功
- if data[2:4] == '00':
- raise ServiceException({
- 'result': 2, 'description': u'设备忙无响应。本次操作没有扣除您的金额,您可以稍后重试或者试试附近其他设备。'})
- else:
- left_time = int(data[4:8], 16)
- if left_time <= 0 or left_time == 65535:
- raise ServiceException({
- 'result': 2, 'description': u'设备忙无响应。本次操作没有扣除您的金额,您可以稍后重试或者试试附近其他设备。'})
- else:
- raise ServiceException({
- 'result': 2, 'description': u'设备忙无响应。本次操作没有扣除您的金额,您可以稍后重试或者试试附近其他设备。'})
- @start_error_timer(missMessages = [u"请您选择合适的充电线路、电池类型信息", u"请您选择合适的充电线路", u"该端口正在使用中"])
- def start_device(self, package, openId, attachParas):
- if attachParas is None:
- raise ServiceException({'result': 2, 'description': u'请您选择合适的充电线路、电池类型信息'})
- if 'chargeIndex' not in attachParas:
- raise ServiceException({'result': 2, 'description': u'请您选择合适的充电线路'})
- coinElec = self.device.get_other_conf_item('coinElec')
- if coinElec is None:
- conf = self.get_dev_setting_1E()
- coinElec = int(conf.get('coinElec', 10))
- else:
- coinElec = int(coinElec)
- price = float(package['price'])
- port = hex(int(attachParas['chargeIndex']))
- hexPort = fill_2_hexByte(port, 2)
- coins = float(package['coins'])
- hexCoins = fill_2_hexByte(hex(int(coins * 10))) # 注意单位是角
- needElec = round((coins * coinElec) / 10.0, 2) # 单位是0.01度电(配置中每次投币的最大用电量单位却是0.1度电,这里要乘以10)
- hexElec = fill_2_hexByte(hex(int(needElec * 100)), 4)
- unit = package.get('unit', u'分钟')
- needTime = int(package['time'])
- if unit in [u'分钟', u'小时', u'天']:
- billingType = 'time'
- if unit == u'小时':
- needTime = int(package['time']) * 60
- elif unit == u'天':
- needTime = int(package['time']) * 1440
- hexTime = fill_2_hexByte(hex(needTime))
- elif unit == u'度':
- billingType = 'elec'
- needElec = round((package['time']), 2)
- hexElec = fill_2_hexByte(hex(int(needElec * 100)), 4)
- hexTime = fill_2_hexByte(hex(Device.get_elec_static_time(self._device['devNo'])))
- else:
- billingType = 'elec'
- devObj = Device.objects.get(devNo=self.device.devNo)
- if 'isTempPackage' in attachParas:
- elecFee = float(devObj.otherConf.get('tempElecPrice', 0.9))
- else:
- elecFee = float(devObj.otherConf.get('elecFee', 0.9))
- needElec = round(min(float(coins / elecFee), needElec), 2)
- hexElec = fill_2_hexByte(hex(int(needElec * 100)), 4)
- hexTime = fill_2_hexByte(hex(Device.get_elec_static_time(self._device['devNo'])))
- devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {
- 'IMEI': self._device['devNo'],
- "funCode": '14',
- 'data': hexPort + hexCoins + hexTime + hexElec
- }, timeout=MQTT_TIMEOUT.START_DEVICE)
- usePort = int(attachParas['chargeIndex'])
- if devInfo['rst'] != ErrorCode.SUCCESS:
- if devInfo['rst'] == ErrorCode.DEVICE_CONN_FAIL:
- raise ServiceException(
- {
- 'result': 2,
- 'description': u'当前设备信号弱无响应。本次操作没有扣除您的金额,您可以稍后重试或者试试附近其他设备。'
- }
- )
- elif devInfo['rst'] == ErrorCode.BOARD_UART_TIMEOUT:
- if devInfo.get('checked', 0) == 0:
- self.check_serial_port_for_startcmd(attachParas['chargeIndex'])
- else:
- logger.debug('{} checked value is: {}'.format(self.device, devInfo.get('checked')))
- raise ServiceException(
- {'result': 2, 'description': u'设备忙无响应。本次操作没有扣除您的金额,您可以稍后重试或者试试附近其他设备。'})
- elif devInfo.get('checked', 0) == 0:
- logger.debug('{} apply start success.'.format(self.device))
- data = devInfo['data'][6::]
- if data[0:2] == '01': # 表示成功
- pass
- else:
- raise ServiceException({'result': 2, 'description': u'获取端口数据失败,请重试看能否解决'})
- result = data[4:6]
- if result == '01': # 成功
- pass
- elif result == '0B':
- newValue = {str(usePort): {'status': Const.DEV_WORK_STATUS_FAULT, 'statusInfo': u'充电站故障'}}
- Device.update_dev_control_cache(self._device['devNo'], newValue)
- raise ServiceException({'result': 2, 'description': u'充电站故障'})
- elif result == '0C':
- newValue = {str(usePort): {'status': Const.DEV_WORK_STATUS_WORKING, 'statusInfo': u''}}
- Device.update_dev_control_cache(self._device['devNo'], newValue)
- raise ServiceException({'result': 2, 'description': u'该端口正在使用中'})
- else:
- logger.warning('{} check 15 result is: {}.'.format(self.device, devInfo.get('checked')))
- start_timestamp = int(time.time())
- portDict = {
- 'startTime': timestamp_to_dt(start_timestamp).strftime('%Y-%m-%d %H:%M:%S'),
- 'status': Const.DEV_WORK_STATUS_WORKING,
- 'coins': coins,
- 'isStart': True,
- 'price': price,
- 'openId': openId,
- 'refunded': False,
- 'needElec': needElec,
- 'billingType': billingType,
- 'vCardId': self._vcard_id,
- 'consumeType': 'server'
- }
- lastPortInfo = Device.get_port_control_cache(self.device.devNo, str(usePort))
- if lastPortInfo and \
- lastPortInfo.get('status', '') == Const.DEV_WORK_STATUS_WORKING and \
- lastPortInfo.get('openId') == openId and \
- lastPortInfo.get('billingType') == billingType and \
- ('consumeType' not in lastPortInfo or (lastPortInfo['consumeType'] == 'server')):
- is_continus = True
- else:
- is_continus = False
- if is_continus:
- if 'coins' in lastPortInfo:
- portDict['coins'] = coins + lastPortInfo['coins']
- if 'price' in lastPortInfo:
- portDict['price'] = price + lastPortInfo['price']
- if 'startTime' in lastPortInfo:
- portDict['startTime'] = lastPortInfo['startTime']
- if billingType == 'time':
- portDict.update({'needTime': needTime, 'needElec': needElec})
- if is_continus:
- if lastPortInfo.has_key('needTime'):
- portDict['needTime'] = needTime + lastPortInfo['needTime']
- if lastPortInfo.has_key('needElec'):
- portDict['needElec'] = needElec + lastPortInfo['needElec']
- finishedTime = int(time.time()) + portDict['needTime'] * 60
- else:
- portDict.update({'needElec': needElec})
- if is_continus:
- lastPortInfo['needElec'] = needElec + lastPortInfo['needElec']
- finishedTime = int(time.time()) + 12 * 60 * 60
- if attachParas.has_key('orderNo'):
- portDict.update({'orderNo': attachParas['orderNo']})
- if attachParas.get('redpackId'):
- if is_continus:
- redpackInfo = lastPortInfo.get("redpackInfo", list())
- if not redpackInfo:
- logger.warning("miss redpackInfo! {}-{}".format(self._device["devNo"], usePort))
- else:
- redpackInfo = list()
- redpackInfo.append({'redpackId': str(attachParas['redpackId'])})
- portDict['redpackInfo'] = redpackInfo
- else:
- if is_continus:
- portDict['redpackInfo'] = lastPortInfo.get("redpackInfo", list())
- else:
- portDict['redpackInfo'] = list()
- if 'linkedRechargeRecordId' in attachParas and attachParas.get('isQuickPay', False):
- item = {
- 'rechargeRcdId': str(attachParas['linkedRechargeRecordId'])
- }
- if is_continus:
- pay_info = lastPortInfo.get('payInfo', list())
- else:
- pay_info = list()
- pay_info.append(item)
- portDict['payInfo'] = pay_info
- if 'extOrderNo' in attachParas:
- portDict['extOrderNo'] = attachParas.get('extOrderNo')
- if 'isTempPackage' in attachParas:
- portDict['isTempPackage'] = attachParas['isTempPackage']
- devInfo['finishedTime'] = finishedTime
- portDict.update({'finishedTime': finishedTime})
- Device.update_dev_control_cache(self.device.devNo, {str(usePort): portDict})
- if self.device.owner.supports("supportBeiJingFengTai"):
- from apps.web.south_intf.bj_north.api import push_port_info,post_charging_meta_info
- push_port_info(self.device.devNo, attachParas['chargeIndex'])
- post_charging_meta_info(self.device.devNo, attachParas['chargeIndex'])
- return devInfo
- def start_from_api(self, record):
- # type: (APIStartDeviceRecord)->Optional[Dict]
- if 'chargeIndex' not in record.attachParas:
- from apps.web.api.exceptions import ApiParameterError
- raise ApiParameterError(u'请传入充电桩端口号chargeIndex参数')
- return super(ChargingJNDZBox, self).start_from_api(record)
- def analyze_event_data(self, device_event):
- # 升级兼容. 避免重启过程中老的消息
- if 'data' in device_event:
- data = device_event['data']
- else:
- data = device_event
- cmdCode = data[4:6]
- #: 提交充电结束状态 (06)
- #: 老版本
- if cmdCode == CMD_CODE.DEVICE_SUBMIT_CHARGE_FINISHED_06:
- port = int(data[8:10], 16)
- leftTime = int(data[10:14], 16)
- reasonCode = data[14:16]
- orderPower = device_event.get("orderPower")
- desc_map = {
- "00": u'购买的充电时间或电量用完了。',
- "01": u'可能是插头被拔掉,或者电瓶已经充满。系统判断为异常断电,由于电瓶车充电器种类繁多,可能存在误差。如有问题,请您及时联系商家协助解决问题并恢复充电。',
- "02": u'恭喜您!电池已经充满电!',
- "0B": u'设备或端口出现问题,为了安全起见,被迫停止工作。建议您根据已经充电的时间评估是否需要到现场换到其他端口充电。'
- }
- return {
- 'status': Const.DEV_WORK_STATUS_IDLE,
- 'cmdCode': cmdCode,
- 'port': port,
- 'leftTime': leftTime,
- 'reason': desc_map[reasonCode],
- 'reasonCode': reasonCode,
- 'uartData': data,
- 'orderPower': orderPower
- }
- #: (高版本的) 提交充电结束状态 (16)
- elif cmdCode == CMD_CODE.DEVICE_SUBMIT_CHARGE_FINISHED_v2_16:
- port = int(data[8:10], 16)
- leftTime = int(data[10:14], 16)
- elec = int(data[14:18], 16) / 100.0
- reasonCode = data[18:20]
- orderPower = device_event.get("orderPower")
- # 如果设备类型有自定义结束推送通知就走自定义
- devType = DeviceType.objects(id=self.device['devType']['id']).first()
- finishedReasonDict = devType.finishedReasonDict
- if finishedReasonDict != {}:
- desc_map = finishedReasonDict
- else:
- desc_map = {
- '00': u'购买的充电时间或电量用完了。',
- '01': u'可能是插头被拔掉,或者电瓶已经充满。',
- '02': u'恭喜您!电池已经充满电!',
- '03': u'警告!您的充电功率超过充电桩的最大使用功率,已经停止充电!!',
- '04': u'远程断电。',
- '0B': u'设备或端口出现问题,被迫停止工作。建议您根据已经充电的时间评估是否需要到现场换到其他端口充电。'
- }
- desc = desc_map.get(reasonCode, u'电池没有充满!原因未知。')
- return {
- 'status': Const.DEV_WORK_STATUS_IDLE,
- 'cmdCode': cmdCode,
- 'port': port,
- 'leftTime': leftTime,
- 'elec': elec,
- 'reason': desc,
- 'reasonCode': reasonCode,
- 'uartData': data,
- 'orderPower': orderPower
- }
- # todo 0A的告警不要了,先注释掉,后续删除
- #: 上传设备故障
- # elif cmdCode == CMD_CODE.DEVICE_SUBMIT_DEVICE_FAULT_0A:
- # port = int(data[8:10], 16)
- # errCode = data[10:12]
- #
- # FaultDict = {
- # 'A0': ['充电异常,继电器粘连,短路', FAULT_LEVEL.FATAL],
- # 'A1': ['高温异常', FAULT_LEVEL.CRITICAL],
- # '21': ['高温状态恢复', FAULT_LEVEL.NORMAL],
- # 'A2': ['低温异常', FAULT_LEVEL.NORMAL],
- # '22': ['低温状态恢复', FAULT_LEVEL.NORMAL],
- # 'A3': ['空载,充电头脱落、充电器拔出', FAULT_LEVEL.NORMAL],
- # '23': ['负载恢复正常', FAULT_LEVEL.NORMAL],
- # 'A4': ['设备消防(烟感)异常', FAULT_LEVEL.CRITICAL],
- # '24': ['设备消防(烟感)恢复正常', FAULT_LEVEL.CRITICAL],
- # 'A5': ['总功率过载' if port == 255 else '{}号端口过载'.format(port), FAULT_LEVEL.FATAL],
- # '25': ['总功率过载恢复正常' if port == 255 else '{}号端口过载恢复正常'.format(port), FAULT_LEVEL.NORMAL],
- # 'A6': ['设备倾斜异常', FAULT_LEVEL.FATAL],
- # '26': ['设备倾斜恢复正常', FAULT_LEVEL.NORMAL],
- # 'A7': ['水压高异常', FAULT_LEVEL.NORMAL],
- # '27': ['水压(从高)恢复正常', FAULT_LEVEL.NORMAL],
- # 'A8': ['水压低异常', FAULT_LEVEL.NORMAL],
- # '28': ['水压(从低)恢复正常', FAULT_LEVEL.NORMAL],
- # 'A9': ['设备过压异常', FAULT_LEVEL.NORMAL],
- # '29': ['设备过压恢复正常', FAULT_LEVEL.NORMAL],
- # 'AA': ['设备欠压异常', FAULT_LEVEL.NORMAL],
- # '2A': ['设备欠压恢复正常', FAULT_LEVEL.NORMAL],
- #
- # '00': ['继电器粘黏(端口: {})'.format(port), FAULT_LEVEL.NORMAL], # 久恒老设备 100206
- # }
- #
- # return {
- # 'status': Const.DEV_WORK_STATUS_FAULT,
- # 'statusInfo': FaultDict.get(errCode, ['设备故障', FAULT_LEVEL.NORMAL])[0],
- # 'cmdCode': cmdCode,
- # 'port': port,
- # 'errCode': errCode,
- # 'faultContent': FaultDict.get(errCode, [errCode, FAULT_LEVEL.NORMAL])[0],
- # 'level': FaultDict.get(errCode, [errCode, FAULT_LEVEL.NORMAL])[1]
- # }
- # 用户刷卡上报的信息
- #: 在线卡上传卡号,预扣费
- #: 示例:
- #: CARD_ID CARD_CST CARD_OPE
- #: 0x00000000 0x00 0x00
- #: 参数
- #: CARD_ID : IC 卡卡号
- #: CARD_SURP: 卡片需要改变的金额信息(以角为单位)
- #: CARD_OPE: 0x00 是扣费(减少),0x01 是充值(增加)。
- #: 回复
- #: RES: 0x00,表示扣费成功,0x01 表示余额不足,0x02 表示非法卡。
- #: CARD_SURP: 表示卡余额(以角为单位)。
- elif cmdCode == CMD_CODE.SWIPE_CARD_10:
- # 过滤掉长度不够的10命令
- if data[2:4] == '04':
- return None
- group = Group.get_group(self._device['groupId'])
- dealer = Dealer.get_dealer(group['ownerId'])
- agent = Agent.objects(id = dealer['agentId']).first()
- device = Device.objects(devNo=self._device['devNo']).first()
- devType = DeviceType.objects(id=device['devType']['id']).first()
- cardNo = str(int(data[8:16], 16))
- # 兼容以前的老代码, 先走以前的老代码, 如果有新代码再走新的.
- if agent is not None and 'cardNoReverse' in agent.features:
- cardData = data[14:16] + data[12:14] + data[10:12] + data[8:10]
- cardNo = str(int(cardData, 16))
- if 'cardNoReverse' in devType.features:
- if devType.features['cardNoReverse'] is True:
- cardData = data[14:16] + data[12:14] + data[10:12] + data[8:10]
- cardNo = str(int(cardData, 16))
- else:
- cardNo = str(int(data[8:16], 16))
- else:
- pass
- #: 卡里的余额,以角为单位
- preFee = int(data[16:18], 16) / 10.0
- #: 操作符 00(增加) | 01(减少)
- oper = data[18:20]
- return {'cardNo': cardNo, 'preFee': preFee, 'cmdCode': cmdCode, 'oper': oper, "sourceData": data}
- elif cmdCode == CMD_CODE.SWIPE_CARD_50:
- data = data[8:-2]
- cardNo = str(int(data, 16))
- return {
- 'cardNo' : cardNo,
- 'command' : 'query',
- 'cmdCode': cmdCode
- }
- elif cmdCode == CMD_CODE.SWIPE_CARD_52:
- data = data[8:-2]
- port = str(int(data[:2], 16))
- coins = str(int(data[2:6], 16) * 0.1)
- needtime = str(int(data[6:10], 16))
- cardNo = str(int(data[10:18], 16))
- deductType = str(int(data[18:20], 16))
- ackId = device_event['ack_id']
- return {'port': port, 'coins': coins, 'needTime': needtime, 'cardNo': cardNo,
- 'deductType': deductType, 'cmdCode': cmdCode, 'command': 'strat','ack_id':ackId}
- elif cmdCode == CMD_CODE.SWIPE_CARD_56:
- data = data[8:-2]
- port = str(int(data[:2], 16))
- usedTime = str(int(data[2:6], 16))
- usedElec = str(int(data[6:10], 16))
- reasonCode = str(int(data[10:12], 16))
- refundMoney = str(int(data[12:16], 16))
- refundTime = str(int(data[16:20], 16))
- refundType = str(int(data[20:22], 16))
- desc_map = {
- '00': u'购买的充电时间或电量用完了。',
- '01': u'可能是插头被拔掉,或者电瓶已经充满。',
- '02': u'恭喜您!电池已经充满电!',
- '03': u'警告!您的充电功率超过充电桩的最大使用功率,已经停止充电!!',
- '04': u'远程断电。',
- '0B': u'设备或端口出现问题,被迫停止工作。建议您根据已经充电的时间评估是否需要到现场换到其他端口充电。'
- }
- desc = desc_map.get(reasonCode, u'电池没有充满!原因未知。')
- ackId = device_event['ack_id']
- return {'port': port, 'usedTime': usedTime, 'usedElec': usedElec, 'reason': desc, 'reasonCode': reasonCode,
- 'refundMoney': refundMoney, 'refundTime': refundTime, 'refundType': refundType, 'cmdCode': cmdCode,
- 'command': 'finished','ack_id':ackId}
- #: 上报投币打开的信息
- elif cmdCode == CMD_CODE.DEVICE_SUBMIT_OFFLINE_COINS_20: # 启动设备
- port = int(data[8:10], 16)
- needTime = int(data[10:14], 16)
- elec = int(data[14:18], 16) / 100.0
- consumeTypeTemp = data[18:20]
- if consumeTypeTemp == '00':
- consumeType = 'coin'
- elif consumeTypeTemp == '01':
- consumeType = 'card'
- elif consumeTypeTemp == '03':
- consumeType = 'server'
- else:
- consumeType = 'other'
- money = int(data[20:22], 16) / 10.0
- rv = {
- 'cmdCode': cmdCode,
- 'port': port,
- 'needTime': needTime,
- 'elec': elec,
- 'consumeType': consumeType,
- 'coins': money,
- 'uartData': data
- }
- if 'today_coins' in device_event and 'ts' in device_event:
- rv.update({
- 'today_coins': device_event['today_coins'],
- 'ts': device_event['ts']
- })
- return rv
- # 4个故障的告警
- elif cmdCode == CMD_CODE.DEVICE_FAULT_FIRE:
- return {"cmdCode": cmdCode, "fault": u"火灾报警"}
- elif cmdCode == CMD_CODE.DEVICE_FAULT_SMOKE:
- return {"cmdCode": cmdCode, "fault": "烟雾报警"}
- elif cmdCode == CMD_CODE.DEVICE_FAULT_TEMPERATURE:
- return {"cmdCode": cmdCode, "fault": "温度超限告警"}
- elif cmdCode == CMD_CODE.DEVICE_FAULT_POWER:
- return {"cmdCode": cmdCode, "fault": "功率超线告警"}
- elif cmdCode == CMD_CODE.DEVICE_FAULT_ALTER:
- def getBin8Str(binData):
- bin8Str = str(bin(binData))[2:]
- while len(bin8Str) < 8:
- bin8Str = '0' + bin8Str
- return bin8Str
- fire = int(data[8:10],16)
- smoke = int(data[10:12],16)
- overload = int(data[12:14],16)
- overheat = int(data[14:16],16)
- relayAdhesion = data[16:24]
- relayAdhesionDetail = (getBin8Str(int(relayAdhesion[0:2], 16)) + getBin8Str(int(relayAdhesion[2:4], 16)) + getBin8Str(int(relayAdhesion[4:6], 16)) + getBin8Str(int(relayAdhesion[6:8], 16)))[::-1]
- portRelayAdhesion = {}
- for _ in range(0, len(relayAdhesionDetail)):
- if int(relayAdhesionDetail[_]):
- portRelayAdhesion.update({str(_ + 1): int(relayAdhesionDetail[_])})
- result = {"cmdCode": cmdCode, "fire": bool(fire), "smoke": bool(smoke), "overload": bool(overload), "overheat":bool(overheat), "portRelayAdhesion": portRelayAdhesion}
- dealer = Dealer.objects(id=self.device['ownerId']).first()
- if dealer is None:
- return {}
- if 'supportAdhesionAlert' not in dealer.features:
- result.pop('portRelayAdhesion')
- fault = []
- desc = []
- if result.get('fire', False):
- fault.append("火灾报警")
- result["errorCode"] = "B202"
- if result.get('smoke', False):
- fault.append("烟雾报警")
- result["errorCode"] = "B202"
- if result.get('overload', False):
- fault.append("功率超限告警")
- result["errorCode"] = "B203"
- if result.get('overheat', False):
- fault.append("温度超限告警")
- result["errorCode"] = "B201"
- if result.get('portRelayAdhesion', {}):
- fault.append("继电器粘连告警")
- result["errorCode"] = "B204"
- for _ in portRelayAdhesion.keys():
- desc.append("{}号继电器粘连告警 ".format(_))
- if desc:
- desc = '--'.join(desc)
- result.update({"desc": desc})
- if fault:
- fault = '--'.join(fault)
- result.update({"fault": fault})
- else:
- result = {}
- return result
- # 2个状态量上报
- elif cmdCode == CMD_CODE.DEVICE_FAULT_POWER:
- maxPower = int(data[8:12],16)
- return {"cmdCode": cmdCode, "maxPower": maxPower}
- elif cmdCode == CMD_CODE.DEVICE_FAULT_TEMPERATURE:
- maxTemperature = int(data[8:10],16)
- return {"cmdCode": cmdCode, "maxTemperature": maxTemperature}
- elif cmdCode == CMD_CODE.DEVICE_ELEC:
- elec = int(data[8:12], 16)
- return {"cmdCode": cmdCode, "elec": elec}
- elif cmdCode == CMD_CODE.DEVICE_TEMPERATURE:
- temperature = int(data[10:12], 16)
- if data[8:10] == "00":
- temperature = temperature * -1
- return {"cmdCode": cmdCode, "temperature": temperature}
- elif cmdCode == CMD_CODE.DEVICE_CARD_CHARGE_2D:
- _result = data[6: 8]
- _port = str(int(data[8: 10], 16))
- _time = int(data[10: 14], 16)
- _elec = int(data[14: 18], 16) / 100.0
- _type = data[18: 20]
- _coins = int(data[20: 22], 16)
- _cardNo = str(int(data[22: 30], 16))
- _card_cst = int(data[30: 34], 16) / 10.0
- _operation = data[34: 36]
- _card_type = data[36: 38]
- _session_id = data[38: 46]
- return {
- "portStr": _port,
- "time": _time,
- "elec": _elec,
- "chargeType": _type,
- "coins": _coins,
- "cardNo": _cardNo,
- "cardCst": _card_cst,
- "operation": _operation,
- "cardType": _card_type,
- "sessionId": _session_id,
- "cmdCode": cmdCode,
- "result": _result,
- "sourceData": data
- }
- elif cmdCode == CMD_CODE.DEVICE_REAL_TIME_REPORT_21:
- _result = data[6: 8]
- port_num = int(data[8:10],16)
- port_info_urat_info = data[10:170]
- port_status_desc = {
- "01": "端口空闲",
- "02": "端口正在使用",
- "03": "端口禁用",
- "04": "端口故障",
- }
- port_info = {}
- for index in xrange(0, 160, 16):
- item = port_info_urat_info[index: index + 16]
- one_port = {}
- one_port["port"] = int(item[:2], 16)
- one_port["portStatus"] = item[2:4]
- one_port["portStatusDesc"] = port_status_desc.get(item[2:4])
- one_port["leftTime"] = int(item[4:8], 16)
- one_port["power"] = int(item[8:12], 16)
- one_port["elec"] = int(item[12:16], 16) * 0.01
- port_info[str(one_port["port"])] = one_port
- return {"cmdCode": cmdCode, "result": _result, "sourceData": data, "portNum": port_num,
- "portInfo": port_info}
- else:
- logger.info("receive data <{}>, cmd is invalid".format(data))
- def get_dev_consume_count(self):
- devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
- {'IMEI': self._device['devNo'], "funCode": '07', 'data': '00'})
- if devInfo.has_key('rst') and devInfo['rst'] != 0:
- if devInfo['rst'] == -1:
- raise ServiceException(
- {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
- elif devInfo['rst'] == 1:
- raise ServiceException(
- {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
- data = devInfo['data'][6::]
- if data[0:2] == '01': # 表示成功
- pass
- else:
- raise ServiceException({'result': 2, 'description': u'获取统计数据失败,请重试看能否解决'})
- cardFee = str(RMB(int(data[2:6], 16) / 10.0)) # 以角为单位
- coinFee = int(data[6:10], 16) # 以元为单位
- return {'cardFee': cardFee, 'coinFee': coinFee}
- def get_port_info(self, line):
- data = fill_2_hexByte(hex(int(line)), 2)
- devInfo = MessageSender.send(self.device, self.make_random_cmdcode(),
- {"funCode": '15', 'data': data})
- 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'和充电桩通讯失败({}),请您稍候再试'.format(devInfo['rst'])})
- data = devInfo['data'][6::]
- if data[0:2] == '01': # 表示成功
- pass
- else:
- raise ServiceException({'result': 2, 'description': u'获取端口信息失败,请重试看能否解决'})
- if data[2:4] == '00':
- status = Const.DEV_WORK_STATUS_IDLE
- else:
- left_time = int(data[4:8], 16)
- if left_time <= 0 or left_time == 65535:
- status = Const.DEV_WORK_STATUS_IDLE
- else:
- status = Const.DEV_WORK_STATUS_WORKING
- # 这里存在多线程更新缓存的场景,可能性比较低,但是必须先取出来,然后逐个更新状态,然后再记录缓存
- ctrInfo = Device.get_dev_control_cache(self.device.devNo)
- old_status = ctrInfo.get(str(line), {}).get('status', Const.DEV_WORK_STATUS_IDLE)
- if old_status != status:
- if str(line) in ctrInfo:
- ctrInfo[str(line)]['status'] = status
- else:
- ctrInfo[str(line)] = {'status': status}
- Device.update_dev_control_cache(self.device.devNo, ctrInfo)
- leftTime = int(data[4:8], 16)
- if data[8:12] == 'FFFF':
- power = 0
- else:
- power = int(data[8:12], 16)
- if data[12:16] == 'FFFF':
- elec = 0
- else:
- elec = int(data[12:16], 16) * 0.01
- if data[16:20] == 'FFFF':
- surp = 0
- else:
- surp = int(data[16:20], 16)
- rv = {'port': line, 'leftTime': leftTime, 'power': power, 'surp': surp, 'leftElec': elec, 'status': status}
- if self.device.my_obj.bill_as_service_feature.on:
- rv.pop('leftTime', None)
- return rv
- def get_port_status(self, force = False):
- if force:
- return self.get_port_status_from_dev()
- ctrInfo = Device.get_dev_control_cache(self._device['devNo'])
- statusDict = {}
- if 'allPorts' not in ctrInfo:
- self.get_port_status_from_dev()
- ctrInfo = Device.get_dev_control_cache(self._device['devNo'])
- allPorts = ctrInfo.get('allPorts', 10)
- # allPorts 有的时候会为0, 这个时候强制设置为10
- if allPorts == 0:
- allPorts = 10
- for ii in range(allPorts):
- tempDict = ctrInfo.get(str(ii + 1), {})
- if tempDict.has_key('status'):
- statusDict[str(ii + 1)] = {'status': tempDict.get('status')}
- elif tempDict.has_key('isStart'):
- if tempDict['isStart']:
- statusDict[str(ii + 1)] = {'status': Const.DEV_WORK_STATUS_WORKING}
- else:
- statusDict[str(ii + 1)] = {'status': Const.DEV_WORK_STATUS_IDLE}
- else:
- statusDict[str(ii + 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):
- devInfo = MessageSender.send(self.device, self.make_random_cmdcode(),
- {'IMEI': self._device['devNo'], "funCode": '0F', 'data': '00'}, timeout=MQTT_TIMEOUT.CHECK_DEVICE_STATUS)
- if devInfo.has_key('rst') and devInfo['rst'] != 0:
- if devInfo['rst'] == -1:
- raise ServiceException(
- {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
- elif devInfo['rst'] == 1:
- raise ServiceException(
- {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
- data = devInfo['data'][6::]
- if data[0:2] == '01': # 表示成功
- pass
- else:
- raise ServiceException({'result': 2, 'description': u'获取统计数据失败,请重试看能否解决'})
- result = {}
- portNum = int(data[2:4], 16)
- portData = data[4::]
- ii = 0
- while ii < portNum:
- port = int(portData[ii * 4:ii * 4 + 2], 16)
- statusTemp = portData[ii * 4 + 2:ii * 4 + 4]
- if statusTemp == '01':
- status = {'status': Const.DEV_WORK_STATUS_IDLE}
- elif statusTemp == '02':
- status = {'status': Const.DEV_WORK_STATUS_WORKING}
- elif statusTemp == '03':
- status = {'status': Const.DEV_WORK_STATUS_FORBIDDEN}
- elif statusTemp == '04':
- status = {'status': Const.DEV_WORK_STATUS_FAULT}
- else:
- status = {'status': Const.DEV_WORK_STATUS_IDLE}
- ii += 1
- result[str(port)] = status
- allPorts, usedPorts, usePorts = self.get_port_static_info(result)
- Device.update_dev_control_cache(self._device['devNo'],
- {'allPorts': allPorts, 'usedPorts': usedPorts, 'usePorts': usePorts})
- # 这里存在多线程更新缓存的场景,可能性比较低,但是必须先取出来,然后逐个更新状态,然后再记录缓存
- ctrInfo = Device.get_dev_control_cache(self._device['devNo'])
- for strPort, info in result.items():
- if ctrInfo.has_key(strPort):
- ctrInfo[strPort].update({'status': info['status']})
- else:
- ctrInfo[strPort] = info
- Device.update_dev_control_cache(self._device['devNo'], ctrInfo)
- return result
- def lock_unlock_port(self, port, lock = True):
- lockStr = '00' if lock else '01'
- portStr = fill_2_hexByte(hex(int(port)), 2)
- devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
- {'IMEI': self._device['devNo'], "funCode": '0C', 'data': portStr + lockStr})
- if devInfo.has_key('rst') and devInfo['rst'] != 0:
- if devInfo['rst'] == -1:
- raise ServiceException(
- {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
- elif devInfo['rst'] == 1:
- raise ServiceException(
- {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
- data = devInfo['data'][6::]
- if data[0:2] == '01': # 表示成功
- pass
- else:
- raise ServiceException({'result': 2, 'description': u'操作端口失败,请重试看能否解决'})
- if lock:
- Device.update_dev_control_cache(self._device['devNo'],
- {str(port): {'status': Const.DEV_WORK_STATUS_FORBIDDEN}})
- else:
- Device.update_dev_control_cache(self._device['devNo'], {str(port): {'status': Const.DEV_WORK_STATUS_IDLE}})
- def active_deactive_port(self, port, active):
- if not active:
- self.stop_charging_port(port)
- devInfo = Device.get_dev_control_cache(self._device['devNo'])
- portCtrInfo = devInfo.get(str(port), {})
- portCtrInfo.update({'isStart': False, 'status': Const.DEV_WORK_STATUS_IDLE,
- 'endTime': datetime.datetime.now().strftime(Const.DATETIME_FMT)})
- newValue = {str(port): portCtrInfo}
- Device.update_dev_control_cache(self._device['devNo'], newValue)
- else:
- raise ServiceException({'result': 2, 'description': u'此设备不支持直接打开端口'})
- def stop_charging_port(self, port):
- portStr = fill_2_hexByte(hex(int(port)), 2)
- devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
- {'IMEI': self._device['devNo'], "funCode": '0D', 'data': portStr + '00'}, timeout=7)
- if devInfo.has_key('rst') and devInfo['rst'] != 0:
- if devInfo['rst'] == -1:
- raise ServiceException(
- {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
- elif devInfo['rst'] == 1:
- raise ServiceException(
- {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
- data = devInfo['data'][6::]
- if data[0:2] == '01': # 表示成功
- pass
- else:
- raise ServiceException({'result': 2, 'description': u'操作端口失败,请重试看能否解决'})
- port = int(data[2:4], 16)
- leftTime = int(data[4:8], 16)
- result = {'port': port, 'leftTime': leftTime}
- return result
- def get_dev_setting_1E(self):
- devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
- {'IMEI': self._device['devNo'], "funCode": '1E', 'data': '00'})
- if devInfo.has_key('rst') and devInfo['rst'] != 0:
- if devInfo['rst'] == -1:
- raise ServiceException(
- {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
- elif devInfo['rst'] == 1:
- raise ServiceException(
- {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
- data = devInfo['data'][6::]
- if data[0:2] == '01': # 表示成功
- pass
- else:
- raise ServiceException({'result': 2, 'description': u'操作端口失败,请重试看能否解决'})
- if len(data) > 62:
- confData = data[2:-2]
- coinMin = int(confData[0:4], 16)
- cardMin = int(confData[4:8], 16)
- coinElec = int(confData[8:10], 16)
- cardElec = int(confData[10:12], 16)
- cst = int(confData[12:14], 16)
- powerMax1 = int(confData[14:18], 16)
- powerMax2 = int(confData[18:22], 16)
- powerMax3 = int(confData[22:26], 16)
- powerMax4 = int(confData[26:30], 16)
- powerMax5 = int(confData[30:34], 16)
- powerMax6 = int(confData[34:38], 16)
- powerMax7 = int(confData[38:42], 16)
- powerMax8 = int(confData[42:46], 16)
- power2Ti = int(confData[46:48], 16)
- power3Ti = int(confData[48:50], 16)
- power4Ti = int(confData[50:52], 16)
- power5Ti = int(confData[52:54], 16)
- power6Ti = int(confData[54:56], 16)
- power7Ti = int(confData[56:58], 16)
- power8Ti = int(confData[58:60], 16)
- spRecMon = int(confData[60:62], 16)
- spFullEmpty = int(confData[62:64], 16)
- fullPowerMin = int(confData[64:66], 16)
- fullChargeTime = int(confData[66:68], 16)
- elecTimeFirst = int(confData[68:70], 16)
- firstCoinTime = 0
- secondCoinTime = 0
- thirdCoinTime = 0
- resultDict = {
- 'coinMin': coinMin,
- 'cardMin': cardMin,
- 'coinElec': coinElec,
- 'cardElec': cardElec,
- 'cst': cst,
- 'powerMax1': powerMax1,
- 'powerMax2': powerMax2,
- 'powerMax3': powerMax3,
- 'powerMax4': powerMax4,
- 'powerMax5': powerMax5,
- 'powerMax6': powerMax6,
- 'powerMax7': powerMax7,
- 'powerMax8': powerMax8,
- 'power2Ti': power2Ti,
- 'power3Ti': power3Ti,
- 'power4Ti': power4Ti,
- 'power5Ti': power5Ti,
- 'power6Ti': power6Ti,
- 'power7Ti': power7Ti,
- 'power8Ti': power8Ti,
- 'spRecMon': spRecMon,
- 'spFullEmpty': spFullEmpty,
- 'fullPowerMin': fullPowerMin,
- 'fullChargeTime': fullChargeTime,
- 'elecTimeFirst': elecTimeFirst,
- 'firstCoinTime': firstCoinTime,
- 'secondCoinTime': secondCoinTime,
- 'thirdCoinTime': thirdCoinTime
- }
- resultDict.update({'support8PowerTi': True})
- else:
- confData = data[2:-2]
- coinMin = int(confData[0:4], 16)
- cardMin = int(confData[4:8], 16)
- coinElec = int(confData[8:10], 16)
- cardElec = int(confData[10:12], 16)
- cst = int(confData[12:14], 16)
- powerMax1 = int(confData[14:18], 16)
- powerMax2 = int(confData[18:22], 16)
- powerMax3 = int(confData[22:26], 16)
- powerMax4 = int(confData[26:30], 16)
- power2Ti = int(confData[30:32], 16)
- power3Ti = int(confData[32:34], 16)
- power4Ti = int(confData[34:36], 16)
- spRecMon = int(confData[36:38], 16)
- spFullEmpty = int(confData[38:40], 16)
- fullPowerMin = int(confData[40:42], 16)
- fullChargeTime = int(confData[42:44], 16)
- elecTimeFirst = int(confData[44:46], 16)
- try:
- firstCoinTime = int(confData[46:50], 16)
- secondCoinTime = int(confData[50:54], 16)
- thirdCoinTime = int(confData[54:58], 16)
- except Exception as e:
- firstCoinTime = 0
- secondCoinTime = 0
- thirdCoinTime = 0
- resultDict = {
- 'coinMin': coinMin,
- 'cardMin': cardMin,
- 'coinElec': coinElec,
- 'cardElec': cardElec,
- 'cst': cst,
- 'powerMax1': powerMax1,
- 'powerMax2': powerMax2,
- 'powerMax3': powerMax3,
- 'powerMax4': powerMax4,
- 'power2Ti': power2Ti,
- 'power3Ti': power3Ti,
- 'power4Ti': power4Ti,
- 'spRecMon': spRecMon,
- 'spFullEmpty': spFullEmpty,
- 'fullPowerMin': fullPowerMin,
- 'fullChargeTime': fullChargeTime,
- 'elecTimeFirst': elecTimeFirst,
- 'firstCoinTime': firstCoinTime,
- 'secondCoinTime': secondCoinTime,
- 'thirdCoinTime': thirdCoinTime
- }
- try:
- self.device.update_other_conf(
- cst = cst, coinMin = coinMin, coinElec = coinElec, cardMin = cardMin, cardElec = cardElec)
- except Exception, e:
- pass
- return resultDict
- def get_dev_setting(self):
- """
- 获取设备配置参数
- :return:
- """
- resultDict = self.get_dev_setting_1E()
- consumeInfo = self.get_dev_consume_count()
- resultDict.update(consumeInfo)
- deviceInfo = self.get_real_time_device_info()
- resultDict.update(deviceInfo)
- return resultDict
- def set_shenlin_8_gear_settings(self, setConf):
- data = ''
- data += fill_2_hexByte(hex(int(setConf['coinMin'])), 4)
- data += fill_2_hexByte(hex(int(setConf['cardMin'])), 4)
- data += fill_2_hexByte(hex(int(setConf['coinElec'])), 2)
- data += fill_2_hexByte(hex(int(setConf['cardElec'])), 2)
- data += fill_2_hexByte(hex(int(setConf['cst'])), 2)
- data += fill_2_hexByte(hex(int(setConf['powerMax1'])), 4)
- data += fill_2_hexByte(hex(int(setConf['powerMax2'])), 4)
- data += fill_2_hexByte(hex(int(setConf['powerMax3'])), 4)
- data += fill_2_hexByte(hex(int(setConf['powerMax4'])), 4)
- data += fill_2_hexByte(hex(int(setConf['powerMax5'])), 4)
- data += fill_2_hexByte(hex(int(setConf['powerMax6'])), 4)
- data += fill_2_hexByte(hex(int(setConf['powerMax7'])), 4)
- data += fill_2_hexByte(hex(int(setConf['powerMax8'])), 4)
- data += fill_2_hexByte(hex(int(setConf['power2Ti'])), 2)
- data += fill_2_hexByte(hex(int(setConf['power3Ti'])), 2)
- data += fill_2_hexByte(hex(int(setConf['power4Ti'])), 2)
- data += fill_2_hexByte(hex(int(setConf['power5Ti'])), 2)
- data += fill_2_hexByte(hex(int(setConf['power6Ti'])), 2)
- data += fill_2_hexByte(hex(int(setConf['power7Ti'])), 2)
- data += fill_2_hexByte(hex(int(setConf['power8Ti'])), 2)
- data += fill_2_hexByte(hex(int(setConf['spRecMon'])), 2)
- data += fill_2_hexByte(hex(int(setConf['spFullEmpty'])), 2)
- data += fill_2_hexByte(hex(int(setConf['fullPowerMin'])), 2)
- data += fill_2_hexByte(hex(int(setConf['fullChargeTime'])), 2)
- data += fill_2_hexByte(hex(int(setConf['elecTimeFirst'])), 2)
- devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
- {'IMEI': self._device['devNo'], "funCode": '18', 'data': data})
- if devInfo.has_key('rst') and devInfo['rst'] != 0:
- if devInfo['rst'] == -1:
- raise ServiceException(
- {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
- elif devInfo['rst'] == 1:
- raise ServiceException(
- {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
- data = devInfo['data'][6::]
- if data[0:2] == '01': # 表示成功
- self.device.update_other_conf(
- cst=int(setConf['cst']), coinMin=int(setConf['coinMin']),
- coinElec=int(setConf['coinElec']), cardMin=int(setConf['cardMin']),
- cardElec=int(setConf['cardElec']))
- else:
- raise ServiceException({'result': 2, 'description': u'操作端口失败,请重试看能否解决'})
- def set_dev_setting(self, setConf):
- """
- 设置设备配置参数
- :param setConf:
- :return:
- """
- data = ''
- data += fill_2_hexByte(hex(int(setConf['coinMin'])), 4)
- data += fill_2_hexByte(hex(int(setConf['cardMin'])), 4)
- data += fill_2_hexByte(hex(int(setConf['coinElec'])), 2)
- data += fill_2_hexByte(hex(int(setConf['cardElec'])), 2)
- data += fill_2_hexByte(hex(int(setConf['cst'])), 2)
- data += fill_2_hexByte(hex(int(setConf['powerMax1'])), 4)
- data += fill_2_hexByte(hex(int(setConf['powerMax2'])), 4)
- data += fill_2_hexByte(hex(int(setConf['powerMax3'])), 4)
- data += fill_2_hexByte(hex(int(setConf['powerMax4'])), 4)
- data += fill_2_hexByte(hex(int(setConf['power2Ti'])), 2)
- data += fill_2_hexByte(hex(int(setConf['power3Ti'])), 2)
- data += fill_2_hexByte(hex(int(setConf['power4Ti'])), 2)
- data += fill_2_hexByte(hex(int(setConf['spRecMon'])), 2)
- data += fill_2_hexByte(hex(int(setConf['spFullEmpty'])), 2)
- data += fill_2_hexByte(hex(int(setConf['fullPowerMin'])), 2)
- data += fill_2_hexByte(hex(int(setConf['fullChargeTime'])), 2)
- data += fill_2_hexByte(hex(int(setConf['elecTimeFirst'])), 2)
- if self.device['devType']['code'] == Const.DEVICE_TYPE_CODE_CHARGING_JH_TOUBI:
- data += fill_2_hexByte(hex(int(setConf['firstCoinTime'])), 4)
- data += fill_2_hexByte(hex(int(setConf['secondCoinTime'])), 4)
- data += fill_2_hexByte(hex(int(setConf['thirdCoinTime'])), 4)
- devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
- {'IMEI': self._device['devNo'], "funCode": '18', 'data': data})
- if devInfo.has_key('rst') and devInfo['rst'] != 0:
- if devInfo['rst'] == -1:
- raise ServiceException(
- {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
- elif devInfo['rst'] == 1:
- raise ServiceException(
- {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
- data = devInfo['data'][6::]
- if data[0:2] == '01': # 表示成功
- self.device.update_other_conf(
- cst=int(setConf['cst']), coinMin=int(setConf['coinMin']),
- coinElec=int(setConf['coinElec']), cardMin=int(setConf['cardMin']),
- cardElec=int(setConf['cardElec']))
- else:
- raise ServiceException({'result': 2, 'description': u'操作端口失败,请重试看能否解决'})
- def response_use_card(self, res, balance, uartId = None):
- logger.info("ready to send response to dev <{}> funcode 10".format(self.device.devNo))
- if not uartId:
- data = '55061001'
- data = data + res + fill_2_hexByte(hex(int(balance * 10)), 4)
- devInfo = MessageSender.send(self.device, DeviceCmdCode.PASSTHROUGH_OPERATE_DEV_NO_RESPONSE,
- {'IMEI': self._device['devNo'], "funCode": '10', 'data': data})
- if devInfo.has_key('rst') and devInfo['rst'] != 0:
- if devInfo['rst'] == -1:
- raise ServiceException(
- {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
- elif devInfo['rst'] == 1: # 等于1的时候,说明服务器和远程模块通讯OK,响应已经收到,不需要异常处理
- pass
- else:
- data = '55061001'
- data = data + res + fill_2_hexByte(hex(int(balance * 10)), 4)
- MessageSender.send(
- self.device,
- DeviceCmdCode.PASSTHROUGH_OPERATE_DEV_NO_RESPONSE,
- {
- "IMEI": self.device.devNo,
- "funCode": '10',
- "data": data,
- "uartId": int(uartId)
- }
- )
- def set_device_function_param(self, request, lastSetConf):
- coinMin = request.POST.get('coinMin', None)
- cardMin = request.POST.get('cardMin', None)
- coinElec = request.POST.get('coinElec', None)
- cardElec = request.POST.get('cardElec', None)
- cst = request.POST.get('cst', None)
- powerMax1 = request.POST.get('powerMax1', None)
- powerMax2 = request.POST.get('powerMax2', None)
- powerMax3 = request.POST.get('powerMax3', None)
- powerMax4 = request.POST.get('powerMax4', None)
- power2Ti = request.POST.get('power2Ti', None)
- power3Ti = request.POST.get('power3Ti', None)
- power4Ti = request.POST.get('power4Ti', None)
- spRecMon = request.POST.get('spRecMon', None)
- spFullEmpty = request.POST.get('spFullEmpty', None)
- fullPowerMin = request.POST.get('fullPowerMin', None)
- fullChargeTime = request.POST.get('fullChargeTime', None)
- elecTimeFirst = request.POST.get('elecTimeFirst', None)
- # 这几个参数是墨小智V3特有的
- stWTime = request.POST.get('stWTime', None)
- temThre = request.POST.get('temThre', None)
- freeUse = request.POST.get('freeUse', None)
- relayMasterSwitch = request.POST.get('relayMasterSwitch', None)
- # 这几个参数是久恒保险丝版本特有的
- firstCoinTime = request.POST.get('firstCoinTime', None)
- secondCoinTime = request.POST.get('secondCoinTime', None)
- thirdCoinTime = request.POST.get('thirdCoinTime', None)
- # 这几个参数是申林电子8档久恒板特有的
- powerMax5 = request.POST.get('powerMax5', None)
- powerMax6 = request.POST.get('powerMax6', None)
- powerMax7 = request.POST.get('powerMax7', None)
- powerMax8 = request.POST.get('powerMax8', None)
- power5Ti = request.POST.get('power5Ti', None)
- power6Ti = request.POST.get('power6Ti', None)
- power7Ti = request.POST.get('power7Ti', None)
- power8Ti = request.POST.get('power8Ti', None)
- if coinMin:
- lastSetConf.update({'coinMin': int(coinMin)})
- if cardMin:
- lastSetConf.update({'cardMin': int(cardMin)})
- if coinElec:
- lastSetConf.update({'coinElec': int(coinElec)})
- if cardElec:
- lastSetConf.update({'cardElec': int(cardElec)})
- if cst:
- lastSetConf.update({'cst': int(cst)})
- if powerMax1:
- lastSetConf.update({'powerMax1': int(powerMax1)})
- if powerMax2:
- lastSetConf.update({'powerMax2': int(powerMax2)})
- if powerMax3:
- lastSetConf.update({'powerMax3': int(powerMax3)})
- if powerMax4:
- lastSetConf.update({'powerMax4': int(powerMax4)})
- if power2Ti:
- lastSetConf.update({'power2Ti': int(power2Ti)})
- if power3Ti:
- lastSetConf.update({'power3Ti': int(power3Ti)})
- if power4Ti:
- lastSetConf.update({'power4Ti': int(power4Ti)})
- if spRecMon:
- lastSetConf.update({'spRecMon': int(spRecMon)})
- if spFullEmpty:
- lastSetConf.update({'spFullEmpty': int(spFullEmpty)})
- if fullPowerMin:
- lastSetConf.update({'fullPowerMin': int(fullPowerMin)})
- if fullChargeTime:
- lastSetConf.update({'fullChargeTime': int(fullChargeTime)})
- if elecTimeFirst:
- lastSetConf.update({'elecTimeFirst': int(elecTimeFirst)})
- # 这几个参数是墨小智V3特有的
- if stWTime:
- lastSetConf.update({'stWTime': int(stWTime)})
- if temThre:
- lastSetConf.update({'temThre': int(temThre)})
- if freeUse:
- lastSetConf.update({'freeUse': int(freeUse)})
- # 这几个参数是久恒保险丝版本特有的
- if firstCoinTime:
- lastSetConf.update({'firstCoinTime': int(firstCoinTime)})
- if secondCoinTime:
- lastSetConf.update({'secondCoinTime': int(secondCoinTime)})
- if thirdCoinTime:
- lastSetConf.update({'thirdCoinTime': int(thirdCoinTime)})
- # 这几个参数是申林电子8档久恒板特有的
- if powerMax5:
- lastSetConf.update({'powerMax5': int(powerMax5)})
- if powerMax6:
- lastSetConf.update({'powerMax6': int(powerMax6)})
- if powerMax7:
- lastSetConf.update({'powerMax7': int(powerMax7)})
- if powerMax8:
- lastSetConf.update({'powerMax8': int(powerMax8)})
- if power5Ti:
- lastSetConf.update({'power5Ti': int(power5Ti)})
- if power6Ti:
- lastSetConf.update({'power6Ti': int(power6Ti)})
- if power7Ti:
- lastSetConf.update({'power7Ti': int(power7Ti)})
- if power8Ti:
- lastSetConf.update({'power8Ti': int(power8Ti)})
- if all([powerMax5, powerMax6, powerMax7, powerMax8, power5Ti, power6Ti, power7Ti, power8Ti]) is True:
- self.set_shenlin_8_gear_settings(lastSetConf)
- else:
- self.set_dev_setting(lastSetConf)
- # 新增总继电器开关
- if relayMasterSwitch:
- try:
- self.relay_master_switch(relayMasterSwitch)
- except Exception as e:
- pass
- def handle_clear_start_error(self, port):
- dealer = Dealer.objects.get(id = self._device["ownerId"])
- if not dealer or not dealer.managerialOpenId:
- return
- group = Group.get_group(self._device["groupId"])
- self.lock_unlock_port(port, lock = False)
- notifyData = {
- "title": "设备故障报警解除",
- "device": u"{gNum}组-{lc}-{port}端口".format(gNum = self._device["groupNumber"],
- lc = self._device["logicalCode"],
- port = port),
- "location": u"{address}-{groupName}".format(address = group["address"], groupName = group["groupName"]),
- "fault": u"当前端口已被正常启动,端口故障解除",
- "notifyTime": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- }
- task_caller(
- func_name = 'report_to_dealer_via_wechat',
- openId = dealer.managerialOpenId,
- dealerId = str(dealer.id),
- templateName = "device_fault",
- **notifyData
- )
- self.lock_unlock_port(port, lock = False)
- def handle_out_start_error(self, port):
- dealer = Dealer.objects.get(id = self._device["ownerId"])
- if not dealer or not dealer.managerialOpenId:
- return
- group = Group.get_group(self._device["groupId"])
- times = Device.get_error_start_times(self._device["devNo"], port)
- self.lock_unlock_port(port, lock = True)
- notifyData = {
- "title": u"注意,您的设备可能发生故障!",
- "device": u"{gNum}组-{lc}-{port}端口".format(gNum = self._device["groupNumber"],
- lc = self._device["logicalCode"],
- port = port),
- "location": u"{address}-{groupName}".format(address = group["address"], groupName = group["groupName"]),
- "fault": u"当前设备端口连续启动 {times} 失败,目前该端口已经被自动禁用,请注意该端口是否发生故障".format(times = times),
- "notifyTime": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- }
- task_caller(
- func_name = 'report_to_dealer_via_wechat',
- openId = dealer.managerialOpenId,
- dealerId = str(dealer.id),
- templateName = "device_fault",
- **notifyData
- )
- # 麦总的告警3次触发,同时锁定设备,为避免解锁设备之后 再次触发 这个地方需要将其缓存清空
- Device.delete_error_start_times(self._device["devNo"], port)
- @SmartBox.check_device_features(device_features=["fun_code_30_31"])
- def relay_master_switch(self,relayMasterSwitch=1):
- if relayMasterSwitch == 1:
- data = "01"
- else:
- data = "00"
- devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
- {'IMEI': self._device['devNo'], 'funCode': '31', 'data': data},timeout=7)
- if devInfo.has_key('rst') and devInfo['rst'] != 0:
- if devInfo['rst'] == -1:
- raise ServiceException(
- {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
- elif devInfo['rst'] == 1:
- raise ServiceException(
- {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
- self.device.update_other_conf(relayMasterSwitch=relayMasterSwitch)
- @SmartBox.check_device_features(device_features=["fun_code_30_31"], no_features_to_return={"haveStatus": False})
- def get_real_time_device_info(self):
- try:
- devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
- {'IMEI': self._device['devNo'], 'funCode': '30', 'data': '00'},timeout=7)
- if devInfo.has_key('rst') and devInfo['rst'] != 0:
- if devInfo['rst'] == -1:
- raise ServiceException(
- {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
- elif devInfo['rst'] == 1:
- raise ServiceException(
- {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
- except Exception:
- return {"haveStatus": False}
- data = devInfo.get("data")
- maxPower = int(data[8:12], 16)
- elec = int(data[12:16], 16)
- maxTemperature = int(data[16:18], 16)
- base = -1 if int(data[18:20], 16) == 1 else 1
- temperature = int(data[20:22], 16) * base
- fire = int(data[22:24], 16)
- smoke = int(data[24:26], 16)
- overheat = int(data[26:28], 16)
- overload = int(data[28:30], 16)
- relayMasterSwitch = int(data[30:32], 16)
- return {"haveStatus": True, "maxPower": maxPower, "elec": elec, "maxTemperature": maxTemperature,
- "temperature": temperature,
- "fire": fire, "smoke": smoke, "overheat": overheat, "overload": overload,
- "relayMasterSwitch": relayMasterSwitch, }
- def _response_to_2D(self, sessionId):
- """
- 回复 充电桩主板的2D指令 否则会重复上报
- :param sessionId:
- :return:
- """
- MessageSender.send(
- device=self.device,
- cmd=DeviceCmdCode.OPERATE_DEV_NO_RESPONSE,
- payload={
- "funCode": "2D",
- "data": sessionId,
- "IMEI": self.device.devNo
- }
- )
- def _check_package(self, package):
- """
- 获取设备启动的发送数据 根据设备的当前模式以及套餐获取
- :param package:
- :return:
- """
- unit = package.get("unit", u"分钟")
- _time = float(package.get("time", 0))
- # 按时间计费
- if unit == u"小时":
- billingType = "time"
- _time = _time * 60
- elif unit == u"天":
- billingType = "time"
- _time = _time * 24 * 60
- elif unit == u"秒":
- billingType = "time"
- _time = _time / 60
- elif unit == u"分钟":
- billingType = "time"
- _time = _time
- else:
- billingType = "elec"
- _time = _time
- return _time, unit, billingType
- def response_card(self, res, balance, fee, oper, cardNoHex, isVir=False, virtual_card_id=None):
- if isVir:
- res = int(res)
- count = int(balance) * 10
- fee = int(fee) * 10
- oper = int(oper)
- MessageSender.send(
- device=self.device,
- cmd=220,
- payload={
- "res": res,
- "balance": count,
- "card_cst": fee,
- "card_ope": oper,
- "card_id": cardNoHex,
- "funCode": "10",
- "isVir": isVir,
- "virtual_card_id": virtual_card_id
- }
- )
- else:
- res = int(res)
- balance = int(balance) * 10
- fee = int(fee) * 10
- oper = int(oper)
- MessageSender.send(
- device=self.device,
- cmd=220,
- payload={
- "res": res,
- "balance": balance,
- "card_cst": fee,
- "card_ope": oper,
- "card_id": cardNoHex,
- "funCode": "10",
- "isVir": isVir
- }
- )
- def apiGetPortStatusFromJh(self, record):
- return self.get_port_status_from_dev()
- def apiGetPortStatusFromJn(self, record):
- port = record['port']
- statusData = self.get_port_status_from_dev()
- portData = self.get_port_info(port)
- device = Device.objects(devNo=self._device.devNo).first()
- group = Group.objects(id=device.groupId).first()
- cs = ConsumeRecord.objects(devNo=self._device.devNo).order_by('-dateTimeAdded')[0:10]
- elecValue = 0
- for _ in cs:
- if _.attachParas.get('chargeIndex', '0') == port:
- usedHours = round(float(round(((datetime.datetime.now() - _.dateTimeAdded).total_seconds() / 60.0))) / 60, 2)
- elecValue = round((usedHours * portData.get('power', 0)) / 1000, 2)
- break
- else:
- elecValue = 0
- status = statusData.get(portData.get('port', -1), '04')
- if status != '01':
- elecValue = 0
- voltage = random.randint(220, 240)
- elecCurrent = 0
- result = {
- 'port': portData.get('port', -1), # int
- 'status': statusData.get(portData.get('port', -1), '04'), # str '00' -> idle, '01' -> working, '03' -> 'forbidden', '04' -> 'fault'
- 'voltage': voltage, # int
- 'deviceCode': self._device.logicalCode, # str
- 'elecCurrent': elecCurrent, # float
- 'elecValue': elecValue, # float
- 'leftTime': portData.get('leftTime', 0) * 60, # int 秒
- 'groupName': group.groupName # str
- }
- return result
- def apiStartDeviceForJh(self, record):
- port = record['port']
- minutes = record['time']
- elec = record['elec']
- hexPort = fill_2_hexByte(hex(int(port)), 2)
- hexCoins = '000A'
- hexTime = fill_2_hexByte(hex(int(minutes)))
- hexElec = fill_2_hexByte(hex(int(float(elec) * 100)), 4)
- devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {
- 'IMEI': self._device['devNo'],
- "funCode": '14',
- 'data': hexPort + hexCoins + hexTime + hexElec
- }, timeout=10)
- if devInfo.has_key('rst') and devInfo['rst'] != 0:
- if devInfo['rst'] == -1:
- return {'result': u'启动失败', 'resultStatus': 2, 'description': u'当前设备信号弱无响应。'}
- elif devInfo['rst'] == 1:
- return {'result': u'启动失败', 'resultStatus': 2, 'description': u'设备串口不通。'}
- data = devInfo['data'][6::]
- if data[0:2] == '01': # 表示成功
- pass
- else:
- return {'result': u'启动失败', 'resultStatus': 2, 'description': u'设备返回失败。'}
- result = data[4:6]
- if result == '01': # 成功
- pass
- elif result == '0B':
- return {'result': u'启动失败', 'resultStatus': 2, 'description': u'设备故障。'}
- elif result == '0C':
- return {'result': u'启动失败', 'resultStatus': 2, 'description': u'端口正在使用中。'}
- start_timestamp = int(time.time())
- portDict = {
- 'startTime': timestamp_to_dt(start_timestamp).strftime('%Y-%m-%d %H:%M:%S'),
- 'status': Const.DEV_WORK_STATUS_WORKING,
- 'coins': 1,
- 'price': 1,
- 'needElec': elec,
- 'needTime': minutes,
- 'isApi': True
- }
- Device.update_dev_control_cache(self._device['devNo'], {str(port): portDict})
- return {'result': u'启动成功', 'resultStatus': 1, 'description': u'设备开始充电。'}
- def apiStopChargingPortForJh(self, record):
- port = record['port']
- self.stop_charging_port(port)
- return {'result': u'停止充电成功', 'resultStatus': 1, 'description': u'{}号端口停止充电。'.format(str(port))}
- def apiGetPortInfoFromJh(self, record):
- result = self.get_port_info(record['port'])
- result.pop('surp')
- return result
- def get_ports_info(self, **kw):
- result = self.get_port_status_from_dev()
- port_list = []
- ctrInfo = Device.get_dev_control_cache(self.device.devNo)
- statsMap = {Const.DEV_WORK_STATUS_IDLE: 'idle',
- Const.DEV_WORK_STATUS_WORKING: 'busy',
- Const.DEV_WORK_STATUS_FAULT: 'fault',
- Const.DEV_WORK_STATUS_FORBIDDEN: 'ban',
- Const.DEV_WORK_STATUS_CONNECTED: 'connected',
- Const.DEV_WORK_STATUS_FINISHED: 'finished'}
- for port, _info in result.items():
- _info['index'] = port
- if _info.get('status') == Const.DEV_WORK_STATUS_WORKING:
- _info.update(self.get_port_using_detail(port, ctrInfo, isLazy=True))
- for k, v in _info.items():
- if k.lower().endswith('money'):
- _info.pop(k)
- _info['status'] = statsMap.get(_info['status'], 'busy')
- port_list.append(_info)
- return port_list
- def _set_service_charge_pare_for_dev(self, elecCharge, serviceCharge, on):
- _elecCharge = float(str(elecCharge))
- _serviceCharge = float(str(serviceCharge))
- billAsServiceSwitch = '01' if on else '00'
- hexElecCharge_4 = fill_2_hexByte(hex(int(_elecCharge * 100)), 4)
- hexServiceCharge_4 = fill_2_hexByte(hex(int(_serviceCharge * 100)), 4)
- data = billAsServiceSwitch + hexElecCharge_4 + hexServiceCharge_4 + "0000000000"
- devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {
- 'IMEI': self._device['devNo'],
- "funCode": '22',
- 'data': data
- }, timeout=7)
- 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'设备通讯失败'})
- self.device.update_device_obj(**{
- 'devType.features.billAsService.elecCharge': _elecCharge,
- 'devType.features.billAsService.serviceCharge': _serviceCharge,
- 'devType.features.billAsService.on': True if billAsServiceSwitch == '01' else False
- })
- def __get_service_charge_pare_for_dev(self):
- serviceChargeInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
- {"funCode": '23', 'data': '00'}, timeout=7)
- if serviceChargeInfo['rst'] != 0:
- if serviceChargeInfo['rst'] == -1:
- raise ServiceException(
- {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
- elif serviceChargeInfo['rst'] == 1:
- raise ServiceException(
- {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
- else:
- raise ServiceException(
- {'result': 2, 'description': u'设备通讯失败'})
- data = serviceChargeInfo['data'][8:]
- on = True if data[:2] == '01' else False
- elecCharge = float(int(data[2:6], 16)) / 100
- serviceCharge = float(int(data[6:10], 16)) / 100
- Device.get_collection().update_one({'devNo': self.device.devNo}, {
- '$set': {
- 'devType.features.billAsService.elecCharge': elecCharge,
- 'devType.features.billAsService.serviceCharge': serviceCharge,
- 'devType.features.billAsService.on': on
- }})
- Device.invalid_device_cache(self.device.devNo)
- return {
- "on": on,
- "elecCharge": elecCharge,
- "serviceCharge": serviceCharge
- }
- def response_balance_inquiry_50(self,balance,leftDayQuota,cardNo,status,power='0000'):
- hexBalance = fill_2_hexByte(hex(int(float(balance) * 10)))
- hexLeftDayQuota = fill_2_hexByte(hex(int(leftDayQuota)))
- hexCardNo = fill_2_hexByte(hex(int(cardNo)))
- hexStatus = fill_2_hexByte(hex(int(status)),2)
- hexPower = fill_2_hexByte(hex(int(float(power))))
- data = hexBalance + hexLeftDayQuota + hexCardNo + hexStatus + hexPower
- MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_NO_RESPONSE,
- {'IMEI': self._device['devNo'], 'funCode': '50', 'data': data}, timeout=7)
- def response_use_card_52(self,cardNo):
- data = fill_2_hexByte(hex(int(cardNo)),8)
- MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_NO_RESPONSE,
- {'IMEI': self._device['devNo'], 'funCode': '52', 'data': data}, timeout=7)
- def respone_use_card_finished_56(self,cardNo):
- data = fill_2_hexByte(hex(int(cardNo)),8)
- MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_NO_RESPONSE,
- {'IMEI': self._device['devNo'], 'funCode': '56', 'data': data}, timeout=7)
- def response_ak_5X(self,ack_id):
- data = ack_id
- MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_NO_RESPONSE,
- {'IMEI': self._device['devNo'], 'funCode': 'AK', 'data': data}, timeout=7)
- def get_server_setting(self):
- refundProtectionTime = int(self.device.get_other_conf_item('refundProtectionTime', 5))
- return {
- "refundProtectionTime": refundProtectionTime,
- "cardRefundProtectionTime": int(
- self.device.get_other_conf_item('cardRefundProtectionTime', refundProtectionTime)),
- "minUsedTime": int(self.device.get_other_conf_item('minUsedTime', 0)),
- "billingType": self.device.get_other_conf_item('billingType', 'time'),
- "elecFee": float(self.device.get_other_conf_item('elecFee', 0.9))
- }
- def set_server_setting(self, payload):
- minUsedTime = int(payload['minUsedTime'])
- refundProtectionTime = int(payload['refundProtectionTime'])
- cardRefundProtectionTime = int(payload['cardRefundProtectionTime'])
- if minUsedTime > 0:
- if refundProtectionTime >= minUsedTime:
- raise InvalidParameter(u'最小使用时长不能小于扫码保护退费时间')
- if cardRefundProtectionTime >= minUsedTime:
- raise InvalidParameter(u'最小使用时长不能小于刷卡保护退费时间')
- self.device.update_other_conf(refundProtectionTime=refundProtectionTime,
- cardRefundProtectionTime=cardRefundProtectionTime,
- minUsedTime=minUsedTime,
- billingType=payload['billingType'],
- elecFee=float(payload['elecFee']))
- def set_service_fee_info(self, payload):
- self._set_service_charge_pare_for_dev(
- payload['billAsService'].get('elecCharge'), payload['billAsService'].get('serviceCharge'),
- payload['billAsService'].get('on'))
- super(ChargingJNDZBox, self).set_service_fee_info(payload)
- def get_service_fee_info(self):
- rv = super(ChargingJNDZBox, self).get_service_fee_info()
- rv['billAsService'].update(self.__get_service_charge_pare_for_dev())
- return rv
- class IdCardStartAckEvent(AckEvent):
- pass
|