Floralyfe is a remote, real-time and distributed plant monitor-irrigation system -- a project that helps you take care and grow your plants in a healthy manner. Floralyfe aims to make the plant-growing hobby simpler and thus more attractive to broadent the plant-parent demographic. The project consists of a web-interface client, backend GraphQL and WebSocket servers and, of course, the Raspberry Pi devices and hardware hosting the system.
Floralyfe was developed during Winter 2022 by
Abdalla Abdelhadi
Yousef Yassin
Zakariyya Almalki
- View a full demo here and a shorter one here
- Here's a hardware-only view.
- You can also view our presentation here
The floralyfe system ensures stress-free and healthy plant growth, allowing individuals to spend more time enjoying their plants rather than worrying about their health. To facilitate the care of houseplants, floralyfe provides the functionality below.
Remote Plant Vital Monitoring: The system allows users to register themselves and up to two plants they'd like to take care of. Live vital measurements - temperature, humidity, soil moisture, light and green growth - are periodically recorded and sent to the client to be displayed visually.
Vital Notifications: Users can specify optimal thresholds for specific plant vitals. During periodic measurements, user's are notified if and which vitals are below their set thresholds with both an email and client-based notification. The icon on the SenseHat also changes to convey the critical vital.
Closed-loop Automatic Irrigation: The system employs a state-machine-based feedback loop to water a given plant when its moisture is low. The plant is repeatedly watered until a) the water's moisture level is above the set threshold or b) there is insufficient water in the tank.
Plant Live Camera Feed: Images of the system's environment are repeatedly taken and transmitted to the client to create a live video feed. Users are able to rotate the camera yaw from the client. Once a day, images of each plant are taken and saved to create a timelapse feed.
Plant-specific Notes: Users are able to track the growth progress and other details of their plants by creating plant-specific note posts. The notes are akin to a diary to track plant progress.
You'll need a few things before you can start caring for your plants. The materials needed to build a single floralyfe single are provided below.
- Raspberry Pi v3 or v4
- SenseHat and 40-pin long-header
- Note the long-header connection is needed to be able to interface both the Pi's GPIO pins along with the SenseHat.
- Pi Camera
- MCP3008 (ADC)
- 2 Moisture Sensors
- 1 Water Level Sensor
- 2 DC Water Pumps
- 1 Servo Motor
- And a variety of other circuit components: a breadboard, jumper wires, 3+ transistors (BJT), and resistors.
- NodeJS v16+
- Python 3.9+
- SQLite
- ngrok
- The files in this repository and their dependencies (see Development)
The floralyfe system consists of three primary nodes: a NextJS-Chakra Client, an Express-GraphQL server, and distributed Raspberry Pi systems. Independent installation instructions are required for each system.
- Assuming that you have acquired all the hardware components described in the hardware requirements above, refer to section 4: Hardware Design in the Detailed Design Document for hardware connection. Connect the hardware components to the Raspberry Pi as described by the provided circuit diagrams. Any changes to the provided GPIO ports need to be reflected in
Sensors.py
module in thepi/src
directory.
- There are several steps to configuring the three system nodes with regards to software. For brevity, these have been omitted from this primary README and included in a dedicated discussion: installation.md.
- The pi node implements a unit test workflow, to help develop code that passes these tests, follow these instructions to setup linting for VSCode.
- We recommend using the Remote SSH extension on VSCode when developping on the Raspberry Pi.
- Once all hardware and software requirements have been installed, you can start the systems by following these steps.
- Start the server by navigating to the
server/
directory and running the scripts below.
First, start the Firestore database emulator.
$ npm run emulator
And then, start the server itself.
$ npm run dev
By default, the WebSocket and Express REST server run on port 5000. The GraphQL server runs on port 5001.
- Then, start the client by navigating to the
client/
directory and runningnpm run dev
. - Now, tunnel your ports so they may be accessible remotely. You need to do this so the Pi can access your servers, at a minimum. There are several ways to tunnel the ports: two I suggest are localtunnel or ngrok.
- With ngrok, locate your config yaml file. On Windows, it'll be under
Users/<your-user>/.ngrok2/ngrok
. - Authenticate with ngrok and obtain your auth-token, then set the config file to the following:
- With ngrok, locate your config yaml file. On Windows, it'll be under
authtoken: 25WHb2ZqTR24fNtm2XCelZC9mKy_6iinQfUBftMg9KcfFstGD
tunnels:
first:
addr: 5000
proto: http
second:
addr: 5001
proto: http
third:
addr: 3001
proto: http
And now you can tunnel all of the ports using the command ngrok start --all
.
- Once you've tunneled the ports, change the endpoints in the config files in both the
client/
andpi/
directories.- Pi:
pi/src/config/config.py
- Client:
client/src/lib/config.ts
- Pi:
- Finally, start the Raspberry Pi system by running the main script. First navigate to the
pi/
directory and enter the virtual environment by runningsource scripts/run.sh
. Then navigate to thesrc/
directory and runpython main.py
. You'll be prompted to login, don't yet. - First, register yourself as a user using the sign-up option on the client interface. If successful, you should see a green message. Navigate to
localhost:8000
to see the Firestore instance and your user should be there. - Try signing in with your user, you should be redirected to a page that prompts you to pair your RPi device.
- Now login on the RPi device using the same credentials you signed up with. A successful sign-in will pair your device with your user and begin transmitting data. Refresh the client to wrap-up registration.
- There you go, now you're able to communicate with your device and register any plants. Enjoy! 🎉
The Raspberry Pi system is written in Python. The system is architected as a multi-threaded applications where each major subsystems defines two dedicated threads: a main and worker thread. Each subsystem node derives a parent Floranode that defines its basic interface.
scripts/
: Holds various helper scripts for installing dependencies and configuring the python virtual environmnent. The remainder of the soruce code can be found under the src/
directory.
config/
: Holds all system variables, namely API and server endpoints.
flora_node/
: Defines the FloraNode Parent class that must be inherited by all floralyfe system nodes. Defines the basic interface for all system nodes.
camera_system/
: The camera monitoring subsystem node and its associated utility functions, including luminescense and green growth estimation in opencv_filters.py
.
irrigation_system/
: The automatic irrigation subsystem node and its associated helpers for maintaining soil moisture.
vital_system/
: The vital subsystem for measuring and transmitting plant vitals / notifications.
query/
: GraphQL helpers for mutating the cloud Firestore database. Also contains certain REST endpoint helpers, such as for creating emails.
test/
: Contains all unit tests.
timelapse/
: Contains periodically captured plant images to create a timelapse. The ones here are from the last demo.
main.py
: The main entrypoint to the Floralyfe RPi System.
database.py
: Creates the SQLite database and offers accessor helpers for each table.
ws.py
: The WebSocket client that binds the Websocket server. Offers functionality to send and receive messages - routes messages to appropriate node message queues.
Sensors.py
: Hardware helper to interface with GPIO and all system sensors and actuators.
util/Logger.py
: Logger helper to log debug statements.
util/Singleton.py
: Singleton helper to define Singleton classes.
gpiozero_mocks/
: Stores all hardware simulations to support development without the RPi, such as on Windows.
camera_standalone.py
: This file is unused but presents an example of how subsystems should be tested. To maintain the src
root, all files should define a wrapper file to call them from the root.
The server is written in TypeScript and uses the Node JS framework to manage communication across application nodes. The server connects to a Firestore database, or an internal emulator. The node uses the Express framework to define two servers: one for a WebSocket and one exposing a GraphQL API with support for data subscriptions using the publisher-subscriber pattern.
test/
: Contains all unit tests. All remaining source code is found in the src/
directory.
graphql/
: Contains GraphQL definitions for resolvers and the schema. These are largely imported from models/
.
models/
: Contains model-specific defintions for GraphQL resolvers and schemas.
notifications/
: Containts REST notification route logic for sending emails with nodemailer.
server.ts
: Main entrypoint for the server - initializes and starts the server.
setupWebSocket.ts
: Helper to create, initialize and bind the websocket to the main express server. All websocket logic goes here.
util.ts
: Utility helpers, mainly for logging.
The client is also written in TypeScript and uses the NextJS framework along with Chakra UI to display a web interface that a user can use to interact with the Floralyfe system. This node is largely configuration - the majority of relevant files can be found under client/src/lib
.
api/queries/
: Defines GraphQL query, subscription and mutation queries.
api/createQuery.ts
: Helper for requesting a GraphQL query.
api/plantId.ts
: Helper for requesting the plant Id API for plant identification.
api/pages/
: Contains all client pages (routes): login, signup, register-plants and home-dashboard.
api/components/components
: Contains all interface components, these are not listed for brevity.
api/components/hooks/useWebSocket.ts
: WebSocket client helper to connect to the websocket server, receive and send messages. Also binds callbacks to specific message topics.
api/components/layout
: Primary interface entrypoint. Defines layout in which components are presented.
api/components/util
: Contains utility helpers for GraphQL requests with apollo-client, creating toast notifications, and other logging helpers.
api/store/
: Zustand store and store slices for state-management and data persistence.
- Migrate the video feed from using WebSockets to using WebRTC. The latter is optimized for media transfer and will support more seamless video streaming from the RPi to the client.
- Weather proofing and packaging the model such that it can be safely used outdoors.
- The addition of a computer vision model to detect animals (either outdoors - squirrels, birds, rabits, etc. or indoor pets).
- Adding a buzzer to add a audio component to notifications and to scare off animals.
- Integrating the Plant id API further to detect plant diseases.
- Querying registered plants in our database to suggest plant optima to users.
For more information regarding the project, please reference the documentation/
directory. There, you'll find the project proposal and detailed design .
- The web-interface client uses the nextarter-chakra boilerplate.
- The UI is based off the Purity UI dashboard although it was developped independently.
- The login and sign-up pages are based off templates from Chakra-templates