Message Layer (7Fh)

Isotropic Sensor Network Specifications, Message Layer

OSI: Session and Presentation Layers

Keywords: structured data presentation, data entry, host side processing, heterogeneous devices, profile-less, dynamic content, interoperability, rapid development, self-binding, very low communication overhead, sensors, internet of things, embedded systems, sensor networks

Document: ISN-Message-1.1 released on February 25, 2017 by Isotel, (c) All Rights Reserved

Creative Commons License
Isotropic Network Specifications: Message Layer 1.1 by Isotel is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.
Permissions beyond the scope of this license may be available at

Note: Any adaptations to this specifications made by groups, individuals or companies are according to the license not allowed for general publication, but we strongly encourage you to send your modifications back to us for further consideration for the next releases.

Commercial License: By using the Sensor Message Layer in your commercial products a royal-free one-time-payment to the Isotel d.o.o., Slovenia, of 9.90 EUR + Tax per device identification descriptor has to be paid, where unlimited number of devices can be sold. Device descriptor is used to reserve and maintain the identification address space to avoid cross-device collisions, protect manufacturer ownership, hyper-linking with the manufacturer web sites, and promotion. After payment is received Isotel will verify the uniqueness of the identification descriptor and availability. In the case device identification descriptor collides with an existing record, a customer is required to modify the identification descriptor in order to fulfil its uniqueness. With this fee you also sponsor the further development of the distributed Isotropic Sensor Network protocols.


The scope of this document is to define the Isotropic Sensor Network Protocol Message Layer for broadcast and peer to peer connections in a distributed sensor area network, wired or wireless, low and high data rate devices, battery powered devices, short-range devices with short operational space, low-cost devices to support trivial sensors, besides the fully featured devices and rapid development of embedded hardware. The Message layer defines simple but powerful communication protocol for compact implementation designed to meet requirements of the next generation distributed Internet of Things (IoT) devices.


The purpose of this specifications is to provide a standard for low complexity, low cost, and low power (aware) consumption devices (sensors).

Key features

  • Rapid Sensor Development
  • Rich Data Structures with very Low Transmission Overhead
  • Self Describing (Dynamic Content) Human Readable Output
  • Direct Mapping to rich Web JSON API
  • High Level Pre/Post-Processing (Math) Support
  • Advanced Value Presentation with Precision, Accuracy and Unit
  • Hand-Shaking for Transfer Reliability
  • Low-Cost and Compact Implementation


This document provides specifications of the Message Layer for use in information exchange between IoT devices themselves and devices and presentation sides. Applications cover sensors, sensor networks, development and debugging of embedded systems via simple UART interfaces to monitor and configure the application, in production environments used for testing, calibration and adjustments, and more. Whenever rapid development, low footprint implementation and dynamic message content is desired.

It provides a straight forward approach of data presentation, reduces CPU complexity and allows transfer of the measured values in their native format, without introducing rounding and other numerical errors. It represents a bi-directional communication where communication over-head and complexity is reduced to the minimum by:

  • splitting the description (the static part) from the arguments (the dynamic part) of the message, which need to be send only once, or on update.
  • description can also be loaded by presentation software, in which case, the device is only sending useful (arguments) data in its raw form,
  • contents is split among messages, where device can update multiple message at once,
  • and receive update in its natural format which means, that a math inverse is computed on the presentation, host side.

Definitions, Acronyms and Abbreviations

device specific parameter in raw (typically native) form
An entity containing this protocol implementation. Also referred as sensor device or just sensor or device.
holds a Sensor Message Layer typical format to describe a device and arguments
The format of aggregated bits that are transmitted together in time.
identification descriptor, message
Zero-th message holds a so called global unique descriptor identifying one device only globally
Internet of Things, and also as Isotel of Things
typically referred to a presentation side of the information received from the sensor, and as user input to the sensor
holding either descriptors or arguments
The format of aggregated bits that are transmitted together in time across the physical medium.
least significant bit
most significant bit

Packet Format

Frame Format

Fields Protocol ID Description Flag Message Number Message Body
Bits 8 1 7 length
Value 0x7F ARGS: 0, DESC: 1 MSGNUM: 0-127 Args or Description

A 16-bit header is followed by an arbitrary length of payload, limited by encapsulating protocol. Header provides unique Protocol ID, followed by a Message Designation.

Message Designation is split into two parts:

  • Description Flag, which defines the content of the Message Body,
  • Message Number, with the first message starting from 0 ending at 127.

Based on Descriptor Flag, Message Body carries either:

  • ARGS: Raw Arguments,
  • DESC: Message Descriptor.

Arguments are specified by the Message descriptor, and when they’re send are encoded as described under section below Arguments Encoding.

The first message MSGNUM=0 is also called a Device Identification Descriptor. It must uniquely define a device by specifying product name, vendor, and version. Serial number and product specific numbers may be passed as arguments, however not the version or any other value that would mean a change in other message descriptors (MSGNUM>0) that would disallow unique and non-ambitious identification of a device. Based on this message hosts may cache the remaining message descriptors.


Description Flag Message Body Length Command
0 0 Request for Argument Update
0 >0 Reply: Argument Update
1 0 Request for Descriptor Update
1 >0 Reply: Descriptor Update

Hand-shaking is unidirectional with two requests for which only one possible reply exists, the content updates. Typically a device contains messages, transmits measurements and a host is a receiver, and user or machine input. However with the reverse direction hosts can serve as remote storage and can be asked by devices to serve input or stored data, configurations, passwords, etc.

Size of the message arguments and descriptors is limited by underlying layers as well as the number of concurrent requests.

Identifying and Setting up a Device

  1. If a device receives an Argument Update for an unknown message then it sends back a Requests for Descriptor for the same message.
  2. If a Descriptor Update is received but arguments are unknown then it sends back a Request for Argument Update for the same message.
  3. For an unknown device, the first request issued is Request for Descriptor for Message Number, MSGNUM=0, to obtain Device Identification Descriptor and possibly re-use the cached content; if device is unknown to a host, then continues as follows:
  4. Content is loaded by starting with the highest message number, sending Request for Descriptor with MSGNUM=0x7F Device replies by returning an Descriptor Update with the last possible message number.
  5. Loading continues with last MSGNUM-1, MSGNUM-2, and stops at MSGNUM=1.

Information Directions and Acknowledging Changes

The message descriptor defines the I/O relations of some parameter, whether it is an output from a sensor only (Output only), can it be changed (I/O), or is it an input driven (Input Only) parameter.

These types define how an originator of a parameter, typically a device, manages and replies to a host.

Output Only Parameters

These cannot be changed, and a device receiving an update to a non-changeable parameter can be ignored without issuing a reply. However if network throughput permits a reply it is advisable that it resends the old value back to the host.

Host should disallow sending updates to such parameters to remove unwanted network traffic and loss of energy.

Input Only Parameters

These can be changed and are controlled by the host, however for this types of parameters host does not expect a reply. It is meant to enter information which does not need a reverse feedback, as password, streaming data to a speaker, etc.

Input and Output Parameters

These fall into the group of full acknowledgment cycle, which requires that a device replies with an updated value, in one of the following two methods:

  1. same as input, or
  2. not-same but different as before

to the host issuing a request. Which type of acknowledgment method is used is selected by the host input. It should follow the following specifications:

  1. when user, or some machine requests to change a value by providing its exact value, or mnemonics, then the acknowledgment procedure selects method 1,
  2. when input is prefixed by a ~ character, like “~1”, or “~Off”, then the 2nd method is selected.

Host must identify the correctness of the reply to give accurate report to a user or machine. It follows this procedure:

  • Sends Argument (Value Change) Request to a Device
  • Waits for a Message with the Desired Value Change:
    • If value received is OK (as per 1st or 2nd method), it reports Success.
    • otherwise it retries N times, before it reports an Error.
    • if no reply is received within a time frame, it retries N times, before it reports: Timeout
  • If device doesn’t send any kind of messages within some time period, device is declared as: Inactive

Device engaged in the above procedure should first serve requests, and then continue with the rest of the updates. This minimizes the number of retries in the network, and increases reaction time.

Device and hosts may send messages concurrently. It may happen that just after sending a request to change a value, a message with an argument update is received from the same device. Above procedure should handle such scenarios by sending a 2nd retry. If underlying protocol provides time synchronization then the message sequence becomes clear to remove redundant retries.

Message Descriptor Specification

Each of 128 available messages is described by a description. It is called a Message Descriptor and provides rich elements as structured text, parameters, data structures, simple expressions, rich math with cross-referencing between parameters, unit and accuracy specifiers, lists / enumerations, view modes and sections.

Text Elements

Typically interaction with a device is done on the variable - value pairs (parameters), however the text elements are used to provide basic descriptions of the device and help on parameters, in human understanding readable way for direct representation by a host.

General Rules

Text is sent as is to the output unless one of the following is used:

  • general escape character %… used to describe arguments and additional text elements,
  • expressions which start with { .. and end with }, immediately followed by optional unit […]
  • data structure that start with a name and followed by {, i.e. struct{ … }

Identifiers (Variable names, List elements, … ) should contain basic ASCII characters:

  • First character must be a letter or [“.”,”_”, “#”, “!”, “?”, “@”] character.
  • Other characters can also include digits and [“/”,”’”, “~”] characters.


  • %T0{…}: title segment, which should be present in the first message and only once per device or unit
  • %T1{…}: page
  • %T2{…}: section
  • %T3{…}: sub-section

Text Size

  • %t0{…}: size equal to title segment,
  • %t1{…}: size equal to heading level 1,
  • %t2{…}: size equal to heading level 2 and so forth

Advanced and Development Headings - Sections

Every heading can include an identifier to denote an advanced or a development section to control the device output level.

  • %Txa{…}: advanced section, x = 0,1,2… header level
  • %Txd{…}: development section, x = 0,1,2… header level

Inheritance from parent sections apply; for example, everything after %T2a{} header would fall under the advanced sections as long as another normal section as %T2{} or %T1{} is defined.

Line Breaking

New line can be requested by:

  • \n which denotes a new paragraph, as <p> …
  • \r denotes a new line, as <br> …


A normal space generates a space at the output, but a space is also assumed at the end of each message, so a string from two messages will be shown as joined strings with a space in-between.


  • %% is used to display %

Argument Specifiers

Argument specifiers define how raw arguments (ARGS) are represented in their native (binary) form, just as like in standard printf().

Argument specifier starts with a % followed by direction, length, and format.


  • %<.. denotes a read-only parameter that is send from a device and cannot be written
  • %>.. denotes a write-only parameter that can only be sent but not read (as pin/password codes)
  • %… denotes a read-write parameter that can be read and modified


  • h: specifies short, an 8-bit byte
  • l: specifies long, a 32-bit word
  • L: specifies long long, a 64-bit word


  • i: 16-bit signed integer
  • u: 16-bit unsigned integer
  • x: 16-bit hex
  • f: 32-bit floating point as per IEEE 754, and lf stands for 64-bit
  • i,u,x,f: denote small endian
  • I,U,X,F: denote big endian format (capital letters)


%u     for 16-bit little endian format
%LU    for 64-bit big endian format
%<Lx   for 64-bit little endian read-only format printed in hex


  • Floating point numbers support default %f which is 32-bit and long %lf 64-bit
  • Above specifiers are not limited to integers only but with the math expressions they represent also fixed-point arithmetic.
  • Omit the length specifier to preserve the default format’s length.

Format with an additional Not-a-Number (NaN) state

The use of NaN has potential in sensors to denote that a measurement is yet invalid or state undefined. Unsigned and signed specifiers are provided:

  • j,J: same as signed integer i,I, but with -MAX (i.e. for %hj value of −128) value denoting the NaN value
  • k,K: same as unsigned integer u,U, but with 0 denoting NaN value

The NaN can be assigned any value, see Lists (Enumeration) below.

Arguments Encoding and Granularity Size


  • 8-bit, as a single byte.
  • 16-bit, two bytes ordered either in little/big endian
  • 32-bit, 4 bytes ordered either in little/big endian

Default granularity size is 8-bit. Some CPU’s have bus widths of 16-bit thus granularity size of one word. These different encoding can be enabled by putting a specifier in a description (usually in msg 0, before the arguments)


  • %e for 16-bit mode
  • %E for 32-bit mode

Cross Referencing

  • %v:<msgnum>$<argnum>: where <msgnum> is message id=0,1,2.. and <argnum> is consecutive argument number 1,2,3.. in the message given by <msgnum>
  • %v:<parameter>: where <parameter> consists of <scope><parameter name>. Scope can be declared in following ways:
    • a full or partial data structure hierarchy path i.e. device.sensor.<parameter name>
    • number of dots ‘.’, representing the number of levels back in the hierarchy where parameter is searched, starting from the level where cross reference is located. i.e. .var will look for parameter var in current scope, while …var will also look two levels higher in the hierarchy
    • if scope is omitted, parameter is searched globally. The first parameter with the corresponding <parameter name> is returned
  • <parameter>: inside expressions, ‘%v:’ can be omitted. Other rules still apply


Expressions represent math objects that are post-process after received by the host. When used in conjunction with variables (parameters) these also define the math-inverse process when changing their values.

General form is given by brackets:



  • math elements include standard operators, arguments, and can directly reference other variables by their full name
  • description is an optional part describing the expression itself, and may provide accuracy, value descriptions (lists/enumeration), or as a set of conditions under which expression is valid or combination of above.

Math Operators and Functions

The following arithmetic/bitwise operators are supported (by descending precedence):

Operator Symbol
Exponential **
Multiplicative * / %
Additive + -
Shift << >>
Bitwise AND &
Bitwise XOR ^
Bitwise OR |

Supported are the following standard math functions: abs, acos, asin, atan, cbrt, cos, cosh, exp, expm1, log, log10, sin, sinh, sqrt, tan, tanh



Math Resolution / Precision

Resolution is automatically determined by the least accurate argument within the expression, i.e. an 8-bit value by itself determines 3 digits, and the decimal point is derived from the equation itself. Resolution then determines the number of digits and decimals to be displayed.

Developers may align the device readings in such a way that output bytes, words, directly denote precision of some measurement.

For instance, the following:


does not apply reduction in resolution or precision, but is simply adding fixed point bits to the output. Word must be properly aligned in the raw arguments after the i.e. A/D reading.

Confidence Interval - Accuracy

An optional argument, besides the precision, is accuracy, which determines the interval of confidence. It can be assigned besides the argument specifier or on the expression level in the description part.

Example, both giving final accuracy of +-0.3:


the character +- can be replaced by the single character according to the ASCII extended ±


Accuracy is computed among entire expression and all arguments to derive the final accuracy, displayed as: value ± error

Accuracy can also be a dynamic expression, in which case it need to be defined in parentheses to separate from main expression


Lists (Enumeration)

The Math Description specifies how values are translated into lists.



  • item0, item1 are assigned default values 0,1,2,..
  • if description for given value does not exists, a value is printed out.
  • The NaN keyword is reserved for integer Not a Number, so {%hu:NaN=0} is equal to {%hk}, see also the two predefined specifiers

Data Structures

Data structure is declared as:

data{ ... }


  • data{ can open the structure in any message, while } can close it in the same or any message after.
  • any degree of nesting is allowed.

Variable - Value Pair Assignments (Parameters)

Variable is syntactically derived from an expression with given list description:


and can only exists in pairs with expressions, in the following form, followed by an expression, and with optional, recommended, unit specifier:



  • where a math object can contain one or more arguments,
  • if at least one is of Input/Output direction then variable may be changed by calculating its inverse, and sending raw arguments back to a device.

Unit specifier should comply with the International System of Units.


{:variable}={1}[V]               // a constant
{:variable}={%<I*0.123}[mA]      // represents a read-only current in mA with some gain factor
{:variable}={%hu:off,on}         // an 8-bit value is used to display state, that may be modified by user

There should be an empty space between a text entry and an expression/assignment, for example:

"Variable description {:var1}={%U}[kWh]"  --correct

"Variable description{:var1}={%U}[kWh]" --incorrect

As on the other hand, data structures are declared without an empty space:


Base Units with Scaling Prefixes

m meter T tera 10^12
g gram G giga 10^9
s second M mega 10^6
A ampere k kilo 10^3
K kelvin d deci 10^−1
mol mole m mili 10^−3
cd candela μ micro 10^−6
n nano 10^-9
p piko 10^−12
f femto 10^−15

Derived Units

rad radian sr steradian
Hz hertz N newtoon
Pa pascal J joule
W Watt C coloumb
V volt F farad
Ω Ohm S siemens
Wb weber T tesla
H henry °C degree celsius
lm lumen lx lux
Bq backuerel Gy gray
Sv sievert kat katal

Hidden variables

Hidden variables are declared using ‘#’ character instead of standard ‘:’, ie. {#var}={…}

Hidden variables are not displayed in output unless specified. They are still used in calculations and can be accessed with terminal console commands.


Vectors can be defined in the following ways:

General form:


[n:m] defines the range of vector.

For example:


which defines a vector of 3 same expressions, and 3 arguments.

Vectors can be defined also with different expressions as:


in which case the number of columns is determined by the comas.

if vector size is defined as in:


It must match the number of elements, otherwise error is reported.

Multi-Message Descriptors

When underlying protocol prohibits the use of long descriptors, then multiple message numbers may be used to form a larger Message Descriptor by placing a plus character ‘+’ at the beginning of successive messages. Arguments below to the first message, and the remaining message numbers are skipped when sending/receiving arguments.


msg 1:          "First {:var11}={%hu}[kWh] in {:var12}={%hu};"
msg 2:          "+Second {:var21}={%hu}[kWh] in {:var22}={%hu};"
msg 3:          "+Third {:var31}={%hu}[kWh] in {:var32}={%hu};"

Creates a longer descriptor for MSGNUM=1, from which same message arguments are read when displaying or updating a message.

Multi-Message Updates

It is desired that messages aren’t too long with too many arguments to offer fine grained control over configuration parameters, or individual updates. However on the other side there are multi-message updates to reduce network overhead and at the same time permitting fine grained control.

Multi-message update is formed with an argument field containig arguments of several messages, starting from the given message number to which it is targeted to, say MSGNUM. The remaining arguments are passed to the following messages MSGNUM+1, MSGNUM+2, etc.


msg 1:            "MultiArg1 {:m1}={%hu+%hu}"
msg 2:            "MultiArg2 {:m2}={%hu+%hu}"
msg 3:            "MultiArg3 {:m3}={%hu+%hu}"

A 6-byte long argument update for msg 1 would in this case update all three messages.



Basic descriptors contain basic headers, data structures, expressions and text elements.

msg0: "%T0{Company Device}V1.1.08 dev{"

msg1: "%T1{First header}\r Temperature {:T}={%li/100}[oC]\r"

msg2: "Enumeration {:state}={%hu:Off,On,Error}"

msg3: "Structure str{{:I_A}={2.174*%hu}[mA] {:M_B}={%u+12}}\r"

msg4: "%T1{Second header}\r"

msg5: "{:ChA}={%u} {:ChB}={%lu}"

msg6: "Final section ending the main structure {:t}={%lU}[UTC]}}"


Advanced descriptors contain more complex expressions, advanced headers and cross references.

msg0:  "%T0{Company Device}V1.1.08 dev{"

msg1:  "%T1{First header}\r Expression with accuracy {:T}={%li/100:+-10}[oC]\r"

msg2:  "Enumeration with defined values {:state}={%hu:Off=0,On=4,Error=8}"

msg3:  "Structure spanning two messages below\r"

msg4:  "str{{:I_A}={2.174*%hu+(12/%u)}[mA] {:M_B}={%u&%u}"

msg5:  "Variable cross reference {:ref}={%u*1.3} {:relativeRef}={2.174*ref} {:absoluteRef}={2.174*dev.str.ref}}\r"

msg6:  "%T1a{Advanced section header}\r Read only {:ChA}={%<hu} write only {:ChB}={%>hu}"

msg7:  "Hex and shift expressions {:hexVar}={%lx} {:phaseShift}={((%U<<8)+%hu)}\r

msg8:  "%T1d{Development section header}\r

msg9:  "Web Link %tu{}"

msg10: "Final section ending the main structure {:t}={%lU}[UTC]}}"


Complex descriptors contain multiple cross references, over multiple messages, more complex expressions and hidden variables.

msg0:  "%T0{Company Device with hidden serial id and 16bit endian encoding rule}V1.1.09 %e {#sid}={%Lx} dev{"

msg1:  "%T1{First header}\r Expression with changing accuracy {:T}={%li/100:+-(%u/100)}[oC]\r"

msg2:  "Enumeration with non-integer values {:state}={%hi*0.2:val1=-0.8,val2=4.2,val3=12}"

msg3:  "Structure spanning two messages below\r"

msg4:  "str{{:I_A}={2.174*%hu+(12/%u)}[mA] NaN arguments {:J_B}={%j}{:K_B}={%k}"

msg5:  "Multiple cross reference {:ref}={%u*1.3} {:relativeRef}={2.174*ref} {:absoluteRef}={2.174*dev.str.ref} {:multiRef}={1.2*ref*absoluteRef}}\r"

msg6:  "Argument cross reference {:argref}={%4:2*1.3}\r"

msg7:  "%T1a{Advanced section header}\r"

msg8:  "Read only {:ChA}={%<hu} write only {:ChB}={%>hu} continues to multi-msg description"

msg9:  "+Hex and shift expressions {:hexVar}={%<lx} {:phaseShift}={((%U<<8)+%hu)}\r

msg10: "%T1d{Development section header}\r

msg11: "Web Link %tu{}"

msg12: "Final section ending the main structure {:t}={%lU}[UTC]}}"

Contributions and Support

This specifications have a long history of over 10 years, starting from a complex message layer for sensor networks, and initial implementations. To reduce complexity on the presentation side and to still fit most of the applications significant effort was done to simplify the specification now released as Sensor Message Layer.

During the development the following two institutions have noticable support by either financial support and also by practical verifications and use cases.

Document Changes

Date Release Changes
February 23, 2006 0.1 Initial Message Layer
November 23, 2006 0.2 Revised for first implementations.
July 10, 2010 0.3 Public version.
December 18,2011 0.4 Simplified version of Message Layer derived
January 23, 2012 0.5 Alignment with first IoT release
February 14, 2016 1.0 Public version of Renewed Sensor Message Layer
February 25, 2017 1.1 Added 32/64-bit floating point specifier





Use of an ISOTEL specification is wholly voluntary. The ISOTEL disclaims liability for any personal injury, property or other damage, of any nature whatsoever, whether special, indirect, consequential, or compensatory, directly or indirectly resulting from the publication, use of, or reliance upon this, or any other ISOTEL specification document.

The ISOTEL does not warrant or represent the accuracy or content of the material contained herein, and expressly disclaims any express or implied warranty, including any implied warranty of merchantability or fitness for a specific purpose, or that the use of the material contained herein is free from patent infringement. ISOTEL specifications documents are supplied AS IS.

The existence of an ISOTEL specification does not imply that there are no other ways to produce, test, measure, purchase, market, or provide other goods and services related to the scope of the ISOTEL specification. Furthermore, the viewpoint expressed at the time a specification is approved and issued is subject to change brought about through developments in the state of the art and comments received from users of the specification. Every ISOTEL specification is subjected to review at least every five years for revision or reaffirmation. When a document is more than five years old and has not been reaffirmed, it is reasonable to conclude that its contents, although still of some value, do not wholly reflect the present state of the art. Users are cautioned to check to determine that they have the latest edition of any ISOTEL specification.

In publishing and making this document available, the ISOTEL is not suggesting or rendering professional or other services for, or on behalf of, any person or entity. Nor is the ISOTEL undertaking to perform any duty owed by any other person or entity to another. Any person utilizing this, and any other ISOTEL specifications document, should rely upon the advice of a competent professional in determining the exercise of reasonable care in any given circumstances.

Interpretations: Occasionally questions may arise regarding the meaning of portions of specifications as they relate to specific applications. When the need for interpretations is brought to the attention of ISOTEL, the ISOTEL will initiate action to prepare appropriate responses. Since ISOTEL specifications represent a consensus of concerned interests, it is important to ensure that any interpretation has also received the concurrence of a balance of interests. For this reason, ISOTEL and the members of its societies are not able to provide an instant response to interpretation requests except in those cases where the matter has previously received formal consideration.

Comments for revision of ISOTEL specifications are welcome from any interested party, regardless of membership affiliation with ISOTEL. Suggestions for changes in documents should be in the form of a proposed change of text, together with appropriate supporting comments. Comments on specifications and requests for interpretations should be addressed to Isotel d.o.o., Slovenia.

Attention is called to the possibility that implementation of this specification may require use of subject matter covered by patent rights. By publication of this specification, no position is taken with respect to the existence or validity of any patent rights in connection therewith. The ISOTEL shall not be responsible for identifying patents for which a license may be required by an ISOTEL specification or for conducting inquiries into the legal validity or scope of those patents that are brought to its attention.