Mes passions, le boulots, mes coups de gueule...




Détecteur de CO2 modèle 2CO3TB : Récupérer les données du capteur sur un Raspberry Pi avec gatttool

Catégories : Domotique, Geek, Informatique, Linux, Raspberry Pi · par 16 Déc 2021

Introduction

Avec la pandémie qui persiste, il est recommandé d’utiliser un appareil de mesure du CO2 pour déterminer la qualité de l’air et son bon renouvellement. Je me suis donc mis à la recherche d’un capteur qui réponde à ces besoins et, tant qu’à faire, essayer d’en trouver un en Bluetooth pour compléter ma collection et relever les données à intervalles réguliers.

Voici les précédents articles qui parlent de mes capteurs :

Présentation du capteur

Mon choix s’est porté sur un appareil « no name » de type 2CO3TB.

Ses dimensions sont : 70mm x 89mm x 35mm et il mesure :

  • Le monoxyde de carbone
  • Le formaldéhyde
  • Les composés organiques volatiles (COV)
  • La température
  • L’humidité

Vous pouvez le retrouver sur Amazon pour un peu plus de 30€ : https://amzn.to/3p0KyGN

Il est muni d’un port micro-USB pour l’alimenter et recharger la batterie amovible (fournie) de 3.7V, de type 18650 et de 1500mAh. La batterie n’est pas nécessaire s’il est alimenté en USB. Un câble d’un mètre est livré dans la boite. L’autonomie sur batterie est de quelques heures.

L’écran affiche toutes les informations utiles en couleur. Il n’est pas de grande qualité et offre un faible angle de vision. Son affichage est rafraichi toutes les secondes.

Un seul et unique bouton permet de :

  • Allumer ou éteindre le capteur.
  • Sélectionner l’affichage en Celsius ou Fahrenheit.
  • Activer ou désactiver l’alarme sonore de dépassement de 1000ppm de CO2.

Importer les données

Installation du Bluetooth

En principe, si vous utilisez un RPi avec Jessie, Stretch, Buster ou Bullseye, les outils gatttool et hcitool que nous allons utiliser plus loin devraient déjà être installés.

Si ce n’est pas le cas, je vous renvoie vers cet article : https://fr.tipsandtrics.com

$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get install bluetooth bluez-utils blueman bluez

Déterminer l’adresse MAC du capteur 2CO3TB

Pour déterminer cette adresse, nous allons utiliser l’outil hcitool.

$ sudo hcitool lescan

Ce qui devrait nous retourner la liste des périphérique Bluetooth LE (Low Energy) qui se trouvent à proximité :

LE Scan ...
1F:6B:29:20:B3:B7 (unknown)
04:F7:A5:C7:2B:93 (unknown)
B6:6B:04:5C:82:B8 XS-82B8
B6:6B:04:5C:82:B8 XS-82B8
59:CE:9B:42:D4:EB (unknown)
FC:E4:1D:88:BD:59 FCE41D88
FC:E4:1D:88:BD:59 (unknown)
6E:A7:D6:8F:70:26 (unknown)
C4:7C:8D:62:83:C9 (unknown)
C4:7C:8D:62:83:C9 Flower care
EA:80:2F:03:5B:70 (unknown)
C4:F7:3A:21:8A:6D (unknown)
BA:95:9F:9F:58:00 A06AMJ
BA:95:9F:9F:58:00 (unknown)
D9:6A:EB:12:C1:1A (unknown)
F4:0F:24:21:C3:6A (unknown)
90:03:B7:E7:DC:6C Parrot
F4:0F:24:21:C3:6A (unknown)
4F:BE:C3:52:33:73 (unknown)

Le capteur 2CO3TB a donc la MAC Address suivante : B6:6B:04:5C:82:B8

Importer les données avec gatttool

gatttool en mode interactif

Premiers pas

Pour commencer, nous allons nous connecter en mode interactif ( -I ) avec cette commande :

$ sudo gatttool --device=B6:6B:04:5C:82:B8 -I

Une fois démarré, l’outil est prêt à recevoir des commandes et ceci devrait apparaitre à l’écran :

[B6:6B:04:5C:82:B8][LE]>

On va se connecter avec cette commande :

connect

L’outil devrait répondre quelque chose comme ceci et l’adresse MAC devrait passer en bleu lorsque la connexion est établie :

[B6:6B:04:5C:82:B8][LE]> connect
Attempting to connect to B6:6B:04:5C:82:B8
Connection successful
Notification handle = 0x000c value: 23 06 10 04 00 dc 00 30 5d 
Notification handle = 0x000c value: 23 08 10 04 01 9f 00 0c 00 03 07 
Notification handle = 0x000c value: 23 06 10 04 00 dc 00 30 5d 
Notification handle = 0x000c value: 23 08 10 04 01 9f 00 0c 00 03 07 
Notification handle = 0x000c value: 23 06 10 04 00 dc 00 30 5d 
Notification handle = 0x000c value: 23 08 10 04 01 9f 00 0c 00 03 07 
Notification handle = 0x000c value: 23 06 10 04 00 dc 00 30 5d 
Notification handle = 0x000c value: 23 08 10 04 01 9f 00 0c 00 03 07 
Notification handle = 0x000c value: 23 06 10 04 00 dc 00 30 5d 
Notification handle = 0x000c value: 23 08 10 04 01 9f 00 0c 00 03 07 
Notification handle = 0x000c value: 23 06 10 04 00 dc 00 30 5d 
Notification handle = 0x000c value: 23 08 10 04 01 9f 00 0c 00 03 07 

À intervalles réguliers de quelques secondes, on voit s’ajouter des lignes de « Notification handle« . Ce sont les données du capteur qui sont renvoyées sous forme de notifications.

Dans le bouquin « Inside bluetooth low energy – Second Edition » de Naresh Gupta aux éditions Artech House, à la page 323 (https://books.google.be/, l’auteur explique le principe des notifications ATT (Attribute Protocol).

Le serveur envoie des notifications au client sans attendre d’accusé de réception. Ces notifications comprennent un descripteur et une valeur d’attribut.

Identification des UUID des handles

La commande char-desc va explorer les descripteurs de caractéristiques et nous retourner tous les handle disponibles avec leurs numéros et leurs uuid :

[B6:6B:04:5C:82:B8][LE]> char-desc
handle: 0x0001, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x0002, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0003, uuid: 00002a00-0000-1000-8000-00805f9b34fb
handle: 0x0004, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x0005, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0006, uuid: 00002a05-0000-1000-8000-00805f9b34fb
handle: 0x0007, uuid: 00002902-0000-1000-8000-00805f9b34fb
handle: 0x0008, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x0009, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x000a, uuid: 0000c762-0000-1000-8000-00805f9b34fb
handle: 0x000b, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x000c, uuid: 0000c761-0000-1000-8000-00805f9b34fb
handle: 0x000d, uuid: 00002902-0000-1000-8000-00805f9b34fb
handle: 0x000e, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x000f, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0010, uuid: f000ffc1-0451-4000-b000-000000000000
handle: 0x0011, uuid: 00002902-0000-1000-8000-00805f9b34fb
handle: 0x0012, uuid: 00002901-0000-1000-8000-00805f9b34fb
handle: 0x0013, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0014, uuid: f000ffc2-0451-4000-b000-000000000000
handle: 0x0015, uuid: 00002902-0000-1000-8000-00805f9b34fb
handle: 0x0016, uuid: 00002901-0000-1000-8000-00805f9b34fb

Allons télécharger la liste des UUID standardisés du Bluetooth : https://www.bluetooth.com/.

Malheureusement, l’UUID du handle 0x000c : 0000c761 ne correspond à rien de standardisé dans la liste.

Le seul qui peut nous intéresser est le 0x0003 : 00002a00 qui correspond au Device Name. Les autres UUID ne figurent pas dans la liste.

Lire un handle

Pour lire le contenu d’un handle, on utilise la commande char-read-hnd suivie du n° du handle qui nous intéresse :

[B6:6B:04:5C:82:B8][LE]> char-read-hnd 0x0003
Characteristic value/descriptor: 58 53 2d 31 32 33 34 00

Convertir un handle

Pour convertir les données, il suffit d’utiliser la table ASCII :

Dans notre cas :

58532d3132333400
XS1234(NULL)

Nous obtenons : XS-1234

gatttool en ligne de commande

Lire un handle

Pour lire un handle en ligne de commande, nous utiliserons :

$ sudo gatttool --device=B6:6B:04:5C:82:B8 --char-read -a 0x03
Characteristic value/descriptor: 58 53 2d 31 32 33 34 00

Écouter les Notification handle

Dans le cas qui nous occupe, pour lire les données, il n’est pas possible de lire directement le handle 0c.

Voici les valeurs qui seraient retournées :

$ sudo gatttool --device=B6:6B:04:5C:82:B8 --char-read -a 0x0c
Characteristic value/descriptor: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 

Pour obtenir les données, nous allons inscrire une valeur arbitraire dans le handle 31 qui n’existe pas et écouter tout ce qui se passe ensuite ( --listen ):

$ sudo gatttool --device=B6:6B:04:5C:82:B8 --char-write-req --handle=0x0031 --value=0100 --listen
Characteristic Write Request failed: Invalid handle
Notification handle = 0x000c value: 23 06 10 04 00 e9 00 2c 64 
Notification handle = 0x000c value: 23 08 10 04 01 a5 00 0d 00 04 0f 
Notification handle = 0x000c value: 23 06 10 04 00 e9 00 2c 64 
Notification handle = 0x000c value: 23 08 10 04 01 a2 00 0d 00 03 13 
Notification handle = 0x000c value: 23 06 10 04 00 e9 00 2c 64 
Notification handle = 0x000c value: 23 08 10 04 01 a2 00 0e 00 03 12 
Notification handle = 0x000c value: 23 06 10 04 00 e9 00 2c 64 
Notification handle = 0x000c value: 23 08 10 04 01 a5 00 0e 00 04 0e 
Notification handle = 0x000c value: 23 06 10 04 00 e9 00 2c 64 
Notification handle = 0x000c value: 23 08 10 04 01 a5 00 0d 00 04 0f 
Notification handle = 0x000c value: 23 06 10 04 00 e9 00 2c 64 
^C

Une fois la tentative d’écriture échouée, la commande va continuer à recevoir les notifications du boîtier jusqu’à interruption avec [ctrl] C.

Pour éviter ce blocage, on va restreindre le temps d’exécution à 5 secondes ( timeout 5 ).

Dans les données, on remarque que la commande nous retourne successivement 2 lignes différentes. On va donc ne récupérer que 2 lignes de ces notifications ( grep ) :

sudo timeout 5 gatttool --device=B6:6B:04:5C:82:B8 --char-write-req --handle=0x0031 --value=0100 --listen | grep --max-count=2 "Notification handle"

Et voici la réponse retournée après 15 secondes :

Notification handle = 0x000c value: 23 08 10 04 01 9b 00 06 00 04 fe
Notification handle = 0x000c value: 23 06 10 04 00 e9 00 2c 64

Exploitation des données

Dans les données, on s’aperçoit que certains octets gardent toujours la même valeur alors que d’autres varient.

Notification handle = 0x000c value: 23 08 10 04 01 9b 00 0a 00 0d fe
Notification handle = 0x000c value: 23 06 10 04 00 e9 00 2c 64

En rouge, les octets fixes et en vert, ceux qui nous intéressent.

Voici comment se structurent les données :

CO2TVOCHCHO
019b000a000d
4111013
TempératureHumidité
00e9002c
23344

Les octets sont regroupés par deux et convertis d’hexadécimal vers décimal : 019b => 411

Il faut diviser la température par 10 : 00e9 => 233 => 23,3°C

Les taux TVOC et HCHO doivent être divisés par 1000 : 000a => 10 => 0,010 mg/m³ et 000d => 13 => 0,013 mg/m³

Script

Voici un petit script qui va nous retourner toutes les valeurs utiles du capteur :

#!/bin/bash

# Vérifie que l'on est en Root
if [[ $EUID -ne 0 ]];
then
	echo "Ce script doit être exécuté avec les privilèges administrateur"
   	exit 1
fi

MACadd="B6:6B:04:5C:82:B8"

hciconfig hci0 down
hciconfig hci0 up


hnd03=$(gatttool --device=$MACadd --char-read -a 0x03)
#Characteristic value/descriptor: 58 53 2d 31 32 33 34 00
name=$(echo "$hnd03" | cut -c34-57 | xxd -r -p | tr -d '\0')
echo "Nom : $name"
echo

data=$((timeout 5 gatttool --device=$MACadd --char-write-req --handle=0x0031 --value=0100 --listen | grep --max-count=2 "Notification handle") 2>/dev/null)

data1=$(echo "$data" | grep --max-count=1 "Notification handle = 0x000c value: 23 08 10 04")
data2=$(echo "$data" | grep --max-count=1 "Notification handle = 0x000c value: 23 06 10 04")

co2=${data1:48:2}${data1:51:2}
co2=$((16#$co2))
echo "CO2 : $co2 ppm"

tvoc=${data1:54:2}${data1:57:2}
tvoc=$((16#$tvoc))
tvoc=$(echo "scale=3;$tvoc/1000" | bc | sed 's/^\./0./')
echo "TVOC : $tvoc mg/m³"

hcho=${data1:60:2}${data1:63:2}
hcho=$((16#$hcho))
hcho=$(echo "scale=3;$hcho/1000" | bc | sed 's/^\./0./')
echo "HCHO : $hcho mg/m³"

temp=${data2:48:2}${data2:51:2}
temp=$((16#$temp))
temp=$(echo "scale=3;$temp/10" | bc | sed 's/^\./0./')
echo "Température : $temp °C"

hum=${data2:54:2}${data2:57:2}
hum=$((16#$hum))
echo "Humidité : $hum %"

Edit 09/01/2022 : Les modifications proposées par Francesco Talamona dans les commentaires ont été implémentées au script.

Voici ce que le script devrait retourner comme résultat :

Nom : XS-1234

Characteristic Write Request failed: Invalid handle
CO2 : 418 ppm
TVOC : 0.013 mg/m³
HCHO : 0.003 mg/m³
Température : 23.300 °C
Humidité : 44 %

(3) comments

Francesco Talamona
4 mois ago · Répondre

Awesome! I was playing around with the same device and this page helped me a lot.
I modified two lines in the script in order to suppress bash warning and the error message:

name=$(echo « $hnd03 » | cut -c34-57 | xxd -r -p | tr -d ‘\0’)

data=$((timeout 5 gatttool –device=$MACadd –char-write-req –handle=0x0031 –value=0100 –listen | grep –max-count=2 « Notification handle ») 2>/dev/null)

Furthermore there’s no need to reset hciconfig, so I’m not running the script as root.

    fanjoe
    4 mois ago · Répondre

    Thanks for your comment and the script corrections.

Guillaume
3 mois ago · Répondre

Hello

Pour fiabiliser la prise de mesure, voici un bout de code

while [ -z « $data » ]
do
data=$((timeout 5 gatttool –device=$MACadd –char-write-req –handle=0x0031 –value=0100 –listen | grep –max-count=2 « Notification handle ») 2>/dev/null)

(( compteur_while = compteur_while + 1 ))

if [ « $compteur_while » -gt 20 ]
then
exit 0
fi
done

Merci pour le script

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.