Nanit Baby Monitor Integration

The knowledge here is amazing, and it’s really inspiring. I do have to say that my mind is missing the simple step by step. Homebridge is already up and running for me prior, ffmpeg can be install without issue. But I cannot understand how to fill out the script for the ip address and my baby uid? Could everyone that has already taken much time to accomplish what is here, please take another moment and help me out? I’d like to give my wife some reprieve from having her phone app active all the time when we’re not directly in from our girl.

Thank you.

Which bit in particular are you having trouble with? The calls to obtain the baby id from nanit?

Yes, or how to obtain the information needed for the home bridge config. I don’t know the IP or the UID, not how to obtain them in specificity.

I just need a simple 1, 2, 3 guide to get that information and I’ll be good. Thanks for your time and effort. It’s just how my mind works.

You’ll need to use an app called Postman to interact with the Nanit API. Once you have the setup, you can use on a Postman Collection to save you the time of working out the API calls needed.

To obtain the IP address of your Nanit camera, you’ll need to check with whatever DHCP server is allocating IP addresses on your network. If you’re using ISP-provided hardware, log in to that and have a look around until you see a screen that shows all of the devices on your network.

Really cool, I’ve never done any API calls or anything, you certainly gave me the fast track.

Is the UID what I have named the camera in the app or the ID that is returned after sending the step 2 request to Nanit?

Uid stands for unique ID and is the unique ID for your baby created by nanit. You’ll get it back in the second request. From memory, it’s baby_uid in the response.

Thank you again, but that UID isn’t present in the data from the second request.

{
    "user": {
        "mixpanel_tracking_enabled": true,
        "confirmed_at": "2022-08-20T10:08:37Z",
        "email": "bXXXXX",
        "phone": "+XXXX",
        "logs": 0,
        "enforce_mfa": true,
        "name": "XXXX",
        "pending_email": null,
        "source": "YouTube",
        "image_url": null,
        "logs_nl": 0,
        "research_group": null,
        "id": XXXX,
        "research_groups": [],
        "feature_flags": {
            "pip_crash_fix": true,
            "suggested_skeleton": true,
            "force_wifi_band": true,
            "change_plan_name": true,
            "semi_auto_sting_v2": true,
            "mfa": true,
            "allow_skip_smart_sheets_calibration": true,
            "debug_nanit_pro_pairing": true,
            "dashboard_head_pose_ios": true,
            "put_streaming_for_start_request": true,
            "bmm_stopped_by": true,
            "nightlight_interaction": true,
            "disable_keep_alive": true,
            "security_change_phone_extra_mfa_step_ios": true,
            "pairing_double_discover_timeout": true,
            "mavenoid": true,
            "dont_auto_renew_access_token": true,
            "sleep_training_v1": false,
            "cvr_v3": true,
            "enable_iap_v3": true,
            "pip_ios_v1": false,
            "release_sting_bpm": true,
            "tls": true,
            "double_write_server": true,
            "enforce_mfa_on_registration_android": true,
            "ping_v2": true,
            "dev_milestones_android": true,
            "enable_keychain_cooldown": true,
            "pip_ios_v3": true,
            "dev_milestones_ios": true,
            "security_change_email_extra_password_step_ios": true,
            "sms_hide_calibration": true,
            "monitoring_sounds": true,
            "audio_only_one_minute": true,
            "dashboard_bmm_android": true,
            "p2p_no_retries": true,
            "enforce_mfa_on_login_android": false,
            "memories": true,
            "android_app_shortcuts": true,
            "camera_standby": true,
            "sting": true,
            "cvr_okhttp": true,
            "alert_zone_v2": true,
            "dashboard_head_pose_android": true,
            "allow_detach_camera": true,
            "nanit_pro_released": true,
            "alert_zone_android_v1": true,
            "event_counter_ios": false,
            "multi_cameras_poc": true,
            "use_new_port": true,
            "watch_them_grow_cta_v3": true,
            "event_counter_android": true,
            "pairing_double_timeouts": true,
            "watch_them_grow_ai": true,
            "mcs": true,
            "dashboard_activity_score_android": true,
            "baby_out_of_crib": true,
            "audio_only_one_minute_android": true,
            "dashboard_bmm_ios": true,
            "force_ir_off": true,
            "downgrade_parenting_team": true,
            "sleep_training_v2": false,
            "sleep_training_v3": true,
            "sms_manual_measurement": true,
            "dashboard_temp_and_humidity_ios": true,
            "dashboard_activity_score_ios": true,
            "security_change_phone_extra_mfa_step_android": true,
            "semi_auto_sting_android": true,
            "cvr_in_feed": true,
            "moments_playlist": true,
            "allow_disconnection_notifications_tracking": true,
            "smart_sheets": true,
            "pairing_double_connect_timeout": true,
            "dashboard_body_pose_ios": true,
            "enforce_protected_data_check": true,
            "pairing_double_auth_timeout": true,
            "watch_them_grow_ai_android": true,
            "dashboard_body_pose_android": true,
            "should_disable_intercom_android": true,
            "mcs_v2": true,
            "community_cta_v3": true,
            "enforce_mfa_on_registration_ios": true,
            "should_disable_intercom_ios": true,
            "dashboard_temp_and_humidity_android": true
        },
        "enforce_mfa_due_date": null,
        "units": {
            "temperature": "fahrenheit",
            "weight": "pounds",
            "length": "inches"
        },
        "country": "US",
        "created_at": "2022-08-20T10:08:05Z"
    },
    "access_token": "XXX",
    "refresh_token": "XXX",
    "token": "3XXX"
}

You’re right, my apologies. If you search this thread for “baby_uid”, there’s mention of how to obtain it from a different api call.

Anyone who’d like a tip to help me out I’d appreciate it.

A GET request to https://api.nanit.com/babies will get your your Baby ID

Came here to ask this. From what I can tell, there’s no API endpoint for turning the camera on and off or for controlling the night light. Instead, those commands seem to be sent to the camera directly via the WSS connection. I’ll be working on this over the coming days, so if I make any progress, I’ll post an update.

4 Likes

My Nanit docker is still working great as I have been able to avoid MFA (multi factor authentication) enforcing by not using my login through the app. I am technically still logged in I suppose, but without MFA. Either my wife monitors, or I monitor through Home Assistant. Does anyone know if I was to login to the app with my wife’s username, or add a new member login, if I would be able to keep my original login working with HA without MFA, but still use the app logged in as either my wife or a new user?

Aside from all this, has anyone been able to integrate Nanit with HA with MFA enabled?

EDIT: NM on the last question. I found the article regarding setup with 2FA.

Hello,

I had Adam’s solution working for a long time and then when MFA was forced, it stopped working. Using a bunch of different replies in this thread I have put together something that works (just over a day), and I’m sure someone else can improve upon it. It’s not ideal I admit, but it works for me.

This is my first post here, so I’m only allowed to post 2 links. Therefore I can’t post the full url for the APIs, but it’s just the api url plus the endpoint specified.

Step 1: Getting your Access Token, Refresh Token, and Baby UIDs

  • Download Postman and the Nanit collection

Send a POST request to this url: /login
In the Body of the request enter your username and password like this:

{ 
  "email" :"youremail",
  "password" :"yourpassword"
}

In your headers, make sure you set nanit-api-version as 1 (type nanit-api-version in the left column, 1 in the right)

In the response you will get a MFA token:

{
    "mfa_token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "phone_suffix": "xx",
    "channel": "sms"
}

Now we need to send a POST request to this url endpoint: /login

In the body of the request enter the mfa_token value from the previous response and the 4-digit code that was sent to whatever you have setup in Nanit (SMS, maybe email?):

{ 
  "mfa_token" :"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "chennel" :"sms",
  "mfa_code" :"xxxx",
  "password":"yourpassword",
  "email":"youremail"
}

At the very bottom of the response you will see 3 values:

...
"access_token": "db03a76aba913bc952fd23db9f890b60dee8df94761378af",
"refresh_token": "4eaa5af7db14a34773348bc476a9f5cfd7f37e68f9bf81bb",
"token": "db03a76aba913bc952fd23db9f890b60dee8df94761378af"
...

Take note of these values.

Now you will send a GET request to this url endpoint: /babies
The only thing you need to send is your access token in the headers. If you’re using Postman, it already does that for you. Look in the response for uid and your baby’s name should be nearby. If you have multiple cameras, there will be more than 1 of these ids and you will need to look for the name to know which is which (or look at the camera feed later I guess?).

Step 2: Refreshing your token every hour with python

There’s probably a better way to do this, but it works. First make sure you’ve followed all the steps to use python scripts in your instance. Here: Python Scripts - Home Assistant
I am assuming you have this set up for the rest of the instructions.

Save your access token and refresh token from step 1 in files called access.token and refresh.token and put them in your python_scripts folder.
Save the refresh.py from here: https://github.com/jakeledwards/nanitTokenRefresh in your python_scripts folder and update the file with your baby’s uid.

Step 3: Set up cameras and automate the refresh token

Place this in your configuration.yaml with your cameras:

camera:
  - name: Tiny Tim
    platform: ffmpeg
    input: !secret nanit_access_1
  - name: Little Jonny
    platform: ffmpeg
    input: !secret nanit_access_2

Place this in your configuration.yaml with your other shell commands. If you don’t have any other ones, just put it somewhere nice.

shell_command:
  update_nanit_token: "python3 /config/python_scripts/refresh.py > /config/www/log.log"

Place this in your automations.yaml

- id: 'xxxxxxxxxx'
  alias: Nanit Token Update
  description: Refreshes the Nanit token every hour and then reloads the configuration.yaml
  trigger:
  - platform: time_pattern
    minutes: /5
  condition: []
  action:
  - service: shell_command.update_nanit_token
    data: {}
  - delay:
      hours: 0
      minutes: 1
      seconds: 0
      milliseconds: 0
  - service: homeassistant.reload_core_config
    data: {}
  mode: single

Open your secrets.yaml and place this at the bottom:

nanit_access_1: xxthiscanbeanythingatallincludingthisxx

Restart Home Assistant

Step 4: Configure your lovelace dashboard

Place this card in your dashboard:

    cards:
      - show_state: false
        show_name: true
        camera_view: auto
        type: picture-entity
        entity: camera.jack
        camera_image: camera.jack
        theme: Graphite
        aspect_ratio: '16:9'
        image: >-
          https://dm41breupsxmi.cloudfront.net/babies/29c2bc1c/VWZnMBUM-8MJkcMvWoam5w.jpg
4 Likes

Hi Jakee!

Do you have a link to the “nanit collection”? My wife is on me to get the monitor back up and running in HA.

Edit: Found the API link a few posts above. Got this working! Curious to know how long yours has gone for un-interupted!

Thanks!

Not the person you asked, but mine has been solid for over a week now.

I took a different approach to this problem and I created a plugin for Scrypted. I liked this approach for a couple reasons

  1. Scrypted is fast. The video delay is under 1 second. It’s as good as watching the video in nanit
  2. Scrypted has native support for rebroadcasting as RTSP which works well with HA
  3. You can add external motion/sound detection through Scrypted
  4. HKSV, i am actually using Scrypted for homekit for the HKSV

Caveat is that I use the external RTMP stream (rtmp://media-secured.nanit.com/…). It also doesn’t do anything with temp/humidity or motions.

If there is interest, I would be happy to clean it up a bit and open source it.

6 Likes

I’d be interested in giving it a try.

Same, would love to try but would need more detail. Looks interesting.

I’ll do some more cleanup to it this week. Here is a working implementation and a readme with instructions. GitHub - zone99dev/scrypted-nanit

1 Like

It seems to work, but I haven’t tried adding it to HA yet. I’ll get to that tomorrow.

There might be a missing step from the installation instructions. I needed to run npm run build before I was able to deploy.