123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890 |
- # -*- coding: utf-8 -*-
- # !/usr/bin/env python
- import datetime
- import logging
- import re
- from decimal import Decimal
- from typing import TYPE_CHECKING, Optional
- from apps.web.common.proxy import ClientConsumeModelProxy
- from apps.web.constant import Const, DeviceCmdCode, CONSUMETYPE
- from apps.web.core.adapter.base import SmartBox
- from apps.web.core.adapter.policy_common import PolicyCommon
- from apps.web.core.device_define.jndz import CMD_CODE
- from apps.web.core.exceptions import ServiceException
- from apps.web.core.networking import MessageSender
- from apps.web.dealer.models import Dealer
- from apps.web.device.models import Device, Group
- from taskmanager.mediator import task_caller
- logger = logging.getLogger(__name__)
- if TYPE_CHECKING:
- pass
- # from apps.web.device.models import Device, Group
- # from apps.web.user.models import ConsumeRecord, MyUser, Card
- class CmdHelper(object):
- @staticmethod
- def encode_str(data, length=2, ratio=1.0, base=16):
- # type:(str,int,float,int) -> str
- if not isinstance(data, Decimal):
- data = Decimal(data)
- if not isinstance(length, str):
- length = str(length)
- if not isinstance(ratio, Decimal):
- ratio = Decimal(ratio)
- end = 'X' if base == 16 else 'd'
- encodeStr = '%.' + length + end
- encodeStr = encodeStr % (data * ratio)
- return encodeStr
- @staticmethod
- def decode_str(data, ratio=1, base=16, to_num=True):
- # type:(str,Optional[float, int],int, bool) -> Optional[float, str]
- """
- ratio:比率单位转换
- """
- if not isinstance(data, str):
- data = str(data)
- if to_num:
- return int(data, base) * ratio
- else:
- return '%.10g' % (int(data, base) * ratio)
- @staticmethod
- def reverse_hex(data):
- # type:(str) -> str
- if not isinstance(data, str):
- raise TypeError
- return ''.join(list(reversed(re.findall(r'.{2}', data))))
- @staticmethod
- def split_data_to_list(split_str, data):
- # type:(str,str) ->Optional[list, None]
- """
- return: list
- """
- part = '({})'
- all_ = sum(map(lambda _: int(_) * 2, split_str))
- pattern = reduce(lambda a, b: a + b, map(lambda _: part.format('..' * int(_)), split_str))
- result = re.match(pattern, data[:all_])
- if result:
- return result.groups()
- def decode_long_hex_to_list(self, data, split=2, ratio=1.0, base=16):
- # type:(str,int,float,int) -> list
- """
- return: list
- """
- if len(data) % split != 0:
- raise Exception('Invalid data')
- pattern = r'.{%s}' % split
- hex_list = re.findall(pattern, data)
- hex_list = map(lambda x: self.decode_str(x, ratio=ratio, base=base), hex_list)
- return hex_list
- @staticmethod
- def check_params_range(params, minData=None, maxData=None, desc=''):
- # type:(str,float,float,str) -> str
- """
- 检查参数,返回字符串参数
- """
- if params is None:
- raise ServiceException({'result': 2, 'description': u'参数错误.'})
- if not isinstance(params, Decimal):
- params = Decimal(params)
- if not minData and maxData:
- if not isinstance(maxData, Decimal):
- maxData = Decimal(maxData)
- if params <= maxData:
- return '%g' % params
- else:
- raise ServiceException({'result': 2, 'description': u'%s超出可选范围,可选最大值为%g' % (desc, maxData)})
- if not maxData and minData:
- if not isinstance(minData, Decimal):
- minData = Decimal(minData)
- if minData <= params:
- return '%g' % params
- else:
- raise ServiceException({'result': 2, 'description': u'%s超出可选范围,可选最小值为%g' % (desc, minData)})
- if not minData and not maxData:
- return '%g' % params
- else:
- if not isinstance(minData, Decimal):
- minData = Decimal(minData)
- if not isinstance(maxData, Decimal):
- maxData = Decimal(maxData)
- if minData <= params <= maxData:
- return '%g' % params
- else:
- raise ServiceException(
- {'result': 2, 'description': u'%s参数超出可选范围,可取范围为%g-%g' % (desc, minData, maxData)})
- class JNDZPOLICYBox(PolicyCommon, CmdHelper):
- def __init__(self, device):
- super(JNDZPOLICYBox, self).__init__(device)
- def disable_app_device(self, switch=True):
- # type:(bool) -> None
- otherConf = self.device.get('otherConf', {})
- otherConf['disableDevice'] = switch
- Device.objects.filter(devNo=self.device['devNo']).update(otherConf=otherConf)
- Device.invalid_device_cache(self.device['devNo'])
- @property
- def device_configs(self):
- dev = Device.get_dev(self.device.devNo)
- deviceConfigs = dev.get('otherConf', {}).get('deviceConfigs', {})
- return deviceConfigs
- @property
- def server_configs(self):
- dev = Device.get_dev(self.device.devNo)
- serverConfigs = dev.get('otherConf', {}).get('serverConfigs', {})
- return serverConfigs
- def analyze_event_data(self, device_event):
- # 升级兼容. 避免重启过程中老的消息
- if 'data' in device_event:
- data = device_event['data']
- else:
- data = device_event
- cmdCode = data[4:6]
- # 4个故障的告警
- if 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_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, 16 * port_num, 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_default_port_nums(self):
- data = self.send_mqtt({'funCode': '01', 'data': '00'})
- portTotalNum = self.decode_str(data[8:10])
- theFirst = self.decode_str(data[10:12])
- return portTotalNum, theFirst
- def get_idle_port(self):
- data = self.send_mqtt({'funCode': '02', 'data': '00'})
- idlePortNum = self.decode_str(data[8:10])
- idlePortList = self.decode_long_hex_to_list(data[10:-2])
- return {'idlePortNum': idlePortNum, 'idlePortList': idlePortList}
- def lock_unlock_port(self, port, lock=True):
- lockStr = '00' if lock else '01'
- portStr = self.encode_str(port)
- data = portStr + lockStr
- data = self.send_mqtt({'funCode': '0C', 'data': data})
- if data[6:8] == '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 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 not ctrInfo.has_key('allPorts'):
- 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):
- data = self.send_mqtt({'funCode': '0F', 'data': '00'})
- data = 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_FAULT}
- 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 test(self, coins, port=1, time='60', elec='0'):
- data = self.encode_str(str(port))
- data += self.encode_str(coins)
- data += self.encode_str(time, length=4)
- data += self.encode_str(elec, length=4, ratio=100)
- devInfo = self.send_mqtt({'funCode': '14', 'data': data})
- return devInfo
- def get_dev_setting(self):
- """
- 获取设备配置参数
- :return:
- """
- 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'操作端口失败,请重试看能否解决'})
- 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
- try:
- self.device.update_other_conf(
- cst=cst, coinMin=coinMin, coinElec=coinElec, cardMin=cardMin, cardElec=cardElec)
- except Exception as e:
- pass
- 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
- }
- consumeInfo = self.get_dev_consume_count()
- resultDict.update(consumeInfo)
- deviceInfo = self.get_real_time_device_info()
- resultDict.update(deviceInfo)
- return resultDict
- @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 get_dev_consume_count(self):
- data = self.send_mqtt({'funCode': '07', 'data': '00'})
- data = data[6:]
- if data[0:2] == '01': # 表示成功
- pass
- else:
- raise ServiceException({'result': 2, 'description': u'获取统计数据失败,请重试看能否解决'})
- cardFee = int(data[2:6], 16) / 10.0 # 以角为单位
- coinFee = int(data[6:10], 16) # 以元为单位
- return {'cardFee': cardFee, 'coinFee': coinFee}
- def set_dev_setting(self, setConf):
- data = self.encode_str(setConf['coinMin'], length=4)
- data += self.encode_str(setConf['cardMin'], length=4)
- data += self.encode_str(setConf['coinElec'], length=2)
- data += self.encode_str(setConf['cardElec'], length=2)
- data += self.encode_str(setConf['cst'], length=2)
- data += self.encode_str(setConf['powerMax1'], length=4)
- data += self.encode_str(setConf['powerMax2'], length=4)
- data += self.encode_str(setConf['powerMax3'], length=4)
- data += self.encode_str(setConf['powerMax4'], length=4)
- data += self.encode_str(setConf['power2Ti'], length=2)
- data += self.encode_str(setConf['power3Ti'], length=2)
- data += self.encode_str(setConf['power4Ti'], length=2)
- data += self.encode_str(setConf['spRecMon'], length=2)
- data += self.encode_str(setConf['spFullEmpty'], length=2)
- data += self.encode_str(setConf['fullPowerMin'], length=2)
- data += self.encode_str(setConf['fullChargeTime'], length=2)
- data += self.encode_str(setConf['elecTimeFirst'], length=2)
- self.send_mqtt({'funCode': '18', 'data': data})
- def set_dev_setting2(self, setConf):
- if 'lowPower' in setConf: # 新版本
- data = self.encode_str(setConf['lowPower'])
- else: # 老版本
- data = self.encode_str(setConf['stopDelay'])
- data += self.encode_str(setConf['maxTotalTime'])
- data += self.encode_str(setConf['overVoltage'], length=4)
- data += self.encode_str(setConf['lowVoltage'], length=4)
- data += self.encode_str(setConf['overTemp'])
- data += self.encode_str(setConf['overTempDelayTime'])
- data += str(setConf['timeDspOn']).replace(':', '')
- data += str(setConf['timeDspOff']).replace(':', '')
- data += self.encode_str(setConf['pricePower1'], length=4, ratio=1000.0)
- data += self.encode_str(setConf['pricePower2'], length=4, ratio=1000.0)
- data += self.encode_str(setConf['pricePower3'], length=4, ratio=1000.0)
- data += self.encode_str(setConf['pricePower4'], length=4, ratio=1000.0)
- data += self.encode_str(setConf['pricePower5'], length=4, ratio=1000.0)
- if 'lowPower' in setConf: # 新版本
- data += self.encode_str(setConf.get('lowPowerCheckTime', 30), length=4)
- data += self.encode_str(setConf.get('stopDelayTime', 30), length=4)
- else:
- pass
- if 'maxTotalPower' in setConf:
- data += self.encode_str(setConf['maxTotalPower'])
- self.send_mqtt({'funCode': '22', 'data': data})
- 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)})
- 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)
- def set_coin_ic_switch(self, coin=True, ic=True):
- if coin:
- data = '01'
- else:
- data = '00'
- if ic:
- data += '01'
- else:
- data += '00'
- result = self.send_mqtt({'funCode': '09', 'data': data})
- return result
- @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)
- def check_order_state(self, openId):
- """
- 通过 openId 以及设备来鉴别 订单
- :param openId:
- :return:
- """
- dealerId = self.device.ownerId
- return ClientConsumeModelProxy.get_not_finished_record(ownerId=dealerId, openId=openId,
- devTypeCode=self._device['devType']['code'],
- package__billingMethod=CONSUMETYPE.POSTPAID)
- def start_device_realiable(self, order):
- return super(JNDZPOLICYBox, self).start_device_realiable(order)
- def deal_order_finish(self, order, data=None):
- pass
- def set_volume(self, volume):
- volume = self.check_params_range(volume, minData=0.0, maxData=8.0, desc='音量')
- try:
- self.send_mqtt({'funCode': '24', 'data': self.encode_str(volume)}, timeout=2)
- except:
- pass
- Device.get_collection().update_one(filter={'devNo': self.device.devNo},
- update={'$set': {'otherConf.volume': volume, }})
- Device.invalid_device_cache(self.device.devNo)
- def get_server_setting(self):
- return {
- 'minAfterStartCoins': self.device['otherConf'].get('minAfterStartCoins', 0),
- 'refundProtectionTime': self.server_configs.get('refundProtectionTime', 5),
- 'packages': self.get_power_price_rules(),
- 'timeElec': self.server_configs.get('timeElec', 1),
- 'coinRatio': self.server_configs.get('coinRatio', 1),
- 'onlineCardMinStartCoins': self.server_configs.get('onlineCardMinStartCoins', 0),
- 'onlineCardTime': self.server_configs.get('onlineCardTime', 720),
- 'onlineCardELec': self.server_configs.get('onlineCardELec', 3)
- }
- def set_server_setting(self, payload):
- updateConf = {
- }
- packages = payload.get('packages')
- if packages:
- updateConf.update({
- 'otherConf.serverConfigs.power_price_rules': self.check_power_price_rules(packages)
- })
- timeElec = payload.get('timeElec')
- if timeElec:
- updateConf.update({'otherConf.serverConfigs.timeElec': round(float(timeElec), 4)})
- refundProtectionTime = payload.get('refundProtectionTime', None)
- if refundProtectionTime:
- updateConf.update({
- 'otherConf.serverConfigs.refundProtectionTime': int(refundProtectionTime)
- })
- coinRatio = payload.get('coinRatio')
- if coinRatio:
- updateConf.update({
- 'otherConf.serverConfigs.coinRatio': round(float(coinRatio), 2)
- })
- if 'minAfterStartCoins' in payload and payload['minAfterStartCoins']:
- minAfterStartCoins = self.check_params_range(
- payload['minAfterStartCoins'], minData=0.0, maxData=100.0, desc='设备启动最小余额')
- updateConf.update({
- 'otherConf.minAfterStartCoins': float(minAfterStartCoins)
- })
- onlineCardMinStartCoins = payload.get('onlineCardMinStartCoins')
- onlineCardTime = payload.get('onlineCardTime')
- onlineCardELec = payload.get('onlineCardELec')
- if onlineCardMinStartCoins and onlineCardTime and onlineCardELec:
- updateConf.update(
- {
- 'otherConf.serverConfigs.onlineCardMinStartCoins': round(float(onlineCardMinStartCoins), 2),
- 'otherConf.serverConfigs.onlineCardTime': round(float(onlineCardTime), 2),
- 'otherConf.serverConfigs.onlineCardELec': round(float(onlineCardELec), 4)
- })
- self.device.update_device_obj(**updateConf)
|