Support for register using a seed host (#51)

This commit is contained in:
Simon J
2021-09-12 15:34:09 +10:00
committed by GitHub
parent 91cc450451
commit be4fcdff24
10 changed files with 219 additions and 44 deletions

View File

@@ -22,7 +22,7 @@ const bonob = bonobService(
"AppLink"
);
const sonosSystem = sonos(config.sonos.deviceDiscovery, config.sonos.seedHost);
const sonosSystem = sonos(config.sonos.discovery);
const streamUserAgent = config.navidrome.customClientsFor
? appendMimeTypeToClientFor(config.navidrome.customClientsFor.split(","))
@@ -90,7 +90,7 @@ if (config.sonos.autoRegister) {
);
}
});
} else if(config.sonos.deviceDiscovery) {
} else if(config.sonos.discovery.auto) {
sonosSystem.devices().then(devices => {
devices.forEach(d => {
logger.info(`Found device ${d.name}(${d.group}) @ ${d.ip}:${d.port}`)

View File

@@ -36,9 +36,11 @@ export default function () {
},
sonos: {
serviceName: process.env["BONOB_SONOS_SERVICE_NAME"] || "bonob",
deviceDiscovery:
(process.env["BONOB_SONOS_DEVICE_DISCOVERY"] || "true") == "true",
seedHost: process.env["BONOB_SONOS_SEED_HOST"],
discovery: {
auto:
(process.env["BONOB_SONOS_DEVICE_DISCOVERY"] || "true") == "true",
seedHost: process.env["BONOB_SONOS_SEED_HOST"],
},
autoRegister:
(process.env["BONOB_SONOS_AUTO_REGISTER"] || "false") == "true",
sid: Number(process.env["BONOB_SONOS_SERVICE_ID"] || "246"),

View File

@@ -1,4 +1,5 @@
import registrar from "./registrar";
import readConfig from "./config";
import { URLBuilder } from "./url_builder";
const params = process.argv.slice(2);
@@ -9,7 +10,10 @@ if (params.length != 1) {
}
const bonobUrl = new URLBuilder(params[0]!);
registrar(bonobUrl)()
const config = readConfig();
registrar(bonobUrl, config.sonos.discovery)()
.then((success) => {
if (success) {
console.log(`Successfully registered bonob @ ${bonobUrl} with sonos`);

View File

@@ -1,19 +1,38 @@
import axios from "axios";
import _ from "underscore";
import logger from "./logger";
import sonos, { bonobService } from "./sonos";
import sonos, { bonobService, Discovery } 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));
};
export default (
bonobUrl: URLBuilder,
sonosDiscovery: Discovery = {
auto: true,
seedHost: undefined,
}
) =>
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((res) => {
const name = _.get(res, ["service", "name"]);
const sid = _.get(res, ["service", "sid"]);
if (!name || !sid) {
throw `Unexpected response from ${about.href()}, expected service.name and service.sid`;
}
return {
name,
sid: Number.parseInt(sid),
};
})
.then(({ name, sid }: { name: string; sid: number }) =>
bonobService(name, sid, bonobUrl)
)
.then((service) => sonos(sonosDiscovery).register(service));
};

View File

@@ -9,7 +9,20 @@ import qs from "querystring";
import { URLBuilder } from "./url_builder";
import { LANG } from "./i8n";
export const SONOS_LANG: LANG[] = ["en-US", "da-DK", "de-DE", "es-ES", "fr-FR", "it-IT", "ja-JP", "nb-NO", "nl-NL", "pt-BR", "sv-SE", "zh-CN"]
export const SONOS_LANG: LANG[] = [
"en-US",
"da-DK",
"de-DE",
"es-ES",
"fr-FR",
"it-IT",
"ja-JP",
"nb-NO",
"nl-NL",
"pt-BR",
"sv-SE",
"zh-CN",
];
export const PRESENTATION_AND_STRINGS_VERSION = "21";
@@ -118,7 +131,7 @@ export const asDevice = (sonosDevice: SonosDevice): Device => ({
export const asRemoveCustomdForm = (csrfToken: string, sid: number) => ({
csrfToken,
sid: `${sid}`
sid: `${sid}`,
});
export const asCustomdForm = (csrfToken: string, service: Service) => ({
@@ -168,7 +181,10 @@ export function autoDiscoverySonos(sonosSeedHost?: string): Sonos {
});
};
const post = async (action: string, customdForm: (csrfToken: string) => any) => {
const post = async (
action: string,
customdForm: (csrfToken: string) => any
) => {
const anyDevice = await sonosDevices().then((devices) => head(devices));
if (!anyDevice) {
@@ -195,7 +211,7 @@ export function autoDiscoverySonos(sonosSeedHost?: string): Sonos {
);
return false;
}
const form = customdForm(csrfToken)
const form = customdForm(csrfToken);
logger.info(`${action} with sonos @ ${customd}`, { form });
return axios
.post(customd, new URLSearchParams(qs.stringify(form)), {
@@ -218,16 +234,22 @@ export function autoDiscoverySonos(sonosSeedHost?: string): Sonos {
)
.then((it) => it.map(asService)),
remove: async (sid: number) => post("remove", (csrfToken) => asRemoveCustomdForm(csrfToken, sid)),
remove: async (sid: number) =>
post("remove", (csrfToken) => asRemoveCustomdForm(csrfToken, sid)),
register: async (service: Service) => post("register", (csrfToken) => asCustomdForm(csrfToken, service)),
register: async (service: Service) =>
post("register", (csrfToken) => asCustomdForm(csrfToken, service)),
};
}
const sonos = (
discoveryEnabled: boolean = true,
sonosSeedHost: string | undefined = undefined
): Sonos =>
discoveryEnabled ? autoDiscoverySonos(sonosSeedHost) : SONOS_DISABLED;
export type Discovery = {
auto: boolean;
seedHost?: string;
};
export default sonos;
export default (
sonosDiscovery: Discovery = { auto: true }
): Sonos =>
sonosDiscovery.auto
? autoDiscoverySonos(sonosDiscovery.seedHost)
: SONOS_DISABLED;