DevEUI for non-hardware assigned values

I didn’t understand this … why becoming worthless??

Starting at €0.19 for onesies, excluding the postage



You’ll have to judge whether you want to use a random ID. However, the definition of EUI-64 allows for this. The definition is given in chapter 8 of the IEEE-802 spec (freely available at

In section 8.2, they describe the u/l bit (bit 1) of byte 0 of EUI-64. If you set that bit, you have a “locally administered address”. Bit 0 always has to be zero for addresses. So a legitimate way of generating a random address, with very low probability of collision, is to generate 8 random bytes, then set bit 1 of byte 0, clear bit 0 of byte 0. On Ubuntu, this simple program will do what you need.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/fcntl.h>
int main(int ac, char **av) {
    int fd, i;
    unsigned char eui[8];
    fd = open("/dev/random", O_RDONLY);
    if (fd < 0) {
        perror("can't open /dev/random");
    if (read(fd, eui, sizeof(eui)) != sizeof(eui)) {
        fprintf(stderr, "couldn't read %zu bytes\n", sizeof(eui));
    eui[0] = (eui[0] & ~1) | 2;
    for (i = 0; i < sizeof(eui); ++i) {
        printf("%02X%c", eui[i], i == sizeof(eui)-1 ? '\n' : '-');
    return 0;

I think we have our solution. Thanks, @terrillmoore!

I’ve posted the program on in case anyone is interested. If I have time, I’ll update it to do simple things like generate a block, and allow you to omit the “-” in the output, which is often convenient when copying/pasting.


A more common, though deprecated, approach seems to be to insert 0xFFFE in the middle; see “Mapping an EUI-48 to an EUI-64” in, emphasis for the past tense mine:

Some standards have described how an EUI-48 value could be mapped to an EUI-64, as follows: Let the six octets of the EUI-48 be labeled eui48[0] through eui48[5]. Let the eight octets of the mapped EUI-64 be labeled eui64[0] through eui64[7]. The following mapping has been described:

eui64[0] = eui48[0]
eui64[1] = eui48[1]
eui64[2] = eui48[2]
eui64[3] = FFhex
eui64[4] = FEhex or eui64[4] = FFhex
eui64[5] = eui48[3]
eui64[6] = eui48[4]
eui64[7] = eui48[5]

In other words, the EUI-64 value was generated by inserting either the value FFFEhex or the value FFFFhex in between eui48[2] and eui48[3].

But beware it also notes this is deprecated, emphasis mine:

Mapping an EUI-48 assigned with an MA-S/OUI-36 or MA-M assignment to an EUI-64 potentially creates a duplicate of an EUI-64 assigned with a different MA-S/OUI-36 or MA-M. The IEEE RA has taken appropriate actions to mitigate creation of duplicates based on this mapping but, to protect the integrity of EUI-64 identifiers, this mapping is deprecated.

Earlier it stated, again emphasis mine:

The mapping described here is deprecated and it should not be used in new applications as it includes an unacceptable probability of duplicating an EUI-64.

(It’s also used in IPv6 but there it also sets a specific bit which in IPv6 defines universal/global scope, so would probably not suffer any chances of duplicating IPv6 addresses.)

1 Like

Just to add up to the excellent response of @terrillmoore : DO NOT USE A FULLY RANDOM EUI64! Sorry for the all caps, but I see people sometimes acting in very un-neighborly ways on those matters, because they ignore that there are a simple ways to be neighborly.

Let’s say the EUI64 is in the following format Hh:HH:HH:HH:HH:HH:HH (canonical representation, in network order, aka MSB first, aka. Big Endian, aka “the way people write numbers in left-to-right writing systems”). It’s a 16-digit hexadecimal number, and the second digit (aka the lower nibble of the most significant byte), represented with the lower case ‘h’, has a special meaning. The IEEE has a document on the matter, (top of page 4) but it’s lacking some nice examples.

First, let’s assume we can ignore “group” addresses so the ‘M’ bit is always 0. The IEEE then consider an address can be of two types (depending on the ‘X’ bit):

  • fist type is a globally administrated address. This type of address is guaranteed unique, assuming people follow the rules and don’t do whatever they want. It’s composed of a 24 or 36 bit OUI, followed by some bits managed by the owner of the OUI. In that case, the ‘h’ digit of the address is always 0, 4, 8 or C.
  • second type is a locally administrated address. There, the IEEE say “do whatever you want, but please identify your address as a locally administrated one”. In that case, the ‘h’ digit of the address is always 2, 6, A or E.

To sum up, for personal projects, it’s perfectly ok to use a nearly randomly generated address, just make sure to force the second hexadecimal digit of the address to be ‘2’. With 60 bits left to pick randomly, the probability of collision is really really low, assuming you properly seed the rand() function of your favorite language :smiley:

As soon as your project has any chance of having a real customer, just contact the IEEE. Getting an OUI36 is reasonably cheap and simple, even for a very small business.

Yup, this 48 <-> 64 mapping doesn’t make sense anymore, specially for manufacturers with an OUI36.

Would it be useful to have ttn give out locally administered DevEUI numbers? This way, these numbers are at least generated in a correct way, and you don’t have the problem of people not knowing that certain bits have to be set in a certain way, or making other mistakes or wrong assumptions that jeopardize the uniqueness of the ID’s. And there is no need to buy a block.

That would be quite convenient, yes, to be able to generate and auto-fill a valid locally administrated DevEUI when declaring a new device.

I’d like the generation of numbers ,except that I also would like to identify my gateways/nodes visually. So if part of the hex number would be generated for me at my TTN account, then I can fill in the last two hex numbers. Or TTN assigns the numbers according to a recognizable scheme. For example;

  • first part is generated by TTN to be guaranteed unique on the network, then
  • gateway number ends with 0x?0 [00…FF] for each gw that you have on your account, and then
  • application 1 ends with 0x?1 [00…FF] for nodes in your first application
  • application 2 ends with 0x?2 [00…FF] for nodes in your second application

The above is, for one account, capable of 256 gateways, 16 applications and 256 nodes per application. Of course for large scale node deployment a second numbering scheme can be used.

Just my thoughts on fully generating a number.

How would you guarantee that, if other devices use an official DevEUI which does not use the same home brewed scheme? Or are you proposing that TTN just reserves 256 × 16 × 256 ids of its official block of EUIs whenever someone registers an account?

All DevEUI’s are stored in TTN’s databases, so TTN should be able to warn when a new device is created on the console with an existing DevEUI. But that would be the official way.
I’m not sure yet what happens if I would just copy over your device public DevEUI and frame counter into a second ‘clone’ device. I think the secret application- and network keys causes wrong data to be rejected.

Let’s assume the other DevEUI is the one that’s valid. When buying off-the-shelf LoRaWAN nodes that come with built-in official EUIs, then any home brewed scheme to generate EUIs should never collide with those official EUIs.

Might be doable, but I doubt it’s worth the effort. Especially if all one gets is nice-looking EUIs.

Just for future reference, one can also have TTN Console generate one for you by clicking the :twisted_rightwards_arrows: icon at the start of the input field:



But see also Generated Device EUI clashes with officially assigned EUIs.

1 Like

For device EUI, I use the ESP32 chip_id - essentially, this is the WiFi MAC address and so should be unique to the board - take a look here:

Just 6 bytes is not enough for an EUI64, so how do you generate the remaining two bytes?

Beware that any id that is unique to the board, is not (at all) automatically suitable as the Device EUI. A DevEUI should at least be unique in the network. See the discussions above and the topics it links to.

And preferably/officially also not be used in nearby LoRaWAN networks that also receive radio packets from the device, and preferably/officially also not clash with any (future) official EUI that is not even related to LoRaWAN.

Hi @arjanvanb, to create a 64-bit address, I use the recommendation to add bytes in the middle.

I think I appreciate the need for a unique address on the network, but I assumed it would effectively be unique when combined with a specific APP EUI.

Can I ask - would there be a case where a node would be live without being tied to an application?

Assuming the handling will not change, today for TTN indeed a DevEUI might only need to be unique within an AppEUI:

However, that might not be true for other networks, which might then try to handle an OTAA Join Request? Of course, chances are low.