Skip to content

josueisaihs/drones

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

34 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Drone Delivery

There is a major new technology that is destined to be a disruptive force in the field of transportation: the drone. Just as the mobile phone allowed developing countries to leapfrog older technologies for personal communication, the drone has the potential to leapfrog traditional transportation infrastructure.

Useful drone functions include delivery of small items that are (urgently) needed in locations with difficult access.

We have a fleet of 10 drones. A drone is capable of carrying devices, other than cameras, and capable of delivering small loads. For our use case the load is medications.

Features

  • Registering a Drone
  • Loading drone with medications items
  • Checking loaded medication items for a given drone
  • Checking available drones for loading
  • Check drone battery level for a given drone

Tech

Drone Delivery uses a number of projects to work properly:

And of course Drone Delivery itself is open source with a public on GitHub.

Installation

Drone Delivery requires to run:

Dependency Version
Celery 5.2.3
Django 4.0.1
Django Filter 21.1
Django REST Framework 3.13.1
Django Simple History 3.0.0
Python 3.8.8
Redis 4.1.0

Install


Linux and Mac

Clone github repository:

git clone https://github.com/josueisaihs/drones

Create virtual environment and activate it:

cd drones
python3 -m venv env/
source env/bin/activate

Install dependencies:

cd src
pip install -r requirements.txt

Create the database file and create the models in the database:

cd drones
mkdir db
touch db/db.sqlite3
./manage.py migrate

Load data to test the app

Create data tot test the app:

./manage.py create_data --all

(optional) Added custom commands to add and remove data for testing the app. The create command options are:

./manage.py create_data [--all] [--drone] [--medications] [--package]
optional arguments:
--drone         Create 10 drones with random data 
--medication    Create medications with random data
--package       Create packets with random data
--user          Create user, username: "admin" and password: "password"
--all           Create all the above data

The remove command options are:

./manage.py clean_data [--all] [--drone] [--medications] [--package] [--delivery]
optional arguments:
--drone         Remove drones
--medication    Remove medications
--package       Remove packets
--delivery      Remove delivery packages
--all           Remove all data

The battery charge command options are:

./manage.py charge_batteries [--random]
optional arguments:
--random         Provides a random value between 10 and 100 for the battery status

Charge the drones that are in Low Battery and their state is other than IDLE, to a state of charge of 100%.

Settings

Must set the following fields in the settings.py:

DRONE_DELIVERY_CONFIG = {
    "MAX_WEIGHT": 500.0,
    "LOW_BATTERY": 25.0,
    "BATTERY_STATUS_UPDATE_TIME": 1,
}
Key Description
MAX_WEIGHT Maximum capacity that supports a drone
LOW_BATTERY Indicates value to decide if the battery is low
BATTERY_STATUS_UPDATE_TIME Time in minutes to run the drone battery level update task

Run Server

Finally, run the following to launch the local server

./manage.py runserver

Redis

First download Redis and read the README file. Open the downloaded folder in the another terminal and simply run:

make

After building Redis, it is a good idea to test it using:

make test

To run Redis with the default configuration, just type:

cd src
./redis-server

You can use redis-cli to play with Redis. Start a redis-server instance, then in another terminal try the following:

cd src
./redis-cli
redis> ping
PONG
redis>quit

Celery

Open a new instance of the terminal in the project's containing folder to initialize celery:

source env/bin/activate
cd src/drones
celery -A drones worker -l info

And open an another instance of the terminal in the project's containing folder and run the following:

source env/bin/activate
cd src/drones
celery -A drones beat -l info

Test


To run the tests, try the following:

cd src/drones
./migrate test

API


Drones

The serial number can only have up to 100 characters. A drone can load up to MAX_WEIGHT, configured in the settings.py. The states IDLE, LOADING, LOADED, DELIVERING, DELIVERED, RETURNING. A drone can only receive a charge if it is in IDLE state

To create, retrieve, update and destroy drones:

Create and List http://localhost:8000/drone-delivery/api/drone/list/

Retrieve, Update, Destroy http://localhost:8000/drone-delivery/api/drone/slug/detail/

JSON format that accepts to create, retrieve, update and destroy:

{
    "serial_number": <String>,
    "model": <String: Cruiserweight, Lightweight, "Middleweight, Cruiserweight, Heavyweight>,
    "weight_limit": <Float>,
    "battery_capacity": <Int>,
    "state": <String: IDLE, LOADING, LOADED, DELIVERING, DELIVERED, RETURNING>
}

JSON format to list results:

{
    "id": <Int>,
    "slug": <String>,
    "serial_number": <String>,
    "model": <String: Cruiserweight, Lightweight, "Middleweight, Cruiserweight, Heavyweight>,
    "weight_limit": <Float>,
    "battery_capacity": <Int>,
    "state": <String: IDLE, LOADING, LOADED, DELIVERING, DELIVERED, RETURNING>
}

Medications

The name field Allow only letters [A-Za-z], numbers [0-9], "-" and underscore The code field allow only upper case letters [A-Z], underscore and numbers [0-9] A medication can have a maximum weight of MAX_WEIGHT, configured in the settings.py.

To create, retrieve, update and destroy medications:

Create and List http://localhost:8000/drone-delivery/api/medication/list/

Retrieve, Update, Destroy http://localhost:8000/drone-delivery/api/medication/slug/detail/

JSON format that accepts to create, retrieve, update and destroy:

{
    "name": <String>,
    "weight": <Float>,
    "code": <String>,
    "image": <Image>
}

JSON format to list results:

{
    "id": <Int>,
    "slug": <Slug>,
    "name": <String>,
    "weight": <Float>,
    "code": <String>,
    "image": <URL>
}

Packages

A package is a certain medication with the respective quantity. A package can have a maximum weight of MAX_WEIGHT, configured in the settings.py.

To create, retrieve, update and destroy medications:

Create and List http://localhost:8000/drone-delivery/api/package/list/

Retrieve, Update, Destroy http://localhost:8000/drone-delivery/api/package/slug/detail/

JSON format that accepts to create, retrieve, update and destroy:

{
    "medication": <Medication.pk>,
    "qty": <Int>
}

JSON format to list results:

{
    "id": <Int>,
    "slug": <Slug>,
    "medication": {
        "name": <String>,
        "slug": <Slug>
    },
    "qty": <Int>,
    "created": "%y-%m-%d %H:%M",
    "weight": <Float>
}

Deliveries Packages

A delivery package is to assign a drone a certain number of packages, as long as the drone is capable of supporting the weight of the load. A drone is only available for loading when its battery is greater than LOW_BATTERY, configured in the settings, and it is in IDLE state.

To create, retrieve, update and destroy deliveries packages:

Create and List http://localhost:8000/drone-delivery/api/delivery/list/

Retrieve, Update, Destroy http://localhost:8000/drone-delivery/api/delivery/slug/detail/

JSON format that accepts to create, retrieve, update and destroy:

{
    "drone": <Drone.pk>,
    "package": [<Package.pk>, <Package.pk>, ..., <Package.pk>]
}

JSON format to list results:

{
    "slug": <Slug>,
    "drone": {
        "slug": <Slug>, 
        "serial_number": <String>, 
        "weight_limit": <Float>, 
        "battery_capacity": <Int>
    },
    "package": {
        "items": [
            {
                "id": <Int>,
                "slug": <Slug>, 
                "weight": <Float>, 
                "qty": <Int>,
                "medication": {
                    "slug": <Slug>,
                    "name": <String>
                }
            }
        ],
        "weight": <Float>
    }
}

Examples


Below is the sequence to create a delivery order.

curl -X GET http://127.0.0.1:8000/drone-delivery/api/drone/list/

Using the admin and password credentials a drone is registered:

curl -u 'admin:password' -d '{"serial_number": "456345647", "model": "Cruiserweight", "weight_limit": 400.0, "battery_capacity": 98, "state": "IDLE"}' -H "Content-Type: application/json" -X POST http://127.0.0.1:8000/drone-delivery/api/drone/list/
{"id":11,"slug":"456345647","serial_number":"456345647","model":"Cruiserweight","weight_limit":"400.00","battery_capacity":98,"state":"IDLE"}

Now the package should be created:

curl -u 'admin:password' -d '{"medication": 1, "qty": 1}' -H "Content-Type: application/json" -X POST http://127.0.0.1:8000/drone-delivery/api/package/list/
{"id":11,"slug":"acetaminophen-1","medication":{"name":"Acetaminophen","slug":"acetaminophen-lt0u94wqy8"},"qty":1,"created":"2022-01-17 01:49","weight":4.0}%  
curl -u 'admin:password' -d '{"medication": 2, "qty": 1}' -H "Content-Type: application/json" -X POST http://127.0.0.1:8000/drone-delivery/api/package/list/
{"id":12,"slug":"adenosine-1","medication":{"name":"Adenosine","slug":"adenosine-qkd8kg"},"qty":1,"created":"2022-01-17 01:50","weight":7.0}%          

Finally, the drone is assigned (id = 11) and the packages created (id = 11, id = 12) to form the delivery package:

curl -u 'admin:password' -d '{"drone": 11, "package": [11, 12]}' -H "Content-Type: application/json" -X POST http://127.0.0.1:8000/drone-delivery/api/delivery/list/
{"slug":"456345647","drone":{"slug":"456345647","serial_number":456345647.0,"weight_limit":400.0,"battery_capacity":98},"package":{"items":[{"slug":"acetaminophen-1","weight":4.0,"qty":1,"medication":{"slug":"acetaminophen-lt0u94wqy8","name":"Acetaminophen"}},{"slug":"adenosine-1","weight":7.0,"qty":1,"medication":{"slug":"adenosine-qkd8kg","name":"Adenosine"}}],"weight":11.0}}%

Admin


Django's admin view is also available. Use the admin and password credentials to authenticate.