# Connecter une chatiere Sure Petcare a Gladys via MQTT

**URL:** <https://community.gladysassistant.com/t/connecter-une-chatiere-sure-petcare-a-gladys-via-mqtt/10146>\
**Category:** Tutoriels\
**Tags:** mqtt\
**Created:** [Mars 21, 2026, 12:32 UTC](https://community.gladysassistant.com/t/connecter-une-chatiere-sure-petcare-a-gladys-via-mqtt/10146 "2026-03-21T12:32:26Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![David-Digitis](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/david-digitis/32/20537_2.png) [@David-Digitis](https://community.gladysassistant.com/u/David-Digitis)\
**Post date:** [Mars 21, 2026, 12:32 UTC](https://community.gladysassistant.com/t/connecter-une-chatiere-sure-petcare-a-gladys-via-mqtt/10146/1 "2026-03-21T12:32:26Z")

</div>

## **Le contexte**

J’ai migre toute ma domotique de Home Assistant vers Gladys. Un de mes sacrifices : la chatiere connectee **Sure Petcare** (Cat Flap Connect) qui n’a pas d’integration native dans Gladys.

Sur Home Assistant, l’integration Sure Petcare remontait la position du chat (dedans/dehors), la batterie de la chatiere, l’etat du verrou, etc. En passant sur Gladys, j’ai perdu tout ca.

La solution ? Le meme principe que pour mes bandeaux LED Magic Home : un **bridge MQTT** custom qui fait le lien entre l’API cloud Sure Petcare et Gladys.

Le bridge a ete developpe avec Claude Code (l’agent CLI d’Anthropic). Je ne m’en cache pas, ca fait partie de ma stack maintenant et ca m’a fait gagner un temps considerable sur la partie recherche API + code.

**Update**  
Repos Github dispo :

> **[GitHub - david-digitis/sure-petcare-bridge: Sure Petcare MQTT bridge for Gladys Assistant —...](https://github.com/david-digitis/sure-petcare-bridge)**
>
> Sure Petcare MQTT bridge for Gladys Assistant — connects cat flaps and pet doors to Gladys via MQTT

## **L’architecture**

```auto
Sure Petcare Cloud <--HTTPS--> sure-petcare-bridge (Python) <--MQTT--> Mosquitto <--> Gladys

```

Un seul container Python (~50 Mo RAM) qui :

1. **Poll** l’API Sure Petcare toutes les 60 secondes via la librairie [surepy](https://github.com/benleb/surepy) (la meme que Home Assistant utilisait)

2. **Publie sur MQTT** l’etat vers Gladys : position du chat, batterie de la chatiere

3. **Log intelligent** : n’affiche que les changements d’etat (pas de spam dans les logs)

## **Ce qu’il faut**

- Gladys avec l’integration **MQTT** configuree et connectee a un broker **Mosquitto**

- Un compte **Sure Petcare** (celui de l’app smartphone)

- Une chatiere **Cat Flap Connect** ou **Pet Door Connect** avec son **Hub** connecte au WiFi

- **Docker** sur votre serveur

## **Etape 1 : Preparer les fichiers**

Creez un dossier pour le bridge, par exemple `/volume1/docker/sure-petcare-bridge/`.

**requirements.txt** :

```auto
surepy>=0.9.0
paho-mqtt>=2.0

```

**Dockerfile** :

```auto
FROM python:3.12-slim

WORKDIR /app

RUN apt-get update && \
    apt-get install -y --no-install-recommends gcc libc6-dev && \
    rm -rf /var/lib/apt/lists/*

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

RUN apt-get purge -y gcc libc6-dev && apt-get autoremove -y

COPY bridge.py .

CMD ["python", "-u", "bridge.py"]

```

**bridge.py** :

```auto
#!/usr/bin/env python3
"""
Sure Petcare MQTT Bridge for Gladys Assistant v1.0

Polls Sure Petcare cloud API via surepy and publishes pet/device state
to Gladys via MQTT topics.

Environment variables:
  SUREPETCARE_EMAIL (required)
  SUREPETCARE_PASSWORD (required)
  MQTT_HOST (default: localhost)
  MQTT_PORT (default: 1883)
  POLL_INTERVAL (default: 60, seconds)
  LOG_LEVEL (default: INFO)
"""

import os
import sys
import signal
import asyncio
import logging

import paho.mqtt.client as paho
from surepy import Surepy
from surepy.enums import EntityType

# --- Configuration ---

EMAIL = os.environ.get('SUREPETCARE_EMAIL', '')
PASSWORD = os.environ.get('SUREPETCARE_PASSWORD', '')
MQTT_HOST = os.environ.get('MQTT_HOST', 'localhost')
MQTT_PORT = int(os.environ.get('MQTT_PORT', '1883'))
POLL_INTERVAL = int(os.environ.get('POLL_INTERVAL', '60'))
LOG_LEVEL = os.environ.get('LOG_LEVEL', 'INFO')

if not EMAIL or not PASSWORD:
    sys.exit('[FATAL] SUREPETCARE_EMAIL et SUREPETCARE_PASSWORD requis')

logging.basicConfig(
    level=getattr(logging, LOG_LEVEL.upper(), logging.INFO),
    format='%(asctime)s [%(name)s] %(message)s',
    datefmt='%H:%M:%S',
)
log = logging.getLogger('sure-bridge')

def slugify(name):
    """Nom -> slug compatible external_id Gladys."""
    s = name.lower().replace(' ', '-').replace("'", '').replace('"', '')
    for old, new in {'e': 'e', 'e': 'e', 'e': 'e', 'a': 'a', 'u': 'u', 'c': 'c'}.items():
        s = s.replace(old, new)
    return s

def publish(client, device_ext, feature_suffix, value):
    """Publie une valeur sur le topic MQTT Gladys."""
    feat_ext = f'{device_ext}:{feature_suffix}'
    topic = f'gladys/master/device/{device_ext}/feature/{feat_ext}/state'
    client.publish(topic, str(value))

_prev_state = {}

def state_changed(key, **kwargs):
    prev = _prev_state.get(key)
    if prev != kwargs:
        _prev_state[key] = kwargs
        return True
    return False

async def run():
    # MQTT
    try:
        mqtt = paho.Client(paho.CallbackAPIVersion.VERSION2, client_id='sure-petcare-bridge')
    except (AttributeError, TypeError):
        mqtt = paho.Client(client_id='sure-petcare-bridge')

    mqtt.on_connect = lambda *_: log.info(f'MQTT connecte ({MQTT_HOST}:{MQTT_PORT})')
    mqtt.on_disconnect = lambda *_: log.warning('MQTT deconnecte, reconnexion auto...')
    mqtt.reconnect_delay_set(min_delay=1, max_delay=30)

    try:
        mqtt.connect(MQTT_HOST, MQTT_PORT)
    except Exception as e:
        sys.exit(f'[FATAL] MQTT connexion impossible: {e}')

    mqtt.loop_start()

    # Sure Petcare
    surepy = Surepy(email=EMAIL, password=PASSWORD)

    log.info('Sure Petcare Bridge v1.0 demarre')
    log.info(f'Compte: {EMAIL} | poll: {POLL_INTERVAL}s')

    first_run = True

    try:
        while True:
            try:
                entities = await surepy.get_entities()

                if first_run:
                    pets = [e for e in entities.values() if e.type == EntityType.PET]
                    flaps = [e for e in entities.values()
                             if e.type in (EntityType.CAT_FLAP, EntityType.PET_FLAP)]
                    hubs = [e for e in entities.values() if e.type == EntityType.HUB]
                    log.info(f'Decouvert: {len(pets)} animal(aux), {len(flaps)} chatiere(s), {len(hubs)} hub(s)')
                    for p in pets:
                        log.info(f' Animal: {p.name} (id={p.id})')
                    for f in flaps:
                        log.info(f' Chatiere: {f.name} (id={f.id})')
                    first_run = False

                # Pets
                for entity in entities.values():
                    if entity.type != EntityType.PET:
                        continue
                    slug = slugify(entity.name)
                    ext_id = f'mqtt:maison:pet-{slug}'
                    at_home = 1 if entity.at_home else 0
                    publish(mqtt, ext_id, 'presence', at_home)

                    if state_changed(f'pet-{entity.id}', at_home=at_home):
                        loc = 'dedans' if at_home else 'dehors'
                        log.info(f'[PET] {entity.name}: {loc}')

                # Flaps
                for entity in entities.values():
                    if entity.type not in (EntityType.CAT_FLAP, EntityType.PET_FLAP):
                        continue
                    slug = slugify(entity.name)
                    ext_id = f'mqtt:maison:chatiere-{slug}'

                    battery = getattr(entity, 'battery_level', None)
                    if battery is not None:
                        publish(mqtt, ext_id, 'battery', battery)

                    lock_state = getattr(entity, 'state', None)
                    lock_label = str(lock_state) if lock_state is not None else '?'

                    if state_changed(f'flap-{entity.id}', battery=battery, lock=lock_label):
                        log.info(f'[FLAP] {entity.name}: batterie={battery}% verrou={lock_label}')

            except Exception as e:
                log.error(f'Erreur poll: {e}')

            await asyncio.sleep(POLL_INTERVAL)

    finally:
        mqtt.loop_stop()
        mqtt.disconnect()

def main():
    signal.signal(signal.SIGTERM, lambda *_: sys.exit(0))
    try:
        asyncio.run(run())
    except (KeyboardInterrupt, SystemExit):
        log.info('Arret.')

if __name__ == ' __main__':
    main()

```

## **Etape 2 : Builder et lancer**

```auto
# Build l'image
docker build -t sure-petcare-bridge /chemin/vers/sure-petcare-bridge/

# Lancer le container
docker run -d \
  --name sure-petcare-bridge \
  --network host \
  --restart unless-stopped \
  -e SUREPETCARE_EMAIL=votre@email.com \
  -e SUREPETCARE_PASSWORD=votre_mot_de_passe \
  -e MQTT_HOST=localhost \
  -e MQTT_PORT=1883 \
  -e POLL_INTERVAL=60 \
  sure-petcare-bridge:latest

```

> **Securite** : ne mettez jamais vos credentials en dur dans le code. Toujours en variables d’environnement.

### **Verifier les logs**

```auto
docker logs sure-petcare-bridge

```

Vous devriez voir :

```auto
12:15:21 [sure-bridge] MQTT connecte (localhost:1883)
12:15:21 [sure-bridge] Sure Petcare Bridge v1.0 demarre
12:15:21 [sure-bridge] Compte: votre@email.com | poll: 60s
12:15:23 [sure-bridge] Decouvert: 1 animal(aux), 1 chatiere(s), 1 hub(s)
12:15:23 [sure-bridge] Animal: Arwen (id=12345)
12:15:23 [sure-bridge] Chatiere: CatDoor (id=67890)
12:15:23 [sure-bridge] [PET] Arwen: dedans
12:15:23 [sure-bridge] [FLAP] CatDoor: batterie=51% verrou=Unlocked

```

> Le warning `404` sur `/api/report/household/` est normal — c’est un endpoint optionnel de l’API Sure Petcare que surepy tente d’appeler. Ca n’affecte rien.

## **Etape 3 : Creer les devices MQTT dans Gladys**

### **Device 1 — Votre chat**

Allez dans **Integrations → MQTT → Appareils → Nouveau +**

| Champ | Valeur |
| --- | --- |
| Nom | `Arwen` (ou le nom de votre chat) |
| ID externe | `mqtt:maison:pet-arwen` |
| Piece | (la ou votre chat traine le plus) |

**Feature a ajouter :**

| Champ | Valeur |
| --- | --- |
| Nom | `Presence` |
| ID externe | `mqtt:maison:pet-arwen:presence` |
| Categorie | Capteur de presence |
| Type | Binaire |
| Est-ce un capteur ? | **Oui** |
| Min | 0 |
| Max | 1 |

> **Convention de nommage** : l’ID externe du device et de la feature doivent correspondre exactement a ce que le bridge publie. Le format est `mqtt:maison:pet-{nom-en-minuscules}`. Si votre chat s’appelle « Moustache », ca donnera `mqtt:maison:pet-moustache`.

### **Device 2 — La chatiere**

| Champ | Valeur |
| --- | --- |
| Nom | `Chatiere` |
| ID externe | `mqtt:maison:chatiere-catdoor` |
| Piece | (la ou se trouve la chatiere) |

**Feature a ajouter :**

| Champ | Valeur |
| --- | --- |
| Nom | `Batterie` |
| ID externe | `mqtt:maison:chatiere-catdoor:battery` |
| Categorie | Batterie |
| Type | Entier |
| Est-ce un capteur ? | **Oui** |
| Min | 0 |
| Max | 100 |
| Unite | % |

> **Astuce** : regardez les logs du bridge au premier demarrage pour trouver les bons slugs. Le bridge vous affiche le nom de chaque animal et chatiere detectes.

## **Etape 4 : Verifier dans le dashboard**

Ajoutez les widgets sur votre dashboard Gladys :

- Un widget avec la feature « Presence » du chat — affichera 1 (dedans) ou 0 (dehors)

- Un widget « Jauge » pour la batterie de la chatiere

Le bridge poll toutes les 60 secondes. Quand votre chat passe la chatiere, la valeur change au prochain cycle de poll.

## **Comment ca marche**

### **Le flux de donnees**

1. Votre chat passe la chatiere

2. La chatiere detecte la puce (ou le tag RFID) et envoie l’info au Hub Sure Petcare

3. Le Hub transmet au cloud Sure Petcare

4. Le bridge poll l’API cloud via **surepy** (la meme librairie que Home Assistant utilisait)

5. Le bridge publie le nouvel etat sur MQTT : `gladys/master/device/mqtt:maison:pet-arwen/feature/mqtt:maison:pet-arwen:presence/state` → `0` (dehors)

6. Gladys recoit le message et met a jour le dashboard

### **Pourquoi du cloud polling ?**

Sure Petcare n’expose pas d’API locale. Tout passe par leur cloud. C’est la meme limitation qu’on avait sur Home Assistant. Si les serveurs Sure Petcare tombent, plus de remontee d’info (mais l’app smartphone sera aussi HS).

Le polling a 60 secondes est un bon compromis : assez rapide pour savoir ou est le chat, pas assez agressif pour se faire rate-limit par l’API.

### **Le cache de changement**

Le bridge ne spamme pas les logs. Il garde en memoire le dernier etat et ne log que quand quelque chose change. Les messages MQTT sont toujours publies (pour que Gladys ait toujours la derniere valeur), mais les logs restent propres.

## **Appareils compatibles**

Le bridge detecte automatiquement tous les appareils de votre compte Sure Petcare :

- **Cat Flap Connect** (chatiere a puce)

- **Pet Door Connect** (porte pour animaux)

- **Hub** (passerelle WiFi)

- **Feeder Connect** / **Felaqua** (gamelle/fontaine — pas encore expose dans le bridge mais facile a ajouter)

Si vous avez plusieurs chats, le bridge creera un topic MQTT par animal. Il suffit de creer un device Gladys par chat.

## **Pourquoi MQTT et pas Matter / Matterbridge ?**

On a aussi un plugin Matterbridge custom pour nos bandeaux LED Magic Home, donc la question s’est posee. On a etudie la piste serieusement avant de partir sur MQTT. Voila pourquoi on n’a pas retenu Matter pour la chatiere :

Sur les 3 infos qu’on voulait remonter, voici ce que Matter supporte cote Gladys aujourd’hui :

| Besoin | Cluster Matter | Supporte par Gladys ? |
| --- | --- | --- |
| Chat dedans/dehors | `BooleanState` (ContactSensor) | Oui — lu comme un binaire |
| Batterie | `PowerSource` | **Non** — pas encore mappe dans Gladys |
| Dernier passage | aucun equivalent Matter | Non applicable |

En gros, **1 feature sur 3** passait par Matter. La batterie aurait necessite que Gladys implemente le cluster `PowerSource` (c’est standard, ca viendra probablement), et le « dernier passage » n’a tout simplement pas d’equivalent dans le protocole Matter.

Du coup, faire un hybride Matterbridge + MQTT pour compenser les manques, c’etait du bricolage pour pas grand-chose. Le bridge MQTT pur couvre 100% du besoin des le premier jour, sans attendre que des features soient ajoutees cote Gladys ou cote Matter.

Et soyons honnetes : pour du cloud polling a 60 secondes sur une chatiere, Matter n’apporte aucun avantage. Matter est fait pour du controle local temps reel — la c’est juste de la remontee de capteurs depuis un cloud tiers.

## **Limitations**

- **Cloud only** : pas de controle local, dependance aux serveurs Sure Petcare

- **Latence** : entre 0 et 60 secondes selon le moment du poll (configurable via `POLL_INTERVAL`)

- **Lecture seule** : le bridge ne gere pas (encore) le verrouillage/deverrouillage de la chatiere depuis Gladys. C’est techniquement possible avec surepy, si ca interesse du monde je peux ajouter la feature

- **Pas de dernier passage** : Gladys n’a pas de feature « timestamp » native. Par contre, la feature presence dans Gladys enregistre quand la valeur a change — c’est de fait votre « dernier passage »

## **Stack technique**

- **Python 3.12** (Docker slim)

- **surepy** v0.9.0 — librairie Python pour l’API Sure Petcare (la meme que Home Assistant)

- **paho-mqtt** v2.x — client MQTT

- **~50 Mo RAM** en fonctionnement

* * *

Teste avec succes sur un NAS Synology DS1520+ avec Gladys v4, Mosquitto, et une Cat Flap Connect + Hub Sure Petcare.

Si vous avez des questions ou des ameliorations a suggerer, n’hesitez pas !

---

<div class="post-metadata">

**Author:** ![David-Digitis](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/david-digitis/32/20537_2.png) [@David-Digitis](https://community.gladysassistant.com/u/David-Digitis)\
**Post date:** [Mars 21, 2026, 12:33 UTC](https://community.gladysassistant.com/t/connecter-une-chatiere-sure-petcare-a-gladys-via-mqtt/10146/2 "2026-03-21T12:33:08Z")

</div>

![image](https://gladys-assistant-community.b-cdn.net/uploads/default/original/3X/f/7/f72437c8d928ac235516cc573d5c39bdcba03381.png)

---

<div class="post-metadata">

**Author:** ![mutmut](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/mutmut/32/14064_2.png) [@mutmut](https://community.gladysassistant.com/u/mutmut)\
**Post date:** [Mars 21, 2026, 5:31 UTC](https://community.gladysassistant.com/t/connecter-une-chatiere-sure-petcare-a-gladys-via-mqtt/10146/3 "2026-03-21T17:31:14Z")

</div>

Au taquet @David-Digitis !  
Bravo pour ce tuto aux petits oignons 👌  
Bon, je n’en aurai pas besoin car pas de chat ni chatière 🤣

Petite question : comme tu as fait le tuto de tes LEDs en node.js, pourquoi ne pas avoir continuer et être passé sur python ?  
Je pose la question car Gladys est en js et si un jour il y a une intégration, ce serait d’autant plus simple d’utiliser tel quel (ou presque) que de devoir convertir.

Et je me posais la question sur un repo github où tu mettrais directement le code et une image docker (et utiliser [ghcr.io](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-docker-registry) en créant un `package`) ?

J’ai un syno et j’avais remarqué que tu en avais aussi un dès que tu as mis `/volume1/docker/...`.  
Pour les non initiés, ce n’est pas forcément le plus simple de créer les fichiers avec le code (pyhton, js, etc.) sur une plateforme type syno ou autre.Par contre lancer juste une commande docker ça me parait plus simple.  
Tu penses que ça pourrait être bien pour tes dev ?

---

<div class="post-metadata">

**Author:** ![David-Digitis](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/david-digitis/32/20537_2.png) [@David-Digitis](https://community.gladysassistant.com/u/David-Digitis)\
**Post date:** [Mars 21, 2026, 6:03 UTC](https://community.gladysassistant.com/t/connecter-une-chatiere-sure-petcare-a-gladys-via-mqtt/10146/4 "2026-03-21T18:03:43Z")

</div>

Hello 😉

En vrai, quand tu es bien organisé / formé avec les IA argentiques, tu peux faire beaucoup de choses très bien et très vite. Je n’ai pas beaucoup de mérite, hormis avoir les idées d’architecture.

Pour le langage utilisé, c’est tout simplement parce que nous utilisons une librairie existante. La même utilisée par HA.

Pendant que je t’écris cette réponse Claude est en train de faire un repo sur mon GitHub 😆

---

<div class="post-metadata">

**Author:** ![David-Digitis](https://gladys-assistant-community.b-cdn.net/user_avatar/community.gladysassistant.com/david-digitis/32/20537_2.png) [@David-Digitis](https://community.gladysassistant.com/u/David-Digitis)\
**Post date:** [Mars 21, 2026, 6:11 UTC](https://community.gladysassistant.com/t/connecter-une-chatiere-sure-petcare-a-gladys-via-mqtt/10146/5 "2026-03-21T18:11:38Z")

</div>

> **[GitHub - david-digitis/sure-petcare-bridge: Sure Petcare MQTT bridge for Gladys Assistant —...](https://github.com/david-digitis/sure-petcare-bridge)**
>
> Sure Petcare MQTT bridge for Gladys Assistant — connects cat flaps and pet doors to Gladys via MQTT
