Отправка файла ihex (intel Hex) по UDP с использованием Python Sockets
Я работаю с сокетами IPv6 и UDP, используя python-2.7. Я особенно сосредоточен на многоадресной рассылке IPv6 ff02::1
где каждое Link-Local адрес устройства (с fe80::
) отвечает на запросы от объекта центрального сервера.
У меня есть микроконтроллеры, подключенные к этим устройствам, которым нужна программа в виде .ihex
(Intel Hex). Фрагмент файла, как показано ниже:
:103100005542200135D0085A8245381131400031EE
:103110003F4002000F9308249242381120012F8370
:103120009F4F1E390011F8233F4036000F930724AC
Я думаю, что способ использовать это struct
и используя такие функции, как pack
а также unpack
но я не уверен, что отправка такого файла ihex размером в несколько килобайт решит эту задачу.
Могу ли я сделать что-то вроде:
#!/usr/bin/env python
from struct import pack, unpack
import socket
. # Create a UDP socket and Bind it..
.
myHexCode = open("Filename.ihex")
dataToSend = struct.pack('Paramaters for packing', myHexCode)
.
. Send data to socket..
Какими будут параметры упаковки? (я должен делать !
или Большой или маленький Endian >
или же <
для шестнадцатеричного файла?)
Заметка
Я не могу использовать
scp
ниsftp
поскольку оба эти протокола работают по протоколу TCP и не поддерживают многоадресную рассылку, и я работаю в среде, где потери в сети могут быть выше (Wireless Medium)Также я должен преобразовать файл Intel Hex в двоичный файл, как предложено в этом запросе, а затем упаковать двоичный файл?
1 ответ
Использование UDP с многоадресной рассылкой для отправки файла нескольким потребителям кажется чреватым проблемами, если только весь файл не помещается в один пакет. Пакеты UDP могут быть отброшены / отброшены по ряду причин, и вы уже сказали, что сеть с потерями. У вас должен быть способ для каждого потребителя отслеживать и уведомлять отправителя о сброшенных пакетах.
Это, как говорится, это, безусловно, выполнимо. Одна идея: создать начальный пакет, который вы многоадресно рассылаете несколько раз, возможно со случайными задержками между ними (в попытке гарантировать, что все станции получат его). Этот начальный пакет говорит в сущности как "Готов отправить новую программу - ожидайте N последующих пакетов записи").
Затем отправьте N пакетов, возможно, по два раза в каждом. Поместите идентификационный серийный номер в каждый пакет данных и попросите потребителей отслеживать, какие из них они получают. После некоторой задержки (или когда все были получены), каждый потребитель должен ответить пакетом состояния, говорящим либо "Я получил все N пакетов", либо "Я не получил записи 5, 98, 144 и 3019" (или любую другую схему). уместно на основе потерь).
Затем отправитель может собирать эти идентификаторы потерянных записей и отправлять их до тех пор, пока все потребители не будут удовлетворены тем, что получили весь файл.
Для упаковки их в дейтаграммы, я не думаю, что имеет значение, отправляете ли вы "intel hex" или двоичный файл. В любом случае вы захотите отправить их в виде потока байтов. Двоичный файл будет меньше и, следовательно, будет принимать меньше пакетов, но нет другой разницы в процессе их отправки. По той же причине выбранный порядок байтов не будет иметь значения. Для простых потоков байтов вам не нужно использовать struct
упаковать их вообще. Вы можете просто отправить их.
Примечание: python3 различает
bytes
а такжеstr
типы, так что вам нужно будет открыть файл в "двоичном" режиме, чтобы это оставалось верным для python3.
Однако если, как предложено выше, вы в конечном итоге отправляете серийный номер в каждом пакете, этот серийный номер нужно будет как-то отформатировать. Вы можете отформатировать число в виде строки ASCII и нет struct.pack
нужно. Или, если вы отформатируете его в двоичном формате, вам нужно будет выбрать формат упаковки. Обычно сетевые пакеты используют "сетевой порядок байтов" (который фактически совпадает с порядком байтов), но это только соглашение.
Если бы я делал это, я мог бы структурировать каждую запись с помощью:
- тип записи (двоичный, один байт - это пакет данных)
- идентификатор записи (двоичный, два байта - серийный номер [или больше в зависимости от размера файлов))
- длина данных записи (двоичная, два байта, указывающие длину поля данных записи)
- данные записи (двоичные, N байт)
Затем вы можете создать полезную нагрузку примерно так:
payload = struct.pack("!BHH", record_type, record_id, len(record_data))
+ record_data
Здесь мы создаем 5-байтовую строку с struct.pack
содержит поля заголовка (упакованные с использованием сетевого порядка байтов), а затем просто добавляют запись_данных, которая уже является строкой байтов.