diff --git a/.gitignore b/.gitignore index ba74660..825f225 100644 --- a/.gitignore +++ b/.gitignore @@ -55,3 +55,6 @@ docs/_build/ # PyBuilder target/ + +#MyPy +.idea diff --git a/.travis.yml b/.travis.yml index 13478fa..5b909be 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,13 @@ sudo: false language: python python: - - "2.7" - - "3.6" +- "2.7" +- "3.6" install: - - "pip install -r requirements-dev.txt" - - "pip install -e ." +- pip install -r requirements-dev.txt +- pip install -e . script: - - mamba +- mamba +before_install: +- openssl aes-256-cbc -K $encrypted_b6b988576cbe_key -iv $encrypted_b6b988576cbe_iv + -in primestg/data/WS_DC.wsdl.enc -out primestg/data/WS_DC.wsdl -d diff --git a/primestg/__init__.py b/primestg/__init__.py index b74a6cb..11602c7 100644 --- a/primestg/__init__.py +++ b/primestg/__init__.py @@ -1,5 +1,14 @@ +import os + try: __version__ = __import__('pkg_resources') \ .get_distribution(__name__).version except Exception, e: __version__ = 'unknown' + +_ROOT = os.path.abspath(os.path.dirname(__file__)) + + +def get_data(path): + filename = isinstance(path, (list, tuple)) and path[0] or path + return os.path.join(_ROOT, 'data', filename) diff --git a/primestg/data/WS_DC.wsdl.enc b/primestg/data/WS_DC.wsdl.enc new file mode 100644 index 0000000..ce5a88c Binary files /dev/null and b/primestg/data/WS_DC.wsdl.enc differ diff --git a/primestg/service.py b/primestg/service.py new file mode 100644 index 0000000..c42af29 --- /dev/null +++ b/primestg/service.py @@ -0,0 +1,136 @@ +# -*- coding: UTF-8 -*- + +from zeep import Client +import primestg + + +class Service(object): + def __init__(self, fact_id, cnc_url, sync=True, source=None): + self.cnc_url = cnc_url + self.fact_id = fact_id + self.sync = sync + if not source: + self.source = 'DCF' # By default it doesn't look to the meter for data + else: + self.source = source + self.DC_service = self.create_service() + + def send(self, report_id, meters, date_from='', date_to=''): + + if self.sync: + results = self.DC_service.Request(self.fact_id, report_id, + date_from, date_to, meters, 2) + else: + results = self.DC_service.AsynchRequest(self.fact_id, report_id, + date_from, date_to, + meters, 2, self.source) + + return results + + def create_service(self): + binding = '{http://www.asais.fr/ns/Saturne/DC/ws}WS_DCSoap' + client = Client(wsdl=primestg.get_data('WS_DC.wsdl')) + client.set_ns_prefix(None, 'http://www.asais.fr/ns/Saturne/DC/ws') + return client.create_service(binding, self.cnc_url) + + def get_instant_data(self, meters): + """ + Asks for a S01 report to the specified meter. + :param meters: a meter_id + :return: an S01 report for the corresponding meter + """ + if isinstance(meters, list): + meters = ','.join(meters) + return self.send('S01', meters) + + def get_daily_incremental(self, meters, date_from, date_to): + """ + Asks for a S02 report to the specified meter. + :param meters: a meter_id + :return: an S02 report for the corresponding meter + """ + if isinstance(meters, list): + meters = ','.join(meters) + return self.send('S02', meters, date_from, date_to) + + def get_all_daily_incremental(self, date_from, date_to): + """ + Asks for a S02 report to all meters. + :return: an S02 report from every meter + """ + return self.send('S02', '', date_from, date_to) + + def get_monthly_billing(self, meters, date_from, date_to): + """ + Asks for a S04 report to the specified meter. + :param meters: a meter_id + :return: an S04 report for the corresponding meter + """ + if isinstance(meters, list): + meters = ','.join(meters) + return self.send('S04', meters, date_from, date_to) + + def get_all_monthly_billing(self, date_from, date_to): + """ + Asks for a S04 report to all meters. + :return: an S04 report from every meter + """ + return self.send('S04', '', date_from, date_to) + + def get_daily_absolute(self, meters, date_from, date_to): + """ + Asks for a S05 report to the specified meter. + :param meters: a meter_id + :return: an S05 report for the corresponding meter + """ + if isinstance(meters, list): + meters = ','.join(meters) + return self.send('S05', meters, date_from, date_to) + + def get_all_daily_absolute(self, date_from, date_to): + """ + Asks for a S05 report to all meters. + :return: an S05 report from every meter + """ + return self.send('S05', '', date_from, date_to) + + def get_meter_events(self, meters, date_from, date_to): + """ + Asks for a S09 report to the specified meter. + :param meters: a meter_id + :return: an S09 report for the corresponding meter + """ + if isinstance(meters, list): + meters = ','.join(meters) + return self.send('S09', meters, date_from, date_to) + + def get_all_meter_events(self, date_from, date_to): + """ + Asks for a S09 report to all meters. + :return: an S09 report from every meter + """ + return self.send('S09', '', date_from, date_to) + + def get_meter_parameters(self, meters, date_from, date_to): + """ + Asks for a S06 report to the specified meter. + :param meters: a meter_id + :return: an S06 report for the corresponding meter + """ + if isinstance(meters, list): + meters = ','.join(meters) + return self.send('S06', meters, date_from, date_to) + + def get_all_meter_parameters(self, date_from, date_to): + """ + Asks for a S06 report to all meters. + :return: an S06 report from every meter + """ + return self.send('S06', '', date_from, date_to) + + def get_concentrator_parameters(self, dc, date_from, date_to): + """ + Asks for a S12 report to the concentrator. + :return: an S12 report from the concentrator. + """ + return self.send('S12', dc, date_from, date_to) diff --git a/requirements-dev.txt b/requirements-dev.txt index 62f329f..2c08d92 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,3 +1,4 @@ pre-commit mamba expects +responses diff --git a/setup.py b/setup.py index 677e03e..9e704fe 100644 --- a/setup.py +++ b/setup.py @@ -3,14 +3,15 @@ setup( name='primestg', - version='1.2.0', + version='1.3.0', packages=find_packages(), url='https://github.com/gisce/primestg', license='GNU Affero General Public License v3', author='GISCE-TI, S.L.', author_email='devel@gisce.net', install_requires=[ - 'lxml' + 'lxml', + 'zeep' ], description='Prime STG-DC Interface Specification' ) diff --git a/spec/web_service_spec.py b/spec/web_service_spec.py new file mode 100644 index 0000000..ad974ed --- /dev/null +++ b/spec/web_service_spec.py @@ -0,0 +1,92 @@ +import responses +from primestg.service import Service +from zeep.exceptions import TransportError + +with description('Web services run'): + with before.all: + self.s = Service(1, 'http://cct.gisce.lan:8080/') + + with it('asking for S02 report with mocked connection'): + with responses.RequestsMock() as rsps: + rsps.add(responses.POST, 'http://cct.gisce.lan:8080/', + body='{"error": "expected S02 error"}', status=404) + try: + resp = self.s.get_daily_incremental('ZIV0040318130', + '20170610010000', + '20170611000000') + except TransportError as te: + assert 'expected S02 error' in te.message + + with it('asking for S02 report for all meters with mocked connection'): + with responses.RequestsMock() as rsps: + rsps.add(responses.POST, 'http://cct.gisce.lan:8080/', + body='{"error": "expected S02 error"}', status=404) + try: + resp = self.s.get_all_daily_incremental('20170610010000', + '20170611000000') + except TransportError as te: + assert 'expected S02 error' in te.message + + with it('asking for S04 report with mocked connection'): + with responses.RequestsMock() as rsps: + rsps.add(responses.POST, 'http://cct.gisce.lan:8080/', + body='{"error": "expected S04 error"}', status=404) + try: + resp = self.s.get_monthly_billing('ZIV0040318130', + '20170600010000', + '20170631000000') + except TransportError as te: + assert 'expected S04 error' in te.message + + with it('asking for S04 report for all meters with mocked connection'): + with responses.RequestsMock() as rsps: + rsps.add(responses.POST, 'http://cct.gisce.lan:8080/', + body='{"error": "expected S04 error"}', status=404) + try: + resp = self.s.get_all_monthly_billing('20170600010000', + '20170631000000') + except TransportError as te: + assert 'expected S04 error' in te.message + + with it('asking for S05 report with mocked connection'): + with responses.RequestsMock() as rsps: + rsps.add(responses.POST, 'http://cct.gisce.lan:8080/', + body='{"error": "expected S05 error"}', status=404) + try: + resp = self.s.get_daily_absolute('ZIV0040318130', + '20170609010000', + '20170611000000') + except TransportError as te: + assert 'expected S05 error' in te.message + + with it('asking for S05 report for all meters with mocked connection'): + with responses.RequestsMock() as rsps: + rsps.add(responses.POST, 'http://cct.gisce.lan:8080/', + body='{"error": "expected S05 error"}', status=404) + try: + resp = self.s.get_all_daily_absolute('20170609010000', + '20170611000000') + except TransportError as te: + assert 'expected S05 error' in te.message + + with it('asking for S09 report with mocked connection'): + with responses.RequestsMock() as rsps: + rsps.add(responses.POST, 'http://cct.gisce.lan:8080/', + body='{"error": "expected S09 error"}', status=404) + try: + resp = self.s.get_meter_events('ZIV0040318130', + '20170609010000', + '20170611000000') + except TransportError as te: + assert 'expected S09 error' in te.message + + with it('asking for S06 report with mocked connection'): + with responses.RequestsMock() as rsps: + rsps.add(responses.POST, 'http://cct.gisce.lan:8080/', + body='{"error": "expected S06 error"}', status=404) + try: + resp = self.s.get_meter_parameters('ZIV0040318130', + '20170609010000', + '20170611000000') + except TransportError as te: + assert 'expected S06 error' in te.message