tsightler / ring-mqtt

Ring devices to MQTT Bridge
MIT License
593 stars 106 forks source link

Battery level not reported for Spotlight Cam #529

Closed Rubenfer closed 1 year ago

Rubenfer commented 1 year ago

Describe the Bug

Battery information for Spotlight Cam is not published

Steps to Reproduce

Ring account with Spotlight Cam

Expected Behavior

Topic with battery information is available. This camera has two battery slots.

Log Output

The log doesn't show nothing special

Screenshots

No response

Config File

Standard config

Install Type

Docker

Version

5.0.5

Operating System

Raspbian Lite

Architecture

arm64

Machine Details

Raspberry Pi

Rubenfer commented 1 year ago

This data is returned by the API as "battery_life" and "battery_life_2" as string if there is a battery and null if no battery.

tsightler commented 1 year ago

Yeah, the battery current code, which is pretty much unchanged for years, just uses whatever the getHealth() call returns for battery_percentage, but either Ring has deprecated that or some devices just don't return anything here. As I don't own any battery cameras it's not something I've been motivated to solve and nobody has submitted a PR for it, but it's way overdue for a refactor. Honestly this is really true of the whole code base as it would be good to move to a more event driven model for data updates, but it works mostly well enough now and has been really stable for the last year or so thus I've not wanted to change much in the broader code base, not to mention haven't really had the time.

I'll try to sneak some improvements on the battery status in to 5.1.0 which I'm hoping to release in the next few weeks.

tsightler commented 1 year ago

I've coded up something that I hope will be an improvement for the dev branch. If you want to test it feel free to give it a try using the branch feature.

Rubenfer commented 1 year ago

Thank you @tsightler! I've made a quick try in my testing environment and it doesn't seem to load properly the dev branch. I'm using a Docker installation with the following docker-compose.yml file:

version: "3.7"
services:
  ring-mqtt:
    container_name: ring-mqtt
    restart: unless-stopped
    image: tsightler/ring-mqtt:latest
    volumes:
      - ./data:/data
    environment:
      - BRANCH="dev"
Rubenfer commented 1 year ago

Woops, copy&pasting the environment from the wiki made me forget to remove the quotes 😅.

Now running v5.1.0 but no battery topic appears to be available in MQTT...

Captura de pantalla 2023-01-16 a las 15 17 21
tsightler commented 1 year ago

Now running v5.1.0 but no battery topic appears to be available in MQTT...

There's never a separate battery topic, battery levels are reported as part of the JSON data in the info topic.

Rubenfer commented 1 year ago

I've started using this a few weeks ago and maybe I missing something. The other cameras and battery-powered doorbells reports the battery in the topic ring////battery/attributes, but for the Spotlight Cam with two batteries this information doesn't appear in a specific topic (.../battery/attributes) nor in the info topic as part of the JSON where firmware and wireless info comes. Is this correct?

Captura de pantalla 2023-01-16 a las 18 57 49
tsightler commented 1 year ago

Ha, ha, well, I did write this attribute topic code a long time ago, so maybe I just forgot how it works!! But, the attribute topics always pull their state from the info topic, basically, if it's not in the info topic then there won't be a corresponding topic.

So, what's clear in your screenshot, is that there is no battery information in the info topic, thus there will be no battery topic, as it's just a subset of the info topic with just the battery specific properties. What's far less clear is why that is the case. The code simply uses the "hasBattery" flag provided by ring-client-api.

Is there any chance you don't have a battery in slot 1 at all? Looking at the code in ring-client-api, it appears that it only checks for "battery_life" attribute in the device data, but I believe that it only reported if there is a battery inserted.

tsightler commented 1 year ago

Ideally if you could provide Data Discovery for the device that is not working, that would be the most useful information.

Rubenfer commented 1 year ago

That was the reason. Now I have a battery in both slots and receive the battery level in MQTT.

The status topic now reports it but there is three fields for the battery information.

Captura de pantalla 2023-01-17 a las 17 55 36
tsightler commented 1 year ago

Could you please try the current dev branch (just restart addon to pull in the latest). I've tried to improve the battery detection logic.

Rubenfer commented 1 year ago

Same info from the previous day in MQTT:

"batteryLevel": 60,
"batteryLife": 100,
"batteryLife2": 0,

I provide the data discovery result for this camera. Hope it's helpful. The key fields are:

{
          "description": "...",
          "subscribed": false,
          "subscribed_motions": false,
          "battery_life": "100",
          "external_connection": false,
          "firmware_version": "Up to Date",
          "kind": "stickup_cam_v4",
          "settings": {
            "cv_settings": {
              "detection_types": {
                "human": {...},
                "loitering": {...},
                "motion": {...},
                "moving_vehicle": {...},
                "other_motion": {...},
                "package_delivery": {...},
                "package_pickup": {...}
              },
              "threshold": {
                "loitering": 10
              },
              "triggers": []
            },
            "cv_paid_features": {
              "baby_cry": true,
              "car_alarm": true,
              "co2_smoke_alarm": true,
              "dog_bark": true,
              "general_sound": true,
              "glass_break": true,
              "human": true,
              "loitering": true,
              "motion": true,
              "moving_vehicle": true,
              "other_motion": true,
              "package_delivery": true,
              "package_pickup": true,
              "cv_triggers": true
            },
            "other_paid_features": {
              "alexa_concierge": true,
              "sheila_cv": true,
              "sheila_recording": true
            },
            "sheila_settings": {
              "cv_processing_enabled": null,
              "local_storage_enabled": null
            },
            "server_settings": {
              "ring_media_server_enabled": true,
              "ring_media_server_host": "..."
            },
            "zone_settings": {
              "motion": [...]
            },
            "offline_motion_event_settings": {
              "subscribed": true,
              "enabled": false,
              "max_upload_kb": 5000,
              "resolution_p": 360,
              "frequency_after_secs": 2,
              "period_after_secs": 30
            },
            "lite_24x7": {
              "subscribed": true,
              "enabled": true,
              "frequency_secs": 3600,
              "resolution_p": 360
            },
            "enable_vod": 1,
            "exposure_control": 2,
            "motion_zones": [
              1,
              1,
              1,
              1,
              1
            ],
            "motion_snooze_preset_profile": "none",
            "motion_snooze_presets": [
              "none",
              "low",
              "medium",
              "high"
            ],
            "live_view_preset_profile": "middle",
            "live_view_presets": [
              "low",
              "middle",
              "high",
              "highest"
            ],
            "pir_sensitivity_1": 10,
            "vod_suspended": 0,
            "doorbell_volume": 8,
            "vod_status": "enabled",
            "video_settings": {
              "encryption_enabled": false,
              "encryption_method": 1
            },
            "advanced_motion_detection_enabled": false,
            "advanced_motion_zones": {...},
            "advanced_motion_detection_human_only_mode": false,
            "enable_audio_recording": true,
            "people_detection_eligible": true,
            "live_view_disabled": false,
            "ignore_zones": {...},
            "enable_rich_notifications": true,
            "rich_notifications_billing_eligible": true,
            "loitering_threshold": 10,
            "advanced_motion_detection_types": [],
            "motion_detection_enabled": false,
            "rich_notifications_scene_source": "cloud",
            "advanced_motion_zones_enabled": false,
            "advanced_motion_zones_type": "8vertices",
            "advanced_pir_motion_zones": {
              "zone1_sensitivity": 5,
              "zone2_sensitivity": 5,
              "zone3_sensitivity": 5,
              "zone4_sensitivity": 5,
              "zone5_sensitivity": 5,
              "zone6_sensitivity": 5
            },
            "light_settings": {
              "brightness": 10
            },
            "enable_white_leds": 0,
            "rich_notifica-uuid": false
          },
          "features": {
            "motion_zone_recommendation": false,
            "motions_enabled": true,
            "show_recordings": true,
            "show_vod_settings": true,
            "rich_notifications_eligible": true,
            "show_24x7_lite": true,
            "show_offline_motion_events": false,
            "cfes_eligible": true,
            "sheila_camera_eligible": true,
            "sheila_camera_processing_eligible": true
          },
          "owned": true,
          "alerts": {
            "connection": "online",
            "ota_status": "timeout"
          },
          "motion_snooze": null,
          "stolen": false,
          "is_sidewalk_gateway": false,
          "created_at": "...",
          "shared_at": null,
          "active_schedule_uuid": null,
          "health": {
            "device_type": "stickup_cam_v4",
            "last_update_time": 1674352538,
            "connected": true,
            "rss_connected": true,
            "vod_enabled": true,
            "sidewalk_connection": false,
            "floodlight_on": false,
            "white_led_on": false,
            "night_mode_on": false,
            "hatch_open": false,
            "packet_loss": 0,
            "packet_loss_category": "good",
            "rssi": -35,
            "wifi_is_ring_network": false,
            "ota_status": "timeout",
            "ext_power_state": 0,
            "network_connection_value": "wifi",
            "ac_power": 0,
            "external_connection": false,
            "battery_percentage": 100,
            "battery_percentage_category": "very_good",
            "battery_voltage": 4153,
            "battery_voltage_category": "very_good",
            "firmware_version": "cam-10.0.27",
            "active_battery": 2,
            "rssi_category": "good",
            "second_battery_percentage": 60,
            "second_battery_percentage_category": "good",
            "second_battery_voltage": 3712,
            "second_battery_voltage_category": "good",
            "battery_save": false,
            "firmware_version_status": "Up to Date",
            "stream_resolution": 0,
            "status_time": 54865182593954,
            "firmware_avg_bitrate": "0",
            "video_packets_total": "5460"
          },
          "deactivated_at": null,
          "battery_life_2": "60",
          "battery_voltage": 4153,
          "battery_voltage_2": 3712,
          "led_status": {
            "seconds_remaining": 0
          },
          "siren_status": {
            "seconds_remaining": 0
          },
          "night_mode": 0,
          "ext_power_state": 0
        },
tsightler commented 1 year ago

I'm sorry, but I have to ask this basic question, are you absolutely sure you have restarted the addon and not just Home Assistant? I don't see how the current code could possibly produce the same output as previous. The previous output was easy to explain as I had accidentally flipped the true/false state for the second battery calculation, but I can't figure out any reason the current code could produce the same output as all it does is check for the presence of battery_life_2 and, if it exist, parses that into a floating-point value.

Rubenfer commented 1 year ago

I'm totally sure because I'm running it on my Mac (not the Raspberry Pi with the stable version) and starting this from terminal without Home Assistant.

Just to clarify, the current issue is not the reported battery when only one slot has a battery inside. It's that the value for the two batteries are reported as "batteryLevel" and "batteryLife" instead of "batteryLife" and "batteryLife2". Currently batteryLife2 is always 0.

tsightler commented 1 year ago

batteryLevel will always be the level of the currently active battery, which the data shows is battery2 in your case, so that is the correct value.

batteryLife is the level of the first battery, which is 100 percent, so that is correct.

batteryLife2 should be the level of the second battery, which is the active battery in your case, so should be the same as batteryLevel, but I can't figure out any reason that it would not be reporting correctly with the current code. Can you please provide full logs for ring-mqtt?

tsightler commented 1 year ago

I'm totally sure because I'm running it on my Mac (not the Raspberry Pi with the stable version) and starting this from terminal without Home Assistant.

Latest version should display as 5.1.0-rc3, are you seeing that version when starting the code?

Rubenfer commented 1 year ago

Here's the logs. Let me know if you need the complete ones. I removed a lot of lines that I found unnecessary.

Attaching to ring-mqtt
ring-mqtt  | s6-rc: info: service s6rc-oneshot-runner: starting
ring-mqtt  | s6-rc: info: service s6rc-oneshot-runner successfully started
ring-mqtt  | s6-rc: info: service fix-attrs: starting
ring-mqtt  | s6-rc: info: service fix-attrs successfully started
ring-mqtt  | s6-rc: info: service legacy-cont-init: starting
ring-mqtt  | cont-init: info: running /etc/cont-init.d/ring-mqtt.sh
ring-mqtt  | -------------------------------------------------------
ring-mqtt  | | Ring-MQTT with Video Streaming                      |
ring-mqtt  | | Docker Edition                                      |
ring-mqtt  | |                                                     |
ring-mqtt  | | For support questions please visit:                 |
ring-mqtt  | | https://github.com/tsightler/ring-mqtt/discussions  |
ring-mqtt  | -------------------------------------------------------
ring-mqtt  | The ring-mqtt-dev has been updated.
ring-mqtt  | cont-init: info: /etc/cont-init.d/ring-mqtt.sh exited 0
ring-mqtt  | s6-rc: info: service legacy-cont-init successfully started
ring-mqtt  | s6-rc: info: service legacy-services: starting
ring-mqtt  | services-up: info: copying legacy longrun ring-mqtt (no readiness notification)
ring-mqtt  | s6-rc: info: service legacy-services successfully started
ring-mqtt  | -------------------------------------------------------
ring-mqtt  | ring-mqtt.js version: 5.1.0
ring-mqtt  | Node version v16.17.1
ring-mqtt  | NPM version 8.10.0
ring-mqtt  | git version 2.36.2
ring-mqtt  | -------------------------------------------------------
ring-mqtt  | Running ring-mqtt...
ring-mqtt  | 2023-01-23T18:17:28.503Z ring-mqtt Detected runmode: docker
ring-mqtt  | 2023-01-23T18:17:28.506Z ring-mqtt Configuration file: /data/config.json
ring-mqtt  | 2023-01-23T18:17:29.858Z ring-mqtt Reading latest data from state file: /data/ring-state.json
ring-mqtt  | 2023-01-23T18:17:29.883Z ring-mqtt MQTT URL: mqtt://admin:********@mosquitto.docker_default:1883
ring-mqtt  | 2023-01-23T18:17:30.211Z ring-mqtt Attempting connection to Ring API using saved refresh token...
ring-mqtt  | 2023-01-23T18:17:32.116Z ring-mqtt Successfully established connection to Ring API using saved token
ring-mqtt  | 2023-01-23T18:17:32.117Z ring-mqtt Received updated refresh token
ring-mqtt  | 2023-01-23T18:17:32.117Z ring-mqtt Saving updated refresh token to state file
ring-mqtt  | 2023-01-23T18:17:33.138Z ring-mqtt Successfully saved updated state file: /data/ring-state.json
ring-mqtt  | 2023-01-23T18:17:34.117Z ring-mqtt Attempting connection to MQTT broker...
ring-mqtt  | 2023-01-23T18:17:34.230Z ring-mqtt MQTT connection established, processing Ring locations...
...
ring-mqtt  | 2023-01-23T18:18:19.657Z ring-attr [xxx] ring/xxx/camera/xxx/info/state {"batteryLevel":58,"batteryLife":100,"batteryLife2":0,"firmwareStatus":"Up to Date","lastUpdate":"2023-01-23T14:41:56Z","wirelessNetwork":"xxx","wirelessSignal":-37}
tsightler commented 1 year ago

ring-mqtt | ring-mqtt.js version: 5.1.0

Hmm...this is the part that is confusing, it should show:

ring-mqtt | ring-mqtt.js version: 5.1.0-rc3

As that is the current dev version. I don't even understand how it is possible to be pulling the wrong version. Even the update script update logging is showing incorrectly (it has a typo that is fixed in current versions). Very strange.

Rubenfer commented 1 year ago

I've made a fresh install (removing the container, image, and starting from scratch) and now works as expected!

Looks like restarting the container is not enough and at least recreate the container is needed to pull the latest dev changes.

Captura de pantalla 2023-01-24 a las 15 01 09

Thanks so much for your support.

tsightler commented 1 year ago

I would have thought docker stop/start would be enough, but honestly, I almost always run with --rm, so my containers are always removed automatically on stop and I start again with a new docker run command.

Thanks for testing and glad it is working as expected, I was going crazy trying to figure out how it could possibly not be working. :)

tsightler commented 1 year ago

Version 5.1.0 has been published.