--- /dev/null
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ; while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" = `pwd` ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+ @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
--- /dev/null
+SUBDIRS = ul_drv
+
+QT_SUBDIRS = src
+
--- /dev/null
+# Version for Linux/RTLinux builds. #OMK@linux
+#
+# Makefile.rules - OCERA make framework common project rules -*- makefile -*- #OMK@base
+#
+# (C) Copyright 2003 by Pavel Pisa - OCERA team member
+# (C) Copyright 2006 by Michal Sojka - Czech Technical University, FEE, DCE
+#
+# Homepage: http://rtime.felk.cvut.cz/omk/
+#
+# The OMK build system is distributed under the GNU General Public
+# License. See file COPYING for details.
+#
+# input variables
+# V .. if set to 1, full command text is shown else short form is used
+# W .. whole tree - if set to 1, make is always called from the top-level directory
+# SUBDIRS .. list of subdirectories intended for make from actual directory
+# default_CONFIG .. list of default config assignments CONFIG_XXX=y/n ...
+# LN_HEADERS .. if "y", header files are symbolicaly linked instead of copied. #OMK@include
+# #OMK@linux
+# input variables
+# lib_LIBRARIES .. list of the user-space libraries
+# shared_LIBRARIES .. list of the user-space shared libraries
+# kernel_LIBRARIES .. list of the kernel-space libraries
+# rtlinux_LIBRARIES.. list of the RT-Linux kernel-space libraries
+# include_HEADERS .. list of the user-space public header files
+# nobase_include_HEADERS .. public headers copied even with directory part
+# renamed_include_HEADERS .. public headers copied to the different target name
+# kernel_HEADERS .. list of the kernel-space public header files
+# rtlinux_HEADERS .. list of the RT-Linux kernel-space public header files
+# bin_PROGRAMS .. list of the require binary programs
+# utils_PROGRAMS .. list of the development utility programs
+# test_PROGRAMS .. list of the testing programs
+# kernel_MODULES .. list of the kernel side modules/applications
+# rtlinux_MODULES .. list of RT-Linux the kernel side modules/applications
+# xxx_SOURCES .. list of specific target sources
+# xxx_LIBS .. list of specific target libraries
+# INCLUDES .. additional include directories and defines for user-space
+# kernel_INCLUDES .. additional include directories and defines for kernel-space
+# rtlinux_INCLUDES .. additional include directories and defines for RT-Linux
+# OMIT_KERNEL_PASSES if defined, all kernel passes are omited
+#
+# LINUX_DIR .. location of Linux kernel sources
+# RTL_DIR .. location of RT-Linux sources
+# CFLAGS .. C compiler flags
+# CXXFLAGS .. C++ compiler flags
+# CPPFLAGS .. C preprocessor flags
+# LDFLAGS .. linker flags for programs linking
+# LOCAL_CONFIG_H .. name of local config.h file generated from values #OMK@config_h
+# of options defined in the current directory
+# config_include_HEADERS .. names of global config files (possibly
+# with subdirectories)
+# xxx_DEFINES .. list of config directives to be included in
+# config header file of the name <somedir>/xxx.h
+# DOXYGEN .. if non-empty, generated headers includes Doxygen's @file
+# command, so it is possible to document config
+# variables.
+# QT_SUBDIRS .. subdirectories where to build QT applications using qmake #OMK@qt
+# QTDIR .. where QT resides
+OMK_RULES_TYPE=linux #OMK@__type
+ #OMK@base
+# We need to ensure definition of sources directory first
+ifndef SOURCES_DIR
+# Only shell built-in pwd understands -L
+SOURCES_DIR := $(shell ( pwd -L ) )
+endif
+
+# If we are not called by OMK leaf Makefile...
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(abspath $(dir $(filter %Makefile.rules,$(MAKEFILE_LIST))))
+endif
+
+# OUTPUT_DIR is the place where _compiled, _build and possible other
+# files/directories are created. By default is the same as
+# $(MAKERULES_DIR).
+ifndef OUTPUT_DIR
+OUTPUT_DIR := $(MAKERULES_DIR)
+endif
+
+.PHONY: all default check-make-ver omkize
+
+ifdef W
+ ifeq ("$(origin W)", "command line")
+ OMK_WHOLE_TREE:=$(W)
+ endif
+endif
+ifndef OMK_WHOLE_TREE
+ OMK_WHOLE_TREE:=0
+endif
+
+ifneq ($(OMK_WHOLE_TREE),1)
+all: check-make-ver default
+ @echo "Compilation finished"
+else
+# Run make in the top-level directory
+all:
+ @$(MAKE) -C $(MAKERULES_DIR) OMK_SERIALIZE_INCLUDED=n SOURCES_DIR=$(MAKERULES_DIR) RELATIVE_DIR="" $(MAKECMDGOALS) W=0
+endif
+
+ifdef OMK_TESTSROOT
+# Usage: $(call canttest,<error message>)
+define canttest
+ ( echo "$(1)" > $(OUTPUT_DIR)/_canttest; echo "$(1)"; exit 1 )
+endef
+else
+define canttest
+ echo "$(1)"
+endef
+endif
+
+#=========================
+# Include the config file
+
+# FIXME: I think CONFIG_FILE_OK variable is useless. We have three
+# config files and it is not clearly defined to which file is this
+# variable related.
+ifneq ($(CONFIG_FILE_OK),y)
+ifndef CONFIG_FILE
+CONFIG_FILE := $(OUTPUT_DIR)/config.omk
+endif
+ifneq ($(wildcard $(CONFIG_FILE)-default),)
+-include $(CONFIG_FILE)-default
+else
+ifneq ($(MAKECMDGOALS),default-config)
+$(warning Please, run "make default-config" first)
+endif
+endif
+
+-include $(OUTPUT_DIR)/config.target
+
+ifneq ($(wildcard $(CONFIG_FILE)),)
+-include $(CONFIG_FILE)
+CONFIG_FILE_OK = y
+endif
+endif #$(CONFIG_FILE_OK)
+
+
+CONFIG_FILES ?= $(wildcard $(CONFIG_FILE)-default) $(wildcard $(OUTPUT_DIR)/config.target) $(wildcard $(CONFIG_FILE))
+
+
+export SOURCES_DIR MAKERULES_DIR RELATIVE_DIR
+export CONFIG_FILE CONFIG_FILES OMK_SERIALIZE_INCLUDED OMK_VERBOSE OMK_SILENT
+# OMK_SERIALIZE_INCLUDED has to be exported to submakes because passes
+# must to be serialized only in the toplevel make.
+
+ifndef RELATIVE_DIR
+RELATIVE_DIR := $(SOURCES_DIR:$(OUTPUT_DIR)%=%)
+endif
+#$(warning === RELATIVE_DIR = "$(RELATIVE_DIR)" ===)
+override RELATIVE_DIR := $(RELATIVE_DIR:/%=%)
+override RELATIVE_DIR := $(RELATIVE_DIR:\\%=%)
+#$(warning RELATIVE_DIR = "$(RELATIVE_DIR)")
+override BACK2TOP_DIR := $(shell echo $(RELATIVE_DIR)/ | sed -e 's_//_/_g' -e 's_/\./_/_g' -e 's_^\./__g' -e 's_\([^/][^/]*\)_.._g' -e 's_/$$__')
+#$(warning BACK2TOP_DIR = "$(BACK2TOP_DIR)")
+
+#$(warning SOURCES_DIR = "$(SOURCES_DIR)")
+#$(warning MAKERULES_DIR = "$(OUTPUT_DIR)")
+#$(warning RELATIVE_DIR = "$(RELATIVE_DIR)")
+
+# We have to use RELATIVE_PREFIX because of mingw
+override RELATIVE_PREFIX := $(RELATIVE_DIR)/
+override RELATIVE_PREFIX := $(RELATIVE_PREFIX:/%=%)
+
+#vpath %.c $(SOURCES_DIR)
+#vpath %.cc $(SOURCES_DIR)
+#vpath %.cxx $(SOURCES_DIR)
+
+# Define srcdir for Automake compatibility
+srcdir = $(SOURCES_DIR)
+
+# Defines for quiet compilation
+ifdef V
+ ifeq ("$(origin V)", "command line")
+ OMK_VERBOSE = $(V)
+ endif
+endif
+ifndef OMK_VERBOSE
+ OMK_VERBOSE = 0
+endif
+ifneq ($(OMK_VERBOSE),0)
+ Q =
+else
+ Q = @
+endif
+ifneq ($(findstring s,$(MAKEFLAGS)),)
+ QUIET_CMD_ECHO = true
+ OMK_SILENT = 1
+else
+ QUIET_CMD_ECHO = echo
+endif
+
+MAKEFILE_OMK=Makefile.omk
+# All subdirectories (even linked ones) containing Makefile.omk
+# Usage in Makefile.omk: SUBDIRS = $(ALL_OMK_SUBDIRS)
+ALL_OMK_SUBDIRS = $(patsubst %/$(MAKEFILE_OMK),%,$(patsubst $(SOURCES_DIR)/%,%,$(wildcard $(SOURCES_DIR)/*/$(MAKEFILE_OMK))))
+
+# ===================================================================
+# We have set up all important variables, so we can check and include
+# real OCERA style Makefile.omk now
+ifndef OMK_INCLUDED
+include $(SOURCES_DIR)/$(MAKEFILE_OMK)
+ifeq ($(AUTOMATIC_SUBDIRS),y)
+SUBDIRS?=$(ALL_OMK_SUBDIRS)
+endif
+OMK_INCLUDED := 1
+endif
+
+check-make-ver:
+ @GOOD_MAKE_VERSION=`echo $(MAKE_VERSION) | sed -n -e 's/^[4-9]\..*\|^3\.9[0-9].*\|^3\.8[1-9].*/y/p'` ; \
+ if [ x$$GOOD_MAKE_VERSION != xy ] ; then \
+ echo "Your make program version is too old and does not support OMK system." ; \
+ echo "Please update to make program 3.81beta1 or newer." ; exit 1 ; \
+ fi
+
+distclean dist-clean:
+ @$(QUIET_CMD_ECHO) " RM $(COMPILED_DIR_NAME) $(BUILD_DIR_NAME)"
+ @rm -fr $(OUTPUT_DIR)/$(COMPILED_DIR_NAME) $(OUTPUT_DIR)/$(BUILD_DIR_NAME)
+
+# Common OMK templates
+# ====================
+
+# Syntax: $(call mkdir,<dir name>)
+define mkdir_def
+ [ -d $(1) ] || mkdir -p $(1) || exit 1
+endef
+
+ifneq ($(OMK_VERBOSE),2)
+NO_PRINT_DIRECTORY := --no-print-directory
+endif
+
+ifeq ($(USE_LEAF_MAKEFILES),n)
+export USE_LEAF_MAKEFILES
+SUBDIR_MAKEFILE=$(MAKERULES_DIR)/Makefile.rules
+SOURCESDIR_MAKEFILE=$(MAKERULES_DIR)/Makefile.rules
+else
+SUBDIR_MAKEFILE=$(SOURCES_DIR)/$(3)/Makefile
+SOURCESDIR_MAKEFILE=$(SOURCES_DIR)/Makefile
+endif
+
+pass = $(strip $(1))
+
+# Call a pass in a subdirectory
+# Usage: $(call omk_pass_subdir_template,<pass name>,<build dir>,<subdir>)
+define omk_pass_subdir_template
+.PHONY: $(pass)-$(3)-subdir
+$(pass)-submakes: $(pass)-$(3)-subdir
+$(pass)-$(3)-subdir:
+ @$(call mkdir_def,$(2)/$(3))
+ +@$(MAKE) SOURCES_DIR=$(SOURCES_DIR)/$(3) $(NO_PRINT_DIRECTORY) \
+ RELATIVE_DIR=$(RELATIVE_PREFIX)$(3) -C $(2)/$(3) \
+ -f $(SUBDIR_MAKEFILE) $(pass)-submakes
+# In subdirectories we can call submakes directly since passes are
+# already searialized on the toplevel make.
+endef
+
+ifdef OMK_TESTSROOT
+check-target = $(1:%=%-check)
+endif
+
+# Call a pass in a subdirectory
+# Usage: $(call extra_rules_subdir_template,<subdir>)
+define extra_rules_subdir_template
+extra-rules-subdirs: extra-rules-$(1)
+extra-rules-$(1):
+ +@$(MAKE) OMK_SERIALIZE_INCLUDED=n MAKERULES_DIR=$(SOURCES_DIR)/$(1) OUTPUT_DIR=$(OUTPUT_DIR) \
+ SOURCES_DIR=$(SOURCES_DIR)/$(1) RELATIVE_DIR=$(RELATIVE_PREFIX)$(1) -C $(SOURCES_DIR)/$(1)
+endef
+
+.PHONY: extra-rules-subdirs
+extra-rules-subdirs:
+
+$(foreach subdir,$(EXTRA_RULES_SUBDIRS),$(eval $(call extra_rules_subdir_template,$(subdir))))
+
+# Usage: $(call omk_pass_template,<pass name>,<build dir>,[<local make flags>],[<local enable condition>])
+define omk_pass_template
+.PHONY: $(pass) $(pass)-local $(pass)-check $(pass)-submakes
+$(foreach subdir,$(SUBDIRS),$(eval $(call omk_pass_subdir_template,$(pass),$(2),$(subdir))))
+$(pass):
+# Submakes have to be called this way and not as dependecies for pass
+# serialization to work
+ +@$(MAKE) SOURCES_DIR=$(SOURCES_DIR) $(NO_PRINT_DIRECTORY) \
+ RELATIVE_DIR=$(RELATIVE_DIR) \
+ -f $(SOURCESDIR_MAKEFILE) $(pass)-submakes
+$(pass)-submakes:
+ @true # Do not emit "nothing to be done" messages
+
+ifneq ($(4)$($(pass)_HOOKS),)
+$(pass)-submakes: $(pass)-this-dir
+$(pass)-this-dir: $(foreach subdir,$(SUBDIRS),$(pass)-$(subdir)-subdir)
+ +@echo "make[omk]: $(pass) in $(RELATIVE_DIR)"
+ @$(call mkdir_def,$(2))
+ +@$(MAKE) $(NO_PRINT_DIRECTORY) SOURCES_DIR=$(SOURCES_DIR) RELATIVE_DIR=$(RELATIVE_DIR) -C $(2) \
+ -f $(SOURCESDIR_MAKEFILE) $(3) $(check-target) $(1:%=%-local)
+$(pass)-local: $($(pass)_HOOKS)
+endif
+endef
+
+# =======================
+# DEFAULT CONFIG PASS
+
+default-config:
+ @echo "# Start of OMK config file" > "$(CONFIG_FILE)-default"
+ @echo "# This file should not be altered manually" >> "$(CONFIG_FILE)-default"
+ @echo "# Overrides should be stored in file $(notdir $(CONFIG_FILE))" >> "$(CONFIG_FILE)-default"
+ @echo >> "$(CONFIG_FILE)-default"
+ @$(MAKE) $(NO_PRINT_DIRECTORY) -C $(OUTPUT_DIR) \
+ RELATIVE_DIR="" SOURCES_DIR=$(OUTPUT_DIR) \
+ -f $(OUTPUT_DIR)/Makefile default-config-pass
+
+$(eval $(call omk_pass_template,default-config-pass,$$(LOCAL_BUILD_DIR),,always))
+
+default-config-pass-local:
+# @echo Default config for $(RELATIVE_DIR)
+ @echo "# Config for $(RELATIVE_DIR)" >> "$(CONFIG_FILE)-default"
+ @$(foreach x, $(default_CONFIG), echo '$(x)' | \
+ sed -e 's/^[^=]*=x$$/#\0/' >> "$(CONFIG_FILE)-default" ; )
+
+
+omkize:
+ $(Q)if ! grep -q MAKERULES_DIR Makefile; then \
+ echo "Makefile is not OMK leaf makefile!" >&2; exit 1; \
+ fi
+ $(Q)for i in `find -L . -name Makefile.omk` ; do \
+ d=`dirname $${i}`; \
+ if ! test -f "$${d}/Makefile.rules" && ( ! test -f "$${d}/Makefile" || ! cmp --silent Makefile "$${d}/Makefile" ); then \
+ rm -f "$${d}/Makefile"; \
+ cp -v Makefile "$${d}/Makefile"; \
+ fi \
+ done
+ifeq ($(OMK_VERBOSE),1) #OMK@include
+CPHEADER_FLAGS += -v
+LNHEADER_FLAGS += -v
+endif
+
+ifneq ($(LN_HEADERS),y)
+define cp_cmd
+( echo " CP $(1:$(OUTPUT_DIR)/%=%) -> $(2:$(OUTPUT_DIR)/%=%)"; cp $(CPHEADER_FLAGS) $(1) $(2) )
+endef
+else
+define cp_cmd
+( echo " LN $(1:$(OUTPUT_DIR)/%=%) -> $(2:$(OUTPUT_DIR)/%=%)"; [ -f $(1) ] && ln -sf $(LNHEADER_FLAGS) $(1) $(2) )
+endef
+endif
+
+# TODO: Check modification date of changed header files. If it is
+# newer that in source dir, show a warning.
+
+# Syntax: $(call include-pass-template,<include dir>,<keyword>)
+define include-pass-template
+include-pass-local: include-pass-local-$(2)
+include-pass-local-$(2): $$($(2)_GEN_HEADERS) $$(foreach f,$$(renamed_$(2)_GEN_HEADERS),$$(shell echo '$$(f)' | sed -e 's/^\(.*\)->.*$$$$/\1/'))
+ @$$(foreach f, $$($(2)_HEADERS), cmp --quiet $$(SOURCES_DIR)/$$(f) $(1)/$$(notdir $$(f)) \
+ || $$(call cp_cmd,$$(SOURCES_DIR)/$$(f),$(1)/$$(notdir $$(f))) || exit 1 ; )
+ @$$(foreach f, $$($(2)_GEN_HEADERS), cmp --quiet $$(f) $(1)/$$(notdir $$(f)) \
+ || $$(call cp_cmd,$$(LOCAL_BUILD_DIR)/$$(f),$(1)/$$(notdir $$(f))) || exit 1 ; ) # FIXME: Use correct build dir, then document it
+ @$$(foreach f, $$(nobase_$(2)_HEADERS), cmp --quiet $$(SOURCES_DIR)/$$(f) $(1)/$$(f) \
+ || ( mkdir -p $(1)/$$(dir $$(f)) && $$(call cp_cmd,$$(SOURCES_DIR)/$$(f),$(1)/$$(f)) ) || exit 1 ; )
+ @$$(foreach f, $$(renamed_$(2)_HEADERS), \
+ srcfname=`echo '$$(f)' | sed -e 's/^\(.*\)->.*$$$$/\1/'` ; destfname=`echo '$$(f)' | sed -e 's/^.*->\(.*\)$$$$/\1/'` ; \
+ cmp --quiet $$(SOURCES_DIR)/$$$${srcfname} $(1)/$$$${destfname} \
+ || ( mkdir -p `dirname $(1)/$$$${destfname}` && $$(call cp_cmd,$$(SOURCES_DIR)/$$$${srcfname},$(1)/$$$${destfname}) ) || exit 1 ; )
+ @$$(foreach f, $$(renamed_$(2)_GEN_HEADERS), \
+ srcfname=`echo '$$(f)' | sed -e 's/^\(.*\)->.*$$$$/\1/'` ; destfname=`echo '$$(f)' | sed -e 's/^.*->\(.*\)$$$$/\1/'` ; \
+ cmp --quiet $$$${srcfname} $(1)/$$$${destfname} \
+ || ( mkdir -p `dirname $(1)/$$$${destfname}` && $$(call cp_cmd,$$(LOCAL_BUILD_DIR)/$$$${srcfname},$(1)/$$$${destfname}) ) || exit 1 ; )
+endef
+
+# Local Variables:
+# mode:makefile
+# End:
+ #OMK@linux
+# Hack to check RT-Linux rules
+#LINUX_DIR := /home/cvs/ocera/ocera-build/kernel/linux
+#RTL_DIR := /home/cvs/ocera/ocera-build/kernel/rtlinux
+#CONFIG_RTLINUX = y
+#OCERA_DIR := $(shell ( cd -L $(OUTPUT_DIR)/../../.. ; pwd -L ) )
+
+-include $(OUTPUT_DIR)/OCERA_TOP_DIR
+
+BUILD_DIR_NAME = _build
+COMPILED_DIR_NAME = _compiled
+ifndef GROUP_DIR_NAME
+GROUP_DIR_NAME = nogroup
+endif
+
+ifdef OCERA_DIR
+ifeq ($(wildcard $(OCERA_DIR)/ocera.mk),)
+$(warning "ocera.mk" file does not exist. Adapt Makefile.rules for standalone compilation)
+$(warning (comment out definition of OCERA_DIR line and optionally select RTL_DIR) )
+$(error or go to the ocera/ directory and do 'make' to generate the "ocera.mk" file first, please)
+endif
+include $(OCERA_DIR)/ocera.mk
+KERN_INCLUDE_DIR := $(OCERA_KERNEL_INCLUDES_DIR)
+KERN_LIB_DIR := $(OCERA_KERNEL_LIBRARIES_DIR)
+KERN_MODULES_DIR := $(OCERA_MODULES_DIR)
+KERN_BUILD_DIR := $(BUILD_DIR)/kern/$(GROUP_DIR_NAME)
+KERN_MODPOST_DIR := $(BUILD_DIR)/kern-modpost
+USER_INCLUDE_DIR := $(OCERA_USER_INCLUDES_DIR)
+USER_LIB_DIR := $(OCERA_USER_LIBRARIES_DIR)
+USER_UTILS_DIR := $(TARGET_DIR)/usr/bin
+USER_TESTS_DIR := $(TARGET_DIR)/usr/bin
+USER_BIN_DIR := $(TARGET_DIR)/usr/bin
+USER_BUILD_DIR := $(BUILD_DIR)/user/$(GROUP_DIR_NAME)
+#LINUX_DIR := $(OCERA_DIR)/kernel/linux
+#RTL_DIR := $(OCERA_DIR)/kernel/rtlinux
+#CONFIG_FILE := $(OCERA_DIR)/emdebsys/.config
+ifneq ($(wildcard $(CONFIG_FILE)),)
+CONFIG_FILE_OK = y
+endif
+else # OCERA_DIR
+KERN_INCLUDE_DIR := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/include-kern
+KERN_LIB_DIR := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/lib-kern
+KERN_MODULES_DIR := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/modules
+KERN_BUILD_DIR := $(OUTPUT_DIR)/$(BUILD_DIR_NAME)/kern
+KERN_MODPOST_DIR := $(OUTPUT_DIR)/$(BUILD_DIR_NAME)/kern-modpost
+USER_INCLUDE_DIR := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/include
+USER_LIB_DIR := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/lib
+USER_UTILS_DIR := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/bin-utils
+USER_TESTS_DIR := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/bin-tests
+USER_BIN_DIR := $(OUTPUT_DIR)/$(COMPILED_DIR_NAME)/bin
+USER_BUILD_DIR := $(OUTPUT_DIR)/$(BUILD_DIR_NAME)/user
+
+ifndef LINUX_VERSION
+LINUX_VERSION=$(shell uname -r)
+endif
+ifndef LINUX_DIR
+LINUX_DIR=/lib/modules/$(LINUX_VERSION)/build
+endif
+endif # OCERA_DIR
+
+ifeq ($(BUILD_OS),)
+ # Check for target
+ ifeq ($(OS),Windows_NT)
+ BUILD_OS := win32
+ else
+ BUILD_OS := $(shell uname | tr '[A-Z]' '[a-z]' )
+ #$(warning BUILD_OS=$(BUILD_OS))
+ endif
+endif
+
+ifeq ($(TARGET_OS),)
+ TARGET_OS := $(BUILD_OS)
+endif
+
+LOCAL_BUILD_DIR = $(USER_OBJS_DIR)
+
+# Assign default values to CFLAGS variable. If the variable is defined
+# earlier (i.g. in config.omk), it is not overriden here.
+CFLAGS ?= -O2 -Wall
+CXXFLAGS ?= -O2 -Wall
+
+
+CPPFLAGS += -I $(USER_INCLUDE_DIR)
+
+LOADLIBES += -L$(USER_LIB_DIR)
+
+LOADLIBES += $(lib_LOADLIBES:%=-l%)
+
+LIB_CPPFLAGS += $(CPPFLAGS)
+LIB_CFLAGS += $(CFLAGS)
+
+ifeq ($(TARGET_OS),win32)
+ SOLIB_EXT = dll
+else
+ SOLIB_EXT = so
+ SOLIB_PICFLAGS += -fpic
+endif
+
+#vpath %.c $(SOURCES_DIR)
+#vpath %.cc $(SOURCES_DIR)
+#vpath %.cxx $(SOURCES_DIR)
+
+USER_OBJS_DIR = $(USER_BUILD_DIR)/$(RELATIVE_DIR)
+KERN_OBJS_DIR = $(KERN_BUILD_DIR)/$(RELATIVE_DIR)
+
+.PHONY: dep subdirs clean clean-custom cleandepend check-dir
+
+# Some support to serialize some targets for parallel make
+ifneq ($(OMK_SERIALIZE_INCLUDED),y)
+include-pass: check-dir
+library-pass: include-pass
+binary-pass: library-pass
+kernel-lib-pass: include-pass
+kernel-mod-pass: kernel-lib-pass
+kernel-modpost-pass: kernel-mod-pass
+kernel-pass: kernel-mod-pass kernel-modpost-pass
+
+override OMK_SERIALIZE_INCLUDED = y
+MAKEOVERRIDES := $(filter-out OMK_SERIALIZE_INCLUDED=n,$(MAKEOVERRIDES))
+endif
+
+# Checks for OMK tester
+ifdef OMK_TESTSROOT
+default-config-pass-check include-pass-check:
+library-pass-check binary-pass-check:
+ @[ -x "$(shell which $(CC))" ] || $(call canttest,Cannot find compiler: $(CC))
+endif
+
+#=====================================================================
+# User-space rules and templates to compile programs, libraries etc.
+
+ifdef USER_RULE_TEMPLATES
+
+USER_SOURCES2OBJS = .o/.c .o/.cc .o/.cxx .o/.S .o/.o
+
+USER_SOURCES2OBJSLO = .lo/.c .lo/.cc .lo/.cxx .lo/.S .lo/.lo
+
+#%.lo: %.c
+# $(CC) -o $@ $(LCFLAGS) -c $<
+
+c_o_COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -DOMK_FOR_USER
+
+cc_o_COMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -DOMK_FOR_USER
+
+S_o_COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) $(ASFLAGS) -DOMK_FOR_USER
+
+idl_COMPILE = $(IDL_COMPILER)
+
+# Check GCC version for user build
+ifndef CC_MAJOR_VERSION
+CC_MAJOR_VERSION := $(shell $(CC) -dumpversion | sed -e 's/\([^.]\)\..*/\1/')
+endif
+# Prepare suitable define for dependency building
+ifeq ($(CC_MAJOR_VERSION),2)
+CC_DEPFLAGS = -Wp,-MD,"$@.d.tmp"
+else
+CC_DEPFLAGS = -MT $@ -MD -MP -MF "$@.d.tmp"
+endif
+
+
+# Syntax: $(call COMPILE_c_o_template,<source>,<target>,<additional c-flags>)
+define COMPILE_c_o_template
+$(2): $(1) $$(GEN_HEADERS)
+ @$(QUIET_CMD_ECHO) " CC $$@"
+ $(Q) if $$(c_o_COMPILE) $$(CC_DEPFLAGS) $(3) -o $$@ -c $$< ; \
+ then mv -f "$$@.d.tmp" "$$@.d" ; \
+ else rm -f "$$@.d.tmp" ; exit 1; \
+ fi
+endef
+
+
+# Syntax: $(call COMPILE_cc_o_template,<source>,<target>,<additional c-flags>)
+define COMPILE_cc_o_template
+$(2): $(1) $$(GEN_HEADERS)
+ @$(QUIET_CMD_ECHO) " CXX $$@"
+ $(Q) if $$(cc_o_COMPILE) $$(CC_DEPFLAGS) $(3) -o $$@ -c $$< ; \
+ then mv -f "$$@.d.tmp" "$$@.d" ; \
+ else rm -f "$$@.d.tmp" ; exit 1; \
+ fi
+endef
+
+
+# Syntax: $(call COMPILE_S_o_template,<source>,<target>,<additional c-flags>)
+define COMPILE_S_o_template
+$(2): $(1) $$(GEN_HEADERS)
+ @$(QUIET_CMD_ECHO) " AS $$@"
+ $(Q) if $$(S_o_COMPILE) -D__ASSEMBLY__ $$(CC_DEPFLAGS) $(3) -o $$@ -c $$< ; \
+ then mv -f "$$@.d.tmp" "$$@.d" ; \
+ else rm -f "$$@.d.tmp" ; exit 1; \
+ fi
+endef
+
+
+# Syntax: $(call CMETRIC_o_h_template,<object_file>,<target_header>)
+define CMETRIC_o_h_template
+$(2): $(1)
+ @$(QUIET_CMD_ECHO) " CMETRIC $$@"
+ $(Q)if [ -n `dirname $$@` ] ; then \
+ if [ ! -e `dirname $$@` ] ; then \
+ mkdir -p `dirname $$@` ; fi ; fi
+ $(Q)echo >$$@ '/* Automatically generated from $$< */'
+ $(Q)echo >>$$@ '/* Conditionals to control compilation */'
+ $(Q)set -o pipefail ; $(NM) $$< \
+ | sed -n 's/^ *0*\(0[0-9A-Fa-f]*\) *A *_cmetric2cond_\([A-Za-z_0-9]*\) */#define \2 0x\1/p' \
+ | sort >>$$@
+ $(Q)echo >>$$@ '/* Defines from the values defined to symbols */'
+ $(Q)set -o pipefail ; $(NM) $$< \
+ | sed -n 's/^ *0*\(0[0-9A-Fa-f]*\) *A *_cmetric2def_\([A-Za-z_0-9]*\) */#define \2 0x\1/p' \
+ | sort >>$$@
+endef
+
+
+
+define COMPILE_idl_template
+$(2).c $(2)-stubs.c $(2)-skels.c $(2)-common.c $(2).h: $(1)
+ @$(QUIET_CMD_ECHO) " IDL $$@"
+ $(Q) $$(idl_COMPILE) $(1)
+endef
+
+
+# Syntax: $(call PROGRAM_template,<dir>,<executable-name>,<executable-suffix>,<linker-sript>)
+# FIXME: ???????? asi je tu blbej komentar
+define PROGRAM_template
+
+USER_IDLS += $$($(1)_SERVER_IDL) $$($(1)_CLIENT_IDL) $$($(1)_IDL)
+$(1)_GEN_SOURCES += $$(filter %.c,$$($(1)_SERVER_IDL:%.idl=%-skels.c))
+$(1)_GEN_SOURCES += $$(filter %.c,$$($(1)_SERVER_IDL:%.idl=%-common.c))
+$(1)_GEN_SOURCES += $$(filter %.c,$$($(1)_CLIENT_IDL:%.idl=%-stubs.c))
+$(1)_GEN_SOURCES += $$(filter %.c,$$($(1)_CLIENT_IDL:%.idl=%-common.c))
+$(1)_GEN_SOURCES += $$(filter %.c,$$($(1)_IDL:%.idl=%.c))
+USER_GEN_SOURCES += $$($(1)_GEN_SOURCES)
+
+$(foreach x, $(USER_SOURCES2OBJS),
+$(1)_OBJS += $$(patsubst %$(notdir $(x)),%$(dir $(x)),$$(filter %$(notdir $(x)),\
+ $$($(1)_SOURCES) $$($(1)_GEN_SOURCES)))
+)
+$(1)_OBJS := $$(sort $$($(1)_OBJS:%/=%))
+
+USER_OBJS += $$($(1)_OBJS)
+USER_SOURCES += $$($(1)_SOURCES)
+
+$(2)/$(1)$(3): $$($(1)_OBJS)
+ @$(QUIET_CMD_ECHO) " LINK $$@"
+ $(Q) $$(if $$(filter %.cc,$$($(1)_SOURCES:%.cxx=%.cc)),$$(CXX),$$(CC)) \
+ $$($(1)_OBJS) $$($(1)_LIBS:%=-l%) $$(LOADLIBES) $$(LDFLAGS) -Wl,-Map,$(USER_OBJS_DIR)/$(1).exe.map -o $$@
+ @echo "$(2)/$(1)$(3): \\" >$(USER_OBJS_DIR)/$(1).exe.d
+ @sed -n -e 's|^LOAD \(.*\)$$$$| \1 \&|p' $(USER_OBJS_DIR)/$(1).exe.map|tr '&' '\134' >>$(USER_OBJS_DIR)/$(1).exe.d
+ @echo >>$(USER_OBJS_DIR)/$(1).exe.d
+endef
+
+
+# Syntax: $(call LIBRARY_template,<library-name>)
+define LIBRARY_template
+
+USER_IDLS += $$($(1)_SERVER_IDL) $$($(1)_CLIENT_IDL) $$($(1)_IDL)
+$(1)_GEN_SOURCES += $$(filter %.c,$$($(1)_SERVER_IDL:%.idl=%-skels.c))
+$(1)_GEN_SOURCES += $$(filter %.c,$$($(1)_SERVER_IDL:%.idl=%-common.c))
+$(1)_GEN_SOURCES += $$(filter %.c,$$($(1)_CLIENT_IDL:%.idl=%-stubs.c))
+$(1)_GEN_SOURCES += $$(filter %.c,$$($(1)_CLIENT_IDL:%.idl=%-common.c))
+$(1)_GEN_SOURCES += $$(filter %.c,$$($(1)_IDL:%.idl=%.c))
+USER_GEN_SOURCES += $$($(1)_GEN_SOURCES)
+
+$(foreach x, $(USER_SOURCES2OBJS),
+$(1)_OBJS += $$(patsubst %$(notdir $(x)),%$(dir $(x)),$$(filter %$(notdir $(x)),\
+ $$($(1)_SOURCES) $$($(1)_GEN_SOURCES)))
+)
+$(1)_OBJS := $$(sort $$($(1)_OBJS:%/=%))
+
+USER_OBJS += $$($(1)_OBJS)
+USER_SOURCES += $$($(1)_SOURCES)
+
+$(USER_LIB_DIR)/lib$(1).a: $$($(1)_OBJS)
+ @$(QUIET_CMD_ECHO) " AR $$@"
+ $(Q) $(AR) rcs $$@ $$^
+endef
+
+
+# Syntax: $(call SOLIB_template,<library-name>)
+define SOLIB_template
+
+USER_IDLS += $$($(1)_SERVER_IDL) $$($(1)_CLIENT_IDL) $$($(1)_IDL)
+$(1)_GEN_SOURCES += $$(filter %.c,$$($(1)_SERVER_IDL:%.idl=%-skels.c))
+$(1)_GEN_SOURCES += $$(filter %.c,$$($(1)_SERVER_IDL:%.idl=%-common.c))
+$(1)_GEN_SOURCES += $$(filter %.c,$$($(1)_CLIENT_IDL:%.idl=%-stubs.c))
+$(1)_GEN_SOURCES += $$(filter %.c,$$($(1)_CLIENT_IDL:%.idl=%-common.c))
+$(1)_GEN_SOURCES += $$(filter %.c,$$($(1)_IDL:%.idl=%.c))
+SOLIB_GEN_SOURCES += $$($(1)_GEN_SOURCES)
+
+$(foreach x, $(USER_SOURCES2OBJSLO),
+$(1)_OBJSLO += $$(patsubst %$(notdir $(x)),%$(dir $(x)),$$(filter %$(notdir $(x)),\
+ $$($(1)_SOURCES) $$($(1)_GEN_SOURCES)))
+)
+$(1)_OBJSLO := $$(sort $$($(1)_OBJSLO:%/=%))
+
+SOLIB_OBJS += $$($(1)_OBJSLO)
+SOLIB_SOURCES += $$($(1)_SOURCES)
+
+$(USER_LIB_DIR)/lib$(1).$(SOLIB_EXT): $$($(1)_OBJSLO)
+ @$(QUIET_CMD_ECHO) " LINK $$@"
+ $(Q) $(CC) --shared -Xlinker -soname=lib$(1).$(SOLIB_EXT) -o $$@ $$^ $$(LOADLIBES) $$($(1)_LIBS:%=-l%)
+endef
+
+
+
+library-pass-local: $(addprefix $(USER_INCLUDE_DIR)/,$(cmetric_include_HEADERS)) \
+ $(lib_LIBRARIES:%=$(USER_LIB_DIR)/lib%.a) $(shared_LIBRARIES:%=$(USER_LIB_DIR)/lib%.$(SOLIB_EXT))
+
+binary-pass-local: $(bin_PROGRAMS:%=$(USER_BIN_DIR)/%$(EXE_SUFFIX)) $(utils_PROGRAMS:%=$(USER_UTILS_DIR)/%$(EXE_SUFFIX)) $(test_PROGRAMS:%=$(USER_TESTS_DIR)/%$(EXE_SUFFIX))
+
+# Special rules for CMETRIC generated headers
+
+$(foreach cmetrh,$(cmetric_include_HEADERS),$(eval $(call COMPILE_c_o_template,\
+ $(SOURCES_DIR)/$($(basename $(notdir $(cmetrh)))_CMETRIC_SOURCES),\
+ $($(basename $(notdir $(cmetrh)))_CMETRIC_SOURCES:%.c=%.o),)))
+$(foreach cmetrh,$(cmetric_include_HEADERS),$(eval $(call CMETRIC_o_h_template,\
+ $($(basename $(notdir $(cmetrh)))_CMETRIC_SOURCES:%.c=%.o),\
+ $(addprefix $(USER_INCLUDE_DIR)/,$(cmetrh)))))
+
+GEN_HEADERS+=$(cmetric_include_HEADERS:%=$(USER_INCLUDE_DIR)/%)
+
+GEN_HEADERS+=$(filter %.h,$(USER_IDLS:%.idl=%.h))
+
+# Generate rules for compilation of programs and libraries
+
+$(foreach prog,$(utils_PROGRAMS),$(eval $(call PROGRAM_template,$(prog),$(USER_UTILS_DIR),$(EXE_SUFFIX))))
+
+$(foreach prog,$(test_PROGRAMS),$(eval $(call PROGRAM_template,$(prog),$(USER_TESTS_DIR),$(EXE_SUFFIX))))
+
+$(foreach prog,$(bin_PROGRAMS),$(eval $(call PROGRAM_template,$(prog),$(USER_BIN_DIR),$(EXE_SUFFIX))))
+
+$(foreach lib,$(lib_LIBRARIES),$(eval $(call LIBRARY_template,$(lib))))
+
+$(foreach lib,$(shared_LIBRARIES),$(eval $(call SOLIB_template,$(lib))))
+
+-include $(USER_OBJS_DIR)/*.d
+
+endif
+
+#=====================================================================
+# Kernel-space rules and templates to compile modules, libraries etc.
+
+ifdef KERN_RULE_TEMPLATES
+
+$(KERN_LIB_DIR)/kernel.mk: $(LINUX_DIR)/.config $(MAKERULES_DIR)/kernelcfg2mk
+ @$(QUIET_CMD_ECHO) " KCFG2MK $$@"
+ $(Q) $(MAKERULES_DIR)/kernelcfg2mk $(LINUX_DIR) $(KERN_LIB_DIR)
+
+ifeq ($(CONFIG_RTLINUX),y)
+include $(RTL_DIR)/rtl.mk
+
+KERN_CC = $(CC)
+kern_GCCLIB_DIR=$(shell LANG=C LC_ALL=C LC_MESSAGES=C $(CC) -print-search-dirs | sed -n -e 's/^install: \(.*\)$$/\1/p' )
+INCLUDES := -I $(KERN_INCLUDE_DIR) $(INCLUDE) $(rtlinux_INCLUDES) $(kernel_INCLUDES)
+#-DEXPORT_NO_SYMBOLS
+c_o_kern_COMPILE = $(KERN_CC) -idirafter $(kern_GCCLIB_DIR)/include $(INCLUDES) $(CFLAGS) -DOMK_FOR_KERNEL -DEXPORT_SYMTAB -nostdinc
+cc_o_kern_COMPILE = $(CXX) $(INCLUDES) $(CXXFLAGS) -DOMK_FOR_KERNEL -DEXPORT_SYMTAB
+KERN_EXE_SUFFIX := .o
+KERN_ARCH = $(ARCH)
+KERN_LD = $(LD)
+KERN_AR = $(AR)
+
+else # CONFIG_RTLINUX
+
+include $(KERN_LIB_DIR)/kernel.mk
+
+ifeq ($(LINUX_SRC),)
+LINUX_SRC = $(LINUX_DIR)
+endif
+kernel_INCLUDES += -I $(LINUX_DIR) -idirafter $(LINUX_SRC)/include/linux
+
+ifdef LINUX_CC
+KERN_CC = $(LINUX_CC)
+kern_GCCLIB_DIR=$(shell LANG=C LC_ALL=C LC_MESSAGES=C $(LINUX_CC) -print-search-dirs | sed -n -e 's/^install: \(.*\)$$/\1/p' )
+else
+KERN_CC = echo KERN_CC not defined - compilation skipped
+endif
+c_o_kern_COMPILE = $(KERN_CC) $(kernel_INCLUDES) -idirafter $(kern_GCCLIB_DIR)/include $(LINUX_CPPFLAGS) $(LINUX_CFLAGS) $(LINUX_CFLAGS_MODULE) -DOMK_FOR_KERNEL -DEXPORT_SYMTAB -nostdinc
+cc_o_kern_COMPILE = $(KERN_CC) $(kernel_INCLUDES) -idirafter $(kern_GCCLIB_DIR)/include $(LINUX_CPPFLAGS) $(LINUX_CFLAGS) $(LINUX_CFLAGS_MODULE) -DOMK_FOR_KERNEL -DEXPORT_SYMTAB
+S_o_kern_COMPILE = $(KERN_CC) $(kernel_INCLUDES) -idirafter $(kern_GCCLIB_DIR)/include $(LINUX_CPPFLAGS) $(LINUX_AFLAGS) $(LINUX_CFLAGS_MODULE) -DOMK_FOR_KERNEL -DEXPORT_SYMTAB
+KERN_EXE_SUFFIX := $(LINUX_MODULE_EXT)
+KERN_LDFLAGS = $(LINUX_LDFLAGS)
+ifdef LINUX_ARCH
+KERN_ARCH = $(LINUX_ARCH)
+else
+KERN_ARCH = echo KERN_ARCH not defined - skipped
+endif
+ifdef LINUX_LD
+KERN_LD = $(LINUX_LD)
+else
+KERN_LD = echo KERN_LD not defined - skipped
+endif
+ifneq ($(LINUX_AR),)
+KERN_AR = $(LINUX_AR)
+else
+KERN_AR = $(AR)
+endif
+ifeq ($(LINUX_QUOTE_MODNAME),y)
+KERN_MQ=\"
+KERN_KBUILD_MODNAME=-D"KBUILD_MODNAME=((THIS_MODULE)!=NULL?(THIS_MODULE)->name:NULL)"
+endif
+endif # CONFIG_RTLINUX
+
+KERN_LOADLIBES += -L$(KERN_LIB_DIR)
+
+KERN_LOADLIBES += $(rtlinux_LOADLIBES:%=-l%)
+KERN_LOADLIBES += $(kernel_LOADLIBES:%=-l%)
+
+
+
+# Check GCC version for kernel part of build
+ifndef kern_CC_MAJOR_VERSION
+kern_CC_MAJOR_VERSION := $(shell $(KERN_CC) -dumpversion | sed -e 's/\([^.]\)\..*/\1/')
+endif
+# Prepare suitable define for dependency building
+ifeq ($(kern_CC_MAJOR_VERSION),2)
+kern_CC_DEPFLAGS = -Wp,-MD,"$@.d.tmp"
+else
+kern_CC_DEPFLAGS = -MT $@ -MD -MP -MF "$@.d.tmp"
+endif
+
+ifeq ($(KERN_EXE_SUFFIX),.ko)
+ifeq ($(wildcard $(LINUX_DIR)/scripts/mod/modpost),)
+KERN_MODPOST = $(LINUX_DIR)/scripts/modpost
+else
+KERN_MODPOST = $(LINUX_DIR)/scripts/mod/modpost
+endif
+KERN_MODULES_LINK_DIR = $(KERN_MODPOST_DIR)
+KERN_LINK_SUFFIX = .o
+else
+KERN_MODULES_LINK_DIR = $(KERN_MODULES_DIR)
+KERN_LINK_SUFFIX = $(KERN_EXE_SUFFIX)
+endif
+
+define COMPILE_c_o_kern_template
+
+$(2): $(1)
+ @$(QUIET_CMD_ECHO) " CC [K] $$@"
+ $(Q) if $$(c_o_kern_COMPILE) $$(kern_CC_DEPFLAGS) $(3) $(KERN_KBUILD_MODNAME) \
+ -D"KBUILD_BASENAME=$(KERN_MQ)$(notdir $(basename $(1)))$(KERN_MQ)" \
+ -o $$@ -c $$< ; \
+ then mv -f "$$@.d.tmp" "$$@.d" ; \
+ else rm -f "$$@.d.tmp" ; exit 1; \
+ fi
+endef
+
+
+
+define COMPILE_cc_o_kern_template
+
+$(2): $(1)
+ @$(QUIET_CMD_ECHO) " CXX [K] $$@"
+ $(Q) if $$(cc_o_kern_COMPILE) $$(kern_CC_DEPFLAGS) $(3) $(KERN_KBUILD_MODNAME) \
+ -D"KBUILD_BASENAME=$(KERN_MQ)$(notdir $(basename $(1)))$(KERN_MQ)" \
+ -o $$@ -c $$< ; \
+ then mv -f "$$@.d.tmp" "$$@.d" ; \
+ else rm -f "$$@.d.tmp" ; exit 1; \
+ fi
+endef
+
+
+
+define COMPILE_S_o_kern_template
+
+$(2): $(1)
+ @$(QUIET_CMD_ECHO) " AS [K] $$@"
+ $(Q) if $$(S_o_kern_COMPILE) $$(kern_CC_DEPFLAGS) $(3) $(KERN_KBUILD_MODNAME) \
+ -D"KBUILD_BASENAME=$(KERN_MQ)$(notdir $(basename $(1)))$(KERN_MQ)" \
+ -o $$@ -c $$< ; \
+ then mv -f "$$@.d.tmp" "$$@.d" ; \
+ else rm -f "$$@.d.tmp" ; exit 1; \
+ fi
+endef
+
+
+
+define MODULE_kern_template
+$(1)_OBJS += $$(filter %.o,$$($(1)_SOURCES:%.c=%.o))
+$(1)_OBJS += $$(filter %.o,$$($(1)_SOURCES:%.cc=%.o))
+$(1)_OBJS += $$(filter %.o,$$($(1)_SOURCES:%.cxx=%.o))
+$(1)_OBJS := $$(sort $$($(1)_OBJS))
+
+KERN_OBJS += $$($(1)_OBJS)
+KERN_SOURCES += $$($(1)_SOURCES)
+
+# this is hack to build "__this_module" structure for 2.6.x kernels
+# modpost is used for that purpose now
+
+#$(1).mod.c:
+# echo "\
+# #include <linux/version.h>@\
+# #include <linux/module.h>@\
+# #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,5))@\
+# #include <linux/vermagic.h>@\
+# #include <linux/compiler.h>@\
+# @\
+# MODULE_INFO(vermagic, VERMAGIC_STRING);@\
+# @\
+# #undef unix@\
+# struct module __this_module@\
+# __attribute__((section(\".gnu.linkonce.this_module\"))) = {@\
+# .name = __stringify(KBUILD_MODNAME),@\
+# .init = init_module,@\
+# #ifdef CONFIG_MODULE_UNLOAD@\
+# .exit = cleanup_module,@\
+# #endif@\
+# };@\
+# #endif@\
+# " | tr @ \\n >$$@
+
+
+#$(eval $(call COMPILE_c_o_kern_template,$(1).mod.c,$(1).mod.o,-DKBUILD_MODNAME=$(1)))
+
+$(2)/$(1)$(KERN_LINK_SUFFIX): $$($(1)_OBJS)
+ @$(QUIET_CMD_ECHO) " LD [K] $$@"
+ $(Q) $$(KERN_LD) $$(KERN_LDFLAGS) -r $$($(1)_OBJS) -L$$(kern_GCCLIB_DIR) $$($(1)_LIBS:%=-l%) $$(KERN_LOADLIBES) -Map $(KERN_OBJS_DIR)/$(1).mod.map -o $$@
+ @echo "$(2)/$(1)$(KERN_LINK_SUFFIX): \\" >$(KERN_OBJS_DIR)/$(1).mod.d
+ @sed -n -e 's/^LOAD \(.*\)$$$$/ \1 \\/p' $(KERN_OBJS_DIR)/$(1).mod.map >>$(KERN_OBJS_DIR)/$(1).mod.d
+ @echo >>$(KERN_OBJS_DIR)/$(1).mod.d
+ @if [ "$(KERN_EXE_SUFFIX)" = ".ko" ] ; then \
+ echo $(1) >>$(KERN_MODPOST_DIR)/module-changes ; \
+ echo $(1) >>$(KERN_MODPOST_DIR)/$(1).mod.stamp ; \
+ fi
+
+endef
+
+
+
+define LIBRARY_kern_template
+$(1)_OBJS += $$(filter %.o,$$($(1)_SOURCES:%.c=%.o))
+$(1)_OBJS += $$(filter %.o,$$($(1)_SOURCES:%.cc=%.o))
+$(1)_OBJS += $$(filter %.o,$$($(1)_SOURCES:%.cxx=%.o))
+$(1)_OBJS := $$(sort $$($(1)_OBJS))
+
+KERN_OBJS += $$($(1)_OBJS)
+KERN_SOURCES += $$($(1)_SOURCES)
+
+$(KERN_LIB_DIR)/lib$(1).a: $$($(1)_OBJS)
+ @$(QUIET_CMD_ECHO) " AR [K] $$@"
+ $(Q) $(KERN_AR) rcs $$@ $$^
+endef
+
+
+ifdef LINUX_DIR
+
+kernel-lib-pass-local: $(kernel_LIBRARIES:%=$(KERN_LIB_DIR)/lib%.a)
+
+kernel-mod-pass-local: $(kernel_MODULES:%=$(KERN_MODULES_LINK_DIR)/%$(KERN_LINK_SUFFIX))
+
+$(foreach module,$(kernel_MODULES),$(eval $(call MODULE_kern_template,$(module),$(KERN_MODULES_LINK_DIR))))
+
+$(foreach lib,$(kernel_LIBRARIES),$(eval $(call LIBRARY_kern_template,$(lib))))
+
+endif
+
+
+ifeq ($(CONFIG_RTLINUX),y)
+
+kernel-mod-pass-local: $(rtlinux_MODULES:%=$(KERN_MODULES_LINK_DIR)/%$(KERN_LINK_SUFFIX))
+
+kernel-lib-pass-local: $(rtlinux_LIBRARIES:%=$(KERN_LIB_DIR)/lib%.a)
+
+$(foreach module,$(rtlinux_MODULES),$(eval $(call MODULE_kern_template,$(module),$(KERN_MODULES_LINK_DIR))))
+
+$(foreach lib,$(rtlinux_LIBRARIES),$(eval $(call LIBRARY_kern_template,$(lib))))
+
+endif
+
+ifeq ($(KERN_MODPOST_PASS),y)
+
+MODULES_LIST := $(wildcard *.mod.stamp)
+MODULES_LIST := $(MODULES_LIST:%.mod.stamp=%)
+
+define MODPOST_kern_template
+$(2) : $(1)$(KERN_LINK_SUFFIX) $(1).mod.c
+ @$(QUIET_CMD_ECHO) " LD [M] $$@"
+ $(Q) $$(cc_o_kern_COMPILE) -D"KBUILD_BASENAME=$(KERN_MQ)$(1)$(KERN_MQ)" \
+ -D"KBUILD_MODNAME=$(KERN_MQ)$(1)$(KERN_MQ)" \
+ -o $(1).mod.o -c $(1).mod.c
+ $(Q) $$(KERN_LD) $$(KERN_LDFLAGS) $(1)$(KERN_LINK_SUFFIX) $(1).mod.o -r -o $$@
+endef
+
+kernel-modpost-versions: $(wildcard $(LINUX_DIR)/Module.symvers)
+ @$(QUIET_CMD_ECHO) " MODPOST $(KERN_MODPOST_DIR)"
+ @echo >$(KERN_MODPOST_DIR)/modpost-running
+ @rm -f $(KERN_MODPOST_DIR)/module-changes
+ $(Q) $(KERN_MODPOST) $(MODULES_LIST:%=%$(KERN_LINK_SUFFIX)) $(^:%=-i %)
+
+$(MODULES_LIST:%=%.mod.c) : kernel-modpost-versions
+
+kernel-modpost-pass-local: $(MODULES_LIST:%=$(KERN_MODULES_DIR)/%$(KERN_EXE_SUFFIX))
+ @rm -f $(KERN_MODPOST_DIR)/modpost-running
+
+$(foreach module,$(MODULES_LIST),$(eval $(call MODPOST_kern_template,$(module),$(module:%=$(KERN_MODULES_DIR)/%$(KERN_EXE_SUFFIX)))))
+
+endif
+
+-include $(KERN_OBJS_DIR)/*.d
+
+endif
+
+#=====================================================================
+
+# Kernel requires its own set of configuration header-files
+ifneq ($(kernel_LIBRARIES)$(rtlinux_LIBRARIES)$(kernel_MODULES)$(rtlinux_MODULES)$(kernel_HEADERS)$(rtlinux_HEADERS)$(kernel_HEADERS)$(rtlinux_HEADERS)$(nobase_kernel_HEADERS)$(nobase_rtlinux_HEADERS)$(renamed_kernel_HEADERS)$(renamed_rtlinux_HEADERS),)
+KERN_CONFIG_HEADERS_REQUIRED = y
+endif
+
+$(eval $(call omk_pass_template, kernel-lib-pass,$(KERN_OBJS_DIR),KERN_RULE_TEMPLATES=y,$(kernel_LIBRARIES)$(rtlinux_LIBRARIES)))
+$(eval $(call omk_pass_template, kernel-mod-pass,$(KERN_OBJS_DIR),KERN_RULE_TEMPLATES=y,$(kernel_MODULES)$(rtlinux_MODULES)))
+
+kernel-modpost-pass:
+ +@if [ -e "$(KERN_MODPOST_DIR)/module-changes" -o -e "$(KERN_MODPOST_DIR)/modpost-running" ] ; \
+ then \
+ $(MAKE) --no-print-directory -C $(KERN_MODPOST_DIR) \
+ -f $(SOURCES_DIR)/Makefile KERN_RULE_TEMPLATES=y KERN_MODPOST_PASS=y $(@:%=%-local) ; \
+ fi
+
+$(eval $(call omk_pass_template, library-pass,$(USER_OBJS_DIR),USER_RULE_TEMPLATES=y,$(lib_LIBRARIES)$(shared_LIBRARIES)))
+$(eval $(call omk_pass_template, binary-pass, $(USER_OBJS_DIR),USER_RULE_TEMPLATES=y,$(bin_PROGRAMS)$(utils_PROGRAMS)$(test_PROGRAMS)))
+
+$(eval $(call omk_pass_template,clean,$(USER_OBJS_DIR),,always))
+$(eval $(call omk_pass_template,install,$(USER_OBJS_DIR),,always))
+$(eval $(call omk_pass_template,include-pass,$(USER_OBJS_DIR),USER_RULE_TEMPLATES=y,always))
+
+check-dir:
+ @$(call mkdir_def,$(USER_BUILD_DIR))
+ @$(call mkdir_def,$(KERN_BUILD_DIR))
+ @$(call mkdir_def,$(USER_INCLUDE_DIR))
+ @$(call mkdir_def,$(KERN_INCLUDE_DIR))
+ @$(call mkdir_def,$(USER_LIB_DIR))
+ @$(call mkdir_def,$(KERN_LIB_DIR))
+ @$(call mkdir_def,$(USER_BIN_DIR))
+ @$(call mkdir_def,$(USER_UTILS_DIR))
+ @$(call mkdir_def,$(USER_TESTS_DIR))
+ @$(call mkdir_def,$(KERN_MODULES_DIR))
+ @$(call mkdir_def,$(KERN_MODPOST_DIR))
+
+install-local: # TODO
+
+$(eval $(call include-pass-template,$(USER_INCLUDE_DIR),include))
+$(eval $(call include-pass-template,$(KERN_INCLUDE_DIR),kernel))
+ifeq ($(CONFIG_RTLINUX),y)
+$(eval $(call include-pass-template,$(KERN_INCLUDE_DIR),rtlinux))
+endif
+
+
+ifdef USER_RULE_TEMPLATES
+
+# User-space static libraries and applications object files
+
+USER_SOURCES := $(sort $(USER_SOURCES))
+
+USER_GEN_SOURCES := $(sort $(USER_GEN_SOURCES))
+
+#$(warning USER_SOURCES = $(USER_SOURCES))
+
+$(foreach src,$(filter %.c,$(USER_SOURCES)),$(eval $(call COMPILE_c_o_template,$(SOURCES_DIR)/$(src),$(src:%.c=%.o),)))
+
+$(foreach src,$(filter %.cc,$(USER_SOURCES)),$(eval $(call COMPILE_cc_o_template,$(SOURCES_DIR)/$(src),$(src:%.cc=%.o),)))
+
+$(foreach src,$(filter %.cxx,$(USER_SOURCES)),$(eval $(call COMPILE_cc_o_template,$(SOURCES_DIR)/$(src),$(src:%.cxx=%.o),)))
+
+$(foreach src,$(filter %.S,$(USER_SOURCES)),$(eval $(call COMPILE_S_o_template,$(SOURCES_DIR)/$(src),$(src:%.S=%.o),)))
+
+$(foreach src,$(filter %.c,$(USER_GEN_SOURCES)),$(eval $(call COMPILE_c_o_template,$(src),$(src:%.c=%.o),)))
+
+# User-space shared libraries object files
+
+SOLIB_SOURCES := $(sort $(SOLIB_SOURCES))
+
+SOLIB_GEN_SOURCES := $(sort $(SOLIB_GEN_SOURCES))
+
+#$(warning SOLIB_SOURCES = $(SOLIB_SOURCES))
+#$(warning SOLIB_GEN_SOURCES = $(SOLIB_GEN_SOURCES))
+
+$(foreach src,$(filter %.c,$(SOLIB_SOURCES)),$(eval $(call COMPILE_c_o_template,$(SOURCES_DIR)/$(src),$(src:%.c=%.lo),$(SOLIB_PICFLAGS))))
+
+$(foreach src,$(filter %.cc,$(SOLIB_SOURCES)),$(eval $(call COMPILE_cc_o_template,$(SOURCES_DIR)/$(src),$(src:%.cc=%.lo),$(SOLIB_PICFLAGS))))
+
+$(foreach src,$(filter %.cxx,$(SOLIB_SOURCES)),$(eval $(call COMPILE_cc_o_template,$(SOURCES_DIR)/$(src),$(src:%.cxx=%.lo),$(SOLIB_PICFLAGS))))
+
+$(foreach src,$(filter %.S,$(SOLIB_SOURCES)),$(eval $(call COMPILE_S_o_template,$(SOURCES_DIR)/$(src),$(src:%.S=%.lo),$(SOLIB_PICFLAGS))))
+
+$(foreach src,$(filter %.c,$(SOLIB_GEN_SOURCES)),$(eval $(call COMPILE_c_o_template,$(src),$(src:%.c=%.lo),$(SOLIB_PICFLAGS))))
+
+# IDL compilation
+
+USER_IDLS := $(sort $(USER_IDLS))
+
+$(foreach src,$(filter %.idl,$(USER_IDLS)),$(eval $(call COMPILE_idl_template,$(SOURCES_DIR)/$(src),$(src:%.idl=%))))
+
+endif
+
+ifdef KERN_RULE_TEMPLATES
+
+KERN_SOURCES := $(sort $(KERN_SOURCES))
+
+#$(warning KERN_SOURCES = $(KERN_SOURCES))
+
+$(foreach src,$(filter %.c,$(KERN_SOURCES)),$(eval $(call COMPILE_c_o_kern_template,$(SOURCES_DIR)/$(src),$(src:%.c=%.o),)))
+
+$(foreach src,$(filter %.cc,$(KERN_SOURCES)),$(eval $(call COMPILE_cc_o_kern_template,$(SOURCES_DIR)/$(src),$(src:%.cc=%.o),)))
+
+$(foreach src,$(filter %.cxx,$(KERN_SOURCES)),$(eval $(call COMPILE_cc_o_kern_template,$(SOURCES_DIR)/$(src),$(src:%.cxx=%.o),)))
+
+$(foreach src,$(filter %.S,$(USER_SOURCES)),$(eval $(call COMPILE_S_o_kern_template,$(SOURCES_DIR)/$(src),$(src:%.S=%.o),)))
+endif
+
+clean-local: clean-custom
+ @echo Cleaning in $(KERN_OBJS_DIR) and $(USER_OBJS_DIR)
+ @rm -f $(KERN_OBJS_DIR)/*.o $(USER_OBJS_DIR)/*.[och] $(USER_OBJS_DIR)/*.lo\
+ $(KERN_OBJS_DIR)/*.d $(USER_OBJS_DIR)/*.d \
+ $(KERN_OBJS_DIR)/*.map $(USER_OBJS_DIR)/*.map \
+ $(KERN_OBJS_DIR)/*.mod.c \
+ $(kernel_MODULES:%=$(KERN_MODPOST_DIR)/%.*) \
+ $(LOCAL_CONFIG_H:%=$(KERN_OBJS_DIR)/%) \
+ $(LOCAL_CONFIG_H:%=$(USER_OBJS_DIR)/%)
+ @if [ -e $(KERN_LIB_DIR)/kernel.mk ] ; then \
+ touch -t 200001010101 $(KERN_LIB_DIR)/kernel.mk ; \
+ fi
+
+include-pass-submakes: extra-rules-subdirs
+
+# We must go to EXTRA_RULES_SUBDIRS beofre going to any other
+# directory, since the executables compiled in EXTRA_RULES_SUBDIRS
+# might be needed there.
+include-pass-this-dir $(foreach subdir,$(SUBDIRS),include-pass-$(subdir)-subdir): extra-rules-subdirs
+
+default: include-pass library-pass binary-pass
+ifndef OMIT_KERNEL_PASSES
+# Also make kernel passes if not disabled
+default: kernel-lib-pass kernel-pass
+endif
+
+# Local Variables:
+# mode:makefile
+# End:
+ #OMK@config_h
+# Syntax: $(call BUILD_CONFIG_H_template,<stamp_dir>,<header_file_path>,<list_of_options_to_export>,<header_barrier>)
+define BUILD_CONFIG_H_template
+
+$(addprefix $(1)/,$(notdir $(addsuffix .stamp,$(2)))) : $(CONFIG_FILES)
+ @$(QUIET_CMD_ECHO) " CONFGEN $$(@:%.stamp=%)"
+ @if [ ! -d `dirname $(2).tmp` ] ; then \
+ mkdir -p `dirname $(2).tmp` ; fi
+ @echo "/* Automatically generated from */" > "$(2).tmp"
+ @echo "/* config files: $$(^:$(OUTPUT_DIR)/%=%) */" >> "$(2).tmp"
+ $(if $(DOXYGEN),@echo "/** @file */" >> "$(2).tmp")
+ @echo "#ifndef $(4)" >> "$(2).tmp"
+ @echo "#define $(4)" >> "$(2).tmp"
+ @( $(foreach x, $(shell echo '$($(3))' | tr 'x\t ' 'x\n\n' | sed -e 's/^\([^ =]*\)\(=[^ ]\+\|\)$$/\1/' ), \
+ echo '$(x).$($(x))' ; ) echo ; ) | \
+ sed -e '/^[^.]*\.n$$$$/d' -e '/^[^.]*\.$$$$/d' -e 's/^\([^.]*\)\.[ym]$$$$/\1.1/' | \
+ sed -n -e 's/^\([^.]*\)\.\(.*\)$$$$/#define \1 \2/p' \
+ >> "$(2).tmp"
+ @echo "#endif /*$(4)*/" >> "$(2).tmp"
+ @touch "$$@"
+ @if cmp --quiet "$(2).tmp" "$(2)" ; then rm "$(2).tmp"; \
+ else mv "$(2).tmp" "$(2)" ; \
+ echo "Updated configuration $(2)" ; fi
+
+endef
+
+ifdef LOCAL_CONFIG_H
+
+# This must be declared after the default cflags are assigned!
+# Override is used to override command line assignemnt.
+override CFLAGS += -I $(USER_OBJS_DIR)
+override kernel_INCLUDES += -I $(KERN_OBJS_DIR)
+$(eval $(call BUILD_CONFIG_H_template,$(USER_OBJS_DIR),$(USER_OBJS_DIR)/$(LOCAL_CONFIG_H),default_CONFIG,_LOCAL_CONFIG_H) )
+
+endif
+
+# Special rules for configuration exported headers
+
+#FIXME: The directory for headers should not be specified here.
+$(foreach confh,$(config_include_HEADERS),$(eval $(call BUILD_CONFIG_H_template,$(USER_OBJS_DIR),$(addprefix $(USER_INCLUDE_DIR)/,$(confh)),$(basename $(notdir $(confh)))_DEFINES,\
+_$(basename $(notdir $(confh)))_H \
+)))
+
+config_h_stamp_files = $(addprefix $(USER_OBJS_DIR)/,$(notdir $(addsuffix .stamp,$(config_include_HEADERS) $(LOCAL_CONFIG_H))))
+
+# Add some hooks to standard passes
+include-pass-local: $(config_h_stamp_files)
+
+ifneq ($(KERN_CONFIG_HEADERS_REQUIRED),)
+
+ifdef LOCAL_CONFIG_H
+$(eval $(call BUILD_CONFIG_H_template,$(KERN_OBJS_DIR),$(KERN_OBJS_DIR)/$(LOCAL_CONFIG_H),default_CONFIG,_LOCAL_CONFIG_H) )
+endif
+
+$(foreach confh,$(config_include_HEADERS),$(eval $(call BUILD_CONFIG_H_template,$(KERN_OBJS_DIR),$(addprefix $(KERN_INCLUDE_DIR)/,$(confh)),$(basename $(notdir $(confh)))_DEFINES,\
+_$(basename $(notdir $(confh)))_H \
+)))
+
+kern_config_h_stamp_files = $(addprefix $(KERN_OBJS_DIR)/,$(notdir $(addsuffix .stamp,$(config_include_HEADERS) $(LOCAL_CONFIG_H))))
+
+# Add some hooks to standard passes
+include-pass-local: $(kern_config_h_stamp_files)
+
+endif
+
+clean-local: clean-local-config-h
+
+clean-local-config-h:
+ @$(foreach confh,$(config_h_stamp_files) $(kern_config_h_stamp_files),\
+ if [ -e $(confh) ] ; then rm $(confh) ; fi ; \
+ )
+
+
+# Local Variables:
+# mode:makefile
+# End:
+ #OMK@qt
+ifneq ($(QT_SUBDIRS),)
+
+.PHONY: qt-subpass clean-qt distclean-qt
+
+# Usage: $(call qt_makefile_template,<qt-subdir>)
+define qt_makefile_template
+$(SOURCES_DIR)/$(1)/Makefile: $(wildcard $(SOURCES_DIR)/$(1)/*.pro)
+ cd $(SOURCES_DIR)/$(1); $(QTDIR:%=%/bin/)qmake TOP_DIR=$(OUTPUT_DIR) \
+ RELATIVE_DIR=$(RELATIVE_PREFIX)$(1) $(QTDIR:%=QTDIR=%) CC=$(CC) \
+ CXX=$(CXX) LIBS+="-L$(USER_LIB_DIR)" INCLUDEPATH+="$(USER_INCLUDE_DIR)"
+endef
+$(foreach dir,$(QT_SUBDIRS), $(eval $(call qt_makefile_template,$(dir))))
+
+qt-subpass: $(foreach dir,$(QT_SUBDIRS), $(SOURCES_DIR)/$(dir)/Makefile)
+ $(foreach dir,$(QT_SUBDIRS),\
+ $(MAKE) SOURCES_DIR=$(SOURCES_DIR)/$(dir) \
+ RELATIVE_DIR=$(RELATIVE_PREFIX)$(dir) -C $(SOURCES_DIR)/$(dir) \
+ -f $(SOURCES_DIR)/$(dir)/Makefile || exit 1 ;)
+
+# Hook to binary pass
+binary-pass-submakes: qt-subpass
+
+# Hook to clean pass
+clean-local: clean-qt
+clean-qt:
+ +@$(foreach dir, $(QT_SUBDIRS), \
+ $(if $(wildcard $(SOURCES_DIR)/$(dir)/Makefile), \
+ @$(QUIET_CMD_ECHO) " CLEAN $(dir)"; \
+ $(MAKE) SOURCES_DIR=$(SOURCES_DIR)/$(dir) \
+ RELATIVE_DIR=$(RELATIVE_PREFIX)$(dir) -C $(SOURCES_DIR)/$(dir) \
+ -f $(SOURCES_DIR)/$(dir)/Makefile clean|| exit 1 ;))
+
+
+# Hook to distclean
+distclean: distclean-qt
+
+# TODO: Add distclean-qt-pass to handle QT_SUBDIRS in the whole
+# tree. This way we only distclean toplevel subdirs.
+distclean-qt:
+ +@$(foreach dir, $(QT_SUBDIRS), \
+ $(if $(wildcard $(SOURCES_DIR)/$(dir)/Makefile), \
+ @$(QUIET_CMD_ECHO) " DISTCLEAN $(dir)"; \
+ $(MAKE) SOURCES_DIR=$(SOURCES_DIR)/$(dir) \
+ RELATIVE_DIR=$(RELATIVE_PREFIX)$(dir) -C $(SOURCES_DIR)/$(dir) \
+ -f $(SOURCES_DIR)/$(dir)/Makefile distclean|| exit 1 ;))
+endif
+
+# Local Variables:
+# mode:makefile
+# End:
+ #OMK@sources-list
+# Rules that creates the list of files which are used during
+# compilation. The list reflects conditional compilation depending on
+# config.omk and other variables.
+
+SOURCES_LIST_FN=sources.txt
+ifndef SOURCES_LIST
+SOURCES_LIST_DIR:=$(RELATIVE_DIR)
+SOURCES_LIST:=$(OUTPUT_DIR)/$(SOURCES_LIST_DIR)/$(SOURCES_LIST_FN)
+SOURCES_LIST_D := $(LOCAL_BUILD_DIR)/$(SOURCES_LIST_FN).d
+export SOURCES_LIST SOURCES_LIST_DIR SOURCES_LIST_D
+endif
+
+ifeq ($(MAKECMDGOALS),sources-list)
+NEED_SOURCES_LIST=y
+endif
+ifeq ($(MAKECMDGOALS),TAGS)
+NEED_SOURCES_LIST=y
+endif
+ifeq ($(MAKECMDGOALS),tags)
+NEED_SOURCES_LIST=y
+endif
+
+ifeq ($(NEED_SOURCES_LIST),y) # avoid execution of find command bellow if it is not useful
+.PHONY: sources-list
+sources-list: $(SOURCES_LIST)
+
+$(SOURCES_LIST): $(CONFIG_FILES) $(shell find -name $(MAKEFILE_OMK))
+ @$(call mkdir_def,$(dir $(SOURCES_LIST_D)))
+ @echo -n "" > "$(SOURCES_LIST).tmp"
+ @echo -n "" > "$(SOURCES_LIST_D).tmp"
+ @$(MAKE) --no-print-directory sources-list-pass
+ @echo "# Automatically generated list of files in '$(RELATIVE_DIR)' that are used during OMK compilation" > "$(SOURCES_LIST).tmp2"
+ @cat "$(SOURCES_LIST).tmp"|sort|uniq >> "$(SOURCES_LIST).tmp2"
+ @rm "$(SOURCES_LIST).tmp"
+ @mv "$(SOURCES_LIST).tmp2" "$(SOURCES_LIST)"
+ @echo "$(SOURCES_LIST): \\" > "$(SOURCES_LIST_D).tmp2"
+ @cat "$(SOURCES_LIST_D).tmp"|grep -v "$(SOURCES_LIST_D).tmp"|sort|uniq|\
+ sed -e 's/$$/\\/' >> "$(SOURCES_LIST_D).tmp2"
+ @rm "$(SOURCES_LIST_D).tmp"
+ @mv "$(SOURCES_LIST_D).tmp2" "$(SOURCES_LIST_D)"
+endif
+
+$(eval $(call omk_pass_template,sources-list-pass,$$(LOCAL_BUILD_DIR),,always))
+
+sources-list-pass-local:
+ @$(foreach m,$(MAKEFILE_LIST),echo ' $(m)' >> "$(SOURCES_LIST_D).tmp";)
+ @$(foreach h,$(include_HEADERS) $(nobase_include_HEADERS) $(kernel_HEADERS),\
+ echo "$(addsuffix /,$(RELATIVE_DIR:$(SOURCES_LIST_DIR)/%=%))$(h)" >> "$(SOURCES_LIST).tmp";)
+ @$(foreach ch,$(config_include_HEADERS), \
+ echo "$(USER_INCLUDE_DIR:$(OUTPUT_DIR)/$(addsuffix /,$(SOURCES_LIST_DIR))%=%)/$(ch)" >> "$(SOURCES_LIST).tmp";)
+ @$(foreach h,$(renamed_include_HEADERS),echo '$(h)'|sed -e 's|\(.*\)->.*|$(addsuffix /,$(RELATIVE_DIR:$(SOURCES_LIST_DIR)/%=%))\1|' >> "$(SOURCES_LIST).tmp";)
+ @$(foreach bin,$(lib_LIBRARIES) $(shared_LIBRARIES) $(bin_PROGRAMS) $(test_PROGRAMS) $(utils_PROGRAMS) \
+ $(kernel_LIBRARIES) $(rtlinux_LIBRARIES) $(kernel_MODULES),\
+ $(foreach src,$(filter-out %.o,$($(bin)_SOURCES)),echo "$(addsuffix /,$(RELATIVE_DIR:$(SOURCES_LIST_DIR)/%=%))$(src)" >> "$(SOURCES_LIST).tmp";))
+
+############ TAGS ###########
+
+ifeq ($(MAKECMDGOALS),TAGS)
+ETAGS=etags
+TAGS_CMD = $(ETAGS)
+TAGS: $(SOURCES_LIST)
+ @$(MAKE) --no-print-directory do-tags
+endif
+ifeq ($(MAKECMDGOALS),tags)
+CTAGS=ctags -N
+TAGS_CMD = $(CTAGS)
+tags: $(SOURCES_LIST)
+ @$(MAKE) --no-print-directory do-tags
+endif
+export TAGS_CMD
+
+ifeq ($(MAKECMDGOALS),do-tags)
+.PHONY: do-tags
+do-tags: $(shell sed -e '/^\#/d' $(SOURCES_LIST))
+ @$(QUIET_CMD_ECHO) " TAGS $(SOURCES_LIST_FN)"
+ $(Q)$(TAGS_CMD) $^
+endif
+
+############ CSCOPE ###########
+
+cscope: $(SOURCES_LIST)
+ @$(QUIET_CMD_ECHO) " CSCOPE < $(SOURCES_LIST_FN)"
+ $(Q)sed -e '/^#/d' $(SOURCES_LIST)|cscope -b -i-
+#FIXME: see doc to -i in cscope(1)
+
+# Local Variables:
+# mode:makefile
+# End:
--- /dev/null
+/* Automatically generated from */
+/* config files: config.omk-default */
+#ifndef _LOCAL_CONFIG_H
+#define _LOCAL_CONFIG_H
+#define CONFIG_OC_UL_DRV_WITH_USB 1
+#define CONFIG_OC_UL_DRV_WITH_PCI 1
+#endif /*_LOCAL_CONFIG_H*/
--- /dev/null
+/* Automatically generated from */
+/* config files: config.omk-default */
+#ifndef _LOCAL_CONFIG_H
+#define _LOCAL_CONFIG_H
+#define CONFIG_OC_UL_DRV_WITH_USB 1
+#define CONFIG_OC_UL_DRV_WITH_PCI 1
+#endif /*_LOCAL_CONFIG_H*/
--- /dev/null
+/* Automatically generated from */
+/* config files: config.omk-default */
+#ifndef _LOCAL_CONFIG_H
+#define _LOCAL_CONFIG_H
+#define CONFIG_OC_UL_DRV_WITH_USB 1
+#define CONFIG_OC_UL_DRV_WITH_PCI 1
+#endif /*_LOCAL_CONFIG_H*/
--- /dev/null
+/* Automatically generated from */
+/* config files: config.omk-default */
+#ifndef _LOCAL_CONFIG_H
+#define _LOCAL_CONFIG_H
+#define CONFIG_OC_UL_DRV_WITH_USB 1
+#define CONFIG_OC_UL_DRV_WITH_PCI 1
+#endif /*_LOCAL_CONFIG_H*/
--- /dev/null
+ul_l_drv.o ul_l_drv.o: \
+ /home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/ul_drv/ul_lib/ul_l_drv.c \
+ /usr/include/sys/types.h /usr/include/features.h \
+ /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
+ /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/time.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.2.3/include/stddef.h \
+ /usr/include/endian.h /usr/include/bits/endian.h \
+ /usr/include/sys/select.h /usr/include/bits/select.h \
+ /usr/include/bits/sigset.h /usr/include/bits/time.h \
+ /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
+ /usr/include/sys/stat.h /usr/include/bits/stat.h \
+ /usr/include/sys/time.h /usr/include/unistd.h \
+ /usr/include/bits/posix_opt.h /usr/include/bits/confname.h \
+ /usr/include/getopt.h /usr/include/fcntl.h /usr/include/bits/fcntl.h \
+ /usr/include/errno.h /usr/include/bits/errno.h \
+ /usr/include/linux/errno.h /usr/include/asm/errno.h \
+ /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \
+ /usr/include/string.h /usr/include/bits/string.h \
+ /usr/include/bits/string2.h /usr/include/stdlib.h /usr/include/alloca.h \
+ /home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ulan.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.2.3/include/stdarg.h \
+ /home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ul_drvdef.h \
+ /home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ul_lib_config.h \
+ /usr/include/sys/ioctl.h /usr/include/bits/ioctls.h \
+ /usr/include/asm/ioctls.h /usr/include/asm/ioctl.h \
+ /usr/include/asm-generic/ioctl.h /usr/include/bits/ioctl-types.h \
+ /usr/include/sys/ttydefaults.h \
+ /home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ul_fd.h \
+ /home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ul_fddir.h
+
+/usr/include/sys/types.h:
+
+/usr/include/features.h:
+
+/usr/include/sys/cdefs.h:
+
+/usr/include/bits/wordsize.h:
+
+/usr/include/gnu/stubs.h:
+
+/usr/include/gnu/stubs-64.h:
+
+/usr/include/bits/types.h:
+
+/usr/include/bits/typesizes.h:
+
+/usr/include/time.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.2.3/include/stddef.h:
+
+/usr/include/endian.h:
+
+/usr/include/bits/endian.h:
+
+/usr/include/sys/select.h:
+
+/usr/include/bits/select.h:
+
+/usr/include/bits/sigset.h:
+
+/usr/include/bits/time.h:
+
+/usr/include/sys/sysmacros.h:
+
+/usr/include/bits/pthreadtypes.h:
+
+/usr/include/sys/stat.h:
+
+/usr/include/bits/stat.h:
+
+/usr/include/sys/time.h:
+
+/usr/include/unistd.h:
+
+/usr/include/bits/posix_opt.h:
+
+/usr/include/bits/confname.h:
+
+/usr/include/getopt.h:
+
+/usr/include/fcntl.h:
+
+/usr/include/bits/fcntl.h:
+
+/usr/include/errno.h:
+
+/usr/include/bits/errno.h:
+
+/usr/include/linux/errno.h:
+
+/usr/include/asm/errno.h:
+
+/usr/include/asm-generic/errno.h:
+
+/usr/include/asm-generic/errno-base.h:
+
+/usr/include/string.h:
+
+/usr/include/bits/string.h:
+
+/usr/include/bits/string2.h:
+
+/usr/include/stdlib.h:
+
+/usr/include/alloca.h:
+
+/home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ulan.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.2.3/include/stdarg.h:
+
+/home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ul_drvdef.h:
+
+/home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ul_lib_config.h:
+
+/usr/include/sys/ioctl.h:
+
+/usr/include/bits/ioctls.h:
+
+/usr/include/asm/ioctls.h:
+
+/usr/include/asm/ioctl.h:
+
+/usr/include/asm-generic/ioctl.h:
+
+/usr/include/bits/ioctl-types.h:
+
+/usr/include/sys/ttydefaults.h:
+
+/home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ul_fd.h:
+
+/home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ul_fddir.h:
--- /dev/null
+ul_l_log.o ul_l_log.o: \
+ /home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/ul_drv/ul_lib/ul_l_log.c \
+ /usr/include/stdlib.h /usr/include/features.h /usr/include/sys/cdefs.h \
+ /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
+ /usr/include/gnu/stubs-64.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.2.3/include/stddef.h \
+ /usr/include/sys/types.h /usr/include/bits/types.h \
+ /usr/include/bits/typesizes.h /usr/include/time.h /usr/include/endian.h \
+ /usr/include/bits/endian.h /usr/include/sys/select.h \
+ /usr/include/bits/select.h /usr/include/bits/sigset.h \
+ /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
+ /usr/include/bits/pthreadtypes.h /usr/include/alloca.h \
+ /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h \
+ /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.2.3/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/bits/stdio.h \
+ /home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ulan.h \
+ /home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ul_drvdef.h \
+ /home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ul_lib_config.h \
+ /usr/include/sys/ioctl.h /usr/include/bits/ioctls.h \
+ /usr/include/asm/ioctls.h /usr/include/asm/ioctl.h \
+ /usr/include/asm-generic/ioctl.h /usr/include/bits/ioctl-types.h \
+ /usr/include/sys/ttydefaults.h \
+ /home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ul_fd.h \
+ /home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ul_fddir.h \
+ /home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ul_l_log.h
+
+/usr/include/stdlib.h:
+
+/usr/include/features.h:
+
+/usr/include/sys/cdefs.h:
+
+/usr/include/bits/wordsize.h:
+
+/usr/include/gnu/stubs.h:
+
+/usr/include/gnu/stubs-64.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.2.3/include/stddef.h:
+
+/usr/include/sys/types.h:
+
+/usr/include/bits/types.h:
+
+/usr/include/bits/typesizes.h:
+
+/usr/include/time.h:
+
+/usr/include/endian.h:
+
+/usr/include/bits/endian.h:
+
+/usr/include/sys/select.h:
+
+/usr/include/bits/select.h:
+
+/usr/include/bits/sigset.h:
+
+/usr/include/bits/time.h:
+
+/usr/include/sys/sysmacros.h:
+
+/usr/include/bits/pthreadtypes.h:
+
+/usr/include/alloca.h:
+
+/usr/include/stdio.h:
+
+/usr/include/libio.h:
+
+/usr/include/_G_config.h:
+
+/usr/include/wchar.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.2.3/include/stdarg.h:
+
+/usr/include/bits/stdio_lim.h:
+
+/usr/include/bits/sys_errlist.h:
+
+/usr/include/bits/stdio.h:
+
+/home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ulan.h:
+
+/home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ul_drvdef.h:
+
+/home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ul_lib_config.h:
+
+/usr/include/sys/ioctl.h:
+
+/usr/include/bits/ioctls.h:
+
+/usr/include/asm/ioctls.h:
+
+/usr/include/asm/ioctl.h:
+
+/usr/include/asm-generic/ioctl.h:
+
+/usr/include/bits/ioctl-types.h:
+
+/usr/include/sys/ttydefaults.h:
+
+/home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ul_fd.h:
+
+/home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ul_fddir.h:
+
+/home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ul_l_log.h:
--- /dev/null
+ul_l_msg.o ul_l_msg.o: \
+ /home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/ul_drv/ul_lib/ul_l_msg.c \
+ /usr/include/stdlib.h /usr/include/features.h /usr/include/sys/cdefs.h \
+ /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
+ /usr/include/gnu/stubs-64.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.2.3/include/stddef.h \
+ /usr/include/sys/types.h /usr/include/bits/types.h \
+ /usr/include/bits/typesizes.h /usr/include/time.h /usr/include/endian.h \
+ /usr/include/bits/endian.h /usr/include/sys/select.h \
+ /usr/include/bits/select.h /usr/include/bits/sigset.h \
+ /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
+ /usr/include/bits/pthreadtypes.h /usr/include/alloca.h \
+ /usr/include/string.h /usr/include/bits/string.h \
+ /usr/include/bits/string2.h \
+ /home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ulan.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.2.3/include/stdarg.h \
+ /home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ul_drvdef.h \
+ /home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ul_lib_config.h \
+ /usr/include/sys/ioctl.h /usr/include/bits/ioctls.h \
+ /usr/include/asm/ioctls.h /usr/include/asm/ioctl.h \
+ /usr/include/asm-generic/ioctl.h /usr/include/bits/ioctl-types.h \
+ /usr/include/sys/ttydefaults.h \
+ /home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ul_fd.h \
+ /home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ul_fddir.h
+
+/usr/include/stdlib.h:
+
+/usr/include/features.h:
+
+/usr/include/sys/cdefs.h:
+
+/usr/include/bits/wordsize.h:
+
+/usr/include/gnu/stubs.h:
+
+/usr/include/gnu/stubs-64.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.2.3/include/stddef.h:
+
+/usr/include/sys/types.h:
+
+/usr/include/bits/types.h:
+
+/usr/include/bits/typesizes.h:
+
+/usr/include/time.h:
+
+/usr/include/endian.h:
+
+/usr/include/bits/endian.h:
+
+/usr/include/sys/select.h:
+
+/usr/include/bits/select.h:
+
+/usr/include/bits/sigset.h:
+
+/usr/include/bits/time.h:
+
+/usr/include/sys/sysmacros.h:
+
+/usr/include/bits/pthreadtypes.h:
+
+/usr/include/alloca.h:
+
+/usr/include/string.h:
+
+/usr/include/bits/string.h:
+
+/usr/include/bits/string2.h:
+
+/home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ulan.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.2.3/include/stdarg.h:
+
+/home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ul_drvdef.h:
+
+/home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ul_lib_config.h:
+
+/usr/include/sys/ioctl.h:
+
+/usr/include/bits/ioctls.h:
+
+/usr/include/asm/ioctls.h:
+
+/usr/include/asm/ioctl.h:
+
+/usr/include/asm-generic/ioctl.h:
+
+/usr/include/bits/ioctl-types.h:
+
+/usr/include/sys/ttydefaults.h:
+
+/home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ul_fd.h:
+
+/home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ul_fddir.h:
--- /dev/null
+ul_l_oi.o ul_l_oi.o: \
+ /home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/ul_drv/ul_lib/ul_l_oi.c \
+ /usr/include/stdlib.h /usr/include/features.h /usr/include/sys/cdefs.h \
+ /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
+ /usr/include/gnu/stubs-64.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.2.3/include/stddef.h \
+ /usr/include/sys/types.h /usr/include/bits/types.h \
+ /usr/include/bits/typesizes.h /usr/include/time.h /usr/include/endian.h \
+ /usr/include/bits/endian.h /usr/include/sys/select.h \
+ /usr/include/bits/select.h /usr/include/bits/sigset.h \
+ /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
+ /usr/include/bits/pthreadtypes.h /usr/include/alloca.h \
+ /usr/include/string.h /usr/include/bits/string.h \
+ /usr/include/bits/string2.h \
+ /home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ulan.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.2.3/include/stdarg.h \
+ /home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ul_drvdef.h \
+ /home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ul_lib_config.h \
+ /usr/include/sys/ioctl.h /usr/include/bits/ioctls.h \
+ /usr/include/asm/ioctls.h /usr/include/asm/ioctl.h \
+ /usr/include/asm-generic/ioctl.h /usr/include/bits/ioctl-types.h \
+ /usr/include/sys/ttydefaults.h \
+ /home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ul_fd.h \
+ /home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ul_fddir.h \
+ /home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ul_l_log.h
+
+/usr/include/stdlib.h:
+
+/usr/include/features.h:
+
+/usr/include/sys/cdefs.h:
+
+/usr/include/bits/wordsize.h:
+
+/usr/include/gnu/stubs.h:
+
+/usr/include/gnu/stubs-64.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.2.3/include/stddef.h:
+
+/usr/include/sys/types.h:
+
+/usr/include/bits/types.h:
+
+/usr/include/bits/typesizes.h:
+
+/usr/include/time.h:
+
+/usr/include/endian.h:
+
+/usr/include/bits/endian.h:
+
+/usr/include/sys/select.h:
+
+/usr/include/bits/select.h:
+
+/usr/include/bits/sigset.h:
+
+/usr/include/bits/time.h:
+
+/usr/include/sys/sysmacros.h:
+
+/usr/include/bits/pthreadtypes.h:
+
+/usr/include/alloca.h:
+
+/usr/include/string.h:
+
+/usr/include/bits/string.h:
+
+/usr/include/bits/string2.h:
+
+/home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ulan.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.2.3/include/stdarg.h:
+
+/home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ul_drvdef.h:
+
+/home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ul_lib_config.h:
+
+/usr/include/sys/ioctl.h:
+
+/usr/include/bits/ioctls.h:
+
+/usr/include/asm/ioctls.h:
+
+/usr/include/asm/ioctl.h:
+
+/usr/include/asm-generic/ioctl.h:
+
+/usr/include/bits/ioctl-types.h:
+
+/usr/include/sys/ttydefaults.h:
+
+/home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ul_fd.h:
+
+/home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ul_fddir.h:
+
+/home/stefic/BAP/build_ulan/ulan/embedded/hydro/app-bohyn/_compiled/include/ul_lib/ul_l_log.h:
--- /dev/null
+#ifndef _UL_L_DRV_ETH_H
+#define _UL_L_DRV_ETH_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <ul_dbuff.h>
+#include <ul_netbase.h>
+
+#define UL_ETH_SOCK_TIMEOUT 10
+
+int ul_eth_recv_msg(int fd,ul_dbuff_t *rcvbuff,int timeout, int *terminated);
+int ul_eth_send_msg(FILE *fd,ul_msg_buf_t *sndbuff);
+int ul_eth_demarshal_stream(ul_msg_buf_t *msg_buf,char *stream,int stream_len);
+
+#ifdef __cplusplus
+} /* extern "C"*/
+#endif
+
+#endif /*_UL_L_DRV_ETH_H*/
--- /dev/null
+/*******************************************************************
+ uLan Communication - user visible definitions
+
+ ul_drvdef.h - driver exported definitions and types to userspace
+
+ (C) Copyright 1996,1999 by Pavel Pisa
+
+ The uLan driver is distributed under the Gnu General Public Licence.
+ See file COPYING for details.
+ *******************************************************************/
+
+#ifndef _UL_DRVDEF_H
+#define _UL_DRVDEF_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined OMK_FOR_TARGET || defined OMK_FOR_USER || defined OMK_FOR_KERNEL
+ #include <ul_lib/ul_lib_config.h>
+#endif
+
+#ifndef _WIN32
+ #ifndef CONFIG_OC_UL_DRV_SYSLESS
+ #include <sys/ioctl.h>
+ #endif /* CONFIG_OC_UL_DRV_SYSLESS */
+#else /* _WIN32 */
+ #include <windows.h>
+ #include <winioctl.h>
+#endif /* _WIN32 */
+
+#ifndef uchar
+ #define uchar unsigned char
+#endif
+
+/* ul_mess_head flags definition defines proccessing
+ of message or its frames stored in bll */
+#define UL_BFL_LOCK 0x8000 /* locked message is pointed only once */
+#define UL_BFL_MSST 0x4000 /* Message must be received by some proccess */
+#define UL_BFL_M2IN 0x2000 /* After succesfull proccessing move to proc_bll */
+#define UL_BFL_LNMM 0x1000 /* Length of received frame must match expected len */
+#define UL_BFL_FAIL 0x0800 /* Message cannot be proccessed - error */
+#define UL_BFL_TAIL 0x0400 /* Multiframe message continues by next bll block */
+#define UL_BFL_SND 0x0200 /* Send this frame */
+#define UL_BFL_REC 0x0100 /* Receive answer frame into this bll block */
+#define UL_BFL_VERL 0x0040 /* Verify free space in buffer of destination station */
+#define UL_BFL_NORE 0x0020 /* Do not try to repeat if error occurs */
+#define UL_BFL_REWA 0x0010 /* If error occurs do wait with retry */
+#define UL_BFL_PRQ 0x0002 /* Request imediate proccessing of frame by receiver station */
+#define UL_BFL_ARQ 0x0001 /* Request imediate acknowledge by receiving station */
+
+#define UL_BFL_PROC 0x0000 /* Flag used by ASM code version */
+
+/*******************************************************************/
+/* ioctl definitions */
+
+#ifdef _WIN32
+
+/* 32768-65535 are reserved for use by customers.*/
+#define FILE_DEVICE_ULAN 0x0000A000
+
+/* function codes 2048-4095 are reserved for customers. */
+#define UL_IOCTL_INDEX 0xA00
+
+#define UL_IO(function) \
+ CTL_CODE(FILE_DEVICE_ULAN,UL_IOCTL_INDEX+function,METHOD_BUFFERED,FILE_ANY_ACCESS)
+#define UL_IOR(function,size) \
+ CTL_CODE(FILE_DEVICE_ULAN,UL_IOCTL_INDEX+function,METHOD_BUFFERED,FILE_ANY_ACCESS)
+#define UL_IOW(function,size) \
+ CTL_CODE(FILE_DEVICE_ULAN,UL_IOCTL_INDEX+function,METHOD_BUFFERED,FILE_ANY_ACCESS)
+
+#else /* _WIN32 */
+
+#define UL_IOCTL 0x75
+
+#define UL_IO(function) _IO(UL_IOCTL,function)
+#define UL_IOR(function,size) _IOR(UL_IOCTL,function,size)
+#define UL_IOW(function,size) _IOW(UL_IOCTL,function,size)
+
+#endif /* _WIN32 */
+
+#define UL_DRV_VER UL_IO(0x10)
+#define UL_NEWMSG UL_IOW(0x11,ul_msginfo)
+#define UL_TAILMSG UL_IOW(0x12,ul_msginfo)
+#define UL_FREEMSG UL_IO(0x13)
+#define UL_ACCEPTMSG UL_IOR(0x14,ul_msginfo)
+#define UL_ACTAILMSG UL_IOR(0x15,ul_msginfo)
+#define UL_ADDFILT UL_IOW(0x16,ul_msginfo)
+#define UL_ABORTMSG UL_IO(0x17)
+#define UL_REWMSG UL_IO(0x18)
+#define UL_INEPOLL UL_IO(0x19)
+#define UL_WAITREC UL_IO(0x1A)
+#define UL_SETMYADR UL_IO(0x1B) /* arg = new station address */
+#define UL_SETIDSTR UL_IO(0x1C) /* arg = "C" string */
+#define UL_SETBAUDRATE UL_IO(0x1D) /* arg = new baudrate */
+#define UL_KLOGBLL UL_IO(0x41)
+#define UL_STROKE UL_IO(0x42)
+#define UL_DEBFLG UL_IO(0x43) /* arg = new debug mask */
+#define UL_HWTEST UL_IO(0x44) /* arg = test subcommand */
+
+typedef struct ul_msginfo {
+ int dadr; /* destignation address */
+ int sadr; /* source address */
+ int cmd; /* command/socket number */
+ int flg; /* message flags */
+ int len; /* length of frame */
+ unsigned stamp; /* unigue message number */
+} ul_msginfo;
+
+/*******************************************************************/
+/* command definitions */
+
+/* standard command codes
+ 00H .. 3FH store to buffer
+ 40H .. 7FH store to buffer without ACK
+ 80H .. 9FH proccess at onece
+ A0H .. BFH process with additional receive
+ C0H .. FFH process with additional send
+*/
+
+#define UL_CMD_RES 0x80 /* Reinitialize RS485 or connected module */
+#define UL_CMD_SFT 0x81 /* Test free space in input buffer */
+#define UL_CMD_SID 0xF0 /* Send identification */
+#define UL_CMD_SFI 0xF1 /* Send amount of free space in IB */
+#define UL_CMD_TF0 0x98 /* End of stepping */
+#define UL_CMD_TF1 0x99 /* Begin of stepping */
+#define UL_CMD_STP 0x9A /* Do step */
+#define UL_CMD_DEB 0x9B /* Additional debug commands */
+#define UL_CMD_SPC 0xDA /* Send state - for 8051 PCL PCH PSW ACC */
+
+#define UL_CMD_RDM 0xF8 /* Read memory T T B B L L */
+#define UL_CMD_WRM 0xB8 /* Write mamory T T B B L L */
+#define UL_CMD_ERM 0x88 /* Erase memory T T B B L L */
+
+#ifdef __cplusplus
+} /* extern "C"*/
+#endif
+
+#endif /* _UL_DRVDEF_H */
+
+
--- /dev/null
+#ifndef _UL_FD_H
+#define _UL_FD_H
+
+/* The applications calls directly functions based above uLan driver API */
+
+#include <ul_lib/ul_fddir.h>
+
+#undef WITH_UL_FD_INDIRECT
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef ul_fd_direct_t ul_fd_t;
+#define UL_FD_INVALID UL_FD_DIRECT_INVALID
+
+static inline ul_fd_direct_t ul_fd2sys_fd(ul_fd_t fd)
+{
+ return fd;
+}
+
+#ifdef __cplusplus
+} /* extern "C"*/
+#endif
+
+#endif /*_UL_FD_H*/
--- /dev/null
+#ifndef _UL_FDDIR_H
+#define _UL_FDDIR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef _WIN32
+
+ #define UL_DEV_NAME "\\\\.\\UL_DRV"
+
+ typedef HANDLE ul_fd_direct_t;
+
+ #define UL_FD_DIRECT_INVALID INVALID_HANDLE_VALUE
+ typedef long ssize_t;
+
+ #define WITHOUT_SYS_SELECT
+ #define HAS_GETOPT_LONG
+
+ #ifdef WITH_UL_FD_INDIRECT
+ #define WIN32_FILE_OVERLAPPED
+ #endif /* WITH_UL_FD_INDIRECT */
+
+ #if defined(WIN32_FILE_OVERLAPPED)&&!defined(WITH_UL_FD_INDIRECT)
+ #error to enable WIN32_FILE_OVERLAPPED operation is neccessary compile sources with flag WITH_UL_FD_INDIRECT
+ #endif
+
+#elif defined(__DJGPP__) || defined(CONFIG_OC_UL_DRV_SYSLESS) || defined(CONFIG_OC_UL_DRV_USLIB)
+
+ #ifdef(__DJGPP__)
+ #define UL_DEV_NAME "1"
+ #else /* !__DJGPP__ */
+ #define UL_DEV_NAME "/dev/ulan"
+ #endif /* !__DJGPP__ */
+
+ struct ul_opdata;
+ typedef struct ul_opdata *ul_fd_direct_t;
+ #define UL_FD_DIRECT_INVALID (NULL)
+
+ #define WITHOUT_SYS_SELECT
+ #define UL_DRV_IN_LIB
+
+#else /* !_WIN32 && !__DJGPP__ */
+
+ #define UL_DEV_NAME "/dev/ulan"
+
+ typedef int ul_fd_direct_t;
+
+ #define UL_FD_DIRECT_INVALID (-1)
+
+ #define HAS_GETDELIM
+ #define HAS_GETOPT_LONG
+
+#endif /* _WIN32 */
+
+#ifdef __cplusplus
+} /* extern "C"*/
+#endif
+
+#endif /*_UL_FDDIR_H*/
--- /dev/null
+#ifndef _UL_L_LOG_H
+#define _UL_L_LOG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* debugging support routines */
+int uloi_debug_flg;
+
+#ifndef UL_LOGL_FATAL
+
+#define UL_LOGL_MASK (0xff)
+#define UL_LOGL_CONT (0x1000)
+
+#define UL_LOGL_FATAL 1
+#define UL_LOGL_ERR 2
+#define UL_LOGL_MSG 3
+#define UL_LOGL_INF 4
+#define UL_LOGL_DEB 5
+#define UL_LOGL_TRASH 6
+
+#endif /*UL_LOGL_FATAL*/
+
+struct ul_log_domain;
+
+typedef void (ul_log_fnc_t)(struct ul_log_domain *domain, int level,
+ const char *format, va_list ap);
+
+void ul_log(struct ul_log_domain *domain, int level,
+ const char *format, ...) UL_ATTR_PRINTF (3, 4);
+
+void ul_log_redir(ul_log_fnc_t *log_fnc, int add_flags);
+
+#ifdef __cplusplus
+} /* extern "C"*/
+#endif
+
+#endif /* _UL_L_LOG_H */
+
--- /dev/null
+/* Automatically generated from */
+/* config files: config.omk-default */
+#ifndef _ul_lib_config_H
+#define _ul_lib_config_H
+#endif /* _ul_lib_config_H */
--- /dev/null
+#ifndef _ULAN_H
+#define _ULAN_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdarg.h>
+#include <sys/types.h>
+#include <ul_lib/ul_drvdef.h>
+#include <ul_lib/ul_fd.h>
+
+/* GNUC neat features */
+
+#ifdef __GNUC__
+#ifndef UL_ATTR_UNUSED
+#define UL_ATTR_PRINTF( format_idx, arg_idx ) \
+ __attribute__((format (printf, format_idx, arg_idx)))
+#define UL_ATTR_SCANF( format_idx, arg_idx ) \
+ __attribute__((format (scanf, format_idx, arg_idx)))
+#define UL_ATTR_FORMAT( arg_idx ) \
+ __attribute__((format_arg (arg_idx)))
+#define UL_ATTR_NORETURN \
+ __attribute__((noreturn))
+#define UL_ATTR_CONST \
+ __attribute__((const))
+#define UL_ATTR_UNUSED \
+ __attribute__((unused))
+#endif /*UL_ATTR_UNUSED*/
+#else /* !__GNUC__ */
+#ifndef UL_ATTR_UNUSED
+#define UL_ATTR_PRINTF( format_idx, arg_idx )
+#define UL_ATTR_SCANF( format_idx, arg_idx )
+#define UL_ATTR_FORMAT( arg_idx )
+#define UL_ATTR_NORETURN
+#define UL_ATTR_CONST
+#define UL_ATTR_UNUSED
+#endif /*UL_ATTR_UNUSED*/
+#endif /* !__GNUC__ */
+
+/* driver interface */
+
+ul_fd_t ul_open(const char *dev_name, const char *options);
+int ul_close(ul_fd_t ul_fd);
+int ul_drv_version(ul_fd_t ul_fd);
+ssize_t ul_read(ul_fd_t ul_fd, void *buffer, size_t size);
+ssize_t ul_write(ul_fd_t ul_fd, const void *buffer, size_t size);
+int ul_newmsg(ul_fd_t ul_fd,const ul_msginfo *msginfo);
+int ul_tailmsg(ul_fd_t ul_fd,const ul_msginfo *msginfo);
+int ul_freemsg(ul_fd_t ul_fd);
+int ul_acceptmsg(ul_fd_t ul_fd,ul_msginfo *msginfo);
+int ul_actailmsg(ul_fd_t ul_fd,ul_msginfo *msginfo);
+int ul_addfilt(ul_fd_t ul_fd,const ul_msginfo *msginfo);
+int ul_abortmsg(ul_fd_t ul_fd);
+int ul_rewmsg(ul_fd_t ul_fd);
+int ul_inepoll(ul_fd_t ul_fd);
+int ul_drv_debflg(ul_fd_t ul_fd,int debug_msk);
+int ul_fd_wait(ul_fd_t ul_fd, int wait_sec);
+int ul_setmyadr(ul_fd_t ul_fd, int newadr);
+int ul_setidstr(ul_fd_t ul_fd, const char *idstr);
+int ul_setbaudrate(ul_fd_t ul_fd, int baudrate);
+int ul_stroke(ul_fd_t ul_fd);
+
+/* simple message operations */
+
+int ul_send_command(ul_fd_t ul_fd,int dadr,int cmd,int flg,
+ const void *buf,int len);
+int ul_send_command_wait(ul_fd_t ul_fd,int dadr,int cmd,int flg,
+ const void *buf,int len);
+int ul_send_query(ul_fd_t ul_fd,int dadr,int cmd,int flg,
+ const void *buf,int len);
+int ul_send_query_wait(ul_fd_t ul_fd,int dadr,int cmd,int flg,
+ const void *bufin,int lenin,void **bufout,int *lenout);
+
+/* basic uLan commands/services */
+
+#define UL_CMD_OISV 0x10 /* Object Interface Service */
+#define UL_CMD_LCDABS 0x4f /* Absorbance data block */
+#define UL_CMD_LCDMRK 0x4e /* Mark */
+#define UL_CMD_NCS 0x7f /* Network Control Service */
+#define UL_CMD_GST 0xc1 /* Fast module get status */
+#define UL_CMD_PDO 0xc2 /* Asynchronous service */
+
+/* definitions of basic uLan OI commands */
+
+#define ULOI_AOID 10 /* name is defined in ASCII for DOIx */
+#define ULOI_DOII 12 /* description of input objects */
+#define ULOI_DOIO 14 /* description of output objects */
+#define ULOI_QOII 16 /* ID numbers of recognized input objects */
+#define ULOI_QOIO 18 /* ID numbers of recognized output objects */
+#define ULOI_RDRQ 20 /* object values read request */
+#define ULOI_STATUS 30 /* read instrument status */
+#define ULOI_ERRCLR 31 /* clear error status */
+
+typedef struct uloi_coninfo_t {
+ int adr; /* address of target module */
+ int cmd; /* service/cmd number for uLOI on target */
+ int bcmd; /* service/cmd number for returned messages */
+ int sn; /* sequence counter */
+ int bsn; /* sequence counter of target module */
+ int outflg; /* flags used for outgoing messages */
+ ul_fd_t ul_fd;/* handle for ul_drv */
+ ul_fd_t ul_fd1;/* the auxiliary handle for ULOI direct reply */
+ int timeout; /* timeout */
+ int error; /* error condition occurred */
+ int state; /* internal state */
+} uloi_coninfo_t;
+
+/* definitions of basic uLan OI functions */
+
+uloi_coninfo_t* uloi_open(char *ul_dev_name,int adr,int cmd,
+ int bcmd, int timeout);
+void uloi_close(uloi_coninfo_t *coninfo);
+int uloi_transfer(uloi_coninfo_t *coninfo,
+ uchar *bufin,int lenin,uchar **bufout,int *lenout);
+int uloi_set_var(uloi_coninfo_t *coninfo,int oid, void *val, int size);
+int uloi_get_var(uloi_coninfo_t *coninfo,int oid, void *val, int size);
+int uloi_set_var_u2(uloi_coninfo_t *coninfo,int oid,unsigned val);
+int uloi_get_var_u2(uloi_coninfo_t *coninfo,int oid,unsigned *val);
+int uloi_send_cmd(uloi_coninfo_t *coninfo,int oid);
+int uloi_get_oids(uloi_coninfo_t *coninfo,int list,int **oids_list);
+int uloi_get_oiddes(uloi_coninfo_t *coninfo,int list, int oid, uchar **poiddespack);
+int uloi_get_aoiddes(uloi_coninfo_t *coninfo,int list,char *aoid, uchar **poiddespack);
+uchar *uloi_oiddespack_getloc(uchar *despack, int strindex);
+char *uloi_oiddespack_strdup(uchar *despack, int strindex);
+
+/* UL_CMD_NCS Network Control Service */
+
+#define ULNCS_ADR_RQ 0xC0 /* SN0 SN1 SN2 SN3 */
+#define ULNCS_SET_ADDR 0xC1 /* SN0 SN1 SN2 SN3 NEW_ADR */
+#define ULNCS_SID_RQ 0xC2 /* send serial num and ID string request */
+#define ULNCS_SID_RPLY 0xC3 /* SN0 SN1 SN2 SN3 ID ... */
+#define ULNCS_ADDR_NVSV 0xC4 /* SN0 SN1 SN2 SN3 - save addres to EEPROM */
+#define ULNCS_BOOT_ACT 0xC5 /* SN0 SN1 SN2 SN3 */
+#define ULNCS_BOOT_ACK 0xC6 /* SN0 SN1 SN2 SN3 */
+#define ULNCS_SET_SN 0xE0 /* SN0 SN1 SN2 SN3 */
+
+/* UL_CMD_RES Reinitialize RS485 or connected module */
+
+#define ULRES_LINK 0x10
+#define ULRES_BAUD 0x12
+#define ULRES_CPU 0x21 /* password - default 0x55 0xAA */
+
+#if 0
+ #define read error_to_use_read
+ #define write error_to_use_write
+ #define open error_to_use_open
+ #define close error_to_use_close
+ #define ioctl error_to_use_ioctl
+#endif
+
+#ifdef __cplusplus
+} /* extern "C"*/
+#endif
+
+#endif /* _ULAN_H */
+
--- /dev/null
+/*******************************************************************
+ uLan Communication - C interface library
+
+ ul_netbase.c - basic network and module constructions
+
+ (C) Copyright 2001 by Pavel Pisa - Originator
+
+ (C) Copyright 2002-2004 by Pavel Pisa - Originator
+
+ The uLan C interface library can be used, copied and modified
+ under next licenses
+ - GPL - GNU General Public License
+ - LGPL - GNU Lesser General Public License
+ - MPL - Mozilla Public License
+ - and other licenses added by project originators
+ Code can be modified and re-distributed under any combination
+ of the above listed licenses. If contributor does not agree with
+ some of the licenses, he/she can delete appropriate line.
+ Warning, if you delete all lines, you are not allowed to
+ distribute source code and/or binaries utilizing code.
+
+ See files COPYING and README for details.
+
+ *******************************************************************/
+
+#ifndef _UL_MSG_BUF_H
+#define _UL_MSG_BUF_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <ul_lib/ulan.h>
+#include <ul_dbuff.h>
+
+
+typedef struct ul_msg_buf{ /* buffer to hold full message taken from driver */
+ ul_msginfo msginfo; /* dadr, sadr, cmd, flg, len, stamp */
+ ul_dbuff_t data; /* message data */
+ struct ul_msg_buf *tail; /* optional tail message */
+} ul_msg_buf_t;
+
+
+int ul_msg_buf_init(ul_msg_buf_t *buf);
+void ul_msg_buf_destroy(ul_msg_buf_t *buf);
+int ul_msg_buf_rd_data(ul_msg_buf_t *buf, ul_fd_t ul_fd);
+int ul_msg_buf_rd_rest(ul_msg_buf_t *buf, ul_fd_t ul_fd);
+int ul_msg_buf_wr(ul_msg_buf_t *buf, ul_fd_t ul_fd);
+
+#ifdef __cplusplus
+} /* extern "C"*/
+#endif
+
+#endif /* _UL_MSG_BUF_H */
--- /dev/null
+# Debian lighttpd configuration file
+#
+
+############ Options you really have to take care of ####################
+
+## modules to load
+# mod_access, mod_accesslog and mod_alias are loaded by default
+# all other module should only be loaded if neccesary
+# - saves some time
+# - saves memory
+
+server.modules = (
+ "mod_access",
+ "mod_alias",
+ "mod_accesslog",
+ "mod_compress",
+# "mod_fastcgi",
+# "mod_rewrite",
+# "mod_redirect",
+# "mod_evhost",
+# "mod_usertrack",
+# "mod_rrdtool",
+# "mod_webdav",
+# "mod_expire",
+# "mod_flv_streaming",
+# "mod_evasive"
+)
+
+## a static document-root, for virtual-hosting take look at the
+## server.virtual-* options
+server.document-root = "/var/www/"
+
+## where to upload files to, purged daily.
+server.upload-dirs = ( "/var/cache/lighttpd/uploads" )
+
+## where to send error-messages to
+server.errorlog = "/var/log/lighttpd/error.log"
+
+## files to check for if .../ is requested
+index-file.names = ( "index.php", "index.html",
+ "index.htm", "default.htm",
+ "index.lighttpd.html" )
+
+
+## Use the "Content-Type" extended attribute to obtain mime type if possible
+# mimetype.use-xattr = "enable"
+
+#### accesslog module
+accesslog.filename = "/var/log/lighttpd/access.log"
+
+## deny access the file-extensions
+#
+# ~ is for backupfiles from vi, emacs, joe, ...
+# .inc is often used for code includes which should in general not be part
+# of the document-root
+url.access-deny = ( "~", ".inc" )
+
+##
+# which extensions should not be handle via static-file transfer
+#
+# .php, .pl, .fcgi are most often handled by mod_fastcgi or mod_cgi
+static-file.exclude-extensions = ( ".php", ".pl", ".fcgi" )
+
+
+######### Options that are good to be but not neccesary to be changed #######
+
+## Use ipv6 only if available.
+include_shell "/usr/share/lighttpd/use-ipv6.pl"
+
+## bind to port (default: 80)
+server.port = 81
+
+## bind to localhost only (default: all interfaces)
+## server.bind = "localhost"
+
+## error-handler for status 404
+#server.error-handler-404 = "/error-handler.html"
+#server.error-handler-404 = "/error-handler.php"
+
+## to help the rc.scripts
+server.pid-file = "/var/run/lighttpd.pid"
+
+##
+## Format: <errorfile-prefix><status>.html
+## -> ..../status-404.html for 'File not found'
+#server.errorfile-prefix = "/var/www/"
+
+## virtual directory listings
+dir-listing.encoding = "utf-8"
+server.dir-listing = "enable"
+
+## send unhandled HTTP-header headers to error-log
+#debug.dump-unknown-headers = "enable"
+
+### only root can use these options
+#
+# chroot() to directory (default: no chroot() )
+#server.chroot = "/"
+
+## change uid to <uid> (default: don't care)
+server.username = "www-data"
+
+## change uid to <uid> (default: don't care)
+server.groupname = "www-data"
+
+#### compress module
+compress.cache-dir = "/var/cache/lighttpd/compress/"
+compress.filetype = ("text/plain", "text/html", "application/x-javascript", "text/css")
+
+
+#### url handling modules (rewrite, redirect, access)
+# url.rewrite = ( "^/$" => "/server-status" )
+# url.redirect = ( "^/wishlist/(.+)" => "http://www.123.org/$1" )
+
+#
+# define a pattern for the host url finding
+# %% => % sign
+# %0 => domain name + tld
+# %1 => tld
+# %2 => domain name without tld
+# %3 => subdomain 1 name
+# %4 => subdomain 2 name
+#
+# evhost.path-pattern = "/home/storage/dev/www/%3/htdocs/"
+
+#### expire module
+# expire.url = ( "/buggy/" => "access 2 hours", "/asdhas/" => "access plus 1 seconds 2 minutes")
+
+#### rrdtool
+# rrdtool.binary = "/usr/bin/rrdtool"
+# rrdtool.db-name = "/var/www/lighttpd.rrd"
+
+
+#### variable usage:
+## variable name without "." is auto prefixed by "var." and becomes "var.bar"
+#bar = 1
+#var.mystring = "foo"
+
+## integer add
+#bar += 1
+## string concat, with integer cast as string, result: "www.foo1.com"
+#server.name = "www." + mystring + var.bar + ".com"
+## array merge
+#index-file.names = (foo + ".php") + index-file.names
+#index-file.names += (foo + ".php")
+
+
+#### external configuration files
+## mimetype mapping
+include_shell "/usr/share/lighttpd/create-mime.assign.pl"
+
+## load enabled configuration files,
+## read /etc/lighttpd/conf-available/README first
+include_shell "/usr/share/lighttpd/include-conf-enabled.pl"
+
+#### handle Debian Policy Manual, Section 11.5. urls
+## by default allow them only from localhost
+## (This must come last due to #445459)
+## Note: =~ "127.0.0.1" works with ipv6 enabled, whereas == "127.0.0.1" doesn't
+$HTTP["remoteip"] =~ "127.0.0.1" {
+ alias.url += (
+ "/doc/" => "/usr/share/doc/",
+ "/images/" => "/usr/share/images/"
+ )
+ $HTTP["url"] =~ "^/doc/|^/images/" {
+ dir-listing.activate = "enable"
+ }
+}
+
+$HTTP["host"] == "hydroponie" {
+ server.server-root = "/var/www"
+ server.document-root = "/"
+
+ fastcgi.server = ( "/scripts/" =>
+ (( "bin-path" => "/home/bohacekm/fel/X36BAP/hydroweb/src/hydroponie",
+ "socket" => "/tmp/hydro.socket",
+ "max-procs" => 1,
+ "check-local" => "disable",
+ "docroot" => "/scripts/" # remote server may use
+ # it's own docroot
+ ))
+ )
+}
+
+
+#$HTTP["host"] == "threads" {
+# server.server-root = "/var/www"
+# server.document-root = "/"
+#
+# fastcgi.server = ( "/" =>
+# (( "bin-path" => "/home/bohacekm/src/qt_lighttpd_test/fcgi_testapp",
+# "socket" => "/tmp/fcgi_testapp.socket",
+# "max-procs" => 10,
+# "check-local" => "disable",
+# "docroot" => "/" # remote server may use
+# # it's own docroot
+# ))
+# )
+#}
+
+
--- /dev/null
+/*
+ * jQuery 1.2.1 - New Wave Javascript
+ *
+ * Copyright (c) 2007 John Resig (jquery.com)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * $Date: 2007-09-16 23:42:06 -0400 (Sun, 16 Sep 2007) $
+ * $Rev: 3353 $
+ */
+eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(G(){9(1m E!="W")H w=E;H E=18.15=G(a,b){I 6 7u E?6.5N(a,b):1u E(a,b)};9(1m $!="W")H D=$;18.$=E;H u=/^[^<]*(<(.|\\s)+>)[^>]*$|^#(\\w+)$/;E.1b=E.3A={5N:G(c,a){c=c||U;9(1m c=="1M"){H m=u.2S(c);9(m&&(m[1]||!a)){9(m[1])c=E.4D([m[1]],a);J{H b=U.3S(m[3]);9(b)9(b.22!=m[3])I E().1Y(c);J{6[0]=b;6.K=1;I 6}J c=[]}}J I 1u E(a).1Y(c)}J 9(E.1n(c))I 1u E(U)[E.1b.2d?"2d":"39"](c);I 6.6v(c.1c==1B&&c||(c.4c||c.K&&c!=18&&!c.1y&&c[0]!=W&&c[0].1y)&&E.2h(c)||[c])},4c:"1.2.1",7Y:G(){I 6.K},K:0,21:G(a){I a==W?E.2h(6):6[a]},2o:G(a){H b=E(a);b.4Y=6;I b},6v:G(a){6.K=0;1B.3A.1a.16(6,a);I 6},N:G(a,b){I E.N(6,a,b)},4I:G(a){H b=-1;6.N(G(i){9(6==a)b=i});I b},1x:G(f,d,e){H c=f;9(f.1c==3X)9(d==W)I 6.K&&E[e||"1x"](6[0],f)||W;J{c={};c[f]=d}I 6.N(G(a){L(H b 1i c)E.1x(e?6.R:6,b,E.1e(6,c[b],e,a,b))})},17:G(b,a){I 6.1x(b,a,"3C")},2g:G(e){9(1m e!="5i"&&e!=S)I 6.4n().3g(U.6F(e));H t="";E.N(e||6,G(){E.N(6.3j,G(){9(6.1y!=8)t+=6.1y!=1?6.6x:E.1b.2g([6])})});I t},5m:G(b){9(6[0])E(b,6[0].3H).6u().3d(6[0]).1X(G(){H a=6;1W(a.1w)a=a.1w;I a}).3g(6);I 6},8m:G(a){I 6.N(G(){E(6).6q().5m(a)})},8d:G(a){I 6.N(G(){E(6).5m(a)})},3g:G(){I 6.3z(1q,Q,1,G(a){6.58(a)})},6j:G(){I 6.3z(1q,Q,-1,G(a){6.3d(a,6.1w)})},6g:G(){I 6.3z(1q,P,1,G(a){6.12.3d(a,6)})},50:G(){I 6.3z(1q,P,-1,G(a){6.12.3d(a,6.2q)})},2D:G(){I 6.4Y||E([])},1Y:G(t){H b=E.1X(6,G(a){I E.1Y(t,a)});I 6.2o(/[^+>] [^+>]/.14(t)||t.1g("..")>-1?E.4V(b):b)},6u:G(e){H f=6.1X(G(){I 6.67?E(6.67)[0]:6.4R(Q)});H d=f.1Y("*").4O().N(G(){9(6[F]!=W)6[F]=S});9(e===Q)6.1Y("*").4O().N(G(i){H c=E.M(6,"2P");L(H a 1i c)L(H b 1i c[a])E.1j.1f(d[i],a,c[a][b],c[a][b].M)});I f},1E:G(t){I 6.2o(E.1n(t)&&E.2W(6,G(b,a){I t.16(b,[a])})||E.3m(t,6))},5V:G(t){I 6.2o(t.1c==3X&&E.3m(t,6,Q)||E.2W(6,G(a){I(t.1c==1B||t.4c)?E.2A(a,t)<0:a!=t}))},1f:G(t){I 6.2o(E.1R(6.21(),t.1c==3X?E(t).21():t.K!=W&&(!t.11||E.11(t,"2Y"))?t:[t]))},3t:G(a){I a?E.3m(a,6).K>0:P},7c:G(a){I 6.3t("."+a)},3i:G(b){9(b==W){9(6.K){H c=6[0];9(E.11(c,"24")){H e=c.4Z,a=[],Y=c.Y,2G=c.O=="24-2G";9(e<0)I S;L(H i=2G?e:0,33=2G?e+1:Y.K;i<33;i++){H d=Y[i];9(d.26){H b=E.V.1h&&!d.9V["1Q"].9L?d.2g:d.1Q;9(2G)I b;a.1a(b)}}I a}J I 6[0].1Q.1p(/\\r/g,"")}}J I 6.N(G(){9(b.1c==1B&&/4k|5j/.14(6.O))6.2Q=(E.2A(6.1Q,b)>=0||E.2A(6.2H,b)>=0);J 9(E.11(6,"24")){H a=b.1c==1B?b:[b];E("9h",6).N(G(){6.26=(E.2A(6.1Q,a)>=0||E.2A(6.2g,a)>=0)});9(!a.K)6.4Z=-1}J 6.1Q=b})},4o:G(a){I a==W?(6.K?6[0].3O:S):6.4n().3g(a)},6H:G(a){I 6.50(a).28()},6E:G(i){I 6.2J(i,i+1)},2J:G(){I 6.2o(1B.3A.2J.16(6,1q))},1X:G(b){I 6.2o(E.1X(6,G(a,i){I b.2O(a,i,a)}))},4O:G(){I 6.1f(6.4Y)},3z:G(f,d,g,e){H c=6.K>1,a;I 6.N(G(){9(!a){a=E.4D(f,6.3H);9(g<0)a.8U()}H b=6;9(d&&E.11(6,"1I")&&E.11(a[0],"4m"))b=6.4l("1K")[0]||6.58(U.5B("1K"));E.N(a,G(){H a=c?6.4R(Q):6;9(!5A(0,a))e.2O(b,a)})})}};G 5A(i,b){H a=E.11(b,"1J");9(a){9(b.3k)E.3G({1d:b.3k,3e:P,1V:"1J"});J E.5f(b.2g||b.6s||b.3O||"");9(b.12)b.12.3b(b)}J 9(b.1y==1)E("1J",b).N(5A);I a}E.1k=E.1b.1k=G(){H c=1q[0]||{},a=1,2c=1q.K,5e=P;9(c.1c==8o){5e=c;c=1q[1]||{}}9(2c==1){c=6;a=0}H b;L(;a<2c;a++)9((b=1q[a])!=S)L(H i 1i b){9(c==b[i])6r;9(5e&&1m b[i]==\'5i\'&&c[i])E.1k(c[i],b[i]);J 9(b[i]!=W)c[i]=b[i]}I c};H F="15"+(1u 3D()).3B(),6p=0,5c={};E.1k({8a:G(a){18.$=D;9(a)18.15=w;I E},1n:G(a){I!!a&&1m a!="1M"&&!a.11&&a.1c!=1B&&/G/i.14(a+"")},4a:G(a){I a.2V&&!a.1G||a.37&&a.3H&&!a.3H.1G},5f:G(a){a=E.36(a);9(a){9(18.6l)18.6l(a);J 9(E.V.1N)18.56(a,0);J 3w.2O(18,a)}},11:G(b,a){I b.11&&b.11.27()==a.27()},1L:{},M:G(c,d,b){c=c==18?5c:c;H a=c[F];9(!a)a=c[F]=++6p;9(d&&!E.1L[a])E.1L[a]={};9(b!=W)E.1L[a][d]=b;I d?E.1L[a][d]:a},30:G(c,b){c=c==18?5c:c;H a=c[F];9(b){9(E.1L[a]){2E E.1L[a][b];b="";L(b 1i E.1L[a])1T;9(!b)E.30(c)}}J{2a{2E c[F]}29(e){9(c.53)c.53(F)}2E E.1L[a]}},N:G(a,b,c){9(c){9(a.K==W)L(H i 1i a)b.16(a[i],c);J L(H i=0,48=a.K;i<48;i++)9(b.16(a[i],c)===P)1T}J{9(a.K==W)L(H i 1i a)b.2O(a[i],i,a[i]);J L(H i=0,48=a.K,3i=a[0];i<48&&b.2O(3i,i,3i)!==P;3i=a[++i]){}}I a},1e:G(c,b,d,e,a){9(E.1n(b))b=b.2O(c,[e]);H f=/z-?4I|7T-?7Q|1r|69|7P-?1H/i;I b&&b.1c==4W&&d=="3C"&&!f.14(a)?b+"2T":b},1o:{1f:G(b,c){E.N((c||"").2l(/\\s+/),G(i,a){9(!E.1o.3K(b.1o,a))b.1o+=(b.1o?" ":"")+a})},28:G(b,c){b.1o=c!=W?E.2W(b.1o.2l(/\\s+/),G(a){I!E.1o.3K(c,a)}).66(" "):""},3K:G(t,c){I E.2A(c,(t.1o||t).3s().2l(/\\s+/))>-1}},2k:G(e,o,f){L(H i 1i o){e.R["3r"+i]=e.R[i];e.R[i]=o[i]}f.16(e,[]);L(H i 1i o)e.R[i]=e.R["3r"+i]},17:G(e,p){9(p=="1H"||p=="2N"){H b={},42,41,d=["7J","7I","7G","7F"];E.N(d,G(){b["7C"+6]=0;b["7B"+6+"5Z"]=0});E.2k(e,b,G(){9(E(e).3t(\':3R\')){42=e.7A;41=e.7w}J{e=E(e.4R(Q)).1Y(":4k").5W("2Q").2D().17({4C:"1P",2X:"4F",19:"2Z",7o:"0",1S:"0"}).5R(e.12)[0];H a=E.17(e.12,"2X")||"3V";9(a=="3V")e.12.R.2X="7g";42=e.7e;41=e.7b;9(a=="3V")e.12.R.2X="3V";e.12.3b(e)}});I p=="1H"?42:41}I E.3C(e,p)},3C:G(h,j,i){H g,2w=[],2k=[];G 3n(a){9(!E.V.1N)I P;H b=U.3o.3Z(a,S);I!b||b.4y("3n")==""}9(j=="1r"&&E.V.1h){g=E.1x(h.R,"1r");I g==""?"1":g}9(j.1t(/4u/i))j=y;9(!i&&h.R[j])g=h.R[j];J 9(U.3o&&U.3o.3Z){9(j.1t(/4u/i))j="4u";j=j.1p(/([A-Z])/g,"-$1").2p();H d=U.3o.3Z(h,S);9(d&&!3n(h))g=d.4y(j);J{L(H a=h;a&&3n(a);a=a.12)2w.4w(a);L(a=0;a<2w.K;a++)9(3n(2w[a])){2k[a]=2w[a].R.19;2w[a].R.19="2Z"}g=j=="19"&&2k[2w.K-1]!=S?"2s":U.3o.3Z(h,S).4y(j)||"";L(a=0;a<2k.K;a++)9(2k[a]!=S)2w[a].R.19=2k[a]}9(j=="1r"&&g=="")g="1"}J 9(h.3Q){H f=j.1p(/\\-(\\w)/g,G(m,c){I c.27()});g=h.3Q[j]||h.3Q[f];9(!/^\\d+(2T)?$/i.14(g)&&/^\\d/.14(g)){H k=h.R.1S;H e=h.4v.1S;h.4v.1S=h.3Q.1S;h.R.1S=g||0;g=h.R.71+"2T";h.R.1S=k;h.4v.1S=e}}I g},4D:G(a,e){H r=[];e=e||U;E.N(a,G(i,d){9(!d)I;9(d.1c==4W)d=d.3s();9(1m d=="1M"){d=d.1p(/(<(\\w+)[^>]*?)\\/>/g,G(m,a,b){I b.1t(/^(70|6Z|6Y|9Q|4t|9N|9K|3a|9G|9E)$/i)?m:a+"></"+b+">"});H s=E.36(d).2p(),1s=e.5B("1s"),2x=[];H c=!s.1g("<9y")&&[1,"<24>","</24>"]||!s.1g("<9w")&&[1,"<6T>","</6T>"]||s.1t(/^<(9u|1K|9t|9r|9p)/)&&[1,"<1I>","</1I>"]||!s.1g("<4m")&&[2,"<1I><1K>","</1K></1I>"]||(!s.1g("<9m")||!s.1g("<9k"))&&[3,"<1I><1K><4m>","</4m></1K></1I>"]||!s.1g("<6Y")&&[2,"<1I><1K></1K><6L>","</6L></1I>"]||E.V.1h&&[1,"1s<1s>","</1s>"]||[0,"",""];1s.3O=c[1]+d+c[2];1W(c[0]--)1s=1s.5p;9(E.V.1h){9(!s.1g("<1I")&&s.1g("<1K")<0)2x=1s.1w&&1s.1w.3j;J 9(c[1]=="<1I>"&&s.1g("<1K")<0)2x=1s.3j;L(H n=2x.K-1;n>=0;--n)9(E.11(2x[n],"1K")&&!2x[n].3j.K)2x[n].12.3b(2x[n]);9(/^\\s/.14(d))1s.3d(e.6F(d.1t(/^\\s*/)[0]),1s.1w)}d=E.2h(1s.3j)}9(0===d.K&&(!E.11(d,"2Y")&&!E.11(d,"24")))I;9(d[0]==W||E.11(d,"2Y")||d.Y)r.1a(d);J r=E.1R(r,d)});I r},1x:G(c,d,a){H e=E.4a(c)?{}:E.5o;9(d=="26"&&E.V.1N)c.12.4Z;9(e[d]){9(a!=W)c[e[d]]=a;I c[e[d]]}J 9(E.V.1h&&d=="R")I E.1x(c.R,"9e",a);J 9(a==W&&E.V.1h&&E.11(c,"2Y")&&(d=="9d"||d=="9a"))I c.97(d).6x;J 9(c.37){9(a!=W){9(d=="O"&&E.11(c,"4t")&&c.12)6G"O 94 93\'t 92 91";c.90(d,a)}9(E.V.1h&&/6C|3k/.14(d)&&!E.4a(c))I c.4p(d,2);I c.4p(d)}J{9(d=="1r"&&E.V.1h){9(a!=W){c.69=1;c.1E=(c.1E||"").1p(/6O\\([^)]*\\)/,"")+(3I(a).3s()=="8S"?"":"6O(1r="+a*6A+")")}I c.1E?(3I(c.1E.1t(/1r=([^)]*)/)[1])/6A).3s():""}d=d.1p(/-([a-z])/8Q,G(z,b){I b.27()});9(a!=W)c[d]=a;I c[d]}},36:G(t){I(t||"").1p(/^\\s+|\\s+$/g,"")},2h:G(a){H r=[];9(1m a!="8P")L(H i=0,2c=a.K;i<2c;i++)r.1a(a[i]);J r=a.2J(0);I r},2A:G(b,a){L(H i=0,2c=a.K;i<2c;i++)9(a[i]==b)I i;I-1},1R:G(a,b){9(E.V.1h){L(H i=0;b[i];i++)9(b[i].1y!=8)a.1a(b[i])}J L(H i=0;b[i];i++)a.1a(b[i]);I a},4V:G(b){H r=[],2f={};2a{L(H i=0,6y=b.K;i<6y;i++){H a=E.M(b[i]);9(!2f[a]){2f[a]=Q;r.1a(b[i])}}}29(e){r=b}I r},2W:G(b,a,c){9(1m a=="1M")a=3w("P||G(a,i){I "+a+"}");H d=[];L(H i=0,4g=b.K;i<4g;i++)9(!c&&a(b[i],i)||c&&!a(b[i],i))d.1a(b[i]);I d},1X:G(c,b){9(1m b=="1M")b=3w("P||G(a){I "+b+"}");H d=[];L(H i=0,4g=c.K;i<4g;i++){H a=b(c[i],i);9(a!==S&&a!=W){9(a.1c!=1B)a=[a];d=d.8M(a)}}I d}});H v=8K.8I.2p();E.V={4s:(v.1t(/.+(?:8F|8E|8C|8B)[\\/: ]([\\d.]+)/)||[])[1],1N:/6w/.14(v),34:/34/.14(v),1h:/1h/.14(v)&&!/34/.14(v),35:/35/.14(v)&&!/(8z|6w)/.14(v)};H y=E.V.1h?"4h":"5h";E.1k({5g:!E.V.1h||U.8y=="8x",4h:E.V.1h?"4h":"5h",5o:{"L":"8w","8v":"1o","4u":y,5h:y,4h:y,3O:"3O",1o:"1o",1Q:"1Q",3c:"3c",2Q:"2Q",8u:"8t",26:"26",8s:"8r"}});E.N({1D:"a.12",8q:"15.4e(a,\'12\')",8p:"15.2I(a,2,\'2q\')",8n:"15.2I(a,2,\'4d\')",8l:"15.4e(a,\'2q\')",8k:"15.4e(a,\'4d\')",8j:"15.5d(a.12.1w,a)",8i:"15.5d(a.1w)",6q:"15.11(a,\'8h\')?a.8f||a.8e.U:15.2h(a.3j)"},G(i,n){E.1b[i]=G(a){H b=E.1X(6,n);9(a&&1m a=="1M")b=E.3m(a,b);I 6.2o(E.4V(b))}});E.N({5R:"3g",8c:"6j",3d:"6g",8b:"50",89:"6H"},G(i,n){E.1b[i]=G(){H a=1q;I 6.N(G(){L(H j=0,2c=a.K;j<2c;j++)E(a[j])[n](6)})}});E.N({5W:G(a){E.1x(6,a,"");6.53(a)},88:G(c){E.1o.1f(6,c)},87:G(c){E.1o.28(6,c)},86:G(c){E.1o[E.1o.3K(6,c)?"28":"1f"](6,c)},28:G(a){9(!a||E.1E(a,[6]).r.K){E.30(6);6.12.3b(6)}},4n:G(){E("*",6).N(G(){E.30(6)});1W(6.1w)6.3b(6.1w)}},G(i,n){E.1b[i]=G(){I 6.N(n,1q)}});E.N(["85","5Z"],G(i,a){H n=a.2p();E.1b[n]=G(h){I 6[0]==18?E.V.1N&&3y["84"+a]||E.5g&&38.33(U.2V["5a"+a],U.1G["5a"+a])||U.1G["5a"+a]:6[0]==U?38.33(U.1G["6n"+a],U.1G["6m"+a]):h==W?(6.K?E.17(6[0],n):S):6.17(n,h.1c==3X?h:h+"2T")}});H C=E.V.1N&&3x(E.V.4s)<83?"(?:[\\\\w*57-]|\\\\\\\\.)":"(?:[\\\\w\\82-\\81*57-]|\\\\\\\\.)",6k=1u 47("^>\\\\s*("+C+"+)"),6i=1u 47("^("+C+"+)(#)("+C+"+)"),6h=1u 47("^([#.]?)("+C+"*)");E.1k({55:{"":"m[2]==\'*\'||15.11(a,m[2])","#":"a.4p(\'22\')==m[2]",":":{80:"i<m[3]-0",7Z:"i>m[3]-0",2I:"m[3]-0==i",6E:"m[3]-0==i",3v:"i==0",3u:"i==r.K-1",6f:"i%2==0",6e:"i%2","3v-46":"a.12.4l(\'*\')[0]==a","3u-46":"15.2I(a.12.5p,1,\'4d\')==a","7X-46":"!15.2I(a.12.5p,2,\'4d\')",1D:"a.1w",4n:"!a.1w",7W:"(a.6s||a.7V||15(a).2g()||\'\').1g(m[3])>=0",3R:\'"1P"!=a.O&&15.17(a,"19")!="2s"&&15.17(a,"4C")!="1P"\',1P:\'"1P"==a.O||15.17(a,"19")=="2s"||15.17(a,"4C")=="1P"\',7U:"!a.3c",3c:"a.3c",2Q:"a.2Q",26:"a.26||15.1x(a,\'26\')",2g:"\'2g\'==a.O",4k:"\'4k\'==a.O",5j:"\'5j\'==a.O",54:"\'54\'==a.O",52:"\'52\'==a.O",51:"\'51\'==a.O",6d:"\'6d\'==a.O",6c:"\'6c\'==a.O",2r:\'"2r"==a.O||15.11(a,"2r")\',4t:"/4t|24|6b|2r/i.14(a.11)",3K:"15.1Y(m[3],a).K",7S:"/h\\\\d/i.14(a.11)",7R:"15.2W(15.32,G(1b){I a==1b.T;}).K"}},6a:[/^(\\[) *@?([\\w-]+) *([!*$^~=]*) *(\'?"?)(.*?)\\4 *\\]/,/^(:)([\\w-]+)\\("?\'?(.*?(\\(.*?\\))?[^(]*?)"?\'?\\)/,1u 47("^([:.#]*)("+C+"+)")],3m:G(a,c,b){H d,2b=[];1W(a&&a!=d){d=a;H f=E.1E(a,c,b);a=f.t.1p(/^\\s*,\\s*/,"");2b=b?c=f.r:E.1R(2b,f.r)}I 2b},1Y:G(t,o){9(1m t!="1M")I[t];9(o&&!o.1y)o=S;o=o||U;H d=[o],2f=[],3u;1W(t&&3u!=t){H r=[];3u=t;t=E.36(t);H l=P;H g=6k;H m=g.2S(t);9(m){H p=m[1].27();L(H i=0;d[i];i++)L(H c=d[i].1w;c;c=c.2q)9(c.1y==1&&(p=="*"||c.11.27()==p.27()))r.1a(c);d=r;t=t.1p(g,"");9(t.1g(" ")==0)6r;l=Q}J{g=/^([>+~])\\s*(\\w*)/i;9((m=g.2S(t))!=S){r=[];H p=m[2],1R={};m=m[1];L(H j=0,31=d.K;j<31;j++){H n=m=="~"||m=="+"?d[j].2q:d[j].1w;L(;n;n=n.2q)9(n.1y==1){H h=E.M(n);9(m=="~"&&1R[h])1T;9(!p||n.11.27()==p.27()){9(m=="~")1R[h]=Q;r.1a(n)}9(m=="+")1T}}d=r;t=E.36(t.1p(g,""));l=Q}}9(t&&!l){9(!t.1g(",")){9(o==d[0])d.44();2f=E.1R(2f,d);r=d=[o];t=" "+t.68(1,t.K)}J{H k=6i;H m=k.2S(t);9(m){m=[0,m[2],m[3],m[1]]}J{k=6h;m=k.2S(t)}m[2]=m[2].1p(/\\\\/g,"");H f=d[d.K-1];9(m[1]=="#"&&f&&f.3S&&!E.4a(f)){H q=f.3S(m[2]);9((E.V.1h||E.V.34)&&q&&1m q.22=="1M"&&q.22!=m[2])q=E(\'[@22="\'+m[2]+\'"]\',f)[0];d=r=q&&(!m[3]||E.11(q,m[3]))?[q]:[]}J{L(H i=0;d[i];i++){H a=m[1]=="#"&&m[3]?m[3]:m[1]!=""||m[0]==""?"*":m[2];9(a=="*"&&d[i].11.2p()=="5i")a="3a";r=E.1R(r,d[i].4l(a))}9(m[1]==".")r=E.4X(r,m[2]);9(m[1]=="#"){H e=[];L(H i=0;r[i];i++)9(r[i].4p("22")==m[2]){e=[r[i]];1T}r=e}d=r}t=t.1p(k,"")}}9(t){H b=E.1E(t,r);d=r=b.r;t=E.36(b.t)}}9(t)d=[];9(d&&o==d[0])d.44();2f=E.1R(2f,d);I 2f},4X:G(r,m,a){m=" "+m+" ";H c=[];L(H i=0;r[i];i++){H b=(" "+r[i].1o+" ").1g(m)>=0;9(!a&&b||a&&!b)c.1a(r[i])}I c},1E:G(t,r,h){H d;1W(t&&t!=d){d=t;H p=E.6a,m;L(H i=0;p[i];i++){m=p[i].2S(t);9(m){t=t.7O(m[0].K);m[2]=m[2].1p(/\\\\/g,"");1T}}9(!m)1T;9(m[1]==":"&&m[2]=="5V")r=E.1E(m[3],r,Q).r;J 9(m[1]==".")r=E.4X(r,m[2],h);J 9(m[1]=="["){H g=[],O=m[3];L(H i=0,31=r.K;i<31;i++){H a=r[i],z=a[E.5o[m[2]]||m[2]];9(z==S||/6C|3k|26/.14(m[2]))z=E.1x(a,m[2])||\'\';9((O==""&&!!z||O=="="&&z==m[5]||O=="!="&&z!=m[5]||O=="^="&&z&&!z.1g(m[5])||O=="$="&&z.68(z.K-m[5].K)==m[5]||(O=="*="||O=="~=")&&z.1g(m[5])>=0)^h)g.1a(a)}r=g}J 9(m[1]==":"&&m[2]=="2I-46"){H e={},g=[],14=/(\\d*)n\\+?(\\d*)/.2S(m[3]=="6f"&&"2n"||m[3]=="6e"&&"2n+1"||!/\\D/.14(m[3])&&"n+"+m[3]||m[3]),3v=(14[1]||1)-0,d=14[2]-0;L(H i=0,31=r.K;i<31;i++){H j=r[i],12=j.12,22=E.M(12);9(!e[22]){H c=1;L(H n=12.1w;n;n=n.2q)9(n.1y==1)n.4U=c++;e[22]=Q}H b=P;9(3v==1){9(d==0||j.4U==d)b=Q}J 9((j.4U+d)%3v==0)b=Q;9(b^h)g.1a(j)}r=g}J{H f=E.55[m[1]];9(1m f!="1M")f=E.55[m[1]][m[2]];f=3w("P||G(a,i){I "+f+"}");r=E.2W(r,f,h)}}I{r:r,t:t}},4e:G(b,c){H d=[];H a=b[c];1W(a&&a!=U){9(a.1y==1)d.1a(a);a=a[c]}I d},2I:G(a,e,c,b){e=e||1;H d=0;L(;a;a=a[c])9(a.1y==1&&++d==e)1T;I a},5d:G(n,a){H r=[];L(;n;n=n.2q){9(n.1y==1&&(!a||n!=a))r.1a(n)}I r}});E.1j={1f:G(g,e,c,h){9(E.V.1h&&g.4j!=W)g=18;9(!c.2u)c.2u=6.2u++;9(h!=W){H d=c;c=G(){I d.16(6,1q)};c.M=h;c.2u=d.2u}H i=e.2l(".");e=i[0];c.O=i[1];H b=E.M(g,"2P")||E.M(g,"2P",{});H f=E.M(g,"2t",G(){H a;9(1m E=="W"||E.1j.4T)I a;a=E.1j.2t.16(g,1q);I a});H j=b[e];9(!j){j=b[e]={};9(g.4S)g.4S(e,f,P);J g.7N("43"+e,f)}j[c.2u]=c;6.1Z[e]=Q},2u:1,1Z:{},28:G(d,c,b){H e=E.M(d,"2P"),2L,4I;9(1m c=="1M"){H a=c.2l(".");c=a[0]}9(e){9(c&&c.O){b=c.4Q;c=c.O}9(!c){L(c 1i e)6.28(d,c)}J 9(e[c]){9(b)2E e[c][b.2u];J L(b 1i e[c])9(!a[1]||e[c][b].O==a[1])2E e[c][b];L(2L 1i e[c])1T;9(!2L){9(d.4P)d.4P(c,E.M(d,"2t"),P);J d.7M("43"+c,E.M(d,"2t"));2L=S;2E e[c]}}L(2L 1i e)1T;9(!2L){E.30(d,"2P");E.30(d,"2t")}}},1F:G(d,b,e,c,f){b=E.2h(b||[]);9(!e){9(6.1Z[d])E("*").1f([18,U]).1F(d,b)}J{H a,2L,1b=E.1n(e[d]||S),4N=!b[0]||!b[0].2M;9(4N)b.4w(6.4M({O:d,2m:e}));b[0].O=d;9(E.1n(E.M(e,"2t")))a=E.M(e,"2t").16(e,b);9(!1b&&e["43"+d]&&e["43"+d].16(e,b)===P)a=P;9(4N)b.44();9(f&&f.16(e,b)===P)a=P;9(1b&&c!==P&&a!==P&&!(E.11(e,\'a\')&&d=="4L")){6.4T=Q;e[d]()}6.4T=P}I a},2t:G(d){H a;d=E.1j.4M(d||18.1j||{});H b=d.O.2l(".");d.O=b[0];H c=E.M(6,"2P")&&E.M(6,"2P")[d.O],3q=1B.3A.2J.2O(1q,1);3q.4w(d);L(H j 1i c){3q[0].4Q=c[j];3q[0].M=c[j].M;9(!b[1]||c[j].O==b[1]){H e=c[j].16(6,3q);9(a!==P)a=e;9(e===P){d.2M();d.3p()}}}9(E.V.1h)d.2m=d.2M=d.3p=d.4Q=d.M=S;I a},4M:G(c){H a=c;c=E.1k({},a);c.2M=G(){9(a.2M)a.2M();a.7L=P};c.3p=G(){9(a.3p)a.3p();a.7K=Q};9(!c.2m&&c.65)c.2m=c.65;9(E.V.1N&&c.2m.1y==3)c.2m=a.2m.12;9(!c.4K&&c.4J)c.4K=c.4J==c.2m?c.7H:c.4J;9(c.64==S&&c.63!=S){H e=U.2V,b=U.1G;c.64=c.63+(e&&e.2R||b.2R||0);c.7E=c.7D+(e&&e.2B||b.2B||0)}9(!c.3Y&&(c.61||c.60))c.3Y=c.61||c.60;9(!c.5F&&c.5D)c.5F=c.5D;9(!c.3Y&&c.2r)c.3Y=(c.2r&1?1:(c.2r&2?3:(c.2r&4?2:0)));I c}};E.1b.1k({3W:G(c,a,b){I c=="5Y"?6.2G(c,a,b):6.N(G(){E.1j.1f(6,c,b||a,b&&a)})},2G:G(d,b,c){I 6.N(G(){E.1j.1f(6,d,G(a){E(6).5X(a);I(c||b).16(6,1q)},c&&b)})},5X:G(a,b){I 6.N(G(){E.1j.28(6,a,b)})},1F:G(c,a,b){I 6.N(G(){E.1j.1F(c,a,6,Q,b)})},7x:G(c,a,b){9(6[0])I E.1j.1F(c,a,6[0],P,b)},25:G(){H a=1q;I 6.4L(G(e){6.4H=0==6.4H?1:0;e.2M();I a[6.4H].16(6,[e])||P})},7v:G(f,g){G 4G(e){H p=e.4K;1W(p&&p!=6)2a{p=p.12}29(e){p=6};9(p==6)I P;I(e.O=="4x"?f:g).16(6,[e])}I 6.4x(4G).5U(4G)},2d:G(f){5T();9(E.3T)f.16(U,[E]);J E.3l.1a(G(){I f.16(6,[E])});I 6}});E.1k({3T:P,3l:[],2d:G(){9(!E.3T){E.3T=Q;9(E.3l){E.N(E.3l,G(){6.16(U)});E.3l=S}9(E.V.35||E.V.34)U.4P("5S",E.2d,P);9(!18.7t.K)E(18).39(G(){E("#4E").28()})}}});E.N(("7s,7r,39,7q,6n,5Y,4L,7p,"+"7n,7m,7l,4x,5U,7k,24,"+"51,7j,7i,7h,3U").2l(","),G(i,o){E.1b[o]=G(f){I f?6.3W(o,f):6.1F(o)}});H x=P;G 5T(){9(x)I;x=Q;9(E.V.35||E.V.34)U.4S("5S",E.2d,P);J 9(E.V.1h){U.7f("<7d"+"7y 22=4E 7z=Q "+"3k=//:><\\/1J>");H a=U.3S("4E");9(a)a.62=G(){9(6.2C!="1l")I;E.2d()};a=S}J 9(E.V.1N)E.4B=4j(G(){9(U.2C=="5Q"||U.2C=="1l"){4A(E.4B);E.4B=S;E.2d()}},10);E.1j.1f(18,"39",E.2d)}E.1b.1k({39:G(g,d,c){9(E.1n(g))I 6.3W("39",g);H e=g.1g(" ");9(e>=0){H i=g.2J(e,g.K);g=g.2J(0,e)}c=c||G(){};H f="4z";9(d)9(E.1n(d)){c=d;d=S}J{d=E.3a(d);f="5P"}H h=6;E.3G({1d:g,O:f,M:d,1l:G(a,b){9(b=="1C"||b=="5O")h.4o(i?E("<1s/>").3g(a.40.1p(/<1J(.|\\s)*?\\/1J>/g,"")).1Y(i):a.40);56(G(){h.N(c,[a.40,b,a])},13)}});I 6},7a:G(){I E.3a(6.5M())},5M:G(){I 6.1X(G(){I E.11(6,"2Y")?E.2h(6.79):6}).1E(G(){I 6.2H&&!6.3c&&(6.2Q||/24|6b/i.14(6.11)||/2g|1P|52/i.14(6.O))}).1X(G(i,c){H b=E(6).3i();I b==S?S:b.1c==1B?E.1X(b,G(a,i){I{2H:c.2H,1Q:a}}):{2H:c.2H,1Q:b}}).21()}});E.N("5L,5K,6t,5J,5I,5H".2l(","),G(i,o){E.1b[o]=G(f){I 6.3W(o,f)}});H B=(1u 3D).3B();E.1k({21:G(d,b,a,c){9(E.1n(b)){a=b;b=S}I E.3G({O:"4z",1d:d,M:b,1C:a,1V:c})},78:G(b,a){I E.21(b,S,a,"1J")},77:G(c,b,a){I E.21(c,b,a,"45")},76:G(d,b,a,c){9(E.1n(b)){a=b;b={}}I E.3G({O:"5P",1d:d,M:b,1C:a,1V:c})},75:G(a){E.1k(E.59,a)},59:{1Z:Q,O:"4z",2z:0,5G:"74/x-73-2Y-72",6o:Q,3e:Q,M:S},49:{},3G:G(s){H f,2y=/=(\\?|%3F)/g,1v,M;s=E.1k(Q,s,E.1k(Q,{},E.59,s));9(s.M&&s.6o&&1m s.M!="1M")s.M=E.3a(s.M);9(s.1V=="4b"){9(s.O.2p()=="21"){9(!s.1d.1t(2y))s.1d+=(s.1d.1t(/\\?/)?"&":"?")+(s.4b||"5E")+"=?"}J 9(!s.M||!s.M.1t(2y))s.M=(s.M?s.M+"&":"")+(s.4b||"5E")+"=?";s.1V="45"}9(s.1V=="45"&&(s.M&&s.M.1t(2y)||s.1d.1t(2y))){f="4b"+B++;9(s.M)s.M=s.M.1p(2y,"="+f);s.1d=s.1d.1p(2y,"="+f);s.1V="1J";18[f]=G(a){M=a;1C();1l();18[f]=W;2a{2E 18[f]}29(e){}}}9(s.1V=="1J"&&s.1L==S)s.1L=P;9(s.1L===P&&s.O.2p()=="21")s.1d+=(s.1d.1t(/\\?/)?"&":"?")+"57="+(1u 3D()).3B();9(s.M&&s.O.2p()=="21"){s.1d+=(s.1d.1t(/\\?/)?"&":"?")+s.M;s.M=S}9(s.1Z&&!E.5b++)E.1j.1F("5L");9(!s.1d.1g("8g")&&s.1V=="1J"){H h=U.4l("9U")[0];H g=U.5B("1J");g.3k=s.1d;9(!f&&(s.1C||s.1l)){H j=P;g.9R=g.62=G(){9(!j&&(!6.2C||6.2C=="5Q"||6.2C=="1l")){j=Q;1C();1l();h.3b(g)}}}h.58(g);I}H k=P;H i=18.6X?1u 6X("9P.9O"):1u 6W();i.9M(s.O,s.1d,s.3e);9(s.M)i.5C("9J-9I",s.5G);9(s.5y)i.5C("9H-5x-9F",E.49[s.1d]||"9D, 9C 9B 9A 5v:5v:5v 9z");i.5C("X-9x-9v","6W");9(s.6U)s.6U(i);9(s.1Z)E.1j.1F("5H",[i,s]);H c=G(a){9(!k&&i&&(i.2C==4||a=="2z")){k=Q;9(d){4A(d);d=S}1v=a=="2z"&&"2z"||!E.6S(i)&&"3U"||s.5y&&E.6R(i,s.1d)&&"5O"||"1C";9(1v=="1C"){2a{M=E.6Q(i,s.1V)}29(e){1v="5k"}}9(1v=="1C"){H b;2a{b=i.5s("6P-5x")}29(e){}9(s.5y&&b)E.49[s.1d]=b;9(!f)1C()}J E.5r(s,i,1v);1l();9(s.3e)i=S}};9(s.3e){H d=4j(c,13);9(s.2z>0)56(G(){9(i){i.9q();9(!k)c("2z")}},s.2z)}2a{i.9o(s.M)}29(e){E.5r(s,i,S,e)}9(!s.3e)c();I i;G 1C(){9(s.1C)s.1C(M,1v);9(s.1Z)E.1j.1F("5I",[i,s])}G 1l(){9(s.1l)s.1l(i,1v);9(s.1Z)E.1j.1F("6t",[i,s]);9(s.1Z&&!--E.5b)E.1j.1F("5K")}},5r:G(s,a,b,e){9(s.3U)s.3U(a,b,e);9(s.1Z)E.1j.1F("5J",[a,s,e])},5b:0,6S:G(r){2a{I!r.1v&&9n.9l=="54:"||(r.1v>=6N&&r.1v<9j)||r.1v==6M||E.V.1N&&r.1v==W}29(e){}I P},6R:G(a,c){2a{H b=a.5s("6P-5x");I a.1v==6M||b==E.49[c]||E.V.1N&&a.1v==W}29(e){}I P},6Q:G(r,b){H c=r.5s("9i-O");H d=b=="6K"||!b&&c&&c.1g("6K")>=0;H a=d?r.9g:r.40;9(d&&a.2V.37=="5k")6G"5k";9(b=="1J")E.5f(a);9(b=="45")a=3w("("+a+")");I a},3a:G(a){H s=[];9(a.1c==1B||a.4c)E.N(a,G(){s.1a(3f(6.2H)+"="+3f(6.1Q))});J L(H j 1i a)9(a[j]&&a[j].1c==1B)E.N(a[j],G(){s.1a(3f(j)+"="+3f(6))});J s.1a(3f(j)+"="+3f(a[j]));I s.66("&").1p(/%20/g,"+")}});E.1b.1k({1A:G(b,a){I b?6.1U({1H:"1A",2N:"1A",1r:"1A"},b,a):6.1E(":1P").N(G(){6.R.19=6.3h?6.3h:"";9(E.17(6,"19")=="2s")6.R.19="2Z"}).2D()},1z:G(b,a){I b?6.1U({1H:"1z",2N:"1z",1r:"1z"},b,a):6.1E(":3R").N(G(){6.3h=6.3h||E.17(6,"19");9(6.3h=="2s")6.3h="2Z";6.R.19="2s"}).2D()},6J:E.1b.25,25:G(a,b){I E.1n(a)&&E.1n(b)?6.6J(a,b):a?6.1U({1H:"25",2N:"25",1r:"25"},a,b):6.N(G(){E(6)[E(6).3t(":1P")?"1A":"1z"]()})},9c:G(b,a){I 6.1U({1H:"1A"},b,a)},9b:G(b,a){I 6.1U({1H:"1z"},b,a)},99:G(b,a){I 6.1U({1H:"25"},b,a)},98:G(b,a){I 6.1U({1r:"1A"},b,a)},96:G(b,a){I 6.1U({1r:"1z"},b,a)},95:G(c,a,b){I 6.1U({1r:a},c,b)},1U:G(k,i,h,g){H j=E.6D(i,h,g);I 6[j.3L===P?"N":"3L"](G(){j=E.1k({},j);H f=E(6).3t(":1P"),3y=6;L(H p 1i k){9(k[p]=="1z"&&f||k[p]=="1A"&&!f)I E.1n(j.1l)&&j.1l.16(6);9(p=="1H"||p=="2N"){j.19=E.17(6,"19");j.2U=6.R.2U}}9(j.2U!=S)6.R.2U="1P";j.3M=E.1k({},k);E.N(k,G(c,a){H e=1u E.2j(3y,j,c);9(/25|1A|1z/.14(a))e[a=="25"?f?"1A":"1z":a](k);J{H b=a.3s().1t(/^([+-]=)?([\\d+-.]+)(.*)$/),1O=e.2b(Q)||0;9(b){H d=3I(b[2]),2i=b[3]||"2T";9(2i!="2T"){3y.R[c]=(d||1)+2i;1O=((d||1)/e.2b(Q))*1O;3y.R[c]=1O+2i}9(b[1])d=((b[1]=="-="?-1:1)*d)+1O;e.3N(1O,d,2i)}J e.3N(1O,a,"")}});I Q})},3L:G(a,b){9(E.1n(a)){b=a;a="2j"}9(!a||(1m a=="1M"&&!b))I A(6[0],a);I 6.N(G(){9(b.1c==1B)A(6,a,b);J{A(6,a).1a(b);9(A(6,a).K==1)b.16(6)}})},9f:G(){H a=E.32;I 6.N(G(){L(H i=0;i<a.K;i++)9(a[i].T==6)a.6I(i--,1)}).5n()}});H A=G(b,c,a){9(!b)I;H q=E.M(b,c+"3L");9(!q||a)q=E.M(b,c+"3L",a?E.2h(a):[]);I q};E.1b.5n=G(a){a=a||"2j";I 6.N(G(){H q=A(6,a);q.44();9(q.K)q[0].16(6)})};E.1k({6D:G(b,a,c){H d=b&&b.1c==8Z?b:{1l:c||!c&&a||E.1n(b)&&b,2e:b,3J:c&&a||a&&a.1c!=8Y&&a};d.2e=(d.2e&&d.2e.1c==4W?d.2e:{8X:8W,8V:6N}[d.2e])||8T;d.3r=d.1l;d.1l=G(){E(6).5n();9(E.1n(d.3r))d.3r.16(6)};I d},3J:{6B:G(p,n,b,a){I b+a*p},5q:G(p,n,b,a){I((-38.9s(p*38.8R)/2)+0.5)*a+b}},32:[],2j:G(b,c,a){6.Y=c;6.T=b;6.1e=a;9(!c.3P)c.3P={}}});E.2j.3A={4r:G(){9(6.Y.2F)6.Y.2F.16(6.T,[6.2v,6]);(E.2j.2F[6.1e]||E.2j.2F.6z)(6);9(6.1e=="1H"||6.1e=="2N")6.T.R.19="2Z"},2b:G(a){9(6.T[6.1e]!=S&&6.T.R[6.1e]==S)I 6.T[6.1e];H r=3I(E.3C(6.T,6.1e,a));I r&&r>-8O?r:3I(E.17(6.T,6.1e))||0},3N:G(c,b,e){6.5u=(1u 3D()).3B();6.1O=c;6.2D=b;6.2i=e||6.2i||"2T";6.2v=6.1O;6.4q=6.4i=0;6.4r();H f=6;G t(){I f.2F()}t.T=6.T;E.32.1a(t);9(E.32.K==1){H d=4j(G(){H a=E.32;L(H i=0;i<a.K;i++)9(!a[i]())a.6I(i--,1);9(!a.K)4A(d)},13)}},1A:G(){6.Y.3P[6.1e]=E.1x(6.T.R,6.1e);6.Y.1A=Q;6.3N(0,6.2b());9(6.1e=="2N"||6.1e=="1H")6.T.R[6.1e]="8N";E(6.T).1A()},1z:G(){6.Y.3P[6.1e]=E.1x(6.T.R,6.1e);6.Y.1z=Q;6.3N(6.2b(),0)},2F:G(){H t=(1u 3D()).3B();9(t>6.Y.2e+6.5u){6.2v=6.2D;6.4q=6.4i=1;6.4r();6.Y.3M[6.1e]=Q;H a=Q;L(H i 1i 6.Y.3M)9(6.Y.3M[i]!==Q)a=P;9(a){9(6.Y.19!=S){6.T.R.2U=6.Y.2U;6.T.R.19=6.Y.19;9(E.17(6.T,"19")=="2s")6.T.R.19="2Z"}9(6.Y.1z)6.T.R.19="2s";9(6.Y.1z||6.Y.1A)L(H p 1i 6.Y.3M)E.1x(6.T.R,p,6.Y.3P[p])}9(a&&E.1n(6.Y.1l))6.Y.1l.16(6.T);I P}J{H n=t-6.5u;6.4i=n/6.Y.2e;6.4q=E.3J[6.Y.3J||(E.3J.5q?"5q":"6B")](6.4i,n,0,1,6.Y.2e);6.2v=6.1O+((6.2D-6.1O)*6.4q);6.4r()}I Q}};E.2j.2F={2R:G(a){a.T.2R=a.2v},2B:G(a){a.T.2B=a.2v},1r:G(a){E.1x(a.T.R,"1r",a.2v)},6z:G(a){a.T.R[a.1e]=a.2v+a.2i}};E.1b.6m=G(){H c=0,3E=0,T=6[0],5t;9(T)8L(E.V){H b=E.17(T,"2X")=="4F",1D=T.12,23=T.23,2K=T.3H,4f=1N&&3x(4s)<8J;9(T.6V){5w=T.6V();1f(5w.1S+38.33(2K.2V.2R,2K.1G.2R),5w.3E+38.33(2K.2V.2B,2K.1G.2B));9(1h){H d=E("4o").17("8H");d=(d=="8G"||E.5g&&3x(4s)>=7)&&2||d;1f(-d,-d)}}J{1f(T.5l,T.5z);1W(23){1f(23.5l,23.5z);9(35&&/^t[d|h]$/i.14(1D.37)||!4f)d(23);9(4f&&!b&&E.17(23,"2X")=="4F")b=Q;23=23.23}1W(1D.37&&!/^1G|4o$/i.14(1D.37)){9(!/^8D|1I-9S.*$/i.14(E.17(1D,"19")))1f(-1D.2R,-1D.2B);9(35&&E.17(1D,"2U")!="3R")d(1D);1D=1D.12}9(4f&&b)1f(-2K.1G.5l,-2K.1G.5z)}5t={3E:3E,1S:c}}I 5t;G d(a){1f(E.17(a,"9T"),E.17(a,"8A"))}G 1f(l,t){c+=3x(l)||0;3E+=3x(t)||0}}})();',62,616,'||||||this|||if|||||||||||||||||||||||||||||||||function|var|return|else|length|for|data|each|type|false|true|style|null|elem|document|browser|undefined||options|||nodeName|parentNode||test|jQuery|apply|css|window|display|push|fn|constructor|url|prop|add|indexOf|msie|in|event|extend|complete|typeof|isFunction|className|replace|arguments|opacity|div|match|new|status|firstChild|attr|nodeType|hide|show|Array|success|parent|filter|trigger|body|height|table|script|tbody|cache|string|safari|start|hidden|value|merge|left|break|animate|dataType|while|map|find|global||get|id|offsetParent|select|toggle|selected|toUpperCase|remove|catch|try|cur|al|ready|duration|done|text|makeArray|unit|fx|swap|split|target||pushStack|toLowerCase|nextSibling|button|none|handle|guid|now|stack|tb|jsre|timeout|inArray|scrollTop|readyState|end|delete|step|one|name|nth|slice|doc|ret|preventDefault|width|call|events|checked|scrollLeft|exec|px|overflow|documentElement|grep|position|form|block|removeData|rl|timers|max|opera|mozilla|trim|tagName|Math|load|param|removeChild|disabled|insertBefore|async|encodeURIComponent|append|oldblock|val|childNodes|src|readyList|multiFilter|color|defaultView|stopPropagation|args|old|toString|is|last|first|eval|parseInt|self|domManip|prototype|getTime|curCSS|Date|top||ajax|ownerDocument|parseFloat|easing|has|queue|curAnim|custom|innerHTML|orig|currentStyle|visible|getElementById|isReady|error|static|bind|String|which|getComputedStyle|responseText|oWidth|oHeight|on|shift|json|child|RegExp|ol|lastModified|isXMLDoc|jsonp|jquery|previousSibling|dir|safari2|el|styleFloat|state|setInterval|radio|getElementsByTagName|tr|empty|html|getAttribute|pos|update|version|input|float|runtimeStyle|unshift|mouseover|getPropertyValue|GET|clearInterval|safariTimer|visibility|clean|__ie_init|absolute|handleHover|lastToggle|index|fromElement|relatedTarget|click|fix|evt|andSelf|removeEventListener|handler|cloneNode|addEventListener|triggered|nodeIndex|unique|Number|classFilter|prevObject|selectedIndex|after|submit|password|removeAttribute|file|expr|setTimeout|_|appendChild|ajaxSettings|client|active|win|sibling|deep|globalEval|boxModel|cssFloat|object|checkbox|parsererror|offsetLeft|wrapAll|dequeue|props|lastChild|swing|handleError|getResponseHeader|results|startTime|00|box|Modified|ifModified|offsetTop|evalScript|createElement|setRequestHeader|ctrlKey|callback|metaKey|contentType|ajaxSend|ajaxSuccess|ajaxError|ajaxStop|ajaxStart|serializeArray|init|notmodified|POST|loaded|appendTo|DOMContentLoaded|bindReady|mouseout|not|removeAttr|unbind|unload|Width|keyCode|charCode|onreadystatechange|clientX|pageX|srcElement|join|outerHTML|substr|zoom|parse|textarea|reset|image|odd|even|before|quickClass|quickID|prepend|quickChild|execScript|offset|scroll|processData|uuid|contents|continue|textContent|ajaxComplete|clone|setArray|webkit|nodeValue|fl|_default|100|linear|href|speed|eq|createTextNode|throw|replaceWith|splice|_toggle|xml|colgroup|304|200|alpha|Last|httpData|httpNotModified|httpSuccess|fieldset|beforeSend|getBoundingClientRect|XMLHttpRequest|ActiveXObject|col|br|abbr|pixelLeft|urlencoded|www|application|ajaxSetup|post|getJSON|getScript|elements|serialize|clientWidth|hasClass|scr|clientHeight|write|relative|keyup|keypress|keydown|change|mousemove|mouseup|mousedown|right|dblclick|resize|focus|blur|frames|instanceof|hover|offsetWidth|triggerHandler|ipt|defer|offsetHeight|border|padding|clientY|pageY|Left|Right|toElement|Bottom|Top|cancelBubble|returnValue|detachEvent|attachEvent|substring|line|weight|animated|header|font|enabled|innerText|contains|only|size|gt|lt|uFFFF|u0128|417|inner|Height|toggleClass|removeClass|addClass|replaceAll|noConflict|insertAfter|prependTo|wrap|contentWindow|contentDocument|http|iframe|children|siblings|prevAll|nextAll|wrapInner|prev|Boolean|next|parents|maxLength|maxlength|readOnly|readonly|class|htmlFor|CSS1Compat|compatMode|compatible|borderTopWidth|ie|ra|inline|it|rv|medium|borderWidth|userAgent|522|navigator|with|concat|1px|10000|array|ig|PI|NaN|400|reverse|fast|600|slow|Function|Object|setAttribute|changed|be|can|property|fadeTo|fadeOut|getAttributeNode|fadeIn|slideToggle|method|slideUp|slideDown|action|cssText|stop|responseXML|option|content|300|th|protocol|td|location|send|cap|abort|colg|cos|tfoot|thead|With|leg|Requested|opt|GMT|1970|Jan|01|Thu|area|Since|hr|If|Type|Content|meta|specified|open|link|XMLHTTP|Microsoft|img|onload|row|borderLeftWidth|head|attributes'.split('|'),0,{}))
\ No newline at end of file
--- /dev/null
+
+function refreshVarValue(url, target_id) {
+ $.ajax({
+ url: url,
+ success: function(response) {
+ $('#'+target_id).html(response);
+ }
+ });
+}
+
--- /dev/null
+
+* {
+ margin: 0px;
+ padding: 0px;
+}
+
+body {
+ font-size: 13px;
+ font-family: Tahoma, Arial;
+}
+
+a {
+ text-decoration: none;
+ color: #007700;
+ font-weight: bold;
+}
+
+a:hover {
+ text-decoration: underline;
+}
+
+h1 {
+ margin: 10px 30px;
+ font-style: italic;
+ float: left;
+}
+
+.cleaner {
+ clear: both;
+ visibility: hidden;
+ border: 0px none;
+}
+
+.spacer {
+ width: 100%;
+ height: 10px;
+}
+
+#body {
+ width: 1140px;
+}
+
+#crumbs {
+ clear: both;
+ border: 1px solid black;
+ margin: 5px;
+ width: 1122px;
+}
+
+#crumbs span {
+ display: block;
+ padding: 5px 10px 5px 10px;
+}
+
+#nodes {
+ border: 1px solid black;
+ margin: 5px;
+ width: 200px;
+ float: left;
+}
+
+#nodes ul {
+ margin: 10px;
+}
+
+#nodes ul li {
+ list-style-type: none;
+ margin: 10px 0px;
+}
+
+.title {
+ border-bottom: 1px solid black;
+/* background-color: silver; */
+ background-color: black;
+ color: white;
+ font-weight: bold;
+}
+
+.title span {
+ display: block;
+ height: 1.3em;
+ padding: 5px 10px 5px 10px;
+}
+
+#main {
+ border: 1px solid black;
+ margin: 5px;
+ width: 910px;
+ float: left;
+}
+
+#main #mainInner {
+ margin: 10px;
+}
+
+#main #mainInner .title {
+ margin: -10px -10px 10px -10px;
+}
+
+#configLink {
+ margin-top: 25px;
+ margin-right: 40px;
+ float: right;
+}
+
+ul.nodeVars {
+ margin-top: 20px;
+}
+
+ul.nodeVars li {
+ list-style-type: none;
+}
+
+table.configTable {
+ border: 1px solid black;
+ border-spacing: 1px;
+ padding: 0px;
+}
+
+table.configTable th {
+ padding: 10px;
+}
+
+table.configTable td {
+ border: 1px solid black;
+ padding: 7px;
+}
+
+.errors {
+ color: red;
+}
--- /dev/null
+#############################################################################
+# Makefile for building: hydroponie
+# Generated by qmake (2.01a) (Qt 4.3.4) on: pá úno 6 12:49:29 2009
+# Project: src.pro
+# Template: app
+# Command: /usr/bin/qmake -unix -o Makefile src.pro
+#############################################################################
+
+####### Compiler, tools and options
+
+CC = gcc
+CXX = g++
+DEFINES = -DQT_SHARED -DQT_SQL_LIB -DQT_XML_LIB -DQT_GUI_LIB -DQT_CORE_LIB
+CFLAGS = -pipe -g -D_REENTRANT -Wall -W $(DEFINES)
+CXXFLAGS = -pipe -fpermissive -g -D_REENTRANT -Wall -W $(DEFINES)
+INCPATH = -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4/QtGui -I/usr/include/qt4/QtXml -I/usr/include/qt4/QtXml -I/usr/include/qt4/QtSql -I/usr/include/qt4/QtSql -I/usr/include/qt4 -I../_compiled/include -I. -I.
+LINK = g++
+LFLAGS = -Wl,--no-undefined
+LIBS = $(SUBLIBS) -L/usr/lib -L../_compiled/lib -lfcgi -lulan -lQtSql -lQtXml -lQtGui -lQtCore -lpthread
+AR = ar cqs
+RANLIB =
+QMAKE = /usr/bin/qmake
+TAR = tar -cf
+COMPRESS = gzip -9f
+COPY = cp -f
+SED = sed
+COPY_FILE = $(COPY)
+COPY_DIR = $(COPY) -r
+INSTALL_FILE = install -m 644 -p
+INSTALL_DIR = $(COPY_DIR)
+INSTALL_PROGRAM = install -m 755 -p
+DEL_FILE = rm -f
+SYMLINK = ln -sf
+DEL_DIR = rmdir
+MOVE = mv -f
+CHK_DIR_EXISTS= test -d
+MKDIR = mkdir -p
+
+####### Output directory
+
+OBJECTS_DIR = ./
+
+####### Files
+
+SOURCES = node.cc \
+ uldy_server.cc \
+ html_layer.cc \
+ address_parser.cc \
+ value_cache.cc \
+ graph_painter.cc \
+ http.cc \
+ utils.cc \
+ fcgi.cc \
+ forms.cc moc_forms.cpp
+OBJECTS = node.o \
+ uldy_server.o \
+ html_layer.o \
+ address_parser.o \
+ value_cache.o \
+ graph_painter.o \
+ http.o \
+ utils.o \
+ fcgi.o \
+ forms.o \
+ moc_forms.o
+DIST = /usr/share/qt4/mkspecs/common/g++.conf \
+ /usr/share/qt4/mkspecs/common/unix.conf \
+ /usr/share/qt4/mkspecs/common/linux.conf \
+ /usr/share/qt4/mkspecs/qconfig.pri \
+ /usr/share/qt4/mkspecs/features/qt_functions.prf \
+ /usr/share/qt4/mkspecs/features/qt_config.prf \
+ /usr/share/qt4/mkspecs/features/exclusive_builds.prf \
+ /usr/share/qt4/mkspecs/features/default_pre.prf \
+ /usr/share/qt4/mkspecs/features/debug.prf \
+ /usr/share/qt4/mkspecs/features/default_post.prf \
+ /usr/share/qt4/mkspecs/features/qt.prf \
+ /usr/share/qt4/mkspecs/features/unix/thread.prf \
+ /usr/share/qt4/mkspecs/features/moc.prf \
+ /usr/share/qt4/mkspecs/features/warn_on.prf \
+ /usr/share/qt4/mkspecs/features/resources.prf \
+ /usr/share/qt4/mkspecs/features/uic.prf \
+ /usr/share/qt4/mkspecs/features/yacc.prf \
+ /usr/share/qt4/mkspecs/features/lex.prf \
+ src.pro
+QMAKE_TARGET = hydroponie
+DESTDIR =
+TARGET = hydroponie
+
+first: all
+####### Implicit rules
+
+.SUFFIXES: .o .c .cpp .cc .cxx .C
+
+.cpp.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
+
+.cc.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
+
+.cxx.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
+
+.C.o:
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
+
+.c.o:
+ $(CC) -c $(CFLAGS) $(INCPATH) -o "$@" "$<"
+
+####### Build rules
+
+all: Makefile $(TARGET)
+
+$(TARGET): $(OBJECTS)
+ $(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJCOMP) $(LIBS)
+
+Makefile: src.pro /usr/share/qt4/mkspecs/linux-g++/qmake.conf /usr/share/qt4/mkspecs/common/g++.conf \
+ /usr/share/qt4/mkspecs/common/unix.conf \
+ /usr/share/qt4/mkspecs/common/linux.conf \
+ /usr/share/qt4/mkspecs/qconfig.pri \
+ /usr/share/qt4/mkspecs/features/qt_functions.prf \
+ /usr/share/qt4/mkspecs/features/qt_config.prf \
+ /usr/share/qt4/mkspecs/features/exclusive_builds.prf \
+ /usr/share/qt4/mkspecs/features/default_pre.prf \
+ /usr/share/qt4/mkspecs/features/debug.prf \
+ /usr/share/qt4/mkspecs/features/default_post.prf \
+ /usr/share/qt4/mkspecs/features/qt.prf \
+ /usr/share/qt4/mkspecs/features/unix/thread.prf \
+ /usr/share/qt4/mkspecs/features/moc.prf \
+ /usr/share/qt4/mkspecs/features/warn_on.prf \
+ /usr/share/qt4/mkspecs/features/resources.prf \
+ /usr/share/qt4/mkspecs/features/uic.prf \
+ /usr/share/qt4/mkspecs/features/yacc.prf \
+ /usr/share/qt4/mkspecs/features/lex.prf
+ $(QMAKE) -unix -o Makefile src.pro
+/usr/share/qt4/mkspecs/common/g++.conf:
+/usr/share/qt4/mkspecs/common/unix.conf:
+/usr/share/qt4/mkspecs/common/linux.conf:
+/usr/share/qt4/mkspecs/qconfig.pri:
+/usr/share/qt4/mkspecs/features/qt_functions.prf:
+/usr/share/qt4/mkspecs/features/qt_config.prf:
+/usr/share/qt4/mkspecs/features/exclusive_builds.prf:
+/usr/share/qt4/mkspecs/features/default_pre.prf:
+/usr/share/qt4/mkspecs/features/debug.prf:
+/usr/share/qt4/mkspecs/features/default_post.prf:
+/usr/share/qt4/mkspecs/features/qt.prf:
+/usr/share/qt4/mkspecs/features/unix/thread.prf:
+/usr/share/qt4/mkspecs/features/moc.prf:
+/usr/share/qt4/mkspecs/features/warn_on.prf:
+/usr/share/qt4/mkspecs/features/resources.prf:
+/usr/share/qt4/mkspecs/features/uic.prf:
+/usr/share/qt4/mkspecs/features/yacc.prf:
+/usr/share/qt4/mkspecs/features/lex.prf:
+qmake: FORCE
+ @$(QMAKE) -unix -o Makefile src.pro
+
+dist:
+ @$(CHK_DIR_EXISTS) .tmp/hydroponie1.0.0 || $(MKDIR) .tmp/hydroponie1.0.0
+ $(COPY_FILE) --parents $(SOURCES) $(DIST) .tmp/hydroponie1.0.0/ && $(COPY_FILE) --parents node.h uldy_server.h html_layer.h address_parser.h value_cache.h graph_painter.h http.h utils.h defines.h forms.h .tmp/hydroponie1.0.0/ && $(COPY_FILE) --parents node.cc uldy_server.cc html_layer.cc address_parser.cc value_cache.cc graph_painter.cc http.cc utils.cc fcgi.cc forms.cc .tmp/hydroponie1.0.0/ && (cd `dirname .tmp/hydroponie1.0.0` && $(TAR) hydroponie1.0.0.tar hydroponie1.0.0 && $(COMPRESS) hydroponie1.0.0.tar) && $(MOVE) `dirname .tmp/hydroponie1.0.0`/hydroponie1.0.0.tar.gz . && $(DEL_FILE) -r .tmp/hydroponie1.0.0
+
+
+clean:compiler_clean
+ -$(DEL_FILE) $(OBJECTS)
+ -$(DEL_FILE) *~ core *.core
+
+
+####### Sub-libraries
+
+distclean: clean
+ -$(DEL_FILE) $(TARGET)
+ -$(DEL_FILE) Makefile
+
+
+mocclean: compiler_moc_header_clean compiler_moc_source_clean
+
+mocables: compiler_moc_header_make_all compiler_moc_source_make_all
+
+compiler_moc_header_make_all: moc_forms.cpp
+compiler_moc_header_clean:
+ -$(DEL_FILE) moc_forms.cpp
+moc_forms.cpp: http.h \
+ utils.h \
+ defines.h \
+ forms.h
+ /usr/bin/moc-qt4 $(DEFINES) $(INCPATH) forms.h -o moc_forms.cpp
+
+compiler_rcc_make_all:
+compiler_rcc_clean:
+compiler_image_collection_make_all: qmake_image_collection.cpp
+compiler_image_collection_clean:
+ -$(DEL_FILE) qmake_image_collection.cpp
+compiler_moc_source_make_all:
+compiler_moc_source_clean:
+compiler_uic_make_all:
+compiler_uic_clean:
+compiler_yacc_decl_make_all:
+compiler_yacc_decl_clean:
+compiler_yacc_impl_make_all:
+compiler_yacc_impl_clean:
+compiler_lex_make_all:
+compiler_lex_clean:
+compiler_clean: compiler_moc_header_clean
+
+####### Compile
+
+node.o: node.cc node.h \
+ defines.h \
+ utils.h
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o node.o node.cc
+
+uldy_server.o: uldy_server.cc uldy_server.h \
+ node.h \
+ defines.h \
+ utils.h \
+ value_cache.h
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o uldy_server.o uldy_server.cc
+
+html_layer.o: html_layer.cc html_layer.h \
+ defines.h \
+ utils.h \
+ node.h \
+ value_cache.h \
+ graph_painter.h \
+ http.h \
+ forms.h
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o html_layer.o html_layer.cc
+
+address_parser.o: address_parser.cc address_parser.h \
+ utils.h \
+ defines.h
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o address_parser.o address_parser.cc
+
+value_cache.o: value_cache.cc value_cache.h \
+ defines.h \
+ utils.h
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o value_cache.o value_cache.cc
+
+graph_painter.o: graph_painter.cc graph_painter.h
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o graph_painter.o graph_painter.cc
+
+http.o: http.cc http.h \
+ utils.h \
+ defines.h
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o http.o http.cc
+
+utils.o: utils.cc utils.h \
+ defines.h
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o utils.o utils.cc
+
+fcgi.o: fcgi.cc defines.h \
+ utils.h \
+ http.h \
+ uldy_server.h \
+ node.h \
+ value_cache.h \
+ address_parser.h \
+ html_layer.h \
+ graph_painter.h \
+ forms.h
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o fcgi.o fcgi.cc
+
+forms.o: forms.cc forms.h \
+ http.h \
+ utils.h \
+ defines.h
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o forms.o forms.cc
+
+moc_forms.o: moc_forms.cpp
+ $(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_forms.o moc_forms.cpp
+
+####### Install
+
+install: FORCE
+
+uninstall: FORCE
+
+FORCE:
+
--- /dev/null
+
+lib_LOADLIBES = fcgi ulan QtCore
+
+INCLUDES = -I/usr/include/qt4
+
+bin_PROGRAMS = hydroponie
+hydroponie_HEADERS = node.h
+hydroponie_SOURCES = node.cc fcgi.cc
--- /dev/null
+
+#include "address_parser.h"
+
+AddressParser::AddressParser(QString path) {
+ docRoot = QString(getenv("DOCUMENT_ROOT"));
+ url = path;
+}
+
+QString AddressParser::getUrlPart(int position) const {
+ return url.path().split("/").value(docRoot.split("/").size() - 2 + position, "");
+}
+
+int AddressParser::getCurrentAddr() const {
+// int addr = url.path().split("/").value(docRoot.split("/").size() - 2 + 1, "").toInt();
+ int addr = getUrlPart(1).toInt();
+ if (addr < 0) addr = 0;
+ return addr;
+}
+
+QString AddressParser::getCurrentVarName() const {
+// QString varName = url.path().split("/").value(docRoot.split("/").size() - 2 + 2, "");
+// return varName;
+ return getUrlPart(2);
+}
--- /dev/null
+# ifndef _ADDRESS_PARSER_H
+# define _ADDRESS_PARSER_H
+
+#include <stdlib.h>
+
+#include <QString>
+#include <QStringList>
+#include <QUrl>
+
+#include "utils.h"
+
+class AddressParser {
+ private:
+ QString docRoot;
+ QUrl url;
+
+ public:
+ AddressParser(QString path);
+
+ QString getUrlPart(int position) const;
+
+ int getCurrentAddr() const;
+
+ QString getCurrentVarName() const;
+
+};
+
+# endif
--- /dev/null
+# ifndef _DEFINES_H
+# define _DEFINES_H
+
+#define MAX_ADDR 60
+
+#define NOT_ASSIGNED_ADDR 99
+
+#define LOG_FILENAME "/home/bohacekm/fel/bap/hydroweb/src/log.txt"
+
+#define NODE_CLEANER_PERIOD_SECS 4
+#define HEARTBEAT_CID 1023
+#define PDO_SKIP_BYTES 3
+
+#define SQLITE_DB_FILE "/home/bohacekm/fel/bap/hydroweb/db/db.sqlite"
+#define SQLITE_CACHE_TABLE_NAME "history"
+#define SQLITE_CACHE_SIZE 20
+
+#define VAR_IMG_WIDTH 700
+#define VAR_IMG_HEIGHT 400
+#define VAR_IMG_BORDER_TOP 30
+#define VAR_IMG_BORDER_RIGHT 30
+#define VAR_IMG_BORDER_BOTTOM 30
+#define VAR_IMG_BORDER_LEFT 50
+#define VAR_CACHE_AGE 3600 * 24 * 7
+#define VAR_IMG_FILE_PATH "/var/www/hydroponie/media/"
+#define VAR_IMG_URL_BASE "/media/"
+
+#define HISTORY_LEN 60
+
+// #define TEST_RUN 1
+
+# endif
--- /dev/null
+// #include <stdlib.h>
+#include <iostream>
+#include <string>
+#include <string.h>
+
+#include <QApplication>
+#include <QString>
+#include <QTextCodec>
+
+#include <fcgi_config.h>
+#include <fcgi_stdio.h>
+#include <ul_lib/ulan.h>
+
+#include "defines.h"
+#include "utils.h"
+
+#include "http.h"
+#include "uldy_server.h"
+// #include "node_cleaner.h"
+#include "node.h"
+#include "address_parser.h"
+#include "html_layer.h"
+// #include "forms.h"
+#include "graph_painter.h"
+
+using namespace std;
+
+extern CidPool cidPool;
+
+void myMessageOutput(QtMsgType type, const char *msg)
+ {
+ switch (type) {
+ case QtDebugMsg:
+ logToFile(QString("Debug: %1").arg(msg));
+ break;
+ case QtWarningMsg:
+ logToFile(QString("Warning: %1").arg(msg));
+ break;
+ case QtCriticalMsg:
+ logToFile(QString("Critical: %1").arg(msg));
+ break;
+ case QtFatalMsg:
+ logToFile(QString("Fatal: %1").arg(msg));
+// abort();
+ }
+}
+
+int main(int argc, char *argv[]) {
+ logToFile("START SERVERU");
+ qInstallMsgHandler(myMessageOutput);
+ QApplication app(argc, argv, false);
+ QTime timer;
+ QByteArray ba;
+
+ /* globalni aktivace utf-8 */
+ QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
+
+ int currentNodeAddr = 0;
+ QString currentVarName = "";
+
+ ULDYServer uldySrv;
+ uldySrv.start();
+
+ while (FCGI_Accept() >= 0) {
+ HttpRequest request;
+ HtmlLayer html(request);
+// logToFile(QString("request %1").arg(request.method()));
+
+ html.startBuffering();
+
+ AddressParser parser(request.path());
+ currentNodeAddr = parser.getCurrentAddr();
+ currentVarName = parser.getCurrentVarName();
+
+ NodeMap &nodes = uldySrv.getNodesRef();
+ ValueCache &valueCache = uldySrv.getValueCacheRef();
+#ifndef TEST_RUN
+ uldySrv.tryRemoveNodes();
+#endif
+ bool printRefreshHeader = false;
+ try {
+ if (parser.getUrlPart(1) == "xml_config") {
+
+ if (parser.getUrlPart(2) == "download") {
+ html.stopBuffering();
+ html.printXMLDownload(nodes);
+ continue;
+ }
+
+ html.addCrumb(QString("%1xml_config/").arg(html.documentRoot()), "Správa konfigurace");
+ html.printNodesConfig(nodes);
+
+ } else if (currentNodeAddr == 0) {
+
+ printRefreshHeader = true;
+ html.home(nodes, valueCache);
+
+ } else {
+ Node &selectedNode = nodes.getNodeRef(currentNodeAddr);
+ html.addCrumb(QString("%1%2/").arg(html.documentRoot()).arg(currentNodeAddr), selectedNode.getCustomName());
+
+ if (currentVarName == "configure_vars") {
+ /* konfigurace promennych nodu */
+ html.addCrumb("./", "Konfigurace zařízení");
+ html.printVarsConfig(nodes, selectedNode, cidPool);
+ } else if (currentVarName != "") {
+ /* detail promenne */
+ NodeVar selectedVar = selectedNode.getVar(currentVarName);
+ if (parser.getUrlPart(3) == "refresh_value") {
+ html.stopBuffering();
+ html.printHTTPHeaders();
+ html.printVarValueAjaxRespose(selectedNode, selectedVar);
+ continue;
+ } else {
+ html.addCrumb("./", selectedVar.getCustomDescription());
+ html.printVar(selectedVar, valueCache);
+ printRefreshHeader = true;
+ }
+ } else {
+ /* detail nodu */
+ html.printNode(selectedNode);
+ }
+
+ }
+
+ } catch (NodeError err) {
+ html.stopBuffering();
+ html.printHTTP404Headers();
+ html.print404Error();
+ continue;
+ } catch (NodeVarError err) {
+ html.stopBuffering();
+ html.printHTTP404Headers();
+ html.print404Error();
+ continue;
+ } catch (HttpRedirect redir) {
+ html.stopBuffering();
+ html.printHTTPRedirectHeaders(redir.getUrl());
+ continue;
+ }
+
+ html.stopBuffering();
+
+ if (printRefreshHeader)
+ html.printHTTPRefreshHeaders(10);
+ else
+ html.printHTTPHeaders();
+ html.printDocumentStart();
+ html.printCrumbs();
+ html.printNodes(nodes);
+ html.printContentStart();
+ html.printBuffer();
+ html.printContentEnd();
+// html.printEnvVars();
+ html.print("<hr />");
+// html.print(cidPool.cidsToStr());
+ html.printDocumentEnd();
+
+ } /* while */
+
+// nodeClenaer.stopCleaner();
+// nodeClenaer.wait(3000);
+
+ uldySrv.stopServer();
+ uldySrv.wait(3000);
+
+ return 0;
+}
--- /dev/null
+
+#include "forms.h"
+
+/* Widgets */
+/* TextInput */
+QString TextInput::render(QString name, QVariant value) const {
+ return QString("<input type=\"text\" id=\"id_%1\" name=\"%1\" value=\"%2\" />").arg(name, value.toString());
+}
+
+/* Select */
+QString Select::render(QString name, QVariant value) const {
+ QString output = QString("<select id=\"id_%1\" name=\"%1\">\n").arg(name);
+ if (show_empty_row)
+ output.append("\t<option value=\"\">------</option>\n");
+ SelectOption option;
+ QString selected_str = "";
+ QListIterator<SelectOption> it(choices);
+ while (it.hasNext()) {
+ option = it.next();
+ if (option.first == value.toString())
+ selected_str = " selected=\"selected\"";
+ else
+ selected_str = "";
+ output.append(QString("\t<option%1 value=\"%2\">%3</option>\n").arg(selected_str, option.first, option.second));
+ }
+ output.append("</select>\n");
+ return output;
+}
+
+/* CheckboxInput */
+QString CheckboxInput::render(QString name, QVariant value) const {
+ QString checked_str = "";
+ if (value.toBool())
+ checked_str = " checked=\"checked\"";
+ return QString("<input type=\"checkbox\" id=\"id_%1\" name=\"%1\" value=\"true\"%2>").arg(name, checked_str);
+}
+
+QVariant CheckboxInput::valueFromDatadict(const QueryDict &data, const FilesDict &, QString name) const {
+ return QVariant(data.value(name, "")).toBool();
+}
+
+/* FileInput */
+QString FileInput::render(QString name, QVariant) const {
+ return QString("<input type=\"file\" id=\"id_%1\" name=\"%1\">").arg(name);
+}
+
+QVariant FileInput::valueFromDatadict(const QueryDict &, const FilesDict &files, QString name) const {
+ QVariant value;
+ value.setValue(files.value(name, UploadedFile()));
+ return value;
+}
+
+/* Fields */
+/* Field - abstract */
+QVariant Field::clean(QVariant value) const {
+ QString strval = value.toString().trimmed();
+ if (isRequired() && strval == "")
+ throw ValidationError("Pole je povinné");
+ return strval;
+}
+
+QString Field::render(const QueryDict &data, QString field_template) const {
+ Form *form = (Form*)parent();
+ QVariant value;
+ if (form->isBound())
+ value = data.value(objectName(), "");
+ else
+ value = getInitial();
+ return field_template.arg(widget->render(objectName(), value));
+}
+
+/* CharField */
+CharField::CharField(QString _label, bool _required, QVariant _initial, QObject *parent)
+ : Field(_label, _required, _initial, parent) {
+ widget = new TextInput(this);
+}
+
+/* IntegerField */
+IntegerField::IntegerField(QString _label, bool _required, QVariant _initial, QObject *parent)
+ : Field(_label, _required, _initial, parent) {
+ widget = new TextInput(this);
+}
+
+QVariant IntegerField::clean(QVariant value) const {
+ bool success;
+ int retval;
+ QString strval = Field::clean(value).toString();
+ retval = strval.toInt(&success);
+ if (!success) {
+ if (!isRequired() && value.toString() == "")
+ return "";
+ throw ValidationError("Hodnotu nelze převést na celé číslo");
+ }
+ return retval;
+}
+
+/* DoubleField */
+FloatField::FloatField(QString _label, bool _required, QVariant _initial, QObject *parent)
+ : Field(_label, _required, _initial, parent) {
+ widget = new TextInput(this);
+}
+
+QVariant FloatField::clean(QVariant value) const {
+ bool success;
+ float retval;
+ QString strval = Field::clean(value).toString();
+ retval = strval.toFloat(&success);
+ if (!success) {
+ if (!isRequired() && value.toString() == "")
+ return "";
+ throw ValidationError("Hodnotu nelze převést na desetinné číslo");
+ }
+ return retval;
+}
+
+/* ChoiceField */
+ChoiceField::ChoiceField(QString _label, const QList<SelectOption> &_choices, bool _required, QVariant _initial, QObject *parent)
+ : Field(_label, _required, _initial, parent), choices(_choices) {
+ widget = new Select(_choices, true, this);
+}
+
+QVariant ChoiceField::clean(QVariant value) const {
+ QString strval = Field::clean(value).toString();
+ QListIterator<SelectOption> it(choices);
+ SelectOption option;
+ while (it.hasNext()) {
+ option = it.next();
+ if (option.first == value.toString())
+ return value;
+ }
+ if (!isRequired() && value.toString() == "")
+ return "";
+ throw ValidationError("Neplatná hodnota");
+}
+
+/* BooleanField */
+BooleanField::BooleanField(QString _label, bool _required, QVariant _initial, QObject *parent)
+ : Field(_label, _required, _initial, parent) {
+ widget = new CheckboxInput();
+}
+
+QVariant BooleanField::clean(QVariant value) const {
+ bool boolval = value.toBool();
+ if (!boolval)
+ QString strval = Field::clean("").toString();
+ return boolval;
+}
+
+/* FielField */
+FileField::FileField(QString _label, bool _required, QObject *parent)
+ : Field(_label, _required, "", parent) {
+ widget = new FileInput();
+}
+
+QVariant FileField::clean(QVariant value) const {
+ UploadedFile file = value.value<UploadedFile>();
+ logToFile(QString("file: povinne: %1, null: %2").arg(isRequired()).arg(file.isNull()));
+ if (isRequired() && file.isNull())
+ throw ValidationError("Pole je povinné");
+ return value;
+}
+
+
+/* Form */
+void Form::addField(QString name, Field *field) {
+ field->setObjectName(name);
+ field->setParent(this);
+}
+
+void Form::setError(QString field_name, QString msg) {
+ errors.insert(field_name, msg);
+}
+
+void Form::fullClean() {
+ Field *field;
+ QListIterator<Field*> it(this->findChildren<Field*>());
+ while (it.hasNext()) {
+ field = it.next();
+ try {
+// cleaned_data.insert(field->objectName(), field->clean(data.value(field->objectName(), "")));
+// logToFile(QString("cistim %1").arg(field->objectName()));
+ QVariant value = field->getWidgetPtr()->valueFromDatadict(data, files, field->objectName());
+// logToFile(QString("vycisteno %1").arg(field->objectName()));
+ cleaned_data.insert(field->objectName(), field->clean(value));
+ } catch (ValidationError err) {
+// logToFile(QString("nevycisteno %1").arg(field->objectName()));
+ errors.insert(field->objectName(), err.getMsg());
+ }
+ }
+}
+
+bool Form::isValid() {
+ fullClean();
+ return isBound() && !(errors.size() > 0);
+}
+
+QString Form::renderField(QString field_name, QString field_template, QString label_template, QString error_template) const {
+ /*
+ field template: <p>%1 %2 %3</p>
+ label template: <label for="%1">%2</label>
+ error template: <span class="errors">%1</span>
+ */
+ Field *field = findChild<Field*>(field_name);
+ QString label_str = "";
+ QString error_str = "";
+ if (field) {
+ if (label_template != "")
+ label_str = label_template.arg(QString("id_%1").arg(field->objectName()), field->getLabel());
+ if (errors.contains(field_name) && error_template != "")
+ error_str = error_template.arg(errors.value(field_name));
+ return field_template.arg(label_str, field->render(data), error_str);
+ } else {
+ return "";
+ }
+}
+
+QList<QString> Form::fieldNames() const {
+ QList<QString> names;
+ QListIterator<Field*> it(this->findChildren<Field*>());
+ while (it.hasNext()) {
+ names.append(it.next()->objectName());
+ }
+ return names;
+}
+
+Field *Form::operator[](QString field_name) const {
+ return findChild<Field*>(field_name);
+}
--- /dev/null
+# ifndef FORMS_H
+# define FORMS_H
+
+#include <QPair>
+#include <QString>
+#include <QVariant>
+#include <QVariantMap>
+
+#include "http.h"
+#include "utils.h"
+
+/* Form Errors */
+typedef QMap<QString, QString> ErrorDict;
+class ValidationError {
+ private:
+ QString msg;
+
+ public:
+ ValidationError(QString _msg): msg(_msg) {}
+
+ QString getMsg() { return msg; }
+};
+
+
+/* Widgets */
+class Widget : public QObject {
+ Q_OBJECT;
+ public:
+ Widget(QObject *parent=0): QObject(parent) {}
+
+ virtual ~Widget() {};
+
+ virtual QString render(QString name, QVariant value) const = 0;
+
+ virtual QVariant valueFromDatadict(const QueryDict &data, const FilesDict &, QString name) const {
+ return QVariant(data.value(name, ""));
+ }
+};
+
+class TextInput : public Widget {
+ public:
+ TextInput(QObject *parent=0): Widget(parent) {}
+
+ virtual QString render(QString name, QVariant value) const;
+
+};
+
+typedef QPair<QString, QString> SelectOption;
+class Select : public Widget {
+ private:
+ QList<SelectOption> choices;
+ bool show_empty_row;
+
+ public:
+ Select(bool _show_empty_row=true, QObject *parent=0): Widget(parent), show_empty_row(_show_empty_row) {}
+
+ Select(const QList<SelectOption> &_choices, bool _show_empty_row=true, QObject *parent=0): Widget(parent), choices(_choices), show_empty_row(_show_empty_row) {}
+
+ void addOption(const SelectOption &option) {
+ choices.append(option);
+ }
+
+ virtual QString render(QString name, QVariant value) const;
+
+ virtual const QList<SelectOption> &getChoicesRef() const { return choices; }
+};
+
+class CheckboxInput : public Widget {
+ public:
+ CheckboxInput(QObject *parent=0): Widget(parent) {}
+
+ virtual QString render(QString name, QVariant value) const;
+
+ virtual QVariant valueFromDatadict(const QueryDict &data, const FilesDict &files, QString name) const;
+};
+
+class FileInput : public Widget {
+ public:
+ FileInput(QObject *parent=0): Widget(parent) {}
+
+ virtual QString render(QString name, QVariant value) const;
+
+ virtual QVariant valueFromDatadict(const QueryDict &data, const FilesDict &files, QString name) const;
+};
+
+
+/* Fields */
+class Field : public QObject {
+ Q_OBJECT;
+ protected:
+ QString label;
+ bool required;
+ QVariant initial;
+ Widget *widget;
+
+ public:
+ Field(QString _label, bool _required, QVariant _initial, QObject *parent=0)
+ : QObject(parent), label(_label), required(_required), initial(_initial) {}
+
+ virtual ~Field() {};
+
+ virtual QString render(const QueryDict &data, QString field_template="%1") const;
+
+ virtual QVariant clean(QVariant value) const;
+
+ virtual QString getLabel() const { return label; }
+
+ virtual bool isRequired() const { return required; }
+
+ virtual QVariant getInitial() const { return initial; }
+
+ virtual Widget *getWidgetPtr() { return widget; }
+};
+
+class CharField : public Field {
+ public:
+ CharField(QString _label, bool _required, QVariant _initial="", QObject *parent=0);
+
+};
+
+class IntegerField : public Field {
+ public:
+ IntegerField(QString _label, bool _required, QVariant _initial="", QObject *parent=0);
+
+ virtual QVariant clean(QVariant value) const;
+};
+
+class FloatField : public Field {
+ public:
+ FloatField(QString _label, bool _required, QVariant _initial="", QObject *parent=0);
+
+ virtual QVariant clean(QVariant value) const;
+};
+
+class ChoiceField : public Field {
+ private:
+ const QList<SelectOption> &choices;
+
+ public:
+ ChoiceField(QString _label, const QList<SelectOption> &_choices, bool _required, QVariant _initial="", QObject *parent=0);
+
+ virtual QVariant clean(QVariant value) const;
+};
+
+class BooleanField : public Field {
+ public:
+ BooleanField(QString _label, bool _required, QVariant _initial=false, QObject *parent=0);
+
+ virtual QVariant clean(QVariant value) const;
+};
+
+class FileField : public Field {
+ public:
+ FileField(QString _label, bool _required, QObject *parent=0);
+
+ virtual QVariant clean(QVariant value) const;
+};
+
+
+/* Form */
+class Form : public QObject {
+ Q_OBJECT;
+ private:
+ bool is_bound;
+ QueryDict data;
+ FilesDict files;
+ ErrorDict errors;
+ QVariantMap cleaned_data;
+
+ public:
+ Form(QObject *parent=0): QObject(parent), is_bound(false) {}
+
+ virtual ~Form() {}
+
+ void bindData(const QueryDict &_data) {
+ is_bound = true;
+ data = _data;
+ }
+
+ void bindFiles(const FilesDict &_files) {
+ is_bound = true;
+ files = _files;
+ }
+
+ bool isBound() const { return is_bound; }
+
+ void addField(QString name, Field *field);
+
+ void setError(QString field_name, QString msg);
+
+ void fullClean();
+
+ bool isValid();
+
+ QString renderField(QString field_name, QString field_template="<p>\n\t%1\n\t%2\n\t%3\n</p>\n", QString label_template="<label for=\"%1\">%2</label>\n", QString error_template="<span class=\"errors\">%1</span>\n") const;
+
+ QList<QString> fieldNames() const;
+
+ const QVariantMap &getCleanedDataRef() const { return cleaned_data; }
+
+ Field *operator[](QString field_name) const;
+};
+
+
+# endif
--- /dev/null
+
+# include "graph_painter.h"
+
+#define SHRINK_FACTOR 1.2
+
+double Graph::maxVal() const {
+ if (this->data.size() == 0) return 0.0;
+ double maxval = this->data[0].y();
+ for (int i = 1; i < this->data.size(); i++)
+ if (this->data[i].y() > maxval) maxval = this->data[i].y();
+ return maxval;
+}
+
+double Graph::minVal() const {
+ if (this->data.size() == 0) return 0.0;
+ double minval = this->data[0].y();
+ for (int i = 1; i < this->data.size(); i++)
+ if (this->data[i].y() < minval) minval = this->data[i].y();
+ return minval;
+}
+
+QPen Graph::getLinePen() const {
+ QPen linePen(this->color);
+ linePen.setStyle(this->penStyle);
+ linePen.setWidth(1);
+ return linePen;
+}
+
+QPen Graph::getPointPen() const {
+ QPen pointPen(this->color);
+ pointPen.setWidth(4);
+ return pointPen;
+}
+
+QPen Graph::getValuesPen() const {
+ QPen valuesPen(Qt::darkRed);
+ valuesPen.setWidth(1);
+ return valuesPen;
+}
+
+
+/* class GraphPainter */
+QPen GraphPainter::getAxisPen() const {
+ QPen axisPen(Qt::black);
+ axisPen.setWidth(1);
+ return axisPen;
+}
+
+double GraphPainter::getStep() const {
+ return ((double)(image.width() - borderLeft - borderRight)) / (maxValuesCount - 1);
+}
+
+/* prepocet Y-hodnoty z kartezskeho systemu do souradnic QPainteru + posunuti o definovany okraj */
+double GraphPainter::_correctYvalue(double val) const {
+ return image.height() - borderBottom - val;
+}
+
+double GraphPainter::_countXvalue(double val) const {
+ return x_size / (x_max - x_min) * (val - x_min) + borderLeft;
+}
+
+double GraphPainter::totalMaxVal() const {
+ if (graphs.size() == 0) return 0.0;
+ double maxval = graphs[0].maxVal();
+ double tmpmax;
+ for (int i = 1; i < graphs.size(); i++) {
+ tmpmax = graphs[i].maxVal();
+ if (tmpmax > maxval) maxval = tmpmax;
+ }
+ return maxval;
+}
+
+double GraphPainter::totalMinVal() const {
+ if (graphs.size() == 0) return 0.0;
+ double minval = graphs[0].minVal();
+ double tmpmin;
+ for (int i = 1; i < graphs.size(); i++) {
+ tmpmin = graphs[i].minVal();
+ if (tmpmin < minval) minval = tmpmin;
+ }
+ return minval;
+}
+
+void GraphPainter::drawAxes(double zero_level, const AxisLabelList &x_labels, double y_axis_minval, double y_axis_maxval, double scale, double lift) {
+ painter.setPen(getAxisPen());
+ painter.drawLine(borderLeft, _correctYvalue(zero_level), image.width() - borderRight, _correctYvalue(zero_level));
+ painter.drawLine(borderLeft, borderTop, borderLeft, _correctYvalue(0.0));
+ painter.drawText(0, _correctYvalue(zero_level) - 7, borderLeft - 10, 20, Qt::AlignRight, "0");
+
+ AxisLabel label;
+ double x_value;
+ for (int i = 0; i < x_labels.size(); i++) {
+ label = x_labels[i];
+ if (label.first >= x_min && label.first <= x_max) {
+ x_value = _countXvalue(label.first);
+ painter.drawLine(x_value, _correctYvalue(zero_level), x_value, _correctYvalue(zero_level - 5));
+ painter.drawText(x_value, _correctYvalue(zero_level - 18), label.second);
+ }
+ }
+
+ double y_range = y_axis_maxval - y_axis_minval;
+ if (y_range > 0.0) {
+ double y_step;
+ double y_pos;
+ if (y_range <= 1)
+ y_step = y_range / 10.0;
+ else if (y_range <= 10)
+ y_step = ((int)y_range / 10.0);
+ else
+ y_step = (int)(y_range / 10.0);
+
+ y_pos = y_step;
+ while (y_pos <= (y_axis_maxval)) {
+ painter.drawText(0, _correctYvalue(scale * y_pos + lift) - 7, borderLeft - 10, 20, Qt::AlignRight, QString("%1").arg(y_pos));
+ painter.drawLine(borderLeft - 5, _correctYvalue(scale * y_pos + lift), borderLeft, _correctYvalue(scale * y_pos + lift));
+ y_pos += y_step;
+ }
+ y_pos = -y_step;
+ while (y_pos >= (y_axis_minval)) {
+ painter.drawText(0, _correctYvalue(scale * y_pos + lift) - 7, borderLeft - 10, 20, Qt::AlignRight, QString("%1").arg(y_pos));
+ painter.drawLine(borderLeft - 5, _correctYvalue(scale * y_pos + lift), borderLeft, _correctYvalue(scale * y_pos + lift));
+ y_pos -= y_step;
+ }
+ }
+}
+
+QPolygonF GraphPainter::data2Polygon(const GraphData &data, double scale, double lift) const {
+ double x_coord, y_coord, x_val;
+// double step = getStep();
+ QPolygonF polygon;
+ for (int i = 0; i < data.size(); i++) {
+// x_coord = borderLeft + qRound(i * step);
+ x_val = data[i].x();
+ if (x_val < x_min || x_val > x_max)
+ continue;
+ x_coord = _countXvalue(x_val);
+ y_coord = _correctYvalue(scale * data[i].y() + lift);
+ polygon.append(QPointF(x_coord, y_coord));
+ }
+ return polygon;
+}
+
+bool GraphPainter::existsNonEmptyGraph() const {
+ for (int i = 0; i < graphs.size(); i++)
+ if (graphs[i].getDataConstRef().size() > 0) return true;
+ return false;
+}
+
+GraphPainter::GraphPainter(QSize _size, int _borderTop, int _borderRight, int _borderBottom, int _borderLeft) {
+// this->maxValuesCount = _maxValuesCount;
+ this->borderTop = _borderTop; this->borderRight = _borderRight; this->borderBottom = _borderBottom; this->borderLeft = _borderLeft;
+ this->x_min = 0.0;
+ this->x_max = 1.0;
+ this->x_size = _size.width() - _borderLeft - _borderRight;
+ image = QImage(_size, QImage::Format_RGB16);
+ painter.begin(&image);
+ painter.fillRect(image.rect(), Qt::white);
+}
+
+/* pridani grafu pro vykresleni */
+void GraphPainter::addGraph(const Graph &graph) {
+ graphs.append(graph);
+}
+
+/* kresleni grafu - maxValuesCount udava max. pocet hodnot v datove rade */
+void GraphPainter::drawGraphs(double x_min, double x_max) {
+ AxisLabelList empty_list;
+ drawGraphs(x_min, x_max, empty_list);
+}
+
+void GraphPainter::drawGraphs(double _x_min, double _x_max, const AxisLabelList &x_labels) {
+ x_min = _x_min;
+ x_max = _x_max;
+
+ /* pokud nejsou k dispozici hodnoty, jsou nakresleny pozue souradne osy */
+ if (existsNonEmptyGraph()) {
+ double minval = totalMinVal();
+ double maxval = totalMaxVal();
+ int box_height = image.height() - borderTop - borderBottom;
+ double range = maxval - minval;
+ double x_coord, y_coord;
+ double y_axis_minval, y_axis_maxval;
+ int y_shift;
+
+ /* vypocet umisteni nuly na ose Y, meritka a posunuti grafu po ose Y */
+ double zero_level, scale, lift;
+ if (maxval >= 0.0 && minval >= 0.0) {
+ zero_level = 0.0;
+ scale = box_height / maxval / SHRINK_FACTOR;
+ lift = 0.0;
+ y_axis_minval = 0.0;
+ y_axis_maxval = maxval * (SHRINK_FACTOR - (SHRINK_FACTOR - 1) / 2.0);
+ } else if (maxval <= 0.0 && minval <= 0.0) {
+ zero_level = box_height;
+ scale = box_height / qAbs(minval) / SHRINK_FACTOR;
+ lift = qAbs(minval) * scale * SHRINK_FACTOR;
+ y_axis_minval = minval * (SHRINK_FACTOR - (SHRINK_FACTOR - 1) / 2.0);
+ y_axis_maxval = 0.0;
+ } else {
+ zero_level = box_height * (range - maxval) / range;
+ scale = qMin( (box_height - zero_level) / maxval , zero_level / qAbs(minval) ) / SHRINK_FACTOR;
+ lift = qAbs(minval) * scale * SHRINK_FACTOR;
+ y_axis_minval = minval;
+ y_axis_maxval = maxval;
+ }
+
+ drawAxes(zero_level, x_labels, y_axis_minval, y_axis_maxval, scale, lift);
+
+ for (int i = 0; i < graphs.size(); i++) {
+ Graph &graph = graphs[i];
+ QPolygonF polygon = data2Polygon(graph.getDataConstRef(), scale, lift);
+
+ /* kresleni uzlu a hran */
+ painter.setPen(graph.getPointPen());
+ painter.drawPoints(polygon);
+ painter.setPen(graph.getLinePen());
+ painter.drawPolyline(polygon);
+
+ if (graph.withValues()) {
+ /* kresleni ciselnych hodnot */
+ painter.setPen(graph.getValuesPen());
+ painter.setFont(QFont(painter.font().family(), 10));
+ for (int j = 0; j < polygon.size(); j++) {
+ x_coord = polygon[j].x();
+ y_coord = polygon[j].y();
+ if (graph.getDataConstRef()[j].y() >= 0.0) y_shift = -20;
+ else y_shift = 4;
+ painter.translate(x_coord + 1, y_coord + y_shift);
+ painter.rotate(30);
+ painter.drawText(0, 0, 40, 20, Qt::AlignLeft, QString("%1").arg(graph.getDataConstRef()[j].y(), 0, 'f', 1));
+ painter.resetTransform();
+ }
+ }
+ }
+ } else
+ drawAxes(0.0, x_labels, 0.0, 0.0);
+}
+
+/* ulozeni grafu do souboru */
+bool GraphPainter::saveGraphs(QString filename) const {
+ return image.save(filename, "PNG", 40);
+}
--- /dev/null
+# ifndef _GRAPH_PAINTER_H
+# define _GRAPH_PAINTER_H
+
+#include <cmath>
+#include <QtSql>
+#include <QImage>
+#include <QPainter>
+#include <QPen>
+#include <QPointF>
+#include <QPolygonF>
+#include <QList>
+#include <QPair>
+
+// #include "defines.h"
+// #include "utils.h"
+
+typedef QVector<QPointF> GraphData;
+class Graph {
+ private:
+ GraphData data;
+ QColor color;
+ Qt::PenStyle penStyle;
+ bool drawValues;
+
+ public:
+ Graph(GraphData _data, QColor _color, Qt::PenStyle _penStyle=Qt::SolidLine, bool _drawValues=true): data(_data), color(_color), penStyle(_penStyle), drawValues(_drawValues) {}
+
+ double maxVal() const;
+
+ double minVal() const;
+
+ bool withValues() {
+ return this->drawValues;
+ }
+
+ QColor getColor() const {
+ return this->color;
+ }
+
+ Qt::PenStyle getPenStyle() const {
+ return this->penStyle;
+ }
+
+ QPen getLinePen() const;
+
+ QPen getPointPen() const;
+
+ QPen getValuesPen() const;
+
+ const GraphData &getDataConstRef() const {
+ return this->data;
+ }
+};
+
+typedef QPair<double, QString> AxisLabel;
+typedef QList<AxisLabel> AxisLabelList;
+class GraphPainter {
+ private:
+ QImage image;
+ QPainter painter;
+ QList<Graph> graphs;
+ int borderTop, borderRight, borderBottom, borderLeft;
+ int maxValuesCount;
+ int x_size;
+ double x_min;
+ double x_max;
+
+ QPen getAxisPen() const;
+
+ double getStep() const;
+
+ double _correctYvalue(double val) const;
+
+ double _countXvalue(double val) const;
+
+ double totalMaxVal() const;
+
+ double totalMinVal() const;
+
+ void drawAxes(double zero_level, const AxisLabelList &x_labels, double y_axis_minval, double y_axis_maxval, double scale=1.0, double lift=0.0);
+
+ QPolygonF data2Polygon(const GraphData &data, double scale=1.0, double lift=0.0) const;
+
+ bool existsNonEmptyGraph() const;
+
+ public:
+ GraphPainter(QSize _size, int _borderTop, int _borderRight, int _borderBottom, int _borderLeft);
+
+ void addGraph(const Graph &graph);
+
+ void drawGraphs(double x_min, double x_max);
+
+ void drawGraphs(double x_min, double x_max, const AxisLabelList &x_labels);
+
+ bool saveGraphs(QString filename) const;
+};
+
+# endif
--- /dev/null
+
+#include "html_layer.h"
+
+extern char** environ;
+
+using namespace std;
+
+void HtmlLayer::_print(const QString &msg) {
+ if (this->buffering) {
+ this->buffer.append(msg);
+ } else {
+ QByteArray ba = msg.toUtf8();
+ printf("%s", ba.constData());
+ }
+}
+
+HtmlLayer::HtmlLayer(HttpRequest &request) {
+ this->addCrumb(documentRoot(), "Home");
+ this->buffering = false;
+ this->request = request;
+}
+
+/* buffer funkce */
+void HtmlLayer::startBuffering() {
+ this->buffering = true;
+ this->buffer = "";
+}
+
+void HtmlLayer::stopBuffering() { this->buffering = false; }
+
+void HtmlLayer::printBuffer() const {
+ QByteArray ba = this->buffer.toUtf8();
+ printf("%s", ba.constData());
+}
+
+/* drobky */
+void HtmlLayer::addCrumb(QString url, QString link) {
+ QStringList crumb;
+ crumb.append(url);
+ crumb.append(link);
+ crumbs.append(crumb);
+}
+
+void HtmlLayer::printCrumbs() {
+ CrumbsIterator it(crumbs);
+ QByteArray url;
+ QByteArray link;
+ _print("<div id=\"crumbs\"><span>");
+ while (it.hasNext()) {
+ QStringList crumb = it.next();
+ _print(QString("<a href=\"%1\">%2</a>").arg(crumb[0]).arg(crumb[1]));
+ if (it.hasNext()) _print(" >> ");
+ }
+ _print("</span></div>\n");
+}
+
+/* zakladni html funkce */
+QString HtmlLayer::documentRoot() const {
+ return QString(getenv("DOCUMENT_ROOT"));
+}
+
+void HtmlLayer::printHTTPHeaders() {
+ _print("Status: 200 OK\r\n");
+ _print("Pragma: no-cache\r\n");
+ _print("Content-Type: text/html; charset=UTF-8\r\n\r\n");
+}
+
+void HtmlLayer::printHTTPRefreshHeaders(int seconds) {
+ _print("Status: 200 OK\r\n");
+ _print(QString("Refresh: %1\r\n").arg(seconds));
+ _print("Pragma: no-cache\r\n");
+ _print("Content-Type: text/html; charset=UTF-8\r\n\r\n");
+}
+
+void HtmlLayer::printHTTPRedirectHeaders(QString location) {
+ _print("Status: 302 Found\r\n");
+ _print(QString("Location: %1\r\n").arg(location));
+ _print("Connection: close\r\n\r\n");
+}
+
+void HtmlLayer::printHTTP404Headers() {
+ _print("Status: 404 Not Found\r\n");
+ _print("Pragma: no-cache\r\n");
+ _print("Content-Type: text/html; charset=UTF-8\r\n\r\n");
+}
+
+void HtmlLayer::print404Error() {
+ _print("<html>\r\n\t<head>\r\n\t\t<title>404 - Not Found</title>\r\n\t<body>\r\n\t\t<h1>404 - Not Found</h1>\r\n\t</body>\r\n</html>\r\n");
+}
+
+void HtmlLayer::printDocumentStart() {
+ _print(
+ "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\r\n"
+ "<html>\r\n"
+ "<head>\n"
+ "\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\r\n"
+ "\t<script type=\"text/javascript\" src=\"" VAR_IMG_URL_BASE "js/jquery.js\"></script>\r\n"
+ "\t<script type=\"text/javascript\" src=\"" VAR_IMG_URL_BASE "js/nodevar.js\"></script>\r\n"
+ "\t<link rel=\"stylesheet\" type=\"text/css\" href=\"" VAR_IMG_URL_BASE "styles/main.css\" media=\"screen\" />\r\n"
+ "\t<title>Hydroponie FastCGI echo</title>\r\n"
+ "</head>\n"
+ "<body><div id=\"body\">\r\n\t<h1>Hydroponie web interface</h1>\r\n"
+ );
+ _print(QString("<a id=\"configLink\" href=\"%1xml_config/\">Správa konfigurace</a>").arg(documentRoot()));
+}
+
+void HtmlLayer::printDocumentEnd() {
+ _print("</div></body></html>\r\n");
+}
+
+void HtmlLayer::printContentStart() {
+ _print("<div id=\"main\"><div id=\"mainInner\">\n");
+}
+
+void HtmlLayer::printContentEnd() {
+ _print("</div></div><div class=\"cleaner\"></div>\n");
+}
+
+void HtmlLayer::printEnvVars() {
+ int i;
+ _print("<hr />\n"
+ "<div id=\"envVars\" style=\"color: grey;\">\n");
+ for(i = 0; environ[i] != NULL; i++)
+ _print(QString("%1<br />\n").arg(environ[i]));
+ _print("</div>\n");
+}
+
+/* funkce pro prezentaci nodu */
+void HtmlLayer::home(NodeMap &nodes, ValueCache &valueCache) {
+ _print(QString("<div class=\"title\"><span>Vyberte zařízení...</span></div>\n"));
+
+ QString filename("common_graph.png");
+ GraphPainter gp(QSize(VAR_IMG_WIDTH, VAR_IMG_HEIGHT), VAR_IMG_BORDER_TOP, VAR_IMG_BORDER_RIGHT, VAR_IMG_BORDER_BOTTOM, VAR_IMG_BORDER_LEFT);
+ NodeMapIterator itm(nodes);
+ while (itm.hasNext()) {
+ itm.next();
+ NodeVarIterator itv = itm.value()->getIterator();
+ while (itv.hasNext()) {
+ itv.next();
+ if (itv.value().getCommonGraphDisplay()) {
+ GraphData gdata = valueCache.getValues(itv.value().getNodeSN(), itv.value().getId(), HISTORY_LEN).first;
+ gp.addGraph(Graph(gdata, itv.value().getGraphColor(), Qt::SolidLine, false));
+ }
+ }
+ }
+ QDateTime current_datetime = currentDateTime();
+ gp.drawGraphs(current_datetime.toTime_t() - HISTORY_LEN, current_datetime.toTime_t(), getTimeLabels(HISTORY_LEN));
+ gp.saveGraphs(QString(VAR_IMG_FILE_PATH).append(filename));
+
+ _print(QString("<img src=\"" VAR_IMG_URL_BASE "%1\" />\n").arg(filename));
+
+}
+
+void HtmlLayer::printNodes(NodeMap &nodes) {
+ QByteArray ba;
+ NodeMapKeysIterator it(nodes.keys());
+ _print("<div id=\"nodes\"><div class=\"title\"><span>Dostupná zařízení</span></div><ul>\n");
+ while (it.hasNext()) {
+ int addr = it.next();
+ if (nodes.contains(addr)) {
+ Node &tmpNode = nodes.getNodeRef(addr);
+ _print(QString("\t<li><a href=\"%1%2/\" title=\"%3\">%4</a></li>\n").arg(documentRoot()).arg(tmpNode.getAddr()).arg(tmpNode.getIdStr()).arg(tmpNode.getCustomName()));
+ }
+ }
+ _print("</ul></div>\n");
+}
+
+void HtmlLayer::printNodesConfig(NodeMap &nodes) {
+ Form conf_form;
+ conf_form.addField("config_file", new FileField("Konfigurace", true));
+
+ if (request.method() == "POST") {
+ conf_form.bindFiles(request.FILES());
+
+ if (conf_form.isValid()) {
+ bool parseErr = false;
+ UploadedFile config_file = conf_form.getCleanedDataRef()["config_file"].value<UploadedFile>();
+ if (!config_file.isNull()) {
+ QDomDocument config;
+ if (config.setContent(config_file.contentRef())) {
+ QDomElement confElem = config.documentElement();
+ if (confElem.tagName() != "configuration") {
+ parseErr = true;
+ } else {
+ QDomElement nodesElem = confElem.firstChildElement("nodes");
+ if (!nodesElem.isNull())
+ nodes.setXMLConfig(nodesElem);
+ }
+ }
+ } else {
+ parseErr = true;
+ }
+
+ if (parseErr) {
+ conf_form.setError("config_file", "Chyba při parsování konfiguračního souboru");
+ } else {
+ throw HttpRedirect("./");
+ }
+
+ }
+ }
+
+ _print("<div class=\"title\"><span>Nahrání konfigurace</span></div>");
+ _print("<form action=\"./\" method=\"post\" enctype=\"multipart/form-data\"><table class=\"configTable\">\n");
+ _print(conf_form.renderField("config_file", "<tr><td>%1</td><td>%2 %3</td></tr>\n"));
+ _print("\t<tr><td colspan=\"2\"><input type=\"submit\" value=\"Uložit\" /></td></tr>\n</table></form>\n");
+ _print("<div class=\"spacer\"></div><p><a href=\"./download/\">Stáhnout aktuální konfguraci</a></p>\n");
+}
+
+void HtmlLayer::printNode(Node node) {
+// addCrumb("./", node.getIdStr());
+ NodeVarIterator it = node.getIterator();
+ _print(QString("<div class=\"title\"><span>%1</span></div>").arg(node.getCustomName()));
+ _print(QString("<a href=\"%1%2/configure_vars/\">Konfigurace zařízení</a>").arg(documentRoot()).arg(node.getAddr()));
+ _print("<ul class=\"nodeVars\">\n");
+ while (it.hasNext()) {
+ it.next();
+ NodeVar tmpVar = it.value();
+// if (!tmpVar.isVisible()) continue;
+ if (tmpVar.isSystemVar()) continue;
+ _print(QString("\t<li><a href=\"./%1/\">%2</a></li>\n").arg(tmpVar.getName()).arg(tmpVar.getCustomDescription()));
+ }
+ _print("</ul>\n");
+}
+
+void HtmlLayer::printVarsConfig(NodeMap &nodes, Node &node, CidPool &cidPool) {
+ Form vars_form, node_form;
+ processVarsConfig(nodes, node, vars_form, cidPool);
+ processNodeConfig(node, node_form);
+
+ _print(QString("<div class=\"title\"><span>%1 (konfigurace zařízení)</span></div>").arg(node.getCustomName()));
+
+ /* formular pro konfiguraci nodu */
+ _print("<form action=\"./\" method=\"post\"><table class=\"configTable\">\n");
+ _print(node_form.renderField("node_name", "<tr><td>%1</td><td>%2 %3</td></tr>\n"));
+// _print(node_form.renderField("config_file", "<tr><td>%1</td><td>%2 %3</td></tr>\n"));
+ _print("\t<tr><td colspan=\"2\"><input type=\"submit\" value=\"Uložit\" name=\"configure_node\" /></td></tr>\n</table></form>\n");
+
+ _print("<div class=\"spacer cleaner\"></div>");
+
+ /* formular pro konfiguraci promennych */
+ _print("<form action=\"./\" method=\"post\"><table class=\"configTable\">\n"
+ "\t<tr>"
+ "<th>Systémový název</th>"
+ "<th>Uživatelský název</th>"
+ "<th>Nastavit hodnotu</th>"
+ "<th>Aktuální hodnota</th>"
+ "<th>Barva</th>"
+ "<th>Spol. graf</th>"
+ "<th>Detail</th>"
+ "</tr>\n");
+
+ QString descr_field("%1_description");
+ QString value_field("%1_value");
+ QString color_field("%1_color");
+ QString displ_field("%1_display");
+
+ ULOIConnection conn(node.getAddr());
+
+ NodeVarIterator it = node.getIterator();
+ while (it.hasNext()) {
+ it.next();
+ NodeVar tmpVar = it.value();
+ QString name = tmpVar.getName();
+ QString tdTemplate("<td>%1%2%3</td>");
+ QString errTemplate("<span class=\"errors\">%1</td>");
+ if (!tmpVar.isVisible()) continue;
+
+ _print("\t<tr>");
+// _print(QString("<td>%1 (W:%2 R:%3)</td>").arg(name).arg(tmpVar.isWriteable()).arg(tmpVar.isReadable()));
+ _print(QString("<td>%1</td>").arg(name));
+
+ /* field pro popis */
+ _print(vars_form.renderField(descr_field.arg(name), tdTemplate, "", errTemplate));
+
+ /* field pro hodnotu */
+ if (vars_form[value_field.arg(name)])
+ _print(vars_form.renderField(value_field.arg(name), tdTemplate, "", errTemplate));
+ else
+ _print("<td></td>");
+
+ /* odkaz pro aktualizaci hodnoty */
+ if (tmpVar.isReadable())
+ _print(QString("<td><span id=\"%5\">%1</span> <a onclick=\"refreshVarValue(this.href, '%5'); return false;\" href=\"%2%3/%4/refresh_value/\"><img border=\"0\" style=\"margin-bottom: -3px;\" src=\"" VAR_IMG_URL_BASE "arrow_refresh.png\" /></a></td>").arg(tmpVar.getFloatValue(conn)).arg(documentRoot()).arg(node.getAddr()).arg(name).arg(tmpVar.getId()));
+ else
+ _print("<td></td>");
+
+ /* field pro barvu a pro zobrazeni ve spolecnem grafu, odkaz na detail */
+ if (vars_form[color_field.arg(name)] && vars_form[displ_field.arg(name)]) {
+ _print(vars_form.renderField(color_field.arg(name), tdTemplate, "", errTemplate));
+ _print(vars_form.renderField(displ_field.arg(name), tdTemplate, "", errTemplate));
+ _print(QString("<td><a href=\"%1%2/%3/\">Detail</a></td>").arg(documentRoot()).arg(node.getAddr()).arg(name));
+ } else
+ _print("<td></td><td></td><td></td>");
+
+ _print("</tr>\n");
+ }
+
+ _print("\t<tr><td colspan=\"7\"><input type=\"submit\" name =\"configure_vars\" value=\"Uložit\"></td></tr>\n"
+ "</table></form>\n");
+}
+
+void HtmlLayer::printVar(NodeVar &var, ValueCache &valueCache) {
+
+ _print(QString("<div class=\"title\"><span>%1 (historie hodnot)</span></div>").arg(var.getCustomDescription()));
+ QString filename = QString("%1-%2.png").arg(var.getNodeSN()).arg(var.getId());
+
+ QPair<GraphData, GraphData> values = valueCache.getValues(var.getNodeSN(), var.getId(), HISTORY_LEN);
+ Graph g1(values.first, var.getGraphColor(), Qt::SolidLine, false);
+ Graph g2(values.second, var.getGraphColor(), Qt::DashLine, false);
+
+ GraphPainter gp(QSize(VAR_IMG_WIDTH, VAR_IMG_HEIGHT), VAR_IMG_BORDER_TOP, VAR_IMG_BORDER_RIGHT, VAR_IMG_BORDER_BOTTOM, VAR_IMG_BORDER_LEFT);
+ gp.addGraph(g1);
+ gp.addGraph(g2);
+
+ QDateTime current_datetime = currentDateTime();
+ gp.drawGraphs(current_datetime.toTime_t() - HISTORY_LEN, current_datetime.toTime_t(), getTimeLabels(HISTORY_LEN));
+ gp.saveGraphs(QString(VAR_IMG_FILE_PATH).append(filename));
+
+ _print(QString("<img src=\"" VAR_IMG_URL_BASE "%1\" />\n").arg(filename));
+ if (values.first.size() > 0) {
+ _print("<table border=\"1\"><tr>\n");
+ for (int i = 0; i < values.first.size(); i++) {
+ _print(QString("\t<td width=\"30\">%1</td>\n").arg(values.first[i].y()));
+ }
+ _print("</tr></table>\n");
+ }
+}
+
+/* AJAX odezva */
+void HtmlLayer::printVarValueAjaxRespose(Node &node, NodeVar &var) {
+ if (var.isVisible() && var.isReadable()) {
+#ifndef TEST_RUN
+ ULOIConnection conn(node.getAddr());
+ _print(QString("%1").arg(var.getFloatValue(conn)));
+#else
+ _print(QString("%1").arg(getRandom()));
+#endif
+ }
+}
+
+/* XML download a upload */
+void HtmlLayer::printXMLDownload(NodeMap &nodes) {
+ QDomDocument doc;
+ QDomElement configElem = doc.createElement("configuration");
+
+ doc.appendChild(configElem);
+ configElem.appendChild(nodes.getXMLConfig(doc));
+
+ _print("Status: 200 OK\r\n");
+ _print("Pragma: no-cache\r\n");
+ _print("Content-Type: text/html; charset=UTF-8\r\n");
+ _print("Content-Disposition: attachment; filename=config.xml\r\n\r\n");
+ _print(doc.toString(4));
+}
+
+/* zpracovani dat od uzivatele */
+void HtmlLayer::processVarsConfig(NodeMap &nodes, Node &node, Form &form, CidPool &cidPool) {
+ QList<SelectOption> colorOptions = getColorOptions();
+ QList<SelectOption> onOffOptions = getOnOffOptions();
+ QList<SelectOption> slotOptions = nodes.getSlotOptions(node.getAddr());
+
+ QString descr_field("%1_description");
+ QString value_field("%1_value");
+ QString color_field("%1_color");
+ QString displ_field("%1_display");
+
+ /*******************************/
+ /*
+ Form form;
+
+ form.addField("first_name", new CharField("Jméno", true, "...vyplňte jméno..."));
+ form.addField("surname", new CharField("Příjmení", true, "...vyplňte příjmení..."));
+ form.addField("age", new CharInteger("Věk", true, 18));
+
+ if (request.method() == "POST") {
+
+ form.bindData(request.POST());
+ if (form.isValid()) {
+
+ QVariantMap cleaned_data = form.getCleanedDataRef();
+
+ }
+
+ }
+ */
+ /*******************************/
+
+ CidPool localCidCache;
+ ULOIConnection conn(node.getAddr());
+
+ /* vytvoreni formulare */
+ NodeVarIterator it = node.getIterator();
+ while (it.hasNext()) {
+ it.next();
+ NodeVar tmpVar = it.value();
+ QString name = tmpVar.getName();
+ if (!tmpVar.isVisible()) continue;
+
+ /* field pro popis */
+ form.addField(descr_field.arg(name), new CharField("", true, tmpVar.getCustomDescription()));
+
+ /* field pro hodnotu */
+ if (tmpVar.isWriteable()) {
+ if (tmpVar.getUserType() == "cid")
+ form.addField(value_field.arg(name), new CidField("", true, cidPool, localCidCache, tmpVar.getFloatValue(conn)));
+ else if (tmpVar.getUserType() == "bool")
+ form.addField(value_field.arg(name), new ChoiceField("", onOffOptions, true, QVariant(tmpVar.getFloatValue(conn)).toString()));
+ else if (tmpVar.getUserType() == "slot")
+ form.addField(value_field.arg(name), new ChoiceField("", slotOptions, false, QVariant(tmpVar.getFloatValue(conn)).toString()));
+ else if (tmpVar.getDecimalPlaces() > 0)
+ form.addField(value_field.arg(name), new FloatField("", true, tmpVar.getFloatValue(conn)));
+ else
+ form.addField(value_field.arg(name), new IntegerField("", true, tmpVar.getFloatValue(conn)));
+ }
+
+ /* field pro barvu a pro zobrazeni ve spolecnem grafu */
+ if (!tmpVar.isSystemVar() && tmpVar.isReadable()) {
+ form.addField(color_field.arg(name), new ChoiceField("", colorOptions, true, tmpVar.getGraphColor().name()));
+ form.addField(displ_field.arg(name), new BooleanField("", false, tmpVar.getCommonGraphDisplay()));
+ }
+ }
+
+ if (request.method() == "POST" && request.POST().contains("configure_vars")) {
+ form.bindData(request.POST());
+
+ if (form.isValid()) {
+ QVariantMap cleaned_data = form.getCleanedDataRef();
+ NodeVarMutableIterator it = node.getMutableIterator();
+ QByteArray qItemVal;
+ node.resetUsedCids();
+ while (it.hasNext()) {
+ it.next();
+ NodeVar &tmpVar = it.value();
+ QString name = tmpVar.getName();
+ if (!tmpVar.isVisible()) continue;
+
+ /* nastaveni popisu */
+ tmpVar.setCustomDescription(cleaned_data[descr_field.arg(name)].toString());
+
+ /* nastaveni hodnoty */
+// node.resetUsedCids();
+ if (cleaned_data.contains(value_field.arg(name))) {
+ float val = cleaned_data.value(value_field.arg(name)).toDouble();
+ if (tmpVar.getUserType() == "cid") {
+ if ((val == form[value_field.arg(name)]->getInitial().toDouble()) || tmpVar.setFloatValue(val, conn)) {
+ node.addUsedCid((int)val);
+ cidPool.freeCid(form[value_field.arg(name)]->getInitial().toInt());
+ cidPool.blockCid((int)val);
+ logToFile("CID nastaven");
+// } else if (tmpVar.setFloatValue(val, conn)) {
+// node.addUsedCid(val);
+// cidPool.freeCid(form[value_field.arg(name)]->getInitial().toInt());
+// cidPool.blockCid(val);
+// logToFile("CID nastaven");
+ } else
+ logToFile("chyba pri nastavovani CIDu");
+ } else if (val != form[value_field.arg(name)]->getInitial().toDouble())
+ tmpVar.setFloatValue(val, conn);
+ }
+
+ /* nastaveni barvy a zobrazeni ve spolecnem grafu */
+ if (cleaned_data.contains(color_field.arg(name)) && cleaned_data.contains(displ_field.arg(name))) {
+ tmpVar.setGraphColor(QColor(cleaned_data.value(color_field.arg(name)).toString()));
+ tmpVar.setCommonGraphDisplay(cleaned_data.value(displ_field.arg(name)).toBool());
+ }
+
+ it.setValue(tmpVar);
+ }
+ throw HttpRedirect("./");
+ }
+
+ }
+}
+
+void HtmlLayer::processNodeConfig(Node &node, Form &form) {
+ form.addField("node_name", new CharField("Název zařízení", true, node.getCustomName()));
+
+ if (request.method() == "POST" && request.POST().contains("configure_node")) {
+ form.bindData(request.POST());
+ if (form.isValid()) {
+ node.setCustomName(form.getCleanedDataRef()["node_name"].toString());
+ throw HttpRedirect("./");
+ }
+ }
+}
+
+/* chybova hlaseni */
+void HtmlLayer::invalidNode(NodeError err, int/* nodeAddr*/) {
+ _print(QString("<h2 class=\"error\">%1</h2>\n").arg(err.getErrorMsg()));
+}
+
+void HtmlLayer::invalidNodeVar(NodeVarError err, QString/* nodeVarName*/) {
+ _print(QString("<h2 class=\"error\">%1</h2>\n").arg(err.getErrorMsg()));
+}
+
+/* obecne funkce */
+void HtmlLayer::print(const QString &msg) {
+ _print(msg);
+}
+
+
+/* na miru udelany form field kvuli validaci unikatnosti CIDu */
+CidField::CidField(QString _label, bool _required, CidPool &_cidPool, CidPool &_localCidCache, QVariant _initial, QObject *parent)
+ : IntegerField(_label, _required, _initial, parent), cidPool(_cidPool), localCidCache(_localCidCache) {}
+
+QVariant CidField::clean(QVariant value) const {
+ QVariant retval = IntegerField::clean(value);
+ if (retval == initial)
+ return retval;
+ int tmp_cid_val = retval.toInt();
+ if (tmp_cid_val == 0)
+ return 0;
+ if (!cidPool.isFreeCid(tmp_cid_val))
+ throw ValidationError("Tento CID je již používán");
+ if (!localCidCache.isFreeCid(tmp_cid_val))
+ throw ValidationError("CID musí být unikátní");
+ localCidCache.blockCid(tmp_cid_val);
+ return retval;
+}
--- /dev/null
+# ifndef _HTML_LAYER_H
+# define _HTML_LAYER_H
+
+#include <stdlib.h>
+
+#include <QByteArray>
+#include <QPair>
+#include <QString>
+#include <QStringList>
+#include <QList>
+#include <QListIterator>
+#include <QDateTime>
+#include <QDomDocument>
+
+#include <fcgi_config.h>
+#include <fcgi_stdio.h>
+
+#include "defines.h"
+#include "utils.h"
+
+#include "node.h"
+#include "value_cache.h"
+#include "graph_painter.h"
+#include "http.h"
+#include "forms.h"
+
+typedef QList<QStringList> Crumbs;
+typedef QListIterator<QStringList> CrumbsIterator;
+
+class HtmlLayer {
+ private:
+ Crumbs crumbs;
+ QString buffer;
+ bool buffering;
+ HttpRequest request;
+
+ void _print(const QString &msg);
+
+ public:
+ HtmlLayer(HttpRequest &request);
+
+ /* buffer funkce */
+ void startBuffering();
+
+ void stopBuffering();
+
+ void printBuffer() const;
+
+ /* drobky */
+ void addCrumb(QString url, QString name);
+
+ void printCrumbs();
+
+ /* zakladni html funkce */
+ QString documentRoot() const;
+
+ void printHTTPHeaders();
+
+ void printHTTPRefreshHeaders(int seconds);
+
+ void printHTTPRedirectHeaders(QString location);
+
+ void printHTTP404Headers();
+
+ void print404Error();
+
+ void printDocumentStart();
+
+ void printDocumentEnd();
+
+ void printContentStart();
+
+ void printContentEnd();
+
+ void printEnvVars();
+
+ /* funkce pro prezentaci nodu */
+ void home(NodeMap &nodes, ValueCache &valueCache);
+
+ void printNodes(NodeMap &nodes);
+
+ void printNodesConfig(NodeMap &nodes);
+
+ void printNode(Node node);
+
+ void printVarsConfig(NodeMap &nodes, Node &node, CidPool &cidPool);
+
+ void printVar(NodeVar &var, ValueCache &valueCache);
+
+ /* AJAX odezva */
+ void printVarValueAjaxRespose(Node &node, NodeVar &var);
+
+ /* XML download a upload */
+ void printXMLDownload(NodeMap &nodes);
+
+ /* zpracovani dat od uzivatele */
+ void processVarsConfig(NodeMap &nodes, Node &node, Form &form, CidPool &cidPool);
+
+ void processNodeConfig(Node &node, Form &form);
+
+ /* chybova hlaseni */
+ void invalidNode(NodeError err, int nodeAddr);
+
+ void invalidNodeVar(NodeVarError err, QString nodeVarName);
+
+ /* obecne funkce */
+ void print(const QString &msg);
+};
+
+
+/* na miru udelany form field kvuli validaci unikatnosti CIDu */
+class CidField : public IntegerField {
+ private:
+ CidPool &cidPool;
+ CidPool &localCidCache;
+
+ public:
+ CidField(QString _label, bool _required, CidPool &_cidPool, CidPool &_localCidCache, QVariant _initial, QObject *parent=0);
+
+ virtual QVariant clean(QVariant value) const;
+};
+
+# endif
--- /dev/null
+
+#include "http.h"
+
+QString CRLF("\r\n");
+
+/* class UploadedFile */
+const UploadedFile &UploadedFile::sharedNull() {
+ static UploadedFile uf = UploadedFile(DUMMY_TYPE());
+ return uf;
+}
+
+UploadedFile::UploadedFile() {
+ *this = sharedNull();
+}
+
+UploadedFile::UploadedFile(QString _file_name, QString _content_type, int _file_size, const QByteArray &_content) {
+ d = new Data;
+ d->null = false;
+ d->file_name = _file_name;
+ d->content_type = _content_type;
+ d->file_size = _file_size;
+ d->content = _content;
+}
+
+
+/* class HttpRequest */
+void HttpRequest::parsePostData() {
+ QList<QPair<QByteArray, QByteArray> > queryItems;
+ QString content_type(getenv("CONTENT_TYPE"));
+ int content_length = QString(getenv("CONTENT_LENGTH")).toInt();
+ if (content_type.startsWith("multipart/form-data")) {
+ parseMultipartData(content_length, content_type);
+ } else {
+ if (content_length > 0) {
+ QByteArray buf_in;
+ buf_in.resize(content_length);
+ fread(buf_in.data(), 1, buf_in.size(), FCGI_stdin);
+ QUrl pseudoUrl(QString("/?").append(buf_in));
+ queryItems = pseudoUrl.encodedQueryItems();
+ for (int i = 0; i < queryItems.size(); i++) {
+ QString first = QUrl::fromPercentEncoding(queryItems[i].first).replace("+", "%20");
+ QString second = QUrl::fromPercentEncoding(queryItems[i].second).replace("+", "%20");
+ post_data.insert(QUrl::fromPercentEncoding(first.toUtf8()), QUrl::fromPercentEncoding(second.toUtf8()));
+ }
+ }
+ }
+}
+
+void HttpRequest::parseMultipartData(int content_length, QString content_type) {
+ QByteArray buf_in;
+ buf_in.resize(content_length);
+ if (fread(buf_in.data(), 1, buf_in.size(), FCGI_stdin) != (uint)content_length)
+ return;
+ QByteArray boundary_str = QString(content_type).mid(QString("multipart/form-data").size() + QString("; boundary=").size()).prepend("--").toAscii();
+ buf_in = buf_in.mid(boundary_str.size() + CRLF.size());
+ QList<QByteArray> content_parts;
+ int boundary_index;
+ while (true) {
+ boundary_index = buf_in.indexOf(boundary_str);
+ if (boundary_index == -1)
+ break;
+ content_parts.append(buf_in.left(boundary_index - CRLF.size()));
+ buf_in = buf_in.mid(boundary_index + boundary_str.size() + CRLF.size());
+ }
+ buf_in.clear();
+
+ for (int i = 0; i < content_parts.size(); i++)
+ parseContentPart(content_parts[i]);
+}
+
+void HttpRequest::parseContentPart(QByteArray &content_part) {
+ int crlf_pos = content_part.indexOf(CRLF);
+ QRegExp file_reg("^Content-Disposition: form-data; name=\"(.+)\"; filename=\"(.*)\"$");
+ QRegExp field_reg("^Content-Disposition: form-data; name=\"(.+)\"$");
+ if (file_reg.exactMatch(content_part.left(crlf_pos))) {
+ parseFileContent(file_reg.cap(1), file_reg.cap(2), content_part, crlf_pos + CRLF.size());
+ } else if (field_reg.exactMatch(content_part.left(crlf_pos))) {
+ parseFieldContent(field_reg.cap(1), content_part, crlf_pos + CRLF.size());
+ } else
+ return;
+}
+
+void HttpRequest::parseFileContent(QString field_name, QString file_name, QByteArray &content_part, int start_pos) {
+ int crlf_pos = content_part.indexOf(CRLF, start_pos);
+ QRegExp content_type_reg("^Content-Type: (.+)$");
+ if (!content_type_reg.exactMatch(content_part.mid(start_pos, crlf_pos - start_pos)))
+ return;
+ QString content_type = content_type_reg.cap(1);
+ content_part = content_part.mid(crlf_pos + 2 * CRLF.size(), content_part.size() - crlf_pos - 2 * CRLF.size());
+ if (file_name != "") {
+// logToFile(QString("vytvarim soubor %1, size %2").arg(file_name).arg(content_part.size()));
+ files_data.insert(field_name, UploadedFile(file_name, content_type, content_part.size(), content_part));
+// logToFile(QString("vytvoren soubor %1").arg(file_name));
+ }
+}
+
+void HttpRequest::parseFieldContent(QString field_name, QByteArray &content_part, int start_pos) {
+ QString content = content_part.mid(start_pos + CRLF.size(), content_part.size() - start_pos - CRLF.size());
+ post_data.insert(field_name, content);
+}
+
+
+HttpRequest::HttpRequest() {
+ QUrl requestUrl(getenv("REQUEST_URI"));
+ _path = requestUrl.path();
+ _method = getenv("REQUEST_METHOD");
+ QList<QPair<QByteArray, QByteArray> > queryItems = requestUrl.encodedQueryItems();
+ for (int i = 0; i < queryItems.size(); i++) {
+ QString first = QUrl::fromPercentEncoding(queryItems[i].first);
+ QString second = QUrl::fromPercentEncoding(queryItems[i].second);
+ get_data.insert(QUrl::fromPercentEncoding(first.toUtf8()), QUrl::fromPercentEncoding(second.toUtf8()));
+ }
+ parsePostData();
+
+// QMapIterator<QString, QString> it(post_data);
+// while (it.hasNext()) {
+// it.next();
+// logToFile(QString("POST --- KEY: %1, VAL %2").arg(it.key(), it.value()));
+// }
+// QMapIterator<QString, UploadedFile> itf(files_data);
+// while (itf.hasNext()) {
+// itf.next();
+// logToFile(QString("FILES --- KEY: %1, VAL %2, SIZE %3").arg(itf.key(), itf.value().fileName()).arg(itf.value().size()));
+// logToFile(QString("CCCCCCC\n%1").arg(QString(itf.value().contentRef())));
+// }
+}
--- /dev/null
+
+# ifndef _HTTP_H
+# define _HTTP_H
+
+#include <stdlib.h>
+
+#include <QSharedData>
+#include <QSharedDataPointer>
+#include <QVariant>
+#include <QUrl>
+#include <QString>
+#include <QByteArray>
+#include <QMap>
+#include <QRegExp>
+
+#include <fcgi_config.h>
+#include <fcgi_stdio.h>
+
+#include "utils.h"
+
+class UploadedFile : public QVariant {
+ private:
+ struct Data : public QSharedData {
+ bool null;
+ QString file_name;
+ QString content_type;
+ int file_size;
+ QByteArray content;
+ Data(): null(true), file_name(""), content_type(""), file_size(0), content("") {};
+ };
+ QSharedDataPointer<Data> d;
+
+ class DUMMY_TYPE {};
+
+ static const UploadedFile& sharedNull();
+
+ UploadedFile(DUMMY_TYPE) { d = new Data; };
+
+ public:
+ UploadedFile();
+
+ UploadedFile(QString _file_name, QString _content_type, int _file_size, const QByteArray &_content);
+
+ QString fileName() const { return d->file_name; }
+
+ QString contentType() const { return d->content_type; }
+
+ int size() const { return d->file_size; }
+
+ const QByteArray &contentRef() const { return d->content; }
+
+ bool isNull() { return d->null; }
+};
+Q_DECLARE_METATYPE(UploadedFile)
+
+
+typedef QMap<QString, QString> QueryDict;
+typedef QMap<QString, UploadedFile> FilesDict;
+
+class HttpRedirect {
+ private:
+ QString url;
+
+ public:
+ HttpRedirect(QString _url): url(_url) {}
+
+ QString getUrl() const {
+ return url;
+ }
+};
+
+class HttpRequest {
+ private:
+ QString _path;
+ QString _method;
+ QueryDict post_data;
+ QueryDict get_data;
+ FilesDict files_data;
+
+ void parsePostData();
+
+ void parseMultipartData(int content_length, QString content_type);
+
+ void parseContentPart(QByteArray &content_part);
+
+ void parseFileContent(QString field_name, QString file_name, QByteArray &content_part, int start_pos);
+
+ void parseFieldContent(QString field_name, QByteArray &content_part, int start_pos);
+
+ public:
+ HttpRequest();
+
+ QString path() const {
+ return this->_path;
+ }
+
+ QString method() const {
+ return this->_method;
+ }
+
+ const QueryDict &GET() const {
+ return this->get_data;
+ }
+
+ const QueryDict &POST() const {
+ return this->post_data;
+ }
+
+ const FilesDict &FILES() const {
+ return this->files_data;
+ }
+};
+
+// class HttpResponse() {
+//
+// };
+
+# endif
--- /dev/null
+/****************************************************************************
+** Meta object code from reading C++ file 'forms.h'
+**
+** Created: Wed Feb 4 01:02:31 2009
+** by: The Qt Meta Object Compiler version 59 (Qt 4.4.3)
+**
+** WARNING! All changes made in this file will be lost!
+*****************************************************************************/
+
+#include "forms.h"
+#if !defined(Q_MOC_OUTPUT_REVISION)
+#error "The header file 'forms.h' doesn't include <QObject>."
+#elif Q_MOC_OUTPUT_REVISION != 59
+#error "This file was generated using the moc from 4.4.3. It"
+#error "cannot be used with the include files from this version of Qt."
+#error "(The moc has changed too much.)"
+#endif
+
+QT_BEGIN_MOC_NAMESPACE
+static const uint qt_meta_data_Widget[] = {
+
+ // content:
+ 1, // revision
+ 0, // classname
+ 0, 0, // classinfo
+ 0, 0, // methods
+ 0, 0, // properties
+ 0, 0, // enums/sets
+
+ 0 // eod
+};
+
+static const char qt_meta_stringdata_Widget[] = {
+ "Widget\0"
+};
+
+const QMetaObject Widget::staticMetaObject = {
+ { &QObject::staticMetaObject, qt_meta_stringdata_Widget,
+ qt_meta_data_Widget, 0 }
+};
+
+const QMetaObject *Widget::metaObject() const
+{
+ return &staticMetaObject;
+}
+
+void *Widget::qt_metacast(const char *_clname)
+{
+ if (!_clname) return 0;
+ if (!strcmp(_clname, qt_meta_stringdata_Widget))
+ return static_cast<void*>(const_cast< Widget*>(this));
+ return QObject::qt_metacast(_clname);
+}
+
+int Widget::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+ _id = QObject::qt_metacall(_c, _id, _a);
+ if (_id < 0)
+ return _id;
+ return _id;
+}
+static const uint qt_meta_data_Field[] = {
+
+ // content:
+ 1, // revision
+ 0, // classname
+ 0, 0, // classinfo
+ 0, 0, // methods
+ 0, 0, // properties
+ 0, 0, // enums/sets
+
+ 0 // eod
+};
+
+static const char qt_meta_stringdata_Field[] = {
+ "Field\0"
+};
+
+const QMetaObject Field::staticMetaObject = {
+ { &QObject::staticMetaObject, qt_meta_stringdata_Field,
+ qt_meta_data_Field, 0 }
+};
+
+const QMetaObject *Field::metaObject() const
+{
+ return &staticMetaObject;
+}
+
+void *Field::qt_metacast(const char *_clname)
+{
+ if (!_clname) return 0;
+ if (!strcmp(_clname, qt_meta_stringdata_Field))
+ return static_cast<void*>(const_cast< Field*>(this));
+ return QObject::qt_metacast(_clname);
+}
+
+int Field::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+ _id = QObject::qt_metacall(_c, _id, _a);
+ if (_id < 0)
+ return _id;
+ return _id;
+}
+static const uint qt_meta_data_Form[] = {
+
+ // content:
+ 1, // revision
+ 0, // classname
+ 0, 0, // classinfo
+ 0, 0, // methods
+ 0, 0, // properties
+ 0, 0, // enums/sets
+
+ 0 // eod
+};
+
+static const char qt_meta_stringdata_Form[] = {
+ "Form\0"
+};
+
+const QMetaObject Form::staticMetaObject = {
+ { &QObject::staticMetaObject, qt_meta_stringdata_Form,
+ qt_meta_data_Form, 0 }
+};
+
+const QMetaObject *Form::metaObject() const
+{
+ return &staticMetaObject;
+}
+
+void *Form::qt_metacast(const char *_clname)
+{
+ if (!_clname) return 0;
+ if (!strcmp(_clname, qt_meta_stringdata_Form))
+ return static_cast<void*>(const_cast< Form*>(this));
+ return QObject::qt_metacast(_clname);
+}
+
+int Form::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+ _id = QObject::qt_metacall(_c, _id, _a);
+ if (_id < 0)
+ return _id;
+ return _id;
+}
+QT_END_MOC_NAMESPACE
--- /dev/null
+
+#include "node.h"
+
+using namespace std;
+
+/*class CidPool */
+void CidPool::blockCid(int cid) {
+ assignedCids.insert(cid);
+}
+
+void CidPool::freeCid(int cid) {
+ assignedCids.remove(cid);
+}
+
+void CidPool::freeCids(const QSet<int> &cids) {
+ assignedCids.subtract(cids);
+}
+
+bool CidPool::isFreeCid(int cid) const {
+ return (!assignedCids.contains(cid) || cid == 0);
+}
+
+QString CidPool::cidsToStr() const {
+ QString ret(" -- ");
+ QSetIterator<int> it(assignedCids);
+ while (it.hasNext()) {
+ ret.append(QString("%1 -- ").arg(it.next()));
+ }
+ return ret;
+}
+
+/* instance CidPoolu */
+CidPool cidPool;
+
+
+/* ULOIConnection */
+ULOIConnection::ULOIConnection(int addr) {
+// if (_coninfo != NULL)
+// uloi_close(_coninfo);
+
+ int num_tries = 1;
+ while (num_tries < 4) {
+ _coninfo = uloi_open((char*)UL_DEV_NAME, addr, 0x10, 0, 50);
+ if (!_coninfo) {
+ logToFile(QString("[WW] - Chyba pri otevirani objektoveho rozhrani nodu %1..., try %2").arg(addr).arg(num_tries));
+ _coninfo = NULL;
+ } else
+ break;
+ num_tries++;
+ }
+}
+
+ULOIConnection::~ULOIConnection() {
+ if (_coninfo)
+ uloi_close(_coninfo);
+ _coninfo = NULL;
+}
+
+uloi_coninfo_t *ULOIConnection::coninfo() const {
+ return _coninfo;
+}
+
+
+/* class NodeVar */
+const NodeVar &NodeVar::sharedNull() {
+ static NodeVar nv = NodeVar(DUMMY_TYPE());
+ return nv;
+}
+
+bool NodeVar::setFloatValue(float val, const ULOIConnection &conn) const {
+#ifndef TEST_RUN
+ int retval, vallen, ival;
+ logToFile(QString("nastavuji hodnotu %1 konverze na %2").arg(val).arg((int)(val * pow(10.0, (double)getDecimalPlaces()))));
+ if (!conn.coninfo()) {
+ logToFile("neni coninfo");
+ return false;
+ }
+ ival = (int)(val * pow(10.0, (double)getDecimalPlaces()));
+ vallen = 2;
+ logToFile(QString("nastavuji var ID %1, VAL %2, iVAL %3").arg(getId()).arg(val).arg(ival));
+ retval = uloi_set_var(conn.coninfo(), getId(), &ival, vallen);
+ logToFile(QString("nastavena var, ret = %1").arg(retval));
+// usleep(10);
+ return (retval<0)?false:true;
+#else
+ return true;
+#endif
+}
+
+float NodeVar::getFloatValue(const ULOIConnection &conn) const {
+#ifndef TEST_RUN
+ if (!conn.coninfo())
+ return 0.0;
+ int retval = 0, vallen, state;
+ vallen = 2;
+ state = uloi_get_var(conn.coninfo(), getId(), &retval, vallen);
+ if (state < 0) {
+ return 0.0;
+ }
+ if (retval & 0x8000) retval |= ~0xffff; else retval &= 0xffff;
+ return ((float)retval) / pow(10.0, (double)getDecimalPlaces());
+#else
+ return 666.0;
+#endif
+}
+
+NodeVar::NodeVar() {
+ *this = sharedNull();
+}
+
+NodeVar::NodeVar(int varId, int nodeAddr, long node_sn, QString const &name, QString const &typeStr, bool readable, bool writeable) {
+ d = new Data;
+ d->varId = varId;
+ d->nodeAddr = nodeAddr;
+ d->node_sn = node_sn;
+ d->name = name;
+ QList<QString> parsedType = typeStr.split("/");
+ d->type = parsedType[0];
+
+ if (parsedType.size() > 1 && parsedType[1].startsWith("."))
+ d->decimalPlaces = parsedType[1].mid(1).toInt();
+ else
+ d->decimalPlaces = 0;
+
+ if (parsedType.size() > 1 && !parsedType.last().startsWith("."))
+ d->userType = parsedType.last();
+ else
+ d->userType = "";
+
+ d->readable = readable;
+ d->writeable = writeable;
+}
+
+bool NodeVar::isSystemVar() const {
+ if (this->getUserType() == "cid") return true;
+ if (this->getUserType() == "slot") return true;
+ if (this->getName() == "PERIOD") return true;
+ return !(this->isVisible());
+}
+
+bool NodeVar::isVisible() const {
+ if (this->getName() == "STATUS" || this->getName() == "ERRCLR") return false;
+ return true;
+}
+
+QDomElement NodeVar::getXMLConfig(QDomDocument &doc, const ULOIConnection &conn) const {
+ QDomElement varElem = doc.createElement("var");
+ varElem.setAttribute("oid", QVariant(getId()).toString());
+
+ QDomElement customDescrElem = doc.createElement("customDescription");
+ QDomElement colorElem = doc.createElement("color");
+ QDomElement commonGraphElem = doc.createElement("commonGraphDisplay");
+
+ customDescrElem.appendChild(doc.createTextNode(getCustomDescription()));
+ colorElem.appendChild(doc.createTextNode(getGraphColor().name()));
+ commonGraphElem.appendChild(doc.createTextNode(QVariant(getCommonGraphDisplay()).toString()));
+
+ varElem.appendChild(customDescrElem);
+ varElem.appendChild(colorElem);
+ varElem.appendChild(commonGraphElem);
+#ifndef TEST_RUN
+ if (isReadable() && isWriteable()) {
+ QDomElement valueElem = doc.createElement("value");
+ valueElem.appendChild(doc.createTextNode(QVariant(getFloatValue(conn)).toString()));
+ varElem.appendChild(valueElem);
+ }
+#endif
+ return varElem;
+}
+
+void NodeVar::setXMLConfig(const QDomElement &conf, const ULOIConnection &conn, QSet<int> &usedCids) {
+ QDomElement customDescrElem = conf.firstChildElement("customDescription");
+ if (!customDescrElem.isNull()) {
+ setCustomDescription(customDescrElem.text());
+ }
+
+ QDomElement colorElem = conf.firstChildElement("color");
+ if (!colorElem.isNull()) {
+ QColor color(colorElem.text());
+ if (color.isValid())
+ setGraphColor(color);
+ }
+
+ QDomElement commonGraphElem = conf.firstChildElement("commonGraphDisplay");
+ if (!commonGraphElem.isNull()) {
+ bool commonGraphDisplay = QVariant(commonGraphElem.text()).toBool();
+ setCommonGraphDisplay(commonGraphDisplay);
+ }
+#ifndef TEST_RUN
+ if (isReadable() && isWriteable()) {
+ QDomElement valueElem = conf.firstChildElement("value");
+ if (!valueElem.isNull()) {
+ bool succ;
+ float value = valueElem.text().toFloat(&succ);
+ if (succ) {
+ if (getUserType() == "cid") {
+ int actual_cid = getFloatValue(conn);
+ if (cidPool.isFreeCid((int)value) && setFloatValue(value, conn)) {
+ cidPool.freeCid(actual_cid);
+ cidPool.blockCid((int)value);
+ usedCids.remove(actual_cid);
+ usedCids.insert((int)value);
+ }
+ } else {
+ setFloatValue(value, conn);
+ }
+ }
+ }
+ }
+#endif
+}
+
+
+/* class Node */
+// const Node& Node::sharedNull() {
+// static Node n = Node(DUMMY_TYPE());
+// return n;
+// }
+
+// Node::Node() {
+// *this = sharedNull();
+// }
+
+Node::Node(int addr, long sn) {
+// d = new Data;
+ d = &_d;
+ refreshLastUpdate();
+ d->addr = addr;
+ d->sn = sn;
+ d->idStr = QString("zarizeni %1").arg(sn);
+
+ logToFile(QString("[II] zadam o info na adresu %1 a zakladam nod...").arg(addr));
+
+#ifndef TEST_RUN
+ ULOIConnection conn(getAddr());
+ int ret, i, *oids;
+#endif
+
+#ifdef TEST_RUN
+ registerVar(1, (uchar*)"TEMPERATURE;s2/.2", true);
+ registerVar(2, (uchar*)"TEMPERATURE_CID;u2/cid", true);
+ registerVar(2, (uchar*)"TEMPERATURE_CID;u2/cid", false);
+ registerVar(3, (uchar*)"PERIOD;u2", true);
+ registerVar(3, (uchar*)"PERIOD;u2", false);
+ registerVar(4, (uchar*)"STATUS;u2", true);
+ registerVar(5, (uchar*)"FAN;u2/bool", true);
+ registerVar(5, (uchar*)"FAN;u2/bool", false);
+ registerVar(6, (uchar*)"FAN_SLOT;u2/slot", true);
+ registerVar(6, (uchar*)"FAN_SLOT;u2/slot", false);
+#else
+ do {
+ if (!conn.coninfo()) {
+ logToFile("[WW] - Chyba pri otevirani objektoveho rozhrani...");
+ break;
+ }
+ ret = uloi_get_oids(conn.coninfo(), ULOI_QOIO, &oids);
+ if (ret < 0) {
+ logToFile("[WW] - Chyba pri ziskavani promennych pro cteni...");
+ break;
+ }
+ for (i = 0; i < ret; i++) { // nacteni promennych pro cteni
+ uchar *despack = NULL;
+ if (uloi_get_oiddes(conn.coninfo(), ULOI_DOIO, oids[i], &despack) >= 0) {
+ registerVar(oids[i], despack, true);
+ if (despack) free(despack);
+ }
+ }
+ free(oids);
+ ret = uloi_get_oids(conn.coninfo(), ULOI_QOII, &oids);
+ if (ret < 0) {
+ logToFile("[WW] - Chyba pri ziskavani promennych pro zapis...");
+ break;
+ }
+ for (i=0; i < ret; i++) { // nacteni promennych pro zapis
+ uchar *despack=NULL;
+ if (uloi_get_oiddes(conn.coninfo(), ULOI_DOII, oids[i], &despack) >= 0) {
+ registerVar(oids[i], despack, false);
+ if (despack) free(despack);
+ }
+ }
+ free(oids);
+ } while (0);
+#endif
+ logToFile(QString("[II] zalozen nod na adrese %1...").arg(addr));
+}
+
+NodeVar Node::getVar(QString name) const {
+ if (d->vars.contains(name)) {
+ return d->vars[name];
+ } else {
+ logToFile("hazim neex. promennou");
+ throw NodeVarError("Neplatny nazev promenne");
+ }
+}
+
+NodeVar &Node::getVarRef(QString name) {
+ if (d->vars.contains(name)) {
+ return d->vars[name];
+ } else {
+ logToFile("hazim neex. promennou ref");
+ throw NodeVarError("Neplatny nazev promenne");
+ }
+}
+
+void Node::registerVar(int oid, uchar *despack, bool isReadVar) {
+#ifdef TEST_RUN
+ QString pack((char*)despack);
+ QStringList parsed_pack = pack.split(";");
+ QByteArray ba_name = parsed_pack[0].toUtf8();
+ QByteArray ba_type = parsed_pack[1].toUtf8();
+ char *desname = ba_name.data();
+ char *destype = ba_type.data();
+#else
+ char *desname = uloi_oiddespack_strdup(despack,0);
+ char *destype = uloi_oiddespack_strdup(despack,1);
+#endif
+ if (desname){
+ if (isReadVar) {
+ if (d->vars.contains(desname)) {
+ NodeVar tmp = d->vars.value(desname);
+ tmp.setReadable(true);
+ d->vars.insert(desname, tmp);
+ } else {
+ d->vars.insert(desname, NodeVar(oid, getAddr(), getSN(), desname, destype, true, false));
+ }
+ } else {
+ if (d->vars.contains(desname)) {
+ NodeVar tmp = (d->vars.value(desname));
+ tmp.setWriteable(true);
+ d->vars.insert(desname, tmp);
+ } else {
+ d->vars.insert(desname, NodeVar(oid, getAddr(), getSN(), desname, destype, false, true));
+ }
+ }
+#ifndef TEST_RUN
+ free(desname);
+#endif
+ }
+#ifndef TEST_RUN
+ if (destype) free(destype);
+#endif
+}
+
+NodeVar Node::hasCid(int cid) const {
+ NodeVarIterator it = getIterator();
+ ULOIConnection conn(getAddr());
+ while (it.hasNext()) {
+ it.next();
+ NodeVar tmpVar = it.value();
+ if (tmpVar.getUserType() != "cid") continue;
+#ifndef TEST_RUN
+ if ((int)tmpVar.getFloatValue(conn) != cid) continue;
+#endif
+ QString trgtVarName = tmpVar.getName().left(tmpVar.getName().size() - 4);
+ if (this->hasVar(trgtVarName)) {
+// return this->getVar(trgtVarName).getId();
+ return this->getVar(trgtVarName);
+ }
+ }
+ throw NodeVarError("promenna neexistuje");
+}
+
+NodeVarIterator Node::getIterator() const {
+ return NodeVarIterator(d->vars);
+}
+
+NodeVarMutableIterator Node::getMutableIterator() {
+ return NodeVarMutableIterator(d->vars);
+}
+
+QDomElement Node::getXMLConfig(QDomDocument &doc) const {
+ ULOIConnection conn(getAddr());
+
+ QDomElement nodeElem = doc.createElement("node");
+ nodeElem.setAttribute("sn", QVariant((qlonglong)getSN()).toString());
+
+ QDomElement customNameElem = doc.createElement("customName");
+ QDomElement varsElem = doc.createElement("vars");
+
+ customNameElem.appendChild(doc.createTextNode(getCustomName()));
+ NodeVarIterator it = getIterator();
+ while (it.hasNext()) {
+ it.next();
+ varsElem.appendChild(it.value().getXMLConfig(doc, conn));
+ }
+
+ nodeElem.appendChild(customNameElem);
+ nodeElem.appendChild(varsElem);
+
+ return nodeElem;
+}
+
+void Node::setXMLConfig(const QDomElement &conf) {
+ ULOIConnection conn(getAddr());
+
+ QDomElement customNameElem = conf.firstChildElement("customName");
+ if (!customNameElem.isNull())
+ setCustomName(customNameElem.text());
+
+ QDomElement varsElem = conf.firstChildElement("vars");
+ if (varsElem.isNull())
+ return;
+ QDomElement varElem = varsElem.firstChildElement("var");
+ bool succ;
+ while (!varElem.isNull()) {
+ int oid = varElem.attribute("oid").toInt(&succ);
+ if (succ) {
+ NodeVarMutableIterator it = getMutableIterator();
+ while (it.hasNext()) {
+ it.next();
+ if (it.value().getId() == oid) {
+ it.value().setXMLConfig(varElem, conn, d->usedCids);
+ break;
+ }
+ }
+ }
+ varElem = varElem.nextSiblingElement("var");
+ }
+}
+
+
+/* class NodeMap */
+// ::Node NodeMap::getNode(int addr) const {
+// if (this->contains(addr)) {
+// return this->value(addr);
+// } else {
+// logToFile("hazim neex. node");
+// throw NodeError("Neplatne zarizeni");
+// }
+// }
+
+::Node &NodeMap::getNodeRef(int addr) {
+// static QMutex m;
+ if (this->contains(addr)) {
+// logToFile("chci to zamknout");
+// m.lock();
+// logToFile("je to zamceny");
+ ::Node *tmpNode = (*this)[addr];
+// logToFile("chci to odemknout");
+// m.unlock();
+ return *tmpNode;
+// return nd;
+ } else {
+ logToFile("hazim neex. node ref");
+ throw NodeError("Neplatne zarizeni");
+ }
+}
+
+// const NodeMapIterator NodeMap::getIterator() const {
+// return NodeMapIterator(*this);
+// }
+
+// const NodeMapMutableIterator NodeMap::getMutableIterator() {
+// return NodeMapMutableIterator(*this);
+// }
+
+QList< QPair<QString, QString> > NodeMap::getSlotOptions(int excludeAddr) const {
+ QList< QPair<QString, QString> > slotOptions;
+ NodeMapIterator it(*this);
+ while (it.hasNext()) {
+ it.next();
+ if (it.key() == excludeAddr)
+ continue;
+ const ::Node &tmpNode = *it.value();
+ NodeVarIterator itv = tmpNode.getIterator();
+ ULOIConnection conn(tmpNode.getAddr());
+ while (itv.hasNext()) {
+ itv.next();
+ const NodeVar &tmpVar = itv.value();
+ if (tmpVar.getUserType() == "cid" && tmpVar.isReadable()) {
+ int cid_val = tmpVar.getFloatValue(conn);
+ if (cid_val != 0) {
+ QString optLabel = QString("%1 - %2").arg(tmpNode.getCustomName(), tmpVar.getCustomDescription());
+ slotOptions.append(QPair<QString, QString>(QVariant(cid_val).toString(), optLabel));
+ }
+ }
+ }
+ }
+ return slotOptions;
+}
+
+QDomElement NodeMap::getXMLConfig(QDomDocument &doc) const {
+ QDomElement nodesElem = doc.createElement("nodes");
+ NodeMapIterator it(*this);
+ while (it.hasNext()) {
+ it.next();
+ nodesElem.appendChild(it.value()->getXMLConfig(doc));
+ }
+ return nodesElem;
+}
+
+void NodeMap::setXMLConfig(const QDomElement &conf) {
+ QDomElement nodeElem = conf.firstChildElement("node");
+ bool succ;
+ while (!nodeElem.isNull()) {
+ long sn = nodeElem.attribute("sn").toLong(&succ);
+ if (succ) {
+ NodeMapMutableIterator it(*this);
+ while (it.hasNext()) {
+ it.next();
+ if (sn == it.value()->getSN()) {
+ it.value()->setXMLConfig(nodeElem);
+ break;
+ }
+ }
+ }
+ nodeElem = nodeElem.nextSiblingElement("node");
+ }
+}
+
--- /dev/null
+# ifndef _NODE_H
+# define _NODE_H
+
+#include <stdlib.h>
+#include <cmath>
+
+#include <QString>
+#include <QStringList>
+#include <QUrl>
+#include <QListIterator>
+#include <QMap>
+#include <QMapIterator>
+#include <QMutableMapIterator>
+#include <QMutex>
+#include <QSharedDataPointer>
+#include <QTime>
+#include <QDateTime>
+#include <QSet>
+#include <QMutableSetIterator>
+#include <QColor>
+#include <QDomDocument>
+
+#include <QtSql>
+
+#include <fcgi_stdio.h>
+
+#include <ul_lib/ulan.h>
+#include "defines.h"
+#include "utils.h"
+
+class CidPool {
+ private:
+ QSet<int> assignedCids;
+
+ public:
+ CidPool(int reserve=50) {
+ assignedCids.reserve(reserve);
+ }
+
+ void blockCid(int cid);
+
+ void freeCid(int cid);
+
+ void freeCids(const QSet<int> &cids);
+
+ bool isFreeCid(int cid) const;
+
+ QString cidsToStr() const;
+};
+
+class ULOIConnection {
+ private:
+ uloi_coninfo_t *_coninfo;
+
+ public:
+ ULOIConnection(int addr);
+
+ ~ULOIConnection();
+
+ uloi_coninfo_t *coninfo() const;
+};
+
+class NodeVar {
+ private:
+ struct Data : public QSharedData {
+ int varId;
+ int nodeAddr;
+ long node_sn;
+ QString name;
+ QString type;
+ int decimalPlaces;
+ QString userType;
+ bool readable;
+ bool writeable;
+ QString customDescription;
+ QColor graphColor;
+ bool commonGraphDisplay;
+ Data(): nodeAddr(0), node_sn(0), readable(true), writeable(false), customDescription(""), graphColor(Qt::red), commonGraphDisplay(false) {};
+ };
+ QSharedDataPointer<Data> d;
+
+ class DUMMY_TYPE {};
+
+ static const NodeVar& sharedNull();
+
+ NodeVar(DUMMY_TYPE) { d = new Data; };
+
+ public:
+ NodeVar();
+
+ NodeVar(int varId, int nodeAddr, long node_sn, QString const &name, QString const &typeStr, bool readable=true, bool writeable=false);
+
+ int getId() const {
+ return d->varId;
+ }
+
+ QString getName() const {
+ return d->name;
+ }
+
+ QString getType() const {
+ return d->type;
+ }
+
+ int getDecimalPlaces() const {
+ return d->decimalPlaces;
+ }
+
+ QString getUserType() const {
+ return d->userType;
+ }
+
+ long getNodeSN() const {
+ return d->node_sn;
+ }
+
+ bool isReadable() const {
+ return d->readable;
+ }
+
+ bool isWriteable() const {
+ return d->writeable;
+ }
+
+ QColor getGraphColor() const {
+ return d->graphColor;
+ }
+
+ bool getCommonGraphDisplay() const {
+ return d->commonGraphDisplay;
+ }
+
+ void setReadable(bool state) {
+ d->readable = state;
+ }
+
+ void setWriteable(bool state) {
+ d->writeable = state;
+ }
+
+ bool setFloatValue(float val, const ULOIConnection &conn) const;
+
+ float getFloatValue(const ULOIConnection &conn) const;
+
+ QString getCustomDescription() const {
+ if (d->customDescription == "")
+ return d->name;
+ return d->customDescription;
+ }
+
+ void setCustomDescription(QString descr) {
+ d->customDescription = descr;
+ }
+
+ void setGraphColor(QColor color) {
+ d->graphColor = color;
+ }
+
+ void setCommonGraphDisplay(bool display) {
+ d->commonGraphDisplay = display;
+ }
+
+ bool isSystemVar() const;
+
+ bool isVisible() const;
+
+ QDomElement getXMLConfig(QDomDocument &doc, const ULOIConnection &conn) const;
+
+ void setXMLConfig(const QDomElement &conf, const ULOIConnection &conn, QSet<int> &usedCids);
+
+};
+// Q_DECLARE_METATYPE(NodeVar);
+
+typedef QMapIterator<QString, NodeVar> NodeVarIterator;
+typedef QMutableMapIterator<QString, NodeVar> NodeVarMutableIterator;
+
+class Node {
+ private:
+// struct Data : public QSharedData {
+ struct Data {
+ int addr;
+ long sn;
+ QString idStr;
+ QString customName;
+ QMap<QString, NodeVar> vars;
+ QDateTime lastUpdate;
+ QSet<int> usedCids;
+ Data(): addr(0), sn(0), lastUpdate(currentDateTime()) {};
+ };
+// QSharedDataPointer<Data> d;
+ Data _d, *d;
+
+// class DUMMY_TYPE {};
+
+// static const Node& sharedNull();
+
+// Node(DUMMY_TYPE) { d = new Data; };
+
+ public:
+ Node();
+
+ Node(int addr, long sn);
+
+ NodeVar getVar(QString name) const;
+
+ NodeVar &getVarRef(QString name);
+
+ /* nastavi promennou varName_PER na hodnotu period */
+ void setVarPeriod(QString varName, int period);
+
+ /* nastavi promennou varName_CID na hodnotu cid */
+ void setVarCid(QString varName, int cid);
+
+ /* zaregistruje novou promennou k tomuto nodu */
+ void registerVar(int oid, uchar *despack, bool isReadVar);
+
+ int getAddr() const {
+ return d->addr;
+ }
+
+ long getSN() const {
+ return d->sn;
+ }
+
+ QString getIdStr() const {
+ return d->idStr;
+ }
+
+ QString getCustomName() const {
+ if (d->customName == "")
+ return d->idStr;
+ return d->customName;
+ }
+
+ void setCustomName(QString name) {
+ d->customName = name;
+ }
+
+ /* vraci true, pokud tomto nodu existuje promenna varName */
+ bool hasVar(QString varName) const {
+ return d->vars.contains(varName);
+ }
+
+ /* pokud v tomto nodu existuje promenna s nastavenym CID == cid, vraci OID teto promenne, jinak vraci 0 */
+ NodeVar hasCid(int cid) const;
+
+ NodeVarIterator getIterator() const;
+
+ NodeVarMutableIterator getMutableIterator();
+
+ QDateTime getLastUpdate() const {
+ return d->lastUpdate;
+ }
+
+ void refreshLastUpdate() {
+ d->lastUpdate = currentDateTime();
+ }
+
+ void resetUsedCids() {
+ d->usedCids.clear();
+ }
+
+ void addUsedCid(int cid) {
+ d->usedCids.insert(cid);
+ }
+
+ const QSet<int> &getUsedCidsRef() const {
+ return d->usedCids;
+ }
+
+ QDomElement getXMLConfig(QDomDocument &doc) const;
+
+ void setXMLConfig(const QDomElement &conf);
+
+};
+// Q_DECLARE_METATYPE(Node);
+
+
+class NodeError {
+ private:
+ QString msg;
+ public:
+ NodeError(const QString &msg) { this->msg = msg; };
+
+ QString getErrorMsg() const {
+ return this->msg;
+ }
+};
+
+class NodeVarError {
+ private:
+ QString msg;
+ public:
+ NodeVarError(const QString &msg) { this->msg = msg; };
+
+ QString getErrorMsg() const {
+ return this->msg;
+ }
+};
+
+typedef QMapIterator<int, Node*> NodeMapIterator;
+typedef QMutableMapIterator<int, Node*> NodeMapMutableIterator;
+typedef QListIterator<int> NodeMapKeysIterator;
+
+class NodeMap : public QMap<int, Node*> {
+ public:
+ ~NodeMap() {
+ qDeleteAll(this->values());
+ }
+
+// ::Node getNode(int addr) const;
+
+ ::Node &getNodeRef(int addr);
+
+// const NodeMapIterator getIterator() const;
+
+// const NodeMapMutableIterator getMutableIterator();
+
+ QList< QPair<QString, QString> > getSlotOptions(int excludeAddr=0) const;
+
+ QDomElement getXMLConfig(QDomDocument &doc) const;
+
+ void setXMLConfig(const QDomElement &conf);
+
+};
+
+# endif
--- /dev/null
+CONFIG += qt
+
+QT += sql xml
+
+HEADERS += node.h uldy_server.h html_layer.h address_parser.h value_cache.h graph_painter.h http.h utils.h defines.h forms.h
+SOURCES += node.cc uldy_server.cc html_layer.cc address_parser.cc value_cache.cc graph_painter.cc http.cc utils.cc fcgi.cc forms.cc
+
+TARGET = hydroponie
+TEMPLATE = app
+
+INCLUDEPATH += ../_compiled/include/
+LIBS += -L../_compiled/lib -lfcgi -lulan
--- /dev/null
+#include "uldy_server.h"
+
+using namespace std;
+
+extern CidPool cidPool;
+
+bool AddressPool::blockAddress(long sn, int addr) {
+ if (!assignedAddrs.contains(sn) && !assignedAddrs.values().contains(addr)) {
+ assignedAddrs.insert(sn, addr);
+ holes.remove(addr);
+ }
+ return false;
+}
+
+int AddressPool::getFreeAddress(long sn) {
+// return 60; // DOCASNE
+ if (assignedAddrs.size() == MAX_ADDR) return 0;
+ int retval;
+ if (holes.size() == 0) {
+ retval = assignedAddrs.size() + 1;
+ } else {
+ QMutableSetIterator<int> it(holes);
+ it.next();
+ retval = it.value();
+ it.remove();
+ }
+ assignedAddrs.insert(sn, retval);
+ return retval;
+}
+
+void AddressPool::freeAddress(long sn) {
+// return; // DOCASNE
+ if (assignedAddrs.contains(sn)) {
+ int addr = assignedAddrs.value(sn);
+ if (addr != assignedAddrs.size())
+ holes.insert(addr);
+ assignedAddrs.remove(sn);
+ }
+}
+AddressPool addressPool;
+
+
+void ULDYServer::sendNewAddress(int addr, long sn) const {
+ int ret;
+ QByteArray buf_out;
+ ul_fd_t ul_fd = ul_open(UL_DEV_NAME, NULL);
+ if (ul_fd == UL_FD_INVALID) {
+ logToFile("[EE] ULDYSRV - chyba pri zasilani adresy: neplatny deskriptor...");
+ return;
+ }
+ buf_out.append(ULNCS_SET_ADDR); /* SN0 SN1 SN2 SN3 NEW_ADR */
+ buf_out += sn2buf(sn);
+ buf_out.append(addr);
+ ret = ul_send_command(ul_fd, 0, UL_CMD_NCS, UL_BFL_NORE, (uchar*)buf_out.constData(), buf_out.size()); //UL_BFL_ARQ
+// logToFile(QString("[II] odeslana zprava, status: %1, len: %2 data %3").arg(ret).arg(buf_out.size()).arg(buf_out.toHex().constData()));
+ ul_close(ul_fd);
+}
+
+void ULDYServer::requestIdentification(int addr) const {
+ int ret;
+ QByteArray buf_out;
+ ul_fd_t ul_fd = ul_open(UL_DEV_NAME, NULL);
+ if (ul_fd == UL_FD_INVALID) {
+ logToFile("[EE] ULDYSRV - chyba pri dotazu na identifikaci: neplatny deskriptor...");
+ return;
+ }
+ buf_out.append(ULNCS_SID_RQ);
+ ret = ul_send_command(ul_fd, addr, UL_CMD_NCS, UL_BFL_NORE, (uchar*)buf_out.constData(), buf_out.size()); //UL_BFL_ARQ
+ logToFile(QString("[II] odeslana zadost o identifikaci na adresu %1").arg(addr));
+ ul_close(ul_fd);
+}
+
+void ULDYServer::processPDOMessage(int saddr, int cid, int data) {
+// logToFile(QString("PDO msg: CID = %1, DATA = %2").arg(cid).arg(data));
+ if (nodes.contains(saddr)) {
+ Node &node = nodes.getNodeRef(saddr);
+ if (cid == HEARTBEAT_CID) {
+
+ logToFile(QString("[II] - HEARTBEAT from address %1").arg(saddr));
+ node.refreshLastUpdate();
+
+ } else {
+
+ try {
+ NodeVar tmpVar = node.hasCid(cid);
+ float fdata = ((float)data) / pow(10.0, (double)tmpVar.getDecimalPlaces());
+ valueCache.insertValue(node.getSN(), tmpVar.getId(), fdata);
+ } catch (NodeVarError) { }
+ node.refreshLastUpdate();
+
+ }
+ } else if (saddr != NOT_ASSIGNED_ADDR) {
+
+ requestIdentification(saddr);
+
+ }
+// logToFile(QString("PDO zpracovana %1").arg((unsigned long)QThread::currentThreadId()));
+}
+
+void ULDYServer::stopServer(void) {
+ logToFile("[II] ULDYSRV - stopping uldy server...");
+ this->running = false;
+}
+
+void ULDYServer::run() {
+ int ret;
+ int addr, saddr, msg_len;
+ long sn;
+ QByteArray buf_in;
+ ul_msginfo msginfo;
+
+ QTime timer;
+ timer.start();
+#ifdef TEST_RUN
+ Node *newNode = new Node(30, 102);
+ this->nodes.insert(30, newNode);
+
+ while (this->running) {
+ sleep(5);
+ int data = getRandom();
+ int cid = 16;
+ processPDOMessage(30, cid, data);
+ }
+#else
+ ul_fd_t ul_fd = ul_open(UL_DEV_NAME, NULL);
+ if (ul_fd == UL_FD_INVALID) {
+ logToFile("[EE] ULDYSRV - neplatny deskriptor");
+ return;
+ }
+
+ memset(&msginfo, 0, sizeof(ul_msginfo));
+ ul_addfilt(ul_fd, &msginfo);
+
+ logToFile("[II] ULDYSRV - cekam na zpravu...");
+
+ while (this->running) { // main loop
+
+ while ((ul_fd_wait(ul_fd, 1) <= 0) && this->running) ;
+
+ if ((ul_inepoll(ul_fd) > 0) && (ul_acceptmsg(ul_fd, &msginfo)) >= 0) {
+ if (msginfo.cmd == UL_CMD_NCS) {
+ msg_len = msginfo.len;
+ saddr = msginfo.sadr;
+ buf_in.resize(msg_len);
+ ret = ul_read(ul_fd, buf_in.data(), msg_len); // nacteni SN do bufferu
+// logToFile(QString("[II] prijata zprava, sadr: %1, dadr: %2, len: %3 data %4").arg(msginfo.sadr).arg(msginfo.dadr).arg(msginfo.len).arg(buf_in.toHex().constData()));
+ ul_freemsg(ul_fd);
+ switch ((uchar)buf_in[0]) {
+ case ULNCS_ADR_RQ:
+ sn = buf2sn(buf_in);
+ if (sn == -1) {
+ logToFile(QString("[WW] ULDYSRV - neplatna zadost o adresu, ocekavam delku minimalne 5").arg(msg_len));
+ break;
+ }
+// logToFile(QString("[II] prijmam zadost o adresu, SN %1").arg(sn));
+ if ((addr = addressPool.getFreeAddress(sn)) != 0) {
+ logToFile(QString("[II] ULDYSRV - sending new address \"%1\" to SN \"%2\"...").arg(addr).arg(sn));
+ if (!(this->nodes.contains(addr))) {
+ sendNewAddress(addr, sn);
+ Node *newNode = new Node(addr, sn);
+ this->nodes.insert(addr, newNode);
+ logToFile(QString("[II] mapa nodu nyni obsahuje %1 polozek...").arg(this->nodes.size()));
+ } else { logToFile("nod uz tam je"); }
+ } else {
+ logToFile("[WW] ULDYSRV - address pool is full, try again later, please...");
+ }
+ break;
+ case ULNCS_SID_RPLY:
+ sn = buf2sn(buf_in);
+ logToFile(QString("[II] - received identification from unknown node, addr %1").arg(saddr));
+ if (!(this->nodes.contains(saddr))) {
+ Node *newNode = new Node(saddr, sn);
+ addressPool.blockAddress(sn, saddr);
+ this->nodes.insert(saddr, newNode);
+ logToFile(QString("[II] mapa nodu nyni obsahuje %1 polozek...").arg(this->nodes.size()));
+ } else { logToFile("nod uz tam je"); }
+ break;
+
+ default:
+ break;
+ } /* switch */
+
+ } else if (msginfo.cmd == UL_CMD_PDO) {
+ msg_len = msginfo.len;
+ saddr = msginfo.sadr;
+ buf_in.resize(msg_len);
+ ret = ul_read(ul_fd, buf_in.data(), msg_len);
+ ul_freemsg(ul_fd);
+
+ buf_in = buf_in.mid(PDO_SKIP_BYTES);
+
+ while (1) {
+ bool success = true;
+
+ int cid = takeCid(buf_in, &success);
+ if (!success) break;
+
+ int len = takeLen(buf_in, &success);
+ if (!success) break;
+
+ int data = takeData(buf_in, len, &success);
+ if (!success) break;
+
+ processPDOMessage(saddr, cid, data);
+ }
+ } else
+ ul_freemsg(ul_fd);
+
+ } /* ul_inepool && ul_acceptmsg */
+
+ } /* while(running) */
+#endif
+}
+
+int ULDYServer::takeCid(QByteArray &buf, bool *success) const {
+ if (buf.size() < 2) { *success = false; /*logToFile("nedostatecna delka CID");*/ return 0; }
+ int ret = buf2uint16(buf);
+ buf = buf.mid(2);
+ *success = true;
+ return ret;
+}
+
+int ULDYServer::takeLen(QByteArray &buf, bool *success) const {
+// return takeCid(buf, success);
+ if (buf.size() < 2) { *success = false; /*logToFile("nedostatecna delka LEN");*/ return 0; }
+// int ret = buf[0];
+ int ret = buf2uint16(buf);
+ buf = buf.mid(2);
+ *success = true;
+ return ret;
+}
+
+int ULDYServer::takeData(QByteArray &buf, int len, bool *success) const {
+ if (buf.size() < len) { *success = false; return 0; }
+ int ret = 0;
+ for (int i = 0; i < len; i++) {
+ ret += (uchar)buf[i]<<(i * 8);
+ }
+ buf = buf.mid(len);
+ *success = true;
+ return ret;
+}
+
+const NodeMap &ULDYServer::getNodes() const {
+ return this->nodes;
+}
+
+NodeMap &ULDYServer::getNodesRef() {
+ return this->nodes;
+}
+
+ValueCache &ULDYServer::getValueCacheRef() {
+ return this->valueCache;
+}
+
+void ULDYServer::tryRemoveNodes() {
+ NodeMapMutableIterator it(this->nodes);
+ QDateTime curr, last;
+ while (it.hasNext()) {
+ it.next();
+ int addr = it.key();
+ curr = currentDateTime();
+ last = this->nodes.getNodeRef(addr).getLastUpdate();
+ last.setTimeSpec(Qt::UTC);
+ if ((curr.toTime_t() - last.toTime_t()) > NODE_CLEANER_PERIOD_SECS) {
+ logToFile(QString("[II] - Removing node SN %1...").arg(this->nodes.getNodeRef(addr).getSN()));
+ addressPool.freeAddress(this->nodes.getNodeRef(addr).getSN());
+ cidPool.freeCids(this->nodes.getNodeRef(addr).getUsedCidsRef());
+ Node *tmpNode = this->nodes.value(addr);
+ this->nodes.remove(addr);
+ delete tmpNode;
+ }
+ }
+}
+
--- /dev/null
+# ifndef _ULDY_SERVER_H
+# define _ULDY_SERVER_H
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <QByteArray>
+#include <QThread>
+
+#include <ul_lib/ulan.h>
+
+#include "node.h"
+#include "value_cache.h"
+#include "utils.h"
+#include "defines.h"
+
+// typedef QMap<long, uchar> AddressPool;
+// typedef QMutableMapIterator<long, uchar> AddressPoolMutableIterator;
+
+class AddressPool {
+ private:
+ QMap<long, int> assignedAddrs;
+ QSet<int> holes;
+
+ public:
+ AddressPool() {
+// assignedAddrs.reserve(MAX_ADDR);
+ holes.reserve(20);
+ }
+
+ bool blockAddress(long sn, int addr);
+
+ int getFreeAddress(long sn);
+
+ void freeAddress(long sn);
+};
+
+
+class ULDYServer : public QThread {
+ private:
+ bool running;
+ NodeMap nodes;
+ ValueCache valueCache;
+
+ void sendNewAddress(int addr, long sn) const;
+
+ void requestIdentification(int addr) const;
+
+ void processPDOMessage(int saddr, int cid, int data);
+
+ public:
+ ULDYServer(): running(true) {};
+
+ void stopServer();
+
+ void run();
+
+ int takeCid(QByteArray &buf, bool *success) const;
+
+ int takeLen(QByteArray &buf, bool *success) const;
+
+ int takeData(QByteArray &buf, int len, bool *success) const;
+
+ const NodeMap &getNodes() const;
+
+ NodeMap &getNodesRef();
+
+ ValueCache &getValueCacheRef();
+
+ void tryRemoveNodes();
+};
+
+# endif
--- /dev/null
+#include "utils.h"
+
+using namespace std;
+
+unsigned long buf2sn(const QByteArray &_buf) {
+ if (_buf.size() < 5) return -1;
+ const uchar *buf = (const uchar*)(_buf.constData()+1);
+ unsigned long l;
+ l = (unsigned long)buf[0];
+ l += (unsigned long)buf[1]<<8;
+ l += (unsigned long)buf[2]<<16;
+ l += (unsigned long)buf[3]<<24;
+ return l;
+}
+
+QByteArray sn2buf(unsigned long mod_sn) {
+ QByteArray ret_val;
+ ret_val.resize(4);
+ uchar *buf = (uchar*)(ret_val.data());
+ buf[0] = mod_sn>>0;
+ buf[1] = mod_sn>>8;
+ buf[2] = mod_sn>>16;
+ buf[3] = mod_sn>>24;
+ return ret_val;
+}
+
+int16_t buf2int16(const QByteArray &_buf) {
+ int i;
+ i = (uchar)_buf[0];
+// i += (int)_buf[1]<<8;
+ i = ((uchar)_buf[1]<<8) | i;
+ return (int16_t)i;
+}
+
+uint16_t buf2uint16(const QByteArray &_buf) {
+ return (uint16_t)buf2int16(_buf);
+}
+
+void logToFile(const QString &msg, bool end_new_line) {
+ FILE *log = fopen(LOG_FILENAME, "a");
+ int write;
+ if (log) {
+ QString now = currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
+ now.append(" - ");
+ QByteArray ba;
+ ba = now.toUtf8();
+ write = fwrite(ba.constData(), 1, now.length(), log);
+ ba = msg.toUtf8();
+ write = fwrite(ba.constData(), 1, msg.length(), log);
+ if (end_new_line)
+ write = fwrite("\n", 1, 1, log);
+ fclose(log);
+ }
+}
+
+void logDebug(const QByteArray &buf) {
+ FILE *debug_log = fopen("/home/bohacekm/fel/bap/hydroweb/src/log_debug.txt", "a");
+ int write;
+ write = fwrite(buf.constData(), 1, buf.size(), debug_log);
+ fclose(debug_log);
+}
+
+QDateTime currentDateTime() {
+ QDateTime curr_dtime = QDateTime::currentDateTime();
+// QDateTime curr_dtime;
+ curr_dtime.setTimeSpec(Qt::UTC);
+ return curr_dtime;
+}
+
+int getRandom() {
+
+ return sin(currentDateTime().toTime_t()) + log(qRound(RAND_MAX / (qrand() / 2.0)) * 5 + 1);
+}
+
+QList< QPair<QString, QString> > getColorOptions() {
+ QList< QPair<QString, QString> > colorOptions;
+ colorOptions.append(QPair<QString, QString>("#ff0000", "Červená"));
+ colorOptions.append(QPair<QString, QString>("#800000", "Tmavě červená"));
+ colorOptions.append(QPair<QString, QString>("#00ff00", "Zelená"));
+ colorOptions.append(QPair<QString, QString>("#008000", "Tmavě zelená"));
+ colorOptions.append(QPair<QString, QString>("#0000ff", "Modrá"));
+ colorOptions.append(QPair<QString, QString>("#000080", "Tmavě modrá"));
+ return colorOptions;
+}
+
+QList< QPair<QString, QString> > getOnOffOptions() {
+ QList< QPair<QString, QString> > onOffOptions;
+ onOffOptions.append(QPair<QString, QString>("0", "Vypnuto"));
+ onOffOptions.append(QPair<QString, QString>("1", "Zapnuto"));
+ return onOffOptions;
+}
+
+QList< QPair<double, QString> > getTimeLabels(int secs_ago) {
+ QDateTime ago_dtime = currentDateTime().addSecs(-secs_ago);
+ ago_dtime.setTimeSpec(Qt::UTC);
+ QDateTime start_dtime;
+ QString format_str;
+ int step;
+ if (secs_ago < 240) { /* po 10 sekundach */
+ format_str = "h:mm:ss";
+ step = 10;
+ start_dtime = ago_dtime.addSecs((60 - ago_dtime.time().second()) % 10);
+ } else if (secs_ago < 720) { /* po 1 minute */
+ format_str = "h:mm";
+ step = 60;
+ start_dtime = ago_dtime.addSecs((60 - ago_dtime.time().second()) % 60);
+ } else if (secs_ago < 7200) { /* po 10 minutach */
+ format_str = "h:mm";
+ step = 600;
+ start_dtime = ago_dtime.addSecs((60 - ago_dtime.time().second()) % 60);
+ start_dtime = start_dtime.addSecs(((60 - start_dtime.time().minute()) % 10) * 60);
+ } else if (secs_ago < 48 * 3600) { /* po 1 hodine */
+ format_str = "h:mm";
+ step = 3600;
+ start_dtime = ago_dtime.addSecs((60 - ago_dtime.time().second()) % 60);
+ start_dtime = start_dtime.addSecs(((60 - start_dtime.time().minute()) % 60) * 60);
+ } else { /* po 1 dni */
+ format_str = "d.M.";
+ step = 24 * 3600;
+ start_dtime = QDateTime(ago_dtime.date());
+ if (ago_dtime.time().second() || ago_dtime.time().minute() || ago_dtime.time().hour())
+ start_dtime = start_dtime.addDays(1);
+ }
+ start_dtime.setTimeSpec(Qt::UTC);
+ QList< QPair<double, QString> > ret_value;
+ int elapsed_secs = 0;
+ while (elapsed_secs <= (secs_ago - step)) {
+ ret_value.append(QPair<double, QString>(start_dtime.toTime_t(), start_dtime.toString(format_str)));
+ start_dtime = start_dtime.addSecs(step);
+ elapsed_secs += step;
+ }
+ return ret_value;
+}
--- /dev/null
+# ifndef _UTILS_H
+# define _UTILS_H
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <cmath>
+
+#include <QPair>
+#include <QByteArray>
+#include <QString>
+#include <QDateTime>
+
+#include <ul_lib/ulan.h>
+
+#include "defines.h"
+
+unsigned long buf2sn(const QByteArray &_buf);
+
+QByteArray sn2buf(unsigned long mod_sn);
+
+int16_t buf2int16(const QByteArray &_buf);
+
+uint16_t buf2uint16(const QByteArray &_buf);
+
+int takeCid(QByteArray &buf);
+
+int takeLen(QByteArray &buf);
+
+int takeData(QByteArray &buf, int len);
+
+void logToFile(const QString &msg, bool end_new_line=true);
+
+void logDebug(const QByteArray &buf);
+
+QDateTime currentDateTime();
+
+int getRandom();
+
+QList< QPair<QString, QString> > getColorOptions();
+
+QList< QPair<QString, QString> > getOnOffOptions();
+
+QList< QPair<double, QString> > getTimeLabels(int secs_ago);
+
+# endif
--- /dev/null
+
+#include "value_cache.h"
+
+#define SECS_PER_DAY 60*60*24
+
+// static uint toTime_tHelper(const QDate &utcDate, const QTime &utcTime)
+// {
+// int days = QDate(1970, 1, 1).daysTo(utcDate);
+// int secs = QTime().secsTo(utcTime);
+// if (days < 0 || (days == 0 && secs < 0))
+// return uint(-1);
+//
+// qlonglong retval = (qlonglong(days) * SECS_PER_DAY) + secs;
+// if (retval >= Q_INT64_C(0xFFFFFFFF))
+// return uint(-1);
+// return uint(retval);
+// }
+//
+// /*!
+// Returns the datetime as the number of seconds that have passed
+// since 1970-01-01T00:00:00, Coordinated Universal Time (Qt::UTC).
+//
+// On systems that do not support time zones, this function will
+// behave as if local time were Qt::UTC.
+//
+// \sa setTime_t()
+// */
+//
+// static uint myToTime_t(QDateTime d)
+// {
+// // return 0;
+// // QDate utcDate = d.toUTC().date();
+// // QTime utcTime = d.toUTC().time();
+// QDate utcDate = d.date();
+// QTime utcTime = d.time();
+// // d->getUTC(utcDate, utcTime);
+//
+// return toTime_tHelper(utcDate, utcTime);
+// }
+
+/* formatuje chybove hlaseni driveru */
+QString ValueCache::getErrorMsg(QSqlQuery &query) const {
+ QSqlError err = query.lastError();
+ return QString("%1: %2 - %3").arg(err.number()).arg(err.driverText()).arg(err.databaseText());
+}
+
+/* spusteni query + log pripadne chyby */
+QSqlQuery &ValueCache::processQuery(QSqlQuery &query) const {
+ if (!query.exec()) {
+ logToFile(QString("[WW] - error when executing query: %1").arg(getErrorMsg(query)));
+ logToFile(QString("[WW] - query was: %1").arg(query.lastQuery()));
+ }
+ return query;
+}
+
+/* konstruktor - vytvoreni tabulek v DB, pokud je potreba */
+ValueCache::ValueCache() {
+ db = QSqlDatabase::addDatabase("QSQLITE");
+ db.setDatabaseName(SQLITE_DB_FILE);
+ if (!db.open())
+ logToFile("[WW] - error when opening database " SQLITE_DB_FILE);
+ QSqlQuery query(db);
+ query.prepare(
+ "CREATE TABLE IF NOT EXISTS " SQLITE_CACHE_TABLE_NAME " ("
+ "id INTEGER PRIMARY KEY, node_sn NUMERIC, value NUMERIC, var_oid NUMERIC, mov_avg NUMERIC, mov_avg_count NUMERIC, timestamp NUMERIC"
+ ");"
+ );
+ processQuery(query);
+}
+
+/* destruktor */
+ValueCache::~ValueCache() {
+ db.close();
+}
+
+/* vlozeni zaznamu do cache a smazani nadbytecnych radku */
+void ValueCache::insertValue(long node_sn, int var_oid, float value) const {
+ /* zjisteni poctu existujicich zaznamu pro dany nod a promennou */
+ QDateTime current_dtime = currentDateTime();
+ QSqlQuery queryCnt(db);
+ queryCnt.prepare("SELECT id, value, timestamp FROM " SQLITE_CACHE_TABLE_NAME " WHERE node_sn = :node_sn AND var_oid = :var_oid ORDER BY timestamp ASC;");
+ queryCnt.bindValue(":node_sn", (qlonglong)node_sn);
+ queryCnt.bindValue(":var_oid", var_oid);
+ processQuery(queryCnt);
+ QList<int> ids;
+ int new_id, avg_val_count = 1;
+ uint timestamp = 0;
+ float new_avg = value;
+ while (queryCnt.next()) {
+ if (!timestamp)
+ timestamp = queryCnt.value(2).toInt();
+ ids.append(queryCnt.value(0).toInt());
+// if (timestamp > (current_dtime.toTime_t() - HISTORY_LEN)) {
+ new_avg += queryCnt.value(1).toDouble();
+ avg_val_count++;
+// }
+ }
+ if (!timestamp)
+ timestamp = current_dtime.toTime_t();
+
+ new_avg /= avg_val_count;
+
+ if (timestamp < (current_dtime.toTime_t() - HISTORY_LEN))
+ new_id = ids[0];
+ else
+ new_id = 0;
+
+ /* vlozeni noveho zaznamu */
+ QSqlQuery queryIns(db);
+ if (new_id == 0)
+ queryIns.prepare("INSERT INTO " SQLITE_CACHE_TABLE_NAME " (node_sn, var_oid, value, mov_avg, timestamp) VALUES (:node_sn, :var_oid, :value, :mov_avg, :timestamp);");
+ else {
+ queryIns.prepare("INSERT OR REPLACE INTO " SQLITE_CACHE_TABLE_NAME " (id, node_sn, var_oid, value, mov_avg, timestamp) VALUES (:id, :node_sn, :var_oid, :value, :mov_avg, :timestamp);");
+ queryIns.bindValue(":id", new_id);
+ }
+ queryIns.bindValue(":node_sn", (qlonglong)node_sn);
+ queryIns.bindValue(":var_oid", var_oid);
+ queryIns.bindValue(":value", value);
+ queryIns.bindValue(":mov_avg", new_avg);
+ QDateTime curr = currentDateTime();
+ curr.setTimeSpec(Qt::UTC);
+ queryIns.bindValue(":timestamp", curr.toTime_t());
+ processQuery(queryIns);
+}
+
+/* zajistuje odstraneni vsech zaznamu navazanych na promennou z cache */
+void ValueCache::removeVar(long node_sn, int var_oid) const {
+ QSqlQuery query(db);
+ query.prepare("DELETE FROM " SQLITE_CACHE_TABLE_NAME " WHERE node_sn = :node_sn AND var_oid = :var_oid ;");
+ query.bindValue(":node_sn", (int)node_sn);
+ query.bindValue(":var_oid", var_oid);
+ processQuery(query);
+}
+
+/* zajistuje odstraneni vsech zaznamu navazanych na nod z cache */
+void ValueCache::removeNode(long node_sn) const {
+ QSqlQuery query(db);
+ query.prepare("DELETE FROM " SQLITE_CACHE_TABLE_NAME " WHERE node_sn = :node_sn;");
+ query.bindValue(":node_sn", (int)node_sn);
+ processQuery(query);
+}
+
+/* vraci QList hodnot pro danou promennou v nodu */
+QPair< QVector<QPointF>, QVector<QPointF> > ValueCache::getValues(long node_sn, int var_oid, int secs_ago) const {
+ QDateTime current_dtime = currentDateTime();
+ QSqlQuery query(db);
+ query.prepare("SELECT value, mov_avg, timestamp FROM " SQLITE_CACHE_TABLE_NAME " WHERE node_sn = :node_sn AND var_oid = :var_oid AND timestamp >= :timestamp ORDER BY timestamp ASC;");
+ query.bindValue(":node_sn", (int)node_sn);
+ query.bindValue(":var_oid", var_oid);
+ query.bindValue(":timestamp", current_dtime.toTime_t() - secs_ago);
+ processQuery(query);
+ QVector<QPointF> values;
+ QVector<QPointF> avgs;
+ while (query.next()) {
+ values.append(QPointF(query.value(2).toDouble(), query.value(0).toDouble()));
+ avgs.append(QPointF(query.value(2).toDouble(), query.value(1).toDouble()));
+ }
+ return QPair< QVector<QPointF>, QVector<QPointF> >(values, avgs);
+}
--- /dev/null
+# ifndef _VALUE_CACHE_H
+# define _VALUE_CACHE_H
+
+#include <QChar>
+#include <QList>
+#include <QTextStream>
+
+#include <QtSql>
+
+#include "defines.h"
+#include "utils.h"
+
+class ValueCache {
+ private:
+ QSqlDatabase db;
+
+ QString getErrorMsg(QSqlQuery &query) const;
+
+ QSqlQuery &processQuery(QSqlQuery &query) const;
+
+ public:
+ ValueCache();
+
+ ~ValueCache();
+
+ void insertValue(long node_sn, int var_oid, float value) const;
+
+ void removeVar(long node_sn, int var_oid) const;
+
+ void removeNode(long node_sn) const;
+
+ QPair< QVector<QPointF>, QVector<QPointF> > getValues(long node_sn, int var_oid, int secs_ago) const;
+};
+
+# endif
--- /dev/null
+/home/stefic/BAP/build_ulan/ulan/host/ul_drv
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+<grammar xmlns="http://relaxng.org/ns/structure/1.0">
+ <start>
+ <element name="configuration">
+ <element name="nodes">
+ <oneOrMore>
+ <element name="node">
+ <attribute name="sn">
+ <text />
+ </attribute>
+ <optional>
+ <element name="customName">
+ <text />
+ </element>
+ </optional>
+ <element name="vars">
+ <oneOrMore>
+ <element name="var">
+ <attribute name="oid">
+ <text />
+ </attribute>
+ <optional>
+ <element name="customDescription">
+ <text />
+ </element>
+ </optional>
+ <optional>
+ <element name="color">
+ <text />
+ </element>
+ </optional>
+ <optional>
+ <element name="commonGraphDisplay">
+ <text />
+ </element>
+ </optional>
+ <optional>
+ <element name="value">
+ <text />
+ </element>
+ </optional>
+ </element>
+ </oneOrMore>
+ </element>
+ </element>
+ </oneOrMore>
+ </element>
+ </element>
+ </start>
+</grammar>
void set_fan_PIN(){
if (oi_fan == 1) {
- SET_OUT_PIN(OUT_PORT,P1_29_FAN);
+// SET_OUT_PIN(OUT_PORT,P1_30_FAN);
+ SET_OUT_PIN(LED_PORT,P0_28_FAN);
printf("FAN PIN UP\n");
} else {
- CLR_OUT_PIN(OUT_PORT,P1_29_FAN);
+// CLR_OUT_PIN(OUT_PORT,P1_30_FAN);
+ CLR_OUT_PIN(LED_PORT,P0_28_FAN);
printf("FAN PIN DOWN\n");
}
}
void set_humidifier_PIN(){
+ IO0DIR |= 0x40000000;
if (oi_humidifier == 1) {
- SET_OUT_PIN(OUT_PORT,P1_30_HUMIDIFIER);
+// SET_OUT_PIN(OUT_PORT,P1_29_HUMIDIFIER);
+ SET_OUT_PIN(LED_PORT,P0_30_HUMIDIFIER);
printf("HUM PIN UP\n");
} else {
- CLR_OUT_PIN(OUT_PORT,P1_30_HUMIDIFIER);
+// CLR_OUT_PIN(OUT_PORT,P1_29_HUMIDIFIER);
+ CLR_OUT_PIN(LED_PORT,P0_30_HUMIDIFIER);
printf("HUM PIN DOWN\n");
}
}
void set_light_PIN(){
if (oi_light == 1) {
- SET_OUT_PIN(OUT_PORT,P1_31_LIGHT);
+// SET_OUT_PIN(OUT_PORT,P1_31_LIGHT);
+ SET_OUT_PIN(LED_PORT,P0_25_LIGHT);
printf("LIGHT PIN UP\n");
} else {
- CLR_OUT_PIN(OUT_PORT,P1_31_LIGHT);
+// CLR_OUT_PIN(OUT_PORT,P1_31_LIGHT);
+ CLR_OUT_PIN(LED_PORT,P0_25_LIGHT);
printf("LIGHT PIN DOWN\n");
}
}
static const int MAX_CID_CNT = 4;
cid_data_t cids[MAX_CID_CNT];
- if (oi_period == 1){
+ if (oi_period == HEART_PERIOD){
cids[cid_cnt].cid = HEART_CID;
cids[cid_cnt].value = status_val;
cid_cnt++;
buff_len += 2;
}
- msgsend = ul_send_query(ul_fd, 0, UL_CMD_PDO, UL_BFL_NORE, (void*) buf, buff_len);
+ msgsend = ul_send_command(ul_fd, 0, UL_CMD_PDO, UL_BFL_NORE, (void*) buf, buff_len);
printf("[I] DATA\n");
ul_freemsg(ul_fd);
}
oi_light = 0;
oi_cid_light = 0;
oi_slot_light = 0;
- oi_period = 1;
+ oi_period = 2;
status_val = 5;
}
void check_PDO(int cid, int data){
- printf("CID: %i\n", cid);
if (cid == oi_slot_fan){
oi_fan = data;
set_fan_PIN();
void work_with(void){
- PINSEL1 &= 0xFFFFB3FF;
+// PINSEL1 &= 0xFFFFB3FF;
+ PINSEL1 &= 0xCCF3FFFF;
// u vetsi karbicky je SET z 0 do 3.3
// u mensi je SET z -3.3 do 0
// IO0SET = P0_21_BIT;
// IO0SET = P0_22_BIT;
- SET_OUT_PIN(OUT_PORT, P1_29_FAN);
- SET_OUT_PIN(OUT_PORT, P1_31_LIGHT);
- SET_OUT_PIN(OUT_PORT, P1_30_HUMIDIFIER);
+// CLR_OUT_PIN(OUT_PORT, P1_26_UNUSED_BIT);
+//
+// CLR_OUT_PIN(OUT_PORT, P1_30_FAN);
+// CLR_OUT_PIN(OUT_PORT, P1_31_LIGHT);
+// CLR_OUT_PIN(OUT_PORT, P1_29_HUMIDIFIER);
+// CLR_OUT_PIN(OUT_PORT, P1_28_UNUSED_BIT);
+// SET_OUT_PIN(OUT_PORT, P1_27_UNUSED_BIT);
+
+
+IO0DIR |= 0x40000000;
+
+CLR_OUT_PIN(LED_PORT, P0_25_LIGHT); //25
+CLR_OUT_PIN(LED_PORT, P0_28_FAN); //28
+// CLR_OUT_PIN(LED_PORT, P0_30_PIN); //30
+
+// SET_OUT_PIN(LED_PORT, P0_25_PIN); //25
+// SET_OUT_PIN(LED_PORT, P0_28_PIN); //28
+SET_OUT_PIN(LED_PORT, P0_30_HUMIDIFIER);
IO0SET = LED1_BIT; //vypinani LED
ULOI_GENOBJDES(LIGHT_CID,I_LIGHT_CID,"u2/cid",uloi_uint_rdfnc,&oi_cid_light,oi_cid_light_wrfnc,&oi_cid_light)
ULOI_GENOBJDES(LIGHT_SLOT,I_LIGHT_SLOT,"u2/slot",uloi_uint_rdfnc,&oi_slot_light,oi_slot_light_wrfnc,&oi_slot_light)
-ULOI_GENOBJDES(PERIOD,I_PERIOD,"u2",uloi_uint_rdfnc,&oi_period,NULL_CODE,NULL/*oi_period_wrfnc,&oi_period*/)
+ULOI_GENOBJDES(PERIOD,I_PERIOD,"u2",uloi_uint_rdfnc,&oi_period,oi_period_wrfnc,&oi_period)
const uloi_objdes_t * ULOI_CODE uloi_objdes_main_items[]={
&uloid_objdes_DOII,
unsigned int oi_want_temp;
unsigned int oi_want_hum;
unsigned int oi_want_light;
-unsigned int oi_want_dark;
+unsigned int oi_grow_cykl;
+unsigned int lighting;
+unsigned int last = 0;
+float res = 10;
-int hyst_temp = 1;
+float hyst_temp = 0.5;
int hyst_hum = 10;
unsigned int fan = 0;
unsigned int hum = 0;
unsigned int light = 0;
-int temperature;
-int humidity;
+float temperature;
+float humidity;
// OBJECT INTERFACE FUNCTIONS
int oi_cid_fan_wrfnc(ULOI_PARAM_coninfo void *context){
return 1;
}
+int oi_want_light_wrfnc(ULOI_PARAM_coninfo void *context){
+ uloi_uint_wrfnc(ULOI_ARG_coninfo context);
+
+ if (oi_want_light != 0){
+ if (last != oi_want_light){
+ last = oi_want_light;
+ l3time = current_time();
+ }
+ lighting = 1;
+ } else {
+ lighting = 0;
+ last = 0;
+ }
+
+ return 1;
+}
+
+int oi_grow_cykl_wrfnc(ULOI_PARAM_coninfo void *context){
+ uloi_uint_wrfnc(ULOI_ARG_coninfo context);
+ return 1;
+}
+
void send_data() {
int msgsend;
static const int MAX_CID_CNT = 4;
cid_data_t cids[MAX_CID_CNT];
- if (oi_period == 1){
+ if (oi_period == HEART_PERIOD){
cids[cid_cnt].cid = HEART_CID;
cids[cid_cnt].value = status_val;
cid_cnt++;
buff_len += 2;
}
- msgsend = ul_send_query(ul_fd, 0, UL_CMD_PDO, UL_BFL_NORE, (void*) buf, buff_len);
+ msgsend = ul_send_command(ul_fd, 0, UL_CMD_PDO, UL_BFL_NORE, (void*) buf, buff_len);
printf("[I] DATA\n");
ul_freemsg(ul_fd);
}
void check_PDO(int cid, int data){
printf("CID: %i\n", cid);
if (cid == oi_slot_temp){
- temperature = data;
- printf("temperature: %i\n", temperature);
+ temperature = data/res;
+ printf("temperature: %f\n", temperature);
}
if (cid == oi_slot_hum){
- humidity = data;
- printf("humidity: %i\n", humidity);
+ humidity = data/res;
+ printf("humidity: %f\n", humidity);
}
}
void regulate(void){
- if (((oi_want_temp + hyst_temp) > temperature) && fan != 1) fan = 1;
- if (((oi_want_temp - hyst_temp) < temperature) && fan != 0) fan = 0;
+ if (temperature > (oi_want_temp/res + hyst_temp)) fan = 1;
+ if (temperature < (oi_want_temp/res - hyst_temp)) fan = 0;
- if (((oi_want_hum + hyst_hum) > humidity) && hum != 1) hum = 1;
- if (((oi_want_hum - hyst_hum) < humidity) && hum != 0) hum = 0;
+ if (humidity < (oi_want_hum/res + hyst_hum)) hum = 1;
+ if (humidity > (oi_want_hum/res - hyst_hum)) hum = 0;
- if(((current_time()-l3time) < oi_want_light*3600*1000) && light == 0) {
- light = 1;
- l3time = current_time();
- }
- if(((current_time()-l3time) < oi_want_dark*3600*1000) && light == 1) {
- light = 0;
- l3time = current_time();
+ if (lighting == 1){
+ if((current_time()-l3time) < oi_want_light/res/* *3600*/*1000) {
+ light = 1;
+ } else if((current_time()-l3time) < oi_grow_cykl/res/* *3600*/*1000){
+ light = 0;
+ } else l3time = current_time();
}
}
void work_with(void){
}
-
-
#define DATA_BUF_LEN 15
#define SN 103
-
// OI
extern const ULOI_CODE uloi_objdes_array_t uloi_objdes_main;
extern unsigned int status_val;
extern unsigned int oi_period;
extern unsigned int oi_want_temp;
extern unsigned int oi_want_hum;
+extern unsigned int oi_want_light;
+extern unsigned int oi_grow_cykl;
typedef struct cid_data {
int cid;
int oi_period_wrfnc(ULOI_PARAM_coninfo void *context);
int oi_want_temp_wrfnc(ULOI_PARAM_coninfo void *context);
int oi_want_hum_wrfnc(ULOI_PARAM_coninfo void *context);
+int oi_want_light_wrfnc(ULOI_PARAM_coninfo void *context);
+int oi_grow_cykl_wrfnc(ULOI_PARAM_coninfo void *context);
void send_data();
void oiinit(void);
#define I_WANT_TEMP 1100
#define I_WANT_HUM 1200
+#define I_WANT_LIGHT 1300
+#define I_GROW_CYKL 1400
unsigned int status_val;
ULOI_GENOBJDES(WANT_TEMP,I_WANT_TEMP,"u2/.1",uloi_uint_rdfnc,&oi_want_temp,oi_want_temp_wrfnc,&oi_want_temp)
ULOI_GENOBJDES(WANT_HUM,I_WANT_HUM,"u2/.1",uloi_uint_rdfnc,&oi_want_hum,oi_want_hum_wrfnc,&oi_want_hum)
+ULOI_GENOBJDES(WANT_LIGHT,I_WANT_LIGHT,"u2/.1",uloi_uint_rdfnc,&oi_want_light,oi_want_light_wrfnc,&oi_want_light)
+ULOI_GENOBJDES(GROW_CYKL,I_GROW_CYKL,"u2/.1",uloi_uint_rdfnc,&oi_grow_cykl,oi_grow_cykl_wrfnc,&oi_grow_cykl)
const uloi_objdes_t * ULOI_CODE uloi_objdes_main_items[]={
&uloid_objdes_DOII,
&uloid_objdes_HUMIDITY_SLOT,
&uloid_objdes_PERIOD,
&uloid_objdes_WANT_TEMP,
- &uloid_objdes_WANT_HUM
+ &uloid_objdes_WANT_HUM,
+ &uloid_objdes_WANT_LIGHT,
+ &uloid_objdes_GROW_CYKL
};
const ULOI_CODE uloi_objdes_array_t uloi_objdes_main={
#include <system_def.h>
#include <cpu_def.h>
+#include <math.h>
+
#include "board.h"
adc_stat_t adcst;
static const int MAX_CID_CNT = 3;
cid_data_t cids[MAX_CID_CNT];
- if (oi_period == 1){
+ if (oi_period == HEART_PERIOD){
cids[cid_cnt].cid = HEART_CID;
cids[cid_cnt].value = status_val;
cid_cnt++;
buff_len += 2;
}
- msgsend = ul_send_query(ul_fd, 0, UL_CMD_PDO, UL_BFL_NORE, (void*) buf, buff_len);
+ msgsend = ul_send_command(ul_fd, 0, UL_CMD_PDO, UL_BFL_NORE, (void*) buf, buff_len);
printf("[I] DATA\n");
ul_freemsg(ul_fd);
}
// }
void adc2oi(void){
- oi_temperature = adcst.temp;
- printf("temperature: %i\n",adcst.temp);
- oi_humidity = adcst.hum;
- printf("humidity: %i\n",adcst.hum);
+ double tmp_temp, tmp_hum;
+
+ tmp_temp = (adcst.temp*ADres*100)/Aoz;
+ tmp_temp = ((int)(tmp_temp*10))/10.0;
+
+ tmp_hum = (adcst.hum*ADres)*20;
+
+ oi_temperature = tmp_temp * 10;
+ printf("temperature: %4.1f\n",tmp_temp);
+ oi_humidity = tmp_hum * 10;
+ printf("humidity: %4.1f\n",tmp_hum);
}
void oiinit(void){
led1_time = current_time();
led2_time = current_time();
// adcst.read = 0;
-// adcst.temp = 0;
+ adcst.temp = 498;
// adcst.temp_tmp = 0;
// adcst.hum = 0;
// adcst.hum_tmp = 0;
time = current_time();
- while(1){
-// blink();
-// read_ADC(&adcst);
-
- if((current_time()-time) > 1000){
- printf("AD0.1 %i\n", adcst.temp);
-// printf("AD0.2 %i\n", adcst.hum);
- time = current_time();
- }
- }
+ double tmp_temp;
+ tmp_temp = (adcst.temp*ADres*100)/Aoz;
+ printf("temperature: %f\n",tmp_temp);
+
+
+// while(1){
+// // blink();
+// // read_ADC(&adcst);
+//
+// if((current_time()-time) > 1000){
+// printf("AD0.1 %i\n", adcst.temp);
+// // printf("AD0.2 %i\n", adcst.hum);
+// time = current_time();
+// }
+// }
}
void init_ADC (int selected){
+ #ifndef OS_POSIX
+
PINSEL1|= 0x05000000; // P0.28 and P0.29 set for AD0.1 and AD0.2 inputs
AD0CR &= 0x00000000; // Clear All Bit Control
switch (selected){
// AD0CR &= 0xFF3FFFFF; // TEST[1:0] = 00 = Modo normal
// AD0CR &= 0xF7FFFFFF; // EDGE = 0 = Flanco de bajada
// AD0STAT = 0x00000110;
+ #endif
}
int read_ADC (adc_stat_t *adcst){
+ #ifndef OS_POSIX
+
init_ADC(1);
AD0CR |= 0x01000000; // start conversion
while (!(AD0GDR & (ADGDR_DONE))); // wait for DONE to go high
return 1;
}
+ #endif
return 0;
}
#define DATA_BUF_LEN 15
#define SN 101
+#define ADres 0.0032
+#define Aoz 6.43
+
#define CNT 10
// OI
if(clock_gettime(CLOCK_REALTIME, &tp) == 0){
ret = tp.tv_sec*1000;
ret += tp.tv_nsec/1000000;
- }
+ }
#else
lt_mstime_update();
ret = actual_msec;
int2buf(&buf[7],status_val);
msgsend = ul_send_command(ul_fd, ul_dyac->ul_dysa, UL_CMD_PDO, UL_BFL_NORE, (void*) buf, HEART_BUF_LEN);
- printf("[I] BEAT\n");
+ printf("[I] BEAT %i \n",msgsend);
free(buf);
}
if (msginfo.cmd == UL_CMD_PDO){
process_PDO();
ul_freemsg(ul_fd);
- printf("accept PDO msg: sadr: %i, dadr: %i\n", msginfo.sadr, msginfo.dadr);
+// printf("accept PDO msg: sadr: %i, dadr: %i\n", msginfo.sadr, msginfo.dadr);
} else if (msginfo.sadr != 99) {
if (!(msginfo.flg&(UL_BFL_PROC | UL_BFL_FAIL))) {
//waiting for msg from bus
check_PDO(cid, data);
}
+ free(buf);
}
uint take_cid(uchar * buf){
#define HEART_BUF_LEN 9
#define HEART_CID 1023
+#define HEART_PERIOD 2
#define UL_DEV "/dev/ulan"
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
-//#define OS_POSIX
+// #define OS_POSIX
#ifdef HAVE_CONFIG_H
#include <config.h>
ltime = current_time();
l2time = current_time();
- l3time = current_time();
while(1){
blink();
ctime = current_time();
if (oi_period != 0){
- if (oi_period == 1){
- if((ctime-ltime) > 1000){
+ if (oi_period == HEART_PERIOD){
+ if((ctime-ltime) > 1000*HEART_PERIOD){
send_data();
ltime = current_time();
}
} else {
- if((ctime-ltime) > 1000){
+ if((ctime-ltime) > 1000*HEART_PERIOD){
heartbeat();
ltime = current_time();
}
l2time = current_time();
}
}
- } else heartbeat();
+ } else {
+ if((ctime-ltime) > 1000*HEART_PERIOD){
+ heartbeat();
+ ltime = current_time();
+ }
+ }
accept_SDO();
regulate();
#include "definitions.h"
#include "ul_idstr.h"
+
+
#endif /* HYDRO */