diff --git a/mote/v2/openwrt/package/flukso/Makefile b/mote/v2/openwrt/package/flukso/Makefile index f800d2a..9b7af1a 100644 --- a/mote/v2/openwrt/package/flukso/Makefile +++ b/mote/v2/openwrt/package/flukso/Makefile @@ -27,9 +27,12 @@ define Build/Prepare mkdir -p $(PKG_BUILD_DIR) $(CP) ./src/* $(PKG_BUILD_DIR)/ $(CP) ./luasrc/* $(PKG_BUILD_DIR)/ + $(CP) ./config/* $(PKG_BUILD_DIR)/ endef define Package/flukso/install + $(INSTALL_DIR) $(1)/etc/config + $(INSTALL_DATA) $(PKG_BUILD_DIR)/flukso.uci $(1)/etc/config/flukso $(INSTALL_DIR) $(1)/usr/lib/lua $(INSTALL_DATA) $(PKG_BUILD_DIR)/dbg.lua $(1)/usr/lib/lua/ $(INSTALL_DIR) $(1)/usr/lib/lua/rrd @@ -40,6 +43,8 @@ define Package/flukso/install $(INSTALL_BIN) $(PKG_BUILD_DIR)/luad $(1)/usr/sbin/ $(LN) /usr/sbin/luad $(1)/usr/sbin/fluksod $(INSTALL_BIN) $(PKG_BUILD_DIR)/fluksod.lua $(1)/usr/sbin/ + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/fsync.lua $(1)/usr/bin/fsync endef $(eval $(call BuildPackage,flukso)) diff --git a/mote/v2/openwrt/package/flukso/config/flukso.uci b/mote/v2/openwrt/package/flukso/config/flukso.uci new file mode 100644 index 0000000..b371c63 --- /dev/null +++ b/mote/v2/openwrt/package/flukso/config/flukso.uci @@ -0,0 +1,53 @@ +config settings main + option hw_major 2 + option hw_minor 0 + option sw_major 1 + option sw_minor 0 + option max_sensors 6 + option reset_counters 0 + +### sensor config options +# config sensor <1..6> +# option id +# option type +# list port <1..6> +# option constant [] +# option voltage [] +# option current [] + +config sensor 1 + option id 0123456789abcdef0123456789abcde1 + option type analog + list port 1 + option voltage 230 + option current 50 + +config sensor 2 + option id 0123456789abcdef0123456789abcde2 + option type analog + list port 2 + option voltage 230 + option current 50 + +config sensor 3 + option id 0123456789abcdef0123456789abcde3 + option type analog + list port 3 + option voltage 230 + option current 50 + +config sensor 4 + option id 0123456789abcdef0123456789abcde4 + option type pulse + list port 4 + option constant 1 + +config sensor 5 + option id 0123456789abcdef0123456789abcde5 + option type pulse + list port 5 + option constant 1 + +config sensor 6 + option type uart + list port 6 diff --git a/mote/v2/openwrt/package/flukso/luasrc/fsync.lua b/mote/v2/openwrt/package/flukso/luasrc/fsync.lua new file mode 100755 index 0000000..5c3f53a --- /dev/null +++ b/mote/v2/openwrt/package/flukso/luasrc/fsync.lua @@ -0,0 +1,193 @@ +#!/usr/bin/env lua + +local dbg = require 'dbg' +local nixio = require 'nixio' +nixio.fs = require 'nixio.fs' +local uci = require 'luci.model.uci'.cursor() + +local CTRL_PATH = '/var/run/fluksod/ctrl' +local CTRL_PATH_IN = CTRL_PATH .. '/in' +local CTRL_PATH_OUT = CTRL_PATH .. '/out' + +local O_RDWR_NONBLOCK = nixio.open_flags('rdwr', 'nonblock') +local POLLIN = nixio.poll_flags('in') +local POLL_TIMEOUT_MS = 1000 +local MAX_TRIES = 5 + +local ctrl = { fdin = nixio.open(CTRL_PATH_IN, O_RDWR_NONBLOCK), + fdout = nixio.open(CTRL_PATH_OUT, O_RDWR_NONBLOCK), + events = POLLIN, + revents = 0 } + +ctrl.fd = ctrl.fdout -- need this entry for nixio.poll +ctrl.line = ctrl.fdout:linesource() + +if ctrl.fdin == nil or ctrl.fdout == nil then + print('Unable to open the ctrl fifos.') + print('Exiting...') + os.exit(1) +end + +-- TODO acquire an exclusive lock on the ctrl fifos or exit + + +local function send(ctrl, cmd) + while ctrl.line() do end -- flush the out fifo + + for i = 1, MAX_TRIES do + ctrl.fdin:write(cmd .. '\n') + + local poll, errno, errmsg = nixio.poll({ ctrl }, POLL_TIMEOUT_MS) + + if poll < 0 then + print('Poll failed with error message: ' .. errmsg) + + elseif poll == 0 then + print('Poll timed out after ' .. POLL_TIMEOUT_MS .. 'ms') + + elseif poll > 0 then + reply = ctrl.line() + + if cmd:sub(1, 1) == 's' then + if reply == cmd then + print(reply .. ' .. ok') + return reply + else + print(reply .. ' .. nok .. should be ' .. cmd .. ' instead') + end + elseif cmd:sub(1, 2) == reply:sub(1, 2) then + print(reply .. ' .. ok') + return reply + else + print(reply .. ' .. nok') + end + end + end + + print(MAX_TRIES .. ' write attempts failed. Exiting ...') + os.exit(2) +end + +local function toc(num) + return num - 1 +end + + +-- parse and load /etc/config/flukso +local flukso = uci:get_all('flukso') + +local HW_CHECK_OVERRIDE = (arg[1] == '-f') + +local MAX_SENSORS = tonumber(flukso.main.max_sensors) +local METERCONST_FACTOR = 0.449 + +local GET_HW_VERSION = 'gh' +local GET_HW_VERSION_R = '^gh%s+(%d+)%s+(%d+)$' +local SET_ENABLE = 'se %d %d' +local SET_PHY_TO_LOG = 'sp' -- with [1..MAX_SENSORS] arguments +local SET_METERCONST = 'sm %d %d' +local SET_COUNTER = 'sc %d %d' + +-- check hardware version +local hw_major, hw_minor = send(ctrl, GET_HW_VERSION):match(GET_HW_VERSION_R) + +if hw_major ~= flukso.main.hw_major or hw_minor > flukso.main.hw_minor then + print(string.format('Hardware check (major: %s, minor: %s) .. nok', hw_major, hw_minor)) + if hw_major ~= flukso.main.hw_major then + print('Major version does not match.') + end + + if hw_minor > flukso.main.hw_minor then + print('Sensor board minor version is not supported by this package.') + end + + if HW_CHECK_OVERRIDE then + print('Overridden. Good luck!') + else + print('Use -f to override this check at your own peril.') + os.exit(3) + end +else + print(string.format('Hardware check (major: %s, minor: %s) .. ok', hw_major, hw_minor)) +end + +-- disable all ports +for i = 1, MAX_SENSORS do + local cmd = string.format(SET_ENABLE, toc(i), 0) + send(ctrl, cmd) +end + +-- populate phy_to_log +local phy_to_log = {} + +for i = 1, MAX_SENSORS do + local set = { analog = true, pulse = true } + + if flukso[tostring(i)] ~= nil and set[flukso[tostring(i)]['type']] then + local ports = flukso[tostring(i)].port or {} + + for j = 1, #ports do + phy_to_log[toc(tonumber(ports[j]))] = toc(i) + end + end +end + +for i = 0, MAX_SENSORS - 1 do + if not phy_to_log[i] then + phy_to_log[i] = 0xff + end +end + +local cmd = SET_PHY_TO_LOG .. ' ' .. table.concat(phy_to_log, ' ', 0) +send(ctrl, cmd) + +-- populate meterconst +for i = 1, MAX_SENSORS do + local cmd + + if flukso[tostring(i)] == nil then + cmd = string.format(SET_METERCONST, toc(i), 0) + + elseif flukso[tostring(i)]['type'] == 'analog' then + local voltage = tonumber(flukso[tostring(i)].voltage) + local current = tonumber(flukso[tostring(i)].current) + cmd = string.format(SET_METERCONST, toc(i), math.floor(METERCONST_FACTOR * voltage * current)) + + elseif flukso[tostring(i)]['type'] == 'pulse'then + local meterconst = tonumber(flukso[tostring(i)].constant) + cmd = string.format(SET_METERCONST, toc(i), meterconst) + else + cmd = string.format(SET_METERCONST, toc(i), 0) + end + + if cmd then send(ctrl,cmd) end +end + +-- populate counter if reset_counters is set +if flukso.main.reset_counters == '1' then + for i = 1, MAX_SENSORS do + local cmd = string.format(SET_COUNTER, toc(i), 0) + send(ctrl, cmd) + end + + uci:set('flukso', 'main', 'reset_counters', 0) + uci:commit('flukso') +end + +-- enable configured ports +for i = 1, MAX_SENSORS do + if flukso[tostring(i)] ~= nil then + local ports = flukso[tostring(i)].port or {} + + for j = 1, #ports do + cmd = string.format(SET_ENABLE, toc(tonumber(ports[j])), 1) + send(ctrl, cmd) + end + end +end + +-- clean up +ctrl.fdin:close() +ctrl.fdout:close() + +print(arg[0] .. ' completed successfully. Bye!')