[Python] Parrot flower Power

Vous avez créé un script LUA dont vous êtes fier, un .sh génial, un programme Python hors du commun, un Tuto, c'est ici que vous pouvez les partager.
deennoo
Messages : 4036
Inscription : 25 janv. 2015, 02:00

Re: Parrot flower Power

Message par deennoo »

Je viens de finir et d avoir ce qu'il me fallait, merci a Olivier pour son soutient et orientation

Voici mon script :

Code : Tout sélectionner

var async = require('async');

var FlowerPower = require('./index');

var hasCalibratedData = false;

var http = require('http');

var options = {
  host: '192.168.0.21',
  port: '8080', 
  path: ''
};

var path = '/json.htm?type=command&param=udevice&idx=';
var AirTemperature = 0;
var Humidity = 0;

FlowerPower.discover(function(flowerPower) {
  async.series([
    function(callback) {
      flowerPower.on('disconnect', function() {
        console.log('disconnected!');
        process.exit(0);
      });

      flowerPower.on('sunlightChange', function(sunlight) {
        console.log('sunlight = ' + sunlight.toFixed(2) + ' mol/m²/d');
        options.path = path + '1196&svalue=' + (sunlight.toFixed(2) * 53.93);
        var req = http.request(options).end(); 
      });

      flowerPower.on('soilElectricalConductivityChange', function(soilElectricalConductivity) {
        console.log('soil electrical conductivity = ' + soilElectricalConductivity.toFixed(2));
      });

      flowerPower.on('soilTemperatureChange', function(temperature) {
        console.log('soil temperature = ' + temperature.toFixed(2) + '°C');
	options.path = path + '1234&svalue=' + AirTemperature + ';' + Humidity + ';2' ;
        var req = http.request(options).end()
      });

      flowerPower.on('airTemperatureChange', function(temperature) {
        console.log('air temperature = ' + temperature.toFixed(2) + '°C');
      });

      flowerPower.on('soilMoistureChange', function(soilMoisture) {
        console.log('soil moisture = ' + soilMoisture.toFixed(2) + '%');
      });

      flowerPower.on('calibratedSoilMoistureChange', function(soilMoisture) {
        console.log('calibrated soil moisture = ' + soilMoisture.toFixed(2) + '%');
      });

      flowerPower.on('calibratedAirTemperatureChange', function(temperature) {
        console.log('calibrated air temperature = ' + temperature.toFixed(2) + '°C');
      });

      flowerPower.on('calibratedSunlightChange', function(sunlight) {
        console.log('calibrated sunlight = ' + sunlight.toFixed(2) + ' mol/m²/d');
      });

      flowerPower.on('calibratedEaChange', function(ea) {
        console.log('calibrated EA = ' + ea.toFixed(2));
      });

      flowerPower.on('calibratedEcbChange', function(ecb) {
        console.log('calibrated ECB = ' + ecb.toFixed(2) + ' dS/m');
      });

      flowerPower.on('calibratedEcPorousChange', function(ecPorous) {
        console.log('calibrated EC porous = ' + ecPorous.toFixed(2)+ ' dS/m');
        var req = http.request(options).end()
      });

      console.log('connectAndSetup');
      flowerPower.connectAndSetup(callback);
    },
    function(callback) {
      console.log('readSystemId');
      flowerPower.readSystemId(function(systemId) {
        console.log('\tsystem id = ' + systemId);
        callback();
      });
    },
    function(callback) {
      console.log('readSerialNumber');
      flowerPower.readSerialNumber(function(serialNumber) {
        console.log('\tserial number = ' + serialNumber);
        callback();
      });
    },
    function(callback) {
      console.log('readFirmwareRevision');
      flowerPower.readFirmwareRevision(function(firmwareRevision) {
        console.log('\tfirmware revision = ' + firmwareRevision);

        var version = firmwareRevision.split('_')[1].split('-')[1];

        hasCalibratedData = (version >= '1.1.0');

        callback();
      });
    },
    function(callback) {
      console.log('readHardwareRevision');
      flowerPower.readHardwareRevision(function(hardwareRevision) {
        console.log('\thardware revision = ' + hardwareRevision);
        callback();
      });
    },
    function(callback) {
      console.log('readManufacturerName');
      flowerPower.readManufacturerName(function(manufacturerName) {
        console.log('\tmanufacturer name = ' + manufacturerName);
        callback();
      });
    },
    function(callback) {
      console.log('readBatteryLevel');
      flowerPower.readBatteryLevel(function(batteryLevel) {
	options.path = path + '1232&nvalue=0&svalue=' + (batteryLevel);
        console.log('battery level = ' + batteryLevel);
	var req = http.request(options).end();
	
        callback();
      });
    },
    function(callback) {
      console.log('readFriendlyName');
      flowerPower.readFriendlyName(function(friendlyName) {
        console.log('\tfriendly name = ' + friendlyName);

        console.log('writeFriendlyName');
        flowerPower.writeFriendlyName(friendlyName, callback);
      });
    },
    function(callback) {
      console.log('readColor');
      flowerPower.readColor(function(color) {
        console.log('\tcolor = ' + color);

        callback();
      });
    },
    function(callback) {
      console.log('readSunlight');
      flowerPower.readSunlight(function(sunlight) {
        console.log('sunlight = ' + sunlight.toFixed(2) + ' mol/m²/d');

        callback();
      });
    },
    function(callback) {
      console.log('readSoilElectricalConductivity');
      flowerPower.readSoilElectricalConductivity(function(soilElectricalConductivity) {
        console.log('soil electrical conductivity = ' + soilElectricalConductivity.toFixed(2));

        callback();
      });
    },
    function(callback) {
      console.log('readSoilTemperature');
      flowerPower.readSoilTemperature(function(temperature) {
        console.log('soil temperature = ' + temperature.toFixed(2) + '°C');

        callback();
      });
    },
    function(callback) {
      console.log('readAirTemperature');
      flowerPower.readAirTemperature(function(temperature) {
        console.log('air temperature = ' + temperature.toFixed(2) + '°C');
	AirTemperature = temperature.toFixed(2);
        callback();
      });
    },
    function(callback) {
      console.log('readSoilMoisture');
      flowerPower.readSoilMoisture(function(soilMoisture) {
        console.log('soil moisture = ' + soilMoisture.toFixed(2) + '%');
	Humidity = soilMoisture.toFixed(2);
        callback();
      });
    },
    function(callback) {
      if (hasCalibratedData) {
        async.series([
          function(callback) {
            console.log('readCalibratedSoilMoisture');
            flowerPower.readCalibratedSoilMoisture(function(soilMoisture) {
              console.log('calibrated soil moisture = ' + soilMoisture.toFixed(2) + '%');

              callback();
            });
          },
          function(callback) {
            console.log('readCalibratedAirTemperature');
            flowerPower.readCalibratedAirTemperature(function(temperature) {
              console.log('calibrated air temperature = ' + temperature.toFixed(2) + '°C');

              callback();
            });
          },
          function(callback) {
            console.log('readCalibratedSunlight');
            flowerPower.readCalibratedSunlight(function(sunlight) {
              console.log('calibrated sunlight = ' + sunlight.toFixed(2) + ' mol/m²/d');

              callback();
            });
          },
          function(callback) {
            console.log('readCalibratedEa');
            flowerPower.readCalibratedEa(function(ea) {
              console.log('calibrated EA = ' + ea.toFixed(2));

              callback();
            });
          },
          function(callback) {
            console.log('readCalibratedEcb');
            flowerPower.readCalibratedEcb(function(ecb) {
              console.log('calibrated ECB = ' + ecb.toFixed(2) + ' dS/m');

              callback();
            });
          },
          function(callback) {
            console.log('readCalibratedEcPorous');
            flowerPower.readCalibratedEcPorous(function(ecPorous) {
              console.log('calibrated EC porous = ' + ecPorous.toFixed(2) + ' dS/m');

              callback();
            });
          },
          function() {
            callback();
          }
        ]);
      } else {
        callback();
      }
    },
    function(callback) {
      console.log('enableLiveMode');
      flowerPower.enableLiveMode(callback);
    },
    function(callback) {
      console.log('live mode');
      setTimeout(callback, 5000);
    },
    function(callback) {
      console.log('disableLiveMode');
      flowerPower.disableLiveMode(callback);
    },
    function(callback) {
      if (hasCalibratedData) {
        async.series([
          function(callback) {
            console.log('enableCalibratedLiveMode');
            flowerPower.enableCalibratedLiveMode(callback);
          },
          function(callback) {
            console.log('calibrated live mode');
            setTimeout(callback, 5000);
          },
          function(callback) {
            console.log('disableCalibratedLiveMode');
            flowerPower.disableCalibratedLiveMode(callback);
          },
          function() {
            callback();
          }
        ]);
      } else {
        callback();
      }
    },
    function(callback) {
      console.log('ledPulse');
      flowerPower.ledPulse(callback);
    },
    function(callback) {
      console.log('delay');
      setTimeout(callback, 2000);
    },
    function(callback) {
      console.log('ledOff');
      flowerPower.ledOff(callback);
    },
    function(callback) {
      console.log('disconnect');
      flowerPower.disconnect(callback);
    }
  ]);
});


Reste a updater le cloud directement depuis le Raspberry afin de s'affranchir de l'appli parrot
De quoi se faire Plaisir et essayer d'aider...
http://www.domo-attitude.fr
js-martin
Messages : 487
Inscription : 22 mars 2015, 22:08
Contact :

Re: Parrot flower Power

Message par js-martin »

Je viens d'avoir un 'flower power' pour Noel et j'ai pu l'intégrer à Domoticz.

L'utilisation des capteurs virtuels de type "compteurs" ne me plaisait pas. J'ai fait des capteurs virtuel "Temp" / "Hydro" et "Luminosité" (en Lux avec la petite conversion x54) : c'est mieux.

Pour le niveau d'engrais, je ne sais pas quoi choisir comme "capteur virtuel" : un avis ?

Par ailleurs, je voulais utiliser "Humidité du sol" (Soil Moisture) mais je ne sais pas quelle type de valeur est attendue (par défaut=> "3 cb" ??)

Je cherche...

Cela serait pas mal d'avoir la liste des capteurs virtuels avec les données attentdues :
par exemple pour un capteur température + hydro

Code : Tout sélectionner

température (float) ; hydrométrie (float) ; zone_confort(interger de 0 à 4)
(j'ai mis cela de tête, c'est pour montrer ce que je cherche pour tous les capteurs virtuels)

Pas mal aussi l'idée de faire les échanges avec le Raspberry en bluetooth : je vais y réflechir...
Domotisation de : mes compteurs EDF, solaire, eau / mon alarme / ma Chaudière Viessamnn / mon congel / ma sonnette. Matériels : Pi2 - RFXTrx433e - Zwave+ Aeotec, ampoules Hue - Détecteur et prises Fibaro - Capteurs Oregon - présentation installation => lien
js-martin
Messages : 487
Inscription : 22 mars 2015, 22:08
Contact :

Re: Parrot flower Power

Message par js-martin »

J'ai pas mal avancé :

1/ déjà, il y a ici la liste de toutes les données attendues par Domoticz : je le cherchais dans mon message précédent !
http://www.domoticz.com/wiki/Domoticz_API/JSON_URL%27s

2/ ensuite, j''ai fait quelques modifs dans le code :
- réécriture de la recherche des valeurs (j'avais des bugs avec les valeurs nulles ou négatives)
- prise en compte du niveau de la batterie du flower power dans chaque widget (comme cela, le widget passera en jaune lorsqu'il y aura moins de 10% de batterie)
- rajout d'un widget "Battery Level"

Je mets mon code ici bientôt si ça en intéresse certains.

3/ J'ai souhaité remplacer les 2 widgets "Instruction" et "Status" par un seul "Alerte" mais il y a un bug dans Domoticz
J'ai mis un message sur Domoticz.com pour voir si ça peut s'améliorer
http://www.domoticz.com/forum/viewtopic ... 693#p69159

4/ Pour une interrogation directe en bluetooth, j'aimerai savoir si cela pose un problème particulier pour la batterie ?
Domotisation de : mes compteurs EDF, solaire, eau / mon alarme / ma Chaudière Viessamnn / mon congel / ma sonnette. Matériels : Pi2 - RFXTrx433e - Zwave+ Aeotec, ampoules Hue - Détecteur et prises Fibaro - Capteurs Oregon - présentation installation => lien
deennoo
Messages : 4036
Inscription : 25 janv. 2015, 02:00

Message par deennoo »

Merci d'avance pour le futur partage.

Ayant déplacer mon flower power, je dois remettre en place l'interrogation par BT direct

4/normalement non, il faut être raisonnable, une fois par jour doit suffire.
js-martin
Messages : 487
Inscription : 22 mars 2015, 22:08
Contact :

Re: Parrot flower Power

Message par js-martin »

voila le code provisoire (car le point 3 - bug Domoticz - vient d'être résolu par gizmocuz dans la beta #4088 : Fixed: Alert Sensor, displaying sValue again !). Je vais pouvoir faire des belles alertes dans une version 2 qui arrivera bientôt ;)

Voici ma V1.1

Code : Tout sélectionner

#!/usr/bin/python
# -*- coding: utf-8 -*-


# il faut le module requests 
# sudo pip install requests 

import requests
from requests.auth import HTTPBasicAuth

from pprint import pformat  # here only for aesthetic 

import config_Domoticz

#~~~~~~~~~~ Parametres Domoticz ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
domoticz_ip=config_Domoticz.domoticz_ip
domoticz_port=config_Domoticz.domoticz_port
user=config_Domoticz.domoticz_user
password=config_Domoticz.domoticz_password
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#~~~~~~~~~~~ Parametres Parrot ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"

# First we set our credentials
username = 'login'
password = 'password'

# Get your client credentials here: https://apiflowerpower.parrot.com/api_access/signup
client_id = 'votre_id'
client_secret = 'lxX66ZPb8NATXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#~~~~~~~~~~~ Parametres de la plante ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#         c'est le nom que vous avez donne chez Parrot
Nom_Plante='Ficus'

### Parametrage des idx des widget text de Domoticz ##########################

periph_idx= {        'Plante_Lumiere_Instruction' : 112, 
            		     'Plante_Lumiere_Status' : 113,
                     'Plante_Lumiere_Valeur' : 124,
                     'Plante_Temp_Instruction' : 115,
                     'Plante_Temp_Status' : 116,
                     'Plante_Temp_Valeur' : 125,
                     'Plante_Humidite_Instruction' : 118,
                     'Plante_Humidite_Status' : 119,
                     'Plante_Humidite_Valeur' : 126,
                     'Plante_Engrais_Instruction' : 121,
                     'Plante_Engrais_Status' : 122,
                     'Plante_Engrais_Valeur' : 127,
                     'Plante_Batterie_Valeur' : 128,
                  }



##################################################################################

### Mode debug ##################################################################
# si debug = autre chose que 0 on affiche les données recues 
debug=1
##################################################################################



#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~~~~~~~~~~~~~~~~~~~~~~~~~FIN DES PARAMETRAGES~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


###### 
def maj_widget_texte(domoticz_idx,inst_key,battery):
    requete='http://'+domoticz_ip+':'+domoticz_port+'/json.htm?type=command&param=udevice&idx='+domoticz_idx+'&svalue='+inst_key+'&battery='+str(battery)
    r=requests.get(requete,auth=HTTPBasicAuth(user,password))
    if debug!=0:
        #print r	
        print "Index:"+domoticz_idx+" - Valeur:"+inst_key+" (battery level="+str(battery)+"%)"
       

#########

######En cours - attende de correction bug Domoticz
def maj_widget_texte2(domoticz_idx,inst_key1,inst_key2):
    if inst_key1 == 'status_ok': 
        # OK => green
        inst_key1='1'
    if inst_key1 == 'status_warning':
        # warning => orange
        inst_key1='3'
    if inst_key1 == 'status_critical':
        # critical => red
        inst_key1='4'

    requete='http://'+domoticz_ip+':'+domoticz_port+'/json.htm?type=command&param=udevice&idx='+domoticz_idx+'&nvalue='+inst_key1+'&svalue='+"blabla"
    r=requests.get(requete,auth=HTTPBasicAuth(user,password))
    if debug!=0:
        #print r
        print "Index:"+domoticz_idx+" - Alert_color:"+inst_key1+" - Valeur:"+inst_key2

req = requests.get('https://apiflowerpower.parrot.com/user/v1/authenticate',
                   data={'grant_type': 'password',
                         'username': username,
                         'password': password,
                         'client_id': client_id,
                         'client_secret': client_secret,
                         })
response = req.json()

if debug!=0:
    print ('############# Authentification###############')
    print('Server response: {0}'.format(pformat(response)))
    print ('##############################################')

# Get authorization token from response
access_token = response['access_token']
auth_header = {'Authorization': 'Bearer {token}'.format(token=access_token)}

# From now on, we won't need initial credentials: access_token and auth_header
# will be enough.

# Get sync data
req = requests.get('https://apiflowerpower.parrot.com/sensor_data/v3/sync',
                   headers=auth_header)
response = req.json()

if debug!=0:
    print ('############# Sensor datas Sync ###############')
    print ('Sync sensor data')
    print('Server response: {0}'.format(pformat(response)))
    print ('##############################################')


sync_locations = response['locations']
#print "SYNC_LOCATIONS"
#print sync_locations

# Build a dict to link location_identifiers to plant name
loc2name = {l['location_identifier']: l['plant_nickname'] for l in sync_locations}


# pour recuperer le niveau de la batterie, il faut lier le numero de serie
# du Flower Parot au nom de la plante choisie afin de relever le bon niveau de batterie 
# pour une plante donnée
# Build a second dict to link sensor_serial to plant name

name2serial = {l['plant_nickname']: l['sensor_serial'] for l in sync_locations}
#print "NAME2SERIAL"
#print name2serial
#print "voici le serial du flower power de la plante : "+Nom_Plante
serial=name2serial[Nom_Plante]
#print serial



# Get locations status
req = requests.get('https://apiflowerpower.parrot.com/sensor_data/v3/' +
                   'garden_locations_status',
                   headers=auth_header)
response = req.json()

if debug!=0:
    print ('############# Garden location Status###############')
    print (response)
    print ('############# Garden location Status End###############')



#### on recupere le niveau de la batterie du flower power grace au bon serial
ch=response['sensors']
#print ch
serial2battery = {l['sensor_serial']: l['battery_level'] for l in ch}
#print "SERIAL2BATTERY"
#print serial2battery
batt=serial2battery[serial]
#print batt
battery_level=batt['level_percent']
if debug!=0:
      print ('-------------------------------------------------------------------')
      print "voici le niveau de batterie du flower power de la plante "+Nom_Plante
      print battery_level
      print ('-------------------------------------------------------------------')
domoticz_idx=str(periph_idx['Plante_Batterie_Valeur'])
maj_widget_texte(domoticz_idx,str(battery_level),battery_level)


status_locations = response['locations']

Nom_Plante=Nom_Plante+":"

for loc in status_locations:
    plante=('{plant}:'.format(plant=loc2name[loc['location_identifier']].encode('utf-8')))
    print plante
    if plante == Nom_Plante:
        print('Plante trouvée')
        for metric in ['light', 'soil_moisture', 'air_temperature', 'fertilizer']:
            data = loc[metric]
            if debug!=0:
                print ('############# metrics###############')
                print('  {metric}:'.format(metric=metric))
                #print('    instruction_key: {0}'.format(data['instruction_key']))
                print('#####################################')
            inst_key=format(data['instruction_key'])
            status_key=format(data['status_key'])


            if metric == 'light':
                domoticz_idx=str(periph_idx['Plante_Lumiere_Instruction'])
                maj_widget_texte(domoticz_idx,inst_key,battery_level)
                domoticz_idx=str(periph_idx['Plante_Lumiere_Status'])
                maj_widget_texte(domoticz_idx,status_key,battery_level)
                #domoticz_idx='132'
                #maj_widget_texte2(domoticz_idx,status_key,inst_key)   
                z=data['gauge_values']
                # Conversion de la valeur en Lux (1 PAR = 53.93 Lux) 
                valeur=z['current_value']*53.93
                valeur="%.2f" % valeur
                domoticz_idx=str(periph_idx['Plante_Lumiere_Valeur'])
                maj_widget_texte(domoticz_idx,valeur,battery_level)

            if metric == 'soil_moisture':
                domoticz_idx=str(periph_idx['Plante_Humidite_Instruction'])
                maj_widget_texte(domoticz_idx,inst_key,battery_level)
                domoticz_idx=str(periph_idx['Plante_Humidite_Status'])
                maj_widget_texte(domoticz_idx,status_key,battery_level)

                z=data['gauge_values']
                valeur="%.2f" % z['current_value']
                domoticz_idx=str(periph_idx['Plante_Humidite_Valeur'])
                maj_widget_texte(domoticz_idx,valeur,battery_level)

            if metric == 'air_temperature':
                domoticz_idx=str(periph_idx['Plante_Temp_Instruction'])
                maj_widget_texte(domoticz_idx,inst_key,battery_level)
                domoticz_idx=str(periph_idx['Plante_Temp_Status'])
                maj_widget_texte(domoticz_idx,status_key,battery_level)

                z=data['gauge_values']
                valeur="%.1f" % z['current_value']
                domoticz_idx=str(periph_idx['Plante_Temp_Valeur'])
                maj_widget_texte(domoticz_idx,valeur,battery_level)

            if metric == 'fertilizer':
                domoticz_idx=str(periph_idx['Plante_Engrais_Instruction'])
                maj_widget_texte(domoticz_idx,inst_key,battery_level)
                domoticz_idx=str(periph_idx['Plante_Engrais_Status'])
                maj_widget_texte(domoticz_idx,status_key,battery_level)

                z=data['gauge_values']
                valeur="%.1f" % z['current_value']
                domoticz_idx=str(periph_idx['Plante_Engrais_Valeur'])
                valeur=str("%.1f" % (float(valeur)*100/5))
                maj_widget_texte(domoticz_idx,valeur,battery_level)

Explications :

il faut s'appuyer sur l'excellent tutorial de Patrice
http://easydomoticz.com/domoticz-et-par ... wer-power/

Par contre, au lieu de créer des widget virtuels "compteurs", il faut créer :

- un widget "température" pour la température
- trois widget "pourcentage' pour la batterie, l'humidité du sol et la quantité d'engrais
- un widget "luminosité en lux" pour la luminosité

voici mes modifications :
- réécriture de la recherche des valeurs (j'avais des bugs avec les valeurs nulles ou négatives)

Ce bout de code fait de recherche de chaîne de caractère mais cela plantait lorsque j'avais des valeurs spéciales (0.0 par exemple) :

Code : Tout sélectionner

            
                z=format(data['gauge_values'])
                lgterme=len(terme)
                trouve_a= z.find(terme)
                debut=trouve_a+lgterme
                valeur=z[debut+offset:debut+offset+lg_chaine_a_garder]
                domoticz_idx=str(periph_idx['Plante_Air_Valeur'])
                maj_widget_texte(domoticz_idx,valeur)
voici ma proposition en utilisant les fonctions de list de Python :

Code : Tout sélectionner

            
                z=data['gauge_values']
                valeur="%.1f" % z['current_value']
                domoticz_idx=str(periph_idx['Plante_Temp_Valeur'])
                maj_widget_texte(domoticz_idx,valeur,battery_level)
- Recupération du niveau de batterie :

Cela a été plus compliqué car il faut croiser deux requêtes qui n'ont pas grand chose en commun sauf le numéro de série du flower power (dans le cas où vous avez plusieurs flower power...)
flower_power1.jpg
flower_power1.jpg (69.25 Kio) Consulté 9498 fois
Enfin, j'ai pu associer le niveau de la batterie du flower power aux différents widgets virtuels en rajoutant simplement un :

Code : Tout sélectionner

 +'&battery='+str(battery)
à la fin des requêtes json de mise à jour de Domoticz :
flower_power2.jpg
flower_power2.jpg (73.27 Kio) Consulté 9498 fois
Comme cela, l'étiquette du widget changera de couleur lorsque la batterie sera sous la barre des 10% (et du coup, il est possible de supprimer le widget qui mesure le niveau de la batterie pour limiter le nombre de widgets)
Dernière modification par js-martin le 11 janv. 2016, 16:23, modifié 1 fois.
Domotisation de : mes compteurs EDF, solaire, eau / mon alarme / ma Chaudière Viessamnn / mon congel / ma sonnette. Matériels : Pi2 - RFXTrx433e - Zwave+ Aeotec, ampoules Hue - Détecteur et prises Fibaro - Capteurs Oregon - présentation installation => lien
js-martin
Messages : 487
Inscription : 22 mars 2015, 22:08
Contact :

Re:

Message par js-martin »

deennoo a écrit :4/normalement non, il faut être raisonnable, une fois par jour doit suffire.
Oui, c'est très raisonnable... mais si je veux suivre la luminosité de ma pièce, il faudrait le faire toutes les 10 min et j'ai peur pour la pile.

Dommage que ma sonde UV Oregon soit si peu sensible. Je n'ai jamais eu de réponse de la part d'Oregon à ce sujet d'ailleurs...
Domotisation de : mes compteurs EDF, solaire, eau / mon alarme / ma Chaudière Viessamnn / mon congel / ma sonnette. Matériels : Pi2 - RFXTrx433e - Zwave+ Aeotec, ampoules Hue - Détecteur et prises Fibaro - Capteurs Oregon - présentation installation => lien
js-martin
Messages : 487
Inscription : 22 mars 2015, 22:08
Contact :

Re: Parrot flower Power

Message par js-martin »

Voici la V2 qui fonctionnera seulement si votre version de Domoticz est supérieure ou égale à V2.4088 :

- les 8 widgets "texte" (status ou instruction) ne sont plus nécessaire.
- création de 4 widgets "alerter" qui cumulent les deux fonctions (il faut la version V2.4088 de Domoticz).

Code : Tout sélectionner

#!/usr/bin/python
# -*- coding: utf-8 -*-


# il faut le module requests 
# sudo pip install requests 

import requests
from requests.auth import HTTPBasicAuth

from pprint import pformat  # here only for aesthetic 

#import time
import config_Domoticz

#~~~~~~~~~~ Parametres Domoticz ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
domoticz_ip=config_Domoticz.domoticz_ip
domoticz_port=config_Domoticz.domoticz_port
user=config_Domoticz.domoticz_user
password=config_Domoticz.domoticz_password
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#~~~~~~~~~~~ Parametres Parrot ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"

# First we set our credentials
username = 'email'
password = 'mdp'

# Get your client credentials here: https://apiflowerpower.parrot.com/api_access/signup
client_id = 'email'
client_secret = 'XXXXXXXXXXXXX'
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#~~~~~~~~~~~ Parametres de la plante ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#         c'est le nom que vous avez donne chez Parrot
Nom_Plante='Ficus'

### Parametrage des idx des widget text de Domoticz ##########################

periph_idx= {        'Plante_Lumiere_Status' : 132,
                     'Plante_Lumiere_Valeur' : 124,
                     'Plante_Temp_Status' : 135,
                     'Plante_Temp_Valeur' : 125,
                     'Plante_Humidite_Status' : 136,
                     'Plante_Humidite_Valeur' : 126,
                     'Plante_Engrais_Status' : 137,
                     'Plante_Engrais_Valeur' : 127,
                     'Plante_Batterie_Valeur' : 128,
                  }



##################################################################################
### Option Widget battery ########################################################
# si wbattery = autre chose que 0 on active le widget dédié au niveau de batterie 
wbattery=1
##################################################################################



### Mode debug ##################################################################
# si debug = autre chose que 0 on affiche les données recues 
debug=1
##################################################################################



#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~~~~~~~~~~~~~~~~~~~~~~~~~FIN DES PARAMETRAGES~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


###### 
def maj_widget_texte(domoticz_idx,inst_key,battery):
    requete='http://'+domoticz_ip+':'+domoticz_port+'/json.htm?type=command&param=udevice&idx='+domoticz_idx+'&svalue='+inst_key+'&battery='+str(battery)
    r=requests.get(requete,auth=HTTPBasicAuth(user,password))
    if debug!=0:
        #print r	
        print "Index:"+domoticz_idx+" - Valeur:"+inst_key
       

#########

######
def maj_widget_alert(domoticz_idx,inst_key1,inst_key2,battery):
    if inst_key1 == 'status_ok': 
        # OK => green
        inst_key1='1'
    if inst_key1 == 'status_warning':
        # warning => orange
        inst_key1='3'
    if inst_key1 == 'status_critical':
        # critical => red
        inst_key1='4'
    
    #on rajoute un espace pour une meilleure lisibilité
    inst_key2=' '+inst_key2+' '
    requete='http://'+domoticz_ip+':'+domoticz_port+'/json.htm?type=command&param=udevice&idx='+domoticz_idx+'&nvalue='+inst_key1+'&svalue='+inst_key2+'&battery='+str(battery)
    r=requests.get(requete,auth=HTTPBasicAuth(user,password))
    if debug!=0:
        #print r
        print "Index:"+domoticz_idx+" - Alert_color:"+inst_key1+" - Valeur:"+inst_key2

req = requests.get('https://apiflowerpower.parrot.com/user/v1/authenticate',
                   data={'grant_type': 'password',
                         'username': username,
                         'password': password,
                         'client_id': client_id,
                         'client_secret': client_secret,
                         })
response = req.json()

if debug!=0:
    print ('############# Authentification###############')
    print('Server response: {0}'.format(pformat(response)))
    print ('##############################################')

# Get authorization token from response
access_token = response['access_token']
auth_header = {'Authorization': 'Bearer {token}'.format(token=access_token)}

# From now on, we won't need initial credentials: access_token and auth_header
# will be enough.

# Get sync data
req = requests.get('https://apiflowerpower.parrot.com/sensor_data/v3/sync',
                   headers=auth_header)
response = req.json()

if debug!=0:
    print ('############# Sensor datas Sync ###############')
    print ('Sync sensor data')
    print('Server response: {0}'.format(pformat(response)))
    print ('##############################################')


sync_locations = response['locations']
#print "SYNC_LOCATIONS"
#print sync_locations

# Build a dict to link location_identifiers to plant name
loc2name = {l['location_identifier']: l['plant_nickname'] for l in sync_locations}


# pour recuperer le niveau de la batterie, il faut lier le numero de serie
# du Flower Parot au nom de la plante choisie afin de relever le bon niveau de batterie 
# pour une plante donnée
# Build a second dict to link sensor_serial to plant name

name2serial = {l['plant_nickname']: l['sensor_serial'] for l in sync_locations}
#print "NAME2SERIAL"
#print name2serial
#print "voici le serial du flower power de la plante : "+Nom_Plante
serial=name2serial[Nom_Plante]
#print serial



# Get locations status
req = requests.get('https://apiflowerpower.parrot.com/sensor_data/v3/' +
                   'garden_locations_status',
                   headers=auth_header)
response = req.json()

if debug!=0:
    print ('############# Garden location Status###############')
    print (response)
    print ('############# Garden location Status End###############')



#### on recupere le niveau de la batterie du flower power grace au bon serial
ch=response['sensors']
#print ch
serial2battery = {l['sensor_serial']: l['battery_level'] for l in ch}
#print "SERIAL2BATTERY"
#print serial2battery
batt=serial2battery[serial]
#print batt
battery_level=batt['level_percent']
if debug!=0:
      print ('-------------------------------------------------------------------')
      print "voici le niveau de batterie du flower power de la plante "+Nom_Plante
      print battery_level
      print ('-------------------------------------------------------------------')

# Si vous souhaitez avoir un widget dédié avec le niveau de la batterie du flower power
if wbattery!=0:
     domoticz_idx=str(periph_idx['Plante_Batterie_Valeur'])
     maj_widget_texte(domoticz_idx,str(battery_level),battery_level)


status_locations = response['locations']

Nom_Plante=Nom_Plante+":"

for loc in status_locations:
    plante=('{plant}:'.format(plant=loc2name[loc['location_identifier']].encode('utf-8')))
    print plante
    if plante == Nom_Plante:
        print('Plante trouvée')
        for metric in ['light', 'soil_moisture', 'air_temperature', 'fertilizer']:
            data = loc[metric]
            if debug!=0:
                print ('############# metrics###############')
                print('  {metric}:'.format(metric=metric))
                #print('    instruction_key: {0}'.format(data['instruction_key']))
                print('#####################################')
            inst_key=format(data['instruction_key'])
            status_key=format(data['status_key'])


            if metric == 'light':
                domoticz_idx=str(periph_idx['Plante_Lumiere_Status'])
                maj_widget_alert(domoticz_idx,status_key,inst_key,battery_level)   
                
                z=data['gauge_values']
                # Conversion de la valeur en Lux (1 PAR = 53.93 Lux) 
                valeur=z['current_value']*53.93
                valeur="%.2f" % valeur
                domoticz_idx=str(periph_idx['Plante_Lumiere_Valeur'])
                maj_widget_texte(domoticz_idx,valeur,battery_level)

            if metric == 'soil_moisture':
                domoticz_idx=str(periph_idx['Plante_Humidite_Status'])
                maj_widget_alert(domoticz_idx,status_key,inst_key,battery_level)

                z=data['gauge_values']
                valeur="%.2f" % z['current_value']
                domoticz_idx=str(periph_idx['Plante_Humidite_Valeur'])
                maj_widget_texte(domoticz_idx,valeur,battery_level)

            if metric == 'air_temperature':
                domoticz_idx=str(periph_idx['Plante_Temp_Status'])
                maj_widget_alert(domoticz_idx,status_key,inst_key,battery_level)

                z=data['gauge_values']
                valeur="%.1f" % z['current_value']
                domoticz_idx=str(periph_idx['Plante_Temp_Valeur'])
                maj_widget_texte(domoticz_idx,valeur,battery_level)

            if metric == 'fertilizer':
                domoticz_idx=str(periph_idx['Plante_Engrais_Status'])
                maj_widget_alert(domoticz_idx,status_key,inst_key,battery_level)                

                z=data['gauge_values']
                valeur="%.1f" % z['current_value']
                domoticz_idx=str(periph_idx['Plante_Engrais_Valeur'])
                valeur=str("%.1f" % (float(valeur)*100/5))
                maj_widget_texte(domoticz_idx,valeur,battery_level)
Donc, si je résume :

1/ vous créez :
- quatre widgets "alerter"
- un widget "température" pour la température
- deux ou trois widget "pourcentage' pour la batterie, l'humidité du sol et la quantité d'engrais (le widget batterie est optionnel)
- un widget "luminosité en lux" pour la luminosité

voici la liste ci-dessous (ne prenez en compte que ceux qui sont surlignés en jaune) :
fp2.jpg
fp2.jpg (127.03 Kio) Consulté 9487 fois

2/ vous copiez le code et vous le complétez en suivant les instructions du tuto de Patrice

3/ vous obtiendrez cela :
fp1.jpg
fp1.jpg (112.9 Kio) Consulté 9487 fois
Dernière modification par js-martin le 21 mars 2016, 22:56, modifié 1 fois.
Domotisation de : mes compteurs EDF, solaire, eau / mon alarme / ma Chaudière Viessamnn / mon congel / ma sonnette. Matériels : Pi2 - RFXTrx433e - Zwave+ Aeotec, ampoules Hue - Détecteur et prises Fibaro - Capteurs Oregon - présentation installation => lien
deennoo
Messages : 4036
Inscription : 25 janv. 2015, 02:00

Re: Parrot flower Power

Message par deennoo »

Avec ton script on consulte le flower power en direct via BT ou sur l API dispo ?
De quoi se faire Plaisir et essayer d'aider...
http://www.domo-attitude.fr
patrice
Messages : 1720
Inscription : 22 sept. 2014, 21:51

Re: Parrot flower Power

Message par patrice »

Bonjour
Je réponds car je fus à l'origine du truc : Par l'api chez Sense
A l"epoque seul L'aPI etait documentee , je pense que le BT l'est maintenant
et j'ai lu sur le forum des trucs à ce sujets me semble t'il
Raspberry pi 3, Dongle RfxCom et Zigate +, plugin de pipiche, Volets Roulants profalux, contrôle d'éclairage, détecteurs de présence, alarme incendie, pilotage livebox ...
Objectif : WAF > 1
deennoo
Messages : 4036
Inscription : 25 janv. 2015, 02:00

Message par deennoo »

Je viens de remettre en place mon script de consultation direct par bt, il me manque juste un moyen d'updater le cloud parrot pour bénéficier de leur analyse en retour

Édit : Parrot a publier un outil pour Updater leur cloud depuis une consultation "hors applications Android/IOS" :


https://github.com/Parrot-Developers/FlowerPower-Tools

Dans ce topic il y a le script nodejs que j'utilise pour consulter directement le flower power en BT et non via l'API comme proposé.
Répondre