Improve the process for GNU tools
[minix3.git] / minix / share / beaglebone / weather / weatherstation.lua
blob8e287e6eda0f7e28b69e77c3e31c9d94059dd3c7
1 #!/usr/bin/lua
2 --
3 -- weatherstation.lua - a simple web server intended to be run from tcpd to
4 -- expose sensors from the BeagleBone Weather cape and serve the web app.
5 --
7 -- List of files shared by this service.
8 distfiles={}
9 distfiles["/index.html"] = true
10 distfiles["/style.css"] = true
11 distfiles["/jquery.js"] = true
12 distfiles["/processing.js"] = true
13 distfiles["/spin.js"] = true
14 distfiles["/weatherstation.js"] = true
16 -- Base path for distfiles
17 prefix="/usr/share/beaglebone/weather"
19 -- Check that the filename is part of this demo.
20 function filename_is_valid(filename)
21 return distfiles[filename] ~= nil
22 end
24 -- Check if the string 's' starts with 'starting'
25 function starts_with(s, starting)
26 return string.sub(s, 1, string.len(starting)) == starting
27 end
29 -- Check if the string 's' ends with 'ending'
30 function ends_with(s, ending)
31 return string.sub(s, -string.len(ending)) == ending
32 end
34 -- Return the content type of the file based only on the file extension.
35 function get_content_type(filename)
37 if ends_with(filename, ".js") then
38 return "application/javascript"
39 elseif ends_with(filename, ".css") then
40 return "text/css"
41 elseif ends_with(filename, ".html") then
42 return "text/html"
43 elseif ends_with(filename, ".json") then
44 return "application/json"
45 else
46 return "text/plain"
47 end
48 end
50 -- Reads from STDIN until an empty or nil line is received.
51 -- Returns the first line of the request.
52 function read_request()
54 local i = 0
55 local lines = {}
57 repeat
58 local line = io.read("*line")
59 if line == nil or line == "\r" then
60 break
61 end
62 lines[i] = line
63 i = i + 1
64 until false
66 return lines[0]
67 end
69 -- Return the entire contents of a file
70 function read_file(filename)
71 local f = io.open(filename, "rb")
73 if f == nil then
74 return nil
75 end
76 local content = f:read("*all")
77 f:close()
79 return content
80 end
82 -- Extract the value of the LABEL:VALUE pairs read from the device files.
83 function extract_value(data, pat)
85 local x = string.match(data, pat)
87 if x == nil then
88 return "0"
89 end
90 return x
91 end
93 -- Read the sensor values and generate json output
94 function generate_json()
95 local json = ""
97 local tsl2550 = read_file("/dev/tsl2550b3s39")
98 if tsl2550 == nil then
99 return nil
101 local illuminance = extract_value(tsl2550, "ILLUMINANCE: (%d+)")
103 local sht21 = read_file("/dev/sht21b3s40")
104 if sht21 == nil then
105 return nil
107 local temperature = extract_value(sht21, "TEMPERATURE: (%d+.%d+)")
108 local humidity = extract_value(sht21, "HUMIDITY: (%d+.%d+)")
110 local bmp085 = read_file("/dev/bmp085b3s77")
111 if bmp085 == nil then
112 return nil
114 local pressure = extract_value(bmp085, "PRESSURE: (%d+)")
116 json = json .. "{\n"
117 json = json .. "\"temperature\": " .. temperature .. ",\n"
118 json = json .. "\"humidity\": " .. humidity .. ",\n"
119 json = json .. "\"illuminance\": " .. illuminance .. ",\n"
120 json = json .. "\"pressure\": " .. pressure .. "\n"
121 json = json .. "}\n"
123 return json
126 function handle_request(req)
128 if req == nil then
129 response("404 Not Found", "text/plain", "Unknown Request")
130 return
133 -- Parse filename out of HTTP request
134 local filename = (string.match(req, " %S+ "):gsub("^%s+", ""):gsub("%s+$", ""))
135 if filename == "" or filename == "/" then
136 filename = "/index.html"
139 -- Check if the filename is known (i.e. it's a file in the web app)
140 if filename_is_valid(filename) then
141 local contents = read_file(prefix .. filename)
143 if contents ~= nil then
144 response("200 OK", get_content_type(filename), contents)
145 else
146 response("404 Not Found", "text/plain", "Failed to load known file")
148 -- Else maybe the user is requesting the dynamic json data
149 elseif starts_with(filename, "/weather.json") then
150 local json = generate_json()
151 if json == nil then
152 response("500 Internal Server Error", "text/plain", "Could not get sensor values")
153 else
154 response("200 OK", get_content_type("/weather.json"), json)
156 -- Else, the user is requesting something not part of the app
157 else
158 response("403 Forbidden", "text/plain", "File not allowed.")
161 return
164 -- Send the response to the HTTP request.
165 function response(err_code, content_type, content)
166 io.write("HTTP/1.1 " .. err_code .. "\r\n")
167 io.write("Content-Type: " .. content_type .. "\r\n")
168 io.write("\r\n")
169 io.write(content)
170 io.write("\r\n")
173 -- Read the request and then handle it.
174 handle_request(read_request())