hongzhuo.py 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727
  1. # -*- coding: utf-8 -*-
  2. # !/usr/bin/env python
  3. import binascii
  4. import datetime
  5. import logging
  6. import time
  7. from django.core.cache import caches
  8. from apilib.utils_datetime import timestamp_to_dt, to_datetime
  9. from apps.web.constant import Const, DeviceCmdCode, MQTT_TIMEOUT
  10. from apps.web.core.adapter.base import SmartBox, fill_2_hexByte, reverse_hex
  11. from apps.web.core.exceptions import ServiceException
  12. from apps.web.core.networking import MessageSender
  13. from apps.web.device.models import Device
  14. from apps.web.user.models import MyUser, Card
  15. from bson import ObjectId
  16. logger = logging.getLogger(__name__)
  17. class ChargingHongZhuoBox(SmartBox):
  18. TYPE_MAP = {
  19. "01": "投币扫码启动",
  20. "02": "刷卡启动",
  21. "03": "远程启动",
  22. "04": "其他启动方式"
  23. }
  24. def __init__(self, device):
  25. super(ChargingHongZhuoBox, self).__init__(device)
  26. def change_4_data(self, data):
  27. return data[2:4] + data[0:2]
  28. def get_port_status_from_dev(self):
  29. devInfo = MessageSender.send(self.device, self.make_random_cmdcode(),
  30. {'IMEI': self._device['devNo'], "funCode": '0F', '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. data = devInfo['data'][12::]
  39. if data[0:2] == '01': # 表示成功
  40. pass
  41. else:
  42. raise ServiceException({'result': 2, 'description': u'获取统计数据失败,请重试看能否解决'})
  43. result = {}
  44. portNum = int(data[2:4], 16)
  45. portData = data[4::]
  46. ii = 0
  47. while ii < portNum:
  48. port = int(portData[ii * 4:ii * 4 + 2], 16)
  49. statusTemp = portData[ii * 4 + 2:ii * 4 + 4]
  50. if statusTemp == '01':
  51. status = {'status': Const.DEV_WORK_STATUS_IDLE}
  52. elif statusTemp == '02':
  53. status = {'status': Const.DEV_WORK_STATUS_WORKING}
  54. elif statusTemp == '03':
  55. status = {'status': Const.DEV_WORK_STATUS_FORBIDDEN}
  56. elif statusTemp == '04':
  57. status = {'status': Const.DEV_WORK_STATUS_FAULT}
  58. else:
  59. status = {'status': Const.DEV_WORK_STATUS_FAULT}
  60. ii += 1
  61. result[str(port)] = status
  62. allPorts, usedPorts, usePorts = self.get_port_static_info(result)
  63. Device.update_dev_control_cache(self._device['devNo'],
  64. {'allPorts': allPorts, 'usedPorts': usedPorts, 'usePorts': usePorts})
  65. # 这里存在多线程更新缓存的场景,可能性比较低,但是必须先取出来,然后逐个更新状态,然后再记录缓存
  66. ctrInfo = Device.get_dev_control_cache(self._device['devNo'])
  67. for strPort, info in result.items():
  68. if ctrInfo.has_key(strPort):
  69. ctrInfo[strPort].update({'status': info['status']})
  70. else:
  71. ctrInfo[strPort] = info
  72. Device.update_dev_control_cache(self._device['devNo'], ctrInfo)
  73. return result
  74. def get_port_status(self, force = False):
  75. if force:
  76. return self.get_port_status_from_dev()
  77. ctrInfo = Device.get_dev_control_cache(self._device['devNo'])
  78. statusDict = {}
  79. if not ctrInfo.has_key('allPorts'):
  80. self.get_port_status_from_dev()
  81. ctrInfo = Device.get_dev_control_cache(self._device['devNo'])
  82. allPorts = ctrInfo.get('allPorts', 10)
  83. for ii in range(allPorts):
  84. tempDict = ctrInfo.get(str(ii + 1), {})
  85. if tempDict.has_key('status'):
  86. statusDict[str(ii + 1)] = {'status': tempDict.get('status')}
  87. elif tempDict.has_key('isStart'):
  88. if tempDict['isStart']:
  89. statusDict[str(ii + 1)] = {'status': Const.DEV_WORK_STATUS_WORKING}
  90. else:
  91. statusDict[str(ii + 1)] = {'status': Const.DEV_WORK_STATUS_IDLE}
  92. else:
  93. statusDict[str(ii + 1)] = {'status': Const.DEV_WORK_STATUS_IDLE}
  94. allPorts, usedPorts, usePorts = self.get_port_static_info(statusDict)
  95. Device.update_dev_control_cache(self._device['devNo'],
  96. {'allPorts': allPorts, 'usedPorts': usedPorts, 'usePorts': usePorts})
  97. return statusDict
  98. def start_device(self, package, openId, attachParas):
  99. if attachParas is None:
  100. raise ServiceException({'result': 2, 'description': u'请您选择合适的充电线路、电池类型信息'})
  101. if not attachParas.has_key('chargeIndex'):
  102. raise ServiceException({'result': 2, 'description': u'请您选择合适的充电线路'})
  103. dev = Device.objects.get(devNo=self._device['devNo'])
  104. mode = dev.otherConf.get('workMode', 'time')
  105. if mode == 'time':
  106. mode = '00'
  107. else:
  108. mode = '01'
  109. price = float(package['price'])
  110. port = hex(int(attachParas['chargeIndex']))
  111. hexPort = fill_2_hexByte(port, 2)
  112. coins = int(package['coins'])
  113. hexCoins = fill_2_hexByte(hex(coins * 100)) # 注意单位是分
  114. needElec = coins
  115. hexElec = fill_2_hexByte(hex(needElec * 100))
  116. unit = package.get('unit', u'分钟')
  117. if unit in [u'分钟', u'小时', u'天']:
  118. billingType = 'time'
  119. needTime = int(package['time'])
  120. if unit == u'小时':
  121. needTime = int(package['time']) * 60
  122. elif unit == u'天':
  123. needTime = int(package['time']) * 1440
  124. hexTime = fill_2_hexByte(hex(needTime))
  125. elif unit == u'度' or mode == '02':
  126. billingType = 'elec'
  127. devConf = caches['devmgr'].get('settingConf_%s' % (self._device['devNo']))
  128. if devConf is None:
  129. conf = self.get_dev_setting()
  130. caches['devmgr'].set('settingConf_%s' % (self._device['devNo']), conf, 24 * 3600)
  131. elecFee = conf['elecFee']
  132. else:
  133. elecFee = devConf['elecFee']
  134. needElec = round((package['time']), 2)
  135. needElec = round(min(float(coins / elecFee), needElec), 2)
  136. hexElec = fill_2_hexByte(hex(int(needElec * 100)), 4)
  137. needTime = 12 * 60
  138. hexTime = fill_2_hexByte(hex(needTime))
  139. else:
  140. billingType = 'elec'
  141. devConf = caches['devmgr'].get('settingConf_%s' % (self._device['devNo']))
  142. if devConf is None:
  143. conf = self.get_dev_setting()
  144. caches['devmgr'].set('settingConf_%s' % (self._device['devNo']), conf, 24 * 3600)
  145. elecFee = conf['elecFee']
  146. else:
  147. elecFee = devConf['elecFee']
  148. needElec = round((package['time']), 2)
  149. needElec = round(min(float(coins / elecFee), needElec), 2)
  150. hexElec = fill_2_hexByte(hex(int(needElec * 100)), 4)
  151. needTime = 12 * 60
  152. hexTime = fill_2_hexByte(hex(needTime))
  153. hexCoins = self.change_4_data(hexCoins)
  154. hexTime = self.change_4_data(hexTime)
  155. hexElec = self.change_4_data(hexElec)
  156. devInfo = MessageSender.send(device = self.device, cmd = DeviceCmdCode.OPERATE_DEV_SYNC, payload = {
  157. 'IMEI': self._device['devNo'],
  158. "funCode": '14',
  159. 'data': mode + hexPort + hexCoins + hexTime + hexElec
  160. }, timeout = MQTT_TIMEOUT.START_DEVICE)
  161. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  162. if devInfo['rst'] == -1:
  163. raise ServiceException({'result': 2, 'description': u'充电桩正在玩命找网络,您的金币还在,重试不需要重新付款,建议您试试旁边其他设备,或者稍后再试哦'})
  164. elif devInfo['rst'] == 1:
  165. raise ServiceException({'result': 2, 'description': u'充电桩正在忙,无响应,您的金币还在,请试试其他线路,或者请稍后再试哦'})
  166. data = devInfo['data'][12::]
  167. if data[0:2] == '01': # 表示成功
  168. pass
  169. else:
  170. raise ServiceException({'result': 2, 'description': u'获取端口数据失败,请重试看能否解决'})
  171. usePort = int(attachParas['chargeIndex'])
  172. result = data[4:6]
  173. if result == '01': # 成功
  174. pass
  175. elif result == '0B':
  176. newValue = {str(usePort): {'status': Const.DEV_WORK_STATUS_FAULT, 'statusInfo': u'充电站故障'}}
  177. Device.update_dev_control_cache(self._device['devNo'], newValue)
  178. raise ServiceException({'result': 2, 'description': u'充电站故障'})
  179. elif result == '0C':
  180. newValue = {str(usePort): {'status': Const.DEV_WORK_STATUS_WORKING, 'statusInfo': u''}}
  181. Device.update_dev_control_cache(self._device['devNo'], newValue)
  182. raise ServiceException({'result': 2, 'description': u'该端口正在使用中'})
  183. start_timestamp = int(time.time())
  184. devInfo['finishedTime'] = start_timestamp + needTime * 60
  185. portDict = {
  186. 'startTime': timestamp_to_dt(start_timestamp).strftime('%Y-%m-%d %H:%M:%S'),
  187. 'status': Const.DEV_WORK_STATUS_WORKING,
  188. 'finishedTime': devInfo['finishedTime'],
  189. 'coins': float(coins),
  190. 'isStart': True,
  191. 'price': price,
  192. 'openId': openId,
  193. 'refunded': False,
  194. 'needTime': needTime,
  195. 'billingType': billingType,
  196. 'vCardId': self._vcard_id
  197. }
  198. if attachParas.has_key('orderNo'):
  199. portDict.update({'orderNo': attachParas['orderNo']})
  200. Device.update_dev_control_cache(self._device['devNo'], {str(usePort): portDict})
  201. return devInfo
  202. def get_port_info(self, line):
  203. # 20220225 新增版本
  204. data = fill_2_hexByte(hex(int(line)), 2)
  205. devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  206. {'IMEI': self._device['devNo'], "funCode": '15', 'data': data})
  207. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  208. if devInfo['rst'] == -1:
  209. raise ServiceException(
  210. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  211. elif devInfo['rst'] == 1:
  212. raise ServiceException(
  213. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  214. data = devInfo['data'][12::]
  215. if data[0:2] == '01': # 表示成功
  216. pass
  217. else:
  218. raise ServiceException({'result': 2, 'description': u'获取统计数据失败,请重试看能否解决'})
  219. mode = data[2:4]
  220. if mode == '01':
  221. usedTime = int(self.change_4_data(data[6:10]), 16)
  222. power = round(int(self.change_4_data(data[10:14]), 16) * 0.1 ,2)
  223. elec = str(round(int(self.change_4_data(data[14:18]), 16) * 0.01, 2))
  224. leftMoney = round(int(self.change_4_data(data[18:22]), 16) * 0.01, 2)
  225. STA = '0'
  226. elif mode == '02':
  227. usedTime = int(self.change_4_data(data[6:10]), 16)
  228. power = str(round(int(binascii.hexlify(binascii.unhexlify(data[10:18])[::-1]), 16) * 0.1,2))
  229. elec = str(round(int(self.change_4_data(data[18:22]), 16) * 0.01, 2))
  230. leftMoney = round(int(self.change_4_data(data[22:26]), 16) * 0.01, 2)
  231. STA = str(int(binascii.hexlify(binascii.unhexlify(data[26:28])[::-1]), 16))
  232. return {'port': line, 'usedTime': usedTime, 'power': power, 'usedElec': elec, 'leftMoney': leftMoney,'STA':STA}
  233. def active_deactive_port(self, port, active):
  234. if not active:
  235. self.stop_charging_port(port)
  236. devInfo = Device.get_dev_control_cache(self._device['devNo'])
  237. portCtrInfo = devInfo.get(str(port),{})
  238. portCtrInfo.update({'isStart':False,'status':Const.DEV_WORK_STATUS_IDLE,'endTime':datetime.datetime.now().strftime(Const.DATETIME_FMT)})
  239. newValue = {str(port):portCtrInfo}
  240. Device.update_dev_control_cache(self._device['devNo'], newValue)
  241. else:
  242. raise ServiceException({'result': 2, 'description': u'此设备不支持直接打开端口'})
  243. def stop(self, port = None):
  244. infoDict = self.stop_charging_port(port)
  245. infoDict['remainder_time'] = infoDict['leftTime']
  246. return infoDict
  247. def stop_charging_port(self, port):
  248. portStr = fill_2_hexByte(hex(int(port)), 2)
  249. devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  250. {'IMEI': self._device['devNo'], "funCode": '0D', 'data': portStr + '00'})
  251. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  252. if devInfo['rst'] == -1:
  253. raise ServiceException(
  254. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  255. elif devInfo['rst'] == 1:
  256. raise ServiceException(
  257. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  258. data = devInfo['data'][12::]
  259. if data[0:2] == '01': # 表示成功
  260. pass
  261. else:
  262. raise ServiceException({'result': 2, 'description': u'操作端口失败,请重试看能否解决'})
  263. port = int(data[4:6], 16)
  264. money = int(self.change_4_data(data[6:10]), 16)
  265. leftTime = int(self.change_4_data(data[10:14]), 16)
  266. elec = int(self.change_4_data(data[14:18]), 16)
  267. return {'port': port, 'money': money, 'leftTime': leftTime, 'elec': elec}
  268. def set_dev_setting(self,setConf):
  269. data = ''
  270. data += self.change_4_data(fill_2_hexByte(hex(int(setConf['coinTime'])), 4))
  271. data += self.change_4_data(fill_2_hexByte(hex(int(setConf['cardTime'])), 4))
  272. data += self.change_4_data(fill_2_hexByte(hex(int(setConf['elecFee'])), 4))
  273. data += self.change_4_data(fill_2_hexByte(hex(int(setConf['cardFee'])), 4))
  274. data += self.change_4_data(fill_2_hexByte(hex(int(setConf['level1Power'])), 4))
  275. data += self.change_4_data(fill_2_hexByte(hex(int(setConf['level2Power'])), 4))
  276. data += self.change_4_data(fill_2_hexByte(hex(int(setConf['level3Power'])), 4))
  277. data += self.change_4_data(fill_2_hexByte(hex(int(setConf['level4Power'])), 4))
  278. data += self.change_4_data(fill_2_hexByte(hex(int(setConf['level1Time'])), 4))
  279. data += self.change_4_data(fill_2_hexByte(hex(int(setConf['level2Time'])), 4))
  280. data += self.change_4_data(fill_2_hexByte(hex(int(setConf['level3Time'])), 4))
  281. data += self.change_4_data(fill_2_hexByte(hex(int(setConf['level4Time'])), 4))
  282. data += fill_2_hexByte(hex(int(setConf['refundMoney'])), 2)
  283. data += fill_2_hexByte(hex(int(setConf['fullPowerStop'])), 2)
  284. data += self.change_4_data(fill_2_hexByte(hex(int(setConf['minPowerDetection'])), 4))
  285. data += self.change_4_data(fill_2_hexByte(hex(int(setConf['fullDelayTime'])), 4))
  286. data += fill_2_hexByte(hex(int(setConf['boardDisplay'])), 2)
  287. devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  288. {'IMEI': self._device['devNo'], "funCode": '18', 'data': data})
  289. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  290. if devInfo['rst'] == -1:
  291. raise ServiceException(
  292. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  293. elif devInfo['rst'] == 1:
  294. raise ServiceException(
  295. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  296. data = devInfo['data'][12::]
  297. if data[0:2] == '01':#表示成功
  298. otherConf = self._device.get("otherConf", dict())
  299. otherConf.update(
  300. {
  301. "workMode": setConf['workMode'],
  302. "refundMoney": setConf['refundMoney']
  303. }
  304. )
  305. Device.objects.filter(devNo=self._device["devNo"]).update(otherConf=otherConf)
  306. Device.invalid_device_cache(self._device["devNo"])
  307. # dev = Device.objects.get(devNo=self._device['devNo'])
  308. # dev.otherConf.update({'workMode': setConf['workMode']})
  309. # dev.save()
  310. else:
  311. raise ServiceException({'result': 2, 'description': u'操作端口失败,请重试看能否解决'})
  312. def get_dev_setting(self):
  313. devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  314. {'IMEI': self._device['devNo'], "funCode": '1E', 'data': '00'})
  315. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  316. if devInfo['rst'] == -1:
  317. raise ServiceException(
  318. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  319. elif devInfo['rst'] == 1:
  320. raise ServiceException(
  321. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  322. data = devInfo['data'][12::]
  323. if data[0:2] == '01': # 表示成功
  324. pass
  325. else:
  326. raise ServiceException({'result': 2, 'description': u'操作端口失败,请重试看能否解决'})
  327. confData = data[2:-2]
  328. coinTime = int(self.change_4_data(confData[0:4]), 16)
  329. cardTime = int(self.change_4_data(confData[4:8]), 16)
  330. elecFee = int(self.change_4_data(confData[8:12]), 16)
  331. cardFee = int(self.change_4_data(confData[12:16]), 16)
  332. level1Power = int(self.change_4_data(confData[16:20]), 16)
  333. level2Power = int(self.change_4_data(confData[20:24]), 16)
  334. level3Power = int(self.change_4_data(confData[24:28]), 16)
  335. level4Power = int(self.change_4_data(confData[28:32]), 16)
  336. level1Time = int(self.change_4_data(confData[32:36]), 16)
  337. level2Time = int(self.change_4_data(confData[36:40]), 16)
  338. level3Time = int(self.change_4_data(confData[40:44]), 16)
  339. level4Time = int(self.change_4_data(confData[44:48]), 16)
  340. refundMoney = int(confData[48:50], 16)
  341. fullPowerStop = int(confData[50:52], 16)
  342. minPowerDetection = int(self.change_4_data(confData[52:56]), 16)
  343. fullDelayTime = int(self.change_4_data(confData[56:60]), 16)
  344. boardDisplay = int(confData[60:62], 16)
  345. dev = Device.objects.get(devNo=self._device['devNo'])
  346. workMode = dev.otherConf.get('workMode', 'time')
  347. data={
  348. 'coinTime': coinTime,
  349. 'cardTime': cardTime,
  350. 'elecFee': elecFee,
  351. 'cardFee': cardFee,
  352. 'level1Power': level1Power,
  353. 'level2Power': level2Power,
  354. 'level3Power': level3Power,
  355. 'level4Power': level4Power,
  356. 'level1Time': level1Time,
  357. 'level2Time': level2Time,
  358. 'level3Time': level3Time,
  359. 'level4Time': level4Time,
  360. 'refundMoney': refundMoney,
  361. 'fullPowerStop': fullPowerStop,
  362. 'minPowerDetection': minPowerDetection,
  363. 'fullDelayTime': fullDelayTime,
  364. 'boardDisplay': boardDisplay,
  365. 'workMode': workMode
  366. }
  367. try:
  368. elecNum = self.remote_meter_reading()
  369. data.update(elecNum)
  370. except:
  371. pass
  372. return data
  373. def set_device_function_param(self, request, lastSetConf):
  374. coinTime = request.POST.get('coinTime', None)
  375. cardTime = request.POST.get('cardTime', None)
  376. elecFee = request.POST.get('elecFee', None)
  377. cardFee = request.POST.get('cardFee', None)
  378. level1Power = request.POST.get('level1Power', None)
  379. level2Power = request.POST.get('level2Power', None)
  380. level3Power = request.POST.get('level3Power', None)
  381. level4Power = request.POST.get('level4Power', None)
  382. level1Time = request.POST.get('level1Time', None)
  383. level2Time = request.POST.get('level2Time', None)
  384. level3Time = request.POST.get('level3Time', None)
  385. level4Time = request.POST.get('level4Time', None)
  386. refundMoney = request.POST.get('refundMoney', None)
  387. fullPowerStop = request.POST.get('fullPowerStop', None)
  388. minPowerDetection = request.POST.get('minPowerDetection', None)
  389. fullDelayTime = request.POST.get('fullDelayTime', None)
  390. boardDisplay = request.POST.get('boardDisplay', None)
  391. workMode = request.POST.get('workMode', None)
  392. if coinTime:
  393. lastSetConf.update({'coinTime': int(coinTime)})
  394. if cardTime:
  395. lastSetConf.update({'cardTime': int(cardTime)})
  396. if elecFee:
  397. lastSetConf.update({'elecFee': int(elecFee)})
  398. if cardFee:
  399. lastSetConf.update({'cardFee': int(cardFee)})
  400. if level1Power:
  401. lastSetConf.update({'level1Power': int(level1Power)})
  402. if level2Power:
  403. lastSetConf.update({'level2Power': int(level2Power)})
  404. if level3Power:
  405. lastSetConf.update({'level3Power': int(level3Power)})
  406. if level4Power:
  407. lastSetConf.update({'level4Power': int(level4Power)})
  408. if level1Time:
  409. lastSetConf.update({'level1Time': int(level1Time)})
  410. if level2Time:
  411. lastSetConf.update({'level2Time': int(level2Time)})
  412. if level3Time:
  413. lastSetConf.update({'level3Time': int(level3Time)})
  414. if level4Time:
  415. lastSetConf.update({'level4Time': int(level4Time)})
  416. if refundMoney:
  417. lastSetConf.update({'refundMoney': int(refundMoney)})
  418. if fullPowerStop:
  419. lastSetConf.update({'fullPowerStop': int(fullPowerStop)})
  420. if minPowerDetection:
  421. lastSetConf.update({'minPowerDetection': int(minPowerDetection)})
  422. if fullDelayTime:
  423. lastSetConf.update({'fullDelayTime': int(fullDelayTime)})
  424. if boardDisplay:
  425. lastSetConf.update({'boardDisplay': int(boardDisplay)})
  426. if workMode:
  427. lastSetConf.update({'workMode': workMode})
  428. self.set_dev_setting(lastSetConf)
  429. def analyze_event_data(self, data):
  430. cmdCode = data[10:12]
  431. if cmdCode == '16':
  432. mode = int(data[14:16], 16)
  433. port = int(data[16:18], 16)
  434. reason = data[18:20]
  435. leftMoney = round(int(self.change_4_data(data[20:24]), 16) * 0.01, 2)
  436. duration = int(self.change_4_data(data[24:28]), 16)
  437. elec = round(int(self.change_4_data(data[28:32]), 16) * 0.01, 2)
  438. if reason == '00':
  439. desc = u'购买的充电时间用完了。'
  440. elif reason == '01':
  441. desc = u'可能是插头被拔掉,或者电瓶已经充满。系统判断为异常断电,由于电瓶车充电器种类繁多,可能存在误差。如有问题,请您及时联系商家协助解决问题并恢复充电。'
  442. elif reason == '02':
  443. desc = u'恭喜您!电池已经充满电!'
  444. elif reason == '03':
  445. desc = u'警告!您的电池超功率,已经停止充电,为了公共安全,不建议您在该充电桩充电!提醒您,为了安全大功率的电池不要放入楼道、室内等位置充电哦'
  446. elif reason == '04':
  447. desc = u'远程断电。'
  448. elif reason == '05':
  449. desc = u'设备或端口出现问题,为了安全起见,被迫停止工作。建议您根据已经充电的时间评估是否需要到现场换到其他端口充电。'
  450. else:
  451. desc = u'电池没有充满!原因未知。'
  452. return {
  453. 'status': Const.DEV_WORK_STATUS_IDLE,
  454. 'cmdCode': cmdCode,
  455. 'mode': mode,
  456. 'port': port,
  457. 'leftMoney': leftMoney,
  458. 'duration': duration,
  459. 'elec': elec,
  460. 'reason': desc
  461. }
  462. # ID卡刷卡指令上传
  463. elif cmdCode == "10":
  464. result = data[12: 14]
  465. if result != "01":
  466. logger.info("card event result is {}".format(result))
  467. return
  468. portStr = str(int(data[14: 16]))
  469. cardNo = str(int(reverse_hex(data[16: 24]), 16))
  470. preFee = int(data[24: 26], 16)
  471. oper = data[26: 28]
  472. return {
  473. "cardNo": cardNo,
  474. "preFee": preFee,
  475. "oper": oper,
  476. "cmdCode": cmdCode,
  477. "portStr": portStr
  478. }
  479. elif cmdCode == "20":
  480. mode = data[14: 16]
  481. portStr = str(int(data[16: 18], 16))
  482. money = str(int(reverse_hex(data[18: 22]), 16) / 100.0) # 单位是分
  483. chargeTime = str(int(reverse_hex(data[22: 26]), 16)) # 单位是分钟
  484. elec = str(int(reverse_hex(data[26: 30]), 16) / 100.0) # 单位是0.01kwh
  485. typeCode = data[30: 32]
  486. chargeType = self.TYPE_MAP.get(typeCode, "")
  487. return {
  488. "mode": mode,
  489. "portStr": portStr,
  490. "money": money,
  491. "chargeTime": chargeTime,
  492. "elec": elec,
  493. "chargeType": chargeType,
  494. "typeCode": typeCode,
  495. "cmdCode": cmdCode
  496. }
  497. else:
  498. logger.info("error cmd code! cmd is {}".format(cmdCode))
  499. def response_use_card(self, res, port, balance):
  500. resHex = fill_2_hexByte(hex(int(res)), 2)
  501. portHex = fill_2_hexByte(hex(int(port)), 2)
  502. balanceHex = fill_2_hexByte(hex(int(balance)), 4, reverse=True)
  503. data = resHex + portHex + balanceHex
  504. MessageSender.send(device = self.device, cmd = DeviceCmdCode.OPERATE_DEV_NO_RESPONSE, payload = {
  505. "IMEI": self._device["devNo"],
  506. "funCode": "10",
  507. "data": data
  508. })
  509. def get_device_function_by_key(self, keyName):
  510. devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  511. {'IMEI': self._device['devNo'], "funCode": '30', 'data': '00'})
  512. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  513. if devInfo['rst'] == -1:
  514. raise ServiceException(
  515. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  516. elif devInfo['rst'] == 1:
  517. raise ServiceException(
  518. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  519. devInfo1 = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  520. {'IMEI': self._device['devNo'], "funCode": '32', 'data': '00'})
  521. if devInfo1.has_key('rst') and devInfo['rst'] != 0:
  522. if devInfo1['rst'] == -1:
  523. raise ServiceException(
  524. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  525. elif devInfo1['rst'] == 1:
  526. raise ServiceException(
  527. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  528. data = devInfo['data'][12::]
  529. data1 = devInfo1['data'][12::]
  530. if data[0:2] == '01' and data1[0:2] == '01': # 表示成功
  531. pass
  532. else:
  533. raise ServiceException({'result': 2, 'description': u'操作端口失败,请重试看能否解决'})
  534. fileNameStr = data[2:10]
  535. fileName = chr(int(fileNameStr[0:2], 16)) + chr(int(fileNameStr[2:4], 16)) + chr(int(fileNameStr[4:6], 16)) + chr(int(fileNameStr[6:8], 16))
  536. boardVersion1 = int(data1[2:4])
  537. boardVersion2 = int(data1[4:6])
  538. boardVersion = str(boardVersion1) + '.' + str(boardVersion2)
  539. return {'fileName': fileName + '.bin' + '(当前主板版本为: v' + boardVersion + ')'}
  540. def set_device_function(self, request, lastSetConf):
  541. host_url = 'http://www.sdhongzhuo.com/down/bin_hz/'
  542. fileName = lastSetConf.get('fileName', '')
  543. if fileName == '':
  544. raise ServiceException({'result': 2, 'description': u'升级文件不存在, 请重新获取'})
  545. fileNameStr = fileName[0:fileName.find('(')]
  546. mcu_url = host_url + fileNameStr
  547. devInfo = MessageSender.send(self.device, DeviceCmdCode.SET_DEVINFO,
  548. {'IMEI': self._device['devNo'], 'mcu_set': {'mcu_url': mcu_url}})
  549. if devInfo.has_key('rst') and devInfo['rst'] != 0:
  550. if devInfo['rst'] == -1:
  551. raise ServiceException(
  552. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  553. elif devInfo['rst'] == 1:
  554. raise ServiceException(
  555. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  556. @property
  557. def isHaveStopEvent(self):
  558. return True
  559. # 20220225新增,获取时间34,远程抄表35
  560. def remote_meter_reading(self):
  561. devInfo = MessageSender.send(self.device, DeviceCmdCode.OPERATE_DEV_SYNC,
  562. {'IMEI': self._device['devNo'], "funCode": '35', 'data': '01'})
  563. if devInfo.has_key('rst') and devInfo['rst'] == -1:
  564. raise ServiceException(
  565. {'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  566. elif devInfo['rst'] == 1:
  567. raise ServiceException(
  568. {'result': 2, 'description': u'充电桩忙,无响应,请您稍候再试。也可能是您的设备版本过低,暂时不支持此功能'})
  569. elif devInfo['rst'] == 102:
  570. return {'elecNum' : None}
  571. data = devInfo['data'][12::]
  572. if data[0:2] == '01': # 表示成功
  573. pass
  574. else:
  575. raise ServiceException({'result': 2, 'description': u'获取统计数据失败,请重试看能否解决'})
  576. elec = float(int(binascii.hexlify(binascii.unhexlify(data[2:10])[::-1]), 16)) * 0.01
  577. return {'elecNum' : elec}
  578. def format_port_using_detail(self, detailDict):
  579. portData = {}
  580. usedTime = detailDict.get('usedTime',None)
  581. portData['usedTime'] = usedTime
  582. power = detailDict.get('power',None)
  583. portData['powerNow'] = power
  584. if detailDict.has_key('needTime'):
  585. detailDict.pop('needTime',None)
  586. if detailDict.has_key('openId'):
  587. user = MyUser.objects(openId=detailDict['openId'], groupId=self.device.groupId).first()
  588. if user:
  589. portData['nickName'] = user.nickname
  590. if detailDict.has_key('cardId'):
  591. if not detailDict.has_key('consumeType'):
  592. portData['consumeType'] = 'card'
  593. card = Card.objects.get(id=ObjectId(detailDict['cardId']))
  594. if card.cardName:
  595. portData['cardName'] = card.cardName
  596. portData['cardNo'] = card.cardNo
  597. # 注意,如果是IC卡,不支持余额回收,这里也不要显示出来
  598. if card.cardType == 'IC' and portData.has_key('leftMoney'):
  599. portData.pop('leftMoney')
  600. elif detailDict.has_key('openId') and (not detailDict.has_key('consumeType')):
  601. if detailDict.get('vCardId'):
  602. portData['consumeType'] = 'mobile_vcard'
  603. else:
  604. portData['consumeType'] = 'mobile'
  605. elif detailDict.has_key('consumeType') and detailDict['consumeType'] == 'coin':
  606. portData['consumeType'] = 'coin' # 硬币的都无法退费
  607. if portData.has_key('leftMoney'):
  608. portData.pop('leftMoney')
  609. detailDict.update(portData)
  610. for k, v in detailDict.items():
  611. if v < 0:
  612. detailDict.pop(k)
  613. # 因为前台显示的开始时间如果带年,就显示不下,这里做个切割
  614. if detailDict.has_key('startTime') and detailDict['startTime'].count('-') == 2:
  615. detailDict['startTime'] = to_datetime(detailDict['startTime']).strftime('%m-%d %H:%M:%S')
  616. return detailDict