123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821 |
- # -*- coding: utf-8 -*-
- # !/usr/bin/env python
- import binascii
- import datetime
- import logging
- import time
- from apilib.monetary import VirtualCoin
- from apps.web.core.adapter.base import SmartBox, fill_2_hexByte
- from apps.web.core.device_define.dianchuan_CarCharging import ChargeMode, StopReason
- from apps.web.core.networking import MessageSender
- from apps.web.core.exceptions import ServiceException
- from apps.web.constant import DeviceCmdCode, Const
- from apps.web.user.models import ConsumeRecord
- from apps.web.device.models import Device, DeviceType
- from apps.web.utils import concat_user_login_entry_url
- logger = logging.getLogger(__name__)
- class DianchuanCarCharging(SmartBox):
- def _send_data(self, funCode, data, cmd=DeviceCmdCode.OPERATE_DEV_SYNC, timeout=30):
- """
- 调用MessageSender类中的send方法,向主板发送指令信息,并获得其响应
- :param funCode: 功能码,具体内容参考主板协议和驱动
- :param data:
- :param cmd:经典命令码,默认210 命令方向:服务器->驱动->主板,主板->驱动->服务器
- :param timeout:访问超时时间
- :return:主板收到命令后的响应,具体内容参考主板协议和驱动
- """
- # result 中的信息有:cmd,ts (发送响应瞬间的时间戳),IMEI,data,rst
- result = MessageSender.send(
- device=self.device,
- cmd=cmd,
- payload={"IMEI": self.device.devNo, "funCode": funCode, "data": data},
- timeout=timeout
- )
- # 检测rst,-1为网络不通,1为串口不同,-1会发生在任何传输过程,1指挥发生在驱动到主板端
- if result.get('rst') == -1:
- raise ServiceException({'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
- if result.get('rst') == 1:
- raise ServiceException({'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
- return result
- @staticmethod
- def _suit_package(package):
- '''
- 返回充电模式以及充电参数
- '''
- unit = package["unit"]
- coins = VirtualCoin(package['coins'])
- userAcquire = package["time"]
- nowTime = int(time.time())
- if unit == u"天":
- mode = ChargeMode.TIME_QUOTA
- chargeParam = userAcquire * 24 * 60
- finishedTime = nowTime + chargeParam * 60
- return mode, chargeParam, finishedTime
- elif unit == u"小时":
- mode = ChargeMode.TIME_QUOTA
- chargeParam = userAcquire * 60
- finishedTime = nowTime + chargeParam * 60
- return mode, chargeParam, finishedTime
- elif unit == u"分钟":
- mode = ChargeMode.TIME_QUOTA
- chargeParam = userAcquire
- finishedTime = nowTime + chargeParam * 60
- return mode, chargeParam, finishedTime
- elif unit == u"度":
- mode = ChargeMode.ELEC_QUOTA
- chargeParam = userAcquire * 100
- finishedTime = nowTime + 12 * 60 * 60
- return mode, chargeParam, finishedTime
- elif unit == u"次": # 充满自停
- mode = ChargeMode.COIN_QUOTA
- chargeParam = int((coins * 100).amount)
- finishedTime = nowTime + 12 * 60 * 60
- return mode, chargeParam, finishedTime
- @staticmethod
- def _to_ascii(s):
- '''
- 将数据转化为二进制数据的十六进制表示
- :param s:
- :return:
- '''
- return binascii.hexlify(s).upper()
- @staticmethod
- def _to_str(h):
- """
- 将 16进制ascii 转换成 字符串
- :param h:
- :return:
- """
- return binascii.unhexlify(h).lower()
- # 状态查询
- def _status_check(self):
- network_status = fill_2_hexByte(hex(int(1)), 2)
- network_quality = fill_2_hexByte(hex(int(10)), 2)
- data = network_status + network_quality + '{:0>12}'.format(0)
- result = self._send_data("41", data=data)
- data = result['data']
- port_count = data[8:10],
- port_status = [data[10:14][i:i + 2] for i in range(len(data[12:16])) if i % 2 == 0]
- pile_status = [str(binascii.hexlify(binascii.unhexlify(fill_2_hexByte(bin(int(data[14:18])), 16))[::-1]))[i] for
- i in range(-1, -6, -1)]
- statusInfo = {
- 'port_count': port_count,
- 'port_status': port_status,
- 'pile_status': pile_status
- }
- result['statusInfo'] = statusInfo
- return result #
- # 生成seqNo
- def _make_seqNo(self, port, logicNo):
- """
- 生成流水号
- :param port:充电端口
- :param logicNo:充电桩的设备码
- :return:特征码+桩编号后 4 位+ 月日时分秒+端口号+充电计数
- """
- characteristic_code = '55' # 本地启动特征码为 0x99,远程启动特征码为 0x55
- logicNo_four_digits = logicNo[-4:]
- date_MDHMS = time.strftime('%m%d%H%M%S')
- portHex = fill_2_hexByte(hex(int(port)), 2)
- # charge_count = fill_2_hexByte(hex(random.randint(0, 255)),2)
- charge_count = fill_2_hexByte(logicNo[:2], 2)
- seqNo = characteristic_code + logicNo_four_digits + date_MDHMS + portHex + charge_count
- return seqNo
- # 生成配置表单
- def _make_config_list(self, top_price_rate, peak_price_rate, normal_price_rate, valley_price_rate,
- half_hour_price_list):
- top_price_rateHex = binascii.hexlify(binascii.unhexlify(fill_2_hexByte(hex(int(top_price_rate)), 4))[::-1])
- peak_price_rateHex = binascii.hexlify(binascii.unhexlify(fill_2_hexByte(hex(int(peak_price_rate)), 4))[::-1])
- normal_price_rateHex = binascii.hexlify(
- binascii.unhexlify(fill_2_hexByte(hex(int(normal_price_rate)), 4))[::-1])
- valley_price_rateHex = binascii.hexlify(
- binascii.unhexlify(fill_2_hexByte(hex(int(valley_price_rate)), 4))[::-1])
- half_hour_priceHex = ''.join(
- fill_2_hexByte(hex(int(half_hour_price)), 2) for half_hour_price in half_hour_price_list)
- data = top_price_rateHex + peak_price_rateHex + normal_price_rateHex + valley_price_rateHex + half_hour_priceHex + '{:0>16}'.format(
- 0)
- return data
- # 查询当前的配置表
- def _config_list_check(self):
- result = self._send_data('48', '55')
- code = result['data'][8:10]
- if code == '55':
- return self._parse_config_change_upload(result['data'])
- raise ServiceException({'result': 2, 'description': u'信息查询错误'})
- # 配置表主动下发
- def _config_list_issue(self, top_price_rate, peak_price_rate, normal_price_rate, valley_price_rate,
- half_hour_price_list):
- data = self._make_config_list(top_price_rate, peak_price_rate, normal_price_rate, valley_price_rate,
- half_hour_price_list)
- result = self._send_data('49', data=data)
- code = result['data'][8:10]
- if code == '00':
- return result
- else:
- raise ServiceException({'result': 2, 'description': u'请求失败,请重试'})
- # 控制设备
- def _control_device(self, pile_instruct, port_instruct):
- pile_instructHex = binascii.hexlify(binascii.unhexlify(fill_2_hexByte(hex(pile_instruct), 4))[::-1])
- port_instructHex = fill_2_hexByte(hex(port_instruct), 4)
- data = pile_instructHex + port_instructHex + '{:0>16}'.format(0)
- result = self._send_data('47', data=data)
- code = result['data'][8:10]
- if code == "00":
- return result
- else:
- raise ServiceException({'result': 2, 'description': u'设备操作失败'})
- # 下发二维码以及模块编号
- def _qr_code_devNo_issue(self):
- deviceNo = self._to_ascii(self.device.devNo)
- if deviceNo[0:1] == 'G':
- deviceNo = self._to_ascii(deviceNo[1:])
- qr_code_url = self._to_ascii(concat_user_login_entry_url(l=self._device["logicalCode"])).ljust(128, "0")
- data = qr_code_url + deviceNo
- self._send_data('89', data=data)
- # 远程启动
- def _start_remote(self, port, seqNo, mode, chargeParam, balance):
- """
- 拼接远程启动指令并发送到主板,获取启动响应
- :param port:设备端口号
- :param seqNo: 设备logic码
- :param mode:停止充电条件
- :param chargeParam:充电参数:充电金额,充电时间,充电电量等
- :param balance:充电支付的总金额
- :return:主板返回的远程启动响应
- """
- seqNo = seqNo
- card_No = '00000000'
- portHex = fill_2_hexByte(hex(int(port)), 2)
- modeHex = fill_2_hexByte(hex(int(mode)), 2)
- chargeParamHex = binascii.hexlify(binascii.unhexlify(fill_2_hexByte(hex(int(chargeParam)), 4))[::-1])
- balanceHex = binascii.hexlify(binascii.unhexlify(fill_2_hexByte(hex(int(balance)), 8))[::-1]).upper()
- data = seqNo + card_No + portHex + modeHex + chargeParamHex + balanceHex + '{:0>36}'.format(0)
- result = self._send_data("42", data=data)
- code = result["data"][10:-4]
- if code == "00":
- return result
- if code == '11':
- raise ServiceException({'result': 2, 'description': u'您使用的充电枪已经在充电了,请您换其他空闲的充电枪吧!'})
- if code == '12':
- raise ServiceException({'result': 2, 'description': u'您没有插充电枪,请先插好充电枪,然后再操作哦!'})
- if code == '13':
- raise ServiceException({'result': 2, 'description': u'充电故障,暂时无法使用,您本次操作不会扣费,您可以试试其他可用的设备。'})
- if code == '14':
- raise ServiceException({'result': 2, 'description': u'待机故障,暂时无法使用,您本次操作不会扣费,您可以试试其他可用的设备。'})
- if code == '15':
- raise ServiceException({'result': 2, 'description': u'车辆未连接,请先插好充电枪,然后再操作哦!'})
- if code == '16':
- raise ServiceException({'result': 2, 'description': u'设备紧急按钮已被按下,请确认设备是否正常工作,然后再操作哦!'})
- if code == '17':
- raise ServiceException({'result': 2, 'description': u'正在等待上次充电结算,请您换其他空闲的充电枪吧!'})
- if code == '18':
- raise ServiceException({'result': 2, 'description': u'无此端口,本次操作不会扣费,请您重试看是否能够解决'})
- if code == '19':
- raise ServiceException({'result': 2, 'description': u'设备已暂停服务,请您换其他空闲的充电枪吧!'})
- raise ServiceException({'result': 2, 'description': u'设备返回一个未知的错误,本次操作不会扣费,请您重试看是否能够解决'})
- # 远程停止
- def _stop_remote(self, port, seqNo):
- """
- 远程停止
- """
- portHex = fill_2_hexByte(hex(int(port)), 2)
- seqNo = seqNo
- data = seqNo + portHex
- result = self._send_data('45', data)
- if result['data'][30:-4] != "00":
- if result['data'][30:-4] == "01":
- raise ServiceException({'result': 2, 'description': u'该充电枪已经空闲,没有充电'})
- else:
- raise ServiceException({'result': 2, 'description': u'断电失败'})
- return result
- # 配置表变化上传
- @staticmethod
- def _parse_config_change_upload(data):
- top_rate = int(binascii.hexlify(binascii.unhexlify(data[10:14])[::-1]), 16)
- top_price_rate = str(float(top_rate) / 100)
- peak_rate = int(binascii.hexlify(binascii.unhexlify(data[14:18])[::-1]), 16)
- peak_price_rate = str(float(peak_rate) / 100)
- normal_rate = int(binascii.hexlify(binascii.unhexlify(data[18:22])[::-1]), 16)
- normal_price_rate = str(float(normal_rate) / 100)
- valley_rate = int(binascii.hexlify(binascii.unhexlify(data[22:26])[::-1]), 16)
- valley_price_rate = str(float(valley_rate) / 100)
- half_hour_price_list = [str(int(i)) for i in
- [data[26:-20][i:i + 2] for i in range(len(data[26:-20]) - 1) if i % 2 == 0]]
- return {
- 'top_price_rate': top_price_rate,
- 'peak_price_rate': peak_price_rate,
- 'normal_price_rate': normal_price_rate,
- 'valley_price_rate': valley_price_rate,
- 'half_hour_price_list': half_hour_price_list
- }
- # 充电实时数据上报
- @staticmethod
- def _charge_data_report(data):
- current_rate = data[8:10]
- port_count = data[10:12] # 正在充电的端口数量
- port_data = {}
- tag = 12
- for i in range(port_count):
- port_data[i] = {
- 'chargeIndex': data[tag:tag + 2],
- 'output_voltage': str(int(binascii.hexlify(binascii.unhexlify(data[tag + 2:tag + 6])[::-1]), 16)),
- 'output_current': str(int(binascii.hexlify(binascii.unhexlify(data[tag + 6:tag + 10])[::-1]), 16)),
- 'output_power': str(int(binascii.hexlify(binascii.unhexlify(data[tag + 10:tag + 14])[::-1]), 16)),
- 'used_time': str(int(binascii.hexlify(binascii.unhexlify(data[tag + 14:tag + 18])[::-1]), 16)),
- 'top_elec': str(int(binascii.hexlify(binascii.unhexlify(data[tag + 18:tag + 22])[::-1]), 16)),
- 'peak_elec': str(int(binascii.hexlify(binascii.unhexlify(data[tag + 22:tag + 26])[::-1]), 16)),
- 'normal_elec': str(int(binascii.hexlify(binascii.unhexlify(data[tag + 26:tag + 30])[::-1]), 16)),
- 'vallery_elec': str(int(binascii.hexlify(binascii.unhexlify(data[tag + 30:tag + 34])[::-1]), 16)),
- 'total_elec': str(int(binascii.hexlify(binascii.unhexlify(data[tag + 34:tag + 38])[::-1]), 16)),
- 'top_expense': str(int(binascii.hexlify(binascii.unhexlify(data[tag + 38:tag + 42])[::-1]), 16)),
- 'peak_expense': str(int(binascii.hexlify(binascii.unhexlify(data[tag + 42:tag + 46])[::-1]), 16)),
- 'normal_expense': str(int(binascii.hexlify(binascii.unhexlify(data[tag + 46:tag + 50])[::-1]), 16)),
- 'vallery_expense': str(int(binascii.hexlify(binascii.unhexlify(data[tag + 50:tag + 54])[::-1]), 16)),
- 'total_expense': str(int(binascii.hexlify(binascii.unhexlify(data[tag + 54:tag + 58])[::-1]), 16)),
- }
- tag = tag + 58
- return {
- 'current_rate': current_rate,
- 'port_count': port_count,
- 'port_data': port_data,
- }
- def _response_finished(self, seqNo):
- seqNo = seqNo
- self._send_data("AK", seqNo, cmd=DeviceCmdCode.OPERATE_DEV_NO_RESPONSE)
- # 获取二维码以及设备编号
- def _parse_get_qr_code_devNo(self, data):
- time = int(data[8:-4], 16)
- self._qr_code_devNo_issue()
- @property
- def isHaveStopEvent(self):
- return True
- # 分析上报事件数据
- def analyze_event_data(self, data):
- cmdcode = data[6:8]
- if cmdcode == '36':
- seqNo = data[8:28]
- port = int(data[28:30], 16)
- mode = int(data[30:32], 16)
- startTime = data[40:54]
- finishTime = data[54:68]
- eDuration = int(binascii.hexlify(binascii.unhexlify(data[68:72])[::-1]), 16)
- top_spend_elec = float(int(binascii.hexlify(binascii.unhexlify(data[72:76])[::-1]), 16))
- peak_spend_elec = float(int(binascii.hexlify(binascii.unhexlify(data[76:80])[::-1]), 16))
- normal_spend_elec = float(int(binascii.hexlify(binascii.unhexlify(data[80:84])[::-1]), 16))
- valley_spend_elec = float(int(binascii.hexlify(binascii.unhexlify(data[84:88])[::-1]), 16))
- top_spend_money = int(binascii.hexlify(binascii.unhexlify(data[88:92])[::-1]), 16)
- peak_spend_money = int(binascii.hexlify(binascii.unhexlify(data[92:96])[::-1]), 16)
- normal_spend_money = int(binascii.hexlify(binascii.unhexlify(data[96:100])[::-1]), 16)
- valley_spend_money = int(binascii.hexlify(binascii.unhexlify(data[100:104])[::-1]), 16)
- total_spend_elec = float(int(binascii.hexlify(binascii.unhexlify(data[104:108])[::-1]), 16))
- total_spend_money = float(int(binascii.hexlify(binascii.unhexlify(data[108:112])[::-1]), 16))
- reason = str(int(data[120:122], 16))
- eDuration = eDuration / 60
- top_spend_elec = top_spend_elec / 100
- peak_spend_elec = peak_spend_elec / 100
- normal_spend_elec = normal_spend_elec / 100
- valley_spend_elec = valley_spend_elec / 100
- top_spend_money = top_spend_money / 100
- peak_spend_money = peak_spend_money / 100
- normal_spend_money = normal_spend_money / 100
- valley_spend_money = valley_spend_money / 100
- total_spend_elec = total_spend_elec / 100
- total_spend_money = total_spend_money / 100
- if reason == StopReason.NO_SUFFICIENT_BALANCE:
- desc = '余额不足'
- elif reason == StopReason.CHARGE_TIME_DONE:
- desc = '已充电到指定时间'
- elif reason == StopReason.CHARGE_ELEC_DONE:
- desc = '已充电到指定电量'
- elif reason == StopReason.CHARGE_MONEY_DONE:
- desc = '已充电到指定金额'
- elif reason == StopReason.SCRAM_BUTTON_STOP:
- desc = '急停按钮被按下,请联系管理员或客服'
- elif reason == StopReason.CC_DISCONNECT:
- desc = '枪把断开连接,请稍候再试'
- elif reason == StopReason.CP_SIGNAL_ABNORMAL:
- desc = '电压信号异常,请稍候再试'
- elif reason == StopReason.CHARGE_DONE:
- desc = '充电已完成'
- elif reason == StopReason.CURRENT_OVERLOAD:
- desc = '电流超载,请稍候再试'
- elif reason == StopReason.ELECTRIC_METER_FAILURE:
- desc = '电表故障,请联系管理员或客服'
- elif reason == StopReason.CHARGING_PILE_DISABLE:
- desc = '充电桩被远程停止已停用'
- elif reason == StopReason.CP_DISCONNECT:
- desc = '充电枪断开连接'
- elif reason == StopReason.USER_CARD_STOP:
- desc = '刷卡停止'
- elif reason == StopReason.CHARGING_PILE_POWER_OUTAGES:
- desc = '充电桩断电,请联系管理员或客服'
- elif reason == StopReason.ELEC_PRICE_EQUAL_ZERO:
- desc = '电价设置异常,请联系管理员或客服'
- else:
- desc = ''
- return {
- 'cmdCode': '36',
- 'seqNo': seqNo,
- 'port': port,
- 'mode': mode,
- 'startTime': startTime,
- 'finishTime': finishTime,
- 'eDuration': eDuration,
- 'top_spend_elec': top_spend_elec,
- 'peak_spend_elec': peak_spend_elec,
- 'normal_spend_elec': normal_spend_elec,
- 'valley_spend_elec': valley_spend_elec,
- 'top_spend_money': top_spend_money,
- 'peak_spend_money': peak_spend_money,
- 'normal_spend_money': normal_spend_money,
- 'valley_spend_money': valley_spend_money,
- 'total_spend_elec': total_spend_elec,
- 'total_spend_money': total_spend_money,
- 'reason': desc
- }
- if cmdcode == '79':
- return {
- 'cmdCode': '79'
- }
- if cmdcode == '34':
- return {
- 'cmdCode': '34'
- }
- # 启动设备
- def start_device(self, package, openId, attachParas):
- chargeIndex = attachParas.get("chargeIndex")
- if not chargeIndex:
- raise ServiceException({'result': 2, 'description': u'请您选择合适的充电线路'})
- if not openId:
- raise ServiceException({"result": 2, "description": u"本设备暂不支持上分"})
- devStatus = self.get_port_status_from_dev()
- if devStatus[chargeIndex]['status'] != Const.DEV_WORK_STATUS_CONNECTED:
- raise ServiceException(
- {'result': 2, 'description': u'车辆未连接,请先连接车辆!'})
- mode, chargeParam, finishedTime = self._suit_package(package)
- seqNo = str(self._make_seqNo(chargeIndex, self.device.devNo))
- order = ConsumeRecord.objects.get(orderNo=attachParas["orderNo"]) # type: ConsumeRecord
- order.sequanceNo = seqNo
- order.save()
- balance = int((VirtualCoin(package['price']) * 100))
- result = self._start_remote(chargeIndex, seqNo, mode, chargeParam, balance)
- portDict = {
- 'startTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- 'status': Const.DEV_WORK_STATUS_WORKING,
- 'finishedTime': finishedTime,
- 'coins': float(balance) / 100,
- 'isStart': True,
- 'sequanceNo': seqNo,
- 'orderNo': attachParas['orderNo'],
- 'useType': 'mobile',
- 'openId': openId,
- 'refunded': False,
- 'chargeMode': mode,
- 'need': chargeParam,
- }
- Device.update_dev_control_cache(self._device['devNo'], {str(chargeIndex): portDict})
- result["finishedTime"] = finishedTime
- return result
- # 停止设备
- def stop(self, port=None):
- if not port:
- raise ServiceException({"result": 2, "description": u"请选择需要结束的充电端口"})
- portCache = Device.get_port_control_cache(self.device.devNo, str(port))
- seqNo = portCache.get("sequanceNo")
- if not seqNo:
- raise ServiceException({"result": 2, "description": u"当前端口无工作"})
- return self._stop_remote(port, seqNo)
- # 获取端口运行信息
- def get_port_info(self, line):
- ctrInfo = Device.get_dev_control_cache(self._device['devNo'])
- value = ctrInfo.get(line, {})
- data = self.check_real_elec(line)
- data_list = {'port': line, 'sequanceNo': value['sequanceNo'], 'usedTime': data['eduration'],
- 'elec': data['total_elec'], 'power': data['output_power'], 'outputVoltage': data['output_voltage'],
- 'elecFee':data['total_spend']}
- serviceChargeOn = self.device.bill_as_service_feature.on
- if serviceChargeOn:
- serviceFee = self.caculate_consume(data)
- data_list.update({'serviceFee':serviceFee})
- consumeMoney = data['total_spend'] + serviceFee
- data_list.update({'consumeMoney':consumeMoney})
- else:
- data_list.update({'consumeMoney': data['total_spend']})
- return data_list
- # 获取端口状态
- def get_port_status_from_dev(self):
- devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
- {"IMEI": self.device.devNo, "funCode": '41', "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'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
- result = {}
- data = devInfo['data'][8:14]
- portNum = int(data[0:2], 16)
- portData = data[2::]
- ii = 0
- portNo = 1
- while ii < portNum:
- port = portNo
- statusTemp = portData[ii * 2: ii * 2 + 2]
- if statusTemp == '00':
- status = {'status': Const.DEV_WORK_STATUS_FAULT}
- elif statusTemp == '55':
- status = {'status': Const.DEV_WORK_STATUS_PAUSE}
- elif statusTemp == '10':
- status = {'status': Const.DEV_WORK_STATUS_IDLE}
- elif statusTemp == '11':
- status = {'status': Const.DEV_WORK_STATUS_CONNECTED}
- elif statusTemp == '12':
- status = {'status': Const.DEV_WORK_STATUS_WORKING}
- elif statusTemp == '13':
- status = {'status': Const.DEV_WORK_STATUS_FINISHED}
- elif statusTemp == '14':
- status = {'status': Const.DEV_WORK_STATUS_FAULT}
- elif statusTemp == '15':
- status = {'status': Const.DEV_WORK_STATUS_FAULT}
- elif statusTemp == '16':
- status = {'status': Const.DEV_WORK_STATUS_WORKING}
- else:
- status = {'status': Const.DEV_WORK_STATUS_FAULT}
- ii += 1
- portNo += 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 set_device_function_param(self, request, lastSetConf):
- if request.POST.has_key('top_price_rate') and request.POST.has_key('peak_price_rate') and request.POST.has_key(
- 'normal_price_rate') and request.POST.has_key('valley_price_rate') and request.POST.has_key(
- 'half_hour_price_list'):
- if request.POST.has_key('pile_pause'):
- self._control_device(pile_instruct=1, port_instruct=1)
- return
- elif request.POST.has_key('pile_continue'):
- self._control_device(pile_instruct=0, port_instruct=1)
- return
- elif request.POST.has_key('pile_reboot'):
- self._control_device(pile_instruct=2, port_instruct=1)
- return
- lastSetConf.update({'top_price_rate': float(request.POST.get('top_price_rate', 0))})
- lastSetConf.update({'peak_price_rate': float(request.POST.get('peak_price_rate', 0))})
- lastSetConf.update({'normal_price_rate': float(request.POST.get('normal_price_rate', 0))})
- lastSetConf.update({'valley_price_rate': float(request.POST.get('valley_price_rate', 0))})
- lastSetConf.update({'half_hour_price_list': request.POST.get('half_hour_price_list', 0)})
- self.set_elec_conf(lastSetConf)
- # self.set_elec_charge_by_device(lastSetConf)
- def set_elec_conf(self, infoDic):
- top_price_rateHex = binascii.hexlify(
- binascii.unhexlify(fill_2_hexByte(hex(int(infoDic['top_price_rate'] * 100)), 4))[::-1])
- peak_price_rateHex = binascii.hexlify(
- binascii.unhexlify(fill_2_hexByte(hex(int(infoDic['peak_price_rate'] * 100)), 4))[::-1])
- normal_price_rateHex = binascii.hexlify(
- binascii.unhexlify(fill_2_hexByte(hex(int(infoDic['normal_price_rate'] * 100)), 4))[::-1])
- valley_price_rateHex = binascii.hexlify(
- binascii.unhexlify(fill_2_hexByte(hex(int(infoDic['valley_price_rate'] * 100)), 4))[::-1])
- half_hour_priceHex = ''.join(
- fill_2_hexByte(hex(int(half_hour_price)), 2) for half_hour_price in infoDic['half_hour_price_list'])
- data = top_price_rateHex + peak_price_rateHex + normal_price_rateHex + valley_price_rateHex + half_hour_priceHex + '{:0>16}'.format(
- 0)
- devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
- {'IMEI': self._device['devNo'], "funCode": '49', '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'充电桩忙,无响应,请您稍候再试'})
- # 获取设备配置参数
- def get_dev_setting(self):
- result = MessageSender.send(
- device=self.device,
- cmd=DeviceCmdCode.OPERATE_DEV_SYNC,
- payload={
- "IMEI": self._device["devNo"],
- "data": "55",
- "funCode": "48"
- }
- )
- rst = result.get("rst")
- if rst == -1:
- raise ServiceException({'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
- elif rst == 1:
- raise ServiceException({'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
- elif rst == 0:
- resultDict = self._parse_config_change_upload(result['data'])
- driverCode = self._device.get("devType", dict()).get("code", "")
- resultDict.update({'driverCode': driverCode})
- return resultDict
- def get_port_status(self, force=False):
- if force:
- return self.get_port_status_from_dev()
- statusDict = {}
- # self.async_update_portinfo_from_dev()
- self.get_port_status_from_dev()
- ctrInfo = Device.get_dev_control_cache(self._device['devNo'])
- allPorts = ctrInfo.get('allPorts', 2)
- 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 active_deactive_port(self, port, active):
- if not active:
- self.stop(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 check_real_elec(self, port):
- data = "{:0>2X}".format(int(port))
- result = self._send_data('44', data)
- rst = result.get("rst")
- if rst != 1:
- if rst == -1:
- raise ServiceException({'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
- elif rst == 1:
- raise ServiceException({'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
- elec_info = result.get("data")[8:]
- ii = 0
- port_str = str(int(elec_info[ii:ii + 2]))
- output_voltage = float(int(binascii.hexlify(binascii.unhexlify(elec_info[ii + 2:ii + 6])[::-1]), 16))
- output_current = float(int(binascii.hexlify(binascii.unhexlify(elec_info[ii + 6:ii + 10])[::-1]), 16))
- output_power = float(int(binascii.hexlify(binascii.unhexlify(elec_info[ii + 10:ii + 14])[::-1]), 16))
- eduration = int(binascii.hexlify(binascii.unhexlify(elec_info[ii + 14:ii + 18])[::-1]), 16)
- top_elec = float(int(binascii.hexlify(binascii.unhexlify(elec_info[ii + 18:ii + 22])[::-1]), 16))
- peak_elec = float(int(binascii.hexlify(binascii.unhexlify(elec_info[ii + 22:ii + 26])[::-1]), 16))
- normal_elec = float(int(binascii.hexlify(binascii.unhexlify(elec_info[ii + 26:ii + 30])[::-1]), 16))
- valley_elec = float(int(binascii.hexlify(binascii.unhexlify(elec_info[ii + 30:ii + 34])[::-1]), 16))
- total_elec = float(int(binascii.hexlify(binascii.unhexlify(elec_info[ii + 34:ii + 38])[::-1]), 16))
- top_spend = float(int(binascii.hexlify(binascii.unhexlify(elec_info[ii + 38:ii + 42])[::-1]), 16))
- peak_spend = float(int(binascii.hexlify(binascii.unhexlify(elec_info[ii + 42:ii + 46])[::-1]), 16))
- normal_spend = float(int(binascii.hexlify(binascii.unhexlify(elec_info[ii + 46:ii + 50])[::-1]), 16))
- valley_spend = float(int(binascii.hexlify(binascii.unhexlify(elec_info[ii + 50:ii + 54])[::-1]), 16))
- total_spend = float(int(binascii.hexlify(binascii.unhexlify(elec_info[ii + 54:ii + 58])[::-1]), 16))
- output_voltage = int(output_voltage * 0.1)
- output_current = output_current / 100
- output_power = output_power
- eduration = eduration / 60
- top_elec = top_elec / 100
- peak_elec = peak_elec / 100
- normal_elec = normal_elec / 100
- valley_elec = valley_elec / 100
- total_elec = total_elec / 100
- top_spend = top_spend / 100
- peak_spend = peak_spend / 100
- normal_spend = normal_spend / 100
- valley_spend = valley_spend / 100
- total_spend = total_spend / 100
- new_data = {
- 'port': port_str,
- 'output_voltage': output_voltage,
- 'output_current': output_current,
- 'output_power': output_power,
- 'eduration': eduration,
- 'top_elec': top_elec,
- 'peak_elec': peak_elec,
- 'normal_elec': normal_elec,
- 'valley_elec': valley_elec,
- 'total_elec': total_elec,
- 'top_spend': top_spend,
- 'peak_spend': peak_spend,
- 'normal_spend': normal_spend,
- 'valley_spend': valley_spend,
- 'total_spend': total_spend,
- }
- return new_data
- def get_elec_charge(self):
- # 从主板获取到各时段费费率
- resultDict = self.get_dev_setting()
- # 查找当前时段的费率
- nowTime = datetime.datetime.now().strftime('%H:%M')
- timeNowList = nowTime.split(':')
- index = int(timeNowList[0])*2 + 2 if int(timeNowList[1])>30 else 1 - 1
- nowElecChargeRate = resultDict['half_hour_price_list'][index]
- if nowElecChargeRate == '1':
- nowElecCharge = resultDict['valley_price_rate']
- elif nowElecChargeRate == '2':
- nowElecCharge = resultDict['normal_price_rate']
- elif nowElecChargeRate == '3':
- nowElecCharge = resultDict['peak_price_rate']
- elif nowElecChargeRate == '4':
- nowElecCharge = resultDict['top_price_rate']
- return nowElecCharge
- def set_elec_charge_by_dealer(self,elecCharge):
- IntElecCharge = float(elecCharge)
- infoDic = {
- 'top_price_rate': IntElecCharge,
- 'peak_price_rate': IntElecCharge,
- 'normal_price_rate': IntElecCharge,
- 'valley_price_rate': IntElecCharge,
- 'half_hour_price_list': [IntElecCharge] * 48
- }
- self.set_elec_conf(infoDic)
- def set_elec_charge_by_device(self,lastSetConf):
- half_hour_price_list = lastSetConf['half_hour_price_list']
- for i in range(len(half_hour_price_list)):
- if half_hour_price_list[i] == '01':
- half_hour_price_list[i] = 'top_price_rate'
- elif half_hour_price_list[i] == '02':
- half_hour_price_list[i] = 'peak_price_rate'
- elif half_hour_price_list[i] == '03':
- half_hour_price_list[i] = 'normal_price_rate'
- elif half_hour_price_list[i] == '04':
- half_hour_price_list[i] = 'valley_price_rate'
- elecCharge = {
- 'top_price_rate' :lastSetConf['top_price_rate'],
- 'peak_price_rate' :lastSetConf['peak_price_rate'],
- 'normal_price_rate' :lastSetConf['normal_price_rate'],
- 'valley_price_rate' :lastSetConf['valley_price_rate'],
- 'half_hour_price_list': half_hour_price_list,
- }
- Device.get_collection().update_one({'devNo': self._device['devNo']}, {
- '$set': {
- 'devType.features.billAsService.elecCharge':elecCharge
- }
- })
- Device.invalid_device_cache(self._device['devNo'])
- def caculate_consume(self,data):
- serviceCharge = self._device.bill_as_service_feature.service_charge
- elec = data['total_elec']
- serviceFee = round(serviceCharge * elec,2)
- return serviceFee
- # def get_current_elec_charge_by_database(self):
- # device = None
- # para = device.bill_as_service_feature
- # half_hour_price_list = para.elecCharge.half_hour_price_list
- # nowTime = datetime.datetime.now().strftime('%H:%M')
- # timeNowList = nowTime.split(':')
- # index = int(timeNowList[0]) * 2 + 2 if int(timeNowList[1]) > 30 else 1 - 1
- # currentElecChargeRate = half_hour_price_list['half_hour_price_list'][index]
- # if currentElecChargeRate == '01':
- # elecCharge = para.elecCharge.top_price_rate
- # elif currentElecChargeRate == '02':
- # elecCharge = para.elecCharge.peak_price_rate
- # elif currentElecChargeRate == '03':
- # elecCharge = para.elecCharge.normal_price_rate
- # elif currentElecChargeRate == '04':
- # elecCharge = para.elecCharge.valley_price_rate
- # return elecCharge
- # 从参数设置中配置电费时电费信息存入数据库
- # 获取参数设置时电费信息存入数据库
- # 经销商配置充电费时直接下发到设备
- # 绑定设备时,默认信息直接下发到设备(避免出bug)
- # 获取从数据库中拿,不走设备
- # 查询当前服务费
- # 推送信息
|