update esppilight lib

content of the library is not filtered on 433mhz only
This commit is contained in:
Florian committed 2018-11-28 20:41:37 +01:00
1 parent a275e48ee1
commit 67dd7ac078
1030 files changed
+203335 -116

No files matched your search

+9
View File
@@ -1 +1,10 @@
*~
src/pilight/libs/pilight/core/binary.c
src/pilight/libs/pilight/core/binary.h
src/pilight/libs/pilight/core/dso.h
src/pilight/libs/pilight/core/json.c
src/pilight/libs/pilight/core/json.h
src/pilight/libs/pilight/core/mem.h
src/pilight/libs/pilight/protocols/433.92/*
src/pilight/libs/pilight/protocols/protocol_header.h
src/pilight/libs/pilight/protocols/protocol_init.h
+2
View File
@@ -20,6 +20,8 @@ env:
install:
# PlatformIO
- pip install -U platformio
# integrate pilight
- make
script:
- platformio ci --lib="." --board=huzzah --board=d1_mini --board=esp32dev
+1 -1
View File
@@ -47,7 +47,7 @@ $(DST_DIR)/libs/pilight/core/json.c: $(SRC_DIR)/libs/pilight/core/json.c
@mkdir -p $(@D)
cp $< $@
# ESP8266 Android, sprintf not working with float. Patch:
sed 's/sprintf(buf, "%.*f", decimals, num);/dtostrf(num, 0, decimals, buf);/' -i $@
sed 's/\(^[ \t]*\)\(sprintf(buf, "%.*f", decimals, num);\)/#ifdef ESP8266\n\1dtostrf(num, 0, decimals, buf);\n#else\n\1\2\n#endif/' -i $@
# Arduino did not provide printf, fprintf
sed 's!#include <stdio.h>!#include <stdio.h>\n#include "../../../../tools/aprintf.h"!' -i $@
+1 -1
View File
@@ -7,7 +7,7 @@
"type": "git",
"url": "https://github.com/puuu/ESPiLight.git"
},
"version": "0.14.2",
"version": "0.15.0",
"license": "GPL-3.0",
"frameworks": "arduino",
"platforms":
+1 -1
View File
@@ -1,5 +1,5 @@
name=ESPiLight
version=0.14.2
version=0.15.0
author=Puuu
maintainer=Puuu <puuu@users.noreply.github.com>
sentence=pilight 433.92 MHz protocols library for Arduino
+1
View File
@@ -0,0 +1 @@
text eol=lf
+51
View File
@@ -0,0 +1,51 @@
# CMake and build files
*.o
build/
CMakeFiles/
Makefile
*.cmake
CMakeCache.txt
cmake_uninstall.cmake.in
# Headers created when running cmake
inc/defines.h
*_header.h
*_init.h
# Libraries and pilight executables
*.a
*.so
pilight-control
pilight-daemon
pilight-debug
pilight-flash
pilight-raw
pilight-receive
pilight-send
pilight-sha256
pilight-uuid
*.exe
# JSON files in base directory - often used for local testing of different configs
/*.json
# IDE project files
.project
.settings/
.cproject
.idea/
*.iml
*.ipr
*.iws
# General os files
*~
*.bak
*.swp
.directory
._*
ehthumbs.db
Thumbs.db
# docs
docs/build
+90
View File
@@ -0,0 +1,90 @@
set(WEBSERVER ON CACHE BOOL "enable the built-in webserver")
set(WEBSERVER_HTTPS ON CACHE BOOL "enable webserver ssl protocol")
set(EVENTS ON CACHE BOOL "enable the eventing functionality")
set(IR OFF CACHE BOOL "enable IR remotes support")
set(ZWAVE OFF CACHE BOOL "enable Z-Wave support")
set(PROTOCOL_ALECTO_WS1700 ON CACHE BOOL "support for the Alecto WS1700 protocol")
set(PROTOCOL_ALECTO_WSD17 ON CACHE BOOL "support for the Alecto WSD 17 protocol")
set(PROTOCOL_ALECTO_WX500 ON CACHE BOOL "support for the Alecto WX500 protocol")
set(PROTOCOL_AURIOL ON CACHE BOOL "support for the Auriol weather station protocol")
set(PROTOCOL_ARPING ON CACHE BOOL "support for the MAC based ping protocol")
set(PROTOCOL_BEAMISH_SWITCH ON CACHE BOOL "support for the Beamish switch protocol")
set(PROTOCOL_BMP180 ON CACHE BOOL "support for the BMP180/085 i2c barometric pressure-temperature sensor")
set(PROTOCOL_BRENNENSTUHL_SWITCH ON CACHE BOOL "support for the Brennenstuhl switch protocol")
set(PROTOCOL_BYEBYESTANDBY_SWITCH ON CACHE BOOL "support for the ByeByeStandBy switch protocol")
set(PROTOCOL_CLARUS ON CACHE BOOL "support for the Clarus switch protocol")
set(PROTOCOL_CLEVERWATTS ON CACHE BOOL "support for the Cleverwatts switch protocol")
set(PROTOCOL_COCO_SWITCH ON CACHE BOOL "support for the new ClickOnClickOff switch protocol")
set(PROTOCOL_COGEX_SWITCH ON CACHE BOOL "support for the Cogex switch protocol")
set(PROTOCOL_CONRAD_RSL_SWITCH ON CACHE BOOL "support for the Conrad RSL switch protocol")
set(PROTOCOL_CONRAD_RSL_CONTACT ON CACHE BOOL "support for the Conrad RSL contact sensor protocol")
set(PROTOCOL_CONRAD_WEATHER ON CACHE BOOL "support for the Conrad weather stations protocol")
set(PROTOCOL_CPU_TEMP ON CACHE BOOL "support for CPU temperature sensor")
set(PROTOCOL_DATETIME ON CACHE BOOL "support for the (NTP) date and time protocol")
set(PROTOCOL_DAYCOM ON CACHE BOOL "support Daycom switch (Pollin)")
set(PROTOCOL_DS18B20 ON CACHE BOOL "support for the 1-Wire ds18b20 temperature sensor")
set(PROTOCOL_DS18S20 ON CACHE BOOL "support for the 1-Wire ds18s20 temperature sensor")
set(PROTOCOL_DHT11 ON CACHE BOOL "support for the DHT11 temperature-humidity sensor")
set(PROTOCOL_DHT22 ON CACHE BOOL "support for the DHT22/AM2302 temperature-humidity sensor")
set(PROTOCOL_DIO_SWITCH ON CACHE BOOL "support for the D-IO switch protocol")
set(PROTOCOL_DUWI_SWITCH ON CACHE BOOL "support for the Düwi Terminal switch protocol")
set(PROTOCOL_EHOME ON CACHE BOOL "support for the eHome switch protocol")
set(PROTOCOL_ELRO_SWITCH ON CACHE BOOL "support for the Elro switch protocol")
set(PROTOCOL_ELRO_CONTACT ON CACHE BOOL "support for the Elro contact protocol")
set(PROTOCOL_EURODOMEST_SWITCH ON CACHE BOOL "support for the Eurodomest switch protocol")
set(PROTOCOL_EV1527 ON CACHE BOOL "support for the EV1527 contact protocol")
set(PROTOCOL_GENERIC_DIMMER ON CACHE BOOL "support for the generic dimmer protocol")
set(PROTOCOL_GENERIC_SCREEN ON CACHE BOOL "support for the generic screen protocol")
set(PROTOCOL_GENERIC_SWITCH ON CACHE BOOL "support for the generic switch protocol")
set(PROTOCOL_GENERIC_WEATHER ON CACHE BOOL "support for the generic weather protocol")
set(PROTOCOL_GENERIC_WEBCAM ON CACHE BOOL "support for the generic webcam protocol")
set(PROTOCOL_GPIO_SWITCH ON CACHE BOOL "support for the GPIO switch protocol")
set(PROTOCOL_HEITECH ON CACHE BOOL "support for the Heitech switch protocol")
set(PROTOCOL_IMPULS ON CACHE BOOL "support for the Impuls switch protocol")
set(PROTOCOL_INTERTECHNO_SWITCH ON CACHE BOOL "support for the new Intertechno switch protocol")
set(PROTOCOL_INTERTECHNO_OLD ON CACHE BOOL "support for the old Intertecho switch protocol")
set(PROTOCOL_KAKU_CONTACT ON CACHE BOOL "support for the new KlikAanKlikUit contact protocol")
set(PROTOCOL_KAKU_DIMMER ON CACHE BOOL "support for the old KlikAanKlikUit dimmer protocol")
set(PROTOCOL_KAKU_DUSK ON CACHE BOOL "support for the old KlikAanKlikUit dusk/dawn protocol")
set(PROTOCOL_KAKU_MOTION ON CACHE BOOL "support for the old KlikAanKlikUit PIR protocol")
set(PROTOCOL_KAKU_SWITCH_OLD ON CACHE BOOL "support for the old KlikAanKlikUit switch protocol")
set(PROTOCOL_KAKU_SCREEN_OLD ON CACHE BOOL "support for the old KlikAanKlikUit screen protocol")
set(PROTOCOL_KAKU_SWITCH ON CACHE BOOL "support for the new KlikAanKlikUit switch protocol")
set(PROTOCOL_KAKU_SCREEN ON CACHE BOOL "support for the new KlikAanKlikUit screen protocol")
set(PROTOCOL_LM75 ON CACHE BOOL "support for the lm75 i2c temperature sensor")
set(PROTOCOL_LM76 ON CACHE BOOL "support for the lm76 i2c temperature sensor")
set(PROTOCOL_LIRC ON CACHE BOOL "support for the Lirc API")
set(PROTOCOL_LIVOLO_SWITCH ON CACHE BOOL "support for the Livolo switch protocol")
set(PROTOCOL_LOGILINK_SWITCH ON CACHE BOOL "support for the Logilink switch protocol")
set(PROTOCOL_MUMBI_SWITCH ON CACHE BOOL "support for the Mumbi switch protocol")
set(PROTOCOL_NEXA_SWITCH ON CACHE BOOL "support for the Nexa switch protocol")
set(PROTOCOL_NINJABLOCKS_WEATHER ON CACHE BOOL "support for Ninjablocks temperature-humidity sensor protocol")
set(PROTOCOL_OPENWEATHERMAP ON CACHE BOOL "support for the Open Weather Map API")
set(PROTOCOL_PING ON CACHE BOOL "support for the ping protocol")
set(PROTOCOL_POLLIN_SWITCH ON CACHE BOOL "support for the polling switch protocol")
set(PROTOCOL_PROGRAM ON CACHE BOOL "support for the program switching protocol")
set(PROTOCOL_PROMAX_SWITCH ON CACHE BOOL "support for the PRO max switch protocol")
set(PROTOCOL_QUIGG_SCREEN ON CACHE BOOL "support for Quigg switch w screen protocol")
set(PROTOCOL_QUIGG_GT1000 ON CACHE BOOL "support for Quigg GT-1000 protocol")
set(PROTOCOL_QUIGG_GT7000 ON CACHE BOOL "support for Quigg GT-7000 protocol")
set(PROTOCOL_QUIGG_GT9000 ON CACHE BOOL "support for Quigg GT-9000 protocol")
set(PROTOCOL_RAW ON CACHE BOOL "support for the raw / simulator")
set(PROTOCOL_RELAY ON CACHE BOOL "support for GPIO relay devices")
set(PROTOCOL_REV ON CACHE BOOL "support for the Rev protocol")
set(PROTOCOL_RSL366 ON CACHE BOOL "support for RSL366 switch protocol")
set(PROTOCOL_RC101 ON CACHE BOOL "support for RC101 switch protocol")
set(PROTOCOL_RC102 ON CACHE BOOL "support for RC102 switch protocol")
set(PROTOCOL_SC2262 ON CACHE BOOL "support for the SC2262 Contact protocol")
set(PROTOCOL_SECUDO_SMOKE ON CACHE BOOL "support for Secudo/FlammEx smoke sensor protocol")
set(PROTOCOL_SELECTREMOTE ON CACHE BOOL "support for the Selectremote switch protocol")
set(PROTOCOL_SILVERCREST ON CACHE BOOL "support for the Silvercrest switch protocol")
set(PROTOCOL_SUNRISESET ON CACHE BOOL "support for the Sunrise / Sunset calculator")
set(PROTOCOL_TCM ON CACHE BOOL "support for the TCM 218943 weather station protocol")
set(PROTOCOL_TECHLICO ON CACHE BOOL "support for TechLiCo Lamps protocol")
set(PROTOCOL_TEKNIHALL ON CACHE BOOL "support for the Teknihall weather station protocol")
set(PROTOCOL_TFA ON CACHE BOOL "support for the TFA weather station protocol")
set(PROTOCOL_WUNDERGROUND ON CACHE BOOL "support for the Weather Underground API")
set(PROTOCOL_X10 ON CACHE BOOL "support for the X10 protocol")
set(PROTOCOL_XBMC ON CACHE BOOL "support for the XBMC API")
set(HARDWARE_433_GPIO ON CACHE BOOL "support for the direct GPIO communication")
set(HARDWARE_433_LIRC ON CACHE BOOL "support for the lirc_rpi kernel module")
+732
View File
@@ -0,0 +1,732 @@
cmake_minimum_required(VERSION 2.8.8)
include(CMakeConfig.txt)
project(pilight)
set(VERSION 7.0)
set(MODULESPACK OFF)
set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_SKIP_RULE_DEPENDENCY TRUE)
set(CPACK_DEB_COMPONENT_INSTALL TRUE)
if(${ZWAVE} MATCHES "ON")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-psabi")
endif()
if(CMAKE_BUILD_TOOL MATCHES "(msdev|devenv|nmake)")
# Use the highest warning level for visual studio.
if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
else(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
endif(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
if(CMAKE_C_FLAGS MATCHES "/W[0-4]")
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
else(CMAKE_C_FLAGS MATCHES "/W[0-4]")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4")
endif(CMAKE_C_FLAGS MATCHES "/W[0-4]")
# Disable deprecation warnings for standard C functions in VS2005 and later
if(CMAKE_COMPILER_2005)
add_definitions(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE)
endif(CMAKE_COMPILER_2005)
endif(CMAKE_BUILD_TOOL MATCHES "(msdev|devenv|nmake)")
if(CMAKE_BUILD_TOOL MATCHES "make")
if(NOT CMAKE_CXX_FLAGS MATCHES "-Wall")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
endif(NOT CMAKE_CXX_FLAGS MATCHES "-Wall")
if(NOT CMAKE_C_FLAGS MATCHES "-Wall")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
endif(NOT CMAKE_C_FLAGS MATCHES "-Wall")
endif(CMAKE_BUILD_TOOL MATCHES "make")
if(NOT WIN32)
string(ASCII 27 Esc)
set(ColorReset "${Esc}[m")
set(ColorBold "${Esc}[1m")
set(Red "${Esc}[31m")
set(Green "${Esc}[32m")
set(Yellow "${Esc}[33m")
set(Blue "${Esc}[34m")
set(Magenta "${Esc}[35m")
set(Cyan "${Esc}[36m")
set(White "${Esc}[37m")
set(BoldRed "${Esc}[1;31m")
set(BoldGreen "${Esc}[1;32m")
set(BoldYellow "${Esc}[1;33m")
set(BoldBlue "${Esc}[1;34m")
set(BoldMagenta "${Esc}[1;35m")
set(BoldCyan "${Esc}[1;36m")
set(BoldWhite "${Esc}[1;37m")
endif()
set(CMAKE_SKIP_RPATH TRUE)
if(NOT WIN32)
set(CMAKE_EXE_LINKER_FLAGS " -Wl,-rpath=.,-rpath=/usr/local/lib/,-rpath=/usr/lib/,-rpath=/lib/")
set(CMAKE_SHARED_LINKER_FLAGS " -Wl,-rpath=.,-rpath=/usr/local/lib/,-rpath=/usr/lib/,-rpath=/lib/")
set(CMAKE_MODULE_LINKER_FLAGS " -Wl,-rpath=.,-rpath=/usr/local/lib/,-rpath=/usr/lib/,-rpath=/lib/")
else()
set(CMAKE_EXE_LINKER_FLAGS "-static -static-libgcc")
endif()
if(NOT WIN32)
# Start uninstaller generator
function(WRITE_UNINSTALL_TARGET_SCRIPT)
# Create uninstall target template file, if it doesn't exist...
if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in)
set(__uninstall_filename ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake.in)
# BEGIN actual write to file...
file(WRITE ${__uninstall_filename} "\# - uninstall target template\n\#")
file(APPEND ${__uninstall_filename} "
if (NOT EXISTS \"\@CMAKE_CURRENT_BINARY_DIR\@/install_manifest.txt\")
message(FATAL_ERROR \"Cannot find install manifest: \\\"\@CMAKE_CURRENT_BINARY_DIR\@/install_manifest.txt\\\"\")
endif(NOT EXISTS \"\@CMAKE_CURRENT_BINARY_DIR\@/install_manifest.txt\")
file(READ \"\@CMAKE_CURRENT_BINARY_DIR\@/install_manifest.txt\" files)
string(REGEX REPLACE \"\\n\" \";\" files \"\${files}\")
foreach (file \${files})
message(STATUS \"Uninstalling \\\"\$ENV{DESTDIR}\${file}\\\"\")
if (EXISTS \"\$ENV{DESTDIR}\${file}\")
execute_process(
COMMAND \@CMAKE_COMMAND\@ -E remove \"\$ENV{DESTDIR}\${file}\"
OUTPUT_VARIABLE rm_out
RESULT_VARIABLE rm_retval
)
if(NOT \${rm_retval} EQUAL 0)
message(FATAL_ERROR \"Problem when removing \\\"\$ENV{DESTDIR}\${file}\\\"\")
endif (NOT \${rm_retval} EQUAL 0)
else (EXISTS \"\$ENV{DESTDIR}\${file}\")
message(STATUS \"File \\\"\$ENV{DESTDIR}\${file}\\\" does not exist.\")
endif (EXISTS \"\$ENV{DESTDIR}\${file}\")
endforeach(file)
execute_process(COMMAND update-rc.d ${PROJECT_NAME} remove)
execute_process(COMMAND ldconfig)
") # END of appending to file...
endif()
endfunction()
# End of the uninstaller generator
if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/cmake_postinstall.cmake)
set(__uninstall_filename ${CMAKE_CURRENT_BINARY_DIR}/cmake_postinstall.cmake)
# BEGIN actual write to file...
file(WRITE ${__uninstall_filename} "execute_process(COMMAND update-rc.d ${PROJECT_NAME} defaults)")
endif()
endif()
execute_process(COMMAND git log -n 1 --pretty=format:"%h"
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
RESULT_VARIABLE git_result
OUTPUT_VARIABLE git_hash)
execute_process(COMMAND git describe --always --abbrev=0
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
RESULT_VARIABLE git_result
OUTPUT_VARIABLE git_ver)
string(REGEX REPLACE "\n" "" git_ver "${git_ver}")
string(REGEX REPLACE "\"" "" git_hash "${git_hash}")
add_definitions(-DHASH="${git_ver}-nightly-${git_hash}")
file(MD5 ${PROJECT_SOURCE_DIR}/res/pilight.pem md5sum)
add_definitions(-DPILIGHT_PEM_MD5="${md5sum}")
if(${MODULESPACK} MATCHES "ON" AND NOT WIN32)
add_definitions(-DMODULE="1")
endif()
if(NOT WIN32)
if(${PROTOCOL_ARPING} MATCHES "ON")
set(CMAKE_PCAP_LIBS_INIT)
find_library(CMAKE_PCAP_LIBS_INIT
NAME pcap
PATHS
${CROSS_COMPILE_LIBS}
/usr/lib
/usr/lib32
/usr/lib64
/usr/lib/i386-linux-gnu
/usr/lib/x86_64-linux-gnu
/usr/local/lib
/usr/local/lib32
/usr/local/lib64
/usr/lib/arm-linux-gnueabi
/usr/lib/arm-linux-gnueabihf
/usr/lib/aarch64-linux-gnu
NO_DEFAULT_PATH)
if(${CMAKE_PCAP_LIBS_INIT} MATCHES "CMAKE_PCAP_LIBS_INIT-NOTFOUND")
message(FATAL_ERROR "Looking for libpcap - not found")
else()
message(STATUS "Looking for libpcap - found (${CMAKE_PCAP_LIBS_INIT})")
endif()
endif()
set(CMAKE_UNWIND_LIBS_INIT)
if(NOT ${CMAKE_SYSTEM_PROCESSOR} MATCHES "^mips")
find_library(CMAKE_UNWIND_LIBS_INIT
NAME unwind
PATHS
${CROSS_COMPILE_LIBS}
/usr/lib
/usr/lib32
/usr/lib64
/usr/lib/i386-linux-gnu
/usr/lib/x86_64-linux-gnu
/usr/local/lib
/usr/local/lib32
/usr/local/lib64
/usr/lib/arm-linux-gnueabi
/usr/lib/arm-linux-gnueabihf
/usr/lib/aarch64-linux-gnu
NO_DEFAULT_PATH)
if(${CMAKE_UNWIND_LIBS_INIT} MATCHES "CMAKE_UNWIND_LIBS_INIT-NOTFOUND")
message(FATAL_ERROR "Looking for libunwind - not found")
else()
message(STATUS "Looking for libunwind - found (${CMAKE_UNWIND_LIBS_INIT})")
endif()
endif()
find_library(CMAKE_WIRINGX_LIBS_INIT
NAME wiringx
PATHS
${CROSS_COMPILE_LIBS}
/usr/lib
/usr/lib32
/usr/lib64
/usr/lib/i386-linux-gnu
/usr/lib/x86_64-linux-gnu
/usr/local/lib
/usr/local/lib32
/usr/local/lib64
/usr/lib/arm-linux-gnueabi
/usr/lib/arm-linux-gnueabihf
/usr/lib/aarch64-linux-gnu
NO_DEFAULT_PATH)
if(${CMAKE_WIRINGX_LIBS_INIT} MATCHES "CMAKE_WIRINGX_LIBS_INIT-NOTFOUND")
message(FATAL_ERROR "Looking for libwiringx - not found")
else()
message(STATUS "Looking for libwiringx - found (${CMAKE_WIRINGX_LIBS_INIT})")
endif()
endif()
find_library(CMAKE_MBEDTLS_LIBS_INIT
NAME mbedtls
PATHS
${CROSS_COMPILE_LIBS}
/usr/lib
/usr/lib32
/usr/lib64
/usr/lib/i386-linux-gnu
/usr/lib/x86_64-linux-gnu
/usr/local/lib
/usr/local/lib32
/usr/local/lib64
/usr/lib/arm-linux-gnueabi
/usr/lib/arm-linux-gnueabihf
/usr/lib/aarch64-linux-gnu
NO_DEFAULT_PATH)
if(${CMAKE_MBEDTLS_LIBS_INIT} MATCHES "CMAKE_MBEDTLS_LIBS_INIT-NOTFOUND")
message(FATAL_ERROR "Looking for libmbedtls - not found")
else()
message(STATUS "Looking for libmbedtls - found (${CMAKE_MBEDTLS_LIBS_INIT})")
endif()
find_library(CMAKE_MBEDCRYPTO_LIBS_INIT
NAME mbedcrypto
PATHS
${CROSS_COMPILE_LIBS}
/usr/lib
/usr/lib32
/usr/lib64
/usr/lib/i386-linux-gnu
/usr/lib/x86_64-linux-gnu
/usr/local/lib
/usr/local/lib32
/usr/local/lib64
/usr/lib/arm-linux-gnueabi
/usr/lib/arm-linux-gnueabihf
/usr/lib/aarch64-linux-gnu
NO_DEFAULT_PATH)
if(${CMAKE_MBEDCRYPTO_LIBS_INIT} MATCHES "CMAKE_MBEDCRYPTO_LIBS_INIT-NOTFOUND")
message(FATAL_ERROR "Looking for libmbedcrypto - not found")
else()
message(STATUS "Looking for libmbedcrypto - found (${CMAKE_MBEDCRYPTO_LIBS_INIT})")
endif()
find_library(CMAKE_MBEDX509_LIBS_INIT
NAME mbedx509
PATHS
${CROSS_COMPILE_LIBS}
/usr/lib
/usr/lib32
/usr/lib64
/usr/lib/i386-linux-gnu
/usr/lib/x86_64-linux-gnu
/usr/local/lib
/usr/local/lib32
/usr/local/lib64
/usr/lib/arm-linux-gnueabi
/usr/lib/arm-linux-gnueabihf
/usr/lib/aarch64-linux-gnu
NO_DEFAULT_PATH)
if(${CMAKE_MBEDX509_LIBS_INIT} MATCHES "CMAKE_MBEDX509_LIBS_INIT-NOTFOUND")
message(FATAL_ERROR "Looking for libmbedx509 - not found")
else()
message(STATUS "Looking for libmbedx509 - found (${CMAKE_MBEDX509_LIBS_INIT})")
endif()
find_library(CMAKE_LUA_LIBS_INIT
NAME luajit-5.1
PATHS
${CROSS_COMPILE_LIBS}
/usr/lib
/usr/lib32
/usr/lib64
/usr/lib/i386-linux-gnu
/usr/lib/x86_64-linux-gnu
/usr/local/lib
/usr/local/lib32
/usr/local/lib64
/usr/lib/arm-linux-gnueabi
/usr/lib/arm-linux-gnueabihf
/usr/lib/aarch64-linux-gnu
NO_DEFAULT_PATH)
if(${CMAKE_LUA_LIBS_INIT} MATCHES "CMAKE_LUA_LIBS_INIT-NOTFOUND")
message(FATAL_ERROR "Looking for libluajit - not found")
else()
message(STATUS "Looking for libluajit - found (${CMAKE_LUA_LIBS_INIT})")
endif()
include_directories(${PROJECT_SOURCE_DIR}/inc)
include_directories(${PROJECT_SOURCE_DIR}/libs/libuv)
include_directories(/usr/local/include/)
add_subdirectory(inc)
add_subdirectory(libs)
if(WIN32)
set(THREADS_USE_PTHREADS_WIN32 true)
endif()
find_package(Threads REQUIRED)
if(NOT WIN32)
if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
find_package(Backtrace REQUIRED)
endif()
endif()
if(${MODULESPACK} MATCHES "OFF" OR WIN32)
if(WIN32)
add_custom_command(OUTPUT ${PROJECT_SOURCE_DIR}/res/win32/admin.obj COMMAND ${CMAKE_RC_COMPILER} -o ${PROJECT_SOURCE_DIR}/res/win32/admin.obj ${PROJECT_SOURCE_DIR}/res/win32/admin.rc)
add_custom_command(OUTPUT ${PROJECT_SOURCE_DIR}/res/win32/icon.obj COMMAND ${CMAKE_RC_COMPILER} -o ${PROJECT_SOURCE_DIR}/res/win32/icon.obj ${PROJECT_SOURCE_DIR}/res/win32/icon.rc)
add_library(admin STATIC ${PROJECT_SOURCE_DIR}/res/win32/admin.obj)
add_library(icon STATIC ${PROJECT_SOURCE_DIR}/res/win32/icon.obj)
set_source_files_properties(${PROJECT_SOURCE_DIR}/res/win32/admin.obj PROPERTIES EXTERNAL_OBJECT true GENERATED true)
set_source_files_properties(${PROJECT_SOURCE_DIR}/res/win32/icon.obj PROPERTIES EXTERNAL_OBJECT true GENERATED true)
set_target_properties(admin PROPERTIES LINKER_LANGUAGE C)
set_target_properties(icon PROPERTIES LINKER_LANGUAGE C)
endif()
add_library(${PROJECT_NAME} OBJECT ${libs_files})
set_property(TARGET ${PROJECT_NAME} PROPERTY POSITION_INDEPENDENT_CODE TRUE)
if(WIN32)
add_library(${PROJECT_NAME}_shared STATIC $<TARGET_OBJECTS:${PROJECT_NAME}>)
else()
add_library(${PROJECT_NAME}_shared SHARED $<TARGET_OBJECTS:${PROJECT_NAME}>)
endif()
add_library(${PROJECT_NAME}_static STATIC $<TARGET_OBJECTS:${PROJECT_NAME}>)
target_link_libraries(${PROJECT_NAME}_shared ${CMAKE_THREAD_LIBS_INIT})
if(WIN32)
target_link_libraries(${PROJECT_NAME}_shared ws2_32)
target_link_libraries(${PROJECT_NAME}_shared user32)
target_link_libraries(${PROJECT_NAME}_shared userenv)
target_link_libraries(${PROJECT_NAME}_shared wsock32)
target_link_libraries(${PROJECT_NAME}_shared iphlpapi)
target_link_libraries(${PROJECT_NAME}_shared psapi)
target_link_libraries(${PROJECT_NAME}_static ws2_32)
target_link_libraries(${PROJECT_NAME}_static user32)
target_link_libraries(${PROJECT_NAME}_static userenv)
target_link_libraries(${PROJECT_NAME}_static wsock32)
target_link_libraries(${PROJECT_NAME}_static iphlpapi)
target_link_libraries(${PROJECT_NAME}_static psapi)
if(${PROTOCOL_ARPING} MATCHES "ON")
target_link_libraries(${PROJECT_NAME}_shared ${PROJECT_SOURCE_DIR}/res/win32/libwpcap.dll.a)
target_link_libraries(${PROJECT_NAME}_static ${PROJECT_SOURCE_DIR}/res/win32/libwpcap.dll.a)
endif()
endif()
target_link_libraries(${PROJECT_NAME}_shared m)
if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
target_link_libraries(${PROJECT_NAME}_shared ${Backtrace_LIBRARIES})
endif()
if(NOT WIN32)
target_link_libraries(${PROJECT_NAME}_shared rt)
endif()
target_link_libraries(${PROJECT_NAME}_shared ${CMAKE_DL_LIBS})
target_link_libraries(${PROJECT_NAME}_shared ${CMAKE_WIRINGX_LIBS_INIT})
target_link_libraries(${PROJECT_NAME}_shared ${CMAKE_MBEDTLS_LIBS_INIT})
target_link_libraries(${PROJECT_NAME}_shared ${CMAKE_MBEDCRYPTO_LIBS_INIT})
target_link_libraries(${PROJECT_NAME}_shared ${CMAKE_MBEDX509_LIBS_INIT})
target_link_libraries(${PROJECT_NAME}_shared ${CMAKE_LUA_LIBS_INIT})
target_link_libraries(${PROJECT_NAME}_static ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(${PROJECT_NAME}_static m)
if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
target_link_libraries(${PROJECT_NAME}_static ${Backtrace_LIBRARIES})
endif()
if(NOT WIN32)
target_link_libraries(${PROJECT_NAME}_static rt)
endif()
target_link_libraries(${PROJECT_NAME}_static ${CMAKE_DL_LIBS})
target_link_libraries(${PROJECT_NAME}_static ${CMAKE_WIRINGX_LIBS_INIT})
target_link_libraries(${PROJECT_NAME}_static ${CMAKE_MBEDTLS_LIBS_INIT})
target_link_libraries(${PROJECT_NAME}_static ${CMAKE_MBEDCRYPTO_LIBS_INIT})
target_link_libraries(${PROJECT_NAME}_static ${CMAKE_MBEDX509_LIBS_INIT})
target_link_libraries(${PROJECT_NAME}_static ${CMAKE_LUA_LIBS_INIT})
if(${PROTOCOL_ARPING} MATCHES "ON")
target_link_libraries(${PROJECT_NAME}_shared ${CMAKE_PCAP_LIBS_INIT})
target_link_libraries(${PROJECT_NAME}_static ${CMAKE_PCAP_LIBS_INIT})
endif()
if(NOT WIN32)
target_link_libraries(${PROJECT_NAME}_shared ${CMAKE_UNWIND_LIBS_INIT})
target_link_libraries(${PROJECT_NAME}_static ${CMAKE_UNWIND_LIBS_INIT})
endif()
set_target_properties(${PROJECT_NAME}_shared ${PROJECT_NAME}_static PROPERTIES OUTPUT_NAME ${PROJECT_NAME})
if(NOT WIN32)
install(CODE "execute_process(COMMAND rm /usr/local/lib/lib${PROJECT_NAME}.so)")
install(FILES ${CMAKE_BINARY_DIR}/lib${PROJECT_NAME}.so DESTINATION lib RENAME lib${PROJECT_NAME}.so.${VERSION} COMPONENT ${PROJECT_NAME})
install(FILES ${CMAKE_BINARY_DIR}/lib${PROJECT_NAME}.a DESTINATION lib RENAME lib${PROJECT_NAME}.a COMPONENT ${PROJECT_NAME})
install(CODE "execute_process(COMMAND ln -s \"/usr/local/lib/lib${PROJECT_NAME}.so.${VERSION}\" \"/usr/local/lib/lib${PROJECT_NAME}.so\")")
if(EXISTS "/usr/local/lib/${PROJECT_NAME}/protocols")
install(CODE "execute_process(COMMAND find /usr/local/lib/${PROJECT_NAME}/protocols/ -type f -exec rm {} \\;)")
endif()
if(EXISTS "/usr/local/lib/${PROJECT_NAME}/hardware")
install(CODE "execute_process(COMMAND find /usr/local/lib/${PROJECT_NAME}/hardware/ -type f -exec rm {} \\;)")
endif()
if(EXISTS "/usr/local/lib/${PROJECT_NAME}/actions")
install(CODE "execute_process(COMMAND find /usr/local/lib/${PROJECT_NAME}/actions/ -type f -exec rm {} \\;)")
endif()
if(EXISTS "/usr/local/lib/${PROJECT_NAME}/operators")
install(CODE "execute_process(COMMAND find /usr/local/lib/${PROJECT_NAME}/operators/ -type f -exec rm {} \\;)")
endif()
if(EXISTS "/usr/local/${PROJECT_NAME}/operators")
install(CODE "execute_process(COMMAND find /usr/local/${PROJECT_NAME}/operators/ -type f -exec rm {} \\;)")
endif()
if(EXISTS "/etc/${PROJECT_NAME}/config.json")
install(CODE "execute_process(COMMAND mv /etc/${PROJECT_NAME}/config.json /etc/${PROJECT_NAME}/config.json.bak)")
endif()
if(EXISTS "/etc/${PROJECT_NAME}/pilight.pem")
install(CODE "execute_process(COMMAND mv /etc/${PROJECT_NAME}/pilight.pem /etc/${PROJECT_NAME}/pilight.pem.bak)")
endif()
install(PROGRAMS ${PROJECT_SOURCE_DIR}/res/init/${PROJECT_NAME}.initd DESTINATION /etc/init.d/ RENAME ${PROJECT_NAME})
install(FILES ${PROJECT_SOURCE_DIR}/res/config/config.json-default DESTINATION /etc/${PROJECT_NAME}/ RENAME config.json COMPONENT ${PROJECT_NAME})
install(FILES ${PROJECT_SOURCE_DIR}/res/pilight.pem DESTINATION /etc/${PROJECT_NAME}/ COMPONENT ${PROJECT_NAME})
else()
# install(FILES ${CMAKE_BINARY_DIR}/lib${PROJECT_NAME}.dll DESTINATION . RENAME lib${PROJECT_NAME}.dll COMPONENT ${PROJECT_NAME})
install(FILES ${PROJECT_SOURCE_DIR}/res/config/config.json-default-w32 DESTINATION . RENAME config.json-default COMPONENT ${PROJECT_NAME})
endif()
if(${WEBSERVER} MATCHES "ON")
if(WIN32)
install(DIRECTORY ${PROJECT_SOURCE_DIR}/libs/webgui/ DESTINATION web/ COMPONENT webgui)
else()
install(DIRECTORY ${PROJECT_SOURCE_DIR}/libs/webgui/ DESTINATION /usr/local/lib/${PROJECT_NAME}/webgui COMPONENT webgui)
endif()
endif()
if(WIN32)
add_executable(${PROJECT_NAME}-daemon daemon.c ${PROJECT_SOURCE_DIR}/res/win32/icon.obj)
target_link_libraries(${PROJECT_NAME}-daemon "-Wl,--subsystem,windows")
else()
add_executable(${PROJECT_NAME}-daemon daemon.c)
endif()
target_link_libraries(${PROJECT_NAME}-daemon ${PROJECT_NAME}_shared)
if(${ZWAVE} MATCHES "ON")
target_link_libraries(${PROJECT_NAME}-daemon stdc++)
endif()
target_link_libraries(${PROJECT_NAME}-daemon ${CMAKE_DL_LIBS})
target_link_libraries(${PROJECT_NAME}-daemon m)
if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
target_link_libraries(${PROJECT_NAME}-daemon ${Backtrace_LIBRARIES})
endif()
target_link_libraries(${PROJECT_NAME}-daemon ${CMAKE_THREAD_LIBS_INIT})
# if(WIN32)
# add_executable(${PROJECT_NAME}-unittest unittest.c ${PROJECT_SOURCE_DIR}/res/win32/icon.obj)
# target_link_libraries(${PROJECT_NAME}-unittest "-Wl,--subsystem,windows")
# else()
# add_executable(${PROJECT_NAME}-unittest unittest.c)
# endif()
# target_link_libraries(${PROJECT_NAME}-unittest ${PROJECT_NAME}_shared)
# if(${ZWAVE} MATCHES "ON")
# target_link_libraries(${PROJECT_NAME}-unittest stdc++)
# endif()
# target_link_libraries(${PROJECT_NAME}-unittest ${CMAKE_DL_LIBS})
# target_link_libraries(${PROJECT_NAME}-unittest m)
# if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
# target_link_libraries(${PROJECT_NAME}-unittest ${Backtrace_LIBRARIES})
# endif()
# target_link_libraries(${PROJECT_NAME}-unittest ${CMAKE_THREAD_LIBS_INIT})
if(WIN32)
add_executable(${PROJECT_NAME}-raw raw.c ${PROJECT_SOURCE_DIR}/res/win32/icon.obj)
else()
add_executable(${PROJECT_NAME}-raw raw.c)
endif()
target_link_libraries(${PROJECT_NAME}-raw ${PROJECT_NAME}_shared)
if(${ZWAVE} MATCHES "ON")
target_link_libraries(${PROJECT_NAME}-raw stdc++)
endif()
target_link_libraries(${PROJECT_NAME}-raw ${CMAKE_DL_LIBS})
target_link_libraries(${PROJECT_NAME}-raw m)
if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
target_link_libraries(${PROJECT_NAME}-raw ${Backtrace_LIBRARIES})
endif()
target_link_libraries(${PROJECT_NAME}-raw ${CMAKE_THREAD_LIBS_INIT})
if(WIN32)
add_executable(${PROJECT_NAME}-send send.c ${PROJECT_SOURCE_DIR}/res/win32/icon.obj)
else()
add_executable(${PROJECT_NAME}-send send.c)
endif()
target_link_libraries(${PROJECT_NAME}-send ${PROJECT_NAME}_shared)
target_link_libraries(${PROJECT_NAME}-send ${CMAKE_DL_LIBS})
if(${ZWAVE} MATCHES "ON")
target_link_libraries(${PROJECT_NAME}-send stdc++)
endif()
target_link_libraries(${PROJECT_NAME}-send m)
if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
target_link_libraries(${PROJECT_NAME}-send ${Backtrace_LIBRARIES})
endif()
target_link_libraries(${PROJECT_NAME}-send ${CMAKE_THREAD_LIBS_INIT})
if(WIN32)
add_executable(${PROJECT_NAME}-control control.c ${PROJECT_SOURCE_DIR}/res/win32/icon.obj)
else()
add_executable(${PROJECT_NAME}-control control.c)
endif()
target_link_libraries(${PROJECT_NAME}-control ${PROJECT_NAME}_shared)
target_link_libraries(${PROJECT_NAME}-control ${CMAKE_DL_LIBS})
if(${ZWAVE} MATCHES "ON")
target_link_libraries(${PROJECT_NAME}-control stdc++)
endif()
target_link_libraries(${PROJECT_NAME}-control m)
if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
target_link_libraries(${PROJECT_NAME}-control ${Backtrace_LIBRARIES})
endif()
target_link_libraries(${PROJECT_NAME}-control ${CMAKE_THREAD_LIBS_INIT})
if(WIN32)
add_executable(${PROJECT_NAME}-receive receive.c ${PROJECT_SOURCE_DIR}/res/win32/icon.obj)
else()
add_executable(${PROJECT_NAME}-receive receive.c)
endif()
target_link_libraries(${PROJECT_NAME}-receive ${PROJECT_NAME}_shared)
if(${ZWAVE} MATCHES "ON")
target_link_libraries(${PROJECT_NAME}-receive stdc++)
endif()
target_link_libraries(${PROJECT_NAME}-receive ${CMAKE_DL_LIBS})
target_link_libraries(${PROJECT_NAME}-receive m)
if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
target_link_libraries(${PROJECT_NAME}-receive ${Backtrace_LIBRARIES})
endif()
target_link_libraries(${PROJECT_NAME}-receive ${CMAKE_THREAD_LIBS_INIT})
if(WIN32)
add_executable(${PROJECT_NAME}-debug debug.c ${PROJECT_SOURCE_DIR}/res/win32/icon.obj)
else()
add_executable(${PROJECT_NAME}-debug debug.c)
endif()
target_link_libraries(${PROJECT_NAME}-debug ${PROJECT_NAME}_shared)
if(${ZWAVE} MATCHES "ON")
target_link_libraries(${PROJECT_NAME}-debug stdc++)
endif()
target_link_libraries(${PROJECT_NAME}-debug ${CMAKE_DL_LIBS})
target_link_libraries(${PROJECT_NAME}-debug m)
if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
target_link_libraries(${PROJECT_NAME}-debug ${Backtrace_LIBRARIES})
endif()
target_link_libraries(${PROJECT_NAME}-debug ${CMAKE_THREAD_LIBS_INIT})
if(WIN32)
add_executable(${PROJECT_NAME}-uuid uuid.c ${PROJECT_SOURCE_DIR}/res/win32/icon.obj)
else()
add_executable(${PROJECT_NAME}-uuid uuid.c)
endif()
target_link_libraries(${PROJECT_NAME}-uuid ${PROJECT_NAME}_shared)
if(${ZWAVE} MATCHES "ON")
target_link_libraries(${PROJECT_NAME}-uuid stdc++)
endif()
target_link_libraries(${PROJECT_NAME}-uuid ${CMAKE_DL_LIBS})
target_link_libraries(${PROJECT_NAME}-uuid m)
if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
target_link_libraries(${PROJECT_NAME}-uuid ${Backtrace_LIBRARIES})
endif()
target_link_libraries(${PROJECT_NAME}-uuid ${CMAKE_THREAD_LIBS_INIT})
if(WIN32)
add_executable(${PROJECT_NAME}-sha256 sha256.c ${PROJECT_SOURCE_DIR}/res/win32/icon.obj)
else()
add_executable(${PROJECT_NAME}-sha256 sha256.c)
endif()
target_link_libraries(${PROJECT_NAME}-sha256 ${PROJECT_NAME}_shared)
if(${ZWAVE} MATCHES "ON")
target_link_libraries(${PROJECT_NAME}-sha256 stdc++)
endif()
target_link_libraries(${PROJECT_NAME}-sha256 ${CMAKE_DL_LIBS})
target_link_libraries(${PROJECT_NAME}-sha256 m)
if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
target_link_libraries(${PROJECT_NAME}-sha256 ${Backtrace_LIBRARIES})
endif()
target_link_libraries(${PROJECT_NAME}-sha256 ${CMAKE_THREAD_LIBS_INIT})
if(WIN32)
add_executable(${PROJECT_NAME}-flash flash.c ${PROJECT_SOURCE_DIR}/res/win32/icon.obj)
else()
add_executable(${PROJECT_NAME}-flash flash.c)
endif()
target_link_libraries(${PROJECT_NAME}-flash ${PROJECT_NAME}_shared)
if(${ZWAVE} MATCHES "ON")
target_link_libraries(${PROJECT_NAME}-flash stdc++)
endif()
target_link_libraries(${PROJECT_NAME}-flash ${CMAKE_DL_LIBS})
target_link_libraries(${PROJECT_NAME}-flash m)
if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
target_link_libraries(${PROJECT_NAME}-flash ${Backtrace_LIBRARIES})
endif()
target_link_libraries(${PROJECT_NAME}-flash ${CMAKE_THREAD_LIBS_INIT})
if(WIN32)
install(FILES "${PROJECT_SOURCE_DIR}/res/firmware/${PROJECT_NAME}_usb_nano.hex" DESTINATION . COMPONENT ${PROJECT_NAME})
endif()
if(NOT WIN32)
if(EXISTS "/usr/local/sbin/${PROJECT_NAME}-send")
install(CODE "execute_process(COMMAND rm /usr/local/sbin/${PROJECT_NAME}-send)")
endif()
if(EXISTS "/usr/local/sbin/${PROJECT_NAME}-receive")
install(CODE "execute_process(COMMAND rm /usr/local/sbin/${PROJECT_NAME}-receive)")
endif()
if(EXISTS "/usr/local/sbin/${PROJECT_NAME}-control")
install(CODE "execute_process(COMMAND rm /usr/local/sbin/${PROJECT_NAME}-control)")
endif()
if(EXISTS "/usr/local/sbin/${PROJECT_NAME}-uuid")
install(CODE "execute_process(COMMAND rm /usr/local/sbin/${PROJECT_NAME}-uuid)")
endif()
endif()
if(WIN32)
install(FILES "${PROJECT_SOURCE_DIR}/LICENSE.txt" DESTINATION . COMPONENT ${PROJECT_NAME})
install(FILES "${PROJECT_SOURCE_DIR}/res/win32/libmbedx509.dll" DESTINATION . COMPONENT ${PROJECT_NAME})
install(FILES "${PROJECT_SOURCE_DIR}/res/win32/libmbedcrypto.dll" DESTINATION . COMPONENT ${PROJECT_NAME})
install(FILES "${PROJECT_SOURCE_DIR}/res/win32/libmbedtls.dll" DESTINATION . COMPONENT ${PROJECT_NAME})
install(FILES "${PROJECT_SOURCE_DIR}/res/win32/libwinpthread-1.dll" DESTINATION . COMPONENT ${PROJECT_NAME})
install(FILES "${PROJECT_SOURCE_DIR}/res/win32/Packet.dll" DESTINATION . COMPONENT ${PROJECT_NAME})
install(FILES "${PROJECT_SOURCE_DIR}/res/win32/wpcap.dll" DESTINATION . COMPONENT ${PROJECT_NAME})
install(PROGRAMS ${CMAKE_BINARY_DIR}/${PROJECT_NAME}-daemon.exe DESTINATION . COMPONENT ${PROJECT_NAME})
install(PROGRAMS ${CMAKE_BINARY_DIR}/${PROJECT_NAME}-raw.exe DESTINATION . COMPONENT ${PROJECT_NAME})
install(PROGRAMS ${CMAKE_BINARY_DIR}/${PROJECT_NAME}-send.exe DESTINATION . COMPONENT ${PROJECT_NAME})
install(PROGRAMS ${CMAKE_BINARY_DIR}/${PROJECT_NAME}-control.exe DESTINATION . COMPONENT ${PROJECT_NAME})
install(PROGRAMS ${CMAKE_BINARY_DIR}/${PROJECT_NAME}-receive.exe DESTINATION . COMPONENT ${PROJECT_NAME})
install(PROGRAMS ${CMAKE_BINARY_DIR}/${PROJECT_NAME}-debug.exe DESTINATION . COMPONENT ${PROJECT_NAME})
install(PROGRAMS ${CMAKE_BINARY_DIR}/${PROJECT_NAME}-flash.exe DESTINATION . COMPONENT ${PROJECT_NAME})
install(PROGRAMS ${CMAKE_BINARY_DIR}/${PROJECT_NAME}-uuid.exe DESTINATION . COMPONENT ${PROJECT_NAME})
install(PROGRAMS ${CMAKE_BINARY_DIR}/${PROJECT_NAME}-sha256.exe DESTINATION . COMPONENT ${PROJECT_NAME})
else()
install(PROGRAMS ${CMAKE_BINARY_DIR}/${PROJECT_NAME}-daemon DESTINATION sbin COMPONENT ${PROJECT_NAME})
install(PROGRAMS ${CMAKE_BINARY_DIR}/${PROJECT_NAME}-raw DESTINATION sbin COMPONENT ${PROJECT_NAME})
install(PROGRAMS ${CMAKE_BINARY_DIR}/${PROJECT_NAME}-send DESTINATION bin COMPONENT ${PROJECT_NAME})
install(PROGRAMS ${CMAKE_BINARY_DIR}/${PROJECT_NAME}-control DESTINATION bin COMPONENT ${PROJECT_NAME})
install(PROGRAMS ${CMAKE_BINARY_DIR}/${PROJECT_NAME}-receive DESTINATION bin COMPONENT ${PROJECT_NAME})
install(PROGRAMS ${CMAKE_BINARY_DIR}/${PROJECT_NAME}-debug DESTINATION sbin COMPONENT ${PROJECT_NAME})
install(PROGRAMS ${CMAKE_BINARY_DIR}/${PROJECT_NAME}-flash DESTINATION sbin COMPONENT ${PROJECT_NAME})
install(PROGRAMS ${CMAKE_BINARY_DIR}/${PROJECT_NAME}-uuid DESTINATION bin COMPONENT ${PROJECT_NAME})
install(PROGRAMS ${CMAKE_BINARY_DIR}/${PROJECT_NAME}-sha256 DESTINATION bin COMPONENT ${PROJECT_NAME})
install(CODE "execute_process(COMMAND update-rc.d ${PROJECT_NAME} defaults)")
install(CODE "execute_process(COMMAND ldconfig)")
endif()
endif()
if(WIN32)
set(CPACK_MONOLITHIC_INSTALL True)
set(CPACK_NSIS_INSTALL_ROOT "c:")
set(CPACK_PACKAGE_INSTALL_DIRECTORY "${PROJECT_NAME}")
set(CPACK_NSIS_DISPLAY_NAME "${PROJECT_NAME}")
set(CPACK_NSIS_PACKAGE_NAME "${PROJECT_NAME} ${git_ver}")
set(CPACK_NSIS_URL_INFO_ABOUT "http://www.${PROJECT_NAME}.org")
set(CPACK_NSIS_CONTACT "info@${PROJECT_NAME}.org")
set(CPACK_NSIS_EXECUTABLES_DIRECTORY ".")
set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL True)
set(CPACK_NSIS_MENU_LINKS
"${PROJECT_NAME}-daemon" "${PROJECT_NAME}-daemon"
)
set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE.txt")
# set(CPACK_COMPONENTS_ALL ${PROJECT_NAME} webgui)
set(CPACK_GENERATOR "NSIS")
set(CPACK_PACKAGING_INSTALL_DIRECTORY "${PROJECT_NAME}")
set(CPACK_SOURCE_STRIP_FILES TRUE)
set(CPACK_STRIP_FILES TRUE)
set(CPACK_PACKAGE_CONTACT "CurlyMo <info@${PROJECT_NAME}.org>")
set(CPACK_PACKAGE_VERSION ${git_ver})
set(CPACK_PACKAGE_NAME "${PROJECT_NAME}")
set(CPACK_PACKAGE_VENDOR "${PROJECT_NAME}")
set(CPACK_PACKAGE_DESCRIPTION "Control RF devices with the Raspberry Pi")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Control RF devices with the Raspberry Pi")
include(CPack)
else()
WRITE_UNINSTALL_TARGET_SCRIPT()
configure_file("${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
IMMEDIATE @ONLY)
add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
set(CPACK_GENERATOR "DEB")
set(CPACK_PACKAGING_INSTALL_PREFIX "/usr/local/")
set(CPACK_SOURCE_STRIP_FILES TRUE)
set(CPACK_STRIP_FILES TRUE)
set(CPACK_PACKAGE_CONTACT "CurlyMo <info@${PROJECT_NAME}.org>")
set(CPACK_PACKAGE_VERSION ${VERSION})
set(CPACK_PACKAGE_NAME "${PROJECT_NAME}")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "zlib1g-dev")
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
set(CPACK_PACKAGE_DESCRIPTION "Control RF devices with the Raspberry Pi")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Control RF devices with the Raspberry Pi")
include(CPack)
message("")
message("${Red}-- WARNING --${ColorReset}")
message("${Yellow}Manually compiling and installing ${PROJECT_NAME} will also clear all module folders:
/usr/local/lib/${PROJECT_NAME}/protocols/
/usr/local/lib/${PROJECT_NAME}/hardware/
/usr/local/lib/${PROJECT_NAME}/actions/
/usr/local/lib/${PROJECT_NAME}/operators/${ColorReset}")
message("${Red}-- WARNING --${ColorReset}")
message("")
endif()
+77
View File
@@ -0,0 +1,77 @@
Rules for contributing to pilight
=================================
First of all, thanks for making this project better. Without your help, pilight wouldn't have come to what it is now!
**BUT**, be aware that contributing to a big project shouldn't be considered a playground. It also isn't meant for you to learn `git`.
So if you don't know what you are doing then don't do it. Instead open a [forum topic](http://forum.pilight.org), point to your code and ask for help.
Checklist
---------
When you contribute to pilight make sure to follow this checklist:
1. Is your pull request directed at the development branch?
*pilight doesn't accept contributions to the master branch because this branch reflects the latest stable code.*
2. Did you read the [development](http://manual.pilight.org/development/) pages of pilight?
*Even if you think you know all, please check and double check. There are always small syntax changes. Also check similar already existing modules for syntax.*
3. Keep the coding style in sync with that of pilight (see below).
4. First merge with the latest development code.
5. Make a different branch for each new feature you want to commit.
6. Test how pull-requests work on your own test repositories.
7. Make sure your pull-request contains [one single commit](http://eli.thegreenplace.net/2014/02/19/squashing-github-pull-requests-into-a-single-commit).
8. Open a pull-request when you indeed want to contribute and follow-up on our comments. If you don't want to implement our requested changes after reviewing your pull-request, don't bother opening one.
9. Re-read this file before every pull-request, because it will be updated regularly.
10. Don't forget to enjoy the appreciation of the end user!
Coding style
-----
- No unnecessary spaces
```
if ( 1 == 1 )
{
...
}
```
should become:
```
if(1 == 1) {
...
}
```
- Don't inline variables:
```
int x = 0;
int long_variable_name = 0;
int a = 0;
```
but use
```
int x = 0;
int long_variable_name = 0;
int a = 0;
```
but preferable use for around max 50 characters:
```
int x = 0, long_variable_name = 0, a = 0;
```
- Variable defining order.
First start with `struct`, then specials types (`*_t`), then `char`, then `double` / `float` and end with `int`.
```
struct protocol_threads_t *node = (struct protocol_threads_t *)param;
struct JsonNode *json = (struct JsonNode *)node->param;
struct JsonNode *jid = NULL;
struct JsonNode *jchild = NULL;
time_t time;
char *tmp = NULL;
double itmp = 0.0;
int id = 0, state = 0, nstate = 0;
```
- Initialize your variables.
```
char *a = NULL;
char a[10];
memset(&a, 0, 10);
double a = 0.0;
int a = 0;
```
- User the `static` keyword for all variables and function only use in the single C file your module consists of.
- Always use tabs instead of spaces for inline markup.
+674
View File
@@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+674
View File
@@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+20
View File
@@ -0,0 +1,20 @@
pilight version 7.0
=======
<a class="donate" href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=curlymoo1%40gmail%2ecom&lc=US&item_name=curlymoo&no_note=0&currency_code=USD&bn=PP%2dDonationsBF%3abtn_donate_SM%2egif%3aNonHostedGuest" target="_blank">
<img alt="PayPal" title="PayPal" border="0" src="https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif" style="max-width:100%;"></a>
<a href="https://flattr.com/submit/auto?user_id=pilight&url=http%3A%2F%2Fwww.pilight.org" target="_blank"><img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0"></a>
Visit http://www.pilight.org or http://wiki.pilight.org for more information.
# Dependencies
The pilight development code depends on the following packages:
1. [libmbedtls](https://github.com/ARMmbed/mbedtls)
2. [libmbedx509](https://github.com/ARMmbed/mbedtls)
3. [libmbedcrypto](https://github.com/ARMmbed/mbedtls)
4. [liblua5.2](https://github.com/lua/lua)
5. [libwiringx](https://github.com/wiringx/wiringx) (rewrite branch)
6. [libpcap](http://www.tcpdump.org/release/)
7. [libunwind](http://download.savannah.nongnu.org/releases/libunwind/)
Either manually compile each of these packages or install them by using the package repository of your distribution of choice
+147
View File
@@ -0,0 +1,147 @@
/*
Copyright (C) 2013 CurlyMo
This file is part of pilight.
pilight is free software: you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with pilight. If not, see <http://www.gnu.org/licenses/>
*/
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ByteArrayInputStream;
import java.io.StringReader;
import java.nio.charset.Charset;
import java.io.PrintStream;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.Collections;
import java.util.Enumeration;
import sun.net.*;
import java.net.*;
import java.util.Date;
public class process {
public static void main(String[] args) {
String line = null;
DatagramSocket ssdp = null;
PrintStream printStream = null;
BufferedReader bufferedReader = null;
int port = 0;
String server = null;
Socket socket = null;
String msg = "M-SEARCH * HTTP/1.1\r\n"
+ "Host:239.255.255.250:1900\r\n"
+ "ST:urn:schemas-upnp-org:service:pilight:1\r\n"
+ "Man:\"ssdp:discover\"\r\n"
+ "MX:3\r\n\r\n";
try {
Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
for(NetworkInterface netint : Collections.list(nets)) {
Enumeration<InetAddress> inetAddresses = netint.getInetAddresses();
for(InetAddress inetAddress : Collections.list(inetAddresses)) {
if(!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) {
try {
ssdp = new DatagramSocket(new InetSocketAddress(inetAddress.getHostAddress().toString(), 0));
byte[] buff = msg.getBytes();
DatagramPacket sendPack = new DatagramPacket(buff, buff.length);
sendPack.setAddress(InetAddress.getByName("239.255.255.250"));
sendPack.setPort(1900);
try {
ssdp.send(sendPack);
ssdp.setSoTimeout(10);
boolean loop = true;
while(loop) {
DatagramPacket recvPack = new DatagramPacket(new byte[1024], 1024);
ssdp.receive(recvPack);
byte[] recvData = recvPack.getData();
InputStreamReader recvInput = new InputStreamReader(new ByteArrayInputStream(recvData), Charset.forName("UTF-8"));
StringBuilder recvOutput = new StringBuilder();
for(int value; (value = recvInput.read()) != -1;) {
recvOutput.append((char)value);
}
BufferedReader bufReader = new BufferedReader(new StringReader(recvOutput.toString()));
Pattern pattern = Pattern.compile("Location:([0-9.]+):(.*)");
while((line=bufReader.readLine()) != null) {
Matcher matcher = pattern.matcher(line);
if(matcher.matches()) {
server = matcher.group(1);
port = Integer.parseInt(matcher.group(2));
loop = false;
break;
}
}
}
} catch(SocketTimeoutException e) {
} catch(IOException e) {
System.out.println("no pilight ssdp connections found");
ssdp.close();
System.exit(0);
}
} catch(UnknownHostException e) {
}
}
}
}
} catch(SocketException e) {
}
if(server == null || port == 0) {
System.out.println("no pilight ssdp connections found");
System.exit(0);
}
try {
socket = new Socket();
socket.connect(new InetSocketAddress(server, port), 1000);
try {
if(printStream == null) {
printStream = new PrintStream(socket.getOutputStream(), false);
}
printStream.print("{\"action\":\"identify\",\"options\":{\"receiver\":1}}\n");
printStream.flush();
} catch(IOException e) {
System.out.println("failed to write messages to server");
}
int size = 0;
if(size == 0) {
size = 1025;
}
try {
if(bufferedReader == null) {
bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"), size);
}
int c = 0;
StringBuilder response = new StringBuilder();
if(bufferedReader.ready()) {
while((c = bufferedReader.read()) > 0) {
response.append((char)c);
}
System.out.println(response.toString());
}
} catch(IOException e) {
System.out.println("failed to receive messages from server");
}
} catch (UnknownHostException e) {
System.out.println("don't know about host");
} catch(IOException e) {
System.out.println("could not get I/O for connection");
}
}
}
+69
View File
@@ -0,0 +1,69 @@
#!/usr/bin/env php
<?php
/*
Copyright (C) 2013 CurlyMo
This file is part of pilight.
pilight is free software: you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with pilight. If not, see <http://www.gnu.org/licenses/>
*/
$sMsg = "M-SEARCH * HTTP/1.1\r\n";
$sMsg .= "Host:239.255.255.250:1900\r\n";
$sMsg .= "ST:urn:schemas-upnp-org:service:pilight:1\r\n";
$sMsg .= "Man:\"ssdp:discover\"\r\n";
$sMsg .= "MX:3\r\n\r\n";
$sBuffer = NULL;
$sTmp = NULL;
$rSocket = socket_create(AF_INET, SOCK_DGRAM, 0);
socket_set_option($rSocket, SOL_SOCKET, SO_RCVTIMEO, array('sec'=>0, 'usec'=>10000));
$send_ret = socket_sendto($rSocket, $sMsg, 1024, 0, '239.255.255.250', 1900);
$aHosts = Array();
$x = 0;
while(@socket_recvfrom($rSocket, $sBuffer, 1024, MSG_WAITALL, $sTmp, $sTmp)) {
if(strpos($sBuffer, 'pilight') !== false) {
$aLines = explode("\r\n", $sBuffer);
foreach($aLines as $sLine) {
if(sscanf($sLine, "Location:%d.%d.%d.%d:%d\r\n", $ip1, $ip2, $ip3, $ip4, $port) > 0) {
$ip = $ip1.'.'.$ip2.'.'.$ip3.'.'.$ip4;
$aHosts[$x]['ip'] = $ip;
$aHosts[$x]['port'] = $port;
$x++;
}
}
}
}
socket_close($rSocket);
$sLine = '';
if(count($aHosts) > 0) {
$fp = fsockopen($aHosts[0]['ip'], $aHosts[0]['port'], $errno, $errdesc) or die ("Couldn't connect to server");
fputs($fp, '{"action":"identify","options":{"receiver":1}}');
$sLine = fgets($fp, 1024);
if($sLine == "{\"status\":\"success\"}\n") {
$iLen = 0;
$sLine = '';
while(true) {
$sLine .= fgets($fp, 1024);
$iLen = strlen($sLine);
if($iLen > 2 && ord($sLine[$iLen-1]) === 10 && ord($sLine[$iLen-2]) === 10) {
$sLine = substr($sLine, 0, -2);
echo $sLine."\n";
$sLine = '';
}
}
}
} else {
die("no pilight ssdp connections found\n");
}
?>
+65
View File
@@ -0,0 +1,65 @@
#!/usr/bin/env perl
#
# Copyright (C) 2013 CurlyMo
#
# This file is part of pilight.
#
# pilight is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# pilight is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with pilight. If not, see <http://www.gnu.org/licenses/>
#
use IO::Socket;
socket(sock, PF_INET, SOCK_DGRAM, getprotobyname("udp")) or die "socket:$@";
setsockopt(sock, SOL_SOCKET, SO_BROADCAST, 1) or die "setsockopt:$@";
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, pack('l!l!', 0, 10000)) or die "setsockopt:$@";
my $dest = sockaddr_in(1900, inet_aton('239.255.255.250'));
$msg = "M-SEARCH * HTTP/1.1\r\n";
$msg .= "Host:239.255.255.250:1900\r\n";
$msg .= "ST:urn:schemas-upnp-org:service:pilight:1\r\n";
$msg .= "Man:\"ssdp:discover\"\r\n";
$msg .= "MX:3\r\n\r\n";
my $ip = '';
my $port = '';
send(sock, $msg, 1024, $dest);
while(recv(sock, $data, 1024, $dest)) {
if(index($data, "pilight") != -1) {
foreach(split(/\r\n/, $data)) {
$_ =~ /Location:([0-9\.]+):([0-9]+)/ || next;
($ip,$port) = ($1,$2);
}
}
}
$socket = new IO::Socket::INET (
PeerHost => $ip,
PeerPort => $port,
Proto => 'tcp',
) or die "no pilight ssdp connections found\n";
$socket->send('{"action":"identify","options":{"receiver":1}}');
$socket->recv($recv_data, 1024);
my $text = '';
while(1) {
$text = '';
while(1) {
$socket->recv($recv_data, 1024);
$text .= $recv_data;
if($recv_data[(length $recv_data)-1] == '\n' || $recv_data[(length $recv_data)] == '\n') {
$text = substr $text, 0, -1;
last;
}
}
print $text;
}
+109
View File
@@ -0,0 +1,109 @@
#!/usr/bin/env python
#
# Copyright (C) 2017 pilino1234
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
"""Example Python 2 client for pilight daemon socket API
Runs a SSDP discovery for pilight daemons on the network, and connects to it.
Identifies as a "receiver" type client, and prints received messages until
terminated.
"""
import socket
import struct
import re
def discover(service, retries=1):
"""SSDP discovery function
:param service: The name of the SSDP service to run discovery for
:type service: str
:param retries: The number of discovery retries. Defaults to 1.
:type retries: int
"""
group = ("239.255.255.250", 1900)
message = "\r\n".join([
'M-SEARCH * HTTP/1.1',
'HOST: {0}:{1}'.format(*group),
'MAN: "ssdp:discover"',
'ST: {st}', 'MX: 3', '', ''])
ssdp_responses = {}
for i in range(retries):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM,
socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO,
struct.pack('LL', 0, 10000))
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2)
sock.sendto(message.format(st=service), group)
while True:
try:
ssdp_responses[i] = sock.recv(1024)
break
except socket.timeout:
break
except IOError:
print "no pilight ssdp connections found"
break
sock.close()
return ssdp_responses
if __name__ == "__main__":
RESPONSES = discover("urn:schemas-upnp-org:service:pilight:1")
if len(RESPONSES) > 0:
for resp in RESPONSES:
locationsrc = re.search('Location:([0-9.]+):(.*)',
str(RESPONSES[0]), re.IGNORECASE)
if locationsrc:
location = locationsrc.group(1)
port = locationsrc.group(2)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.setdefaulttimeout(0)
try:
s.connect((location, int(port)))
except ConnectionRefusedError:
# Connection was refused, try next SSDP response
print "connection refused"
continue
s.send('{"action": "identify", "options": {"core": 1}}')
text = ""
while True:
line = s.recv(1024)
text += line
if "\n\n" in line[-2:]:
text = text[:-2]
break
if text == '{"status":"success"}':
text = ""
while True:
line = s.recv(1024)
text += line
if "\n\n" in line[-2:]:
text = text[:-2]
for f in iter(text.splitlines()):
print f
text = ""
elif text == '{"status":"failure"}':
# connection failed, try next SSDP response
print "connection failed"
continue
s.close()
+108
View File
@@ -0,0 +1,108 @@
#!/usr/bin/env python
#
# Copyright (C) 2017 pilino1234
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
"""Example Python 3 client for pilight daemon socket API
Runs a SSDP discovery for pilight daemons on the network, and connects to it.
Identifies as a "receiver" type client, and prints received messages until
terminated.
"""
import socket
import struct
import re
def discover(service, retries=1):
"""SSDP discovery function
:param service: The name of the SSDP service to run discovery for
:type service: str
:param retries: The number of discovery retries. Defaults to 1.
:type retries: int
"""
group = ("239.255.255.250", 1900)
discover_message = "\r\n".join([
'M-SEARCH * HTTP/1.1',
'HOST: {0}:{1}'.format(*group),
'MAN: "ssdp:discover"',
'ST: {st}', 'MX: 3', '', '']).format(st=service)
ssdp_responses = {}
for i in range(retries):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM,
socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO,
struct.pack('LL', 0, 10000))
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2)
sock.sendto(bytes(discover_message, "utf-8"), group)
while True:
try:
ssdp_responses[i] = sock.recv(1024).decode("utf-8")
break
except socket.timeout:
break
except IOError:
print("no pilight ssdp connections found")
break
sock.close()
return ssdp_responses
if __name__ == "__main__":
RESPONSES = discover("urn:schemas-upnp-org:service:pilight:1")
if len(RESPONSES) > 0:
for resp in RESPONSES: # try all responses until one works
locationsrc = re.search("Location:([0-9.]+):(.*)",
str(RESPONSES[resp]), re.IGNORECASE)
if locationsrc:
location = locationsrc.group(1)
port = locationsrc.group(2)
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
try:
s.connect((location, int(port)))
except ConnectionRefusedError:
# Connection was refused, try next SSDP response
print("connection refused")
continue
s.send(bytes('{"action": "identify", \
"options": {"receiver": 1}}', "utf-8"))
response = ""
while True:
line = s.recv(1024).decode("utf-8")
response += line
if "\n\n" in line[-2:]:
response = response[:-2]
break
if response == '{"status":"success"}':
message = ""
while True:
line = s.recv(1024).decode("utf-8")
message += line
if "\n\n" in line[-2:]:
message = message[:-2]
for f in iter(message.splitlines()):
print(f)
message = ""
elif response == '{"status":"failure"}':
# connection failed, try next SSDP response
print("connection failed")
continue
+359
View File
@@ -0,0 +1,359 @@
/*
Copyright (C) 2013 - 2014 CurlyMo
This file is part of pilight.
pilight is free software: you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with pilight. If not, see <http://www.gnu.org/licenses/>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#ifndef _WIN32
#include <wiringx.h>
#endif
#include "libs/pilight/core/threads.h"
#include "libs/pilight/core/pilight.h"
#include "libs/pilight/core/common.h"
#include "libs/pilight/core/config.h"
#include "libs/pilight/core/log.h"
#include "libs/pilight/core/options.h"
#include "libs/pilight/core/socket.h"
#include "libs/pilight/core/json.h"
#include "libs/pilight/core/ssdp.h"
#include "libs/pilight/core/dso.h"
#include "libs/pilight/core/gc.h"
#include "libs/pilight/config/devices.h"
#include "libs/pilight/protocols/protocol.h"
#include "libs/pilight/events/events.h"
int main(int argc, char **argv) {
// memtrack();
atomicinit();
struct options_t *options = NULL;
struct ssdp_list_t *ssdp_list = NULL;
struct devices_t *dev = NULL;
struct JsonNode *json = NULL;
struct JsonNode *tmp = NULL;
char *recvBuff = NULL, *message = NULL, *output = NULL;
char *device = NULL, *state = NULL, *values = NULL;
char *server = NULL;
int has_values = 0, sockfd = 0, hasconfarg = 0;
unsigned short port = 0, showhelp = 0, showversion = 0;
log_file_disable();
log_shell_enable();
log_level_set(LOG_NOTICE);
if((progname = MALLOC(16)) == NULL) {
fprintf(stderr, "out of memory\n");
exit(EXIT_FAILURE);
}
strcpy(progname, "pilight-control");
/* Define all CLI arguments of this program */
options_add(&options, 'H', "help", OPTION_NO_VALUE, 0, JSON_NULL, NULL, NULL);
options_add(&options, 'V', "version", OPTION_NO_VALUE, 0, JSON_NULL, NULL, NULL);
options_add(&options, 'd', "device", OPTION_HAS_VALUE, 0, JSON_NULL, NULL, NULL);
options_add(&options, 's', "state", OPTION_HAS_VALUE, 0, JSON_NULL, NULL, NULL);
options_add(&options, 'v', "values", OPTION_HAS_VALUE, 0, JSON_NULL, NULL, NULL);
options_add(&options, 'S', "server", OPTION_HAS_VALUE, 0, JSON_NULL, NULL, "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$");
options_add(&options, 'P', "port", OPTION_HAS_VALUE, 0, JSON_NULL, NULL, "[0-9]{1,4}");
options_add(&options, 'C', "config", OPTION_HAS_VALUE, 0, JSON_NULL, NULL, NULL);
/* Store all CLI arguments for later usage
and also check if the CLI arguments where
used correctly by the user. This will also
fill all necessary values in the options struct */
while(1) {
int c;
c = options_parse(&options, argc, argv, 1, &optarg);
if(c == -1)
break;
if(c == -2) {
showhelp = 1;
break;
}
switch(c) {
case 'H':
showhelp = 1;
break;
case 'V':
showversion = 1;
break;
case 'd':
if((device = REALLOC(device, strlen(optarg)+1)) == NULL) {
fprintf(stderr, "out of memory\n");
exit(EXIT_FAILURE);
}
strcpy(device, optarg);
break;
case 's':
if((state = REALLOC(state, strlen(optarg)+1)) == NULL) {
fprintf(stderr, "out of memory\n");
exit(EXIT_FAILURE);
}
strcpy(state, optarg);
break;
case 'v':
if((values = REALLOC(values, strlen(optarg)+1)) == NULL) {
fprintf(stderr, "out of memory\n");
exit(EXIT_FAILURE);
}
strcpy(values, optarg);
break;
case 'C':
if(config_set_file(optarg) == EXIT_FAILURE) {
return EXIT_FAILURE;
}
hasconfarg = 1;
break;
case 'S':
if(!(server = REALLOC(server, strlen(optarg)+1))) {
fprintf(stderr, "out of memory\n");
exit(EXIT_FAILURE);
}
strcpy(server, optarg);
break;
case 'P':
port = (unsigned short)atoi(optarg);
break;
default:
printf("Usage: %s -l location -d device -s state\n", progname);
goto close;
break;
}
}
options_delete(options);
if(showversion == 1) {
printf("%s v%s\n", progname, PILIGHT_VERSION);
goto close;
}
if(showhelp == 1) {
printf("\t -H --help\t\t\tdisplay this message\n");
printf("\t -V --version\t\t\tdisplay version\n");
printf("\t -S --server=x.x.x.x\t\tconnect to server address\n");
printf("\t -C --config\t\t\tconfig file\n");
printf("\t -P --port=xxxx\t\t\tconnect to server port\n");
printf("\t -d --device=device\t\tthe device that you want to control\n");
printf("\t -s --state=state\t\tthe new state of the device\n");
printf("\t -v --values=values\t\tspecific comma separated values, e.g.:\n");
printf("\t\t\t\t\t-v dimlevel=10\n");
goto close;
}
if(device == NULL || state == NULL ||
strlen(device) == 0 || strlen(state) == 0) {
printf("Usage: %s -d device -s state\n", progname);
goto close;
}
if(server && port > 0) {
if((sockfd = socket_connect(server, port)) == -1) {
logprintf(LOG_ERR, "could not connect to pilight-daemon");
goto close;
}
} else if(ssdp_seek(&ssdp_list) == -1) {
logprintf(LOG_NOTICE, "no pilight ssdp connections found");
goto close;
} else {
if((sockfd = socket_connect(ssdp_list->ip, ssdp_list->port)) == -1) {
logprintf(LOG_ERR, "could not connect to pilight-daemon");
goto close;
}
}
if(ssdp_list) {
ssdp_free(ssdp_list);
}
protocol_init();
config_init();
if(hasconfarg == 1) {
if(config_read() != EXIT_SUCCESS) {
goto close;
}
}
socket_write(sockfd, "{\"action\":\"identify\"}");
if(socket_read(sockfd, &recvBuff, 0) != 0
|| strcmp(recvBuff, "{\"status\":\"success\"}") != 0) {
goto close;
}
json = json_mkobject();
json_append_member(json, "action", json_mkstring("request config"));
output = json_stringify(json, NULL);
socket_write(sockfd, output);
json_free(output);
json_delete(json);
if(socket_read(sockfd, &recvBuff, 0) == 0) {
if(json_validate(recvBuff) == true) {
json = json_decode(recvBuff);
if(json_find_string(json, "message", &message) == 0) {
if(strcmp(message, "config") == 0) {
struct JsonNode *jconfig = NULL;
if((jconfig = json_find_member(json, "config")) != NULL) {
int match = 1;
while(match) {
struct JsonNode *jchilds = json_first_child(jconfig);
match = 0;
while(jchilds) {
if(strcmp(jchilds->key, "devices") != 0) {
json_remove_from_parent(jchilds);
tmp = jchilds;
match = 1;
}
jchilds = jchilds->next;
if(tmp != NULL) {
json_delete(tmp);
}
tmp = NULL;
}
}
config_parse(jconfig);
if(devices_get(device, &dev) == 0) {
JsonNode *joutput = json_mkobject();
JsonNode *jcode = json_mkobject();
JsonNode *jvalues = json_mkobject();
json_append_member(jcode, "device", json_mkstring(device));
if(values != NULL) {
char *sptr = NULL;
char *ptr1 = strtok_r(values, ",", &sptr);
while(ptr1) {
char **array = NULL;
int n = explode(ptr1, "=", &array), q = 0;
if(n == 2) {
char *name = MALLOC(strlen(array[0])+1);
if(name == NULL) {
logprintf(LOG_ERR, "out of memory\n");
exit(EXIT_FAILURE);
}
strcpy(name, array[q]);
char *val = MALLOC(strlen(array[q+1])+1);
if(val == NULL) {
logprintf(LOG_ERR, "out of memory\n");
exit(EXIT_FAILURE);
}
strcpy(val, array[1]);
if(devices_valid_value(device, name, val) == 0) {
if(isNumeric(val) == EXIT_SUCCESS) {
json_append_member(jvalues, name, json_mknumber(atof(val), nrDecimals(val)));
} else {
json_append_member(jvalues, name, json_mkstring(val));
}
has_values = 1;
FREE(name);
FREE(values);
array_free(&array, n);
} else {
logprintf(LOG_ERR, "\"%s\" is an invalid value for device \"%s\"", name, device);
array_free(&array, n);
FREE(name);
FREE(values);
json_delete(json);
goto close;
}
} else {
array_free(&array, n);
logprintf(LOG_ERR, "\"%s\" requires a name=value format", ptr1);
break;
}
ptr1 = strtok_r(NULL, ",", &sptr);
}
}
if(devices_valid_state(device, state) == 0) {
json_append_member(jcode, "state", json_mkstring(state));
} else {
logprintf(LOG_ERR, "\"%s\" is an invalid state for device \"%s\"", state, device);
json_delete(json);
goto close;
}
if(has_values == 1) {
json_append_member(jcode, "values", jvalues);
} else {
json_delete(jvalues);
}
json_append_member(joutput, "action", json_mkstring("control"));
json_append_member(joutput, "code", jcode);
output = json_stringify(joutput, NULL);
socket_write(sockfd, output);
json_free(output);
json_delete(joutput);
if(socket_read(sockfd, &recvBuff, 0) != 0
|| strcmp(recvBuff, "{\"status\":\"success\"}") != 0) {
logprintf(LOG_ERR, "failed to control %s", device);
}
} else {
logprintf(LOG_ERR, "the device \"%s\" does not exist", device);
json_delete(json);
goto close;
}
}
}
}
json_delete(json);
}
}
close:
if(recvBuff) {
FREE(recvBuff);
}
if(sockfd > 0) {
socket_close(sockfd);
}
if(server != NULL) {
FREE(server);
}
if(device != NULL) {
FREE(device);
}
if(state != NULL) {
FREE(state);
}
if(values != NULL) {
FREE(values);
}
log_shell_disable();
socket_gc();
config_gc();
protocol_gc();
options_gc();
#ifdef EVENTS
events_gc();
#endif
dso_gc();
log_gc();
threads_gc();
gc_clear();
FREE(progname);
xfree();
#ifdef _WIN32
WSACleanup();
#endif
return EXIT_SUCCESS;
}
File diff suppressed because it is too large. Load diff
+608
View File
@@ -0,0 +1,608 @@
/*
Copyright (C) 2013 - 2014 CurlyMo
This file is part of pilight.
pilight is free software: you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
pilight is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with pilight. If not, see <http://www.gnu.org/licenses/>
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#include <fcntl.h>
#include <limits.h>
#include <errno.h>
#include <time.h>
#include <math.h>
#include <string.h>
#ifndef _WIN32
#include <wiringx.h>
#endif
#include "libs/pilight/core/threads.h"
#include "libs/pilight/core/pilight.h"
#include "libs/pilight/core/network.h"
#include "libs/pilight/core/config.h"
#include "libs/pilight/core/log.h"
#include "libs/pilight/core/options.h"
#include "libs/pilight/core/threads.h"
#include "libs/pilight/core/datetime.h"
#include "libs/pilight/core/ssdp.h"
#include "libs/pilight/core/socket.h"
#include "libs/pilight/core/gc.h"
#include "libs/pilight/core/dso.h"
#include "libs/pilight/events/events.h"
#include "libs/pilight/config/hardware.h"
static unsigned short main_loop = 1;
static unsigned short inner_loop = 1;
#ifndef PILIGHT_DEVELOPMENT
static uv_signal_t *signal_req = NULL;
static int doSkip = 0;
#endif
static int normalize(int i, int pulselen) {
double x;
x=(double)i/pulselen;
return (int)(round(x));
}
int main_gc(void) {
log_shell_disable();
main_loop = 0;
inner_loop = 0;
datetime_gc();
ssdp_gc();
#ifdef EVENTS
events_gc();
#endif
options_gc();
socket_gc();
#ifndef PILIGHT_DEVELOPMENT
eventpool_gc();
#endif
config_gc();
protocol_gc();
whitelist_free();
threads_gc();
#ifndef _WIN32
wiringXGC();
#endif
dso_gc();
log_gc();
gc_clear();
FREE(progname);
xfree();
return EXIT_SUCCESS;
}
void *receivePulseTrain(void *param) {
int i = 0;
int pulselen = 0;
int pulse = 0;
struct rawcode_t r;
struct tm tm;
time_t now = 0;
struct hardware_t *hw = (hardware_t *)param;
while(main_loop) {
memset(&r.pulses, 0, sizeof(r.pulses));
memset(&tm, '\0', sizeof(struct tm));
pulse = 0;
inner_loop = 1;
i = 0;
time(&now);
hw->receivePulseTrain(&r);
if(r.length == -1) {
main_gc();
break;
} else if(r.length > 0) {
pulselen = r.pulses[r.length-1]/PULSE_DIV;
if(pulselen > 25) {
for(i=3;i<r.length;i++) {
if((r.pulses[i]/pulselen) >= 2) {
pulse=r.pulses[i];
break;
}
}
if(normalize(pulse, pulselen) > 0 && r.length > 25) {
/* Print everything */
printf("--[RESULTS]--\n");
printf("\n");
#ifdef _WIN32
localtime(&now);
#else
localtime_r(&now, &tm);
#endif
#ifdef _WIN32
printf("time:\t\t%s\n", asctime(&tm));
#else
char buf[128];
char *p = buf;
memset(&buf, '\0', sizeof(buf));
asctime_r(&tm, p);
printf("time:\t\t%s", buf);
#endif
printf("hardware:\t%s\n", hw->id);
printf("pulse:\t\t%d\n", normalize(pulse, pulselen));
printf("rawlen:\t\t%d\n", r.length);
printf("pulselen:\t%d\n", pulselen);
printf("\n");
printf("Raw code:\n");
for(i=0;i<r.length;i++) {
printf("%d ", r.pulses[i]);
}
printf("\n");
}
}
}
}
return (void *)NULL;
}
void *receivePulseTrain1(int reason, void *param) {
doSkip ^= 1;
if(doSkip == 1) {
return NULL;
}
struct reason_received_pulsetrain_t *data = param;
int pulselen = 0;
int pulse = 0;
struct tm tm;
time_t now = 0;
#ifdef PILIGHT_DEVELOPMENT
struct hardware_t *hw = NULL;
#endif
int i = 0;
if(data->hardware != NULL && data->pulses != NULL && data->length > 0) {
#ifndef PILIGHT_REWRITE
char *id = NULL;
struct conf_hardware_t *tmp_confhw = conf_hardware;
while(tmp_confhw) {
if(strcmp(tmp_confhw->hardware->id, data->hardware) == 0) {
id = tmp_confhw->hardware->id;
}
tmp_confhw = tmp_confhw->next;
}
#else
if(hardware_select_struct(ORIGIN_MASTER, data->hardware, &hw) == 0) {
#endif
memset(&tm, '\0', sizeof(struct tm));
pulse = 0;
inner_loop = 1;
i = 0;
time(&now);
if(data->length > 0) {
pulselen = data->pulses[data->length-1]/PULSE_DIV;
if(pulselen > 25) {
for(i=3;i<data->length;i++) {
if((data->pulses[i]/pulselen) >= 2) {
pulse=data->pulses[i];
break;
}
}
if(normalize(pulse, pulselen) > 0 && data->length > 25) {
/* Print everything */
printf("--[RESULTS]--\n");
printf("\n");
#ifdef _WIN32
memcpy(&tm, localtime(&now), sizeof(struct tm));
#else
localtime_r(&now, &tm);
#endif
#ifdef _WIN32
printf("time:\t\t%s", asctime(&tm));
#else
char buf[128];
char *p = buf;
memset(&buf, '\0', sizeof(buf));
#ifdef __sun
asctime_r(&tm, p, sizeof(buf));
#else
asctime_r(&tm, p);
#endif
printf("time:\t\t%s", buf);
#endif
#ifdef PILIGHT_DEVELOPMENT
printf("hardware:\t%s\n", hw->id);
#else
printf("hardware:\t%s\n", id);
#endif
printf("pulse:\t\t%d\n", normalize(pulse, pulselen));
printf("rawlen:\t\t%d\n", data->length);
printf("pulselen:\t%d\n", pulselen);
printf("\n");
printf("Raw code:\n");
for(i=0;i<data->length;i++) {
printf("%d ", data->pulses[i]);
}
printf("\n");
}
}
}
#ifdef PILIGHT_DEVELOPMENT
}
#endif
}
return (void *)NULL;
}
void *receiveOOK(void *param) {
int duration = 0;
int i = 0;
unsigned int y = 0;
int recording = 1;
int pulselen = 0;
int bit = 0;
int raw[MAXPULSESTREAMLENGTH] = {0};
int pRaw[MAXPULSESTREAMLENGTH] = {0};
int footer = 0;
int pulse = 0;
int rawLength = 0;
int plsdec = 1;
struct tm tm;
time_t now = 0, later = 0;
struct hardware_t *hw = (hardware_t *)param;
while(main_loop) {
memset(&raw, '\0', sizeof(raw));
memset(&pRaw, '\0', sizeof(pRaw));
memset(&tm, '\0', sizeof(struct tm));
recording = 1;
bit = 0;
footer = 0;
pulse = 0;
rawLength = 0;
inner_loop = 1;
pulselen = 0;
duration = 0;
i = 0;
y = 0;
time(&now);
while(inner_loop == 1 && hw->receiveOOK != NULL) {
duration = hw->receiveOOK();
time(&later);
if(difftime(later, now) > 1) {
inner_loop = 0;
}
/* If we are recording, keep recording until the next footer has been matched */
if(recording == 1) {
if(bit < MAXPULSESTREAMLENGTH) {
raw[bit++] = duration;
} else {
bit = 0;
recording = 0;
}
}
/* First try to catch code that seems to be a footer.
If a real footer has been recognized, start using that as the new footer */
if((duration > 5100 && footer == 0) || ((footer-(footer*0.3)<duration) && (footer+(footer*0.3)>duration))) {
recording = 1;
pulselen = (int)duration/PULSE_DIV;
/* Check if we are recording similar codes */
for(i=0;i<(bit-1);i++) {
if(!(((pRaw[i]-(pRaw[i]*0.3)) < raw[i]) && ((pRaw[i]+(pRaw[i]*0.3)) > raw[i]))) {
y=0;
recording=0;
}
pRaw[i]=raw[i];
}
y++;
/* Continue if we have 2 matches */
if(y>=1) {
/* If we are certain we are recording similar codes. Save the raw code length. */
if(footer>0) {
if(rawLength == 0)
rawLength=bit;
}
if(pulselen > 1000) {
plsdec = 10;
}
/* Try to catch the footer, and the low and high values */
for(i=0;i<bit;i++) {
if((i+1)<bit && i > 2 && footer > 0) {
if((raw[i]/(pulselen/plsdec)) >= 2) {
pulse=raw[i];
}
}
if(duration > 5100) {
footer=raw[i];
}
}
/* If we have gathered all data, stop with the loop */
if(footer > 0 && pulse > 0 && rawLength > 0) {
inner_loop = 0;
}
}
bit=0;
}
fflush(stdout);
}
if(normalize(pulse, (pulselen/plsdec)) > 0 && rawLength > 25) {
/* Print everything */
printf("--[RESULTS]--\n");
printf("\n");
#ifdef _WIN32
localtime(&now);
#else
localtime_r(&now, &tm);
#endif
#ifdef _WIN32
printf("time:\t\t%s\n", asctime(&tm));
#else
char buf[128];
char *p = buf;
memset(&buf, '\0', sizeof(buf));
asctime_r(&tm, p);
printf("time:\t\t%s", buf);
#endif
printf("hardware:\t%s\n", hw->id);
printf("pulse:\t\t%d\n", normalize(pulse, (pulselen/plsdec)));
printf("rawlen:\t\t%d\n", rawLength);
printf("pulselen:\t%d\n", pulselen);
printf("\n");
printf("Raw code:\n");
for(i=0;i<rawLength;i++) {
printf("%d ",normalize(raw[i], (pulselen/plsdec))*(pulselen/plsdec));
}
printf("\n");
}
}
main_loop = 0;
return NULL;
}
#ifndef PILIGHT_DEVELOPMENT
static void signal_cb(uv_signal_t *handle, int signum) {
uv_stop(uv_default_loop());
main_gc();
}
static void close_cb(uv_handle_t *handle) {
FREE(handle);
}
static void walk_cb(uv_handle_t *handle, void *arg) {
if(!uv_is_closing(handle)) {
uv_close(handle, close_cb);
}
}
static void main_loop1(int onclose) {
if(onclose == 1) {
signal_cb(NULL, SIGINT);
}
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
uv_walk(uv_default_loop(), walk_cb, NULL);
uv_run(uv_default_loop(), UV_RUN_ONCE);
if(onclose == 1) {
while(uv_loop_close(uv_default_loop()) == UV_EBUSY) {
usleep(10);
}
}
}
#endif
int main(int argc, char **argv) {
#ifndef PILIGHT_DEVELOPMENT
const uv_thread_t pth_cur_id = uv_thread_self();
memcpy((void *)&pth_main_id, &pth_cur_id, sizeof(uv_thread_t));
#endif
memtrack();
atomicinit();
gc_attach(main_gc);
/* Catch all exit signals for gc */
gc_catch();
if((progname = MALLOC(15)) == NULL) {
fprintf(stderr, "out of memory\n");
exit(EXIT_FAILURE);
}
strcpy(progname, "pilight-debug");
#ifndef PILIGHT_DEVELOPMENT
if((signal_req = MALLOC(sizeof(uv_signal_t))) == NULL) {
OUT_OF_MEMORY /*LCOV_EXCL_LINE*/
}
uv_signal_init(uv_default_loop(), signal_req);
uv_signal_start(signal_req, signal_cb, SIGINT);
#endif
#ifndef _WIN32
if(geteuid() != 0) {
printf("%s requires root privileges in order to run\n", progname);
FREE(progname);
exit(EXIT_FAILURE);
}
#endif
log_shell_enable();
log_file_disable();
log_level_set(LOG_NOTICE);
struct options_t *options = NULL;
char *args = NULL;
pid_t pid = 0;
char configtmp[] = CONFIG_FILE;
config_set_file(configtmp);
options_add(&options, 'H', "help", OPTION_NO_VALUE, 0, JSON_NULL, NULL, NULL);
options_add(&options, 'V', "version", OPTION_NO_VALUE, 0, JSON_NULL, NULL, NULL);
options_add(&options, 'C', "config", OPTION_HAS_VALUE, 0, JSON_NULL, NULL, NULL);
while (1) {
int c;
c = options_parse(&options, argc, argv, 1, &args);
if(c == -1)
break;
if(c == -2)
c = 'H';
switch (c) {
case 'H':
printf("Usage: %s [options]\n", progname);
printf("\t -H --help\t\tdisplay usage summary\n");
printf("\t -V --version\t\tdisplay version\n");
printf("\t -C --config\t\tconfig file\n");
goto clear;
break;
case 'V':
printf("%s v%s\n", progname, PILIGHT_VERSION);
goto clear;
break;
case 'C':
if(config_set_file(args) == EXIT_FAILURE) {
goto clear;
}
break;
default:
printf("Usage: %s [options]\n", progname);
goto clear;
break;
}
}
options_delete(options);
#ifdef _WIN32
if((pid = check_instances(L"pilight-debug")) != -1) {
logprintf(LOG_NOTICE, "pilight-debug is already running");
goto clear;
}
#endif
if((pid = isrunning("pilight-daemon")) != -1) {
logprintf(LOG_NOTICE, "pilight-daemon instance found (%d)", (int)pid);
goto clear;
}
if((pid = isrunning("pilight-raw")) != -1) {
logprintf(LOG_NOTICE, "pilight-raw instance found (%d)", (int)pid);
goto clear;
}
#ifndef PILIGHT_DEVELOPMENT
eventpool_init(EVENTPOOL_THREADED);
#endif
protocol_init();
config_init();
if(config_read() != EXIT_SUCCESS) {
goto clear;
}
#ifndef PILIGHT_DEVELOPMENT
eventpool_callback(REASON_RECEIVED_PULSETRAIN, receivePulseTrain1);
#endif
/* Start threads library that keeps track of all threads used */
threads_start();
struct conf_hardware_t *tmp_confhw = conf_hardware;
while(tmp_confhw) {
if(tmp_confhw->hardware->init) {
if(tmp_confhw->hardware->comtype == COMOOK) {
tmp_confhw->hardware->maxrawlen = MAXPULSESTREAMLENGTH;
tmp_confhw->hardware->minrawlen = 25;
tmp_confhw->hardware->maxgaplen = 34000;
tmp_confhw->hardware->mingaplen = 5100;
}
if(tmp_confhw->hardware->init() == EXIT_FAILURE) {
logprintf(LOG_ERR, "could not initialize %s hardware mode", tmp_confhw->hardware->id);
goto clear;
}
if(tmp_confhw->hardware->comtype == COMOOK) {
#ifdef PILIGHT_DEVELOPMENT
// threads_register(tmp_confhw->hardware->id, &receiveOOK, (void *)tmp_confhw->hardware, 0);
#endif
} else if(tmp_confhw->hardware->comtype == COMPLSTRAIN) {
threads_register(tmp_confhw->hardware->id, &receivePulseTrain, (void *)tmp_confhw->hardware, 0);
}
}
tmp_confhw = tmp_confhw->next;
}
printf("Press and hold one of the buttons on your remote or wait until\n");
printf("another device such as a weather station has sent new codes\n");
printf("The debugger will automatically reset itself after one second of\n");
printf("failed leads. It will keep running until you explicitly stop it.\n");
printf("This is done by pressing both the [CTRL] and C buttons on your keyboard.\n");
#ifdef PILIGHT_DEVELOPMENT
while(main_loop) {
sleep(1);
}
#else
main_loop1(0);
#endif
clear:
#ifdef PILIGHT_DEVELOPMENT
if(main_loop == 1) {
main_gc();
}
#else
main_loop1(1);
main_gc();
#endif
return (EXIT_FAILURE);
}
+36
View File
@@ -0,0 +1,36 @@
@ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=source
set BUILDDIR=build
set SPHINXPROJ=pilight
if "%1" == "" goto help
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
:end
popd
@@ -0,0 +1,212 @@
body,
h1, h2, h3,
h4, h5, h6,
dt, dl, dd,
blockquote,
td, th, div,
ul, li, ol,
a, p, input,
table, table td,
div.sphinxsidebar .sidebar-toc a,
.sidebar-block h2,
.text-logo,
.admonition-title {
font-family:'Roboto Condensed', sans-serif;
}
blockquote {
padding: 0px;
}
.underline {
text-decoration: underline;
}
h1 {
background-color: #fafafa;
}
img {
display: block;
width: 100%;
}
div.sphinxsidebar {
margin-top: 5px;
padding-top: 80px;
background: url('pilight.png') no-repeat top center;
}
.text-logo {
opacity: 0;
height: 102px;
margin-top: -100px;
}
blockquote {
background: transparent;
border: 0px;
}
table.footnote * {
font-size: 12px;
}
table.footnote .label {
color: #428bca;
}
table.docutils:not(.footnote) {
border: 0px solid transparent;
min-width: 100%;
margin-bottom: 10px;
display: block;
overflow: auto;
}
table.docutils:not(.footnote).alt {
display: table;
}
table.docutils:not(.footnote) img {
display: inline-block;
width: auto;
}
table.docutils:not(.footnote).alt img {
display: block;
width: 100%;
}
table.docutils:not(.footnote) td {
border: 0px solid transparent;
white-space: nowrap;
padding: 5px;
vertical-align: middle;
}
table.docutils:not(.footnote) tr.row-odd td {
background: #fbfbfb;
}
table.docutils:not(.footnote) tr:first-child td {
background: #fafafa;
font-weight: 800;
border-bottom: 1px solid #aaaaaa;
}
div[class^='highlight'] {
overflow-x: auto;
margin: 1px 0 24px 0
}
div[class^='highlight'] div[class^='highlight'] {
margin: 0;
padding: 0;
}
table {
border-collapse: collapse;
margin: 0px;
padding: 0px;
}
pre {
margin: 0px;
padding: 0px;
border: 0px;
}
.highlighttable pre {
margin: -5px 0px 0px 0px;
padding: 0px;
border-left: 1px solid #eeeeee;
}
.event-success,
.event-fail {
position: relative;
float: right;
font-size: 16px;
padding: 0px;
margin-top: -1px;
width: 60px;
display: block;
}
.event-success {
color: green;
}
.event-fail {
color: red;
}
.text-logo {
background: #fafafa;
}
.sidebar-toc ul li a:hover {
background-color: white;
color: red;
}
.sidebar-toc ul li.current > a,
.sidebar-toc ul li.current > a:hover {
background-color: #ffcc00;
color: #fff;
}
/* .sidebar-toc .toctree-l1.current > a, */
/* .sidebar-toc .toctree-l1.current > a:hover { */
/* background-color: #dedede; */
/* } */
h1:hover > a.headerlink,
h2:hover > a.headerlink,
h3:hover > a.headerlink,
h4:hover > a.headerlink,
h5:hover > a.headerlink,
h6:hover > a.headerlink,
dt:hover > a.headerlink {
visibility: hidden;
}
.footnote-reference {
vertical-align: super;
font-size: 10px;
}
table.field-list {
display: none!important;
}
.versionchanged {
border-bottom: 1px solid #ffcc00;
}
.deprecated {
border-bottom: 1px solid #ff0000;
}
.versionadded {
border-bottom: 1px solid #aaffaa;
}
.versionchanged,
.versionmodified,
.versionadded,
.deprecated {
color: black;
margin-bottom: 15px;
margin-top: 15px;
}
.versionmodified *,
.versionchanged *,
.versionadded *,
.deprecated * {
font-style: normal;
padding: 0px;
margin: 0px;
}
@@ -0,0 +1,6 @@
$(document).ready(function() {
$('.toctree-l1.current:has(.toctree-l2.current) > a').css({
background: '#bbbbbb',
color: 'white'
});
});
@@ -0,0 +1 @@
@font-face{font-family:'Roboto Condensed';font-style:normal;font-weight:300;src:local('Roboto Condensed Light'),local('RobotoCondensed-Light'),url(Roboto-Condensed.woff2) format('woff2'),url(Roboto-Condensed.woff) format('woff')}
@@ -0,0 +1,11 @@
About manual
============
The pilight manual is a community driven project open for everyone to participate in. The goal is to provide a multi-lingual and professional software manual for each pilight release. All users are invited to add, edit, or replace content to their best effort. If you want to contribute then also add your name in the contributor list below.
The pilight manual consists of various so called RestructuredText documents which can be found in the `pilight development repository <https://github.com/pilight/pilight/tree/development/docs>`_.
These individual documents are transformed using the `Sphinx toolset <http://www.sphinx-doc.org>`_ into the pilight manual.
| Contributors:
| CurlyMo, pilino1234, wo_rasp
@@ -0,0 +1,322 @@
Adhoc Network
=============
- `Introduction`_
- `Network of Senders and Receivers`_
- `Network of (Conflicting) Sensors and Relays`_
- `Stable Mail Daemon`_
Introduction
------------
The probably least known but advanced feature of pilight is its adhoc network functionality. This basically means that you can create a big network of pilight instances (such as several Raspberry Pis and Windows or Linux computers) working together. A bit like the Borg from Star Trek.
Consider the following, quite common, user case scenario. We have one Raspberry Pi running pilight with a sender and receiver connected. This single pilight instance controls our remote controlled lights and can retrieve weather information from our weather station and/or from e.g. openweathermap.org. This system has already been set up and works.
Network of Senders and Receivers
--------------------------------
.. only:: html
.. |fig1h| image:: images/adhoc-network-nodeA+B.svg
.. |fig2h| image:: images/adhoc-network-nodeA+B.svg
.. rst-class:: alt
+-----------------+-----------------+
| |fig1h| | |fig2h| |
+-----------------+-----------------+
| Image 1: Node A | Image 1: Node B |
+-----------------+-----------------+
.. only:: latex
.. |fig1l| image:: images/adhoc-network-nodeA+B.pdf
.. |fig2l| image:: images/adhoc-network-nodeA+B.pdf
.. rst-class:: alt
+-----------------+-----------------+
| |fig1l| | |fig2l| |
+-----------------+-----------------+
| Image 1: Node A | Image 1: Node B |
+-----------------+-----------------+
The biggest limitation of a home domotica set-up is its range. Of course we can tinker with antennas and such, but that does not always solve the problem. How then, can we reach those corners in our house that the single Raspberry Pi with pilight cannot reach?
The solution is to create a network of senders and receivers all working together. That is exactly what pilight offers with the AdHoc network functionality. To be able to use this feature, we need (at least) two pilight capable computers. In this example we use two Raspberry Pis to control our devices; a lamp in our bookshelf ("bookshelf") on one side of the house and a lamp in the garden ("gardenlights") on the other side:
.. code-block:: json
:linenos:
{
"devices": {
"bookshelf": {
"protocol": [ "kaku_switch" ],
"id": [{
"id": 123456
"unit": 1
}],
"state": "off"
},
"gardenlights": {
"protocol": [ "kaku_switch" ],
"id": [{
"id": 123456
"unit": 2
}],
"state": "off"
}
}
}
Our settings for Node A will look like this:
.. code-block:: json
:linenos:
{
"settings": {
"log-level": 6,
"log-file": "/var/log/pilight-daemon.log",
"webserver-enable": 1,
"webserver-cache": 1,
"webserver-http-port": 5001,
"webserver-root": "/usr/local/share/pilight/",
"whitelist": ""
}
Now, when we start pilight in debug mode in Node A, we can see this:
.. code-block:: console
[Jan 24 15:34:18:191682] pilight-daemon: DEBUG: ssdp sent search
[Jan 24 15:34:18:292486] pilight-daemon: NOTICE: no pilight daemon found, daemonizing
pilight knows it is (currently) the only instance running inside the home network and will therefore start as a main daemon. However, we notice that we cannot control both our bookshelf lamp and the light in the garden with a single Raspberry Pi with pilight, because of the limited range of the sender and receiver. The solution is to add another Raspberry Pi with pilight on the other side of the house and to connect them to the home network. The settings of Node B will look like this:
.. code-block:: json
:linenos:
{
"settings": {
"log-level": 6,
"log-file": "/var/log/pilight-daemon.log",
"whitelist": ""
}
}
As you can see here, we have removed the **webserver settings**, because a pilight node **will not have its webserver enabled**. Once we start Node B in debug mode, we can see the following:
.. code-block:: console
[Jan 24 15:40:44:334028] pilight-daemon: DEBUG: ssdp sent search
[Jan 24 15:40:44:434492] pilight-daemon: NOTICE: a pilight daemon was found @192.168.1.100, clientizing
pilight has found the first daemon Node A and will connect to it. It will identify as a node and connect to it
(clientizing):
.. code-block:: console
[Jan 24 15:40:44:544657] pilight-daemon: DEBUG: socket write succeeded: {"action":"identify","options":{"receiver":1,"forward":1,"config":1},"uuid":"0363-00-00-63-000300"}
[Jan 24 15:40:44:547148] pilight-daemon: DEBUG: socket recv: {"status":"success"}
[Jan 24 15:40:44:547455] pilight-daemon: DEBUG: socket write succeeded: {"action":"request config"}
The last important part is that Node B will request the configuration from Node A, so that all nodes work with the same configuration definition as the main daemon (Node A). Once a code is received on Node B, it will be synchronised with Node A and Node A will again synchronize it with Node C etc. Whenever you send a code (using a 433MHz remote or the webGUI) it will automatically arrive at Node A, because all clients will always connect to the main daemon. Node A will transfer send request (such as to control a socket) to all connected nodes. So not only Node A will send but also **all other nodes**.
If the main daemon Node A crashes, the network is down. However, the other nodes will keep running until the main daemon is back up again. They will of course first clear the local configuration and resynchronize it with the daemon (because pilight cannot know what the new configuration will be):
.. code-block:: console
[Jan 24 15:45:37:250271] pilight-daemon: DEBUG: garbage collected config library
[Jan 24 15:45:37:250397] pilight-daemon: NOTICE: connection to main pilight daemon lost
[Jan 24 15:45:37:250691] pilight-daemon: NOTICE: trying to reconnect...
[Jan 24 15:45:40:250971] pilight-daemon: DEBUG: ssdp sent search
[Jan 24 15:45:40:350471] pilight-daemon: ERROR: no pilight ssdp connections found
[Jan 24 15:45:40:350758] pilight-daemon: DEBUG: garbage collected config library
[Jan 24 15:45:40:350835] pilight-daemon: NOTICE: connection to main pilight daemon lost
[Jan 24 15:45:40:350913] pilight-daemon: NOTICE: trying to reconnect...
Once the main daemon is back online (which does not necessarily have to be Node A), all nodes will reconnect:
.. code-block:: console
[Jan 24 15:47:50:565899] pilight-daemon: NOTICE: trying to reconnect...
[Jan 24 15:47:53:566159] pilight-daemon: DEBUG: ssdp sent search
[Jan 24 15:40:44:544657] pilight-daemon: DEBUG: socket write succeeded: {"action":"identify","options":{"receiver":1,"forward":1,"config":1},"uuid":"0363-00-00-63-000300"}
[Jan 24 15:40:44:547148] pilight-daemon: DEBUG: socket recv: {"status":"success"}
[Jan 24 15:40:44:547455] pilight-daemon: DEBUG: socket write succeeded: {"action":"request config"}
This means that when you want to update the configuration with new devices, you only have to restart the main daemon and all nodes will reconnect and resynchronize the new configuration file. This way we can control both the bookshelf lamps in front of our house and the backyard light at the back.
pilight can also control various other devices like relays and read from sensors for temperature and/or humidity in the same network. We are going to continue on the previous example but add two additional pilight instances.
Network of (Conflicting) Sensors and Relays
-------------------------------------------
pilight can also control various other devices like relays and read from sensors for temperature and/or humidity in the *same network*. We are going to continue on the previous example but add two additional pilight instances.
.. only:: html
.. |fig3h| image:: images/adhoc-network-nodeC.svg
.. |fig4h| image:: images/adhoc-network-nodeD.svg
.. rst-class:: alt
+-----------------+-----------------+
| |fig3h| | |fig4h| |
+-----------------+-----------------+
| Image 1: Node C | Image 1: Node D |
+-----------------+-----------------+
.. only:: latex
.. |fig3l| image:: images/adhoc-network-nodeC.pdf
.. |fig4l| image:: images/adhoc-network-nodeD.pdf
.. rst-class:: alt
+-----------------+-----------------+
| |fig3l| | |fig4l| |
+-----------------+-----------------+
| Image 1: Node C | Image 1: Node D |
+-----------------+-----------------+
Node C is meant to add additional coverage in the house to make sure we receive all signals, but it also has a relay connected. We are going to use this relay to turn our television set on and off. The new configuration file will look like this:
.. code-block:: json
:linenos:
{
"devices": {
"bookshelf": {
"protocol": [ "kaku_switch" ],
"id": [{
"id": 123456
"unit": 1
}],
"state": "off"
},
"television": {
"protocol": [ "relay" ],
"id": [{
"gpio": 4
}],
"state": "off"
},
"gardenlights": {
"protocol": [ "kaku_switch" ],
"id": [{
"id": 123456
"unit": 2
}],
"state": "off"
}
}
}
Until now, we did not encounter any issues with our pilight AdHoc network. But what happens when we add another relay (also connected to GPIO 3, but on Node D) to control a heater? Our new configuration file will look like this:
.. code-block:: json
:linenos:
{
"devices": {
"heater": {
"protocol": [ "relay" ],
"id": [{
"gpio": 4
}],
"state": "off"
},
"bookshelf": {
"protocol": [ "kaku_switch" ],
"id": [{
"id": 123456
"unit": 1
}],
"state": "off"
},
"television": {
"protocol": [ "relay" ],
"id": [{
"gpio": 4
}],
"state": "off"
},
"gardenlights": {
"protocol": [ "kaku_switch" ],
"id": [{
"id": 123456
"unit": 2
}],
"state": "off"
}
}
}
As you might see, we have a problem here. As soon as I turn my television set on, I also turn on the heater and when I turn the heater off, the television will go off as well. In this case, pilight has no way of knowing which relay it needs to control so it just switches all of them. So if I set GPIO 3 of Node D to HIGH, GPIO 3 of Node A, B, C will also be set HIGH. pilight offers a solution to this issue by giving all pilight instances a specific UUID. By adding the UUID of a pilight instance in the configuration file, pilight will know exactly what relay it should control. To know what the UUID of our pilight instance is, we can run the program called pilight-uuid. We are going to run this program first to know what the UUID of Node C is by running it on that Raspberry Pi:
.. code-block:: console
pi@pilight:~# pilight-uuid
0338-00-00-38-000300
And then on the Raspberry Pi of Node D to see what his UUID is:
.. code-block:: console
pi@pilight:~# pilight-uuid
0363-00-00-63-000300
Now we edit our configuration file incorporating the new UUID values:
.. code-block:: json
:linenos:
{
"devices": {
"heater": {
"uuid": "0338-00-00-38-000300",
"protocol": [ "relay" ],
"id": [{
"gpio": 4
}],
"state": "off"
},
"bookshelf": {
"protocol": [ "kaku_switch" ],
"id": [{
"id": 123456
"unit": 1
}],
"state": "off"
},
"television": {
"uuid": "0338-00-00-68-000300",
"protocol": [ "relay" ],
"id": [{
"gpio": 4
}],
"state": "off"
},
"gardenlights": {
"protocol": [ "kaku_switch" ],
"id": [{
"id": 123456
"unit": 2
}],
"state": "off"
}
}
}
If you now want to turn the television set on, pilight knows that it should only control the relay connected to Node C with the UUID 0338-00-00-38-000300. The same would count for sensors connected to your Raspberry Pi. Just add proper UUID values to them, and pilight will know which sensor is connected to which pilight node.
Stable Mail Daemon
------------------
As you might have noticed, the main daemon is very important in the pilight AdHoc network. Once the main daemon crashes, the whole network will be down. You can easily restore the network by just restarting the main daemon. However, you might also have noticed that a Raspberry Pi is a bit less stable than normal everyday computers and less stable then your regular NAS system. What about running the main daemon on there? You can!
pilight has been tested on various platforms other than just the Raspberry Pi. It successfully ran on \*BSD and Debian based systems. The only problem is that these consumer mainboards generally does not have GPIO capability. That is not a problem because pilight can just run on these devices when you remove all hardware definitions.
@@ -0,0 +1,216 @@
Changelog
=========
.. versionadded:: 8.1.0
.. rubric:: Improvements
- Ported events operators and functions to LUA
- Complete rewritten event parser with:
- (nested) IF/ELSE/THEN support
- case insensitive
- operator precedence compliant
- better error messages
- string concatenation
- calculations inside actions
- etc.
.. rubric:: bugfixes
- webGUI: Take `stats-enable` into account
- webGUI: Warp long labels into multiple lines
- webGUI: Keep values together on small screens
- webGUI: Fix dimmer element being too small
.. versionadded:: 8.0.10
.. rubric:: Bugfixes
- Ignore dst in DATE_FORMAT function to keep input datetime unaffected by dst.
.. versionadded:: 8.0.9
.. rubric:: Bugfixes
- Properly reset time variable in DATE_FORMAT function to correctly handle dst.
.. versionadded:: 8.0.8
.. rubric:: Bugfixes
- --debuglevel=2 replaced --debuglevel=1. Now both are allowed.
.. versionadded:: 8.0.7
.. rubric:: Change functionality
- Openweathermap now requires a personal API key. Until now, a free pilight organization API key was used, but that exceeded the maximum allowed requests per minute.
.. rubric:: Bugfixes
- Actually allow --debuglevel=2 to see additional mail logging
.. versionadded:: 8.0.6
.. rubric:: Bugfixes
- Readded min / max dimlevel in generic_dimmer, but validation is still disabled
.. versionadded:: 8.0.5
.. rubric:: New functionality
- IPv6 support for all in library clients
- Disable min / max dimlevel in generic_dimmer
.. rubric:: Internal core changed
- Callback in mail library when host is not reachable
- Shutdown on more signals
.. rubric:: Bugfixes
- Fixed pilight removal with apt
- Calling REST API with socket API
- Prevent using ``.`` as message body
- Segfault due to wrong memory freeing
.. versionadded:: 8.0.4
.. rubric:: New functionality
- webGUI long labels are wrapped
.. rubric:: Internal core changed
- Olsen timezone database is now used for timezone parsing
- 433.92Mhz now respect the UUID setting
- improved datetime, openweathermap, weatherunderground, and sunriseset library
.. rubric:: Bugfixes
- config not being saved at shutdown
.. versionadded:: 8.0.3
.. rubric:: Bugfixes
- webgui labels are word-wrapped into multiple lines on small screens
- webgui takes ``stats-enable`` into account by hiding CPU stats
- memory usage statistics has been removed because they were unreliable
- arctech_dimmer signals sent by pilight are now correctly received by pilight as well
.. rubric:: webserver, mail and http library
At this moment the https, mail, and webserver module and the full ``pilight-sha256`` program has been backported from rewrite. The asynchronous I/O library libuv has been added as well as the new SSL and eventpool module. The openweathermap and weather underground protocols have been adapted to use this new code as well as the pushbullet and pushover event actions.
- pilight now supports a HTTPS webserver which can be configured in the settings:
.. code-block:: json
{ "webserver-https-port": 5002 }
- pilight also stopped detecting if the mailserver you have configures requires an SSL connection. To tell pilight about the SSL requirement of a mail server a new setting has been added. Servers that switch from a plain connection to SSL require a 0 value here:
.. code-block:: json
{ "smtp-ssl": 1 }
.. versionadded:: 8.0.2
.. rubric:: Bugfixes
- wiringX log was scrambled
.. versionadded:: 8.0.1
.. rubric:: Bugfixes
- gpio_switch protocol that stops working after a while
- pilight not starting at boottime
.. versionadded:: 8.0
.. note::
Not all changes from development where ported to stable. Especially the rules can break when upgraded from the latest development to the latest stable. Porting the new eventing code is in the planning real soon, but until then, just stick with development.
.. rubric:: Breaking changes
- The PHP parsing functionality has been removed.
.. rubric:: New functionality
- Proper REST API through the webserver. See `Development -> API <https://manual.pilight.org/development/api.html#webserver>`_.
- Protocol names cannot be used anymore as configuration device names.
- Supporting flashing the Arduino Uno.
- Added TFA 30.X weather stations. FIXME
- Added Quigg GT-9000 protocol. See FIXME.
- Added Secudo / FlammEx smoke sensor. FIXME.
- Added Eurodomest protocol. `Protocols -> 433.92Mhz -> Switches -> Eurodomest <https://manual.pilight.org/protocols/433.92/switch/eurodomest.html>`_
- Added TCM 218943 protocol `Protocols -> 433.92Mhz -> Weather -> TCM <https://manual.pilight.org/protocols/433.92/weather/protocols/433.92/weather/tcm.html>`_
- Allow event triggers based on received actions. See `Eventing -> Syntax <https://manual.pilight.org/eventing/syntax.html#devices>`_.
- Added the ISNOT operator. See `Eventing -> Operators <https://manual.pilight.org/eventing/operators.html>`_
- Added webGUI support for illuminance sensor.
- Allow filtering ``pilight-receive`` protocols. See `Programs -> pilight-receive <https://manual.pilight.org/programs/receive.html>`_
- Split pilight daemon debug and foreground functionality in two parameters. See `Programs -> pilight-daemon <https://manual.pilight.org/programs/daemon.html>`_
- Removed internal wiringX integration and changes to shared library linking.
- Validate duplicate 433gpio GPIO for both sender and receiver value.
- Default pilight paths have changes.
- The tzdata.json file has been deprecated and moved internally into pilight.
.. rubric:: Bugfixes
- XBMC and LIRC protocol. Properly try to reconnect when connection is lost.
- X10 Switch. The same unit was sent for units 8 and 9.
- Beamisch Switch. Resend the beamisch switch 10 times again.
- Arctech Switch. More precise pulse lengths.
- EV1527 Switch. Allow a bigger ID range.
- Conrad RSL switch. Add learn parameter for device learning.
- RSL366 Switch. Better protocol validation for less false positives.
- Arctech Dusk. Fixed swapped states.
- Clarus Switch. Prevent crashes on too long ID parameter.
- Alecto WX500 Weather Station. Fixed negative temperatures.
- Alecto WS1700 Weather Station. Better protocol implementation according to specsheet.
- Arctech Old Switch. Better protocol validation for less false positives.
- Quigg GT-1000 Switch. Added support more group codes.
- Elro 800 Switch. Support for more systemcodes.
- Teknihall Weather Station. Fixed negatives temperature values.
- Dim action. IN timeout could take too long.
- ``smtp-user`` setting. Any character is now allowed.
- ``smtp-email`` setting. Better email address validation.
- pilight startup. Start pilight after network at boottime.
.. rubric:: Internal core changes
- Frequency properties are made hardware module independent.
- Added file_get_contents function.
- Updated webGUI jQuery and moment library .
- Better internal pushbullet and pushbullet action argument parsing.
- Better binary to decimals and vice versa parsing.
- Support for AArch64 compilation.
- Send version after request values API call.
- Differentiate JSON types using bitmasks.
- Better mail library status checking.
- Added python3 client example.
- Various typo fixes.
- Fixed shared and static library linking.
- Fixed unused protocol repeat parameter.
- Fixed various uninitialized fields or incomplete buffer initializations.
- Fixed memory leaks in Dim, Label, and Switch action.
- Fixed inconsistent min and max dimlevel parsing in generic dimmer.
- Fixed webGUI dimmer display bugs.
- Fixed possible deadlock in datetime library.
- Fixed various buffer overflows in protocols.
- Fixed lm75, lm76, and bmp180 i2c-patch parsing.
- Fixed ntp time library bugs.
+173
View File
@@ -0,0 +1,173 @@
# -*- coding: utf-8 -*-
#
# pilight documentation build configuration file, created by
# sphinx-quickstart on Tue Sep 12 20:56:47 2017.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
import sphinx_bootstrap_theme
import guzzle_sphinx_theme
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))
def setup(app):
app.add_stylesheet('font.min.css')
app.add_stylesheet('custom.css')
app.add_javascript('custom.js')
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#
# needs_sphinx = '1.0'
locale_dirs = ['.locale/']
gettext_compact = False
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = []
# Add any paths that contain templates here, relative to this directory.
templates_path = ['.templates']
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
# source_suffix = ['.rst', '.md']
source_suffix = '.rst'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'pilight'
copyright = u'2017, pilight'
author = u'pilight contributors'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = u'7.0'
# The full version, including alpha/beta/rc tags.
release = u'7.0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This patterns also effect to html_static_path and html_extra_path
exclude_patterns = []
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'github'
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'guzzle_sphinx_theme'
html_theme_path = guzzle_sphinx_theme.html_theme_path()
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#
html_theme_options = {
"project_nav_name": "&nbsp;",
}
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['.static']
html_favicon = 'images/favicon.ico'
html_logo = 'images/pilight.png'
html_show_sourcelink = False;
html_show_sphinx = False;
# -- Options for HTMLHelp output ------------------------------------------
# Output file base name for HTML help builder.
htmlhelp_basename = 'pilightdoc'
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'pilight.tex', u'pilight documentation',
u'pilight contributors', 'howto'),
]
# -- Options for manual page output ---------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'pilight', u'pilight Documentation',
[author], 1)
]
# -- Options for Texinfo output -------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'pilight', u'pilight Documentation',
author, 'pilight', 'One line description of project.',
'Miscellaneous'),
]
@@ -0,0 +1,198 @@
Devices
=======
* `Introduction`_
* `Structure`_
* `Device Types`_
* `Multiple IDs`_
* `Multiple Protocols Per Device`_
* `Overriding Protocol Settings`_
Introduction
------------
.. warning::
Make sure pilight is not running before editing your configuration or else all changes will be lost.
.. note::
This page will only explain the device set-up basics with some protocols as an example. To see the full
list of supported protocols and their respective syntax read the protocol pages of this manual.
pilight can be ran with or without a fixed devices set-up. The advantage of a fixed device set-up is that pilight can use them in events and for external clients such as the built-in webGUI. Status updates will automatically be updated just like information from weather information.
The protocol names outputted by *pilight-receive* are not (always) the same as the protocols used in the device setup. The reason for this, is that various brands use the same underlying protocol. The arctech_switch protocol is used by at least five different brands. So there is the same underlying protocol for each of these brands.
#. Check the brand of the device you want to define in the device set-up.
#. Check if your device is recognize in *pilight-receive*.
#. Check the protocol pages to see if your device is listed and what the device syntax is.
If your specific brand / device is not listed, but *pilight-receive* does show output, then contact us so we can add the device to the specific protocol supported brand list.
Structure
---------
.. code-block:: json
:linenos:
{
"devices": {
"television": {
"protocol": [ "relay" ],
"id": [{
"gpio": 3
}],
"state": "off"
},
"bookShelfLight": {
"protocol": [ "kaku_switch" ],
"id": [{
"id": 123456,
"unit": 1
}],
"state": "off"
}
}
}
Each device you want to set-up in pilight has its own entry. In this example we have set-up two devices. One GPIO connected Relay that turns the television on and off and KlikAanKlikUit controlled bookShelfLight. Whenever an action has been performed or received by pilight the registered device will update itself when necessary. So, would you in this example, turn the bookShelfLight to on with a KlikAanKlikUit remote, pilight will also record this, and change the status of the bookShelfLight to on. Of course, a receiver needs to be connected for this to work. Each device has its own specific syntax but its basic properties remain the same. That is:
#. name
#. protocol
#. id
To know the syntax of the specific protocol you want to use you can refer to the protocols description found in the protocol section of this manual.
.. note:: changed in version 8
Protocol names cannot be used as device names.
Device Types
------------
pilight can work with various device types. Each device type has different functionality and requirements, however, they sometimes use the same code characteristics. One example are the KlikAanKlikUit switches, dimmers, doorbells, and screens. In pilight a KlikAanKlikUit code can show up like this:
.. code-block:: console
{
"origin": "sender",
"protocol": "arctech_switches",
"code": {
"id": 100,
"unit": 15,
"state": off
},
"repeat": 1,
}
{
"origin": "sender",
"protocol": "arctech_dimmers",
"code": {
"id": 100,
"unit": 15,
"state": off
},
"repeat": 1,
}
{
"origin": "sender",
"protocol": "arctech_screens",
"code": {
"id": 100,
"unit": 15,
"state": up
},
"repeat": 1,
}
As you can see, a single KlikAanKlikUit command was interpreted as three different devices. You need to choose carefully which device actually sent the code to make sure how to define it in the device set-up. The difference is that a dimmer will have a slider and an on/off button, a switch will just show an on/off button, and a screen will have momentary up/down buttons. Defining a screen as a dimmer is possible but does not give you the ability to control the dimmer as a dimmer from the different GUIs.
Multiple IDs
------------
Each protocol needs to have at least one id defined so pilight knows what device has been controlled. However, it is possible that you have multiple KlikAanKlikUit remotes that control the same KlikAanKlikUit switch. In that case, you can define multiple id's to your devices. In case of a KlikAanKlikUit switch:
.. code-block:: json
:linenos:
{
"devices": {
"bookShelfLight": {
"protocol": ["kaku_switch"],
"id": [{
"id": 1234,
"unit": 0
},
{
"id": 2345,
"unit": 1
}],
"state": "off"
}
}
}
Whenever one of these id's have been received, pilight will update the device accordingly.
Multiple Protocols Per Device
-----------------------------
pilight supports multiple protocols per device. The new KlikAanKlikUit switches are backwards compatible with the old KlikAanKlikUit remotes. This means that pilight needs to check both protocols to know whether a device state was changed. In case of a KlikAanKlikUit dimmer, pilight needs to check three protocols. To add multiple protocols per device, the device must contain at least one ID for each protocol and all protocol values should be present. An example:
.. code-block:: json
:linenos:
{
"devices": {
"bookShelfLight": {
"protocol": [ "kaku_dimmer", "kaku_switch", "kaku_old" ],
"id": [{
"id": 123456,
"unit": 1
},
{
"id": 10,
"unit": 5
}],
"state": "off",
"dimlevel": 10
}
}
}
There are a few important steps when you use multiple protocols in a single device setup.
1. The kaku_dimmer and kaku_switch protocols both share the same id specifications, but the kaku_old protocol can only have an id < 16 and a unit < 33. The id set for the kaku_switch and kaku_dimmer is thereby not supported by the kaku_old protocol. Therefore an additional id must be added to match the requirements by kaku_old.
2. Because we have a dimmer and switch protocol combined we must have a dimlevel and state value present in the device.
3. The kaku_dimmer is the first protocol defined. This is important, because pilight will now interpret this device as a dimmer instead of a switch. Would the kaku_dimmer protocol be defined as second or third protocol, then the device would be interpreted as a switch.
Overriding Protocol Settings
----------------------------
Each protocol has some specific settings you can override in your device set-up. What these settings are, can be found in the protocols section of this manual. These settings can change the internal functioning of a protocol or the values a protocol can take. These settings are device specific.
For example, we do not want to have our dimmer to go to a full dimlevel, because then it is to bright. But we also do not want it to go to its minimum dimlevel, because then it is to dim. In that case, you can override the minimum and maximum values of the dimmer:
.. code-block:: json
:linenos:
{
"devices": {
"bookShelfLight": {
"protocol": [ "kaku_dimmer" ],
"id": [{
"id": 1234,
"unit": 1
}],
"state": "on",
"dimlevel": 3,
"dimlevel-minimum": 3,
"dimlevel-maximum": 10
}
}
}
Of course, the maximum dimlevels can still be overridden by the KlikAanKlikUit remote, but pilight will make sure it cannot control the dimmers below or above these dimlevels within pilight.
@@ -0,0 +1,58 @@
Example
=======
.. warning::
Make sure pilight is not running before editing your configuration or else all changes will be lost.
.. code-block:: json
:linenos:
{
"devices": {
"tv": {
"protocol": ["relay"],
"id": [{
"gpio": 3
}],
"state": "off",
"default-state": "off"
}
},
"rules": {
"lightswitch": {
"rule": "IF tv.state IS on THEN switch DEVICE tv TO off",
"active": 1
}
},
"gui": {
"tv": {
"name": "Television",
"group": ["Living"],
"media": ["all"],
"readonly": 0
}
},
"settings": {
"log-level": 6,
"pid-file": "/var/run/pilight.pid",
"log-file": "/var/log/pilight.log",
"webserver-enable": 1,
"webserver-http-port": 5001,
"webserver-cache": 1,
"webserver-root": "/usr/local/share/pilight"
},
"hardware": {
"433gpio": {
"sender": 0,
"receiver": 1
}
},
"registry": {
"pilight": {
"version": {
"current": "6.0"
}
}
}
}
@@ -0,0 +1,90 @@
GUI
===
- `Introduction`_
- `Elements`_
- `Group`_
Introduction
------------
.. warning::
Make sure pilight is not running before editing your configuration or else all changes will be lost.
pilight has an extensive API that allows developers to create custom graphical user interfaces (GUI). A pilight GUI is actually nothing more then a presentation of the devices a user wants to easily control. This means that a GUI does not have to show all devices added to the device set-up and that not all GUIs have to show the same devices. You can have a more compact GUI for a small screen such as a mobile phone or a more extensive GUI for you computer screen.
Elements
--------
Remember the device set-up we created earlier.
.. code-block:: json
:linenos:
{
"devices": {
"television": {
"protocol": [ "relay" ],
"id": [{
"gpio": 3
}],
"state": "off"
},
"bookShelfLight": {
"protocol": [ "kaku_switch" ],
"id": [{
"id": 123456,
"unit": 1
}],
"state": "off"
}
}
}
To present one of these two devices to our GUI, we add the to the GUI list like this:
.. code-block:: json
:linenos:
{
"gui": {
"television": {
"name": "Television",
"group": [ "Living" ],
"media": [ "web" ],
"readonly": 0
},
"bookShelfLight": {
"name": "Book Shelve",
"group": [ "Library" ],
"media": [ "mobile" ],
"readonly": 1
}
}
}
Each device you want to add to the GUI has its own entry. You can only add devices that are also registered in the device set-up, but of course, you do not have to present all those devices to the GUIs. There are some fixed fields that are common for all GUI elements:
- name
The display name inside the GUI.
- group
See below.
- media
Which GUIs should display this devices: mobile, web, desktop, all (default)
- readonly
Should the GUI element be readonly? Default is 0.
- confirm
Should the GUI ask for confirmation before switching the device? Default is 0.
To know what the additional options are for the specific protocols, check the protocol section of this manual.
Group
-----
The group attribute allows you to group GUI elements. pilight allows you to define multiple groups but it is dependent on the GUI how it will interpret these groups. Currently, the pilight webGUI and the Android App Illumina only parse the first group and will create different tabs for each one of them. However, possible implementation could be:
- Assign element to multiple groups
- Create a treeview of descending parents / children
- Create pages with grouped widgets
@@ -0,0 +1,85 @@
Hardware
========
- `Disabled`_
- `433.92Mhz`_
- `433lirc`_
- `433gpio`_
- `433nano`_
Introduction
------------
.. warning::
Make sure pilight is not running before editing your configuration or else all changes will be lost.
Since pilight 3.0 the feature to send and receive from multiple hardware modules has been introduced. This means you can control various different frequencies at the same time. However, only one module per frequency is supported. Each hardware module has its own syntax as listed below.
Disabled
--------
.. code-block:: json
:linenos:
{
"hardware": {
"none": { }
}
}
433.92Mhz
---------
.. _433lirc:
.. rubric:: Lirc Kernel Module
.. code-block:: json
:linenos:
{
"hardware": {
"433lirc": {
"socket": "/dev/lirc0"
}
}
}
.. _433gpio:
.. rubric:: Direct GPIO Access
.. code-block:: json
:linenos:
{
"hardware": {
"433gpio": {
"sender": 0,
"receiver": 1
}
}
}
The default configuration to be used with the pilight PCB. When using custom wiring, refer to http://www.wiringx.org for the pin numbering of the various supported devices. If you want to disable the sender or receiver pin, set it to
-1.
.. versionchanged:: 8.0
You must now specify which GPIO platform pilight is running on. Refer to the settings page for more information.
.. _433nano:
.. rubric:: pilight USB Nano
.. code-block:: json
:linenos:
{
"hardware": {
"433nano": {
"comport": "/dev/ttyUSB0"
}
}
}
The comport value needs to correspond to a valid COM device on your platform. On Windows this value is generally formatted as COM1, on Linux as /dev/ttyUSB0, and on FreeBSD /dev/cuau0.
@@ -0,0 +1,17 @@
.. raw:: latex
\newpage
Configuration
=============
.. toctree::
:maxdepth: 1
devices
rules
gui
settings
hardware
registry
example
@@ -0,0 +1,8 @@
Registry
========
.. warning::
Make sure pilight is not running before editing your configuration or else all changes will be lost.
Besides all the fixed configuration objects, pilight also allows developers to use the integrated registry. This registry allows developers to store information that can later be retrieved when reading the configuration. pilight itself will for example store its current version and available version in the registry and the pilight webGUI will store additional settings in there as well. You are therefore advised to leave the registry untouched so all additional information created by the different webGUIs is not lost.
@@ -0,0 +1,30 @@
Rules
=====
.. warning::
Make sure pilight is not running before editing your configuration or else all changes will be lost.
Since pilight version 6, eventing has been introduced. To use events, you need to first define rules inside the pilight configuration.
The basic pilight rule structure for the configuration looks like this:
.. code-block:: json
:linenos:
{
"rules": {
"rule_name": {
"rule": "IF switch.state IS on THEN switch DEVICE switch.state TO off",
"active": 1
}
}
}
As you can see, a rules object consists of various elements:
#. Each rule is placed in its own object with a unique identifier.
#. Each rule consists of the actual rule placed in the rule field.
#. Each rule consists of an active field that tells pilight if the rule is active or not.
You can of course define as many rules as you like.
@@ -0,0 +1,691 @@
Settings
========
- `Introduction`_
- `Core`_
- `port`_
- `standalone`_
- `pid-file`_
- `pem-file`_
- `log-file`_
- `log-level`_
- `whitelist`_
- `stats-enable`_
- `watchdog-enable`_
- `gpio-platform`_
- `Webserver`_
- `webgui-websockets`_
- `webserver-authentication`_
- `webserver-cache`_
- `webserver-enable`_
- `webserver-http-port`_
- `webserver-https-port`_
- `webserver-root`_
- `webserver-user`_
- `SMTP`_
- `smtp-sender`_
- `smtp-user`_
- `smtp-password`_
- `smtp-host`_
- `smtp-port`_
- `smtp-ssl`_
- `Miscellaneous`_
- `ntp-servers`_
- `Firmware`_
- `firmware-gpio-miso`_
- `firmware-gpio-mosi`_
- `firmware-gpio-reset`_
- `firmware-gpio-sck`_
- `Module Paths`_
- `action-root`_
- `function-root`_
- `hardware-root`_
- `operator-root`_
- `protocol-root`_
Introduction
------------
.. warning::
Make sure pilight is not running before editing your configuration or else all changes will be lost.
The way pilight functions can be altered by changing various settings. All pilight settings will be described in this chapter grouped by their respective category.
Core
----
.. _port:
.. rubric:: port
.. note::
Linux, \*BSD, and Windows
.. code-block:: json
:linenos:
{ "port": 5000 }
By default, pilight uses a random port for its socket server. Use the port setting if you want to set this to a fixed port.
.. _standalone:
.. rubric:: standalone
.. note::
Linux, \*BSD, and Windows
.. code-block:: json
:linenos:
{ "standalone": 0 }
When pilight starts, it will first check if there are other instances running inside the same network. If it does, it will connect to the other pilight instance and will join or create the AdHoc network. If you want to force pilight into running as a standalone daemon, you can set the standalone setting to 1. When running pilight in standalone mode, the SSDP server will also be disabled. This means that other pilight clients will not be able to discover it using SSDP.
.. _pid-file:
.. rubric:: pid-file
.. note::
Linux and \*BSD
.. code-block:: json
:linenos:
{ "pid-file": "/var/run/pilight.pid" }
The pid-file is used by pilight to save the process id number of the pilight-daemon. pilight itself uses this information as one of the ways to determine if pilight is already running or not. This setting must contain a valid path to store the pid-file.
.. _pem-file:
.. rubric:: pem-file
.. note::
Linux and \*BSD
.. code-block:: json
:linenos:
{ "pem-file": "/etc/pilight/pilight.pem" }
.. note::
Windows
.. code-block:: json
:linenos:
{ "pem-file": "c:/pilight/pilight.pem" }
The pem-file is used by pilight for the secure https webserver. Using the default pilight pemfile makes the secure webserver still insecure, so users are adviced to generate a custom pem file.
.. code-block:: console
pi@pilight ~# openssl req -x509 -newkey rsa:4096 -sha256 -nodes -keyout pilight.key -out pilight.crt -subj "/CN=pilight.org" -days 3650
pi@pilight ~# cat pilight.key pilight.crt > /etc/pilight/pilight.pem
.. _log-file:
.. rubric:: log-file
.. note::
Linux and \*BSD
.. code-block:: json
:linenos:
{ "log-file": "/var/log/pilight.log" }
.. note::
Windows
.. code-block:: json
:linenos:
{ "log-file": "c:/pilight/pilight.log" }
The log-file is used by pilight to various information gathered while pilight is running. This information can be used to debug errors or gather information about triggered actions. This setting must contain a valid path to store the log-file.
.. _log-level:
.. rubric:: log-level
.. note::
Linux, \*BSD, and Windows
.. code-block:: json
:linenos:
{ "log-level": 4 }
The log-level tells pilight what messages it should log into the log-file. The higher the log-level the more messages are logged into the log-file. The highest log-level is 6 and the lowest is 0. These log-levels correspond to the following log types:
0 = emergency, 1 = alert, 2 = critical, 3 = , 4 = warning,
5 = notification, 6 = information
.. _whitelist:
.. rubric:: whitelist
.. note::
Linux, \*BSD, and Windows
.. code-block:: json
:linenos:
{ "whitelist": [ "*.*.*.*" ] }
All software able to use socket connections can communicate to pilight. Such software can be *pilight-receive*, a user visiting the webGUI, or external pilight plugins such a provided by FHEM. If you want to limit the computers in your network that can connect to pilight, you set up a whitelist. This setting should contain a list of valid IPv4 addresses that are allowed to connect to pilight. All other IPs will be blocked. If you want to allow IPv4 ranges, you can specify them by using wildcards. For example, if we want to allow all IP addresses ranging from 192.168.1.0 to 192.168.1.254 we can add the IP address 192.168.1.* to the list. If we want to allow all IP addresses ranging from 10.0.0.0 to 10.0.254.254 we can add the IP address 10.0.*.* to the list. Each whitelist entry should contain a valid IPv4 address with or without using wildcards.
.. _stats-enable:
.. rubric:: stats-enable
.. note::
Linux, \*BSD, and Windows
.. code-block:: json
:linenos:
{ "stats-enable": 1 }
pilight monitors its own CPU and RAM resource usage. This information can be shared with external clients and is shared by default with the websockets connections. If you want to disable the display of the CPU and RAM statistics and/or want to disable the communication of these statistics over the websocket connection you can set this to 0. This setting can be either 0 or 1.
.. _watchdog-enable:
.. rubric:: watchdog-enable
.. note::
Linux, \*BSD, and Windows
.. code-block:: json
:linenos:
{ "watchdog-enable": 1 }
pilight monitors its own CPU and RAM resource usage. This information is used to shutdown or terminate pilight when it uses too much CPU or RAM. If want to disable this watchdog feature and therefor the automatic termination of pilight when needed, you can set this setting to 0. This setting can be either 0 or 1.
.. _gpio-platform:
.. rubric:: gpio-platform
.. versionadded:: 8.0
.. note::
Linux, \*BSD, and Windows
.. code-block:: json
:linenos:
{ "gpio-platform": "raspberrypi2" }
pilight can be ran on various GPIO compatible platforms. However, it is impossible to reliably distinguish them all. Therefor, you must specify on which platform you are running pilight. Under the hood, pilight uses the wiringX library to interface with the GPIO of your platform. Only those platforms that are supported by wiringX are also supported by pilight. A full and recent list of supported platforms retrieved by calling the following command:
.. code-block:: console
# ./pilight-daemon -H
Usage: pilight-daemon [options]
-H --help display usage summary
-V --version display version
-C --config config file
-S --server=x.x.x.x connect to server address
-P --port=xxxx connect to server port
-F --foreground do not daemonize
-D --debug do not daemonize and
show debug information
--stacktracer show internal function calls
--threadprofiler show per thread cpu usage
--debuglevel show additional development info
The following GPIO platforms are supported:
- none
- odroidxu4
- odroidc2
- odroidc1
- raspberrypi3
- raspberrypi2
- raspberrypizero
- raspberrypi1b+
- raspberrypi1b2
- raspberrypi1b1
- hummingboard_edge_dq
- hummingboard_gate_dq
- hummingboard_edge_sdl
- hummingboard_gate_sdl
- hummingboard_base_dq
- hummingboard_pro_dq
- hummingboard_base_sdl
- hummingboard_pro_sdl
- orangepipc+
- bananapim2
- bananapi1
- pcduino1
If you are running on a platform that doesn't support GPIO, you can either use ``none`` as the ``gpio-platform`` or remove the setting altogether.
Webserver
---------
The following settings change the way the internal webserver will serve the internal pilight webGUI or it can be disabled altogether.
.. _webgui-websockets:
.. rubric:: webgui-websockets
.. note::
Linux, \*BSD, and Windows
.. code-block:: json
:linenos:
{ "webgui-websockets": 1 }
By default the webGUI communicates to pilight by using websockets. This is a relatively new technique that allows us to receive all changes from pilight instead of having to poll pilight for changes. The problem is that some older devices and browsers do not support websockets, but they do support the polling technique. So to disable the websockets and use polling instead we set webgui-websockets setting to 0. This setting can be either 0 or 1.
.. _webserver-authentication:
.. rubric:: webserver-authentication
.. note::
Linux, \*BSD, and Windows
.. code-block:: json
:linenos:
{ "webserver-authentication": [ "username", "password" ] }
By default, pilight can be controlled from the webGUI by anyone that can access it. If you want to prevent this, you can secure the webGUI with a username and password. The username should be in plain text, the password is SHA256 encrypted. Use pilight-sha256 to create the encrypted password hash. Regular SHA256 encryption tools will not work because pilight hashes the password several thousand times.
.. code-block:: console
pi@pilight ~# pilight-sha256 -p admin
4f32102debed8dabd87e88cf84c752ccb23a74b29f90b42edde05cbc7be41f80
So if we want to use a username user and password admin the values should look like this:
.. code-block:: json
:linenos:
{ "webserver-authentication": [ "user", "4f32102debed8dabd87e88cf84c752ccb23a74b29f90b42edde05cbc7be41f80" ] }
.. _webserver-cache:
.. rubric:: webserver-cache
.. note::
Linux, \*BSD, and Windows
.. code-block:: json
:linenos:
{ "webserver-cache": 1 }
pilight has the ability to cache all files used for the webGUI. This reduces the amount of reads done from the SD card on devices like the Raspberry Pi and Hummingboard, and makes it faster to load the webGUI from devices with a slow internal storage such as routers. This setting can be either 0 or 1.
.. _webserver-enable:
.. rubric:: webserver-enable
.. note::
Linux, \*BSD, and Windows
.. code-block:: json
:linenos:
{ "webserver-enable": 1 }
The pilight webserver can be turned off as a whole. This could be useful if you do not want to use the webGUI at all or if you want to use your own webserver implementation. This setting can be either 0 or 1.
.. _webserver-http-port:
.. rubric:: webserver-http-port
.. note::
Linux, \*BSD, and Windows
.. code-block:: json
:linenos:
{ "webserver-http-port": 5001 }
The pilight webserver runs by default on the non-standard port 5001. This is done to prevent interference with other webservers running on the default HTTP port 80. If you do want to run the webserver on port 80 or any other port, you can change this setting. The port specified must be a valid and unused port.
.. _webserver-https-port:
.. rubric:: webserver-https-port
.. deprecated:: 8.0
.. versionadded:: 8.0.3
.. note::
Linux, \*BSD, and Windows
.. code-block:: json
:linenos:
{ "webserver-https-port": 5002 }
The webserver does not allow secure connections by default. Currently the only way to get HTTPS support is by manually compiling pilight. The pilight secure webserver runs by default on the non-standard port 5002. This is done to prevent interference with other webservers running on the default HTTPS port 443. If you do want to run the secure webserver on port 443 or any other port, you can change this setting. The port specified must be a valid and unused port.
.. _webserver-root:
.. rubric:: webserver-root
.. note::
Linux, \*BSD, and Windows
.. code-block:: json
:linenos:
{ "webserver-root": "/usr/local/share/pilight" }
.. versionchanged:: 8.0
.. code-block:: json
:linenos:
{ "webserver-root": "/usr/local/share/pilight/webgui" }
The webserver root tells pilight where it should look for all files that should be served by the webserver. This setting must contain a valid path.
.. _webserver-user:
.. rubric:: webserver-user
.. note::
Linux
.. code-block:: json
:linenos:
{ "webserver-user": "www-root" }
.. note::
\*BSD
.. code-block:: json
:linenos:
{ "webserver-user": "www" }
The webserver runs by default as a non-root user. This to prevent the execution of malicious code. If you want to force the webserver to run as the root user or any other system user, you can change this setting accordingly. This setting needs to contain a valid system user.
SMTP
----
pilight has the capability to communicate with several types of mail servers. This offers pilight the possibility to use for example mail actions inside our event rules, so email messages can be sent in case of a certain event. Most users will have an email account from their internet hosting provider or free mail solutions can be used like gmail. In case of a (non-existing) gmail account named: pilight@gmail.com with password: foobar, the SMTP settings should be configured like this:
.. code-block:: json
:linenos:
{
"smtp-sender": "pilight@gmail.com",
"smtp-host": "smtp.gmail.com",
"smtp-port": 465,
"smtp-user": "pilight@gmail.com",
"smtp-password": "foobar",
"smtp-ssl": 1
}
.. _smtp-sender:
.. rubric:: smtp-sender
.. note::
Linux, \*BSD, and Windows
.. code-block:: json
:linenos:
{ "smtp-sender": "...@....com" }
The smtp-sender requires a valid e-mail address. As soon as a mail is sent by pilight, this e-mail address will be used as the address from with the mail was sent.
.. _smtp-user:
.. rubric:: smtp-user
.. note::
Linux, \*BSD, and Windows
.. code-block:: json
:linenos:
{ "smtp-user": "...@....com" }
The smtp-user requires a valid e-mail address. This e-mail address is used to validate the account details at the e-mail provider.
.. versionchanged:: 8.0 Allow any string for smtp-user
The smtp-user can be any string, and doesn't have to be an valid e-mail address anymore.
.. _smtp-password:
.. rubric:: smtp-password
.. note::
Linux, \*BSD, and Windows
.. code-block:: json
:linenos:
{ "smtp-password": "..." }
The smtp-password is used to validate the account details at the e-mail provider together with the smtp-user setting. The password should therefore be a valid password for this e-mail account.
.. _smtp-host:
.. rubric:: smtp-host
.. note::
Linux, \*BSD, and Windows
.. code-block:: json
:linenos:
{ "smtp-host": "smtp.foo.com" }
The smtp-host setting should contain a valid mail server hostname. Normally, the host name is similar to name of the internet hosting provider.
.. _smtp-port:
.. rubric:: smtp-port
.. note::
Linux, \*BSD, and Windows
.. code-block:: json
:linenos:
{ "smtp-port": 25 }
.. deprecated:: 8.0.3
The smtp-port should contain a valid smtp server port. This can currently be either 25, 465, or 587. pilight will communicate over a secure connection when using port 465, when using port 25 or 587 it will depend on the server how pilight will set-up the connection.
.. versionchanged:: 8.0.3
The smtp-port should contain a valid smtp server port. This can be any port. SSL connections should be explicitly defined in the smtp-ssl setting.
.. versionadded:: 8.0.3
.. _smtp-ssl:
.. rubric:: smtp-ssl
.. note::
Linux, \*BSD, and Windows
.. code-block:: json
:linenos:
{ "smtp-ssl": 0 }
The smtp-ssl tells pilight if the mailserver uses a secure SSL communication from the start. If server change to SSL while initializing a connection, pilight will do so automatically as well. In those cases, this setting can be set to zero.
Miscellaneous
-------------
.. _ntp-servers:
.. rubric:: ntp-servers
.. note::
Linux, \*BSD, and Windows
.. code-block:: json
:linenos:
{ "ntp-servers": [ "eu.pool.ntp.org", "uk.pool.ntp.org" ] }
One important feature of any automation setup is the ability to trigger time based actions. However, these events greatly rely on a correct date and time. Problems occur when the system time is not set to the correct time (for our specific timezone). This can happen on systems like the Raspberry Pi which does not have a RTC that allows it to keep track of time when turned off. To overcome this problem pilight has the ability to retrieve the correct time by synchronizing with NTP servers. You can pick any server from http://www.pool.ntp.org/. Any number of servers can be added to the ntp-servers list. pilight will first try to synchronize with the first server. If this fails it will try the second server etc. It will continue this process until an actual response was received.
Firmware
--------
pilight provides an easy tool to flash the firmware of several microcontrollers in the form of pilight-flash. pilight flashes microcontrollers by using either bitbanging or through USB. To use bitbanging we need four GPIOs. These GPIOs are by default configured for usage on a Raspberry Pi. They can however, be changed to other GPIOs according to the device you want to use. Each GPIO is named according to the SPI requirements, but any GPIO can be used because we are not actually using SPI to communicate with our microcontrollers. In pilight the SPI identifiers MISO, MOSI, Reset and SCK are only used to separate the different GPIO.
If you are unsure what valid GPIOs are on your platform,
please refer to the http://www.wiringx.org documentation.
.. _firmware-gpio-miso:
.. rubric:: firmware-gpio-miso
.. note::
Linux and \*BSD
.. code-block:: json
:linenos:
{ "firmware-gpio-miso": 13 }
This setting defines the GPIO pin to be used as MISO. Any valid GPIO for your platform can be used.
.. _firmware-gpio-mosi:
.. rubric:: firmware-gpio-mosi
.. note::
Linux and \*BSD
.. code-block:: json
:linenos:
{ "firmware-gpio-mosi": 12 }
This setting defines the GPIO pin to be used as MOSI. Any valid GPIO for your platform can be used.
.. _firmware-gpio-reset:
.. rubric:: firmware-gpio-reset
.. note::
Linux and \*BSD
.. code-block:: json
:linenos:
{ "firmware-gpio-reset": 10 }
This setting defines the GPIO pin to be used as Reset. Any valid GPIO for your platform can be used.
.. _firmware-gpio-sck:
.. rubric:: firmware-gpio-sck
.. note::
Linux and \*BSD
.. code-block:: json
:linenos:
{ "firmware-gpio-sck": 14 }
This setting defines the GPIO pin to be used as SCK. Any valid GPIO for your platform can be used.
Module Paths
------------
pilight has the possibility to load various external modules to enhance its functionality. These modules are single files and should be placed in fixed folders. However, these folders locations can be changed by altering one of the following settings.
.. warning::
There is generally no reason to load external modules.
The latest pilight version always contains the latest
protocols, hardware drivers, event operators, functions,
and actions.
.. _action-root:
.. rubric:: action-root
.. note::
Linux and \*BSD
.. code-block:: json
:linenos:
{ "action-root": "/usr/local/lib/pilight/action" }
pilight event actions are loaded from the action-root folder. The action-root setting must contain a valid path.
.. _function-root:
.. rubric:: function-root
.. note::
Linux and \*BSD
.. code-block:: json
:linenos:
{ "function-root": "/usr/local/lib/pilight/function" }
pilight event actions are loaded from the function-root folder. The function-root setting must contain a valid path.
.. _hardware-root:
.. rubric:: hardware-root
.. note::
Linux and \*BSD
.. code-block:: json
:linenos:
{ "hardware-root": "/usr/local/lib/pilight/hardware" }
pilight event actions are loaded from the hardware-root folder. The hardware-root setting must contain a valid path.
.. _operator-root:
.. rubric:: operator-root
.. note::
Linux and \*BSD
.. code-block:: json
:linenos:
{ "operator-root": "/usr/local/lib/pilight/operator" }
pilight event actions are loaded from the operator-root folder. The operator-root setting must contain a valid path.
.. _protocol-root:
.. rubric:: protocol-root
.. note::
Linux and \*BSD
.. code-block:: json
:linenos:
{ "protocol-root": "/usr/local/lib/pilight/protocol" }
pilight event actions are loaded from the protocol-root folder. The protocol-root setting must contain a valid path.
@@ -0,0 +1,425 @@
API
===
- `Identification`_
- `Options`_
- `Actions`_
- `Webserver (REST Api)`_
- `Heartbeat`_
- `Buffer Sizes`_
Identification
--------------
All programs communicate with each other by using JSON objects. The normal identification process is as follows:
- Connect to pilight-daemon by using the pilight IP and port. The port pilight is running at is either a randomly chosen number or a fixed number as configured in the pilight settings.
- The pilight-daemon waits for the client to identify itself by sending the following JSON object:
.. code-block:: json
:linenos:
{
"action": "identify"
}
- Additionally, a client can send certain options to tell the daemon what level of communication is the client want to set-up. A full identification JSON looks like this:
.. code-block:: json
:linenos:
{
"action": "identify",
"options": {
"core": 1,
"receiver": 1,
"config": 1,
"forward": 0
},
"uuid": "0000-d0-63-00-000000",
"media": "all"
}
- After each action, the daemon will send either one of the following two status responses indicating a success or failure:
.. code-block:: json
:linenos:
{
"status": "success"
}
.. code-block:: json
:linenos:
{
"status": "failure"
}
Options
-------
The identification options define what communication is set-up between the daemon and the client.
- receiver
When the receiver option is set, the daemon will forward the received or sent codes to the client. An example:
.. code-block:: json
:linenos:
{
"origin": "receiver",
"protocol": "kaku_switch",
"code": {
"id": 1234,
"unit": 0,
"off": 1
}
}
{
"origin": "sender",
"protocol": "kaku_switch",
"code": {
"id": 1234,
"unit": 0,
"off": 1
}
}
In the received JSON messages, the origin will tell if an externally received message was received or a code sent by pilight self.
- config
When the config option is set, the daemon will communicate all configuration updates. An example:
.. code-block:: json
:linenos:
{
"origin": "config",
"devices": [ "mainlight" ],
"values": {
"state": "on"
}
}
|
- core
When the core option is set, the daemon will communicate pilight core information.
- stats
When the stats option is set, the daemon will communicate the RAM and CPU statistics.
.. code-block:: json
:linenos:
{
"origin": "core",
"values": {
"cpu": 0.07822473698105643,
"ram": 0.1535397936955158
},
"type": -1,
"uuid": "0000-d0-63-00-000000"
}
|
- forward
When the forward option is enabled, all incoming (valid) socket data will be forwarded to the client.
The uuid setting is meant for the client to send its unique UUID.
The media setting is used to tell the daemon what information is sent based on the specific media. As can be read in the GUI configuration, a user can create different GUIs based on different devices. The currently supported GUI types are all, web, mobile, and desktop. If you define your client as one of those GUI types, pilight will only send devices, GUI elements, config updates and rules that apply the specific GUI type, leaving the rest out. Therefore, you do not have to do any additional parsing on the client side.
These options can be updated on-the-fly while the client is running. The daemon will start or stop sending specific messages. To update these options, just send another identification request. An example identification object:
.. code-block:: json
:linenos:
{
"action": "identify",
"options": {
"stats": 1,
"receiver": 1
},
"uuid": "0000-d0-63-00-000000"
}
Actions
-------
As we have seen in the identification process, pilight can handle several actions. The first action we encounter is the identification action. The following list contains all possible actions the daemon can handle. Again, the daemon will respond to all actions with a success and failure so the client can check if the action succeeded.
- send
In case the client wants to send specific protocol codes, the send action is used. A sent action is accompanied by specific additional arguments:
.. code-block:: json
:linenos:
{
"action": "send",
"code": {
"protocol": [ "kaku_switch" ],
"id": 1234,
"unit": 0,
"off": 1
}
}
These are basically the command like arguments. If an argument requires a value, then the value is added to the argument (as with id and unit). If the argument does not take a value, than it is defaulted to 1 (as with off). The pilight-daemon will check if the code was valid, and report back with a failure if it was not.
- control
The control action is used to control registered devices by using their device IDs. The pilight-daemon will check if the values are valid and report back with a failure if they are not. An example control object:
.. code-block:: json
:linenos:
{
"action": "control",
"code": {
"device": "mainlight",
"state": "on",
"values": {
"dimlevel": 10
}
}
}
|
- registry
The pilight registry can be managed by the registry API. The registry is a multi-purpose storage solution within pilight. Developers can store any information they want inside it so it is retrievable later on. The registry allows three types of actions: set, get, remove. The syntax for each on of them is:
.. code-block:: json
:linenos:
{
"action": "registry",
"type": "set",
"key": "pilight.version",
"value": "6.0"
}
.. code-block:: json
:linenos:
{
"action": "registry",
"type": "get",
"key": "pilight.version"
}
.. code-block:: json
:linenos:
{
"action": "registry",
"type": "remove",
"key": "pilight.version"
}
The response to a get command is as follows:
.. code-block:: json
:linenos:
{
"action": "registry",
"value": "6.0",
"key": "pilight.version"
}
Please note that the pilight registry can only hold JSON string and number types.
- request config
The request config is used to request the full configuration object from the pilight-daemon:
.. code-block:: json
:linenos:
{
"action": "request config"
}
|
After this command, the pilight-daemon will send the raw JSON configuration as it is used internally.
.. code-block:: json
:linenos:
{
"devices": {
"tv": {
"uuid": "0000-00-00-07-646b93",
"origin": "0000-d0-63-00-000000",
"timestamp": 0,
"protocol": [ "relay" ],
"id": [{
"gpio": 3
}],
"state": "off",
"default": "off"
}
},
"rules": {
"tvswitch": {
"rule": "IF tv.state IS on THEN switch DEVICE tv TO off",
"active": 1
}
},
"gui": {
"television": {
"type": 4,
"order": 1,
"name": "tv",
"group": [ "Living" ],
"media": [ "all" ],
"readonly": 0
}
},
"settings": {
"log-level": 4,
"pid-file": "/var/run/pilight.pid",
"log-file": "/var/log/pilight.log",
"webserver-enable": 1,
"webserver-http-port": 5001,
"webserver-cache": 0,
"webserver-root": "/usr/local/share/pilight"
},
"hardware": {
"433gpio": {
"sender": 0,
"receiver": 1
}
},
"registry": {
"pilight": {
"version": {
"current": "6.0"
}
}
}
}
- request values
.. code-block:: json
:linenos:
{
"action": "request values"
}
pilight tries to make app development as easy as possible. This means that GUIs should only have to parse the GUI configuration object. The downside however is that the GUI object does not contain the device values. To solve this issue, the GUIs can request the values for all devices at once. The returned object will have the same information as the daemon communicates with the config option enabled, but now in bulk for all devices. An example:
.. code-block:: json
:linenos:
[{
"type": 4,
"devices": [ "tv" ],
"values": {
"timestamp": 0,
"state": "off"
}
},
{
"type": 1,
"devices": [ "bookShelfLight" ],
"values": {
"timestamp": 0,
"state": "off"
}
}]
Please be aware that right after the request values object, the pilight version object is sent. It is up to the GUIs to ignore or parse this information.
Webserver (REST API)
--------------------
The webserver has some special pages:
- The config page will present the latest configuration JSON object.
- The values page will present the latest values of all device.
The values and config page will by default only show the configuration that applies to a web GUI type. To retrieve the configuration relevant for other GUI types, use the media argument:
.. code-block:: console
http://x.x.x.x:5001/config?media=all
.. versionadded:: 4.0 Send codes through webserver
- The send page can be used to control devices. To use this function, call the send page with a URL-encoded "send" or "registry" JSON object like this:
.. code-block:: console
send%3F%7B%0A%09%22action%22%3A%20%22control%22%2C%0A%09%22code%22%3A%20%7B%0A%09%09%22device%22%3A%20%22mainlight%22%2C%0A%09%09%22state%22%3A%20%22on%22%2C%0A%09%09%22values%22%3A%20%7B%0A%09%09%09%22dimlevel%22%3A%20%2210%22%0A%09%09%7D%0A%09%7D%0A%7D
This will send the object as described earlier.
.. versionchanged:: 8.0 Implemented REST API instead of posting arbitrary JSON codes
- The send page has the same functionality as the ``pilight-send`` program and uses the same arguments:
.. code-block:: guess
http://x.x.x.x:5001/send?protocol=kaku_switch&on=1&id=1&unit=1
As can be seen, the URL arguments are the same as for the ``kaku_switch`` protocol:
.. code-block:: console
pi@pilight:~# pilight-send -p kaku_switch -H
...
[kaku_switch]
-t --on send an on signal
-f --off send an off signal
-u --unit=unit control a device with this unit code
-i --id=id control a device with this id
-a --all send command to all devices with this id
-l --learn send multiple streams so switch can learn
All protocols can be controlled using their respective arguments using the webserver send page as described in this example.
- The control page has the same functionality as the ``pilight-control`` program and uses the same arguments:
.. code-block:: guess
http://x.x.x.x/control?device=nasStatus&values[label]=computer%20is%20disconnected&values[color]=red
In this case a generic_label device is being controlled
Heartbeat
---------
One special function of the *pilight-daemon* is the heartbeat. The heartbeat is meant to check if a connection is still alive. The client has to send a "HEART\n" on which the *pilight-daemon* will respond with a "BEAT\n". This is the only exception in which not a JSON object is sent.
Buffer Sizes
------------
pilight will sends all streams in 1024 bits. If these streams are smaller than 1024 bits, everything was sent at once. If a stream is 1024 bits, then you will know it is a chunk of a bigger stream. In that case, read until you encounter the end of streams delimiter which is currently made up of two new lines "\n\n".
If multiple streams were buffered somewhere, you can also distinguish them by the double new line delimiters. An example:
.. code-block:: console
:linenos:
{"message":"test"}\n\n
{"message":"test"}\n\n
{"message":"test"}\n\n
As you can see. pilight wanted to send three messages, but the TCP sockets concatenated them to one.
The pilight socket_read function takes care of these buffered messages to check if we encountered concatenated multiple streams. pilight will then convert these messages back so the output is just one big stream separated by single newlines:
.. code-block:: console
:linenos:
{"message":"test"}\n
{"message":"test"}\n
{"message":"test"}\n
@@ -0,0 +1,173 @@
Debugging
=========
- `Introduction`_
- `Prerequisites`_
- `How to recognize a Bug?`_
- `How to Debug?`_
Introduction
------------
pilight is a product developed by a growing community. Due to its Open Source character, developers around the world can contribute code. Although all developers try to write bug free code, it is not always possible for the developers of pilight to check for every possible mistake that can be made. Especially, because not everyone has every hardware available for testing.
Prerequisites
-------------
If you found this page, you probably encountered a bug in the pilight code or noticed that things are not working as they should be. Before you continue reading, consider the following.
First, pilight offers code in several stages of stability:
#. Stable apt repository and GitHub master branch
This code has been tested to work without bugs for various weeks by the developer and a large community. If bugs are found in this version of pilight, the problem has probably already been fixed in the developmental code.
#. Nightly apt repository and GitHub development branch
This code always contains the very latest features and fixes. It is updated several times a week. However, this also means that not all bugs are already encountered when a user starts to use it.
Second, this page is made for those users using the developmental GitHub branch. This tutorial assumes the following:
#. You are aware of the distinction between bugs and changes in the pilight functionality.
#. You have read the GitHub commit messages to be sure that what you have encountered is indeed a bug and not a changed functionality.
#. You have enough experience working with your operating system.
#. You have the patience to help finding the problem.
#. You have some knowledge about programming (and the C language).
#. You know when to recognize a clear code bug.
#. You are able to manually compile pilight so debugging is possible. The automatically compiled versions do not support debugging as described here.
How to Recognize a Bug?
-----------------------
The two most encountered bugs are the memory issues or the segmentation faults. A memory bug can look like this:
.. code-block:: console
* glibc detected ./pilight-daemon: double free or corruption (!logfile): 0x0000000000c6ed50 **
This message means in this case that the variable logfile was freed twice.
A segmentation fault looks like this:
.. code-block:: console
pi@raspberrypi ~/pilight $ sudo service pilight start
[....] Starting : pilightSegmentation fault
failed!
This message means there has been a general error in which pilight so it cannot be started properly.
How to Debug?
-------------
To debug C code, the GNU Debugger is used, also called gdb. This program will run next to pilight without any performance issue, but when pilight crashes, it allows us to track the specific line where the error occurred. So first of all, make sure you have gdb installed. This is how you start gdb together with pilight:
.. code-block:: console
pi@pilight:~> sudo su
root@pilight:~# gdb --args pilight-daemon -D
GNU gdb (GDB) 7.4.1-debian
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "arm-linux-gnueabihf".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /usr/local/sbin/pilight-daemon...done.
(gdb) run
Starting program: /usr/local/sbin/pilight-daemon -D
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/arm-linux-gnueabihf/libthread_db.so.1".
[Jan 18 16:23:33:657363] pilight-daemon: DEBUG: ssdp sent search
[Jan 18 16:23:33:701618] pilight-daemon: NOTICE: no pilight daemon found, daemonizing
[Jan 18 16:23:33:718878] pilight-daemon: DEBUG: -- start parsed config file --
Now pilight will start as it you would have started it normally. Just let it run like this until it crashes or try to invoke the crash. If it crashes, you will see something like this:
.. code-block:: console
*** glibc detected *** /usr/local/sbin/pilight-daemon: double free or corruption (fasttop): 0x000369d8 ***
[New Thread 0xb228c470 (LWP 26235)]
Program received signal SIGABRT, Aborted.
[Switching to Thread 0xb4d7d470 (LWP 26230)]
0xb6dddbfc in __GI_raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:67
67 ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb)
Again, you see the **(gdb)** prompt that allows you to type new commands.
The first step is to get a backtrace of all functions called when this crash occurred:
.. code-block:: console
(gdb) backtrace
#0 0xb6dddbfc in __GI_raise (sig=6)
at ../nptl/sysdeps/unix/sysv/linux/raise.c:67
#1 0xb6de197c in __GI_abort () at abort.c:92
#2 0xb6e15cf8 in __libc_message (do_abort=2,
fmt=0xb6ec78d0 "*** glibc detected *** %s: %s: 0x%s ***\n")
at ../sysdeps/unix/sysv/linux/libc_fatal.c:189
#3 0xb6e20584 in malloc_printerr (action=3,
str=0xb6ec7a6c "double free or corruption (fasttop)", ptr=<optimized out>)
at malloc.c:6283
#4 0xb6e24e00 in __GI___libc_free (mem=<optimized out>) at malloc.c:3738
#5 0x0000b5d8 in broadcast (param=<optimized out>) at daemon.c:260
#6 0xb6ee6bfc in start_thread (arg=0xb4d7d470) at pthread_create.c:306
#7 0xb6e7b758 in ?? ()
at ../ports/sysdeps/unix/sysv/linux/arm/nptl/../clone.S:116
from /lib/arm-linux-gnueabihf/libc.so.6
#8 0xb6e7b758 in ?? ()
at ../ports/sysdeps/unix/sysv/linux/arm/nptl/../clone.S:116
from /lib/arm-linux-gnueabihf/libc.so.6
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
(gdb)
Copy this output so it can be communicated on the forum.
The second step is to look for the exact line causing this crash. This can be done by zooming into each part of each function related to this bug. We start at the end and work our way to the beginning. To zoom into a function the command **frame** # is used in which the # is replaced by one of the numbers you see in the backtrace. As said earlier, we will start at the end:
.. code-block:: console
(gdb) frame 8
#8 0xb6e7b758 in ?? ()
at ../ports/sysdeps/unix/sysv/linux/arm/nptl/../clone.S:116
from /lib/arm-linux-gnueabihf/libc.so.6
116 ../ports/sysdeps/unix/sysv/linux/arm/nptl/../clone.S: No such file or directory.
This doesn't tell us anything useful. So we continue to the previous frame.
.. code-block:: console
(gdb) frame 7
#7 0xb6e7b758 in ?? ()
at ../ports/sysdeps/unix/sysv/linux/arm/nptl/../clone.S:116
from /lib/arm-linux-gnueabihf/libc.so.6
116 ../ports/sysdeps/unix/sysv/linux/arm/nptl/../clone.S: No such file or directory.
Still no useful information here.
.. code-block:: console
(gdb) frame 6
#6 0xb6ee6bfc in start_thread (arg=0xb4d7d470) at pthread_create.c:306
306 pthread_create.c: No such file or directory.
Nope.
.. code-block:: console
(gdb) frame 5
#5 0x0000b5d8 in broadcast (param=<optimized out>) at daemon.c:260
260 json_delete(jret);
Yes, finally something related to pilight. As you can see here, the conflicting line can be found in daemon.c in the function broadcast at line 260. The actual command that leaded to the crash was json_delete. Although we now know that this was the line causing the crash, the actual bug could lay elsewhere. Therefore we continue until the last pilight related frame.
No useful information in frame 4. So, frame 5 was the only interesting frame here. Make sure to copy the output of the informative frames so it can be used in a forum post later on.
To exit:
.. code-block:: console
(gdb) q
As you might have seen, this way of debugging makes it a lot easier to track bugging code. gdb will tell you the exact line on which the bug occurred to in can be easier tracked down and fixed.
@@ -0,0 +1,8 @@
Development
===========
.. toctree::
:maxdepth: 1
api
debugging
@@ -0,0 +1,8 @@
Electronics
===========
.. toctree::
:maxdepth: 1
wiring
pcb_soldering
@@ -0,0 +1,200 @@
PCB Soldering
=============
- `Introduction`_
- `PCB Eights`_
- `Headers`_
- `Voltage Regulator`_
- `PCB Quarter`_
- `P1 Meter`_
- `PCB Half`_
- `Pre-Filter`_
- `PCB Full`_
Introduction
------------
The pilight PCB can be ordered as a do-it-yourself kit or pre-soldered. In case you want to solder it yourself, this page will show you all steps needed. If you follow all steps, you will eventually end up with the full pilight PCB. However, if you want to leave certain options, just pick the steps you need.
PCB Eights
----------
.. _Headers:
.. rubric:: Headers
First start by soldering the two headers. This makes it easier to position the rest of the components.
.. |fig1| image:: ../images/soldering/1.jpg
.. rst-class:: alt
+-----------------------+
| |fig1| |
+-----------------------+
| Image 1: First Header |
+-----------------------+
.. |fig2| image:: ../images/soldering/2.jpg
.. rst-class:: alt
+------------------------+
| |fig2| |
+------------------------+
| Image 2: Second Header |
+------------------------+
As you can see, the second header is wider than the number of pins on the PCB. Just strip the unconnected connections on the left side to make the header evenly wide as the PCB.
.. |fig3| image:: ../images/soldering/3.jpg
.. rst-class:: alt
+---------------------------------+
| |fig3| |
+---------------------------------+
| Image 3: Stripped Second Header |
+---------------------------------+
.. _Voltage Regulator:
.. rubric:: Voltage Regulator
The voltage regulator consists of a capacitor, resistor, and transistor. First start by soldering the transistor close to the first header. Make sure to match the flat and rounded side of the transistor as shown on the PCB itself. Also make sure to push the transistor far through enough so it stays under the first header.
.. |fig4| image:: ../images/soldering/4.jpg
.. rst-class:: alt
+---------------------------------------+
| |fig4| |
+---------------------------------------+
| Image 4: Voltage Regulator Transistor |
+---------------------------------------+
The capacitor can best be solder with a little more slack so you can bend it in such manner that it will stay under the first header. Do not bend it too much because then it can interfere with the resistors needed for the pre-filter.
.. |fig5| image:: ../images/soldering/5.jpg
.. rst-class:: alt
+--------------------------------------+
| |fig5| |
+--------------------------------------+
| Image 5: Voltage Regulator Capacitor |
+--------------------------------------+
Finish the voltage regulator by soldering the resistor.
.. |fig6| image:: ../images/soldering/6.jpg
.. rst-class:: alt
+-------------------------------------+
| |fig6| |
+-------------------------------------+
| Image 6: Voltage Regulator Resistor |
+-------------------------------------+
PCB Quarter
-----------
.. _P1 Meter:
.. rubric:: P1 Meter
The P1 meter consists of two resistors, a transistor and a wire terminal. Take care in placing the resistors, because they are placed in between the resistors of the pre-filter. Also check if the terminal is not too high for mounting on your final device. For example the System on Module of the Hummingboard together with the P1 terminal make it too high for proper mounting. In this case, leave the terminal and just connect the wires directly to the PCB.
.. |fig7| image:: ../images/soldering/7.jpg
.. rst-class:: alt
+----------------------------------+
| |fig7| |
+----------------------------------+
| Image 7: P1 Meter First Resistor |
+----------------------------------+
.. |fig8| image:: ../images/soldering/8.jpg
.. rst-class:: alt
+-----------------------------------+
| |fig8| |
+-----------------------------------+
| Image 8: P1 Meter Second Resistor |
+-----------------------------------+
Place the transistor as shown on the PCB, with its flat side to the ATTiny.
.. |fig9| image:: ../images/soldering/9.jpg
.. rst-class:: alt
+------------------------------+
| |fig9| |
+------------------------------+
| Image 9: P1 Meter Transistor |
+------------------------------+
.. |fig10| image:: ../images/soldering/10.jpg
.. rst-class:: alt
+-----------------------------+
| |fig10| |
+-----------------------------+
| Image 10: P1 Meter Terminal |
+-----------------------------+
PCB Half
--------
.. _Pre-Filter:
.. rubric:: Pre-Filter
..
.. |fig11| image:: ../images/soldering/11.jpg
.. rst-class:: alt
+--------------------------------+
| |fig11| |
+--------------------------------+
| Image 11: Pre-Filter Resistors |
+--------------------------------+
When installing the socket, please remember where the dot and notch are placed. In the final ATTiny installation, the dot on the PCB and on the ATTiny should match.
.. |fig12| image:: ../images/soldering/12.jpg
.. rst-class:: alt
+-----------------------------+
| |fig12| |
+-----------------------------+
| Image 12: Pre-Filter Socket |
+-----------------------------+
PCB Full
--------
.. |fig13| image:: ../images/soldering/13.jpg
.. rst-class:: alt
+------------------------------+
| |fig13| |
+------------------------------+
| Image 13: PCB Final Top View |
+------------------------------+
.. |fig14| image:: ../images/soldering/14.jpg
.. rst-class:: alt
+---------------------------------+
| |fig14| |
+---------------------------------+
| Image 14: PCB Final Bottom View |
+---------------------------------+
@@ -0,0 +1,92 @@
Wiring
======
- `Introduction`_
- `ATTiny pre-filter`_
- `pilight USB nano`_
Introduction
------------
The wiring of the different pilight hardware solutions will be described here in the best possible way. Please refer to the Configuration – Hardware page to see how the hardware modules are configured on the software side.
ATTiny pre-filter
-----------------
.. only:: html
.. figure:: ../images/attiny-wiring.svg
:align: left
.. only: latex
.. image:: ../images/attiny-wiring.pdf
The ATTiny pre-filter is meant to filter the noise from 433.92Mhz receivers. Using a filter is not strictly necessary. However, it greatly reduces the CPU usage of your Raspberry Pi (and similar devices) so you can use it for more applications than just pilight.
Wiring the filter can be done it two steps. A required one, and an optional one. All optional wirings are made purple in the drawing. These wires are only used for firmware upgrades, which only happen rarely.
The different pins on the Raspberry Pi are numbered from bottom left (Pin 1) and top left (Pin 2) to bottom right (Pin 39) and top right (Pin 40).
The pins on the receiver (large rectangle) are numbered from left (Pin 1) to right (Pin 8).
The pins on the ATTiny are numbered from top left (Pin 1) to bottom left (Pin 4) and from bottom right (Pin 5) to top right (Pin 8).
The pins on the sender (small rectangle) are numbered from left (Pin 1) to right (Pin 4).
With this information, the following wiring scheme can be used for wiring up the ATTiny pre-filter together with the sender and receiver.
+--------------+------------------+-+------------+------------------+-+------------+------------------+
| **Receiver** | **ATTiny** | | **ATTiny** | **Raspberry Pi** | | **Sender** | **Raspberry Pi** |
+--------------+------------------+ +------------+------------------+-+------------+------------------+
| Pin 7 (Data) | Pin 3 | | Pin 1 | Pin 24 (CE0) | | Pin 1 | Pin 2 (5V) |
+--------------+------------------+ +------------+------------------+-+------------+------------------+
| **Receiver** | **Raspberry Pi** | | Pin 2 | Pin 12 (GPIO 1) | | Pin 2 | Pin 11 (GPIO 0) |
+--------------+------------------+ +------------+------------------+-+------------+------------------+
| Pin 5 (VDD) | Pin 2 (5V) | | Pin 4 | Pin 6 (GND) | | Pin 3 | Pin 3 (GND) |
+--------------+------------------+ +------------+------------------+-+------------+------------------+
| Pin 8 (GND) | Pin 6 (GND) | | Pin 5 | Pin 19 (MOSI) | | |
+--------------+------------------+ +------------+------------------+-+------------+------------------+
| | | Pin 6 | Pin 21 (MISO) | | |
+--------------+------------------+ +------------+------------------+-+------------+------------------+
| | | Pin 7 | Pin 23 (SCLK) | | |
+---------------------------------+-+------------+------------------+-+------------+------------------+
pilight USB nano
----------------
.. only:: html
.. figure:: ../images/usb-nano-wiring.svg
:align: left
.. only: latex
.. image:: ../images/usb-nano-wiring.pdf
The pilight USB nano allows users to use pilight on any computer with USB support. The wiring scheme of the sender and receiver with the Arduino Nano is shown in the drawing. The Arduino Nano should be connected to the final computer over USB.
The pins on the Arduino Nano are as follow:
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| VIN | GND | RST | 5V | A7 | A6 | A5 | A4 | A3 | A1 | A2 | A0 | REF | 3V3 | D13 | |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ USB +
| TX1 | RX0 | RST | GND | D2 | D3 | D4 | D5 | D6 | D7 | D8 | D9 | D10 | D11 | D12 | |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
The pins on the receiver are numbered from left (Pin 1) to right (Pin 8).
The pins on the sender are numbered from left (Pin 1) to right (Pin 4).
With all this information, the following wiring scheme can be used for wiring up the pilight USB nano together with the sender and receiver.
+--------------+----------+-+--------------+----------+
| **Receiver** | **Nano** | | **Sender** | **Nano** |
+--------------+----------+ +--------------+----------+
| Pin 1 (VDD) | 5V | | Pin 1 (GND) | GND |
+--------------+----------+ +--------------+----------+
| Pin 7 (Data) | D2 | | Pin 2 (Data) | D5 |
+--------------+----------+ +--------------+----------+
| Pin 8 (GND) | GND | | Pin 3 (VDD) | 5V |
+--------------+----------+-+--------------+----------+
@@ -0,0 +1,76 @@
.. |yes| image:: ../../images/yes.png
.. |no| image:: ../../images/no.png
.. role:: underline
:class: underline
Dim
===
.. rubric:: Description
Dims a device to a dimlevel or starts a sequence from one dimlevel to another.
.. rubric:: Options
+----------+------------------+---------------------+-------------------------------------------------------+
| **Name** | **Required** | **Multiple Values** | **Description** |
+----------+------------------+---------------------+-------------------------------------------------------+
| DEVICE | |yes| | |yes| | Device(s) to change |
+----------+------------------+---------------------+-------------------------------------------------------+
| TO | |yes| | |no| | New dimlevel |
+----------+------------------+---------------------+-------------------------------------------------------+
.. versionadded:: 7.0
+----------+------------------+---------------------+-------------------------------------------------------+
| **Name** | **Required** | **Multiple Values** | **Description** |
+----------+------------------+---------------------+-------------------------------------------------------+
| FOR | |no| | |no| | | Determine how long this new state lasts before |
| | | | | we change back to the previous dimlevel and state |
+----------+------------------+---------------------+-------------------------------------------------------+
| AFTER | |no| | |no| | After how long do we want the new state to be set |
+----------+------------------+---------------------+-------------------------------------------------------+
| IN | |no| | |no| | | To be combined with FROM. In what time do we want |
| | | | | to change the dimlevel FROM x TO y |
+----------+------------------+---------------------+-------------------------------------------------------+
| FROM | |no| | |no| | | To be combined with IN. From what dimlevel do we |
| | | | | want to start a sequence to the target dimlevel |
+----------+------------------+---------------------+-------------------------------------------------------+
.. note:: Units for ``FOR``, ``AFTER``, and ``IN``
- MILLISECOND
- SECOND
- MINUTE
- HOUR
- DAY
.. rubric:: Examples
.. code-block:: console
IF 1 == 1 THEN dim DEVICE mainlight TO 15
IF 1 == 1 THEN dim DEVICE mainlight AND bookshelve AND hall TO 10
.. versionadded:: 7.0
.. code-block:: console
IF 1 == 1 THEN dim DEVICE mainlight TO 15 FOR 10 MINUTE
IF 1 == 1 THEN dim DEVICE mainlight TO 15 AFTER 30 SECOND
IF 1 == 1 THEN dim DEVICE mainlight TO 15 AFTER 30 SECOND FOR 10 MINUTE
IF 1 == 1 THEN dim DEVICE mainlight TO 15 FROM 0 IN 45 MINUTE
IF 1 == 1 THEN dim DEVICE mainlight TO 15 FROM 0 IN 45 MINUTE FOR 15 MINUTE AFTER 5 MINUTE
IF 1 == 1 THEN switch DEVICE light TO off FOR 10 SECOND AFTER 30 MINUTE
.. versionchanged:: 8.1.0
.. code-block:: console
IF 1 == 1 THEN dim DEVICE mainlight TO 15 FOR '10 MINUTE'
IF 1 == 1 THEN dim DEVICE mainlight TO 15 AFTER '30 SECOND'
IF 1 == 1 THEN dim DEVICE mainlight TO 15 AFTER '30 SECOND' FOR '10 MINUTE'
IF 1 == 1 THEN dim DEVICE mainlight TO 15 FROM 0 IN '45 MINUTE'
IF 1 == 1 THEN dim DEVICE mainlight TO 15 FROM 0 IN '45 MINUTE' FOR '15 MINUTE' AFTER '5 MINUTE'
IF 1 == 1 THEN switch DEVICE light TO off FOR '10 SECOND' AFTER '30 MINUTE'
@@ -0,0 +1,21 @@
Actions
=======
.. versionadded:: 6.0
.. toctree::
:maxdepth: 1
dim
pushover
switch
toggle
.. versionadded:: 7.0
.. toctree::
:maxdepth: 1
label
pushbullet
sendmail
@@ -0,0 +1,59 @@
.. |yes| image:: ../../images/yes.png
.. |no| image:: ../../images/no.png
.. role:: underline
:class: underline
Label
=====
.. rubric:: Description
Changes the text and color of a generic label device.
.. rubric:: Options
+----------+------------------+---------------------+---------------------------------------------------+
| **Name** | **Required** | **Multiple Values** | **Description** |
+----------+------------------+---------------------+---------------------------------------------------+
| DEVICE | |yes| | |yes| | Device(s) to change |
+----------+------------------+---------------------+---------------------------------------------------+
| TO | |yes| | |no| | New text |
+----------+------------------+---------------------+---------------------------------------------------+
| COLOR | |no| | |no| | New color. If omitted, color is set to black |
+----------+------------------+---------------------+---------------------------------------------------+
| **Name** | **Required** | **Multiple Values** | **Description** |
+----------+------------------+---------------------+---------------------------------------------------+
| FOR | |no| | |no| | | Determine how long this new label lasts |
| | | | | before we change back to the previous label |
+----------+------------------+---------------------+---------------------------------------------------+
| AFTER | |no| | |no| | After how long do we want the new label to be set |
+----------+------------------+---------------------+---------------------------------------------------+
.. note:: Units for ``FOR`` and ``AFTER``
- MILLISECOND
- SECOND
- MINUTE
- HOUR
- DAY
.. rubric:: Examples
.. code-block:: console
IF 1 == 1 THEN label DEVICE tempLabel TO on
IF 1 == 1 THEN label DEVICE tempLabel AND humiLabel TO No information
IF 1 == 1 THEN label DEVICE tempLabel TO 23.5 FOR 10 SECOND
IF 1 == 1 THEN label DEVICE tempLabel TO Bell rang AFTER 30 SECOND
IF 1 == 1 THEN label DEVICE tempLabel TO None FOR 10 MINUTE AFTER 30 SECOND
.. versionchanged:: 8.1.0.
.. code-block:: console
IF 1 == 1 THEN label DEVICE tempLabel TO on
IF 1 == 1 THEN label DEVICE tempLabel AND humiLabel TO 'No information'
IF 1 == 1 THEN label DEVICE tempLabel TO 23.5 FOR '10 SECOND'
IF 1 == 1 THEN label DEVICE tempLabel TO 'Bell rang' AFTER '30 SECOND'
IF 1 == 1 THEN label DEVICE tempLabel TO None FOR '10 MINUTE' AFTER '30 SECOND'
@@ -0,0 +1,38 @@
.. |yes| image:: ../../images/yes.png
.. |no| image:: ../../images/no.png
.. role:: underline
:class: underline
Pushbullet
==========
.. rubric:: Description
Send a message to your mobile phone with the pushbullet API
.. rubric:: Options
+----------+------------------+---------------------+---------------------------------------------------+
| **Name** | **Required** | **Multiple Values** | **Description** |
+----------+------------------+---------------------+---------------------------------------------------+
| TITLE | |yes| | |no| | |
+----------+------------------+---------------------+---------------------------------------------------+
| BODY | |yes| | |no| | |
+----------+------------------+---------------------+---------------------------------------------------+
| TOKEN | |yes| | |no| | Unique pushbullet user account token |
+----------+------------------+---------------------+---------------------------------------------------+
| TYPE | |yes| | |no| | Message type |
+----------+------------------+---------------------+---------------------------------------------------+
.. rubric:: Example
.. code-block:: console
IF 1 == 1 THEN pushbullet TITLE Doorbell rang BODY Doorbell rang TOKEN abcd123abc TYPE note
.. versionchanged:: 8.1.0
.. code-block:: console
IF 1 == 1 THEN pushbullet TITLE 'Doorbell rang' BODY 'Doorbell rang' TOKEN abcd123abc TYPE note
@@ -0,0 +1,38 @@
.. |yes| image:: ../../images/yes.png
.. |no| image:: ../../images/no.png
.. role:: underline
:class: underline
Pushover
========
.. rubric:: Description
Send a message to your mobile phone with the pushover API
.. rubric:: Options
+----------+------------------+---------------------+---------------------------------------------------+
| **Name** | **Required** | **Multiple Values** | **Description** |
+----------+------------------+---------------------+---------------------------------------------------+
| TITLE | |yes| | |no| | |
+----------+------------------+---------------------+---------------------------------------------------+
| MESSAGE | |yes| | |no| | |
+----------+------------------+---------------------+---------------------------------------------------+
| TOKEN | |yes| | |no| | Unique pushover user account token |
+----------+------------------+---------------------+---------------------------------------------------+
| USER | |yes| | |no| | Unique pushover username |
+----------+------------------+---------------------+---------------------------------------------------+
.. rubric:: Example
.. code-block:: console
IF 1 == 1 THEN pushover TITLE Doorbell rang MESSAGE Doorbell rang TOKEN abcd123abc USER pilight
.. versionchanged:: 8.1.0
.. code-block:: console
IF 1 == 1 THEN pushover TITLE 'Doorbell rang' MESSAGE 'Doorbell rang' TOKEN abcd123abc USER pilight
@@ -0,0 +1,52 @@
.. |yes| image:: ../../images/yes.png
.. |no| image:: ../../images/no.png
.. role:: underline
:class: underline
Sendmail
========
.. rubric:: Description
Send a message to any e-mail address
.. rubric:: Options
+----------+------------------+---------------------+---------------------------------------------------+
| **Name** | **Required** | **Multiple Values** | **Description** |
+----------+------------------+---------------------+---------------------------------------------------+
| TO | |yes| | |no| | |
+----------+------------------+---------------------+---------------------------------------------------+
| SUBJECT | |yes| | |no| | |
+----------+------------------+---------------------+---------------------------------------------------+
| MESSAGE | |yes| | |no| | |
+----------+------------------+---------------------+---------------------------------------------------+
.. note::
The ``sendmail`` action requires some additional settings in the pilight configuration:
.. code-block:: json
{
"settings": {
"smtp-sender": "sender@domain.com",
"smtp-host": "smtp.smtphost.com",
"smtp-port": 465,
"smtp-user": "smtpuser@domain.com",
"smtp-password": "password"
}
}
.. rubric:: Examples
.. code-block:: console
IF 1 == 1 THEN sendmail SUBJECT Doorbell rang MESSAGE Doorbell rang TO someone@somewhere.com
.. versionchanged:: 8.1.0
.. code-block:: console
IF 1 == 1 THEN sendmail SUBJECT 'Doorbell rang' MESSAGE 'Doorbell rang' TO someone@somewhere.com
@@ -0,0 +1,64 @@
.. |yes| image:: ../../images/yes.png
.. |no| image:: ../../images/no.png
.. role:: underline
:class: underline
Switch
======
.. rubric:: Description
Changes the state of a switch, relay or dimmer.
.. rubric:: Options
+----------+------------------+---------------------+---------------------------------------------------+
| **Name** | **Required** | **Multiple Values** | **Description** |
+----------+------------------+---------------------+---------------------------------------------------+
| DEVICE | |yes| | |yes| | Device(s) to change |
+----------+------------------+---------------------+---------------------------------------------------+
| TO | |yes| | |no| | New state |
+----------+------------------+---------------------+---------------------------------------------------+
.. versionadded:: 7.0
+----------+------------------+---------------------+---------------------------------------------------+
| **Name** | **Required** | **Multiple Values** | **Description** |
+----------+------------------+---------------------+---------------------------------------------------+
| FOR | |no| | |no| | | Determine how long this new state lasts |
| | | | | before we change back to the previous state |
+----------+------------------+---------------------+---------------------------------------------------+
| AFTER | |no| | |no| | After how long do we want the new state to be set |
+----------+------------------+---------------------+---------------------------------------------------+
.. note:: Units for ``FOR`` and ``AFTER``
- MILLISECOND
- SECOND
- MINUTE
- HOUR
- DAY
.. rubric:: Examples
.. code-block:: console
IF 1 == 1 THEN switch DEVICE light TO on
IF 1 == 1 THEN switch DEVICE mainlight AND bookshelve AND hall TO on
.. versionadded:: 7.0
.. code-block:: console
IF 1 == 1 THEN switch DEVICE light TO on FOR 10 MINUTE
IF 1 == 1 THEN switch DEVICE light TO on AFTER 30 MILLISECOND
IF 1 == 1 THEN switch DEVICE light TO off FOR 10 SECOND AFTER 30 MINUTE
.. versionchanged:: 8.1.0
.. code-block:: console
IF 1 == 1 THEN switch DEVICE light TO on FOR '10 MINUTE'
IF 1 == 1 THEN switch DEVICE light TO on AFTER '30 MILLISECOND'
IF 1 == 1 THEN switch DEVICE light TO off FOR '10 SECOND' AFTER '30 MINUTE'
@@ -0,0 +1,30 @@
.. |yes| image:: ../../images/yes.png
.. |no| image:: ../../images/no.png
.. role:: underline
:class: underline
Toggle
======
.. rubric:: Description
Toggles a device between state X and state Y. This action is especially made for ``one-shot`` devices such as a remote control button where a normal separate 'switch-on' and separate 'switch-off' rule doesn't apply. This action will check what the current state of a device is, and will change it to the non-current state.
.. rubric:: Options
+----------+------------------+---------------------+---------------------------------------------------+
| **Name** | **Required** | **Multiple Values** | **Description** |
+----------+------------------+---------------------+---------------------------------------------------+
| DEVICE | |yes| | |yes| | Device(s) to change |
+----------+------------------+---------------------+---------------------------------------------------+
| BETWEEN | |yes| | |no| | State 1 |
+----------+------------------+---------------------+---------------------------------------------------+
| AND | |no| | |no| | State 2 |
+----------+------------------+---------------------+---------------------------------------------------+
.. rubric:: Example
.. code-block:: console
IF 1 == 1 THEN toggle DEVICE television BETWEEN on AND off
@@ -0,0 +1,12 @@
Examples
========
.. toctree::
:maxdepth: 1
ir
kodi
mail
mail1
sunriseset
time
@@ -0,0 +1,62 @@
.. |yes| image:: ../../images/yes.png
.. |no| image:: ../../images/no.png
.. role:: underline
:class: underline
IR Remote
=========
.. rubric:: Description
Switch devices based on your IR remote buttons
.. rubric:: Devices
.. code-block:: json
:linenos:
{
"devices": {
"television": {
"protocol": [ "kaku_switch" ],
"id": [{
"id": 123456,
"unit": 0
}],
"state": "off"
},
"remote": {
"protocol": [ "lirc" ],
"id": [{
"remote": "logitech"
}],
"code": "000000000000e290",
"repeat": 2,
"button": "KEY_P"
}
}
.. rubric:: Rule
.. code-block:: json
:linenos:
{
"remote-television-switch": {
"rule": "IF remote.button IS KEY_P AND remote.repeat == 0 THEN toggle DEVICE television BETWEEN on AND off",
"active": 1
}
}
.. versionchanged:: 8.1.0
.. code-block:: json
:linenos:
{
"remote-television-switch": {
"rule": "IF remote.button == KEY_P AND remote.repeat == 0 THEN toggle DEVICE television BETWEEN on AND off",
"active": 1
}
}
@@ -0,0 +1,69 @@
.. |yes| image:: ../../images/yes.png
.. |no| image:: ../../images/no.png
.. role:: underline
:class: underline
XBMC / Kodi
===========
.. rubric:: Description
Execute rules based on XBMC / KODI based events
.. rubric:: Devices
.. code-block:: json
:linenos:
{
"xbmcControls": {
"protocol": [ "xbmc" ],
"id": [{
"server": "127.0.0.1",
"port": 9090
}],
"action": "home",
"media": "none"
},
"speakers": {
"protocol": [ "kaku_switch" ],
"id": [{
"id": 123456,
"unit": 4
}],
"state": "off"
}
}
.. rubric:: Rule
.. code-block:: json
:linenos:
{
"speakers-on": {
"rule": "IF xbmcControls.action IS play THEN switch DEVICE speakers TO on",
"active": 1
},
"speakers-off": {
"rule": "IF xbmcControls.action IS pause OR xbmcControls.action IS home THEN switch DEVICE speakers TO off AFTER 3 MINUTES",
"active": 1
}
}
.. versionchanged:: 8.1.0
.. code-block:: json
:linenos:
{
"speakers-on": {
"rule": "IF xbmcControls.action == play THEN switch DEVICE speakers TO on",
"active": 1
},
"speakers-off": {
"rule": "IF xbmcControls.action == pause OR xbmcControls.action == home THEN switch DEVICE speakers TO off AFTER '3 MINUTES'",
"active": 1
}
}
@@ -0,0 +1,67 @@
.. |yes| image:: ../../images/yes.png
.. |no| image:: ../../images/no.png
.. role:: underline
:class: underline
Mail on contact trigger
=======================
.. rubric:: Description
Sending a mail based on a contact device trigger including the time when it happened.
.. rubric:: Devices
.. code-block:: json
:linenos:
{
"currentdatetime": {
"protocol": [ "datetime" ],
"id": [{
"longitude": 1.2345,
"latitude": 12.3456
}],
"year": 2015,
"month": 1,
"day": 27,
"hour": 14,
"minute": 37,
"second": 8,
"weekday": 3,
"dst": 1
},
"frontdoor-contact": {
"protocol": [ "kaku_contact" ],
"id": [{
"id": 123456,
"unit": 0
}],
"state": "opened"
}
}
.. rubric:: Rule
.. code-block:: json
:linenos:
{
"frontdoor-contact-mail": {
"rule": "IF frontdoor-contact.state IS opened THEN sendmail TO foo@bar.com SUBJECT Frontdoor was opened at DATE_FORMAT(currentdatetime, %c) MESSAGE .",
"active": 1
}
}
.. versionchanged:: 8.1.0
.. code-block:: json
:linenos:
{
"frontdoor-contact-mail": {
"rule": "IF frontdoor-contact.state == opened THEN sendmail TO foo@bar.com SUBJECT 'Frontdoor was opened at ' . DATE_FORMAT(currentdatetime, %c) MESSAGE ..",
"active": 1
}
}
@@ -0,0 +1,67 @@
.. |yes| image:: ../../images/yes.png
.. |no| image:: ../../images/no.png
.. role:: underline
:class: underline
Mail on computer disconnection
==============================
.. rubric:: Description
Send a mail when one of the computer goes offline.
.. rubric:: Devices
.. code-block:: json
:linenos:
{
"currentdatetime": {
"protocol": [ "datetime" ],
"id": [{
"longitude": 1.2345,
"latitude": 12.3456
}],
"year": 2015,
"month": 1,
"day": 27,
"hour": 14,
"minute": 37,
"second": 8,
"weekday": 3,
"dst": 1
},
"nasPing": {
"protocol": [ "arping" ],
"id": [{
"mac": "aa:bb:cc:dd:00:11"
}],
"ip": "192.168.1.1",
"state": "connected"
}
}
.. rubric:: Rule
.. code-block:: json
:linenos:
{
"nas-mail": {
"rule": "IF nasPing.state IS disconnected THEN sendmail TO foo@bar.com SUBJECT NAS is offline since DATE_FORMAT(currentdatetime, %c) MESSAGE .",
"active": 1
}
}
.. versionchanged:: 8.1.0
.. code-block:: json
:linenos:
{
"nas-mail": {
"rule": "IF nasPing.state IS disconnected THEN sendmail TO foo@bar.com SUBJECT 'NAS is offline since ' . DATE_FORMAT(currentdatetime, %c) MESSAGE ..",
"active": 1
}
}
@@ -0,0 +1,147 @@
.. |yes| image:: ../../images/yes.png
.. |no| image:: ../../images/no.png
.. role:: underline
:class: underline
Sunrise / Sunset Event
======================
.. rubric:: Description
This rule executes when the sun sets or rises.
.. rubric:: Devices
.. code-block:: json
:linenos:
{
"devices": {
"currentdatetime": {
"protocol": [ "datetime" ],
"id": [{
"longitude": 1.2345,
"latitude": 12.3456
}],
"year": 2015,
"month": 1,
"day": 27,
"hour": 14,
"minute": 37,
"second": 8,
"weekday": 3,
"dst": 1
},
"sunrisesetdevice": {
"protocol": [ "sunriseset" ],
"id": [{
"longitude": 1.234567,
"latitude": 12.123456
}],
"sunrise": 6.40,
"sunset": 18.50,
"sun": "rise"
},
"light": {
"protocol": [ "kaku_switch" ],
"id": [{
"id": 123456,
"unit": 0
}],
"state": "off"
}
}
}
.. rubric:: Rule
By using math
.. code-block:: json
:linenos:
{
"sunset": {
"rule": "IF ((sunrisesetdevice.sunset == (currentdatetime.hour + (currentdatetime.minute / 100)) AND light.state IS off) AND currentdatetime.second == 0) THEN switch DEVICE light TO on",
"active": 1
},
"sunrise": {
"rule": "IF ((sunrisesetdevice.sunrise == (currentdatetime.hour + (currentdatetime.minute / 100)) AND light.state IS off) AND currentdatetime.second == 0) THEN switch DEVICE light TO on",
"active": 1
}
}
By using the DATE_FORMAT function
.. code-block:: json
:linenos:
{
"sunset": {
"rule": "IF (sunrisesetdevice.sunset == DATE_FORMAT(currentdatetime, %H.%M)) AND light.state IS off AND currentdatetime.second == 0 THEN switch DEVICE light TO on",
"active": 1
},
"sunrise": {
"rule": "IF (sunrisesetdevice.sunrise == DATE_FORMAT(currentdatetime, %H.%M)) AND light.state IS off AND currentdatetime.second == 0 THEN switch DEVICE light TO on",
"active": 1
}
}
Or an hour before the sun sets:
.. code-block:: json
:linenos:
{
"sunset": {
"rule": "IF (sunrisesetdevice.sunset == DATE_FORMAT(DATE_ADD(currentdatetime, +1 HOUR), \"%Y-%m-%d %H:%M:%S\", %H.%M)) AND light.state IS off AND currentdatetime.second == 0 THEN switch DEVICE light TO on",
"active": 1
}
}
.. versionchanged:: 8.1.0
By using math
.. code-block:: json
:linenos:
{
"sunset": {
"rule": "IF ((sunrisesetdevice.sunset == (currentdatetime.hour + (currentdatetime.minute / 100)) AND light.state == off) AND currentdatetime.second == 0) THEN switch DEVICE light TO on",
"active": 1
},
"sunrise": {
"rule": "IF ((sunrisesetdevice.sunrise == (currentdatetime.hour + (currentdatetime.minute / 100)) AND light.state == off) AND currentdatetime.second == 0) THEN switch DEVICE light TO on",
"active": 1
}
}
By using the DATE_FORMAT function
.. code-block:: json
:linenos:
{
"sunset": {
"rule": "IF (sunrisesetdevice.sunset == DATE_FORMAT(currentdatetime, %H.%M)) AND light.state == off AND currentdatetime.second == 0 THEN switch DEVICE light TO on",
"active": 1
},
"sunrise": {
"rule": "IF (sunrisesetdevice.sunrise == DATE_FORMAT(currentdatetime, %H.%M)) AND light.state == off AND currentdatetime.second == 0 THEN switch DEVICE light TO on",
"active": 1
}
}
Or an hour before the sun sets:
.. code-block:: json
:linenos:
{
"sunset": {
"rule": "IF (sunrisesetdevice.sunset == DATE_FORMAT(DATE_ADD(currentdatetime, '+1 HOUR'), '%Y-%m-%d %H:%M:%S', %H.%M)) AND light.state == off AND currentdatetime.second == 0 THEN switch DEVICE light TO on",
"active": 1
}
}
@@ -0,0 +1,67 @@
.. |yes| image:: ../../images/yes.png
.. |no| image:: ../../images/no.png
.. role:: underline
:class: underline
Time based
==========
.. rubric:: Description
Trigger events based on time
.. rubric:: Devices
.. code-block:: json
:linenos:
{
"currentdatetime": {
"protocol": [ "datetime" ],
"id": [{
"longitude": 1.2345,
"latitude": 12.3456
}],
"year": 2015,
"month": 1,
"day": 27,
"hour": 14,
"minute": 37,
"second": 8,
"weekday": 3,
"dst": 1
},
"outsidelight": {
"protocol": [ "kaku_switch" ],
"id": [{
"id": 123456,
"unit": 0
}],
"state": "off"
}
}
.. rubric:: Rule
.. code-block:: json
:linenos:
{
"christmass-tree-off": {
"rule": "IF DATE_FORMAT(currentdatetime, %H.%M%S) == 23.0000 THEN switch DEVICE outsidelight TO on AFTER RANDOM(0, 90) MINUTE FOR RANDOM(5, 15) MINUTE",
"active": 1
}
}
.. versionchanged:: 8.1.0
.. code-block:: json
:linenos:
{
"christmass-tree-off": {
"rule": "IF DATE_FORMAT(currentdatetime, %H.%M%S) == 23.0000 THEN switch DEVICE outsidelight TO on AFTER RANDOM(0, 90) . ' MINUTE' FOR RANDOM(5, 15) . ' MINUTE'",
"active": 1
}
}
@@ -0,0 +1,56 @@
.. |yes| image:: ../../images/yes.png
.. |no| image:: ../../images/no.png
.. role:: underline
:class: underline
date_add
========
.. rubric:: Description
Calculations with date and time values.
.. rubric:: Arguments
+----------+------------------+------------------------------------------+
| **#** | **Required** | **Description** |
+----------+------------------+------------------------------------------+
| 1 | |yes| | | A datetime device or a datetime string |
| | | | The datetime string must be in the |
| | | | format YYYY-MM-DD HH:MM:SS. |
+----------+------------------+------------------------------------------+
| 2 | |yes| | | A number and unit. The number can be |
| | | | either positive or negative. |
| | | | The unit can be |
| | | | - SECOND |
| | | | - MINUTE |
| | | | - HOUR |
| | | | - DAY |
| | | | - MONTH |
| | | | - YEAR |
+----------+------------------+------------------------------------------+
.. rubric:: Return value
The returned datetime string is always in the format ``%Y-%m-%d %H:%M:%S``. So in case of the third example, the output will be ``"2016-01-01 00:00:00"``.
.. rubric:: Examples
.. code-block:: console
IF DATE_ADD(datetime, +1 HOUR) == ...
IF DATE_ADD(datetime, -1 DAY) == ...
IF DATE_ADD(2015-12-31, 23:59:59, +1 SECOND) == ...
IF DATE_ADD(datetime, RANDOM(-3, +3) DAY) == ...
IF DATE_FORMAT(DATE_ADD(2015-01-01 21:00:00, RANDOM(0, 120) MINUTE), \"%Y-%m-%d %H:%M:%S\", %H.%M) == ...
.. versionchanged:: 8.1.0
.. code-block:: console
IF DATE_ADD(datetime, '+1 HOUR') == ...
IF DATE_ADD(datetime, '-1 DAY') == ...
IF DATE_ADD('2015-12-31, 23:59:59', '+1 SECOND') == ...
IF DATE_ADD(datetime, RANDOM(-3, +3) . ' DAY') == ...
IF DATE_FORMAT(DATE_ADD('2015-01-01 21:00:00', RANDOM(0, 120) . ' MINUTE'), '%Y-%m-%d %H:%M:%S', %H.%M) == ...
@@ -0,0 +1,152 @@
.. |yes| image:: ../../images/yes.png
.. |no| image:: ../../images/no.png
.. role:: underline
:class: underline
date_format
===========
.. rubric:: Description
Reformat date and time values
.. rubric:: Arguments
+----------+------------------+------------------------------------------+
| **#** | **Required** | **Description** |
+----------+------------------+------------------------------------------+
| **Using two parameters** |
+----------+------------------+------------------------------------------+
| 1 | |yes| | A datetime device |
+----------+------------------+------------------------------------------+
| 2 | |yes| | Output format (see below) |
+----------+------------------+------------------------------------------+
| **Using three parameters** |
+----------+------------------+------------------------------------------+
| 1 | |yes| | A datetime string |
+----------+------------------+------------------------------------------+
| 2 | |yes| | Input format (see below) |
+----------+------------------+------------------------------------------+
| 3 | |yes| | Output format (see below) |
+----------+------------------+------------------------------------------+
.. note:: **Input / output**
Consider that the flexibility of the function depends on the input. If you input just ``%H:%M:%S``, the DATE_FORMAT can't output a format like this ``%Y-%m-%d``, because the function didn't receive any date information. It only received time information. So, DATE_FORMAT can't be used to exterpolate information that's not present.
.. rubric:: Return value
The function will output the exact format as requested in the last (second or third argument). There are a few things you must consider when working with the DATE_FORMAT function. The types of operators you can use with DATE_FORMAT depends on the output format requested. If you want to compare the output format ``%c`` you can only use the ``IS`` operator, because the final output will be interpreted as a string value. If you want to compare ``%H.%M``, you will need numeric operators like ``==``, ``>``, or ``<``, because the output will be evaluated as a number.
Also consider the usage of quotes. The flexibility in which DATE_FORMAT can format date and time values isn't always accepted by pilight. For example: ``DATE_FORMAT(datetime, %c)`` outputs ``Fri Apr 24 11:35:36 2015`` which pilight subsequently can't handle. If you want to output string like this, use quotes ``DATE_FORMAT(datetime, "%c")``, which will output as ``"Fri Apr 24 11:35:36 2015"``.
.. rubric:: Examples
.. code-block:: console
IF DATE_ADD(datetime, +1 HOUR) == ...
IF DATE_ADD(datetime, -1 DAY) == ...
IF DATE_ADD(2015-12-31, 23:59:59, +1 SECOND) == ...
IF DATE_ADD(datetime, RANDOM(-3, +3) DAY) == ...
IF DATE_FORMAT(DATE_ADD(2015-01-01 21:00:00, RANDOM(0, 120) MINUTE), \"%Y-%m-%d %H:%M:%S\", %H.%M) == ...
.. versionchanged:: 8.1.0
.. code-block:: console
IF DATE_ADD(datetime, '+1 HOUR') == ...
IF DATE_ADD(datetime, '-1 DAY') == ...
IF DATE_ADD(2015-12-31, 23:59:59, '+1 SECOND') == ...
IF DATE_ADD(datetime, RANDOM(-3, +3) . ' DAY') == ...
IF DATE_FORMAT(DATE_ADD('2015-01-01 21:00:00', RANDOM(0, 120) . ' MINUTE'), '%Y-%m-%d %H:%M:%S', %H.%M) == ...
.. note:: **DATE_ADD as an argument**
When you use DATE_ADD as the first argument, you should consider the return value of DATE_ADD, because that's what DATE_FORMAT will eventually receive. The output format of DATE_ADD is ``"%Y-%m-%d %H:%M:%S"``, so the input format for DATE_FORMAT should be the same.
.. rubric:: Formatting characters
+---------------+------------------------------------------------------------------------+--------------------------+
| **Specifier** | **Replaced by** | **Example** |
+---------------+------------------------------------------------------------------------+--------------------------+
| %a | Abbreviated weekday name [#f1]_ | Thu |
+---------------+------------------------------------------------------------------------+--------------------------+
| %A | Full weekday name [#f1]_ | Thursday |
+---------------+------------------------------------------------------------------------+--------------------------+
| %b %h | Abbreviated month name [#f1]_ | Aug |
+---------------+------------------------------------------------------------------------+--------------------------+
| %B | Full month name [#f1]_ | August |
+---------------+------------------------------------------------------------------------+--------------------------+
| %c | Date and time representation [#f1]_ | Thu Aug 23 14:55:02 2001 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %C | Year divided by 100 and truncated to integer (00-99) | 20 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %d | Day of the month, zero-padded (01-31) | 23 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %D | Short MM/DD/YY date, equivalent to %m/%d/%y | 08/23/01 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %e | Day of the month, space-padded (1-31) | 23 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %F | Short YYYY-MM-DD date, equivalent to %Y-%m-%d | 2001-08-23 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %g | Week-based year, last two digits (00-99) | 01 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %G | Week-based year | 2001 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %g | Week-based year | 2001 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %H | Hour in 24h format (00-23) | 14 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %I | Hour in 12h format (01-12) | 02 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %j | Day of the year (001-366) | 235 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %m | Month as a decimal number (01-12) | 08 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %M | Minute (00-59) | 55 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %n | New-line character ('\n') | |
+---------------+------------------------------------------------------------------------+--------------------------+
| %p | AM or PM designation | PM |
+---------------+------------------------------------------------------------------------+--------------------------+
| %r | 12-hour clock time [#f1]_ | 02:55:02 pm |
+---------------+------------------------------------------------------------------------+--------------------------+
| %R | 24-hour HH:MM time, equivalent to %H:%M | 14:55 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %S | Second (00-61) | 02 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %t | Horizontal-tab character ('\t') | |
+---------------+------------------------------------------------------------------------+--------------------------+
| %T | ISO 8601 time format (HH:MM:SS), equivalent to %H:%M:%S | 14:55:02 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %u | ISO 8601 weekday as number with Monday as 1 (1-7) | 4 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %U | Week number with the first Sunday as the first day of week one (00-53) | 33 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %V | ISO 8601 week number (01-53) | 34 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %w | Weekday as a decimal number with Sunday as 0 (0-6) | 4 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %W | Week number with the first Monday as the first day of week one (00-53) | 34 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %x | Date representation [#f1]_ | 08/23/01 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %X | Time representation [#f1]_ | 14:55:02 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %y | Year, last two digits (00-99) | 01 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %Y | Year | 2001 |
+---------------+------------------------------------------------------------------------+--------------------------+
| %z | | ISO 8601 offset from UTC in timezone (1 minute=1, 1 hour=100) | +100 |
| | | If timezone cannot be determined, no characters | |
+---------------+------------------------------------------------------------------------+--------------------------+
| %Z | | Timezone name or abbreviation [#f1]_ | CDT |
| | | If timezone cannot be determined, no characters | |
+---------------+------------------------------------------------------------------------+--------------------------+
| %% | A ``%`` sign | % |
+---------------+------------------------------------------------------------------------+--------------------------+
Copied from http://www.cplusplus.com/reference/ctime/strftime/
.. [#f1] These specifiers are locale-dependent.
@@ -0,0 +1,11 @@
Functions
=========
.. versionadded:: 7.0
.. toctree::
:maxdepth: 1
random
date_add
date_format
@@ -0,0 +1,34 @@
.. |yes| image:: ../../images/yes.png
.. |no| image:: ../../images/no.png
.. role:: underline
:class: underline
random
======
.. rubric:: Description
Generate a random number.
.. rubric:: Parameters
+----------+------------------+---------------------+
| **#** | **Required** | **Description** |
+----------+------------------+---------------------+
| 1 | |yes| | Lower boundary |
+----------+------------------+---------------------+
| 2 | |yes| | Higher boundary |
+----------+------------------+---------------------+
.. rubric:: Return value
A random number
.. rubric:: Examples
.. code-block:: console
IF RANDOM(0, 10) == 5 THEN ...
IF RANDOM(1, 100) == 10 THEN ...
IF RANDOM(randomLow.dimlevel, randomHigh.dimlevel) == 10 THEN ...
@@ -0,0 +1,11 @@
Eventing
========
.. toctree::
:maxdepth: 2
syntax
operators
actions/index
functions/index
examples/index
@@ -0,0 +1,106 @@
Operators
=========
.. rubric:: Arithmetic
+--------------+-------------------------------------------------+--------------------------+
| **Operator** | **Description** | **Example** |
+--------------+-------------------------------------------------+--------------------------+
| \+ | Adds two operands. | 10 + 20 = 30 |
+--------------+-------------------------------------------------+--------------------------+
| − | Subtracts second operand from the first. | 10 − 20 = -10 |
+--------------+-------------------------------------------------+--------------------------+
| \* | Multiplies both operands. | 10 * 20 = 200 |
+--------------+-------------------------------------------------+--------------------------+
| / | Divides numerator by de-numerator. | | 10 / 20 = 2 |
| | | | 10 / 3 = 3.333... |
+--------------+-------------------------------------------------+--------------------------+
| \\ [#f1]_ | Integer divides numerator by de-numerator. | 10 \\ 3 = 3 |
+--------------+-------------------------------------------------+--------------------------+
| % | Remainder after an integer division. | | 20 % 10 = 0 |
| | | | 11 % 3 = 2 |
+--------------+-------------------------------------------------+--------------------------+
.. [#f1] The backslash is also used as an ``escape`` character. So if you want to use the intdivide operator inside a rule you must write your rulses like this:
.. code-block:: json
{
"rules": {
"rule": "IF 3 \\ 2 = 1 THEN switch DEVICE light TO on",
"active": 1
}
}
.. rubric:: Relational
+--------------+-------------------------------------------------+--------------------------+
| **Operator** | **Description** | **Example** |
+--------------+-------------------------------------------------+--------------------------+
| == | | Checks if the first and second (nummeric) | | 20 == 10 = false |
| | | operand are equal. | | 10 == 10 = true |
+--------------+-------------------------------------------------+--------------------------+
| != | | Checks if the first and second (nummeric) | | 20 != 10 = true |
| | | operand are unequal. | | 10 != 10 = false |
+--------------+-------------------------------------------------+--------------------------+
| IS | | Checks if the first and second (character) | | a IS b = false |
| | | operand are equal. | | a IS a = true |
+--------------+-------------------------------------------------+--------------------------+
| >= | | Checks if the first operand is greater or | | 20 >= 10 = true |
| | | equal to the second operand. | | 10 >= 20 = false |
| | | | 10 >= 10 = true |
+--------------+-------------------------------------------------+--------------------------+
| > | | Checks if the first operand is greater than | | 20 > 10 = true |
| | | the second operand. | | 10 > 20 = false |
| | | | 10 > 10 = false |
+--------------+-------------------------------------------------+--------------------------+
| <= | | Checks if the first operand is smaller or | | 20 <= 10 = false |
| | | equal to the second operand. | | 10 <= 20 = true |
| | | | 10 <= 10 = true |
+--------------+-------------------------------------------------+--------------------------+
| < | | Checks if the first operand is smaller than | | 20 < 10 = false |
| | | the second operand. | | 10 < 20 = true |
| | | | 10 < 10 = false |
+--------------+-------------------------------------------------+--------------------------+
.. versionadded:: 8.0 ISNOT operator added
.. deprecated:: 8.1.0
+--------------+-------------------------------------------------+--------------------------+
| **Operator** | **Description** | **Example** |
+--------------+-------------------------------------------------+--------------------------+
| ISNOT | | Checks if the first and second (character) | | a ISNOT b = true |
| | | operand are equal. | | a ISNOT a = false |
+--------------+-------------------------------------------------+--------------------------+
.. rubric:: Logical
+--------------+-------------------------------------------------+--------------------------+
| **Operator** | **Description** | **Example** |
+--------------+-------------------------------------------------+--------------------------+
| AND | | Checks if the first and second operands are | | 1 AND 1 = true |
| | | true. | | 1 AND 0 = false |
| | | - values greater of smaller then 0 are true | | foo AND false = true |
| | | - strings equals to ``0`` are false | | true AND true = true |
| | | - strings other than ``0`` are true | | false AND false = true |
+--------------+-------------------------------------------------+--------------------------+
| OR | | Checks if the first or second operands are | | 0 OR 0 = false |
| | | true. | | 1 OR 0 = true |
| | | - values greater of smaller then 0 are true | | foo OR false = true |
| | | - strings equals to ``0`` are false | | true OR true = true |
| | | - strings other than ``0`` are true | | false OR false = true |
+--------------+-------------------------------------------------+--------------------------+
.. rubric:: Other
.. versionadded:: 8.1.0
+----------------+-------------------------------------------------+--------------------------+
| **Operator** | **Description** | **Example** |
+----------------+-------------------------------------------------+--------------------------+
| | . | Concatenates two strings | | a . b == 'ab' |
| | (single dot) | | | a . ' ' . b == 'a b' |
| | | | RANDOM(1, 2) . '34' |
+----------------+-------------------------------------------------+--------------------------+
@@ -0,0 +1,366 @@
.. role:: event-success
.. role:: event-fail
Syntax
======
- `Introduction`_
- `Rule Parsing`_
- `Basic Structure`_
- `True or False`_
- `AND and OR`_
- `Hooks`_
- `Operator`_
- `String and Concatenation`_
- `Devices`_
- `Functions`_
- `Actions`_
- `Using Device Parameters`_
Introduction
------------
The pilight eventing library allows you to automate your house by writing event rules. These rules tell pilight what should happen at a given time or at a given event. pilight event rules follow the regular mathematical conventions and because you can work with an infinite number of hooks, they can become highly complex but are also highly flexible.
As with everything inside pilight, the eventing library is also highly modular. This means that the operators, actions, and functions are external modules that can be easily extended. Developers and users do not have to touch the core of the eventing library to add additional features.
Rule Parsing
------------
There are few things that are useful to know before working with pilight event rules. When you better understand how pilight parses the rules, you can write really efficient and advanced rules.
.. _Basic Structure:
.. rubric:: Basic Structure
All rules basically consist of the same structure:
.. code-block:: guess
IF ... THEN ...
A rule always start with the IF, followed by the rule logic, and is closed by a THEN. All actions are put after the THEN.
.. versionadded:: 8.1.0
The IF / THEN logic can be expanded by an ELSE. The actions written after the ELSE will be executed if the logic contained in the first if block is false.
.. code-block:: guess
IF ... THEN ... ELSE ...
Or you can nest an infinite number of IF/ELSE conditions by using adding the END keyword
.. code-block:: guess
IF ... THEN IF ... THEN ... ELSE ... END ELSE IF ... THEN ... ELSE ... END END
.. _True or False:
.. rubric:: True or False
Let us start with how pilight handles succeeding or failing conditions. pilight converts each logical mathematical and logical step into a true or false. The final condition must be true before triggering an action. If the final result is false, the action is skipped. These two examples will both succeed:
:event-success:`Succeeds`
.. code-block:: guess
IF (1 == 1) == True THEN
:event-success:`Succeeds`
.. code-block:: guess
IF (1 == 1) != False THEN
These two examples will both fail:
:event-fail:`Fails`
.. code-block:: guess
IF (1 == 0) IS True THEN
:event-fail:`Fails`
.. code-block:: guess
IF (1 != 1) IS False THEN
.. _AND and OR:
.. rubric:: AND and OR
In the first examples we only used one condition but this does not allow us to make very advanced and flexible rules. Therefore we need to be able to combine several conditions in a single rule. This is possible by combining them with AND and OR operators. Let us take a look at some basic examples:
:event-fail:`Fails`
.. code-block:: guess
IF 1 == 1 AND 1 == 2 THEN ...
:event-success:`Succeeds`
.. code-block:: guess
IF 1 == 1 OR 1 == 2 THEN ...
:event-fail:`Fails`
.. code-block:: guess
IF 1 == 2 OR 1 == 1 AND 2 == 3 THEN ...
:event-success:`Succeeds`
.. code-block:: guess
IF 1 == 1 OR 1 == 1 AND 2 == 3 THEN ...
:event-fail:`Fails`
.. code-block:: guess
IF 1 == 2 AND 1 == 1 OR 2 == 3 THEN ...
:event-success:`Succeeds`
.. code-block:: guess
IF 1 == 1 AND 2 == 2 OR 2 == 3 THEN ...
In the first two examples only a single AND and OR operator is used. In the rest of the examples we see multiple AND and OR operators. pilight follows standard operator associativity rules in parsing AND and OR operators.
.. _Hooks:
.. rubric:: Hooks
As we saw in our first examples, hooks can be used inside pilight rules. This can be useful to better structure and combine the various conditions of our rules. Let us create even more complex rules and see how hooks can change the outcome of a rule without changing the conditions.
:event-success:`Succeeds`
.. code-block:: guess
IF 1 == 2 OR 2 == 3 AND 2 == 3 OR 1 == 1 THEN ...
:event-fail:`Fails`
.. code-block:: guess
IF (1 == 2 OR 2 == 3) AND (2 == 3 OR 1 == 1) THEN ...
Operator
--------
Various mathematical operators can be used to do calculations inside our rules. A list of these operators can be found further on in this manual. pilight follows standard operator associativity rules in parsing mathematical operators. Let us just show some basic self-explanatory examples:
:event-success:`Succeeds`
.. code-block:: guess
IF 1 + 1 == 2 THEN ...
:event-success:`Succeeds`
.. code-block:: guess
IF 2 % 2 == 0 THEN ...
:event-success:`Succeeds`
.. code-block:: guess
IF 1 < 10 THEN ...
:event-fail:`Fails`
.. code-block:: guess
IF 10 / 2 == 4 THEN ...
String and Concatenation
------------------------
.. versionadded:: 8.1.0
pilight parses individual components inside a rule by looking at queues like spaces, comma's, hooks, and preserved words (e.g. actions or functions). In any case, pilight can be forces to parse any of these components as strings by enclosing them into quotes.
:event-success:`Succeeds`
.. code-block:: guess
IF 1 + 1 == 3 - 1 THEN ...
In this case, pilight will compare the outcome of both formulas (which is 2) with each other for further parsing. We can also tell pilight to compare the same formula but now with strings:
:event-fail:`Fails`
.. code-block:: guess
IF '1 + 1' == '3 - 1' THEN ...
The same formula parsed with two strings will now fail because both strings are not equal anymore.
It is important to understand how to enforce string parsing when working with functions. The following example with give a syntax error, because the DATE_ADD function only expects two arguments delimited by a comma when the first argument is a datetime device. However, pilight sees the ``+1`` and ``HOUR`` as two separate string that normally should be delimited by a comma. Would be add that comma, we would still call the DATE_ADD function with the wrong parameter count.
.. code-block:: guess
IF DATE_ADD(datetime, +1 HOUR) == ...
The rule above should be written like this instead so the ``+1`` and ``HOUR`` are parsed like ``+1 HOUR``.
.. code-block:: guess
IF DATE_ADD(datetime, '+1 HOUR') == ...
Another issue arises when strings and device values or functions need to be combined like in this example:
.. code-block:: guess
IF ... THEN label DEVICE alarm TO the alarm was trigger at DATE_FORMAT(datetime, %Y-%m-%d)
This rule will trigger a syntax error because the TO argument only expects one string, but five strings and a function were given. To make this into one string we need to use quotes and the concatenate ``.`` operator:
.. code-block:: guess
IF ... THEN label DEVICE alarm TO 'the alarm was trigger at' . DATE_FORMAT(datetime, %Y-%m-%d)
Another scenario in which we want to explicitly cast a keyword into a string is given in this example:
.. code-block:: guess
IF ... THEN label DEVICE label TO on
The ``label`` device is parsed by pilight as the label action because it's a reserved keyword. pilight does allow using label as a device name when casting it as a string like this:
.. code-block:: guess
IF ... THEN label DEVICE 'label' TO on
As shown above, keywords or operators can be parsed into strings so pilight will ignore their default meaning.
Devices
-------
pilight rules are quite useless if we cannot work with live data. This live data comes from our devices in and around the house. So let us say we have a switch called switch and we use this configured device to create a rule like this:
.. code-block:: guess
IF switch.state IS on THEN ...
Depending on the actual state of the switch this rule will succeed or fail. Let us now use a dimmer device called *dimmer*.
.. code-block:: guess
IF dimmer.dimlevel > 10 THEN ...
Again, this rule will succeed or fail depending on the actual dimlevel of the configured dimmer device. These two examples can of course be combined:
.. code-block:: guess
IF switch.state IS on AND dimmer.dimlevel > 10 THEN ...
As you can also see, the fields (*state* or *dimlevel*) we can use depends on the device we are using inside our rules. A switch does not have a *dimlevel* field but a dimmer does have a *state* field.
.. versionadded:: 8.0 rules based on received codes
Some devices are only used inside rules. Configuring them as explicit devices might sometimes feel a bit bloated. Therefor, pilight allows you to trigger rules based on received codes instead of device updates:
.. deprecated:: 8.1.0
.. code-block:: guess
IF archtech_switch.state IS on AND archtech_switch.id == 123456 AND arctech_switch.unit == 0 THEN ...
.. versionadded:: 8.1.0
.. code-block:: guess
IF archtech_switch.state == on AND archtech_switch.id == 123456 AND arctech_switch.unit == 0 THEN ...
In this case, an action will be triggered as soon as an ``archtech_switch`` code is received with a specific state, id, and unitcode. The ``arctech_switch`` doesn't have to be configured as an explicit device for this rule to work.
Functions
---------
In some cases, standard operators limit us in writing our rules. For example, calculating with time is a hideous task considering that hours do not go above 24, minute and seconds do not go above 60, and there are no negative numbers. Other functionality like randomization are also not possible in the standard event operators. This more advanced functionality is added in the form of function. A simple example:
.. code-block:: guess
IF datetime.hour == RANDOM(21, 23) THEN ...
As we can see in this example we use the RANDOM function to check if the hour is either 21, 22, or 23. This allows us to trigger an action on random hours each day. Actions can also be nested for more advanced logic:
.. code-block:: guess
IF datetime.hour == RANDOM(RANDOM(21, 22), RANDOM(22, 23)) THEN ...
The output of this RANDOM function is the same as with the previous example, but the idea should be clear.
Actions
-------
Actions are the final goal of our rules. These actions tell pilight what should happen when certain conditions have been met. A rule can contain unlimited number of actions and each action can trigger an unlimited number of devices. First two examples of basic actions triggering a switch called *lamp* and a dimmer called *ambientLight*:
.. code-block:: guess
IF ... THEN switch DEVICE lamp TO on
IF ... THEN dim DEVICE ambientLight TO 10
Both actions only trigger a single device. However, if we wanted to trigger both device to just on we can combine them in a single action:
.. code-block:: guess
IF ... THEN switch DEVICE lamp AND ambientLight TO on
As we can see here, the switch action takes at least the DEVICE and TO parameters. In case of the switch action, several values (as in devices) can be combined by separating them with ANDs. We can also combine dim and switch action would we want to switch the *lamp* to on and dim the *ambientLight* to dimlevel 10 based on the same condition:
.. code-block:: guess
IF ... THEN switch DEVICE lamp TO on AND dim DEVICE ambientLight TO 10
We can combine an unlimited number of actions like this. Again we see that we use the AND to combine several actions. We can also switch several devices across several actions in a single rule. Let's say we have a relay connected to our television set called television that we want to turn on as well.
.. code-block:: guess
IF ... THEN switch DEVICE lamp AND television TO on AND dim DEVICE ambientLight TO 10
.. versionadded:: 8.1.0
As described earlier, actions can also be trigger based on a false condition like this:
.. code-block:: guess
IF ... THEN switch DEVICE lamp AND television TO on ELSE dim DEVICE ambientLight TO 10 END
Using Device Parameters
-----------------------
Device parameters can be used as rule input almost everywhere. Let us look at a few examples to demonstrate this:
.. code-block:: guess
IF 1 == 1 THEN dim DEVICE dimmer TO dimmerMax.dimlevel FOR dimmerDuration.dimlevel
In this case we use three dimmer devices. One dimmer called dimmer that we actually want to dim, and two dimmers that changes the way this rule behaves. The dimmerMax device tells pilight to what value the dimmer should dim. The dimmerDuration device tells pilight how long it should take to reach that dimlevel. Another example:
.. code-block:: guess
IF 1 == 1 THEN switch DEVICE lamp1 TO lamp2.state
In this case we want to switch the device lamp1 to the same state as the device lamp2.
Device parameters can also be used in function:
.. code-block:: guess
IF RANDOM(randomLow.dimlevel, randomHigh.dimlevel) == 10 THEN switch DEVICE lamp1 TO on
In this case we use two dimmers called randomLow and randomHigh to dynamically change the input of the RANDOM function used in this rule. A comprehensive and advanced example:
.. code-block:: guess
IF sunriseset.sunset == DATE_FORMAT(DATE_ADD(datetime, +1 HOUR), \"%Y-%m-%d %H:%M:%S\", %H.%M) THEN switch DEVICE lamp1 TO on
.. versionchanged:: 8.1.0
.. code-block:: guess
IF sunriseset.sunset == DATE_FORMAT(DATE_ADD(datetime, '+1 HOUR'), '%Y-%m-%d %H:%M:%S', %H.%M) THEN switch DEVICE lamp1 TO on
+186
View File
@@ -0,0 +1,186 @@
Frequently Asked Questions
==========================
- `General`_
- `Retrieving pilight version`_
- `pilight doesn't start or immediately exits`_
- `Fixing SSDP connection issues`_
- `Disabling SSDP completely`_
- `Using other devices besides 433.92 MHz`_
- `Fixing broken Lirc and 1-wire protocols`_
- `Fixing the high CPU usage after a Kernel upgrade`_
- `Sending & Receiving`_
- `The GPIO connected receiver does not work`_
- `I only see sent codes, not received ones`_
- `Let devices learn new codes sent from pilight`_
- `Configuration`_
- `How to use raw codes in the configuration`_
- `How to fix an empty webGUI`_
.. deprecated:: 8.0
- `General`_
- `Using PHP inside the pilight webserver`_
- `Sending & Receiving`_
- `The send-repeat setting does not work anymore`_
General
-------
.. _Retrieving pilight version:
.. rubric:: Retrieving pilight version
You can use the following command to retrieve the pilight version:
.. code-block:: console
pi@pilight:~# pilight-daemon -V
If you run a stable version, only the version will be shown:
.. code-block:: console
pilight-daemon version v7.0
If you run a developmental version, a commit message will also be shown. It will point to the last commit included in your pilight compilation.
.. code-block:: console
pilight-daemon version v7.0-24-gb64a135
In this case, the 24th commit after version 7.0 with the SHA id gb64a135 is running. To see which commit this is, check the `git development commit list <https://github.com/pilight/pilight/commits/development>`_.
.. _pilight doesn't start or immediately exits:
.. rubric:: pilight doesn't start or immediately exits
Most probably you made an error in the pilight configuration. Start pilight in debug mode and check the output:
.. code-block:: console
pi@pilight:~# pilight-daemon -D
.. _Fixing SSDP connection issues:
.. rubric:: Fixing SSDP connection issues
Make sure your iptables are set correctly:
.. code-block:: console
pi@pilight:~# sudo iptables -A INPUT -s 127.0.0.1 -j ACCEPT
Also make sure your network interfaces are configured correctly in **/etc/network/interfaces**:
.. code-block:: guess
:linenos:
auto lo
iface lo inet loopback
allow-hotplug eth0
auto eth0
iface eth0 inet static
address x.x.x.x
netmask 255.255.255.0
gateway x.x.x.x
Especially the **iface lo inet loopback** part is essential for SSDP to work. A reboot could be necessary after making these changes.
.. _Disabling SSDP completely:
.. rubric:: Disabling SSDP completely
Add the standalone setting in the config.json and set it to 1.
.. code-block:: json
:linenos:
{
"settings": {
"standalone": 1
}
}
However, because all pilight clients use SSDP to find the main pilight daemon, you need to pass the server and port arguments when you want to control this standalone running daemon. Check the documentation for the specific pilight client for additonal information.
.. _Using PHP inside the pilight webserver:
.. rubric:: Using PHP inside the pilight webserver
.. deprecated:: 8.0
You probably encounter this message when running pilight in debug mode:
.. code-block:: guess
:linenos:
pilight-daemon: ERROR: php support disabled due to missing php-cgi executable
This means that you miss some packages to run PHP. The required packages pilight needs for PHP support are:
- php-cgi
- base64
- cat
.. _Using other devices besides 433.92 MHz:
.. rubric:: Using other devices besides 433.92 MHz
pilight was built with 433.92 MHz devices as a reference, but the code is not limited to this frequency. We actually always wrote the code with other frequencies in mind. The only reason no other frequencies like 868 MHz are supported is lack of time and the lack of other developers to do it for us. The hardware part of pilight is completely modular so adding support for other frequencies should be as easy as writing new protocols.
.. _Fixing broken Lirc and 1-wire protocols:
.. rubric:: Fixing broken Lirc and 1-wire protocols
You probably installed the latest Raspberry Pi kernel. The new kernel works with device trees so the kernel knows what devices you want to use. Check the Raspberry Pi documentation how to use this new device tree.
.. _Fixing the high CPU usage after a Kernel upgrade:
.. rubric:: Fixing the high CPU usage after a Kernel upgrade
The wiringPi GPIO library used in pilight version 5.0 and lower contained a bug. This is fixed in pilight version 6 and up.
Version 8 and up use the wiringX library also written by the pilight developers which also fixes the (old) wiringPi bugs.
Sending & Receiving
-------------------
.. _The GPIO connected receiver does not work:
.. rubric:: The GPIO connected receiver does not work
The most encountered reason for this problem is the quality of the receiver. A lot of users buy unsupported (cheap) receivers from either eBay, DealExtreme or similar sites often referred to as FS1000A and XY-MK-5V. However, these receivers have a terrible range. To make sure it is the receiver and not a fault in connecting the device to your Raspberry Pi, make sure to keep your remote next to the receiver. If it still fails, check then check your connections.
If you do want to use pilight for controlling devices across your house, consider buying a good quality receiver. Refer to the pilight shop for supported peripherals.
.. _I only see sent codes, not received ones:
.. rubric:: I only see sent codes, not received ones
The pilight receive output always contains an origin value. This means you can see from were the outputted code came from. Only if this field says receiver you know that the code was picked up by the receiver. When it says sender the codes has been created and processed internally. pilight processes these codes as if it was a received code so it can update the GUIs and config. Only if you see receiver you know it was not generated by pilight.
.. _Let devices learn new codes sent from pilight:
.. rubric:: Let devices learn new codes sent from pilight
Some protocols support learning devices. This learn feature temporarily sends an increased amount of codes to the device. Check the protocol send arguments to see if your protocol supports it. For example, the KlikAanKlikUit protocol does this as follows:
.. code-block:: console
pi@pilight:~# pilight-send -p kaku_switch -i 1 -u 1 -t -l
.. _The send-repeat setting does not work anymore:
.. rubric:: The send-repeat setting does not work anymore
.. deprecated:: 6.0
pilight version 6 was the last version supporting the global send-repeat setting. This setting told pilight how often a pulsetrain was repeated. This setting got removed because it interfered with a lot of protocols.
Most remote control devices repeat a pulsetrain two to six times on a single button press. On some devices all pulsetrains are identical, so repeating them does not introduce any issues. However, on some devices the 1st pulsetrain differs from the subsequent pulsetrains. In addition, some devices sent a wakeup pulse sequence before the very 1st pulsetrain to trigger internal wakeup logic. Most devices use footer pulses, while devices transmit header pulses, and some devices transmit both.
If you keep the button pressed on some remote controls, a series of pulsetrains is sent until the button is released, while others stop sending repetitive pulsetrains after a certain time period, and some set a toggle bit for repetitive pulsetrains each time a button is pressed.
pilight was not differentiating between those various operating scenarios, because the send-repeat parameter specified only how often a single pulsetrain was re-transmitted for all devices. So increasing the global send-repeats actually broke a lot of these protocols. We therefore removed the old global send-repeat parameter and replaced it with a protocol specific repeat parameter, currently not configurable from userspace.
We also discovered that in almost all cases, the solution was not increasing the send-repeats parameter, but instead using a good antenna.
Configuration
-------------
.. _How to use raw codes in the configuration:
.. rubric:: How to use raw codes in the configuration
This is not possible, because pilight cannot know what these codes mean and how to interpret them.
.. _How to fix an empty webGUI:
.. rubric:: How to fix an empty webGUI
You need to add devices to the "GUI" section of config.json as well, not just the "devices" section.
File diff suppressed because it is too large. Load diff

After

Width:  |  Height:  |  Size: 136 KiB

File diff suppressed because it is too large. Load diff

After

Width:  |  Height:  |  Size: 134 KiB

File diff suppressed because it is too large. Load diff

After

Width:  |  Height:  |  Size: 115 KiB

File diff suppressed because it is too large. Load diff

After

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 405 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 378 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 391 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 403 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 390 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 382 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 373 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 371 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 359 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 391 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 403 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 416 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 KiB

File diff suppressed because it is too large. Load diff

After

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

@@ -0,0 +1,88 @@
:tocdepth: 5
Welcome to pilight's documentation!
===================================
.. raw:: latex
\newpage
Overview
--------
pilight is a free, open source, full fledged domotica solution that runs on a Raspberry Pi, Hummingboard, and BananaPi, but also on \*BSD, various Linux distributions (tested on Arch, Ubuntu, and Debian), Windows, and OpenWRT routers. pilight works with a great deal of devices and is frequency independent. Therefore, due to its modular set-up, it can control devices working at 315 MHz, 433 MHz, and 868 MHz, but only 433.92 MHz is currently supported. Support for other frequencies and/or devices is dependent on community input, because we as developers do not own them all.
.. raw:: latex
\newpage
Features
--------
The main features of pilight are:
* `Open Source`_
* `Open Hardware`_
* `Free`_
* `Fully Modular`_
* `High Quality Code`_
* `Integrated Webserver and webGUI`_
* `Light-Weight`_
.. _Open Source:
.. rubric:: Open Source
The pilight source code can be found on the internet at https://www.github.com/pilight/. pilight is largely dependent on community input so if you have any suggestions, improvements, or fixes, feel free to provide them.
.. _Open Hardware:
.. rubric:: Open Hardware
The source and schematics of all pilight hardware is open and free for everyone. This means that you can easily build the hardware pilight offers yourself. However, by buying the hardware from pilight, you also support the project.
.. _Free:
.. rubric:: Free
pilight is free as in free speech. It is licensed under the GPLv3 license. If you have any plans with our source code, please make it clear that you are not affiliated to pilight in any way. We do not want to end up in a situation were we have to give support for something we did not approve.
.. _Fully Modular:
.. rubric:: Fully Modular
pilight is modular in about every inch. Adding new protocols is very easy just like adding new hardware modules. The API allows users to develop new applications that interact with pilight. The community already developed phone apps, desktop apps, and various plug-ins for various other projects.
.. _High Quality Code:
.. rubric:: High quality code
Almost everything pilight does is also developed by pilight from the ground up. This means that the developers of pilight know what is going on in every part of the pilight code. Whenever additional functionality is needed, external libraries are carefully selected for their own code quality. As an example, pilight does not use OpenSSL but polarSSL (currently called mbed TLS). OpenSSL has a bad reputation in terms of code quality while polarSSL is far more robust. pilight developers also constantly audit their own code by using tools like valgrind or gdb. Memory leaks or other common issues are therefore 99% nonexisting in pilight. The pilight code quality also allows it to be ported easily to any platform as was proven with the Windows and OpenWRT ports.
.. _Integrated Webserver and webGUI:
.. rubric:: Integrated webserver and webGUI
pilight has an integrated webserver and serves an intergrated webGUI. This allows users to immediately start using pilight in all its capacity. The webGUI makes it easy to control devices or to see their states. Those who do not want to install the phone apps can just use their regular browser to access pilight.
.. _Light-Weight:
.. rubric:: Light-Weight
pilight is written in C. This means that it is very fast and does not use much resources. All plug-ins are compiled into pilight so the overhead of the plug-ins is also kept to a minimum. This is also one of the reasons pilight can run on low-power consumer products like OpenWRT routers. All pilight hardware such as the ATTiny filter and the Arduino Nano interface are also written in pure C. This again allows us to have control over every inch of code and to prevent any overhead from tools like the Arduino programming libraries.
.. raw:: latex
\newpage
Sitemap
-------
.. toctree::
:maxdepth: 4
:titlesonly:
changelog
installation
configuration/index
protocols/index
eventing/index
adhoc_network
programs/index
electronics/index
faq
development/index
about_manual
@@ -0,0 +1,190 @@
Installation
============
* `Linux Debian Based`_
* `Windows 7 and up`_
* `OpenWRT Routers`_
Linux Debian Based
------------------
Install pilight by using the apt repository in Debian / Ubuntu based distributions.
#. Login to your computer.
#. Make sure you are running as root. Run the following command and use your own password.
.. code-block:: console
pi@pilight:~# sudo su
Password:
#. Add the apt repository to the apt sources list:
.. code-block:: console
pi@pilight:~# echo "deb http://apt.pilight.org/ stable main" > /etc/apt/sources.list.d/pilight.list
If you want to install the nightly version of pilight then also add:
.. code-block:: console
root@pilight:~# echo "deb http://apt.pilight.org/ nightly main" >> /etc/apt/sources.list.d/pilight.list
#. pilight uses a signed repository. This means packages get validated before installation. So, to safely download and install pilight packages the pilight key needs to be installed.
.. code-block:: console
root@pilight:~# wget -O - http://apt.pilight.org/pilight.key | apt-key add -
#. Now update the apt package list:
.. code-block:: console
root@pilight:~# apt-get update
#. And install pilight
.. code-block:: console
root@pilight:~# apt-get install pilight
#. When no errors are shown, pilight will be installed and automatically started at boot time. To manually start pilight:
.. code-block:: console
root@pilight:~# service pilight start
#. And to stop pilight:
.. code-block:: console
root@pilight:~# service pilight stop
.. note::
pilight makes it easy to install previous version, because all stable versions and all nightly versions between two stable versions will remain available in the apt repository.
To see what versions are available, you can run the following command:
.. code-block:: console
root@pilight:~# apt-cache policy pilight
pilight:
Installed: 7.0.16-g233c268
Candidate: 7.0.21-ga8b12ea
Version table:
7.0.21-ga8b12ea 500
500 http://apt.pilight.org nightly/main armhf Packages
*** 7.0.16-g233c268 500
500 http://apt.pilight.org nightly/main armhf Packages
7.0.9-gfbc2643 500
500 http://apt.pilight.org nightly/main armhf Packages
7.0.8-g953bb85 500
500 http://apt.pilight.org nightly/main armhf Packages
7.0 500
500 http://apt.pilight.org stable/main armhf Packages
6.0 500
500 http://apt.pilight.org stable/main armhf Packages
5.0 500
500 http://apt.pilight.org stable/main armhf Packages
4.0 500
500 http://apt.pilight.org stable/main amd64 Package
In this case, both the stable and the nightly apt repositories are enabled. If you want to install a specific version run the following command:
.. code-block:: console
root@pilight:~# apt-get install pilight=7.0.67-g960219e
.. raw:: latex
\newpage
Windows 7 and up
----------------
#. Go to http://download.pilight.org.
#. Download the latest Windows executable called pilight-vX.0-win32.exe. Run it to install pilight.
#. By default pilight will install into to c:\\pilight\\.
#. A default configuration can also be found in that folder.
#. If you want to use the pilight USB nano you can use the pilight-usb-nano.hex found in the default folder.
OpenWRT Routers
---------------
#. When using OpenWRT you are assumed also to know how to login to your router with SSH.
#. Go to http://download.pilight.org.
#. Download the latest pilight OpenWRT compilation called pilight-Atheros-AR9132-vX.0.tar.gz.
#. Unpack this file like this:
.. code-block:: console
root@OpenWrt:~# tar -zxvf pilight-Atheros-AR9132-vX.0.tar.gz -C /
#. The OpenWRT package only contains pilight-daemon to save space.
#. A default configuration is put into /etc/pilight/config.json.
Manually Compiled Version
-------------------------
.. warning::
We try to provide as many options as possible for you to keep up-to-date with the latest developments. Compiling C software requires some level of expertise, which we cannot and will not provide. This means that **no support is given** if any issues occur with manually compiling pilight.
Manually compiling pilight is also possible. Use this method is you are not using a Debian-based or a \*BSD based operating system.
#. Login to your computer.
#. Make sure you've configured the pilight stable apt repository, because some required dependencies are not available elsewhere.
#. Make sure you are running as root. Run the following command and use your own password.
.. code-block:: console
pi@pilight:~# sudo su
Password:
#. Install all packages needed for manually compiling pilight. The best way to do this depends on your operating system. The packages needed for Debian are:
#. build-essential
#. cmake
#. git
#. dialog
#. libwiringx-dev
#. libwiringx
#. libpcap0.8-dev
#. libpcap0.8
#. libmbedtls-dev
#. libmbedx509-0
#. libmbedcrypto0
#. libmbedtls10
#. liblua5.2
#. liblua5.2-dev
#. Then download the pilight source code from the pilight GitHub:
.. code-block:: console
root@pilight:~# git clone --depth 5 -b [branch] https://www.github.com/pilight/pilight.git
root@pilight:~# cd pilight
#. Replace the [branch] with either **master** for the latest stable version. This version is exactly the same as the stable version available through the apt repository. Or use **development** for the very latest developmental build. This development version of pilight is also automatically generated each night. You can download it from the pilight nightly repository.
#. pilight can be compiled with various built-in features which can be included or excluded. This is done through a menu driven program. This program will also automatically compile and install pilight:
.. code-block:: console
root@pilight:~/pilight# chmod +x setup.sh
root@pilight:~/pilight# ./setup.sh
.. image:: images/installation.png
#. When you are thrown back into the command prompt without error(s), pilight has been installed successfully. It will also install a default configuration in /etc/pilight/config.json.
#. Make sure to run the following command after installation:
.. code-block:: console
root@pilight:~/pilight# ldconfig
#. pilight can now be started with:
.. code-block:: console
root@pilight:~/pilight# service pilight start
@@ -0,0 +1,83 @@
===============
pilight-control
===============
Control pilight devices
-----------------------
:Date: 2017
:Copyright: MPLv2
:Version: 7.0
:Manual section: 1
:Manual group: pilight 7.0 man pages
SYNOPSIS
========
| ``pilight-control`` --device DEVICE --state STATE
| ``pilight-control`` [OPTION]... --device DEVICE --values VALUES
| ``pilight-control`` [--server SERVER] [ --port PORT] [OPTION]... --device DEVICE
DESCRIPTION
===========
``pilight-control`` is a tool to control a device configured in a pilight daemon configuration. It supports switching the state and/or modifying other values (such as dimlevel, temperature, or humidity) of the device.
OPTIONS
=======
Mandatory arguments to long options are mandatory for short options too.
|
| ``-H``, ``--help``
| Print allowed options and exit
|
| ``-V``, ``--version``
| Print version information and exit
|
| ``-S``, ``--server=x.x.x.x``
| Connect to a pilight daemon at this address. Requires -P
|
| ``-P``, ``--port=xxxx``
| Connect to a pilight daemon at this port. Requires -S
|
| ``-C``, ``--config=PATH_TO_CONFIG``
| Path to configuration file
|
| ``-d``, ``--device=DEVICE_NAME``
| Name of the configured device to be controlled
|
| ``-s``, ``--state=STATE``
| State to switch DEVICE to
|
| ``-v``, ``--values=VALUES``
| Supply other values for DEVICE, such as dimlevel=10
BUGS
====
Please report all bugs on GitHub <https://github.com/pilight/pilight/>.
AUTHOR
======
Curlymo <info@pilight.org> and contributors.
This man page was originally written by pilino1234 <pilino1234@zoho.eu>.
WWW
===
https://www.pilight.org/
SEE ALSO
========
| ``pilight-daemon``
| ``pilight-debug``
| ``pilight-flash``
| ``pilight-raw``
| ``pilight-receive``
| ``pilight-send``
| ``pilight-sha256``
| ``pilight-uuid``
Loaded 100 of 1030 files, more files were not shown because too many files have changed in this diff. Show more