minix/share/beaglebone/weather/weatherstation.lua
Lionel Sambuc efa169276f WeatherStation: slight update
- Replaced the use of string.find by string.match, as it was not
   working as expected with the new lua interpretor.

 - Slight simplification of extract_value as we now can use a full-blown
   regular expression.

Change-Id: I1d7df66a272120cd10aa40f8e9326057b9709e3d
2014-07-28 17:05:40 +02:00

176 lines
4.3 KiB
Lua
Executable file

#!/usr/bin/lua
--
-- weatherstation.lua - a simple web server intended to be run from tcpd to
-- expose sensors from the BeagleBone Weather cape and serve the web app.
--
-- List of files shared by this service.
distfiles={}
distfiles["/index.html"] = true
distfiles["/style.css"] = true
distfiles["/jquery.js"] = true
distfiles["/processing.js"] = true
distfiles["/spin.js"] = true
distfiles["/weatherstation.js"] = true
-- Base path for distfiles
prefix="/usr/share/beaglebone/weather"
-- Check that the filename is part of this demo.
function filename_is_valid(filename)
return distfiles[filename] ~= nil
end
-- Check if the string 's' starts with 'starting'
function starts_with(s, starting)
return string.sub(s, 1, string.len(starting)) == starting
end
-- Check if the string 's' ends with 'ending'
function ends_with(s, ending)
return string.sub(s, -string.len(ending)) == ending
end
-- Return the content type of the file based only on the file extension.
function get_content_type(filename)
if ends_with(filename, ".js") then
return "application/javascript"
elseif ends_with(filename, ".css") then
return "text/css"
elseif ends_with(filename, ".html") then
return "text/html"
elseif ends_with(filename, ".json") then
return "application/json"
else
return "text/plain"
end
end
-- Reads from STDIN until an empty or nil line is received.
-- Returns the first line of the request.
function read_request()
local i = 0
local lines = {}
repeat
local line = io.read("*line")
if line == nil or line == "\r" then
break
end
lines[i] = line
i = i + 1
until false
return lines[0]
end
-- Return the entire contents of a file
function read_file(filename)
local f = io.open(filename, "rb")
if f == nil then
return nil
end
local content = f:read("*all")
f:close()
return content
end
-- Extract the value of the LABEL:VALUE pairs read from the device files.
function extract_value(data, pat)
local x = string.match(data, pat)
if x == nil then
return "0"
end
return x
end
-- Read the sensor values and generate json output
function generate_json()
local json = ""
local tsl2550 = read_file("/dev/tsl2550b3s39")
if tsl2550 == nil then
return nil
end
local illuminance = extract_value(tsl2550, "ILLUMINANCE: (%d+)")
local sht21 = read_file("/dev/sht21b3s40")
if sht21 == nil then
return nil
end
local temperature = extract_value(sht21, "TEMPERATURE: (%d+.%d+)")
local humidity = extract_value(sht21, "HUMIDITY: (%d+.%d+)")
local bmp085 = read_file("/dev/bmp085b3s77")
if bmp085 == nil then
return nil
end
local pressure = extract_value(bmp085, "PRESSURE: (%d+)")
json = json .. "{\n"
json = json .. "\"temperature\": " .. temperature .. ",\n"
json = json .. "\"humidity\": " .. humidity .. ",\n"
json = json .. "\"illuminance\": " .. illuminance .. ",\n"
json = json .. "\"pressure\": " .. pressure .. "\n"
json = json .. "}\n"
return json
end
function handle_request(req)
if req == nil then
response("404 Not Found", "text/plain", "Unknown Request")
return
end
-- Parse filename out of HTTP request
local filename = (string.match(req, " %S+ "):gsub("^%s+", ""):gsub("%s+$", ""))
if filename == "" or filename == "/" then
filename = "/index.html"
end
-- Check if the filename is known (i.e. it's a file in the web app)
if filename_is_valid(filename) then
local contents = read_file(prefix .. filename)
if contents ~= nil then
response("200 OK", get_content_type(filename), contents)
else
response("404 Not Found", "text/plain", "Failed to load known file")
end
-- Else maybe the user is requesting the dynamic json data
elseif starts_with(filename, "/weather.json") then
local json = generate_json()
if json == nil then
response("500 Internal Server Error", "text/plain", "Could not get sensor values")
else
response("200 OK", get_content_type("/weather.json"), json)
end
-- Else, the user is requesting something not part of the app
else
response("403 Forbidden", "text/plain", "File not allowed.")
end
return
end
-- Send the response to the HTTP request.
function response(err_code, content_type, content)
io.write("HTTP/1.1 " .. err_code .. "\r\n")
io.write("Content-Type: " .. content_type .. "\r\n")
io.write("\r\n")
io.write(content)
io.write("\r\n")
end
-- Read the request and then handle it.
handle_request(read_request())