api-amr/agv_main.ts
2025-06-04 19:15:02 +08:00

212 lines
6.3 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// main.ts
/// <reference lib="deno.unstable" />
// 导入 UUID 库请根据实际情况调整URL
import { v4 as uuidv4 } from "npm:uuid";
import { setupAgvWorker, initAgvWorker } from "./agv_manager.ts";
import { reconnectAllWorker, setupMasterWorker, updateDeviceListFromConfig } from "./master_manager.ts";
import { globalEventManager } from "./event_manager.ts";
// Load config and mappings from JSON files at runtime
const configText = await Deno.readTextFile("./config.json");
const config = JSON.parse(configText);
const mappingFile = config.mappingFile || "mapping.json";
const mappingsText = await Deno.readTextFile(`./${mappingFile}`);
const mappings = JSON.parse(mappingsText);
// Generate a unique instance ID from manufacturer and UUID
const instanceId = uuidv4();
// 添加全局事件监听器
globalEventManager.addEventListener("reconnect-all", (event: Event) => {
const customEvent = event as CustomEvent;
console.log("🎯 主线程收到全局重连事件:", customEvent.detail);
handleReconnectAll();
});
globalEventManager.addEventListener("grpc-connection-lost", (event: Event) => {
const customEvent = event as CustomEvent;
console.log("🎯 主线程收到 gRPC 连接丢失事件:", customEvent.detail);
// 可以添加特殊的 gRPC 重连逻辑
});
globalEventManager.addEventListener("device-status-update", (event: Event) => {
const customEvent = event as CustomEvent;
console.log("🎯 主线程收到设备状态更新事件:", customEvent.detail.data);
});
// 重连处理函数
function handleReconnectAll() {
console.log("agv_main: 执行全局重连");
reconnectAllWorker(kv, webWorker, masterWorker, agvWorker, config, mappings, instanceId);
}
// 初始化 downWorker 并支持自身重启
let downWorker: Worker;
function startDownWorker() {
console.log("agv_main: 启动 downWorker");
downWorker = new Worker(
new URL("./vda5050_transformer_worker.ts", import.meta.url).href,
{ type: "module" }
);
// 注册到全局事件管理器
globalEventManager.registerWorker("downWorker", downWorker);
// 初始化 downWorker
downWorker.postMessage({
type: "init",
mqtt: config.mqtt,
mappings,
instanceId
});
// 监听重启请求
downWorker.onmessage = (event: MessageEvent) => {
const message = event.data;
// 只处理非全局事件相关的消息
if (message.type === "reconnect-all" && message.type !== "dispatchGlobalEvent") {
console.log("agv_main: 收到 downWorker reconnect-all重启所有 Workers");
handleReconnectAll();
} else if (message.type === "reconnect-down") {
console.log("agv_main: 收到 downWorker reconnect-down重启 downWorker");
downWorker.postMessage({ type: "stop" });
downWorker.terminate();
startDownWorker();
}
};
}
startDownWorker();
// 打开 Deno KV 数据库Deno KV 在最新版本中为内置特性)
const kv = await Deno.openKv();
// // 启动 Web Worker 用于可视化界面
const webWorker = new Worker(
new URL("./web_worker.ts", import.meta.url).href,
{ type: "module" }
);
console.log("Web Worker 已启动");
const masterWorker = new Worker(
new URL("./vda_worker.ts", import.meta.url).href,
{ type: "module" }
);
const agvWorker = new Worker(
new URL("./agv_worker.ts", import.meta.url).href,
{ type: "module" }
);
// 注册所有 Worker 到全局事件管理器
globalEventManager.registerWorker("webWorker", webWorker);
globalEventManager.registerWorker("masterWorker", masterWorker);
globalEventManager.registerWorker("agvWorker", agvWorker);
reconnectAllWorker(kv, webWorker, masterWorker, agvWorker, config, mappings, instanceId);
// 监听配置文件变化,动态更新设备列表
const watcher = Deno.watchFs("./devices.json");
(async () => {
console.log("开始监控配置文件变化...");
for await (const event of watcher) {
if (event.paths.some((p) => p.endsWith("devices.json"))) {
console.log("检测到设备配置文件变化,更新设备列表...");
await updateDeviceListFromConfig(masterWorker, config, instanceId);
}
}
})();
// 处理 Ctrl+CSIGINT退出
Deno.addSignalListener("SIGINT", () => {
console.log("接收到 Ctrl+C主程序通知 Worker 退出...");
// 向所有 Worker 发送 shutdown 消息
agvWorker.postMessage("shutdown");
masterWorker.postMessage({ type: "shutdown" });
webWorker.postMessage({ type: "shutdown" });
// 通知 downWorker 关闭
downWorker.postMessage({ type: "shutdown" });
// 延时后终止 Worker 并退出主程序
setTimeout(() => {
agvWorker.terminate();
masterWorker.terminate();
webWorker.terminate();
downWorker.terminate();
console.log("所有 Worker 已终止,程序退出");
Deno.exit(0);
}, 2000);
});
// Web Worker 错误处理
webWorker.onerror = (error) => {
console.error("Web Worker 执行错误:", error);
};
// 发送导航订单的函数(示例订单)
function sendNavigationOrder() {
// 使用 UUID v4 生成订单号
const orderId = uuidv4();
console.log(`创建新的导航订单 ${orderId}`);
masterWorker.postMessage({
type: "sendOrder",
orderId: orderId,
nodes: [
{
nodeId: "start",
nodePosition: {
x: 0.0,
y: 0.0,
mapId: "warehouse",
theta: 0,
},
actions: [],
},
{
nodeId: "waypoint1",
nodePosition: {
x: 5.0,
y: 0.0,
mapId: "warehouse",
theta: 0,
},
actions: [],
},
{
nodeId: "destination",
nodePosition: {
x: 10.0,
y: 5.0,
mapId: "warehouse",
theta: 0,
},
actions: [],
},
],
});
}
// 取消订单的函数
function cancelOrder(orderId: string) {
console.log(`取消订单 ${orderId}`);
masterWorker.postMessage({
type: "cancelOrder",
orderId: orderId,
});
}
// 发送自定义命令设置给 Worker 的函数
function sendCustomCommand(cmd: string) {
console.log(`发送自定义命令设置: ${cmd}`);
masterWorker.postMessage({
type: "setCommand",
command: cmd,
});
}
// CLI moved to cli.ts
import { startCli } from "./cli.ts";
startCli(masterWorker, agvWorker, sendNavigationOrder, cancelOrder, sendCustomCommand, instanceId);
console.log("VDA 5050 控制程序已启动,输入命令或按 Ctrl+C 退出程序");