Merge pull request #70 from bremme/master
Add SocketReader to connect to remote serial port
This commit is contained in:
		
						commit
						dc2f493739
					
				
							
								
								
									
										19
									
								
								README.rst
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								README.rst
									
									
									
									
									
								
							| @ -46,6 +46,25 @@ process because the code is blocking (not asynchronous): | |||||||
| 
 | 
 | ||||||
| To be documented. | To be documented. | ||||||
| 
 | 
 | ||||||
|  | **Socket client** | ||||||
|  | 
 | ||||||
|  | Read a remote serial port (for example using ser2net) and work with the parsed telegrams. | ||||||
|  | It should be run in a separate process because the code is blocking (not asynchronous): | ||||||
|  | 
 | ||||||
|  | .. code-block:: python | ||||||
|  | 
 | ||||||
|  |      from dsmr_parser import telegram_specifications | ||||||
|  |      from dsmr_parser.clients import SocketReader | ||||||
|  |      | ||||||
|  |      socket_reader = SocketReader( | ||||||
|  |          host='127.0.0.1', | ||||||
|  |          port=2001, | ||||||
|  |          telegram_specification=telegram_specifications.V4 | ||||||
|  |      ) | ||||||
|  |      | ||||||
|  |      for telegram in socket_reader.read(): | ||||||
|  |          print(telegram)  # see 'Telegram object' docs below | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| Parsing module usage | Parsing module usage | ||||||
| -------------------- | -------------------- | ||||||
|  | |||||||
| @ -1,5 +1,6 @@ | |||||||
| from dsmr_parser.clients.settings import SERIAL_SETTINGS_V2_2, \ | from dsmr_parser.clients.settings import SERIAL_SETTINGS_V2_2, \ | ||||||
|     SERIAL_SETTINGS_V4, SERIAL_SETTINGS_V5 |     SERIAL_SETTINGS_V4, SERIAL_SETTINGS_V5 | ||||||
| from dsmr_parser.clients.serial_ import SerialReader, AsyncSerialReader | from dsmr_parser.clients.serial_ import SerialReader, AsyncSerialReader | ||||||
|  | from dsmr_parser.clients.socket_ import SocketReader | ||||||
| from dsmr_parser.clients.protocol import create_dsmr_protocol, \ | from dsmr_parser.clients.protocol import create_dsmr_protocol, \ | ||||||
|     create_dsmr_reader, create_tcp_dsmr_reader |     create_dsmr_reader, create_tcp_dsmr_reader | ||||||
|  | |||||||
							
								
								
									
										91
									
								
								dsmr_parser/clients/socket_.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								dsmr_parser/clients/socket_.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,91 @@ | |||||||
|  | import logging | ||||||
|  | import socket | ||||||
|  | 
 | ||||||
|  | from dsmr_parser.clients.telegram_buffer import TelegramBuffer | ||||||
|  | from dsmr_parser.exceptions import ParseError, InvalidChecksumError | ||||||
|  | from dsmr_parser.parsers import TelegramParser | ||||||
|  | from dsmr_parser.objects import Telegram | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | logger = logging.getLogger(__name__) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class SocketReader(object): | ||||||
|  | 
 | ||||||
|  |     BUFFER_SIZE = 256 | ||||||
|  | 
 | ||||||
|  |     def __init__(self, host, port, telegram_specification): | ||||||
|  |         self.host = host | ||||||
|  |         self.port = port | ||||||
|  | 
 | ||||||
|  |         self.telegram_parser = TelegramParser(telegram_specification) | ||||||
|  |         self.telegram_buffer = TelegramBuffer() | ||||||
|  |         self.telegram_specification = telegram_specification | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     def read(self): | ||||||
|  |         """ | ||||||
|  |         Read complete DSMR telegram's from remote interface and parse it | ||||||
|  |         into CosemObject's and MbusObject's | ||||||
|  | 
 | ||||||
|  |         :rtype: generator | ||||||
|  |         """ | ||||||
|  |         buffer = b"" | ||||||
|  | 
 | ||||||
|  |         with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as socket_handle: | ||||||
|  | 
 | ||||||
|  |             socket_handle.connect((self.host, self.port)) | ||||||
|  | 
 | ||||||
|  |             while True: | ||||||
|  |                 buffer += socket_handle.recv(self.BUFFER_SIZE) | ||||||
|  | 
 | ||||||
|  |                 lines = buffer.splitlines(keepends=True) | ||||||
|  | 
 | ||||||
|  |                 if len(lines) == 0: | ||||||
|  |                     continue | ||||||
|  | 
 | ||||||
|  |                 for data in lines: | ||||||
|  |                     self.telegram_buffer.append(data.decode('ascii')) | ||||||
|  | 
 | ||||||
|  |                 for telegram in self.telegram_buffer.get_all(): | ||||||
|  |                     try: | ||||||
|  |                         yield self.telegram_parser.parse(telegram) | ||||||
|  |                     except InvalidChecksumError as e: | ||||||
|  |                         logger.warning(str(e)) | ||||||
|  |                     except ParseError as e: | ||||||
|  |                         logger.error('Failed to parse telegram: %s', e) | ||||||
|  | 
 | ||||||
|  |                 buffer = b"" | ||||||
|  | 
 | ||||||
|  |     def read_as_object(self): | ||||||
|  |         """ | ||||||
|  |         Read complete DSMR telegram's from remote and return a Telegram object. | ||||||
|  | 
 | ||||||
|  |         :rtype: generator | ||||||
|  |         """ | ||||||
|  |         buffer = b"" | ||||||
|  | 
 | ||||||
|  |         with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as socket_handle: | ||||||
|  | 
 | ||||||
|  |             socket_handle.connect((self.host, self.port)) | ||||||
|  | 
 | ||||||
|  |             while True: | ||||||
|  |                 buffer += socket_handle.recv(self.BUFFER_SIZE) | ||||||
|  | 
 | ||||||
|  |                 lines = buffer.splitlines(keepends=True) | ||||||
|  | 
 | ||||||
|  |                 if len(lines) == 0: | ||||||
|  |                     continue | ||||||
|  | 
 | ||||||
|  |                 for data in lines: | ||||||
|  |                     self.telegram_buffer.append(data.decode('ascii')) | ||||||
|  | 
 | ||||||
|  |                     for telegram in self.telegram_buffer.get_all(): | ||||||
|  |                         try: | ||||||
|  |                             yield Telegram(telegram, self.telegram_parser, self.telegram_specification) | ||||||
|  |                         except InvalidChecksumError as e: | ||||||
|  |                             logger.warning(str(e)) | ||||||
|  |                         except ParseError as e: | ||||||
|  |                             logger.error('Failed to parse telegram: %s', e) | ||||||
|  | 
 | ||||||
|  |                 buffer = b"" | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user