Introduction & Use Case:

Today, Weโ€™ll build some automation (playbooks ๐Ÿ“’) to swiftly address incidents when logged data values breach predefined thresholds. In this case, Iโ€™d like automated alerts โš  for when my plants are too hot ๐Ÿ”ฅ, too cold โ„, or too thirsty ๐Ÿ’ง.

๐Ÿ‘‰ Note: This follows up on a previous post where we built a Raspberry Pi based soil sensor and onboarded it to Azure IoT Hub, then sent that data to a Log Analytics Workspace, bypassing the endpoint bottleneck.



In this Post We Will:

  • ๐Ÿ‘‰ Build a Logic App to automate email alerting based on sensor readings ๐Ÿ“ˆ
  • ๐Ÿ‘‰ Get alerts for when our plants are too hot ๐Ÿ”ฅ, too cold โ„, or too thirsty ๐Ÿ’ง
  • ๐Ÿ‘‰ Make the most of the free IoT Hub tier ๐Ÿ’ช



Hardware Setup:

See previous post for hardward setupโ€ฆ



Get alerts for when our plants are too hot ๐Ÿ”ฅ, too cold โ„, or too thirsty ๐Ÿ’ง


Youโ€™ll want to follow this setup for a quick win:



1. Recurrence

The first Action in our Logic App dictates how often it should run. Here we can see itโ€™s configured to trigger every 4 hours.



2. Run

Retrieves a list of unique PepperName (hostname) values from a dataset named peppers that meet certain moisture and temperature conditions. Hereโ€™s a high-level breakdown of what it does:

  • It starts by looking at the peppers dataset.

  • It then applies a filter to only include records where the Moisture or Temperature values (converted to decimal) fall outside of certain ranges.

  • These ranges are defined by the MoistureGreaterThan, MoistureLessThan, TempGreaterThan, and TempLessThan parameters.

  • Finally, it selects the distinct PepperName from the remaining data.



3. Parse

Hereโ€™s a high-level summary:

  • The top-level element is an object.

  • This object has a property named value.

  • The value property is an array (indicated by โ€œtypeโ€: โ€œarrayโ€).

  • Each item in the value array is an object (indicated by โ€œtypeโ€: โ€œobjectโ€ under items).

  • These objects have a property named PepperName, which is a string (indicated by โ€œtypeโ€: โ€œstringโ€).

  • The PepperName property is required for each object in the value array (indicated by the required array).

In simpler terms, this schema describes an object that contains an array of objects (value), each with a required string property (PepperName).



4. Initialize

high-level summary of what this step does:

  • It initializes a variable as part of a workflow.

  • The variable is named PeppersOutOfCondition and its type is array. Itโ€™s intended to hold a list of peppers that meet certain conditions (too hot/cold etc.).

  • This step in the workflow is set to run after the prior step has succeeded.

  • The PeppersOutOfCondition variable is used to store the results from the previous step.

In simpler terms, this step is preparing an empty list (or array) named PeppersOutOfCondition to store data that will be used later in the workflow (peppers that are too hot/cold etc.)



5. For Each Loop 1 - Extract

High-level summary of what this next step does:

  • Itโ€™s a Foreach loop, which is used to iterate over a collection of items. In this case, itโ€™s iterating over the value array from the results of a previous step (Peppers that match or fail to match predefined conditions).

  • This Foreach loop is set to run after the previous Initialize step has succeeded.

This step is iterating over the results of a parsed JSON, extracting the PepperName from each item, and appending these names to an array named PeppersOutOfCondition. This happens after the PeppersOutOfCondition variable has been initialized.



6. Append Results to an Array

The action here is of type AppendToArrayVariable, which means it appends a value to an existing array variable that was initialized in a previous step in the workflow (step 4).

  • The array variable is named PeppersOutOfCondition.

  • The value being appended to the PeppersOutOfCondition array is the PepperName from each item in the Foreach loop in the previous step.

This action adds the name of each pepper that meets certain conditions (extracted in a previous step) to the PeppersOutOfCondition array. Thus, this array will contain a list of all peppers that are outside of the specified moisture and temperature conditions.

๐Ÿ‘‰ This is how we can get more than one sensor transmitting across the same service bus and endpoint, and then โ€œpeelโ€ them back out by hostname and throw them into an array to continue working with.



7. Foreach Loop 2 - Filter

This Foreach loop applies to or iterates over the value array from the results of the previous step:



8. Run Query

This Action starts by looking at the peppers dataset. It then filters the data to only include records where the PepperName matches a specific value using a KQL query.

Next, it applies another filter to only include records where the Moisture or Temperature values (converted to decimal) fall outside of certain ranges. These ranges are defined by the MoistureGreaterThan, MoistureLessThan, TempGreaterThan, and TempLessThan parameters.

Finally, it selects the top 1 record from the remaining data, ordered by PepperName.

๐Ÿ‘‰ if youโ€™re looking for a specific pepper that has moisture and temperature values outside of certain ranges, this is the query that will find it.



9. Foreach Loop 3 - Check Conditions with KQL

This third Foreach loop iterates over the value array from the result of the previous Run step.



10. Parse KQL Results

  • The action is of type ParseJson, which means itโ€™s parsing a JSON string into a JSON object.

  • The JSON string to be parsed is provided by the items(โ€˜For_each_-_KQL_Results_Check_Moisture_Conditionsโ€™) expression from the prior Foreach loop.

  • The schema defines the expected structure of the JSON object. Here itโ€™s configured with the following properties: IngestionTime, Moisture, MoisturePercentageEstimate, PepperName, Temperature, and TimeGenerated.

  • The types of these properties are also defined (string for most properties and number for MoisturePercentageEstimate).

In simpler terms, this action is taking a JSON string from a previous step in the workflow, parsing it into a JSON object, and validating its structure against the defined schema.



11. Check Moisture Condition

The If action checks a condition based on the Moisture value from the parsed JSON result of each pepper.

If the Moisture is greater than a threshold (MoistureGreaterThan), or True as illustrated in the Logic App Designer view, it triggers the next Action in the workflow that corresponds with the True condition.

If the Moisture is less than the threshold (False) then trigger the next Action in the workflow corresponding with the False condition.



12. Send Email Action

This action checks the moisture condition for each pepper, and sendg an email alert if the moisture is too high or too low:

  • The Send_an_email_(V2)_-_High_Moisture action sends an email indicating high moisture. The email is sent to the address provided by the email parameter, and the email body includes the PepperName and Moisture values from the parsed JSON result.

  • If the Moisture is not greater than the MoistureGreaterThan threshold, it checks another condition where the Moisture is less than the MoistureLessThan threshold.

  • If this condition is met, it triggers the Send_an_email_(V2)_-_Low_Moisture action.

  • Similar to the high moisture email, it includes the PepperName and Moisture values in the email body.

๐Ÿ‘‰ Make sure to connect your Send from email account when configuring the Send an email V2 action.



13. Re-iteratate for Temperature

Repeat steps 9 through 12, but for Temperature instead of Moisture



Sensor Thresholds:

Iโ€™m growing a variety of peppers (jalapeno, sichuan, goat horn, etc.) so my thresholds are as follows for this sensor setup (you may want to adjust these based on the moisture requirements for what youโ€™re trying to grow. Tomatoes usually need more water than peppers in my experience):


Humidity/Moisture Alerts:

<300 --> too dry
>800 --> too wet



Temperature Alerts:

<45 Degrees F --> too low
>90 Degress F --> too high



Conclusion:

Thanks for reading! With this configuration illustrated across the past few blog posts, you can now securely leverage the free Azure IoTHub to setup automated email alerting for multiple sensors simultaneously (bypassing the single service endpoint bottleneck) so your crop never goes cold โ„, too hot ๐Ÿ”ฅ, or thirsty ๐Ÿ’ง, without breaking the bank! ๐Ÿ’ฐ

๐ŸŒฑ ๐ŸŒฟ What will you grow next? ๐ŸŒผ๐ŸŒป



In this Post We:

  • ๐Ÿ‘‰ Built a Logic App to automate email alerting based on sensor readings ๐Ÿ“ˆ
  • ๐Ÿ‘‰ Got alerts for when our plants are too hot ๐Ÿ”ฅ, too cold โ„, or too thirsty ๐Ÿ’ง
  • ๐Ÿ‘‰ Made the most of the free IoT Hub tier ๐Ÿ’ช



www.hanley.cloud