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
|
if not modules then modules = { } end modules ['util-imp-evohome-server'] = {
version = 1.002,
comment = "simple server for simple evohome extensions",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "PRAGMA ADE",
license = "see context related readme files"
}
local P, C, patterns, lpegmatch = lpeg.P, lpeg.C, lpeg.patterns, lpeg.match
local urlhashed, urlquery, urlunescapeget = url.hashed, url.query, url.unescapeget
local ioflush = io.flush
local newline = patterns.newline
local spacer = patterns.spacer
local whitespace = patterns.whitespace
local method = P("GET")
+ P("POST")
local identify = (1-method)^0
* C(method)
* spacer^1
* C((1-spacer)^1)
* spacer^1
* P("HTTP/")
* (1-whitespace)^0
* C(P(1)^0)
do
local loaded = package.loaded
if not loaded.socket then loaded.socket = loaded["socket.core"] end
if not loaded.mime then loaded.mime = loaded["mime.core"] end
end
local evohome = require("util-evo")
require("trac-lmx")
local report = logs.reporter("evohome","server")
local convert = lmx.convert
function evohome.server(specification)
local filename = specification.filename
if not filename then
report("unable to run server, no filename given")
return
end
local step, process, presets = evohome.actions.poller(filename)
if not (step and process and presets) then
report("unable to run server, invalid presets")
return
end
local template = presets.files.template
if not template then
report("unable to run server, no template given")
return
end
local port = specification.port or (presets.server and presets.server.port) or 8068
local host = specification.host or (presets.server and presets.server.host) or "*"
if presets.initial == "alloff" then
report("turning all zones off")
evohome.actions.alloff(presets)
else
report("using default initial state")
end
package.extraluapath(presets.filepath)
local socket = socket or require("socket")
local copas = copas or require("copas")
local function copashttp(skt)
local client = copas.wrap(skt)
local request, e = client:receive()
if not e then
local method, fullurl, body = lpegmatch(identify,request)
if method ~= "" and fullurl ~= "" then
local fullurl = urlunescapeget(fullurl)
local hashed = urlhashed(fullurl)
process(hashed.queries or { })
ioflush()
end
-- todo: split off css and use that instead of general one, now too much
local content = convert(presets.results and presets.results.template or template,false,presets)
if not content then
report("error in converting template")
content = "error in template"
end
client:send("HTTP/1.1 200 OK\r\n")
client:send("Connection: close\r\n")
client:send("Content-Length: " .. #content .. "\r\n")
client:send("Content-Type: text/html\r\n")
client:send("Location: " .. host .. "\r\n")
client:send("Cache-Control: no-cache, no-store, must-revalidate, max-age=0\r\n")
client:send("\r\n")
client:send(content)
client:send("\r\n")
client:close()
end
end
local function copaspoll()
while step do
local delay = step()
if type(delay) == "number" then
copas.sleep(delay or 0)
end
end
end
local server = socket.bind(host,port)
if server then
report("server started at %s:%s",host,port)
ioflush()
copas.addserver(server,copashttp)
copas.addthread(copaspoll)
copas.loop()
else
report("unable to start server at %s:%s",host,port)
os.exit()
end
end
return evohome
|