Skip to content

CropCare, an IoT farm that uses Microsoft Azure as the connection to communicate with the Raspberry Pi/Python backend to deliver telemetry data & control options to our .NET MAUI mobile app.

Notifications You must be signed in to change notification settings

carsonSgit/CropCare

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

image


๐ŸŒฑ Project Description

CropCare's goal is to combat the growing impact urbanization has on the safety of the farming & agriculture world. Our application provides users (farm Technicians or Owners) with a centralized control & monitoring center for everything that is going on in their IoT container farms. The mobile application sends and receives data through Microsoft Azure which acts as an intermediary between our mobile application and the project back-end. The project back-end is developed in Python and hosted/ran off of a Rasperry Pi reTerminal that is repeatedly getting readings and states from the hardware it is connected with, ultimately sending it off to Microsoft Azure to then be received on the Mobile Application interface.


๐Ÿ”ง Contributions

Developer Contribution
Cristiano Fazi Full-stack developer & team lead
Kevin Baggott Back-end & hardware developer
Carson Spriggs-Audet Full-stack developer & designer

Important

It is important to know that there were no distinct set roles, the contributions above are what each person primarily focused on, but each team member evenly contributed in various ways.


๐Ÿ› ๏ธ Relevant Technologies

In relation to the courses this project was made for, below are the technologies used;

Application Development 3:

  • Development in .NET Maui
  • Visual Studio 2022 Community Edition

Connected Objects:

  • Python
  • Azure IoT Tools
  • Raspberry Pi
  • Visual Studio Code

External:


๐ŸŒ 3D Model

3D Model

Tip

If you want to interact with the 3D model, please click the image above or you can follow this link.


๐Ÿ”— Design Document

If you are interested in the design of our app and code structure (i.e. our "blueprint" before we began developing), please visit this link, you will be met with a Google Doc with our detailed strategy.


๐Ÿ“„ Other documents & files

If you are interested in viewing more details/more expansive versions of the information presented in this README (3D models, UML diagrams, wireframes), navigate to the "./Documents" path. image


App Layout

Below is an image displaying the functionality of each page within our mobile app (in light mode). CropCare App Layout

โš™๏ธ App Setup

You need the following technology - .NET MAUI & an Android Emulator - A Raspberry Pi & a base hat - Various sensors & actuators (all noted below)

For .NET MAUI setup, you need to modify the appsettings.json to have the correct keys. Your appsettings.json should go in the project top level project directory. It should look like this:

{
  "Settings": {
    "FirebaseAuthorizedDomain": "my-firebase-app-d60e2.firebaseapp.com",
    "FireBaseApiKey": "awdawdFWADSf32134dadwawda",
    "FireBaseDatabaseURL": "https://my-firebase-app-d60e2-default-rtdb.firebaseio.com/",
    "GoogleMapsAPIKey": "gdtrhrdffeff3fsdffasefsegjntsbgfawddwa",
    "EventHubConnectionString": "Endpoint=sb:https://iothub-ns-my-app-59465961-6d1bd0200e.servicebus.windows.net/;SharedAccessKeyName=iothubowner;SharedAccessKey=0es2007K2ch9jfd6n9rDBX1kEIX8HkAc9AIoTHoehx0=;EntityPath=my-app",
    "EventHubName": "my-app",
    "IotHubConnectionString": "HostName=my-app.azure-devices.net;SharedAccessKeyName=iothubowner;SharedAccessKey=0es2007K2ch9jfd6n9rDBX1kEIX8HkAc9AIoTHoehx0="
  }
}

In order to get a google maps api key, follow the intstructions here: Use API Keys

For the azure setup, you must create an iothub resource. To get the EventHubConnectionString and EventHubName you must go to the Build-in endpoints tab and you will see them there. As for the iothubconnection string you must go to the Shared access policies tab, click on iothubowner and copy the primary connection string from there. There firebase API keys are all obtained from the firebase console.

Once azure is set up, you must create a device, click on it and copy its primary key or connection string and put it in a .env in farm/ folder in this repo. You can use .env.example as an example of how your .env should look. In order to properly get readings from iot hub from within the app, when you create a farm you must enter the device_id that matches the correct device in Azure iot hub:

image image

๐ŸŽฎ Controlling Actuators

๐ŸŒฑ Plant Subsystem Device Documentation

Follow the port guide below to sucessfully utilize the farm setup.

Sensor/Actuator Port on Grove Base Hat Port Type Unit
Soil Moisture Sensor 0 PIN ฮฉ
Temperature/Humidity Sensor 26 PIN Temp: ยฐC, Humi: % HR
Water Level Sensor 5 PIN water level
Fan 12 PIN N/A
LED 18 PIN N/A

๐Ÿ”’ Security Subsystem Device Documentation

Follow the port guide below to sucessfully utilize the farm setup.

Sensor/Actuator Port on Grove Base Hat Port Type Unit
Loudness Sensor 2 PIN unitless
Luminosity Sensor N/A BUS nm
Motion Sensor 22 PIN N/A
Vibration Sensor N/A PIN N/A
Servo 16 PIN N/A
Door Sensor 24 PIN N/A

๐ŸŒ Geolocation Subsystem Device Documentation

Follow the port guide below to sucessfully utilize the farm setup.

Sensor/Actuator Port on Grove Base Hat Port Type Unit
Accelerometer N/A BUS ยฐ
Buzzer N/A BUS N/A
GPS /dev/ttyS0 UART N/A

๐Ÿ› ๏ธ Controlling the Actuators from the Cloud:

Direct Methods are used to control each actuator. We felt that it made the most sense since we control them with a method in our code to just invoke the same method with the parameters specified in the payload.

๐ŸŒ€ Fan

The target field must be set to fan and the value can be either on or off. az iot hub invoke-device-method --hub-name cropcare --device-id {device_id} --method-name control_actuator --method-payload '{"target":"fan", "value": "on"}'

๐Ÿ”Š Buzzer

The target field must be set to buzzer and the value can be either on or off. az iot hub invoke-device-method --hub-name cropcare --device-id {device_id} --method-name control_actuator --method-payload '{"target":"buzzer", "value": "on"}'

๐ŸŽš๏ธ Servo

The target field must be set to servo and the value can be a float from -1 to 1 inclusively. az iot hub invoke-device-method --hub-name cropcare --device-id {device_id} --method-name control_actuator --method-payload '{"target":"servo", "value": "1"}'

๐Ÿ’ก LED

The target field must be set to led and the value can be either on or off. az iot hub invoke-device-method --hub-name cropcare --device-id {device_id} --method-name control_actuator --method-payload '{"target":"led", "value": "on"}'

๐Ÿ“ก Additional Communication from the Cloud

We can also get the state of any actuator we want without changing them by using the following command: az iot hub invoke-device-method --hub-name cropcare --device-id {device_id} --method-name get_single_actuator_state --method-payload '{"target":"fan"}'

This will return a message resembling: { "payload": { "target": "fan", "value": "ON" }, "status": 200 } To set telemetryInterval to 5 seconds: az iot hub device-twin update -n cropcare -d {device_id} --desired '{"telemetryInterval": 5}'

โฌ†๏ธ D2C Messages

Longitude and Latitude to determine GPS location:

  • az iot device send-d2c-message -n {iothub_name} -d {device_id} --data "{'reading_type': 'LONGITUDE', 'value': 152.408976, 'unit': 'ยฐ'}"
  • az iot device send-d2c-message -n {iothub_name} -d {device_id} --data "{'reading_type': 'LATITUDE', 'value': 152.408976, 'unit': 'ยฐ'}"

Temperature of the container:

  • az iot device send-d2c-message -n {iothub_name} -d {device_id} --data "{'reading_type': 'TEMPERATURE', 'value': 40.34324, 'unit': 'ยฐC'}"

Humidity inside the container:

  • az iot device send-d2c-message -n {iothub_name} -d {device_id} --data "{'reading_type': 'HUMIDITY', 'value': 20.231, 'unit': '% HR'}"

Luminosity for detecting light levels:

  • az iot device send-d2c-message -n {iothub_name} -d {device_id} --data "{'reading_type': 'LUMINOSITY', 'value': 433, 'unit': 'lux'}"

Loudness inside the container:

  • az iot device send-d2c-message -n {iothub_name} -d {device_id} --data "{'reading_type': 'LOUDNESS', 'value': 200, 'unit': 'Db'}"

Moisture of the soil:

  • az iot device send-d2c-message -n {iothub_name} -d {device_id} --data "{'reading_type': 'MOISTURE', 'value': 232.34311, 'unit': 'ฮฉ'}"

Waterlevel:

  • az iot device send-d2c-message -n {iothub_name} -d {device_id} --data "{'reading_type': 'WATERLEVEL', 'value': 221, 'unit': 'ฮฉ'}"

Motion inside the container:

  • az iot device send-d2c-message -n {iothub_name} -d {device_id} --data "{'reading_type': 'MOTION', 'value': True, 'unit': ''}"

Vibration in the container:

  • az iot device send-d2c-message -n {iothub_name} -d {device_id} --data "{'reading_type': 'VIBRATION', 'value': False, 'unit': ''}"

Magnet for detecting if the door is closed:

  • az iot device send-d2c-message -n {iothub_name} -d {device_id} --data "{'reading_type': 'MAGNET', 'value': True, 'unit': ''}"

Pitch of the container:

  • az iot device send-d2c-message -n {iothub_name} -d {device_id} --data "{'reading_type': 'PITCH', 'value': 12.322, 'unit': 'ยฐ'}"

Roll of the container:

  • az iot device send-d2c-message -n {iothub_name} -d {device_id} --data "{'reading_type': 'ROLL', 'value': 56.7445, 'unit': 'ยฐ'}"

๐Ÿ› ๏ธ App Overview

Hardware Features

  • Monitoring

    • Measure relative water levels
    • Measure soil moisture levels
    • Read fan state (on/off)
    • Read light state (on/off)
    • Collect container GPS Location
    • Read container pitch and roll angles
    • Read vibration levels
    • Read buzzer state (On/Off)
    • Read noise levels
    • Read luminosity levels
    • Read motion sensor state (motion detected)
    • Read door-lock state (servo open/closed)
    • Read door state
  • Remote Controls

    • Control buzzer state (On/Off)
    • Control door-lock state (servo open/closed)
    • Control fan state (on/off)
    • Control light state (on/off)

โ˜๏ธ Cloud Computing Features

  • Azure IoT Setup

    • Able to create containers
    • Create azure keyvault to store connection strings
  • IoT Access

    • Collect Telemetry data from Azure IoT hub
    • Allow for D2C commands to alter computer unit (Raspberry Pi reTerminal)'s state

๐Ÿ“ฑ Mobile App Features

  • User Authentication

    • Build a user login/signup page
    • Create a user login system
    • Create a user sign-up system (Considering the two account types)
    • Implement a logout button
    • Ensure app differentiates between account types
  • Supporting Infrastructure

    • Create a flyout menu
    • Create a logo for the application and company
    • Access environment variables
  • Overview

    • Owners are able to instantiate new farms
    • Owners & Technicians are able to enter farms assosciated with their user ID
  • Dashboard

    • Users are able to see 3 general health statuses (Plant, Security, GPS)
    • Owners have the following cards; Plant, Security, GPS, Modify Technicians, Settings
    • Technicians have the following cards; Plant & Security
  • Plant Monitoring Page

    • Display all the data relating to the plants, such as moisture, and water levels through an interactive page
    • Display health statuses according to current data
  • Security Page

    • Display container state information
    • Allow users to control systems of the container farm, such as the door
  • GPS Monitoring Page

    • Fleet manager should see a map on their farm page with the actual farm location
  • Modify Technicians Page

    • The owner of a farm is able to modify the technicians who are assigned to a farm
  • Farm Settings Page

    • Owners can; change farm name, change twin patch interval, and the icon of their farm
  • Settings Page

    • Design Settings Page
    • Allow user to change account details
    • Allow users to change colour theme

๐ŸŽจ App Wireframes

CropCare v2

๐Ÿ“ App UML Diagrams

User & Farm

classDiagram
    class User {
        - List<string> farmKeys
        + PropertyChangedEventHandler PropertyChanged
        + string Key
        + string Email
        + string Name
        + bool IsOwner
        + List<string> FarmKeys
        + bool IsAssigned
        + User(string email, string name, bool isOwner)
    }

    class Farm {
        + PropertyChangedEventHandler PropertyChanged
        + string Key
        + string Name
        + string DeviceId
        + EventHubConsumerClient Consumer
        - PlantController PlantController
        - SecurityController SecurityController
        - GeolocationController GeolocationController
        + Farm(string farmName, string deviceId)
    }

    class UserToFarm {
        + string Key
        + string UserId
        + string FarmId
        + UserToFarm(string userId, string farmId)
    }

    User "1" --> "0..*" UserToFarm
    Farm "1" --> "0..*" UserToFarm
Loading

Controllers

classDiagram
    class BaseController {
        - string[] _readingTypes
        + Dictionary<string, ObservableCollection<Reading>> Readings
        + bool ValidateReading(Reading reading)
        + virtual void AddReading(Reading reading)
        + BaseController(string[] readingTypes)
    }

    class PlantController {
        - static readonly string[] _readingTypes
        + PropertyChangedEventHandler PropertyChanged
        + Reading Temperature
        + Reading Humidity
        + Reading Moisture
        + Reading WaterLevel
        + void ToggleFan()
        + void ToggleLed()
        + void AddReading(Reading reading)
        + PlantController()
        + string UpdateReadingHealthLabel(string sensorReading, char unitSymbol, double highThreshold, double lowThreshold)
        + string UpdateStateHealthLabel(string actuatorState)
    }

    class SecurityController {
        - static readonly string[] _readingTypes
        + PropertyChangedEventHandler PropertyChanged
        + Reading Loudness
        + Reading Motion
        + Reading Vibration
        + Reading Luminosity
        + void ToggleDoorLock()
        + void ToggleDoorOpen()
        + void AddReading(Reading reading)
        + SecurityController()
        + string UpdateReadingHealthLabel(string sensorReading, char unitSymbol, double highThreshold, double lowThreshold)
        + string UpdateStateHealthLabel(string actuatorState)
    }

    class GeolocationController {
        - static readonly string[] _readingTypes
        + PropertyChangedEventHandler PropertyChanged
        + Reading Latitude
        + Reading Longitude
        + Reading Pitch
        + Reading Roll
        + void ToggleBuzzer()
        + void AddReading(Reading reading)
        + GeolocationController()
    }

    BaseController <|-- PlantController
    BaseController <|-- SecurityController
    BaseController <|-- GeolocationController
Loading

About

CropCare, an IoT farm that uses Microsoft Azure as the connection to communicate with the Raspberry Pi/Python backend to deliver telemetry data & control options to our .NET MAUI mobile app.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published