streamer-node 1.0.30 → 1.0.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/package.json +6 -2
- package/dist/scripts/README.md +670 -0
- package/dist/scripts/install-streamer-node.sh +117 -0
- package/dist/scripts/reframe_ball.py +354 -0
- package/dist/src/application/interfaces/StartStreamUseCase.types.d.ts +3 -1
- package/dist/src/application/interfaces/StartStreamUseCase.types.d.ts.map +1 -1
- package/dist/src/application/interfaces/StartStreamUseCase.types.js.map +1 -1
- package/dist/src/application/services/HttpClient.d.ts +21 -0
- package/dist/src/application/services/HttpClient.d.ts.map +1 -1
- package/dist/src/application/services/HttpClient.js +37 -5
- package/dist/src/application/services/HttpClient.js.map +1 -1
- package/dist/src/application/services/StreamManagerService.d.ts.map +1 -1
- package/dist/src/application/services/StreamManagerService.js +2 -0
- package/dist/src/application/services/StreamManagerService.js.map +1 -1
- package/dist/src/application/use-cases/CaptureHighlightUseCase.d.ts +52 -0
- package/dist/src/application/use-cases/CaptureHighlightUseCase.d.ts.map +1 -0
- package/dist/src/application/use-cases/CaptureHighlightUseCase.js +169 -0
- package/dist/src/application/use-cases/CaptureHighlightUseCase.js.map +1 -0
- package/dist/src/application/use-cases/StartStreamUseCase.d.ts +9 -1
- package/dist/src/application/use-cases/StartStreamUseCase.d.ts.map +1 -1
- package/dist/src/application/use-cases/StartStreamUseCase.js +125 -2
- package/dist/src/application/use-cases/StartStreamUseCase.js.map +1 -1
- package/dist/src/application/use-cases/StopStreamUseCase.d.ts +5 -1
- package/dist/src/application/use-cases/StopStreamUseCase.d.ts.map +1 -1
- package/dist/src/application/use-cases/StopStreamUseCase.js +7 -1
- package/dist/src/application/use-cases/StopStreamUseCase.js.map +1 -1
- package/dist/src/domain/events/StreamEvent.d.ts +5 -0
- package/dist/src/domain/events/StreamEvent.d.ts.map +1 -1
- package/dist/src/domain/services/BallReframer.d.ts +35 -0
- package/dist/src/domain/services/BallReframer.d.ts.map +1 -0
- package/dist/src/domain/services/BallReframer.js +3 -0
- package/dist/src/domain/services/BallReframer.js.map +1 -0
- package/dist/src/domain/services/FFmpegService.d.ts +6 -2
- package/dist/src/domain/services/FFmpegService.d.ts.map +1 -1
- package/dist/src/domain/services/HighlightSignalSource.d.ts +113 -0
- package/dist/src/domain/services/HighlightSignalSource.d.ts.map +1 -0
- package/dist/src/domain/services/HighlightSignalSource.js +3 -0
- package/dist/src/domain/services/HighlightSignalSource.js.map +1 -0
- package/dist/src/domain/services/SSEService.d.ts +1 -0
- package/dist/src/domain/services/SSEService.d.ts.map +1 -1
- package/dist/src/infrastructure/config/Config.d.ts +32 -0
- package/dist/src/infrastructure/config/Config.d.ts.map +1 -1
- package/dist/src/infrastructure/config/Config.js +60 -0
- package/dist/src/infrastructure/config/Config.js.map +1 -1
- package/dist/src/infrastructure/listeners/SupabaseListener.d.ts +5 -0
- package/dist/src/infrastructure/listeners/SupabaseListener.d.ts.map +1 -1
- package/dist/src/infrastructure/listeners/SupabaseListener.js +43 -5
- package/dist/src/infrastructure/listeners/SupabaseListener.js.map +1 -1
- package/dist/src/infrastructure/logging/LogShippingService.d.ts +3 -1
- package/dist/src/infrastructure/logging/LogShippingService.d.ts.map +1 -1
- package/dist/src/infrastructure/logging/LogShippingService.js +13 -4
- package/dist/src/infrastructure/logging/LogShippingService.js.map +1 -1
- package/dist/src/infrastructure/logging/RemoteLogger.d.ts +1 -0
- package/dist/src/infrastructure/logging/RemoteLogger.d.ts.map +1 -1
- package/dist/src/infrastructure/logging/RemoteLogger.js +1 -1
- package/dist/src/infrastructure/logging/RemoteLogger.js.map +1 -1
- package/dist/src/infrastructure/services/AdDownloaderService.d.ts +85 -0
- package/dist/src/infrastructure/services/AdDownloaderService.d.ts.map +1 -0
- package/dist/src/infrastructure/services/AdDownloaderService.js +530 -0
- package/dist/src/infrastructure/services/AdDownloaderService.js.map +1 -0
- package/dist/src/infrastructure/services/AdRotator.d.ts +63 -0
- package/dist/src/infrastructure/services/AdRotator.d.ts.map +1 -0
- package/dist/src/infrastructure/services/AdRotator.js +223 -0
- package/dist/src/infrastructure/services/AdRotator.js.map +1 -0
- package/dist/src/infrastructure/services/HighlightBufferManager.d.ts +65 -0
- package/dist/src/infrastructure/services/HighlightBufferManager.d.ts.map +1 -0
- package/dist/src/infrastructure/services/HighlightBufferManager.js +203 -0
- package/dist/src/infrastructure/services/HighlightBufferManager.js.map +1 -0
- package/dist/src/infrastructure/services/HighlightBufferRegistry.d.ts +23 -0
- package/dist/src/infrastructure/services/HighlightBufferRegistry.d.ts.map +1 -0
- package/dist/src/infrastructure/services/HighlightBufferRegistry.js +44 -0
- package/dist/src/infrastructure/services/HighlightBufferRegistry.js.map +1 -0
- package/dist/src/infrastructure/services/HighlightExtractorService.d.ts +65 -0
- package/dist/src/infrastructure/services/HighlightExtractorService.d.ts.map +1 -0
- package/dist/src/infrastructure/services/HighlightExtractorService.js +264 -0
- package/dist/src/infrastructure/services/HighlightExtractorService.js.map +1 -0
- package/dist/src/infrastructure/services/HighlightRendererService.d.ts +38 -0
- package/dist/src/infrastructure/services/HighlightRendererService.d.ts.map +1 -0
- package/dist/src/infrastructure/services/HighlightRendererService.js +182 -0
- package/dist/src/infrastructure/services/HighlightRendererService.js.map +1 -0
- package/dist/src/infrastructure/services/NodeFFmpegService.d.ts +6 -4
- package/dist/src/infrastructure/services/NodeFFmpegService.d.ts.map +1 -1
- package/dist/src/infrastructure/services/NodeFFmpegService.js +154 -32
- package/dist/src/infrastructure/services/NodeFFmpegService.js.map +1 -1
- package/dist/src/infrastructure/services/NodeSSEService.d.ts +8 -0
- package/dist/src/infrastructure/services/NodeSSEService.d.ts.map +1 -1
- package/dist/src/infrastructure/services/NodeSSEService.js +71 -27
- package/dist/src/infrastructure/services/NodeSSEService.js.map +1 -1
- package/dist/src/infrastructure/services/NullBallReframer.d.ts +11 -0
- package/dist/src/infrastructure/services/NullBallReframer.d.ts.map +1 -0
- package/dist/src/infrastructure/services/NullBallReframer.js +16 -0
- package/dist/src/infrastructure/services/NullBallReframer.js.map +1 -0
- package/dist/src/infrastructure/services/PythonBallReframer.d.ts +35 -0
- package/dist/src/infrastructure/services/PythonBallReframer.d.ts.map +1 -0
- package/dist/src/infrastructure/services/PythonBallReframer.js +238 -0
- package/dist/src/infrastructure/services/PythonBallReframer.js.map +1 -0
- package/dist/src/infrastructure/services/SerialHighlightListener.d.ts +45 -0
- package/dist/src/infrastructure/services/SerialHighlightListener.d.ts.map +1 -0
- package/dist/src/infrastructure/services/SerialHighlightListener.js +440 -0
- package/dist/src/infrastructure/services/SerialHighlightListener.js.map +1 -0
- package/dist/src/infrastructure/services/YouTubeUploadService.d.ts +36 -0
- package/dist/src/infrastructure/services/YouTubeUploadService.d.ts.map +1 -0
- package/dist/src/infrastructure/services/YouTubeUploadService.js +402 -0
- package/dist/src/infrastructure/services/YouTubeUploadService.js.map +1 -0
- package/dist/src/infrastructure/utils/ResourceSampler.d.ts +47 -0
- package/dist/src/infrastructure/utils/ResourceSampler.d.ts.map +1 -0
- package/dist/src/infrastructure/utils/ResourceSampler.js +102 -0
- package/dist/src/infrastructure/utils/ResourceSampler.js.map +1 -0
- package/dist/src/infrastructure/utils/lowPriority.d.ts +29 -0
- package/dist/src/infrastructure/utils/lowPriority.d.ts.map +1 -0
- package/dist/src/infrastructure/utils/lowPriority.js +31 -0
- package/dist/src/infrastructure/utils/lowPriority.js.map +1 -0
- package/dist/src/infrastructure/utils/paths.d.ts +27 -0
- package/dist/src/infrastructure/utils/paths.d.ts.map +1 -0
- package/dist/src/infrastructure/utils/paths.js +69 -0
- package/dist/src/infrastructure/utils/paths.js.map +1 -0
- package/dist/src/infrastructure/utils/spawnToFile.d.ts +20 -0
- package/dist/src/infrastructure/utils/spawnToFile.d.ts.map +1 -0
- package/dist/src/infrastructure/utils/spawnToFile.js +98 -0
- package/dist/src/infrastructure/utils/spawnToFile.js.map +1 -0
- package/dist/src/main.js +228 -2
- package/dist/src/main.js.map +1 -1
- package/package.json +6 -2
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.PythonBallReframer = void 0;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const child_process_1 = require("child_process");
|
|
40
|
+
const lowPriority_1 = require("../utils/lowPriority");
|
|
41
|
+
/**
|
|
42
|
+
* BallReframer backed by a one-shot Python/OpenCV script (scripts/reframe_ball.py).
|
|
43
|
+
*
|
|
44
|
+
* ── IN SIMPLE WORDS ──
|
|
45
|
+
* Hands the raw clip to a small Python program that watches the ball and writes
|
|
46
|
+
* a cropped, vertical version. If Python isn't installed, the script errors, or
|
|
47
|
+
* it takes too long, we just return null and the full-frame clip is used.
|
|
48
|
+
*
|
|
49
|
+
* ── WHY IT'S BUILT THIS WAY (change at your peril) ──
|
|
50
|
+
* Same one-shot-subprocess pattern as the ffmpeg calls: spawn, wait with a
|
|
51
|
+
* timeout, read back the produced file. It is fail-soft by construction — a
|
|
52
|
+
* missing interpreter, a crash, a timeout, or a missing output file all resolve
|
|
53
|
+
* to null. A highlight must never be lost because tracking misbehaved.
|
|
54
|
+
*
|
|
55
|
+
* ── DO NOT ──
|
|
56
|
+
* - Do NOT let this throw; every error path returns null.
|
|
57
|
+
* - Do NOT enable in production before the CV script is tuned on real padel
|
|
58
|
+
* footage — until then the crop quality is unproven (hence default OFF).
|
|
59
|
+
*/
|
|
60
|
+
class PythonBallReframer {
|
|
61
|
+
constructor(reelAspect, logger, scriptPath) {
|
|
62
|
+
this.reelAspect = reelAspect;
|
|
63
|
+
this.logger = logger;
|
|
64
|
+
// The reframe is the heaviest highlight stage (two-pass OpenCV). It runs at
|
|
65
|
+
// low CPU priority (see withLowPriority), so on a weak box it can take a
|
|
66
|
+
// while — give it a generous ceiling rather than killing a nearly-done pass.
|
|
67
|
+
// Detection is downscaled + frame-skipped (reframe_ball.py) to keep it well
|
|
68
|
+
// under this in practice.
|
|
69
|
+
this.timeoutMs = 240000;
|
|
70
|
+
// The app ships as an npm package run via `npx` — so the script must be
|
|
71
|
+
// found INSIDE the package (the build copies scripts/ into dist/), not from
|
|
72
|
+
// the CWD. Resolve relative to this compiled module (dist/scripts) first,
|
|
73
|
+
// then fall back to a repo-root checkout (dev / git deploy). __dirname here
|
|
74
|
+
// is <pkg>/dist/src/infrastructure/services, so ../../../scripts = dist/scripts.
|
|
75
|
+
const candidates = [
|
|
76
|
+
path.join(__dirname, "..", "..", "..", "scripts", "reframe_ball.py"),
|
|
77
|
+
path.resolve("scripts/reframe_ball.py"),
|
|
78
|
+
];
|
|
79
|
+
this.scriptPath =
|
|
80
|
+
scriptPath ?? candidates.find((p) => fs.existsSync(p)) ?? candidates[0];
|
|
81
|
+
}
|
|
82
|
+
async reframe(clipPath, courtId) {
|
|
83
|
+
if (!fs.existsSync(this.scriptPath)) {
|
|
84
|
+
this.logger.warn("Ball reframer script missing; using full frame", {
|
|
85
|
+
courtId,
|
|
86
|
+
scriptPath: this.scriptPath,
|
|
87
|
+
});
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
// Nothing to crop → nothing to track. The reframer takes a window as WIDE
|
|
91
|
+
// as `aspect` allows out of a full-height source, so when the target is as
|
|
92
|
+
// wide as (or wider than) the source there is no horizontal room to pan and
|
|
93
|
+
// the pass would be a pure re-encode: ~40s of CPU on a streamer box for a
|
|
94
|
+
// frame-identical result. Skip it and let the caller use the raw clip.
|
|
95
|
+
//
|
|
96
|
+
// This is the normal case for the default 16:9 target on a 16:9 camera.
|
|
97
|
+
const srcDims = await this.probeDimensions(clipPath);
|
|
98
|
+
if (srcDims) {
|
|
99
|
+
const target = this.parseAspect(this.reelAspect);
|
|
100
|
+
const source = srcDims.width / srcDims.height;
|
|
101
|
+
if (target !== null && target >= source - 0.001) {
|
|
102
|
+
this.logger.info("Ball reframe skipped: target aspect is not narrower than the source, nothing to crop", { courtId, aspect: this.reelAspect, source: `${srcDims.width}x${srcDims.height}` });
|
|
103
|
+
return null; // caller falls back to the full-frame clip — the desired result
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
const dir = path.dirname(clipPath);
|
|
107
|
+
const base = path.basename(clipPath, path.extname(clipPath));
|
|
108
|
+
const out = path.join(dir, `reframed-${base}.mp4`);
|
|
109
|
+
try {
|
|
110
|
+
// --debug makes the script print a one-line detector summary to stderr
|
|
111
|
+
// (frames / hit_rate / motion); we log it so staging can SEE whether
|
|
112
|
+
// tracking actually locked onto players, not just that the script ran.
|
|
113
|
+
const stderr = await this.runPython([
|
|
114
|
+
this.scriptPath,
|
|
115
|
+
"--input", clipPath,
|
|
116
|
+
"--output", out,
|
|
117
|
+
"--aspect", this.reelAspect,
|
|
118
|
+
"--debug",
|
|
119
|
+
]);
|
|
120
|
+
const summary = stderr
|
|
121
|
+
.split("\n")
|
|
122
|
+
.map((l) => l.trim())
|
|
123
|
+
.filter((l) => l.startsWith("reframe_ball:"))
|
|
124
|
+
.pop();
|
|
125
|
+
if (summary) {
|
|
126
|
+
this.logger.info("Ball reframe stats", { courtId, summary });
|
|
127
|
+
}
|
|
128
|
+
if (!fs.existsSync(out)) {
|
|
129
|
+
this.logger.warn("Ball reframer produced no output; using full frame", {
|
|
130
|
+
courtId,
|
|
131
|
+
});
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
// Existence isn't enough — a 0-byte / corrupt file would then be trusted
|
|
135
|
+
// over the good raw clip. Require a probeable, non-zero-duration video.
|
|
136
|
+
if (!(await this.isPlayable(out))) {
|
|
137
|
+
this.logger.warn("Ball reframer output invalid; using full frame", {
|
|
138
|
+
courtId,
|
|
139
|
+
out,
|
|
140
|
+
});
|
|
141
|
+
fs.unlink(out, () => { }); // don't leave the bad file to be picked up
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
this.logger.info("Ball reframe complete", { courtId, out });
|
|
145
|
+
return out;
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
this.logger.warn("Ball reframe failed; using full frame", {
|
|
149
|
+
courtId,
|
|
150
|
+
error: error instanceof Error ? error.message : String(error),
|
|
151
|
+
});
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/** "16:9" -> 1.777…; null when unparseable (caller then just runs the pass). */
|
|
156
|
+
parseAspect(aspect) {
|
|
157
|
+
const m = aspect.match(/^\s*(\d+(?:\.\d+)?)\s*:\s*(\d+(?:\.\d+)?)\s*$/);
|
|
158
|
+
if (!m)
|
|
159
|
+
return null;
|
|
160
|
+
const w = parseFloat(m[1]);
|
|
161
|
+
const h = parseFloat(m[2]);
|
|
162
|
+
return h > 0 && w > 0 ? w / h : null;
|
|
163
|
+
}
|
|
164
|
+
// Width/height of `file`, or null on any probe failure (never throws).
|
|
165
|
+
probeDimensions(file) {
|
|
166
|
+
return new Promise((resolve) => {
|
|
167
|
+
const proc = (0, child_process_1.spawn)("ffprobe", [
|
|
168
|
+
"-v", "error",
|
|
169
|
+
"-select_streams", "v:0",
|
|
170
|
+
"-show_entries", "stream=width,height",
|
|
171
|
+
"-of", "csv=p=0",
|
|
172
|
+
file,
|
|
173
|
+
]);
|
|
174
|
+
let out = "";
|
|
175
|
+
proc.stdout?.on("data", (d) => (out += d.toString()));
|
|
176
|
+
proc.on("exit", (code) => {
|
|
177
|
+
if (code !== 0)
|
|
178
|
+
return resolve(null);
|
|
179
|
+
const m = out.trim().match(/(\d+)\s*,\s*(\d+)/);
|
|
180
|
+
resolve(m ? { width: parseInt(m[1], 10), height: parseInt(m[2], 10) } : null);
|
|
181
|
+
});
|
|
182
|
+
proc.on("error", () => resolve(null));
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
// True when ffprobe reports a positive duration for `file` (i.e. a real,
|
|
186
|
+
// non-empty video). Resolves false on any probe failure — never throws.
|
|
187
|
+
isPlayable(file) {
|
|
188
|
+
return new Promise((resolve) => {
|
|
189
|
+
const proc = (0, child_process_1.spawn)("ffprobe", [
|
|
190
|
+
"-v", "error",
|
|
191
|
+
"-show_entries", "format=duration",
|
|
192
|
+
"-of", "default=nw=1:nk=1",
|
|
193
|
+
file,
|
|
194
|
+
]);
|
|
195
|
+
let out = "";
|
|
196
|
+
proc.stdout?.on("data", (d) => {
|
|
197
|
+
out += d.toString();
|
|
198
|
+
});
|
|
199
|
+
proc.on("exit", (code) => {
|
|
200
|
+
const dur = parseFloat(out.trim());
|
|
201
|
+
resolve(code === 0 && Number.isFinite(dur) && dur > 0);
|
|
202
|
+
});
|
|
203
|
+
proc.on("error", () => resolve(false));
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
// Resolves with the process's stderr (used for the --debug summary line);
|
|
207
|
+
// rejects on non-zero exit, spawn error, or timeout.
|
|
208
|
+
runPython(args) {
|
|
209
|
+
return new Promise((resolve, reject) => {
|
|
210
|
+
// Low CPU priority so the OpenCV passes can't starve the live ffmpeg.
|
|
211
|
+
const lp = (0, lowPriority_1.withLowPriority)("python3", args);
|
|
212
|
+
const proc = (0, child_process_1.spawn)(lp.command, lp.args, {
|
|
213
|
+
stdio: ["ignore", "ignore", "pipe"],
|
|
214
|
+
});
|
|
215
|
+
let stderr = "";
|
|
216
|
+
proc.stderr?.on("data", (d) => {
|
|
217
|
+
stderr += d.toString();
|
|
218
|
+
});
|
|
219
|
+
const timeout = setTimeout(() => {
|
|
220
|
+
proc.kill("SIGKILL");
|
|
221
|
+
reject(new Error("python reframe timed out"));
|
|
222
|
+
}, this.timeoutMs);
|
|
223
|
+
proc.on("exit", (code) => {
|
|
224
|
+
clearTimeout(timeout);
|
|
225
|
+
if (code === 0)
|
|
226
|
+
resolve(stderr);
|
|
227
|
+
else
|
|
228
|
+
reject(new Error(`python exited ${code}: ${stderr.slice(-200)}`));
|
|
229
|
+
});
|
|
230
|
+
proc.on("error", (err) => {
|
|
231
|
+
clearTimeout(timeout);
|
|
232
|
+
reject(err); // e.g. python3 not installed
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
exports.PythonBallReframer = PythonBallReframer;
|
|
238
|
+
//# sourceMappingURL=PythonBallReframer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PythonBallReframer.js","sourceRoot":"","sources":["../../../../src/infrastructure/services/PythonBallReframer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { EventEmitter } from "events";
|
|
2
|
+
import { CourtScoreSignal, HighlightSignal, HighlightSignalSource } from "../../domain/services/HighlightSignalSource";
|
|
3
|
+
import { Logger } from "../../application/interfaces/Logger";
|
|
4
|
+
export declare class SerialHighlightListener extends EventEmitter implements HighlightSignalSource {
|
|
5
|
+
private readonly portPath;
|
|
6
|
+
private readonly baudRate;
|
|
7
|
+
private readonly logger;
|
|
8
|
+
private readonly forcePresent;
|
|
9
|
+
private readonly triggerFile;
|
|
10
|
+
private port;
|
|
11
|
+
private parser;
|
|
12
|
+
private lastTrafficAtMs;
|
|
13
|
+
private portOpenedAtMs;
|
|
14
|
+
private started;
|
|
15
|
+
private reconnectTimer;
|
|
16
|
+
private reconnectAttempts;
|
|
17
|
+
private triggerTimer;
|
|
18
|
+
private lastButtonSeq;
|
|
19
|
+
private serialLib;
|
|
20
|
+
private parserLib;
|
|
21
|
+
constructor(portPath: string, // "auto" or an explicit device path
|
|
22
|
+
baudRate: number, logger: Logger, forcePresent?: boolean, triggerFile?: string);
|
|
23
|
+
onHighlight(listener: (signal: HighlightSignal) => void): void;
|
|
24
|
+
onScore(listener: (signal: CourtScoreSignal) => void): void;
|
|
25
|
+
start(): void;
|
|
26
|
+
stop(): void;
|
|
27
|
+
private startTriggerFileWatch;
|
|
28
|
+
isDevicePresent(): boolean;
|
|
29
|
+
private openPort;
|
|
30
|
+
private handleLine;
|
|
31
|
+
/**
|
|
32
|
+
* A `score` packet: the board's current state, forwarded verbatim.
|
|
33
|
+
*
|
|
34
|
+
* Score packets are the one type that carries NO `source` field, so anything
|
|
35
|
+
* keying on `source` being present would drop them — switch on `type` only.
|
|
36
|
+
* Values are passed through untouched: interpreting "AD" or mapping the mode
|
|
37
|
+
* is the consumer's job, not the transport's.
|
|
38
|
+
*/
|
|
39
|
+
private handleScore;
|
|
40
|
+
private resolvePortPath;
|
|
41
|
+
private handlePortDown;
|
|
42
|
+
private teardownPort;
|
|
43
|
+
private scheduleReconnect;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=SerialHighlightListener.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SerialHighlightListener.d.ts","sourceRoot":"","sources":["../../../../src/infrastructure/services/SerialHighlightListener.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAItC,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,qBAAqB,EACtB,MAAM,6CAA6C,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,qCAAqC,CAAC;AAsE7D,qBAAa,uBACX,SAAQ,YACR,YAAW,qBAAqB;IAmB9B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAIvB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAxB9B,OAAO,CAAC,IAAI,CAAmC;IAC/C,OAAO,CAAC,MAAM,CAAuC;IACrD,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,YAAY,CAA+B;IAEnD,OAAO,CAAC,aAAa,CAAqB;IAI1C,OAAO,CAAC,SAAS,CAA4C;IAC7D,OAAO,CAAC,SAAS,CAA6D;gBAG3D,QAAQ,EAAE,MAAM,EAAE,oCAAoC;IACtD,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EAId,YAAY,GAAE,OAAe,EAC7B,WAAW,GAAE,MAAW;IAKpC,WAAW,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,GAAG,IAAI;IAI9D,OAAO,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,GAAG,IAAI;IAI3D,KAAK,IAAI,IAAI;IAoBb,IAAI,IAAI,IAAI;IAkBnB,OAAO,CAAC,qBAAqB;IAiBtB,eAAe,IAAI,OAAO;YAanB,QAAQ;IAwEtB,OAAO,CAAC,UAAU;IA8ElB;;;;;;;OAOG;IACH,OAAO,CAAC,WAAW;YAsBL,eAAe;IAwC7B,OAAO,CAAC,cAAc;IAOtB,OAAO,CAAC,YAAY;IAqBpB,OAAO,CAAC,iBAAiB;CAiB1B"}
|