123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 |
- # coding=utf-8
- from apps.web.core.adapter.base import *
- import simplejson as json
- class QiangLongBox(SmartBox):
- PORT_NUMBER_KEY = "CZ"
- CARD_NUMBER_KEY = "KH"
- CARD_BALANCE = "YE"
- DEFAULT_CARD_CST = 1
- DEFAULT_CARD_TIME = 3
- def _send_data(self, funCode, data=None, cmd=None, timeout=None):
- if data is None:
- data = ""
- if cmd is None:
- cmd = DeviceCmdCode.OPERATE_DEV_SYNC
- if timeout is None:
- timeout = MQTT_TIMEOUT.NORMAL
- result = MessageSender.send(device = self.device, cmd = cmd, payload = {
- "IMEI": self._device["devNo"],
- "funCode": funCode,
- "data": data
- }, timeout = timeout)
- if "rst" in result and result.get("rst") != 0:
- if result.get("rst") == -1:
- raise ServiceException({"result": 2, "description": u"网络故障,请重新试试"})
- if result.get("rst") == 1:
- raise ServiceException({"result": 2, "description": u"充电桩无响应,请稍后再试试"})
- return result
- @staticmethod
- def _parse_one_port_data(data):
- data0 = data[0:2]
- data1 = data[2:4]
- data2 = data[4:6]
- data3 = data[6:8]
- data0Bit = "{:0>8}".format(bin(int(data0, 16)).replace("0b", ""))
- data0PartOne = data0Bit[:2]
- data0PartTwo = data0Bit[2:]
- status = int(data0PartOne)
- power = int(data0PartTwo, 2) * 100 + int(data1, 16)
- elec = int(data2, 16) + int(data3, 16) * 0.01
- return {
- "status": status,
- "power": power,
- "elec": elec
- }
- @staticmethod
- def _parse_event_C0(data):
- portStr = str(int(data[6:8], 16))
- return {
- "portStr": portStr
- }
- @staticmethod
- def _parse_event_EE(data):
- # 尾部会有00 终止符
- asciiData = data[6: -4]
- jsonData = binascii.unhexlify(asciiData)
- dictData = json.loads(jsonData.strip(b'\x00'.decode()))
- portStr = dictData.get(QiangLongBox.PORT_NUMBER_KEY, 0)
- cardNo = dictData.get(QiangLongBox.CARD_NUMBER_KEY, "")
- return {
- "portStr": portStr,
- "cardNo": cardNo
- }
- def _query_all_port_status(self):
- result = self._send_data("D0")
- data = result.get("data", "")[8:-4]
- portNum = int(result.get("data", "")[6:8] or "0", 16)
- portInfo = dict()
- for i in range(portNum):
- portStr = str(int(data[:2], 16))
- portInfo[portStr] = QiangLongBox._parse_one_port_data(data[2:10])
- data = data[10:]
- print portStr, portInfo[portStr]
- return portInfo
- def _query_port_status(self, port):
- portHex = fill_2_hexByte(hex(int(port)), 2)
- result = self._send_data("D1", portHex)
- data = result.get("data", "")[6:-4]
- return QiangLongBox._parse_one_port_data(data)
- def _start(self, port, _time):
- statusHex = "01"
- timeHex = fill_2_hexByte(hex(int(_time)), 4)
- portHex = fill_2_hexByte(hex(int(port)), 2)
- return self._send_data("D2", portHex+statusHex+timeHex, timeout = MQTT_TIMEOUT.START_DEVICE)
- def _stop(self, port):
- statusHex = "00"
- timeHex = "0000"
- portHex = fill_2_hexByte(hex(int(port)), 2)
- return self._send_data("D2", portHex+statusHex+timeHex)
- def _response_card(self, portStr, balance, msg):
- data = {
- "Z": "P",
- "ADDR": "1",
- }
- data.update({
- QiangLongBox.PORT_NUMBER_KEY: str(portStr),
- QiangLongBox.CARD_BALANCE: str(balance),
- "msg": str(msg),
- "ZL": str(msg) == "255" and "1" or "255"
- })
- data = binascii.hexlify(json.dumps(data, separators=(",", ":"))).upper()
- self._send_data("EF", data, cmd=DeviceCmdCode.OPERATE_DEV_NO_RESPONSE)
- def get_port_status_from_dev(self):
- portInfo = self._query_all_port_status()
- portDict = dict()
- for portStr, info in portInfo.items():
- tempStatus = info.get("status", Const.DEV_WORK_STATUS_IDLE)
- portDict[portStr] = {"status": tempStatus}
- # 更新可用端口数量
- allPorts, usedPorts, usePorts = self.get_port_static_info(portDict)
- Device.update_dev_control_cache(
- self._device["devNo"],
- {
- "allPorts": allPorts,
- "usedPorts": usedPorts,
- "usePorts": usePorts
- }
- )
- # 更新端口状态
- devCache = Device.get_dev_control_cache(self._device["devNo"])
- for port, info in portDict.items():
- if port in devCache and isinstance(info, dict):
- devCache[port].update({"status": info["status"]})
- else:
- devCache[port] = info
- Device.update_dev_control_cache(self._device["devNo"], devCache)
- return portDict
- def get_port_status(self, force=False):
- if force:
- return self.get_port_status_from_dev()
- devCache = Device.get_dev_control_cache(self._device["devNo"])
- if "allPorts" not in devCache:
- self.get_port_status_from_dev()
- devCache = Device.get_dev_control_cache(self._device["devNo"])
- allPorts = devCache.get("allPorts")
- if allPorts is None:
- raise ServiceException({'result': 2, 'description': u'充电端口信息获取失败'})
- statusDict = dict()
- for portNum in xrange(allPorts):
- portStr = str(portNum + 1)
- tempDict = devCache.get(portStr, {})
- if "status" in tempDict:
- statusDict[portStr] = {"status": tempDict["status"]}
- elif "isStart" in tempDict:
- if tempDict["isStart"]:
- statusDict[portStr] = {"status": Const.DEV_WORK_STATUS_WORKING}
- else:
- statusDict[portStr] = {"status": Const.DEV_WORK_STATUS_IDLE}
- else:
- statusDict[portStr] = {"status": Const.DEV_WORK_STATUS_IDLE}
- allPorts, usedPorts, usePorts = self.get_port_static_info(statusDict)
- portsDict = {"allPorts": allPorts, "usedPorts": usedPorts, "usePorts": usePorts}
- Device.update_dev_control_cache(self._device["devNo"], portsDict)
- # 返还的是要显示的端口数量
- return statusDict
- def start_device(self, package, openId, attachParas):
- chargeIndex = attachParas.get("chargeIndex")
- _time = package.get("time", 0)
- coins = package.get("coins")
- result = self._start(port=chargeIndex, _time=_time)
- result["finishedTime"] = int(time.time()) + _time * 60
- portCache = {
- "status": Const.DEV_WORK_STATUS_WORKING,
- "coins": coins,
- "startTime": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
- "openId": openId,
- "isStart": True,
- "needTime": _time,
- "startTimeStamp": int(time.time())
- }
- Device.update_dev_control_cache(self.device.devNo, {chargeIndex: portCache})
- return result
- def analyze_event_data(self, data):
- cmdCode = data[4:6]
- funcName = "_parse_event_{}".format(cmdCode.upper())
- func = getattr(QiangLongBox, funcName)
- if not func:
- return
- eventData = func(data)
- eventData.update({"cmdCode": cmdCode})
- return eventData
- def get_dev_setting(self):
- otherConf = self.device.get("otherConf", dict())
- cardCst = otherConf.get("cardCst", QiangLongBox.DEFAULT_CARD_CST)
- cardTime = otherConf.get("cardTime", QiangLongBox.DEFAULT_CARD_TIME)
- return {
- "cardCst": cardCst,
- "cardTime": cardTime
- }
- def set_device_function_param(self, request, lastSetConf):
- cardCst = request.POST.get("cardCst")
- cardTime = request.POST.get("cardTime")
- if not all([cardCst, cardTime]):
- raise ServiceException({"result": "2", "description": u"参数不全"})
- otherConf = self.device.get("otherConf", dict())
- otherConf.update(
- {
- "cardCst": cardCst,
- "cardTime": cardTime
- }
- )
- Device.objects.filter(devNo=self.device.devNo).update(otherConf=otherConf)
- Device.invalid_device_cache(self.device.devNo)
- def active_deactive_port(self, port, active):
- if not active:
- self._stop(port)
- else:
- raise ServiceException({'result': 2, 'description': u'此设备不支持直接打开端口'})
|