diff --git a/swagger/sdrangel/examples/Readme.md b/swagger/sdrangel/examples/Readme.md
index e5eb73462..c3b899583 100644
--- a/swagger/sdrangel/examples/Readme.md
+++ b/swagger/sdrangel/examples/Readme.md
@@ -10,9 +10,9 @@ Adds a channel to a device set specifying device set index and channel type.
- URI: `/sdrangel/deviceset/{deviceSetIndex}/channel`
- HTTP method: `POST`
-
devicesets_config.py
+config.py
-Example of building an entire configuration with 3 device sets using presets to configure each one of the device sets then start streaming on all of them.
+Configure a SDRangel instance with a sequence of API calls defined as a list in a JSON file. See `test.json` for an example.
It uses the following APIs:
diff --git a/swagger/sdrangel/examples/config.py b/swagger/sdrangel/examples/config.py
new file mode 100755
index 000000000..d59e8853a
--- /dev/null
+++ b/swagger/sdrangel/examples/config.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python3
+
+import requests, traceback, sys, json
+from optparse import OptionParser
+
+base_url = "http://127.0.0.1:8091/sdrangel"
+
+# commands list in JSON file. Each command is a list:
+# - URL suffix (API function)
+# - HTTP method (GET, PATCH, POST, PUT, DELETE)
+# - Params as key:value pairs or None if unused
+# - JSON body or None if unused
+# - Descriptive message fragment
+
+requests_methods = {
+ "GET": requests.get,
+ "PATCH": requests.patch,
+ "POST": requests.post,
+ "PUT": requests.put,
+ "DELETE": requests.delete
+}
+
+# ======================================================================
+def getInputOptions():
+
+ parser = OptionParser(usage="usage: %%prog [-t]\n")
+ parser.add_option("-a", "--address", dest="address", help="address and port", metavar="ADDRESS", type="string")
+ parser.add_option("-j", "--json-file", dest="json_file", help="JSON file containing commands", metavar="FILE", type="string")
+
+ (options, args) = parser.parse_args()
+
+ if (options.address == None):
+ options.address = "127.0.0.1:8091"
+
+ return options
+
+# ======================================================================
+def main():
+ try:
+ options = getInputOptions()
+
+ global base_url
+ base_url = "http://%s/sdrangel" % options.address
+
+ with open(options.json_file) as json_file:
+ commands = json.load(json_file)
+ for command in commands:
+ url = base_url + command[0]
+ method = requests_methods.get(command[1], None)
+ if method is not None:
+ r = method(url=url, params=command[2], json=command[3])
+ if r.status_code // 100 == 2:
+ print("Done: %s" % command[4])
+ else:
+ print("Error %d:%s" % (r.status_code, command[4]))
+ print(r.text)
+ exit(1)
+ else:
+ print("requests method error")
+ exit(1)
+
+ print("All done!")
+
+ except Exception as ex:
+ tb = traceback.format_exc()
+ print >> sys.stderr, tb
+
+
+# ======================================================================
+if __name__ == "__main__":
+ main()
+
diff --git a/swagger/sdrangel/examples/devicesets_config.py b/swagger/sdrangel/examples/devicesets_config.py
deleted file mode 100755
index e22814da5..000000000
--- a/swagger/sdrangel/examples/devicesets_config.py
+++ /dev/null
@@ -1,83 +0,0 @@
-#!/usr/bin/env python
-
-import requests, traceback, sys
-from optparse import OptionParser
-
-base_url = "http://127.0.0.1:8091/sdrangel"
-
-# commands list. Each command is a list:
-# - URL suffix (API function)
-# - HTTP method (GET, PATCH, POST, PUT, DELETE)
-# - Params as key:value pairs or None if unused
-# - JSON body or None if unused
-# - Descriptive message fragment
-commands = [
- ["/deviceset/0/device", "PUT", None, {"hwType": "AirspyHF"}, "setup AirspyHF on Rx 0"],
- ["/preset", "PATCH", None, {"deviceSetIndex": 0, "preset": {"groupName": "OM144", "centerFrequency": 145480000, "type": "R", "name": "Rept + Simplex + DV"}}, "load preset on Rx 0"],
- ["/deviceset", "POST", None, None, "add Rx 1 device set"],
- ["/deviceset/1/device", "PUT", None, {"hwType": "RemoteInput"}, "setup RemoteInput on Rx 1"],
- ["/preset", "PATCH", None, {"deviceSetIndex": 1, "preset": {"groupName": "PRO400", "centerFrequency": 463750000, "type": "R", "name": "PM nice low remote"}}, "load preset on Rx 1"],
- ["/deviceset", "POST", None, None, "add Rx 2 device set"],
- ["/deviceset/2/device", "PUT", None, {"hwType": "Perseus"}, "setup Perseus on Rx 2"],
- ["/preset", "PATCH", None, {"deviceSetIndex": 2, "preset": {"groupName": "40m", "centerFrequency": 7074000, "type": "R", "name": "FT8"}}, "load preset on Rx 2"],
- ["/dvserial", "PATCH", {"dvserial": 1}, None, "set DV serial processing for AMBE frames decoding"],
- ["/deviceset/0/device/run", "POST", None, None, "Start device on deviceset R0"],
- ["/deviceset/1/device/run", "POST", None, None, "Start device on deviceset R1"],
- ["/deviceset/2/device/run", "POST", None, None, "Start device on deviceset R2"],
-]
-
-requests_methods = {
- "GET": requests.get,
- "PATCH": requests.patch,
- "POST": requests.post,
- "PUT": requests.put,
- "DELETE": requests.delete
-}
-
-# ======================================================================
-def getInputOptions():
-
- parser = OptionParser(usage="usage: %%prog [-t]\n")
- parser.add_option("-a", "--address", dest="address", help="address and port", metavar="ADDRESS", type="string")
-
- (options, args) = parser.parse_args()
-
- if (options.address == None):
- options.address = "127.0.0.1:8091"
-
- return options
-
-# ======================================================================
-def main():
- try:
- options = getInputOptions()
-
- global base_url
- base_url = "http://%s/sdrangel" % options.address
-
- for command in commands:
- url = base_url + command[0]
- method = requests_methods.get(command[1], None)
- if method is not None:
- r = method(url=url, params=command[2], json=command[3])
- if r.status_code / 100 == 2:
- print("Done: %s" % command[4])
- else:
- print("Error %d:%s" % (r.status_code, command[4]))
- print(r.text)
- exit(1)
- else:
- print("requests method error")
- exit(1)
-
- print("All done!")
-
- except Exception as ex:
- tb = traceback.format_exc()
- print >> sys.stderr, tb
-
-
-# ======================================================================
-if __name__ == "__main__":
- main()
-
diff --git a/swagger/sdrangel/examples/test.json b/swagger/sdrangel/examples/test.json
new file mode 100644
index 000000000..623afe3e8
--- /dev/null
+++ b/swagger/sdrangel/examples/test.json
@@ -0,0 +1,151 @@
+[
+ [
+ "/deviceset/0/device",
+ "PUT",
+ null,
+ {
+ "hwType": "HackRF"
+ },
+ "Set HackRF on Rx 0"
+ ],
+ [
+ "/deviceset/0/device/settings",
+ "PUT",
+ null,
+ {
+ "deviceHwType": "HackRF",
+ "hackRFInputSettings": {
+ "LOppmTenths": 0,
+ "bandwidth": 1750000,
+ "biasT": 0,
+ "centerFrequency": 433800000,
+ "dcBlock": 1,
+ "devSampleRate": 1536000,
+ "fcPos": 2,
+ "iqCorrection": 0,
+ "lnaExt": 1,
+ "lnaGain": 32,
+ "log2Decim": 2,
+ "reverseAPIAddress": "127.0.0.1",
+ "reverseAPIDeviceIndex": 0,
+ "reverseAPIPort": 8888,
+ "useReverseAPI": 0,
+ "vgaGain": 24
+ },
+ "tx": 0
+ },
+ "Setup HackRF on Rx 0"
+ ],
+ [
+ "/deviceset/0/channel",
+ "POST",
+ null,
+ {
+ "channelType": "RemoteSink",
+ "tx": 0
+ },
+ "Add a remote sink channel"
+ ],
+ [
+ "/deviceset/0/channel/0/settings",
+ "PUT",
+ null,
+ {
+ "RemoteSinkSettings": {
+ "dataAddress": "192.168.1.5",
+ "dataPort": 9094,
+ "filterChainHash": 0,
+ "log2Decim": 3,
+ "nbFECBlocks": 8,
+ "reverseAPIAddress": "127.0.0.1",
+ "reverseAPIChannelIndex": 0,
+ "reverseAPIDeviceIndex": 0,
+ "reverseAPIPort": 8888,
+ "rgbColor": -7601148,
+ "title": "Channel 0",
+ "txDelay": 0,
+ "useReverseAPI": 0
+ },
+ "channelType": "RemoteSink",
+ "tx": 0
+ },
+ "Setup remote sink on channel 0"
+ ],
+ [
+ "/deviceset/0/channel",
+ "POST",
+ null,
+ {
+ "channelType": "RemoteSink",
+ "tx": 0
+ },
+ "Add a remote sink channel"
+ ],
+ [
+ "/deviceset/0/channel/1/settings",
+ "PUT",
+ null,
+ {
+ "RemoteSinkSettings": {
+ "dataAddress": "192.168.1.5",
+ "dataPort": 9095,
+ "filterChainHash": 13,
+ "log2Decim": 3,
+ "nbFECBlocks": 8,
+ "reverseAPIAddress": "127.0.0.1",
+ "reverseAPIChannelIndex": 0,
+ "reverseAPIDeviceIndex": 0,
+ "reverseAPIPort": 8888,
+ "rgbColor": -7601148,
+ "title": "Remote sink",
+ "txDelay": 0,
+ "useReverseAPI": 0
+ },
+ "channelType": "RemoteSink",
+ "tx": 0
+ },
+ "Setup remote sink on channel 1"
+ ],
+ [
+ "/deviceset/0/channel",
+ "POST",
+ null,
+ {
+ "channelType": "RemoteSink",
+ "tx": 0
+ },
+ "Add a remote sink channel"
+ ],
+ [
+ "/deviceset/0/channel/2/settings",
+ "PUT",
+ null,
+ {
+ "RemoteSinkSettings": {
+ "dataAddress": "192.168.1.5",
+ "dataPort": 9096,
+ "filterChainHash": 26,
+ "log2Decim": 3,
+ "nbFECBlocks": 8,
+ "reverseAPIAddress": "127.0.0.1",
+ "reverseAPIChannelIndex": 0,
+ "reverseAPIDeviceIndex": 0,
+ "reverseAPIPort": 8888,
+ "rgbColor": -7601148,
+ "title": "Remote sink",
+ "txDelay": 0,
+ "useReverseAPI": 0
+ },
+ "channelType": "RemoteSink",
+ "tx": 0
+ },
+ "Setup remote sink on channel 2"
+ ],
+ [
+ "/deviceset/0/device/run",
+ "POST",
+ null,
+ null,
+ "Start device on deviceset R0"
+ ]
+]
\ No newline at end of file