.. BACowl Primitive Data Types

Primitive Data Types
====================

The standard defines *primitive data types* to describe most of the components 
of objects and protocol data units.

Null
----

This is a special class that holds a unique value to signify special values 
in objects and special values for APDU's::

    :Null
        rdf:type owl:Class ;
        owl:equivalentClass
              [ rdf:type owl:Class ;
                owl:oneOf (null:null)
              ] .

This class has only one named individual::

    null:null
        rdf:type :Null , owl:NamedIndividual .

Boolean
-------

Boolean values are pretty straight forward::

    :Boolean
        rdf:type rdfs:Datatype ;
        owl:equivalentClass xsd:boolean .

Unsigned
--------

Most of the unsigned values used in the standard have no specific value limit
so the ontology specifies them as long::

    :Unsigned
        rdf:type rdfs:Datatype ;
        owl:equivalentClass xsd:unsignedLong .

Integer
-------

Integers are very similar to unsigned values::

    :Integer
        rdf:type rdfs:Datatype ;
        owl:equivalentClass xsd:long .

Real
----

This datatype is identical to the IEEE single precision floating point::

    :Real
        rdf:type rdfs:Datatype ;
        owl:equivalentClass xsd:float .

Double
------

This datatype is identical to the IEEE double precision floating point::

    :Double
        rdf:type rdfs:Datatype ;
        owl:equivalentClass xsd:double .

OctetString
-----------

Octet strings are used to transfer blobs of information that is not otherwise
specified as structured content::

    :OctetString
        rdf:type rdfs:Datatype ;
        owl:equivalentClass xsd:base64Binary .

CharacterString
---------------

Character strings are
This is a long line of text::

    :CharacterString
        rdf:type rdfs:Datatype ;
        owl:equivalentClass xsd:string .

*Character strings have an "encoding" when it appears in an APDU, and some 
devices have restrictions on what encoding formats they support.*

BitString
---------

Here is an ASN.1 example of a bit string::

    BACnetEventTransitionBits ::= BIT STRING {
        to-offnormal  (0),
        to-fault      (1),
        to-normal     (2)
        }

Bit strings are packed arrays of named bits, this ontology uses rdf:Bag to 
note the bit definitions can be unordered::

    :BitString
        rdf:type owl:Class ;
        rdfs:subClassOf rdf:Bag .

The bag contains bits, each of which has a specific nominal value::

    :Bit rdf:type owl:Class .

    bit:nominal
        rdf:type owl:DatatypeProperty , owl:FunctionalProperty ;
        rdfs:domain :Bit ;
        rdfs:range xsd:nonNegativeInteger .

*How can the ontology restrict the "bag" contents to only contain named individual 
bits that are a subclass of BitString?*

Enumeration
-----------

This is the ANS.1 definition of an enumeration::

    BACnetFileAccessMethod ::= ENUMERATED {
        record-access     (0),
        stream-access     (1)
        }

The Enumeration class is a way to group all labeled values together.  There are
two types of enumerations, those defined in the standard and those that can be
defined by vendors with their own names and values::

    :Enumeration
        rdf:type owl:Class ;
        owl:disjointUnionOf (:ProprietaryEnumeration :StandardEnumeration) .

Some enumerations (see below) can have additional values added to them by vendors
which are called extended enumerations::

    :ExtendedEnumeration
        rdf:type owl:Class ;
        rdfs:subClassOf :StandardEnumeration .

Every enumerated value is a named individual object that has a nominal value::

    enum:nominal
        rdf:type owl:DatatypeProperty , owl:FunctionalProperty ;
        rdfs:domain :Enumerated ;
        rdfs:range xsd:nonNegativeInteger .

Enumerations that are defined by a vendor have a relationship to the Vendor
object, and this applies to both extended enumerations and proprietary 
enumerations::

    enum:vendor
        rdf:type owl:FunctionalProperty , owl:ObjectProperty ;
        rdfs:domain
              [ rdf:type owl:Class ;
                owl:unionOf (:ExtendedEnumeration :ProprietaryEnumeration)
              ] ;
        rdfs:range :Vendor .

PropertyIdentifier
~~~~~~~~~~~~~~~~~~

This is an example of an extended enumeration definition.

Property identifiers are used to describe *properties* or components of objects.
Vendors can extend objects by adding their own properties which are distinguished 
from those in the standard by using values above those reserved to ASHRAE.

The standard defines some property identifiers::

    :PropertyIdentifier
        rdf:type owl:Class ;
        rdfs:subClassOf :StandardEnumeration ;
        owl:equivalentClass
            [ rdf:type owl:Class ;
              owl:oneOf (pi:ackedTransitions pi:ackRequired pi:action ... )
            ] .

Because the *PropertyIdentifier* class is restricted to the named individuals,
there is a subclass for those that the vendor wants to define.  This is a subclass
so that every place where a *PropertyIdentifier* is required, an *ExtendedPropertyIdentifier*
can be used.  The upper bound is the maximum value the enumeration can have so
vendors know an appropriate integer size (short, long, etc.) in their
implementation::

    :ExtendedPropertyIdentifier
        rdf:type owl:Class ;
        rdfs:subClassOf :PropertyIdentifier , :ExtendedEnumeration ;
        rdfs:subClassOf
            [ rdf:type owl:Restriction ;
              owl:onProperty enum:nominal ;
              owl:someValuesFrom
                  [ rdf:type rdfs:Datatype ;
                    owl:onDatatype xsd:nonNegativeInteger ;
                    owl:withRestrictions
                        ( [ xsd:minInclusive 512 ]
                          [ xsd:maxInclusive 4194303 ]
                        )
                  ]
            ] .

The property identifiers that are defined in the standard are defined in the 
ontology as named individuals::

    pi:ackedTransitions
        rdf:type :PropertyIdentifier , owl:NamedIndividual ;
        enum:nominal 0 .
    pi:ackRequired
        rdf:type :PropertyIdentifier , owl:NamedIndividual ;
        enum:nominal 1 .
    pi:action
        rdf:type :PropertyIdentifier , owl:NamedIndividual ;
        enum:nominal 2 .

*I have a suspicion that I can't restrict the standard enumerations to some named 
individuals and yet open up a subclass to vendor values.*

Date
----

The date value in the standard has four parts; year, month, day and day-of-week.
Each of these values are unsigned octets that can have the value 255 meaning
"wild card" value.  The ontology defines this as a patterned string of four 
components similar to other date formats, but cannot use standard date formats
because of the wild card value::

    :Date
        rdf:type rdfs:Datatype ;
        owl:equivalentClass
              [ rdf:type rdfs:Datatype ;
                owl:onDatatype xsd:string ;
                owl:withRestrictions
                        ([ xsd:pattern "([0-9]{4}|[*])-([0-9]{2}|[*])-([0-9]{2}|[*])-([0-9]{2}|[*])"
                          ])
              ] .

Time
----

The time value is very similar to the date format with four parts; hours, minutes,
seconds, and hundredths.  It can also contian wild card values::

    :Time
        rdf:type rdfs:Datatype ;
        owl:equivalentClass
              [ rdf:type rdfs:Datatype ;
                owl:onDatatype xsd:string ;
                owl:withRestrictions
                        ([ xsd:pattern "([0-9]{2}|[*]):([0-9]{2}|[*]):([0-9]{2}|[*])[.]([0-9]{2}|[*])"
                          ])
              ] .

ObjectIdentifier
----------------

Every object in the standard has a unique object identifier, a 32-bit packed 
value which contains a 10-bit object type and 22-bit instances number::

    :ObjectIdentifier
        rdf:type owl:Class .

Rather than specifying the object type as an unsigned integer, the ontology 
defines it as a relationship to a named individual of type ObjectIdentifier,
which is itself an enumerated value::

    oid:type
        rdf:type owl:FunctionalProperty , owl:ObjectProperty ;
        rdfs:domain :ObjectIdentifier ;
        rdfs:range :ObjectType .

The instance number is just a non-negative integer with a limited range::

    oid:instance
        rdf:type owl:DatatypeProperty , owl:FunctionalProperty ;
        rdfs:domain :ObjectIdentifier ;
        rdfs:range
              [ rdf:type rdfs:Datatype ;
                owl:onDatatype xsd:nonNegativeInteger ;
                owl:withRestrictions
                        ([ xsd:minInclusive 0
                          ] [ xsd:maxInclusive 4194302
                          ])
              ] .

ObjectName
~~~~~~~~~~

Most of the character strings in the standard can be empty, but object names
must have at least one character::

    :ObjectName
        rdf:type rdfs:Datatype ;
        owl:equivalentClass
              [ rdf:type rdfs:Datatype ;
                owl:onDatatype xsd:string ;
                owl:withRestrictions
                        ([ xsd:minLength 1
                          ])
              ] .

*Assuming there is a Device class, and that devices contain objects, how can
the ontology specify that the object name for each object must be unique 
within the device?*