Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 26 Next »

Background

In order to model a real-world IoT application or a solution it is imperative to combine things with data. Let's take an example of real-world use case.

Real-world use-case

For the purpose of this tutorial let's model the Greenhouse monitoring system with following configuration.

  • Greenhouse: size: 40 feet by 110 feet
  • crop types, tomatoes and peppers
  • 3 lanes, each lane has 10 zones
  • Total 30 zones (each zone is 10 feet by 10 feet. Lay out is 3 by 10): 20 zones (2 by 10) are tomatoes, 10 zones are peppers

Each zone subdivided into 9 grids. Each grid is 3.33 feet by 3.33 feet. Total 270 grids

 Zone Content: 

  • 1 temperature sensor (total 30)
  • 1 humidity sensor (total 30)
  • 1 camera (total 30)
  • 1 irrigation motor (total 30)

 Zone Grid Content:

  • 1 ambient light sensor (total 270)
  • 1 light (total 270)
  • 1 irrigation nozzle (total 270)

 External Conditions:

  • 1 ambient light sensor
  • 1 temperature sensor
  • 1 humidity sensor

Tutorial Requirement

For the purpose of this tutorial, let's create a Greenhouse, Lane, Zone, Grid and combine Temperature Sensor from tutorial 1 to a particular zone.

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.

 DataModel
Detected corrupted macro, please contact Atlassian Support for assistance.

Go to page

Custom Types

We create two custom types to store GeoLocation and BoundingBox.

  1. GeoLocation - To Store GeoLocation

    GeoLocation Type
    <Def Name="GeoLocation">
      <Number Name="latitude"/>
      <Number Name="longitude"/>
    </Def>	
  2. BoundingBox - To Store Geo Boundary of Zone, etc

    BoundingBox Type
    <Def Name="BoundingBox">
      <GeoLocation Name="Vertex1"/>
      <GeoLocation Name="Vertex2"/>
      <GeoLocation Name="Vertex3"/>
      <GeoLocation Name="Vertex4"/>
    </Def>
  3. EnvInfo - Capture all the important environment related information like temperature, humidity, light, pressuue

    EnvInfo Type
    <Def Name="EnvInfo">
          <Number Name="Temperature"/>
          <Number Name="Humidity"/>
          <Number Name="Light"/>
          <Number Name="Pressure"/>
          <Number Name="SoilMoisture"/>
          <Number Name="Wind"/>
          <String Name="LastUpdatedByProvider"/>
    </Def>

List of DataModels

  1. Greenhouse : Overall DataModel holder for Greenhouse. GHLanes is defined as Reference to include all the Lanes from Lane model.

    Greenhouse DataModel
    <DataModel Name="Greenhouse">
          <Sid Name="GreenhouseID"/>
          <String Name="GreenhouseName"/>
          <GeoLocation Name="Location"/>
          <String Name="LocationName"/>
          <BoundingBox Name="Boundary"/>
          <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"/>
          <Boolean Name="Running" default="false"/> <!-- true / false -->
          <Reference Name="GHLanes"/>
          <Reference Name="GHExternalEnv"/>
          <Reference Name="GHInternalEnv"/>
    </DataModel>
  2. GHExternalEnv & GHInternalEnv

    GHExternalEnv and GHInternalEnv Data Model
    <DataModel Name="ExternalEnv">
          <Sid Name="ExternalEnvID"/>
          <Number Name="ExtTemperature"/>
          <Number Name="ExtHumidity"/>
          <Number Name="ExtLight"/>
          <Reference Name="GreenhouseID" Type="Greenhouse" Cardinality="1"/>
        </DataModel>
    <DataModel Name="InternalEnv">
          <Sid Name="InternalEnvID"/>
          <Number Name="IntTemperature"/>
          <Number Name="IntHumidity"/>
          <Number Name="IntLight"/>
          <Reference Name="GreenhouseID" Type="Greenhouse" Cardinality="1"/>
    </DataModel>


  3. Grid - DataModel for storing Grid information.

    Grid DataModel
    <DataModel Name="Grid">
          <Sid Name="GridID"/>
          <String Name="GridName"/>
          <BoundingBox Name="GridLocation"/>
          <Integer Name="GridNSPosition"/>
          <Integer Name="GridWEPosition"/>
          <Double Name="GridLength"/>
          <Double Name="GridWidth"/>
          <Double Name="SoilMoisture"/>
          <Double Name="AmbientLight"/>
          <Reference Name="ZoneID" Type="Zone" Cardinality="1"/>
     </DataModel>
  4. 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.

    Zone DataModel
    <DataModel Name="Zone">
          <Sid Name="ZoneID"/>
          <String Name="ZoneName"/>
          <BoundingBox Name="ZoneLocation"/>
          <GeoLocation Name="Location"/>
          <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"/>
          <String Name="Live"/> <!-- Yes/No -->
          <Reference Name="LaneID" Type="Lane" Cardinality="1"/>
          <Reference Name="ZoneGrids"/>
    </DataModel>
  5. Lane - DataModel to hold Lane information. Defines Smart Reference to Zones.

    Lane DataModel
    <DataModel Name="Lane">
          <Sid Name="LaneID"/>
          <String Name="LaneName"/>
          <Double Name="LaneLength"/>
          <Double Name="LaneWidth"/>
          <Integer Name="ZoneInLane"/>
          <String Name="BorderLane"/>
          <BoundingBox Name="LaneLocation"/>
          <Reference Name="GreenhouseID" Type="Greenhouse" Cardinality="1"/>
          <Reference Name="LaneZones"/
    </DataModel>

Data + Things

We have to assign 1 temperature sensor per zone. We do this by:

  1. Use the content of MultipleSensors tutorial project and bring in all the model content into this tutorial.
  2. Use Simple Reference in TempSensorModel to a particular Zone using ZoneID
    Other sensors and actuators can be referenced in a similar fashion.
TempSensorModel with reference to Zone
<ThingFacet Name="TempFacetSerial">
            <String Name="TempValue" update="auto" KnownBy="SerialReadAction"/>    
            <String Name="Unit" default="Celsius"/>
            <String Name="Peripheral"/>
            <String Name="InterfacePort"/>
            <String Name="Interface"/>
            <String Name="UniqueId" default="56789"/>
            <String Name="Baudrate"/>
            <String Name="Format" default="ascii"/>
            <String Name="Operation"/>
            <String Name="Payload"/>
            <Action Name="SerialReadAction">
                <Workflow Limit="1" Live="1" Timeout="-1">
                    <Task name="Main" while="true">
                        <Event name="Argument" as="ActionArgument" />
                        <Invoke name="InvokeSerialRead" waitFor="Argument" get="perif://">
                            <Message>
                                <Value>
                                    <InterfacePort>"[%:Event.Argument.interfacePort.Value:%]"</InterfacePort>
                                    <Baudrate>"[%:Event.Argument.baudrate.Value:%]"</Baudrate>
                                    <Interface>"[%:Event.Argument.interface.Value:%]"</Interface>
                                    <UniqueId>"[%:Event.Argument.uniqueId.Value:%]"</UniqueId>
                                    <Operation>"[%:Event.Argument.operation.Value:%]"</Operation>
                                    <format>"[%:Event.Argument.format.Value:%]"</format>
                                    <Payload>"[%:Event.Argument.payload.Value:%]"</Payload>
                                    <Peripheral>"[%:Event.Argument.peripheral.Value:%]"</Peripheral>
                                </Value>
                            </Message>
                        </Invoke>
                        <Output name="Result" as="ActionResult">
                            <Value>
                                <tempValue>[%:Invoke.InvokeSerialRead.Message.Value/number(substring-before(substring-after
                                    ("[%:Invoke.InvokeSerialRead.Message.Value.received:%]",'#TCB:'), '#')):%]
                                </tempValue>
                            </Value>
                        </Output>
                    </Task>
                </Workflow>
            </Action>
</ThingFacet>
<ThingModel Name="TempSensor" combines="TempFacetSerial">
    <Sid Name="sensorId"/>
    <Reference Name="ZoneID" Type="Zone" Cardinality="1"/>
</ThingModel>

Queries

Let's start writing some queries to create and read the data. 

Create Grids

Create Grid
<Query>
  <Find>
    <Zone>
      <ZoneName eq="Zone1"/>
    </Zone>
  </Find>
  <Create>
    <Grid>
      <GridName>
        Grid1
      </GridName>
      <GridNSPosition>
        1
      </GridNSPosition>
      <GridWEPosition>
        1
      </GridWEPosition>
      <GridLength>
        3.33
      </GridLength>
      <GridWidth>
        3.33
      </GridWidth>
      <SoilMoisture>
        0
      </SoilMoisture>
      <AmbientLight>
        0
      </AmbientLight>
      <ZoneGrid>[:$Response.Message.Value.Find.Result.Zone.ZoneID:]</ZoneGrid>
    </Grid>
  </Create>
 
</Query>

Create Zone

Create Zone
<Query>
  <DeleteAll>
    <Zone>
      <ZoneID ne=""/>
    </Zone>
  </DeleteAll>
  <Create>
    <Zone>
      <ZoneWidth>
        10
      </ZoneWidth>
      <ZoneLength>
        10
      </ZoneLength>
      <GridOnLength>
        3
      </GridOnLength>
      <GridOnWidth>
        3
      </GridOnWidth>
      <GridCount>
        9
      </GridCount>
      <GridLength>
        3.33
      </GridLength>
      <GridWidth>
        3.33
      </GridWidth>
      <EndZone>
        No
      </EndZone>
      <ZoneTemperature>
        0
      </ZoneTemperature>
      <ZoneHumidity>
        0
      </ZoneHumidity>
      <CropType>Tomato</CropType>
    </Zone>
  </Create>
</Query>

Create Lane

Create Lane
<Query>
  <Create>
    <Lane>
      <LaneWidth>
        110
      </LaneWidth>
      <ZoneInLane>
        10
      </ZoneInLane>
      <BorderLane>
        Yes
      </BorderLane>
      <LaneZones>
      </LaneZones>
    </Lane>
  </Create>
</Query>

Create Greenhouse

Create Greenhouse
<Query>
  <Create>
    <Greenhouse>
      <LaneCount>
        3
      </LaneCount>
      <LaneWidth>
        110
      </LaneWidth>
      <ZoneLength>
        10
      </ZoneLength>
      <ZoneInLane>
        10
      </ZoneInLane>
      <ZoneCount>
        90
      </ZoneCount>
      <ExtEnvInfo>
        <Temperature>
          0
        </Temperature>
        <Humidity>
          0
        </Humidity>
        <Light>
          0
        </Light>
      </ExtEnvInfo>
      <GHLanes></GHLanes>
    </Greenhouse>
  </Create>
</Query>

Create Temperature Sensor

TempSensorInZone value is the ZoneID value of the Zone. This is dynamically assigned by querying the Zone Model.

Create Temperature Sensor
<Query>
  <DeleteAll>
    <TempSensorModel>
      <TempSensorId ne=""/>
    </TempSensorModel>
  </DeleteAll>
  <Find>
    <Zone>
      <ZoneName eq="Zone1"/>
    </Zone>
  </Find>
  <Create>
    <TempSensorModel>
      <TempValueInC>
        0
      </TempValueInC>
      <TempValueInF>
        0
      </TempValueInF>
      <TempSensorInZone>
        [:$Response.Message.Value.Find.Result.Zone.ZoneID:]
      </TempSensorInZone>
    </TempSensorModel>
  </Create>
</Query>

Find Temperature above x degree C

Find Temperature
<Query>
  <Find nested="*" format="Version">
    <TempSensorModel>
      <TempSensorId ne="" />
    </TempSensorModel>
  </Find>
</Query>
  • No labels