Domanda

Come posso recuperare i dati grezzi delle serie storiche da un Proficy Historian / iHistorian?

Idealmente, chiederei dati per un tag particolare tra due date.

È stato utile?

Soluzione

Esistono diverse modalità di campionamento che puoi sperimentare.

  • Raw
  • interpolata
  • Lab
  • Trend
  • calcolato

Queste modalità sono disponibili utilizzando tutte le seguenti API.

  • API utente (ihuapi.dll)
  • SDK (ihsdk.dll)
  • OLEDB (iholedb.dll)
  • API di accesso client (Proficy.Historian.ClientAccess.API)

Di questi, la modalità di campionamento delle tendenze è probabilmente ciò che desideri poiché è specificamente progettata per la creazione di grafici / trend. Anche lab e interpolati possono essere utili.

Leggi il libro elettronico per maggiori informazioni su ciascuna modalità di campionamento. Sul mio computer è memorizzato come C: \ Programmi \ GE Fanuc \ Proficy Historian \ Docs \ iHistorian.chm e ho installato la versione 3.5. Prestare particolare attenzione alle seguenti sezioni.

  • Utilizzo del provider OLE DB Historian
  • Argomenti avanzati | Recupero

Ecco come è possibile costruire un OLEDB per eseguire il campionamento delle tendenze.

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'

La visualizzazione dei metodi equivalenti utilizzando l'API utente e l'SDK è complessa (in particolare con l'API utente) poiché richiede molta installazione nel codice per ottenere l'installazione. L'API di accesso client è più recente e utilizza WCF dietro le quinte.

Comunque, ci sono alcune limitazioni con il metodo OLEDB.

  • Nonostante ciò che la documentazione dice che non non è mai stato in grado di far funzionare i parametri delle query native. Questo è uno showstopper se si desidera utilizzarlo con SQL Server Reporting Services, ad esempio.
  • Non è possibile scrivere campioni nell'archivio o in alcun modo apportare modifiche alla configurazione di Historian tra cui l'aggiunta / modifica di tag, la scrittura di messaggi, ecc.
  • In alcuni casi può essere un po 'lento.
  • Non è previsto il crosstabbing di più tagname nelle colonne e quindi il trasferimento di campioni in modo che esista un valore per ogni combinazione data / ora e tag. La modalità di campionamento dell'andamento ti porta a metà strada, ma non è ancora a campi incrociati e in realtà non carica campioni grezzi. Quindi, anche l'API utente e l'SDK non possono farlo.

Altri suggerimenti

Un mio collega ha messo insieme questo:

In web.config:

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

Nel livello dati:

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

Aggiornamento:

Funzionava bene, ma abbiamo riscontrato un problema con i tag che non si aggiornano molto spesso. Se il tag non si aggiornava vicino all'inizio o alla fine della data di inizio e della data di fine richieste, le tendenze sembrerebbero negative. Peggio ancora, c'erano ancora casi in cui non c'erano punti espliciti durante la finestra richiesta - non avremmo avuto nessun dato indietro.

Ho risolto questo problema facendo tre domande:

  1. Il valore precedente prima della data di inizio
  2. I punti tra startDate e endDate
  3. Il valore successivo dopo la data di fine

Questo è un modo potenzialmente inefficiente per farlo ma funziona:

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

E sì, lo so, quelle query dovrebbero essere parametrizzate.

Michael - in IP21 c'è un "Interpolato" tabella, nonché la tabella "attuale" tabella dei punti dati. Anche Proficy ha questo?

Abbiamo scritto una DLL wrapper simile a questa:

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

Alcune note indicano che iFIX verificherà se la DLL viene caricata all'avvio, quindi è necessario eseguire operazioni come caricare / scaricare dinamicamente la DLL in modo che altre applicazioni non si arrestino in modo anomalo. Lo abbiamo fatto cancellando / aggiungendo le chiavi di registro al volo.

Un altro è se si esegue il polling di 10.000 campioni e 1 dei campioni è corrotto, eliminerà tutti i 10.000 campioni. È necessario implementare un gestore dati non valido che verrà avviato su entrambi i lati dei dati errati e incrementato in passaggi per ottenere tutti i dati su entrambi i lati del campione errato.

Esistono diversi file di intestazione C che contengono tutti i codici di errore e l'intestazione della funzione per la DLL.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top