Page 2 sur 2

Re: Programmation PuraBasic et domotique Velbus

Publié : dim. 13/sept./2009 16:28
par Golfy
Merci pour cette aide précieuse (simplification intéressante !)

Voici un code un peu plus clair incluant une procédure d'envoi (Evenement Velbus : Transmit Push Button) et le traitement du checksum

Pour info, la trame Velbus commence toujours par 4 octets :
$0F (Start ou SOF)
$F8 ou $FB (priorité Haute ou Basse)
$xx (Adresse du module)
$ss (Longueur des données suivantes)
$z1
$z2
$..
$kk (CheckSum)
$04 (EOF)

Code : Tout sélectionner

Enumeration 
	#CanalCOM
	#Window_0
	#Button_0
  #String_0
  #Button_1
  #Editor_0
  #Combo_0
EndEnumeration

Global *Buffer = AllocateMemory(2048)
Global *BufOut = AllocateMemory(1024)

Procedure Open_Window_0()
  If OpenWindow(#Window_0, 216, 0, 318, 300, "Velbus via VelbusLink",  #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_TitleBar )
      ButtonGadget(#Button_0, 20, 20, 70, 20, "ON")
      StringGadget(#String_0, 160, 20, 50, 20, "")
      ButtonGadget(#Button_1, 230, 20, 70, 20, "OFF")
      EditorGadget(#Editor_0, 20, 60, 280, 140)
      ComboBoxGadget(#Combo_0, 20, 240, 280, 20)
  EndIf
EndProcedure
Procedure.s Hexa2(*B,longueur)
	Debug "Longueur Trame (proc Hexa2): "+ Str(longueur) + "  ["+PeekS(*B)+"]"
	r$ = ""
	For t = 0 To longueur
		; Read the buffer from 0 to lengh and remove negative value (& 255) to avoid FFFFFFFFFFFFFx value
	  a$ = Trim(Hex(PeekB(*B+t) & 255))+" "
	  If Len(a$) = 2
	  	a$ = "0"+ a$
	  EndIf
		r$ = r$ + a$
	Next t
	r$ = r$ + Chr(13)+Chr(10)
	ProcedureReturn r$
EndProcedure
Procedure LecturePort()
    Resultat = AvailableSerialPortInput(#CanalCOM)
    If Resultat
    	longueur = ReadSerialPortData(#CanalCOM, *Buffer, Resultat)
    	Commande$ = Hexa2(*Buffer, longueur)
    	;CommandParser(Commande$)
    	Debug Commande$	
    	SetGadgetText(#Editor_0, GetGadgetText(#Editor_0)+Commande$)
    EndIf
EndProcedure
Procedure.i CheckSum(*BufOut,longueur.i)
	somme=0
	For t=0 To longueur
		Somme=Somme+PeekB(*BufOut+t)
	Next t
	Somme = (Somme & $FF) ! $FF
	Somme = Somme + 1
	ProcedureReturn Somme
EndProcedure
Procedure.i SendButton(*B, Amodule.i, Abutton.i, StatusButton.i)
	PokeB(*B+0,$0F)						; Start
	PokeB(*B+1,$F8)						; Priorité
	PokeB(*B+2,Amodule)				; Address module(peek an existing address !)
	PokeB(*B+3,$04)						; Data = 4 bytes (no RTR)
	PokeB(*B+4,$00)						; Push Button Function (H00)
	Select StatusButton
	Case 0	; Just Release
		PokeB(*B+5,$00)						; Just pressed
		PokeB(*B+6,Abutton)				; Just Release
		PokeB(*B+7,$00)						; Long Press
	Case 1	; Just Pressed
		PokeB(*B+5,Abutton)						; Just pressed
		PokeB(*B+6,$00)						; Just Release (NO)
		PokeB(*B+7,$00)						; Long Press (NO)
	Default	; Just Pressed
		PokeB(*B+5,$00)						; Just pressed
		PokeB(*B+6,$00)						; Just Release (NO)
		PokeB(*B+7,Abutton)				; Long Press (NO)
	EndSelect
		
	PokeB(*B+8,CheckSum(*B,8)	)					; Checksum from h0F to Checksum (not included of course)
	PokeB(*B+9,$04)						; ETX (End of Transmission)
	Commande$ = Hexa2(*B, 10)
	Debug "Send => "+Commande$
	ProcedureReturn WriteSerialPortData(#CanalCOM, *B, 10)
EndProcedure
 


If OpenSerialPort(#CanalCOM, "COM9", 9600, #PB_SerialPort_NoParity, 8, 1, #PB_SerialPort_NoHandshake, 1024, 1024)
	Open_Window_0()
	If IsWindow(#WIndow_0) = 0
		CloseSerialPort(#CanalCOM)
		End
	EndIf
  Repeat
    EventID = WaitWindowEvent(20)
    LecturePort()
				    
    If EventID = #PB_Event_Gadget
      Select EventGadget()
        Case #Button_0
        	Debug "Hello_____________________"
        	SendButton(*BufOut, 1,2,1)
        Case #Button_1
         	Debug "Bye_______________________"
        	SendButton(*BufOut, 1,2,0)       
      EndSelect
    EndIf
  Until EventID = #PB_Event_CloseWindow
  CloseSerialPort(#CanalCOM)
Else
	MessageRequester("Erreur","Le port série n'a pas été initialisé",0)
EndIf
Pour ceux qui seront intéressé par le projet, je propose de voir sur le forum Velbus :
http://forum.velleman.be/viewtopic.php?f=13&t=3457

Re: Programmation PuraBasic et domotique Velbus

Publié : lun. 14/sept./2009 6:18
par Golfy
Voilà de quoi interagir sur le BUS :
SetLed sur les Boutons-Poussoirs permet de choisir OFF, ON, Clignotement lent, Clignotement, Clignotement rapide
SwitchRelay sur les modules relais permet de changer l'état en ON ou OFF

Code : Tout sélectionner

; ******************************************************************************
; Velbus communication                                                         *
; Author : D. Roumanet                         Date : 14/09/2009               *
; e-mail : golfy @ free . fr                   Ver. : 1.0 (Purbasic : 4.x)     *
; -----------------------------------------------------------------------------*

Enumeration 
	#CanalCOM
	#Window_0
	#Button_0
  #String_0
  #Button_1
  #Editor_0
  #Combo_0
EndEnumeration

Global *Buffer = AllocateMemory(2048)
Global *BufOut = AllocateMemory(1024)

Procedure Open_Window_0()
  If OpenWindow(#Window_0, 216, 0, 500, 300, "Velbus via VelbusLink",  #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_TitleBar )
      ButtonGadget(#Button_0, 20, 20, 70, 20, "Bouton",#PB_Button_Toggle)
      StringGadget(#String_0, 160, 20, 50, 20, "")
      ButtonGadget(#Button_1, 230, 20, 70, 20, "Relais",#PB_Button_Toggle)
      EditorGadget(#Editor_0, 20, 60, 470, 140)
      ComboBoxGadget(#Combo_0, 20, 240, 280, 20)
  EndIf
EndProcedure
Procedure.s Hexa2(*B,longueur)
	; This procedure transform ASCII string in Hexadecimal string (for human). SPACE car. is separator.
	r$ = ""
	For t = 0 To longueur
		; Read the buffer from 0 to lengh
	  a$ = RSet(Hex(PeekB(*B+t) & $FF),2,"0")+" "		; Rset use to have '$0F' in place of '$F'
		r$ = r$ + a$
	Next t
	r$ = r$ + Chr(13)+Chr(10)												; Add CR+LF characters
	ProcedureReturn r$
EndProcedure
Procedure LecturePort()
  ; ******* NOT FINAL PROCEDURE : JUST HELP TO READ BUS AND SEE MESSAGES ********
  Resultat = AvailableSerialPortInput(#CanalCOM)
  If Resultat
  	longueur = ReadSerialPortData(#CanalCOM, *Buffer, Resultat)
  	Commande$ = Hexa2(*Buffer, longueur)
  	;CommandParser(Commande$)
  	Debug "Rcv  => "+Commande$	
  	Debug "________________"
  	SetGadgetText(#Editor_0, GetGadgetText(#Editor_0)+Commande$)
  EndIf
EndProcedure
Procedure.i CheckSum(*B,longueur.i)
	somme=0														; Initialize Counter
	For t=0 To longueur								; Loop from 0 to checksum byte -1
		Somme=Somme+PeekB(*B+t)					; Adding each byte from the packet
	Next t
	Somme = (Somme & $FF) ! $FF				; As PureBasic as signed integer, need to remove higher value
	Somme = Somme + 1									; (AND operation) and inverse with XOR (!), them add '1'
	ProcedureReturn Somme							; Return the checksum value
EndProcedure
Procedure.i SendButton(*B, Amodule.i, Abutton.i, StatusButton.i)
	PokeB(*B+0,$0F)							; Start
	PokeB(*B+1,$F8)							; Priority
	PokeB(*B+2,Amodule)					; Address module(peek an existing address !)
	PokeB(*B+3,$04)							; Data = 4 bytes (no RTR)
	PokeB(*B+4,$00)							; Push Button Function (H00)
	Select StatusButton
	Case 0											; Status is "Just Release"
		PokeB(*B+5,$00)						; Just pressed (NO)
		PokeB(*B+6,Abutton)				; Just Release ((YES, Button number)
		PokeB(*B+7,$00)						; Long Press (NO)
		
	Case 1											; Status is "Just Pressed"
		PokeB(*B+5,Abutton)				; Just Pressed (YES, Button number)
		PokeB(*B+6,$00)						; Just Release (NO)
		PokeB(*B+7,$00)						; Long Press (NO)
		
	Default											; Status is "Long Press"
		PokeB(*B+5,$00)						; Just pressed (NO)
		PokeB(*B+6,$00)						; Just Release (NO)
		PokeB(*B+7,Abutton)				; Long Press (YES, Button number)
	EndSelect
		
	PokeB(*B+8,CheckSum(*B,8)	)	; Checksum from h0F to Checksum (not included of course)
	PokeB(*B+9,$04)							; ETX (End of Transmission)
	Commande$ = Hexa2(*B, 10)
	Debug "Send => "+Commande$
	ProcedureReturn WriteSerialPortData(#CanalCOM, *B, 10)
EndProcedure
Procedure.i SwitchRelay(*B, Amodule.i, Arelay.i, StatusRelay.i)
	PokeB(*B+0,$0F)						; Start
	PokeB(*B+1,$F8)						; Priority
	PokeB(*B+2,Amodule)				; Address module(peek an existing address !)
	PokeB(*B+3,$02)						; Data = 2 bytes (no RTR)
	Select StatusRelay
	Case 0	; Relay OFF
		PokeB(*B+4,$02)						; OFF
	Default	; Relay ON
		PokeB(*B+4,$01)						; ON
	EndSelect
	PokeB(*B+5,Arelay)					; Relay Number (1,2,4,8 else it's binary : 3 = 1+2 ?)
		
	PokeB(*B+6,CheckSum(*B,5)	)	; Checksum from h0F to Checksum (not included of course)
	PokeB(*B+7,$04)							; ETX (End of Transmission)
	Commande$ = Hexa2(*B, 8)
	Debug "Send => "+Commande$
	ProcedureReturn WriteSerialPortData(#CanalCOM, *B, 8)
EndProcedure
Procedure.i SetLed(*B, Amodule.i, Aled.i, StatusLed.i)
	; OFF=F5, ON=F6, BlinkSlow=F7, BlinkFast=F8, BlinkVeryFast=F9
	;
	PokeB(*B+0,$0F)							; Start
	PokeB(*B+1,$FB)							; Priority
	PokeB(*B+2,Amodule)					; Address module(peek an existing address !)
	PokeB(*B+3,$02)							; Data = 2 bytes (no RTR)
	Select StatusLed
	Case 0											; Clear
		PokeB(*B+4,$F5)						; 
	Case 1											; Always ON
		PokeB(*B+4,$F6)						; 
	Case 2											; Blink Slowly
		PokeB(*B+4,$F7)						; 
	Case 3											; Blink Fast
		PokeB(*B+4,$F8)						; 
	Default											; Blink Very Fast
		PokeB(*B+4,$F9)						; 
	EndSelect
	PokeB(*B+5,Aled)						; LED number
		
	PokeB(*B+6,CheckSum(*B,5)	)	; Checksum from h0F to Checksum (not included of course)
	PokeB(*B+7,$04)							; ETX (End of Transmission)
	Commande$ = Hexa2(*B, 8)
	Debug "Send => "+Commande$
	ProcedureReturn WriteSerialPortData(#CanalCOM, *B, 8)
EndProcedure 


If OpenSerialPort(#CanalCOM, "COM9", 9600, #PB_SerialPort_NoParity, 8, 1, #PB_SerialPort_NoHandshake, 1024, 1024)
	Open_Window_0()
	If IsWindow(#WIndow_0) = 0
		CloseSerialPort(#CanalCOM)
		End
	EndIf
  Repeat
    EventID = WaitWindowEvent(20)
    LecturePort()
				    
    If EventID = #PB_Event_Gadget
      Select EventGadget()
        Case #Button_0
        	Debug "Hello_____________________"
        	SendButton(*BufOut, 1,2,1)
        	SetLed(*BufOut, 1, 3, 2)
        	SetLed(*BufOut, 2, 4, 3)
        Case #Button_1
         	If GetGadgetState(#Button_1) = 1
	         	Debug "Relay OFF______________________"
	        	SwitchRelay(*BufOut, 2,2,0)
	        	;SetGadgetState(#Button_1, 0)       
					Else
	         	Debug "Relay ON_______________________"
	        	SwitchRelay(*BufOut, 2,2,1)       
	        	;SetGadgetState(#Button_1, 1)       
	EndIf
      EndSelect
    EndIf
  Until EventID = #PB_Event_CloseWindow
  CloseSerialPort(#CanalCOM)
Else
	MessageRequester("Erreur","Le port série n'a pas été initialisé",0)
EndIf

Re: Programmation PureBasic et domotique Velbus

Publié : dim. 20/sept./2009 5:39
par Thyphoon
intéressant ! ça avance ! :D

Re: Programmation PureBasic et domotique Velbus

Publié : dim. 20/sept./2009 21:47
par Golfy
En effet... aujourd'hui : la lecture des trames
Résultat :

Code : Tout sélectionner

0FF8010400020000F204
0FFB0102F502FC04
0FFB0208FB02000000000000EF04
0FFB0102F640BD04
0FFB0102F644B904
0FFB0102F640BD04
0FF8020400000200F104
0FF8010400000200F204
0FF8010400010000F304
0FFB0102F501FD04
0FFB0102F501FD04
0FFB0102F501FD04
0FFB0102F501FD04
0FFB0208FB01070000000000E904
0FFB0102F644B904
0FFB0102F640BD04
0FF8020400000100F204
0FF8010400000100F304
Procédure :

Code : Tout sélectionner

Procedure.s Hexa2(*B,longueur)
	; This procedure transform ASCII string in Hexadecimal string (for human). SPACE car. is separator.

	If longueur > 5																				; at least, a 0 byte message should be readable
		taille = PeekB(*B+3)+5															; this procedure would be enhanced with a $0F start test...
		Debug "Len = "+Str(taille)
		If PeekB(*B+taille) = $04														; EOF should be $04 else "bad frame"
			msg$ = ""
			For t = 0 To taille																; Read byte for the first frame
				msg$ = msg$ + RSet(Hex(PeekB(*B+t) & $FF),2,"0")
			Next t
		Else
			Debug Hex(PeekB(*B+taille))+" <> $04"
		EndIf
		
		; first message has been read, message is 1st frame + other message  ;-)
		ProcedureReturn  msg$ + Chr(13)+Chr(10)+Hexa2(*B+taille+1, longueur-(taille+1))
	Else																									; less than 5 bytes left ? frame isn't right
		ProcedureReturn msg$																
	EndIf
EndProcedure
La fonction récursive 8) mérite sûrement quelques corrections et tests complémentaires... :roll: mais pour ce soir, j'ai déjà des noeuds au cerveau :P :mrgreen:

Re: Programmation PureBasic et domotique Velbus

Publié : lun. 01/févr./2010 11:09
par Golfy
Juste un petit point d'avancement : en fait je viens de changer de PC (Win7 sur un quad-core 64 bits Intel) puis de changer d'OS (Win7 me donne vraiment la nausée :x : et pourtant, j'ai toujours bidouillé un max sous WinNT puis W2000 puis WinXP !)

Donc, le même programme testé sous Ubuntu 9.10 fonctionne !!!
Merci Fred et merci à toute l'équipe Purebasic.


:idea: Le seul changement est sur la fonction OpenSerialPort, où il faut remplacer "COMx:" par "/dev/ttyACM0"

Le développement devrait continuer normalement pour fonctionner sur un Fit PC (http://www.fit-pc.com/web/)

Re: Programmation PureBasic et domotique Velbus

Publié : lun. 01/févr./2010 11:43
par Fred
Cool :)

Re: Programmation PureBasic et domotique Velbus

Publié : jeu. 04/févr./2010 16:43
par guismoman33
FRANCHEMENT, FRANCHEMENT, je suis débutant, OK, mais même un confirmer pourrait le dire :


Je tire mon chapeau pour ce programme même si je ne comprend rien...

Re: Programmation PureBasic et domotique Velbus

Publié : jeu. 04/févr./2010 18:13
par venom
Salut,

Si je comprend bien ton post tu joue avec le port parallèle via purebasic c'est bien ça ?
Si c'est sa chapeau l'artichaut :D








@++

Re: Programmation PureBasic et domotique Velbus

Publié : lun. 08/févr./2010 16:30
par poshu
Jouer avec le port parallèle, c'est natif dans pure. Ce qui est fait ici, c'est s'interfacer avec la domotique Velbus (c'est écrit dans le titre); pour faire simple, il s'agit de contrôler des appareils compatibles avec cette norme depuis son PC.

Re: Programmation PureBasic et domotique Velbus

Publié : lun. 08/févr./2010 19:36
par venom
Ah d'accord :wink: merci poshu de ton explication.

En parlant de port parallèle (DB25), chez moi il est afficher dans mon gestionnaire de périphérique, alors que purebasic ne le voie pas :? .
il voie seulement le port COM1 qui lui est bien le port RS232 ? étrange.







@++

Re: Programmation PureBasic et domotique Velbus

Publié : lun. 31/oct./2011 16:31
par Golfy
Re-bonjour à tous :)

Après quelques mois (presque 2 ans en fait) d'interruption, je redémarre mon projet de contrôle domotique.
Du coup, le changement le plus important est la possibilité de lire/écrire le BUS via un serveur qui sert de relais USB / TCP-IP.

Par contre, ma procédure de lecture réseau semble bloquer mon programme (et notamment ma fenêtre) : une idée du pourquoi ?
Le pire étant que le debug ne semble pas être bloqué (réception en temps réel)... 8O

Code : Tout sélectionner


Procedure LectureNet()
  Resultat = ReceiveNetworkData(ConnectionID, *Buffer, 2000)
  If Resultat
    Commande$ = Hexa2(*Buffer, Resultat)
    Debug "Rcv  => "+Commande$
    R = AddGadgetItem(#Editor_0, -1, Commande$)
  EndIf  
EndProcedure

If InitNetwork()
  ConnectionID = OpenNetworkConnection("192.168.168.250",8080)
  If ConnectionID
    Open_Window_0()
    Repeat
      EventID = WaitWindowEvent(20)
      LectureNet()
      If EventID = #PB_Event_Gadget
        Debug "Evènement Fenêtre"
        Select EventGadget()
        Case #Button_0
           Debug "Hello_____________________"
           ;SendButton(*BufOut, 1,2,1)
           ;SetLed(*BufOut, 1, 3, 2)
           ;SetLed(*BufOut, 2, 4, 3)
        EndSelect
      EndIf
    Until EventID = #PB_Event_CloseWindow
  EndIf
EndIf
End

Re: Programmation PureBasic et domotique Velbus

Publié : lun. 31/oct./2011 17:46
par Golfy
J'ai trouvé !

Code : Tout sélectionner

      If NetworkClientEvent(ConnectionID) = #PB_NetworkEvent_Data
        LectureNet()
      EndIf

Re: Programmation PureBasic et domotique Velbus

Publié : ven. 30/déc./2011 22:32
par Golfy
Just a small (but important) update : A new application is running with PureBasic, PB_Velbus-server !
*Zut* je suis sur le forum français...

bon, si Fred cherche toujours des exemples d'applications faites en PureBasic, voici ma pierre à l'édifice (enfin) !
Il s'agit d'un simple serveur capable de recevoir/émettre les données d'un bus domotique (Velbus) vers/depuis plusieurs clients Ethernet (@IP).

voir image sur le forum Velbus :
http://forum.velleman.eu/viewtopic.php? ... 960#p26960

Les forces de l'application :
- évite l'engorgement du bus Velbus (plus lent que Ethernet)
- analyse et renvoit uniquement des trames correctes
- lorsque plusieurs clients Ethernet sont présents, renvoit les messages Velbus vers tous !

Merci Fred pour PureBasic !!!

Re: Programmation PureBasic et domotique Velbus

Publié : lun. 24/sept./2012 22:38
par Golfy
Cette fois, voici le programme en version non-console : les fenêtres et gadgets sont présents :
http://forum.velleman.eu/viewtopic.php? ... 546#p31098

Image

Merci à ceux qui m'aident régulièrement sur ce forum 8)

Re: Programmation PureBasic et domotique Velbus

Publié : mar. 25/sept./2012 0:39
par Ar-S
Bravo à toi pour ce programme.