ywt_chongdiangui.py 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582
  1. # -*- coding: utf-8 -*-
  2. # !/usr/bin/env python
  3. import logging
  4. import sys
  5. import time
  6. import datetime
  7. from apilib.monetary import RMB, VirtualCoin
  8. from apps.web.device.models import DevicePortReport, Device, Group
  9. from apps.web.south_intf.platform import notify_event_to_north_v2
  10. from apps.web.user.models import ServiceProgress, MonthlyPackage, CardRechargeOrder, ConsumeRecord, CardConsumeRecord, \
  11. MyUser
  12. from apps.common.utils import int_to_hex
  13. from apps.web.eventer import EventBuilder
  14. from apps.web.core.device_define.ywt_chongdiangui import DefaultParams, Calculater
  15. from apps.web.constant import DeviceCmdCode, Const, DEALER_CONSUMPTION_AGG_KIND
  16. from apps.web.eventer.base import FaultEvent, WorkEvent
  17. logger = logging.getLogger(__name__)
  18. class builder(EventBuilder):
  19. def __getEvent__(self, device_event):
  20. event_data = self.deviceAdapter.analyze_event_data(device_event['data'])
  21. if event_data is None or 'cmdCode' not in event_data:
  22. return None
  23. # 粤万通的版本比较复杂 没有一个统一的版本 这次力争升级到一个统一的版本
  24. # TODO 补丁
  25. if "ack_id" in device_event and self.device.driverVersion not in [
  26. "v1.0.0", "v1.0.1", "v1.0.2", "v3.0.1", "v3.0.2", "v3.0.3", "v4.0.0", "v4.0.1"
  27. ]:
  28. self.deviceAdapter._ack(device_event["ack_id"])
  29. cmdCode = event_data.get("cmdCode", "")
  30. className = "ChargeCabinetEvent{}".format(cmdCode.capitalize())
  31. myClass = getattr(sys.modules[__name__], className, None)
  32. if myClass:
  33. return myClass(self.deviceAdapter, event_data)
  34. # 工具类
  35. class ChargeCabinetEventBase(object):
  36. @property
  37. def device_adapter(self):
  38. return getattr(self, 'deviceAdapter')
  39. @staticmethod
  40. def reverse_hex(s):
  41. if len(s) == 0:
  42. return ""
  43. return s[-2:] + ChargeCabinetEventBase.reverse_hex(s[:-2])
  44. def is_start_by_card(self, port):
  45. devCache = Device.get_dev_control_cache(self.device_adapter.device.devNo)
  46. return "cardNo" in devCache.get(port, dict())
  47. def response_card_start(self, _type, portStrHex, cardNoHex, balance = 0, orderNo = "0", chargeTime = 0, pw = 0,
  48. cardType = 0, leftDays = 0):
  49. balance = ChargeCabinetEventBase.reverse_hex("{:0>8X}".format(int(balance * 100) & 0xFFFFFFFF))
  50. cardType = ChargeCabinetEventBase.reverse_hex("{:0>2X}".format(int(cardType)))
  51. leftDays = ChargeCabinetEventBase.reverse_hex("{:0>4X}".format(int(leftDays)))
  52. orderNo = ChargeCabinetEventBase.reverse_hex("{:0>14X}".format(int(orderNo)))
  53. chargeTime = ChargeCabinetEventBase.reverse_hex("{:0>4X}".format(int(chargeTime)))
  54. pw = ChargeCabinetEventBase.reverse_hex("{:0>4X}".format(int(pw)))
  55. sendData = cardNoHex + portStrHex + _type + balance + cardType + leftDays + orderNo + chargeTime + pw
  56. self.device_adapter._send_data(funCode="B0", sendData=sendData, cmd=DeviceCmdCode.OPERATE_DEV_NO_RESPONSE)
  57. def response_finish(self, orderNoHex, portStr):
  58. portStrHex = int_to_hex(portStr, lens=2)
  59. sendData = orderNoHex + portStrHex + "01"
  60. self.device_adapter._send_data("C1", sendData, cmd=DeviceCmdCode.OPERATE_DEV_NO_RESPONSE)
  61. def start_device(self, port, orderNo, pw, operate):
  62. return self.device_adapter._start(port, orderNo, pw, operate)
  63. def response_fault(self, port):
  64. portStrHex = "{:02X}".format(port)
  65. sendData = portStrHex + "01"
  66. self.device_adapter._send_data("E0", sendData, cmd = DeviceCmdCode.OPERATE_DEV_NO_RESPONSE)
  67. def response_card_finish(self, cardNoHex, portStrHex, balance, consumeMoney, cardType = 1, leftDays = 0,
  68. cardStatus = "01"):
  69. balanceHex = ChargeCabinetEventBase.reverse_hex("{:0>8X}".format(int(balance * 100)))
  70. consumeMoneyHex = ChargeCabinetEventBase.reverse_hex("{:0>8X}".format(int(consumeMoney * 100)))
  71. cardTypeHex = ChargeCabinetEventBase.reverse_hex("{:0>2X}".format(int(cardType)))
  72. leftDaysHex = ChargeCabinetEventBase.reverse_hex("{:0>4X}".format(int(leftDays)))
  73. sendData = cardNoHex + portStrHex + cardStatus + balanceHex + cardTypeHex + leftDaysHex + consumeMoneyHex
  74. self.device_adapter._send_data("B1", sendData, cmd = DeviceCmdCode.OPERATE_DEV_NO_RESPONSE)
  75. def deduct_for_card(self, portStr, card, money, consumeOrder, cardConsumeOrder):
  76. devCache = Device.get_dev_control_cache(self.device_adapter.device.devNo)
  77. portCache = devCache.get(portStr)
  78. monthlyPackageId = portCache.get("monthlyPackageId")
  79. if monthlyPackageId:
  80. monthlyPackage = MonthlyPackage.objects.get(id = monthlyPackageId)
  81. monthlyPackage.deduct(consumeOrder)
  82. else:
  83. cardBalance = card.balance - RMB(money)
  84. card.balance = cardBalance
  85. card.save()
  86. # 更新
  87. consumeOrder.update(money = RMB(money).mongo_amount, coin = VirtualCoin(money).mongo_amount, status = "finished")
  88. cardConsumeOrder.update(money = RMB(money).mongo_amount, coin = VirtualCoin(money).mongo_amount)
  89. # 故障
  90. class ChargeCabinetEventE0(FaultEvent, ChargeCabinetEventBase):
  91. def do(self, **args):
  92. group = Group.get_group(self.device["groupId"])
  93. if self.is_notify_dealer():
  94. self.notify_dealer(
  95. "device_fault",
  96. title=u"注意注意您的设备发生故障",
  97. device=u"组号:{},二维码编号:{}".format(self.device["groupNumber"], self.device["logicalCode"]),
  98. location=u"组名称:{},地址:{}".format(group["groupName"], group["address"]),
  99. fault=self.event_data["statusInfo"],
  100. notifyTime=str(datetime.datetime.now())[:19]
  101. )
  102. warningData = {
  103. "warningStatus": 2,
  104. "warningDesc": self.event_data["statusInfo"],
  105. "warningTime": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
  106. }
  107. # 整机告警
  108. part = self.event_data.get("portStr", "0")
  109. Device.update_dev_warning_cache(self.device.devNo, {part: warningData})
  110. try:
  111. faultRecord = self.record(faultCode=self.event_data.get("faultCode", ""), detail={"errorCode": self.event_data["faultCode"]})
  112. self.north_to_liangxi(faultRecord)
  113. except Exception as e:
  114. logger.error(e)
  115. finally:
  116. sendData = self.event_data.get("portHex") + "01"
  117. self.deviceAdapter._send_data("E0", sendData = sendData, cmd = DeviceCmdCode.OPERATE_DEV_NO_RESPONSE)
  118. # 时间同步
  119. class ChargeCabinetEventA1(WorkEvent, ChargeCabinetEventBase):
  120. def do(self, **args):
  121. logger.info("charge cabinet <{}> request to synchronization time".format(self.device.devNo))
  122. self.deviceAdapter._sync_device_time()
  123. # 参数设置同步
  124. class ChargeCabinetEventA2(WorkEvent, ChargeCabinetEventBase):
  125. def do(self, **args):
  126. logger.info("charge cabinet <{}> request to device params".format(self.device.devNo))
  127. self.deviceAdapter._sync_device_settings()
  128. # 刷卡上报
  129. class ChargeCabinetEventB0(WorkEvent, ChargeCabinetEventBase):
  130. def do(self, **args):
  131. """
  132. 两个问题 刷卡的时候主板会判断当前端口是否已经被占用
  133. :param args:
  134. :return:
  135. """
  136. logger.info("charge cabinet <{}> send a card <{}> start signal ".format(self.device.devNo,self.event_data.get("cardNo")))
  137. cardNo = self.event_data.get("cardNo")
  138. portStr = self.event_data.get("portStr")
  139. portStrHex = self.event_data['portHex']
  140. cardNoHex = self.event_data['cardNoHex']
  141. card = self.update_card_dealer_and_type(cardNo)
  142. if not card or not card.openId or card.frozen:
  143. self.response_card_start(_type="03", portStrHex=portStrHex, cardNoHex=cardNoHex)
  144. logger.info("bad card, cardNo is %s, cannot start port!" % cardNo)
  145. return
  146. # 充值未到账的卡的处理 有些卡充值在没有上报类型之前 充值结果不会到账的 这个地方需要处理一下
  147. card_recharge_order = CardRechargeOrder.get_last_to_do_one(str(card.id))
  148. self.recharge_id_card(card=card, rechargeType='append', order=card_recharge_order)
  149. card.reload()
  150. # 能够刷卡的最低的金额
  151. monthlyPackage = card.monthlyPackage
  152. if monthlyPackage:
  153. cardType = 2
  154. leftDays = (monthlyPackage.expireDateTime - datetime.datetime.now()).days
  155. else:
  156. # 能够刷卡的最低的金额
  157. minCardMoney = self.device.get("otherConf", dict()).get("minAfterStartCoins",
  158. DefaultParams.DEFAULT_MIN_START_COINS)
  159. if float(card.balance) < float(minCardMoney):
  160. self.response_card_start(_type = "02", portStrHex = portStrHex, cardNoHex = cardNoHex,
  161. balance = card.balance)
  162. logger.info("negative card, card No is %s, card balance is %s" % (cardNo, card.balance))
  163. return
  164. cardType = 1
  165. leftDays = 0
  166. # 制造启动前的各种参数 密码 时间等等
  167. chargeTime = 0xFFFF
  168. pw = self.deviceAdapter.password
  169. otherConf = self.device.get("otherConf")
  170. servicedInfo = {"pw": pw, "chargeType": otherConf.get("chargeType", DefaultParams.DEFAULT_CHARGE_TYPE)}
  171. orderNo, cardConsumeOrderNo = self.record_consume_for_card(
  172. card=card,
  173. money=RMB(0),
  174. servicedInfo=servicedInfo,
  175. attachParas={"pw": pw}
  176. )
  177. # 返回刷卡 OK 的信息
  178. self.response_card_start(
  179. "01",
  180. portStrHex,
  181. cardNoHex=cardNoHex,
  182. balance=card.balance,
  183. orderNo=orderNo,
  184. chargeTime=chargeTime,
  185. pw=pw,
  186. cardType=cardType,
  187. leftDays=leftDays
  188. )
  189. logger.info("card start ok! event has been report!")
  190. # 主动下发指令B2-02 ,开启柜门开启充电启动设备
  191. self.start_device(portStr, orderNo, pw, "02")
  192. # 启动设备之后,注册服务,并更新端口缓存值
  193. ServiceProgress.register_card_service(
  194. self.device,
  195. int(portStr),
  196. card,
  197. {
  198. "orderNo": orderNo,
  199. "cardOrderNo": cardConsumeOrderNo
  200. },
  201. finishedTime = int(time.time()) + 7 * 24 * 60 * 60
  202. )
  203. portDict = {
  204. "status": Const.DEV_WORK_STATUS_WORKING,
  205. "isStart": True,
  206. "orderNo": orderNo,
  207. "cardOrderNo": cardConsumeOrderNo,
  208. "cardNo": cardNo,
  209. "openId": card.openId,
  210. "startTime": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
  211. "pw": pw,
  212. "monthlyPackageId": None if cardType == 1 else str(monthlyPackage.id)
  213. }
  214. Device.update_dev_control_cache(self.device["devNo"], {portStr: portDict})
  215. # 通知用户已经启动了
  216. self.notify_user(
  217. managerialOpenId = card.managerialOpenId,
  218. templateName = "consume_notify",
  219. title = u"您正在刷卡启动充电柜业务",
  220. money = u"使用结束后计算费用",
  221. serviceType = u"刷卡消费, 当前启动为: {}柜门".format(portStr),
  222. finishTime = datetime.datetime.now().strftime(Const.DATETIME_FMT)
  223. )
  224. # 刷卡结束上报
  225. class ChargeCabinetEventB1(WorkEvent, ChargeCabinetEventBase):
  226. def do(self): # zjl 去掉参数
  227. """
  228. 刷卡结束的时候, 仅仅会接受到刷卡上报的信息 和主板商沟通过不会再有充电结束的上报
  229. :return:
  230. """
  231. portStrHex = self.event_data['portHex'] # zjl
  232. cardNoHex = self.event_data['cardNoHex'] # zjl
  233. cardNo = self.event_data.get("cardNo")
  234. portStr = self.event_data.get("portStr")
  235. orderNo = self.event_data.get("orderNo")
  236. devCache = Device.get_dev_control_cache(self.device.devNo)
  237. portCache = devCache.get(portStr) or dict()
  238. if not portCache:
  239. logger.error("no port cache, error card finished!, card is <{}>".format(cardNo))
  240. self.response_card_finish(cardNoHex, portStrHex, cardStatus="03")
  241. return
  242. if cardNo != portCache.get("cardNo"):
  243. logger.error("card no is not equal , card is <{}>".format(cardNo))
  244. self.response_card_finish(cardNoHex, portStrHex, cardStatus="03")
  245. return
  246. pw = portCache.get("pw", "")
  247. openId = portCache.get("openId", "")
  248. cardOrderNo = portCache.get("cardOrderNo", "")
  249. try:
  250. card = self.update_card_dealer_and_type(cardNo)
  251. consumeOrder = ConsumeRecord.objects.get(orderNo=orderNo)
  252. cardConsumeOrder = CardConsumeRecord.objects.get(orderNo=cardOrderNo)
  253. except Exception as e:
  254. logger.exception(e)
  255. return
  256. # 请求结束充电 发送
  257. result = self.start_device(portStr, orderNo, pw, "12")
  258. data = result.get("data")
  259. curInfo = self.deviceAdapter._parse_result_B2(data)
  260. DevicePortReport.create(
  261. devNo=self.device.devNo,
  262. port=curInfo.get("portStr"),
  263. orderNo=curInfo.get("orderNo"),
  264. openId=openId,
  265. voltage=curInfo.get("voltage"),
  266. power=curInfo.get("power"),
  267. elec=curInfo.get("elec"),
  268. chargeTime=curInfo.get("chargeTime"),
  269. stayTime=curInfo.get("stayTime"),
  270. isBilling=portCache.get("status", Const.DEV_WORK_STATUS_IDLE) == Const.DEV_WORK_STATUS_WORKING
  271. )
  272. # 刷卡计费
  273. consumeMoney = Calculater(self.device, consumeOrder).result
  274. self.deduct_for_card(portStr, card, consumeMoney, consumeOrder, cardConsumeOrder)
  275. # 结束服务
  276. consumeDict = {
  277. "chargeIndex": portStr,
  278. 'actualNeedTime': curInfo.get("chargeTime"),
  279. 'elec': curInfo.get("elec"),
  280. 'stayTime': curInfo.get("stayTime"),
  281. 'chargeTime': curInfo.get("chargeTime"),
  282. }
  283. ServiceProgress.update_progress_and_consume_rcd(
  284. self.device["ownerId"],
  285. {
  286. "cardId": str(card.id),
  287. "open_id": consumeOrder.openId,
  288. "device_imei": self.device["devNo"],
  289. "port": int(portStr),
  290. "isFinished": False
  291. },
  292. consumeDict
  293. )
  294. # 最后回复B1 指令
  295. monthlyPackageId = portCache.get("monthlyPackageId")
  296. if monthlyPackageId:
  297. monthlyPackage = MonthlyPackage.objects.get(id = monthlyPackageId)
  298. self.response_card_finish(
  299. cardNoHex = cardNoHex,
  300. portStrHex = portStrHex,
  301. balance = RMB(0),
  302. consumeMoney = RMB(consumeMoney),
  303. cardType = 2,
  304. leftDays = max((monthlyPackage.expireDateTime - datetime.datetime.now()).days, 0)
  305. )
  306. extra = [({"消费金额": "{}元".format(consumeMoney), "余额": "{}元".format(0)})]
  307. else:
  308. self.response_card_finish(
  309. cardNoHex = cardNoHex,
  310. portStrHex = portStrHex,
  311. balance = RMB(card.balance),
  312. consumeMoney = RMB(consumeMoney)
  313. )
  314. extra=[({"消费金额": "{}元".format(consumeMoney), "余额": "{}元".format(card.balance)})]
  315. self.notify_user_service_complete(
  316. service_name='充电',
  317. openid=card.managerialOpenId,
  318. port=portStr,
  319. address=self.device.group['address'],
  320. reason=self.event_data.get('reasonDesc'),
  321. finished_time=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
  322. extra=extra)
  323. Device.clear_port_control_cache(self.device.devNo, portStr)
  324. # 状态上报
  325. class ChargeCabinetEventC0(WorkEvent, ChargeCabinetEventBase):
  326. def do(self, **args):
  327. orderNo = self.event_data.get("orderNo")
  328. orderNoHex = self.event_data.get("orderNoHex")
  329. portStr = self.event_data.get("portStr")
  330. voltage = self.event_data.get("voltage")
  331. power = self.event_data.get("power")
  332. elec = self.event_data.get("elec")
  333. chargeTime = self.event_data.get("chargeTime")
  334. temperature = self.event_data.get("temperature")
  335. status = self.event_data.get("status")
  336. stayTime = self.event_data.get("stayTime")
  337. devCache = Device.get_dev_control_cache(self.device["devNo"])
  338. portCache = devCache.get(portStr, dict())
  339. # 首先回复设备表示该状态已经收到
  340. if self.device.driverVersion in ['v1.0.0', 'v1.0.1']:
  341. sendData = orderNoHex + "{:0>2X}".format(int(portStr)) + "01"
  342. self.deviceAdapter._send_data(funCode="C0", sendData=sendData, cmd=DeviceCmdCode.OPERATE_DEV_NO_RESPONSE)
  343. # 空闲状态的端口过滤
  344. if status == Const.DEV_WORK_STATUS_IDLE:
  345. logger.info("device {} port {} report event, useless info!".format(self.device["devNo"], portStr))
  346. return
  347. openId = portCache.get("openId")
  348. if not openId:
  349. logger.info("port report event, has not openId, useless info!")
  350. return
  351. if orderNo != portCache.get("orderNo"):
  352. logger.info("port report event, not equal orderNo, useless info!{}".format(portStr))
  353. return
  354. # 保存数据库, 更新端口缓存
  355. data = {
  356. "devNo": self.device["devNo"],
  357. "port": portStr,
  358. "orderNo": orderNo,
  359. "openId": openId,
  360. "voltage": voltage,
  361. "power": power,
  362. "elec": elec,
  363. "chargeTime": chargeTime,
  364. "stayTime": stayTime
  365. }
  366. if status == Const.DEV_WORK_STATUS_OCCUPY:
  367. data.update({"isBilling": False})
  368. reportRecord = DevicePortReport.create(**data)
  369. if not reportRecord:
  370. logger.info("port report event, save db error!")
  371. return
  372. portCache.update({
  373. "voltage": voltage,
  374. "elec": elec,
  375. "temperature": temperature
  376. })
  377. Device.update_dev_control_cache(self.device["devNo"], {portStr: portCache})
  378. # 充电结束上报
  379. class ChargeCabinetEventC1(WorkEvent, ChargeCabinetEventBase):
  380. def do(self, **args):
  381. orderNo = self.event_data.get("orderNo")
  382. portStr = self.event_data.get("portStr")
  383. orderNoHex = self.event_data.get("orderNoHex")
  384. chargeTime = int(self.event_data.get("chargeTime"))
  385. elec = self.event_data.get("elec")
  386. voltage = self.event_data.get("voltage")
  387. power = self.event_data.get("power")
  388. stayTime = self.event_data.get("stayTime")
  389. devCache = Device.get_dev_control_cache(self.device["devNo"])
  390. portCache = devCache.get(portStr, dict())
  391. openId = portCache.get("openId")
  392. self.response_finish(orderNoHex, portStr)
  393. if portCache.get("orderNo") != orderNo:
  394. logger.warning("charge finish, but the orderNo not equal {}".format(portCache))
  395. # TODO 这种情况怎么去处理
  396. # 更新充电的时间 结束充电的时候 is_billing 一定是有效的 也就是说这一笔记录是需要算充电钱的
  397. DevicePortReport.create(
  398. devNo=self.device.devNo,
  399. port=portStr,
  400. orderNo=orderNo,
  401. openId=openId,
  402. voltage=voltage,
  403. power=power,
  404. elec=elec,
  405. chargeTime=chargeTime,
  406. stayTime=stayTime
  407. )
  408. # 更新新的portCache 这一轮的计费结束 就是 下一轮 占位费的开始
  409. portCache.update({
  410. "status": Const.DEV_WORK_STATUS_OCCUPY, # 状态更新进入占位状态
  411. "occupyStartTime": int(time.time()) # 占位的起始时间
  412. })
  413. Device.update_dev_control_cache(self.device.devNo, {portStr: portCache})
  414. if self.event_data.get("reasonCode") == "06":
  415. # 密码开锁的,需要结单, 这个可能是离线的信息上报 需要直接结单
  416. consumeOrder = ConsumeRecord.objects.get(orderNo = orderNo) # type: ConsumeRecord
  417. consumeMoney = Calculater(self.device, consumeOrder).result
  418. consumeDict = {
  419. "chargeIndex": portStr,
  420. 'actualNeedTime': self.event_data.get("chargeTime"),
  421. 'elec': self.event_data.get("elec"),
  422. 'stayTime': self.event_data.get("stayTime"),
  423. 'chargeTime': self.event_data.get("chargeTime"),
  424. }
  425. if self.is_start_by_card(portStr):
  426. cardNo = portCache.get("cardNo")
  427. card = self.update_card_dealer_and_type(cardNo)
  428. cardOrderNo = portCache.get("cardOrderNo", "")
  429. cardConsumeOrder = CardConsumeRecord.objects.get(orderNo = cardOrderNo)
  430. self.deduct_for_card(portStr, card, consumeMoney, consumeOrder, cardConsumeOrder)
  431. consumeDict = {
  432. "chargeIndex": portStr,
  433. 'actualNeedTime': self.event_data.get("chargeTime"),
  434. 'elec': self.event_data.get("elec"),
  435. 'stayTime': self.event_data.get("stayTime"),
  436. 'chargeTime': self.event_data.get("chargeTime"),
  437. DEALER_CONSUMPTION_AGG_KIND.CONSUME_CARD: RMB(consumeMoney).mongo_amount
  438. }
  439. else:
  440. # 扫码启动的设备的情况
  441. # 切换到运行结束的状态
  442. consumeOrder.update(money=RMB(consumeMoney).mongo_amount, coin=VirtualCoin(consumeMoney).mongo_amount)
  443. consumeOrder.reload()
  444. consumeOrder.s_to_e()
  445. ServiceProgress.update_progress_and_consume_rcd(
  446. self.device["ownerId"],
  447. {
  448. "open_id": consumeOrder.openId,
  449. "device_imei": self.device["devNo"],
  450. "port": int(portStr),
  451. "isFinished": False
  452. },
  453. consumeDict
  454. )
  455. Device.clear_port_control_cache(self.device.devNo, portStr)
  456. # 开始通知用户充电结束 进入占位状态
  457. else:
  458. user = MyUser.objects.filter(openId=portCache.get("openId"), groupId=self.device["groupId"]).first()
  459. group = Group.get_group(self.device["groupId"])
  460. self.notify_user(
  461. managerialOpenId=user.managerialOpenId if user else "",
  462. templateName="service_complete",
  463. title=u"\\n\\n结束原因:\\t\\t{reason}\\n\\n设备编号:\\t\\t{logicalCode}-{port}\\n\\n服务地址:\\t\\t{group}\\n\\n充电时间:\\t\\t{chargeTime}分钟".format(
  464. reason=self.event_data["reason"],
  465. logicalCode=self.device["logicalCode"],
  466. port=self.event_data["portStr"],
  467. group=group["address"],
  468. chargeTime=chargeTime,
  469. ),
  470. service=u"充电柜充电服务",
  471. finishTime=str(datetime.datetime.now())[: 19],
  472. remark=u'充电已经结束,请及时扫码,结束本次订单,取走您的电池!'
  473. )
  474. # 北向接口, 传递给API调用方
  475. notify_event_to_north_v2(self.device["devNo"], self.event_data)
  476. class ChargeCabinetEventCa(WorkEvent, ChargeCabinetEventBase):
  477. def do(self, **args):
  478. logger.info("device <{}> receive CA, event data = {}".format(self.device.devNo, self.event_data))
  479. subChargeList = self.event_data["subChargeList"]
  480. for _sub in subChargeList:
  481. ChargeCabinetEventC0(self.deviceAdapter, _sub).do()