# -*- coding: utf-8 -*- # !/usr/bin/env python import logging from voluptuous import Schema, Range, Required, REMOVE_EXTRA from apps.web.constant import DeviceCmdCode, Const, MQTT_TIMEOUT from apps.web.core.adapter.base import SmartBox, fill_2_hexByte from apps.web.core.exceptions import ServiceException from apps.web.core.networking import MessageSender from apps.web.device.models import Device logger = logging.getLogger(__name__) class ChargingZhongChuangBox(SmartBox): FIRST_INDEX = 1 DATA_SIZE = 80 DATA_OFFSET = 8 SETTING_FIRST_INDEX = 41 SETTING_LAST_INDEX = 43 SETTING_SCHEMA = Schema({ Required('unitPrice'): Range(min = 1, max = 250, msg = u'单次刷卡扣费参数错误'), Required('feeRate'): Range(min = 1, max = 99, msg = u'一元可充电度数参数错误'), Required('powerLimit'): Range(min = 100, max = 3000, msg = u'功耗极限设定参数错误'), }, extra = REMOVE_EXTRA) def __init__(self, device): super(ChargingZhongChuangBox, self).__init__(device) def translate_funcode(self,funCode): funCodeDict = { '03':u'从设备读数据', '06':u'向设备写数据', } return funCodeDict.get(funCode,'') def __read__(self, offset, size): request_data = fill_2_hexByte(hex(int(offset)), 4) request_data += (fill_2_hexByte(hex(int(size)), 4)) devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], "funCode": '03', 'data': request_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'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'}) return devInfo['data'][ChargingZhongChuangBox.DATA_OFFSET:] def __write__(self, offset, value,timeout = MQTT_TIMEOUT.NORMAL,orderNo=None): request_data = fill_2_hexByte(hex(int(offset)), 4) request_data += fill_2_hexByte(hex(int(value)), 4) devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], 'funCode': '06', 'data': request_data}, timeout = timeout) 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'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'}) if devInfo['data'][:-4] != ('0106' + request_data): raise ServiceException({'result': 2, 'description': u'写入充电桩数据错误'}) return devInfo def get_port_info(self, line): return self.get_port_status().get(line) def __parse_port_status(self, response_data): if len(response_data) < 44:#现网日志报错,有异常报文上报 return {} forbidden_flag = int(response_data[40:44], 16) result = {} for ii in range(1, 11): response_status = response_data[(ii - 1) * 4: ii * 4] status = Const.DEV_WORK_STATUS_IDLE if forbidden_flag == 1 else Const.DEV_WORK_STATUS_FORBIDDEN if response_status == '0001': status = Const.DEV_WORK_STATUS_WORKING elif response_status == '0000': status = Const.DEV_WORK_STATUS_IDLE if forbidden_flag == 1 else Const.DEV_WORK_STATUS_FORBIDDEN elif response_status == '0002': status = Const.DEV_WORK_STATUS_FAULT result[str(ii)] = {'status': status} allPorts, usedPorts, usePorts = self.get_port_static_info(result) Device.update_dev_control_cache(self._device['devNo'], {'allPorts': allPorts, 'usedPorts': usedPorts, 'usePorts': usePorts, 'ports': result}) return result def get_port_status(self, force=False): cacheValue = Device.get_dev_control_cache(self._device['devNo']) if 'ports' in cacheValue and force: return cacheValue['ports'] else: return self.__parse_port_status(self.__read__(21, 11)) def start_device(self, package, openId, attachParas): price = int(package['price'] * 10) if price < 1: raise ServiceException({'result': 2, 'description': u'请输入正确的支付费用'}) logger.debug('charge index = %s; price = %s' % (attachParas['chargeIndex'], price)) orderNo = attachParas.get('orderNo') devInfo = self.__write__(attachParas['chargeIndex'], price, timeout = MQTT_TIMEOUT.START_DEVICE, orderNo = orderNo) cacheValue = Device.get_dev_control_cache(self._device['devNo']) if not cacheValue: return cacheValue.update({'openId': openId, 'isStart': True}) if 'ports' in cacheValue and str(attachParas['chargeIndex']) in cacheValue['ports']: cacheValue['ports'][str(attachParas['chargeIndex'])].update({'status': Const.DEV_WORK_STATUS_WORKING}) Device.update_dev_control_cache(self._device['devNo'], cacheValue) return devInfo def get_dev_setting(self): device = Device.get_dev(self._device['devNo']) if device['otherConf']: return device['otherConf'] else: response_data = self.__read__(ChargingZhongChuangBox.SETTING_FIRST_INDEX, ChargingZhongChuangBox.SETTING_LAST_INDEX) unitPrice = float(int(response_data[0:4], 16)) / 10 feeRate = float(int(response_data[4:8], 16)) / 10 powerLimit = int(response_data[8:12], 16) Device.update_field( dev_no = self._device['devNo'], otherConf = { 'unitPrice': unitPrice, 'feeRate': feeRate, 'powerLimit': powerLimit }) return {'unitPrice': unitPrice, 'feeRate': feeRate, 'powerLimit': powerLimit} def set_dev_setting(self, configDict): settings = { 'unitPrice': int(10 * float(configDict.get('unitPrice'))), 'feeRate': int(10 * float(configDict.get('feeRate'))), 'powerLimit': int(configDict.get('powerLimit')) } settings = ChargingZhongChuangBox.SETTING_SCHEMA(settings) if settings['unitPrice'] != int(10 * float(self._device['otherConf']['unitPrice'])): self.__write__(ChargingZhongChuangBox.SETTING_FIRST_INDEX, settings['unitPrice']) if settings['feeRate'] != int(10 * float(self._device['otherConf']['feeRate'])): self.__write__(ChargingZhongChuangBox.SETTING_FIRST_INDEX + 1, settings['feeRate']) if settings['powerLimit'] != int(self._device['otherConf']['powerLimit']): self.__write__(ChargingZhongChuangBox.SETTING_FIRST_INDEX + 2, settings['powerLimit']) Device.update_field( dev_no = self._device['devNo'], otherConf = { 'unitPrice': float(configDict.get('unitPrice')), 'feeRate': float(configDict.get('feeRate')), 'powerLimit': configDict.get('powerLimit') }) def analyze_event_data(self, data): self.__parse_port_status(data[ChargingZhongChuangBox.DATA_OFFSET:][20 * 4:31 * 4]) def remote_charge_card(self, price, rechargeRecord=None): return self.__write__(50, 10 * int(price.amount)) def set_device_function_param(self,request,lastSetConf): setting = { 'unitPrice': request.POST.get('unitPrice'), 'feeRate': request.POST.get('feeRate'), 'powerLimit': request.POST.get('powerLimit') } self.set_dev_setting(setting)