123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332 |
- # -*- coding: utf-8 -*-
- #!/usr/bin/env python
- import time
- import logging
- import datetime
- from apilib.utils_datetime import timestamp_to_dt
- from apps.web.constant import Const, DeviceCmdCode, 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.dealer.models import Dealer
- from apps.web.device.models import Device, Group
- from apps.web.core.device_define.water_despenser import CMD_CODE
- from apps.web.helpers import get_wechat_manager_mp_proxy
- from apps.web.user.models import MyUser
- logger = logging.getLogger(__name__)
- class WaterControllerBox(SmartBox):
- def __init__(self, device):
- super(WaterControllerBox, self).__init__(device)
- def _refresh_device_uart(self):
- devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
- {'IMEI': self._device['devNo'], "funCode": 'E9', 'data': ''},
- timeout=15)
- self.__verify_device_operate_status(devInfo)
- def __verify_device_operate_status(self, devInfo):
- if 'rst' in devInfo 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 start_device(self, package, openId, attachParas):
- self._refresh_device_uart()
- if attachParas is None or 'chargeIndex' not in attachParas:
- raise ServiceException({'result': 2, 'description': u'请您选择合适的端口'})
- unit = package.get('unit', u'分钟')
- if unit not in [u'分钟', u'秒']:
- raise ServiceException({'result': 2, 'description': u'套餐错误,套餐只支持秒,分钟'})
- price = float(package['price'])
- coins = float(package['coins'])
- port = hex(int(attachParas['chargeIndex']))
- hexPort = fill_2_hexByte(port, 2)
- devPortInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {
- 'IMEI': self._device['devNo'],
- 'funCode': 'EF',
- 'data': hexPort
- }, timeout=15)
- self.__verify_device_operate_status(devPortInfo)
- portCanUse = True if devPortInfo['data'][2:6] == '0000' else False
- if portCanUse is False:
- raise ServiceException({'result': 2, 'description': u'端口繁忙,目前无法启动,请稍后再试。'})
- # 杜绝续充以及事件异常导致有缓存的情况
- Device.clear_port_control_cache(self._device['devNo'], str(attachParas['chargeIndex']))
- type = 'FE' if unit == u'秒' else 'FD'
- needTime = int(package['time'])
- hexTime = fill_2_hexByte(hex(needTime), 4)
- devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {
- 'IMEI': self._device['devNo'],
- 'funCode': '55',
- 'data': hexPort + type + hexTime
- }, timeout=MQTT_TIMEOUT.START_DEVICE)
- self.__verify_device_operate_status(devInfo)
- usePort = int(attachParas['chargeIndex'])
- start_timestamp = int(time.time())
- if type == 'FE':
- finishedTime = start_timestamp + int(needTime)
- else:
- finishedTime = start_timestamp + (int(needTime) * 60)
- portDict = {
- 'startTime': timestamp_to_dt(start_timestamp).strftime('%Y-%m-%d %H:%M:%S'),
- 'status': Const.DEV_WORK_STATUS_WORKING,
- 'price': price,
- 'coins': coins,
- 'isStart': True,
- 'openId': openId,
- 'refunded': False,
- 'needTime': needTime,
- 'type': 'second' if type == 'FE' else 'minute',
- 'vCardId': self._vcard_id,
- 'finishedTime': finishedTime,
- 'isPause': False
- }
- if 'linkedRechargeRecordId' in attachParas:
- item = {
- 'rechargeRcdId': str(attachParas['linkedRechargeRecordId'])
- }
- portDict['payInfo'] = [item]
- Device.update_dev_control_cache(self._device['devNo'], {str(usePort): portDict})
- return devInfo
- def get_port_status(self, force=True):
- # self._refresh_device_uart()
- # ctrInfo = Device.get_dev_control_cache(self._device['devNo'])
- # device = Device.objects(devNo=self._device['devNo']).first()
- # allPorts = ctrInfo.get('allPorts', device.otherConf.get('portNumber', 5))
- # statusDict = {}
- # 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})
- #
- # ctrInfo = Device.get_dev_control_cache(self._device['devNo'])
- # for strPort, info in statusDict.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 statusDict
- self._refresh_device_uart()
- devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
- {'IMEI': self._device['devNo'], "funCode": 'EF', 'data': '55'},
- timeout=15)
- self.__verify_device_operate_status(devInfo)
- device = Device.objects(devNo=self._device['devNo']).first()
- result = {}
- portNum = device.otherConf.get('portNumber', 5) + 1
- portData = devInfo['data']
- ctrInfo = Device.get_dev_control_cache(self._device['devNo'])
- ii = 1
- while ii < portNum:
- port = int(portData[ii * 8 - 2:ii * 8], 16)
- statusTemp = portData[ii * 8 - 6:ii * 8 - 2]
- if statusTemp == '0000':
- if str(port) in ctrInfo:
- if ctrInfo[str(port)].get('status', 0) == Const.DEV_WORK_STATUS_FORBIDDEN:
- status = {'status': Const.DEV_WORK_STATUS_FORBIDDEN}
- else:
- status = {'status': Const.DEV_WORK_STATUS_IDLE}
- else:
- status = {'status': Const.DEV_WORK_STATUS_IDLE}
- else:
- status = {'status': Const.DEV_WORK_STATUS_WORKING}
- 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 strPort in ctrInfo:
- ctrInfo[strPort].update({'status': info['status']})
- else:
- ctrInfo[strPort] = info
- Device.update_dev_control_cache(self._device['devNo'], ctrInfo)
- return result
- def get_port_status_from_dev(self):
- return {}
- def pauseToUseDevice(self, port, oper):
- self._refresh_device_uart()
- ctrInfo = Device.get_dev_control_cache(self.device['devNo'])
- lineInfo = ctrInfo.get(str(port))
- funCode = 'EE' if lineInfo.get('isPause', True) is True else 'ED'
- hexPort = fill_2_hexByte(hex(int(port)), 2)
- MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
- {'IMEI': self._device['devNo'], "funCode": funCode, 'data': hexPort})
- if funCode == 'EE':
- Device.update_dev_control_cache(self._device['devNo'], {str(port): {'isPause': False}})
- elif funCode == 'ED':
- Device.update_dev_control_cache(self._device['devNo'], {str(port): {'isPause': True}})
- else:
- pass
- 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 stop_charging_port(self, port):
- self._refresh_device_uart()
- hexPort = fill_2_hexByte(hex(int(port)), 2)
- devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
- {'IMEI': self._device['devNo'], "funCode": 'EC', 'data': hexPort}, timeout=7)
- self.__verify_device_operate_status(devInfo)
- leftTime = int(devInfo['data'][2:6], 16)
- port = int(devInfo['data'][6:8], 16)
- return {'leftTime': leftTime, 'port': str(port)}
- def stop(self, port = None):
- boardRefund = self.get_dev_setting()['boardRefund']
- if boardRefund is False:
- raise ServiceException({'result': 2, 'description': u'暂不支持用户远程停止设备'})
- self.stop_charging_port(port)
- infoDict = dict()
- infoDict['remainder_time'] = 0
- return infoDict
- @property
- def isHaveStopEvent(self):
- return True
- def analyze_event_data(self, data):
- cmdCode = data[0:2]
- if cmdCode == 'EB':
- port = str(int(data[2:4], 16))
- return {
- 'status': Const.DEV_WORK_STATUS_IDLE,
- 'cmdCode': cmdCode,
- 'port': port
- }
- elif cmdCode == 'EC':
- leftTime = str(int(data[2:6], 16))
- port = str(int(data[6:8], 16))
- return {
- 'status': Const.DEV_WORK_STATUS_IDLE,
- 'cmdCode': cmdCode,
- 'leftTime': leftTime,
- 'port': port
- }
- def get_dev_setting(self):
- device = Device.objects(devNo=self._device['devNo']).first()
- volumeControl = device.otherConf.get('volumeControl', 'medium')
- portNumber = device.otherConf.get('portNumber', 5)
- boardRefund = device.otherConf.get('boardRefund', False)
- return {'volumeControl': volumeControl, 'portNumber': portNumber, 'boardRefund': boardRefund}
- def set_device_function_param(self, request, lastSetConf):
- self._refresh_device_uart()
- portNumber = request.POST['portNumber']
- volumeControl = request.POST['volumeControl']
- boardRefund = request.POST['boardRefund']
- if volumeControl == 'high':
- volumeControl = '03'
- elif volumeControl == 'medium':
- volumeControl = '02'
- elif volumeControl == 'low':
- volumeControl = '01'
- else:
- pass
- MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_NO_RESPONSE,
- {'IMEI': self._device['devNo'], "funCode": 'EA', 'data': volumeControl}, timeout=15)
- time.sleep(2)
- MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_NO_RESPONSE,
- {'IMEI': self._device['devNo'], "funCode": 'F7' if boardRefund is True else 'F9', 'data': ''}, timeout=15)
- device = Device.objects(devNo=self._device['devNo']).first()
- device.otherConf.update({'volumeControl': request.POST['volumeControl']})
- device.otherConf.update({'boardRefund': request.POST['boardRefund']})
- device.otherConf.update({'portNumber': int(portNumber)})
- device.save()
- Device.invalid_device_cache(device.devNo)
- def lock_unlock_port(self, port, lock = True):
- 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}})
|