sdrplay-fm-radio/microservice.py

193 lines
4.7 KiB
Python
Executable File

#! /usr/bin/env python3
import SoapySDR as soapy
from radio import Radio
from flask import Flask, jsonify
from flasgger import Swagger
app = Flask(__name__)
swag = Swagger(app)
radios = {}
@app.route('/radio/report')
def report():
"""List radio devices available to the system.
---
responses:
200:
description: A list of radio devices.
"""
devices = [dict(device) for device in soapy.Device.enumerate()]
return jsonify(devices)
@app.route('/radio/<radio>/connect')
def connect(radio):
"""Connect to a radio device, by driver name or serial number.
---
parameters:
- name: radio
description: Radio device driver name, or serial number.
in: path
type: string
required: true
responses:
200:
description: Successfully connected to a radio.
400:
description: No radio device by that name is available.
500:
description: Failed to connect to radio.
"""
if radio in radios:
return "Radio device already connected", 400
devices = [dict(device) for device in soapy.Device.enumerate()]
for device in devices:
if radio in device.values():
try:
radios[radio] = Radio(radio, device)
return "", 200
except Exception as e:
radios.pop(radio)
return str(e), 500
return "Radio device not found", 400
@app.route('/radio/<radio>/disconnect')
def disconnect(radio):
"""Disconnect from a radio device.
---
parameters:
- name: radio
description: Radio device driver name, or serial number.
in: path
type: string
required: true
responses:
200:
description: Successfully connected to a radio.
400:
description: No radio device by that name is available.
500:
description: An unknown error occurred.
"""
if radio in radios:
radios.pop(radio)
return "", 200
else:
return "Radio not connected", 400
@app.route('/radio/<radio>/configure/<frequency>')
def configure(radio, frequency):
"""Tune the radio to a frequency.
You must connect to the radio before attempting to configure it.
The radio must be configured before streaming can be started.
---
parameters:
- name: radio
description: Radio device driver name, or serial number.
in: path
type: string
required: true
- name: frequency
description: Frequency (in Hz) to tune the radio to. Suffixing is also supported, ie 87.5M, 108.0M, etc.
in: path
type: string
required: true
responses:
200:
description: JSON
400:
description: The specified radio is not connected.
"""
if radio in radios:
return jsonify(radios[radio].configure(frequency))
else:
return "Radio not connected", 400
@app.route('/radio/<radio>/start')
def start_stream(radio):
"""Start the radio stream.
Once the stream has been started, connect to the stream at:
rtsp://[host]:8554/radio/[radio]/stream
---
parameters:
- name: radio
description: Radio device driver name, or serial number.
in: path
type: string
required: true
"""
try:
radios[radio].start_stream()
return "", 200
except Exception as e:
return str(e), 400
@app.route('/radio/<radio>/end')
def end_stream(radio):
"""Terminate the radio stream.
---
parameters:
- name: radio
description: Radio device driver name, or serial number.
in: path
type: string
required: true
"""
try:
radios[radio].end_stream()
return "", 200
except Exception as e:
return str(e), 400
@app.route('/radio/<radio>/info')
def radio_info(radio):
"""Get information about a radio.
---
parameters:
- name: radio
description: Radio device driver name, or serial number.
in: path
type: string
required: true
responses:
200:
description: JSON
400:
description: The specified radio is not connected.
"""
try:
return jsonify(radios[radio].get_info())
except Exception as e:
return str(e), 400
if __name__ == '__main__':
import subprocess
rtsp_relay = subprocess.Popen(
[
'./dependencies/mediamtx/mediamtx',
'./mediamtx.yml'
],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL
)
app.run(
host='0.0.0.0',
threaded=True,
debug=False
)
print('Killing RTSP relay...')
rtsp_relay.kill()
rtsp_relay.wait() # Necessary?