# -*- coding: utf-8 -*- # !/usr/bin/env python import time from apps.common.utils import int_to_hex from apps.web.constant import DeviceCmdCode, MQTT_TIMEOUT, Const from apps.web.core.adapter.base import SmartBox from apps.web.core.exceptions import ServiceException from apps.web.core.networking import MessageSender from apps.web.device.models import Device class WasherBox(SmartBox): WORK_MODE = { u"加强洗": "01", # 工作46分钟 u"标准洗": "02", # 工作38分钟 u"快速洗": "03", # 工作22分钟 u"单脱水": "04", # 工作06分钟 u"桶消毒": "05", # 工作04分钟 u"自检": "06" # 工作30秒 } STATUS_CODE_INFO = { '00': u'待机中', '01': u'预约中', '02': u'消毒清洁中', '03': u'洗衣工作中', '04': u'洗衣机洗涤结束', '05': u'洗衣机自检中', '06': u'进水超时', '07': u'排水超时', '08': u'脱水时撞桶', '09': u'脱水开盖', '0A': u'水位传感器异常', '0B': u'溢水报警', '0C': u'电机故障', '0D': u'通讯故障', 'FD': u'IMEI', 'FE': u'投币金额', } @staticmethod def _parse_status(status): return WasherBox.STATUS_CODE_INFO.get(status, u"未知状态") def _send_data(self, funCode, data, cmd=None, timeout=None): result = MessageSender.send(self.device, cmd or DeviceCmdCode.OPERATE_DEV_SYNC, { "IMEI": self.device.devNo, "data": data, "funCode": funCode }, timeout = timeout or MQTT_TIMEOUT.NORMAL) if result["rst"] != 0: if result['rst'] == -1: raise ServiceException({'result': 2, 'description': u'洗衣机正在玩命找网络,请稍候再试'}) elif result['rst'] == 1: raise ServiceException({'result': 2, 'description': u'洗衣机主板连接故障'}) else: raise ServiceException({'result': 2, 'description': u'系统错误'}) return result def _start(self, workMode): result = self._send_data("02", workMode, timeout = MQTT_TIMEOUT.START_DEVICE) data = result.get("data", "") if data[8:10] != "03": status = WasherBox._parse_status(data[8:10]) raise ServiceException({"result": 2, "description": u"启动失败, {}".format(status)}) return result def _occupy(self, _time): """ 预约洗衣机 时间不在8-20默认15分钟 :param _time: :return: """ if 8 < _time < 15: raise ServiceException({"result": 2, "description": u"预约时间范围在8-20分钟"}) timeHex = int_to_hex(_time, lens=2) result = self._send_data("03", timeHex) data = result.get("data", "") if data[8:10] != "01": raise ServiceException({"result": 2, "description": u"预约失败"}) def _cancel_occupy(self): """ 取消预约 :return: """ self._send_data("05", "00") def _query_work_status(self): result = self._send_data("01", "00") data = result.get("data", "") status = WasherBox._parse_status(data[8:10]) leftTime = int(data[10:12], 16) return { "status": status, "leftTime": leftTime, "statusCode": data[8:10] } def start_device(self, package, openId, attachParas): # 首先校验洗衣机状态 statusInfo = self._query_work_status() if statusInfo.get("statusCode") != "00": raise ServiceException({"result": 2, "description": u"洗衣机当前正在工作,请稍后重试"}) # 然后 找套餐 packName = package.get("name") workMode = WasherBox.WORK_MODE.get(packName) if not workMode: raise ServiceException({"result": 2, "description": "当前洗衣机不支持该启动模式,请联系相应经销商解决"}) # 发指令 result = self._start(workMode) # 写缓存 data = result.get("data", "") leftTime = int(data[10:12], 16) devCache = { "openId": openId, "washName": packName } Device.update_dev_control_cache(self.device.devNo, devCache) result["finishedTime"] = int(time.time()) + 60 * leftTime return result #获取设备的当前状态信息,用于控制面板按钮 def get_device_function_by_key(self, keyName): if keyName == 'workingStatus': status_info = self._query_work_status() leftTime = status_info['leftTime'] code = status_info['statusCode'] if code not in ['03','02']: leftTime = None if leftTime > 47: leftTime = None return {"workingStatus": status_info['status'],'leftTime': leftTime} return None # 控制面板 def press_down_key(self, keyName): ''' 按钮控制面板 ''' cmd = 02 #获取洗衣机状态 status_info = self._query_work_status() # 自检 if keyName == u'zjStart': if status_info['statusCode'] == '03' : raise ServiceException({"result": 2, "description": u"请停止洗衣机"}) if status_info['statusCode'] == '02' : raise ServiceException({"result": 2, "description": u"请等待消毒完成"}) mode = self.WORK_MODE[u'自检'] return self._send_data(cmd, mode) #桶消毒过程点击停止后会进入一个假死的结束状态(04),需要从新发送两次才能正常操作(屏蔽掉,让他自己正常结束) if status_info['statusCode'] == '02': raise ServiceException({"result": 2, "description": u"桶消毒正在工作中,请稍等"}) #仅仅用于停止 if keyName == u'stop': if status_info['statusCode'] == '00': raise ServiceException({"result": 2, "description": u"洗衣机未启动"}) mode = self.WORK_MODE[u'自检'] return self._send_data(cmd, mode) #洗衣机不在待机状态 if status_info['statusCode'] != '00': raise ServiceException({"result": 2, "description": u"洗衣机正在工作中"}) if keyName == u'dtStart': mode = self.WORK_MODE[u'单脱水'] elif keyName == u'ksStart': mode = self.WORK_MODE[u'快速洗'] elif keyName == u'bzStart': mode = self.WORK_MODE[u'标准洗'] elif keyName == u'jqStart': mode = self.WORK_MODE[u'加强洗'] elif keyName == u'xdStart': mode = self.WORK_MODE[u'桶消毒'] else: raise ServiceException({"result": 2, "description": u"参数错误"}) result = self._send_data(cmd, mode) data = result.get("data", "") status = WasherBox._parse_status(data[8:10]) if status == u"未知状态": raise ServiceException({'result': 2, 'description': u'洗衣机出现未知错误,请停止后重试'}) if keyName == 'stop': Device.update_dev_control_cache(self._device['devNo'], {'status': Const.DEV_WORK_STATUS_IDLE}) else: Device.update_dev_control_cache(self._device['devNo'], {'status': Const.DEV_WORK_STATUS_WORKING}) return result