123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374 |
- # -*- coding: utf-8 -*-
- # !/usr/bin/env python
- import copy
- import logging
- import datetime
- import time
- from typing import TYPE_CHECKING
- from apps.web.constant import Const
- from apps.web.core.exceptions import ServiceException
- from apps.web.core.adapter.base import SmartBox, start_error_timer
- from apps.web.core.device_define.baolai import send_request
- from apps.web.device.models import Device
- from apps.web.user.models import ConsumeRecord
- if TYPE_CHECKING:
- pass
- logger = logging.getLogger(__name__)
- # 2.4 , 2.6 , 2.12 , 2.14 , 2.15 , 3.2 , 3.3 , 3.4 , 3.5 , 3.6 , 3.7 , 3.9
- class SampleData:
- """
- sampleMap = {
- "max_power":200, # 单路最大充电功率,单位W
- "charge_full_power_threshold":10, # 充满阈值,单位W,默认10W
- "charge_full_time_threshold":7200, # 浮充时间,单位s,默认7200s
- "charge_single_amount":100, # 单次按键金额,单位分,默认1.00
- "max_time":900, # 最大充电时间,单位分,默认600分
- "trickle_threshold":10, # 未开放,暂勿需对接
- "no_load_power_threshold":2.5, # 空载阈值,单位W,默认0.8W
- "high_temperature_threshold":85, # 过温阈值,单位℃,默认60℃
- "max_current":12, # 单路最大电流,单位A
- "no_load_time_threshold":45 # 空载时间,单位s,默认45s
- }
- """
- sampleMap = {
- 'max_power': 0,
- 'charge_full_power_threshold': 0,
- 'charge_full_time_threshold': 0,
- 'charge_single_amount': 0,
- 'max_time': 0,
- 'trickle_threshold': 0,
- 'no_load_power_threshold': 0,
- 'high_temperature_threshold': 0,
- 'max_current': 0,
- 'no_load_time_threshold': 0,
- }
- class BoLaiTenCharge(SmartBox):
- def __init__(self, device):
- super(BoLaiTenCharge, self).__init__(device)
- devObj = self.device.my_obj
- self.billingType = devObj.otherConf.get('billingType', 'time')
- self.config_list = devObj.otherConf.get('config_list', [])
- self.onceCard = devObj.otherConf.get('onceCard', 100)
- self.cardTime = devObj.otherConf.get('cardTime', 180)
- self.cardElec = devObj.otherConf.get('cardElec', 1)
- # 2.4 配置节点最大充电功率
- def _set_dev_max_power(self, portConfig):
- for port,conf in portConfig.items():
- setInfo = {'gateway_id': self.device.devNo,
- 'node_index': 0,
- 'port_index': int(port)-1,
- 'max_current': conf['max_current'],
- 'max_power': conf['max_max_power'],
- 'timeout': 5}
- devInfo = self._send_request("cmd/set-node-config", setInfo,"2")
- if devInfo['data']['code'] != 0:
- raise ServiceException({'result': 2, 'description': u'设备服务器返回错误,建议您重试,或者联系客服'})
- def _send_request(self, cmdPath, jsonPara, cmdKind):
- return send_request(self.device.devNo, self.device.devNo, cmdPath, jsonPara,cmdKind)
- # 2.6 获取节点最大充电功率 /2/cmd/get-node-config
- def _get_dev_max_power(self):
- portConfig = {}
- for i in range(12):
- setConf = {"gateway_id": self.device.devNo,
- "node_index": 0,
- "port_index": i}
- devInfo = self._send_request("cmd/get-node-config", setConf,"2")
- if devInfo['data']['code'] != 0:
- raise ServiceException({'result': 2, 'description': u'设备服务器返回错误,建议您重试,或者联系客服'})
- config = devInfo['data']['data']
- portConfig.update({str(i+1):{"max_current": config['max_current'], "max_max_power": config['max_power']}})
- return portConfig
- # 2.12 控制节点(充电柜/十二路/十路机/六路机/独立版) /3/cmd/control,
- def _start_device(self, jsonPara):
- return self._send_request("cmd/control", jsonPara,"3")
- # 2.14 设置系统参数 /3/cmd/set-node-config,
- def _set_dev_setting(self, setConf):
- setConf.update({'node_index': 0})
- devObj = Device.objects.get(devNo=self._device['devNo'])
- devObj.otherConf.update({
- 'billingType': setConf['chargeType'], # 前端直接传elec,time,power
- 'onceCard': int(float(setConf['onceCard'])),
- 'cardTime': int(setConf['cardTime']),
- 'cardElec': float(setConf['cardElec']),
- 'config_list': setConf['config_list'],
- })
- devObj.save()
- setConf.pop('chargeType')
- setConf.pop('onceCard')
- setConf.pop('cardTime')
- setConf.pop('cardElec')
- setConf.pop('config_list')
- setConf['charge_single_amount'] = int(setConf['charge_single_amount']) * 100
- setConf.update({
- 'charge_full_time_threshold': int(setConf['charge_full_timeout']),
- 'no_load_time_threshold': int(setConf['no_load_timeout'])
- })
- setConf.pop('charge_full_timeout')
- setConf.pop('no_load_timeout')
- devInfo = self._send_request('cmd/set-node-config', setConf, 3)
- if devInfo['data']['code'] != 0:
- raise ServiceException({'result': 2, 'description': u'设备服务器返回错误,建议您重试,或者联系客服'})
- return devInfo
- # 2.15 读取系统参数 /3/cmd/get-node-config,
- def get_dev_setting(self):
- setConf = {
- "gateway_id": self.device.devNo,
- "node_index": 0,
- }
- devInfo = self._send_request("cmd/get-node-config", setConf,3)
- if devInfo['data']['code'] != 0:
- raise ServiceException({'result': 2, 'description': u'设备服务器返回错误,建议您重试,或者联系客服'})
- config = devInfo['data']['data']
- if self.device.devTypeCode == Const.DEVICE_TYPE_CODE_CHANGING_BL_TWELVE:
- portConfig = self._get_dev_max_power()
- config.update({'portConfig':portConfig})
- config.update({
- 'chargeType': str(self.billingType),
- 'onceCard': self.onceCard,
- 'cardTime': self.cardTime,
- 'cardElec': self.cardElec,
- 'config_list': self.config_list,
- 'charge_full_timeout': config['charge_full_time_threshold'],
- 'no_load_timeout': config['no_load_time_threshold']
- })
- config['charge_single_amount'] = config['charge_single_amount'] * 0.01
- return config
- # 3.2 , 3.3 , 3.4 , 3.5 , 3.6 , 3.7 , 3.9
- @start_error_timer(
- missMessages=[u"请您选择合适的充电线路、电池类型信息", u"请您选择合适的充电线路", u"该端口正在使用中"])
- def start_device(self, package, openId, attachParas):
- if attachParas is None:
- raise ServiceException({'result': 2, 'description': u'请您选择合适的充电线路、电池类型信息'})
- if not attachParas.has_key('chargeIndex'):
- raise ServiceException({'result': 2, 'description': u'请您选择合适的充电线路'})
- # 端口从0开始
- port = int(attachParas['chargeIndex'])
- # attachParas['chargeIndex'] = port
- unit = package.get('unit', u'分钟')
- needTime, needElec = None, None
- jsonPara = {'gateway_id': self.device.devNo, 'node_index': 0, 'port_index': port-1, \
- 'switch_state': 1, 'control__type': 1, 'timeout': 10,'charge_energy': 0,\
- 'charge_time': 0}
- # 按时充电
- if self.billingType == 'time':
- if unit == u'秒':
- if int(package['time']) < 60:
- raise ServiceException({'result': 2, 'description': u'套餐的最小时间不能小于60秒'})
- needTime = int(float(package['time']) / 60.0)
- jsonPara.update({'charge_time': needTime, 'charge_type': 1})
- elif unit == u'分钟':
- needTime = int(float(package['time']))
- jsonPara.update({'charge_time': needTime, 'charge_type': 1})
- elif unit == u'小时':
- needTime = int(float(package['time']) * 60)
- jsonPara.update({'charge_time': needTime, 'charge_type': 1})
- elif unit == u'天':
- needTime = int(float(package['time']) * 60 * 24)
- jsonPara.update({'charge_time': needTime, 'charge_type': 1})
- else:
- raise ServiceException({'result': 2, 'description': u'运营商没有配置正确的套餐,请运营商配置正确的套餐'})
- # 按量充电
- elif self.billingType == 'elec':
- if unit == u'度':
- needElec = int(float(package['time']) * 1000) # 微度
- jsonPara.update({'charge_energy': needElec, 'charge_type': 2})
- else:
- raise ServiceException({'result': 2, 'description': u'运营商没有配置正确的套餐,请运营商配置正确的套餐'})
- # 按功率充电
- else:
- if not self.config_list:
- raise ServiceException(
- {'result': 2, 'description': u'运营商没有配置正确的分档功率,请运营商配置正确的分档功率'})
- """
- charge_power = {
- "money":"",
- "config_list":[{
- "power":"",
- "price":"",
- "time":"",
- }]
- }
- """
- needTime = int(float(package['time']))
- coins = int(float(package['coins']) * 100) # 单位为分
- jsonPara.update({'charge_power': {'money': coins, 'config_list': self.config_list}})
- jsonPara.update({'charge_type': 3})
- jsonPara.pop('charge_energy')
- jsonPara.pop('charge_time')
- devInfo = self._send_request("cmd/control", jsonPara,"3")
- if devInfo['data']['code'] != 0:
- raise ServiceException({'result': 2, 'description': u'设备服务器返回错误,建议您重试,或者联系客服'})
- if devInfo['rst'] == 0: # 成功
- newValue = {
- str(port): {
- 'status': Const.DEV_WORK_STATUS_WORKING,
- 'startTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- 'controlType': 1
- }
- }
- else:
- raise ServiceException({'result': 2, 'description': u'充电插座响应异常,请您稍后再试哦'})
- servicedInfo = {}
- if self.billingType == 'time':
- finishedTime = int(time.time()) + needTime * 60
- devInfo['needTime'] = needTime
- servicedInfo.update({'needTime': needTime, 'billingType': 'time'})
- elif self.billingType == 'elec':
- finishedTime = int(time.time()) + 60 * 60 * 10 # 设定10个小时,确实很难知道可以用多久结束
- devInfo['needElec'] = float(package['time'])
- servicedInfo.update({'needElec': float(package['time']), 'billingType': 'elec'})
- else:
- finishedTime = int(time.time()) + 60 * 60 * 10 # 设定10个小时,确实很难知道可以用多久结束
- servicedInfo.update({'billingType': 'power'})
- newValue[str(port)].update({'power': 10}) # 端口下的数据依赖心跳上报,但是心跳有时间间隔,这样查看服务的时候,因为功率是0,会认为已经结束,这里给一个初始值
- sequanceNo = devInfo['data']['data']['transaction_id']
- newValue[str(port)].update({'finishedTime': finishedTime,'sequanceNo':sequanceNo})
- Device.clear_port_control_cache(self._device['devNo'], port)
- Device.update_dev_control_cache(self._device['devNo'], newValue)
- devInfo['finishedTime'] = finishedTime
- devInfo['sequanceNo'] = sequanceNo
- devInfo['servicedInfo'] = servicedInfo
- return devInfo
- def stop_charging_port(self,port):
- portInfo = self.get_port_info(port)
- controlType = portInfo.get('controlType', 1)
- jsonPara = {'node_index': 0, 'port_index': port, 'charge_type': 3, 'switch_state': 0,'control__type':controlType}
- if self.billingType == 'power':
- jsonPara.update({'charge_power': {'money': 0,'config_list': self.config_list}})
- devInfo = self._send_request('cmd/control', jsonPara, 3)
- elif self.billingType == 'time':
- jsonPara.update({'charge_time': 0, 'charge_type': 1})
- devInfo = self._send_request('cmd/control', jsonPara, 3)
- else:
- jsonPara.update({'charge_energy': 0, 'charge_type': 2})
- devInfo = self._send_request('cmd/control', jsonPara, 3)
- if devInfo['data']['code'] != 0:
- raise ServiceException({'result': 2, 'description': u'设备服务器返回错误,建议您重试,或者联系客服'})
- if devInfo['rst'] == 0:
- Device.update_dev_control_cache(self._device['devNo'], {str(port): {'status': Const.DEV_WORK_STATUS_IDLE}})
- return True if devInfo['rst'] == 0 else False
- def get_port_status_from_dev(self):
- # 解析缓存
- return self.get_port_status()
- def get_port_info(self, port):
- '''
- 获取 端口的详细信息
- :param port:
- :return:
- '''
- port=int(port)
- devCache = Device.get_dev_control_cache(self.device.devNo)
- return devCache.get(str(port), dict())
- def get_port_status(self, force=False):
- '''
- 获取设备状态
- :param force:
- :return:
- '''
- statusDict = dict()
- devCache = Device.get_dev_control_cache(self._device['devNo'])
- if self.device.devTypeCode == Const.DEVICE_TYPE_CODE_CHANGING_BL_TWELVE:
- allPorts = devCache.get('allPorts', 12)
- else:
- allPorts = devCache.get('allPorts', 10)
- for portNum in range(allPorts):
- tempDict = devCache.get(str(portNum + 1), {})
- if 'status' in tempDict:
- statusDict[str(portNum + 1)] = {'status': tempDict.get('status')}
- if tempDict['status'] == 1:
- try:
- order = ConsumeRecord.get_consumed_records(sequanceNo=tempDict['sequanceNo'])[0]
- startTime = order.dateTimeAdded
- usedTime = (datetime.datetime.now() - startTime).seconds / 60
- statusDict[str(portNum + 1)].update({'usedTime':usedTime})
- except:
- pass
- elif 'isStart' in tempDict:
- if tempDict['isStart']:
- statusDict[str(portNum + 1)] = {'status': Const.DEV_WORK_STATUS_WORKING}
- else:
- statusDict[str(portNum + 1)] = {'status': Const.DEV_WORK_STATUS_IDLE}
- else:
- statusDict[str(portNum + 1)] = {'status': Const.DEV_WORK_STATUS_IDLE}
- Device.update_dev_control_cache(self._device['devNo'],statusDict)
- allPorts, usedPorts, usePorts = self.get_port_static_info(statusDict)
- Device.update_dev_control_cache(self._device['devNo'],
- {'allPorts': allPorts, 'usedPorts': usedPorts, 'usePorts': usePorts})
- return statusDict
- def set_device_function_param(self, request, lastSetConf):
- newConf = copy.deepcopy(request.POST)
- newConf.pop('logicalCode', None)
- if 'portConfig' in newConf:
- portConfig = newConf.pop('portConfig')
- self._set_dev_setting(newConf)
- if self.device.devTypeCode == Const.DEVICE_TYPE_CODE_CHANGING_BL_TWELVE:
- self._set_dev_max_power(portConfig)
- Device.invalid_device_cache(self.device.devNo)
- def active_deactive_port(self, port, active):
- port = int(port)-1
- if active:
- raise ServiceException({'result': 2, 'description': u'该设备不支持直接打开端口'})
- return self.stop_charging_port(port)
- def get_server_setting(self):
- refundProtectionTime = self.device.otherConf.get('refundProtectionTime',5)
- return refundProtectionTime
- def set_server_setting(self,payload):
- refundProtectionTime = int(payload['refundProtectionTime'])
- self.device.update_other_conf(refundProtectionTime=refundProtectionTime)
|