#крутое дня
Не то чтоб я собирался всё же сходу показывать дизайн будущего пульта целиком, думал, буду сразу стили на Flutter набрасывать и выкладывать в песочницу, но пара подписчиков захотела это ещё и на HTML/CSS отверстать. Да, @mazya? :)
Не могу сказать, что я прям принимаю вызов, процесс у меня будет двигаться медленно. Но чо бы и нет, мне эти стили пригодятся 😊
В общем, смотрим, комментируем: https://www.figma.com/file/ZEOa8mgVHabB3pgiEuwCm4/mi-tv-remote-app-control-(Copy)
#flutter #figma #remote
Не то чтоб я собирался всё же сходу показывать дизайн будущего пульта целиком, думал, буду сразу стили на Flutter набрасывать и выкладывать в песочницу, но пара подписчиков захотела это ещё и на HTML/CSS отверстать. Да, @mazya? :)
Не могу сказать, что я прям принимаю вызов, процесс у меня будет двигаться медленно. Но чо бы и нет, мне эти стили пригодятся 😊
В общем, смотрим, комментируем: https://www.figma.com/file/ZEOa8mgVHabB3pgiEuwCm4/mi-tv-remote-app-control-(Copy)
#flutter #figma #remote
🔥12👍4❤2
Media is too big
VIEW IN TELEGRAM
#прогресс дня
Чутка заболел, но зато всё-таки начал писать приложение-пульт.
Итак, открытия за пару дней:
1. Возможность собирать нативное приложение, а не запускать симулятор мобилы, это очень удобно.
2. Я не знаю ООП 🙈
3. Рендер теней во Flutter отличается от такового в браузере. Придётся подгонять.
4. BoxShadow inset не поддерживается, зато в репозиториях пакетов Flutter присутствует реализация на базе кода из Chrome.
5. Классы, классы, классы… константы иконок тоже в класс пришлось положить.
6. Мой перфекционизм заставил даже найти пакет для CSD. Ну чтобы заголовок окна спрятать, получилась красота.
7. Флексбокс он и во Flutter флексбокс, ничего нового там нет.
8. Линтер в расширении для VS Code работает просто потрясающе, я это всё пишу почти не заглядывая в доку, по наитию и паре примеров.
9. Документация, впрочем, великолепная. И примеры виджетов классные.
10. Состояние :active надо реализовывать через tapUp и tapDown, потому что вот так.
Оставайтесь на связи :)
#flutter
Чутка заболел, но зато всё-таки начал писать приложение-пульт.
Итак, открытия за пару дней:
1. Возможность собирать нативное приложение, а не запускать симулятор мобилы, это очень удобно.
2. Я не знаю ООП 🙈
3. Рендер теней во Flutter отличается от такового в браузере. Придётся подгонять.
4. BoxShadow inset не поддерживается, зато в репозиториях пакетов Flutter присутствует реализация на базе кода из Chrome.
5. Классы, классы, классы… константы иконок тоже в класс пришлось положить.
6. Мой перфекционизм заставил даже найти пакет для CSD. Ну чтобы заголовок окна спрятать, получилась красота.
7. Флексбокс он и во Flutter флексбокс, ничего нового там нет.
8. Линтер в расширении для VS Code работает просто потрясающе, я это всё пишу почти не заглядывая в доку, по наитию и паре примеров.
9. Документация, впрочем, великолепная. И примеры виджетов классные.
10. Состояние :active надо реализовывать через tapUp и tapDown, потому что вот так.
Оставайтесь на связи :)
#flutter
🔥19👍12❤2🥴1
#заметка дня
Щас будет линкдамп. Потому что ну надо мне структурировать информацию в голове.
Собственно, как вы в курсе, я пытаюсь писать приложение на Flutter для управления своим телевизором Samsung. Довольно старая модель, года 2018, но на TIzen OS, Smart TV.
Почему я это делаю? Дочь грызёт пульт и рано или поздно она его сгрызёт. У меня уже запасной есть, но так неинтересно.
Вторая причина — это просто интересная задача, которую можно решить несколькими способами, а само приложение легко расширять в сторону поддержки DLNA (шарить экран или медиа с телефона, короче).
Итак, как же можно управлять современным Smart TV?
1. ИК-пульт. Не вариант в моём случае, потому что не у всех телефонов он есть. У моего второго — есть, впрочем. стандартное приложение отлично работает.
2. Bluetooth-пульт, из поставки ТВ или от братьев-китайцев. Протокол обмена ключами мне сходу нагуглить не удалось, но что-то мне подсказывает, что это в любом случае буквально обычная клавиатура.
3. TCP/IP, по сети. А конкретно — вебсокеты. Устанавливаешь соединение, получаешь токен — отправляешь жисончик. Протокол в доках я не нашёл, но есть множество реализаций:
https://github.com/Toxblh/samsung-tv-control
https://github.com/ollo69/ha-samsungtv-smart
https://github.com/dahuby/iobroker.samsung_tizen
https://github.com/stephensli/samsung-tv-api
Понятное дело, что тут проблема в том, что если телевизор ушёл в глубокий спящий режим, сетевые функции будут отключены. И это ещё предстоит решать. Ходят слухи, что у Samsung есть специальный API для этого, т. е. в сон уходит не до конца. Ну или можно отключить энергосбережение.
Можете поставить себе одну из реализаций и побаловаться с компа, если у вас Samsung.
4. Ну и специальный API с названием Samsung SmartThings. Требуют получения токена через сервера Samsung, используя их же учётку. Официальное приложение его и использует. Ужасно медленно работает, впрочем :( И всё так же неясно с состоянием спящего режима.
Реализация тоже имеется:
https://github.com/pegatron89/smartthingstv
Я пока буду делать на вебсокетах, а дальше посмотрим, куда меня это всё заведёт. Возможно, следующий шаг будет попытка в DLNA и шаринг экрана, а возможно, пойду изучать, как работает Bluetooth.
#flutter #samsung #remote
Щас будет линкдамп. Потому что ну надо мне структурировать информацию в голове.
Собственно, как вы в курсе, я пытаюсь писать приложение на Flutter для управления своим телевизором Samsung. Довольно старая модель, года 2018, но на TIzen OS, Smart TV.
Почему я это делаю? Дочь грызёт пульт и рано или поздно она его сгрызёт. У меня уже запасной есть, но так неинтересно.
Вторая причина — это просто интересная задача, которую можно решить несколькими способами, а само приложение легко расширять в сторону поддержки DLNA (шарить экран или медиа с телефона, короче).
Итак, как же можно управлять современным Smart TV?
1. ИК-пульт. Не вариант в моём случае, потому что не у всех телефонов он есть. У моего второго — есть, впрочем. стандартное приложение отлично работает.
2. Bluetooth-пульт, из поставки ТВ или от братьев-китайцев. Протокол обмена ключами мне сходу нагуглить не удалось, но что-то мне подсказывает, что это в любом случае буквально обычная клавиатура.
3. TCP/IP, по сети. А конкретно — вебсокеты. Устанавливаешь соединение, получаешь токен — отправляешь жисончик. Протокол в доках я не нашёл, но есть множество реализаций:
https://github.com/Toxblh/samsung-tv-control
https://github.com/ollo69/ha-samsungtv-smart
https://github.com/dahuby/iobroker.samsung_tizen
https://github.com/stephensli/samsung-tv-api
Понятное дело, что тут проблема в том, что если телевизор ушёл в глубокий спящий режим, сетевые функции будут отключены. И это ещё предстоит решать. Ходят слухи, что у Samsung есть специальный API для этого, т. е. в сон уходит не до конца. Ну или можно отключить энергосбережение.
Можете поставить себе одну из реализаций и побаловаться с компа, если у вас Samsung.
4. Ну и специальный API с названием Samsung SmartThings. Требуют получения токена через сервера Samsung, используя их же учётку. Официальное приложение его и использует. Ужасно медленно работает, впрочем :( И всё так же неясно с состоянием спящего режима.
Реализация тоже имеется:
https://github.com/pegatron89/smartthingstv
Я пока буду делать на вебсокетах, а дальше посмотрим, куда меня это всё заведёт. Возможно, следующий шаг будет попытка в DLNA и шаринг экрана, а возможно, пойду изучать, как работает Bluetooth.
#flutter #samsung #remote
❤8👍7
#заметка дня
Итак, что же меня восхищает в волшебном значении border-radius равному 9999px?
Всё очень просто и забавно одновременно: border-radius: 9999px построит вам прямоугольник со скруглёнными углами. В случае квадрата это будет, очевидно, круг.
Вот issue из обсуждений спецификации CSS WG: https://www.w3.org/Style/CSS/Tracker/issues/29
Сам автор issue говорит, что безпол-литра картинок там не разобраться. Cut the crap, они пошли по третьему варианту: https://www.w3.org/TR/css-backgrounds-3/#corner-overlap
Там в целом геометрия эллипсов, потому описание формулы такое странное и учитываются все углы, но давайте просто посчитаем, что же получится для значения в 10000px (проще считать) и прямоугольника размером 320x240px, углы начинаем с верхнего левого (Top Left):
TL: 320/20000 vs 240/20000
TR: 320/20000 vs 240/20000
BR: 320/20000 vs 240/20000
BL: 320/20000 vs 240/20000
0.016 vs 0.012 в каждом случае
Итого, 0.012 — минимальное значение коэффициента приведения радиуса.
10000 * 0.012 = 120.
Половина высоты, выходит. Проверяем себя: https://codepen.io/alinaki/pen/jOxRwJJ
Вариант, когда значения радиуса индивидуальны, рассмотрен там же в спецификации.
Во Flutter используется геометрия кривых и понять это пусть всё ещё проще, чем структуру исходного кода Chromium, но всё равно сложно. Тем не менее, имеются упоминания, что радиусы приводятся к минимальному значению размерности.
И да, 9999px это совсем не то же, что 50%, опять же — смотрите спецификацию, там эллипсы. Но в случае квадрата — и там и там будет круг.
#geometry #borderradius #css #flutter
Итак, что же меня восхищает в волшебном значении border-radius равному 9999px?
Всё очень просто и забавно одновременно: border-radius: 9999px построит вам прямоугольник со скруглёнными углами. В случае квадрата это будет, очевидно, круг.
Вот issue из обсуждений спецификации CSS WG: https://www.w3.org/Style/CSS/Tracker/issues/29
Сам автор issue говорит, что без
Там в целом геометрия эллипсов, потому описание формулы такое странное и учитываются все углы, но давайте просто посчитаем, что же получится для значения в 10000px (проще считать) и прямоугольника размером 320x240px, углы начинаем с верхнего левого (Top Left):
TL: 320/20000 vs 240/20000
TR: 320/20000 vs 240/20000
BR: 320/20000 vs 240/20000
BL: 320/20000 vs 240/20000
0.016 vs 0.012 в каждом случае
Итого, 0.012 — минимальное значение коэффициента приведения радиуса.
10000 * 0.012 = 120.
Половина высоты, выходит. Проверяем себя: https://codepen.io/alinaki/pen/jOxRwJJ
Вариант, когда значения радиуса индивидуальны, рассмотрен там же в спецификации.
Во Flutter используется геометрия кривых и понять это пусть всё ещё проще, чем структуру исходного кода Chromium, но всё равно сложно. Тем не менее, имеются упоминания, что радиусы приводятся к минимальному значению размерности.
И да, 9999px это совсем не то же, что 50%, опять же — смотрите спецификацию, там эллипсы. Но в случае квадрата — и там и там будет круг.
#geometry #borderradius #css #flutter
👍5🤯3
#заметка дня
Вы что, реально думали, что я забросил свой проект пульта для телевизора Samsung на Flutter?
Ну, так-то, да... забросил. Но вернулся на днях!
Напомню, что тогда дочка грызла основной пульт и я захотел сделать альтернативу, заодно изучив Flutter. Кинул клич в канале в поиске дизайнеров, быстренько сверстал получившееся на Dart.
Итак, я остановился на том, что научился посылать широковещательное сообщение в локальную сеть и собирать отклики. Следующим шагом стало бы получение информации о телевизоре: IP-адрес, название модели и телевизора, уникальный id на всякий случай. И здесь имеются два варианта:
1. Широковещательный поиск по SSDP-запросу (если у вас дома есть телевизор Samsung, можете попробовать код из этого поста)
Но за этим API толком больше ничего не стоит, документация Samsung прям скудная, надо искать по крупицам. Но есть второй вариант!
2. На телевизорах с 2016 года имеется web-API!
У меня ушёл час чтобы понять, что в конце слэш обязателен. Впрочем, ничего нового.
И вот GET-запрос на этот адрес отдаёт, кто бы мог подумать, JSON. А поддержка JSON в Dart нативная.
Запихиваем ответ в ChatGPT, просим создать класс и фабрику из JSON. Вы серьёзно думали, что я определения типов в 2023 году буду сам писать? Нейронка отлично справилась, создав на каждый вложенный объект по классу, адекватно их назвала, преобразовала булевы строки в нормальные значения и вообще умница.
Но, как я уже сказал, документация Samsung на всю эту тему максимально ужасная. Нет ни слова насчёт того, как же запустить, например, приложение или получить их список.
Благо, на Reddit есть целые сообщества, которые ищут такую информацию. Вот, например, один такой пост: https://www.reddit.com/r/homeassistant/comments/fxddeh/controlling_a_samsung_tv/
Итого, чтобы запустить, например, Netflix мне нужно или совершить пустой POST-запрос на
А GET-запросы просто выдадут состояния этих приложений. Их перебором можно узнать, что на телевизоре установлено. Самое смешное, опять же, то XML, то JSON соответственно. А ответ на POST в первом случае — 200 и URL, а во втором — 200 и
Как ищутся все эти ID типа
Кажется, я и так уже достаточно много написал. Можем с вами договориться, например, что я буду писать по одному посту про Flutter в неделю. Таким образом у меня будет мотивация что-то делать и посты могут стать более приземлёнными. Отпишитесь в комментариях.
Вариантов постов много: как работает навигация во Flutter-приложениях, как сделать аналог BottomSheet из iOS, как совершить запрос и разобрать XML/JSON, как верстать UI... Задавайте ваши ответы.
#flutter #remote
Вы что, реально думали, что я забросил свой проект пульта для телевизора Samsung на Flutter?
Ну, так-то, да... забросил. Но вернулся на днях!
Напомню, что тогда дочка грызла основной пульт и я захотел сделать альтернативу, заодно изучив Flutter. Кинул клич в канале в поиске дизайнеров, быстренько сверстал получившееся на Dart.
Итак, я остановился на том, что научился посылать широковещательное сообщение в локальную сеть и собирать отклики. Следующим шагом стало бы получение информации о телевизоре: IP-адрес, название модели и телевизора, уникальный id на всякий случай. И здесь имеются два варианта:
1. Широковещательный поиск по SSDP-запросу (если у вас дома есть телевизор Samsung, можете попробовать код из этого поста)
urn:samsung.com:device:RemoteControlReceiver:1
отдаёт некий интересный адрес http://192.168.3.6:7676/rcr/
. Несложно догадаться, что rcr это receiver
, приёмник. И там имеется XML со всей необходимой информацией, включая поддердживаемые протоколы. Но, честно, покажите мне человека, который любит разгребать XML? Да и пакет отдельный надо ставить, давно уже формат не в фаворе... Но если интересно, как это делают на Dart — могу рассказать.Но за этим API толком больше ничего не стоит, документация Samsung прям скудная, надо искать по крупицам. Но есть второй вариант!
2. На телевизорах с 2016 года имеется web-API!
http://192.168.3.6:8001/api/v2/
(не спрашивайте, куда делся v1).У меня ушёл час чтобы понять, что в конце слэш обязателен. Впрочем, ничего нового.
И вот GET-запрос на этот адрес отдаёт, кто бы мог подумать, JSON. А поддержка JSON в Dart нативная.
Запихиваем ответ в ChatGPT, просим создать класс и фабрику из JSON. Вы серьёзно думали, что я определения типов в 2023 году буду сам писать? Нейронка отлично справилась, создав на каждый вложенный объект по классу, адекватно их назвала, преобразовала булевы строки в нормальные значения и вообще умница.
Но, как я уже сказал, документация Samsung на всю эту тему максимально ужасная. Нет ни слова насчёт того, как же запустить, например, приложение или получить их список.
Благо, на Reddit есть целые сообщества, которые ищут такую информацию. Вот, например, один такой пост: https://www.reddit.com/r/homeassistant/comments/fxddeh/controlling_a_samsung_tv/
Итого, чтобы запустить, например, Netflix мне нужно или совершить пустой POST-запрос на
http://192.168.1.145:8001/ws/apps/Netflix
или пустой POST-запрос на http://192.168.3.6:8001/api/v2/applications/11101200001
А GET-запросы просто выдадут состояния этих приложений. Их перебором можно узнать, что на телевизоре установлено. Самое смешное, опять же, то XML, то JSON соответственно. А ответ на POST в первом случае — 200 и URL, а во втором — 200 и
true
🤡 Так что ваши API не настолько и плохи, как вы думаете.Как ищутся все эти ID типа
11101200001
? Удивительное дело, но в вашем аккаунте в Samsung есть страничка с устройствами, которая больше напоминает домашнюю страницу роутера. И там показано, какой вид активности сейчас на телевизоре происходит. Ну а конкретно адреса API ищутся внутри скачиваемого SDK. Документации (хором) нет.Кажется, я и так уже достаточно много написал. Можем с вами договориться, например, что я буду писать по одному посту про Flutter в неделю. Таким образом у меня будет мотивация что-то делать и посты могут стать более приземлёнными. Отпишитесь в комментариях.
Вариантов постов много: как работает навигация во Flutter-приложениях, как сделать аналог BottomSheet из iOS, как совершить запрос и разобрать XML/JSON, как верстать UI... Задавайте ваши ответы.
#flutter #remote
🔥23❤5💩2👍1
#заметка дня
Продолжаем эпопею про написание пульта для телевизора на Flutter.
Мы с вами уже умеем верстать виджеты, находить телевизор широковещательным сообщением, выбирать его, открывать и закрывать на нём приложения и знаем, как искать их идентификаторы.
Потихоньку подбираемся к самому главному: как, собственно, посылать команды, точнее, нажатия кнопок.
А делается это довольно просто.
1. Постучались на WebSocket API, передав название приложения. Почему-то в моём случае стучаться пришлось на secure-вариант (ws vs wss, это как http vs https), разрешив использование самоподписанных сертификатов (потом расскажу, что не так).
2. Телевизор спросит разрешение на удалённое управление. И вот тут придётся подтверждать с пульта или джойстика на телевизоре, других вариантов нет. В ответ будет прислан токен. Чтобы больше не спрашивал — все дальнейшие запросы должны содержать в себе идентификатор приложения и токен, собственно. Как параметры запроса:
3. Формируем команду, на которую, естественно, опять нет никакой документации. Но когда это нам мешало? Копаемся в issues легендарной (в узком кругу) библиотеки Samsungctl, находим нужный формат.
4. Отправляем.
5. ...
6. Пищим от восторга.
На этом месте будет небольшая ода Джаваскрипту: нет на свете языка, который бы позволил быстрее настряпать всякие тестовые куски кода, вне зависимости от того, нужен вам UI, или нет. Ну, может, Python что-то способен противопоставить. Тяп-ляп и готов код, чтобы быстро проверить теорию или соответствие стандарта вашему телевизору: https://gist.github.com/bekharsky/80fce4263304eedcec7a46045b1a0ebd
Представьте, как было бы обидно, написать это всё на Dart и обнаружить, что мой телевизор старее, чем нужно. Впрочем, там не сильно сложнее, сделаю сегодня.
И посоветуйте, кто чем вебсокеты отлаживает. Что-нибудь вроде Postman, но не Postman.
К слову, если у кого-нибудь есть телевизоры Samsung и кому не лень, проверьте код выше (он просто выключает звук) и напишите модель в комментарии, пожалуйста (как узнать модель — смотрите ссылку в первых словах поста, там про API телевизора). Это мне потом очень поможет :)
Удачи в ваших пет-проектах, котаны.
P. S. если кому интересно, вот тут человек на Go автоматизирует браузер телевизора, чтобы дашборды Grafana запустить. Целый кладезь команд и подсказок. Красивое: https://gist.github.com/freman/8d98742de09d476c4d3d9e5d55f9db63
#flutter #dart #websockets
Продолжаем эпопею про написание пульта для телевизора на Flutter.
Мы с вами уже умеем верстать виджеты, находить телевизор широковещательным сообщением, выбирать его, открывать и закрывать на нём приложения и знаем, как искать их идентификаторы.
Потихоньку подбираемся к самому главному: как, собственно, посылать команды, точнее, нажатия кнопок.
А делается это довольно просто.
1. Постучались на WebSocket API, передав название приложения. Почему-то в моём случае стучаться пришлось на secure-вариант (ws vs wss, это как http vs https), разрешив использование самоподписанных сертификатов (потом расскажу, что не так).
2. Телевизор спросит разрешение на удалённое управление. И вот тут придётся подтверждать с пульта или джойстика на телевизоре, других вариантов нет. В ответ будет прислан токен. Чтобы больше не спрашивал — все дальнейшие запросы должны содержать в себе идентификатор приложения и токен, собственно. Как параметры запроса:
?name=xxx&token=yyy
.3. Формируем команду, на которую, естественно, опять нет никакой документации. Но когда это нам мешало? Копаемся в issues легендарной (в узком кругу) библиотеки Samsungctl, находим нужный формат.
4. Отправляем.
5. ...
6. Пищим от восторга.
На этом месте будет небольшая ода Джаваскрипту: нет на свете языка, который бы позволил быстрее настряпать всякие тестовые куски кода, вне зависимости от того, нужен вам UI, или нет. Ну, может, Python что-то способен противопоставить. Тяп-ляп и готов код, чтобы быстро проверить теорию или соответствие стандарта вашему телевизору: https://gist.github.com/bekharsky/80fce4263304eedcec7a46045b1a0ebd
Представьте, как было бы обидно, написать это всё на Dart и обнаружить, что мой телевизор старее, чем нужно. Впрочем, там не сильно сложнее, сделаю сегодня.
И посоветуйте, кто чем вебсокеты отлаживает. Что-нибудь вроде Postman, но не Postman.
К слову, если у кого-нибудь есть телевизоры Samsung и кому не лень, проверьте код выше (он просто выключает звук) и напишите модель в комментарии, пожалуйста (как узнать модель — смотрите ссылку в первых словах поста, там про API телевизора). Это мне потом очень поможет :)
Удачи в ваших пет-проектах, котаны.
P. S. если кому интересно, вот тут человек на Go автоматизирует браузер телевизора, чтобы дашборды Grafana запустить. Целый кладезь команд и подсказок. Красивое: https://gist.github.com/freman/8d98742de09d476c4d3d9e5d55f9db63
#flutter #dart #websockets
❤11👍2
#заметка дня
Мобильная разработка, как ни крути, выходит ближе к железу и понимать в ней нужно чуть больше.
Да, это опять я со своим нытьём про Dart и Flutter, которое можно найти по тегу #remote. И сегодня мы поговорим о сокетах. Конкретно — WebSockets.
Вы наверняка должны были задуматься, откуда в вебсокетах приставка "веб". И ответ на самом деле простой: потому что они реализованы поверх протокола HTTP, для чего используется, очевидно, некий HTTP-клиент. В браузерах свой, в Node.js свой, в мобильных фреймворках свой.
Что из этого следует, например? Ну, что сертификаты наруливаются согласно спецификации HTTPS. И тут начинается самое интересное.
Нода и браузеры вам прощают вообще все. Предполагается, что веб-разработчику вообще не надо толком думать, а что там внутри.
Вот у телевизоров Samsung сертификат самоподписанный. Вебсокеты по протоколу wss (websocket secure) работать с таким откажутся, но всё, что надо сделать в JS — передать опцию allowUnauthorized. Всё, полетели жисоны.
Что надо сделать в том же Dart/Flutter?
Перегрузить (заменить, override) библиотечный HTTP-клиент!
Вот так:
И дальше есть выбор, делать это на глобальном уровне, или передать в конструктор. В моём случае — глобально, поскольку API тоже спрятан за самоподписанным сертификатом:
И такое на каждом шагу. Нельзя просто так взять и...
Может, поэтому мобильным разработчикам зачастую больше платят? 🤔
#flutter #remote #dart #websocket
Мобильная разработка, как ни крути, выходит ближе к железу и понимать в ней нужно чуть больше.
Да, это опять я со своим нытьём про Dart и Flutter, которое можно найти по тегу #remote. И сегодня мы поговорим о сокетах. Конкретно — WebSockets.
Вы наверняка должны были задуматься, откуда в вебсокетах приставка "веб". И ответ на самом деле простой: потому что они реализованы поверх протокола HTTP, для чего используется, очевидно, некий HTTP-клиент. В браузерах свой, в Node.js свой, в мобильных фреймворках свой.
Что из этого следует, например? Ну, что сертификаты наруливаются согласно спецификации HTTPS. И тут начинается самое интересное.
Нода и браузеры вам прощают вообще все. Предполагается, что веб-разработчику вообще не надо толком думать, а что там внутри.
Вот у телевизоров Samsung сертификат самоподписанный. Вебсокеты по протоколу wss (websocket secure) работать с таким откажутся, но всё, что надо сделать в JS — передать опцию allowUnauthorized. Всё, полетели жисоны.
Что надо сделать в том же Dart/Flutter?
Перегрузить (заменить, override) библиотечный HTTP-клиент!
Вот так:
class SamsungHttpOverrides extends HttpOverrides {
@override
HttpClient createHttpClient(SecurityContext? context) {
return super.createHttpClient(context)
..badCertificateCallback =
(X509Certificate cert, String host, int port) => true;
}
}
И дальше есть выбор, делать это на глобальном уровне, или передать в конструктор. В моём случае — глобально, поскольку API тоже спрятан за самоподписанным сертификатом:
HttpOverrides.global = SamsungHttpOverrides();
И такое на каждом шагу. Нельзя просто так взять и...
Может, поэтому мобильным разработчикам зачастую больше платят? 🤔
#flutter #remote #dart #websocket
😱8
#инструмент дня
Вы, наверное, уже наслышаны от обладателей айфонов про AirDropи дикпики.
Кроме шуток, передать файлы по локальной сети между двумя своими устройствами должно быть максимально просто же! Без ковыряний в Network Discovery, настроек Samba и так далее.
И такое решение есть, даже с открытым кодом: LocalSend.
Сайт: https://localsend.org/
Написано на Dart и Flutter, работает на всех разумно доступных платформах: Windows, Linux, MacOS, Android, iOS.
Не опирается на один протокол, а перебирает все доступные и даже может запустить свой собственный сервер по необходимости. В крайнем случае, можно донастроить.
Никаких облаков, всё по локальной сети.
Поддержка нескольких получателей, поддержка буфера обмена.
В общем, если у вас дома зоопарк устройств и пока не хватило времени настроить что-то иное, или лучше Samba вы ничего в жизни не видели — вот это самое то.
Мне особенно импонирует Flutter. Я недавно вернулся к разработке своего пульта и это всё ещё очень приятный экспириенс.
#flutter #localsend #airdrop #network
Вы, наверное, уже наслышаны от обладателей айфонов про AirDrop
Кроме шуток, передать файлы по локальной сети между двумя своими устройствами должно быть максимально просто же! Без ковыряний в Network Discovery, настроек Samba и так далее.
И такое решение есть, даже с открытым кодом: LocalSend.
Сайт: https://localsend.org/
Написано на Dart и Flutter, работает на всех разумно доступных платформах: Windows, Linux, MacOS, Android, iOS.
Не опирается на один протокол, а перебирает все доступные и даже может запустить свой собственный сервер по необходимости. В крайнем случае, можно донастроить.
Никаких облаков, всё по локальной сети.
Поддержка нескольких получателей, поддержка буфера обмена.
В общем, если у вас дома зоопарк устройств и пока не хватило времени настроить что-то иное, или лучше Samba вы ничего в жизни не видели — вот это самое то.
Мне особенно импонирует Flutter. Я недавно вернулся к разработке своего пульта и это всё ещё очень приятный экспириенс.
#flutter #localsend #airdrop #network
❤9
Media is too big
VIEW IN TELEGRAM
#видео дня
Вы думали, я забыл?
Я тут каким-то чудом выкроил время, подолбился в геометрию, документацию и ChatGPT и таки довёл свой ТВ-пульт на #Flutter до вида, в котором за него уже не стыдно.
Теперь навернуть ещё фичей, отшлифовать настройки и в продакшен, котаны!
Подумываю ввести воскресную рубрику о разработке на Flutter и для не-веба вообще, чтобы получилось некое обещание.
Надо? :)
Вы думали, я забыл?
Я тут каким-то чудом выкроил время, подолбился в геометрию, документацию и ChatGPT и таки довёл свой ТВ-пульт на #Flutter до вида, в котором за него уже не стыдно.
Теперь навернуть ещё фичей, отшлифовать настройки и в продакшен, котаны!
Подумываю ввести воскресную рубрику о разработке на Flutter и для не-веба вообще, чтобы получилось некое обещание.
Надо? :)
❤21👍19🤩2
#инструмент дня
Когда вы последний раз дизассемблировали React Native приложение?
А я вчера.
Вот так вот решил закончить череду постов этото года лёгким хардкором. На полшишечки.
Давайте по порядку. Как вы все, должно быть, помните, я уже довольно давно пишу свой пульт для телевизора Samsung на Flutter.
Почему Samsung? Ну потому что он дома стоит.
И да, хоть это всё и происходит крайне медленно, минимальный набор функций имеется. Я постоянно им пользуюсь, когда нужно что-то переключить ребёнку или мне, а настоящий пульт искать лень.
Но у пары конкурентных приложений были функции, которые кажутся весьма уместными. И речь даже не о DLNA-стриминге фотографий и видео с телефона на телевизор, это-то как раз понятно и хорошо документированно.
А вот, например, такая простая штука, как получение списка всех приложений. Ну или, например, иные методы поиска телевизоров. В моём-то приложении список приложений и иконок к ним тупо захардкожен.
И не сказать, что я их не знаю — в начале разработки провёл огромную работу по поиску нужных API, но руки всё равно чесались.
И тут очень к месту пришлась возможность использования приложений для iPhone на макбуках с м-процессорами. Запускаешь приложение параллельно с Wireshark и мониторишь запросы. Очень удобно (на иллюстрации).
Но я не учёл такой простой вещи, как шифрование.
Да-да, практически все вебсокет-запросы оказались зашифрованы протоколом TLS 1.2 (
Кто бы мог подумать, а. Ведь я сам обходил это в своей имплементации: сертификаты на телевизорах свои, и, зачастую, протухшие давно.
Пусть это и не самый надёжный в 2024 году протокол, но всё же опыта расшифровки у меня нет. На самом-то деле в телевизорах есть и несекьюрные API, позволяющие даже запустить приложение, но они не всегда доступны без dev-режима. Да и нужного среди них не оказалось. А я так надеялся, что есть что-то простое.
Впрочем, строки поиска SSDP я себе выписал. LG, ты следующий.
Итак, но приложение же вот оно, лежит в каталоге Applications. А это что значит?
А это значит, можно посмотреть содержимое пакета! Да, если вы не знали, приложения в macOS и iOS (и на Android) это, по факту, просто архив.
Распаковав, я обнаружил подозрительный каталог node_modules и нечто под названием main.jsbundle.
Надо же, самый крутой конкурент оказался ни чем иным, как приложением на React Native!
А что я с ним делал дальше — напишу через несколько часов, иначе как-то длинно получается. Оставайтесь на связи :)
#remote #flutter #reactnative
Когда вы последний раз дизассемблировали React Native приложение?
А я вчера.
Вот так вот решил закончить череду постов этото года лёгким хардкором. На полшишечки.
Давайте по порядку. Как вы все, должно быть, помните, я уже довольно давно пишу свой пульт для телевизора Samsung на Flutter.
Почему Samsung? Ну потому что он дома стоит.
И да, хоть это всё и происходит крайне медленно, минимальный набор функций имеется. Я постоянно им пользуюсь, когда нужно что-то переключить ребёнку или мне, а настоящий пульт искать лень.
Но у пары конкурентных приложений были функции, которые кажутся весьма уместными. И речь даже не о DLNA-стриминге фотографий и видео с телефона на телевизор, это-то как раз понятно и хорошо документированно.
А вот, например, такая простая штука, как получение списка всех приложений. Ну или, например, иные методы поиска телевизоров. В моём-то приложении список приложений и иконок к ним тупо захардкожен.
И не сказать, что я их не знаю — в начале разработки провёл огромную работу по поиску нужных API, но руки всё равно чесались.
И тут очень к месту пришлась возможность использования приложений для iPhone на макбуках с м-процессорами. Запускаешь приложение параллельно с Wireshark и мониторишь запросы. Очень удобно (на иллюстрации).
Но я не учёл такой простой вещи, как шифрование.
Да-да, практически все вебсокет-запросы оказались зашифрованы протоколом TLS 1.2 (
wss://
).Кто бы мог подумать, а. Ведь я сам обходил это в своей имплементации: сертификаты на телевизорах свои, и, зачастую, протухшие давно.
Пусть это и не самый надёжный в 2024 году протокол, но всё же опыта расшифровки у меня нет. На самом-то деле в телевизорах есть и несекьюрные API, позволяющие даже запустить приложение, но они не всегда доступны без dev-режима. Да и нужного среди них не оказалось. А я так надеялся, что есть что-то простое.
Впрочем, строки поиска SSDP я себе выписал. LG, ты следующий.
Итак, но приложение же вот оно, лежит в каталоге Applications. А это что значит?
А это значит, можно посмотреть содержимое пакета! Да, если вы не знали, приложения в macOS и iOS (и на Android) это, по факту, просто архив.
Распаковав, я обнаружил подозрительный каталог node_modules и нечто под названием main.jsbundle.
Надо же, самый крутой конкурент оказался ни чем иным, как приложением на React Native!
А что я с ним делал дальше — напишу через несколько часов, иначе как-то длинно получается. Оставайтесь на связи :)
#remote #flutter #reactnative
👍19❤4🤩4
Media is too big
VIEW IN TELEGRAM
#заметка дня
Быть в отпуске, который никак заранее не планировал, а в конце которого — полная смена работы (и даже отчасти деятельности: из продукта в дизайн-систему) — штука довольно тяжёлая.
С одной стороны, на работу ходить не надо. С другой — нужно как-то себя развлекать!
Зато, наконец, появилось время добить пульт на Flutter и запустить его на телефоне.
Не без проблем, конечно. И с Android, и с iOS.
Если с Android всё более-менее понятно — старая конфигурация, мелкие баги, — то с iOS…
Симулятор против реальности
iOS на симуляторе и iOS на реальном устройстве — это две совершенно разные iOS.
Нам никто не обещал полноценной эмуляции. Да, симулятор упрощает вход в разработку. Но почему бы не предупреждать разработчиков, что потом всё пойдёт не так?
Хотя, признаюсь, в половине случаев виноват сам.
Например, приложение падало при поиске телевизоров, который у меня реализован через SSDP (Service Discovery Protocol). Это работает через мультикаст (multicast) — а это уже отдельный мир.
Оказывается:
- Мультикаст — это отдельное разрешение, scope.
- Его нужно объявлять в конфигураци приложения.
- Потом — проходить модерацию в App Store.
Более того, нужно заранее уведомить Apple и получить соответствующий сертификат ещё до начала разработки.
И всё это — только если у тебя есть разработческий аккаунт за $99 в год. Без него — даже не пробуй.
А симулятор? Он позволяет всё. Мультикаст работает без проблем. Никаких предупреждений. Всё как по маслу — пока не ставишь приложение на свой собственный iPhone.
Решения
Окей. Я решил:
- Оставлю поиск включённых телевизоров на более дружелюбных ОС.
- Добавлю fallback — диалог ручного ввода IP-адреса телевизора.
Это помогло.
Но тут всплыла новая проблема — Wake-On-LAN не работает.
Хотя он должен работать даже по Wi-Fi: ваши «умные» устройства де-факто никогда не выключаются. Но я забыл, что у телефона две сети — Wi-Fi и сотовая. А вещать нужно в Wi-Fi.
Когда я начал фильтровать интерфейсы по ключевым словам (например, en на iOS/macOS или wlan на Android/Linux), всё наконец заработало.
SSDP без мультикаста?
И тут меня осенило: а можно ли использовать SSDP без мультикаста — через broadcast?
Ответ — да! Достаточно:
- Изменить IP шлюза.
- Отключить присоединение к мультикаст-группе.
Поиск устройств заработал. Никаких разрешений от Apple не нужно. Всё прекрасно!
Даже пока не надо тратить сотку...
Хотя ручное добавление по IP я всё равно оставил — на всякий случай.
Кстати, на эмуляторе Android ни SSDP, ни WebSockets — пока не работают... Вот вам и минус мультиплатформенной разработки — приходится разбираться в нюансах вообще всего.
Зато на iOS, macOS, Linux и Windows теперь всё просто прекрасно.
#flutter #ios
Быть в отпуске, который никак заранее не планировал, а в конце которого — полная смена работы (и даже отчасти деятельности: из продукта в дизайн-систему) — штука довольно тяжёлая.
С одной стороны, на работу ходить не надо. С другой — нужно как-то себя развлекать!
Зато, наконец, появилось время добить пульт на Flutter и запустить его на телефоне.
Не без проблем, конечно. И с Android, и с iOS.
Если с Android всё более-менее понятно — старая конфигурация, мелкие баги, — то с iOS…
Симулятор против реальности
iOS на симуляторе и iOS на реальном устройстве — это две совершенно разные iOS.
Нам никто не обещал полноценной эмуляции. Да, симулятор упрощает вход в разработку. Но почему бы не предупреждать разработчиков, что потом всё пойдёт не так?
Хотя, признаюсь, в половине случаев виноват сам.
Например, приложение падало при поиске телевизоров, который у меня реализован через SSDP (Service Discovery Protocol). Это работает через мультикаст (multicast) — а это уже отдельный мир.
Оказывается:
- Мультикаст — это отдельное разрешение, scope.
- Его нужно объявлять в конфигураци приложения.
- Потом — проходить модерацию в App Store.
Более того, нужно заранее уведомить Apple и получить соответствующий сертификат ещё до начала разработки.
И всё это — только если у тебя есть разработческий аккаунт за $99 в год. Без него — даже не пробуй.
А симулятор? Он позволяет всё. Мультикаст работает без проблем. Никаких предупреждений. Всё как по маслу — пока не ставишь приложение на свой собственный iPhone.
Решения
Окей. Я решил:
- Оставлю поиск включённых телевизоров на более дружелюбных ОС.
- Добавлю fallback — диалог ручного ввода IP-адреса телевизора.
Это помогло.
Но тут всплыла новая проблема — Wake-On-LAN не работает.
Хотя он должен работать даже по Wi-Fi: ваши «умные» устройства де-факто никогда не выключаются. Но я забыл, что у телефона две сети — Wi-Fi и сотовая. А вещать нужно в Wi-Fi.
Когда я начал фильтровать интерфейсы по ключевым словам (например, en на iOS/macOS или wlan на Android/Linux), всё наконец заработало.
SSDP без мультикаста?
И тут меня осенило: а можно ли использовать SSDP без мультикаста — через broadcast?
Ответ — да! Достаточно:
- Изменить IP шлюза.
- Отключить присоединение к мультикаст-группе.
Поиск устройств заработал. Никаких разрешений от Apple не нужно. Всё прекрасно!
Даже пока не надо тратить сотку...
Хотя ручное добавление по IP я всё равно оставил — на всякий случай.
Кстати, на эмуляторе Android ни SSDP, ни WebSockets — пока не работают... Вот вам и минус мультиплатформенной разработки — приходится разбираться в нюансах вообще всего.
Зато на iOS, macOS, Linux и Windows теперь всё просто прекрасно.
#flutter #ios
👍18❤5🫡3
This media is not supported in your browser
VIEW IN TELEGRAM
#видео дня
Если вы интересовались прогрессом моего пульта на Flutter, то, собственно, вот он!
Всё работает и на Linux, и на Windows, и на macOS и, конечно же, на изначальной целевой платформе — iOS.
А вот на Android чот не могу разрешения на сеть победить, но я справлюсь.
На десктопе при этом полная поддержка горячих клавиш. Иметь пульт на ноутбуке — это гораздо сподручнее, чем кажется!
Отмечайтесь, интересно ли вам почитать, чем разработка на Flutter напоминает веб-разработку и как оно там вообще.
#flutter #mobile
Если вы интересовались прогрессом моего пульта на Flutter, то, собственно, вот он!
Всё работает и на Linux, и на Windows, и на macOS и, конечно же, на изначальной целевой платформе — iOS.
А вот на Android чот не могу разрешения на сеть победить, но я справлюсь.
На десктопе при этом полная поддержка горячих клавиш. Иметь пульт на ноутбуке — это гораздо сподручнее, чем кажется!
Отмечайтесь, интересно ли вам почитать, чем разработка на Flutter напоминает веб-разработку и как оно там вообще.
#flutter #mobile
👍59❤7🤡2