In the last installment of this basic oBIX guide, I
discussed reading and writing objects in oBIX. This
week I'm going to discuss objects in more detail and
oBIX Operations. Once we've understood this concept,
we can start using oBIX as an API and then dig into
Watches and some of the other advanced features.
Before we start invoking Operations, let's go back
to an oBIX document and discuss Contracts. As stated
last week, an oBIX object is an XML document that
can be identified by its own unique URL. However, we
need someway to identify 'types' of objects. For
instance, we need someway to distingish between a
NumericWritable from a SineWave object. This is
where Contracts come in. Let's look at the first
line of a NumericWritable...
<real val="1.0" href="http://localhost/obix/config/Folder/NumericWritable/"
is="/obix/def/control:NumericWritable /obix/def/control:NumericPoint obix:Point"...
The above 'is' attribute identifies the 'type' of
object. You can read the content of this attribute
from left to right and see all the Contracts
NumericWritable implements. Therefore, a
NumericWritable is also a NumericPoint and a generic
oBIX Point. For all you developers out there, you
can think of this as a flattened inheritance
hierarchy.
Now let's talk about Operations. In the last part
of the guide, I discussed using HTTP GET and PUT for
reading and writing oBIX data. To invoke an oBIX
Operation, we need to use an HTTP POST. To execute
an Action we simply...
- Identify the URL of the Action we want to
invoke.
- HTTP POST to this URL with the content being
the input argument for the Operation.
- This invokes the Action and returns any
result in the response.
That's it - easy eh? Ok let's try this out with
ORT again. As described in part 1, run ORT and a
test Station. In your Station, add a Program Object
to 'Folder'. Edit the Program Object and add the
following code...
public void onExecute()
{
System.out.println("Hello world!!!");
}
...now save the changes and open web browser. Log
in and surf to the 'execute' Action on the Program
Object. It should look something like...
http://localhost/obix/config/Folder/Program/execute/
Note how the 'execute' Action is listed as an
'op' XML element. Now paste this as the URL into
ORT, select POST from the drop down menu and hit the
'Send' button. Everytime you hit the 'Send' button,
you should see the 'Hello World!!!' message appear
in the Station output. Congratulations, you can now
externally execute a Program Object! And yes you've
just implemented a custom fully functioning web
service for a Station!
Let's go back at and have a look at the
definition for an oBIX Operation...
<op href="http://localhost/obix/config/Folder/NumericWritable/set/" in="obix:real" out="obix:Nil" />
You'll notice I'm now referring to another
Operation that now takes an argument. In this case,
the above Operation would invoke a 'set' Action on a
NumericWritable. The 'in' attribute refers to the
Contract of the input argument and the 'out'
attribute specifies the output (which in this case
is nothing). For the 'set' Action, you would POST...
<real val="12.2" />
[an error occurred while processing this directive]
Let's take a more complicated example for invoking
the 'override' Action on the same NumericWritable
component. Now let's view the 'op' for the override
Operation. By surfing to...
http://localhost/obix/config/Folder/NumericWritable/override/
...you should get back...
<op href="http://localhost/obix/config/Folder/NumericWritable/override/"
in="/obix/def/control:NumericOverride /obix/def/control:Override" displayName="Override"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://obix.org/ns/schema/1.0 /obix/xsd" xmlns="http://obix.org/ns/schema/1.0"/>
So we're interested in the 'in' attribute and we
can see it takes an 'NumericOverride' object. Well
that's very nice. But how do I find out about the
Contract? Well just cut and paste the relative URL
into your web browser and surf to it. For example,
by surfing too...
http://localhost/obix/def/control:NumericOverride
...you should get back...
<obj href="http://localhost/obix/def/control:NumericOverride/" is="/obix/def/control:Override" display="0.0 : permanent"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://obix.org/ns/schema/1.0 /obix/xsd"
xmlns="http://obix.org/ns/schema/1.0">
<reltime name="duration" val="PT0S" href="duration/" display="0ms" displayName="Duration" writable="true"/>
<real name="value" val="0.0" href="value/" displayName="Value" writable="true"/>
</obj>
Mmmm. There's quite a few attributes in there.
The good news is for invoking the 'override'
Operation, we don't need to include all the detail
as specified in the Contract. Basically, we just
need to specify the name and value. Therefore, you
would really POST...
<obj>
<reltime name="duration" val="PT0S" />
<real name="value" val="32.6" />
</obj>
Now believe it or not, you've just learnt a core
piece of oBIX and one that will allow you to do
virtually anything. Let me explain...
- By using oBIX Operations you can execute any
kind of Niagara Action. Therefore, if you
develop your own components with their own
Actions, they automatically get exposed as web
services! Wow - neat eh? It certainly takes the
pain out of creating external interfaces for
custom applications! Consequently you can
concentrate on your Niagara components and not
anything with angle brackets.
- An Operation can take one argument (note
this could be a structure and hence take as many
arguments as you want).
- An Operation can return a result (another
oBIX document).
- Interacting with Watches, Alarms and
Histories all rely on using oBIX Operations. Now
you know how to invoke an Operation, you can
scout ahead to these oBIX objects, look at their
Operations and start invoking them. Eh presto -
you're now just using another API.
Phew - well if you didn't quite catch the last
bit then don't worry. In the next part, we're going
to be looking at using the Watch Service
(although if you've just understood everything I've
just discussed you should be able to get there
without me).
One last thing - thanks for all the positive
comments I've had about my blog!