Compare commits
8 Commits
Inspection
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| a01f9d4cd7 | |||
| c517993e1a | |||
| d11907dc3c | |||
|
|
2dafd9096b | ||
|
|
24e1d09d8e | ||
|
|
702a80fba2 | ||
|
|
44d79db962 | ||
| e9dea7d845 |
@ -1,9 +1,9 @@
|
||||
using Aurora.Api;
|
||||
using Aurora.Api;
|
||||
using Aurora.Api.DataType;
|
||||
using Aurora.Api.Devices;
|
||||
using PropertyTools.DataAnnotations;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.IO.Ports;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
@ -14,6 +14,50 @@ namespace AuroraLight
|
||||
public class LightConfig : IDeviceConfig
|
||||
{
|
||||
public IConnConfig ConnConfig { get; set; }
|
||||
|
||||
[Category("Light Level")]
|
||||
[DisplayName("Channel 1 Level (0~255)")]
|
||||
[Description("Channel 1 Brightness")]
|
||||
public int Ch1Level { get; set; } = 200;
|
||||
|
||||
[Category("Light Level")]
|
||||
[DisplayName("Channel 2 Level (0~255)")]
|
||||
[Description("Channel 2 Brightness")]
|
||||
public int Ch2Level { get; set; } = 200;
|
||||
|
||||
[Category("Light Level")]
|
||||
[DisplayName("Channel 3 Level (0~255)")]
|
||||
[Description("Channel 3 Brightness")]
|
||||
public int Ch3Level { get; set; } = 200;
|
||||
|
||||
[Category("Light Level")]
|
||||
[DisplayName("Channel 4 Level (0~255)")]
|
||||
[Description("Channel 4 Brightness")]
|
||||
public int Ch4Level { get; set; } = 200;
|
||||
|
||||
public int GetChannelLevel(int channel)
|
||||
{
|
||||
switch (channel)
|
||||
{
|
||||
case 0: return Ch1Level;
|
||||
case 1: return Ch2Level;
|
||||
case 2: return Ch3Level;
|
||||
case 3: return Ch4Level;
|
||||
default: return Ch1Level;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetChannelLevel(int channel, int value)
|
||||
{
|
||||
switch (channel)
|
||||
{
|
||||
case 0: Ch1Level = value; break;
|
||||
case 1: Ch2Level = value; break;
|
||||
case 2: Ch3Level = value; break;
|
||||
case 3: Ch4Level = value; break;
|
||||
}
|
||||
}
|
||||
|
||||
public LightConfig()
|
||||
{
|
||||
ConnConfig = new SerialConnConfig() {
|
||||
@ -24,6 +68,10 @@ namespace AuroraLight
|
||||
DataBits = 8,
|
||||
ReadTimeout = 500
|
||||
};
|
||||
Ch1Level = 200;
|
||||
Ch2Level = 200;
|
||||
Ch3Level = 200;
|
||||
Ch4Level = 200;
|
||||
}
|
||||
|
||||
public static LightConfig GetDefaultConfig()
|
||||
@ -37,6 +85,10 @@ namespace AuroraLight
|
||||
DataBits = 8,
|
||||
ReadTimeout = 500
|
||||
};
|
||||
config.Ch1Level = 200;
|
||||
config.Ch2Level = 200;
|
||||
config.Ch3Level = 200;
|
||||
config.Ch4Level = 200;
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
using Aurora.Api;
|
||||
using Aurora.Api;
|
||||
using Aurora.Api.DataType;
|
||||
using Aurora.Api.Devices;
|
||||
using AuroraLight.ALT;
|
||||
@ -25,6 +25,7 @@ namespace AuroraLight
|
||||
Logger Log;
|
||||
internal eLight _lightType;
|
||||
internal ILight _light;
|
||||
public LightConfig Config { get; private set; }
|
||||
|
||||
public LightDevice(string deviceId, eLight light)
|
||||
{
|
||||
@ -38,6 +39,7 @@ namespace AuroraLight
|
||||
protected override int DoActivate(IDeviceConfig config)
|
||||
{
|
||||
var l_config = config as LightConfig;
|
||||
Config = l_config;
|
||||
|
||||
if (IsSimul) {
|
||||
return E1.OK;
|
||||
@ -57,7 +59,15 @@ namespace AuroraLight
|
||||
break;
|
||||
}
|
||||
|
||||
return _light.InitInternal(config.ConnConfig as SerialConnConfig) ? E1.OK : E2.NOT_CONNECTED;
|
||||
bool connected = _light.InitInternal(config.ConnConfig as SerialConnConfig);
|
||||
if (connected && l_config != null) {
|
||||
int chCount = _lightType == eLight.ALT_8CH ? 8 : 4;
|
||||
for (int i = 0; i < chCount; i++) {
|
||||
_light.SetLightValueInternal(i, l_config.GetChannelLevel(i));
|
||||
}
|
||||
}
|
||||
|
||||
return connected ? E1.OK : E2.NOT_CONNECTED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<UserControl x:Class="AuroraLight.View.KsLight"
|
||||
<UserControl x:Class="AuroraLight.View.KsLight"
|
||||
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"
|
||||
@ -19,8 +19,9 @@
|
||||
|
||||
<StackPanel Orientation="Vertical" Margin="0,20,0,20" HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
|
||||
<StackPanel>
|
||||
<Button Margin="0,20,0,20" Width="100" Height="40" Command="{Binding CMD_Reload}" Content="ReLoad"/>
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<Button Margin="10,20,10,20" Width="100" Height="40" Command="{Binding CMD_Reload}" Content="ReLoad"/>
|
||||
<Button Margin="10,20,10,20" Width="100" Height="40" Command="{Binding CMD_Save}" Content="Save"/>
|
||||
<!-- <Button Width="100" Height="40" Margin="10" Command="{Binding CMD_GetStat}" Content="GetStat"/> -->
|
||||
</StackPanel>
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
using Aurora;
|
||||
using Aurora;
|
||||
using Aurora.Api;
|
||||
using Aurora.View;
|
||||
using Hermes;
|
||||
@ -140,6 +140,12 @@ namespace AuroraLight.View
|
||||
{
|
||||
if (_LightDevice1 != null && _LightDevice1._light != null)
|
||||
_LightDevice1._light.SetLightValueInternal(cbChannel1, value);
|
||||
|
||||
var config = _aurora?.DeviceManager?.GetDeviceConfig(_deviceId1) as LightConfig;
|
||||
if (config != null)
|
||||
{
|
||||
config.SetChannelLevel(cbChannel1, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -161,6 +167,12 @@ namespace AuroraLight.View
|
||||
{
|
||||
if (_LightDevice2 != null && _LightDevice2._light != null)
|
||||
_LightDevice2._light.SetLightValueInternal(cbChannel2, value);
|
||||
|
||||
var config = _aurora?.DeviceManager?.GetDeviceConfig(_deviceId2) as LightConfig;
|
||||
if (config != null)
|
||||
{
|
||||
config.SetChannelLevel(cbChannel2, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -191,10 +203,48 @@ namespace AuroraLight.View
|
||||
public List<int> lsChannel2 { get => _lsChannel2; set => SetProperty(ref _lsChannel2, value); }
|
||||
|
||||
private int _cbChannel1;
|
||||
public int cbChannel1 { get => _cbChannel1; set => SetProperty(ref _cbChannel1, value); }
|
||||
public int cbChannel1
|
||||
{
|
||||
get => _cbChannel1;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _cbChannel1, value))
|
||||
{
|
||||
var config = _aurora?.DeviceManager?.GetDeviceConfig(_deviceId1) as LightConfig;
|
||||
if (config != null)
|
||||
{
|
||||
int chLevel = config.GetChannelLevel(value);
|
||||
if (_nSliderValue1 != chLevel)
|
||||
{
|
||||
_nSliderValue1 = chLevel;
|
||||
NotifyPropertyChanged(nameof(nSliderValue1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int _cbChannel2;
|
||||
public int cbChannel2 { get => _cbChannel2; set => SetProperty(ref _cbChannel2, value); }
|
||||
public int cbChannel2
|
||||
{
|
||||
get => _cbChannel2;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _cbChannel2, value))
|
||||
{
|
||||
var config = _aurora?.DeviceManager?.GetDeviceConfig(_deviceId2) as LightConfig;
|
||||
if (config != null)
|
||||
{
|
||||
int chLevel = config.GetChannelLevel(value);
|
||||
if (_nSliderValue2 != chLevel)
|
||||
{
|
||||
_nSliderValue2 = chLevel;
|
||||
NotifyPropertyChanged(nameof(nSliderValue2));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -221,6 +271,17 @@ namespace AuroraLight.View
|
||||
_LightDevice2._light.SetLightValueInternal(cbChannelALL, value);
|
||||
}
|
||||
|
||||
var config1 = _aurora?.DeviceManager?.GetDeviceConfig(_deviceId1) as LightConfig;
|
||||
if (config1 != null)
|
||||
{
|
||||
config1.SetChannelLevel(cbChannelALL, value);
|
||||
}
|
||||
var config2 = _aurora?.DeviceManager?.GetDeviceConfig(_deviceId2) as LightConfig;
|
||||
if (config2 != null)
|
||||
{
|
||||
config2.SetChannelLevel(cbChannelALL, value);
|
||||
}
|
||||
|
||||
nSliderValue1 = value;
|
||||
nSliderValue2 = value;
|
||||
}
|
||||
@ -262,9 +323,13 @@ namespace AuroraLight.View
|
||||
public ICommand CMD_LightOnOffALL { get; }
|
||||
|
||||
public ICommand CMD_Reload { get; }
|
||||
public ICommand CMD_Save { get; }
|
||||
public ICommand CMD_GetStat { get; }
|
||||
#endregion
|
||||
|
||||
private IAuroraEnvironment _aurora;
|
||||
private string _deviceId1;
|
||||
private string _deviceId2;
|
||||
private LightDevice _LightDevice1;
|
||||
private LightDevice _LightDevice2;
|
||||
|
||||
@ -275,35 +340,30 @@ namespace AuroraLight.View
|
||||
|
||||
public KsLightModel(IAuroraEnvironment aurora, string deviceId1, string deviceId2)
|
||||
{
|
||||
_aurora = aurora;
|
||||
_deviceId1 = deviceId1;
|
||||
_deviceId2 = deviceId2;
|
||||
|
||||
_LightDevice1 = aurora.DeviceManager[deviceId1] as LightDevice;
|
||||
_LightDevice2 = aurora.DeviceManager[deviceId2] as LightDevice;
|
||||
|
||||
|
||||
IsActive1 = true;
|
||||
IsActive2 = true;
|
||||
IsActiveALL = true;
|
||||
|
||||
SliderName1 = _LightDevice1.DeviceId;
|
||||
SliderName2 = _LightDevice2.DeviceId;
|
||||
SliderName1 = _LightDevice1 != null ? _LightDevice1.DeviceId : deviceId1;
|
||||
SliderName2 = _LightDevice2 != null ? _LightDevice2.DeviceId : deviceId2;
|
||||
|
||||
#region Initialize Binding Properties
|
||||
// config 에서 읽어와서 update 해야한다. device 등록할 때 config 만든 config 를 받아올 것. 임시로 고정값 입력
|
||||
nSliderMax = 100;
|
||||
nSliderValue1 = 0;
|
||||
nSliderValue2 = 0;
|
||||
nSliderValueALL = 0;
|
||||
_nSliderValue1 = 0;
|
||||
_nSliderValue2 = 0;
|
||||
_nSliderValueALL = 0;
|
||||
|
||||
if ((_LightDevice1 != null && _LightDevice1._lightType == eLight.ERI) && (_LightDevice2 != null && _LightDevice2._lightType == eLight.ERI))
|
||||
{
|
||||
// 안타깝게도 채널수나 config 는 추상화항목에 없다. 추후에 업데이트하겠음. 일단은 type convert 해서 가져옴
|
||||
// activate 된 후에나 class 생성이 된다. 클래스에서 property 를 가져올수없음
|
||||
//var lightdevice = _LightDevice as ERILight;
|
||||
//nChannel = lightdevice.GetChannelCount();
|
||||
nChannel = 4;
|
||||
nSliderMax = 255;
|
||||
nSliderValue1 = 200;
|
||||
nSliderValue2 = 200;
|
||||
nSliderValueALL = 200;
|
||||
}
|
||||
else nChannel = 8;
|
||||
|
||||
@ -319,16 +379,39 @@ namespace AuroraLight.View
|
||||
int nChannelMax2 = nChannel; // default setting
|
||||
for (int i = 0; i < nChannelMax2; i++) lsChannel2.Add(i);
|
||||
|
||||
buttonOnOffToggle1 = true;
|
||||
strButtonOnOff1 = "ON";
|
||||
|
||||
buttonOnOffToggle2 = true;
|
||||
strButtonOnOff2 = "ON";
|
||||
|
||||
lsChannelALL = new List<int>();
|
||||
int nChannelMaxALL = nChannel; // default setting
|
||||
for (int i = 0; i < nChannelMaxALL; i++) lsChannelALL.Add(i);
|
||||
strButtonOnOffALL = "ON";
|
||||
|
||||
// Read saved values from LightConfig
|
||||
var config1 = _aurora?.DeviceManager?.GetDeviceConfig(_deviceId1) as LightConfig;
|
||||
var config2 = _aurora?.DeviceManager?.GetDeviceConfig(_deviceId2) as LightConfig;
|
||||
|
||||
_nSliderValue1 = config1 != null ? config1.GetChannelLevel(cbChannel1) : 200;
|
||||
_nSliderValue2 = config2 != null ? config2.GetChannelLevel(cbChannel2) : 200;
|
||||
_nSliderValueALL = _nSliderValue1;
|
||||
NotifyPropertyChanged(nameof(nSliderValue1));
|
||||
NotifyPropertyChanged(nameof(nSliderValue2));
|
||||
NotifyPropertyChanged(nameof(nSliderValueALL));
|
||||
|
||||
// Turn on lights with configured brightness values
|
||||
if (_LightDevice1 != null && _LightDevice1._light != null)
|
||||
{
|
||||
_LightDevice1._light.SetLightValueInternal(cbChannel1, _nSliderValue1);
|
||||
}
|
||||
if (_LightDevice2 != null && _LightDevice2._light != null)
|
||||
{
|
||||
_LightDevice2._light.SetLightValueInternal(cbChannel2, _nSliderValue2);
|
||||
}
|
||||
|
||||
buttonOnOffToggle1 = false;
|
||||
strButtonOnOff1 = "OFF";
|
||||
|
||||
buttonOnOffToggle2 = false;
|
||||
strButtonOnOff2 = "OFF";
|
||||
|
||||
buttonOnOffToggleALL = false;
|
||||
strButtonOnOffALL = "OFF";
|
||||
|
||||
#endregion
|
||||
|
||||
@ -338,6 +421,7 @@ namespace AuroraLight.View
|
||||
CMD_LightOnOffALL = new DelegateCommand(LightOnOffALL);
|
||||
|
||||
CMD_Reload = new DelegateCommand(ReLoad);
|
||||
CMD_Save = new DelegateCommand(Save);
|
||||
CMD_GetStat = new DelegateCommand(GetStat);
|
||||
#endregion
|
||||
}
|
||||
@ -351,7 +435,7 @@ namespace AuroraLight.View
|
||||
|
||||
private void ReLoad(object obj)
|
||||
{
|
||||
if (_LightDevice1.IsActivated)
|
||||
if (_LightDevice1 != null && _LightDevice1.IsActivated)
|
||||
{
|
||||
IsActive1 = true;
|
||||
}
|
||||
@ -360,7 +444,7 @@ namespace AuroraLight.View
|
||||
IsActive1 = false;
|
||||
}
|
||||
|
||||
if (_LightDevice2.IsActivated)
|
||||
if (_LightDevice2 != null && _LightDevice2.IsActivated)
|
||||
{
|
||||
IsActive2 = true;
|
||||
}
|
||||
@ -377,6 +461,51 @@ namespace AuroraLight.View
|
||||
{
|
||||
IsActiveALL = false;
|
||||
}
|
||||
|
||||
if (_aurora != null && _aurora.DeviceManager != null)
|
||||
{
|
||||
var config1 = _aurora.DeviceManager.GetDeviceConfig(_deviceId1) as LightConfig;
|
||||
if (config1 != null)
|
||||
{
|
||||
_nSliderValue1 = config1.GetChannelLevel(cbChannel1);
|
||||
NotifyPropertyChanged(nameof(nSliderValue1));
|
||||
}
|
||||
var config2 = _aurora.DeviceManager.GetDeviceConfig(_deviceId2) as LightConfig;
|
||||
if (config2 != null)
|
||||
{
|
||||
_nSliderValue2 = config2.GetChannelLevel(cbChannel2);
|
||||
NotifyPropertyChanged(nameof(nSliderValue2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Save(object obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_aurora != null && _aurora.DeviceManager != null)
|
||||
{
|
||||
var config1 = _aurora.DeviceManager.GetDeviceConfig(_deviceId1) as LightConfig;
|
||||
if (config1 != null)
|
||||
{
|
||||
config1.SetChannelLevel(cbChannel1, nSliderValue1);
|
||||
_aurora.DeviceManager.SaveDeviceConfig(_deviceId1);
|
||||
}
|
||||
|
||||
var config2 = _aurora.DeviceManager.GetDeviceConfig(_deviceId2) as LightConfig;
|
||||
if (config2 != null)
|
||||
{
|
||||
config2.SetChannelLevel(cbChannel2, nSliderValue2);
|
||||
_aurora.DeviceManager.SaveDeviceConfig(_deviceId2);
|
||||
}
|
||||
|
||||
MessageUtil.ShowSuccessToast("Light configuration saved.");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageUtil.ShowErrorToast($"Failed to save light config: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void LightOnOff1(object obj)
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
using Aurora;
|
||||
using Aurora;
|
||||
using Aurora.View;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@ -17,6 +17,12 @@ namespace AuroraLight.View
|
||||
if (SetProperty(ref _nSliderValue, value)) {
|
||||
if (_LightDevice != null && _LightDevice._light != null)
|
||||
_LightDevice._light.SetLightValueInternal(cbChannel, value);
|
||||
|
||||
var config = _aurora?.DeviceManager?.GetDeviceConfig(_deviceId) as LightConfig;
|
||||
if (config != null)
|
||||
{
|
||||
config.SetChannelLevel(cbChannel, value);
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
@ -34,32 +40,45 @@ namespace AuroraLight.View
|
||||
private List<int> _lsChannel;
|
||||
public List<int> lsChannel { get => _lsChannel; set => SetProperty(ref _lsChannel, value); }
|
||||
private int _cbChannel;
|
||||
public int cbChannel { get => _cbChannel; set => SetProperty(ref _cbChannel, value); }
|
||||
public int cbChannel {
|
||||
get => _cbChannel;
|
||||
set {
|
||||
if (SetProperty(ref _cbChannel, value)) {
|
||||
var config = _aurora?.DeviceManager?.GetDeviceConfig(_deviceId) as LightConfig;
|
||||
if (config != null) {
|
||||
int chLevel = config.GetChannelLevel(value);
|
||||
if (_nSliderValue != chLevel) {
|
||||
_nSliderValue = chLevel;
|
||||
NotifyPropertyChanged(nameof(nSliderValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region EventCommands
|
||||
public ICommand CMD_LightOnOff { get; }
|
||||
public ICommand CMD_Save { get; }
|
||||
#endregion
|
||||
|
||||
private IAuroraEnvironment _aurora;
|
||||
private string _deviceId;
|
||||
private LightDevice _LightDevice;
|
||||
|
||||
public UCLightViewModel(IAuroraEnvironment aurora, string deviceId)
|
||||
{
|
||||
_aurora = aurora;
|
||||
_deviceId = deviceId;
|
||||
_LightDevice = aurora.DeviceManager[deviceId] as LightDevice;
|
||||
|
||||
#region Initialize Binding Properties
|
||||
// config 에서 읽어와서 update 해야한다. device 등록할 때 config 만든 config 를 받아올 것. 임시로 고정값 입력
|
||||
nSliderMax = 100;
|
||||
nSliderValue = 0;
|
||||
_nSliderValue = 0;
|
||||
|
||||
if (_LightDevice != null && _LightDevice._lightType == eLight.ERI) {
|
||||
// 안타깝게도 채널수나 config 는 추상화항목에 없다. 추후에 업데이트하겠음. 일단은 type convert 해서 가져옴
|
||||
// activate 된 후에나 class 생성이 된다. 클래스에서 property 를 가져올수없음
|
||||
//var lightdevice = _LightDevice as ERILight;
|
||||
//nChannel = lightdevice.GetChannelCount();
|
||||
nChannel = 4;
|
||||
nSliderMax = 255;
|
||||
nSliderValue = 180;
|
||||
} else nChannel = 8;
|
||||
|
||||
if (lsChannel != null)
|
||||
@ -69,17 +88,42 @@ namespace AuroraLight.View
|
||||
for (int i = 0; i < nChannelMax; i++)
|
||||
lsChannel.Add(i);
|
||||
|
||||
buttonOnOffToggle = true;
|
||||
strButtonOnOff = "ON";
|
||||
var config = _aurora?.DeviceManager?.GetDeviceConfig(_deviceId) as LightConfig;
|
||||
_nSliderValue = config != null ? config.GetChannelLevel(cbChannel) : 200;
|
||||
NotifyPropertyChanged(nameof(nSliderValue));
|
||||
|
||||
if (_LightDevice != null && _LightDevice._light != null) {
|
||||
_LightDevice._light.SetLightValueInternal(cbChannel, _nSliderValue);
|
||||
}
|
||||
|
||||
buttonOnOffToggle = false;
|
||||
strButtonOnOff = "OFF";
|
||||
|
||||
#endregion
|
||||
|
||||
#region DelegateCommands
|
||||
CMD_LightOnOff = new DelegateCommand(LightOnOff);
|
||||
CMD_Save = new DelegateCommand(Save);
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
private void Save(object obj)
|
||||
{
|
||||
try {
|
||||
if (_aurora != null && _aurora.DeviceManager != null) {
|
||||
var config = _aurora.DeviceManager.GetDeviceConfig(_deviceId) as LightConfig;
|
||||
if (config != null) {
|
||||
config.SetChannelLevel(cbChannel, nSliderValue);
|
||||
_aurora.DeviceManager.SaveDeviceConfig(_deviceId);
|
||||
}
|
||||
MessageUtil.ShowSuccessToast("Light configuration saved.");
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
MessageUtil.ShowErrorToast($"Failed to save light config: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void LightOnOff(object obj)
|
||||
{
|
||||
if (_LightDevice != null && _LightDevice._light != null) {
|
||||
|
||||
@ -39,10 +39,6 @@
|
||||
<Reference Include="Aurora">
|
||||
<HintPath>..\..\External\Aurora\bin\Aurora.exe</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="AuroraMotor, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\_out\x64-Debug\AuroraMotor.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="hermes.csharp">
|
||||
<HintPath>..\..\External\Aurora\csharp_lib\hermes.csharp.dll</HintPath>
|
||||
</Reference>
|
||||
@ -161,6 +157,10 @@
|
||||
<Project>{304a2f8d-b543-4ffe-b14f-ddff839d4efb}</Project>
|
||||
<Name>AuroraDeviceCommon</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\AuroraMotor\AuroraMotor.csproj">
|
||||
<Project>{49a61fb7-ec36-4035-b7bc-63ab983590b4}</Project>
|
||||
<Name>AuroraMotor</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
|
||||
@ -431,6 +431,9 @@ namespace CogUI {
|
||||
return DisplayDrawer.ExistsGetInteractiveGraphic(cogDisplay, CogConstants.KEY_TRAIN_ORIGIN);
|
||||
}
|
||||
|
||||
public void UpdateRadiusOfTrainOrigin(double radius) {
|
||||
}
|
||||
|
||||
public void AddRoi(ROI roi, eColor color, bool isRotatable = false) {
|
||||
if (ROI.IsNullOrEmpty(roi)) {
|
||||
DisplayDrawer.AddRoi(cogDisplay, ColorConverter.ConvertColor(color), roi, CogConstants.KEY_ROI);
|
||||
|
||||
@ -219,5 +219,8 @@ namespace CogUI {
|
||||
NotifyPropertyChanged(nameof(RunParam));
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateRadiusOfRoi(eGraRoiType graRoiType, double radius) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -409,5 +409,8 @@ namespace CogUI {
|
||||
NotifyPropertyChanged(nameof(TrainParam));
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateRadiusOfRoi(eGraRoiType graRoiType, double radius) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -290,5 +290,8 @@ namespace CogUI {
|
||||
NotifyPropertyChanged(nameof(RunParam));
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateRadiusOfRoi(eGraRoiType graRoiType, double radius) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -12,6 +12,7 @@ namespace MilPattern {
|
||||
public class PmParamExt : ICloneable {
|
||||
private const string FILE_NAME = "PmParamExt.json";
|
||||
public ROI FindROI { get; set; } = new ROI();
|
||||
public double TrainRoiSize { get; set; } = 25.0;
|
||||
|
||||
public PmParamExt() {
|
||||
}
|
||||
@ -22,7 +23,8 @@ namespace MilPattern {
|
||||
|
||||
public object Clone() {
|
||||
return new PmParamExt() {
|
||||
FindROI = FindROI.Clone() as ROI
|
||||
FindROI = FindROI.Clone() as ROI,
|
||||
TrainRoiSize = TrainRoiSize
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
using Aurora.Api;
|
||||
using Aurora.Api;
|
||||
using Aurora.Api.DataType;
|
||||
using Hermes;
|
||||
using Hermes.Functional;
|
||||
@ -61,8 +61,10 @@ namespace MilUI {
|
||||
|
||||
#region TrainRoi & FindRoi Changed Event
|
||||
private GCHandle _TrainRoiChangedDataHandle;
|
||||
private GCHandle _TrainOriginChangedDataHandle;
|
||||
private Dictionary<eRoiIdx, GCHandle> _FindRoiChangedDataHandles = new Dictionary<eRoiIdx, GCHandle>();
|
||||
private MIL_GRA_HOOK_FUNCTION_PTR _OnTrainRoiChangedFuncPtr;
|
||||
private MIL_GRA_HOOK_FUNCTION_PTR _OnTrainOriginChangedFuncPtr;
|
||||
private Dictionary<eRoiIdx, MIL_GRA_HOOK_FUNCTION_PTR> _OnFindRoiChangedFuncPtrs = new Dictionary<eRoiIdx, MIL_GRA_HOOK_FUNCTION_PTR>();
|
||||
#endregion
|
||||
|
||||
@ -644,11 +646,15 @@ namespace MilUI {
|
||||
return E1.GENERIC;
|
||||
}
|
||||
|
||||
MIL.MgraArc(GraphicContext, StaticGraphicList, imageCenter.Origin.X, imageCenter.Origin.Y, 25, 25, 0, 360);
|
||||
double radius = imageCenter.Length > 0 ? imageCenter.Length : 25;
|
||||
|
||||
MIL.MgraArc(GraphicContext, StaticGraphicList, imageCenter.Origin.X, imageCenter.Origin.Y, radius, radius, 0, 360);
|
||||
MIL.MgraInquireList(StaticGraphicList, MIL.M_LIST, MIL.M_DEFAULT, MIL.M_LAST_LABEL, ref _trainOriginLabel);
|
||||
MIL.MgraControlList(StaticGraphicList, MIL.M_GRAPHIC_LABEL(_trainOriginLabel), MIL.M_DEFAULT, MIL.M_RESIZABLE, MIL.M_DISABLE);
|
||||
MIL.MgraControlList(StaticGraphicList, MIL.M_GRAPHIC_LABEL(_trainOriginLabel), MIL.M_DEFAULT, MIL.M_RESIZABLE, MIL.M_ENABLE);
|
||||
MIL.MgraControlList(StaticGraphicList, MIL.M_GRAPHIC_LABEL(_trainOriginLabel), MIL.M_DEFAULT, MIL.M_CONSTRAIN_ASPECT_RATIO, 1.0);
|
||||
MIL.MgraControlList(StaticGraphicList, MIL.M_GRAPHIC_LABEL(_trainOriginLabel), MIL.M_DEFAULT, MIL.M_SPECIFIC_FEATURES_EDITABLE, MIL.M_DISABLE);
|
||||
|
||||
SetTrainOriginChangedEvent();
|
||||
_trainGraphics.Add();
|
||||
|
||||
return E1.OK;
|
||||
@ -661,10 +667,23 @@ namespace MilUI {
|
||||
|
||||
double x = 0;
|
||||
double y = 0;
|
||||
double radius = 0;
|
||||
MIL.MgraInquireList(StaticGraphicList, MIL.M_GRAPHIC_LABEL(_trainOriginLabel), MIL.M_DEFAULT, MIL.M_POSITION_X, ref x);
|
||||
MIL.MgraInquireList(StaticGraphicList, MIL.M_GRAPHIC_LABEL(_trainOriginLabel), MIL.M_DEFAULT, MIL.M_POSITION_Y, ref y);
|
||||
MIL.MgraInquireList(StaticGraphicList, MIL.M_GRAPHIC_LABEL(_trainOriginLabel), MIL.M_DEFAULT, MIL.M_RADIUS_X, ref radius);
|
||||
|
||||
return new Cross(new ImagePoint(x, y));
|
||||
return new Cross(new ImagePoint(x, y), radius);
|
||||
}
|
||||
|
||||
public void UpdateRadiusOfTrainOrigin(double radius) {
|
||||
if (HasTrainOrigin()) {
|
||||
MIL.MgraControlList(StaticGraphicList, MIL.M_GRAPHIC_LABEL(_trainOriginLabel), MIL.M_DEFAULT, MIL.M_RADIUS_X, radius);
|
||||
MIL.MgraControlList(StaticGraphicList, MIL.M_GRAPHIC_LABEL(_trainOriginLabel), MIL.M_DEFAULT, MIL.M_RADIUS_Y, radius);
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasTrainOrigin() {
|
||||
return _trainGraphics != null && _trainGraphics.HasGraphicLabel(_trainOriginLabel);
|
||||
}
|
||||
|
||||
public int AddDefaultFindRoi(ImageSize imageSize, bool isRotatable = false) {
|
||||
@ -860,6 +879,8 @@ namespace MilUI {
|
||||
}
|
||||
|
||||
public int ClearTrainGraphics(eGraphicToClear graphicToClear = eGraphicToClear.ALL) {
|
||||
RemoveTrainRoiChangedEvent();
|
||||
RemoveTrainOriginChangedEvent();
|
||||
_trainGraphics?.Clear();
|
||||
_trainRoiLabel = MIL.M_NULL;
|
||||
_trainOriginLabel = MIL.M_NULL;
|
||||
@ -1051,6 +1072,68 @@ namespace MilUI {
|
||||
}
|
||||
}
|
||||
|
||||
private void SetTrainOriginChangedEvent() {
|
||||
RemoveTrainOriginChangedEvent();
|
||||
|
||||
if (!_TrainOriginChangedDataHandle.IsAllocated) {
|
||||
if (_trainOriginLabel != MIL.M_NULL) {
|
||||
_TrainOriginChangedDataHandle = GCHandle.Alloc(_trainOriginLabel);
|
||||
_OnTrainOriginChangedFuncPtr = new MIL_GRA_HOOK_FUNCTION_PTR(OnTrainOriginChanged);
|
||||
MIL.MgraHookFunction(StaticGraphicList, MIL.M_INTERACTIVE_GRAPHIC_STATE_MODIFIED, _OnTrainOriginChangedFuncPtr, GCHandle.ToIntPtr(_TrainOriginChangedDataHandle));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveTrainOriginChangedEvent() {
|
||||
if (_TrainOriginChangedDataHandle.IsAllocated) {
|
||||
MIL.MgraHookFunction(StaticGraphicList, MIL.M_INTERACTIVE_GRAPHIC_STATE_MODIFIED + MIL.M_UNHOOK, _OnTrainOriginChangedFuncPtr, GCHandle.ToIntPtr(_TrainOriginChangedDataHandle));
|
||||
_OnTrainOriginChangedFuncPtr = null;
|
||||
_TrainOriginChangedDataHandle.Free();
|
||||
}
|
||||
}
|
||||
|
||||
private MIL_INT OnTrainOriginChanged(MIL_INT HookType, MIL_ID EventId, IntPtr UserDataPtr) {
|
||||
try {
|
||||
if (_trainOriginLabel == MIL.M_NULL) {
|
||||
return MIL.M_NULL;
|
||||
}
|
||||
|
||||
if (!IntPtr.Zero.Equals(UserDataPtr)) {
|
||||
MIL_INT curState = 0;
|
||||
MIL.MgraGetHookInfo(EventId, MIL.M_INTERACTIVE_GRAPHIC_STATE, ref curState);
|
||||
|
||||
if (curState == MIL.M_STATE_GRAPHIC_HOVERED || curState == MIL.M_STATE_HANDLE_HOVERED) {
|
||||
return MIL.M_NULL;
|
||||
}
|
||||
|
||||
MIL_INT modifiedGraphicLabel = 0;
|
||||
MIL.MgraGetHookInfo(EventId, MIL.M_GRAPHIC_LABEL_VALUE, ref modifiedGraphicLabel);
|
||||
|
||||
if (modifiedGraphicLabel == _trainOriginLabel) {
|
||||
double radiusX = 0;
|
||||
MIL.MgraInquireList(StaticGraphicList, MIL.M_GRAPHIC_LABEL(_trainOriginLabel), MIL.M_DEFAULT, MIL.M_RADIUS_X, ref radiusX);
|
||||
|
||||
if (radiusX > 500.0) {
|
||||
radiusX = 500.0;
|
||||
MIL.MgraControlList(StaticGraphicList, MIL.M_GRAPHIC_LABEL(_trainOriginLabel), MIL.M_DEFAULT, MIL.M_RADIUS_X, 500.0);
|
||||
MIL.MgraControlList(StaticGraphicList, MIL.M_GRAPHIC_LABEL(_trainOriginLabel), MIL.M_DEFAULT, MIL.M_RADIUS_Y, 500.0);
|
||||
}
|
||||
|
||||
if (_PatternInfos.ContainsKey(eRoiIdx.Roi0) && _GraEventSubscribers?.Count > 0) {
|
||||
var patternInfo = _PatternInfos[eRoiIdx.Roi0];
|
||||
if (_GraEventSubscribers.ContainsKey(patternInfo)) {
|
||||
_GraEventSubscribers[patternInfo]?.UpdateRadiusOfRoi(eGraRoiType.TrainOrigin, radiusX);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
_Logger?.FuncE(e.Message);
|
||||
}
|
||||
return MIL.M_NULL;
|
||||
}
|
||||
|
||||
private void RemoveFindRoiChangedEvent(eRoiIdx roiIdx) {
|
||||
if (_FindRoiChangedDataHandles.ContainsKey(roiIdx) && _FindRoiChangedDataHandles[roiIdx].IsAllocated) {
|
||||
MIL.MgraHookFunction(StaticGraphicList, MIL.M_INTERACTIVE_GRAPHIC_STATE_MODIFIED + MIL.M_UNHOOK, _OnFindRoiChangedFuncPtrs[roiIdx], GCHandle.ToIntPtr(_FindRoiChangedDataHandles[roiIdx]));
|
||||
@ -1127,6 +1210,7 @@ namespace MilUI {
|
||||
|
||||
private void RemoveHookFunc() {
|
||||
RemoveTrainRoiChangedEvent();
|
||||
RemoveTrainOriginChangedEvent();
|
||||
for (int i = 0; i < _FindRoiChangedDataHandles.Count; i++) {
|
||||
RemoveFindRoiChangedEvent((eRoiIdx)i);
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
@ -220,5 +220,8 @@ namespace MilUI {
|
||||
NotifyPropertyChanged(nameof(RunParam));
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateRadiusOfRoi(eGraRoiType graRoiType, double radius) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -174,6 +174,7 @@ namespace MilUI {
|
||||
if (result == MessageBoxResult.Yes) {
|
||||
var mainPatternInfo = _patternAgent.GetMainPatternInfo(_patternInfo.GetPatternIndex());
|
||||
if (E1.OK == _patternAgent.CopyPattern(mainPatternInfo.GetPatternIndex(), _patternInfo.GetPatternIndex())) {
|
||||
DeactivateRegisteredSubPattern();
|
||||
InitRunParam();
|
||||
InitFixturePatterns();
|
||||
UpdateControlButtons(true);
|
||||
@ -186,6 +187,7 @@ namespace MilUI {
|
||||
if (!_patternAgent.IsPatternExist(_patternInfo.GetPatternIndex())) {
|
||||
if (E1.OK == _patternAgent.Create(_patternInfo) &&
|
||||
E1.OK == _patternAgent.Save(_patternInfo)) {
|
||||
DeactivateRegisteredSubPattern();
|
||||
InitRunParam();
|
||||
InitFixturePatterns();
|
||||
UpdateControlButtons(true);
|
||||
@ -214,12 +216,34 @@ namespace MilUI {
|
||||
var result = MessageBoxUtil.ShowMessageBoxQuestion(StrTokens.MSG_Q_Delete);
|
||||
if (result == MessageBoxResult.Yes) {
|
||||
if (_patternAgent.IsPatternExist(_patternInfo.GetPatternIndex())) {
|
||||
if (_patternAgent.IsPatternFileLocked(_patternInfo, out string lockedFilePath)) {
|
||||
MessageBoxUtil.ShowMessageBoxError(PatternAgentBase.GetPatternFileLockedMessage(lockedFilePath));
|
||||
return;
|
||||
}
|
||||
if (E1.OK == _patternAgent.Remove(_patternInfo)) {
|
||||
UpdateControlButtons(false);
|
||||
}
|
||||
else {
|
||||
MessageBoxUtil.ShowMessageBoxError(PatternAgentBase.GetPatternFileLockedMessage(string.Empty));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 서브 패턴은 OFF(IsActivated = false) 로 등록한다. 작업자가 확인한 뒤 ON 으로 바꾼다.
|
||||
private void DeactivateRegisteredSubPattern() {
|
||||
if (!IsSubPattern) {
|
||||
return;
|
||||
}
|
||||
|
||||
_patternInfo.IsActivated = false;
|
||||
|
||||
var registeredPatternInfo = _patternAgent.GetPatternInfo(_patternInfo.GetPatternIndex());
|
||||
if (registeredPatternInfo != null) {
|
||||
registeredPatternInfo.IsActivated = false;
|
||||
_patternAgent.Save(registeredPatternInfo);
|
||||
}
|
||||
}
|
||||
|
||||
private void ClosingWindow() {
|
||||
_cameraDisplay.ClearTrainGraphics();
|
||||
@ -410,5 +434,8 @@ namespace MilUI {
|
||||
NotifyPropertyChanged(nameof(TrainParam));
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateRadiusOfRoi(eGraRoiType graRoiType, double radius) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
@ -290,5 +290,8 @@ namespace MilUI {
|
||||
NotifyPropertyChanged(nameof(RunParam));
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateRadiusOfRoi(eGraRoiType graRoiType, double radius) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -170,6 +170,9 @@ namespace MilUI {
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateRadiusOfRoi(eGraRoiType graRoiType, double radius) {
|
||||
}
|
||||
|
||||
private double ConvertDegreeDecimalPlaces(double degree) {
|
||||
return Math.Round(degree, 1);
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<UserControl x:Class="MilUI.PatternMatchingSettingView"
|
||||
<UserControl x:Class="MilUI.PatternMatchingSettingView"
|
||||
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"
|
||||
@ -65,6 +65,7 @@
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition/>
|
||||
@ -127,6 +128,15 @@
|
||||
</TextBlock>
|
||||
</visionCommonUI:UCContentComboBox>
|
||||
</Grid>
|
||||
|
||||
<visionCommonUI:UCContentSlider Grid.Row="3" Grid.ColumnSpan="2" Margin="5"
|
||||
MinValue="1" MaxValue="500" TickFrequency="10" Step="1"
|
||||
KeyValue="{Binding ElementName=patternMatchingSettingView, Path=DataContext.TrainRoiSize}">
|
||||
<TextBlock Style="{StaticResource stylePatternSliderTextBlock}">
|
||||
<Run Text="{Binding [Train], Source={StaticResource langTokens}, Mode=OneWay}"/>
|
||||
<Run Text="{Binding [ROI], Source={StaticResource langTokens}, Mode=OneWay}"/>
|
||||
</TextBlock>
|
||||
</visionCommonUI:UCContentSlider>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@ using VisionCommonUI;
|
||||
using VisionCommonUI.Resources;
|
||||
|
||||
namespace MilUI {
|
||||
public class PatternMatchingSettingViewModel : NotifyPropertyChangedBase {
|
||||
public class PatternMatchingSettingViewModel : NotifyPropertyChangedBase, IGraEventSubscriber {
|
||||
private Logger _logger = new Logger("PatternMatchingSettingVM");
|
||||
|
||||
public ICommand CMD_VisibleChanged { get; }
|
||||
@ -57,6 +57,25 @@ namespace MilUI {
|
||||
private PatternMatchingRunParam _runParam;
|
||||
public PatternMatchingRunParam RunParam { get => _runParam; set => SetProperty(ref _runParam, value); }
|
||||
|
||||
private double _trainRoiSize = 25;
|
||||
public double TrainRoiSize {
|
||||
get => _trainRoiSize;
|
||||
set {
|
||||
if (SetProperty(ref _trainRoiSize, value)) {
|
||||
if (RunParam?.PmParamExt != null) {
|
||||
RunParam.PmParamExt.TrainRoiSize = value;
|
||||
}
|
||||
if (!_isUpdatingFromDisplay) {
|
||||
if (_cameraDisplay != null && _cameraDisplay.HasTrainOrigin()) {
|
||||
_cameraDisplay.UpdateRadiusOfTrainOrigin(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool _isUpdatingFromDisplay = false;
|
||||
|
||||
private IEnumerable<int> _fixturePatterns;
|
||||
public IEnumerable<int> FixturePatterns { get => _fixturePatterns; set => SetProperty(ref _fixturePatterns, value); }
|
||||
|
||||
@ -96,6 +115,7 @@ namespace MilUI {
|
||||
InitRunParam();
|
||||
InitFixturePatterns();
|
||||
UpdateControlButtons(IsPatternRegistered);
|
||||
_cameraDisplay.SetGraEventSubscriber(_patternInfo, this);
|
||||
}
|
||||
|
||||
public void InitRegistered() {
|
||||
@ -109,6 +129,10 @@ namespace MilUI {
|
||||
else {
|
||||
RunParam = new PatternMatchingRunParam();
|
||||
}
|
||||
if (RunParam?.PmParamExt != null && RunParam.PmParamExt.TrainRoiSize > 0) {
|
||||
_trainRoiSize = RunParam.PmParamExt.TrainRoiSize;
|
||||
NotifyPropertyChanged(nameof(TrainRoiSize));
|
||||
}
|
||||
}
|
||||
|
||||
public void InitFixturePatterns() {
|
||||
@ -134,6 +158,7 @@ namespace MilUI {
|
||||
if (result == MessageBoxResult.Yes) {
|
||||
var mainPatternInfo = _patternAgent.GetMainPatternInfo(_patternInfo.GetPatternIndex());
|
||||
if (E1.OK == _patternAgent.CopyPattern(mainPatternInfo.GetPatternIndex(), _patternInfo.GetPatternIndex())) {
|
||||
DeactivateRegisteredSubPattern();
|
||||
InitRunParam();
|
||||
InitFixturePatterns();
|
||||
UpdateControlButtons(true);
|
||||
@ -146,6 +171,7 @@ namespace MilUI {
|
||||
if (!_patternAgent.IsPatternExist(_patternInfo.GetPatternIndex())) {
|
||||
if (E1.OK == _patternAgent.Create(_patternInfo) &&
|
||||
E1.OK == _patternAgent.Save(_patternInfo)) {
|
||||
DeactivateRegisteredSubPattern();
|
||||
InitRunParam();
|
||||
InitFixturePatterns();
|
||||
UpdateControlButtons(true);
|
||||
@ -158,6 +184,9 @@ namespace MilUI {
|
||||
if (_cameraDisplay.HasFindRoi()) {
|
||||
RunParam.SetFindROI(_cameraDisplay.GetFindRoi().Clone() as ROI);
|
||||
}
|
||||
if (RunParam?.PmParamExt != null) {
|
||||
RunParam.PmParamExt.TrainRoiSize = TrainRoiSize;
|
||||
}
|
||||
_patternAgent.SetRunParam(_patternInfo, RunParam);
|
||||
_patternAgent.Save(_patternInfo);
|
||||
MessageBoxUtil.ShowMessageBoxOk(StrTokens.MSG_O_SaveCompleted);
|
||||
@ -173,12 +202,34 @@ namespace MilUI {
|
||||
var result = MessageBoxUtil.ShowMessageBoxQuestion(StrTokens.MSG_Q_Delete);
|
||||
if (result == MessageBoxResult.Yes) {
|
||||
if (_patternAgent.IsPatternExist(_patternInfo.GetPatternIndex())) {
|
||||
if (_patternAgent.IsPatternFileLocked(_patternInfo, out string lockedFilePath)) {
|
||||
MessageBoxUtil.ShowMessageBoxError(PatternAgentBase.GetPatternFileLockedMessage(lockedFilePath));
|
||||
return;
|
||||
}
|
||||
if (E1.OK == _patternAgent.Remove(_patternInfo)) {
|
||||
UpdateControlButtons(false);
|
||||
}
|
||||
else {
|
||||
MessageBoxUtil.ShowMessageBoxError(PatternAgentBase.GetPatternFileLockedMessage(string.Empty));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sub pattern is registered as OFF (IsActivated = false). The operator turns it ON after checking.
|
||||
private void DeactivateRegisteredSubPattern() {
|
||||
if (!IsSubPattern) {
|
||||
return;
|
||||
}
|
||||
|
||||
_patternInfo.IsActivated = false;
|
||||
|
||||
var registeredPatternInfo = _patternAgent.GetPatternInfo(_patternInfo.GetPatternIndex());
|
||||
if (registeredPatternInfo != null) {
|
||||
registeredPatternInfo.IsActivated = false;
|
||||
_patternAgent.Save(registeredPatternInfo);
|
||||
}
|
||||
}
|
||||
|
||||
private void ClosingWindow() {
|
||||
_cameraDisplay.ClearTrainGraphics();
|
||||
@ -216,6 +267,7 @@ namespace MilUI {
|
||||
}
|
||||
|
||||
private void SetTrainROI(object obj) {
|
||||
_cameraDisplay.SetPatternInfo(_patternInfo);
|
||||
var milImage = _cameraDisplay.GetImage();
|
||||
if (milImage != 0) {
|
||||
var curPattern = _patternAgent.GetPattern(_patternInfo) as IPatternTrain;
|
||||
@ -225,9 +277,15 @@ namespace MilUI {
|
||||
var imageCenter = MilEnvironment.GetImageCenter(milImage);
|
||||
if (ROI.IsNullOrEmpty(TrainParam.TrainRoi) || TrainParam.TrainOrigin is null) {
|
||||
_cameraDisplay.AddTrainRoi(imageCenter);
|
||||
_cameraDisplay.AddTrainOrigin(new Cross(imageCenter));
|
||||
_cameraDisplay.AddTrainOrigin(new Cross(imageCenter, TrainRoiSize));
|
||||
}
|
||||
else {
|
||||
if (TrainParam.TrainOrigin.Length <= 0) {
|
||||
TrainParam.TrainOrigin.Length = TrainRoiSize;
|
||||
}
|
||||
else {
|
||||
TrainRoiSize = TrainParam.TrainOrigin.Length;
|
||||
}
|
||||
_cameraDisplay.AddTrainRoi(TrainParam.TrainRoi);
|
||||
_cameraDisplay.AddTrainOrigin(TrainParam.TrainOrigin);
|
||||
}
|
||||
@ -377,5 +435,20 @@ namespace MilUI {
|
||||
ResetWindow();
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateAngleOfRoi(eGraRoiType graRoiType, object param) {
|
||||
}
|
||||
|
||||
public void UpdateRadiusOfRoi(eGraRoiType graRoiType, double radius) {
|
||||
if (graRoiType == eGraRoiType.TrainOrigin) {
|
||||
_isUpdatingFromDisplay = true;
|
||||
try {
|
||||
TrainRoiSize = Math.Min(500, Math.Max(1, Math.Round(radius, 1)));
|
||||
}
|
||||
finally {
|
||||
_isUpdatingFromDisplay = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -495,9 +495,30 @@ namespace VisionCommon {
|
||||
public int Remove(PatternInfo patternInfo) {
|
||||
if (patternInfo != null) {
|
||||
if (GetPatterns().ContainsKey(patternInfo)) {
|
||||
// MIL 프로그램 등에서 패턴 파일을 열어 두면 폴더 삭제 중 예외가 나므로, 먼저 확인하고 아무것도 지우지 않는다.
|
||||
if (IsPatternFileLocked(patternInfo, out string lockedFilePath)) {
|
||||
_logger.E($"Pattern file is locked : {lockedFilePath}");
|
||||
return E1.GENERIC;
|
||||
}
|
||||
|
||||
try {
|
||||
GetPatterns()[patternInfo].Remove(); // Remove Sub Pattern Directory
|
||||
GetPatterns().Remove(patternInfo);
|
||||
DeletePatternDirectory(patternInfo);
|
||||
}
|
||||
catch (Exception e) {
|
||||
_logger.E($"Remove pattern error : {patternInfo}, {e.Message}");
|
||||
// 삭제 도중 실패하면 남은 파일로 패턴을 다시 불러와 둔다.
|
||||
try {
|
||||
if (GetPatterns().ContainsKey(patternInfo)) {
|
||||
ReloadPattern(patternInfo);
|
||||
}
|
||||
}
|
||||
catch (Exception reloadException) {
|
||||
_logger.E($"Reload pattern error : {patternInfo}, {reloadException.Message}");
|
||||
}
|
||||
return E1.GENERIC;
|
||||
}
|
||||
|
||||
return E1.OK;
|
||||
}
|
||||
@ -505,6 +526,48 @@ namespace VisionCommon {
|
||||
return E2.NOT_FOUND;
|
||||
}
|
||||
|
||||
// 패턴(메인 또는 서브 하나) 폴더의 파일 중 다른 프로그램이 열고 있는 파일이 있는지 확인한다.
|
||||
public bool IsPatternFileLocked(PatternInfo patternInfo, out string lockedFilePath) {
|
||||
lockedFilePath = string.Empty;
|
||||
|
||||
var patternDirPath = Path.GetDirectoryName(PatternConstants.GetSubPatternInfoFilePath(patternInfo));
|
||||
if (!Directory.Exists(patternDirPath)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (var filePath in Directory.GetFiles(patternDirPath, "*", SearchOption.AllDirectories)) {
|
||||
try {
|
||||
using (File.Open(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None)) {
|
||||
}
|
||||
}
|
||||
catch (IOException) {
|
||||
lockedFilePath = filePath;
|
||||
return true;
|
||||
}
|
||||
catch (UnauthorizedAccessException) {
|
||||
lockedFilePath = filePath;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 메인과 서브 패턴 전체 중 다른 프로그램이 열고 있는 파일이 있는지 확인한다.
|
||||
public bool IsMainSubPatternFileLocked(PatternInfo patternInfo, out string lockedFilePath) {
|
||||
lockedFilePath = string.Empty;
|
||||
foreach (var curPatternInfo in GetMainSubPatterns(patternInfo)) {
|
||||
if (IsPatternFileLocked(curPatternInfo, out lockedFilePath)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static string GetPatternFileLockedMessage(string lockedFilePath) {
|
||||
return "패턴 파일이 다른 프로그램에서 열려 있어 삭제할 수 없습니다.\n" +
|
||||
"MIL 프로그램 등에서 파일을 닫은 뒤 다시 삭제하세요.\n\n" + lockedFilePath;
|
||||
}
|
||||
|
||||
public abstract IPatternFinder CreatePattern(PatternInfo patternInfo);
|
||||
|
||||
public void DeletePatternDirectory(PatternInfo patternInfo) {
|
||||
|
||||
@ -34,6 +34,8 @@ namespace VisionCommon {
|
||||
ROI GetTrainRoi();
|
||||
int AddTrainOrigin(Cross imageCenter);
|
||||
Cross GetTrainOrigin();
|
||||
void UpdateRadiusOfTrainOrigin(double radius);
|
||||
bool HasTrainOrigin();
|
||||
|
||||
int AddDefaultFindRoi(ImageSize imageSize, bool isRotatable = false);
|
||||
int AddFindRoi(ROI findRoi, bool isRotatable = false);
|
||||
|
||||
@ -5,10 +5,12 @@
|
||||
namespace VisionCommon {
|
||||
public enum eGraRoiType {
|
||||
TrainRoi,
|
||||
FindRoi
|
||||
FindRoi,
|
||||
TrainOrigin
|
||||
}
|
||||
|
||||
public interface IGraEventSubscriber {
|
||||
void UpdateAngleOfRoi(eGraRoiType graRoiType, object param);
|
||||
void UpdateRadiusOfRoi(eGraRoiType graRoiType, double radius);
|
||||
}
|
||||
}
|
||||
@ -48,6 +48,9 @@ namespace VisionCommon {
|
||||
public int MilSystemId { get; set; }
|
||||
[JsonIgnore]
|
||||
public Bitmap Thumbnail { get; set; } = ThumbnailUtil.GetDefaultImage();
|
||||
// Sub pattern list for display (pattern list thumbnails)
|
||||
[JsonIgnore]
|
||||
public System.Collections.Generic.List<PatternInfo> SubPatternInfos { get; set; } = new System.Collections.Generic.List<PatternInfo>();
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
protected void OnPropertyChanged(string propertyName)
|
||||
|
||||
@ -17,7 +17,7 @@ namespace VisionCommon {
|
||||
public const int MAIN_PATTERN_INDEX = 0;
|
||||
public const int FOV_PATTERN_COUNT = 20;
|
||||
public const int CAM_PATTERN_COUNT = 20;
|
||||
public const int SUB_PATTERN_COUNT = 5;
|
||||
public const int SUB_PATTERN_COUNT = 11; // 메인(0) 포함. 서브는 1 ~ 10
|
||||
|
||||
public static bool IsMainPattern(PatternIndex patternIndex) {
|
||||
return patternIndex.PatternSubId == MAIN_PATTERN_INDEX;
|
||||
|
||||
@ -4,6 +4,7 @@ using VisionSequence.Pattern;
|
||||
using VisionCommonUI;
|
||||
using VisionCommonUI.Resources;
|
||||
using Aurora.View;
|
||||
using Hermes;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
@ -133,6 +134,7 @@ namespace VisionUI {
|
||||
|
||||
var curPatternInfo = Patterns[Patterns.Count - 1];
|
||||
curPatternInfo.Thumbnail = _PatternAgent.GetThumbnail(curPatternInfo);
|
||||
curPatternInfo.SubPatternInfos = GetSubPatternsWithThumbnail(curPatternInfo);
|
||||
}
|
||||
else {
|
||||
Patterns.Add(CreateDefaultPatternInfo(i));
|
||||
@ -147,6 +149,22 @@ namespace VisionUI {
|
||||
}
|
||||
}
|
||||
|
||||
// 목록의 행마다 서브 패턴 썸네일을 함께 보여주기 위해, 서브 번호순으로 썸네일을 채운 서브 패턴 목록을 만든다.
|
||||
private List<PatternInfo> GetSubPatternsWithThumbnail(PatternInfo mainPatternInfo) {
|
||||
var subPatternInfos = new List<PatternInfo>();
|
||||
try {
|
||||
foreach (var subPatternInfo in _PatternAgent.GetSubPatterns(mainPatternInfo)
|
||||
.OrderBy(pi => pi.GetPatternIndex().PatternSubId)) {
|
||||
subPatternInfo.Thumbnail = _PatternAgent.GetThumbnail(subPatternInfo);
|
||||
subPatternInfos.Add(subPatternInfo);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
_logger.FuncE(e.Message);
|
||||
}
|
||||
return subPatternInfos;
|
||||
}
|
||||
|
||||
public List<PatternInfo> GetExistingPatterns() {
|
||||
if (_PatternAgent == null) {
|
||||
ResetPatternAgent();
|
||||
@ -256,23 +274,39 @@ namespace VisionUI {
|
||||
var result = MessageBoxUtil.ShowMessageBoxQuestion(
|
||||
string.Format(StrTokens.MSG_Q_DeletePatternFormat, SelectedPatternIndex));
|
||||
if (result == MessageBoxResult.Yes) {
|
||||
// 메인/서브 중 하나라도 다른 프로그램이 열고 있으면 아무것도 지우지 않는다.
|
||||
if (_PatternAgent.IsMainSubPatternFileLocked(Patterns[SelectedPatternIndex], out string lockedFilePath)) {
|
||||
_logger.FuncE($"Pattern file is locked : {lockedFilePath}");
|
||||
MessageBoxUtil.ShowMessageBoxError(PatternAgentBase.GetPatternFileLockedMessage(lockedFilePath));
|
||||
return;
|
||||
}
|
||||
|
||||
Application.Current.Dispatcher.Invoke(() => {
|
||||
DeleteSubPatterns(Patterns[SelectedPatternIndex]);
|
||||
DeleteMainPattern(Patterns[SelectedPatternIndex]);
|
||||
Patterns[SelectedPatternIndex] = CreateDefaultPatternInfo(SelectedPatternIndex);
|
||||
try {
|
||||
bool isRemoved = DeleteSubPatterns(Patterns[SelectedPatternIndex]);
|
||||
isRemoved &= DeleteMainPattern(Patterns[SelectedPatternIndex]);
|
||||
if (!isRemoved) {
|
||||
MessageBoxUtil.ShowMessageBoxError(PatternAgentBase.GetPatternFileLockedMessage(string.Empty));
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
_logger.FuncE(e.Message);
|
||||
}
|
||||
InitPatternList(lastSelectedPatternIndex);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void DeleteSubPatterns(PatternInfo patternInfo) {
|
||||
private bool DeleteSubPatterns(PatternInfo patternInfo) {
|
||||
bool isRemoved = true;
|
||||
var subPatternList = _PatternAgent.GetSubPatterns(patternInfo);
|
||||
foreach (var subPatternInfo in subPatternList) {
|
||||
_PatternAgent.Remove(subPatternInfo);
|
||||
isRemoved &= (E1.OK == _PatternAgent.Remove(subPatternInfo));
|
||||
}
|
||||
return isRemoved;
|
||||
}
|
||||
private void DeleteMainPattern(PatternInfo patternInfo) {
|
||||
_PatternAgent.Remove(patternInfo);
|
||||
private bool DeleteMainPattern(PatternInfo patternInfo) {
|
||||
return E1.OK == _PatternAgent.Remove(patternInfo);
|
||||
}
|
||||
|
||||
private void Apply(object obj) {
|
||||
|
||||
@ -50,9 +50,9 @@
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="1*"/>
|
||||
<ColumnDefinition Width="3*"/>
|
||||
<ColumnDefinition Width="7*"/>
|
||||
<ColumnDefinition Width="5*"/>
|
||||
<ColumnDefinition Width="15*"/>
|
||||
<ColumnDefinition Width="6*"/>
|
||||
<ColumnDefinition Width="8*"/>
|
||||
<ColumnDefinition Width="16*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" Style="{StaticResource styleGroupBoxHeaderTextBlock}" TextAlignment="Center" FontSize="15" Text="ID"/>
|
||||
<TextBlock Grid.Column="1" Style="{StaticResource styleGroupBoxHeaderTextBlock}" TextAlignment="Center" FontSize="15"
|
||||
@ -77,16 +77,58 @@
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="1*"/>
|
||||
<ColumnDefinition Width="3*"/>
|
||||
<ColumnDefinition Width="7*"/>
|
||||
<ColumnDefinition Width="5*"/>
|
||||
<ColumnDefinition Width="15*"/>
|
||||
<ColumnDefinition Width="6*"/>
|
||||
<ColumnDefinition Width="8*"/>
|
||||
<ColumnDefinition Width="16*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" Style="{StaticResource styleTextBlockDataGridItem}" FontSize="15" Text="{Binding PatternIndex.PatternId}"/>
|
||||
<TextBlock Grid.Column="1" Style="{StaticResource styleTextBlockDataGridItem}" FontSize="15" Text="{Binding IsActivated}"/>
|
||||
<TextBlock Grid.Column="2" Style="{StaticResource styleTextBlockDataGridItem}" FontSize="15" Text="{Binding PatternType}"/>
|
||||
<Image Grid.Column="3" Margin="0" Width="38" Height="38"
|
||||
<!-- 메인(M) 썸네일 뒤에 서브 패턴 썸네일을 서브 번호순으로 한 줄로 보여준다. 서브는 2개 폭만 보이고 나머지는 좌우 스크롤. OFF 인 서브는 흐리게 표시한다. -->
|
||||
<DockPanel Grid.Column="3" VerticalAlignment="Center" LastChildFill="True">
|
||||
<StackPanel DockPanel.Dock="Left" Margin="2, 0" ToolTip="Main">
|
||||
<Image Margin="0" Width="38" Height="38"
|
||||
RenderOptions.BitmapScalingMode="HighQuality"
|
||||
Source="{Binding Thumbnail, Converter={StaticResource bitmapConverter}}"/>
|
||||
<TextBlock Style="{StaticResource styleTextBlockDataGridItem}" FontSize="10" HorizontalAlignment="Center" Text="M"/>
|
||||
</StackPanel>
|
||||
<ScrollViewer MaxWidth="88" HorizontalAlignment="Left"
|
||||
HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled"
|
||||
PanningMode="HorizontalOnly"
|
||||
PreviewMouseWheel="svSubThumbnails_PreviewMouseWheel">
|
||||
<ItemsControl ItemsSource="{Binding SubPatternInfos}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal"/>
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel x:Name="spSubThumbnail" Margin="2, 0">
|
||||
<StackPanel.ToolTip>
|
||||
<TextBlock>
|
||||
<Run Text="Sub"/>
|
||||
<Run Text="{Binding PatternIndex.PatternSubId, Mode=OneWay}"/>
|
||||
<Run Text=" : "/>
|
||||
<Run Text="{Binding IsActivated, Mode=OneWay}"/>
|
||||
</TextBlock>
|
||||
</StackPanel.ToolTip>
|
||||
<Image Margin="0" Width="38" Height="38"
|
||||
RenderOptions.BitmapScalingMode="HighQuality"
|
||||
Source="{Binding Thumbnail, Converter={StaticResource bitmapConverter}}"/>
|
||||
<TextBlock Style="{StaticResource styleTextBlockDataGridItem}" FontSize="10" HorizontalAlignment="Center"
|
||||
Text="{Binding PatternIndex.PatternSubId}"/>
|
||||
</StackPanel>
|
||||
<DataTemplate.Triggers>
|
||||
<DataTrigger Binding="{Binding IsActivated}" Value="False">
|
||||
<Setter TargetName="spSubThumbnail" Property="Opacity" Value="0.35"/>
|
||||
</DataTrigger>
|
||||
</DataTemplate.Triggers>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</ScrollViewer>
|
||||
</DockPanel>
|
||||
<TextBlock Grid.Column="4" Style="{StaticResource styleTextBlockDataGridItem}" FontSize="15" Text="{Binding Description}"/>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
|
||||
@ -161,6 +161,25 @@ namespace VisionUI.Pattern {
|
||||
}
|
||||
}
|
||||
|
||||
// 썸네일 행 안 : Shift + 휠은 좌우 스크롤, 그냥 휠은 목록 위아래 스크롤로 넘긴다.
|
||||
private void svSubThumbnails_PreviewMouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e) {
|
||||
if (!(sender is ScrollViewer scrollViewer)) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
if (System.Windows.Input.Keyboard.Modifiers == System.Windows.Input.ModifierKeys.Shift) {
|
||||
scrollViewer.ScrollToHorizontalOffset(scrollViewer.HorizontalOffset - e.Delta);
|
||||
return;
|
||||
}
|
||||
|
||||
var parent = System.Windows.Media.VisualTreeHelper.GetParent(scrollViewer) as UIElement;
|
||||
parent?.RaiseEvent(new System.Windows.Input.MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta) {
|
||||
RoutedEvent = UIElement.MouseWheelEvent,
|
||||
Source = scrollViewer
|
||||
});
|
||||
}
|
||||
|
||||
private void UpdateVisionRecipes() {
|
||||
_FovRecipe = VisionRecipeManager.GetFovRecipe(_FovInfo);
|
||||
}
|
||||
|
||||
@ -123,6 +123,7 @@ namespace ILSOS_KS.Device
|
||||
PLC_DOOR_INTERLOCK,
|
||||
PLC_EMO_STATUS,
|
||||
PLC_RECIPE_CHANGE_REQ,
|
||||
PLC_RCC_PATTERN_CHANGED_ACK = 0X09, // B2409 : B2506(RCC 패턴 변경) 수신 ACK
|
||||
|
||||
PLC_JIG_LOAD_COMPLETE = 0X0C,
|
||||
/// <summary>
|
||||
@ -156,6 +157,7 @@ namespace ILSOS_KS.Device
|
||||
PC_MANUAL_COMPLETE,
|
||||
PC_LIGHT_ALARM_STATUS,
|
||||
PC_HEAVY_ALARM_STATUS,
|
||||
PC_RCC_PATTERN_CHANGED = 0X06, // B2506 : RCC 패턴 변경 알림 (B2409 ACK 를 받으면 끈다)
|
||||
PC_RECIPE_CHANGE_COMPLETE = 0X08,
|
||||
PC_RECIPE_PARAM_UPLOAD_COMPLETE,
|
||||
PC_WELD_MANUAL_TEST,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
using Aurora;
|
||||
using Aurora;
|
||||
using Aurora.Api;
|
||||
using Aurora.Api.Devices;
|
||||
using Aurora.Api.Manager;
|
||||
@ -156,10 +156,10 @@ namespace ILSOS_KS
|
||||
// () => _plc, PLCMelsecNetConfig.GetDefaultConfig(),
|
||||
// device => new UCPLCDevice() { DataContext = new UCPLCDeviceViewModel(AuroraEnv, _plc) });
|
||||
|
||||
registry.Register(DeviceIds.KSLight1, () => new LightDevice(CommonDeviceIds.Light, eLight.ERI), new LightConfig(),
|
||||
registry.Register(DeviceIds.KSLight1, () => new LightDevice(DeviceIds.KSLight1, eLight.ERI), new LightConfig(),
|
||||
device => new UCLight() { DataContext = new UCLightViewModel(AuroraEnv, DeviceIds.KSLight1) });
|
||||
|
||||
registry.Register(DeviceIds.KSLight2, () => new LightDevice(CommonDeviceIds.Light, eLight.ERI), new LightConfig(),
|
||||
registry.Register(DeviceIds.KSLight2, () => new LightDevice(DeviceIds.KSLight2, eLight.ERI), new LightConfig(),
|
||||
device => new UCLight() { DataContext = new UCLightViewModel(AuroraEnv, DeviceIds.KSLight2) });
|
||||
|
||||
RegisterStreamServices(registry);
|
||||
|
||||
@ -66,9 +66,6 @@
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\_out\x64-Debug\AuroraDeviceCommon.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="AuroraTriggerBoard">
|
||||
<HintPath>..\..\_out\x64-Debug\AuroraTriggerBoard.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="AuroraUIComponent, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\_out\x64-Debug\AuroraUIComponent.dll</HintPath>
|
||||
@ -315,6 +312,10 @@
|
||||
<Project>{1A47B1F3-5BDE-41DF-8F4D-25298AD4F6DE}</Project>
|
||||
<Name>AuroraPLC</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\AuroraDevices\AuroraTriggerBoard\AuroraTriggerBoard.csproj">
|
||||
<Project>{ffbd974d-a4ac-4705-8473-7a62268728f8}</Project>
|
||||
<Name>AuroraTriggerBoard</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\AuroraVision\MilCommon\MilCommon.csproj">
|
||||
<Project>{30FCD6D2-8E66-45E4-93A9-701A1A47DB9E}</Project>
|
||||
<Name>MilCommon</Name>
|
||||
@ -327,6 +328,10 @@
|
||||
<Project>{3db398e6-80b7-4bb9-8be7-caf12979c269}</Project>
|
||||
<Name>VisionCommon</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\AuroraVision\VisionUI\VisionUI.csproj">
|
||||
<Project>{DE586F5E-5BC0-4CAC-9CCB-360473A411B4}</Project>
|
||||
<Name>VisionUI</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\WeldingComponents\LASA\GUI\LASAGUI.csproj">
|
||||
<Project>{e4658ed8-bbb0-4aad-899a-0bad56f2732a}</Project>
|
||||
<Name>LASAGUI</Name>
|
||||
@ -353,13 +358,13 @@ xcopy "$(SolutionDir)\External\Graphviz\*.*" "$(TargetDir)Graphviz\*.*" /s /d /y
|
||||
xcopy "$(SolutionDir)\Packages\MIL\*.dll" "$(TargetDir)" /s /d /y /I
|
||||
xcopy "$(SolutionDir)\External\AuroraVision\_dummyImages" "$(TargetDir)_dummyImages" /s /d /y /I
|
||||
xcopy "$(SolutionDir)\External\AuroraVision\lib" "$(TargetDir)" /s /d /y /I
|
||||
xcopy "$(SolutionDir)\External\LaserScanner\*.dll" "$(TargetDir)" /s /d /y /I
|
||||
xcopy "$(SolutionDir)\External\OpenCvSharp4\*.dll" "$(TargetDir)" /s /d /y /I
|
||||
xcopy "$(SolutionDir)\External\Ajin\*.dll" "$(TargetDir)" /s /d /y /I
|
||||
xcopy "$(SolutionDir)\External\Ajin\*.lib" "$(TargetDir)" /s /d /y /I
|
||||
xcopy "$(SolutionDir)\External\AuroraPLC\*.dll" "$(TargetDir)" /s /d /y /I
|
||||
xcopy "$(SolutionDir)\External\PAIX\*.dll" "$(TargetDir)" /s /d /y /I
|
||||
xcopy "$(SolutionDir)\External\PAIX\*.lib" "$(TargetDir)" /s /d /y /I</PostBuildEvent>
|
||||
xcopy "$(SolutionDir)\External\LaserScanner\*.dll" "$(TargetDir)" /s /d /y
|
||||
xcopy "$(SolutionDir)\External\OpenCvSharp4\*.dll" "$(TargetDir)" /s /d /y
|
||||
xcopy "$(SolutionDir)\External\Ajin\*.dll" "$(TargetDir)" /s /d /y
|
||||
xcopy "$(SolutionDir)\External\Ajin\*.lib" "$(TargetDir)" /s /d /y
|
||||
xcopy "$(SolutionDir)\External\AuroraPLC\*.dll" "$(TargetDir)" /s /d /y
|
||||
xcopy "$(SolutionDir)\External\PAIX\*.dll" "$(TargetDir)" /s /d /y
|
||||
xcopy "$(SolutionDir)\External\PAIX\*.lib" "$(TargetDir)" /s /d /y</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<Import Project="..\..\packages\Microsoft.ML.OnnxRuntime.Managed.1.22.2\build\netstandard2.0\Microsoft.ML.OnnxRuntime.Managed.targets" Condition="Exists('..\..\packages\Microsoft.ML.OnnxRuntime.Managed.1.22.2\build\netstandard2.0\Microsoft.ML.OnnxRuntime.Managed.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
|
||||
@ -49,5 +49,5 @@ using System.Windows;
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.1")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.1")]
|
||||
[assembly: AssemblyVersion("1.0.0.4")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.4")]
|
||||
|
||||
@ -61,6 +61,7 @@ using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
using System.Xml.Linq;
|
||||
using VisionCommon;
|
||||
using VisionUI.Camera;
|
||||
using WeldingCommon;
|
||||
using WeldingCommon.Alarm;
|
||||
using WeldingCommon.Data;
|
||||
@ -263,6 +264,9 @@ namespace ILSOS_KS.Sequences
|
||||
|
||||
bool ksExit = false;
|
||||
|
||||
// RCC 패턴 변경 알림 : 변경이 있으면 B2506 을 켜고, PLC ACK(B2409) 가 오면 끈다.
|
||||
private CancellationTokenSource _RccChangeNoticeCts;
|
||||
|
||||
int[] ResultDataList = new int[4];
|
||||
|
||||
public SeqAutoRunKS()
|
||||
@ -315,7 +319,7 @@ namespace ILSOS_KS.Sequences
|
||||
sb.AddAction(SEQ_GENERATE_WELDING_OBJECT, GenerateWeldingObject);
|
||||
|
||||
//Image Processing
|
||||
sb.AddAction(SEQ_BEFORE_WELD_MOVE_OBJECT, BeforeWeldMoveObject);
|
||||
sb.AddDecision(SEQ_BEFORE_WELD_MOVE_OBJECT, BeforeWeldMoveObject);
|
||||
sb.AddAction(SEQ_AFTER_WELD_CHECK_BEAD, AfterWeldCheckBead);
|
||||
sb.AddDecision(SEQ_CHECK_RCC_MODE, CheckRCCMode);
|
||||
sb.AddDecision(SEQ_CHECK_BEFORE_OR_AFTER, CheckBeforeOrAfter);
|
||||
@ -372,6 +376,9 @@ namespace ILSOS_KS.Sequences
|
||||
> sb[SEQ_SEND_EVENT_SENDER].Send(EVENT_TRIGGER_SAVE_FILE) > sb[SEQ_CHECK_BEFORE_OR_AFTER]
|
||||
> sb[SEQ_BEFORE_WELD_MOVE_OBJECT] > sb[SEQ_READY_SCANNER_LIST]);
|
||||
|
||||
// RCC NG인 경우
|
||||
sb.Flows(sb[SEQ_BEFORE_WELD_MOVE_OBJECT] > sb[SEQ_CHECK_PAGENO]);
|
||||
|
||||
sb.Flows(sb[SEQ_CHECK_RCC_MODE]
|
||||
// RCC FlyingVision
|
||||
> sb[SEQ_SET_SCOUT_FLYING_VISION_SEQ] > sb[SEQ_DO_ID_SCOUT_FLYING_VISION_SEQ] > sb[SEQ_GET_SCOUT_FLYING_VISION_SEQ]
|
||||
@ -534,7 +541,7 @@ namespace ILSOS_KS.Sequences
|
||||
|
||||
}
|
||||
}
|
||||
private SequenceActionResult BeforeWeldMoveObject(SequenceContext context, string id, SequenceActionResult param)
|
||||
private string BeforeWeldMoveObject(SequenceContext context, string id, ICollection<string> branches, SequenceActionResult param)
|
||||
{
|
||||
|
||||
|
||||
@ -560,7 +567,7 @@ namespace ILSOS_KS.Sequences
|
||||
|
||||
// 4 Page 시퀀스 사용으로 spiral 페이지 사용시 RCC 사용안함
|
||||
if (_PageNoRcc % 2 == 1)
|
||||
return SequenceAction.Ok();
|
||||
return SEQ_READY_SCANNER_LIST;
|
||||
|
||||
_SystemParameter = context.GetSetting<SystemParameter>(CommonSettingIds.SystemParameter);
|
||||
var mainPage = WeldingRecipeManager.GetWeldingPage();
|
||||
@ -623,7 +630,17 @@ namespace ILSOS_KS.Sequences
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.W("Pattern is not found.");
|
||||
recipeRequestId = (short)_PLC.ReadDWord((int)eWordOutput.PC_RECIPE_NO, isInput: false).data;
|
||||
if (recipeRequestId == 21) {
|
||||
Log.I(string.Format($"TEST!! Welding : ExecuteList_{_WeldingScannerListNo}"));
|
||||
}
|
||||
else {
|
||||
Log.W("RCC Pattern is not found. NG Process");
|
||||
_PLC.WriteBit((int)eBitOutput.PC_LBAD_RESULT_NG, true);
|
||||
pre_welding = true;
|
||||
context.Wait(1000);
|
||||
return SEQ_CHECK_PAGENO;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -673,7 +690,7 @@ namespace ILSOS_KS.Sequences
|
||||
}
|
||||
}
|
||||
|
||||
return SequenceAction.Ok();
|
||||
return SEQ_READY_SCANNER_LIST;
|
||||
}
|
||||
//private SequenceActionResult AfterWeldCheckBead(SequenceContext context, string id, SequenceActionResult param)
|
||||
//{
|
||||
@ -1316,6 +1333,111 @@ namespace ILSOS_KS.Sequences
|
||||
return SequenceAction.Ok();
|
||||
}
|
||||
|
||||
// RCC 패턴이 바뀌었으면 B2506 을 켜고, PLC ACK(B2409) 를 받았을 때만 알림 완료로 기록한다.
|
||||
// ACK 없이 오토런이 끝나면 B2506 만 끄고 기록하지 않아서 다음 오토런에서 다시 알린다. 오토런은 막지 않는다.
|
||||
private void StartRccPatternChangeNotice(SequenceContext context)
|
||||
{
|
||||
_RccChangeNoticeCts?.Cancel();
|
||||
WriteRccPatternChangedBit(false, "AutoRun Start Reset");
|
||||
|
||||
if (_SystemParameter.SequenceType != eSequenceType.RCC)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string recipeKey;
|
||||
string hash;
|
||||
try
|
||||
{
|
||||
recipeKey = RccPatternChangeRecord.GetCurrentRecipeKey();
|
||||
hash = RccPatternChangeRecord.ComputePatternHash();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.E($"[RccPatternChange] Pattern hash failed : {e.Message}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (RccPatternChangeRecord.IsAcknowledged(recipeKey, hash))
|
||||
{
|
||||
Log.I($"[RccPatternChange] No change. {GetRccPatternBitState()}");
|
||||
return;
|
||||
}
|
||||
|
||||
WriteRccPatternChangedBit(true, "RCC pattern changed -> Wait PLC ACK");
|
||||
|
||||
var cts = new CancellationTokenSource();
|
||||
_RccChangeNoticeCts = cts;
|
||||
Task.Run(() =>
|
||||
{
|
||||
bool acked = false;
|
||||
try
|
||||
{
|
||||
// 이전 ACK 가 켜진 채로 남아 있으면 꺼질 때까지 기다린 뒤, 새로 켜지는 순간(OFF -> ON)만 ACK 로 본다.
|
||||
bool ackArmed = !_PLC.ReadBit((int)eBitInput.PLC_RCC_PATTERN_CHANGED_ACK).data;
|
||||
if (!ackArmed)
|
||||
{
|
||||
Log.I($"[RccPatternChange] PLC ACK is already ON. Wait ACK OFF. {GetRccPatternBitState()}");
|
||||
}
|
||||
|
||||
while (!cts.IsCancellationRequested && !context.Stopped)
|
||||
{
|
||||
bool ack = _PLC.ReadBit((int)eBitInput.PLC_RCC_PATTERN_CHANGED_ACK).data;
|
||||
if (!ackArmed)
|
||||
{
|
||||
if (!ack)
|
||||
{
|
||||
ackArmed = true;
|
||||
Log.I($"[RccPatternChange] PLC ACK OFF. Wait new ACK. {GetRccPatternBitState()}");
|
||||
}
|
||||
}
|
||||
else if (ack)
|
||||
{
|
||||
acked = true;
|
||||
break;
|
||||
}
|
||||
Thread.Sleep(100);
|
||||
}
|
||||
|
||||
if (acked)
|
||||
{
|
||||
RccPatternChangeRecord.Acknowledge(recipeKey, hash);
|
||||
Log.I($"[RccPatternChange] PLC ACK received -> Recorded. {GetRccPatternBitState()}");
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.E($"[RccPatternChange] {e.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
// 오토런을 다시 시작해 새 감시가 돌고 있으면, 새로 켠 비트를 건드리지 않는다.
|
||||
if (ReferenceEquals(_RccChangeNoticeCts, cts))
|
||||
{
|
||||
WriteRccPatternChangedBit(false, acked
|
||||
? "After PLC ACK"
|
||||
: "AutoRun ended without ACK -> Not recorded, notify again next AutoRun");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// B2506 을 쓰고, 쓴 뒤의 B2506 / B2409 상태를 읽어서 로그로 남긴다.
|
||||
private void WriteRccPatternChangedBit(bool value, string reason)
|
||||
{
|
||||
int ret = _PLC.WriteBit((int)eBitOutput.PC_RCC_PATTERN_CHANGED, value);
|
||||
Log.I($"[RccPatternChange] {reason} : ret={ret}, {GetRccPatternBitState()}");
|
||||
}
|
||||
|
||||
// PC_RCC_PATTERN_CHANGED(B2506, PC 출력 블록) 와 PLC_RCC_PATTERN_CHANGED_ACK(B2409, PLC 입력) 를 읽어서 상태 문자열로 만든다.
|
||||
private string GetRccPatternBitState()
|
||||
{
|
||||
var pc = _PLC.ReadBit((int)eBitOutput.PC_RCC_PATTERN_CHANGED, isInput: false);
|
||||
var ack = _PLC.ReadBit((int)eBitInput.PLC_RCC_PATTERN_CHANGED_ACK);
|
||||
return $"PC_RCC_PATTERN_CHANGED(B2506)={(pc.err == 0 ? pc.data.ToString() : $"ReadErr{pc.err}")}, " +
|
||||
$"PLC_RCC_PATTERN_CHANGED_ACK(B2409)={(ack.err == 0 ? ack.data.ToString() : $"ReadErr{ack.err}")}";
|
||||
}
|
||||
|
||||
private bool InitSequenceVariable(SequenceContext context)
|
||||
{
|
||||
_AutoRunStartTime = DateTime.Now;
|
||||
@ -1446,6 +1568,9 @@ namespace ILSOS_KS.Sequences
|
||||
// PLC Interface AutoStatus Start
|
||||
InitAutoRunBit();
|
||||
|
||||
// RCC 패턴 변경 알림 : 해시 계산에 시간이 걸리므로 PC_AUTO_STATUS 를 켠 뒤에 한다.
|
||||
StartRccPatternChangeNotice(context);
|
||||
|
||||
// Laser Initialize
|
||||
_Laser.PilotLaserOff();
|
||||
_Laser.LaserOn();
|
||||
@ -1541,9 +1666,9 @@ namespace ILSOS_KS.Sequences
|
||||
Log.I(string.Format($"[IOInterface] Start AutoRun IO Bit Initialize"));
|
||||
_IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADReadyStatus), false);
|
||||
Log.I(string.Format($"[IOInterface]SET PCLBADReadyStatus False"));
|
||||
_IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADWeldingTrigger), false);
|
||||
WriteLBADDo(eADOAddress.PCLBADWeldingTrigger, false);
|
||||
Log.I(string.Format($"[IOInterface]SET PCLBADWeldingTrigger False"));
|
||||
_IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADWeldingStop), false);
|
||||
WriteLBADDo(eADOAddress.PCLBADWeldingStop, false);
|
||||
Log.I(string.Format($"[IOInterface]SET PCLBADWeldingStop False"));
|
||||
_IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADJudgementCompleteAck), false);
|
||||
Log.I(string.Format($"[IOInterface]SET PCLBADJudgementCompleteAck False"));
|
||||
@ -1789,6 +1914,10 @@ namespace ILSOS_KS.Sequences
|
||||
_PLC.WriteBit((int)eBitOutput.PC_LBAD_RESULT_NG, false);
|
||||
Log.I(string.Format($"[PLCInterface]SET PC_LBAD_RESULT_NG False"));
|
||||
|
||||
// 이전 셀의 LBAD 판정값이 남아있으면 이번 셀에서 판정을 못했을 때 그대로 재전송되므로 여기서 초기화한다.
|
||||
Status.GetProcessingWeldingData().LBAD_Judge = string.Empty;
|
||||
Log.I(string.Format($"[PLCInterface]CLEAR LBAD_Judge"));
|
||||
|
||||
|
||||
_InterfaceStartTime = DateTime.Now;
|
||||
while (!context.Stopped)
|
||||
@ -1973,6 +2102,9 @@ namespace ILSOS_KS.Sequences
|
||||
{
|
||||
|
||||
var resultOutParam = param.Param as SeqScoutFlyingVision_OutParam;
|
||||
|
||||
CameraUcManager.Instance.StartLiveAll(eDisplayType.Machine_A);
|
||||
|
||||
return SequenceAction.Ok();
|
||||
|
||||
//if (pre_welding)
|
||||
@ -2255,6 +2387,18 @@ namespace ILSOS_KS.Sequences
|
||||
return SequenceAction.Ok();
|
||||
}
|
||||
|
||||
// LBAD IO 출력 : 쓰기 반환값(0 = 성공)을 로그로 남기고, 실패하면 에러 로그를 남긴다.
|
||||
private int WriteLBADDo(eADOAddress address, bool value)
|
||||
{
|
||||
int ret = _IO._iOUnit.WriteDoBit(Convert.ToInt32(address), value);
|
||||
Log.I(string.Format($"[IOInterface] WriteDoBit {address}({Convert.ToInt32(address)}) {value} ret={ret}"));
|
||||
if (ret != 0)
|
||||
{
|
||||
Log.E(string.Format($"[IOInterface] WriteDoBit {address}({Convert.ToInt32(address)}) {value} FAIL ret={ret}"));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private SequenceActionResult ExecuteWelding(SequenceContext context, string id, SequenceActionResult param)
|
||||
{
|
||||
Status.SetWorkingPosition(eWorkingPosition.EXECUTING_WELD);
|
||||
@ -2266,7 +2410,7 @@ namespace ILSOS_KS.Sequences
|
||||
|
||||
int recipeNo = _RecipeManager.ActivatedRecipe().Id;
|
||||
|
||||
_IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADWeldingTrigger), true);
|
||||
WriteLBADDo(eADOAddress.PCLBADWeldingTrigger, true);
|
||||
|
||||
//int sendresult = _LBAD.SendCellData(_LotId, _CellId, recipeNo, _ModelNo);
|
||||
if (_BcrID.Contains(""))
|
||||
@ -2332,11 +2476,11 @@ namespace ILSOS_KS.Sequences
|
||||
_PLC.WriteBit((int)eBitOutput.PC_WELD_READY, false);
|
||||
Log.I(string.Format($"[PLCInterface]SET PC_WELD_READY False"));
|
||||
|
||||
_IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADWeldingTrigger), false);
|
||||
WriteLBADDo(eADOAddress.PCLBADWeldingTrigger, false);
|
||||
Log.I(string.Format($"[IOInterface]SET PCWeldingTrigger false"));
|
||||
|
||||
|
||||
_IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADWeldingStop), true);
|
||||
WriteLBADDo(eADOAddress.PCLBADWeldingStop, true);
|
||||
Log.I(string.Format($"[IOInterface]{_PageNo} setp --> SET PCWeldingStop true"));
|
||||
|
||||
return SequenceAction.Ok();
|
||||
@ -2381,7 +2525,7 @@ namespace ILSOS_KS.Sequences
|
||||
//LBAD 결과 받아오는 부분 우선 여기서 추가하여 테스트하고 Sub 시퀀스로 빼자
|
||||
if (_LBAD.IsSimul)
|
||||
{
|
||||
_IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADWeldingStop), false);
|
||||
WriteLBADDo(eADOAddress.PCLBADWeldingStop, false);
|
||||
Log.I(string.Format($"[IOInterface]SET PCLBADWeldingStop false, LBAD is Simul"));
|
||||
}
|
||||
else
|
||||
@ -3173,7 +3317,7 @@ namespace ILSOS_KS.Sequences
|
||||
{
|
||||
Log.I(string.Format($"[IOInterface]Get PLC_WELD_REQEUST True"));
|
||||
|
||||
_IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADWeldingStop), false);
|
||||
WriteLBADDo(eADOAddress.PCLBADWeldingStop, false);
|
||||
Log.I(string.Format($"[IOInterface]LBAD {_PageNoRcc} setp --> SET PCWeldingStop false"));
|
||||
|
||||
bool[] Page = new bool[4];
|
||||
@ -3217,7 +3361,7 @@ namespace ILSOS_KS.Sequences
|
||||
|
||||
WeldingEnd = true;
|
||||
|
||||
_IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADWeldingStop), false);
|
||||
WriteLBADDo(eADOAddress.PCLBADWeldingStop, false);
|
||||
Log.I(string.Format($"[IOInterface]LBAD {_PageNoRcc} setp --> SET PCWeldingStop false"));
|
||||
|
||||
DateTime startTime = DateTime.Now;
|
||||
@ -3564,6 +3708,7 @@ namespace ILSOS_KS.Sequences
|
||||
|
||||
private SequenceActionResult Complete(SequenceContext context, string id, SequenceActionResult param)
|
||||
{
|
||||
_RccChangeNoticeCts?.Cancel();
|
||||
RestoreDeviceStatus();
|
||||
Log.I("AutoRun Complete");
|
||||
|
||||
@ -3583,6 +3728,10 @@ namespace ILSOS_KS.Sequences
|
||||
|
||||
private bool RestoreDeviceStatus()
|
||||
{
|
||||
// RCC 패턴 변경 알림 감시 종료 + B2506 OFF (ACK 전이면 기록하지 않았으므로 다음 오토런에서 다시 알린다)
|
||||
_RccChangeNoticeCts?.Cancel();
|
||||
WriteRccPatternChangedBit(false, "AutoRun Stop");
|
||||
|
||||
//PLC All BIT OFF
|
||||
_PLC.WriteBit((int)eBitOutput.PC_WELD_REQEUST_ACK, false);
|
||||
_PLC.WriteBit((int)eBitOutput.PC_WELD_COMPLETE, false);
|
||||
@ -3599,9 +3748,9 @@ namespace ILSOS_KS.Sequences
|
||||
UpdatePLCMemoryAreaCls((int)eWordOutput.STEP1_Arc1_LowerLimit, (int)eWordOutput.WeldingOK_NG);
|
||||
|
||||
//LBAD IO All BIT OFF
|
||||
_IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADWeldingTrigger), false);
|
||||
WriteLBADDo(eADOAddress.PCLBADWeldingTrigger, false);
|
||||
_IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADReadyStatus), false);
|
||||
_IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADWeldingStop), false);
|
||||
WriteLBADDo(eADOAddress.PCLBADWeldingStop, false);
|
||||
_IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADJudgementCompleteAck), false);
|
||||
Log.I(string.Format("[IOInterface]PC All Bit Off"));
|
||||
|
||||
@ -3658,6 +3807,10 @@ namespace ILSOS_KS.Sequences
|
||||
|
||||
private void OnSeqActionStop()
|
||||
{
|
||||
// RCC 패턴 변경 알림 감시 종료 + B2506 OFF (ACK 전이면 기록하지 않았으므로 다음 오토런에서 다시 알린다)
|
||||
_RccChangeNoticeCts?.Cancel();
|
||||
WriteRccPatternChangedBit(false, "AutoRun Stop");
|
||||
|
||||
//PLC All BIT OFF
|
||||
_PLC.WriteBit((int)eBitOutput.PC_WELD_REQEUST_ACK, false);
|
||||
_PLC.WriteBit((int)eBitOutput.PC_WELD_COMPLETE, false);
|
||||
@ -3674,9 +3827,9 @@ namespace ILSOS_KS.Sequences
|
||||
UpdatePLCMemoryAreaCls((int)eWordOutput.STEP1_Arc1_LowerLimit, (int)eWordOutput.WeldingOK_NG);
|
||||
|
||||
//LBAD IO All BIT OFF
|
||||
_IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADWeldingTrigger), false);
|
||||
WriteLBADDo(eADOAddress.PCLBADWeldingTrigger, false);
|
||||
_IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADReadyStatus), false);
|
||||
_IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADWeldingStop), false);
|
||||
WriteLBADDo(eADOAddress.PCLBADWeldingStop, false);
|
||||
_IO._iOUnit.WriteDoBit(Convert.ToInt32(eADOAddress.PCLBADJudgementCompleteAck), false);
|
||||
Log.I(string.Format("[IOInterface]PC All Bit Off"));
|
||||
|
||||
@ -3737,6 +3890,86 @@ namespace ILSOS_KS.Sequences
|
||||
|
||||
}
|
||||
|
||||
// RCC 패턴 변경 기록 : 패턴 폴더 전체 내용 해시를 레시피별로 DATA_PATH\_config_setting\RccPatternChangeRecord.json 에 기록하고 비교한다.
|
||||
public static class RccPatternChangeRecord
|
||||
{
|
||||
private const string FILE_NAME = "RccPatternChangeRecord.json";
|
||||
private static readonly object _Lock = new object();
|
||||
|
||||
private static string RecordFilePath =>
|
||||
Path.Combine(ApplicationExt.DataPath, "_config_setting", FILE_NAME);
|
||||
|
||||
// 기록 키 : 현재 레시피 폴더 경로
|
||||
public static string GetCurrentRecipeKey()
|
||||
{
|
||||
return Path.GetFullPath(PatternConstants.GetCurrentRecipeFilePath()).TrimEnd('\\').ToLowerInvariant();
|
||||
}
|
||||
|
||||
// 현재 레시피의 패턴 폴더 전체 내용 해시
|
||||
public static string ComputePatternHash()
|
||||
{
|
||||
string patternDir = PatternConstants.GetCurrentRecipePatternRootPath();
|
||||
|
||||
var files = new List<string>();
|
||||
if (Directory.Exists(patternDir))
|
||||
{
|
||||
files.AddRange(Directory.GetFiles(patternDir, "*", SearchOption.AllDirectories));
|
||||
}
|
||||
|
||||
using (var sha = SHA256.Create())
|
||||
{
|
||||
foreach (var file in files.OrderBy(f => f, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
byte[] name = Encoding.UTF8.GetBytes(GetRelativePath(patternDir, file).ToLowerInvariant());
|
||||
sha.TransformBlock(name, 0, name.Length, null, 0);
|
||||
byte[] content = File.ReadAllBytes(file);
|
||||
sha.TransformBlock(content, 0, content.Length, null, 0);
|
||||
}
|
||||
sha.TransformFinalBlock(new byte[0], 0, 0);
|
||||
return BitConverter.ToString(sha.Hash).Replace("-", "");
|
||||
}
|
||||
}
|
||||
|
||||
// 레시피가 이 해시로 알림 완료됐는지
|
||||
public static bool IsAcknowledged(string recipeKey, string hash)
|
||||
{
|
||||
lock (_Lock)
|
||||
{
|
||||
return Load().TryGetValue(recipeKey, out string recorded) && recorded == hash;
|
||||
}
|
||||
}
|
||||
|
||||
// 레시피의 이 해시를 알림 완료로 기록한다.
|
||||
public static void Acknowledge(string recipeKey, string hash)
|
||||
{
|
||||
lock (_Lock)
|
||||
{
|
||||
var records = Load();
|
||||
records[recipeKey] = hash;
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(RecordFilePath));
|
||||
File.WriteAllText(RecordFilePath,
|
||||
Newtonsoft.Json.JsonConvert.SerializeObject(records, Newtonsoft.Json.Formatting.Indented), Encoding.UTF8);
|
||||
}
|
||||
}
|
||||
|
||||
private static Dictionary<string, string> Load()
|
||||
{
|
||||
if (!File.Exists(RecordFilePath))
|
||||
{
|
||||
return new Dictionary<string, string>();
|
||||
}
|
||||
return Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, string>>(File.ReadAllText(RecordFilePath))
|
||||
?? new Dictionary<string, string>();
|
||||
}
|
||||
|
||||
private static string GetRelativePath(string baseDir, string fullPath)
|
||||
{
|
||||
string root = Path.GetFullPath(baseDir).TrimEnd('\\') + "\\";
|
||||
string full = Path.GetFullPath(fullPath);
|
||||
return full.StartsWith(root, StringComparison.OrdinalIgnoreCase) ? full.Substring(root.Length) : full;
|
||||
}
|
||||
}
|
||||
|
||||
public class ScannerObjectInfo
|
||||
{
|
||||
public object Object { get; set; } // Arc, Line, Spline, Dot
|
||||
|
||||
@ -219,13 +219,13 @@ namespace ILSOS_KS.Views
|
||||
NowDateTime = DateTime.Now;
|
||||
|
||||
// Sequence Status check
|
||||
if (_SeqAutoRun.RunState != SequenceRunState.Idle)
|
||||
if (_SeqAutoRun.RunState == SequenceRunState.Idle || _SeqAutoRun.RunState == SequenceRunState.EmergencyStopHandling)
|
||||
{
|
||||
IsSequenceRunning_AutoRun = true;
|
||||
IsSequenceRunning_AutoRun = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
IsSequenceRunning_AutoRun = false;
|
||||
IsSequenceRunning_AutoRun = true;
|
||||
}
|
||||
|
||||
// Alarm Status check
|
||||
|
||||
@ -156,7 +156,7 @@
|
||||
<Border Grid.Row="0" Grid.Column="0" MinHeight="30">
|
||||
<TextBlock Margin="10 0" FontSize="12" Foreground="#FFBBBBBB" FontWeight="Bold" Text="Option Type" VerticalAlignment="Center" HorizontalAlignment="Right"/>
|
||||
</Border>
|
||||
<ComboBox Grid.Row="0" Grid.Column="1" ItemsSource="{Binding OptionList}" SelectedItem="{Binding SelectedOption}" Height="30" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" FontSize="12" Padding="2"/>
|
||||
<ComboBox Grid.Row="0" Grid.Column="1" ItemsSource="{Binding OptionList}" SelectedItem="{Binding SelectedOption}" Height="30" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" FontSize="12" Padding="2" IsEnabled="False"/>
|
||||
</Grid>
|
||||
|
||||
<!-- SelectedOption is SMW-->
|
||||
|
||||
@ -402,7 +402,7 @@ namespace WeldingCommon.Views
|
||||
_Stopwatch = new Stopwatch();
|
||||
|
||||
OptionList = new ObservableCollection<string> { "SMW", "Inzi", "LFW", "KS", "Flangeless" };
|
||||
SelectedOption = OptionList[0];
|
||||
SelectedOption = OptionList[3];
|
||||
|
||||
var pixelResolution = ((_SystemParameter.CameraPixelSize) / _SystemParameter.LensMagnification) / 1000.0;
|
||||
_ObjectGenerator = new ObjectGenerator(pixelResolution);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user