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 sends | Protocol 78 record | For which inputs |
|---|---|---|
| Current readings | 0x12 | All enabled counting inputs; on the magnet command — all inputs in Counting mode, disabled ones included |
| Daily packet of the hourly archive | 0x02 — input 1, 0x04 — input 2 | Inputs 1 and 2 only |
| Reply to input configuration | 0x08, CFG_ID and CFG_RESULT subtypes | Any 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).
| Value | Trigger | What the input counts |
|---|---|---|
| 0 | Opening (rising edge) | One opening — one pulse |
| 1 | Closing (falling edge), default | One closing — one pulse |
| 2 | Any change | The counter increments on both edges: two counts per pulse |
| 3 | None | Nothing: 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.
| Parameter | Command 0x05 byte | Actual default | Valid range | Value 0 or out of range |
|---|---|---|---|---|
| Debounce time | 0 | 24 ms (byte 6) | 20–512 ms: byte values 5–128 | The device uses 26 ms |
| Pulse polling period | 1 | 100 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
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).
| Parameter | Default value |
|---|---|
| Input type | Counting (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 |
| Trigger | Closing (falling edge) |
| Capture type | COMBI |
| Priority | LOW |
| Command 0x04 byte | 0x10 |
| Coefficient | 1, divide |
| Debounce time | 24 ms (26 ms in the firmware, see above) |
| Pulse polling period | 100 ms (101 ms in the firmware) |
| Send interval | 24 hours |
| EEPROM save interval | 30 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–14 | Coefficient minus 1 |
| 15 | 1 — 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.
| Field | Size | Meaning |
|---|---|---|
| FORMAT | 1 byte | 0x12 |
| TIMESTAMP | 4 bytes, uint32, least significant byte first | Seconds since 2000-01-01 00:00 UTC. To get UNIX time, add 946684800 |
| FLAGS | 1 byte | Bit 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 header | 1 byte | Bits 0–2 — input number (from 0), bits 3–4 — value length minus 1, bit 7 — sign |
| Value | 1–4 bytes, least significant byte first | Reading 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
| Bytes | Meaning |
|---|---|
78 01 00 | Protocol 78 header: ID, SEQ, FLAGS |
12 | FORMAT 0x12 — current readings |
40 42 5A 32 | TIMESTAMP 0x325A4240 = 844776000; 844776000 + 946684800 = 1791460800 — 2026-10-08 12:00:00 UTC |
84 | FLAGS: bit 7 = 1 — input number in the value header; bits 2–4 = 1 — two counters |
08 | Header: input 0 (input 1), bits 3–4 = 1 — 2-byte value, sign 0 |
39 30 | 0x3039 = 12345 |
01 | Header: input 1 (input 2), 1-byte value |
05 | 5 |
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.
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.
| Field | Size | Meaning |
|---|---|---|
| FORMAT | 1 byte | 0x02 — input 1, 0x04 — input 2 |
| TIMESTAMP | 4 bytes, uint32, least significant byte first | Time of the first record in the block, seconds since 2000-01-01 00:00 UTC |
| Initial value | 4 bytes, int32, least significant byte first | Reading of the first record with the coefficient applied |
| FLAGS | 2 bytes, uint16, least significant byte first | Bits 8–13 (REC_NUM) — number of differences; bit 15 — the counter did not change during the day, the packet carries no differences |
| Differences | Variable | Compressed 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
| Bytes | Meaning |
|---|---|
78 02 00 | Protocol 78 header: ID, SEQ, FLAGS |
02 | FORMAT 0x02 — daily archive of input 1 |
D0 FE 58 32 | TIMESTAMP 0x3258FED0 = 844693200; 844693200 + 946684800 = 1791378000 — 2026-10-07 13:00:00 UTC |
E8 03 00 00 | Initial value 1000 |
00 97 | FLAGS 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.
| Byte | Meaning |
|---|---|
| FORMAT | 0x10 |
| LEN | 6 |
| 0 | Low nibble — input: 0 — input 1, 1 — input 2. High nibble — archive type: 0 — hourly |
| 1–4 | Period start: uint32, least significant byte first, seconds since 2000-01-01 00:00 UTC |
| 5 | Number 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
| Bytes | Meaning |
|---|---|
78 00 00 | Protocol 78 header: ID, SEQ, FLAGS |
10 | FORMAT 0x10 — archive request |
06 | LEN: 6 bytes of block body |
00 | Input 0 (input 1), type 0 — hourly archive |
00 48 58 32 | 0x32584800 = 844646400 — 2026-10-07 00:00:00 UTC |
18 | 24 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 byte | Meaning |
|---|---|
| 0 | Input number: 0, 1, 2 for inputs 1, 2, 3. A block with number 3 or higher is not applied |
| 1 | CFG_ID — configuration version, see the "Configuration version and device reply" section |
| 2 onward | Commands: a CMD byte followed by the command data. A block may contain several commands |
Counting input commands
| CMD | Purpose | Data |
|---|---|---|
| 0x00 | Counter: absolute value | 4 bytes, int32, least significant byte first, in pulses. Written to EEPROM immediately |
| 0x01 | Counter: increment | 4 bytes, int32, least significant byte first, in pulses. Written to EEPROM immediately |
| 0x02 | Current readings send interval | 3 bytes, uint24, least significant byte first, in seconds. The device silently ignores a value shorter than 60 seconds |
| 0x03 | Counter EEPROM save interval | 2 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 |
| 0x04 | Input type, priority, trigger, capture type | 1 byte, see the next section |
| 0x05 | Debounce time and pulse polling period | 2 bytes in "ms / 4" units: byte 0 — debounce, byte 1 — pulse polling period |
| 0x06 | Coefficient | 2 bytes, uint16, least significant byte first, see the "Coefficient and initial value" section |
| 0x0A | Activation | 1 byte: bit 0 — input enabled, bit 1 — logging, bit 2 — archive sending |
| 0xEE | LoRaWAN confirmation | 1 byte, see the table below |
The command 0xEE byte sets which packets are sent with LoRaWAN confirmation:
| Bit | Packets |
|---|---|
| 0 | Current readings — 0x12 records |
| 1 | Digital input events and state; has no effect on a counting input |
| 2 | Daily archive — 0x02 and 0x04 records |
The "Input type" byte (command 0x04)
| Bits | Parameter | Values for a counting input |
|---|---|---|
| 0–1 | Input type | 0 — counting (1 — Digital). Values 2 and 3 are a format error |
| 2–3 | Priority | Default — 0 (LOW). Value 3 is a format error |
| 4–5 | Trigger | 0 — opening, 1 — closing, 2 — any change, 3 — None (do not set), see the "Trigger" section |
| 6–7 | Capture type | 0 — 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
| Bytes | Meaning |
|---|---|
78 00 00 | Protocol 78 header: ID, SEQ, FLAGS |
02 | FORMAT 0x02 — DI CFG block |
0D | LEN: 13 bytes of block body follow |
00 | Input number 0 — input 1 |
05 | CFG_ID = 5 |
0A 07 | Activation: input enabled, logging, archive sending |
02 10 0E 00 | Send interval 0x000E10 = 3600 seconds (1 hour) |
04 10 | Input type: counting, LOW, closing, COMBI |
06 09 00 | Coefficient: 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
| Bytes | Meaning |
|---|---|
78 00 00 | Protocol 78 header: ID, SEQ, FLAGS |
02 | FORMAT 0x02 — DI CFG block |
07 | LEN: 7 bytes of block body follow |
00 | Input number 0 — input 1 |
06 | CFG_ID = 6 |
00 48 E8 01 00 | Command 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_ID | What the device does |
|---|---|
| 0 | Applies nothing, only reports the current version |
| 1–254 | Applies the block only if CFG_ID differs from the stored version. If they match, the whole block is skipped, including the counter setting |
| 255 | Always 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_CFGwith thesuccessandcfg_idfields.
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
- Digital — Digital mode: input state and events.
- Digital inputs — input modes and the digital input schematic.
- Operation — device production and warehouse modes.
- 0x02 Counter1 — daily archive — flags and difference compression of the daily packet.
- Protocol 78 playground — decoding device packets in the browser.