MQTT or IFTTT?
MQTT⌠they send metrics like temperature or other stuff⌠you can clearly see it using a simple nmap over the irsap host.
Oh sorry - as they support IFTTT, I thought you was referring to it. Good thing they use MQTT, Iâll try to inspect it with Wireshark maybe this way (and maybe learn something new )
Will report back!
While analyzing the traffic on my iPhone using apps that inspect data by faking SSL, I discovered that the application logs in through Amazon Cognito. However, I wasnât able to find a typical link or endpoint where I could input credentials and directly retrieve a token. Despite uncovering the login process, the method to access or intercept the authentication token remains unclear.
Ok so I took some patience and cracked it open, the case has an outer shell (held down with various tabs, very hard to pull) and an inner shell with some Torx screws.
Seems like a custom board, with a Telit GS2200 Wi-Fi module attached.
I see some serial pinouts (J3, J7) but my limited knowledge canât help much with it.
Hereâs a manual about that GS2200M GS2200M S2W Adapter Command Reference Guide and MQTT
As we are mostly Italian, @ilvianez created a small Telegram group to work together. Feel free to join us, ask in DM!
Of course weâll report back here any success
Hi everyone,
Iâve quickly put together a Python script that handles authentication via AWS Cognito using a username and password, and then makes a GraphQL request to fetch device data. The retrieved data is summarized and printed, including device firmware details, temperature and other useful information.
This is a rough initial version, but it could serve as a good starting point for anyone interested in helping us build a more complete integration.
Weâre working on this collaboratively and anyone interested is welcome to join us on Telegram to discuss and contribute!
Hereâs the script:
import requests
from warrant import Cognito
import json
# Configurazione con il tuo User Pool ID, Client ID e regione
USER_POOL_ID = 'eu-west-1_qU4ok6EGG' # Sostituisci con il tuo User Pool ID
CLIENT_ID = '4eg8veup8n831ebokk4ii5uasf' # Sostituisci con il tuo Client ID
REGION = 'eu-west-1' # Sostituisci con la tua regione (esempio: eu-west-1)
USERNAME = 'IRSAPEMAILACCOUNT' # Sostituisci con il tuo username
PASSWORD = 'PASSWORD' # Sostituisci con la tua password
# Funzione per eseguire il login e ottenere l'access token
def login_with_srp(username, password):
try:
# Configurazione del client Cognito con User Pool ID, Client ID, username e regione
u = Cognito(USER_POOL_ID, CLIENT_ID, username=username, user_pool_region=REGION)
# Effettua il login utilizzando SRP
u.authenticate(password=password)
# Ottenere il token di accesso
print("Login effettuato con successo.")
return u.access_token
except Exception as e:
print(f"Errore durante il login: {e}")
return None
# Funzione per eseguire la chiamata GraphQL con l'access token
def make_graphql_call(access_token):
try:
url = 'https://flqpp5xzjzacpfpgkloiiuqizq.appsync-api.eu-west-1.amazonaws.com/graphql'
headers = {
'Authorization': f'Bearer {access_token}',
'Content-Type': 'application/json',
'Host': 'flqpp5xzjzacpfpgkloiiuqizq.appsync-api.eu-west-1.amazonaws.com',
'User-Agent': 'now2/2124 CFNetwork/1568.100.1 Darwin/24.0.0',
'Connection': 'keep-alive',
'Accept': '*/*',
'x-amz-user-agent': 'aws-amplify/3.0.7 react-native',
'Accept-Language': 'it-IT,it;q=0.9'
}
# Corpo della richiesta
graphql_query = {
"operationName": "GetShadow",
"variables": {"envId": "c1d14842-c769-4701-abe3-1986df43f8bd"},
"query": "query GetShadow($envId: ID!) {\n getShadow(envId: $envId) {\n envId\n payload\n __typename\n }\n}\n"
}
# Eseguire la richiesta POST
response = requests.post(url, headers=headers, json=graphql_query)
if response.status_code == 200:
return response.json()
else:
print(f"Errore nella richiesta: {response.status_code}")
print(response.text)
return None
except Exception as e:
print(f"Errore durante la chiamata GraphQL: {e}")
return None
# Funzione per analizzare e stampare i dati
def analyze_and_print_data(response_data):
# Parsing del payload JSON interno
payload = json.loads(response_data['data']['getShadow']['payload'])
# Formattazione dei dati
output = f"""
ID dellâambiente: {payload['id']}
⢠Client ID: {payload['clientId']}
⢠Timestamp: {payload['timestamp']}
⢠Dati del dispositivo âD-Iâ:
⢠Seriale: {payload['state']['desired']['D-I_SRL']}
⢠Firmware: {payload['state']['desired']['D-I_FWV']}
⢠Ultimo aggiornamento: {payload['state']['desired']['D-I_LUP']}
⢠Offset del sensore di temperatura: {payload['state']['desired']['D-I_X_temperatureSensorOffset']}
⢠Indirizzo IP: {payload['state']['desired']['D-I_X_ipAddress']}
⢠Valori VOC e CO2: {payload['state']['desired']['D-I_X_vocValue']}, {payload['state']['desired']['D-I_X_co2Value']}
⢠Finestra aperta rilevata: {payload['state']['desired']['D-I_X_OpenWindowDetected']}
⢠Dati del dispositivo âDfOâ:
⢠Seriale: {payload['state']['desired']['DfO_SRL']}
⢠Firmware: {payload['state']['desired']['DfO_FWV']}
⢠Ultimo aggiornamento: {payload['state']['desired']['DfO_LUP']}
⢠Offset del sensore di temperatura: {payload['state']['desired']['DfO_X_temperatureSensorOffset']}
⢠Indirizzo IP: {payload['state']['desired']['DfO_X_ipAddress']}
⢠Dati del dispositivo âDO4â:
⢠Seriale: {payload['state']['desired']['DO4_SRL']}
⢠Firmware: {payload['state']['desired']['DO4_FWV']}
⢠Ultimo aggiornamento: {payload['state']['desired']['DO4_LUP']}
⢠Offset del sensore di temperatura: {payload['state']['desired']['DO4_X_temperatureSensorOffset']}
⢠Indirizzo IP: {payload['state']['desired']['DO4_X_ipAddress']}
⢠Informazioni aggiuntive sui bagni:
⢠Bagno Padronale: Temperatura attuale: {payload['state']['desired']['Pca_TMP']}
⢠Bagno Piano Primo: Temperatura attuale: {payload['state']['desired']['Pwg_TMP']}
⢠Bagno Piano Terra: Temperatura attuale: {payload['state']['desired']['PTG_TMP']}
⢠Informazioni sul clima esterno:
⢠Temperatura esterna: {payload['state']['desired']['E_WTD']['current']['temperature']}
⢠Umidità esterna: {payload['state']['desired']['E_WTD']['current']['humidity']}%
⢠Previsioni per il giorno:
⢠Alba: {payload['state']['desired']['E_WTD']['dayDetails']['sunrise']}
⢠Tramonto: {payload['state']['desired']['E_WTD']['dayDetails']['sunset']}
⢠Temperature minime: {payload['state']['desired']['E_WTD']['dayDetails']['temperatures']['min']}
⢠Temperature massime: {payload['state']['desired']['E_WTD']['dayDetails']['temperatures']['max']}
⢠Localizzazione:
⢠Città :
⢠Via:
⢠CAP:
⢠Coordinate geografiche: {payload['state']['desired']['E_LOC']['latLon']}
"""
print(output)
# Eseguire il login, la chiamata e l'analisi dei dati
if __name__ == "__main__":
# Ottenere il token di accesso tramite login
token = login_with_srp(USERNAME, PASSWORD)
# Eseguire la chiamata GraphQL con il token aggiornato
if token:
response_data = make_graphql_call(token)
if response_data:
analyze_and_print_data(response_data)
1. Stato di accensione/spegnimento (ENB):
⢠Il parametro ENB è quello che indica se il dispositivo è acceso o spento.
⢠Nei dati inviati, troviamo i campi come:
⢠"Pca_ENB": 1 â Significa che il dispositivo âBagno Padronaleâ è acceso (1 indica acceso, 0 indica spento).
⢠"Pwg_ENB": 0 â Significa che il dispositivo âBagno Piano Primoâ è spento.
⢠"PTG_ENB": 0 â Indica che il dispositivo âBagno Piano Terraâ è spento.
2. Temperatura impostata (TSP):
⢠Il campo TSP (che si trova dentro la sezione state.desired) è quello che rappresenta la temperatura impostata.
⢠Ad esempio:
⢠"Pca_TSP": {"p": {"u": 0, "v": 200, "m": 3, "k": "TEMPORARY"}} â Qui la temperatura impostata per il âBagno Padronaleâ è 200 (devi dividere per 10, quindi 20.0°C).
⢠"Pwg_TSP": {"p": {"u": 0, "v": 200, "m": 3, "k": "TEMPORARY"}} â Anche per il âBagno Piano Primoâ è impostata a 200 (20.0°C).
⢠"PTG_TSP": {"p": {"u": 0, "v": 200, "m": 3, "k": "TEMPORARY"}} â Temperatura impostata per il âBagno Piano Terraâ a 200 (20.0°C).
Hello there,
as promised iâm coming back to you with a further update from IRSAP: sadly thatâs not I was hoping to hear.
See below the exchange with the customer service.
*"Buongiorno Sig. *****,
Dopo confronto con il reparto sviluppo del Sistema Now, mi dispiace informarla che al momento non è prevista unâintegrazione con Home Assistant.
Sono in fase di valutazione lâimplementazione verso altri protocolli, ma non siamo in grado di fornirle ulteriori indicazioni e tempistiche.
Come indicato nelle guide presenti online, è presente unâintegrazione con IFTT. Le riporto il link alle guide dove può trovare le possibili operazioni: https://support.irsapnow.com/hc/it/articles/18313863323921-Integrazione-con-IFTTT"
âŚand my answerâŚ
âLa ringrazio per il gentile riscontro, devo dire che è davvero un peccato: lâintegrazione con Home Assistant o comunque lâutilizzo di protocolli aperti e universali come Matter è qualcosa che è presente ormai in pressochè qualsiasi dispositivo smart in commercio (compresi prodotti cinesi molto low cost), difficile portare avanti il made in italy quando aziende prestigiose come la Vostra non sanno adattarsi a necessitĂ tecnologiche di base.â
Happy to hear tough that someone with the right skills is trying to solve the issue, if you need some beta testers⌠here I am
thanks
ciao
fabio
We are well on our way, the repository will be published here and an ad hoc topic will be created, obviously the issues will be to be included in the repository but we expect to publish soon.
There will be a climate type entity to drive power on, power off (antifreeze mode) and of course temperature setting (in the future the reset of a weekly schedule if there is one) and other sensor type entities with some information (e.g. check open window, filpilote, standby, block manual changes)
Hello Home Assistant community!
Iâm excited to announce the IRSAP Integration for Home Assistant, now available on GitHub! This integration allows you to seamlessly control your IRSAP radiators, enhancing your homeâs heating management.
Key Features:
- Active Scheduling: Manage your radiator schedules effectively.
- Easy Configuration: Simple setup to get you started in no time.
- Recent Updates: The latest version (1.1) includes bug fixes and a domain change for improved compatibility, as requested by the brand.
The integration is currently pending approval for HACS, but you can access the repository here: IRSAP Integration GitHub.
I welcome your feedback and suggestions for further improvements. Thank you for your support, and I look forward to hearing from you!
Best,
Valerio
is there a reason itâs supported only from 2024.9 version or can I change it to older versions? Iâve the august one
Actually it is because we tried with that and not a lower version, you can try it and let us know, so we make the change
Ok, tried with a fork but Iâve the error when I try to add the integration, not from hacs, but the step after, in hass.
âImpossibile caricare il flusso di configurazione: {âmessageâ:âInvalid handler specifiedâ}â
Try taking the files and copying them inside the custom_components folder and then inside irsap-ha
did that, all the files (*.py and manifest.json) inside custom_components/irsap-ha but same issue
Do you see anything in the logs?
Yes, in config_entries.py:2871
Error occurred loading flow for integration irsap_ha: No module named âwarrantâ
I saw that Cognito is imported from warrant, so maybe some dependencies is missing? Do I need some additional module? For further debug, Iâm using the standalone hass, not the os. Could be that?
I tried to manual install warrant, now the error is
Error occurred loading flow for integration irsap_ha: cannot import name âMappingâ from âcollectionsâ (/usr/local/lib/python3.12/collections/init.py)