# -*- coding: utf-8 -*- # !/usr/bin/env python import datetime import logging import time import simplejson as json from apilib.utils_string import cn from apps.web.constant import DeviceErrorCodeDesc, ErrorCode, DeviceOnlineStatus, DeviceCmdCode, Const, FAULT_CODE, \ MQTT_TIMEOUT from apps.web.core.adapter.base import SmartBox from apps.web.core.exceptions import ServiceException, DeviceNetworkTimeoutError from apps.web.core.networking import MessageSender from apps.web.device.models import Device from apps.web.core.device_define import PackageDict logger = logging.getLogger(__name__) class MySmartBox(SmartBox): def __init__(self, device): super(MySmartBox, self).__init__(device) def check_dev_status(self, attachParas = None): """ 如果超过两个心跳周期没有报心跳,并且最后一次更新时间在2个小时内,需要从设备获取状态 否则以缓存状态为准。 :param attachParas: :return: """ if not self.device.need_fetch_online: raise ServiceException( {'result': 2, 'description': DeviceErrorCodeDesc.get(ErrorCode.DEVICE_CONN_FAIL)}) if self.device.online == DeviceOnlineStatus.DEV_STATUS_ONLINE: retry = 3 timeout = 12 else: retry = 2 timeout = 10 operation_result = MessageSender.send(device = self.device, cmd = DeviceCmdCode.GET_DEVINFO, payload = { 'IMEI': self.device.devNo, 'fields': ['signal', 'pulse_open', 'board_volt', 'board_valid'] }, timeout = timeout, retry = retry) if operation_result['rst'] != ErrorCode.DEVICE_SUCCESS: if operation_result['rst'] == ErrorCode.DEVICE_CONN_FAIL: raise ServiceException( { 'result': 2, 'description': DeviceErrorCodeDesc.get(ErrorCode.DEVICE_CONN_CHECK_FAIL) }) else: raise ServiceException( { 'result': 2, 'description': u'检测设备状态失败({})'.format(operation_result['rst']) }) else: if 'pulse_open' in operation_result and (not operation_result['pulse_open']): raise ServiceException( { 'result': 2, 'description': u'检测设备状态失败({})'.format(ErrorCode.PULSE_IS_CLOSE) }) if 'board_valid' in operation_result and 'board_volt' in operation_result and operation_result[ 'board_valid'] != 2: if operation_result['board_volt'] != operation_result['board_valid']: raise ServiceException( { 'result': 2, 'description': u'当前设备正在工作,请稍后再试' }) def test(self, coins): now_time = datetime.datetime.now() return MessageSender.send(device = self.device, cmd = DeviceCmdCode.PAY_MONEY, payload = { 't': int(time.mktime(now_time.timetuple())), 'duration': coins * 60, 'app_pay': coins }) def start_device(self, package, openId, attachParas): pay_count = int(package['coins']) result = MessageSender.net_pay(self.device, pay_count, timeout = MQTT_TIMEOUT.START_DEVICE) if result['rst'] == ErrorCode.DEVICE_CONN_FAIL: raise DeviceNetworkTimeoutError() elif result['rst'] != ErrorCode.DEVICE_SUCCESS: logger.debug('MySmartBox() failed to start, result was=%s' % (json.dumps(result),)) raise ServiceException({'result': 2, 'description': DeviceErrorCodeDesc.get(result['rst'])}) try: duration = self.get_duration(package) result['finishedTime'] = (int(time.time()) + duration) Device.update_dev_control_cache(self._device['devNo'], { 'status': Const.DEV_WORK_STATUS_WORKING, 'finishedTime': result['finishedTime'] }) except Exception as e: logger.exception('error = %s' % e) return result def start_device_realiable(self, order): try: now_time = datetime.datetime.now() result = MessageSender.send(device = self.device, cmd = DeviceCmdCode.PAY_MONEY, payload = { 't': int(time.mktime(now_time.timetuple())), 'duration': PackageDict(order.package).estimated_duraion, 'order_id': order.orderNo, 'order_type': 'pulse_start', 'app_pay': int(order.package['coins']) }) if result['rst'] == ErrorCode.DEVICE_CONN_FAIL: result.update({ 'fts': int(time.time()), 'order_type': 'com_start', 'order_id': order.orderNo }) except ServiceException as e: logger.exception(e) return { 'rst': ErrorCode.EXCEPTION, 'fts': int(time.time()), 'errorDesc': cn(e.result.get('description')), 'order_type': 'com_start', 'order_id': order.orderNo } except Exception as e: logger.exception(e) return { 'rst': ErrorCode.EXCEPTION, 'fts': int(time.time()), 'order_type': 'com_start', 'order_id': order.orderNo } def get_total_coin(self): result = MessageSender.send(self.device, DeviceCmdCode.GET_DEVINFO, {'cmd': DeviceCmdCode.GET_DEVINFO, 'IMEI': self._device['devNo']}) if result['rst'] != ErrorCode.DEVICE_SUCCESS: logger.debug('MySmartBox() failed to get total coin, result was=%s' % (json.dumps(result),)) description = u'当前设备信号弱没有响应,请您稍后重试。' raise ServiceException({'result': 2, 'description': description}) if not result.has_key('total_coin'): raise ServiceException({'result': 2, 'description': u'当前设备暂时不支持获取总的硬币数目,待版本自动升级后,会支持'}) return result['total_coin'] # 基类函数,检查告警状态,只能做一个简单的检查,设备是否在线 def check_alarm(self, alarm): if alarm.faultCode == FAULT_CODE.OFFLINE: dev_info = MessageSender.send(device = self.device, cmd = DeviceCmdCode.GET_DEVINFO, payload = {'IMEI': self.device.devNo, 'fields': []}, timeout = MQTT_TIMEOUT.SHORT) if dev_info['rst'] == 0: return u'设备状态检查在线,网络通畅,网络可能出现闪断' else: raise ServiceException({'result': 2, 'description': u'设备玩命也无法找到网络,设备可能不在线'}) else: return u'无法检查该设备的告警状态,建议您用其他方式确认此告警是否正常' def set_device_function_param(self, request, lastSetConf): cardPrice = request.POST.get("cardPrice") eachCoin = request.POST.get("eachCoin") # 服务器参数 if cardPrice and eachCoin: if not str(cardPrice).isdigit(): raise ServiceException({"result": 2, "description": "刷卡单价必须为整数"}) if not str(eachCoin).isdigit(): raise ServiceException({"result": 2, "description": "脉冲次数必须为整数"}) cardPrice = int(cardPrice) packages = self.device['washConfig'] packages = sorted(packages.values(), key = lambda x: x["coins"]) min_coin = int(packages[0].get("coins")) max_coin = int(packages[-1].get("coins")) eachCoin = int(eachCoin) if min_coin > eachCoin or max_coin < eachCoin: raise ServiceException({"result": 2, "description": "脉冲次数不能超过套餐投币数范围"}) dic = { 'cardPrice': cardPrice, 'eachCoin': eachCoin } dev = Device.objects.get(devNo = self.device.devNo) dev.otherConf.update(dic) dev.save() dev.invalid_device_cache(dev.devNo) def get_dev_setting(self): data = {} # 服务器参数 if self.device['otherConf'] and self.device['otherConf'].get('cardPrice') and self.device['otherConf'].get( 'eachCoin'): data['cardPrice'] = self.device['otherConf']['cardPrice'] data['eachCoin'] = self.device['otherConf']['eachCoin'] return data