Python script for Netatmo weather station

Python and python framework

Moderator: leecollings

cyberbob
Posts: 12
Joined: Monday 02 March 2015 14:46
Target OS: NAS (Synology & others)
Domoticz version:
Contact:

Re: Python script for Netatmo weather station

Post by cyberbob »

Screen Shot 2015-03-06 at 13.36.29.png
Screen Shot 2015-03-06 at 13.36.29.png (221.61 KiB) Viewed 6095 times
Definitely
User avatar
Mediacj
Posts: 74
Joined: Wednesday 11 February 2015 16:09
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: Netherlands
Contact:

Re: Python script for Netatmo weather station

Post by Mediacj »

Ok problem solved, the Domoticz Hardware ID in the netatmo_settings.xml file was wrong, changed it to the right hardware id and now it works!

You can find the right hardware id by: http://192.168.xx.xx:8080/json.htm?type=hardware
Piacco
Posts: 70
Joined: Friday 14 November 2014 9:33
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Python script for Netatmo weather station

Post by Piacco »

Hello the Netatmo script works great thanks :D , but i have a problem with the Noise meter, in the netatmo settings file i have added dev_type =243 and subtype =24, when i check the devices tab i see the Noise meter with the Domoticz logo and the noise value, but when i add the device i can't find it on the utility tab :o, what do i wrong?
cyberbob
Posts: 12
Joined: Monday 02 March 2015 14:46
Target OS: NAS (Synology & others)
Domoticz version:
Contact:

Re: Python script for Netatmo weather station

Post by cyberbob »

which version of domoticz are you using?
Piacco
Posts: 70
Joined: Friday 14 November 2014 9:33
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Python script for Netatmo weather station

Post by Piacco »

I'm using version 2.2284 on a raspberry pi
cyberbob
Posts: 12
Joined: Monday 02 March 2015 14:46
Target OS: NAS (Synology & others)
Domoticz version:
Contact:

Re: Python script for Netatmo weather station

Post by cyberbob »

upgrade to 2300+
Piacco
Posts: 70
Joined: Friday 14 November 2014 9:33
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Python script for Netatmo weather station

Post by Piacco »

thnx, problem is solved :D
User avatar
wadoline
Posts: 6
Joined: Monday 14 July 2014 17:45
Target OS: Linux
Domoticz version:
Contact:

Re: Python script for Netatmo weather station

Post by wadoline »

Hi,

I have a problem with Sound meter, it always measures 0 dBs in domoticz. All devices show right values excepts this one.

I have this line in Settings:

<device data_type="Noise" domoticz_dev_id="90008" domoticz_dev_subtype="24" domoticz_dev_type="243" id="70:ee:xx:xx:xx:xx" module_id="" />

Can you help me?

Best regards
cyberbob
Posts: 12
Joined: Monday 02 March 2015 14:46
Target OS: NAS (Synology & others)
Domoticz version:
Contact:

Re: Python script for Netatmo weather station

Post by cyberbob »

did you adjust the script and update domoticz to version 2300+?
User avatar
wadoline
Posts: 6
Joined: Monday 14 July 2014 17:45
Target OS: Linux
Domoticz version:
Contact:

Re: Python script for Netatmo weather station

Post by wadoline »

I am in 2313. What do you mean with "adjust the script"?

Thaks for your fast answer!!! :)
cyberbob
Posts: 12
Joined: Monday 02 March 2015 14:46
Target OS: NAS (Synology & others)
Domoticz version:
Contact:

Re: Python script for Netatmo weather station

Post by cyberbob »

this is only the netatmo.py adjusted to include rain and decibel.
netatmo.py.zip
(4.71 KiB) Downloaded 271 times

Check this post for installation method:

http://www.domoticz.com/forum/viewtopic ... =20#p26776

replace the script with the one above..

and

use these device settings

Code: Select all

<devices>
   <device data_type="Temperature" domoticz_dev_id="90001" domoticz_dev_subtype="10" domoticz_dev_type="80" ...
        <device data_type="CO2" domoticz_dev_id="90002" domoticz_dev_subtype="0" domoticz_dev_type="249" ...
        <device data_type="Humidity" domoticz_dev_id="90003" domoticz_dev_subtype="0" domoticz_dev_type="81" ...
        <device data_type="Noise" domoticz_dev_id="90008" domoticz_dev_subtype="24" domoticz_dev_type="243" ...
        <device data_type="Pressure" domoticz_dev_id="90004" domoticz_dev_subtype="9" domoticz_dev_type="243" ...
        <device data_type="Temperature" domoticz_dev_id="90005" domoticz_dev_subtype="10" domoticz_dev_type="80" ...
        <device data_type="Humidity" domoticz_dev_id="90006" domoticz_dev_subtype="0" domoticz_dev_type="81"... 
        <device data_type="Rain" domoticz_dev_id="90007" domoticz_dev_subtype="0" domoticz_dev_type="85" ...
        </devices>
User avatar
wadoline
Posts: 6
Joined: Monday 14 July 2014 17:45
Target OS: Linux
Domoticz version:
Contact:

Re: Python script for Netatmo weather station

Post by wadoline »

It works like a charms!!!!

Thankyou very much!!!!
mathlegl
Posts: 2
Joined: Monday 16 March 2015 17:19
Target OS: -
Domoticz version:
Contact:

Re: Python script for Netatmo weather station

Post by mathlegl »

Hi,
I try to find the xml file. This download link doenst seems to be correct. (http://www.domoticz.com/forum/download/file.php?id=785)
The archive downloaded is corrupted.

Could somebody tell me where I can find the xml file ou the package (.py and .xml file).

Thank you.
mathlegl
Posts: 2
Joined: Monday 16 March 2015 17:19
Target OS: -
Domoticz version:
Contact:

Re: Python script for Netatmo weather station

Post by mathlegl »

Forget my post.
The archive couldn't be opened by the Windows archive manager.
I tested with 7zip ; it works.

Sorry !
Piacco
Posts: 70
Joined: Friday 14 November 2014 9:33
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Python script for Netatmo weather station

Post by Piacco »

Hello,

Is it possible to use the barometer symbol in stead of the gauge symbol for showing the Netatmo pressure?

I've tried domoticz_dev_subtype = 1 and domoticz_dev_type = 84 but that's not working :(
brakc
Posts: 28
Joined: Friday 13 March 2015 12:36
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Python script for Netatmo weather station

Post by brakc »

Piacco wrote:Hello,

Is it possible to use the barometer symbol in stead of the gauge symbol for showing the Netatmo pressure?

I've tried domoticz_dev_subtype = 1 and domoticz_dev_type = 84 but that's not working :(
I have same pb
RFAH
Posts: 15
Joined: Monday 16 March 2015 11:10
Target OS: Raspberry Pi / ODroid
Domoticz version: 3.6395
Location: Netherlands
Contact:

Re: Python script for Netatmo weather station

Post by RFAH »

Hello,

I've a problem with my rain sensor.
I've installed the python script accoording to the install procedure given by Box18 (thanks for that)
and i use the netatmo.py script provided by cyberbot with the noise and rain sensor lines added. (also thanks)
All sensors are added to Domoticz, included the rain sensor. All sensors are given the correct values, except the rain sensor.
The rain sensor is added to the tab weather, but with the Domoticz logo and no values.
In the tab devices, it is shown as a rain sensor and the shown values are 0, 0
I'm using Domoticz version 2.2336 on raspberry pi.

Can somebody help me to correct this problem or is it a bug?
Thanks in advance.

Edit: 30-3-2015
I've tried something else.
I added a rain sensor using the button "add virtual sensor" in the tab Hardware.
Looked into the database and compared the two rain sensors.
I can see two differences, the Unit number and subtype
The unit number of the sensor added by the script is 3, the manually added sensor is 1.
The subtype of the sensor added by the script is 0, the manually added sensor subtype is 3.
So i changed the subtype number of the rain sensor in 3 (in the netatmo setting file), removed the sensor of the devices tab and let the script do it's work.
The sensor is added again, but still the same problem as described above.
I also tried to add a rain sensor manally and change the id in the netatmo setting file into the id of the manually added sensor, but then the value of the sensor is not changed (also the time does not update, while the other sensors times are updated.) So no succes at all.

If anybody has any idea's it would be appreciated.
Thanks
User avatar
wadoline
Posts: 6
Joined: Monday 14 July 2014 17:45
Target OS: Linux
Domoticz version:
Contact:

Re: Python script for Netatmo weather station

Post by wadoline »

RFAH wrote:Hello,

I've a problem with my rain sensor.
I've installed the python script accoording to the install procedure given by Box18 (thanks for that)
and i use the netatmo.py script provided by cyberbot with the noise and rain sensor lines added. (also thanks)
All sensors are added to Domoticz, included the rain sensor. All sensors are given the correct values, except the rain sensor.
The rain sensor is added to the tab weather, but with the Domoticz logo and no values.
In the tab devices, it is shown as a rain sensor and the shown values are 0, 0
I'm using Domoticz version 2.2336 on raspberry pi.

Can somebody help me to correct this problem or is it a bug?
Thanks in advance.

Edit: 30-3-2015
I've tried something else.
I added a rain sensor using the button "add virtual sensor" in the tab Hardware.
Looked into the database and compared the two rain sensors.
I can see two differences, the Unit number and subtype
The unit number of the sensor added by the script is 3, the manually added sensor is 1.
The subtype of the sensor added by the script is 0, the manually added sensor subtype is 3.
So i changed the subtype number of the rain sensor in 3 (in the netatmo setting file), removed the sensor of the devices tab and let the script do it's work.
The sensor is added again, but still the same problem as described above.
I also tried to add a rain sensor manally and change the id in the netatmo setting file into the id of the manually added sensor, but then the value of the sensor is not changed (also the time does not update, while the other sensors times are updated.) So no succes at all.

If anybody has any idea's it would be appreciated.
Thanks
I have the same problem with my rain sensor. I added today but this sensor isn't working in domoticz.

Image
brakc
Posts: 28
Joined: Friday 13 March 2015 12:36
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Python script for Netatmo weather station

Post by brakc »

Hi,

I connect with login and password to my Domoticz. but netatmo.py doesn't work, error : "Error in TransferMeasures"

Why can I configure my Domoticz login/password in this script please?

Thank's
User avatar
krazny
Posts: 27
Joined: Saturday 01 November 2014 23:31
Target OS: Raspberry Pi / ODroid
Domoticz version: beta
Location: Netherlands
Contact:

Re: Python script for Netatmo weather station

Post by krazny »

brakc wrote:Hi,

I connect with login and password to my Domoticz. but netatmo.py doesn't work, error : "Error in TransferMeasures"

Why can I configure my Domoticz login/password in this script please?

Thank's
There are 2 files;
1. netatmo.py
2. netatmo_settings.xml

With the files/settings below it works with my Netatmo;
netatmo.py

Code: Select all

import sys
import os
import string
import json
import urllib
import datetime
import xml.etree.ElementTree as ET


####################################################################################################
## Access token handling
####################################################################################################


####################################################################################################
## Netatmo constants
####################################################################################################

URL_RequestToken = 'https://api.netatmo.net/oauth2/token'
URL_DeviceList = 'https://api.netatmo.net/api/devicelist'
URL_GetMeasure = 'https://api.netatmo.net/api/getmeasure'

PARM_Grant_Type = 'grant_type'
PARM_Grant_Type_Password = 'password'
PARM_Grant_Type_RefreshToken = 'refresh_token'
PARM_Client_Id = 'client_id'
PARM_Client_Secret = 'client_secret'
PARM_Username = 'username'
PARM_Password = 'password'
PARM_Refresh_Token = 'refresh_token'

PARM_Access_Token = 'access_token'
PARM_Device_Id = 'device_id'
PARM_Module_Id = 'module_id'
PARM_Scale = 'scale'
PARM_Scale_Max = 'max'
PARM_Scale_30Min = '30min'
PARM_Scale_1Hour = '1hour'
PARM_Scale_3Hours = '3hours'
PARM_Scale_1Day = '1day'
PARM_Scale_1Week = '1week'
PARM_Scale_1Month = '1month'

PARM_Measure_Type = 'type'
PARM_Date_Begin = 'date_begin'
PARM_Date_End = 'date_end'
PARM_Date_End_Last = 'last'
PARM_Limit = 'limit'
PARM_Optimize = 'optimize'
PARM_Real_Time = 'real_time'

DATATYPE_Temperature = 'Temperature'
DATATYPE_Humidity = 'Humidity'
DATATYPE_CO2 = 'Co2'
DATATYPE_Pressure = 'Pressure'
DATATYPE_Noise = 'Noise'

RESPONSE_Status = 'status'
RESPONSE_Status_OK = 'ok'
RESPONSE_Body = 'body'


####################################################################################################
## DomoticZ constants
####################################################################################################

URL_JSON = "/json.htm"
PARM_Type = "type"
PARM_Type_Command = "command"
PARM_Param = "param"
PARM_Param_UpdateDevice = "udevice"
PARM_HardwareId = "hid"
PARM_DeviceId = "did"
PARM_DeviceUnit = "dunit"
PARM_DeviceType = "dtype"
PARM_DeviceSubType = "dsubtype"
PARM_NValue = "nvalue"
PARM_SValue = "svalue"

# status types for humidity
HUMSTAT_NORMAL = 0x0;
HUMSTAT_COMFORT = 0x1;
HUMSTAT_DRY = 0x2;
HUMSTAT_WET = 0x3;


####################################################################################################
## XML constants
####################################################################################################

TOKEN_ROOT = 'token'
TOKEN_ATTR_ACCESS_TOKEN = 'access_token'
TOKEN_ATTR_EXPIRES_IN = 'expires_in' 
TOKEN_ATTR_REFRESH_TOKEN = 'refresh_token'
TOKEN_ATTR_EXPIRED_AT = 'expired_at' 


SETTINGS_ROOT = 'settings'
NODE_AUTHENTICATE = 'authentication'
ATTR_AUTH_CLIENT_ID = 'client_id'
ATTR_AUTH_CLIENT_SECRET= 'client_secret'
ATTR_AUTH_USERNAME = 'username'
ATTR_AUTH_PASSWORD = 'password'

NODE_DOMOTICZ = 'domoticz'
ATTR_DOMOTICZ_URL = 'url'
ATTR_DOMOTICZ_HARDWARE_ID = 'hardware_id'

DEVICES_ROOT = 'devices'
DEVICES_NODE_DEVICE = 'device'
DEVICES_NODE_MODULE = 'module' 
DEVICES_ID = 'id'
DEVICES_NODE_MEASURE = 'measure' 


####################################################################################################
## General functiona
####################################################################################################

def Log(message):
    sys.stderr.write("{}\n".format(message))
    

def GetWorkingPath():
    return os.path.dirname(os.path.realpath(__file__)) + os.sep


####################################################################################################
## Access token handling
####################################################################################################
    
def GetTokenFileName():
    return GetWorkingPath() + "token.xml"

    
def SaveToken(token):
    token_filename = GetTokenFileName()
    if ET.iselement(token):
        try:
            ET.ElementTree(token).write(token_filename)
        except Exception:
            Log('ERROR: in SaveToken(%s)' % token_filename)            
            pass
    pass    
    

def DeleteTokenFile():
    token_filename = GetTokenFileName()
    if os.path.isfile(token_filename):
        try:
            os.remove(token_filename)
        except:            
            Log('ERROR: in DeleteTokeFile(%s)' % token_filename)
            pass
    pass


def CreateToken(json_data):
    newtoken = ET.Element(TOKEN_ROOT)
    if newtoken != None and json_data != None:
        json_decoded = json.loads(json_data)
        newtoken.set(TOKEN_ATTR_ACCESS_TOKEN, json_decoded[TOKEN_ATTR_ACCESS_TOKEN])
        newtoken.set(TOKEN_ATTR_EXPIRES_IN, str(json_decoded[TOKEN_ATTR_EXPIRES_IN]))
        newtoken.set(TOKEN_ATTR_REFRESH_TOKEN, json_decoded[TOKEN_ATTR_REFRESH_TOKEN])
        expired_at = datetime.datetime.now() + datetime.timedelta(seconds = json_decoded[TOKEN_ATTR_EXPIRES_IN])
        newtoken.set(TOKEN_ATTR_EXPIRED_AT, expired_at.strftime("%Y-%m-%d %H:%M:%S"))
        SaveToken(newtoken)
    return newtoken


def GetAuthentication():
    authentication = {PARM_Client_Id: '', PARM_Client_Secret: '', PARM_Username: '', PARM_Password: ''}
    settings = LoadSettings()
    if settings != None:
        authenticate = settings.find('.//%s' % NODE_AUTHENTICATE)
        if authenticate != None:
            if len(authenticate.get(ATTR_AUTH_CLIENT_ID)) > 0:
                authentication[PARM_Client_Id] = authenticate.get(ATTR_AUTH_CLIENT_ID)
            if len(authenticate.get(ATTR_AUTH_CLIENT_SECRET)) > 0:
                authentication[PARM_Client_Secret] = authenticate.get(ATTR_AUTH_CLIENT_SECRET)
            if len(authenticate.get(ATTR_AUTH_USERNAME)) > 0:
                authentication[PARM_Username] = authenticate.get(ATTR_AUTH_USERNAME)
            if len(authenticate.get(ATTR_AUTH_PASSWORD)) > 0:
                authentication[PARM_Password] = authenticate.get(ATTR_AUTH_PASSWORD)
            pass
        pass
    return authentication

def RequestToken():
    authentication = GetAuthentication()
    params = urllib.urlencode({
        PARM_Grant_Type: PARM_Grant_Type_Password,
        PARM_Client_Id: authentication[PARM_Client_Id],        
        PARM_Client_Secret: authentication[PARM_Client_Secret],
        PARM_Username: authentication[PARM_Username],
        PARM_Password: authentication[PARM_Password]
        })
    json_data = urllib.urlopen(URL_RequestToken, params).read()
    return CreateToken(json_data)


def RefreshToken(refresh_token):
    authentication = GetAuthentication()
    params = urllib.urlencode({
        PARM_Grant_Type: PARM_Grant_Type_RefreshToken,
        PARM_Refresh_Token: refresh_token,
        PARM_Client_Id: authentication[PARM_Client_Id],        
        PARM_Client_Secret: authentication[PARM_Client_Secret]
        })
    json_data = urllib.urlopen(URL_RequestToken, params).read()
    return CreateToken(json_data)

    
def LoadToken():
    token_filename = GetTokenFileName()
    if os.path.isfile(token_filename):
        try:
            tree = ET.parse(token_filename)
            root = tree.getroot()
            return root
        except:            
            Log('ERROR: in LoadToken(%s)' % token_filename)
            pass
    return RequestToken()


def GetToken():
    token = LoadToken()
    if token != None:
        try:
            # we should always have a token
            expired_at = datetime.datetime.strptime(token.get(TOKEN_ATTR_EXPIRED_AT), "%Y-%m-%d %H:%M:%S")
            if expired_at < datetime.datetime.now() + datetime.timedelta(seconds = 30):
                # is expired or will expire within 30 seconds: Refresh the token
                token = RefreshToken(token.get(TOKEN_ATTR_REFRESH_TOKEN))
            pass
        except:
            token = None
            pass
    if token == None:
        DeleteTokenFile()
    return token                                 


####################################################################################################
## Devices
####################################################################################################
    
def GetSettingsFileName():
    return GetWorkingPath() + "netatmo_settings.xml"


def AddSubElement(node, tag):
    if node != None and tag != None:
        return ET.SubElement(node, tag)
    return None

    
def SaveSettings(settings):
    filename = GetSettingsFileName()
    if ET.iselement(settings):
        try:
            ET.ElementTree(settings).write(filename)
        except Exception:
            Log('ERROR: in SaveSettings(%s)' % filename)            
            pass
    pass    
    

def CreateSettings():
    settings = ET.Element(SETTINGS_ROOT)
    if settings != None:
        authenticate = AddSubElement(settings, NODE_AUTHENTICATE)
        authenticate.set(ATTR_AUTH_CLIENT_ID, 'CLIENT_ID')
        authenticate.set(ATTR_AUTH_CLIENT_SECRET, 'CLIENT_SECRET')
        authenticate.set(ATTR_AUTH_USERNAME, 'USERNAME')
        authenticate.set(ATTR_AUTH_PASSWORD, 'PASSWORD')
        domoticz = AddSubElement(settings, NODE_DOMOTICZ)
        domoticz.set(ATTR_DOMOTICZ_URL, 'http://127.0.0.1:8080')
        domoticz.set(ATTR_DOMOTICZ_HARDWARE_ID, '10')
        devices = AddSubElement(settings, DEVICES_ROOT)
        SaveSettings(settings)
    return settings


def LoadSettings():
    filename = GetSettingsFileName()
    if os.path.isfile(filename):
        try:
            tree = ET.parse(filename)
            root = tree.getroot()
            return root
        except:            
            Log('ERROR: in LoadSettings(%s)' % filename)
            pass
    return CreateSettings()   
    

def GetDomoticzIds(device_ids, device_id, module_id, data_type):
    domoticz_ids = {"domoticz_dev_id" : "", "domoticz_dev_type": "", "domoticz_dev_subtype" : ""}
    if device_ids != None:
        try:
            device_present = False
            # cannot get this one to work (using multiple attributes)
            xpath = '//%s[@id="%s" and @module_id="%s" and @data_type="%s"]' % (DEVICES_NODE_DEVICE, device_id, module_id, data_type)
            xpath = './/%s[@id="%s"]' % (DEVICES_NODE_DEVICE, device_id)
            device_list = device_ids.findall(xpath)
            for device in device_list:
                if device.get("module_id") == module_id and device.get("data_type") == data_type:
                    device_present = True
                    domoticz_ids["domoticz_dev_id"] = device.get("domoticz_dev_id")
                    domoticz_ids["domoticz_dev_type"] = device.get("domoticz_dev_type")
                    domoticz_ids["domoticz_dev_subtype"] = device.get("domoticz_dev_subtype")
                    break
            if device_present == False:
                new_device = AddSubElement(device_ids, DEVICES_NODE_DEVICE)
                new_device.set("id", device_id)
                new_device.set("module_id", module_id)
                new_device.set("data_type", data_type)
                new_device.set("domoticz_dev_id", "")
                new_device.set("domoticz_dev_type", "")
                new_device.set("domoticz_dev_subtype", "")
        except:
            pass
    return domoticz_ids
                    
    
def AddMeasures(root, data_types, device_ids):
    if root == None or data_types == None:
        return
    device_id = root.get(DEVICES_ID)
    module_id = root.get("module_id")
    for data_type in data_types:
        data_element = AddSubElement (root, DEVICES_NODE_MEASURE)         
        data_element.set("data_type", data_type)
        domoticz_ids = GetDomoticzIds(device_ids, device_id, module_id, data_type)
        for domoticz_id in domoticz_ids.keys():
            data_element.set(domoticz_id, domoticz_ids[domoticz_id])
    pass


def AddDevices(root, devices, device_ids, unit, is_module):
    if root == None or devices == None or device_ids == None:
        return unit
    for device in devices:
        unit += 1
        if is_module == True:
            device_id = device["main_device"]
            module_id = device["_id"]
        else:
            device_id = device["_id"]
            module_id = ""
        module_name = device["module_name"]
        device_element = AddSubElement (root, DEVICES_NODE_DEVICE)         
        device_element.set(DEVICES_ID, device_id); 
        device_element.set("module_id", module_id); 
        device_element.set("module_name", module_name);
        device_element.set("dunit", str(unit))
        AddMeasures(device_element, device["data_type"], device_ids)        
    return unit


def GetMeasures(devices, access_token):
    try:
        # cannot get this one to work using multiple attributes
        xpath = './/%s' % DEVICES_NODE_DEVICE
        device_list = devices.findall(xpath)
        for device in device_list:
            device_id = device.get("id")
            module_id = device.get("module_id")
            xpath_measure = './/%s' % DEVICES_NODE_MEASURE
            measure_list = device.findall(xpath_measure)
            for measure in measure_list:
                if module_id != None:
                    params = urllib.urlencode({
                        PARM_Access_Token: access_token,
                        PARM_Device_Id: device_id,
                        PARM_Module_Id: module_id,
                        PARM_Scale: PARM_Scale_Max,
                        PARM_Measure_Type: measure.get("data_type"),
                        PARM_Date_End: PARM_Date_End_Last,
                        PARM_Optimize: "True"                    
                        })
                else:
                    params = urllib.urlencode({
                        PARM_Access_Token: access_token,
                        PARM_Device_Id: device_id,
                        PARM_Scale: PARM_Scale_Max,
                        PARM_Measure_Type: measure.get("data_type"),
                        PARM_Date_End: PARM_Date_End_Last,
                        PARM_Optimize: "True"                    
                        })
                json_data = urllib.urlopen(URL_GetMeasure, params).read()
                measure_response = json.loads(json_data)
                if measure_response != None and RESPONSE_Status in measure_response.keys() and measure_response[RESPONSE_Status] == RESPONSE_Status_OK:
                    body = measure_response[RESPONSE_Body]
                    value = body[0]["value"][0][0]
                    measure.set("value", str(value))
                    pass
    except:
        pass    
    #pass


def MeasureIsValid(measure):
    if measure.get("data_type") != None and len(measure.get("data_type")) > 0 and \
       measure.get("domoticz_dev_id") != None and len(measure.get("domoticz_dev_id")) > 0 and \
       measure.get("domoticz_dev_type") != None and len(measure.get("domoticz_dev_type")) > 0 and \
       measure.get("domoticz_dev_subtype") != None and len(measure.get("domoticz_dev_subtype")) > 0 and \
       measure.get("value") != None and len(measure.get("value")) > 0:
        return True
    return False


def AddQueryParameter(name, value, cat = '&'):
    return '%s%s=%s' % (cat, name, value)


def GetNSValues(data_type, value):
    values = { PARM_NValue: "0", PARM_SValue: "0" }
    if data_type == DATATYPE_Temperature:
        values[PARM_SValue] = value
    elif data_type == DATATYPE_Humidity:
        values[PARM_NValue] = value
        intvalue =int(value)
        if intvalue < 40:
            values[PARM_SValue] = HUMSTAT_DRY
        elif intvalue > 90:
            values[PARM_SValue] = HUMSTAT_WET
        elif intvalue >= 50 and intvalue <= 70:
            values[PARM_SValue] = HUMSTAT_COMFORT
        else:
            values[PARM_SValue] = HUMSTAT_NORMAL                    
    elif data_type == DATATYPE_CO2:
        values[PARM_NValue] = value
    elif data_type == DATATYPE_Pressure:
        values[PARM_SValue] = value
    elif data_type == DATATYPE_Noise:
        values[PARM_NValue] = value
    return values


def TransferSingleMeasure(url, hardware_id, unit, measure):
    if MeasureIsValid(measure):
        url = '%s%s' % (url, URL_JSON)
        url += AddQueryParameter(PARM_Type, PARM_Type_Command, '?')
        url += AddQueryParameter(PARM_Param, PARM_Param_UpdateDevice)
        url += AddQueryParameter(PARM_HardwareId, hardware_id)
        url += AddQueryParameter(PARM_DeviceId, measure.get("domoticz_dev_id"))
        url += AddQueryParameter(PARM_DeviceUnit, unit)
        url += AddQueryParameter(PARM_DeviceType, measure.get("domoticz_dev_type"))
        url += AddQueryParameter(PARM_DeviceSubType, measure.get("domoticz_dev_subtype"))
        values = GetNSValues(measure.get("data_type"), measure.get("value"))
        for value in values.keys():
            url += AddQueryParameter(value, values[value])
        urllib.urlopen(url)
        pass
    pass


def TransferMeasures(devices, url, hardware_id):
    # Transfer all measurements to DomoticZ
    try:
        xpath = './/%s' % DEVICES_NODE_DEVICE
        device_list = devices.findall(xpath)
        for device in device_list:
            unit = device.get("dunit")
            xpath_measure = './/%s[@value]' % DEVICES_NODE_MEASURE
            measure_list = device.findall(xpath_measure)
            for measure in measure_list:
                TransferSingleMeasure(url, hardware_id, unit, measure)
                pass
        pass
    except:
        Log("Error in TransferMeasures")
        pass    
    #ET.dump(devices)
    pass


def HandleDevices(json_data, access_token):
    if json_data != None:
        try:
            device = json.loads(json_data)
            if RESPONSE_Status in device.keys() and RESPONSE_Body in device.keys() and device[RESPONSE_Status] == RESPONSE_Status_OK:
                body = device[RESPONSE_Body]
                settings = LoadSettings()
                domoticz = settings.find('.//%s' % NODE_DOMOTICZ)                
                device_ids = settings.find('.//%s' % DEVICES_ROOT)
                devices = ET.Element(DEVICES_ROOT)
                if devices != None:
                    # Build the actual device list
                    unit = AddDevices(devices, body['devices'], device_ids, 0, False)
                    unit = AddDevices(devices, body['modules'], device_ids, unit, True)
                    if domoticz != None and domoticz.get(ATTR_DOMOTICZ_HARDWARE_ID) == None:
                        domoticz.set(ATTR_DOMOTICZ_HARDWARE_ID, "100")
                    SaveSettings(settings)
                    # Get the actual measurement values from Netatmo service
                    GetMeasures(devices, access_token)
                    if domoticz != None and domoticz.get(ATTR_DOMOTICZ_URL) != None:
                        # Transfer the measurements to DomoticZ
                        TransferMeasures(devices, domoticz.get(ATTR_DOMOTICZ_URL), domoticz.get(ATTR_DOMOTICZ_HARDWARE_ID))
        except:
	    Log("Error in HandleDevices")
            pass
    pass

    
def UpdateDeviceList(access_token):
    if access_token != None:
        params = urllib.urlencode({
            PARM_Access_Token: access_token
            })
        json_data = urllib.urlopen(URL_DeviceList, params).read()
        HandleDevices(json_data, access_token)
    pass


####################################################################################################
## Main entry
####################################################################################################

def main():
    token = GetToken()
    if token != None:
        UpdateDeviceList(token.get(TOKEN_ATTR_ACCESS_TOKEN))
        
    
if __name__ == "__main__":
    main()
netatmo_settings.xml (of course fill in your own ID's / credentials)
FYI
Get your hardware ID by opening the URL with all the Hardware IDs from Domoticz; http://YOUR_IP:8080/json.htm?type=devices&filter=all&used=true&order=Name

Code: Select all

<settings>
	<authentication client_id="ID" client_secret="ID" password="PASSWORD" username="USERNAME" />
	<domoticz hardware_id="YOUR_HARDWARE_ID" url="http://127.0.0.1:8080" />
		<devices>
		</devices>
</settings>
Now run the netatmo.py script in a telnet session on your Domoticz device; python netatmo.py
If successful, the netatmo_settings.xml has now changed and updated with your Netatmo devices. In my case; The indoor station and 1 outdoor sensor;

My netatmo_settings.xml file looks like this: (again change your IDs and credentials

Code: Select all

<settings>
	<authentication client_id="ID" client_secret="SECRET" password="PASSWORD" username="USERNAME" />
	<domoticz hardware_id="YOUR_HARDWARE_ID" url="http://127.0.0.1:8080" />
		<devices>
		<device data_type="Temperature" domoticz_dev_id="90001" domoticz_dev_subtype="10" domoticz_dev_type="80" id="MACADDRESS" module_id="" />
		<device data_type="CO2" domoticz_dev_id="90002" domoticz_dev_subtype="0" domoticz_dev_type="249" id="MACADDRESS" module_id="" />
		<device data_type="Humidity" domoticz_dev_id="90003" domoticz_dev_subtype="0" domoticz_dev_type="81" id="MACADDRESS" module_id="" />
		<device data_type="Noise" domoticz_dev_id="" domoticz_dev_subtype="" domoticz_dev_type="" id="" module_id="" />
		<device data_type="Pressure" domoticz_dev_id="90004" domoticz_dev_subtype="9" domoticz_dev_type="243" id="MACADDRESS" module_id="" />
		<device data_type="Temperature" domoticz_dev_id="90005" domoticz_dev_subtype="10" domoticz_dev_type="80" id="MACADDRESS" module_id="MAC_OUTDOORSTATION" />
		<device data_type="Humidity" domoticz_dev_id="90006" domoticz_dev_subtype="0" domoticz_dev_type="81" id="MACADDRESS" module_id="MAC_OUTDOORSTATION" />
	</devices>
</settings>
Raspberry Pi, Aeon Z-Stick, Fibaro Motion Sensor, 4x Fibaro Wall Plug, 2x Fibaro Dimmer, Netatmo Weatherstation
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest