diff --git a/src/CncSimulator/Admin/AdminHandler.cs b/src/CncSimulator/Admin/AdminHandler.cs index 27cf515..00f3782 100644 --- a/src/CncSimulator/Admin/AdminHandler.cs +++ b/src/CncSimulator/Admin/AdminHandler.cs @@ -5,26 +5,27 @@ namespace CncSimulator.Admin { /// /// 管理页面HTML生成器。 - /// 生成总管理页面和单地址管理页面的完整HTML+CSS+JS。 + /// 总管理页面:显示数据库地址+手动启停。 + /// 单地址页面:设备卡片+统计+设备增减。 /// public class AdminHandler { - /// 生成总管理页面(网关页面) + /// 生成总管理页面 public string BuildGatewayPage(SimulatorEngine engine) { var sb = new StringBuilder(); - sb.AppendLine(""); - sb.AppendLine(""); + sb.AppendLine(""); sb.AppendLine(""); sb.AppendLine("CNC 模拟采集服务 - 总管理"); sb.AppendLine(""); sb.AppendLine("
"); sb.AppendLine("

CNC 模拟采集服务

"); sb.AppendLine("
"); sb.AppendLine(" "); sb.AppendLine(" "); + sb.AppendLine(" "); sb.AppendLine("
"); sb.AppendLine("
"); sb.AppendLine("
"); - sb.AppendLine("

地址列表

"); - sb.AppendLine(" "); - sb.AppendLine("
名称端口状态设备数数据频率请求次数操作
"); + sb.AppendLine("

数据库采集地址

"); + sb.AppendLine(" "); + sb.AppendLine("
ID名称机床数状态端口频率(秒)总零件操作
"); sb.AppendLine("
"); - sb.AppendLine("

控制台日志

"); - sb.AppendLine("
加载中...
"); + sb.AppendLine("

运行中模拟端口

"); + sb.AppendLine(" "); + sb.AppendLine("
名称端口设备请求次数总零件操作
"); sb.AppendLine("
"); sb.AppendLine("
"); sb.AppendLine(""); return sb.ToString(); @@ -76,15 +102,14 @@ namespace CncSimulator.Admin public string BuildSingleAddressPage(SimulatorServer server) { var sb = new StringBuilder(); - sb.AppendLine(""); - sb.AppendLine(""); + sb.AppendLine(""); sb.AppendLine(""); sb.AppendLine("" + server.Name + " - 模拟管理"); sb.AppendLine(""); sb.AppendLine("
"); sb.AppendLine("

" + server.Name + " (端口 " + server.Port + ")

"); @@ -123,6 +153,20 @@ namespace CncSimulator.Admin sb.AppendLine("
"); sb.AppendLine("
"); sb.AppendLine("
"); + + // 统计概览 + sb.AppendLine("

统计概览

"); + sb.AppendLine("
加载中...
"); + sb.AppendLine("
"); + + // 零件统计表(按设备+NC程序) + sb.AppendLine("

零件统计(按设备+NC程序)

"); + sb.AppendLine(" "); + sb.AppendLine(" "); + sb.AppendLine(" "); + sb.AppendLine("
设备编码描述NC程序零件数当前零件
"); + sb.AppendLine("
"); + // 全局设置 sb.AppendLine("

全局设置

"); sb.AppendLine("
"); @@ -138,40 +182,65 @@ namespace CncSimulator.Admin sb.AppendLine("
"); sb.AppendLine(" "); sb.AppendLine(" "); sb.AppendLine("
"); sb.AppendLine("
"); - // 设备状态卡片 - sb.AppendLine("

设备状态卡片

"); + + // 设备状态卡片(含添加/移除) + sb.AppendLine("

设备状态

"); sb.AppendLine("
加载中...
"); + sb.AppendLine("
"); + sb.AppendLine(" "); + sb.AppendLine(" "); + sb.AppendLine(" "); + sb.AppendLine("
"); sb.AppendLine("
"); + // JSON预览 - sb.AppendLine("

当前返回JSON预览

"); + sb.AppendLine("

当前返回JSON

"); sb.AppendLine(" "); sb.AppendLine("
加载中...
"); sb.AppendLine("
"); + // 日志 - sb.AppendLine("

返回数据日志(最近100条)

"); + sb.AppendLine("

日志

"); sb.AppendLine(" "); - sb.AppendLine(" "); + sb.AppendLine(" "); sb.AppendLine(" "); sb.AppendLine("
#时间设备数关键数据耗时操作
#时间设备数关键数据耗时
"); sb.AppendLine("
"); - // 统计 - sb.AppendLine("

统计

"); - sb.AppendLine("
加载中...
"); - sb.AppendLine("
"); sb.AppendLine("
"); + // JavaScript sb.AppendLine(""); return sb.ToString(); } diff --git a/src/CncSimulator/CncSimulator.csproj b/src/CncSimulator/CncSimulator.csproj index 06b24d3..c9f1dd4 100644 --- a/src/CncSimulator/CncSimulator.csproj +++ b/src/CncSimulator/CncSimulator.csproj @@ -17,6 +17,7 @@ + diff --git a/src/CncSimulator/Config/SimulatorConfig.cs b/src/CncSimulator/Config/SimulatorConfig.cs index f85fbed..36b3549 100644 --- a/src/CncSimulator/Config/SimulatorConfig.cs +++ b/src/CncSimulator/Config/SimulatorConfig.cs @@ -10,7 +10,15 @@ namespace CncSimulator.Config [JsonProperty("gatewayPort")] public int GatewayPort { get; set; } = 9000; - /// 采集地址列表 + /// 数据库连接字符串 + [JsonProperty("dbConnection")] + public string DbConnection { get; set; } = "Server=localhost;Database=cnc_business;Uid=root;Pwd=root;Charset=utf8mb4;SslMode=None;"; + + /// 数据变化频率(秒)- 全局默认值 + [JsonProperty("defaultDataChangeInterval")] + public int DefaultDataChangeInterval { get; set; } = 10; + + /// 采集地址列表(运行时动态创建) [JsonProperty("addresses")] public List Addresses { get; set; } = new List(); } @@ -18,6 +26,10 @@ namespace CncSimulator.Config /// 单个采集地址配置 public class AddressConfig { + /// 数据库中的采集地址ID + [JsonProperty("dbAddressId")] + public int DbAddressId { get; set; } + /// 显示名称 [JsonProperty("name")] public string Name { get; set; } diff --git a/src/CncSimulator/Core/DatabaseReader.cs b/src/CncSimulator/Core/DatabaseReader.cs new file mode 100644 index 0000000..de1833e --- /dev/null +++ b/src/CncSimulator/Core/DatabaseReader.cs @@ -0,0 +1,108 @@ +using System; +using System.Collections.Generic; +using MySqlConnector; +using CncSimulator.Config; + +namespace CncSimulator.Core +{ + /// + /// 数据库读取器。从MariaDB读取采集地址和机床信息。 + /// + public class DatabaseReader + { + private readonly string _connectionString; + + public DatabaseReader(string connectionString) + { + _connectionString = connectionString; + } + + /// 测试数据库连接 + public bool TestConnection(out string error) + { + error = ""; + try + { + using (var conn = new MySqlConnection(_connectionString)) + { + conn.Open(); + return true; + } + } + catch (Exception ex) + { + error = ex.Message; + return false; + } + } + + /// 读取所有采集地址及其机床 + public List ReadAddresses() + { + var addresses = new List(); + + using (var conn = new MySqlConnection(_connectionString)) + { + conn.Open(); + + // 读取采集地址 + string addrSql = "SELECT id, name, url FROM cnc_collect_address ORDER BY id"; + using (var cmd = new MySqlCommand(addrSql, conn)) + using (var reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + addresses.Add(new AddressInfo + { + DbId = reader.GetInt32("id"), + Name = reader.GetString("name"), + Url = reader.IsDBNull(reader.GetOrdinal("url")) ? "" : reader.GetString("url"), + Machines = new List() + }); + } + } + + // 为每个地址读取机床 + foreach (var addr in addresses) + { + string machineSql = "SELECT id, device_code, name FROM cnc_machine WHERE collect_address_id = @addrId ORDER BY id"; + using (var cmd = new MySqlCommand(machineSql, conn)) + { + cmd.Parameters.AddWithValue("@addrId", addr.DbId); + using (var reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + addr.Machines.Add(new MachineInfo + { + Id = reader.GetInt32("id"), + DeviceCode = reader.GetString("device_code"), + Name = reader.IsDBNull(reader.GetOrdinal("name")) ? "" : reader.GetString("name") + }); + } + } + } + } + } + + return addresses; + } + } + + /// 采集地址信息(从数据库读取) + public class AddressInfo + { + public int DbId { get; set; } + public string Name { get; set; } + public string Url { get; set; } + public List Machines { get; set; } + } + + /// 机床信息(从数据库读取) + public class MachineInfo + { + public int Id { get; set; } + public string DeviceCode { get; set; } + public string Name { get; set; } + } +} diff --git a/src/CncSimulator/Core/SimulatorEngine.cs b/src/CncSimulator/Core/SimulatorEngine.cs index d7391d1..ca5c68e 100644 --- a/src/CncSimulator/Core/SimulatorEngine.cs +++ b/src/CncSimulator/Core/SimulatorEngine.cs @@ -1,17 +1,16 @@ using System; using System.Collections.Generic; -using System.IO; using System.Net; using System.Text; using CncSimulator.Admin; using CncSimulator.Config; -using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace CncSimulator.Core { /// - /// 引擎主控。管理多个SimulatorServer实例和总管理页面。 + /// 引擎主控。启动时只开启9000管理页面,从数据库读取地址信息, + /// 用户手动启动各端口模拟。 /// public class SimulatorEngine { @@ -19,48 +18,120 @@ namespace CncSimulator.Core private SimulatorConfig _config; private HttpListener _gatewayListener; private readonly AdminHandler _adminHandler = new AdminHandler(); - private bool _running; + private DatabaseReader _dbReader; + private List _dbAddresses = new List(); + private int _nextPort; - /// 所有地址服务 + /// 所有已创建的地址服务 public List Servers => _servers; - /// 加载配置并创建所有SimulatorServer + /// 数据库中的采集地址列表 + public List DbAddresses => _dbAddresses; + + /// 配置 + public SimulatorConfig Config => _config; + + /// 加载数据库配置 public void LoadConfig(SimulatorConfig config) { _config = config; - _servers.Clear(); + _nextPort = config.GatewayPort + 1; + } - foreach (var addr in config.Addresses) + /// 连接数据库并读取采集地址 + public bool LoadFromDatabase(out string error) + { + _dbReader = new DatabaseReader(_config.DbConnection); + if (!_dbReader.TestConnection(out error)) { - var server = new SimulatorServer(addr); - _servers.Add(server); + return false; } + + _dbAddresses = _dbReader.ReadAddresses(); + return true; } - /// 启动所有服务 - public void StartAll() + /// 只启动总管理页面(不启动模拟端口) + public void StartGateway() { - _running = true; + StartGatewayListener(); + } - // 启动所有地址服务 - foreach (var server in _servers) + /// 为指定采集地址创建并启动模拟端口 + public SimulatorServer StartAddress(int dbAddressId, int? port = null, int? interval = null) + { + // 查找数据库中的地址信息 + AddressInfo addrInfo = null; + foreach (var a in _dbAddresses) { - server.Start(); + if (a.DbId == dbAddressId) { addrInfo = a; break; } } + if (addrInfo == null) return null; - // 启动总管理页面 - StartGateway(); + // 检查是否已存在 + foreach (var s in _servers) + { + if (s.Config.DbAddressId == dbAddressId) return s; + } + + // 分配端口 + int usePort = port ?? _nextPort; + if (usePort <= _config.GatewayPort) usePort = _config.GatewayPort + 1; + _nextPort = usePort + 1; + + // 创建配置 + var addrConfig = new AddressConfig + { + DbAddressId = dbAddressId, + Name = addrInfo.Name + "模拟", + Port = usePort, + Brand = "fanuc", + DataChangeInterval = interval ?? _config.DefaultDataChangeInterval, + ScenarioMode = "auto" + }; + + // 为每台机床创建设备配置 + foreach (var m in addrInfo.Machines) + { + addrConfig.Devices.Add(new DeviceConfig + { + DeviceCode = m.DeviceCode, + Desc = m.Name, + InitialProgram = "O0001", + InitialPartCount = 0 + }); + } + + // 创建并启动服务 + var server = new SimulatorServer(addrConfig); + server.Start(); // 启动HttpListener + Timer(数据模拟) + _servers.Add(server); + + Console.WriteLine($" [✓] 启动模拟: {addrConfig.Name} → http://localhost:{usePort}/ ({addrInfo.Machines.Count}台设备)"); + return server; + } + + /// 停止指定地址的模拟 + public void StopAddress(int dbAddressId) + { + for (int i = _servers.Count - 1; i >= 0; i--) + { + if (_servers[i].Config.DbAddressId == dbAddressId) + { + _servers[i].Shutdown(); + _servers.RemoveAt(i); + } + } } /// 停止所有服务 public void StopAll() { - _running = false; foreach (var server in _servers) { server.Shutdown(); } - + _servers.Clear(); try { _gatewayListener?.Stop(); } catch { } } @@ -82,13 +153,16 @@ namespace CncSimulator.Core { arr.Add(new JObject { + ["dbAddressId"] = server.Config.DbAddressId, ["name"] = server.Name, ["port"] = server.Port, ["isRunning"] = server.IsRunning, ["totalDevices"] = server.TotalDeviceCount, ["onlineDevices"] = server.OnlineDeviceCount, ["requestCount"] = server.RequestCount, - ["dataChangeInterval"] = server.Config.DataChangeInterval + ["dataChangeInterval"] = server.Config.DataChangeInterval, + ["totalParts"] = server.GetTotalParts(), + ["partsByDevice"] = server.GetPartsByDeviceAndProgram() }); } return arr; @@ -96,7 +170,7 @@ namespace CncSimulator.Core // ===== 总管理页面 ===== - private void StartGateway() + private void StartGatewayListener() { try { @@ -138,21 +212,87 @@ namespace CncSimulator.Core string html = _adminHandler.BuildGatewayPage(this); SendResponse(ctx, 200, html, "text/html; charset=utf-8"); } + else if (path == "/admin/api/db-addresses") + { + // 返回数据库中的采集地址列表 + var arr = new JArray(); + foreach (var a in _dbAddresses) + { + // 检查是否已在运行 + bool running = false; + int runningPort = 0; + foreach (var s in _servers) + { + if (s.Config.DbAddressId == a.DbId) + { + running = true; + runningPort = s.Port; + break; + } + } + arr.Add(new JObject + { + ["dbId"] = a.DbId, + ["name"] = a.Name, + ["url"] = a.Url, + ["machineCount"] = a.Machines.Count, + ["machines"] = JArray.FromObject(a.Machines), + ["isRunning"] = running, + ["runningPort"] = runningPort + }); + } + SendResponse(ctx, 200, arr.ToString(), "application/json"); + } else if (path == "/admin/api/status") { var summary = GetStatusSummary(); SendResponse(ctx, 200, summary.ToString(), "application/json"); } - else if (path == "/admin/api/start") + else if (path == "/admin/api/start-address") + { + string body = ReadRequestBody(ctx); + var obj = JObject.Parse(body); + int dbId = obj["dbAddressId"]?.Value() ?? 0; + int? port = obj["port"]?.Value(); + int? interval = obj["interval"]?.Value(); + var server = StartAddress(dbId, port, interval); + SendResponse(ctx, 200, server != null ? "{\"ok\":true,\"port\":" + server.Port + "}" : "{\"ok\":false}", "application/json"); + } + else if (path == "/admin/api/stop-address") + { + string body = ReadRequestBody(ctx); + var obj = JObject.Parse(body); + int dbId = obj["dbAddressId"]?.Value() ?? 0; + StopAddress(dbId); + SendResponse(ctx, 200, "{\"ok\":true}", "application/json"); + } + else if (path == "/admin/api/start-all") { - foreach (var s in _servers) if (!s.IsRunning) s.Start(); + foreach (var a in _dbAddresses) + { + bool alreadyRunning = false; + foreach (var s in _servers) + { + if (s.Config.DbAddressId == a.DbId) { alreadyRunning = true; break; } + } + if (!alreadyRunning) StartAddress(a.DbId); + } SendResponse(ctx, 200, "{\"ok\":true}", "application/json"); } - else if (path == "/admin/api/stop") + else if (path == "/admin/api/stop-all") { - foreach (var s in _servers) s.Stop(); + foreach (var server in _servers.ToArray()) + { + server.Shutdown(); + } + _servers.Clear(); SendResponse(ctx, 200, "{\"ok\":true}", "application/json"); } + else if (path == "/admin/api/reload-db") + { + _dbAddresses = _dbReader.ReadAddresses(); + SendResponse(ctx, 200, "{\"ok\":true,\"count\":" + _dbAddresses.Count + "}", "application/json"); + } else { SendResponse(ctx, 200, "CNC模拟采集服务网关。请访问 /admin 管理页面。", "text/plain"); @@ -160,7 +300,15 @@ namespace CncSimulator.Core } catch (Exception ex) { - try { SendResponse(ctx, 500, ex.Message, "text/plain"); } catch { } + try { SendResponse(ctx, 500, "{\"error\":\"" + ex.Message.Replace("\"", "'") + "\"}", "application/json"); } catch { } + } + } + + private string ReadRequestBody(HttpListenerContext ctx) + { + using (var reader = new System.IO.StreamReader(ctx.Request.InputStream, Encoding.UTF8)) + { + return reader.ReadToEnd(); } } diff --git a/src/CncSimulator/Core/SimulatorServer.cs b/src/CncSimulator/Core/SimulatorServer.cs index ef03b64..83ddeea 100644 --- a/src/CncSimulator/Core/SimulatorServer.cs +++ b/src/CncSimulator/Core/SimulatorServer.cs @@ -73,6 +73,74 @@ namespace CncSimulator.Core /// 日志记录器引用 public LogRecorder LogRecorder => _logRecorder; + /// 获取本次启动后所有设备的总加工零件数 + public int GetTotalParts() + { + int total = 0; + foreach (var d in _devices) total += d.State.TotalPartsSinceStart; + return total; + } + + /// 获取按设备+NC程序名统计的零件数 + public JObject GetPartsByDeviceAndProgram() + { + var result = new JObject(); + foreach (var dev in _devices) + { + var s = dev.State; + var programs = new JObject(); + foreach (var kvp in s.PartsByProgram) + { + programs[kvp.Key] = kvp.Value; + } + result[s.DeviceCode] = new JObject + { + ["desc"] = s.Desc, + ["totalParts"] = s.TotalPartsSinceStart, + ["currentProgram"] = s.ProgramName, + ["currentPartCount"] = s.PartCount, + ["programs"] = programs + }; + } + return result; + } + + /// 添加一台模拟设备 + public void AddDevice(string deviceCode, string desc) + { + var devCfg = new Config.DeviceConfig + { + DeviceCode = deviceCode, + Desc = desc, + InitialProgram = "O0001", + InitialPartCount = 0 + }; + var sim = new DeviceSimulator(devCfg, _config.DataChangeInterval); + _devices.Add(sim); + + var player = new ScenarioPlayer( + sim, + _config.ScenarioMode == "auto", + Environment.TickCount + _devices.Count * 1000 + deviceCode.GetHashCode() + ); + _players.Add(player); + } + + /// 移除一台模拟设备 + public bool RemoveDevice(string deviceCode) + { + for (int i = 0; i < _devices.Count; i++) + { + if (_devices[i].State.DeviceCode == deviceCode) + { + _devices.RemoveAt(i); + _players.RemoveAt(i); + return true; + } + } + return false; + } + public SimulatorServer(AddressConfig config) { _config = config; @@ -483,6 +551,34 @@ namespace CncSimulator.Core SendTextResponse(ctx, 200, logsArr.ToString(), "application/json"); break; + case "/admin/api/stats": + var stats = new JObject + { + ["totalDevices"] = _devices.Count, + ["onlineDevices"] = OnlineDeviceCount, + ["totalParts"] = GetTotalParts(), + ["partsByDevice"] = GetPartsByDeviceAndProgram() + }; + SendTextResponse(ctx, 200, stats.ToString(), "application/json"); + break; + + case "/admin/api/add-device": + string addBody = ReadRequestBody(ctx); + var addObj = JObject.Parse(addBody); + AddDevice( + addObj["deviceCode"]?.ToString(), + addObj["desc"]?.ToString() + ); + SendTextResponse(ctx, 200, "{\"ok\":true}", "application/json"); + break; + + case "/admin/api/remove-device": + string remBody = ReadRequestBody(ctx); + var remObj = JObject.Parse(remBody); + bool removed = RemoveDevice(remObj["deviceCode"]?.ToString()); + SendTextResponse(ctx, 200, removed ? "{\"ok\":true}" : "{\"ok\":false}", "application/json"); + break; + default: SendJsonResponse(ctx, 404, "{\"error\":\"Unknown API\"}"); break; diff --git a/src/CncSimulator/Device/DeviceSimulator.cs b/src/CncSimulator/Device/DeviceSimulator.cs index d0fd5ce..14ee454 100644 --- a/src/CncSimulator/Device/DeviceSimulator.cs +++ b/src/CncSimulator/Device/DeviceSimulator.cs @@ -117,6 +117,11 @@ namespace CncSimulator.Device { case "machining": _state.PartCount++; + _state.TotalPartsSinceStart++; + // 按NC程序名累计零件数 + if (!_state.PartsByProgram.ContainsKey(_state.ProgramName)) + _state.PartsByProgram[_state.ProgramName] = 0; + _state.PartsByProgram[_state.ProgramName]++; _state.RunStatus = 3; _state.DeviceStatus = 1; _state.OperateMode = 1; diff --git a/src/CncSimulator/Device/DeviceState.cs b/src/CncSimulator/Device/DeviceState.cs index 11ad840..713fc87 100644 --- a/src/CncSimulator/Device/DeviceState.cs +++ b/src/CncSimulator/Device/DeviceState.cs @@ -1,3 +1,5 @@ +using System.Collections.Generic; + namespace CncSimulator.Device { /// 单台模拟设备的完整状态 @@ -78,5 +80,12 @@ namespace CncSimulator.Device // ===== 内部辅助 ===== /// 数据变化间隔(秒) public int DataChangeInterval { get; set; } = 10; + + // ===== 统计信息 ===== + /// 本次启动后累计总加工零件数 + public int TotalPartsSinceStart { get; set; } = 0; + + /// 按NC程序名统计的零件数(程序名 → 零件数) + public Dictionary PartsByProgram { get; set; } = new Dictionary(); } } diff --git a/src/CncSimulator/Program.cs b/src/CncSimulator/Program.cs index 7cf7ca2..a677acc 100644 --- a/src/CncSimulator/Program.cs +++ b/src/CncSimulator/Program.cs @@ -47,14 +47,32 @@ namespace CncSimulator Console.WriteLine($" - {addr.Name} (:{addr.Port}) {addr.Devices.Count}台设备"); } - // 创建并启动引擎 + // 创建引擎 var engine = new SimulatorEngine(); engine.LoadConfig(config); - Console.WriteLine("\n启动服务..."); - engine.StartAll(); + // 从数据库读取采集地址和机床 + Console.WriteLine("\n连接数据库..."); + if (engine.LoadFromDatabase(out string dbError)) + { + Console.WriteLine($" [✓] 数据库连接成功,读取到 {engine.DbAddresses.Count} 个采集地址"); + foreach (var a in engine.DbAddresses) + { + Console.WriteLine($" - {a.Name} ({a.Machines.Count}台机床)"); + } + } + else + { + Console.WriteLine($" [✗] 数据库连接失败: {dbError}"); + Console.WriteLine(" 将以空配置启动,可在管理界面手动配置"); + } + + // 只启动管理页面(不自动启动模拟端口) + Console.WriteLine("\n启动管理页面..."); + engine.StartGateway(); - Console.WriteLine("\n按任意键退出..."); + Console.WriteLine("\n请在浏览器中打开管理页面配置并启动模拟。"); + Console.WriteLine("按任意键退出..."); Console.ReadKey(); engine.StopAll(); diff --git a/src/CncSimulator/simulator.json b/src/CncSimulator/simulator.json index ad6963f..2ed5ac4 100644 --- a/src/CncSimulator/simulator.json +++ b/src/CncSimulator/simulator.json @@ -1,53 +1,6 @@ { "gatewayPort": 9000, - "addresses": [ - { - "name": "FANUC-1号模拟", - "port": 9001, - "brand": "fanuc", - "dataChangeInterval": 10, - "scenarioMode": "auto", - "devices": [ - { - "deviceCode": "CNC-A001", - "desc": "西栋1号", - "initialProgram": "O0001", - "initialPartCount": 50 - }, - { - "deviceCode": "CNC-006", - "desc": "6号机床", - "initialProgram": "O0002", - "initialPartCount": 120 - }, - { - "deviceCode": "CNC-008", - "desc": "8号机床", - "initialProgram": "O0003", - "initialPartCount": 0 - } - ] - }, - { - "name": "FANUC-2号模拟", - "port": 9002, - "brand": "fanuc", - "dataChangeInterval": 15, - "scenarioMode": "auto", - "devices": [ - { - "deviceCode": "CNC-B002", - "desc": "B栋2号", - "initialProgram": "1566.NC", - "initialPartCount": 80 - }, - { - "deviceCode": "CNC-005", - "desc": "验证机床", - "initialProgram": "TEST001", - "initialPartCount": 10 - } - ] - } - ] + "dbConnection": "Server=localhost;Database=cnc_business;Uid=root;Pwd=root;Charset=utf8mb4;SslMode=None;", + "defaultDataChangeInterval": 10, + "addresses": [] }