|
@@ -11,6 +11,7 @@ namespace xicheji
|
|
private readonly Config config;
|
|
private readonly Config config;
|
|
private readonly List<WashRecord> washRecords = new();
|
|
private readonly List<WashRecord> washRecords = new();
|
|
private DateTime lastReceiveTime = DateTime.MinValue;
|
|
private DateTime lastReceiveTime = DateTime.MinValue;
|
|
|
|
+ private byte[] currentDataBlock;
|
|
private Plc? plc = null;
|
|
private Plc? plc = null;
|
|
private HikApi? hikApi = null;
|
|
private HikApi? hikApi = null;
|
|
|
|
|
|
@@ -43,6 +44,7 @@ namespace xicheji
|
|
ConnectPLC();
|
|
ConnectPLC();
|
|
//ConnectCamera();
|
|
//ConnectCamera();
|
|
|
|
|
|
|
|
+ receivePLCTimer.Interval = config.PLCReceiveInterval * 1000;
|
|
receivePLCTimer.Enabled = true;
|
|
receivePLCTimer.Enabled = true;
|
|
uploadTimer.Enabled = true;
|
|
uploadTimer.Enabled = true;
|
|
}
|
|
}
|
|
@@ -93,8 +95,7 @@ namespace xicheji
|
|
|
|
|
|
private void ReadPLCData()
|
|
private void ReadPLCData()
|
|
{
|
|
{
|
|
- lblWashCount.Text = ReadPLCString("洗车次数");
|
|
|
|
- return;
|
|
|
|
|
|
+ currentDataBlock = plc!.ReadBytes(DataType.DataBlock, 1, 0, 100);
|
|
|
|
|
|
var time = new DateTime(
|
|
var time = new DateTime(
|
|
DateTime.Now.Year,
|
|
DateTime.Now.Year,
|
|
@@ -162,31 +163,52 @@ namespace xicheji
|
|
private string ReadPLCString(string name)
|
|
private string ReadPLCString(string name)
|
|
{
|
|
{
|
|
var variable = ConfigHelper.FindVariable(name);
|
|
var variable = ConfigHelper.FindVariable(name);
|
|
- if (plc == null || variable == null)
|
|
|
|
|
|
+ if (variable == null)
|
|
return string.Empty;
|
|
return string.Empty;
|
|
|
|
|
|
- var value = plc.Read(variable.Key);
|
|
|
|
- return $"{value} {variable.Desc}";
|
|
|
|
|
|
+ Parse(variable.Key, out _, out _, out var varType, out var address, out var bitNumber);
|
|
|
|
+ if (varType == VarType.DWord)
|
|
|
|
+ {
|
|
|
|
+ var value = S7.Net.Types.DWord.FromByteArray(currentDataBlock.Take(new Range(address, address + 4)).ToArray());
|
|
|
|
+ return $"{value} {variable.Desc}";
|
|
|
|
+ }
|
|
|
|
+ else if (varType == VarType.Word)
|
|
|
|
+ {
|
|
|
|
+ var value = S7.Net.Types.Word.FromByteArray(currentDataBlock.Take(new Range(address, address + 2)).ToArray());
|
|
|
|
+ return $"{value} {variable.Desc}";
|
|
|
|
+ }
|
|
|
|
+ return string.Empty;
|
|
}
|
|
}
|
|
|
|
|
|
private int ReadPLCInt(string name)
|
|
private int ReadPLCInt(string name)
|
|
{
|
|
{
|
|
var variable = ConfigHelper.FindVariable(name);
|
|
var variable = ConfigHelper.FindVariable(name);
|
|
- if (plc == null || variable == null)
|
|
|
|
|
|
+ if (variable == null)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
- var value = plc.Read(variable.Key);
|
|
|
|
- return int.Parse(value?.ToString() ?? "0");
|
|
|
|
|
|
+ Parse(variable.Key, out var dataType, out var dbNumber, out var varType, out var address, out var bitNumber);
|
|
|
|
+ if (varType == VarType.DWord)
|
|
|
|
+ {
|
|
|
|
+ var value = S7.Net.Types.DWord.FromByteArray(currentDataBlock.Take(new Range(address, address + 4)).ToArray());
|
|
|
|
+ return (int)value;
|
|
|
|
+ }
|
|
|
|
+ else if (varType == VarType.Word)
|
|
|
|
+ {
|
|
|
|
+ var value = S7.Net.Types.Word.FromByteArray(currentDataBlock.Take(new Range(address, address + 2)).ToArray());
|
|
|
|
+ return value;
|
|
|
|
+ }
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
private bool ReadPLCBool(string name)
|
|
private bool ReadPLCBool(string name)
|
|
{
|
|
{
|
|
var variable = ConfigHelper.FindVariable(name);
|
|
var variable = ConfigHelper.FindVariable(name);
|
|
- if (plc == null || variable == null)
|
|
|
|
|
|
+ if (variable == null)
|
|
return false;
|
|
return false;
|
|
|
|
|
|
- var value = plc.Read(variable.Key);
|
|
|
|
- return value?.ToString()?.ToLower() == "true";
|
|
|
|
|
|
+ Parse(variable.Key, out _, out _, out _, out var address, out var bitNumber);
|
|
|
|
+ var value = S7.Net.Types.Boolean.GetValue(currentDataBlock[address], bitNumber);
|
|
|
|
+ return value;
|
|
}
|
|
}
|
|
|
|
|
|
private void uploadTimer_Tick(object sender, EventArgs e)
|
|
private void uploadTimer_Tick(object sender, EventArgs e)
|
|
@@ -216,7 +238,7 @@ namespace xicheji
|
|
plc = new Plc(config.PLCType, config.PLCIP, int.Parse(config.PLCPort), 0, 1);
|
|
plc = new Plc(config.PLCType, config.PLCIP, int.Parse(config.PLCPort), 0, 1);
|
|
plc.Open();
|
|
plc.Open();
|
|
|
|
|
|
- if (plc == null || !plc.IsConnected)
|
|
|
|
|
|
+ if (!plc.IsConnected)
|
|
{
|
|
{
|
|
MessageBox.Show("PLC连接失败!");
|
|
MessageBox.Show("PLC连接失败!");
|
|
return;
|
|
return;
|
|
@@ -251,5 +273,169 @@ namespace xicheji
|
|
this.Text = now.ToString();
|
|
this.Text = now.ToString();
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ public static void Parse(string input, out DataType dataType, out int dbNumber, out VarType varType, out int address, out int bitNumber)
|
|
|
|
+ {
|
|
|
|
+ bitNumber = -1;
|
|
|
|
+ dbNumber = 0;
|
|
|
|
+
|
|
|
|
+ switch (input.Substring(0, 2))
|
|
|
|
+ {
|
|
|
|
+ case "DB":
|
|
|
|
+ string[] strings = input.Split(new char[] { '.' });
|
|
|
|
+ if (strings.Length < 2)
|
|
|
|
+ throw new InvalidAddressException("To few periods for DB address");
|
|
|
|
+
|
|
|
|
+ dataType = DataType.DataBlock;
|
|
|
|
+ dbNumber = int.Parse(strings[0].Substring(2));
|
|
|
|
+ address = int.Parse(strings[1].Substring(3));
|
|
|
|
+
|
|
|
|
+ string dbType = strings[1].Substring(0, 3);
|
|
|
|
+ switch (dbType)
|
|
|
|
+ {
|
|
|
|
+ case "DBB":
|
|
|
|
+ varType = VarType.Byte;
|
|
|
|
+ return;
|
|
|
|
+ case "DBW":
|
|
|
|
+ varType = VarType.Word;
|
|
|
|
+ return;
|
|
|
|
+ case "DBD":
|
|
|
|
+ varType = VarType.DWord;
|
|
|
|
+ return;
|
|
|
|
+ case "DBX":
|
|
|
|
+ bitNumber = int.Parse(strings[2]);
|
|
|
|
+ if (bitNumber > 7)
|
|
|
|
+ throw new InvalidAddressException("Bit can only be 0-7");
|
|
|
|
+ varType = VarType.Bit;
|
|
|
|
+ return;
|
|
|
|
+ default:
|
|
|
|
+ throw new InvalidAddressException();
|
|
|
|
+ }
|
|
|
|
+ case "IB":
|
|
|
|
+ case "EB":
|
|
|
|
+ // Input byte
|
|
|
|
+ dataType = DataType.Input;
|
|
|
|
+ dbNumber = 0;
|
|
|
|
+ address = int.Parse(input.Substring(2));
|
|
|
|
+ varType = VarType.Byte;
|
|
|
|
+ return;
|
|
|
|
+ case "IW":
|
|
|
|
+ case "EW":
|
|
|
|
+ // Input word
|
|
|
|
+ dataType = DataType.Input;
|
|
|
|
+ dbNumber = 0;
|
|
|
|
+ address = int.Parse(input.Substring(2));
|
|
|
|
+ varType = VarType.Word;
|
|
|
|
+ return;
|
|
|
|
+ case "ID":
|
|
|
|
+ case "ED":
|
|
|
|
+ // Input double-word
|
|
|
|
+ dataType = DataType.Input;
|
|
|
|
+ dbNumber = 0;
|
|
|
|
+ address = int.Parse(input.Substring(2));
|
|
|
|
+ varType = VarType.DWord;
|
|
|
|
+ return;
|
|
|
|
+ case "QB":
|
|
|
|
+ case "AB":
|
|
|
|
+ case "OB":
|
|
|
|
+ // Output byte
|
|
|
|
+ dataType = DataType.Output;
|
|
|
|
+ dbNumber = 0;
|
|
|
|
+ address = int.Parse(input.Substring(2));
|
|
|
|
+ varType = VarType.Byte;
|
|
|
|
+ return;
|
|
|
|
+ case "QW":
|
|
|
|
+ case "AW":
|
|
|
|
+ case "OW":
|
|
|
|
+ // Output word
|
|
|
|
+ dataType = DataType.Output;
|
|
|
|
+ dbNumber = 0;
|
|
|
|
+ address = int.Parse(input.Substring(2));
|
|
|
|
+ varType = VarType.Word;
|
|
|
|
+ return;
|
|
|
|
+ case "QD":
|
|
|
|
+ case "AD":
|
|
|
|
+ case "OD":
|
|
|
|
+ // Output double-word
|
|
|
|
+ dataType = DataType.Output;
|
|
|
|
+ dbNumber = 0;
|
|
|
|
+ address = int.Parse(input.Substring(2));
|
|
|
|
+ varType = VarType.DWord;
|
|
|
|
+ return;
|
|
|
|
+ case "MB":
|
|
|
|
+ // Memory byte
|
|
|
|
+ dataType = DataType.Memory;
|
|
|
|
+ dbNumber = 0;
|
|
|
|
+ address = int.Parse(input.Substring(2));
|
|
|
|
+ varType = VarType.Byte;
|
|
|
|
+ return;
|
|
|
|
+ case "MW":
|
|
|
|
+ // Memory word
|
|
|
|
+ dataType = DataType.Memory;
|
|
|
|
+ dbNumber = 0;
|
|
|
|
+ address = int.Parse(input.Substring(2));
|
|
|
|
+ varType = VarType.Word;
|
|
|
|
+ return;
|
|
|
|
+ case "MD":
|
|
|
|
+ // Memory double-word
|
|
|
|
+ dataType = DataType.Memory;
|
|
|
|
+ dbNumber = 0;
|
|
|
|
+ address = int.Parse(input.Substring(2));
|
|
|
|
+ varType = VarType.DWord;
|
|
|
|
+ return;
|
|
|
|
+ default:
|
|
|
|
+ switch (input.Substring(0, 1))
|
|
|
|
+ {
|
|
|
|
+ case "E":
|
|
|
|
+ case "I":
|
|
|
|
+ // Input
|
|
|
|
+ dataType = DataType.Input;
|
|
|
|
+ varType = VarType.Bit;
|
|
|
|
+ break;
|
|
|
|
+ case "Q":
|
|
|
|
+ case "A":
|
|
|
|
+ case "O":
|
|
|
|
+ // Output
|
|
|
|
+ dataType = DataType.Output;
|
|
|
|
+ varType = VarType.Bit;
|
|
|
|
+ break;
|
|
|
|
+ case "M":
|
|
|
|
+ // Memory
|
|
|
|
+ dataType = DataType.Memory;
|
|
|
|
+ varType = VarType.Bit;
|
|
|
|
+ break;
|
|
|
|
+ case "T":
|
|
|
|
+ // Timer
|
|
|
|
+ dataType = DataType.Timer;
|
|
|
|
+ dbNumber = 0;
|
|
|
|
+ address = int.Parse(input.Substring(1));
|
|
|
|
+ varType = VarType.Timer;
|
|
|
|
+ return;
|
|
|
|
+ case "Z":
|
|
|
|
+ case "C":
|
|
|
|
+ // Counter
|
|
|
|
+ dataType = DataType.Counter;
|
|
|
|
+ dbNumber = 0;
|
|
|
|
+ address = int.Parse(input.Substring(1));
|
|
|
|
+ varType = VarType.Counter;
|
|
|
|
+ return;
|
|
|
|
+ default:
|
|
|
|
+ throw new InvalidAddressException(string.Format("{0} is not a valid address", input.Substring(0, 1)));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ string txt2 = input.Substring(1);
|
|
|
|
+ if (txt2.IndexOf(".") == -1)
|
|
|
|
+ throw new InvalidAddressException("To few periods for DB address");
|
|
|
|
+
|
|
|
|
+ address = int.Parse(txt2.Substring(0, txt2.IndexOf(".")));
|
|
|
|
+ bitNumber = int.Parse(txt2.Substring(txt2.IndexOf(".") + 1));
|
|
|
|
+ if (bitNumber > 7)
|
|
|
|
+ throw new InvalidAddressException("Bit can only be 0-7");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
}
|
|
}
|
|
|
|
+
|
|
}
|
|
}
|