From 8c2485d70f5fe9743be05d6d7b9f72b339e6707c Mon Sep 17 00:00:00 2001 From: Hans Erik van Elburg Date: Tue, 24 Dec 2019 00:57:44 +0100 Subject: [PATCH 1/8] added file tail reader --- dsmr_parser/clients/filereader.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/dsmr_parser/clients/filereader.py b/dsmr_parser/clients/filereader.py index e6eeb59..12164f2 100644 --- a/dsmr_parser/clients/filereader.py +++ b/dsmr_parser/clients/filereader.py @@ -1,5 +1,6 @@ import logging import fileinput +import tailer from dsmr_parser.clients.telegram_buffer import TelegramBuffer from dsmr_parser.exceptions import ParseError, InvalidChecksumError @@ -120,3 +121,31 @@ class FileInputReader(object): logger.warning(str(e)) except ParseError as e: logger.error('Failed to parse telegram: %s', e) + + +class FileTailReader(object): + + def __init__(self, file, telegram_specification): + self._file = file + self.telegram_parser = TelegramParser(telegram_specification) + self.telegram_buffer = TelegramBuffer() + self.telegram_specification = telegram_specification + + def read_as_object(self): + """ + Read complete DSMR telegram's from a files tail and return a Telegram object. + :rtype: generator + """ + with open(self._file,"rb") as file_handle: + for data in tailer.follow(file_handle): + str = data.decode() + self.telegram_buffer.append(str) + + for telegram in self.telegram_buffer.get_all(): + try: + yield Telegram(telegram, self.telegram_parser, self.telegram_specification) + except dsmr_parser.exceptions.InvalidChecksumError as e: + logger.warning(str(e)) + except dsmr_parser.exceptions.ParseError as e: + logger.error('Failed to parse telegram: %s', e) + From e6625df4a7ff66da22cab1c74e80f393a9e4cd02 Mon Sep 17 00:00:00 2001 From: Hans Erik van Elburg Date: Fri, 27 Dec 2019 15:18:35 +0100 Subject: [PATCH 2/8] add documentation to FileTailReader --- dsmr_parser/clients/filereader.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/dsmr_parser/clients/filereader.py b/dsmr_parser/clients/filereader.py index 12164f2..3869a8a 100644 --- a/dsmr_parser/clients/filereader.py +++ b/dsmr_parser/clients/filereader.py @@ -124,6 +124,25 @@ class FileInputReader(object): class FileTailReader(object): + """ + Filereader to read and parse raw telegram strings from the tail of a + given file and instantiate Telegram objects for each read telegram. + Usage python script "syphon_smartmeter_readings_stdin.py": + from dsmr_parser import telegram_specifications + from dsmr_parser.clients.filereader import FileTailReader + + if __name__== "__main__": + + infile = '/data/smartmeter/readings.txt' + + filetail_reader = FileTailReader( + file = infile, + telegram_specification = telegram_specifications.V5 + ) + + for telegram in filetail_reader.read_as_object(): + print(telegram) + """ def __init__(self, file, telegram_specification): self._file = file From 0675a6e2e7af1f626d90abc3cf37341ae26233dd Mon Sep 17 00:00:00 2001 From: Hans Erik van Elburg Date: Fri, 27 Dec 2019 16:22:10 +0100 Subject: [PATCH 3/8] add tailer dependency --- setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index e1f0139..0c6015d 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,8 @@ setup( 'pyserial>=3,<4', 'pyserial-asyncio<1', 'pytz', - 'PyCRC>=1.2,<2' + 'PyCRC>=1.2,<2', + 'Tailer==0.4.1' ], entry_points={ 'console_scripts': ['dsmr_console=dsmr_parser.__main__:console'] From fee3f696c46a062c1ca717773372e777bc797d0e Mon Sep 17 00:00:00 2001 From: Hans Erik van Elburg Date: Sun, 2 Feb 2020 17:26:47 +0100 Subject: [PATCH 4/8] merged upstream 0.18 version and resolved conflict --- CHANGELOG.rst | 8 ++++++++ dsmr_parser/parsers.py | 27 +++++++++++++++++++++++++-- setup.py | 3 +-- tox.ini | 1 - 4 files changed, 34 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index babab7c..0fda0e3 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,14 @@ Change Log ---------- +**0.18** (2020-01-28) + +- PyCRC replacement (`pull request #48 `_). + +**0.17** (2019-12-21) + +- Add a true telegram object (`pull request #40 `_). + **0.16** (2019-12-21) - Add support for Belgian and Smarty meters (`pull request #44 `_). diff --git a/dsmr_parser/parsers.py b/dsmr_parser/parsers.py index 4b415f6..4609287 100644 --- a/dsmr_parser/parsers.py +++ b/dsmr_parser/parsers.py @@ -1,7 +1,7 @@ import logging import re -from PyCRC.CRC16 import CRC16 +from ctypes import c_ushort from dsmr_parser.objects import MBusObject, CosemObject, Telegram from dsmr_parser.exceptions import ParseError, InvalidChecksumError @@ -79,7 +79,7 @@ class TelegramParser(object): 'incomplete. The checksum and/or content values are missing.' ) - calculated_crc = CRC16().calculate(checksum_contents.group(0)) + calculated_crc = TelegramParser.crc16(checksum_contents.group(0)) expected_crc = int(checksum_hex.group(0), base=16) if calculated_crc != expected_crc: @@ -91,6 +91,29 @@ class TelegramParser(object): ) ) + @staticmethod + def crc16(telegram): + crc16_tab = [] + + for i in range(0, 256): + crc = c_ushort(i).value + for j in range(0, 8): + if (crc & 0x0001): + crc = c_ushort(crc >> 1).value ^ 0xA001 + else: + crc = c_ushort(crc >> 1).value + crc16_tab.append(hex(crc)) + + crcValue = 0x0000 + + for c in telegram: + d = ord(c) + tmp = crcValue ^ d + rotated = c_ushort(crcValue >> 8).value + crcValue = rotated ^ int(crc16_tab[(tmp & 0x00ff)], 0) + + return crcValue + class DSMRObjectParser(object): """ diff --git a/setup.py b/setup.py index 0c6015d..beb8e57 100644 --- a/setup.py +++ b/setup.py @@ -6,13 +6,12 @@ setup( author='Nigel Dokter', author_email='nigel@nldr.net', url='https://github.com/ndokter/dsmr_parser', - version='0.17', + version='0.19', packages=find_packages(), install_requires=[ 'pyserial>=3,<4', 'pyserial-asyncio<1', 'pytz', - 'PyCRC>=1.2,<2', 'Tailer==0.4.1' ], entry_points={ diff --git a/tox.ini b/tox.ini index 23fe214..3efa213 100644 --- a/tox.ini +++ b/tox.ini @@ -9,7 +9,6 @@ deps= pytest-asyncio pytest-catchlog pytest-mock - PyCRC commands= py.test --cov=dsmr_parser test {posargs} pylama dsmr_parser test From b6537678a70961ecabfc618273a46f5bc1dabd15 Mon Sep 17 00:00:00 2001 From: Hans Erik van Elburg Date: Sun, 2 Feb 2020 22:12:25 +0100 Subject: [PATCH 5/8] cleaned up based on pylama complaints / pinpointed to coverage version 4.5.4 as next version is incompatible --- dsmr_parser/clients/filereader.py | 11 +++-- dsmr_parser/clients/protocol.py | 1 + dsmr_parser/obis_name_mapping.py | 80 +++++++++++++++---------------- dsmr_parser/objects.py | 3 +- dsmr_parser/parsers.py | 2 +- test/experiment_telegram.py | 10 +--- test/test_telegram.py | 23 +++------ tox.ini | 12 +++-- 8 files changed, 67 insertions(+), 75 deletions(-) diff --git a/dsmr_parser/clients/filereader.py b/dsmr_parser/clients/filereader.py index 3869a8a..061eda7 100644 --- a/dsmr_parser/clients/filereader.py +++ b/dsmr_parser/clients/filereader.py @@ -9,6 +9,7 @@ from dsmr_parser.parsers import TelegramParser logger = logging.getLogger(__name__) + class FileReader(object): """ Filereader to read and parse raw telegram strings from a file and instantiate Telegram objects @@ -60,7 +61,7 @@ class FileReader(object): Read complete DSMR telegram's from a file and return a Telegram object. :rtype: generator """ - with open(self._file,"rb") as file_handle: + with open(self._file, "rb") as file_handle: while True: data = file_handle.readline() str = data.decode() @@ -74,6 +75,7 @@ class FileReader(object): except ParseError as e: logger.error('Failed to parse telegram: %s', e) + class FileInputReader(object): """ Filereader to read and parse raw telegram strings from stdin or files specified at the commandline @@ -155,7 +157,7 @@ class FileTailReader(object): Read complete DSMR telegram's from a files tail and return a Telegram object. :rtype: generator """ - with open(self._file,"rb") as file_handle: + with open(self._file, "rb") as file_handle: for data in tailer.follow(file_handle): str = data.decode() self.telegram_buffer.append(str) @@ -163,8 +165,7 @@ class FileTailReader(object): for telegram in self.telegram_buffer.get_all(): try: yield Telegram(telegram, self.telegram_parser, self.telegram_specification) - except dsmr_parser.exceptions.InvalidChecksumError as e: + except InvalidChecksumError as e: logger.warning(str(e)) - except dsmr_parser.exceptions.ParseError as e: + except ParseError as e: logger.error('Failed to parse telegram: %s', e) - diff --git a/dsmr_parser/clients/protocol.py b/dsmr_parser/clients/protocol.py index 7e8e260..e43e230 100644 --- a/dsmr_parser/clients/protocol.py +++ b/dsmr_parser/clients/protocol.py @@ -59,6 +59,7 @@ def create_tcp_dsmr_reader(host, port, dsmr_version, conn = loop.create_connection(protocol, host, port) return conn + class DSMRProtocol(asyncio.Protocol): """Assemble and handle incoming data into complete DSM telegrams.""" diff --git a/dsmr_parser/obis_name_mapping.py b/dsmr_parser/obis_name_mapping.py index 8f72654..0401f5e 100644 --- a/dsmr_parser/obis_name_mapping.py +++ b/dsmr_parser/obis_name_mapping.py @@ -10,45 +10,45 @@ This module contains a mapping of obis references to names. EN = { obis.P1_MESSAGE_HEADER: 'P1_MESSAGE_HEADER', obis.P1_MESSAGE_TIMESTAMP: 'P1_MESSAGE_TIMESTAMP', - obis.ELECTRICITY_IMPORTED_TOTAL : 'ELECTRICITY_IMPORTED_TOTAL', - obis.ELECTRICITY_USED_TARIFF_1 : 'ELECTRICITY_USED_TARIFF_1', - obis.ELECTRICITY_USED_TARIFF_2 : 'ELECTRICITY_USED_TARIFF_2', - obis.ELECTRICITY_DELIVERED_TARIFF_1 : 'ELECTRICITY_DELIVERED_TARIFF_1', - obis.ELECTRICITY_DELIVERED_TARIFF_2 : 'ELECTRICITY_DELIVERED_TARIFF_2', - obis.ELECTRICITY_ACTIVE_TARIFF : 'ELECTRICITY_ACTIVE_TARIFF', - obis.EQUIPMENT_IDENTIFIER : 'EQUIPMENT_IDENTIFIER', - obis.CURRENT_ELECTRICITY_USAGE : 'CURRENT_ELECTRICITY_USAGE', - obis.CURRENT_ELECTRICITY_DELIVERY : 'CURRENT_ELECTRICITY_DELIVERY', - obis.LONG_POWER_FAILURE_COUNT : 'LONG_POWER_FAILURE_COUNT', - obis.SHORT_POWER_FAILURE_COUNT : 'SHORT_POWER_FAILURE_COUNT', - obis.POWER_EVENT_FAILURE_LOG : 'POWER_EVENT_FAILURE_LOG', - obis.VOLTAGE_SAG_L1_COUNT : 'VOLTAGE_SAG_L1_COUNT', - obis.VOLTAGE_SAG_L2_COUNT : 'VOLTAGE_SAG_L2_COUNT', - obis.VOLTAGE_SAG_L3_COUNT : 'VOLTAGE_SAG_L3_COUNT', - obis.VOLTAGE_SWELL_L1_COUNT : 'VOLTAGE_SWELL_L1_COUNT', - obis.VOLTAGE_SWELL_L2_COUNT : 'VOLTAGE_SWELL_L2_COUNT', - obis.VOLTAGE_SWELL_L3_COUNT : 'VOLTAGE_SWELL_L3_COUNT', - obis.INSTANTANEOUS_VOLTAGE_L1 : 'INSTANTANEOUS_VOLTAGE_L1', - obis.INSTANTANEOUS_VOLTAGE_L2 : 'INSTANTANEOUS_VOLTAGE_L2', - obis.INSTANTANEOUS_VOLTAGE_L3 : 'INSTANTANEOUS_VOLTAGE_L3', - obis.INSTANTANEOUS_CURRENT_L1 : 'INSTANTANEOUS_CURRENT_L1', - obis.INSTANTANEOUS_CURRENT_L2 : 'INSTANTANEOUS_CURRENT_L2', - obis.INSTANTANEOUS_CURRENT_L3 : 'INSTANTANEOUS_CURRENT_L3', - obis.TEXT_MESSAGE_CODE : 'TEXT_MESSAGE_CODE', - obis.TEXT_MESSAGE : 'TEXT_MESSAGE', - obis.DEVICE_TYPE : 'DEVICE_TYPE', - obis.INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE : 'INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE', - obis.INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE : 'INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE', - obis.INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE : 'INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE', - obis.INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE : 'INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE', - obis.INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE : 'INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE', - obis.INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE : 'INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE', - obis.EQUIPMENT_IDENTIFIER_GAS : 'EQUIPMENT_IDENTIFIER_GAS', - obis.HOURLY_GAS_METER_READING : 'HOURLY_GAS_METER_READING', - obis.GAS_METER_READING : 'GAS_METER_READING', - obis.ACTUAL_TRESHOLD_ELECTRICITY : 'ACTUAL_TRESHOLD_ELECTRICITY', - obis.ACTUAL_SWITCH_POSITION : 'ACTUAL_SWITCH_POSITION', - obis.VALVE_POSITION_GAS : 'VALVE_POSITION_GAS' + obis.ELECTRICITY_IMPORTED_TOTAL: 'ELECTRICITY_IMPORTED_TOTAL', + obis.ELECTRICITY_USED_TARIFF_1: 'ELECTRICITY_USED_TARIFF_1', + obis.ELECTRICITY_USED_TARIFF_2: 'ELECTRICITY_USED_TARIFF_2', + obis.ELECTRICITY_DELIVERED_TARIFF_1: 'ELECTRICITY_DELIVERED_TARIFF_1', + obis.ELECTRICITY_DELIVERED_TARIFF_2: 'ELECTRICITY_DELIVERED_TARIFF_2', + obis.ELECTRICITY_ACTIVE_TARIFF: 'ELECTRICITY_ACTIVE_TARIFF', + obis.EQUIPMENT_IDENTIFIER: 'EQUIPMENT_IDENTIFIER', + obis.CURRENT_ELECTRICITY_USAGE: 'CURRENT_ELECTRICITY_USAGE', + obis.CURRENT_ELECTRICITY_DELIVERY: 'CURRENT_ELECTRICITY_DELIVERY', + obis.LONG_POWER_FAILURE_COUNT: 'LONG_POWER_FAILURE_COUNT', + obis.SHORT_POWER_FAILURE_COUNT: 'SHORT_POWER_FAILURE_COUNT', + obis.POWER_EVENT_FAILURE_LOG: 'POWER_EVENT_FAILURE_LOG', + obis.VOLTAGE_SAG_L1_COUNT: 'VOLTAGE_SAG_L1_COUNT', + obis.VOLTAGE_SAG_L2_COUNT: 'VOLTAGE_SAG_L2_COUNT', + obis.VOLTAGE_SAG_L3_COUNT: 'VOLTAGE_SAG_L3_COUNT', + obis.VOLTAGE_SWELL_L1_COUNT: 'VOLTAGE_SWELL_L1_COUNT', + obis.VOLTAGE_SWELL_L2_COUNT: 'VOLTAGE_SWELL_L2_COUNT', + obis.VOLTAGE_SWELL_L3_COUNT: 'VOLTAGE_SWELL_L3_COUNT', + obis.INSTANTANEOUS_VOLTAGE_L1: 'INSTANTANEOUS_VOLTAGE_L1', + obis.INSTANTANEOUS_VOLTAGE_L2: 'INSTANTANEOUS_VOLTAGE_L2', + obis.INSTANTANEOUS_VOLTAGE_L3: 'INSTANTANEOUS_VOLTAGE_L3', + obis.INSTANTANEOUS_CURRENT_L1: 'INSTANTANEOUS_CURRENT_L1', + obis.INSTANTANEOUS_CURRENT_L2: 'INSTANTANEOUS_CURRENT_L2', + obis.INSTANTANEOUS_CURRENT_L3: 'INSTANTANEOUS_CURRENT_L3', + obis.TEXT_MESSAGE_CODE: 'TEXT_MESSAGE_CODE', + obis.TEXT_MESSAGE: 'TEXT_MESSAGE', + obis.DEVICE_TYPE: 'DEVICE_TYPE', + obis.INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE: 'INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE', + obis.INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE: 'INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE', + obis.INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE: 'INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE', + obis.INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE: 'INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE', + obis.INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE: 'INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE', + obis.INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE: 'INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE', + obis.EQUIPMENT_IDENTIFIER_GAS: 'EQUIPMENT_IDENTIFIER_GAS', + obis.HOURLY_GAS_METER_READING: 'HOURLY_GAS_METER_READING', + obis.GAS_METER_READING: 'GAS_METER_READING', + obis.ACTUAL_TRESHOLD_ELECTRICITY: 'ACTUAL_TRESHOLD_ELECTRICITY', + obis.ACTUAL_SWITCH_POSITION: 'ACTUAL_SWITCH_POSITION', + obis.VALVE_POSITION_GAS: 'VALVE_POSITION_GAS' } -REVERSE_EN = dict([ (v,k) for k,v in EN.items()]) \ No newline at end of file +REVERSE_EN = dict([(v, k) for k, v in EN.items()]) diff --git a/dsmr_parser/objects.py b/dsmr_parser/objects.py index 07d576d..e313cd5 100644 --- a/dsmr_parser/objects.py +++ b/dsmr_parser/objects.py @@ -1,5 +1,6 @@ import dsmr_parser.obis_name_mapping + class Telegram(object): """ Container for raw and parsed telegram data. @@ -47,7 +48,7 @@ class Telegram(object): def __str__(self): output = "" for attr, value in self: - output += "{}: \t {} \t[{}]\n".format(attr,str(value.value),str(value.unit)) + output += "{}: \t {} \t[{}]\n".format(attr, str(value.value), str(value.unit)) return output diff --git a/dsmr_parser/parsers.py b/dsmr_parser/parsers.py index 4609287..d9aeb5a 100644 --- a/dsmr_parser/parsers.py +++ b/dsmr_parser/parsers.py @@ -3,7 +3,7 @@ import re from ctypes import c_ushort -from dsmr_parser.objects import MBusObject, CosemObject, Telegram +from dsmr_parser.objects import MBusObject, CosemObject from dsmr_parser.exceptions import ParseError, InvalidChecksumError logger = logging.getLogger(__name__) diff --git a/test/experiment_telegram.py b/test/experiment_telegram.py index 2649f51..2892346 100644 --- a/test/experiment_telegram.py +++ b/test/experiment_telegram.py @@ -1,14 +1,8 @@ -from decimal import Decimal -import datetime -import unittest -import pytz -from dsmr_parser import obis_references as obis from dsmr_parser import telegram_specifications -from dsmr_parser.exceptions import InvalidChecksumError, ParseError -from dsmr_parser.objects import CosemObject, MBusObject, Telegram +from dsmr_parser.objects import Telegram from dsmr_parser.parsers import TelegramParser from example_telegrams import TELEGRAM_V4_2 parser = TelegramParser(telegram_specifications.V4) telegram = Telegram(TELEGRAM_V4_2, parser, telegram_specifications.V4) -print(telegram) \ No newline at end of file +print(telegram) diff --git a/test/test_telegram.py b/test/test_telegram.py index d0e1042..ea85704 100644 --- a/test/test_telegram.py +++ b/test/test_telegram.py @@ -1,30 +1,21 @@ -from decimal import Decimal - -import datetime import unittest -import pytz - -from dsmr_parser import obis_references as obis from dsmr_parser import telegram_specifications -from dsmr_parser.exceptions import InvalidChecksumError, ParseError -from dsmr_parser.objects import CosemObject, MBusObject, Telegram +from dsmr_parser.objects import CosemObject +from dsmr_parser.objects import Telegram from dsmr_parser.parsers import TelegramParser from test.example_telegrams import TELEGRAM_V4_2 + class TelegramTest(unittest.TestCase): """ Test instantiation of Telegram object """ def test_instantiate(self): parser = TelegramParser(telegram_specifications.V4) - #result = parser.parse(TELEGRAM_V4_2) telegram = Telegram(TELEGRAM_V4_2, parser, telegram_specifications.V4) - - - # P1_MESSAGE_HEADER (1-3:0.2.8) - #assert isinstance(result[obis.P1_MESSAGE_HEADER], CosemObject) - #assert result[obis.P1_MESSAGE_HEADER].unit is None - #assert isinstance(result[obis.P1_MESSAGE_HEADER].value, str) - #assert result[obis.P1_MESSAGE_HEADER].value == '50' + testitem = telegram.P1_MESSAGE_HEADER + assert isinstance(testitem, CosemObject) + assert testitem.unit is None + assert testitem.value == '42' diff --git a/tox.ini b/tox.ini index 3efa213..6b0f152 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,6 @@ [tox] -envlist = py34,py35,p36 +envlist = py34,py35,py36,py37 +requires = coverage<=4.5.4 [testenv] deps= @@ -14,10 +15,13 @@ commands= pylama dsmr_parser test [pylama:dsmr_parser/clients/__init__.py] -ignore = W0611,W0605 +ignore = W0611 + +[pylama:dsmr_parser/parsers.py] +ignore = W605 [pylama:pylint] -max_line_length = 100 +max_line_length = 120 [pylama:pycodestyle] -max_line_length = 100 +max_line_length = 120 From 5d88284d8d4dbb6bda1b5d484c6cb5869ae9ad19 Mon Sep 17 00:00:00 2001 From: Hans Erik van Elburg Date: Sun, 2 Feb 2020 22:34:17 +0100 Subject: [PATCH 6/8] remove requires property again --- tox.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/tox.ini b/tox.ini index 6b0f152..a3e12f0 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,5 @@ [tox] envlist = py34,py35,py36,py37 -requires = coverage<=4.5.4 [testenv] deps= From a7b0b03391f4ed82f670abda49276e3d45518bbf Mon Sep 17 00:00:00 2001 From: lowdef Date: Sun, 2 Feb 2020 22:52:06 +0100 Subject: [PATCH 7/8] remove conflicting entries --- setup.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index beb8e57..a33f5a4 100644 --- a/setup.py +++ b/setup.py @@ -6,13 +6,12 @@ setup( author='Nigel Dokter', author_email='nigel@nldr.net', url='https://github.com/ndokter/dsmr_parser', - version='0.19', + version='0.18', packages=find_packages(), install_requires=[ 'pyserial>=3,<4', 'pyserial-asyncio<1', - 'pytz', - 'Tailer==0.4.1' + 'pytz' ], entry_points={ 'console_scripts': ['dsmr_console=dsmr_parser.__main__:console'] From fe710e927286cde8c2628af4017409ece7ab0142 Mon Sep 17 00:00:00 2001 From: lowdef Date: Sun, 2 Feb 2020 22:54:21 +0100 Subject: [PATCH 8/8] redo essential change --- setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index a33f5a4..9c47c51 100644 --- a/setup.py +++ b/setup.py @@ -11,7 +11,8 @@ setup( install_requires=[ 'pyserial>=3,<4', 'pyserial-asyncio<1', - 'pytz' + 'pytz', + 'Tailer==0.4.1' ], entry_points={ 'console_scripts': ['dsmr_console=dsmr_parser.__main__:console']