Skip to content

Commit

Permalink
Add client and connection abstractions (#3)
Browse files Browse the repository at this point in the history
  • Loading branch information
nickw444 committed Oct 27, 2018
1 parent bee1f69 commit f284b02
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 0 deletions.
4 changes: 4 additions & 0 deletions py_ness_232/__init__.py
@@ -0,0 +1,4 @@
from .client import Client
from .connection import Connection

__all__ = ['Client', 'Connection']
35 changes: 35 additions & 0 deletions py_ness_232/client.py
@@ -0,0 +1,35 @@
from typing import Optional

from .connection import Connection, IP232Connection
from .event import BaseEvent
from .packet import CommandType, Packet


class Client:
def __init__(self,
connection: Optional[Connection] = None,
host: Optional[str] = None,
port: Optional[int] = None):
if connection is None:
assert host is not None
assert port is not None
connection = IP232Connection(host, port)

self.__connection = connection

def send_command(self, command: str) -> None:
packet = Packet.create(
command=CommandType.USER_INTERFACE,
start=0x83,
address=0x00,
data=command.encode('ascii'),
)
return self.__connection.write(packet.encode().encode('ascii'))

def read_event(self) -> Optional[BaseEvent]:
data = self.__connection.read()
if data is not None:
pkt = Packet.decode(data)
return BaseEvent.decode(pkt)

return None
72 changes: 72 additions & 0 deletions py_ness_232/connection.py
@@ -0,0 +1,72 @@
import socket
from abc import ABC
from typing import Optional


class Connection(ABC):
"""Represents a connection to a Ness D8X/D16X server"""

def read(self) -> Optional[bytes]:
raise NotImplementedError()

def write(self, data: bytes) -> None:
raise NotImplementedError()

def close(self) -> None:
raise NotImplementedError()


class IP232Connection(Connection):
"""A connection via IP232 with a Ness D8X/D16X server"""

def __init__(self, host: str, port: int):
super().__init__()

self.__host = host
self.__port = port
self.__socket: Optional[socket.socket] = None

def __connect(self) -> None:
self.__socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.__socket.connect((self.__host, self.__port))

def read(self) -> Optional[bytes]:
if self.__socket is None:
self.__connect()
assert self.__socket is not None

data = self.__socket.recv(1024)
if data is None:
self.close()
return None

data = data.strip()
if len(data) == 0:
return None

return data

def write(self, data: bytes) -> None:
if self.__socket is None:
self.__connect()
assert self.__socket is not None

self.__socket.send(data)

def close(self) -> None:
if self.__socket is not None:
self.__socket.close()
self.__socket = None


class RS232Connection(Connection):
"""A connection via RS232 with a Ness D8X/D16X server"""

def read(self) -> Optional[bytes]:
pass

def write(self, data: bytes) -> None:
pass

def close(self) -> None:
pass

0 comments on commit f284b02

Please sign in to comment.