Page 1 sur 1
Comment tester *B and *C = *B ? (CompareMemory() ?)
Publié : lun. 22/oct./2012 17:19
par Golfy
Encore une question bizarre :
je suis toujours sur mes trames Velbus. Je dois comparer la trame originale avec une trame de recherche dans laquelle -- disons pour simplifier -- j'ai des wildcards (* ou ?)
ORI : 0FFB7207E6....
SCH: 0FFB720?E6
Resultat doit être vrai pour 01, 02, 03... 0F sur le 4ème octet.
Mon but est de comparer les buffers directement, comme avec le subnetmask en réseau : du coup, est-il possible de définir un mask FFFFFFF0FF et de le comparer avec un AND (en mode buffer --> *B AND *MASK)
Re: Comment tester *B and *C = *B ? (CompareMemory() ?)
Publié : lun. 22/oct./2012 18:46
par graph100
Il ne me semble pas que ce soit possible avec les commandes natives de PB.
Par contre, une petite procedure vite faite :
Code : Tout sélectionner
Procedure.b CompareMemoryWithMask(*MemoryId1.i, *MemoryId2.i, *Mask.i, Longueur.l) ; Compare les buffers en tenant compte du mask, retourne 0 si = et sinon, l'index du premier octet <>
Protected index.l
Longueur - 1
For index = 0 To Longueur
; Debug "#####"
; Debug index
; Debug ""
; Debug RSet(Bin(PeekB(*MemoryId1 + index), #PB_Byte), 32, "0")
; Debug RSet(Bin(PeekB(*Mask + index), #PB_Byte), 32, "0")
; Debug RSet(Bin(PeekB(*MemoryId1 + index) & PeekB(*Mask + index), #PB_Byte), 32, "0")
; Debug ""
; Debug RSet(Bin(PeekB(*MemoryId2 + index), #PB_Byte), 32, "0")
If PeekB(*MemoryId1 + index) & PeekB(*Mask + index) <> PeekB(*MemoryId2 + index) & PeekB(*Mask + index)
ProcedureReturn index + 1
EndIf
Next
ProcedureReturn 0
EndProcedure
; TEST
Procedure WriteDataFromSection(*MemoryId1.i, *adr_data.i, Longueur.l)
Protected index.l
Longueur - 1
Debug ""
For index = 0 To Longueur
PokeB(*MemoryId1 + index, PeekB(*adr_data + index))
Debug Hex(PeekB(*adr_data + index), #PB_Byte)
Next
Debug ""
Debug "FIN"
EndProcedure
DataSection
ORI:
Data.b $0F, $FB, $72, $07, $E6
SCH:
Data.b $0F, $FB, $72, $03, $E6
MASK:
Data.b $FF, $FF, $FF, $F0, $FF
EndDataSection
DataSize.l = 5
*buffer_1.i = AllocateMemory(DataSize)
*buffer_2.i = AllocateMemory(DataSize)
*Mask.i = AllocateMemory(DataSize)
WriteDataFromSection(*buffer_1, ?ORI, DataSize)
WriteDataFromSection(*buffer_2, ?SCH, DataSize)
WriteDataFromSection(*Mask, ?MASK, DataSize)
res = CompareMemoryWithMask(*buffer_1, *buffer_2, *Mask, DataSize)
If res = 0
Debug "Les Buffers sont egaux en tenant compte du mask"
Else
Debug "Différence au " + Str(res) + " octet"
EndIf
; Test de vitesse :
limit = 1000000
;{ CompareMemory
t = ElapsedMilliseconds()
DisableDebugger
For a = 0 To limit
CompareMemory(*buffer_1, *buffer_2, DataSize)
Next
t = ElapsedMilliseconds() - t
EnableDebugger
Debug "CompareMemory time = " + Str(t)
;}
;{ CompareMemoryWithMask
t = ElapsedMilliseconds()
DisableDebugger
For a = 0 To limit
CompareMemoryWithMask(*buffer_1, *buffer_2, *Mask, DataSize)
Next
t = ElapsedMilliseconds() - t
EnableDebugger
Debug "CompareMemoryWithMask time = " + Str(t)
;}
;{ CompareMemoryWithMask sans procedure
t = ElapsedMilliseconds()
DisableDebugger
For a = 0 To limit
IS_equal.b = #True
For tmp_index = 0 To DataSize
If PeekB(*buffer_1 + tmp_index) & PeekB(*Mask + tmp_index) <> PeekB(*buffer_2 + tmp_index) & PeekB(*Mask + tmp_index)
IS_equal = #False
Break
EndIf
Next
Next
t = ElapsedMilliseconds() - t
EnableDebugger
Debug "CompareMemoryWithMask sans procedure time = " + Str(t)
;}
On voit bien que si tu recherches la vitesse plutôt que la facilité de programmation tu peux mettre le code dans une macro et utiliser un marqueur pour récupérer le résultat...
[EDIT] : Oups

une petite erreur avec la taille d'un byte -_-, c'est corrigé !
Re: Comment tester *B and *C = *B ? (CompareMemory() ?)
Publié : mar. 23/oct./2012 20:54
par Golfy
Houlà, le code que j'ai pondu n'est peut-être pas très algorithmique par rapport au tien
Je considère toutefois que c'est une solution intermédiaire valable : qu'en penses-tu ?
1) je copie le buffer original
2) je met à zéro les champs sur lesquels il y a un wildcard
3) je compare la copie avec le buffer à chercher
Par contre, mes octets étant compris entre 0 et 255, j'ai préféré PeekA et PokeA... est-ce utile ?
Code : Tout sélectionner
Procedure.i IsSearchedFrame(*Original, chaine$)
Size=Len(chaine$)/2
*B = AllocateMemory(size)
*Copy = AllocateMemory(size)
CopyMemory(*Original, *Copy, size) ; work on a copy !
y = 0
For i=1 To Len(chaine$) Step 2 ; creating mask and search buffer
a$ = Mid(chaine$,i,2) ; 1 byte is 2 car (ie. $E5)
x = Val("$"+Left(a$,1))*16 + Val("$"+Right(a$,1)) ;
PokeA(*B+y,x)
position = FindString(a$,"*") ; mask copy value if wildcard met
If position
If a$="**" Or a$="??"
PokeA(*Copy+y,0)
ElseIf position=1
PokeA(*Copy+y,$0F & PeekA(*Copy+y))
Else
PokeA(*Copy+y,$F0 & PeekA(*Copy+y))
EndIf
EndIf
y+1
Next i
Debug ReadMsg(*B, size)
Debug ReadMsg(*Copy, size)
res = CompareMemory(*B, *Copy, size) ; after that, just compare value
E=FreeMemory(*B)
E=FreeMemory(*Copy)
ProcedureReturn res
EndProcedure
Re: Comment tester *B and *C = *B ? (CompareMemory() ?)
Publié : jeu. 25/oct./2012 21:37
par graph100
ben comme tu utilises des string, ça va être bcp plus lent je pense...
je t'ai filé mon code, si il t'es utile tant mieux ^^
je n'ai pas regardé en détail ce que tu as fait, mais si ça fonctionne selon tes besoins c'est l'essentiel.
Pour le PokeA ou PokeB, je ne pense pas que ça ai de l'importance, (faudrait vérifier) car c'est une histoire d'interprétation d'une même valeur... Donc la comparaison bit à bit est la même.
Par contre dans la même comparaison il faut rester du même coté (pas de pokeA peekB par exemple..)
Je vois que tu utilises une chaine de caractère pour définir ton mask, tu devrais pouvoir faire un truc rapide pour transformer cette chaine en buffer et l'utiliser dans mon code.
Re: Comment tester *B and *C = *B ? (CompareMemory() ?)
Publié : ven. 26/oct./2012 15:48
par Golfy
Merci Graph100 ! tes informations m'ont éclairé... c'est plutôt moi qui suis resté flou sur mon attente exacte :
En fait, j'ai un programme qui envoit des commandes sur un réseau domotique. Le mode de fonctionnement est identique au BUS CAN, ce qui implique des retours de trame à chaque commande envoyée.
Le BUS tourne à 19 kbps max mais par contre, je doit permettre à l'utilisateur de sélectionner une trame attendue (avec des masques).
Le programme étant en mode console, l'utilisateur ne peut envoyer une trame directement, d'où la conversion texte... mais ce n'est executé qu'une fois par commande envoyé (même si mon programme permet d'envoyer plusieurs commandes, dans les fait, les utilisateurs en envoient de une à quatre)
Donc pas de problème de vitesse/performance sur ce programme
Code : Tout sélectionner
G:\VelbusCmd>velbuscmd.exe server:192.168.168.250 port:8080 ERREUR:$06-1 TEMP:$76-1 TEMP:$82-1
VelbusCmd [1.4] Sending to [192.168.168.250-8080]
----------------------------------------------------------
$06 ;0;0;0; (TX-RX-BOFF)
$76 ;16.5;13.5;23.5; (Tcur-Tmin-Tmax)
$82 ;Timeout; (Tcur-Tmin-Tmax)
----------------------------------------------------------
Re: Comment tester *B and *C = *B ? (CompareMemory() ?)
Publié : ven. 26/oct./2012 18:07
par graph100
Ok !
Je suis ravis de voir une application de PB dans un domaine que j'aime bien ! C'est concret.
Donc, si j'ai bien tout lu, ton problème est réglé ? ^^
Re: Comment tester *B and *C = *B ? (CompareMemory() ?)
Publié : ven. 26/oct./2012 20:28
par Golfy
Oui, mon problème est réglé : sur le programme de supervision que je dois développer (Téo & Téa) j'utiliserai une recherche en mode buffer (comme tu l'as montré). Sur le programme VelbusCmd, j'ai l'algo que j'ai décrit ci-dessus.
Sur l'aspect Purebasic dans la domotique, j'ai un programme qui à mon sens pourrait figurer dans les exemples d'applications faites en Purebasic :
http://forum.velleman.eu/viewtopic.php?p=31919#p31919
Et, pour ceux qui veulent voir comment je programme (sans les pieds

), le code source :
http://golfy.free.fr/Velbus/PB_Velbus-S ... server3.pb (programme principal)
http://golfy.free.fr/Velbus/PB_Velbus-Server/Common.pb (forme)
Re: Comment tester *B and *C = *B ? (CompareMemory() ?)
Publié : sam. 27/oct./2012 6:03
par graph100
nickel ^^ j'ai parcouru tout ça rapidement.
C'est sympa ce que tu fais. Par contre le lien pour le site me donne ça :
502 Bad Gateway
Et c'est marrant ^^ on peux voir la température qu'il fait dans la chambre des parents (ta chambre ?!) avec le lien pour les fichiers PB que tu as filé
A quand ça deviens chaud !!
[edit] : tu n'as pas prévu que ton programme puisse être lancé sur un pc qui n'a rien a voir avec un réseau velbus ?
Parce que ça a planté direct à l'ouverture : Message d'erreur puis ensuite, il gère pas l'erreur, ça plante.
Re: Comment tester *B and *C = *B ? (CompareMemory() ?)
Publié : sam. 27/oct./2012 10:28
par Golfy
C'est exact pour les températures : c'est mon premier jet "Teo-Tea" qui permet d'exporter en HTML toutes les 5mn...
Les admins du site
www.olympe.in permettent un hébergement gratuit... mais pas toujours au point
Avec Google, tu pourras voir le cache
Concernant la possibilité de fonctionner sans réseau Velbus... c'est un peu inutile, vu que c'est la raison d'être de PB_Velbus-server
mais il essaye de lire un fichier INI... je vais vérifier qu'il donne un message d'explication...

avant de planter

Re: Comment tester *B and *C = *B ? (CompareMemory() ?)
Publié : dim. 28/oct./2012 18:57
par graph100
Non, mais un programme qui est fini et diffusable ne devrais pas planter aussi facilement
Il faut juste gérer une exception, du genre après le message d'erreur fermer proprement le logiciel
Re: Comment tester *B and *C = *B ? (CompareMemory() ?)
Publié : dim. 28/oct./2012 23:20
par Golfy
Bon sang : tout à fait juste !!!
je viens de repéter une instruction "END" qui était commentée
Honte à moi, quel mauvais débogueur je fais !!!
Merci pour l'avertissement !!!