¿Cómo puedo recuperar datos de series temporales crudas de un Proficy Historian/iHistorian?¿Cómo consulto datos sin procesar de un Proficy Historian?
Lo ideal sería pedir datos para una etiqueta en particular entre dos fechas.
¿Cómo puedo recuperar datos de series temporales crudas de un Proficy Historian/iHistorian?¿Cómo consulto datos sin procesar de un Proficy Historian?
Lo ideal sería pedir datos para una etiqueta en particular entre dos fechas.
Existen varios modos de muestreo diferentes con los que puede experimentar.
Estos modos están disponibles usando todas las siguientes APIs.
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 está almacenado 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.
Así es como puede construir un OLEDB para hacer un muestreo de tendencia.
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'
Mostrando los métodos equivalentes que utilizan la API de usuario y el SDK son complejos (más aún con la API de usuario), ya que requieren una gran cantidad de fontanerí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.
Un compañero de trabajo mío puso esta juntos:
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 nos encontramos con 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 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:
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 se deben parametrizar.
OLE es muy lento. El uso de la API tiene un rendimiento mucho mejor, también puede escribir métodos de extensión que le permiten hacer mucho más de lo que OLE brindará de inmediato. – rolls
En cuanto a la obtención de muestras no puede hacer "ReadSamplesByCount" en lugar de tiempo, de esa manera se obtiene al menos 1 muestra de nuevo. Si no hay muchas muestras, la muestra puede tardar años después del período de tiempo que desea mostrar. – rolls
Michael - en IP21 hay una tabla "Interpolada", así como la tabla de puntos de datos "reales". ¿Tiene Proficy eso también?
@reallyJim Creo que sí, sin embargo, en mi caso necesitaba datos sin procesar –
Me encontré con lo mismo hace unos años con un sistema PI, así que siento su dolor! – reallyJim
escribimos un contenedor DLL que se veía así de esta manera:
[DllImport("IHUAPI.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "[email protected]")]
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 comprobará si el archivo DLL se carga en el arranque por lo que necesita para hacer cosas como cargar dinámicamente/descarga la DLL para que otras aplicaciones no se cuelguen. Lo hicimos eliminando/agregando claves de registro sobre la marcha.
Otra es que si sondea 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 la DLL.
Un poco tarde lo sé, pero es mejor tarde que nunca. Además, responder viejas preguntas sobre SO es como mi estilo de todos modos. –
No tengo tiempo para probar esto ahora, pero es exactamente lo que estaba buscando cuando comencé. ¡Gracias! ¿Puede por casualidad agregar una nota sobre dónde se encuentra normalmente el ebook? –
¿Alguna idea sobre cómo usar las funciones del historiador incorporado como PreviousValue de esta manera? ¿Puede el oledb hacer esto? algo en la línea de seleccionar "indicación de fecha y hora, PreviousValue (Time, tagname) from ..." – xdumaine