如何从Proficy Historian查询原始数据?

时间:2008-11-20 19:59:21

标签: c# oledb proficy historian

如何从Proficy Historian / iHistorian中检索原始时间序列数据?

理想情况下,我会要求两个日期之间的特定标签的数据。

4 个答案:

答案 0 :(得分:17)

答案 1 :(得分:4)

我的一位同事把它放在一起:

在web.config中:

<add name="HistorianConnectionString" 
     providerName="ihOLEDB.iHistorian.1" 
     connectionString="
       Provider=ihOLEDB.iHistorian;
       User Id=;
       Password=;
       Data Source=localhost;"
/>

在数据层中:

public DataTable GetProficyData(string tagName, DateTime startDate, DateTime endDate)
{
    using (System.Data.OleDb.OleDbConnection cn = new System.Data.OleDb.OleDbConnection())
    {
        cn.ConnectionString = webConfig.ConnectionStrings.ConnectionStrings["HistorianConnectionString"];
        cn.Open();

        string queryString = string.Format(
                "set samplingmode = rawbytime\n select value as theValue,Timestamp from ihrawdata where tagname = '{0}' AND timestamp between '{1}' and '{2}' and value > 0 order by timestamp",
                tagName.Replace("'", "\""), startDate, endDate);

        System.Data.OleDb.OleDbDataAdapter adp = new System.Data.OleDb.OleDbDataAdapter(queryString, cn);
        DataSet ds = new DataSet();

        adp.Fill(ds);
        return ds.Tables[0];
    }
}

更新:

这很好用但是我们遇到了一个问题,这个问题不经常更新。如果标记未在请求的startDate和endDate的开头或结尾附近更新,则趋势看起来会很糟糕。更糟糕的是,仍然是在请求的窗口期间没有明确点的情况 - 我们没有得到任何数据。

我通过三个查询解决了这个问题:

  1. 之前的值 开始日期
  2. startDate和endDate之间的点
  3. endDate
  4. 之后的下一个值

    这是一种潜在的低效方法,但它可行:

    public DataTable GetProficyData(string tagName, DateTime startDate, DateTime endDate)
    {
        DataSet ds = new DataSet();
        string queryString;
        System.Data.OleDb.OleDbDataAdapter adp;
    
        using (System.Data.OleDb.OleDbConnection cn = new System.Data.OleDb.OleDbConnection())
        {
            cn.ConnectionString = proficyConn.ConnectionString;
            cn.Open();
    
            // always get a start value
            queryString = string.Format(
                 "set samplingmode = lab\nselect value as theValue,Timestamp from ihrawdata where tagname = '{0}' AND timestamp between '{1}' and '{2}' order by timestamp",
                tagName.Replace("'", "\""), startDate.AddMinutes(-1), startDate);
            adp = new System.Data.OleDb.OleDbDataAdapter(queryString, cn);
            adp.Fill(ds);
    
            // get the range
            queryString = string.Format(
                 "set samplingmode = rawbytime\nselect value as theValue,Timestamp from ihrawdata where tagname = '{0}' AND timestamp between '{1}' and '{2}' order by timestamp",
                tagName.Replace("'", "\""), startDate, endDate);
            adp = new System.Data.OleDb.OleDbDataAdapter(queryString, cn);
            adp.Fill(ds);
    
            // always get an end value
            queryString = string.Format(
                 "set samplingmode = lab\nselect value as theValue,Timestamp from ihrawdata where tagname = '{0}' AND timestamp between '{1}' and '{2}' order by timestamp",
            tagName.Replace("'", "\""), endDate.AddMinutes(-1), endDate);
            adp = new System.Data.OleDb.OleDbDataAdapter(queryString, cn);
            adp.Fill(ds);
    
            return ds.Tables[0];
        }
    }
    

    是的,我知道,这些查询应该参数化。

答案 2 :(得分:0)

Michael - 在IP21中有一个“Interpolated”表,以及“实际”数据点表。 Proficy也有这个吗?

答案 3 :(得分:0)

我们编写了一个如下所示的包装DLL:

[DllImport("IHUAPI.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "ihuReadRawDataByTime@24")]
public static extern int ihuReadRawDataByTime(int serverhandle, string tagname, ref IHU_TIMESTAMP startTime, ref IHU_TIMESTAMP endTime, ref int noOfSamples, ref IHU_DATA_SAMPLE* dataValues);
...
private int _handle;

public HistorianTypes.ErrorCode ReadRawByTime(string tagName, DateTime startTime, DateTime endTime,
                                              out double[] timeStamps, out double[] values, out IhuComment [] comments)
{
    var startTimeStruct = new IhuApi.IHU_TIMESTAMP();  //Custom datetime to epoch extension method
    var endTimeStruct = new IhuApi.IHU_TIMESTAMP();

    int lRet = 0;
    int noOfSamples = 0;
    startTimeStruct = DateTimeToTimeStruct(dstZone.ToUniversalTime(startTime));
    endTimeStruct = DateTimeToTimeStruct(dstZone.ToUniversalTime(endTime));
    IhuApi.IHU_DATA_SAMPLE* dataSample = (IhuApi.IHU_DATA_SAMPLE*)new IntPtr(0);

    try {
        lRet = IhuApi.ihuReadRawDataByTime
            (
                _handle, // the handle returned from the connect
                tagName, // the single tagname to retrieve
                ref startTimeStruct, // start time for query
                ref endTimeStruct, // end time for query
                ref noOfSamples, // will be set by API
                ref dataSample // will be allocated and populated in the user API
            );
            ....

有些注意事项是iFIX将检查DLL是否在启动时加载,因此您需要执行诸如动态加载/卸载DLL以使其他应用程序不会崩溃的操作。我们通过动态删除/添加注册表项来完成此任务。

另一个是如果您轮询10,000个样本并且其中一个样本已损坏,则会丢弃所有10,000个样本。您需要实现一个错误的数据处理程序,该处理程序将从错误数据的任一侧开始,并逐步递增以获取错误样本的任何一侧的所有数据。

有几个C头文件包含DLL的所有错误代码和函数头。