- 协议与 C# 版 card-printer-agent 逐字段对齐(38200-38202 顺延、CORS *、串行任务队列、30 分钟保留) - macOS CUPS 后端:lpoptions 队列发现 + lp 参数列表提交(LC_ALL=C 防本地化粘连坑) - --mock 模拟模式 + bin/agent.dart headless 入口 + 测试卡生成工具 - 真机验收:HiTi CS-200e status 就绪 + 真实出卡;macOS 通用二进制构建通过 - App Sandbox 已关闭(服务需绑回环端口并调用 lp 子进程);zaxprint URL scheme 已注册
88 lines
2.5 KiB
Dart
88 lines
2.5 KiB
Dart
import 'dart:async';
|
||
|
||
import 'print/backend.dart';
|
||
import 'print/mock_backend.dart';
|
||
import 'server/http_server.dart';
|
||
import 'server/print_queue.dart';
|
||
|
||
/// 启动参数:--mock 模拟打印;--port=NNN / --port NNN 指定监听端口(默认 38200-38202 顺延)。
|
||
class AgentOptions {
|
||
AgentOptions({this.mock = false, this.port});
|
||
|
||
final bool mock;
|
||
final int? port;
|
||
|
||
factory AgentOptions.parse(List<String> args) {
|
||
var mock = false;
|
||
int? port;
|
||
for (var i = 0; i < args.length; i++) {
|
||
final arg = args[i];
|
||
if (arg == '--mock') {
|
||
mock = true;
|
||
} else if (arg.startsWith('--port=')) {
|
||
port = int.tryParse(arg.substring('--port='.length));
|
||
} else if ((arg == '--port' || arg == '-p') && i + 1 < args.length) {
|
||
port = int.tryParse(args[++i]);
|
||
}
|
||
}
|
||
return AgentOptions(mock: mock, port: port);
|
||
}
|
||
}
|
||
|
||
/// 运行日志环形缓冲(GUI 展示用),同时打到 stdout。
|
||
class AgentLog {
|
||
final lines = <String>[];
|
||
final _controller = StreamController<String>.broadcast();
|
||
|
||
Stream<String> get stream => _controller.stream;
|
||
|
||
void write(String line) {
|
||
final stamped = '${DateTime.now().toIso8601String().substring(11, 19)} $line';
|
||
lines.add(stamped);
|
||
if (lines.length > 500) {
|
||
lines.removeRange(0, lines.length - 500);
|
||
}
|
||
// ignore: avoid_print
|
||
print(stamped);
|
||
_controller.add(stamped);
|
||
}
|
||
|
||
void dispose() => _controller.close();
|
||
}
|
||
|
||
/// 助手核心:组合打印后端、任务队列与 HTTP 服务(Flutter 窗口与 headless 入口共用)。
|
||
class Agent {
|
||
Agent(this.options) : log = AgentLog();
|
||
|
||
final AgentOptions options;
|
||
final AgentLog log;
|
||
|
||
late final PrintQueue queue;
|
||
late final PrintBackend backend;
|
||
late final AgentHttpServer server;
|
||
int? port;
|
||
|
||
Future<int> start() async {
|
||
final backendName = osBackendName();
|
||
backend = options.mock ? MockBackend(onLog: log.write) : createOsBackend(onLog: log.write);
|
||
queue = PrintQueue(backend, onLog: log.write);
|
||
server = AgentHttpServer(
|
||
queue: queue,
|
||
backend: backend,
|
||
mock: options.mock,
|
||
manifestBackendName: backendName,
|
||
);
|
||
final ports = options.port == null ? const [38200, 38201, 38202] : <int>[options.port!];
|
||
port = await server.start(candidatePorts: ports);
|
||
log.write('饭卡打印助手已启动 http://127.0.0.1:$port'
|
||
'(后端=$backendName,mock=${options.mock},agent=desktop-plugin)');
|
||
return port!;
|
||
}
|
||
|
||
Future<void> stop() async {
|
||
await server.stop();
|
||
queue.dispose();
|
||
log.dispose();
|
||
}
|
||
}
|