Create working PoC of /sonos endpoint
This commit is contained in:
@@ -12,21 +12,30 @@ class Request private constructor(
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
val body = extractBody(request)
|
val body = extractBody(request)
|
||||||
val pathParams = extractPathParams(matchingResult)
|
val pathParameters = extractPathParameters(matchingResult)
|
||||||
|
val queryVariables = extractQueryVariables(request)
|
||||||
|
|
||||||
luaTable.set("body", body)
|
luaTable.set("body", body)
|
||||||
luaTable.set("params", pathParams)
|
luaTable.set("query", queryVariables)
|
||||||
|
luaTable.set("path", pathParameters)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun extractPathParams(matchingResult: UriTemplate.MatchingResult) =
|
private fun extractPathParameters(matchingResult: UriTemplate.MatchingResult) =
|
||||||
LuaValue.tableOf().also { params ->
|
LuaValue.tableOf().also { table ->
|
||||||
matchingResult.variables
|
matchingResult.variables
|
||||||
.map { LuaValue.valueOf(it.key) to LuaValue.valueOf(it.value) }
|
.map { LuaValue.valueOf(it.key) to LuaValue.valueOf(it.value) }
|
||||||
.forEach { params.set(it.first, it.second) }
|
.forEach { table.set(it.first, it.second) }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun extractQueryVariables(request: NanoHTTPD.IHTTPSession) =
|
||||||
|
LuaValue.tableOf().also { table ->
|
||||||
|
request.parms
|
||||||
|
.map { LuaValue.valueOf(it.key) to LuaValue.valueOf(it.value) }
|
||||||
|
.forEach { table.set(it.first, it.second) }
|
||||||
|
}
|
||||||
|
|
||||||
private fun extractBody(request: NanoHTTPD.IHTTPSession) =
|
private fun extractBody(request: NanoHTTPD.IHTTPSession) =
|
||||||
mutableMapOf<String, String>().let {
|
mutableMapOf<String, String>().let {
|
||||||
request.parseBody(it)
|
request.parseBody(it)
|
||||||
|
|||||||
@@ -50,7 +50,9 @@ class ScriptsInitializer(private val context: Context, private val preferences:
|
|||||||
private const val INITIALIZED_FLAG = "flag_initialized"
|
private const val INITIALIZED_FLAG = "flag_initialized"
|
||||||
private val endpoints = mapOf(
|
private val endpoints = mapOf(
|
||||||
"say.lua" to R.raw.say,
|
"say.lua" to R.raw.say,
|
||||||
"file.lua" to R.raw.file
|
"file.lua" to R.raw.file,
|
||||||
|
"sonos.lua" to R.raw.sonos,
|
||||||
|
"cache.lua" to R.raw.cache
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
15
app/src/main/res/raw/cache.lua
Normal file
15
app/src/main/res/raw/cache.lua
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
return {
|
||||||
|
uri = "/cache/{filename}.{ext}",
|
||||||
|
method = Method.GET,
|
||||||
|
consumer = function(request)
|
||||||
|
local filename = string.format("%s.%s", request.path.filename, request.path.ext)
|
||||||
|
local file = cache.file(filename)
|
||||||
|
local mime = Mime[request.path.ext:upper()]
|
||||||
|
|
||||||
|
return {
|
||||||
|
mime = mime,
|
||||||
|
cached = true,
|
||||||
|
data = file
|
||||||
|
}
|
||||||
|
end
|
||||||
|
}
|
||||||
@@ -1,17 +1,16 @@
|
|||||||
return {
|
return {
|
||||||
uri = "/{format}",
|
uri = "/tts.{ext}",
|
||||||
method = Method.POST,
|
method = Method.GET,
|
||||||
accepts = Mime.JSON,
|
|
||||||
consumer = function(request)
|
consumer = function(request)
|
||||||
local body = json.decode(request.body)
|
local format = (request.path.ext or "wav"):upper()
|
||||||
local format = (request.params.format or "WAV"):upper()
|
|
||||||
local audioFormat = AudioFormat[format]
|
local audioFormat = AudioFormat[format]
|
||||||
local mime = Mime[format]
|
local mime = Mime[format]
|
||||||
|
|
||||||
local file = tts.sayToFile(body.text, body.language or "en", audioFormat)
|
local file = tts.sayToFile(request.query.phrase, request.query.lang or "en", audioFormat)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
mime = mime,
|
mime = mime,
|
||||||
|
cached = false,
|
||||||
data = file
|
data = file
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|||||||
47
app/src/main/res/raw/sonos.lua
Normal file
47
app/src/main/res/raw/sonos.lua
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
local announcementUrl = "http://" .. server.address .. ":8080/cache"
|
||||||
|
local snapshot = nil
|
||||||
|
|
||||||
|
function prepareTTSFile(phrase, language)
|
||||||
|
local file = tts.sayToFile(phrase, language, AudioFormat.MP3)
|
||||||
|
return announcementUrl .. "/" .. file:getName()
|
||||||
|
end
|
||||||
|
|
||||||
|
function updateSnapshotIfFirst(device)
|
||||||
|
if(snapshot == nil) then
|
||||||
|
snapshot = device:snapshot()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function announce(device, data, url)
|
||||||
|
device:stop()
|
||||||
|
device:setVolume(data.volume)
|
||||||
|
device:playUri(url, "")
|
||||||
|
while(device:getPlayState():name() ~= "STOPPED") do
|
||||||
|
thread.sleep(500)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function restoreSnapshotIfLast(queueLength)
|
||||||
|
if(queueLength() == 0) then
|
||||||
|
if(snapshot ~= nil) then
|
||||||
|
snapshot:restore()
|
||||||
|
snapshot = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return {
|
||||||
|
uri = "/sonos",
|
||||||
|
method = Method.POST,
|
||||||
|
accepts = Mime.JSON,
|
||||||
|
queued = true,
|
||||||
|
consumer = function(request, queueLength)
|
||||||
|
local body = json.decode(request.body)
|
||||||
|
local zone = config.sonosDevices[body.zone]
|
||||||
|
|
||||||
|
local url = prepareTTSFile(body.text, body.language or "en")
|
||||||
|
updateSnapshotIfFirst(zone)
|
||||||
|
announce(zone, body, url)
|
||||||
|
restoreSnapshotIfLast(queueLength)
|
||||||
|
end
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user