Netatmo: Welcome Camera

„Welcome“ may sound like a strange name for Netatmo’s Web-enabled security camera, but the camera expresses the camera’s purpose: „There’s always something at the front door to welcome invited guests, and the proper authorities to any unwanted activity.“

The Welcome performs the basic features of a home security camera well, without a lot of bells and whistles – except for the actual whistles that comes with your computer or smartphone. Its truly unique feature is remarkably well.

Welcome to indoor camera with face recognition capabilities. Welcome senses motions and detects faces or when Presence detects cars, animals or humans.
Each detection is considered an event, and the cameras generate timelines of events (motions, face detected, car detected etc …).
Users can choose what they think is relevant to record in their settings. For Presence, users can choose their settings where they want to record. They can select specific areas for alerts, called alert zones. Only the events within these alert zones will be recorded.
Events are recorded and stored locally on the SD card that goes with every camera, depending on those above mentioned preferences.Following a FIFO model, as soon as the SD card is full, the oldest videos get deleted and disappear from users‘ timelines.
For each event, the camera takes a snapshot and records a video. The snapshot is displayed in the timeline.

Accessing the Netatmo Data Servers:

Using Netatmo Smart Home API, you can retrieve users‘ home events and timelines, browse through past events, access videos and event snapshots. To retrieve data from Netatmo cameras, you have to use the Netatmo Data Servers. Authorization code grant is required for authentication. User should be able to remove his camera from the 3rd party application. For getting the authentication (access tokens) we are programming in PHP / Python and running the code on the local host (server).

Using PHP –

Steps-

  1. Installing the XAMPP application for creating a server.
  2. Creation of the Apache servers to execute the PHP codes.
  3. Creation of the Netatmo app on the Netatmo development pages.
  4. Modifying the code with the client id and client secret according to the web app created on netatmo pages.
  5. Running the PHP code on the local browser using the link something like this http: //localhost/php/WEB_AuthorizationGrant_Example.php? Start = Start & error = redirect_uri_mismatch & state = 660769866

Code Snipets

<? Php 
/ * 
* Authentication to Netatmo Servers using Authorization grant. 
This script has to be hosted on a web server in order to make it work 
* For more details about Netatmo API, please take a look at https://dev.netatmo.com/doc 
* / 
define ( '__ ROOT__', dirname (dirname (__FILE__))); 
require_once (__ROOT __. '/ src / Netatmo / autoload.php'); 
require_once 'Config.php'; 
require_once 'Utils.php'; 

// API client configuration 
$ config = array ("client_id" => $ client_id, 
                "client_secret" => $ client_secret, 
                "scope" => Netatmo \ Common \ NAScopes :: SCOPE_READ_STATION);
$ config ['client_secret'] = 'rS0oKZmPmcQSxmcqeKEkcNDFVi3bk5fQI3yN49'; 
$ config ['scope'] = 'read_camera'; 
$ client = new Netatmo \ Clients \ NAWelcomeApiClient ($ config); 
$ client = new Netatmo \ Clients \ NAWSApiClient ($ config); 

// if code is provided in get param, It Means user has accepted your app and has been redirected here 
if (isset ($ _ GET [ "code"])) 
{ 
    // get the tokens, you can store $ tokens [ ' refresh_token '] in order to retrieve a new access_token next time 
    try { 
        $ tokens = $ client-> getAccessToken (); 
    } 
    catch (Netatmo \ Exceptions \ NAClientException $ ex) 
    {
        echo "An error occured while trying to retrieve your tokens \ n"; 
        echo "Reason:". $ ex-> getMessage (). "\ n"; 
        the (); 
    } 
    // retrieve user's weatherstation data 
    try { 
        $ data = $ client-> getData (); 
    } 
    catch (Netatmo \ Exceptions \ NAClientException $ ex) 
    { 
       echo "An error occurred while retrieving data:". $ Ex-> getMessage () "\ n". 
       the (); 
    } 

    if (! isset ($ data ['devices']) ||! is_array ($ data ['devices']) || count ($ data ['devices']) <
        the (); 
    } 

    // In this example, we only want to deal with the first weather station 
    $ device = $ data ['devices'] [0]; 

    // last month report 
    $ reports = getMonthReport ($ device, $ client); 

    // get device timezone 
    if (! Is_null ($ device) &&! Empty ($ device)) 
    { 
        if (isset ($ device ['place'] ['timezone'])) 
            $ tz = $ device ['place'] ['timezone']; 
        else $ tz = 'GMT'; 

    // print data 
?> 
<Html> 
<meta charset = "UTF-8"> 
    <Body> 
        <div style = "text-align: center;"php echo $ device ['station_name']; ?> </ h2> 
            <p> id: <? php echo $ device ['_ id']; ?> </ P> 
<? Php 
printDashboardDataInHtml ($ device ['dashboard_data'], $ tz); 
foreach ($ device ['modules'] as $ module) 
{ 
    printModuleInHtml ($ module, $ tz); 
} 

    if (! is_null ($ reports) &&! empty ($ reports)) 
    { 
         echo "<div style = 'display: inline-block; vertical-align: top; text-align: center; margin: 15px;'>" ; 
         echo "<h3> Month report </ h3>";
                 printDashBoardDataInHtml ($ report, $ tz); 
             else echo "<p>". $ report. "</ p>"; 
         } 
         echo "</ div>"; 
    } 
 ?> 
        </ Div> 
    </ body> 
</ html> 
<? Php 
    } 
} 
else { 
    // OAuth returned an error 
    if (isset ($ _ GET ['error'])) 
    { 
        if ($ _ GET ['error'] === "access_denied") 
            echo "You refused to let this application access your Netatmo data \ n "; 
        else echo "An error occured";
/ html> <? Php 
    } 
} 
/ **

* @param array data: 
* @brief: Print general data of a device in HTML 
* / 
function printDashboardDataInHtml ($ data, $ tz) 
{ 
    foreach ($ data as $ key => $ value) 
    { 
        echo "<p>"; 
        echo $ key. ":"; 
        if ($ key === 'time_utc' || preg_match ("/ ^ date_. * /", $ key)) 
        { 
            printTimeInTz ($ value, $ tz, 'j FH: i'); 
        } 
        else { 
            echo $ value; 
            print unit ($ key); 
        } 
        echo "</ p>";

* @param string $ tz device's timezone 
* @brief print a Netatmo Weather Station's HTML module 
* / 
function printModuleInHtml ($ module, $ tz) 
{ 
    echo "<div style = 'display: inline-block; vertical-align: top; margin : 15px; text-align: center; '> "; 
    echo "<h3>". $ Module ['module_name']. "</ H3>"; 
    echo "<p> id:". $ module ['_ id']. "</ P>"; 
    echo "<p> type:"; 
    switch ($ module ['type']) 
    { 
        case "NAModule1": echo "Outdoor"; 
            break; 
        case "NAModule2": echo "Wind Sensor"; 
            break; 
        case "NAModule3": echo "Rain Gauge";
            break; 
        case "NAModule4": echo "Indoor"; 
            break; 
    } 
    echo "</ p>"; 
    printDashboardDataInHtml ($ module ['dashboard_data'], $ tz); 
    echo "</ div>"; 
} 

/ ** 
* @param array $ device 
* @param NAWSApiClient $ client 
* @return array $ report: array with device or module as keys, and their data as the month 
* values retrieve month data for a device and its modules 
* / 
function getMonthReport ($ device, $ client) 
{ 
    $ report = array (); 
    // step between two measurements 
    $ scale = '1month';
    $ type = "Temperature, CO2, Humidity, Pressure, Noise, max_temp, date_max_temp, min_temp, date_min_temp, max_hum, date_max_hum, min_hum, date_min_hum, max_pressure, date_max_pressure, min_pressure, date_min_pressure, max_noise, date_max_noise, min_noise, date_min_noise, max_co2, date_max_co2, min_co2, date_min_co2 "; 
    // main device 
    try { 
        $ measure = $ client-> getMeasure ($ device ['_ id'], NULL, $ scale, $ type, NULL, "last", NULL, FALSE, FALSE); 
        $ measure = addMeasureKeys ($ measure, $ type); 
        $ report [$ device ['_ id']] = $ measure; 
    } 
    catch (Netatmo \ Exceptions \ NAClientException $ ex) 
    { 
        $ report [$ device ['_ id']] = "$ device ['_ id']. ":". $ ex-> getMessage (); 
    } 

    foreach ($ device ['modules'] as $ module) 
    { 
        switch ($ module ['type']) 
        { 
            // outdoor 
            case "NAModule1": $ type = "temperature, humidity"; 
                 break; 
            // wind sensor 
            case "NAModule2": $ type = "WindStrength, WindAngle, GustStrength, GustAngle, date_max_gust"; 
                 break; 
            // Rain Gauge 
            case "NAModule3": $ type = "sum_rain"; 
                break; 
            // Indoor
            case "NAModule4": $ type = "temperature, Co2, humidity, noise, pressure"; 
                break; 
        } 
        try { 
            $ measure = $ client-> getMeasure ($ device ['_ id'], $ module ['_ id'], $ scale, $ type, NULL, "last", NULL, FALSE, FALSE); 
            $ measure = addMeasureKeys ($ measure, $ type); 
            $ report [$ module ['_ id']] = $ measure; 
        } 
        catch (Netatmo \ Exceptions \ NAClientException $ ex) 
        { 
            $ report [$ module ['_ id']] = "Error retrieving measure for". $ module ['_ id']. ":". $ ex-> getMessage ();
} 
/ ** 
* @param array measures: measure sent back by getMeasure method 
* @param string $ type: types of measure requested 
* @return array $ measurements: array of measures mapped by type 
* @brief add the type as a key for each measure 
* / 
function addMeasureKeys ($ measures, $ type) 
{ 
    $ measurements = array (); 
    $ keys = explode (",", $ type); 
    foreach ($ measures as $ measure) 
    { 
           foreach ($ measure as $ key => $ val) 
           { 
               $ measurements [$ keys [$ key]] = $ val; 
           } 
    } 
    return $ measurements; 
} 
?

During the process, the following errors were faced – 

Error 1 – The device was successfully registered with the netatmo development account.

Error 2- an error occurred which could not be resolved.

Error 3 – As suggested by the Netatmo Developer community, we tried putting the same code in the Postman software.

References –

Netatmo Developer Program https://dev.netatmo.com/resources/technical/introduction

PHP Basics – https://www.w3schools.com/pHP/default.asp

Using Python – 

The following link was used for obtaining the access token using Python.
https://dev.netatmo.com/resources/technical/samplessdks/codesamples

Steps –

  1. Installation of Python 2.7x or 3x (Common errors with python installation – internal or external command not found, Solution inclusion of path in system path variables, Refer to image 1.2). Download latest version of Python from-https://www.python.org/downloads/
  2. Install the Pip library in python ( https://pip.pypa.io/en/stable/installing/ )
  3. Install the necessary libraries using ‚pip install xxxxxx‘ command in command prompt (Flask, Request)
  4. From the link above, modify the code with your client id and client secret.
  5. Run the python code using the command prompt.

Code Snipets –

from flask import Flask, render_template, redirect
from flask import request as r
import requests

app = Flask(__name__)

@app.route('/')
def sign():
return "<form action='/signin' method='get'><button type='submit'>Sign in</button></form>"

#Authorization Code type authentication flow
@app.route('/signin', methods=['GET'])
def signin():
# Test if "code" is provided in get parameters (that would mean that user has already accepted the app and has been redirected here)
if r.args.get('code'):
code = r.args.get('code')
payload = {'grant_type': 'authorization_code',
'client_id': '[5b0c5adb923dfe4ece8babb2]',
'client_secret': '[rS0oKZmPmcQSxmcqeKEkcNDFVi3bk5fQI3yN49]',
'code': code,
'redirect_uri': 'http://localhost:5000/signin'}
try:
response = requests.post("https://api.netatmo.com/oauth2/token", data=payload)
response.raise_for_status()
access_token=response.json()["access_token"]
refresh_token=response.json()["refresh_token"]
scope=response.json()["scope"]
return "<p>Your access_token is:" + access_token + "</p>"

except requests.exceptions.HTTPError as error:
print(error.response.status_code, error.response.text)
# Test if "error" is provided in get parameters (that would mean that the user has refused the app)
elif r.args.get('error') == 'access_denied':
return "The user refused to give access to his Netatmo data"
# If "error" and "code" are not provided in get parameters: the user should be prompted to authorize your app
else:

payload = {'client_id':"[5ae4d16aac34a592b18c0707]",
'redirect_uri': "http://localhost:5000/signin",
'scope': '[read_camera]',
'state':'[SOME_ARBITRARY_BUT_UNIQUE_STRING]'}
try:
response = requests.post("https://api.netatmo.com/oauth2/authorize", params=payload)
response.raise_for_status()
return redirect(response.url, code=302)
except requests.exceptions.HTTPError as error:
print(error.response.status_code, error.response.text)

if __name__ == "__main__":
app.run()

The following shows the Errors faced during the process

When you are doing the same thing, you are saying „You are entering the development servers, please use WSGI servers“.

Since the previous method did not work for us, the
following has been used for obtaining the access token using Python.
https://dev.netatmo.com/resources/technical/samplessdks/codesamples

This method is the creation of the python web app on the Azure cloud server using PowerShell.
The steps to follow are in the Following link:
https://docs.microsoft.com/en-us/azure/app-service/app-service-web-get-started-python
The same code used for this method. The following shows the errors

Schreibe einen Kommentar