diff --git a/lib/exmbus/parser/apl/data_record.ex b/lib/exmbus/parser/apl/data_record.ex index 3382c68..7230b64 100644 --- a/lib/exmbus/parser/apl/data_record.ex +++ b/lib/exmbus/parser/apl/data_record.ex @@ -38,8 +38,8 @@ defmodule Exmbus.Parser.Apl.DataRecord do @doc """ Decodes a single DataRecord from a binary. """ - def parse(bin, opts, ctx) do - case Header.parse(bin, opts, ctx) do + def parse(bin, ctx) do + case Header.parse(bin, ctx) do {:ok, %Header{} = header, rest} -> case parse_data(header, rest) do {:ok, data, rest} -> @@ -64,8 +64,8 @@ defmodule Exmbus.Parser.Apl.DataRecord do end end - def unparse(opts, %__MODULE__{header: h, data: d}) do - with {:ok, h_bytes} <- Header.unparse(opts, h), + def unparse(%__MODULE__{header: h, data: d}) do + with {:ok, h_bytes} <- Header.unparse(h), {:ok, d_bytes} <- unparse_data(h, d) do {:ok, <>} end diff --git a/lib/exmbus/parser/apl/data_record/data_information_block.ex b/lib/exmbus/parser/apl/data_record/data_information_block.ex index 74b069a..0a50105 100644 --- a/lib/exmbus/parser/apl/data_record/data_information_block.ex +++ b/lib/exmbus/parser/apl/data_record/data_information_block.ex @@ -29,13 +29,13 @@ defmodule Exmbus.Parser.Apl.DataRecord.DataInformationBlock do size: nil ] - def unparse(_opts, %__MODULE__{device: 0, tariff: 0, storage: s} = dib) when s <= 1 do + def unparse(%__MODULE__{device: 0, tariff: 0, storage: s} = dib) when s <= 1 do ff_int = encode_function_field(dib.function_field) df_int = encode_data_field(dib.data_type, dib.size) {:ok, <<0::1, s::1, ff_int::2, df_int::4>>} end - def parse(<>, _opts, _ctx) do + def parse(<>, _ctx) do # note that we are effectively stripping the least-significant bits of the dif which is # always 0b1111 (i.e. 0xF) for special functions, so the following case only checks for the top # 4 bits. In the manual these are written together (i.e. 0x0F), here we only write the MSB (0x0 instead of 0x0F) @@ -64,7 +64,7 @@ defmodule Exmbus.Parser.Apl.DataRecord.DataInformationBlock do end # regular DIF parsing: - def parse(<>, _opts, _ctx) do + def parse(<>, _ctx) do {:ok, device, tariff, msb_storage, rest} = case e do # if extensions, decode dife: diff --git a/lib/exmbus/parser/apl/data_record/header.ex b/lib/exmbus/parser/apl/data_record/header.ex index a53bcd7..3778c2d 100644 --- a/lib/exmbus/parser/apl/data_record/header.ex +++ b/lib/exmbus/parser/apl/data_record/header.ex @@ -2,7 +2,6 @@ defmodule Exmbus.Parser.Apl.DataRecord.Header do @moduledoc """ This module represents the header of a DataRecord. """ - alias Exmbus.Parser.Binary alias Exmbus.Parser.Apl.DataRecord.DataInformationBlock, as: DIB alias Exmbus.Parser.Apl.DataRecord.ValueInformationBlock, as: VIB @@ -37,28 +36,27 @@ defmodule Exmbus.Parser.Apl.DataRecord.Header do @doc """ Parses the next DataRecord Header from a binary. """ - def parse(bin, opts, ctx) do - {:ok, dib_bytes, rest_after_dib} = Binary.collect_by_extension_bit(bin) - - case DIB.parse(dib_bytes, opts, ctx) do - {:special_function, type, <<>>} -> + def parse(bin, ctx) do + case DIB.parse(bin, ctx) do + {:special_function, type, rest_after_dib} -> # we just return the special function. The parser upstream will have to decide what to do, # but there isn't a real header here. The APL layer knows what to do. {:special_function, type, rest_after_dib} - {:ok, %DIB{} = dib, <<>>} -> - # {:ok, vib_bytes, rest_after_vib} = Binary.collect_by_extension_bit(rest_after_dib) + {:ok, %DIB{} = dib, rest_after_dib} -> # We found a DataInformationBlock. # We now expect a VIB to follow, which needs the context from the DIB to be able to parse # correctly. - case VIB.parse(rest_after_dib, opts, %{ctx | dib: dib}) do + case VIB.parse(rest_after_dib, %{ctx | dib: dib}) do {:ok, %VIB{} = vib, rest_after_vib} -> - vib_bytes = - binary_part( - rest_after_dib, - 0, - byte_size(rest_after_dib) - byte_size(rest_after_vib) - ) + dib_size = byte_size(bin) - byte_size(rest_after_dib) + vib_size = byte_size(rest_after_dib) - byte_size(rest_after_vib) + + << + dib_bytes::binary-size(dib_size), + vib_bytes::binary-size(vib_size), + _::binary + >> = bin {:ok, coding} = summarize_coding(dib, vib) @@ -84,15 +82,15 @@ defmodule Exmbus.Parser.Apl.DataRecord.Header do }, rest_after_vib} end - {:error, reason, <<>>} -> + {:error, reason, rest_after_dib} -> {:ok, %InvalidHeader{error_message: "Parsing DIB failed: #{inspect(reason)}"}, rest_after_dib} end end - def unparse(opts, %__MODULE__{vib: vib, dib: dib}) do - with {:ok, vib_bytes} <- VIB.unparse(opts, vib), - {:ok, dib_bytes} <- DIB.unparse(opts, dib) do + def unparse(%__MODULE__{vib: vib, dib: dib}) do + with {:ok, vib_bytes} <- VIB.unparse(vib), + {:ok, dib_bytes} <- DIB.unparse(dib) do {:ok, <>} end end diff --git a/lib/exmbus/parser/apl/data_record/value_information_block.ex b/lib/exmbus/parser/apl/data_record/value_information_block.ex index cbdc1a0..08c241b 100644 --- a/lib/exmbus/parser/apl/data_record/value_information_block.ex +++ b/lib/exmbus/parser/apl/data_record/value_information_block.ex @@ -52,15 +52,15 @@ defmodule Exmbus.Parser.Apl.DataRecord.ValueInformationBlock do table: nil ] - @spec parse(binary, opts :: map(), Context.t()) :: + @spec parse(binary, Context.t()) :: {:ok, VIB.t(), rest :: binary} | {:error, any, binary} - def parse(bin, opts, ctx) do + def parse(bin, ctx) do # delegate the parsing to the primary table - VifTableMain.parse(bin, opts, ctx) + VifTableMain.parse(bin, ctx) end # Basic unparse, main table, no extensions - def unparse(opts, %VIB{table: :main} = vib) do - VifTableMain.unparse(opts, vib) + def unparse(%VIB{table: :main} = vib) do + VifTableMain.unparse(vib) end end diff --git a/lib/exmbus/parser/apl/data_record/value_information_block/vif_table_fb.ex b/lib/exmbus/parser/apl/data_record/value_information_block/vif_table_fb.ex index 3637019..91f65e3 100644 --- a/lib/exmbus/parser/apl/data_record/value_information_block/vif_table_fb.ex +++ b/lib/exmbus/parser/apl/data_record/value_information_block/vif_table_fb.ex @@ -8,38 +8,38 @@ defmodule Exmbus.Parser.Apl.DataRecord.ValueInformationBlock.VifTableFB do alias Exmbus.Parser.Apl.DataRecord.ValueInformationBlock.Vife # Table 0xFB from table 14 in EN 13757-3:2018 section 6.4.5 - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx| vib: %VIB{table: :fb, description: :energy, multiplier: pow10to(n-1), unit: "MWh"}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx| vib: %VIB{table: :fb, description: :reactive_energy, multiplier: pow10to(n), unit: "kVARh"}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx| vib: %VIB{table: :fb, description: :apparent_energy, multiplier: pow10to(n), unit: "kVAh"}}) - def parse(<>, _opts, ctx), do: Vife.error(e, rest, {:reserved, "VIF E000011n reserved"}, ctx) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx| vib: %VIB{table: :fb, description: :energy, multiplier: pow10to(n-1), unit: "GJ"}}) - def parse(<>, _opts, ctx), do: Vife.error(e, rest, {:reserved, "VIF E000101n reserved"}, ctx) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx| vib: %VIB{table: :fb, description: :energy, multiplier: pow10to(nn-1), unit: "MCal"}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx| vib: %VIB{table: :fb, description: :volume, multiplier: pow10to(n+2), unit: "m^3"}}) - def parse(<>, _opts, ctx), do: Vife.error(e, rest, {:reserved, "VIF E001001n reserved"}, ctx) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx| vib: %VIB{table: :fb, description: :reactive_power, multiplier: pow10to(nn-3), unit: "kVAR"}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx| vib: %VIB{table: :fb, coding: fb_remark_d(ctx), description: :mass, multiplier: pow10to(n+2), unit: "t"}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx| vib: %VIB{table: :fb, coding: fb_remark_d(ctx), description: :relative_humidity, multiplier: pow10to(n-1), unit: "%"}}) - def parse(<>, _opts, ctx) when n >= 0b001_1100 and n <= 0b001_1111, do: Vife.error(e, rest, {:reserved, "VIF E0011100 - E0011111 reserved"}, ctx) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx| vib: %VIB{table: :fb, description: :volume, unit: "ft^3"}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx| vib: %VIB{table: :fb, description: :volume, multiplier: 0.1, unit: "ft^3"}}) - def parse(<>, _opts, ctx) when n >= 0b010_0010 and n <= 0b010_0111, do: Vife.error(e, rest, {:reserved, "VIF E0100010 - E0100111 were used until 2004, now they are reserved for future use."}, ctx) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx| vib: %VIB{table: :fb, description: :power, multiplier: pow10to(n-1), unit: "MW"}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx| vib: %VIB{table: :fb, description: :phase_volt_to_volt, unit: "°"}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx| vib: %VIB{table: :fb, description: :phase_volt_to_current, unit: "°"}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx| vib: %VIB{table: :fb, description: :frequency, multiplier: pow10to(nn-3), unit: "Hz"}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx| vib: %VIB{table: :fb, description: :power, multiplier: pow10to(n-1), unit: "GJ/h"}}) - def parse(<>, _opts, ctx), do: Vife.error(e, rest, {:reserved, "VIF E011001n reserved"}, ctx) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx| vib: %VIB{table: :fb, description: :apparent_power, multiplier: pow10to(nn-3), unit: "kVA"}}) - def parse(<>, _opts, ctx) when n >= 0b0111000 and n <= 0b1010111, do: Vife.error(e, rest, {:reserved, "E0111000 - E1010111 reserved"}, ctx) - def parse(<>, _opts, ctx) when n >= 0b010_0010 and n <= 0b010_0111, do: Vife.error(e, rest, {:reserved, "VIF E1011000 - E1100111 were used until 2004, now they are reserved for future use."}, ctx) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx| vib: %VIB{table: :fb, description: :temperature_limit, multiplier: pow10to(nn-3), unit: "°C"}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx| vib: %VIB{table: :fb, description: :cumulative_max_active_power, multiplier: pow10to(nnn-3), unit: "W"}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx| vib: %VIB{table: :fb, coding: fb_remark_d(ctx), description: :resulting_rating_factor_k, multiplier: pow2to(-12), unit: "units for HCA"}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx| vib: %VIB{table: :fb, coding: fb_remark_d(ctx), description: :thermal_output_rating_factor_kq, multiplier: pow2to(-12), unit: "W"}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx| vib: %VIB{table: :fb, description: :energy, multiplier: pow10to(n-1), unit: "MWh"}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx| vib: %VIB{table: :fb, description: :reactive_energy, multiplier: pow10to(n), unit: "kVARh"}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx| vib: %VIB{table: :fb, description: :apparent_energy, multiplier: pow10to(n), unit: "kVAh"}}) + def parse(<>, ctx), do: Vife.error(e, rest, {:reserved, "VIF E000011n reserved"}, ctx) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx| vib: %VIB{table: :fb, description: :energy, multiplier: pow10to(n-1), unit: "GJ"}}) + def parse(<>, ctx), do: Vife.error(e, rest, {:reserved, "VIF E000101n reserved"}, ctx) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx| vib: %VIB{table: :fb, description: :energy, multiplier: pow10to(nn-1), unit: "MCal"}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx| vib: %VIB{table: :fb, description: :volume, multiplier: pow10to(n+2), unit: "m^3"}}) + def parse(<>, ctx), do: Vife.error(e, rest, {:reserved, "VIF E001001n reserved"}, ctx) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx| vib: %VIB{table: :fb, description: :reactive_power, multiplier: pow10to(nn-3), unit: "kVAR"}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx| vib: %VIB{table: :fb, coding: fb_remark_d(ctx), description: :mass, multiplier: pow10to(n+2), unit: "t"}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx| vib: %VIB{table: :fb, coding: fb_remark_d(ctx), description: :relative_humidity, multiplier: pow10to(n-1), unit: "%"}}) + def parse(<>, ctx) when n >= 0b001_1100 and n <= 0b001_1111, do: Vife.error(e, rest, {:reserved, "VIF E0011100 - E0011111 reserved"}, ctx) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx| vib: %VIB{table: :fb, description: :volume, unit: "ft^3"}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx| vib: %VIB{table: :fb, description: :volume, multiplier: 0.1, unit: "ft^3"}}) + def parse(<>, ctx) when n >= 0b010_0010 and n <= 0b010_0111, do: Vife.error(e, rest, {:reserved, "VIF E0100010 - E0100111 were used until 2004, now they are reserved for future use."}, ctx) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx| vib: %VIB{table: :fb, description: :power, multiplier: pow10to(n-1), unit: "MW"}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx| vib: %VIB{table: :fb, description: :phase_volt_to_volt, unit: "°"}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx| vib: %VIB{table: :fb, description: :phase_volt_to_current, unit: "°"}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx| vib: %VIB{table: :fb, description: :frequency, multiplier: pow10to(nn-3), unit: "Hz"}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx| vib: %VIB{table: :fb, description: :power, multiplier: pow10to(n-1), unit: "GJ/h"}}) + def parse(<>, ctx), do: Vife.error(e, rest, {:reserved, "VIF E011001n reserved"}, ctx) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx| vib: %VIB{table: :fb, description: :apparent_power, multiplier: pow10to(nn-3), unit: "kVA"}}) + def parse(<>, ctx) when n >= 0b0111000 and n <= 0b1010111, do: Vife.error(e, rest, {:reserved, "E0111000 - E1010111 reserved"}, ctx) + def parse(<>, ctx) when n >= 0b010_0010 and n <= 0b010_0111, do: Vife.error(e, rest, {:reserved, "VIF E1011000 - E1100111 were used until 2004, now they are reserved for future use."}, ctx) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx| vib: %VIB{table: :fb, description: :temperature_limit, multiplier: pow10to(nn-3), unit: "°C"}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx| vib: %VIB{table: :fb, description: :cumulative_max_active_power, multiplier: pow10to(nnn-3), unit: "W"}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx| vib: %VIB{table: :fb, coding: fb_remark_d(ctx), description: :resulting_rating_factor_k, multiplier: pow2to(-12), unit: "units for HCA"}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx| vib: %VIB{table: :fb, coding: fb_remark_d(ctx), description: :thermal_output_rating_factor_kq, multiplier: pow2to(-12), unit: "W"}}) # skipping some HCA things here - def parse(<>, _opts, ctx) do + def parse(<>, ctx) do raise "decoding from VIF linear extension table 0xFB not implemented. VIFE was: #{Exmbus.Debug.to_bits(vif)}, ctx was: #{inspect ctx}" end diff --git a/lib/exmbus/parser/apl/data_record/value_information_block/vif_table_fd.ex b/lib/exmbus/parser/apl/data_record/value_information_block/vif_table_fd.ex index 187678c..02ca15e 100644 --- a/lib/exmbus/parser/apl/data_record/value_information_block/vif_table_fd.ex +++ b/lib/exmbus/parser/apl/data_record/value_information_block/vif_table_fd.ex @@ -10,62 +10,62 @@ defmodule Exmbus.Parser.Apl.DataRecord.ValueInformationBlock.VifTableFD do ## ## The FD table ## - def parse(<<_::1, 0b000_00::5, _nn::2>>, _opts, _ctx), do: raise "0xFD vif 0bE00000nn not supported. Credit of 10^(nn–3) of the nominal local legal currency units." - def parse(<<_::1, 0b000_01::5, _nn::2>>, _opts, _ctx), do: raise "0xFD vif 0bE00000nn not supported. Debit of 10^(nn–3) of the nominal local legal currency units." - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :unique_message_identification}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :device_type}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :manufacturer}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :parameter_set_identification}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :model_version}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :hardware_version_number}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :firmware_version_number}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :other_software_version_number}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :customer_location}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :customer}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :access_code_user}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :access_code_operator}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :access_code_system_operator}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :access_code_developer}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :password}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, coding: :type_d, description: :error_flags}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :error_mask}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :security_key}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :digital_output}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :digital_input}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :baud_rate}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :response_delay_time}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, description: :retry}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, description: :remote_control}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :first_storage_number_for_cyclic_storage}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :last_storage_number_for_cyclic_storage}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :size_of_storage_block}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :descriptor_for_tariff_and_device}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, description: :storage_interval, unit: on_time_unit(nn)}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, description: {:storage_interval, :month}}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, description: {:storage_interval, :year}}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, description: :operator_specific_data}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :time_point_second}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: {:duration_size_last_readout, :second}}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: {:duration_size_last_readout, :minute}}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: {:duration_size_last_readout, :hour}}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: {:duration_size_last_readout, :day}}}) + def parse(<<_::1, 0b000_00::5, _nn::2>>, _ctx), do: raise "0xFD vif 0bE00000nn not supported. Credit of 10^(nn–3) of the nominal local legal currency units." + def parse(<<_::1, 0b000_01::5, _nn::2>>, _ctx), do: raise "0xFD vif 0bE00000nn not supported. Debit of 10^(nn–3) of the nominal local legal currency units." + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :unique_message_identification}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :device_type}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :manufacturer}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :parameter_set_identification}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :model_version}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :hardware_version_number}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :firmware_version_number}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :other_software_version_number}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :customer_location}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :customer}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :access_code_user}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :access_code_operator}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :access_code_system_operator}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :access_code_developer}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :password}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, coding: :type_d, description: :error_flags}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :error_mask}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :security_key}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :digital_output}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :digital_input}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :baud_rate}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :response_delay_time}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, description: :retry}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, description: :remote_control}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :first_storage_number_for_cyclic_storage}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :last_storage_number_for_cyclic_storage}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :size_of_storage_block}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :descriptor_for_tariff_and_device}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, description: :storage_interval, unit: on_time_unit(nn)}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, description: {:storage_interval, :month}}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, description: {:storage_interval, :year}}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, description: :operator_specific_data}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :time_point_second}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: {:duration_size_last_readout, :second}}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: {:duration_size_last_readout, :minute}}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: {:duration_size_last_readout, :hour}}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: {:duration_size_last_readout, :day}}}) # ... skipped some vifs ... - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, description: :dimensionless}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, description: {:container, :wmbus}}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :period_of_nominal_data_transmissions, unit: on_time_unit(nn)}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, description: :volts, multiplier: pow10to(nnnn-9), unit: "V"}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, description: :amperes, multiplier: pow10to(nnnn-12), unit: "A"}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, description: :dimensionless}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, description: {:container, :wmbus}}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :period_of_nominal_data_transmissions, unit: on_time_unit(nn)}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, description: :volts, multiplier: pow10to(nnnn-9), unit: "V"}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, description: :amperes, multiplier: pow10to(nnnn-12), unit: "A"}}) # ... skipped some vifs ... - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, description: :reset_counter}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, description: :cumulation_counter}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, description: :reset_counter}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, description: :cumulation_counter}}) # ... skipped some vifs ... - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, description: :rf_level_units_dbm}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, description: :rf_level_units_dbm}}) # ... skipped some vifs ... - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :remaining_battery_life_time_days}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :number_of_times_meter_was_stopped}}) - def parse(<>, opts, ctx), do: Vife.parse(e, rest, opts, %{ctx | vib: %VIB{table: :fd, description: {:container, :manufacturer}}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :remaining_battery_life_time_days}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, coding: fd_remark_k(ctx), description: :number_of_times_meter_was_stopped}}) + def parse(<>, ctx), do: Vife.parse(e, rest, %{ctx | vib: %VIB{table: :fd, description: {:container, :manufacturer}}}) # ... skipped some vifs ... - def parse(<<_::1, vif::7, rest::binary>>, _opts, ctx) do + def parse(<<_::1, vif::7, rest::binary>>, ctx) do raise "decoding from VIF linear extension table 0xFD not implemented. VIFE was: #{Exmbus.Debug.to_hex(vif)} (#{Exmbus.Debug.to_bits(vif)}), ctx was: #{inspect ctx}, rest was: #{inspect rest}" end diff --git a/lib/exmbus/parser/apl/data_record/value_information_block/vif_table_main.ex b/lib/exmbus/parser/apl/data_record/value_information_block/vif_table_main.ex index 1345262..d202e6c 100644 --- a/lib/exmbus/parser/apl/data_record/value_information_block/vif_table_main.ex +++ b/lib/exmbus/parser/apl/data_record/value_information_block/vif_table_main.ex @@ -13,8 +13,7 @@ defmodule Exmbus.Parser.Apl.DataRecord.ValueInformationBlock.VifTableMain do # helper to transition the parser into VIFE parsing. - @compile {:inline, more: 6} - defp more(e, rest, opts, ctx, description, keywords \\ []) do + defp more(e, rest, ctx, description, keywords \\ []) do vib = %VIB{ table: :main, description: description, @@ -24,66 +23,66 @@ defmodule Exmbus.Parser.Apl.DataRecord.ValueInformationBlock.VifTableMain do coding: Keyword.get(keywords, :coding, nil) } - Vife.parse(e, rest, opts, %{ctx | vib: vib}) + Vife.parse(e, rest, %{ctx | vib: vib}) end ### # primary VIF table decoding ### - def parse(<>, opts, ctx), do: more(e, rest, opts, ctx, :energy, multiplier: pow10to(n-3), unit: "Wh") - def parse(<>, opts, ctx), do: more(e, rest, opts, ctx, :energy, multiplier: pow10to(n), unit: "J") - def parse(<>, opts, ctx), do: more(e, rest, opts, ctx, :volume, multiplier: pow10to(n-6), unit: "m^3") - def parse(<>, opts, ctx), do: more(e, rest, opts, ctx, :mass, multiplier: pow10to(n-6), unit: "kg") - def parse(<>, opts, ctx), do: more(e, rest, opts, ctx, :on_time, unit: decode_time_unit(n)) - def parse(<>, opts, ctx), do: more(e, rest, opts, ctx, :operating_time, unit: decode_time_unit(n)) - def parse(<>, opts, ctx), do: more(e, rest, opts, ctx, :power, multiplier: pow10to(n-3), unit: "W") - def parse(<>, opts, ctx), do: more(e, rest, opts, ctx, :power, multiplier: pow10to(n), unit: "J/h") - def parse(<>, opts, ctx), do: more(e, rest, opts, ctx, :volume_flow, multiplier: pow10to(n-6), unit: "m^3/h") - def parse(<>, opts, ctx), do: more(e, rest, opts, ctx, :volume_flow_ext, multiplier: pow10to(n-7), unit: "m^3/min") - def parse(<>, opts, ctx), do: more(e, rest, opts, ctx, :volume_flow_ext, multiplier: pow10to(n-9), unit: "m^3/s") - def parse(<>, opts, ctx), do: more(e, rest, opts, ctx, :mass_flow, multiplier: pow10to(n-3), unit: "kg/h") - def parse(<>, opts, ctx), do: more(e, rest, opts, ctx, :flow_temperature, multiplier: pow10to(n-3), unit: "°C") - def parse(<>, opts, ctx), do: more(e, rest, opts, ctx, :return_temperature, multiplier: pow10to(n-3), unit: "°C") - def parse(<>, opts, ctx), do: more(e, rest, opts, ctx, :temperature_difference, multiplier: pow10to(n-3), unit: "K") - def parse(<>, opts, ctx), do: more(e, rest, opts, ctx, :external_temperature, multiplier: pow10to(n-3), unit: "°C") - def parse(<>, opts, ctx), do: more(e, rest, opts, ctx, :pressure, multiplier: pow10to(n-3), unit: "bar") + def parse(<>, ctx), do: more(e, rest, ctx, :energy, multiplier: pow10to(n-3), unit: "Wh") + def parse(<>, ctx), do: more(e, rest, ctx, :energy, multiplier: pow10to(n), unit: "J") + def parse(<>, ctx), do: more(e, rest, ctx, :volume, multiplier: pow10to(n-6), unit: "m^3") + def parse(<>, ctx), do: more(e, rest, ctx, :mass, multiplier: pow10to(n-6), unit: "kg") + def parse(<>, ctx), do: more(e, rest, ctx, :on_time, unit: decode_time_unit(n)) + def parse(<>, ctx), do: more(e, rest, ctx, :operating_time, unit: decode_time_unit(n)) + def parse(<>, ctx), do: more(e, rest, ctx, :power, multiplier: pow10to(n-3), unit: "W") + def parse(<>, ctx), do: more(e, rest, ctx, :power, multiplier: pow10to(n), unit: "J/h") + def parse(<>, ctx), do: more(e, rest, ctx, :volume_flow, multiplier: pow10to(n-6), unit: "m^3/h") + def parse(<>, ctx), do: more(e, rest, ctx, :volume_flow_ext, multiplier: pow10to(n-7), unit: "m^3/min") + def parse(<>, ctx), do: more(e, rest, ctx, :volume_flow_ext, multiplier: pow10to(n-9), unit: "m^3/s") + def parse(<>, ctx), do: more(e, rest, ctx, :mass_flow, multiplier: pow10to(n-3), unit: "kg/h") + def parse(<>, ctx), do: more(e, rest, ctx, :flow_temperature, multiplier: pow10to(n-3), unit: "°C") + def parse(<>, ctx), do: more(e, rest, ctx, :return_temperature, multiplier: pow10to(n-3), unit: "°C") + def parse(<>, ctx), do: more(e, rest, ctx, :temperature_difference, multiplier: pow10to(n-3), unit: "K") + def parse(<>, ctx), do: more(e, rest, ctx, :external_temperature, multiplier: pow10to(n-3), unit: "°C") + def parse(<>, ctx), do: more(e, rest, ctx, :pressure, multiplier: pow10to(n-3), unit: "bar") # TYPE: Date and Time # - Data field 0b0010, type G # - Data field 0b0011, type J # - Data field 0b0100, type F # - Data field 0b0110, type I # - Data field 0b1101, type M (LVAR) - def parse(<>, opts, %{dib: %DIB{data_type: :int_or_bin, size: 16}}=ctx), do: more(e, rest, opts, ctx, :date, coding: :type_g) - def parse(<>, _pts, %{dib: %DIB{data_type: _, size: _} }=ctx), do: Vife.error(e, rest, {:invalid, "data field must be 0b0010 from Table 10 in EN 13757-3:2018 \"Meaning depends on data field. Other data fields shall be handled as invalid\""}, ctx) - def parse(<>, opts, %{dib: %DIB{data_type: :int_or_bin, size: 24}}=ctx), do: more(e, rest, opts, ctx, :time, coding: :type_j) - def parse(<>, opts, %{dib: %DIB{data_type: :int_or_bin, size: 32}}=ctx), do: more(e, rest, opts, ctx, :naive_datetime, coding: :type_f) - def parse(<>, opts, %{dib: %DIB{data_type: :int_or_bin, size: 48}}=ctx), do: more(e, rest, opts, ctx, :naive_datetime, coding: :type_i) - def parse(<>, opts, %{dib: %DIB{data_type: :variable_length }}=ctx), do: more(e, rest, opts, ctx, :datetime, coding: :type_m) + def parse(<>, %{dib: %DIB{data_type: :int_or_bin, size: 16}}=ctx), do: more(e, rest, ctx, :date, coding: :type_g) + def parse(<>, %{dib: %DIB{data_type: _, size: _} }=ctx), do: Vife.error(e, rest, {:invalid, "data field must be 0b0010 from Table 10 in EN 13757-3:2018 \"Meaning depends on data field. Other data fields shall be handled as invalid\""}, ctx) + def parse(<>, %{dib: %DIB{data_type: :int_or_bin, size: 24}}=ctx), do: more(e, rest, ctx, :time, coding: :type_j) + def parse(<>, %{dib: %DIB{data_type: :int_or_bin, size: 32}}=ctx), do: more(e, rest, ctx, :naive_datetime, coding: :type_f) + def parse(<>, %{dib: %DIB{data_type: :int_or_bin, size: 48}}=ctx), do: more(e, rest, ctx, :naive_datetime, coding: :type_i) + def parse(<>, %{dib: %DIB{data_type: :variable_length }}=ctx), do: more(e, rest, ctx, :datetime, coding: :type_m) # Rest after date and time - def parse(<>, opts, ctx), do: more(e, rest, opts, ctx, :units_for_hca) - def parse(<>, _opts, ctx), do: Vife.error(e, rest, {:reserved, "VIF 0b1101111 reserved for future use"}, ctx) - def parse(<>, opts, ctx), do: more(e, rest, opts, ctx, :averaging_duration, unit: decode_time_unit(nn)) - def parse(<>, opts, ctx), do: more(e, rest, opts, ctx, :actuality_duration, unit: decode_time_unit(nn)) - def parse(<>, opts, ctx), do: more(e, rest, opts, ctx, :fabrication_no) - def parse(<>, opts, ctx), do: more(e, rest, opts, ctx, :enhanced_identification) - def parse(<>, opts, ctx), do: more(e, rest, opts, ctx, :address) + def parse(<>, ctx), do: more(e, rest, ctx, :units_for_hca) + def parse(<>, ctx), do: Vife.error(e, rest, {:reserved, "VIF 0b1101111 reserved for future use"}, ctx) + def parse(<>, ctx), do: more(e, rest, ctx, :averaging_duration, unit: decode_time_unit(nn)) + def parse(<>, ctx), do: more(e, rest, ctx, :actuality_duration, unit: decode_time_unit(nn)) + def parse(<>, ctx), do: more(e, rest, ctx, :fabrication_no) + def parse(<>, ctx), do: more(e, rest, ctx, :enhanced_identification) + def parse(<>, ctx), do: more(e, rest, ctx, :address) # plain-text VIF: # See EN 13757-3:2018(EN) - C.2 # - def parse(<>, opts, ctx) do + def parse(<>, ctx) do # first we need to parse all of the extensions as well. # we pass in a description set to a marker we can match on it's way out of the vifes/4 again # to make sure it hasn't changed. - case more(e, rest, opts, ctx, :plain_text_unit) do + case more(e, rest, ctx, :plain_text_unit) do # the length in bytes and the ascii unit itself is found after the VIB # so we now need to read the unit out from the rest of the data. # First we get the length in the first byte: {:ok, %VIB{description: :plain_text_unit}=vib, <>} -> # then we match that number of bytes: <> = rest - # The right-most character is transmittet first, so we need to reverse the + # The right-most character is transmitted first, so we need to reverse the # ascii string to get proper text ascii_vif = rev_ascii_vif @@ -94,9 +93,9 @@ defmodule Exmbus.Parser.Apl.DataRecord.ValueInformationBlock.VifTableMain do end end - def parse(<>, _opts, ctx), do: Vife.error(e, rest, "Any VIF 0x7E / 0xFE not implemented. See 6.4.1 list item d.", ctx) + def parse(<>, ctx), do: Vife.error(e, rest, "Any VIF 0x7E / 0xFE not implemented. See 6.4.1 list item d.", ctx) - def parse(<>, _opts, _ctx) do + def parse(<>, _ctx) do # Manufacturer specific encoding, 7F / FF. # Rest of data-record (including VIFEs) are manufacturer specific. {:ok, vifes, rest} = @@ -113,9 +112,9 @@ defmodule Exmbus.Parser.Apl.DataRecord.ValueInformationBlock.VifTableMain do }, rest} end - def parse(<<0b1111_1011, rest::binary>>, opts, ctx), do: FB.parse(rest, opts, ctx) - def parse(<<0b1111_1101, rest::binary>>, opts, ctx), do: FD.parse(rest, opts, ctx) - def parse(<<0b1110_1111, _rest::binary>>, _opts, _ctx), do: raise "VIF 0xEF reserved for future use." + def parse(<<0b1111_1011, rest::binary>>, ctx), do: FB.parse(rest, ctx) + def parse(<<0b1111_1101, rest::binary>>, ctx), do: FD.parse(rest, ctx) + def parse(<<0b1110_1111, _rest::binary>>, _ctx), do: raise "VIF 0xEF reserved for future use." @@ -125,40 +124,40 @@ defmodule Exmbus.Parser.Apl.DataRecord.ValueInformationBlock.VifTableMain do TODO: implement unparsing VIBs with extensions """ - def unparse(opts, %VIB{table: :main} = vib) do + def unparse(%VIB{table: :main} = vib) do # _unparse for now just parses no-extensions VIBs from the main table - _unparse(opts, vib) + _unparse(vib) end - defp _unparse(_opts, %VIB{extensions: [], description: :energy, multiplier: m, unit: "Wh"}), do: {:ok, <<0::1, 0b0000::4, (log10int(m)+3)::3>>} - defp _unparse(_opts, %VIB{extensions: [], description: :energy, multiplier: m, unit: "J"}), do: {:ok, <<0::1, 0b0001::4, (log10int(m)+0)::3>>} - defp _unparse(_opts, %VIB{extensions: [], description: :volume, multiplier: m, unit: "m^3"}), do: {:ok, <<0::1, 0b0010::4, (log10int(m)+6)::3>>} - defp _unparse(_opts, %VIB{extensions: [], description: :mass, multiplier: m, unit: "kg"}), do: {:ok, <<0::1, 0b0011::4, (log10int(m)+6)::3>>} - defp _unparse(_opts, %VIB{extensions: [], description: :on_time, unit: u}), do: {:ok, <<0::1, 0b01000::5, (encode_time_unit(u))::2>>} - defp _unparse(_opts, %VIB{extensions: [], description: :operating_time, unit: u}), do: {:ok, <<0::1, 0b01001::5, (encode_time_unit(u))::2>>} - defp _unparse(_opts, %VIB{extensions: [], description: :power, multiplier: m, unit: "W"}), do: {:ok, <<0::1, 0b0101::4, (log10int(m)+3)::3>>} - defp _unparse(_opts, %VIB{extensions: [], description: :power, multiplier: m, unit: "J/h"}), do: {:ok, <<0::1, 0b0110::4, (log10int(m)+0)::3>>} - defp _unparse(_opts, %VIB{extensions: [], description: :volume_flow, multiplier: m, unit: "m^3/h"}), do: {:ok, <<0::1, 0b0111::4, (log10int(m)+6)::3>>} - defp _unparse(_opts, %VIB{extensions: [], description: :volume_flow_ext, multiplier: m, unit: "m^3/min"}), do: {:ok, <<0::1, 0b1000::4, (log10int(m)+7)::3>>} - defp _unparse(_opts, %VIB{extensions: [], description: :volume_flow_ext, multiplier: m, unit: "m^3/s"}), do: {:ok, <<0::1, 0b1001::4, (log10int(m)+9)::3>>} - defp _unparse(_opts, %VIB{extensions: [], description: :mass_flow, multiplier: m, unit: "kg/h"}), do: {:ok, <<0::1, 0b1010::4, (log10int(m)+3)::3>>} - defp _unparse(_opts, %VIB{extensions: [], description: :flow_temperature, multiplier: m, unit: "°C"}), do: {:ok, <<0::1, 0b10110::5, (log10int(m)+3)::2>>} - defp _unparse(_opts, %VIB{extensions: [], description: :return_temperature, multiplier: m, unit: "°C"}), do: {:ok, <<0::1, 0b10111::5, (log10int(m)+3)::2>>} - defp _unparse(_opts, %VIB{extensions: [], description: :temperature_difference, multiplier: m, unit: "K"}), do: {:ok, <<0::1, 0b11000::5, (log10int(m)+3)::2>>} - defp _unparse(_opts, %VIB{extensions: [], description: :external_temperature, multiplier: m, unit: "°C"}), do: {:ok, <<0::1, 0b11001::5, (log10int(m)+3)::2>>} - defp _unparse(_opts, %VIB{extensions: [], description: :pressure, multiplier: m, unit: "bar"}), do: {:ok, <<0::1, 0b11010::5, (log10int(m)+3)::2>>} - defp _unparse(_opts, %VIB{extensions: [], description: :date, coding: :type_g}), do: {:ok, <<0::1, 0b1101100::7>>} - defp _unparse(_opts, %VIB{extensions: [], description: :time, coding: :type_j}), do: {:ok, <<0::1, 0b1101101::7>>} - defp _unparse(_opts, %VIB{extensions: [], description: :naive_datetime, coding: :type_f}), do: {:ok, <<0::1, 0b1101101::7>>} - defp _unparse(_opts, %VIB{extensions: [], description: :naive_datetime, coding: :type_i}), do: {:ok, <<0::1, 0b1101101::7>>} - defp _unparse(_opts, %VIB{extensions: [], description: :datetime, coding: :type_m}), do: {:ok, <<0::1, 0b1101101::7>>} - defp _unparse(_opts, %VIB{extensions: [], description: :units_for_hca}), do: {:ok, <<0::1, 0b1101110::7>>} - defp _unparse(_opts, %VIB{extensions: [], description: :averaging_duration, unit: u}), do: {:ok, <<0::1, 0b11100::5, (encode_time_unit(u))::2>>} - defp _unparse(_opts, %VIB{extensions: [], description: :actuality_duration, unit: u}), do: {:ok, <<0::1, 0b11101::5, (encode_time_unit(u))::2>>} - defp _unparse(_opts, %VIB{extensions: [], description: :fabrication_no}), do: {:ok, <<0::1, 0b1111000::7>>} - defp _unparse(_opts, %VIB{extensions: [], description: :enhanced_identification}), do: {:ok, <<0::1, 0b1111001::7>>} - defp _unparse(_opts, %VIB{extensions: [], description: :address}), do: {:ok, <<0::1, 0b1111010::7>>} - - defp _unparse(_opts, %VIB{extensions: es, description: :manufacturer_specific_encoding}) do + defp _unparse(%VIB{extensions: [], description: :energy, multiplier: m, unit: "Wh"}), do: {:ok, <<0::1, 0b0000::4, (log10int(m)+3)::3>>} + defp _unparse(%VIB{extensions: [], description: :energy, multiplier: m, unit: "J"}), do: {:ok, <<0::1, 0b0001::4, (log10int(m)+0)::3>>} + defp _unparse(%VIB{extensions: [], description: :volume, multiplier: m, unit: "m^3"}), do: {:ok, <<0::1, 0b0010::4, (log10int(m)+6)::3>>} + defp _unparse(%VIB{extensions: [], description: :mass, multiplier: m, unit: "kg"}), do: {:ok, <<0::1, 0b0011::4, (log10int(m)+6)::3>>} + defp _unparse(%VIB{extensions: [], description: :on_time, unit: u}), do: {:ok, <<0::1, 0b01000::5, (encode_time_unit(u))::2>>} + defp _unparse(%VIB{extensions: [], description: :operating_time, unit: u}), do: {:ok, <<0::1, 0b01001::5, (encode_time_unit(u))::2>>} + defp _unparse(%VIB{extensions: [], description: :power, multiplier: m, unit: "W"}), do: {:ok, <<0::1, 0b0101::4, (log10int(m)+3)::3>>} + defp _unparse(%VIB{extensions: [], description: :power, multiplier: m, unit: "J/h"}), do: {:ok, <<0::1, 0b0110::4, (log10int(m)+0)::3>>} + defp _unparse(%VIB{extensions: [], description: :volume_flow, multiplier: m, unit: "m^3/h"}), do: {:ok, <<0::1, 0b0111::4, (log10int(m)+6)::3>>} + defp _unparse(%VIB{extensions: [], description: :volume_flow_ext, multiplier: m, unit: "m^3/min"}), do: {:ok, <<0::1, 0b1000::4, (log10int(m)+7)::3>>} + defp _unparse(%VIB{extensions: [], description: :volume_flow_ext, multiplier: m, unit: "m^3/s"}), do: {:ok, <<0::1, 0b1001::4, (log10int(m)+9)::3>>} + defp _unparse(%VIB{extensions: [], description: :mass_flow, multiplier: m, unit: "kg/h"}), do: {:ok, <<0::1, 0b1010::4, (log10int(m)+3)::3>>} + defp _unparse(%VIB{extensions: [], description: :flow_temperature, multiplier: m, unit: "°C"}), do: {:ok, <<0::1, 0b10110::5, (log10int(m)+3)::2>>} + defp _unparse(%VIB{extensions: [], description: :return_temperature, multiplier: m, unit: "°C"}), do: {:ok, <<0::1, 0b10111::5, (log10int(m)+3)::2>>} + defp _unparse(%VIB{extensions: [], description: :temperature_difference, multiplier: m, unit: "K"}), do: {:ok, <<0::1, 0b11000::5, (log10int(m)+3)::2>>} + defp _unparse(%VIB{extensions: [], description: :external_temperature, multiplier: m, unit: "°C"}), do: {:ok, <<0::1, 0b11001::5, (log10int(m)+3)::2>>} + defp _unparse(%VIB{extensions: [], description: :pressure, multiplier: m, unit: "bar"}), do: {:ok, <<0::1, 0b11010::5, (log10int(m)+3)::2>>} + defp _unparse(%VIB{extensions: [], description: :date, coding: :type_g}), do: {:ok, <<0::1, 0b1101100::7>>} + defp _unparse(%VIB{extensions: [], description: :time, coding: :type_j}), do: {:ok, <<0::1, 0b1101101::7>>} + defp _unparse(%VIB{extensions: [], description: :naive_datetime, coding: :type_f}), do: {:ok, <<0::1, 0b1101101::7>>} + defp _unparse(%VIB{extensions: [], description: :naive_datetime, coding: :type_i}), do: {:ok, <<0::1, 0b1101101::7>>} + defp _unparse(%VIB{extensions: [], description: :datetime, coding: :type_m}), do: {:ok, <<0::1, 0b1101101::7>>} + defp _unparse(%VIB{extensions: [], description: :units_for_hca}), do: {:ok, <<0::1, 0b1101110::7>>} + defp _unparse(%VIB{extensions: [], description: :averaging_duration, unit: u}), do: {:ok, <<0::1, 0b11100::5, (encode_time_unit(u))::2>>} + defp _unparse(%VIB{extensions: [], description: :actuality_duration, unit: u}), do: {:ok, <<0::1, 0b11101::5, (encode_time_unit(u))::2>>} + defp _unparse(%VIB{extensions: [], description: :fabrication_no}), do: {:ok, <<0::1, 0b1111000::7>>} + defp _unparse(%VIB{extensions: [], description: :enhanced_identification}), do: {:ok, <<0::1, 0b1111001::7>>} + defp _unparse(%VIB{extensions: [], description: :address}), do: {:ok, <<0::1, 0b1111010::7>>} + + defp _unparse(%VIB{extensions: es, description: :manufacturer_specific_encoding}) do vife_bytes = es |> Enum.map(fn({:manufacturer_specific_vife, vife}) -> <> end) diff --git a/lib/exmbus/parser/apl/data_record/value_information_block/vife.ex b/lib/exmbus/parser/apl/data_record/value_information_block/vife.ex index 85b14cd..548502a 100644 --- a/lib/exmbus/parser/apl/data_record/value_information_block/vife.ex +++ b/lib/exmbus/parser/apl/data_record/value_information_block/vife.ex @@ -41,7 +41,6 @@ defmodule Exmbus.Parser.Apl.DataRecord.ValueInformationBlock.Vife do def parse( 1, <>, - opts, %{vib: %VIB{table: :main, extensions: exts} = vib} = ctx ) do case direction_from_ctx(ctx) do @@ -49,25 +48,25 @@ defmodule Exmbus.Parser.Apl.DataRecord.ValueInformationBlock.Vife do case ErrorCode.decode(xxxx) do {:ok, record_error} -> vib = %VIB{vib | extensions: [{:record_error, record_error} | exts]} - parse(e, rest, opts, %{ctx | vib: vib}) + parse(e, rest, %{ctx | vib: vib}) # for now we just pass the reserved numbers through. # if they are being used it is most likely because we have not implemented them. # I've already seen 0b0_1000 in use in the real world. {:error, {:reserved, _} = r} -> vib = %VIB{vib | extensions: [{:record_error, r} | exts]} - parse(e, rest, opts, %{ctx | vib: vib}) + parse(e, rest, %{ctx | vib: vib}) end end end - def parse(1, rest, opts, %{vib: %VIB{extensions: exts} = vib} = ctx) do - case exts(1, rest, opts, exts) do - {:ok, rest, exts} -> parse(0, rest, opts, %{ctx | vib: %VIB{vib | extensions: exts}}) + def parse(1, rest, %{vib: %VIB{extensions: exts} = vib} = ctx) do + case exts(1, rest, exts) do + {:ok, rest, exts} -> parse(0, rest, %{ctx | vib: %VIB{vib | extensions: exts}}) end end - def parse(0, rest, _opts, ctx) do + def parse(0, rest, ctx) do # when no more extensions, return the vib (which we used as an accumulator so far) {:ok, ctx.vib, rest} end @@ -83,190 +82,190 @@ defmodule Exmbus.Parser.Apl.DataRecord.ValueInformationBlock.Vife do defp direction_from_ctx(%{}), do: {:error, :no_direction} # Table 15 — Combinable (orthogonal) VIFE-table - defp exts(0, rest, _opts, acc) do + defp exts(0, rest, acc) do {:ok, rest, Enum.reverse(acc)} end - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [:average_value | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [:average_value | acc]) # EN 13757-3:2018 table 15 - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [{:compact_profile, :inverse} | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [{:compact_profile, :inverse} | acc]) # EN 13757-3:2018 table 15 - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [:standard_conform | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [:standard_conform | acc]) # EN 13757-3:2018 table 15 - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [:standard_conform | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [:standard_conform | acc]) # EN 13757-3:2018 table 15 - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [{:compact_profile, :register_numbers} | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [{:compact_profile, :register_numbers} | acc]) # EN 13757-3:2018 table 15 - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [{:compact_profile, :compact_profile} | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [{:compact_profile, :compact_profile} | acc]) - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [{:per, :interval, :second} | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [{:per, :interval, :second} | acc]) - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [{:per, :interval, :minute} | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [{:per, :interval, :minute} | acc]) - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [{:per, :interval, :hour} | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [{:per, :interval, :hour} | acc]) - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [{:per, :interval, :day} | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [{:per, :interval, :day} | acc]) - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [{:per, :interval, :week} | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [{:per, :interval, :week} | acc]) - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [{:per, :interval, :month} | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [{:per, :interval, :month} | acc]) - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [{:per, :interval, :year} | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [{:per, :interval, :year} | acc]) - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [{:per, :misc, :revolution_or_measurement} | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [{:per, :misc, :revolution_or_measurement} | acc]) - defp exts(1, <>, opts, acc) do + defp exts(1, <>, acc) do # Increment per input pulse on input channel number p - exts(e, rest, opts, [{:per, :input_pulse, {:channel_number, p}} | acc]) + exts(e, rest, [{:per, :input_pulse, {:channel_number, p}} | acc]) end - defp exts(1, <>, opts, acc) do + defp exts(1, <>, acc) do # Increment per output pulse on output channel number p - exts(e, rest, opts, [{:per, :output_pulse, {:channel_number, p}} | acc]) + exts(e, rest, [{:per, :output_pulse, {:channel_number, p}} | acc]) end - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [{:per, :unit, "l"} | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [{:per, :unit, "l"} | acc]) - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [{:per, :unit, "m3"} | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [{:per, :unit, "m3"} | acc]) - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [{:per, :unit, "kg"} | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [{:per, :unit, "kg"} | acc]) - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [{:per, :unit, "K"} | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [{:per, :unit, "K"} | acc]) - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [{:per, :unit, "kWh"} | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [{:per, :unit, "kWh"} | acc]) - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [{:per, :unit, "GJ"} | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [{:per, :unit, "GJ"} | acc]) - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [{:per, :unit, "kW"} | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [{:per, :unit, "kW"} | acc]) - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [{:per, :unit, "Kl"} | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [{:per, :unit, "Kl"} | acc]) - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [{:per, :unit, "V"} | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [{:per, :unit, "V"} | acc]) - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [{:per, :unit, "A"} | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [{:per, :unit, "A"} | acc]) - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [{:multiplied_by, "s"} | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [{:multiplied_by, "s"} | acc]) - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [{:multiplied_by, "(s/V)"} | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [{:multiplied_by, "(s/V)"} | acc]) - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [{:multiplied_by, "(s/A)"} | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [{:multiplied_by, "(s/A)"} | acc]) - defp exts(1, <<_::1, 0b0111001::7, _rest::binary>>, _opts, _acc), + defp exts(1, <<_::1, 0b0111001::7, _rest::binary>>, _acc), do: raise("E011 1001 'Start date(/time) of' not supported") - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [:vif_contains_uncorrected_unit_or_value | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [:vif_contains_uncorrected_unit_or_value | acc]) - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [{:accumulation_only, :forward_flow} | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [{:accumulation_only, :forward_flow} | acc]) - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [{:accumulation_only, :backward_flow} | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [{:accumulation_only, :backward_flow} | acc]) - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [:non_metric | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [:non_metric | acc]) - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [:value_at_base_condition | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [:value_at_base_condition | acc]) - defp exts(1, <<_::1, 0b0111111::7, _rest::binary>>, _opts, _acc), + defp exts(1, <<_::1, 0b0111111::7, _rest::binary>>, _acc), do: raise("E011 1111 OBIS-declaration not supported") - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [{:limit_value, :lower} | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [{:limit_value, :lower} | acc]) - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [{:limit_value, :upper} | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [{:limit_value, :upper} | acc]) - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [{:number_of_exceeds_of_limit_value, :lower} | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [{:number_of_exceeds_of_limit_value, :lower} | acc]) - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [{:number_of_exceeds_of_limit_value, :upper} | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [{:number_of_exceeds_of_limit_value, :upper} | acc]) - defp exts(1, <>, opts, acc) do + defp exts(1, <>, acc) do # Date (/time) of: b = 0: begin, b = 1: end of, f = 0: first, f= 1: last, u = 0: lower, u = 1: upper limit exceeded begin_end = if b == 0, do: :begin, else: :end first_last = if f == 0, do: :first, else: :last upper_lower = if u == 0, do: :lower, else: :upper extension = {:limit_exceeded, upper_lower, first_last, begin_end} - exts(e, rest, opts, [extension | acc]) + exts(e, rest, [extension | acc]) end - defp exts(1, <<_::1, 0b101::3, _u::1, _f::1, _nn::2, _rest::binary>>, _opts, _acc), + defp exts(1, <<_::1, 0b101::3, _u::1, _f::1, _nn::2, _rest::binary>>, _acc), do: raise("E101 ufnn Duration of limit exceed not supported") - defp exts(1, <<_::1, 0b1100::4, _f::1, _nn::2, _rest::binary>>, _opts, _acc), + defp exts(1, <<_::1, 0b1100::4, _f::1, _nn::2, _rest::binary>>, _acc), do: raise("E110 0fnn Duration of d not supported") - defp exts(1, <<_::1, 0b1101::4, _u::1, 00::2, _rest::binary>>, _opts, _acc), + defp exts(1, <<_::1, 0b1101::4, _u::1, 00::2, _rest::binary>>, _acc), do: raise("E110 1u00 Value during lower (u = 0), upper (u = 1) limit exceed not supported") - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [:leakage_values | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [:leakage_values | acc]) - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [:overflow_values | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [:overflow_values | acc]) - defp exts(1, <<_::1, 0b110_1::4, _u::1, 00::2, _rest::binary>>, _opts, _acc), + defp exts(1, <<_::1, 0b110_1::4, _u::1, 00::2, _rest::binary>>, _acc), do: raise("E110 1f1b 'Date (/time) of' not supported") - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [{:multiplicative_correction_factor, pow10to(nnn - 6)} | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [{:multiplicative_correction_factor, pow10to(nnn - 6)} | acc]) - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [{:additive_correction_constant, pow10to(nn - 3)} | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [{:additive_correction_constant, pow10to(nn - 3)} | acc]) - defp exts(1, <<_::1, 0b111_1100::7, _rest::binary>>, _opts, _acc), + defp exts(1, <<_::1, 0b111_1100::7, _rest::binary>>, _acc), do: raise("E111 1100 Extension of combinable (orthogonal) VIFE-Code not supported") - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [{:multiplicative_correction_factor, 103} | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [{:multiplicative_correction_factor, 103} | acc]) - defp exts(1, <>, opts, acc), - do: exts(e, rest, opts, [:future_value | acc]) + defp exts(1, <>, acc), + do: exts(e, rest, [:future_value | acc]) - defp exts(1, <>, opts, acc), - do: exts_manufacturer_specific(e, rest, opts, acc) + defp exts(1, <>, acc), + do: exts_manufacturer_specific(e, rest, acc) - defp exts_manufacturer_specific(0, rest, opts, acc) do - exts(0, rest, opts, acc) + defp exts_manufacturer_specific(0, rest, acc) do + exts(0, rest, acc) end - defp exts_manufacturer_specific(1, <>, opts, acc) do - exts_manufacturer_specific(e, rest, opts, [{:manufacturer_specific_vife, vife} | acc]) + defp exts_manufacturer_specific(1, <>, acc) do + exts_manufacturer_specific(e, rest, [{:manufacturer_specific_vife, vife} | acc]) end defp pow10to(power) do diff --git a/lib/exmbus/parser/apl/format_frame.ex b/lib/exmbus/parser/apl/format_frame.ex index 126fcaf..20c3fcd 100644 --- a/lib/exmbus/parser/apl/format_frame.ex +++ b/lib/exmbus/parser/apl/format_frame.ex @@ -20,7 +20,7 @@ defmodule Exmbus.Parser.Apl.FormatFrame do end defp _parse_format_frame(ff_header, bin, ctx, acc) do - case DataRecord.Header.parse(bin, ctx.opts, ctx) do + case DataRecord.Header.parse(bin, ctx) do {:ok, header, rest} -> _parse_format_frame(ff_header, rest, ctx, [header | acc]) @@ -88,7 +88,7 @@ defmodule Exmbus.Parser.Apl.FormatFrame do # otherwise we need to try and unparse the headers %DataRecord.Header{dib_bytes: d, vib_bytes: v} = header when is_nil(d) or is_nil(v) -> - {:ok, header_bin} = DataRecord.Header.unparse(%{}, header) + {:ok, header_bin} = DataRecord.Header.unparse(header) header_bin end) |> Enum.into("") diff --git a/lib/exmbus/parser/apl/full_frame.ex b/lib/exmbus/parser/apl/full_frame.ex index 673b712..1eca412 100644 --- a/lib/exmbus/parser/apl/full_frame.ex +++ b/lib/exmbus/parser/apl/full_frame.ex @@ -14,42 +14,42 @@ defmodule Exmbus.Parser.Apl.FullFrame do manufacturer_bytes: nil def parse(%Context{} = ctx) do - parse_full_frame(ctx, []) + parse_full_frame(ctx.bin, ctx, []) end - defp parse_full_frame(%{bin: <<>>} = ctx, acc) do - finalize_full_frame(ctx, acc) + defp parse_full_frame(<<>>, ctx, acc) do + finalize_full_frame(<<>>, ctx, acc) end - defp parse_full_frame(ctx, acc) do - case DataRecord.parse(ctx.bin, ctx.opts, ctx) do + defp parse_full_frame(bin, ctx, acc) do + case DataRecord.parse(bin, ctx) do {:ok, %DataRecord{} = data_record, rest} -> - parse_full_frame(%{ctx | bin: rest}, [data_record | acc]) + parse_full_frame(rest, ctx, [data_record | acc]) {:ok, %InvalidDataRecord{} = data_record, rest} -> - parse_full_frame(%{ctx | bin: rest}, [data_record | acc]) + parse_full_frame(rest, ctx, [data_record | acc]) # just skip the idle filler {:special_function, :idle_filler, rest} -> - parse_full_frame(%{ctx | bin: rest}, acc) + parse_full_frame(rest, ctx, acc) # manufacturer specific data is the rest of the APL data {:special_function, {:manufacturer_specific, :to_end}, rest} -> - finalize_full_frame(%{ctx | bin: rest}, acc) + finalize_full_frame(rest, ctx, acc) {:special_function, {:manufacturer_specific, :more_records_follow}, rest} -> - finalize_full_frame(%{ctx | bin: rest}, acc) + finalize_full_frame(rest, ctx, acc) {:error, _reason, _rest} = e -> e end end - defp finalize_full_frame(%{} = ctx, acc) do + defp finalize_full_frame(rest, %{} = ctx, acc) do full_frame = %__MODULE__{ records: Enum.reverse(acc), # all remaining bytes are manufacturer specific: - manufacturer_bytes: ctx.bin + manufacturer_bytes: rest } {:next, %{ctx | bin: <<>>, apl: full_frame}} @@ -65,7 +65,7 @@ defmodule Exmbus.Parser.Apl.FullFrame do record_bytes = records |> Enum.map(fn record -> - {:ok, bytes} = DataRecord.unparse(%{}, record) + {:ok, bytes} = DataRecord.unparse(record) bytes end) |> Enum.into("") diff --git a/test/parser/apl/data_record/data_information_block_test.exs b/test/parser/apl/data_record/data_information_block_test.exs index 94668c5..c2e72e3 100644 --- a/test/parser/apl/data_record/data_information_block_test.exs +++ b/test/parser/apl/data_record/data_information_block_test.exs @@ -17,7 +17,7 @@ defmodule Parser.Apl.DataRecord.DataInformationBlockTest do bin = unquote(dib_bytes) assert {:error, {:reserved_special_function, f}, <<>>} = - DIB.parse(bin, %{}, Context.new()) + DIB.parse(bin, Context.new()) assert is_integer(f) end @@ -26,15 +26,15 @@ defmodule Parser.Apl.DataRecord.DataInformationBlockTest do <> = dib_bytes -> test "special function: #{special}" do bin = unquote(dib_bytes) - assert {:special_function, _, <<>>} = DIB.parse(bin, %{}, Context.new()) + assert {:special_function, _, <<>>} = DIB.parse(bin, Context.new()) end # test non-extended dib <<0::1, storage::1, ff::2, df::4>> = dib_bytes -> test "non-extended dib parse/unparse storage=#{storage} function_field=#{ff} data_field=#{df}" do bin = unquote(dib_bytes) - assert {:ok, dib, <<>>} = DIB.parse(bin, %{}, Context.new()) - assert {:ok, ^bin} = DIB.unparse(%{}, dib) + assert {:ok, dib, <<>>} = DIB.parse(bin, Context.new()) + assert {:ok, ^bin} = DIB.unparse(dib) end end end diff --git a/test/parser/apl/data_record/data_record_header_test.exs b/test/parser/apl/data_record/data_record_header_test.exs index ddec23f..a5f7002 100644 --- a/test/parser/apl/data_record/data_record_header_test.exs +++ b/test/parser/apl/data_record/data_record_header_test.exs @@ -12,7 +12,7 @@ defmodule Parser.Apl.DataRecord.HeaderTest do test "parse/unparse header mismatch 2022-01-14" do # unparsing this yielded 01FA21 which ofc is wrong, it should be same as input orignal_drh = "01FF21" |> Base.decode16!() - {:ok, %Header{} = header, ""} = Header.parse(orignal_drh, %{}, Context.new()) + {:ok, %Header{} = header, ""} = Header.parse(orignal_drh, Context.new()) assert %Header{ coding: :type_b, @@ -38,7 +38,7 @@ defmodule Parser.Apl.DataRecord.HeaderTest do # be sure we don't "cheat" :) header = Map.drop(header, [:dib_bytes, :vib_bytes]) - assert {:ok, <<0x01, 0xFF, 0x21>>} = Header.unparse(%{}, header) + assert {:ok, <<0x01, 0xFF, 0x21>>} = Header.unparse(header) end end end diff --git a/test/parser/apl/data_record/data_record_test.exs b/test/parser/apl/data_record/data_record_test.exs index 7843581..dda91e8 100644 --- a/test/parser/apl/data_record/data_record_test.exs +++ b/test/parser/apl/data_record/data_record_test.exs @@ -14,7 +14,6 @@ defmodule Parser.Apl.DataRecord.DataRecordTest do {:ok, record, <<0xFF, 0xFF>>} = DataRecord.parse( <<0x02, 0xFD, 0x17, 0b00000100, 0b10000000, 0xFF, 0xFF>>, - %{}, Context.new() ) @@ -75,7 +74,7 @@ defmodule Parser.Apl.DataRecord.DataRecordTest do 0x75 >> - {:ok, data_record, ""} = DataRecord.parse(data_record_bytes, %{}, Context.new()) + {:ok, data_record, ""} = DataRecord.parse(data_record_bytes, Context.new()) assert %DataRecord{ data: 75_420_826, diff --git a/test/parser/apl/data_record/value_information_block_test.exs b/test/parser/apl/data_record/value_information_block_test.exs index 18634ce..68a8728 100644 --- a/test/parser/apl/data_record/value_information_block_test.exs +++ b/test/parser/apl/data_record/value_information_block_test.exs @@ -12,7 +12,7 @@ defmodule Parser.Apl.DataRecord.ValueInformationBlockTest do <<0::1, 0b1101111::7>> = vib_bytes -> test "reserved: #{i}" do bin = unquote(vib_bytes) - assert {:error, {:reserved, _}, <<>>} = VIB.parse(bin, %{}, []) + assert {:error, {:reserved, _}, <<>>} = VIB.parse(bin, []) end <<_::8>> = vib_bytes -> @@ -28,8 +28,8 @@ defmodule Parser.Apl.DataRecord.ValueInformationBlockTest do %DIB{data_type: :int_or_bin, size: 32} end - assert {:ok, vib, <<>>} = VIB.parse(bin, %{}, Context.new(dib: dib)) - assert {:ok, ^bin} = VIB.unparse(%{}, vib) + assert {:ok, vib, <<>>} = VIB.parse(bin, Context.new(dib: dib)) + assert {:ok, ^bin} = VIB.unparse(vib) end end end