Pregunta

¿Cómo puedo recuperar datos brutos de series temporales de un Proficy Historian / iHistorian?

Idealmente, pediría datos para una etiqueta particular entre dos fechas.

¿Fue útil?

Solución

Hay varios modos de muestreo diferentes con los que puede experimentar.

  • Crudo
  • Interpolado
  • Laboratorio
  • Tendencia
  • Calculado

Estos modos están disponibles con todas las siguientes API.

  • API de usuario (ihuapi.dll)
  • SDK (ihsdk.dll)
  • OLEDB (iholedb.dll)
  • API de acceso de cliente (Proficy.Historian.ClientAccess.API)

De estos, el modo de muestreo de tendencias es probablemente lo que desea, ya que está específicamente diseñado para gráficos / tendencias. Sin embargo, el laboratorio y el interpolado también pueden ser útiles.

Lea el libro electrónico para obtener más información sobre cada modo de muestreo. En mi máquina se almacena como C: \ Archivos de programa \ GE Fanuc \ Proficy Historian \ Docs \ iHistorian.chm y tengo instalada la versión 3.5. Presta especial atención a las siguientes secciones.

  • Uso del proveedor OLE DB Historian
  • Temas avanzados | Recuperación

Aquí es cómo puede construir un OLEDB para hacer un muestreo de tendencias.

set 
    SamplingMode = 'Trend',
    StartTime = '2010-07-01 00:00:00',
    EndTime = '2010-07-02 00:00:00',
    IntervalMilliseconds = 1h
select 
    timestamp, 
    value, 
    quality 
from 
    ihRawData 
where 
    tagname = 'YOUR_TAG'

Mostrar los métodos equivalentes que usan la API de usuario y el SDK son complejos (más aún con la API de usuario) ya que requieren mucha conexión en el código para su configuración. La API de acceso de cliente es más nueva y usa WCF detrás de escena.

Por cierto, existen algunas limitaciones con el método OLEDB.

  • A pesar de lo que dice la documentación, nunca he podido hacer funcionar parámetros de consulta nativos. Eso es un showtopper si desea usarlo con SQL Server Reporting Services, por ejemplo.
  • No puede escribir muestras en el archivo o de ninguna manera realizar cambios en la configuración de Historian incluyendo agregar / cambiar etiquetas, escribir mensajes, etc.
  • Puede ser un poco lento en algunos casos.
  • No tiene ninguna disposición para cruzar varios nombres de etiquetas en las columnas y luego llevar muestras para que exista un valor para cada combinación de marca de tiempo y etiqueta. El modo de muestreo de tendencia lo lleva a la mitad del camino, pero aún no cruza y no carga muestras crudas. Por otra parte, la API de usuario y el SDK tampoco pueden hacer esto.

Otros consejos

Un compañero de trabajo mío armó esto:

En web.config:

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

En la capa de datos:

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];
    }
}

Actualización:

Esto funcionó bien, pero encontramos un problema con las etiquetas que no se actualizan con mucha frecuencia. Si la etiqueta no se actualizó cerca del inicio o el final de la fecha de inicio y la fecha de finalización solicitadas, las tendencias se verían mal. Peor aún, todavía hubo casos en los que no hubo puntos explícitos durante la ventana solicitada: no recuperaríamos los datos.

Resolví esto haciendo tres consultas:

  1. El valor anterior antes de la fecha de inicio
  2. Los puntos entre startDate y endDate
  3. El siguiente valor después de el endDate

Esta es una forma potencialmente ineficiente de hacerlo, pero funciona:

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];
    }
}

Y sí, lo sé, esas consultas deberían ser parametrizadas.

Michael - en IP21 hay un "Interpolado" tabla, así como la " real " tabla de puntos de datos. ¿Proficy tiene eso también?

Escribimos una DLL de envoltorio que se veía así:

[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
            );
            ....

Algunas notas son que iFIX verificará si la DLL está cargada en el inicio, por lo que debe hacer cosas como cargar / descargar dinámicamente la DLL para que otras aplicaciones no se bloqueen. Lo hicimos eliminando / agregando claves de registro sobre la marcha.

Otra es que si sondea 10,000 muestras y 1 de las muestras está dañada, eliminará todas las 10,000 muestras. Debe implementar un controlador de datos incorrectos que comenzará a ambos lados de los datos incorrectos y se incrementará en pasos para obtener todos los datos a ambos lados de la muestra incorrecta.

Hay varios archivos de encabezado C que contienen todos los códigos de error y el encabezado de función para la DLL.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top