if not modules then modules = { } end modules ['mtx-signal'] = { version = 1.002, comment = "companion to mtxrun.lua", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright = "PRAGMA ADE / ConTeXt Development Team", license = "see context related readme files" } -- Using wipe and prune is only for experiments. One can better use a switch -- because onless (in HH's case) a dedicated lamp is used for the non runner -- processes. So mostly for feature for AFO running on the same hub as HH. -- mtxrun --script signal --signals --lamps=2,3 runner -- mtxrun --script signal --signals --lamps=1,2,3,4 runner -- mtxrun --script signal --servers --url=https://192.168.2.1/ hue -- mtxrun --script signal --servers --url=http://192.168.2.1/ conbee -- mtxrun --script signal --servers --token=XXXXXXXXXX conbee -- mtxrun --script signal --servers --protocol=deconz conbee -- local connect = [[curl --silent --insecure -X POST -i "http://127.0.0.1/api" --data "{ \"devicetype\" : \"demohans\" }"]] -- local s = os.resultof(connect) -- local u = "A1EDC09865" -- curl -X GET -i "http://127.0.0.1/api/E2FB3528DA/lights" --data "{ \"devicetype\" : \"test-prive\" }" -- curl -X GET -i "http://127.0.0.1/api/E2FB3528DA/sensors" -- tasklist /V /FO CSV -- last column Window Title local helpinfo = [[ mtx-signal ConTeXt State Reporting 1.00 create configuration show configuration show enabled servers and signals set parameter in server entry set parameter in signal entry enable a given signal category disable a given signal category use the given server current run (lamp) number current lamp (run) number reset, busy, error, done, maxruns, problem, finished set all devices turn them off set timer on --lamp=n (use with care or not, administrator !) reset --max=n timer (use with care or not, administrator !) Examples mtxrun --script signal --servers --url=http://127.0.0.1 --token=ABC --protocol=hue huehub mtxrun --script signal --usage huehub mtxrun --script signal --enable runner mtxrun --script signal --disable mtxrun --script signal --info mtxrun --script signal --state=busy runner mtxrun --script signal --state=busy --run=2 runner mtxrun --script signal --state=off runner ]] local arguments = environment.arguments local files = environment.files local application = logs.application { name = "mtx-signal", banner = "ConTeXt State Reporting 1.00", helpinfo = helpinfo, } scripts = scripts or { } scripts.signal = scripts.signal or { } -- This only handles "runner" but we might add more later. I also use it for -- configuring "distribution" and "teststuite" but there we don't wipe -- lights and use switches. Wiping is fragile anyway. And there's also the -- -- mtxrun --script --reset -- -- that one can use to turn of the runner lamps. do local function gettrigger() local signal = (type(arguments.signal) == "string" and arguments.signal) or files[1] or "runner" local trigger = utilities.signals.initialize(signal) if trigger then return trigger else application.report("no trigger %a",signal) end end function scripts.signal.trigger() local trigger = gettrigger() if trigger then trigger( arguments.state or "reset", arguments.run or arguments.lamp or 0, arguments.all or false ) end end function scripts.signal.wipe() -- set timer on lamp local trigger = gettrigger() if trigger then local lamp = tonumber(arguments.lamp) if lamp and arguments.force then local id = trigger("wipe",lamp,tonumber(arguments.minutes) or 5) application.report("wiping lamp %a has id %a",lamp,id) -- -- rather hue specific so let's not do it now -- -- if id then -- local data = utilities.signals.loadstate(true) -- local timers = data.usage.timers or { } -- data.usage.timers = timers -- timers[id] = true -- utilities.signals.savestate(data) -- end -- else application.report("setting timer on lamp %a needs --lamp=l [--minutes=m] and --force",lamp) end end end function scripts.signal.prune() -- resets timer on lamp local trigger = gettrigger() if trigger then -- -- rather hue specific so let's not do it now -- -- local data = utilities.signals.loadstate(true) -- for id in table.sortedhash(data.usage.timers or { }) do -- trigger("prune",timers[i]) -- end -- data.usage.timers = nil -- utilities.signals.savestate(data) -- local id = tonumber(arguments.id) local max = tonumber(arguments.max) if (id or max) and arguments.force then trigger("prune",id,max) else application.report("pruning %i rules needs --id=i or --max=m and --force",max) end end end end local function loadconfiguration(create) local data, name = utilities.signals.loadstate() if not data then if create then application.report("creating configuration file %a",utilities.signals.configuration) data = { } else application.report("no configuration file %a found",utilities.signals.configuration) return end end -- sanity check if not data.version then data.version = utilities.signals.version end if not data.comment then data.comment = "signal setup file" end if not data.servers then data.servers = { } end if not data.signals then data.signals = { } end if not data.usage then data.usage = { } end return data, name end local function saveconfiguration(data) return utilities.signals.savestate(data) end function scripts.signal.reset() local data = loadconfiguration(true) local signals = data.signals if signals then for signal in table.sortedhash(signals) do local trigger = utilities.signals.initialize(signal) if trigger then trigger( "reset", 0, true ) end end end end do function scripts.signal.create() local data, name = loadconfiguration() if data then application.report("configuration found in %a",name) else local data = loadconfiguration(true) local name = saveconfiguration(data) application.report("configuration saved in %a",name) end end function scripts.signal.servers() local server = files[1] or "default" local data = loadconfiguration(true) local servers = data.servers local usage = data.usage local target = servers[server] or { } local update = false if arguments.delete then if usage.server == server then usage.server = nil end target = nil else if type(arguments.url) == "string" then target.url = arguments.url update = true end if type(arguments.token) == "string" then target.token = arguments.token update = true end if type(arguments.protocol) == "string" then target.protocol = arguments.protocol update = true end if update or not usage.server then usage.server = server end end servers[server] = target saveconfiguration(data) end function scripts.signal.usage() local data = loadconfiguration(true) local usage = data.usage if type(arguments.server) == "string" then usage.server = arguments.server elseif files[1] then usage.server = files[1] end if type(arguments.enable) == "boolean" then usage.enabled = arguments.enable elseif type(arguments.disable) == "boolean" then usage.enabled = not arguments.disable end saveconfiguration(data) end function scripts.signal.signals() local signal = files[1] or "default" local data = loadconfiguration(true) local signals = data.signals local target = signals[signal] or { } if arguments.delete then target = nil else if type(arguments.lamps) == "string" then local lamps = utilities.parsers.settings_to_array(arguments.lamps) local clean = { } for i=1,#lamps do clean[#clean+1] = tonumber(lamps[i]) end if #clean == 0 then clean = nil end target.lamps = clean end end signals[signal] = target saveconfiguration(data) end end do local function set(what) local data = loadconfiguration(true) local signal = arguments.signal or environment.files[1] if signal then local signals = data.signals if signals then local specific = signals[signal] if specific then if type(what) == "boolean" then specific.enabled = what saveconfiguration(data) else return specific.enabled and "enabled" or "disabled" end end end elseif type(what) == "boolean" then data.usage.enabled = what saveconfiguration(data) end end function scripts.signal.enable () set(true ) end function scripts.signal.disable() set(false) end function scripts.signal.enabled() print(set( )) end end function scripts.signal.show() local data, name = loadconfiguration() if data then application.report("file: %s",name) application.report("data:\n\n%s\n",table.serialize(data,false)) end end function scripts.signal.sleep() os.sleep(tonumber(arguments.sleep) or 2) end function scripts.signal.info() local data, name = loadconfiguration() if data then local t = { } local s = { } local u = data.usage.server local e = data.usage.enabled for k, v in table.sortedhash(data.servers) do if k == u then t[#t+1] = k else t[#t+1] = "[" .. k .. "]" end end for k, v in table.sortedhash(data.signals) do local l = v.lamps if l then l = table.concat(l,",") else l = "?" end l = k .. ":" .. l if k == v.enabled then s[#s+1] = "[" .. l .. "]" else s[#s+1] = l end end application.report("servers : % t",t) application.report("signals : % t",s) if type(e) == "boolean" then application.report("usage : %s",e and "enabled" or "disabled") end end end if not scripts.signal.trigger then return elseif arguments.create then scripts.signal.create() elseif arguments.servers then scripts.signal.servers() elseif arguments.signals then scripts.signal.signals() elseif arguments.usage then scripts.signal.usage() elseif arguments.enable then scripts.signal.enable() elseif arguments.disable then scripts.signal.disable() elseif arguments.reset then scripts.signal.reset() elseif arguments.show then scripts.signal.show() elseif arguments.wipe then scripts.signal.wipe() elseif arguments.prune then scripts.signal.prune() elseif arguments.state then scripts.signal.trigger() elseif arguments.enabled then scripts.signal.enabled() elseif arguments.info then scripts.signal.info() elseif arguments.sleep then scripts.signal.sleep() elseif arguments.exporthelp then application.export(arguments.exporthelp,environment.files[1]) else application.help() end