ring icon indicating copy to clipboard operation
ring copied to clipboard

No battery level reported for stickup_cam_v4

Open sjonez opened this issue 2 years ago • 7 comments

Is there an existing issue for this?

  • [X] I have searched the existing issues

Describe The Bug

I'm not seeing any battery data for one of my cameras which is a stickup cam v4. Here's the discovery data:

[
	{
		"kind": "stickup_cam_v4",
		"description": "Garden",
		"is_sidewalk_gateway": false,
		"created_at": "2022-07-29T13:49:36Z",
		"deactivated_at": null,
		"firmware_version": "Up to Date",
		"owned": true,
		"stolen": false,
		"shared_at": null,
		"health": {
			"ac_power": 0,
			"battery_percentage_category": "unknown",
			"battery_save": false,
			"battery_voltage_category": "unknown",
			"connected": true,
			"device_type": "stickup_cam_v4",
			"external_connection": false,
			"firmware_version": "cam-12.0.38",
			"floodlight_on": false,
			"last_update_time": 1695194126,
			"network_connection_value": "wifi",
			"night_mode_on": false,
			"ota_status": "timeout",
			"rss_connected": true,
			"rssi": -70,
			"rssi_category": "okay",
			"second_battery_percentage": 61,
			"second_battery_percentage_category": "good",
			"second_battery_voltage_category": "good",
			"sidewalk_connection": false,
			"white_led_on": false,
			"firmware_version_status": "Up to Date",
			"packet_loss": 0,
			"packet_loss_category": "good",
			"hatch_open": false,
			"ext_power_state": 0,
			"second_battery_voltage": 3656,
			"active_schedule_uuid": "537bd0d37f6f45e9b35a02651fdcebfb",
			"bandwidth": 4800,
			"status_time": 55547722363647,
			"vod_enabled": true,
			"battery_error": false,
			"bandwidth_last_time": 1691548239,
			"firmware_avg_bitrate": "0",
			"stream_resolution": 0,
			"video_packets_total": "1423",
			"wifi_is_ring_network": false,
			"wifi_name": "Nacho Internet",
			"active_battery": 2
		},
		"subscribed": false,
		"subscribed_motions": true,
		"external_connection": false,
		"active_schedule_uuid": "537bd0d37f6f45e9b35a02651fdcebfb",
		"alerts": {
			"connection": "online",
			"ota_status": "timeout"
		},
		"motion_snooze": null,
		"battery_life": null,
		"settings": {
			"motion_snooze_preset_profile": "low",
			"motion_snooze_presets": [
				"none",
				"low",
				"medium",
				"high"
			],
			"live_view_preset_profile": "middle",
			"live_view_presets": [
				"low",
				"middle",
				"high",
				"highest"
			],
			"doorbell_volume": 8,
			"advanced_motion_detection_enabled": true,
			"advanced_motion_detection_human_only_mode": true,
			"enable_audio_recording": true,
			"people_detection_eligible": true,
			"live_view_disabled": false,
			"ignore_zones": {
				"zone1": {
					"name": "Privacy Zone 1",
					"state": 2,
					"vertex1": {
						"x": 0.36,
						"y": 0.2
					},
					"vertex2": {
						"x": 0.46,
						"y": 0.35
					}
				},
				"zone2": {
					"name": "Zone 2",
					"state": 0,
					"vertex1": {
						"x": 0,
						"y": 0
					},
					"vertex2": {
						"x": 0,
						"y": 0
					}
				},
				"zone3": {
					"name": "Zone 3",
					"state": 0,
					"vertex1": {
						"x": 0,
						"y": 0
					},
					"vertex2": {
						"x": 0,
						"y": 0
					}
				},
				"zone4": {
					"name": "Zone 4",
					"state": 0,
					"vertex1": {
						"x": 0,
						"y": 0
					},
					"vertex2": {
						"x": 0,
						"y": 0
					}
				}
			},
			"enable_rich_notifications": true,
			"rich_notifications_billing_eligible": true,
			"loitering_threshold": 10,
			"advanced_motion_detection_types": [
				"human"
			],
			"motion_detection_enabled": false,
			"rich_notifications_scene_source": "cloud",
			"offline_motion_event_settings": {
				"subscribed": true,
				"enabled": false,
				"max_upload_kb": 5000,
				"resolution_p": 360,
				"frequency_after_secs": 2,
				"period_after_secs": 30
			},
			"cv_settings": {
				"detection_types": {
					"human": {
						"enabled": true,
						"mode": "cloud",
						"record": null,
						"notification": true
					},
					"loitering": {
						"enabled": false,
						"mode": "none",
						"record": null,
						"notification": false
					},
					"motion": {
						"enabled": true,
						"mode": "cloud",
						"record": null,
						"notification": false
					},
					"moving_vehicle": {
						"enabled": false,
						"mode": "none",
						"record": null,
						"notification": false
					},
					"other_motion": {
						"enabled": true,
						"mode": "cloud",
						"record": null,
						"notification": false
					},
					"package_delivery": {
						"enabled": false,
						"mode": "none",
						"record": null,
						"notification": false
					},
					"package_pickup": {
						"enabled": false,
						"mode": "none",
						"record": null,
						"notification": false
					}
				},
				"threshold": {
					"loitering": 10,
					"package_delivery": 2
				},
				"triggers": []
			},
			"sheila_settings": {
				"cv_processing_enabled": false,
				"local_storage_enabled": false
			},
			"server_settings": {
				"ring_media_server_enabled": true,
				"ring_media_server_host": "rms-eu-west-1.rapi.us-east-1.prod.client.cap.ring.devices.a2z.com"
			},
			"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,
				"other_motion": true,
				"package_delivery": true,
				"package_pickup": true,
				"cv_triggers": true
			},
			"other_paid_features": {
				"alexa_concierge": true,
				"sheila_cv": true,
				"sheila_recording": true,
				"critical_alerts": null,
				"system_level_pip": null,
				"extended_live_view": null,
				"recording_24x7": null
			},
			"zone_settings": {
				"motion": [
					{
						"name": "Default Zone",
						"state": "enabled",
						"properties": {
							"detection_types": [
								"motion"
							],
							"style": 1
						},
						"vertices": [
							{
								"x": 0.403337,
								"y": 0.404864
							},
							{
								"x": 0.493018,
								"y": 0.25
							},
							{
								"x": 0.695425,
								"y": 0.25
							},
							{
								"x": 0.727806,
								"y": 0.367174
							},
							{
								"x": 0.998585,
								"y": 0.25
							},
							{
								"x": 0.992606,
								"y": 1
							},
							{
								"x": 0.081107,
								"y": 0.997888
							},
							{
								"x": 0.007451,
								"y": 0.478096
							}
						]
					}
				],
				"privacy": [
					{
						"name": "Privacy Zone 1",
						"state": "enabled",
						"properties": {},
						"vertices": [
							{
								"x": 0.36,
								"y": 0.2
							},
							{
								"x": 0.46,
								"y": 0.35
							}
						]
					}
				]
			},
			"stark_enrolled": null,
			"network_settings": {
				"mac_address_ble": null,
				"max_dynamic_listen_interval": null,
				"network_diagnosis": {
					"channel_analysis": null,
					"periodic_diagnosis": null,
					"lan_performance": null,
					"tcp_iperf": null,
					"tcp_host": null,
					"tcp_port": null,
					"udp_iperf": null,
					"udp_host": null,
					"udp_port": null,
					"udp_bandwidth": null
				},
				"multi_net_pref": 3,
				"mac_address_wifi_24": null,
				"mac_address_wifi_5": null
			},
			"motion_zones": [
				1,
				1,
				1,
				1,
				1
			],
			"enable_vod": 1,
			"exposure_control": 2,
			"vod_suspended": 0,
			"vod_status": "enabled",
			"voice_volume": 11,
			"video_settings": {
				"encryption_enabled": false,
				"encryption_method": 1
			},
			"advanced_motion_zones": {
				"zone1": {
					"name": "Default Zone",
					"state": 2,
					"vertex1": {
						"x": 0.403337,
						"y": 0.404864
					},
					"vertex2": {
						"x": 0.493018,
						"y": 0.25
					},
					"vertex3": {
						"x": 0.695425,
						"y": 0.25
					},
					"vertex4": {
						"x": 0.727806,
						"y": 0.367174
					},
					"vertex5": {
						"x": 0.998585,
						"y": 0.25
					},
					"vertex6": {
						"x": 0.992606,
						"y": 1
					},
					"vertex7": {
						"x": 0.081107,
						"y": 0.997888
					},
					"vertex8": {
						"x": 0.007451,
						"y": 0.478096
					}
				},
				"zone2": {
					"name": "Zone 2",
					"state": 0,
					"vertex1": {
						"x": 0,
						"y": 0
					},
					"vertex2": {
						"x": 0,
						"y": 0
					},
					"vertex3": {
						"x": 0,
						"y": 0
					},
					"vertex4": {
						"x": 0,
						"y": 0
					},
					"vertex5": {
						"x": 0,
						"y": 0
					},
					"vertex6": {
						"x": 0,
						"y": 0
					},
					"vertex7": {
						"x": 0,
						"y": 0
					},
					"vertex8": {
						"x": 0,
						"y": 0
					}
				},
				"zone3": {
					"name": "Zone 3",
					"state": 0,
					"vertex1": {
						"x": 0,
						"y": 0
					},
					"vertex2": {
						"x": 0,
						"y": 0
					},
					"vertex3": {
						"x": 0,
						"y": 0
					},
					"vertex4": {
						"x": 0,
						"y": 0
					},
					"vertex5": {
						"x": 0,
						"y": 0
					},
					"vertex6": {
						"x": 0,
						"y": 0
					},
					"vertex7": {
						"x": 0,
						"y": 0
					},
					"vertex8": {
						"x": 0,
						"y": 0
					}
				}
			},
			"advanced_motion_zones_enabled": true,
			"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
			},
			"enable_white_leds": 1,
			"light_settings": {
				"brightness": 10
			},
			"floodlight_settings": {
				"brightness": 10
			},
			"pir_sensitivity_1": 7,
			"lite_24x7": {
				"subscribed": true,
				"enabled": true,
				"frequency_secs": 840,
				"resolution_p": 360
			},
			"rich_notifica-uuid": false
		},
		"battery_voltage": null,
		"led_status": {
			"seconds_remaining": 0
		},
		"night_mode": 0,
		"siren_status": {
			"seconds_remaining": 0
		},
		"ext_power_state": 0,
		"features": {
			"cfes_eligible": true,
			"motion_zone_recommendation": false,
			"motions_enabled": true,
			"show_recordings": true,
			"show_vod_settings": true,
			"rich_notifications_eligible": true,
			"show_offline_motion_events": false,
			"sheila_camera_eligible": true,
			"sheila_camera_processing_eligible": true,
			"dynamic_network_switching_eligible": false,
			"show_24x7_lite": true
		},
		"battery_voltage_2": 3656,
		"battery_life_2": "61"
	}
]

I think it's because there is no health.battery_percentage or health.battery_present like my other devices, but there is instead health.active_battery

To Reproduce

No response

Expected behavior

Battery reported

Relevant log output

No response

Screenshots

No response

Additional context

No response

OS

Ubuntu

Node.js Version

20.6.1

NPM Version

9.8.1

ring-client-api

12.0.1

Operating System

Ubuntu

sjonez avatar Sep 20 '23 21:09 sjonez

I'm pretty sure it's because the code checks for hasBattery() during startup, but that will only return true if "battery_life" property exist. However, it appears there is either no battery, or a completely dead battery, in slot 1, thus this check returns false and no battery characteristics are registered for the device. If you simply move the battery to slot one and restart the plugin, my guess is it will work.

Realistically, the code should probably check for either "battery_life" or "battery_life_2" and return true if either are present (that is what I do in ring-mqtt), but it's a pretty good corner case as I believe this is only checked during initial startup.

tsightler avatar Sep 20 '23 21:09 tsightler

The battery_life property is in there, it just has a value of null.

I'll test swapping the battery to the other slot tomorrow and see if it makes a difference

sjonez avatar Sep 20 '23 21:09 sjonez

Ah yes, sorry, missed it, glanced through too quickly. So it's not that it is not registering a battery characteristic, it's that it is reporting the battery value as null because the primary battery is either completely dead or not installed. Looks like it is probably because of getBatteryLevel() in ring-camera.ts, specifically this:

  if (
    !levels.length ||
    (health && !health.battery_percentage && !health.battery_present)
  ) {
    return null
  }

Because there is no battery_percentage or battery_present properties, this function will return null instead of the value from second battery (I believe the goal of this function is to return the highest value from either of two batteries). Should probably add an additional check for !health.second_battery_percentage to this function, then it will return value of second battery even if first is completely dead/removed.

tsightler avatar Sep 20 '23 22:09 tsightler

If you modify line 38 in node_modules/ring-client-api/lib/ring-camera.js and change:

(health && !health.battery_percentage && !health.battery_present)) {

to

(health && !health.battery_percentage && !health.second_battery_percentage && !health.battery_present)) {

Restart and I believe it will work.

tsightler avatar Sep 20 '23 22:09 tsightler

If you modify line 38 in node_modules/ring-client-api/lib/ring-camera.js and change:

(health && !health.battery_percentage && !health.battery_present)) {

to

(health && !health.battery_percentage && !health.second_battery_percentage && !health.battery_present)) {

Restart and I believe it will work.

It looks like slot 1 of the camera has an issue, the camera won't boot up unless the battery is in slot 2 :(

I made the code change you suggested though and that does indeed fix the problem when there is only a battery in slot 2, thanks!

sjonez avatar Sep 22 '23 15:09 sjonez

Great, I'll see about getting a fix into the next version.

tsightler avatar Sep 22 '23 15:09 tsightler

@sjonez it looks like we may have already merged a fix for this. Would you mind updating to the latest version and letting us know if the battery level now shows up correctly?

dgreif avatar Aug 04 '24 19:08 dgreif