Visualize Raspberry PI Zero W Processor Temperature Monitoring Data in R

To automatically update data within a small weather visualization project in the regions of the Russian Federation I use an R script that runs on a schedule (every three hours every day) on my small home device, the Raspberry PI Zero W.

Little home helper working 24/7
Little home helper working 24/7

Initial data: cpu_temp.log

This time we will visualize the data of the Raspberry PI processor temperature changes per minute, which are saved in a special log file using a bash script:

#!/bin/bash
date +"%d.%m.%Y %T" | tr '\n' '\t' >> /home/pi/cpu_temp.log ; vcgencmd measure_temp| tr -d "temp=" | tr -d "'C" >> /home/pi/cpu_temp.log

To run a bash script on a schedule via cron, an entry was added (every minute):

*/1 * * * * ~/cpu_temp.sh

As a result of the script execution, data on the processor temperature is saved to the log:

We will visualize this data using R (cpu_temp.R), and insert the Raspberry PI logo on the chart: https://disk.yandex.ru/d/dP16Vwq9sH6RNQ

library(tidyverse)
library(readr)
library(geomtextpath)
library(glue)
library(here)

# Загружаем логотип Raspberry Pi
png <- magick::image_read("raspberrypi-logo.png")
img <- grid::rasterGrob(png, interpolate = TRUE)

# Загружаем данные (лог температуры)
cpu_temp <- read_delim(
    "cpu_temp.log",
    delim = "\t",
    col_names = c("datetime", "cpu_temp"),
    trim_ws = TRUE) %>%
  mutate(datetime = lubridate::as_datetime(datetime,
                                           "%d.%m.%Y %H:%M:%S",
                                           tz = "Asia/Yekaterinburg"))

# Временной интервал для графика -- последние 3 часа из лога
last_datetime <- cpu_temp$datetime[length(cpu_temp$datetime)]
first_datetime <- last_datetime - lubridate::hours(3)

# Описательные для графика (мин, макс, среднее)
maxTempCPU <- max(cpu_temp$cpu_temp[between(cpu_temp$datetime,
                                            first_datetime, last_datetime)])
minTempCPU <- min(cpu_temp$cpu_temp[between(cpu_temp$datetime,
                                            first_datetime, last_datetime)])
meanTempCPU_period <-
  round(mean(cpu_temp$cpu_temp[between(cpu_temp$datetime,
                                       first_datetime, last_datetime)]), 1)

# для вставки лого
mt <- ceiling(max(cpu_temp$cpu_temp))
mt_min <- floor(min(cpu_temp$cpu_temp))
x_max <- last_datetime + lubridate::minutes(25)
x_min <- last_datetime + lubridate::minutes(10)

cpu_temp %>%
  filter(between(datetime, first_datetime, last_datetime)) %>%
  ggplot(aes(datetime, cpu_temp)) +
  annotation_custom(
    img,
    ymin = mt ,
    ymax = mt + 8.25,
    xmin = x_min,
    xmax = x_max
  ) +
  geom_texthline(
    yintercept = mean(cpu_temp$cpu_temp),
    size = 3.75,
    linetype = "dashed",
    linewidth = 0.25,
    label = glue("Среднее за всё время: <b>{round(mean(cpu_temp$cpu_temp),1)}</b>°C"),
    hjust = 0.985,
    vjust = -0.2,
    color = "gray70",
    rich = TRUE
  ) +
  geom_texthline(
    yintercept = meanTempCPU_period,
    size = 3.75,
    linewidth = 0.25,
    label = glue("Среднее за 3 часа: <b>{meanTempCPU_period}</b>°C"),
    hjust = 0.985,
    vjust = -0.2,
    color = "gray70",
    rich = TRUE
  ) +
  geom_step(color = "gray10") +
  scale_y_continuous(
    breaks = seq(mt_min, mt + 1, 2),
    limits = c(mt_min, mt + 1),
    labels = c(as.character(seq(mt_min, mt - 1, 2)),
               glue::glue("{mt + 1}°C"))
  ) +
  scale_x_datetime(
    "Время",
    date_breaks = "30 min",
    date_labels = "%H:%M",
    expand = c(0.15, 0)
  ) +
  labs(
    title = "Температура процессора Raspberry Pi Zero W",
    subtitle = glue(
      "Поминутное изменение температуры за последние 3 часа\n",
      "{format(first_datetime, format="%d %b %H:%M")} - {format(last_datetime, format="%H:%M")}",
      " | Мин {minTempCPU}°C | Среднее {meanTempCPU_period}°C | Макс {maxTempCPU}°C"
    ),
    x = "Время",
    y = ""
  ) +
  coord_cartesian(clip = "off") +
  theme(text = element_text(family = "Open Sans"),
        panel.background = element_blank(),
        axis.title.x = element_text(size = 14),
        plot.margin = margin(25, 30, 10, 12),
        plot.title.position = "plot",
        plot.subtitle = element_text(size = 12, color = "gray60"),
        title = element_text(size = 16),
        axis.text.y = element_text(size = 12),
        axis.text.x = element_text(size = 12)
  )
ggsave(
  glue("img/cpu_temp_{format(last_datetime, '%d_%m_%Y_%H_%M')}.png"),
  dpi = 300,
  scale = 1.5
)

The final chart looks like this:

To run the script every three hours, create a task in cron:

0 */3 * * * Rscript /home/pi/cpu_temp/cpu_temp_pi.R

We will send the resulting graph to ourselves in telegrams via a telegram bot (see an excellent tutorial on creating bots in R) to send personal notifications with a simple command at the end of our script:

bot$sendPhoto(chat_id,
              photo = glue("~/cpu_temp/img/cpu_temp_{format(last_datetime, '%d_%m_%Y_%H_%M')}.png")
)
Messages with a schedule from the bot
Messages with a schedule from the bot

PS: to quickly install the latest version of R without having to compile the main packages, I recommend using the information from project R4Pi.

Similar Posts

Leave a Reply