Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add client and connection abstractions (#3)
- Loading branch information
Showing
3 changed files
with
111 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
from .client import Client | ||
from .connection import Connection | ||
|
||
__all__ = ['Client', 'Connection'] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |