/// <summary>
        /// KPI_Archive的操作
        /// </summary>
        /// <returns></returns>
        public bool KPIArchiveCalc()
        {
            #region 系统初始化

            ////////////////////////////////////////////////////////////////////////////////////////////
            //1. 系统参数初始化
            m_KPIVar.bFirst = true;
            if (!m_KPIVar.KPIInitialVar()) {
                LogUtil.LogMessage("系统初始化错误!");
                return false;
            }

            ////////////////////////////////////////////////////////////////////////////////////////////
            //2. 获取历史计算列表
            List<KPI_RedoEntity> lts = m_KPIVar.KPIGetRedos();
            if (lts.Count <= 0) {
                return true;
            }

            #endregion

            #region 机组循环

            /////////////////////////////////////////////////////////////////
            //0-	机组集,当前只有 机组有效................................
            ////////////////////////////////////////////////////////////////
            //1-	设备集
            //2-	指标集
            //3-	经济指标
            //4-	安全指标
            foreach (KPI_RedoEntity redo in lts) {
                #region 初始化

                if (redo.RDIsCalced > 0) {
                    continue;
                }

                ////////////////////////////////////////////////////////////////////////////////

                //机组信息
                KPI_UnitEntity ue = new KPI_UnitEntity();
                foreach (KPI_UnitEntity ueone in m_KPIVar.ltUnits) {
                    if (ueone.UnitID == redo.RDKPIID) {
                        ue = ueone;
                    }
                }

                if (ue == null) {
                    continue;
                }

                DateTime dtST = DateTime.Parse(redo.RDStartTime);
                DateTime dtET = DateTime.Parse(redo.RDEndTime);

                //历史重算时一律使用数据库服务器时间
                DateTime dtServerTime = DateTime.Now;

                if (KIsTest == 0) {
                    //非测试环境时需要使用PI Server Time
                    //dtServerTime = m_RTDataAccess.GetServerTime();
                }

                //记录相关信息!!
                string strInfor = "开始计算机组:" + ue.UnitCode + ", " + ue.UnitName;
                strInfor += "\r\n" + "开始时间:" + redo.RDStartTime + ", 结束时间:" + redo.RDEndTime;

                LogUtil.LogMessage(strInfor);

                //初始化开始时间
                DateTime dtStartTime = dtST.AddSeconds(dtST.Second * -1);

                bool bFirst = true;
                bool bsnap = false;
                bool bCollect = redo.RDIsCollect == 1 ? true : false;

                #endregion

                #region 时间周期循环

                //计算时间必须小于结束服务器时间,服务器时间,本地时间
                for (DateTime dtCurrentMinute = dtStartTime;                   //开始
                        (dtCurrentMinute < dtET
                            && dtCurrentMinute < dtServerTime
                            && dtCurrentMinute < DateTime.Now.AddMinutes(-2));  //判断
                    dtCurrentMinute = dtCurrentMinute.AddMinutes(1))            //增加1分钟
                {

                    //时间分钟
                    String strCurrentMinute = dtCurrentMinute.ToString("yyyy-MM-dd HH:mm:00");

                    Console.WriteLine("正在计算" + dtCurrentMinute.ToString("yyyy-MM-dd HH:mm:ss") + "指标数据。");

                    #region 同一台机组的时间循环
                    //////////////////////////////////////////////////////////////////////////////////
                    //错误信息
                    String strError = "";

                    #region  获得历史数据

                    //////////////////////////////////////////////////////////////////////////////////////////////
                    //3 实时数据
                    if (!GetUnitArchiveValue(ue, bFirst, dtCurrentMinute, bCollect, out strError)) {
                        LogUtil.LogMessage(strError);
                        bFirst = false;
                        LogUtil.LogMessage(ue.UnitCode + "," + ue.UnitName + "历史数据无法获取!" + strError);
                        continue;
                    }
                    //Console.WriteLine("获取测点历史数据成功。");
                    #endregion

                    #region 获得状态和值次

                    ///////////////////////////////////////////////////////////////////////
                    //6.1 计算条件
                    //机组状态和负荷
                    if (!GetUnitArchiveState(ue, dtCurrentMinute)) {
                    }
                    //Console.WriteLine("获取机组状态和负荷历史数据成功。");
                    ///////////////////////////////////////////////////////////////////////
                    //6.2 班次信息
                    //获取值班信息
                    String strWorkID = ue.WorkID;
                    if (strWorkID == null || strWorkID == "") {
                        bFirst = false;

                        continue;
                    }

                    //获取当前时间的值与班
                    String strCurrentShift = "";
                    String strCurrentPeriod = "";
                    String strStartTime = "";
                    String strEndTime = "";

                    KPI_WorkDal.GetShiftAndPeriod(strWorkID, strCurrentMinute,
                        ref strCurrentShift, ref strCurrentPeriod, ref strStartTime, ref strEndTime);
                    //Console.WriteLine("获取值与班数据成功。");

                    #endregion

                    ///////////////////////////////////////////////////////////////////////
                    //6.3 指标计算

                    //获取该机组、有效设备、有效指标集的所有指标
                    var kpiresult = from kpi in m_KPIVar.ltECs
                                    where (kpi.UnitID == ue.UnitID) //&&(kpi.ECIndex==1028)
                                    //        && m_KPIVar.ltSeqs.Contains(kpi.SeqID) && m_KPIVar.ltKpis.Contains(kpi.KpiID))
                                    orderby kpi.ECCalcClass
                                    select kpi;

                    //Console.WriteLine("获取该机组、有效设备、有效指标集的所有指标成功。");
                    ////////////////////////////////////////////////////////////////////////////
                    //历史数据
                    string ECTX = "";  //删除数据时使用,IN 查询
                    //BulkWrite to SQL
                    string BulkTable = "KPI_ECSSArchive";
                    DataTable dt = m_DBClient.GetTableSchema("kpivalue");

                    #region 指标循环

                    //指标计算
                    foreach (ECTagEntity ecte in kpiresult) {
                        #region 计算周期

                        //一律以0点开始的分钟、小时循环。
                        //不按值开始的时间进行循环。

                        //机组状态
                        bool bRunning = m_KPIVar.dicUnitStatus[ue.UnitID];
                        //Console.WriteLine("ECIndex=" + ecte.ECIndex);
                        //获取周期
                        CycleEntity cye = m_KPIVar.dicCYs[ecte.CycleID];
                        int ncyc = cye.CycleValue;
                        int nmin = dtCurrentMinute.Hour * 60 + dtCurrentMinute.Minute;

                        //Value Entity
                        ECSSValueEntity kpiECV = new ECSSValueEntity();

                        if (cye.CycleName == "TN") {
                            //按班周期循环计算的
                            if (KPICalcForTN(bsnap, ecte, cye, dtCurrentMinute, strCurrentShift, strCurrentPeriod, out kpiECV)) {

                            }

                        }
                        else if (cye.CycleName == "TD") {
                            //按日周期循环计算的
                            if (KPICalcForTD(bsnap, ecte, cye, dtCurrentMinute, strCurrentShift, strCurrentPeriod, out kpiECV)) {

                            }

                        }
                        else {
                            //第一次时必须全部计算
                            if (bFirst) {
                                if (KPICalcForTM(bsnap, bRunning, ecte, dtCurrentMinute, strCurrentShift, strCurrentPeriod, out kpiECV)) {

                                }

                            }
                            else {
                                //按分周期循环计算的
                                if (nmin % ncyc == 0) {
                                    if (KPICalcForTM(bsnap, bRunning, ecte, dtCurrentMinute, strCurrentShift, strCurrentPeriod, out kpiECV)) {

                                    }
                                }
                            }
                        }

                        #endregion

                        #region Add to BulkTable

                        ///////////////////////////////////////////////////////
                        //添加到DataTable
                        //Console.WriteLine("指标得分计算完成,准备写数据库。");
                        if ((kpiECV != null) && (!String.IsNullOrEmpty(kpiECV.UnitID))) {
                            ECTX += "'" + ecte.ECCode + "',";

                            DataRow dr = dt.NewRow();
                            dr["SSID"] = kpiECV.SSID;
                            dr["UnitID"] = kpiECV.UnitID;
                            dr["SeqID"] = kpiECV.SeqID;
                            dr["KpiID"] = kpiECV.KpiID;
                            dr["ECID"] = kpiECV.ECID;
                            dr["ECName"] = kpiECV.ECName;
                            dr["ECTX"] = ecte.ECCode;
                            dr["ECTime"] = kpiECV.ECTime;
                            //dr["ECValue"] = kpiECV.ECValue;
                            //dr["ECOpt"] = kpiECV.ECOpt
                            if (kpiECV.ECValue == double.MinValue) {
                                dr["ECValue"] = 0;// System.DBNull.Value;
                            }
                            else {
                                dr["ECValue"] = kpiECV.ECValue;
                            }
                            if (kpiECV.ECOpt == double.MinValue) {
                                dr["ECOpt"] = System.DBNull.Value;
                            }
                            else {
                                dr["ECOpt"] = kpiECV.ECOpt;
                            }

                            dr["ECOptExp"] = "";// kpiECV.ECOptExp;
                            dr["ECExpression"] = kpiECV.ECExpression;

                            //dr["ECScore"] = kpiECV.ECScore;
                            //dr["ECQulity"] = kpiECV.ECQulity;

                            if (kpiECV.ECScore == double.MinValue) {
                                dr["ECScore"] = 0;// System.DBNull.Value;
                            }
                            else {
                                dr["ECScore"] = kpiECV.ECScore;
                            }
                            if (kpiECV.ECQulity == int.MinValue) {
                                dr["ECQulity"] = 0;// System.DBNull.Value;
                            }
                            else {
                                dr["ECQulity"] = kpiECV.ECQulity;
                            }

                            dr["ECPeriod"] = kpiECV.ECPeriod;
                            dr["ECShift"] = kpiECV.ECShift;

                            //dr["ECIsRemove"] = kpiECV.ECIsRemove;
                            if (kpiECV.ECIsRemove == int.MinValue) {
                                dr["ECIsRemove"] = 0;// System.DBNull.Value;
                            }
                            else {
                                dr["ECIsRemove"] = kpiECV.ECIsRemove;
                            }

                            dt.Rows.Add(dr);
                        }
                        bFirst = false;
                        #endregion
                    }
                    //Console.WriteLine("ECTX=" + ECTX);
                    //Console.WriteLine("指标得分计算完成。");
                    if (dt.Rows.Count > 0) {
                        //删除
                        //Console.WriteLine("ECTX=" + ECTX);
                        ECTX = ECTX.TrimEnd(',');
                        //Console.WriteLine("删除历史数据完成。");
                        m_DBClient.DeleteData(ue.UnitID, strCurrentMinute, ECTX, BulkTable);
                        //insert
                        m_DBClient.BulkToDB(dt, BulkTable);
                    }
                    dt.Dispose();
                    //Console.WriteLine("写数据库完成。");
                    #endregion
                    ECSSSnapshotDal.GenerateArchiveCoalConsumption(ue.UnitID, ue.UnitName, strCurrentMinute);
                    LogUtil.LogMessage(ue.UnitName + ":  " + strCurrentMinute + "计算完毕!");
                    if (KIsTest == 0) {
                        //非测试环境时需要使用PI Server Time
                        //dtServerTime = m_RTDataAccess.GetServerTime();
                    }
                    //for
                    //dtCurrentMinute 自动加 1 分钟。。。。。。。。。。。。。

                    #endregion

                }
                LogUtil.LogMessage(ue.UnitCode + "," + ue.UnitName + "计算完毕!");

                #endregion

                ////////////////////////////////////////////////////////////////////////////////
                //更新数据库
                redo.RDIsValid = 0;
                redo.RDIsCalced = 1;
                redo.RDCalcedTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                KPI_RedoDal.Update(redo);
            }
            #endregion
            return true;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns> 
        public bool GetUnitArchiveValue(KPI_UnitEntity ue, bool bFirst, DateTime dtValid, bool bCollect, out string strError)
        {
            strError = "";
            if (m_KPIVar.ltReals.Count <= 0) {
                strError = "没有标签点";
                return false;
            }

            //不过滤了,全部一次取完!!!!
            //过滤当前机组的Tags
            var reltags = from kpi in m_KPIVar.ltReals
                          where (kpi.UnitID == ue.UnitID)
                          select kpi;

            if (reltags.Count() <= 0) {
                strError = "该机组的标签点为0";
                return false;
            }

            String strCM = dtValid.ToString("yyyy-MM-dd HH:mm:00");
            //当前只考虑了实时值。
            #region 测试环境

            if (KIsTest == 1) {
                string BulkTable = "KPI_ArchiveValue";
                DataTable dt = m_DBClient.GetTableSchema("tagvalue");
                foreach (KPI_RealTagEntity rte in m_KPIVar.ltReals) {
                    Random rand = new Random();
                    double dvtemp = rand.Next(500, 1000);
                    String strCode = "'" + rte.RealCode.ToUpper().Trim() + "'";
                    m_KPIVar.dicTags[strCode] = dvtemp;
                    DataRow dr = dt.NewRow();

                    dr["RVID"] = Guid.NewGuid().ToString();
                    dr["UnitID"] = rte.UnitID;
                    dr["RealID"] = rte.RealID;
                    dr["RealCode"] = rte.RealCode;
                    dr["RealDesc"] = rte.RealDesc;
                    dr["RealEngunit"] = rte.RealEngunit;
                    dr["RealTime"] = strCM;
                    dr["RealValue"] = dvtemp;
                    dr["RealQulity"] = "0";
                    dt.Rows.Add(dr);
                }
                if (dt.Rows.Count > 0) {
                    //删除
                    m_DBClient.DeleteData(ue.UnitID, strCM,"", BulkTable);
                    //插入
                    m_DBClient.BulkToDB(dt, BulkTable);
                }
                dt.Dispose();
            }
            #endregion

            #region 生产环境

            if (KIsTest == 0) {
                //从数据库获取数据
                if (bCollect) {
                    #region 采集数据

                    Dictionary<String, SIS.DBControl.TagValue> lttvs = new Dictionary<String, SIS.DBControl.TagValue>();
                    foreach (KPI_RealTagEntity rte in reltags) {
                        //点名
                        String strCode = rte.RealCode.ToUpper().Trim();
                        lttvs[strCode] = new TagValue(strCode);
                    }

                    //每个机组只添加一次
                    //if (bFirst) {
                    //    if (!m_RTDataAccess.SetPointList(lttvs, out strError)) {
                    //        LogUtil.LogMessage("SetPointList Exception: " + strError);
                    //        return false;
                    //    }
                    //}

                    //获取历史数据
                    //if (!DBAccess.GetRealTime().GetSnapshotListData(ref lttvs, out strError))
                    if (!m_RTDataAccess.GetArchiveListData(ref lttvs, dtValid, out strError)) {
                        LogUtil.LogMessage("GetArchiveListData Exception: " + strError);
                        return false;
                    }

                    #endregion

                    #region BulkTable

                    //历史数据
                    //BulkWrite to SQL
                    string BulkTable = "KPI_ArchiveValue";
                    DataTable dt = m_DBClient.GetTableSchema("tagvalue");
                    foreach (KPI_RealTagEntity rte in m_KPIVar.ltReals) {
                        //点名
                        String strCode = rte.RealCode.ToUpper().Trim();
                        String strTagCode = "'" + rte.RealCode.ToUpper().Trim() + "'";

                        //更新Dictory
                        m_KPIVar.dicTags[strTagCode] = 0.0;
                        if (lttvs.ContainsKey(strCode) && lttvs[strCode].TagQulity == 0) {
                            m_KPIVar.dicTags[strTagCode] = double.Parse(lttvs[strCode].TagStringValue);
                        }
                        DataRow dr = dt.NewRow();
                        dr["RVID"] = Guid.NewGuid().ToString();
                        dr["UnitID"] = rte.UnitID;
                        dr["RealID"] = rte.RealID;
                        dr["RealCode"] = rte.RealCode;
                        dr["RealDesc"] = rte.RealDesc;
                        dr["RealEngunit"] = rte.RealEngunit;
                        dr["RealTime"] = strCM;
                        dr["RealValue"] = m_KPIVar.dicTags[strTagCode];//.ToString();
                        dr["RealQulity"] = "0";
                        dt.Rows.Add(dr);
                    }

                    if (dt.Rows.Count > 0) {
                        //删除
                        m_DBClient.DeleteData(ue.UnitID, strCM, "",BulkTable);
                        //插入
                        m_DBClient.BulkToDB(dt, BulkTable);
                    }

                    dt.Dispose();
                    lttvs.Clear();
                    lttvs = null;
                    #endregion
                }
                else {
                    //从SQL数据库中查询获得只查询,不再写入了
                    List<ValueEntity> lrvs = ArchiveValueDal.GetValuesByTime(ue.UnitID, strCM);
                    foreach (ValueEntity rte in lrvs) {
                        //点名
                        String strCode = rte.RealCode.ToUpper().Trim();
                        String strTagCode = "'" + rte.RealCode.ToUpper().Trim() + "'";
                        //更新Dictory
                        m_KPIVar.dicTags[strTagCode] = rte.RealValue;
                    }

                }
            }
            #endregion
            return true;
        }
        /// <summary>
        /// 判断机组运行状态
        /// 获得机组有效负荷
        /// </summary>
        private bool GetUnitRealState(KPI_UnitEntity ue, DateTime dtValid)
        {
            #region 测试环境

            if (KIsTest == 1) {
                m_KPIVar.dicUnitStatus[ue.UnitID] = true;
                Random rand = new Random();
                m_KPIVar.dicUnitPEs[ue.UnitID] = rand.Next(260, 300);
            }
            #endregion

            #region 生产环境

            if (KIsTest == 0) {
                //获得机组运行条件
                string expression = ue.UnitCondition;
                m_KPIVar.dicUnitStatus[ue.UnitID] = false;
                if (!String.IsNullOrEmpty(ue.UnitCondition)) {
                    double dexp = m_RTDataAccess.ExpCurrentValue(expression);
                    m_KPIVar.dicUnitStatus[ue.UnitID] = false;
                    if (dexp != double.MinValue && dexp > 0) {
                        m_KPIVar.dicUnitStatus[ue.UnitID] = true;
                    }
                }

                //获得机组负荷
                string tag = ue.UnitMWTag;
                m_KPIVar.dicUnitPEs[ue.UnitID] = 0.0;
                if (!String.IsNullOrEmpty(ue.UnitMWTag)) {
                    double dvalue = m_RTDataAccess.GetSnapshotValue(tag);
                    if (dvalue != double.MinValue) {
                        m_KPIVar.dicUnitPEs[ue.UnitID] = dvalue;
                    }
                }
            }
            #endregion

            return true;
        }