npm package: @peapodtech/peapodos
Description: Main software for PeaPod.
Author: PeaPod Technologies
Latest version: 0.1.1

# PeaPod OS <!-- omit in toc -->

[![issuesopen](https://img.shields.io/github/issues/PeaPodTechnologies/peapod)](https://github.com/PeaPodTech/PeaPod/issues) [![issuesclosed](https://img.shields.io/github/issues-closed/PeaPodTechnologies/peapod)](https://github.com/PeaPodTech/PeaPod/issues?q=is%3Aissue+is%3Aclosed) [![opensource](https://img.shields.io/badge/open-source-red)](https://github.com/PeaPodTechnologies/PeaPod/issues?q=is%3Aopen+is%3Aissue+label%3A%22Status%3A+Open%22) ![coffee](https://img.shields.io/badge/powered%20by-coffee-brown) [![24/7](https://img.shields.io/badge/Eat,%20Sleep,-PeaPod-darkgreen)](https://www.youtube.com/watch?v=2zWv9JC5G3w) [![FLDSMDFR](https://img.shields.io/badge/The-FLDSMDFR-orange)](https://www.youtube.com/watch?v=k8xFbWLUDoQ)

<!-- TODO: Build Statuses? -->
 
Main software for PeaPod.

A cloud-connected isolated and automated plant growth environment, able to generate any environment from a combination of independent environment parameters. 

Designed as both a hassle-free food production system and a research tool for precise and distributed mapping of the plant-environment relationship.

***
### Table of Contents
- [Background](#background)
- [Production](#production)
    - [Setting Up Raspberry Pi](#setting-up-raspberry-pi)
- [Development](#development)
    - [Arduino Test Suite](#arduino-test-suite)
    - [Raspberry Pi Serial Testing](#raspberry-pi-serial-testing)
    - [Build from Source](#build-from-source)
***

# Background

<img src="assets/control_flow.png" width=60% style="border: 5px solid #333"/>

***

# Production

### Setting Up Raspberry Pi

The following are performed on a computer:

1. Format a microSD card (>=4GB) with a single FAT partition.
2. Download the Raspberry Pi Imager [(Download)](https://www.raspberrypi.com/software/).
3. Flash the SD card with a *Raspberry Pi OS Lite* image.

> Note: In Future, a custom PeaPod Raspberry Pi OS Lite image will be released with steps 5, 6, and 12 already complete.

4. Plug in a keyboard and display, insert the microSD card, and power the Raspberry Pi device.

The following are performed on the Raspberry Pi, with a keyboard and monitor:

5. Login with the default username (`pi`) and password (`raspberry`).
6. Execute `sudo raspi-config` and perform these steps to setup the Pi:
   1. *System Options > Wireless Lan* - Setup WiFi and connect to the Internet
   2. *System Options > Hostname* - Set a unique host name (`e.g. john-peapod`)
   3. *System Options > Boot/Auto Login* - Select `Console Autologin`
   4. *Interface Options > SSH* - `Enable` SSH Server
   5. *Interface Options > Serial Port* - `Disable` serial login shell, but `Enable` the serial port hardware
   6. *Performance Options > GPU Memory* - 256 (MB)
   7. *Localisation Options > Locale* (i.e. `en_US.UTF-8`)
   8. *Localisation Options > Timezone* (i.e. `US` > `Eastern`)
   9. *Localisation Options > Keyboard* (i.e. `Generic 105-key` > `English (US)` > `Default` > `No compose key`)
   10. Optional: *Advanced Options > Expand Filesystem*
   11. Reboot to save: `sudo reboot` 

> You can now SSH into the Raspberry Pi to perform the rest of the setup (`ssh pi@peapod.local`, or with VS Code)

> Note: In Future, steps 7-11 will be performed at runtime.
7. Update Packages:
     1. Update package listings, upgrade existing packages: `sudo apt-get update && sudo apt-get upgrade -y`
     2. Install Node.JS, the Node package manager, and *avrdude*: `sudo apt-get install -y nodejs npm avrdude python3-venv` (could take a while)
     3. Install main software package: `sudo npm i -g @peapodtech/peapodos --save`

<!-- 8. Install and configure the Arduino CLI:
    1. Install with `curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | sh`. Successful output ends with something like:
      ```
      arduino-cli  Version: 0.21.0 Commit: 10107d24 Date: 2022-02-08T15:05:43Z installed successfully in /home/pi/bin
      ```
    2. Open `nano ~/.bashrc` and add this line to the bottom: `export PATH=$PATH:/home/pi/bin` (*Ctrl-O* to save, *Ctrl-X* to exit)
    3. Reboot to reset the path: `sudo reboot`
    4. Perform initial configuration: `arduino-cli config init`
    5. Update the list of cores: `arduino-cli core update-index`
    6. Install the AVR cores (incl. Arduino Nano/ATMega328P): `arduino-cli core install arduino:avr` -->

8. Install PlatformIO Core with `python3 -c "$(curl -fsSL https://raw.githubusercontent.com/platformio/platformio/master/scripts/get-platformio.py)"`

9. Create a custom configuration file for the AVR flash utility *avrdude* to be able to program the Arduino Nano via ICSP over the Raspberry Pi's GPIO pins:
   1.  Create a local copy of the *avrdude* configuration file with `cp /etc/avrdude.conf ~/software/microcontroller/avrdude_gpio.conf`, then modify your copy with `nano ~/software/microcontroller/avrdude_gpio.conf`. Copy the following to the end of the file:

       ```
       # Raspberry Pi GPIO configuration for avrdude.
       programmer
         id    = "peapod";
         desc  = "Use the Linux sysfs interface to bitbang GPIO lines";
         type  = "linuxgpio";
         reset = 5;
         sck   = 6;
         mosi  = 12;
         miso  = 13;
       ;
       ```
       (*Ctrl-O* to save, *Ctrl-X* to exit)
   2.  Verify the configuration and connection to the Arduino with `sudo avrdude -p m328p -C/avrdude_gpio.conf -c peapod -v`. A successful output should look something like:
       ```
       avrdude: Version 6.3-20171130
            Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
            Copyright (c) 2007-2014 Joerg Wunsch

            System wide configuration file is "/home/pi/avrdude_gpio.conf"
            User configuration file is "/root/.avrduderc"
            User configuration file does not exist or is not a regular file, skipping

            Using Port                    : unknown
            Using Programmer              : peapod
            AVR Part                      : ATmega328P
            Chip Erase delay              : 9000 us
            PAGEL                         : PD7
            BS2                           : PC2
            RESET disposition             : dedicated
            RETRY pulse                   : SCK
            serial program mode           : yes
            parallel program mode         : yes
            Timeout                       : 200
            StabDelay                     : 100
            CmdexeDelay                   : 25
            SyncLoops                     : 32
            ByteDelay                     : 0
            PollIndex                     : 3
            PollValue                     : 0x53
            Memory Detail                 :

                                     Block Poll               Page                       Polled
              Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
              ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
              eeprom        65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff
              flash         65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
              lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
              hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
              efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
              lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
              calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
              signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

            Programmer Type : linuxgpio
            Description     : Use the Linux sysfs interface to bitbang GPIO lines
            Pin assignment  : /sys/class/gpio/gpio{n}
              RESET   =  8
              SCK     =  11
              MOSI    =  10
              MISO    =  9

       avrdude: AVR device initialized and ready to accept instructions

       Reading | ################################################## | 100% 0.00s

       avrdude: Device signature = 0x1e950f (probably m328p)
       avrdude: safemode: lfuse reads as FF
       avrdude: safemode: hfuse reads as DA
       avrdude: safemode: efuse reads as FD

       avrdude: safemode: lfuse reads as FF
       avrdude: safemode: hfuse reads as DA
       avrdude: safemode: efuse reads as FD
       avrdude: safemode: Fuses OK (E:FD, H:DA, L:FF)

       avrdude done.  Thank you.
       ```

10. Perform first-time flashing with `~/.platformio/penv/bin/platformio run -d ~/software/microcontroller/ --target upload`

11. Edit the `sudoers` file to allow `avrdude` to be executed using `sudo` *without a password*:
    1.  Open the `sudoers` file: `sudo visudo`
    2.  Add the following line to the end (assuming your username is `pi`, the hostname is `peapod`, and the `avrdude` binary is located at `/usr/bin/avrdude`):
        
        `pi peapod = (root) NOPASSWD: /usr/bin/avrdude`
        
        (*Ctrl-O* to save, *Ctrl-X* to exit; *avrdude* can be located with `whereis avrdude`)

12. Install the *UV4L* camera library:
    1.  `curl https://www.linux-projects.org/listing/uv4l_repo/lpkey.asc | sudo apt-key add -`
    2.  Add the package listings: `echo "deb https://www.linux-projects.org/listing/uv4l_repo/raspbian/stretch stretch main" | sudo tee /etc/apt/sources.list.d/uv4l.list`
    3.  Update packages: `sudo apt-get update`
    4.  Install the core library, the Raspberry Pi driver, extra scripts, adn WebRTC support: `sudo apt-get install uv4l uv4l-raspicam uv4l-raspicam-extras uv4l-webrtc-armv6`

13. Populate a `.env` file with Firebase and Google and/or GitHub auth keys (a template is provided as `.env.template`), as well as the field `SERIALPORT="/dev/ttyS0"` (Raspberry Pi Zero 2 W GPIO mini-UART).

14. Run the main program by executing `peapodos`.

<!-- https://github.com/nebrius/raspi-io/wiki/Getting-a-Raspberry-Pi-ready-for-NodeBots#configuring-your-app-to-start-on-startup -->
# Development

### Arduino Test Suite

To run the PlatformIO Arduino test suite: `~/.platformio/penv/bin/platformio test -d ~/software/microcontroller/`

### Raspberry Pi Serial Testing

To test the GPIO serial port (`/dev/ttyS0`), connect GPIO pins 8 and 10 (TX and RX) and execute the following:
1. Install the Python package manager *pip*: `sudo apt-get install pip`
2. Install the Serial package *pyserial*: `pip install pyserial`
3. Execute the test script: `python ~/PeaPod/software/tests/serialTest.py`

Correct output should look like:

```
Serial port '/dev/ttyS0' ready for test:
Sent 20 bytes: 'Testing Raspberry Pi GPIO serial port ...'
Received 20 bytes: 'Testing Raspberry Pi GPIO serial port ...'
Port '/dev/ttyS0' is is setup correctly!
```

### Build from Source

1. Install TypeScript language support and compiler, as well as a Node build tool: `sudo npm install -g typescript`
2. Clone source
3. Navigate to `software/` folder
4. Build the `serialport` package from source: `sudo npm install serialport --unsafe-perm --build-from-source`
5. Install all other Node dependencies: `npm i`
6. Compile the source with `tsc` and execute with `node .`