wxlz.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. # coding=utf-8
  2. import logging
  3. from typing import TYPE_CHECKING
  4. from apps.web.constant import Const
  5. from apps.web.core.adapter.base import SmartBox
  6. from apps.web.core.device_define.wxlz import DefaultParams
  7. from apps.web.core.exceptions import ServiceException
  8. from apps.web.core.networking import MessageSender
  9. from apps.web.device.models import Device
  10. if TYPE_CHECKING:
  11. from apps.web.user.models import ConsumeRecord
  12. logger = logging.getLogger(__name__)
  13. class ChargingBox(SmartBox):
  14. STATUS_MAP = {
  15. 0x01: Const.DEV_WORK_STATUS_IDLE,
  16. 0x02: Const.DEV_WORK_STATUS_WORKING,
  17. 0x03: Const.DEV_WORK_STATUS_FORBIDDEN,
  18. 0x04: Const.DEV_WORK_STATUS_FAULT,
  19. }
  20. @staticmethod
  21. def _check_package(package):
  22. if package["unit"] == u"分钟":
  23. chargeTime = int(package["time"])
  24. elif package["unit"] == u"小时":
  25. chargeTime = int(package["time"]) * 60
  26. else:
  27. chargeTime = 0
  28. return chargeTime
  29. @staticmethod
  30. def _trans_status(status):
  31. return ChargingBox.STATUS_MAP.get(status, Const.DEV_WORK_STATUS_FAULT)
  32. def _clean_elec(self):
  33. result = MessageSender.send(
  34. device=self.device,
  35. cmd=210,
  36. payload={
  37. "funCode": "clean_elec",
  38. }
  39. )
  40. if result["rst"] == -1:
  41. raise ServiceException({"result": 2, "description": u"设备网络故障,清除电量失败"})
  42. if result["rst"] == 1:
  43. raise ServiceException({"result": 2, "description": u"设备端口故障,停止电量失败"})
  44. def _get_settings_from_device(self):
  45. """
  46. 获取设备端的参数设置 包括存储在模块的参数
  47. :return:
  48. """
  49. result = MessageSender.send(
  50. device=self.device,
  51. cmd=210,
  52. payload={
  53. "funCode": "get_settings"
  54. }
  55. )
  56. if result["rst"] == -1:
  57. raise ServiceException({"result": 2, "description": u"设备网络故障,读取设备参数失败"})
  58. if result["rst"] == 1:
  59. raise ServiceException({"result": 2, "description": u"设备端口故障,读取设备参数失败"})
  60. powerPackage = list()
  61. powerDefaultPrice = int(result["data"]["power_default_price"]) / 100.0
  62. for _item in result["data"]["power_step"]:
  63. powerPackage.append(
  64. {"min": int(_item["min"]), "max": int(_item["max"]), "price": int(_item["price"]) / 100.0}
  65. )
  66. return {
  67. "powerPackage": powerPackage,
  68. "powerDefaultPrice": powerDefaultPrice,
  69. "usedElec": result["data"]["used_elec"] / 100.0,
  70. "temperature": result["data"]["temperature"]
  71. }
  72. def _set_settings_to_device(self, conf):
  73. powerDefaultPrice = int(float(conf["powerDefaultPrice"]) * 100)
  74. powerPackage = list()
  75. for _item in conf["powerPackage"]:
  76. powerPackage.append(
  77. {"min": int(_item["min"]), "max": int(_item["max"]), "price": int(float(_item["price"])*100)}
  78. )
  79. data = {
  80. "power_step": powerPackage,
  81. "power_default_price": powerDefaultPrice
  82. }
  83. result = MessageSender.send(
  84. device=self.device,
  85. cmd=210,
  86. payload={
  87. "funCode": "set_settings",
  88. "data": data
  89. }
  90. )
  91. if result["rst"] == -1:
  92. raise ServiceException({"result": 2, "description": u"设备网络故障,设置设备参数失败"})
  93. if result["rst"] == 1:
  94. raise ServiceException({"result": 2, "description": u"设备端口故障,设置设备参数失败"})
  95. def _stop(self, port):
  96. result = MessageSender.send(
  97. device=self.device,
  98. cmd=210,
  99. payload={
  100. "funCode": "stop",
  101. "data": {"port": int(port)}
  102. }
  103. )
  104. if result["rst"] == -1:
  105. raise ServiceException({"result": 2, "description": u"设备网络故障,停止运行失败"})
  106. if result["rst"] == 1:
  107. raise ServiceException({"result": 2, "description": u"设备端口故障,停止运行失败"})
  108. def _get_all_status_from_device(self):
  109. result = MessageSender.send(
  110. device=self.device,
  111. cmd=210,
  112. payload={
  113. "funCode": "all_status",
  114. }
  115. )
  116. if result["rst"] == -1:
  117. raise ServiceException({"result": 2, "description": u"设备网络故障,获取端口运行状态失败"})
  118. if result["rst"] == 1:
  119. raise ServiceException({"result": 2, "description": u"设备端口故障,获取端口运行状态失败"})
  120. data = result["data"]
  121. allStatus = dict()
  122. for _port, _item in data.items():
  123. allStatus[_port] = {"status": self._trans_status(_item["status"]), "power": _item["power"]}
  124. return allStatus
  125. def _async_settings(self):
  126. otherConf = self.device.get("otherConf", dict())
  127. conf = {
  128. "powerPackage": otherConf.get("powerPackage", DefaultParams.DEFAULT_POWER_PACKAGE),
  129. "powerDefaultPrice": otherConf.get("powerDefaultPrice", DefaultParams.DEFAULT_POWER_PRICE)
  130. }
  131. self._set_settings_to_device(conf)
  132. def _get_port_detail(self, port):
  133. result = MessageSender.send(
  134. device=self.device,
  135. cmd=210,
  136. payload={
  137. "funCode": "port_status",
  138. "data": {
  139. "port": int(port)
  140. }
  141. }
  142. )
  143. if result["rst"] == -1:
  144. raise ServiceException({"result": 2, "description": u"设备网络故障,端口状态获取失败"})
  145. if result["rst"] == 1:
  146. raise ServiceException({"result": 2, "description": u"设备端口故障,端口状态获取失败"})
  147. data = result["data"]
  148. order = data.pop("order", None)
  149. if order:
  150. data["needTime"] = order["charge_time"]
  151. data["startTime"] = order["sts"]
  152. data["openId"] = order["open_id"]
  153. data["consumeMoney"] = order["money"] / 100.0
  154. data["usedTime"] = order["duration"] / 60
  155. data["status"] = self._trans_status(data["status"])
  156. return data
  157. def get_dev_setting(self):
  158. deviceSettings = self._get_settings_from_device()
  159. deviceSettings["powerPackage"] = deviceSettings["powerPackage"] or []
  160. serverSettings = self.device.get("otherConf") or dict()
  161. allSettings = {
  162. "usedElec": deviceSettings["usedElec"],
  163. "temperature": deviceSettings["temperature"],
  164. "minAfterStartCoins": serverSettings.get("minAfterStartCoins", DefaultParams.DEFAULT_MIN_COIN),
  165. "chargeType": "power",
  166. "elecPrice": 0,
  167. "powerPackage": deviceSettings["powerPackage"],
  168. "powerDefaultPrice": deviceSettings["powerDefaultPrice"],
  169. }
  170. return allSettings
  171. def set_device_function_param(self, request, lastSetConf):
  172. chargeType = request.POST.get("chargeType")
  173. if chargeType == "elec":
  174. raise ServiceException({"result": 2, "description": u"电量计费模式尚未开放,敬请期待"})
  175. minAfterStartCoins = request.POST.get("minAfterStartCoins")
  176. powerPackage = request.POST.get("powerPackage")
  177. powerDefaultPrice = request.POST.get("powerDefaultPrice")
  178. otherConf = self.device.get("otherConf", dict())
  179. otherConf["powerPackage"] = powerPackage
  180. otherConf["powerDefaultPrice"] = powerDefaultPrice
  181. otherConf["minAfterStartCoins"] = minAfterStartCoins
  182. Device.objects.filter(devNo=self.device.devNo).update(otherConf=otherConf)
  183. Device.invalid_device_cache(self.device.devNo)
  184. self._set_settings_to_device(otherConf)
  185. def set_device_function(self, request, lastSetConf):
  186. cleanElec = request.POST.get("cleanElec")
  187. if cleanElec:
  188. self._clean_elec()
  189. def start_device_realiable(self, order): # type:(ConsumeRecord)->dict
  190. port = order.used_port
  191. if port == -1:
  192. raise ServiceException({"result": 2, "description": u"请您选择合适的充电线路"})
  193. chargeTime = self._check_package(order.package)
  194. if not chargeTime:
  195. raise ServiceException({"result": 2, "description": u"充电套餐单位错误,请联系设备老板进行处理"})
  196. data = {
  197. "open_id": order.openId,
  198. "order_id": order.orderNo,
  199. "order_type": "com_start",
  200. "port": port,
  201. "charge_time": chargeTime
  202. }
  203. result = MessageSender.send(
  204. device=self.device,
  205. cmd=210,
  206. payload={
  207. "funCode": "start",
  208. "data": data
  209. }
  210. )
  211. return result
  212. def stop(self, port=None):
  213. if not port:
  214. raise ServiceException({"result": 2, "description": u"停止运行失败,无效的设备端口"})
  215. self._stop(port)
  216. def get_port_status_from_dev(self):
  217. allStatus = self._get_all_status_from_device()
  218. status = {}
  219. devCache = Device.get_dev_control_cache(self.device.devNo)
  220. for _key, _value in allStatus.items():
  221. _portCache = devCache.get(_key) or dict()
  222. _portCache.update(_value)
  223. status[_key] = _portCache
  224. Device.update_dev_control_cache(self.device.devNo, status)
  225. allPorts, usedPorts, usePorts = self.get_port_static_info(allStatus)
  226. Device.update_dev_control_cache(
  227. self._device["devNo"],
  228. {
  229. "allPorts": allPorts,
  230. "usedPorts": usedPorts,
  231. "usePorts": usePorts
  232. }
  233. )
  234. return allStatus
  235. def get_port_status(self, force = False):
  236. if force:
  237. self.get_port_status_from_dev()
  238. devCache = Device.get_dev_control_cache(self.device.devNo)
  239. allPorts = devCache.get("allPorts", 10)
  240. status = dict()
  241. for _port in xrange(1, allPorts+1):
  242. status[str(_port)] = {"status": devCache.get(str(_port), dict()).get("status", Const.DEV_WORK_STATUS_IDLE)}
  243. return status
  244. def get_port_info(self, port):
  245. data = self._get_port_detail(port)
  246. return data
  247. def get_port_using_detail(self, port, ctrInfo, isLazy=False):
  248. portCache = ctrInfo.get(str(port), dict())
  249. curInfo = self.get_port_info(port)
  250. curInfo.update(portCache)
  251. return curInfo
  252. def active_deactive_port(self, port, active):
  253. if not active:
  254. self.stop(port)