├── .gitignore
├── LICENSE
├── README.md
├── app
├── .gitignore
├── README.md
├── app.py
├── camera.py
├── config.json
├── growlab.service
├── index.jinja
├── requirements.txt
├── sample.sh
├── sensor-i2c.png
├── sensors.py
├── specimen.py
└── sync-code.sh
└── data-logger
├── .gitignore
├── README.md
├── dashboard.json
├── sender
├── main.py
├── requirements.txt
└── sensors.py
├── stack.yml
└── submit-sample
├── __init__.py
├── handler.py
└── requirements.txt
/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 | .venv
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Alex Ellis
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## News!
4 |
5 | If you particpated in Growlab 2021, you can [register for our prize draw here](https://forms.gle/ekZuGnuWDfwpaEGd6)
6 |
7 | ## A global contest to grow seeds and share your progress with the Raspberry Pi
8 |
9 | My early growlab
10 |
11 | 
12 | > A capture from phototimer of my seed tray with a wide-angle camera positioned above
13 |
14 | 
15 | > My own growlab laboratory
16 |
17 | 
18 | > Graduated seedlings
19 |
20 | ## Videos
21 |
22 | * [Overview - Growing your own with the Raspberry Pi with Alex Ellis at GIFEE Day](https://www.youtube.com/watch?v=GE7kyi6kFJY)
23 | * [Live stream "Grow your own food with Raspberry Pi" - Alex Ellis & Richard Gee](https://www.youtube.com/watch?v=Ta_LBKpI5-0)
24 |
25 | ## How it works
26 |
27 | 1) Read the launch blog post: [Join the Grow Lab Challenge](https://blog.alexellis.io/the-grow-lab-challenge/).
28 | 3) Decide you're taking part by sending a PR and adding yourself to the "growlab Technicians" section below.
29 | 2) Find or buy the required components for the experiments you want to take part in (read all of this file to learn more)
30 | 4) Build your own `#growlab` using one of the designs, or customise it. And start growing and recording a timelapse.
31 | 5) Use the [#growlab hashtag](https://twitter.com/search?q=%23growlab&src=typed_query) and share as many pictures as you like.
32 | 6) Send a Pull Request and link to each Tweet to unlock each level.
33 | 7) At the conclusion of the growing period, we'll send some prizes from OpenFaaS Ltd and Pimoroni to entries at random for different tiers.
34 |
35 | > Note: Growlab 2021 concludes Sunday 3rd October to mark Harvest Festival in the United Kingdom.
36 |
37 | Prizes to be provided by: [OpenFaaS Ltd](https://openfaas.com) and [Pimoroni](https://www.pimoroni.com). Want to sponsor or provide prizes? Send an email to [alex@openfaas.com](mailto:alex@openfaas.com)
38 |
39 | ### Unlock each level
40 |
41 | Before you get started with your build, send a PR to list yourself as a "lab technician".
42 |
43 | Bronze - assemble your `#growlab` using one of the recommend designs or customise it. Tweet a photo of your build fully assembled.
44 |
45 | Silver - install the software and capture your first photo of your seed tray or pots. Tweet the photo.
46 |
47 | Gold - Wait until at least one of your seeds has germinated and grown into a seedling - around 2-3cm in height. Tweet the photo taken by the timelapse software.
48 |
49 | Platinum - use the [phototimer](https://github.com/alexellis/phototimer) or seeds2 software to capture images over 14 days. Compile the images into a timelapse and upload it to YouTube. We recommend one photo every 10 minutes. Feel free to exclude any photos prior to the seeds germinating. Tweet a link to the video.
50 |
51 | ## Growlab Technicians
52 |
53 | Technicians work in laboratories, and you are no different, so if you've bought your kit, or have decided to join, then add your details below so that we can encourage each other and see how many people are participating. If you don't have a Twitter or GitHub handle just put N/a.
54 |
55 | | # | Name | Twitter | GitHub | Live preview URL | Country |
56 | |---|---------------------|-----------------|---------------|------------------|----------|
57 | | 1 | Alex Ellis | [@alexellisuk](https://twitter.com/alexellisuk) | [alexellis](https://github.com/alexellis) | [Live preview with the growlab app](http://growlab.alexellis.io/) | United Kingdom |
58 | | 2 | Simon Emms | [@MrSimonEmms](https://twitter.com/MrSimonEmms) | [MrSimonEmms](https://github.com/MrSimonEmms) | [Images captured by phototimer](https://growlab.simonemms.com) | United Kingdom |
59 | | 3 | Richard Gee | [@rgee0](https://twitter.com/rgee0) | [rgee0](https://github.com/rgee0) | [Most recently captured image](https://growlab.technologee.co.uk/) | United Kingdom |
60 | | 4 | Jakob Waibel | [@jakobwaibel](https://twitter.com/jakobwaibel) | [JakWai01](https://github.com/JakWai01) | [Live preview with the growlab app](https://jakwai01.github.io/growlab/) | Germany |
61 | | 5 | Florian Clanet | [@FlolightC](https://twitter.com/FlolightC) | [Flolight](https://github.com/Flolight) | |
62 | | 6 | Felix Pojtinger | [@pojntfx](https://twitter.com/pojntfx) | [pojntfx](https://github.com/pojntfx) | |
63 | | 7 | Sam Perrin | [@sam_perrin](https://twitter.com/sam_perrin) | [sam-perrin](https://github.com/sam-perrin) | | United Kingdom |
64 | | 8 | Philippe Charrière | [@k33g_org](https://twitter.com/k33g_org) | [k33g](https://github.com/k33g) | |
65 | | 9 | John McCabe | [@mccabejohn](https://twitter.com/mccabejohn) | [johnmccabe](https://github.com/johnmccabe) | | United Kingdom |
66 | | 10 | Adam Craggs | [@abigpancake](https://twitter.com/abigpancake) | [agcraggs](https://github.com/agcraggs) | | United Kingdom |
67 | | 11 | Martin Woodward | [@martinwoodward](https://twitter.com/martinwoodward) | [martinwoodward](https://github.com/martinwoodward) | [Live preview](https://bfaulty.z16.web.core.windows.net/) | United Kingdom |
68 | | 12 | Jérôme Velociter | [@jvelo](https://twitter.com/jvelo) | [jvelo](https://github.com/jvelo) | | France |
69 | | 13 | Philippe Ensarguet | [@p_ensarguet](https://twitter.com/P_Ensarguet) | [pensarguet](https://github.com/pensarguet) | [Live preview](https://pensarguet.github.io/growlab-livepreview/) | France |
70 | | 14 | Sander Vanhove | [@SanderWaylay](https://twitter.com/SanderWaylay) | [SanderVanhove](https://github.com/SanderVanhove) | [Live preview](https://www.sandervanhove.com/plant-monitor) |
71 | | 15 | Sergei Vasilev | [@nblpblc](https://twitter.com/nblpblc) | [sergevas](https://github.com/sergevas) | [Live preview](https://growlab.sergevas.dev) |
72 | | 16 | Iheb | [@iboonox](https://twitter.com/iboonox) | [iboonox](https://github.com/iboonox) | [Live preview](https://iheb.io) | France |
73 | | 17 | Allan Pead | [@adpead](https://twitter.com/adpead) | [apead](https://github.com/apead) | |
74 | | 18 | Keith Hubner | [@keithhubner](https://twitter.com/keithhubner) | [keithhubner](https://github.com/keithhubner) | [Live preview](https://growlab.hubner.co.uk/) |
75 | | 19 | Antoine Mouchere | [@mouchere_a](https://twitter.com/mouchere_a) | [amouchere](https://github.com/amouchere/growlab-project#readme) | [Live preview](https://amouchere.github.io/growlab-preview/) |
76 | | 20 | Kyle Brennan | [@kylos101](https://twitter.com/kylos101/) | [kylos101](https://github.com/kylos101)| [Live Preview](https://kylos101.github.io/growlab/docs/) |
77 | | 21 | Ben Hughes | [@bwghghs](https://twitter.com/bwghghs) | [bwghughes](https://github.com/bwghughes)| [Live Preview](https://bwghughes.github.io/growlab/app/docs/) |
78 | | 22 | Carlos Panato | [@comedordexis](https://twitter.com/comedordexis) | [cpanato](https://github.com/cpanato)| [Live Preview](https://cpanato.dev/growlab-live/) | Germany |
79 | | 23 | Plant Holmes | [@plantholmes](https://twitter.com/plantholmes) | [scrimples](https://github.com/scrimples)| | |
80 | | 24 | Marian Horgan | [@always_marian](https://twitter.com/always_marian) | [Quarkiness](https://github.com/Quarkiness)| | Ireland |
81 | | 25 | Felipe Cruz | [@felipecruz](https://twitter.com/felipecruz) | [felipecruz91](https://github.com/felipecruz91)| [Live preview with the growlab app](https://felipecruz91.github.io/growlab) | Spain |
82 | | 26 | Iván Gómez | [@ivanusatuiter](https://twitter.com/ivanusatuiter) | [igomezal](https://github.com/igomezal)| [Live Preview](https://igomezal.github.io/growlab/) | Spain |
83 | | 27 | Thibault Jochem | [@tryumk](https://twitter.com/tryumk) | [tryum](https://github.com/Tryum) | N/A (yet) | France |
84 | | 28 | Peter Dongo | [@TheDaN997](https://twitter.com/TheDaN997) | [dpeter79](https://github.com/dpeter79) | [Live preview with the growlab app](https://dpeter79.github.io/growlab/) | Hungary |
85 | | 29 | Dalton Cole | [@LessTechnology](https://twitter.com/LessTechnology) | [dalton-cole](https://github.com/dalton-cole) | [Live preview](https://raspberry.farm) | United States |
86 | | 30 | Beril Kurt| [@berlonics](https://twitter.com/berlonics) | [berlonics](https://github.com/berlonics) | | Germany |
87 | | 31 | Cameron Bunce | | [cameronbunce](https://github.com/cameronbunce) | coming soon | United States |
88 | ### Live preview URLs
89 |
90 | A live preview URL keeps things interesting and lets the community get a view inside your lab.
91 |
92 | See the new [growlab app](/app) for your Raspberry Pi
93 |
94 | ## Contest entries `#growlab` 🥇🥈🥉
95 |
96 | | Name | Bronze | Silver | Gold | Platinum |
97 | |-------|----------|----------|--------|----------|
98 | | Alex Ellis | [Bronze](https://twitter.com/alexellisuk/status/1380227185894690823) | [Silver](https://twitter.com/alexellisuk/status/1380227185894690823) | [Gold](https://twitter.com/alexellisuk/status1380417347861774337) | [Platinum](https://www.youtube.com/watch?v=YiFUVAP0B18) |
99 | | Simon Emms | [Bronze](https://twitter.com/MrSimonEmms/status/1386361659187412996) | [Silver](https://twitter.com/MrSimonEmms/status/1386361659187412996) | [Gold](https://twitter.com/MrSimonEmms/status/1391832940225630212) | [Platinum](https://twitter.com/MrSimonEmms/status/1391832943170146313) |
100 | | Richard Gee | [Bronze](https://twitter.com/rgee0/status/1383379807585521665) | [Silver](https://twitter.com/rgee0/status/1383379805928759301) | [Gold](https://twitter.com/rgee0/status/1384765411913355265) | [Platinum](https://twitter.com/rgee0/status/1393890208446402561) |
101 | | Jakob Waibel | [Bronze](https://twitter.com/jakobwaibel/status/1386372010658443265) | [Silver](https://twitter.com/jakobwaibel/status/1386372010658443265) | [Gold](https://twitter.com/jakobwaibel/status/1388894057955479554) | [Platinum](https://www.youtube.com/watch?v=z8sY37OlFrw) |
102 | | Florian Clanet | [Bronze](https://twitter.com/FlolightC/status/1384587367785369602) | [Silver](https://twitter.com/FlolightC/status/1383802323164561418) | | |
103 | | Felix Pojtinger | | | |
104 | | Sam Perrin | [Bronze](https://twitter.com/sam_perrin/status/1391383693860687876) | [Silver](https://twitter.com/sam_perrin/status/1391383693860687876) | [Gold](https://twitter.com/sam_perrin/status/1393898134527414272) | |
105 | | Philippe Charrière | | | |
106 | | John McCabe | [Bronze](https://twitter.com/mccabejohn/status/1387001148419227648) | [Silver](https://twitter.com/mccabejohn/status/1396484258403950598) | | |
107 | | Adam Craggs | [Bronze](https://twitter.com/ABigPancake/status/1387414840914894851) | | | |
108 | | Martin Woodward | [Bronze](https://twitter.com/martinwoodward/status/1388813602828730369) | [Silver](https://twitter.com/martinwoodward/status/1388887836196098049)| [Gold](https://twitter.com/martinwoodward/status/1392376722612445184) | |
109 | | Jérôme Velociter | [Bronze](https://twitter.com/jvelo/status/1393892964305448961) | | | |
110 | | Philippe Ensarguet | [Bronze](https://twitter.com/P_Ensarguet/status/1391382014557933569) |[Silver](https://twitter.com/P_Ensarguet/status/1395743166507139072) |[Gold](https://twitter.com/P_Ensarguet/status/1401155745157206018) |[Platinum](https://twitter.com/P_Ensarguet/status/1401151522692534281) |
111 | | Sander Vanhove | [Bronze](https://twitter.com/SanderWaylay/status/1391665619616026624) | [Silver](https://twitter.com/SanderWaylay/status/1397853230315540482) | [Gold](https://twitter.com/SanderWaylay/status/1400716134094098433) | |
112 | | Sergei Vasilev | [Bronze](https://twitter.com/nblpblc/status/1398195911390633984) |[Silver](https://twitter.com/nblpblc/status/1398195911390633984) |[Gold](https://twitter.com/nblpblc/status/1398617422400208900) |[Platinum](https://twitter.com/nblpblc/status/1404772425691111427) |
113 | | Iheb | [Bronze](https://twitter.com/iboonox/status/1393532825031397377) | [Silver](https://twitter.com/iboonox/status/1393532908166602753)| [Gold](https://twitter.com/iboonox/status/1395105689161412614) | [Platinium](https://youtu.be/M2rNWlyxRKA) |
114 | | Allan Pead | [Bronze](https://twitter.com/adpead/status/1393984772381229059) | [Silver](https://twitter.com/adpead/status/1394906481515024385) | | |
115 | | Keith Hubner | [Bronze](https://twitter.com/keithhubner/status/1393611768660963335) | [Silver](https://twitter.com/keithhubner/status/1394203963352887301) | [Gold](https://twitter.com/keithhubner/status/1394608874636914690) | |
116 | | Antoine Mouchere | [Bronze](https://twitter.com/mouchere_a/status/1428079585757995015) | [Silver](https://twitter.com/mouchere_a/status/1437878692882100233) | [Gold](https://twitter.com/mouchere_a/status/1437878700763230213)|[Platinium](https://www.youtube.com/watch?v=0tuGF8XQPz4) |
117 | | Kyle Brennan | | | | |
118 | | Carlos Panato | [Bronze](https://twitter.com/comedordexis/status/1398203436559130624) | [Silver](https://twitter.com/comedordexis/status/1398203436559130624) | | |
119 | | Felipe Cruz | [Bronze](https://twitter.com/felipecruz/status/1401197347586068482) | [Silver](https://twitter.com/felipecruz/status/1401197973929873410) | | |
120 | | Marian Horgan | [Bronze](https://twitter.com/always_marian/status/1402967317907226635) | [Silver](https://twitter.com/always_marian/status/1402967860171915269) | [Gold](https://twitter.com/always_marian/status/1405978590714413057) | |
121 | | Thibault Jochem | [Bronze](https://twitter.com/Tryumk/status/1414234033668730886) | | | |
122 | | Peter Dongo | [Bronze](https://twitter.com/TheDaN997/status/1415298756757573637) | [Silver](https://twitter.com/TheDaN997/status/1415299162623594499) | [Gold](https://twitter.com/TheDaN997/status/1422856683575988225) | [Platinum](https://twitter.com/TheDaN997/status/1422857244706807810) |
123 | | Iván Gómez | [Bronze](https://twitter.com/ivanusatuiter/status/1401564344656216069) | [Silver](https://twitter.com/ivanusatuiter/status/1416383863606157312) | [Gold](https://twitter.com/ivanusatuiter/status/1416405907752247299) | |
124 | | Dalton Cole | [Bronze](https://twitter.com/LessTechnology/status/1421238078241484801) | [Silver](https://twitter.com/LessTechnology/status/1421241626354192395) | | |
125 |
126 | ## Official growlab apps
127 |
128 | We have three experiments that you can take part in:
129 |
130 | 1) [phototimer - Record images for the timelapse contest](https://github.com/alexellis/phototimer)
131 |
132 | You'll need a Raspberry Pi Zero or greater with a camera module. This is required for the contest.
133 |
134 | 2) [live preview app - Generate and upload a live-preview with sensor data growlab app](/app)
135 |
136 | You'll need a Raspberry Pi Zero or greater with a camera module. If you have a BME280 sensor or BMP280 sensor, then you can add sensor data to the live preview image. This is optional for the contest, but recommended so that you can share with the community.
137 |
138 | 3) [data-logger - Capture environment data and plot on a Grafana dashboard](/data-logger)
139 |
140 | You'll need an RPi 3 or 4 to run the time series database, and dashboard. Then you can attach a sensor to this unit directly, or have a number of other Raspberry Pi Zeros or greater with the BME280 sensor or BMP280 sensor.
141 |
142 | The data-logger does not require you to grow any plants, you can even use it to monitor your home and garden temperatures during the year. This experiment is optional.
143 |
144 | ### Focusing your camera
145 |
146 | Some cameras like the HQ camera are variable focus, the cheaper lenses can also have their glue broken to enable them to close focus.
147 |
148 | Low latency with built-in web-browser:
149 |
150 | ["Raspberry Pi High Quality Camera setup for low-latency Video Conferencing"](http://www.davidhunt.ie/raspberry-pi-high-quality-camera-setup-for-low-latency-video-conferencing/)
151 |
152 | Quick and functional:
153 |
154 | ```bash
155 | # On your Raspberry Pi
156 | raspivid -t 0 -w 1280 -h 720 -fps 10 -o - | nc -lkv4 8080
157 |
158 | # On your computer, enter this URL into VLC under "Network Stream"
159 | # Replace with your Raspberry Pi's IP
160 | tcp/h264://192.168.0.53:8080
161 | ```
162 |
163 | ### Making your timelapse
164 |
165 | If you're using phototimer, then you can run the following with ffmpeg. It's advised that you copy the images to your PC before running the command since the Raspberry Pi Zero is rather slow at crunching videos.
166 |
167 | ```bash
168 | echo $(echo $(find ./Desktop/image/ | sort -V|grep jpg)) | xargs cat | ffmpeg -framerate 10 -f image2pipe -vcodec mjpeg -i - -vcodec libx264 out.mp4
169 | ```
170 |
171 | iMovie is also relatively easy to use, by dragging the images into the timeline and changing the time between images to ~ 0.1s
172 |
173 | Here's a sample from 9th-22nd April you can watch on YouTube:
174 |
175 | [](https://www.youtube.com/watch?v=YiFUVAP0B18)
176 |
177 | [Click here](https://www.youtube.com/watch?v=YiFUVAP0B18) to watch my video timelapse
178 |
179 | ### Extra points and taking things further
180 |
181 | 
182 | > A self-watering system
183 |
184 | * Overlay temperature and humidity data with a Bosch BME280 or BMP280 sensor
185 | * Add a self-watering system with a small pump and capacitive soil sensor
186 | * Try a garden RGB grow-light to give your seeds a little more help
187 | * Experiment with hydroponics
188 | * Install your lab in an outdoor greenhouse, shed or cold-frame
189 | * Use a light sensor / LDR or UV sensor measure available light
190 | * Try a suitable solar panel and battery capacity to run your experiment outdoors or in a room without a socket
191 |
192 | ## Community projects and add-ons
193 |
194 | * phototimer for capturing photos from the RPi camera for a timelapse: [alexellis/phototimer](https://github.com/alexellis/phototimer)
195 | * Richard Gee's seeds2 repo for tweeting and capturing images: [rgee0/seeds2](https://github.com/rgee0/seeds2)
196 | * Sam Perrin's seed-viewer for viewing the images captured with phototimer [sam-perrin/seed-viewer](https://github.com/sam-perrin/seed-viewer)
197 | * Sander Vanhove's plant-monitor using Waylay: [SanderVanhove/plant-monitor](https://github.com/SanderVanhove/plant-monitor)
198 | * Felipe Cruz's repo for displaying sensor readings in an OLED i2c screen: [felipecruz91/growlab-oled](https://github.com/felipecruz91/growlab-oled)
199 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /.ssh/*
2 | /roboto/*
3 | /html/*
4 | /image.jpg
5 | /preview.jpg
6 |
7 | /__pycache__/**
8 |
--------------------------------------------------------------------------------
/app/README.md:
--------------------------------------------------------------------------------
1 | # `#growlab` app for Raspberry Pi
2 |
3 | Record a timelapse and live preview image with sensor data from a Bosch BME280 or BMP280 sensor
4 |
5 | * The BME280 costs slightly more and measures: temperature, humidity and air pressure.
6 | * The BMP can only measure temperature and air pressure.
7 |
8 | 
9 | > Example HTML output which can be synced to GitHub Pages, an S3 bucket, or served directly from the RPi using [inlets](https://docs.inlets.dev/)
10 |
11 | See also: [app roadmap](https://github.com/alexellis/growlab/issues/15)
12 |
13 | ## Assembling the build
14 |
15 | * You'll need a Raspberry Pi Zero W or any other Raspberry Pi.
16 | * An RPi camera connected - any version
17 | * A Bosch BME280 or BMP280 sensor connected to GND, VCC SDL and SCL.
18 |
19 | 
20 | > How to connect the sensor over i2c
21 |
22 | ### Configuring the RPi
23 |
24 | Using `raspi-config`
25 |
26 | * Set your hostname such as `growpi`
27 | * Enable i2c under interfacing options
28 | * Change the password for the `pi` user
29 |
30 | ### Getting started with the software
31 |
32 | Install git, tmux, Python and font pages
33 |
34 | ```bash
35 | sudo apt update -qy && \
36 | sudo apt install -qy python3 \
37 | i2c-tools \
38 | python3-pip \
39 | git \
40 | tmux \
41 | libopenjp2-7 \
42 | libopenjp2-7-dev \
43 | libopenjp2-tools
44 | ```
45 |
46 | > The `libopenjp2` package is for overlaying text on top of the images.
47 |
48 | Clone the repo:
49 |
50 | ```bash
51 | git clone https://github.com/alexellis/growlab
52 | cd growlab/app
53 | ```
54 |
55 | Get the free Roboto font from Google's download page:
56 |
57 | ```bash
58 | curl -sSL https://github.com/googlefonts/roboto/releases/download/v2.138/roboto-unhinted.zip -o roboto.zip \
59 | && unzip roboto.zip -d roboto \
60 | && rm roboto.zip
61 | ```
62 |
63 | Install Python modules with `pip3`:
64 |
65 | ```bash
66 | sudo pip3 install -r requirements.txt
67 | ```
68 |
69 | Capture a test image to determine if you need a horizontal or vertical flip or not:
70 |
71 | ```bash
72 | # On the RPi
73 | raspistill -o growlab.jpg
74 |
75 | # From your PC:
76 | scp pi@growlab.local:~/growlab.jpg Desktop/
77 |
78 | # On a Mac:
79 | open Desktop/growlab.jpg
80 |
81 | # On a Linux desktop:
82 | xdg-open Desktop/growlab.jpg
83 | ```
84 |
85 | If needed, test again with `-vf` or `-hf` to flip the image.
86 |
87 | Edit the `config.json` file if needed and update the flip settings, and width and height to match the file that you got from your test `growlab.jpg` image.
88 |
89 | ```json
90 | {
91 | "images": {
92 | "output_dir": "./images/",
93 | "encoding": "jpeg",
94 | "width": 2592,
95 | "height": 1944,
96 | "image_quality": 70,
97 | "preview_seconds": 1,
98 | "vertical_flip": false,
99 | "horizontal_flip": false,
100 | "interval_seconds": 600
101 | },
102 | "text": {
103 | "colour": {
104 | "red": 255,
105 | "green": 255,
106 | "blue": 255
107 | },
108 | "size": 48
109 | }
110 | }
111 | ```
112 |
113 | Capture a test photo and HTML page. You'll see the files generated in the `html` folder as `image.jpg` and `index.html`.
114 |
115 | ```bash
116 | python3 app.py
117 | ```
118 |
119 | If you have no sensors, then run:
120 |
121 | ```bash
122 | export SENSOR_TYPE=none
123 | python3 app.py
124 | ```
125 |
126 | If you have the BMP280, then run this instead:
127 |
128 | ```bash
129 | export SENSOR_TYPE=bmp280
130 | python3 app.py
131 | ```
132 |
133 | ### Serve a preview with GitHub pages
134 |
135 | Configure GitHub pages and / or a custom domain using the CNAME approach
136 |
137 | Set the folder for serving content to "docs"
138 |
139 | Generate an SSH key:
140 |
141 | ```bash
142 | cd growlab/app
143 | mkdir -p .ssh
144 |
145 | ssh-keygen -f `pwd`/.ssh/id_rsa
146 | ```
147 |
148 | Remove the HTTPS git remote and add a SSH one, changing "alexellis" to your own name.
149 |
150 | ```bash
151 | git remote rm origin
152 | git remote add origin git@github.com:alexellis/growlab.git
153 | ```
154 |
155 | Configure your git user/email:
156 |
157 | ```
158 | git config --global user.name 'YOUR_USERNAME'
159 | git config --global user.email 'YOUR_EMAIL'
160 | ```
161 |
162 | Go to the repo settings and add the deploy key and check *Allow write access*
163 |
164 | Now run the sample.sh bash script. Feel free to view its contents to see how it works
165 |
166 | ```bash
167 | mkdir -p docs
168 | cd growlab/app
169 |
170 | ./sample.sh
171 | ```
172 |
173 | You can also put this into a loop to run every 10 minutes:
174 |
175 | ```bash
176 | while [ true ] ; do ./sample.sh && echo "waiting 10 minutes" && sleep 600 ; done
177 | ```
178 |
179 | ### Install growlab as a service
180 |
181 | In the `growlab.service` file change the line where says `Environment="SENSOR_TYPE=none"` if you are using a sensor
182 | then change for the sensor you have, ie. if you have BMP280 change for `Environment="SENSOR_TYPE=bmp280"`
183 |
184 | Install the systemd service:
185 |
186 | ```bash
187 | chmod +x app.py
188 | sudo cp growlab.service /etc/systemd/system
189 | sudo systemctl enable growlab
190 | sudo systemctl start growlab
191 | ```
192 |
--------------------------------------------------------------------------------
/app/app.py:
--------------------------------------------------------------------------------
1 | #!/bin/python3
2 |
3 | import json
4 | import os, sys
5 | from sensors import growbme280, growbmp280, grownosensor
6 | from camera import camera
7 | from specimen import specimen
8 |
9 | if __name__ == "__main__":
10 | print("Starting growlab")
11 |
12 | config = {}
13 | try:
14 | with open("./config.json") as f:
15 | config = json.loads(f.read())
16 | except Exception as e:
17 | sys.stderr.write("Error: {}".format(e))
18 | sys.exit(1)
19 |
20 | print("Loaded config, saving images every {} seconds to {}".format( config["images"]["interval_seconds"], config["images"]["output_directory"]))
21 |
22 | sensor = None
23 | sensor_type = os.getenv("SENSOR_TYPE", "bme280")
24 | if sensor_type == "bme280":
25 | sensor = growbme280()
26 | if sensor_type == "bmp280":
27 | sensor = growbmp280()
28 | elif sensor_type == "none":
29 | sensor = grownosensor()
30 |
31 | readings = sensor.get_readings()
32 | print(readings)
33 |
34 | cam = camera(config["images"])
35 | frame = cam.get_frame()
36 |
37 | pwd = os.getcwd()
38 | output_path = pwd + "/html"
39 |
40 | try:
41 | os.mkdir(output_path)
42 | except:
43 | pass
44 |
45 | spec = specimen(config["text"], config["images"])
46 | spec.save_image("{}/image.jpg".format(pwd), frame, readings)
47 |
48 | spec.save_html("{}/image.jpg".format(pwd), output_path, readings)
49 |
--------------------------------------------------------------------------------
/app/camera.py:
--------------------------------------------------------------------------------
1 | import picamera
2 | import io
3 | import time
4 |
5 | class camera:
6 | def __init__(self, camera_opts):
7 | self.camera_opts = camera_opts
8 |
9 | def get_frame(self):
10 | stream = io.BytesIO()
11 | with picamera.PiCamera() as camera:
12 | camera.start_preview()
13 | camera.vflip = self.camera_opts["vertical_flip"]
14 | camera.hflip = self.camera_opts["horizontal_flip"]
15 | camera.meter_mode = self.camera_opts["meter_mode"]
16 | camera.exposure_mode = "auto"
17 | camera.resolution = (self.camera_opts["width"], self.camera_opts["height"])
18 | # Camera warm-up time
19 | time.sleep(self.camera_opts["preview_seconds"])
20 | camera.capture(stream, format=self.camera_opts["encoding"], quality=self.camera_opts["image_quality"])
21 |
22 | return stream
23 |
--------------------------------------------------------------------------------
/app/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "images": {
3 | "output_directory": "./images/",
4 | "encoding": "jpeg",
5 | "width": 2592,
6 | "height": 1944,
7 | "image_quality": 70,
8 | "preview_seconds": 1,
9 | "vertical_flip": false,
10 | "horizontal_flip": false,
11 | "meter_mode": "matrix",
12 | "interval_seconds": 600
13 | },
14 | "text": {
15 | "colour": {
16 | "red": 255,
17 | "green": 255,
18 | "blue": 255
19 | },
20 | "size": 48
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/app/growlab.service:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=Growlab
3 | After=network.target
4 |
5 | [Service]
6 | Type=simple
7 | User=pi
8 | Group=pi
9 | Restart=always
10 |
11 | # Every 600 seconds (or 10 minutes)
12 | RestartSec=600
13 |
14 | StartLimitInterval=0
15 |
16 | # Sensor type: "none", "BME280" or "BMP280"
17 | Environment="SENSOR_TYPE=BME280"
18 | WorkingDirectory=/home/pi/growlab/app
19 | ExecStart=/home/pi/growlab/app/sample.sh
20 |
21 | [Install]
22 | WantedBy=multi-user.target
23 |
--------------------------------------------------------------------------------
/app/index.jinja:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Welcome to your live monitoring33 |
Generated with the growlab app
37 | 38 |Reading | 44 |Value | 45 |
---|---|
Time | 50 |{{ time }} | 51 |
Temperature | 54 |{{ temperature }} | 55 |
Humidity | 58 |{{ humidity }} | 59 |
Pressure | 62 |{{ pressure }} | 63 |