mirror of
https://github.com/OpenLogics/MewtocolNet.git
synced 2025-12-06 03:01:24 +00:00
261 lines
6.7 KiB
C#
261 lines
6.7 KiB
C#
using MewtocolNet.Logging;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.IO.Ports;
|
|
using System.Linq;
|
|
using System.Net.Sockets;
|
|
using System.Net;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Threading;
|
|
|
|
namespace MewtocolNet {
|
|
|
|
public class MewtocolInterfaceSerial : MewtocolInterface, IPlcSerial {
|
|
|
|
private bool autoSerial;
|
|
|
|
//serial config
|
|
public string PortName { get; private set; }
|
|
public int SerialBaudRate { get; private set; }
|
|
public int SerialDataBits { get; private set; }
|
|
public Parity SerialParity { get; private set; }
|
|
public StopBits SerialStopBits { get; private set; }
|
|
|
|
//Serial
|
|
internal SerialPort serialClient;
|
|
|
|
internal MewtocolInterfaceSerial () : base() { }
|
|
|
|
|
|
/// <inheritdoc/>
|
|
public IPlcSerial WithPoller () {
|
|
|
|
usePoller = true;
|
|
return this;
|
|
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public override string GetConnectionInfo() {
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
sb.Append($"{PortName}, ");
|
|
sb.Append($"{SerialBaudRate}, ");
|
|
sb.Append($"{SerialDataBits} ");
|
|
|
|
sb.Append($"{SerialParity.ToString().Substring(0, 1)} ");
|
|
|
|
switch (SerialStopBits) {
|
|
case StopBits.None:
|
|
sb.Append("0");
|
|
break;
|
|
case StopBits.One:
|
|
sb.Append("1");
|
|
break;
|
|
case StopBits.Two:
|
|
sb.Append("2");
|
|
break;
|
|
case StopBits.OnePointFive:
|
|
sb.Append("1.5");
|
|
break;
|
|
}
|
|
|
|
return sb.ToString();
|
|
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public void ConfigureConnection (string _portName, int _baudRate = 19200, int _dataBits = 8, Parity _parity = Parity.Odd, StopBits _stopBits = StopBits.One, int _station = 1) {
|
|
|
|
PortName = _portName;
|
|
SerialBaudRate = _baudRate;
|
|
SerialDataBits = _dataBits;
|
|
SerialParity = _parity;
|
|
SerialStopBits = _stopBits;
|
|
stationNumber = _station;
|
|
|
|
OnSerialPropsChanged();
|
|
Disconnect();
|
|
|
|
}
|
|
|
|
internal void ConfigureConnectionAuto () {
|
|
|
|
autoSerial = true;
|
|
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public override async Task ConnectAsync () {
|
|
|
|
try {
|
|
|
|
PLCInfo gotInfo = null;
|
|
|
|
if(autoSerial) {
|
|
|
|
gotInfo = await TryConnectAsyncMulti();
|
|
|
|
} else {
|
|
|
|
gotInfo = await TryConnectAsyncSingle(PortName, SerialBaudRate, SerialDataBits, SerialParity, SerialStopBits);
|
|
|
|
}
|
|
|
|
if(gotInfo != null) {
|
|
|
|
OnConnected(gotInfo);
|
|
|
|
} else {
|
|
|
|
Logger.Log("Initial connection failed", LogLevel.Info, this);
|
|
OnMajorSocketExceptionWhileConnecting();
|
|
|
|
}
|
|
|
|
await Task.CompletedTask;
|
|
|
|
} catch (SocketException) {
|
|
|
|
OnMajorSocketExceptionWhileConnecting();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private async Task<PLCInfo> TryConnectAsyncMulti () {
|
|
|
|
var baudRates = Enum.GetValues(typeof(BaudRate)).Cast<BaudRate>();
|
|
|
|
//ordered by most commonly used
|
|
baudRates = new List<BaudRate> {
|
|
//most common 3
|
|
BaudRate._19200,
|
|
BaudRate._115200,
|
|
BaudRate._9600,
|
|
//others
|
|
BaudRate._1200,
|
|
BaudRate._2400,
|
|
BaudRate._4800,
|
|
BaudRate._38400,
|
|
BaudRate._57600,
|
|
BaudRate._230400,
|
|
};
|
|
|
|
var dataBits = Enum.GetValues(typeof(DataBits)).Cast<DataBits>();
|
|
var parities = new List<Parity>() { Parity.None, Parity.Odd, Parity.Even, Parity.Mark };
|
|
var stopBits = new List<StopBits> { StopBits.One, StopBits.Two };
|
|
|
|
foreach (var baud in baudRates) {
|
|
|
|
foreach (var databit in dataBits) {
|
|
|
|
foreach (var parity in parities) {
|
|
|
|
foreach (var stopBit in stopBits) {
|
|
|
|
var res = await TryConnectAsyncSingle(PortName, (int)baud, (int)databit, parity, stopBit);
|
|
if(res != null) return res;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
private async Task<PLCInfo> TryConnectAsyncSingle (string port, int baud, int dbits, Parity par, StopBits sbits) {
|
|
|
|
try {
|
|
|
|
serialClient = new SerialPort() {
|
|
PortName = port,
|
|
BaudRate = baud,
|
|
DataBits = dbits,
|
|
Parity = par,
|
|
StopBits = sbits,
|
|
ReadTimeout = 100,
|
|
Handshake = Handshake.None
|
|
};
|
|
|
|
PortName = port;
|
|
SerialBaudRate = baud;
|
|
SerialDataBits = dbits;
|
|
SerialParity = par;
|
|
SerialStopBits = sbits;
|
|
OnSerialPropsChanged();
|
|
|
|
serialClient.Open();
|
|
|
|
if (!serialClient.IsOpen) {
|
|
|
|
Logger.Log($"Failed to open [SERIAL]: {GetConnectionInfo()}", LogLevel.Verbose, this);
|
|
return null;
|
|
|
|
}
|
|
|
|
stream = serialClient.BaseStream;
|
|
|
|
Logger.Log($"Opened [SERIAL]: {GetConnectionInfo()}", LogLevel.Verbose, this);
|
|
|
|
var plcinf = await GetPLCInfoAsync(100);
|
|
|
|
if (plcinf == null) CloseClient();
|
|
|
|
return plcinf;
|
|
|
|
} catch (UnauthorizedAccessException) {
|
|
|
|
Logger.Log($"The port {serialClient.PortName} is currently in use. Close all accessing applications first", LogLevel.Error, this);
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private void CloseClient () {
|
|
|
|
if(serialClient.IsOpen) {
|
|
|
|
serialClient.Close();
|
|
Logger.Log($"Closed [SERIAL]", LogLevel.Verbose, this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private protected override void OnDisconnect() {
|
|
|
|
if (IsConnected) {
|
|
|
|
base.OnDisconnect();
|
|
|
|
CloseClient();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private void OnSerialPropsChanged () {
|
|
|
|
OnPropChange(nameof(PortName));
|
|
OnPropChange(nameof(SerialBaudRate));
|
|
OnPropChange(nameof(SerialDataBits));
|
|
OnPropChange(nameof(SerialParity));
|
|
OnPropChange(nameof(SerialStopBits));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|