hainiaoDouble.py 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  1. # -*- coding: utf-8 -*-
  2. # !/usr/bin/env python
  3. import time
  4. import logging
  5. from apilib.utils_datetime import timestamp_to_dt
  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. from apps.web.constant import Const, DeviceCmdCode, MQTT_TIMEOUT
  11. logger = logging.getLogger(__name__)
  12. class ChargingHaiNiaoDoubleBox(SmartBox):
  13. def __init__(self, device):
  14. super(ChargingHaiNiaoDoubleBox, self).__init__(device)
  15. def translate_funcode(self, funCode):
  16. funCodeDict = {
  17. '01': u'获取端口状态',
  18. '02': u'获取设备参数',
  19. '03': u'操作端口',
  20. '04': u'设置参数',
  21. }
  22. return funCodeDict.get(funCode, '')
  23. def translate_event_cmdcode(self, cmdCode):
  24. cmdDict = {
  25. '86': u'设备上报信息',
  26. }
  27. return cmdDict.get(cmdCode, '')
  28. def get_port_status_from_dev(self): # 获取端口状态
  29. devInfo = MessageSender.send(self.device, self.make_random_cmdcode(),
  30. {'IMEI': self._device['devNo'], "funCode": '01', 'data': '00'})
  31. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  32. if devInfo['rst'] == -1:
  33. raise ServiceException(
  34. {'result': 2, 'description': u'当前设备正在玩命找网络,请您稍候再试'})
  35. elif devInfo['rst'] == 1:
  36. raise ServiceException(
  37. {'result': 2, 'description': u'当前设备忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  38. result = {}
  39. if devInfo['data'][10:12] == '00':
  40. result['1'] = {'status': Const.DEV_WORK_STATUS_IDLE}
  41. result['2'] = {'status': Const.DEV_WORK_STATUS_IDLE}
  42. elif devInfo['data'][10:12] == '01':
  43. result['1'] = {'status': Const.DEV_WORK_STATUS_WORKING}
  44. result['2'] = {'status': Const.DEV_WORK_STATUS_IDLE}
  45. elif devInfo['data'][10:12] == '02':
  46. result['1'] = {'status': Const.DEV_WORK_STATUS_IDLE}
  47. result['2'] = {'status': Const.DEV_WORK_STATUS_WORKING}
  48. elif devInfo['data'][10:12] == '03':
  49. result['1'] = {'status': Const.DEV_WORK_STATUS_WORKING}
  50. result['2'] = {'status': Const.DEV_WORK_STATUS_WORKING}
  51. allPorts, usedPorts, usePorts = self.get_port_static_info(result)
  52. Device.update_dev_control_cache(self._device['devNo'],
  53. {'allPorts': allPorts, 'usedPorts': usedPorts, 'usePorts': usePorts})
  54. # 这里存在多线程更新缓存的场景,可能性比较低,但是必须先取出来,然后逐个更新状态,然后再记录缓存
  55. ctrInfo = Device.get_dev_control_cache(self._device['devNo'])
  56. for strPort, info in result.items():
  57. if ctrInfo.has_key(strPort):
  58. ctrInfo[strPort].update({'status': info['status']})
  59. else:
  60. ctrInfo[strPort] = info
  61. Device.update_dev_control_cache(self._device['devNo'], ctrInfo)
  62. return result
  63. def get_port_status(self, force=False): # 获取端口状态(缓存)
  64. if force:
  65. return self.get_port_status_from_dev()
  66. ctrInfo = Device.get_dev_control_cache(self._device['devNo'])
  67. statusDict = {}
  68. allPorts = ctrInfo.get('allPorts', 1)
  69. for ii in range(allPorts):
  70. tempDict = ctrInfo.get(str(ii + 1), {})
  71. if tempDict.has_key('status'):
  72. statusDict[str(ii + 1)] = {'status': tempDict.get('status')}
  73. elif tempDict.has_key('isStart'):
  74. if tempDict['isStart']:
  75. statusDict[str(ii + 1)] = {'status': Const.DEV_WORK_STATUS_WORKING}
  76. else:
  77. statusDict[str(ii + 1)] = {'status': Const.DEV_WORK_STATUS_IDLE}
  78. else:
  79. statusDict[str(ii + 1)] = {'status': Const.DEV_WORK_STATUS_IDLE}
  80. allPorts, usedPorts, usePorts = self.get_port_static_info(statusDict)
  81. Device.update_dev_control_cache(self._device['devNo'],
  82. {'allPorts': allPorts, 'usedPorts': usedPorts, 'usePorts': usePorts})
  83. return statusDict
  84. def start_device(self, package, openId, attachParas):
  85. if attachParas is None:
  86. raise ServiceException({'result': 2, 'description': u'请您选择合适的充电线路、电池类型信息'})
  87. if not attachParas.has_key('chargeIndex'):
  88. raise ServiceException({'result': 2, 'description': u'请您选择合适的充电线路'})
  89. hexPort = '000' + attachParas['chargeIndex']
  90. if 'linkedRechargeRecordId' in attachParas and attachParas.get('isQuickPay', False):
  91. needPrice = float(package['price'])
  92. else:
  93. needPrice = float(package['coins'])
  94. hexNeedPrice = fill_2_hexByte(hex(int(needPrice * 100)))
  95. needTime = int(package['time'])
  96. hexTime = fill_2_hexByte(hex(needTime))
  97. timeUnit = package.get('unit', u'分钟')
  98. data = hexPort + '01' + hexTime + hexNeedPrice
  99. portStatus = self.get_port_status_from_dev()
  100. if timeUnit == u'秒':
  101. data = hexPort + hexTime + hexNeedPrice
  102. devInfo = MessageSender.send(
  103. device=self.device,
  104. cmd=DeviceCmdCode.OPERATE_DEV_SYNC,
  105. payload={
  106. 'IMEI': self._device['devNo'],
  107. "funCode": '0A',
  108. 'data': data
  109. }, timeout=MQTT_TIMEOUT.START_DEVICE)
  110. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  111. if devInfo['rst'] == -1:
  112. raise ServiceException(
  113. {'result': 2, 'description': u'当前设备正在玩命找网络,您的金币还在,重试不需要重新付款,建议您试试旁边其他设备,或者稍后再试哦'})
  114. elif devInfo['rst'] == 1:
  115. raise ServiceException({'result': 2, 'description': u'当前设备正在忙,无响应,您的金币还在,请试试其他线路,或者请稍后再试哦'})
  116. data = devInfo['data'][8::]
  117. binUsePort = str(bin(int(data[2:4])))[2:]
  118. while len(binUsePort) < 2:
  119. binUsePort = '0' + binUsePort
  120. if binUsePort == '01':
  121. usePort = 1
  122. elif binUsePort == '10':
  123. usePort = 2
  124. result = data[4:8]
  125. if result == '0000': # 代表失败
  126. newValue = {str(usePort): {'status': Const.DEV_WORK_STATUS_FAULT, 'statusInfo': u'充电站故障'}}
  127. Device.update_dev_control_cache(self._device['devNo'], newValue)
  128. raise ServiceException({'result': 2, 'description': u'充电站故障'})
  129. start_timestamp = int(time.time())
  130. finishedTime = start_timestamp + needTime * 60
  131. portDict = {
  132. 'startTime': timestamp_to_dt(start_timestamp).strftime('%Y-%m-%d %H:%M:%S'),
  133. 'status': Const.DEV_WORK_STATUS_WORKING,
  134. 'finishedTime': finishedTime,
  135. 'needPrice': needPrice,
  136. # 个人中心断电需要用到
  137. 'coins': needPrice,
  138. 'isStart': True,
  139. 'needTime': needTime,
  140. 'openId': openId,
  141. 'refunded': False,
  142. 'vCardId': self._vcard_id,
  143. 'timeUnit': timeUnit
  144. }
  145. ctrInfo = Device.get_dev_control_cache(self._device['devNo'])
  146. lastPortInfo = ctrInfo.get(str(usePort), None)
  147. is_continue = False
  148. if lastPortInfo is not None and \
  149. lastPortInfo.get('status', '') == Const.DEV_WORK_STATUS_WORKING and \
  150. lastPortInfo.get('openId', '') == openId:
  151. is_continue = True
  152. if 'needPrice' in lastPortInfo:
  153. portDict['needPrice'] = float(needPrice) + lastPortInfo['needPrice']
  154. if 'needTime' in lastPortInfo:
  155. portDict['needTime'] = needTime + lastPortInfo['needTime']
  156. finishedTime = int(time.time()) + portDict['needTime'] * 60
  157. portDict.update({'finishedTime': finishedTime})
  158. if 'linkedRechargeRecordId' in attachParas and attachParas.get('isQuickPay', False):
  159. item = {
  160. 'rechargeRcdId': str(attachParas['linkedRechargeRecordId'])
  161. }
  162. if is_continue:
  163. payInfo = lastPortInfo.get('payInfo', list())
  164. else:
  165. payInfo = list()
  166. payInfo.append(item)
  167. portDict['payInfo'] = payInfo
  168. else:
  169. if portStatus[attachParas['chargeIndex']]['status'] == Const.DEV_WORK_STATUS_WORKING:
  170. # 续充07指令, 字节不同
  171. data = data[0:4] + data[6:10]
  172. devInfo = MessageSender.send(
  173. device=self.device,
  174. cmd=DeviceCmdCode.OPERATE_DEV_SYNC,
  175. payload={
  176. 'IMEI': self._device['devNo'],
  177. "funCode": '09',
  178. 'data': data
  179. }, timeout=MQTT_TIMEOUT.START_DEVICE)
  180. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  181. if devInfo['rst'] == -1:
  182. raise ServiceException(
  183. {'result': 2, 'description': u'当前设备正在玩命找网络,您的金币还在,重试不需要重新付款,建议您试试旁边其他设备,或者稍后再试哦'})
  184. elif devInfo['rst'] == 1:
  185. raise ServiceException({'result': 2, 'description': u'当前设备正在忙,无响应,您的金币还在,请试试其他线路,或者请稍后再试哦'})
  186. data = devInfo['data'][8::]
  187. binUsePort = str(bin(int(data[2:4])))[2:]
  188. while len(binUsePort) < 2:
  189. binUsePort = '0' + binUsePort
  190. if binUsePort == '01':
  191. usePort = 1
  192. elif binUsePort == '10':
  193. usePort = 2
  194. result = data[4:8]
  195. if result == '0000': # 代表失败
  196. newValue = {str(usePort): {'status': Const.DEV_WORK_STATUS_FAULT, 'statusInfo': u'充电站故障'}}
  197. Device.update_dev_control_cache(self._device['devNo'], newValue)
  198. raise ServiceException({'result': 2, 'description': u'充电站故障'})
  199. start_timestamp = int(time.time())
  200. finishedTime = start_timestamp + needTime * 60
  201. portDict = {
  202. 'startTime': timestamp_to_dt(start_timestamp).strftime('%Y-%m-%d %H:%M:%S'),
  203. 'status': Const.DEV_WORK_STATUS_WORKING,
  204. 'finishedTime': finishedTime,
  205. 'needPrice': needPrice,
  206. # 个人中心断电需要用到
  207. 'coins': needPrice,
  208. 'isStart': True,
  209. 'needTime': needTime,
  210. 'openId': openId,
  211. 'refunded': False,
  212. 'vCardId': self._vcard_id,
  213. 'timeUnit': timeUnit
  214. }
  215. ctrInfo = Device.get_dev_control_cache(self._device['devNo'])
  216. lastPortInfo = ctrInfo.get(str(usePort), None)
  217. is_continue = False
  218. if lastPortInfo is not None and \
  219. lastPortInfo.get('status', '') == Const.DEV_WORK_STATUS_WORKING and \
  220. lastPortInfo.get('openId', '') == openId:
  221. is_continue = True
  222. if 'needPrice' in lastPortInfo:
  223. portDict['needPrice'] = float(needPrice) + lastPortInfo['needPrice']
  224. if 'needTime' in lastPortInfo:
  225. portDict['needTime'] = needTime + lastPortInfo['needTime']
  226. finishedTime = int(time.time()) + portDict['needTime'] * 60
  227. portDict.update({'finishedTime': finishedTime})
  228. if 'linkedRechargeRecordId' in attachParas and attachParas.get('isQuickPay', False):
  229. item = {
  230. 'rechargeRcdId': str(attachParas['linkedRechargeRecordId'])
  231. }
  232. if is_continue:
  233. payInfo = lastPortInfo.get('payInfo', list())
  234. else:
  235. payInfo = list()
  236. payInfo.append(item)
  237. portDict['payInfo'] = payInfo
  238. else:
  239. devInfo = MessageSender.send(
  240. device=self.device,
  241. cmd=DeviceCmdCode.OPERATE_DEV_SYNC,
  242. payload={
  243. 'IMEI': self._device['devNo'],
  244. "funCode": '08',
  245. 'data': data
  246. }, timeout=MQTT_TIMEOUT.START_DEVICE)
  247. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  248. if devInfo['rst'] == -1:
  249. raise ServiceException(
  250. {'result': 2, 'description': u'当前设备正在玩命找网络,您的金币还在,重试不需要重新付款,建议您试试旁边其他设备,或者稍后再试哦'})
  251. elif devInfo['rst'] == 1:
  252. raise ServiceException({'result': 2, 'description': u'当前设备正在忙,无响应,您的金币还在,请试试其他线路,或者请稍后再试哦'})
  253. data = devInfo['data'][8::]
  254. binUsePort = str(bin(int(data[2:4])))[2:]
  255. while len(binUsePort) < 2:
  256. binUsePort = '0' + binUsePort
  257. if binUsePort == '01':
  258. usePort = 1
  259. elif binUsePort == '10':
  260. usePort = 2
  261. result = data[4:8]
  262. if result == '0000': # 代表失败
  263. newValue = {str(usePort): {'status': Const.DEV_WORK_STATUS_FAULT, 'statusInfo': u'充电站故障'}}
  264. Device.update_dev_control_cache(self._device['devNo'], newValue)
  265. raise ServiceException({'result': 2, 'description': u'充电站故障'})
  266. start_timestamp = int(time.time())
  267. finishedTime = start_timestamp + needTime * 60
  268. portDict = {
  269. 'startTime': timestamp_to_dt(start_timestamp).strftime('%Y-%m-%d %H:%M:%S'),
  270. 'status': Const.DEV_WORK_STATUS_WORKING,
  271. 'finishedTime': finishedTime,
  272. 'needPrice': needPrice,
  273. # 个人中心断电需要用到
  274. 'coins': needPrice,
  275. 'isStart': True,
  276. 'needTime': needTime,
  277. 'openId': openId,
  278. 'refunded': False,
  279. 'vCardId': self._vcard_id,
  280. 'timeUnit': timeUnit
  281. }
  282. if 'linkedRechargeRecordId' in attachParas:
  283. item = {
  284. 'rechargeRcdId': str(attachParas['linkedRechargeRecordId'])
  285. }
  286. portDict['payInfo'] = [item]
  287. Device.update_dev_control_cache(self._device['devNo'], {str(usePort): portDict})
  288. return devInfo
  289. def get_dev_setting(self):
  290. devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  291. {'IMEI': self._device['devNo'], "funCode": '02', 'data': '00'})
  292. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  293. if devInfo['rst'] == -1:
  294. raise ServiceException(
  295. {'result': 2, 'description': u'当前设备正在玩命找网络,请您稍候再试'})
  296. elif devInfo['rst'] == 1:
  297. raise ServiceException(
  298. {'result': 2, 'description': u'当前设备忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  299. confData = devInfo['data'][8::]
  300. channelParams = int(confData[0:2], 16)
  301. accumulatedCoins = int(confData[2:6], 16)
  302. versionNumber = int(confData[6:10], 16)
  303. charge1PriceForH0 = int(confData[10:12], 16)
  304. charge1TimeForH0 = int(confData[12:16], 16)
  305. power1PriceForCharge2 = int(confData[22:24], 16)
  306. power1TimeForCharge2 = int(confData[24:28], 16)
  307. power2PriceForCharge2 = int(confData[28:30], 16)
  308. power2TimeForCharge2 = int(confData[30:34], 16)
  309. power3PriceForCharge2 = int(confData[34:36], 16)
  310. power3TimeForCharge2 = int(confData[36:40], 16)
  311. power4PriceForCharge2 = int(confData[40:42], 16)
  312. power4TimeForCharge2 = int(confData[42:46], 16)
  313. binStr = str(bin(channelParams))[2:]
  314. while len(binStr) < 8:
  315. binStr = '0' + binStr
  316. playSound = True if int(binStr[7]) else False
  317. if binStr[4:7] == '001':
  318. clearMode = '1minutes'
  319. elif binStr[4:7] == '010':
  320. clearMode = '2minutes'
  321. elif binStr[4:7] == '011':
  322. clearMode = '3minutes'
  323. else:
  324. clearMode = 'restart'
  325. pauseSwitch = True if int(binStr[2]) else False
  326. # clearMode = '10minutes' if int(binStr[4]) else '1minutes'
  327. workingMode = 'public' if int(binStr[3]) else 'private'
  328. infraredMode = True if int(binStr[1]) else False
  329. coinLaunchMode = 'button' if int(binStr[0]) else 'direct'
  330. device = Device.objects(devNo=self._device['devNo']).first()
  331. minConsumptionLimit = device.otherConf.get('minConsumptionLimit', 0)
  332. return {
  333. 'playSound': playSound,
  334. 'pauseSwitch': pauseSwitch,
  335. 'clearMode': clearMode,
  336. 'workingMode': workingMode,
  337. 'infraredMode': infraredMode,
  338. 'coinLaunchMode': coinLaunchMode,
  339. 'accumulatedCoins': accumulatedCoins,
  340. 'versionNumber': versionNumber,
  341. 'charge1PriceForH0': charge1PriceForH0,
  342. 'charge1TimeForH0': charge1TimeForH0,
  343. 'power1PriceForCharge2': power1PriceForCharge2,
  344. 'power1TimeForCharge2': power1TimeForCharge2,
  345. 'power2PriceForCharge2': power2PriceForCharge2,
  346. 'power2TimeForCharge2': power2TimeForCharge2,
  347. 'power3PriceForCharge2': power3PriceForCharge2,
  348. 'power3TimeForCharge2': power3TimeForCharge2,
  349. 'power4PriceForCharge2': power4PriceForCharge2,
  350. 'power4TimeForCharge2': power4TimeForCharge2,
  351. 'minConsumptionLimit': minConsumptionLimit
  352. }
  353. def send_setting_data(self, data):
  354. devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  355. {'IMEI': self._device['devNo'], "funCode": '04', 'data': data})
  356. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  357. if devInfo['rst'] == -1:
  358. raise ServiceException(
  359. {'result': 2, 'description': u'当前设备正在玩命找网络,请您稍候再试'})
  360. elif devInfo['rst'] == 1:
  361. raise ServiceException(
  362. {'result': 2, 'description': u'当前设备忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  363. if devInfo['data'][14:16] == '01':
  364. raise ServiceException(
  365. {'result': 2, 'description': u'设置失败'})
  366. def set_pauseSwitch_mode(self, pauseSwitch):
  367. data = '08' + ('0001' if pauseSwitch else '0000')
  368. self.send_setting_data(data)
  369. def set_playSound_mode(self, playSound):
  370. data = '07' + ('0001' if playSound else '0000')
  371. self.send_setting_data(data)
  372. def set_infraredMode_mode(self, infraredMode):
  373. data = '0B' + ('0001' if infraredMode else '0000')
  374. self.send_setting_data(data)
  375. def set_base_settings(self, baseSettingsDict):
  376. # workingModeData = '0A' + ('0001' if baseSettingsDict['workingMode'] == 'multiple' else '0000')
  377. workingModeData = '0A0000'
  378. self.send_setting_data(workingModeData)
  379. coinLaunchModeData = '09' + ('0001' if baseSettingsDict['coinLaunchMode'] == 'button' else '0000')
  380. self.send_setting_data(coinLaunchModeData)
  381. # clearMode = '0C' + ('0001' if baseSettingsDict['clearMode'] == '10minutes' else '0000')
  382. # self.send_setting_data(clearMode)
  383. if baseSettingsDict['clearMode'] == '1minutes':
  384. clearMode = '0C0001'
  385. elif baseSettingsDict['clearMode'] == '2minutes':
  386. clearMode = '0C0002'
  387. elif baseSettingsDict['clearMode'] == '3minutes':
  388. clearMode = '0C0003'
  389. else:
  390. clearMode = '0C0004'
  391. self.send_setting_data(clearMode)
  392. device = Device.objects(devNo=self._device['devNo']).first()
  393. device.otherConf['minConsumptionLimit'] = baseSettingsDict['minConsumptionLimit']
  394. device.save()
  395. def set_private_settings(self, powerPriceDict):
  396. charge1PriceForH0 = '14' + fill_2_hexByte(hex(int(powerPriceDict['charge1PriceForH0'])))
  397. self.send_setting_data(charge1PriceForH0)
  398. charge1TimeForH0 = '15' + fill_2_hexByte(hex(int(powerPriceDict['charge1TimeForH0'])))
  399. self.send_setting_data(charge1TimeForH0)
  400. def set_public_settings(self, powerMatterDict):
  401. power1PriceForCharge2 = '18' + fill_2_hexByte(hex(int(powerMatterDict['power1PriceForCharge2'])))
  402. self.send_setting_data(power1PriceForCharge2)
  403. power1TimeForCharge2 = '19' + fill_2_hexByte(hex(int(powerMatterDict['power1TimeForCharge2'])))
  404. self.send_setting_data(power1TimeForCharge2)
  405. power2PriceForCharge2 = '1A' + fill_2_hexByte(hex(int(powerMatterDict['power2PriceForCharge2'])))
  406. self.send_setting_data(power2PriceForCharge2)
  407. power2TimeForCharge2 = '1B' + fill_2_hexByte(hex(int(powerMatterDict['power2TimeForCharge2'])))
  408. self.send_setting_data(power2TimeForCharge2)
  409. power3PriceForCharge2 = '1C' + fill_2_hexByte(hex(int(powerMatterDict['power3PriceForCharge2'])))
  410. self.send_setting_data(power3PriceForCharge2)
  411. power3TimeForCharge2 = '1D' + fill_2_hexByte(hex(int(powerMatterDict['power3TimeForCharge2'])))
  412. self.send_setting_data(power3TimeForCharge2)
  413. power4PriceForCharge2 = '1E' + fill_2_hexByte(hex(int(powerMatterDict['power4PriceForCharge2'])))
  414. self.send_setting_data(power4PriceForCharge2)
  415. power4TimeForCharge2 = '1F' + fill_2_hexByte(hex(int(powerMatterDict['power4TimeForCharge2'])))
  416. self.send_setting_data(power4TimeForCharge2)
  417. def set_device_function(self, request, lastSetConf):
  418. if 'infraredMode' in request.POST:
  419. infraredMode = request.POST['infraredMode']
  420. self.set_infraredMode_mode(infraredMode)
  421. if 'playSound' in request.POST:
  422. playSound = request.POST['playSound']
  423. self.set_playSound_mode(playSound)
  424. if 'pauseSwitch' in request.POST:
  425. pauseSwitch = request.POST['pauseSwitch']
  426. self.set_pauseSwitch_mode(pauseSwitch)
  427. def set_device_function_param(self, request, lastSetConf):
  428. # if 'coinLaunchMode' in request.POST \
  429. # and 'workingMode' in request.POST \
  430. # and 'minConsumptionLimit' in request.POST \
  431. # and 'clearMode' in request.POST:
  432. if 'coinLaunchMode' in request.POST \
  433. and 'minConsumptionLimit' in request.POST \
  434. and 'clearMode' in request.POST:
  435. coinLaunchMode = request.POST['coinLaunchMode']
  436. # workingMode = request.POST['workingMode']
  437. minConsumptionLimit = request.POST['minConsumptionLimit']
  438. clearMode = request.POST['clearMode']
  439. self.set_base_settings({
  440. 'coinLaunchMode': coinLaunchMode,
  441. # 'workingMode': workingMode,
  442. 'minConsumptionLimit': minConsumptionLimit,
  443. 'clearMode': clearMode
  444. })
  445. if 'charge1PriceForH0' in request.POST and 'charge1TimeForH0' in request.POST:
  446. charge1PriceForH0 = request.POST['charge1PriceForH0']
  447. charge1TimeForH0 = request.POST['charge1TimeForH0']
  448. self.set_private_settings({
  449. 'charge1PriceForH0': charge1PriceForH0,
  450. 'charge1TimeForH0': charge1TimeForH0
  451. })
  452. if 'power1PriceForCharge2' in request.POST \
  453. and 'power1TimeForCharge2' in request.POST \
  454. and 'power2PriceForCharge2' in request.POST \
  455. and 'power2TimeForCharge2' in request.POST \
  456. and 'power3PriceForCharge2' in request.POST \
  457. and 'power3TimeForCharge2' in request.POST \
  458. and 'power4PriceForCharge2' in request.POST \
  459. and 'power4TimeForCharge2' in request.POST:
  460. power1PriceForCharge2 = request.POST['power1PriceForCharge2']
  461. power1TimeForCharge2 = request.POST['power1TimeForCharge2']
  462. power2PriceForCharge2 = request.POST['power2PriceForCharge2']
  463. power2TimeForCharge2 = request.POST['power2TimeForCharge2']
  464. power3PriceForCharge2 = request.POST['power3PriceForCharge2']
  465. power3TimeForCharge2 = request.POST['power3TimeForCharge2']
  466. power4PriceForCharge2 = request.POST['power4PriceForCharge2']
  467. power4TimeForCharge2 = request.POST['power4TimeForCharge2']
  468. self.set_public_settings({
  469. 'power1PriceForCharge2': power1PriceForCharge2,
  470. 'power1TimeForCharge2': power1TimeForCharge2,
  471. 'power2PriceForCharge2': power2PriceForCharge2,
  472. 'power2TimeForCharge2': power2TimeForCharge2,
  473. 'power3PriceForCharge2': power3PriceForCharge2,
  474. 'power3TimeForCharge2': power3TimeForCharge2,
  475. 'power4PriceForCharge2': power4PriceForCharge2,
  476. 'power4TimeForCharge2': power4TimeForCharge2
  477. })
  478. def get_port_info(self, line):
  479. devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  480. {'IMEI': self._device['devNo'], "funCode": '01', 'data': '00'})
  481. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  482. if devInfo['rst'] == -1:
  483. raise ServiceException(
  484. {'result': 2, 'description': u'当前设备正在玩命找网络,请您稍候再试'})
  485. elif devInfo['rst'] == 1:
  486. raise ServiceException(
  487. {'result': 2, 'description': u'当前设备忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  488. if str(line) == '1':
  489. leftTimeSec = int(devInfo['data'][12:20], 16)
  490. leftTime = leftTimeSec / 60
  491. elif str(line) == '2':
  492. leftTimeSec = int(devInfo['data'][20:28], 16)
  493. leftTime = leftTimeSec / 60
  494. else:
  495. leftTime = 0
  496. return {'port': line, 'leftTime': leftTime}
  497. def active_deactive_port(self, port, active):
  498. if active:
  499. return
  500. else:
  501. data = '000' + str(port) + '00'
  502. devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  503. {'IMEI': self._device['devNo'], "funCode": '03', 'data': data + '0000'})
  504. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  505. if devInfo['rst'] == -1:
  506. raise ServiceException(
  507. {'result': 2, 'description': u'当前设备正在玩命找网络,请您稍候再试'})
  508. elif devInfo['rst'] == 1:
  509. # 不处理
  510. pass
  511. def analyze_event_data(self, data):
  512. cmdCode = data[6:8]
  513. if cmdCode == '86':
  514. # data = data[8:]
  515. channelChangeStatus = data[10:12]
  516. channelOperateStatus = data[14:16]
  517. binChannelChangeStatus = str(bin(int(channelChangeStatus, 16)))[2:]
  518. while len(binChannelChangeStatus) < 8:
  519. binChannelChangeStatus = '0' + binChannelChangeStatus
  520. binChannelOperateStatus = str(bin(int(channelOperateStatus, 16)))[2:]
  521. while len(binChannelOperateStatus) < 8:
  522. binChannelOperateStatus = '0' + binChannelOperateStatus
  523. channel1Status = False if binChannelChangeStatus[-1] == '1' and binChannelOperateStatus[-1] == '0' else True
  524. channel2Status = False if binChannelChangeStatus[-2] == '1' and binChannelOperateStatus[-2] == '0' else True
  525. channel1Start = False if binChannelChangeStatus[-1] == '1' and binChannelOperateStatus[-1] == '1' else True
  526. channel2Start = False if binChannelChangeStatus[-2] == '1' and binChannelOperateStatus[-2] == '1' else True
  527. if channel1Status is False:
  528. port = '1'
  529. reason = data[16:18]
  530. leftTime = int(data[36:44], 16) / 60
  531. leftPrice = float(int(data[44:48], 16)) / 100
  532. elif channel2Status is False:
  533. port = '2'
  534. reason = data[18:20]
  535. leftTime = int(data[48:56], 16) / 60
  536. leftPrice = float(int(data[56:60], 16)) / 100
  537. else:
  538. port = -1
  539. reason = ''
  540. leftTime = -1
  541. leftPrice = -1
  542. if reason == '00':
  543. desc = u'购买的充电时间或者电量用完了。'
  544. elif reason in ['04', '06', '07']:
  545. desc = u'管理人员可能远程断电了,或是插头被拔掉, 建议您根据已经充电的时间评估是否需要到现场换到其他端口充电。'
  546. elif reason == '05':
  547. desc = u'空载断电。'
  548. else:
  549. desc = u''
  550. return {
  551. 'status': Const.DEV_WORK_STATUS_IDLE,
  552. 'leftPrice': leftPrice,
  553. 'leftTime': leftTime,
  554. 'cmdCode': cmdCode,
  555. 'reason': desc,
  556. 'port': port,
  557. 'channel1Start':channel1Start,
  558. 'channel2Start':channel2Start
  559. }
  560. else:
  561. return {}
  562. def stop(self, port=None):
  563. self.stop_charging_port(port)
  564. infoDict = dict()
  565. infoDict['remainder_time'] = 0
  566. return infoDict
  567. def stop_charging_port(self, port):
  568. self.active_deactive_port(port, False)
  569. def pauseToUseDevice(self, port, oper):
  570. MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_NO_RESPONSE,
  571. {'IMEI': self._device['devNo'], "funCode": '03', 'data': '000' + port + oper + '0000'})
  572. if oper == '02':
  573. Device.update_dev_control_cache(self._device['devNo'], {port: {'pausePort': True}})
  574. elif oper == '01':
  575. Device.update_dev_control_cache(self._device['devNo'], {port: {'pausePort': False}})
  576. else:
  577. pass
  578. @property
  579. def isHaveStopEvent(self):
  580. return True