simple sonos smapi soap webservice registered

This commit is contained in:
simojenki
2021-02-08 20:45:17 +11:00
parent 2ed2fce280
commit 302efd2878
8 changed files with 2298 additions and 19 deletions

View File

@@ -15,6 +15,7 @@
"eta": "^1.12.1",
"express": "^4.17.1",
"node-html-parser": "^2.1.0",
"soap": "^0.36.0",
"ts-md5": "^1.2.7",
"typescript": "^4.1.3",
"underscore":"^1.12.0",
@@ -27,6 +28,7 @@
"@types/mocha": "^8.2.0",
"@types/supertest": "^2.0.10",
"chai": "^4.2.0",
"get-port": "^5.1.1",
"jest": "^26.6.3",
"nodemon": "^2.0.7",
"supertest": "^6.1.3",
@@ -38,6 +40,6 @@
"build": "tsc",
"dev": "nodemon ./src/app.ts",
"test": "jest",
"testw": "mocha --require ts-node/register --watch --watch-files tests/**/* tests/**/*.test.ts"
"client-test": "ts-node tests/bonob_client.ts"
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,16 @@
import express, { Express } from "express";
import * as Eta from "eta";
import { listen } from "soap";
import { readFileSync } from "fs";
import path from "path";
import { Sonos, Service } from "./sonos";
import logger from "./logger";
const WSDL_FILE = path.resolve(
__dirname,
"Sonoswsdl-1.19.4-20190411.142401-3.wsdl"
);
function server(sonos: Sonos, bonobService: Service): Express {
const app = express();
@@ -12,26 +22,68 @@ function server(sonos: Sonos, bonobService: Service): Express {
app.set("views", "./web/views");
app.get("/", (_, res) => {
Promise.all([
sonos.devices(),
sonos.services()
]).then(([devices, services]) => {
const registeredBonobService = services.find(it => it.sid == bonobService.sid);
Promise.all([sonos.devices(), sonos.services()]).then(
([devices, services]) => {
const registeredBonobService = services.find(
(it) => it.sid == bonobService.sid
);
res.render("index", {
devices,
services,
bonobService,
registeredBonobService
registeredBonobService,
});
})
}
);
});
app.post("/register", (_, res) => {
sonos.register(bonobService).then(success => {
if(success) res.send("Yay")
else res.send("boo hoo")
})
sonos.register(bonobService).then((success) => {
if (success) res.send("Yay");
else res.send("boo hoo");
});
});
const sonosService = {
Sonos: {
SonosSoap: {
getSessionId: ({
username
}: {
username: string;
password: string;
}) => {
return Promise.resolve({
username,
sessionId: '123'
});
},
},
},
};
const x = listen(
app,
"/ws",
sonosService,
readFileSync(WSDL_FILE, "utf8")
);
x.log = (type, data) => {
switch (type) {
case "info":
logger.info({ data });
break;
case "warn":
logger.warn({ data });
break;
case "error":
logger.error({ data });
break;
default:
logger.debug({ data });
}
};
return app;
}

33
tests/bonob_client.ts Normal file
View File

@@ -0,0 +1,33 @@
import getPort from "get-port";
import { createClientAsync } from "soap";
import sonos, { bonobService } from "../src/sonos";
import server from "../src/server";
import logger from "../src/logger";
const bonob = bonobService("bonob-test", 247, "http://localhost:1234");
const app = server(sonos("disabled"), bonob);
getPort().then((port) => {
logger.debug(`Starting on port ${port}`);
app.listen(port);
createClientAsync(`http://localhost:${port}/ws?wsdl`, {
endpoint: `http://localhost:${port}/ws`,
}).then((client) => {
client
.getSessionIdAsync(
{ username: "bob", password: "foo" }
)
.then(
([{ username, sessionId }]: [
{ username: string; sessionId: string }
]) => {
console.log(`${username} has sessionId=${sessionId}`);
}
);
console.log(`done`);
});
});

View File

@@ -1,6 +1,7 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"target": "es2019",
"baseUrl": "./",
"module": "commonjs",
"experimentalDecorators": true,

54
tests/ws.test.ts Normal file
View File

@@ -0,0 +1,54 @@
import request from "supertest";
import makeServer from "../src/server";
import { SONOS_DISABLED } from "../src/sonos";
import { aService } from "./builders";
import { createClientAsync } from "soap";
describe("ws", () => {
describe("can call getSessionId", () => {
it("should do something", async () => {
const server = makeServer(SONOS_DISABLED, aService());
const { username, sessionId } = await createClientAsync(
`http://localhost/ws?wsdl`,
{
endpoint: `http://localhost/ws`,
httpClient: {
request: (
rurl: string,
data: any,
callback: (error: any, res?: any, body?: any) => any,
exheaders?: any
) => {
const withoutHost = rurl.replace("http://localhost", "");
const req =
data == null
? request(server).get(withoutHost).send()
: request(server).post(withoutHost).send(data);
req
.set(exheaders || {})
.then((response) => callback(null, response, response.text))
.catch(callback);
},
},
}
).then((client) =>
client
.getSessionIdAsync({ username: "bob", password: "foo" })
.then(
([{ username, sessionId }]: [
{ username: string; sessionId: string }
]) => ({
username,
sessionId,
})
)
);
expect(username).toEqual("bob");
expect(sessionId).toEqual("123");
});
});
});

View File

@@ -4,7 +4,7 @@
/* Basic Options */
// "incremental": true, /* Enable incremental compilation */
"target": "ES6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
"target": "ES2019", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
"lib": ["es2019"], /* Specify library files to be included in the compilation. */
// "allowJs": true, /* Allow javascript files to be compiled. */

View File

@@ -2015,6 +2015,11 @@ get-package-type@^0.1.0:
resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a"
integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==
get-port@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/get-port/-/get-port-5.1.1.tgz#0469ed07563479de6efb986baf053dcd7d4e3193"
integrity sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==
get-stream@^4.0.0, get-stream@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5"
@@ -2029,6 +2034,11 @@ get-stream@^5.0.0, get-stream@^5.1.0:
dependencies:
pump "^3.0.0"
get-stream@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.0.tgz#3e0012cb6827319da2706e601a1583e8629a6718"
integrity sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==
get-value@^2.0.3, get-value@^2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
@@ -2233,6 +2243,19 @@ http-signature@~1.2.0:
jsprim "^1.2.2"
sshpk "^1.7.0"
httpntlm@^1.5.2:
version "1.7.6"
resolved "https://registry.yarnpkg.com/httpntlm/-/httpntlm-1.7.6.tgz#6991e8352836007d67101b83db8ed0f915f906d0"
integrity sha1-aZHoNSg2AH1nEBuD247Q+RX5BtA=
dependencies:
httpreq ">=0.4.22"
underscore "~1.7.0"
httpreq@>=0.4.22:
version "0.4.24"
resolved "https://registry.yarnpkg.com/httpreq/-/httpreq-0.4.24.tgz#4335ffd82cd969668a39465c929ac61d6393627f"
integrity sha1-QzX/2CzZaWaKOUZckprGHWOTYn8=
human-signals@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3"
@@ -3868,7 +3891,7 @@ request-promise-native@^1.0.8:
stealthy-require "^1.1.1"
tough-cookie "^2.3.3"
request@^2.88.2:
request@>=2.9.0, request@^2.88.2:
version "2.88.2"
resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==
@@ -3990,6 +4013,11 @@ sane@^4.0.3:
minimist "^1.1.1"
walker "~1.0.5"
sax@>=0.6:
version "1.2.4"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
saxes@^5.0.0:
version "5.0.1"
resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d"
@@ -4151,6 +4179,21 @@ snapdragon@^0.8.1:
source-map-resolve "^0.5.0"
use "^3.1.0"
soap@^0.36.0:
version "0.36.0"
resolved "https://registry.yarnpkg.com/soap/-/soap-0.36.0.tgz#80d1a55e89e048f175ae5538c288428d8c649445"
integrity sha512-MEFr2H7+a02fAA2FWyJE1B0xvDE8jiH5Ke6P1WKChHR9TGcJMK7kRAlPK/YR+NNO1pUs6W1FaIz4w8I9kuvybw==
dependencies:
debug "^4.1.1"
get-stream "^6.0.0"
httpntlm "^1.5.2"
lodash "^4.17.19"
request ">=2.9.0"
sax ">=0.6"
strip-bom "^3.0.0"
uuid "^8.3.0"
xml-crypto "^2.0.0"
source-map-resolve@^0.5.0:
version "0.5.3"
resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a"
@@ -4332,6 +4375,11 @@ strip-ansi@^6.0.0:
dependencies:
ansi-regex "^5.0.0"
strip-bom@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=
strip-bom@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878"
@@ -4636,6 +4684,11 @@ underscore@^1.12.0:
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.12.0.tgz#4814940551fc80587cef7840d1ebb0f16453be97"
integrity sha512-21rQzss/XPMjolTiIezSu3JAjgagXKROtNrYFEOWK109qY1Uv2tVjPTZ1ci2HgvQDA16gHYSthQIJfB+XId/rQ==
underscore@~1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.7.0.tgz#6bbaf0877500d36be34ecaa584e0db9fef035209"
integrity sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=
union-value@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847"
@@ -4900,6 +4953,14 @@ xdg-basedir@^4.0.0:
resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13"
integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==
xml-crypto@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/xml-crypto/-/xml-crypto-2.0.0.tgz#54cd268ad9d31930afcf7092cbb664258ca9e826"
integrity sha512-/a04qr7RpONRZHOxROZ6iIHItdsQQjN3sj8lJkYDDss8tAkEaAs0VrFjb3tlhmS5snQru5lTs9/5ISSMdPDHlg==
dependencies:
xmldom "0.1.27"
xpath "0.0.27"
xml-name-validator@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"
@@ -4910,6 +4971,16 @@ xmlchars@^2.2.0:
resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb"
integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==
xmldom@0.1.27:
version "0.1.27"
resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.27.tgz#d501f97b3bdb403af8ef9ecc20573187aadac0e9"
integrity sha1-1QH5ezvbQDr4757MIFcxh6rawOk=
xpath@0.0.27:
version "0.0.27"
resolved "https://registry.yarnpkg.com/xpath/-/xpath-0.0.27.tgz#dd3421fbdcc5646ac32c48531b4d7e9d0c2cfa92"
integrity sha512-fg03WRxtkCV6ohClePNAECYsmpKKTv5L8y/X3Dn1hQrec3POx2jHZ/0P2qQ6HvsrU1BmeqXcof3NGGueG6LxwQ==
y18n@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.1.tgz#8db2b83c31c5d75099bb890b23f3094891e247d4"