diff options
| author | Noah Stride <[email protected]> | 2024-02-02 19:51:25 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2024-02-02 09:51:25 -1000 |
| commit | ffcb5db042e1f74b93020a9e840704eb9984913c (patch) | |
| tree | 2ee157217aa958ff6195a6aaa3e4ec968e8c62d9 /node_id.go | |
| parent | 463760ccf1cb99f387f5bf99ed83e31772744671 (diff) | |
Support for generating random NodeIDs and deriving Short/Long names (#2)
* Super rough initial subscription to channels and sending node info
* Very ugly hacky FromRadio subscription
* Add more TODOs :weary:
* Add log message before we try to broadcast NodeInfo
* Add basic positioning broadcasting
* demo sending message from consumer
* Use const for BroadcastNodeID
* Config validation and defaults
* Tidy up examples/TODOs
* Tidy up example
* Handle position and devicetelemetry updates
* Fix dodgy merge
* Allow configuring interval for nodeinfo/position seperately
* Make broadcasted position configurable
* Add MQTTProtoTopic constant rather than modifying topic root
* Add Long/Short generation from NodeID
* Mimic Meshtastic source more closely
* Use generated Long/Short when not specified
* Add TestRandomNodeID
* Generate NodeID above the threshold
Diffstat (limited to 'node_id.go')
| -rw-r--r-- | node_id.go | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/node_id.go b/node_id.go new file mode 100644 index 0000000..5e89145 --- /dev/null +++ b/node_id.go @@ -0,0 +1,77 @@ +package meshtastic + +import ( + "crypto/rand" + "encoding/binary" + "fmt" + "math" + "math/big" +) + +// NodeID holds the node identifier. This is a uint32 value which uniquely identifies a node within a mesh. +type NodeID uint32 + +const ( + // BroadcastNodeID is the special NodeID used when broadcasting a packet to a channel. + BroadcastNodeID NodeID = math.MaxUint32 + // ReservedNodeIDThreshold is the threshold at which NodeIDs are considered reserved. Random NodeIDs should not + // be generated below this threshold. + // Source: https://github.com/meshtastic/firmware/blob/d1ea58975755e146457a8345065e4ca357555275/src/mesh/NodeDB.cpp#L461 + reservedNodeIDThreshold NodeID = 4 +) + +// Uint32 returns the underlying uint32 value of the NodeID. +func (n NodeID) Uint32() uint32 { + return uint32(n) +} + +// String converts the NodeID to a hex formatted string. +// This is typically how NodeIDs are displayed in Meshtastic UIs. +func (n NodeID) String() string { + return fmt.Sprintf("!%08x", uint32(n)) +} + +// Bytes converts the NodeID to a byte slice +func (n NodeID) Bytes() []byte { + bytes := make([]byte, 4) // uint32 is 4 bytes + binary.BigEndian.PutUint32(bytes, n.Uint32()) + return bytes +} + +// DefaultLongName returns the default long node name based on the NodeID. +// Source: https://github.com/meshtastic/firmware/blob/d1ea58975755e146457a8345065e4ca357555275/src/mesh/NodeDB.cpp#L382 +func (n NodeID) DefaultLongName() string { + bytes := make([]byte, 4) // uint32 is 4 bytes + binary.BigEndian.PutUint32(bytes, n.Uint32()) + return fmt.Sprintf("Meshtastic %04x", bytes[2:]) +} + +// DefaultShortName returns the default short node name based on the NodeID. +// Last two bytes of the NodeID represented in hex. +// Source: https://github.com/meshtastic/firmware/blob/d1ea58975755e146457a8345065e4ca357555275/src/mesh/NodeDB.cpp#L382 +func (n NodeID) DefaultShortName() string { + bytes := make([]byte, 4) // uint32 is 4 bytes + binary.BigEndian.PutUint32(bytes, n.Uint32()) + return fmt.Sprintf("%04x", bytes[2:]) +} + +// RandomNodeID returns a randomised NodeID. +// It's recommended to call this the first time a node is started and persist the result. +// +// Hardware meshtastic nodes first try a NodeID of the last four bytes of the BLE MAC address. If that ID is already in +// use or invalid, a random NodeID is generated. +// Source: https://github.com/meshtastic/firmware/blob/d1ea58975755e146457a8345065e4ca357555275/src/mesh/NodeDB.cpp#L466 +func RandomNodeID() (NodeID, error) { + // Generates a random uint32 between reservedNodeIDThreshold and math.MaxUint32 + randomInt, err := rand.Int( + rand.Reader, + big.NewInt( + int64(math.MaxUint32-reservedNodeIDThreshold.Uint32()), + ), + ) + if err != nil { + return NodeID(0), fmt.Errorf("reading entropy: %w", err) + } + r := uint32(randomInt.Uint64()) + reservedNodeIDThreshold.Uint32() + return NodeID(r), nil +} |
