Package: pysnoo2
pysnoo2pysnoo2 is a python library to interact with the SNOO Smart Sleeper Bassinet. pysnoo2 is based on pysnoo by @rado0x54DisclaimerPlease use this library at your own risk and make sure that you do not violate theTerms of Service of HappiestBaby. Note that happiest baby can change their API any anytime and may cause this library to break.Installationpipinstallpysnoo2Known IssuesRefresh tokens are not currently working, access tokens are instead granted every 3 hours as needed.To DoSave pubnub tokens off similar to how access tokens are saved for re-useProgrammatic UsageProgramatically, the project provides two main class inferfaces. The Snoo API Client interfacesnoo.pyand the Snoo PubNub
interfacepubnub.py.Here's a short example to setup both. It uses the Snoo API Interface to get the Snoo serial number,
and access token, and pubnub access token which are required to initialize the PubNub interface. More usage examples can be
found by looking at theCLI ToolasyncwithSnooAuthSession(token,token_updater)asauth:ifnotauth.authorized:# Init Authnew_token=awaitauth.fetch_token()token_updater(new_token)# Snoo API Interfacesnoo=Snoo(auth)devices=awaitsnoo.get_devices()ifnotdevices:# No devicesprint('There is no Snoo connected to that account!')else:# Snoo PubNub InterfacepubnubToken=awaitsnoo.pubnub_auth()pubnub=SnooPubNub(pubnubToken,snoo.pubnub_auth,devices[0].serial_number,f'pn-pysnoo-{devices[0].serial_number}')last_activity_state=(awaitpubnub.history())[0]iflast_activity_state.state_machine.state==SessionLevel.ONLINE:# Startawaitpubnub.publish_start()else:# Stopawaitpubnub.publish_goto_state(SessionLevel.ONLINE)awaitpubnub.stop()CLI UsageThe pysnoo package contains thesnooCLI tool:# snoo -hSnooSmartBassinett

positionalarguments:{user,device,baby,last_session,status,sessions,session_avg,total,monitor,history,toggle,toggle_hold,up,down}optionalarguments:-h,--helpshowthishelpmessageandexit-uUSERNAME,--usernameUSERNAMEusernameforSnooaccount-pPASSWORD,--passwordPASSWORDusernameforSnooaccount-tfile,--token_filefileCachedtokenfiletoreadandwriteanexistingOAuthTokento.-dDATETIME,--datetimeDATETIMEDatetimeinISO8601fromat.Usedforsomecommands.-llevel,--levelSessionLevelUsedtosetthelevelwiththelevelcommand.SeeSessionLevelforvalidvalues.-v,--verboseShowverboselogging.Credentials / Token / First RunIf the tool cannot find a valid oauth token in--token_file(./.snoo_token.txtby default), it will automatically query for
a username and password on the first run. After a successful authentication a token will be placed in the specified
file. Subsequent calls that have access to the token will not query for credentials any longer.# snoo statusUsername:snoo-user@gmail.com
Password:awake(since:0:34:54.891556)# ls .snoo_token.txt.snoo_token.txt# snoo statusawake(since:0:36:27.266366).snoo_token.txtSnoo CLI Commandsstatussnoo statusreturns the current status of the snoo.monitorsnoo monitormonitors the live events emited by the Snoo Bassinet. Monitoring can be cancelled
viaCTRL-C. The command always returns the last historic event when launching.# snoo monitor{"left_safety_clip":1,"rx_signal":{"rssi":-45,"strength":99},"right_safety_clip":1,"sw_version":"v1.14.22","event_time_ms":1698816595667,"state_machine":{"up_transition":"NONE","since_session_start_ms":-1,"sticky_white_noise":"off","weaning":"off","time_left":-1,"session_id":"0","state":"ONLINE","is_active_session":"false","down_transition":"NONE","hold":"off","audio":"on"},"system_state":"normal","event":"status_requested"}togglesnoo toggletoggle the Snoo Bassinet between an active and a paused state.toggle_holdsnoo toggle_holdwill toggle the hold option on or off.upsnoo upwill transition the Snoo Bassinet one level up (if available)downsnoo downwill transition the Snoo Bassinet one level down (if available)historysnoo historywill return the last 100 events from the Snoo Bassinet.# snoo history{'event':'cry','event_time':'2021-02-13T16:02:23.025Z','left_safety_clip':True,'right_safety_clip':True,'rx_signal':{'rssi':-45,'strength':100},'state_machine':{'audio':True,'down_transition':'LEVEL1','hold':False,'is_active_session':True,'session_id':'1696520262','since_session_start':'1:01:40.420000','state':'LEVEL2','sticky_white_noise':False,'time_left':'0:06:00','up_transition':'LEVEL3','weaning':False},'sw_version':'v1.14.12','system_state':'normal'}{'event':'activity','event_time':'2021-02-13T16:02:40.628Z','left_safety_clip':True,'right_safety_clip':True,'rx_signal':{'rssi':-45,'strength':100},'state_machine':{'audio':True,'down_transition':'NONE','hold':False,'is_active_session':False,'session_id':'0','since_session_start':None,'state':'ONLINE','sticky_white_noise':False,'time_left':None,'up_transition':'NONE','weaning':False},'sw_version':'v1.14.12','system_state':'normal'}...babysnoo babyreturns data about the baby and the settings of the linked Snoo Bassinet.{'baby':'ID','babyName':'BABY_NAME','birthDate':'2021-01-17','createdAt':'2020-11-18T16:12:08.064Z','disabledLimiter':False,'pictures':[{'encoded':False,'id':'PICTURE_ID','mime':'image/png','updatedAt':'2021-01-21T10:45:07.542Z'}],'preemie':None,'settings':{'carRideMode':False,'daytimeStart':7,'minimalLevel':'baseline','minimalLevelVolume':'lvl-1','motionLimiter':True,'offlineLock':False,'responsivenessLevel':'lvl0','soothingLevelVolume':'lvl0','weaning':False},'sex':'Male','updatedAt':'2021-02-02T22:23:10.770Z','updatedByUserAt':'2021-02-02T21:35:45.665Z'}Some of these settings can be upgraded programmatically.devicesnoo devicereturns information around the linked Snoo Bassinet:{'baby':'BABY_ID','createdAt':'2019-02-19T19:03:13.544Z','firmwareUpdateDate':'2021-01-14T17:36:51.149Z','firmwareVersion':'v1.14.12','lastProvisionSuccess':'2020-11-18T16:25:57.973Z','lastSSID':{'name':'SSID-Network','updatedAt':'2021-01-28T22:04:21.151Z'},'serialNumber':'SERIAL_NUMBER','timezone':'America/New_York','updatedAt':'2021-02-13T16:50:16.685Z'}usersnoo userreturns account related information:{'email':'EMAIL','givenName':'GIVEN_NAME','region':'US','surname':'SURNAME','userId':'USER_ID'}last_sessionsnoo last_sessionreturns information around the last or currently active session.{'currentStatus':'awake','currentStatusDuration':'0:51:04.121661','endTime':'2021-02-13T16:02:40.635Z','levels':['BASELINE','LEVEL1','LEVEL2','ONLINE'],'startTime':'2021-02-13T15:00:42.604Z'}session_avgsnoo session_avg -d DATETIMEreturns the average values for the week starting fromDATETIME.# snoo session_avg -d 2021-01-30T07:00:00{'daySleepAVG':'5:38:43','days':{'daySleep':['4:46:18','5:06:47','5:32:30','7:41:16','6:15:46','5:39:27','4:28:57'],'longestSleep':['3:25:44','3:35:49','3:32:16','3:56:58','3:11:14','4:02:54','3:12:44'],'nightSleep':['8:12:50','8:30:22','6:40:29','6:42:13','8:46:07','6:24:24','8:14:42'],'nightWakings':[4,3,6,5,4,3,3],'totalSleep':['12:59:08','13:37:09','12:12:59','14:23:29','15:01:53','12:03:51','12:43:39']},'longestSleepAVG':'3:33:57','nightSleepAVG':'7:38:44','nightWakingsAVG':4,'totalSleepAVG':'13:17:27'}totalsnoo totalreturns the total time the Snoo Bassinet has been in operation.# snoo total11days,9:13:32