UNPKG

@katesthings/smartsonos

Version:

Utility functions to control Sonos speakers

133 lines (132 loc) 6.94 kB
'use strict'; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; const SmartState = require('@katesthings/smartstate'); const axios = require("axios"); function getSonosData(key) { return __awaiter(this, void 0, void 0, function* () { return yield SmartState.getHomeMode('niwot', 'sonos-' + key); }); } ; function putSonosData(key, value) { return __awaiter(this, void 0, void 0, function* () { yield SmartState.putHomeMode('niwot', 'sonos-' + key, value); }); } ; function refreshToken() { return __awaiter(this, void 0, void 0, function* () { let accessToken; try { const refreshToken = yield getSonosData('refresh-token'); console.log('refreshToken - retrieved refresh token: ', refreshToken); const urlToken = 'https://api.sonos.com/login/v3/oauth/access'; const params = new URLSearchParams(); params.append('grant_type', 'refresh_token'); params.append('refresh_token', refreshToken); console.log('refreshToken - initialized parameters: ', params); const config = { headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8', 'Authorization': 'Basic ZDMxM2EyYTAtOTYwZS00ODFmLTlmYzctM2MwMmU0MzY2OTU1OjNhY2ZkZmQ5LTI3YzQtNGE3NC05NzhkLWUyN2ZlZmE0NWJkMg==' } }; console.log('refreshToken - refreshing access token'); axios.post(urlToken, params, config).then((result) => { console.log('refreshToken - Success! Data: ', result.data); const token_data = result.data; accessToken = token_data.access_token; putSonosData('token-time', new Date()); putSonosData('access-token', token_data.access_token); putSonosData('refresh-token', token_data.refresh_token); putSonosData('expires-in', token_data.expires_in.toString()); }).catch((err) => { console.log('refreshToken - error refreshing token: ', err); }); } catch (err) { console.log('refreshToken - error getting refresh token from DynamoDB: ', err); } return accessToken; }); } ; function getAccessToken() { return __awaiter(this, void 0, void 0, function* () { let accessToken; try { console.log('getAccessToken - getting Sonos data from DyanmoDB'); accessToken = yield getSonosData('access-token'); const tokenTime = new Date(yield getSonosData('token-time')); const expiresIn = yield getSonosData('expires-in'); const currentTime = new Date(); const elapsedTime = (currentTime.getTime() - tokenTime.getTime()) / 1000; console.log('getAccessToken - token-time: ', tokenTime, ', expires-in: ', expiresIn, ', time gap: ', elapsedTime); if (elapsedTime > expiresIn) { console.log('getAccessToken - token expired, need to refresh: ', elapsedTime); accessToken = yield refreshToken(); } } catch (err) { console.log('getAccessToken - error getting refresh token from DynamoDB: ', err); } return accessToken; }); } ; function controlSpeakers(context, speakers, command) { return __awaiter(this, void 0, void 0, function* () { try { const access_token = yield getAccessToken(); const sonosControl = axios.create({ baseURL: 'https://api.ws.sonos.com/control/api/v1', timeout: 5000, headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + access_token } }); console.log('controlSpeakers - getting households'); sonosControl.get('households').then((result) => { const householdId = result.data.households[0].id; console.log('controlSpeakers - household ID: ', householdId); sonosControl.get('households/' + householdId + '/groups').then((result) => { const sonosPlayers = result.data.players; const sonosGroups = result.data.groups; const speakerDevices = context.config[speakers]; for (const speaker of speakerDevices) { const speakerId = speaker.deviceConfig.deviceId; context.api.devices.get(speakerId).then((speakerInfo) => { const speakerName = speakerInfo.name; console.log('controlSpeakers - find speaker: ', speakerName, ', speakerId: ', speakerId); const player = sonosPlayers.find(speaker => speaker.name === speakerName); console.log('controlSpeakers - player found: ', player, ', id: ', player.id); for (const group of sonosGroups) { const groupPlayers = group.playerIds; if (groupPlayers.indexOf(player.id) > -1) { const urlControl = '/groups/' + group.id + '/playback/' + command; console.log('controlSpeakers - command: ', command, ', urlControl: ', urlControl); sonosControl.post(urlControl).then((result) => { console.log('controlSpeakers - Success! Data: ', result.data); ; }).catch((err) => { console.log('controlSpeakers - error controlling speaker: ', err, ', command: ', command); }); } } }); } }).catch((err) => { console.log('controlSpeakers - error getting groups/speakers: ', err); }); }).catch((err) => { console.log('controlSpeakers - error getting household(s): ', err); }); } catch (err) { console.log('controlSpeakers - error controlling Sonos: ', err); } }); } ; module.exports.controlSpeakers = controlSpeakers;