passerelle-grandlyon-iodas/grandlyon_iodas/models.py

243 lines
13 KiB
Python

import requests
import json
import hashlib
from suds.transport.http import HttpAuthenticated
from suds.client import Client
from suds.transport import Reply
import suds.sudsobject
from django.db import models
from django.utils.encoding import force_bytes, force_text
from django.utils.translation import ugettext_lazy as _
from django.core.cache import cache
from passerelle.base.models import BaseResource
from passerelle.utils.api import endpoint
from passerelle.utils.jsonresponse import APIError
from datetime import datetime
import dateutil.relativedelta
def sudsobject_to_dict(sudsobject):
out = {}
for key, value in suds.sudsobject.asdict(sudsobject).items():
if hasattr(value, '__keylist__'):
out[key] = sudsobject_to_dict(value)
elif isinstance(value, list):
out[key] = []
for item in value:
if hasattr(item, '__keylist__'):
out[key].append(sudsobject_to_dict(item))
else:
out[key].append(item)
else:
out[key] = value
return out
class grandlyonIodas(BaseResource):
token_url = models.URLField(_('Token URL'), max_length=256)
token_authorization = models.CharField(_('Token Authorization'), max_length=128)
wsdl_url = models.CharField(_('WSDL URL'), max_length=256) # not URLField, it can be file://
verify_cert = models.BooleanField(default=True,
verbose_name=_('Check HTTPS Certificate validity'))
category = _('Business Process Connectors')
class Meta:
verbose_name = 'Connecteur IODAS Grand Lyon'
def get_token(self, renew=False):
cache_key = 'iodas-%s-token' % self.id
if not renew:
token = cache.get(cache_key)
if token:
return token
headers = {'Authorization': 'Basic %s' % self.token_authorization}
resp = self.requests.post(self.token_url, headers=headers,
data={'grant_type': 'client_credentials'},
verify=self.verify_cert).json()
token = '%s %s' % (resp.get('token_type'), resp.get('access_token'))
timeout = int(resp.get('expires_in'))
cache.set(cache_key, token, timeout)
self.logger.debug('new token: %s (timeout %ss)', token, timeout)
return token
def get_client(self):
class Transport(HttpAuthenticated):
def __init__(self, instance):
self.instance = instance
HttpAuthenticated.__init__(self)
def send(self, request):
#request.message = request.message.replace("contentType", "xm:contentType")
request.headers['Authorization'] = self.instance.get_token()
resp = self.instance.requests.post(request.url, data=request.message,
headers=request.headers,
verify=self.instance.verify_cert)
if resp.status_code == 401:
# ask for a new token, and retry
request.headers['Authorization'] = self.instance.get_token(renew=True)
resp = self.instance.requests.post(request.url, data=request.message,
headers=request.headers,
verify=self.instance.verify_cert)
return Reply(resp.status_code, resp.headers, resp.content)
return Client(url=self.wsdl_url, transport=Transport(self))
@endpoint(perm='can_access')
def getProcedures(self, request, nom, pren, datenais, dpap, typepro):
# Params in the order required by the WSDL from stambia
resp = self.get_client().service.ODA_getProceduresSIH(dpap, typepro, datenais, nom, pren)
data = sudsobject_to_dict(resp)
# Counts procedures to get the last procedure
nbProc = (len(data['procedures']['procedures']['procedure']) - 1) if 'procedures' in data else ''
# recupere la liste des droits en cours de toutes les procedures d'un individu
droits = []
if 'procedures' in data :
for procedure in data['procedures']['procedures']['procedure'] :
for etape in procedure['etapes']['etape'] :
if 'taches' in etape :
for tache in etape['taches']['tache'] :
if tache['idtypetache'] == 2 and datetime.strptime(tache['datearret'], "%d/%m/%Y") > datetime.now():
for nb in [3,6] :
deltafindroit = nb if (datetime.strptime(tache['datearret'], "%d/%m/%Y") - dateutil.relativedelta.relativedelta(months=nb)) == datetime.now().replace(hour=0, minute=0, second=0, microsecond=0) else 0
droits.append({"libl":tache['produit']['libl'], "dateproposition":tache['dateproposition'], "datearret":tache['datearret'], "dateeffet":tache['dateeffet'], "deltafindroit":deltafindroit})
return {'hash': force_text(hashlib.sha224(force_bytes(json.dumps(data)).hexdigest()),
'libl': data['procedures']['procedures']['procedure'][nbProc]['libl'] if 'procedures' in data else '',
'etapes': sorted(data['procedures']['procedures']['procedure'][nbProc]['etapes']['etape'], key=lambda x: x['id'], reverse=True) if 'procedures' in data else '',
'droits': droits,
'recevabilite': data['procedures']['procedures']['procedure'][nbProc]['recevabilite'] if 'procedures' in data and 'recevabilite' in data['procedures']['procedures']['procedure'][nbProc] else '',
'found': 1 if 'procedures' in data else 0}
@endpoint(perm='can_access')
def getProceduresPA(self, request, nom, pren, datenais, typepro):
# Params in the order required by the WSDL from stambia
resp = self.get_client().service.ODA_getProceduresPA(typepro, datenais, nom, pren)
data = sudsobject_to_dict(resp)
# Counts procedures to get the last procedure
#nbProc = (len(data['procedurespa']['procedurespa']['procedurepa']) - 1) if 'procedurespa' in data else ''
procedures = []
nb = 0
#print >> open('/home/grandlyon/marln/debug.test', 'a+'), "***** *****"
for proc in data['procedurespa']['procedurespa']['procedurepa'] :
#print >> open('/home/grandlyon/marln/debug.test', 'a+'), foo
nb += 1
if (nb < len(data['procedurespa']['procedurespa']['procedurepa']) and proc['libl'] != data['procedurespa']['procedurespa']['procedurepa'][nb]['libl']) or nb == len(data['procedurespa']['procedurespa']['procedurepa']) :
test = proc['libl']
procedures.append(proc)
#print >> open('/home/grandlyon/marln/debug.test', 'a+'), self.get_client().service.ODA_getProceduresPA()
return {'hash': force_text(hashlib.sha224(force_bytes(json.dumps(data))).hexdigest()),
#'libl': data['procedurespa']['procedurespa']['procedurepa'][nbProc]['libl'] if 'procedurespa' in data else '',
#'procedures': data['procedurespa']['procedurespa']['procedurepa'][nbProc] if 'procedurespa' in data else '',
#'procedures': data['procedurespa']['procedurespa']['procedurepa'] if 'procedurespa' in data else '',
'procedures': procedures,
#'etapes': sorted(data['procedurespa']['procedurespa']['procedurepa'][nbProc]['etapes']['etape'], key=lambda x: x['id'], reverse=True) if 'procedures' in data else '',
'found': 1 if 'procedurespa' in data else 0}
@endpoint(perm='can_access')
def getTest(self, request, container):
import urllib2
import base64
import dateutil.parser
from collections import defaultdict
from xml.etree import cElementTree as ET
# Convert XML to dict
def etree_to_dict(t):
d = {t.tag: {} if t.attrib else None}
children = list(t)
if children:
dd = defaultdict(list)
for dc in map(etree_to_dict, children):
for k, v in dc.items():
dd[k.replace('{http://www.opengroup.org/xsd/omi/1.0/}','').replace('{http://www.opengroup.org/xsd/odf/1.0/}','')].append(v)
d = {t.tag: {k: v[0] if len(v) == 1 else v for k, v in dd.items()}}
if t.attrib:
d[t.tag].update((k, v) for k, v in t.attrib.items())
if t.text:
text = t.text.strip()
if children or t.attrib:
if text:
d[t.tag]['text'] = text
else:
d[t.tag] = text
return d
url = 'https://biotope-omi.alpha.grandlyon.com'
# Get container and sensor from csv file with ID from data.grandlyon.com
reqContainer = requests.get('https://passerelle.guichet-dev.grandlyon.com/csvdatasource/biotope/data?q='+container)
container = reqContainer.json()
# Get container
containerDict={}
if container['data'][0]['id'] and container['data'][0]['id'] != '' and len(container['data'][0]['id']) > 14 :
payload='<omiEnvelope xmlns="http://www.opengroup.org/xsd/omi/1.0/" version="1.0" ttl="0">'
payload+='<read msgformat="odf">'
payload+='<msg>'
payload+='<Objects xmlns="http://www.opengroup.org/xsd/odf/1.0/">'
payload+='<Object>'
payload+='<id>Organization:Mineris-V1.0.0</id>'
payload+='<Object>'
payload+='<id>Deployment:Bottle_Bank</id>'
payload+='<Object>'
payload+='<id>'+container['data'][0]['id']+'</id>'
payload+='</Object>'
payload+='</Object>'
payload+='</Object>'
payload+='</Objects>'
payload+='</msg>'
payload+='</read>'
payload+='</omiEnvelope>'
head = {"Content-type": "application/xml"}
req = requests.post(url, headers=head, data=payload)
# XML result to dict
containerRes = ET.XML(req.text.encode('utf8'))
containerDict = etree_to_dict(containerRes)
# Get sensor
sensorDict={}
if container['data'][0]['sensor'] and container['data'][0]['sensor'] != '' :
payloadSensor='<omiEnvelope xmlns="http://www.opengroup.org/xsd/omi/1.0/" version="1.0" ttl="0">'
payloadSensor+='<read msgformat="odf">'
payloadSensor+='<msg>'
payloadSensor+='<Objects xmlns="http://www.opengroup.org/xsd/odf/1.0/">'
payloadSensor+='<Object>'
payloadSensor+='<id>Organization:SigrenEa-V1.1.0</id>'
payloadSensor+='<Object>'
payloadSensor+='<id>Deployment:Bottle_Bank:1edd171c-5f2d-11e8-a6ab-10604b7fb2e7</id>'
payloadSensor+='<Object>'
payloadSensor+='<id>'+container['data'][0]['sensor']+'</id>'
payloadSensor+='</Object>'
payloadSensor+='</Object>'
payloadSensor+='</Object>'
payloadSensor+='</Objects>'
payloadSensor+='</msg>'
payloadSensor+='</read>'
payloadSensor+='</omiEnvelope>'
headSensor = {"Content-type": "application/xml"}
reqSensor = requests.post(url, headers=headSensor, data=payloadSensor)
# XML result to dict
sensRes = ET.XML(reqSensor.text.encode('utf8'))
sensorDict = etree_to_dict(sensRes)
# Build result dict
result = {}
if containerDict :
# Container info
for item in containerDict["{http://www.opengroup.org/xsd/omi/1.0/}omiEnvelope"]["response"]["result"]["msg"]["Objects"]["Object"]["Object"]["Object"]["InfoItem"] :
result.update({ item["name"].replace('schema:','') : dateutil.parser.parse(item["value"]["text"]).strftime("%d/%m/%Y") if "date" in item["name"] else item["value"]["text"] })
if sensorDict :
# Id Container
result.update({'idContainer':sensorDict["{http://www.opengroup.org/xsd/omi/1.0/}omiEnvelope"]["response"]["result"]["msg"]["Objects"]["Object"]["Object"]["Object"]["Object"]["Object"]['id']})
# Sensor info
for item in sensorDict["{http://www.opengroup.org/xsd/omi/1.0/}omiEnvelope"]["response"]["result"]["msg"]["Objects"]["Object"]["Object"]["Object"]["Object"]["Object"]["InfoItem"] :
result.update({ item["name"].replace('schema:','').replace('FIWARE:','') : item["value"]["text"] })
for subItem in sensorDict["{http://www.opengroup.org/xsd/omi/1.0/}omiEnvelope"]["response"]["result"]["msg"]["Objects"]["Object"]["Object"]["Object"]["Object"]["Object"]["Object"] :
if 'InfoItem' in subItem :
result.update({subItem['id'].replace('Container:',''):subItem['InfoItem']})
return result