Skip to content

Latest commit

 

History

History
608 lines (431 loc) · 26.8 KB

changelog.rst.txt

File metadata and controls

608 lines (431 loc) · 26.8 KB

UAF changelog

Version = X.Y with

  • X : major version number
    • incremented only when major functionality has been added
    • e.g. when a Server implementation has been added
  • Y : minor version number
    • incremented every time some minor functionality has been added
    • e.g. when the Client implementation supports another OPC UA service

Bugfixes (which do not have any implications on the API) can only be tracked via the GIT version control system.

1.10 @ 2014/07/30

Important notice This version will be the last version before version 2.0.0, which will contain a few rather drastic API changes, affecting poorly designed parts of the UAF (see the plans for version 2.0.0 below). The goal is to turn this version (1.10) into a "long-term" supported one, by maintaining it in a different branch from version 2.0.0, which will receive an updated API and new features.

So there will be two main branches:

  • long-term:
    • based on version 1.10 (this one)
    • tested and production-ready at any time
    • API and feature set are frozen, but bugfixes are applied.
  • master:
    • will start with version 2.0.0, and will then adhere to [semantic versioning](http://semver.org)
    • tested and production-ready at any time
    • contains latest API and latest features, is actively developed.

Plans for version 2.0.0:

  • simplify the API related to session/subscription management. Get rid of concepts like "SessionConfig", "SubscriptionConfig", "manuallyConnect", ... and simply provide functions like "createSession", "createSubscription", etc. Session and subscription management remains optional for the user (as it's easier to let the UAF handle that), but those users that want to keep full control over their sessions and subscriptions will have a much easier API to work with.
  • support security
  • fix some small API inconsistencies so that the remaining missing OPC UA services (such as ModifyMonitoredItems) can be implemented easily, and so that the API can remain more stable while the first attempts to implement the server-side are carried out...

New in this version:

Informally:

  • Updated the README.md to explain the intent and the added value of (Py)UAF a bit better (section "Why?").

  • The monitoring mode (Disabled/Sampling/Reported) can now be set for monitored items via the SetMonitoringMode service. This is the preferred way to temporarily disable monitored items from being reported, e.g. when the tab of a graphical user interface is not visible. The newly added method "setMonitoringMode" will find out to which sessions and subscriptions your specified monitored items belong to: you only have to provide their client handles. This means that you can code your application against the specification of some nodes, without worrying about questions like "which node is currently hosted by which server?" or "which monitored item currently belongs to which subscription?".

  • Connections and subscriptions can now be monitored much better because the following events are now exposed to the user (via callback functions):

    • ConnectionStatusChanged
    • SubscriptionStatusChanged
    • NotificationsMissing
  • !!! breaking change !!!

    By default, when you create monitored items, the queue size is now 1 and the discard policy is set to "discard oldest". The default queue size used to be 0, which meant that servers always had to revise this number and correct it to 1. The default discard policy used to be "discard newest", which meant that the most recent data got lost in case a variable changed too rapidly. With the new defaults, clients are now always notified of the most recent data changes and events. For most applications, this makes a lot more sense.

  • Bugfix: the value returned by pyuaf.util.Status.opcUaStatusCode() was sometimes wrong: SWIG converted the value into a signed 'long' which numerically (but not always bitwise!) corresponds to the 32-bit code defined by the OPC UA standard. Since pyuaf.util.opcuastatuscodes contains 'int's that correspond bitwise (but not always numerically!) to the status codes defined by the OPC UA standard, there was a mismatch between the output of pyuaf.util.Status.opcUaStatusCode() and the contents of pyuaf.util.opcuastatuscodes. This is now fixed: both correspond now bitwise to the OPC UA status codes, so they can be compared with each other.

  • Fixed a bug that caused the UAF to crash when providing Namespace URIs and Server URIs that contain percentage (%) signs. The bug occurred when trying to connect to the Ignition OPC UA server by Inductive Automation. See http://github.com/uaf/uaf/issues/30

  • Microsoft VS2008 is now supported (credits to robi-wan @ GitHub). The VS2008 compiler requires the third-party "msinttypes" C++ headers, which are shipped with the UAF. If you don't want these headers to be included automatically by the CMake build script, set the NO_THIRD_PARTY_MSINTTYPES option to ON (see install_windows.rst.txt). See http://github.com/uaf/uaf/issues/29

  • Python primitives such as pyuaf.util.primitives.Bool, UInt32 etc. now also accept strings, which they automatically cast to the correct datatype. For example, besides IUnt64(42) you can now also write UInt64("42"). See http://github.com/uaf/uaf/issues/27

Formally:

  • The following methods were added:
    • uafc::Client::setMonitoringMode (pyuaf.client.Client.setMonitoringMode)
  • On the C++ side, the following methods were added to uafc::ClientInterface:
    • connectionStatusChanged
    • subscriptionStatusChanged
    • notificationsMissing
  • On the Python side, the following methods were added to pyuaf.client.Client:
    • connectionStatusChanged() and registerConnectionStatusCallback()
    • subscriptionStatusChanged() and registerSubscriptionStatusCallback()
    • notificationsMissing() and registerNotificationsMissingCallback()
    • registerKeepAliveCallback() (note: keepAliveReceived() existed already)
  • The following method may produce a different output in some cases (Python only):
    • pyuaf.util.Status.opcUaStatusCode() (the output now always corresponds to the numbers defined in pyuaf.util.opcuastatuscodes)
  • The following attributes have different default value:
    • uafc::CreateMonitoredDataRequest::queueSize (pyuaf.client.requests.CreateMonitoredDataRequest.queueSize) --> now 1 instead of 0
    • uafc::CreateMonitoredDataRequest::discardOldest (pyuaf.client.requests.CreateMonitoredDataRequest.discardOldest) --> now true instead of false
    • uafc::CreateMonitoredEventsRequest::queueSize (pyuaf.client.requests.CreateMonitoredEventsRequest.queueSize) --> now 1 instead of 0
    • uafc::CreateMonitoredEventsRequest::discardOldest (pyuaf.client.requests.CreateMonitoredEventsRequest.discardOldest) --> now true instead of false

1.9 @ 2014/04/17

Informally:

  • This version doesn't really add more features to the UAF. It mostly fixes some not-so-critical problems that have been known for a long while, but were cumbersome to solve.

  • Bugfix: iterators of vectors are now properly wrapped. So you can do "for item in vec: ..." for all vectors. This functionality is now also tested by the unittests.

  • Improved the reading/writing/historical reading/... of NodeIds, ExpandedNodeIds and QualifiedNames. Whenever you are reading/writing/... these particular datatypes, they will automatically be resolved by the UAF. For instance: when you read a QualifiedName, only the namespace index of the QualifiedName will be sent over the wire. As of now, the UAF will automatically insert the correct namespace URI into the result (according to the NamespaceArray of the server), so that the result is fully resolved. Another example: you can now simply do:

    currentOrderAddress = Address(NodeId("currentOrder", "my_company_namespace_uri"), "my_server_uri")
    myClient.write(addresses = [ currentOrderAddress ]
                   data      = [ NodeId("orders.order5", "my_company_namespace_uri") ])

    In the above example, the UAF will automatically resolve the 'data' argument (meaning: it will find out the namespace index of "my_company_namespace_uri" and insert it into the data argument, before sending the request to the server).

  • Completely removed the abstract class uaf::Stringifiable (pyuaf.util.Stringifiable). This most likely won't affect your code (do a search for "Stringifiable" if in doubt: if you don't find any occurrence, then you're safe).

    • Rationale: The reason for removing it is that SWIG had difficulties with vectors of classes that derive from uaf::Stringifiable. More specifically: SWIG didn't wrap the iterators correctly of std::vectors of classes in the uafc:: namespace that implement uaf::Stringifiable. For example, you couldn't do:

      vec = pyuaf.client.settings.SessionSecuritySettingsVector()
      vec.resize(2)
      for item in vec:
          print(item)

      Instead, you could only do "for i in xrange(len(vec)): ...". The problem was that the iterator ('item' in the code above) didn't point to a properly wrapped SessionSecuritySettings instance. Instead, 'item' was an opaque SWIG value, i.e. a SWIG artifact that you couldn't use directly. Now that SessionSecuritySettings doesn't implement Stringifiable anymore, this bug is avoided. Of course it comes at the cost of losing uaf::Stringifiable, but this class wasn't very useful so the advantage of fixing the bug was considered more important.

  • Added comparison operators for several classes.

Formally:

  • The following classes have been removed:
    • uaf::Stringifiable (pyuaf.util.Stringifiable)
  • Comparison operators (==, != and < in C++; __eq__, __ne__, __lt__, __gt__, __ge__ and __le__ in Python) have been added to the following existing classes:
    • uaf::ApplicationDescription (pyuaf.util.ApplicationDescription)
    • uaf::UserTokenPolicy (pyuaf.util.UserTokenPolicy)
    • uaf::EndpointDescription (pyuaf.util.EndpointDescription)
    • uafc::SessionSecuritySettings (pyuaf.client.settings.SessionSecuritySettings)
    • uafc::MonitoredItemNotification (pyuaf.client.MonitoredItemNotification)
    • uafc::DataChangeNotification (pyuaf.client.DataChangeNotification)
    • uafc::EventNotification (pyuaf.client.EventNotification)
    • uafc::AsyncResultTarget (pyuaf.client.results.AsyncResultTarget)
    • uafc::BrowseResultTarget (pyuaf.client.results.BrowseResultTarget)
    • uafc::CreateMonitoredDataResultTarget (pyuaf.client.results.CreateMonitoredDataResultTarget)
    • uafc::CreateMonitoredEventsResultTarget (pyuaf.client.results.CreateMonitoredEventsResultTarget)
    • uafc::HistoryReadRawModifiedResultTarget (pyuaf.client.results.HistoryReadRawModifiedResultTarget)
    • uafc::MethodCallResultTarget (pyuaf.client.results.MethodCallResultTarget)
    • uafc::ReadResultTarget (pyuaf.client.results.ReadResultTarget)
    • uafc::TranslateBrowsePathsToNodeIdsResultTarget (pyuaf.client.results.TranslateBrowsePathsToNodeIdsResultTarget)
    • uafc::WriteResultTarget (pyuaf.client.results.WriteResultTarget)

1.8 @ 2014/03/10

Informally:

  • The client can now manually connect to an endpoint, without using the discovery services.

    A UAF client normally uses the discovery process to identify a server and connect to it. The user therefore doesn't have to worry about connecting, disconnecting, session management, etc. However, in certain cases you may want to connect manually to a specific endpoint, without using the discovery process (i.e. without relying on the discovery endpoint of the server). In these cases, you can now use Client::manuallyConnectToEndpoint().

Formally:

  • The following methods were added to existing classes:
    • uafc::Client::manuallyConnectToEndpoint() (pyuaf.client.Client.manuallyConnectToEndpoint())

1.7 @ 2014/01/28

Informally:

  • The 'SetPublishingMode' service has been implemented. With this service, you can enable or disable the publishing of notifications by a particular subscription. It's useful e.g. when you want to receive datachange notifications only when a particular widget of your User Interface is active. In this case, you can group the monitored items of that widget in a single subscription (could be a "unique" subscription, by setting the "unique" flag of the SubscriptionSettings), and then subsequently:

    • enable the subscription, whenever the widget becomes active
    • disable the subscription, whenever the widget becomes inactive.
  • A method 'monitoredItemInformation(<ClientHandle>)' has been added to the Client class. The result of this method is a 'MonitoredItemInformation' instance, which provides you information about the monitored item that you specified using the client handle. Among other things, it will tell you the handle of the subscription that owns the monitored item.

  • !!!Breaking change!!!

    The concept of 'notification handles' was redundant with the concept of 'client handles' of monitored items. It has therefore been removed from the UAF. To make sure your code remains compatible, do a (case insensitive) search-all for 'notificationHandle', and replace all occurrences with 'clientHandle'. Note that the term 'notificationhandle' may occur both in attribute names and in method names.

  • !!!Breaking change!!!

    BaseServiceSettings has been renamed to ServiceSettings. This -most likely- won't affect your existing code. To be sure: do a search-all for 'BaseServiceSettings' and replace all occurrences with 'ServiceSettings'.

  • !!!Breaking change!!!

    The 'exclusive' flag of subscription settings has been renamed to a more appropriate 'unique' flag (to force the UAF to create a new subscription instead of reusing an existing one). This -most likely- won't affect your existing code. To be sure: do a search-all for 'exclusive' and replace all occurrences with 'unique'.

Formally:

  • The following methods were added to existing classes:

    • uafc::Client::setPublishingMode() (pyuaf.client.Client.setPublishingMode())
    • uafc::Client::monitoredItemInformation() (pyuaf.client.Client.monitoredItemInformation())
  • The following classes were added:

    • uafc::MonitoredItemInformation (pyuaf.client.Client.MonitoredItemInformation)
  • The following namespaces (modules) were added:

    • uafc::monitoreditemstates (pyuaf.client.monitoreditemstates)
  • The following attributes have been renamed or removed due to the removal of the redundant 'notification handle' concept in favor of the 'client handle' concept:

    • uafc::StatusDiagnostics (pyuaf.util.StatusDiagnostics):

      • hasNotificationHandles() -> renamed to hasClientHandles()
      • getNotificationHandles() -> renamed to getClientHandles()
      • setNotificationHandles() -> renamed to setClientHandles()
    • uafc::MonitoredItemNotification (pyuaf.client.subscriptions.MonitoredItemNotification),
      uafc::DataChangeNotification (pyuaf.client.subscriptions.DataChangeNotification),
      uafc::CreateMonitoredEventsResultTarget (pyuaf.client.results.CreateMonitoredEventsResultTarget),
      uafc::CreateMonitoredDataResultTarget (pyuaf.client.results.CreateMonitoredDataResultTarget)
      • notificationHandle -> removed (use clientHandle instead)
  • The following classes have been renamed:

    • uafc::BaseServiceSettings (pyuaf.client.settings.BaseServiceSettings) has been renamed to uafc::ServiceSettings (pyuaf.client.settings.ServiceSettings)
  • The following attributes have been renamed:

    • uafc::SubscriptionSettings::exclusive (pyuaf.client.settings.SubscriptionSettings.exclusive) has been renamed to uafc::ServiceSettings::unique (pyuaf.client.settings.ServiceSettings.unique)

1.6 @ 2014/01/07

Informally:

  • The UAF / PyUAF now require the Unified Automation SDK version 1.4.0 or higher!

  • The unit tests and examples now require UaServerCPP (that comes with SDK v1.4) to be run instead of UaDemoServer (that comes with SDK v1.3 or lower).

  • The unit tests are now based on Python's 'unittest' builtin module.

  • By default, the UAF is now compiled with HTTPS support. However, if your Stack and SDK were built without HTTPS support, you must (!!!) also compile the UAF without HTTPS support. See the install_linux.rst.txt and install_windows.rst.txt files for more info.

  • Address now also has a constructor to create an address based on a single RelativePathElement. This allows you to define relative addresses in one line, also in C++:

    Address myMachine            ( NodeId("Demo", nsUri), serverUri );
    Address myMachineTemperature ( &myMachine, RelativePathElement(QualifiedName("Temperature" , nsUri)) );
    Address myMachinePressure    ( &myMachine, RelativePathElement(QualifiedName("Pressure"    , nsUri)) );

Formally:

  • The following classes got an additional constructor:
    • uafc::Address (pyuaf.util.Address)

1.5 @ 2013/11/30

Informally:

  • KeepAlive notifications are now supported. KeepAlive notifications make sure that the client is aware that a subscription (and its monitored items) is still alive even though no notifications were send lately (since no data had changed or no events were sent).
  • BaseNotification is now known as MonitoredItemNotification, to clarify that it is only a superclass of DataChangeNotification and EventNotification, and not of other notifications such as the new KeepAliveNotification.

Formally:

  • !!!Breaking change!!!

    uafc::BaseNotification (pyuaf.client.BaseNotification) is now known as uafc::MonitoredItemNotification (pyuaf.client.MonitoredItemNotification). Only the name has changed (because it's more correct, see above), nothing else.

  • The following classes have been added:

    • uafc::KeepAliveNotification (pyuaf.client.KeepAliveNotification)
  • The following methods were added to existing classes

    • uafc::ClientInterface::keepAliveReceived() (pyuaf.client.Client.keepAliveReceived())

1.4 @ 2013/11/27

Informally:

  • When createMonitoredData() or createMonitoredEvents() fail, you can now access the handles that were assigned to the monitored items in Python (<the raised exception>.status.additionalDiagnostics().getNotificationHandles()) and C++ (<the returned Status>.additionalDiagnostics().getNotificationHandles()). This is useful because when createMonitoredData() or createMonitoredEvents() fail (e.g. because the server is not online yet), the UAF will still try to create the monitored items automatically in the background. So as soon as the UAF succeeds in creating the monitored items, you will need the handles to identify the notifications that you start to receive.

Formally:

  • !!!Breaking change (only for the C++ API)!!!

    The handles from "uaf/client/clienthandles.h" (that were part of the uafc namespace) are now part of the "uaf/util/handles.h" file (so they are not part of the uaf namespace). Also uaf::NotificationHandle (formerly uafc::NotificationHandle) is now a 32-bit unsigned int instead of 64-bit unsigned int. All this has no consequences for the Python API.

  • The following classes have been added:

    • uaf::StatusDiagnostics (pyuaf.util.StatusDiagnostics)
  • The following methods were added to existing classes

    • uaf::Status::additionalDiagnostics() (pyuaf.util.Status.additionalDiagnostics())

1.3 @ 2013/11/25

Informally:

  • Added the convenience functions for asynchronous reading and writing (beginRead and beginWrite). (Asynchronous reading and writing was already available before, but only using the generic processRequest function).

Formally:

  • The following methods have been added to existing classes:
    • uafc::Client::beginRead (pyuaf.client.Client.beginRead)
    • uafc::Client::beginWrite (pyuaf.client.Client.beginWrite)

1.2 @ 2013/05/24

Informally:

  • DataValues are now better supported. A DataValue class (with a status, a value, timestamps, ...) has been added, and ReadResultTarget and WriteRequestTarget inherit now from this class.
  • The "timestampstoreturn" namespace / Python module has been added to allow the user to specify which timestamps should be returned by the server.
  • The "opcuastatuscodes" Python module has been added to allow Python users to access all OPC UA status codes symbolically.
  • A new service has been added: it's now possible to read raw historical data, and the modifications of this historical data. As with the Browse service implementation, the UAF can deal with continuation points automatically.

Formally:

  • !!!Breaking change!!!

    An uafc::WriteRequestTarget / pyuaf.client.requests.WriteRequestTarget now has a 'status' attribute (of type uaf::Status / pyuaf.util.Status) instead of a 'opcUaStatusCode' attribute (of type uint32_t / int).

  • The following namespaces (modules) have been added:

    • uaf::timestampstoreturn (pyuaf.util.timestampstoreturn)
  • The following classes have been added:

    • uaf::DataValue (pyuaf.util.DataValue)
    • uafc::HistoryReadRawModifiedRequest (pyuaf.client.requests.HistoryReadRawModifiedRequest)
    • uafc::HistoryReadRawModifiedRequestTarget (pyuaf.client.requests.HistoryReadRawModifiedRequestTarget and pyuaf.client.requests.HistoryReadRawModifiedRequestTargetVector)
    • uafc::HistoryReadRawModifiedConfig (pyuaf.client.configs.HistoryReadRawModifiedConfig)
    • uafc::HistoryReadRawModifiedSettings (pyuaf.client.configs.HistoryReadRawModifiedSettings)
    • uafc::HistoryReadRawModifiedResult (pyuaf.client.requests.HistoryReadRawModifiedResult)
    • uafc::HistoryReadRawModifiedResultTarget (pyuaf.client.requests.HistoryReadRawModifiedResultTarget and pyuaf.client.requests.HistoryReadRawModifiedResultTargetVector)
  • The following class inheritances have been modified:

    • uafc::ReadResultTarget: inherits now from uaf::DataValue (pyuaf.client.results.ReadResultTarget: inherits now from pyuaf.util.DataValue)
    • uafc::WriteRequestTarget: inherits now from uaf::DataValue (pyuaf.client.requests.WriteRequestTarget: inherits now from pyuaf.util.DataValue)
  • The following methods have been added to existing classes:

    • uafc::Client.historyReadRaw() and historyReadModified() (pyuaf.client.Client.historyReadRaw() and historyReadModified())
    • uaf::Status::hasSpecificOpcUaStatusCode(): replaces hasOpcUaStatusCode() (pyuaf.util.Status.hasSpecificOpcUaStatusCode(): replaces hasOpcUaStatusCode())
    • uaf::Status::setOpcUaStatusCode() (pyuaf.util.Status.setOpcUaStatusCode())
    • uaf::DateTime::sleep() and msleep() (pyuaf.util.DateTime.sleep() and msleep())

1.1 @ 2013/05/22

Informally:

  • The Browse service is now supported (including the functionality to let the UAF invoke BrowseNext automatically).
  • Strings and ByteStrings that are part of OPC UA requests and results have become "primitive" values in Python (i.e. they are encapsulated in Python by pyuaf.util.primitives.String and pyuaf.util.primitives.ByteString classes).
  • Bytestrings are now better supported in Python: a typemap has been added that maps a uaf::ByteString to a built-in Python bytearray and the other way around.
  • Timestamps are now supported via the DateTime class.
  • NodeId identifiers can now also be GUIDs (Globally Unique Identifiers) and bytestrings.
  • Browse examples have been added

Formally:

  • The following namespaces (modules) have been added:
    • uaf::nodeclasses (pyuaf.util.nodeclasses)
    • uaf::browsedirections (pyuaf.util.browsedirections)
  • The following classes have been added:
    • uaf::ViewDescription (pyuaf.util.ViewDescription)
    • uaf::Guid (pyuaf.util.Guid)
    • uaf::ReferenceDescription (pyuaf.util.ReferenceDescription and pyuaf.util.ReferenceDescriptionVector)
    • uaf::DateTime (pyuaf.util.DateTime)
    • uafc::BrowseRequest (pyuaf.client.requests.BrowseRequest)
    • uafc::BrowseRequestTarget (pyuaf.client.requests.BrowseRequestTarget and pyuaf.client.requests.BrowseRequestTargetVector)
    • uafc::BrowseConfig (pyuaf.client.configs.BrowseConfig)
    • uafc::BrowseSettings (pyuaf.client.configs.BrowseSettings)
    • uafc::BrowseResult (pyuaf.client.requests.BrowseResult)
    • uafc::BrowseResultTarget (pyuaf.client.requests.BrowseResultTarget and pyuaf.client.requests.BrowseResultTargetVector)
    • uafc::BrowseNextRequest (pyuaf.client.requests.BrowseNextRequest)
    • uafc::BrowseNextRequestTarget (pyuaf.client.requests.BrowseNextRequestTarget and pyuaf.client.requests.BrowseNextRequestTargetVector)
    • uafc::BrowseNextConfig (pyuaf.client.configs.BrowseNextConfig)
    • uafc::BrowseNextSettings (pyuaf.client.configs.BrowseNextSettings)
    • uafc::BrowseNextResult (pyuaf.client.requests.BrowseNextResult)
    • uafc::BrowseNextResultTarget (same as pyuaf.client.requests.BrowseResultTarget and pyuaf.client.requests.BrowseResultTargetVector)
  • The following methods and attributes have been added to existing classes:
    • uafc::Client::browse() (pyuaf.util.Client.browse())
    • uaf::NodeId::isNull() (pyuaf.util.NodeId.isNull())
    • uaf::NodeIdIdentifier::isNull(), idGuid, idOpaque (pyuaf.util.NodeIdIdentifier.isNull(), idGuid, idOpaque)
    • uaf::Variant::toDateTime(), toDateTimeArray(), fromDateTime(), fromDateTimeArray() (DateTime Variants are converted automatically into DateTime instances in Python)
    • uaf::Variant::toByteString(), fromByteString(), toByteStringArray(), fromByteStringArray() (ByteString Variants are converted automatically into bytearray instances in Python)

1.0 @ 2013/05/14

  • Public release on GitHub.