Стендап Сьогодні

Що я зробив, що я хочу зробити, і що це все значить.
Повсякденні здобутки в форматі стендапу.
Детальніше в статті

Підписатись на RSS
📢 Канал в Telegram @stendap_sogodni
🦣 @stendap_sogodni@shevtsov.me в Федиверсі

02.07.2023

Реверс-інжинірінг формату тепловізора, ч. 2

… Після вимірів зображення в файлі розташовувалась матриця з двобайтових значень. А далі — сюрприз — ще одна матриця, але вже з однобайтових значень. Тож отримав одну матрицю 16-бітних чисел, іншу - 8-бітних, а також 112 байтів додаткової інформації, такої, як відбиток часу та інше. Двох матриць я не очікував.

(Як взагалі здогадатись, що то матриця та який розмір її елемента? Бо послідовні елементи мають близькі значення. Тож повторюватись буде або кожний байт, або кожний другий байт. Також на початку кожного рядка значення теж близькі до попереднього. Все це легко побачити в hex-редакторі.)

Що робити з матрицями чисел? Спробував записати в CSV, але він погано сприймається. Краще перетворити на зображення. Тож відкрив для себе вбудований в Go пакет image. Він не дуже багато вміє, але дозволяє створити зображення, встановити в ньому значення пікселів, а потім зберегти у формат PNG. Саме так я й зробив (результат — вище.)

Після наочного перегляду 8-бітна матриця виявилася, напевно, сирим змістом сенсора. Її пікселі мали весь діапазон значень від 0 від 255 (Хоча цікаво, що не на кожній світлині — при малій розбіжності температур значення були більш обмежені. Тож можу зробити висновок, що вона не нормалізована, а саме сира.)

А от з 16-бітною не так все зрозуміло, бо у графічному поданні вона мала рівномірно сірий вигляд. Тоді знайшов мінімальне та максимальне значення, та стало зрозуміло, що це температура, але помножена на 10. (Ще одна сфера застосування цілочисельних дробів.) Ці значення відповідали тим, що показує сам пристрій.

На цьому питання не закінчуються. Можна було б очікувати, що температура є лінійною функцією від показників сенсора. Проте ні — як тепловізор її обчислює, я поки не зрозумів. Але я точно знаю, що одному значенню сенсора відповідають різні значення температури (в межах однієї світлини, звісно.)

P.S. Сподіваюся, зроблю пізніше повноцінну статтю з ілюстраціями та кодом, бо у формат Телеграму та щоденних постів воно ніяк не влазить.


01.07.2023

Реверс-інжинірінг формату файлів тепловізора

Мав нагоду випробувати індустріальний тепловізор. Окрім всього іншого, цікаво, що ті світлини, що він зберігає, хоч і мають формат .jpg, але за допомогою супутнього програмного забезпечення дозволяють працювати, фактично, з RAW-даними. Захотілося дізнатись, як же ж воно влаштоване. З першого погляду, ці JPEG-файли 240x320 займають близько 300 Кб, що відразу викликає підозру: навіть нестиснутий файл BMP з такою роздільною здатністю займав би не більш ніж 240 Кб. Проте звичайні переглядачі світлин нічого цікавого в файлі не знаходили.

Тому в першу чергу звернувся до HEX-редактора. Останній раз я таким займався ще на Windows та років 15 тому, отже, для macOS довелося шукати. Є з чого обрати, насправді; я зупинився на редакторі ImHex. Він відразу сподобався тим, що наочно показує значення в різних представленнях, а також підтримує структурні дані. Причому структуру JPEG він вже знає. Але тут теж файл розкусити не вдалося.

Файл JPEG, як я дізнався, складається з сегментів. Сегмент заголовка, метаданих, і так далі. Останній сегмент містить дані світлини та зазвичай продовжується до кінця файлу. Тому наївні програми-читачі — в їхньому числі й ImHex - просто ігнорують те, що може йти після нього. Втім, кінець сегмента з зображенням (Entropy Coded Segment) можна знайти (за послідовністю байт FFxx, де xx - не 0).

Перейшов до написання утиліти на Go, яка біжить по JPEG файлу та перебирає сегменти аж до логічного кінця. Таким чином вдалося знайти не тільки кінець того JPEG, який видно “ззовні”, але й друге зображення JPEG - це була світлина, яку тепловізор робить звичайною фотокамерою.

Зображення просто знаходилися в файлі одне за одним. Але після них залишилося ще багацька даних — близько 250 Кб. Відкрив залишок в ImHex. Помітив, по-перше, що файл починається з ширини та висоти зображення, а далі — повторювану послідовність двобайтових значень, яка, як нетрудно здогадатись, містила якусь матрицю. Але про це, напевно, завтра.


30.06.2023

Робота з великими вихідними файлами на ECS

Сьогодні продовжував роботу з ECS, генерацією даних, тестами та так далі. Додатковий нюанс — застосування великих вихідних файлів.


29.06.2023

Запуск локальних скриптів на ECS за допомогою ngrok

В продовження теми з запуском скриптів на ECS, сьогодні винайшов ще більш зручний спосіб. Задача була схожа: зробити бенчмарк, який можливо запустити тільки з середовища ECS. Проблема така сама: на ECS можна запускати тільки готові контейнери Docker. Бенчмарк потребує послідовного налагодження та експериментування. Якщо підходити до цього нормальним шляхом — тобто комітити код, запускати скрипт деплою та очікувати, доки GitHub Actions та AWS CodeDeploy зроблять своє діло — то власне запустити скрипт вдасться раз хвилин в десять. Всякий фокус втрачається.

Тепер в мене є кращий спосіб: скрипт завантажується в контейнер ECS з локального компʼютера. Ніякої попередньої підготовки сервісу для цього не потрібно.

Найкраще це працює з Go, оскільки там все компілюється в єдиний файл, та не треба окремо завантажувати залежності. Проте й в інтерпретованих мовах залежності змінюються не так часто, тому підхід працює.


28.06.2023

Кілька порад з мого повсякденного Git


27.06.2023

Генерація тестових даних зі справжніх

Почну ось з чого: нагенерувати дані, що виглядають, як справжній результат роботи проєкту — за моїм досвідом — в загальному нереально. А це буває потрібно — може, щоб мати гарні дані для стейджингу; або щоб правильно навантажити системний стрес-тест.

Просто створити записи з синтетичними даними відносно нескладно; для цього є бібліотеки на Ruby чи JavaScript, чи Go. Але це вже на рівні одного обʼєкта може викликати нереальні комбінації даних, а з групами обʼєктів взагалі виникає стільки різних нюансів, що продумати їх вручну стає неможливо. (Скільки коментарів має блог-пост, в середньому? А до скількох коментарів мають бути відповіді? А якщо блог-пост не опублікований? І так далі.) Такі дані підійдуть для автотестів, де відомо, що очікувати, але не допоможуть оцінити роботу продукту до потрапляння в продакшн.

Є інший підхід — взяти дані з продакшна. Там вони за означенням “справжні”. Проте на продакшні містяться дані користувачів, які ми абсолютно не можемо поширювати на стейджинг та інші незахищені середовища. Тоді нам залишається змінити дані з продакшна таким чином, щоб вони втратили привʼязку до користувачів, але зберегли свою топологію, тобто відношення та статистичні властивості.

Я знайшов такий спосіб: використати ті самі бібліотеки фальшивих даних, але передавати їм зерно, обчислене з оригінального значення. З однаковим зерном будь-яка випадкова функція матиме однакове значення, тобто ми будемо впевнені, що структура даних залишається, без того, щоб будувати словник для кожного наявного поля. Де взяти зерно? Пропоную обчислити простий хеш, наприклад, MD5 або SHA1 (простий — бо швидкий!), взяти від нього перші 8 байтів та зліпити з них int64. Далі можна генерувати по зерну хоч імʼя, хоч імейл, хоч ціле оповідання. Вони будуть як правдоподібні (завдяки відповідній бібліотечній функції), так і зберігатимуть статистичні властивості.

Можна навіть зробити копію бази, де кожне поле замінене на своє зерно, а потім використати цю копію як “зерно” для генерації, скажімо, великого масиву даних для стрес-тесту.

(До речі, це може бути хороша задача для нейронної мережі, якщо придумати що робити з приватною інформацією, щоб вона не могла вилізти назовні.)


26.06.2023

Зони відповідальності

В продовження вчорашньої теми, про яку довелося багато сьогодні думати, додам про модель зон відповідальності. В такому вигляді, як я їх використовую, придумав їх сам, хоча звісно, ідея не нова.

Що таке зона відповідальності? Це частинка життя, в середині якої немає конфлікту інтересів. Тобто справи однієї зони рухаються до більш-менш однієї цілі. Та, якщо задачі та цілі є тимчасовими, то зони залишаються, доки не зміняться обставини — фактично, загальний набір зон існує все життя. Тож склавши перелік зон один раз, його вистачить надовго.

Зони відповідальності охоплюють все, на що в житті треба звернути увагу — робота, дім, сімʼя, друзі, здоровʼя і так далі. Але такі макрокатегорії ще розділяються. Наприклад, в роботі окрім зони основної посади може бути зона для гільдії або інших обовʼязків. В сімʼї — зони для найближчої сімʼї, розширеної, батьків та дітей. Окремі зони можуть бути для проєктів, різних хобі. В мене виходить близько 20 зон.

Що це дає:


25.06.2023

Самоорганізація з блокнотом, раунд 2

Настав час спробувати систему самоорганізації в блокноті, в наступній ітерації. Головна ціль — це впоратись з ростом кількості задач. В цілому, оригінальна система зберігається, змінюється тільки алгоритм підтримки списку задач.

Система складається приблизно з таких компонент:


24.06.2023

Список проєктів та майбутнього в GTD

Останнім часом багато міркую на тему того, як втримати систему самоорганізації від неконтрольованого росту. Хочу поділитися принаймні однією причиною.

Як в мене зʼявляється величезний список задач? Я користуюся алгоритмом GTD - його я запамʼятав багато років тому та так чи інакше він формує моє мислення про задачі. В цьому алгоритмі є ключове питання — чи можна щось зробити з даним предметом? Я сприймав це як — чи не має обʼєктивних перешкод, щоб його робити. Ну, наприклад, я не можу зараз поїхати в турне по Європі. Це йде в список “на майбутнє” - зрозуміло. Але більшість моїх ідей та бажань готові до роботи вже зараз. Вони й поповнювали список активних проєктів.

Здавалося б, нічого поганого в цьому немає, більше ідей — більше можливостей. Але такий великий список неодмінно заглушує ті справи, які вимагають уваги. Це вже розпочаті проєкти та ті, що мають близький термін. Результатом є те, що ти кидаєш такий список та починаєш займатись тим, що чіпляє увагу. В наслідку, щось робиться, щось забувається, та залишається неприємне відчуття нескерованості.

Так от, зробив висновок, що в список проєктів має потрапляти тільки те, що я вже роблю, або маю намір почати сьогодні. Все інше — в “майбутнє”. Та до того ж починати новий проєкт тільки тоді, коли закінчуєш щось старе. Тобто направляти всі зусилля на закінчення початого (принаймні поетапно.) А коли звільняється місце — обирати щось з “майбутнього”.

Мені здається, що це більш правильна інтерпретація GTD, бо вона виправдовує існування “проєкту” як зафіксованої точки, в яку ти рухаєшся. Якщо все “дієздатне” потрапляє в проєкти, та немає різниці, почати новий проєкт або закінчувати старий, то можна обійтися й простим списком задач.


23.06.2023

Повідомлення про відключення AWS, або хто наглядає наглядачів?

Нещодавно в AWS була чергове відключення. На цей раз зачепило й сервіс AWS Lambda, через що в нас відвалилися система моніторингу, та ми були до деякого ступеня сліпі до того, що взагалі відбувається.

Насправді всі сервіси, що не потребують Lambda, були в порядку. Але, наприклад, якщо Lambda використовується для перевірки здоровʼя, то без них можна опинитись в стані, коли ти не можеш запускати або перезапускати сервіси, або ще гірше — вони почнуть зупинятися сами (хоча такої архітектури, де невідомий стан перевірки призводить до перезапуску, краще уникати.)

Можна сказати — при такого масштабу ситуації користувачі самі здогадаються, що відбувається, тому оскільки вона вийшла з-під нашого контролю, то робити нічого не потрібно. Але все ж принаймні варто помітити таку ситуацію та оголосити про неї раніше, ніж користувачі почнуть писати в підтримку.

Для початку, варто налагодити моніторинг, який знаходиться “на відстані” від головного додатка. Це може бути сервіс healthchecks.io. Або моніторинг в іншому регіоні AWS (бо відразу два регіони рідко відключаться.) Або, ще краще, моніторинг з іншого хмарного провайдера (Google або Azure.)

Багато робити не обовʼязково, аби була базова перевірка. Ось ідея на пʼять хвилин: налаштувати Google Alert на запит aws outage site:news.ycombinator.com.