ELF-M
The ELF-M driver is a driver in the OrionMeter LA-IP-MBUS firmware for ELF-M heat meters made by JSC Teplovodomer. The modem itself reads current values and archives from the meter, synchronizes the clocks and sends ready-made parameters over LoRaWAN — energy, volume, temperatures and others — rather than the raw meter response the universal driver sends. This page covers how to configure the driver by downlink and how to parse its data.
Driver availability
The standard OrionMeter LA-IP-MBUS firmware does not contain the ELF-M driver: it includes only the universal M-Bus driver. Working with ELF-M requires a separate firmware build that includes this driver. The driver number is 0x17.
If the modem runs firmware without the driver, the ELF-M configuration is not applied. The modem responds with the CFG_FAILED service event (code 19, 0x13) with subcode 0x50–0x53: the high digit 5 means "driver not in the build", the low digit is the device number (0–3). Slots that are already working are left untouched.
How the modem polls the meter
The driver talks to the meter over two protocols on the same line:
- current values — over M-Bus: request
REQ_UD2, responseRSP_UD(start byte 0x68, the modem verifies the checksum); - date and time, time setting and archives — over the PT01-2008 protocol: commands 0x2D (read time), 0x28 (set time) and 0x2F (read archive). A request starts with byte 0x4D, a response with byte 0x53, the checksum is CRC8.
The steps of one polling cycle go in this order:
| Step | What the modem does |
|---|---|
| 1 | Takes a job from the queue: a scheduled poll or a one-time command |
| 2 | Opens the port |
| 3 | Reads the meter date and time (command 0x2D) |
| 4 | Corrects the time — see "Time synchronization" |
| 5 | Selects the meter — only with addressing by serial number |
| 6 | Reads current values (M-Bus) |
| 7 | Reads archives (command 0x2F) |
| 8 | Closes the port |
The modem reads the time in every cycle, before reading data. If the meter has not answered the time request after all attempts, the cycle ends with an error and current values are not read.
Meter addressing
The configuration holds two meter addresses:
- the primary (network) address — 1 byte, field
dev_addr_primary; - the serial number — 4 bytes, field
dev_addr.
The modem always requests time and archives over PT01-2008 by the primary address, even when it reads current values by serial number. So always set the primary address.
How current values are requested is set by bits 3–4 of the DEVCFG field:
| DEVCFG bits 3–4 | How the modem requests current values |
|---|---|
| Not 0 | REQ_UD2 to the primary address |
| 0 | First selects the meter by serial number: SND_UD to address 0xFD with the meter-selection CI; the data holds 4 bytes of the serial number, least significant byte first, and 4 bytes of 0xFF. After the 0xE5 acknowledgement it sends REQ_UD2 to address 0xFD |
The driver does not check the serial number in the RSP_UD response.
Driver configuration
The configuration takes 29 bytes. Multi-byte fields are sent least significant byte first.
| Offset | Field | Bytes | Contents |
|---|---|---|---|
| 0 | dev_addr | 4 | Meter serial number |
| 4 | dev_addr_primary | 1 | Meter primary address |
| 5 | dev_cfg | 2 | DEVCFG: addressing, time synchronization, number of attempts |
| 7 | rfu | 2 | Reserved |
| 9 | Group 1 | 5 | PARAM CFG (3 bytes) and PARAM LIST (2 bytes) |
| 14 | Group 2 | 5 | Same |
| 19 | Group 3 | 5 | Same |
| 24 | Group 4 | 5 | Same |
The DEVCFG field:
| Bits | Purpose |
|---|---|
| 3–4 | Addressing of current values: 0 — by serial number, any other value — by primary address |
| 10 | The modem writes its time to the meter |
| 11 | The modem takes the time from the meter |
| 12–13 | Number of attempts to reach the meter: 0 and 1 — one attempt without retry, 2 — two attempts, 3 — three |
Polling groups
Each of the four groups sets its own polling period, origin hour, data source and parameter list.
PARAM CFG
The field takes 24 bits:
| Bits | Purpose |
|---|---|
| 0–12 | Polling period: (value + 1) × 10 minutes |
| 13–17 | Origin hour in UTC, 0–23: the driver counts it from UTC midnight, ignoring the time zone. Value 31 (0x1F) is a random hour. The ELF-M driver does not keep the chosen hour between polling cycles, so set an explicit hour (0–23) for a predictable schedule. Any other value above 23 disables the group |
| 18–20 | Data source: 0 — current values, 1 — hourly archive, 2 — daily, 3 — monthly, 4 — yearly |
| 23 | Group active |
On schedule the modem reads the latest record from the archive.
PARAM LIST
A 2-byte parameter bit mask. The table also gives the parameter id and its value length in packet 0x13 — see "Data transmission over LoRaWAN".
| Mask bit | Parameter | id in packet 0x13 | Value length, bytes |
|---|---|---|---|
| 0x0001 | Energy | 0x00 | 4 (float32) |
| 0x0002 | Volume | 0x06 | 4 |
| 0x0004 | Heat power | 0x05 | 2 |
| 0x0008 | Volume flow | 0x04 | 2 |
| 0x0010 | Supply pipe temperature | 0x02 | 2 |
| 0x0020 | Return pipe temperature | 0x22 | 2 |
| 0x0040 | Binary error flags | 0x0B | 4 |
| 0x0080 | Error flags | 0x2B | 4 |
| 0x0100 | Pulse input 1 | 0x0A | 4 |
| 0x0200 | Pulse input 2 | 0x2A | 4 |
| 0x0400 | Pulse input 3 | 0x4A | 4 |
| 0x0800 | Pulse input 4 | 0x6A | 4 |
| 0x1000 | Operating time, seconds | 0x09 | 4 |
| 0x2000 | Operating time with error, seconds | 0x29 | 4 |
List limits:
- Specify no more than 13 parameters in one group.
- Error flags (0x0080) are read only from current values. If this bit is set in an archive group, the modem ends the polling cycle: the data of this group and of the groups after it in this cycle is not sent.
- Binary error flags (0x0040) in the hourly and daily archive are skipped without an error: these archives contain no error codes.
Time synchronization
The modem reads the meter time in every polling cycle. What to do with it next is set by DEVCFG bits:
- Bit 11 — if the modem clock needs setting, the modem takes the time from the meter.
- Bit 10 — if the modem clock is correct, the modem writes its time to the meter with command 0x28: minutes, hours, day, month, year, century (20), day of week. The write happens no more than once a day; after the modem powers on, the first write is postponed by a day. The time is written from the modem clock in UTC, without conversion to local time, while the driver reads the meter time as local. If the modem time zone is not UTC, bit 10 shifts the meter clock by the zone offset.
One-time commands
A one-time command reads current values or an archive record for a date without waiting for the schedule. A command is 1 type byte and up to 16 data bytes; the modem rejects a longer command. A command that arrives during a poll is not postponed: the modem responds with a CFG_FAILED event with subcode 0x1… — see "Errors and service events".
| Type | What it reads | Data after the type byte |
|---|---|---|
| 0 | Current values | PARAM LIST, 2 bytes |
| 1 | Hourly archive | Year, month, day, hour — 1 byte each, then PARAM LIST, 2 bytes |
| 2 | Daily archive | Same |
| 3 | Monthly archive | Same |
| 4 | Yearly archive | Same |
How the modem parses the date in an archive command:
- The year is the last two digits (years since 2000). Year 0 means the latest archive record.
- If the year is not 0, the month must be 1–12, the day 1–31, the hour 0–23. Otherwise the modem sends a CONFIG event (code 7) with subcode 0.
- The modem converts the date to an archive record number. Archive depth: yearly — 9 records, monthly — 19, daily — 79, hourly — 744. If the date is in the future or beyond the archive depth, the modem sends a CONFIG event with subcode 6 and does not read the record.
The modem queues the command result with the highest priority (CRITICAL) and transmits right after it finishes. Scheduled data goes out with LOW priority.
How to send the configuration and a command
The configuration and commands are sent in downlink block 0x06 (SERIAL DRIVER CFG PORT 0). This firmware does not process block 0x05 (port 1); the port is always 0.
The block data starts with a header:
| Field | Size | Contents |
|---|---|---|
| DRV_HDR | 2 bytes, least significant byte first | Bits 0–11 — driver number 0x17; bits 12–13 — device number 0–3; bit 15 — slot enabled |
| LEN_TYPE | 1 byte | Bits 0–5 — data length minus 1; bits 6–7 — type: 1 — CONFIG (configuration), 3 — COMMAND (command) |
| Data | 29 bytes for CONFIG, up to 17 bytes for COMMAND | Configuration or command |
For example, for the configuration of device 0: DRV_HDR = 0x8017 (bytes 17 80), LEN_TYPE = 0x5C (type 1, length 29 − 1 = 28). For a type 0 command LEN_TYPE = 0xC2, for an archive command 0xC6.
The 29-byte configuration fits within the 43-byte limit for driver data, so it goes out in one block, without fragmentation.
Data transmission over LoRaWAN
The driver sends data in packet 0x13 (heat meter data), not in the extended packet 0x14.
| Field | Bytes | Contents |
|---|---|---|
| Packet type | 1 | 0x13 |
| Timestamp | 4 | Seconds since 2000-01-01 00:00:00 UTC, least significant byte first |
| Flags | 1 | Bits 0–1 — device number; bits 2–6 — number of parameters minus 1; bit 7 — archive record |
| Parameters | — | For each parameter: an id byte (bits 0–4 — quantity code, bits 5–7 — channel) and the value, least significant byte first. The id and value length are in the PARAM LIST table |
The timestamp:
- for current values — the meter clock time from the response to command 0x2D;
- for an archive record — the date of the record itself.
The modem converts both timestamps from local time to UTC. From the timestamps of hourly and daily records it also subtracts 1 second, from those of monthly records 1 hour 1 second; yearly record timestamps are sent as is.
The archive type is not sent in the packet: bit 7 of the flags only says the record is from an archive, and an hourly, daily, monthly or yearly record cannot be told apart from the packet.
If the parameters do not fit in one LoRaWAN frame, the modem splits packet 0x13 by parameters and returns the remainder to the transmit queue with a raised priority. Confirmed sending is enabled not in the driver configuration but by a group mask in the device slot settings.
The protocol 78 codec does not know packet 0x13: parsing stops at an unknown PID, so the codec does not parse the data after 0x13 either. The codec has no ELF-M profiles or configuration blocks. Packet 0x13 has to be parsed on your side.
Errors and service events
The driver reports errors in service packet 0x08 with subtype 0x07 (SERIAL_DRIVER_EVENT). It carries a timestamp, the driver number (0x17 in events from the ELF-M driver itself) with the device number, the error code and a subcode. The protocol 78 codec parses this subtype.
| Code | Name | Meaning |
|---|---|---|
| 1 | TIMEOUT | The meter did not answer in the allotted time |
| 2 | CRC | The response checksum did not match |
| 3 | ACCESS | The meter did not acknowledge selection by serial number (no 0xE5) or rejected the time setting (the reply to 0x28 does not start with 0x53) |
| 7 | CONFIG | Invalid configuration or command: for example, an invalid date in a command or a date beyond the archive |
| 8 | PROTOCOL | The response does not follow the protocol: wrong start byte (not 0x68 or 0x53) or the response could not be parsed; also — the modem could not build a request |
| 11–13, 15, 16 | — | Line errors: receiver overrun, framing error, noise, parity error and their combination |
| 14 | HARDWARE | UART or DMA hardware failure |
| 19 | CFG_FAILED | A configuration or command from a downlink was not applied; the reason is in the subcode, see below |
| 255 | UNKNOWN | Unrecognized error |
The ELF-M subcode is a small number the driver uses to mark the stage where the error occurred. The subcodes of the CONFIG event are described in the "One-time commands" section.
The CFG_FAILED subcode is structured differently: the high digit is the reason, the low digit is the device number (0–3). Reasons that concern ELF-M:
- 0x1… — the modem was polling at that moment, and it does not postpone commands;
- 0x3… — the command is addressed to a disabled slot;
- 0x5… — the ELF-M driver is not in the firmware build;
- 0x8… — the driver rejected the data, for example a command longer than 17 bytes;
- 0xC… — a command to a driver that is not on the port, for example an ELF-M command on firmware without this driver.
The CFG_FAILED event is generated by the modem, not by the ELF-M driver: it carries the number of the driver currently loaded on the port, so take the device number from the low digit of the subcode.
Good to know
- The driver exists only in a separate firmware build. With the standard build the ELF-M configuration is not applied, and the modem responds with a CFG_FAILED event.
- The primary address is always needed: the modem reads time and archives by it. If the meter does not answer the time request, the modem does not read current values either.
- Do not set error flags (0x0080) in archive groups, and specify no more than 13 parameters per group.
- Scales are not given here. The driver converts current and archive values differently: it multiplies the temperature from current values by 10 and passes the archive temperature as is. The driver obtains archive energy by reading the bits of an integer as float32, so this value cannot be used. Before using the data in calculations, check it against the meter readings.
- The modem clock runs in UTC. The driver counts the group origin hour from UTC midnight, and bit 10 writes UTC time to the meter, although the driver reads the meter time as local. If the modem time zone is not UTC, bit 10 shifts the meter clock by the zone offset.
- Packet 0x13 does not tell which archive a record came from, and the protocol 78 codec does not parse this packet.
See also
- M-BUS — which drivers the modem has and how they differ.
- Universal driver — polling standard M-Bus meters without a separate firmware build.
- Connection — wiring diagram for M-Bus metering devices.
- Specification — how many M-Bus meters can be connected to the modem.