--- id: protobuf-api title: Protobuf API Reference slug: /protobufs/api sidebar_label: Protobuf Reference --- ## admin.proto ### AdminMessage :::note `message` description This message is handled by the Admin module and is responsible for all settings/channel read/write operations. This message is used to do settings operations to both remote AND local nodes. (Prior to 1.2 these operations were done via special ToRadio operations) ::: | Field | Type | Description | | ----- | ---- | ----------- | | [**oneof**](https://developers.google.com/protocol-buffers/docs/proto3#oneof) payload_variant.get_channel_request | uint32 | Send the specified channel in the response to this message NOTE: This field is sent with the channel index + 1 (to ensure we never try to send 'zero' - which protobufs treats as not present) | | [**oneof**](https://developers.google.com/protocol-buffers/docs/proto3#oneof) payload_variant.get_channel_response | [`Channel`](#channel) | TODO: REPLACE | | [**oneof**](https://developers.google.com/protocol-buffers/docs/proto3#oneof) payload_variant.get_owner_request | bool | Send the current owner data in the response to this message. | | [**oneof**](https://developers.google.com/protocol-buffers/docs/proto3#oneof) payload_variant.get_owner_response | [`User`](#user) | TODO: REPLACE | | [**oneof**](https://developers.google.com/protocol-buffers/docs/proto3#oneof) payload_variant.get_config_request | [`AdminMessage.ConfigType`](#adminmessageconfigtype) | Ask for the following config data to be sent | | [**oneof**](https://developers.google.com/protocol-buffers/docs/proto3#oneof) payload_variant.get_config_response | [`Config`](#config) | Send the current Config in the response to this message. | | [**oneof**](https://developers.google.com/protocol-buffers/docs/proto3#oneof) payload_variant.get_module_config_request | [`AdminMessage.ModuleConfigType`](#adminmessagemoduleconfigtype) | Ask for the following config data to be sent | | [**oneof**](https://developers.google.com/protocol-buffers/docs/proto3#oneof) payload_variant.get_module_config_response | [`ModuleConfig`](#moduleconfig) | Send the current Config in the response to this message. | | [**oneof**](https://developers.google.com/protocol-buffers/docs/proto3#oneof) payload_variant.get_canned_message_module_messages_request | bool | Get the Canned Message Module messages in the response to this message. | | [**oneof**](https://developers.google.com/protocol-buffers/docs/proto3#oneof) payload_variant.get_canned_message_module_messages_response | string | Get the Canned Message Module messages in the response to this message. | | [**oneof**](https://developers.google.com/protocol-buffers/docs/proto3#oneof) payload_variant.get_device_metadata_request | bool | Request the node to send device metadata (firmware, protobuf version, etc) | | [**oneof**](https://developers.google.com/protocol-buffers/docs/proto3#oneof) payload_variant.get_device_metadata_response | [`DeviceMetadata`](#devicemetadata) | Device metadata response | | [**oneof**](https://developers.google.com/protocol-buffers/docs/proto3#oneof) payload_variant.set_owner | [`User`](#user) | Set the owner for this node | | [**oneof**](https://developers.google.com/protocol-buffers/docs/proto3#oneof) payload_variant.set_channel | [`Channel`](#channel) | Set channels (using the new API). A special channel is the "primary channel". The other records are secondary channels. Note: only one channel can be marked as primary. If the client sets a particular channel to be primary, the previous channel will be set to SECONDARY automatically. | | [**oneof**](https://developers.google.com/protocol-buffers/docs/proto3#oneof) payload_variant.set_config | [`Config`](#config) | Set the current Config | | [**oneof**](https://developers.google.com/protocol-buffers/docs/proto3#oneof) payload_variant.set_module_config | [`ModuleConfig`](#moduleconfig) | Set the current Config | | [**oneof**](https://developers.google.com/protocol-buffers/docs/proto3#oneof) payload_variant.set_canned_message_module_messages | string | Set the Canned Message Module messages text. | | [**oneof**](https://developers.google.com/protocol-buffers/docs/proto3#oneof) payload_variant.confirm_set_config | bool | Sent immediatly after a config change has been sent to ensure comms, if this is not recieved, the config will be reverted after 10 mins | | [**oneof**](https://developers.google.com/protocol-buffers/docs/proto3#oneof) payload_variant.confirm_set_module_config | bool | Sent immediatly after a config change has been sent to ensure comms, if this is not recieved, the config will be reverted after 10 mins | | [**oneof**](https://developers.google.com/protocol-buffers/docs/proto3#oneof) payload_variant.confirm_set_channel | bool | Setting channels/radio config remotely carries the risk that you might send an invalid config and the radio never talks to your mesh again. Therefore if setting either of these properties remotely, you must send a confirm_xxx message within 10 minutes. If you fail to do so, the radio will assume loss of comms and revert your changes. These messages are optional when changing the local node. | | [**oneof**](https://developers.google.com/protocol-buffers/docs/proto3#oneof) payload_variant.confirm_set_radio | bool | TODO: REPLACE | | [**oneof**](https://developers.google.com/protocol-buffers/docs/proto3#oneof) payload_variant.reboot_ota_seconds | int32 | Tell the node to reboot into the OTA Firmware in this many seconds (or <0 to cancel reboot) Only Implemented for ESP32 Devices. This needs to be issued to send a new main firmware via bluetooth. | | [**oneof**](https://developers.google.com/protocol-buffers/docs/proto3#oneof) payload_variant.exit_simulator | bool | This message is only supported for the simulator porduino build. If received the simulator will exit successfully. | | [**oneof**](https://developers.google.com/protocol-buffers/docs/proto3#oneof) payload_variant.reboot_seconds | int32 | Tell the node to reboot in this many seconds (or <0 to cancel reboot) | | [**oneof**](https://developers.google.com/protocol-buffers/docs/proto3#oneof) payload_variant.shutdown_seconds | int32 | Tell the node to shutdown in this many seconds (or <0 to cancel shutdown) | | [**oneof**](https://developers.google.com/protocol-buffers/docs/proto3#oneof) payload_variant.factory_reset | int32 | Tell the node to factory reset, all device settings will be returned to factory defaults. | | [**oneof**](https://developers.google.com/protocol-buffers/docs/proto3#oneof) payload_variant.nodedb_reset | int32 | Tell the node to reset the nodedb. | ### AdminMessage.ConfigType :::note `enum` description TODO: REPLACE ::: | Name | Number | Description | | ---- | ------ | ----------- | | `DEVICE_CONFIG` | `0` | TODO: REPLACE | | `POSITION_CONFIG` | `1` | TODO: REPLACE | | `POWER_CONFIG` | `2` | TODO: REPLACE | | `NETWORK_CONFIG` | `3` | TODO: REPLACE | | `DISPLAY_CONFIG` | `4` | TODO: REPLACE | | `LORA_CONFIG` | `5` | TODO: REPLACE | | `BLUETOOTH_CONFIG` | `6` | TODO: REPLACE | ### AdminMessage.ModuleConfigType :::note `enum` description TODO: REPLACE ::: | Name | Number | Description | | ---- | ------ | ----------- | | `MQTT_CONFIG` | `0` | TODO: REPLACE | | `SERIAL_CONFIG` | `1` | TODO: REPLACE | | `EXTNOTIF_CONFIG` | `2` | TODO: REPLACE | | `STOREFORWARD_CONFIG` | `3` | TODO: REPLACE | | `RANGETEST_CONFIG` | `4` | TODO: REPLACE | | `TELEMETRY_CONFIG` | `5` | TODO: REPLACE | | `CANNEDMSG_CONFIG` | `6` | TODO: REPLACE | ## apponly.proto ### ChannelSet :::note `message` description This is the most compact possible representation for a set of channels. It includes only one PRIMARY channel (which must be first) and any SECONDARY channels. No DISABLED channels are included. This abstraction is used only on the the 'app side' of the world (ie python, javascript and android etc) to show a group of Channels as a (long) URL ::: | Field | Type | Description | | ----- | ---- | ----------- | | settings | [`ChannelSettings`](#channelsettings) | Channel list with settings | | lora_config | [`Config.LoRaConfig`](#configloraconfig) | LoRa config | ## cannedmessages.proto ### CannedMessageModuleConfig :::note `message` description Canned message module configuration. ::: | Field | Type | Description | | ----- | ---- | ----------- | | messages | string | Predefined messages for canned message module separated by '|' characters. | ## channel.proto ### Channel :::note `message` description A pair of a channel number, mode and the (sharable) settings for that channel ::: | Field | Type | Description | | ----- | ---- | ----------- | | index | int32 | The index of this channel in the channel table (from 0 to MAX_NUM_CHANNELS-1) (Someday - not currently implemented) An index of -1 could be used to mean "set by name", in which case the target node will find and set the channel by settings.name. | | settings | [`ChannelSettings`](#channelsettings) | The new settings, or NULL to disable that channel | | role | [`Channel.Role`](#channelrole) | TODO: REPLACE | ### ChannelSettings :::note `message` description Full settings (center freq, spread factor, pre-shared secret key etc...) needed to configure a radio for speaking on a particular channel This information can be encoded as a QRcode/url so that other users can configure their radio to join the same channel. A note about how channel names are shown to users: channelname-Xy poundsymbol is a prefix used to indicate this is a channel name (idea from @professr). Where X is a letter from A-Z (base 26) representing a hash of the PSK for this channel - so that if the user changes anything about the channel (which does force a new PSK) this letter will also change. Thus preventing user confusion if two friends try to type in a channel name of "BobsChan" and then can't talk because their PSKs will be different. The PSK is hashed into this letter by "0x41 + [xor all bytes of the psk ] modulo 26" This also allows the option of someday if people have the PSK off (zero), the users COULD type in a channel name and be able to talk. Y is a lower case letter from a-z that represents the channel 'speed' settings (for some future definition of speed) FIXME: Add description of multi-channel support and how primary vs secondary channels are used. FIXME: explain how apps use channels for security. explain how remote settings and remote gpio are managed as an example ::: | Field | Type | Description | | ----- | ---- | ----------- | | channel_num | uint32 | Deprecated in favor of LoraConfig.channel_num | | psk | bytes | A simple pre-shared key for now for crypto. Must be either 0 bytes (no crypto), 16 bytes (AES128), or 32 bytes (AES256). A special shorthand is used for 1 byte long psks. These psks should be treated as only minimally secure, because they are listed in this source code. Those bytes are mapped using the following scheme: `0` = No crypto `1` = The special "default" channel key: {0xd4, 0xf1, 0xbb, 0x3a, 0x20, 0x29, 0x07, 0x59, 0xf0, 0xbc, 0xff, 0xab, 0xcf, 0x4e, 0x69, 0xbf} `2` through 10 = The default channel key, except with 1 through 9 added to the last byte. Shown to user as simple1 through 10 | | name | string | A SHORT name that will be packed into the URL. Less than 12 bytes. Something for end users to call the channel If this is the empty string it is assumed that this channel is the special (minimally secure) "Default"channel. In user interfaces it should be rendered as a local language translation of "X". For channel_num hashing empty string will be treated as "X". Where "X" is selected based on the English words listed above for ModemPreset | | id | fixed32 | Used to construct a globally unique channel ID. The full globally unique ID will be: "name.id" where ID is shown as base36. Assuming that the number of meshtastic users is below 20K (true for a long time) the chance of this 64 bit random number colliding with anyone else is super low. And the penalty for collision is low as well, it just means that anyone trying to decrypt channel messages might need to try multiple candidate channels. Any time a non wire compatible change is made to a channel, this field should be regenerated. There are a small number of 'special' globally known (and fairly) insecure standard channels. Those channels do not have a numeric id included in the settings, but instead it is pulled from a table of well known IDs. (see Well Known Channels FIXME) | | uplink_enabled | bool | If true, messages on the mesh will be sent to the *public* internet by any gateway ndoe | | downlink_enabled | bool | If true, messages seen on the internet will be forwarded to the local mesh. | ### Channel.Role :::note `enum` description How this channel is being used (or not). Note: this field is an enum to give us options for the future. In particular, someday we might make a 'SCANNING' option. SCANNING channels could have different frequencies and the radio would occasionally check that freq to see if anything is being transmitted. For devices that have multiple physical radios attached, we could keep multiple PRIMARY/SCANNING channels active at once to allow cross band routing as needed. If a device has only a single radio (the common case) only one channel can be PRIMARY at a time (but any number of SECONDARY channels can't be sent received on that common frequency) ::: | Name | Number | Description | | ---- | ------ | ----------- | | `DISABLED` | `0` | This channel is not in use right now | | `PRIMARY` | `1` | This channel is used to set the frequency for the radio - all other enabled channels must be SECONDARY | | `SECONDARY` | `2` | Secondary channels are only used for encryption/decryption/authentication purposes. Their radio settings (freq etc) are ignored, only psk is used. | ## config.proto ### Config | Field | Type | Description | | ----- | ---- | ----------- | | [**oneof**](https://developers.google.com/protocol-buffers/docs/proto3#oneof) payload_variant.device | [`Config.DeviceConfig`](#configdeviceconfig) | none | | [**oneof**](https://developers.google.com/protocol-buffers/docs/proto3#oneof) payload_variant.position | [`Config.PositionConfig`](#configpositionconfig) | none | | [**oneof**](https://developers.google.com/protocol-buffers/docs/proto3#oneof) payload_variant.power | [`Config.PowerConfig`](#configpowerconfig) | none | | [**oneof**](https://developers.google.com/protocol-buffers/docs/proto3#oneof) payload_variant.network | [`Config.NetworkConfig`](#confignetworkconfig) | none | | [**oneof**](https://developers.google.com/protocol-buffers/docs/proto3#oneof) payload_variant.display | [`Config.DisplayConfig`](#configdisplayconfig) | none | | [**oneof**](https://developers.google.com/protocol-buffers/docs/proto3#oneof) payload_variant.lora | [`Config.LoRaConfig`](#configloraconfig) | none | | [**oneof**](https://developers.google.com/protocol-buffers/docs/proto3#oneof) payload_variant.bluetooth | [`Config.BluetoothConfig`](#configbluetoothconfig) | none | ### Config.BluetoothConfig | Field | Type | Description | | ----- | ---- | ----------- | | enabled | bool | Enable Bluetooth on the device | | mode | [`Config.BluetoothConfig.PairingMode`](#configbluetoothconfigpairingmode) | Determines the pairing strategy for the device | | fixed_pin | uint32 | Specified pin for PairingMode.FixedPin | ### Config.DeviceConfig :::note `message` description Configuration ::: | Field | Type | Description | | ----- | ---- | ----------- | | role | [`Config.DeviceConfig.Role`](#configdeviceconfigrole) | Sets the role of node | | serial_enabled | bool | Disabling this will disable the SerialConsole by not initilizing the StreamAPI | | debug_log_enabled | bool | By default we turn off logging as soon as an API client connects (to keep shared serial link quiet). Set this to true to leave the debug log outputting even when API is active. | ### Config.DisplayConfig :::note `message` description Display Config ::: | Field | Type | Description | | ----- | ---- | ----------- | | screen_on_secs | uint32 | Number of seconds the screen stays on after pressing the user button or receiving a message 0 for default of one minute MAXUINT for always on | | gps_format | [`Config.DisplayConfig.GpsCoordinateFormat`](#configdisplayconfiggpscoordinateformat) | How the GPS coordinates are formatted on the OLED screen. | | auto_screen_carousel_secs | uint32 | Automatically toggles to the next page on the screen like a carousel, based the specified interval in seconds. Potentially useful for devices without user buttons. | | compass_north_top | bool | If this is set, the displayed compass will always point north. if unset, the old behaviour (top of display is heading direction) is used. | | flip_screen | bool | Flip screen vertically, for cases that mount the screen upside down | | units | [`Config.DisplayConfig.DisplayUnits`](#configdisplayconfigdisplayunits) | Perferred display units | ### Config.LoRaConfig :::note `message` description Lora Config ::: | Field | Type | Description | | ----- | ---- | ----------- | | use_preset | bool | When enabled, the `modem_preset` fields will be adheared to, else the `bandwidth`/`spread_factor`/`coding_rate` will be taked from their respective manually defined fields | | modem_preset | [`Config.LoRaConfig.ModemPreset`](#configloraconfigmodempreset) | Either modem_config or bandwidth/spreading/coding will be specified - NOT BOTH. As a heuristic: If bandwidth is specified, do not use modem_config. Because protobufs take ZERO space when the value is zero this works out nicely. This value is replaced by bandwidth/spread_factor/coding_rate. If you'd like to experiment with other options add them to MeshRadio.cpp in the device code. | | bandwidth | uint32 | Bandwidth in MHz Certain bandwidth numbers are 'special' and will be converted to the appropriate floating point value: 31 -> 31.25MHz | | spread_factor | uint32 | A number from 7 to 12. Indicates number of chirps per symbol as 1<