An other Velbus-server (Purebasic)

You can try this source code : it’s Purebasic code but there is a free version of Purebasic (so you can modify and compile your own code)


; Velbus server 1.0 by Golfy (Purebasic 4.60)
;
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
  Port$ = "COM4"
CompilerElse
  Port$ = "/dev/ttyS0"
CompilerEndIf

OpenConsole()
If OpenSerialPort(0, Port$, 9600, #PB_SerialPort_NoParity, 8, 1, #PB_SerialPort_NoHandshake, 2048, 2048)
	PrintN("open port "+port$+" done")
Else
	PrintN("Erreur port "+port$)
	Delay(2000)
	End
EndIf

If InitNetwork() = 0
	PrintN("Error : Can't initialize the network !")
	Delay(2000)
  End
EndIf

Port = 8080
*BSin = AllocateMemory(4096)
*BSout = AllocateMemory(4096)
*BNin = AllocateMemory(4096)
*BNout = AllocateMemory(4096)

NewList Client.i()

If CreateNetworkServer(0, Port)
	PrintN("Listening on Ethernet port : "+Str(port))
  
  Repeat
      
    SEvent = NetworkServerEvent()
    If SEvent
      ClientID = EventClient()
      Select SEvent
      	Case #PB_NetworkEvent_Connect
      		; new client connected
      		AddElement(Client())
      		Client() = ClientID
      		IP$=IPString(GetClientIP(ClientID))

      		PrintN("Opening Connexion ID "+Str(Client())+" for "+ip$+" (Client Number : "+Str(ListSize(Client()))+")")
      		

      	Case #PB_NetworkEvent_Data
      		; clientID has sent packet
          RXLen = ReceiveNetworkData(ClientID, *BNin, 1024)
          Err = WriteSerialPortData(0, *BNin, RXLen)
          ; Each Client but ClientID receive frame transmit by ClientID
          ForEach Client()
          	If Client() <> ClientID
          		Err = SendNetworkData(Client(), *BNin, RXLen)
          	EndIf
    			Next    	

          PrintN("Net --> "+port$+" ("+Str(RXLen)+" bytes)")
          Delay(RXLen*10)
  
        Case #PB_NetworkEvent_Disconnect
        	ForEach Client()
        		If Client() = ClientID
        			DeleteElement(Client(),1)
        			PrintN("Closing Connexion ID "+Str(Client())+" (Client Number : "+Str(ListSize(Client()))+")")
        		EndIf
        	Next
      EndSelect
    EndIf
    
    Serial = AvailableSerialPortInput(0)
    If Serial
    	RXLen = ReadSerialPortData(0,*BSin,2048)
    	ForEach Client()
    		Err = SendNetworkData(ClientID, *BSin, RXLen)
    		PrintN(port$+"--> Net  ("+Str(RXLen)+" bytes)")
    	Next    	
    EndIf
    
  Until Quit = 1 
  
  CloseNetworkServer(0)
Else
  PrintN("Error : Can't create the server (port in use ?).")
EndIf

  
End   

Bus OFF and Buffer FULL not managed for now but hey… it midnight, I’ve to sleep :slight_smile:

Working hard on a Purebasic Velbus server and trying VelbusLink through it… and do you know ? I’ve see a frame like this :

65 6c 62 75 73 4c 69 6e 6b 20 38 2e 34 2e.....

This frame is received at VelbusLink startup : it probably mean “VelbusLink 8.4.61687” (even if I’ve loose de ‘V’)

But now, here is the PureBasic Velbus-Server

[code]; Velbus server 1.0 by Golfy (Purebasic 4.60)
; v2 -> try to delay message from Ethernet -> Velbus

; Default parameters : COM4 and 8080
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
Port$ = “COM4”
CompilerElse
Port$ = “/dev/ttyS0”
CompilerEndIf
Port = 8080

OpenConsole()
EnableGraphicalConsole(1)

; declare useful procedures
Declare.i AnalyseMessage(*bus,Len.i)
Declare.s Hexa2(*B,longueur.i)
Declare.i LectureNet()
Declare.i CheckSum(*B,longueur.i)

; if parameter are transmit after commandline
If FindString(UCase(ProgramParameter(0)),“H”,1) Or FindString(UCase(ProgramParameter(0)),"?",1)
PrintN(“PB_Velbus-server.exe SERIALport NETWORKport (ex: PB_Velbus-server.exe COM4 8131)”)
PrintN(“PB_Velbus-server.exe default = COM4 and 8080”)
Input()
End
EndIf

If ProgramParameter(0) : port$ = ProgramParameter(0) : EndIf
If ProgramParameter(1) : port = Val(ProgramParameter(1)) : EndIf

If OpenSerialPort(0, Port$, 9600, #PB_SerialPort_NoParity, 8, 1, #PB_SerialPort_NoHandshake, 2048, 2048)
PrintN(“PB_Velbus-Server v2.0 : open port “+port$+” done”)
Else
PrintN("Erreur port "+port$)
Delay(2000)
End
EndIf

If InitNetwork() = 0
PrintN(“Error : Can’t initialize the network !”)
Delay(2000)
End
EndIf

*BSin = AllocateMemory(4096)
*BNin = AllocateMemory(4096)
*BFull = AllocateMemory(7)
*BReady = AllocateMemory(7)

PokeB(*BFull+0,$0F)
PokeB(*BFull+1,$F8)
PokeB(*BFull+2,$00)
PokeB(*BFull+3,$01)
PokeB(*BFull+4,$0B)
PokeB(*BFull+5,$ED)
PokeB(*BFull+6,$04)

PokeB(*BReady+0,$0F)
PokeB(*BReady+1,$F8)
PokeB(*BReady+2,$00)
PokeB(*BReady+3,$01)
PokeB(*BReady+4,$0C)
PokeB(*BReady+5,$EC)
PokeB(*BReady+6,$04)

Structure Vmsg
Len.i
*cmd
EndStructure

Global NewList messages.Vmsg()
Global NewList Client.i()
Global TXNET.q
Global TXBUS.q

If CreateNetworkServer(0, Port)
PrintN(" ] Listening on Ethernet port : "+Str(port))
HauteurCurseur = 0
d = ElapsedMilliseconds()

Repeat
; server is alive : show date (french format)
If Date() <> dd
dd = Date()
ConsoleLocate(60,2)
PrintN(FormatDate("%dd/%mm%/%yyyy %hh:%ii:%ss",Date()))
EndIf

; Send bufferised messages with 60ms delay
If ListSize(messages()) And ElapsedMilliseconds()-d > 40
	Err = FirstElement(messages())
	Err = WriteSerialPortData(0, messages()\cmd, messages()\len)
	err = FreeMemory(messages()\cmd)
	Err = DeleteElement(messages(),1)
	d = ElapsedMilliseconds()
EndIf

SEvent = NetworkServerEvent()
If SEvent
 	ConsoleLocate(0,2)
	PrintN("[N]")    	
  ClientID = EventClient()
  Select SEvent
  	Case #PB_NetworkEvent_Connect
  		; new client connected
  		ConsoleLocate(0,3)
  		AddElement(Client())
  		Client() = ClientID
  		IP$=IPString(GetClientIP(ClientID))
  		PrintN("Opening Connexion ID "+Str(Client())+" for "+ip$+" (Client Number : "+Str(ListSize(Client()))+")")
  		
  	Case #PB_NetworkEvent_Data
  		RXLen = ReceiveNetworkData(ClientID, *BNin, 4096)
  		If RXLen > 5
   			N = AnalyseMessage(*BNin,RXLen)
   			Locate(30,2)
    			PrintN("Ethernet-> "+Str(RXLen)+"     ")
   			;PrintN("NET --> VelBUS : "+Str(N)+" messages received ("+Str(RXLen)+" bytes received)")
  		EndIf
  		
  	Case #PB_NetworkEvent_Disconnect
  		; client has diconnected
  		ConsoleLocate(0,3)
    	ForEach Client()
    		If Client() = ClientID
    			DeleteElement(Client(),1)
    			PrintN("Closing Connexion ID "+Str(ClientID)+" (Client Number : "+Str(ListSize(Client()))+")")
    		EndIf
    	Next
  EndSelect
EndIf

; SERIAL TO NETWORK ==========================================================================
Serial = AvailableSerialPortInput(0)
If Serial
	ConsoleLocate(0,2)
	PrintN("[S]")
	RXLen = ReadSerialPortData(0,*BSin,Serial)
	If RXlen = Serial
    	ForEach Client()
    		Err = SendNetworkData(Client(), *BSin, RXLen)
    	Next
    Else
    	Locate(45,2)
    	PrintN("Velbus-> "+Str(RXLen)+"     ")
    EndIf
EndIf	

Until Quit = 1

CloseNetworkServer(0)
Else
PrintN(“Error : Can’t create the server (port in use ?).”)
EndIf

End

; ------
; Procedure for Network/BUS command
; _______________________________________________________________________________________________________
Procedure.i AnalyseMessage(*bus,full.i)
; Format de trame :
; OF FB ** RL xx xx xx CK 04 - 0F FB ** …
; 12 34 56 78 9A …
stx = 0
etx = 0
lng = 0
counter = 0
t = 0
Repeat
If PeekB(*bus+t) & $FF = $0F
counter+1
fixlen = 4
varlen = PeekB(*bus+t+3) & $0F
fintrame = t+fixlen+varlen+1
crcloc = fintrame-1
tlen = fixlen+varlen+2
crc = checksum(*bus+t,tlen-3)
If PeekB(*bus+fintrame) = $04 And (PeekB(*bus+crcloc) & $FF)=crc
AddElement(messages())
messages()\len = tlen
messages()\Cmd = AllocateMemory(messages()\len)
CopyMemory(*bus+t,messages()\cmd,messages()\len)
t = t+(messages()\len-2)
EndIf
EndIf
t = t + 1

Until t=>full
ProcedureReturn ListSize(messages())

EndProcedure
; _______________________________________________________________________________________________________

Procedure.i CheckSum(*B,longueur.i)
somme=0 ; Initialize Counter
For tr=0 To longueur ; Loop from 0 to checksum byte -1
Somme=Somme+PeekB(*B+tr) & $FF ; Adding each byte from the packet
Next tr
Somme = (Somme & $FF) ! $FF ; As PureBasic use 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
[/code]

[quote=“Golfy”]Working hard on a Purebasic Velbus server and trying VelbusLink through it… and do you know ? I’ve see a frame like this :

65 6c 62 75 73 4c 69 6e 6b 20 38 2e 34 2e.....

This frame is received at VelbusLink startup : it probably mean “VelbusLink 8.4.61687” (even if I’ve loose de ‘V’)
[/quote]

That is a requirement for HomeCenter; I will remove this in the next version for the ‘Network connection’ option since it is not strictly needed there

When parsing you should check if you really have a packet:

  • Does it start with 0F?
  • Is the checksum correct?
  • Does it end with 04?

The way I parse with VelbusLink is:

  • Search for a start-of-packet (0F)
  • Wait until I have 4 bytes in the buffer (so we have all header bytes, including the byte that tells us the number of data bytes)
  • Perform some checks on the 4 bytes that I already have
  • Wait until I have 4 bytes + number of databytes + 2 (checksum and ETX) = the entire packet
  • Check if the checksum is correct and the packet ends with ETX
  • Continue doing the above until we no longer have 4 bytes in the buffer (= nothing useable until the next read)

If something doesn’t check out, we discard the first byte and keep on going

Golfy,

check the following dir. In this dir you’ll find my C code of a velbus gateway. Also is there a code for reading out my temp sensors (temp.pl) written in perl. In the perl script you’ll find a routine “check_valid”. This is a possible way to check the message.

velbus dir

greets

ps: in the dir graph you’'ll find my read outs of my sensors, the red background is when the heating is on.

Thanks VEL448, check are done here (find $04 at end of frame (calculation for the len) and check CRC) :

If PeekB(*bus+fintrame) = $04 And (PeekB(*bus+crcloc) & $FF)=crc

In my case serial port always send me at least one full message. Since long time with purebasic, I try to find a non complete frame without success : maybe it’s the way that Purebasic works with buffer… never a truncated frame at present time :slight_smile:
However, I found more big frame (like 0F…04 00 00 00 00)

The best advantage of my Velbus-server, is sending packet from Ethernet network to Velbus network : each message is delayed in the time while Ethernet buffer works at full speed.
I’ve to do that because VelbusLink 8.4 isn’t able to synchronize full modules (66 on my network) or scan Velbus network when configured with velbus-server and Ethernet :frowning:

If I understand, discard first byte is enough ?

Here are my PureBasic Velbus-Server 2.0 :slight_smile:

golfy.free.fr/Velbus/PB_Velbus-server.exe

And here, is a picture on how it works : PB_Velbus-server COMx YYYY (where x is a valid COM port on PC and YYYY is an ethernet port number)
below, you can see an example with : PB_Velbus-server COM4 8080

And for all coders, here is the source code :
golfy.free.fr/Velbus/PB_Velbus-server.pb

Basic functions are :

  • PB_Velbus-server manage speed (each message from Ethernet to Velbus are delayed to avoid full buffer or bus down)
  • Each messages from Ethernet are checked (lengh, checksum, …)
  • Multiples Ethernet clients are supported (they all receive frame from Velbus bus but from other clients too)
  • Could be launch with parameter (possible to create a shortcut in start menu)

**Happy new year to all enjoyed guys which are working on programing nice applications with Velbus and (of course) to all Velbus employees who works hard to help us ** :slight_smile:

Edit :
[size=85]
V2.1 : manage programs that are making too much errors on transmitting (rate : 10 errors/mn)
V2.2 : checksum calculation correction (could block “Quick Read” message on some modules)
[/size]

Thanks a lot for sharing this! I’ll check it out soon.

Hey guys : Velbus bandwidth isn’t use in same way for each module !
My VMB4RY can transmits up to 10-12kbps
My VMB8PB can transmits at around 6 kbps if build > 0649, else 1 kbps
etc…

very funny to see :sunglasses:

idd, noticed this also a time ago:-).
Even with 2 relay modules but other software version.

When reading there are two possibilities:

  • Ask for a memory dump, receive memory in blocks of four bytes (fastest)
  • Ask for each memory block, receive each memory block (slowest)

When writing there are two possibilities

  • Write four bytes at a time, verify four bytes at a time (fastest)
  • Write each byte, verify each byte (slowest)

By the way, the PB_Velbus-server has been upgraded : for those who want to see before try :
http://golfy.olympe.in/PB_Velbus-server.jpg

EXE file is here (DOS mode) : golfy.olympe.in/PB_Velbus-server.exe (27 kB)
Purebasic code is here : golfy.olympe.in/PB_Velbus-server.pb

To start with windows, you can create an INI file like this : golfy.olympe.in/PB_Velbus-server.ini (and put a link in Start menu of Windows)

Hope this will help you ! my goal is to promote VELBUS as a great open domotic system :slight_smile:

Hi There,

I’m new at this and I got a little problem.
I have set up the server and it is connected with my velbus.
when i try to controll with the velbus plex tool everyting works perfectly.

now, I want to controll my system with Openremote.
so i send a raw package over TCP/IP (0ff8100400080000dd04) from Openremote.
the server receives the package but it’s not transfered to the velbus…

What am i doing wrong?

Thanks!!!

The server include a checksum control : if your checksum is bad, it wouldn’t transmit it (and should write in red that there is a problem).

The checksum is correct

Make sure that the packet is understood by the module that you are sending it to (test it in VelbusLink first)
Make sure that the packet is sent correctly in its raw form by your OpenRemote

The data I send is copied from the flex application and it works perfectly from there…
the “eth ->” counter counts the same amount of data as I send it from flex.
but it isn’t transfered to the bus…

is there a way for monitorring my input?

Thanks!

[quote=“Golfy”]
I’ve to develop it but it would not be to hard… thanks for your feedback !
I would probably publish it tonight (with -debug parameter…)[/quote]

Well, I’m working a little bit more than previous… because console mode take around 50% of CPU… will try to use Window GUI application (still able to compile on Linux or Windows but would be more expressive with frames and logs). Not for tonight, sorry… but will be better than Console version

http://golfy.olympe.in/PB_Velbus-server_init.jpg

I’m trying to make it work with openremote…
this is android compatible and easy to design…

problem is poor feedback capabillaties
but they are working on this…

[size=150]Hey ! PB Velbus-Server 3.0 is out ![/size]
http://golfy.olympe.in/PB_Velbus-server_3.0.jpg

  1. Less CPU consumption rather old console version (old = around 50%, new = around 2%) !!!
  2. Now you can save the log list as TXT file (PB_Velbus-server.log in current directory)… log list is limited to 250 events (for now… could be enhanced in future)
  3. Error messages will be shown in red (with the right icon From/To Velbus)
  4. You can filter unwanted message (see image for example, [Filter] button must be Toggle)
  5. You know IP addresses connected to the server
  6. You can… exit ! Ok this version isn’t fully functional but all the needed are present… I will improve it as soon as possible.

Please give me your feedback !
Download link : golfy.olympe.in/PB_Velbus-server.exe
ini file is (for example) :

COMx 8080

Et en français ça sert à quoi en fait ?
J’ai essayé de m’y connecter en rentrant Com3 qui correspond à mon branchement USB, ca se connecte, mais rien n’apparait dedans :frowning:

Je me connecte sur mon navigateur ensuite en localhost:8080/
Mon ip local apparait alors dans le programme, mais au niveau du navigateur ca charge en boucle. Et rien ne se passe.

Bion je débute en Velbus, sur une petite install de test, le gros ne va arriver que dans les mois à venir (construction en cours)
Donc je ne comprend pas encore tout ^^

[quote=“Daweb”]Et en français ça sert à quoi en fait ?
J’ai essayé de m’y connecter en rentrant Com3 qui correspond à mon branchement USB, ca se connecte, mais rien n’apparait dedans :frowning:

Je me connecte sur mon navigateur ensuite en localhost:8080/
Mon ip local apparait alors dans le programme, mais au niveau du navigateur ca charge en boucle. Et rien ne se passe.

Bion je débute en Velbus, sur une petite install de test, le gros ne va arriver que dans les mois à venir (construction en cours)
Donc je ne comprend pas encore tout ^^[/quote]

Ce programme n’est qu’un pont (bridge) entre le monde IP et le monde BUS CAN VELBUS : il n’est utile que pour permettre à plusieurs programmes d’accéder à un seul module VMB1USB ou VMB1RS.

Pour comprendre, vous pouvez connecter le programme VelbusLink (choisir “Network connection (TCP/IP)” à la place de “Direct cable connection”)
Vous pouvez aussi télécharger le programme décrit dans ce topic : Velbus via command line

L’intérêt est de pouvoir l’utiliser sur un PC allumé en permanence (devient ‘serveur’) et donc d’accéder aux fonctions Velbus depuis n’importe quel autre ordinateur de votre réseau (LAN ou WiFi). Il est même possible l’utiliser via Internet (WAN) mais pour cela il faut modifier la table NAT de votre routeur/firewall/box ADSL…