diff --git a/README.md b/README.md index 1d7c7aa..032f134 100644 --- a/README.md +++ b/README.md @@ -54,15 +54,17 @@ Bonob will now auto-register itself with sonos on startup, updating the registra ### Running bonob on a different network to your sonos devices -Running bonob outside of your lan will require registering your bonob install with your sonos devices from within your lan. +Running bonob outside of your lan will require registering your bonob install with your sonos devices from within your LAN. -If you are running this on the internet, you should put bonob behind a reverse proxy and use certificates/https. +If you are using bonob over the Internet, you do this at your own risk and should use TLS. -Start bonob outside the lan with sonos discovery & registration disabled as they are meaningless in this case, ie. +Start bonob outside the LAN with sonos discovery & registration disabled as they are meaningless in this case, ie. ```bash docker run \ -e BONOB_PORT=4534 \ + -e BONOB_SONOS_SERVICE_NAME=MyAwesomeMusic \ + -e BONOB_SECRET=changeme \ -e BONOB_URL=https://my-server.example.com/bonob \ -e BONOB_SONOS_AUTO_REGISTER=false \ -e BONOB_SONOS_DEVICE_DISCOVERY=false \ @@ -71,17 +73,16 @@ docker run \ simojenki/bonob ``` -Now inside the lan that contains the sonos devices run bonob registration, using the same BONOB_URL as above, and with discovery enabled. Make sure to use host networking so that bonob can find the sonos devices (or provide a BONOB_SONOS_SEED_HOST) +Now within the LAN that contains the sonos devices run bonob the registration process. ```bash docker run \ - -e BONOB_URL=https://my-server.example.com/bonob \ - -e BONOB_SONOS_DEVICE_DISCOVERY=true \ --network host \ - simojenki/bonob register + simojenki/bonob register https://my-server.example.com/bonob ``` ### Running bonob and navidrome using docker-compose + ```yaml version: "3" services: diff --git a/package.json b/package.json index ce9f54a..ecd8d6c 100644 --- a/package.json +++ b/package.json @@ -46,9 +46,10 @@ "xpath-ts": "^1.3.13" }, "scripts": { + "clean": "rm -Rf build", "build": "tsc", - "dev": "BONOB_PORT=4000 nodemon ./src/app.ts", - "test": "jest", - "client-test": "ts-node tests/bonob_client.ts" + "dev": "BONOB_PORT=4000 BONOB_URL=http://$(hostname):4000 BONOB_SONOS_SERVICE_NAME=bonobDev BONOB_SONOS_DEVICE_DISCOVERY=false BONOB_SONOS_AUTO_REGISTER=false nodemon ./src/app.ts", + "register-dev": "ts-node ./src/register.ts http://$(hostname):4000", + "test": "jest" } } diff --git a/src/app.ts b/src/app.ts index a2f1140..a9a21f7 100644 --- a/src/app.ts +++ b/src/app.ts @@ -67,6 +67,10 @@ const app = server( true, ); +app.listen(config.port, () => { + logger.info(`Listening on ${config.port} available @ ${config.bonobUrl}`); +}); + if (config.sonos.autoRegister) { sonosSystem.register(bonob).then((success) => { if (success) { @@ -75,10 +79,12 @@ if (config.sonos.autoRegister) { ); } }); +} else if(config.sonos.deviceDiscovery) { + sonosSystem.devices().then(devices => { + devices.forEach(d => { + logger.info(`Found device ${d.name}(${d.group}) @ ${d.ip}:${d.port}`) + }) + }) } -app.listen(config.port, () => { - logger.info(`Listening on ${config.port} available @ ${config.bonobUrl}`); -}); - export default app; diff --git a/src/register.ts b/src/register.ts index 97b815f..28cbd7c 100644 --- a/src/register.ts +++ b/src/register.ts @@ -1,26 +1,15 @@ -import readConfig from "./config"; -import logger from "./logger"; -import sonos, { bonobService } from "./sonos"; +import registrar from "./registrar"; +import { URLBuilder } from "./url_builder"; -const config = readConfig(); +const params = process.argv.slice(2); -const bonob = bonobService( - config.sonos.serviceName, - config.sonos.sid, - config.bonobUrl, - "AppLink" -); +if (params.length != 1) { + console.error("Usage: register [URL to bonob]"); + process.exit(1); +} -const sonosSystem = sonos(config.sonos.deviceDiscovery, config.sonos.seedHost); - -sonosSystem.register(bonob).then((success) => { - if (success) { - logger.info( - `Successfully registered ${bonob.name}(SID:${bonob.sid}) with sonos` - ); - process.exit(0); - } else { - logger.error(`Failed to register ${bonob.name}(SID:${bonob.sid}) with sonos!!`) - process.exit(1); - } -}); \ No newline at end of file +const bonobUrl = new URLBuilder(params[0]!); +registrar(bonobUrl)().then((success) => { + if (success) console.log(`Successfully registered bonob @ ${bonobUrl} with sonos`); + else console.error(`Failed registering bonob @ ${bonobUrl} with sonos`); +}); diff --git a/src/registrar.ts b/src/registrar.ts new file mode 100644 index 0000000..18a5e94 --- /dev/null +++ b/src/registrar.ts @@ -0,0 +1,19 @@ +import axios from "axios"; +import logger from "./logger"; +import sonos, { bonobService } from "./sonos"; +import { URLBuilder } from "./url_builder"; + +export default (bonobUrl: URLBuilder) => async () => { + const about = bonobUrl.append({ pathname: "/about" }); + logger.info(`Fetching bonob service about from ${about}`); + return axios + .get(about.href()) + .then((res) => { + if (res.status == 200) return res.data; + else throw `Unexpected response status ${res.status} from ${about}`; + }) + .then((about) => + bonobService(about.service.name, about.service.sid, bonobUrl) + ) + .then((bonobService) => sonos(true).register(bonobService)); +}; diff --git a/src/server.ts b/src/server.ts index d2bbfe7..50dcdb7 100644 --- a/src/server.ts +++ b/src/server.ts @@ -101,6 +101,15 @@ function server( ); }); + app.get("/about", (_, res) => { + return res.send({ + service: { + name: service.name, + sid: service.sid + } + }); + }); + app.post(REGISTER_ROUTE, (_, res) => { sonos.register(service).then((success) => { if (success) { diff --git a/src/sonos.ts b/src/sonos.ts index 92c0e01..67023db 100644 --- a/src/sonos.ts +++ b/src/sonos.ts @@ -132,7 +132,7 @@ const setupDiscovery = ( sonosSeedHost?: string ): Promise => { if (sonosSeedHost == undefined || sonosSeedHost == "") { - logger.info("Trying to auto discover sonos devices"); + logger.info("Trying to discover sonos devices"); return manager.InitializeWithDiscovery(10); } else { logger.info(`Trying to discover sonos devices using seed ${sonosSeedHost}`); diff --git a/tests/server.test.ts b/tests/server.test.ts index 86cb6f3..8c361c0 100644 --- a/tests/server.test.ts +++ b/tests/server.test.ts @@ -307,6 +307,36 @@ describe("server", () => { }); }); + describe("/about", () => { + const sonos = { + register: jest.fn(), + }; + const theService = aService({ + name: "We can all live a life of service", + sid: 999, + }); + const server = makeServer( + sonos as unknown as Sonos, + theService, + bonobUrl, + new InMemoryMusicService() + ); + + it("should report some information about the service", async () => { + const res = await request(server) + .get(bonobUrl.append({ pathname: "/about" }).path()) + .send(); + + expect(res.status).toEqual(200); + expect(res.body).toEqual({ + service: { + name: theService.name, + sid: theService.sid + } + }); + }); + }); + describe("/register", () => { const sonos = { register: jest.fn(), @@ -322,7 +352,7 @@ describe("server", () => { new InMemoryMusicService() ); - describe("when is succesfull", () => { + describe("when is successful", () => { it("should return a nice message", async () => { sonos.register.mockResolvedValue(true); @@ -338,7 +368,7 @@ describe("server", () => { }); }); - describe("when is unsuccesfull", () => { + describe("when is unsuccessful", () => { it("should return a failure message", async () => { sonos.register.mockResolvedValue(false);