# coding=utf-8 import binascii import logging import time from apps.web.constant import DeviceCmdCode, MQTT_TIMEOUT, Const from apps.web.core.adapter.base import SmartBox from apps.web.core.device_define.hangzhoufulian import FaultMap from apps.web.core.exceptions import ServiceException from apps.web.core.networking import MessageSender from apps.web.device.models import Device from apps.web.user.models import UniqueUser logger = logging.getLogger(__name__) class HZFLChargeBox(SmartBox): def _send_data(self, funCode, sendData, cmd=DeviceCmdCode.OPERATE_DEV_SYNC, timeout=MQTT_TIMEOUT.NORMAL): result = MessageSender.send( device=self.device, cmd=cmd, payload={ "IMEI": self._device["devNo"], "funCode": funCode, "data": sendData }, timeout=timeout ) if "rst" in result: if result["rst"] == -1: raise ServiceException({'result': 2, 'description': u'充电桩正在玩命找网络,请稍候再试'}) elif result["rst"] == 1: raise ServiceException({'result': 2, 'description': u'充电桩暂时无响应,请稍后再试'}) elif result["rst"] == 0: return result else: raise ServiceException({'result': 2, 'description': u'系统错误'}) else: raise ServiceException({'result': 2, 'description': u'系统错误'}) @staticmethod def _to_ascii(s): """ :param s: 原始字符串 :return: """ return binascii.hexlify(s) @staticmethod def _to_str(h): """ :param h: :return: """ return binascii.unhexlify(h) @staticmethod def _parse_0100(data): """ 故障解析 :param data: :return: """ faultCode = data[18: 20] port = int(data[20: 22], 16) isStop = not bool(int(data[22: 24], 16)) return { "faultCode": faultCode, "port": port, "isStop": isStop, "fault": FaultMap.get(faultCode, u"未知错误") } @staticmethod def _parse_0102(data): """端口功率上报""" # TODO zjl 看下是不是轮询的解析 以及流水号的作用 serialNo = data[18: 28] power = int(data[28: 32], 16) port = int(data[32: 34], 16) return { "serilaNo": serialNo, "power": power, "port": port } @staticmethod def _parse_0105(data): """充电开始或者结束上报""" serialNo = data[18: 28] port = int(data[28: 30], 16) needTime = int(data[30: 34], 16) power = int(data[34: 38], 16) isStop = bool(int(data[38: 40], 16)) return { "serialNo": serialNo, "port": port, "needTime": needTime, "power": power, "isStop": isStop } @staticmethod def _parse_000A(data): pass @staticmethod def _parse_0107(data): """使用电量上报""" serialNo = data[18: 28] totalElec = int(data[28: 34], 16) return { "serialNo": serialNo, "totalElec": totalElec } def _check_device(self): """检查设备状态""" self._send_data("FFFF", "") def _set_device_power(self, noPower, littlePower, largePower, noPowerTime): """设置设备功率阈值""" noPowerHex = "{:0>4X}".format(int(noPower)) littlePowerHex = "{:0>4X}".format(int(littlePower)) largePowerHex = "{:0>4X}".format(int(largePower)) noPowerTimeHex = "{:0>2X}".format(int(noPowerTime)) sendData = noPowerTimeHex + noPowerHex + littlePowerHex + largePowerHex result = self._send_data("0003", sendData) if result["data"][18:20] != "01": raise ServiceException({"result": "2", "description": u"参数设置失败,请重试再试!"}) def _set_device_package(self, coins, powerType, chargeTime): """设置设备套餐""" coinsHex = "{:0>2X}".format(coins) powerTypeHex = "{:0>4X}".format(powerType) chargeTimeHex = "{:0>4X}".format(chargeTime) sendData = coinsHex + powerTypeHex + chargeTimeHex result = self._send_data("0101", sendData) if result["data"][18:20] != "01": raise ServiceException({"result": "2", "description": u"参数设置失败,请重试再试!"}) def _start_device(self, orderNo, coins, userId, port): """启动设备""" orderNoHex = "{:0>64}".format(self._to_ascii(orderNo)) coinsHex = "{:0>4X}".format(int(coins)) userIdHex = "{:0>8X}".format(int(userId)) portHex = "{:0>2X}".format(port) sendData = orderNoHex + coinsHex + userIdHex + portHex result = self._send_data("0004", sendData) return result def _get_server_conf(self): otherConf = self.device.get("otherConf", dict()) return { "totalElec": otherConf.get("totalElec", 0) } def _get_device_conf(self): return {} def get_port_status_from_dev(self): maxPorts = 10 resultDict = dict() devCache = Device.get_dev_control_cache(self.device.devNo) for _port in range(1, maxPorts+1): chargeIndex = str(_port) portCache = devCache.get(chargeIndex) if not portCache: portCache = {"status": Const.DEV_WORK_STATUS_IDLE} resultDict[chargeIndex] = portCache allPorts, usedPorts, usePorts = self.get_port_static_info(resultDict) Device.update_dev_control_cache( self._device["devNo"], { "allPorts": allPorts, "usedPorts": usedPorts, "usePorts": usePorts } ) return resultDict def get_port_status(self, force=False): return self.get_port_status_from_dev() def get_dev_setting(self): conf = dict() serverConf = self._get_server_conf() deviceConf = self._get_device_conf() conf.update(serverConf) conf.update(deviceConf) return conf def set_device_function_param(self, request, lastSetConf): if "noPower" in request.POST: pass elif "chargeType" in request.POST: pass else: raise ServiceException({"result": "2", "description": u"不支持的参数设置!"}) def analyze_event_data(self, data): funCode = data[14:16] if funCode == "0100": event = self._parse_0100(data) elif funCode == "0102": event = self._parse_0102(data) elif funCode == "0105": event = self._parse_0105(data) elif funCode == "000A": event = self._parse_000A(data) elif funCode == "0107": event = self._parse_0107(data) else: logger.error("receice unanalyze event data, data is <{}>, device is <{}>".format(data, self.device.devNo)) return event["cmdCode"] = funCode return event def start_device(self, package, openId, attachParas): chargeIndex = attachParas.get("chargeIndex") if not chargeIndex: raise ServiceException({"result": "2", "description": u"请选择合适的充电线路!"}) port = int(chargeIndex) orderNo = attachParas["orderNo"] coins = package["time"] uniqueUser = UniqueUser.objects.filter(openId=openId).first() # type: UniqueUser userId = uniqueUser.userId if uniqueUser else 0 result = self._start_device(orderNo=orderNo, coins=coins, userId=userId, port=port) startTime = int(time.time()) portCache = { "status": Const.DEV_WORK_STATUS_WORKING, "isStart": True, "coins": coins, "openId": openId, "orderNo": orderNo, "startTime": startTime } Device.update_dev_control_cache(self.device.devNo, {str(port): portCache}) result["finishedTime"] = (3600 * 12) + startTime result["startTIme"] = startTime return result def check_dev_status(self, attachParas=None): self._check_device()