| 
									
										
										
										
											2021-11-26 15:21:01 +01:00
										 |  |  | #!/usr/bin/env python3 | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | Dumps a SDRangel instance configuration to a sequence of commands in a JSON file | 
					
						
							|  |  |  | compatible with config.py | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Each command is a JSON document with the following keys: | 
					
						
							|  |  |  |   - endpoint: URL suffix (API function) - mandatory | 
					
						
							|  |  |  |   - method: HTTP method (GET, PATCH, POST, PUT, DELETE) - mandatory | 
					
						
							|  |  |  |   - params: pairs of argument and values - optional | 
					
						
							|  |  |  |   - payload: request body in JSON format - optional | 
					
						
							|  |  |  |   - msg: descriptive message for console display - optional | 
					
						
							|  |  |  |   - delay: delay in milliseconds after command - optional | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import requests, traceback, sys, json, time | 
					
						
							|  |  |  | from optparse import OptionParser | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | base_url = "http://127.0.0.1:8091/sdrangel" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # ====================================================================== | 
					
						
							|  |  |  | class Instance: | 
					
						
							|  |  |  |     def __init__(self): | 
					
						
							|  |  |  |         self.devicesets = [] | 
					
						
							| 
									
										
										
										
											2022-08-16 14:53:02 +02:00
										 |  |  |         self.features = [] | 
					
						
							| 
									
										
										
										
											2021-11-26 15:21:01 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def add_deviceset(self, json_data): | 
					
						
							|  |  |  |         ds = DeviceSet(len(self.devicesets), json_data["direction"], json_data["deviceHwType"], json_data) | 
					
						
							|  |  |  |         self.devicesets.append(ds) | 
					
						
							|  |  |  |         return ds | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def add_deviceset_item(self, direction): | 
					
						
							|  |  |  |         return { | 
					
						
							|  |  |  |             "endpoint": "/deviceset", | 
					
						
							|  |  |  |             "method": "POST", | 
					
						
							|  |  |  |             "params": {"direction": direction}, | 
					
						
							|  |  |  |             "msg": f"Add device set" | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-16 14:53:02 +02:00
										 |  |  |     def add_feature(self, json_data): | 
					
						
							|  |  |  |         feat = Feature(len(self.features), json_data["featureType"], json_data) | 
					
						
							|  |  |  |         self.features.append(feat) | 
					
						
							|  |  |  |         return feat | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def delete_all_features_items(self): | 
					
						
							|  |  |  |         nb_features = len(self.features) | 
					
						
							|  |  |  |         items = [] | 
					
						
							|  |  |  |         for i_feat in reversed(range(nb_features)): | 
					
						
							|  |  |  |             items.append({ | 
					
						
							|  |  |  |                 "endpoint": f"/featureset/{self.index}/feature/{i_feat}", | 
					
						
							|  |  |  |                 "method": "DELETE", | 
					
						
							|  |  |  |                 "msg": f"Delete feature at index {i_feat} in feature set {self.index}" | 
					
						
							|  |  |  |             }) | 
					
						
							|  |  |  |         return items | 
					
						
							| 
									
										
										
										
											2021-11-26 15:21:01 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def get_config_items(self): | 
					
						
							|  |  |  |         items = [] | 
					
						
							|  |  |  |         for i_ds, deviceset in enumerate(self.devicesets): | 
					
						
							|  |  |  |             items.append(self.add_deviceset_item(deviceset.direction)) | 
					
						
							|  |  |  |             items.append(deviceset.change_device_item()) | 
					
						
							|  |  |  |             items.append(deviceset.set_device_item()) | 
					
						
							|  |  |  |             for channel in deviceset.channels: | 
					
						
							|  |  |  |                 items.append(channel.add_channel_item()) | 
					
						
							|  |  |  |                 items.append(channel.set_channel_item()) | 
					
						
							|  |  |  |             items.append(deviceset.set_spectrum_item()) | 
					
						
							| 
									
										
										
										
											2022-08-16 14:53:02 +02:00
										 |  |  |         for feature in self.features: | 
					
						
							|  |  |  |             items.append(feature.add_feature_item()) | 
					
						
							|  |  |  |             items.append(feature.set_feature_item()) | 
					
						
							| 
									
										
										
										
											2021-11-26 15:21:01 +01:00
										 |  |  |         return items | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # ====================================================================== | 
					
						
							|  |  |  | class DeviceSet: | 
					
						
							|  |  |  |     def __init__(self, index, direction, hwType, settings): | 
					
						
							|  |  |  |         self.index = index | 
					
						
							|  |  |  |         self.direction = direction | 
					
						
							|  |  |  |         self.hwType = hwType | 
					
						
							|  |  |  |         self.device_settings = settings | 
					
						
							|  |  |  |         self.spectrum_settings = {} | 
					
						
							|  |  |  |         self.channels = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def set_spectrum_settings(self, settings): | 
					
						
							|  |  |  |         self.spectrum_settings = settings | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def add_channel(self, json_data): | 
					
						
							|  |  |  |         ch = Channel(self.index, len(self.channels), json_data["direction"], json_data["channelType"], json_data) | 
					
						
							|  |  |  |         self.channels.append(ch) | 
					
						
							|  |  |  |         return ch | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def change_device_item(self): | 
					
						
							|  |  |  |         return { | 
					
						
							|  |  |  |             "endpoint": f"/deviceset/{self.index}/device", | 
					
						
							|  |  |  |             "method": "PUT", | 
					
						
							|  |  |  |             "payload": { | 
					
						
							|  |  |  |                 "hwType": self.hwType, | 
					
						
							|  |  |  |                 "direction": self.direction | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             "msg": f"Change device to {self.hwType} on device set {self.index}" | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def set_device_item(self): | 
					
						
							|  |  |  |         return { | 
					
						
							|  |  |  |             "endpoint": f"/deviceset/{self.index}/device/settings", | 
					
						
							|  |  |  |             "method": "PUT", | 
					
						
							|  |  |  |             "payload": self.device_settings, | 
					
						
							|  |  |  |             "msg": f"Setup device {self.hwType} on device set {self.index}" | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def set_spectrum_item(self): | 
					
						
							|  |  |  |         return { | 
					
						
							|  |  |  |             "endpoint": f"/deviceset/{self.index}/spectrum/settings", | 
					
						
							|  |  |  |             "method": "PUT", | 
					
						
							|  |  |  |             "payload": self.spectrum_settings, | 
					
						
							|  |  |  |             "msg": f"Setup spectrum on device set {self.index}" | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def delete_all_channels_items(self): | 
					
						
							|  |  |  |         nb_channels = len(self.channels) | 
					
						
							|  |  |  |         items = [] | 
					
						
							|  |  |  |         for i_chan in reversed(range(nb_channels)): | 
					
						
							|  |  |  |             items.append({ | 
					
						
							|  |  |  |                 "endpoint": f"/deviceset/{self.index}/channel/{i_chan}", | 
					
						
							|  |  |  |                 "method": "DELETE", | 
					
						
							|  |  |  |                 "msg": f"Delete channel at index {i_chan} in device set {self.index}" | 
					
						
							|  |  |  |             }) | 
					
						
							|  |  |  |         return items | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # ====================================================================== | 
					
						
							|  |  |  | class Channel: | 
					
						
							|  |  |  |     def __init__(self, ds_index, index, direction, type, settings): | 
					
						
							|  |  |  |         self.ds_index = ds_index | 
					
						
							|  |  |  |         self.index = index | 
					
						
							|  |  |  |         self.direction = direction | 
					
						
							|  |  |  |         self.type = type | 
					
						
							|  |  |  |         self.channel_settings = settings | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def add_channel_item(self): | 
					
						
							|  |  |  |         return { | 
					
						
							|  |  |  |             "endpoint": f"/deviceset/{self.ds_index}/channel", | 
					
						
							|  |  |  |             "method": "POST", | 
					
						
							|  |  |  |             "payload": { | 
					
						
							|  |  |  |                 "channelType": self.type, | 
					
						
							|  |  |  |                 "direction": self.direction | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             "msg": f"Add channel {self.type} in device set index {self.ds_index}" | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def set_channel_item(self): | 
					
						
							|  |  |  |         return { | 
					
						
							|  |  |  |             "endpoint": f"/deviceset/{self.ds_index}/channel/{self.index}/settings", | 
					
						
							|  |  |  |             "method": "PUT", | 
					
						
							|  |  |  |             "payload": self.channel_settings, | 
					
						
							|  |  |  |             "msg": f"Setup channel {self.type} at {self.index} in device set {self.ds_index}" | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # ====================================================================== | 
					
						
							|  |  |  | class Feature: | 
					
						
							| 
									
										
										
										
											2022-08-16 14:53:02 +02:00
										 |  |  |     def __init__(self, index, type, settings): | 
					
						
							| 
									
										
										
										
											2021-11-26 15:21:01 +01:00
										 |  |  |         self.index = index | 
					
						
							|  |  |  |         self.type = type | 
					
						
							|  |  |  |         self.feature_settings = settings | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def add_feature_item(self): | 
					
						
							|  |  |  |         return { | 
					
						
							| 
									
										
										
										
											2022-08-16 14:53:02 +02:00
										 |  |  |             "endpoint": f"/featureset/feature", | 
					
						
							| 
									
										
										
										
											2021-11-26 15:21:01 +01:00
										 |  |  |             "method": "POST", | 
					
						
							|  |  |  |             "payload": { | 
					
						
							|  |  |  |                 "featureType": self.type | 
					
						
							|  |  |  |             }, | 
					
						
							| 
									
										
										
										
											2022-08-16 14:53:02 +02:00
										 |  |  |             "msg": f"Add feature {self.type} in feature set" | 
					
						
							| 
									
										
										
										
											2021-11-26 15:21:01 +01:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def set_feature_item(self): | 
					
						
							|  |  |  |         return { | 
					
						
							| 
									
										
										
										
											2022-08-16 14:53:02 +02:00
										 |  |  |             "endpoint": f"/featureset/feature/{self.index}/settings", | 
					
						
							| 
									
										
										
										
											2021-11-26 15:21:01 +01:00
										 |  |  |             "method": "PUT", | 
					
						
							|  |  |  |             "payload": self.feature_settings, | 
					
						
							| 
									
										
										
										
											2022-08-16 14:53:02 +02:00
										 |  |  |             "msg": f"Setup feature {self.type} at {self.index} in feature set" | 
					
						
							| 
									
										
										
										
											2021-11-26 15:21:01 +01:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # ====================================================================== | 
					
						
							|  |  |  | def getInputOptions(): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     parser = OptionParser(usage="usage: %%prog [-t]\n") | 
					
						
							|  |  |  |     parser.add_option("-a", "--address", dest="address", help="Address and port. Default: 127.0.0.1:8091", metavar="ADDRESS", type="string") | 
					
						
							|  |  |  |     parser.add_option("-j", "--json-file", dest="json_file", help="JSON output file where commands are stored. Mandatory", metavar="FILE", type="string") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     (options, args) = parser.parse_args() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (options.address == None): | 
					
						
							|  |  |  |         options.address = "127.0.0.1:8091" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return options | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # ====================================================================== | 
					
						
							|  |  |  | def dump(): | 
					
						
							|  |  |  |     instance = None | 
					
						
							|  |  |  |     r = requests.get(url=f"{base_url}") | 
					
						
							|  |  |  |     if r.status_code // 100 == 2: | 
					
						
							|  |  |  |         instance = Instance() | 
					
						
							|  |  |  |         nb_devicesets = r.json()["devicesetlist"]["devicesetcount"] | 
					
						
							|  |  |  |         for i_deviceset in range(nb_devicesets): | 
					
						
							|  |  |  |             r_ds = requests.get(url=f"{base_url}/deviceset/{i_deviceset}") | 
					
						
							|  |  |  |             if r_ds.status_code // 100 == 2: | 
					
						
							|  |  |  |                 nb_channels = r_ds.json()["channelcount"] | 
					
						
							|  |  |  |                 r_dev = requests.get(url=f"{base_url}/deviceset/{i_deviceset}/device/settings") | 
					
						
							|  |  |  |                 if r_dev.status_code // 100 == 2: | 
					
						
							|  |  |  |                     ds = instance.add_deviceset(r_dev.json()) | 
					
						
							|  |  |  |                     for i_channel in range(nb_channels): | 
					
						
							|  |  |  |                         r_chan = requests.get(url=f"{base_url}/deviceset/{i_deviceset}/channel/{i_channel}/settings") | 
					
						
							|  |  |  |                         if r_chan.status_code // 100 == 2: | 
					
						
							|  |  |  |                             ds.add_channel(r_chan.json()) | 
					
						
							|  |  |  |                     r_spec = requests.get(url=f"{base_url}/deviceset/{i_deviceset}/spectrum/settings") | 
					
						
							|  |  |  |                     if r_spec.status_code // 100 == 2: | 
					
						
							|  |  |  |                         ds.set_spectrum_settings(r_spec.json()) | 
					
						
							| 
									
										
										
										
											2022-08-16 14:53:02 +02:00
										 |  |  |         nb_features = r.json()["featureset"]["featurecount"] | 
					
						
							|  |  |  |         for i_feature in range(nb_features): | 
					
						
							|  |  |  |             r_feat = requests.get(url=f"{base_url}/featureset/feature/{i_feature}/settings") | 
					
						
							|  |  |  |             if r_feat.status_code // 100 == 2: | 
					
						
							|  |  |  |                 instance.add_feature(r_feat.json()) | 
					
						
							| 
									
										
										
										
											2021-11-26 15:21:01 +01:00
										 |  |  |     return instance | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # ====================================================================== | 
					
						
							|  |  |  | def main(): | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         options = getInputOptions() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         global base_url | 
					
						
							|  |  |  |         base_url = "http://%s/sdrangel" % options.address | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         instance = dump() | 
					
						
							|  |  |  |         json_items = instance.get_config_items() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         with open(options.json_file,'w') as json_file: | 
					
						
							|  |  |  |             json.dump(json_items, json_file, indent=2) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         print("All done!") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     except Exception as ex: | 
					
						
							|  |  |  |         tb = traceback.format_exc() | 
					
						
							|  |  |  |         print(tb, file=sys.stderr) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # ====================================================================== | 
					
						
							|  |  |  | if __name__ == "__main__": | 
					
						
							|  |  |  |     main() |