Oakland, fireworks, air pollution and the 4th of July

Oakland is a great city. I’ve enjoyed living here for the past 7 years, and working for another 13 before that. The people, the arts, the culture, the food, it’s all wonderful. Except for the fireworks.

Each year as the 4th of July approaches, the fireworks start. Right around 9pm nightly, someone’s lighting them up, splashing the sky with colors and the air with sounds. Sitting on the roof of my house, I see fireworks 360 degrees. They’re beautiful to watch though after 6 hours, it’s all rather tiring. And the sounds become opressive. They’re constant and punctuated by ridiculously loud explosions.

There’s one aspect that I hadn’t considered before, air quality. I recently installed a PurpleAir module to monitor the air quality. The fires last fall wreched havoc on the air quality and being a geek, I wanted something in place to monitor the next fire season. It’s on the PurpleAir map. I pull the data from it to a local InfluxDB database and recently went exploring through the measurements. What I found was interesting.

PurpleAir PM10 Air Quality

The PM10 air quality reached 305 around 11:52PM on the 4th.

The PM2.5 air quality reached 81 around 12:12AM on the 5th.

The PM10 of 305 and PM2.5 of 81 are way, way higher than recommended maximums. Midnight is when the bulk of fireworks are ignited.

As a city, we need to do better for each other.

[Addendum 2020-07-25 16:44:55]

Another aspect that I want to cover for next year is sound levels. Adding a mechanism by which the decible level for general human and k9 hearing would go a fair way toward a better view into what happens with the fireworks.

I would appreciate any suggestions on sensors that would assist with this endeavour.

Influx Telegraf and inputs.exec

I’m a fan of Influxdb for capturing data over time. Coupling it with Grafana and interesting dashboards come to life.

Part of Influx’s tool set is Telegraf, their data collection tool. It comes with a slew of data input and output plugins that are reasonably easy to configure and use. I use two of them fairly regularly, inputs.snmp and inputs.exec. The inputs.snmp plugin uses the long standing SNMP protocol to pull data from network devices. Configuration is fairly straight forward. Here’s a sample for collecting data from a network switch:

  agents = ["NAME_OR_IP"]
  version = 2
  community = "COMMUNITY"
  timeout = "60s"

    oid = "RFC1213-MIB::sysUpTime.0"
    name = "uptime"

    oid = "RFC1213-MIB::sysName.0"
    name = "source"
    is_tag = true

    oid = "IF-MIB::ifTable"
    name = "interface"
    inherit_tags = ["source"]

      oid = "IF-MIB::ifDescr"
      name = "ifDescr"
      is_tag = true

Change NAME_OR_IP to the device name / IP address and the COMMUNITY to the configured SNMP community on the device and Telegraf will pull data from the switch every 60 seconds.

I put one of these configuration files in the


directory for each device. I use the device name as the file name. So for network switch ns1, the configuration file is


At home, the network has 4 switches and there are 4 .conf files in the telegraf.d directory. The inputs.snmp plugin handles all the .conf files and processes the data from all the network devices as expected.

The second Telegraf plugin I often use is inputs.exec. This will launch a program and collect the output to send to the influx database. CSV, JSON, etc. all work to feed the Influx engine.

A typical configuration file looks like:

  commands = [
    "/usr/local/bin/purpleair_json.py https://www.purpleair.com/data.json?show=DEVICEID&key=APIKEY"

  interval = "60s"
  timeout = "10s"
  data_format = "json"
  name_suffix = "_purpleair"
  tag_keys = [

In this case, the exec will run the /usr/local/bin/purpleair_json.py program and capture the data from a PurpleAir device every 60 seconds.

The problem is that the inputs.exec plugin doesn’t allow for multiple instances as with the inputs.snmp plugin. If there are more than one .conf file with inputs.exec, only the last one read by telegraf will be used. As such, more than one program cannot be used to feed via telegraf into influxdb. Rather annoying.

To get around this, I create another instance of the telegraf service. That includes a new systemd service file, a separate /etc/telegraf_EXECNAME folder and supporting configuration files.
In /lib/systemd/system/telegraf_EXECNAME.service:

Description=The plugin-driven server agent for reporting metrics into InfluxDB

ExecStart=/usr/bin/telegraf -config /etc/telegraf_EXECNAME/telegraf.conf -config-directory /etc/telegraf_EXECNAME/telegraf.d $TELEGRAF_OPTS
ExecReload=/bin/kill -HUP $MAINPID


In the /etc/systemd/system/multi-user.target.wants directory, a symbolic link to the new services file:

cd /etc/systemd/system/multi-user.target.wants/
ln -s /lib/systemd/system/telegraf_EXECNAME.service .

In the /etc/telegraf_EXECNAME/telegraf.conf:

  interval = "10s"
  round_interval = true
  metric_batch_size = 1000
  metric_buffer_limit = 10000
  collection_jitter = "0s"
  flush_interval = "10s"
  flush_jitter = "0s"
  precision = ""
  debug = true
  logtarget = "file"
  logfile = "/var/log/telegraf/telegraf_EXECNAME.log"
  logfile_rotation_interval = "1d"
  logfile_rotation_max_size = "50MB"
  logfile_rotation_max_archives = 10
  hostname = ""
  omit_hostname = false


[Add the needed options to the influxdb section for where the influxdb is hosted]

Note that this .conf file has removed all the collection information for the localhost, that remains in the original telegraf instance.

The .conf for the inputs.exec plugin are placed in


To kick off the new service:

systemctl daemon-reload
systemctl enable telegraf_EXECNAME
systemctl start telegraf_EXECNAME

[In all the examples above, replace EXECNAME with a name that describes what’s being run.]

Creating multiple instances of the Telegraf service is annoying but it does allow me to collect the data from multiple places by running programs that reach out, gather the data and format for use with Telegraf and then into an InfluxDB database. See https://github.com/pkropf/telegraf for some examples.

Tags : , ,

Rejection! Burning Man DMV Rejects Most Useless II

Sadly, the Burning Man DMV department has decided that Most Useless II doesn’t meet their minimums. Here’s the rejection letter:

Mutant Vehicle: Most Useless, II
Registration #: M20-0254
Owner: Peter Kropf

Dear Peter Kropf,

The DMV has carefully reviewed your application for your Mutant Vehicle project Most
Useless,II (M20-0254) and we’re very sorry to inform you that your vehicle was not 
accepted for invitation to Burning Man this year.

Please read this letter carefully for more information about the decision regarding 
your vehicle.

The DMV Review Team felt that:



Unfortunately, your vehicle as presented in your application does not meet the 
minimum criteria for a mutant vehicle license:

* * * *
"Level of Mutation / Visual Presentation

Mutate your vehicle to the point that it is not recognizable as a street or stock 
vehicle. A radically mutated vehicle will not resemble or represent a car, truck, golf
cart or any other readily identifiable street or stock vehicle. In most cases, little or
none of the base vehicle should be visible. Beyond just changing, covering or hiding
the base vehicle, the mutation should aim to be visually compelling, providing
“wow factor” for the other participants of Black Rock City. When a person sees this
vehicle, their reaction should be “Wow! Look at that!” If a vehicle maintains it’s 
stock form (i.e. – it keeps the shape of a bus, golf cart or street vehicle) it may not
be sufficiently mutated to meet the Mutant Vehicle Criteria."
* * * *

The DMV Review team felt that while your vehicle has custom attributes, and we
appreciate teh "Most Useless" concept, overall the design does not fundamentally
change the vehicle's visuals from the base Taylor-Dunn.

We should be clear that the team overall enjoyed your vehicle, but in the interest
of fairness, we could not invite as the base is too much the same as the stock 
vehicle it is based upon.


Due to the high number of applications and the limited number of vehicles we can
invite, we simply can't invite all applicants, even when they meet the minimum 
requirements.  We don't want anyone to have the sad experience of bringing a
vehicle out to the playa and having it denied a license after all that work!  We
do our best to give invitations to those most likely to get approved on playa.

We very much understand that you have committed significant time and resources
to creating your mutant vehicle (many of us are mutant vehicle creators ourselves,
so we know what it takes) and that this is hard news to receive.  The level of 
execution of mutant vehicles submitted by the Burning Man community for review
increases from year to year, and unfortunately, there is a limit to how many 
moving vehicles we can allow during the event. Your vehicle simply did not exceed
the very high bar that has been set by your fellow Mutant Vehicle creators this year.

Once again, we realize that this is not the news you likely wanted to hear, but we
do want to thank you for the effort you made and look forward to seeing you on the

If you have questions or wish to discuss this issue further, we can be reached at 
- The DMV Hotties and the Burning Man staff and community.

Finding Raspberry Pi’s

I’m using Raspberry Pi’s for all sorts of projects. They’re fabulous, inexpensive computers that run Linux and can interact with the physical world. But sometimes, I have trouble finding them on my network. I know they’re there but I don’t have any idea of their IP address. For Pi’s that are connected to the display, keyboard and mouse, this isn’t much of a problem. But when the Pi is running headless, it’s a bit annoying trying to find it.

An easy way is to use nmap to find the all hosts on the local network with a specific MAC address prefix. For Raspberry Pi’s, there are two: B8:27:EB for older RPy models 1, 2, 3 and DC:A6:32 for RPy 4.

#! /bin/sh

nmap -sP | awk '/^Nmap/{ip=$NF}/B8:27:EB/{print ip}'
nmap -sP | awk '/^Nmap/{ip=$NF}/DC:A6:32/{print ip}'

nmap will find hosts on the specified network and awk will pull out the IP address of the host if the MAC address prefix matches those of the RPy’s.

Note that you’ll need to change the to match your local network.

LPG Cylinder Sizes

On a regular basis, I’m building flame effects that are fueled with propane. Invariably for the larger effects, I’m scrambling around looking for specifications and details on propane cylinders to just how long an effect will run given a certain amount of fuel, or how long before this effect freezed the cylinder, or what are the basic dimensions to know how to build the mounting mechanism(s) for the cylinders. So here’s the first table showing basic dimensions and weights associated with propane cylinders. For the curious, the 20# cylinder is what you would typically next to a BBQ.

cylinder size lpg gallons weight empty weight full width height orient vendor model
100# 23.6 68# 170# 14.5 48 vert
40# 9.4 29# 70# 12.5 29 vert
30# 7.1 24# 54# 12.5 24 vert
20# 4.7 18# 38# 12.5 18 vert
12.2 49# 100# 12 28 horiz Flame King YSN122a
20.3 78# 163# 16 27 horiz Flame King YSN203
29.3 97# 220# 15 48 horiz Flame King YSN293
16.4 81# 150# 14 40 horiz Manchester 6828
11.3 69# 116# 12 32 horiz Manchester 6817