pour leur aide dans l'avancement de mes projets Purebasic.
SQLite et JSON m'ont donnés du fil a retordre et sans eux je serais encore entrain de m'arracher les cheveux.
Le code ci dessous regroupe tous leurs conseils sur SQLite et JSON dans une ébauche de gestion des chaines Freebox (pour les abonnés)
a) récupération en ligne des informations de toutes les chaines diffusées par Free au format JSON
d) extraction de cette BD de quelques informations sur l'identifiant d'une chaine Ex:uuid-webtv-612 = TF1
e) récupération du guide TV d'un chaine au format JSON et traitement pour afficher le guide
f) récupération d'informations sur la Freebox au format JSON + traitement et affichage de informations
J'espère que ce code sera utile a des Freenautes, mais aussi a toute personne voulant capitaliser avec SQLite et JSON
Code : Tout sélectionner
EnableExplicit
Declare.a fileExist(f$)
Declare.a getProgrammeTV(chaine$)
Declare.a get_api_version()
Declare.a CheckDatabaseQuery(Database, Query$)
Declare.a CheckDatabaseUpdate(Database, Query$)
Declare.s replaceAllString(string$,find$,replace$,flags=0)
#DATABASE$ = ".\m3u\Freebox\playlist.db"
#PLAYLIST$ = ".\m3u\Freebox\playlist.m3u"
;#JSONFILE$ = ".\m3u\Freebox\playlist.json" ; n'est plus nécessaire
;#JSONTEXT$ = ".\m3u\Freebox\playlist.json.txt" ; n'est plus nécessaire
;----------------------------------------------------------------------
;Pour les abonnés Free (Freebox)
#FBX_BASEURL$ = "http://mafreebox.freebox.fr"
#FBX_CONNECT$ = "http://mafreebox.freebox.fr/login.php"
#FBX_PLAYURL$ = "http://mafreebox.freebox.fr/freeboxtv/playlist.m3u"
#FBX_JSONURL$ = "http://mafreebox.freebox.fr/api/v3/tv/channels"
#FBX_VERSION$ = "http://mafreebox.freebox.fr/api_version"
#FBX_DOC_URL$ = "http://mafreebox.freebox.fr/doc/index.html"
;----------------------------------------------------------------------
Structure DATAS_CHAINE
uuid.s
name.s
available.a
logo_url.s
has_service.a
short_name.s
has_abo.a
EndStructure
Structure CHAINE
NomCanal.s
DonneesChaine.DATAS_CHAINE
EndStructure
Structure DATAS_GUIDE
sub_title.s
_next.s
id.s
duration.c
picture.s
desc.s
picture_big.s
categorie_name.s
title.s
prev.s
categorie.a
episode_number.c
saison_number.c
date.c
EndStructure
Structure GUIDE
Horodatage.s
DonneesGuide.DATAS_GUIDE
EndStructure
Global NewList CHAINES.CHAINE()
Global NewList MYGUIDE.GUIDE()
Define JSON, jsonObjectValue
Define ChaineJSON.s
Define *TamponJSON
*TamponJSON=ReceiveHTTPMemory(#FBX_JSONURL$)
If *TamponJSON
JSON = CatchJSON(#PB_Any, *TamponJSON, MemorySize(*TamponJSON))
If JSON
ChaineJSON=ComposeJSON(JSON)
; ------- !!!! IMPORTANT !!!! ----------
; Remplacer les valeurs true et false pour qu'elles puissent être récupérées via la structure DATAS_CHAINE
ChaineJSON=ReplaceAllString(ChaineJSON,": true," ,":1,",#PB_String_NoCase)
ChaineJSON=ReplaceAllString(ChaineJSON,":true," ,":1,",#PB_String_NoCase)
ChaineJSON=ReplaceAllString(ChaineJSON,": false,",":0,",#PB_String_NoCase)
ChaineJSON=ReplaceAllString(ChaineJSON,":false," ,":0,",#PB_String_NoCase)
; --------------------------------------
JSON = ParseJSON(#PB_Any, ChaineJSON, #PB_JSON_NoCase)
Else
Debug "Echec lors de l'analyse des données JSON"
EndIf
FreeMemory(*TamponJSON)
Else
Debug "Echec de la réception en mémoire du fichier JSON"
EndIf
If JSON
; get the json object value
; On pointe vers le membre 'success' pour obtenir sa valeur
jsonObjectValue = GetJSONMember(JSONValue(JSON),"success")
If jsonObjectValue ; Si l'objet 'success" a été trouvé
If GetJSONInteger(jsonObjectValue) ; Si la valeur de 'success" est égale à 1 ('true')
Debug "Retour Free : Succès"
; On pointe vers le membre 'result' pour récupérer la collection de sous-membres
jsonObjectValue = GetJSONMember(JSONValue(JSON),"result")
If jsonObjectValue ; si l'objet 'result' a été trouvé
If ExamineJSONMembers(jsonObjectValue) ; si il contient des membres
While NextJSONMember(jsonObjectValue)
AddElement(CHAINES())
With CHAINES()
\NomCanal=JSONMemberKey(jsonObjectValue)
ExtractJSONStructure(JSONMemberValue(jsonObjectValue),\DonneesChaine,DATAS_CHAINE)
EndWith
Wend
EndIf
Else
Debug "Pas de membre 'Result' !"
EndIf
Else
Debug "Retour Free : Échec"
EndIf
Else
Debug "Pas de membre 'Success' !"
EndIf
; clear & release the json object
FreeJSON(JSON)
EndIf
UseSQLiteDatabase()
Global IN, OUT, DB, I, DATAS.s
If Not fileExist(#DATABASE$)
OUT = CreateFile(#PB_Any, #DATABASE$)
If OUT
CloseFile(OUT)
Else
Debug "Can't create the database file !"
End
EndIf
EndIf
#QUERY_DELETE_TABLE="DROP TABLE IF EXISTS DATABASE"
#QUERY_CREATE_TABLE="CREATE TABLE DATABASE ("+
"uuid TEXT,"+
"name TEXT,"+
"available INTEGER,"+
"logo_url TEXT,"+
"has_service INTEGER,"+
"short_name TEXT,"+
"has_abo INTEGER)"
;#QUERY_SELECT_TABLE="SELECT UUID,NAME FROM DATABASE ORDER BY ROWID WHERE NAME LIKE "
#QUERY_SELECT_TABLE="SELECT UUID,NAME FROM DATABASE WHERE NAME LIKE "
OUT = OpenDatabase(#PB_Any, #DATABASE$, #Empty$, #Empty$)
If OUT
CheckDatabaseUpdate(OUT, #QUERY_DELETE_TABLE)
CheckDatabaseUpdate(OUT, #QUERY_CREATE_TABLE)
I=0
CheckDatabaseUpdate(OUT, "BEGIN")
ForEach CHAINES()
I+1
;Debug CHAINES()\NomCanal+" :"
With CHAINES()\DonneesChaine
;Debug " name : "+\name
;Debug " has_abo : "+\has_abo
;Debug " available : "+\available
;Debug " short_name : "+\short_name
;Debug " has_service : "+\has_service
;Debug " logo_url : "+\logo_url
;Debug " uuid : "+\uuid
;Solution qui ne fonctionne pas pour retirer les caractères interdits
;DATAS.s= "'"+\uuid+"','"+\name+"','"+\available+"','"+\logo_url+"','"+\has_service+"','"+\short_name+"','"+\has_abo+"'"
;CheckDatabaseUpdate(OUT, "INSERT INTO DATABASE (uuid, name, available, logo_url, has_service, short_name, has_abo) VALUES ("+DATAS+")")
;Solution qui fonctionne pour retirer les caractères interdits
DATAS.s= \uuid+","+\name+","+\available+","+\logo_url+","+\has_service+","+\short_name+","+\has_abo
SetDatabaseString(OUT, 0, StringField(DATAS, 1, ","))
SetDatabaseString(OUT, 1, StringField(DATAS, 2, ","))
SetDatabaseString(OUT, 2, StringField(DATAS, 3, ","))
SetDatabaseString(OUT, 3, StringField(DATAS, 4, ","))
SetDatabaseString(OUT, 4, StringField(DATAS, 5, ","))
SetDatabaseString(OUT, 5, StringField(DATAS, 6, ","))
SetDatabaseString(OUT, 6, StringField(DATAS, 7, ","))
CheckDatabaseUpdate(OUT, "INSERT INTO DATABASE VALUES (?, ?, ?, ?, ?, ?, ?)")
EndWith
Next
ClearList(CHAINES())
CheckDatabaseUpdate(OUT, "COMMIT")
CheckDatabaseUpdate(OUT, "PRAGMA auto_vacuum = FULL")
CheckDatabaseUpdate(OUT, "VACUUM")
CloseDatabase(OUT)
Debug "NombreDeChaines="+I
Else
Debug "Can't open the database file for writing !"
EndIf ; If OUT
DB = OpenDatabase(#PB_Any, #DATABASE$, #Empty$, #Empty$, #PB_Database_SQLite)
If DB
Debug "Open database Ok"
CheckDatabaseUpdate(DB, "PRAGMA auto_vacuum = FULL")
CheckDatabaseUpdate(DB, "VACUUM")
Debug #CRLF$+"Recherche des chaines TF1"
CheckDatabaseQuery(DB, #QUERY_SELECT_TABLE+"'%TF1%'")
Debug #CRLF$+"Recherche des chaines ARTE"
CheckDatabaseQuery(DB, #QUERY_SELECT_TABLE+"'%ARTE%'")
Debug #CRLF$+"Recherche des chaines BFM"
CheckDatabaseQuery(DB, #QUERY_SELECT_TABLE+"'%BFM%'")
Debug #CRLF$+"Recherche des chaines FRANCE"
CheckDatabaseQuery(DB, #QUERY_SELECT_TABLE+"'%FRANCE%'")
Debug #CRLF$+"Recherche des chaines HD"
CheckDatabaseQuery(DB, #QUERY_SELECT_TABLE+"'%HD%'")
CloseDatabase(DB)
Debug Str(Round(FileSize(#DATABASE$)/1024,#PB_Round_Up))+" Ko"
EndIf ; If DB
Debug "----------------------------------------------"
get_api_version()
Debug "----------------------------------------------"
getProgrammeTV("uuid-webtv-404")
Debug "----------------------------------------------"
getProgrammeTV("uuid-webtv-612")
Debug "----------------------------------------------"
End
Procedure.a fileExist(f$)
If FileSize(f$) < 0
ProcedureReturn #False
Else
ProcedureReturn #True
EndIf
EndProcedure
Procedure.s replaceAllString(string$,find$,replace$,flags=0)
While CountString(string$, find$) > 0
string$ = ReplaceString(string$, find$, replace$, flags)
Wend
ProcedureReturn string$
EndProcedure
Procedure.a CheckDatabaseQuery(Database, Query$)
If DatabaseQuery(Database, Query$, #PB_Database_StaticCursor)
;Debug "DatabaseColumns="+DatabaseColumns(Database)
While NextDatabaseRow(Database) ; Loop for each records
Debug GetDatabaseString(Database, 0)+" = "+GetDatabaseString(Database, 1)
Wend
FinishDatabaseQuery(Database)
ProcedureReturn #True
Else
Debug DatabaseError()
ProcedureReturn #False
EndIf
EndProcedure
Procedure.a CheckDatabaseUpdate(Database, Query$)
If DatabaseUpdate(Database, Query$)
ProcedureReturn #True
Else
Debug DatabaseError()
ProcedureReturn #False
EndIf
EndProcedure
Procedure.a getProgrammeTV(chaine$)
;;http://mafreebox.freebox.fr/api/v3/tv/epg/by_channel/<channel_id>/<epoch_time>
Protected epoch_time$ = Str(Date())
Protected channel_id$ = chaine$
Protected url$ = "http://mafreebox.freebox.fr/api/v3/tv/epg/by_channel/"
Protected JSON, jsonObjectValue
Protected ChaineJSON$, Heure$
Protected *TamponJSON
;Debug url$+channel_id$+"/"+epoch_time$
*TamponJSON = ReceiveHTTPMemory(url$+channel_id$+"/"+epoch_time$)
If *TamponJSON
JSON = CatchJSON(#PB_Any, *TamponJSON, MemorySize(*TamponJSON))
If JSON
ChaineJSON$ = ComposeJSON(JSON)
; ------- !!!! IMPORTANT !!!! ----------
; Remplacer les valeurs true et false pour qu'elles puissent être récupérées via la structure DATAS_GUIDE
ChaineJSON$=ReplaceAllString(ChaineJSON$,": true," ,":1,",#PB_String_NoCase)
ChaineJSON$=ReplaceAllString(ChaineJSON$,":true," ,":1,",#PB_String_NoCase)
ChaineJSON$=ReplaceAllString(ChaineJSON$,": false,",":0,",#PB_String_NoCase)
ChaineJSON$=ReplaceAllString(ChaineJSON$,":false," ,":0,",#PB_String_NoCase)
; --------------------------------------
JSON = ParseJSON(#PB_Any, ChaineJSON$, #PB_JSON_NoCase)
Else
Debug "Echec lors de l'analyse des données JSON"
EndIf
FreeMemory(*TamponJSON)
Else
Debug "Echec de la réception en mémoire du fichier JSON"
EndIf
;;;
If JSON
; get the json object value
; On pointe vers le membre 'success' pour obtenir sa valeur
jsonObjectValue = GetJSONMember(JSONValue(JSON),"success")
If jsonObjectValue ; Si l'objet 'success" a été trouvé
If GetJSONInteger(jsonObjectValue) ; Si la valeur de 'success" est égale à 1 ('true')
;Debug "Retour Free : Succès"
; On pointe vers le membre 'result' pour récupérer la collection de sous-membres
jsonObjectValue = GetJSONMember(JSONValue(JSON),"result")
If jsonObjectValue ; si l'objet 'result' a été trouvé
If ExamineJSONMembers(jsonObjectValue) ; si il contient des membres
While NextJSONMember(jsonObjectValue)
AddElement(MYGUIDE())
With MYGUIDE()
\Horodatage=JSONMemberKey(jsonObjectValue)
ExtractJSONStructure(JSONMemberValue(jsonObjectValue),\DonneesGuide,DATAS_GUIDE)
EndWith
Wend
EndIf
Else
Debug "Pas de membre 'Result' !"
EndIf
Else
Debug "Retour Free : Échec"
EndIf
Else
Debug "Pas de membre 'Success' !"
EndIf
; clear & release the json object
FreeJSON(JSON)
; On trie la liste MYGUIDE() en fonction de la valeur Horodatage (TimeStamp)
SortStructuredList(MYGUIDE(), #PB_Sort_Ascending,OffsetOf(GUIDE\Horodatage), TypeOf(GUIDE\Horodatage))
ForEach MYGUIDE()
I+1
Heure$ = MYGUIDE()\Horodatage ;: Debug Heure$
Heure$ = StringField(Heure$,1,"_")
Heure$ = FormatDate("%yyyy/%mm/%dd %hh:%ii:%ss",Val(Heure$))
Debug #CRLF$+Heure$
With MYGUIDE()\DonneesGuide
If \categorie_name <> #Empty$ : Debug \categorie_name : EndIf
If \title <> #Empty$ : Debug \title : EndIf
If \sub_title <> #Empty$ : Debug \sub_title : EndIf
If \saison_number : Debug "Saison: " +\saison_number : EndIf
If \episode_number : Debug "Episode: "+\episode_number : EndIf
If \duration : Debug "Durée: " +Str(\duration/60)+"mn" : EndIf
If \desc <> #Empty$
\desc=replaceAllString(\desc,". ",#CRLF$)
Debug \desc
EndIf
EndWith
Next
ClearList(MYGUIDE())
EndIf
EndProcedure
Procedure.a get_api_version()
;;http://mafreebox.freebox.fr/api_version
Protected url$ = "http://mafreebox.freebox.fr/api_version"
Protected JSON, jsonObjectValue
Protected ChaineJSON$
Protected *TamponJSON
*TamponJSON = ReceiveHTTPMemory(url$)
If *TamponJSON
JSON = CatchJSON(#PB_Any, *TamponJSON, MemorySize(*TamponJSON))
If JSON
ChaineJSON$ = ComposeJSON(JSON)
; ------- !!!! IMPORTANT !!!! ----------
; Remplacer les valeurs true et false pour qu'elles puissent être récupérées via la structure DATAS_GUIDE
ChaineJSON$=ReplaceAllString(ChaineJSON$,": true," ,":1,",#PB_String_NoCase)
ChaineJSON$=ReplaceAllString(ChaineJSON$,":true," ,":1,",#PB_String_NoCase)
ChaineJSON$=ReplaceAllString(ChaineJSON$,": false,",":0,",#PB_String_NoCase)
ChaineJSON$=ReplaceAllString(ChaineJSON$,":false," ,":0,",#PB_String_NoCase)
; --------------------------------------
JSON = ParseJSON(#PB_Any, ChaineJSON$, #PB_JSON_NoCase)
Else
Debug "Echec lors de l'analyse des données JSON"
EndIf
FreeMemory(*TamponJSON)
Else
Debug "Echec de la réception en mémoire du fichier JSON"
EndIf
If JSON
; get the json object value
; On pointe vers le membre 'success' pour obtenir sa valeur
jsonObjectValue = GetJSONMember(JSONValue(JSON),"device_name")
Debug "Nom de la Box: "+GetJSONString(jsonObjectValue)
jsonObjectValue = GetJSONMember(JSONValue(JSON),"box_model_name")
Debug "Modèle de la Box: "+GetJSONString(jsonObjectValue)
jsonObjectValue = GetJSONMember(JSONValue(JSON),"box_model")
Debug "Modèle de la Box: "+GetJSONString(jsonObjectValue)
jsonObjectValue = GetJSONMember(JSONValue(JSON),"api_version")
Debug "Version de la Box: "+GetJSONString(jsonObjectValue)
; clear & release the json object
FreeJSON(JSON)
Else
Debug "Echec lors de l'analyse des données JSON"
EndIf
;api_base_url "/api/"
;https_port 42182
;device_name "FBCAGE"
;https_available true
;box_model "fbxgw8-r1"
;api_domain "wuk0txyh.fbxos.fr"
;uid "18c6e2d9b696fd3634aeec9fa1f5f8b1"
;api_version "10.2"
;device_type "FreeboxServer8,1"
EndProcedure
; Les outils SQLite
;
; https://sqlitebrowser.org
; https://www.sqliteexpert.com
;
; Les outils JSON
;
; https://www.mitec.cz/jsonv.html
; http://tomeko.net/software/JSONedit/
;
; Les références
;
; https://www.sqlite.org
; https://sql.sh
; https://www.sqlitetutorial.net
; https://www.timestamp.fr
; https://www.epochconverter.com
; https://fr.wikipedia.org/wiki/Horodatage
;
; Les articles des forums
;
;https://www.purebasic.fr/french/viewtopic.php?t=18716
;https://www.purebasic.fr/french/viewtopic.php?t=19045
;
;https://www.purebasic.fr/french/viewtopic.php?t=14511
;https://www.purebasic.fr/french/viewtopic.php?t=17424
;
;https://www.purebasic.fr/english/viewtopic.php?t=62501
;https://www.purebasic.fr/english/viewtopic.php?t=62502
;https://www.purebasic.fr/english/viewtopic.php?t=72004
;https://www.purebasic.fr/english/viewtopic.php?t=74732
;
; Autres ressources
;
;https://dev.freebox.fr/bugs/
;https://dev.freebox.fr/sdk/os/#
;https://dev.freebox.fr/sdk/os/upload/#ws-upload-api
;https://dev.freebox.fr/sdk/server.html
;https://dev.freebox.fr/sdk/player.html
;https://dev.freebox.fr/sdk/libfbxqml/
;https://dev.freebox.fr/sdk/telec.html
;https://github.com/fbx/