# -*- coding: utf-8 -*- # !/usr/bin/env python import logging import time from apilib.utils_datetime import timestamp_to_dt 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, Part logger = logging.getLogger(__name__) class ChargingDelixiBox(SmartBox): def __init__(self, device): super(ChargingDelixiBox, self).__init__(device) # 设备上报事件 def analyze_event_data(self, data): if data.get('cmd') == 100: power = int(data['status'][0:4], 16) leftTime = int(data['status'][4:8], 16) reasonCode = data['status'][8:10] port = str(data['port']) chargeStatus = '00' if reasonCode == '03': reason = u'开始充电' chargeStatus = '01' elif reasonCode == '04': reason = u'空载断电' elif reasonCode == '05': reason = u'交流输入故障禁止充电' elif reasonCode == '06': reason = u'输出电流过大禁止充电' elif reasonCode == '07': reason = u'其他故障禁止充电' elif reasonCode == '00': reason = u'结束充电' else: reason = u'' return {'cmdCode': 100, 'reason': reason, 'reasonCode': reasonCode, 'chargeStatus': chargeStatus, 'power': power, 'leftTime': leftTime, 'port': port} def get_port_status_from_dev(self): data = '00 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000' data = data.replace(' ', '') devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], "funCode": '06', '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'] resultDict = {} for ii in range(10): jj = 12 + ii * 12 power = int(data[jj:jj + 4], 16) leftTime = int(data[jj + 4:jj + 8], 16) devStatus = str(data[jj + 8:jj + 10]) if devStatus == '00': status = Const.DEV_WORK_STATUS_IDLE else: status = Const.DEV_WORK_STATUS_WORKING money = int(data[jj + 10:jj + 12], 16) valueDict = {str(ii + 1): {'power': power, 'leftTime': leftTime, 'status': status, 'devStatus': devStatus, 'money': money}} resultDict.update(valueDict) allPorts, usedPorts, usePorts = self.get_port_static_info(resultDict) Device.update_dev_control_cache(self._device['devNo'], {'allPorts': allPorts, 'usedPorts': usedPorts, 'usePorts': usePorts}) # 这里存在多线程更新缓存的场景,可能性比较低,但是必须先取出来,然后逐个更新状态,然后再记录缓存 for _ in range(allPorts): Device.clear_port_control_cache(self._device['devNo'], str(_ + 1)) ctrInfo = Device.get_dev_control_cache(self._device['devNo']) for v in resultDict.keys(): if ctrInfo.has_key(v): ctrInfo[v].update({'status': resultDict[v]['status']}) else: ctrInfo[v] = resultDict[v] Device.update_dev_control_cache(self._device['devNo'], ctrInfo) # 判断充电桩是否写入传感器 parts = Part.objects(logicalCode = self._device['logicalCode']) if not parts.count(): logger.error('The part with logicalcode of {} was not found'.format(self._device['logicalCode'])) else: # 添加温度互感器 if not Part.objects(logicalCode = self._device['logicalCode'], partType = '3001').count(): temperature = Part( logicalCode = self._device['logicalCode'], ownerId = self._device['ownerId'], partName = u'温度互感器', partType = '3001' ) temperature.save() # 添加电流互感器 elif not Part.objects(logicalCode = self._device['logicalCode'], partType = '3002').count(): electricity = Part( logicalCode = self._device['logicalCode'], ownerId = self._device['ownerId'], partName = u'电流互感器', partType = '3002' ) electricity.save() logger.info('A transformer has been added to locigalcode {} database'.format(self._device['logicalCode'])) return resultDict 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 = {} allPorts = ctrInfo.get('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 stop(self, port = None): # 构造报文 elecFee = fill_2_hexByte(hex(int(float(self._device['otherConf'].get('elecFee')) * 10)))[-2:] dataPort = '' for v in range(10): if v + 1 == port: dataPort += 'AA00' else: dataPort += '0000' data = elecFee + dataPort + '5CFD' # 发送报文 devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], "funCode": '06', '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'充电桩正在忙,无响应,您的金币还在,请试试其他线路,或者请稍后再试哦'}) # 更新端口状态 Device.update_dev_control_cache(self._device['devNo'], {str(port): {'status': '00'}}) def translate_funcode(self, funCode): funCodeDict = { '03': u'移动支付', '06': u'获取端口数据', '02': u'获取设备参数', } return funCodeDict.get(funCode, '') def start_device(self, package, openId, attachParas): # 微信支付 if attachParas is None: raise ServiceException({'result': 2, 'description': u'请您选择合适的充电线路、电池类型信息'}) if not attachParas.has_key('chargeIndex'): raise ServiceException({'result': 2, 'description': u'请您选择合适的充电线路'}) # 用户付款 userPay = fill_2_hexByte(hex(int(float(package['price']) * 10)), num = 2) # 单位电价 setConf = self.get_dev_setting() elecFee = fill_2_hexByte(hex(int(float(setConf['elecFee']) * 10)), num = 2) # 要使用的端口 port = attachParas['chargeIndex'] # 编辑端口信息报文 dataPort = '' for v in range(10): if v + 1 == int(port): dataPort += '55' + userPay else: dataPort += '0000' # 完成所有报文 data = elecFee + dataPort + '5CFD' devInfo = MessageSender.send(device = self.device, cmd = DeviceCmdCode.OPERATE_DEV_SYNC, payload = { 'IMEI': self._device['devNo'], "funCode": '06', 'data': data}, timeout = MQTT_TIMEOUT.START_DEVICE) 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'充电桩正在忙,无响应,您的金币还在,请试试其他线路,或者请稍后再试哦'}) # 其他情况返回 jj = int(port) * 12 + 12 if devInfo['data'][jj + 8:jj + 10] in ['05', '06', '07', '09']: raise ServiceException({'result': 2, 'description': u'充电桩今天休假辣,您的金币还在,请试试其他线路,或者请稍后再试哦'}) start_timestamp = int(time.time()) devInfo['finishedTime'] = start_timestamp + 24 * 60 * 60 Device.update_dev_control_cache( self._device['devNo'], { str(port): { 'startTime': timestamp_to_dt(start_timestamp).strftime('%Y-%m-%d %H:%M:%S'), 'status': Const.DEV_WORK_STATUS_WORKING, 'finishedTime': devInfo['finishedTime'], 'isStart': True, 'coins': package['coins'], 'elecFee': setConf['elecFee'], 'openId': openId, 'refunded': True, 'vCardId': self._vcard_id } }) return devInfo def get_dev_setting(self): dev = Device.objects.get(devNo = self._device['devNo']) elecFee = dev.otherConf.get('elecFee', '1') return {'elecFee': elecFee} def set_device_function_param(self, request, lastsetConf): elecFee = request.POST.get('elecFee', None) dev = Device.objects.get(devNo = self._device['devNo']) dev.otherConf.update({'elecFee': str(elecFee)}) dev.save()