# -*- coding: utf-8 -*- # !/usr/bin/env python import logging import time import uuid from apilib.utils_json import JsonResponse from apps.web.constant import Const, DeviceCmdCode, MQTT_TIMEOUT from apps.web.core.adapter.base import SmartBox, hexbyte_2_bin, 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 PedicureCom1(SmartBox): def __init__(self, device): super(PedicureCom1, self).__init__(device) # 串口设备的状态检测,需要单独进行,和非串口的不一样 def check_dev_status(self, attachParas = None): devInfo = self.get_dev_info() 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 not devInfo['isStart']: Device.invalid_device_control_cache(self._device['devNo']) if devInfo['status'] == Const.DEV_WORK_STATUS_FAULT: raise ServiceException({'result': 2, 'description': u'足疗机出现故障:%s,您找下管理员吧' % devInfo['statusInfo']}) # 足疗机的事件报文和get上来的报文一样,直接调用即可 def analyze_event_data(self, data): return self.analyze_get_data(data) # 解析get到的报文信息 def analyze_get_data(self, data): result = {} if 'F2F2F008' not in data: return result status = Const.DEV_WORK_STATUS_WORKING fault = '' # 解析返回的报文,报文格式F2F2... resultData = data[8:24] if resultData[0:2] == '00': isStart = False else: isStart = True hTime = resultData[2:4] mTime = resultData[4:6] sTime = resultData[6:8] leftTime = int(hTime, 16) * 3600 + int(mTime, 16) * 60 + int(sTime, 16) totalTime = int(resultData[8:12], 16) * 3600 + int(resultData[12:13], 16) hexFault = resultData[14:16] binFault = hexbyte_2_bin(hexFault) if binFault[0] == '1': status = Const.DEV_WORK_STATUS_FAULT fault = u'堵转故障' if binFault[1] == '1': fault = u'按摩脚霍尔传感器不归位' if binFault[2] == '1': fault = u'付款没有开机故障' if leftTime == 0 and fault == '': status = Const.DEV_WORK_STATUS_IDLE return {'status': status, 'fault': fault, 'isStart': isStart, 'totalTime': totalTime, 'leftTime': leftTime} def get_dev_info(self): result = MessageSender.send(self.device, DeviceCmdCode.PASSTHROUGH_OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], 'funCode': 'F0', 'data': 'F2F2F00100'}) if result['rst'] != 0: return {'rst': -1, 'isOffline': 1} result.update(self.analyze_get_data(result['data'])) return result def changeVolume(self, volume): service_cache = Device.get_dev_control_cache(self._device['devNo']) if not PedicureCom1.is_working(service_cache): raise ServiceException({'result': 2, 'description': u'足疗机已经结束工作,请支付后再试'}) data = fill_2_hexByte(hex(int(volume)), 2) result = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], 'funCode': 'FA', 'data': data}) if 'rst' in result and result['rst'] != 0: current_dev_type_name = self._device['devType']['name'] if current_dev_type_name == u'其他': current_dev_type_name = u'自助设备' description = u'当前' + current_dev_type_name + u'修改音量失败,可能是当前网络状况差,请稍候再试' raise ServiceException({'result': 2, 'description': description}) service_cache['volume'] = volume Device.update_dev_control_cache(self._device['devNo'], service_cache) leftTime = service_cache['finishedTime'] - int(time.time()) return { 'leftTime': leftTime if leftTime > 0 else 0 } def do_control(self, button, value): cmd_dict = {'start0': '00', 'start1': '01', 'hot1': '02', 'hot0': '03', 'mode1': '04', 'mode2': '05', 'mode3': '06', 'strength1': '07', 'strength2': '08', 'strength3': '09', 'strength4': '0A'} func_name = '%s%d' % (button, value) if func_name not in cmd_dict: logger.error('not support function. button = %s; value = %d' % (button, value)) raise ServiceException({'result': 2, 'description': u'暂时不支持该功能'}) dev_info = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC, {'IMEI': self._device['devNo'], "funCode": 'FC', 'data': cmd_dict[func_name]}) if dev_info and 'rst' in dev_info and dev_info['rst'] != 0: if dev_info['rst'] == -1: raise ServiceException({'result': 2, 'description': u'足疗机正在玩命找网络,您的金币还在,重试不需要重新付款,建议您试试旁边其他设备,或者稍后再试哦'}) elif dev_info['rst'] == 1: raise ServiceException({'result': 2, 'description': u'足疗机正在忙,无响应,您的金币还在,请稍后再试哦'}) def press_button(self, button, value): service_cache = Device.get_dev_control_cache(self._device['devNo']) if not PedicureCom1.is_working(service_cache): raise ServiceException({'result': 2, 'description': u'足疗机已经结束工作,请支付后再试'}) self.do_control(button, value) service_cache[button] = value Device.update_dev_control_cache(self._device['devNo'], service_cache) leftTime = service_cache['finishedTime'] - int(time.time()) return { 'leftTime': leftTime if leftTime > 0 else 0 } def send_dev_runtime(self, openId, duration): dev_info, left_time = self.send_time(int(duration / 60)) if left_time == 0: Device.update_dev_control_cache(self._device['devNo'], {'status': Const.DEV_WORK_STATUS_IDLE}) return dev_info need_time = duration * 60 start_time, hot, mode, strength = int(time.time()), 1, 1, 2 finished_time = start_time + need_time service_cache = Device.get_dev_control_cache(self._device['devNo']) if PedicureCom1.is_working(service_cache): service_cache['finishedTime'] = service_cache['finishedTime'] + need_time else: service_cache = {'status': Const.DEV_WORK_STATUS_WORKING, 'startTime': start_time, 'finishedTime': finished_time} Device.update_dev_control_cache(self._device['devNo'], service_cache) return dev_info def send_time(self, time, timeout = MQTT_TIMEOUT.NORMAL): oxTime = hex(time)[2::] oxTime = '0000' + oxTime oxTime = oxTime[-4::] uuId = str(uuid.uuid4()).replace('-', '')[0:16] data = uuId + oxTime result = MessageSender.send(device = self.device, cmd = DeviceCmdCode.OPERATE_DEV_SYNC, payload = { 'IMEI': self._device['devNo'], 'funCode': '05', 'data': data }, timeout = timeout) if 'rst' in result and result['rst'] != 0: current_dev_type_name = self._device['devType']['name'] if current_dev_type_name == u'其他': current_dev_type_name = u'自助设备' description = u'当前' + current_dev_type_name + u'充值失败,可能是当前网络状况差,请稍候再试' raise ServiceException({'result': 2, 'description': description}) status = result['data'][24:26] if status == '00': raise ServiceException({'result': 2, 'description': u'设备启动异常,请联系客服'}) hour = int(result['data'][26:28], 16) minute = int(result['data'][28:30], 16) second = int(result['data'][30:32], 16) left_time = 3600 * hour + 60 * minute + second return result, left_time def test(self, coins): result, left_time = self.send_time(1) return result def start_device(self, package, openId, attachParas): unit = package.get('unit', u'分钟') if unit == u'分钟': duration = int(package['time']) elif unit == u'小时': duration = int(package['time']) * 60 elif unit == u'天': duration = int(package['time']) * 1440 else: duration = int(package['time']) dev_info, left_time = self.send_time(duration, timeout = MQTT_TIMEOUT.START_DEVICE) if left_time == 0: Device.invalid_device_control_cache(self._device['devNo']) return dev_info need_time = duration * 60 start_time, hot, mode, strength = int(time.time()), 1, 1, 2 finished_time = start_time + need_time service_cache = Device.get_dev_control_cache(self._device['devNo']) if PedicureCom1.is_working(service_cache): service_cache['finishedTime'] = service_cache['finishedTime'] + need_time else: service_cache = {'status': Const.DEV_WORK_STATUS_WORKING, 'startTime': start_time, 'finishedTime': finished_time} Device.update_dev_control_cache(self._device['devNo'], service_cache) return dev_info def support_count_down(self, openId = None, port = None): return True def count_down(self, request, dev, agent, group, devType, lastOpenId, port = None): dev_info = self.get_dev_info() if dev_info['rst'] != 0: return JsonResponse({'result': 0, 'description': u'足疗机网络不太好,再试试哦'}) result = { 'result': 1, 'description': '', 'payload': { 'surplus': 0.0, 'sum': 0.0, 'name': group['groupName'], 'address': group['address'], 'code': devType.get('code'), 'orderProcessing': False, 'logicalCode': dev['logicalCode'], 'user': 'me', 'agentFeatures': agent.features, 'status': { 'hot': 1, 'mode': 1, 'strength': 2, 'volume': 30 } } } if not dev_info['isStart']: Device.clear_port_control_cache(self._device['devNo']) return JsonResponse(result) left_time = dev_info['leftTime'] start_time = int(time.time()) service_cache = Device.get_dev_control_cache(self._device['devNo']) if PedicureCom1.is_working(service_cache): cache_left_time = service_cache['finishedTime'] - service_cache['startTime'] diff_left_time = left_time - cache_left_time finished_time = service_cache['finishedTime'] + diff_left_time if finished_time >= service_cache['startTime']: service_cache['startTime'] = start_time service_cache['finishedTime'] = start_time + left_time else: service_cache['finishedTime'] = finished_time else: service_cache = {'status': Const.DEV_WORK_STATUS_WORKING, 'startTime': start_time, 'finishedTime': start_time + left_time} Device.update_dev_control_cache(self._device['devNo'], service_cache) result['payload']['surplus'] = left_time / 60.0 result['payload']['sum'] = (service_cache['finishedTime'] - service_cache['startTime']) / 60.0 if 'volume' in service_cache: result['payload']['status']['volume'] = service_cache['volume'] if 'hot' in service_cache: result['payload']['status']['hot'] = service_cache['hot'] if 'mode' in service_cache: result['payload']['status']['mode'] = service_cache['mode'] if 'strength' in service_cache: result['payload']['status']['strength'] = service_cache['strength'] return JsonResponse(result) @staticmethod def is_working(service_cache): if service_cache and 'finishedTime' in service_cache \ and 'startTime' in service_cache \ and service_cache['finishedTime'] > int(time.time()) \ and service_cache['status'] in [Const.DEV_WORK_STATUS_WORKING, Const.DEV_WORK_STATUS_PAUSE]: return True else: return False def pause(self, openId, isContinue, port = None): service_cache = Device.get_dev_control_cache(self._device['devNo']) if not PedicureCom1.is_working(service_cache): raise ServiceException({'result': 2, 'description': u'足疗机可能没有工作,请刷新后再试'}) button = 'start' if isContinue: value = 1 else: value = 0 self.do_control(button, value) service_cache['status'] = Const.DEV_WORK_STATUS_PAUSE Device.update_dev_control_cache(self._device['devNo'], service_cache) leftTime = service_cache['finishedTime'] - int(time.time()) return { 'leftTime': leftTime if leftTime > 0 else 0 }