feat: 饭卡打印助手 Flutter 版(Phase 1/2:协议服务器 + macOS CUPS 真机打印)
- 协议与 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 已注册
This commit is contained in:
commit
689a07ca44
46 files changed
+2986
No files matched your search
@@ -0,0 +1,54 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
/// 外部命令执行失败(非零退出/超时/无法启动)。
|
||||
class CommandException implements Exception {
|
||||
CommandException(this.message);
|
||||
|
||||
final String message;
|
||||
|
||||
@override
|
||||
String toString() => message;
|
||||
}
|
||||
|
||||
/// 运行外部命令(lp/lpoptions/lpstat)并返回标准输出。
|
||||
///
|
||||
/// 一律用参数列表传参不经过 shell,杜绝命令注入;
|
||||
/// 强制 LC_ALL=C 英文输出(macOS 会把 lpstat/lp 本地化,中文系统队列名与状态词粘连无法按空格解析)。
|
||||
Future<String> runCommand(
|
||||
String executable,
|
||||
List<String> arguments, {
|
||||
int timeoutMs = 15000,
|
||||
bool tolerateExit = false,
|
||||
}) async {
|
||||
final Process process;
|
||||
try {
|
||||
process = await Process.start(
|
||||
executable,
|
||||
arguments,
|
||||
environment: const {'LC_ALL': 'C', 'LANG': 'C'},
|
||||
);
|
||||
} on ProcessException catch (e) {
|
||||
throw CommandException('无法启动 $executable:${e.message}');
|
||||
}
|
||||
|
||||
// stdout/stderr 立即挂上消费 Future,避免管道缓冲区写满导致死锁
|
||||
final stdoutFuture = process.stdout.transform(utf8.decoder).join();
|
||||
final stderrFuture = process.stderr.transform(utf8.decoder).join();
|
||||
|
||||
final int exitCode;
|
||||
try {
|
||||
exitCode = await process.exitCode.timeout(Duration(milliseconds: timeoutMs));
|
||||
} on TimeoutException {
|
||||
process.kill();
|
||||
throw CommandException('$executable 执行超时');
|
||||
}
|
||||
|
||||
final out = await stdoutFuture;
|
||||
if (exitCode != 0 && !tolerateExit) {
|
||||
final err = await stderrFuture;
|
||||
throw CommandException('$executable 返回 $exitCode:${err.trim()}');
|
||||
}
|
||||
return out;
|
||||
}
|
||||
Reference in new issue
Block a user