123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766 |
- # -*- coding: utf-8 -*-
- # !/usr/bin/env python
- import binascii
- import datetime
- import logging
- import struct
- import time
- from apps.web.agent.models import Agent
- from apps.web.constant import Const, DeviceCmdCode, MQTT_TIMEOUT
- from apps.web.core.adapter.base import SmartBox, fill_2_hexByte
- from apps.web.core.exceptions import ServiceException
- from apps.web.core.networking import MessageSender
- from apps.web.dealer.models import Dealer
- from apps.web.device.models import Device, Group, DeviceType
- from apps.web.device.timescale import FluentedEngine
- from apps.web.utils import concat_user_login_entry_url
- logger = logging.getLogger(__name__)
- class ChargingJNCar(SmartBox):
- PORT_STATUS_MAP = {
- "01": Const.DEV_WORK_STATUS_IDLE,
- "02": Const.DEV_WORK_STATUS_WORKING,
- "03": Const.DEV_WORK_STATUS_FORBIDDEN,
- # 劲能汽车桩 故障和连接状态没有区分开 咨询过主板 只能靠人工判断 插枪了如果还是故障 就是真的故障
- "04": Const.DEV_WORK_STATUS_CONNECTED
- }
- ERROR_MAP = {
- "0001": u"继电器粘连",
- "0002": u"其他错误"
- }
- FINISH_MAP = {
- '00': u'购买的充电时间或电量用完了。',
- '01': u'可能是插头被拔掉,或者电瓶已经充满。系统判断为异常断电,由于电瓶车充电器种类繁多,可能存在误差。如有问题,请您及时联系商家协助解决问题并恢复充电。',
- '02': u'恭喜您!电池已经充满电!',
- '03': u'警告!您的电池超功率,已经停止充电,为了公共安全,不建议您在该充电桩充电!提醒您,为了安全大功率的电池不要放入楼道、室内等位置充电哦',
- '04': u'远程断电。',
- '05': u'刷卡断电',
- '0B': u'设备或端口出现问题,为了安全起见,被迫停止工作。建议您根据已经充电的时间评估是否需要到现场换到其他端口充电。'
- }
- def _send_data(self, funCode, data, cmd=None, timeout=MQTT_TIMEOUT.NORMAL):
- """
- :param funCode:
- :param data:
- :param cmd:
- :param timeout:
- :return:
- """
- if cmd is None:
- cmd = DeviceCmdCode.OPERATE_DEV_SYNC
- result = MessageSender.send(device = self.device, cmd = cmd, payload = {
- "IMEI": self.device.devNo,
- "funCode": funCode,
- "data": data
- }, timeout = timeout)
- if "rst" in result and result.get("rst") != 0:
- if result.get("rst") == -1:
- raise ServiceException({"result": 2, "description": u"网络故障,请重新试试"})
- if result.get("rst") == 1:
- raise ServiceException({"result": 2, "description": u"充电桩无响应,请稍后再试试"})
- return result
- @property
- def _sessionId(self):
- return int(time.time())
- @staticmethod
- def _to_ascii(s):
- """
- 将字符串转换成ascii
- :param s:
- :return:
- """
- return binascii.hexlify(s)
- @staticmethod
- def _parse_event_26(data):
- """
- 解析 26 指令上报过来的数据
- 26 指令主要负责上传端口的实时状态 是将所有的端口一次性上传
- :return:
- """
- portNum = int(data[8:10], 16)
- portStatusDict = dict()
- data = data[10:]
- for i in xrange(portNum):
- portStr = str(int(data[:2], 16))
- portStatusDict[portStr] = {
- "status": ChargingJNCar.PORT_STATUS_MAP.get(data[4:6], Const.DEV_WORK_STATUS_IDLE),
- "usedTime": int(data[6:10], 16),
- "power": int(data[10:14], 16),
- "usedElec": int(data[14:18], 16) / 100.0,
- "voltage": int(data[18:22], 16) / 10.0,
- "a": int(data[22: 26], 16) / 100.0
- }
- data = data[26: ]
- portStatusDict["portNum"] = portNum
- return portStatusDict
- @staticmethod
- def _parse_event_0A(data):
- """
- 解析故障报警
- :param data:
- :return:
- """
- port = data[8:10]
- if port == "FFFF":
- portStr = 0
- else:
- portStr = str(int(port, 16))
- errorCode = data[10:14]
- errorDesc = ChargingJNCar.ERROR_MAP.get(errorCode, "")
- return {
- "portStr": portStr,
- "errorCode": errorCode,
- "errorDesc": errorDesc
- }
- def _start(self, port, money, elec, _type=None, _time=None):
- """
- 启动设备
- :param port:
- :param money:
- :param elec:
- :param _type:
- :param _time:
- :return:
- """
- # 目前只支持按电量计费
- if _type is None:
- chargeTypeHex = "02"
- else:
- chargeTypeHex = fill_2_hexByte(hex(int(_type)), 2)
- if _time is None:
- chargeTimeHex = "0000"
- else:
- chargeTimeHex = fill_2_hexByte(hex(int(_time)), 4)
- moneyHex = fill_2_hexByte(hex(int(float(money)*10)), 4)
- portHex = fill_2_hexByte(hex(int(port)), 2)
- elecHex = fill_2_hexByte(hex(int(float(elec)*100)), 4)
- sessionHex = fill_2_hexByte(hex(self._sessionId), 8)
- sendData = portHex + moneyHex + chargeTimeHex + elecHex + sessionHex + chargeTypeHex
- result = self._send_data("27", sendData, timeout=MQTT_TIMEOUT.START_DEVICE)
- data = result.get("data", "")
- if data[10:12] == "0B":
- raise ServiceException({"result": 0, "description": u"充电站故障,请重新试试"})
- elif data[10:12] == "0C":
- raise ServiceException({"result": 0, "description": u"该端口已被占用,请换个端口进行充电"})
- elif data[10:12] == "02":
- raise ServiceException({"result": 0, "description": u"暂不支持此充电模式,请联系经销商解决"})
- elif data[10:12] == "01":
- return result
- else:
- raise ServiceException({"result": 2, "description": u"未知充电错误"})
- def _stop(self, port):
- """
- 停止设备使用
- _type 表示 停止的订单类型 0x00/所有类型的订单 0x01/通过模块提交的充电信息 0x02/本地的支付订单,如刷卡、投币
- :return:
- """
- portHex = fill_2_hexByte(hex(int(port)), 2)
- _type = "00"
- self._send_data("0D", portHex+_type)
- def _set_device_qr_code(self):
- """
- 设置设备的二维码
- :return:
- """
- logicalCode = self.device.logicalCode[-6:]
- qr_code_url = concat_user_login_entry_url(l = self._device["logicalCode"])
- code = fill_2_hexByte(hex(int(logicalCode)), 8)
- urlBuf = ChargingJNCar._to_ascii(qr_code_url).upper()
- urlBuf = "{:0<140}".format(urlBuf) # 最长70个字节结尾为00
- self._send_data("2F", code+urlBuf, DeviceCmdCode.OPERATE_DEV_NO_RESPONSE)
- # d = "000012A8687474703A2F2F646576656C6F702E3574616F3561692E636F6D2F757365724C6F67696E3F6C3D34343737363800000000000000000000000000000000000000000000000000"
- # self._send_data("2F", d, DeviceCmdCode.OPERATE_DEV_NO_RESPONSE)
- def _get_device_settings_2B(self):
- """
- 获取设备的 一些设置
- :return:
- """
- result = self._send_data("2B", "00")
- data = result.get("data", "")
- cardCst = int(data[8:12], 16) # 单位为角
- elecPri = int(data[12:16], 16) # 单位是分
- return {
- "cardCst": cardCst,
- "elecPri": elecPri
- }
- def _set_device_settings_2A(self, cst, elecFee):
- """
- 设置设备的一些参数
- :return:
- """
- cstHex = fill_2_hexByte(hex(int(cst)), 4)
- elecFeeHex = fill_2_hexByte(hex(int(elecFee)), 4)
- return self._send_data("2A", cstHex+elecFeeHex)
- def _get_port_charge_status(self, port):
- """
- 查询当前的充电状态 电流暂时不要
- :return:
- """
- portHex = fill_2_hexByte(hex(int(port)), 2)
- result = self._send_data("2E", portHex)
- data = result.get("data")
- leftTime = data[10:14]
- power = data[14:18]
- leftElec = data[18:22]
- surp = data[22:26]
- voltage = data[26:30]
- maxTime = data[34:38]
- return {
- "leftTime": int(leftTime, 16) if leftTime else 0,
- "power": int(power, 16) if power else 0,
- "leftElec": int(leftElec, 16) / 100.0 if leftElec else 0,
- "surp": int(surp, 16) / 10.0 if surp else 0,
- "voltage": int(voltage, 16) if voltage else 0,
- "maxTime": int(maxTime, 16) if maxTime else 0
- }
- def _get_device_max_charge_time(self):
- """
- 获取设备的最长充电时间
- :return:
- """
- result = self._send_data("25", "00")
- data = result.get("data", "")
- maxChargeTime = int(data[8:12], 16)
- return {
- "maxChargeTime": maxChargeTime
- }
- def _set_device_max_charge_time(self, chargeTime):
- """
- 设置设备的最长充电时间 单位是分钟
- :return:
- """
- chargeTimeHex = fill_2_hexByte(hex(int(chargeTime)), 4)
- return self._send_data("24", chargeTimeHex)
- def _get_device_version(self):
- """
- 获取设备的主板信息 版本等等
- :return:
- """
- typeMap = {
- "01": u"十路智慧款",
- "02": u"双路电轿款",
- "04": u"离线充值机",
- "05": u"16路智慧款",
- "06": u"20路智慧款",
- "07": u"单路7kw交流桩"
- }
- result = self._send_data("23", "00")
- data = result.get("data", "")
- hdType = data[8:10]
- hwVer = data[10:14]
- swVer = data[14:18]
- idBuf = data[18:42]
- return {
- "hdType": typeMap.get(hdType, ""),
- "hwVer": hwVer,
- "swVer": swVer,
- "idBuf": idBuf
- }
- def _get_device_port_status(self):
- """
- 读取每个设备的状态
- :return:
- """
- result = self._send_data("0F", "00")
- data = result.get("data", "")
- portNum = int(data[8:10], 16)
- portHexData = data[10:-2]
- portStatusDict = dict()
- for i in range(portNum):
- offset = i * 4
- portStr = str(int(portHexData[0+offset: 2+offset], 16))
- portStatus = ChargingJNCar.PORT_STATUS_MAP.get(portHexData[2+offset: 4+offset])
- portStatusDict[portStr] = {"status": portStatus}
- return portStatusDict
- def _lock_port(self, port):
- """
- 锁定端口
- :param port:
- :return:
- """
- portHex = fill_2_hexByte(hex(int(port)), 2)
- statusHex = "00"
- self._send_data("0C", portHex+statusHex, cmd=DeviceCmdCode.OPERATE_DEV_NO_RESPONSE)
- def _unlock_port(self, port):
- """
- 解锁端口
- :param port:
- :return:
- """
- portHex = fill_2_hexByte(hex(int(port)), 2)
- statusHex = "01"
- self._send_data("0C", portHex + statusHex, cmd=DeviceCmdCode.OPERATE_DEV_NO_RESPONSE)
- def _get_consume_data_from_device(self):
- """
- 从 主板 侧获取消费数据
- :return:
- """
- result = self._send_data("07", "00")
- data = result.get("data", "")
- cardMoney = int(data[8:12], 16) / 10.0
- coinMoney = int(data[12:16], 16)
- return {
- "cardMoney": cardMoney,
- "coinMoney": coinMoney
- }
- def _get_all_port_num(self):
- """
- 获取端口总数
- :return:
- """
- result = self._send_data("01", "00")
- data = result.get("data", "")
- portNum = int(data[8:10], 16)
- return {
- "portNum": portNum
- }
- def _response_card_balance(self, cardBalance, res):
- """
- 回复刷卡余额的数据
- :param cardBalance:
- :param res:
- :return:
- """
- balanceHex = fill_2_hexByte(hex(int(cardBalance) * 10), 4)
- self._send_data("10", res+balanceHex, cmd=DeviceCmdCode.OPERATE_DEV_NO_RESPONSE)
- def _response_finished(self, port, sessionId):
- """
- 回复主板结束事件
- :param port:
- :param sessionId:
- :return:
- """
- portHex = fill_2_hexByte(hex(int(port)), 2)
- self._send_data("2C", portHex+sessionId, cmd=DeviceCmdCode.OPERATE_DEV_NO_RESPONSE)
- def lock_unlock_port(self, port, lock=True):
- """
- 禁用 解禁 端口
- :param port:
- :param lock:
- :return:
- """
- if lock:
- self._lock_port(port)
- else:
- self._unlock_port(port)
- def active_deactive_port(self, port, active):
- if not active:
- self._stop(port)
- else:
- raise ServiceException({'result': 2, 'description': u'此设备不支持直接打开端口'})
- def stop(self, port=None):
- """
- 停止设备运行
- :param port:
- :return:
- """
- self._stop(port)
- def get_port_info(self, port):
- """
- 获取端口运行的信息 可以从设备端获取 也可以从缓存获取
- :param port:
- :return:
- """
- devCache = Device.get_dev_control_cache(self.device.devNo)
- return devCache.get(str(port), dict())
- def get_port_status_from_dev(self):
- """
- 获取设备 端口的实时状态
- :return:
- """
- portDict = self._get_device_port_status()
- # 更新可用端口数量
- allPorts, usedPorts, usePorts = self.get_port_static_info(portDict)
- Device.update_dev_control_cache(
- self._device["devNo"],
- {
- "allPorts": allPorts,
- "usedPorts": usedPorts,
- "usePorts": usePorts
- }
- )
- # 更新端口状态
- devCache = Device.get_dev_control_cache(self._device["devNo"])
- for port, info in portDict.items():
- if port in devCache and isinstance(info, dict):
- devCache[port].update({"status": info["status"]})
- else:
- devCache[port] = info
- Device.update_dev_control_cache(self._device["devNo"], devCache)
- return portDict
- def get_port_status(self, force = False):
- """
- 获取 设备端口状态 一般是从缓存读取
- :param force:
- :return:
- """
- if force:
- return self.get_port_status_from_dev()
- devCache = Device.get_dev_control_cache(self._device["devNo"])
- if "allPorts" not in devCache:
- self.get_port_status_from_dev()
- devCache = Device.get_dev_control_cache(self._device["devNo"])
- allPorts = devCache.get("allPorts")
- if allPorts is None:
- raise ServiceException({'result': 2, 'description': u'充电端口信息获取失败'})
- # 获取显示端口的数量 客户要求可以设置 显示给用户多少个端口
- statusDict = dict()
- for portNum in xrange(allPorts):
- portStr = str(portNum + 1)
- tempDict = devCache.get(portStr, {})
- if "status" in tempDict:
- statusDict[portStr] = {"status": tempDict["status"]}
- elif "isStart" in tempDict:
- if tempDict["isStart"]:
- statusDict[portStr] = {"status": Const.DEV_WORK_STATUS_WORKING}
- else:
- statusDict[portStr] = {"status": Const.DEV_WORK_STATUS_IDLE}
- else:
- statusDict[portStr] = {"status": Const.DEV_WORK_STATUS_IDLE}
- allPorts, usedPorts, usePorts = self.get_port_static_info(statusDict)
- portsDict = {"allPorts": allPorts, "usedPorts": usedPorts, "usePorts": usePorts}
- Device.update_dev_control_cache(self._device["devNo"], portsDict)
- # 返还的是要显示的端口数量
- return statusDict
- def check_dev_status(self, attachParas=None):
- """
- 汽车充电桩使用现金支付的时候,首先先检查一下设备的端口是否正常
- :param attachParas:
- :return:
- """
- chargeIndex = attachParas.get("chargeIndex", "")
- portStatus = self._get_device_port_status().get(chargeIndex, dict()).get("status")
- return portStatus == Const.DEV_WORK_STATUS_IDLE
- def test(self, coins):
- """
- 联网检测
- :param coins:
- :return:
- """
- port = "01"
- elec = "10"
- return self._start(port, coins, elec)
- def start_device(self, package, openId, attachParas):
- """
- 启动设备,目前仅支持按按电量计费
- :param package:
- :param openId:
- :param attachParas:
- :return:
- """
- if attachParas is None:
- raise ServiceException({'result': 2, 'description': u'请您选择合适的充电线路、电池类型信息'})
- if "chargeIndex" not in attachParas:
- raise ServiceException({'result': 2, 'description': u'请您选择合适的充电线路'})
- chargeIndex = attachParas.get("chargeIndex")
- needElec = package.get("time")
- coins = package.get("coins")
- price = package.get("price")
- try:
- result = self._start(chargeIndex, price, needElec)
- except ServiceException as se:
- if se.result.get("result") == 0:
- # TODO zjl 执行退款事件
- se.result.update({"result": 2})
- raise ServiceException(se.result)
- devCache = Device.get_dev_control_cache(self.device.devNo)
- portCache = devCache.get(str(chargeIndex), dict())
- nowTimeStamp = int(time.time())
- portCache.update({
- "isStart": True,
- "status": Const.DEV_WORK_STATUS_WORKING,
- "openId": openId,
- "price": price,
- "coins": coins,
- "needElec": needElec,
- "startTime": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
- "startTimeStamp": nowTimeStamp,
- "consumeType": "mobile",
- "vCardId": self._vcard_id,
- "power": 1 # 为power添加默认值 主要是getCurrentUse 的这个接口有一个判断power==0的时候直接将ServiceProgress结束了
- })
- if 'linkedRechargeRecordId' in attachParas and attachParas.get('isQuickPay', False):
- item = {
- 'rechargeRcdId': str(attachParas['linkedRechargeRecordId'])
- }
- portCache['payInfo'] = [item]
- Device.update_dev_control_cache(self.device.devNo, {str(chargeIndex): portCache})
- result["finishedTime"] = 24 * 60 * 60 + nowTimeStamp
- return result
- def check_and_do_card_number_reverse(self, cardNo, cardNoData):
- group = Group.get_group(self._device['groupId'])
- dealer = Dealer.get_dealer(group['ownerId'])
- agent = Agent.objects(id=dealer['agentId']).first()
- device = Device.objects(devNo=self._device['devNo']).first()
- devType = DeviceType.objects(id=device['devType']['id']).first()
- if agent is not None and 'cardNoReverse' in agent.features:
- cardData = [cardNoData[_*2:(_ + 1)*2] for _ in range(0, len(cardNoData) / 2)]
- cardData.reverse()
- cardData = ''.join(cardData)
- cardNo = str(int(cardData, 16))
- if 'cardNoReverse' in devType.features:
- if devType.features['cardNoReverse'] is True:
- cardData = [cardNoData[_ * 2:(_ + 1) * 2] for _ in range(0, len(cardNoData) / 2)]
- cardData.reverse()
- cardData = ''.join(cardData)
- cardNo = str(int(cardData, 16))
- else:
- cardData = [cardNoData[_ * 2:(_ + 1) * 2] for _ in range(0, len(cardNoData) / 2)]
- cardData = ''.join(cardData)
- cardNo = str(int(cardData, 16))
- else:
- pass
- return cardNo
- def analyze_event_data(self, data):
- """
- 接受事件
- :param data:
- :return:
- """
- cmdCode = data[4:6]
- # 请求二维码
- if cmdCode == "2F":
- self._set_device_qr_code()
- return
- elif cmdCode == "2C":
- portStr = str(int(data[8:10], 16))
- leftTime = int(data[10:14], 16)
- leftElec = int(data[14:18], 16) / 100.0
- cardNo = str(int(data[18:26], 16))
- cardNo = self.check_and_do_card_number_reverse(cardNo, data[18:26])
- cardLeftBalance = int(data[26:30], 16) / 10.0
- cardOpe = data[30:32]
- cardType = data[32:34]
- reasonCode = data[34:36]
- sessionId = data[36:44]
- return {
- "cmdCode": cmdCode,
- "portStr": portStr,
- "leftTime": leftTime,
- "leftElec": leftElec,
- "cardNo": cardNo,
- "cardLeftBalance": cardLeftBalance,
- "cardOpe": cardOpe,
- "cardType": cardType,
- "reasonCode": reasonCode,
- "desc": ChargingJNCar.FINISH_MAP.get(reasonCode),
- "sessionId": sessionId
- }
- elif cmdCode == "2D":
- portStr = str(int(data[8:10], 16))
- needTime = int(data[10:14], 16)
- needElec = int(data[14:18], 16) / 100.0
- chargeType = data[18:20]
- coinNum = int(data[20:22], 16)
- cardNo = str(int(data[22:30], 16))
- cardNo = self.check_and_do_card_number_reverse(cardNo, data[22:30])
- cardCst = int(data[30:34], 16) / 10.0
- cardOpe = data[34:36]
- cardType = data[36:38]
- sessionId = data[38:46]
- return {
- "cmdCode": cmdCode,
- "portStr": portStr,
- "needTime": needTime,
- "needElec": needElec,
- "chargeType": chargeType,
- "coinNum": coinNum,
- "cardNo": cardNo,
- "cardCst": cardCst,
- "cardOpe": cardOpe,
- "cardType": cardType,
- "sessionId": sessionId
- }
- elif cmdCode == "10":
- cardNo = str(int(data[8:16], 16))
- cardNo = self.check_and_do_card_number_reverse(cardNo, data[8:16])
- cardCst = int(data[16:18], 16) / 10.0
- return {
- "cmdCode": cmdCode,
- "cardNo": cardNo,
- "cardCst": cardCst
- }
- # 其余的event指令
- funcName = "_parse_event_{}".format(cmdCode.upper())
- func = getattr(ChargingJNCar, funcName, None)
- if not func:
- logger.error("<{}> device receive an invalid cmd <{}>".format(self.device.devNo, cmdCode))
- return
- eventData = func(data)
- eventData.update({"cmdCode": cmdCode})
- return eventData
- def get_dev_setting(self):
- """
- 汽车充电桩目前就两个设置
- :return:
- """
- return self._get_device_settings_2B()
- def set_device_function_param(self, request, lastSetConf):
- """
- 汽车桩的参数设置
- :param request:
- :param lastSetConf:
- :return:
- """
- cardCst = request.POST.get("cardCst", None) or lastSetConf.get("cardCst")
- elecPri = request.POST.get("elecPri", None) or lastSetConf.get("elecPri")
- self._set_device_settings_2A(cardCst, elecPri)
- @property
- def isHaveStopEvent(self):
- return True
- def do_heartbeat(self, value, ts):
- logger.debug('do heartbeat for {}. value = {}; ts = {}'.format(str(self.device), value, ts))
- cmd = struct.unpack_from('<B', value, 2)[0]
- if cmd != 0x26:
- return
- port_num = struct.unpack_from('<B', value, 4)[0]
- if port_num == 0:
- logger.warning('return port of {} is zero.'.format(str(self.device)))
- return
- logger.debug('port of {} is: {}'.format(str(self.device), port_num))
- update_cache = {}
- for i in range(1, port_num + 1):
- offset = (i - 1) * 13 + 5
- port, value_type, status, time_value, power, elec_value, v, a = \
- struct.unpack_from('<BBBHHHHH', value, offset)
- FluentedEngine().in_power_udp(devNo = self.device.devNo,
- port = str(port),
- ts = ts,
- power = power,
- voltage = None,
- current = None)
- update_cache[str(port)] = {
- "voltage": round(float(v) / 10, 2),
- "power": power
- }
- if value_type == 0x00:
- update_cache[str(port)].update({
- 'leftTime': time_value,
- 'leftElec': elec_value
- })
- else:
- update_cache[str(port)].update({
- 'usedTime': time_value,
- 'usedElec': elec_value
- })
- logger.debug('update cache of {} is: {}'.format(str(self.device), update_cache))
- Device.update_dev_control_cache(self.device.devNo, update_cache)
- if not self.device.support_power_graph:
- Device.get_collection().update_one({'devNo': self.device.devNo}, {'$set': {'otherConf.supportPG': True}})
- Device.invalid_device_cache(self.device.devNo)
|