5.2 KiB
5.2 KiB
API d'introspection UPnP
Vue d'ensemble
L'API d'introspection UPnP permet d'explorer et de modifier en temps réel la hiérarchie Device/Service/Action/Variable du serveur UPnP via des endpoints REST.
Architecture
DeviceRegistry (thread_local)
├── DeviceInstanceSet (indexé par nom)
└── Index UDN → nom
UpnpServer trait (pour pmoserver::Server)
├── register_device() - Enregistre un device
├── device_count() - Nombre de devices
├── list_devices() - Liste tous les devices
└── get_device(udn) - Récupère par UDN
UpnpApiExt trait (pour pmoserver::Server)
└── register_upnp_api() - Monte l'API REST
Utilisation dans PMOMusic
use pmoupnp::{UpnpServer, upnp_api::UpnpApiExt};
let mut server = ServerBuilder::new_configured().build();
// Enregistrer l'API d'introspection
server.register_upnp_api().await;
// Enregistrer un device UPnP
server.register_device(MEDIA_RENDERER.clone()).await?;
Endpoints REST disponibles
Liste tous les devices
GET /api/upnp/devices
Réponse :
{
"count": 1,
"devices": [
{
"udn": "uuid:f9ef6c21-0ed3-470c-9846-bc1ae85fea62",
"name": "MediaRenderer",
"friendly_name": "PMOMusic MediaRenderer",
"device_type": "urn:schemas-upnp-org:device:MediaRenderer:1",
"manufacturer": "PMOMusic",
"model_name": "MediaRenderer",
"base_url": "http://192.168.1.100:8080",
"description_url": "http://192.168.1.100:8080/device/uuid:f9ef6c21.../desc.xml"
}
]
}
Détails d'un device
GET /api/upnp/devices/:udn
Réponse :
{
"udn": "uuid:f9ef6c21-0ed3-470c-9846-bc1ae85fea62",
"name": "MediaRenderer",
"friendly_name": "PMOMusic MediaRenderer",
"device_type": "urn:schemas-upnp-org:device:MediaRenderer:1",
"manufacturer": "PMOMusic",
"model_name": "MediaRenderer",
"base_url": "http://192.168.1.100:8080",
"description_url": "http://192.168.1.100:8080/device/uuid:f9ef6c21.../desc.xml",
"services": [
{
"name": "AVTransport",
"service_type": "urn:schemas-upnp-org:service:AVTransport:1",
"service_id": "urn:upnp-org:serviceId:AVTransport",
"control_url": "http://192.168.1.100:8080/.../control",
"event_url": "http://192.168.1.100:8080/.../event",
"scpd_url": "http://192.168.1.100:8080/.../desc.xml"
}
]
}
Variables d'un service
GET /api/upnp/devices/:udn/services/:service/variables
Réponse :
{
"udn": "uuid:f9ef6c21-0ed3-470c-9846-bc1ae85fea62",
"service": "AVTransport",
"variables": [
{
"name": "TransportState",
"value": "STOPPED",
"sends_events": true
},
{
"name": "TransportStatus",
"value": "OK",
"sends_events": true
},
{
"name": "CurrentTrackURI",
"value": "",
"sends_events": true
}
]
}
Développement d'une interface web
L'API REST permet de créer facilement un composant Vue.js pour explorer l'état du serveur UPnP :
<template>
<div class="upnp-explorer">
<h2>UPnP Devices</h2>
<div v-for="device in devices" :key="device.udn">
<h3>{{ device.friendly_name }}</h3>
<button @click="loadDeviceDetails(device.udn)">Details</button>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
const devices = ref([]);
onMounted(async () => {
const response = await fetch('/api/upnp/devices');
const data = await response.json();
devices.value = data.devices;
});
async function loadDeviceDetails(udn) {
const response = await fetch(`/api/upnp/devices/${udn}`);
const data = await response.json();
console.log(data);
}
</script>
Structures de données
DeviceRegistry
Maintient la collection de tous les DeviceInstance avec :
- Double indexation (par nom et UDN)
- Méthodes d'introspection
- Modification des variables d'état
Structures sérialisables
Toutes les structures sont sérialisables en JSON via Serde :
DeviceInfo: Informations complètes sur un deviceServiceInfo: Informations sur un serviceActionInfo: Informations sur une actionArgumentInfo: Informations sur un argumentVariableInfo: Informations sur une variable d'état
Fonctions helper
upnp_server::with_devices
Exécute une closure avec accès aux devices :
use pmoupnp::upnp_server::with_devices;
let device_count = with_devices(|devices| devices.len());
upnp_server::get_device_by_udn
Récupère un device par son UDN :
use pmoupnp::upnp_server::get_device_by_udn;
if let Some(device) = get_device_by_udn("uuid:...") {
println!("Found: {}", device.get_name());
}
Modification des variables (TODO)
L'API pour modifier les variables sera ajoutée ultérieurement via des endpoints POST/PUT :
PUT /api/upnp/devices/:udn/services/:service/variables/:variable
Content-Type: application/json
{
"value": "PLAYING"
}
Notes d'implémentation
- Le
DeviceRegistryest stocké enthread_local!pour ne pas modifierpmoserver::Server - Suit le pattern d'extension utilisé dans PMOMusic (traits
UpnpServeretUpnpApiExt) - Compatible avec l'architecture existante de
pmologetpmocovers