c# oledb proficy historian

c# - ¿Cómo consulto datos sin procesar de un Proficy Historian?



oledb (4)

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

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


Un compañero de trabajo lo armó todo:

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

Actualizar:

Esto funcionó bien, pero nos encontramos con un problema con las etiquetas que no se actualizan muy a menudo. Si la etiqueta no se actualizó cerca del inicio o el final de los startDate y endDate solicitados, las tendencias se verán mal. Peor aún, todavía había casos en los que no había puntos explícitos durante la ventana solicitada; no obtendríamos 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 del final Fecha

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 estar parametrizadas.


Michael: en IP21 hay una tabla "Interpolada", así como la tabla de puntos de datos "reales". ¿Tiene Proficy eso también?


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

  • Crudo
  • Interpolado
  • Laboratorio
  • Tendencia
  • Calculado

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

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

De estos, el modo de muestreo de tendencias es probablemente lo que desea, ya que está diseñado específicamente para gráficos / tendencias. Sin embargo, el laboratorio y la interpolación 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:/Program Files/GE Fanuc/Proficy Historian/Docs/iHistorian.chm y tengo la versión 3.5 instalada. Presta especial atención a las siguientes secciones.

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

Aquí es cómo puedes 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 utilizando la API de usuario y el SDK es complejo (más aún con la API de usuario), ya que requieren una gran cantidad de plomería en el código para obtener la configuración. La API de acceso de cliente es más nueva y usa WCF detrás de escena.

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

  • A pesar de lo que dice la documentación, nunca pude conseguir que los parámetros de consulta nativos funcionen. Eso es sorprendente si quiere usarlo con SQL Server Reporting Services, por ejemplo.
  • No puede escribir muestras en el archivo o realizar cambios en la configuración de Historian, como agregar / cambiar etiquetas, escribir mensajes, etc.
  • Puede ser un poco lento en algunos casos.
  • No tiene ninguna disposición para el cruce de múltiples nombres de etiquetas en las columnas y luego el envío de muestras para que exista un valor para cada marca de tiempo y combinación de etiquetas. El modo de muestreo de tendencias te lleva a la mitad, pero todavía no cruza y no carga muestras crudas. Por otra parte, la API de usuario y el SDK tampoco pueden hacer esto.

Escribimos un archivo contenedor 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 indican que iFIX verificará si la DLL se carga al inicio, por lo que debe hacer cosas como cargar / descargar dinámicamente la DLL para que otras aplicaciones no se cuelguen. Lo hicimos eliminando / agregando claves de registro sobre la marcha.

Otro ejemplo es que si encuesta 10,000 muestras y una de las muestras está dañada, se eliminarán todas las 10,000 muestras. Debe implementar un manejador de datos incorrecto que se iniciará en ambos lados de los datos incorrectos e incremente en pasos para obtener todos los datos a cada lado 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 el archivo DLL.