Skip to content

GeorgeSGN/Ping

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Ping

Личная утилита для мониторинга работы VPN: показывает текущий пинг до Cloudflare (1.1.1.1) и страну выходного узла. Помогает понять, жив ли VPN и через какой регион сейчас ходит трафик.

Состоит из трёх таргетов в одном Xcode-проекте:

  • Ping — iOS-приложение (минимальный экран с инструкцией).
  • PingWidget — iOS Widget Extension, интерактивный виджет на главный экран.
  • Tick — macOS menubar-приложение с автозамером по таймеру.

Локальная утилита, в App Store не публикуется.

Resume Claude-сессии

Вся история разработки в чате с Claude Code, можно продолжить:

claude --resume f24bd348-d95e-45df-ac3c-d6f256e74221

Архитектура

Логика замера

PingService.measure() делает один прогревочный HTTPS-запрос к https://1.1.1.1/cdn-cgi/trace (warmup, не учитывается — нужен чтобы TLS-handshake не задрал первый замер), затем 5 последовательных запросов, меряет RTT каждого, парсит loc=XX из ответа Cloudflare для определения страны.

Таймаут на запрос — 3 секунды. Если все 5 не дошли — loss=100%.

Возвращает PingResult с полями:

  • avg, min, max — статистика по успешным запросам в мс.
  • loss — процент потерянных пакетов (0/20/40/60/80/100).
  • timings: [Double?] — все 5 индивидуальных замеров (nil = таймаут).
  • country — ISO-код страны датацентра Cloudflare (DE, RU, IT, GB...).

PingService.swift продублирован в PingWidget/ и Tick/ (одинаковая логика, разные таргеты).

iOS Widget (PingWidget/)

Виджет размера systemSmall, полностью кликабельный — тап в любую точку запускает замер через MeasurePingIntent (App Intent, iOS 17+).

UI виджета:

  • Цифра avg ms с градиентом цвета по значению (зелёный→жёлтый→красный, плавная HSB-интерполяция в диапазоне 30–220 мс).
  • 5 столбиков пропорциональной высоты, цвета по тому же градиенту, с цифрами внутри.
  • Капсула с полным названием страны (Locale.localizedString(forRegionCode:)) в правом верхнем углу.
  • При loss=100% — крупный «—» и подпись timeout.

Хранение: последний результат пишется в UserDefaults.standard внутри extension'а (PingStore.save/load).

macOS menubar (Tick/)

Приложение без иконки в Dock (LSUIElement=YES), только пункт в строке меню сверху через MenuBarExtra.

В menubar-label: только цифра, типа 46 ms (или — ms при таймауте, или wifi-иконка пока нет данных).

Дропдаун при клике:

  • Цифра avg ms с градиентом + ISO-код страны рядом.
  • 5 столбиков с цифрами (компонент MacPingBars).
  • Пикер интервала автозамера: 5s / 30s / 1min / 5min / Off (хранится в UserDefaults).
  • Тумблер «Launch at login» через SMAppService.mainApp (требует наличия app в /Applications/).
  • Кнопки «Measure now» и «Quit».

PingMonitor (ObservableObject) держит Timer, по умолчанию замер раз в 30 секунд. Автопауза при засыпании экрана через NSWorkspace.screensDidSleepNotification и автозамер при пробуждении.

Подписи

Все таргеты подписаны Personal Team (бесплатный Apple ID). На бесплатном профиле подпись iOS-приложения протухает раз в 7 дней — приходится переустанавливать через Xcode.

macOS Tick подписан Development-сертификатом, работает на этой машине бессрочно.

Установка

iOS Widget (Ping + PingWidget)

В Xcode:

  1. Выбрать схему Ping, цель — подключённый iPhone.
  2. Run (⌘R).
  3. На iPhone: добавить виджет на главный экран (long-press → «+» → найти Ping).

Переподпись раз в неделю

Personal Team (бесплатный Apple ID) выпускает сертификат всего на 7 дней. После этого iOS перестаёт запускать приложение и виджет — увидишь ошибку «не удалось проверить разработчика».

Раз в неделю:

  1. Подключить iPhone кабелем.
  2. В Xcode: схема Ping, цель — iPhone, жмёшь Play (⌘R).
  3. Готово. Виджет на главном экране сам подхватит, перенастраивать не надо.

Альтернативы:

  • $99/год Apple Developer — сертификат на год, переподпись не нужна.
  • AltStore/SideStore — автопереподпись, но требует своей возни с настройкой.

macOS menubar (Tick)

Из репозитория собирается Release-версия (universal-бинарник для Apple Silicon + Intel) и кладётся в /Applications. В конце удаляются временные копии из DerivedData, иначе Spotlight/Launchpad начинают показывать несколько одинаковых иконок «Tick».

cd /Users/george_ns/Developer/Ping
pkill -f "Tick$" 2>/dev/null
xcodebuild -scheme Tick -configuration Release -destination 'platform=macOS' \
  ARCHS='arm64 x86_64' ONLY_ACTIVE_ARCH=NO build
rm -rf /Applications/Tick.app
cp -R ~/Library/Developer/Xcode/DerivedData/Ping-*/Build/Products/Release/Tick.app /Applications/
rm -rf ~/Library/Developer/Xcode/DerivedData/Ping-*/Build/Products/Debug/Tick.app
rm -rf ~/Library/Developer/Xcode/DerivedData/Ping-*/Build/Products/Release/Tick.app
killall Dock 2>/dev/null
open /Applications/Tick.app

Для пересборки DMG для раздачи друзьям после этого:

cd /Users/george_ns/Developer/Ping
mkdir -p dist/staging && cp -R /Applications/Tick.app dist/staging/
ln -sf /Applications dist/staging/Applications
hdiutil create -volname Tick -srcfolder dist/staging -ov -format UDZO dist/Tick.dmg
rm -rf dist/staging

После запуска — клик на цифру в меню → включить «Launch at login».

Важно: SMAppService запоминает путь к app. Если запустить Tick через Xcode (он живёт в DerivedData), а потом включить автозапуск — после ребута macOS будет искать Tick.app в DerivedData, что нестабильно. Поэтому только из /Applications.

В отличие от iOS, macOS не требует еженедельной переподписи — Development-сертификат живёт около года, и macOS не делает регулярных проверок свежести подписи у уже установленных приложений. Tick в /Applications будет работать сколь угодно долго, пока сам не удалишь.

Перенос на другой Mac или после переустановки

  1. Открыть проект в Xcode — он перевыпустит сертификаты автоматически.
  2. Запустить команды установки выше.

Каталог иконок Cloudflare

Поле colo= в trace отвечает за конкретный датацентр (трёхбуквенный IATA-код аэропорта), loc= — за страну (ISO-2). Сейчас используем loc, но если когда-нибудь захочется датацентр для большей точности — в PingService.parseCountry достаточно поменять одну строку.

Примеры colo: FRA Франкфурт, AMS Амстердам, MXP Милан, DME Москва-Домодедово, LED Санкт-Петербург, IST Стамбул, WAW Варшава.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages