bspwm - делимся полезными наработками

Предлагаю размещать здесь у кого что есть интересного по bspwm

Скрипт погоды для polybar и Погода с яндекса, дополнение (спасибо patashnik), значительно упрощающее задачу
"Сворачивание" окон на панель
Планируется:
Разные режимы создания новых окон а автоматическом режиме и их смена "на лету" (layouts)
Выпадающий терминал
Scratchpads - вызов во float режиме и скрытие любых окон на текущем workspase
Зарезервировано...
Скрипт погоды для polybar

Давно хотел сделать погоду на панели WM такую как хочется. А именно - чтобы без сторонних приложений, без погодных сервисов, исходя из того что сайт погоды есть в свободном доступе, брать с него данные и выводить на панель. Вот и сделал. Данный вариант работает с панелью polybar, но его при желании можно легко приспособить и для xmobar, и для dzen, и для других подобных панелей. По клику на панели погода переключается в краткий формат (только иконка и температура) и развернутый формат (краткий + влажность + направление и скорость ветра + давление + тенденция давления: растет/падает)



Конструкция состоит из 4 файлов с данными - это промежуточный и конечный с данными веб-страницы, pipe канал, конф-файл состояния кратко/подробно,
~/.config/.curweath-tmp
~/.config/.curweath-web
/tmp/.weather-pipe
~/.config/.pb-weather-mode

3 небольших скриптов:
Скрипт 1 ~/.bin/pb-get-weather
Запускается каждые 10 мин., если есть пинг
Качает страницу, запускает Скрипт 2
Скрипт 2 ~/.bin/pb-superweather
парсит страницу и загоняет данные в pipe, читая конф-файл
Скрипт 3 (по клику) ~/.bin/toggle-pb-weather
Переключает параметр конф-файла и запускает Скрипт 2

и двух модулей панели polybar:
Модуль 1
Ничего не выводит, а только запускает Скрипт 1 с заданным интервалом
Модуль 2
Читает pipe и выводит на панель, по клику запускает Скрипт 3

Данные о погоде берутся с сайта accuweather.com
Используется шрифт Weather Icons

Итак, по порядку:
1. Именованный канал.
Создаем канал где-нибудь в автозагрузке (например, в .xinitrc)
mkfifo /tmp/.weather-pipe &

2. Скрипт 1 ~/.bin/pb-get-weather
#!/usr/bin/bash
# Search for your city at http://www.accuweather.com and replace the URL in the following script with the URL for your city

~/.bin/pb-superweather $(cat ~/.config/.pb-weather-mode) && wget -q -O ~/.config/.curweath-tmp "http://www.accuweather.com/ru/ru/surgut/288459/current-weather/288459" && cp ~/.config/.curweath-tmp ~/.config/.curweath-web && ~/.bin/pb-superweather $(cat ~/.config/.pb-weather-mode)

Почему мы здесь сначала запускаем Скрипт 2, затем качаем страницу и потом повторно запускаем Скрипт 2? Потому что Скрипт 1 запускается при старте/перезагрузке панели (системы) и нужно сразу вывести данные на панель, пусть даже устаревшие, но они отобразятся сразу, а потом пусть неспешно (ведь инет не всегда быстрый) обновятся. А почему 2 файла ~/.config/.curweath-tmp и ~/.config/.curweath-web? Так инет жеж не всегда быстрый, и если wget будет работать несколько секунд, а в это время сработает Скрипт 2, то в pipe полетит ошибка, копирование же произойдет мгновенно и ошибка вылезти не успеет.

Адрес "http://www.accuweather.com/ru/ru/surgut/288459/current-weather/288459" - это Сургут, пройдите по ссылке, выберите свое место и скопируйте адресную строку браузера в скрипт.

Если вы используете не polybar, то можете в автозагрузку поставить примерно такой скрипт:
#!/usr/bin/bash
# Search for your city at http://www.accuweather.com and replace the URL in the following script with the URL for your city
SLEEP_INTERVAL=60

while :
do
if `ping -c 1 -w 5 8.8.8.8 &> /dev/null`
then
    SLEEP_INTERVAL=600
     ~/.bin/pb-superweather $(cat ~/.config/.pb-weather-mode) && wget -q -O ~/.config/.curweath-tmp
"http://www.accuweather.com/ru/ru/surgut/288459/current-weather/288459" && cp ~/.config/.curweath-tmp ~/.config/.curweath-web && ~/.bin/pb-superweather $(cat ~/.config/.pb-weather-mode)
fi
    sleep $SLEEP_INTERVAL
done

Скрипт 2 ~/.bin/pb-superweather
#!/usr/bin/bash

if ! [ -f "$HOME/.config/.pb-weather-mode" ]; then
	touch $HOME/.config/.pb-weather-mode
fi

if ! [ -f "$HOME/.config/.curweath-web" ]; then
	echo "%{F#2587CB}%{T5}%{T-}%{F-}"
	exit 0
fi

# температура
WTEMP="$(cat ~/.config/.curweath-web | awk -F\' '/acm_RecentLocationsCarousel\.push/{print $10"°C"}'| head -1)"

# погода
WCONDI="$(cat ~/.config/.curweath-web | awk -F\' '/acm_RecentLocationsCarousel\.push/{print $13}' | head -1 | cut -c 10- | rev | cut -c 5- | rev | sed 's/.*/\L&/')"

# направление ветра
# скорость ветра м/с
WSP="$(echo "$(grep км/ч ~/.config/.curweath-web | cut -c 26- | rev | cut -c 24- | rev) * 1000 / 3600" | bc)"
if grep -q Безветренно  ~/.config/.curweath-web
then
  WSPEED="";
  WWINGH="С"
else
  WSPEED="$(echo " $WSP m/s")";
  WWINGH="$(grep wind-point ~/.config/.curweath-web | cut -c 28- | rev | cut -c 10- | rev)"
fi

# давление мм/рт.ст
WPRESS="$(echo "$(grep Давление ~/.config/.curweath-web | cut -c 59- | cut -c 1-7) * 750064 / 1000000" | bc)"

# давление растет/парадает
if grep -q uarr  ~/.config/.curweath-web
then
   WPREST=" ";
elif grep -q darr  ~/.config/.curweath-web
then
   WPREST=" ";
else
   WPREST="";
fi

#влажность %
WETNES="$(grep Влажность ~/.config/.curweath-web | cut -c 61- | rev | cut -c 17- | rev)"

# N — обозначает северный ветер, Е — востчный, S — южный, W — западный, С — затишье (нет ветра).
# NE — северо-восток, SE — юго-восток, SW — юго-запад, NW — северо-запад.
# NNE — обозначает северо-северо-восток, ENE — востоко-северо-восток, ESE — востоко-юго-восток и т. д.
WI=("N" "E" "S" "W" "С" "NE" "SE" "SW" "NW" "NNE" "ENE" "ESE" "SSE" "SSW" "WSW" "WNW" "NNW" "*")
WO=("" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "")
for i in $(seq 0 ${#WI[@]}); do
    if [[ "$WWINGH" == "${WI[$i]}" ]]; then
      WINGICON="${WO[$i]}"
    fi
done
TIMESDAY="ITSNIGHT"
    HOUR=$(date +"%-H")
    MONTH=$(date +"%-m")

# time is relevant for 60 parallels, for other places it is necessary to set an appropriate time of sunrise and sunset for each month of the year
    if [[ 6 = "$MONTH" || 7 = "$MONTH" ]]; then
      if (( $HOUR >= 3 && $HOUR <= 23 )); then
        TIMESDAY="ITSDAY"
      fi
    elif [[ 5 = "$MONTH" || 8 = "$MONTH" ]]; then
      if (( $HOUR >= 4 && $HOUR <= 22 )); then
        TIMESDAY="ITSDAY"
      fi
    elif [[ 4 = "$MONTH" || 9 = "$MONTH" ]]; then
      if (( $HOUR >= 5 && $HOUR <= 20 )); then
        TIMESDAY="ITSDAY"
      fi
    elif [[ 3 = "$MONTH" || 10 = "$MONTH" ]]; then
      if (( $HOUR >= 6 && $HOUR <= 18 )); then
        TIMESDAY="ITSDAY"
      fi
    elif [[ 2 = "$MONTH" || 11 = "$MONTH" ]]; then
      if (( $HOUR >= 7 && $HOUR <= 16 )); then
        TIMESDAY="ITSDAY"
      fi
    else [[ 1 = "$MONTH" || 12 = "$MONTH" ]]
      if (( $HOUR >= 8 && $HOUR <= 15 )); then
        TIMESDAY="ITSDAY"
      fi
    fi

II=("преимущественно ясно" "ясно" "солнечно" "слабый туман" "слабый снег и туман" "слабый снегопад" "небольшой снег" "сильный снегопад" "снегопад" "снег с дождем" "снег" "значительная облачность" "облачно с прояснениями" "небольшая облачность" "преимущественно облачно" "малооблачно" "облачно" "метель" "дождь" "ливень с грозой" "ливень" "гроза" "небольшой туман" "*")

S2="ITSDAY"
if [ $TIMESDAY = $S2 ]; then
IO=("" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "")
else
IO=("" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "")
fi

for i in $(seq 0 ${#II[@]}); do
    if [[ "$WCONDI" == "${II[$i]}" ]]; then
      WICON="${IO[$i]}"
    fi
done

FULLMODE="full"
APPLICATION=$1

if [[ "$APPLICATION" == "$FULLMODE" ]]; then
   echo "%{T5}$WICON%{T-} $WTEMP %{F#55}%{T5}%{T-}%{F-} $WETNES %{F#9F78E1}%{T5}$WINGICON%{T-}%{F-}$WSPEED %{F#55}%{T5}%{T-}%{F-} $WPRESS%{T5}$WPREST%{T-}" > /tmp/.weather-pipe
else
  echo "%{T5}$WICON%{T-} $WTEMP" > /tmp/.weather-pipe
fi

exit 0

Как вы поняли, погодные иконки рисуются разные для дня и ночи и в блоке где определяется день сейчас или ночь
if [[ 6 = "$MONTH" || 7 = "$MONTH" ]]; then
      if (( $HOUR >= 3 && $HOUR <= 23 )); then
        TIMESDAY="ITSDAY"
у меня указано, что в месяцах 6 и 7 днем считать время от 3 до 23 часов и т.д., вы, конечно же, должны проставить свои параметры.

Скрипт 3 ~/.bin/toggle-pb-weather
#!/usr/bin/bash

WMODE="$(cat ~/.config/.pb-weather-mode)"
FLMODE="full"

if [[ "$WMODE" == "$FLMODE" ]]; then
  echo "" > ~/.config/.pb-weather-mode
else
  echo "full" > ~/.config/.pb-weather-mode
fi

~/.bin/pb-superweather $(cat ~/.config/.pb-weather-mode)
exit 0

Модули панели
.....
modules-right = ... get-weather weather...
.....
;=====================================================
; Module get-weather
;=====================================================
[module/get-weather]
type = custom/script
format = <label>
label =
exec = ~/.bin/pb-get-weather
exec-if = ping -c 1 -w 5 8.8.8.8 &> /dev/null
interval = 600

;=====================================================
; Module weather
;=====================================================
[module/weather]
type = custom/script
exec = tail -F /tmp/.weather-pipe
exec-if = [ -p /tmp/.weather-pipe ]
tail = true
format = <label>
label = %output%
click-left = ~/.bin/toggle-pb-weather
click-right =
label-padding    = 2
label-background = #55

.....
Еще один момент: у меня в polybar шрифты заданы в следующем порядке:
.....
font-0 = Play:pixelsize=11:antialias=false;3
font-1 = unifont:fontformat=truetype:size=8:antialias=false;0
font-2 = Symbola:pixelsize=12;3
font-3 = FontAwesome:pixelsize=10:antialias=false;3
font-4 = Weather Icons:pixelsize=12:antialias=false;4
font-5 = fixed:pixelsize=10;3
font-6 = siji:pixelsize=10;1
font-7 = Symbola:pixelsize=13;3
.....

Стало быть шрифт Weather Icons у меня пятый, и он выводится в ~/.bin/pb-superweather следующим образом
echo "%{T5}$WICON%{T-}....
Если у вас другой порядок шрифтов, замените 5 на свое значение.

Ну вот кажется и все, буду рад дельным советам :)
--
p.s. Если пропадет иконка состояния погоды, значит на сайте появилась новая фраза. Зайдите на сайт, посмотрите что там, например, не "Солнечно", а "Грибной дождик", и допишите в массивы скрипта ~/.bin/pb-superweather новую фразу и соответствующую ей иконку.
Тема "bspwm - делимся полезными наработками", а написано про polybar. И зачем так мучаться с погодой, если можно: а) закурлить со спец.ресурсов, б) запарсить по человечески, в) использовать пакеты из аура, которые погоду в терминал кидают, г) на каком-нибудь яп с поддержкой модулей/сторонних библиотек по ключу выводить погоду.
SirKittyKnight, я же написал чего хотел: "чтобы без сторонних приложений, без погодных сервисов", если бы я хотел с ключами/пакетами/в терминал, то сделал бы по-другому.
SirKittyKnight
запарсить по человечески,
Если есть предложение по оптимизации кода - буду рад...
Погода с яндекса

#!/bin/bash
# установить xmlstarlet

region=1 # https://tech.yandex.ru/xml/doc/dg/reference/regions-docpage/
curl -s "https://export.yandex.ru/bar/reginfo.xml?region=$region" -o /tmp/weather.xml

xml_sel() {
  xmlstarlet sel -t -m "info/weather/day/day_part[1]" -v "$1" /tmp/weather.xml
}

cond="$(xml_sel weather_type)"   # погода
wind="$(xml_sel wind_speed)"     # ветер м/с
dire="$(xml_sel wind_direction)" # направление
damp="$(xml_sel dampness)"       # влажность %
pres="$(xml_sel pressure)"       # давление рт. ст.
temp="$(xml_sel temperature)"    # температура С°
icon="$(xml_sel image)"          # иконка

# пример
echo -e "Погода:\\t\\t$cond
Ветер:\\t\\t$wind м/с ($dire)
Влажность:\\t$damp %
Давление:\\t$pres рт. ст.
Температура:\\t$temp С°
Картинка:\\t$icon"

$ yandex_weather
Погода:         облачно
Ветер:          2.8 м/с (восток)
Влажность:      94 %
Давление:       748 рт. ст.
Температура:    +10 С°
Картинка:       https://yastatic.net/weather/i/icons/blueye/24/ovc.png
patashnik
Погода с яндекса
Спасибо огромное! Давно искал нечто подобное. Добавлю в шапку и потестирую.
Благодарю.
[email protected],
по-поводу сторонних сервисов, вы же в своем же скрипте используете сторонний сервис. Если у вас нет собственных датчиков, то зачем придумывать велосипед, если есть готовый. Как написали выше, через яндекс. Можно через
curl wttr.in/Moscow
Можно через яп, например, у меня через питон:
#!/usr/bin/env python3

import pyowm

owm = pyowm.OWM('*******')
place = owm.weather_at_place('Moscow,ru')
weather = place.get_weather()
temp = str(round(int(weather.get_temperature('celsius')['temp']), 0)) + '°C'
#wind = str(weather.get_wind()['speed']) + 'm/s'
status = str(weather).split(',')[-1].replace('status=', '').replace('>', '')
print(status, temp)

Drizzle 0°C
SirKittyKnight, говоря о сервисах, я имел в виду вот это, где "Fast, Low Priced and Automated, the simplest way to get AccuWeather?s Weather Data at your end, starting at US$0.69 per month.", а читать страницу, которая в открытом доступе - не есть использование какого-то сервиса.
 
Зарегистрироваться или войдите чтобы оставить сообщение.