Key Concepts
Tip | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||||||||||||
| ||||||||||||||||||||
Tip | ||||||||||||||||||||
| ||||||||||||||||||||
|
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.
title | DataModel |
---|
invalidmacro |
---|
Custom Types
We create two custom types to store GeoLocation and BoundingBox.
GeoLocation - To Store GeoLocation
Code Block language xml title GeoLocation Type linenumbers true <Def Name="GeoLocation"> <Number Name="latitude"/> <Number Name="longitude"/> </Def>
BoundingBox - To Store Geo Boundary of Zone, etc
Code Block language xml title BoundingBox Type linenumbers true <Def Name="BoundingBox"> <GeoLocation Name="Vertex1"/> <GeoLocation Name="Vertex2"/> <GeoLocation Name="Vertex3"/> <GeoLocation Name="Vertex4"/> </Def>
EnvInfo - Capture all the important environment related information like temperature, humidity, light, pressuue
Code Block language xml title EnvInfo Type linenumbers true <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
Greenhouse : Overall DataModel holder for Greenhouse. GHLanes is defined as Reference to include all the Lanes from Lane model.
Code Block language xml title Greenhouse DataModel linenumbers true <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>
GHExternalEnv & GHInternalEnv
Code Block language xml title GHExternalEnv and GHInternalEnv Data Model linenumbers true <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>
Grid - DataModel for storing Grid information.
Code Block language xml title Grid DataModel linenumbers true <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>
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 language xml title Zone DataModel linenumbers true <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>
Lane - DataModel to hold Lane information. Defines Smart Reference to Zones.
Code Block language xml title Lane DataModel linenumbers true <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:
- 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 | ||||||
---|---|---|---|---|---|---|
| ||||||
<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
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<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
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<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
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<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
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<<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.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<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
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<Query> <Find nested="*"> <Greenhouse> <GreenhouseID ne=""/> </Greenhouse> </Find> </Query> |