Meshtastic-Android/app/src/main/proto/mesh.proto
2020-01-27 14:54:35 -08:00

208 lines
8.4 KiB
Protocol Buffer

syntax = "proto3";
// per https://developers.google.com/protocol-buffers/docs/proto3
package mesh;
option java_package = "com.geeksville.mesh";
option java_outer_classname = "MeshProtos";
/**
MESH RADIO PROTOCOL
Old TODO notes on the mesh radio protocol, merge into real docs below...
for each named group we have a pre-shared key known by all group members and wrapped around the device.
you can only be in one group at a time (FIXME?!)
To join the group we read a qr code with the preshared key and ParamsCodeEnum. that gets sent via
bluetooth to the device. ParamsCodeEnum maps to a set of various radio params (regulatory region,
center freq, SF, bandwidth, bitrate, power etc...) so all members of the mesh can have their radios set the same way.
once in that group, we can talk between 254 node numbers.
to get our node number (and announce our presence in the channel) we pick a random node number and
broadcast as that node with WANT-NODENUM(my globally unique name). If anyone on the channel has
seen someone _else_ using that name within the last 24 hrs(?) they reply with DENY-NODENUM.
Note: we might receive multiple denies. Note: this allows others to speak up for some other node
that might be saving battery right now.
Any time we hear from another node (for any message type), we add that node number to the unpickable
list. To dramatically decrease the odds a node number we request is already used by someone.
If no one denies within TBD seconds, we assume that we have that node number. As long as we keep
talking to folks at least once every 24 hrs, others should remember we have it.
Once we have a node number we can broadcast POSITION-UPDATE(my globally unique name, lat, lon, alt,
amt battery remaining). All receivers will use this to a) update the mapping of who is at what
node nums, b) the time of last rx, c) position. If we haven't heard from that node in a while we
reply to that node (only) with our current POSITION_UPDATE state - so that node (presumably just
rejoined the network) can build a map of all participants.
We will periodically broadcast POSITION-UPDATE as needed based on distance moved or a periodic minimum heartbeat.
If user wants to send a text they can SEND_TEXT(dest user, short text message). Dest user is a
node number, or 0xff for broadcast.
*/
// a gps position
message Position {
double latitude = 1;
double longitude = 2;
int32 altitude = 3;
int32 battery_level = 4; // 0-100
}
// Times are typically not sent over the mesh, but they will be added to any Packet (chain of SubPacket)
// sent to the phone (so the phone can know exact time of reception)
message Time {
uint64 msecs = 1; // msecs since 1970
}
// a data message to forward to an external app (or possibly also be consumed internally in the case of CLEAR_TEXT and CLEAR_READACK
message Data {
enum Type {
/// A message sent from a device outside of the mesh, in a form the mesh does not understand
SIGNAL_OPAQUE = 0; // NOTE: This must be 0, because it is documented in IMeshService.aidl to be so
/// a simple UTF-8 text message, which even the little micros in the mesh can understand and show on their screen
/// eventually in some circumstances even signal might send messages in this form (see below)
CLEAR_TEXT = 1;
/// a message receive acknowledgement, sent in cleartext - allows radio to show user that a message has been read by the recipient, optional
CLEAR_READACK = 2;
/// Not yet used but eventually:
/// SIGNAL_CLEAR_DATA = 3; // Unencrypted at the signal level, relying on the radio crypt only (to keep size small), but contains Signal control data radios don't care about (ie non text)
}
Type typ = 1; // required
bytes payload = 2; // required
}
// Sent from the phone over bluetooth to set the user id for the owner of this node.
// Also sent from nodes to each other when a new node signs on (so all clients can have this info)
message User {
string id = 1; // a globally unique ID string for this user. In the case of Signal that would mean +16504442323
string long_name = 2; // A full name for this user, i.e. "Kevin Hester"
string short_name = 3; // A VERY short name, ideally two characters. Suitable for a tiny OLED screen
}
// Broadcast when a newly powered mesh node wants to find a node num it can use (see document for more
// details)
message WantNodeNum {
// No payload, just its existence is sufficient (desired node num will be in the from field)
}
// Sent to a node which has requested a nodenum when it is told it can't have it
message DenyNodeNum {
}
// A single packet might have a series of SubPacket included
message SubPacket {
oneof variant {
Position position = 1;
Time time = 2;
Data data = 3;
User user = 4;
WantNodeNum want_node = 5;
DenyNodeNum deny_node = 6;
}
}
// A packet sent over our mesh.
// NOTE: this raw payload does not include the from and to addresses, which are stripped off
// and passed into the mesh library code separately.
message MeshPayload {
repeated SubPacket subPackets = 3;
}
// A full packet sent/received over the mesh
message MeshPacket {
int32 from = 1;
int32 to = 2;
MeshPayload payload = 3;
}
// Full settings (center freq, spread factor, pre-shared secret key etc...) needed to configure a radio
message RadioConfig {
// FIXME
// If true, radio should not try to be smart about what packets to queue to the phone
bool keep_all_packets = 100;
// If true, we will try to capture all the packets sent on the mesh, not just the ones destined to our node.
bool promiscuous_mode = 101;
}
/**
The bluetooth to device link:
Old BTLE protocol docs from TODO, merge in above and make real docs...
use protocol buffers, and NanoPB
messages from device to phone:
POSITION_UPDATE (..., time)
TEXT_RECEIVED(from, text, time)
OPAQUE_RECEIVED(from, payload, time) (for signal messages or other applications)
messages from phone to device:
SET_MYID(id, human readable long, human readable short) (send down the unique ID string used for this node, a human readable string shown for that id, and a very short human readable string suitable for oled screen)
SEND_OPAQUE(dest, payload) (for signal messages or other applications)
SEND_TEXT(dest, text)
Get all nodes() (returns list of nodes, with full info, last time seen, loc, battery level etc)
SET_CONFIG (switches device to a new set of radio params and preshared key, drops all existing nodes, force our node to rejoin this new group)
*/
// Full information about a node on the mesh
message NodeInfo {
int32 num = 1; // the node number
User user = 2;
Position position = 4;
Time last_seen = 5;
}
// packets from the radio to the phone will appear on the fromRadio characteristic. It will support
// READ and NOTIFY. When a new packet arrives the device will notify? possibly identify instead?
// it will sit in that descriptor until consumed by the phone, at which point the next item in the FIFO
// will be populated. FIXME
message FromRadio {
// The packet num, used to allow the phone to request missing read packets from the FIFO, see our bluetooth docs
uint32 num = 1;
oneof variant {
MeshPacket packet = 2;
/// Tells the phone what our node number is, can be -1 if we've not yet joined a mesh.
sint32 my_node_num = 3;
/// One packet is sent for each node in the on radio DB
NodeInfo node_info = 4;
}
}
// packets/commands to the radio will be written (reliably) to the toRadio characteristic. Once the
// write completes the phone can assume it is handled.
message ToRadio {
// If sent to the radio, the radio will send the phone its full node DB (NodeInfo records)
// Used to populate network info the first time the phone connects to the radio
message WantNodes {
// Empty
}
oneof variant {
MeshPacket packet = 1; // send this packet on the mesh
//
// Rare operations
//
/// phone wants radio to send full node db to the phone, This is typically the first packet sent
/// to the radio when the phone gets a bluetooth connection.
/// The radio will respond by sending back a FromRadio.my_node_num and a series of FromRadio.node_info
WantNodes want_nodes = 100;
RadioConfig set_radio = 101; // set the radio provisioning for this node
User set_owner = 102; // Set the owner for this node
}
}