GS1.Utils (gs1_barcode v0.1.2)

View Source

Utility functions for:

  • GLN validation
  • Converting AI data with implied decimal points into floats.
  • Converting between GS1 20-digit location strings and WGS84 lat/long coordinates and vice versa.

Summary

Functions

Extracts ISO currency code and amount value from ISO AI data string containing an ISO currency code prefix followed by an amount with an implied decimal point into structured data.

Converts a AIs (like "310x", "320x", etc.) data string, which may contain an implied decimal point to float.

Converts a 20-char data string (e.g., AI "8200") to WGS84 lat, lon coords.

Decodes int X component of GS1 location string back into a WGS84 latitude.

Decodes the int Y component of GS1 location string back into a WGS84 longitude.

Validates if a code structure matches a GLN (Global Location Number). GLN is structurally identical to a GTIN-13 but relies on context.

Converts WGS84 lat/lon coords into integer representation used by GS1.

Converts WGS84 lan, lon coords to 20-char GS1 encoded string.

Functions

data_iso_to_float(arg1, dec_places)

@spec data_iso_to_float(String.t(), any()) ::
  {:error, :invalid | :len_mismatch} | {:ok, String.t(), float()}

Extracts ISO currency code and amount value from ISO AI data string containing an ISO currency code prefix followed by an amount with an implied decimal point into structured data.

This function is used for AIs like "391n" where the data field consists of:

  • 3-digit ISO 4217 currency code (e.g., "978" for EUR, "840" for USD)
  • Amount with an implied decimal point position (n part from AI)

See data_to_float/2 for the underlying amount conversion logic.

Parameters

  • data: AI data string starting with a 3-digit ISO currency code followed by the amount (e.g., "978150" for €1.50 when dec_places is 2).
  • dec_places: The number of digits after the implied decimal point.

Returns

  • {:ok, iso_code_str, float_amount} - on success; note that ISO 4217 currency code validation is not performed.
  • {:error, :invalid} - if the ISO code or amount cannot be parsed.
  • {:error, :len_mismatch} - if the amount part is too short for the given decimal places.

Examples

iex> GS1.Utils.data_iso_to_float("978150", 2)
{:ok, "978", 1.5}

iex> GS1.Utils.data_iso_to_float("8401000", 0)
{:ok, "840", 1000.0}

iex> GS1.Utils.data_iso_to_float("978099", 2)
{:ok, "978", 0.99}

data_to_float(data, dec_places)

@spec data_to_float(String.t(), non_neg_integer()) ::
  {:error, :invalid | :len_mismatch} | {:ok, float()}

Converts a AIs (like "310x", "320x", etc.) data string, which may contain an implied decimal point to float.

The dec_places parameter specifies how many digits from the right of the string represent the fractional part. See genspec: 7.8.7 Application Identifiers with implied decimal point positions

Parameters

  • data: AI data part (e.g., "3000200").
  • dec_places: The number of digits after the implied decimal point (e.g., 3).

Returns

  • {:ok, float()} - if conversion is successful.
  • {:error, :invalid} - if the resulting string cannot be parsed as a float.
  • {:error, :len_mismatch} - if the length of data is less than or equal to dec_places.

Examples

iex> GS1.Utils.data_to_float("3000200", 3)
{:ok, 3000.2}

string_20_to_wgs84_lat_log(arg1)

@spec string_20_to_wgs84_lat_log(String.t()) ::
  {:error, :invalid} | {:ok, {float(), float()}}

Converts a 20-char data string (e.g., AI "8200") to WGS84 lat, lon coords.

Input is split into two 10-char parts:

  • First 10 characters encode latitude (X).
  • Second 10 characters encode longitude (Y).

The conversion logic is defined by GS1 specifications for location encoding.

Parameters

  • data: A 20-char binary/string containing the encoded coordinates.

Returns

  • {:ok, {latitude, longitude}} - where both are floats.
  • {:error, :invalid} - if the input is not a 20-char binary or parts are invalid.

Examples

iex> GS1.Utils.string_20_to_wgs84_lat_log("02790858483015297971")
{:ok, {-62.0914152, -58.470202900000004}}

to_wgs84_latitude_deg(x)

@spec to_wgs84_latitude_deg(non_neg_integer()) :: nil | float()

Decodes int X component of GS1 location string back into a WGS84 latitude.

Examples

  iex> GS1.Utils.to_wgs84_latitude_deg(0279085848)
  -62.0914152

to_wgs84_longitude_deg(y)

@spec to_wgs84_longitude_deg(non_neg_integer()) :: nil | float()

Decodes the int Y component of GS1 location string back into a WGS84 longitude.

Examples

  iex> GS1.Utils.to_wgs84_longitude_deg(3015297971)
  -58.470202900000004

valid_gln?(code)

@spec valid_gln?(String.t()) :: boolean()

Validates if a code structure matches a GLN (Global Location Number). GLN is structurally identical to a GTIN-13 but relies on context.

Examples

iex> GS1.Utils.valid_gln?("4006381333931")
true

wgs84_lat_log_to_ints(lat_deg, lon_deg)

@spec wgs84_lat_log_to_ints(float(), float()) ::
  {:ok, {non_neg_integer(), non_neg_integer()}} | {:error, :invalid_lat_lon}

Converts WGS84 lat/lon coords into integer representation used by GS1.

This function applies the offset and scaling factors defined in the GS1 General Specifications but does not format them into the final data field string.

Parameters

  • lat_deg: WGS84 latitude in decimal degrees ([-90.0, 90.0]).
  • lon_deg: WGS84 longitude in decimal degrees ([-180.0 and 180.0]).

Returns

  • {:ok, {x_int, y_int}} - int representations of latitude and longitude.
  • {:error, :invalid_lat_lon} - error if coords is out of range.

Examples

  iex> GS1.Utils.wgs84_lat_log_to_ints(-62.0914152, -58.470202900000004)
  {:ok, {279085848, 3015297971}}

wgs84_lat_log_to_string_20(lat_deg, lon_deg)

@spec wgs84_lat_log_to_string_20(float(), float()) ::
  {:ok, String.t()} | {:error, :invalid_lat_lon}

Converts WGS84 lan, lon coords to 20-char GS1 encoded string.

The resulting string is formatted as a 10-digit encoded latitude followed by a 10-digit encoded longitude. Each encoded integer is padded with leading zeros to ensure a 10-char length. This is the reverse operation of string_20_to_wgs84_lat_log/1.

Parameters

  • lat_deg: WGS84 latitude in decimal degrees ($-90.0$ to $90.0$).
  • lon_deg: WGS84 longitude in decimal degrees ($-180.0$ to $180.0$).

Returns

  • {:ok, String.t()} - 20-char encoded string.
  • {:error, :invalid_lat_lon} - when input coords are outside the valid WGS84 range.

Examples

iex> GS1.Utils.wgs84_lat_log_to_string_20(-62.0914152, -58.470202900000004)
{:ok, "02790858483015297971"}