143 lines
5.5 KiB
TypeScript
143 lines
5.5 KiB
TypeScript
import axios, { AxiosError } from 'axios';
|
|
import { HaArea, HaEntity } from '@/types/types';
|
|
|
|
// CONFIGURAZIONE
|
|
const HA_API_URL = process.env.EXPO_PUBLIC_HA_API_URL;
|
|
const HA_TOKEN = process.env.EXPO_PUBLIC_HA_TOKEN;
|
|
|
|
// Crea un'istanza di axios per Home Assistant
|
|
const haApi = axios.create({
|
|
baseURL: HA_API_URL,
|
|
headers: {
|
|
'Authorization': `Bearer ${HA_TOKEN}`,
|
|
'Content-Type': 'application/json',
|
|
},
|
|
timeout: 5000, // 5 secondi di timeout
|
|
});
|
|
|
|
haApi.interceptors.request.use((config) => {
|
|
console.log(`[HOME ASSISTANT API REQUEST] ${config.method?.toUpperCase()} ${config.url}`);
|
|
return config;
|
|
});
|
|
|
|
/*
|
|
* Connection test
|
|
*/
|
|
export const testHaConnection = async (): Promise<{ success: boolean; message: string }> => {
|
|
// Controlla se le variabili d'ambiente sono caricate
|
|
if (!HA_API_URL || !HA_TOKEN) {
|
|
console.error("Variabili d'ambiente per Home Assistant non trovate. Assicurati che EXPO_PUBLIC_HA_API_URL and EXPO_PUBLIC_HA_TOKEN siano definite nel file .env");
|
|
return { success: false, message: "Configurazione API per Home Assistant mancante." };
|
|
}
|
|
|
|
try {
|
|
const response = await haApi.get('/');
|
|
// Se la risposta è OK, HA restituisce un JSON con 'message'
|
|
if (response.status === 200 && response.data.message) {
|
|
return { success: true, message: response.data.message };
|
|
}
|
|
return { success: false, message: "Risposta inattesa dal server Home Assistant." };
|
|
|
|
} catch (error) {
|
|
const axiosError = error as AxiosError;
|
|
|
|
if (axiosError.code === 'ECONNABORTED' || axiosError.message.includes('timeout')) {
|
|
return { success: false, message: "Timeout: Il server non risponde (IP errato o server offline)." };
|
|
}
|
|
|
|
if (axiosError.response) {
|
|
// Errori con una risposta dal server (es. 401, 404)
|
|
if (axiosError.response.status === 401) {
|
|
return { success: false, message: "Errore 401: Token non autorizzato. Controlla il Long-Lived Token." };
|
|
}
|
|
if (axiosError.response.status === 404) {
|
|
return { success: false, message: "Errore 404: Verifica la configurazione di Home Assistant." };
|
|
}
|
|
return { success: false, message: `Errore server: Status ${axiosError.response.status}` };
|
|
} else if (axiosError.request) {
|
|
// Errori di rete (la richiesta è partita ma non ha ricevuto risposta)
|
|
return { success: false, message: `Errore di rete: Impossibile raggiungere ${HA_API_URL}` };
|
|
} else {
|
|
// Errore generico
|
|
return { success: false, message: `Errore sconosciuto: ${axiosError.message}` };
|
|
}
|
|
}
|
|
};
|
|
|
|
// Fetch Home Assistant Areas
|
|
export const getHaAreas = async (): Promise<HaArea[]> => {
|
|
try {
|
|
const response = await haApi.post('/template', {
|
|
"template": `
|
|
[
|
|
{%- for area_id in areas() %}
|
|
{%- set area_name = area_name(area_id) %}
|
|
{%- set f_id = floor_id(area_name) %}
|
|
{%- set f_name = floor_name(f_id) %}
|
|
{
|
|
"id": "{{ area_id }}",
|
|
"name": "{{ area_name }}",
|
|
"floor_id": {% if f_id != None %}"{{ f_id }}"{% else %}null{% endif %},
|
|
"floor_name": {% if f_name != None %}"{{ f_name }}"{% else %}null{% endif %},
|
|
"device_count": {{area_devices(area_id)|count}}
|
|
}{% if not loop.last %},{% endif %}
|
|
{%- endfor %}
|
|
]
|
|
`
|
|
});
|
|
|
|
const data = typeof response.data === 'string' ? JSON.parse(response.data) : response.data;
|
|
// console.log("Aree recuperate da Home Assistant:", data);
|
|
return data;
|
|
|
|
} catch (error) {
|
|
console.error("Errore recupero aree:", error);
|
|
return []; // Restituisce un array vuoto in caso di errore
|
|
}
|
|
};
|
|
|
|
// Fetch Home Assistant Entities by Area
|
|
export const getHaEntitiesByArea = async (areaId: string): Promise<HaEntity[]> => {
|
|
try {
|
|
const response = await haApi.post('/template', {
|
|
"template": `
|
|
[
|
|
{%- set area_entities = area_entities('${areaId}') %}
|
|
{%- for entity_id in area_entities %}
|
|
{
|
|
"entity_id": {{ entity_id | tojson }},
|
|
"name": {{ state_attr(entity_id, 'friendly_name') | tojson }},
|
|
"state": {{ states(entity_id) | tojson }}
|
|
}{% if not loop.last %},{% endif %}
|
|
{%- endfor %}
|
|
]
|
|
`
|
|
});
|
|
|
|
const data = typeof response.data === 'string' ? JSON.parse(response.data) : response.data;
|
|
// console.log(`Entità recuperate per l'area ${areaId}:`, data);
|
|
return data;
|
|
|
|
} catch (error) {
|
|
console.error(`Errore recupero entità per l'area ${areaId}:`, error);
|
|
return []; // Restituisce un array vuoto in caso di errore
|
|
}
|
|
};
|
|
|
|
// Toggle Home Assistant Entity
|
|
export const toggleHaEntity = async (entityId: string): Promise<boolean> => {
|
|
try {
|
|
const domain = entityId.split('.')[0];
|
|
|
|
await haApi.post('/services/' + domain + '/toggle', {
|
|
entity_id: entityId
|
|
});
|
|
|
|
return true;
|
|
} catch (error) {
|
|
console.error(`Errore toggle ${entityId}:`, error);
|
|
return false;
|
|
}
|
|
};
|
|
|