mirror of
https://github.com/lowobservable/oec.git
synced 2026-01-11 23:53:04 +00:00
Detect unsupported DFT terminals
This commit is contained in:
parent
52a05ad1df
commit
c1b8dc11c4
33
README.md
33
README.md
@ -1,22 +1,31 @@
|
||||
# oec
|
||||
|
||||
IBM 3270 terminal controller - an open replacement for the IBM 3174 Establishment Controller.
|
||||
IBM 3270 terminal controller - a replacement for the IBM 3174.
|
||||
|
||||

|
||||
|
||||
## Features
|
||||
|
||||
This is a work in progress - as of now it only provides basic TN3270 and VT100 emulation.
|
||||
The goal of this project is to create an open replacement for the IBM 3174 Establishment Controller, specifically for users looking to connect a IBM 3270 type terminal to the Hercules emulator. It is a work in progress and is far from providing all the features of the 3174, but it does provide basic TN3270 and VT100 emulation.
|
||||
|
||||
- [x] TN3270
|
||||
- [x] Basic TN3270
|
||||
- [ ] EAB
|
||||
- [ ] TN3270E
|
||||
- [ ] SSL/TLS
|
||||
- [ ] Non-English character sets
|
||||
- [x] VT100
|
||||
- [ ] Connection menu
|
||||
- [ ] Multiple logical terminals
|
||||
- [x] TN3270
|
||||
- [x] Basic TN3270
|
||||
- [ ] TN3270E
|
||||
- [ ] EAB (Extended Attribute Buffer)
|
||||
- [ ] SSL/TLS
|
||||
- [ ] Non-English character sets
|
||||
- [x] VT100
|
||||
- [ ] Connection menu
|
||||
- [ ] MLT (Multiple Logical Terminals)
|
||||
|
||||
## Supported Terminals
|
||||
|
||||
Only CUT (Control Unit Terminal) type terminals are supported. I have tested oec with the following terminals:
|
||||
|
||||
* IBM 3278-2
|
||||
* IBM 3483-V (InfoWindow II)
|
||||
|
||||
You may have to modify the key mapping to support your specific terminal configuration.
|
||||
|
||||
## Usage
|
||||
|
||||
@ -27,7 +36,7 @@ Then configure a Python virtual environment and install dependencies:
|
||||
```
|
||||
python -m venv VIRTUALENV
|
||||
. VIRTUALENV/bin/activate
|
||||
pip install -r requirements.txt --no-deps
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
Assuming your interface is connected to `/dev/ttyACM0` and you want to connect to a TN3270 host named `mainframe`:
|
||||
|
||||
@ -6,9 +6,10 @@ oec.controller
|
||||
import time
|
||||
import logging
|
||||
from coax import poll, poll_ack, load_control_register, PollAction, \
|
||||
KeystrokePollResponse, ReceiveTimeout, ReceiveError, ProtocolError
|
||||
KeystrokePollResponse, TerminalType, ReceiveTimeout, \
|
||||
ReceiveError, ProtocolError
|
||||
|
||||
from .terminal import Terminal, read_terminal_ids
|
||||
from .terminal import Terminal, UnsupportedTerminalError, read_terminal_ids
|
||||
from .keyboard import Key
|
||||
from .session import SessionDisconnectedError
|
||||
|
||||
@ -76,7 +77,11 @@ class Controller:
|
||||
return
|
||||
|
||||
if not self.terminal:
|
||||
self._handle_terminal_attached(poll_response)
|
||||
try:
|
||||
self._handle_terminal_attached(poll_response)
|
||||
except UnsupportedTerminalError as error:
|
||||
self.logger.error(f'Unsupported terminal: {error}')
|
||||
return
|
||||
|
||||
if poll_response:
|
||||
self._handle_poll_response(poll_response)
|
||||
@ -89,6 +94,9 @@ class Controller:
|
||||
|
||||
self.logger.info(f'Terminal ID = {terminal_id}, Extended ID = {extended_id}')
|
||||
|
||||
if terminal_id.type != TerminalType.CUT:
|
||||
raise UnsupportedTerminalError('Only CUT type terminals are supported')
|
||||
|
||||
# Get the keymap.
|
||||
keymap = self.get_keymap(terminal_id, extended_id)
|
||||
|
||||
|
||||
@ -93,3 +93,6 @@ class Terminal:
|
||||
cursor_blink=self.display.cursor_blink)
|
||||
|
||||
return control
|
||||
|
||||
class UnsupportedTerminalError(Exception):
|
||||
"""Unsupported terminal."""
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
ptyprocess==0.6.0
|
||||
pycoax==0.3.1
|
||||
pycoax==0.4.0
|
||||
pyserial==3.4
|
||||
pyte==0.8.0
|
||||
pytn3270==0.5.0
|
||||
sliplib==0.3.0
|
||||
sliplib==0.5.0
|
||||
sortedcontainers==2.1.0
|
||||
wcwidth==0.1.7
|
||||
|
||||
@ -10,7 +10,8 @@ from oec.session import SessionDisconnectedError
|
||||
from oec.keyboard import KeyboardModifiers, Key
|
||||
from oec.keymap_3278_2 import KEYMAP as KEYMAP_3278_2
|
||||
|
||||
TERMINAL_IDS = (TerminalId(0b11110100), 'c1348300')
|
||||
CUT_TERMINAL_IDS = (TerminalId(0b11110100), 'c1348300')
|
||||
DFT_TERMINAL_IDS = (TerminalId(0b00000001), None)
|
||||
|
||||
class RunLoopTestCase(unittest.TestCase):
|
||||
def setUp(self):
|
||||
@ -21,6 +22,8 @@ class RunLoopTestCase(unittest.TestCase):
|
||||
|
||||
self.controller = Controller(self.interface, lambda terminal_id, extended_id: KEYMAP_3278_2, self.create_session_mock)
|
||||
|
||||
self.controller.logger = Mock()
|
||||
|
||||
self.controller.connected_poll_period = 1
|
||||
|
||||
patcher = patch('oec.controller.poll')
|
||||
@ -35,7 +38,7 @@ class RunLoopTestCase(unittest.TestCase):
|
||||
|
||||
self.read_terminal_ids_mock = patcher.start()
|
||||
|
||||
self.read_terminal_ids_mock.return_value = TERMINAL_IDS
|
||||
self.read_terminal_ids_mock.return_value = CUT_TERMINAL_IDS
|
||||
|
||||
patcher = patch('oec.controller.load_control_register')
|
||||
|
||||
@ -80,6 +83,14 @@ class RunLoopTestCase(unittest.TestCase):
|
||||
|
||||
self.controller.session.handle_host.assert_called()
|
||||
|
||||
def test_unsupported_terminal_attached(self):
|
||||
self.read_terminal_ids_mock.return_value = DFT_TERMINAL_IDS
|
||||
|
||||
self._assert_run_loop(0, PowerOnResetCompletePollResponse(0xa), 0, True)
|
||||
|
||||
self.assertIsNone(self.controller.terminal)
|
||||
self.assertIsNone(self.controller.session)
|
||||
|
||||
def test_keystroke(self):
|
||||
self._assert_run_loop(0, PowerOnResetCompletePollResponse(0xa), 0, True)
|
||||
self._assert_run_loop(0, KeystrokePollResponse(0b0110000010), 0, True)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user