Added Swagger files to design web API

This commit is contained in:
f4exb 2017-11-15 01:38:11 +01:00
parent 3db655fe61
commit 1e8820e94e
16 changed files with 726 additions and 0 deletions

34
swagger/sdrangel/.gitignore vendored Normal file
View File

@ -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

View File

@ -0,0 +1,59 @@
# Swagger project for SDRangel
<h1>What is Swagger?</h1>
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.
<h1>Install Swagger</h1>
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
```
<h1>Work with Swagger</h1>
<h2>Edit files with Swagger</h2>
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
```
<h2>Mocking</h2>
Write controllers for mocking in `api/mocks/`
Run the server in mock mode:
```shell
swagger project start -m
```

View File

@ -0,0 +1 @@
Place your controllers in this directory.

View File

@ -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);
}

View File

@ -0,0 +1 @@
Place helper files in this directory.

View File

@ -0,0 +1,5 @@
<h1>This directory contains the controller files to support the mock server</h1>
<h2>Controllers</h2>
- `instance.js`: methods found in the `/sdrangel` route

View File

@ -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"
}
]
}]);
}
}

View File

@ -0,0 +1,9 @@
User:
required:
- index
- name
properties:
index:
type: integer
name:
type: string

View File

@ -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

23
swagger/sdrangel/app.js Normal file
View File

@ -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');
}
});

View File

@ -0,0 +1 @@
Place configuration files in this directory.

View File

@ -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...

View File

@ -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"
}
}

View File

@ -0,0 +1 @@
Place your controller tests in this directory.

View File

@ -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();
});
});
});
});
});

View File

@ -0,0 +1 @@
Place your helper tests in this directory.