fix rrd rotation
[julm/air-duino.git] / GNUmakefile
index 408e098079670a5ae3b2e984e5ae307f1d015d85..c1ffc9e8677b9d8efc2a7dbd45fdc675baace4c3 100644 (file)
@@ -1,19 +1,41 @@
-# Licence: WTFPLv2 <http://www.wtfpl.net/txt/copying/>
+# Licence: GPLv3+ <http://www.gnu.org/licenses/gpl.txt>
 # Copyright 2015: Julien Moutinho <julm+air@autogeree.net>
 
+#
+## GNUmakefile
+###
 .SECONDARY:
 .SUFFIXES:
        MAKEFLAGS += -r
-RRD_CF:=AVERAGE
-SENSORS:= \
- humidity \
+
+uniq=$(if $1,$(call \
+       uniq,$(wordlist 2,$(words $1),$1),$2 $(if \
+               $(filter $(firstword $1),$2),,$(firstword $1))) \
+ ,$2)
+
+views := png html5
+all: $(views)
+
+#
+## Sensors
+###
+
+SENSOR_LABEL_temperature=Température (°C)
+SENSOR_LABEL_humidity=Humidité (%)
+SENSOR_LABEL_particles=Particules
+SENSOR_LABEL_quality=Qualité de l’air
+sensors := \
  temperature \
+ humidity \
  quality \
  particles
 
-.rrd = $(wildcard rrd/*/*.rrd)
+#
+## Round Robin Database (RRD)
+###
 
-all: png
+RRD_CF := AVERAGE
+.rrd = $(wildcard rrd/*/*.rrd)
 
 #
 ## INO
@@ -36,57 +58,186 @@ ARDUINO_LIBS := \
 
 USER_LIB_PATH := $(abspath ./libraries)
 
+ifeq ($(NO_INO),)
 include $(ARDMK_DIR)/Arduino.mk
+endif
 
 ino: $(TARGET_EEP) $(TARGET_HEX)
 
 #
 ## PNG
 ###
-.PHONY: png $(addprefix png/,$(SENSORS))
-png: $(addprefix png/,$(SENSORS))
-
-ym=$(patsubst %.rrd,,$(notdir $*))
-month_begin=$(shell date +'%s' -d '$(ym)/01')
-month_end=$(shell date +'%s' -d '$(ym)/01 + 1 month - 1 second')
-month_length=$(shell date +'%d' -d '$(ym)/01 + 1 month - 1 second')
-day_begin=$(shell date +'%s' -d '$(ym)/$(day)')
-day_end=$(shell date +'%s' -d '$(ym)/$(day) + 1 month - 1 second')
-
-define png/sensor
-sensor:=$1
-label:=$2
-png/$$(sensor): \
- $$(patsubst rrd/%.rrd,png/$$(sensor)/%.png,$$(.rrd))
-       echo $$@
-
-png/$$(sensor)/%.png: rrd/%.rrd
-       mkdir -p png/$$(sensor)/$$*
+
+define view/sensor/png
+endef
+
+define view/sensor/year/png
+view/$(sensor)/$(year)/png:
+endef
+
+define view/sensor/year/month/png
+view/$(sensor)/$(year)/$(month)/png: \
+view/$(sensor)/$(year)/$(month).png
+
+view/$(sensor)/$(year)/$(month).png: \
+rrd/$(year)/$(month).rrd
+       mkdir -p $$(@D)
        rrdtool graph $$@ \
         -w 785 -h 120 -a PNG \
         --slope-mode \
-        --start $$(month_begin) --end $$(month_end) \
-        --vertical-label '$$(label)' \
+        --start $(month_begin) --end $(month_end) \
+        --vertical-label '$$(SENSOR_LABEL_$(sensor))' \
         --x-grid HOUR:8:DAY:1:DAY:1:86400:%d \
-        DEF:$$(sensor)=rrd/$$*.rrd:$$(sensor):$$(RRD_CF) \
-        LINE1:$$(sensor)'#ff0000':"$$(sensor)"
-       for day in $$(shell seq -w $$(month_length)); \
-        do \
-               day_begin=$$$$(date +'%s' -d "$$(ym)/$$$$day"); \
-               day_end=$$$$(date +'%s' -d "$$(ym)/$$$$day + 1 day - 1 second"); \
-               rrdtool graph png/$$(sensor)/$$*/$$$$day.png \
-                -w 785 -h 120 -a PNG \
-                --slope-mode \
-                --start $$$$day_begin --end $$$$day_end \
-                --vertical-label '$$(label)' \
-                --x-grid MINUTE:10:HOUR:1:HOUR:1:0:%H \
-                DEF:$$(sensor)=rrd/$$*.rrd:$$(sensor):$$(RRD_CF) \
-                LINE1:$$(sensor)'#ff0000':"$$(sensor)"; \
-        done
+        DEF:$(sensor)=rrd/$(year)/$(month).rrd:$(sensor):$$(RRD_CF) \
+        LINE1:$(sensor)'#ff0000':"$(sensor)"
+endef
+
+define view/sensor/year/month/day/png
+view/$(sensor)/$(year)/$(month)/$(day)/png: \
+view/$(sensor)/$(year)/$(month)/$(day).png
+
+view/$(sensor)/$(year)/$(month)/$(day).png: \
+rrd/$(year)/$(month).rrd
+       mkdir -p $$(@D)
+       rrdtool graph $$@ \
+        -w 785 -h 120 -a PNG \
+        --slope-mode \
+        --start $(day_begin) --end $(day_end) \
+        --vertical-label '$$(SENSOR_LABEL_$(sensor))' \
+        --x-grid MINUTE:10:HOUR:1:HOUR:1:0:%H \
+        DEF:$(sensor)=rrd/$(year)/$(month).rrd:$(sensor):$$(RRD_CF) \
+        LINE1:$(sensor)'#ff0000':"$(sensor)";
+endef
+
+#
+## HTML5
+###
+
+define view/sensor/html5
+endef
+
+define view/sensor/year/html5
+view/$(sensor)/$(year)/html5:
+endef
+
+define view/sensor/year/month/html5
+view/$(sensor)/$(year)/$(month)/html5: \
+view/$(sensor)/$(year)/$(month).html5
+
+view/$(sensor)/$(year)/$(month).html5: \
+view/$(sensor)/$(year)/$(month)/png
+       printf ' \
+       <report sensor="$(sensor)" year="$(year)" month="$(month)"> \
+               $(foreach day,$(days), \
+               <date \
+                day="$(day)" \
+                day-name="$$(shell date +'%A' -d '$(year)/$(month)/$(day)')"/>) \
+        </report>' | \
+       xsltproc --output $$@ \
+        xsl/sensor/year/month.html5.xsl -
+endef
+define view/year/month/html5
+view/$(year)/$(month)/html5: \
+view/$(year)/$(month).html5
+
+view/$(year)/$(month).html5: \
+$(foreach sensor,$(sensors), view/$(sensor)/$(year)/$(month)/png)
+       mkdir -p $$(@D)
+       printf ' \
+       <report year="$(year)" month="$(month)"> \
+               $(foreach day,$(days), \
+               <date \
+                day="$(day)" \
+                day-name="$$(shell date +'%A' -d '$(year)/$(month)/$(day)')"> \
+                       $(foreach sensor,$(sensors), \
+                               <sensor name="$(sensor)"/> \
+                        ) \
+               </date>) \
+        </report>' | \
+       xsltproc --output $$@ \
+        xsl/year/month.html5.xsl -
+endef
+
+define view/sensor/year/month/day/html5
+#view/$(sensor)/$(year)/$(month)/$(day)/html5: \
+#view/$(sensor)/$(year)/$(month)/$(day).html5
+
+endef
+
+#
+## Dates
+###
+years=$(call uniq,$(foreach rrd,$(.rrd),$(word 2,$(subst /, ,$(rrd)))))
+months=$(foreach rrd,$(filter rrd/$(year)/%,$(.rrd)),$(basename $(word 3,$(subst /, ,$(rrd)))))
+days=$(shell seq -w $$(date +'%d' -d '$(year)/$(month)/01 + 1 month - 1 second'))
+
+month_begin=$(shell date +'%s' -d '$(year)/$(month)/01')
+month_end=$(shell date +'%s' -d '$(year)/$(month)/01 + 1 month - 1 second')
+
+day_begin=$(shell date +'%s' -d '$(year)/$(month)/$(day)')
+day_end=$(shell date +'%s' -d '$(year)/$(month)/$(day) + 1 day - 1 second')
+
+define foreach/sensor
+.PHONY:     view/$(sensor)/$(view)
+view/$(view): view/$(sensor)/$(view)
+$(call view/sensor/$(view))
+endef
+
+define foreach/year/sensor/view
+.PHONY:               view/$(sensor)/$(year)/$(view)
+view/$(sensor)/$(view): view/$(sensor)/$(year)/$(view)
+$(call view/sensor/year/$(view))
+endef
+
+define foreach/year/month/sensor/view
+.PHONY:                       view/$(sensor)/$(year)/$(month)/$(view)
+view/$(sensor)/$(year)/$(view): view/$(sensor)/$(year)/$(month)/$(view)
+$(call view/sensor/year/month/$(view))
+endef
+define foreach/year/month/view
+.PHONY:             view/$(year)/$(month)/$(view)
+view/$(year)/$(view): view/$(year)/$(month)/$(view)
+$(call view/year/month/$(view))
+endef
+
+define foreach/year/month/day/sensor/view
+.PHONY:                                view/$(sensor)/$(year)/$(month)/$(day)/$(view)
+view/$(sensor)/$(year)/$(month)/$(view): view/$(sensor)/$(year)/$(month)/$(day)/$(view)
+$(call view/sensor/year/month/day/$(view))
 endef
 
-)=)
-$(eval $(call png/sensor,temperature,Température (°C$)))
-$(eval $(call png/sensor,humidity,Humidité (%$)))
-$(eval $(call png/sensor,particles,Particules))
-$(eval $(call png/sensor,quality,Qualité de l’air))
+$(foreach sensor,$(sensors), \
+       $(foreach view,$(views), \
+               $(eval $(call foreach/sensor)) \
+        ) \
+ )
+$(foreach year,$(years), \
+       $(foreach view,$(views), \
+               $(eval $(call foreach/year/view)) \
+        ) \
+       $(foreach sensor,$(sensors), \
+               $(foreach view,$(views), \
+                       $(eval $(call foreach/year/sensor/view)) \
+                ) \
+        ) \
+       $(foreach month,$(months), \
+               $(foreach view,$(views), \
+                       $(eval $(call foreach/year/month/view)) \
+                ) \
+               $(foreach sensor,$(sensors), \
+                       $(foreach view,$(views), \
+                               $(eval $(call foreach/year/month/sensor/view)) \
+                        ) \
+                ) \
+               $(foreach day,$(days), \
+                       $(foreach view,$(views), \
+                               $(eval $(call foreach/year/month/day/view)) \
+                        ) \
+                       $(foreach sensor,$(sensors), \
+                               $(foreach view,$(views), \
+                                       $(eval $(call foreach/year/month/day/sensor/view)) \
+                                ) \
+                        ) \
+                ) \
+        ) \
+ )