Files
ring-mqtt/lib/streaming/streaming-connection-base.js
tsightler b8338e30de Release 5.1.0 (#537)
* Use MQTT for start-stream debug messages
* Fix ANSI colors
* Refactor event URL management
* Fix subscription detection
* Improve event URL expiry handling by parsing Amazon S3 expire time
* Convert to ESM/replace colors with chalk
* Force colors for chalk
* Migrate to ESM
* Fix stop of keepalive stream
* Add transcoded event selections
* Update event URL on raw/trancoded toggle
* Switch to per-camera livecall threads
* Customized WebRTC functions
Mostly copied from ring-client-api with port to pure Javascript, removal of unneeded features and additional debugging modified for use as worker thread with ring-mqtt.  Allows easier testing with updated Werift versions.
* Add nightlight enable/disable
* Include nightlight state as attribute
* Only pro versions have nightlight
* Tweak battery level reporting for dual battery cameras
* Release 5.1.0
2023-02-02 20:59:09 -05:00

97 lines
2.8 KiB
JavaScript

// This code is largely copied from ring-client-api, but converted from Typescript
// to straight Javascript and some code not required for ring-mqtt removed.
// Much thanks to @dgreif for the original code which is the basis for this work.
import { WeriftPeerConnection } from './peer-connection.js'
import { Subscribed } from './subscribed.js'
import { fromEvent, ReplaySubject } from 'rxjs'
import { concatMap } from 'rxjs/operators'
export class StreamingConnectionBase extends Subscribed {
constructor(ws) {
super()
this.ws = ws
this.onCallAnswered = new ReplaySubject(1)
this.onCallEnded = new ReplaySubject(1)
this.onMessage = new ReplaySubject()
this.hasEnded = false
const pc = new WeriftPeerConnection()
this.pc = pc
this.onAudioRtp = pc.onAudioRtp
this.onVideoRtp = pc.onVideoRtp
this.onWsOpen = fromEvent(this.ws, 'open')
const onMessage = fromEvent(this.ws, 'message')
const onError = fromEvent(this.ws, 'error')
const onClose = fromEvent(this.ws, 'close')
this.addSubscriptions(
onMessage.pipe(concatMap((event) => {
const message = JSON.parse(event.data)
this.onMessage.next(message)
return this.handleMessage(message)
})).subscribe(),
onError.subscribe((e) => {
this.callEnded()
}),
onClose.subscribe(() => {
this.callEnded()
}),
this.pc.onConnectionState.subscribe((state) => {
if (state === 'failed') {
this.callEnded()
}
if (state === 'closed') {
this.callEnded()
}
})
)
}
activate() {
// the activate_session message is required to keep the stream alive longer than 70 seconds
this.sendSessionMessage('activate_session')
this.sendSessionMessage('stream_options', {
audio_enabled: true,
video_enabled: true,
})
}
sendMessage(message) {
if (this.hasEnded) {
return
}
this.ws.send(JSON.stringify(message))
}
callEnded() {
if (this.hasEnded) {
return
}
try {
this.sendMessage({
reason: { code: 0, text: '' },
method: 'close',
})
this.ws.close()
}
catch (_) {
// ignore any errors since we are stopping the call
}
this.hasEnded = true
this.unsubscribe()
this.onCallEnded.next()
this.pc.close()
}
stop() {
this.callEnded()
}
requestKeyFrame() {
this.pc.requestKeyFrame?.()
}
}