api-amr/agv_main.ts

212 lines
6.3 KiB
TypeScript
Raw Normal View History

2025-06-04 19:15:02 +08:00
// 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 退出程序");