
LogicMachine als Gateway zu RESOL über VBus-Protokoll


Example: LogicMachine as gateway to RESOL via VBus protocol
Task
This examples will show how to integrate RESOL solar automation solution into common KNX/ModBus/BACnet/EnOCean/DALI visualization through LogicMachine.
For integration you need to have VBus LAN adapter connected to your RESOL system.
Direct commands are not yet implemented in this example.
User Libraries
Add the following scripts in Scripting –> User libraries.
luavbuspacket.lua
- local luavbuspacket = {}
- luavbuspacket_mt = { __index = luavbuspacket }
-
- luavbuspacket.srcAddress = 0 -- source address (2 byte)
- luavbuspacket.dstAddress = 0 -- destination address (2 byte)
- luavbuspacket.protoVersion = 1 -- protocol version 0x10 o 0x20 or 0x30 (1 byte)
- --- packet version
- luavbuspacket.version = 0 -- version (1 byte)
- luavbuspacket.command = 0 -- command (2 bytes)
- luavbuspacket.payloads = 0 -- number of payloads (2 bytes)
- luavbuspacket.payloadsData = nil -- 4-byte payloads
- luavbuspacket.dataPointID = nil -- ID of the data point (2 bytes)
- luavbuspacket.dataPointValue = nil -- value of data point ( 4 bytes)
- luavbuspacket.checksum = 0 -- CRC (1 bytes)
- luavbuspacket.profile = nil -- vbus profile
- luavbuspacket.profileData = nil -- vbus profile data
-
-
-
- luavbuspacket.mt = {} -- metatable
-
- --- Creates a new instance of luavbuspacket
- -- @author Luca Palazzo
- -- @return instance of luavbuspacket
- --
- function luavbuspacket.new ( o )
- luavbuspacket.log ( DEBUG3, string.format ( "luavbuspacket.new( %s )", o ) )
- local _vp = o or {}
- luavbuspacket.log ( DEBUG4, string.format ( "luavbuspacket.new(): %s", _vp ) )
-
- setmetatable(_vp, luavbuspacket_mt )
- luavbuspacket_mt.__tostring = luavbuspacket.tostring
- return _vp
- end
-
- --- Stringify luavbuspacket object. Use in __tostring metatable field too
- -- @author Luca Palazzo
- -- @param packet the instance of luavbuspacket to stringify
- -- @return string-fied version of luavbuspacket
- function luavbuspacket.tostring( packet )
- luavbuspacket.log ( DEBUG3, "luavbuspacket.tostring( packet )" )
- -- if ( packet == nil or packet.srcAddress == nil ) then
- -- return "nil packet"
- -- end
- vbus_packet_string = string.format( "VBus frame source address 0x%04x destination address 0x%04x version 0x%02x command 0x%02x checksum 0x%04x payloads %d", packet.srcAddress, packet.dstAddress, packet.version, packet.command, packet.checksum, packet.payloads )
- luavbuspacket.log ( DEBUG3, vbus_packet_string )
- return vbus_packet_string
- end
-
- function luavbuspacket.profileprint( packet )
- luavbuspacket.log ( DEBUG3, "luavbuspacket.profilestring( packet )" )
- vbus_packet_string = ""
- if ( packet == nil ) then
- return "no packet"
- end
-
- if ( packet.profile == nil ) then
- return "no profile"
- end
-
- if ( packet.profile.objects == nil ) then
- return "no objects"
- end
-
- for k, v in pairs( packet.profile.objects ) do
- local offset = tonumber(v[1])
- local length = tonumber(v[2])
- local unknown = tonumber(v[3])
- local name = v[4]
- local factor = tonumber(v[5])
- local unit = v[6]
- if (unit==nil) then
- unit = ""
- end
- luavbuspacket.log( DEBUG4, string.format ("Offset %d length %d", offset, length ) )
-
- local value = 0
- packet_length = string.len(packet.payloadsData)
- -- PacketDump(data)
- for index = 1, length, 1 do
- if ( offset+index > packet_length ) then
- luavbuspacket.log ( DEBUG3, string.format ("Buffer overrun (length %d)", packet_length ) )
- break
- end
- luavbuspacket.log ( DEBUG4, string.format ("Getting byte %d at offset %d with value 0x%02x", index, offset, packet.payloadsData:byte(offset+index) ) )
- -- print ("Adding "..data:byte(offset+index+1)*(256^index))
- value = value + packet.payloadsData:byte(offset+index)*(256^(index-1))
- -- print ( "Value: " .. value .. " index " .. index )
- end
-
-
- luavbuspacket.log ( DEBUG2, string.format ("luavbus:packetParseV1(): name %s Value %02.2f %s", name, value*factor, unit ) )
- vbus_packet_string = vbus_packet_string .. string.format ("%s: %02.2f %s ", name, value*factor, unit )
-
- end
- -- vbus_packet_string = string.format( "VBus frame source address 0x%04x destination address 0x%04x version 0x%02x command 0x%02x checksum 0x%04x", packet.srcAddress, packet.dstAddress, packet.version, packet.command, packet.checksum )
- luavbuspacket.log ( DEBUG4, vbus_packet_string )
- return vbus_packet_string
- end
-
- function luavbuspacket.getProfileData( self )
- luavbuspacket.log ( DEBUG3, "luavbuspacket.getProfileData()" )
-
- if ( self.profile == nil ) then
- luavbuspacket.log ( WARN, "Packet ha no profile" )
- return nil
- end
-
- self.profileData = {}
-
- for k, object in pairs( self.profile.objects ) do
- local offset = tonumber(object[1])
- local length = tonumber(object[2])
- local unknown = tonumber(object[3])
- local name = object[4]
- local factor = tonumber(object[5])
- local unit = object[6]
- local value = 0
-
- if (unit==nil) then
- unit = ""
- end
- luavbuspacket.log( DEBUG4, string.format ("Offset %d length %d", offset, length ) )
-
- packet_length = string.len(self.payloadsData)
- for index = 1, length, 1 do
- if ( offset+index > packet_length ) then
- luavbuspacket.log ( WARN, string.format ("Buffer overrun (length %d)", packet_length ) )
- break
- end
- luavbuspacket.log ( DEBUG2, string.format ("Getting byte %d at offset %d with value 0x%02x", index, offset, self.payloadsData:byte(offset+index) ) )
- -- print ("Adding "..data:byte(offset+index+1)*(256^index))
- value = value + self.payloadsData:byte(offset+index)*(256^(index-1))
- -- print ( "Value: " .. value .. " index " .. index )
- end
- data = {}
- data.name = name
- data.factor = factor
- data.unit = unit
- data.value = value*factor
- table.insert(self.profileData, data)
- luavbuspacket.log ( DEBUG2, string.format ("luavbuspacket.getProfileData(): name %s value %.02f",data.name, data.value ) )
-
- end
- end
-
- function luavbuspacket.log ( level, ... )
- local prefix = ""
- local log_string = ""
- if ( log_level ~= nil and level ~= nil and level <= log_level ) then
- if ( level == ERR ) then
- log_string = "ERROR"
- elseif ( level == WARN ) then
- log_string = "WARN"
- elseif ( level == INFO ) then
- log_string = "INFO"
- elseif ( level == DEBUG1 ) then
- log_string = "DEBUG1"
- elseif ( level == DEBUG2 ) then
- log_string = "DEBUG2"
- elseif ( level == DEBUG3 ) then
- log_string = "DEBUG3"
- elseif ( level == DEBUG4 ) then
- log_string = "DEBUG4"
- elseif ( level == DEBUG5 ) then
- log_string = "DEBUG5"
- else
- log_string = "UNKNOWN"
- end
- print ( log_string .. ": " .. ... )
- end
- end
-
- return luavbuspacket
vbusprofiles.lua you define your device profiles as you wish
- vbusprofiles = {}
-
- vbusprofiles[0] =
- '{
- "id": "0x7E11",
- "name": "DeltaSol MX [Controller]",
- "objects": [
- [ 0, 2, 0, "Temperature sensor 1", 0.1, "В°C" ],
- [ 2, 2, 0, "Temperature sensor 2", 0.1, "В°C" ],
- [ 4, 2, 0, "Temperature sensor 3", 0.1, "В°C" ],
- [ 6, 2, 0, "Temperature sensor 4", 0.1, "В°C" ],
- [ 8, 2, 0, "Temperature sensor 5", 0.1, "В°C" ],
- [ 10, 2, 0, "Temperature sensor 6", 0.1, "В°C" ],
- [ 12, 2, 0, "Temperature sensor 7", 0.1, "В°C" ],
- [ 14, 2, 0, "Temperature sensor 8", 0.1, "В°C" ],
- [ 16, 2, 0, "Temperature sensor 9", 0.1, "В°C" ],
- [ 18, 2, 0, "Temperature sensor 10", 0.1, "В°C" ],
- [ 20, 2, 0, "Temperature sensor 11", 0.1, "В°C" ],
- [ 22, 2, 0, "Temperature sensor 12", 0.1, "В°C" ],
- [ 24, 2, 0, "Temperature sensor 13", 0.1, "В°C" ],
- [ 26, 2, 0, "Temperature sensor 14", 0.1, "В°C" ],
- [ 28, 2, 0, "Temperature sensor 15", 0.1, "В°C" ],
- [ 30, 2, 0, "Irridiation sensor 16", 1, "W/mВІ" ],
- [ 32, 2, 0, "Temperature sensor 17", 0.1, "В°C" ],
- [ 34, 2, 0, "Temperature sensor 18", 0.1, "В°C" ],
- [ 36, 2, 0, "Temperature sensor 19", 0.1, "В°C" ],
- [ 38, 2, 0, "Temperature sensor 20", 0.1, "В°C" ],
- [ 40, 4, 0, "Volume flow rate sensor 13", 1, "l/h" ],
- [ 44, 4, 0, "Volume flow rate sensor 14", 1, "l/h" ],
- [ 48, 4, 0, "Volume flow rate sensor 15", 1, "l/h" ],
- [ 52, 4, 0, "Volume flow rate sensor 17", 1, "l/h" ],
- [ 56, 4, 0, "Volume flow rate sensor 18", 1, "l/h" ],
- [ 60, 4, 0, "Volume flow rate sensor 19", 1, "l/h" ],
- [ 64, 4, 0, "Volume flow rate sensor 20", 1, "l/h" ],
- [ 68, 2, 0, "Pressure sensor 17", 0.01, "bar" ],
- [ 70, 2, 0, "Pressure sensor 18", 0.01, "bar" ],
- [ 72, 2, 0, "Pressure sensor 19", 0.01, "bar" ],
- [ 74, 2, 0, "Pressure sensor 20", 0.01, "bar" ],
- [ 76, 1, 0, "Pump speed relay 1", 1, "%" ],
- [ 77, 1, 0, "Pump speed relay 2", 1, "%" ],
- [ 78, 1, 0, "Pump speed relay 3", 1, "%" ],
- [ 79, 1, 0, "Pump speed relay 4", 1, "%" ],
- [ 80, 1, 0, "Pump speed relay 5", 1, "%" ],
- [ 81, 1, 0, "Pump speed relay 6", 1, "%" ],
- [ 82, 1, 0, "Pump speed relay 7", 1, "%" ],
- [ 83, 1, 0, "Pump speed relay 8", 1, "%" ],
- [ 84, 1, 0, "Pump speed relay 9", 1, "%" ],
- [ 85, 1, 0, "Pump speed relay 10", 1, "%" ],
- [ 86, 1, 0, "Pump speed relay 11", 1, "%" ],
- [ 87, 1, 0, "Pump speed relay 12", 1, "%" ],
- [ 88, 1, 0, "Pump speed relay 13", 1, "%" ],
- [ 89, 1, 0, "Pump speed relay 14", 1, "%" ],
- [ 90, 2, 0, "Unknown", 1 ],
- [ 92, 4, 0, "System date", 1 ],
- [ 96, 4, 0, "Error mask", 1 ]
- ]
- }'
-
- return vbusprofiles
Resident program
- for _, searcher in ipairs(package.searchers or package.loaders) do
- name = "luavbus"
- local loader = searcher(name)
- if type(loader) == 'function' then
- package.preload[name] = loader
- vbus = require (name)
- break
- end
- name = "user.luavbus"
- local loader = searcher(name)
- if type(loader) == 'function' then
- package.preload[name] = loader
- vbus = require (name)
- break
- end
- end
-
- log_level = WARN
- if ( vbus == nil ) then
- log ( "VBus modules not available")
-
- end
- vbus.new(nil, TCPIP, "vbus" )
-
- vbus.remote_host = "192.168.168.19"
- vbus.remote_port = "7053"
- vbus.password = "vbus"
-
- vbus:connect()
-
- -- filter = { srcAddress = 0x7e11, dstAddress = 0x0010 }
- -- filter = { command = 0x200 }
-
- packets = vbus:waitData(filter, 30 )
-
- if (packets ~= nil ) then
- log( string.format ( "Returned %d packets", #packets ) )
- for key, packet in pairs(packets) do
- -- print ( string.format ( "Packet: %s", packet ) )
- -- print ( packet:profileprint() )
- if ( packet.profileData ~= nil) then
- for k, data in pairs ( packet.profileData ) do
- if ( data.factor < 1 ) then
- log( string.format ( "Name %s Value %.02f %s", data.name, data.value, data.unit ) )
- else
- log( string.format ( "Name %s Value %d %s", data.name, data.value, data.unit ) )
- end
- end
-
- end
- end
- else
- log( "No packet!!!")
- end
Please consult LogicMachine forum VBus thread for more functionality and updated scripts.
Created by Luca Palazzo