Skip to main content

Counting

In Counting mode an OrionMeter LA-IP-RSP or LA-IP-RSP[A] input counts pulses from a utility meter — a water, gas or electricity meter with a dry contact or open collector output. The device periodically sends the accumulated value to the LoRaWAN network, and for inputs 1 and 2 it also keeps an hourly archive. This page is for those who configure the input over the air and decode device packets on their own server. The Protocol 78 description calls this mode "counting input" (input type 0), and the codec calls it counter.

What a counting input does​

The LA-IP-RSP and LA-IP-RSP[A] have three inputs — numbered 0–2 in the protocol, which are inputs 1–3 — and no discrete output. Counting inputs and the archive work the same way as on the base OrionMeter LA-IP: the firmware uses the same code.

  • A pulse only increments the counter: a counting input generates no events and does not start RS-485 polling. Only an input in Digital mode generates events. The exception is a separate LA-IP-RSP[A] firmware build with the leak and burst detector: if the detector is enabled in the system configuration, a counting input produces leak and burst events.
  • Counting and the hourly archive work only in the device production mode. The inputs and the hourly timer start when the device enters production mode and stop when it leaves it, so pulses are not counted in warehouse mode. The modes are described on the Operation page.
What the device sendsProtocol 78 recordFor which inputs
Current readings0x12All enabled counting inputs; on the magnet command — all inputs in Counting mode, disabled ones included
Daily packet of the hourly archive0x02 — input 1, 0x04 — input 2Inputs 1 and 2 only
Reply to input configuration0x08, CFG_ID and CFG_RESULT subtypesAny input

How the input counts pulses​

Trigger​

Which edge is counted is set by the trigger — bits 4–5 of the command 0x04 byte (see the "Over-the-air configuration" section).

ValueTriggerWhat the input counts
0Opening (rising edge)One opening — one pulse
1Closing (falling edge), defaultOne closing — one pulse
2Any changeThe counter increments on both edges: two counts per pulse
3NoneNothing: the device accepts this setting without an error, but the input does not count. The protocol description forbids this trigger for a counting input

A command 0x04 byte of 0x00 sets up counting of openings, not closings. To count closings in COMBI mode with LOW priority, send 0x10.

COMBI mode: debounce and pulse polling​

A counting input always works in the COMBI capture mode:

  • A closing is counted immediately, on the falling edge. Then the device waits for the debounce time.
  • New closings during this time are not counted; they extend it.
  • If the input stays closed longer than the debounce time, after 1000 ms the device switches off the pull-up and then checks the input once per pulse polling period to save the battery.

Hence the pulse frequency limit is about 1 / debounce time: roughly 40 Hz at 24 ms and 50 Hz at the minimum 20 ms. If the contact stays closed longer than the debounce time, the pause between pulses must also be longer than that time. The Digital inputs page states 40 Hz for COMBI.

Both times are set with command 0x05: one byte per parameter, in "ms / 4" units. EEPROM also stores them in 4 ms units, so the firmware defaults of 26 and 101 ms become 24 and 100 ms after being written and read back. These are the values the input actually uses.

ParameterCommand 0x05 byteActual defaultValid rangeValue 0 or out of range
Debounce time024 ms (byte 6)20–512 ms: byte values 5–128The device uses 26 ms
Pulse polling period1100 ms (byte 25)50–1000 ms; in 4 ms steps these are byte values 13–250 (52–1000 ms)The device uses 101 ms

INTERRUPT mode is not available​

Warning

The firmware does not save the INTERRUPT capture type (bits 6–7 of the command 0x04 byte = 1): these bits are not written to EEPROM, and after the settings are applied the configuration is read back from EEPROM. So the input always works in COMBI mode. The device nevertheless stores the new configuration version and reports it in the reply as if the setting had been applied. All firmware versions with this input module, since 2022, behave this way.

The maximum pulse frequency of 200 Hz, which the specification gives for the device and the Digital inputs page gives for INTERRUPT mode, cannot be reached. Plan for the COMBI limit of about 40 Hz. Set bits 6–7 to 0: values 2 and 3 are a format error, and the device stops parsing the frame at this block.

Default settings​

These settings apply until the input configuration has been changed, and also when the input settings block in EEPROM is corrupted (invalid CRC).

ParameterDefault value
Input typeCounting (0) — on all three inputs
Input enabled (command 0x0A, bit 0)Inputs 1 and 2 — yes, input 3 — no
Logging (command 0x0A, bit 1)Inputs 1 and 2 — on, input 3 — off
Archive sending (command 0x0A, bit 2)On for all three inputs; input 3 has the bit set but is not archived
TriggerClosing (falling edge)
Capture typeCOMBI
PriorityLOW
Command 0x04 byte0x10
Coefficient1, divide
Debounce time24 ms (26 ms in the firmware, see above)
Pulse polling period100 ms (101 ms in the firmware)
Send interval24 hours
EEPROM save interval30 minutes — 120 cycles of 15 seconds
LoRaWAN confirmation (command 0xEE)Off
Configuration version (CFG_ID)0

Input 3 is disabled from the factory: to make it count, enable it with command 0x0A (bit 0).

Counter storage and power loss​

The counter stores the number of pulses as a signed 32-bit integer. It has two copies — in RAM and in EEPROM — each with its own checksum (CRC).

  • The value is written to EEPROM only if it has changed, and no more than once per save interval — 30 minutes by default. The interval is set with command 0x03.
  • At startup the device takes the RAM copy if its CRC is valid and the value is greater than the one saved in EEPROM. Otherwise it takes the EEPROM copy, and if both are corrupted, 0.
  • Before a reboot by command the device saves the counters to EEPROM.
  • On power loss the counters are not saved: the power loss detector does not write them to EEPROM.

So when power is cut — the battery is replaced on an LA-IP-RSP or mains power is lost on an LA-IP-RSP[A] — the pulses accumulated since the last EEPROM save are lost: up to 30 minutes of counting with the default interval. Pulses that the utility meter produces while an LA-IP-RSP[A] has no power are lost too — see Function and application.

Coefficient and initial value​

The counter always stores pulses. The device applies the coefficient (command 0x06) to the readings it sends — 0x12 records — and to the hourly archive records. Division is integer division; the remainder is discarded.

Bits of the command 0x06 value (uint16, least significant byte first)Meaning
0–14Coefficient minus 1
151 — multiply, 0 — divide

For example, 06 09 00 means divide by 10. If bits 0–14 carry 0x7FFF (coefficient 32768), the device uses 1, so the coefficients that actually work are 1–32767. The protocol description and the codec give the range 1–32768.

The initial value is set with commands 0x00 (absolute value) and 0x01 (increment). Both carry an int32, least significant byte first, also in pulses rather than in reading units. The device writes the new value to EEPROM immediately.

For the device to send reading R with divider K, set the counter to R × K pulses. For example, with divider 10 and a utility meter reading of 12,500, set 125,000 pulses — an example frame for input 1 is in the "Over-the-air configuration" section.

Current readings (FORMAT 0x12)​

The device sends counting input readings as a 0x12 record. The record is created:

  • when the input send interval timer fires (command 0x02);
  • on the "forced send" magnet command — the record then includes all inputs in Counting mode, disabled ones included (from the factory, all three).

The packet the device sends at startup carries no readings. So after activation the first readings arrive only after the send interval — 24 hours with the default settings.

The send interval timer counts from the moment the device enters production mode or from the last change of the settings of any input and is not tied to the clock. Inputs with the same send interval go into one record. The record is queued and goes out at the next transmission; its timestamp is the moment the readings were taken, not the moment of transmission.

FieldSizeMeaning
FORMAT1 byte0x12
TIMESTAMP4 bytes, uint32, least significant byte firstSeconds since 2000-01-01 00:00 UTC. To get UNIX time, add 946684800
FLAGS1 byteBit 7 = 1 — the input number is given in the value header; bits 2–4 — number of counters minus 1; bit 5 — initialization flag, the LA-IP-RSP firmware does not set it
Value header1 byteBits 0–2 — input number (from 0), bits 3–4 — value length minus 1, bit 7 — sign
Value1–4 bytes, least significant byte firstReading with the coefficient applied

The header and the value repeat for each counting input in the record.

Example: on 2026-10-08 at 12:00:00 UTC input 1 reads 12345 and input 2 reads 5.

78 01 00 12 40 42 5A 32 84 08 39 30 01 05
BytesMeaning
78 01 00Protocol 78 header: ID, SEQ, FLAGS
12FORMAT 0x12 — current readings
40 42 5A 32TIMESTAMP 0x325A4240 = 844776000; 844776000 + 946684800 = 1791460800 — 2026-10-08 12:00:00 UTC
84FLAGS: bit 7 = 1 — input number in the value header; bits 2–4 = 1 — two counters
08Header: input 0 (input 1), bits 3–4 = 1 — 2-byte value, sign 0
39 300x3039 = 12345
01Header: input 1 (input 2), 1-byte value
055

A fragment of the codec output for this packet (service fields omitted):

"utctimestamp": "2026-10-08T12:00:00.000Z",
"counter_1": { "rawValue": 12345, "value": 12345 },
"counter_2": { "rawValue": 5, "value": 5 }

The codec calls input 3 counter_3: the frame 78 01 00 12 40 42 5A 32 80 02 07 gives counter_3 = 7. A negative value is sent with the sign bit in the header: in the frame 78 01 00 12 40 42 5A 32 80 80 FB the codec decodes counter_1 = −5.

Hourly archive of inputs 1 and 2​

The hourly archive is kept only for inputs 1 and 2; input 3 is not archived.

  • At the start of every hour by the device clock, the accumulated reading with the coefficient applied is written to the archive — if the input is enabled, works in Counting mode and has logging on (command 0x0A, bit 1). Otherwise 0 is written.
  • The records of the current day accumulate in RAM. After the 24th record the block is saved to EEPROM, and for each of inputs 1 and 2 that is enabled, works in Counting mode and has logging and archive sending on (command 0x0A, bits 0–2) the device queues a packet with 24 values.
  • The block timestamp is the time of the 24th record minus 23 hours, so the block is not tied to midnight. Records have no timestamps of their own: they follow the block timestamp in 1-hour steps. If an hourly tick is missed (for example, during a reboot), the timestamps of the earlier records in the block shift.

EEPROM holds a ring of daily blocks: a new block overwrites the oldest one. In firmware METER_V3.0.4.24 and later there are 49 blocks, so the archive covers about 49 days; earlier versions have 52 or 54 blocks. The specification states 62 days, which does not match the firmware. The records of the current incomplete day are kept only in RAM: they cannot be requested over the air and are lost on power loss.

Warning

Values in the block are stored as int16 differences. If the hourly increase (after the coefficient) of input 1 or 2 falls outside −32768…32767, the daily block is not written for both inputs, and no daily packets are sent. This happens:

  • when an input or its logging is turned on or off in the middle of the day and the reading is greater than 32767;
  • when the counter is set with command 0x00 or 0x01 and jumps by more than 32767;
  • with a flow of more than 32767 pulses per hour without a divider.

Daily packet (FORMAT 0x02 and 0x04)​

The archive of input 1 arrives as a 0x02 record, that of input 2 as a 0x04 record. The LA-IP-RSP does not send 0x06 records. Flags and difference compression are described in detail on the 0x02 and 0x04 pages.

FieldSizeMeaning
FORMAT1 byte0x02 — input 1, 0x04 — input 2
TIMESTAMP4 bytes, uint32, least significant byte firstTime of the first record in the block, seconds since 2000-01-01 00:00 UTC
Initial value4 bytes, int32, least significant byte firstReading of the first record with the coefficient applied
FLAGS2 bytes, uint16, least significant byte firstBits 8–13 (REC_NUM) — number of differences; bit 15 — the counter did not change during the day, the packet carries no differences
DifferencesVariableCompressed differences between adjacent records

Example: daily packet of input 1; the counter did not change during the day and equals 1000.

78 02 00 02 D0 FE 58 32 E8 03 00 00 00 97
BytesMeaning
78 02 00Protocol 78 header: ID, SEQ, FLAGS
02FORMAT 0x02 — daily archive of input 1
D0 FE 58 32TIMESTAMP 0x3258FED0 = 844693200; 844693200 + 946684800 = 1791378000 — 2026-10-07 13:00:00 UTC
E8 03 00 00Initial value 1000
00 97FLAGS 0x9700: bit 15 = 1 — counter unchanged, no differences; REC_NUM = 23

The codec decodes the packet as counter1 with a values array of 24 values of 1000: the first one at 2026-10-07T13:00:00Z, with an interval step of 3600 seconds.

Requesting the archive over the air (FORMAT 0x10)​

Daily blocks stored in EEPROM can be requested with a FORMAT 0x10 downlink block on fPort 1 or 2 — the same as input settings.

ByteMeaning
FORMAT0x10
LEN6
0Low nibble — input: 0 — input 1, 1 — input 2. High nibble — archive type: 0 — hourly
1–4Period start: uint32, least significant byte first, seconds since 2000-01-01 00:00 UTC
5Number of records. The device cuts values above 24 down to 24

The device replies with a 0x02 or 0x04 record. The timestamp in the reply is the period start rounded down to an archive record. If the compressed data do not fit into one frame, the rest goes out in the next packet. The reply is queued with the highest priority, which speeds up its transmission.

The device sends no reply at all if:

  • the archive has no data for the requested period;
  • input 3 is requested;
  • the daily archive type is requested;
  • 0 records are requested.

Example: request 24 records of input 1 starting from 2026-10-07 00:00 UTC. The example is built from the firmware: the codec does not decode block 0x10.

78 00 00 10 06 00 00 48 58 32 18
BytesMeaning
78 00 00Protocol 78 header: ID, SEQ, FLAGS
10FORMAT 0x10 — archive request
06LEN: 6 bytes of block body
00Input 0 (input 1), type 0 — hourly archive
00 48 58 320x32584800 = 844646400 — 2026-10-07 00:00:00 UTC
1824 records

Over-the-air configuration: DI CFG block (FORMAT 0x02)​

Inputs are configured with a Protocol 78 downlink packet. The device accepts it on fPort 1 and 2; the codec encodes it on fPort 2. The header (ID 0x78, SEQ, FLAGS — see Packet format) is followed by the DI CFG block: a FORMAT byte = 0x02, a LEN byte with the block body length, then the body.

Body byteMeaning
0Input number: 0, 1, 2 for inputs 1, 2, 3. A block with number 3 or higher is not applied
1CFG_ID — configuration version, see the "Configuration version and device reply" section
2 onwardCommands: a CMD byte followed by the command data. A block may contain several commands

Counting input commands​

CMDPurposeData
0x00Counter: absolute value4 bytes, int32, least significant byte first, in pulses. Written to EEPROM immediately
0x01Counter: increment4 bytes, int32, least significant byte first, in pulses. Written to EEPROM immediately
0x02Current readings send interval3 bytes, uint24, least significant byte first, in seconds. The device silently ignores a value shorter than 60 seconds
0x03Counter EEPROM save interval2 bytes, uint16, least significant byte first, in seconds. The device divides the value by 15 and discards the remainder; values 1–14 give the default 30 minutes, 0 is ignored
0x04Input type, priority, trigger, capture type1 byte, see the next section
0x05Debounce time and pulse polling period2 bytes in "ms / 4" units: byte 0 — debounce, byte 1 — pulse polling period
0x06Coefficient2 bytes, uint16, least significant byte first, see the "Coefficient and initial value" section
0x0AActivation1 byte: bit 0 — input enabled, bit 1 — logging, bit 2 — archive sending
0xEELoRaWAN confirmation1 byte, see the table below

The command 0xEE byte sets which packets are sent with LoRaWAN confirmation:

BitPackets
0Current readings — 0x12 records
1Digital input events and state; has no effect on a counting input
2Daily archive — 0x02 and 0x04 records

The "Input type" byte (command 0x04)​

BitsParameterValues for a counting input
0–1Input type0 — counting (1 — Digital). Values 2 and 3 are a format error
2–3PriorityDefault — 0 (LOW). Value 3 is a format error
4–5Trigger0 — opening, 1 — closing, 2 — any change, 3 — None (do not set), see the "Trigger" section
6–7Capture type0 — COMBI. 1 — INTERRUPT, not saved by the firmware. Values 2 and 3 are a format error

To count closings in COMBI mode with LOW priority, send 0x10.

Example: configuring input 1​

Input 1: counting, LOW, on closing, COMBI; input, logging and archive sending on; send interval 1 hour; divider 10; configuration version 5. Frame on fPort 2:

78 00 00 02 0D 00 05 0A 07 02 10 0E 00 04 10 06 09 00
BytesMeaning
78 00 00Protocol 78 header: ID, SEQ, FLAGS
02FORMAT 0x02 — DI CFG block
0DLEN: 13 bytes of block body follow
00Input number 0 — input 1
05CFG_ID = 5
0A 07Activation: input enabled, logging, archive sending
02 10 0E 00Send interval 0x000E10 = 3600 seconds (1 hour)
04 10Input type: counting, LOW, closing, COMBI
06 09 00Coefficient: bits 0–14 = 9 — coefficient 10, bit 15 = 0 — divide

Example: setting the counter​

Set the counter of input 1 to 125,000 pulses, configuration version 6:

78 00 00 02 07 00 06 00 48 E8 01 00
BytesMeaning
78 00 00Protocol 78 header: ID, SEQ, FLAGS
02FORMAT 0x02 — DI CFG block
07LEN: 7 bytes of block body follow
00Input number 0 — input 1
06CFG_ID = 6
00 48 E8 01 00Command 0x00: counter = 0x0001E848 = 125,000 pulses

Configuration version and device reply​

CFG_ID in the DI CFG block determines whether the block is applied:

CFG_IDWhat the device does
0Applies nothing, only reports the current version
1–254Applies the block only if CFG_ID differs from the stored version. If they match, the whole block is skipped, including the counter setting
255Always applies the block
  • A new version is stored only if the input settings changed.
  • A block with only command 0x00 or 0x01 sets the counter but does not change the version: the reply carries the previous version, and repeating the same frame sets the counter again. With command 0x01 a repeat adds the increment again.
  • The device replies to a DI CFG block with a 0x08 service record of the CFG_ID subtype: subtype 3, block number 0x02 and the version, for example 08 03 02 05 — version 5. The reply carries no input number.
  • After parsing the whole downlink the device sends one more 0x08 service record — subtype 2 (CFG_RESULT): 2 bytes, uint16, least significant byte first; bit n = 1 — the n-th configuration block in the frame (counting from 0) was accepted. For a DI CFG block the bit is set even if the settings did not change. Example for a frame with one block: 08 02 01 00. The codec merges both records into one — DI_CFG with the success and cfg_id fields.

After new settings are applied, the input is reinitialized and in COMBI mode starts accepting pulses after about 1 second. The current readings send timers restart from that moment.

Errors in the block​

  • A block with input number 3 or higher is not applied.
  • On a format error — command data shorter than required, and for a block being applied also priority 3, input type 2 or 3, capture type 2 or 3 — the device stops parsing the downlink at that point: the block with the error and all blocks after it are not applied and get no reply, and no CFG_RESULT record is sent either. Earlier blocks in the frame and commands 0x00/0x01 of this block placed before the error have already been applied.
  • If the block is not applied — CFG_ID is 0 or equals the stored version — invalid values of the command 0x04 byte are not checked and are not an error.

Good to know​

  • A command 0x04 byte of 0x00 sets up counting of openings. To count closings, send 0x10.
  • The "any change" trigger gives two counts per pulse, the "None" trigger gives none.
  • The firmware does not save INTERRUPT: the frequency limit is about 40 Hz, not the 200 Hz from the specification.
  • After activation the first readings arrive after the send interval — 24 hours with the default settings.
  • The counter is set in pulses: with divider K, set R × K pulses for reading R.
  • A block whose CFG_ID equals the stored version is skipped entirely — together with the counter setting.
  • An increase of more than 32767 per hour on input 1 or 2 means the daily archive of both inputs is not written.
  • The archive is kept for about 49 days (52–54 in older firmware versions), not the 62 days stated in the specification.
  • Do not set a send interval longer than 4,294,967 seconds (about 49.7 days): the device timer overflows.
  • On power loss the pulses accumulated since the last EEPROM save are lost — up to 30 minutes of counting with the default interval.

See also​