Skip to content
This repository has been archived by the owner on Apr 5, 2024. It is now read-only.

Commit

Permalink
Introduced Telegraf to take readings and push to InfluxDB cloud
Browse files Browse the repository at this point in the history
Change-type: minor
Signed-off-by: Chris Crocker-White <chriscw@balena.io>
  • Loading branch information
chrisys committed Jun 19, 2019
1 parent 5f50929 commit 3dac868
Show file tree
Hide file tree
Showing 8 changed files with 172 additions and 88 deletions.
6 changes: 6 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,9 @@ services:
- 'sense-data:/data'
depends_on:
- influxdb
telegraf:
build: ./telegraf
restart: always
depends_on:
- influxdb
- sensor
2 changes: 1 addition & 1 deletion sensor/Dockerfile.template
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ WORKDIR /usr/src/app/bsec_bme680_linux
RUN chmod +x make.sh
RUN ./make.sh

RUN pip install smbus influxdb
RUN pip install smbus

WORKDIR /usr/src/app
COPY ./scripts ./scripts
Expand Down
2 changes: 1 addition & 1 deletion sensor/entry.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ mkdir -p /data/sensor
touch /data/sensor/bsec_iaq.state
cp -n /usr/src/app/bsec_bme680_linux/bsec_iaq.config /data/sensor/bsec_iaq.config

python /usr/src/app/scripts/take_measurement.py
python /usr/src/app/scripts/sensor.py
110 changes: 110 additions & 0 deletions sensor/scripts/sensor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# This script detects for the presence of either a BME680 sensor on the I2C bus or a Sense HAT
# The BME680 includes sensors for temperature, humidity, pressure and gas content
# The Sense HAT does not have a gas sensor, and so air quality is approximated using temperature and humidity only.

import sys
import time
import smbus
import os
import json

from hts221 import HTS221
from bme680 import BME680
from http.server import HTTPServer, BaseHTTPRequestHandler

class balenaSense():
readfrom = 'unset'
bus = smbus.SMBus(1)

def __init__(self):
# First, check to see if there is a BME680 on the I2C bus
try:
self.bus.write_byte(0x76, 0)
except IOError:
print('BME680 not found on 0x76, trying 0x77')
else:
self.readfrom = 'bme680primary'

# If we didn't find it on 0x76, look on 0x77
if self.readfrom == 'unset':
try:
self.bus.write_byte(0x77, 0)
except IOError:
print('BME680 not found on 0x77')
else:
self.readfrom = 'bme680secondary'


# If no BME680, is there a Sense HAT?
if self.readfrom == 'unset':
try:
self.bus.write_byte(0x5F, 0)
except:
print('Sense HAT not found')
else:
self.readfrom = 'sense-hat'
print('Using Sense HAT for readings (no gas measurements)')

# Import the sense hat methods
import sense_hat_air_quality

self.sensor = HTS221()
else:
print('Using BME680 for readings')

# Import the BME680 methods
self.sensor = BME680(self.readfrom)


# If this is still unset, no sensors were found; quit!
if self.readfrom == 'unset':
print('No suitable sensors found! Exiting.')
sys.exit()

def sample(self):
if self.readfrom == 'sense-hat':
return self.apply_offsets(sense_hat_air_quality.get_readings(self.sensor))
else:
return self.apply_offsets(self.sensor.get_readings(self.sensor))


def apply_offsets(self, measurements):
# Apply any offsets to the measurements before storing them in the database
if os.environ.get('BALENASENSE_TEMP_OFFSET') != None:
measurements[0]['fields']['temperature'] = measurements[0]['fields']['temperature'] + float(os.environ['BALENASENSE_TEMP_OFFSET'])

if os.environ.get('BALENASENSE_HUM_OFFSET') != None:
measurements[0]['fields']['humidity'] = measurements[0]['fields']['humidity'] + float(os.environ['BALENASENSE_HUM_OFFSET'])

if os.environ.get('BALENASENSE_ALTITUDE') != None:
# if there's an altitude set (in meters), then apply a barometric pressure offset
altitude = float(os.environ['BALENASENSE_ALTITUDE'])
measurements[0]['fields']['pressure'] = measurements[0]['fields']['pressure'] * (1-((0.0065 * altitude) / (measurements[0]['fields']['temperature'] + (0.0065 * altitude) + 273.15))) ** -5.257

return measurements



class balenaSenseHTTP(BaseHTTPRequestHandler):
def _set_headers(self):
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()

def do_GET(self):
self._set_headers()
measurements = balenasense.sample()
self.wfile.write(json.dumps(measurements[0]['fields']).encode('UTF-8'))

def do_HEAD(self):
self._set_headers()


# Start the server to answer requests for readings
balenasense = balenaSense()

while True:
server_address = ('', 80)
httpd = HTTPServer(server_address, balenaSenseHTTP)
print('Sensor HTTP server running')
httpd.serve_forever()
86 changes: 0 additions & 86 deletions sensor/scripts/take_measurement.py

This file was deleted.

10 changes: 10 additions & 0 deletions telegraf/Dockerfile.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
FROM balenalib/%%BALENA_MACHINE_NAME%%

RUN curl -o /tmp/telegraf.deb https://dl.influxdata.com/telegraf/releases/telegraf_1.11.0-1_armhf.deb
RUN dpkg -i /tmp/telegraf.deb && rm /tmp/telegraf.deb

COPY telegraf.conf /etc/telegraf/telegraf.conf
COPY entry.sh /entry.sh
RUN chmod +x /entry.sh

CMD /entry.sh
10 changes: 10 additions & 0 deletions telegraf/entry.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/bash
if [[ -z $INFLUX_TOKEN || -z $INFLUX_ORG || -z $INFLUX_BUCKET ]]; then
echo 'One or more InfluxDB variables are undefined - not using cloud'
sed -i '/influxdb_v2/,/bucket/ s/^#*/#/' /etc/telegraf/telegraf.conf
else
echo 'InfluxDB variables are defined - using cloud'
sed -i '/influxdb_v2/,/bucket/ s/^##*//' /etc/telegraf/telegraf.conf
fi

telegraf
34 changes: 34 additions & 0 deletions telegraf/telegraf.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[global_tags]
balena_sense_id = "$BALENASENSE_ID"

[agent]
interval = "10s"
round_interval = true
metric_batch_size = 1000
metric_buffer_limit = 10000
collection_jitter = "0s"
flush_interval = "10s"
flush_jitter = "0s"
debug = false
quiet = false
omit_hostname = false

[[outputs.influxdb]]
urls = ["http://influxdb:8086"]
database = "balena-sense"
timeout = "1s"

[[outputs.influxdb_v2]]
urls = ["https://us-west-2-1.aws.cloud2.influxdata.com"]
token = "$INFLUX_TOKEN"
organization = "$INFLUX_ORG"
bucket = "$INFLUX_BUCKET"

[[inputs.http]]
urls = [
"http://sensor"
]

timeout = "1s"
data_format = "json"
name_override = "balena-sense"

0 comments on commit 3dac868

Please sign in to comment.