delixi.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. # -*- coding: utf-8 -*-
  2. # !/usr/bin/env python
  3. import logging
  4. import time
  5. from apilib.utils_datetime import timestamp_to_dt
  6. from apps.web.constant import DeviceCmdCode, Const, MQTT_TIMEOUT
  7. from apps.web.core.adapter.base import SmartBox, fill_2_hexByte
  8. from apps.web.core.exceptions import ServiceException
  9. from apps.web.core.networking import MessageSender
  10. from apps.web.device.models import Device, Part
  11. logger = logging.getLogger(__name__)
  12. class ChargingDelixiBox(SmartBox):
  13. def __init__(self, device):
  14. super(ChargingDelixiBox, self).__init__(device)
  15. # 设备上报事件
  16. def analyze_event_data(self, data):
  17. if data.get('cmd') == 100:
  18. power = int(data['status'][0:4], 16)
  19. leftTime = int(data['status'][4:8], 16)
  20. reasonCode = data['status'][8:10]
  21. port = str(data['port'])
  22. chargeStatus = '00'
  23. if reasonCode == '03':
  24. reason = u'开始充电'
  25. chargeStatus = '01'
  26. elif reasonCode == '04':
  27. reason = u'空载断电'
  28. elif reasonCode == '05':
  29. reason = u'交流输入故障禁止充电'
  30. elif reasonCode == '06':
  31. reason = u'输出电流过大禁止充电'
  32. elif reasonCode == '07':
  33. reason = u'其他故障禁止充电'
  34. elif reasonCode == '00':
  35. reason = u'结束充电'
  36. else:
  37. reason = u''
  38. return {'cmdCode': 100, 'reason': reason, 'reasonCode': reasonCode, 'chargeStatus': chargeStatus,
  39. 'power': power, 'leftTime': leftTime, 'port': port}
  40. def get_port_status_from_dev(self):
  41. data = '00 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000'
  42. data = data.replace(' ', '')
  43. devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  44. {'IMEI': self._device['devNo'], "funCode": '06', 'data': data})
  45. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  46. if devInfo['rst'] == -1:
  47. raise ServiceException(
  48. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  49. elif devInfo['rst'] == 1:
  50. raise ServiceException(
  51. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  52. data = devInfo['data']
  53. resultDict = {}
  54. for ii in range(10):
  55. jj = 12 + ii * 12
  56. power = int(data[jj:jj + 4], 16)
  57. leftTime = int(data[jj + 4:jj + 8], 16)
  58. devStatus = str(data[jj + 8:jj + 10])
  59. if devStatus == '00':
  60. status = Const.DEV_WORK_STATUS_IDLE
  61. else:
  62. status = Const.DEV_WORK_STATUS_WORKING
  63. money = int(data[jj + 10:jj + 12], 16)
  64. valueDict = {str(ii + 1): {'power': power, 'leftTime': leftTime, 'status': status, 'devStatus': devStatus,
  65. 'money': money}}
  66. resultDict.update(valueDict)
  67. allPorts, usedPorts, usePorts = self.get_port_static_info(resultDict)
  68. Device.update_dev_control_cache(self._device['devNo'],
  69. {'allPorts': allPorts, 'usedPorts': usedPorts, 'usePorts': usePorts})
  70. # 这里存在多线程更新缓存的场景,可能性比较低,但是必须先取出来,然后逐个更新状态,然后再记录缓存
  71. for _ in range(allPorts):
  72. Device.clear_port_control_cache(self._device['devNo'], str(_ + 1))
  73. ctrInfo = Device.get_dev_control_cache(self._device['devNo'])
  74. for v in resultDict.keys():
  75. if ctrInfo.has_key(v):
  76. ctrInfo[v].update({'status': resultDict[v]['status']})
  77. else:
  78. ctrInfo[v] = resultDict[v]
  79. Device.update_dev_control_cache(self._device['devNo'], ctrInfo)
  80. # 判断充电桩是否写入传感器
  81. parts = Part.objects(logicalCode = self._device['logicalCode'])
  82. if not parts.count():
  83. logger.error('The part with logicalcode of {} was not found'.format(self._device['logicalCode']))
  84. else:
  85. # 添加温度互感器
  86. if not Part.objects(logicalCode = self._device['logicalCode'], partType = '3001').count():
  87. temperature = Part(
  88. logicalCode = self._device['logicalCode'],
  89. ownerId = self._device['ownerId'],
  90. partName = u'温度互感器',
  91. partType = '3001'
  92. )
  93. temperature.save()
  94. # 添加电流互感器
  95. elif not Part.objects(logicalCode = self._device['logicalCode'], partType = '3002').count():
  96. electricity = Part(
  97. logicalCode = self._device['logicalCode'],
  98. ownerId = self._device['ownerId'],
  99. partName = u'电流互感器',
  100. partType = '3002'
  101. )
  102. electricity.save()
  103. logger.info('A transformer has been added to locigalcode {} database'.format(self._device['logicalCode']))
  104. return resultDict
  105. def get_port_status(self, force = False):
  106. if force:
  107. return self.get_port_status_from_dev()
  108. ctrInfo = Device.get_dev_control_cache(self._device['devNo'])
  109. statusDict = {}
  110. allPorts = ctrInfo.get('allPorts', 10)
  111. for ii in range(allPorts):
  112. tempDict = ctrInfo.get(str(ii + 1), {})
  113. if tempDict.has_key('status'):
  114. statusDict[str(ii + 1)] = {'status': tempDict.get('status')}
  115. elif tempDict.has_key('isStart'):
  116. if tempDict['isStart']:
  117. statusDict[str(ii + 1)] = {'status': Const.DEV_WORK_STATUS_WORKING}
  118. else:
  119. statusDict[str(ii + 1)] = {'status': Const.DEV_WORK_STATUS_IDLE}
  120. else:
  121. statusDict[str(ii + 1)] = {'status': Const.DEV_WORK_STATUS_IDLE}
  122. allPorts, usedPorts, usePorts = self.get_port_static_info(statusDict)
  123. Device.update_dev_control_cache(self._device['devNo'],
  124. {'allPorts': allPorts, 'usedPorts': usedPorts, 'usePorts': usePorts})
  125. return statusDict
  126. def stop(self, port = None):
  127. # 构造报文
  128. elecFee = fill_2_hexByte(hex(int(float(self._device['otherConf'].get('elecFee')) * 10)))[-2:]
  129. dataPort = ''
  130. for v in range(10):
  131. if v + 1 == port:
  132. dataPort += 'AA00'
  133. else:
  134. dataPort += '0000'
  135. data = elecFee + dataPort + '5CFD'
  136. # 发送报文
  137. devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  138. {'IMEI': self._device['devNo'], "funCode": '06',
  139. 'data': data})
  140. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  141. if devInfo['rst'] == -1:
  142. raise ServiceException({'result': 2, 'description': u'充电桩正在玩命找网络,您的金币还在,重试不需要重新付款,建议您试试旁边其他设备,或者稍后再试哦'})
  143. elif devInfo['rst'] == 1:
  144. raise ServiceException({'result': 2, 'description': u'充电桩正在忙,无响应,您的金币还在,请试试其他线路,或者请稍后再试哦'})
  145. # 更新端口状态
  146. Device.update_dev_control_cache(self._device['devNo'], {str(port): {'status': '00'}})
  147. def translate_funcode(self, funCode):
  148. funCodeDict = {
  149. '03': u'移动支付',
  150. '06': u'获取端口数据',
  151. '02': u'获取设备参数',
  152. }
  153. return funCodeDict.get(funCode, '')
  154. def start_device(self, package, openId, attachParas): # 微信支付
  155. if attachParas is None:
  156. raise ServiceException({'result': 2, 'description': u'请您选择合适的充电线路、电池类型信息'})
  157. if not attachParas.has_key('chargeIndex'):
  158. raise ServiceException({'result': 2, 'description': u'请您选择合适的充电线路'})
  159. # 用户付款
  160. userPay = fill_2_hexByte(hex(int(float(package['price']) * 10)), num = 2)
  161. # 单位电价
  162. setConf = self.get_dev_setting()
  163. elecFee = fill_2_hexByte(hex(int(float(setConf['elecFee']) * 10)), num = 2)
  164. # 要使用的端口
  165. port = attachParas['chargeIndex']
  166. # 编辑端口信息报文
  167. dataPort = ''
  168. for v in range(10):
  169. if v + 1 == int(port):
  170. dataPort += '55' + userPay
  171. else:
  172. dataPort += '0000'
  173. # 完成所有报文
  174. data = elecFee + dataPort + '5CFD'
  175. devInfo = MessageSender.send(device = self.device, cmd = DeviceCmdCode.OPERATE_DEV_SYNC, payload = {
  176. 'IMEI': self._device['devNo'],
  177. "funCode": '06',
  178. 'data': data}, timeout = MQTT_TIMEOUT.START_DEVICE)
  179. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  180. if devInfo['rst'] == -1:
  181. raise ServiceException({'result': 2, 'description': u'充电桩正在玩命找网络,您的金币还在,重试不需要重新付款,建议您试试旁边其他设备,或者稍后再试哦'})
  182. elif devInfo['rst'] == 1:
  183. raise ServiceException({'result': 2, 'description': u'充电桩正在忙,无响应,您的金币还在,请试试其他线路,或者请稍后再试哦'})
  184. # 其他情况返回
  185. jj = int(port) * 12 + 12
  186. if devInfo['data'][jj + 8:jj + 10] in ['05', '06', '07', '09']:
  187. raise ServiceException({'result': 2, 'description': u'充电桩今天休假辣,您的金币还在,请试试其他线路,或者请稍后再试哦'})
  188. start_timestamp = int(time.time())
  189. devInfo['finishedTime'] = start_timestamp + 24 * 60 * 60
  190. Device.update_dev_control_cache(
  191. self._device['devNo'],
  192. {
  193. str(port):
  194. {
  195. 'startTime': timestamp_to_dt(start_timestamp).strftime('%Y-%m-%d %H:%M:%S'),
  196. 'status': Const.DEV_WORK_STATUS_WORKING,
  197. 'finishedTime': devInfo['finishedTime'],
  198. 'isStart': True,
  199. 'coins': package['coins'],
  200. 'elecFee': setConf['elecFee'],
  201. 'openId': openId,
  202. 'refunded': True,
  203. 'vCardId': self._vcard_id
  204. }
  205. })
  206. return devInfo
  207. def get_dev_setting(self):
  208. dev = Device.objects.get(devNo = self._device['devNo'])
  209. elecFee = dev.otherConf.get('elecFee', '1')
  210. return {'elecFee': elecFee}
  211. def set_device_function_param(self, request, lastsetConf):
  212. elecFee = request.POST.get('elecFee', None)
  213. dev = Device.objects.get(devNo = self._device['devNo'])
  214. dev.otherConf.update({'elecFee': str(elecFee)})
  215. dev.save()