vladak / workmon

Work environment monitoring and alerting
10 stars 0 forks source link

Python checks

workmon

In the beginning of the pandemic, the company offices went closed rather quickly and I found myself working with my laptop placed on a piano. The initial shock held for a long time, I spent couple of months working like that. This was not good for my posture (mental and physical) at all.

Later on, I built a very nice setup around motorized standing desk with all the bells and whistles (quite meticulous cable management, custom oak wooden top, BenQ LED light placed on external display, IKEA pegboard next to the table to hold the essentials (like noise cancelling headphones), Varmilo keyboard, Grovemade desk pad, WiFi extender AP mounted underneath the desk, professionally framed pictures/drawings on the wall, etc.

Using this setup allowed me to be very productive, possibly more productive than in the office, to the point when I wanted to know more about how I work to make the increased productivity levels sustainable.

When shopping around for parts of another project on Adafruit, I remembered an interesting presentation from GrafanaCon 2021 called WFH habits during lockdown told by Grafana where the presenter used sensor paired with Grafana to monitor her WFH behavior w.r.t. breaks etc. This made me throw some more stuff to the Adafruit order, scavenge some parts laying around and make my own version of work habits monitoring setup.

My goal is to provide the following functionality:

Hardware

This is the 2nd version. See below for older versions.

some of the parts back of the Feather ultrasonic sensor mounted underneath the table front side

Features

The blinking of the neopixel is prioritized so that it will blink with the color corresponding to the highest priority alert.

History

Originally, this was based on a Raspberry Pi with a directly attached USB hub to connect the distance reader and a light bulb with 3 lights which was used to do the alerting. The ultrasonic distance sensor was placed in original iPhone plastic box (the one with the transparent cover) with two holes for the sensor. The Rpi died suddenly and I found more fun "architecture" based on microcontrollers.

Also, I believe the placement of the distance sensor was causing value flapping. It was attached with double sticky tape the white cable holder underneath the table on the right side and was not fully in horizontal position which is possibly made it to get erroneous readings. Another possibility is some interaction with the Linux running on the Raspberry Pi.

Setup

NTP server

The code assumes there is NTP server running and responding on the default IPv4 gateway.

TP-link P110

Install the Tapo app on a mobile phone. Register new account, remember the user ID and password as these will be necessary.

Setup the plug so that it connects to dedicated (IoT) WiFi network with static IP address. Set up and configure https://github.com/vladak/plug2mqtt/ somewhere on the IoT network (say on a Raspberry Pi) to publish the state of the plug, notably the power consumption.

Feather

Solder the US-100 (in UART mode) per the US-100 guide.

Metrics (prerequisites)

Prometheus

The Prometheus configuration needs to have the bits for the above mentioned pre-requisites. For the table distance the MQTT exporter configuration in /etc/prometheus/mqtt-exporter.yaml needs to be augmented with this section:

metrics:
  -
    # The name of the metric in prometheus
    prom_name: distance
    # The name of the metric in a MQTT JSON message
    mqtt_name: distance
    # The prometheus help text for this metric
    help: distance
    # The prometheus type for this metric. Valid values are: "gauge" and "counter"
    type: gauge

Grafana

Assumes the Prometheus data source is already set up.

Perform the following setup on the Grafana server:

Configure

The secrets.py should look like this:

secrets = {
    "SSID": "FOO",
    "password": "XYZ",
    "broker": "172.40.0.3",
    "broker_port": 1883,
    "log_level": "info",
    "mqtt_topic_env": "devices/pracovna/qtpy",
    "mqtt_topic_power": "devices/plug/pracovna",
    "mqtt_topic": "devices/pracovna/featherTFT",
    "distance_threshold": 90,
    "power_threshold_watts": 35,
    "co2_threshold": 1000,
    "last_update_threshold": 60,
    "break_threshold_seconds": 2700,
    "icon_paths": [
        "/images/icons8-totoro-120.bmp",
        "/images/icons8-totoro-120-umbrella.bmp",
    ],
    "table_state_dur_threshold": 1800,
    "start_hr": 8,
    "end_hr": 23,
    "font_file_name": "fonts/Inter-Regular-25.pcf",
}

Install

It assumes there are 2 120x96 images in the images directory. It will do fine without them, however the table position alerting will resort just to blinking the diode.

With circup installed amd the Feather connected over USB (assuming Linux distro):

circup install -r requirements.txt
cp -R images/ fonts/ *.py settings.toml /media/$USER/CIRCUITPY/

Generating bitmap font

Using bitmap fonts makes the display more readable and nicer. Also, some of the glyps like the circle in °C can be actually displayed. The font however has to be converted to fit onto the flash and then it has to be used in a special way for quick display.

  1. grab the fonts from https://rsms.me/inter/
  2. convert the extras/ttf/Inter-Regular.ttf into BDF (use 25 pixels size) using https://fontforge.github.io/
  3. convert the BDF into PCF for smaller size using https://adafruit.github.io/web-bdftopcf/
  4. copy the resulting file to the CIRCUITPY directory

Guides:

Lessons learned