├── device
├── rpi
│ └── web
│ │ ├── __init__.py
│ │ ├── charts.py
│ │ ├── weatherMicroService.py
│ │ └── collector.py
└── arduino
│ └── SensorReader
│ └── SensorReader.ino
├── readme-files
├── cloud.png
├── temperature.png
├── weatherstation1.png
└── weatherstation2.png
├── indi-driver
├── docs
│ ├── indi.png
│ ├── obs.jpeg
│ └── INSTALL
├── build.sh
├── cloud-rain-monitor
│ ├── indi_cloud_rain_monitor.xml
│ ├── cmake_modules
│ │ ├── MacroBoolTo01.cmake
│ │ ├── FindJPEG.cmake
│ │ ├── FindUSB.cmake
│ │ ├── MacroOptionalFindPackage.cmake
│ │ ├── FindVorbis.cmake
│ │ ├── FindFTDI.cmake
│ │ ├── FindQHY.cmake
│ │ ├── FindASI.cmake
│ │ ├── FindQSI.cmake
│ │ ├── FindMEADE.cmake
│ │ ├── FindSBIG.cmake
│ │ ├── FindDC1394.cmake
│ │ ├── FindFLI.cmake
│ │ ├── FindNova.cmake
│ │ ├── FindAPOGEE.cmake
│ │ ├── FindMODBUS.cmake
│ │ ├── FindFISHCAMP.cmake
│ │ ├── FindAIOUSB.cmake
│ │ ├── FindCFITSIO.cmake
│ │ ├── FindALUT.cmake
│ │ ├── FindGPHOTO2.cmake
│ │ ├── FindOpenAL.cmake
│ │ ├── FindUSB-1.cmake
│ │ ├── MacroLogFeature.cmake
│ │ └── FindINDI.cmake
│ ├── CMakeLists.txt
│ ├── cloudrainmonitor.h
│ ├── gason.h
│ ├── cloudrainmonitor.cpp
│ └── gason.cpp
└── mock-weather-device.py
├── .idea
└── vcs.xml
└── README.md
/device/rpi/web/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/readme-files/cloud.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dokeeffe/cloud-rain-monitor/HEAD/readme-files/cloud.png
--------------------------------------------------------------------------------
/indi-driver/docs/indi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dokeeffe/cloud-rain-monitor/HEAD/indi-driver/docs/indi.png
--------------------------------------------------------------------------------
/indi-driver/docs/obs.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dokeeffe/cloud-rain-monitor/HEAD/indi-driver/docs/obs.jpeg
--------------------------------------------------------------------------------
/readme-files/temperature.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dokeeffe/cloud-rain-monitor/HEAD/readme-files/temperature.png
--------------------------------------------------------------------------------
/readme-files/weatherstation1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dokeeffe/cloud-rain-monitor/HEAD/readme-files/weatherstation1.png
--------------------------------------------------------------------------------
/readme-files/weatherstation2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dokeeffe/cloud-rain-monitor/HEAD/readme-files/weatherstation2.png
--------------------------------------------------------------------------------
/indi-driver/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | mkdir build
3 | cd build
4 | rm * -rf
5 | cmake -DCMAKE_INSTALL_PREFIX=/usr ../cloud-rain-monitor/
6 | sudo make install
7 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/indi-driver/docs/INSTALL:
--------------------------------------------------------------------------------
1 | To build and install this indi driver, cd to the same dir as the build.sh script, then sudo ./build.sh
2 | You will need indi dev dependencies installed. Cmake wll inform of any missing deps.
3 |
--------------------------------------------------------------------------------
/indi-driver/cloud-rain-monitor/indi_cloud_rain_monitor.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | indi_cloud_rain_monitor
4 | 1.0
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/indi-driver/mock-weather-device.py:
--------------------------------------------------------------------------------
1 | # HTTP server to be used for testing
2 | # Run the indi driver and configure to connect to a weather station at http://localhost:8080/weather/true to simulate rain conditions
3 | #
4 | from bottle import route, run, template
5 |
6 | @route('/weather/')
7 | def index(rain):
8 | return template('{"uptime":"05:14:12", "skyTemp": 4.230, "outsideTemp": 1.090, "rain":{{rain}} }', rain=rain)
9 |
10 | run(host='localhost', port=8080)
11 |
--------------------------------------------------------------------------------
/indi-driver/cloud-rain-monitor/cmake_modules/MacroBoolTo01.cmake:
--------------------------------------------------------------------------------
1 | # MACRO_BOOL_TO_01( VAR RESULT0 ... RESULTN )
2 | # This macro evaluates its first argument
3 | # and sets all the given vaiables either to 0 or 1
4 | # depending on the value of the first one
5 |
6 | # Copyright (c) 2006, Alexander Neundorf,
7 | #
8 | # Redistribution and use is allowed according to the terms of the BSD license.
9 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file.
10 |
11 |
12 | MACRO(MACRO_BOOL_TO_01 FOUND_VAR )
13 | FOREACH (_current_VAR ${ARGN})
14 | IF(${FOUND_VAR})
15 | SET(${_current_VAR} 1)
16 | ELSE(${FOUND_VAR})
17 | SET(${_current_VAR} 0)
18 | ENDIF(${FOUND_VAR})
19 | ENDFOREACH(_current_VAR)
20 | ENDMACRO(MACRO_BOOL_TO_01)
21 |
--------------------------------------------------------------------------------
/indi-driver/cloud-rain-monitor/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 2.4.7)
2 | PROJECT(indi_cloud_rain_monitor CXX C)
3 |
4 | set(CMAKE_CXX_FLAGS "-std=c++0x ${CMAKE_CXX_FLAGS}")
5 |
6 | set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules/")
7 | set (VERSION_MAJOR 0)
8 | set (VERSION_MINOR 2)
9 |
10 | find_package(INDI REQUIRED)
11 |
12 | include_directories(${CMAKE_CURRENT_BINARY_DIR})
13 | include_directories(${CMAKE_CURRENT_SOURCE_DIR})
14 | include_directories(${INDI_INCLUDE_DIR})
15 |
16 | ################ Cloud rain monitor ################
17 | set(cloudrainmonitor_SRCS
18 | ${CMAKE_CURRENT_SOURCE_DIR}/cloudrainmonitor.cpp
19 | ${CMAKE_CURRENT_SOURCE_DIR}/gason.cpp
20 | )
21 |
22 | add_executable(indi_cloud_rain_monitor ${cloudrainmonitor_SRCS})
23 | target_link_libraries(indi_cloud_rain_monitor ${INDI_DRIVER_LIBRARIES} curl)
24 | install(TARGETS indi_cloud_rain_monitor RUNTIME DESTINATION bin )
25 | install(FILES indi_cloud_rain_monitor.xml DESTINATION ${INDI_DATA_DIR})
26 |
27 |
--------------------------------------------------------------------------------
/indi-driver/cloud-rain-monitor/cmake_modules/FindJPEG.cmake:
--------------------------------------------------------------------------------
1 | # - Find JPEG
2 | # Find the native JPEG includes and library
3 | # This module defines
4 | # JPEG_INCLUDE_DIR, where to find jpeglib.h, etc.
5 | # JPEG_LIBRARIES, the libraries needed to use JPEG.
6 | # JPEG_FOUND, If false, do not try to use JPEG.
7 | # also defined, but not for general use are
8 | # JPEG_LIBRARY, where to find the JPEG library.
9 |
10 | FIND_PATH(JPEG_INCLUDE_DIR jpeglib.h)
11 |
12 | SET(JPEG_NAMES ${JPEG_NAMES} jpeg)
13 | FIND_LIBRARY(JPEG_LIBRARY NAMES ${JPEG_NAMES} )
14 |
15 | # handle the QUIETLY and REQUIRED arguments and set JPEG_FOUND to TRUE if
16 | # all listed variables are TRUE
17 | INCLUDE(FindPackageHandleStandardArgs)
18 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(JPEG DEFAULT_MSG JPEG_LIBRARY JPEG_INCLUDE_DIR)
19 |
20 | IF(JPEG_FOUND)
21 | SET(JPEG_LIBRARIES ${JPEG_LIBRARY})
22 | ENDIF(JPEG_FOUND)
23 |
24 | # Deprecated declarations.
25 | SET (NATIVE_JPEG_INCLUDE_PATH ${JPEG_INCLUDE_DIR} )
26 | GET_FILENAME_COMPONENT (NATIVE_JPEG_LIB_PATH ${JPEG_LIBRARY} PATH)
27 |
28 | MARK_AS_ADVANCED(JPEG_LIBRARY JPEG_INCLUDE_DIR )
29 |
--------------------------------------------------------------------------------
/indi-driver/cloud-rain-monitor/cmake_modules/FindUSB.cmake:
--------------------------------------------------------------------------------
1 | # - Try to find the USB library
2 | # Once done this defines
3 | #
4 | # LIBUSB_FOUND - system has libusb
5 | # LIBUSB_INCLUDE_DIR - the libusb include directory
6 | # LIBUSB_LIBRARIES - Link these to use libusb
7 |
8 | # Copyright (c) 2006, 2008 Laurent Montel,
9 | #
10 | # Redistribution and use is allowed according to the terms of the BSD license.
11 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file.
12 |
13 |
14 | if (NOT WIN32)
15 | # use pkg-config to get the directories and then use these values
16 | # in the FIND_PATH() and FIND_LIBRARY() calls
17 | find_package(PkgConfig)
18 | pkg_check_modules(PC_LIBUSB QUIET libusb)
19 | endif(NOT WIN32)
20 |
21 | find_path(LIBUSB_INCLUDE_DIR usb.h
22 | HINTS ${PC_LIBUSB_INCLUDEDIR} ${PC_LIBUSB_INCLUDE_DIRS})
23 |
24 | find_library(LIBUSB_LIBRARIES NAMES usb
25 | HINTS ${PC_LIBUSB_LIBDIR} ${PC_LIBUSB_LIBRARY_DIRS})
26 |
27 | include(FindPackageHandleStandardArgs)
28 | find_package_handle_standard_args(LIBUSB DEFAULT_MSG LIBUSB_LIBRARIES LIBUSB_INCLUDE_DIR)
29 |
30 | mark_as_advanced(LIBUSB_INCLUDE_DIR LIBUSB_LIBRARIES)
31 |
--------------------------------------------------------------------------------
/indi-driver/cloud-rain-monitor/cmake_modules/MacroOptionalFindPackage.cmake:
--------------------------------------------------------------------------------
1 | # - MACRO_OPTIONAL_FIND_PACKAGE() combines FIND_PACKAGE() with an OPTION()
2 | # MACRO_OPTIONAL_FIND_PACKAGE( [QUIT] )
3 | # This macro is a combination of OPTION() and FIND_PACKAGE(), it
4 | # works like FIND_PACKAGE(), but additionally it automatically creates
5 | # an option name WITH_, which can be disabled via the cmake GUI.
6 | # or via -DWITH_=OFF
7 | # The standard _FOUND variables can be used in the same way
8 | # as when using the normal FIND_PACKAGE()
9 |
10 | # Copyright (c) 2006, Alexander Neundorf,
11 | #
12 | # Redistribution and use is allowed according to the terms of the BSD license.
13 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file.
14 |
15 |
16 | MACRO (MACRO_OPTIONAL_FIND_PACKAGE _name )
17 | OPTION(WITH_${_name} "Search for ${_name} package" ON)
18 | if (WITH_${_name})
19 | FIND_PACKAGE(${_name} ${ARGN})
20 | else (WITH_${_name})
21 | set(${_name}_FOUND)
22 | set(${_name}_INCLUDE_DIR)
23 | set(${_name}_INCLUDES)
24 | set(${_name}_LIBRARY)
25 | set(${_name}_LIBRARIES)
26 | endif (WITH_${_name})
27 | ENDMACRO (MACRO_OPTIONAL_FIND_PACKAGE)
28 |
29 |
--------------------------------------------------------------------------------
/indi-driver/cloud-rain-monitor/cmake_modules/FindVorbis.cmake:
--------------------------------------------------------------------------------
1 | # - Find vorbis
2 | # Find the native vorbis includes and libraries
3 | #
4 | # VORBIS_INCLUDE_DIR - where to find vorbis.h, etc.
5 | # VORBIS_LIBRARIES - List of libraries when using vorbis(file).
6 | # VORBIS_FOUND - True if vorbis found.
7 |
8 | if(VORBIS_INCLUDE_DIR)
9 | # Already in cache, be silent
10 | set(VORBIS_FIND_QUIETLY TRUE)
11 | endif(VORBIS_INCLUDE_DIR)
12 |
13 | find_path(VORBIS_INCLUDE_DIR vorbis/vorbisfile.h)
14 |
15 | find_library(OGG_LIBRARY NAMES ogg)
16 | find_library(VORBIS_LIBRARY NAMES vorbis)
17 | find_library(VORBISFILE_LIBRARY NAMES vorbisfile)
18 |
19 | # Handle the QUIETLY and REQUIRED arguments and set VORBIS_FOUND to TRUE if
20 | # all listed variables are TRUE.
21 | include(FindPackageHandleStandardArgs)
22 | find_package_handle_standard_args(VORBIS DEFAULT_MSG
23 | VORBIS_INCLUDE_DIR OGG_LIBRARY VORBIS_LIBRARY VORBIS_LIBRARY)
24 |
25 | if(VORBIS_FOUND)
26 | set(VORBIS_LIBRARIES ${VORBISFILE_LIBRARY} ${VORBIS_LIBRARY} ${OGG_LIBRARY})
27 | else(VORBIS_FOUND)
28 | set(VORBIS_LIBRARIES)
29 | endif(VORBIS_FOUND)
30 |
31 | mark_as_advanced(VORBIS_INCLUDE_DIR)
32 | mark_as_advanced(OGG_LIBRARY VORBIS_LIBRARY VORBISFILE_LIBRARY)
33 |
--------------------------------------------------------------------------------
/indi-driver/cloud-rain-monitor/cmake_modules/FindFTDI.cmake:
--------------------------------------------------------------------------------
1 | # - Try to find FTDI
2 | # Once done this will define
3 | #
4 | # FTDI_FOUND - system has FTDI
5 | # FTDI_INCLUDE_DIR - the FTDI include directory
6 | # FTDI_LIBRARIES - Link these to use FTDI
7 |
8 | # Redistribution and use is allowed according to the terms of the BSD license.
9 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file.
10 |
11 | if (FTDI_INCLUDE_DIR AND FTDI_LIBRARIES)
12 |
13 | # in cache already
14 | set(FTDI_FOUND TRUE)
15 | message(STATUS "Found libftdi: ${FTDI_LIBRARIES}")
16 |
17 | else (FTDI_INCLUDE_DIR AND FTDI_LIBRARIES)
18 |
19 | find_path(FTDI_INCLUDE_DIR ftdi.h
20 | ${_obIncDir}
21 | ${GNUWIN32_DIR}/include
22 | )
23 |
24 | find_library(FTDI_LIBRARIES NAMES ftdi
25 | PATHS
26 | ${_obLinkDir}
27 | ${GNUWIN32_DIR}/lib
28 | )
29 |
30 | if(FTDI_INCLUDE_DIR AND FTDI_LIBRARIES)
31 | set(FTDI_FOUND TRUE)
32 | else (FTDI_INCLUDE_DIR AND FTDI_LIBRARIES)
33 | set(FTDI_FOUND FALSE)
34 | endif(FTDI_INCLUDE_DIR AND FTDI_LIBRARIES)
35 |
36 |
37 | if (FTDI_FOUND)
38 | if (NOT FTDI_FIND_QUIETLY)
39 | message(STATUS "Found FTDI: ${FTDI_LIBRARIES}")
40 | endif (NOT FTDI_FIND_QUIETLY)
41 | else (FTDI_FOUND)
42 | if (FTDI_FIND_REQUIRED)
43 | message(FATAL_ERROR "FTDI not found. Please install libftdi-dev")
44 | endif (FTDI_FIND_REQUIRED)
45 | endif (FTDI_FOUND)
46 |
47 | mark_as_advanced(FTDI_INCLUDE_DIR FTDI_LIBRARIES)
48 |
49 | endif (FTDI_INCLUDE_DIR AND FTDI_LIBRARIES)
50 |
--------------------------------------------------------------------------------
/indi-driver/cloud-rain-monitor/cmake_modules/FindQHY.cmake:
--------------------------------------------------------------------------------
1 | # - Try to find QHY Library
2 | # Once done this will define
3 | #
4 | # QHY_FOUND - system has QHY
5 | # QHY_INCLUDE_DIR - the QHY include directory
6 | # QHY_LIBRARIES - Link these to use QHY
7 |
8 | # Redistribution and use is allowed according to the terms of the BSD license.
9 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file.
10 |
11 | if (QHY_INCLUDE_DIR AND QHY_LIBRARIES)
12 |
13 | # in cache already
14 | set(QHY_FOUND TRUE)
15 | message(STATUS "Found libqhy: ${QHY_LIBRARIES}")
16 |
17 | else (QHY_INCLUDE_DIR AND QHY_LIBRARIES)
18 |
19 | find_path(QHY_INCLUDE_DIR qhyccd.h
20 | PATH_SUFFIXES libqhy
21 | ${_obIncDir}
22 | ${GNUWIN32_DIR}/include
23 | )
24 |
25 | find_library(QHY_LIBRARIES NAMES qhy
26 | PATHS
27 | ${_obLinkDir}
28 | ${GNUWIN32_DIR}/lib
29 | )
30 |
31 | if(QHY_INCLUDE_DIR AND QHY_LIBRARIES)
32 | set(QHY_FOUND TRUE)
33 | else (QHY_INCLUDE_DIR AND QHY_LIBRARIES)
34 | set(QHY_FOUND FALSE)
35 | endif(QHY_INCLUDE_DIR AND QHY_LIBRARIES)
36 |
37 |
38 | if (QHY_FOUND)
39 | if (NOT QHY_FIND_QUIETLY)
40 | message(STATUS "Found QHY: ${QHY_LIBRARIES}")
41 | endif (NOT QHY_FIND_QUIETLY)
42 | else (QHY_FOUND)
43 | if (QHY_FIND_REQUIRED)
44 | message(FATAL_ERROR "QHY not found. Please install libqhy http://www.indilib.org")
45 | endif (QHY_FIND_REQUIRED)
46 | endif (QHY_FOUND)
47 |
48 | mark_as_advanced(QHY_INCLUDE_DIR QHY_LIBRARIES)
49 |
50 | endif (QHY_INCLUDE_DIR AND QHY_LIBRARIES)
51 |
--------------------------------------------------------------------------------
/indi-driver/cloud-rain-monitor/cmake_modules/FindASI.cmake:
--------------------------------------------------------------------------------
1 | # - Try to find ASI Library
2 | # Once done this will define
3 | #
4 | # ASI_FOUND - system has ASI
5 | # ASI_INCLUDE_DIR - the ASI include directory
6 | # ASI_LIBRARIES - Link these to use ASI
7 |
8 | # Redistribution and use is allowed according to the terms of the BSD license.
9 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file.
10 |
11 | if (ASI_INCLUDE_DIR AND ASI_LIBRARIES)
12 |
13 | # in cache already
14 | set(ASI_FOUND TRUE)
15 | message(STATUS "Found libasi: ${ASI_LIBRARIES}")
16 |
17 | else (ASI_INCLUDE_DIR AND ASI_LIBRARIES)
18 |
19 | find_path(ASI_INCLUDE_DIR ASICamera2.h
20 | PATH_SUFFIXES libasi
21 | ${_obIncDir}
22 | ${GNUWIN32_DIR}/include
23 | )
24 |
25 | find_library(ASI_LIBRARIES NAMES ASICamera2
26 | PATHS
27 | ${_obLinkDir}
28 | ${GNUWIN32_DIR}/lib
29 | )
30 |
31 | if(ASI_INCLUDE_DIR AND ASI_LIBRARIES)
32 | set(ASI_FOUND TRUE)
33 | else (ASI_INCLUDE_DIR AND ASI_LIBRARIES)
34 | set(ASI_FOUND FALSE)
35 | endif(ASI_INCLUDE_DIR AND ASI_LIBRARIES)
36 |
37 |
38 | if (ASI_FOUND)
39 | if (NOT ASI_FIND_QUIETLY)
40 | message(STATUS "Found ASI: ${ASI_LIBRARIES}")
41 | endif (NOT ASI_FIND_QUIETLY)
42 | else (ASI_FOUND)
43 | if (ASI_FIND_REQUIRED)
44 | message(FATAL_ERROR "ASI not found. Please install libasi http://www.indilib.org")
45 | endif (ASI_FIND_REQUIRED)
46 | endif (ASI_FOUND)
47 |
48 | mark_as_advanced(ASI_INCLUDE_DIR ASI_LIBRARIES)
49 |
50 | endif (ASI_INCLUDE_DIR AND ASI_LIBRARIES)
51 |
--------------------------------------------------------------------------------
/indi-driver/cloud-rain-monitor/cmake_modules/FindQSI.cmake:
--------------------------------------------------------------------------------
1 | # - Try to find Quantum Scientific Imaging Library
2 | # Once done this will define
3 | #
4 | # QSI_FOUND - system has QSI
5 | # QSI_INCLUDE_DIR - the QSI include directory
6 | # QSI_LIBRARIES - Link these to use QSI
7 |
8 | # Redistribution and use is allowed according to the terms of the BSD license.
9 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file.
10 |
11 | if (QSI_INCLUDE_DIR AND QSI_LIBRARIES)
12 |
13 | # in cache already
14 | set(QSI_FOUND TRUE)
15 | message(STATUS "Found libqsiapi: ${QSI_LIBRARIES}")
16 |
17 | else (QSI_INCLUDE_DIR AND QSI_LIBRARIES)
18 |
19 | find_path(QSI_INCLUDE_DIR qsiapi.h
20 | PATH_SUFFIXES qsiapi
21 | ${_obIncDir}
22 | ${GNUWIN32_DIR}/include
23 | )
24 |
25 | find_library(QSI_LIBRARIES NAMES qsiapi
26 | PATHS
27 | ${_obLinkDir}
28 | ${GNUWIN32_DIR}/lib
29 | )
30 |
31 | if(QSI_INCLUDE_DIR AND QSI_LIBRARIES)
32 | set(QSI_FOUND TRUE)
33 | else (QSI_INCLUDE_DIR AND QSI_LIBRARIES)
34 | set(QSI_FOUND FALSE)
35 | endif(QSI_INCLUDE_DIR AND QSI_LIBRARIES)
36 |
37 |
38 | if (QSI_FOUND)
39 | if (NOT QSI_FIND_QUIETLY)
40 | message(STATUS "Found QSI: ${QSI_LIBRARIES}")
41 | endif (NOT QSI_FIND_QUIETLY)
42 | else (QSI_FOUND)
43 | if (QSI_FIND_REQUIRED)
44 | message(FATAL_ERROR "QSI not found. Please install libqsi http://www.indilib.org")
45 | endif (QSI_FIND_REQUIRED)
46 | endif (QSI_FOUND)
47 |
48 | mark_as_advanced(QSI_INCLUDE_DIR QSI_LIBRARIES)
49 |
50 | endif (QSI_INCLUDE_DIR AND QSI_LIBRARIES)
51 |
--------------------------------------------------------------------------------
/indi-driver/cloud-rain-monitor/cmake_modules/FindMEADE.cmake:
--------------------------------------------------------------------------------
1 | # - Try to find Meade DSI Library.
2 | # Once done this will define
3 | #
4 | # MEADEDSI_FOUND - system has Meade DSI
5 | # MEADEDSI_LIBRARIES - Link these to use Meade DSI
6 |
7 | # Copyright (c) 2006, Jasem Mutlaq
8 | # Based on FindLibfacile by Carsten Niehaus,
9 | #
10 | # Redistribution and use is allowed according to the terms of the BSD license.
11 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file.
12 |
13 | if (MEADEDSI_LIBRARIES)
14 |
15 | # in cache already
16 | set(MEADEDSI_FOUND TRUE)
17 | message(STATUS "Found MEADEDSI: ${MEADEDSI_LIBRARIES}")
18 |
19 | else (MEADEDSI_LIBRARIES)
20 |
21 | find_library(MEADEDSI_LIBRARIES NAMES dsi
22 | PATHS
23 | ${_obLinkDir}
24 | ${GNUWIN32_DIR}/lib
25 | )
26 |
27 | set(CMAKE_REQUIRED_LIBRARIES ${MEADEDSI_LIBRARIES})
28 |
29 | if(MEADEDSI_LIBRARIES)
30 | set(MEADEDSI_FOUND TRUE)
31 | else (MEADEDSI_LIBRARIES)
32 | set(MEADEDSI_FOUND FALSE)
33 | endif(MEADEDSI_LIBRARIES)
34 |
35 | if (MEADEDSI_FOUND)
36 | if (NOT MEADEDSI_FIND_QUIETLY)
37 | message(STATUS "Found Meade DSI: ${MEADEDSI_LIBRARIES}")
38 | endif (NOT MEADEDSI_FIND_QUIETLY)
39 | else (MEADEDSI_FOUND)
40 | if (MEADEDSI_FIND_REQUIRED)
41 | message(FATAL_ERROR "Meade DSI not found. Please install Meade DSI library. http://linuxdsi.sourceforge.net")
42 | endif (MEADEDSI_FIND_REQUIRED)
43 | endif (MEADEDSI_FOUND)
44 |
45 | mark_as_advanced(MEADEDSI_LIBRARIES)
46 |
47 | endif (MEADEDSI_LIBRARIES)
48 |
--------------------------------------------------------------------------------
/indi-driver/cloud-rain-monitor/cmake_modules/FindSBIG.cmake:
--------------------------------------------------------------------------------
1 | # - Try to find SBIG Universal Library
2 | # Once done this will define
3 | #
4 | # SBIG_FOUND - system has SBIG
5 | # SBIG_INCLUDE_DIR - the SBIG include directory
6 | # SBIG_LIBRARIES - Link these to use SBIG
7 |
8 | # Redistribution and use is allowed according to the terms of the BSD license.
9 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file.
10 |
11 | if (SBIG_INCLUDE_DIR AND SBIG_LIBRARIES)
12 |
13 | # in cache already
14 | set(SBIG_FOUND TRUE)
15 | message(STATUS "Found libsbig: ${SBIG_LIBRARIES}")
16 |
17 | else (SBIG_INCLUDE_DIR AND SBIG_LIBRARIES)
18 |
19 | find_path(SBIG_INCLUDE_DIR sbigudrv.h
20 | PATH_SUFFIXES libsbig
21 | ${_obIncDir}
22 | ${GNUWIN32_DIR}/include
23 | )
24 |
25 | find_library(SBIG_LIBRARIES NAMES sbigudrv
26 | PATHS
27 | ${_obLinkDir}
28 | ${GNUWIN32_DIR}/lib
29 | )
30 |
31 | if(SBIG_INCLUDE_DIR AND SBIG_LIBRARIES)
32 | set(SBIG_FOUND TRUE)
33 | else (SBIG_INCLUDE_DIR AND SBIG_LIBRARIES)
34 | set(SBIG_FOUND FALSE)
35 | endif(SBIG_INCLUDE_DIR AND SBIG_LIBRARIES)
36 |
37 |
38 | if (SBIG_FOUND)
39 | if (NOT SBIG_FIND_QUIETLY)
40 | message(STATUS "Found SBIG: ${SBIG_LIBRARIES}")
41 | endif (NOT SBIG_FIND_QUIETLY)
42 | else (SBIG_FOUND)
43 | if (SBIG_FIND_REQUIRED)
44 | message(FATAL_ERROR "SBIG not found. Please install SBIG Library http://www.indilib.org")
45 | endif (SBIG_FIND_REQUIRED)
46 | endif (SBIG_FOUND)
47 |
48 | mark_as_advanced(SBIG_INCLUDE_DIR SBIG_LIBRARIES)
49 |
50 | endif (SBIG_INCLUDE_DIR AND SBIG_LIBRARIES)
51 |
--------------------------------------------------------------------------------
/indi-driver/cloud-rain-monitor/cmake_modules/FindDC1394.cmake:
--------------------------------------------------------------------------------
1 | # - Try to find dc1394 library (version 2) and include files
2 | # Once done this will define
3 | #
4 | # DC1394_FOUND - system has DC1394
5 | # DC1394_INCLUDE_DIR - the DC1394 include directory
6 | # DC1394_LIBRARIES - Link these to use DC1394
7 |
8 | # Redistribution and use is allowed according to the terms of the BSD license.
9 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file.
10 |
11 | if (DC1394_INCLUDE_DIR AND DC1394_LIBRARIES)
12 |
13 | # in cache already
14 | set(DC1394_FOUND TRUE)
15 | message(STATUS "Found libdc1394: ${DC1394_LIBRARIES}")
16 |
17 | else (DC1394_INCLUDE_DIR AND DC1394_LIBRARIES)
18 |
19 | find_path(DC1394_INCLUDE_DIR control.h
20 | PATH_SUFFIXES dc1394
21 | ${_obIncDir}
22 | ${GNUWIN32_DIR}/include
23 | )
24 |
25 | find_library(DC1394_LIBRARIES NAMES dc1394
26 | PATHS
27 | ${_obLinkDir}
28 | ${GNUWIN32_DIR}/lib
29 | )
30 |
31 | if(DC1394_INCLUDE_DIR AND DC1394_LIBRARIES)
32 | set(DC1394_FOUND TRUE)
33 | else (DC1394_INCLUDE_DIR AND DC1394_LIBRARIES)
34 | set(DC1394_FOUND FALSE)
35 | endif(DC1394_INCLUDE_DIR AND DC1394_LIBRARIES)
36 |
37 |
38 | if (DC1394_FOUND)
39 | if (NOT DC1394_FIND_QUIETLY)
40 | message(STATUS "Found DC1394: ${DC1394_LIBRARIES}")
41 | endif (NOT DC1394_FIND_QUIETLY)
42 | else (DC1394_FOUND)
43 | if (DC1394_FIND_REQUIRED)
44 | message(FATAL_ERROR "DC1394 not found. Please install libdc1395")
45 | endif (DC1394_FIND_REQUIRED)
46 | endif (DC1394_FOUND)
47 |
48 | mark_as_advanced(DC1394_INCLUDE_DIR DC1394_LIBRARIES)
49 |
50 | endif (DC1394_INCLUDE_DIR AND DC1394_LIBRARIES)
51 |
--------------------------------------------------------------------------------
/indi-driver/cloud-rain-monitor/cmake_modules/FindFLI.cmake:
--------------------------------------------------------------------------------
1 | # - Try to find Finger Lakes Instruments Library
2 | # Once done this will define
3 | #
4 | # FLI_FOUND - system has FLI
5 | # FLI_INCLUDE_DIR - the FLI include directory
6 | # FLI_LIBRARIES - Link these to use FLI
7 |
8 | # Copyright (c) 2008, Jasem Mutlaq
9 | # Based on FindLibfacile by Carsten Niehaus,
10 | #
11 | # Redistribution and use is allowed according to the terms of the BSD license.
12 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file.
13 |
14 | if (FLI_INCLUDE_DIR AND FLI_LIBRARIES)
15 |
16 | # in cache already
17 | set(FLI_FOUND TRUE)
18 | message(STATUS "Found libfli: ${FLI_LIBRARIES}")
19 |
20 | else (FLI_INCLUDE_DIR AND FLI_LIBRARIES)
21 |
22 | find_path(FLI_INCLUDE_DIR libfli.h
23 | PATH_SUFFIXES fli
24 | ${_obIncDir}
25 | ${GNUWIN32_DIR}/include
26 | )
27 |
28 | find_library(FLI_LIBRARIES NAMES fli
29 | PATHS
30 | ${_obLinkDir}
31 | ${GNUWIN32_DIR}/lib
32 | )
33 |
34 | if(FLI_INCLUDE_DIR AND FLI_LIBRARIES)
35 | set(FLI_FOUND TRUE)
36 | else (FLI_INCLUDE_DIR AND FLI_LIBRARIES)
37 | set(FLI_FOUND FALSE)
38 | endif(FLI_INCLUDE_DIR AND FLI_LIBRARIES)
39 |
40 |
41 | if (FLI_FOUND)
42 | if (NOT FLI_FIND_QUIETLY)
43 | message(STATUS "Found FLI: ${FLI_LIBRARIES}")
44 | endif (NOT FLI_FIND_QUIETLY)
45 | else (FLI_FOUND)
46 | if (FLI_FIND_REQUIRED)
47 | message(FATAL_ERROR "FLI not found. Please install libfli-dev. http://www.indilib.org")
48 | endif (FLI_FIND_REQUIRED)
49 | endif (FLI_FOUND)
50 |
51 | mark_as_advanced(FLI_INCLUDE_DIR FLI_LIBRARIES)
52 |
53 | endif (FLI_INCLUDE_DIR AND FLI_LIBRARIES)
54 |
--------------------------------------------------------------------------------
/indi-driver/cloud-rain-monitor/cmake_modules/FindNova.cmake:
--------------------------------------------------------------------------------
1 | # - Try to find NOVA
2 | # Once done this will define
3 | #
4 | # NOVA_FOUND - system has NOVA
5 | # NOVA_INCLUDE_DIR - the NOVA include directory
6 | # NOVA_LIBRARIES - Link these to use NOVA
7 |
8 | # Copyright (c) 2006, Jasem Mutlaq
9 | # Based on FindLibfacile by Carsten Niehaus,
10 | #
11 | # Redistribution and use is allowed according to the terms of the BSD license.
12 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file.
13 |
14 | if (NOVA_INCLUDE_DIR AND NOVA_LIBRARIES)
15 |
16 | # in cache already
17 | set(NOVA_FOUND TRUE)
18 | message(STATUS "Found libnova: ${NOVA_LIBRARIES}")
19 |
20 | else (NOVA_INCLUDE_DIR AND NOVA_LIBRARIES)
21 |
22 | find_path(NOVA_INCLUDE_DIR libnova.h
23 | PATH_SUFFIXES libnova
24 | ${_obIncDir}
25 | ${GNUWIN32_DIR}/include
26 | )
27 |
28 | find_library(NOVA_LIBRARIES NAMES nova
29 | PATHS
30 | ${_obLinkDir}
31 | ${GNUWIN32_DIR}/lib
32 | )
33 |
34 | set(CMAKE_REQUIRED_INCLUDES ${NOVA_INCLUDE_DIR})
35 | set(CMAKE_REQUIRED_LIBRARIES ${NOVA_LIBRARIES})
36 |
37 | if(NOVA_INCLUDE_DIR AND NOVA_LIBRARIES)
38 | set(NOVA_FOUND TRUE)
39 | else (NOVA_INCLUDE_DIR AND NOVA_LIBRARIES)
40 | set(NOVA_FOUND FALSE)
41 | endif(NOVA_INCLUDE_DIR AND NOVA_LIBRARIES)
42 |
43 | if (NOVA_FOUND)
44 | if (NOT Nova_FIND_QUIETLY)
45 | message(STATUS "Found NOVA: ${NOVA_LIBRARIES}")
46 | endif (NOT Nova_FIND_QUIETLY)
47 | else (NOVA_FOUND)
48 | if (Nova_FIND_REQUIRED)
49 | message(FATAL_ERROR "libnova not found. Please install libnova0-devel. http://indi.sf.net")
50 | endif (Nova_FIND_REQUIRED)
51 | endif (NOVA_FOUND)
52 |
53 | mark_as_advanced(NOVA_INCLUDE_DIR NOVA_LIBRARIES)
54 |
55 | endif (NOVA_INCLUDE_DIR AND NOVA_LIBRARIES)
56 |
--------------------------------------------------------------------------------
/indi-driver/cloud-rain-monitor/cmake_modules/FindAPOGEE.cmake:
--------------------------------------------------------------------------------
1 | # - Try to find Apogee Instruments Library
2 | # Once done this will define
3 | #
4 | # APOGEE_FOUND - system has APOGEE
5 | # APOGEE_INCLUDE_DIR - the APOGEE include directory
6 | # APOGEE_LIBRARY - Link these to use APOGEE
7 |
8 | # Copyright (c) 2008, Jasem Mutlaq
9 | # Based on FindLibfacile by Carsten Niehaus,
10 | #
11 | # Redistribution and use is allowed according to the terms of the BSD license.
12 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file.
13 |
14 | if (APOGEE_INCLUDE_DIR AND APOGEE_LIBRARY)
15 |
16 | # in cache already
17 | set(APOGEE_FOUND TRUE)
18 | message(STATUS "Found libapogee: ${APOGEE_LIBRARY}")
19 |
20 | else (APOGEE_INCLUDE_DIR AND APOGEE_LIBRARY)
21 |
22 | find_path(APOGEE_INCLUDE_DIR ApogeeCam.h
23 | PATH_SUFFIXES libapogee
24 | ${_obIncDir}
25 | ${GNUWIN32_DIR}/include
26 | )
27 |
28 | # Find Apogee Library
29 | find_library(APOGEE_LIBRARY NAMES apogee
30 | PATHS
31 | ${_obLinkDir}
32 | ${GNUWIN32_DIR}/lib
33 | )
34 |
35 | if(APOGEE_INCLUDE_DIR AND APOGEE_LIBRARY)
36 | set(APOGEE_FOUND TRUE)
37 | else (APOGEE_INCLUDE_DIR AND APOGEE_LIBRARY)
38 | set(APOGEE_FOUND FALSE)
39 | endif(APOGEE_INCLUDE_DIR AND APOGEE_LIBRARY)
40 |
41 | if (APOGEE_FOUND)
42 | if (NOT APOGEE_FIND_QUIETLY)
43 | message(STATUS "Found APOGEE: ${APOGEE_LIBRARY}")
44 | endif (NOT APOGEE_FIND_QUIETLY)
45 | else (APOGEE_FOUND)
46 | if (APOGEE_FIND_REQUIRED)
47 | message(FATAL_ERROR "libapogee not found. Cannot compile Apogee CCD Driver. Please install libapogee and try again. http://www.indilib.org")
48 | endif (APOGEE_FIND_REQUIRED)
49 | endif (APOGEE_FOUND)
50 |
51 | mark_as_advanced(APOGEE_INCLUDE_DIR APOGEE_LIBRARY)
52 |
53 | endif (APOGEE_INCLUDE_DIR AND APOGEE_LIBRARY)
54 |
--------------------------------------------------------------------------------
/indi-driver/cloud-rain-monitor/cmake_modules/FindMODBUS.cmake:
--------------------------------------------------------------------------------
1 | # - Try to find libmodbus
2 | # Once done this will define
3 | #
4 | # MODBUS_FOUND - system has MODBUS
5 | # MODBUS_INCLUDE_DIR - the MODBUS include directory
6 | # MODBUS_LIBRARIES - Link these to use MODBUS
7 |
8 | # Copyright (c) 2006, Jasem Mutlaq
9 | # Based on FindLibfacile by Carsten Niehaus,
10 | #
11 | # Redistribution and use is allowed according to the terms of the BSD license.
12 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file.
13 |
14 | if (MODBUS_INCLUDE_DIR AND MODBUS_LIBRARIES)
15 |
16 | # in cache already
17 | set(MODBUS_FOUND TRUE)
18 | message(STATUS "Found libmodbus: ${MODBUS_LIBRARIES}")
19 |
20 | else (MODBUS_INCLUDE_DIR AND MODBUS_LIBRARIES)
21 |
22 | find_path(MODBUS_INCLUDE_DIR modbus.h
23 | PATH_SUFFIXES modbus
24 | ${_obIncDir}
25 | ${GNUWIN32_DIR}/include
26 | )
27 |
28 | find_library(MODBUS_LIBRARIES NAMES modbus
29 | PATHS
30 | ${_obLinkDir}
31 | ${GNUWIN32_DIR}/lib
32 | )
33 |
34 | set(CMAKE_REQUIRED_INCLUDES ${MODBUS_INCLUDE_DIR})
35 | set(CMAKE_REQUIRED_LIBRARIES ${MODBUS_LIBRARIES})
36 |
37 | if(MODBUS_INCLUDE_DIR AND MODBUS_LIBRARIES)
38 | set(MODBUS_FOUND TRUE)
39 | else (MODBUS_INCLUDE_DIR AND MODBUS_LIBRARIES)
40 | set(MODBUS_FOUND FALSE)
41 | endif(MODBUS_INCLUDE_DIR AND MODBUS_LIBRARIES)
42 |
43 | if (MODBUS_FOUND)
44 | if (NOT MODBUS_FIND_QUIETLY)
45 | message(STATUS "Found libmodbus: ${MODBUS_LIBRARIES}")
46 | endif (NOT MODBUS_FIND_QUIETLY)
47 | else (MODBUS_FOUND)
48 | if (MODBUS_FIND_REQUIRED)
49 | message(FATAL_ERROR "libmodbus not found. Please install libmodbus-devel. https://launchpad.net/libmodbus/")
50 | endif (MODBUS_FIND_REQUIRED)
51 | endif (MODBUS_FOUND)
52 |
53 | mark_as_advanced(MODBUS_INCLUDE_DIR MODBUS_LIBRARIES)
54 |
55 | endif (MODBUS_INCLUDE_DIR AND MODBUS_LIBRARIES)
56 |
57 |
--------------------------------------------------------------------------------
/indi-driver/cloud-rain-monitor/cmake_modules/FindFISHCAMP.cmake:
--------------------------------------------------------------------------------
1 | # - Try to find FISHCAMP CCD
2 | # Once done this will define
3 | #
4 | # FISHCAMP_FOUND - system has FISHCAMP
5 | # FISHCAMP_LIBRARIES - Link these to use FISHCAMP
6 | # FISHCAMP_INCLUDE_DIR - Fishcamp include directory
7 |
8 | # Copyright (c) 2006, Jasem Mutlaq
9 | # Based on FindLibfacile by Carsten Niehaus,
10 | #
11 | # Redistribution and use is allowed according to the terms of the BSD license.
12 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file.
13 |
14 | if (FISHCAMP_LIBRARIES AND FISHCAMP_INCLUDE_DIR)
15 |
16 | # in cache already
17 | set(FISHCAMP_FOUND TRUE)
18 | message(STATUS "Found FISHCAMP: ${FISHCAMP_LIBRARIES}")
19 |
20 | else (FISHCAMP_LIBRARIES AND FISHCAMP_INCLUDE_DIR)
21 |
22 | find_library(FISHCAMP_LIBRARIES NAMES fishcamp
23 | PATHS
24 | ${_obLinkDir}
25 | ${GNUWIN32_DIR}/lib
26 | )
27 |
28 | find_path(FISHCAMP_INCLUDE_DIR fishcamp.h
29 | PATH_SUFFIXES libfishcamp
30 | ${_obIncDir}
31 | ${GNUWIN32_DIR}/include
32 | )
33 |
34 | set(CMAKE_REQUIRED_LIBRARIES ${FISHCAMP_LIBRARIES})
35 |
36 | if(FISHCAMP_LIBRARIES AND FISHCAMP_INCLUDE_DIR)
37 | set(FISHCAMP_FOUND TRUE)
38 | else (FISHCAMP_LIBRARIES AND FISHCAMP_INCLUDE_DIR)
39 | set(FISHCAMP_FOUND FALSE)
40 | endif(FISHCAMP_LIBRARIES AND FISHCAMP_INCLUDE_DIR)
41 |
42 | if (FISHCAMP_FOUND)
43 | if (NOT FISHCAMP_FIND_QUIETLY)
44 | message(STATUS "Found FISHCAMP: ${FISHCAMP_LIBRARIES}")
45 | endif (NOT FISHCAMP_FIND_QUIETLY)
46 | else (FISHCAMP_FOUND)
47 | if (FISHCAMP_FIND_REQUIRED)
48 | message(FATAL_ERROR "FISHCAMP not found. Please install FISHCAMP library. http://www.indilib.org")
49 | endif (FISHCAMP_FIND_REQUIRED)
50 | endif (FISHCAMP_FOUND)
51 |
52 | mark_as_advanced(FISHCAMP_LIBRARIES FISHCAMP_INCLUDE_DIR)
53 |
54 | endif (FISHCAMP_LIBRARIES AND FISHCAMP_INCLUDE_DIR)
55 |
--------------------------------------------------------------------------------
/indi-driver/cloud-rain-monitor/cloudrainmonitor.h:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | Copyright(c) 2016 Derek OKeeffe. All rights reserved.
3 |
4 | INDI driver for a Cloud and rain monitor for an astronomical observatory
5 |
6 | This program is free software; you can redistribute it and/or modify it
7 | under the terms of the GNU General Public License as published by the Free
8 | Software Foundation; either version 2 of the License, or (at your option)
9 | any later version.
10 |
11 | This program is distributed in the hope that it will be useful, but WITHOUT
12 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 | more details.
15 |
16 | You should have received a copy of the GNU Library General Public License
17 | along with this library; see the file COPYING.LIB. If not, write to
18 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 | Boston, MA 02110-1301, USA.
20 |
21 | The full GNU General Public License is included in this distribution in the
22 | file called LICENSE.
23 | *******************************************************************************/
24 |
25 | #ifndef INDI_CLOUDRAINMONITOR_H
26 | #define INDI_CLOUDRAINMONITOR_H
27 |
28 | #include "indiweather.h"
29 |
30 | class IndiCloudRainMonitor : public INDI::Weather
31 | {
32 | public:
33 | IndiCloudRainMonitor();
34 | virtual ~IndiCloudRainMonitor();
35 |
36 | // Generic indi device entries
37 | bool Connect();
38 | bool Disconnect();
39 | const char *getDefaultName();
40 |
41 | virtual bool initProperties();
42 | virtual void ISGetProperties (const char *dev);
43 | virtual bool ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n);
44 |
45 | protected:
46 | virtual IPState updateWeather();
47 | virtual bool saveConfigItems(FILE *fp);
48 |
49 | private:
50 | IText httpEndpointT[1];
51 | ITextVectorProperty httpEndpointTP;
52 |
53 | };
54 |
55 | #endif // INDI_CLOUDRAINMONITOR_H
56 |
--------------------------------------------------------------------------------
/device/arduino/SensorReader/SensorReader.ino:
--------------------------------------------------------------------------------
1 | /*
2 | * Arduino firmware for a basic weather station for an astronomical observatory.
3 | * Sends sensor readings from a MLX90614 IR sensor and a rain sensor.
4 | * Sends firmata messages as json strings once per second.
5 | *
6 | * Uses Adafruit's Adafruit_MLX90614 library and wiring, see https://learn.adafruit.com/using-melexis-mlx90614-non-contact-sensors/wiring-and-test
7 | *
8 | * PARTS:
9 | * 1 x Arduino nano (http://www.dx.com/p/arduino-nano-v3-0-81877#.ViKE2RCrRE4)
10 | * 1 x RG-11 Rain sensor
11 | * 1 x MLX90614 IR temp sensor
12 | *
13 | * Wiring:
14 | * Rain sensor:
15 | * Relay is attached to pin 8 and acts as a simple on off switch. Ensure you wire with a pull-down resistor. If you dont know what that means goodle 'arduino button' to see how a basic switch/button is wired.
16 | * MLX90614
17 | * Wired to A4 and A5 with 2 pull up resistors (see https://learn.adafruit.com/using-melexis-mlx90614-non-contact-sensors/wiring-and-test)
18 | *
19 | * Sample json message
20 | * {"rain":false,"sky":20.93,"ambient":21.93}
21 | *
22 | */
23 | #include
24 | #include
25 | #include
26 | #include
27 |
28 | #define RAIN_SENSOR_PIN 8
29 |
30 | Adafruit_MLX90614 mlx = Adafruit_MLX90614();
31 |
32 | /**
33 | * Startup firmata and the mlx
34 | */
35 | void setup() {
36 | Firmata.setFirmwareVersion(FIRMATA_FIRMWARE_MAJOR_VERSION, FIRMATA_FIRMWARE_MINOR_VERSION);
37 | Firmata.begin(57600);
38 | pinMode(8,INPUT);
39 | mlx.begin();
40 | }
41 |
42 | /**
43 | * Once per second take readings from sensors, build a json string and send over firmata.
44 | */
45 | void loop()
46 | {
47 | char charBuf[50];
48 | String message = "{\"rain\":";
49 | if(digitalRead(RAIN_SENSOR_PIN)==HIGH) {
50 | message += "true,";
51 | } else {
52 | message += "false,";
53 | }
54 | message += "\"sky\":";
55 | message += mlx.readObjectTempC();
56 | message += ",\"ambient\":";
57 | message += mlx.readAmbientTempC();
58 | message += "}";
59 | message.toCharArray(charBuf, 50);
60 | Firmata.sendString(charBuf);
61 | delay(1000);
62 | }
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/indi-driver/cloud-rain-monitor/cmake_modules/FindAIOUSB.cmake:
--------------------------------------------------------------------------------
1 | # - Try to find libaiousb
2 | # Once done this will define
3 | #
4 | # AIOUSB_FOUND - system has AIOUSB
5 | # AIOUSB_INCLUDE_DIR - the AIOUSB include directory
6 | # AIOUSB_LIBRARIES - Link these to use AIOUSB (C)
7 | # AIOUSB_CPP_LIBRARIES - Link these to use AIOUSB (C++)
8 |
9 | # Copyright (c) 2006, Jasem Mutlaq
10 | # Based on FindLibfacile by Carsten Niehaus,
11 | #
12 | # Redistribution and use is allowed according to the terms of the BSD license.
13 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file.
14 |
15 | if (AIOUSB_INCLUDE_DIR AND AIOUSB_LIBRARIES AND AIOUSB_CPP_LIBRARIES)
16 |
17 | # in cache already
18 | set(AIOUSB_FOUND TRUE)
19 | message(STATUS "Found libaiusb: ${AIOUSB_LIBRARIES}")
20 | message(STATUS "Found libaiusbcpp: ${AIOUSB_CPP_LIBRARIES}")
21 |
22 | else (AIOUSB_INCLUDE_DIR AND AIOUSB_LIBRARIES AND AIOUSB_CPP_LIBRARIES)
23 |
24 | find_path(AIOUSB_INCLUDE_DIR aiousb.h
25 | ${_obIncDir}
26 | ${GNUWIN32_DIR}/include
27 | )
28 |
29 | find_library(AIOUSB_LIBRARIES NAMES aiousb
30 | PATHS
31 | ${_obLinkDir}
32 | ${GNUWIN32_DIR}/lib
33 | )
34 |
35 | find_library(AIOUSB_CPP_LIBRARIES NAMES aiousbcpp
36 | PATHS
37 | ${_obLinkDir}
38 | ${GNUWIN32_DIR}/lib
39 | )
40 |
41 | if(AIOUSB_INCLUDE_DIR AND AIOUSB_LIBRARIES AND AIOUSB_CPP_LIBRARIES)
42 | set(AIOUSB_FOUND TRUE)
43 | else (AIOUSB_INCLUDE_DIR AND AIOUSB_LIBRARIES AND AIOUSB_CPP_LIBRARIES)
44 | set(AIOUSB_FOUND FALSE)
45 | endif(AIOUSB_INCLUDE_DIR AND AIOUSB_LIBRARIES AND AIOUSB_CPP_LIBRARIES)
46 |
47 | if (AIOUSB_FOUND)
48 | if (NOT AIOUSB_FIND_QUIETLY)
49 | message(STATUS "Found libaiousb: ${AIOUSB_LIBRARIES}")
50 | message(STATUS "Found libaiusbcpp: ${AIOUSB_CPP_LIBRARIES}")
51 | endif (NOT AIOUSB_FIND_QUIETLY)
52 | else (AIOUSB_FOUND)
53 | if (AIOUSB_FIND_REQUIRED)
54 | message(FATAL_ERROR "libaiousb not found. Please install libaiousb. https://www.accesio.com")
55 | endif (AIOUSB_FIND_REQUIRED)
56 | endif (AIOUSB_FOUND)
57 |
58 | mark_as_advanced(AIOUSB_INCLUDE_DIR AIOUSB_LIBRARIES AIOUSB_CPP_LIBRARIES)
59 |
60 | endif (AIOUSB_INCLUDE_DIR AND AIOUSB_LIBRARIES AND AIOUSB_CPP_LIBRARIES)
61 |
62 |
--------------------------------------------------------------------------------
/indi-driver/cloud-rain-monitor/cmake_modules/FindCFITSIO.cmake:
--------------------------------------------------------------------------------
1 | # - Try to find CFITSIO
2 | # Once done this will define
3 | #
4 | # CFITSIO_FOUND - system has CFITSIO
5 | # CFITSIO_INCLUDE_DIR - the CFITSIO include directory
6 | # CFITSIO_LIBRARIES - Link these to use CFITSIO
7 | # CFITSIO_VERSION_STRING - Human readable version number of cfitsio
8 | # CFITSIO_VERSION_MAJOR - Major version number of cfitsio
9 | # CFITSIO_VERSION_MINOR - Minor version number of cfitsio
10 |
11 | # Copyright (c) 2006, Jasem Mutlaq
12 | # Based on FindLibfacile by Carsten Niehaus,
13 | #
14 | # Redistribution and use is allowed according to the terms of the BSD license.
15 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file.
16 |
17 | if (CFITSIO_INCLUDE_DIR AND CFITSIO_LIBRARIES)
18 |
19 | # in cache already
20 | set(CFITSIO_FOUND TRUE)
21 | message(STATUS "Found CFITSIO: ${CFITSIO_LIBRARIES}")
22 |
23 |
24 | else (CFITSIO_INCLUDE_DIR AND CFITSIO_LIBRARIES)
25 |
26 | # JM: Packages from different distributions have different suffixes
27 | find_path(CFITSIO_INCLUDE_DIR fitsio.h
28 | PATH_SUFFIXES libcfitsio3 libcfitsio0 cfitsio
29 | ${_obIncDir}
30 | ${GNUWIN32_DIR}/include
31 | )
32 |
33 | find_library(CFITSIO_LIBRARIES NAMES cfitsio
34 | PATHS
35 | ${_obLinkDir}
36 | ${GNUWIN32_DIR}/lib
37 | )
38 |
39 | if(CFITSIO_INCLUDE_DIR AND CFITSIO_LIBRARIES)
40 | set(CFITSIO_FOUND TRUE)
41 | else (CFITSIO_INCLUDE_DIR AND CFITSIO_LIBRARIES)
42 | set(CFITSIO_FOUND FALSE)
43 | endif(CFITSIO_INCLUDE_DIR AND CFITSIO_LIBRARIES)
44 |
45 |
46 | if (CFITSIO_FOUND)
47 |
48 | # Find the version of the cfitsio header
49 | execute_process(COMMAND egrep CFITSIO_VERSION ${CFITSIO_INCLUDE_DIR}/fitsio.h
50 | OUTPUT_VARIABLE CFITSIO_VERSION_STRING)
51 | STRING(REGEX REPLACE "[^0-9.]" "" CFITSIO_VERSION_STRING ${CFITSIO_VERSION_STRING})
52 | STRING(REGEX REPLACE "^([0-9]+)[.]([0-9]+)" "\\1" CFITSIO_VERSION_MAJOR ${CFITSIO_VERSION_STRING})
53 | STRING(REGEX REPLACE "^([0-9]+)[.]([0-9]+)" "\\2" CFITSIO_VERSION_MINOR ${CFITSIO_VERSION_STRING})
54 |
55 | if (NOT CFITSIO_FIND_QUIETLY)
56 | message(STATUS "Found CFITSIO ${CFITSIO_VERSION_STRING}: ${CFITSIO_LIBRARIES}")
57 | endif (NOT CFITSIO_FIND_QUIETLY)
58 | else (CFITSIO_FOUND)
59 | if (CFITSIO_FIND_REQUIRED)
60 | message(STATUS "CFITSIO not found.")
61 | endif (CFITSIO_FIND_REQUIRED)
62 | endif (CFITSIO_FOUND)
63 |
64 | mark_as_advanced(CFITSIO_INCLUDE_DIR CFITSIO_LIBRARIES)
65 |
66 | endif (CFITSIO_INCLUDE_DIR AND CFITSIO_LIBRARIES)
67 |
--------------------------------------------------------------------------------
/indi-driver/cloud-rain-monitor/cmake_modules/FindALUT.cmake:
--------------------------------------------------------------------------------
1 | # - Locate ALUT
2 | # This module defines
3 | # ALUT_LIBRARY
4 | # ALUT_FOUND, if false, do not try to link to OpenAL
5 | # ALUT_INCLUDE_DIR, where to find the headers
6 | #
7 | # $OPENALDIR is an environment variable that would
8 | # correspond to the ./configure --prefix=$OPENALDIR
9 | # used in building OpenAL.
10 | #
11 | # Created by Bryan Donlan, based on the FindOpenAL.cmake module by Eric Wang.
12 |
13 | FIND_PATH(ALUT_INCLUDE_DIR alut.h
14 | $ENV{OPENALDIR}/include
15 | ~/Library/Frameworks/OpenAL.framework/Headers
16 | /Library/Frameworks/OpenAL.framework/Headers
17 | /System/Library/Frameworks/OpenAL.framework/Headers # Tiger
18 | /usr/local/include/AL
19 | /usr/local/include/OpenAL
20 | /usr/local/include
21 | /usr/include/AL
22 | /usr/include/OpenAL
23 | /usr/include
24 | /sw/include/AL # Fink
25 | /sw/include/OpenAL
26 | /sw/include
27 | /opt/local/include/AL # DarwinPorts
28 | /opt/local/include/OpenAL
29 | /opt/local/include
30 | /opt/csw/include/AL # Blastwave
31 | /opt/csw/include/OpenAL
32 | /opt/csw/include
33 | /opt/include/AL
34 | /opt/include/OpenAL
35 | /opt/include
36 | )
37 | # I'm not sure if I should do a special casing for Apple. It is
38 | # unlikely that other Unix systems will find the framework path.
39 | # But if they do ([Next|Open|GNU]Step?),
40 | # do they want the -framework option also?
41 | IF(${ALUT_INCLUDE_DIR} MATCHES ".framework")
42 | STRING(REGEX REPLACE "(.*)/.*\\.framework/.*" "\\1" ALUT_FRAMEWORK_PATH_TMP ${ALUT_INCLUDE_DIR})
43 | IF("${ALUT_FRAMEWORK_PATH_TMP}" STREQUAL "/Library/Frameworks"
44 | OR "${ALUT_FRAMEWORK_PATH_TMP}" STREQUAL "/System/Library/Frameworks"
45 | )
46 | # String is in default search path, don't need to use -F
47 | SET (ALUT_LIBRARY "-framework OpenAL" CACHE STRING "OpenAL framework for OSX")
48 | ELSE("${ALUT_FRAMEWORK_PATH_TMP}" STREQUAL "/Library/Frameworks"
49 | OR "${ALUT_FRAMEWORK_PATH_TMP}" STREQUAL "/System/Library/Frameworks"
50 | )
51 | # String is not /Library/Frameworks, need to use -F
52 | SET(ALUT_LIBRARY "-F${ALUT_FRAMEWORK_PATH_TMP} -framework OpenAL" CACHE STRING "OpenAL framework for OSX")
53 | ENDIF("${ALUT_FRAMEWORK_PATH_TMP}" STREQUAL "/Library/Frameworks"
54 | OR "${ALUT_FRAMEWORK_PATH_TMP}" STREQUAL "/System/Library/Frameworks"
55 | )
56 | # Clear the temp variable so nobody can see it
57 | SET(ALUT_FRAMEWORK_PATH_TMP "" CACHE INTERNAL "")
58 |
59 | ELSE(${ALUT_INCLUDE_DIR} MATCHES ".framework")
60 | FIND_LIBRARY(ALUT_LIBRARY
61 | NAMES alut
62 | PATHS
63 | $ENV{OPENALDIR}/lib
64 | $ENV{OPENALDIR}/libs
65 | /usr/local/lib
66 | /usr/lib
67 | /sw/lib
68 | /opt/local/lib
69 | /opt/csw/lib
70 | /opt/lib
71 | )
72 | ENDIF(${ALUT_INCLUDE_DIR} MATCHES ".framework")
73 |
74 | SET(ALUT_FOUND "NO")
75 | IF(ALUT_LIBRARY)
76 | SET(ALUT_FOUND "YES")
77 | ENDIF(ALUT_LIBRARY)
78 |
--------------------------------------------------------------------------------
/device/rpi/web/charts.py:
--------------------------------------------------------------------------------
1 | import os
2 | import matplotlib
3 | import sqlite3
4 | matplotlib.use('Agg')
5 | from matplotlib import pyplot as plt
6 | import pandas as pd
7 | import math
8 |
9 | class ChartGenerator:
10 |
11 | NAME = 'ChartGenerator'
12 | HISTORICAL_DATA_SQL = "SELECT rain,sky_temperature, ambient_temperature, date_sensor_read FROM weather_sensor WHERE date_sensor_read >= date('now','-24 hour')"
13 | MIN_SKY_TEMP_HISTORY = "SELECT min(sky_temperature) as min_sky_temperature FROM weather_sensor WHERE date_sensor_read >= date('now','-10 day')"
14 |
15 | def __init__(self, root_dir):
16 | self.root_dir = root_dir
17 | plt.rcParams["figure.figsize"] = (10, 3)
18 | plt.style.use('bmh')
19 | self._conn = sqlite3.connect('weather_sensor.db')
20 |
21 |
22 | def _calculate_cloud_cover(self, sky, ambient, recent_clear_sky_temp):
23 | '''
24 | :param sky:
25 | :param ambient:
26 | :param recent_clear_sky_temp
27 | :return:
28 | '''
29 | print(recent_clear_sky_temp)
30 | scaling_factor = 100 / abs(recent_clear_sky_temp)
31 | x = abs(((sky * -1) * scaling_factor) - 75)
32 | if x < 0:
33 | return 0
34 | elif x > 100:
35 | return 100
36 | else:
37 | return x
38 |
39 | def generate_cloud_chart(self):
40 | weather = self._last_24hrs_data()
41 | recent_clear_sky_temp = self._min_sky_last_month()
42 | weather['CloudCover'] = weather.apply(lambda x: self._calculate_cloud_cover(x['sky_temperature'], x['ambient_temperature'], recent_clear_sky_temp), axis=1)
43 | weather['Rain'] = weather[['rain']]*100
44 | rain_clouds = weather.loc[:,['Rain','CloudCover']]
45 | rain_clouds.resample('5T').mean().plot();
46 | ax = rain_clouds.plot();
47 | ax.set_ylabel("%")
48 | plt.savefig(os.path.join(self.root_dir, './cloud.png'), bbox_inches='tight')
49 | plt.clf()
50 | plt.close()
51 |
52 | def _last_24hrs_data(self):
53 | conn = sqlite3.connect('weather_sensor.db')
54 | with conn:
55 | weather = pd.read_sql(self.HISTORICAL_DATA_SQL, self._conn)
56 | weather = weather.rename(columns={'date_sensor_read': 'Time'})
57 | weather.index = pd.to_datetime(weather.Time)
58 | return weather
59 |
60 | def _min_sky_last_month(self):
61 | conn = sqlite3.connect('weather_sensor.db')
62 | with conn:
63 | cursor=conn.cursor()
64 | cursor.execute(self.MIN_SKY_TEMP_HISTORY)
65 | mintemp = cursor.fetchone()[0]
66 | if mintemp > -5 or mintemp < -25:
67 | return -20 #-20 is a good guess for 100% clear sky
68 | else:
69 | return mintemp
70 |
71 | def generate_temperature_chart(self):
72 | weather = self._last_24hrs_data()
73 | temperatures = weather.loc[:, ['sky_temperature','ambient_temperature']]
74 | ax = temperatures.plot();
75 | ax.set_ylabel("Temp Deg C")
76 | plt.savefig(os.path.join(self.root_dir, './temperature.png'), bbox_inches='tight')
77 | plt.clf()
78 | plt.close()
79 |
--------------------------------------------------------------------------------
/indi-driver/cloud-rain-monitor/cmake_modules/FindGPHOTO2.cmake:
--------------------------------------------------------------------------------
1 | # - Find the native sqlite3 includes and library
2 | #
3 | # This module defines
4 | # GPHOTO2_INCLUDE_DIR, where to find libgphoto2 header files
5 | # GPHOTO2_LIBRARIES, the libraries to link against to use libgphoto2
6 | # GPHOTO2_FOUND, If false, do not try to use libgphoto2.
7 | # GPHOTO2_VERSION_STRING, e.g. 2.4.14
8 | # GPHOTO2_VERSION_MAJOR, e.g. 2
9 | # GPHOTO2_VERSION_MINOR, e.g. 4
10 | # GPHOTO2_VERSION_PATCH, e.g. 14
11 | #
12 | # also defined, but not for general use are
13 | # GPHOTO2_LIBRARY, where to find the sqlite3 library.
14 |
15 |
16 | #=============================================================================
17 | # Copyright 2010 henrik andersson
18 | #=============================================================================
19 |
20 | SET(GPHOTO2_FIND_REQUIRED ${Gphoto2_FIND_REQUIRED})
21 |
22 | find_path(GPHOTO2_INCLUDE_DIR gphoto2/gphoto2.h)
23 | mark_as_advanced(GPHOTO2_INCLUDE_DIR)
24 |
25 | set(GPHOTO2_NAMES ${GPHOTO2_NAMES} gphoto2 libgphoto2)
26 | set(GPHOTO2_PORT_NAMES ${GPHOTO2_PORT_NAMES} gphoto2_port libgphoto2_port)
27 | find_library(GPHOTO2_LIBRARY NAMES ${GPHOTO2_NAMES} )
28 | find_library(GPHOTO2_PORT_LIBRARY NAMES ${GPHOTO2_PORT_NAMES} )
29 | mark_as_advanced(GPHOTO2_LIBRARY)
30 | mark_as_advanced(GPHOTO2_PORT_LIBRARY)
31 |
32 | # Detect libgphoto2 version
33 | FIND_PROGRAM(GPHOTO2CONFIG_EXECUTABLE NAMES gphoto2-config)
34 | IF(GPHOTO2CONFIG_EXECUTABLE)
35 | EXEC_PROGRAM(${GPHOTO2CONFIG_EXECUTABLE} ARGS --version RETURN_VALUE _return_VALUE OUTPUT_VARIABLE GPHOTO2_VERSION)
36 | string(REGEX REPLACE "^.*libgphoto2 ([0-9]+).*$" "\\1" GPHOTO2_VERSION_MAJOR "${GPHOTO2_VERSION}")
37 | string(REGEX REPLACE "^.*libgphoto2 [0-9]+\\.([0-9]+).*$" "\\1" GPHOTO2_VERSION_MINOR "${GPHOTO2_VERSION}")
38 | string(REGEX REPLACE "^.*libgphoto2 [0-9]+\\.[0-9]+\\.([0-9]+).*$" "\\1" GPHOTO2_VERSION_PATCH "${GPHOTO2_VERSION}")
39 |
40 | set(GPHOTO2_VERSION_STRING "${GPHOTO2_VERSION_MAJOR}.${GPHOTO2_VERSION_MINOR}.${GPHOTO2_VERSION_PATCH}")
41 | ENDIF(GPHOTO2CONFIG_EXECUTABLE)
42 |
43 | # handle the QUIETLY and REQUIRED arguments and set GPHOTO2_FOUND to TRUE if
44 | # all listed variables are TRUE
45 | include(FindPackageHandleStandardArgs)
46 | find_package_handle_standard_args(GPHOTO2 DEFAULT_MSG GPHOTO2_LIBRARY GPHOTO2_INCLUDE_DIR)
47 |
48 | IF(GPHOTO2_FOUND)
49 | SET(Gphoto2_LIBRARIES ${GPHOTO2_LIBRARY} ${GPHOTO2_PORT_LIBRARY})
50 | SET(Gphoto2_INCLUDE_DIRS ${GPHOTO2_INCLUDE_DIR})
51 |
52 | # libgphoto2 dynamically loads and unloads usb library
53 | # without calling any cleanup functions (since they are absent from libusb-0.1).
54 | # This leaves usb event handling threads running with invalid callback and return addresses,
55 | # which causes a crash after any usb event is generated, at least in Mac OS X.
56 | # libusb1 backend does correctly call exit function, but ATM it crashes anyway.
57 | # Workaround is to link against libusb so that it wouldn't get unloaded.
58 | IF(APPLE)
59 | find_library(USB_LIBRARY NAMES usb-1.0 libusb-1.0)
60 | mark_as_advanced(USB_LIBRARY)
61 | IF(USB_LIBRARY)
62 | SET(Gphoto2_LIBRARIES ${Gphoto2_LIBRARIES} ${USB_LIBRARY})
63 | ENDIF(USB_LIBRARY)
64 | ENDIF(APPLE)
65 |
66 | ENDIF(GPHOTO2_FOUND)
67 |
--------------------------------------------------------------------------------
/device/rpi/web/weatherMicroService.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import sqlite3
4 | from bottle import route, run, debug, error, request, static_file
5 | from collector import Collector
6 | from charts import ChartGenerator
7 |
8 | '''
9 | A very simple python bottle micro service for weather
10 | '''
11 |
12 | @route('/weather/current')
13 | def current_weather():
14 | '''
15 | GET the current weather state. the latest reading persisted in the DB.
16 | TODO: If the reading is older than 5min then return 404?
17 | :return:
18 | '''
19 | conn = sqlite3.connect('weather_sensor.db')
20 | c = conn.cursor()
21 | c.execute("SELECT rain,sky_temperature,ambient_temperature, date_sensor_read FROM weather_sensor order by id desc limit 1")
22 | result = c.fetchall()
23 | c.close()
24 | sky_temp = result[0][1]
25 | outside_temp = result[0][2]
26 | reading_timestamp = result[0][3]
27 | #rain = (result[0][0] == 1 and sky_temp - outside_temp > -20 and sky_temp > -10) #hack to prevent a true for rain when the sky is clear. Sometimes dew triggers a false positive for rain
28 | rain = result[0][0] == 1
29 | return {'rain': rain, 'skyTemp': sky_temp, 'outsideTemp': outside_temp, 'readingTimestamp': reading_timestamp}
30 |
31 | @route('/weather/history')
32 | def historical_weather():
33 | '''
34 | Return historical weather data. Pass days=x as a qurey string arg to get the previous x days data.
35 | :return:
36 | '''
37 | conn = sqlite3.connect('weather_sensor.db')
38 | c = conn.cursor()
39 | days = request.query.days or 1
40 | c.execute("SELECT rain,sky_temperature, ambient_temperature, date_sensor_read FROM weather_sensor WHERE date_sensor_read >= date('now','-{} day')".format(days))
41 | result = c.fetchall()
42 | c.close()
43 | history = []
44 | count =0
45 | for row in result:
46 | count += 1
47 | history.append({'rain': row[0] == 1, 'skyTemp': row[1], 'outsideTemp': row[2], 'readingTimestamp' : row[3]})
48 | return {'count': count, 'history': history}
49 |
50 | @route('/weather/chart/')
51 | def cloud_chart(chart):
52 | if 'cloud.png' in chart:
53 | _chartGenerator.generate_cloud_chart()
54 | else:
55 | _chartGenerator.generate_temperature_chart()
56 | return static_file(chart, root='/tmp')
57 |
58 | @route('/weather/safety')
59 | def safety():
60 | '''
61 | GET the current weather state. the latest reading persisted in the DB.
62 | TODO: If the reading is older than 5min then return 404?
63 | :return:
64 | '''
65 | conn = sqlite3.connect('weather_sensor.db')
66 | c = conn.cursor()
67 | c.execute("SELECT rain,sky_temperature,ambient_temperature, date_sensor_read FROM weather_sensor order by id desc limit 1")
68 | result = c.fetchall()
69 | c.close()
70 | sky_temp = result[0][1]
71 | outside_temp = result[0][2]
72 | reading_timestamp = result[0][3]
73 | raining = (result[0][0] == 1 and sky_temp - outside_temp > -20 and sky_temp > -10) #hack to prevent a true for rain when the sky is clear. Sometimes dew triggers a false positive for rain
74 | roof_status = {'open_ok': 1, 'reasons': ''}
75 | if sky_temp - outside_temp > -17:
76 | roof_status = {'open_ok': 0, 'reasons': 'Cloudy'}
77 | if raining:
78 | roof_status = {'open_ok': 0, 'reasons': 'Raining'}
79 | return {'timestamp_utc': reading_timestamp, 'roof_status': roof_status}
80 |
81 |
82 | _chartGenerator = ChartGenerator('/tmp')
83 | con = sqlite3.connect('weather_sensor.db')
84 | con.execute("CREATE TABLE IF NOT EXISTS weather_sensor (id INTEGER PRIMARY KEY, rain bool NOT NULL, sky_temperature NUMBER NOT NULL, ambient_temperature NUMBER NOT NULL, date_sensor_read DATETIME DEFAULT CURRENT_TIMESTAMP)")
85 | con.commit()
86 | collector = Collector('/dev/ttyACM0')
87 | run(host='0.0.0.0', port=8080)
88 |
--------------------------------------------------------------------------------
/device/rpi/web/collector.py:
--------------------------------------------------------------------------------
1 | from pyfirmata import Arduino, util
2 | import pyfirmata
3 | import sqlite3
4 | import json
5 | import time
6 |
7 |
8 | class Collector():
9 | """
10 | Handles the communication to arduino SensorReader
11 | The arduino firmware publishes messages using firmata once per second with sensor readings.
12 | This class is responsible for collection and persistance of readings.
13 | AttachTo: ""
14 | """
15 |
16 | NAME = "Collector"
17 |
18 | def __init__(self, port):
19 | '''
20 | Constructor. Adds the callback handler to accept firmata messages from the arduino board connected to the sensors.
21 | '''
22 | self.last_rain_reading_saved = None;
23 | self.last_sky_temperature_reading_saved = 0;
24 | self.last_ambient_temperature_reading_saved = 0;
25 | self.last_reading_saved_time = time.time()
26 | self.board = Arduino(port)
27 | # start an iterator thread so that serial buffer doesn't overflow
28 | it = util.Iterator(self.board)
29 | it.start()
30 | self.board.add_cmd_handler(pyfirmata.pyfirmata.STRING_DATA, self._messageHandler)
31 |
32 | def _messageHandler(self, *args, **kwargs):
33 | '''
34 | Calback method envoked by the firmata library. Handles the string message sent from the arduino.
35 | Grabs the sensor data from the message and persists in the DB table.
36 | :param args:
37 | :param kwargs:
38 | :return:
39 | '''
40 | readings = json.loads(util.two_byte_iter_to_str(args))
41 | sky_temperature = readings['sky']
42 | ambient_temperature = readings['ambient']
43 | rain = readings['rain']
44 | if self.should_persist_sensor_reading(sky_temperature, ambient_temperature, rain):
45 | conn = sqlite3.connect('weather_sensor.db')
46 | c = conn.cursor()
47 | print('inserting observation')
48 | c.execute("INSERT INTO weather_sensor (rain,sky_temperature,ambient_temperature) VALUES (?,?,?)",
49 | (rain, sky_temperature, ambient_temperature))
50 | c.execute("DELETE FROM weather_sensor WHERE date_sensor_read <= date('now','-365 day')")
51 | print('inserted')
52 | # new_id = c.lastrowid
53 | conn.commit()
54 | self.last_rain_reading_saved = rain
55 | self.last_sky_temperature_reading_saved = sky_temperature
56 | self.last_ambient_temperature_reading_saved = ambient_temperature
57 | self.last_reading_saved_time = time.time()
58 | c.close()
59 |
60 | def update(self):
61 | super(Collector, self).update()
62 |
63 | def writeData(self, data):
64 | self.board.send_sysex(pyfirmata.pyfirmata.STRING_DATA, data)
65 |
66 | def dispose(self):
67 | super(Collector, self).dispose()
68 | try:
69 | self.board.exit()
70 | except AttributeError:
71 | print('exit() raised an AttributeError unexpectedly!')
72 |
73 |
74 | def should_persist_sensor_reading(self, sky_temperature, ambient_temperature, rain):
75 | '''
76 | Returns true if the sensor data should be persisted in the DB.
77 | The rules are if any temp change is more than 1 degree, or the rain state changes
78 | or 60sec have elapsed since the last save
79 | :param sky_temperature:
80 | :param ambient_temperature:
81 | :param rain:
82 | :return:
83 | '''
84 | if abs(sky_temperature - self.last_sky_temperature_reading_saved) > 1 or abs(
85 | ambient_temperature - self.last_ambient_temperature_reading_saved) > 1 or rain != self.last_rain_reading_saved or time.time() - self.last_reading_saved_time > 60:
86 | return True
87 | else:
88 | return False
89 |
--------------------------------------------------------------------------------
/indi-driver/cloud-rain-monitor/cmake_modules/FindOpenAL.cmake:
--------------------------------------------------------------------------------
1 | # Locate OpenAL
2 | # This module defines
3 | # OPENAL_LIBRARY
4 | # OPENAL_FOUND, if false, do not try to link to OpenAL
5 | # OPENAL_INCLUDE_DIR, where to find the headers
6 | #
7 | # $OPENALDIR is an environment variable that would
8 | # correspond to the ./configure --prefix=$OPENALDIR
9 | # used in building OpenAL.
10 | #
11 | # Created by Eric Wing. This was influenced by the FindSDL.cmake module.
12 |
13 | # This makes the presumption that you are include al.h like
14 | # #include "al.h"
15 | # and not
16 | # #include
17 | # The reason for this is that the latter is not entirely portable.
18 | # Windows/Creative Labs does not by default put their headers in AL/ and
19 | # OS X uses the convention .
20 | #
21 | # For Windows, Creative Labs seems to have added a registry key for their
22 | # OpenAL 1.1 installer. I have added that key to the list of search paths,
23 | # however, the key looks like it could be a little fragile depending on
24 | # if they decide to change the 1.00.0000 number for bug fix releases.
25 | # Also, they seem to have laid down groundwork for multiple library platforms
26 | # which puts the library in an extra subdirectory. Currently there is only
27 | # Win32 and I have hardcoded that here. This may need to be adjusted as
28 | # platforms are introduced.
29 | # The OpenAL 1.0 installer doesn't seem to have a useful key I can use.
30 | # I do not know if the Nvidia OpenAL SDK has a registry key.
31 | #
32 | # For OS X, remember that OpenAL was added by Apple in 10.4 (Tiger).
33 | # To support the framework, I originally wrote special framework detection
34 | # code in this module which I have now removed with CMake's introduction
35 | # of native support for frameworks.
36 | # In addition, OpenAL is open source, and it is possible to compile on Panther.
37 | # Furthermore, due to bugs in the initial OpenAL release, and the
38 | # transition to OpenAL 1.1, it is common to need to override the built-in
39 | # framework.
40 | # Per my request, CMake should search for frameworks first in
41 | # the following order:
42 | # ~/Library/Frameworks/OpenAL.framework/Headers
43 | # /Library/Frameworks/OpenAL.framework/Headers
44 | # /System/Library/Frameworks/OpenAL.framework/Headers
45 | #
46 | # On OS X, this will prefer the Framework version (if found) over others.
47 | # People will have to manually change the cache values of
48 | # OPENAL_LIBRARY to override this selection or set the CMake environment
49 | # CMAKE_INCLUDE_PATH to modify the search paths.
50 |
51 | FIND_PATH(OPENAL_INCLUDE_DIR al.h
52 | PATHS
53 | $ENV{OPENALDIR}
54 | NO_DEFAULT_PATH
55 | PATH_SUFFIXES include/AL include/OpenAL include
56 | )
57 |
58 | FIND_PATH(OPENAL_INCLUDE_DIR al.h
59 | PATHS
60 | ~/Library/Frameworks
61 | /Library/Frameworks
62 | /usr/local
63 | /usr
64 | /sw # Fink
65 | /opt/local # DarwinPorts
66 | /opt/csw # Blastwave
67 | /opt
68 | [HKEY_LOCAL_MACHINE\\SOFTWARE\\Creative\ Labs\\OpenAL\ 1.1\ Software\ Development\ Kit\\1.00.0000;InstallDir]
69 | PATH_SUFFIXES include/AL include/OpenAL include
70 | )
71 |
72 | FIND_LIBRARY(OPENAL_LIBRARY
73 | NAMES OpenAL al openal OpenAL32
74 | PATHS
75 | $ENV{OPENALDIR}
76 | NO_DEFAULT_PATH
77 | PATH_SUFFIXES lib64 lib libs64 libs libs/Win32 libs/Win64
78 | )
79 |
80 | FIND_LIBRARY(OPENAL_LIBRARY
81 | NAMES OpenAL al openal OpenAL32
82 | PATHS
83 | ~/Library/Frameworks
84 | /Library/Frameworks
85 | /usr/local
86 | /usr
87 | /sw
88 | /opt/local
89 | /opt/csw
90 | /opt
91 | [HKEY_LOCAL_MACHINE\\SOFTWARE\\Creative\ Labs\\OpenAL\ 1.1\ Software\ Development\ Kit\\1.00.0000;InstallDir]
92 | PATH_SUFFIXES lib64 lib libs64 libs libs/Win32 libs/Win64
93 | )
94 |
95 |
96 | SET(OPENAL_FOUND "NO")
97 | IF(OPENAL_LIBRARY AND OPENAL_INCLUDE_DIR)
98 | SET(OPENAL_FOUND "YES")
99 | ENDIF(OPENAL_LIBRARY AND OPENAL_INCLUDE_DIR)
100 |
101 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # cloud-rain-monitor
2 |
3 | An Arduino firmware, Raspberry PI application and indi-driver for a device to measure rain and cloud cover for an astronomical observatory. Cloud cover is determined by measuring the difference between ambient temperature and sky temperature.
4 |
5 | **Outside**
6 |
7 | 
8 |
9 | **Inside**
10 |
11 | 
12 |
13 | The device offers an HTTP interface to GET current conditions. See below for the full API
14 |
15 | Example request to /weather
16 | ```
17 | {
18 | "outsideTemp": 2.75,
19 | "skyTemp": -21.77,
20 | "readingTimestamp":
21 | "2018-03-25 18:02:46",
22 | "rain": false
23 | }
24 | ```
25 |
26 | Clouds are detected using an Melexis [MLX90614](http://www.melexis.com/Infrared-Thermometer-Sensors/Infrared-Thermometer-Sensors/MLX90614-615.aspx) sensor to measure IR radiation from the sky.
27 | 
28 |
29 | Rain is detected using an [RG-11 rain sensor](http://rainsensors.com/)
30 | 
31 |
32 | An [Indi Driver](http://www.indilib.org/devices/weather-stations.html) for observatory automation is also included.
33 |
34 | 
35 |
36 |
37 | The device and driver is currently used in Ballyhoura Observatory
38 |
39 | 
40 |
41 | # Build notes/instructions
42 |
43 | * 1 Flash the ino file to an arduino nano.
44 |
45 | * 2 Wiring diagram (in progress)
46 |
47 | * 3 Clone this repo to raspberry pi then add a line to /etc/rc.local to start the weather micro service on startup
48 |
49 | ```
50 |
51 | # start the weatherstation
52 | /home/pi/code/github/cloud-rain-monitor/device/rpi/web/weatherMicroService.py &
53 | ```
54 |
55 | # HTTP API
56 |
57 | **Current weather status**
58 | ----
59 |
60 | * **URL**
61 |
62 | /weather/current
63 |
64 | * **Method:**
65 |
66 | `GET`
67 |
68 | * **Success Response:**
69 |
70 | * **Code:** 200
71 | **Content:** `{"outsideTemp": 2.75, "skyTemp": -21.77, "readingTimestamp": "2018-03-25 18:02:46", "rain": false}`
72 |
73 | **Historical weather**
74 | ----
75 |
76 | Returns history for the previous 24 hours
77 |
78 | * **URL**
79 |
80 | /weather/history
81 |
82 | * **Method:**
83 |
84 | `GET`
85 |
86 | * **Success Response:**
87 |
88 | * **Code:** 200
89 | **Content:** `[{"outsideTemp": 2.75, "skyTemp": -21.77, "readingTimestamp": "2018-03-25 18:02:46", "rain": false}, {"outsideTemp": 2.75, "skyTemp": -21.77, "readingTimestamp": "2018-03-25 18:02:46", "rain": false}....]`
90 |
91 |
92 | **Charts**
93 | ----
94 |
95 | Returns an image weather chart
96 |
97 | * **URL**
98 |
99 | /weather/chart/
100 |
101 | * **Method:**
102 |
103 | `GET`
104 |
105 | * **URL Params**
106 |
107 | **Required:**
108 |
109 | ``
110 |
111 | Valid values are 'cloud.png' and 'temperature.png'
112 |
113 | * **Sample Call:**
114 |
115 | http://192.168.2.227:8080/weather/chart/cloud.png
116 |
117 | * **Success Response:**
118 |
119 | * **Code:** 200
120 | **Content:**
121 |
122 | 
123 |
124 | 
125 |
126 |
127 |
128 |
--------------------------------------------------------------------------------
/indi-driver/cloud-rain-monitor/cmake_modules/FindUSB-1.cmake:
--------------------------------------------------------------------------------
1 | # - Try to find libusb-1.0
2 | # Once done this will define
3 | #
4 | # LIBUSB_1_FOUND - system has libusb
5 | # LIBUSB_1_INCLUDE_DIRS - the libusb include directory
6 | # LIBUSB_1_LIBRARIES - Link these to use libusb
7 | # LIBUSB_1_DEFINITIONS - Compiler switches required for using libusb
8 | #
9 | # Adapted from cmake-modules Google Code project
10 | #
11 | # Copyright (c) 2006 Andreas Schneider
12 | #
13 | # (Changes for libusb) Copyright (c) 2008 Kyle Machulis
14 | #
15 | # Redistribution and use is allowed according to the terms of the New BSD license.
16 | #
17 | # CMake-Modules Project New BSD License
18 | #
19 | # Redistribution and use in source and binary forms, with or without
20 | # modification, are permitted provided that the following conditions are met:
21 | #
22 | # * Redistributions of source code must retain the above copyright notice, this
23 | # list of conditions and the following disclaimer.
24 | #
25 | # * Redistributions in binary form must reproduce the above copyright notice,
26 | # this list of conditions and the following disclaimer in the
27 | # documentation and/or other materials provided with the distribution.
28 | #
29 | # * Neither the name of the CMake-Modules Project nor the names of its
30 | # contributors may be used to endorse or promote products derived from this
31 | # software without specific prior written permission.
32 | #
33 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
34 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
35 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
36 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
37 | # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
38 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
39 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
40 | # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
41 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
42 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43 | #
44 |
45 | if (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS)
46 | # in cache already
47 | set(LIBUSB_FOUND TRUE)
48 | else (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS)
49 | find_path(LIBUSB_1_INCLUDE_DIR
50 | NAMES
51 | libusb.h
52 | PATHS
53 | /usr/include
54 | /usr/local/include
55 | /opt/local/include
56 | /sw/include
57 | PATH_SUFFIXES
58 | libusb-1.0
59 | )
60 |
61 | find_library(LIBUSB_1_LIBRARY
62 | NAMES
63 | usb-1.0
64 | PATHS
65 | /usr/lib
66 | /usr/local/lib
67 | /opt/local/lib
68 | /sw/lib
69 | )
70 |
71 | set(LIBUSB_1_INCLUDE_DIRS
72 | ${LIBUSB_1_INCLUDE_DIR}
73 | )
74 | set(LIBUSB_1_LIBRARIES
75 | ${LIBUSB_1_LIBRARY}
76 | )
77 |
78 | if (LIBUSB_1_INCLUDE_DIRS AND LIBUSB_1_LIBRARIES)
79 | set(LIBUSB_1_FOUND TRUE)
80 | endif (LIBUSB_1_INCLUDE_DIRS AND LIBUSB_1_LIBRARIES)
81 |
82 | if (LIBUSB_1_FOUND)
83 | if (NOT USB-1_FIND_QUIETLY)
84 | message(STATUS "Found libusb-1.0:")
85 | message(STATUS " - Includes: ${LIBUSB_1_INCLUDE_DIRS}")
86 | message(STATUS " - Libraries: ${LIBUSB_1_LIBRARIES}")
87 | endif (NOT USB-1_FIND_QUIETLY)
88 | set(CMAKE_REQUIRED_INCLUDES ${LIBUSB_1_INCLUDE_DIRS})
89 | set(CMAKE_REQUIRED_LIBRARIES ${LIBUSB_1_LIBRARIES})
90 | if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
91 | include (CheckCXXSourceCompiles)
92 | check_cxx_source_compiles("#include
93 | int main() { libusb_error_name(0); return 0; }" ERROR_NAME_COMPILE)
94 | if (NOT ERROR_NAME_COMPILE)
95 | add_definitions("-DNO_ERROR_NAME")
96 | message(STATUS " - 1.0.8 or older")
97 | endif (NOT ERROR_NAME_COMPILE)
98 | endif ()
99 | else (LIBUSB_1_FOUND)
100 | if (USB-1_FIND_REQUIRED)
101 | message(FATAL_ERROR "Could not find libusb-1.0. Please install libusb-1.0 along with the development package.")
102 | endif (USB-1_FIND_REQUIRED)
103 | endif (LIBUSB_1_FOUND)
104 |
105 | # show the LIBUSB_1_INCLUDE_DIRS and LIBUSB_1_LIBRARIES variables only in the advanced view
106 | mark_as_advanced(LIBUSB_1_INCLUDE_DIRS LIBUSB_1_LIBRARIES)
107 |
108 | endif (LIBUSB_1_LIBRARIES AND LIBUSB_1_INCLUDE_DIRS)
109 |
--------------------------------------------------------------------------------
/indi-driver/cloud-rain-monitor/gason.h:
--------------------------------------------------------------------------------
1 | /*
2 | The MIT License (MIT)
3 |
4 | Copyright (c) 2013-2015 Ivan Vashchaev
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | this software and associated documentation files (the "Software"), to deal in
8 | the Software without restriction, including without limitation the rights to
9 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | the Software, and to permit persons to whom the Software is furnished to do so,
11 | subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 | */
23 |
24 | #pragma once
25 |
26 | #include
27 | #include
28 | #include
29 |
30 | enum JsonTag {
31 | JSON_NUMBER = 0,
32 | JSON_STRING,
33 | JSON_ARRAY,
34 | JSON_OBJECT,
35 | JSON_TRUE,
36 | JSON_FALSE,
37 | JSON_NULL = 0xF
38 | };
39 |
40 | struct JsonNode;
41 |
42 | #define JSON_VALUE_PAYLOAD_MASK 0x00007FFFFFFFFFFFULL
43 | #define JSON_VALUE_NAN_MASK 0x7FF8000000000000ULL
44 | #define JSON_VALUE_TAG_MASK 0xF
45 | #define JSON_VALUE_TAG_SHIFT 47
46 |
47 | union JsonValue {
48 | uint64_t ival;
49 | double fval;
50 |
51 | JsonValue(double x)
52 | : fval(x) {
53 | }
54 | JsonValue(JsonTag tag = JSON_NULL, void *payload = nullptr) {
55 | assert((uint64_t)(uintptr_t)payload <= JSON_VALUE_PAYLOAD_MASK);
56 | ival = JSON_VALUE_NAN_MASK | ((uint64_t)tag << JSON_VALUE_TAG_SHIFT) | (uintptr_t)payload;
57 | }
58 | bool isDouble() const {
59 | return (int64_t)ival <= (int64_t)JSON_VALUE_NAN_MASK;
60 | }
61 | JsonTag getTag() const {
62 | return isDouble() ? JSON_NUMBER : JsonTag((ival >> JSON_VALUE_TAG_SHIFT) & JSON_VALUE_TAG_MASK);
63 | }
64 | uint64_t getPayload() const {
65 | assert(!isDouble());
66 | return ival & JSON_VALUE_PAYLOAD_MASK;
67 | }
68 | double toNumber() const {
69 | assert(getTag() == JSON_NUMBER);
70 | return fval;
71 | }
72 | char *toString() const {
73 | assert(getTag() == JSON_STRING);
74 | return (char *)getPayload();
75 | }
76 | JsonNode *toNode() const {
77 | assert(getTag() == JSON_ARRAY || getTag() == JSON_OBJECT);
78 | return (JsonNode *)getPayload();
79 | }
80 | };
81 |
82 | struct JsonNode {
83 | JsonValue value;
84 | JsonNode *next;
85 | char *key;
86 | };
87 |
88 | struct JsonIterator {
89 | JsonNode *p;
90 |
91 | void operator++() {
92 | p = p->next;
93 | }
94 | bool operator!=(const JsonIterator &x) const {
95 | return p != x.p;
96 | }
97 | JsonNode *operator*() const {
98 | return p;
99 | }
100 | JsonNode *operator->() const {
101 | return p;
102 | }
103 | };
104 |
105 | inline JsonIterator begin(JsonValue o) {
106 | return JsonIterator{o.toNode()};
107 | }
108 | inline JsonIterator end(JsonValue) {
109 | return JsonIterator{nullptr};
110 | }
111 |
112 | #define JSON_ERRNO_MAP(XX) \
113 | XX(OK, "ok") \
114 | XX(BAD_NUMBER, "bad number") \
115 | XX(BAD_STRING, "bad string") \
116 | XX(BAD_IDENTIFIER, "bad identifier") \
117 | XX(STACK_OVERFLOW, "stack overflow") \
118 | XX(STACK_UNDERFLOW, "stack underflow") \
119 | XX(MISMATCH_BRACKET, "mismatch bracket") \
120 | XX(UNEXPECTED_CHARACTER, "unexpected character") \
121 | XX(UNQUOTED_KEY, "unquoted key") \
122 | XX(BREAKING_BAD, "breaking bad") \
123 | XX(ALLOCATION_FAILURE, "allocation failure")
124 |
125 | enum JsonErrno {
126 | #define XX(no, str) JSON_##no,
127 | JSON_ERRNO_MAP(XX)
128 | #undef XX
129 | };
130 |
131 | const char *jsonStrError(int err);
132 |
133 | class JsonAllocator {
134 | struct Zone {
135 | Zone *next;
136 | size_t used;
137 | } *head = nullptr;
138 |
139 | public:
140 | JsonAllocator() = default;
141 | JsonAllocator(const JsonAllocator &) = delete;
142 | JsonAllocator &operator=(const JsonAllocator &) = delete;
143 | JsonAllocator(JsonAllocator &&x) : head(x.head) {
144 | x.head = nullptr;
145 | }
146 | JsonAllocator &operator=(JsonAllocator &&x) {
147 | head = x.head;
148 | x.head = nullptr;
149 | return *this;
150 | }
151 | ~JsonAllocator() {
152 | deallocate();
153 | }
154 | void *allocate(size_t size);
155 | void deallocate();
156 | };
157 |
158 | int jsonParse(char *str, char **endptr, JsonValue *value, JsonAllocator &allocator);
159 |
--------------------------------------------------------------------------------
/indi-driver/cloud-rain-monitor/cmake_modules/MacroLogFeature.cmake:
--------------------------------------------------------------------------------
1 | # This file defines the Feature Logging macros.
2 | #
3 | # MACRO_LOG_FEATURE(VAR FEATURE DESCRIPTION URL [REQUIRED [MIN_VERSION [COMMENTS]]])
4 | # Logs the information so that it can be displayed at the end
5 | # of the configure run
6 | # VAR : TRUE or FALSE, indicating whether the feature is supported
7 | # FEATURE: name of the feature, e.g. "libjpeg"
8 | # DESCRIPTION: description what this feature provides
9 | # URL: home page
10 | # REQUIRED: TRUE or FALSE, indicating whether the featue is required
11 | # MIN_VERSION: minimum version number. empty string if unneeded
12 | # COMMENTS: More info you may want to provide. empty string if unnecessary
13 | #
14 | # MACRO_DISPLAY_FEATURE_LOG()
15 | # Call this to display the collected results.
16 | # Exits CMake with a FATAL error message if a required feature is missing
17 | #
18 | # Example:
19 | #
20 | # INCLUDE(MacroLogFeature)
21 | #
22 | # FIND_PACKAGE(JPEG)
23 | # MACRO_LOG_FEATURE(JPEG_FOUND "libjpeg" "Support JPEG images" "http://www.ijg.org" TRUE "3.2a" "")
24 | # ...
25 | # MACRO_DISPLAY_FEATURE_LOG()
26 |
27 | # Copyright (c) 2006, Alexander Neundorf,
28 | # Copyright (c) 2006, Allen Winter,
29 | #
30 | # Redistribution and use is allowed according to the terms of the BSD license.
31 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file.
32 |
33 | IF (NOT _macroLogFeatureAlreadyIncluded)
34 | SET(_file ${CMAKE_BINARY_DIR}/MissingRequirements.txt)
35 | IF (EXISTS ${_file})
36 | FILE(REMOVE ${_file})
37 | ENDIF (EXISTS ${_file})
38 |
39 | SET(_file ${CMAKE_BINARY_DIR}/EnabledFeatures.txt)
40 | IF (EXISTS ${_file})
41 | FILE(REMOVE ${_file})
42 | ENDIF (EXISTS ${_file})
43 |
44 | SET(_file ${CMAKE_BINARY_DIR}/DisabledFeatures.txt)
45 | IF (EXISTS ${_file})
46 | FILE(REMOVE ${_file})
47 | ENDIF (EXISTS ${_file})
48 |
49 | SET(_macroLogFeatureAlreadyIncluded TRUE)
50 | ENDIF (NOT _macroLogFeatureAlreadyIncluded)
51 |
52 |
53 | MACRO(MACRO_LOG_FEATURE _var _package _description _url ) # _required _minvers _comments)
54 |
55 | SET(_required "${ARGV4}")
56 | SET(_minvers "${ARGV5}")
57 | SET(_comments "${ARGV6}")
58 |
59 | IF (${_var})
60 | SET(_LOGFILENAME ${CMAKE_BINARY_DIR}/EnabledFeatures.txt)
61 | ELSE (${_var})
62 | IF (${_required} MATCHES "[Tt][Rr][Uu][Ee]")
63 | SET(_LOGFILENAME ${CMAKE_BINARY_DIR}/MissingRequirements.txt)
64 | ELSE (${_required} MATCHES "[Tt][Rr][Uu][Ee]")
65 | SET(_LOGFILENAME ${CMAKE_BINARY_DIR}/DisabledFeatures.txt)
66 | ENDIF (${_required} MATCHES "[Tt][Rr][Uu][Ee]")
67 | ENDIF (${_var})
68 |
69 | SET(_logtext "+ ${_package}")
70 |
71 | IF (NOT ${_var})
72 | IF (${_minvers} MATCHES ".*")
73 | SET(_logtext "${_logtext}, ${_minvers}")
74 | ENDIF (${_minvers} MATCHES ".*")
75 | SET(_logtext "${_logtext}: ${_description} <${_url}>")
76 | IF (${_comments} MATCHES ".*")
77 | SET(_logtext "${_logtext}\n${_comments}")
78 | ENDIF (${_comments} MATCHES ".*")
79 | # SET(_logtext "${_logtext}\n") #double-space missing features?
80 | ENDIF (NOT ${_var})
81 | FILE(APPEND "${_LOGFILENAME}" "${_logtext}\n")
82 |
83 | ENDMACRO(MACRO_LOG_FEATURE)
84 |
85 |
86 | MACRO(MACRO_DISPLAY_FEATURE_LOG)
87 |
88 | SET(_file ${CMAKE_BINARY_DIR}/MissingRequirements.txt)
89 | IF (EXISTS ${_file})
90 | FILE(READ ${_file} _requirements)
91 | MESSAGE(STATUS "\n-----------------------------------------------------------------------------\n-- The following REQUIRED packages could NOT be located on your system.\n-- Please install them before continuing this software installation.\n-----------------------------------------------------------------------------\n${_requirements}-----------------------------------------------------------------------------")
92 | FILE(REMOVE ${_file})
93 | MESSAGE(FATAL_ERROR "Exiting: Missing Requirements")
94 | ENDIF (EXISTS ${_file})
95 |
96 | SET(_summary "\n")
97 |
98 | SET(_elist 0)
99 | SET(_file ${CMAKE_BINARY_DIR}/EnabledFeatures.txt)
100 | IF (EXISTS ${_file})
101 | SET(_elist 1)
102 | FILE(READ ${_file} _enabled)
103 | FILE(REMOVE ${_file})
104 | SET(_summary "${_summary}-----------------------------------------------------------------------------\n-- The following external packages were located on your system.\n-- This installation will have the extra features provided by these packages.\n${_enabled}")
105 | ENDIF (EXISTS ${_file})
106 |
107 | SET(_dlist 0)
108 | SET(_file ${CMAKE_BINARY_DIR}/DisabledFeatures.txt)
109 | IF (EXISTS ${_file})
110 | SET(_dlist 1)
111 | FILE(READ ${_file} _disabled)
112 | FILE(REMOVE ${_file})
113 | SET(_summary "${_summary}-----------------------------------------------------------------------------\n-- The following OPTIONAL packages could NOT be located on your system.\n-- Consider installing them to enable more features from this software.\n${_disabled}")
114 | ELSE (EXISTS ${_file})
115 | IF (${_elist})
116 | SET(_summary "${_summary}Congratulations! All external packages have been found.\n")
117 | ENDIF (${_elist})
118 | ENDIF (EXISTS ${_file})
119 |
120 | IF (${_elist} OR ${_dlist})
121 | SET(_summary "${_summary}-----------------------------------------------------------------------------\n")
122 | ENDIF (${_elist} OR ${_dlist})
123 | MESSAGE(STATUS "${_summary}")
124 |
125 | ENDMACRO(MACRO_DISPLAY_FEATURE_LOG)
126 |
--------------------------------------------------------------------------------
/indi-driver/cloud-rain-monitor/cloudrainmonitor.cpp:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | Copyright(c) 2016 Derek OKeeffe. All rights reserved.
3 |
4 | INDI driver for a Cloud and rain monitor for an astronomical observatory.
5 | The device hardware is arduino based and provides an HTTP api.
6 | Example GET request to http://192.168.1.204/weather
7 | Returns a 200 response like below
8 | {
9 | "uptime":"05:14:12",
10 | "skyTemp": 4.230,
11 | "outsideTemp": 10.090,
12 | "rain":false
13 | }
14 |
15 | This driver is responsible for providing weather state information to INDI clients.
16 | The INDI client will decide what action to take (for example: initiate an observatory shutdown or startup process).
17 |
18 | This program is free software; you can redistribute it and/or modify it
19 | under the terms of the GNU General Public License as published by the Free
20 | Software Foundation; either version 2 of the License, or (at your option)
21 | any later version.
22 |
23 | This program is distributed in the hope that it will be useful, but WITHOUT
24 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
25 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
26 | more details.
27 |
28 | You should have received a copy of the GNU Library General Public License
29 | along with this library; see the file COPYING.LIB. If not, write to
30 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
31 | Boston, MA 02110-1301, USA.
32 |
33 | The full GNU General Public License is included in this distribution in the
34 | file called LICENSE.
35 | *******************************************************************************/
36 |
37 | #include
38 | #include "cloudrainmonitor.h"
39 | #include "gason.h"
40 |
41 | #include
42 | #include
43 | #include
44 | #include
45 | #include
46 |
47 | #include
48 |
49 | std::unique_ptr indicloudrainmonitor(new IndiCloudRainMonitor());
50 |
51 | static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
52 | {
53 | ((std::string*)userp)->append((char*)contents, size * nmemb);
54 | return size * nmemb;
55 | }
56 |
57 | void ISGetProperties(const char *dev)
58 | {
59 | indicloudrainmonitor->ISGetProperties(dev);
60 | }
61 |
62 | void ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int num)
63 | {
64 | indicloudrainmonitor->ISNewSwitch(dev, name, states, names, num);
65 | }
66 |
67 | void ISNewText( const char *dev, const char *name, char *texts[], char *names[], int num)
68 | {
69 | indicloudrainmonitor->ISNewText(dev, name, texts, names, num);
70 | }
71 |
72 | void ISNewNumber(const char *dev, const char *name, double values[], char *names[], int num)
73 | {
74 | indicloudrainmonitor->ISNewNumber(dev, name, values, names, num);
75 | }
76 |
77 | void ISNewBLOB (const char *dev, const char *name, int sizes[], int blobsizes[], char *blobs[], char *formats[], char *names[], int n)
78 | {
79 | INDI_UNUSED(dev);
80 | INDI_UNUSED(name);
81 | INDI_UNUSED(sizes);
82 | INDI_UNUSED(blobsizes);
83 | INDI_UNUSED(blobs);
84 | INDI_UNUSED(formats);
85 | INDI_UNUSED(names);
86 | INDI_UNUSED(n);
87 | }
88 | void ISSnoopDevice (XMLEle *root)
89 | {
90 | indicloudrainmonitor->ISSnoopDevice(root);
91 | }
92 |
93 | IndiCloudRainMonitor::IndiCloudRainMonitor()
94 | {
95 | setVersion(1,0);
96 | }
97 |
98 | IndiCloudRainMonitor::~IndiCloudRainMonitor()
99 | {
100 |
101 | }
102 |
103 | const char * IndiCloudRainMonitor::getDefaultName()
104 | {
105 | return (char *)"Indi Cloud Rain Monitor";
106 | }
107 |
108 | bool IndiCloudRainMonitor::Connect()
109 | {
110 | DEBUG(INDI::Logger::DBG_SESSION, "CONNECTING.");
111 | if (httpEndpointT[0].text == NULL)
112 | {
113 | DEBUG(INDI::Logger::DBG_ERROR, "cloudrainmonitor HTTP API endpoint is not available. Set it in the options tab");
114 | return false;
115 | }
116 |
117 | CURL *curl;
118 | CURLcode res;
119 | std::string readBuffer;
120 |
121 | curl = curl_easy_init();
122 | if(curl) {
123 | curl_easy_setopt(curl, CURLOPT_URL, httpEndpointT[0].text);
124 | curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L); //10 sec timeout
125 | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
126 | curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
127 | res = curl_easy_perform(curl);
128 | /* Check for errors */
129 | if(res != CURLE_OK) {
130 | DEBUG(INDI::Logger::DBG_ERROR, "Connecttion to HTTP endpoint failed");
131 | DEBUG(INDI::Logger::DBG_ERROR, "Is the HTTP API endpoint correct? Set it in the options tab. Can you ping the weather device?");
132 | return false;
133 | }
134 | /* always cleanup */
135 | curl_easy_cleanup(curl);
136 |
137 | char srcBuffer[readBuffer.size()];
138 | strncpy(srcBuffer, readBuffer.c_str(), readBuffer.size());
139 | char *source = srcBuffer;
140 | // do not forget terminate source string with 0
141 | char *endptr;
142 | JsonValue value;
143 | JsonAllocator allocator;
144 | int status = jsonParse(source, &endptr, &value, allocator);
145 | if (status != JSON_OK)
146 | {
147 | DEBUGF(INDI::Logger::DBG_ERROR, "%s at %zd", jsonStrError(status), endptr - source);
148 | DEBUGF(INDI::Logger::DBG_DEBUG, "%s", readBuffer.c_str());
149 | return IPS_ALERT;
150 | }
151 | DEBUGF(INDI::Logger::DBG_DEBUG, "HTTP response %s", readBuffer.c_str());
152 | JsonIterator it;
153 | for (it = begin(value); it!= end(value); ++it) {
154 | DEBUGF(INDI::Logger::DBG_DEBUG, "iterating %s", it->key);
155 | }
156 | }
157 |
158 | return true;
159 | }
160 |
161 | bool IndiCloudRainMonitor::Disconnect()
162 | {
163 | return true;
164 | }
165 |
166 | bool IndiCloudRainMonitor::initProperties()
167 | {
168 | INDI::Weather::initProperties();
169 |
170 | IUFillText(&httpEndpointT[0], "API_ENDPOINT", "API Endpoint", "http://192.168.1.204/weather"); //this is the default but can be changed in the options OPTIONS_TAB.
171 | IUFillTextVector(&httpEndpointTP, httpEndpointT, 1, getDeviceName(), "HTTP_API_ENDPOINT", "HTTP endpoint", OPTIONS_TAB, IP_RW, 5, IPS_IDLE);
172 |
173 | addParameter("WEATHER_RAIN", "Rain", 0, 0, 0);
174 | setCriticalParameter("WEATHER_RAIN");
175 | addParameter("WEATHER_STATION_ONLINE", "Station Online", 0, 0, 0);
176 | setCriticalParameter("WEATHER_STATION_ONLINE");
177 | addParameter("WEATHER_CLOUD_COVER", "Cloud Cover", 0, 0, 0);
178 | setCriticalParameter("WEATHER_CLOUD_COVER");
179 |
180 | addDebugControl();
181 | return true;
182 | }
183 |
184 | void IndiCloudRainMonitor::ISGetProperties(const char *dev)
185 | {
186 | INDI::Weather::ISGetProperties(dev);
187 |
188 | defineProperty(&httpEndpointTP);
189 | loadConfig(true, "HTTP_API_ENDPOINT");
190 | }
191 |
192 | bool IndiCloudRainMonitor::ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n)
193 | {
194 | if(!strcmp(dev,getDeviceName()))
195 | {
196 | if (!strcmp(httpEndpointTP.name, name))
197 | {
198 | IUUpdateText(&httpEndpointTP, texts, names, n);
199 | httpEndpointTP.s = IPS_OK;
200 | IDSetText(&httpEndpointTP, NULL);
201 | return true;
202 | }
203 |
204 | }
205 |
206 | return INDI::Weather::ISNewText(dev,name,texts,names,n);
207 | }
208 |
209 | /**
210 | * Poll the device's HTTP API to get the latest measurements. Set the state based on these measurements.
211 | */
212 | IPState IndiCloudRainMonitor::updateWeather()
213 | {
214 | DEBUG(INDI::Logger::DBG_DEBUG, "Updating from weather API_ENDPOINT");
215 | CURL *curl;
216 | CURLcode res;
217 | std::string readBuffer;
218 |
219 | curl = curl_easy_init();
220 | if(curl) {
221 | curl_easy_setopt(curl, CURLOPT_URL, httpEndpointT[0].text);
222 | curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L); //10 sec timeout
223 | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
224 | curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
225 | res = curl_easy_perform(curl);
226 | /* Check for errors */
227 |
228 | DEBUG(INDI::Logger::DBG_DEBUG, "curl complete");
229 |
230 | if(res != CURLE_OK) {
231 | DEBUG(INDI::Logger::DBG_ERROR, "curl failed!!!!!!");
232 | // DEBUGF(INDI::Logger::DBG_ERROR, "Connecttion to HTTP_API_ENDPOINT failed:%s",curl_easy_strerror(res));
233 | DEBUG(INDI::Logger::DBG_ERROR, "Cant contact weather device setting alert state");
234 | setParameterValue("WEATHER_STATION_ONLINE", 1);
235 | return IPS_OK;
236 | }
237 | DEBUG(INDI::Logger::DBG_DEBUG, "curl ok");
238 |
239 | /* always cleanup */
240 | curl_easy_cleanup(curl);
241 |
242 | char srcBuffer[readBuffer.size()];
243 | strncpy(srcBuffer, readBuffer.c_str(), readBuffer.size());
244 | char *source = srcBuffer;
245 | // do not forget terminate source string with 0
246 | char *endptr;
247 | JsonValue value;
248 | JsonAllocator allocator;
249 | int status = jsonParse(source, &endptr, &value, allocator);
250 | if (status != JSON_OK)
251 | {
252 | DEBUG(INDI::Logger::DBG_ERROR, "NON OK response, setting alert state");
253 | setParameterValue("WEATHER_STATION_ONLINE", 1);
254 | return IPS_OK;
255 | }
256 | DEBUGF(INDI::Logger::DBG_DEBUG, "http response %s", readBuffer.c_str());
257 | JsonIterator it;
258 | double skyTemp;
259 | double ambientTemp;
260 | for (it = begin(value); it!= end(value); ++it) {
261 | LOGF_DEBUG("iterating %s", it->key);
262 | if (!strcmp(it->key, "rain")) {
263 | //bool raining = it->value.toBool();
264 | //DEBUGF(INDI::Logger::DBG_DEBUG, "Setting rain value from response %s", it->value);
265 | if (it->value.getTag()==JSON_TRUE) {
266 | setParameterValue("WEATHER_RAIN", 1);
267 | } else {
268 | setParameterValue("WEATHER_RAIN", 0);
269 | }
270 | }
271 | if (!strcmp(it->key, "skyTemp")) {
272 | LOGF_DEBUG("Got skyTemp from response %g", it->value.toNumber());
273 | skyTemp = it->value.toNumber();
274 | }
275 | if (!strcmp(it->key, "outsideTemp")) {
276 | LOGF_DEBUG("Got outsideTemp from response %g", it->value.toNumber());
277 | ambientTemp = it->value.toNumber();
278 | }
279 | }
280 | //Function based on data collected, guesswork and linear regression using wolframalpha https://www.wolframalpha.com/input/?i=linear+fit+{0,+100},{-1,+90},{-2,+80},{-3,+50},{-4,+25},{-5,+10},{-6,0}&lk=3
281 | double result = (18 * skyTemp) + 100;
282 | if(result > 100) {
283 | result = 100;
284 | }
285 | if(result < 0) {
286 | result = 0;
287 | }
288 | LOGF_DEBUG("CLOUD %g", result);
289 | setParameterValue("WEATHER_CLOUD_COVER", result);
290 | }
291 | setParameterValue("WEATHER_STATION_ONLINE", 0);
292 | return IPS_OK;
293 | }
294 |
295 | bool IndiCloudRainMonitor::saveConfigItems(FILE *fp)
296 | {
297 | INDI::Weather::saveConfigItems(fp);
298 |
299 | IUSaveConfigText(fp, &httpEndpointTP);
300 |
301 | return true;
302 | }
303 |
--------------------------------------------------------------------------------
/indi-driver/cloud-rain-monitor/gason.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | The MIT License (MIT)
3 |
4 | Copyright (c) 2013-2015 Ivan Vashchaev
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | this software and associated documentation files (the "Software"), to deal in
8 | the Software without restriction, including without limitation the rights to
9 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | the Software, and to permit persons to whom the Software is furnished to do so,
11 | subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 | */
23 |
24 | #include "gason.h"
25 | #include
26 |
27 | #define JSON_ZONE_SIZE 4096
28 | #define JSON_STACK_SIZE 32
29 |
30 | const char *jsonStrError(int err) {
31 | switch (err) {
32 | #define XX(no, str) \
33 | case JSON_##no: \
34 | return str;
35 | JSON_ERRNO_MAP(XX)
36 | #undef XX
37 | default:
38 | return "unknown";
39 | }
40 | }
41 |
42 | void *JsonAllocator::allocate(size_t size) {
43 | size = (size + 7) & ~7;
44 |
45 | if (head && head->used + size <= JSON_ZONE_SIZE) {
46 | char *p = (char *)head + head->used;
47 | head->used += size;
48 | return p;
49 | }
50 |
51 | size_t allocSize = sizeof(Zone) + size;
52 | Zone *zone = (Zone *)malloc(allocSize <= JSON_ZONE_SIZE ? JSON_ZONE_SIZE : allocSize);
53 | if (zone == nullptr)
54 | return nullptr;
55 | zone->used = allocSize;
56 | if (allocSize <= JSON_ZONE_SIZE || head == nullptr) {
57 | zone->next = head;
58 | head = zone;
59 | } else {
60 | zone->next = head->next;
61 | head->next = zone;
62 | }
63 | return (char *)zone + sizeof(Zone);
64 | }
65 |
66 | void JsonAllocator::deallocate() {
67 | while (head) {
68 | Zone *next = head->next;
69 | free(head);
70 | head = next;
71 | }
72 | }
73 |
74 | static inline bool isspace(char c) {
75 | return c == ' ' || (c >= '\t' && c <= '\r');
76 | }
77 |
78 | static inline bool isdelim(char c) {
79 | return c == ',' || c == ':' || c == ']' || c == '}' || isspace(c) || !c;
80 | }
81 |
82 | static inline bool isdigit(char c) {
83 | return c >= '0' && c <= '9';
84 | }
85 |
86 | static inline bool isxdigit(char c) {
87 | return (c >= '0' && c <= '9') || ((c & ~' ') >= 'A' && (c & ~' ') <= 'F');
88 | }
89 |
90 | static inline int char2int(char c) {
91 | if (c <= '9')
92 | return c - '0';
93 | return (c & ~' ') - 'A' + 10;
94 | }
95 |
96 | static double string2double(char *s, char **endptr) {
97 | char ch = *s;
98 | if (ch == '-')
99 | ++s;
100 |
101 | double result = 0;
102 | while (isdigit(*s))
103 | result = (result * 10) + (*s++ - '0');
104 |
105 | if (*s == '.') {
106 | ++s;
107 |
108 | double fraction = 1;
109 | while (isdigit(*s)) {
110 | fraction *= 0.1;
111 | result += (*s++ - '0') * fraction;
112 | }
113 | }
114 |
115 | if (*s == 'e' || *s == 'E') {
116 | ++s;
117 |
118 | double base = 10;
119 | if (*s == '+')
120 | ++s;
121 | else if (*s == '-') {
122 | ++s;
123 | base = 0.1;
124 | }
125 |
126 | unsigned int exponent = 0;
127 | while (isdigit(*s))
128 | exponent = (exponent * 10) + (*s++ - '0');
129 |
130 | double power = 1;
131 | for (; exponent; exponent >>= 1, base *= base)
132 | if (exponent & 1)
133 | power *= base;
134 |
135 | result *= power;
136 | }
137 |
138 | *endptr = s;
139 | return ch == '-' ? -result : result;
140 | }
141 |
142 | static inline JsonNode *insertAfter(JsonNode *tail, JsonNode *node) {
143 | if (!tail)
144 | return node->next = node;
145 | node->next = tail->next;
146 | tail->next = node;
147 | return node;
148 | }
149 |
150 | static inline JsonValue listToValue(JsonTag tag, JsonNode *tail) {
151 | if (tail) {
152 | auto head = tail->next;
153 | tail->next = nullptr;
154 | return JsonValue(tag, head);
155 | }
156 | return JsonValue(tag, nullptr);
157 | }
158 |
159 | int jsonParse(char *s, char **endptr, JsonValue *value, JsonAllocator &allocator) {
160 | JsonNode *tails[JSON_STACK_SIZE];
161 | JsonTag tags[JSON_STACK_SIZE];
162 | char *keys[JSON_STACK_SIZE];
163 | JsonValue o;
164 | int pos = -1;
165 | bool separator = true;
166 | JsonNode *node;
167 | *endptr = s;
168 |
169 | while (*s) {
170 | while (isspace(*s)) {
171 | ++s;
172 | if (!*s) break;
173 | }
174 | *endptr = s++;
175 | switch (**endptr) {
176 | case '-':
177 | if (!isdigit(*s) && *s != '.') {
178 | *endptr = s;
179 | return JSON_BAD_NUMBER;
180 | }
181 | case '0':
182 | case '1':
183 | case '2':
184 | case '3':
185 | case '4':
186 | case '5':
187 | case '6':
188 | case '7':
189 | case '8':
190 | case '9':
191 | o = JsonValue(string2double(*endptr, &s));
192 | if (!isdelim(*s)) {
193 | *endptr = s;
194 | return JSON_BAD_NUMBER;
195 | }
196 | break;
197 | case '"':
198 | o = JsonValue(JSON_STRING, s);
199 | for (char *it = s; *s; ++it, ++s) {
200 | int c = *it = *s;
201 | if (c == '\\') {
202 | c = *++s;
203 | switch (c) {
204 | case '\\':
205 | case '"':
206 | case '/':
207 | *it = c;
208 | break;
209 | case 'b':
210 | *it = '\b';
211 | break;
212 | case 'f':
213 | *it = '\f';
214 | break;
215 | case 'n':
216 | *it = '\n';
217 | break;
218 | case 'r':
219 | *it = '\r';
220 | break;
221 | case 't':
222 | *it = '\t';
223 | break;
224 | case 'u':
225 | c = 0;
226 | for (int i = 0; i < 4; ++i) {
227 | if (isxdigit(*++s)) {
228 | c = c * 16 + char2int(*s);
229 | } else {
230 | *endptr = s;
231 | return JSON_BAD_STRING;
232 | }
233 | }
234 | if (c < 0x80) {
235 | *it = c;
236 | } else if (c < 0x800) {
237 | *it++ = 0xC0 | (c >> 6);
238 | *it = 0x80 | (c & 0x3F);
239 | } else {
240 | *it++ = 0xE0 | (c >> 12);
241 | *it++ = 0x80 | ((c >> 6) & 0x3F);
242 | *it = 0x80 | (c & 0x3F);
243 | }
244 | break;
245 | default:
246 | *endptr = s;
247 | return JSON_BAD_STRING;
248 | }
249 | } else if ((unsigned int)c < ' ' || c == '\x7F') {
250 | *endptr = s;
251 | return JSON_BAD_STRING;
252 | } else if (c == '"') {
253 | *it = 0;
254 | ++s;
255 | break;
256 | }
257 | }
258 | if (!isdelim(*s)) {
259 | *endptr = s;
260 | return JSON_BAD_STRING;
261 | }
262 | break;
263 | case 't':
264 | if (!(s[0] == 'r' && s[1] == 'u' && s[2] == 'e' && isdelim(s[3])))
265 | return JSON_BAD_IDENTIFIER;
266 | o = JsonValue(JSON_TRUE);
267 | s += 3;
268 | break;
269 | case 'f':
270 | if (!(s[0] == 'a' && s[1] == 'l' && s[2] == 's' && s[3] == 'e' && isdelim(s[4])))
271 | return JSON_BAD_IDENTIFIER;
272 | o = JsonValue(JSON_FALSE);
273 | s += 4;
274 | break;
275 | case 'n':
276 | if (!(s[0] == 'u' && s[1] == 'l' && s[2] == 'l' && isdelim(s[3])))
277 | return JSON_BAD_IDENTIFIER;
278 | o = JsonValue(JSON_NULL);
279 | s += 3;
280 | break;
281 | case ']':
282 | if (pos == -1)
283 | return JSON_STACK_UNDERFLOW;
284 | if (tags[pos] != JSON_ARRAY)
285 | return JSON_MISMATCH_BRACKET;
286 | o = listToValue(JSON_ARRAY, tails[pos--]);
287 | break;
288 | case '}':
289 | if (pos == -1)
290 | return JSON_STACK_UNDERFLOW;
291 | if (tags[pos] != JSON_OBJECT)
292 | return JSON_MISMATCH_BRACKET;
293 | if (keys[pos] != nullptr)
294 | return JSON_UNEXPECTED_CHARACTER;
295 | o = listToValue(JSON_OBJECT, tails[pos--]);
296 | break;
297 | case '[':
298 | if (++pos == JSON_STACK_SIZE)
299 | return JSON_STACK_OVERFLOW;
300 | tails[pos] = nullptr;
301 | tags[pos] = JSON_ARRAY;
302 | keys[pos] = nullptr;
303 | separator = true;
304 | continue;
305 | case '{':
306 | if (++pos == JSON_STACK_SIZE)
307 | return JSON_STACK_OVERFLOW;
308 | tails[pos] = nullptr;
309 | tags[pos] = JSON_OBJECT;
310 | keys[pos] = nullptr;
311 | separator = true;
312 | continue;
313 | case ':':
314 | if (separator || keys[pos] == nullptr)
315 | return JSON_UNEXPECTED_CHARACTER;
316 | separator = true;
317 | continue;
318 | case ',':
319 | if (separator || keys[pos] != nullptr)
320 | return JSON_UNEXPECTED_CHARACTER;
321 | separator = true;
322 | continue;
323 | case '\0':
324 | continue;
325 | default:
326 | return JSON_UNEXPECTED_CHARACTER;
327 | }
328 |
329 | separator = false;
330 |
331 | if (pos == -1) {
332 | *endptr = s;
333 | *value = o;
334 | return JSON_OK;
335 | }
336 |
337 | if (tags[pos] == JSON_OBJECT) {
338 | if (!keys[pos]) {
339 | if (o.getTag() != JSON_STRING)
340 | return JSON_UNQUOTED_KEY;
341 | keys[pos] = o.toString();
342 | continue;
343 | }
344 | if ((node = (JsonNode *) allocator.allocate(sizeof(JsonNode))) == nullptr)
345 | return JSON_ALLOCATION_FAILURE;
346 | tails[pos] = insertAfter(tails[pos], node);
347 | tails[pos]->key = keys[pos];
348 | keys[pos] = nullptr;
349 | } else {
350 | if ((node = (JsonNode *) allocator.allocate(sizeof(JsonNode) - sizeof(char *))) == nullptr)
351 | return JSON_ALLOCATION_FAILURE;
352 | tails[pos] = insertAfter(tails[pos], node);
353 | }
354 | tails[pos]->value = o;
355 | }
356 | return JSON_BREAKING_BAD;
357 | }
358 |
--------------------------------------------------------------------------------
/indi-driver/cloud-rain-monitor/cmake_modules/FindINDI.cmake:
--------------------------------------------------------------------------------
1 | # Licensed under the Apache License, Version 2.0 (the "License");
2 | # you may not use this file except in compliance with the License.
3 | # You may obtain a copy of the License at
4 | # http://www.apache.org/licenses/LICENSE-2.0
5 | # Unless required by applicable law or agreed to in writing, software
6 | # distributed under the License is distributed on an "AS IS" BASIS,
7 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8 | # See the License for the specific language governing permissions and
9 | # limitations under the License.
10 | #
11 | # This module can find INDI Library
12 | #
13 | # Requirements:
14 | # - CMake >= 2.8.3 (for new version of find_package_handle_standard_args)
15 | #
16 | # The following variables will be defined for your use:
17 | # - INDI_FOUND : were all of your specified components found (include dependencies)?
18 | # - INDI_INCLUDE_DIR : INDI include directory
19 | # - INDI_DATA_DIR : INDI include directory
20 | # - INDI_LIBRARIES : INDI libraries
21 | # - INDI_DRIVER_LIBRARIES : Same as above maintained for backward compatibility
22 | # - INDI_VERSION : complete version of INDI (x.y.z)
23 | # - INDI_MAJOR_VERSION : major version of INDI
24 | # - INDI_MINOR_VERSION : minor version of INDI
25 | # - INDI_RELEASE_VERSION : release version of INDI
26 | # - INDI__FOUND : were found? (FALSE for non specified component if it is not a dependency)
27 | #
28 | # For windows or non standard installation, define INDI_ROOT variable to point to the root installation of INDI. Two ways:
29 | # - run cmake with -DINDI_ROOT=
30 | # - define an environment variable with the same name before running cmake
31 | # With cmake-gui, before pressing "Configure":
32 | # 1) Press "Add Entry" button
33 | # 2) Add a new entry defined as:
34 | # - Name: INDI_ROOT
35 | # - Type: choose PATH in the selection list
36 | # - Press "..." button and select the root installation of INDI
37 | #
38 | # Example Usage:
39 | #
40 | # 1. Copy this file in the root of your project source directory
41 | # 2. Then, tell CMake to search this non-standard module in your project directory by adding to your CMakeLists.txt:
42 | # set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR})
43 | # 3. Finally call find_package() once, here are some examples to pick from
44 | #
45 | # Require INDI 1.4 or later
46 | # find_package(INDI 1.4 REQUIRED)
47 | #
48 | # if(INDI_FOUND)
49 | # include_directories(${INDI_INCLUDE_DIR})
50 | # add_executable(myapp myapp.cpp)
51 | # target_link_libraries(myapp ${INDI_LIBRARIES})
52 | # endif(INDI_FOUND)
53 | #
54 | #
55 | # Using Components:
56 | #
57 | # You can search for specific components. Currently, the following components are available
58 | # * driver
59 | # * align
60 | # * client
61 | # * clientqt5
62 | #
63 | # By default, if you do not specify any components, driver and align components are searched.
64 | #
65 | # Example:
66 | #
67 | # To use INDI Qt5 Client library only in your application:
68 | #
69 | # find_package(INDI CLIENTQT5 REQUIRED)
70 | #
71 | # if(INDI_FOUND)
72 | # include_directories(${INDI_INCLUDE_DIR})
73 | # add_executable(myapp myapp.cpp)
74 | # target_link_libraries(myapp ${INDI_CLIENTQT5_LIBRARIES})
75 | # endif(INDI_FOUND)
76 | #
77 | #=============================================================================
78 | # Copyright (c) 2011-2013, julp
79 | # Copyright (c) 2017 Jasem Mutlaq
80 | #
81 | # Distributed under the OSI-approved BSD License
82 | #
83 | # This software is distributed WITHOUT ANY WARRANTY; without even the
84 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTINDILAR PURPOSE.
85 | #=============================================================================
86 |
87 | find_package(PkgConfig QUIET)
88 |
89 | ########## Private ##########
90 | if(NOT DEFINED INDI_PUBLIC_VAR_NS)
91 | set(INDI_PUBLIC_VAR_NS "INDI") # Prefix for all INDI relative public variables
92 | endif(NOT DEFINED INDI_PUBLIC_VAR_NS)
93 | if(NOT DEFINED INDI_PRIVATE_VAR_NS)
94 | set(INDI_PRIVATE_VAR_NS "_${INDI_PUBLIC_VAR_NS}") # Prefix for all INDI relative internal variables
95 | endif(NOT DEFINED INDI_PRIVATE_VAR_NS)
96 | if(NOT DEFINED PC_INDI_PRIVATE_VAR_NS)
97 | set(PC_INDI_PRIVATE_VAR_NS "_PC${INDI_PRIVATE_VAR_NS}") # Prefix for all pkg-config relative internal variables
98 | endif(NOT DEFINED PC_INDI_PRIVATE_VAR_NS)
99 |
100 | function(indidebug _VARNAME)
101 | if(${INDI_PUBLIC_VAR_NS}_DEBUG)
102 | if(DEFINED ${INDI_PUBLIC_VAR_NS}_${_VARNAME})
103 | message("${INDI_PUBLIC_VAR_NS}_${_VARNAME} = ${${INDI_PUBLIC_VAR_NS}_${_VARNAME}}")
104 | else(DEFINED ${INDI_PUBLIC_VAR_NS}_${_VARNAME})
105 | message("${INDI_PUBLIC_VAR_NS}_${_VARNAME} = ")
106 | endif(DEFINED ${INDI_PUBLIC_VAR_NS}_${_VARNAME})
107 | endif(${INDI_PUBLIC_VAR_NS}_DEBUG)
108 | endfunction(indidebug)
109 |
110 | set(${INDI_PRIVATE_VAR_NS}_ROOT "")
111 | if(DEFINED ENV{INDI_ROOT})
112 | set(${INDI_PRIVATE_VAR_NS}_ROOT "$ENV{INDI_ROOT}")
113 | endif(DEFINED ENV{INDI_ROOT})
114 | if (DEFINED INDI_ROOT)
115 | set(${INDI_PRIVATE_VAR_NS}_ROOT "${INDI_ROOT}")
116 | endif(DEFINED INDI_ROOT)
117 |
118 | set(${INDI_PRIVATE_VAR_NS}_BIN_SUFFIXES )
119 | set(${INDI_PRIVATE_VAR_NS}_LIB_SUFFIXES )
120 | if(CMAKE_SIZEOF_VOID_P EQUAL 8)
121 | list(APPEND ${INDI_PRIVATE_VAR_NS}_BIN_SUFFIXES "bin64")
122 | list(APPEND ${INDI_PRIVATE_VAR_NS}_LIB_SUFFIXES "lib64")
123 | endif(CMAKE_SIZEOF_VOID_P EQUAL 8)
124 | list(APPEND ${INDI_PRIVATE_VAR_NS}_BIN_SUFFIXES "bin")
125 | list(APPEND ${INDI_PRIVATE_VAR_NS}_LIB_SUFFIXES "lib")
126 |
127 | set(${INDI_PRIVATE_VAR_NS}_COMPONENTS )
128 | # ...
129 | macro(INDI_declare_component _NAME)
130 | list(APPEND ${INDI_PRIVATE_VAR_NS}_COMPONENTS ${_NAME})
131 | set("${INDI_PRIVATE_VAR_NS}_COMPONENTS_${_NAME}" ${ARGN})
132 | endmacro(INDI_declare_component)
133 |
134 | INDI_declare_component(driver indidriver)
135 | INDI_declare_component(align indiAlignmentDriver)
136 | INDI_declare_component(client indiclient)
137 | INDI_declare_component(clientqt5 indiclientqt5)
138 |
139 | ########## Public ##########
140 | set(${INDI_PUBLIC_VAR_NS}_FOUND TRUE)
141 | set(${INDI_PUBLIC_VAR_NS}_LIBRARIES )
142 | set(${INDI_PUBLIC_VAR_NS}_INCLUDE_DIR )
143 | foreach(${INDI_PRIVATE_VAR_NS}_COMPONENT ${${INDI_PRIVATE_VAR_NS}_COMPONENTS})
144 | string(TOUPPER "${${INDI_PRIVATE_VAR_NS}_COMPONENT}" ${INDI_PRIVATE_VAR_NS}_UPPER_COMPONENT)
145 | set("${INDI_PUBLIC_VAR_NS}_${${INDI_PRIVATE_VAR_NS}_UPPER_COMPONENT}_FOUND" FALSE) # may be done in the INDI_declare_component macro
146 | endforeach(${INDI_PRIVATE_VAR_NS}_COMPONENT)
147 |
148 | # Check components
149 | if(NOT ${INDI_PUBLIC_VAR_NS}_FIND_COMPONENTS) # driver and posix client by default
150 | set(${INDI_PUBLIC_VAR_NS}_FIND_COMPONENTS driver align)
151 | else(NOT ${INDI_PUBLIC_VAR_NS}_FIND_COMPONENTS)
152 | #list(APPEND ${INDI_PUBLIC_VAR_NS}_FIND_COMPONENTS uc)
153 | list(REMOVE_DUPLICATES ${INDI_PUBLIC_VAR_NS}_FIND_COMPONENTS)
154 | foreach(${INDI_PRIVATE_VAR_NS}_COMPONENT ${${INDI_PUBLIC_VAR_NS}_FIND_COMPONENTS})
155 | if(NOT DEFINED ${INDI_PRIVATE_VAR_NS}_COMPONENTS_${${INDI_PRIVATE_VAR_NS}_COMPONENT})
156 | message(FATAL_ERROR "Unknown INDI component: ${${INDI_PRIVATE_VAR_NS}_COMPONENT}")
157 | endif(NOT DEFINED ${INDI_PRIVATE_VAR_NS}_COMPONENTS_${${INDI_PRIVATE_VAR_NS}_COMPONENT})
158 | endforeach(${INDI_PRIVATE_VAR_NS}_COMPONENT)
159 | endif(NOT ${INDI_PUBLIC_VAR_NS}_FIND_COMPONENTS)
160 |
161 | # Includes
162 | find_path(
163 | ${INDI_PUBLIC_VAR_NS}_INCLUDE_DIR
164 | indidevapi.h
165 | PATH_SUFFIXES libindi
166 | ${PC_INDI_INCLUDE_DIR}
167 | ${_obIncDir}
168 | ${GNUWIN32_DIR}/include
169 | HINTS ${${INDI_PRIVATE_VAR_NS}_ROOT}
170 | DOC "Include directory for INDI"
171 | )
172 |
173 | find_path(${INDI_PUBLIC_VAR_NS}_DATA_DIR
174 | drivers.xml
175 | PATH_SUFFIXES share/indi
176 | DOC "Data directory for INDI"
177 | )
178 |
179 | if(${INDI_PUBLIC_VAR_NS}_INCLUDE_DIR)
180 | if(EXISTS "${${INDI_PUBLIC_VAR_NS}_INCLUDE_DIR}/indiversion.h") # INDI >= 1.4
181 | file(READ "${${INDI_PUBLIC_VAR_NS}_INCLUDE_DIR}/indiversion.h" ${INDI_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS)
182 | else()
183 | message(FATAL_ERROR "INDI version header not found")
184 | endif()
185 |
186 | if(${INDI_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS MATCHES ".*INDI_VERSION ([0-9]+).([0-9]+).([0-9]+)")
187 | set(${INDI_PUBLIC_VAR_NS}_MAJOR_VERSION "${CMAKE_MATCH_1}")
188 | set(${INDI_PUBLIC_VAR_NS}_MINOR_VERSION "${CMAKE_MATCH_2}")
189 | set(${INDI_PUBLIC_VAR_NS}_RELEASE_VERSION "${CMAKE_MATCH_3}")
190 | else()
191 | message(FATAL_ERROR "failed to detect INDI version")
192 | endif()
193 | set(${INDI_PUBLIC_VAR_NS}_VERSION "${${INDI_PUBLIC_VAR_NS}_MAJOR_VERSION}.${${INDI_PUBLIC_VAR_NS}_MINOR_VERSION}.${${INDI_PUBLIC_VAR_NS}_RELEASE_VERSION}")
194 |
195 | # Check libraries
196 | foreach(${INDI_PRIVATE_VAR_NS}_COMPONENT ${${INDI_PUBLIC_VAR_NS}_FIND_COMPONENTS})
197 | set(${INDI_PRIVATE_VAR_NS}_POSSIBLE_RELEASE_NAMES )
198 | set(${INDI_PRIVATE_VAR_NS}_POSSIBLE_DEBUG_NAMES )
199 | foreach(${INDI_PRIVATE_VAR_NS}_BASE_NAME ${${INDI_PRIVATE_VAR_NS}_COMPONENTS_${${INDI_PRIVATE_VAR_NS}_COMPONENT}})
200 | list(APPEND ${INDI_PRIVATE_VAR_NS}_POSSIBLE_RELEASE_NAMES "${${INDI_PRIVATE_VAR_NS}_BASE_NAME}")
201 | list(APPEND ${INDI_PRIVATE_VAR_NS}_POSSIBLE_DEBUG_NAMES "${${INDI_PRIVATE_VAR_NS}_BASE_NAME}d")
202 | list(APPEND ${INDI_PRIVATE_VAR_NS}_POSSIBLE_RELEASE_NAMES "${${INDI_PRIVATE_VAR_NS}_BASE_NAME}${INDI_MAJOR_VERSION}${INDI_MINOR_VERSION}")
203 | list(APPEND ${INDI_PRIVATE_VAR_NS}_POSSIBLE_DEBUG_NAMES "${${INDI_PRIVATE_VAR_NS}_BASE_NAME}${INDI_MAJOR_VERSION}${INDI_MINOR_VERSION}d")
204 | endforeach(${INDI_PRIVATE_VAR_NS}_BASE_NAME)
205 |
206 | find_library(
207 | ${INDI_PRIVATE_VAR_NS}_LIB_RELEASE_${${INDI_PRIVATE_VAR_NS}_COMPONENT}
208 | NAMES ${${INDI_PRIVATE_VAR_NS}_POSSIBLE_RELEASE_NAMES}
209 | HINTS ${${INDI_PRIVATE_VAR_NS}_ROOT}
210 | PATH_SUFFIXES ${_INDI_LIB_SUFFIXES}
211 | DOC "Release libraries for INDI"
212 | )
213 | find_library(
214 | ${INDI_PRIVATE_VAR_NS}_LIB_DEBUG_${${INDI_PRIVATE_VAR_NS}_COMPONENT}
215 | NAMES ${${INDI_PRIVATE_VAR_NS}_POSSIBLE_DEBUG_NAMES}
216 | HINTS ${${INDI_PRIVATE_VAR_NS}_ROOT}
217 | PATH_SUFFIXES ${_INDI_LIB_SUFFIXES}
218 | DOC "Debug libraries for INDI"
219 | )
220 |
221 | string(TOUPPER "${${INDI_PRIVATE_VAR_NS}_COMPONENT}" ${INDI_PRIVATE_VAR_NS}_UPPER_COMPONENT)
222 | if(NOT ${INDI_PRIVATE_VAR_NS}_LIB_RELEASE_${${INDI_PRIVATE_VAR_NS}_COMPONENT} AND NOT ${INDI_PRIVATE_VAR_NS}_LIB_DEBUG_${${INDI_PRIVATE_VAR_NS}_COMPONENT}) # both not found
223 | set("${INDI_PUBLIC_VAR_NS}_${${INDI_PRIVATE_VAR_NS}_UPPER_COMPONENT}_FOUND" FALSE)
224 | set("${INDI_PUBLIC_VAR_NS}_FOUND" FALSE)
225 | else(NOT ${INDI_PRIVATE_VAR_NS}_LIB_RELEASE_${${INDI_PRIVATE_VAR_NS}_COMPONENT} AND NOT ${INDI_PRIVATE_VAR_NS}_LIB_DEBUG_${${INDI_PRIVATE_VAR_NS}_COMPONENT}) # one or both found
226 | set("${INDI_PUBLIC_VAR_NS}_${${INDI_PRIVATE_VAR_NS}_UPPER_COMPONENT}_FOUND" TRUE)
227 | if(NOT ${INDI_PRIVATE_VAR_NS}_LIB_RELEASE_${${INDI_PRIVATE_VAR_NS}_COMPONENT}) # release not found => we are in debug
228 | set(${INDI_PRIVATE_VAR_NS}_LIB_${${INDI_PRIVATE_VAR_NS}_COMPONENT} "${${INDI_PRIVATE_VAR_NS}_LIB_DEBUG_${${INDI_PRIVATE_VAR_NS}_COMPONENT}}")
229 | elseif(NOT ${INDI_PRIVATE_VAR_NS}_LIB_DEBUG_${${INDI_PRIVATE_VAR_NS}_COMPONENT}) # debug not found => we are in release
230 | set(${INDI_PRIVATE_VAR_NS}_LIB_${${INDI_PRIVATE_VAR_NS}_COMPONENT} "${${INDI_PRIVATE_VAR_NS}_LIB_RELEASE_${${INDI_PRIVATE_VAR_NS}_COMPONENT}}")
231 | else() # both found
232 | set(
233 | ${INDI_PRIVATE_VAR_NS}_LIB_${${INDI_PRIVATE_VAR_NS}_COMPONENT}
234 | optimized ${${INDI_PRIVATE_VAR_NS}_LIB_RELEASE_${${INDI_PRIVATE_VAR_NS}_COMPONENT}}
235 | debug ${${INDI_PRIVATE_VAR_NS}_LIB_DEBUG_${${INDI_PRIVATE_VAR_NS}_COMPONENT}}
236 | )
237 | endif()
238 | list(APPEND ${INDI_PUBLIC_VAR_NS}_LIBRARIES ${${INDI_PRIVATE_VAR_NS}_LIB_${${INDI_PRIVATE_VAR_NS}_COMPONENT}})
239 | endif(NOT ${INDI_PRIVATE_VAR_NS}_LIB_RELEASE_${${INDI_PRIVATE_VAR_NS}_COMPONENT} AND NOT ${INDI_PRIVATE_VAR_NS}_LIB_DEBUG_${${INDI_PRIVATE_VAR_NS}_COMPONENT})
240 | endforeach(${INDI_PRIVATE_VAR_NS}_COMPONENT)
241 |
242 | # Check find_package arguments
243 | include(FindPackageHandleStandardArgs)
244 | if(${INDI_PUBLIC_VAR_NS}_FIND_REQUIRED AND NOT ${INDI_PUBLIC_VAR_NS}_FIND_QUIETLY)
245 | find_package_handle_standard_args(
246 | ${INDI_PUBLIC_VAR_NS}
247 | REQUIRED_VARS ${INDI_PUBLIC_VAR_NS}_LIBRARIES ${INDI_PUBLIC_VAR_NS}_INCLUDE_DIR
248 | VERSION_VAR ${INDI_PUBLIC_VAR_NS}_VERSION
249 | )
250 | else(${INDI_PUBLIC_VAR_NS}_FIND_REQUIRED AND NOT ${INDI_PUBLIC_VAR_NS}_FIND_QUIETLY)
251 | find_package_handle_standard_args(${INDI_PUBLIC_VAR_NS} "INDI not found" ${INDI_PUBLIC_VAR_NS}_LIBRARIES ${INDI_PUBLIC_VAR_NS}_INCLUDE_DIR)
252 | endif(${INDI_PUBLIC_VAR_NS}_FIND_REQUIRED AND NOT ${INDI_PUBLIC_VAR_NS}_FIND_QUIETLY)
253 | else(${INDI_PUBLIC_VAR_NS}_INCLUDE_DIR)
254 | set("${INDI_PUBLIC_VAR_NS}_FOUND" FALSE)
255 | if(${INDI_PUBLIC_VAR_NS}_FIND_REQUIRED AND NOT ${INDI_PUBLIC_VAR_NS}_FIND_QUIETLY)
256 | message(FATAL_ERROR "Could not find INDI include directory")
257 | endif(${INDI_PUBLIC_VAR_NS}_FIND_REQUIRED AND NOT ${INDI_PUBLIC_VAR_NS}_FIND_QUIETLY)
258 | endif(${INDI_PUBLIC_VAR_NS}_INCLUDE_DIR)
259 |
260 | mark_as_advanced(
261 | ${INDI_PUBLIC_VAR_NS}_INCLUDE_DIR
262 | ${INDI_PUBLIC_VAR_NS}_LIBRARIES
263 | )
264 |
265 | # IN (args)
266 | indidebug("FIND_COMPONENTS")
267 | indidebug("FIND_REQUIRED")
268 | indidebug("FIND_QUIETLY")
269 | indidebug("FIND_VERSION")
270 | # OUT
271 | # Found
272 | indidebug("FOUND")
273 | indidebug("SERVER_FOUND")
274 | indidebug("DRIVERS_FOUND")
275 | indidebug("CLIENT_FOUND")
276 | indidebug("QT5CLIENT_FOUND")
277 |
278 | # Linking
279 | indidebug("INCLUDE_DIR")
280 | indidebug("DATA_DIR")
281 | indidebug("LIBRARIES")
282 | # Backward compatibility
283 | set(${INDI_PUBLIC_VAR_NS}_DRIVER_LIBRARIES ${${INDI_PUBLIC_VAR_NS}_LIBRARIES})
284 | indidebug("DRIVER_LIBRARIES")
285 | # Version
286 | indidebug("MAJOR_VERSION")
287 | indidebug("MINOR_VERSION")
288 | indidebug("RELEASE_VERSION")
289 | indidebug("VERSION")
290 |
--------------------------------------------------------------------------------