using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.ComponentModel;
namespace FLY.Simulation.Coating
{
public class Coating : INotifyPropertyChanged, Misc.ISaveToXml
{
public CoatingCtrl hmi_cc;
public CoatingCtrl inner_cc;
public HMI hmi;
private FLY.Simulation.Coating.CoatingCtrl.COATINGMODE coatingmode = CoatingCtrl.COATINGMODE.Extrusion;
///
/// 涂布类型
///
public FLY.Simulation.Coating.CoatingCtrl.COATINGMODE CoatingMode
{
get {
return coatingmode;
}
set {
if (coatingmode != value)
{
coatingmode = value;
hmi_cc.CoatingMode = value;
inner_cc.CoatingMode = value;
}
}
}
public int Port { get; set; } = 502;
public class DataInfo
{
///
/// 上光纤是亮
///
public bool IsLight;
///
/// 下光纤是亮
///
public bool IsLight2;
///
/// 厚度值
///
public int Thick;
}
//当前数据
public List Datas_Vertical = new List();//纵向数据
public List Datas_Horizontal = new List();//横向数据
int datas_horizontal_avg = 0;
int datas_vertical_position=0;
//30m 后的数据
public List Datas_Vertical_30m = new List();//纵向数据
public List Datas_Horizontal_30m = new List();//横向数据
int datas_vertical_30m_position=0;
///
/// 膜宽
///
public int FilmWidth => Datas_Horizontal.Count();
///
/// 膜速度 m/min
///
public double FilmVelocity { get; set; } = 12;
///
/// 辊周长 mm
///
public double MmOfR=120*3.14;
///
/// 辊信号长度 mm
///
public double MmOfRSignal = 10;
///
/// 当前辊位置 mm
///
double RPosition = 0;
///
/// 膜已经跑了的长度。m
///
public double FilmLength { get; set; }
///
/// 烘箱长度 30m
///
public double OvenLength = 30;
///
/// 辊信号
///
public bool RSignal;
///
/// 上纵向信号
///
public bool VSignal;
///
/// 下纵向信号
///
public bool VSignal2;
///
/// 上横向信号
///
public bool HSignal;
///
/// 下横向信号
///
public bool HSignal2;
public bool DeviceState { get; set; }
public double Avg { get; set; }
void Load_Vertical()
{
Datas_Vertical.Clear();
using (StreamReader sr = new StreamReader(@"coating\datas_vertical.csv"))
{
string header = sr.ReadLine();//标题 , 位置(mm), 纵向信号,厚度
while (!sr.EndOfStream)
{
string s = sr.ReadLine();
string[] ss = s.Split(',');
int pos_mm = int.Parse(ss[0]);
bool isLight = bool.Parse(ss[1]);
bool isLight2 = bool.Parse(ss[2]);
int thick = (int)(double.Parse(ss[3]) * 100);
Datas_Vertical.Add(new DataInfo() { IsLight = isLight, IsLight2 = isLight2, Thick = thick });
Datas_Vertical_30m.Add(new DataInfo() { IsLight = isLight, IsLight2 = isLight2, Thick = thick });
}
sr.Close();
}
}
void Load_Horizontal()
{
Datas_Horizontal.Clear();
using (StreamReader sr = new StreamReader(@"coating\datas_horizontal.csv"))
{
string header = sr.ReadLine();//标题 , 位置(mm), 厚度
while (!sr.EndOfStream)
{
string s = sr.ReadLine();
string[] ss = s.Split(',');
int pos_mm = int.Parse(ss[0]);
bool isLight = bool.Parse(ss[1]);
bool isLight2 = bool.Parse(ss[2]);
int thick = (int)(double.Parse(ss[3]) * 100.0);
Datas_Horizontal.Add(new DataInfo() { IsLight = isLight, IsLight2 = isLight2, Thick = thick });
Datas_Horizontal_30m.Add(new DataInfo() { IsLight = isLight, IsLight2 = isLight2, Thick = thick });
}
sr.Close();
}
}
void Load()
{
Load_Vertical();
Load_Horizontal();
datas_horizontal_avg = (int)(Datas_Horizontal.Average((d) => { return d.Thick; }));
Misc.SaveToXmlHepler.Load("simulation_coating.xml", this);
}
public void Save()
{
Misc.SaveToXmlHepler.Save("simulation_coating.xml", this);
}
public Coating()
{
hmi_cc = new CoatingCtrl(this);
inner_cc = new CoatingCtrl(this);
DeviceState = true;
Load();
hmi = new HMI(this, hmi_cc, Port);
this.PropertyChanged += new PropertyChangedEventHandler(Coating_PropertyChanged);
}
void Coating_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "CoatingMode")
Save();
}
///
/// 获取30m后的数据
///
///
///
public int GetData30m(int mm)
{
if (mm < 0)
return 0;
if (mm >= FilmWidth)
return 0;
return (int)(Datas_Vertical_30m[datas_vertical_position].Thick * ((double)Datas_Horizontal_30m[mm].Thick) / datas_horizontal_avg);
}
public int GetData(int mm)
{
if (mm < 0)
return 0;
if (mm >= FilmWidth)
return 0;
return (int)(Datas_Vertical[datas_vertical_position].Thick * ((double)Datas_Horizontal[mm].Thick) / datas_horizontal_avg);
}
///
/// 上一个时间点
///
DateTime dtLast = DateTime.MinValue;
public void OnPoll(DateTime now)
{
if (dtLast == DateTime.MinValue)
{
dtLast = now;
return;
}
TimeSpan ts= now - dtLast;
dtLast = now;
if (!DeviceState)//没有涂布
return;
double filmMove = ts.TotalMinutes * FilmVelocity;
FilmLength += filmMove;//膜位置
int p1 = (int)(FilmLength * 1000 % Datas_Vertical.Count());
if (p1 != datas_vertical_position)
{
datas_vertical_position = p1;
Avg = Datas_Vertical[datas_vertical_position].Thick / 100.0;
if (AvgChanged != null)
{
AvgChanged(FilmLength, (int)(Avg*100));
}
}
datas_vertical_30m_position = (int)((FilmLength - OvenLength) * 1000 % Datas_Vertical.Count());
if (datas_vertical_30m_position < 0)
datas_vertical_30m_position += Datas_Vertical.Count();
//更新纵向信号
VSignal = Datas_Vertical[datas_vertical_position].IsLight;
VSignal2 = Datas_Vertical[datas_vertical_position].IsLight2;
//更新辊信号
RPosition += filmMove * 1000;
RPosition = RPosition % MmOfR;
if (RPosition < MmOfRSignal)
RSignal = true;
else
RSignal = false;
hmi_cc.OnPoll(filmMove);
inner_cc.OnPoll(filmMove);
}
///
/// 每1mm更新一次
///
public event Action AvgChanged;
public event Action DatasChanged;
public event Action Datas30mChanged;
public void NotifyDatasChanged()
{
if (DatasChanged != null)
{
DatasChanged();
}
}
public void NotifyDatas30mChanged()
{
if (Datas30mChanged != null)
{
Datas30mChanged();
}
}
protected void NotifyPropertyChanged(string propertyname)
{
if (PropertyChanged != null)
{
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyname));
}
}
public event PropertyChangedEventHandler PropertyChanged;
public string[] GetSavePropertyNames()
{
return new string[] {
"Port",
"CoatingMode"
};
}
}
///
/// 涂布控制量
///
public class CoatingCtrlElement:INotifyPropertyChanged
{
///
/// 控制的时间
///
public DateTime Time = DateTime.Now;
private double pump;
public double Pump
{
get
{
return pump;
}
set
{
if (pump != value)
{
pump = value;
NotifyPropertyChanged("Pump");
}
}
}
private double left;
public double LeftDis
{
get
{
return left; ;
}
set
{
if (left != value)
{
left = value;
NotifyPropertyChanged("LeftDis");
}
}
}
private double right;
public double RightDis
{
get
{
return right;
}
set
{
if (right != value)
{
right = value;
NotifyPropertyChanged("RightDis");
}
}
}
///
/// 膜移动的距离
///
public double FilmMove=0;
protected void NotifyPropertyChanged(string propertyname)
{
if (PropertyChanged != null)
{
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyname));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
public class CoatingCtrl : INotifyPropertyChanged
{
Coating mCoating;
#region 参数
public enum COATINGMODE
{
///
/// 挤压涂布
///
Extrusion,
///
/// 转移涂布
///
Transfer
}
///
/// 涂布类型
///
public COATINGMODE CoatingMode = COATINGMODE.Extrusion;
///
/// 泵速因子 1 个 面密度 = N个泵速, 只有挤压涂布有效
///
public double PumpFactor = 0.5;
///
/// 左右刀因子 1个面密度 = N个左右刀
///
public double LeftRightFactor = 1;
///
/// 当前涂布控制量
///
public CoatingCtrlElement NowCtrl;
CoatingCtrlElement NowCtrl_30m;
#endregion
///
/// 控制量
///
List mCtrlElement = new List();
public CoatingCtrl(Coating coating)
{
mCoating = coating;
NowCtrl = new CoatingCtrlElement() { FilmMove = 0, Pump = 90, LeftDis = 200, RightDis = 210 };
NowCtrl_30m = new CoatingCtrlElement() { FilmMove = 0, Pump = 90, LeftDis = 200, RightDis = 210 };
}
public void OnPoll(double filmMove)
{
for (int i = 0; i < mCtrlElement.Count(); i++)
{
if (mCtrlElement[i].FilmMove=mCoating.OvenLength)
{
CoatingAction(NowCtrl_30m, mCtrlElement[i], mCoating.Datas_Vertical_30m, mCoating.Datas_Horizontal_30m, mCoating.NotifyDatas30mChanged);
mCtrlElement.RemoveAt(i);
i--;
}
else
break;
}
}
///
/// 控制量生效
///
///
///
///
void CoatingAction(CoatingCtrlElement now, CoatingCtrlElement element, List datas_vertical, List datas_horizontal, Action NotifyDatasChanged)
{
if (CoatingMode == COATINGMODE.Extrusion)
{
double d_left = element.LeftDis - now.LeftDis;
double d_right = element.RightDis - now.RightDis;
double d = (d_right - d_left) / LeftRightFactor * 100;
for (int i = 0; i < datas_horizontal.Count(); i++)
{
datas_horizontal[i].Thick += (int)(d * i / (datas_horizontal.Count() - 1) - d / 2);
}
double d_pump = element.Pump - now.Pump;
d = (d_pump / PumpFactor) * 100;
for (int i = 0; i < datas_vertical.Count(); i++)
{
FLY.Simulation.Coating.Coating.DataInfo vi = datas_vertical[i];
vi.Thick += (int)d;
datas_vertical[i] = vi;
}
}
else
{
double d_left = element.LeftDis - now.LeftDis;
double d_right = element.RightDis - now.RightDis;
double d = (d_right - d_left) / LeftRightFactor * 100;
for (int i = 0; i < datas_horizontal.Count(); i++)
{
datas_horizontal[i].Thick += (int)(d * i / (datas_horizontal.Count() - 1) - d / 2);
}
d = (d_left + d_right) / 2 / LeftRightFactor * 100;
for (int i = 0; i < datas_vertical.Count(); i++)
{
FLY.Simulation.Coating.Coating.DataInfo vi = datas_vertical[i];
vi.Thick += (int)d;
datas_vertical[i] = vi;
}
}
now.Pump = element.Pump;
now.LeftDis = element.LeftDis;
now.RightDis = element.RightDis;
now.Time = element.Time;
NotifyDatasChanged();
}
public void SetCoatingCtrl(double pump, double left, double right)
{
CoatingCtrlElement element = new CoatingCtrlElement() { Pump = pump, LeftDis = left, RightDis = right };
mCtrlElement.Add(element);
CoatingAction(NowCtrl, element, mCoating.Datas_Vertical, mCoating.Datas_Horizontal, mCoating.NotifyDatasChanged);
}
protected void NotifyPropertyChanged(string propertyname)
{
if (PropertyChanged != null)
{
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyname));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}