IOT Garden Project- Digital Twins

Azure Digital Twins IOT Garden Project -Part 4

 


This is part 4  of my IOT garden project if you want to go to the first blog click here

Azure Digital Twins is a platform as a service (PaaS) offering from Microsoft. It enables  the digital modelling of real-life environments. The models will contain key properties and real time events from which you can create knowledge queries against the environment. The environments can be complex cities, buildings, factories, and farms or  as simple as my private vegetable garden. I use a digital model of my garden to gain insights for temperature, moisture, water usage, soil and crop management.

Azure Digital twins and IOT Hub are excellent cloud services to build a comprehensive and scalable solution to digitise and manage an environment. Through creating a digital model of one single  raised garden bed I can create many new digital copies of my raised bed in any environment and scale the number of digital twins to commercial farm size.

IOT devices bring my garden to life. The Arduino MKR NB 1500 microcontroller connected through Telstra’s IOT CAT network supports my garden environment. Environmental sensor readings like temperature and moisture readings are sent to my digital twin in Azure.

Azure has an event system to build dynamic business logic and data processing. Azure IOT HUB will send the real-life property or telemetric environmental readings to update the digital twin attributes and trigger actions based on environment requirements. That is in my case is to send a message back to the Arduino microcontroller to turn the sprinkler on if the soil is too dry.

I can integrate with Azure data, analytics, and AI services to help track the moisture history and then call weather forecasting to predict future rain and make a judgement to turn on the sprinkler system or wait for rain. In Azure Digital Twins, I define the digital
entities that represent the people, places, and things in my physical environment using custom twin types called models.

The digital twin model for the garden bed is a set of definitions as a specialised property to describe the garden plot. for example, it defines models for the whole farm such as the "PLOTS, coverage area, trellises systems and plants". I then create digital twins based on these models to represent my specific environment. The farm can have multiple plots and multiple types of plants assigned to the plot and this is defined in a JSON-like language called Digital Twins Definition Language (DTDL). It describes the digital twins in terms of their state properties, telemetry events, commands, components, and relationships, an example is shown below.

The models define semantic relationships between my entities so that i can connect my twins into a knowledge graph that reflects their interactions. For example, a farm contains multiple plots of ground. Each plot contains environmental sensors to monitor and watering systems to activate. Each plot also contains multiple vegetables sown at different times and at different stage of its growth cycle.

DTDL is used for data models throughout other Azure IoT services, including IoT Plug and Play (PnP) and Time Series Insights (TSI). This helps you keep your Azure Digital Twins solution connected and compatible with other parts of the Azure ecosystem.

Live execution environment 

My Azure Digital Twins garden is a live, up-to-date representation of the real world. Using the relationships in my custom garden digital twin I can connect to the twins’ live graph representing my garden environment. I can see a visualization of my Azure Digital

Twins graph through the help of a sample application called Azure Digital Twins explorer.  In the image below I have created base models which I can now use to build my complete digital twin environment Here's a view of what the sample visualization looks like:

 

base 

 

 

To see the visual DTDL of plot -A we click Plot-A on the graph, and we see its definition.  If I click on Plot-A it will return the digital twin attributes for Plot A. Here you can see a compilation of many environmental sensors from temperature to moisture levels.

 

 

 

 

plot

 

 

Notice the relationships between the digital twin models. The Farm model has many plots and each plot has many sensors. In the diagram below if I high-light the thermostat sensor it will give its temperature attribute. As PLOT-A is this thermostat parent we need to update the parent’s temperature value. This is done when the IOT event grid detects a temperature change on the sensor. The event grid then triggers an Azure Function whose role is to find the parent of the sensor and then updates the parent’s value. 

 


You can also extract insights from the live execution environment, using Azure Digital Twins' powerful query API. The API lets you query with rich search conditions, including property values,  relationships, relationship properties, model information, and more. You
can also combine queries, gathering a broad range of insights about your environment and answering  custom questions that are important to me. In the example below I ran a search to find all plots with a dry moisture content below 10.

 


Input from IoT and business systems

 

To keep the live execution environment of Azure Digital Twins up to date with the real world, I use Azure IoT Hub to connect my solution to IoT devices. The MKR NB1500 IOT device provides the environmental data that drives this model. You can also drive Azure
Digital Twins from other data sources, using REST APIs or connectors to other services like Logic Apps. For example, I can call on weather forecasts to get up to date rain expectations. AZURE Digital Twins provides a rich event system to keep that graph current with
data processing and business logic. I can connect external compute resources, such as Azure Functions, to drive this data processing in flexible, customized ways. In my garden example I run a value-based moisture content trigger, If the soil is too dry it will trigger an Azure Function that will send a turn on sprinkler command to the microcontroller. This is an image of the message and data flow.

flow

 

Output to TSI, storage, and analytics

The data in my Azure Digital Twins model is routed to downstream Azure services for additional analytics or storage. This is provided through event routes, which use Event Hub, Event Grid, or Service Bus to drive your desired data flows. For example, connecting my Azure Digital Twin to Time Series Insights to track time series history temperature, moisture levels, water usage is recorded over time. Some other things I can do with event routes include Integrating with larger workflows with Logic Apps. One of the digital twin properties of the garden is it records what vegetables I have planted and at what dates. Eventually I will develop logical applications to trigger alerts and reminders for harvesting crops.

 

Next Instalment Azure MAPS and the IOT Garden

In my next IOT blog I will describe how I have developed my Azure Digital Twin of my garden to trigger a function that will update the moisture status of my garden plot on the AZURE maps service. Below you can see how the color of the plot represents the moisture level . 

 

 

 


 

 

This is what my first integration of the Garden Digital twin looks like.   




Garden Digital Twin in DTDL


Garden Digital Twin JSON
*************************************************
Welcome to the AzureDigital Twins Demo Playground *************************************************************Requested
query: SELECT *FROM digitaltwinsRan query for twins, page1:[  {    "$dtId":
"Farm",    "$etag":"W/\"77314ce1-6663-4090-a531-0bc197e642fa\"",   
"$metadata": {      "$model":"dtmi:Koutafarm:DigitalTwins:Space;1"    } 
},  {    "$dtId":"thermostat-B",    "$etag":"W/\"34a511bd-3080-4c75-b8f1-65dcff78fd5a\"",   
"$metadata": {      "$model":"dtmi:Koutafarm:DigitalTwins:Thermostat;1"   
}  },  {    "$dtId":
"Moisture-B",    "$etag":"W/\"e5bd2a21-8715-4154-bcaa-36397b3d8a92\"",   
"Location": " Plot B",   
"Moisture": 8,    "$metadata":
{      "$model":"dtmi:Koutafarm:DigitalTwins:Moisture;1",     
"Location": {       
"lastUpdateTime":"2020-10-22T05:00:33.8351264Z"     
},      "Moisture":
{        "lastUpdateTime":"2020-10-22T05:00:33.8351264Z"     
}    }  },  {    "$dtId":"WaterRelay-2",    "$etag":"W/\"fb47a5ad-e172-41ac-b5ea-c4ac40be8562\"",   
"$metadata": {      "$model":"dtmi:Koutafarm:DigitalTwins:WaterSolenoid;1"   
}  },  {    "$dtId":
"Moisture-C",    "$etag":"W/\"b843b0df-bca9-417e-bd0a-3c046b06d453\"",   
"$metadata": {      "$model":"dtmi:Koutafarm:DigitalTwins:Moisture;1"    } 
},  {    "$dtId":"Waterrelay-3",    "$etag":"W/\"9e60202f-5388-4b4a-b7a8-3001e6ea666e\"",   
"$metadata": {      "$model":"dtmi:Koutafarm:DigitalTwins:WaterSolenoid;1"   
}  },  {    "$dtId":
"Vegtable2",    "$etag":"W/\"22c6849a-e2fe-4e5b-b457-3d6952713560\"",   
"$metadata": {      "$model":"dtmi:Koutafarm:DigitalTwins:Vegatble;1"    } 
},  {    "$dtId":
"Vegtable-a1",    "$etag":"W/\"71734a97-2afe-4351-971f-47210256c5bc\"",   
"Location": " Plot-A2",   
"Planteddate": "20/08/20",    "$metadata":
{      "$model":"dtmi:Koutafarm:DigitalTwins:Vegatble;1",     
"Location": {        "desiredValue":
"Plot-A2",       
"desiredVersion": 1,       
"ackVersion": 1,       
"ackCode": 200,       
"ackDescription":"Auto-Sync"     
},      "Planteddate":
{        "desiredValue": "20/08/20",       
"desiredVersion": 1,     
  "ackVersion": 1,       
"ackCode": 200,       
"ackDescription":"Auto-Sync"      }   
}  },  {    "$dtId":
"Vegtable-C1",    "$etag":"W/\"bad662b1-7cc0-4181-bd5c-51d365c59c6b\"",   
"$metadata": {      "$model":"dtmi:Koutafarm:DigitalTwins:Vegatble;1"    } 
},  {    "$dtId":
"Plot-C",    "$etag":"W/\"cc85647c-ec41-47ad-873c-0ed10d60ffd8\"",   
"$metadata": {      "$model":"dtmi:Koutafarm:DigitalTwins:Plot;1"    } 
},  {    "$dtId":
"Plot-A",    "$etag":"W/\"3bba3697-c916-4637-b799-e4260c0f1058\"",   
"Temperature": 29,    "Humidity":
85,    "Light": 114,   
"UVIndex": 4.11,    "Pressure":
100,    "Chookfood": 0,   
"MoistureA": 83,    "MoistureB":
8,    "MoistureC": 18,   
"WaterFlow": 0,    "WaterflowT":
1,    "Waterflowon": "",   
"Signal": 29,    "AreaMSqr":
22,    "DisplayName":"mbknb1500",    "$metadata":
{      "$model":"dtmi:Koutafarm:DigitalTwins:Plot;1",     
"Temperature": {    
   "lastUpdateTime":"2020-10-22T05:03:04.8921313Z"     
},      "Humidity":
{        "lastUpdateTime":"2020-10-22T05:03:04.9144068Z"     
},      "Light":
{        "lastUpdateTime":"2020-10-22T05:03:05.1445044Z"     
},      "UVIndex":
{        "lastUpdateTime":"2020-10-22T05:03:05.5763046Z"     
},      "Pressure":
{        "lastUpdateTime":"2020-10-22T05:03:05.3610596Z"     
},      "Chookfood":
{        "lastUpdateTime":"2020-10-22T05:03:05.7876381Z"     
},      "MoistureA":
{        "lastUpdateTime":"2020-10-22T05:03:06.0052936Z"     
},      "MoistureB":
{        "lastUpdateTime":"2020-10-22T05:03:06.2209549Z"     
},      "MoistureC":
{        "lastUpdateTime":"2020-10-22T05:03:06.4437752Z"      },      "WaterFlow":
{        "lastUpdateTime":"2020-10-22T05:03:06.6741679Z"     
},      "WaterflowT":
{        "lastUpdateTime":"10/16/2020 06:12:42"     
},      "Waterflowon":
{        "lastUpdateTime":"10/16/2020 06:12:42"     
},      "Signal":
{        "lastUpdateTime":"2020-10-22T05:03:07.2745433Z"     
},      "AreaMSqr":
{        "lastUpdateTime":"10/16/2020 06:12:42"     
},      "DisplayName":
{        "lastUpdateTime":"2020-10-22T05:03:04.4316683Z"     
}    }  },  {    "$dtId":"thermostat67",    "$etag":"W/\"59d3b2b3-577d-470d-85cf-20fa1c2ce6fd\"",   
"Temperature": 29,    "DisplayName":
"55223",    "$metadata":
{      "$model":"dtmi:Koutafarm:DigitalTwins:Thermostat;1",     
"Temperature": {       
"lastUpdateTime":"2020-10-22T05:03:04.2033987Z"     
},      "DisplayName":
{        "lastUpdateTime":"2020-10-22T05:03:03.9857404Z"     
}    }  },  {    "$dtId":"WaterRelay-1",    "$etag":"W/\"b411a1cf-9864-44f0-93b4-16289f78befd\"",   
"$metadata": {      "$model":"dtmi:Koutafarm:DigitalTwins:WaterSolenoid;1"   
}  },  {    "$dtId":"thermostat-C",    "$etag":"W/\"9067e647-c9f6-4c72-9b22-f9846465f460\"",   
"$metadata": {      "$model":"dtmi:Koutafarm:DigitalTwins:Thermostat;1"   
}  },  {    "$dtId":"thermostat-A",    "$etag":"W/\"232d30d6-15d8-4041-ae69-d95a619a8ed9\"",   
"$metadata": {      "$model":"dtmi:Koutafarm:DigitalTwins:Thermostat;1"   
}  },  {    "$dtId":
"Moisture-A",    "$etag":"W/\"1b86578e-766a-420c-a3e5-67ff4d130f2e\"",   
"$metadata": {      "$model":"dtmi:Koutafarm:DigitalTwins:Moisture;1"    } 
},  {    "$dtId":
"Vegatble-A2",    "$etag":"W/\"456c690a-3c04-406f-94bc-4ab75d656374\"",   
"DisplayName": " corn",   
"Location": "Melbourne",    "$metadata":
{      "$model":"dtmi:Koutafarm:DigitalTwins:Vegatble;1",     
"DisplayName": {       
"desiredValue": "corn",       
"desiredVersion": 1,       
"ackVersion": 1,       
"ackCode": 200,       
"ackDescription":"Auto-Sync"      },     
"Location": {       
"desiredValue": "Melbourne",       
"desiredVersion": 1,       
"ackVersion": 1,       
"ackCode": 200,       
"ackDescription":"Auto-Sync"      }   
}  },  {    "$dtId":
"Plot-B",    "$etag":"W/\"96d5c0f2-efe4-419a-8c09-ef8b1480a5de\"",   
"Temperature": 25,    "Humidity":
78,    "Pressure": 1010,   
"MoistureA": 40,    "MoistureB": 8,   
"AreaMSqr": 23,    "$metadata":
{      "$model":"dtmi:Koutafarm:DigitalTwins:Plot;1",     
"Temperature": {       
"lastUpdateTime":"2020-10-22T05:01:34.4439804Z"     
},      "Humidity":
{        "lastUpdateTime":"2020-10-22T05:01:34.4439804Z"     
},      "Pressure":
{        "lastUpdateTime":"2020-10-22T05:01:34.4439804Z"     
},      "MoistureA":
{        "lastUpdateTime":"2020-10-22T05:01:34.4439804Z"     
},      "MoistureB":
{        "lastUpdateTime":"2020-10-22T05:01:34.4439804Z"     
},      "AreaMSqr":
{        "lastUpdateTime":"2020-10-22T05:01:34.4439804Z"     
}    }  }]