Commit d99d43fc authored by Ľubomír Kollár's avatar Ľubomír Kollár
Browse files

Merge branch 'master' into 'Grafana'

# Conflicts:
#   budkaApi/Dockerfile
#   budkaApi/app/main.py
#   docker-compose.yml
parents 2e06823a b82cc2c8
[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,11
[InternetShortcut]
IDList=
URL=https://osoyoo.com/2017/07/27/arduino-lesson-pir-motion-sensor/
......@@ -8,5 +8,7 @@ ENV PYTHONUNBUFFERED True
COPY ./app /app
#RUN ls -R /app
RUN apt update; apt install -y build-essential
# Install production dependencies.
RUN pip install --no-cache-dir fastapi fastapi_mqtt motor
RUN pip install --no-cache-dir fastapi fastapi_mqtt motor aioinflux influxdb
import time
from datetime import datetime, timedelta
import os
import motor.motor_asyncio
from bson import ObjectId
from fastapi import FastAPI, Body
......@@ -9,6 +10,11 @@ from pydantic import BaseModel, Field
from typing import Optional, List
from fastapi.middleware.cors import CORSMiddleware
from starlette.responses import JSONResponse
import json
from influxdb import InfluxDBClient
from aioinflux import *
from typing import NamedTuple
#######################################################################################################################
......@@ -63,10 +69,10 @@ class HouseModel(BaseModel):
}
class TemperatureModel(BaseModel):
class Photo(BaseModel):
id: PyObjectId = Field(default_factory=PyObjectId, alias="_id")
houseId: PyObjectId = Field(default_factory=PyObjectId, alias="houseId")
value: float
base64Data: str
class Config:
allow_population_by_field_name = True
arbitrary_types_allowed = True
......@@ -75,11 +81,45 @@ class TemperatureModel(BaseModel):
"example": {
"id": "123456789012345678901234",
"houseId": "123456789012345678901234",
"temperature": 123.123
"base64Data": "djahjfkahdkfhahfaishfuhxafoaimxfjXXXX===="
}
}
@lineprotocol
class Temperature(NamedTuple):
timestamp: TIMEINT
temperature: INT
house_id: STR
@lineprotocol
class Humidity(NamedTuple):
timestamp: TIMEINT
humidity: INT
house_id: STR
@lineprotocol
class Pressure(NamedTuple):
timestamp: TIMEINT
pressure: INT
house_id: STR
@lineprotocol
class Wind(NamedTuple):
timestamp: TIMEINT
wind: INT
house_id: STR
@lineprotocol
class Smoke(NamedTuple):
timestamp: TIMEINT
smoke: INT
house_id: STR
#######################################################################################################################
......@@ -87,11 +127,12 @@ mongo_client = motor.motor_asyncio.AsyncIOMotorClient(os.getenv('MONGO_URL', def
DB = mongo_client.birdie
app = FastAPI()
mqtt_config = MQTTConfig(
host = "broker.hivemq.com",
port= 1883,
host = "50ffbd7e701c480ca097875a1621692c.s1.eu.hivemq.cloud",
port= 8883,
keepalive = 60,
username=None,
password=None
username="birdie",
password="tjhpnHMQb2021",
ssl=True
)
mqtt = FastMQTT(config=mqtt_config)
mqtt.init_app(app)
......@@ -102,22 +143,71 @@ app.add_middleware(
allow_methods=["*"],
allow_headers=["DELETE", "GET", "POST", "PUT"],
)
influx_client = InfluxDBClient(mode='blocking', db='birdie_data', host=os.getenv('INFLUX_HOST', default='localhost'), port=os.getenv('INFLUX_PORT', default=8086), username='admin', password='birdie123')
influx_client.mode = 'async'
#######################################################################################################################
@mqtt.on_connect()
def connect(client, flags, rc, properties):
mqtt.client.subscribe("/posluchac") #subscribing mqtt topic
mqtt.client.subscribe("birdie/rxtx/from/raspberry")
mqtt.client.subscribe("birdie/temperature")
mqtt.client.subscribe("birdie/humidity")
mqtt.client.subscribe("birdie/windspeed")
mqtt.client.subscribe("birdie/smoke")
mqtt.client.subscribe("birdie/pressure")
print("Connected: ", client, flags, rc, properties, flush=True)
@mqtt.on_message()
async def message(client, topic, payload, qos, properties):
print("Received message: ", topic, payload.decode(), qos, properties, flush=True)
return 0
if topic == 'birdie/rxtx/from/raspberry':
recevieddata = json.loads(payload.decode())
document = {'houseId': ObjectId(recevieddata["houseId"]), 'base64Data': recevieddata["data"]}
result = await DB.photos.insert_one(document)
print('result %s' % repr(result.inserted_id))
if topic == 'birdie/temperature':
recevieddata = json.loads(payload.decode())
temperature = Temperature(
timestamp=int(time.time()),
temperature=recevieddata["temperature"],
house_id=recevieddata["houseId"]
)
await influx_client.write(temperature, time_precision='ms')
if topic == 'birdie/humidity':
recevieddata = json.loads(payload.decode())
humidity = Humidity(
timestamp=int(time.time()),
humidity=recevieddata["humidity"],
house_id=recevieddata["houseId"]
)
await influx_client.write(humidity, time_precision='ms')
if topic == 'birdie/windspeed':
recevieddata = json.loads(payload.decode())
wind = Wind(
timestamp=int(time.time()),
wind=recevieddata["windspeed"],
house_id=recevieddata["houseId"]
)
await influx_client.write(wind, time_precision='ms')
if topic == 'birdie/pressure':
recevieddata = json.loads(payload.decode())
pressure = Pressure(
timestamp=int(time.time()),
pressure=recevieddata["pressure"],
house_id=recevieddata["houseId"]
)
await influx_client.write(pressure, time_precision='ms')
if topic == 'birdie/smoke':
recevieddata = json.loads(payload.decode())
smoke = Smoke(
timestamp=int(time.time()),
smoke=recevieddata["smoke"],
house_id=recevieddata["houseId"]
)
await influx_client.write(smoke, time_precision='ms')
@app.get("/health", response_model=HealthResponse)
async def health():
......@@ -132,11 +222,11 @@ async def get_all_bird_houses_inside_mapbounds(leftTop_long: float, leftTop_lat:
return houses
@app.get("/temperatures/getlast", response_model=TemperatureModel)
async def get_last_temperature_of_specific_bird_house(houseId: str):
@app.get("/photos/getlast", response_model=Photo)
async def get_last_photo_of_specific_bird_house(houseId: str):
if not ObjectId.is_valid(houseId):
return JSONResponse({})
lastTemp = await DB["temperatures"].find({'houseId': ObjectId(houseId)}).sort('_id', -1).to_list(1)
lastTemp = await DB["photos"].find({'houseId': ObjectId(houseId)}).sort('_id', -1).to_list(1)
if len(lastTemp) > 0:
return lastTemp[0]
else:
......
[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,11
[InternetShortcut]
IDList=
URL=https://www.makerguides.com/dht11-dht22-arduino-tutorial/
......@@ -17,7 +17,7 @@ services:
container_name: MongoDB
environment:
- MONGO_INITDB_ROOT_USERNAME=root
- MONGO_INITDB_ROOT_PASSWORD=pass12345
- MONGO_INITDB_ROOT_PASSWORD=pass12345
volumes:
- mongo_data:/data/db
ports:
......@@ -25,11 +25,21 @@ services:
networks:
- main
grafana:
container_name: Grafana
image: grafana/grafana
ports:
- 3000:3000
networks:
- main
volumes:
- grafana_data:/var/lib/grafana
influxdb:
image: influxdb:1.7-alpine
container_name: influxdb
#command: ["influx", "-host", "influxdb", "-port", "8086", "-execute", "'CREATE DATABASE birdie_data'"]
environment:
- INFLUXDB_ADMIN_ENABLED=true
- INFLUXDB_ADMIN_ENABLED=true
- INFLUXDB_ADMIN_USER=${INFLUXDB_ADMIN_USER:-admin}
- INFLUXDB_ADMIN_PASSWORD=${INFLUXDB_ADMIN_PASSWORD:-birdie123}
- INFLUXDB_DB=prometheus
......@@ -37,58 +47,118 @@ services:
- INFLUXDB_REPORTING_DISABLED=true
- INFLUXDB_USER=${INFLUXDB_USER:-prometheus}
- INFLUXDB_USER_PASSWORD=${INFLUXDB_USER_PASSWORD:-prompass}
volumes:
- ./influx_data:/var/lib/influxdb
healthcheck:
test: "ln -sf /bin/busybox /bin/wget && /bin/wget -q -Y off http://localhost:8086/metrics -O /dev/null > /dev/null 2>&1"
interval: 25s
timeout: 3s
start_period: 30s
volumes:
- ./influx_data:/var/lib/influxdb
networks:
- main
grafana:
image: grafana/grafana
ports:
- 3000:3000
container_name: grafana
volumes:
- ./entrypoint.sh:/app/entrypoint.sh
- ./config/grafana.ini:/etc/grafana/grafana.ini
- ./config/dashboards:/var/lib/grafana/dashboards
- ./config/datasources:/etc/grafana/datasources
- ./config/plugins:/var/lib/grafana/plugins
- grafana_data2:/var/lib/grafana
env_file:
- ./config.env
- 8086:8086
networks:
- main
api:
depends_on:
- influxdb
container_name: birdie_API
image: birdieiot/api
container_name: birdieapi
environment:
- MONGO_URL=mongodb://root:pass12345@mongodb:27017
- INFLUX_HOST=influxdb
- INFLUX_PORT=8086
ports:
- 27099:80
networks:
- main
# mosquitto:
# image: eclipse-mosquitto:1.6.14
# container_name: mosquitto
# networks:
# - main
# ports:
# - "1883:1883"
# - "9001:9001"
# volumes:
# #- ./mosquitto/mosquitto.conf:/mosquitto/config/mosquitto.conf
# - mosquitto_data:/data
fakebudka0:
container_name: fakeBudka0
image: birdieiot/fakebudka
networks:
- main
environment:
- HOUSE_ID=608b28eb3650633ec0f34d69
fake01:
image: mrooding/micropython-docker
volumes:
- '${PWD}/scripts:/scripts'
fakebudka1:
container_name: fakeBudka1
image: birdieiot/fakebudka
networks:
- main
environment:
- HOUSE_ID=608b29183650633ec0f34d6b
fakebudka2:
container_name: fakeBudka2
image: birdieiot/fakebudka
networks:
- main
environment:
- HOUSE_ID=608b29473650633ec0f34d6c
fakebudka3:
container_name: fakeBudka3
image: birdieiot/fakebudka
networks:
- main
environment:
- HOUSE_ID=608b29563650633ec0f34d6d
fakebudka4:
container_name: fakeBudka4
image: birdieiot/fakebudka
networks:
- main
environment:
- EXECUTE_FILE=/scripts/main.py
container_name: fake01
- HOUSE_ID=608b29633650633ec0f34d6e
fakebudka5:
container_name: fakeBudka5
image: birdieiot/fakebudka
networks:
- main
environment:
- HOUSE_ID=608b29703650633ec0f34d6f
fakebudka6:
container_name: fakeBudka6
image: birdieiot/fakebudka
networks:
- main
environment:
- HOUSE_ID=608b297b3650633ec0f34d70
fakebudka7:
container_name: fakeBudka7
image: birdieiot/fakebudka
networks:
- main
environment:
- HOUSE_ID=608b29873650633ec0f34d71
fakebudka8:
container_name: fakeBudka8
image: birdieiot/fakebudka
networks:
- main
environment:
- HOUSE_ID=608b28fb3650633ec0f34d6a
volumes:
#node_red_data:
mongo_data:
grafana_data2:
influx_data:
grafana_data:
mosquitto_data:
networks:
main:
from machine import Pin
from time import sleep
import dht
import uasyncio
import network
import ubinascii
from umqtt.robust import MQTTClient
import json
import random
dht_sensor = dht.DHT11(Pin(14))
pir = Pin(13, Pin.IN)
mqtt_client = None
wlan = None
HOUSE_ID = "6088716f4d60d0230034f87c"
def connectToNetwork(ssid, password):
global wlan
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
if not wlan.isconnected():
print('connecting to wlan network: %s' %ssid)
wlan.connect(ssid, password)
while not wlan.isconnected():
pass
print('connected! network config:', wlan.ifconfig())
def on_message(topic, message):
print(message)
def connectToMQTT():
global mqtt_client
SSL_PARAMS = {'server_hostname': '50ffbd7e701c480ca097875a1621692c.s1.eu.hivemq.cloud'}
mqtt_client = MQTTClient(
client_id = 'birdie_house_' + ubinascii.hexlify(network.WLAN().config('mac'),'_').decode(),
server = '50ffbd7e701c480ca097875a1621692c.s1.eu.hivemq.cloud',
port = 8883,
keepalive = 30,
ssl=True,
user='birdie',
password='tjhpnHMQb2021',
ssl_params=SSL_PARAMS
)
mqtt_client.DEBUG = True
mqtt_client.connect()
async def readTemperatrue():
while True:
try:
await uasyncio.sleep(1)
dht_sensor.measure()
temp = dht_sensor.temperature()
x = {'houseId': HOUSE_ID, 'temperature': temp}
mqtt_client.publish('birdie/temperature', json.dumps(x))
hum = dht_sensor.humidity()
y = {'houseId': HOUSE_ID, 'humidity': hum}
mqtt_client.publish('birdie/humidity', json.dumps(y))
print('Temperature: %3.1f C; ' %temp, 'Humidity: %3.1f %%' %hum)
except OSError as e:
print('Failed to read from DHT11 sensor: %s' %e)
async def detectMotion():
while True:
await uasyncio.sleep(1)
if pir.value():
print('Motion detected!')
x = {'houseId': HOUSE_ID, 'command': 'TAKE_PHOTO'}
mqtt_client.publish('birdie/rxtx/to/raspberry', json.dumps(x))
await uasyncio.sleep_ms(40)
while pir.value():
pass
await uasyncio.sleep_ms(40)
else:
print('No motion detected!')
async def detectWindSpeed():
while True:
await uasyncio.sleep(1)
x = {'houseId': HOUSE_ID, 'windspeed': random.randint(0, 74)}
mqtt_client.publish('birdie/windspeed', json.dumps(x))
async def detectSmoke():
while True:
await uasyncio.sleep(1)
x = {'houseId': HOUSE_ID, 'smoke': random.randint(0, 1)}
mqtt_client.publish('birdie/smoke', json.dumps(x))
async def detectPressure():
while True:
await uasyncio.sleep(1)
x = {'houseId': HOUSE_ID, 'pressure': random.randint(250, 750)}
mqtt_client.publish('birdie/pressure', json.dumps(x))
connectToNetwork("wifi-lab", "12345wifilabhouse54321")
connectToMQTT()
event_loop = uasyncio.get_event_loop()
event_loop.create_task(readTemperatrue())
event_loop.create_task(detectMotion())
event_loop.create_task(detectWindSpeed())
event_loop.create_task(detectSmoke())
event_loop.create_task(detectPressure())
event_loop.run_forever()
FROM python:3
ADD main.py /
RUN pip install paho-mqtt
CMD [ "python", "./main.py" ]
\ No newline at end of file
This diff is collapsed.
import paho.mqtt.client as mqtt
import picamera
import time
import io
import base64
import json
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("Connected successfully to MQTT broker")
client.subscribe("birdie/rxtx/to/raspberry")
else:
print(f"Connecting to MQTT broker failed with code {rc}")
def on_message(client, userdata, msg):
messagedecoded = str(msg.payload.decode("utf-8"))
print(messagedecoded)
jsoned_message = json.loads(messagedecoded)
if jsoned_message["command"] == 'TAKE_PHOTO':
print('taking photo!')
photo = io.BytesIO()
with picamera.PiCamera() as camera:
camera.resolution = (320, 200)
camera.rotation = 180
camera.start_preview()
time.sleep(2)
camera.capture(photo, 'jpeg')
print('took photo!')
base64_bytes = base64.b64encode(photo.getvalue())
base64_message = base64_bytes.decode('ascii')
x = {'houseId':jsoned_message["houseId"], 'data': base64_message}
client.publish('birdie/rxtx/from/raspberry', payload=json.dumps(x), qos=0, retain=False)
def on_publish(client,userdata,result):
print("published", result)
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.on_publish = on_publish
client.tls_set()
client.username_pw_set("birdie", "tjhpnHMQb2021")
client.connect(
host = "50ffbd7e701c480ca097875a1621692c.s1.eu.hivemq.cloud",
port= 8883,
keepalive = 60
)
client.loop_forever()
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment