zhongchuangCar.py 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. # -*- coding: utf-8 -*-
  2. # !/usr/bin/env python
  3. import logging
  4. import time
  5. from typing import TYPE_CHECKING
  6. from apilib.utils_string import split_str
  7. from apps.web.constant import DeviceCmdCode, MQTT_TIMEOUT, Const
  8. from apps.web.core.adapter.base import SmartBox, fill_2_hexByte
  9. from apps.web.core.exceptions import ServiceException
  10. from apps.web.core.networking import MessageSender
  11. from apps.web.device.models import Device
  12. if TYPE_CHECKING:
  13. pass
  14. logger = logging.getLogger(__name__)
  15. class ChargingZhongChuangCarBox(SmartBox):
  16. DATA_OFFSET = 8
  17. ARRAY_INDEX_INCR = 10
  18. def __init__(self, device):
  19. super(ChargingZhongChuangCarBox, self).__init__(device)
  20. def translate_funcode(self,funCode):
  21. funCodeDict = {
  22. '03':u'从设备读数据',
  23. '06':u'向设备写数据',
  24. }
  25. return funCodeDict.get(funCode,'')
  26. def __read__(self, offset, size):
  27. request_data = fill_2_hexByte(hex(int(offset)), 4)
  28. request_data += (fill_2_hexByte(hex(int(size)), 4))
  29. devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  30. {'IMEI': self._device['devNo'], "funCode": '03', 'data': request_data})
  31. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  32. if devInfo['rst'] == -1:
  33. raise ServiceException({'result': 2, 'description': u'充电桩正在玩命找网络,建议您试试旁边其他设备,或者稍后再试哦'})
  34. elif devInfo['rst'] == 1:
  35. raise ServiceException({'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  36. return devInfo['data'][ChargingZhongChuangCarBox.DATA_OFFSET:]
  37. def __write__(self, offset, value,timeout = MQTT_TIMEOUT.NORMAL,orderNo=None):
  38. request_data = fill_2_hexByte(hex(int(offset)), 4)
  39. request_data += fill_2_hexByte(hex(int(value)), 4)
  40. devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  41. {'IMEI': self._device['devNo'], 'funCode': '06', 'data': request_data},
  42. timeout = timeout)
  43. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  44. if devInfo['rst'] == -1:
  45. raise ServiceException({'result': 2, 'description': u'充电桩正在玩命找网络,建议您试试旁边其他设备,或者稍后再试哦'})
  46. elif devInfo['rst'] == 1:
  47. raise ServiceException({'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  48. if devInfo['data'][:-4] != ('0106' + request_data):
  49. raise ServiceException({'result': 2, 'description': u'写入充电桩数据错误'})
  50. return devInfo
  51. def get_port_info(self, line):
  52. return self.get_port_status().get(line)
  53. @staticmethod
  54. def __parse_port_status(response_data):
  55. def translate_status(status):
  56. if status in [0,1]:
  57. return Const.DEV_WORK_STATUS_IDLE
  58. elif status in [2]:
  59. return Const.DEV_WORK_STATUS_CONNECTED
  60. elif status in [3]:
  61. return Const.DEV_WORK_STATUS_WORKING
  62. elif status in [5,6,7,8]:
  63. return Const.DEV_WORK_STATUS_FAULT
  64. else:
  65. return Const.DEV_WORK_STATUS_FINISHED
  66. if len(response_data) < 80:#现网日志报错,有异常报文上报
  67. return {}
  68. descDict = {
  69. '0':u'空闲',
  70. '1':u'空闲',
  71. '2':u'枪已经连接',
  72. '3':u'正在充电',
  73. '4':u'充电完成',
  74. '5':u'电压偏高',
  75. '6':u'漏电保护',
  76. '7':u'电压偏低',
  77. '8':u'紧急停止'
  78. }
  79. result = split_str(response_data, lens="4"*21)
  80. devStatus = dict()
  81. # 定义多路之间数组下标增量
  82. portNum = int(result[0], 16)
  83. for port in xrange(portNum):
  84. portStr = str(port+1)
  85. devStatus[portStr] = {
  86. "power": int(result[1+port*ChargingZhongChuangCarBox.ARRAY_INDEX_INCR], 16),
  87. "voltage": int(result[2+port*ChargingZhongChuangCarBox.ARRAY_INDEX_INCR], 16),
  88. "elec": int(result[3+port*ChargingZhongChuangCarBox.ARRAY_INDEX_INCR], 16) / 1000.0,
  89. "orgStatus": int(result[4+port*ChargingZhongChuangCarBox.ARRAY_INDEX_INCR], 16),
  90. "balance": int(result[5+port*ChargingZhongChuangCarBox.ARRAY_INDEX_INCR], 16) / 10.0,
  91. "duration": int(result[6+port*ChargingZhongChuangCarBox.ARRAY_INDEX_INCR], 16),
  92. "status": translate_status(int(result[4+port*ChargingZhongChuangCarBox.ARRAY_INDEX_INCR], 16)),
  93. "desc": descDict.get(str(int(result[4+port*ChargingZhongChuangCarBox.ARRAY_INDEX_INCR])))
  94. }
  95. return devStatus
  96. def get_port_status(self, force=False):
  97. # 缓存中会有初始下发的金币信息
  98. devStatus = self.__parse_port_status(self.__read__(0, 21))
  99. # TODO 连接状态不要影响支付 这个地方暂时简单修改 后续需要将这个去掉 然后前台的状态为 连接状态的时候可以进行支付
  100. for value in devStatus.values():
  101. if isinstance(value, dict) and "status" in value and value["status"] == Const.DEV_WORK_STATUS_CONNECTED:
  102. value["status"] = Const.DEV_WORK_STATUS_IDLE
  103. Device.update_dev_control_cache(self._device["devNo"], devStatus)
  104. devCache = Device.get_dev_control_cache(self._device["devNo"])
  105. return devCache
  106. def start_device(self, package, openId, attachParas):
  107. price = int(package['price'] * 10)
  108. if price < 1:
  109. raise ServiceException({'result': 2, 'description': u'请输入正确的支付费用'})
  110. port = attachParas['chargeIndex']
  111. logger.debug('charge index = %s; price = %s' % (port, price))
  112. offset = 10 + (int(port) - 1) * self.ARRAY_INDEX_INCR
  113. orderNo = attachParas.get('orderNo')
  114. devInfo = self.__write__(offset, price, timeout = MQTT_TIMEOUT.START_DEVICE, orderNo = orderNo)
  115. cacheValue = Device.get_dev_control_cache(self._device['devNo'])
  116. if not cacheValue:
  117. return
  118. rechargeRcdId = attachParas.get("linkedRechargeRecordId")
  119. cacheValue.update({
  120. str(port):
  121. {
  122. 'openId': openId,
  123. "coins": package['coins'],
  124. "price": package['price'],
  125. "rechargeRcdId": str(rechargeRcdId) if rechargeRcdId else None,
  126. "vCardId": self._vcard_id,
  127. 'isStart': True,
  128. 'status': Const.DEV_WORK_STATUS_WORKING,
  129. 'finishedTime': int(time.time()) + 24 * 60 * 60
  130. }
  131. })
  132. Device.update_dev_control_cache(self._device['devNo'], cacheValue)
  133. return devInfo
  134. def get_port_status_from_dev(self):
  135. status = self.get_port_status()
  136. allPorts,usedPorts = len(status),0
  137. for portInfo in status.values():
  138. count = 0 if portInfo['status'] in [Const.DEV_WORK_STATUS_IDLE,Const.DEV_WORK_STATUS_FINISHED] else 1
  139. usedPorts += count
  140. status.update({'allPorts':allPorts,'usedPorts':usedPorts,'usePorts':allPorts - len(usedPorts)})
  141. Device.update_dev_control_cache(self._device['devNo'], status)
  142. return status
  143. def analyze_event_data(self, data):
  144. return self.__parse_port_status(data[ChargingZhongChuangCarBox.DATA_OFFSET:])
  145. def reply_left_balance(self,port,balance=0):
  146. offset = 5 + (int(port) - 1) * self.ARRAY_INDEX_INCR
  147. self.__write__(offset, int(balance), timeout=120)