Blink Camera support

Need to take a break from it for tonight...
Your function samples match up with what I have been trying from the API sample, but I am having no success. I get an "401 = Unauthorized" for the http.
When trying CURL (to see about different formats and just to match up with the API sample and your functions, I get an Invalid PIN response.

Frustrating to feel like it is so close and thinking I must just have a formatting/typo somewhere (thus why I tried the CURL also).

1 Like

Same thing happened to me and I couldn't figure it out.. I was about to give up and realized the JSON I was sending had an extra comma in it.

dunno if this will help.. i got the login and verify to work using this script I wrote. My goal was to prompt for the email/password and then automatically set the values for CLIENT/ACCOUNT/REGION/etc.. but, instead I had to first login and then update the script to set those values.

I'm not sure the best way to send JSON data that has variables in it in a curl command -- hence the functions to print out the JSON..

#!/bin/sh

EMAIL=
PASS=

ACCT=
CLIENT=
PIN=
TOKEN=
REGION=

function printLoginBody() {
    cat <<EOF
    {
      "unique_id": "00000000-0000-0000-0000-000000000000",
      "email": "${EMAIL}",
      "password": "${PASS}"
    }
EOF
}

function login() {
    curl -X POST \
        -H 'Content-Type: application/json'  \
        --data "$(printLoginBody)" \
        --url https://rest-prod.immedia-semi.com/api/v4/account/login
}

function printVerifyBody() {
    cat <<EOF
    {
      "pin": "${PIN}"
    }
EOF
}

function verifyPin() {
    curl --request POST \
        --header 'content-type: application/json' \
        --header "token-auth: $TOKEN" \
        --data "$(printVerifyBody)" \
        --url https://rest-$REGION.immedia-semi.com/api/v4/account/$ACCT/client/$CLIENT/pin/verify
}

function fetchDevices() {
    curl --request GET \
        --header 'content-type: application/json' \
        --header "token-auth: $TOKEN" \
        --url https://rest-$REGION.immedia-semi.com/api/v3/accounts/$ACCT/homescreen
}

echo
echo
echo "Select from the options below:"
select ans in login verifyPIN fetchDevices exit
do
    case $ans in
        login)
            login
            break;
            ;;
        verifyPIN)
            verifyPin
            break;
            ;;
        fetchDevices)
            fetchDevices
            break;
            ;;
        exit)
            exit;
            ;;
    esac
done
1 Like

Following! This would be helpful for me as well. I have two Blink hubs (indoor and outdoor) and arm/disarm based on geofencing/time of day. Would be good to move this off IFTTT and make it local (without have to set up yet another hub RPi; etc!)

The biggest challenge will be receiving timely motion alerts from the cloud without using an external link of some sort. Information I see shows no broadcast from the Cloud, instead frequent polling. I can see Hubitat providing 30 second latency unless you can get a webSocket interface to Blink working or you use a node.js computer or account on (yet another) web product.

Note: If you have an Amazon Alexa account, you should be able to (1) arm/disarm and (2) receive motion alerts from a camera system linked to Amazon Alexa. I can work out instructions for this (I would have to reinstall my old camera system and link to Alexa to test the concept).

Dave

As far as I'm aware Alexa can only arm/disarm via voice commands. It is not possible using Alexa Routines.

Really. You should be able to use a routine that uses the motion alert. See below from Aug of last year

Since it seems like most people have examples using curl (which I have never used before now) I tried using it to see what happens then I felt I would be able to make the driver replicate it. I already had the portion to request the PIN working, so I started with a curl command to do the equivalent figuring that once I had one figured out, the other should be similar...

I have replaced any "identifying" information in the below examples with variable names.

This will successfully trigger a PIN request:

curl --request POST --url https://rest-prod.immedia-semi.com/api/v4/account/login --header "content-type: application/json" --data "{'unique_id': '${ UNIQUE ID HERE }', 'password':'${ PASSWORD }','email':'${ EMAIL }'}"

However, the huge number of variants submitting the PIN verification are failing (either Unauthorized Access 101, or more typically an Invalid PIN with code 1621 response). Any idea on the correct structure of the curl for that part? I have tried 15 different variants so at this point I figure it is just something simple and I need a different pair of eyes to look at it. Here is a sample of one (that failed) that I had the most hope for:

curl --request POST --url https://rest-prod.immedia-semi.com/api/v4/account/${ ACCT# }/client/${ CLIENT# }/pin/verify --header "content-type: application/json" --header "token-auth:${ TOKEN }" --data '{"pin":"${ PIN }"}'
1 Like

It would be nice to get the actual motion outputs directly, instead of having to bounce them through Alexa.

Even nicer would be the ability to get the temperature and the light level from them.

1 Like

I have created some rough examples using my old TP-Link cloud device as a template. It may be more familiar.

def getTokenExample(eMail, password) {
	def data = [
		unique_id: "00000000-0000-0000-0000-000000000000",
		email: "${eMail}",
 		password: "${password}"
	]
	def params = [
		uri: "https://rest-prod.immedia-semi.com/api/v4/account/login",
		contentType: 'application/json',
		headers: ['Accept':'application/json; version=1, */*; q=0.01'],
		body : new groovy.json.JsonBuilder(data).toString()
	]
	httpPostJson(params) {resp ->		//	Can also try httpPost
		log.trace resp.status
		log.trace resp.data
		//	if successful, the token would be in the response text.  Example
		//	state.token = resp.data.result.token
		//	Region, Account, and Client should also be in the response somewhere.
		//	state.region = ...........
		//	state.account = ..............
		//	state.client = .........................
	}
}

def enterTokenExample() {
	//	Variables are in form ${variableName}
	def token = state.token	//	from getTokenExample
	def region = "enter region from the example"	//	REGION FROM EXAMPLE
	def account = "enter the account from the example"	//	ACCT from example
	def client = "enter client from the example"
	def data = [
		pin: "${PIN}"	//	FROM PHONE.
		//	This is a potenial error point.  The PIN is entered here as a string, does the app expect a number?
		//	if so, it would be pin: PIN
	]
	def params = [
		uri: "https://rest-${region}.immedia-semi.com/api/v4/account/${account}/client/${client}/pin/verify",
		contentType: 'application/json',
		headers: [token-auth: token],
		body : new groovy.json.JsonBuilder(data).toString()
	]
	httpPostJson(params) {resp ->		//	Can also try httpPost
		log.trace resp.status
		log.trace resp.data
	}
}

def fetchDevices() {
	//	Variables are in form ${variableName}
	def token = state.token	//	from getTokenExample
	def region = "enter region from the example"	//	REGION FROM EXAMPLE
	def account = "enter the account from the example"	//	ACCT from example
	def client = "enter client from the example"
	
	def params = [
		uri: "https://rest-${region}.immedia-semi.com/api/v3/accounts/${account}/homescreen",
		contentType: 'application/json',
		headers: [token-auth: token]
	]
	httpGet(params) {resp ->
		log.trace resp.status
		log.trace resp.data
	}
}
2 Likes

Welcome to the community!

You should be able get all these directly from the cloud. The latency for the motion detection will be dependent on how frequently you send the get command to the cloud. This latency will NOT be instantaneous. I can see ever 15 or 30 seconds, but more frequently may cause hub performance issues.

This is a designer issue. However, using Amazon is an alternate that would reduce Hubitat load for motion detection.

Dave

1 Like

Yes you can use motion sensors to trigger an Alexa routine but I can't see how that would enable the ability to arm or disarm blink without using IFTTT.

You create a virtual on-off switch. Publish to Amazon via the Amazon Echo Skill. In Amazon, you create two skills - arm and unarm that are triggered by the virtual device on-off attribute. When triggered, these would arm or disarm the device.

Motion is the reverse. You create skills based on motion active and inactive. They would trigger another switch that links to a Hubitat virtual device which would then trigger the motion. (this is all VERY analogous to the IFTTT method).

I do not see how to arm or disarm blink cameras within an Amazon echo routine. I do not think this is possible. Do you have an example you can show?

Edit : typos

You cannot set an action to arm or disarm blink systems in an Alexa Routine.

2 Likes

Not to argue. You see actual results. However, from the Amazon.com page below:
"Works with Alexa – View live streams, motion clips, arm and disarm your system, and set up smart reorders for batteries through select Alexa-enabled devices. " I would surely contact Blink support. They are surely falling short on their promise since Alexa Routines are one of the strengths of amazon connection.

You are correct. Wanted to understand @djgutheinz said it could be done. Really wish Amazon would allow.

Thanks. Getting lots of help, and I appreciate it... I just wish I understood what was going wrong better. Using your enterTokenExample as a test, I get an error in the def params, for the headers:
illegal colon after argument expression; solution: a complex label expression before a colon must be parenthesized @ line 321, column 29

Tried changing it to:

headers: "[ token-auth: ${ token }]",

This does not get a compile error, but results in an error in the log:
java.lang.ClassCastException: org.codehaus.groovy.runtime.GStringImpl cannot be cast to java.util.Map on line 326

Line 326 corresponds to:

httpPostJson(params) {resp -> 

As a related example, here is my latest Params line (this one gets a 408 - Request Timeout response):

Params = [ uri: "https://rest-${ state.Tier }.immedia-semi.com/api/v4/account/${ state.AccountID }/client/${ state.Client }/pin/verify", contentType: "application/json", headers: "[token-auth: ${ state.AuthToken }]", body: "{\"pin\":\"${ PIN }\"}" ]
1 Like

Try this:

headers: [(token-auth): state.AuthToken ]
Or
headers: [(token-auth): "${state.AuthToken}" ]

2 Likes

Thanks, but neither of those work. The problem then is that it indicates:
java.lang.NullPointerException: Cannot invoke method minus() on null object

BUT... What you folks were leading to made me stumble on the correct solution and I got a successful PIN validation! What that line should have been is:
headers: [ "token-auth": "${ state.AuthToken }" ]

So the now-working key line is:

Params = [ uri: "https://rest-${ state.Tier }.immedia-semi.com/api/v4/account/${ state.AccountID }/client/${ state.Client }/pin/verify", contentType: "application/json", headers: ["token-auth": "${ state.AuthToken }" ], body: "{\"pin\":\"${ PIN }\"}" ]

Seeing that verification was a nice boost in the morning here. Of course now I need to get to work, but I should be able to get some more done this evening. Sorry about the delay everyone! Have to add a lot of thank yous to this driver.

5 Likes

Thanks to all that have contributed to this so far.
It will be so nice to get a working solution for this technology that does not require third party assistance such as IFTTT.

3 Likes