Обновление репозитория

This commit is contained in:
Lina 2026-03-05 17:13:19 +03:00
parent 5082c5efa4
commit 9e5a561c5b
13 changed files with 406 additions and 0 deletions

View File

@ -0,0 +1,21 @@
В проекте я использовала клон Arduino Nano: **ATmega328P** c USB-mini портом.
В качестве датчика температуры и влажности клон SHT31: на маркетплейсе он был
обозначен как "**SHT31-D**", на плате указано "**SHT3X**".
Эти две платы необходимо соединить по следующим пинам:
|SHT31 | -> | Arduino Nano|
|------|------|--------------|
|Vin |-> | 3V3 |
|GND |-> |GND |
|SCL |-> |A5 |
|SDA |-> |A4 |
Датчик также работал и при подключении Vin -> +5V, но его работа была
нестабильной и он выдавал повышенные показания.
Также столкнулась с тем, что плата работает стабильнее при прямом подключении в
USB-порт компьютера, а не через USB-хаб.

View File

@ -0,0 +1,83 @@
**2. Прошивка Arduino nano**
В каталоге *arduino* лежит файлы для прошивки arduino nano (ATmega328P).
Для прошивки: устанавила Arduino IDE (из AUR)
**yay -S --aur arduino-ide-bin **
и пакет для доступа к ней через терминал:
**sudo pacman -S arduino**
Разрешаем текущему пользователю доступ к последовательным портам (и
соответсвующим lock файлам) :
**sudo usermod -a -G uucp $USER sudo usermod -a -G lock $USER**
Так как при каждом перетыкивании платы в USB-порт linux увеличивает его
значение (USB0, затем USB1, USB2... и т.д.), я добавила правило для именования
порта для arduino, то есть чтобы порт всегда назывался одинаково
("/dev/arduino") и всегда имел права 666:
выполняем в терминале:
**lsusb **
ищем в нём нашу ардуинку: должно быть что-то вроде:
*Bus 001 Device 003: **ID** **1a86:7523** QinHeng Electronics CH340 serial
converter*
запоминаем полученный **ID**!
выполняем команды:
**sudo nano /etc/udev/rules.d/99-arduino.rules**
вставляем код (замените ID **1a86:7523** на ваши, если плата отличается)
SUBSYSTEM=="tty", ATTRS{idVendor}=="**1a86**", ATTRS{idProduct}=="**7523**",
SYMLINK+="arduino", MODE="0666"
Выполняем запись и выходим: жмём **Ctrl+O**, затем **Ctrl+X**.
применяем правило:
**sudo udevadm control --reload-rules && sudo udevadm trigger**
проверяем:
** ls -l /dev/arduino**
должно вывести примерно так:
*lrwxrwxrwx 1 root root 7 фев 21 15:54 /dev/arduino -> ttyUSB0*
**Запускаем Arduino IDE:**
в **Менеджере плат** (кнопка слева) ищем и устанавливаем: ***Arduino AVR Boards*, **
затем (кнопка ниже) ищем и устанавливаем библиотеку: **Adafruit SHT31 Library**.
Теперь надо **выбрать модель платы**: Инструменты -> Плата -> Менеджер плат ->
Arduino AVR Boards - **Arduino Nano**
**Выбрать порт**: Инструменты -> Серийный порт: **/dev/tty/USB0** (обычно arduino
IDE сама определяет нужный порт, просто тыкаем в него)
**Выбираем загрузчик**: Инструменты -> Processor -> **Atmega328P (Old bootloader)**
Теперь всё должно быть готов для прошивки: вставляем код **sketch_hum_temp.ino **и жмем на кнопку слева (->) "Загрузить на плату". В случае успеха :) ошибок быть не должно и прошивка загрузиться, всё замигает красный светодиод и перестанет - значит данные отправляются в порт USB.
Для проверки, что данные приходят: или в Arduino IDE тыкаем кнопку "Монитор
порта" (изображена в виде лупы вверху слева)). ,
или в терминале вводим: **cat
/dev/arduino**
должно будет вывести сообщения инициализации датчика и отправлять данные о
температуре и влажности каждые 30 секунд.
если всё OK, тогда жмем **Ctrl+С** чтобы прервать чтение из порта, закрываем
терминал и закрываем IDE (чтобы освободить порт arduino)

View File

@ -0,0 +1,24 @@
**3.Декслет для показа данных о температуры и влажности на рабочем столе Cinnamon**
Он довольно примитивный, при желании вы можете перенастроить его "под себя".
В текущей версии он показывает температуру и влажность, а также время получения
этих данных (обновляется каждые 30 секунд).
Для наглядности в декслет добавлены смайлики:
смайлик довольный 😊, если влажность в пределах нормы: от 40% до 60% (иначе: если жарче 🥵, если холоднее 🥶)
смайлик довольный😊, если температура в пределах комфортной: от 22С до 27С (иначе: если сухой воздух 😮‍💨, если влажный 😶‍🌫️)
**Установка**.
Установка заключается в двух действиях:
скопировать из проекта папку **home-meteo@lina** в папку по адресу:
**/home/*имя вашего пользователя*/.local/share/cinnamon/desklets**
после этого на рабочем столе кликнете правой кнопкой мыши "**добавить декслет**", выбрать из списка
**Home Meteo** *Домашняя метеостанция*, нажать "+" для запуска.

View File

@ -0,0 +1,26 @@
**3.Виджет для показа данных о температуры и влажности на рабочем столе KDE PLASMA 6**
Виджет показывает температуру и влажность, а также время получения
этих данных (обновляется каждые 30 секунд).
Для наглядности в декслет добавлены смайлики:
Смайлик довольный 😊, если влажность в пределах нормы: от 40% до 60% (иначе: если жарче 🥵, если холоднее 🥶)
Смайлик довольный😊, если температура в пределах комфортной: от 22С до 27С (иначе: если сухой воздух 😮‍💨, если влажный 😶‍🌫️)
**Установка**.
Установка заключается в двух действиях:
1) перейти в папку org.kde.plasma.homemeteo/package, запустить терминал и выполнить команду для установки виджета в систему:
**kpackagetool6 -t Plasma/Applet --install .**
(обратите внимание, "." точка в конце команды важна!)
*фактически эта команда скопирует содержимое виджета в каталог пользовательских виджетов по следующему пути:* /home/ИМЯ_Пользователя/.local/share/plasma/plasmoids/org.kde.plasma.homemeteo/
2) после этого на рабочем столе кликнете правой кнопкой мыши "**Перейти в режим редактирования**", Нажать на кнопку "добавить или изменить виджеты" и выбрать из списка
**Home Meteo** *Домашняя метеостанция*
[screenshot5.png](README_files/screenshot5.png) , и разместить в удобном месте рабочего стола. После запуска виджета первые данные придут через 30-35 секунд.

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0">
<group name="General">
<entry name="fontSize" type="Int">
<default>16</default>
</entry>
<entry name="customColor" type="Color">
<default>#ffffff</default>
</entry>
<entry name="useCustomColor" type="Bool">
<default>false</default>
</entry>
</group>
</kcfg>

View File

@ -0,0 +1,11 @@
# #!/bin/bash
#
# Настройка порта
stty -F /dev/arduino 9600 raw -echo -icanon hupcl 2>/dev/null
cat /dev/arduino | while read -r line; do
if [[ $line =~ ([0-9.]+)[[:space:]]+([0-9.]+) ]]; then
# Перезаписываем файл: только текущие значения T и H
echo "${BASH_REMATCH[1]} ${BASH_REMATCH[2]}" > /tmp/arduino_last_run
fi
done

View File

@ -0,0 +1,210 @@
import QtQuick
import QtQuick.Layouts
import org.kde.plasma.plasmoid
import org.kde.plasma.components as PlasmaComponents
import org.kde.plasma.plasma5support as Plasma5Support
import org.kde.plasma.core as PlasmaCore
PlasmoidItem {
id: root
readonly property int fontSize: (Plasmoid.configuration.fontSize
> 0) ? Plasmoid.configuration.fontSize : 16
readonly property color textColor: Plasmoid.configuration.useCustomColor ? Plasmoid.configuration.customColor : PlasmaComponents.Label.color
// Настройка заголовка и иконки через присоединенное свойство
Plasmoid.title: i18n("Home Meteo")
Plasmoid.icon: "applications-system"
property string tempValue: "--.-"
property string humValue: "--.-"
property string tempEmoji: "⏳"
property string humEmoji: "⏳"
property string lastUpdate: "..."
width: 320
height: 180
Plasmoid.backgroundHints: PlasmaCore.Types.NoBackground
| PlasmaCore.Types.ConfigurableBackground
fullRepresentation: Rectangle {
id: mainCanvas
implicitWidth: 320
implicitHeight: 180
color: Qt.rgba(root.textColor.r, root.textColor.g,
root.textColor.b, 0.2)
radius: 15
border.color: root.textColor
border.width: 1
clip: true
GridLayout {
// Привязываемся к краям родителя с внутренним отступом
anchors.fill: parent
anchors.margins: 10
columns: 2
rowSpacing: 0 // Убираем лишние промежутки между строками
columnSpacing: 10
// Заголовки
PlasmaComponents.Label {
Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter
text: "Температура, °C"
font.pointSize: root.fontSize * 0.8
color: root.textColor
opacity: 0.7
}
PlasmaComponents.Label {
Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter
text: "Влажность, %"
font.pointSize: root.fontSize * 0.8
color: root.textColor
opacity: 0.7
}
// Эмодзи
Text {
Layout.topMargin: 5
Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter
text: root.tempEmoji
font.pointSize: root.fontSize * 2.6
}
Text {
Layout.topMargin: 5
Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter
text: root.humEmoji
font.pointSize: root.fontSize * 2.6
}
// Значения
PlasmaComponents.Label {
Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter
text: root.tempValue
font.pointSize: root.fontSize * 1.6
font.bold: true
color: root.textColor
}
PlasmaComponents.Label {
Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter
text: root.humValue
font.pointSize: root.fontSize * 1.6
font.bold: true
color: root.textColor
}
PlasmaComponents.Label {
Layout.columnSpan: 2
Layout.fillWidth: true
Layout.topMargin: 5 // Небольшой отступ от цифр
horizontalAlignment: Text.AlignHCenter
text: "Обновлено: " + root.lastUpdate
font.pointSize: root.fontSize * 0.6
opacity: 0.7
color: root.textColor
}
}
gradient: Gradient {
GradientStop {
position: 0.0
color: "azure"
}
GradientStop {
position: 0.7
color: "honeydew"
}
GradientStop {
position: 2.0
color: "lightgoldenrodyellow"
}
}
}
// Источник данных для чтения файла
Plasma5Support.DataSource {
id: fileProcessor
engine: "executable"
connectedSources: []
onNewData: (source, data) => {
let stdout = data.stdout ? data.stdout.trim() : "";
// ШАГ 1: Проверка размера
if (source.includes("stat -c%s")) {
let size = parseInt(stdout) || 0;
if (size > 1024) {
fileProcessor.connectSource("> /tmp/arduino_last_run");
console.log("Критический размер файла! Очистка.");
} else {
// Переход к шагу 2
fileProcessor.connectSource("stat -c%y /tmp/arduino_last_run | awk '{print $2}' | cut -d. -f1");
}
}
// ШАГ 2: Получение времени (ищем формат 00:00:00)
else if (stdout.match(/^\d{2}:\d{2}:\d{2}$/)) {
root.lastUpdate = stdout;
// Переход к шагу 3
fileProcessor.connectSource("cat /tmp/arduino_last_run");
}
// ШАГ 3: Чтение самих данных
else if (source.includes("cat ")) {
parseData(stdout);
}
disconnectSource(source);
}
}
Timer {
id: refreshTimer
interval: 5000
running: true
repeat: true
triggeredOnStart: true
onTriggered: {
// Запуск цепочки: проверяем размер.
// Если файла нет, echo 0 предотвратит ошибку DataSource.
fileProcessor.connectSource("stat -c%s /tmp/arduino_last_run 2>/dev/null || echo 0");
}
}
function parseData(out) {
if (!out) return;
let m = out.match(/[-+]?[0-9]*\.?[0-9]+/g)
if (m && m.length >= 2) {
let t = parseFloat(m[0])
let h = parseFloat(m[1])
root.tempValue = t.toFixed(1)
root.humValue = h.toFixed(1)
root.tempEmoji = t > 27 ? "🥵" : (t < 22 ? "🥶" : "😊")
root.humEmoji = h < 40 ? "😮‍💨" : (h > 60 ? "😶‍🌫️" : "😊")
}
}
Plasma5Support.DataSource {
id: scriptLauncher
engine: "executable"
connectedSources: []
Component.onCompleted: {
// В Plasma 6 используем Qt.resolvedUrl для получения пути к текущей папке
// .replace("file://", "") нужно, так как DataSource ожидает путь к системе, а не URL
let currentDir = Qt.resolvedUrl(".").toString().replace("file://",
"")
let scriptPath = currentDir + "arduino_bridge.sh"
if (scriptPath) {
scriptLauncher.connectSource(`chmod +x ${scriptPath} && ${scriptPath}`)
}
}
}
}

View File

@ -0,0 +1,17 @@
{
"KPackageStructure": "Plasma/Applet",
"KPlugin": {
"Category": "Environment and Weather",
"Id": "org.kde.plasma.homemeteo",
"Name": "Home Meteo",
"Name[ru]": "Домашняя метеостанция",
"Description": "Home Arduino Meteo Station",
"Description[ru]": "Домашняя метеостанция на базе Arduino",
"Version": "1.0",
"Authors": [{ "Name": "Lina" }],
"Icon": "weather-showers-day",
"ServiceTypes": ["Plasma/Applet"]
},
"X-Plasma-API-Minimum-Version" : "6.0"
}