9. Combining Things With Data

Key Concepts

 Related docs
DataModel 
Simple Reference 
Create data 

 

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 model facets. They are simply models to store application data that is essential to create a meaningful real-world IoT application.

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
<Def Name="PeripheralParams">
      <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"/>
    </Def>

    <ThingFacet Name="TempFacetSerial">
      <String Name="SensorData" update="auto" KnownBy="SensorDataReadAction"/>
      <PeripheralParams Name="PerifParams"/>
      <Action Name="SensorDataReadAction">
        <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.PerifParams.InterfacePort.Value:%]"
                  </InterfacePort>
                  <Baudrate>
                    "[%:Event.Argument.PerifParams.Baudrate.Value:%]"
                  </Baudrate>
                  <Interface>
                    "[%:Event.Argument.PerifParams.Interface.Value:%]"
                  </Interface>
                  <UniqueId>
                    "[%:Event.Argument.PerifParams.UniqueId.Value:%]"
                  </UniqueId>
                  <Operation>
                    "[%:Event.Argument.PerifParams.Operation.Value:%]"
                  </Operation>
                  <Peripheral>
                    "[%:Event.Argument.PerifParams.Peripheral.Value:%]"
                  </Peripheral>
                  <Payload>
                    "[%:Event.Argument.PerifParams.Payload.Value:%]"
                  </Payload>
                  <Format>
                    "[%:Event.Argument.PerifParams.Format.Value:%]"
                  </Format>
                </Value>
              </Message>
            </Invoke>
            <Output Name="Result" As="ActionResult">
              <Value>
                <SensorData>
                  [%:Invoke.InvokeSerialRead.Message.Value/normalize-space(received):%]
                </SensorData>
              </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>
  <DeleteAll format="version,current">
    <Grid>
      <GridID ne=""/>
    </Grid>
  </DeleteAll>
  <Create>
    <Grid>
      <GridName>
        Intel-Grid
      </GridName>
      <GridID>
        livegrid
      </GridID>
      <ZoneID>
        livezone
      </ZoneID>
      <GridLength>
        1
      </GridLength>
      <GridWidth>
        1
      </GridWidth>
      <GridNSPosition>
        1
      </GridNSPosition>
      <GridWEPosition>
       2
      </GridWEPosition>
      <GridLocation>
        <Vertex1>
          1
        </Vertex1>
        <Vertex2>
          1
        </Vertex2>
        <Vertex3>
          1
        </Vertex3>
        <Vertex4>
          1
        </Vertex4>
      </GridLocation>
      <SoilMoisture>
        53
      </SoilMoisture>
      <AmbientLight>
        0
      </AmbientLight>
    </Grid>
  </Create>
</Query>

Create Zone

Create Zone
<Query>
  <DeleteAll format="version,current">
    <Zone>
      <ZoneID ne = ""/>
    </Zone>
  </DeleteAll>
  <Create>
    <Zone>
      <ZoneID>
        livezone
      </ZoneID>
      <ZoneName>
        Intel-Zone
      </ZoneName>
      <LaneID>
        livelane
      </LaneID>
      <ZoneLength>
        1
      </ZoneLength>
      <ZoneWidth>
        1
      </ZoneWidth>
      <ZoneLocation>
        <Vertex1>
          1
        </Vertex1>
        <Vertex2>
          1
        </Vertex2>
        <Vertex3>
          1
        </Vertex3>
        <Vertex4>
          1
        </Vertex4>
      </ZoneLocation>
      <EndZone>
        endzone
      </EndZone>
      <GridOnLength>
        1
      </GridOnLength>
      <GridOnWidth>
        1
      </GridOnWidth>
      <GridCount>
        1
      </GridCount>
      <GridLength>
        1
      </GridLength>
      <GridWidth>
        1
      </GridWidth>
      <ZoneTemperature>
        26
      </ZoneTemperature>
      <ZoneHumidity>
        53
      </ZoneHumidity>
      <ZoneAvgSM>
        20
      </ZoneAvgSM>
      <ZoneAvgLight>
        2
      </ZoneAvgLight>
      <CropType>
        Apple
      </CropType>
      <SeedingDate>
        11-04-2016
      </SeedingDate>
      <LastFertilisationDate>
        14-04-2016
      </LastFertilisationDate>
      <HarvestingSeason>
        April
      </HarvestingSeason>
      <NoOfPlants>
        5
      </NoOfPlants>
      <VPD>
        0
      </VPD>
      <Location>
        <latitude>
          1.11
        </latitude>
        <longitude>
          1.12
        </longitude>
      </Location>
      <Live>
        yes
      </Live>
    </Zone>
  </Create>
</Query>

Create Lane

Create Lane
<Query>
  <DeleteAll format="version,current">
    <Lane>
      <LaneID ne = ""/>
    </Lane>
  </DeleteAll>
  <Create>
    <Lane>
      <LaneID>
        livelane
      </LaneID>
      <GreenhouseID>
        livegreenhouse
      </GreenhouseID>
      <LaneName>
        lane-1
      </LaneName>
      <LaneLength>
        5
      </LaneLength>
      <LaneWidth>
        1
      </LaneWidth>
      <ZoneInLane>
        4
      </ZoneInLane>
      <BorderLane>
        1
      </BorderLane>
      <BoundingBox>
        <Vertex1>
          5
        </Vertex1>
        <Vertex2>
          28
        </Vertex2>
        <Vertex3>
          105
        </Vertex3>
        <Vertex4>
          38
        </Vertex4>
      </BoundingBox>
    </Lane>
  </Create>
</Query>

Create Greenhouse

Create Greenhouse
<<Query>
  <DeleteAll format="version,current">
    <Greenhouse>
      <GreenhouseID ne=""/>
    </Greenhouse>
  </DeleteAll>
  <Create>
    <Greenhouse>
      <GreenhouseID>
        livegreenhouse
      </GreenhouseID>
      <GreenhouseName>
        Intel-GreenHouse
      </GreenhouseName>
      <BoundingBox>
        <Vertex1>
          0
        </Vertex1>
        <Vertex2>
          0
        </Vertex2>
        <Vertex3>
          110
        </Vertex3>
        <Vertex4>
          40
        </Vertex4>
      </BoundingBox>
      <LaneCount>
        3
      </LaneCount>
      <LaneWidth>
        110
      </LaneWidth>
      <ZoneLength>
        10
      </ZoneLength>
      <ZoneInLane>
        5
      </ZoneInLane>
      <ZoneCount>
        15
      </ZoneCount>
      <GHLength>
        110
      </GHLength>
      <GHWidth>
        40
      </GHWidth>
      <ExternalEnv>
        <Temperature>
          26
        </Temperature>
        <Humidity>
          53
        </Humidity>
        <Light>
          1
        </Light>
        <SoilMoisture>
          20
        </SoilMoisture>
        <Wind>
          19.5
        </Wind>
      </ExternalEnv>
      <InternalEnv>
        <Temperature>
          20
        </Temperature>
        <Humidity>
          53
        </Humidity>
        <Light>
          1
        </Light>
        <SoilMoisture>
          1
        </SoilMoisture>
      </InternalEnv>
      <GHLanes>
      </GHLanes>
      <SunnyDay>
        True
      </SunnyDay>
      <Location>
        <latitude>
          37.3718999
        </latitude>
        <longitude>
          -122.0022377
        </longitude>
      </Location>
    </Greenhouse>
  </Create>
</Query>

Initialize Temperature Sensor

TempSensorInZone value is the ZoneID value of the Zone.

Create Temperature Sensor
<Query>
  <DeleteAll format="version,current">
    <TempSensor>
      <sensorId ne=""/>
    </TempSensor>
  </DeleteAll>
  <Save format="version,current">
    <!-- This will read -->
    <TempSensor>
      <PerifParams>
        <Peripheral>
          serial
        </Peripheral>
        <Baudrate>
          9600
        </Baudrate>
        <InterfacePort>
          /dev/cu.usbserial-A1025R0Y
        </InterfacePort>
        <Interface>
          serial
        </Interface>
        <Format>
          ascii
        </Format>
        <Operation>
          receive
        </Operation>
        <UniqueId>
          76522
        </UniqueId>
        <Payload>
          $Null()
        </Payload>
      </PerifParams>
      <SensorData>
        $Null()
      </SensorData>
      <TempSensorInZone>
        livezone
      </TempSensorInZone>
    </TempSensor>
  </Save>
</Query>

Find Greenhouse

Find Greenhouse
<Query>
  <Find nested="*">
    <Greenhouse>
      <GreenhouseID ne=""/>
    </Greenhouse>
  </Find>
</Query>