Add quote bridge and quote handoff flow
This commit is contained in:
@@ -0,0 +1,269 @@
|
||||
# Quote Bridge (Listener App)
|
||||
|
||||
This is a separate Python app that runs independently from the Flask app.
|
||||
|
||||
It watches for quote files in `shared/outgoing` and can run in two modes:
|
||||
|
||||
- `move` (default): move incoming files to `shared/processed`
|
||||
- `dosbox`: run DOSBox command/script per quote file, then move to
|
||||
`shared/processed` on success or `shared/failed` on error
|
||||
|
||||
## Run
|
||||
|
||||
From repository root:
|
||||
|
||||
```bash
|
||||
./.venv/bin/python quote-bridge/listener.py
|
||||
```
|
||||
|
||||
Or from this folder:
|
||||
|
||||
```bash
|
||||
../.venv/bin/python listener.py
|
||||
```
|
||||
|
||||
## Install DOSBox On Ubuntu
|
||||
|
||||
You will need DOSBox installed on the Ubuntu machine if you want to use
|
||||
`QUOTE_PROCESSOR_MODE=dosbox`.
|
||||
|
||||
### Option 1: Standard DOSBox
|
||||
|
||||
```bash
|
||||
sudo apt update
|
||||
sudo apt install dosbox
|
||||
```
|
||||
|
||||
### Option 2: DOSBox-X
|
||||
|
||||
If available in your environment or package source, DOSBox-X is a better choice
|
||||
for many protected-mode DOS applications.
|
||||
|
||||
Example:
|
||||
|
||||
```bash
|
||||
sudo apt update
|
||||
sudo apt install dosbox-x
|
||||
```
|
||||
|
||||
If your distro does not provide `dosbox-x`, install it from your preferred
|
||||
package source and then update `dosboxBin` in your profile.
|
||||
|
||||
## Environment Variables
|
||||
|
||||
- `QUOTE_OUTGOING_DIR`: Source directory to watch
|
||||
- `QUOTE_PROCESSED_DIR`: Destination directory for moved files
|
||||
- `QUOTE_FAILED_DIR`: Destination for failed quote files
|
||||
- `QUOTE_PROCESSOR_MODE`: `move` or `dosbox` (default: `move`)
|
||||
- `QUOTE_PROFILE_DIR`: Directory containing per-location DOSBox profiles
|
||||
- `QUOTE_POLL_INTERVAL_SECONDS`: Poll interval (default: `2`)
|
||||
|
||||
### DOSBox Mode Variables
|
||||
|
||||
When `QUOTE_PROCESSOR_MODE=dosbox`, these variables are used:
|
||||
|
||||
- `DOSBOX_BIN`: DOSBox executable (default: `dosbox`)
|
||||
- `DOSBOX_CONF`: Optional DOSBox config file path
|
||||
- `DOSBOX_MOUNT_PATH`: Host path mounted into DOS (default: shared parent path)
|
||||
- `DOSBOX_MOUNT_DRIVE`: DOS drive letter (default: `C`)
|
||||
- `DOSBOX_BRIDGE_COMMAND`: DOS command/batch to run (default: `BRIDGE.BAT`)
|
||||
- `DOSBOX_EXTRA_COMMANDS`: Extra DOS commands separated by `;`
|
||||
- `DOSBOX_TIMEOUT_SECONDS`: Timeout for one DOSBox run (default: `120`)
|
||||
- `DOSBOX_NOCONSOLE`: `true/false` to add `-noconsole` flag
|
||||
|
||||
## Profiles
|
||||
|
||||
When `QUOTE_PROCESSOR_MODE=dosbox`, the helper looks at the quote file's
|
||||
`createdBy.location` field and tries to load a matching profile from:
|
||||
|
||||
- `quote-bridge/profiles/<LOCATION>.json`
|
||||
- then `quote-bridge/profiles/default.json`
|
||||
|
||||
Included sample profiles:
|
||||
|
||||
- `quote-bridge/profiles/IOLA.json`
|
||||
- `quote-bridge/profiles/KC.json`
|
||||
- `quote-bridge/profiles/LINDS.json`
|
||||
- `quote-bridge/profiles/default.json`
|
||||
|
||||
### Where To Enter The Remote Path
|
||||
|
||||
For each location profile, set:
|
||||
|
||||
- `mountPath`: the Linux path where that remote PC's shared drive/folder is mounted
|
||||
|
||||
Example:
|
||||
|
||||
```json
|
||||
{
|
||||
"mountPath": "/mnt/iola-cgw"
|
||||
}
|
||||
```
|
||||
|
||||
That is the main place to enter the mapped path.
|
||||
|
||||
### Where To Enter The DOS App Folder
|
||||
|
||||
For each location profile, set:
|
||||
|
||||
- `workingDirectory`: the DOS folder under the mounted share that contains the app
|
||||
|
||||
Example:
|
||||
|
||||
```json
|
||||
{
|
||||
"workingDirectory": "CGWAPP"
|
||||
}
|
||||
```
|
||||
|
||||
If the DOS app lives at:
|
||||
|
||||
```text
|
||||
/mnt/iola-cgw/CGWAPP
|
||||
```
|
||||
|
||||
then use:
|
||||
|
||||
- `mountPath = /mnt/iola-cgw`
|
||||
- `workingDirectory = CGWAPP`
|
||||
|
||||
### Where To Enter The DOS Entry Script
|
||||
|
||||
For each location profile, set:
|
||||
|
||||
- `bridgeCommand`: the DOS-side batch/script/executable to run after mounting and changing directory
|
||||
|
||||
Example:
|
||||
|
||||
```json
|
||||
{
|
||||
"bridgeCommand": "BRIDGE.BAT"
|
||||
}
|
||||
```
|
||||
|
||||
## Suggested Setup For Multiple PCs
|
||||
|
||||
If each location runs from a different PC, the clean pattern is:
|
||||
|
||||
1. Mount each remote PC's application share on Ubuntu.
|
||||
2. Put that mount path into the matching location profile.
|
||||
3. Keep one profile per location.
|
||||
4. Let the helper auto-select the profile based on the quote's current location.
|
||||
|
||||
Example mapping:
|
||||
|
||||
- `IOLA` -> `/mnt/iola-cgw`
|
||||
- `KC` -> `/mnt/kc-cgw`
|
||||
- `LINDS` -> `/mnt/linds-cgw`
|
||||
|
||||
## Mounting Remote PC Shares On Ubuntu
|
||||
|
||||
If the DOS app is stored on remote Windows PCs, Ubuntu needs those folders
|
||||
mounted locally first.
|
||||
|
||||
Example mount points:
|
||||
|
||||
```bash
|
||||
sudo mkdir -p /mnt/iola-cgw
|
||||
sudo mkdir -p /mnt/kc-cgw
|
||||
sudo mkdir -p /mnt/linds-cgw
|
||||
```
|
||||
|
||||
Example CIFS mount command:
|
||||
|
||||
```bash
|
||||
sudo mount -t cifs //REMOTE-PC/SharedFolder /mnt/iola-cgw \
|
||||
-o username=YOUR_USER,password=YOUR_PASSWORD,uid=$(id -u),gid=$(id -g)
|
||||
```
|
||||
|
||||
Replace:
|
||||
|
||||
- `REMOTE-PC` with the Windows machine name or IP
|
||||
- `SharedFolder` with the shared folder name
|
||||
- `YOUR_USER` and `YOUR_PASSWORD` with Windows credentials
|
||||
|
||||
After the mount is working, put that Linux mount path into the matching profile
|
||||
as `mountPath`.
|
||||
|
||||
## Example .env-Style Setup
|
||||
|
||||
You can export variables in the shell before starting the listener.
|
||||
|
||||
Example:
|
||||
|
||||
```bash
|
||||
export QUOTE_PROCESSOR_MODE=dosbox
|
||||
export QUOTE_PROFILE_DIR=/home/jsalmon/Documents/git/quote-builder/quote-bridge/profiles
|
||||
./.venv/bin/python quote-bridge/listener.py
|
||||
```
|
||||
|
||||
If you prefer, create a small shell script such as `start-quote-bridge.sh` that
|
||||
exports these values and starts the listener.
|
||||
|
||||
## Sample Profile Fields
|
||||
|
||||
Example profile:
|
||||
|
||||
```json
|
||||
{
|
||||
"profileName": "IOLA",
|
||||
"dosboxBin": "dosbox-x",
|
||||
"mountDrive": "C",
|
||||
"mountPath": "/mnt/iola-cgw",
|
||||
"workingDirectory": "CGWAPP",
|
||||
"bridgeCommand": "BRIDGE.BAT",
|
||||
"extraCommands": [
|
||||
"SET CLIPPER=F200"
|
||||
],
|
||||
"timeoutSeconds": 180,
|
||||
"noConsole": false
|
||||
}
|
||||
```
|
||||
|
||||
## DOS-Side BRIDGE.BAT Contract
|
||||
|
||||
The helper currently assumes a DOS-side entry script like:
|
||||
|
||||
```bat
|
||||
BRIDGE.BAT "C:\OUTGOING\20260629-153012-ab12cd34.json"
|
||||
```
|
||||
|
||||
That means `BRIDGE.BAT` should accept the quote file path as `%1`.
|
||||
|
||||
Minimal example:
|
||||
|
||||
```bat
|
||||
@echo off
|
||||
rem %1 is the quote JSON file path inside DOSBox
|
||||
echo Processing quote file: %1
|
||||
rem Start your DOS app here and pass or import the file as needed
|
||||
rem Example only:
|
||||
rem MYAPP.EXE %1
|
||||
```
|
||||
|
||||
If your DOS app requires a different startup sequence, change `bridgeCommand`
|
||||
in the location profile.
|
||||
|
||||
## End-To-End Flow
|
||||
|
||||
1. User clicks `Quote` in the Flask app.
|
||||
2. Flask writes a quote JSON file to `shared/outgoing`.
|
||||
3. Listener sees the new file.
|
||||
4. Listener selects profile based on `createdBy.location` in the quote.
|
||||
5. In `dosbox` mode, listener launches DOSBox using that profile.
|
||||
6. DOSBox runs the configured `bridgeCommand`.
|
||||
7. File moves to:
|
||||
- `shared/processed` on success
|
||||
- `shared/failed` on failure
|
||||
|
||||
## Current Behavior
|
||||
|
||||
- Processes `.json` files only
|
||||
- Ignores temporary files such as `*.tmp`
|
||||
- Appends a timestamp suffix if a destination filename already exists
|
||||
- In `move` mode, files are moved from outgoing to processed
|
||||
- In `dosbox` mode, each file is passed to DOSBox first, then moved to:
|
||||
- `processed` on success
|
||||
- `failed` on failure
|
||||
|
||||
Use `Ctrl+C` to stop the listener.
|
||||
Reference in New Issue
Block a user