Как настроить автоматическое напоминание о выключении Bluetooth на macOS

Если вы хотите автоматизировать рутинные задачи на Mac, AppleScript и Automator – первые инструменты, к которым стоит обратиться. Сегодня разберем частый сценарий: напоминание о выключении Bluetooth через заданное время. Кажется, всё просто, но даже опытные пользователи сталкиваются с подводными камнями, особенно при работе с системными командами и таймерами.

Одна из типичных ошибок – использование shell-скриптов для получения времени там, где достаточно встроенных функций AppleScript. Например, команда date +%s (которая возвращает текущее время в секундах с начала эпохи Unix) часто вызывает проблемы с преобразованием типов данных. Вместо этого лучше использовать time of (current date) – это упрощает вычисления и снижает риск ошибок.

В качестве примера, возьмем такой вариант скрипта:

global Cnt
global Cnt2
global Cnt3
global diff
global curTime
global btOnTime
set Cnt to 0
set Cnt2 to 0
set Cnt3 to 0
set btOnTime to do shell script "date +%s"
set curTime to do shell script "date +%s"
set diff to (curTime as integer) - (btOnTime as integer)
set btStatus to 0

repeat
    
    repeat until btStatus = 0
        try
            do shell script "system_Profiler SPBluetoothDataType | grep -i \"State: On\""
            set btStatus to 1
            set btOnTime to do shell script "date +%s"
        on error
            set btStatus to 0
        end try
        -- delay 110
        set Cnt2 to (Cnt2 + 1)
    end repeat
    
    return display alert "BT ON. OUT OF CICLE 1. Cnt2: " & Cnt2
    
    set curTime to do shell script "date +%s"
    repeat while diff < 120
        set curTime to do shell script "date +%s"
        set diff to (curTime as integer) - (btOnTime as integer)
        set Cnt3 to (Cnt3 + 1)
        -- delay 110
    end repeat
    
    return display alert "BT ON. OUT OF CICLE 2. Cnt3: " & Cnt3
    if diff > 120 and Cnt = 0 then
        -- set recentRestart to (curTime - btOnTime) < 10
        -- if not recentRestart then
        return display notification "Stupendo, SPEGNI IL BLUETOOTH!!" with title "Bluetooth acceso da un BOTTO"
        set Cnt to (Cnt + 1)
        -- end if
    end if
    
end repeat

Почему исходный скрипт может не работать?

Давайте посмотрим на ключевые моменты:

1. Глобальные переменные. В оригинальном коде объявлены global Cnt, global Cnt2 и другие. Хотя AppleScript позволяет это, избыточные глобальные переменные усложняют отладку. В большинстве случаев достаточно локальных переменных, объявленных через local (как в исправленной версии).

2. Проверка статуса Bluetooth. Использование system_Profiler SPBluetoothDataType | grep -i “State: On” работает, но не оптимально. Команда system_Profiler может выполняться до 5-10 секунд, что замедляет скрипт. Лучше анализировать вывод напрямую в AppleScript через contains “Bluetooth Power: On”.

3. Тайминги и задержки. В оригинале есть циклы с repeat until и repeat while, которые могут блокировать выполнение скрипта. Добавление delay 2 (как в исправленном коде) снижает нагрузку на процессор и делает проверки более предсказуемыми.

4. Обработка ошибок. Конструкция try…on error в первом скрипте корректно перехватывает отсутствие включенного Bluetooth, но не учитывает возможные таймауты выполнения команды. В исправленной версии добавлен параметр -timeout 4 для system_Profiler, что предотвращает зависания.

Исправленный код с комментариями

Вот оптимизированная версия скрипта, которая решает описанные проблемы:

use scripting additions
local t1, t2, t3, bton, conn

-- Команда для получения статуса Bluetooth (вывод содержит "Bluetooth Power: On" или "Off")
set cmd to "system_Profiler SPBluetoothDataType -timeout 4"
set t1 to time of (current date) -- Время начала (секунды с полуночи)
set t2 to t1 -- Инициализация переменной времени окончания
set bton to 0 -- Счетчик циклов с включенным Bluetooth

repeat until (t2 - t1 ≥ 30) -- Проверяем статус каждые 2 секунды в течение 30 секунд
    set conn to do shell script cmd -- Запуск команды
    if conn contains "Bluetooth Power: On" then
        set bton to 1 + bton
        delay 2 -- Пауза между проверками
        set t2 to time of (current date)
    else
        set bton to 0
        exit repeat -- Выход, если Bluetooth выключен
    end if
end repeat

set t3 to (t2 - t1) -- Общее время работы цикла
if bton ≥ 1 then
    display alert "Bluetooth включен уже " & t3 & " секунд" giving up after 2
else
    display notification "Bluetooth выключен через " & t3 & " секунд"
end if

Как интегрировать скрипт в Automator

1. Откройте Automator (Программы → Automator).
2. Создайте новый документ типа Быстрое действие.
3. В поиске найдите действие Запустить AppleScript и перетащите его в рабочую область.
4. Вставьте исправленный код в текстовое поле.
5. Сохраните действие через Файл → Сохранить (например, под именем «Проверка Bluetooth»).

Чтобы скрипт запускался автоматически, настройте его выполнение через Настройки → Защита и безопасность → Конфиденциальность → Службы автоматизации. Разрешите Automator управлять Bluetooth.

Возможные ошибки и как их исправить

– Скрипт не реагирует на выключение Bluetooth. Убедитесь, что в системе нет других процессов, блокирующих Bluetooth (например, подключенные устройства или фоновые приложения вроде AirDrop).
– Automator не сохраняет изменения. Попробуйте перезапустить Automator и сохранить скрипт с другим именем.
– Нет уведомлений. Проверьте настройки уведомлений macOS (Системные настройки → Уведомления и фокус) – для Automator должны быть разрешены звуковые и визуальные оповещения.

Дополнительные советы

  • Используйте LaunchAgents для периодического запуска. Если нужно проверять Bluetooth каждые 5 минут, создайте plist-файл в ~/Library/LaunchAgents с параметром StartInterval (инструкции есть на сайте Apple Developer).
  • Оптимизируйте запросы к системе. Замените system_Profiler на blueutil (утилита командной строки для управления Bluetooth), если часто сталкиваетесь с таймаутами. Установите через Homebrew:
brew install blueutil

Затем используйте команду blueutil –power on/off` для управления.

Если вы столкнулись с неочевидной ошибкой, попробуйте добавить log “Текст” в код – это выведет сообщения в консоль (Программы → Утилиты → Консоль), где можно отслеживать выполнение скрипта в реальном времени.

Надеюсь, эти решения помогут сделать ваш Mac чуть более автоматизированным. Если остались вопросы – смело пишите в комментарии, постараюсь помочь!

Добавить комментарий

Все поля обязательны к заполнению. Ваш адрес email не будет виден никому.

Новое
Интересное