Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 51 additions & 51 deletions drivers/DeepSmart/deepsmart/src/config.lua
Original file line number Diff line number Diff line change
@@ -1,51 +1,51 @@
local config = {}
-- device info
-- NOTE: In the future this information
-- may be submitted through the Developer
-- Workspace to avoid hardcoded values.
config.DEVICE_PROFILE={}
config.DEVICE_PROFILE[3]='Ac.v1'
config.DEVICE_PROFILE[4]='Heater.v1'
config.DEVICE_PROFILE[53]='Newfan.v1'
config.DEVICE_TYPE='LAN'
-- SSDP Config
config.MC_ADDRESS='239.255.255.250'
config.MC_PORT=1900
config.MC_TIMEOUT=6
config.ENUM = {}
config.ENUM.AC = 3
config.ENUM.HEATER = 4
config.ENUM.NEWFAN = 53
--device addrtype
config.AC = {}
config.AC.ONOFF = 0
config.AC.MODE = 1
config.AC.FAN = 2
config.AC.SETTEMP = 3
config.AC.TEMP = 4
config.HEATER = {}
config.HEATER.ONOFF = 0
config.HEATER.SETTEMP = 2
config.HEATER.TEMP = 3
config.NEWFAN = {}
config.NEWFAN.ONOFF = 0
config.NEWFAN.FAN = 1
config.DEVICE = {}
config.DEVICE.ONOFF = 0
config.FIELD = {}
config.FIELD.DP2KNX = "dp2knx"
config.FIELD.DPENUM = "dpenum"
config.FIELD.DEVICES = "devices"
config.FIELD.IP = "ip"
config.FIELD.INVALID = "invalid"
return config
local config = {}
-- device info
-- NOTE: In the future this information
-- may be submitted through the Developer
-- Workspace to avoid hardcoded values.
config.DEVICE_PROFILE={}
config.DEVICE_PROFILE[3]='Ac.v1'
config.DEVICE_PROFILE[4]='Heater.v1'
config.DEVICE_PROFILE[53]='Newfan.v1'
config.DEVICE_TYPE='LAN'

-- SSDP Config
config.MC_ADDRESS='239.255.255.250'
config.MC_PORT=1900
config.MC_TIMEOUT=6

config.ENUM = {}
config.ENUM.AC = 3
config.ENUM.HEATER = 4
config.ENUM.NEWFAN = 53


--device addrtype
config.AC = {}
config.AC.ONOFF = 0
config.AC.MODE = 1
config.AC.FAN = 2
config.AC.SETTEMP = 3
config.AC.TEMP = 4

config.HEATER = {}
config.HEATER.ONOFF = 0
config.HEATER.SETTEMP = 2
config.HEATER.TEMP = 3

config.NEWFAN = {}
config.NEWFAN.ONOFF = 0
config.NEWFAN.FAN = 1

config.DEVICE = {}
config.DEVICE.ONOFF = 0

config.FIELD = {}
config.FIELD.DP2KNX = "dp2knx"
config.FIELD.DPENUM = "dpenum"
config.FIELD.DEVICES = "devices"
config.FIELD.IP = "ip"
config.FIELD.INVALID = "invalid"


return config
90 changes: 45 additions & 45 deletions drivers/DeepSmart/deepsmart/src/discovery.lua
Original file line number Diff line number Diff line change
@@ -1,45 +1,45 @@
local log = require('log')
local Wisers = require "deepsmart.wisers"
local ssdp = require('ssdp')
local net_utils = require('st.net_utils')
local disco = {}
-----------------------
-- app discover new bridges or new devices
disco.ssdp_discovery_callback = function(uuid, ip)
if (not net_utils.validate_ipv4_string(ip) or uuid == nil) then
log.warn(string.format('ip (%s) or uuid (%s) is invalid', ip, uuid))
return
end
-- add discovered wiser
Wisers.add_wiser(uuid, ip, nil)
Wisers.refresh_wiser(uuid)
end
-- check whether bridge ip changed
disco.ssdp_checkip_callback = function(uuid, ip)
if (not net_utils.validate_ipv4_string(ip) or uuid == nil) then
log.warn(string.format('ip (%s) or uuid (%s) is invalid', ip, uuid))
return
end
-- check uuid(if added)
Wisers.update_wiser_ip(uuid, ip)
end
-- Discovery service which will
-- invoke the above private functions.
-- - find_device
-- - parse_ssdp
-- - fetch_device_info
-- - create_device
--
-- This resource is linked to
-- driver.discovery and it is
-- automatically called when
-- user scan devices from the
-- SmartThings App.
function disco.start(driver, opts, cons)
log.info('in discover start...')
ssdp.search(disco.ssdp_discovery_callback)
log.info('===== DEVICE DISCOVER DEVICES OVER')
end
return disco
local log = require('log')
local Wisers = require "deepsmart.wisers"
local ssdp = require('ssdp')
local net_utils = require('st.net_utils')

local disco = {}
-----------------------
-- app discover new bridges or new devices
disco.ssdp_discovery_callback = function(uuid, ip)
if (not net_utils.validate_ipv4_string(ip) or uuid == nil) then
log.warn(string.format('ip (%s) or uuid (%s) is invalid', ip, uuid))
return
end
-- add discovered wiser
Wisers.add_wiser(uuid, ip, nil)
Wisers.refresh_wiser(uuid)
end
-- check whether bridge ip changed
disco.ssdp_checkip_callback = function(uuid, ip)
if (not net_utils.validate_ipv4_string(ip) or uuid == nil) then
log.warn(string.format('ip (%s) or uuid (%s) is invalid', ip, uuid))
return
end
-- check uuid(if added)
Wisers.update_wiser_ip(uuid, ip)
end
-- Discovery service which will
-- invoke the above private functions.
-- - find_device
-- - parse_ssdp
-- - fetch_device_info
-- - create_device
--
-- This resource is linked to
-- driver.discovery and it is
-- automatically called when
-- user scan devices from the
-- SmartThings App.
function disco.start(driver, opts, cons)
log.info('in discover start...')
ssdp.search(disco.ssdp_discovery_callback)
log.info('===== DEVICE DISCOVER DEVICES OVER')
end

return disco
178 changes: 89 additions & 89 deletions drivers/DeepSmart/deepsmart/src/ssdp.lua
Original file line number Diff line number Diff line change
@@ -1,89 +1,89 @@
local socket = require('socket')
local log = require('log')
local config = require('config')
local SSDP = {}
local DEEPSMART_SSDP_SEARCH_TERM = "DEEPSMART-ARM"
-----------------------
-- SSDP Response parser
local function parse_ssdp(data)
local res = {}
res.status = data:sub(0, data:find('\r\n'))
for k, v in data:gmatch('([%w-]+): ([%a+-: /=]+)') do
local key = k:lower()
log.info('parse key '..key..' val '..v)
res[key] = v
end
return res
end
-- This function enables a UDP
-- Socket and broadcast a single
-- M-SEARCH request, i.e., it
-- must be looped appart.
function SSDP.search(callback)
local bridges = {}
-- UDP socket initialization
local upnp = socket.udp()
local _,err = upnp:setsockname('0.0.0.0', 0)
if err then
log.error(string.format("udp socket failure setsockname: %s", err))
return false,bridges,err
end
-- use broadcast to find wisers as wifi router's group cast is forbidden by default(need login to router to start group cast)
upnp:setoption('broadcast', true)
local timeout = socket.gettime() + config.MC_TIMEOUT + 1
local mx = 2
-- broadcasting request
log.info('===== SCANNING NETWORK...')
local multicast_msg = table.concat({
"M-SEARCH * HTTP/1.1",
"HOST: 255.255.255.255:1900",
'MAN: "ssdp:discover"', -- yes, there are really supposed to be quotes in this one
string.format("MX: %s", mx),
string.format("ST: %s", DEEPSMART_SSDP_SEARCH_TERM),
"\r\n"
}, "\r\n")
local _, err = upnp:sendto(multicast_msg, config.MC_ADDRESS, config.MC_PORT)
if err then
log.error(string.format("udp socket failure sendto: %s", err))
return false,bridges,err
end
while true do
-- Socket will wait n seconds
-- based on the s:setoption(n)
-- to receive a response back.
local time_remaining = math.max(0, timeout - socket.gettime())
upnp:settimeout(time_remaining)
local res,ip = upnp:receivefrom()
if (res ~= nil) then
log.info('recv wiser '..res..' from '..ip)
local headers = parse_ssdp(res)
-- Device metadata
local usn = headers.usn
local uuid = usn:match("uuid:(%d+)::")
if (uuid ~= nil) then
log.info('usn '..usn..' uuid '..uuid..' ip '..ip)
if callback ~= nil and type(callback) == "function" then
callback(uuid, ip)
end
bridges[uuid] = ip
end
else
break
end
end
log.info('===== SCANNING NETWORK OVER')
-- close udp socket
upnp:close()
return true,bridges,nil
end
return SSDP
local socket = require('socket')
local log = require('log')
local config = require('config')




local SSDP = {}

local DEEPSMART_SSDP_SEARCH_TERM = "DEEPSMART-ARM"
-----------------------
-- SSDP Response parser
local function parse_ssdp(data)
local res = {}
res.status = data:sub(0, data:find('\r\n'))
for k, v in data:gmatch('([%w-]+): ([%a+-: /=]+)') do
local key = k:lower()
log.info('parse key '..key..' val '..v)
res[key] = v
end
return res
end


-- This function enables a UDP
-- Socket and broadcast a single
-- M-SEARCH request, i.e., it
-- must be looped appart.
function SSDP.search(callback)
local bridges = {}
-- UDP socket initialization
local upnp = socket.udp()
local _,err = upnp:setsockname('0.0.0.0', 0)
if err then
log.error(string.format("udp socket failure setsockname: %s", err))
return false,bridges,err
end
-- use broadcast to find wisers as wifi router's group cast is forbidden by default(need login to router to start group cast)
upnp:setoption('broadcast', true)
local timeout = socket.gettime() + config.MC_TIMEOUT + 1
local mx = 2
-- broadcasting request
log.info('===== SCANNING NETWORK...')
local multicast_msg = table.concat({
"M-SEARCH * HTTP/1.1",
"HOST: 255.255.255.255:1900",
'MAN: "ssdp:discover"', -- yes, there are really supposed to be quotes in this one
string.format("MX: %s", mx),
string.format("ST: %s", DEEPSMART_SSDP_SEARCH_TERM),
"\r\n"
}, "\r\n")
local _, err = upnp:sendto(multicast_msg, config.MC_ADDRESS, config.MC_PORT)
if err then
log.error(string.format("udp socket failure sendto: %s", err))
return false,bridges,err
end
while true do
-- Socket will wait n seconds
-- based on the s:setoption(n)
-- to receive a response back.
local time_remaining = math.max(0, timeout - socket.gettime())
upnp:settimeout(time_remaining)
local res,ip = upnp:receivefrom()
if (res ~= nil) then
log.info('recv wiser '..res..' from '..ip)
local headers = parse_ssdp(res)
-- Device metadata
local usn = headers.usn
local uuid = usn:match("uuid:(%d+)::")
if (uuid ~= nil) then
log.info('usn '..usn..' uuid '..uuid..' ip '..ip)
if callback ~= nil and type(callback) == "function" then
callback(uuid, ip)
end
bridges[uuid] = ip
end
else
break
end
end
log.info('===== SCANNING NETWORK OVER')
-- close udp socket
upnp:close()

return true,bridges,nil
end


return SSDP
5 changes: 5 additions & 0 deletions drivers/Nexmosphere/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
name: "NexmosphereEdgeDriver_A"
packageKey: "NexmosphereEdgeDriver_A"
permissions:
lan: {}
discovery: {}
Loading