openwrt: adapt repository structure to simplify build environment setup

This commit is contained in:
Bart Van Der Meerssche 2009-11-20 10:42:43 +00:00
commit 93582b14fe
1486 changed files with 42 additions and 20 deletions

View file

@ -0,0 +1,44 @@
# Copyright (c) 2008 jokamajo.org
# $Id$
include $(TOPDIR)/rules.mk
PKG_NAME:=flukso
PKG_VERSION:=1.0
PKG_RELEASE:=1
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
include $(INCLUDE_DIR)/package.mk
define Package/flukso
SECTION:=utils
CATEGORY:=Utilities
DEPENDS:=+liblua-xmlrpc +ntpclient
TITLE:=Flukso - community metering
endef
define Package/flukso/description
This package contains the necessary openwrt files for the Flukso [www.flukso.net] community metering application.
endef
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
$(CP) ./src/* $(PKG_BUILD_DIR)/
endef
define Build/Compile
endef
define Package/flukso/install
$(INSTALL_DIR) $(1)/usr/share/lua/flukso/
$(CP) $(PKG_BUILD_DIR)/flukso.lua $(1)/usr/share/lua/flukso/
$(CP) $(PKG_BUILD_DIR)/data.lua $(1)/usr/share/lua/flukso/
$(CP) $(PKG_BUILD_DIR)/dbg.lua $(1)/usr/share/lua/flukso/
$(CP) $(PKG_BUILD_DIR)/auth.lua $(1)/usr/share/lua/flukso/
$(CP) $(PKG_BUILD_DIR)/heartbeat.lua $(1)/usr/share/lua/flukso/
$(INSTALL_DIR) $(1)/etc/init.d/
$(CP) $(PKG_BUILD_DIR)/flukso.init $(1)/etc/init.d/flukso
endef
$(eval $(call BuildPackage,flukso))

View file

@ -0,0 +1,73 @@
--
-- auth.lua: property and methods for generating hmac-sha1 authentication
-- Copyright (c) 2009 jokamajo.org
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- as published by the Free Software Foundation; either version 2
-- of the License, or (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
--
-- $Id$
--
require 'luci.model.uci'
require 'lxyssl'
local string, table, os, luci, lxyssl =
string, table, os, luci, lxyssl
local getfenv, setmetatable, type, pairs, tostring =
getfenv, setmetatable, type, pairs, tostring
module(...)
local modenv = getfenv()
function new()
return setmetatable({}, {__index = modenv})
end
function load(T)
local uci = luci.model.uci.cursor()
uci:foreach ('system', 'system',
function(section)
T.device, T.key, T.version = section.device, section.key, section.version
end
)
end
function hmac(T, M, timestamp)
function string.hex(x)
local t={}
for c in x:gmatch('(.)') do t[#t+1]=string.format('%02x', c:byte()) end
return table.concat(t,'')
end
function serialise(M)
if type(M) == 'table' then
local sequence = ''
for k, v in pairs(M) do
if v ~= nil then
sequence = sequence..tostring(k)..serialise(v)
end
end
return sequence
else
return tostring(M)
end
end
T.timestamp = timestamp or os.time()
T.message = T.timestamp..':'..serialise(M)..':'..T.key
T.signature = lxyssl.hash('hmac-sha1', T.key):digest(T.message):hex()
T.message, T.key, T.version = nil, nil, nil
end

View file

@ -0,0 +1,62 @@
--
-- data.lua: property and methods for manipulating incoming measurements
-- Copyright (c) 2009 jokamajo.org
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- as published by the Free Software Foundation; either version 2
-- of the License, or (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
--
-- $Id$
--
local os, math, table =
os, math, table
local getfenv, setmetatable, pairs =
getfenv, setmetatable, pairs
module (...)
local modenv = getfenv() -- module environment
function new()
return setmetatable({}, {__index = modenv})
end
function add(M, meter, timestamp, value)
if not M[meter] then M[meter] = {} end
M[meter][timestamp] = value
end
function clear(M)
for meter in pairs(M) do
M[meter] = nil
end
end
function filter(M, span, offset)
for meter, T in pairs(M) do
local H = {} -- helper table, an indexed array containing all the measurement's timestamps
for timestamp in pairs(T) do H[#H+1] = timestamp end
table.sort(H) -- sort in ascending order, oldest timestamps will be treated first
local i = 2
while not (H[i+1] == nil or H[i] > os.time()-offset) do
if math.floor(H[i-1]/span) == math.floor(H[i]/span) and math.floor(H[i]/span) == math.floor(H[i+1]/span) then
T[H[i]] = nil
table.remove(H, i)
else
i = i+1
end
end
end
end

View file

@ -0,0 +1,50 @@
--
-- dbg.lua: library for debugging with vardump in Lua
-- Lua Programming Gems Chapter 3
-- Vardump: The Power of Seeing What's Behind
-- Copyright 2008 by Tobias Sülzenbrück and Christoph Beckmann
--
-- $Id$
--
local getfenv, getmetatable, print, pairs, type, tostring = getfenv, getmetatable, print, pairs, type, tostring
module(...)
local modenv = getfenv() -- module environment
function vardump(value, depth, key)
local linePrefix = ""
local spaces = ""
if key ~= nil then
linePrefix = "["..key.."] = "
end
if depth == nil then
depth = 0
else
depth = depth + 1
for i = 1,depth do spaces = spaces.." " end
end
if type(value) == 'table' then
-- mTable = getmetatable(value)
-- if mTable == nil then
print(spaces..linePrefix.."(table) ")
-- else
-- print(spaces.."(metatable) ")
-- value = mTable
-- end
for tableKey, tableValue in pairs(value) do
vardump(tableValue, depth, tableKey)
end
elseif type(value) == 'function'
or type(value) == 'thread'
or type(value) == 'userdata'
or value == nil
then
print(spaces..tostring(value))
else
print(spaces..linePrefix.."("..type(value)..") "..tostring(value))
end
end

View file

@ -0,0 +1,17 @@
#!/bin/sh /etc/rc.common
# Copyright (c) 2008-2009 jokamajo.org
# $Id$
START=98
start() {
stty 4800 < /dev/ttyS0
/usr/share/lua/flukso/flukso.lua >&- 2>&- <&- &
/usr/share/lua/flukso/heartbeat.lua 1 >&- 2>&- <&-
echo -e "$(date '+%M') * * * * /usr/share/lua/flukso/heartbeat.lua 0\n"'*/15 * * * * [ -z "$(ps | grep '\'flukso.lu[a]\'')" ] && reboot' | crontab -
}
stop() {
crontab -r
kill -SIGKILL $(ps | grep 'flukso.lu[a]' | awk '{print $1}')
}

View file

@ -0,0 +1,154 @@
#!/usr/bin/env lua
--
-- flukso.lua: flukso deamon running on openwrt
-- Copyright (c) 2008-2009 jokamajo.org
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- as published by the Free Software Foundation; either version 2
-- of the License, or (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
--
-- $Id$
--
require 'posix'
require 'xmlrpc.http'
data = require 'flukso.data'
auth = require 'flukso.auth'
dbg = require 'flukso.dbg'
local param = {xmlrpcaddress = 'http://logger.flukso.net/xmlrpc',
xmlrpcversion = '1',
xmlrpcmethod = 'logger.measurementAdd',
device = '/dev/ttyS0',
interval = 300}
function receive(device)
return coroutine.wrap(function()
-- open the connection to the syslog deamon, specifying our identity
posix.openlog('flukso')
posix.syslog(30, 'starting the flukso deamon')
posix.syslog(30, 'listening for pulses on '..device..'...')
for line in io.lines(device) do
if line:sub(1, 3) == 'pls' and line:len() == 47 and line:find(':') == 37 then -- user data + additional data integrity checks
posix.syslog(30, 'received pulse from '..device..': '..line:sub(5))
-- flash the power led for 50ms
os.execute('gpioctl clear 4')
socket.select(nil, nil, 0.05)
os.execute('gpioctl set 4')
local meter, value = line:sub(5, 36), tonumber(line:sub(38))
coroutine.yield(meter, os.time(), value)
elseif line:sub(1, 3) == 'msg' then -- control data
posix.syslog(31, 'received message from '..device..': '..line:sub(5))
else
posix.syslog(27, 'input error on '..device..': '..line)
end
end
posix.syslog(30, 'closing down the flukso deamon')
os.exit()
end)
end
function buffer(source, interval)
return coroutine.wrap(function()
local measurements = data.new()
local threshold = os.time() + interval
while true do
local meter, timestamp, value = source()
if meter ~= nil and timestamp > 1234567890 then measurements:add(meter, timestamp, value) end
if timestamp > threshold and next(measurements) then --checking whether table is not empty
coroutine.yield(measurements)
threshold = timestamp + interval
end
end
end)
end
function filter(source, span, offset)
return coroutine.wrap(function()
while true do
local measurements = source()
measurements:filter(span, offset)
coroutine.yield(measurements)
end
end)
end
function send(source, address, version, method)
return coroutine.wrap(function()
while true do
local measurements = source()
local auth = auth.new()
auth:load()
auth:hmac(measurements)
local status, ret_or_err, res = pcall(xmlrpc.http.call,
address..'/'..version,
method,
auth,
measurements)
if status then
posix.syslog(30, tostring(res))
if ret_or_err then --successful xmlrpc call
measurements:clear()
end
else
posix.syslog(27, tostring(ret_or_err)..' '..address..' '..tostring(res))
end
coroutine.yield(measurements)
end
end)
end
function gc(source)
return coroutine.wrap(function()
while true do
local measurements = source()
posix.syslog(31, tostring(collectgarbage('count')*1024)..' bytes of memory used by Lua before garbage collection cycle')
collectgarbage() -- force a complete garbage collection cycle
posix.syslog(31, tostring(collectgarbage('count')*1024)..' bytes of memory used by Lua after garbage collection cycle')
coroutine.yield(measurements)
end
end)
end
-- receive: listen to the serial port for incoming pulses
-- buffer: buffer the pulses in a measurement object
-- filter: sweep recursively to filter all redundant entries
-- send: report the measurements to the server via xmlrpc
-- gc: perform a full garbage collection cycle
local aggregator = gc(
send(
filter(
filter(
filter(
buffer(
receive(param.device)
, param.interval)
, 60, 0)
, 900, 7200)
, 86400, 172800)
, param.xmlrpcaddress, param.xmlrpcversion, param.xmlrpcmethod)
)
while true do
dbg.vardump(aggregator())
end

View file

@ -0,0 +1,90 @@
#!/usr/bin/env lua
--
-- Lua 5.1 heartbeat script running on openwrt
-- Copyright (c) 2008-2009 jokamajo.org
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- as published by the Free Software Foundation; either version 2
-- of the License, or (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
--
-- $Id$
--
if not arg[1] then
print ('Please pass the reset argument as a boolean to the script.')
else
-- load libraries
require 'posix'
require 'xmlrpc.http'
require 'luci.sys'
auth = require 'flukso.auth'
dbg = require 'flukso.dbg'
-- config parameters
local param = {server = 'logger.flukso.net',
xmlrpcaddress = 'http://logger.flukso.net/xmlrpc',
xmlrpcversion = '1',
xmlrpcmethod = 'logger.heartbeat'}
local monitor = {reset = tonumber(arg[1])}
-- open the connection to the syslog deamon, specifying our identity
posix.openlog('heartbeat')
-- calculate hmac and collect relevant monitoring points
local auth = auth.new()
auth:load()
monitor.version = tonumber(auth.version)
monitor.uptime = math.floor(luci.sys.uptime())
monitor.uart_oe = string.match(luci.sys.exec('cat /proc/tty/driver/serial'), 'oe:(%d+)') or 0
system, model, monitor.memtotal, monitor.memcached, monitor.membuffers, monitor.memfree = luci.sys.sysinfo()
auth:hmac(monitor)
dbg.vardump(auth)
dbg.vardump(monitor)
-- send a heartbeat method call
local pcall_ok, return_or_err, pong = pcall(xmlrpc.http.call,
param.xmlrpcaddress..'/'..param.xmlrpcversion,
param.xmlrpcmethod,
auth,
monitor)
dbg.vardump(pong)
if pcall_ok and return_or_err then
auth:load()
auth:hmac(pong.upgrade, pong.timestamp)
if auth.signature == pong.signature and pong.timestamp > os.time() - 300 then
posix.syslog(31, 'successful heartbeat authentication')
if tonumber(pong.upgrade) == monitor.version then --reset device
os.execute('reboot')
elseif tonumber(pong.upgrade) > monitor.version then -- upgrade device to specified version
os.execute('wget -P /tmp http://'..param.server..'/files/upgrade/upgrade.'..pong.upgrade)
os.execute('chmod a+x /tmp/upgrade.'..pong.upgrade)
os.execute('/tmp/upgrade.'..pong.upgrade)
os.execute('rm /tmp/upgrade.'..pong.upgrade)
end
end
else
posix.syslog(11, tostring(return_or_err))
end
-- close the connection to the syslog deamon
posix.closelog()
end

View file

@ -0,0 +1,14 @@
#! /usr/bin/env lua
require 'socket'
local fd = assert(io.open('/dev/ttyUSB0', 'w'))
for i = tonumber(arg[1]), tonumber(arg[2]) do
local data = 'pls ' .. arg[3] .. ':' .. string.sub(string.rep('0', 10) .. i, -10, -1) .. '\n'
fd:write(data)
socket.select(nil, nil, 0.001)
end
fd:close()