This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm that you accept these cookies being set.

what about Obix
#1
IS it planned to develop Obix gateway like you did with Bacnet ?

What do you think about it.
-----------
FRANCE SMARTHOME & SMARTBUILDING INTEGRATION
SE ECO EXPERT
Reply
#2
by our information people are not using Obix too widely. You can realize same tasks on web services.
Maybe you can provide your arguments why it is worth to add support of Obix?
Thanks!
Reply
#3
no it was just a question, because I readed this:
http://www.knx.org/fileadmin/downloads/0...ebsite.pdf

And in this doc, Obix looks more open... It was just in order to have your though
-----------
FRANCE SMARTHOME & SMARTBUILDING INTEGRATION
SE ECO EXPERT
Reply
#4
(03.03.2016, 10:00)domotiqa Wrote: no it was just a question, because I readed this:
http://www.knx.org/fileadmin/downloads/0...ebsite.pdf

And in this doc, Obix looks more open... It was just in order to have your though

Hi Domotiqa,

Here are 2 functions i use to communicate with our SmartStruxure Lite controller with oBIX. Maybe you can use it.

-- function to get data from mpm
function get_data_from_mpm(mpm_settings,object,item)
  local url = "http://" .. mpm_settings.username .. ":" .. mpm_settings.password .. "@" .. mpm_settings.ip .. "/obix/network/" .. mpm_settings.node .. "/DEV" .. mpm_settings.instance .. "/" .. object .. "/" .. item
  local b, c, h = mpm.request(url)
  local value = b:match([[val="(.-)"]])
  local value = tonumber(value)
  return value
end

-- function to post data to mpm
function post_data_to_mpm(mpm_settings,object,item,value)
  local url = "http://" .. mpm_settings.username .. ":" .. mpm_settings.password .. "@" .. mpm_settings.ip .. "/obix/network/" .. mpm_settings.node .. "/DEV" .. mpm_settings.instance .. "/" .. object .. "/" .. item .. "/"
  local reqBody = [[<intl val="]] .. value .. [["/>]]
  local headers = {["Content-Type"] = "text/xml", ["Content-Length"] = #reqBody}
  local respTable = {}
  local returnList = {client = {}, code = {}, headers = {}, status = {}}
  local source=ltn12.source.string(reqBody)
  local sink=ltn12.sink.table(respTable)
  local result = mpm.request{url=url, method="POST", source=source, sink=sink, headers=headers}
  return result
end

BR,

Erwin van der Zwart
Reply
#5
cool !!
Thank for the info
-----------
FRANCE SMARTHOME & SMARTBUILDING INTEGRATION
SE ECO EXPERT
Reply
#6
(05.03.2016, 14:00)domotiqa Wrote: cool !!
Thank for the info

You will need to add this: local mpm = require('socket.http')   before using the mpm.request. The request is made to a basic auhtentication server.

I have a mpm.digest libary if you need digest login.

Have fun with it (;

BR,

Erwin van der Zwart
Reply
#7
good job, Erwin! Smile
Reply
#8
thanks to Erwin van der Zwart, I am glad to post a complete oBIX module for  integration with SmartStruxure Lite including Digest Authentication user library.

1. oBIX to MPM with digest - use as event or resident based script


Code:
1234567891011121314151617181920212223
--====================================================================================================== --******************************** MPM OBIX CONNECTION WITH DIGEST SUPPORT ***************************-- --************************ Version 1.0 Created by Erwin van der Zwart 08-01-2016 *********************-- --====================================================================================================== require('user.mpm_functions') -- See this library for mpm number(s) with valid credentials and IP settings -- Select MPM (mpm number, autoresolve node id) mpm_settings = get_mpm_settings(1, true) -- get data from mpm (mpm settings, object, item) result = get_data_from_mpm(mpm_settings, "AV61", "Present_Value") log(result) -- post data to mpm (mpm number, object, item, value) post_data_to_mpm(mpm_settings, "AV61", "Present_Value", 111) -- get data from mpm (mpm settings, object, item) result = get_data_from_mpm(mpm_settings, "AV62", "Present_Value") log(result) -- post data to mpm (mpm number, object, item, value) post_data_to_mpm(mpm_settings, "AV62", "Present_Value", 222)


 2. user.mpm_functions for oBIX to MPM with digest - user libary 1

Code:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
--====================================================================================================== --******************************* MPM FUNCTION LIBRARY WITH DIGEST SUPPORT ***************************-- --************************ Version 1.0 Created by Erwin van der Zwart 08-01-2016 *********************-- --====================================================================================================== local mpm = require "user.mpm_digest" function get_mpm_settings(mpm_number,autoresolve)    function resolve_node()      local url = "http://" .. mpm_username .. ":" .. mpm_password .. "@" .. mpm_ip      local b, c, h = mpm.request(url)      -- resolve node id automaticly (if not found we will use above but that one can be wrong)      if h then        mpm_node_id = string.sub(h.server, 1, 7)      end      return mpm_node_id  end    --======================================================================================================  --**************************************** Put here your MPM settings ********************************--  --======================================================================================================    if mpm_number == 1 then -- Select MPM 1    mpm_ip = '192.168.10.205'    mpm_username = 'admin'    mpm_password = 'Schneider'    mpm_node_id = 'N004EAB'    mpm_instance = 100  elseif mpm_number == 2 then -- Select MPM 2    mpm_ip = '192.168.10.206'    mpm_username = 'admin'    mpm_password = 'Schneider'    mpm_node_id = 'N005EAB'    mpm_instance = 150  elseif mpm_number == 3 then -- Select MPM 3    mpm_ip = '192.168.10.207'    mpm_username = 'admin'    mpm_password = 'Schneider'    mpm_node_id = 'N006EAB'    mpm_instance = 200  else -- Select MPM with default settings (node ID is resolved automaticly)    mpm_ip = '10.50.80.3'    mpm_username = 'admin'    mpm_password = 'admin'    mpm_node_id =  'N000000'    autoresolve = true    mpm_instance = 100  end    --======================================================================================================  --******************************************** End of MPM settings ***********************************--  --======================================================================================================    MPM_Settings = {ip = mpm_ip, username = mpm_username, password = mpm_password, node = mpm_node_id, instance = mpm_instance}    if autoresolve then      MPM_Settings.node = resolve_node()  end  return MPM_Settings end -- function to get data from mpm function get_data_from_mpm(mpm_settings,object,item)  local url = "http://" .. mpm_settings.username .. ":" .. mpm_settings.password .. "@" .. mpm_settings.ip .. "/obix/network/" .. mpm_settings.node .. "/DEV" .. mpm_settings.instance .. "/" .. object .. "/" .. item  local b, c, h = mpm.request(url)  local value = b:match([[val="(.-)"]])  local value = tonumber(value)  return value end -- function to post data to mpm function post_data_to_mpm(mpm_settings,object,item,value)  local url = "http://" .. mpm_settings.username .. ":" .. mpm_settings.password .. "@" .. mpm_settings.ip .. "/obix/network/" .. mpm_settings.node .. "/DEV" .. mpm_settings.instance .. "/" .. object .. "/" .. item .. "/"  local reqBody = [[<intl val="]] .. value .. [["/>]]  local headers = {["Content-Type"] = "text/xml", ["Content-Length"] = #reqBody}  local respTable = {}  local returnList = {client = {}, code = {}, headers = {}, status = {}}  local source=ltn12.source.string(reqBody)  local sink=ltn12.sink.table(respTable)  local result = mpm.request{url=url, method="POST", source=source, sink=sink, headers=headers}  return result end

3. user.mpm_digest for oBIX to MPM with digest - user libary 2

Code:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
--====================================================================================================== --******************************* MPM DIGEST LIBRARY FOR DIGEST MD5 SUPPORT **************************-- --************************ Version 1.0 Created by Erwin van der Zwart 08-01-2016 *********************-- --====================================================================================================== local md5sum = nil local md5 = {} local char, byte, format, rep, sub =  string.char, string.byte, string.format, string.rep, string.sub local bit_or, bit_and, bit_not, bit_xor, bit_rshift, bit_lshift local ok, bit = pcall(require, 'bit') if ok then  bit_or, bit_and, bit_not, bit_xor, bit_rshift, bit_lshift = bit.bor, bit.band, bit.bnot, bit.bxor, bit.rshift, bit.lshift else  ok, bit = pcall(require, 'bit32')  if ok then    bit_not = bit.bnot    local tobit = function(n)      return n <= 0x7fffffff and n or -(bit_not(n) + 1)    end    local normalize = function(f)      return function(a,b) return tobit(f(tobit(a), tobit(b))) end    end    bit_or, bit_and, bit_xor = normalize(bit.bor), normalize(bit.band), normalize(bit.bxor)    bit_rshift, bit_lshift = normalize(bit.rshift), normalize(bit.lshift)  else    local function tbl2number(tbl)      local result = 0      local power = 1      for i = 1, #tbl do        result = result + tbl[i] * power        power = power * 2      end      return result    end    local function expand(t1, t2)      local big, small = t1, t2      if(#big < #small) then        big, small = small, big      end      for i = #small + 1, #big do        small[i] = 0      end    end    local to_bits    bit_not = function(n)      local tbl = to_bits(n)      local size = math.max(#tbl, 32)      for i = 1, size do        if(tbl[i] == 1) then          tbl[i] = 0        else          tbl[i] = 1        end      end      return tbl2number(tbl)    end    to_bits = function (n)      if(n < 0) then        return to_bits(bit_not(math.abs(n)) + 1)      end      local tbl = {}      local cnt = 1      local last      while n > 0 do        last      = n % 2        tbl[cnt]  = last        n         = (n-last)/2        cnt       = cnt + 1      end      return tbl    end    bit_or = function(m, n)      local tbl_m = to_bits(m)      local tbl_n = to_bits(n)      expand(tbl_m, tbl_n)      local tbl = {}      for i = 1, #tbl_m do        if(tbl_m[i]== 0 and tbl_n[i] == 0) then          tbl[i] = 0        else          tbl[i] = 1        end      end      return tbl2number(tbl)    end    bit_and = function(m, n)      local tbl_m = to_bits(m)      local tbl_n = to_bits(n)      expand(tbl_m, tbl_n)      local tbl = {}      for i = 1, #tbl_m do        if(tbl_m[i]== 0 or tbl_n[i] == 0) then          tbl[i] = 0        else          tbl[i] = 1        end      end      return tbl2number(tbl)    end    bit_xor = function(m, n)      local tbl_m = to_bits(m)      local tbl_n = to_bits(n)      expand(tbl_m, tbl_n)      local tbl = {}      for i = 1, #tbl_m do        if(tbl_m[i] ~= tbl_n[i]) then          tbl[i] = 1        else          tbl[i] = 0        end      end      return tbl2number(tbl)    end    bit_rshift = function(n, bits)      local high_bit = 0      if(n < 0) then        n = bit_not(math.abs(n)) + 1        high_bit = 0x80000000      end      local floor = math.floor      for i=1, bits do        n = n/2        n = bit_or(floor(n), high_bit)      end      return floor(n)    end    bit_lshift = function(n, bits)      if(n < 0) then        n = bit_not(math.abs(n)) + 1      end      for i=1, bits do        n = n*2      end      return bit_and(n, 0xFFFFFFFF)    end  end end local function lei2str(i)  local f=function (s) return char( bit_and( bit_rshift(i, s), 255)) end  return f(0)..f(8)..f(16)..f(24) end local function str2bei(s)  local v=0  for i=1, #s do    v = v * 256 + byte(s, i)  end  return v end local function str2lei(s)  local v=0  for i = #s,1,-1 do    v = v*256 + byte(s, i)  end  return v end local function cut_le_str(s,...)  local o, r = 1, {}  local args = {...}  for i=1, #args do    table.insert(r, str2lei(sub(s, o, o + args[i] - 1)))    o = o + args[i]  end  return r end local swap = function (w) return str2bei(lei2str(w)) end local function hex2binaryaux(hexval)  return char(tonumber(hexval, 16)) end local function hex2binary(hex)  local result, _ = hex:gsub('..', hex2binaryaux)  return result end local CONSTS = {  0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,  0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,  0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,  0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,  0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,  0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,  0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,  0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,  0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,  0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,  0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,  0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,  0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,  0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,  0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,  0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,  0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 } local f=function (x,y,z) return bit_or(bit_and(x,y),bit_and(-x-1,z)) end local g=function (x,y,z) return bit_or(bit_and(x,z),bit_and(y,-z-1)) end local h=function (x,y,z) return bit_xor(x,bit_xor(y,z)) end local i=function (x,y,z) return bit_xor(y,bit_or(x,-z-1)) end local z=function (f,a,b,c,d,x,s,ac)  a=bit_and(a+f(b,c,d)+x+ac,0xFFFFFFFF)  return bit_or(bit_lshift(bit_and(a,bit_rshift(0xFFFFFFFF,s)),s),bit_rshift(a,32-s))+b end local function transform(A,B,C,D,X)  local a,b,c,d=A,B,C,D  local t=CONSTS  a=z(f,a,b,c,d,X[ 0], 7,t[ 1])  d=z(f,d,a,b,c,X[ 1],12,t[ 2])  c=z(f,c,d,a,b,X[ 2],17,t[ 3])  b=z(f,b,c,d,a,X[ 3],22,t[ 4])  a=z(f,a,b,c,d,X[ 4], 7,t[ 5])  d=z(f,d,a,b,c,X[ 5],12,t[ 6])  c=z(f,c,d,a,b,X[ 6],17,t[ 7])  b=z(f,b,c,d,a,X[ 7],22,t[ 8])  a=z(f,a,b,c,d,X[ 8], 7,t[ 9])  d=z(f,d,a,b,c,X[ 9],12,t[10])  c=z(f,c,d,a,b,X[10],17,t[11])  b=z(f,b,c,d,a,X[11],22,t[12])  a=z(f,a,b,c,d,X[12], 7,t[13])  d=z(f,d,a,b,c,X[13],12,t[14])  c=z(f,c,d,a,b,X[14],17,t[15])  b=z(f,b,c,d,a,X[15],22,t[16])  a=z(g,a,b,c,d,X[ 1], 5,t[17])  d=z(g,d,a,b,c,X[ 6], 9,t[18])  c=z(g,c,d,a,b,X[11],14,t[19])  b=z(g,b,c,d,a,X[ 0],20,t[20])  a=z(g,a,b,c,d,X[ 5], 5,t[21])  d=z(g,d,a,b,c,X[10], 9,t[22])  c=z(g,c,d,a,b,X[15],14,t[23])  b=z(g,b,c,d,a,X[ 4],20,t[24])  a=z(g,a,b,c,d,X[ 9], 5,t[25])  d=z(g,d,a,b,c,X[14], 9,t[26])  c=z(g,c,d,a,b,X[ 3],14,t[27])  b=z(g,b,c,d,a,X[ 8],20,t[28])  a=z(g,a,b,c,d,X[13], 5,t[29])  d=z(g,d,a,b,c,X[ 2], 9,t[30])  c=z(g,c,d,a,b,X[ 7],14,t[31])  b=z(g,b,c,d,a,X[12],20,t[32])  a=z(h,a,b,c,d,X[ 5], 4,t[33])  d=z(h,d,a,b,c,X[ 8],11,t[34])  c=z(h,c,d,a,b,X[11],16,t[35])  b=z(h,b,c,d,a,X[14],23,t[36])  a=z(h,a,b,c,d,X[ 1], 4,t[37])  d=z(h,d,a,b,c,X[ 4],11,t[38])  c=z(h,c,d,a,b,X[ 7],16,t[39])  b=z(h,b,c,d,a,X[10],23,t[40])  a=z(h,a,b,c,d,X[13], 4,t[41])  d=z(h,d,a,b,c,X[ 0],11,t[42])  c=z(h,c,d,a,b,X[ 3],16,t[43])  b=z(h,b,c,d,a,X[ 6],23,t[44])  a=z(h,a,b,c,d,X[ 9], 4,t[45])  d=z(h,d,a,b,c,X[12],11,t[46])  c=z(h,c,d,a,b,X[15],16,t[47])  b=z(h,b,c,d,a,X[ 2],23,t[48])  a=z(i,a,b,c,d,X[ 0], 6,t[49])  d=z(i,d,a,b,c,X[ 7],10,t[50])  c=z(i,c,d,a,b,X[14],15,t[51])  b=z(i,b,c,d,a,X[ 5],21,t[52])  a=z(i,a,b,c,d,X[12], 6,t[53])  d=z(i,d,a,b,c,X[ 3],10,t[54])  c=z(i,c,d,a,b,X[10],15,t[55])  b=z(i,b,c,d,a,X[ 1],21,t[56])  a=z(i,a,b,c,d,X[ 8], 6,t[57])  d=z(i,d,a,b,c,X[15],10,t[58])  c=z(i,c,d,a,b,X[ 6],15,t[59])  b=z(i,b,c,d,a,X[13],21,t[60])  a=z(i,a,b,c,d,X[ 4], 6,t[61])  d=z(i,d,a,b,c,X[11],10,t[62])  c=z(i,c,d,a,b,X[ 2],15,t[63])  b=z(i,b,c,d,a,X[ 9],21,t[64])  return A+a,B+b,C+c,D+d end function md5.sumhexa(s)  local msgLen = #s  local padLen = 56 - msgLen % 64  if msgLen % 64 > 56 then padLen = padLen + 64 end  if padLen == 0 then padLen = 64 end  s = s .. char(128) .. rep(char(0),padLen-1) .. lei2str(8*msgLen) .. lei2str(0)  assert(#s % 64 == 0)  local t = CONSTS  local a,b,c,d = t[65],t[66],t[67],t[68]  for i=1,#s,64 do    local X = cut_le_str(sub(s,i,i+63),4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4)    assert(#X == 16)    X[0] = table.remove(X,1)    a,b,c,d = transform(a,b,c,d,X)  end  return format("%08x%08x%08x%08x",swap(a),swap(b),swap(c),swap(d)) end function md5.sum(s)  return hex2binary(md5.sumhexa(s)) end do -- select MD5 library  local ok, mod = pcall(require, "crypto")  if ok then    local digest = (mod.evp or mod).digest    if digest then      md5sum = function(str) return digest("md5", str) end    end  end  if not md5sum then      local md5 = (type(mod) == "table") and mod or md5      md5sum = md5.sumhexa or md5.digest  end  if not md5sum then    ok = pcall(require, "digest") -- last because using globals    if ok and md5 then md5sum = md5.digest end  end end local s_http = require "socket.http" local s_url = require "socket.url" local ltn12 = require "ltn12" local hash = function(...)  return md5sum(table.concat({...}, ":")) end local parse_header = function(h)  local r = {}  for k,v in (h .. ','):gmatch("(%w+)=(.-),") do    if v:sub(1, 1) == '"' then -- strip quotes      r[k:lower()] = v:sub(2, -2)    else r[k:lower()] = v end  end  return r end local make_digest_header = function(t)  local s = {}  local x  for i=1,#t do    x = t[i]    if x.unquote then      s[i] =  x[1] .. '=' .. x[2]    else      s[i] = x[1] .. '="' .. x[2] .. '"'    end  end  return "Digest " .. table.concat(s, ', ') end local hcopy = function(t)  local r = {}  for k,v in pairs(t) do r[k] = v end  return r end local _request = function(t)  if not t.url then error("missing URL") end  local url = s_url.parse(t.url)  local user, password = url.user, url.password  if not (user and password) then    error("missing credentials in URL")  end  url.user, url.password, url.authority, url.userinfo = nil, nil, nil, nil  t.url = s_url.build(url)  local ghost_source  if t.source then    local ghost_chunks = {}    local ghost_capture = function(x)      if x then ghost_chunks[#ghost_chunks+1] = x end      return x    end    local ghost_i = 0    ghost_source = function()      ghost_i = ghost_i+1      return ghost_chunks[ghost_i]    end    t.source = ltn12.source.chain(t.source, ghost_capture)  end  local b, c, h = s_http.request(t)  if (c == 401) and h["www-authenticate"] then    local ht = parse_header(h["www-authenticate"])    assert(ht.realm and ht.nonce and ht.opaque)    if ht.qop ~= "auth" then      return nil, string.format("unsupported qop (%s)", tostring(ht.qop))    end    if ht.algorithm and (ht.algorithm:lower() ~= "md5") then      return nil, string.format("unsupported algo (%s)", tostring(ht.algorithm))    end    local nc, cnonce = "00000001", string.format("%08x", os.time())    local uri = s_url.build{path = url.path, query = url.query}    local method = t.method or "GET"    local response = hash(      hash(user, ht.realm, password),      ht.nonce,      nc,      cnonce,      "auth",      hash(method, uri)    )    t.headers = t.headers or {}    t.headers.authorization = make_digest_header{      {"username", user},      {"realm", ht.realm},      {"nonce", ht.nonce},      {"uri", uri},      {"cnonce", cnonce},      {"nc", nc, unquote=true},      {"qop", "auth"},      {"algorithm", "MD5"},      {"response", response},      {"opaque", ht.opaque},    }    if not t.headers.cookie and h["set-cookie"] then      local cookie = (h["set-cookie"] .. ";"):match("(.-=.-)[;,]")      if cookie then        t.headers.cookie = "$Version: 0; " .. cookie .. ";"      end    end    if t.source then t.source = ghost_source end    b, c, h = s_http.request(t)    return b, c, h  else return b, c, h end end local request = function(x)  local _t = type(x)  if _t == "table" then    return _request(hcopy(x))  elseif _t == "string" then    local r = {}    local _, c, h = _request{url = x, sink = ltn12.sink.table(r)}    return table.concat(r), c, h  else error(string.format("unexpected type %s", _t)) end end return {  request = request, }
Reply


Forum Jump: