Page 1 sur 1

Créer une Structure contenant un buffer ?

Publié : sam. 19/sept./2009 9:21
par Golfy
Bonjour

Je travaille sur les messages du bus VelBus. Ces messages contiennent des données à $00, je ne peux donc pas utiliser les variables de type string (.s) pour stocker les messages.
Je penses utiliser un buffer et lire les données en utilisant le pointeur *buffer par exemple (peekB(*buffer)).

Comme il y a plusieurs messages, je voulais utiliser une liste chainée et une structure. Peut-on écrire

Code : Tout sélectionner

Structure messages
  *buffer
EndStructure
ou bien quelque chose d'équivalent ? l'objectif est de détruire le message une fois traité... :roll:

Re: Créer une Structure contenant un buffer ?

Publié : sam. 19/sept./2009 14:37
par Backup
Golfy a écrit :Bonjour

Je travaille sur les messages du bus VelBus. Ces messages contiennent des données à $00, je ne peux donc pas utiliser les variables de type string (.s) pour stocker les messages.
je vois pas pourquoi tu pourrai pas ...

tu reçois une chaine avec des "$00" ?

ben tu filtre c'est tout ! :)

a coup de mid() on peut faire des miracles :)

disons que tu dise que tu veuille pas employer les strings pour une question de vitesse
passe encore... ;)

Re: Créer une Structure contenant un buffer ?

Publié : sam. 19/sept./2009 15:50
par djes
Le mieux est de créer une structure qui te permettre de voir clair dans le contenu des messages. Mets-là ici, qu'on puisse te dire comment la traiter après. Et tu peux mettre des pointeurs dans une structure.

Re: Créer une Structure contenant un buffer ?

Publié : sam. 19/sept./2009 18:22
par Anonyme2
Le premier exemple que je vais mettre permet d'utiliser une structure contenant une variable (pas un pointeur) de type tableau de byte (octets).

Le tableau d'octet de la structure a 0 élément, il en résulte que un sizeof(nom_structure) retourne 0.

Ce n'est pas forcément le plus simple pour ton exemple car on peut utiliser un pointeur simple, au programme de faire évoluer l'adresse du pointeur (voir le deuxième exemple).

J'ai mis cet exemple car certaines structures Microsoft utilisent ce genre d'élément dans une structure, c'est à dire un élément tableau de taille 0.

Le compteur de boucle fait évoluer le pointeur en fonction de sa valeur, attention, la vraie valeur du pointeur ne change pas, elle est utilisée dans le calcul par le compilateur qui se charge de calculer la nouvelle valeur.

Code : Tout sélectionner

EnableExplicit 

Define .i

Structure Buffer_Byte
    val.byte[0]
EndStructure

;// affiche la taille de la structure, juste pour voir  --> = 0
; Debug SizeOf(Buffer_Byte)


Global *var.Buffer_Byte  ; permet de lire chaque valeur
Global compteur         ; compteur de boucle
Global Fin_boucle       ; permet de claculer la valeur à tester pour terminer le for

;// calcul de la fin de boucle
Fin_boucle = ?fin - ?debut - SizeOf(byte)

;// on assigne l'adresse du début des données au pointeur *var.Buffer_Byte
*var = ?debut

;// on démarre la boucle de lecture
Debug "boucle for"
Debug "------------"
For compteur = 0 To Fin_boucle
   Debug Right(Hex(PeekB(*var\val[compteur])), 2) + " --> hexa"
   Debug PeekA(*var\val[compteur]) ; + " --> décimal non signé"
   Debug PeekB(*var\val[compteur]) ; + " --> décimal signé"
   Debug ""
Next


;// autre boucle avec un while - wend
Debug "boucle while"
Debug "------------"
compteur = 0
While (?debut + compteur) < ?fin
   Debug Right(Hex(PeekB(*var\val[compteur])), 2) + " --> hexa"
   Debug PeekA(*var\val[compteur]) ; + " --> décimal non signé"
   Debug PeekB(*var\val[compteur]) ; + " --> décimal signé"
   Debug ""
   compteur = compteur + 1
Wend


DataSection
debut:
     Data.b  $10, $00, $A5, $FF, $9A, 01
fin:     
EndDataSection
voici un deuxième code un peu plus simple avec un pointeur sans structure

Code : Tout sélectionner

EnableExplicit 

Define .i



Global *var.byte     ; permet de lire chaque valeur
Global Fin_boucle    ; permet de claculer la valeur à tester pour terminer le for

;// calcul de la fin de boucle
Fin_boucle = ?fin - SizeOf(byte)

;// on assigne l'adresse du début des données au pointeur *var
;// directement dans la boucle for, il sera incrémenté automatiquement de 1
;// on démarre la boucle de lecture
Debug "boucle for"
Debug "------------"
For *var = ?debut To Fin_boucle
   Debug Right(Hex(*var\b), 2) + " --> hexa"
Next

Debug ""
;// autre boucle avec un while - wend
Debug "boucle while"
Debug "------------"
*var = ?debut
While *var < ?fin
   Debug Right(Hex(*var\b), 2) + " --> hexa"
   ;// on incrémente le pointeur
   *var + SizeOf(byte)
Wend


DataSection
debut:
     Data.b  $10, $00, $A5, $FF, $9A, 01
fin:     
EndDataSection

Re: Créer une Structure contenant un buffer ?

Publié : dim. 20/sept./2009 19:58
par Golfy
Dobro a écrit :
je vois pas pourquoi tu pourrai pas ...

tu reçois une chaine avec des "$00" ?

ben tu filtre c'est tout ! :)

a coup de mid() on peut faire des miracles :)

disons que tu dise que tu veuille pas employer les strings pour une question de vitesse
passe encore... ;)
Désolé, J'ai mal exprimé mon besoin : sauf erreur de ma part, le caractère NULL ou chr(0) est un délimiteur de fin de chaine, non ?
Si je reçois une chaine de 6 caractères comme suis (valeurs exprimée en hexadécimal, $xx) :
$0F $F8 $00 $02 $04

a$ = Chr($0f) + Chr($f8) + Chr($00) + Chr($02) + Chr($04)
Debug Len(a$)
Le résultat est 2 au lieu de 5, non ?

Re: Créer une Structure contenant un buffer ?

Publié : dim. 20/sept./2009 20:06
par Golfy
djes a écrit :Le mieux est de créer une structure qui te permettre de voir clair dans le contenu des messages. Mets-là ici, qu'on puisse te dire comment la traiter après. Et tu peux mettre des pointeurs dans une structure.
L'idée n'est pas mauvaise (d'autant plus que j'ai déjà une procédure de lecture pour mes debug)
Au lieu de a$ = chr($0f)+chr($f8)+....+chr($04) j'ai a$ = "$0F $F8 ... $04"

c'est un peu plus long (espace mémoire) mais plus lisible... :roll:

D'autant plus que ma structures doit avoir 2 parties : les 4 premiers octets définissent la longueur et le type de message qui suit ! les idées les plus simples sont parfois les meilleures.

Re: Créer une Structure contenant un buffer ?

Publié : dim. 20/sept./2009 23:17
par Le Soldat Inconnu
je suis peut-être à coté de la plaque mais

Tu connais la longueur de ton message ?

Code : Tout sélectionner

NewList AdresseMessage.l()
AddElement(AdresseMessage())
longueur = 6
AdresseMessage() = AllocateMemory(longueur)

FreeMemory(AdresseMessage())
DeleteElement(AdresseMessage())
et c'est tout

Re: Créer une Structure contenant un buffer ?

Publié : dim. 20/sept./2009 23:24
par djes
Pareil, je ne vois pas où est le problème. S'il y a bien un langage qui est à l'aise avec ce genre de trucs, c'est bien pb! Si tu veux de l'aide, faut être un peu plus clair...

Re: Créer une Structure contenant un buffer ?

Publié : lun. 21/sept./2009 13:09
par Golfy
djes a écrit :Pareil, je ne vois pas où est le problème. S'il y a bien un langage qui est à l'aise avec ce genre de trucs, c'est bien pb! Si tu veux de l'aide, faut être un peu plus clair...
En fait, je lis des trames sur un BUS. Chaque trame a une longueur déterminée par son 3ème octet + 5 octets (header, checksum et terminaison).
La longueur est donc "variable". le Début est toujours le caractère '$0F' et la fin est toujours '$04'.
Depuis ce week-end, je sais séparer les messages (procédure récursive :mad: ) et voici les traces de debug du BUS (chaque ligne = 1 message) :

Code : Tout sélectionner

0FF8010400020000F204
0FFB0102F502FC04
0FFB0208FB02000000000000EF04
0FFB0102F640BD04
0FFB0102F644B904
0FFB0102F640BD04
0FF8020400000200F104
0FF8010400000200F204
0FF8010400010000F304
0FFB0102F501FD04
0FFB0102F501FD04
0FFB0102F501FD04
0FFB0102F501FD04
0FFB0208FB01070000000000E904
0FFB0102F644B904
0FFB0102F640BD04
0FF8020400000100F204
0FF8010400000100F304
Maintenant, soit je stocke dans un tableau, soit j'utilise une liste (sachant que mon programme doit lire les messages 1 à un et supprimer après traitement).

Re: Créer une Structure contenant un buffer ?

Publié : lun. 21/sept./2009 13:21
par Golfy
Le Soldat Inconnu a écrit :je suis peut-être à coté de la plaque mais

Tu connais la longueur de ton message ?

Code : Tout sélectionner

NewList AdresseMessage.l()
AddElement(AdresseMessage())
longueur = 6
AdresseMessage() = AllocateMemory(longueur)

FreeMemory(AdresseMessage())
DeleteElement(AdresseMessage())
et c'est tout
Voilà ! c'est ce que je voulais savoir :)
A part que maintenant, j'ai une vraie chaine ASCII donc moins de problème pour le stockage de la trame :roll:

Merci LSI !
(PS: j'adore ton soft "Enregistrer sous...")

Re: Créer une Structure contenant un buffer ?

Publié : lun. 21/sept./2009 13:30
par djes
Pourquoi une procédure récursive? Ce n'est pas utile à mon avis, et ça peut être dangereux (débordement de la pile). Dois-tu décoder ces données à la volée (les parser)? Sinon, le plus simple pour les lire est d'utiliser un petit buffer temporaire (taille du message max), que tu remplis octet par octet jusqu'à ce que tu rencontres le caractère de fin. Tu vérifies que la taille obtenue est la même que celle envoyée (sinon ton paquet est foireux). Ceci fait, tu ajoutes un élément à ta liste (voir le truc de lsi), et tu fais une copie avec copymemory de la zone. Et tu recommences. Tu fais ça si possible dans un thread pour éviter de perdre des paquets, et tu les traites en parallèle.

Re: Créer une Structure contenant un buffer ?

Publié : lun. 21/sept./2009 13:48
par Cls
Perso j'utiliserai une structure de ce type pour accéder aux données (non testé) :

Code : Tout sélectionner

Structure MESSAGE
init.b
header.b
checksum.b
length.b
data.l
EndStructure

NewList Message.MESSAGE()
Lors de la lecture des messages et de l'écriture dans le tableau, je ferai un truc comme ça (non testé) :

Code : Tout sélectionner

msg.MESSAGE = @tonbufferdentree

AddElement(Message())
Message()\init = msg\init
Message()\header = msg\header
Message()\checksum = msg\checksum
Message()\length = msg\length

data = AllocateMemory(msg\length)
CopyMemory(@msg\data, @data, msg\length)
Message()\data = @data
Message()\data contient alors l'adresse d'une zone mémoire contenant les données du paquet.

Re: Créer une Structure contenant un buffer ?

Publié : lun. 21/sept./2009 16:35
par Golfy
djes a écrit :Pourquoi une procédure récursive? Ce n'est pas utile à mon avis, et ça peut être dangereux (débordement de la pile).
hmmm... tu es le deuxième à me dire ça ? la récursivité n'est plus à la mode :roll: ? je vais faire une bonne vieille boucle... ça semble plus sûr, merci :)
djes a écrit :Dois-tu décoder ces données à la volée (les parser)? Sinon, le plus simple pour les lire est d'utiliser un petit buffer temporaire (taille du message max), que tu remplis octet par octet jusqu'à ce que tu rencontres le caractère de fin. Tu vérifies que la taille obtenue est la même que celle envoyée (sinon ton paquet est foireux). Ceci fait, tu ajoutes un élément à ta liste (voir le truc de lsi), et tu fais une copie avec copymemory de la zone. Et tu recommences. Tu fais ça si possible dans un thread pour éviter de perdre des paquets, et tu les traites en parallèle.
Les données sont les états des interrupteurs, des relais et toutes les informations qui circulent sur le BUS. Mon objectif est de "monitorer" (superviser) les messages pour afficher en temps réel l'état des modules.
Exemple : le relais 4 du module 2 qui bascule sur ON correspond à la lampe de la cuisine --> lampe cuisine allumée

Parfois, le changement d'état d'un module entraine une réponse d'un autre module, d'où le besoin de lire tous les messages.

Merci à tous pour vos réponses. Image

PS : je bosse sur une application Velbus/Purebasic (forum Applications sur Purebasic)et peut-être pouvoir fournir une DLL ou librairie (si un jour je comprend comment sa marche :roll: )

Re: Créer une Structure contenant un buffer ?

Publié : lun. 21/sept./2009 17:42
par djes
Ce serait génial! Continue à nous faire part de l'avancée de tes travaux :)