import { mapResourceResponse, mapResourceV2Response } from './ResourceClient'; import ApiClient from './ApiClient'; import * as D from './types/Device'; import urls from './urls'; import { mapPlaylistV2Response } from './PlaylistClient'; import { mapPresentationV2Response } from './PresentationClient'; import { mapApplicationVersionResponse, mapApplicationV2Response, } from './ApplicationClient'; import { mapThemeV2Response } from './ThemeClient'; import mapObjectValues from './mapObjectValues'; import { BatchActionStatus, BatchActionStatusResponse, BatchDeviceSettingsRequest, BatchDeviceSettingsResponse, BatchDevicesStatusRequest, BatchDevicesStatusResponse, BatchDeviceStatus, BatchDeviceStatusResponse, } from './types/BatchDeviceSettings'; import { mapLocationACLResponse, mapLocationResponse } from './LocationClient'; import { mapConnectionResponse } from './ConnectionClient'; const mapMetricsResponse = (d: D.DeviceMetricsResponse): D.DeviceMetrics => ({ wifi: d.wifi ? { rssi: d.wifi.rssi, ssid: d.wifi.ssid, lastMetricTime: d.wifi.last_metric_time, } : null, lte: d.lte ? { rssi: d.lte.rssi, lastMetricTime: d.lte.last_metric_time, } : null, system: d.system ? { cpuUsedPercent: d.system.cpu_used_percent, memUsedPercent: d.system.mem_used_percent, diskUsedPercent: d.system.disk_used_percent, lastMetricTime: d.system.last_metric_time, } : null, lastMetricTime: d.last_metric_time, connectionType: d.connection_type, activeMonitors: d.active_monitors, aiCameraStatus: d.ai_camera_status, rxCameraStatus: d.rx_camera_status, rxIrFrameStatus: d.rx_ir_frame_status, }); export const mapDevicePlaylistResponse = ( dp: D.DevicePlaylistResponse, ): D.DevicePlaylist => ({ id: dp.id, name: dp.name, resource: mapResourceResponse(dp.resource), }); export const mapDeviceResponse = (d: D.DeviceResponse): D.Device => ({ id: d.id, name: d.name, description: d.description, model: d.model, features: d.device_features, metrics: d.metrics ? mapMetricsResponse(d.metrics) : null, screenDimensions: d.screen_dimensions, screenOrientation: d.screen_orientation, publishedAt: d.published_at, registeredAt: d.registered_at, resinUuid: d.resin_uuid, playlistId: d.playlist_id, playlist: d.playlist ? mapDevicePlaylistResponse(d.playlist) : null, isAudioOnly: d.is_audio_only, resource: mapResourceResponse(d.resource), lastHeartbeatAt: d.last_heartbeat_at, lastOnlineAt: d.last_online_at, isLite: d.is_lite, isUhd: d.is_uhd, publishAck: d.publish_ack ?? false, publishPlaybackSuccess: d.publish_playback_success ?? false, publishPlaybackError: d.publish_playback_error ?? false, timezone: d.timezone, activeHoursStart: d.active_hours_start, activeHoursEnd: d.active_hours_end, dailyRebootTime: d.daily_reboot_time, dailyRestartTime: d.daily_restart_time, toastRestaurantGuid: d.toast_restaurant_guid, services: d.services, deviceType: d.device_type, screenManufacturer: d.screen_manufacturer, isDisabled: d.is_disabled, screenModel: d.screen_model, screenOsVersion: d.screen_os_version, screenSerialNumber: d.screen_serial_number, location: d.location ? mapLocationResponse(d.location) : null, terminal: d.terminal ? { id: d.terminal.id, externalId: d.terminal.external_id, createdAt: d.terminal.created_at, updatedAt: d.terminal.updated_at, connection: null, } : null, activeMonitors: d.active_monitors, aiCameraStatus: d.ai_camera_status, rxCameraStatus: d.rx_camera_status, rxIrFrameStatus: d.rx_ir_frame_status, }); export const mapDeviceContent = ( d: D.DeviceContentResponse, ): D.DeviceContent => ({ playlistId: d.playlist_id, playlists: d.playlists && mapObjectValues(d.playlists, mapPlaylistV2Response), presentations: d.presentations && mapObjectValues(d.presentations, mapPresentationV2Response), applicationVersions: d.application_versions && mapObjectValues(d.application_versions, mapApplicationVersionResponse), applications: d.applications && mapObjectValues(d.applications, mapApplicationV2Response), themes: d.themes && mapObjectValues(d.themes, mapThemeV2Response), device: d.device && { id: d.device.id, name: d.device.name, timezone: d.device.timezone, r: { resource: mapResourceV2Response(d.device.r.resource), }, }, isMultitimezoneEnabled: d.is_multitimezone_enabled, }); export const mapRecentErrors = ( re: D.RecentDeviceErrorResponse, ): D.RecentDeviceError => ({ timestamp: re.timestamp, deviceId: re.device_id, event: re.event, errorMessage: re.error_message, presentationId: re.presentation_id, presentationName: re.presentation_name, }); export const mapDeviceRegionResponse = ( r: D.PerchviewRegionResponse, ): D.PerchviewRegion => ({ id: r.id ? r.id : '', name: r.name, width: r.width, height: r.height, depth: r.depth, positionX: r.position_x, positionY: r.position_y, positionZ: r.position_z, surgeCount: r.surge_count, surgeFrames: r.surge_frames, volumeAverageFrame: r.volume_average_frame, }); export const mapDevicePerchSettingsReponse = ( pd: D.PerchviewSettingsResponse, ): D.PerchviewSettings => ({ id: pd.id, deviceServiceId: pd.device_service_id, cameraPositionX: pd.camera_position_x, cameraPositionY: pd.camera_position_y, cameraPositionZ: pd.camera_position_z, cameraRotationX: pd.camera_rotation_x, cameraRotationY: pd.camera_rotation_y, cameraRotationZ: pd.camera_rotation_z, minPoints: pd.min_points, frameThreshold: pd.frame_threshold, regions: pd.regions.map((region) => mapDeviceRegionResponse(region)), createdAt: pd.created_at, updatedAt: pd.updated_at, settings: pd.settings, }); export const mapDeviceV2PerchSettingsReponse = ( pd: D.V2PerchviewSettingsResponse, ): D.V2PerchviewSettings => ({ id: pd.id, deviceServiceId: pd.device_service_id, settings: pd.settings, createdAt: pd.created_at, updatedAt: pd.updated_at, }); export const mapBatchActionStatusResponse = ( response: BatchActionStatusResponse, ): BatchActionStatus => ({ action: response.action, status: response.status, createdAt: response.created_at, completedAt: response.completed_at, message: response.message, }); export const mapBatchDeviceStatusResponse = ( response: BatchDeviceStatusResponse, ): BatchDeviceStatus => ({ deviceId: response.device_id, profileId: response.profile_id, actionStatus: response.action_status.map((actionStatus) => mapBatchActionStatusResponse(actionStatus), ), }); export const mapDeviceChargeResponse = ( response: D.DeviceChargeResponse, ): D.DeviceCharge => ({ id: response.id, deviceId: response.device_id, orderId: response.order_id, externalId: response.external_id, status: response.status, items: response.items, error: response.error, updatedAt: response.updated_at, createdAt: response.created_at, subTotal: response.sub_total, tip: response.tip, tax: response.tax, total: response.total, cardType: response.card_type, cardBrand: response.card_brand, cardLast4: response.card_last4, transactionType: response.transaction_type, entryMode: response.entry_mode, authCode: response.auth_code, transactionNumber: response.transaction_number, pinVerified: response.pin_verified, verificationResult: response.verification_result, statusIndicator: response.status_indicator, applicationIdentifier: response.application_identifier, applicationName: response.application_name, applicationCryptogram: response.application_cryptogram, applicationData: response.application_data, applicationResponseCode: response.application_response_code, cardVerificationMethod: response.card_verification_method, }); export const mapV5DevicePlaylistResponse = ( p: D.V5DevicePlaylistResponse, ): D.V5DevicePlaylist => ({ id: p.id, name: p.name, lastActivityAt: p.last_activity_at, updatedAt: p.updated_at, ownedBy: { id: p.owned_by?.id, email: p.owned_by?.email, name: p.owned_by?.name, thumbnailUrl: p.owned_by?.thumbnail_url, domainRole: p.owned_by?.domain_role, }, }); export const mapV5DeviceResponse = (d: D.V5DeviceResponse): D.V5Device => ({ id: d.id, macAddress: d.mac_address, playlistId: d.playlist_id, name: d.name, description: d.description, model: d.model, resourceId: d.resource_id, lastActivityAt: d.last_activity_at, updatedAt: d.updated_at, publishedAt: d.published_at, screenDimensions: d.screen_dimensions, screenOrientation: d.screen_orientation, registrationStatus: d.registration_status, registeredAt: d.registered_at, resinUuid: d.resin_uuid, isDisabled: d.is_disabled, isAudioOnly: d.is_audio_only, timezone: d.timezone, dailyRestartTime: d.daily_restart_time, dailyRebootTime: d.daily_reboot_time, activeHoursStart: d.active_hours_start, activeHoursEnd: d.active_hours_end, lastHeartbeatAt: d.last_heartbeat_at, isLite: d.is_lite, publishAck: d.publish_ack, publishPlaybackSuccess: d.publish_playback_success, publishPlaybackError: d.publish_playback_error, toastRestaurantGuid: d.toast_restaurant_guid, isUhd: d.is_uhd, services: d.services, deviceFeatures: d.device_features, ownedBy: { id: d.owned_by?.id, email: d.owned_by?.email, name: d.owned_by?.name, thumbnailUrl: d.owned_by?.thumbnail_url, domainRole: d.owned_by?.domain_role, }, metrics: d.metrics ? mapMetricsResponse(d.metrics) : null, playlist: d.playlist ? mapV5DevicePlaylistResponse(d.playlist) : null, location: d.location ? mapLocationResponse(d.location) : null, tags: d.tags, acl: d.acl?.map((acl) => mapLocationACLResponse(acl)), deviceType: d.device_type, screenManufacturer: d.screen_manufacturer, screenModel: d.screen_model, screenOsVersion: d.screen_os_version, screenSerialNumber: d.screen_serial_number, terminal: d.terminal ? { id: d.terminal.id, externalId: d.terminal.external_id, createdAt: d.terminal.created_at, updatedAt: d.terminal.updated_at, connection: null, } : null, activeMonitors: d.active_monitors, aiCameraStatus: d.ai_camera_status, rxCameraStatus: d.rx_camera_status, rxIrFrameStatus: d.rx_ir_frame_status, }); export const mapV3DeviceToV5Device = ( v3: D.DeviceResponse, v5: D.V5Device, ): D.V5Device => ({ ...v5, activeHoursEnd: v3.active_hours_end, activeHoursStart: v3.active_hours_start, dailyRebootTime: v3.daily_reboot_time, dailyRestartTime: v3.daily_restart_time, description: v3.description, isAudioOnly: v3.is_audio_only, isUhd: v3.is_uhd, name: v3.name, playlistId: v3.playlist_id, tags: v3.resource?.r?.tags || [], screenDimensions: v3.screen_dimensions, screenOrientation: v3.screen_orientation, timezone: v3.timezone, lastHeartbeatAt: v3.last_heartbeat_at, toastRestaurantGuid: v3.toast_restaurant_guid, }); export const mapV5DeviceToV3Device = ( v5: D.V5DeviceResponse, ): D.DeviceResponse => ({ id: v5.id, name: v5.name, description: v5.description, model: v5.model, device_features: v5.device_features, metrics: v5.metrics, published_at: v5.published_at, registered_at: v5.registered_at, screen_dimensions: v5.screen_dimensions, screen_orientation: v5.screen_orientation, application_thumbnail_url: '', resin_uuid: v5.resin_uuid, playlist_id: v5.playlist_id, playlist: { id: v5.playlist?.id || '', resource: { id: '', profile: { id: v5.playlist?.owned_by?.id || '', email: v5.playlist?.owned_by?.email || '', name: v5.playlist?.owned_by?.name || '', thumbnail_url: v5.playlist?.owned_by?.thumbnail_url || '', domain_id: v5.playlist?.owned_by?.domain_id || '', domain_role: v5.playlist?.owned_by?.domain_role || 'restricted', }, domain: null, created_at: '', updated_at: v5.playlist?.updated_at || '', last_activity_at: v5.playlist?.last_activity_at || '', deleted_at: '', parent_folder_id: '', r: { resource_acls: null, tags: null, }, }, name: v5.playlist?.name || '', }, is_uhd: v5.is_uhd, is_audio_only: v5.is_audio_only, resource: { id: v5.resource_id, profile: { id: v5.owned_by?.id || '', email: v5.owned_by?.email || '', name: v5.owned_by?.name || '', thumbnail_url: v5.owned_by?.thumbnail_url || '', domain_id: v5.owned_by?.domain_id || '', domain_role: v5.owned_by?.domain_role || 'restricted', }, domain: null, created_at: '', updated_at: v5.updated_at || '', last_activity_at: v5.last_activity_at, deleted_at: '', parent_folder_id: '', r: { resource_acls: v5.acl?.map((acl) => ({ id: acl.id, resource_id: v5.resource_id, profile_id: v5.owned_by?.id || '', grant_profile_id: acl.grant_profile?.id, grant_domain_id: acl.grant_domain_id, grant_scope: acl.grant_scope, grant_folder_path: acl.grant_folder_path, read_grant: acl.read_grant, update_grant: acl.update_grant, delete_grant: acl.delete_grant, custom_access_grants: acl.custom_access_grants || [], share_grant: acl.share_grant, full_grant: acl.full_grant, created_at: '', updated_at: '', r: { grant_profile: { ...acl.grant_profile, thumbnail_url: acl.grant_profile?.thumbnail_url || '', domain_id: '', }, profile: { ...v5.owned_by, domain_id: '' }, }, })), tags: v5.tags?.map((v5tag) => ({ ...v5tag, resource_id: '', created_at: '', profile_id: '', })), }, }, last_heartbeat_at: v5.last_heartbeat_at, last_online_at: '', is_lite: v5.is_lite, publish_ack: v5.publish_ack, publish_playback_success: v5.publish_playback_success, publish_playback_error: v5.publish_playback_error, timezone: v5.timezone, active_hours_start: v5.active_hours_start, active_hours_end: v5.active_hours_end, daily_reboot_time: v5.daily_reboot_time, daily_restart_time: v5.daily_restart_time, toast_restaurant_guid: v5.toast_restaurant_guid, services: v5.services, device_type: v5.device_type, screen_manufacturer: v5.screen_manufacturer, screen_model: v5.screen_model, screen_os_version: v5.screen_os_version, screen_serial_number: v5.screen_serial_number, location: v5.location, terminal: v5.terminal, active_monitors: v5.active_monitors, ai_camera_status: v5.ai_camera_status, rx_camera_status: v5.rx_camera_status, rx_ir_frame_status: v5.rx_ir_frame_status, is_disabled: v5.is_disabled, }); const mapDeviceTerminalResponse = ( d: D.DeviceTerminalResponse, ): D.DeviceTerminal => ({ id: d.id, deviceId: d.device_id, externalId: d.external_id, createdAt: d.created_at, updatedAt: d.updated_at, connection: mapConnectionResponse(d.connection), }); export default class DeviceClient { async getDevice(this: ApiClient, id: string): Promise { const data = await this.requestProtected< D.GetDevicesRequest, D.GetDevicesResponse >({ method: 'GET', url: `${urls.devices()}?filter=id eq ${id}`, }); return mapDeviceResponse(data[0]); } async enableDeviceService( this: ApiClient, id: string, service: string, ): Promise { const data = await this.requestProtected< D.DeviceServiceChangeRequest, D.DeviceServiceChangeResponse >({ method: 'PUT', url: urls.deviceService(id, service), }); return data; } async disableDeviceService( this: ApiClient, id: string, service: string, ): Promise { const data = await this.requestProtected< D.DeviceServiceChangeRequest, D.DeviceServiceChangeResponse >({ method: 'DELETE', url: urls.deviceService(id, service), }); return data; } async getDeviceAISettings( this: ApiClient, id: string, ): Promise { const data = await this.requestProtected< D.GetDeviceAIRequest, D.GetDeviceAIResponse >({ method: 'GET', url: urls.deviceAISettings(id), }); return data; } async setDeviceAISettings( this: ApiClient, id: string, settings: D.JSONObject, ): Promise { const data = await this.requestProtected< { settings: D.JSONObject }, D.GetDeviceAIResponse >({ method: 'POST', url: urls.deviceAISettings(id), body: { settings: settings }, }); return data; } async setDeviceAILicenseKey( this: ApiClient, id: string, license_key: string, ): Promise { const data = await this.requestProtected< { license_key: string }, D.GetDeviceAIResponse >({ method: 'POST', url: urls.deviceAILicenseKey(id), body: { license_key: license_key }, }); return data; } async startDeviceAIVideo( this: ApiClient, id: string, ): Promise { const data = await this.requestProtected< { video_stream: boolean }, D.GetDeviceAIVideoResponse >({ method: 'POST', url: urls.deviceAIVideo(id), body: { video_stream: true }, }); return data; } async stopDeviceAIVideo( this: ApiClient, id: string, ): Promise { const data = await this.requestProtected< { video_stream: boolean }, D.GetDeviceAIResponse >({ method: 'POST', url: urls.deviceAIVideo(id), body: { video_stream: false }, }); return data; } async getDevicePerchviewSettings( this: ApiClient, id: string, ): Promise { const data = await this.requestProtected< D.GetPerchviewSettingsRequest, D.PerchviewSettingsResponse >({ method: 'GET', url: urls.devicePerchviewSettings(id), }); return mapDevicePerchSettingsReponse(data); } async getOwnPerchviewSettings( this: ApiClient, ): Promise { const data = await this.requestProtected< D.GetPerchviewSettingsRequest, D.V2PerchviewSettingsResponse >({ method: 'GET', url: urls.deviceOwnPerchviewSettings(), }); return mapDeviceV2PerchSettingsReponse(data); } async setDevicePerchviewSettings( this: ApiClient, id: string, settings: D.PostPerchviewSettingsRequest, ): Promise { const data = await this.requestProtected< D.PostPerchviewSettingsRequest, D.PerchviewSettingsResponse >({ method: 'POST', url: urls.devicePerchviewSettings(id), body: settings, }); return mapDevicePerchSettingsReponse(data); } async updateDevicePerchviewSettings( this: ApiClient, id: string, settings: D.PatchPerchviewSettingsRequest, ): Promise { const data = await this.requestProtected< D.PatchPerchviewSettingsRequest, D.PerchviewSettingsResponse >({ method: 'PATCH', url: urls.devicePerchviewSettings(id), body: settings, }); return mapDevicePerchSettingsReponse(data); } // Perchview Settings V2 async getDeviceV2PerchviewSettings( this: ApiClient, id: string, ): Promise { const data = await this.requestProtected< D.GetPerchviewSettingsRequest, D.V2PerchviewSettingsResponse >({ method: 'GET', url: urls.deviceV2PerchviewSettings(id), }); return mapDeviceV2PerchSettingsReponse(data); } async setDeviceV2PerchviewSettings( this: ApiClient, id: string, settings: D.PostV2PerchviewSettingsRequest, ): Promise { const data = await this.requestProtected< D.PostV2PerchviewSettingsRequest, D.V2PerchviewSettingsResponse >({ method: 'POST', url: urls.deviceV2PerchviewSettings(id), body: settings, }); return mapDeviceV2PerchSettingsReponse(data); } async updateDeviceV2PerchviewSettings( this: ApiClient, id: string, settings: D.PatchV2PerchviewSettingsRequest, ): Promise { const data = await this.requestProtected< D.PatchV2PerchviewSettingsRequest, D.V2PerchviewSettingsResponse >({ method: 'PATCH', url: urls.deviceV2PerchviewSettings(id), body: settings, }); return mapDeviceV2PerchSettingsReponse(data); } async batchDeviceSettings( this: ApiClient, params: BatchDeviceSettingsRequest, ): Promise { const data = await this.requestProtected< BatchDeviceSettingsRequest, BatchDeviceSettingsResponse >({ method: 'POST', url: urls.deviceBatchSettings(), body: params, }); return data; } async getBatchDeviceStatus(this: ApiClient): Promise { const data = await this.requestProtected< BatchDevicesStatusRequest, BatchDevicesStatusResponse >({ method: 'GET', url: urls.deviceBatchStatus(), }); return data.map(mapBatchDeviceStatusResponse); } async getDevices( this: ApiClient, filter?: { ids: string[] }, ): Promise { const filterQs = filter ? `filter=id in ${filter.ids.join(',')}` : ''; const data = await this.requestProtected< D.GetDevicesRequest, D.GetDevicesResponse >({ method: 'GET', url: `${urls.devices()}?${filterQs}`, }); return data.map(mapDeviceResponse); } async getV4ReportingDevices( this: ApiClient, query?: string, ): Promise { const res = await this.requestProtected< D.GetV4ReportingDevicesRequest, D.GetV4ReportingDevicesResponse >({ method: 'GET', url: urls.v4ReportingDevices(query), }); return res; } async getV5Device(this: ApiClient): Promise { const res = await this.requestProtected< D.GetV5DeviceRequest, D.GetV5DeviceResponse >({ method: 'GET', url: urls.v5Device(), }); return { name: res.name, registrationStatus: res.registration_status, confirmationToken: res.confirmation_token, publishedAt: res.published_at, }; } async getV5Devices(this: ApiClient, query?: string): Promise { const res = await this.requestProtected< D.GetV5DevicesRequest, D.GetV5DevicesResponse >({ method: 'GET', url: urls.v5Devices(query), }); return { total: res.total, data: res.data?.map((device) => mapV5DeviceResponse(device)), }; } async updateDevice( this: ApiClient, id: string, params: D.Device, ): Promise { const data = await this.requestProtected< D.UpdateDeviceRequest, D.UpdateDeviceResponse >({ method: 'PATCH', url: urls.device(id), body: { name: params.name, screen_dimensions: params.screenDimensions, screen_orientation: params.screenOrientation, description: params.description, playlist_id: params.playlistId, is_uhd: params.isUhd, is_audio_only: params.isAudioOnly, timezone: params.timezone, active_hours_start: params.activeHoursStart, active_hours_end: params.activeHoursEnd, daily_reboot_time: params.dailyRebootTime, daily_restart_time: params.dailyRestartTime, resource: params.resource && { r: params.resource.r && { tags: params.resource.r.tags?.map((t) => ({ type: t.type, key: t.key, label: t.label, value: t.value, })), }, }, toast_restaurant_guid: params.toastRestaurantGuid, }, }); return mapDeviceResponse(data); } // Currently endpoint is returning type Device not V5Device // So we are simulating the response to be V5Device async updateV5Device( this: ApiClient, id: string, params: D.V5Device, ): Promise { const data = await this.requestProtected< D.UpdateDeviceRequest, D.UpdateDeviceResponse >({ method: 'PATCH', url: urls.device(id), body: { name: params.name, screen_dimensions: params.screenDimensions, screen_orientation: params.screenOrientation, description: params.description, playlist_id: params.playlistId, is_uhd: params.isUhd, is_audio_only: params.isAudioOnly, timezone: params.timezone, active_hours_start: params.activeHoursStart, active_hours_end: params.activeHoursEnd, daily_reboot_time: params.dailyRebootTime, daily_restart_time: params.dailyRestartTime, resource: params.tags && { r: { tags: params.tags?.map((t) => ({ type: t.type, key: t.key, label: t.label, value: t.value, })), }, }, toast_restaurant_guid: params.toastRestaurantGuid, }, }); return mapV3DeviceToV5Device(data, params); } async restartDevice(this: ApiClient, id: string): Promise { await this.requestProtected< D.RestartDeviceRequest, D.RestartDeviceResponse >({ method: 'POST', url: urls.deviceRestart(id), }); } async rebootDevice(this: ApiClient, id: string): Promise { await this.requestProtected({ method: 'POST', url: urls.deviceReboot(id), }); } async publishDevice(this: ApiClient, id: string): Promise { const data = await this.requestProtected< D.PublishDeviceRequest, D.PublishDeviceResponse >({ method: 'POST', url: urls.devicePublish(id), }); return mapDeviceResponse(data); } async registerDevice( this: ApiClient, { activationCode, name, timezone, locationId }: D.RegisterDevice, ): Promise { return mapDeviceResponse( await this.requestProtected< D.RegisterDeviceRequest, D.RegisterDeviceResponse >({ method: 'POST', url: urls.devicesRegister(), body: { confirmation_token: activationCode.toLowerCase(), name: name ? name.trim() : activationCode, timezone, location_id: locationId, }, }), ); } async getSYBSoundZone(this: ApiClient, id: string): Promise { const data = await this.requestProtected< D.GetSYBSoundZoneRequest, D.GetSYBSoundZoneResponse >({ method: 'GET', url: urls.deviceSYBSoundZone(id), }); // We need the id to be the device id to lookup the sound zone and // we don't currently care about the actual sound zone id because // auth to SYB is uses the device id. return data ? { id, name: data.name } : { id, name: '' }; } async generateSYBPairingCode( this: ApiClient, id: string, ): Promise { const data = await this.requestProtected< D.GenerateSYBPairingCodeRequest, D.GenerateSYBPairingCodeResponse >({ method: 'POST', url: urls.deviceSYBGeneratePairingCode(id), }); // We need the id to be the device id to lookup the pairing code. return { id, pairingCode: data.pairing_code, }; } async moveDeviceToFolder( this: ApiClient, deviceId: string, folderId: string, ): Promise { await this.requestProtected<{ folder_id: string }, void>({ method: 'POST', url: urls.deviceMoveToFolder(deviceId), body: { folder_id: folderId, }, }); } async getAffectedDevices( this: ApiClient, body: { presentationIds?: string[]; playlistIds?: string[]; folderIds?: string[]; }, ): Promise { const data = await this.requestProtected< D.GetAffectedDevicesRequest, D.GetAffectedDevicesResponse >({ method: 'POST', url: urls.devicesAffectedDevices(), body: { presentation_ids: body.presentationIds || [], playlist_ids: body.playlistIds || [], folder_ids: body.folderIds || [], }, }); return data.map((d) => ({ id: d.id, name: d.name, })); } async deviceHeartbeat( this: ApiClient, body: D.DeviceHeartbeatRequest = {}, ): Promise { const data = await this.requestProtected< D.DeviceHeartbeatRequest, D.DeviceHeartbeatResponse >({ method: 'POST', url: urls.deviceHeartbeat(), body: { connection_type: body.connection_type, ssid: body.ssid, rssi: body.rssi, }, }); return { name: data.name, registrationStatus: data.registration_status, confirmationToken: data.confirmation_token, isDisabled: data.is_disabled, screenOrientation: data.screen_orientation, publishedAt: data.published_at, publishAck: data.publish_ack ?? false, publishPlaybackSuccess: data.publish_playback_success ?? false, publishPlaybackError: data.publish_playback_error ?? false, polyServiceLevel: data.poly_service_level, }; } async getDevicePublishedContent( this: ApiClient, ): Promise { const data = await this.requestProtected< void, D.DevicePublishedContentResponse >({ method: 'GET', url: urls.devicePublishedContent(), }); return mapDeviceContent(data); } async getDeviceAdContent(this: ApiClient): Promise { const data = await this.requestProtected({ method: 'GET', url: urls.deviceAdContent(), }); return mapDeviceContent(data); } async devicePubnubAuth( this: ApiClient, sessionId: string, ): Promise { const data = await this.requestProtected< D.DevicePubnubAuthRequest, D.DevicePubnubAuthResponse >({ method: 'POST', url: urls.devicePubnubAuth(), body: { session_id: sessionId, }, }); return { authKey: data.auth_key, channelId: data.channel_id, expiresAt: data.expires_at, }; } async unregisterDevice(this: ApiClient, deviceId: string): Promise { await this.requestProtected({ method: 'POST', url: urls.deviceUnregister(deviceId), }); } async getRecentDeviceErrors(this: ApiClient): Promise { const data = await this.requestProtected< void, D.GetRecentDeviceErrorsResponse >({ method: 'GET', url: urls.devicesRecentErrors(), }); return data.map(mapRecentErrors); } async enableMultiTimezone( this: ApiClient, isDomainUser = true, ): Promise { return await this.requestProtected({ method: 'PATCH', url: urls.enableMultiTimeZone(isDomainUser), }); } async createDeviceCharge( this: ApiClient, params: D.CreateDeviceChargeRequest, ): Promise { const data = await this.requestProtected< Record, D.DeviceChargeResponse >({ method: 'POST', url: urls.deviceCharges(), body: { order_id: params.orderId, sub_total: params.subTotal, tip: params.tip, tax: params.tax, total: params.total, items: params.items, }, }); return mapDeviceChargeResponse(data); } async updateDeviceCharge( this: ApiClient, chargeId: string, params: D.UpdateDeviceChargeRequest, ): Promise { const data = await this.requestProtected< Record, D.DeviceChargeResponse >({ method: 'PATCH', url: urls.deviceCharge(chargeId), body: { external_id: params.externalId, status: params.status, error: params.error, card_type: params.cardType, card_brand: params.cardBrand, transaction_type: params.transactionType, pin_verified: params.pinVerified, entry_mode: params.entryMode, card_last4: params.cardLast4, auth_code: params.authCode, transaction_number: params.transactionNumber, verification_result: params.verificationResult, status_indicator: params.statusIndicator, application_identifier: params.applicationIdentifier, application_name: params.applicationName, application_cryptogram: params.applicationCryptogram, application_data: params.applicationData, application_response_code: params.applicationResponseCode, card_verification_method: params.cardVerificationMethod, }, }); return mapDeviceChargeResponse(data); } async getDeviceTerminalStatus( this: ApiClient, ): Promise { const data = await this.requestProtected({ method: 'GET', url: urls.deviceTerminalStatus(), }); return data; } async getDeviceTerminal( this: ApiClient, deviceId: string, ): Promise { const data = await this.requestProtected({ method: 'GET', url: urls.deviceTerminal(deviceId), }); return mapDeviceTerminalResponse(data); } async deleteDeviceTerminal( this: ApiClient, deviceId: string, ): Promise { const data = await this.requestProtected< D.DeleteDeviceTerminalRequest, D.DeleteDeviceTerminalResponse >({ method: 'DELETE', url: urls.deviceTerminal(deviceId), }); return data; } }