212 lines
6.3 KiB
TypeScript
212 lines
6.3 KiB
TypeScript
![]() |
// 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+C(SIGINT)退出
|
|||
|
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 退出程序");
|