zhongchuang.py 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. # -*- coding: utf-8 -*-
  2. # !/usr/bin/env python
  3. import logging
  4. from voluptuous import Schema, Range, Required, REMOVE_EXTRA
  5. from apps.web.constant import DeviceCmdCode, Const, MQTT_TIMEOUT
  6. from apps.web.core.adapter.base import SmartBox, fill_2_hexByte
  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. logger = logging.getLogger(__name__)
  11. class ChargingZhongChuangBox(SmartBox):
  12. FIRST_INDEX = 1
  13. DATA_SIZE = 80
  14. DATA_OFFSET = 8
  15. SETTING_FIRST_INDEX = 41
  16. SETTING_LAST_INDEX = 43
  17. SETTING_SCHEMA = Schema({
  18. Required('unitPrice'): Range(min = 1, max = 250, msg = u'单次刷卡扣费参数错误'),
  19. Required('feeRate'): Range(min = 1, max = 99, msg = u'一元可充电度数参数错误'),
  20. Required('powerLimit'): Range(min = 100, max = 3000, msg = u'功耗极限设定参数错误'),
  21. }, extra = REMOVE_EXTRA)
  22. def __init__(self, device):
  23. super(ChargingZhongChuangBox, self).__init__(device)
  24. def translate_funcode(self,funCode):
  25. funCodeDict = {
  26. '03':u'从设备读数据',
  27. '06':u'向设备写数据',
  28. }
  29. return funCodeDict.get(funCode,'')
  30. def __read__(self, offset, size):
  31. request_data = fill_2_hexByte(hex(int(offset)), 4)
  32. request_data += (fill_2_hexByte(hex(int(size)), 4))
  33. devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  34. {'IMEI': self._device['devNo'], "funCode": '03', 'data': request_data})
  35. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  36. if devInfo['rst'] == -1:
  37. raise ServiceException({'result': 2, 'description': u'充电桩正在玩命找网络,建议您试试旁边其他设备,或者稍后再试哦'})
  38. elif devInfo['rst'] == 1:
  39. raise ServiceException({'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  40. return devInfo['data'][ChargingZhongChuangBox.DATA_OFFSET:]
  41. def __write__(self, offset, value,timeout = MQTT_TIMEOUT.NORMAL,orderNo=None):
  42. request_data = fill_2_hexByte(hex(int(offset)), 4)
  43. request_data += fill_2_hexByte(hex(int(value)), 4)
  44. devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  45. {'IMEI': self._device['devNo'], 'funCode': '06', 'data': request_data},
  46. timeout = timeout)
  47. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  48. if devInfo['rst'] == -1:
  49. raise ServiceException({'result': 2, 'description': u'充电桩正在玩命找网络,建议您试试旁边其他设备,或者稍后再试哦'})
  50. elif devInfo['rst'] == 1:
  51. raise ServiceException({'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  52. if devInfo['data'][:-4] != ('0106' + request_data):
  53. raise ServiceException({'result': 2, 'description': u'写入充电桩数据错误'})
  54. return devInfo
  55. def get_port_info(self, line):
  56. return self.get_port_status().get(line)
  57. def __parse_port_status(self, response_data):
  58. if len(response_data) < 44:#现网日志报错,有异常报文上报
  59. return {}
  60. forbidden_flag = int(response_data[40:44], 16)
  61. result = {}
  62. for ii in range(1, 11):
  63. response_status = response_data[(ii - 1) * 4: ii * 4]
  64. status = Const.DEV_WORK_STATUS_IDLE if forbidden_flag == 1 else Const.DEV_WORK_STATUS_FORBIDDEN
  65. if response_status == '0001':
  66. status = Const.DEV_WORK_STATUS_WORKING
  67. elif response_status == '0000':
  68. status = Const.DEV_WORK_STATUS_IDLE if forbidden_flag == 1 else Const.DEV_WORK_STATUS_FORBIDDEN
  69. elif response_status == '0002':
  70. status = Const.DEV_WORK_STATUS_FAULT
  71. result[str(ii)] = {'status': status}
  72. allPorts, usedPorts, usePorts = self.get_port_static_info(result)
  73. Device.update_dev_control_cache(self._device['devNo'],
  74. {'allPorts': allPorts,
  75. 'usedPorts': usedPorts,
  76. 'usePorts': usePorts,
  77. 'ports': result})
  78. return result
  79. def get_port_status(self, force=False):
  80. cacheValue = Device.get_dev_control_cache(self._device['devNo'])
  81. if 'ports' in cacheValue and force:
  82. return cacheValue['ports']
  83. else:
  84. return self.__parse_port_status(self.__read__(21, 11))
  85. def start_device(self, package, openId, attachParas):
  86. price = int(package['price'] * 10)
  87. if price < 1:
  88. raise ServiceException({'result': 2, 'description': u'请输入正确的支付费用'})
  89. logger.debug('charge index = %s; price = %s' % (attachParas['chargeIndex'], price))
  90. orderNo = attachParas.get('orderNo')
  91. devInfo = self.__write__(attachParas['chargeIndex'], price, timeout = MQTT_TIMEOUT.START_DEVICE,
  92. orderNo = orderNo)
  93. cacheValue = Device.get_dev_control_cache(self._device['devNo'])
  94. if not cacheValue:
  95. return
  96. cacheValue.update({'openId': openId, 'isStart': True})
  97. if 'ports' in cacheValue and str(attachParas['chargeIndex']) in cacheValue['ports']:
  98. cacheValue['ports'][str(attachParas['chargeIndex'])].update({'status': Const.DEV_WORK_STATUS_WORKING})
  99. Device.update_dev_control_cache(self._device['devNo'], cacheValue)
  100. return devInfo
  101. def get_dev_setting(self):
  102. device = Device.get_dev(self._device['devNo'])
  103. if device['otherConf']:
  104. return device['otherConf']
  105. else:
  106. response_data = self.__read__(ChargingZhongChuangBox.SETTING_FIRST_INDEX,
  107. ChargingZhongChuangBox.SETTING_LAST_INDEX)
  108. unitPrice = float(int(response_data[0:4], 16)) / 10
  109. feeRate = float(int(response_data[4:8], 16)) / 10
  110. powerLimit = int(response_data[8:12], 16)
  111. Device.update_field(
  112. dev_no = self._device['devNo'],
  113. otherConf = {
  114. 'unitPrice': unitPrice,
  115. 'feeRate': feeRate,
  116. 'powerLimit': powerLimit
  117. })
  118. return {'unitPrice': unitPrice, 'feeRate': feeRate, 'powerLimit': powerLimit}
  119. def set_dev_setting(self, configDict):
  120. settings = {
  121. 'unitPrice': int(10 * float(configDict.get('unitPrice'))),
  122. 'feeRate': int(10 * float(configDict.get('feeRate'))),
  123. 'powerLimit': int(configDict.get('powerLimit'))
  124. }
  125. settings = ChargingZhongChuangBox.SETTING_SCHEMA(settings)
  126. if settings['unitPrice'] != int(10 * float(self._device['otherConf']['unitPrice'])):
  127. self.__write__(ChargingZhongChuangBox.SETTING_FIRST_INDEX, settings['unitPrice'])
  128. if settings['feeRate'] != int(10 * float(self._device['otherConf']['feeRate'])):
  129. self.__write__(ChargingZhongChuangBox.SETTING_FIRST_INDEX + 1, settings['feeRate'])
  130. if settings['powerLimit'] != int(self._device['otherConf']['powerLimit']):
  131. self.__write__(ChargingZhongChuangBox.SETTING_FIRST_INDEX + 2, settings['powerLimit'])
  132. Device.update_field(
  133. dev_no = self._device['devNo'],
  134. otherConf = {
  135. 'unitPrice': float(configDict.get('unitPrice')),
  136. 'feeRate': float(configDict.get('feeRate')),
  137. 'powerLimit': configDict.get('powerLimit')
  138. })
  139. def analyze_event_data(self, data):
  140. self.__parse_port_status(data[ChargingZhongChuangBox.DATA_OFFSET:][20 * 4:31 * 4])
  141. def remote_charge_card(self, price, rechargeRecord=None):
  142. return self.__write__(50, 10 * int(price.amount))
  143. def set_device_function_param(self,request,lastSetConf):
  144. setting = {
  145. 'unitPrice': request.POST.get('unitPrice'),
  146. 'feeRate': request.POST.get('feeRate'),
  147. 'powerLimit': request.POST.get('powerLimit')
  148. }
  149. self.set_dev_setting(setting)