...
At the time of writing this tutorial Atomiton TQLEngine does not provide specific language constructs to implement simulation. But the existing Atomic domain languages capabilities can be exploited to achieve simple to complex simulation. The simulation design patterns can be classified as follows:
Pattern # | Name | Description | Use Cases | Implementation Flow |
---|---|---|---|---|
1 | @ThingFacet Level | Seamless integration within the attribute's associate action |
|
|
2 | @ThingFacet Level | Separate Action to start the simulation |
|
|
3 | @Protocol Handler Level | Push the simulation logic down into protocol handler level |
|
|
4 | @Behavior Tree | Simulation logic is driven primarily by Behavior Trees. |
|
|
Create DataModel to store non-thing related data
TQLEngine provides DataModel to store "pure" data, DataModels do not combine facets. They are simply models to store application data that is essential to create a meaningful real-world IoT application.
Expand | ||
---|---|---|
| ||
Custom Types
We create two custom types to store GeoLocation and BoundingBox.
...
GeoLocation - To Store GeoLocation
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<Def Name="GeoLocation">
<Number Name="latitude"/>
<Number Name="longitude"/>
</Def> |
...
BoundingBox - To Store Geo Boundary of Zone, etc
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<Def Name="BoundingBox">
<GeoLocation Name="Vertex1"/>
<GeoLocation Name="Vertex2"/>
<GeoLocation Name="Vertex3"/>
<GeoLocation Name="Vertex4"/>
</Def> |
...
Simulating Temperature Sensor
Simulation Logic
- GHCurrentTemp is the general temperature inside the greenhouse
- It is affected by CurrentTemp (external), the vent and fans, and all the heaters
- The heaters are controlled by the application
- The vent and fans controls are not exposed to the application. So vent and fan behavior are simulated by BT, described in the next section.
- GHCurrentTemp is the default value for ZoneTemp if the heater is not on in that zone (if the heater is on in that zone, ZoneTemp will be higher than GHCurrentTemp)
- Value updates every 5 (?) minutes
GHTempAdj On Sunnyday: formula to calculate GHTempAdj in Celcius: GHTempAdj = (100/(CurrentTemp+237.1))3 * 100
For example, when (external) CurrenTemp = -5 Celcius, GHTempAdj = 5.186; when CurrentTemp = 28 Celcius, GHTempAdj = 3.661
On NOT Sunnyday: formula to calculate GHTempAdj in Celcius: GHTempAdj = (100/(CurrentTemp+237.1))3 * 60
For example, when (external) CurrenTemp = -5 Celcius, GHTempAdj = 3.111; when CurrentTemp = 28 Celcius, GHTempAdj = 2.197- Since temperature has an effect on humidity, always determine temperature value before determining humidity value
Add Greenhouse and Heater Model
Code Block | |||
---|---|---|---|
|
...
| |||
<Def Name=" |
...
GeoLocation"> <Number Name=" |
...
latitude"/> <Number Name=" |
...
longitude"/> |
...
</Def> |
List of DataModels
...
Greenhouse : Overall DataModel holder for Greenhouse. GHLanes is defined of type reference. There are two types of references - simple reference and smart reference. Smartness can be defined by providing a "Find" Query at the time of model definition or at the time of instantiating the model. GHLanes is defined as Reference to include all the Lanes from Lane model.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<DataModel Name="Greenhouse">
<Sid Name="GreenhouseID"/>
<BoundingBox Name="GreenhouseLocation"/>
<Integer Name="LaneCount"/>
<Double Name="LaneWidth"/>
<Double Name="ZoneLength"/>
<Integer Name="ZoneInLane"/>
<Integer Name="ZoneCount"/>
<Double Name="GHLength"/>
<Double Name="GHWidth"/>
<EnvInfo Name="ExternalEnv"/>
<EnvInfo Name="InternalEnv"/>
<String Name="VentOnOffState"/>
<String Name="FansOnOffState"/>
<Boolean Name="SunnyDay"/>
<Reference Name="GHLanes">
<Find>
<Lane>
<LaneID ne=""/>
</Lane>
</Find>
</Reference>
</DataModel> |
...
Pipeline Macros
- Execute Internal Query
- Schedule and UnSchedule TQL Code
Code Block | |||
---|---|---|---|
|
...
|
...
<Def Name=" |
...
GeoLocation"> |
...
<Number Name=" |
...
latitude"/> |
...
<Number Name=" |
...
longitude"/> |
...
|
...
Zone - DataModel for storing Zone information. Does a Smart Reference to Grid at instantiation time by simply defining ZoneGrids as Reference type. The Find query can be add at the instantiation time.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<DataModel Name="Zone">
<Sid Name="ZoneID"/>
<String Name="LaneID"/>
<String Name="ZoneName"/>
<BoundingBox Name="ZoneLocation"/>
<Double Name="ZoneWidth"/>
<Double Name="ZoneLength"/>
<Integer Name="GridOnLength"/>
<Integer Name="GridOnWidth"/>
<Integer Name="GridCount"/>
<Double Name="GridLength"/>
<Double Name="GridWidth"/>
<String Name="EndZone"/>
<Double Name="ZoneTemperature"/>
<Double Name="ZoneHumidity"/>
<Double Name="ZoneAvgSM"/>
<Double Name="ZoneAvgLight"/>
<String Name="CropType"/>
<Date Name="SeedingDate" format="$SimpleDateFormat(dd-MM-yyyy)"/>
<Date Name="LastFertilisationDate" format="$SimpleDateFormat(dd-MM-yyyy)"/>
<String Name="HarvestingSeason"/>
<Integer Name="NoOfPlants"/>
<Double Name="VPD"/>
<Reference Name="LaneZone" Type="Lane" Cardinality="1"/>
<Reference Name="ZoneGrids">
<Find>
<Grid>
<GridID ne=""/>
</Grid>
</Find>
</Reference>
</DataModel> |
...
</Def> |
Macro to Simulate Sensor
Code Block | |||
---|---|---|---|
|
...
|
...
<Def Name=" |
...
GeoLocation"> |
...
<Number |
...
Name=" |
...
latitude"/> |
...
<Number Name=" |
...
Data + Things
We have to assign 1 temperature sensor per zone. We do this by:
- Use the content of MultipleSensors tutorial project and bring in all the model content into this tutorial.
- Use Simple Reference in TempSensorModel to a particular Zone using ZoneID
Other sensors and actuators can be referenced in a similar fashion.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<ThingModel Name="TempSensorModel" Combines="TempSensorFacet"> <Sid Name="TempSensorId"/> <Reference Name="TempSensorInZone" Type="Zone" Cardinality="1"/> </ThingModel>longitude"/> </Def> |
Queries
Let's start writing some queries to create and read the data.
...