nengpai.py 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768
  1. # -*- coding: utf-8 -*-
  2. # !/usr/bin/env python
  3. import datetime
  4. import logging
  5. import random, time
  6. from apps.web.constant import DeviceCmdCode, Const
  7. from apps.web.core.adapter.base import SmartBox, fill_2_hexByte, make_cartcp_order_no, reverse_hex, hexbyte_2_bin
  8. from apps.web.core.exceptions import ServiceException
  9. from apps.web.core.networking import MessageSender
  10. from apps.web.device.models import Device
  11. from apps.web.user.models import ServiceProgress
  12. from apps.web.core.adapter.base import string_to_ascstring
  13. from apps.web.common.proxy import ClientConsumeModelProxy
  14. logger = logging.getLogger(__name__)
  15. class NengpaiBox(SmartBox):
  16. def __init__(self, device):
  17. super(NengpaiBox, self).__init__(device)
  18. def translate_funcode(self, fun_code):
  19. fun_codeDict = {
  20. '12': u'读取实时监测数据',
  21. '34': u'运营平台远程控制启机',
  22. '36': u'运营平台远程停机',
  23. '42': u'远程账户余额更新',
  24. '44': u'上报充电结束事件',
  25. '46': u'离线卡数据清除',
  26. '48': u'离线卡数据查询',
  27. '52': u'充电桩工作参数设置',
  28. '56': u'对时设置',
  29. '58': u'计费模型设置',
  30. }
  31. return fun_codeDict.get(fun_code, '')
  32. def translate_event_cmdcode(self, cmdCode):
  33. cmdDict = {
  34. }
  35. return cmdDict.get(cmdCode, '')
  36. @property
  37. def isHaveStopEvent(self):
  38. return True
  39. def get_port_from_ab(self, portAB):
  40. portConf = {'A':1, 'B':2, 'C':3}
  41. if portAB in portConf:
  42. return portConf[portAB]
  43. return int(portAB)
  44. def get_abport_from_index(self, port):
  45. portConf = {'1':'A', '2':'B', '3':'C'}
  46. return portConf.get(port)
  47. def test(self, coins):
  48. data = '6830007C0034%s012018061914444680%s01000000100000000000000000D14B0A54A0860100' % (self._device['devNo'], self._device['devNo'])
  49. sendMsg = {'IMEI':self._device['devNo'], 'cmd': 0x34, 'data': data, 'sqNo': '007C','reply':'device'}
  50. devInfo = MessageSender.send(self.device, '34', sendMsg)
  51. return devInfo
  52. def check_feedback_result(self, cmd, devInfo):
  53. if not devInfo.has_key('rst'):
  54. raise ServiceException({'result': 2, 'description': u'报文异常'})
  55. if devInfo['rst'] == -1:
  56. raise ServiceException({'result': 2, 'description': u'充电桩正在玩命找网络,请您稍候再试'})
  57. if not devInfo.has_key('data'):
  58. return
  59. data = devInfo['data']
  60. if cmd == '36':
  61. errCode = data[-8:-6]
  62. if errCode == '01':
  63. return
  64. codeDesc = data[-6:-4]
  65. if codeDesc == '01':
  66. raise ServiceException({'result': 2, 'description': u'停止失败,设备编号不匹配'})
  67. elif codeDesc == '02':
  68. raise ServiceException({'result': 2, 'description': u'停止失败,枪未处于充电状态'})
  69. elif codeDesc == '03':
  70. raise ServiceException({'result': 2, 'description': u'停止失败,原因未知'})
  71. elif cmd == '58':
  72. codeDesc = data[-6:-4]
  73. if codeDesc == '00':
  74. raise ServiceException({'result': 2, 'description': u'计费模型下发到设备失败,请您重新尝试'})
  75. elif cmd == '34':
  76. codeDesc = data[-6:-4]
  77. if codeDesc == '01':
  78. raise ServiceException({'result': 2, 'description': u'设备编号不匹配'})
  79. elif codeDesc == '02':
  80. raise ServiceException({'result': 2, 'description': u'枪已在充电'})
  81. elif codeDesc == '03':
  82. raise ServiceException({'result': 2, 'description': u'设备故障'})
  83. elif codeDesc == '04':
  84. raise ServiceException({'result': 2, 'description': u'设备离线'})
  85. elif codeDesc == '05':
  86. raise ServiceException({'result': 2, 'description': u'未插枪'})
  87. def check_dev_status(self, attachParas=None):
  88. if attachParas.get("isTempPackage") == True:
  89. washConfig = self.device.get("tempWashConfig", {})
  90. else:
  91. washConfig = self.device.get("washConfig", {})
  92. packageId = attachParas.get("packageId")
  93. if not packageId: # 快捷支付过来的 第一次拉起支付的时候已经校验通过了
  94. return
  95. package = washConfig.get(packageId)
  96. # self._check_package(package)
  97. if package.get('name') == '充满自停' and package.get('coins') == 0 and package.get('price') == 0:
  98. port = int(attachParas['chargeIndex'])
  99. lineInfo = Device.get_dev_control_cache(self.device.devNo).get(str(port), {})
  100. if lineInfo.get('status') == Const.DEV_WORK_STATUS_WORKING:
  101. raise ServiceException({'result': 2, 'description': u'当前端口已处于工作状态,无法使用充满自停套餐, 请换个端口进行充电'})
  102. def make_sqNo(self):
  103. return fill_2_hexByte(hex(random.randint(0x0000, 0xFFFF)))
  104. def register_service_progress(self, openId, weifuleOrderNo, consumeOrder=None, attachParas=None):
  105. return ServiceProgress.objects.create(
  106. open_id=openId,
  107. device_imei=self.device.devNo,
  108. devTypeCode='300001',
  109. port=1,
  110. attachParas=attachParas if attachParas else {},
  111. start_time=int(time.time()),
  112. finished_time=int(time.time() + 24 * 60 * 60),
  113. consumeOrder=consumeOrder if consumeOrder else {},
  114. weifuleOrderNo=weifuleOrderNo,
  115. expireAt=datetime.datetime.now() + datetime.timedelta(days=91)
  116. ).id
  117. def _start(self, money, port, orderNo):
  118. amount = fill_2_hexByte(hex(int(float(money) * 100)), 8, True)
  119. sqNo = self.make_sqNo()
  120. data = '6830' + sqNo + '0034' + orderNo + self._device['devNo'] + fill_2_hexByte(hex(int(port)), 2) + '0000000000000000' + '0000000000000000' + amount
  121. payload = {'sqNo':sqNo, 'data':data, 'reply':'device'}
  122. return MessageSender.send(self.device, '34', payload)
  123. def start_device(self, package, openId, attachParas):
  124. if attachParas is None:
  125. raise ServiceException({'result': 2, 'description': u'请您选择合适的充电线路、电池类型信息'})
  126. if not attachParas.has_key('chargeIndex'):
  127. raise ServiceException({'result': 2, 'description': u'请您选择合适的充电线路'})
  128. port = int(self.get_port_from_ab(attachParas['chargeIndex']))
  129. onPoints = attachParas.get('onPoints')
  130. if onPoints: # 远程上分
  131. orderNo = make_cartcp_order_no(self._device['devNo'], port)
  132. logger.info('dealer onPoints package<{}> order<{}>'.format(package, orderNo))
  133. else:
  134. orderNo = str(attachParas.get('orderNo'))
  135. coins = package.get('coins')
  136. result = self._start(coins, port, orderNo)
  137. self.check_feedback_result('34', result)
  138. data = result['data']
  139. errCode = data[-6:-4]
  140. if errCode == '00':
  141. consumeOrder = {
  142. 'orderNo': orderNo,
  143. 'coin': package.get('coins'),
  144. 'consumeType': 'mobile',
  145. }
  146. self.register_service_progress(openId, orderNo, consumeOrder, attachParas)
  147. Device.update_dev_control_cache(self._device['devNo'], {str(port):{'coins':package.get('coins')}})
  148. return {'rst':0}
  149. return {'rst':int(errCode)}
  150. def reply_authentication(self, payload):
  151. data = '680C' + payload['sqNo'] + '0002' + self._device['devNo'] + '00'
  152. msg = {'IMEI':self._device['devNo'], 'sqNo':payload['sqNo'], 'data':data, 'reply':'server'}
  153. devInfo = MessageSender.send(self._device, '02', msg)
  154. self.check_feedback_result('02', devInfo)
  155. def send_qrcode(self):
  156. sqNo = self.make_sqNo()
  157. data = '6832' + sqNo + '00F0' + self._device['devNo'] + '00' + '25' + '687474703A2F2F7777772E7761736870617965722E636F6D2F757365724C6F67696E3F6C3D'
  158. # data = '680E' + sqNo + '00F0' + self._device['devNo'] + '00' + '01' + '68'
  159. payload = {'IMEI':self._device['devNo'],'sqNo':sqNo, 'data':data, 'reply':'device'}
  160. return MessageSender.send(self.device, 'F0', payload)
  161. # 单独处理北科新能源的二维码下发(JC充电桩与服务平台交互协议V1.4)
  162. def send_qrcode2(self):
  163. sqNo = self.make_sqNo()
  164. str = self._device['devNo']
  165. devNo = string_to_ascstring(str)
  166. if not self._device['ownerId']:
  167. # 用于注册设备
  168. data = '683A' + sqNo + '009C' + '01' + '33' + '00' + '687474703A2F2F7777772E7761736870617965722E636F6D2F757365724C6F67696E3F6C3D' + devNo
  169. else:
  170. portNum = Device.get_dev_control_cache(self.device['devNo']).get('allPorts', 2)
  171. # 判断枪的数量,若为单枪则固定二维码后缀的枪号为01
  172. if int(portNum) == 1:
  173. data = '683C' + sqNo + '009C' + '01' + '35' + '00' + '687474703A2F2F7777772E7761736870617965722E636F6D2F757365724C6F67696E3F6C3D' + devNo + '3031'
  174. else:
  175. data = '683A' + sqNo + '009C' + '01' + '33' + '00' + '687474703A2F2F7777772E7761736870617965722E636F6D2F757365724C6F67696E3F6C3D' + devNo
  176. def reply_feemode(self, payload):
  177. feeNo = payload['data'][-8:-4]
  178. serverFeeNo = self._device.otherConf.get('feeMode', {}).get('modeNo', '')
  179. check = '00' if feeNo == serverFeeNo else '01'
  180. data = '680E' + payload['sqNo'] + '0006' + self._device['devNo'] + feeNo + check
  181. msg = {'IMEI':self._device['devNo'], 'sqNo':payload['sqNo'], 'data':data, 'reply':'server'}
  182. devInfo = MessageSender.send(self._device, '06', msg)
  183. self.check_feedback_result('06', devInfo)
  184. """ 请参考如下格式feeMode的数据
  185. {'modeNo':'0001','jianFee':2.00000,'jianServe':0.16540,
  186. 'fengFee':3.00000,'fengServe':0.16540,
  187. 'pingFee':4.00000,'pingServe':0.16540,
  188. 'guFee':5.00000,'guServe':0.16540,
  189. 'jishunScale':0,
  190. 'shiduan':'0000000000000000000000000000000000000000000000000'
  191. }
  192. """
  193. def reply_new_feemode(self, payload):
  194. feeMode = self._device.otherConf.get('feeMode')
  195. if not feeMode:
  196. raise ServiceException({'result':2, 'description':u'设备没有初始化计费模型,请检查数据'})
  197. feeData = feeMode['modeNo'] + fill_2_hexByte(hex(int(feeMode['jianFee'] * 100000)), 8, True) + fill_2_hexByte(hex(int(feeMode['jianServe'] * 100000)), 8, True) \
  198. + fill_2_hexByte(hex(int(feeMode['fengFee'] * 100000)), 8, True) + fill_2_hexByte(hex(int(feeMode['fengServe'] * 100000)), 8, True)\
  199. + fill_2_hexByte(hex(int(feeMode['pingFee'] * 100000)), 8, True) + fill_2_hexByte(hex(int(feeMode['pingServe'] * 100000)), 8, True)\
  200. + fill_2_hexByte(hex(int(feeMode['guFee'] * 100000)), 8, True) + fill_2_hexByte(hex(int(feeMode['guServe'] * 100000)), 8, True)\
  201. + fill_2_hexByte(hex(int(feeMode['jishunScale'])), 2, True)
  202. for ii in range(48):
  203. temp = '00' if feeMode['shiduan'][ii] == '0' else '01'
  204. feeData += temp
  205. data = '685E' + payload['sqNo'] + '000A' + self._device['devNo'] + feeData
  206. msg = {'IMEI':self._device['devNo'], 'sqNo':payload['sqNo'], 'data':data, 'reply':'server'}
  207. devInfo = MessageSender.send(self._device, '0A', msg)
  208. self.check_feedback_result('0A', devInfo)
  209. return devInfo
  210. def reply_heartbeat(self, payload):
  211. data = '680D' + payload['sqNo'] + '0004' + self._device['devNo'] + payload['data'][-8:-6] + '00'
  212. msg = {'IMEI':self._device['devNo'], 'sqNo':payload['sqNo'], 'data':data, 'reply':'server'}
  213. devInfo = MessageSender.send(self._device, '04', msg)
  214. self.check_feedback_result('04', devInfo)
  215. return devInfo
  216. def stop(self, port=None):
  217. port = self.get_port_from_ab(port)
  218. sqNo = self.make_sqNo()
  219. data = '680C' + sqNo + '0036' + self._device['devNo'] + fill_2_hexByte(hex(port), 2)
  220. msg = {'IMEI':self._device['devNo'], 'sqNo':sqNo, 'data':data, 'reply':'device'}
  221. devInfo = MessageSender.send(self._device, '36', msg)
  222. self.check_feedback_result('36', devInfo)
  223. return devInfo
  224. def reply_finished_order(self, payload, strResult):
  225. data = '6815' + payload['data'][4:8] + '0040' + payload['data'][12:44] + strResult
  226. msg = {'IMEI':self._device['devNo'], 'sqNo':payload['data'][4:8], 'data':data, 'reply':'server'}
  227. devInfo = MessageSender.send(self._device, '40', msg)
  228. self.check_feedback_result('40', devInfo)
  229. return devInfo
  230. def reply_card_start(self, sqNo, orderNo, port, cardNo, balance, success, replyResult):
  231. data = '682A' + sqNo + '0032' + orderNo + self._device['devNo'] + fill_2_hexByte(hex(port), 2) + fill_2_hexByte(hex(int(cardNo)), 16) + fill_2_hexByte(hex(int(balance)), 8) + success + replyResult
  232. msg = {'IMEI':self._device['devNo'], 'sqNo':sqNo, 'data':data, 'reply':'server'}
  233. devInfo = MessageSender.send(self._device, '32', msg)
  234. self.check_feedback_result('32', devInfo)
  235. return devInfo
  236. def send_current_time(self):
  237. nowTime = datetime.datetime.now()
  238. hexTime = reverse_hex(fill_2_hexByte(hex(nowTime.second*1000), 4)) + fill_2_hexByte(hex(nowTime.minute), 2) + fill_2_hexByte(hex(nowTime.hour), 2) \
  239. + fill_2_hexByte(hex(nowTime.day), 2) + fill_2_hexByte(hex(nowTime.month), 2) + fill_2_hexByte(hex(nowTime.year - 2000), 2)
  240. sqNo = self.make_sqNo()
  241. data = '6812' + sqNo + '0056' + self._device['devNo'] + hexTime
  242. msg = {'IMEI':self._device['devNo'], 'sqNo':sqNo, 'data':data, 'reply':'device'}
  243. devInfo = MessageSender.send(self._device, '56', msg)
  244. self.check_feedback_result('56', devInfo)
  245. return devInfo
  246. def get_many_port_info(self, portList):
  247. resultDict = {}
  248. ctrInfo = Device.get_dev_control_cache(self._device['devNo'])
  249. for port in portList:
  250. portIndex = self.get_port_from_ab(port)
  251. valueDict = ctrInfo.get(str(portIndex))
  252. valueDict.update({'index':port})
  253. resultDict[port] = valueDict
  254. return resultDict
  255. def get_port_info(self, line):
  256. line = self.get_port_from_ab(line)
  257. return Device.get_dev_control_cache(self._device['devNo']).get(str(line), {})
  258. def get_values_from_data(self, data):
  259. port = int(data[58:60])
  260. valueDict = {}
  261. valueDict['index'] = port
  262. status = data[60:62]
  263. portStatus = Const.DEV_WORK_STATUS_IDLE
  264. if status == '00': # 端口离线是个什么鬼?先不处理吧
  265. pass
  266. elif status == '01':
  267. portStatus = Const.DEV_WORK_STATUS_FAULT
  268. elif status == '02':
  269. portStatus = Const.DEV_WORK_STATUS_IDLE
  270. elif status == '03':
  271. portStatus = Const.DEV_WORK_STATUS_WORKING
  272. else:
  273. pass
  274. valueDict['status'] = portStatus
  275. qiangGuiwei = data[62:64] # 枪是否归位
  276. if qiangGuiwei == '00':
  277. valueDict['qiangGuiwei'] = 'no'
  278. elif qiangGuiwei == '01':
  279. valueDict['qiangGuiwei'] = 'yes'
  280. else:
  281. valueDict['qiangGuiwei'] = 'unknow'
  282. if data[64:66] == '00': # //是否插枪
  283. valueDict['isPlugin'] = 'no'
  284. else:
  285. valueDict['isPlugin'] = 'yes'
  286. valueDict['voltage'] = int(reverse_hex(data[66:70]), 16) / 10.0
  287. valueDict['current'] = int(reverse_hex(data[70:74]), 16) / 10.0 # 电流,用什么显示呢? 还有电量,需要确认
  288. valueDict['plugLineTemper'] = int(reverse_hex(data[74:76]), 16) / 10.0
  289. valueDict['duration'] = int(reverse_hex(data[96:100]), 16)
  290. # valueDict['leftTime'] = int(reverse_hex(data[100:104]),16)/10.0 # 这个数据从测试看,貌似不准,就直接去掉吧
  291. valueDict['elec'] = int(reverse_hex(data[104:112]), 16) / 10000.0
  292. valueDict['jishunElec'] = int(reverse_hex(data[112:120]), 16) / 10000.0
  293. valueDict['chargedMoney'] = int(reverse_hex(data[120:128]), 16) / 10000.0
  294. binString = hexbyte_2_bin(data[128:130]) + hexbyte_2_bin(data[130:132])
  295. binString = binString[::-1]
  296. faultDesc = ''
  297. if binString[0] == '1':
  298. faultDesc += u'急停按钮动作故障'
  299. if binString[1] == '1':
  300. faultDesc += u'无可用整流模块;'
  301. if binString[2] == '1':
  302. faultDesc += u'出风口温度过高;'
  303. if binString[3] == '1':
  304. faultDesc += u'交流防雷故障;'
  305. if binString[4] == '1':
  306. faultDesc += u'交直流模块 DC20 通信中断;'
  307. if binString[5] == '1':
  308. faultDesc += u'绝缘检测模块 FC08 通信中断;'
  309. if binString[6] == '1':
  310. faultDesc += u'电度表通信中断;'
  311. if binString[7] == '1':
  312. faultDesc += u'读卡器通信中断;'
  313. if binString[8] == '1':
  314. faultDesc += u'RC10 通信中断;'
  315. if binString[9] == '1':
  316. faultDesc += u'风扇调速板故障;'
  317. if binString[10] == '1':
  318. faultDesc += u'直流熔断器故障;'
  319. if binString[11] == '1':
  320. faultDesc += u'高压接触器故障;'
  321. if binString[12] == '1':
  322. faultDesc += u'门打开;'
  323. valueDict['faultDesc'] = faultDesc
  324. return valueDict
  325. # 访问设备,获取设备端口信息 。不支持从设备上获取信息,直接从缓存取
  326. def get_port_status_from_dev(self):
  327. ctrInfo = Device.get_dev_control_cache(self._device['devNo'])
  328. result = {'1':ctrInfo.get('1', {}), '2':ctrInfo.get('2', {})}
  329. return result
  330. # result = {}
  331. # allPorts = ctrInfo.get('allPorts', 2)
  332. # for ii in range(allPorts):
  333. # sqNo = self.make_sqNo()
  334. # data = '680C' + sqNo + '0012' + self._device['devNo'] + '%02d' % (ii + 1)
  335. # msg = {'IMEI':self._device['devNo'],'sqNo':sqNo,'data':data,'reply':'device'}
  336. # devInfo = MessageSender.send(self._device, '12', msg)
  337. # self.check_feedback_result('12', devInfo)
  338. # valueDict = self.get_values_from_data(devInfo['data'])
  339. # Device.update_dev_control_cache(self.device['devNo'],{str(ii+1):valueDict})
  340. # result[str(ii+1)] = valueDict
  341. #
  342. # return result
  343. def get_port_status(self, force=False):
  344. ctrInfo = Device.get_dev_control_cache(self._device['devNo'])
  345. if not ctrInfo.has_key('allPorts'):
  346. self.get_port_status_from_dev()
  347. ctrInfo = Device.get_dev_control_cache(self._device['devNo'])
  348. allPorts = ctrInfo.get('allPorts', 2)
  349. statusDict = {}
  350. abcDict = {'1':'A', '2':'B'}
  351. for ii in range(allPorts):
  352. tempDict = ctrInfo.get(str(ii + 1), {})
  353. lock = self._device.otherConf.get(str(ii + 1), False)
  354. if tempDict.has_key('status'):
  355. statusDict[abcDict[str(ii + 1)]] = {'status': tempDict.get('status')}
  356. elif tempDict.has_key('isStart'):
  357. if tempDict['isStart']:
  358. statusDict[abcDict[str(ii + 1)]] = {'status': Const.DEV_WORK_STATUS_WORKING}
  359. else:
  360. statusDict[abcDict[str(ii + 1)]] = {'status': Const.DEV_WORK_STATUS_IDLE}
  361. else:
  362. statusDict[abcDict[str(ii + 1)]] = {'status': Const.DEV_WORK_STATUS_IDLE}
  363. if lock:
  364. statusDict[abcDict[str(ii + 1)]] = {'status':Const.DEV_WORK_STATUS_FORBIDDEN}
  365. allPorts, usedPorts, usePorts = self.get_port_static_info(statusDict)
  366. Device.update_dev_control_cache(self._device['devNo'],
  367. {'allPorts': allPorts, 'usedPorts': usedPorts, 'usePorts': usePorts})
  368. return statusDict
  369. def lock_unlock_port(self, port, lock=True):
  370. devObj = Device.objects.get(devNo = self.device['devNo'])
  371. port = self.get_port_from_ab(port)
  372. portInfo = self.get_port_info(port)
  373. if portInfo and portInfo['status'] == Const.DEV_WORK_STATUS_WORKING and lock:
  374. raise ServiceException({'result': 2, 'description': u'端口正忙,请先关闭端口后,再禁止端口'})
  375. devObj.otherConf[str(port)] = lock
  376. devObj.save()
  377. if lock:
  378. Device.update_dev_control_cache(self._device['devNo'],
  379. {str(port): {'status': Const.DEV_WORK_STATUS_FORBIDDEN}})
  380. else:
  381. Device.update_dev_control_cache(self._device['devNo'],
  382. {str(port): {'status': Const.DEV_WORK_STATUS_IDLE}})
  383. # 停止该端口下的所有任务
  384. def stop_charging_port(self, port):
  385. devInfo = self.stop(port)
  386. return True if devInfo['rst'] == 0 else False
  387. def get_policy_infos(self):
  388. feeMode = self._device.otherConf.get('feeMode', {})
  389. timeRateList = []
  390. shiduan = feeMode.get('shiduan', '000000000000000000000000000000000000000000000000')
  391. for ii in range(48):
  392. startHour = 0 + ii / 2
  393. startMin = '00' if ii % 2 == 0 else '30'
  394. endHour = startHour if ii % 2 == 0 else startHour + 1
  395. endMin = '30' if ii % 2 == 0 else '00'
  396. startTime = '%02d:%s' % (startHour, startMin)
  397. endTime = '%02d:%s' % (endHour, endMin)
  398. timeRateList.append({'startTime':startTime, 'endTime':endTime, 'rate':shiduan[ii]})
  399. result = {'top_price_rate':feeMode.get('jianFee', 1.2),
  400. 'top_price_service_rate':feeMode.get('jianServe', 0),
  401. 'peak_price_rate':feeMode.get('fengFee', 1.2),
  402. 'peak_price_service_rate':feeMode.get('fengServe', 0),
  403. 'normal_price_rate':feeMode.get('pingFee', 1.2),
  404. 'normal_price_service_rate':feeMode.get('pingServe', 0),
  405. 'valley_price_rate':feeMode.get('guFee', 1.2),
  406. 'valley_price_service_rate':feeMode.get('guServe', 0),
  407. 'jishunScale':feeMode.get('jishunScale', 0),
  408. 'timeRateList':timeRateList}
  409. return result
  410. # 获取设备配置参数
  411. def get_dev_setting(self):
  412. """
  413. 从主板上读取数据显示在前台
  414. :return:
  415. """
  416. return self.get_policy_infos()
  417. # 获取设备配置参数
  418. def set_dev_setting(self, setConf):
  419. """
  420. :param setConf:
  421. :return:
  422. """
  423. return
  424. def set_device_function(self, request, lastSetConf):
  425. if request.POST.has_key('clearSum'):
  426. self.clear_dev_feecount()
  427. elif request.POST.has_key('reboot'):
  428. self.reboot_device()
  429. def set_device_function_param(self, request, lastSetConf):
  430. devObj = Device.objects.get(devNo = self.device['devNo'])
  431. feeMode = devObj.otherConf.get('feeMode', {})
  432. feeMode['modeNo'] = '0001'
  433. feeMode['jianFee'] = float(request.POST.get('top_price_rate'))
  434. feeMode['jianServe'] = float(request.POST.get('top_price_service_rate'))
  435. feeMode['fengFee'] = float(request.POST.get('peak_price_rate'))
  436. feeMode['fengServe'] = float(request.POST.get('peak_price_service_rate'))
  437. feeMode['pingFee'] = float(request.POST.get('normal_price_rate'))
  438. feeMode['pingServe'] = float(request.POST.get('normal_price_service_rate'))
  439. feeMode['guFee'] = float(request.POST.get('valley_price_rate'))
  440. feeMode['guServe'] = float(request.POST.get('valley_price_service_rate'))
  441. feeMode['jishunScale'] = float(request.POST.get('jishunScale', 0))
  442. shiduan = ''
  443. for ii in range(48):
  444. startHour = 0 + ii / 2
  445. startMin = '00' if ii % 2 == 0 else '30'
  446. endHour = startHour if ii % 2 == 0 else startHour + 1
  447. endMin = '30' if ii % 2 == 0 else '00'
  448. startTime = '%02d:%s' % (startHour, startMin)
  449. endTime = '%02d:%s' % (endHour, endMin)
  450. print startTime, endTime
  451. harfHourValue = '0'
  452. for conf in request.POST.get('timeRateList'):
  453. if startTime >= conf['startTime'] and endTime <= conf['endTime']:
  454. harfHourValue = conf['rate']
  455. break
  456. else:
  457. continue
  458. shiduan += harfHourValue
  459. feeMode['shiduan'] = shiduan
  460. # 发送数据给设备
  461. feeData = feeMode['modeNo'] + fill_2_hexByte(hex(int(feeMode['jianFee'] * 100000)), 8, True) + fill_2_hexByte(hex(int(feeMode['jianServe'] * 100000)), 8, True) \
  462. + fill_2_hexByte(hex(int(feeMode['fengFee'] * 100000)), 8, True) + fill_2_hexByte(hex(int(feeMode['fengServe'] * 100000)), 8, True)\
  463. + fill_2_hexByte(hex(int(feeMode['pingFee'] * 100000)), 8, True) + fill_2_hexByte(hex(int(feeMode['pingServe'] * 100000)), 8, True)\
  464. + fill_2_hexByte(hex(int(feeMode['guFee'] * 100000)), 8, True) + fill_2_hexByte(hex(int(feeMode['guServe'] * 100000)), 8, True)\
  465. + fill_2_hexByte(hex(int(feeMode['jishunScale'])), 2, True)
  466. for ii in range(48):
  467. temp = '00' if feeMode['shiduan'][ii] == '0' else '01'
  468. feeData += temp
  469. sqNo = self.make_sqNo()
  470. data = '685E' + sqNo + '0058' + self._device['devNo'] + feeData
  471. msg = {'IMEI':self._device['devNo'], 'sqNo':sqNo, 'data':data, 'reply':'device'}
  472. devInfo = MessageSender.send(self._device, '58', msg)
  473. self.check_feedback_result('58', devInfo)
  474. # 设备那边正确响应后,才能够存入数据库中
  475. devObj.save()
  476. def get_signal(self):
  477. return {'rst':0, 'signal':self._device.signal}
  478. def active_deactive_port(self, port, active):
  479. if active == False:
  480. self.stop(port)
  481. def start_device_swap(self, portNo):
  482. consumeOrderNo = make_cartcp_order_no(self._device['devNo'], portNo)
  483. devInfo = self._start(100, portNo, consumeOrderNo)
  484. if not devInfo.has_key('rst'):
  485. return 1, 3, None # 错误3:设备报文异常
  486. if devInfo['rst'] == -1:
  487. # return 0,2,'1234123412341234'
  488. return 1, 2, None # 错误2:离线
  489. errCode = int(devInfo['data'][-6:-4])
  490. if errCode == 0:
  491. return 0, 0, consumeOrderNo # 成功
  492. return 1, errCode + 3, None
  493. def stop_device_swap(self, portNo):
  494. sqNo = self.make_sqNo()
  495. data = '680C' + sqNo + '0036' + self._device['devNo'] + fill_2_hexByte(hex(int(portNo)), 2)
  496. msg = {'IMEI':self._device['devNo'], 'sqNo':sqNo, 'data':data, 'reply':'device'}
  497. devInfo = MessageSender.send(self._device, '36', msg)
  498. if not devInfo.has_key('rst'):
  499. return 1, 4 # 错误4:设备报文异常
  500. if devInfo['rst'] == -1:
  501. return 0, 2
  502. # return 1,2,None # 错误2:离线
  503. errCode = int(devInfo['data'][-6:-4])
  504. if errCode == 0:
  505. return 0, 0 # 成功
  506. return 1, errCode + 4
  507. def get_charge_status_for_swap(self, portNo, connectorId):
  508. try:
  509. portDict = self.get_port_status_from_dev()
  510. except Exception, e:
  511. portDict = Device.get_dev_control_cache(self._device['devNo'])
  512. portInfo = portDict.get(str(portNo), {})
  513. adapterDict = {str(Const.DEV_WORK_STATUS_IDLE):1, str(Const.DEV_WORK_STATUS_FAULT):255, str(Const.DEV_WORK_STATUS_WORKING):3}
  514. return {
  515. 'StartChargeSeqStat':4 if portInfo.get('status') == Const.DEV_WORK_STATUS_IDLE else 2,
  516. 'ConnectorID':connectorId,
  517. 'ConnectorStatus':adapterDict.get(portInfo.get('status'), 1),
  518. 'CurrentA':portInfo.get('current'),
  519. 'VoltageA':220.0,
  520. 'Soc':0,
  521. 'TotalPower':portInfo.get('elec'),
  522. 'TotalMoney':portInfo.get('chargedMoney'),
  523. }
  524. def get_cur_fee(self):
  525. feeMode = self._device.otherConf.get('feeMode', {})
  526. shiduan = feeMode.get('shiduan', '000000000000000000000000000000000000000000000000')
  527. nowTime = datetime.datetime.now().strftime('%H:%M')
  528. curFeeIndex = 0
  529. for ii in range(48):
  530. startHour = 0 + ii / 2
  531. startMin = '00' if ii % 2 == 0 else '30'
  532. endHour = startHour if ii % 2 == 0 else startHour + 1
  533. endMin = '30' if ii % 2 == 0 else '00'
  534. startTime = '%02d:%s' % (startHour, startMin)
  535. endTime = '%02d:%s' % (endHour, endMin)
  536. if nowTime >= startTime and nowTime <= endTime:
  537. curFeeIndex = shiduan[ii]
  538. break
  539. return {
  540. 'curElecFee':feeMode.get({'0':'jianFee', '1':'fengFee', '2':'pingFee', '3':'guFee'}.get(str(curFeeIndex)), 0),
  541. 'curServiceFee':feeMode.get({'0':'jianServe', '1':'fengServe', '2':'pingServe', '3':'guServe'}.get(str(curFeeIndex)), 0)
  542. }
  543. def update_charger(self,chargerType,power,server,port,username,pwd,filepath,mode,timeout): # 请参考协议内容
  544. sqNo = self.make_sqNo()
  545. data = '6862' + sqNo + '0094' + self._device['devNo'] + fill_2_hexByte(hex(int(chargerType)), 2) + fill_2_hexByte(hex(int(power)), 4)
  546. data = data + string_to_ascstring(server,32) + reverse_hex(fill_2_hexByte(hex(int(port)), 4)) + string_to_ascstring(username,32) + string_to_ascstring(pwd,32)
  547. data = data + string_to_ascstring(filepath,64) + fill_2_hexByte(hex(int(mode)), 2) + fill_2_hexByte(hex(int(timeout)), 2)
  548. msg = {'IMEI':self._device['devNo'], 'sqNo':sqNo, 'data':data, 'reply':'device','cmd':'94','port':8768}
  549. # devInfo = MessageSender.send(self._device, '94', msg)
  550. devInfo = MessageSender.send_car_tcpip('211.159.224.10', 50000, msg)
  551. errCode = int(devInfo['data'][-6:-4])
  552. if errCode == 0:
  553. return 0
  554. return errCode
  555. def get_policy_for_user(self):
  556. feeMode = self._device.otherConf.get('feeMode',{})
  557. shiduan = feeMode.get('shiduan','000000000000000000000000000000000000000000000000')
  558. elecFeeDict = {'0':feeMode.get('jianFee',0),'1':feeMode.get('fengFee',0),'2':feeMode.get('pingFee',0),'3':feeMode.get('guFee',0)}
  559. serveFeeDict = {'0':feeMode.get('jianServe',0),'1':feeMode.get('fengServe',0),'2':feeMode.get('pingServe',0),'3':feeMode.get('guServe',0)}
  560. policyInfos = []
  561. for ii in range(48):
  562. startHour = 0 + ii/2
  563. startMin = '00' if ii%2==0 else '30'
  564. startTime = '%02d:%s' % (startHour,startMin)
  565. if (ii == 0) or (ii > 0 and shiduan[ii] != shiduan[ii-1]):
  566. policyInfos.append({'startTime':startTime,'elecPrice':elecFeeDict.get(shiduan[ii]),'sevicePrice':serveFeeDict.get(shiduan[ii])})
  567. return policyInfos
  568. def set_policy_infos(self,dataDict):
  569. devObj = Device.objects.get(devNo = self.device['devNo'])
  570. if 'feeMode' not in devObj.otherConf:
  571. devObj.otherConf.setdefault('feeMode',{})
  572. feeMode = devObj.otherConf.get('feeMode', {})
  573. feeMode['modeNo'] = '0001'
  574. feeMode['jianFee'] = float(dataDict.get('top_price_rate'))
  575. feeMode['jianServe'] = float(dataDict.get('top_price_service_rate'))
  576. feeMode['fengFee'] = float(dataDict.get('peak_price_rate'))
  577. feeMode['fengServe'] = float(dataDict.get('peak_price_service_rate'))
  578. feeMode['pingFee'] = float(dataDict.get('normal_price_rate'))
  579. feeMode['pingServe'] = float(dataDict.get('normal_price_service_rate'))
  580. feeMode['guFee'] = float(dataDict.get('valley_price_rate'))
  581. feeMode['guServe'] = float(dataDict.get('valley_price_service_rate'))
  582. feeMode['jishunScale'] = float(dataDict.get('jishunScale', 0))
  583. shiduan = ''
  584. for ii in range(48):
  585. startHour = 0 + ii / 2
  586. startMin = '00' if ii % 2 == 0 else '30'
  587. endHour = startHour if ii % 2 == 0 else startHour + 1
  588. endMin = '30' if ii % 2 == 0 else '00'
  589. startTime = '%02d:%s' % (startHour, startMin)
  590. endTime = '%02d:%s' % (endHour, endMin)
  591. print startTime, endTime
  592. harfHourValue = '0'
  593. for conf in dataDict.get('timeRateList'):
  594. if startTime >= conf['startTime'] and endTime <= conf['endTime']:
  595. harfHourValue = conf['rate']
  596. break
  597. else:
  598. continue
  599. shiduan += harfHourValue
  600. feeMode['shiduan'] = shiduan
  601. # 发送数据给设备
  602. feeData = feeMode['modeNo'] + fill_2_hexByte(hex(int(feeMode['jianFee'] * 100000)), 8, True) + fill_2_hexByte(hex(int(feeMode['jianServe'] * 100000)), 8, True) \
  603. + fill_2_hexByte(hex(int(feeMode['fengFee'] * 100000)), 8, True) + fill_2_hexByte(hex(int(feeMode['fengServe'] * 100000)), 8, True)\
  604. + fill_2_hexByte(hex(int(feeMode['pingFee'] * 100000)), 8, True) + fill_2_hexByte(hex(int(feeMode['pingServe'] * 100000)), 8, True)\
  605. + fill_2_hexByte(hex(int(feeMode['guFee'] * 100000)), 8, True) + fill_2_hexByte(hex(int(feeMode['guServe'] * 100000)), 8, True)\
  606. + fill_2_hexByte(hex(int(feeMode['jishunScale'])), 2, True)
  607. for ii in range(48):
  608. temp = '00' if feeMode['shiduan'][ii] == '0' else '01'
  609. feeData += temp
  610. sqNo = self.make_sqNo()
  611. data = '685E' + sqNo + '0058' + self._device['devNo'] + feeData
  612. msg = {'IMEI':self._device['devNo'], 'sqNo':sqNo, 'data':data, 'reply':'device'}
  613. devInfo = MessageSender.send(self._device, '58', msg)
  614. self.check_feedback_result('58', devInfo)
  615. # 设备那边正确响应后,才能够存入数据库中
  616. devObj.save()
  617. return devInfo
  618. def check_order_state(self, openId):
  619. dealerId = self.device.ownerId
  620. return ClientConsumeModelProxy.get_not_finished_record(ownerId=dealerId, openId=openId,
  621. devTypeCode=self._device['devType']['code'])
  622. def get_port_using_detail(self, port, ctrInfo, isLazy=False):
  623. """
  624. 获取设备端口的详细信息
  625. :param port:
  626. :param ctrInfo:
  627. :param isLazy: 是否延时加载设备信息
  628. :return:
  629. """
  630. detailDict = ctrInfo.get(str(port), {})
  631. try:
  632. if isLazy: # 需要点击再次点击按钮加载
  633. portInfo = {'isLazy': True}
  634. else:
  635. portInfo = self.get_port_info(str(port))
  636. detailDict.update(portInfo)
  637. leftMoney = detailDict.get('coins') - detailDict.get('chargedMoney',0)
  638. detailDict.update({"leftMoney":u'%s元'%leftMoney })
  639. detailDict.update({"chargedMoney":u'%s元'%detailDict.get('chargedMoney',0) })
  640. except Exception, e:
  641. logger.exception('get port info from dev=%s err=%s' % (self.device.devNo, e))
  642. return detailDict
  643. return self.format_port_using_detail(detailDict)