12 Replies Latest reply on Sep 7, 2011 2:27 PM by MichaelvdV@Atos

    Getting AF data using Silverlight

    AlistairFrith

          Normal   0           false   false   false     EN-GB   X-NONE   X-NONE                                                                                                                                                                                                                                                                                                                                                      

       

      We are currently using piwebservices to try and obtain AF data into Silverlight. So far, we have obtained values direct from the pi server but we now want to try and get data from the AF server. We are looking at trying to use many of the attributes on the AF server to create a Hierarchical display of the server so a User can drill down to a specific point and obtain a value. We have done this in powerpivot using slicers but we now want to recreate a similar display in Silverlight due to the added control of the visualizations.

       

      Does anyone know if this is possible with the current version of PIWebServices and if so, how would we go about it?

       

      We are using VisualStudio 2010 and PIWebServices 2010 R2.

       

      Many Thanks for your Help

       

      --- Alistair.

        • Re: Getting AF data using Silverlight
          Ahmad Fattahi

          Alistair,

           

          Please see [DEAD LINK] this nice example doing the exact integration you are talking about here (thanks to Lonnie Bowling). Also, you can refer to this vCampus Live! presentation by him.

           

          For some more general discussion you can see this thread as well. In general, the task is doable as long as you want to write the code yourself for it.

            • Re: Getting AF data using Silverlight

              Alistair, can you share some more about your hierarchical display that users can drill down into? I mean, what is the ideal way for you to build it? Is this a somewhat static hierarchy you know ahead of time, or something you would want to construct on the fly, using some "AF navigation capabilities" within PI Web Services?

                • Re: Getting AF data using Silverlight
                  AlistairFrith

                      Normal   0           false   false   false     EN-GB   X-NONE   X-NONE                                                                                                                                                                                                                                                                                                                                                      

                   

                  Hi Ahmad, thanks for the quick reply, we have already used this example to get data from the PI server and have got it working, however we are now trying to get components of the AF server displayed.

                   

                   Hi Steve, again thanks for the quick reply. We are creating a display that uses many primary and secondary electricity substations around the UK and the user would like to be able to find a specific attribute measurement on a specific substation element to show current and historic data.

                   

                   What we would be looking for is a drilldown/hierarchy that users can first select the area location eg. London, and from there select the street the substation is located and then into the specific Transformer or Feeder. The final selection will be the attributes of the chosen transformer or feeder, such as Current, Voltage, MVAR etc. We would be looking for these displays to update alongside the AF server, so when, as planned, the user adds more substations and tags onto the system, they would automatically appear within the drill down display when refreshed.

                   

                   So I guess what I’m trying to say is that although the layout of the hierarchy will be static, we would be looking for the data within it to be constructed on the fly using the AF navigation so we can effectively use the ‘Level’ and ‘Path’ elements of the “ElementHierarchy” to allow the user to work his way downwards.

                   

                   Many Thanks

                    • Re: Getting AF data using Silverlight
                      Ahmad Fattahi

                      You can use PI Web Services to get PI AF data into your application. Note that currently this is read-only; meaning that you cannot write data into PI AF using PI Web Services. For more information and examples please refer to this webinar and this thread. In short you can use GetPISummaryData and GetPIArchiveData to get attribute data. If you need some features that are not currently exposed to PI Web Services you can incorporate AF SDK.

                        • Re: Getting AF data using Silverlight

                          Then in that case I am afraid you will have to use the approach Ahmad referred to...  PI Web Services can read data from AF attributes, but it requires you to know the AF attribute path. In other words, in its current version, however, PI Web Services doesn't expose methods to do "AF navigation" - e.g. discover the underlying items (elements or attributes) of a specific item (element or attribute).

                           

                          This is, of course, something that's on the roadmap for a future version... stay tuned!

                            • Re: Getting AF data using Silverlight

                              Steve Pilon

                              This is, of course, something that's on the roadmap for a future version... stay tuned!
                              On that note, I would really like to hear more about your needs in that area... would you be so kind as to list the requirements you can think of here?  (e.g. need to get children elements and attributes, for a given element or attribute)

                               

                              @Everybody else: please feel free to chime in  as well... the more feedback, the better idea we will have on what to implement and how.

                                • Re: Getting AF data using Silverlight
                                  AlistairFrith

                                  These are the requirements I think:

                                  • To be able to list the child elements below a parent element.
                                  • To be able to list the child attributes below a parent element or attribute.
                                  • To be able to list all the elements of a given template
                                  • To be able to list all the elements of a given name
                                  • Maybe to be able to list all the elements that have a specific attribute (by attribute name)

                                  At the moment, I think that would be enough.

                                   

                                  --- Alistair.

                                   

                                  P.s. Although I said that we have succeeded in retrieving data directly from PI, it seems that I may have been a little premature there! We have succeeded with GetPISummaryData() but GetPIArchiveData() fails with 'Not found'. So we can retrieve things like hourly averages but we cannot get the raw archive or snapshot data. I will make another post with the code...

                                    • Re: Getting AF data using Silverlight
                                      AlistairFrith

                                       

                                       

                                      At present we are attempting to collect data directly from the PI server. We are currently able to get PI Summary values for a tag (e.g. hourly averages) but we are unable to retrieve snapshot or archive values.

                                       

                                       

                                       

                                      We find the documentation rather difficult to interpret. Below, I have pasted the code we have that succeeds in retrieving summary values, along with the GetPISummaryData method documentation, then the code that fails to retrieve snapshot or archive values, along with the corresponding GetPIArchiveData method documentation. Finally, there is the ‘Not Found’ error we are receiving.

                                       

                                       

                                       

                                      Any help, examples or pointers to further documentation would be gratefully received.

                                       

                                       

                                       

                                      Regards,

                                       

                                       

                                       

                                      --- Alistair.

                                       

                                       

                                       

                                       

                                       

                                      Code, Extracts from Manual and Error Message…

                                       

                                       

                                      The PISummary data request that is working and displaying values;

                                       

                                       

                                       

                                      The Code:

                                       

                                       

                                       
                                      using System;
                                      using System.Collections.Generic;
                                      using System.Linq;
                                      using System.Net;
                                      using System.Windows;
                                      using System.Windows.Controls;
                                      using System.Windows.Documents;
                                      using System.Windows.Input;
                                      using System.Windows.Media;
                                      using System.Windows.Media.Animation;
                                      using System.Windows.Shapes;
                                      using System.ServiceModel;
                                      using System.ServiceModel.Description;
                                      using System.Windows.Threading;
                                      using Infrigistics_Example;
                                      using Infrigistics_Example.PIWebServices;
                                       
                                      namespace Infrigistics_Example
                                      {
                                          public partial class MainPage : UserControl
                                          {
                                              public MainPage()
                                              {
                                                  InitializeComponent();
                                       
                                                  string sTag = "pi:\\\\brigg-pi01\\cdt158";
                                                 
                                                  //Call PI Web Servic
                                                  EndpointAddress endPointAdd = new EndpointAddress("http://brigg-pi01/PIWebServices/PITimeSeries.svc");
                                                  BasicHttpBinding basicHttpBinding = new BasicHttpBinding();
                                       
                                                  // Set Callback Function  (>'')
                                                  PITimeSeriesClient client = new PIWebServices.PITimeSeriesClient(basicHttpBinding, endPointAdd);
                                       
                                                  //Get Summary Data
                                                  client.GetPISummaryDataCompleted += new EventHandler(client_GetPISummaryDataCompleted);
                                       
                                                  PISummaryDataRequest[] requests = new PISummaryDataRequest[1];
                                       
                                                  PISummaryDataRequest sumReq = new PISummaryDataRequest();
                                                  PISummaryManner summanner = new PISummaryManner();
                                                  summanner.Intervals = 24;
                                                  summanner.SummaryValue = PISummaryMannerSummaryValue.Average;
                                                  summanner.WeightType = PISummaryMannerWeightType.TimeWeighted;
                                                  sumReq.PISummaryManner = summanner;
                                                  sumReq.Path = sTag;
                                                  TimeRange sumTR = new TimeRange();
                                                  sumTR.Start = "*-1d";
                                                  sumTR.End = "*";
                                                  sumReq.TimeRange = sumTR;
                                                  requests[0] = sumReq;
                                       
                                                  client.GetPISummaryDataAsync(requests);
                                       
                                              void client_GetPISummaryDataCompleted(object sender, GetPISummaryDataCompletedEventArgs e)
                                              {
                                                  TimeSeries[] ts = (TimeSeries[])e.Result;
                                                  label1.Content = ts[0].TimedValues[0].Value + "   " + ts[0].TimedValues[1].Value;
                                              }
                                      
                                       
                                      

                                      And with the accompanied ‘Instructions’

                                       

                                       

                                       

                                      GetPISummaryData Method

                                       

                                      Returns summaries of PI Archive data. This method can return averages, means, minima, maxima, ranges, totals, values, counts, and both sample and population standard deviations.

                                       

                                      Syntax

                                       

                                      TimeSeries (page 78)[] GetPISummaryData(PISummaryDataRequest (page 75)[] requests);

                                       

                                      Arguments

                                       

                                      PISummaryDataRequest (page 75)

                                       

                                      Returns

                                       

                                      TimeSeries (page 78)

                                       

                                      Errors

                                       

                                      If the Web service endpoint cannot be reached, the GetPISummaryData method returns a fault and no data are returned.

                                       

                                       

                                       

                                      PISummaryDataRequest

                                       

                                      Applies to (page 68)

                                       

                                      Represents a query for summary data from a single Path (page 5) for a given time range subject to certain parameters. Since an array of PISummaryDataRequest objects can be passed in a single call to GetPISummaryData (page 68), any number of independent summary data requests can be placed at once.

                                       

                                      Members

                                       

                                      Path (page 5)

                                       

                                      TimeRange (page 77)

                                       

                                      PISummaryManner (page 75)

                                       

                                      PISUMMARYMANNER

                                       

                                      Member of (page 75) Applies to (page 68) Members (page 75)

                                       

                                      Represents the type of summary retrieval. Use this class to specify the summary type and other properties.

                                       

                                      Members

                                       

                                       

                                       

                                       

                                      Followed by the GetArchiveData method that does not work:

                                       

                                       

                                       

                                      The Code:

                                       

                                       

                                       
                                                  string sTag = "pi:\\\\brigg-pi01\\cdt158";
                                                 
                                                  //Call PI Web Service
                                                  EndpointAddress endPointAdd = new EndpointAddress("http://brigg-pi01/PIWebServices/PITimeSeries.svc");
                                                  BasicHttpBinding basicHttpBinding = new BasicHttpBinding();
                                       
                                                  // Set Callback Function  (>'')
                                                  PITimeSeriesClient client = new PIWebServices.PITimeSeriesClient(basicHttpBinding, endPointAdd);
                                       
                                                 // Get Archive Data
                                                  client.GetPIArchiveDataCompleted += new EventHandler(client_GetPIArchiveDataCompleted);
                                                  client.GetProductVersionAsync();
                                       
                                                  PIArcDataRequest[] requests = new PIArcDataRequest[1];
                                                  PIArcDataRequest req = new PIArcDataRequest();
                                                  PIArcManner myPIArcManner = new PIArcManner();
                                                  myPIArcManner.RetrievalType = PIArcMannerRetrievalType.Compressed;
                                                  myPIArcManner.Boundaries = PIArcMannerBoundaries.Interpolated;
                                                  //myPIArcManner.NumValues = 10;  <- We have tried a few values here, to no avail.
                                                  TimeRange tr = new TimeRange();
                                                  tr.Start = "*-1h";
                                                  tr.End = "*";
                                                  req.TimeRange = tr;
                                                  req.Path = sTag;
                                                  TimeSeries[] TS = new TimeSeries[0];
                                                  requests[0] = req;
                                       
                                                  client.GetPIArchiveDataAsync(requests);
                                              }
                                       
                                       
                                              void client_GetPISummaryDataCompleted(object sender, GetPISummaryDataCompletedEventArgs e)
                                              {
                                                  TimeSeries[] ts = (TimeSeries[])e.Result;
                                                  label1.Content = ts[0].TimedValues[0].Value + "   " + ts[0].TimedValues[1].Value;
                                              }
                                       
                                      
                                       
                                      
                                       

                                      with the ‘Instructions’ again;

                                       

                                       

                                       

                                      GetPIArchiveData Method

                                       

                                      Retrieves Compressed, Interpolated and Plot Values as a TimeSeries (page 78).

                                       

                                      Syntax

                                       

                                      TimeSeries (page 78)[] GetPIArchiveData(PIArcDataRequest (page 73)[] requests)

                                       

                                      Arguments

                                       

                                      PIArcDataRequest (page 73)

                                       

                                      Returns

                                       

                                      TimeSeries (page 78)

                                       

                                      Errors

                                       

                                      The returned TimeSeries (page 78) array has the same number of elements as the input PIArcDataRequest (page 73) array. If an error occurs when data for an individual PIArcDataRequest (page 73) is retrieved, the error code and description will be reflected in the corresponding element of the TimeSeries (page 78) array.

                                       

                                      If the Web service endpoint cannot be reached, the GetPIArchiveData method returns a fault and no data are returned.

                                       

                                       

                                       

                                      Remarks

                                       

                                      The behavior during retrieval of Compressed values depends entirely on the existence of events in the PI Archive. If the time range specified in the request does not include any events, you will receive a TimeSeries (page 78) object that has no events; that is, an empty TimedValue (page 80) array. This is important when querying paths containing stale data since you will retrieve data only if the time range includes the time of the most recent snapshot. A solution is to set the Boundaries property of the PIArcManner (page 73) object of the PIArcDataRequest (page 73) to Outside.

                                       

                                      This is important for queries of snapshot values that specify a TimeRange (page 77) for the current time; These queries must specify StartTime=* and EndTime=*, since the snapshot is usually before or at current time.

                                       

                                      For details about how time stamps are applied when you use PI Web Services, refer to Time Stamps (page 8).

                                       

                                       

                                       

                                      PIArcDataRequest

                                       

                                      Applies to (page 67)

                                       

                                      Represents a query to a PI System for Compressed, Interpolated or Plot Values from a single Path (page 5), subject to a single time range (page 77) constraint (page 7) using a single Manner (page 7). Since an array of PIArcDataRequest objects can be passed in a single call to GetPIArchiveData (page 67), any number of independent data requests can be placed at once.

                                       

                                      Members

                                       

                                      Path (page 5)

                                       

                                      PIArcManner (page 73)

                                       

                                      TimeRange (page 77)

                                       

                                      PIARCMANNER

                                       

                                      Member of (page 73) Applies to (page 67) Members (page 74)

                                       

                                      This class contains properties needed to define retrieval behavior for Archive data. Use it to specify Compressed, Interpolated or Plot Values retrieval, boundary handling, and data limits.

                                       

                                      Example

                                       

                                      PIArcManner myPIArcManner = new PIArcManner();

                                       

                                      myPIArcManner.RetrievalType= PIArcMannerRetrievalType.Compressed;

                                       

                                      myPIArcManner.Boundaries= PIArcMannerBoundaries.Outside;

                                       

                                      myPIArcManner.NumValues = 100;

                                       

                                       

                                      Here is a screenshot of the error and its location: 

                                       

                                      4721.Silverlight-Error.png

                                       

                                       

                                       

                                       

                                       

                                       

                                       

                                       

                                       

                                       

                                      The problems we are having is that we can retrieve data from the ‘GetSummaryData’ option however we are unable to use ‘GetArchiveData’, we just get the error as shown in the screenshot above.

                                       

                                      We can however, obtain archive values from the web service using ‘WCFStorm’ (The program recommended in the ‘PIWebServices Manual’ for testing data retrieval)

                                       

                                       

                                       

                                      Hope this is enough information to potentially understand the error and find a solution.

                                       

                                       

                                       

                                      Many Thanks

                                        • Re: Getting AF data using Silverlight
                                          MichaelvdV@Atos

                                          It almost looks like you are experiencing a Silverlight related cross-domain security issue. This would mean that other (non-silverlight) clients will have no problem accessing the service operations, but Silverlight clients do (because of the cross-domain issue).

                                           

                                          Basically, what you need is a clientaccesspolicy.xml file in the root of your webserver. This policyfile describes what rich clients (silverlight and flash) are allowed to access on the server.

                                           

                                          This is a very common issue with Silverlight, mainly because the exceptions are not clear.

                                           

                                          Some references:

                                           

                                          http://msdn.microsoft.com/en-us/library/cc197955(v=vs.95).aspx

                                           

                                          http://www.silverlight.net/learn/data-networking/introduction-to-data-and-networking/how-to-use-cross-domain-policy-files-with-silverlight

                                           

                                           

                                            • Re: Getting AF data using Silverlight
                                              AlistairFrith

                                              We already have clientaccesspolicy.xml and it is set to allow all silverlight through.

                                               

                                               <?xml version="1.0" encoding="utf-8" ?>
                                                <access-policy>
                                                  <cross-domain-access>
                                                    <!--
                                                      Silverlight 3 or higher requires the http-request-headers attribute.
                                                    -->
                                                    <policy>
                                                      <allow-from http-request-headers="*">
                                                        <domain uri="http://*" />
                                                        <domain uri="https://*" />
                                                      </allow-from>
                                                      <grant-to>
                                                        <resource path="/" include-subpaths="true" />
                                                      </grant-to>
                                                    </policy>
                                                  </cross-domain-access>
                                                </access-policy>

                                               

                                              If we remove it then the GetPISummaryData call fails as well as GetPIArchiveData. I can't see how that file would allow the one call and not the other.

                                               

                                              We have downloaded the Web Developer Helper tool mentioned in the silverlight.net link you posted but it gives us no further information.

                                               

                                              --- Alistair.

                                               

                                               

                                                • Re: Getting AF data using Silverlight
                                                  AlistairFrith

                                                  A bit more info from Web Developer Helper (WDH). Here is the WDH log from the successful GetPISummaryData call:

                                                   

                                                  0451.WDH01.png

                                                   

                                                   As you can see, it accesses clientaccesspolicy.xml.

                                                   

                                                  Now here is the WDH log from the failed GetPIArchiveData call:

                                                   

                                                  0550.WDH02.png

                                                   

                                                  There is no mention of clientaccesspolicy.xml.

                                                   

                                                  I don't know if this is useful or a red herring. I still can't see how that file could allow one request but not the other.

                                                   

                                                  ---  Alistair. 

                                                   

                                                   

                                                    • Re: Getting AF data using Silverlight
                                                      MichaelvdV@Atos

                                                      I'm not 100% sure if Silverlight cashes caches the information from the clientaccesspolicy.xml file (thus calling it once every X calls or after Y time.

                                                       

                                                      What happens if you first call the GetPIArchiveData, and then GetPISummaryData?

                                                       

                                                      I'm not 100% sure it's the cross-domain issue, but the error message does sound like it...

                                                       

                                                      I'm not sure if one of the  PIWebservices/Silverlight experts have seen this behavior before?

                                                       

                                                      edit: big difference between caching and cashing :-)