Classes | Typedefs

# Device Model
[HUPnP Core]

This page explains the concept of HUPnP Device Model, which is the logical object hierarchy of HUPnP representing the UPnP Device Architecture. More...

## Classes
class | HAction
| A class that represents a UPnP action found in a UPnP service. More...
class | HActionArgument
| A class that represents an argument for a UPnP action invocation. More...
class | HActionArguments
| A storage class for HActionArgument instances. More...
class | HActionSetup
| This class is used to specify information that is required to setup an HAction. More...
class | HActionsSetupData
| This class is used to specify information that is required to setup the `HActions` of an HService. More...
class | HAsyncOp
| This class is used to identify an asynchronous operation and detail information of it. More...
class | HDevice
| An abstract base class that represents a UPnP device hosted by the HUPnP library. More...
class | HDeviceProxy
| A class that is used at client-side to represent a UPnP device. More...
class | HDeviceSetup
| This class is used to specify information that is required to setup an HDevice. More...
class | HDevicesSetupData
| This class is used to specify information that can be used to setup multiple HDevice instances. More...
class | HExecArgs
| This class is used to specify information used to control the execution of an asynchronous operation and the notification of its completion. More...
class | HReadableStateVariable
| Class that provides read-only access to a state variable. More...
class | HService
| An abstract base class that represents a UPnP service hosted by an HDevice. More...
class | HServiceProxy
| A class that is used at client-side to represent a service found in a UPnP device. More...
class | HServiceSetup
| This class is used to specify information that is required to setup an HService. More...
class | HServicesSetupData
| This class is used to specify information that can be used to setup multiple HService instances. More...
class | HStateVariable
| Class that represents a UPnP state variable. More...
class | HStateVariableEvent
| A class used to transfer HStateVariable event information. More...
class | HStateVariablesSetupData
| This class is used to specify information that is required to setup the `HStateVariables` of an HService. More...
class | HWritableStateVariable
| Class that provides write access to a state variable. More...
class | HStateVariableLocker
| A class that enables locking an HWritableStateVariable for exclusive access. More...
## Typedefs
typedef Functor< int, H_TYPELIST_2(const Herqq::Upnp::HActionArguments &, Herqq::Upnp::HActionArguments *) | HActionInvoke )
typedef Functor< bool, H_TYPELIST_1(HAsyncOp)> | HActionInvokeCallback
typedef QList< HService * > | HServices
typedef QList< HServiceProxy * > | HServiceProxies
typedef QList< HDevice * > | HDevices
typedef QList< HDeviceProxy * > | HDeviceProxies
typedef QList< HStateVariable * > | HStateVariables
typedef QList< HAction * > | HActions

## Detailed Description

## A few notes about the design

The main four components of the UPnP device model are a device (Herqq::Upnp::HDevice), a service (Herqq::Upnp::HService), a state variable (Herqq::Upnp::HStateVariable) and an action (Herqq::Upnp::HAction). These four components form a type of a tree in which devices and services are contained by devices, and state variables and actions are contained by services. This is called the device tree. A device tree has a root device, which is a UPnP device that has no parent, but may contain other UPnP devices. These contained devices are called embedded devices.

The purpose of the other classes part of the device model is to support the initialization and use of the four core classes.

### API differences between client and server sides

The HUPnP device model is largely the same at the server and client sides. That is, whether you are writing a custom UPnP device or trying to interact with a UPnP device found in the network, you will be interacting with the HUPnP device model similarly. The most notable difference is that whereas at server side you will be interacting with classes derived directly from the main four components (`HDevice`, `HService`, `HAction` and `HStateVariable`), at client side you will be interacting with devices and services derived from Herqq::Upnp::HDeviceProxy and Herqq::Upnp::HServiceProxy respectively.

The `HDeviceProxy` is an `HDevice` and the `HServiceProxy` is an `HService`. They both provide some additional methods not found in their base classes, but otherwise their usage is identical. The reason the client side introduces the proxy classes is tied to the very nature of client-server architecture; the server side usually contains the business logic, whereas the client side only invokes it. Put in HUPnP terms, a server side `HDevice` often contains code that is undesired at client-side and vice versa. Furthermore, the model is clearer when the design makes the difference explicit and as such the model clearly separates the different code bases of server-side and client-side.

### The lifetime and ownership of objects

Every `HDevice` has the ownership of all of its embedded devices, services, actions and state variables and the ownership is never released. This means that every `HDevice` always manages the memory used by the objects it owns. Hence, the owner of a root `HDevice` ultimately has the ownership of an entire device tree. This is very important to notice; the lifetime of every object contained by the root device depends of the lifetime of the root device. Or in other words, when a root device is deleted, every embedded device, service, state variable and action underneath it are deleted as well. Furthermore, every root `HDevice` is always owned by HUPnP and the ownership is never released. Because of this you should never call `delete` to any of the components of the device model that is setup by HUPnP. This will result in undefined behavior.

Note:
  There are situations where you may want to instruct HUPnP to `delete` an `HDevice`. For instance, when a UPnP device is removed from the network you may want your `HControlPoint` instance to remove the device that is no longer available. This can be done through the `HControlPoint` interface. But note, HUPnP never deletes an `HDevice` without an explicit request from a user.

## Usage

The device model is location independent, which in essence means that the device model is almost always used the same way. That is, if you have a pointer to any of the core components of the device model, you use the object the same way regardless of whether you got the pointer directly or indirectly from a Herqq::Upnp::HDeviceHost or a Herqq::Upnp::HControlPoint. There is one exception to the rule and it will be discussed in the section concerning the state variables.

Basic use is about interacting with already created objects that comprise the device model. To get started you need to initialize either a device host or a control point and retrieve a list of root devices from it. See Device Hosting for more information about device hosts and control points. Once you have a root device you can interact with any of its embedded devices, services, state variables and actions until:

- you explicitly request an `HDevice` be deleted,
- shut down the owner of a device tree, such as `HControlPoint` or `HDeviceHost`.

See the corresponding classes for more information concerning their use.

Note:
  By default, `HControlPoint` keeps the state of the state variables up-to-date. That is, using default configuration an `HControlPoint` automatically subscribes to events the UPnP services expose. In such a case the state of a device tree at control point side reflects the state of the corresponding device tree at device host side as accurately as the device host keeps sending events.

However, if you wish to implement and host your own UPnP device, things get more involved. See Tutorial for Building a UPnP Device to get you started on building your own UPnP devices.

## About State Variables

UPnP Device Architecture does not specify a mechanism for changing the value of a state variable from a control point. Certainly the value of a state variable may be changeable, but that and the method how it is done depends of the service type in which the state variable is defined.

As described previously, HUPnP uses the same device model everywhere. This means that the same fundamental core classes are used both at the server and client sides. Perhaps the most significant benefit of this is that it provides uniform API regardless of the type of use. In turn, uniform API calls for simplicity and re-usability, since there is only one class structure to be learned and used on both server and client side programming.

However, the lack of a standardized method for manipulating the values of state variables means that the client and server-side cannot use an exactly symmetrical API. This is because on server-side you have to have read-write access to the state variables, whereas on client-side you have to have read-only access to the state variables. In HUPnP this is abstracted to Herqq::Upnp::HWritableStateVariable and Herqq::Upnp::HReadableStateVariable classes. On device host side the dynamic type of every Herqq::Upnp::HStateVariable is `HWritableStateVariable` and on control point side the type is `HReadableStateVariable`.

See also:
  Device Hosting

## Typedef Documentation

typedef Functor<int, H_TYPELIST_2( const Herqq::Upnp::HActionArguments&, Herqq::Upnp::HActionArguments*) HActionInvoke)

This is a type definition for a callable entity that is used for HAction invocation.

You can create `HActionInvoke` objects using normal functions, functors and member functions that follow the signature of

``

`qint32 function(const Herqq::Upnp::HActionArguments& inArgs, Herqq::Upnp::HActionArguments* outArgs = 0);`

``

The following example demonstrates how you can instantiate the `HActionInvoke` for a normal function, functor and a member function.

     #include <HActionInvoke>
     #include <HUpnpCore/HActionArguments>
     #include <HUpnpCore/HActionArguments>

     #include "myclass.h" // your code that contains declaration for MyClass

     namespace
     {
     qint32 freefun(
          const Herqq::Upnp::HActionArguments& inArgs,
          Herqq::Upnp::HActionArguments* outArgs)
     {
         return 0;
     }

     class MyFunctor
     {
     public:
         qint32 operator()(
             const Herqq::Upnp::HActionArguments& inArgs,
             Herqq::Upnp::HActionArguments* outArgs)
         {
             return 0;
         }
     };
     }

     qint32 MyClass::memfun(
          const Herqq::Upnp::HActionArguments& inArgs,
          Herqq::Upnp::HActionArguments* outArgs = 0)
     {
     }

     void MyClass::example()
     {
         Herqq::Upnp::HActionInvoke usingFreeFunction(freefun);

         MyFunctor myfunc;
         Herqq::Upnp::HActionInvoke usingFunctor(myfunc);

         Herqq::Upnp::HActionInvoke usingMemberFunction(this, &MyClass::memfun);
     }

You can test if the object can be invoked simply by issuing `if (actionInvokeObject) { ... }`

typedef Functor<bool, H_TYPELIST_1(HAsyncOp)> HActionInvokeCallback

This is a type definition for a callable entity that is used as a callback for signaling the completion of an HAction invocation.

You can create `HActionInvokeCallback` objects using normal functions, functors and member functions that follow the signature of

``

`bool function(HAsyncOp);`

``

### Parameters

- The first parameter is a type of an "ID" of the asynchronous action invocation.
- The second parameter is the return value of the action invocation.
- The third parameter specifies the output arguments of the action invocation, which may be empty.

### Return value

The return value indicates if the invoked HAction should emit an HAction::invokeComplete() or HAction::invokeFailed() signal depending on the outcome of the invocation after the callback has returned.

- true indicates that the HAction should sent the corresponding event.

The following example demonstrates how you can instantiate the `HActionInvokeCallback` for a normal function, functor and a member function.

     #include <HUpnpCore/HAction>

     #include "myclass.h" // your code that contains declaration for MyClass

     namespace
     {
     bool freefun(HAsyncOp)
     {
         return true;
     }

     class MyFunctor
     {
     public:
         bool operator()(HAsyncOp)
         {
             return true;
         }
     };
     }

     bool MyClass::memfun(HAsyncOp)
     {
         return true;
     }

     void MyClass::example()
     {
         Herqq::Upnp::HActionInvokeCallback usingFreeFunction(freefun);

         MyFunctor myfunc;
         Herqq::Upnp::HActionInvokeCallback usingFunctor(myfunc);

         Herqq::Upnp::HActionInvokeCallback usingMemberFunction(this, &MyClass::memfun);
     }

You can test if the object can be invoked simply by issuing `if (actionInvokeCallbackObject) { ... }`

typedef QList<HService*> HServices

This is a type definition for a collection of pointers to Herqq::Upnp::HService instances.

See also:
  HService

typedef QList<HServiceProxy*> HServiceProxies

This is a type definition for a collection of pointers to Herqq::Upnp::HServiceProxy instances.

See also:
  HServiceProxy

typedef QList<HDevice*> HDevices

This is a type definition for a collection of pointers to Herqq::Upnp::HDevice instances.

See also:
  HDevice

typedef QList<HDeviceProxy*> HDeviceProxies

This is a type definition for a collection of pointers to Herqq::Upnp::HDeviceProxy instances.

See also:
  HDeviceProxy

typedef QList<HStateVariable*> HStateVariables

This is a type definition for a collection of pointers to Herqq::Upnp::HStateVariable instances.

See also:
  HStateVariable

typedef QList<HAction*> HActions

This is a type definition for a collection of pointers to Herqq::Upnp::HAction instances.

See also:
  HAction