Browse Source

update code

pull/8/head
Tony Shou 7 years ago
parent
commit
d48fb9e442
  1. 6
      SCADA/Program/BatchCoreService/BatchCoreService.csproj.user
  2. BIN
      SCADA/Program/BatchCoreService/obj/x86/Debug/BatchCoreService.csprojAssemblyReference.cache
  3. BIN
      SCADA/Program/ClientDriver/obj/Debug/ClientDriver.csprojAssemblyReference.cache
  4. 2
      SCADA/Program/CoreTest/SystemLog.cs
  5. BIN
      SCADA/Program/CoreTest/obj/x86/Debug/Example.csprojAssemblyReference.cache
  6. BIN
      SCADA/Program/DataHelper/obj/x86/Debug/DataHelper.csprojAssemblyReference.cache
  7. 150
      SCADA/Program/DataService/Alarm.cs
  8. 688
      SCADA/Program/DataService/CacheReader.cs
  9. 861
      SCADA/Program/DataService/Condition.cs
  10. 32
      SCADA/Program/DataService/DeviceAddress.cs
  11. 419
      SCADA/Program/DataService/Eval.cs
  12. 463
      SCADA/Program/DataService/ExtensionMethods.cs
  13. 49
      SCADA/Program/DataService/HistoryData.cs
  14. 21
      SCADA/Program/DataService/IGroup.cs
  15. 33
      SCADA/Program/DataService/IReader.cs
  16. 32
      SCADA/Program/DataService/IServer.cs
  17. 419
      SCADA/Program/DataService/ITag.cs
  18. 520
      SCADA/Program/DataService/PLCGroup.cs
  19. 49
      SCADA/Program/DataService/Storage.cs
  20. 39
      SCADA/Program/DataService/TagMetaData.cs
  21. BIN
      SCADA/Program/FileDriver/obj/Debug/FileDriver.csprojAssemblyReference.cache
  22. BIN
      SCADA/Program/HMIControl/bin/Debug/DataHelper.dll
  23. BIN
      SCADA/Program/HMIControl/bin/Debug/DataHelper.pdb
  24. BIN
      SCADA/Program/HMIControl/bin/Debug/DataService.dll
  25. BIN
      SCADA/Program/HMIControl/bin/Debug/DataService.pdb
  26. BIN
      SCADA/Program/HMIControl/bin/Debug/HMIControl.VisualStudio.Design.dll
  27. BIN
      SCADA/Program/HMIControl/bin/Debug/HMIControl.VisualStudio.Design.pdb
  28. BIN
      SCADA/Program/LinkableControlDesignTime/obj/Debug/HMIControl.VisualStudio.Design.dll
  29. BIN
      SCADA/Program/LinkableControlDesignTime/obj/Debug/HMIControl.VisualStudio.Design.pdb
  30. BIN
      SCADA/Program/ModbusDriver/obj/Debug/ModbusDriver.csprojAssemblyReference.cache
  31. BIN
      SCADA/Program/SiemensPLCDriver/obj/Debug/SiemensPLCDriver.csprojAssemblyReference.cache
  32. BIN
      SCADA/Program/TagConfig/TagConfig/obj/x86/Debug/TagConfig.csprojAssemblyReference.cache

6
SCADA/Program/BatchCoreService/BatchCoreService.csproj.user

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectView>ProjectFiles</ProjectView>
</PropertyGroup>
</Project>

BIN
SCADA/Program/BatchCoreService/obj/x86/Debug/BatchCoreService.csprojAssemblyReference.cache

Binary file not shown.

BIN
SCADA/Program/ClientDriver/obj/Debug/ClientDriver.csprojAssemblyReference.cache

Binary file not shown.

2
SCADA/Program/CoreTest/SystemLog.cs

@ -21,7 +21,7 @@ namespace CoreTest
set; set;
} }
public bool IsActived public bool IsActivated
{ {
get; get;
set; set;

BIN
SCADA/Program/CoreTest/obj/x86/Debug/Example.csprojAssemblyReference.cache

Binary file not shown.

BIN
SCADA/Program/DataHelper/obj/x86/Debug/DataHelper.csprojAssemblyReference.cache

Binary file not shown.

150
SCADA/Program/DataService/Alarm.cs

@ -1,121 +1,66 @@
using System; using System;
using System.ComponentModel; using System.ComponentModel;
namespace DataService namespace DataService {
{ public class AlarmItem : IComparable<AlarmItem>, INotifyPropertyChanged {
public class AlarmItem : IComparable<AlarmItem>, INotifyPropertyChanged
{
int _condiId; int _condiId;
Severity _severity; Severity _severity;
SubAlarmType _alarmType; SubAlarmType _alarmType;
DateTime _startTime; DateTime _startTime;
TimeSpan _duration; TimeSpan _duration;
object _alarmValue; object _alarmValue;
string _alarmText; string _alarmText;
string _source; string _source;
public SubAlarmType SubAlarmType public SubAlarmType SubAlarmType {
{ get { return _alarmType; }
get set { _alarmType = value; }
{
return _alarmType;
}
set
{
_alarmType = value;
}
} }
public Severity Severity public Severity Severity {
{ get { return _severity; }
get set { _severity = value; }
{
return _severity;
}
set
{
_severity = value;
}
} }
public DateTime StartTime public DateTime StartTime {
{ get { return _startTime; }
get set { _startTime = value; }
{
return _startTime;
}
set
{
_startTime = value;
}
} }
public int ConditionId public int ConditionId {
{ get { return _condiId; }
get set { _condiId = value; }
{
return _condiId;
}
set
{
_condiId = value;
}
} }
public TimeSpan Duration public TimeSpan Duration {
{ get {
get
{
//return _endTime-_startTime; //return _endTime-_startTime;
return _duration; return _duration;
} }
set set {
{
_duration = value; _duration = value;
OnPropertyChanged("Duration"); OnPropertyChanged("Duration");
} }
} }
public object AlarmValue public object AlarmValue {
{ get { return _alarmValue; }
get set { _alarmValue = value; }
{
return _alarmValue;
}
set
{
_alarmValue = value;
}
} }
public string AlarmText public string AlarmText {
{ get { return _alarmText; }
get set { _alarmText = value; }
{
return _alarmText;
}
set
{
_alarmText = value;
}
} }
public string Source public string Source {
{ get { return _source; }
get set { _source = value; }
{
return _source;
}
set
{
_source = value;
}
} }
public AlarmItem(DateTime time, string alarmText, object alarmValue, SubAlarmType type, Severity severity, int condId, string source) public AlarmItem(DateTime time, string alarmText, object alarmValue, SubAlarmType type, Severity severity,
{ int condId, string source) {
this._startTime = time; this._startTime = time;
this._alarmType = type; this._alarmType = type;
this._alarmText = alarmText; this._alarmText = alarmText;
@ -125,8 +70,7 @@ namespace DataService
this._source = source; this._source = source;
} }
public AlarmItem() public AlarmItem() {
{
this._startTime = DateTime.Now; this._startTime = DateTime.Now;
this._alarmType = SubAlarmType.None; this._alarmType = SubAlarmType.None;
this._alarmText = string.Empty; this._alarmText = string.Empty;
@ -137,8 +81,7 @@ namespace DataService
#region IComparable<AlarmItem> Members #region IComparable<AlarmItem> Members
public int CompareTo(AlarmItem other) public int CompareTo(AlarmItem other) {
{
return this._startTime.CompareTo(other._startTime); return this._startTime.CompareTo(other._startTime);
} }
@ -146,20 +89,15 @@ namespace DataService
public event PropertyChangedEventHandler PropertyChanged; public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName) private void OnPropertyChanged(string propertyName) {
{ if (this.PropertyChanged != null) {
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
} }
} }
} }
[Flags] [Flags]
public enum AlarmType public enum AlarmType {
{
None = 0, None = 0,
Level = 1, Level = 1,
Dev = 2, Dev = 2,
@ -171,8 +109,7 @@ namespace DataService
} }
[Flags] [Flags]
public enum SubAlarmType public enum SubAlarmType {
{
None = 0, None = 0,
LoLo = 1, LoLo = 1,
Low = 2, Low = 2,
@ -187,8 +124,7 @@ namespace DataService
MinROC = 512 MinROC = 512
} }
public enum Severity public enum Severity {
{
Error = 7, Error = 7,
High = 6, High = 6,
MediumHigh = 5, MediumHigh = 5,
@ -200,24 +136,20 @@ namespace DataService
} }
[Flags] [Flags]
public enum ConditionState : byte public enum ConditionState : byte {
{
Acked = 4, Acked = 4,
Actived = 2, Actived = 2,
Enabled = 1 Enabled = 1
} }
public enum EventType : byte public enum EventType : byte {
{
Simple = 1, Simple = 1,
TraceEvent = 2, TraceEvent = 2,
ConditionEvent = 4, ConditionEvent = 4,
} }
public enum ConditionType : byte public enum ConditionType : byte {
{
Absolute = 0, Absolute = 0,
Percent = 1 Percent = 1
} }
}
}

688
SCADA/Program/DataService/CacheReader.cs

File diff suppressed because it is too large

861
SCADA/Program/DataService/Condition.cs

File diff suppressed because it is too large

32
SCADA/Program/DataService/DeviceAddress.cs

@ -1,11 +1,9 @@
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace DataService namespace DataService {
{
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public struct DeviceAddress : IComparable<DeviceAddress> public struct DeviceAddress : IComparable<DeviceAddress> {
{
public int Area; public int Area;
public int Start; public int Start;
public ushort DBNumber; public ushort DBNumber;
@ -14,8 +12,8 @@ namespace DataService
public byte Bit; public byte Bit;
public DataType VarType; public DataType VarType;
public DeviceAddress(int area, ushort dbnumber, ushort cIndex, int start, ushort size, byte bit, DataType type) public DeviceAddress(int area, ushort dbnumber, ushort cIndex, int start, ushort size, byte bit,
{ DataType type) {
Area = area; Area = area;
DBNumber = dbnumber; DBNumber = dbnumber;
CacheIndex = cIndex; CacheIndex = cIndex;
@ -27,17 +25,15 @@ namespace DataService
public static readonly DeviceAddress Empty = new DeviceAddress(0, 0, 0, 0, 0, 0, DataType.NONE); public static readonly DeviceAddress Empty = new DeviceAddress(0, 0, 0, 0, 0, 0, DataType.NONE);
public int CompareTo(DeviceAddress other) public int CompareTo(DeviceAddress other) {
{ return Area > other.Area ? 1 :
return this.Area > other.Area ? 1 : Area < other.Area ? -1 :
this.Area < other.Area ? -1 : DBNumber > other.DBNumber ? 1 :
this.DBNumber > other.DBNumber ? 1 : DBNumber < other.DBNumber ? -1 :
this.DBNumber < other.DBNumber ? -1 : Start > other.Start ? 1 :
this.Start > other.Start ? 1 : Start < other.Start ? -1 :
this.Start < other.Start ? -1 : Bit > other.Bit ? 1 :
this.Bit > other.Bit ? 1 : Bit < other.Bit ? -1 : 0;
this.Bit < other.Bit ? -1 : 0;
} }
} }
}
}

419
SCADA/Program/DataService/Eval.cs

@ -4,51 +4,46 @@ using System.Linq.Expressions;
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace DataService namespace DataService {
{ public class ExpressionEval : IDisposable {
public class ExpressionEval : IDisposable
{
Expression _param1; Expression _param1;
List<ITag> _tagList = new List<ITag>(); List<ITag> _tagList = new List<ITag>();
public List<ITag> TagList
{ public List<ITag> TagList {
get get { return _tagList; }
{
return _tagList;
}
} }
IDataServer _server; IDataServer _server;
public ExpressionEval(IDataServer server) public ExpressionEval(IDataServer server) {
{
_server = server; _server = server;
_param1 = Expression.Constant(this); _param1 = Expression.Constant(this);
} }
public Delegate Eval(string expression) /// <summary>
{ /// 函数表达式
/// </summary>
/// <param name="expression"></param>
/// <returns></returns>
public Delegate Eval(string expression) {
if (string.IsNullOrEmpty(expression)) return null; if (string.IsNullOrEmpty(expression)) return null;
var lambda = ComplieRpnExp(RpnExpression(expression)); var lambda = ComplieRpnExp(RpnExpression(expression));
if (lambda != null) return lambda.Compile(); if (lambda != null) return lambda.Compile();
return null; return null;
} }
public Delegate WriteEval(string expression) public Delegate WriteEval(string expression) {
{
if (_server == null || string.IsNullOrEmpty(expression)) return null; if (_server == null || string.IsNullOrEmpty(expression)) return null;
if (_server[expression.ToUpper()] != null) if (_server[expression.ToUpper()] != null) {
{
return new Func<object, int>((object value) => { return WriteTag(expression, value); }); return new Func<object, int>((object value) => { return WriteTag(expression, value); });
} }
return null; return null;
} }
public Func<int> WriteEval(string expression1, string expression2) public Func<int> WriteEval(string expression1, string expression2) {
{
if (_server == null || string.IsNullOrEmpty(expression2)) return null; if (_server == null || string.IsNullOrEmpty(expression2)) return null;
if (_server[expression1.ToUpper()] != null) if (_server[expression1.ToUpper()] != null) {
{
var dele = Eval(expression2); var dele = Eval(expression2);
var funcbool = dele as Func<bool>; var funcbool = dele as Func<bool>;
if (funcbool != null) if (funcbool != null)
@ -63,12 +58,12 @@ namespace DataService
if (funcstring != null) if (funcstring != null)
return () => { return WriteTag(expression1, funcstring()); }; return () => { return WriteTag(expression1, funcstring()); };
} }
return null; return null;
} }
public static bool ValidationExpression(string expression) public static bool ValidationExpression(string expression) {
{ return true; //可加入正则表达式验证
return true;//可加入正则表达式验证
} }
/// <summary> /// <summary>
@ -76,10 +71,8 @@ namespace DataService
/// </summary> /// </summary>
/// <param name="strOperator">操作符</param> /// <param name="strOperator">操作符</param>
/// <returns>操作运算符,空格返回0,出错返回-1</returns> /// <returns>操作运算符,空格返回0,出错返回-1</returns>
private static byte GetOperatorLevel(char strOperator) private static byte GetOperatorLevel(char strOperator) {
{ switch (strOperator) {
switch (strOperator)
{
case '~': case '~':
return 10; return 10;
case '*': case '*':
@ -109,7 +102,6 @@ namespace DataService
//case ':': //case ':':
default: default:
return 0; return 0;
} }
} }
@ -118,12 +110,12 @@ namespace DataService
/// </summary> /// </summary>
/// <param name="expression">标准中缀表达式</param> /// <param name="expression">标准中缀表达式</param>
/// <returns>标准逆波兰表达式</returns> /// <returns>标准逆波兰表达式</returns>
public static List<string> RpnExpression(string expression) public static List<string> RpnExpression(string expression) {
{
//加入结束标记 //加入结束标记
//定义出栈和入栈堆栈 //定义出栈和入栈堆栈
string[] strNum = expression.Split('~', '%', '>', '<', '=', '!', '&', '|', '?', '#', '^', '+', '-', '*', '/', '(', ')'); string[] strNum = expression.Split('~', '%', '>', '<', '=', '!', '&', '|', '?', '#', '^', '+', '-', '*',
if (strNum.Length < 2) return new List<string>() { expression }; '/', '(', ')');
if (strNum.Length < 2) return new List<string>() {expression};
//操作运算符堆栈 //操作运算符堆栈
Stack<Operator> oper = new Stack<Operator>(); Stack<Operator> oper = new Stack<Operator>();
//定义输出堆栈 //定义输出堆栈
@ -140,71 +132,60 @@ namespace DataService
int intStackCount = 0; int intStackCount = 0;
//从左到右读取前缀表达式 //从左到右读取前缀表达式
while (i < expression.Length) while (i < expression.Length) {
{
//读取一个字符 //读取一个字符
char strChar = expression[i]; char strChar = expression[i];
//取字符的运算级别 //取字符的运算级别
if (strChar == '#') { i++; continue; } if (strChar == '#') {
i++;
continue;
}
byte intLevel = GetOperatorLevel(strChar); byte intLevel = GetOperatorLevel(strChar);
if (intLevel == 0) if (intLevel == 0)
//数字直接推入输出堆栈 //数字直接推入输出堆栈
{ {
while (n++ < strNum.Length) while (n++ < strNum.Length) {
{ if (strNum[n] != "") {
if (strNum[n] != "")
{
output.Add(strNum[n]); output.Add(strNum[n]);
i += strNum[n].Length; i += strNum[n].Length;
//移动数组指针 //移动数组指针
break; break;
} }
} }
} } else //操作字符根据运算字符级别推入运算符堆栈
else //操作字符根据运算字符级别推入运算符堆栈
{ {
if (oper.Count == 0) if (oper.Count == 0) {
{
//运算符堆栈为空,直接推入堆栈 //运算符堆栈为空,直接推入堆栈
oper.Push(new Operator(strChar, intLevel)); oper.Push(new Operator(strChar, intLevel));
//移动字符读取指针 //移动字符读取指针
i++; i++;
} } else {
else
{
op = oper.Peek(); op = oper.Peek();
if (intLevel > op.Level || intLevel == 2) if (intLevel > op.Level || intLevel == 2) {
{
//运算字符比运算符堆栈最后的级别高或者运算符为'('直接推入运算符堆栈 //运算字符比运算符堆栈最后的级别高或者运算符为'('直接推入运算符堆栈
oper.Push(new Operator(strChar, intLevel)); oper.Push(new Operator(strChar, intLevel));
//移动字符读取指针 //移动字符读取指针
i++; i++;
} } else {
else
{
//运算字符不高于运算符堆栈最后的级别,则将运算符堆栈出栈,直到比其高为止 //运算字符不高于运算符堆栈最后的级别,则将运算符堆栈出栈,直到比其高为止
intStackCount = oper.Count; intStackCount = oper.Count;
for (int m = 0; m < intStackCount; m++) for (int m = 0; m < intStackCount; m++) {
{
op = oper.Peek(); op = oper.Peek();
if (op.Level >= intLevel) if (op.Level >= intLevel) {
{
//将操作符出栈并压入输入堆栈 //将操作符出栈并压入输入堆栈
char o = op.OperatorStack; char o = op.OperatorStack;
if (!(o == ')' || o == '(')) if (!(o == ')' || o == '(')) {
{
output.Add(o.ToString()); output.Add(o.ToString());
} }
oper.Pop(); oper.Pop();
if (op.Level == 2) if (op.Level == 2) {
{
//如果操作符堆栈中最后的操作符为'('则停止出栈 //如果操作符堆栈中最后的操作符为'('则停止出栈
i++; i++;
break; break;
} }
} } else {
else
{
//直到运算符已经高出运算符栈中最后的级别,则入栈 //直到运算符已经高出运算符栈中最后的级别,则入栈
oper.Push(new Operator(strChar, intLevel)); oper.Push(new Operator(strChar, intLevel));
i++; i++;
@ -217,8 +198,7 @@ namespace DataService
} }
intStackCount = oper.Count; intStackCount = oper.Count;
for (int m = 0; m < intStackCount; m++) for (int m = 0; m < intStackCount; m++) {
{
op = oper.Peek(); op = oper.Peek();
output.Add(op.OperatorStack.ToString()); output.Add(op.OperatorStack.ToString());
oper.Pop(); oper.Pop();
@ -232,287 +212,273 @@ namespace DataService
/// </summary> /// </summary>
/// <param name="expression">标准逆波兰表达式</param> /// <param name="expression">标准逆波兰表达式</param>
/// <returns>逆波兰表达式的解</returns> /// <returns>逆波兰表达式的解</returns>
public LambdaExpression ComplieRpnExp(List<string> strNum) public LambdaExpression ComplieRpnExp(List<string> strNum) {
{
_tagList.Clear(); _tagList.Clear();
//拆分逆波兰表达式 //拆分逆波兰表达式
int intLenth = strNum.Count; int intLenth = strNum.Count;
if (intLenth == 0) return null; if (intLenth == 0) return null;
//定义数字堆栈 //定义数字堆栈
try try {
{
Stack<Expression> number = new Stack<Expression>(); Stack<Expression> number = new Stack<Expression>();
for (int i = 0; i < intLenth; i++) for (int i = 0; i < intLenth; i++) {
{
string expr = strNum[i]; string expr = strNum[i];
switch (expr) switch (expr) {
{
case "~": case "~":
if (number.Count > 0) if (number.Count > 0) {
{
Expression left = number.Pop(); Expression left = number.Pop();
number.Push(Expression.Not(left)); number.Push(Expression.Not(left));
} }
break; break;
case "*": case "*":
if (number.Count > 1) if (number.Count > 1) {
{
Expression right = number.Pop(); Expression right = number.Pop();
Expression left = number.Pop(); Expression left = number.Pop();
if (left.Type != right.Type) if (left.Type != right.Type) {
{
if (left.Type != typeof(float)) if (left.Type != typeof(float))
left = Expression.Convert(left, typeof(float)); left = Expression.Convert(left, typeof(float));
if (right.Type != typeof(float)) if (right.Type != typeof(float))
right = Expression.Convert(right, typeof(float)); right = Expression.Convert(right, typeof(float));
} }
number.Push(Expression.Multiply(left, right)); number.Push(Expression.Multiply(left, right));
} }
break; break;
case "/": case "/":
if (number.Count > 1) if (number.Count > 1) {
{
Expression right = number.Pop(); Expression right = number.Pop();
Expression left = number.Pop(); Expression left = number.Pop();
if (left.Type != right.Type) if (left.Type != right.Type) {
{
if (left.Type != typeof(float)) if (left.Type != typeof(float))
left = Expression.Convert(left, typeof(float)); left = Expression.Convert(left, typeof(float));
if (right.Type != typeof(float)) if (right.Type != typeof(float))
right = Expression.Convert(right, typeof(float)); right = Expression.Convert(right, typeof(float));
} }
number.Push(Expression.Divide(left, right)); number.Push(Expression.Divide(left, right));
} }
break; break;
case "%": case "%":
if (number.Count > 1) if (number.Count > 1) {
{
Expression right = number.Pop(); Expression right = number.Pop();
Expression left = number.Pop(); Expression left = number.Pop();
if (left.Type != right.Type) if (left.Type != right.Type) {
{
if (left.Type != typeof(int)) if (left.Type != typeof(int))
left = Expression.Convert(left, typeof(int)); left = Expression.Convert(left, typeof(int));
if (right.Type != typeof(int)) if (right.Type != typeof(int))
right = Expression.Convert(right, typeof(int)); right = Expression.Convert(right, typeof(int));
} }
number.Push(Expression.Modulo(left, right)); number.Push(Expression.Modulo(left, right));
} }
break; break;
case "+": case "+":
if (number.Count > 1) if (number.Count > 1) {
{
Expression right = number.Pop(); Expression right = number.Pop();
Expression left = number.Pop(); Expression left = number.Pop();
if (left.Type == typeof(string) || right.Type == typeof(string)) if (left.Type == typeof(string) || right.Type == typeof(string)) {
{
if (left.Type != typeof(string)) if (left.Type != typeof(string))
left = Expression.Convert(left, typeof(object)); left = Expression.Convert(left, typeof(object));
if (right.Type != typeof(string)) if (right.Type != typeof(string))
right = Expression.Convert(right, typeof(object)); right = Expression.Convert(right, typeof(object));
number.Push(Expression.Call(typeof(string).GetMethod("Concat", new Type[] { typeof(object), typeof(object) }), left, right)); number.Push(Expression.Call(
} typeof(string).GetMethod("Concat", new Type[] {typeof(object), typeof(object)}),
else left, right));
{ } else {
if (left.Type != right.Type) if (left.Type != right.Type) {
{
if (left.Type != typeof(float)) if (left.Type != typeof(float))
left = Expression.Convert(left, typeof(float)); left = Expression.Convert(left, typeof(float));
if (right.Type != typeof(float)) if (right.Type != typeof(float))
right = Expression.Convert(right, typeof(float)); right = Expression.Convert(right, typeof(float));
} }
number.Push(Expression.Add(left, right)); number.Push(Expression.Add(left, right));
} }
} }
break; break;
case "-": case "-":
if (number.Count > 1) if (number.Count > 1) {
{
Expression right = number.Pop(); Expression right = number.Pop();
Expression left = number.Pop(); Expression left = number.Pop();
if (left.Type != right.Type) if (left.Type != right.Type) {
{
if (left.Type != typeof(float)) if (left.Type != typeof(float))
left = Expression.Convert(left, typeof(float)); left = Expression.Convert(left, typeof(float));
if (right.Type != typeof(float)) if (right.Type != typeof(float))
right = Expression.Convert(right, typeof(float)); right = Expression.Convert(right, typeof(float));
} }
number.Push(Expression.Subtract(left, right)); number.Push(Expression.Subtract(left, right));
} }
break; break;
case ">": case ">":
if (number.Count > 1) if (number.Count > 1) {
{
Expression right = number.Pop(); Expression right = number.Pop();
Expression left = number.Pop(); Expression left = number.Pop();
if (left.Type != right.Type) if (left.Type != right.Type) {
{
if (left.Type != typeof(float)) if (left.Type != typeof(float))
left = Expression.Convert(left, typeof(float)); left = Expression.Convert(left, typeof(float));
if (right.Type != typeof(float)) if (right.Type != typeof(float))
right = Expression.Convert(right, typeof(float)); right = Expression.Convert(right, typeof(float));
} }
number.Push(Expression.GreaterThan(left, right)); number.Push(Expression.GreaterThan(left, right));
} }
break; break;
case "<": case "<":
if (number.Count > 1) if (number.Count > 1) {
{
Expression right = number.Pop(); Expression right = number.Pop();
Expression left = number.Pop(); Expression left = number.Pop();
if (left.Type != right.Type) if (left.Type != right.Type) {
{
if (left.Type != typeof(float)) if (left.Type != typeof(float))
left = Expression.Convert(left, typeof(float)); left = Expression.Convert(left, typeof(float));
if (right.Type != typeof(float)) if (right.Type != typeof(float))
right = Expression.Convert(right, typeof(float)); right = Expression.Convert(right, typeof(float));
} }
number.Push(Expression.LessThan(left, right)); number.Push(Expression.LessThan(left, right));
} }
break; break;
case "&": case "&":
if (number.Count > 1) if (number.Count > 1) {
{
Expression right = number.Pop(); Expression right = number.Pop();
Expression left = number.Pop(); Expression left = number.Pop();
number.Push(Expression.And(left, right)); number.Push(Expression.And(left, right));
} }
break; break;
case "^": case "^":
if (number.Count > 1) if (number.Count > 1) {
{
Expression right = number.Pop(); Expression right = number.Pop();
Expression left = number.Pop(); Expression left = number.Pop();
number.Push(Expression.ExclusiveOr(left, right)); number.Push(Expression.ExclusiveOr(left, right));
} }
break; break;
case "|": case "|":
if (number.Count > 1) if (number.Count > 1) {
{
Expression right = number.Pop(); Expression right = number.Pop();
Expression left = number.Pop(); Expression left = number.Pop();
number.Push(Expression.Or(left, right)); number.Push(Expression.Or(left, right));
} }
break; break;
case "=": case "=":
if (number.Count > 1) if (number.Count > 1) {
{
Expression right = number.Pop(); Expression right = number.Pop();
Expression left = number.Pop(); Expression left = number.Pop();
if (left.Type != right.Type) if (left.Type != right.Type) {
{
if (left.Type != typeof(float)) if (left.Type != typeof(float))
left = Expression.Convert(left, typeof(float)); left = Expression.Convert(left, typeof(float));
if (right.Type != typeof(float)) if (right.Type != typeof(float))
right = Expression.Convert(right, typeof(float)); right = Expression.Convert(right, typeof(float));
} }
number.Push(Expression.Equal(left, right)); number.Push(Expression.Equal(left, right));
} }
break; break;
case "!": case "!":
if (number.Count > 1) if (number.Count > 1) {
{
Expression right = number.Pop(); Expression right = number.Pop();
Expression left = number.Pop(); Expression left = number.Pop();
if (left.Type != right.Type) if (left.Type != right.Type) {
{
if (left.Type != typeof(float)) if (left.Type != typeof(float))
left = Expression.Convert(left, typeof(float)); left = Expression.Convert(left, typeof(float));
if (right.Type != typeof(float)) if (right.Type != typeof(float))
right = Expression.Convert(right, typeof(float)); right = Expression.Convert(right, typeof(float));
} }
number.Push(Expression.NotEqual(left, right)); number.Push(Expression.NotEqual(left, right));
} }
break; break;
case "?": case "?":
if (number.Count > 1) if (number.Count > 1) {
{
Expression right = number.Pop(); Expression right = number.Pop();
Expression left = number.Pop(); Expression left = number.Pop();
if (left.Type != right.Type) if (left.Type != right.Type) {
{
if (left.Type != typeof(float)) if (left.Type != typeof(float))
left = Expression.Convert(left, typeof(float)); left = Expression.Convert(left, typeof(float));
if (right.Type != typeof(float)) if (right.Type != typeof(float))
right = Expression.Convert(right, typeof(float)); right = Expression.Convert(right, typeof(float));
} }
Expression test = number.Pop(); Expression test = number.Pop();
number.Push(Expression.Condition(test, left, right)); number.Push(Expression.Condition(test, left, right));
} }
break; break;
default: default:
if (expr[0] == '@') if (expr[0] == '@') {
{ switch (expr.Substring(1).ToUpper()) {
switch (expr.Substring(1).ToUpper()) case "TIME": {
{ Expression<Func<string>> f = () => DateTime.Now.ToShortTimeString();
case "TIME": number.Push(f.Body);
{ }
Expression<Func<string>> f = () => DateTime.Now.ToShortTimeString();
number.Push(f.Body);
}
goto lab1; goto lab1;
case "DATE": case "DATE": {
{ Expression<Func<string>> f = () => DateTime.Now.ToShortDateString();
Expression<Func<string>> f = () => DateTime.Now.ToShortDateString(); number.Push(f.Body);
number.Push(f.Body); }
}
goto lab1; goto lab1;
case "DATETIME": case "DATETIME": {
{ Expression<Func<string>> f = () => DateTime.Now.ToString();
Expression<Func<string>> f = () => DateTime.Now.ToString(); number.Push(f.Body);
number.Push(f.Body); }
}
goto lab1; goto lab1;
case "APP": case "APP": {
{ Expression<Func<string>> f = () => AppDomain.CurrentDomain.FriendlyName;
Expression<Func<string>> f = () => AppDomain.CurrentDomain.FriendlyName; number.Push(f.Body);
number.Push(f.Body); }
}
goto lab1; goto lab1;
case "NAME": case "NAME": {
{ Expression<Func<string>> f = () => Environment.MachineName;
Expression<Func<string>> f = () => Environment.MachineName; number.Push(f.Body);
number.Push(f.Body); }
}
goto lab1; goto lab1;
case "PATH": case "PATH": {
{ Expression<Func<string>> f = () => Environment.CurrentDirectory;
Expression<Func<string>> f = () => Environment.CurrentDirectory; number.Push(f.Body);
number.Push(f.Body); }
}
goto lab1; goto lab1;
case "USER": case "USER": {
{ Expression<Func<string>> f = () => Environment.UserName;
Expression<Func<string>> f = () => Environment.UserName; number.Push(f.Body);
number.Push(f.Body); }
}
goto lab1; goto lab1;
case "REGION": case "REGION": {
{ Expression<Func<string>> f = () =>
Expression<Func<string>> f = () => System.Globalization.CultureInfo.CurrentCulture.Name; System.Globalization.CultureInfo.CurrentCulture.Name;
number.Push(f.Body); number.Push(f.Body);
} }
goto lab1; goto lab1;
} }
} }
object result; object result;
if (IsConstant(expr, out result)) if (IsConstant(expr, out result)) {
{
number.Push(Expression.Constant(result)); number.Push(Expression.Constant(result));
} } else {
else
{
number.Push(GetTagExpression(expr)); number.Push(GetTagExpression(expr));
} }
lab1:
lab1:
break; break;
} }
} }
Expression d = number.Pop(); Expression d = number.Pop();
return Expression.Lambda(d); return Expression.Lambda(d);
} catch (Exception e) {
return null;
} }
catch (Exception e) { return null; }
} }
MethodInfo _boolinfo = typeof(ExpressionEval).GetMethod("GetBool"); MethodInfo _boolinfo = typeof(ExpressionEval).GetMethod("GetBool");
@ -520,12 +486,10 @@ namespace DataService
MethodInfo _intinfo = typeof(ExpressionEval).GetMethod("GetInt"); MethodInfo _intinfo = typeof(ExpressionEval).GetMethod("GetInt");
MethodInfo _stringinfo = typeof(ExpressionEval).GetMethod("GetString"); MethodInfo _stringinfo = typeof(ExpressionEval).GetMethod("GetString");
public Expression GetTagExpression(string tagName) public Expression GetTagExpression(string tagName) {
{
if (_server == null) return Expression.Empty(); if (_server == null) return Expression.Empty();
ITag tag = _server[tagName]; ITag tag = _server[tagName];
switch (tag.Address.VarType) switch (tag.Address.VarType) {
{
case DataType.BOOL: case DataType.BOOL:
return Expression.Call(_param1, _boolinfo, Expression.Constant(tagName)); return Expression.Call(_param1, _boolinfo, Expression.Constant(tagName));
case DataType.BYTE: case DataType.BYTE:
@ -543,12 +507,10 @@ namespace DataService
} }
} }
public bool GetBool(string tagName) public bool GetBool(string tagName) {
{
if (_server == null) return false; if (_server == null) return false;
ITag tag = _server[tagName]; ITag tag = _server[tagName];
switch (tag.Address.VarType) switch (tag.Address.VarType) {
{
case DataType.BOOL: case DataType.BOOL:
return tag.Value.Boolean; return tag.Value.Boolean;
case DataType.BYTE: case DataType.BYTE:
@ -568,26 +530,23 @@ namespace DataService
} }
} }
public float GetFloat(string tagName) public float GetFloat(string tagName) {
{
if (_server == null) return 0f; if (_server == null) return 0f;
ITag tag = _server[tagName]; ITag tag = _server[tagName];
return tag.ScaleToValue(tag.Value); return tag.ScaleToValue(tag.Value);
} }
public int GetInt(string tagName) public int GetInt(string tagName) {
{
if (_server == null) return 0; if (_server == null) return 0;
ITag tag = _server[tagName]; ITag tag = _server[tagName];
switch (tag.Address.VarType) switch (tag.Address.VarType) {
{
case DataType.BOOL: case DataType.BOOL:
return tag.Value.Boolean ? 1 : 0; return tag.Value.Boolean ? 1 : 0;
case DataType.BYTE: case DataType.BYTE:
return (int)tag.Value.Byte; return (int) tag.Value.Byte;
case DataType.WORD: case DataType.WORD:
case DataType.SHORT: case DataType.SHORT:
return (int)tag.Value.Int16; return (int) tag.Value.Int16;
case DataType.TIME: case DataType.TIME:
case DataType.INT: case DataType.INT:
return tag.Value.Int32; return tag.Value.Int32;
@ -600,82 +559,71 @@ namespace DataService
} }
} }
public string GetString(string tagName) public string GetString(string tagName) {
{
return _server == null ? null : _server[tagName].ToString(); return _server == null ? null : _server[tagName].ToString();
} }
public int WriteTag(string tagName, object value) public int WriteTag(string tagName, object value) {
{
if (_server == null || value == null) return -1; if (_server == null || value == null) return -1;
ITag tag = _server[tagName]; ITag tag = _server[tagName];
if (tag.Address.VarType == DataType.BOOL || tag.Address.VarType == DataType.STR) if (tag.Address.VarType == DataType.BOOL || tag.Address.VarType == DataType.STR)
return tag.Write(value); return tag.Write(value);
else else {
{
float temp; float temp;
string str = value as string; string str = value as string;
if (str == null) temp = Convert.ToSingle(value); if (str == null) temp = Convert.ToSingle(value);
else else {
{
if (!float.TryParse(str, out temp)) if (!float.TryParse(str, out temp))
return -1; return -1;
} }
return tag.Write(tag.ValueToScale(temp)); return tag.Write(tag.ValueToScale(temp));
} }
} }
private bool IsConstant(string str, out object value) private bool IsConstant(string str, out object value) {
{ if (str.Length > 1 & str[0] == '\'' && str[str.Length - 1] == '\'') {
if (str.Length > 1 & str[0] == '\'' && str[str.Length - 1] == '\'')
{
value = str.Trim('\''); value = str.Trim('\'');
return true; return true;
} }
string upp = str.ToUpper(); string upp = str.ToUpper();
if (upp == "TRUE") if (upp == "TRUE") {
{
value = true; value = true;
return true; return true;
} } else if (upp == "FALSE") {
else if (upp == "FALSE")
{
value = false; value = false;
return true; return true;
} }
if (_server != null)
{ if (_server != null) {
var tag = _server[upp]; var tag = _server[upp];
if (tag != null) if (tag != null) {
{
if (!_tagList.Contains(tag)) if (!_tagList.Contains(tag))
_tagList.Add(tag); _tagList.Add(tag);
value = null; value = null;
return false; return false;
} }
} }
int dotcount = 0; int dotcount = 0;
for (int i = 0; i < str.Length; i++) for (int i = 0; i < str.Length; i++) {
{
char opr = str[i]; char opr = str[i];
if (opr < '0' || opr > '9') if (opr < '0' || opr > '9') {
{ if (opr != '.') {
if (opr != '.')
{
value = str; value = str;
return true; return true;
} } else {
else if (dotcount > 0) {
{
if (dotcount > 0)
{
value = str; value = str;
return true; return true;
} }
dotcount++; dotcount++;
} }
} }
} }
//value = (dotcount == 0 ? int.Parse(str) : float.Parse(str)); //value = (dotcount == 0 ? int.Parse(str) : float.Parse(str));
if (dotcount == 0) if (dotcount == 0)
value = int.Parse(str); value = int.Parse(str);
@ -683,15 +631,13 @@ namespace DataService
return true; return true;
} }
public void Clear() public void Clear() {
{
//_param1 = null; //_param1 = null;
_tagList.Clear(); _tagList.Clear();
//_tagList = null; //_tagList = null;
} }
public void Dispose() public void Dispose() {
{
_param1 = null; _param1 = null;
_tagList.Clear(); _tagList.Clear();
_tagList = null; _tagList = null;
@ -703,14 +649,13 @@ namespace DataService
/// <summary> /// <summary>
/// 操作符结构 /// 操作符结构
/// </summary> /// </summary>
public struct Operator public struct Operator {
{
public char OperatorStack; public char OperatorStack;
public byte Level; public byte Level;
public Operator(char OperatorStack, byte Level)
{ public Operator(char OperatorStack, byte Level) {
this.OperatorStack = OperatorStack; this.OperatorStack = OperatorStack;
this.Level = Level; this.Level = Level;
} }
} }
} }

463
SCADA/Program/DataService/ExtensionMethods.cs

@ -5,111 +5,96 @@ using System.Collections.Generic;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Data.SqlClient; using System.Data.SqlClient;
namespace DataService namespace DataService {
{ public static class ExtMethods {
public static class ExtMethods public static string GetExceptionMsg(this Exception e) {
{
public static string GetExceptionMsg(this Exception e)
{
string err = string.Empty; string err = string.Empty;
Exception exp = e; Exception exp = e;
while (exp != null) while (exp != null) {
{
err += string.Format("\n {0}", exp.Message); err += string.Format("\n {0}", exp.Message);
exp = exp.InnerException; exp = exp.InnerException;
} }
err += string.Format("\n {0}", e.StackTrace); err += string.Format("\n {0}", e.StackTrace);
return err; return err;
} }
public static bool ModifyItemName(this ITag tag, string name) public static bool ModifyItemName(this ITag tag, string name) {
{
IDataServer server = tag.Parent.Server; IDataServer server = tag.Parent.Server;
lock (server.SyncRoot) lock (server.SyncRoot) {
{
int index = server.GetItemProperties(tag.ID); int index = server.GetItemProperties(tag.ID);
if (index < 0) return false; if (index < 0) return false;
var meta = server.MetaDataList[index]; var meta = server.MetaDataList[index];
if (meta.Name == name) return true; if (meta.Name == name) return true;
server.MetaDataList[index] = new TagMetaData(meta.ID, meta.GroupID, name, meta.Address, meta.DataType, meta.Size, meta.Archive, meta.Maximum, meta.Minimum, meta.Cycle); server.MetaDataList[index] = new TagMetaData(meta.ID, meta.GroupID, name, meta.Address, meta.DataType,
meta.Size, meta.Archive, meta.Maximum, meta.Minimum, meta.Cycle);
server.RemoveItemIndex(meta.Name); server.RemoveItemIndex(meta.Name);
server.AddItemIndex(name, tag); server.AddItemIndex(name, tag);
return true; return true;
} }
} }
public static SubCondition FindSubConditon(this IAlarmServer server, string sourceName, SubAlarmType alarmType) public static SubCondition
{ FindSubConditon(this IAlarmServer server, string sourceName, SubAlarmType alarmType) {
var conds = server.QueryConditions(sourceName); var conds = server.QueryConditions(sourceName);
if (conds == null) return SubCondition.Empty; if (conds == null) return SubCondition.Empty;
foreach (ICondition cond in conds) foreach (ICondition cond in conds) {
{
SubCondition sub = cond.FindSubConditon(alarmType); SubCondition sub = cond.FindSubConditon(alarmType);
if (sub.SubAlarmType == alarmType) if (sub.SubAlarmType == alarmType)
return sub; return sub;
} }
return SubCondition.Empty; return SubCondition.Empty;
} }
public static SubCondition FindSubConditon(this ICondition cond, SubAlarmType alarmType) public static SubCondition FindSubConditon(this ICondition cond, SubAlarmType alarmType) {
{
var subs = cond.SubConditions; var subs = cond.SubConditions;
if (subs != null && subs.Count > 0) if (subs != null && subs.Count > 0) {
{ foreach (var sub in subs) {
foreach (var sub in subs) if (sub.SubAlarmType == alarmType) {
{
if (sub.SubAlarmType == alarmType)
{
return sub; return sub;
} }
} }
} }
return SubCondition.Empty; return SubCondition.Empty;
} }
public static bool HasScaling(this IDataServer server, string tagName) public static bool HasScaling(this IDataServer server, string tagName) {
{
ITag tag = server[tagName]; ITag tag = server[tagName];
if (tag == null) return false; if (tag == null) return false;
int scaleid = server.GetScaleByID(tag.ID); int scaleid = server.GetScaleByID(tag.ID);
return scaleid >= 0; return scaleid >= 0;
} }
public static bool HasAlarm(this IDataServer dserver, string sourceName) public static bool HasAlarm(this IDataServer dserver, string sourceName) {
{
IAlarmServer server = dserver as IAlarmServer; IAlarmServer server = dserver as IAlarmServer;
if (server == null) return false; if (server == null) return false;
List<ICondition> conds = server.ConditionList as List<ICondition>; List<ICondition> conds = server.ConditionList as List<ICondition>;
return conds == null || conds.Count == 0 ? false : conds.BinarySearch(new DigitAlarm(0, sourceName)) >= 0; return conds == null || conds.Count == 0 ? false : conds.BinarySearch(new DigitAlarm(0, sourceName)) >= 0;
} }
public static bool HasSubCondition(this IDataServer dserver, string sourceName, SubAlarmType alarmType) public static bool HasSubCondition(this IDataServer dserver, string sourceName, SubAlarmType alarmType) {
{
IAlarmServer server = dserver as IAlarmServer; IAlarmServer server = dserver as IAlarmServer;
if (server == null) return false; if (server == null) return false;
var conds = server.QueryConditions(sourceName); var conds = server.QueryConditions(sourceName);
if (conds == null) return false; if (conds == null) return false;
foreach (ICondition cond in conds) foreach (ICondition cond in conds) {
{
var subs = cond.SubConditions; var subs = cond.SubConditions;
if (subs != null && subs.Count > 0) if (subs != null && subs.Count > 0) {
{ foreach (var sub in subs) {
foreach (var sub in subs) if (sub.SubAlarmType == alarmType) {
{
if (sub.SubAlarmType == alarmType)
{
return true; return true;
} }
} }
} }
} }
return false; return false;
} }
public static ItemData<object> ReadValueEx(this IReaderWriter reader, DeviceAddress address) public static ItemData<object> ReadValueEx(this IReaderWriter reader, DeviceAddress address) {
{ switch (address.VarType) {
switch (address.VarType)
{
case DataType.BOOL: case DataType.BOOL:
var bit = reader.ReadBit(address); var bit = reader.ReadBit(address);
return new ItemData<object>(bit.Value, bit.TimeStamp, bit.Quality); return new ItemData<object>(bit.Value, bit.TimeStamp, bit.Quality);
@ -131,13 +116,12 @@ namespace DataService
var str = reader.ReadString(address, address.DataSize); var str = reader.ReadString(address, address.DataSize);
return new ItemData<object>(str.Value, str.TimeStamp, str.Quality); return new ItemData<object>(str.Value, str.TimeStamp, str.Quality);
} }
return new ItemData<object>(null, 0, QUALITIES.QUALITY_BAD); return new ItemData<object>(null, 0, QUALITIES.QUALITY_BAD);
} }
public static int WriteValueEx(this IReaderWriter writer, DeviceAddress address, object value) public static int WriteValueEx(this IReaderWriter writer, DeviceAddress address, object value) {
{ switch (address.VarType) {
switch (address.VarType)
{
case DataType.BOOL: case DataType.BOOL:
return writer.WriteBit(address, Convert.ToBoolean(value)); return writer.WriteBit(address, Convert.ToBoolean(value));
case DataType.BYTE: case DataType.BYTE:
@ -153,115 +137,112 @@ namespace DataService
case DataType.STR: case DataType.STR:
return writer.WriteString(address, value.ToString()); return writer.WriteString(address, value.ToString());
} }
return -1; return -1;
} }
public static HistoryData[] BatchRead(DataSource source, params ITag[] itemArray) public static HistoryData[] BatchRead(DataSource source, params ITag[] itemArray) {
{
int len = itemArray.Length; int len = itemArray.Length;
HistoryData[] values = new HistoryData[len]; HistoryData[] values = new HistoryData[len];
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++) {
{
itemArray[i].Refresh(source); itemArray[i].Refresh(source);
values[i].ID = itemArray[i].ID; values[i].ID = itemArray[i].ID;
values[i].Value = itemArray[i].Value; values[i].Value = itemArray[i].Value;
values[i].TimeStamp = itemArray[i].TimeStamp; values[i].TimeStamp = itemArray[i].TimeStamp;
} }
return values; return values;
} }
public static int BatchWrite(IDictionary<ITag, object> items) public static int BatchWrite(IDictionary<ITag, object> items) {
{
int rev = 0; int rev = 0;
foreach (var tag in items) foreach (var tag in items) {
{
if (tag.Key.Write(tag.Value) < 0) if (tag.Key.Write(tag.Value) < 0)
rev = -1; rev = -1;
} }
return rev; return rev;
} }
public static List<PDUArea> AssignFromPDU(this ICache cacheReader, int PDU, params DeviceAddress[] addrsArr) public static List<PDUArea> AssignFromPDU(this ICache cacheReader, int PDU, params DeviceAddress[] addrsArr) {
{
List<PDUArea> rangeList = new List<PDUArea>(); List<PDUArea> rangeList = new List<PDUArea>();
int count = addrsArr.Length; int count = addrsArr.Length;
if (count > 0) if (count > 0) {
{
//Array.Sort(addrsArr); //Array.Sort(addrsArr);
DeviceAddress start = addrsArr[0]; DeviceAddress start = addrsArr[0];
start.Bit = 0; start.Bit = 0;
int bitCount = cacheReader.ByteCount; int bitCount = cacheReader.ByteCount;
if (count > 1) if (count > 1) {
{ int cacheLength = 0; //缓冲区的大小
int cacheLength = 0;//缓冲区的大小
int cacheIndexStart = 0; int cacheIndexStart = 0;
int startIndex = 0; int startIndex = 0;
DeviceAddress segmentEnd, tagAddress; DeviceAddress segmentEnd,
tagAddress;
DeviceAddress segmentStart = start; DeviceAddress segmentStart = start;
for (int j = 1, i = 1; i < count; i++, j++) for (int j = 1,
{ i = 1;
tagAddress = addrsArr[i];//当前变量地址 i < count;
i++, j++) {
tagAddress = addrsArr[i]; //当前变量地址
int offset1 = cacheReader.GetOffset(tagAddress, segmentStart); int offset1 = cacheReader.GetOffset(tagAddress, segmentStart);
if (offset1 > (PDU / cacheReader.ByteCount)) if (offset1 > (PDU / cacheReader.ByteCount)) {
{
segmentEnd = addrsArr[i - 1]; segmentEnd = addrsArr[i - 1];
int len = cacheReader.GetOffset(segmentEnd, segmentStart); int len = cacheReader.GetOffset(segmentEnd, segmentStart);
len += segmentEnd.DataSize <= bitCount ? 1 : segmentEnd.DataSize / bitCount; len += segmentEnd.DataSize <= bitCount ? 1 : segmentEnd.DataSize / bitCount;
tagAddress.CacheIndex = (ushort)(cacheIndexStart + len); tagAddress.CacheIndex = (ushort) (cacheIndexStart + len);
addrsArr[i] = tagAddress; addrsArr[i] = tagAddress;
rangeList.Add(new PDUArea(segmentStart, len, startIndex, j)); rangeList.Add(new PDUArea(segmentStart, len, startIndex, j));
startIndex += j; j = 0; startIndex += j;
cacheLength += len;//更新缓存长度 j = 0;
cacheLength += len; //更新缓存长度
cacheIndexStart = cacheLength; cacheIndexStart = cacheLength;
segmentStart = tagAddress;//更新数据片段的起始地址 segmentStart = tagAddress; //更新数据片段的起始地址
} } else {
else tagAddress.CacheIndex = (ushort) (cacheIndexStart + offset1);
{
tagAddress.CacheIndex = (ushort)(cacheIndexStart + offset1);
addrsArr[i] = tagAddress; addrsArr[i] = tagAddress;
} }
if (i == count - 1)
{ if (i == count - 1) {
segmentEnd = addrsArr[i]; segmentEnd = addrsArr[i];
int segmentLength = cacheReader.GetOffset(segmentEnd, segmentStart); int segmentLength = cacheReader.GetOffset(segmentEnd, segmentStart);
if (segmentLength > PDU / cacheReader.ByteCount) if (segmentLength > PDU / cacheReader.ByteCount) {
{
segmentEnd = addrsArr[i - 1]; segmentEnd = addrsArr[i - 1];
segmentLength = segmentEnd.DataSize <= bitCount ? 1 : segmentEnd.DataSize / bitCount; segmentLength = segmentEnd.DataSize <= bitCount ? 1 : segmentEnd.DataSize / bitCount;
} }
tagAddress.CacheIndex = (ushort)(cacheIndexStart + segmentLength);
tagAddress.CacheIndex = (ushort) (cacheIndexStart + segmentLength);
addrsArr[i] = tagAddress; addrsArr[i] = tagAddress;
segmentLength += segmentEnd.DataSize <= bitCount ? 1 : segmentEnd.DataSize / bitCount; segmentLength += segmentEnd.DataSize <= bitCount ? 1 : segmentEnd.DataSize / bitCount;
rangeList.Add(new PDUArea(segmentStart, segmentLength, startIndex, j + 1)); rangeList.Add(new PDUArea(segmentStart, segmentLength, startIndex, j + 1));
cacheLength += segmentLength; cacheLength += segmentLength;
} }
} }
cacheReader.Size = cacheLength; cacheReader.Size = cacheLength;
} } else
else cacheReader.Size =
cacheReader.Size = start.DataSize <= bitCount ? 1 : start.DataSize / bitCount;//改变Cache的Size属性值将创建Cache的内存区域 start.DataSize <= bitCount ? 1 : start.DataSize / bitCount; //改变Cache的Size属性值将创建Cache的内存区域
} }
return rangeList; return rangeList;
} }
//调用前应对地址数组排序(是否加锁?) //调用前应对地址数组排序(是否加锁?)
public static ItemData<Storage>[] PLCReadMultiple(this IPLCDriver plc, ICache cache, DeviceAddress[] addrsArr) public static ItemData<Storage>[] PLCReadMultiple(this IPLCDriver plc, ICache cache, DeviceAddress[] addrsArr) {
{
if (addrsArr == null || cache == null || addrsArr.Length == 0) return null; if (addrsArr == null || cache == null || addrsArr.Length == 0) return null;
int len = addrsArr.Length; int len = addrsArr.Length;
ItemData<Storage>[] items = new ItemData<Storage>[len]; ItemData<Storage>[] items = new ItemData<Storage>[len];
int offset = 0; long now = DateTime.Now.ToFileTime(); int offset = 0;
long now = DateTime.Now.ToFileTime();
List<PDUArea> areas = cache.AssignFromPDU(plc.PDU, addrsArr); List<PDUArea> areas = cache.AssignFromPDU(plc.PDU, addrsArr);
foreach (PDUArea area in areas) foreach (PDUArea area in areas) {
{ byte[] rcvBytes = plc.ReadBytes(area.Start, (ushort) area.Len);
byte[] rcvBytes = plc.ReadBytes(area.Start, (ushort)area.Len);
Buffer.BlockCopy(rcvBytes, 0, cache.Cache, offset, rcvBytes.Length); Buffer.BlockCopy(rcvBytes, 0, cache.Cache, offset, rcvBytes.Length);
offset += rcvBytes.Length / cache.ByteCount; offset += rcvBytes.Length / cache.ByteCount;
} }
for (int i = 0; i < len; i++)
{ for (int i = 0; i < len; i++) {
switch (addrsArr[i].VarType) switch (addrsArr[i].VarType) {
{
case DataType.BOOL: case DataType.BOOL:
items[i].Value.Boolean = cache.ReadBit(addrsArr[i]).Value; items[i].Value.Boolean = cache.ReadBit(addrsArr[i]).Value;
break; break;
@ -283,63 +264,66 @@ namespace DataService
var item = cache.ReadString(addrsArr[i], addrsArr[i].DataSize); var item = cache.ReadString(addrsArr[i], addrsArr[i].DataSize);
break; break;
} }
items[i].Quality = QUALITIES.QUALITY_GOOD; items[i].Quality = QUALITIES.QUALITY_GOOD;
items[i].TimeStamp = now; items[i].TimeStamp = now;
} }
return items; return items;
} }
public static int PLCWriteMultiple(this IPLCDriver plc, ICache cache, DeviceAddress[] addrArr, object[] buffer, int limit) public static int PLCWriteMultiple(this IPLCDriver plc, ICache cache, DeviceAddress[] addrArr, object[] buffer,
{ int limit) {
if (cache == null || addrArr == null || buffer == null || addrArr.Length != buffer.Length) return -1; if (cache == null || addrArr == null || buffer == null || addrArr.Length != buffer.Length) return -1;
if (addrArr.Length == 1) return plc.WriteValue(addrArr[0], buffer[0]); if (addrArr.Length == 1) return plc.WriteValue(addrArr[0], buffer[0]);
lock (plc)//不锁定会有并发冲突问题;锁定也不能保障绝对安全,如有人现场操作会导致数据刷新 lock (plc) //不锁定会有并发冲突问题;锁定也不能保障绝对安全,如有人现场操作会导致数据刷新
{ {
List<PDUArea> areas = cache.AssignFromPDU(plc.PDU, addrArr); List<PDUArea> areas = cache.AssignFromPDU(plc.PDU, addrArr);
int offset = 0; int offset = 0;
foreach (PDUArea area in areas) foreach (PDUArea area in areas) {
{ byte[] rcvBytes = plc.ReadBytes(area.Start, (ushort) area.Len);
byte[] rcvBytes = plc.ReadBytes(area.Start, (ushort)area.Len);
if (rcvBytes == null) return -1; if (rcvBytes == null) return -1;
Buffer.BlockCopy(rcvBytes, 0, cache.Cache, offset, rcvBytes.Length); Buffer.BlockCopy(rcvBytes, 0, cache.Cache, offset, rcvBytes.Length);
offset += rcvBytes.Length / cache.ByteCount; offset += rcvBytes.Length / cache.ByteCount;
} }
DeviceAddress start = addrArr[0]; DeviceAddress start = addrArr[0];
int startIndex = 0; int startIndex = 0;
int endIndex = 0; int endIndex = 0;
while (endIndex < addrArr.Length) while (endIndex < addrArr.Length) {
{ if (start.Area != addrArr[endIndex].Area || start.DBNumber != addrArr[endIndex].DBNumber ||
if (start.Area != addrArr[endIndex].Area || start.DBNumber != addrArr[endIndex].DBNumber || endIndex - startIndex >= limit) endIndex - startIndex >= limit) {
{ for (int i = startIndex; i < endIndex; i++) {
for (int i = startIndex; i < endIndex; i++)
{
cache.WriteValue(addrArr[i], buffer[i]); cache.WriteValue(addrArr[i], buffer[i]);
} }
int c1 = start.CacheIndex; int c2 = addrArr[endIndex - 1].CacheIndex;
int c1 = start.CacheIndex;
int c2 = addrArr[endIndex - 1].CacheIndex;
byte[] bytes = new byte[cache.ByteCount * (c2 - c1 + 1)]; byte[] bytes = new byte[cache.ByteCount * (c2 - c1 + 1)];
Buffer.BlockCopy(cache.Cache, c1, bytes, 0, bytes.Length); Buffer.BlockCopy(cache.Cache, c1, bytes, 0, bytes.Length);
if (plc.WriteBytes(start, bytes) < 0) return -1; if (plc.WriteBytes(start, bytes) < 0) return -1;
start = addrArr[endIndex]; start = addrArr[endIndex];
startIndex = endIndex; startIndex = endIndex;
} }
endIndex++; endIndex++;
} }
} }
return 0; return 0;
} }
/// <summary> /// <summary>
/// string RightFrom /// string RightFrom
/// </summary> /// </summary>
/// <param name="text"></param> /// <param name="text"></param>
/// <param name="length"></param> /// <param name="length"></param>
/// <returns></returns> /// <returns></returns>
public static string RightFrom(this string text, int index) public static string RightFrom(this string text, int index) {
{
return text.Substring(index + 1, text.Length - index - 1); return text.Substring(index + 1, text.Length - index - 1);
} }
public static string Right(this string text, int length) public static string Right(this string text, int length) {
{
return text.Substring(text.Length - length, length); return text.Substring(text.Length - length, length);
} }
@ -348,16 +332,12 @@ namespace DataService
/// </summary> /// </summary>
/// <param name="filetime"></param> /// <param name="filetime"></param>
/// <returns></returns> /// <returns></returns>
public static DateTime ToDateTime(this long filetime) {
public static DateTime ToDateTime(this long filetime)
{
return filetime == 0 ? DateTime.Now : DateTime.FromFileTime(filetime); return filetime == 0 ? DateTime.Now : DateTime.FromFileTime(filetime);
} }
public static Type ToType(this DataType dataType) public static Type ToType(this DataType dataType) {
{ switch (dataType) {
switch (dataType)
{
case DataType.BOOL: case DataType.BOOL:
return typeof(bool); return typeof(bool);
case DataType.BYTE: case DataType.BYTE:
@ -378,15 +358,13 @@ namespace DataService
} }
} }
public static string ToFormatString(this int num, int len) public static string ToFormatString(this int num, int len) {
{
string str = num.ToString(); string str = num.ToString();
int off = len - str.Length; int off = len - str.Length;
return off > 0 ? string.Concat(new string('0', off), str) : str; return off > 0 ? string.Concat(new string('0', off), str) : str;
} }
public static bool IsEquals(this byte[] b1, byte[] b2) public static bool IsEquals(this byte[] b1, byte[] b2) {
{
if (b1 == null || b2 == null) return false; if (b1 == null || b2 == null) return false;
if (b1.Length != b2.Length) return false; if (b1.Length != b2.Length) return false;
for (int i = 0; i < b1.Length; i++) for (int i = 0; i < b1.Length; i++)
@ -395,41 +373,38 @@ namespace DataService
return true; return true;
} }
public static string ConvertToString(this byte[] bits) public static string ConvertToString(this byte[] bits) {
{
char[] chars = new char[bits.Length]; char[] chars = new char[bits.Length];
for (int i = 0; i < bits.Length; i++) for (int i = 0; i < bits.Length; i++) {
{ chars[i] = (char) bits[i];
chars[i] = (char)bits[i];
} }
return new string(chars); return new string(chars);
} }
public static byte[] ConvertToArray(this string bits) public static byte[] ConvertToArray(this string bits) {
{
var chars = bits.ToCharArray(); var chars = bits.ToCharArray();
byte[] arr = new byte[chars.Length]; byte[] arr = new byte[chars.Length];
for (int i = 0; i < chars.Length; i++) for (int i = 0; i < chars.Length; i++) {
{ arr[i] = (byte) chars[i];
arr[i] = (byte)chars[i];
} }
return arr; return arr;
} }
public static int BitSwap(this byte bit) public static int BitSwap(this byte bit) {
{
return (bit < 8 ? bit + 8 : bit - 8); return (bit < 8 ? bit + 8 : bit - 8);
} }
[Obsolete] [Obsolete]
public static Storage ToStorage(this ITag tag, object obj) public static Storage ToStorage(this ITag tag, object obj) {
{
Storage value = Storage.Empty; Storage value = Storage.Empty;
var str = obj as string; var str = obj as string;
switch (tag.Address.VarType) switch (tag.Address.VarType) {
{
case DataType.BOOL: case DataType.BOOL:
value.Boolean = str == null ? Convert.ToBoolean(obj) : str == "0" ? false : str == "1" ? true : bool.Parse(str); value.Boolean = str == null ? Convert.ToBoolean(obj) :
str == "0" ? false :
str == "1" ? true : bool.Parse(str);
break; break;
case DataType.BYTE: case DataType.BYTE:
value.Byte = Convert.ToByte(obj); value.Byte = Convert.ToByte(obj);
@ -446,17 +421,16 @@ namespace DataService
value.Single = Convert.ToSingle(obj); value.Single = Convert.ToSingle(obj);
break; break;
} }
return value; return value;
} }
public static byte[] ToByteArray(this ITag tag) public static byte[] ToByteArray(this ITag tag) {
{ switch (tag.Address.VarType) {
switch (tag.Address.VarType)
{
case DataType.BOOL: case DataType.BOOL:
return new byte[] { tag.Value.Boolean ? (byte)1 : (byte)0 }; return new byte[] {tag.Value.Boolean ? (byte) 1 : (byte) 0};
case DataType.BYTE: case DataType.BYTE:
return new byte[] { tag.Value.Byte }; return new byte[] {tag.Value.Byte};
case DataType.WORD: case DataType.WORD:
case DataType.SHORT: case DataType.SHORT:
return BitConverter.GetBytes(tag.Value.Int16); return BitConverter.GetBytes(tag.Value.Int16);
@ -471,14 +445,12 @@ namespace DataService
} }
} }
public static byte[] ToByteArray(this ITag tag, Storage value) public static byte[] ToByteArray(this ITag tag, Storage value) {
{ switch (tag.Address.VarType) {
switch (tag.Address.VarType)
{
case DataType.BOOL: case DataType.BOOL:
return new byte[] { value.Boolean ? (byte)1 : (byte)0 }; return new byte[] {value.Boolean ? (byte) 1 : (byte) 0};
case DataType.BYTE: case DataType.BYTE:
return new byte[] { value.Byte }; return new byte[] {value.Byte};
case DataType.WORD: case DataType.WORD:
case DataType.SHORT: case DataType.SHORT:
return BitConverter.GetBytes(value.Int16); return BitConverter.GetBytes(value.Int16);
@ -493,10 +465,8 @@ namespace DataService
} }
} }
public static object GetValue(this ITag tag, Storage value) public static object GetValue(this ITag tag, Storage value) {
{ switch (tag.Address.VarType) {
switch (tag.Address.VarType)
{
case DataType.BOOL: case DataType.BOOL:
return value.Boolean; return value.Boolean;
case DataType.BYTE: case DataType.BYTE:
@ -516,42 +486,35 @@ namespace DataService
} }
} }
public static float ValueToScale(this ITag tag, float value) public static float ValueToScale(this ITag tag, float value) {
{
IDataServer srv = tag.Parent.Server; IDataServer srv = tag.Parent.Server;
int ind = srv.GetScaleByID(tag.ID); int ind = srv.GetScaleByID(tag.ID);
Scaling meta = ind < 0 ? Scaling.Empty : srv.ScalingList[ind]; Scaling meta = ind < 0 ? Scaling.Empty : srv.ScalingList[ind];
if (meta.ScaleType == ScaleType.None) if (meta.ScaleType == ScaleType.None) {
{
return value; return value;
} } else {
else
{
double temp = (value - meta.EULo) / (meta.EUHi - meta.EULo); double temp = (value - meta.EULo) / (meta.EUHi - meta.EULo);
if (meta.ScaleType == ScaleType.SquareRoot) if (meta.ScaleType == ScaleType.SquareRoot)
temp = temp * temp; temp = temp * temp;
return (meta.RawHi - meta.RawLo) * (float)temp + meta.RawLo; return (meta.RawHi - meta.RawLo) * (float) temp + meta.RawLo;
} }
} }
public static float ScaleToValue(this ITag tag, Storage value) public static float ScaleToValue(this ITag tag, Storage value) {
{
DataType type = tag.Address.VarType; DataType type = tag.Address.VarType;
if (type == DataType.BOOL) return value.Boolean ? 1f : 0f; if (type == DataType.BOOL) return value.Boolean ? 1f : 0f;
IDataServer srv = tag.Parent.Server; IDataServer srv = tag.Parent.Server;
int ind = srv.GetScaleByID(tag.ID); int ind = srv.GetScaleByID(tag.ID);
Scaling meta = ind < 0 ? Scaling.Empty : srv.ScalingList[ind]; Scaling meta = ind < 0 ? Scaling.Empty : srv.ScalingList[ind];
if (meta.ScaleType == ScaleType.None) if (meta.ScaleType == ScaleType.None) {
{ switch (type) {
switch (type)
{
case DataType.BYTE: case DataType.BYTE:
return (float)value.Byte; return (float) value.Byte;
case DataType.WORD: case DataType.WORD:
case DataType.SHORT: case DataType.SHORT:
return (float)value.Int16; return (float) value.Int16;
case DataType.INT: case DataType.INT:
return (float)value.Int32; return (float) value.Int32;
case DataType.FLOAT: case DataType.FLOAT:
return value.Single; return value.Single;
case DataType.STR: case DataType.STR:
@ -559,12 +522,9 @@ namespace DataService
default: default:
return 0f; return 0f;
} }
} } else {
else
{
double temp; double temp;
switch (type) switch (type) {
{
case DataType.BYTE: case DataType.BYTE:
temp = (value.Byte - meta.RawLo) / (meta.RawHi - meta.RawLo); temp = (value.Byte - meta.RawLo) / (meta.RawHi - meta.RawLo);
break; break;
@ -581,73 +541,57 @@ namespace DataService
default: default:
return 0f; return 0f;
} }
if (meta.ScaleType == ScaleType.SquareRoot) if (meta.ScaleType == ScaleType.SquareRoot)
temp = Math.Sqrt(temp); temp = Math.Sqrt(temp);
return (meta.EUHi - meta.EULo) * (float)temp + meta.EULo; return (meta.EUHi - meta.EULo) * (float) temp + meta.EULo;
} }
} }
public static float ScaleToValue(this ITag tag) public static float ScaleToValue(this ITag tag) {
{
return ScaleToValue(tag, tag.Value); return ScaleToValue(tag, tag.Value);
} }
public static string GetTagName(this ITag tag) public static string GetTagName(this ITag tag) {
{
IDataServer srv = tag.Parent.Server; IDataServer srv = tag.Parent.Server;
int ind = srv.GetItemProperties(tag.ID); int ind = srv.GetItemProperties(tag.ID);
return ind < 0 ? null : srv.MetaDataList[ind].Name; return ind < 0 ? null : srv.MetaDataList[ind].Name;
} }
public static string GetTagName(this IDataServer srv, short id) public static string GetTagName(this IDataServer srv, short id) {
{
int ind = srv.GetItemProperties(id); int ind = srv.GetItemProperties(id);
return ind < 0 ? null : srv.MetaDataList[ind].Name; return ind < 0 ? null : srv.MetaDataList[ind].Name;
} }
public static TagMetaData GetMetaData(this ITag tag) public static TagMetaData GetMetaData(this ITag tag) {
{
IDataServer srv = tag.Parent.Server; IDataServer srv = tag.Parent.Server;
int index = srv.GetItemProperties(tag.ID); int index = srv.GetItemProperties(tag.ID);
return index < 0 ? new TagMetaData() : srv.MetaDataList[index]; return index < 0 ? new TagMetaData() : srv.MetaDataList[index];
} }
} }
public static class Utility public static class Utility {
{
private static readonly ushort[] crcTable = { private static readonly ushort[] crcTable = {
0X0000, 0XC0C1, 0XC181, 0X0140, 0XC301, 0X03C0, 0X0280, 0XC241, 0X0000, 0XC0C1, 0XC181, 0X0140, 0XC301, 0X03C0, 0X0280, 0XC241, 0XC601, 0X06C0, 0X0780, 0XC741, 0X0500,
0XC601, 0X06C0, 0X0780, 0XC741, 0X0500, 0XC5C1, 0XC481, 0X0440, 0XC5C1, 0XC481, 0X0440, 0XCC01, 0X0CC0, 0X0D80, 0XCD41, 0X0F00, 0XCFC1, 0XCE81, 0X0E40, 0X0A00, 0XCAC1,
0XCC01, 0X0CC0, 0X0D80, 0XCD41, 0X0F00, 0XCFC1, 0XCE81, 0X0E40, 0XCB81, 0X0B40, 0XC901, 0X09C0, 0X0880, 0XC841, 0XD801, 0X18C0, 0X1980, 0XD941, 0X1B00, 0XDBC1, 0XDA81,
0X0A00, 0XCAC1, 0XCB81, 0X0B40, 0XC901, 0X09C0, 0X0880, 0XC841, 0X1A40, 0X1E00, 0XDEC1, 0XDF81, 0X1F40, 0XDD01, 0X1DC0, 0X1C80, 0XDC41, 0X1400, 0XD4C1, 0XD581, 0X1540,
0XD801, 0X18C0, 0X1980, 0XD941, 0X1B00, 0XDBC1, 0XDA81, 0X1A40, 0XD701, 0X17C0, 0X1680, 0XD641, 0XD201, 0X12C0, 0X1380, 0XD341, 0X1100, 0XD1C1, 0XD081, 0X1040, 0XF001,
0X1E00, 0XDEC1, 0XDF81, 0X1F40, 0XDD01, 0X1DC0, 0X1C80, 0XDC41, 0X30C0, 0X3180, 0XF141, 0X3300, 0XF3C1, 0XF281, 0X3240, 0X3600, 0XF6C1, 0XF781, 0X3740, 0XF501, 0X35C0,
0X1400, 0XD4C1, 0XD581, 0X1540, 0XD701, 0X17C0, 0X1680, 0XD641, 0X3480, 0XF441, 0X3C00, 0XFCC1, 0XFD81, 0X3D40, 0XFF01, 0X3FC0, 0X3E80, 0XFE41, 0XFA01, 0X3AC0, 0X3B80,
0XD201, 0X12C0, 0X1380, 0XD341, 0X1100, 0XD1C1, 0XD081, 0X1040, 0XFB41, 0X3900, 0XF9C1, 0XF881, 0X3840, 0X2800, 0XE8C1, 0XE981, 0X2940, 0XEB01, 0X2BC0, 0X2A80, 0XEA41,
0XF001, 0X30C0, 0X3180, 0XF141, 0X3300, 0XF3C1, 0XF281, 0X3240, 0XEE01, 0X2EC0, 0X2F80, 0XEF41, 0X2D00, 0XEDC1, 0XEC81, 0X2C40, 0XE401, 0X24C0, 0X2580, 0XE541, 0X2700,
0X3600, 0XF6C1, 0XF781, 0X3740, 0XF501, 0X35C0, 0X3480, 0XF441, 0XE7C1, 0XE681, 0X2640, 0X2200, 0XE2C1, 0XE381, 0X2340, 0XE101, 0X21C0, 0X2080, 0XE041, 0XA001, 0X60C0,
0X3C00, 0XFCC1, 0XFD81, 0X3D40, 0XFF01, 0X3FC0, 0X3E80, 0XFE41, 0X6180, 0XA141, 0X6300, 0XA3C1, 0XA281, 0X6240, 0X6600, 0XA6C1, 0XA781, 0X6740, 0XA501, 0X65C0, 0X6480,
0XFA01, 0X3AC0, 0X3B80, 0XFB41, 0X3900, 0XF9C1, 0XF881, 0X3840, 0XA441, 0X6C00, 0XACC1, 0XAD81, 0X6D40, 0XAF01, 0X6FC0, 0X6E80, 0XAE41, 0XAA01, 0X6AC0, 0X6B80, 0XAB41,
0X2800, 0XE8C1, 0XE981, 0X2940, 0XEB01, 0X2BC0, 0X2A80, 0XEA41, 0X6900, 0XA9C1, 0XA881, 0X6840, 0X7800, 0XB8C1, 0XB981, 0X7940, 0XBB01, 0X7BC0, 0X7A80, 0XBA41, 0XBE01,
0XEE01, 0X2EC0, 0X2F80, 0XEF41, 0X2D00, 0XEDC1, 0XEC81, 0X2C40, 0X7EC0, 0X7F80, 0XBF41, 0X7D00, 0XBDC1, 0XBC81, 0X7C40, 0XB401, 0X74C0, 0X7580, 0XB541, 0X7700, 0XB7C1,
0XE401, 0X24C0, 0X2580, 0XE541, 0X2700, 0XE7C1, 0XE681, 0X2640, 0XB681, 0X7640, 0X7200, 0XB2C1, 0XB381, 0X7340, 0XB101, 0X71C0, 0X7080, 0XB041, 0X5000, 0X90C1, 0X9181,
0X2200, 0XE2C1, 0XE381, 0X2340, 0XE101, 0X21C0, 0X2080, 0XE041, 0X5140, 0X9301, 0X53C0, 0X5280, 0X9241, 0X9601, 0X56C0, 0X5780, 0X9741, 0X5500, 0X95C1, 0X9481, 0X5440,
0XA001, 0X60C0, 0X6180, 0XA141, 0X6300, 0XA3C1, 0XA281, 0X6240, 0X9C01, 0X5CC0, 0X5D80, 0X9D41, 0X5F00, 0X9FC1, 0X9E81, 0X5E40, 0X5A00, 0X9AC1, 0X9B81, 0X5B40, 0X9901,
0X6600, 0XA6C1, 0XA781, 0X6740, 0XA501, 0X65C0, 0X6480, 0XA441, 0X59C0, 0X5880, 0X9841, 0X8801, 0X48C0, 0X4980, 0X8941, 0X4B00, 0X8BC1, 0X8A81, 0X4A40, 0X4E00, 0X8EC1,
0X6C00, 0XACC1, 0XAD81, 0X6D40, 0XAF01, 0X6FC0, 0X6E80, 0XAE41, 0X8F81, 0X4F40, 0X8D01, 0X4DC0, 0X4C80, 0X8C41, 0X4400, 0X84C1, 0X8581, 0X4540, 0X8701, 0X47C0, 0X4680,
0XAA01, 0X6AC0, 0X6B80, 0XAB41, 0X6900, 0XA9C1, 0XA881, 0X6840, 0X8641, 0X8201, 0X42C0, 0X4380, 0X8341, 0X4100, 0X81C1, 0X8081, 0X4040
0X7800, 0XB8C1, 0XB981, 0X7940, 0XBB01, 0X7BC0, 0X7A80, 0XBA41,
0XBE01, 0X7EC0, 0X7F80, 0XBF41, 0X7D00, 0XBDC1, 0XBC81, 0X7C40,
0XB401, 0X74C0, 0X7580, 0XB541, 0X7700, 0XB7C1, 0XB681, 0X7640,
0X7200, 0XB2C1, 0XB381, 0X7340, 0XB101, 0X71C0, 0X7080, 0XB041,
0X5000, 0X90C1, 0X9181, 0X5140, 0X9301, 0X53C0, 0X5280, 0X9241,
0X9601, 0X56C0, 0X5780, 0X9741, 0X5500, 0X95C1, 0X9481, 0X5440,
0X9C01, 0X5CC0, 0X5D80, 0X9D41, 0X5F00, 0X9FC1, 0X9E81, 0X5E40,
0X5A00, 0X9AC1, 0X9B81, 0X5B40, 0X9901, 0X59C0, 0X5880, 0X9841,
0X8801, 0X48C0, 0X4980, 0X8941, 0X4B00, 0X8BC1, 0X8A81, 0X4A40,
0X4E00, 0X8EC1, 0X8F81, 0X4F40, 0X8D01, 0X4DC0, 0X4C80, 0X8C41,
0X4400, 0X84C1, 0X8581, 0X4540, 0X8701, 0X47C0, 0X4680, 0X8641,
0X8201, 0X42C0, 0X4380, 0X8341, 0X4100, 0X81C1, 0X8081, 0X4040
}; };
/// <summary> /// <summary>
@ -655,13 +599,12 @@ namespace DataService
/// </summary> /// </summary>
/// <param name="numbers">The byte array</param> /// <param name="numbers">The byte array</param>
/// <returns>An array of ASCII byte values</returns> /// <returns>An array of ASCII byte values</returns>
public static string GetAsciiBytes(byte[] numbers) public static string GetAsciiBytes(byte[] numbers) {
{
string str = string.Empty; string str = string.Empty;
for (int i = 0; i < numbers.Length; i++) for (int i = 0; i < numbers.Length; i++) {
{
str += numbers[i].ToString("X2"); str += numbers[i].ToString("X2");
} }
return str; return str;
} }
@ -670,13 +613,12 @@ namespace DataService
/// </summary> /// </summary>
/// <param name="numbers">The ushort array</param> /// <param name="numbers">The ushort array</param>
/// <returns>An array of ASCII byte values</returns> /// <returns>An array of ASCII byte values</returns>
public static string GetAsciiBytes(ushort[] numbers) public static string GetAsciiBytes(ushort[] numbers) {
{
string str = string.Empty; string str = string.Empty;
for (int i = 0; i < numbers.Length; i++) for (int i = 0; i < numbers.Length; i++) {
{
str += numbers[i].ToString("X4"); str += numbers[i].ToString("X4");
} }
return str; return str;
} }
@ -685,8 +627,7 @@ namespace DataService
/// </summary> /// </summary>
/// <param name="networkBytes">The network order byte array</param> /// <param name="networkBytes">The network order byte array</param>
/// <returns>The host order ushort array</returns> /// <returns>The host order ushort array</returns>
public static ushort[] NetworkBytesToHostUInt16(byte[] networkBytes) public static ushort[] NetworkBytesToHostUInt16(byte[] networkBytes) {
{
if (networkBytes == null) if (networkBytes == null)
throw new ArgumentNullException("networkBytes"); throw new ArgumentNullException("networkBytes");
@ -696,7 +637,7 @@ namespace DataService
ushort[] result = new ushort[networkBytes.Length / 2]; ushort[] result = new ushort[networkBytes.Length / 2];
for (int i = 0; i < result.Length; i++) for (int i = 0; i < result.Length; i++)
result[i] = (ushort)IPAddress.HostToNetworkOrder(BitConverter.ToInt16(networkBytes, i * 2)); result[i] = (ushort) IPAddress.HostToNetworkOrder(BitConverter.ToInt16(networkBytes, i * 2));
return result; return result;
} }
@ -706,8 +647,7 @@ namespace DataService
/// </summary> /// </summary>
/// <param name="hex">The hex string</param> /// <param name="hex">The hex string</param>
/// <returns>Array of bytes</returns> /// <returns>Array of bytes</returns>
public static byte[] HexToBytes(string hex) public static byte[] HexToBytes(string hex) {
{
if (string.IsNullOrEmpty(hex)) if (string.IsNullOrEmpty(hex))
throw new ArgumentNullException("hex"); throw new ArgumentNullException("hex");
@ -727,16 +667,16 @@ namespace DataService
/// </summary> /// </summary>
/// <param name="data">The data used in LRC</param> /// <param name="data">The data used in LRC</param>
/// <returns>LRC value</returns> /// <returns>LRC value</returns>
public static byte CalculateLrc(byte[] data, int len = 0) public static byte CalculateLrc(byte[] data, int len = 0) {
{
if (data == null) if (data == null)
throw new ArgumentNullException("data"); throw new ArgumentNullException("data");
if (len == 0) len = data.Length; if (len == 0) len = data.Length;
byte lrc = 0; byte lrc = 0;
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++) {
{ lrc += data[i]; } lrc += data[i];
}
lrc = (byte)((lrc ^ 0xFF) + 1); lrc = (byte) ((lrc ^ 0xFF) + 1);
return lrc; return lrc;
} }
@ -746,15 +686,13 @@ namespace DataService
/// </summary> /// </summary>
/// <param name="data">The data used in CRC</param> /// <param name="data">The data used in CRC</param>
/// <returns>CRC value</returns> /// <returns>CRC value</returns>
public static byte[] CalculateCrc(byte[] data, int len = 0) public static byte[] CalculateCrc(byte[] data, int len = 0) {
{
if (data == null) if (data == null)
throw new ArgumentNullException("data"); throw new ArgumentNullException("data");
if (len == 0) len = data.Length; if (len == 0) len = data.Length;
ushort crc = ushort.MaxValue; ushort crc = ushort.MaxValue;
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++) {
{ byte tableIndex = (byte) (crc ^ data[i]);
byte tableIndex = (byte)(crc ^ data[i]);
crc >>= 8; crc >>= 8;
crc ^= crcTable[tableIndex]; crc ^= crcTable[tableIndex];
} }
@ -762,50 +700,43 @@ namespace DataService
return BitConverter.GetBytes(crc); return BitConverter.GetBytes(crc);
} }
public static bool CheckSumCRC(byte[] frame) public static bool CheckSumCRC(byte[] frame) {
{
int len = frame.Length; int len = frame.Length;
byte[] chk = CalculateCrc(frame, len - 2); byte[] chk = CalculateCrc(frame, len - 2);
return (chk[0] == frame[len - 2] && chk[1] == frame[len - 1]); return (chk[0] == frame[len - 2] && chk[1] == frame[len - 1]);
} }
public static unsafe short NetToInt16(byte[] value, int startIndex) public static unsafe short NetToInt16(byte[] value, int startIndex) {
{ if (value == null || startIndex > value.Length - 2) {
if (value == null || startIndex > value.Length - 2)
{
throw new NotImplementedException(); throw new NotImplementedException();
} }
fixed (byte* numRef = &(value[startIndex]))
{ fixed (byte* numRef = &(value[startIndex])) {
return (short)((numRef[0] << 8) | numRef[1]); return (short) ((numRef[0] << 8) | numRef[1]);
} }
} }
public static unsafe int NetToInt32(byte[] value, int startIndex) public static unsafe int NetToInt32(byte[] value, int startIndex) {
{ if (value == null || startIndex > value.Length - 4) {
if (value == null || startIndex > value.Length - 4)
{
throw new NotImplementedException(); throw new NotImplementedException();
} }
fixed (byte* numRef = &(value[startIndex]))
{ fixed (byte* numRef = &(value[startIndex])) {
return (int)((numRef[0] << 24) | (numRef[1] << 16) | (numRef[2] << 8) | numRef[3]); return (int) ((numRef[0] << 24) | (numRef[1] << 16) | (numRef[2] << 8) | numRef[3]);
} }
} }
public static unsafe float NetToSingle(byte[] value, int startIndex) public static unsafe float NetToSingle(byte[] value, int startIndex) {
{
int a = NetToInt32(value, startIndex); int a = NetToInt32(value, startIndex);
return *(float*)&a; return *(float*) &a;
} }
public static string ConvertToString(byte[] bytes, int start = 0, int len = 0) public static string ConvertToString(byte[] bytes, int start = 0, int len = 0) {
{
//西门子300、400 //西门子300、400
if (bytes == null || bytes.Length == 0) if (bytes == null || bytes.Length == 0)
return string.Empty; return string.Empty;
var klen = bytes[start + 1]; var klen = bytes[start + 1];
return Encoding.ASCII.GetString(bytes, start + 2, klen).Trim((char)0); return Encoding.ASCII.GetString(bytes, start + 2, klen).Trim((char) 0);
} }
} }
} }

49
SCADA/Program/DataService/HistoryData.cs

@ -1,83 +1,68 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace DataService namespace DataService {
{ public struct HistoryData : IComparable<HistoryData> {
public struct HistoryData : IComparable<HistoryData>
{
public short ID; public short ID;
public QUALITIES Quality; public QUALITIES Quality;
public Storage Value; public Storage Value;
public DateTime TimeStamp; public DateTime TimeStamp;
public HistoryData(short id, QUALITIES qualitie, Storage value, DateTime timeStamp) public HistoryData(short id, QUALITIES qualitie, Storage value, DateTime timeStamp) {
{
ID = id; ID = id;
Quality = qualitie; Quality = qualitie;
Value = value; Value = value;
TimeStamp = timeStamp; TimeStamp = timeStamp;
} }
public override bool Equals(object obj) public override bool Equals(object obj) {
{
if (obj == null) return false; if (obj == null) return false;
if (obj is HistoryData) if (obj is HistoryData) {
{ return this == (HistoryData) obj;
return this == (HistoryData)obj; } else return false;
}
else return false;
} }
public override int GetHashCode() public override int GetHashCode() {
{
return ID.GetHashCode() ^ TimeStamp.GetHashCode(); return ID.GetHashCode() ^ TimeStamp.GetHashCode();
} }
public static bool operator ==(HistoryData x, HistoryData y) public static bool operator ==(HistoryData x, HistoryData y) {
{
return x.ID == y.ID && x.TimeStamp == y.TimeStamp; return x.ID == y.ID && x.TimeStamp == y.TimeStamp;
} }
public static bool operator !=(HistoryData x, HistoryData y) public static bool operator !=(HistoryData x, HistoryData y) {
{
return x.ID != y.ID || x.TimeStamp != y.TimeStamp; return x.ID != y.ID || x.TimeStamp != y.TimeStamp;
} }
public static readonly HistoryData Empty = new HistoryData(); public static readonly HistoryData Empty = new HistoryData();
public int CompareTo(HistoryData other) public int CompareTo(HistoryData other) {
{
int comp = this.TimeStamp.CompareTo(other.TimeStamp); int comp = this.TimeStamp.CompareTo(other.TimeStamp);
return comp == 0 ? this.ID.CompareTo(other.ID) : comp; return comp == 0 ? this.ID.CompareTo(other.ID) : comp;
} }
} }
public struct FileData : IComparable<FileData> public struct FileData : IComparable<FileData> {
{
public short ID; public short ID;
public Storage Value; public Storage Value;
public string Text; public string Text;
public FileData(short id, Storage value, string text) public FileData(short id, Storage value, string text) {
{
ID = id; ID = id;
Value = value; Value = value;
Text = text; Text = text;
} }
public int CompareTo(FileData other) public int CompareTo(FileData other) {
{
return this.ID.CompareTo(other.ID); return this.ID.CompareTo(other.ID);
} }
} }
public class CompareHistoryData : IComparer<HistoryData> public class CompareHistoryData : IComparer<HistoryData> {
{ public int Compare(HistoryData x, HistoryData y) {
public int Compare(HistoryData x, HistoryData y)
{
int c1 = x.TimeStamp.CompareTo(y.TimeStamp); int c1 = x.TimeStamp.CompareTo(y.TimeStamp);
return c1 == 0 ? x.ID.CompareTo(y.ID) : c1; return c1 == 0 ? x.ID.CompareTo(y.ID) : c1;
} }
} }
} }

21
SCADA/Program/DataService/IGroup.cs

@ -1,10 +1,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace DataService namespace DataService {
{ public interface IGroup : IDisposable {
public interface IGroup : IDisposable
{
bool IsActive { get; set; } bool IsActive { get; set; }
short ID { get; } short ID { get; }
int UpdateRate { get; set; } int UpdateRate { get; set; }
@ -35,10 +33,8 @@ namespace DataService
event DataChangeEventHandler DataChange; event DataChangeEventHandler DataChange;
} }
public class DataChangeEventArgs : EventArgs public class DataChangeEventArgs : EventArgs {
{ public DataChangeEventArgs(int transactionID, IList<HistoryData> pValues) {
public DataChangeEventArgs(int transactionID, IList<HistoryData> pValues)
{
this.TransactionID = transactionID; this.TransactionID = transactionID;
this.Values = pValues; this.Values = pValues;
} }
@ -47,10 +43,8 @@ namespace DataService
public IList<HistoryData> Values; public IList<HistoryData> Values;
} }
public class WriteCompleteEventArgs : EventArgs public class WriteCompleteEventArgs : EventArgs {
{ public WriteCompleteEventArgs(int transactionID, short[] pIds, int[] errors) {
public WriteCompleteEventArgs(int transactionID, short[] pIds, int[] errors)
{
this.TransactionID = transactionID; this.TransactionID = transactionID;
this.Values = pIds; this.Values = pIds;
this.Errors = errors; this.Errors = errors;
@ -66,5 +60,4 @@ namespace DataService
public delegate void ReadCompleteEventHandler(object sender, DataChangeEventArgs e); public delegate void ReadCompleteEventHandler(object sender, DataChangeEventArgs e);
public delegate void WriteCompleteEventHandler(object sender, WriteCompleteEventArgs e); public delegate void WriteCompleteEventHandler(object sender, WriteCompleteEventArgs e);
}
}

33
SCADA/Program/DataService/IReader.cs

@ -1,10 +1,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace DataService namespace DataService {
{ public interface IReaderWriter {
public interface IReaderWriter
{
byte[] ReadBytes(DeviceAddress address, ushort size); byte[] ReadBytes(DeviceAddress address, ushort size);
ItemData<int> ReadInt32(DeviceAddress address); ItemData<int> ReadInt32(DeviceAddress address);
ItemData<short> ReadInt16(DeviceAddress address); ItemData<short> ReadInt16(DeviceAddress address);
@ -25,26 +23,23 @@ namespace DataService
} }
public interface ICache : IReaderWriter public interface ICache : IReaderWriter {
{
int Size { get; set; } int Size { get; set; }
int ByteCount { get; } int ByteCount { get; }
Array Cache { get; } Array Cache { get; }
int GetOffset(DeviceAddress start, DeviceAddress end); int GetOffset(DeviceAddress start, DeviceAddress end);
} }
public interface IMultiReadWrite public interface IMultiReadWrite {
{
int Limit { get; } int Limit { get; }
ItemData<Storage>[] ReadMultiple(DeviceAddress[] addrsArr); ItemData<Storage>[] ReadMultiple(DeviceAddress[] addrsArr);
int WriteMultiple(DeviceAddress[] addrArr, object[] buffer); int WriteMultiple(DeviceAddress[] addrArr, object[] buffer);
} }
public interface IDriver : IDisposable public interface IDriver : IDisposable {
{
short ID { get; } short ID { get; }
string Name { get; } string Name { get; }
string ServerName { get; set; }//可以考虑增加一个附加参数,Sever只定义本机名 string ServerName { get; set; } //可以考虑增加一个附加参数,Sever只定义本机名
bool IsClosed { get; } bool IsClosed { get; }
int TimeOut { get; set; } int TimeOut { get; set; }
IEnumerable<IGroup> Groups { get; } IEnumerable<IGroup> Groups { get; }
@ -55,28 +50,26 @@ namespace DataService
event ShutdownRequestEventHandler OnClose; event ShutdownRequestEventHandler OnClose;
} }
public interface IPLCDriver : IDriver, IReaderWriter public interface IPLCDriver : IDriver, IReaderWriter {
{
int PDU { get; } int PDU { get; }
DeviceAddress GetDeviceAddress(string address); DeviceAddress GetDeviceAddress(string address);
string GetAddress(DeviceAddress address); string GetAddress(DeviceAddress address);
} }
public interface IFileDriver : IDriver, IReaderWriter public interface IFileDriver : IDriver, IReaderWriter {
{
string FileName { get; set; } string FileName { get; set; }
FileData[] ReadAll(short groupId); FileData[] ReadAll(short groupId);
//bool RecieveData(string data); //bool RecieveData(string data);
} }
public class ShutdownRequestEventArgs : EventArgs public class ShutdownRequestEventArgs : EventArgs {
{ public ShutdownRequestEventArgs(string reson) {
public ShutdownRequestEventArgs(string reson)
{
shutdownReason = reson; shutdownReason = reson;
} }
public string shutdownReason; public string shutdownReason;
} }
public delegate void ShutdownRequestEventHandler(object sender, ShutdownRequestEventArgs e); public delegate void ShutdownRequestEventHandler(object sender, ShutdownRequestEventArgs e);
} }

32
SCADA/Program/DataService/IServer.cs

@ -1,20 +1,18 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace DataService namespace DataService {
{
//历史数据、报警数据的提交和数据均从服务器 //历史数据、报警数据的提交和数据均从服务器
public interface IHDAServer : IDisposable public interface IHDAServer : IDisposable {
{
IEnumerable<HistoryData> ReadAtTime(params DateTime[] timeStamps); IEnumerable<HistoryData> ReadAtTime(params DateTime[] timeStamps);
IEnumerable<HistoryData> ReadAtTime(short ID, params DateTime[] timeStamps); IEnumerable<HistoryData> ReadAtTime(short ID, params DateTime[] timeStamps);
IEnumerable<HistoryData> ReadRaw(DateTime start, DateTime end); IEnumerable<HistoryData> ReadRaw(DateTime start, DateTime end);
IEnumerable<HistoryData> ReadRaw(DateTime start, DateTime end, short ID); IEnumerable<HistoryData> ReadRaw(DateTime start, DateTime end, short ID);
//IEnumerable<HistoryData> ReadProcessed(DateTime start, DateTime end, HDAAggregate aggregates, params short[] aggregateIDs); //IEnumerable<HistoryData> ReadProcessed(DateTime start, DateTime end, HDAAggregate aggregates, params short[] aggregateIDs);
} }
public interface IAlarmServer : IDisposable public interface IAlarmServer : IDisposable {
{
int DisableCondition(string sourceName, AlarmType type); int DisableCondition(string sourceName, AlarmType type);
int EnableCondition(string sourceName, AlarmType type); int EnableCondition(string sourceName, AlarmType type);
int RemoveConditon(string sourceName, AlarmType type); int RemoveConditon(string sourceName, AlarmType type);
@ -26,21 +24,22 @@ namespace DataService
IList<ICondition> ActivedConditionList { get; } IList<ICondition> ActivedConditionList { get; }
} }
public interface IDataServer : IDisposable public interface IDataServer : IDisposable {
{
ITag this[short id] { get; } ITag this[short id] { get; }
ITag this[string name] { get; } ITag this[string name] { get; }
ExpressionEval Eval { get; } ExpressionEval Eval { get; }
Object SyncRoot { get; }//对所有涉及集合更改项目使用;包括IGROUP的ADDITEMS Object SyncRoot { get; } //对所有涉及集合更改项目使用;包括IGROUP的ADDITEMS
IList<TagMetaData> MetaDataList { get; } IList<TagMetaData> MetaDataList { get; }
IList<Scaling> ScalingList { get; } IList<Scaling> ScalingList { get; }
IEnumerable<IDriver> Drivers { get; } IEnumerable<IDriver> Drivers { get; }
IEnumerable<string> BrowseItems(BrowseType browseType, string tagName, DataType dataType); IEnumerable<string> BrowseItems(BrowseType browseType, string tagName, DataType dataType);
IDriver AddDriver(short id, string name, string server, int timeOut, IDriver AddDriver(short id, string name, string server, int timeOut,
string assembly, string className, string spare1, string spare2); string assembly, string className, string spare1, string spare2);
IGroup GetGroupByName(string name); IGroup GetGroupByName(string name);
int GetScaleByID(short id); int GetScaleByID(short id);
int GetItemProperties(short id);//返回的是元数据在元数据列表的索引 int GetItemProperties(short id); //返回的是元数据在元数据列表的索引
bool RemoveDriver(IDriver device); bool RemoveDriver(IDriver device);
bool AddItemIndex(string key, ITag value); bool AddItemIndex(string key, ITag value);
bool RemoveItemIndex(string key); bool RemoveItemIndex(string key);
@ -49,23 +48,21 @@ namespace DataService
HistoryData[] BatchRead(DataSource source, bool sync, params ITag[] itemArray); HistoryData[] BatchRead(DataSource source, bool sync, params ITag[] itemArray);
} }
public class FCTCOMMAND public class FCTCOMMAND {
{ public const byte fctHead = 0xAB; //报头可加密,如报头不符,则不进行任何操作;客户端Socket发送报警请求,封装于Server
public const byte fctHead = 0xAB;//报头可加密,如报头不符,则不进行任何操作;客户端Socket发送报警请求,封装于Server
public const byte fctHdaIdRequest = 30; public const byte fctHdaIdRequest = 30;
public const byte fctHdaRequest = 31; public const byte fctHdaRequest = 31;
public const byte fctAlarmRequest = 32; public const byte fctAlarmRequest = 32;
public const byte fctOrderChange = 33; public const byte fctOrderChange = 33;
public const byte fctReset = 34; public const byte fctReset = 34;
public const byte fctXMLHead = 0xEE;//xml协议 public const byte fctXMLHead = 0xEE; //xml协议
public const byte fctReadSingle = 1; public const byte fctReadSingle = 1;
public const byte fctReadMultiple = 2; public const byte fctReadMultiple = 2;
public const byte fctWriteSingle = 5; public const byte fctWriteSingle = 5;
public const byte fctWriteMultiple = 15; public const byte fctWriteMultiple = 15;
} }
public enum HDAAggregate public enum HDAAggregate {
{
HDANoAggregate, HDANoAggregate,
HDAInterpolative, HDAInterpolative,
HDATotal, HDATotal,
@ -93,8 +90,7 @@ namespace DataService
HDAAnnotations, HDAAnnotations,
} }
public enum BrowseType public enum BrowseType {
{
Branch = 1, Branch = 1,
Leaf = 2, Leaf = 2,
Flat = 3 Flat = 3

419
SCADA/Program/DataService/ITag.cs

@ -1,102 +1,72 @@
using System; using System;
namespace DataService namespace DataService {
{ public abstract class ITag : IComparable<ITag> {
public abstract class ITag : IComparable<ITag>
{
protected short _id; protected short _id;
public short ID
{ public short ID {
get get { return _id; }
{
return _id;
}
} }
protected bool _active = true; protected bool _active = true;
public bool Active
{ public bool Active {
get get { return _active; }
{ set {
return _active;
}
set
{
_group.SetActiveState(value, _id); _group.SetActiveState(value, _id);
_active = value; _active = value;
} }
} }
protected QUALITIES _quality; protected QUALITIES _quality;
public QUALITIES Quality
{ public QUALITIES Quality {
get get { return _quality; }
{
return _quality;
}
} }
protected Storage _value; protected Storage _value;
public Storage Value
{ public Storage Value {
get get { return _value; }
{
return _value;
}
} }
protected DateTime _timeStamp = DateTime.MinValue; protected DateTime _timeStamp = DateTime.MinValue;
public DateTime TimeStamp
{ public DateTime TimeStamp {
get get { return _timeStamp; }
{
return _timeStamp;
}
} }
protected DeviceAddress _plcAddress; protected DeviceAddress _plcAddress;
public DeviceAddress Address
{ public DeviceAddress Address {
get get { return _plcAddress; }
{ set { _plcAddress = value; }
return _plcAddress;
}
set
{
_plcAddress = value;
}
} }
protected IGroup _group; protected IGroup _group;
public IGroup Parent
{ public IGroup Parent {
get get { return _group; }
{
return _group;
}
} }
protected ITag(short id, DeviceAddress address, IGroup group) protected ITag(short id, DeviceAddress address, IGroup group) {
{
_id = id; _id = id;
_group = group; _group = group;
_plcAddress = address; _plcAddress = address;
} }
public void Update(Storage newvalue, DateTime timeStamp, QUALITIES quality) public void Update(Storage newvalue, DateTime timeStamp, QUALITIES quality) {
{ if (_timeStamp > timeStamp) return; //如果时间戳更旧或值未改变
if (_timeStamp > timeStamp) return;//如果时间戳更旧或值未改变 if (ValueChanging != null) {
if (ValueChanging != null) ValueChanging(this,
{ new ValueChangingEventArgs<Storage>(quality, _value, newvalue, _timeStamp, timeStamp));
ValueChanging(this, new ValueChangingEventArgs<Storage>(quality, _value, newvalue, _timeStamp, timeStamp));
} }
_timeStamp = timeStamp; _timeStamp = timeStamp;
_quality = quality; _quality = quality;
if (quality == QUALITIES.QUALITY_GOOD) if (quality == QUALITIES.QUALITY_GOOD) {
{
_value = newvalue; _value = newvalue;
if (ValueChanged != null) if (ValueChanged != null) {
{
ValueChanged(this, new ValueChangedEventArgs(_value)); ValueChanged(this, new ValueChangedEventArgs(_value));
} }
} }
@ -110,33 +80,33 @@ namespace DataService
public abstract int Write(object value); public abstract int Write(object value);
public int Write(Storage value, bool bForce) public int Write(Storage value, bool bForce) {
{
DateTime time = DateTime.Now; DateTime time = DateTime.Now;
_timeStamp = time; _timeStamp = time;
if (bForce) if (bForce) {
{ if (ValueChanging != null) {
if (ValueChanging != null) ValueChanging(this,
{ new ValueChangingEventArgs<Storage>(QUALITIES.QUALITY_GOOD, _value, value, _timeStamp, time));
ValueChanging(this, new ValueChangingEventArgs<Storage>(QUALITIES.QUALITY_GOOD, _value, value, _timeStamp, time));
} }
} }
int result = InnerWrite(value); int result = InnerWrite(value);
if (bForce || result != 0) if (bForce || result != 0) {
{
var data = Read(DataSource.Device); var data = Read(DataSource.Device);
if (data != value) if (data != value) {
{
time = DateTime.Now; time = DateTime.Now;
if (ValueChanging != null) if (ValueChanging != null) {
{ ValueChanging(this,
ValueChanging(this, new ValueChangingEventArgs<Storage>(QUALITIES.QUALITY_GOOD, _value, data, _timeStamp, time)); new ValueChangingEventArgs<Storage>(QUALITIES.QUALITY_GOOD, _value, data, _timeStamp,
time));
} }
_value = data; _value = data;
_timeStamp = time; _timeStamp = time;
return result; return result;
} }
} }
return 0; return 0;
} }
@ -146,64 +116,56 @@ namespace DataService
#region IComparable<PLCAddress> Members #region IComparable<PLCAddress> Members
public override int GetHashCode() public override int GetHashCode() {
{
return _id.GetHashCode(); return _id.GetHashCode();
} }
public int CompareTo(ITag other) public int CompareTo(ITag other) {
{
return _plcAddress.CompareTo(other._plcAddress); return _plcAddress.CompareTo(other._plcAddress);
} }
#endregion #endregion
} }
public sealed class BoolTag : ITag public sealed class BoolTag : ITag {
{
public BoolTag(short id, DeviceAddress addr, IGroup group) public BoolTag(short id, DeviceAddress addr, IGroup group)
: base(id, addr, group) : base(id, addr, group) { }
{
}
#region IDevice Members #region IDevice Members
public override bool Refresh(DataSource source = DataSource.Cache) public override bool Refresh(DataSource source = DataSource.Cache) {
{
var _newvalue = _group.ReadBool(_plcAddress, source); var _newvalue = _group.ReadBool(_plcAddress, source);
if (_newvalue.Value != _value.Boolean) if (_newvalue.Value != _value.Boolean) {
{
Storage value = Storage.Empty; Storage value = Storage.Empty;
value.Boolean = _newvalue.Value; value.Boolean = _newvalue.Value;
DateTime time = _newvalue.TimeStamp.ToDateTime(); DateTime time = _newvalue.TimeStamp.ToDateTime();
if (ValueChanging != null) if (ValueChanging != null) {
{ ValueChanging(this,
ValueChanging(this, new ValueChangingEventArgs<Storage>(_newvalue.Quality, _value, value, _timeStamp, time)); new ValueChangingEventArgs<Storage>(_newvalue.Quality, _value, value, _timeStamp, time));
} }
_timeStamp = time; _timeStamp = time;
_quality = _newvalue.Quality; _quality = _newvalue.Quality;
if (_quality == QUALITIES.QUALITY_GOOD) if (_quality == QUALITIES.QUALITY_GOOD) {
{
_value = value; _value = value;
if (ValueChanged != null) if (ValueChanged != null) {
{
ValueChanged(this, new ValueChangedEventArgs(value)); ValueChanged(this, new ValueChangedEventArgs(value));
} }
} }
return true; return true;
} }
return false; return false;
} }
public override Storage Read(DataSource source = DataSource.Cache) public override Storage Read(DataSource source = DataSource.Cache) {
{
Storage value = Storage.Empty; Storage value = Storage.Empty;
value.Boolean = _group.ReadBool(_plcAddress, source).Value; value.Boolean = _group.ReadBool(_plcAddress, source).Value;
return value; return value;
} }
public override int Write(object value) public override int Write(object value) {
{
if (value == null) return -1; if (value == null) return -1;
bool temp = _value.Boolean; bool temp = _value.Boolean;
var str = value as string; var str = value as string;
@ -215,65 +177,57 @@ namespace DataService
return _group.WriteBit(_plcAddress, temp); return _group.WriteBit(_plcAddress, temp);
} }
protected override int InnerWrite(Storage value) protected override int InnerWrite(Storage value) {
{
return _group.WriteBit(_plcAddress, value.Boolean); return _group.WriteBit(_plcAddress, value.Boolean);
} }
#endregion #endregion
public override string ToString() public override string ToString() {
{
return _value.Boolean.ToString(); return _value.Boolean.ToString();
} }
} }
public sealed class ByteTag : ITag public sealed class ByteTag : ITag {
{
public ByteTag(short id, DeviceAddress addr, IGroup group) public ByteTag(short id, DeviceAddress addr, IGroup group)
: base(id, addr, group) : base(id, addr, group) { }
{
}
#region IDevice Members #region IDevice Members
public override bool Refresh(DataSource source = DataSource.Device)
{ public override bool Refresh(DataSource source = DataSource.Device) {
var _newvalue = _group.ReadByte(_plcAddress, source); var _newvalue = _group.ReadByte(_plcAddress, source);
if (_newvalue.Value != _value.Byte) if (_newvalue.Value != _value.Byte) {
{
Storage value = Storage.Empty; Storage value = Storage.Empty;
value.Byte = _newvalue.Value; value.Byte = _newvalue.Value;
DateTime time = _newvalue.TimeStamp.ToDateTime(); DateTime time = _newvalue.TimeStamp.ToDateTime();
if (ValueChanging != null) if (ValueChanging != null) {
{ ValueChanging(this,
ValueChanging(this, new ValueChangingEventArgs<Storage>(_newvalue.Quality, _value, value, _timeStamp, time)); new ValueChangingEventArgs<Storage>(_newvalue.Quality, _value, value, _timeStamp, time));
} }
_timeStamp = time; _timeStamp = time;
_quality = _newvalue.Quality; _quality = _newvalue.Quality;
if (_quality == QUALITIES.QUALITY_GOOD) if (_quality == QUALITIES.QUALITY_GOOD) {
{
_value = value; _value = value;
if (ValueChanged != null) if (ValueChanged != null) {
{
ValueChanged(this, new ValueChangedEventArgs(value)); ValueChanged(this, new ValueChangedEventArgs(value));
} }
} }
return true; return true;
} }
return false; return false;
} }
public override Storage Read(DataSource source = DataSource.Cache) public override Storage Read(DataSource source = DataSource.Cache) {
{
Storage value = Storage.Empty; Storage value = Storage.Empty;
value.Byte = _group.ReadByte(_plcAddress, source).Value; value.Byte = _group.ReadByte(_plcAddress, source).Value;
return value; return value;
} }
public override int Write(object value) public override int Write(object value) {
{
byte temp = _value.Byte; byte temp = _value.Byte;
var str = value as string; var str = value as string;
if (str == null) if (str == null)
@ -284,65 +238,57 @@ namespace DataService
return _group.WriteBits(_plcAddress, temp); return _group.WriteBits(_plcAddress, temp);
} }
protected override int InnerWrite(Storage value) protected override int InnerWrite(Storage value) {
{
return _group.WriteBits(_plcAddress, value.Byte); return _group.WriteBits(_plcAddress, value.Byte);
} }
#endregion #endregion
public override string ToString() public override string ToString() {
{
return _value.Byte.ToString(); return _value.Byte.ToString();
} }
} }
public sealed class ShortTag : ITag public sealed class ShortTag : ITag {
{
public ShortTag(short id, DeviceAddress addr, IGroup group) public ShortTag(short id, DeviceAddress addr, IGroup group)
: base(id, addr, group) : base(id, addr, group) { }
{
}
#region IDevice Members #region IDevice Members
public override bool Refresh(DataSource source = DataSource.Device)
{ public override bool Refresh(DataSource source = DataSource.Device) {
var _newvalue = _group.ReadInt16(_plcAddress, source); var _newvalue = _group.ReadInt16(_plcAddress, source);
if (_newvalue.Value != _value.Int16) if (_newvalue.Value != _value.Int16) {
{
Storage value = Storage.Empty; Storage value = Storage.Empty;
value.Int16 = _newvalue.Value; value.Int16 = _newvalue.Value;
DateTime time = _newvalue.TimeStamp.ToDateTime(); DateTime time = _newvalue.TimeStamp.ToDateTime();
if (ValueChanging != null) if (ValueChanging != null) {
{ ValueChanging(this,
ValueChanging(this, new ValueChangingEventArgs<Storage>(_newvalue.Quality, _value, value, _timeStamp, time)); new ValueChangingEventArgs<Storage>(_newvalue.Quality, _value, value, _timeStamp, time));
} }
_timeStamp = time; _timeStamp = time;
_quality = _newvalue.Quality; _quality = _newvalue.Quality;
if (_quality == QUALITIES.QUALITY_GOOD) if (_quality == QUALITIES.QUALITY_GOOD) {
{
_value = value; _value = value;
if (ValueChanged != null) if (ValueChanged != null) {
{
ValueChanged(this, new ValueChangedEventArgs(value)); ValueChanged(this, new ValueChangedEventArgs(value));
} }
} }
return true; return true;
} }
return false; return false;
} }
public override Storage Read(DataSource source = DataSource.Cache) public override Storage Read(DataSource source = DataSource.Cache) {
{
Storage value = Storage.Empty; Storage value = Storage.Empty;
value.Int16 = _group.ReadInt16(_plcAddress, source).Value; value.Int16 = _group.ReadInt16(_plcAddress, source).Value;
return value; return value;
} }
public override int Write(object value) public override int Write(object value) {
{
var temp = _value.Int16; var temp = _value.Int16;
var str = value as string; var str = value as string;
if (str == null) if (str == null)
@ -353,64 +299,56 @@ namespace DataService
return _group.WriteInt16(_plcAddress, temp); return _group.WriteInt16(_plcAddress, temp);
} }
protected override int InnerWrite(Storage value) protected override int InnerWrite(Storage value) {
{
return _group.WriteInt16(_plcAddress, value.Int16); return _group.WriteInt16(_plcAddress, value.Int16);
} }
#endregion #endregion
public override string ToString() public override string ToString() {
{
return _value.Int16.ToString(); return _value.Int16.ToString();
} }
} }
public sealed class IntTag : ITag public sealed class IntTag : ITag {
{
public IntTag(short id, DeviceAddress addr, IGroup group) public IntTag(short id, DeviceAddress addr, IGroup group)
: base(id, addr, group) : base(id, addr, group) { }
{
}
#region IDevice Members #region IDevice Members
public override bool Refresh(DataSource source = DataSource.Device)
{ public override bool Refresh(DataSource source = DataSource.Device) {
var _newvalue = _group.ReadInt32(_plcAddress, source); var _newvalue = _group.ReadInt32(_plcAddress, source);
if (_newvalue.Value != _value.Int32) if (_newvalue.Value != _value.Int32) {
{
Storage value = Storage.Empty; Storage value = Storage.Empty;
value.Int32 = _newvalue.Value; value.Int32 = _newvalue.Value;
DateTime time = _newvalue.TimeStamp.ToDateTime(); DateTime time = _newvalue.TimeStamp.ToDateTime();
if (ValueChanging != null) if (ValueChanging != null) {
{ ValueChanging(this,
ValueChanging(this, new ValueChangingEventArgs<Storage>(_newvalue.Quality, _value, value, _timeStamp, time)); new ValueChangingEventArgs<Storage>(_newvalue.Quality, _value, value, _timeStamp, time));
} }
_timeStamp = time; _timeStamp = time;
_quality = _newvalue.Quality; _quality = _newvalue.Quality;
if (_quality == QUALITIES.QUALITY_GOOD) if (_quality == QUALITIES.QUALITY_GOOD) {
{
_value = value; _value = value;
if (ValueChanged != null) if (ValueChanged != null) {
{
ValueChanged(this, new ValueChangedEventArgs(value)); ValueChanged(this, new ValueChangedEventArgs(value));
} }
} }
return true; return true;
} }
return false; return false;
} }
public override Storage Read(DataSource source = DataSource.Cache) public override Storage Read(DataSource source = DataSource.Cache) {
{
Storage value = Storage.Empty; Storage value = Storage.Empty;
value.Int32 = _group.ReadInt32(_plcAddress, source).Value; value.Int32 = _group.ReadInt32(_plcAddress, source).Value;
return value; return value;
} }
public override int Write(object value) public override int Write(object value) {
{
var temp = _value.Int32; var temp = _value.Int32;
var str = value as string; var str = value as string;
if (str == null) if (str == null)
@ -421,65 +359,57 @@ namespace DataService
return _group.WriteInt32(_plcAddress, temp); return _group.WriteInt32(_plcAddress, temp);
} }
protected override int InnerWrite(Storage value) protected override int InnerWrite(Storage value) {
{
return _group.WriteInt32(_plcAddress, value.Int32); return _group.WriteInt32(_plcAddress, value.Int32);
} }
#endregion #endregion
public override string ToString() public override string ToString() {
{
return _value.Int32.ToString(); return _value.Int32.ToString();
} }
} }
public sealed class FloatTag : ITag public sealed class FloatTag : ITag {
{
public FloatTag(short id, DeviceAddress addr, IGroup group) public FloatTag(short id, DeviceAddress addr, IGroup group)
: base(id, addr, group) : base(id, addr, group) { }
{
}
#region IDevice Members #region IDevice Members
public override bool Refresh(DataSource source = DataSource.Device)
{ public override bool Refresh(DataSource source = DataSource.Device) {
var _newvalue = _group.ReadFloat(_plcAddress, source); var _newvalue = _group.ReadFloat(_plcAddress, source);
if (_newvalue.Value != _value.Single) if (_newvalue.Value != _value.Single) {
{
Storage value = Storage.Empty; Storage value = Storage.Empty;
value.Single = _newvalue.Value; value.Single = _newvalue.Value;
DateTime time = _newvalue.TimeStamp.ToDateTime(); DateTime time = _newvalue.TimeStamp.ToDateTime();
if (ValueChanging != null) if (ValueChanging != null) {
{ ValueChanging(this,
ValueChanging(this, new ValueChangingEventArgs<Storage>(_newvalue.Quality, _value, value, _timeStamp, time)); new ValueChangingEventArgs<Storage>(_newvalue.Quality, _value, value, _timeStamp, time));
} }
_timeStamp = time; _timeStamp = time;
_quality = _newvalue.Quality; _quality = _newvalue.Quality;
if (_quality == QUALITIES.QUALITY_GOOD) if (_quality == QUALITIES.QUALITY_GOOD) {
{
_value = value; _value = value;
if (ValueChanged != null) if (ValueChanged != null) {
{
ValueChanged(this, new ValueChangedEventArgs(value)); ValueChanged(this, new ValueChangedEventArgs(value));
} }
} }
return true; return true;
} }
return false; return false;
} }
public override Storage Read(DataSource source = DataSource.Cache) public override Storage Read(DataSource source = DataSource.Cache) {
{
Storage value = Storage.Empty; Storage value = Storage.Empty;
value.Single = _group.ReadFloat(_plcAddress, source).Value; value.Single = _group.ReadFloat(_plcAddress, source).Value;
return value; return value;
} }
public override int Write(object value) public override int Write(object value) {
{
var temp = _value.Single; var temp = _value.Single;
var str = value as string; var str = value as string;
if (str == null) if (str == null)
@ -490,103 +420,86 @@ namespace DataService
return _group.WriteFloat(_plcAddress, temp); return _group.WriteFloat(_plcAddress, temp);
} }
protected override int InnerWrite(Storage value) protected override int InnerWrite(Storage value) {
{
return _group.WriteFloat(_plcAddress, value.Single); return _group.WriteFloat(_plcAddress, value.Single);
} }
#endregion #endregion
public override string ToString() public override string ToString() {
{
return _value.Single.ToString(); return _value.Single.ToString();
} }
} }
public sealed class StringTag : ITag public sealed class StringTag : ITag {
{
string _str; string _str;
public string String
{ public string String {
get get { return _str; }
{ set { _str = value; }
return _str;
}
set
{
_str = value;
}
} }
public StringTag(short id, DeviceAddress addr, IGroup group) public StringTag(short id, DeviceAddress addr, IGroup group)
: base(id, addr, group) : base(id, addr, group) { }
{
}
#region IDevice Members #region IDevice Members
public override bool Refresh(DataSource source = DataSource.Device)
{ public override bool Refresh(DataSource source = DataSource.Device) {
var _newvalue = _group.ReadString(_plcAddress, source); var _newvalue = _group.ReadString(_plcAddress, source);
if (_newvalue.Value != _str) if (_newvalue.Value != _str) {
{
DateTime time = _newvalue.TimeStamp.ToDateTime(); DateTime time = _newvalue.TimeStamp.ToDateTime();
if (ValueChanging != null) if (ValueChanging != null) {
{ ValueChanging(this,
ValueChanging(this, new ValueChangingEventArgs<Storage>(_newvalue.Quality, _value, _value, _timeStamp, time)); new ValueChangingEventArgs<Storage>(_newvalue.Quality, _value, _value, _timeStamp, time));
} }
_timeStamp = time; _timeStamp = time;
_quality = _newvalue.Quality; _quality = _newvalue.Quality;
if (_quality == QUALITIES.QUALITY_GOOD) if (_quality == QUALITIES.QUALITY_GOOD) {
{
_str = _newvalue.Value; _str = _newvalue.Value;
if (ValueChanged != null) if (ValueChanged != null) {
{
ValueChanged(this, new ValueChangedEventArgs(_value)); ValueChanged(this, new ValueChangedEventArgs(_value));
} }
} }
return true; return true;
} }
return false; return false;
} }
public override Storage Read(DataSource source = DataSource.Cache) public override Storage Read(DataSource source = DataSource.Cache) {
{
var value = _group.ReadString(_plcAddress, source); var value = _group.ReadString(_plcAddress, source);
if (value.Quality == QUALITIES.QUALITY_GOOD) if (value.Quality == QUALITIES.QUALITY_GOOD)
_str = value.Value; _str = value.Value;
return Storage.Empty; return Storage.Empty;
} }
public override int Write(object value) public override int Write(object value) {
{
if (value == null) return -1; if (value == null) return -1;
var str = (value is String) ? (String)value : value.ToString(); var str = (value is String) ? (String) value : value.ToString();
_timeStamp = DateTime.Now; _timeStamp = DateTime.Now;
return _group.WriteString(_plcAddress, str); return _group.WriteString(_plcAddress, str);
} }
protected override int InnerWrite(Storage value) protected override int InnerWrite(Storage value) {
{
return _group.WriteString(_plcAddress, _str); return _group.WriteString(_plcAddress, _str);
} }
#endregion #endregion
public override string ToString() public override string ToString() {
{
return _str ?? string.Empty; return _str ?? string.Empty;
} }
} }
public enum DataSource public enum DataSource {
{
Cache = 1, Cache = 1,
Device = 2 Device = 2
} }
public enum DataType : byte public enum DataType : byte {
{
NONE = 0, NONE = 0,
BOOL = 1, BOOL = 1,
BYTE = 3, BYTE = 3,
@ -600,12 +513,11 @@ namespace DataService
} }
public delegate void ValueChangingEventHandler<T>(object sender, ValueChangingEventArgs<T> e); public delegate void ValueChangingEventHandler<T>(object sender, ValueChangingEventArgs<T> e);
public delegate void ValueChangedEventHandler(object sender, ValueChangedEventArgs e); public delegate void ValueChangedEventHandler(object sender, ValueChangedEventArgs e);
public class ValueChangingEventArgs<T> : EventArgs public class ValueChangingEventArgs<T> : EventArgs {
{ public ValueChangingEventArgs(QUALITIES quality, T oldValue, T newValue, DateTime oldTime, DateTime newTime) {
public ValueChangingEventArgs(QUALITIES quality, T oldValue, T newValue, DateTime oldTime, DateTime newTime)
{
this.Quality = quality; this.Quality = quality;
this.OldValue = oldValue; this.OldValue = oldValue;
this.NewValue = newValue; this.NewValue = newValue;
@ -620,14 +532,11 @@ namespace DataService
public DateTime NewTimeStamp; public DateTime NewTimeStamp;
} }
public class ValueChangedEventArgs : EventArgs public class ValueChangedEventArgs : EventArgs {
{ public ValueChangedEventArgs(Storage value) {
public ValueChangedEventArgs(Storage value)
{
this.Value = value; this.Value = value;
} }
public Storage Value; public Storage Value;
} }
}
}

520
SCADA/Program/DataService/PLCGroup.cs

@ -2,31 +2,22 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Timers; using System.Timers;
namespace DataService namespace DataService {
{ public class PLCGroup : IGroup {
public class PLCGroup : IGroup
{
protected Timer _timer; protected Timer _timer;
protected bool _isActive; protected bool _isActive;
public virtual bool IsActive
{ public virtual bool IsActive {
get get { return _isActive; }
{ set {
return _isActive;
}
set
{
_isActive = value; _isActive = value;
if (value) if (value) {
{
if (_updateRate <= 0) _updateRate = 100; if (_updateRate <= 0) _updateRate = 100;
_timer.Interval = _updateRate; _timer.Interval = _updateRate;
_timer.Elapsed += new ElapsedEventHandler(timer_Timer); _timer.Elapsed += new ElapsedEventHandler(timer_Timer);
_timer.Start(); _timer.Start();
} } else {
else
{
_timer.Elapsed -= new ElapsedEventHandler(timer_Timer); _timer.Elapsed -= new ElapsedEventHandler(timer_Timer);
_timer.Stop(); _timer.Stop();
} }
@ -34,98 +25,65 @@ namespace DataService
} }
protected short _id; protected short _id;
public short ID
{ public short ID {
get get { return _id; }
{
return _id;
}
} }
protected int _updateRate; protected int _updateRate;
public int UpdateRate
{ public int UpdateRate {
get get { return _updateRate; }
{ set { _updateRate = value; }
return _updateRate;
}
set
{
_updateRate = value;
}
} }
protected string _name; protected string _name;
public string Name
{ public string Name {
get get { return _name; }
{ set { _name = value; }
return _name;
}
set
{
_name = value;
}
} }
protected float _deadband; protected float _deadband;
public float DeadBand
{ public float DeadBand {
get get { return _deadband; }
{ set { _deadband = value; }
return _deadband;
}
set
{
_deadband = value;
}
} }
protected ICache _cacheReader; protected ICache _cacheReader;
protected IPLCDriver _plcReader; protected IPLCDriver _plcReader;
public IDriver Parent
{ public IDriver Parent {
get get { return _plcReader; }
{
return _plcReader;
}
} }
protected List<int> _changedList; protected List<int> _changedList;
public List<int> ChangedList
{ public List<int> ChangedList {
get get { return _changedList; }
{
return _changedList;
}
} }
protected List<ITag> _items; protected List<ITag> _items;
public IEnumerable<ITag> Items
{ public IEnumerable<ITag> Items {
get { return _items; } get { return _items; }
} }
protected IDataServer _server; protected IDataServer _server;
public IDataServer Server
{ public IDataServer Server {
get get { return _server; }
{
return _server;
}
} }
protected List<PDUArea> _rangeList = new List<PDUArea>(); protected List<PDUArea> _rangeList = new List<PDUArea>();
protected PLCGroup() protected PLCGroup() { }
{
}
public PLCGroup(short id, string name, int updateRate, bool active, IPLCDriver plcReader) public PLCGroup(short id, string name, int updateRate, bool active, IPLCDriver plcReader) {
{
this._id = id; this._id = id;
this._name = name; this._name = name;
this._updateRate = updateRate; this._updateRate = updateRate;
@ -137,24 +95,19 @@ namespace DataService
this._timer = new Timer(); this._timer = new Timer();
} }
public bool AddItems(IList<TagMetaData> items) public bool AddItems(IList<TagMetaData> items) {
{
int count = items.Count; int count = items.Count;
if (_items == null) _items = new List<ITag>(count); if (_items == null) _items = new List<ITag>(count);
lock (_server.SyncRoot) lock (_server.SyncRoot) {
{ for (int i = 0; i < count; i++) {
for (int i = 0; i < count; i++)
{
ITag dataItem = null; ITag dataItem = null;
TagMetaData meta = items[i]; TagMetaData meta = items[i];
if (meta.GroupID == this._id) if (meta.GroupID == this._id) {
{
DeviceAddress addr = _plcReader.GetDeviceAddress(meta.Address); DeviceAddress addr = _plcReader.GetDeviceAddress(meta.Address);
if (addr.DataSize == 0) addr.DataSize = meta.Size; if (addr.DataSize == 0) addr.DataSize = meta.Size;
if (addr.VarType == DataType.NONE) addr.VarType = meta.DataType; if (addr.VarType == DataType.NONE) addr.VarType = meta.DataType;
if (addr.VarType != DataType.BOOL) addr.Bit = 0; if (addr.VarType != DataType.BOOL) addr.Bit = 0;
switch (meta.DataType) switch (meta.DataType) {
{
case DataType.BOOL: case DataType.BOOL:
dataItem = new BoolTag(meta.ID, addr, this); dataItem = new BoolTag(meta.ID, addr, this);
break; break;
@ -176,8 +129,8 @@ namespace DataService
dataItem = new StringTag(meta.ID, addr, this); dataItem = new StringTag(meta.ID, addr, this);
break; break;
} }
if (dataItem != null)
{ if (dataItem != null) {
//dataItem.Active = meta.Active; //dataItem.Active = meta.Active;
_items.Add(dataItem); _items.Add(dataItem);
_server.AddItemIndex(meta.Name, dataItem); _server.AddItemIndex(meta.Name, dataItem);
@ -185,217 +138,190 @@ namespace DataService
} }
} }
} }
_items.TrimExcess(); _items.TrimExcess();
_items.Sort(); _items.Sort();
UpdatePDUArea(); UpdatePDUArea();
return true; return true;
} }
public bool AddTags(IEnumerable<ITag> tags) public bool AddTags(IEnumerable<ITag> tags) {
{ if (_items == null) {
if (_items == null)
{
_items = new List<ITag>(); _items = new List<ITag>();
} }
foreach (ITag tag in tags)
{ foreach (ITag tag in tags) {
if (tag != null) if (tag != null) {
{
_items.Add(tag); _items.Add(tag);
} }
} }
_items.TrimExcess(); _items.TrimExcess();
_items.Sort(); _items.Sort();
UpdatePDUArea(); UpdatePDUArea();
return true; return true;
} }
public bool RemoveItems(params ITag[] items) public bool RemoveItems(params ITag[] items) {
{ foreach (var item in items) {
foreach (var item in items)
{
_server.RemoveItemIndex(item.GetTagName()); _server.RemoveItemIndex(item.GetTagName());
_items.Remove(item); _items.Remove(item);
} }
UpdatePDUArea(); UpdatePDUArea();
return true; return true;
} }
protected void UpdatePDUArea() protected void UpdatePDUArea() {
{
int count = _items.Count; int count = _items.Count;
if (count > 0) if (count > 0) {
{
DeviceAddress _start = _items[0].Address; DeviceAddress _start = _items[0].Address;
_start.Bit = 0; _start.Bit = 0;
int bitCount = _cacheReader.ByteCount; int bitCount = _cacheReader.ByteCount;
if (count > 1) if (count > 1) {
{ int cacheLength = 0; //缓冲区的大小
int cacheLength = 0;//缓冲区的大小
int cacheIndexStart = 0; int cacheIndexStart = 0;
int startIndex = 0; int startIndex = 0;
DeviceAddress segmentEnd = DeviceAddress.Empty; DeviceAddress segmentEnd = DeviceAddress.Empty;
DeviceAddress tagAddress = DeviceAddress.Empty; DeviceAddress tagAddress = DeviceAddress.Empty;
DeviceAddress segmentStart = _start; DeviceAddress segmentStart = _start;
for (int j = 1, i = 1; i < count; i++, j++) for (int j = 1,
{ i = 1;
tagAddress = _items[i].Address;//当前变量地址 i < count;
i++, j++) {
tagAddress = _items[i].Address; //当前变量地址
int offset1 = _cacheReader.GetOffset(tagAddress, segmentStart); int offset1 = _cacheReader.GetOffset(tagAddress, segmentStart);
if (offset1 > (_plcReader.PDU - tagAddress.DataSize) / bitCount) if (offset1 > (_plcReader.PDU - tagAddress.DataSize) / bitCount) {
{
segmentEnd = _items[i - 1].Address; segmentEnd = _items[i - 1].Address;
int len = _cacheReader.GetOffset(segmentEnd, segmentStart); int len = _cacheReader.GetOffset(segmentEnd, segmentStart);
len += segmentEnd.DataSize <= bitCount ? 1 : segmentEnd.DataSize / bitCount; len += segmentEnd.DataSize <= bitCount ? 1 : segmentEnd.DataSize / bitCount;
tagAddress.CacheIndex = (ushort)(cacheIndexStart + len); tagAddress.CacheIndex = (ushort) (cacheIndexStart + len);
_items[i].Address = tagAddress; _items[i].Address = tagAddress;
_rangeList.Add(new PDUArea(segmentStart, len, startIndex, j)); _rangeList.Add(new PDUArea(segmentStart, len, startIndex, j));
startIndex += j; j = 0; startIndex += j;
cacheLength += len;//更新缓存长度 j = 0;
cacheLength += len; //更新缓存长度
cacheIndexStart = cacheLength; cacheIndexStart = cacheLength;
segmentStart = tagAddress;//更新数据片段的起始地址 segmentStart = tagAddress; //更新数据片段的起始地址
} } else {
else tagAddress.CacheIndex = (ushort) (cacheIndexStart + offset1);
{
tagAddress.CacheIndex = (ushort)(cacheIndexStart + offset1);
_items[i].Address = tagAddress; _items[i].Address = tagAddress;
} }
if (i == count - 1)
{ if (i == count - 1) {
segmentEnd = _items[i].Address; segmentEnd = _items[i].Address;
int segmentLength = _cacheReader.GetOffset(segmentEnd, segmentStart); int segmentLength = _cacheReader.GetOffset(segmentEnd, segmentStart);
if (segmentLength > (_plcReader.PDU - segmentEnd.DataSize) / bitCount) if (segmentLength > (_plcReader.PDU - segmentEnd.DataSize) / bitCount) {
{
segmentEnd = _items[i - 1].Address; segmentEnd = _items[i - 1].Address;
segmentLength = segmentEnd.DataSize <= bitCount ? 1 : segmentEnd.DataSize / bitCount; segmentLength = segmentEnd.DataSize <= bitCount ? 1 : segmentEnd.DataSize / bitCount;
} }
tagAddress.CacheIndex = (ushort)(cacheIndexStart + segmentLength);
tagAddress.CacheIndex = (ushort) (cacheIndexStart + segmentLength);
_items[i].Address = tagAddress; _items[i].Address = tagAddress;
segmentLength += segmentEnd.DataSize <= bitCount ? 1 : segmentEnd.DataSize / bitCount; segmentLength += segmentEnd.DataSize <= bitCount ? 1 : segmentEnd.DataSize / bitCount;
_rangeList.Add(new PDUArea(segmentStart, segmentLength, startIndex, j + 1)); _rangeList.Add(new PDUArea(segmentStart, segmentLength, startIndex, j + 1));
cacheLength += segmentLength; cacheLength += segmentLength;
} }
} }
_cacheReader.Size = cacheLength; _cacheReader.Size = cacheLength;
} } else {
else var size = _start.DataSize <= bitCount ? 1 : _start.DataSize / bitCount;
{
var size= _start.DataSize <= bitCount ? 1 : _start.DataSize / bitCount;
_rangeList.Add(new PDUArea(_start, size, 0, 1)); _rangeList.Add(new PDUArea(_start, size, 0, 1));
_cacheReader.Size = size;//改变Cache的Size属性值将创建Cache的内存区域 _cacheReader.Size = size; //改变Cache的Size属性值将创建Cache的内存区域
} }
} }
} }
public ITag FindItemByAddress(DeviceAddress addr) public ITag FindItemByAddress(DeviceAddress addr) {
{
int index = _items.BinarySearch(new BoolTag(0, addr, null)); int index = _items.BinarySearch(new BoolTag(0, addr, null));
return index < 0 ? null : _items[index]; return index < 0 ? null : _items[index];
} }
public bool SetActiveState(bool active, params short[] items) public bool SetActiveState(bool active, params short[] items) {
{
return false; return false;
} }
object sync = new object(); object sync = new object();
protected void timer_Timer(object sender, EventArgs e)
{ protected void timer_Timer(object sender, EventArgs e) {
if (_isActive) if (_isActive) {
{ lock (sync) {
lock (sync)
{
Poll(); Poll();
if (_changedList.Count > 0) if (_changedList.Count > 0)
Update(); Update();
} }
} } else
else
return; return;
} }
protected virtual int Poll() protected virtual int Poll() {
{
if (_plcReader.IsClosed) return -1; if (_plcReader.IsClosed) return -1;
byte[] cache = (byte[])_cacheReader.Cache; byte[] cache = (byte[]) _cacheReader.Cache;
int offset = 0; int offset = 0;
foreach (PDUArea area in _rangeList) foreach (PDUArea area in _rangeList) {
{ byte[] rcvBytes = _plcReader.ReadBytes(area.Start, (ushort) area.Len); //从PLC读取数据
byte[] rcvBytes = _plcReader.ReadBytes(area.Start, (ushort)area.Len);//从PLC读取数据 if (rcvBytes == null) {
if (rcvBytes == null)
{
//_plcReader.Connect(); //_plcReader.Connect();
return -1; return -1;
} } else {
else int index = area.StartIndex; //index指向_items中的Tag元数据
{
int index = area.StartIndex;//index指向_items中的Tag元数据
int count = index + area.Count; int count = index + area.Count;
while (index < count) while (index < count) {
{
DeviceAddress addr = _items[index].Address; DeviceAddress addr = _items[index].Address;
int iByte = addr.CacheIndex; int iByte = addr.CacheIndex;
int iByte1 = iByte - offset; int iByte1 = iByte - offset;
if (addr.VarType == DataType.BOOL) if (addr.VarType == DataType.BOOL) {
{
int tmp = rcvBytes[iByte1] ^ cache[iByte]; int tmp = rcvBytes[iByte1] ^ cache[iByte];
DeviceAddress next = addr; DeviceAddress next = addr;
if (tmp != 0) if (tmp != 0) {
{ while (addr.Start == next.Start) {
while (addr.Start == next.Start)
{
if ((tmp & (1 << next.Bit)) > 0) _changedList.Add(index); if ((tmp & (1 << next.Bit)) > 0) _changedList.Add(index);
if (++index < count) if (++index < count)
next = _items[index].Address; next = _items[index].Address;
else else
break; break;
} }
} } else {
else while (addr.Start == next.Start && ++index < count) {
{
while (addr.Start == next.Start && ++index < count)
{
next = _items[index].Address; next = _items[index].Address;
} }
} }
} } else {
else
{
ushort size = addr.DataSize; ushort size = addr.DataSize;
for (int i = 0; i < size; i++) for (int i = 0; i < size; i++) {
{ if (rcvBytes[iByte1 + i] != cache[iByte + i]) {
if (rcvBytes[iByte1 + i] != cache[iByte + i])
{
_changedList.Add(index); _changedList.Add(index);
break; break;
} }
} }
index++; index++;
} }
} }
for (int j = 0; j < rcvBytes.Length; j++) for (int j = 0; j < rcvBytes.Length; j++)
cache[j + offset] = rcvBytes[j];//将PLC读取的数据写入到CacheReader中 cache[j + offset] = rcvBytes[j]; //将PLC读取的数据写入到CacheReader中
} }
offset += rcvBytes.Length; offset += rcvBytes.Length;
} }
return 1; return 1;
} }
protected void Update() protected void Update() {
{
DateTime dt = DateTime.Now; DateTime dt = DateTime.Now;
if (DataChange != null) if (DataChange != null) {
{
HistoryData[] values = new HistoryData[_changedList.Count]; HistoryData[] values = new HistoryData[_changedList.Count];
int i = 0; int i = 0;
foreach (int index in _changedList) foreach (int index in _changedList) {
{
ITag item = _items[index]; ITag item = _items[index];
var itemData = item.Read(); var itemData = item.Read();
if (item.Active) if (item.Active)
item.Update(itemData, dt, QUALITIES.QUALITY_GOOD); item.Update(itemData, dt, QUALITIES.QUALITY_GOOD);
if (_deadband == 0 || (item.Address.VarType == DataType.FLOAT && if (_deadband == 0 || (item.Address.VarType == DataType.FLOAT &&
(Math.Abs(itemData.Single / item.Value.Single - 1) > _deadband))) (Math.Abs(itemData.Single / item.Value.Single - 1) > _deadband))) {
{
values[i].ID = item.ID; values[i].ID = item.ID;
values[i].Quality = item.Quality; values[i].Quality = item.Quality;
values[i].Value = itemData; values[i].Value = itemData;
@ -403,54 +329,44 @@ namespace DataService
i++; i++;
} }
} }
foreach (DataChangeEventHandler deleg in DataChange.GetInvocationList())
{ foreach (DataChangeEventHandler deleg in DataChange.GetInvocationList()) {
deleg.BeginInvoke(this, new DataChangeEventArgs(1, values), null, null); deleg.BeginInvoke(this, new DataChangeEventArgs(1, values), null, null);
} }
} } else {
else foreach (int index in _changedList) {
{
foreach (int index in _changedList)
{
ITag item = _items[index]; ITag item = _items[index];
if (item.Active) if (item.Active)
item.Update(item.Read(), dt, QUALITIES.QUALITY_GOOD); item.Update(item.Read(), dt, QUALITIES.QUALITY_GOOD);
} }
} }
_changedList.Clear(); _changedList.Clear();
} }
public void Dispose() public void Dispose() {
{
if (_timer != null) if (_timer != null)
_timer.Dispose(); _timer.Dispose();
//if (_items != null) //if (_items != null)
// _items.Clear(); // _items.Clear();
} }
public virtual HistoryData[] BatchRead(DataSource source, bool isSync, params ITag[] itemArray) public virtual HistoryData[] BatchRead(DataSource source, bool isSync, params ITag[] itemArray) {
{
int len = itemArray.Length; int len = itemArray.Length;
HistoryData[] values = new HistoryData[len]; HistoryData[] values = new HistoryData[len];
if (source == DataSource.Device) if (source == DataSource.Device) {
{
IMultiReadWrite multi = _plcReader as IMultiReadWrite; IMultiReadWrite multi = _plcReader as IMultiReadWrite;
if (multi != null) if (multi != null) {
{
Array.Sort(itemArray); Array.Sort(itemArray);
var itemArr = multi.ReadMultiple(Array.ConvertAll(itemArray, x => x.Address)); var itemArr = multi.ReadMultiple(Array.ConvertAll(itemArray, x => x.Address));
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++) {
{
values[i].ID = itemArray[i].ID; values[i].ID = itemArray[i].ID;
values[i].Value = itemArr[i].Value; values[i].Value = itemArr[i].Value;
values[i].TimeStamp = itemArr[i].TimeStamp.ToDateTime(); values[i].TimeStamp = itemArr[i].TimeStamp.ToDateTime();
itemArray[i].Update(itemArr[i].Value, values[i].TimeStamp, itemArr[i].Quality); itemArray[i].Update(itemArr[i].Value, values[i].TimeStamp, itemArr[i].Quality);
} }
} } else {
else for (int i = 0; i < len; i++) {
{
for (int i = 0; i < len; i++)
{
itemArray[i].Refresh(source); itemArray[i].Refresh(source);
values[i].ID = itemArray[i].ID; values[i].ID = itemArray[i].ID;
values[i].Value = itemArray[i].Value; values[i].Value = itemArray[i].Value;
@ -458,52 +374,44 @@ namespace DataService
values[i].TimeStamp = itemArray[i].TimeStamp; values[i].TimeStamp = itemArray[i].TimeStamp;
} }
} }
} } else {
else for (int i = 0; i < len; i++) {
{
for (int i = 0; i < len; i++)
{
values[i].ID = itemArray[i].ID; values[i].ID = itemArray[i].ID;
values[i].Value = itemArray[i].Value; values[i].Value = itemArray[i].Value;
values[i].Quality = itemArray[i].Quality; values[i].Quality = itemArray[i].Quality;
values[i].TimeStamp = itemArray[i].TimeStamp; values[i].TimeStamp = itemArray[i].TimeStamp;
} }
} }
return values; return values;
} }
public virtual int BatchWrite(SortedDictionary<ITag, object> items, bool isSync = true) public virtual int BatchWrite(SortedDictionary<ITag, object> items, bool isSync = true) {
{
int len = items.Count; int len = items.Count;
int rev = 0; int rev = 0;
IMultiReadWrite multi = _plcReader as IMultiReadWrite; IMultiReadWrite multi = _plcReader as IMultiReadWrite;
if (multi != null) if (multi != null) {
{
DeviceAddress[] addrs = new DeviceAddress[len]; DeviceAddress[] addrs = new DeviceAddress[len];
object[] objs = new object[len]; object[] objs = new object[len];
int i = 0; int i = 0;
foreach (var item in items) foreach (var item in items) {
{
addrs[i] = item.Key.Address; addrs[i] = item.Key.Address;
objs[i] = item.Value; objs[i] = item.Value;
i++; i++;
} }
rev = multi.WriteMultiple(addrs, objs); rev = multi.WriteMultiple(addrs, objs);
} } else {
else foreach (var tag in items) {
{
foreach (var tag in items)
{
if (tag.Key.Write(tag.Value) < 0) if (tag.Key.Write(tag.Value) < 0)
rev = -1; rev = -1;
} }
} }
if (DataChange != null && rev >= 0)
{ if (DataChange != null && rev >= 0) {
HistoryData[] data = new HistoryData[len]; HistoryData[] data = new HistoryData[len];
int i = 0; int i = 0;
foreach (var item in items) foreach (var item in items) {
{
ITag tag = item.Key; ITag tag = item.Key;
data[i].ID = tag.ID; data[i].ID = tag.ID;
data[i].TimeStamp = tag.TimeStamp; data[i].TimeStamp = tag.TimeStamp;
@ -511,156 +419,150 @@ namespace DataService
data[i].Value = item.Key.ToStorage(item.Value); data[i].Value = item.Key.ToStorage(item.Value);
i++; i++;
} }
foreach (DataChangeEventHandler deleg in DataChange.GetInvocationList())
{ foreach (DataChangeEventHandler deleg in DataChange.GetInvocationList()) {
deleg.BeginInvoke(this, new DataChangeEventArgs(1, data), null, null); deleg.BeginInvoke(this, new DataChangeEventArgs(1, data), null, null);
} }
} }
return rev; return rev;
} }
public ItemData<int> ReadInt32(DeviceAddress address, DataSource source = DataSource.Cache) public ItemData<int> ReadInt32(DeviceAddress address, DataSource source = DataSource.Cache) {
{
return source == DataSource.Cache ? _cacheReader.ReadInt32(address) : _plcReader.ReadInt32(address); return source == DataSource.Cache ? _cacheReader.ReadInt32(address) : _plcReader.ReadInt32(address);
} }
public ItemData<short> ReadInt16(DeviceAddress address, DataSource source = DataSource.Cache) public ItemData<short> ReadInt16(DeviceAddress address, DataSource source = DataSource.Cache) {
{
return source == DataSource.Cache ? _cacheReader.ReadInt16(address) : _plcReader.ReadInt16(address); return source == DataSource.Cache ? _cacheReader.ReadInt16(address) : _plcReader.ReadInt16(address);
} }
public ItemData<byte> ReadByte(DeviceAddress address, DataSource source = DataSource.Cache) public ItemData<byte> ReadByte(DeviceAddress address, DataSource source = DataSource.Cache) {
{
return source == DataSource.Cache ? _cacheReader.ReadByte(address) : _plcReader.ReadByte(address); return source == DataSource.Cache ? _cacheReader.ReadByte(address) : _plcReader.ReadByte(address);
} }
public ItemData<float> ReadFloat(DeviceAddress address, DataSource source = DataSource.Cache) public ItemData<float> ReadFloat(DeviceAddress address, DataSource source = DataSource.Cache) {
{
return source == DataSource.Cache ? _cacheReader.ReadFloat(address) : _plcReader.ReadFloat(address); return source == DataSource.Cache ? _cacheReader.ReadFloat(address) : _plcReader.ReadFloat(address);
} }
public ItemData<bool> ReadBool(DeviceAddress address, DataSource source = DataSource.Cache) public ItemData<bool> ReadBool(DeviceAddress address, DataSource source = DataSource.Cache) {
{
return source == DataSource.Cache ? _cacheReader.ReadBit(address) : _plcReader.ReadBit(address); return source == DataSource.Cache ? _cacheReader.ReadBit(address) : _plcReader.ReadBit(address);
} }
public ItemData<string> ReadString(DeviceAddress address, DataSource source = DataSource.Cache) public ItemData<string> ReadString(DeviceAddress address, DataSource source = DataSource.Cache) {
{
ushort siz = address.DataSize; ushort siz = address.DataSize;
return source == DataSource.Cache ? _cacheReader.ReadString(address, siz) : return source == DataSource.Cache
_plcReader.ReadString(address, siz); ? _cacheReader.ReadString(address, siz)
: _plcReader.ReadString(address, siz);
} }
public int WriteInt32(DeviceAddress address, int value) public int WriteInt32(DeviceAddress address, int value) {
{
int rs = _plcReader.WriteInt32(address, value); int rs = _plcReader.WriteInt32(address, value);
if (rs >= 0) if (rs >= 0) {
{ if (DataChange != null) {
if (DataChange != null)
{
ITag tag = GetTagByAddress(address); ITag tag = GetTagByAddress(address);
if (tag != null) if (tag != null)
DataChange(this, new DataChangeEventArgs(1, new HistoryData[1] DataChange(this,
{ new DataChangeEventArgs(1,
new HistoryData(tag.ID,QUALITIES.QUALITY_GOOD,new Storage{Int32=value}, DateTime.Now) new HistoryData[1] {
})); new HistoryData(tag.ID, QUALITIES.QUALITY_GOOD, new Storage {Int32 = value},
DateTime.Now)
}));
} }
} }
return rs; return rs;
} }
public int WriteInt16(DeviceAddress address, short value) public int WriteInt16(DeviceAddress address, short value) {
{
int rs = _plcReader.WriteInt16(address, value); int rs = _plcReader.WriteInt16(address, value);
if (rs >= 0) if (rs >= 0) {
{ if (DataChange != null) {
if (DataChange != null)
{
ITag tag = GetTagByAddress(address); ITag tag = GetTagByAddress(address);
if (tag != null) if (tag != null)
DataChange(this, new DataChangeEventArgs(1, new HistoryData[1] DataChange(this,
{ new DataChangeEventArgs(1,
new HistoryData(tag.ID,QUALITIES.QUALITY_GOOD,new Storage{Int16=value}, DateTime.Now) new HistoryData[1] {
})); new HistoryData(tag.ID, QUALITIES.QUALITY_GOOD, new Storage {Int16 = value},
DateTime.Now)
}));
} }
} }
return rs; return rs;
} }
public int WriteFloat(DeviceAddress address, float value) public int WriteFloat(DeviceAddress address, float value) {
{
int rs = _plcReader.WriteFloat(address, value); int rs = _plcReader.WriteFloat(address, value);
if (rs >= 0) if (rs >= 0) {
{ if (DataChange != null) {
if (DataChange != null)
{
ITag tag = GetTagByAddress(address); ITag tag = GetTagByAddress(address);
if (tag != null) if (tag != null)
DataChange(this, new DataChangeEventArgs(1, new HistoryData[1] DataChange(this,
{ new DataChangeEventArgs(1,
new HistoryData(tag.ID,QUALITIES.QUALITY_GOOD,new Storage{Single=value}, DateTime.Now) new HistoryData[1] {
})); new HistoryData(tag.ID, QUALITIES.QUALITY_GOOD, new Storage {Single = value},
DateTime.Now)
}));
} }
} }
return rs; return rs;
} }
public int WriteString(DeviceAddress address, string value) public int WriteString(DeviceAddress address, string value) {
{
int rs = _plcReader.WriteString(address, value); int rs = _plcReader.WriteString(address, value);
if (rs >= 0) if (rs >= 0) {
{ if (DataChange != null) {
if (DataChange != null)
{
ITag tag = GetTagByAddress(address); ITag tag = GetTagByAddress(address);
if (tag != null) if (tag != null)
DataChange(this, new DataChangeEventArgs(1, new HistoryData[1] DataChange(this,
{ new DataChangeEventArgs(1,
new HistoryData(tag.ID,QUALITIES.QUALITY_GOOD,Storage.Empty, DateTime.Now) new HistoryData[1] {
})); new HistoryData(tag.ID, QUALITIES.QUALITY_GOOD, Storage.Empty, DateTime.Now)
}));
} }
} }
return rs; return rs;
} }
public int WriteBit(DeviceAddress address, bool value) public int WriteBit(DeviceAddress address, bool value) {
{
int rs = _plcReader.WriteBit(address, value); int rs = _plcReader.WriteBit(address, value);
if (rs >= 0) if (rs >= 0) {
{ if (DataChange != null) {
if (DataChange != null)
{
ITag tag = GetTagByAddress(address); ITag tag = GetTagByAddress(address);
if (tag != null) if (tag != null)
DataChange(this, new DataChangeEventArgs(1, new HistoryData[1] DataChange(this,
{ new DataChangeEventArgs(1,
new HistoryData(tag.ID,QUALITIES.QUALITY_GOOD,new Storage{Boolean=value}, DateTime.Now) new HistoryData[1] {
})); new HistoryData(tag.ID, QUALITIES.QUALITY_GOOD, new Storage {Boolean = value},
DateTime.Now)
}));
} }
} }
return rs; return rs;
} }
public int WriteBits(DeviceAddress address, byte value) public int WriteBits(DeviceAddress address, byte value) {
{
int rs = _plcReader.WriteBits(address, value); int rs = _plcReader.WriteBits(address, value);
if (rs >= 0) if (rs >= 0) {
{ if (DataChange != null) {
if (DataChange != null)
{
ITag tag = GetTagByAddress(address); ITag tag = GetTagByAddress(address);
if (tag != null) if (tag != null)
DataChange(this, new DataChangeEventArgs(1, new HistoryData[1] DataChange(this,
{ new DataChangeEventArgs(1,
new HistoryData(tag.ID,QUALITIES.QUALITY_GOOD,new Storage{Byte=value}, DateTime.Now) new HistoryData[1] {
})); new HistoryData(tag.ID, QUALITIES.QUALITY_GOOD, new Storage {Byte = value},
DateTime.Now)
}));
} }
} }
return rs; return rs;
} }
private ITag GetTagByAddress(DeviceAddress addr) private ITag GetTagByAddress(DeviceAddress addr) {
{
int index = _items.BinarySearch(new BoolTag(0, addr, null)); int index = _items.BinarySearch(new BoolTag(0, addr, null));
return index < 0 ? null : _items[index]; return index < 0 ? null : _items[index];
} }
@ -669,19 +571,17 @@ namespace DataService
} }
public struct PDUArea public struct PDUArea {
{
public DeviceAddress Start; public DeviceAddress Start;
public int Len; public int Len;
public int StartIndex; public int StartIndex;
public int Count; public int Count;
public PDUArea(DeviceAddress start, int len, int startIndex, int count) public PDUArea(DeviceAddress start, int len, int startIndex, int count) {
{
Start = start; Start = start;
Len = len; Len = len;
StartIndex = startIndex; StartIndex = startIndex;
Count = count; Count = count;
} }
} }
} }

49
SCADA/Program/DataService/Storage.cs

@ -1,76 +1,73 @@
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System; using System;
namespace DataService namespace DataService {
{
[StructLayout(LayoutKind.Explicit, Size = 4)] [StructLayout(LayoutKind.Explicit, Size = 4)]
public struct Storage public struct Storage {
{
// Fields // Fields
[FieldOffset(0)] [FieldOffset(0)]
public bool Boolean; public bool Boolean;
[FieldOffset(0)] [FieldOffset(0)]
public byte Byte; public byte Byte;
[FieldOffset(0)] [FieldOffset(0)]
public short Int16; public short Int16;
[FieldOffset(0)] [FieldOffset(0)]
public int Int32; public int Int32;
[FieldOffset(0)] [FieldOffset(0)]
public float Single; public float Single;
public static readonly Storage Empty ; public static readonly Storage Empty;
static Storage() static Storage() {
{
Empty = new Storage(); Empty = new Storage();
} }
public override bool Equals(object obj) public override bool Equals(object obj) {
{
if (obj == null) return false; if (obj == null) return false;
Type type = obj.GetType(); Type type = obj.GetType();
if (type == typeof(Storage)) if (type == typeof(Storage))
return this.Int32 == ((Storage)obj).Int32; return this.Int32 == ((Storage) obj).Int32;
else else {
{
if (type == typeof(Int32)) if (type == typeof(Int32))
return this.Int32 == (Int32)obj; return this.Int32 == (Int32) obj;
if (type == typeof(Int16)) if (type == typeof(Int16))
return this.Int16 == (Int16)obj; return this.Int16 == (Int16) obj;
if (type == typeof(Byte)) if (type == typeof(Byte))
return this.Byte == (Byte)obj; return this.Byte == (Byte) obj;
if (type == typeof(Boolean)) if (type == typeof(Boolean))
return this.Boolean == (Boolean)obj; return this.Boolean == (Boolean) obj;
if (type == typeof(Single)) if (type == typeof(Single))
return this.Single == (Single)obj; return this.Single == (Single) obj;
if (type == typeof(String)) if (type == typeof(String))
return this.ToString() == obj.ToString(); return this.ToString() == obj.ToString();
} }
return false; return false;
} }
public override int GetHashCode() public override int GetHashCode() {
{
return Int32.GetHashCode(); return Int32.GetHashCode();
} }
public static bool operator ==(Storage x, Storage y) public static bool operator ==(Storage x, Storage y) {
{
return x.Int32 == y.Int32; return x.Int32 == y.Int32;
} }
public static bool operator !=(Storage x, Storage y) public static bool operator !=(Storage x, Storage y) {
{
return x.Int32 != y.Int32; return x.Int32 != y.Int32;
} }
} }
public enum QUALITIES : short public enum QUALITIES : short {
{
// Fields // Fields
LIMIT_CONST = 3, LIMIT_CONST = 3,
LIMIT_HIGH = 2, LIMIT_HIGH = 2,
LIMIT_LOW = 1, LIMIT_LOW = 1,
//LIMIT_MASK = 3, //LIMIT_MASK = 3,
//LIMIT_OK = 0, //LIMIT_OK = 0,
QUALITY_BAD = 0, QUALITY_BAD = 0,

39
SCADA/Program/DataService/TagMetaData.cs

@ -1,11 +1,9 @@
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace DataService namespace DataService {
{
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public struct TagMetaData : IComparable<TagMetaData> public struct TagMetaData : IComparable<TagMetaData> {
{
public bool Archive; public bool Archive;
public DataType DataType; public DataType DataType;
@ -27,8 +25,7 @@ namespace DataService
public string Name; public string Name;
public TagMetaData(short id, short grpId, string name, string address, public TagMetaData(short id, short grpId, string name, string address,
DataType type, ushort size, bool archive = false, float max = 0, float min = 0, int cycle = 0) DataType type, ushort size, bool archive = false, float max = 0, float min = 0, int cycle = 0) {
{
ID = id; ID = id;
GroupID = grpId; GroupID = grpId;
Name = name; Name = name;
@ -41,20 +38,17 @@ namespace DataService
Cycle = cycle; Cycle = cycle;
} }
public int CompareTo(TagMetaData other) public int CompareTo(TagMetaData other) {
{ return ID.CompareTo(other.ID);
return this.ID.CompareTo(other.ID);
} }
public override string ToString() public override string ToString() {
{
return Name; return Name;
} }
} }
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public struct Scaling : IComparable<Scaling> public struct Scaling : IComparable<Scaling> {
{
public short ID; public short ID;
public ScaleType ScaleType; public ScaleType ScaleType;
@ -67,8 +61,7 @@ namespace DataService
public float RawLo; public float RawLo;
public Scaling(short id, ScaleType type, float euHi, float euLo, float rawHi, float rawLo) public Scaling(short id, ScaleType type, float euHi, float euLo, float rawHi, float rawLo) {
{
ID = id; ID = id;
ScaleType = type; ScaleType = type;
EUHi = euHi; EUHi = euHi;
@ -77,32 +70,28 @@ namespace DataService
RawLo = rawLo; RawLo = rawLo;
} }
public int CompareTo(Scaling other) public int CompareTo(Scaling other) {
{
return ID.CompareTo(other.ID); return ID.CompareTo(other.ID);
} }
public static readonly Scaling Empty = new Scaling { ScaleType = ScaleType.None }; public static readonly Scaling Empty = new Scaling {ScaleType = ScaleType.None};
} }
public struct ItemData<T> public struct ItemData<T> {
{
public T Value; public T Value;
public long TimeStamp; public long TimeStamp;
public QUALITIES Quality; public QUALITIES Quality;
public ItemData(T value, long timeStamp, QUALITIES quality) public ItemData(T value, long timeStamp, QUALITIES quality) {
{
Value = value; Value = value;
TimeStamp = timeStamp; TimeStamp = timeStamp;
Quality = quality; Quality = quality;
} }
} }
public enum ScaleType : byte public enum ScaleType : byte {
{
None = 0, None = 0,
Linear = 1, Linear = 1,
SquareRoot = 2 SquareRoot = 2
} }
} }

BIN
SCADA/Program/FileDriver/obj/Debug/FileDriver.csprojAssemblyReference.cache

Binary file not shown.

BIN
SCADA/Program/HMIControl/bin/Debug/DataHelper.dll

Binary file not shown.

BIN
SCADA/Program/HMIControl/bin/Debug/DataHelper.pdb

Binary file not shown.

BIN
SCADA/Program/HMIControl/bin/Debug/DataService.dll

Binary file not shown.

BIN
SCADA/Program/HMIControl/bin/Debug/DataService.pdb

Binary file not shown.

BIN
SCADA/Program/HMIControl/bin/Debug/HMIControl.VisualStudio.Design.dll

Binary file not shown.

BIN
SCADA/Program/HMIControl/bin/Debug/HMIControl.VisualStudio.Design.pdb

Binary file not shown.

BIN
SCADA/Program/LinkableControlDesignTime/obj/Debug/HMIControl.VisualStudio.Design.dll

Binary file not shown.

BIN
SCADA/Program/LinkableControlDesignTime/obj/Debug/HMIControl.VisualStudio.Design.pdb

Binary file not shown.

BIN
SCADA/Program/ModbusDriver/obj/Debug/ModbusDriver.csprojAssemblyReference.cache

Binary file not shown.

BIN
SCADA/Program/SiemensPLCDriver/obj/Debug/SiemensPLCDriver.csprojAssemblyReference.cache

Binary file not shown.

BIN
SCADA/Program/TagConfig/TagConfig/obj/x86/Debug/TagConfig.csprojAssemblyReference.cache

Binary file not shown.
Loading…
Cancel
Save