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. | ||||
| 
 | ||||
| **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 | ||||
| -------------------- | ||||
|  | ||||
| @ -1,5 +1,6 @@ | ||||
| from dsmr_parser.clients.settings import SERIAL_SETTINGS_V2_2, \ | ||||
|     SERIAL_SETTINGS_V4, SERIAL_SETTINGS_V5 | ||||
| from dsmr_parser.clients.serial_ import SerialReader, AsyncSerialReader | ||||
| from dsmr_parser.clients.socket_ import SocketReader | ||||
| from dsmr_parser.clients.protocol import create_dsmr_protocol, \ | ||||
|     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