36 changed files with 45893 additions and 85 deletions
Binary file not shown.
@ -0,0 +1,28 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
<PropertyGroup> |
|||
<OutputType>WinExe</OutputType> |
|||
<TargetFramework>net9.0-windows</TargetFramework> |
|||
<UseWPF>true</UseWPF> |
|||
<RootNamespace>Housing</RootNamespace> |
|||
<Nullable>enable</Nullable> |
|||
<ImplicitUsings>enable</ImplicitUsings> |
|||
</PropertyGroup> |
|||
<ItemGroup> |
|||
<PackageReference Include="Microsoft.Data.SqlClient" Version="6.1.3" /> |
|||
<PackageReference Include="System.IO.Ports" Version="9.0.10" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<None Update="Database.ini"> |
|||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> |
|||
</None> |
|||
<None Update="Hardware.ini"> |
|||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> |
|||
</None> |
|||
<None Update="InspectionSettings.ini"> |
|||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> |
|||
</None> |
|||
<None Update="init.sql"> |
|||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> |
|||
</None> |
|||
</ItemGroup> |
|||
</Project> |
|||
|
After Width: | Height: | Size: 144 KiB |
|
After Width: | Height: | Size: 192 B |
|
After Width: | Height: | Size: 9.3 KiB |
@ -0,0 +1,69 @@ |
|||
using System.IO; |
|||
|
|||
namespace Housing.Services; |
|||
|
|||
public sealed class BarcodeScannerSettings |
|||
{ |
|||
public bool Enabled { get; set; } |
|||
public string PortName { get; set; } = "Auto"; |
|||
public int BaudRate { get; set; } = 9600; |
|||
public int ReadTimeout { get; set; } = 500; |
|||
public int IdleCommitMilliseconds { get; set; } = 250; |
|||
public bool DtrEnable { get; set; } = true; |
|||
public bool RtsEnable { get; set; } = true; |
|||
|
|||
public static BarcodeScannerSettings Load(string filePath) |
|||
{ |
|||
if (!File.Exists(filePath)) |
|||
{ |
|||
throw new FileNotFoundException("Hardware.ini file was not found.", filePath); |
|||
} |
|||
|
|||
var values = IniFile.LoadSection(filePath, "BarcodeScanner"); |
|||
return new BarcodeScannerSettings |
|||
{ |
|||
Enabled = GetBool(values, "Enabled", false), |
|||
PortName = GetString(values, "PortName", "Auto"), |
|||
BaudRate = GetInt(values, "BaudRate", 9600), |
|||
ReadTimeout = GetInt(values, "ReadTimeout", 500), |
|||
IdleCommitMilliseconds = GetInt(values, "IdleCommitMilliseconds", 250), |
|||
DtrEnable = GetBool(values, "DtrEnable", true), |
|||
RtsEnable = GetBool(values, "RtsEnable", true) |
|||
}; |
|||
} |
|||
|
|||
public static bool IsAutoPort(string portName) |
|||
{ |
|||
return string.IsNullOrWhiteSpace(portName) || |
|||
string.Equals(portName.Trim(), "Auto", StringComparison.OrdinalIgnoreCase); |
|||
} |
|||
|
|||
private static string GetString(Dictionary<string, string> values, string key, string defaultValue) |
|||
{ |
|||
return values.TryGetValue(key, out var value) && !string.IsNullOrWhiteSpace(value) |
|||
? value.Trim() |
|||
: defaultValue; |
|||
} |
|||
|
|||
private static int GetInt(Dictionary<string, string> values, string key, int defaultValue) |
|||
{ |
|||
return values.TryGetValue(key, out var value) && int.TryParse(value, out var result) |
|||
? result |
|||
: defaultValue; |
|||
} |
|||
|
|||
private static bool GetBool(Dictionary<string, string> values, string key, bool defaultValue) |
|||
{ |
|||
if (!values.TryGetValue(key, out var value) || string.IsNullOrWhiteSpace(value)) |
|||
{ |
|||
return defaultValue; |
|||
} |
|||
|
|||
return value.Trim().ToUpperInvariant() switch |
|||
{ |
|||
"1" or "TRUE" or "YES" or "ON" => true, |
|||
"0" or "FALSE" or "NO" or "OFF" => false, |
|||
_ => defaultValue |
|||
}; |
|||
} |
|||
} |
|||
@ -0,0 +1,426 @@ |
|||
using System.IO.Ports; |
|||
using System.Text; |
|||
using System.Text.RegularExpressions; |
|||
|
|||
namespace Housing.Services; |
|||
|
|||
public sealed class BarcodeScanReceivedEventArgs : EventArgs |
|||
{ |
|||
public BarcodeScanReceivedEventArgs(string portName, string text, bool isConfirmedPort) |
|||
{ |
|||
PortName = portName; |
|||
Text = text; |
|||
IsConfirmedPort = isConfirmedPort; |
|||
} |
|||
|
|||
public string PortName { get; } |
|||
public string Text { get; } |
|||
public bool IsConfirmedPort { get; } |
|||
} |
|||
|
|||
public sealed class SerialBarcodeScanner : IDisposable |
|||
{ |
|||
private readonly BarcodeScannerSettings _settings; |
|||
private readonly HashSet<string> _excludedPortNames; |
|||
private readonly List<PortSession> _sessions = new(); |
|||
private readonly object _sync = new(); |
|||
private bool _disposed; |
|||
private string? _confirmedPortName; |
|||
|
|||
public SerialBarcodeScanner(BarcodeScannerSettings settings, IEnumerable<string> excludedPortNames) |
|||
{ |
|||
_settings = settings; |
|||
_excludedPortNames = excludedPortNames |
|||
.Where(portName => !string.IsNullOrWhiteSpace(portName)) |
|||
.Select(NormalizePortName) |
|||
.ToHashSet(StringComparer.OrdinalIgnoreCase); |
|||
} |
|||
|
|||
public event EventHandler<BarcodeScanReceivedEventArgs>? ScanReceived; |
|||
|
|||
public string? ConfirmedPortName |
|||
{ |
|||
get |
|||
{ |
|||
lock (_sync) |
|||
{ |
|||
return _confirmedPortName; |
|||
} |
|||
} |
|||
} |
|||
|
|||
public void Start() |
|||
{ |
|||
ThrowIfDisposed(); |
|||
|
|||
var candidatePortNames = GetCandidatePortNames(); |
|||
if (candidatePortNames.Length == 0) |
|||
{ |
|||
throw new InvalidOperationException("No available COM ports for the barcode scanner."); |
|||
} |
|||
|
|||
var openErrors = new List<string>(); |
|||
foreach (var portName in candidatePortNames) |
|||
{ |
|||
PortSession? session = null; |
|||
try |
|||
{ |
|||
var port = CreateSerialPort(portName); |
|||
session = new PortSession(port, CommitBufferedScan); |
|||
|
|||
port.DataReceived += SerialPort_DataReceived; |
|||
lock (_sync) |
|||
{ |
|||
_sessions.Add(session); |
|||
} |
|||
|
|||
port.Open(); |
|||
port.DiscardInBuffer(); |
|||
port.DiscardOutBuffer(); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
if (session is not null) |
|||
{ |
|||
lock (_sync) |
|||
{ |
|||
_sessions.Remove(session); |
|||
} |
|||
|
|||
CloseSession(session); |
|||
} |
|||
|
|||
openErrors.Add($"{portName}: {ex.Message}"); |
|||
} |
|||
} |
|||
|
|||
int sessionCount; |
|||
lock (_sync) |
|||
{ |
|||
sessionCount = _sessions.Count; |
|||
} |
|||
|
|||
if (sessionCount == 0) |
|||
{ |
|||
var detail = openErrors.Count == 0 ? string.Empty : $" ({string.Join("; ", openErrors)})"; |
|||
throw new InvalidOperationException($"Could not open a barcode scanner COM port.{detail}"); |
|||
} |
|||
|
|||
if (!BarcodeScannerSettings.IsAutoPort(_settings.PortName) || sessionCount == 1) |
|||
{ |
|||
lock (_sync) |
|||
{ |
|||
_confirmedPortName = _sessions[0].Port.PortName; |
|||
} |
|||
} |
|||
} |
|||
|
|||
public void ConfirmPort(string portName) |
|||
{ |
|||
if (string.IsNullOrWhiteSpace(portName)) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
List<PortSession> sessionsToClose; |
|||
lock (_sync) |
|||
{ |
|||
if (_disposed) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var normalizedPortName = NormalizePortName(portName); |
|||
if (!string.IsNullOrWhiteSpace(_confirmedPortName) && |
|||
!string.Equals(_confirmedPortName, normalizedPortName, StringComparison.OrdinalIgnoreCase)) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var confirmedSession = _sessions.FirstOrDefault(session => |
|||
string.Equals(session.Port.PortName, normalizedPortName, StringComparison.OrdinalIgnoreCase)); |
|||
if (confirmedSession is null) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
_confirmedPortName = confirmedSession.Port.PortName; |
|||
sessionsToClose = _sessions |
|||
.Where(session => !ReferenceEquals(session, confirmedSession)) |
|||
.ToList(); |
|||
|
|||
_sessions.RemoveAll(session => !ReferenceEquals(session, confirmedSession)); |
|||
} |
|||
|
|||
foreach (var session in sessionsToClose) |
|||
{ |
|||
CloseSession(session); |
|||
} |
|||
} |
|||
|
|||
private SerialPort CreateSerialPort(string portName) |
|||
{ |
|||
return new SerialPort(portName, _settings.BaudRate) |
|||
{ |
|||
Encoding = Encoding.ASCII, |
|||
NewLine = "\r\n", |
|||
ReadTimeout = _settings.ReadTimeout, |
|||
WriteTimeout = _settings.ReadTimeout, |
|||
DtrEnable = _settings.DtrEnable, |
|||
RtsEnable = _settings.RtsEnable |
|||
}; |
|||
} |
|||
|
|||
private string[] GetCandidatePortNames() |
|||
{ |
|||
if (!BarcodeScannerSettings.IsAutoPort(_settings.PortName)) |
|||
{ |
|||
return new[] { NormalizePortName(_settings.PortName) }; |
|||
} |
|||
|
|||
return SerialPort.GetPortNames() |
|||
.Select(NormalizePortName) |
|||
.Where(portName => !_excludedPortNames.Contains(portName)) |
|||
.OrderBy(GetPortNumber) |
|||
.ThenBy(portName => portName, StringComparer.OrdinalIgnoreCase) |
|||
.ToArray(); |
|||
} |
|||
|
|||
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) |
|||
{ |
|||
if (sender is not SerialPort port) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
PortSession? session; |
|||
lock (_sync) |
|||
{ |
|||
if (_disposed) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
session = _sessions.FirstOrDefault(item => ReferenceEquals(item.Port, port)); |
|||
} |
|||
|
|||
if (session is null) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
string text; |
|||
try |
|||
{ |
|||
text = port.ReadExisting(); |
|||
} |
|||
catch |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
if (string.IsNullOrEmpty(text)) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var scans = AppendReceivedText(session, text); |
|||
foreach (var scan in scans) |
|||
{ |
|||
PublishScan(session, scan); |
|||
} |
|||
} |
|||
|
|||
private List<string> AppendReceivedText(PortSession session, string text) |
|||
{ |
|||
lock (session.Sync) |
|||
{ |
|||
session.Buffer.Append(text); |
|||
var scans = DrainCompleteScans(session.Buffer); |
|||
|
|||
if (session.Buffer.Length > 0) |
|||
{ |
|||
var delay = Math.Max(50, _settings.IdleCommitMilliseconds); |
|||
session.CommitTimer.Change(delay, Timeout.Infinite); |
|||
} |
|||
else |
|||
{ |
|||
session.CommitTimer.Change(Timeout.Infinite, Timeout.Infinite); |
|||
} |
|||
|
|||
return scans; |
|||
} |
|||
} |
|||
|
|||
private void CommitBufferedScan(PortSession session) |
|||
{ |
|||
string scan; |
|||
lock (session.Sync) |
|||
{ |
|||
scan = NormalizeScanText(session.Buffer.ToString()); |
|||
session.Buffer.Clear(); |
|||
session.CommitTimer.Change(Timeout.Infinite, Timeout.Infinite); |
|||
} |
|||
|
|||
PublishScan(session, scan); |
|||
} |
|||
|
|||
private void PublishScan(PortSession session, string scan) |
|||
{ |
|||
scan = NormalizeScanText(scan); |
|||
if (string.IsNullOrWhiteSpace(scan)) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
bool isConfirmedPort; |
|||
lock (_sync) |
|||
{ |
|||
if (_disposed || !_sessions.Contains(session)) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
isConfirmedPort = string.Equals( |
|||
_confirmedPortName, |
|||
session.Port.PortName, |
|||
StringComparison.OrdinalIgnoreCase); |
|||
} |
|||
|
|||
ScanReceived?.Invoke(this, new BarcodeScanReceivedEventArgs(session.Port.PortName, scan, isConfirmedPort)); |
|||
} |
|||
|
|||
private static List<string> DrainCompleteScans(StringBuilder buffer) |
|||
{ |
|||
var scans = new List<string>(); |
|||
var text = buffer.ToString(); |
|||
var start = 0; |
|||
|
|||
for (var index = 0; index < text.Length; index++) |
|||
{ |
|||
if (text[index] != '\r' && text[index] != '\n') |
|||
{ |
|||
continue; |
|||
} |
|||
|
|||
var line = NormalizeScanText(text[start..index]); |
|||
if (line.Length > 0) |
|||
{ |
|||
scans.Add(line); |
|||
} |
|||
|
|||
if (text[index] == '\r' && index + 1 < text.Length && text[index + 1] == '\n') |
|||
{ |
|||
index++; |
|||
} |
|||
|
|||
start = index + 1; |
|||
} |
|||
|
|||
if (start > 0) |
|||
{ |
|||
buffer.Clear(); |
|||
if (start < text.Length) |
|||
{ |
|||
buffer.Append(text[start..]); |
|||
} |
|||
} |
|||
|
|||
return scans; |
|||
} |
|||
|
|||
private static string NormalizeScanText(string text) |
|||
{ |
|||
if (string.IsNullOrEmpty(text)) |
|||
{ |
|||
return string.Empty; |
|||
} |
|||
|
|||
var builder = new StringBuilder(text.Length); |
|||
foreach (var character in text.Trim()) |
|||
{ |
|||
if (!char.IsControl(character)) |
|||
{ |
|||
builder.Append(character); |
|||
} |
|||
} |
|||
|
|||
return builder.ToString().Trim(); |
|||
} |
|||
|
|||
private static string NormalizePortName(string portName) |
|||
{ |
|||
return portName.Trim().ToUpperInvariant(); |
|||
} |
|||
|
|||
private static int GetPortNumber(string portName) |
|||
{ |
|||
var match = Regex.Match(portName, @"\d+"); |
|||
return match.Success && int.TryParse(match.Value, out var number) |
|||
? number |
|||
: int.MaxValue; |
|||
} |
|||
|
|||
private void ThrowIfDisposed() |
|||
{ |
|||
ObjectDisposedException.ThrowIf(_disposed, this); |
|||
} |
|||
|
|||
private void CloseSession(PortSession session) |
|||
{ |
|||
try |
|||
{ |
|||
session.Port.DataReceived -= SerialPort_DataReceived; |
|||
} |
|||
catch |
|||
{ |
|||
// Best effort during shutdown.
|
|||
} |
|||
|
|||
session.Dispose(); |
|||
} |
|||
|
|||
public void Dispose() |
|||
{ |
|||
List<PortSession> sessionsToClose; |
|||
lock (_sync) |
|||
{ |
|||
if (_disposed) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
_disposed = true; |
|||
sessionsToClose = _sessions.ToList(); |
|||
_sessions.Clear(); |
|||
} |
|||
|
|||
foreach (var session in sessionsToClose) |
|||
{ |
|||
CloseSession(session); |
|||
} |
|||
} |
|||
|
|||
private sealed class PortSession : IDisposable |
|||
{ |
|||
private readonly Action<PortSession> _commitBufferedScan; |
|||
|
|||
public PortSession(SerialPort port, Action<PortSession> commitBufferedScan) |
|||
{ |
|||
Port = port; |
|||
_commitBufferedScan = commitBufferedScan; |
|||
CommitTimer = new Timer(_ => _commitBufferedScan(this), null, Timeout.Infinite, Timeout.Infinite); |
|||
} |
|||
|
|||
public SerialPort Port { get; } |
|||
public StringBuilder Buffer { get; } = new(); |
|||
public object Sync { get; } = new(); |
|||
public Timer CommitTimer { get; } |
|||
|
|||
public void Dispose() |
|||
{ |
|||
CommitTimer.Dispose(); |
|||
Port.Dispose(); |
|||
} |
|||
} |
|||
} |
|||
Binary file not shown.
File diff suppressed because it is too large
@ -0,0 +1,112 @@ |
|||
-- Run this script against the Housing database before running the app. |
|||
-- It creates the login table and login procedures. |
|||
|
|||
IF OBJECT_ID(N'dbo.Operator_Account', N'U') IS NULL |
|||
BEGIN |
|||
CREATE TABLE dbo.Operator_Account |
|||
( |
|||
[Operator] NVARCHAR(10) NOT NULL |
|||
CONSTRAINT PK_Operator_Account PRIMARY KEY, |
|||
[Password] NVARCHAR(50) NOT NULL, |
|||
[CreatedAt] DATETIME2(0) NOT NULL |
|||
CONSTRAINT DF_Operator_Account_CreatedAt DEFAULT (SYSDATETIME()), |
|||
[UpdatedAt] DATETIME2(0) NULL |
|||
); |
|||
END; |
|||
GO |
|||
|
|||
IF COL_LENGTH(N'dbo.Operator_Account', N'IsActive') IS NOT NULL |
|||
BEGIN |
|||
DECLARE @DefaultConstraintName SYSNAME; |
|||
|
|||
SELECT @DefaultConstraintName = dc.name |
|||
FROM sys.default_constraints AS dc |
|||
INNER JOIN sys.columns AS c |
|||
ON c.default_object_id = dc.object_id |
|||
WHERE dc.parent_object_id = OBJECT_ID(N'dbo.Operator_Account', N'U') |
|||
AND c.name = N'IsActive'; |
|||
|
|||
IF @DefaultConstraintName IS NOT NULL |
|||
BEGIN |
|||
EXEC(N'ALTER TABLE dbo.Operator_Account DROP CONSTRAINT [' + @DefaultConstraintName + N']'); |
|||
END; |
|||
|
|||
ALTER TABLE dbo.Operator_Account DROP COLUMN [IsActive]; |
|||
END; |
|||
GO |
|||
|
|||
IF EXISTS (SELECT 1 FROM dbo.Operator_Account WHERE [Operator] = N'su') |
|||
BEGIN |
|||
UPDATE dbo.Operator_Account |
|||
SET |
|||
[Password] = N'su', |
|||
[UpdatedAt] = SYSDATETIME() |
|||
WHERE [Operator] = N'su'; |
|||
END |
|||
ELSE |
|||
BEGIN |
|||
INSERT INTO dbo.Operator_Account |
|||
( |
|||
[Operator], |
|||
[Password] |
|||
) |
|||
VALUES |
|||
( |
|||
N'su', |
|||
N'su' |
|||
); |
|||
END; |
|||
GO |
|||
|
|||
CREATE OR ALTER PROCEDURE dbo.CheckOperator |
|||
@Operator NVARCHAR(10), |
|||
@Password NVARCHAR(50) |
|||
AS |
|||
BEGIN |
|||
SET NOCOUNT ON; |
|||
|
|||
SELECT CAST( |
|||
CASE |
|||
WHEN EXISTS |
|||
( |
|||
SELECT 1 |
|||
FROM dbo.Operator_Account |
|||
WHERE [Operator] = @Operator |
|||
AND [Password] = @Password |
|||
) |
|||
THEN 1 |
|||
ELSE 0 |
|||
END AS BIT) AS IsValid; |
|||
END; |
|||
GO |
|||
|
|||
CREATE OR ALTER PROCEDURE dbo.SaveOperator |
|||
@Operator NVARCHAR(10), |
|||
@Password NVARCHAR(50) |
|||
AS |
|||
BEGIN |
|||
SET NOCOUNT ON; |
|||
|
|||
IF EXISTS (SELECT 1 FROM dbo.Operator_Account WHERE [Operator] = @Operator) |
|||
BEGIN |
|||
UPDATE dbo.Operator_Account |
|||
SET |
|||
[Password] = @Password, |
|||
[UpdatedAt] = SYSDATETIME() |
|||
WHERE [Operator] = @Operator; |
|||
END |
|||
ELSE |
|||
BEGIN |
|||
INSERT INTO dbo.Operator_Account |
|||
( |
|||
[Operator], |
|||
[Password] |
|||
) |
|||
VALUES |
|||
( |
|||
@Operator, |
|||
@Password |
|||
); |
|||
END; |
|||
END; |
|||
GO |
|||
Binary file not shown.
@ -0,0 +1,12 @@ |
|||
[Database] |
|||
IP=127.0.0.1 |
|||
Database=Housing |
|||
DbId=sa |
|||
DbPw=your_password |
|||
Encrypt=True |
|||
TrustServerCertificate=True |
|||
Timeout=5 |
|||
|
|||
[Login] |
|||
Procedure=dbo.CheckOperator |
|||
OfflinePreview=true |
|||
@ -0,0 +1,78 @@ |
|||
[Board] |
|||
PortName=COM5 |
|||
BaudRate=115200 |
|||
ReadTimeout=5000 |
|||
PreConnectCommand=x00o |
|||
ConnectCommand=x00c_001101:owt28006727ea97c7801 |
|||
ReadIdCommand=x00c_001101:ow2800326003e |
|||
PostReadIdCommand=x00o |
|||
CalDefaultCommand=x00c_001001:owt28006727ea97c7801 |
|||
EndToken=<end> |
|||
DtrEnable=false |
|||
RtsEnable=false |
|||
|
|||
[BarcodeScanner] |
|||
Enabled=true |
|||
PortName=Auto |
|||
BaudRate=9600 |
|||
ReadTimeout=500 |
|||
IdleCommitMilliseconds=250 |
|||
DtrEnable=true |
|||
RtsEnable=true |
|||
|
|||
[StartSignal] |
|||
; USB-6501 |
|||
Enabled=true |
|||
Connection=Ni6501 |
|||
PhysicalChannel=Dev1/port0/line0 |
|||
ActiveState=High |
|||
PollIntervalMilliseconds=50 |
|||
TimeoutMilliseconds=30000 |
|||
PostSignalDelayMilliseconds=2000 |
|||
RequireInactiveBeforeStart=true |
|||
|
|||
[Equipment] |
|||
; V 출력: Keysight 34465A DMM 값 |
|||
; A 출력: Keysight E36233A Power Supply CH1 Current 값 |
|||
; USB 장비는 Keysight Connection Expert 또는 NI MAX에서 보이는 VISA 주소를 Resource |
|||
Timeout=5000 |
|||
SettleMilliseconds=300 |
|||
PreBoardCommand=VOLT 5, (@2);OUTP ON, (@2) |
|||
PreBoardDelayMilliseconds=2000 |
|||
LogoutCommand=OUTP OFF, (@1);OUTP OFF, (@2) |
|||
|
|||
; 34465A DMM |
|||
VoltageConnection=LAN |
|||
VoltageResource= |
|||
VoltageIdnMatch=34465A |
|||
VoltageHost=192.168.200.3 |
|||
VoltagePort=5025 |
|||
VoltageSetupCommand= |
|||
VoltageReadCommand=MEAS:VOLT:DC? |
|||
|
|||
; E36233A Power Supply |
|||
CurrentConnection=LAN |
|||
CurrentResource= |
|||
CurrentIdnMatch=E36233A |
|||
; Change this to the E36233A LAN IP if the instrument uses a different address. |
|||
CurrentHost=192.168.200.111 |
|||
CurrentPort=5025 |
|||
CurrentPortName= |
|||
CurrentBaudRate=9600 |
|||
CurrentTerminator=LF |
|||
CurrentSetupCommand=OUTP ON, (@1) |
|||
CurrentCleanupCommand=OUTP OFF, (@1) |
|||
CurrentReadCommand=MEAS:CURR? (@1) |
|||
|
|||
; COM 포트로 잡히는 장비 예시: |
|||
; VoltageConnection=Serial |
|||
; VoltagePortName=Auto |
|||
; VoltageBaudRate=115200 |
|||
|
|||
; LAN 장비 예시: |
|||
; VoltageConnection=Tcp |
|||
; VoltageHost=192.168.0.10 |
|||
; VoltagePort=5025 |
|||
|
|||
; E36233A 파워서플라이에서 CH1 전압까지 읽고 싶을 때 예시: |
|||
; VoltageReadCommand=MEAS:VOLT? CH1 |
|||
Binary file not shown.
Binary file not shown.
@ -0,0 +1,5 @@ |
|||
[Judgement] |
|||
VMin=0.00 |
|||
VMax=9.99 |
|||
AMin=0.00 |
|||
AMax=9.99 |
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,112 @@ |
|||
-- Run this script against the Housing database before running the app. |
|||
-- It creates the login table and login procedures. |
|||
|
|||
IF OBJECT_ID(N'dbo.Operator_Account', N'U') IS NULL |
|||
BEGIN |
|||
CREATE TABLE dbo.Operator_Account |
|||
( |
|||
[Operator] NVARCHAR(10) NOT NULL |
|||
CONSTRAINT PK_Operator_Account PRIMARY KEY, |
|||
[Password] NVARCHAR(50) NOT NULL, |
|||
[CreatedAt] DATETIME2(0) NOT NULL |
|||
CONSTRAINT DF_Operator_Account_CreatedAt DEFAULT (SYSDATETIME()), |
|||
[UpdatedAt] DATETIME2(0) NULL |
|||
); |
|||
END; |
|||
GO |
|||
|
|||
IF COL_LENGTH(N'dbo.Operator_Account', N'IsActive') IS NOT NULL |
|||
BEGIN |
|||
DECLARE @DefaultConstraintName SYSNAME; |
|||
|
|||
SELECT @DefaultConstraintName = dc.name |
|||
FROM sys.default_constraints AS dc |
|||
INNER JOIN sys.columns AS c |
|||
ON c.default_object_id = dc.object_id |
|||
WHERE dc.parent_object_id = OBJECT_ID(N'dbo.Operator_Account', N'U') |
|||
AND c.name = N'IsActive'; |
|||
|
|||
IF @DefaultConstraintName IS NOT NULL |
|||
BEGIN |
|||
EXEC(N'ALTER TABLE dbo.Operator_Account DROP CONSTRAINT [' + @DefaultConstraintName + N']'); |
|||
END; |
|||
|
|||
ALTER TABLE dbo.Operator_Account DROP COLUMN [IsActive]; |
|||
END; |
|||
GO |
|||
|
|||
IF EXISTS (SELECT 1 FROM dbo.Operator_Account WHERE [Operator] = N'su') |
|||
BEGIN |
|||
UPDATE dbo.Operator_Account |
|||
SET |
|||
[Password] = N'su', |
|||
[UpdatedAt] = SYSDATETIME() |
|||
WHERE [Operator] = N'su'; |
|||
END |
|||
ELSE |
|||
BEGIN |
|||
INSERT INTO dbo.Operator_Account |
|||
( |
|||
[Operator], |
|||
[Password] |
|||
) |
|||
VALUES |
|||
( |
|||
N'su', |
|||
N'su' |
|||
); |
|||
END; |
|||
GO |
|||
|
|||
CREATE OR ALTER PROCEDURE dbo.CheckOperator |
|||
@Operator NVARCHAR(10), |
|||
@Password NVARCHAR(50) |
|||
AS |
|||
BEGIN |
|||
SET NOCOUNT ON; |
|||
|
|||
SELECT CAST( |
|||
CASE |
|||
WHEN EXISTS |
|||
( |
|||
SELECT 1 |
|||
FROM dbo.Operator_Account |
|||
WHERE [Operator] = @Operator |
|||
AND [Password] = @Password |
|||
) |
|||
THEN 1 |
|||
ELSE 0 |
|||
END AS BIT) AS IsValid; |
|||
END; |
|||
GO |
|||
|
|||
CREATE OR ALTER PROCEDURE dbo.SaveOperator |
|||
@Operator NVARCHAR(10), |
|||
@Password NVARCHAR(50) |
|||
AS |
|||
BEGIN |
|||
SET NOCOUNT ON; |
|||
|
|||
IF EXISTS (SELECT 1 FROM dbo.Operator_Account WHERE [Operator] = @Operator) |
|||
BEGIN |
|||
UPDATE dbo.Operator_Account |
|||
SET |
|||
[Password] = @Password, |
|||
[UpdatedAt] = SYSDATETIME() |
|||
WHERE [Operator] = @Operator; |
|||
END |
|||
ELSE |
|||
BEGIN |
|||
INSERT INTO dbo.Operator_Account |
|||
( |
|||
[Operator], |
|||
[Password] |
|||
) |
|||
VALUES |
|||
( |
|||
@Operator, |
|||
@Password |
|||
); |
|||
END; |
|||
END; |
|||
GO |
|||
Binary file not shown.
Binary file not shown.
Loading…
Reference in new issue