123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477 |
- # -*- coding: utf-8 -*-
- # !/usr/bin/env python
- import datetime
- import logging
- import uuid
- import requests
- from django.conf import settings
- from mongoengine import StringField, BooleanField
- from typing import TYPE_CHECKING
- from apps.web.core.db import Searchable
- from apps.web.agent.models import Agent
- from apps.web.common.models import District
- if TYPE_CHECKING:
- from apps.web.dealer.models import Dealer
- from apps.web.device.models import DeviceDict, FaultRecord
- logger = logging.getLogger(__name__)
- class LiangXiXiaoFang(object):
- # ipPort = "lxzhyd.idea-sf.com:82/safe"
- ipPort = "114.216.202.169:82/safe" # 测试使用ip
- faultMap = {
- "01": u"温度故障",
- "02": u"烟感故障",
- "03": u"插座功率过载故障",
- "04": u"充电器故障",
- "05": u"电池故障",
- "06": u"设备功率过载",
- "07": u"网络故障"
- }
- devNos = [
- ['869300033348255', # 尚城公寓
- '869300033348370', ],
- ['868575025762834', # 金科观天下
- '868575025758550',
- '868575025756588', ],
- ['869300039898691', ], # 水榭新大陆
- ['869300039913326', ], # 观天下
- ['869300039911593', # 东方水榭
- '860344042976259', ],
- ['860344042561788', # 东方王谢洋房
- '860344046870920', ],
- ['868575025757818', # 水榭七号楼
- '868575025738909', ],
- ['868575025757776', # 水榭2号楼
- '868575025738842',
- '868575025752900',
- '868575025746233',
- '868575025766181', ],
- ['868575025747926', # 观天下 (助力充电桩)
- '868575025756844',
- '868575025754179',
- '868575025757735',
- '868575025739063',
- '868575025758410',
- '868575025738677',
- '868575025753593', ],
- ['869300033357249', # 尚城绿园
- '869300033346705',
- '869300033369673',
- '869300033347687',
- '869300033353941',
- '869300033354360',
- '869300033357579',
- '869300033383831',
- '869300033357637',
- '869300033356480', ]
- ]
- # # 测试的devNOs
- # devNos = [
- # ["862285036747669"]
- # ]
- PLOTFORM = "XCKJ"
- BELOBG_TO = u"商品房"
- FAULT_STATUS = 3
- FREE_STATUS = 0
- @staticmethod
- def gen_uuid():
- u = str(uuid.uuid4())
- return "".join(u.split('-'))
- @staticmethod
- def send_to_xf_ini(dev, districtInfo):
- province, city, block = districtInfo.split(" ")
- data = {
- "platform": "XCKJ",
- "province": province,
- "city": city,
- "block": block,
- "chargerList": []
- }
- setupDate = datetime.datetime.strftime(datetime.datetime.now(), "%Y-%m-%d %H:%M:%S")
- # 物业相关信息暂时不需要上传
- devData = {
- "id": dev['logicalCode'],
- "chargerName": u"%s 充电桩 -%s" % (dev.get('groupInfo', {}).get("address", ""), dev.get("groupNumber")),
- "belongTo": LiangXiXiaoFang.BELOBG_TO,
- "lng": dev["lng"],
- "lat": dev["lat"],
- "supplierName": u"信长科技",
- "supplierPerson": dev['supplierPerson'],
- "supplierTel": dev["supplierTel"],
- "street": dev.get('groupInfo', {}).get("address", ""),
- "status": LiangXiXiaoFang.FAULT_STATUS if dev["isFault"] else LiangXiXiaoFang.FREE_STATUS,
- "chargeNum": len(dev['pileList']),
- "isOnline": int(not dev["isFault"]),
- "setupDate": setupDate,
- "pileList": dev["pileList"]
- }
- data['chargerList'].append(devData)
- url = "http://%s/charger/device.json" % LiangXiXiaoFang.ipPort
- try:
- result = LiangXiXiaoFang.send_request_to_xf(url, [data])
- except Exception as e:
- logger.exception(e)
- if result.get("msgCode") != '0':
- logger.info("send to xiaofang deviceinfo filed, the reason is %s" % result.get("msg", ""))
- @staticmethod
- def send_to_xf_fault(dev, faultCode, faultContent, pileNum = None):
- """ 判断需要上报的设备 """
- devNos = [item.devNo for item in LiangXiXiaoFangDev.objects(needSend = True).all()]
- if dev['devNo'] not in devNos:
- return
- plotform = LiangXiXiaoFang.PLOTFORM
- faultname = LiangXiXiaoFang.faultMap.get(faultCode, "")
- districtInfo = dev.get("districtInfo", "")
- pilenum = pileNum or 0
- _id = LiangXiXiaoFang.gen_uuid()
- province, city, block = districtInfo.split(" ")
- data = [{
- "province": province,
- "city": city,
- "block": block,
- "platform": plotform,
- "realTimeAlarmList": [{
- "id": _id,
- "chargerId": dev['logicalCode'],
- "chargerName": u"%s 充电桩 -%s" % (dev["groupAddr"], dev.get("groupNumber")),
- "pileNum": int(pilenum),
- "faultName": faultname,
- "faultContent": faultContent,
- "createTime": datetime.datetime.strftime(datetime.datetime.now(), "%Y-%m-%d %H:%M:%S")
- }]
- }]
- url = "http://%s/charger/faultList.json" % LiangXiXiaoFang.ipPort
- try:
- result = LiangXiXiaoFang.send_request_to_xf(url, data)
- except Exception as e:
- logger.exception(e)
- if result.get("msgCode") != '0':
- logger.info("send to xiaofang fault filed, the reason is %s" % result.get("msg", ""))
- # 上报处理信息
- LiangXiXiaoFang.send_to_xf_handle(_id)
- @staticmethod
- def send_to_xf_handle(_id):
- data = [{
- "id": _id,
- "platform": "XCKJ",
- "handleMemo": u"故障已经处理",
- "handleTime": datetime.datetime.strftime(datetime.datetime.now(), "%Y-%m-%d %H:%M:%S"),
- "handleName": u"徐应金"
- }]
- url = "http://%s/charger/faultHandlerList.json" % LiangXiXiaoFang.ipPort
- try:
- result = LiangXiXiaoFang.send_request_to_xf(url, data)
- except Exception as e:
- logger.exception(e)
- if result.get("msgCode") != '0':
- logger.info("send to xiaofang handle filed, the reason is %s" % result.get("msg", ""))
- @staticmethod
- def send_request_to_xf(url, data):
- res = requests.post(url, json = data, timeout = 15)
- if res.status_code == 200:
- return res.json()
- return {}
- class LiangXiXiaoFangDev(Searchable):
- devNo = StringField(verbose_name = "设备编号", min_length = 1, unique = True)
- needSend = BooleanField(verbose_name = "是否需要上报", default = True)
- meta = {
- "collection": "LiangXiXiaoFangDev",
- "db_alias": "default"
- }
- class ToXiaoFang(object):
- """
- 经销商需要配置属性 特性 LXXF
- """
- FAULT_MAP = {
- "01": u"温度故障",
- "02": u"烟感故障",
- "03": u"插座功率过载故障",
- "04": u"充电器故障",
- "05": u"电池故障",
- "06": u"设备功率过载",
- "07": u"网络故障"
- }
- # 对不同的设备的告警故障进行处理
- FAULT_CODE_MAP = {
- # TODO zjl 新电川 记得合并到100210
- "100252": {
- "41": "02",
- "47": "01",
- "01": "07",
- "02": "03",
- "03": "05"
- },
- "100210": {
- "01": "07",
- "02": "03",
- "03": "05",
- "41": "02"
- },
- "100206": {
- "B3": "03",
- "B4": "02",
- "B8": "01",
- "B7": "06",
- "B2": "01",
- "B201": "01",
- "B202": "02",
- "B203": "06",
- "1603": "03",
- "160B": "04"
- },
- "100202": {
- "B3": "03",
- "B4": "02",
- "B8": "01",
- "B7": "06",
- "B201": "01",
- "B202": "02",
- "B203": "06",
- "1603": "03",
- "160B": "04"
- }
- }
- PLATFORM_MAP = {
- u'全城': u'PQC',
- u'粤万通': u'YWT',
- u'雪影': u'XY'
- }
- SUPPORT_ADDRESS = u"梁溪区"
- def __init__(self, device, platformName = None):
- # type: (DeviceDict, str) -> None
- """
- :param device: 设备
- :param platformName: 平台
- """
- dealer = device.owner # type: Dealer
- # 获取平台代码
- if not platformName or platformName not in ToXiaoFang.PLATFORM_MAP.values():
- agent = Agent.objects.get(id = dealer.agentId)
- for _name, _key in ToXiaoFang.PLATFORM_MAP.items():
- if _name in agent.productName:
- platformName = _key
- break
- else:
- platformName = ""
- self._platform = platformName
- self._device = device
- self._dealer = dealer
- # 是否支持
- dealerSupport = "LXXF" in dealer.features
- devTypeSupport = self._device.devTypeCode in ToXiaoFang.FAULT_CODE_MAP
- deviceSupport = District.get_district(self._device.group['districtId']).endswith(ToXiaoFang.SUPPORT_ADDRESS)
- self._support = dealerSupport and devTypeSupport and deviceSupport
- if settings.MY_DOMAIN == "develop.5tao5ai.com":
- self.ipPort = "http://lxzhyd.idea-sf.com:82/safe"
- else:
- self.ipPort = "https://lxzhyd.idea-sf.com/safe"
- def send_request_to_xf(self, url, data):
- res = requests.post(url, json = data, timeout = 15)
- if res.status_code != 200:
- logger.info(
- "dev {} send to liangxi {} data = {} error, status code = {}".format(self._device.devNo, url, data,
- res.status_code))
- return
- responseData = res.json()
- logger.info(
- "dev {} send to liangxi {} data = {}, response = {}".format(self._device.devNo, url, data, responseData))
- @staticmethod
- def get_fault(devTypeCode, faultCode):
- """
- 获取相应的code
- :param devTypeCode:
- :param faultCode:
- :return:
- """
- typeMap = ToXiaoFang.FAULT_CODE_MAP.get(devTypeCode)
- code = typeMap.get(faultCode, "01")
- return ToXiaoFang.FAULT_MAP.get(code)
- def send_to_xf_ini(self):
- """
- 初始化设备
- :return:
- """
- if not self._support:
- return
- logger.info("device <{}> send to liangxi xiaofang init".format(self._device.devNo))
- from apps.web.core.helpers import ActionDeviceBuilder
- # 端口状态
- pileList = list()
- try:
- box = ActionDeviceBuilder.create_action_device(self._device)
- portStatus = box.get_port_status() or dict()
- except Exception as e:
- logger.exception("send liangxi xf error, device={}, e={}".format(self._device, e))
- return
- devStatus = 1
- for _portStr, _portInfo in portStatus.items():
- pileList.append({
- "num": int(_portStr),
- # 梁溪消防的定义状态数量值 比我们系统的 多 1
- "status": int(_portInfo.get("status", 0)) + 1
- })
- if _portInfo.get("status", 0) == 1:
- devStatus = 2
- # 设备的状态
- chargerList = {
- "id": self._device.logicalCode,
- "chargerName": u"%s 充电桩 -%s" % (self._device.group.get("address", ""), self._device.get("groupNumber")),
- "belongTo": u"商品房",
- "lng": self._device.lng,
- "lat": self._device.lat,
- "supplierName": self._dealer.nickname,
- "street": self._device.group.get("address", ""),
- "status": devStatus,
- "chargeNum": len(pileList),
- "isOnline": int(self._device.online),
- "setupDate": datetime.datetime.now().strftime("%Y-%m-%d"),
- "pileList": pileList
- }
- # 整状态
- group = self._device.group
- districtInfo = District.get_district(group['districtId'])
- province, city, block = districtInfo.split()
- data = {
- "platform": self._platform,
- "province": province,
- "city": city,
- "block": block,
- "chargerList": [chargerList]
- }
- url = "{}/charger/device.json".format(self.ipPort)
- try:
- self.send_request_to_xf(url, [data])
- except Exception as e:
- logger.error("device {} send to xiaofang init error = {}".format(self._device.devNo, e))
- return
- def send_to_xf_fault(self, faultRecord): # type:(FaultRecord) -> None
- """
- 故障告警到消防局
- :param faultRecord:
- :return:
- """
- if not self._support:
- return
- logger.info("device <{}> send to liangxi xiaofang fault <{}>".format(self._device.devNo, faultRecord.id))
- realTimeAlarm = {
- "id": str(faultRecord.id),
- "chargerId": self._device.logicalCode,
- "chargerName": u"%s 充电桩 -%s" % (self._device.group.get("address", ""), self._device.get("groupNumber")),
- "pileNum": int(faultRecord.portNo),
- "faultName": ToXiaoFang.get_fault(self._device.devTypeCode, faultRecord.detail.get("errorCode", "")),
- "faultContent": faultRecord.description,
- "createTime": faultRecord.createdTime.strftime("%Y-%m-%d %H:%M:%S")
- }
- group = self._device.group
- districtInfo = District.get_district(group['districtId'])
- province, city, block = districtInfo.split()
- data = {
- "platform": self._platform,
- "province": province,
- "city": city,
- "block": block,
- "realTimeAlarmList": [realTimeAlarm]
- }
- url = "{}/charger/faultList.json".format(self.ipPort)
- try:
- self.send_request_to_xf(url, [data])
- except Exception as e:
- logger.error("device {} send to xiaofang fault {} error = {}".format(self._device.devNo, faultRecord.id, e))
- return
- def send_to_xf_handle(self, faultRecord): # type:(FaultRecord) -> None
- """
- 发送处理的结束的消息
- :param faultRecord:
- :return:
- """
- if not self._support:
- return
- logger.info("device <{}> send to liangxi xiaofang handle <{}>".format(self._device.devNo, faultRecord.id))
- faultHandler = {
- "id": str(faultRecord.id),
- "platform": self._platform,
- "handleMemo": faultRecord.dealedDetail or u"故障已处理",
- "handleTime": faultRecord.dealedTime.strftime("%Y-%m-%d %H:%M:%S"),
- "handlerTel": self._dealer.username,
- "handleType": "1",
- "handlerName": self._dealer.nickname
- }
- url = "{}/charger/faultHandlerList.json".format(self.ipPort)
- try:
- self.send_request_to_xf(url, [faultHandler])
- except Exception as e:
- logger.error(
- "device {} send to xiaofang handle {} error = {}".format(self._device.devNo, faultRecord.id, e))
- return
|