Итак, erlang / elixir - отличные языки для деконструкции необработанных пакетов в двоичном формате - это то, что возвращает Circuits.UART.read()
.Вы деконструируете двоичный файл <<...>>
с совпадением двоичного шаблона , и ваша таблица данных содержит спецификацию для шаблона, который вы будете использовать.Нет необходимости в кодировании base16, делении на 424D
или разбиении на куски 2:
defmodule My do
def match(<<
66, 77,
_fr_len::big-integer-size(16),
data1::big-integer-size(16),
data2::big-integer-size(16),
data3::big-integer-size(16),
data4::big-integer-size(16),
data5::big-integer-size(16),
data6::big-integer-size(16),
data7::big-integer-size(16),
data8::big-integer-size(16),
data9::big-integer-size(16),
data10::big-integer-size(16),
data11::big-integer-size(16),
data12::big-integer-size(16),
_reserved::big-integer-size(16),
_check_code::big-integer-size(16),
rest::binary
>>) do
IO.puts "pm 1.0 cf: #{data1} ug/m^3"
IO.puts "pm 2.5 atmospheric: #{data5} ug/m^3"
match(rest)
end
def match(partial_frame) do
IO.puts "partial_frame:"
IO.inspect partial_frame
end
def go() do
match(<<66, 77, 0, 28, 0, 23, 0, 32, 0, 32, 0, 22, 0, 31, 0, 32,
17, 124, 4, 211, 0, 171, 0, 8, 0, 0, 0, 0, 151, 0, 4, 5,
66, 77, 0, 28, 0, 23, 0, 32, 0, 32, 0, 22, 0, 31, 0, 32>>)
:ok
end
end
В iex:
iex(1)> My.go
pm 1.0 cf: 23 ug/m^3
pm 2.5 atmospheric: 31 ug/m^3
partial_frame:
<<66, 77, 0, 28, 0, 23, 0, 32, 0, 32, 0, 22, 0, 31, 0, 32>>
:ok
Вы можете написать 0x42, 0x4D
внутри шаблоначтобы точно соответствовать спецификации таблицы данных, однако я думаю, что более ясно использовать десятичные эквиваленты, 66, 77
, потому что elixir не выводит шестнадцатеричные коды при выводе двоичного файла, а elixir выводит десятичные дроби - как это видно в вашем data
(Или, иногда, elixir выводит строку в двойных кавычках для двоичного файла, что действительно сбивает с толку и глупо.) Имея в шаблоне 66, 77
, вы можете легко посмотреть на данные и увидеть, где они совпадают.
Примечаниечто последний сегмент rest::binary
подобен записи .*
в регулярном выражении.
Прежде чем доверять любым данным, назначенным переменным, вам, вероятно, следует проверить, что длина кадра равна 28, и проверить код проверки.К сожалению, я не могу понять, что представляет код проверки.Я получаю 1029
за код проверки.
========= *
Можете ли вы опубликовать пример того, как вы ожидаете, что данные будут выглядеть?
Шестнадцатеричная строка, такая как "1C"
, эквивалентна десятичной 28
.Вы можете получить все десятичные эквиваленты, как это:
data = [ "00", "1C", "00", "17", "00", "20", "00", "20", "00", "16", "00",
"1F", "00", "20", "11", "7C", "04", "D3", "00", "AB", "00", "08",
"00", "00", "00", "00", "97", "00", "04", "05"]
for str <- data do
Integer.parse(str, 16)
end
|> IO.inspect
|> Enum.map(fn {a, _} -> a end)
Integer.parse () возвращает кортеж, где первый элемент является целым числом, а второй элемент является "остатком"строки ", то есть все, что не может быть интерпретировано как целое число.
Вывод:
[
{0, ""},
{28, ""},
{0, ""},
{23, ""},
{0, ""},
{32, ""},
{0, ""},
{32, ""},
{0, ""},
{22, ""},
{0, ""},
{31, ""},
{0, ""},
{32, ""},
{17, ""},
{124, ""},
{4, ""},
{211, ""},
{0, ""},
{171, ""},
{0, ""},
{8, ""},
{0, ""},
{0, ""},
{0, ""},
{0, ""},
{151, ""},
{0, ""},
{4, ""},
{5, ""}
]
[0, 28, 0, 23, 0, 32, 0, 32, 0, 22, 0, 31, 0, 32, 17, 124,
4, 211, 0, 171, 0, 8, 0, 0, 0, 0, 151, 0, 4, 5]
Это то, что ваши данные должны выглядеть?
Это похоже на код java:
...forEach[b | bts.append(Integer.toHexString(b)]
немного изменяет оператор битового оператора java : |
, что не имеет смысла для меня в этом фрагменте кода,Но в эликсире вы бы сделали это с Bitwise.bor (a, b) .Я действительно думаю, что код Java должен выглядеть следующим образом:
...forEach(b -> bts.append(Integer.toHexString(b))
Другими словами, forEach () принимает лямбду в качестве аргумента.Черт возьми, это так любопытно, что я собираюсь спросить парня, что это значит.
Редактировать:
Хорошо, парень ответил мне, и это не Java--это синтаксис лямбды, хотя - на некотором языке DSL.