10 Replies Latest reply on Mar 9, 2012 8:09 PM by charlie@osisoft.com

    Time In Future error

    rbrown567

      I get a TimeInFuture error, 0x80040765, when I execute the following code:

       

      JNIEXPORT jboolean JNICALL Java_com_draper_smartgen_PiConnector_setPiValueFloat
        (JNIEnv *env, jobject obj, jstring serverName, jstring tagName, jfloat newValue, jdouble timeStamp)
      {
          _bstr_t bServerName,bTagName;
         
          const char *tag = env->GetStringUTFChars(tagName, 0);
          const char *server = env->GetStringUTFChars(serverName, 0);
         
          bServerName = server;
          bTagName = tag;
         

          CoInitialize(NULL);
         
          try {
              IPISDKPtr pPISDK(__uuidof(PISDK));
              ServersPtr pServers;
              ServerPtr pServer;

              pServers = pPISDK->Servers;
              pServer = pServers->Item[bServerName];
             
              PIPointsPtr pPiPoints;
              PIPointPtr pPoint;
             
              pPiPoints = pServer->PIPoints;
              pPoint = pPiPoints->Item[bTagName];
             
              float nv = newValue;

              pPoint->Data->UpdateValue(nv, "*", dmReplaceDuplicates, NULL);
             
          }
          catch(_com_error Err)
          {
              _tprintf(_T("Error:%s : 0x%x \n"),(TCHAR *)Err.Description(),Err.Error());
              return false;
          }
         
          CoUninitialize();
         
          env->ReleaseStringUTFChars(tagName, tag);
          env->ReleaseStringUTFChars(serverName, server);
          return true;
      }

       

      Why is this happening.

        • Re: Time In Future error
          Ahmad Fattahi

          Is the PI Server on the same machine you are running your application? If not, can you see any time mismatch between the two boxes?

           

          Assuming your error is thrown on the UpdateValue method, can you try the method with 1) an absolute timestamp clearly in the past b) an older relative timestamp such as "*-1d" or "*-30d" to see if you get any different result?

            • Re: Time In Future error
              rbrown567

              The PI Server and the machine on which I'm running my application have their times synched via NTP.  I'm still getting errors even though I'm using "*-120s".  Occasionally I also get a "Unable to create _PITime" error (0x80040519).  I'd like to try creating a PITime object, setting it's value to the current time, and pass that to UpdateValue.  Here's the C++ code I'm using to do that:

               
              try {
              
              IPISDKPtr pPISDK(__uuidof(PISDK));
              
              ServersPtr pServers;
              
              ServerPtr pServer;
              
              pServers = pPISDK->Servers;
              
              pServer = pServers->Item[bServerName];
              
              PIPointsPtr pPiPoints;
              
              PIPointPtr pPoint;
              
              pPiPoints = pServer->PIPoints;
              
              pPoint = pPiPoints->Item[bTagName];
              
              _PITimePtr pTime;
              
              pTime.CreateInstance(__uuidof(PITime));
              
              pTime->SetToCurrent();
              
              float nv = newValue;
              
              pPoint->Data->UpdateValue(nv, pTime, dmReplaceDuplicates, NULL);
              
              }
              
              catch(_com_error Err)
              

               

               

               

               

              However I get the following compilation error:

               

              1>.\PiWrapper.cpp(189) : error C2664: '_PIData::UpdateValue' : cannot convert parameter 2 from '_PITimePtr' to 'const _variant_t &'
              1>        Reason: cannot convert from '_PITimePtr' to 'const _variant_t'
              1>        No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
              1>Build log was saved at "file://c:\smartgen\PI Interface\PiWrapper\Release\BuildLog.htm"
              1>PiWrapper - 1 error(s), 1 warning(s)

               

              I think I'm missing something basic.  Do you have sample C++ code that creates a PITime object and uses it in UpdateValue?

                • Re: Time In Future error
                  andreas

                  Robert Brown

                  I think I'm missing something basic.  Do you have sample C++ code that creates a PITime object and uses it in UpdateValue?

                   

                   

                  Not with PITime - but here are some examples for UpdateValue and UpdateValues in C++

                    • Re: Time In Future error

                      Here's an example with PITimeFormat - which extends PITime.

                       
                      _PITimeFormatPtr pTime;
                      pTime.CreateInstance(__uuidof(PITimeFormat));
                      pTime->InputString = "*-1d";
                      //pTime->InputString = "11-dec-11 11:10:09";
                      //pTime->InputString = "t";
                      
                      // Do something with pTime->LocalDate
                      //                or pTime->UTCFileTime
                      //                or pTime->UTCSeconds
                      //                or pTime->OutputString
                      std::cout << pTime->OutputString;     
                      

                       Hope this helps!

                        • Re: Time In Future error

                          Please take a look at the documentation for the variant time arguments for UpdateValue.  In fact, most PISDK methods use the same conversion algorithm.

                           

                          1. A numeric value for the variant argument will convert directly to a double timestamps (TAI, or nominally UTC) that are sent to the PI Server.  You should be aware of the special treatment a value of 0 receives.

                           

                          2. A string time value must be converted to a double precision value.  The PISDK internally creates a PITimeFormat and uses InputString.  Please read the InputString help page.

                           

                          3. A VT_DISPATCH type is detected and assumed to be a PITime interface.  The UTCSeconds() property is accessed to get the double value.

                           

                          OK, now that is the way it is supposed to work.  Obviously, there is more to this problem.  If "*" is used and time in the future is returned from the PI Server.  I have heard (a long long time ago...) of NTP client algorithms that can create problems, but if any such code remains I would like to hear about it!  I have also heard about satellites broadcasting incorrect information.  A google search should tell us if that happened.  Finally, the EventLog will tell us if NTP is happy on the box.  At this point, let's dismiss the NTP error possibility.

                           

                          So that leaves us with the mystery of the translation of "*".  One clue is the subsequent observation:

                           

                          "Occasionally I also get a "Unable to create _PITime" error (0x80040519).  ".

                           

                          In particular, the "Occasionally" leads me to believe there are lifetime issues for the underlying COM objects.  First, the PISDK object destructor and PITime object destructors may be fired before the completion of the call.  This is particularly likely in languages (Java, .NET) where interop layers are involved.

                           

                          Secondly, the compiler error:

                           

                          1>        Reason: cannot convert from '_PITimePtr' to 'const _variant_t'

                           

                          1>        No user-defined-conversion operator available that can perform this conversion, or

                           

                          is solved by using an explicit QueryInterface for the IDispatch interface, or in _com_ptr syntax, just use (IPIDispatchPtr) cast for the _variant_t argument.

                            • Re: Time In Future error
                              MvanderVeeken

                              Robert,

                               

                              Did the suggestions provided by Ahmad, Steve, Andreas and Charlie help you out with your issue? It would be great to have some feedback for future reference (in case someone else encounters something like this in the future).

                                • Re: Time In Future error
                                  rbrown567

                                  Here is what I ended up doing:

                                   

                                  JNIEXPORT jboolean JNICALL Java_com_draper_smartgen_PiConnector_setPiValueFloat
                                    (JNIEnv *env, jobject obj, jstring serverName, jstring tagName, jfloat newValue, jdouble timeStamp)
                                  {
                                       _bstr_t bServerName,bTagName;
                                       
                                       const char *tag = env->GetStringUTFChars(tagName, 0);
                                       const char *server = env->GetStringUTFChars(serverName, 0);
                                       
                                       bServerName = server;
                                       bTagName = tag;
                                       
                                  
                                       CoInitialize(NULL);
                                       
                                       try {
                                            IPISDKPtr pPISDK(__uuidof(PISDK));
                                            ServersPtr pServers;
                                            ServerPtr pServer;
                                  
                                            pServers = pPISDK->Servers;
                                            pServer = pServers->Item[bServerName];
                                            
                                            PIPointsPtr pPiPoints;
                                            PIPointPtr pPoint;
                                            
                                            pPiPoints = pServer->PIPoints;
                                            pPoint = pPiPoints->Item[bTagName];
                                  
                                            _PITimeFormatPtr pTime;
                                            pTime.CreateInstance(__uuidof(PITimeFormat));
                                            pTime->SetToCurrent();
                                            
                                            float nv = newValue;
                                            pPoint->Data->UpdateValue(nv, pTime->GetOutputString(), dmReplaceDuplicates, NULL);
                                            _tprintf(_T("value:%g date:%s written to PI"),nv,(TCHAR *)pTime->GetOutputString());
                                       
                                       }
                                       catch(_com_error Err)
                                       {
                                            
                                            _tprintf(_T("Error:%s : 0x%x \n"),(TCHAR *)Err.Description(),Err.Error());
                                            return false;
                                       } 
                                       
                                       CoUninitialize();
                                       
                                       env->ReleaseStringUTFChars(tagName, tag);
                                       env->ReleaseStringUTFChars(serverName, server);
                                       return true;
                                  }
                                  

                                   

                                  I didn't have time to try out Charles Henze's suggestion.  When I get more time I'll do that. What I'm doing works, although it may not be the most efficient way.

                                    • Re: Time In Future error

                                      Robert,

                                       

                                      A few more optimal code examples shown below:

                                       
                                      {
                                         ServersPtr pServers;
                                         ServerPtr pServer = pServers->Item[bServerName];
                                         // Do an explicit connection step for easier readability
                                         _bstr_t strCnxn(L"");
                                         pServer->Open(strCnxn);
                                      
                                         // This highlights the implicit type cast of the value argument
                                         _variant_t vtnv((float)42.0);
                                      
                                         // double UTC seconds is passed to the PI Server, so eliminate some conversions.
                                         // Some more optimal methods w/o To/From string types.
                                         _variant_t vtTime(pServer->ServerTime()->UTCSeconds); // Server subsecond time
                                         _variant_t vtTime2((long)time(NULL)); // integer UTC/TAI time
                                         _PITimePtr pPItime(__uuidof(PITime));
                                         pPItime->SetToCurrent();
                                         _variant_t vtTime3(pPItime->UTCSeconds); // integer UTC/TAI time
                                      
                                         // Two ways to pass _variant_t as (VARIANT *) type.
                                         pData->UpdateValue(&vtnv, &(vtTime.GetVARIANT()), dmReplaceDuplicates, NULL);
                                      }
                                      

                                       PS. If this is called often, the initialize and wind-down of the PISDK object and connection can take significant time.