Skip to content
Урок 1. 12 байт, каждый с работой

Урок 1. 12 байт, каждый с работой

Урок 1. 12 байт, каждый с работой: проектируем формат пакета

Паспорт урока

ПараметрЗначение
Место в модулеBeaconRadio, модуль 1 «Информатика», урок 1 из 7
Длительность45 мин
Возраст12–16
ОборудованиеКомпьютер, бумага в клетку; желательно плата с прошивкой
Предварительные знанияДвоичная и шестнадцатеричная системы (базово)
ПредметИнформатика (представление данных)

Образовательные цели

ЦельБлумМиллерЧем доказывается
1.1Проектировать бинарный пакет: раскладывать величины по байтамприменятьпоказывает какПакет, собранный на бумаге
1.2Упаковывать булевы флаги в битовое полеприменятьпоказывает какСобранный статус-байт 0x69
1.3Обосновывать целочисленное представление вместо дробногооцениватьзнает какОтвет: 4 байта против 8
1.4Объяснять роль порядка байт (little-endian)пониматьзнает какРазбор записи lat×1e7
Легенда, задающая планку. Пакет проектируется для носимого маячка человека с деменцией: GPS-трек, кнопка SOS, детекция падения. Это не абстрактное упражнение — каждый байт обслуживает безопасность реального человека. Держите эту рамку весь урок: она превращает «уложить данные» в инженерную задачу с ценой ошибки.

Сценарий занятия (45 минут)

ВремяБлокЧто делает педагогЧто делают ученики
0–7ПостановкаЛегенда маячка, вопрос «что послать?»Перечисляют нужные данные
7–15Проблема размера«А сколько это байт? Эфир дорогой»Оценивают наивный размер
15–28ТеорияЦелые числа, порядок байт, битовые флагиРазбирают формат
28–40ПрактикаСобирают пакет на бумагеРешают задачи
40–45Итог и ДЗФиксацияЗаписывают

Блок 1. Постановка задачи (0–7 мин)

Легенда

«Мы делаем маячок для пожилого человека с деменцией. Он может уйти и потеряться, может упасть. Маячок должен рассказывать диспетчеру, где человек и что с ним. Вопрос: что именно маячок должен передавать?»

Класс перечисляет, педагог фиксирует на доске:

Что нужно знать диспетчеруДанные
Где человекширота, долгота
Какой маячок (их много)номер устройства
Нажал ли кнопку помощифлаг SOS
Не упал лифлаг падения
Не лежит ли без движенияфлаг неподвижности
Работает ли GPSфлаг валидности
Не сел ли аккумуляторзаряд, флаг разряда

Ключевой вопрос урока

«Всё это надо уложить в один короткий пакет и послать по радио. Почему короткий? Потому что эфир — общий ресурс, а батарея — ограничена. Чем длиннее пакет, тем дольше передача, тем больше энергии и тем меньше места для других. Наша задача — уложить всё нужное в минимум байт.»


Блок 2. Проблема размера (7–15 мин)

Наивный подход

«Давайте прикинем размер “в лоб”. Координата — дробное число вроде 55.6306. Как компьютер хранит дробное число?»

Ответ: тип double — 8 байт. Значит две координаты — 16 байт только на позицию. Плюс всё остальное — получается более 20 байт.

Постановка проблемы оптимизации

«20 байт — много. Можно ли меньше, ничего не потеряв? Оказывается, да — и это работа инженера: уложить те же данные плотнее.»

Записать на доску целевую цифру: 12 байт. Весь урок — путь к ней.


Блок 3. Теория (15–28 мин)

3.1. Базовый уровень (12–14 лет)

Идея 1. Координата — это целое число, если убрать точку.

Широта 55.6306 — это то же, что 556 306 000, если умножить на 10 миллионов. А целое число до пары миллиардов помещается в 4 байта вместо 8. Мы просто «запомнили», что надо потом поделить обратно.

Идея 2. Восемь фактов — в одном байте.

Флаги «нажал SOS», «упал», «лежит», «GPS работает», «батарея села» — это ответы да/нет. Каждый ответ — один бит. В одном байте восемь битов, значит восемь ответов помещаются в один байт вместо восьми.

Аналогия:

Это как список галочек в анкете: не пишешь «да» словом пять раз, а ставишь пять галочек в одной строке.

3.2. Углублённый уровень (14–16 лет)

Шаг 1. Итоговый формат — 12 байт.

СмещениеРазмерПолеТипНазначение
01iduint8номер маячка
1–44latint32широта × 10⁷
5–84lonint32долгота × 10⁷
91statusбиты5 флагов + счётчик
101batteryuint8заряд, %
111crc8uint8контрольная сумма

Шаг 2. Целочисленное представление координаты.

Вместо double (8 байт) координата хранится как int32:

latint=round(lat×107)lat_{\text{int}} = \text{round}(lat \times 10^7)

Для 55.6306: 556 306 000 — умещается в int32 (диапазон ±2,1 млрд). Точность 10⁻⁷ градуса — это около 1 см на местности, заведомо избыточно для GPS (его точность — метры).

Выигрыш: 4 байта вместо 8 на каждую координату, и никаких операций с плавающей точкой в эфире.

Шаг 3. Порядок байт (endianness).

Число 556 306 000 в шестнадцатеричном виде — 0x21288E50. В памяти четыре байта можно расположить двумя способами:

ПорядокБайты в эфиреКто использует
little-endian50 8E 28 21 (младший первым)x86, ARM, наш стенд
big-endian21 28 8E 50 (старший первым)сетевые протоколы («сетевой порядок»)

Отправитель и получатель должны договориться о порядке, иначе число прочитается неверно. Наш стенд использует little-endian — «родной» для процессора, не требует перестановки.

Шаг 4. Битовое поле статуса.

Байт status упаковывает восемь фактов:

Бит76543210
Значениеseqseqseqlow_battgps_validimmobilefallSOS

Биты 0–4 — пять флагов. Биты 5–7 — счётчик seq (0…7 по кругу).

Зачем seq. Вместе со счётчиком кадров LoRaWAN он мгновенно показывает, где теряются пакеты: дыры в счётчике на сервере — проблема в эфире или шлюзе; кадры есть, а строк в базе нет — проблема в обработке. Три бита превращаются в диагностический инструмент.

Шаг 5. Как собрать байт статуса.

status=SOS(fall1)(immobile2)(gps3)(low4)((seq & 7)5)status = SOS \lor (fall \ll 1) \lor (immobile \ll 2) \lor (gps \ll 3) \lor (low \ll 4) \lor ((seq\ \&\ 7) \ll 5)

Оператор << сдвигает бит на нужную позицию, (побитовое ИЛИ) объединяет.


Блок 4. Практикум: собираем пакет (28–40 мин)

Работа на бумаге в клетку, в парах.

Разбор примера вместе с классом

Событие: нажата кнопка SOS, GPS работает, seq = 3.

Флаги: SOS = 1, fall = 0, immobile = 0, gps_valid = 1, low_batt = 0, seq = 3.

status=1(13)(35)=1+8+96=105=0x69status = 1 \lor (1 \ll 3) \lor (3 \ll 5) = 1 + 8 + 96 = 105 = \mathbf{0x69}

Проверить по битам:

Бит76543210
Значение01101001
└─ seq=3 ─┘low=0gps=1im=0fall=0SOS=1

01101001 = 0x69. Сходится.

Сверка с реальным логом. В журнале отладки маячка тревожные пакеты идут со статусами 0x29 → 0x49 → 0x69 → 0x89. Это SOS с растущим seq (1, 2, 3, 4). Ученики могут разобрать эту последовательность сами — она подтверждает, что их расчёт совпадает с настоящей прошивкой.

Блок 5. Практические задачи (внутри блока 4)

Уровень A (12–14 лет)

A1. Сколько фактов «да/нет» помещается в один байт? Почему?

Ответ

Восемь — потому что в байте восемь битов, а каждый бит хранит один ответ да/нет (0 или 1).

A2. Почему координату умножают на 10 миллионов и хранят как целое число?

Ответ

Чтобы избавиться от дробной части: целое число занимает 4 байта вместо 8 у дробного, и с ним проще и надёжнее работать. Множитель 10⁷ сохраняет точность до сантиметра — этого более чем достаточно.

A3. Соберите статус-байт для события: GPS работает, остальное выключено, seq = 0.

Ответ

Только бит 3 (gps_valid): 00001000 = 0x08. Это обычный телеметрический пакет — «всё спокойно, координата свежая».

Уровень B (14–15 лет)

B1. Соберите статус-байт для события: обнаружено падение, человек неподвижен, GPS работает, seq = 5.

Решение

fall = 1 (бит 1), immobile = 1 (бит 2), gps = 1 (бит 3), seq = 5 (биты 5–7).

status=(11)(12)(13)(55)=2+4+8+160=174=0xAEstatus = (1 \ll 1) \lor (1 \ll 2) \lor (1 \ll 3) \lor (5 \ll 5) = 2 + 4 + 8 + 160 = 174 = \mathbf{0xAE}

Проверка по битам: 10101110 = 0xAE. Сходится.

B2. Координата долготы 37.6033. Как она запишется в 4 байта (int32, little-endian)?

Решение

37.6033 × 10⁷ = 376 033 000 = 0x1669CEE8.

В little-endian (младший байт первым) в эфир уйдут байты: E8 CE 69 16.

Проверка обратно: 0x1669CEE8 = 376 033 000; делим на 10⁷ = 37,6033 — исходное значение восстановлено точно.

Замечание для педагога: при программной реализации стоит использовать округление round(v * 1e7), а не отбрасывание дробной части, — иначе на некоторых значениях появится ошибка в последнем разряде из-за представления чисел с плавающей точкой.

B3. Почему отправитель и получатель должны договориться о порядке байт?

Ответ

Число из нескольких байтов можно расположить в памяти двумя способами (младший байт первым или старший первым). Если отправитель пишет одним способом, а получатель читает другим, число прочитается неверно — например, 0x21288E50 превратится в 0x508E2821, то есть в совершенно другую координату. Договорённость о порядке (у нас little-endian) устраняет неоднозначность.

Уровень C (15–16 лет)

C1. Оцените экономию нашего формата по сравнению с наивным (координаты double, флаги — по байту на каждый). Во сколько раз короче?

Решение

Наивный формат:

ПолеБайт
id1
lat (double)8
lon (double)8
5 флагов (по байту)5
battery1
Итого23

Наш формат: 12 байт.

Экономия: 23 / 12 ≈ в 1,9 раза короче. При SF10 это примерно вдвое меньше эфирного времени и энергии на каждый пакет — а маячок шлёт их годами.

C2. Счётчик seq — всего 3 бита (0…7). Не мало ли для диагностики потерь? Обоснуйте.

Разбор

3 бита дают цикл из 8 значений. Этого достаточно, потому что seq работает в паре с 4-байтовым счётчиком FCnt самого LoRaWAN:

  • FCnt (миллиарды значений) показывает потери на уровне эфир/шлюз;
  • seq (8 значений) показывает потери на уровне обработки после приёма — если между двумя строками в базе seq перескочил, потеряна запись в конвейере.

Для второй задачи 8 значений хватает: если подряд теряется больше 8 пакетов обработки, проблема очевидна и без точного счёта. Тратить больше 3 бит на seq было бы расточительством — байт статуса и так плотно занят.

Вывод: размер поля выбирается под его роль, а не «побольше». 3 бита — точный инженерный выбор.

C3. Предложите, что изменить в формате, если добавить передачу высоты (altitude) и скорости движения. Уложитесь в разумный размер.

Разбор

Высота: диапазон в России примерно от −30 до +5000 м, точность метра достаточно. Помещается в int16 (±32 000) — 2 байта.

Скорость пешехода: 0–10 м/с, с точностью 0,1 м/с — значения 0–100, помещается в 1 байт (uint8).

Итого +3 байта → пакет станет 15 байт. Это приемлемо. Но стоит спросить: нужны ли эти поля для задачи? Для маячка человека с деменцией высота бесполезна, скорость — сомнительна. Лучший инженерный ответ часто: «не добавлять то, что не работает на задачу». Каждое поле должно обслуживать конкретную потребность диспетчера.


Ответы на вопросы, которые прозвучат

Вопрос ученикаКак отвечать
«Почему не послать просто текстом, как сообщение?»Текст "55.6306,37.6033,SOS" — это ~20 символов = 20 байт только на координаты, плюс разбор строки на приёмнике. Бинарный формат вдвое короче и парсится мгновенно
«А если координата отрицательная (западная долгота)?»int32 — знаковый тип, хранит и отрицательные. −37.6° × 10⁷ уложится так же
«Зачем битовые флаги, память же большая?»В эфире важна не память, а время передачи. Каждый байт — это эфирное время и энергия батареи. Маячок живёт годами, экономия критична
«Что если понадобится девятый флаг?»В байте статуса seq занимает 3 бита. Если нужен ещё флаг — сократить seq до 2 бит или добавить второй байт статуса. Это осознанное проектное решение
«Как приёмник поймёт, где кончается одно поле и начинается другое?»По фиксированной схеме: все знают, что байты 1–4 — широта, 5–8 — долгота. Формат жёстко задан, разделители не нужны

Раздаточный лист (для печати)

Урок 1. Формат пакета маячка

Задача: уложить данные маячка в 12 байт.

[0]  [1  2  3  4]   [5  6  7  8]   [9]     [10]   [11]
id    lat × 1e7      lon × 1e7    status   batt   CRC8
      (int32)        (int32)      (биты)   (%)

Битовое поле статуса:

Бит76543210
seqseqseqlow_battgps_validimmobilefallSOS

Формула сборки: status = SOS | (fall<<1) | (immobile<<2) | (gps<<3) | (low<<4) | ((seq&7)<<5)

Задания. Соберите статус-байт:

СобытиеБитыРезультат (hex)
SOS, GPS работает, seq=3
Падение, неподвижность, GPS, seq=5
Только GPS (телеметрия), seq=0
Разряд батареи, GPS, seq=0

Перевод координаты в int32:

Широта _______ × 10⁷ = ___________ = 0x________

Мой вывод: зачем нужен компактный бинарный формат?

____________________________________________________


Домашнее задание

Обязательная часть

Врайтап по рубрике А. Обязательный пункт: объясните своими словами, почему координату хранят целым числом, а не дробным.

Уровень A

Придумать формат пакета для другого устройства — например, домашней метеостанции (температура, влажность, давление). Расписать, сколько байт под каждое поле и почему.

Уровень B

Разобрать три статус-байта из лога маячка: 0x29, 0x49, 0x89. Определить для каждого: какие флаги взведены и чему равен seq. Что происходило с маячком?

Ответ для педагога

Все три: бит 0 (SOS) = 1, бит 3 (gps_valid) = 1. seq: 0x29 → 1, 0x49 → 2, 0x89 → 4. Это серия тревожных пакетов SOS с растущим счётчиком (пакет с seq=3, то есть 0x69, между ними потерян или не попал в выборку). Человек нажал кнопку помощи, GPS даёт валидную координату.

Уровень C

Спроектировать формат пакета для маячка с расширенными возможностями: добавить точность GPS (HDOP) и температуру носителя (контроль переохлаждения). Обосновать выбор типа и размера каждого нового поля, оценить итоговый размер пакета и его эфирное время при SF10.


Итог урока: что записать в журнал

Вывод урока 1

  1. В эфире важен размер пакета: он определяет время передачи и расход батареи.
  2. Дробную координату хранят как целое lat × 10⁷: 4 байта вместо 8, без операций с плавающей точкой.
  3. Восемь фактов «да/нет» упаковываются в один байт битовыми флагами.
  4. Отправитель и получатель договариваются о порядке байт (у нас little-endian).
  5. Счётчик seq (3 бита) вместе с FCnt показывает, где теряются пакеты.
  6. Итог: все данные маячка уложены в 12 байт — вдвое компактнее наивного формата.

Связь с курсом

Что родилось на этом урокеГде станет инструментом
Проектирование пакетаFoxHunter (пакет лисы), RFCurtain, PowerSentry
Битовые флагиPowerSentry (байт flags), RFCurtain
Порядок байтЛюбая работа с протоколами
seq как диагностика потерьPowerSentry, WarWalk

Чек-лист педагога перед уроком

  • Бумага в клетку по числу учеников
  • На доске заготовлена таблица битов статуса
  • Проверен пример: SOS+GPS+seq3 = 0x69
  • Готов лог маячка со статусами 0x29…0x89 для сверки
  • Раздаточный лист распечатан