Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Merge in the scared.lua scripts for the latest blog post. |
---|---|
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
26b540b3274a662fb0375299ed555008 |
User & Date: | rberteig 2015-05-22 23:23:49 |
Context
2015-06-16
| ||
22:18 | Merged to trunk for next blog post release. This has the nominally working email when startled script that can be configured to either email a plot of SPL or an MP3 of the room audio around the event. check-in: 8d8ccc7f52 user: rberteig tags: blog-splear09, trunk | |
2015-05-22
| ||
23:23 | Merge in the scared.lua scripts for the latest blog post. check-in: 26b540b327 user: rberteig tags: trunk | |
22:25 | Fix published email address. check-in: 31ad4ca9c2 user: rberteig tags: scared | |
2015-04-17
| ||
22:06 | Caught a typo, and renamed readme.txt to readme.md in most folders. check-in: 3b4f54236e user: rberteig tags: trunk | |
Changes
Added Scared/plotspl.lua.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | --[[ Lua module to plot SPL data with gnuplot. Uses temp files to hold the data and plotting script, with the script written from a template in this module. Produces a plot with labeled axes, a title, and annotations for the trigger time, mean and 1 sigma range about the mean. ]] -- miminal Lua 5.x module setup, M is the module's table. local M = { _NAME=(...) or "plotspl", _DESCRIPTION="Plot SPL data with gnuplot", _VERSION="0.001", } package.loaded[M._NAME] = M -- write the data array to a temp file local function prepdata(data) local datfile = "tmp-SPL.data" f = assert(io.open(datfile,"w")) f:write(data) f:close() return datfile end -- write out a gnuplot script to plot the data file -- to the named pngfile, with an offset to the trigger -- time and the specified title. local function prepscript(datafile, pngfile, trigger, title) assert(datafile) pngfile = pngfile or "tmp-SPL.png" trigger = trigger or 2.6 title = title or "Scaredy Cat" local plotfile = "tmp-SPL.plot" f = assert(io.open(plotfile, "w")) f:write('# Configuration\n', 'trigger=', trigger, '\n', 'datafile="', datafile, '"\n', 'outfile="', pngfile, '"\n', 'titletext="', title, '"\n', '\n') f:write[===[ set terminal push # Graph Title, Axis labels, key and grid set title titletext set xlabel "seconds" set ylabel "SPL, dB" set key off set grid xtics ytics # Compute mean and sd by cheating with a constant function fit to the # data. f(x) = mean_y fit f(x) datafile via mean_y stddev_y = sqrt(FIT_WSSR / (FIT_NDF + 1 )) set terminal png set output outfile # label a vertical line at trigger time, which will be at x=0 after # transformations set label 1 "Trigger" at 0, graph 0 offset character 0.25,0.5 set arrow 1 from 0, graph 0 to 0, graph 1 nohead linewidth 5 lc rgb "#ccccff" # plot with stddev bounds and mean, scaling and offsetting x to # seconds with x=0 at the trigger plot datafile using ($1 - trigger):2 with lines linewidth 2.5, \ mean_y with lines lc rgb "#00dd00", \ mean_y-stddev_y with lines lc rgb "#dd0000", \ mean_y+stddev_y with lines lc rgb "#dd0000" set output set terminal pop ]===] f:close() return plotfile end -- plot the given data string to the named png file. function M.plot(data, pngfile, trigger, title) local datafile = prepdata(data) local plotfile = prepscript(datafile, pngfile, trigger, title) local cmd = "gnuplot " .. plotfile .. " >" .. plotfile .. ".log 2>&1" print(cmd) os.execute(cmd) end -- return the module table return M |
Added Scared/scared.lua.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | #! lua local plot = require "plotspl" address = "user@example.com" -- today's date in (almost) ISO-8601 format local function isodate() return os.date"%Y-%m-%d %H:%M:%S" end -- make its argument be a single string function flatten(s) if type(s)=="string" then return '"'..s..'"' end if type(s)~="table" then return nil end return '"'..table.concat(s, '" "')..'"' end -- Send an email to addr with subject and body. If body -- is nil then just repeat the subject. This assumes that -- a "mail" command is available with the usual options. local function email(addr, subj, body) body = body or subj local mail = ("mail -s '%q' %s"):format(subj,addr) local b = assert(io.popen(mail, "w")) b:write([[I heard a noise on ]], isodate(), "\r\n\r\n") b:write(body, "\r\n\r\n") b:write"(This an automated message.)\r\n" b:close() end -- Send a MIME packed email containing an image of the -- event to a recipient with a subject -- mpack(address, eek, "scared.png") local function mpack(address, subject, pngfile) assert(address) assert(subject) assert(pngfile) local cmd = ("mpack -a -s %q %q %s"):format(subject, pngfile, address) print(cmd) os.execute(cmd) end -- Implement a buffer of samples. For simplicity, let the -- index increment without bound. Note that this will have -- a problem after 2^53 samples, which is about 30 million -- years at 10 samples per second. local recent = { depth=200, n=1, add=function(self,spl) local n = self.n self[n] = spl self[n-self.depth] = nil self.n = n + 1 end, text=function(self) local t = {"0.1s, dB"} local offset = self.n-self.depth-1 for i=1,self.depth do if self[i+offset] then t[#t+1] = ("%0.1f, %s"):format(i/10,self[i+offset]) end end return table.concat(t,"\n") end } -- Quick and dirty way to force the UART to have the -- tty driver settings we need for clean raw access -- to the port. os.execute("stty -F /dev/ttyAMA0 115200" .." pass8 raw -iexten" .." -echo -echoe -echok -echoke -echoctl") -- Open the UART for both reading and writing, and send -- the SPLear command to go into raw SPL sample mode. The -- output must be unbuffered because the current SPLear -- firmware would revert to 0.5 Hz summary mode if it -- receives a newline. local port = assert(io.open('/dev/ttyAMA0','r+')) port:setvbuf"no" -- no output buffer at all port:write"S" -- so this write is immediate -- Loop reading the SPL samples and watching for loud -- noises, keeping a log of recent samples as we go. -- When a loud noise is heard, keep logging for a bit -- before sending email. Include the log in the email. local spl, spl0 local triggered = false local eek = "" local addr = flatten(address) print("Notifying "..addr) while true do local line = port:read"*l" -- read a single line spl = tonumber(line) if spl then spl = 0.75 * spl io.write("SPL "..(triggered and "TRG " or " "), spl, "\r") recent:add(spl) -- Watch for the trigger condition: 12 dB louder if not triggered and spl0 and (spl - spl0 > 12.) then triggered = math.floor(recent.depth * 2. / 3.) eek = "EEK! "..spl.." dB" end if triggered then triggered = triggered - 1 if triggered == 0 then triggered = false local data = recent:text() local pngfile = "startled-plot.png" plot.plot(data, pngfile, recent.depth/30., -- 1/3 trigger pos, 1/10 for time scale "Startled at "..isodate()) local body = eek.."\n"..data print("email " .. addr, eek, isodate()) mpack(addr, eek, pngfile) end end spl0 = spl end end |