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.
- 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
Drone Delivery uses a number of projects to work properly:
- [Python] - https://www.python.org
- [Django] - https://docs.djangoproject.com
- [Django REST framework] - https://www.django-rest-framework.org/
- [Redis] - https://redis.io/
- [Celery] - https://docs.celeryproject.org
- [django-simple-history] - https://django-simple-history.readthedocs.io/en/latest/index.html
And of course Drone Delivery itself is open source with a public on GitHub.
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 |
Clone github repository:
git clone https://github.com/josueisaihs/dronesCreate virtual environment and activate it:
cd drones
python3 -m venv env/
source env/bin/activateInstall dependencies:
cd src
pip install -r requirements.txtCreate the database file and create the models in the database:
cd drones
mkdir db
touch db/db.sqlite3
./manage.py migrateCreate 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 dataThe 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 dataThe battery charge command options are:
./manage.py charge_batteries [--random]
optional arguments:
--random Provides a random value between 10 and 100 for the battery statusCharge the drones that are in Low Battery and their state is other than IDLE, to a state of charge of 100%.
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 |
Finally, run the following to launch the local server
./manage.py runserverFirst download Redis and read the README file.
Open the downloaded folder in the another terminal and simply run:
makeAfter building Redis, it is a good idea to test it using:
make testTo run Redis with the default configuration, just type:
cd src
./redis-serverYou 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>quitOpen 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 infoAnd 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 infoTo run the tests, try the following:
cd src/drones
./migrate testThe 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>
}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>
}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>
}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>
}
}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}}%Django's admin view is also available. Use the admin and password credentials to authenticate.