MESシステムにおいて、ラインのワークステーション配置や作業計画を効率的に管理するWinFormベースの中間ウェアコンポーネントを開発します。このコンポーネントは、複数の指令端末に対応し、製品の移動から作業実行までのプロセスを包括的にサポートします。
一、基本設計構造
1. 全体アーキテクチャ(多指令モード)
MESデータベースと連携し、ERP/資材システム、工程システム、ライン実行端末との双方向通信を通じて、以下の主要機能を実現します。
- 資材調達計画
- レイアウト設定完了
- 工程パラメータ指令
- データ同期
- 作業指示の分散・状態同期
2. 核心ビジネスモデル
| モジュール | 主要エンティティ | キー属性 |
|---|---|---|
| 資材調達 | 調達計画 | 計画番号、ライン/工段、資材コード/数量、調達ステータス、時間枠 |
| ワークステーションレイアウト | ライン/工段/工位 | 階層コード、座標位置、サイズ、レイアウトステータス、資材バインドステータス |
| 作業計画 | 工位作業計画 | 計画番号、工位コード、関連調達計画、作業数量、工程パラメータ、実行ステータス |
| 多指令スケジューリング | スケジュール指令 | 指令ID、送信元/受信先、指令タイプ、関連エンティティ、実行ステータス、タイムスタンプ |
二、コード実装
1. コアデータモデル
// ==================== 資材調達モデル ====================
public class MesAllotPlan
{
public string PlanId { get; set; }
public string LineCode { get; set; }
public string MaterialCode { get; set; }
public decimal Quantity { get; set; }
public string Status { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
}
// ==================== ワークステーションモデル ====================
public class MesStationLayout
{
public string StationId { get; set; }
public int XPosition { get; set; }
public int YPosition { get; set; }
public int Width { get; set; }
public int Height { get; set; }
public string Type { get; set; }
public string MaterialStatus { get; set; }
public string JobStatus { get; set; }
}
// ==================== 作業計画モデル ====================
public class MesJobPlan
{
public string JobId { get; set; }
public string StationId { get; set; }
public decimal WorkQuantity { get; set; }
public string ProcessData { get; set; }
public string Status { get; set; }
}
// ==================== 指令モデル ====================
public class MesDispatchCommand
{
public string CommandId { get; set; }
public string Source { get; set; }
public string Target { get; set; }
public string CommandType { get; set; }
public string Content { get; set; }
public string Status { get; set; }
}
2. 可視化コントロール
/// <summary>
/// ワークステーションのレイアウト可視化コントロール
/// </summary>
public partial class MesStationControl : UserControl
{
private MesStationLayout _selectedStation;
private float _scaleFactor = 1.0f;
public MesStationControl()
{
InitializeComponent();
DoubleBuffered = true;
SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true);
}
protected override void OnPaint(PaintEventArgs e)
{
Graphics g = e.Graphics;
g.ScaleTransform(_scaleFactor, _scaleFactor);
// ワークステーション描画
foreach (var station in GetStations())
{
var rect = new Rectangle(station.XPosition, station.YPosition, station.Width, station.Height);
g.FillRectangle(new SolidBrush(GetStatusColor(station.MaterialStatus)), rect);
g.DrawRectangle(Pens.Black, rect);
g.DrawString(station.StationId, Font, Brushes.Black, rect.Location);
}
}
private Color GetStatusColor(string status)
{
return status switch
{
"Ready" => Color.Green,
"Pending" => Color.Orange,
"Error" => Color.Red,
_ => Color.Gray
};
}
private List<MesStationLayout> GetStations()
{
return new List<MesStationLayout>
{
new MesStationLayout { StationId = "S1", XPosition = 50, YPosition = 50, Width = 100, Height = 80, MaterialStatus = "Ready" },
new MesStationLayout { StationId = "S2", XPosition = 200, YPosition = 50, Width = 100, Height = 80, MaterialStatus = "Pending" }
};
}
}
三、主インターフェース
public partial class MainForm : Form
{
private readonly MesStationControl _stationControl;
public MainForm()
{
InitializeComponent();
_stationControl = new MesStationControl();
_stationControl.Dock = DockStyle.Fill;
panelMain.Controls.Add(_stationControl);
LoadData();
}
private void LoadData()
{
using var conn = new SqlConnection("...");
var stations = conn.Query<MesStationLayout>("SELECT * FROM Stations");
UpdateDisplay(stations);
}
private void UpdateDisplay(IEnumerable<MesStationLayout> stations)
{
_stationControl.Invalidate(); // 再描画トリガー
}
}
四、データベーススキーマ
CREATE TABLE Stations (
StationId VARCHAR(50) PRIMARY KEY,
X INT,
Y INT,
Width INT,
Height INT,
Status VARCHAR(20)
);
CREATE TABLE Jobs (
JobId VARCHAR(50) PRIMARY KEY,
StationId VARCHAR(50),
Quantity DECIMAL(18,2),
Process NVARCHAR(MAX),
Status VARCHAR(20)
);