weifule_washer.py 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571
  1. # -*- coding: utf-8 -*-
  2. #!/usr/bin/env python
  3. import copy
  4. import time
  5. from apps.web.constant import DeviceCmdCode, Const, FAULT_CODE, ErrorCode, MQTT_TIMEOUT
  6. from apps.web.core.adapter.base import SmartBox
  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.user.models import ConsumeRecord, Card
  11. from apilib.utils_AES import EncryptDate
  12. cardKey = 'FR4e1OFCnDdrYA7u'
  13. class WashingWEIFULEBox(SmartBox):
  14. def __init__(self, device):
  15. super(WashingWEIFULEBox, self).__init__(device)
  16. def translate_funcode(self, funCode):
  17. funCodeDict = {
  18. '01': u'查询详细信息',
  19. '02': u'启动洗衣订单',
  20. '03': u'结束洗衣订单',
  21. '04': u'查询订单',
  22. '05': u'查询统计信息',
  23. '06': u'清除统计信息',
  24. '07': u'下发配置信息',
  25. '08': u'查询配置信息',
  26. '09': u'设置卡模式',
  27. '0A': u'查询卡模式',
  28. }
  29. return funCodeDict.get(funCode, '')
  30. def get_desc_from_code(self, errCode):
  31. errCode = hex(errCode)
  32. descDict = {
  33. '0xe1':u'获取水位失败',
  34. '0xe2':u'进水阀操作失败',
  35. '0xe3':u'排水阀操作失败',
  36. '0xe4':u'门状态获取失败',
  37. '0xe5':u'操作电机失败',
  38. '0xe6':u'蜂鸣器失败',
  39. '0xe7':u'获取电机状态失败',
  40. '0xe8':u'获取进水阀状态失败',
  41. '0xe9':u'获取出水阀的状态失败',
  42. '0xea':u'LeD错误',
  43. '0xeb':u'串口通讯失败',
  44. '0xec':u'暂时不用,没有对应的命令码',
  45. '0xed':u'操作总的继电器失败',
  46. '0xee':u'获取总继电器状态失败',
  47. '0xef':u'碰撞发生关闭订单',
  48. '0xf1':u'开门暂停订单',
  49. '0xf2':u'断电失败',
  50. '0xf3':u'水位异常',
  51. '0xf4':u'漫水事件',
  52. '0xf5':u'排水超时',
  53. '0xf6':u'脱水不平衡,暂停任务,进行平衡修正',
  54. '0xf7':u'水位相差较大,暂停任务,等待进水',
  55. '0xf8':u'脱水不平衡,建议用户手工开门修正,然后合盖运行',
  56. '0xf9':u'人工关闭订单',
  57. '0xfa':u'注水超时',
  58. '0xfb':u'设备处于禁用状态'
  59. }
  60. return descDict.get(str(errCode), u'正常完成')
  61. def translate_event_cmdcode(self, cmdCode):
  62. cmdDict = {
  63. }
  64. return cmdDict.get(cmdCode, '')
  65. def test(self, coins):
  66. data = {'funCode':0x14}
  67. devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  68. {'IMEI': self._device['devNo'], 'data': data})
  69. if devInfo['rst'] not in [0, 1, -1]:
  70. devInfo['desc'] = self.get_desc_from_code(devInfo['rst'])
  71. return devInfo
  72. def check_feedback_result(self, devInfo):
  73. if not devInfo.has_key('rst'):
  74. raise ServiceException({'result': 2, 'description': u'报文异常'})
  75. if devInfo['rst'] == -1:
  76. raise ServiceException({'result': 2, 'description': u'洗衣机正在玩命找网络,请您稍候再试'})
  77. if devInfo['rst'] == 1:
  78. raise ServiceException({'result': 2, 'description': u'串口通讯失败,您稍候再试,或者联系客服'})
  79. if devInfo['rst'] == 2:
  80. raise ServiceException({'result': 2, 'description': u'没有找到对应的套餐'})
  81. if devInfo['rst'] == 3:
  82. raise ServiceException({'result': 2, 'description': u'创建订单失败'})
  83. if devInfo['rst'] == 5:
  84. raise ServiceException({'result': 2, 'description': u'设备正在自检'})
  85. if devInfo['rst'] == 6:
  86. raise ServiceException({'result': 2, 'description': u'任务订单已经满了,请等当前订单结束后再使用'})
  87. def check_dev_status(self, attachParas=None):
  88. data = {'funCode':0x01}
  89. devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  90. {'IMEI': self._device['devNo'], 'data': data})
  91. self.check_feedback_result(devInfo)
  92. data = devInfo['data']
  93. if data.has_key('order') and data['order']:
  94. raise ServiceException({"result": 2, "description": u"有任务正在运行,不允许使用"})
  95. if data['devStatus'].has_key('errors') and data['devStatus']['errors']:
  96. descList = []
  97. for err in data['devStatus']['errors']:
  98. descList.append(self.get_desc_from_code(err))
  99. raise ServiceException({"result": 2, "description": u"洗衣机传感器异常:%s" % ','.join(descList)})
  100. if data['devStatus'].has_key('status') and data['devStatus']['status'] == 'forbidden':
  101. raise ServiceException({"result": 2, "description": u"当前洗衣机处于禁用状态,无法使用,请您使用其他洗衣机"})
  102. if data['devStatus']['door'] == 1:
  103. raise ServiceException({"result": 2, "description": u"请您先关闭洗衣机盖子,然后在付费使用"})
  104. def start_device(self, package, openId, attachParas):
  105. if attachParas is None:
  106. raise ServiceException({'result': 2, 'description': u'请您选择合适的套餐信息'})
  107. coins = int(package['coins']) # 单位为元
  108. onPoints = attachParas.get('onPoints')
  109. if onPoints: # 远程上分
  110. self.stop_charging_port()
  111. orderNo = ConsumeRecord.make_no()
  112. else:
  113. orderNo = str(attachParas.get("orderNo"))
  114. data = {'funCode':0x02, 'orderNo':orderNo, 'coins':coins}
  115. devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  116. {'IMEI': self._device['devNo'], 'data': data}, timeout=MQTT_TIMEOUT.START_DEVICE)
  117. self.check_feedback_result(devInfo)
  118. data = devInfo['data']
  119. if devInfo['rst'] != 0: # 成功
  120. desc = self.get_desc_from_code(devInfo['rst'])
  121. raise ServiceException({'result': 2, 'description': u'洗衣机响应异常:%s,请您稍后再试哦' % desc})
  122. finishedTime = int(time.time()) + 24*60*60
  123. Device.update_dev_control_cache(self._device['devNo'], {'finishedTime':finishedTime,'status':Const.DEV_WORK_STATUS_WORKING})
  124. devInfo['consumeOrderNo'] = orderNo
  125. devInfo['finished_time'] = finishedTime # 这个时间实际上不需要,因为用户打开个人中心的时候,可以直接到设备上获取时间
  126. return devInfo
  127. def analyze_event_data(self, data):
  128. if data['funCode'] == 34: # 如果是结束事件,需要把reason翻译出来
  129. order = data['order']
  130. order['reason'] = self.get_desc_from_code(order['desc'])
  131. data['order'] = order
  132. return data
  133. def get_dev_consume_count(self):
  134. devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  135. {'IMEI': self._device['devNo'], 'data': {'funCode': 0x05}})
  136. self.check_feedback_result(devInfo)
  137. data = devInfo['data']
  138. return {'cardFee': data['total_card'] / 100.0, 'coinFee': data['total_coin'] / 100.0} # 单位为分
  139. def __translate_status_from_str(self, status):
  140. dictConf = {
  141. 'idle':Const.DEV_WORK_STATUS_IDLE,
  142. 'busy':Const.DEV_WORK_STATUS_WORKING,
  143. 'forbid':Const.DEV_WORK_STATUS_FORBIDDEN,
  144. 'fault':Const.DEV_WORK_STATUS_FAULT,
  145. 'running':Const.DEV_WORK_STATUS_WORKING
  146. }
  147. return dictConf.get(status, Const.DEV_WORK_STATUS_IDLE)
  148. # 停止该端口下的所有任务
  149. def stop_charging_port(self, port=-2):
  150. devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  151. {'IMEI': self._device['devNo'], 'data': {'funCode': 0x03}})
  152. self.check_feedback_result(devInfo)
  153. if devInfo['rst'] == 0:
  154. Device.update_dev_control_cache(self._device['devNo'], {str(port): {'status': Const.DEV_WORK_STATUS_IDLE}})
  155. return True if devInfo['rst'] == 0 else False
  156. def get_order(self, order_no):
  157. devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  158. {'IMEI': self._device['devNo'], 'data': {'funCode': 0x04, 'orderNo': order_no}})
  159. self.check_feedback_result(devInfo)
  160. orders = devInfo['data'].get('orders', None)
  161. curOrder = None
  162. for tmpOrder in orders:
  163. if tmpOrder['id'] == order_no:
  164. curOrder = tmpOrder
  165. break
  166. if not curOrder:
  167. return None
  168. result = {}
  169. if not curOrder.has_key('orderType'): # 有可能没有订单,应该返回空
  170. return result
  171. result['status'] = curOrder['status']
  172. if curOrder['orderType'] == 'apps_start':
  173. result['consumeType'] = 'mobile'
  174. try:
  175. rcd = ConsumeRecord.objects.get(orderNo=curOrder['id'])
  176. if u'虚拟卡' in rcd.remarks:
  177. result['consumeType'] = 'mobile_vcard'
  178. except Exception, e:
  179. pass
  180. elif curOrder['orderType'] == 'coin_start':
  181. result['consumeType'] = 'coin'
  182. elif curOrder['orderType'] == 'card_start':
  183. result['consumeType'] = 'card'
  184. if curOrder.has_key('needTime'):
  185. result['needTime'] = round(curOrder['needTime'] / 60000.0, 1)
  186. if curOrder.has_key('passedTime'):
  187. result['duration'] = round(curOrder['passedTime'] / 60000.0, 1)
  188. if curOrder.has_key('leftTime'):
  189. result['leftTime'] = round(curOrder['leftTime'] / 60000.0, 1)
  190. if curOrder.has_key('card_no'):
  191. result['cardNo'] = str(int(curOrder['card_no'], 16))
  192. if curOrder.has_key('id') and (curOrder['orderType'] not in ['coin_start', 'card_charge']) : # card_charge
  193. try:
  194. rcd = ConsumeRecord.objects.get(orderNo=curOrder['id'])
  195. result['openId'] = rcd['openId']
  196. result['coins'] = float(str(rcd['coin'])) # 都用coins
  197. result['orderNo'] = str(curOrder['id'])
  198. except Exception, e:
  199. return None
  200. return result
  201. def response_card_balance(self, cardNo, balance, result):
  202. devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  203. {'IMEI': self._device['devNo'], 'data': {'funCode':0x0F, 'card_no':cardNo, 'balance':int(100 * float(balance)), 'result':result}})
  204. self.check_feedback_result(devInfo)
  205. # 获取设备配置参数
  206. def get_dev_setting(self):
  207. devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  208. {'IMEI': self._device['devNo'], 'data': {'funCode': 0x08}})
  209. self.check_feedback_result(devInfo)
  210. conf = devInfo['data']
  211. nameDict = {
  212. 'dantuoshui':u'单脱水',
  213. 'kuaishuxi':u'快速洗',
  214. 'biaozhunxi':u'标准洗',
  215. 'dawuxi':u'大物洗',
  216. }
  217. pkgConf = conf['package_work_conf'] # 单位转为分钟
  218. for name,tempConf in pkgConf.items():
  219. tempConf['needTime'] =tempConf['needTime'] / 60000
  220. tempConf['name'] = nameDict.get(name,'')
  221. conf['package_work_conf'].pop('tongqingjie') # 先不要显示桶清洁
  222. result = {
  223. 'motify_dewater_unbalance': conf['motify_dewater_unbalance'],
  224. 'order_memory':conf['order_memory'],
  225. 'protect_conf':conf['protect_conf'],
  226. 'max_unbalance_time':conf['max_unbalance_time'],
  227. 'washer_status':conf['washer_status'],
  228. 'zero_level':conf['water_level_conf']['zero_level'],
  229. 'drain_low_level':conf['water_level_conf']['drain_low_level'],
  230. 'drain_delay_time':conf['water_level_conf']['drain_delay_time']/60000,
  231. 'fulled_level':conf['water_level_conf']['fulled_level'],
  232. 'water_levels':conf['water_level_conf']['water_levels'],
  233. 'package_work_conf':pkgConf,
  234. }
  235. return result
  236. # 获取设备配置参数
  237. def set_dev_setting(self, setConf):
  238. data = {'funCode':0x01}
  239. devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  240. {'IMEI': self._device['devNo'], 'data': data})
  241. self.check_feedback_result(devInfo)
  242. data = devInfo['data']
  243. if data.has_key('order') and data['order']:
  244. raise ServiceException({"result": 2, "description": u"有任务正在运行,不允许下发配置"})
  245. data = {'funCode':0x07,'water_level_conf':{},'package_work_conf':{}}
  246. # 如果是卡密码,直接进行修改
  247. if setConf.has_key('card_pwd'):
  248. return self.set_card_pwd(setConf['card_pwd'])
  249. if setConf.has_key('motify_dewater_unbalance'):
  250. data['motify_dewater_unbalance'] = setConf['motify_dewater_unbalance']
  251. if setConf.has_key('order_memory'):
  252. data['order_memory'] = setConf['order_memory']
  253. if setConf.has_key('zero_level'):
  254. # 0水位一定要比刻度1要大。
  255. if setConf.has_key('water_levels'):
  256. firstLevel =setConf['water_levels'][0]
  257. if setConf['zero_level'] <= firstLevel:
  258. raise ServiceException({'result': 2, 'description': u'零水位一定要比水位刻度1的值要大。(值越大,水位越低)'})
  259. data['water_level_conf']['zero_level'] = setConf['zero_level']
  260. if setConf.has_key('water_levels'):
  261. # 水位刻度的检查。必须一个个比一个小。
  262. levels = setConf['water_levels']
  263. for ii in range(len(levels)-1):
  264. if levels[ii+1] >= levels[ii]:
  265. raise ServiceException({'result': 2, 'description': u'刻度%s的值,必须大于刻度%s的值(值越大,水位越低)' % ((ii +1),(ii +2))})
  266. data['water_level_conf']['water_levels'] = setConf['water_levels']
  267. if setConf.has_key('fulled_level'):
  268. data['water_level_conf']['fulled_level'] = setConf['fulled_level']
  269. if setConf.has_key('drain_low_level'):
  270. data['water_level_conf']['drain_low_level'] = setConf['drain_low_level']
  271. if setConf.has_key('drain_delay_time'):
  272. if setConf['drain_delay_time'] <= 0 or setConf['drain_delay_time'] >= 20:
  273. raise ServiceException({'result': 2, 'description': u'排水低于低水位后的等待时间不允许为0分钟,不允许超过20分钟。'})
  274. data['water_level_conf']['drain_delay_time'] = setConf['drain_delay_time'] * 60000
  275. if setConf.has_key('protect_conf'):
  276. data['protect_conf'] = setConf['protect_conf']
  277. if setConf.has_key('washer_status'):
  278. data['washer_status'] = setConf['washer_status']
  279. if setConf.has_key('max_unbalance_time'):
  280. data['max_unbalance_time'] = setConf['max_unbalance_time']
  281. #检查套餐的时间,并转为ms
  282. if setConf.has_key('package_work_conf'):
  283. pkgConf = setConf['package_work_conf']
  284. for name,conf in pkgConf.items():
  285. if name == 'dantuoshui' and conf['needTime'] < 5:
  286. raise ServiceException({'result': 2, 'description': u'单脱水的时间不允许小于5分钟'})
  287. if name == 'kuaishuxi' and conf['needTime'] < 25:
  288. raise ServiceException({'result': 2, 'description': u'快速洗的时间不允许小于25分钟'})
  289. if name == 'biaozhunxi' and conf['needTime'] < 35:
  290. raise ServiceException({'result': 2, 'description': u'标准洗的时间不允许小于35分钟'})
  291. if name == 'dawuxi' and conf['needTime'] < 45:
  292. raise ServiceException({'result': 2, 'description': u'大物洗的时间不允许小于45分钟'})
  293. conf['needTime'] = conf['needTime'] * 60000
  294. data['package_work_conf'][name] = conf
  295. devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  296. {'IMEI': self._device['devNo'], 'data': data})
  297. self.check_feedback_result(devInfo)
  298. def ack_event(self, orderNo, funCode):
  299. devInfo = MessageSender.send(self.device, DeviceCmdCode.PASSTHROUGH_OPERATE_DEV_NO_RESPONSE,
  300. {'IMEI': self._device['devNo'], 'data': {'funCode':funCode, 'orderNo':orderNo}})
  301. self.check_feedback_result(devInfo)
  302. def clear_dev_feecount(self):
  303. devInfo = MessageSender.send(self.device, self.make_random_cmdcode(),
  304. {'IMEI': self._device['devNo'], 'data': {'funCode':0x06, 'total_coin':True, 'total_card':True}})
  305. self.check_feedback_result(devInfo)
  306. def response_card_charge_result(self, cardNo, result):
  307. MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SERVER_ASYNC,
  308. {'IMEI': self._device['devNo'], 'data': {'funCode':0x0F, 'card_no':cardNo, 'result':result}})
  309. def reboot_device(self):
  310. data = {'funCode':0x0B, 'reset_mcu':True}
  311. MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  312. {'IMEI': self._device['devNo'], 'data': data})
  313. MessageSender.async_send(self.device, DeviceCmdCode.SET_DEVINFO,
  314. {'IMEI': self._device['devNo'], 'restart': True})
  315. def send_water_cmd(self,oper):
  316. devInfo = MessageSender.send(self.device, self.make_random_cmdcode(),
  317. {'IMEI': self._device['devNo'], 'data': {'funCode':0x10, 'oper':oper}})
  318. self.check_feedback_result(devInfo)
  319. def recovery_water_conf(self):
  320. devInfo = MessageSender.send(self.device, self.make_random_cmdcode(),
  321. {'IMEI': self._device['devNo'], 'data': {'funCode':0x13}})
  322. self.check_feedback_result(devInfo)
  323. def set_device_function(self, request, lastSetConf):
  324. if request.POST.has_key('clearSum'):
  325. self.clear_dev_feecount()
  326. elif request.POST.has_key('reboot'):
  327. self.reboot_device()
  328. elif request.POST.has_key('ksps') and request.POST.get('ksps'):
  329. self.send_water_cmd('drain')
  330. elif request.POST.has_key('tzps') and request.POST.get('tzps'):
  331. self.send_water_cmd('stop_drain')
  332. elif request.POST.has_key('ksjs') and request.POST.get('ksjs'):
  333. self.send_water_cmd('inject')
  334. elif request.POST.has_key('tzjs') and request.POST.get('tzjs'):
  335. self.send_water_cmd('stop_inject')
  336. elif request.POST.has_key('hfsw') and request.POST.get('hfsw'):
  337. self.recovery_water_conf()
  338. elif request.POST.has_key('tzyx') and request.POST.get('tzyx'):
  339. self.stop_charging_port()
  340. elif request.POST.has_key('xtzj') and request.POST.get('xtzj'):
  341. devInfo = self.test(1)
  342. self.check_feedback_result(devInfo)
  343. if devInfo['rst'] != 0:
  344. desc = self.get_desc_from_code(devInfo['rst'])
  345. raise ServiceException({'result': 2, 'description': u'系统自检报错:%s' % desc})
  346. def set_device_function_param(self, request, lastSetConf):
  347. newConf = copy.deepcopy(request.POST)
  348. newConf.pop('logicalCode', None)
  349. self.set_dev_setting(newConf)
  350. def get_card_pwd(self):
  351. devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  352. {'IMEI': self._device['devNo'], 'data': {'funCode': 0x11}})
  353. self.check_feedback_result(devInfo)
  354. result = devInfo['data']
  355. enObj = EncryptDate(cardKey)
  356. cardPwd = enObj.decrypt(result['card_pwd'])
  357. if not cardPwd:
  358. cardPwd = ''
  359. return {'card_pwd':cardPwd}
  360. def translante_card_no(self, hexCardNo):
  361. return int(hexCardNo, 16)
  362. def check_pwd(self, pwd):
  363. if len(pwd) != 6:
  364. raise ServiceException({'result': 2, 'description': u'密码必须是6位纯数字密码'})
  365. for char in pwd:
  366. if not (char >= '0' and char <= '9'):
  367. raise ServiceException({'result': 2, 'description': u'密码必须是6位纯数字密码'})
  368. return
  369. def set_card_pwd(self, pwd):
  370. self.check_pwd(pwd)
  371. enObj = EncryptDate(cardKey)
  372. devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  373. {'IMEI': self._device['devNo'], 'data': {'funCode':0x0B, 'card_pwd':enObj.encrypt(pwd)}})
  374. self.check_feedback_result(devInfo)
  375. def set_card_mode(self, setConf):
  376. cardMode = int(setConf.get('card_mode'))
  377. valueDict = {'funCode':0x10}
  378. if cardMode == 0:
  379. valueDict.update({'mode':cardMode})
  380. elif cardMode == 1: # 格式化为离线卡
  381. self.check_pwd(setConf['new_pwd'])
  382. newPwd = setConf['new_pwd']
  383. if not str(setConf['balance']).isdigit():
  384. raise ServiceException({'result': 2, 'description': u'余额必须是数字'})
  385. balance = int(setConf['balance'])
  386. if not (balance >= 0 and balance <= 5000):
  387. raise ServiceException({'result': 2, 'description': u'余额必须在0和5000元之间'})
  388. balance = balance * 10 # 硬件模块记录的单位是角
  389. enObj = EncryptDate(cardKey)
  390. valueDict.update({'mode':1, 'new_pwd':enObj.encrypt(str(newPwd)), 'balance':balance})
  391. elif cardMode == 2:
  392. self.check_pwd(setConf['old_pwd'])
  393. self.check_pwd(setConf['new_pwd'])
  394. newPwd = setConf['new_pwd']
  395. oldPwd = setConf['old_pwd']
  396. enObj = EncryptDate(cardKey)
  397. valueDict.update({'mode':2, 'old_pwd':enObj.encrypt(str(oldPwd)), 'new_pwd':enObj.encrypt(str(newPwd))})
  398. devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  399. {'IMEI': self._device['devNo'], 'data': valueDict})
  400. self.check_feedback_result(devInfo)
  401. def get_card_mode(self):
  402. devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  403. {'IMEI': self._device['devNo'], 'data': {'funCode': 0x11}})
  404. self.check_feedback_result(devInfo)
  405. cardMode = devInfo['data']['card_mode']
  406. return {'card_mode':cardMode}
  407. def check_alarm(self, alarm):
  408. if alarm.faultCode == FAULT_CODE.MCU_REBOOT:
  409. return u'此告警,建议您多观察,如果比较频繁不停上报单台设备的告警,可能会运行不稳定。需要您联系技术支持确认。'
  410. elif alarm.faultCode == FAULT_CODE.COUNTER_FAULT:
  411. portInfo = self.get_port_info(alarm.portNo)
  412. if portInfo['status'] == Const.DEV_WORK_STATUS_FAULT:
  413. return u'此端口目前已经为故障状态,继电器可能运行不稳定,建议您联系技术支持,以确认设备运行情况。'
  414. else:
  415. return u'端口状态检查正常,继电器或存偶尔无法获取数据。暂不影响使用。'
  416. elif alarm.faultCode == FAULT_CODE.RELAY_FAULT:
  417. return u'无法进行远程诊断,建议您到现场,直接插上插座,然后检查是否不用付款,就能够充电。如果是的,就属于继电器粘连。'
  418. elif alarm.faultCode == FAULT_CODE.DEV_OVERLOAD:
  419. return u'整机功率最大限定为7500瓦,接入的负载超过此负载,为了安全,将强行关闭所有充电端口。'
  420. elif alarm.faultCode == FAULT_CODE.COPY_CARD:
  421. return u'出现一模一样的卡,可能是用户复制了另外一张离线卡,然后使用,会给您造成经济上的损失,建议冻结。'
  422. return ''
  423. def recharge_card(self, cardNo, money, orderNo=None):
  424. hex_cardNo = hex(int(cardNo))[2::].replace('L', '').upper()
  425. result = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SERVER_ASYNC,
  426. {'IMEI': self.device['devNo'],
  427. 'data': {'funCode': 37, 'result': 1, 'card_no': hex_cardNo,
  428. 'charge': int(money * 100),
  429. 'orderNo': orderNo}})
  430. # 返回验证
  431. self.check_feedback_result(result)
  432. card = Card.objects.filter(cardNo=cardNo, dealerId=self.device.ownerId).first()
  433. balance = card.balance + money
  434. return {
  435. 'result': ErrorCode.SUCCESS,
  436. 'description': ''
  437. }, balance
  438. def get_device_function_by_key(self,keyName):
  439. if 'waterlevel' in keyName:
  440. data = {'funCode':0x01}
  441. devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  442. {'IMEI': self._device['devNo'], 'data': data}, timeout=MQTT_TIMEOUT.START_DEVICE)
  443. self.check_feedback_result(devInfo)
  444. devStatus = devInfo['data']['devStatus']
  445. desc = ''
  446. if devStatus.has_key('errors') and devStatus['errors']:
  447. descList = []
  448. for err in devStatus['errors']:
  449. descList.append(self.get_desc_from_code(err))
  450. desc = ';'.join(descList)
  451. return {
  452. "waterlevel": devStatus['waterlevel'],
  453. "watervalue":devStatus['watervalue'],
  454. "drain":devStatus['drain'],
  455. 'door':devStatus['door'],
  456. 'machine':devStatus['machine'],
  457. 'inject':devStatus['inject'],
  458. 'desc':desc,
  459. 'status':devInfo['data']['status']
  460. }
  461. return None