Comment tester *B and *C = *B ? (CompareMemory() ?)

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Golfy
Messages : 423
Inscription : mer. 25/août/2004 15:14
Localisation : Grenoble
Contact :

Comment tester *B and *C = *B ? (CompareMemory() ?)

Message 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)
Purebasic 5.30 full sous Windows XP (x86) et Win7 (64 bits), Linux Debian. Orientation réseaux, domotique
http://golfy.olympe.in/Teo-Tea/
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

Re: Comment tester *B and *C = *B ? (CompareMemory() ?)

Message 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 :oops: une petite erreur avec la taille d'un byte -_-, c'est corrigé !
_________________________________________________
Mon site : CeriseCode (Attention Chantier perpétuel ;))
Golfy
Messages : 423
Inscription : mer. 25/août/2004 15:14
Localisation : Grenoble
Contact :

Re: Comment tester *B and *C = *B ? (CompareMemory() ?)

Message par Golfy »

Houlà, le code que j'ai pondu n'est peut-être pas très algorithmique par rapport au tien :oops:

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
Purebasic 5.30 full sous Windows XP (x86) et Win7 (64 bits), Linux Debian. Orientation réseaux, domotique
http://golfy.olympe.in/Teo-Tea/
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

Re: Comment tester *B and *C = *B ? (CompareMemory() ?)

Message 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.
_________________________________________________
Mon site : CeriseCode (Attention Chantier perpétuel ;))
Golfy
Messages : 423
Inscription : mer. 25/août/2004 15:14
Localisation : Grenoble
Contact :

Re: Comment tester *B and *C = *B ? (CompareMemory() ?)

Message 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)
----------------------------------------------------------
Purebasic 5.30 full sous Windows XP (x86) et Win7 (64 bits), Linux Debian. Orientation réseaux, domotique
http://golfy.olympe.in/Teo-Tea/
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

Re: Comment tester *B and *C = *B ? (CompareMemory() ?)

Message 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é ? ^^
_________________________________________________
Mon site : CeriseCode (Attention Chantier perpétuel ;))
Golfy
Messages : 423
Inscription : mer. 25/août/2004 15:14
Localisation : Grenoble
Contact :

Re: Comment tester *B and *C = *B ? (CompareMemory() ?)

Message 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 :wink: ), 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)
Purebasic 5.30 full sous Windows XP (x86) et Win7 (64 bits), Linux Debian. Orientation réseaux, domotique
http://golfy.olympe.in/Teo-Tea/
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

Re: Comment tester *B and *C = *B ? (CompareMemory() ?)

Message 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.
_________________________________________________
Mon site : CeriseCode (Attention Chantier perpétuel ;))
Golfy
Messages : 423
Inscription : mer. 25/août/2004 15:14
Localisation : Grenoble
Contact :

Re: Comment tester *B and *C = *B ? (CompareMemory() ?)

Message 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 :roll:
mais il essaye de lire un fichier INI... je vais vérifier qu'il donne un message d'explication... :idea: avant de planter :mrgreen:
Purebasic 5.30 full sous Windows XP (x86) et Win7 (64 bits), Linux Debian. Orientation réseaux, domotique
http://golfy.olympe.in/Teo-Tea/
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

Re: Comment tester *B and *C = *B ? (CompareMemory() ?)

Message par graph100 »

Non, mais un programme qui est fini et diffusable ne devrais pas planter aussi facilement :lol:
Il faut juste gérer une exception, du genre après le message d'erreur fermer proprement le logiciel
_________________________________________________
Mon site : CeriseCode (Attention Chantier perpétuel ;))
Golfy
Messages : 423
Inscription : mer. 25/août/2004 15:14
Localisation : Grenoble
Contact :

Re: Comment tester *B and *C = *B ? (CompareMemory() ?)

Message par Golfy »

Bon sang : tout à fait juste !!!
je viens de repéter une instruction "END" qui était commentée 8O

Honte à moi, quel mauvais débogueur je fais !!!
:oops:

Merci pour l'avertissement !!!
Purebasic 5.30 full sous Windows XP (x86) et Win7 (64 bits), Linux Debian. Orientation réseaux, domotique
http://golfy.olympe.in/Teo-Tea/
Répondre