IOT Garden Project-Azure Digital Twin

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 saleable solution to manage an environment. Through creating a digital model of one 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 the 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 in my case is to send a message back to the Arduino microcontroller to turn the sprinkler on.

I can integrate with Azure data, analytics, and AI services to help you 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. In Azure Digital Twins, you define the digital entities that represent the people, places, and things in your physical environment using custom twin types called models.

The digital twin model for the garden bed is a set of definitions as a specialised properties to describe the garden plot. for example, it defines models for the whole farm such as "PLOTS, 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 assignd to the plot and this is defined in a JSON-like language called Digital Twins Definition Language (DTDL). It describs 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 your entities so that you can connect your 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 lifecycle.

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 used to build my complete digital twin environment

Here's a view of what the sample visualization looks like:


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.

Notice the relationships between the digital twin models. The Farm model has manay 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 parents 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 whos role is to find the parent of the sensor and then updates the parents 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 you.

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.



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 Installment 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
************************************************* Welcome to the Azure
Digital Twins Demo Playground *************************************************************Requested query: SELECT *
FROM digitaltwinsRan query for twins, page
1:[  {    "$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"      }    }  }]