Для автоматического обновления данных в рамках небольшого проекта по визуализации погоды в регионах РФ используется скрипт на языке R, который выполняется по расписанию (ежедневно каждые три часа) на моём маленьком домашнем устройстве — Raspberry PI Zero W.
Исходные данные: cpu_temp.log
В этот раз мы будем визуализировать данные поминутного изменения температуры процессора Raspberry PI, которые сохраняются в специальным лог-файле c помощью bash-скрипта:
#!/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
Для запуска bash-скрипта по расписанию через cron была добавлена запись (каждую минуту):
*/1 * * * * ~/cpu_temp.sh
В результате выполнения скрипта данные о температуре процессора сохраняются в лог:
Эти данные мы и будем визуализировать с помощью R (cpu_temp.R), а на график вставим лого Raspberry PI: 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
)
Финальный график выглядит так:
Для запуска скрипта каждые три часа создадим задачу в cron:
0 */3 * * * Rscript /home/pi/cpu_temp/cpu_temp_pi.R
Полученный график будем отправлять себе в телеграм через телеграм-бота (см. отличный туториал по созданию ботов в R) для отправки личных уведомлений простой командой в конце нашего скрипта:
bot$sendPhoto(chat_id,
photo = glue("~/cpu_temp/img/cpu_temp_{format(last_datetime, '%d_%m_%Y_%H_%M')}.png")
)
PS: для быстрой установки R последней версии без необходимости компиляции основных пакетов рекомендую воспользоваться информацией из проекта R4Pi.