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
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
openapi: 3.0.0
info:
title: IQEngine Plugins Open Interface API
description: |
The plugins API is a unified open interface for managing the processing of RF recordings and corresponding dataflow,
with the goal of standardizing inputs and outputs to RF processing functions for easy of interoperability and to combat vendor lockin.
The plugins API is planned to be converted to an OpenAPI spec once its further refined. It will use JSON for the fields.
version: 0.0.1
servers:
- url: /plugins
paths:
/:
get:
summary: Returns the list of RF Functions available at this ip/host, as a list of strings, must match functionName below.
responses:
'200':
description: 'OK'
content:
application/json:
schema:
type: array
items:
type: string
minItems: 1
maxItems: 1000
uniqueItems: true
/{functionName}:
get:
summary: Gets the RF Function's custom params in the form of a JSON schema that is only 1 layer deep.
parameters:
- in: path
name: functionName
schema:
type: string
required: true
description: Name of RF Function
responses:
'400':
description: Bad request. RF Function does not exist.
'200':
description: 'OK'
content:
application/json:
schema:
type: object
required:
- custom_params
properties:
max_inputs: # max sets of IQ as input
type: integer
default: 1 # note that default documents behavior when a field is absent
minimum: 0 # a siggen/tx wouldn't have IQ on the input side, only custom params
max_outputs: # max sets of IQ as output
type: integer
default: 1
minimum: 0
custom_params: # This object is essentially just a json schema that is at most 1 layer deep
# e.g.:
# {'param1': {'title': 'Param1', 'default': 1, 'type': 'integer'},
# 'param2': {'title': 'Param2', 'default': 'test2', 'type': 'string'},
# 'param3': {'title': 'Param3', 'default': 5.67, 'type': 'number'}}
type: object
minProperties: 1
maxProperties: 100
additionalProperties:
type: object
properties:
title:
type: string
type:
type: string
# anyOf:
# # For now this is all we'll support
# - type: string
# - type: number # (float)
# - type: integer
# - type: boolean
default:
type: string
post:
summary: Run the RF Function, using the provided IQ samples and params
parameters:
- in: path
name: functionName
schema:
type: string
required: true
description: Name of RF Function
requestBody:
description: IQ samples and parameters needed to run the RF Function
required: true
content:
application/json:
schema:
type: object
# Provide either samples (IQ samples) or samples_pointer (pointer to blob storage)
oneOf:
- required:
- required:
properties:
samples_b64:
type: array # list of IQ samples, most functions will just have 1
items:
$ref: '#/components/schemas/samples_b64'
samples_cloud:
type: array # list of IQ samples, most functions will just have 1
items:
$ref: '#/components/schemas/samples_cloud'
# Custom params
additionalProperties:
anyOf:
- type: string
- type: number # (float)
- type: integer
- type: boolean
responses:
'400':
description: Bad request. RF Function does not exist.
content:
application/json:
schema:
type: object
properties:
details:
type: string
'401':
description: Bad request. Missing a required param.
content:
application/json:
schema:
type: object
properties:
details:
type: string
'200':
description: 'OK'
content:
application/json:
schema:
# The following is taken from SigMF's annotations schema (currently a subset of it)
type: object
properties:
data_output:
type: array # list of IQ samples, most functions will just have 1
items:
$ref: '#/components/schemas/samples_b64'
samples_cloud:
type: array # list of IQ samples, most functions will just have 1
items:
$ref: '#/components/schemas/samples_cloud'
annotations:
description: See https://github.com/sigmf/SigMF/blob/sigmf-v1.x/sigmf-spec.md#annotations-array
type: array
items:
$ref: '#/components/schemas/annotation'
# A way to specify properties that are reused, or simply too large to have look good within parameters/responses objects
components:
schemas:
samples_b64: # samples directly within the JSON request/response
type: object
required:
- samples
- data_type
properties:
samples:
# IQ samples, as a base64 encoded string, MIME type will indicate the datatype of the underlying bytes
type: string
format: byte # base64-encoded characters
data_type: # uses MIME types, plus custom types we are adding for IQ, based on SigMF
$ref: '#/components/schemas/data_type'
sample_rate: # in case sample rate changed
type: number
default: 1
center_freq: # in case center freq changed
type: number
default: 0
samples_cloud: # a pointer to IQ samples in cloud storage
type: object
required:
- account_name
- container_name
- file_path
- data_type
properties:
account_name:
type: string
container_name:
type: string
file_path:
type: string
sas_token:
type: string
byte_offset:
type: integer
default: 0
byte_length: # default is to grab all of the samples in the file
type: integer
data_type:
$ref: '#/components/schemas/data_type'
sample_rate:
type: number
default: 1
center_freq:
type: number
default: 0
data_type:
type: string
enum:
- iq/ci8_le # from SigMF
- iq/ci16_le # from SigMF
- iq/cf32_le # from SigMF
- image/png
- audio/wav
- application/octet-stream # eg application/octet-stream
- text/plain # e.g. for representing an ASCII message or speech to text output
annotation:
type: object
required:
- core:sample_start
- core:sample_count
properties:
core:comment:
default: ''
description: A human-readable comment
type: string
core:freq_lower_edge:
description: The frequency (Hz) of the lower edge of the feature described by this annotation.
type: number
minimum: -1.7976931348623157E+308
maximum: 1.7976931348623157E+308
core:freq_upper_edge:
description: The frequency (Hz) of the upper edge of the feature described by this annotation.
type: number
minimum: -1.7976931348623157E+308
maximum: 1.7976931348623157E+308
core:generator:
description: Human-readable name of the entity that created this annotation.
type: string
core:label:
description: A short form human/machine-readable label for the annotation. CAN BE USED TO LABEL CLASSIFIER OUTPUT
type: string
core:sample_count:
description: The number of samples that this Segment applies to.
type: integer
minimum: 0
maximum: 18446744073709551615
core:sample_start:
default: 0
description: The sample index at which this Segment takes effect
minimum: 0
maximum: 18446744073709551615
type: integer
core:uuid:
description: RFC-4122 unique identifier.
format: uuid
type: string
additionalProperties: true