changyuanCar.py 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645
  1. # -*- coding: utf-8 -*-
  2. # !/usr/bin/env python
  3. import datetime
  4. import logging
  5. import time
  6. from typing import TYPE_CHECKING
  7. from apilib.utils_datetime import timestamp_to_dt
  8. from apps.web.constant import DeviceCmdCode, Const, MQTT_TIMEOUT
  9. from apps.web.core.adapter.base import SmartBox, fill_2_hexByte
  10. from apps.web.core.device_define.changyuan import FunCode, CmdCode
  11. from apps.web.core.exceptions import ServiceException
  12. from apps.web.core.networking import MessageSender
  13. from apps.web.dealer.models import Dealer
  14. from apps.web.device.models import Device, Part
  15. from apps.web.user.models import Card, CardRechargeOrder, CardRechargeRecord, Group
  16. from apilib.monetary import RMB
  17. from bson import ObjectId
  18. if TYPE_CHECKING:
  19. pass
  20. logger = logging.getLogger(__name__)
  21. class MyHex(object):
  22. # 16进制字符串加法
  23. @staticmethod
  24. def __check_hex(hexNum):
  25. if not isinstance(hexNum, MyHex):
  26. raise TypeError("can not add")
  27. def __init__(self, hexNum):
  28. self.hexNum = hexNum
  29. def __add__(self, other):
  30. self.__check_hex(other)
  31. return hex(int(self.hexNum, 16) + int(other.hexNum, 16))
  32. class ChangYuanCarBox(SmartBox):
  33. # 发送函数
  34. def __sendData(self, funCode, data, timeout = MQTT_TIMEOUT.NORMAL):
  35. result = MessageSender.send(device = self.device, cmd = DeviceCmdCode.OPERATE_DEV_SYNC,
  36. payload = {"IMEI": self._device["devNo"], "funCode": funCode, "data": data},
  37. timeout = timeout)
  38. if result["rst"] != 0:
  39. if result['rst'] == -1:
  40. raise ServiceException({'result': 2, 'description': u'充电桩正在玩命找网络,请稍候再试'})
  41. elif result['rst'] == 1:
  42. raise ServiceException({'result': 2, 'description': u'充电桩主板连接故障'})
  43. else:
  44. raise ServiceException({'result': 2, 'description': u'系统错误'})
  45. return result
  46. def test(self, coins):
  47. coinsHex = fill_2_hexByte(hex(int(coins * 100)), 4)
  48. result = self.__sendData(FunCode.WEIXIN_PAY_START, "{}0000".format(coinsHex))
  49. data = result["data"]
  50. if data[8: 12] == "4552":
  51. raise ServiceException({'result': 2, 'description': u'设备相应错误,未能成功启动设备,请上报设备故障'})
  52. elif data[8: 12] == "4F4B":
  53. pass
  54. else:
  55. raise ServiceException({'result': 2, 'description': u'设备相应错误,未能成功启动设备,请上报设备故障'})
  56. return result
  57. def start_device(self, package, openId, attachParas):
  58. # 先从缓存检查,缓存如果状态不对再请求一次状态,缓存状态如果正确不需要请求。枪把的连接状态是会上报事件的
  59. devInfo = Device.get_dev_control_cache(self._device["devNo"])
  60. if "status" not in devInfo or devInfo["status"] != Const.DEV_WORK_STATUS_CONNECTED:
  61. status = self._check_dev_status()
  62. if status != "AC":
  63. raise ServiceException({'result': 2, 'description': u'请先将充电桩枪把连接'})
  64. # 获取套餐金额数,转换为分
  65. coins = package.get("coins")
  66. price = package.get("price")
  67. orderNo = attachParas.get("orderNo")
  68. priceData = fill_2_hexByte(hex(int(price * 100)), 4)
  69. result = self.__sendData(FunCode.WEIXIN_PAY_START, "{}0000".format(priceData), timeout=MQTT_TIMEOUT.START_DEVICE)
  70. data = result["data"]
  71. if data[8: 12] == "4552":
  72. raise ServiceException({'result': 2, 'description': u'设备相应错误,未能成功启动设备,请上报设备故障'})
  73. elif data[8: 12] == "4F4B":
  74. pass
  75. else:
  76. raise ServiceException({'result': 2, 'description': u'设备相应错误,未能成功启动设备,请上报设备故障'})
  77. rechargeRcdId = attachParas.get("linkedRechargeRecordId")
  78. start_timestamp = int(time.time())
  79. result['finishedTime'] = start_timestamp + 24 * 60 * 60
  80. devCache = {
  81. "openId": openId,
  82. "isStart": True,
  83. "coins": coins,
  84. "price": price,
  85. "rechargeRcdId": str(rechargeRcdId) if rechargeRcdId else None,
  86. "status": Const.DEV_WORK_STATUS_WORKING,
  87. "finishedTime": result['finishedTime'],
  88. "vCardId": self._vcard_id,
  89. "startTime": timestamp_to_dt(start_timestamp).strftime("%Y-%m-%d %H:%M:%S"),
  90. "orderNo": orderNo
  91. }
  92. Device.update_dev_control_cache(self._device["devNo"], devCache)
  93. # 非远程上分的情况下 需要将rechargeRcdId 写入到consumeRecord中
  94. if openId:
  95. result["rechargeRcdId"] = str(rechargeRcdId) if rechargeRcdId else None
  96. return result
  97. def analyze_event_data(self, data):
  98. cmdCode = data[4: 6]
  99. if cmdCode == CmdCode.STOP_DEV: # 设备停止事件
  100. reasonMap = {
  101. "E4": "充电已经正常结束",
  102. "E5": "充电已经被停止",
  103. "E6": "充电状态异常结束",
  104. "E7": "未知原因结束充电",
  105. }
  106. reasonCode = data[8: 10]
  107. # 去掉对于reasonCode的限制
  108. desc = reasonMap.get(reasonCode, reasonCode)
  109. cardNo = data[10: 18]
  110. electricNum = int(data[18: 22], 16) / 100.0
  111. chargeTime = int(data[22: 26], 16)
  112. balance = int(data[26: 30], 16) / 100.0
  113. cardBalance = int(data[30: 36], 16) / 100.0
  114. payMoney = int(data[38: 40] + data[36: 38], 16) / 100.0
  115. return {"cardNo": cardNo, "status": Const.DEV_WORK_STATUS_FINISHED,
  116. "electricNum": electricNum, "chargeTime": chargeTime,
  117. "balance": balance, "desc": desc, "reasonCode": reasonCode,
  118. "cmdCode": cmdCode, "cardBalance": cardBalance, "payMoney": payMoney
  119. }
  120. elif cmdCode == CmdCode.DEV_CONNECTED:
  121. status = data[8: 10]
  122. return {"status": status, "cmdCode": cmdCode}
  123. elif cmdCode == CmdCode.CARD_PAY_START:
  124. cardNo = data[8: 16]
  125. return {"cardNo": cardNo, "cmdCode": cmdCode}
  126. elif cmdCode == CmdCode.HEART_BEAT:
  127. # 昌原的经常把1代和2代的设备注册错误,2种汽车充电桩发送的B2长度不通 含义也截然不通 这个地方做一个保护 发现长度不对就直接扔掉
  128. if len(data) != 20:
  129. return
  130. leftBalanceStr = data[8: 12]
  131. leftBalance = int(leftBalanceStr, 16) / 100.0
  132. return {"leftBalance": leftBalance, "cmdCode": cmdCode}
  133. elif cmdCode == CmdCode.CARD_REFUND:
  134. cardNo = data[8:16]
  135. beforeRefund = int(data[16:22], 16) / 100.0 # 返费前 单位分
  136. refund = int(data[22:26], 16) / 100.0 # 返费额 单位分
  137. afterRefund = int(data[26:32], 16) / 100.0 # 返费后 单位分
  138. return {
  139. "cardNo": cardNo,
  140. "beforeRefund": beforeRefund,
  141. "refund": refund,
  142. "afterRefund": afterRefund,
  143. "cmdCode": cmdCode
  144. }
  145. # 真实发送检查设备状态函数 返回设备当前状态字节 更新设备状态缓存
  146. def _check_dev_status(self):
  147. # 在这个地方加入部件
  148. if not Part.objects.filter(logicalCode = self._device["logicalCode"]).count():
  149. Part(
  150. logicalCode = self._device["logicalCode"],
  151. ownerId = self._device["ownerId"],
  152. partName = u"充电端口",
  153. partType = "3",
  154. partNo = "1"
  155. ).save()
  156. result = self.__sendData(FunCode.CHECK_DEV_STATUS, "00")
  157. data = result["data"]
  158. status = data[8: 10]
  159. carNo = data[30: 38]
  160. if carNo == "00000000":
  161. carNo = u"在线支付"
  162. data = {
  163. "outputVoltage": int(data[10: 14], 16) / 1.0,
  164. "power": int(data[14: 18], 16) / 1.0,
  165. "elec": int(data[18: 22], 16) / 100.0,
  166. "usedTime": int(data[22: 26], 16),
  167. "leftMoney": int(data[26: 30], 16) / 100.0,
  168. "cardNo": carNo,
  169. }
  170. Device.update_dev_control_cache(self._device["devNo"], data)
  171. return status
  172. # 检查设备状态 供客户端调用
  173. def check_dev_status(self, attachParas = None):
  174. status = self._check_dev_status()
  175. if status == "AA":
  176. Device.update_dev_control_cache(self._device["devNo"], {"status": Const.DEV_WORK_STATUS_WORKING})
  177. raise ServiceException({'result': 2, 'description': u'当前充电桩正忙,不允许下发启动命令'})
  178. elif status == "AB":
  179. Device.update_dev_control_cache(self._device["devNo"], {"status": Const.DEV_WORK_STATUS_APPOINTMENT})
  180. raise ServiceException({'result': 2, 'description': u'当前充电桩已经被预约,不允许下发启动命令'})
  181. elif status == "AC": # 枪把连接OK
  182. Device.update_dev_control_cache(self._device["devNo"], {"status": Const.DEV_WORK_STATUS_CONNECTED})
  183. elif status == "55":
  184. Device.update_dev_control_cache(self._device["devNo"], {"status": Const.DEV_WORK_STATUS_IDLE})
  185. raise ServiceException({'result': 2, 'description': u'请先将充电桩枪把插上汽车充电口'})
  186. else:
  187. raise ServiceException({'result': 2, 'description': u'未知的充电桩状态,请你重新扫码'})
  188. # 真正停止设备函数,参数 传递主板 用于播放语音或者清除卡内余额
  189. def _stop(self, isLawful = True):
  190. # 是否需要清除离线卡卡内金额
  191. if isLawful:
  192. data = "00"
  193. else:
  194. data = "01"
  195. result = self.__sendData(FunCode.STOP_DEV, data)
  196. data = result["data"]
  197. if data[8:12] != "4F4B":
  198. raise ServiceException({'result': 2, 'description': u'结束充电失败,请重新操作'})
  199. return result
  200. # 远程停止设备 供客户端调用
  201. def stop(self, port = None):
  202. # 停止充电钱需要判断充电状态,处于充电状态的充电桩才才允许停电
  203. status = self._check_dev_status()
  204. if status != "AA":
  205. raise ServiceException({'result': 2, 'description': u'当前充电桩不在充电状态,无法远程终止充电'})
  206. return self._stop()
  207. @property
  208. def isHaveStopEvent(self):
  209. return True
  210. # 获取设备参数
  211. def get_dev_setting(self):
  212. result = self.__sendData(FunCode.GET_SETTING, "00")
  213. data = result["data"]
  214. isFree = data[8: 10]
  215. free = 0 if isFree == "00" else 1
  216. electricPrice = int(data[10: 12], 16) / 100.0
  217. maxConsume = int(data[12: 16], 16) / 100.0
  218. maxChargeTime = int(data[16: 20], 16)
  219. volume = int(data[20: 22], 16)
  220. resultDict = {
  221. "is_free": free,
  222. "electricPrice": electricPrice,
  223. "maxConsume": maxConsume,
  224. "maxChargeTime": maxChargeTime,
  225. "volume": volume
  226. }
  227. ctrDevInfo = self.getDevInfo()
  228. resultDict.update(ctrDevInfo)
  229. resultDict.update({
  230. "disableButton": int(self._device.get("otherConf", {}).get("disableDevice", False)),
  231. "needBindCard": int(self._device.get("otherConf", dict()).get("needBindCard", True))
  232. })
  233. return resultDict
  234. # 设置设备参数 内部调用
  235. def set_dev_setting(self, setConf):
  236. isFree = "AA" if int(setConf.get("is_free", 0)) else "00"
  237. electricPrice = int(float(setConf["electricPrice"]) * 100)
  238. maxConsume = int(float(setConf["maxConsume"]) * 100)
  239. maxChargeTime = int(float(setConf["maxChargeTime"]))
  240. volume = int(float(setConf["volume"]))
  241. data = list()
  242. data.append(isFree)
  243. data.append(fill_2_hexByte(hex(electricPrice), 2))
  244. data.append(fill_2_hexByte(hex(maxConsume), 4))
  245. data.append(fill_2_hexByte(hex(maxChargeTime), 4))
  246. data.append(fill_2_hexByte(hex(volume), 2))
  247. data = "".join(data)
  248. result = self.__sendData(FunCode.SET_SETTING, data)
  249. data = result["data"]
  250. if data[8: 12] != "4F4B":
  251. raise ServiceException({'result': 2, 'description': u'设备参数设置失败,请重试看能否解决'})
  252. otherConf = Device.get_dev(self._device["devNo"]).get("otherConf", dict())
  253. otherConf.update({"elecPrice": electricPrice / 100.0})
  254. Device.objects.filter(devNo = self._device["devNo"]).update(otherConf = otherConf)
  255. Device.invalid_device_cache(self._device["devNo"])
  256. # 充值离线卡 比较特殊,公共函数对其有修改 传递参数从 value 变为 充值记录Obj
  257. def remote_charge_card(self, price, recharge_record = None):
  258. # recharge_record.devNo = self._device["devNo"]
  259. # recharge_record.logicalCode = self._device["logicalCode"]
  260. # recharge_record.devType = self._device["devType"]["name"]
  261. # try:
  262. # recharge_record.save()
  263. # except Exception as e:
  264. # logger.error("recharge record device info error , the error is %s" % e)
  265. value = recharge_record.money
  266. value = int(float(value) * 100)
  267. value = fill_2_hexByte(hex(value), 4)
  268. openId = recharge_record.openId
  269. group = Group.get_group(recharge_record.groupId)
  270. # 下发充值 这个地方不使用sendData函数,方便知道下发数据的成功或者失败的消息
  271. result = MessageSender.send(device = self.device, cmd = DeviceCmdCode.OPERATE_DEV_SYNC, payload = {
  272. "IMEI": self._device["devNo"],
  273. "funCode": FunCode.CARD_RECHARGR,
  274. "data": value
  275. }, timeout = MQTT_TIMEOUT.LONGEST)
  276. # 汽车桩卡充值失败之后不现金退款了
  277. # TODO zjl 这个地方考虑将 在模块驱动层面 receive 这条指令之后 上抛一个失败的时间 从而直接在event里面处理退款事件 维持流程的统一性
  278. if result.get("rst") != 0 or result.get("data") == "5050AC02455201E50D0A":
  279. needRefund = True
  280. # 充值成功之后
  281. data = result.get("data")
  282. cardNo = data[8: 16]
  283. leftBalance = int(data[16: 22], 16) / 100.0 # 充值后余额
  284. rightBalance = int(data[22: 28], 16) / 100.0 # 充值前余额
  285. logger.info("remote charge card, cardNo is %s, afterBalance is %s, beforeBalance is %s" % (
  286. cardNo, leftBalance, rightBalance))
  287. # 此类充值, 充值的时候没有对于卡号的记录,需要手动更新卡信息
  288. card = Card.objects(cardNo = cardNo, cardType = "IC", dealerId = self._device["ownerId"])
  289. try:
  290. if card.count() == 0:
  291. # 绑定新卡
  292. card = Card(
  293. cardNo = cardNo,
  294. cardType = "IC",
  295. dealerId = self._device["ownerId"],
  296. balance = RMB(leftBalance),
  297. devNo = self._device["devNo"],
  298. lastMaxBalance = RMB(leftBalance - rightBalance)
  299. ).save()
  300. logger.info("new remote charge card %s" % RMB(leftBalance))
  301. else:
  302. card = card[0]
  303. card.balance = RMB(leftBalance)
  304. logger.info("remote charge card %s" % RMB(leftBalance))
  305. card.lastMaxBalance = RMB(leftBalance - rightBalance)
  306. card.save()
  307. except Exception as e:
  308. logger.error("card info update error %s" % e)
  309. else:
  310. cardId = str(card.id)
  311. # 记录卡充值订单
  312. newOrder = CardRechargeOrder.new_one(openId,
  313. cardId,
  314. cardNo,
  315. recharge_record.money,
  316. recharge_record.coins,
  317. group,
  318. recharge_record.id)
  319. # 记录卡充值记录
  320. newRcd = CardRechargeRecord(
  321. cardId = cardId,
  322. cardNo = cardNo,
  323. openId = openId,
  324. ownerId = ObjectId(self._device['ownerId']),
  325. money = recharge_record.money,
  326. coins = recharge_record.coins,
  327. balance = RMB(leftBalance),
  328. preBalance = RMB(rightBalance),
  329. devNo = self._device['devNo'],
  330. devTypeCode = self._device['devType']['code'],
  331. logicalCode = self._device['logicalCode'],
  332. groupId = self._device['groupId'],
  333. address = group['address'],
  334. groupNumber = self._device['groupNumber'],
  335. groupName = group['groupName'],
  336. status = 'success',
  337. rechargeType = 'netpay'
  338. )
  339. try:
  340. newOrder.save()
  341. newRcd.save()
  342. except Exception as e:
  343. logger.error("save card recharge card error, reason is %s" % e)
  344. return False
  345. # 设置设备故障
  346. def set_dev_disable(self, disable):
  347. if disable:
  348. status = "E9"
  349. else:
  350. status = "E8"
  351. result = self.__sendData(FunCode.START_OR_STOP, status)
  352. data = result["data"]
  353. if data[8: 12] != "4F4B":
  354. raise ServiceException({'result': 2, 'description': u'设置失败,请重试'})
  355. otherConf = self._device.get("otherConf", {})
  356. otherConf["disableDevice"] = disable
  357. Device.objects.filter(devNo = self._device["devNo"]).update(otherConf = otherConf)
  358. Device.invalid_device_cache(self._device["devNo"])
  359. # 暂时未使用
  360. def restart(self):
  361. self.__sendData(FunCode.RESTART, "00")
  362. # 暂时未使用
  363. def get_card_balance(self):
  364. result = self.__sendData(FunCode.CARD_BALANCE, "00")
  365. data = result["data"]
  366. if data[6: 8] == "02" and data[8: 12] == "4552":
  367. raise ServiceException({'result': 2, 'description': u'读取失败,请将卡放置在设备指定区域'})
  368. cardNo = int(data[8:16], 16)
  369. balance = int(data[16: 22], 16) / 100.0
  370. return cardNo, balance
  371. # 获取设备端的信息,主要是累计使用量、累计总金额,刷卡总额(刷卡总额是计算出来的,等于总-微信支付的)
  372. def getDevInfo(self):
  373. result = self.__sendData(FunCode.GET_DEV_INFO, "00")
  374. data = result["data"]
  375. amount = data[8: 14]
  376. electricNum = data[14: 20]
  377. if amount == "FFF" or electricNum == "FFF":
  378. # TODO zjl 需不需要上报事件告知这个溢出情况
  379. pass
  380. trans = lambda x: (int(x, 16) / 100.0)
  381. amount = trans(amount)
  382. electricNum = trans(electricNum)
  383. return {
  384. "totalConsume": amount,
  385. "totalElec": electricNum
  386. }
  387. # 清除设备端的累计信息
  388. def cleanDevInfo(self, amount = False, electricNum = False):
  389. if not amount and not electricNum:
  390. return
  391. elif amount and not electricNum:
  392. data = "E1"
  393. elif electricNum and not amount:
  394. data = "E2"
  395. else:
  396. data = "E3"
  397. self.__sendData(FunCode.CLEAN_DEV_INFO, data)
  398. timeDict = dict()
  399. if amount:
  400. timeDict["amountCleanTime"] = datetime.datetime.strftime(datetime.datetime.now(), "%Y-%m-%d %H:%M:%S")
  401. if electricNum:
  402. timeDict["electricNumCleanTime"] = datetime.datetime.strftime(datetime.datetime.now(), "%Y-%m-%d %H:%M:%S")
  403. Device.update_dev_control_cache(self._device["devNo"], timeDict)
  404. # 获取10条未返费的记录 暂时未使用
  405. def no_refund_record(self):
  406. result = self.__sendData(FunCode.REFUND_RECORD, "00")
  407. data = result["data"]
  408. noRefund = list()
  409. data = data[8: -8]
  410. for i in xrange(10):
  411. tempData = data[12 * i: 12 * (i + 1)]
  412. cardNo = tempData[: 8]
  413. amount = tempData[8: 12]
  414. if cardNo == "FFFFFFFF" or cardNo == "00000000": continue
  415. amount = int(amount, 16) / 100.0
  416. noRefund.append({"cardNo": cardNo, "amount": amount})
  417. return noRefund
  418. # 获取最近的几条充电记录 暂时未使用
  419. def get_charge_record(self, num):
  420. num = min(num, 30)
  421. baseHex = MyHex("80")
  422. numHex = MyHex(fill_2_hexByte(hex(num), 2))
  423. data = fill_2_hexByte((baseHex + numHex), 2)
  424. result = self.__sendData(FunCode.CHARGE_RECORD, data)
  425. data = result["data"]
  426. dataLen = int(data[6: 8], 16) * 2 - 2 # 数据字符数量
  427. recordData = data[10: 10 + dataLen]
  428. recordList = list()
  429. while recordData:
  430. cardNo = recordData[: 8]
  431. electricNum = int(recordData[8: 12], 16) / 100.0
  432. chargeTime = int(recordData[12: 16], 16)
  433. chargeBalance = int(recordData[16: 20], 16) / 100.0
  434. cardBalance = int(recordData[20: 26], 16) / 100.0
  435. recordData = recordData[26:]
  436. if cardNo == "FFFFFFFF":
  437. continue
  438. recordList.append(
  439. {
  440. "type": u"{} 刷卡充电".format(cardNo) if cardNo != "00000000" else u"扫码充电",
  441. "elec": u"{} 度".format(electricNum),
  442. "duration": u"{} 分钟".format(chargeTime),
  443. "chargeBalance": u"{} 元".format(chargeBalance),
  444. "cardBalance": u"{} 元".format(cardBalance) if cardBalance else u"本次无刷卡消费"
  445. }
  446. )
  447. return recordList
  448. # 功能设置 对接view
  449. def set_device_function(self, request, lastSetConf):
  450. remoteStop = request.POST.get("remoteStop", None)
  451. clearTotalConsume = request.POST.get("clearTotalConsume", False)
  452. clearTotalElec = request.POST.get("clearTotalElec", False)
  453. # 停止设备
  454. if remoteStop:
  455. return self.stop()
  456. # 清除设备计费信息
  457. if any([clearTotalConsume, clearTotalElec]):
  458. self.cleanDevInfo(clearTotalConsume, clearTotalElec)
  459. # 功能参数设置 对接view
  460. def set_device_function_param(self, request, lastSetConf):
  461. disable = request.POST.get("disableButton")
  462. if disable is not None:
  463. dealer = Dealer.objects.filter(id = self._device["ownerId"]).first()
  464. if "dealerDisableDevice" not in dealer.features:
  465. raise ServiceException({"result": 2, "description": "抱歉,您无此操作权限,请联系厂家获取权限"})
  466. return self.set_dev_disable(bool(int(disable)))
  467. if "needBindCard" in request.POST:
  468. needBindCard = bool(int(request.POST.get('needBindCard')))
  469. otherConf = self.device.get("otherConf", dict())
  470. otherConf.update({"needBindCard": needBindCard})
  471. Device.objects.get(devNo=self.device.devNo).update(otherConf=otherConf)
  472. Device.invalid_device_cache(self.device.devNo)
  473. return
  474. newDict = {
  475. "is_free": request.POST.get("is_free", None),
  476. "electricPrice": request.POST.get("electricPrice", None),
  477. "maxConsume": request.POST.get("maxConsume", None),
  478. "maxChargeTime": request.POST.get("maxChargeTime", None),
  479. "volume": request.POST.get("volume", None)
  480. }
  481. resultDict = self.get_dev_setting()
  482. for k, v in newDict.items():
  483. if v is not None:
  484. resultDict.update({k: v})
  485. self.set_dev_setting(resultDict)
  486. def get_device_function_by_key(self, key):
  487. if key == "noRefund":
  488. rcd = self.no_refund_record()
  489. return {"noRefund": rcd}
  490. elif key == "record":
  491. rcd = self.get_charge_record(15)
  492. return {"record": rcd}
  493. def get_port_info(self, port):
  494. result = self.__sendData(FunCode.CHECK_DEV_STATUS, "00")
  495. data = result["data"]
  496. carNo = data[30: 38]
  497. if carNo == "00000000":
  498. carNo = u"在线支付"
  499. devCache = Device.get_dev_control_cache(self.device.devNo)
  500. if data[8: 10] == "55":
  501. status = Const.DEV_WORK_STATUS_IDLE
  502. elif data[8: 10] == "AC":
  503. status = Const.DEV_WORK_STATUS_CONNECTED
  504. else:
  505. status = Const.DEV_WORK_STATUS_WORKING
  506. data = {
  507. "status": status,
  508. "outputVoltage": str(int(data[10: 14], 16) / 1.0),
  509. "power": str(int(data[14: 18], 16) / 1.0),
  510. "elec": str(int(data[18: 22], 16) / 100.0),
  511. "usedTime": str(int(data[22: 26], 16)),
  512. "leftMoney": str(int(data[26: 30], 16) / 100.0),
  513. "cardNo": carNo,
  514. }
  515. devCache.update(data)
  516. return devCache
  517. def dealer_get_port_status(self):
  518. devInfo = self.get_port_info(1)
  519. if devInfo["status"] != Const.DEV_WORK_STATUS_WORKING:
  520. devInfo = {"status": devInfo["status"]}
  521. return {"1": devInfo}
  522. def active_deactive_port(self, port, active):
  523. if not active:
  524. self._stop()
  525. else:
  526. super(ChangYuanCarBox, self).active_deactive_port(port, active)