C# SCADA
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

806 lines
31 KiB

using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using DataService;
using HMIControl;
using Microsoft.Research.DynamicDataDisplay.DataSources;
using FORMS = System.Windows.Forms;
namespace CoreTest
{
public static class WindowHelper
{
//绑定到DAServer,采用递归
public static List<TagNodeHandle> BindingToServer(this DependencyObject panel, IDataServer _srv)
{
if (_srv == null) return null;
ExpressionEval eval = _srv.Eval;
List<TagNodeHandle> valueChangedList = new List<TagNodeHandle>();
var items = panel.FindTagControls();
if (items != null)
{
foreach (var element in items)
{
BindingControl(element, valueChangedList, eval);
}
}
eval.Clear();
valueChangedList.Sort();
return valueChangedList;
}
private static void BindingControl(ITagLink taglink, List<TagNodeHandle> valueChangedList, ExpressionEval eval)
{
var ctrl = taglink as UIElement;
if (ctrl == null) return;
var complex = taglink as ITagReader;
if (complex != null)
{
string txt = complex.TagReadText;
if (!string.IsNullOrEmpty(txt))
{
foreach (var v in txt.GetListFromText())
{
ITagLink tagConn = complex;
string[] strs = v.Key.Split('.');
if (strs.Length > 1)
{
for (int i = 0; i < strs.Length - 1; i++)
{
var c = tagConn as ITagReader;
if (c == null || c.Children == null) break;
foreach (var item in c.Children)
{
if (item.Node == strs[i])
{
tagConn = item;
break;
}
}
}
}
var r = tagConn as ITagReader;
var key = strs[strs.Length - 1];
try
{
var action = r.SetTagReader(key, eval.Eval(v.Value));
if (action != null)
{
action();
ValueChangedEventHandler handle = (s1, e1) =>
{
ctrl.InvokeAsynchronously(action);
};
foreach (ITag tag in eval.TagList)
{
valueChangedList.Add(new TagNodeHandle(tag.ID, key, tagConn, handle));
tag.ValueChanged += handle;
}
}
}
catch (Exception e)
{
App.AddErrorLog(e);
MessageBox.Show(string.Format("设备'{0}'属性'{1}'的值'{2}'转化出错!", string.IsNullOrEmpty(r.Node) ? r.GetType().ToString() : r.Node, key, v.Value));
}
if (Attribute.IsDefined(tagConn.GetType(), typeof(StartableAttribute), false))
{
FrameworkElement element = tagConn as FrameworkElement;
element.Cursor = Cursors.UpArrow;
element.AddHandler(UIElement.MouseEnterEvent, new MouseEventHandler(element_MouseEnter));
element.AddHandler(UIElement.MouseLeaveEvent, new MouseEventHandler(element_MouseLeave));
element.AddHandler(UIElement.MouseLeftButtonDownEvent, new MouseButtonEventHandler(element_MouseLeftButtonDown));
}
var hmi = tagConn as HMIControlBase;
if (hmi != null && hmi.ShowCaption && !string.IsNullOrEmpty(hmi.Caption))
{
AdornerLayer lay = AdornerLayer.GetAdornerLayer(hmi);
if (lay != null)
{
TextAdorner frame = new TextAdorner(hmi);
frame.Text = hmi.Caption;
lay.Add(frame);
}
}
}
}
}
var writer = taglink as ITagWriter;
if (writer != null && !string.IsNullOrEmpty(writer.TagWriteText))
{
var delgts = new List<Delegate>();
foreach (var item in writer.TagWriteText.GetListFromText())
{
try
{
if (!string.IsNullOrEmpty(item.Value))
delgts.Add(eval.WriteEval(item.Key, item.Value));
else
delgts.Add(eval.WriteEval(item.Key));
}
catch (Exception e)
{
App.AddErrorLog(e);
MessageBox.Show(string.Format("设备{0}变量{1}写入PLC公式转换失败", taglink.Node, item.Key) + "\n" + e.Message);
}
writer.SetTagWriter(delgts);
}
}
}
static AnimationTimeline animaEnter = new DoubleAnimationUsingKeyFrames
{
KeyFrames = new DoubleKeyFrameCollection { new DiscreteDoubleKeyFrame(1.05, KeyTime.FromPercent(0)) }
};
static AnimationTimeline animaLeave = new DoubleAnimationUsingKeyFrames
{
KeyFrames = new DoubleKeyFrameCollection { new DiscreteDoubleKeyFrame(1, KeyTime.FromPercent(0)) }
};
static ScaleTransform GetScaleTransform(UIElement element)
{
var group = element.RenderTransform as TransformGroup;
ScaleTransform scale = null;
if (group == null)
{
scale = new ScaleTransform();
element.RenderTransform = new TransformGroup { Children = new TransformCollection { element.RenderTransform, scale } };
}
else
{
if (group.IsFrozen)
group = group.Clone();
foreach (var transform in group.Children)
{
scale = transform as ScaleTransform;
if (scale != null)
break;
}
if (scale == null)
{
scale = new ScaleTransform();
group.Children.Add(scale);
}
element.RenderTransform = group;
}
return scale;
}
static void element_MouseEnter(object sender, MouseEventArgs e)
{
UIElement element = sender as UIElement;
//ScaleTransform scale = GetScaleTransform(element);
//scale.BeginAnimation(ScaleTransform.ScaleXProperty, animaEnter);
//scale.BeginAnimation(ScaleTransform.ScaleYProperty, animaEnter);
AdornerLayer lay = AdornerLayer.GetAdornerLayer(element);
if (lay != null)
{
FrameAdorner frame = new FrameAdorner(element);
lay.Add(frame);
}
}
static void element_MouseLeave(object sender, MouseEventArgs e)
{
UIElement element = sender as UIElement;
//var scale = GetScaleTransform(element);
//scale.BeginAnimation(ScaleTransform.ScaleXProperty, animaLeave);
//scale.BeginAnimation(ScaleTransform.ScaleYProperty, animaLeave);
AdornerLayer lay = AdornerLayer.GetAdornerLayer(element);
if (lay != null)
{
var adorners = lay.GetAdorners(element);
if (adorners != null)
{
FrameAdorner frame = null;
for (int i = 0; i < adorners.Length; i++)
{
frame = adorners[i] as FrameAdorner;
if (frame != null)
{
lay.Remove(frame);
return;
}
}
}
}
}
static StartDevice frm1 = null;
static void element_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
HMIControlBase ui = sender as HMIControlBase;
if (ui != null && !string.IsNullOrEmpty(ui.DeviceName))
{
if (frm1 != null)
frm1.Close();
frm1 = new StartDevice(ui.DeviceName, ui.PointToScreen(new Point(ui.ActualWidth / 2, ui.ActualHeight / 2)));
frm1.Show();
}
e.Handled = true;
}
static ITagLink FindElement(ITagLink tag, string key)
{
ITagLink tagConn = tag;
string[] strs = key.Split('.');
for (int i = 0; i < strs.Length; i++)
{
var c = tagConn as ITagReader;
if (c == null || c.Children == null) break;
foreach (var item in c.Children)
{
if (item.Node == strs[i])
{
tagConn = item;
break;
}
}
}
return tagConn;
}
public static IEnumerable<DependencyObject> FindVisualChildren(this DependencyObject parent)
{
var count = VisualTreeHelper.GetChildrenCount(parent);
if (count > 0)
{
for (var i = 0; i < count; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
yield return child;
var children = FindVisualChildren(child);
foreach (var item in children)
yield return item;
}
}
}
public static IEnumerable<T> FindChildren<T>(this DependencyObject parent) where T : class
{
var count = VisualTreeHelper.GetChildrenCount(parent);
if (count > 0)
{
for (var i = 0; i < count; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
var t = child as T;
if (t != null)
yield return t;
var children = FindChildren<T>(child);
foreach (var item in children)
yield return item;
}
}
}
public static IEnumerable<ITagLink> FindTagControls(this DependencyObject parent)
{
var count = VisualTreeHelper.GetChildrenCount(parent);
if (count > 0)
{
for (var i = 0; i < count; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
var t = child as ITagLink;
if (t != null)
yield return t;
else
{
var children = FindTagControls(child);
foreach (var item in children)
yield return item;
}
}
}
}
public static LinkLine FindLine(this DependencyObject parent, string source, string target)
{
if (string.IsNullOrEmpty(source) || string.IsNullOrEmpty(target)) return null;
var controls = parent.FindTagControls(); if (controls == null) return null;
var lines = new List<LinkLine>();
Rect sourcerect = Rect.Empty;
Rect targetrect = Rect.Empty;
foreach (var ctrl in controls)
{
var element = ctrl as HMIControlBase;
if (element != null)
{
if (sourcerect == Rect.Empty && element.Caption == source)
{
sourcerect = new Rect(element.TranslatePoint(new Point(), element.Parent as UIElement), new Size(element.ActualWidth, element.ActualHeight));
}
else if (targetrect == Rect.Empty && element.Caption == target)
{
targetrect = new Rect(element.TranslatePoint(new Point(), element.Parent as UIElement), new Size(element.ActualWidth, element.ActualHeight));
}
}
else
{
var line = ctrl as LinkLine;
if (line != null)
{
if (sourcerect != Rect.Empty && targetrect != Rect.Empty)
{
if (line.OriginInfo.DesignerRect == sourcerect && line.TargetInfo.DesignerRect == targetrect)
return line;
}
else
lines.Add(line);
}
}
}
if (sourcerect == Rect.Empty || targetrect == Rect.Empty)
return null;
foreach (LinkLine line in lines)
{
if (line.OriginInfo.DesignerRect == sourcerect && line.TargetInfo.DesignerRect == targetrect)
return line;
}
return null;
}
public static T HitTest<T>(this Visual hitobj, Point p)
{
var target = VisualTreeHelper.HitTest(hitobj, p).VisualHit;
while (target != null && !(target is T))
{
target = VisualTreeHelper.GetParent(target);
}
return target == null ? default(T) : (T)((object)target);
}
public static Window GetParentWindow(this DependencyObject child)
{
DependencyObject parentObject = VisualTreeHelper.GetParent(child);
if (parentObject == null)
{
return null;
}
Window parent = parentObject as Window;
if (parent != null)
{
return parent;
}
else
{
return GetParentWindow(parentObject);
}
}
public static void RemoveHandles(this IDataServer srv, params List<TagNodeHandle>[] handleLists)
{
foreach (var handleList in handleLists)
{
if (handleList != null)
{
foreach (var item in handleList)
{
srv[item.TagID].ValueChanged -= item.Handle;
var element = item.Element as FrameworkElement;
if (element != null)
{
element.RemoveHandler(UIElement.MouseEnterEvent, new MouseEventHandler(element_MouseEnter));
element.RemoveHandler(UIElement.MouseLeaveEvent, new MouseEventHandler(element_MouseLeave));
element.RemoveHandler(UIElement.MouseLeftButtonDownEvent, new MouseButtonEventHandler(element_MouseLeftButtonDown));
}
}
handleList.Clear();
}
}
}
public static void SetWindowState(this Window window)
{
Dictionary<string, Rect> dict = ConfigCache.Windows;
string name = window.DependencyObjectType.Name;
if (dict.ContainsKey(name))
{
Rect rec = dict[name];
if (rec.Width == 0 || rec.Height == 0 || double.IsInfinity(rec.Left) || double.IsInfinity(rec.Top))
{
window.WindowState = WindowState.Maximized;
window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
}
else
{
window.Left = rec.Left;
window.Top = rec.Top;
window.Width = rec.Width;
window.Height = rec.Height;
}
}
else
{
ConfigCache.Windows.Add(name, new Rect());
window.WindowState = WindowState.Maximized;
window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
}
}
public static void SaveWindowState(this Window window)
{
Dictionary<string, Rect> dict = ConfigCache.Windows;
dict[window.DependencyObjectType.Name] = window.WindowState == WindowState.Maximized ? new Rect() :
new Rect(window.Left, window.Top, window.Width, window.Height);
}
public static Window FindWindow(string name)
{
foreach (Window window in App.Current.Windows)
{
if (window.DependencyObjectType.Name == name)
{
return window;
}
}
return null;
}
public static void SetWindowPos(this Window window, int screenIndex)
{
var screens = FORMS.Screen.AllScreens;//只是测试状态,待完善
if (screenIndex < screens.Length)
{
var area = screens[screenIndex].WorkingArea;
if (window.WindowState == WindowState.Maximized)
{
window.Top = area.Top;
window.Left = area.Left;
}
else
{
window.Top += area.Top;
window.Left += area.Left;
}
}
}
public static void InvokeAsynchronously(this UIElement element, Action action)
{
if (element.Dispatcher.CheckAccess())
{
action();
}
else
element.Dispatcher.BeginInvoke(action, System.Windows.Threading.DispatcherPriority.Normal);
}
public static void GetWorkInfo(DateTime current, out DateTime start, out DateTime end, out string team)
{
float[] startarray = new float[3] { App.Server["START_1"].Value.Single, App.Server["START_2"].Value.Single, App.Server["START_3"].Value.Single };
float[] endarray = new float[3] { App.Server["END_1"].Value.Single, App.Server["END_2"].Value.Single, App.Server["END_3"].Value.Single };
double hour = current.Hour + current.Minute / 60.0;
//Array.Sort(startarray);
DateTime today = current.Date;
for (int i = 0; i < startarray.Length; i++)
{
if (startarray[i] == endarray[i]) continue;
if (hour >= startarray[i] && hour <= endarray[i])
{
start = today.AddHours(startarray[i]);
end = today.AddHours(endarray[i]);
team = i.ToString();
return;
}
else if (startarray[i] >= endarray[i] && hour >= startarray[i])
{
start = today.AddHours(startarray[i]);
end = today.AddDays(1).AddHours(endarray[i]);
team = i.ToString();
return;
}
else if (startarray[i] >= endarray[i] && hour <= endarray[i])
{
start = today.AddDays(-1).AddHours(startarray[i]);
end = today.AddHours(endarray[i]);
team = i.ToString();
return;
}
}
start = current.AddHours(-8);
end = current;
team = null;
}
//startTime/endTime:班次上/下班时间 starthour/endhour:阶段起始/结束时间 start/end:本班次阶段区间
public static void GetTimeRange(DateTime startTime, DateTime endTime, float starthour, float endhour, out DateTime start, out DateTime end)
{
if (starthour == endhour)
{
start = end = DateTime.MinValue;
return;
}
DateTime startdate = startTime.Date;
DateTime enddate = endTime.Date;
double hstart = startTime.Hour + startTime.Minute / 60.0 + startTime.Second / 60.0;
double hend = endTime.Hour + endTime.Minute / 60.0 + endTime.Second / 60.0;
if (startdate == enddate)
{
if (endhour > starthour)
{
start = starthour > hstart ? startdate.AddHours(starthour) : startTime;
end = endhour < hend ? startdate.AddHours(endhour) : endTime;
}
else
{
if (endhour > hstart)
{
start = startTime;
end = endhour > hend ? endTime : startdate.AddHours(endhour);
}
else if (starthour < hend)
{
end = endTime;
start = starthour > hstart ? startdate.AddHours(starthour) : startTime;
}
else
{
start = end = DateTime.MinValue;
}
}
}
else
{
if (endhour > starthour)
{
if (endhour > hstart)
{
start = starthour > hstart ? startdate.AddHours(starthour) : startTime;
end = startdate.AddHours(endhour);
}
else if (starthour < hend)
{
end = endhour < hend ? enddate.AddHours(endhour) : endTime;
start = enddate.AddHours(starthour);
}
else
{
start = end = DateTime.MinValue;
}
}
else
{
start = starthour > hstart ? startdate.AddHours(starthour) : startTime;
end = endhour < hend ? enddate.AddHours(endhour) : endTime;
}
}
}
public static void SetSourceMapping(this QueueListSource<HistoryData> source, ITag currentTag)
{
if (currentTag != null)
{
switch (currentTag.Address.VarType)
{
case DataType.BOOL:
source.SetYMapping(Y => Y.Value.Boolean ? 1 : 0);
break;
case DataType.BYTE:
source.SetYMapping(Y => Y.Value.Byte);
break;
case DataType.WORD:
case DataType.SHORT:
source.SetYMapping(Y => Y.Value.Int16);
break;
case DataType.TIME:
case DataType.INT:
source.SetYMapping(Y => Y.Value.Int32);
break;
case DataType.FLOAT:
source.SetYMapping(Y => Y.Value.Single);
break;
}
}
}
public static void SetSourceMapping(this ObservableDataSource<HistoryData> source, ITag currentTag)
{
if (currentTag != null)
{
switch (currentTag.Address.VarType)
{
case DataType.BOOL:
source.SetYMapping(Y => Y.Value.Boolean ? 1 : 0);
break;
case DataType.BYTE:
source.SetYMapping(Y => Y.Value.Byte);
break;
case DataType.WORD:
case DataType.SHORT:
source.SetYMapping(Y => Y.Value.Int16);
break;
case DataType.TIME:
case DataType.INT:
source.SetYMapping(Y => Y.Value.Int32);
break;
case DataType.FLOAT:
source.SetYMapping(Y => Y.Value.Single);
break;
}
}
}
}
public class TagNodeHandle : IComparable<TagNodeHandle>
{
short _tagID;
public short TagID
{
get
{
return _tagID;
}
}
string _key;
public string Key
{
get
{
return _key;
}
}
ITagLink _element;
public ITagLink Element
{
get
{
return _element;
}
}
ValueChangedEventHandler _handle;
public ValueChangedEventHandler Handle
{
get
{
return _handle;
}
}
public TagNodeHandle(short tag, string key, ITagLink element, ValueChangedEventHandler handle)
{
_tagID = tag;
_key = key;
_element = element;
_handle = handle;
}
public int CompareTo(TagNodeHandle other)
{
int comp = _tagID.CompareTo(other._tagID);
return comp == 0 ? _key.CompareTo(other._key) : comp;
}
}
public static class Extension
{
public static string GetNullableString(this SqlDataReader dataReader, int index)
{
var svr = dataReader.GetSqlString(index);
return svr.IsNull ? null : svr.Value;
}
public static string GetNullableString(this DateTime? time)
{
return time.HasValue ? "'" + time.ToString() + "'" : "NULL";
}
/// <summary>
/// 返回指定变量最接近指定时间的值
/// </summary>
/// <param name="list"></param>
/// <param name="time">时间</param>
/// <param name="id"></param>
/// <returns></returns>
public static int GetInt(this IEnumerable<HistoryData> list, DateTime time, short id)
{
var data = (from raw in list where raw.ID == id && raw.TimeStamp <= time && raw.Value.Int32 > 0 select raw.Value.Int32).LastOrDefault();
if (data == 0) data = (from raw in list where raw.ID == id && raw.TimeStamp >= time && raw.Value.Int32 > 0 select raw.Value.Int32).FirstOrDefault();
return data;
}
/// <summary>
/// 返回变量最接近指定时间的值
/// </summary>
/// <param name="list"></param>
/// <param name="time">时间</param>
/// <returns></returns>
public static int GetInt(this IEnumerable<HistoryData> list, DateTime time)
{
var data = (from raw in list where raw.TimeStamp <= time && raw.Value.Int32 > 0 select raw.Value.Int32).LastOrDefault();
if (data == 0) data = (from raw in list where raw.TimeStamp >= time && raw.Value.Int32 > 0 select raw.Value.Int32).FirstOrDefault();
return data;
}
/// <summary>
/// 返回在开始时间和结束时间范围内变量的变化值
/// </summary>
/// <param name="list"></param>
/// <param name="start">开始时间</param>
/// <param name="end">结束时间</param>
/// <param name="id"></param>
/// <returns></returns>
public static int GetInt(this IEnumerable<HistoryData> list, DateTime start, DateTime end, short id)
{
return GetInt(list, end, id) - GetInt(list, start, id);
}
/// <summary>
/// 返回指定变量最接近指定时间的值
/// </summary>
/// <param name="list"></param>
/// <param name="time">时间</param>
/// <param name="id"></param>
/// <returns></returns>
public static float GetFloat(this IEnumerable<HistoryData> list, DateTime time, short id)
{
var data = (from raw in list where raw.ID == id && raw.TimeStamp <= time && raw.Value.Single > 0 select raw.Value.Single).LastOrDefault();
if (data == 0) data = (from raw in list where raw.ID == id && raw.TimeStamp >= time && raw.Value.Single > 0 select raw.Value.Single).FirstOrDefault();
return data;
}
/// <summary>
/// 返回变量最接近指定时间的值
/// </summary>
/// <param name="list"></param>
/// <param name="time">时间</param>
/// <returns></returns>
public static float GetFloat(this IEnumerable<HistoryData> list, DateTime time)
{
var data = (from raw in list where raw.TimeStamp <= time && raw.Value.Single > 0 select raw.Value.Single).LastOrDefault();
if (data == 0) data = (from raw in list where raw.TimeStamp >= time && raw.Value.Single > 0 select raw.Value.Single).FirstOrDefault();
return data;
}
/// <summary>
/// 返回在开始时间和结束时间范围内变量的变化值
/// </summary>
/// <param name="list"></param>
/// <param name="start">开始时间</param>
/// <param name="end">结束时间</param>
/// <param name="id"></param>
/// <returns></returns>
public static float GetFloat(this IEnumerable<HistoryData> list, DateTime start, DateTime end, short id)
{
return GetFloat(list, end, id) - GetFloat(list, start, id);
}
public static float GetFloat2(this List<HistoryData> list, DateTime start, DateTime end, short id)
{
float result = 0;
var data = (from raw in list where raw.TimeStamp >= start && raw.TimeStamp <= end && raw.ID == id && raw.Value.Single >= 0 select raw.Value.Single).ToList();
if (data.Count > 0)
{
List<int> li = new List<int>();
li.Add(0);
for (int i = 0; i < data.Count - 1; i++)
{
if (data[i] > data[i + 1] && i > 0)
{
li.Add(i);
}
}
li.Add(data.Count - 1);
for (int i = 1; i < li.Count; i++)
{
result += data[li[i]] - data[li[i - 1] + 1];
}
}
return result;
}
}
}