123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248 |
- # -*- 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()
|