ThingModel is one kind of models (the other kinds are DataModels and AppModels). Therefore it has all the properties of Models (Lifecycle of models, Model Attributes, Unique and Constraints).
A ThingModel has
- a Name,
- any number of Model Attributes
- and usually one or more Actions
However, as a recommended practice, the Attributes and Actions related to the interactions with an external thing (sensors, actuators, machines) are often defined in a reusable structure called ThingFacet, and combined into a ThingModel. This relationship was explained in the concept of Models and Model Facets. Application related information are often defined directly as attributes of the ThingModel.
In the following example, the ThingModel PhidgetServoModel combines the ThingFacet PhidgetServoFacet, where:
- PhidgetServoFacet contains the device interaction specific Attributes (e.g. ServoProtocolURL) and Actions (e.g. PhidgetServoAction);
- PhidgetServoModel contains application related Attributes: PhidServoId and InstalledAtZone (assuming the Phidget servo motor is installed in a particular zone within a Greenhouse environment, which has multiple zones).
- Combines is a modifier of ThingModel
In the most simple case, a ThingModel may only have one single directly defined attribute of type Sid.
<ThingModel Name="PhidgetServoModel" Combines="PhidgetServoFacet"> <Sid Name="PhidServoId"/> <String Name="InstalledAtZone"/> </ThingModel> <ThingFacet Name="PhidgetServoFacet"> <String Name="ServoProtocolURL" Default="phid://" /> <String Name="DeviceInterfaceIndex" /> <String Name="PhidgetDeviceType" /> <Integer Name="ServoAngle" KnownBy="PhidgetServoAction" /> <Action Name="PhidgetServoAction" Documentation="Control servo motor"> ... </Action> </ThingFacet>
This pattern allows the ThingFacet to become a reusable artifact, and potentially combined by multiple ThingModels.
Purpose of ThingModels:
- ThingModels are normally defined by users when interacting with Physical Things. The behavior of Physical Things are modeled via ThingFacet.
- ThingModels are driver for ThingFacets. ThingFacet (s) are reusable models and TQL CRUD operations can not be performed on ThingFacet. ThingFacet(s) are put to use only when combined within a ThingModel.
- ThingModels can contain application related information that are related to things.
ThingsFacets are used within ThingModels using Combines modifier. Example of a PhidgetServoModel ThingModel combining a PhidgetServoFacet ThingFacet
<ThingModel Name="PhidgetServoModel" Combines="PhidgetServoFacet"> <Sid Name="PhidServoId"/> </ThingModel>
Note: One can combine multiple ThingFacets within a single ThingModel using comma separated list of ThingFacets.
For Example Esky ThingModel combining EskyPreset and EskyImage Thing Facets
<ThingFacet name="EskyPreset"> <String name="State" KnownBy="SyncPreset"/> <String name="Preset" KnownBy="SyncPreset"/> <Action name="SyncPreset" documentation="Synchronize camera state and preset"> <Workflow Limit="1" Live="1" Timeout="PT20S"> <Task name="Main" while="true"> <Event name="Argument" as="ActionArgument"/> ... </Task> </Workflow> </Action> </ThingFacet> <ThingFacet name="EskyImage" combines="Login"> <String name="State" KnownBy="SyncImage"/> <Clob name="Image" KnownBy="SyncImage"/> <!-- Actions --> <Action name="SyncImage" documentation="Synchronize camera state and snapshot image"> <Workflow Limit="1" Live="1" Timeout="PT10S"> <Task name="Main" while="true"> <Event name="Argument" as="ActionArgument"/> ... </Task> </Workflow> </Action> </ThingFacet> <ThingModel name="Esky" combines="EskyPreset,EskyImage" documentation="actual single instance camera model"> <Sid name="CameraId"/> </ThingModel>
Adding application related information to a ThingModel. For Example, assume that the Phidget Servo Motor is part of a Zone within a Greenhouse environment. Greenhouse contains multiple zones.
<ThingModel Name="PhidgetServoModel" Combines="PhidgetServoFacet"> <Sid Name="PhidServoId"/> <String Name="InstalledAtZone"/> </ThingModel>
Examples of CRUD Operation on a ThingModel:
CREATE:
<Create> <PhidgetServoModel> <ServoProtocolURL> phid:// </ServoProtocolURL> <PhidgetDeviceType> PhidgetAdvancedServo </PhidgetDeviceType> <DeviceInterfaceIndex> 0 </DeviceInterfaceIndex> <ServoAngle> 110 </ServoAngle> </PhidgetServoModel> </Create>
CREATE RESULT:
<Create Status="Success"> <PhidgetServoModel> <PhidServoId>KNJN2YRVAAAAUAABA7LIQ4Y6</PhidServoId> <ServoProtocolURL Status="Success+Created:1:1457384153653;" Value="phid://"/> <DeviceInterfaceIndex Status="Success+Created:1:1457384153653;" Value="0"/> <PhidgetDeviceType Status="Success+Created:1:1457384153653;" Value="PhidgetAdvancedServo"/> <ServoAngle Status="Success+Created:1:1457384153654;" Value="110"/> </PhidgetServoModel> </Create>
Note: If a ThingModel is combined with a ThingFacet, creation of a ThingModel results in instantiating (Trigger) of a ThingFacet action.
UPDATE:
<Query> <Find format="version"> <PhidgetServoModel as="var.PS"> <PhidServoId ne=""/> </PhidgetServoModel> </Find> <SetResponseData> <key> Message.Value.Find.Result.PhidgetServoModel.ServoAngle.Value </key> <value> 120 </value> </SetResponseData> <Update> <from> Result </from> <Include> $Response.Message.Value.Find </Include> </Update> </Query>
UPDATE Result:
<Find Status="Success" Format="version"> <Result> <PhidgetServoModel> <PhidServoId>KNJPIFR6AAAAUAABA67ZRBQO</PhidServoId> <PhidgetDeviceType Value="PhidgetAdvancedServo" Version="1"/> <ServoAngle Version="1" Value="120"/> <DeviceInterfaceIndex Value="0" Version="1"/> <ServoProtocolURL Value="phid://" Version="1"/> </PhidgetServoModel> </Result> </Find> <Update Status="Success" Format="version"> <PhidgetServoModel> <PhidServoId>KNJPIFR6AAAAUAABA67ZRBQO</PhidServoId> <ServoProtocolURL Status="Success_NoAction:1:1457385641534;" Value="phid://" Version="1"/> <DeviceInterfaceIndex Status="Success_NoAction:1:1457385641534;" Value="0" Version="1"/> <PhidgetDeviceType Status="Success_NoAction:1:1457385641535;" Value="PhidgetAdvancedServo" Version="1"/> <ServoAngle Status="Success=Updated:2:1457385767153;" Value="120" Version="2"/> </PhidgetServoModel> </Update>
Note: If a ThingModel is combined with a ThingFacet updating a ThingModel attribute results in Trigger of a Action if that attribute is associated with an action.
DELETE:
<<Query> <DeleteAll> <PhidgetServoModel> <PhidServoId ne=""/> </PhidgetServoModel> </DeleteAll> </Query>
DELETE Result
<DeleteAll Status="Success"> <Result> <PhidgetServoModel> <PhidServoId>KNJOOOBZAAAAUAABA72MMI6E</PhidServoId> <PhidgetDeviceType>PhidgetAdvancedServo</PhidgetDeviceType> <ServoAngle>110</ServoAngle> <DeviceInterfaceIndex>0</DeviceInterfaceIndex> <ServoProtocolURL>phid://</ServoProtocolURL> </PhidgetServoModel> </Result> </DeleteAll>
Note: If a ThingModel is combined with a ThingFacet, creation of a ThingModel results in deleting an instance results in cleanup of connections with actual things as per the protocol Handler used.
FIND
<Query> <Find format="all"> <PhidgetServoModel> <PhidServoId ne="" /> </PhidgetServoModel> </Find> </Query>
Find result: Format="all" - returns all the internal attribute data as well.
<Find Status="Success" Format="all"> <Result> <PhidgetServoModel QName="Atomiton.PhidgetServos.PhidgetServoModel"> <PhidServoId>KNJOOOBZAAAAUAABA72MMI6E</PhidServoId> <PhidgetDeviceType Value="PhidgetAdvancedServo" Known="PhidgetAdvancedServo" Version="1" Timestamp="1457384798266" DateTime="2016-03-07 13:06:38.266" QName="Atomiton.PhidgetServos.PhidgetServoModel.PhidgetDeviceType" FName="PhidgetDeviceType"/> <ServoAngle Value="110" Known="110" Version="1" Timestamp="1457384798266" DateTime="2016-03-07 13:06:38.266" QName="Atomiton.PhidgetServos.PhidgetServoModel.ServoAngle" FName="ServoAngle"/> <DeviceInterfaceIndex Value="0" Known="0" Version="1" Timestamp="1457384798266" DateTime="2016-03-07 13:06:38.266" QName="Atomiton.PhidgetServos.PhidgetServoModel.DeviceInterfaceIndex" FName="DeviceInterfaceIndex"/> <ServoProtocolURL Value="phid://" Known="phid://" Version="1" Timestamp="1457384798265" DateTime="2016-03-07 13:06:38.265" QName="Atomiton.PhidgetServos.PhidgetServoModel.ServoProtocolURL" FName="ServoProtocolURL"/> </PhidgetServoModel> </Result> </Find>
Note:
- When ThingModels are do not combine ThingFacet it is equivalent of a DataModel i.e pure Data only.
- Although not required, it is best practice to always create a ThingModel with one attribute that is of type SystemId or Sid.