qianglong.py 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. # coding=utf-8
  2. from apps.web.core.adapter.base import *
  3. import simplejson as json
  4. class QiangLongBox(SmartBox):
  5. PORT_NUMBER_KEY = "CZ"
  6. CARD_NUMBER_KEY = "KH"
  7. CARD_BALANCE = "YE"
  8. DEFAULT_CARD_CST = 1
  9. DEFAULT_CARD_TIME = 3
  10. def _send_data(self, funCode, data=None, cmd=None, timeout=None):
  11. if data is None:
  12. data = ""
  13. if cmd is None:
  14. cmd = DeviceCmdCode.OPERATE_DEV_SYNC
  15. if timeout is None:
  16. timeout = MQTT_TIMEOUT.NORMAL
  17. result = MessageSender.send(device = self.device, cmd = cmd, payload = {
  18. "IMEI": self._device["devNo"],
  19. "funCode": funCode,
  20. "data": data
  21. }, timeout = timeout)
  22. if "rst" in result and result.get("rst") != 0:
  23. if result.get("rst") == -1:
  24. raise ServiceException({"result": 2, "description": u"网络故障,请重新试试"})
  25. if result.get("rst") == 1:
  26. raise ServiceException({"result": 2, "description": u"充电桩无响应,请稍后再试试"})
  27. return result
  28. @staticmethod
  29. def _parse_one_port_data(data):
  30. data0 = data[0:2]
  31. data1 = data[2:4]
  32. data2 = data[4:6]
  33. data3 = data[6:8]
  34. data0Bit = "{:0>8}".format(bin(int(data0, 16)).replace("0b", ""))
  35. data0PartOne = data0Bit[:2]
  36. data0PartTwo = data0Bit[2:]
  37. status = int(data0PartOne)
  38. power = int(data0PartTwo, 2) * 100 + int(data1, 16)
  39. elec = int(data2, 16) + int(data3, 16) * 0.01
  40. return {
  41. "status": status,
  42. "power": power,
  43. "elec": elec
  44. }
  45. @staticmethod
  46. def _parse_event_C0(data):
  47. portStr = str(int(data[6:8], 16))
  48. return {
  49. "portStr": portStr
  50. }
  51. @staticmethod
  52. def _parse_event_EE(data):
  53. # 尾部会有00 终止符
  54. asciiData = data[6: -4]
  55. jsonData = binascii.unhexlify(asciiData)
  56. dictData = json.loads(jsonData.strip(b'\x00'.decode()))
  57. portStr = dictData.get(QiangLongBox.PORT_NUMBER_KEY, 0)
  58. cardNo = dictData.get(QiangLongBox.CARD_NUMBER_KEY, "")
  59. return {
  60. "portStr": portStr,
  61. "cardNo": cardNo
  62. }
  63. def _query_all_port_status(self):
  64. result = self._send_data("D0")
  65. data = result.get("data", "")[8:-4]
  66. portNum = int(result.get("data", "")[6:8] or "0", 16)
  67. portInfo = dict()
  68. for i in range(portNum):
  69. portStr = str(int(data[:2], 16))
  70. portInfo[portStr] = QiangLongBox._parse_one_port_data(data[2:10])
  71. data = data[10:]
  72. print portStr, portInfo[portStr]
  73. return portInfo
  74. def _query_port_status(self, port):
  75. portHex = fill_2_hexByte(hex(int(port)), 2)
  76. result = self._send_data("D1", portHex)
  77. data = result.get("data", "")[6:-4]
  78. return QiangLongBox._parse_one_port_data(data)
  79. def _start(self, port, _time):
  80. statusHex = "01"
  81. timeHex = fill_2_hexByte(hex(int(_time)), 4)
  82. portHex = fill_2_hexByte(hex(int(port)), 2)
  83. return self._send_data("D2", portHex+statusHex+timeHex, timeout = MQTT_TIMEOUT.START_DEVICE)
  84. def _stop(self, port):
  85. statusHex = "00"
  86. timeHex = "0000"
  87. portHex = fill_2_hexByte(hex(int(port)), 2)
  88. return self._send_data("D2", portHex+statusHex+timeHex)
  89. def _response_card(self, portStr, balance, msg):
  90. data = {
  91. "Z": "P",
  92. "ADDR": "1",
  93. }
  94. data.update({
  95. QiangLongBox.PORT_NUMBER_KEY: str(portStr),
  96. QiangLongBox.CARD_BALANCE: str(balance),
  97. "msg": str(msg),
  98. "ZL": str(msg) == "255" and "1" or "255"
  99. })
  100. data = binascii.hexlify(json.dumps(data, separators=(",", ":"))).upper()
  101. self._send_data("EF", data, cmd=DeviceCmdCode.OPERATE_DEV_NO_RESPONSE)
  102. def get_port_status_from_dev(self):
  103. portInfo = self._query_all_port_status()
  104. portDict = dict()
  105. for portStr, info in portInfo.items():
  106. tempStatus = info.get("status", Const.DEV_WORK_STATUS_IDLE)
  107. portDict[portStr] = {"status": tempStatus}
  108. # 更新可用端口数量
  109. allPorts, usedPorts, usePorts = self.get_port_static_info(portDict)
  110. Device.update_dev_control_cache(
  111. self._device["devNo"],
  112. {
  113. "allPorts": allPorts,
  114. "usedPorts": usedPorts,
  115. "usePorts": usePorts
  116. }
  117. )
  118. # 更新端口状态
  119. devCache = Device.get_dev_control_cache(self._device["devNo"])
  120. for port, info in portDict.items():
  121. if port in devCache and isinstance(info, dict):
  122. devCache[port].update({"status": info["status"]})
  123. else:
  124. devCache[port] = info
  125. Device.update_dev_control_cache(self._device["devNo"], devCache)
  126. return portDict
  127. def get_port_status(self, force=False):
  128. if force:
  129. return self.get_port_status_from_dev()
  130. devCache = Device.get_dev_control_cache(self._device["devNo"])
  131. if "allPorts" not in devCache:
  132. self.get_port_status_from_dev()
  133. devCache = Device.get_dev_control_cache(self._device["devNo"])
  134. allPorts = devCache.get("allPorts")
  135. if allPorts is None:
  136. raise ServiceException({'result': 2, 'description': u'充电端口信息获取失败'})
  137. statusDict = dict()
  138. for portNum in xrange(allPorts):
  139. portStr = str(portNum + 1)
  140. tempDict = devCache.get(portStr, {})
  141. if "status" in tempDict:
  142. statusDict[portStr] = {"status": tempDict["status"]}
  143. elif "isStart" in tempDict:
  144. if tempDict["isStart"]:
  145. statusDict[portStr] = {"status": Const.DEV_WORK_STATUS_WORKING}
  146. else:
  147. statusDict[portStr] = {"status": Const.DEV_WORK_STATUS_IDLE}
  148. else:
  149. statusDict[portStr] = {"status": Const.DEV_WORK_STATUS_IDLE}
  150. allPorts, usedPorts, usePorts = self.get_port_static_info(statusDict)
  151. portsDict = {"allPorts": allPorts, "usedPorts": usedPorts, "usePorts": usePorts}
  152. Device.update_dev_control_cache(self._device["devNo"], portsDict)
  153. # 返还的是要显示的端口数量
  154. return statusDict
  155. def start_device(self, package, openId, attachParas):
  156. chargeIndex = attachParas.get("chargeIndex")
  157. _time = package.get("time", 0)
  158. coins = package.get("coins")
  159. result = self._start(port=chargeIndex, _time=_time)
  160. result["finishedTime"] = int(time.time()) + _time * 60
  161. portCache = {
  162. "status": Const.DEV_WORK_STATUS_WORKING,
  163. "coins": coins,
  164. "startTime": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
  165. "openId": openId,
  166. "isStart": True,
  167. "needTime": _time,
  168. "startTimeStamp": int(time.time())
  169. }
  170. Device.update_dev_control_cache(self.device.devNo, {chargeIndex: portCache})
  171. return result
  172. def analyze_event_data(self, data):
  173. cmdCode = data[4:6]
  174. funcName = "_parse_event_{}".format(cmdCode.upper())
  175. func = getattr(QiangLongBox, funcName)
  176. if not func:
  177. return
  178. eventData = func(data)
  179. eventData.update({"cmdCode": cmdCode})
  180. return eventData
  181. def get_dev_setting(self):
  182. otherConf = self.device.get("otherConf", dict())
  183. cardCst = otherConf.get("cardCst", QiangLongBox.DEFAULT_CARD_CST)
  184. cardTime = otherConf.get("cardTime", QiangLongBox.DEFAULT_CARD_TIME)
  185. return {
  186. "cardCst": cardCst,
  187. "cardTime": cardTime
  188. }
  189. def set_device_function_param(self, request, lastSetConf):
  190. cardCst = request.POST.get("cardCst")
  191. cardTime = request.POST.get("cardTime")
  192. if not all([cardCst, cardTime]):
  193. raise ServiceException({"result": "2", "description": u"参数不全"})
  194. otherConf = self.device.get("otherConf", dict())
  195. otherConf.update(
  196. {
  197. "cardCst": cardCst,
  198. "cardTime": cardTime
  199. }
  200. )
  201. Device.objects.filter(devNo=self.device.devNo).update(otherConf=otherConf)
  202. Device.invalid_device_cache(self.device.devNo)
  203. def active_deactive_port(self, port, active):
  204. if not active:
  205. self._stop(port)
  206. else:
  207. raise ServiceException({'result': 2, 'description': u'此设备不支持直接打开端口'})