Перейти к содержанию
Материалы раздела

Heatshrink

Модуль сжатия данных для встраиваемых систем. Использует алгоритм LZSS и поддерживает как одноразовую, так и потоковую обработку.

Heatshrink особенно полезен для:

  • Сжатия данных перед передачей по сети (MQTT, HTTP)
  • Компактного хранения логов и конфигураций
  • OTA обновлений
  • Сжатия Lua скриптов

heatshrink.encode(data [, window, lookahead])

Сжимает данные.

Аргументы:

  • data: строка с данными для сжатия
  • window (опционально): размер окна поиска (4-14, по умолчанию 10 = 1024 байта)
  • lookahead (опционально): размер предпросмотра (3 до window-1, по умолчанию 5 = 32 байта)

Если для окна 4 или 5 параметр lookahead не указан, модуль автоматически использует window - 1.

Возвращает: сжатые данные (строка).

-- Простое сжатие с параметрами по умолчанию
local original = "Hello, World! Hello, World! Hello, World!"
local compressed = heatshrink.encode(original)
print("Original: " .. #original .. " bytes")
print("Compressed: " .. #compressed .. " bytes")
Original: 41 bytes
Compressed: 22 bytes
-- Сжатие с пользовательскими параметрами
local compressed = heatshrink.encode(data, 8, 4)

-- Или через таблицу
local compressed = heatshrink.encode(data, {window = 8, lookahead = 4})

heatshrink.decode(data [, window, lookahead, max_output])

Распаковывает данные. Параметры window и lookahead должны совпадать с теми, что использовались при сжатии.

Аргументы:

  • data: строка со сжатыми данными
  • window (опционально): размер окна 4-15 (должен совпадать с encode)
  • lookahead (опционально): размер предпросмотра (должен совпадать с encode)
  • max_output (опционально): максимальный размер результата, по умолчанию 262144 байта; допустимый диапазон 1-1048576 байт

Возвращает: распакованные данные (строка).

local compressed = heatshrink.encode("Hello, World!")
local decompressed = heatshrink.decode(compressed)
print(decompressed)
Hello, World!

Параметры можно передать таблицей:

local decompressed = heatshrink.decode(compressed, {
    window = 10,
    lookahead = 5,
    max_output = 512 * 1024,
})

Для данных больше 1 МиБ используйте потоковый декодер.

heatshrink.encoder([params])

Создает объект-кодировщик для инкрементального сжатия данных. Полезен при работе с большими объемами данных или потоковой обработке.

Аргументы:

  • params (опционально): таблица с параметрами {window = N, lookahead = N} или числа window, lookahead; максимальное окно кодировщика — 14

Возвращает: объект encoder.

local enc = heatshrink.encoder()
-- или
local enc = heatshrink.encoder({window = 10, lookahead = 5})
-- или
local enc = heatshrink.encoder(10, 5)

encoder:sink(data)

Подает данные на вход кодировщика.

Возвращает: количество принятых байт.

local consumed = enc:sink("Hello, World!")

encoder:poll([maxlen])

Извлекает сжатые данные из кодировщика.

Аргументы:

  • maxlen (опционально): максимальный размер буфера от 1 до 65536 байт (по умолчанию 4096)

Возвращает: data, has_more (сжатые данные и флаг наличия дополнительных данных).

local data, has_more = enc:poll()
while has_more do
    local more_data
    more_data, has_more = enc:poll()
    data = data .. more_data
end

encoder:finish()

Завершает сжатие и сбрасывает оставшиеся данные.

Возвращает: is_done (true если сжатие завершено).

local is_done = enc:finish()
while not is_done do
    local data = enc:poll()
    -- обработка data
    is_done = enc:finish()
end

encoder:reset()

Сбрасывает состояние кодировщика для повторного использования.

enc:reset()

heatshrink.decoder([params])

Создает объект-декодер для инкрементальной распаковки данных.

Аргументы:

  • params (опционально): таблица {window = N, lookahead = N, input_buffer = N}; input_buffer должен быть в диапазоне 1-65535

Возвращает: объект decoder.

local dec = heatshrink.decoder()
-- или с пользовательским буфером
local dec = heatshrink.decoder({window = 10, lookahead = 5, input_buffer = 512})

decoder:sink(data)

Подает сжатые данные на вход декодера.

Возвращает: количество принятых байт.

decoder:poll([maxlen])

Извлекает распакованные данные из декодера.

Параметр maxlen должен быть в диапазоне 1-65536 байт; значение по умолчанию — 4096.

Возвращает: data, has_more.

decoder:finish()

Завершает распаковку.

Возвращает: is_done.

decoder:reset()

Сбрасывает состояние декодера.

Константы

  • heatshrink.MIN_WINDOW — минимальный размер окна (4)
  • heatshrink.MAX_WINDOW — максимальный размер окна кодировщика (14)
  • heatshrink.MAX_DECODER_WINDOW — максимальный размер окна декодера (15)
  • heatshrink.MIN_LOOKAHEAD — минимальный размер предпросмотра (3)
  • heatshrink.DEFAULT_MAX_OUTPUT — стандартный лимит результата decode (262144 байта)
  • heatshrink.MAX_OUTPUT — максимальный разрешенный лимит результата decode (1048576 байт)

Примеры

Сжатие файла

-- Сжатие Lua скрипта
local f = io.open("/sd/script.lua", "r")
local content = f:read("*a")
f:close()

local compressed = heatshrink.encode(content)

local f = io.open("/sd/script.lua.hs", "w")
f:write(compressed)
f:close()

print("Compression ratio: " .. math.floor(#compressed / #content * 100) .. "%")

Потоковое сжатие для MQTT

-- Сжатие данных перед отправкой
local function compress_and_send(topic, data)
    local compressed = heatshrink.encode(data)
    mqtt:publish(topic .. "/compressed", compressed)
end

-- Получение и распаковка
mqtt:subscribe("sensor/data/compressed", function(topic, payload)
    local data = heatshrink.decode(payload)
    print("Received: " .. data)
end)

Инкрементальное сжатие большого файла

local enc = heatshrink.encoder()
local f_in = io.open("/sd/large_file.txt", "r")
local f_out = io.open("/sd/large_file.hs", "w")

-- Читаем и сжимаем по частям
while true do
    local chunk = f_in:read(1024)
    if not chunk then break end

    enc:sink(chunk)

    local data, has_more = enc:poll()
    f_out:write(data)
    while has_more do
        data, has_more = enc:poll()
        f_out:write(data)
    end
end

-- Завершаем сжатие
local is_done = enc:finish()
while not is_done do
    local data = enc:poll()
    f_out:write(data)
    is_done = enc:finish()
end

f_in:close()
f_out:close()

Рекомендации по параметрам

ПараметрПамятьСжатиеРекомендация
window=8, lookahead=4~256 байтсреднеедля очень ограниченной памяти
window=10, lookahead=5~1 КБхорошеепо умолчанию, рекомендуется
window=12, lookahead=6~4 КБотличноедля максимального сжатия

Большее окно даёт лучшее сжатие, но требует больше памяти. Lookahead обычно устанавливается как window/2.