Bonjour,
Avec l'arrivé de la mise à jour "Freebox OS", et surtout de son API... J'ai tenté d'écrire un petit script pour envoyer des fichiers multimédia via AirPlay sur la freebox. Chose que l'ont pouvait difficilement faire sous linux :/
Bref, en fait, il y a 2 scripts.
Le 1er, sert à obtenir un token pour le script qui va faire du AirMedia (à utiliser qu'une seule fois), le 2nd est l'application en elle-même.
1er script:
#!/bin/bash
myHelp()
{
[ $# -ne 0 ] && echo >&2 -e "$@"
myName=${FUNCNAME[$((${#FUNCNAME[@]}-1))]}
cat >&2 <<EOF
Usage :
${myName} -i app_id -n app_name -v app_version -d device_version
${myName} -h
Options:
-i : ID de l'application
-n : Nom de l'application
-v : Version de l'application
-d : Nom du device autorisé
-h : Affiche cette aide
EOF
[ $# -ne 0 ] && return 1
return 0
}
while getopts :i:n:v:d:h option
do
case "${option}" in
h) myHelp
exit 0;;
:) myHelp "Argument manquant pour l'option '-${OPTARG}'"
exit 1;;
"?") myHelp "Option non valide : ${OPTARG}."
exit 1;;
i) app_id="${OPTARG}";;
n) app_name="${OPTARG}";;
v) app_version="${OPTARG}";;
d) device_name="${OPTARG}";;
esac
done
[[ ${app_id} ]] || { myHelp "ID de l'application manquant !"; exit 1; }
[[ ${app_name} ]] || { myHelp "Nom de l'application manquant !"; exit 1; }
[[ ${app_version} ]] || { myHelp "Version de l'application manquante !"; exit 1; }
[[ ${device_name} ]] || { myHelp "Nom du device manquant !"; exit 1; }
chars=( '|' '/' '-' '\')
# demande d'autorisation de l\'application avec récupération du token :
IFS=$'"' read -a values < <(curl -v http://mafreebox.free.fr/api/v1/login/authorize/ -d '{"app_id":"'${app_id}'", "app_name":"'${app_name}'", "app_version":"'${app_version}'" , "device_name":"'${device_name}'"}' 2>/dev/null)
[[ "${values[@]}" == *success\ :false* ]] && {
retour=$(printf '%s"' "${values[@]}")
cat >&2 <<EOF
Erreur lors de la demande d\'autorisation !
Retour de la demande : ${retour%$'"'}
EOF
exit 2
}
app_token="${values[7]//\\}"
app_token="${app_token//$'\r'}"
app_track="${values[10]//[:\}]}"
app_track="${app_track//$'\r'}"
printf "En attente d'authorisation - à valider sur l'écran du freebox Server : "
i=0
while reponse=$(curl http://mafreebox.free.fr/api/v1/login/authorize/${app_track} 2>/dev/null) && [[ ${reponse} == *pending* ]]
do
printf "\b%s" "${chars[i]}"
sleep 1
((i++)) && (( i == ${#chars[@]} )) && i=0
done
printf "\b\n"
case ${reponse} in
*timeout*)
echo "Réponse trop tardive (time out) !" >&2; exit 2;;
*granted*)
printf "APP_ID=%s\nAPP_TOKEN=%s\nTRACK_ID=%s\n" "${app_id}" "${app_token}" "${app_track}";;
*denied*)
echo "Autorisation refusée !" >&2; exit 2;;
*unknown*)
echo "Erreur de token !" >&2; exit 2;;
esac
exit
ex : script -i fr.freebox.monAppli -n "Appli AirMedia" -v "1.0.0" -d $(hostname)
2nd Script :
#!/bin/bash
myHelp()
{
[ $# -ne 0 ] && echo >&2 -e "$@"
myName=${FUNCNAME[$((${#FUNCNAME[@]}-1))]}
cat >&2 <<EOF
Usage :
${myName} -i app_id -t app_token -f fichier
${myName} -h
Options:
-i : ID de l'application
-t : Token d'authentification
-f : Fichier audio/vidéo à jouer
-h : Affiche cette aide
EOF
[ $# -ne 0 ] && return 1
return 0
}
while getopts :i:t:f:h option
do
case "${option}" in
h) myHelp
exit 0;;
:) myHelp "Argument manquant pour l'option '-${OPTARG}'"
exit 1;;
"?") myHelp "Option non valide : ${OPTARG}."
exit 1;;
i) app_id="${OPTARG}";;
t) app_token="${OPTARG}";;
f) fichier="${OPTARG}";;
esac
done
[[ ${app_id} ]] || { myHelp "ID de l'application manquant !"; exit 1; }
[[ ${app_token} ]] || { myHelp "Token de l'application manquant !"; exit 1; }
[[ ${fichier} ]] || { myHelp "Nom de fichier audio/vidéo manquant !"; exit 1; }
# demande du challenge :
IFS='"' read -a values < <(curl http://mafreebox.free.fr/api/v1/login/ 2>/dev/null)
[[ "${values[@]}" == *success\ :false* ]] && {
retour=$(printf '%s"' "${values[@]}")
cat >&2 <<EOF
Erreur lors de la demande de challenge !
Retour de la demande : ${retour%$'"'}
EOF
exit 2
}
CHALLENGE="${values[9]//\\}"
# construction du passord
read foo PASSWORD < <(printf "${CHALLENGE}" |openssl dgst -sha1 -hmac ${app_token})
# ouverture de la session
IFS='"' read -a values < <(curl http://mafreebox.free.fr/api/v1/login/session/ -d '{"app_id":"'${app_id}'", "password":"'${PASSWORD}'"}' 2>/dev/null)
[[ "${values[@]}" == *success\ :false* ]] && {
retour=$(printf '%s"' "${values[@]}")
cat >&2 <<EOF
Erreur lors de la demande de session !
Retour de la demande : ${retour%$'"'}
EOF
exit 2
}
SESSION_TOKEN="${values[5]}"
# encodage du nom du fichier
FILE_PATH_ENCODED=$(base64 <(printf "%s" "${fichier}"))
# vérification de la connaissance du fichier
values=$(curl -H "X-Fbx-App-Auth: ${SESSION_TOKEN}" http://mafreebox.free.fr/api/v1/fs/ls/${FILE_PATH_ENCODED} 2>/dev/null)
[[ "${values}" == *success\ :false* ]] && {
cat >&2 <<EOF
Fichier inconnu du freebox Server !
Retour de la demande : ${values}
EOF
exit 2
}
# création d'un partage pour obtention URL
IFS='"' read -a values < <(curl -H "X-Fbx-App-Auth: ${SESSION_TOKEN}" http://mafreebox.free.fr/api/v1/share_link/ -d '{ "path":"'${FILE_PATH_ENCODED}'","expire":"0","fullurl":""}' 2>/dev/null)
[[ "${values[@]}" == *success\ :false* ]] && {
retour=$(printf '%s"' "${values[@]}")
cat >&2 <<EOF
Erreur lors de la création du partage !
Retour de la demande : ${retour%$'"'}
EOF
exit 2
}
FILE_TOKEN="${values[11]//\\}"
FILE_URL="${values[21]}"
values=$(curl -H "X-Fbx-App-Auth: ${SESSION_TOKEN}" http://mafreebox.free.fr/api/v1/airmedia/receivers/Freebox%20Player/ -d '{ "action": "start", "media_type": "video", "media": "'${FILE_URL}'", "password": "" }' 2>/dev/null)
[[ "${values[@]}" == *success\ :false* ]] && {
retour=$(printf '%s"' "${values[@]}")
cat >&2 <<EOF
Erreur lors de la lecture du fichier ${fichier} !
Retour de la demande : ${retour%$'"'}
EOF
exit 2
}
echo "Envoi de ${fichier} réussi !"
echo "Pour suppression partage : curl -X DELETE -H \"X-Fbx-App-Auth: ${SESSION_TOKEN}\" http://mafreebox.free.fr/api/v1/share_link/${FILE_TOKEN}"
exit
ex : script -i fr.freebox.monAppli -t "<valeur retournée par le 1er script>" -f <fichier reconnu par le freebox server>
Pré-requis :
- curl
- base64
Note : L'API attend une URL "HTTP" comme nom de fichier, c'est pourquoi :
- il faut autoriser l'accès HTTP extérieur au freebox serveur
- ce script créé un partage pour chaque fichier envoyé. une instruction pour supprimer ce partage est retournée mais cette dernière n'est valable que le temps de la session d'authentification. Le partage peut également être supprimé via l'interface d'administration du freebox serveur (Gestion des partages dans le gestionnaire de fichiers)
Le fichier doit être connu du freebox serveur (donc fichier sur le disque dur ou sur un média USB branché et activé)
Ex : /Disque dur/Enregistrements/UneChanson.mp3
A améliorer :
L'API freebox OS ne permet pas à ce jour de vérifier si un média est toujours en court de lecture ou pas... Si un jour cela est réalisable, la suppression du partage sera géré intrinsèquement.