123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364 |
- # -*- coding: utf-8 -*-
- # !/usr/bin/env python
- import base64
- import datetime
- import json
- import logging
- import urllib2
- import uuid
- import pika
- from Crypto import Random
- from Crypto.Cipher import PKCS1_v1_5
- from Crypto.PublicKey import RSA
- from mongoengine import DoesNotExist, StringField, IntField, DictField, DateTimeField
- from six.moves.urllib import parse
- from apilib.utils_datetime import to_datetime
- from apps.web.constant import Const
- from apps.web.core.db import Searchable
- from apps.web.dealer.models import Dealer
- from apps.web.device.models import Part, FaultRecord, Device
- from apps.web.exceptions import UserServerException
- logger = logging.getLogger(__name__)
- class ZhejiangRSA(object):
- # 本地产生的publicKey,北向会过来拿这个key,用于加密数据传递给我们,我们用私钥解密
- publicKeyHear = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAueN4TXcy27K/HoArURK5\n4NSNvWQhqpTk1s9bVlrSANwctascPBQlLWKf3HyL6+yxxgJ4oKZk00qagceSu85E\n1SG/opmvjPOQfIGwi/y0yuFWRM+x2DtfVxtH/4YMIMHq2DAmKY/MBj1RtPEz89oF\nsqJRHbZxe1aV5cDCRUJWgeSaJWbphrCRnko+PDGKIqc/5+9/zE1QRaTMEmifkjEg\nj/9+bOGZYYH+acgdeJe9jMUtPMytmCD/ovqIBH9ntAKWhFGzGqzjxkPnKQ/JOqX/\nMEV63R/CQAA/y2dypm1Ce2FXS6d6L7HlPs26YkXw6/Q1pzkbKSrnempbZUGc+5KT\noQIDAQAB\n-----END PUBLIC KEY-----"
- # 用于解密北向过来的数据
- privateKeyHear = '-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAueN4TXcy27K/HoArURK54NSNvWQhqpTk1s9bVlrSANwctasc\nPBQlLWKf3HyL6+yxxgJ4oKZk00qagceSu85E1SG/opmvjPOQfIGwi/y0yuFWRM+x\n2DtfVxtH/4YMIMHq2DAmKY/MBj1RtPEz89oFsqJRHbZxe1aV5cDCRUJWgeSaJWbp\nhrCRnko+PDGKIqc/5+9/zE1QRaTMEmifkjEgj/9+bOGZYYH+acgdeJe9jMUtPMyt\nmCD/ovqIBH9ntAKWhFGzGqzjxkPnKQ/JOqX/MEV63R/CQAA/y2dypm1Ce2FXS6d6\nL7HlPs26YkXw6/Q1pzkbKSrnempbZUGc+5KToQIDAQABAoIBAGLPtMJQ63r3gDph\nXSVCdAY8Vn/nOzIm5aH+JYo4ysrkNmqnY2HYP47pjxqwJdyqPDGKXL7g1FWwoYL9\nKFWmptY4k1qGoVemnRZiBgvTr/LsZ2Q6l0ne/aYa/WGpysaa7hAvQAn1wzlJ3SX2\n1Wv5Z+/18nJ96cLrWtD/bwVL5xoyFmgz36PgUbZAx0r9bAz630MFQkPWF33/ts1P\nzkImLTi8WAJQy8xDN6DisgUpj+GFjLn21IAXfMvg57wZaUVL8OPaqe5W1Q11ud27\nAkzBh6vVDrbx5g6vVno4MLopw61o7kiAH0i8E9g/IuTj6BHN4BV5MmL7CvZrxgIy\nYHksf5UCgYEAxbrULv03fm5aAIO4GYXJ2s6q9ZhN9EbPdAumzoeIyGZNLiSmRKcF\n9KDorWEwv9K+IPDdcV39xFtJQLDL27TVIgyeSKZV5KohQ7z58WeV0PWMQ7L2FSvd\nUOJQQAeZbk5H4GmJ3b/rMckWHH77hey6nrcY9PJKr69Nk2Z/krnWg88CgYEA8KtP\nu8QbZE+C6c9HZXCoIZL0iNfLCvwc57RJpGg5E/ChlxwN0D/Fi9DWEbcvGvr/+Dd6\nwgtE2C7GoP5RZb/8dgjJJZ72gfozlseH9TSdrEh1uQcMD8PMtkV+Qs58fFDtI/PB\np0bXopPy+/w9h2pwquEYh6d+9foMnmNbMVjHnY8CgYBc7DsxRgDhYtzbJwvKuswt\nDzjaqFPiO7DcuWkP4DQQ8brNt52H3/J1j3UpneY6D8EYW/nFgEV1FO1tAGkdfHM5\nSDLOs5TkHGv7mIDhyStoAy2C10S8mFuu2lyaarfZVeKDfTW0R7AxOm4wwCBWRPVD\nB4sr+f3NaJYNcnr7qmg8kwKBgQCw4rhvoOshBu+JOTeYbvyj8IaaLUCmijYUdoXJ\nuHB7H1kk3xGoBbcD1DICQ0jz45dOsDghdnbbDUYf/cuFpV3AwyRT6knzrhlMsMpU\nhp98iKU9oNhUnexP6zOplmoYVMJ2sima8I58h5EHc5Ulei3k6hxFV+4Qi//KSew0\nkLPmMQKBgF360CEMz7IAR3RokcXP554tRiUmoIcTn3io8+N4cLX9x6MTdA5Bh2Pq\nsNSfwk7mki38eQD3+kmEa+DmhK5URbGemc4xK8lau5t010A2KB9MUPC5O0NglJdZ\nzBR6Hzr3sriFmRCQKxGQ8ae+Ggkn/5rfc6GEbmRg0dyG98680VGI\n-----END RSA PRIVATE KEY-----'
- # 从北向接口那边得到的publicKey,用于加密数据后,发给北向
- publicKeyFromNorth = ''
- @staticmethod
- def make_rsa_key():
- rsaObj = RSA.generate(2048)
- privateKeyHear = rsaObj.exportKey()
- publicKeyHear = rsaObj.publickey().exportKey()
- ZhejiangRSA.privateKeyHear = privateKeyHear
- ZhejiangRSA.publicKeyHear = publicKeyHear
- @staticmethod
- def get_north_publicKey(ipPort):
- try:
- backInfo = send_url_request_to_north('http://%s/api/getPublicKey' % ipPort, 'GET')
- if backInfo['code'] != 0:
- return None
- ZhejiangRSA.publicKeyFromNorth = '-----BEGIN PUBLIC KEY-----\n' + backInfo['data'][
- 'publicKey'] + '\n-----END PUBLIC KEY-----'
- except Exception as e:
- logger.exception(e)
- return None
- return ZhejiangRSA.publicKeyFromNorth
- @staticmethod
- def decrypt(data):
- try:
- privateKey = RSA.importKey(ZhejiangRSA.privateKeyHear)
- cipher = PKCS1_v1_5.new(privateKey)
- random_generator = Random.new().read
- text = cipher.decrypt(base64.b64decode(data), random_generator)
- except Exception as e:
- logger.exception(e)
- return None
- return text
- class ZhejiangAddressType(Searchable):
- value = StringField(verbose_name = "地址类型编码", unique = True)
- label = StringField(verbose_name = "地址名称", default = "")
- typeId = StringField(verbose_name = "南向地址类型编码", default = "")
- typeName = StringField(verbose_name = "typeName", default = "")
- meta = {"collection": "ZhejiangAddressType", "db_alias": "default"}
- codeDict = {}
- @staticmethod
- def get_typeId(value):
- if not ZhejiangAddressType.codeDict:
- objs = ZhejiangAddressType.objects.all()
- for obj in objs:
- ZhejiangAddressType.codeDict[obj.value] = {'typeId': obj.typeId, 'typeName': obj.typeName}
- return str(ZhejiangAddressType.codeDict.get(value, {}).get('typeId', '999'))
- class ZhejiangZone(Searchable):
- code = StringField(verbose_name = "地址类型编码", unique = True)
- name = StringField(verbose_name = "northDistinctId", default = "")
- parent = StringField(verbose_name = "parent", default = "")
- level = IntField(verbose_name = "level", default = "")
- meta = {
- "collection": "ZhejiangZone",
- "db_alias": "default",
- "index": ["name"]
- }
- distinctDict = {}
- @staticmethod
- def get_distinct_id(area, address):
- defaultId = "330000"
- parent = ZhejiangZone.objects.filter(name = area).first()
- if not parent:
- return defaultId
- children = ZhejiangZone.objects.filter(name = address).first()
- if not children or children.parent != parent.code:
- return parent.code
- return children.code
- # if not ZhejiangZone.distinctDict:
- # objs = ZhejiangZone.objects.filter(level=3).all()
- # for obj in objs:
- # ZhejiangZone.distinctDict[obj.name] = obj.code
- #
- # parentCode = ZhejiangZone.distinctDict.get(area)
- # if not parentCode:
- # return "330000"
- # else:
- # z = ZhejiangZone.objects.filter(parent=parentCode, name=address)
- # if not z:
- # return parentCode
- # else:
- # return z.code
- class ZhejiangNorther(Searchable):
- """
- 一个代理商可以开一个接口
- """
- usernameFromHear = StringField(verbose_name = "用于登录我们平台", default = "")
- passwordFromHear = StringField(verbose_name = "password", default = "")
- tokenId = StringField(verbose_name = "tokenId 就是agentId", default = "")
- mqDomain = StringField(verbose_name = "mqDomain", default = "http://36.26.79.155:8120/")
- mqUser = StringField(verbose_name = "mqUser", default = "mqUser")
- mqPassword = StringField(verbose_name = "mqPassword", default = "mq258456")
- host = StringField(verbose_name = "host", default = "")
- port = IntField(verbose_name = "port", default = 5672)
- routingKey = StringField(verbose_name = "routingKey", default = '')
- exchange = DictField(verbose_name = "exchange", default = {})
- usernameFromNorth = StringField(verbose_name = "用于登录消防平台", default = "")
- passwordFromNorth = StringField(verbose_name = "password", default = "")
- serviceCodeFromNorth = StringField(verbose_name = "平台分配的服务编码", default = "")
- fetchedMQTime = DateTimeField(verbose_name = "获取MQ的时间,平台意见是每天要获取一次",
- default = to_datetime('2000-01-01 00:00:00'))
- northPort = StringField(verbose_name = "北向IP地址以及端口",
- default = "36.26.79.155:8120") # 测试和交付的端口可能不一样,每一家的也可能不一样,所以需要配置
- meta = {"collection": "ZhejiangNorther", "db_alias": "default"}
- def get_mq_info(self):
- # # obj.make_rsa_key()
- northPublicKey = ZhejiangRSA.get_north_publicKey(self.northPort)
- publicKey = RSA.importKey(northPublicKey)
- cipher = PKCS1_v1_5.new(publicKey)
- enPassword = base64.b64encode(cipher.encrypt(str(self.mqPassword)))
- result = send_url_request_to_north('http://%s/api/getMqInfo' % self.northPort, #
- method = 'POST',
- isNeedResponse = True,
- username = self.mqUser,
- password = enPassword)
- if result['code'] != 0:
- raise UnableToGetPublicKey('get publicKey from north error=%s' % (result['message'],))
- self.host = result['data']['mqInfo']['host']
- self.port = result['data']['mqInfo']['port']
- self.routingKey = result['data']['mqInfo']['routingKey']
- self.exchange = result['data']['mqInfo']['exchange']
- self.usernameFromNorth = result['data']['mqInfo']['username']
- self.passwordFromNorth = result['data']['mqInfo']['password']
- self.fetchedMQTime = datetime.datetime.now()
- self.save()
- return self
- def send_event_to_north(self, eventInfo):
- if not self.usernameFromNorth:
- self.get_mq_info()
- nowTime = datetime.datetime.now()
- if (nowTime - self.fetchedMQTime).days > 1:
- self.get_mq_info()
- credentials = pika.PlainCredentials(self.usernameFromNorth, self.passwordFromNorth)
- connection = pika.BlockingConnection(pika.ConnectionParameters(self.host, self.port, '/', credentials))
- channel = connection.channel()
- eventInfo.update({'producerCode': self.serviceCodeFromNorth})
- channel.basic_publish(exchange = self.exchange['chargingPile'],
- routing_key = '%s.5.pubinfo' % self.serviceCodeFromNorth,
- body = json.dumps(eventInfo))
- def send_url_request_to_north(url, method = "POST", isNeedResponse = True, **kwargs):
- paras = {}
- paras.update(kwargs)
- if method == 'POST':
- req = urllib2.Request(url = url, data = parse.urlencode(paras))
- else:
- if paras:
- getParas = parse.urlencode(paras)
- url = url + '?' + getParas
- req = urllib2.Request(url = url)
- response = urllib2.urlopen(req, timeout = 15)
- if isNeedResponse:
- return json.loads(response.read())
- return None
- def handler_event_to_zhejiang(alarm_id):
- """
- 报警时间处理结果反馈
- :param alarm_id:
- :return:
- """
- try:
- record = FaultRecord.objects.get(id = alarm_id)
- except DoesNotExist:
- return
- device = Device.get_dev(record.imei)
- dealer = Dealer.objects.filter(id = record.dealerId).first()
- if device is None:
- logger.info("can not find device, devNo is {}".format(record.imei))
- return
- if dealer is None:
- logger.info("can not find dealer dealer is {}".format(record.dealerId))
- try:
- norther = ZhejiangNorther.objects.get(tokenId = dealer.agentId)
- company = Company.objects.get(ownerId = str(dealer.id))
- except Exception as e:
- return
- devTypeCode = device.get("devType", dict()).get("code")
- if (not Const.ZHEJIANG_EVENT_TYPE_DICT.has_key(devTypeCode)) or \
- (not Const.ZHEJIANG_EVENT_TYPE_DICT[devTypeCode].has_key(record.faultCode)):
- return
- eventType = Const.ZHEJIANG_EVENT_TYPE_DICT[devTypeCode][record.faultCode]
- try:
- part = Part.objects.get(logicalCode = device.get('logicalCode'), partNo = str(record.portNo))
- except Exception as e:
- logger.exception(e)
- return
- event = {
- 'handlerEventId': str(uuid.uuid4()),
- 'alarmEventId': record.alarmEventId,
- 'deviceId': record.logicalCode,
- 'buildingId': device.get("groupId"),
- 'happenTime': str(record.createdTime)[:19],
- 'alarmContent': {u'详细描述': record.description},
- 'alarmType': eventType,
- 'partsId': str(part.id),
- 'producerCode': company.unifiedSocialCreditCode,
- "handleContent": record.dealedDetail,
- "handleType": "1",
- "handleName": dealer.nickname,
- "handlePhone": dealer.username,
- "handleTime": str(record.dealedTime)[:19]
- }
- norther.send_event_to_north(event)
- def send_event_to_zhejiang(dealer, device, eventInfo, partId = None):
- try:
- norther = ZhejiangNorther.objects.get(tokenId = dealer.agentId)
- company = Company.objects.get(ownerId = str(dealer.id))
- except Exception as e:
- return
- devTypeCode = device['devType']['code']
- if (not Const.ZHEJIANG_EVENT_TYPE_DICT.has_key(devTypeCode)) or \
- (not Const.ZHEJIANG_EVENT_TYPE_DICT[devTypeCode].has_key(eventInfo['reasonCode'])):
- return
- eventType = Const.ZHEJIANG_EVENT_TYPE_DICT[devTypeCode][eventInfo['reasonCode']]
- try:
- if not partId:
- part = Part.objects.get(logicalCode = device.logicalCode, partNo = str(eventInfo['port']))
- else:
- part = Part.objects.get(id = partId)
- except Exception as e:
- logger.exception(e)
- return
- nowDate = datetime.datetime.now()
- alarmEventId = str(uuid.uuid4())
- event = {
- 'alarmEventId': alarmEventId,
- 'deviceId': device.logicalCode,
- 'buildingId': device.groupId,
- 'happenTime': nowDate.strftime(Const.DATETIME_FMT),
- 'alarmContent': {u'详细描述': eventInfo['reason']},
- 'alarmType': eventType,
- 'partsId': str(part.id),
- 'producerCode': company.unifiedSocialCreditCode
- }
- # 存储记录 存储的时候存储端口号,然后取出发送处置结果的时候 通过端口号查找partId
- try:
- FaultRecord.record_xf(
- logicalCode = device.logicalCode,
- port = eventInfo["port"],
- description = eventInfo["reason"],
- faultCode = eventInfo["reasonCode"],
- groupId = device.groupId,
- createdTime = nowDate,
- alarmEventId = alarmEventId
- )
- except Exception as e:
- logger.error(e)
- return
- norther.send_event_to_north(event)
- class Company(Searchable):
- ownerId = StringField(verbose_name = "ownerId", unique = True)
- agentId = StringField(verbose_name = "agentId", default = "")
- name = StringField(verbose_name = "name", default = "")
- code = StringField(verbose_name = "code", default = "")
- unifiedSocialCreditCode = StringField(verbose_name = '统一社会信用编码', default = '')
- address = StringField(verbose_name = "address", default = "")
- contactName = StringField(verbose_name = "contactName", default = "")
- telephone = StringField(verbose_name = "telephone", default = "")
- manufacturer = StringField(verbose_name = "manufacturer", default = "充电桩厂家")
- dateTimeAdded = DateTimeField(default = datetime.datetime.now, verbose_name = '添加进来的时间')
- dateTimeUpdated = DateTimeField(default = datetime.datetime.now, verbose_name = '更新时间')
- meta = {"collection": "Company", "db_alias": "default"}
- class UnableToGetPublicKey(UserServerException):
- pass
|