Question

Comment puis-je récupérer des données brutes de séries chronologiques d'un Proficy Historian / iHistorian?

Idéalement, je demanderais des données pour une balise particulière entre deux dates.

Était-ce utile?

La solution

Il existe plusieurs modes d'échantillonnage différents que vous pouvez expérimenter.

  • Raw
  • Interpolé
  • laboratoire
  • Tendance
  • calculé

Ces modes sont disponibles à l'aide de toutes les API suivantes.

  • API utilisateur (ihuapi.dll)
  • SDK (ihsdk.dll)
  • OLEDB (iholedb.dll)
  • API d'accès client (Proficy.Historian.ClientAccess.API)

Parmi ceux-ci, le mode d'échantillonnage de tendance est probablement ce que vous voulez, car il est spécialement conçu pour les graphiques / tendances. Bien qu’un laboratoire et une interpolation puissent également être utiles.

Lisez le livre électronique pour plus d'informations sur chaque mode d'échantillonnage. Sur ma machine, il est stocké sous le nom C: \ Program Files \ GE Fanuc \ Proficy Historian \ Docs \ iHistorian.chm et la version 3.5 est installée. Portez une attention particulière aux sections suivantes.

  • Utilisation du fournisseur Historian OLE DB
  • Sujets avancés | Récupération

Voici comment vous pouvez créer un OLEDB pour effectuer un échantillonnage de tendance.

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'

Afficher les méthodes équivalentes utilisant l’API utilisateur et le SDK est complexe (plus particulièrement avec l’API utilisateur) car elles nécessitent beaucoup de plomberie dans le code pour pouvoir être installées. L’API d’accès au client est plus récente et utilise WCF en coulisse.

Cependant, il existe quelques limitations avec la méthode OLEDB.

  • Malgré ce que dit la documentation, jamais n’a jamais été en mesure de faire fonctionner les paramètres de requête natifs. C’est un échec si vous souhaitez l’utiliser avec SQL Server Reporting Services par exemple.
  • Vous ne pouvez pas écrire d'échantillons dans l'archive ni modifier de quelque manière que ce soit la configuration de Historian, y compris l'ajout / modification de balises, la rédaction de messages, etc.
  • Cela peut être un peu lent dans certains cas.
  • Il n'est pas possible de regrouper plusieurs noms de variables dans les colonnes, puis de reporter des échantillons afin qu'une valeur existe pour chaque combinaison d'horodatage et de balises. Le mode d'échantillonnage de tendance vous amène à mi-chemin, mais n'entre toujours pas dans l'analyse croisée et ne charge pas les échantillons bruts. Là encore, l’API utilisateur et le SDK ne peuvent pas le faire non plus.

Autres conseils

Un de mes collègues a mis cela en place:

Dans web.config:

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

Dans la couche de données:

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

Mise à jour:

Cela a bien fonctionné mais nous avons rencontré un problème avec les balises qui ne se mettent pas à jour très souvent. Si la balise ne s'est pas mise à jour au début ou à la fin des dates demandées startDate et endDate, les tendances sembleraient mauvaises. Pire encore, il y avait encore des cas où il n'y avait pas de points explicites pendant la fenêtre demandée - nous ne récupérerions aucune donnée.

J'ai résolu ce problème en effectuant trois requêtes:

  1. La valeur précédente avant la date de début
  2. Les points entre startDate et endDate
  3. La valeur suivante après la date de fin

C’est un moyen potentiellement inefficace de le faire, mais ça marche:

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

Et oui, je sais, ces requêtes doivent être paramétrées.

Michael - dans IP21, il existe un "Interpolated" table, ainsi que le " réel " table de points de données. Est-ce que Proficy en a aussi?

Nous avons écrit une DLL wrapper ressemblant à ceci:

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

Certaines notes indiquent qu'iFIX vérifiera si la DLL est chargée au démarrage. Vous devez par exemple charger / décharger dynamiquement la DLL afin que les autres applications ne tombent pas en panne. Pour ce faire, nous avons supprimé / ajouté des clés de registre à la volée.

Un autre problème est que si vous interrogez 10 000 échantillons et que l'un des échantillons est corrompu, tous les 10 000 échantillons seront supprimés. Vous devez implémenter un gestionnaire de données incorrect qui démarrera d'un côté ou de l'autre et incrémenté par étapes pour obtenir toutes les données de chaque côté de l'échantillon incorrect.

Plusieurs fichiers d’en-tête C contiennent tous les codes d’erreur et l’en-tête de la fonction pour la DLL.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top