PedicureCom1.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. # -*- coding: utf-8 -*-
  2. # !/usr/bin/env python
  3. import logging
  4. import time
  5. import uuid
  6. from apilib.utils_json import JsonResponse
  7. from apps.web.constant import Const, DeviceCmdCode, MQTT_TIMEOUT
  8. from apps.web.core.adapter.base import SmartBox, hexbyte_2_bin, 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. logger = logging.getLogger(__name__)
  13. class PedicureCom1(SmartBox):
  14. def __init__(self, device):
  15. super(PedicureCom1, self).__init__(device)
  16. # 串口设备的状态检测,需要单独进行,和非串口的不一样
  17. def check_dev_status(self, attachParas = None):
  18. devInfo = self.get_dev_info()
  19. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  20. if devInfo['rst'] == -1:
  21. raise ServiceException(
  22. {'result': 2, 'description': u'当前足疗机正在玩命找网络,请您稍候再试'})
  23. elif devInfo['rst'] == 1:
  24. raise ServiceException(
  25. {'result': 2, 'description': u'当前足疗机忙,无响应,请您稍候再试'})
  26. if not devInfo['isStart']:
  27. Device.invalid_device_control_cache(self._device['devNo'])
  28. if devInfo['status'] == Const.DEV_WORK_STATUS_FAULT:
  29. raise ServiceException({'result': 2, 'description': u'足疗机出现故障:%s,您找下管理员吧' % devInfo['statusInfo']})
  30. # 足疗机的事件报文和get上来的报文一样,直接调用即可
  31. def analyze_event_data(self, data):
  32. return self.analyze_get_data(data)
  33. # 解析get到的报文信息
  34. def analyze_get_data(self, data):
  35. result = {}
  36. if 'F2F2F008' not in data:
  37. return result
  38. status = Const.DEV_WORK_STATUS_WORKING
  39. fault = ''
  40. # 解析返回的报文,报文格式F2F2...
  41. resultData = data[8:24]
  42. if resultData[0:2] == '00':
  43. isStart = False
  44. else:
  45. isStart = True
  46. hTime = resultData[2:4]
  47. mTime = resultData[4:6]
  48. sTime = resultData[6:8]
  49. leftTime = int(hTime, 16) * 3600 + int(mTime, 16) * 60 + int(sTime, 16)
  50. totalTime = int(resultData[8:12], 16) * 3600 + int(resultData[12:13], 16)
  51. hexFault = resultData[14:16]
  52. binFault = hexbyte_2_bin(hexFault)
  53. if binFault[0] == '1':
  54. status = Const.DEV_WORK_STATUS_FAULT
  55. fault = u'堵转故障'
  56. if binFault[1] == '1':
  57. fault = u'按摩脚霍尔传感器不归位'
  58. if binFault[2] == '1':
  59. fault = u'付款没有开机故障'
  60. if leftTime == 0 and fault == '':
  61. status = Const.DEV_WORK_STATUS_IDLE
  62. return {'status': status, 'fault': fault, 'isStart': isStart, 'totalTime': totalTime,
  63. 'leftTime': leftTime}
  64. def get_dev_info(self):
  65. result = MessageSender.send(self.device, DeviceCmdCode.PASSTHROUGH_OPERATE_DEV_SYNC,
  66. {'IMEI': self._device['devNo'], 'funCode': 'F0', 'data': 'F2F2F00100'})
  67. if result['rst'] != 0:
  68. return {'rst': -1, 'isOffline': 1}
  69. result.update(self.analyze_get_data(result['data']))
  70. return result
  71. def changeVolume(self, volume):
  72. service_cache = Device.get_dev_control_cache(self._device['devNo'])
  73. if not PedicureCom1.is_working(service_cache):
  74. raise ServiceException({'result': 2, 'description': u'足疗机已经结束工作,请支付后再试'})
  75. data = fill_2_hexByte(hex(int(volume)), 2)
  76. result = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  77. {'IMEI': self._device['devNo'], 'funCode': 'FA', 'data': data})
  78. if 'rst' in result and result['rst'] != 0:
  79. current_dev_type_name = self._device['devType']['name']
  80. if current_dev_type_name == u'其他':
  81. current_dev_type_name = u'自助设备'
  82. description = u'当前' + current_dev_type_name + u'修改音量失败,可能是当前网络状况差,请稍候再试'
  83. raise ServiceException({'result': 2, 'description': description})
  84. service_cache['volume'] = volume
  85. Device.update_dev_control_cache(self._device['devNo'], service_cache)
  86. leftTime = service_cache['finishedTime'] - int(time.time())
  87. return {
  88. 'leftTime': leftTime if leftTime > 0 else 0
  89. }
  90. def do_control(self, button, value):
  91. cmd_dict = {'start0': '00', 'start1': '01', 'hot1': '02', 'hot0': '03',
  92. 'mode1': '04', 'mode2': '05', 'mode3': '06',
  93. 'strength1': '07', 'strength2': '08', 'strength3': '09', 'strength4': '0A'}
  94. func_name = '%s%d' % (button, value)
  95. if func_name not in cmd_dict:
  96. logger.error('not support function. button = %s; value = %d' % (button, value))
  97. raise ServiceException({'result': 2, 'description': u'暂时不支持该功能'})
  98. dev_info = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  99. {'IMEI': self._device['devNo'], "funCode": 'FC', 'data': cmd_dict[func_name]})
  100. if dev_info and 'rst' in dev_info and dev_info['rst'] != 0:
  101. if dev_info['rst'] == -1:
  102. raise ServiceException({'result': 2, 'description': u'足疗机正在玩命找网络,您的金币还在,重试不需要重新付款,建议您试试旁边其他设备,或者稍后再试哦'})
  103. elif dev_info['rst'] == 1:
  104. raise ServiceException({'result': 2, 'description': u'足疗机正在忙,无响应,您的金币还在,请稍后再试哦'})
  105. def press_button(self, button, value):
  106. service_cache = Device.get_dev_control_cache(self._device['devNo'])
  107. if not PedicureCom1.is_working(service_cache):
  108. raise ServiceException({'result': 2, 'description': u'足疗机已经结束工作,请支付后再试'})
  109. self.do_control(button, value)
  110. service_cache[button] = value
  111. Device.update_dev_control_cache(self._device['devNo'], service_cache)
  112. leftTime = service_cache['finishedTime'] - int(time.time())
  113. return {
  114. 'leftTime': leftTime if leftTime > 0 else 0
  115. }
  116. def send_dev_runtime(self, openId, duration):
  117. dev_info, left_time = self.send_time(int(duration / 60))
  118. if left_time == 0:
  119. Device.update_dev_control_cache(self._device['devNo'], {'status': Const.DEV_WORK_STATUS_IDLE})
  120. return dev_info
  121. need_time = duration * 60
  122. start_time, hot, mode, strength = int(time.time()), 1, 1, 2
  123. finished_time = start_time + need_time
  124. service_cache = Device.get_dev_control_cache(self._device['devNo'])
  125. if PedicureCom1.is_working(service_cache):
  126. service_cache['finishedTime'] = service_cache['finishedTime'] + need_time
  127. else:
  128. service_cache = {'status': Const.DEV_WORK_STATUS_WORKING,
  129. 'startTime': start_time, 'finishedTime': finished_time}
  130. Device.update_dev_control_cache(self._device['devNo'], service_cache)
  131. return dev_info
  132. def send_time(self, time, timeout = MQTT_TIMEOUT.NORMAL):
  133. oxTime = hex(time)[2::]
  134. oxTime = '0000' + oxTime
  135. oxTime = oxTime[-4::]
  136. uuId = str(uuid.uuid4()).replace('-', '')[0:16]
  137. data = uuId + oxTime
  138. result = MessageSender.send(device = self.device,
  139. cmd = DeviceCmdCode.OPERATE_DEV_SYNC,
  140. payload = {
  141. 'IMEI': self._device['devNo'],
  142. 'funCode': '05',
  143. 'data': data
  144. },
  145. timeout = timeout)
  146. if 'rst' in result and result['rst'] != 0:
  147. current_dev_type_name = self._device['devType']['name']
  148. if current_dev_type_name == u'其他':
  149. current_dev_type_name = u'自助设备'
  150. description = u'当前' + current_dev_type_name + u'充值失败,可能是当前网络状况差,请稍候再试'
  151. raise ServiceException({'result': 2, 'description': description})
  152. status = result['data'][24:26]
  153. if status == '00':
  154. raise ServiceException({'result': 2, 'description': u'设备启动异常,请联系客服'})
  155. hour = int(result['data'][26:28], 16)
  156. minute = int(result['data'][28:30], 16)
  157. second = int(result['data'][30:32], 16)
  158. left_time = 3600 * hour + 60 * minute + second
  159. return result, left_time
  160. def test(self, coins):
  161. result, left_time = self.send_time(1)
  162. return result
  163. def start_device(self, package, openId, attachParas):
  164. unit = package.get('unit', u'分钟')
  165. if unit == u'分钟':
  166. duration = int(package['time'])
  167. elif unit == u'小时':
  168. duration = int(package['time']) * 60
  169. elif unit == u'天':
  170. duration = int(package['time']) * 1440
  171. else:
  172. duration = int(package['time'])
  173. dev_info, left_time = self.send_time(duration, timeout = MQTT_TIMEOUT.START_DEVICE)
  174. if left_time == 0:
  175. Device.invalid_device_control_cache(self._device['devNo'])
  176. return dev_info
  177. need_time = duration * 60
  178. start_time, hot, mode, strength = int(time.time()), 1, 1, 2
  179. finished_time = start_time + need_time
  180. service_cache = Device.get_dev_control_cache(self._device['devNo'])
  181. if PedicureCom1.is_working(service_cache):
  182. service_cache['finishedTime'] = service_cache['finishedTime'] + need_time
  183. else:
  184. service_cache = {'status': Const.DEV_WORK_STATUS_WORKING,
  185. 'startTime': start_time, 'finishedTime': finished_time}
  186. Device.update_dev_control_cache(self._device['devNo'], service_cache)
  187. return dev_info
  188. def support_count_down(self, openId = None, port = None):
  189. return True
  190. def count_down(self, request, dev, agent, group, devType, lastOpenId, port = None):
  191. dev_info = self.get_dev_info()
  192. if dev_info['rst'] != 0:
  193. return JsonResponse({'result': 0, 'description': u'足疗机网络不太好,再试试哦'})
  194. result = {
  195. 'result': 1,
  196. 'description': '',
  197. 'payload': {
  198. 'surplus': 0.0,
  199. 'sum': 0.0,
  200. 'name': group['groupName'],
  201. 'address': group['address'],
  202. 'code': devType.get('code'),
  203. 'orderProcessing': False,
  204. 'logicalCode': dev['logicalCode'],
  205. 'user': 'me',
  206. 'agentFeatures': agent.features,
  207. 'status': {
  208. 'hot': 1,
  209. 'mode': 1,
  210. 'strength': 2,
  211. 'volume': 30
  212. }
  213. }
  214. }
  215. if not dev_info['isStart']:
  216. Device.clear_port_control_cache(self._device['devNo'])
  217. return JsonResponse(result)
  218. left_time = dev_info['leftTime']
  219. start_time = int(time.time())
  220. service_cache = Device.get_dev_control_cache(self._device['devNo'])
  221. if PedicureCom1.is_working(service_cache):
  222. cache_left_time = service_cache['finishedTime'] - service_cache['startTime']
  223. diff_left_time = left_time - cache_left_time
  224. finished_time = service_cache['finishedTime'] + diff_left_time
  225. if finished_time >= service_cache['startTime']:
  226. service_cache['startTime'] = start_time
  227. service_cache['finishedTime'] = start_time + left_time
  228. else:
  229. service_cache['finishedTime'] = finished_time
  230. else:
  231. service_cache = {'status': Const.DEV_WORK_STATUS_WORKING,
  232. 'startTime': start_time, 'finishedTime': start_time + left_time}
  233. Device.update_dev_control_cache(self._device['devNo'], service_cache)
  234. result['payload']['surplus'] = left_time / 60.0
  235. result['payload']['sum'] = (service_cache['finishedTime'] - service_cache['startTime']) / 60.0
  236. if 'volume' in service_cache:
  237. result['payload']['status']['volume'] = service_cache['volume']
  238. if 'hot' in service_cache:
  239. result['payload']['status']['hot'] = service_cache['hot']
  240. if 'mode' in service_cache:
  241. result['payload']['status']['mode'] = service_cache['mode']
  242. if 'strength' in service_cache:
  243. result['payload']['status']['strength'] = service_cache['strength']
  244. return JsonResponse(result)
  245. @staticmethod
  246. def is_working(service_cache):
  247. if service_cache and 'finishedTime' in service_cache \
  248. and 'startTime' in service_cache \
  249. and service_cache['finishedTime'] > int(time.time()) \
  250. and service_cache['status'] in [Const.DEV_WORK_STATUS_WORKING, Const.DEV_WORK_STATUS_PAUSE]:
  251. return True
  252. else:
  253. return False
  254. def pause(self, openId, isContinue, port = None):
  255. service_cache = Device.get_dev_control_cache(self._device['devNo'])
  256. if not PedicureCom1.is_working(service_cache):
  257. raise ServiceException({'result': 2, 'description': u'足疗机可能没有工作,请刷新后再试'})
  258. button = 'start'
  259. if isContinue:
  260. value = 1
  261. else:
  262. value = 0
  263. self.do_control(button, value)
  264. service_cache['status'] = Const.DEV_WORK_STATUS_PAUSE
  265. Device.update_dev_control_cache(self._device['devNo'], service_cache)
  266. leftTime = service_cache['finishedTime'] - int(time.time())
  267. return {
  268. 'leftTime': leftTime if leftTime > 0 else 0
  269. }