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;
}
public bool IsActived
public bool IsActivated
{
get;
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.ComponentModel;
namespace DataService
{
public class AlarmItem : IComparable<AlarmItem>, INotifyPropertyChanged
{
namespace DataService {
public class AlarmItem : IComparable<AlarmItem>, INotifyPropertyChanged {
int _condiId;
Severity _severity;
SubAlarmType _alarmType;
DateTime _startTime;
TimeSpan _duration;
TimeSpan _duration;
object _alarmValue;
string _alarmText;
string _source;
public SubAlarmType SubAlarmType
{
get
{
return _alarmType;
}
set
{
_alarmType = value;
}
public SubAlarmType SubAlarmType {
get { return _alarmType; }
set { _alarmType = value; }
}
public Severity Severity
{
get
{
return _severity;
}
set
{
_severity = value;
}
public Severity Severity {
get { return _severity; }
set { _severity = value; }
}
public DateTime StartTime
{
get
{
return _startTime;
}
set
{
_startTime = value;
}
public DateTime StartTime {
get { return _startTime; }
set { _startTime = value; }
}
public int ConditionId
{
get
{
return _condiId;
}
set
{
_condiId = value;
}
public int ConditionId {
get { return _condiId; }
set { _condiId = value; }
}
public TimeSpan Duration
{
get
{
public TimeSpan Duration {
get {
//return _endTime-_startTime;
return _duration;
}
set
{
set {
_duration = value;
OnPropertyChanged("Duration");
}
}
public object AlarmValue
{
get
{
return _alarmValue;
}
set
{
_alarmValue = value;
}
public object AlarmValue {
get { return _alarmValue; }
set { _alarmValue = value; }
}
public string AlarmText
{
get
{
return _alarmText;
}
set
{
_alarmText = value;
}
public string AlarmText {
get { return _alarmText; }
set { _alarmText = value; }
}
public string Source
{
get
{
return _source;
}
set
{
_source = value;
}
public string Source {
get { 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._alarmType = type;
this._alarmText = alarmText;
@ -125,8 +70,7 @@ namespace DataService
this._source = source;
}
public AlarmItem()
{
public AlarmItem() {
this._startTime = DateTime.Now;
this._alarmType = SubAlarmType.None;
this._alarmText = string.Empty;
@ -137,8 +81,7 @@ namespace DataService
#region IComparable<AlarmItem> Members
public int CompareTo(AlarmItem other)
{
public int CompareTo(AlarmItem other) {
return this._startTime.CompareTo(other._startTime);
}
@ -146,20 +89,15 @@ namespace DataService
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
private void OnPropertyChanged(string propertyName) {
if (this.PropertyChanged != null) {
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
[Flags]
public enum AlarmType
{
public enum AlarmType {
None = 0,
Level = 1,
Dev = 2,
@ -171,8 +109,7 @@ namespace DataService
}
[Flags]
public enum SubAlarmType
{
public enum SubAlarmType {
None = 0,
LoLo = 1,
Low = 2,
@ -187,8 +124,7 @@ namespace DataService
MinROC = 512
}
public enum Severity
{
public enum Severity {
Error = 7,
High = 6,
MediumHigh = 5,
@ -200,24 +136,20 @@ namespace DataService
}
[Flags]
public enum ConditionState : byte
{
public enum ConditionState : byte {
Acked = 4,
Actived = 2,
Enabled = 1
}
public enum EventType : byte
{
public enum EventType : byte {
Simple = 1,
TraceEvent = 2,
ConditionEvent = 4,
}
public enum ConditionType : byte
{
public enum ConditionType : byte {
Absolute = 0,
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.Runtime.InteropServices;
namespace DataService
{
namespace DataService {
[StructLayout(LayoutKind.Sequential)]
public struct DeviceAddress : IComparable<DeviceAddress>
{
public struct DeviceAddress : IComparable<DeviceAddress> {
public int Area;
public int Start;
public ushort DBNumber;
@ -14,8 +12,8 @@ namespace DataService
public byte Bit;
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;
DBNumber = dbnumber;
CacheIndex = cIndex;
@ -27,17 +25,15 @@ namespace DataService
public static readonly DeviceAddress Empty = new DeviceAddress(0, 0, 0, 0, 0, 0, DataType.NONE);
public int CompareTo(DeviceAddress other)
{
return this.Area > other.Area ? 1 :
this.Area < other.Area ? -1 :
this.DBNumber > other.DBNumber ? 1 :
this.DBNumber < other.DBNumber ? -1 :
this.Start > other.Start ? 1 :
this.Start < other.Start ? -1 :
this.Bit > other.Bit ? 1 :
this.Bit < other.Bit ? -1 : 0;
public int CompareTo(DeviceAddress other) {
return Area > other.Area ? 1 :
Area < other.Area ? -1 :
DBNumber > other.DBNumber ? 1 :
DBNumber < other.DBNumber ? -1 :
Start > other.Start ? 1 :
Start < other.Start ? -1 :
Bit > other.Bit ? 1 :
Bit < other.Bit ? -1 : 0;
}
}
}
}

419
SCADA/Program/DataService/Eval.cs

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

463
SCADA/Program/DataService/ExtensionMethods.cs

@ -5,111 +5,96 @@ using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Data.SqlClient;
namespace DataService
{
public static class ExtMethods
{
public static string GetExceptionMsg(this Exception e)
{
namespace DataService {
public static class ExtMethods {
public static string GetExceptionMsg(this Exception e) {
string err = string.Empty;
Exception exp = e;
while (exp != null)
{
while (exp != null) {
err += string.Format("\n {0}", exp.Message);
exp = exp.InnerException;
}
err += string.Format("\n {0}", e.StackTrace);
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;
lock (server.SyncRoot)
{
lock (server.SyncRoot) {
int index = server.GetItemProperties(tag.ID);
if (index < 0) return false;
var meta = server.MetaDataList[index];
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.AddItemIndex(name, tag);
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);
if (conds == null) return SubCondition.Empty;
foreach (ICondition cond in conds)
{
foreach (ICondition cond in conds) {
SubCondition sub = cond.FindSubConditon(alarmType);
if (sub.SubAlarmType == alarmType)
return sub;
}
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;
if (subs != null && subs.Count > 0)
{
foreach (var sub in subs)
{
if (sub.SubAlarmType == alarmType)
{
if (subs != null && subs.Count > 0) {
foreach (var sub in subs) {
if (sub.SubAlarmType == alarmType) {
return sub;
}
}
}
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];
if (tag == null) return false;
int scaleid = server.GetScaleByID(tag.ID);
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;
if (server == null) return false;
List<ICondition> conds = server.ConditionList as List<ICondition>;
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;
if (server == null) return false;
var conds = server.QueryConditions(sourceName);
if (conds == null) return false;
foreach (ICondition cond in conds)
{
foreach (ICondition cond in conds) {
var subs = cond.SubConditions;
if (subs != null && subs.Count > 0)
{
foreach (var sub in subs)
{
if (sub.SubAlarmType == alarmType)
{
if (subs != null && subs.Count > 0) {
foreach (var sub in subs) {
if (sub.SubAlarmType == alarmType) {
return true;
}
}
}
}
return false;
}
public static ItemData<object> ReadValueEx(this IReaderWriter reader, DeviceAddress address)
{
switch (address.VarType)
{
public static ItemData<object> ReadValueEx(this IReaderWriter reader, DeviceAddress address) {
switch (address.VarType) {
case DataType.BOOL:
var bit = reader.ReadBit(address);
return new ItemData<object>(bit.Value, bit.TimeStamp, bit.Quality);
@ -131,13 +116,12 @@ namespace DataService
var str = reader.ReadString(address, address.DataSize);
return new ItemData<object>(str.Value, str.TimeStamp, str.Quality);
}
return new ItemData<object>(null, 0, QUALITIES.QUALITY_BAD);
}
public static int WriteValueEx(this IReaderWriter writer, DeviceAddress address, object value)
{
switch (address.VarType)
{
public static int WriteValueEx(this IReaderWriter writer, DeviceAddress address, object value) {
switch (address.VarType) {
case DataType.BOOL:
return writer.WriteBit(address, Convert.ToBoolean(value));
case DataType.BYTE:
@ -153,115 +137,112 @@ namespace DataService
case DataType.STR:
return writer.WriteString(address, value.ToString());
}
return -1;
}
public static HistoryData[] BatchRead(DataSource source, params ITag[] itemArray)
{
public static HistoryData[] BatchRead(DataSource source, params ITag[] itemArray) {
int len = itemArray.Length;
HistoryData[] values = new HistoryData[len];
for (int i = 0; i < len; i++)
{
for (int i = 0; i < len; i++) {
itemArray[i].Refresh(source);
values[i].ID = itemArray[i].ID;
values[i].Value = itemArray[i].Value;
values[i].TimeStamp = itemArray[i].TimeStamp;
}
return values;
}
public static int BatchWrite(IDictionary<ITag, object> items)
{
public static int BatchWrite(IDictionary<ITag, object> items) {
int rev = 0;
foreach (var tag in items)
{
foreach (var tag in items) {
if (tag.Key.Write(tag.Value) < 0)
rev = -1;
}
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>();
int count = addrsArr.Length;
if (count > 0)
{
if (count > 0) {
//Array.Sort(addrsArr);
DeviceAddress start = addrsArr[0];
start.Bit = 0;
int bitCount = cacheReader.ByteCount;
if (count > 1)
{
int cacheLength = 0;//缓冲区的大小
if (count > 1) {
int cacheLength = 0; //缓冲区的大小
int cacheIndexStart = 0;
int startIndex = 0;
DeviceAddress segmentEnd, tagAddress;
DeviceAddress segmentEnd,
tagAddress;
DeviceAddress segmentStart = start;
for (int j = 1, i = 1; i < count; i++, j++)
{
tagAddress = addrsArr[i];//当前变量地址
for (int j = 1,
i = 1;
i < count;
i++, j++) {
tagAddress = addrsArr[i]; //当前变量地址
int offset1 = cacheReader.GetOffset(tagAddress, segmentStart);
if (offset1 > (PDU / cacheReader.ByteCount))
{
if (offset1 > (PDU / cacheReader.ByteCount)) {
segmentEnd = addrsArr[i - 1];
int len = cacheReader.GetOffset(segmentEnd, segmentStart);
len += segmentEnd.DataSize <= bitCount ? 1 : segmentEnd.DataSize / bitCount;
tagAddress.CacheIndex = (ushort)(cacheIndexStart + len);
tagAddress.CacheIndex = (ushort) (cacheIndexStart + len);
addrsArr[i] = tagAddress;
rangeList.Add(new PDUArea(segmentStart, len, startIndex, j));
startIndex += j; j = 0;
cacheLength += len;//更新缓存长度
startIndex += j;
j = 0;
cacheLength += len; //更新缓存长度
cacheIndexStart = cacheLength;
segmentStart = tagAddress;//更新数据片段的起始地址
}
else
{
tagAddress.CacheIndex = (ushort)(cacheIndexStart + offset1);
segmentStart = tagAddress; //更新数据片段的起始地址
} else {
tagAddress.CacheIndex = (ushort) (cacheIndexStart + offset1);
addrsArr[i] = tagAddress;
}
if (i == count - 1)
{
if (i == count - 1) {
segmentEnd = addrsArr[i];
int segmentLength = cacheReader.GetOffset(segmentEnd, segmentStart);
if (segmentLength > PDU / cacheReader.ByteCount)
{
if (segmentLength > PDU / cacheReader.ByteCount) {
segmentEnd = addrsArr[i - 1];
segmentLength = segmentEnd.DataSize <= bitCount ? 1 : segmentEnd.DataSize / bitCount;
}
tagAddress.CacheIndex = (ushort)(cacheIndexStart + segmentLength);
tagAddress.CacheIndex = (ushort) (cacheIndexStart + segmentLength);
addrsArr[i] = tagAddress;
segmentLength += segmentEnd.DataSize <= bitCount ? 1 : segmentEnd.DataSize / bitCount;
rangeList.Add(new PDUArea(segmentStart, segmentLength, startIndex, j + 1));
cacheLength += segmentLength;
}
}
cacheReader.Size = cacheLength;
}
else
cacheReader.Size = start.DataSize <= bitCount ? 1 : start.DataSize / bitCount;//改变Cache的Size属性值将创建Cache的内存区域
} else
cacheReader.Size =
start.DataSize <= bitCount ? 1 : start.DataSize / bitCount; //改变Cache的Size属性值将创建Cache的内存区域
}
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;
int len = addrsArr.Length;
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);
foreach (PDUArea area in areas)
{
byte[] rcvBytes = plc.ReadBytes(area.Start, (ushort)area.Len);
foreach (PDUArea area in areas) {
byte[] rcvBytes = plc.ReadBytes(area.Start, (ushort) area.Len);
Buffer.BlockCopy(rcvBytes, 0, cache.Cache, offset, rcvBytes.Length);
offset += rcvBytes.Length / cache.ByteCount;
}
for (int i = 0; i < len; i++)
{
switch (addrsArr[i].VarType)
{
for (int i = 0; i < len; i++) {
switch (addrsArr[i].VarType) {
case DataType.BOOL:
items[i].Value.Boolean = cache.ReadBit(addrsArr[i]).Value;
break;
@ -283,63 +264,66 @@ namespace DataService
var item = cache.ReadString(addrsArr[i], addrsArr[i].DataSize);
break;
}
items[i].Quality = QUALITIES.QUALITY_GOOD;
items[i].TimeStamp = now;
}
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 (addrArr.Length == 1) return plc.WriteValue(addrArr[0], buffer[0]);
lock (plc)//不锁定会有并发冲突问题;锁定也不能保障绝对安全,如有人现场操作会导致数据刷新
lock (plc) //不锁定会有并发冲突问题;锁定也不能保障绝对安全,如有人现场操作会导致数据刷新
{
List<PDUArea> areas = cache.AssignFromPDU(plc.PDU, addrArr);
int offset = 0;
foreach (PDUArea area in areas)
{
byte[] rcvBytes = plc.ReadBytes(area.Start, (ushort)area.Len);
foreach (PDUArea area in areas) {
byte[] rcvBytes = plc.ReadBytes(area.Start, (ushort) area.Len);
if (rcvBytes == null) return -1;
Buffer.BlockCopy(rcvBytes, 0, cache.Cache, offset, rcvBytes.Length);
offset += rcvBytes.Length / cache.ByteCount;
}
DeviceAddress start = addrArr[0];
int startIndex = 0;
int endIndex = 0;
while (endIndex < addrArr.Length)
{
if (start.Area != addrArr[endIndex].Area || start.DBNumber != addrArr[endIndex].DBNumber || endIndex - startIndex >= limit)
{
for (int i = startIndex; i < endIndex; i++)
{
while (endIndex < addrArr.Length) {
if (start.Area != addrArr[endIndex].Area || start.DBNumber != addrArr[endIndex].DBNumber ||
endIndex - startIndex >= limit) {
for (int i = startIndex; i < endIndex; 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)];
Buffer.BlockCopy(cache.Cache, c1, bytes, 0, bytes.Length);
if (plc.WriteBytes(start, bytes) < 0) return -1;
start = addrArr[endIndex];
startIndex = endIndex;
}
endIndex++;
}
}
return 0;
}
/// <summary>
/// string RightFrom
/// </summary>
/// <param name="text"></param>
/// <param name="length"></param>
/// <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);
}
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);
}
@ -348,16 +332,12 @@ namespace DataService
/// </summary>
/// <param name="filetime"></param>
/// <returns></returns>
public static DateTime ToDateTime(this long filetime)
{
public static DateTime ToDateTime(this long filetime) {
return filetime == 0 ? DateTime.Now : DateTime.FromFileTime(filetime);
}
public static Type ToType(this DataType dataType)
{
switch (dataType)
{
public static Type ToType(this DataType dataType) {
switch (dataType) {
case DataType.BOOL:
return typeof(bool);
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();
int off = len - str.Length;
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.Length != b2.Length) return false;
for (int i = 0; i < b1.Length; i++)
@ -395,41 +373,38 @@ namespace DataService
return true;
}
public static string ConvertToString(this byte[] bits)
{
public static string ConvertToString(this byte[] bits) {
char[] chars = new char[bits.Length];
for (int i = 0; i < bits.Length; i++)
{
chars[i] = (char)bits[i];
for (int i = 0; i < bits.Length; i++) {
chars[i] = (char) bits[i];
}
return new string(chars);
}
public static byte[] ConvertToArray(this string bits)
{
public static byte[] ConvertToArray(this string bits) {
var chars = bits.ToCharArray();
byte[] arr = new byte[chars.Length];
for (int i = 0; i < chars.Length; i++)
{
arr[i] = (byte)chars[i];
for (int i = 0; i < chars.Length; i++) {
arr[i] = (byte) chars[i];
}
return arr;
}
public static int BitSwap(this byte bit)
{
public static int BitSwap(this byte bit) {
return (bit < 8 ? bit + 8 : bit - 8);
}
[Obsolete]
public static Storage ToStorage(this ITag tag, object obj)
{
public static Storage ToStorage(this ITag tag, object obj) {
Storage value = Storage.Empty;
var str = obj as string;
switch (tag.Address.VarType)
{
switch (tag.Address.VarType) {
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;
case DataType.BYTE:
value.Byte = Convert.ToByte(obj);
@ -446,17 +421,16 @@ namespace DataService
value.Single = Convert.ToSingle(obj);
break;
}
return value;
}
public static byte[] ToByteArray(this ITag tag)
{
switch (tag.Address.VarType)
{
public static byte[] ToByteArray(this ITag tag) {
switch (tag.Address.VarType) {
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:
return new byte[] { tag.Value.Byte };
return new byte[] {tag.Value.Byte};
case DataType.WORD:
case DataType.SHORT:
return BitConverter.GetBytes(tag.Value.Int16);
@ -471,14 +445,12 @@ namespace DataService
}
}
public static byte[] ToByteArray(this ITag tag, Storage value)
{
switch (tag.Address.VarType)
{
public static byte[] ToByteArray(this ITag tag, Storage value) {
switch (tag.Address.VarType) {
case DataType.BOOL:
return new byte[] { value.Boolean ? (byte)1 : (byte)0 };
return new byte[] {value.Boolean ? (byte) 1 : (byte) 0};
case DataType.BYTE:
return new byte[] { value.Byte };
return new byte[] {value.Byte};
case DataType.WORD:
case DataType.SHORT:
return BitConverter.GetBytes(value.Int16);
@ -493,10 +465,8 @@ namespace DataService
}
}
public static object GetValue(this ITag tag, Storage value)
{
switch (tag.Address.VarType)
{
public static object GetValue(this ITag tag, Storage value) {
switch (tag.Address.VarType) {
case DataType.BOOL:
return value.Boolean;
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;
int ind = srv.GetScaleByID(tag.ID);
Scaling meta = ind < 0 ? Scaling.Empty : srv.ScalingList[ind];
if (meta.ScaleType == ScaleType.None)
{
if (meta.ScaleType == ScaleType.None) {
return value;
}
else
{
} else {
double temp = (value - meta.EULo) / (meta.EUHi - meta.EULo);
if (meta.ScaleType == ScaleType.SquareRoot)
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;
if (type == DataType.BOOL) return value.Boolean ? 1f : 0f;
IDataServer srv = tag.Parent.Server;
int ind = srv.GetScaleByID(tag.ID);
Scaling meta = ind < 0 ? Scaling.Empty : srv.ScalingList[ind];
if (meta.ScaleType == ScaleType.None)
{
switch (type)
{
if (meta.ScaleType == ScaleType.None) {
switch (type) {
case DataType.BYTE:
return (float)value.Byte;
return (float) value.Byte;
case DataType.WORD:
case DataType.SHORT:
return (float)value.Int16;
return (float) value.Int16;
case DataType.INT:
return (float)value.Int32;
return (float) value.Int32;
case DataType.FLOAT:
return value.Single;
case DataType.STR:
@ -559,12 +522,9 @@ namespace DataService
default:
return 0f;
}
}
else
{
} else {
double temp;
switch (type)
{
switch (type) {
case DataType.BYTE:
temp = (value.Byte - meta.RawLo) / (meta.RawHi - meta.RawLo);
break;
@ -581,73 +541,57 @@ namespace DataService
default:
return 0f;
}
if (meta.ScaleType == ScaleType.SquareRoot)
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);
}
public static string GetTagName(this ITag tag)
{
public static string GetTagName(this ITag tag) {
IDataServer srv = tag.Parent.Server;
int ind = srv.GetItemProperties(tag.ID);
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);
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;
int index = srv.GetItemProperties(tag.ID);
return index < 0 ? new TagMetaData() : srv.MetaDataList[index];
}
}
public static class Utility
{
public static class Utility {
private static readonly ushort[] crcTable = {
0X0000, 0XC0C1, 0XC181, 0X0140, 0XC301, 0X03C0, 0X0280, 0XC241,
0XC601, 0X06C0, 0X0780, 0XC741, 0X0500, 0XC5C1, 0XC481, 0X0440,
0XCC01, 0X0CC0, 0X0D80, 0XCD41, 0X0F00, 0XCFC1, 0XCE81, 0X0E40,
0X0A00, 0XCAC1, 0XCB81, 0X0B40, 0XC901, 0X09C0, 0X0880, 0XC841,
0XD801, 0X18C0, 0X1980, 0XD941, 0X1B00, 0XDBC1, 0XDA81, 0X1A40,
0X1E00, 0XDEC1, 0XDF81, 0X1F40, 0XDD01, 0X1DC0, 0X1C80, 0XDC41,
0X1400, 0XD4C1, 0XD581, 0X1540, 0XD701, 0X17C0, 0X1680, 0XD641,
0XD201, 0X12C0, 0X1380, 0XD341, 0X1100, 0XD1C1, 0XD081, 0X1040,
0XF001, 0X30C0, 0X3180, 0XF141, 0X3300, 0XF3C1, 0XF281, 0X3240,
0X3600, 0XF6C1, 0XF781, 0X3740, 0XF501, 0X35C0, 0X3480, 0XF441,
0X3C00, 0XFCC1, 0XFD81, 0X3D40, 0XFF01, 0X3FC0, 0X3E80, 0XFE41,
0XFA01, 0X3AC0, 0X3B80, 0XFB41, 0X3900, 0XF9C1, 0XF881, 0X3840,
0X2800, 0XE8C1, 0XE981, 0X2940, 0XEB01, 0X2BC0, 0X2A80, 0XEA41,
0XEE01, 0X2EC0, 0X2F80, 0XEF41, 0X2D00, 0XEDC1, 0XEC81, 0X2C40,
0XE401, 0X24C0, 0X2580, 0XE541, 0X2700, 0XE7C1, 0XE681, 0X2640,
0X2200, 0XE2C1, 0XE381, 0X2340, 0XE101, 0X21C0, 0X2080, 0XE041,
0XA001, 0X60C0, 0X6180, 0XA141, 0X6300, 0XA3C1, 0XA281, 0X6240,
0X6600, 0XA6C1, 0XA781, 0X6740, 0XA501, 0X65C0, 0X6480, 0XA441,
0X6C00, 0XACC1, 0XAD81, 0X6D40, 0XAF01, 0X6FC0, 0X6E80, 0XAE41,
0XAA01, 0X6AC0, 0X6B80, 0XAB41, 0X6900, 0XA9C1, 0XA881, 0X6840,
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
0X0000, 0XC0C1, 0XC181, 0X0140, 0XC301, 0X03C0, 0X0280, 0XC241, 0XC601, 0X06C0, 0X0780, 0XC741, 0X0500,
0XC5C1, 0XC481, 0X0440, 0XCC01, 0X0CC0, 0X0D80, 0XCD41, 0X0F00, 0XCFC1, 0XCE81, 0X0E40, 0X0A00, 0XCAC1,
0XCB81, 0X0B40, 0XC901, 0X09C0, 0X0880, 0XC841, 0XD801, 0X18C0, 0X1980, 0XD941, 0X1B00, 0XDBC1, 0XDA81,
0X1A40, 0X1E00, 0XDEC1, 0XDF81, 0X1F40, 0XDD01, 0X1DC0, 0X1C80, 0XDC41, 0X1400, 0XD4C1, 0XD581, 0X1540,
0XD701, 0X17C0, 0X1680, 0XD641, 0XD201, 0X12C0, 0X1380, 0XD341, 0X1100, 0XD1C1, 0XD081, 0X1040, 0XF001,
0X30C0, 0X3180, 0XF141, 0X3300, 0XF3C1, 0XF281, 0X3240, 0X3600, 0XF6C1, 0XF781, 0X3740, 0XF501, 0X35C0,
0X3480, 0XF441, 0X3C00, 0XFCC1, 0XFD81, 0X3D40, 0XFF01, 0X3FC0, 0X3E80, 0XFE41, 0XFA01, 0X3AC0, 0X3B80,
0XFB41, 0X3900, 0XF9C1, 0XF881, 0X3840, 0X2800, 0XE8C1, 0XE981, 0X2940, 0XEB01, 0X2BC0, 0X2A80, 0XEA41,
0XEE01, 0X2EC0, 0X2F80, 0XEF41, 0X2D00, 0XEDC1, 0XEC81, 0X2C40, 0XE401, 0X24C0, 0X2580, 0XE541, 0X2700,
0XE7C1, 0XE681, 0X2640, 0X2200, 0XE2C1, 0XE381, 0X2340, 0XE101, 0X21C0, 0X2080, 0XE041, 0XA001, 0X60C0,
0X6180, 0XA141, 0X6300, 0XA3C1, 0XA281, 0X6240, 0X6600, 0XA6C1, 0XA781, 0X6740, 0XA501, 0X65C0, 0X6480,
0XA441, 0X6C00, 0XACC1, 0XAD81, 0X6D40, 0XAF01, 0X6FC0, 0X6E80, 0XAE41, 0XAA01, 0X6AC0, 0X6B80, 0XAB41,
0X6900, 0XA9C1, 0XA881, 0X6840, 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>
@ -655,13 +599,12 @@ namespace DataService
/// </summary>
/// <param name="numbers">The byte array</param>
/// <returns>An array of ASCII byte values</returns>
public static string GetAsciiBytes(byte[] numbers)
{
public static string GetAsciiBytes(byte[] numbers) {
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");
}
return str;
}
@ -670,13 +613,12 @@ namespace DataService
/// </summary>
/// <param name="numbers">The ushort array</param>
/// <returns>An array of ASCII byte values</returns>
public static string GetAsciiBytes(ushort[] numbers)
{
public static string GetAsciiBytes(ushort[] numbers) {
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");
}
return str;
}
@ -685,8 +627,7 @@ namespace DataService
/// </summary>
/// <param name="networkBytes">The network order byte array</param>
/// <returns>The host order ushort array</returns>
public static ushort[] NetworkBytesToHostUInt16(byte[] networkBytes)
{
public static ushort[] NetworkBytesToHostUInt16(byte[] networkBytes) {
if (networkBytes == null)
throw new ArgumentNullException("networkBytes");
@ -696,7 +637,7 @@ namespace DataService
ushort[] result = new ushort[networkBytes.Length / 2];
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;
}
@ -706,8 +647,7 @@ namespace DataService
/// </summary>
/// <param name="hex">The hex string</param>
/// <returns>Array of bytes</returns>
public static byte[] HexToBytes(string hex)
{
public static byte[] HexToBytes(string hex) {
if (string.IsNullOrEmpty(hex))
throw new ArgumentNullException("hex");
@ -727,16 +667,16 @@ namespace DataService
/// </summary>
/// <param name="data">The data used in LRC</param>
/// <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)
throw new ArgumentNullException("data");
if (len == 0) len = data.Length;
byte lrc = 0;
for (int i = 0; i < len; i++)
{ lrc += data[i]; }
for (int i = 0; i < len; i++) {
lrc += data[i];
}
lrc = (byte)((lrc ^ 0xFF) + 1);
lrc = (byte) ((lrc ^ 0xFF) + 1);
return lrc;
}
@ -746,15 +686,13 @@ namespace DataService
/// </summary>
/// <param name="data">The data used in CRC</param>
/// <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)
throw new ArgumentNullException("data");
if (len == 0) len = data.Length;
ushort crc = ushort.MaxValue;
for (int i = 0; i < len; i++)
{
byte tableIndex = (byte)(crc ^ data[i]);
for (int i = 0; i < len; i++) {
byte tableIndex = (byte) (crc ^ data[i]);
crc >>= 8;
crc ^= crcTable[tableIndex];
}
@ -762,50 +700,43 @@ namespace DataService
return BitConverter.GetBytes(crc);
}
public static bool CheckSumCRC(byte[] frame)
{
public static bool CheckSumCRC(byte[] frame) {
int len = frame.Length;
byte[] chk = CalculateCrc(frame, len - 2);
return (chk[0] == frame[len - 2] && chk[1] == frame[len - 1]);
}
public static unsafe short NetToInt16(byte[] value, int startIndex)
{
if (value == null || startIndex > value.Length - 2)
{
public static unsafe short NetToInt16(byte[] value, int startIndex) {
if (value == null || startIndex > value.Length - 2) {
throw new NotImplementedException();
}
fixed (byte* numRef = &(value[startIndex]))
{
return (short)((numRef[0] << 8) | numRef[1]);
fixed (byte* numRef = &(value[startIndex])) {
return (short) ((numRef[0] << 8) | numRef[1]);
}
}
public static unsafe int NetToInt32(byte[] value, int startIndex)
{
if (value == null || startIndex > value.Length - 4)
{
public static unsafe int NetToInt32(byte[] value, int startIndex) {
if (value == null || startIndex > value.Length - 4) {
throw new NotImplementedException();
}
fixed (byte* numRef = &(value[startIndex]))
{
return (int)((numRef[0] << 24) | (numRef[1] << 16) | (numRef[2] << 8) | numRef[3]);
fixed (byte* numRef = &(value[startIndex])) {
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);
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
if (bytes == null || bytes.Length == 0)
return string.Empty;
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.Collections.Generic;
namespace DataService
{
public struct HistoryData : IComparable<HistoryData>
{
namespace DataService {
public struct HistoryData : IComparable<HistoryData> {
public short ID;
public QUALITIES Quality;
public Storage Value;
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;
Quality = qualitie;
Value = value;
TimeStamp = timeStamp;
}
public override bool Equals(object obj)
{
public override bool Equals(object obj) {
if (obj == null) return false;
if (obj is HistoryData)
{
return this == (HistoryData)obj;
}
else return false;
if (obj is HistoryData) {
return this == (HistoryData) obj;
} else return false;
}
public override int GetHashCode()
{
public override int 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;
}
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;
}
public static readonly HistoryData Empty = new HistoryData();
public int CompareTo(HistoryData other)
{
public int CompareTo(HistoryData other) {
int comp = this.TimeStamp.CompareTo(other.TimeStamp);
return comp == 0 ? this.ID.CompareTo(other.ID) : comp;
}
}
public struct FileData : IComparable<FileData>
{
public struct FileData : IComparable<FileData> {
public short ID;
public Storage Value;
public string Text;
public FileData(short id, Storage value, string text)
{
public FileData(short id, Storage value, string text) {
ID = id;
Value = value;
Text = text;
}
public int CompareTo(FileData other)
{
public int CompareTo(FileData other) {
return this.ID.CompareTo(other.ID);
}
}
public class CompareHistoryData : IComparer<HistoryData>
{
public int Compare(HistoryData x, HistoryData y)
{
public class CompareHistoryData : IComparer<HistoryData> {
public int Compare(HistoryData x, HistoryData y) {
int c1 = x.TimeStamp.CompareTo(y.TimeStamp);
return c1 == 0 ? x.ID.CompareTo(y.ID) : c1;
}
}
}
}

21
SCADA/Program/DataService/IGroup.cs

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

33
SCADA/Program/DataService/IReader.cs

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

32
SCADA/Program/DataService/IServer.cs

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

419
SCADA/Program/DataService/ITag.cs

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

520
SCADA/Program/DataService/PLCGroup.cs

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

49
SCADA/Program/DataService/Storage.cs

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

39
SCADA/Program/DataService/TagMetaData.cs

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