mirror of
https://github.com/tsightler/ring-mqtt.git
synced 2025-09-26 21:01:12 +08:00
Release 5.0.0
This commit is contained in:
@@ -55,18 +55,19 @@ RUN apk add --no-cache tar git libcrypto1.1 libssl1.1 musl-utils musl bash curl
|
||||
ENTRYPOINT [ "/init" ]
|
||||
|
||||
EXPOSE 8554/tcp
|
||||
EXPOSE 55123/tcp
|
||||
|
||||
ARG BUILD_VERSION
|
||||
ARG BUILD_DATE
|
||||
|
||||
LABEL \
|
||||
io.hass.name="Ring Device Integration via MQTT" \
|
||||
io.hass.name="Ring-MQTT with Video Streaming" \
|
||||
io.hass.description="Home Assistant Community Add-on for Ring Devices" \
|
||||
io.hass.type="addon" \
|
||||
io.hass.version=${BUILD_VERSION} \
|
||||
maintainer="Tom Sightler <tsightler@gmail.com>" \
|
||||
org.opencontainers.image.title="Ring Device Integration via MQTT" \
|
||||
org.opencontainers.image.description="Home Assistant Community Add-on for Ring Devices" \
|
||||
org.opencontainers.image.title="Ring-MQTT with Video Streaming" \
|
||||
org.opencontainers.image.description="Intergrate wtih Ring devices using MQTT/RTSP" \
|
||||
org.opencontainers.image.authors="Tom Sightler <tsightler@gmail.com> (and various other contributors)" \
|
||||
org.opencontainers.image.licenses="MIT" \
|
||||
org.opencontainers.image.source="https://github.com/tsightler/ring-mqtt" \
|
||||
|
@@ -1,7 +1,6 @@
|
||||
const mqttApi = require('mqtt')
|
||||
const debug = require('debug')('ring-mqtt')
|
||||
const colors = require('colors/safe')
|
||||
const utils = require('./utils.js')
|
||||
|
||||
class Mqtt {
|
||||
constructor() {
|
||||
@@ -27,7 +26,7 @@ class Mqtt {
|
||||
this.start()
|
||||
} catch (error) {
|
||||
debug(error)
|
||||
debug(colors.red('Couldn\'t authenticate to MQTT broker. Please check the broker and configuration settings.'))
|
||||
debug(colors.red(`Could not authenticate to MQTT broker. Please check the broker and configuration settings.`))
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
@@ -81,7 +80,7 @@ class Mqtt {
|
||||
async processMessage(topic, message) {
|
||||
message = message.toString()
|
||||
if (topic === this.config.hass_topic || topic === 'hass/status' || topic === 'hassio/status') {
|
||||
debug('Home Assistant state topic '+topic+' received message: '+message)
|
||||
debug(`Home Assistant state topic ${topic} received message: ${message}`)
|
||||
if (message === 'online') {
|
||||
this.ring.republishDevices(this.client)
|
||||
}
|
||||
|
12
lib/ring.js
12
lib/ring.js
@@ -44,7 +44,7 @@ class Ring {
|
||||
} catch(error) {
|
||||
this.client = false
|
||||
debug(colors.brightYellow(error.message))
|
||||
debug(colors.brightYellow('Failed to establed connection to Ring API using '+tokenSource+' refresh token.'))
|
||||
debug(colors.brightYellow(`Failed to establed connection to Ring API using ${tokenSource} refresh token.`))
|
||||
}
|
||||
return this.client
|
||||
}
|
||||
@@ -67,7 +67,7 @@ class Ring {
|
||||
// Only publish if previous state was actually disconnected
|
||||
if (!location.isConnected) {
|
||||
location.isConnected = true
|
||||
debug('Websocket for location id '+location.locationId+' is connected')
|
||||
debug(`Websocket for location id ${location.locationId} is connected`)
|
||||
this.publishDevices(location)
|
||||
}
|
||||
} else {
|
||||
@@ -76,7 +76,7 @@ class Ring {
|
||||
await utils.sleep(30)
|
||||
if (!location.onConnected._value) {
|
||||
location.isConnected = false
|
||||
debug('Websocket for location id '+location.locationId+' is disconnected')
|
||||
debug(`Websocket for location id ${location.locationId} is disconnected`)
|
||||
this.devices.forEach(device => {
|
||||
if (device.locationId == location.locationId && !device.camera) {
|
||||
device.offline()
|
||||
@@ -89,7 +89,7 @@ class Ring {
|
||||
this.publishDevices(location)
|
||||
}
|
||||
} else {
|
||||
debug('No devices found for location ID '+location.id)
|
||||
debug(`No devices found for location ID ${location.id}`)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -181,7 +181,7 @@ class Ring {
|
||||
}
|
||||
// Output any unsupported devices to debug with warning
|
||||
unsupportedDevices.forEach(deviceType => {
|
||||
debug(colors.yellow(' Unsupported device: '+deviceType))
|
||||
debug(colors.yellow(` Unsupported device: ${deviceType}`))
|
||||
})
|
||||
}
|
||||
debug(colors.green('-'.repeat(80)))
|
||||
@@ -325,7 +325,7 @@ class Ring {
|
||||
const componentCommand = topic.split("/").slice(-2).join("/")
|
||||
cmdDevice.processCommand(message, componentCommand)
|
||||
} else {
|
||||
debug('Received MQTT message for device Id '+deviceId+' at location Id '+locationId+' but could not find matching device')
|
||||
debug(`Received MQTT message for device Id ${deviceId} at location Id ${locationId} but could not find matching device`)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -37,12 +37,11 @@ class TokenApp {
|
||||
return
|
||||
}
|
||||
|
||||
this.runMode = runMode
|
||||
const webdir = __dirname+'/../web'
|
||||
let restClient
|
||||
|
||||
this.listener = this.app.listen(55123, () => {
|
||||
if (this.runMode === 'standard') {
|
||||
if (this.runMode !== 'docker') {
|
||||
debug('Go to http://<host_ip_address>:55123/ to generate a valid token.')
|
||||
}
|
||||
})
|
||||
@@ -92,22 +91,16 @@ class TokenApp {
|
||||
res.sendFile('code.html', {root: webdir})
|
||||
}
|
||||
if (generatedToken) {
|
||||
if (this.runMode !== 'docker') {
|
||||
res.sendFile('restart.html', {root: webdir})
|
||||
this.token.generated = generatedToken.refresh_token
|
||||
if (this.runMode === 'standard') {
|
||||
await this.listener.close()
|
||||
this.listener = false
|
||||
}
|
||||
} else {
|
||||
res.cookie('token', generatedToken.refresh_token, { maxAge: 1000, encode: String })
|
||||
res.sendFile('token.html', {root: webdir})
|
||||
await utils.sleep(2)
|
||||
process.exit(0)
|
||||
}
|
||||
res.sendFile('restart.html', {root: webdir})
|
||||
this.token.generated = generatedToken.refresh_token
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async stop() {
|
||||
await this.listener.close()
|
||||
this.listener = false
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new TokenApp()
|
||||
|
43
ring-mqtt.js
43
ring-mqtt.js
@@ -62,28 +62,13 @@ const main = async(generatedToken) => {
|
||||
await state.init(config)
|
||||
}
|
||||
|
||||
if (config.runMode === 'addon') {
|
||||
tokenApp.start(config.runMode)
|
||||
}
|
||||
|
||||
// If refresh token was generated via web UI, use it, otherwise attempt to get latest token from state file
|
||||
if (generatedToken) {
|
||||
debug(state.valid ? 'Updating state data with token generated via web UI.' : 'Using refresh token generated via web UI.')
|
||||
state.data.ring_token = generatedToken
|
||||
}
|
||||
|
||||
// If no refresh tokens were found, either exit or start Web UI for token generator
|
||||
if (!state.data.ring_token) {
|
||||
if (config.runMode === 'docker') {
|
||||
debug(colors.brightRed('No refresh token was found in state file, generate a token using get-ring-token.js.'))
|
||||
process.exit(2)
|
||||
} else {
|
||||
debug(colors.brightRed('No refresh token was found in state file, generate a token using the Web UI.'))
|
||||
if (config.runMode === 'standard') {
|
||||
tokenApp.start(config.runMode)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
if (state.data.ring_token) {
|
||||
// There is either web UI generated or saved state refresh token available
|
||||
// Wait for the network to be online and then attempt to connect to the Ring API using the token
|
||||
while (!(await isOnline())) {
|
||||
@@ -106,6 +91,9 @@ const main = async(generatedToken) => {
|
||||
// Update the web app with current connected refresh token
|
||||
const currentAuth = await ring.client.restClient.authPromise
|
||||
tokenApp.updateConnectedToken(currentAuth.refresh_token)
|
||||
if (config.runMode !== 'addon') {
|
||||
tokenApp.stop()
|
||||
}
|
||||
|
||||
// Subscribed to token update events and save new token
|
||||
ring.client.onRefreshTokenUpdated.subscribe(({ newRefreshToken, oldRefreshToken }) => {
|
||||
@@ -114,20 +102,21 @@ const main = async(generatedToken) => {
|
||||
|
||||
mqtt.init(ring, config.data)
|
||||
} else {
|
||||
debug(colors.brightRed('Failed to connect to Ring API using the refresh token in the saved state file.'))
|
||||
if (config.runMode === 'docker') {
|
||||
debug(colors.brightRed('Restart the container to try again or generate a new token using get-ring-token.js.'))
|
||||
process.exit(2)
|
||||
} else {
|
||||
debug(colors.brightRed(`Restart the ${this.runMode === 'addon' ? 'addon' : 'script'} or generate a new token using the Web UI.`))
|
||||
if (config.runMode === 'standard') {
|
||||
tokenApp.start(config.runMode)
|
||||
}
|
||||
}
|
||||
debug(colors.brightRed('Failed to connect to Ring API using saved token, a new token can be generated with the web UI.'))
|
||||
debug(color.brightRed('Authentication will be automatically retried in 60 seconds using the existing token.'))
|
||||
tokenApp.start(config.runMode)
|
||||
}
|
||||
} else {
|
||||
// If a refresh token was not found, start Web UI for token generator
|
||||
debug(colors.brightRed('No refresh token was found in state file, generate a token using the Web UI.'))
|
||||
tokenApp.start(config.runMode)
|
||||
}
|
||||
}
|
||||
|
||||
if (config.runMode === 'addon') {
|
||||
tokenApp.start(config.runMode)
|
||||
}
|
||||
|
||||
// Subscribe to token updates from token Web UI
|
||||
tokenApp.token.registerListener(function(generatedToken) {
|
||||
main(generatedToken)
|
||||
|
Reference in New Issue
Block a user