# Fenceless Grazing System API Server This is the repository for the API server component of the Fenceless Grazing System. This server is written in Python using the Flask microframework, and uses the SQLAlchemy ORM to interact with the SQLite database. ## Getting the Dependencies The API server depends on several packages to operate properly, which will likely not be installed by default on your system. There are two ways to get the required dependencies: using Python's `virtualenv` (standard in the Python ecosystem), or using Nix (only if you are into that kind of thing). ### Getting the Dependencies with `virtualenv` First, create a virtual environment (this only has to be done once): ```Bash virtualenv venv ``` Once the virtual environment has been created, activate it using the following command: ```Bash source venv/bin/activate ``` This effectively creates an independent Python environment, into which you can install packages without affecting your entire system. You can now install the packages from the `requirements.txt` file: ```Bash pip install -r requirements.txt ``` With this, you should have all the necessary dependencies. ### Getting the Dependencies with Nix Below is the Nix expression I use daily to work on this application: ```Nix with import {}; mkShell { buildInputs = [ (python3.withPackages (ps: with ps; [ flask flask_sqlalchemy pyjwt bcrypt geopy pip ])) ]; } ``` Note that some packages (`geopy` in particular) are currently unstable; the expressions from stable Nixpkgs may not provide a working derivation. When using the `nixpkgs-unstable`, I have no such issues. ## Setting Up The application requires the `DB_LOC` environment variable to be set to indicate the location of the database that the server should use: ```Bash export DB_LOC=database.sqlite ``` Additionally, Flask uses the `FLASK_APP` environment variable to determine the entry point of a web application ```Bash # Here, fgs represents the fgs/ directory in the repository's root. export FLASK_APP=fgs ``` Finally, on first run, you need to create the tables in the application's database. This can be done as follows: ```Python flask shell # Imports, among other things, the db variable, which is the handle for the SQLAlchemy ORM. from fgs import * # SQLAlchemy needs to be aware of the various tables in our database from fgs.model import * # Creates all tables db.create_all() # It also helps to set up a user and a couple of collars: user = User(username='user', password='password') collar1 = Collar(name='Sample Collar', active=True) collar2 = Collar(name='Another Collar', active=True) # To add the newly created objects to the database, use # db.session.add and db.session.commit db.session.add(user) db.session.add(collar1) db.session.add(collar2) db.session.commit() # You can now press Ctrl-D to exit the Flask shell. ``` Once the database has been created, you can start the server with: ```Bash flask run ``` ## Next Steps Once the server is up and running, consider setting up the [app](https://dev.danilafe.com/CS-46X/app), which is able interact with this API server. Additionally, check out the [cow description language](https://dev.danilafe.com/CS-46X/cdl) if you want to generate mock data for the API server's database.