diff --git a/swagger/sdrangel/.gitignore b/swagger/sdrangel/.gitignore
new file mode 100644
index 000000000..65f91cd1a
--- /dev/null
+++ b/swagger/sdrangel/.gitignore
@@ -0,0 +1,34 @@
+# IDE files
+.idea
+
+# Logs
+logs
+*.log
+
+# Runtime data
+pids
+*.pid
+*.seed
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+lib-cov
+
+# Coverage directory used by tools like istanbul
+coverage
+
+# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
+.grunt
+
+# Compiled binary addons (http://nodejs.org/api/addons.html)
+build/Release
+
+# Dependency directory
+# Commenting this out is preferred by some people, see
+# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
+node_modules
+
+# Users Environment Variables
+.lock-wscript
+
+# Runtime configuration for swagger app
+config/runtime.yaml
diff --git a/swagger/sdrangel/README.md b/swagger/sdrangel/README.md
new file mode 100644
index 000000000..2249faca3
--- /dev/null
+++ b/swagger/sdrangel/README.md
@@ -0,0 +1,59 @@
+# Swagger project for SDRangel
+
+
What is Swagger?
+
+Swagger is an open source software framework backed by a large ecosystem of tools that helps developers design, build, document, and consume RESTful Web services. [Link to Swagger website](https://swagger.io/)
+
+Swagger is used to design the SDRangel web API. You will find the Swagger framework for SDRangel here.
+
+Install Swagger
+
+Uses `apt-get` package manager (Ubuntu, Debian). Use your distribution package manager for other distributions
+
+```shell
+sudo apt-get install npm
+sudo npm install -g swagger
+```
+
+install Node.js 6.x on Ubuntu 16.04 :
+
+```shell
+curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
+sudo apt-get install -y nodejs
+```
+Install http-server a lightweight web server to serve included files
+
+```shell
+sudo npm install -g http-server
+```
+
+Work with Swagger
+
+Edit files with Swagger
+
+All commands are relative to this directory (where the README.md is)
+
+Firstly start a node server to serve files in `api/swagger/include`
+
+```shell
+cd api/swagger/include
+http-server --cors .
+```
+
+Then in start the swagger editor
+
+```shell
+swagger project edit
+```
+
+Mocking
+
+Write controllers for mocking in `api/mocks/`
+
+Run the server in mock mode:
+
+```shell
+swagger project start -m
+```
+
+
diff --git a/swagger/sdrangel/api/controllers/README.md b/swagger/sdrangel/api/controllers/README.md
new file mode 100644
index 000000000..ddb3f6488
--- /dev/null
+++ b/swagger/sdrangel/api/controllers/README.md
@@ -0,0 +1 @@
+Place your controllers in this directory.
diff --git a/swagger/sdrangel/api/controllers/hello_world.js b/swagger/sdrangel/api/controllers/hello_world.js
new file mode 100644
index 000000000..2e17de72b
--- /dev/null
+++ b/swagger/sdrangel/api/controllers/hello_world.js
@@ -0,0 +1,44 @@
+'use strict';
+/*
+ 'use strict' is not required but helpful for turning syntactical errors into true errors in the program flow
+ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode
+*/
+
+/*
+ Modules make it possible to import JavaScript files into your application. Modules are imported
+ using 'require' statements that give you a reference to the module.
+
+ It is a good idea to list the modules that your application depends on in the package.json in the project root
+ */
+var util = require('util');
+
+/*
+ Once you 'require' a module you can reference the things that it exports. These are defined in module.exports.
+
+ For a controller in a127 (which this is) you should export the functions referenced in your Swagger document by name.
+
+ Either:
+ - The HTTP Verb of the corresponding operation (get, put, post, delete, etc)
+ - Or the operationId associated with the operation in your Swagger document
+
+ In the starter/skeleton project the 'get' operation on the '/hello' path has an operationId named 'hello'. Here,
+ we specify that in the exports of this module that 'hello' maps to the function named 'hello'
+ */
+module.exports = {
+ hello: hello
+};
+
+/*
+ Functions in a127 controllers used for operations should take two parameters:
+
+ Param 1: a handle to the request object
+ Param 2: a handle to the response object
+ */
+function hello(req, res) {
+ // variables defined in the Swagger document can be referenced using req.swagger.params.{parameter_name}
+ var name = req.swagger.params.name.value || 'stranger';
+ var hello = util.format('Hello, %s!', name);
+
+ // this sends back a JSON response which is a single string
+ res.json(hello);
+}
diff --git a/swagger/sdrangel/api/helpers/README.md b/swagger/sdrangel/api/helpers/README.md
new file mode 100644
index 000000000..36a598fd0
--- /dev/null
+++ b/swagger/sdrangel/api/helpers/README.md
@@ -0,0 +1 @@
+Place helper files in this directory.
diff --git a/swagger/sdrangel/api/mocks/README.md b/swagger/sdrangel/api/mocks/README.md
new file mode 100644
index 000000000..8069e63b0
--- /dev/null
+++ b/swagger/sdrangel/api/mocks/README.md
@@ -0,0 +1,5 @@
+This directory contains the controller files to support the mock server
+
+Controllers
+
+ - `instance.js`: methods found in the `/sdrangel` route
diff --git a/swagger/sdrangel/api/mocks/instance.js b/swagger/sdrangel/api/mocks/instance.js
new file mode 100644
index 000000000..b71788672
--- /dev/null
+++ b/swagger/sdrangel/api/mocks/instance.js
@@ -0,0 +1,211 @@
+'use strict';
+
+module.exports = {
+ instanceSummary: instanceSummary,
+ instanceDevices: instanceDevices,
+ instanceChannels: instanceChannels
+};
+
+function instanceSummary(req, res, next) {
+
+ res.json([
+ {
+ "version":"4.0.0",
+ "logging": {
+ "consoleLevel": "info",
+ "fileLevel": "debug",
+ "dumpToFile": false
+ },
+ "devicesetcount":2,
+ "devicesets":[
+ {
+ "samplingDevice": {
+ "index":0,
+ "hwType":"RTLSDR",
+ "rx":true,
+ "streamIndex":0,
+ "sequence":0,
+ "serial":"R820T2005",
+ "centerFrequency": 435000000,
+ "bandwidth": 64000
+ },
+ "channelcount":2,
+ "channels":[
+ {"index":0,"id":"AMDemod","deltaFrequency":-12500},
+ {"index":1,"id":"AMDemod","deltaFrequency":12500}
+ ]
+ },
+ {
+ "samplingDevice": {
+ "index":1,
+ "hwType":"HackRF",
+ "rx":false,
+ "streamIndex":0,
+ "sequence":0,
+ "serial":"453c64c8257a608f",
+ "centerFrequency": 435000000,
+ "bandwidth": 128000
+ },
+ "channelcount":1,
+ "channels":[
+ {"index":0,"id":"AMMod","deltaFrequency":12500}
+ ]
+ }
+
+ ],
+ "user":{"index":1,"name":"Sample text"}}
+ ]);
+}
+
+function instanceDevices(req, res, next) {
+ var direction = req.swagger.params.direction.value || "rx";
+ //console.log(direction.value)
+
+ if (direction === "tx") {
+ res.json([
+ {
+ "devicecount": 1,
+ "devices": [
+ {
+ "hwType":"HackRF",
+ "rx":false,
+ "streamIndex":0,
+ "sequence":0,
+ "serial":"453c64c8257a608f"
+ }
+ ]
+ }]);
+ } else {
+ res.json([
+ {
+ "devicecount": 2,
+ "devices": [
+ {
+ "hwType":"RTLSDR",
+ "rx":true,
+ "streamIndex":0,
+ "sequence":0,
+ "serial":"R820T2005"
+ },
+ {
+ "hwType":"HackRF",
+ "rx":true,
+ "streamIndex":0,
+ "sequence":0,
+ "serial":"453c64c8257a608f"
+ }
+ ]
+ }]);
+ }
+}
+
+function instanceChannels(req, res, next) {
+ var direction = req.swagger.params.direction.value || "rx";
+
+ if (direction === "tx") {
+ res.json([
+ {
+ "channelcount": 6,
+ "channels": [
+ {
+ "name":"AM Modulator",
+ "id": "AMMod",
+ "rx":false,
+ "version": "3.9.0"
+ },
+ {
+ "name":"ATV Modulator",
+ "id": "ATVMod",
+ "rx":false,
+ "version": "3.9.0"
+ },
+ {
+ "name":"NFM Modulator",
+ "id": "NFMMod",
+ "rx":false,
+ "version": "3.9.0"
+ },
+ {
+ "name":"SSB Modulator",
+ "id": "SSBMod",
+ "rx":false,
+ "version": "3.9.0"
+ },
+ {
+ "name":"UDP Channel Sink",
+ "id": "UDPSink",
+ "rx":false,
+ "version": "4.0.0"
+ },
+ {
+ "name":"WFM Modulator",
+ "id": "WFMMod",
+ "rx":false,
+ "version": "3.9.0"
+ }
+ ]
+ }]);
+ } else {
+ res.json([
+ {
+ "channelcount": 9,
+ "channels": [
+ {
+ "name":"AM Demodulator",
+ "id": "AMemod",
+ "rx":true,
+ "version": "4.0.0"
+ },
+ {
+ "name":"Broadcast FM Demodulator",
+ "id": "BFMDemod",
+ "rx":true,
+ "version": "4.0.0"
+ },
+ {
+ "name":"ATV Demodulator",
+ "id": "ATVDemod",
+ "rx":true,
+ "version": "4.0.0"
+ },
+ {
+ "name":"DSD Demodulator",
+ "id": "DSDDemod",
+ "rx":true,
+ "version": "4.0.0"
+ },
+ {
+ "name":"NFM Demodulator",
+ "id": "NFDemod",
+ "rx":true,
+ "version": "4.0.0"
+ },
+ {
+ "name":"SSB Demodulator",
+ "id": "SSBDemod",
+ "rx":true,
+ "version": "4.0.0"
+ },
+ {
+ "name":"TCP Channel Source",
+ "id": "TCPSource",
+ "rx":true,
+ "version": "4.0.0"
+ },
+ {
+ "name":"UDP Channel Source",
+ "id": "UDPSource",
+ "rx":true,
+ "version": "4.0.0"
+ },
+ {
+ "name":"WFM Demodulator",
+ "id": "WFMDemod",
+ "rx":true,
+ "version": "4.0.0"
+ }
+ ]
+ }]);
+ }
+
+}
diff --git a/swagger/sdrangel/api/swagger/include/User.yaml b/swagger/sdrangel/api/swagger/include/User.yaml
new file mode 100644
index 000000000..e4c4ca4c8
--- /dev/null
+++ b/swagger/sdrangel/api/swagger/include/User.yaml
@@ -0,0 +1,9 @@
+User:
+ required:
+ - index
+ - name
+ properties:
+ index:
+ type: integer
+ name:
+ type: string
diff --git a/swagger/sdrangel/api/swagger/swagger.yaml b/swagger/sdrangel/api/swagger/swagger.yaml
new file mode 100644
index 000000000..9451edf37
--- /dev/null
+++ b/swagger/sdrangel/api/swagger/swagger.yaml
@@ -0,0 +1,229 @@
+swagger: "2.0"
+info:
+ version: "4.0.0"
+ title: SDRangel
+# during dev, should point to your local machine
+host: localhost:10010
+# basePath prefixes all resource paths
+basePath: /
+#
+schemes:
+ # tip: remove http to make production-grade
+ - http
+ - https
+# format of bodies a client can send (Content-Type)
+consumes:
+ - application/json
+# format of the responses to the client (Accepts)
+produces:
+ - application/json
+paths:
+ /sdrangel:
+ # binds a127 app logic to a route
+ x-swagger-router-controller: instance
+ get:
+ description: SDRangel instance summary
+ # used as the method name of the controller
+ operationId: instanceSummary
+ # parameters:
+ # - name: name
+ # in: query
+ # description: The name of the person to whom to say hello
+ # required: false
+ # type: string
+ responses:
+ "200":
+ description: Success
+ schema:
+ # a pointer to a definition
+ $ref: "#/definitions/InstanceSummaryResponse"
+ # responses may fall through to errors
+ default:
+ description: Error
+ schema:
+ $ref: "#/definitions/ErrorResponse"
+ /sdrangel/devices:
+ x-swagger-router-controller: instance
+ get:
+ description: Get a list of sampling devices
+ operationId: instanceDevices
+ parameters:
+ - name: direction
+ in: query
+ description: gives Rx or Tx direction
+ required: false
+ type: string
+ responses:
+ "200":
+ description: Success
+ schema:
+ $ref: "#/definitions/InstanceDevicesResponse"
+ default:
+ description: Error
+ schema:
+ $ref: "#/definitions/ErrorResponse"
+ /sdrangel/channels:
+ x-swagger-router-controller: instance
+ get:
+ description: Get a list of channel plugins
+ operationId: instanceChannels
+ parameters:
+ - name: direction
+ in: query
+ description: gives Rx or Tx direction
+ required: false
+ type: string
+ responses:
+ "200":
+ description: Success
+ schema:
+ $ref: "#/definitions/InstanceChannelsResponse"
+ default:
+ description: Error
+ schema:
+ $ref: "#/definitions/ErrorResponse"
+ /swagger:
+ x-swagger-pipe: swagger_raw
+# complex objects have schema definitions
+definitions:
+ InstanceSummaryResponse:
+ required:
+ - version
+ - devicesetcount
+ properties:
+ version:
+ type: string
+ logging:
+ $ref: "#/definitions/LoggingInfo"
+ devicesetcount:
+ type: integer
+ devicesets:
+ type: array
+ items:
+ $ref: "#/definitions/DeviceSet"
+ user:
+ $ref: "http://localhost:8080/User.yaml#/User"
+ InstanceDevicesResponse:
+ required:
+ - devicecount
+ properties:
+ devicecount:
+ type: integer
+ devices:
+ type: array
+ items:
+ $ref: "#/definitions/DeviceListItem"
+ InstanceChannelsResponse:
+ required:
+ - channelcount
+ properties:
+ channelcount:
+ type: integer
+ channels:
+ type: array
+ items:
+ $ref: "#/definitions/ChannelListItem"
+ ErrorResponse:
+ required:
+ - message
+ properties:
+ message:
+ type: string
+ LoggingInfo:
+ required:
+ - consoleLevel
+ - fileLevel
+ - dumpToFile
+ properties:
+ consoleLevel:
+ type: string
+ fileLevel:
+ type: string
+ dumpToFile:
+ type: boolean
+ fileName:
+ type: string
+ DeviceListItem:
+ required:
+ - hwType
+ - rx
+ - streamIndex
+ - sequence
+ - serial
+ properties:
+ hwType:
+ type: string
+ rx:
+ type: boolean
+ streamIndex:
+ type: integer
+ sequence:
+ type: integer
+ serial:
+ type: string
+ ChannelListItem:
+ required:
+ - name
+ - id
+ - rx
+ properties:
+ name:
+ type: string
+ id:
+ type: string
+ rx:
+ type: boolean
+ version:
+ type: string
+ DeviceSet:
+ required:
+ - samplingDevice
+ - channelcount
+ properties:
+ samplingDevice:
+ $ref: "#/definitions/SamplingDevice"
+ channelcount:
+ type: integer
+ channels:
+ type: array
+ items:
+ $ref: "#/definitions/Channel"
+ SamplingDevice:
+ required:
+ - index
+ - hwType
+ - rx
+ - streamIndex
+ - sequence
+ - serial
+ - centerFrequency
+ - bandwidth
+ properties:
+ index:
+ type: integer
+ hwType:
+ type: string
+ rx:
+ type: boolean
+ streamIndex:
+ type: integer
+ sequence:
+ type: integer
+ serial:
+ type: string
+ centerFrequency:
+ type: integer
+ bandwidth:
+ type: integer
+ Channel:
+ required:
+ - index
+ - id
+ - deltaFrequency
+ properties:
+ index:
+ type: integer
+ id:
+ type: string
+ deltaFrequency:
+ type: integer
diff --git a/swagger/sdrangel/app.js b/swagger/sdrangel/app.js
new file mode 100644
index 000000000..f4c29aba7
--- /dev/null
+++ b/swagger/sdrangel/app.js
@@ -0,0 +1,23 @@
+'use strict';
+
+var SwaggerExpress = require('swagger-express-mw');
+var app = require('express')();
+module.exports = app; // for testing
+
+var config = {
+ appRoot: __dirname // required config
+};
+
+SwaggerExpress.create(config, function(err, swaggerExpress) {
+ if (err) { throw err; }
+
+ // install middleware
+ swaggerExpress.register(app);
+
+ var port = process.env.PORT || 10010;
+ app.listen(port);
+
+ if (swaggerExpress.runner.swagger.paths['/hello']) {
+ console.log('try this:\ncurl http://127.0.0.1:' + port + '/hello?name=Scott');
+ }
+});
diff --git a/swagger/sdrangel/config/README.md b/swagger/sdrangel/config/README.md
new file mode 100644
index 000000000..d0535bda1
--- /dev/null
+++ b/swagger/sdrangel/config/README.md
@@ -0,0 +1 @@
+Place configuration files in this directory.
diff --git a/swagger/sdrangel/config/default.yaml b/swagger/sdrangel/config/default.yaml
new file mode 100644
index 000000000..cbe55eba3
--- /dev/null
+++ b/swagger/sdrangel/config/default.yaml
@@ -0,0 +1,37 @@
+# swagger configuration file
+
+# values in the swagger hash are system configuration for swagger-node
+swagger:
+
+ fittingsDirs: [ api/fittings ]
+ defaultPipe: null
+ swaggerControllerPipe: swagger_controllers # defines the standard processing pipe for controllers
+
+ # values defined in the bagpipes key are the bagpipes pipes and fittings definitions
+ # (see https://github.com/apigee-127/bagpipes)
+ bagpipes:
+
+ _router:
+ name: swagger_router
+ mockMode: false
+ mockControllersDirs: [ api/mocks ]
+ controllersDirs: [ api/controllers ]
+
+ _swagger_validate:
+ name: swagger_validator
+ validateResponse: true
+
+ # pipe for all swagger-node controllers
+ swagger_controllers:
+ - onError: json_error_handler
+ - cors
+ - swagger_security
+ - _swagger_validate
+ - express_compatibility
+ - _router
+
+ # pipe to serve swagger (endpoint is in swagger.yaml)
+ swagger_raw:
+ name: swagger_raw
+
+# any other values in this file are just loaded into the config for application access...
diff --git a/swagger/sdrangel/package.json b/swagger/sdrangel/package.json
new file mode 100644
index 000000000..e5a1a1aae
--- /dev/null
+++ b/swagger/sdrangel/package.json
@@ -0,0 +1,22 @@
+{
+ "name": "sdrangel",
+ "version": "4.0.0",
+ "private": true,
+ "description": "New Swagger API Project for SDRangel",
+ "keywords": [],
+ "author": "",
+ "license": "",
+ "main": "app.js",
+ "dependencies": {
+ "express": "^4.12.3",
+ "swagger-express-mw": "^0.1.0"
+ },
+ "devDependencies": {
+ "should": "^7.1.0",
+ "supertest": "^1.0.0"
+ },
+ "scripts": {
+ "start": "node app.js",
+ "test": "swagger project test"
+ }
+}
diff --git a/swagger/sdrangel/test/api/controllers/README.md b/swagger/sdrangel/test/api/controllers/README.md
new file mode 100644
index 000000000..16437ee16
--- /dev/null
+++ b/swagger/sdrangel/test/api/controllers/README.md
@@ -0,0 +1 @@
+Place your controller tests in this directory.
diff --git a/swagger/sdrangel/test/api/controllers/hello_world.js b/swagger/sdrangel/test/api/controllers/hello_world.js
new file mode 100644
index 000000000..38f8093dc
--- /dev/null
+++ b/swagger/sdrangel/test/api/controllers/hello_world.js
@@ -0,0 +1,48 @@
+var should = require('should');
+var request = require('supertest');
+var server = require('../../../app');
+
+describe('controllers', function() {
+
+ describe('hello_world', function() {
+
+ describe('GET /hello', function() {
+
+ it('should return a default string', function(done) {
+
+ request(server)
+ .get('/hello')
+ .set('Accept', 'application/json')
+ .expect('Content-Type', /json/)
+ .expect(200)
+ .end(function(err, res) {
+ should.not.exist(err);
+
+ res.body.should.eql('Hello, stranger!');
+
+ done();
+ });
+ });
+
+ it('should accept a name parameter', function(done) {
+
+ request(server)
+ .get('/hello')
+ .query({ name: 'Scott'})
+ .set('Accept', 'application/json')
+ .expect('Content-Type', /json/)
+ .expect(200)
+ .end(function(err, res) {
+ should.not.exist(err);
+
+ res.body.should.eql('Hello, Scott!');
+
+ done();
+ });
+ });
+
+ });
+
+ });
+
+});
diff --git a/swagger/sdrangel/test/api/helpers/README.md b/swagger/sdrangel/test/api/helpers/README.md
new file mode 100644
index 000000000..8528f1b16
--- /dev/null
+++ b/swagger/sdrangel/test/api/helpers/README.md
@@ -0,0 +1 @@
+Place your helper tests in this directory.