diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..7f592ce --- /dev/null +++ b/.travis.yml @@ -0,0 +1,47 @@ +language: python +dist: bionic + +services: + - docker + +before_install: + - pip -q install -U docker-compose + +simulator: &simulator + stage: simulator + install: + - docker-compose -f docker/docker-compose.yml pull + - docker-compose -f docker/docker-compose.yml build + before_script: + - docker-compose -f docker/docker-compose.yml -f docker/edge/docker-compose.edge.yml up -d + - DOCKER_HOST='127.0.0.1:22375' docker-compose -f docker/docker-compose.yml -f docker/edge/docker-compose.edge.yml pull + - DOCKER_HOST='127.0.0.1:22375' docker-compose -f docker/docker-compose.yml -f docker/edge/docker-compose.edge.yml build + script: + - sleep 5 # warm-up + - sed -i 's/# IOT_SERIAL/IOT_SERIAL/g' docker/edge/docker-compose.modules.yml + - DOCKER_HOST='127.0.0.1:22375' docker-compose -f docker/edge/docker-compose.modules.yml up -d + - sleep 30 # collect some telemetry + - curl -sf http://localhost/telemetry/${IOT_TL}1234/last/ + +jobs: + include: + - stage: build + before_script: + - echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin + script: + - docker-compose -f docker/docker-compose.yml build + - docker push daniviga/bite + - docker push daniviga/ntpd + if: branch = master + - stage: django + install: + - docker-compose -f docker/docker-compose.yml pull + - docker-compose -f docker/docker-compose.yml build + before_script: + - docker-compose -f docker/docker-compose.yml up -d + script: + - docker-compose -f docker/docker-compose.yml exec bite python manage.py test + - <<: *simulator + env: IOT_TL=http + - <<: *simulator + env: IOT_TL=mqtt diff --git a/README.md b/README.md index 683f84c..8b4838e 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,123 @@ # BITE - Basic/IoT/Example Playing with IoT + +This project is for educational purposes only. It does not implement any authentication and/or encryption protocol, so it is not suitable for real production. + +## Installation + +### Requirements + +- `docker-ce` or `moby` +- `docker-compose` + +The project is compatible with Docker for Windows (using Linux executors), but it is advised to directly use a minimal Linux VM instead (via the preferred hypervisor). + +The application stack is composed by the following components: + +- [Django](https://www.djangoproject.com/) with [Django REST framework](https://www.django-rest-framework.org/) web application (running via `gunicorn` in production mode) + - `mqtt-to-db` custom daemon to dump telemetry into the timeseries database + - telemetry payload is stored as json object (via PostgreSQL JSON data type) +- [Timescale](https://www.timescale.com/) DB, a [PostgreSQL](https://www.postgresql.org/) database with a timeseries extension +- [Mosquitto](https://mosquitto.org/) MQTT broker (see alternatives below) +- [Nginx](http://nginx.org/) as ingress for HTTP (see alternative below) +- [Chrony](https://chrony.tuxfamily.org/) as NTP server (with optional `MD5` encryption) + +## Deployment + +### Development + +```bash +docker-compose -f docker/docker-compose.yml up -d [--scale {bite,mqtt-to-db)=N] +``` +It exposes: +- `http://localhost:80` (HTTP) +- `tcp://localhost:1883` (MQTT) +- `udp://localhost:123` (NTP) + +Django runs with `DEBUG = True` and `SKIP_WHITELIST = True` + +### Development with direct access to services + +```bash +docker-compose -f docker/docker-compose.yml -f docker-compose.dev.yml up -d [--scale {bite,mqtt-to-db)=N] +``` +It exposes: +- `http://localhost:80` (HTTP) +- `http://localhost:8080` (Django's `runserver`) +- `tcp://localhost:1883` (MQTT) +- `udp://localhost:123` (NTP) +- `tcp://localhost:5432` (PostgreSQL/Timescale) + +Django runs with `DEBUG = True` and `SKIP_WHITELIST = True` + +### Production + +```bash +docker-compose -f docker/docker-compose.yml -f docker-compose.prod.yml up -d [--scale {bite,mqtt-to-db)=N] +``` +It exposes: +- `http://localhost:80` (HTTP) +- `tcp://localhost:1883` (MQTT) +- `udp://localhost:123` (NTP) + +Django runs with `DEBUG = False` and `SKIP_WHITELIST = False` + +## Extra features + +The project provides multiple modules that can be combined with the fore-mentioned configurations. + +### Traefik + +To use [Traefik](https://containo.us/traefik/) instead of Nginx use: +```bash +docker-compose -f docker/docker-compose.yml up -f docker/ingress/docker-compose.traefik.yml -d +``` + +### VerneMQ + +A ~8x memory usage can be expected compared to Mosquitto. + +To use [VerneMQ](https://vernemq.com/) instead of Mosquitto use: +```bash +docker-compose -f docker/docker-compose.yml up -f docker/mqtt/docker-compose.vernemq.yml -d +``` + +### RabbitMQ + +RabbitMQ does provides AMQP protocol too, but ingestion on the application side is not implemented yet. +A ~10x memory usage can be expected compared to Mosquitto. + +To use [RabbitMQ](https://www.rabbitmq.com/) (with the MQTT plugin enabled) instead of Mosquitto use: +```bash +docker-compose -f docker/docker-compose.yml up -f docker/mqtt/docker-compose.rabbitmq.yml -d +``` + +## EDGE gateway simulation (via dind) + +An EDGE gateway, with containers as modules, may be simulated via dind (docker-in-docker). + +### Start the EDGE + +```bash +docker-compose -f docker/docker-compose.yml up -f docker/edge/docker-compose.edge.yml -d +``` + +### Run the modules inside the EDGE + +```bash +DOCKER_HOST='127.0.0.1:22375' docker-compose -f docker-compose.modules.yml up -d [--scale {device-http,device-mqtt}=N] +``` + +## Ardunio + +A simple Arduino UNO sketch is provided in the `arduino/tempLightSensor` folder. The sketch reads temperature and light from sensors. The simple schematic is: + +![tempLightSensor](./arduino/tempLightSensor/tempLightSensor.svg) + +The sketch does require an Ethernet shield and a bunch of libraries which are available as git submodules under `arduino/libraries`. +Be advised that some libraries (notably the NTP one) are customized. + +Configuration parameters are stored and retrieved from the EEPROM. An helper sketch to update the EEPROM is available under `arduino/eeprom_prog` + +An `ESP32` board (or similar Arduino) may be used, with some adaptions, too. diff --git a/arduino/tempLightSensor/tempLightSensor.fzz b/arduino/tempLightSensor/tempLightSensor.fzz new file mode 100644 index 0000000..ea9a274 Binary files /dev/null and b/arduino/tempLightSensor/tempLightSensor.fzz differ diff --git a/arduino/tempLightSensor/tempLightSensor.svg b/arduino/tempLightSensor/tempLightSensor.svg new file mode 100644 index 0000000..476b030 --- /dev/null +++ b/arduino/tempLightSensor/tempLightSensor.svg @@ -0,0 +1,5175 @@ + + + + + + + + + + + + + + + + + + + + 7 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + 1 + + + 5 + + + 5 + + + 10 + + + 10 + + + 15 + + + 15 + + + 20 + + + 20 + + + 25 + + + 25 + + + 30 + + + 30 + + + A + + + A + + + B + + + B + + + C + + + C + + + D + + + D + + + E + + + E + + + F + + + F + + + G + + + G + + + H + + + H + + + I + + + I + + + J + + + J + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + layer 21 + + text:MADE IN + + + text:ITALY + + + text:Prototype + + + text:Limited + + + text:Edition + + + + + + + + + + + + + 13 + + + + + + + + + + + + + + + + + + + + + + + 12 + + + + + + + + + + + + + + + + + + + + + + + 11 + + + + + + + + + + + + + + + + + + + + + + + ETH + + + + + + + + + + + + + + + + + + + + + + + 9 + + + + + + + + + + + + + + + + + + + + + + + 8 + + + + + + + + + + + + + + + + + + + + + + + 7 + + + + + + + + + + + + + + + + + + + + + + + 6 + + + + + + + + + + + + + + + + + + + + + + + 5 + + + + + + + + + + + + + + + + + + + + + + + SDCS + + + + + + + + + + + + + + + + + + + + + + + 3 + + + + + + + + + + + + + + + + + + + + + + + 2 + + + + + + + + + + + + + element:C1 + + package:C0603-ROUND + + + + element:C2 + + package:C0603-ROUND + + + + element:C3 + + package:C0603-ROUND + + + + element:C4 + + package:C0603-ROUND + + + + element:C5 + + package:C0603-ROUND + + + + element:C6 + + package:C0603-ROUND + + + + element:C7 + + package:C0603-ROUND + + + + element:C8 + + package:C0603-ROUND + + + + element:C9 + + package:C0603-ROUND + + + + element:C11 + + package:C0603-ROUND + + + + element:F1 + + package:L1812 + + + + element:FD1 + + package:FIDUCIA-MOUNT + + + + element:FD2 + + package:FIDUCIA-MOUNT + + + + element:FD3 + + package:FIDUCIA-MOUNT + + + + element:GROUND + + package:SJ + + + + element:R1 + + package:R0603-ROUND + + + + element:R2 + + package:R0603-ROUND + + + + element:RN1 + + package:CAY16 + + + + element:RN2 + + package:CAY16 + + + + element:RN3 + + package:CAY16 + + + + element:RN4 + + package:CAY16 + + + + element:Z1 + + package:CT/CN0603 + + + + element:Z2 + + package:CT/CN0603 + + + + + + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + TX + + + + + + + + + + + + + + + + + + + + + + + RX + + + + + + + + + + + + + + + + + + + + + + + AREF + + + + + + + + + + + + + + + + + + + + + + + GND + + + + + + + + + + + + + + layer 25 + + + + + + 5V + + + + + + + text:A0 + + + + A0 + + + + + + + + + + ANALOG IN + + + + + + + text:M.Banzi + + + text:D.Cuartielles + + + text:D.Mellis + + + + + + + TX + + + + + + + + + + + RX + + + + + + + text:G.Martino + + + text:T.Igoe + + + + + + + + + + + + + RESET + + + + + + + + + + + + + + + + + + + + + + + 3V3 + + + + + + + + + + + + + text:A1 + + + + A1 + + + + + + text:A2 + + + + A2 + + + + + + text:A3 + + + + A3 + + + + + + text:A4 + + + + A4 + + + + + + text:A5 + + + + A5 + + + + + + + + + + VIN + + + + + + + + + + + GND + + + + + + + + + + + GND + + + + + + + text:[#=PWM] + + + + DIGITAL (PWM SPI ) + + + + + + + SCL + + + + + + + SDA + + + + + + + + < + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text:# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IOREF + + + + + + + + + + + + + text:SDA + + + text:SCL + + + element:AD + + package:1X06 + + + + element:C1 + + package:C0603-ROUND + + + + element:C2 + + package:C0603-ROUND + + + + element:C3 + + package:C0603-ROUND + + + + element:C4 + + package:C0603-ROUND + + + + element:C5 + + package:C0603-ROUND + + + + element:C6 + + package:C0603-ROUND + + + + element:C7 + + package:C0603-ROUND + + + + element:C8 + + package:C0603-ROUND + + + + element:C9 + + package:C0603-ROUND + + + + element:C11 + + package:C0603-ROUND + + + + element:D1 + + package:SMB + + + + element:D2 + + package:MINIMELF + + + + element:D3 + + package:MINIMELF + + + + element:F1 + + package:L1812 + + + + element:FD1 + + package:FIDUCIA-MOUNT + + + + element:FD2 + + package:FIDUCIA-MOUNT + + + + element:FD3 + + package:FIDUCIA-MOUNT + + + + element:GROUND + + package:SJ + + + + element:ICSP + + text:ICSP + + + + + + + + + + ICSP + + + + + + + + + + + + package:2X03 + + + + element:ICSP1 + + package:2X03 + + + + element:IOH + + package:1X10@1 + + + + element:IOL + + package:1X08 + + + + element:JP2 + + package:2X02 + + + + element:L + + package:CHIP-LED0805 + + + + element:L1 + + package:0805 + + + + element:PC1 + + package:PANASONIC_D + + + + element:PC2 + + package:PANASONIC_D + + + + element:R1 + + package:R0603-ROUND + + + + element:R2 + + package:R0603-ROUND + + + + element:RESET + + package:TS42 + + + + element:RESET-EN + + package:SJ + + + + element:RN1 + + package:CAY16 + + + + element:RN2 + + package:CAY16 + + + + element:RN3 + + package:CAY16 + + + + element:RN4 + + package:CAY16 + + + + element:RX + + package:CHIP-LED0805 + + + + element:T1 + + package:SOT-23 + + + + element:TX + + package:CHIP-LED0805 + + + + element:U1 + + package:SOT223 + + + + element:U2 + + package:SOT23-DBV + + + + element:U3 + + package:MLF32 + + + + element:U5 + + package:MSOP08 + + + + element:X1 + + package:POWERSUPPLY_DC-21MM + + + + element:X2 + + package:PN61729 + + + + element:Y1 + + package:QS + + + + element:Y2 + + package:RESONATOR + + + + element:Z1 + + package:CT/CN0603 + + + + element:Z2 + + package:CT/CN0603 + + + + element:ZU4 + + package:DIL28-3 + + + + + + + + + + + + + + + + + + + + + + + + CS + + + < + + + < + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + TMP + 36 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/arduino/tempLightSensor/tempLightSketch.svg b/arduino/tempLightSensor/tempLightSketch.svg deleted file mode 100644 index cf07828..0000000 --- a/arduino/tempLightSensor/tempLightSketch.svg +++ /dev/null @@ -1,3280 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SCL - SDA - AREF - GND - IOREF - RESET - 3V3 - PWM - PWM - PWM - L - TX - RX - ON - ICSP - PWM - PWM - PWM - TX - RX - 3 - 1 - 2 - 1 - 1 - 1 - 0 - 1 - 9 - 8 - DIGITAL - 7 - 6 - 5 - 4 - 3 - 2 - 1 - 0 - 1 - 5V - Gnd - POWER - www.arduino.cc - ANALOG IN - Vin - 0 - 1 - 2 - 3 - 4 - 5 - Arduino - UNO - - - - - - - - - - - - - - - - - - - - - - 7 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - 1 - 5 - 5 - 10 - 10 - 15 - 15 - 20 - 20 - 25 - 25 - 30 - 30 - A - A - B - B - C - C - D - D - E - E - F - F - G - G - H - H - I - I - J - J - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - AREF - GND - RESET - 3V3 - LINK - PWR - 100M - FULLD - COLL - RX - TX - INT - WP - ICSP - RESET - 13 - 12 - 11 - 10 - 9 - 8 - 7 - 6 - 5 - 4 - 3 - 2 - 1 - TX - RX - 0 - 5V - Gnd - MEGA compatible - ANALOG IN - 9V - A0 - 1 - 2 - 3 - 4 - A5 - Arduino - ETHShield - SD - - - - - - - - - - - - - - - - - - - - - - - - - - - TMP - 36 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - AREF - GND - RESET - 3V3 - LINK - PWR - 100M - FULLD - COLL - RX - TX - INT - WP - ICSP - RESET - 13 - 12 - 11 - 10 - 9 - 8 - 7 - 6 - 5 - 4 - 3 - 2 - 1 - TX - RX - 0 - 5V - Gnd - MEGA compatible - ANALOG IN - 9V - A0 - 1 - 2 - 3 - 4 - A5 - Arduino - ETHShield - SD - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/bite/api/tests.py b/bite/api/tests.py index 7ce503c..75f1ee4 100644 --- a/bite/api/tests.py +++ b/bite/api/tests.py @@ -1,3 +1,26 @@ -from django.test import TestCase +from django.test import TestCase, Client +from api.models import Device, WhiteList -# Create your tests here. + +class ApiTestCase(TestCase): + c = Client() + + def setUp(self): + WhiteList.objects.create(serial='test1234') + Device.objects.create(serial='test1234') + + def test_no_whitelist(self): + response = self.c.post('/api/device/subscribe/', + {'serial': 'test12345'}) + self.assertEqual(response.status_code, 400) + + def test_subscribe_post(self): + WhiteList.objects.create(serial='test12345') + response = self.c.post('/api/device/subscribe/', + {'serial': 'test12345'}) + self.assertEqual(response.status_code, 201) + + def test_subscribe_get(self): + response = self.c.get('/api/device/list/') + self.assertEqual( + response.json()[0]['serial'], 'test1234') diff --git a/bite/telemetry/migrations/0008_auto_20200619_1627.py b/bite/telemetry/migrations/0008_auto_20200619_1627.py new file mode 100644 index 0000000..799aa39 --- /dev/null +++ b/bite/telemetry/migrations/0008_auto_20200619_1627.py @@ -0,0 +1,20 @@ +# Generated by Django 3.0.7 on 2020-06-19 16:27 + +import django.contrib.postgres.fields.jsonb +from django.db import migrations +import telemetry.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('telemetry', '0007_telemetry_transport'), + ] + + operations = [ + migrations.AlterField( + model_name='telemetry', + name='payload', + field=django.contrib.postgres.fields.jsonb.JSONField(validators=[telemetry.models.telemetry_validation]), + ), + ] diff --git a/bite/telemetry/models.py b/bite/telemetry/models.py index 60f1ff0..bf6e23e 100644 --- a/bite/telemetry/models.py +++ b/bite/telemetry/models.py @@ -1,10 +1,16 @@ from django.db import models from django.core.validators import MinValueValidator +from django.core.exceptions import ValidationError from django.contrib.postgres.fields import JSONField from api.models import Device +def telemetry_validation(value): + if not value: + raise ValidationError("No telemetry has been sent") + + class Telemetry(models.Model): device = models.ForeignKey(Device, on_delete=models.CASCADE) time = models.DateTimeField(primary_key=True, auto_now_add=True) @@ -14,7 +20,7 @@ class Telemetry(models.Model): clock = models.IntegerField( validators=[MinValueValidator(0)], null=True) - payload = JSONField() + payload = JSONField(validators=[telemetry_validation]) class Meta: ordering = ['-time', 'device'] diff --git a/bite/telemetry/tests.py b/bite/telemetry/tests.py index 7ce503c..a6f3159 100644 --- a/bite/telemetry/tests.py +++ b/bite/telemetry/tests.py @@ -1,3 +1,53 @@ -from django.test import TestCase +import json +from django.test import TestCase, Client +from api.models import Device, WhiteList -# Create your tests here. + +class ApiTestCase(TestCase): + c = Client() + + payload = { + 'id': 'sensor.server.domain', + 'light': 434, + 'temperature': { + 'celsius': 27.02149, + 'raw': 239, + 'volts': 0.770215 + } + } + + telemetry = { + 'device': 'test1234', + 'clock': 1591194712, + 'payload': json.dumps(payload) + } + + def setUp(self): + WhiteList.objects.create(serial='test1234') + Device.objects.create(serial='test1234') + + def test_no_device(self): + fake_telemetry = dict(self.telemetry) # make a copy of the dict + fake_telemetry['device'] = '1234test' + response = self.c.post('/telemetry/', fake_telemetry) + self.assertEqual(response.status_code, 400) + + def test_empty_telemetry(self): + fake_telemetry = dict(self.telemetry) # make a copy of the dict + fake_telemetry['payload'] = '' + response = self.c.post('/telemetry/', fake_telemetry) + self.assertEqual(response.status_code, 400) + + def test_telemetry_post(self): + response = self.c.post('/telemetry/', self.telemetry) + self.assertEqual(response.status_code, 201) + + def test_telemetry_get(self): + response = self.c.post('/telemetry/', self.telemetry) + response = self.c.get('/telemetry/test1234/last/') + self.assertEqual( + response.json()['device'], 'test1234') + self.assertEqual( + response.json()['transport'], 'http') + self.assertJSONEqual( + json.dumps(response.json()['payload']), self.payload) diff --git a/docker/edge/docker-compose.edge.yml b/docker/edge/docker-compose.edge.yml index 7c028c3..f82d6a1 100644 --- a/docker/edge/docker-compose.edge.yml +++ b/docker/edge/docker-compose.edge.yml @@ -2,12 +2,11 @@ version: "3.7" services: edge-host: - <<: *service_default image: docker:dind privileged: true environment: DOCKER_TLS_CERTDIR: - # networks: - # - net + networks: + - net ports: - "127.0.0.1:22375:2375" diff --git a/docker/edge/docker-compose.modules.yml b/docker/edge/docker-compose.modules.yml index 0d4cfab..7157150 100644 --- a/docker/edge/docker-compose.modules.yml +++ b/docker/edge/docker-compose.modules.yml @@ -1,8 +1,5 @@ version: "3.7" -networks: - localnet: - x-op-service-default: &service_default restart: always init: true @@ -15,12 +12,11 @@ services: context: ../simulator image: daniviga/bite-device-simulator environment: - IOT_HTTP: "http://192.168.10.123:8000" - # IOT_SERIAL: "abcd1234" + IOT_HTTP: "http://ingress" + # IOT_SERIAL: "http1234" # IOT_DELAY: 10 IOT_DEBUG: 1 - networks: - - localnet + network_mode: "host" device-mqtt: <<: *service_default @@ -28,11 +24,10 @@ services: context: ../simulator image: daniviga/bite-device-simulator environment: - IOT_HTTP: "http://192.168.10.123:8000" - IOT_MQTT: "192.168.10.123:1883" - # IOT_SERIAL: "abcd1234" + IOT_HTTP: "http://ingress" + IOT_MQTT: "broker:1883" + # IOT_SERIAL: "mqtt1234" # IOT_DELAY: 10 IOT_DEBUG: 1 command: ["/opt/bite/device_simulator.py", "-t", "mqtt"] - networks: - - localnet + network_mode: "host" diff --git a/docker/ntpd/Dockerfile.enc b/docker/ntpd/Dockerfile.enc new file mode 100644 index 0000000..b0f8fcc --- /dev/null +++ b/docker/ntpd/Dockerfile.enc @@ -0,0 +1,9 @@ +FROM daniviga/ntpd + +COPY ./chrony.keys /etc/chrony/chrony.keys + +RUN echo "keyfile /etc/chrony/chrony.keys" \ + >> /etc/chrony/chrony.conf + +EXPOSE 123/udp +ENTRYPOINT ["chronyd", "-d", "-s", "-x"] diff --git a/docker/ntpd/chrony.keys.sample b/docker/ntpd/chrony.keys.sample new file mode 100644 index 0000000..2c452ee --- /dev/null +++ b/docker/ntpd/chrony.keys.sample @@ -0,0 +1 @@ +1 MD5 HEX:D8ACA3A254EF59F83C35CEEFF6EBD2C7C67DB3D9