Exemple #1
0
        //<<<<<<<<<<Retrieve current value from existing PI Point>>>>>>>>>>
        public object getCurrentValue(String tagName)
        {
            //Retrive the latest value given the tage name
            PIValues val = piServer.PIPoints[tagName].Data.RecordedValuesByCount("*", 1, DirectionConstants.dReverse);

            return(val[1].Value);
        }
Exemple #2
0
        ///////Display tags in certain time frame///////////////////
        public List <PointVal> searchPiPoints(string tagName, string startTime, string endTime)
        {
            //Create new list
            List <PointVal> list = new List <PointVal>();

            try
            {
                //Get point from tagname
                PIPoint point = PI_Server.PIPoints[tagName];

                //Get recorded values for selected time
                // in order to display only those points in the time frame choosen by user
                PIValues values = point.Data.RecordedValues(startTime, endTime);

                //Walk through values list and save each value
                foreach (PIValue value in values)
                {
                    //Create new value object
                    PointVal val = new PointVal();

                    //Save date from values timestamp
                    val.date = value.TimeStamp.LocalDate.ToString();

                    //Save the value, but first check to see if value is a digital state or an actual value
                    // when a tag is first created it does not have a value and therefore it does not
                    //contain a value. Instead is  displays " NO DATA" which means it is in digital state
                    DigitalState state = value.Value as DigitalState;

                    if (state != null)
                    {
                        //Not a value, it's a digital state
                        // it turns it into a string in order to be saved and displayed
                        val.value = (value.Value as DigitalState).Name.ToString();
                    }
                    else
                    {
                        //Convert value to object, then object to string
                        object obj = value.Value;
                        val.value = obj.ToString();
                    }

                    //Add new value to list
                    list.Add(val);
                }
            }
            catch (Exception ex)
            {
            }

            return(list);// return the tags recorded on the list
        }
Exemple #3
0
        private List <PValue> PIValues2PValuesHist(PIValues pivalues)
        {
            //为读取历史数据原始值准备的转换函数
            //values为空时,上面直接退出,返回空list。
            //values不为空时,至少会有两个值。PI会在起始时间和截止时间插值
            List <PValue> pvalues = new List <PValue>();

            //pivalues下标从1开始
            foreach (PIValue pivalue in pivalues)
            {
                //20181224日,重新编写转换函数

                /*
                 * try
                 * {
                 *  DateTime timestamp = DateTime.Parse(pivalue.TimeStamp.LocalDate.ToString());
                 *
                 *  //这个在转换过程中可能出错,出错时,直接跳过
                 *  //——一是有可能是非数值变量,那不可能转换成双精度。
                 *  //——二是数值型,在测试时,有时也不能转换为双精度。没有搞清楚
                 *  double value = Convert.ToDouble(pivalue.Value);
                 *
                 *  //——对于PI数据状态位,比较复杂,还没哟搞清楚,暂不处理。状态位先统一给好质量0.
                 *  //——后面需要对状态位进行判断。
                 *
                 *  pvalues.Add(new PValue(value, timestamp, timestamp, 0));
                 *
                 *  if (pvalues.Count > 1) pvalues[pvalues.Count - 2].Endtime = timestamp;  //修改上一个数据的endtime
                 *  //上面这条语句,PI取出的最后一条数据不会执行。
                 *  //PI语句只要能取出取数,在插值方式下,最后一个有效数据一定为取数周期截止时刻的数据。
                 *  //因此,pvalues的最后一个数据,就是截止时刻数据,并且该Pvalue数据的起始时刻和截止时刻,均为取数周期的截止时刻。
                 * }
                 * catch (Exception ex)
                 * {
                 *  continue;
                 * }
                 */

                try
                {
                    //pivalue.IsGood(),见PI-SDK Help文档
                    //isGood()方法用来判断PIValue对象的PIValue.Value属性值是一个有效数据值,还是一个错误状态值。
                    //——如果isGood返回false,则PIValue.Value属性将会包含一个从系统数字状态集(System digital state set)中返回的数字状态。具体见DigitalState Object主题
                    //——但是isGood返回true,则不能作为判断PIValue是否好数据关键。因为任何一个PIValue只要包含DigitalState,那么即使isGood为true,数据仍然是坏数据。

                    if (pivalue.IsGood())
                    {
                        //时间
                        DateTime timestamp = DateTime.Parse(pivalue.TimeStamp.LocalDate.ToString());

                        //状态
                        long status = 0;
                        //这个在转换过程中可能出错,出错时,直接跳过
                        //——一是有可能是非数值变量,那不可能转换成双精度。
                        //——二是数值型,在测试时,有时也不能转换为双精度。没有搞清楚
                        double pv = 0;
                        if (double.TryParse(pivalue.Value.ToString(), out pv))
                        {
                            pv = Convert.ToDouble(pivalue.Value);
                        }
                        else
                        {
                            pv     = 0;
                            status = 1;
                        }
                        //——对于PI数据状态位,比较复杂,还没哟搞清楚,暂不处理。状态位先统一给好质量0.
                        //——后面需要对状态位进行判断。

                        pvalues.Add(new PValue(pv, timestamp, timestamp, status));

                        if (pvalues.Count > 1)
                        {
                            pvalues[pvalues.Count - 2].Endtime = timestamp;                     //修改上一个数据的endtime
                        }
                        //上面这条语句,PI取出的最后一条数据不会执行。
                        //PI语句只要能取出取数,在btOutside方式下,最后一个有效数据有可能是enddate前,enddate后,也可能等于enddate。
                    }
                    else
                    {
                        //时间
                        DateTime timestamp = DateTime.Parse(pivalue.TimeStamp.LocalDate.ToString());

                        //状态
                        long status = 1;

                        //值
                        double pv = 0;

                        //添加结果
                        pvalues.Add(new PValue(pv, timestamp, timestamp, status));

                        //修改时间
                        if (pvalues.Count > 1)
                        {
                            pvalues[pvalues.Count - 2].Endtime = timestamp;                     //修改上一个数据的endtime
                        }
                    }
                }
                catch (Exception ex)
                {
                    //将pi的异常记录在_exception中,并以PgimDataException的名称继续抛出异常
                    this._exception = "PI数据查询结果PIValue数据格式转换错误。通常应该是pivalue.TimeStamp类型转换错误!" + ex.ToString();
                    throw ex;     //将PI的异常继续向外传递。
                }
            }

            return(pvalues);
        }
Exemple #4
0
        //历史值的读写
        #region 读取历史数据原始值:public List<PValue> GetRawValues(string tagname, DateTime startdate, DateTime enddate)。重点函数,概化计算引擎用。
        /// <summary>
        /// GetRawValues是实时库读取历史数据接口的对外封装。无论何种实时数据库,读取历史数据功能都是指,读取某一个指定标签(tagname)在一段时间内(startdate、enddate)的历史值(浮点型)
        /// 而不同的实时数据库,真正的读取方法和返回值的数据类型略有区别
        /// 要求起始时刻和截止时刻,必须为精确的实时值。如果恰好有这两个时刻点的值,就直接取得。如果没有就采用插值。
        /// 对于PI数据库,读取历史数据接口,当第三个参数设定为btInterp时,接口会自动的获取起始时刻和截止时刻的插值。
        /// </summary>
        /// <param name="tagname">标签名</param>
        /// <param name="startdate">起始时间</param>
        /// <param name="enddate">结束时间</param>
        /// <returns>历史数据,PValue集合</returns>
        public List <PValue> GetRawValues(string tagname, DateTime startdate, DateTime enddate)
        {
            //经过测试,PI数据库读取原始数据时,在起始时刻点,和截止时刻点,可以通过参数设置实现以下几种方式:
            //在piPoint.Data.RecordedValues()中的第三个参数,BoundaryType,可以选择:
            //——auto,自动决定边界点
            //——btInside,只取时间戳大于起始时间的点和时间戳小于截止时刻的点。
            //——btOutside,取得实时数据包含起始时刻前一个有效时刻的值,和截止时刻后一个有效时刻的值。
            //——btInterp,在起始时刻和截止时刻,进行插值。
            //对于计算引擎,需要的就是btInterp这种方式,即在起始时刻和截止时刻,进行精确的插值
            //如果已经取到数据库最早的时间值,则不再向前补值。比如数据最早是2018-1-2 00:00:00的值。取值周期起始时刻是2018-1-1。RecordedValues返回的第一个值是2018-1-2 00:00:00的,不会向前补值。

            //为了在使用长连接时保险起见,这里仅检查是否连接。如果未连接就直接返回空。
            if (this._piServer == null || !this._piServer.Connected)
            {
                return(null);                                                  //如果未登陆,直接返回空值
            }
            //准备读值列表PIValues
            PIValues pivalues = new PIValues();

            if (enddate <= startdate)
            {
                return(null);
            }
            try
            {
                this._piPoint = this._piServer.PIPoints[tagname];
                pivalues      = this._piPoint.Data.RecordedValues(startdate, enddate, BoundaryTypeConstants.btOutside); //BoundaryTypeConstants.btInterp采用边界取外值的办法,起始时刻取前值,截止时刻取后值
            }
            catch (Exception ex)
            {
                //将pi的异常记录在_exception中,并以PgimDataException的名称继续抛出异常
                this._exception = "PI其他未知错误。通常是服务器故障、标签中对应的服务器名称不正确导致!详细错误信息:" + ex.ToString();
                throw ex;     //将PI的异常继续向外传递。
            }

            //PI的RecordedValues()接口,返回的数据,起始时刻和截止时刻的值,均为根据前后值插值得到。除此以外,PI还会返回其他标志值,比如停止,IO超驰等。
            //所以,不能依据pivalues>=2,来判断是否包含了完整的起始时刻和截止时刻的值。
            //如果count为0,直接返回空。外部程序可以根据pvalues==null来处理
            if (pivalues == null || pivalues.Count == 0)
            {
                return(null);
            }

            //将pivalues转换为Pvalue值
            //——返回的pvalues,由于采用了BoundaryTypeConstants.btOutside读法,正常情况应该包含一个等于或早于起始时刻的首值,包含一个早于、等于或者晚于截止时刻的后值。
            //——pivalues中可能有非数值数据,转换后的pivalues只包含数值型数据
            List <PValue> pvalues = PIValues2PValuesHist(pivalues);

            if (pvalues == null || pvalues.Count == 0)
            {
                return(null);
            }

            //处理首值
            if (pvalues[0].Timestamp < startdate)
            {
                pvalues[0].Timestamp = startdate;       //如果首值的时刻小于起始时刻,说明btOutside方式正确取到了前点。则将前点时刻改为起始时刻
            }
            else if (pvalues[0].Timestamp == startdate)
            {
                //如果首值的时刻恰好等于起始时刻,则什么也不做
            }
            else
            {
                //将pi的异常记录在_exception中,并以PgimDataException的名称继续抛出异常
                this._exception = "PI接口读取原始数据错误。未正常读取到起始时刻前值!";
                throw new Exception(this._exception);     //将XIANDB的异常继续向外传递。
            }

            //处理尾值
            if (pvalues[pvalues.Count - 1].Timestamp < enddate)
            {
                //如果最后一个点的时间戳小于截止时刻,则说明没有找到截止时刻后值
                pvalues[pvalues.Count - 1].Endtime = enddate;
                pvalues.Add(new PValue(pvalues[pvalues.Count - 1].Value, enddate, enddate, pvalues[pvalues.Count - 1].Status)); //添加截止时刻点
            }
            else if (pvalues[pvalues.Count - 1].Timestamp == enddate)
            {
                //恰好有截止时刻点,将该值作为截止时刻值
                pvalues[pvalues.Count - 1].Endtime = enddate;
            }
            else
            {
                //取到截止时刻点后值
                pvalues[pvalues.Count - 2].Endtime = enddate;           //修改前一个值的结束时刻到enddate
                //将最后一个值,变为截止时刻点
                pvalues[pvalues.Count - 1].Value     = pvalues[pvalues.Count - 2].Value;
                pvalues[pvalues.Count - 1].Timestamp = enddate;
                pvalues[pvalues.Count - 1].Endtime   = enddate;
                pvalues[pvalues.Count - 1].Status    = pvalues[pvalues.Count - 2].Status;
            }

            return(pvalues);
        }
Exemple #5
0
        protected static void processVals(DateTime dt1, DateTime dt2, PIValues vals, TagInfo ti, int maxPointsCount, Report report,bool addMinutes=true)
        {
            if (vals.Count > maxPointsCount) {
                report.addTag(new Tag(ti, 0, dt1));
                report.addTag(new Tag(ti, 0, dt2));
                return;
            }
            Array vs;
            Array times;
            Array attrs;

            PISDK.IPIValues2 vals2=vals as PISDK.IPIValues2;
            vals2.GetValueArrays(out vs, out times, out attrs);

            for (int i=0; i < vs.Length; i++) {
                double time=(double)times.GetValue(i);
                PITimeServer.PITimeFormat tc=new PITimeServer.PITimeFormat();
                tc.UTCSeconds = time;
                int add=addMinutes?ti.AddMinutes:0;
                DateTime dt=tc.LocalDate.AddMinutes(add);

                object v=vs.GetValue(i);
                double value=getDoubleVal(v);
                Tag tag = new Tag(ti, value, dt);
                report.addTag(tag);
            }
        }