Skip to content

Либа для кодирования и декодирования произвольных сообщений в набор команд

Notifications You must be signed in to change notification settings

hackathon-csharp/lib

Repository files navigation

datapacklib

Протокол и библиотека для преобразования произвольных массивов байтов в переходы SignalChange и обратно. Решение рассчитано на передачу через многоканальный (RGBW) источник света/приёмник и умеет не только обнаруживать, но и исправлять отдельные ошибки без повторной передачи кадров.

Почему это надёжно

  • Каждый кадр начинается преамбулой (длинный импульс + пауза) с магическим номером 0xC39A и завершается эндером 0x51AA.
  • Заголовок содержит длину полезной нагрузки и CRC8-ATM по данным. Дополнительных версионных байтов больше нет.
  • Цветовая четырёхуровневая модуляция теперь непрерывна: после каждого цвета сразу включается следующий, без «чёрных» разделителей. Кроме преамбулы и хвостовой паузы выключенное состояние не используется.
  • Для каждого полубайта используется код Хэмминга (7,4) и дублирование блоков. Декодер выполняет перебор допустимых альтернатив и может восстановить кадр даже при потере нескольких цветовых переходов.
  • Подробная статистика (магические несоответствия, попытки коррекции, количество неоднозначных переходов) помогает оценить качество канала.

Формат кадра

Поле Размер (байт) Описание
Magic 2 0xC39A — позволяет быстро выровнять поток
Payload Length 2 Длина полезных данных
Payload N Пользовательские данные
CRC8 1 Контрольная сумма полезной нагрузки
Ender 2 0x51AA — окончание кадра

По умолчанию единичный временной «тик» — 600 мкс. Преамбула: 16 тиков белого света и 8 тиков паузы. Первый рабочий цвет — красный, далее энкодер чередует цвета так, чтобы одинаковые не соседствовали. После кадра автоматически добавляется «тишина» на 12 тиков, чтобы разделить кадры.

Использование

#include "datapacklib.h"

using namespace datapack;

Encoder encoder;
Decoder decoder(
	[](const std::uint8_t* data, std::size_t len, void*) {
		// обработка полезных данных
		std::vector<std::uint8_t> payload(data, data + len);
		// ...
	});

std::vector<std::uint8_t> payloadBytes = {/* ... */};
datapack::SignalBuffer signal;
if (encoder.encode(payloadBytes.data(), payloadBytes.size(), signal))
{
	for (std::size_t i = 0; i < signal.size(); ++i)
	{
		decoder.feed(signal[i]);
	}
}

SignalChange::level может принимать одно из пяти значений (Off, White, Red, Green, Blue). Для передачи полезных данных используются только цвета; «выключенное» (Off) встречается только в преамбуле и в завершающем промежутке между кадрами.

Декодер можно создавать один раз и вызывать feed при каждом наблюдаемом изменении уровня (значение и длительность в микросекундах). Когда кадр успешно собран или восстановлен после исправлений, вызывается переданный коллбэк.

JavaScript версия

datapacklib.js теперь реализует ту же схему кодирования, что и минималистичная C++-библиотека в этом репозитории. Модуль распространяется в формате UMD: его можно подключить через <script> на веб-странице, импортировать как CommonJS-модуль в Node.js или бандлить любым инструментом.

<script src="datapacklib.js"></script>
<script>
	const {
		LightLevel,
		setSendData,
		getSendCommands,
		feed,
		getReceivedData,
		setOnPacketReceived,
	} = datapack;

	const payload = 'Hello, IR! Привет мир!';
	setOnPacketReceived(({ index, word }) => {
		console.log('Packet', index, '=>', word.toString(16));
	});

	setSendData(payload);
	const commands = getSendCommands();

	// эмулируем передачу: просто подаём закодированные сигналы в декодер
	commands.forEach((cmd) => feed(cmd));

	const rawBytes = getReceivedData();
	console.log('Decoded string:', new TextDecoder().decode(rawBytes));
</script>

В Node.js аналогичные функции доступны через const datapack = require('./datapacklib.js');. Модуль предоставляет:

  • LightLevel — перечисление уровней освещения.
  • setSendData(input) — принимает строку, ArrayBuffer, Uint8Array или массив байтов и формирует внутренний буфер слов.
  • getSendCommands() — возвращает массив { value, duration } для отправки.
  • feed({ value, duration }) — подать наблюдаемый переход в декодер.
  • setOnPacketReceived(callback) — коллбэк при успешном восстановлении пакета.
  • getReceivedData() / getReceivedWords() — срезы накопленных данных.
  • setMinDuration(value) и setSignalDuration(value) — настройка временных параметров.
  • resetEncoder() и resetDecoder() — очистка внутренних буферов.

Сборка примера

g++ -std=c++17 -Wall -Wextra example.cpp datapacklib.cpp -o datapack_demo
./datapack_demo

Настройка протокола

ProtocolConfig позволяет менять длительности импульсов, допуск, базовый цвет для запуска цепочки, коэффициент избыточности (1–3 копии блоков), макс. длину полезной нагрузки, magic/ender и т.д. Все проверки выполняются как на стороне энкодера (возвращает false при ошибке), так и на стороне декодера.

About

Либа для кодирования и декодирования произвольных сообщений в набор команд

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published