-
Notifications
You must be signed in to change notification settings - Fork 1
/
Velux-Active-Shutter.fqa
211 lines (211 loc) · 34 KB
/
Velux-Active-Shutter.fqa
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
{
"name": "Velux Active integration",
"type": "com.fibaro.rollerShutter",
"apiVersion": "1.2",
"initialProperties": {
"viewLayout": {
"$jason": {
"body": {
"header": {
"style": {
"height": "0"
},
"title": "velux-active-shutter"
},
"sections": {
"items": [
{
"components": [
{
"max": "100",
"min": "0",
"name": "slider",
"style": {
"weight": "1.2"
},
"text": "",
"type": "slider",
"visible": true
},
{
"style": {
"weight": "0.5"
},
"type": "space"
}
],
"style": {
"weight": "1.2"
},
"type": "vertical"
},
{
"components": [
{
"components": [
{
"name": "button1",
"style": {
"weight": "0.33"
},
"text": "Zatrzymaj ruch",
"type": "button",
"visible": true
},
{
"name": "button2",
"style": {
"weight": "0.33"
},
"text": "Szukaj urządzeń",
"type": "button",
"visible": true
},
{
"name": "button3",
"style": {
"weight": "0.33"
},
"text": "Odśwież dane",
"type": "button",
"visible": true
}
],
"style": {
"weight": "1.2"
},
"type": "horizontal"
},
{
"style": {
"weight": "0.5"
},
"type": "space"
}
],
"style": {
"weight": "1.2"
},
"type": "vertical"
},
{
"components": [
{
"name": "label",
"style": {
"weight": "1.2"
},
"text": "Velux Active integration",
"type": "label",
"visible": true
},
{
"style": {
"weight": "0.5"
},
"type": "space"
}
],
"style": {
"weight": "1.2"
},
"type": "vertical"
}
]
}
},
"head": {
"title": "velux-active-shutter"
}
}
},
"uiCallbacks": [
{
"callback": "setPositionEvent",
"eventType": "onChanged",
"name": "slider"
},
{
"callback": "stopEvent",
"eventType": "onReleased",
"name": "button1"
},
{
"callback": "searchDevicesEvent",
"eventType": "onReleased",
"name": "button2"
},
{
"callback": "refreshDataEvent",
"eventType": "onReleased",
"name": "button3"
}
],
"quickAppVariables": [
{
"name": "Username",
"type": "string",
"value": ""
},
{
"name": "Password",
"type": "password",
"value": ""
},
{
"name": "HomeID",
"type": "string",
"value": ""
},
{
"name": "GatewayID",
"type": "string",
"value": ""
},
{
"name": "ModuleID",
"type": "string",
"value": ""
}
],
"typeTemplateInitialized": true
},
"files": [
{
"name": "main",
"isMain": true,
"isOpen": true,
"content": "\n--[[\nVelux Active integration\n@author ikubicki\n]]\n\nfunction QuickApp:onInit()\n self.config = Config:new(self)\n self.velux = Velux:new(self.config)\n self.i18n = i18n:new(api.get(\"/settings/info\").defaultLanguage)\n self:trace('')\n self:trace(string.format(self.i18n:get('name'), self.name))\n self:updateProperty('manufacturer', 'Velux')\n self:updateProperty('model', 'Velux Active KIX 300')\n self:updateView(\"button1\", \"text\", self.i18n:get('stop'))\n self:updateView(\"button2\", \"text\", self.i18n:get('search-devices'))\n self:updateView(\"label\", \"text\", self.i18n:get('name'))\n self:updateProperty(\"value\", 99)\n if string.len(self.config:getModuleID()) > 10 then\n self:run()\n end\nend\n\nfunction QuickApp:open()\n self:setPosition(100)\nend\n\nfunction QuickApp:close()\n self:setPosition(0)\nend\n\nfunction QuickApp:stop()\n local callback = function(response)\n self:pullDataFromCloud()\n end\n self.velux:stop(callback)\nend\n\nfunction QuickApp:setValue(value)\n if value > 98 then\n value = 100\n end\n self:setPosition(value)\nend\n\nfunction QuickApp:setPositionEvent(event)\n local position = event.values[1]\n self:setValue(position)\nend\n\nfunction QuickApp:stopEvent(event)\n self:stop()\nend\n\nfunction QuickApp:refreshDataEvent(event)\n self:updateView(\"label\", \"text\", self.i18n:get('refreshing'))\n self:pullDataFromCloud()\nend\n\nfunction QuickApp:setPosition(position)\n -- self:debug(string.format(\"Setting new position (%d%%) ...\", position))\n if position < 1 then\n position = 0\n elseif position > 98 then\n position = 100\n end\n local callback = function(response)\n self:debug(string.format(self.i18n:get('position-set'), position))\n self:pullDataFromCloud()\n end\n self.velux:setPosition(position, callback)\nend\n\nfunction QuickApp:updateValues(position, newPosition)\n value = position\n self:updateView(\"slider\", \"value\", tostring(position))\n if position < 1 then\n value = 0\n text = self.i18n:get('shutter-closed')\n elseif position > 98 then\n value = 99\n text = self.i18n:get('shutter-opened')\n else \n text = string.format(self.i18n:get('shutter-half-open'), position)\n end\n local inMotion = false\n if newPosition ~= nil and newPosition > position then\n text = string.format(self.i18n:get('shutter-opening'), position)\n inMotion = true\n elseif newPosition ~= nil and newPosition < position then\n text = string.format(self.i18n:get('shutter-closing'), position)\n inMotion = true\n end\n if inMotion then\n fibaro.setTimeout(3000, function()\n self:pullDataFromCloud()\n end)\n end\n self:updateView(\"label\", \"text\", text)\n self:updateProperty(\"value\", value)\nend\n\nfunction QuickApp:run()\n self:pullDataFromCloud()\n local interval = self.config:getInterval()\n if (interval > 0) then\n fibaro.setTimeout(interval, function() self:run() end)\n end\nend\n\nfunction QuickApp:pullDataFromCloud()\n local callback = function(moduleData)\n -- QuickApp:debug(json.encode(moduleData))\n self:updateView(\"button3\", \"text\", self.i18n:get('refresh'))\n self:updateValues(moduleData.current_position, moduleData.target_position)\n end\n self:updateView(\"button3\", \"text\", self.i18n:get('refreshing'))\n self.velux:sync(callback)\nend\n\nfunction QuickApp:searchDevicesEvent()\n self:debug(self.i18n:get('searching-devices'))\n self:updateView(\"button2\", \"text\", self.i18n:get('searching-devices'))\n local callback = function(homeData)\n self:updateView(\"button2\", \"text\", self.i18n:get('search-devices'))\n -- printing results\n QuickApp:trace(string.format(self.i18n:get('search-row-home'), homeData.name, homeData.id))\n QuickApp:trace(string.format(self.i18n:get('search-row-home-gateways'), #homeData.gateways))\n for _, gateway in ipairs(homeData.gateways) do\n QuickApp:trace(string.format(self.i18n:get('search-row-gateway'), gateway.name, gateway.id))\n QuickApp:trace(string.format(self.i18n:get('search-row-gateway-shutters'), #gateway.shutters))\n for __, shutter in ipairs(gateway.shutters) do\n QuickApp:trace(string.format(self.i18n:get('search-row-shutter'), shutter.id))\n QuickApp:trace(string.format(self.i18n:get('search-row-shutter-position'), shutter.position))\n end\n end\n self:updateView(\"label\", \"text\", string.format(self.i18n:get('check-logs'), 'QUICKAPP' .. self.id))\n end\n self.velux:searchDevices(callback)\nend\n"
},
{
"name": "HTTPClient",
"isMain": false,
"isOpen": false,
"content": "--[[\nHTTPClient wrapper\n@author ikubicki\n]]\nclass 'HTTPClient'\n\nfunction HTTPClient:new(options)\n if not options then\n options = {}\n end\n self.options = options\n return self\nend\n\nfunction HTTPClient:get(url, success, error, headers)\n local client = net.HTTPClient({timeout = 10000})\n if not headers then\n headers = {}\n end\n client:request(self:url(url), self:requestOptions(success, error, 'GET', nil, headers)) \nend\n\nfunction HTTPClient:post(url, data, success, error, headers)\n local client = net.HTTPClient({timeout = 10000})\n if not headers then\n headers = {}\n end\n client:request(self:url(url), self:requestOptions(success, error, 'POST', data, headers)) \nend\n\nfunction HTTPClient:postForm(url, data, success, error, headers)\n local client = net.HTTPClient({timeout = 10000})\n if not headers then\n headers = {}\n end\n headers[\"Content-Type\"] = 'application/x-www-form-urlencoded;charset=UTF-8'\n client:request(self:url(url), self:requestOptions(success, error, 'POST', data, headers, true)) \nend\n\nfunction HTTPClient:put(url, data, success, error, headers)\n local client = net.HTTPClient({timeout = 10000})\n client:request(self:url(url), self:requestOptions(success, error, 'PUT', data, headers)) \nend\n\nfunction HTTPClient:delete(url, success, error, headers)\n local client = net.HTTPClient({timeout = 10000})\n if not headers then\n headers = {}\n end\n client:request(self:url(url), self:requestOptions(success, error, 'DELETE', nil, headers)) \nend\n\nfunction HTTPClient:url(url)\n if (string.sub(url, 0, 4) == 'http') then\n return url\n end\n if not self.options.baseUrl then\n self.options.baseUrl = 'http://localhost'\n end\n return self.options.baseUrl .. tostring(url)\nend\n\nfunction HTTPClient:requestOptions(success, error, method, data, headers, isFormData)\n if error == nil then\n error = function (error)\n QuickApp:error(json.encode(error))\n end\n end\n if method == nil then\n method = 'GET'\n end\n local options = {\n checkCertificate = false,\n method = method,\n headers = headers,\n }\n if data ~= nil then\n if isFormData then\n options.data = ''\n for key, value in pairs(data) do\n if string.len(options.data) > 0 then \n options.data = options.data .. '&'\n end\n options.data = options.data .. key .. '=' .. value\n end\n elseif type(data) == 'string' then\n options.data = data\n else\n options.data = json.encode(data)\n end\n end\n return {\n options = options,\n success = success,\n error = error\n }\nend"
},
{
"name": "Config",
"isMain": false,
"isOpen": false,
"content": "--[[\nConfiguration handler\n@author ikubicki\n]]\nclass 'Config'\n\nfunction Config:new(app)\n self.app = app\n self:init()\n return self\nend\n\nfunction Config:getUsername()\n if self.username and self.username:len() > 3 then\n return self.username\n end\n return nil\nend\n\nfunction Config:getPassword()\n return self.password\nend\n\nfunction Config:getHomeID()\n return self.home_id\nend\n\nfunction Config:setHomeID(home_id)\n self.home_id = home_id\n Globals:set('velux_home_id', self.home_id)\nend\n\nfunction Config:getGatewayID()\n return self.gateway_id\nend\n\nfunction Config:setGatewayID(gateway_id)\n self.gateway_id = gateway_id\n Globals:set('velux_gateway_id', self.gateway_id)\nend\n\nfunction Config:getModuleID()\n return self.module_id\nend\n\nfunction Config:setModuleID(module_id)\n self.module_id = module_id\nend\n\nfunction Config:getInterval()\n return 1800 * 1000\nend\n\n--[[\nThis function takes variables and sets as global variables if those are not set already.\nThis way, adding other devices might be optional and leaves option for users, \nwhat they want to add into HC3 virtual devices.\n]]\nfunction Config:init()\n self.username = self.app:getVariable('Username')\n self.password = self.app:getVariable('Password')\n self.home_id = self.app:getVariable('HomeID')\n self.gateway_id = self.app:getVariable('GatewayID')\n self.module_id = self.app:getVariable('ModuleID')\n\n local storedUsername = Globals:get('velux_username', '')\n local storedPassword = Globals:get('velux_password', '')\n local storedHomeID = Globals:get('velux_home_id', '')\n local storedGatewayID = Globals:get('velux_gateway_id', '')\n\n -- handling username\n if string.len(self.username) < 4 and string.len(storedUsername) > 3 then\n self.app:setVariable(\"Username\", storedUsername)\n self.username = storedUsername\n elseif (storedUsername == '' and self.username) then\n Globals:set('velux_username', self.username)\n end\n -- handling password\n if string.len(self.password) < 4 and string.len(storedPassword) > 3 then\n self.app:setVariable(\"Password\", storedPassword)\n self.password = storedPassword\n elseif (storedPassword == '' and self.password) then\n Globals:set('velux_password', self.password)\n end\n -- handling Home ID\n if string.len(self.home_id) < 4 and string.len(storedHomeID) > 3 then\n self.app:setVariable(\"HomeID\", storedHomeID)\n self.home_id = storedHomeID\n elseif (storedHomeID == '' and self.home_id) then\n Globals:set('velux_home_id', self.home_id)\n end\n -- handling Gateway ID\n if string.len(self.gateway_id) < 4 and string.len(storedGatewayID) > 3 then\n self.app:setVariable(\"GatewayID\", storedGatewayID)\n self.gateway_id = storedGatewayID\n elseif (storedGatewayID == '' and self.home_id) then\n Globals:set('velux_gateway_id', self.gateway_id)\n end\nend"
},
{
"name": "Globals",
"isMain": false,
"isOpen": false,
"content": "--[[\nGlobal variables handler\n@author ikubicki\n]]\nclass 'Globals'\n\nfunction Globals:get(name, alternative)\n local response = api.get('/globalVariables/' .. name)\n if response then\n local char = string.sub(response.value, 1, 1)\n if char == '{' or char == '\"' then\n return json.decode(response.value)\n end\n return response.value\n end\n return alternative\nend\n\nfunction Globals:set(name, value)\n local response = api.put('/globalVariables/' .. name, {\n name = name,\n value = json.encode(value)\n })\n if not response then\n response = api.post('/globalVariables', {\n name = name,\n value = json.encode(value)\n })\n \n end\n if response ~= nil then\n if response.type == 'ERROR' then\n QuickApp:error('GLOBALS ERROR[' .. response.reason .. ']:', response.message)\n end\n end\nend"
},
{
"name": "Velux",
"isMain": false,
"isOpen": false,
"content": "--[[\nVelux Active SDK\n@author ikubicki\n]]\nclass 'Velux'\n\nfunction Velux:new(config)\n self.user = config:getUsername()\n self.pass = config:getPassword()\n self.home_id = config:getHomeID()\n self.gateway_id = config:getGatewayID()\n self.module_id = config:getModuleID()\n self.token = Globals:get('velux_token', '')\n self.http = HTTPClient:new()\n Velux:start()\n return self\nend\n\nfunction Velux:stop(callback)\n if string.len(Velux:getModuleIDConfig()) < 10 then\n QuickApp:error(\"Unable to sync module status - ModuleID not specified!\")\n return\n end\n local stopCallback = function(response)\n if callback ~= nil then \n callback(response)\n end\n end\n local authCallback = function(response)\n Velux:setStateStopMovements(stopCallback)\n end\n Velux:auth(authCallback)\nend\n\nfunction Velux:sync(callback)\n if string.len(Velux:getModuleIDConfig()) < 10 then\n QuickApp:error(\"Unable to sync module status - ModuleID not specified!\")\n return\n end\n local statusCallback = function(home)\n for _, module in ipairs(home.modules) do\n if module.id == Velux:getModuleIDConfig() then\n -- QuickApp:debug('Module status updated')\n callback(module)\n end\n end\n end\n local authCallback = function(response)\n Velux:getHomeStatus(statusCallback)\n end\n Velux:auth(authCallback)\nend\n\nfunction Velux:setPosition(position, callback)\n local authCallback = function(response)\n Velux:setStatePosition(position, callback)\n end\n Velux:auth(authCallback)\nend\n\nfunction Velux:searchDevices(callback)\n local buildShutter = function(shutterData)\n return {\n id = shutterData.id,\n position = tonumber(shutterData.target_position),\n }\n end\n local buildGateway = function(gatewayData)\n return {\n id = gatewayData.id,\n name = gatewayData.name,\n shutters = {},\n }\n end\n local buildHome = function(callback, homeData)\n local home = {\n id = homeData[\"id\"],\n name = homeData[\"name\"],\n gateways = {}\n }\n local homeStatusCallback = function(homeStatus)\n local gateways = {}\n -- searching for gateways\n for _, module in ipairs(homeStatus.modules) do\n if module.type == \"NXG\" then\n gateways[module.id] = buildGateway(module)\n end\n end\n -- searching for shutters\n for _, module in ipairs(homeStatus.modules) do\n if module.type == \"NXO\" then\n table.insert(gateways[module.bridge].shutters, buildShutter(module))\n end\n end\n -- updating home\n for _, gateway in pairs(gateways) do\n table.insert(home.gateways, gateway)\n end\n if #home.gateways == 1 and home.id == self.getHomeIDConfig() and string.len(Velux:getGatewayIDConfig()) < 10 then\n QuickApp:debug(\"One gateway detected - automatically assigning GatewayID: \" .. home.gateways[1].id)\n Velux:setGatewayIDConfig(home.gateways[1].id)\n if #home.gateways[1].shutters == 1 and string.len(Velux:getModuleIDConfig()) < 10 then\n QuickApp:debug(\"One shutter detected - automatically assigning ModuleID: \" .. home.gateways[1].shutters[1].id)\n Velux:setModuleIDConfig(home.gateways[1].shutters[1].id)\n end\n end\n if callback ~= nil then\n callback(home)\n end\n end\n Velux:getHomeStatus(homeStatusCallback, home.id)\n end\n local homesCallback = function(homes)\n -- QuickApp:debug(json.encode(homes))\n if #homes == 1 and string.len(Velux:getHomeIDConfig()) < 10 then\n QuickApp:debug(\"One home detected - automatically assigning HomeID: \" .. homes[1].id)\n Velux:setHomeIDConfig(homes[1].id)\n end\n QuickApp:debug(\"Found \" .. #homes .. \" homes:\")\n for _, homeData in ipairs(homes) do\n buildHome(callback, homeData)\n end\n end\n local authCallback = function(response)\n Velux:getHomeID(homesCallback)\n end\n Velux:auth(authCallback)\nend\n\nfunction Velux:auth(callback)\n if string.len(self.token) > 1 then\n -- QuickApp:debug('Already authenticated')\n if callback ~= nil then\n callback({})\n end\n return\n end\n local fail = function(response)\n QuickApp:error('Unable to authenticate')\n Velux:setToken('')\n end\n local success = function(response)\n -- QuickApp:debug(json.encode(response))\n if response.status < 200 or response.status > 299 then\n fail(response)\n return\n end\n local data = json.decode(response.data)\n Velux:setToken(data.access_token)\n if callback ~= nil then\n callback(data)\n end\n end\n local url = \"https://app.velux-active.com/oauth2/token\"\n local data = {\n grant_type = \"password\",\n user_prefix = \"velux\",\n username = self.user,\n password = self.pass,\n client_id = self.clientID,\n client_secret = self.clientSecret,\n }\n self.http:postForm(url, data, success, fail)\nend\n\nfunction Velux:setToken(token)\n self.token = token\n Globals:set('velux_token', token)\nend\n\nfunction Velux:getToken()\n if string.len(self.token) > 10 then\n return self.token\n elseif string.len(Globals:get('velux_token', '')) > 10 then\n return Globals:get('velux_token', '')\n end\n return nil\nend\n\nfunction Velux:setHomeIDConfig(home_id)\n Velux.home_id = home_id\n Config:setHomeID(home_id)\nend\n\nfunction Velux:getHomeIDConfig()\n if string.len(Velux.home_id) > 10 then\n return Velux.home_id\n elseif string.len(Config:getHomeID()) > 10 then\n return Config:getHomeID('')\n end\n return ''\nend\n\nfunction Velux:setGatewayIDConfig(gateway_id)\n Velux.gateway_id = gateway_id\n Config:setGatewayID(gateway_id)\nend\n\nfunction Velux:getGatewayIDConfig()\n if string.len(Velux.gateway_id) > 10 then\n return Velux.gateway_id\n elseif string.len(Config:getGatewayID()) > 10 then\n return Config:getGatewayID('')\n end\n return ''\nend\n\nfunction Velux:setModuleIDConfig(module_id)\n Velux.module_id = module_id\n Config:setModuleID(module_id)\nend\n\nfunction Velux:getModuleIDConfig()\n if string.len(Velux.module_id) > 10 then\n return Velux.module_id\n elseif string.len(Config:getModuleID()) > 10 then\n return Config:getModuleID('')\n end\n return ''\nend\n\nfunction Velux:getHomeID(callback)\n local fail = function(response)\n QuickApp:error('Unable to pull homes')\n Velux:setToken('')\n end\n local success = function(response)\n if response.status < 200 or response.status > 299 then\n fail(response)\n return\n end\n local data = json.decode(response.data)\n if callback ~= nil then\n callback(data.body.homes)\n end\n end\n local url = \"https://app.velux-active.com/api/gethomedata\"\n local data = {\n access_token = Velux:getToken()\n }\n self.http:postForm(url, data, success, fail)\nend\n\nfunction Velux:getHomeStatus(callback, home_id, attempt)\n if attempt == nil then\n attempt = 0\n end\n if home_id == nil or home_id == '' then\n home_id = Velux.getHomeIDConfig()\n end\n\n local fail = function(response)\n QuickApp:error('Unable to pull home status')\n Velux:setToken('')\n \n if attempt < 3 then\n attempt = attempt + 1\n fibaro.setTimeout(3000, function()\n QuickApp:debug('Velux:getHomeStatus - Retry attempt #' .. attempt)\n self:getHomeStatus(callback, home_id, attempt)\n end)\n end\n end\n local success = function(response)\n if response.status < 200 or response.status > 299 then\n fail(response)\n return\n end\n local data = json.decode(response.data)\n if callback ~= nil then\n callback(data.body.home)\n end\n end\n local url = \"https://app.velux-active.com/api/homestatus?home_id=\" .. home_id\n local headers = {\n Authorization = \"Bearer \" .. Velux:getToken()\n }\n self.http:post(url, {}, success, fail, headers)\nend\n\nfunction Velux:setStateStopMovements(callback)\n local data = json.encode({\n home = {\n id = Velux:getHomeIDConfig(),\n modules = {{\n id = Velux:getGatewayIDConfig(),\n stop_movements = \"all\",\n }}\n }\n })\n Velux:setState(data, callback)\nend\n\nfunction Velux:setStatePosition(position, callback)\n local data = json.encode({\n home = {\n id = Velux:getHomeIDConfig(),\n modules = {{\n id = Velux:getModuleIDConfig(),\n bridge = Velux:getGatewayIDConfig(),\n target_position = position,\n }}\n }\n })\n Velux:setState(data, callback)\nend\n\nfunction Velux:setState(data, callback)\n if string.len(Velux.getHomeIDConfig()) < 10 then\n QuickApp:error(\"Unable to set state - HomeID not specified!\")\n return\n end\n if string.len(Velux:getGatewayIDConfig()) < 10 then\n QuickApp:error(\"Unable to set state - GatewayID not specified!\")\n return\n end\n if string.len(Velux:getModuleIDConfig()) < 10 then\n QuickApp:error(\"Unable to set state - ModuleID not specified!\")\n return\n end\n local fail = function(response)\n QuickApp:debug(json.encode(response))\n QuickApp:error('Unable to update module ' .. Velux:getModuleIDConfig())\n Velux:setToken('')\n end\n local success = function(response)\n if response.status < 200 or response.status > 299 then\n fail(response)\n return\n end\n local data = json.decode(response.data)\n if callback ~= nil then\n callback(data)\n end\n end\n local url = \"https://app.velux-active.com/syncapi/v1/setstate?home_id=\" .. Velux:getHomeIDConfig()\n local headers = {\n Authorization = \"Bearer \" .. Velux:getToken(),\n [\"Content-Type\"] = \"application/json\"\n }\n self.http:post(url, data, success, fail, headers)\nend\n\nfunction Velux:start()\n local a = \"\"\n local b = \"\"\n b = b .. \"6ae\"\n a = a .. \"593\"\n b = b .. \"2d8\"\n a = a .. \"142\"\n b = b .. \"9d1\"\n a = a .. \"6da\"\n b = b .. \"5e7\"\n a = a .. \"127\"\n b = b .. \"67a\"\n a = a .. \"d98\"\n b = b .. \"e5c\"\n a = a .. \"1e7\"\n b = b .. \"56b\"\n a = a .. \"6bd\"\n b = b .. \"456\"\n a = a .. \"d3f\"\n b = b .. \"b45\"\n b = b .. \"2d3\"\n b = b .. \"19\"\n\n self.clientID = a\n self.clientSecret = b\nend"
},
{
"name": "i18n",
"isMain": false,
"isOpen": false,
"content": "--[[\nInternationalization tool\n@author ikubicki\n]]\nclass 'i18n'\n\nfunction i18n:new(langCode)\n if phrases[langCode] == nil then\n langCode = 'en'\n end\n self.phrases = phrases[langCode]\n return self\nend\n\nfunction i18n:get(key)\n if self.phrases[key] then\n return self.phrases[key]\n end\n return key\nend\n\nphrases = {\n pl = {\n ['name'] = 'Velux Active: Roleta zewnętrzna - %s',\n ['search-devices'] = 'Szukaj urządzeń',\n ['searching-devices'] = 'Szukam...',\n ['refresh'] = 'Odśwież dane',\n ['refreshing'] = 'Odświeżam...',\n ['device-updated'] = 'Zaktualizowano dane urządzenia',\n ['check-logs'] = 'Zakończono wyszukiwanie. Sprawdź logi tego urządzenia: %s',\n ['shutter-opened'] = 'Roleta otwarta',\n ['shutter-closed'] = 'Roleta zamknięta',\n ['shutter-half-open'] = 'Roleta częściowo uchylona (%d%%)',\n ['shutter-opening'] = 'Roleta w trakcie otwierania (-> %d%%)',\n ['shutter-closing'] = 'Roleta w trakcie zamykania (-> %d%%)',\n ['stop'] = 'Zatrzymaj ruch',\n ['position-set'] = 'Pozycja: %d%%',\n\n ['search-row-home'] = '__ DOM %s (# %s)',\n ['search-row-home-gateways'] = '__ Wykryto %d bramek',\n ['search-row-gateway'] = '____ BRAMKA %s (# %s)',\n ['search-row-gateway-shutters'] = '____ Wykryto %d rolet',\n ['search-row-shutter'] = '______ ROLETA # %s',\n ['search-row-shutter-position'] = '______ Pozycja: %d%%',\n },\n en = {\n ['name'] = 'Velux Active: Roof window shutter - %s',\n ['search-devices'] = 'Search devices',\n ['searching-devices'] = 'Searching...',\n ['refresh'] = 'Refresh data',\n ['refreshing'] = 'Refreshing...',\n ['device-updated'] = 'Device updated',\n ['check-logs'] = 'Check device logs (%s) for search results',\n ['shutter-opened'] = 'Rollershutter opened',\n ['shutter-closed'] = 'Rollershutter closed',\n ['shutter-half-open'] = 'Rollershutter partially opened (%d%%)',\n ['shutter-opening'] = 'Rollershutter is opening (-> %d%%)',\n ['shutter-closing'] = 'Rollershutter is closing (-> %d%%)',\n ['stop'] = 'Stop movement',\n ['position-set'] = 'Position: %d%%',\n\n ['search-row-home'] = '__ HOME %s (# %s)',\n ['search-row-home-gateways'] = '__ %d gateways found',\n ['search-row-gateway'] = '____ GATEWAY %s (# %s)',\n ['search-row-gateway-shutters'] = '____ %d shutters found',\n ['search-row-shutter'] = '______ ROLLERSHUTTER # %s',\n ['search-row-shutter-position'] = '______ Position: %d%%',\n },\n de = {\n ['name'] = 'Velux Active: Rollladen - %s',\n ['search-devices'] = 'Geräte suchen',\n ['searching-devices'] = 'Suchen...',\n ['refresh'] = 'Aktualisieren',\n ['refreshing'] = 'Aktualisieren...',\n ['device-updated'] = 'Gerät aktualisiert',\n ['check-logs'] = 'Überprüfen Sie die Geräteprotokolle (%s) auf Suchergebnisse',\n ['shutter-opened'] = 'Rollladen geöffnet',\n ['shutter-closed'] = 'Rollladen geschlossen',\n ['shutter-half-open'] = 'Rollladen teilweise geöffnet (%d%%)',\n ['shutter-opening'] = 'Rollladen öffnet (-> %d%%)',\n ['shutter-closing'] = 'Rollladen schließt (-> %d%%)',\n ['stop'] = 'Bewegung stoppen',\n ['position-set'] = 'Position: %d%%',\n\n ['search-row-home'] = '__ HAUS %s (# %s)',\n ['search-row-home-gateways'] = '__ %d einfahrten gefunden',\n ['search-row-gateway'] = '____ EINFAHRT %s (# %s)',\n ['search-row-gateway-shutters'] = '____ %d rollläden gefunden',\n ['search-row-shutter'] = '______ ROLLLADEN # %s',\n ['search-row-shutter-position'] = '______ Position: %d%%',\n }\n}"
}
]
}