Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Obtaining the Perfect Smoke By Monitoring Your BBQ with InfluxDB and Telegraf

Did you know you can use InfluxDB to monitor your BBQ and to ensure the tastiest results? Join this meetup to learn two different approaches to using a time series database to monitor a BBQ or a smoker. Learn how Will Cooke uses Python, MQTT, Telegraf and InfluxDB 2.0 to monitor his smoker and to gain insight into temperature changes, the stall, and other important stats about his brisket. Scott Anderson will demonstrate how he uses a FireBoard wireless thermometer, Telegraf and InfluxDB 2.0 to continuously work towards the perfect smoke.

  • Be the first to comment

  • Be the first to like this

Obtaining the Perfect Smoke By Monitoring Your BBQ with InfluxDB and Telegraf

  1. 1. December 16, 2020 Time Series Virtual Meetup Obtaining the Perfect Smoke By Monitoring Your BBQ with InfluxDB and Telegraf
  2. 2. 2 Agenda ●Introductions ●Our talk today ●Q&A ●Open Jobs ●Be a speaker
  3. 3. 3 Speakers Will Cooke Engineering Manager, Storage Team InfluxData Scott Anderson Senior Technical Writer & Technical Lead Docs Team InfluxData
  4. 4. Method 1: Python + MQTT + Telegraf + InfluxDB Cloud 2.0 I can make it at home for nothing… Will Cooke
  5. 5. 5 $200
  6. 6. 6
  7. 7. 7
  8. 8. 8
  9. 9. 9
  10. 10. 10
  11. 11. 11 Free!
  12. 12. 12 $120
  13. 13. 13
  14. 14. 14
  15. 15. 15
  16. 16. 16 Free!
  17. 17. 17 Do It Yourself is probably not better, but it is a great way to learn.
  18. 18. 18 COTS
  19. 19. 19 COTSish
  20. 20. 20
  21. 21. 21 Inkbird IBT-4XS ● 4 probes ● Rechargeable battery ● $40
  22. 22. 22 ● Low power ○ Maximum 50% power usage of normal Bluetooth, usually a lot less ● Low speed ○ Theoretical Max 2Mbps, usually a lot less ● Lower range ○ Claims < 100 meters, usually a lot less ○ Simplified modulation scheme ● Well supported under Linux ● Fairly standard architecture Bluetooth Low Energy
  23. 23. 23 Descriptors Getcharacteristics Bluetooth LE device Raspberry Pi Characteristic AuthenticatePSK Getdescriptors Characteristics Characteristic Subscribe&enablerealtime Ihavedataforyou Readdada Senddata Subscribe&enablerealtime
  24. 24. 24 Python code CREDENTIALS_MESSAGE = bytearray.fromhex("21 07 06 05 04 03 02 01 b8 22 00 00 00 00 00") REALTIME_DATA_ENABLE = bytearray.fromhex("0B 01 00 00 00 00") UNITS_FAHRENHEIT = bytearray.fromhex("02 01 00 00 00 00") UNITS_CELSIUS = bytearray.fromhex("02 00 00 00 00 00") BATTERY_LEVEL = bytearray.fromhex("08 24 00 00 00 00") # iBBQ static service MAIN_SERVICE = 0xFFF0 # Service which provides the characteristics CCCD_UUID = 0x2902 # iBBQ static characteristics SETTINGS_RESULTS = 0xFFF1 PAIR_UUID = 0xFFF2 HISTORY_UUID = 0xFFF3 # Don't know how this works, here for completeness REALTIMEDATA_UUID = 0xFFF4 CMD_UUID = 0xFFF5 # Static hex little endian ones and zeros ON = bytearray.fromhex("01 00") OFF = bytearray.fromhex("00 00")
  25. 25. 25 Transports ● Line Protocol ○ DIY ● InfluxDB Client Libraries ○ Clients for most languages ○ Someone has done a lot of the hard work for you ● Telegraf ○ No code option ○ Queuing ○ Pre processing ○ Plugin driven ○ Ready made binaries ○ Already using it
  26. 26. 26 MQTT ● Brokers ○ Mosquitto ● Client Libraries ○ Every platform and every language ○ Python - Paho MQTT ● Telegraf ○ No code option ○ Already using it!
  27. 27. 27 MQTT ● Message Queuing Telemetry Transport ○ pub/sub model ○ Doesn’t actually queue ● Works well on low powered devices ○ Simple protocol = low CPU & memory footprint ● Hierarchy of topics ○ bbq/temperature/1 ○ bbq/temperature/2 ○ bbq/temperature/3 ○ home/sensors/bathroom ○ home/sensors/# ● Payloads ○ bbq/temperature/1 - 106 ○ home/sensors/bathroom - {“humidity”:65, “temperature”:25, “fan_running”:true}
  28. 28. 28 Telegraf ● Python sends MQTT message ○ send_mqtt("bbq/temperature/"+str(idx+1), int(temperature)) ● Telegraf config [[inputs.mqtt_consumer]] servers = ["tcp://192.168.42.100:1883"] topics = [ "bbq/+/#" ] data_format = "value" data_type = "integer" [[outputs.influxdb_v2]] urls = ["https://us-west-2-1.aws.cloud2.influxdata.com"] token =”YOUR_TOKEN” organization = "wcooke@influxdata.com" bucket = "My Monitoring Bucket"
  29. 29. 29
  30. 30. 30 The dreaded stall
  31. 31. 31
  32. 32. 32 Features & Future Plans ● https://github.com/8none1/pybq ○ Contributions welcome! ● Currently working: ○ Reporting temperatures ○ Reporting battery levels ○ Automatically connect to thermometer and start logging ● Alerts ○ Send instant messenger alerts when certain thresholds are hit ○ Leverage Influx Cloud 2 tasks and alerts ● Low Power Mode ○ Only poll the temperature every minute? ● More ribs
  33. 33. Method 2: FireBoard + Telegraf + InfluxDB 2.0 Scott Anderson
  34. 34. Fireboard 1
  35. 35. Fireboard 2
  36. 36. [[outputs.influxdb_v2]] urls = ["$INFLUX_HOST"] token = "$INFLUX_TOKEN" organization = "$INFLUX_ORG" bucket = "fireboard" [[inputs.fireboard]] ## Specify auth token for your account auth_token = "$FIREBOARD_TOKEN"
  37. 37. Passive BBQ Monitor & Alert
  38. 38. import "influxdata/influxdb/monitor" meatProbes = [2,3] checkData = {...} from(bucket:"fireboard") |> range(start: -15m) |> filter(fn: (r) => r._measurement == "fireboard" and contains(set: meatProbes, value: int(v: r.channel))) |> difference(nonNegative: false) |> aggregateWindow(every: 5m, fn: mean) |> fill(usePrevious: true) |> map(fn: (r) => ({ r with status: if r._value <= 0.0 then "cooling" else if r._value <= 0.02 then "stalling" else "cooking" })) |> monitor.check( crit: (r) => r.status == "cooling", warn: (r) => r.status == "stalling", ok: (r) => r.status <= "cooking", messageFn: (r) => "Probe${r.channel} appears to be ${r.status}", data: checkData )
  39. 39. import "influxdata/influxdb/monitor" meatProbes = [2,3] checkData = {...} from(bucket:"fireboard") |> range(start: -15m) |> filter(fn: (r) => r._measurement == "fireboard" and contains(set: meatProbes, value: int(v: r.channel))) |> difference(nonNegative: false) |> aggregateWindow(every: 5m, fn: mean) |> fill(usePrevious: true) |> map(fn: (r) => ({ r with status: if r._value <= 0.0 then "cooling" else if r._value <= 0.02 then "stalling" else "cooking" })) |> monitor.check( crit: (r) => r.status == "cooling", warn: (r) => r.status == "stalling", ok: (r) => r.status <= "cooking", messageFn: (r) => "Probe${r.channel} appears to be ${r.status}", data: checkData )
  40. 40. import "influxdata/influxdb/monitor" meatProbes = [2,3] checkData = {...} from(bucket:"fireboard") |> range(start: -15m) |> filter(fn: (r) => r._measurement == "fireboard" and contains(set: meatProbes, value: int(v: r.channel))) |> difference(nonNegative: false) |> aggregateWindow(every: 5m, fn: mean) |> fill(usePrevious: true) |> map(fn: (r) => ({ r with status: if r._value <= 0.0 then "cooling" else if r._value <= 0.02 then "stalling" else "cooking" })) |> monitor.check( crit: (r) => r.status == "cooling", warn: (r) => r.status == "stalling", ok: (r) => r.status <= "cooking", messageFn: (r) => "Probe${r.channel} appears to be ${r.status}", data: checkData )
  41. 41. import "influxdata/influxdb/monitor" meatProbes = [2,3] checkData = {...} from(bucket:"fireboard") |> range(start: -15m) |> filter(fn: (r) => r._measurement == "fireboard" and contains(set: meatProbes, value: int(v: r.channel))) |> difference(nonNegative: false) |> aggregateWindow(every: 5m, fn: mean) |> fill(usePrevious: true) |> map(fn: (r) => ({ r with status: if r._value <= 0.0 then "cooling" else if r._value <= 0.02 then "stalling" else "cooking" })) |> monitor.check( crit: (r) => r.status == "cooling", warn: (r) => r.status == "stalling", ok: (r) => r.status <= "cooking", messageFn: (r) => "Probe${r.channel} appears to be ${r.status}", data: checkData )
  42. 42. Comparative Analysis
  43. 43. import "experimental" session1 = from(bucket: "fireboard") |> range(start: 2020-07-22T23:34:10Z, stop: 2020-07-24T14:50:00Z) |> filter(fn: (r) => r["_measurement"] == "fireboard") session2 = from(bucket: "fireboard") |> range(start: 2020-04-11T21:36:10Z, stop: 2020-04-12T20:22:00Z) |> filter(fn: (r) => r["_measurement"] == "fireboard") union(tables: [session1, session2]) |> experimental.alignTime()
  44. 44. 54 Other things on my punch list ● Forecasting ○ Estimate remaining cook time ● Enhanced visualizations ○ Status-determined visualization color schemes ● More notifications ○ “Done” alert ○ “Cooling” alert
  45. 45. 58 Fireboard InfluxDB Template github.com/influxdata/community-templates/tree/master/fireboard
  46. 46. 59 Fireboard InfluxDB Template
  47. 47. 60 NEXT MEETUP - January 6, 2021 Monitor Your Homebrew Using InfluxDB Cloud, Telegraf and Raspberry Pi https://bit.ly/3lUYJrS Thanks for coming!

×