-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathplugin.proto
More file actions
229 lines (197 loc) · 7.71 KB
/
Copy pathplugin.proto
File metadata and controls
229 lines (197 loc) · 7.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
// RepeaterTastic Plugin API v1.
//
// A plugin is a separate process that connects to RepeaterTastic's PluginHost: over a Unix socket
// when RepeaterTastic starts it (managed), or over TCP when it runs elsewhere (attached). Every call
// carries the plugin's token in the "authorization" metadata ("Bearer <token>"). The Session stream
// must be opened first; the other calls work while it is open and are checked against the
// permissions the operator granted.
syntax = "proto3";
package repeatertastic.plugin.v1;
option go_package = "github.com/ScotMesh/RepeaterTastic/api/plugin/v1;pluginv1";
service PluginHost {
// Session: the plugin sends Hello first; the host answers Welcome (or closes with an error), then
// streams events the plugin is allowed to see. The plugin sends status, logs and heartbeats.
// Ending the stream means the plugin has stopped.
rpc Session(stream PluginMessage) returns (stream HostMessage);
rpc ListRadios(ListRadiosRequest) returns (ListRadiosResponse);
// nodes.read
rpc ListNodes(ListNodesRequest) returns (ListNodesResponse);
// messages.send: text from a radio's relay persona, within the plugin's send budget.
rpc SendText(SendTextRequest) returns (SendResponse);
// traceroute.send: from the identity chosen in the plugin's "identities" settings on that radio
// (the relay persona when none is), within the plugin's send budget.
rpc Traceroute(TracerouteRequest) returns (SendResponse);
}
// ------------------------------------------------------------------------------------ session
message PluginMessage {
oneof msg {
Hello hello = 1;
Status status = 2;
LogLine log = 3;
Heartbeat heartbeat = 4;
PanelData panel = 5;
}
}
message HostMessage {
oneof msg {
Welcome welcome = 1;
PacketEvent packet = 2;
NodeEvent node = 3;
TextMessageEvent text = 4;
TracerouteEvent traceroute = 5;
SettingsChanged settings = 6;
Stop stop = 7;
PanelAction action = 8;
}
}
message Hello {
string plugin_id = 1;
uint32 api_version = 2; // 1
string plugin_version = 3;
// An attached plugin (no bundle) may send its plugin.yaml so the GUI can show its name, logo URL,
// permissions and settings form. Managed plugins leave it empty: their bundle has one.
string manifest_yaml = 4;
}
message Welcome {
uint32 api_version = 1;
string host_version = 2;
repeated string permissions = 3; // granted
string settings_json = 4; // the plugin's settings, secrets included
repeated Radio radios = 5;
string data_dir = 6; // a folder the plugin may write to (managed plugins)
}
message Status {
string summary = 1; // one line shown on the plugin's card, e.g. "API connected"
map<string, string> fields = 2; // shown as label: value pairs
string state = 3; // "ok", "warning" or "error"
}
message LogLine {
string level = 1; // debug, info, warn, error
string message = 2;
}
message Heartbeat {}
// PanelData: JSON for the plugin's own GUI panel, if it has one. The panel receives the latest
// value (window message {type: "data", data}) whenever it changes and when it opens.
message PanelData {
string json = 1;
}
// PanelAction: the plugin's panel posted {type: "action", name, payload} to the GUI.
message PanelAction {
string name = 1;
string payload_json = 2;
}
message SettingsChanged {
string settings_json = 1;
}
message Stop {
string reason = 1;
}
// ------------------------------------------------------------------------------------ model
message Radio {
string id = 1; // "main", "mf", ...
string name = 2;
string region = 3; // "EU_868"
string preset = 4; // "LONG_FAST"
string preset_name = 5; // "LongFast"
double frequency_mhz = 6;
bool connected = 7;
Identity relay = 8; // the radio's relay persona
repeated Identity identities = 9; // every identity on the radio, the relay persona first
}
message Identity {
string node_id = 1; // "!a1c40e07"
uint32 node_num = 2;
string long_name = 3;
string short_name = 4;
string radio_id = 5;
}
message Node {
uint32 node_num = 1;
string node_id = 2;
string radio_id = 3;
bytes user = 4; // meshtastic.User protobuf, when known
bytes position = 5; // meshtastic.Position protobuf, when known
bytes device_metrics = 6; // meshtastic.DeviceMetrics protobuf, when known
int64 last_heard_ms = 7;
float snr = 8;
int32 rssi = 9;
int32 hops_away = 10; // -1 unknown
bool via_mqtt = 11;
bool local = 12; // one of RepeaterTastic's own identities
}
// ------------------------------------------------------------------------------------ events
// PacketEvent: a packet a radio received or transmitted (packets.read).
message PacketEvent {
string radio_id = 1;
string direction = 2; // "rx" or "tx"
// How RepeaterTastic handled it. rx: heard (decoded, not for us), delivered (to one of our
// identities), relayed, dup (seen before), echo (our own packet repeated back), legacy
// (pre-2.3 firmware, ignored), undecryptable, bad. tx: ours, relayed.
string kind = 3;
// meshtastic.MeshPacket protobuf. Decoded (payload variant "decoded") when a channel or PKI key
// this radio holds could read it, otherwise encrypted exactly as heard. rx_time, rx_snr,
// rx_rssi, hop_limit, hop_start, via_mqtt, relay_node and next_hop are filled.
bytes mesh_packet = 4;
bool decoded = 5;
uint32 channel_hash = 6; // the on-air channel hash (0 for a PKI DM)
string channel_name = 7; // the channel it decoded on, "PKI" for a DM, "" when undecoded
int64 time_ms = 8;
// The node that reports this packet: the radio's relay persona.
uint32 reporter_node_num = 9;
// The channel's index on the relay persona (0-7), or -1 when the relay persona doesn't hold
// the channel. When it is set, mesh_packet.channel is that index; otherwise it is the on-air hash.
int32 relay_channel_index = 10;
// Every identity on this radio that would hear the packet as a node does: those holding the
// channel (with its index on each), or the recipient of a DM (index 0). Empty when undecoded.
repeated ChannelHolder holders = 11;
}
message ChannelHolder {
uint32 node_num = 1;
uint32 channel_index = 2;
}
message NodeEvent {
Node node = 1;
}
// TextMessageEvent: a text message a radio's relay persona received or sent (messages.read).
message TextMessageEvent {
string radio_id = 1;
string identity_node_id = 2;
uint32 from = 3;
uint32 to = 4;
uint32 channel = 5; // channel index on the identity; 0 for DMs
bool direct = 6;
string text = 7;
uint32 packet_id = 8;
int64 time_ms = 9;
string direction = 10; // "in" or "out"
}
message TracerouteEvent {
string radio_id = 1;
string identity_node_id = 2;
string target_node_id = 3;
repeated string route = 4;
repeated double snr_towards = 5;
repeated string route_back = 6;
repeated double snr_back = 7;
}
// ------------------------------------------------------------------------------------ calls
message ListRadiosRequest {}
message ListRadiosResponse { repeated Radio radios = 1; }
message ListNodesRequest { string radio_id = 1; } // "" = every radio
message ListNodesResponse { repeated Node nodes = 1; }
message SendTextRequest {
string radio_id = 1; // "" = the main radio
string to = 2; // "!a1c40e07" for a DM, "" for a channel
uint32 channel = 3; // channel index on the relay persona
string text = 4;
bool want_ack = 5;
}
message TracerouteRequest {
string radio_id = 1; // "" = the main radio
string target = 2; // "!a1c40e07"
// "" = the chosen identity (or the relay persona). Anything else must be that identity.
string from = 3;
}
message SendResponse {
uint32 packet_id = 1;
}