新增机械臂状态显示

master
CaesarBao 5 days ago
parent 63b59cca10
commit 0908de22e9

@ -2,43 +2,73 @@
using SlnMesnac.Repository.service;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using SlnMesnac.Repository;
using SlnMesnac.Repository.service.Impl;
using TouchSocket.Sockets;
using SlnMesnac.Model.domain;
using SlnMesnac.TouchSocket;
using System.Timers;
using SlnMesnac.Model.Enum;
using HslCommunication.Enthernet;
using System.Threading;
namespace SlnMesnac.Business.@base
{
public class BaseTaskInfoBusiness
{
private TcpServer _tcpServer = null;
public Action<AirportTask> _Taskaction;
public Action<string> _RefreshLogMessageAction;
private static BaseTaskInfoBusiness instance;
private ILogger<BaseTaskInfoBusiness> _logger;
private IAirportTaskService _Taskservice;
private IAGVStateService _AGVStateService;
public BaseTaskInfoBusiness(ILogger<BaseTaskInfoBusiness> logger, IAirportTaskService Taskservice, IAGVStateService agvService)
public BaseTaskInfoBusiness(ILogger<BaseTaskInfoBusiness> logger, IAirportTaskService Taskservice, IAGVStateService agvService, TcpServer tcpServer)
{
_logger = logger;
_tcpServer = tcpServer;
_Taskservice = Taskservice;
_AGVStateService = agvService;
InitClearTimer();
//doWhileGetAGVTaskInfo();
}
public static BaseTaskInfoBusiness GetInstance(ILogger<BaseTaskInfoBusiness> logger, IAirportTaskService Taskservice, IAGVStateService agvService)
public static BaseTaskInfoBusiness GetInstance(ILogger<BaseTaskInfoBusiness> logger, IAirportTaskService Taskservice, IAGVStateService agvService, TcpServer tcpServer)
{
if (instance == null)
{
instance = new BaseTaskInfoBusiness(logger, Taskservice,agvService);
instance = new BaseTaskInfoBusiness(logger, Taskservice,agvService, tcpServer);
}
return instance;
}
private void doWhileGetAGVTaskInfo()
{
try
{
Task.Run((() =>
{
while (true)
{
GetAGVTaskInfo(null,null);
Task.Delay(1000);
}
}));
}
catch (Exception ex)
{
}
}
private void InitClearTimer()
{
System.Timers.Timer timer = new System.Timers.Timer
{
Interval = 1000, // 每天执行一次
AutoReset = false,
AutoReset = true,
};
timer.Elapsed += GetAGVTaskInfo;
@ -53,58 +83,154 @@ namespace SlnMesnac.Business.@base
try
{
List<AirportTask> Task = _Taskservice.GetAGVTaskInfos();
if (Task.Count > 0 && Task != null)
if (Task != null)
{
foreach (var TaskItem in Task)
if (Task.Count > 0)
{
_logger.LogInformation($"获取任务信息列表");
//查询AGV设备状态及AMR设备状态
//这里要看AGV是否会立刻更新状态
List<AGVState> State = GetAgvState();
if (State != null && State.Count > 0)
_RefreshLogMessageAction?.Invoke("任务数量:" + Task.Count);
foreach (var TaskItem in Task)
{
foreach (var AgvItem in State)
//AGV未派发AMR未派发
if (string.IsNullOrEmpty(TaskItem.agvno) && string.IsNullOrEmpty(TaskItem.manipulatorno))
{
//根据规则筛选最优AGV
if (AgvItem.agvworkstate == "任务空闲")
{
_logger.LogInformation($"获取空闲AGV列表");
//调用派发任务接口,向任务状态为任务空闲的AGV派发任务
AgvItem.taskno = TaskItem.taskno;
AgvItem.agvworkstate = "任务执行中";
AgvItem.refreshtime = DateTime.Now;
_AGVStateService.UpdateAsync(AgvItem);
//更新任务信息表状态为执行中
TaskItem.agvno = AgvItem.agvno;
TaskItem.taskstate = "执行中";
_Taskservice.UpdateAsync(TaskItem);
_Taskaction?.Invoke(TaskItem);
}
_RefreshLogMessageAction?.Invoke($"正在为AGVAMR分配任务...");
_logger.LogInformation($"正在为AGVAMR分配任务");
//查询AGV设备状态及AMR设备状态
//这里要看AGV是否会立刻更新状态
CreateAGVTask(TaskItem);
//查询机械臂状态
}
//AGV已派发AMR未派发
if (!string.IsNullOrEmpty(TaskItem.agvno) && string.IsNullOrEmpty(TaskItem.manipulatorno))
{
//查询AMR状态
CreateAMRTask(TaskItem);
_RefreshLogMessageAction?.Invoke($"正在为AMR分配任务...");
_logger.LogInformation($"正在为AMR分配任务");
}
//AGV未派发AMR已派发
if (string.IsNullOrEmpty(TaskItem.agvno) && !string.IsNullOrEmpty(TaskItem.manipulatorno))
{
_RefreshLogMessageAction?.Invoke($"正在为AGV分配任务...");
_logger.LogInformation($"正在为AGV分配任务");
}
_Taskaction?.Invoke(TaskItem);
}
}
}
}
catch (Exception ex)
{
}
}
/// <summary>
/// 向AMR派发任务
/// </summary>
/// <param name="AirportTask"></param>
/// <returns></returns>
private bool CreateAMRTask(AirportTask AirportTask)
{
bool iflag = false;
try
{
iflag = true;
List<AGVState> State = GetAgvState(AgvType.AMR);
foreach (var AgvItem in State)
{
//根据规则筛选最优AGV
if (AgvItem.agvworkstate == "任务空闲")
{
_logger.LogInformation($"获取空闲AMR列表");
_RefreshLogMessageAction?.Invoke("执行站台[" + AirportTask.conveyorno + "],下发" + "[" + AirportTask.taskno + "]任务");
//调用派发任务接口,向任务状态为任务空闲的AGV派发任务
bool iTaskflag = true;
if (iTaskflag)
{
_RefreshLogMessageAction?.Invoke("[" + AgvItem.agvno + "]AMR执行任务[" + AirportTask.taskno + "]");
AgvItem.taskno = AirportTask.taskno;
AgvItem.agvworkstate = "任务执行中";
AgvItem.refreshtime = DateTime.Now;
_AGVStateService.UpdateAsync(AgvItem);
//更新任务信息表状态为执行中
AirportTask.manipulatorno = AgvItem.agvno;
AirportTask.taskstate = "执行中";
_Taskservice.UpdateTaskAsync(AirportTask);
break;
}
}
}
return iflag;
}
catch (Exception ex)
{
return iflag;
}
}
private List<AGVState> GetAgvState()
/// <summary>
/// 向AGV派发任务
/// </summary>
/// <returns></returns>
private bool CreateAGVTask(AirportTask AirportTask)
{
bool iflag = false;
try
{
iflag = true;
List<AGVState> State = GetAgvState(AgvType.AGV);
foreach (var AgvItem in State)
{
//根据规则筛选最优AGV
if (AgvItem.agvworkstate == "任务空闲")
{
_logger.LogInformation($"获取空闲AGV列表");
_RefreshLogMessageAction?.Invoke("执行站台[" + AirportTask.conveyorno + "],下发" + "[" + AirportTask.taskno + "]任务");
//调用派发任务接口,向任务状态为任务空闲的AGV派发任务
bool iTaskflag = true;
if (iTaskflag)
{
_RefreshLogMessageAction?.Invoke("[" + AgvItem.agvno + "]AGV执行任务[" + AirportTask.taskno + "]");
AgvItem.taskno = AirportTask.taskno;
AgvItem.agvworkstate = "任务执行中";
AgvItem.refreshtime = DateTime.Now;
_AGVStateService.UpdateAsync(AgvItem);
//更新任务信息表状态为执行中
AirportTask.agvno = AgvItem.agvno;
AirportTask.taskstate = "执行中";
_Taskservice.UpdateTaskAsync(AirportTask);
break;
}
}
}
return iflag;
}
catch (Exception ex)
{
return iflag;
}
}
/// <summary>
/// 获取agv设备状态
/// </summary>
/// <returns></returns>
private List<AGVState> GetAgvState(AgvType AgvType)
{
List<AGVState> State = null;
try
{
State = _AGVStateService.GetAgvState();
State = _AGVStateService.GetAgvState(AgvType);
return State;
}
catch (Exception ex)

@ -58,6 +58,15 @@ namespace SlnMesnac.Config
/// </summary>
public string redisConfig { get; set; }
/// <summary>
/// AMR
/// </summary>
public string AMRIP { get; set; }
public AppConfig Value => this;
}
}

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace SlnMesnac.Model.Enum
{
public enum AgvType
{
AGV = 1,
AMR = 2,
}
}

@ -1,4 +1,5 @@
using SlnMesnac.Model.domain;
using SlnMesnac.Model.Enum;
using SlnMesnac.Repository.service.@base;
using System;
using System.Collections.Generic;
@ -13,7 +14,7 @@ namespace SlnMesnac.Repository.service
/// 查询AGV状态
/// </summary>
/// <returns></returns>
List<AGVState> GetAgvState();
List<AGVState> GetAgvState(AgvType AgvType);
/// <summary>
/// 更新AGV设备状态信息

@ -20,11 +20,33 @@ namespace SlnMesnac.Repository.service
/// <returns></returns>
List<AirportTask> GetAGVTaskInfos();
/// <summary>
/// 根据站台号查询任务列表
/// </summary>
/// <returns></returns>
Task<List<AirportTask>> GetTaskInfoListAsync(string ConveyorNo);
/// <summary>
/// 更新任务列表
/// </summary>
/// <param name="record"></param>
/// <returns></returns>
Task<bool> UpdateAsync(AirportTask record);
Task<bool> UpdateTaskAsync(AirportTask record);
/// <summary>
/// 新增任务
/// </summary>
/// <param name="record"></param>
/// <returns></returns>
Task<bool> AddTaskAsync(AirportTask record);
/// <summary>
/// 删除任务
/// </summary>
/// <param name="record"></param>
/// <returns></returns>
Task<bool> DeleteTaskAsync(AirportTask record);
}
}

@ -1,6 +1,7 @@
using Microsoft.Extensions.Logging;
using SlnMesnac.Common;
using SlnMesnac.Model.domain;
using SlnMesnac.Model.Enum;
using SlnMesnac.Repository.service.@base;
using System;
using System.Collections.Generic;
@ -16,13 +17,14 @@ namespace SlnMesnac.Repository.service.Impl
{
_logger = logger;
}
public List<AGVState> GetAgvState()
public List<AGVState> GetAgvState(AgvType AgvType)
{
string _AgvType = Convert.ToString(((int)AgvType).ToString());
List<AGVState> agvStateInfoList = null;
try
{
Expression<Func<AGVState, bool>> exp = x => true;
exp = exp.And(x => x.agvno != "" && (x.taskno == null || x.taskno == "") && x.agvworkstate == "ÈÎÎñ¿ÕÏÐ");
exp = exp.And(x =>(x.agvno != null || x.agvno != "") && (x.taskno == null || x.taskno == "") && x.agvworkstate == "ÈÎÎñ¿ÕÏÐ" && (x.agvalarmstate == null || x.agvalarmstate == "") && x.agvtype == _AgvType);
agvStateInfoList = base._rep.GetList(exp);
}
@ -38,5 +40,6 @@ namespace SlnMesnac.Repository.service.Impl
bool result = await _rep.UpdateAsync(record);
return result;
}
}
}

@ -51,7 +51,7 @@ namespace SlnMesnac.Repository.service.Impl
List<AirportTask> taskInfos = null;
try
{
String sql = "SELECT ConveyorNo,TaskNo,FlightNo,AGVNo,MAX(StartTime) as StartTime,TaskState, TotalCount ,LoadCount FROM AirportTask group by ConveyorNo ";
String sql = "SELECT id,ConveyorNo,TaskNo,FlightNo,AGVNo,MAX(StartTime) as StartTime,TaskState, TotalCount ,LoadCount FROM AirportTask group by ConveyorNo ";
taskInfos = base._rep.AsTenant().GetConnection("AGV").Ado.SqlQuery<AirportTask>(sql);
}
catch (Exception ex)
@ -70,7 +70,7 @@ namespace SlnMesnac.Repository.service.Impl
List<AirportTask> taskInfos = null;
try
{
String sql = "SELECT id, ConveyorNo,TaskNo,FlightNo,AGVNo,MAX(StartTime) as StartTime,TaskState, TotalCount ,LoadCount FROM AirportTask WHERE AGVNo IS NULL and TaskState = '等待' group by ConveyorNo ";
String sql = "select *from ( SELECT id, ConveyorNo,TaskNo,FlightNo,AGVNo,ManipulatorNo,MAX(StartTime) as StartTime,TaskState, TotalCount ,LoadCount FROM AirportTask group by ConveyorNo )";
taskInfos = base._rep.AsTenant().GetConnection("AGV").Ado.SqlQuery<AirportTask>(sql);
}
catch (Exception ex)
@ -80,11 +80,30 @@ namespace SlnMesnac.Repository.service.Impl
return taskInfos;
}
public async Task<bool> UpdateAsync(AirportTask record)
public async Task<List<AirportTask>> GetTaskInfoListAsync(string ConveyorNo)
{
List<AirportTask> list = null;
list = await _rep.GetListAsync(x=>x.conveyorno == ConveyorNo);
return list;
}
public async Task<bool> UpdateTaskAsync(AirportTask record)
{
bool result = await _rep.UpdateAsync(record);
return result;
}
public async Task<bool> AddTaskAsync(AirportTask record)
{
bool result = await _rep.InsertAsync(record);
return result;
}
public async Task<bool> DeleteTaskAsync(AirportTask record)
{
bool iFlag = await _rep.DeleteAsync(record);
return iFlag;
}
}
}

@ -42,6 +42,8 @@ namespace SlnMesnac.TouchSocket
public delegate void RefreshClientInfo(TcpService tcpService);
public event RefreshClientInfo? RefreshClientInfoEvent;
public Action<String, bool> RefreshStateAction;
public TcpServer(ILogger<TcpServer> logger,TcpService tcpService)
{
_logger = logger;
@ -59,10 +61,12 @@ namespace SlnMesnac.TouchSocket
_service.Connected = (client, e) => {
_logger.LogInformation($"客户端{client.IP}接入服务成功");
RefreshClientInfoEvent?.Invoke(_service);
RefreshStateAction?.Invoke(client.IP,true);
return EasyTask.CompletedTask;
};
_service.Disconnected = (client, e) => {
_logger.LogInformation($"客户端{client.IP}断开连接");
RefreshStateAction?.Invoke(client.IP, false);
RefreshClientInfoEvent?.Invoke(_service);
return EasyTask.CompletedTask;
};
@ -70,7 +74,13 @@ namespace SlnMesnac.TouchSocket
{
//从客户端收到信息
var mes = Encoding.UTF8.GetString(e.ByteBlock.Buffer, 0, e.ByteBlock.Len);//注意数据长度是byteBlock.Len
_logger.LogInformation($"客户端{client.IP}:"+ mes);
//区分一下指令类型,委托传参
if (mes == "heartbeat")
{
RefreshStateAction?.Invoke(client.IP, true);
}
byte[] receivedBuffer = new byte[e.ByteBlock.Len];
Array.Copy(e.ByteBlock.Buffer, 0, receivedBuffer, 0, e.ByteBlock.Len);
ReceivedClientBufferEvent?.Invoke(receivedBuffer);

@ -37,11 +37,11 @@ namespace SlnMesnac.TouchSocket
public static IApplicationBuilder UseTouchSocketExtensions(this IApplicationBuilder app)
{
// var _server = app.ApplicationServices.GetService<TcpServer>();
// _server.Init(20108);
var _server = app.ApplicationServices.GetService<TcpServer>();
_server.Init(6001);
var _apiServer = app.ApplicationServices.GetService<WebApiServer>();
_apiServer.Init();
// var _apiServer = app.ApplicationServices.GetService<WebApiServer>();
// _apiServer.Init();
return app;
}
}

@ -31,7 +31,7 @@
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Center">
<TextBlock Text="生产控制系统" FontSize="50" Foreground="White" FontWeight="Bold"/>
<TextBlock Text="行李空框调度系统" FontSize="50" Foreground="White" FontWeight="Bold"/>
</StackPanel>
<StackPanel Grid.Column="2" VerticalAlignment="Center" HorizontalAlignment="Right">
@ -72,7 +72,7 @@
<StackPanel Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Right" Orientation="Horizontal">
<!--多行状态显示-->
<!--<Grid>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
@ -154,14 +154,14 @@
</StackPanel>
</Grid>
</StackPanel>
</Grid>-->
</Grid>
<!--单行状态显示-->
<!--<Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<!--<ColumnDefinition Width="*"/>-->
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
@ -190,7 +190,7 @@
</Ellipse>
</StackPanel>
<StackPanel Grid.Column="1" VerticalAlignment="Center">
<TextBlock Text="箱壳扫码器" FontSize="15" Foreground="#FFFFFF" Margin="2,0,10,0"/>
<TextBlock Text="机械臂" FontSize="15" Foreground="#FFFFFF" Margin="2,0,10,0"/>
</StackPanel>
</Grid>
</StackPanel>
@ -221,12 +221,12 @@
</Ellipse>
</StackPanel>
<StackPanel Grid.Column="1" VerticalAlignment="Center">
<TextBlock Text="内胆扫码器" FontSize="15" Foreground="#FFFFFF" Margin="2,0,10,0"/>
<TextBlock Text="AGV" FontSize="15" Foreground="#FFFFFF" Margin="2,0,10,0"/>
</StackPanel>
</Grid>
</StackPanel>
<StackPanel Grid.Column="2">
<!--<StackPanel Grid.Column="2">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
@ -255,8 +255,8 @@
<TextBlock Text="PLC状态" FontSize="15" Foreground="#FFFFFF" Margin="2,0,10,0"/>
</StackPanel>
</Grid>
</StackPanel>
</Grid>-->
</StackPanel>-->
</Grid>
</StackPanel>
</Grid>

@ -0,0 +1,49 @@
<Window x:Class="SlnMesnac.WPF.Page.IndexPage.AddTaskContent"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:SlnMesnac.WPF.Page.IndexPage"
mc:Ignorable="d"
Height="360" Width="315" ResizeMode="NoResize" WindowStartupLocation="CenterScreen">
<Border Margin="5" Background="White" CornerRadius="10">
<Border.Effect>
<DropShadowEffect Color="Gray" ShadowDepth="0" BlurRadius="5" Opacity="0.3" Direction="0"></DropShadowEffect>
</Border.Effect>
<StackPanel Grid.Column="1" Margin="0,10" VerticalAlignment="Top">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="60"/>
<RowDefinition Height="60"/>
<RowDefinition Height="60"/>
<RowDefinition Height="60"/>
<RowDefinition Height="60"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal">
<Label Content="任务编号" Width="64" VerticalAlignment="Center"/>
<TextBox Name="taskNo" Width="188" Height="36" IsReadOnly="True"/>
</StackPanel>
<StackPanel Grid.Row="1" Orientation="Horizontal">
<Label Content="站台编号" Width="64" VerticalAlignment="Center"/>
<ComboBox Name="AreaNo" Width="188" Height="36" DisplayMemberPath="Value" SelectedValuePath="Key"/>
</StackPanel>
<StackPanel Grid.Row="2" Orientation="Horizontal">
<Label Content="航班号" Width="64" VerticalAlignment="Center"/>
<TextBox Name="AirNo" Width="188" Height="36"/>
</StackPanel>
<StackPanel Grid.Row="5" Orientation="Horizontal">
<Button x:Name="btn_ok" Content="确认" Width="145" Click="btn_ok_Click" />
<Button x:Name="btn_cancle" Content="取消" Width="145" Click="btn_cancle_Click" />
</StackPanel>
</Grid>
</StackPanel>
</Border>
</Window>

@ -0,0 +1,97 @@
using Microsoft.Extensions.DependencyInjection;
using SlnMesnac.Repository;
using SlnMesnac.Repository.service;
using SlnMesnac.WPF.ViewModel.IndexPage;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using static Microsoft.WindowsAPICodePack.Shell.PropertySystem.SystemProperties.System;
namespace SlnMesnac.WPF.Page.IndexPage
{
/// <summary>
/// AddTaskContent.xaml 的交互逻辑
/// </summary>
public partial class AddTaskContent : Window
{
public Action<AirportTask> _Taskaction;
private IAirportTaskService _taskservice;
public AddTaskContent()
{
InitializeComponent();
_taskservice = App.ServiceProvider.GetService<IAirportTaskService>();
InitAreaCombox();
this.Init();
}
private void Init()
{
taskNo.Text = DateTime.Now.ToString("yyMMddHHmmss");
}
private void InitAreaCombox()
{
Dictionary<int, string> dicItem = new Dictionary<int, string>();
dicItem.Add(1,"1号站台");
dicItem.Add(2, "2号站台");
dicItem.Add(3, "3号站台");
dicItem.Add(4, "4号站台");
dicItem.Add(5, "5号站台");
dicItem.Add(6, "6号站台");
AreaNo.ItemsSource = dicItem;
AreaNo.SelectedIndex = 0;
}
private void btn_cancle_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
private async void btn_ok_Click(object sender, RoutedEventArgs e)
{
//判空
if (string.IsNullOrEmpty(AirNo.Text.Trim()))
{
MessageBox.Show("请输入航班号!");
return;
}
string ss = AreaNo.SelectedIndex.ToString();
//判断站台任务是否结束
AirportTask AirportTask = new AirportTask()
{
taskno = taskNo.Text,
conveyorno = AreaNo.SelectedValue.ToString(),
flightno = AirNo.Text,
taskstate = "等待",
starttime = DateTime.Now
};
bool iflag = await _taskservice.AddTaskAsync(AirportTask);
if (iflag)
{
_Taskaction?.Invoke(AirportTask);
this.Close();
}
}
}
}

@ -0,0 +1,100 @@
<Window x:Class="SlnMesnac.WPF.Page.IndexPage.DetailTaskContent"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:SlnMesnac.WPF.Page.IndexPage"
mc:Ignorable="d"
Height="650" Width="1020" WindowStartupLocation="CenterScreen" Loaded="Window_Loaded">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="6*"/>
<RowDefinition Height="60*"/>
</Grid.RowDefinitions>
<Border Grid.Row="0" Margin="0,5,0,0" BorderBrush="#007DFA" BorderThickness="1" CornerRadius="0" Background="#1254AB">
<StackPanel Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Center">
<TextBlock Name="AreaTask" Text="1号站台任务列表" FontSize="30" Foreground="White" Height="37" Width="249"/>
</StackPanel>
</Border>
<Border Grid.Row="1" Margin="0,5,0,0" BorderBrush="#007DFA" BorderThickness="1" CornerRadius="0" Background="#1254AB">
<DataGrid x:Name="AreaTaskDataGrid" Style="{DynamicResource DataGridStyle}" ColumnHeaderHeight="22" RowHeight="40" AutoGenerateColumns="False" RowHeaderWidth="0" GridLinesVisibility="None" ScrollViewer.HorizontalScrollBarVisibility="Hidden" ScrollViewer.VerticalScrollBarVisibility="Hidden" BorderThickness="0">
<DataGrid.Resources>
<Style x:Key="DataGridStyle" TargetType="DataGrid">
<Setter Property="AlternationCount" Value="2"/>
<Setter Property="ColumnHeaderStyle" Value="{DynamicResource DataGridColumnHeaderStyle}"/>
<Setter Property="CellStyle" Value="{DynamicResource DataGridCellStyle}"/>
<Setter Property="RowStyle" Value="{DynamicResource DataGridRowStyle}"/>
</Style>
<Style x:Key="DataGridColumnHeaderStyle" TargetType="DataGridColumnHeader">
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Background" Value="White"/>
</Style>
<Style x:Key="DataGridRowStyle" TargetType="{x:Type DataGridRow}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridRow}">
<Grid x:Name="DGR_Border" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="1"/>
<DataGridCellsPresenter Grid.Column="1" ItemsPanel="{TemplateBinding ItemsPanel}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="BorderBrush" Value="#00BCD4"/>
</Trigger>
<Trigger Property="AlternationIndex" Value="0">
<Setter Property="Background" Value="#E9F3FD"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsNewItem" Value="True">
<Setter Property="Margin" Value="{Binding NewItemMargin, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"/>
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="DataGridCellStyle" TargetType="{x:Type DataGridCell}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" SnapsToDevicePixels="True">
<ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="Gray"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding id}" Header="编号" Width="60"/>
<!--<DataGridTextColumn Binding="{Binding MachineID}" Header="机台编号" Width="60"/>-->
<DataGridTextColumn Binding="{Binding taskno}" Header="任务编号" Width="*"/>
<DataGridTextColumn Binding="{Binding flightno}" Header="航班号" Width="*"/>
<DataGridTextColumn Binding="{Binding agvno}" Header="AGV" Width="0.6*"/>
<DataGridTextColumn Binding="{Binding manipulatorno}" Header="AMR" Width="0.6*"/>
<DataGridTextColumn Binding="{Binding taskstate}" Header="任务状态" Width="*"/>
<DataGridTextColumn Binding="{Binding totalcount}" Header="总抓取数量" Width="*"/>
<DataGridTextColumn Binding="{Binding loadcount}" Header="已抓取数量" Width="*"/>
<DataGridTextColumn Binding="{Binding starttime,StringFormat=\{0:yyyy-MM-dd HH:mm:ss\}}" Header="开始时间" Width="*"/>
<DataGridTextColumn Binding="{Binding finishtime,StringFormat=\{0:yyyy-MM-dd HH:mm:ss\}}" Header="完成时间" Width="*"/>
</DataGrid.Columns>
</DataGrid>
</Border>
</Grid>
</Window>

@ -0,0 +1,65 @@
using SlnMesnac.Repository.service;
using SlnMesnac.Repository;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using static Microsoft.WindowsAPICodePack.Shell.PropertySystem.SystemProperties.System;
using Microsoft.Extensions.DependencyInjection;
using Task = System.Threading.Tasks.Task;
namespace SlnMesnac.WPF.Page.IndexPage
{
/// <summary>
/// DetailTaskContent.xaml 的交互逻辑
/// </summary>
public partial class DetailTaskContent : Window
{
public Action<AirportTask> _Taskaction;
private IAirportTaskService _taskservice;
public AirportTask AirportTask;
public DetailTaskContent()
{
InitializeComponent();
}
private async void LoadAreaTaskInfo()
{
try
{
List<AirportTask> Task = _taskservice.GetTaskInfoListAsync(AirportTask.conveyorno).Result;
this.AreaTaskDataGrid.ItemsSource = Task;
}
catch (Exception ex)
{
}
}
//在载入行的时候在行表头添加编号
private void dgvMH_LoadingRow(object sender, DataGridRowEventArgs e)
{
e.Row.Header = (e.Row.GetIndex() + 1).ToString();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
if (AirportTask != null)
{
AreaTask.Text = AirportTask.conveyorno + "号站台任务列表";
}
_taskservice = App.ServiceProvider.GetService<IAirportTaskService>();
LoadAreaTaskInfo();
}
}
}

@ -40,15 +40,20 @@
<TextBlock Text="已装载筐数量:" FontSize="18" Foreground="White" Margin="0,10,0,0"/>
<TextBlock Text="{Binding loadcount}" FontSize="18" Foreground="White" Margin="0,10,0,0"/>
</StackPanel>
<!-- <StackPanel Orientation="Horizontal"> -->
<!-- <TextBlock Text="ID" FontSize="18" Foreground="White" Margin="0,10,0,0" Visibility="Visible"/> -->
<!-- <TextBlock Text="{Binding id}" FontSize="18" Foreground="White" Margin="0,10,0,0"/> -->
<!-- </StackPanel> -->
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" Margin="0,10,0,10">
<Button Content="待处理任务" FontSize="14" Style="{StaticResource BUTTON_AGREE}"
Width="80" Height="30" Background="YellowGreen" BorderBrush="YellowGreen" Margin="40,0,0,0"
Command="{Binding DataContext.HandleTaskCommand, RelativeSource={RelativeSource AncestorType=ItemsControl}}"
CommandParameter="{Binding taskno}"/>
CommandParameter="{Binding}"/>
<Button Content="删除任务" FontSize="14" Style="{StaticResource BUTTON_AGREE}"
Width="80" Height="30" Background="Red" BorderBrush="Red" Margin="20,0,0,0"
Command="{Binding DataContext.DeleteTaskCommand, RelativeSource={RelativeSource AncestorType=ItemsControl}}"
CommandParameter="{Binding taskno}"/>
CommandParameter="{Binding }"/>
</StackPanel>
</StackPanel>
</Border>

@ -27,5 +27,6 @@ namespace SlnMesnac.WPF.Page.IndexPage
this.DataContext = new IndexContentViewModel();
}
}
}

@ -50,6 +50,7 @@ namespace SlnMesnac.WPF
//注册任务调度
//services.AddQuartzSetUp();
}
/// <summary>

@ -14,6 +14,11 @@ using SlnMesnac.Repository.service;
using SlnMesnac.Repository;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;
using Task = System.Threading.Tasks.Task;
using SlnMesnac.WPF.Page.IndexPage;
using System.Windows.Documents;
using SlnMesnac.TouchSocket;
using HslCommunication.Enthernet;
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
@ -47,7 +52,7 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage
private IAGVStateService _agvstateService;
private BaseTaskInfoBusiness _taskInfoBusiness;
private DispatcherTimer _timer;
private TcpServer _tcpServer;
public IndexContentViewModel()
{
@ -56,23 +61,50 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage
_taskBusinessLogger = App.ServiceProvider.GetService<ILogger<BaseTaskInfoBusiness>>();
_taskservice = App.ServiceProvider.GetService<IAirportTaskService>();
_agvstateService = App.ServiceProvider.GetService<IAGVStateService>();
_taskInfoBusiness = BaseTaskInfoBusiness.GetInstance(_taskBusinessLogger, _taskservice, _agvstateService);
_tcpServer = App.ServiceProvider.GetService<TcpServer>();
_taskInfoBusiness = BaseTaskInfoBusiness.GetInstance(_taskBusinessLogger, _taskservice, _agvstateService, _tcpServer);
_taskInfoBusiness._RefreshLogMessageAction += RefreshLogMessage;
_taskInfoBusiness._Taskaction += task =>
{
TaskItems = new ObservableCollection<AirportTask>
if (task != null)
{
task
};
var x = TaskItems.ToList().Find(x => x.conveyorno == task.conveyorno);
if (x != null)
{
x.id = task.id;
x.taskno = task.taskno;
x.flightno = task.flightno;
x.manipulatorno = task.manipulatorno;
x.agvno = task.agvno;
x.taskstate = task.taskstate;
TaskItems = new ObservableCollection<AirportTask>(TaskItems);
}
}
};
this.Init();
}
private void LoadTaskInfo()
{
try
{
List<AirportTask> AirportTaskItem = _taskservice.GetTaskInfos();
TaskItems = new ObservableCollection<AirportTask>(AirportTaskItem);
}
catch (Exception ex)
{
}
}
private void Init()
{
#region 测试数据
List<AirportTask> AirportTaskItem = _taskservice.GetTaskInfos();
TaskItems = new ObservableCollection<AirportTask>(AirportTaskItem);
LoadTaskInfo();
// TaskItems = new ObservableCollection<AirportTask>
// {
// new AirportTask { TaskCode = "1", StationName = "1#站台", TaskDetails = "入库P04->C01", Status = "任务状态:执行中" },
@ -83,19 +115,19 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage
// new TaskItem { TaskCode = "6", StationName = "6#站台", TaskDetails = "入库P04->C01", Status = "任务状态:执行中" },
// };
RefreshLogMessage($"1#站台任务下发站台任务下发站台任务下发站台任务下发站台任务下发站台任务下发");
RefreshLogMessage($"2#站台任务下发");
RefreshLogMessage($"3#站台任务下发");
RefreshLogMessage($"4#站台任务下发");
RefreshLogMessage($"5#站台任务下发");
RefreshLogMessage($"6#站台任务下发");
RefreshLogMessage($"7#站台任务下发");
RefreshLogMessage($"2#站台任务下发");
RefreshLogMessage($"3#站台任务下发");
RefreshLogMessage($"4#站台任务下发");
RefreshLogMessage($"5#站台任务下发");
RefreshLogMessage($"6#站台任务下发");
RefreshLogMessage($"7#站台任务下发");
//RefreshLogMessage($"1#站台任务下发站台任务下发站台任务下发站台任务下发站台任务下发站台任务下发");
//RefreshLogMessage($"2#站台任务下发");
//RefreshLogMessage($"3#站台任务下发");
//RefreshLogMessage($"4#站台任务下发");
//RefreshLogMessage($"5#站台任务下发");
//RefreshLogMessage($"6#站台任务下发");
//RefreshLogMessage($"7#站台任务下发");
//RefreshLogMessage($"2#站台任务下发");
//RefreshLogMessage($"3#站台任务下发");
//RefreshLogMessage($"4#站台任务下发");
//RefreshLogMessage($"5#站台任务下发");
//RefreshLogMessage($"6#站台任务下发");
//RefreshLogMessage($"7#站台任务下发");
FlightItems = new ObservableCollection<FlightItem>
{
@ -125,6 +157,29 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage
}
public async void RefreshTaskItems(AirportTask airportTask)
{
try
{
await Task.Run(async () =>
{
foreach (var VARIABLE in TaskItems)
{
if (VARIABLE.agvno == airportTask.conveyorno)
{
VARIABLE.taskstate = airportTask.taskstate;
VARIABLE.agvno = airportTask.agvno;
VARIABLE.totalcount = airportTask.totalcount;
VARIABLE.loadcount = airportTask.loadcount;
}
}
});
}
catch (Exception ex)
{
}
}
#region 参数定义
/// <summary>
/// 任务列表
@ -175,22 +230,96 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage
/// 刷新日志
/// </summary>
/// <param name="msg"></param>
private void RefreshLogMessage(string msg)
public void RefreshLogMessage(string msg)
{
App.Current.Dispatcher.BeginInvoke((Action)(() =>
try
{
App.Current.Dispatcher.BeginInvoke((Action)(() =>
{
LogMessages.Add($"{DateTime.Now}: {msg}");
while (LogMessages.Count > 120)
{
LogMessages.RemoveAt(0);
}
var orderedList = LogMessages.OrderByDescending(x => x); // 排序后转为 List
LogMessages = new ObservableCollection<string>(orderedList);
}));
}
catch (Exception ex)
{
LogMessages.Add($"{DateTime.Now}: {msg}");
}));
}
}
/// <summary>
/// 系统运行日志输出
/// </summary>
/// <param name="message"></param>
private async void PrintMessageToListBox(string message)
{
await Task.Run(() =>
{
try
{
string formattedMessage = $"{DateTime.Now.ToString("HH:mm:ss.ss")} ==> {message}";
lock (LogMessages)
{
LogMessages.Add(formattedMessage);
while (LogMessages.Count > 120)
{
LogMessages.RemoveAt(0);
}
var orderedList = LogMessages.OrderByDescending(x => x).ToList(); // 排序后转为 List
}
}
catch (Exception ex)
{
_logger.LogError($"日志数据绑定异常:{ex.Message}");
}
});
}
/// <summary>
/// 添加任务
/// </summary>
[RelayCommand]
private void AddTask()
{
MessageBox.Show("添加任务");
//生成任务号
//输入航班号
//任务状态默认等待
AddTaskContent AddTaskContent = new AddTaskContent();
AddTaskContent._Taskaction = task =>
{
if (task != null)
{
var x = TaskItems.ToList().Find(x => x.conveyorno == task.conveyorno);
if (x != null)
{
x.id = task.id;
x.taskno = task.taskno;
x.flightno = task.flightno;
x.manipulatorno = task.manipulatorno;
x.agvno = task.agvno;
x.taskstate = task.taskstate;
TaskItems = new ObservableCollection<AirportTask>(TaskItems);
}
else
{
TaskItems.Add(task);
}
}
};
AddTaskContent.ShowDialog();
if ((bool)AddTaskContent.DialogResult)
{
RefreshLogMessage("任务添加成功!");
}
}
/// <summary>
@ -198,9 +327,16 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage
/// </summary>
/// <param name="taskCode"></param>
[RelayCommand]
private void HandleTask(string taskCode)
private void HandleTask(AirportTask taskCode)
{
var info = taskCode;
if (info != null)
{
DetailTaskContent DetailTaskContent = new DetailTaskContent();
DetailTaskContent.AirportTask = taskCode;
DetailTaskContent.ShowDialog();
}
}
/// <summary>
@ -208,9 +344,25 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage
/// </summary>
/// <param name="taskCode"></param>
[RelayCommand]
private void DeleteTask(string taskCode)
private void DeleteTask(AirportTask task)
{
var info = taskCode;
if (task.taskstate != "等待")
{
MessageBox.Show("任务已下发,不允许删除!");
}
else
{
if (MessageBox.Show("请确认是否删除该任务?", "Confirm Message", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
{
//根据任务号删除任务
TaskItems.Remove(task);
//清表
_taskservice.DeleteTaskAsync(task);
//TaskItems = new ObservableCollection<AirportTask>(TaskItems);
LoadTaskInfo();
}
}
}
/// <summary>

@ -1,8 +1,10 @@
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using HslCommunication.Enthernet;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using SlnMesnac.Business.@base;
using SlnMesnac.Config;
using SlnMesnac.Repository.service;
using SlnMesnac.TouchSocket;
using SlnMesnac.WPF.Page.Generate;
@ -18,10 +20,11 @@ namespace SlnMesnac.WPF.ViewModel
private readonly ILogger<BaseTaskInfoBusiness> _BaseTaskInfoBusinesslogger;
private IAirportTaskService _Taskservice;
private IAGVStateService _AGVStateService;
private TcpServer _tcpServer;
//代码生成
private readonly GenerateControl generateControl = new GenerateControl();
private IndexContent indexContent = new IndexContent();
private AppConfig _appConfig;
#region 参数定义
/// <summary>
@ -85,17 +88,23 @@ namespace SlnMesnac.WPF.ViewModel
#endregion
public MainWindowViewModel()
{
{
_appConfig = App.ServiceProvider.GetService<AppConfig>();
_logger = App.ServiceProvider.GetService<ILogger<MainWindowViewModel>>();
_Taskservice = App.ServiceProvider.GetService<IAirportTaskService>();
_AGVStateService = App.ServiceProvider.GetService<IAGVStateService>();
_BaseTaskInfoBusinesslogger = App.ServiceProvider.GetService<ILogger<BaseTaskInfoBusiness>>();
BaseTaskInfoBusiness.GetInstance(_BaseTaskInfoBusinesslogger, _Taskservice, _AGVStateService);
_tcpServer = App.ServiceProvider.GetService<TcpServer>();
BaseTaskInfoBusiness.GetInstance(_BaseTaskInfoBusinesslogger, _Taskservice, _AGVStateService, _tcpServer);
ControlOnClickCommand = new RelayCommand<object>(obj => ControlOnClick(obj));
FormControlCommand = new RelayCommand<object>(x => FormControl(x));
_tcpServer.RefreshStateAction+= (_clientIP, _state) =>
{
if (_clientIP == _appConfig.AMRIP)
{
ShellScannerStatus = _state ? 1 : 2;
}
};
UserContent = indexContent;
}

@ -60,6 +60,10 @@
"isFlage": true
}
],
"AMRIP": "127.0.0.1",
"redisConfig": "175.27.215.92:6379,password=redis@2023"
}
}

Loading…
Cancel
Save