%D \module %D [ file=s-youless, %D version=2013.11.12, %D title=\CONTEXT\ Style File, %D subtitle=Youless Graphics, %D author=Hans Hagen, %D date=\currentdate, %D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] %C %C This module is part of the \CONTEXT\ macro||package and is %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. %D This is experimental code. When I have collected enough data I will make the %D graphics nicer and provide some more. %D %D The Jouless can serve web pages but there is not much detail in them. They also are %D somewhat bad \HTML, like unquoted attributes and so. We don't need this anyway as we %D can also fetch data directly. The data is collected using a dedicated helper script %D (of course we could just call it as module too). The data is fetched from the Jouless %D device using queries (currently we use json, but a more direct parsing of data might %D be more efficient). The data is converted into a proper \LUA\ table and saved (merged). % in cronjob on one of the servers: % % mtxrun --script youless --collect --host=192.168.2.50 --nobackup --electricity youless-electricity.lua \startluacode require("util-you") local round = math.round moduledata.youless = { } local defaults = { electricity = { unit = "watt", maxunit = "maxwatt", }, watt = { unit = "watt", maxunit = "maxwatt", }, pulse = { unit = "watt", maxunit = "maxwatt", }, gas = { unit = "liters", maxunit = "maxliters", }, } local function process(specification,thevariant) local data, message = utilities.youless.analyze(specification.filename or "youless-electricity.lua") if not data then context(message) return end local variant = data.variant local unit = specification.unit local maxunit = specification.maxunit if thevariant then if variant ~= thevariant then context("invalid variant") return end elseif variant then local d = defaults[variant] if d then unit = d.unit maxunit = d.maxunit else context("unknown variant") return end else context("invalid variant") return end local year = tonumber(specification.year) or os.today().year local month = tonumber(specification.month) local years = data.years local max = specification[maxunit] if not max then if unit == "watt" then max = 10000 elseif unit == "liters" then max = 1000 else max = 5000 -- can't happen end end local firstmonth = month or 1 local lastmonth = month or 12 local max = max local delta = round(max/10) local scale = round(delta/20) local mark = 3 for y=year,year do local year = years[y] if year then local grand = 0 for m=firstmonth,lastmonth do local month = year.months[m] if month then context.startMPpage { offset = "10pt" } context("linecap := butt; pickup pencircle scaled .5") for i=0,(math.div(max,delta)+1)*delta,delta/10 do context("draw (%s,%s) -- (%s,%s) withcolor .6white ;",0,i/scale,31 * 24,i/scale) end context("draw (0,%s) -- (31 * 24,%s) dashed dashpattern(on 6 off 6) withcolor darkgreen withpen pencircle scaled 1 ;",year [unit]/scale,year [unit]/scale) context("draw (0,%s) -- (31 * 24,%s) dashed dashpattern(off 6 on 6) withcolor darkred withpen pencircle scaled 1 ;",month[unit]/scale,month[unit]/scale) local days = month.days local total = 0 if days then local nd = os.nofdays(y,m) for d=1,nd do local day = days[d] local xoffset = (d-1) * 24 local wd = os.weekday(d,m,y) local weekend = wd == 1 or wd == 7 if not weekend then -- okay elseif mark == 1 then context("draw (%s,%s) -- (%s,%s) ; ",xoffset, -17.5,xoffset, -32.5) context("draw (%s,%s) -- (%s,%s) ; ",xoffset+24,-17.5,xoffset+24,-32.5) elseif mark == 2 then context("draw (%s,%s) -- (%s,%s) ;",xoffset, -17.5,xoffset+24,-17.5) context("draw (%s,%s) -- (%s,%s) ;",xoffset, -32.5,xoffset+24,-32.5) elseif mark == 3 then context("draw unitsquare xysized (%s,%s) shifted (%s,%s) ;",24,15,xoffset,-32.5) end context([[draw textext("\strut%s") shifted (%s,%s) ;]],d,xoffset + 12,-25) if day then for h=0,23 do local hours = day.hours if hours then local hour = hours[h] if hour then local dx = xoffset + h local dy = hour[unit]/scale local dm = hour[maxunit]/scale context("draw (%s,%s) -- (%s,%s) withcolor %s ;",dx, 0,dx,dy,weekend and "darkmagenta" or "darkblue") context("draw (%s,%s) -- (%s,%s) withcolor %s ;",dx,dy,dx,dm,"darkgray") end end end local use = day.total if use then context([[draw textext("\strut\small\small\small%0.1f") shifted (%s,%s) ;]],use/1000,xoffset + 12,-7.5) total = total + use end end end for d=0,30 do local xoffset = d * 24 context("draw (%s,%s) -- (%s,%s) withcolor darkgray ;",xoffset+ 0,0,xoffset+ 0,-10) context("draw (%s,%s) -- (%s,%s) withcolor darkgray ;",xoffset+ 6,0,xoffset+ 6,-2.5) context("draw (%s,%s) -- (%s,%s) withcolor darkgray ;",xoffset+12,0,xoffset+12,-5) context("draw (%s,%s) -- (%s,%s) withcolor darkgray ;",xoffset+18,0,xoffset+18,-2.5) end local xoffset = 31 * 24 context("draw (%s,%s) -- (%s,%s) withcolor darkgray ;",xoffset,0,xoffset,-10) end grand = grand + total local max = (math.div(max,delta)) for i=0,max*delta,delta do if i > 0 then context([[draw textext.lft("\hbox to 3.5em{\hss\strut%r}") shifted (%s,%s) ; ]],i,-10,i/scale) end context("draw (%s,%s) -- (%s,%s) withcolor .2white ;",0,i/scale,31 * 24,i/scale) end context([[draw textext ("\strut\Word{%s}\enspace\emdash\enspace\month{%s}\enspace%s") shifted (%s,%s) ; ]],variant, m, y, 31 * 24 / 2, -50) context([[draw textext.lft("\hbox to 3.5em{\hss\strut%s}") shifted (%s,%s) ; ]],unit,-10,-25) context([[draw textext.lft("\hbox to 3.5em{\hss\strut\small\small\small%0.1f %s}") shifted (%s,%s) ;]],total/1000,unit == "watt" and "kWh" or [[m\high{3}]],-10, -7.5) context([[draw textext.lft("\hbox to 3.5em{\hss\strut\small\small\small\Sigma\nbsp%0.1f %s}") shifted (%s,%s) ;]],grand/1000,unit == "watt" and "kWh" or [[m\high{3}]],-10,-50.0) context.stopMPpage() else -- maybe placeholder end end end end end function moduledata.youless.kwh(specification) -- todo end function moduledata.youless.electricity(specification) specification.unit = "watt" specification.maxunit = "maxwatt" process(specification,"electricity") end moduledata.youless.watt = moduledata.youless.electricity function moduledata.youless.gas(specification) specification.unit = "liters" specification.maxunit = "maxliters" process(specification,"gas") end function moduledata.youless.pulse(specification) specification.unit = "watt" specification.maxunit = "maxwatt" process(specification,"pulse") end function moduledata.youless.graphics(specification) process(specification) end \stopluacode \continueifinputfile{s-youless.mkiv} \setupbodyfont[dejavu] % smaller sizes also look ok % printer (oce) : > 3000 W startup (900 W idle, 2000 W printing) % coffeemaker : 1500 W when heating % baseline day : 2250 W (servers, airco, workstations, routers, switches, heating, etc) % baseline night : 1750 W \starttext \startluacode -- os.execute([[mtxrun --script youless --collect --electricity "c:/data/system/youless/data/youless-electricity.lua"]]) -- os.execute([[mtxrun --script youless --collect --electricity --nobackup "c:/data/system/youless/data/youless-electricity.lua"]]) -- moduledata.youless.electricity { year = 2017, filename = "c:/data/system/youless/data/youless-electricity.lua" } moduledata.youless.electricity { year = 2017, filename = "youless-electricity.lua" } \stopluacode \stoptext