diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..0c064e24 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,7 @@ +language: cpp +sudo: required +dist: trusty +before_install: + - sudo apt-get -qq update + - sudo apt-get install -qq -y qtbase5-dev libqt5serialport5-dev libusb-1.0-0-dev python-dev libxrender-dev libavahi-core-dev libavahi-compat-libdnssd-dev +script: mkdir build && cd build && cmake -DPLATFORM=x86 -DCMAKE_BUILD_TYPE=Release .. && make -j 2 diff --git a/CMakeLists.txt b/CMakeLists.txt index 75b60527..536611e7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,10 @@ IF ( POLICY CMP0026 ) CMAKE_POLICY( SET CMP0026 OLD ) ENDIF() +SET ( HYPERION_VERSION_STABLE OFF ) +SET ( HYPERION_VERSION_MAJOR 2 ) +SET ( HYPERION_VERSION_MINOR 0 ) +SET ( HYPERION_VERSION_PATCH 0 ) SET ( DEFAULT_AMLOGIC OFF ) SET ( DEFAULT_DISPMANX OFF ) @@ -18,6 +22,7 @@ SET ( DEFAULT_SPIDEV OFF ) SET ( DEFAULT_WS2812BPWM OFF ) SET ( DEFAULT_WS281XPWM OFF ) SET ( DEFAULT_ZEROCONF ON ) +SET ( DEFAULT_USE_SHARED_AVAHI_LIBS OFF ) if (APPLE) SET ( DEFAULT_OSX ON ) @@ -36,6 +41,7 @@ else () elseif ( "${PLATFORM}" STREQUAL "x86" ) SET ( DEFAULT_X11 ON ) SET ( DEFAULT_FB ON ) + SET ( DEFAULT_USE_SHARED_AVAHI_LIBS ON ) elseif ( "${PLATFORM}" STREQUAL "imx6" ) SET ( DEFAULT_FB ON ) endif() @@ -133,8 +139,14 @@ include_directories(${CMAKE_SOURCE_DIR}/include) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -Wall") #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -std=c++11 -Wall") -find_package(Qt5 COMPONENTS Core Gui Widgets Network REQUIRED) +SET(QT_MIN_VERSION "5.2.0") +find_package(Qt5 COMPONENTS Core Gui Network REQUIRED) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}") +message( STATUS "Found Qt Version: ${Qt5Core_VERSION}" ) +IF ( "${Qt5Core_VERSION}" VERSION_LESS "${QT_MIN_VERSION}" ) + message( FATAL_ERROR "Your Qt version is to old! Minimum required ${QT_MIN_VERSION}" ) +ENDIF() + #add libusb and pthreads find_package(libusb-1.0 REQUIRED) diff --git a/CompileHowto.txt b/CompileHowto.txt index 7c5ecdaa..7cc6f820 100644 --- a/CompileHowto.txt +++ b/CompileHowto.txt @@ -1,6 +1,6 @@ # Install the required tools and dependencies sudo apt-get update -sudo apt-get install git cmake build-essential libQt4-dev libusb-1.0-0-dev python-dev libxrender-dev +sudo apt-get install git cmake build-essential qtbase5-dev libqt5serialport5-dev libusb-1.0-0-dev python-dev libxrender-dev libavahi-core-dev libavahi-compat-libdnssd-dev # RPI ONLY: when you build on the rapberry pi and include the dispmanx grabber (which is the default) # you also need the firmware including headers installed. This downloads the firmware from the raspberrypi github @@ -12,7 +12,7 @@ sudo cp -R "$FIRMWARE_DIR/hardfp/opt/" /opt # create hyperion directory and checkout the code from github # You might want to add "--depth 1" if you only want to recompile the current source or dont want to use git any further export HYPERION_DIR="hyperion" -git clone --recursive https://github.com/tvdzwan/hyperion.git "$HYPERION_DIR" +git clone --recursive https://github.com/hyperion-project/hyperion.ng.git "$HYPERION_DIR" # if you forget the --recursive in above statement or you are updating an existing clone you need # to clone the protobuf submodule by runnning the follwing two statements: @@ -24,16 +24,16 @@ mkdir "$HYPERION_DIR/build" cd "$HYPERION_DIR/build" # run cmake to generate make files on the raspberry pi WITHOUT PWM SUPPORT -cmake -DCMAKE_BUILD_TYPE=Release -Wno-dev .. +cmake -DPLATFORM=rpi -DCMAKE_BUILD_TYPE=Release .. # run cmake to generate make files on the raspberry pi WITH PWM SUPPORT -cmake -DENABLE_WS2812BPWM=ON -DENABLE_WS281XPWM=ON -DCMAKE_BUILD_TYPE=Release -Wno-dev .. -# or if you are not compiling on the raspberry pi (e.g. OrangePi) and need to disable the Dispmanx grabber and support for spi devices -cmake -DENABLE_DISPMANX=OFF -DENABLE_SPIDEV=OFF -DENABLE_X11=ON -DCMAKE_BUILD_TYPE=Release -Wno-dev .. +cmake -DPLATFORM=rpi-pwm -DCMAKE_BUILD_TYPE=Release .. +# or if you want to compile on x86x64 +cmake -DPLATFORM=x86 -DCMAKE_BUILD_TYPE=Release .. # on amlogic platforms -cmake -DENABLE_DISPMANX=OFF -DENABLE_SPIDEV=OFF -DENABLE_AMLOGIC=ON -DCMAKE_BUILD_TYPE=Release -Wno-dev .. +cmake -DPLATFORM=aml -DCMAKE_BUILD_TYPE=Release .. # as an alternative for the dispmanx grabber on non-rpi devices (e.g. cubox-i) you could try the framebuffer grabber -cmake -DENABLE_DISPMANX=OFF -DENABLE_SPIDEV=OFF -DENABLE_FB=ON -DCMAKE_BUILD_TYPE=Release -Wno-dev .. -# for OSX build you need XCode, qt4 libraries and cmake (maybe libusb too). You can use macport or homebrew(recommended) to install them: +cmake -DENABLE_FB=ON -DCMAKE_BUILD_TYPE=Release .. +# ToDo: QT5 libs!! for OSX build you need XCode, qt4 libraries and cmake (maybe libusb too). You can use macport or homebrew(recommended) to install them: #for port: sudo port install qt4-mac sudo port install cmake @@ -42,13 +42,10 @@ sudo port install cmake sudo brew install qt4-mac sudo brew install cmake #sudo brew install libusb -cmake -DENABLE_DISPMANX=OFF -DENABLE_SPIDEV=OFF -DENABLE_V4L2=OFF -DENABLE_OSX=ON .. +cmake -DENABLE_V4L2=OFF -DENABLE_OSX=ON .. -# run make to build Hyperion -make -# or if you have a system with more then 1 cpu core -make -j 4 -# "4" is the number of cpu cores (e.g. 4 on RPi2 and RPi3), this makes compile faster +# run make to build Hyperion (all available cpu cores are used) +make -j $(nproc) #after compile, to remove any stuff not needed for a release version. strip bin/* @@ -58,4 +55,4 @@ sudo cp ./bin/hyperion-remote /usr/bin/ sudo cp ./bin/hyperiond /usr/bin/ # Copy the effect folder (if you did not use the normal installation methode before) -sudo mkdir -p /opt/hyperion/effects && sudo cp -R ../effects/ /opt/hyperion/ +sudo mkdir -p /usr/share/hyperion/effects && sudo cp -R ../effects/ /usr/share/hyperion/ diff --git a/HyperionConfig.h.in b/HyperionConfig.h.in index 3ce776b5..20d6c2b6 100644 --- a/HyperionConfig.h.in +++ b/HyperionConfig.h.in @@ -34,4 +34,11 @@ #cmakedefine ENABLE_PROFILER // the hyperion build id string -#define HYPERION_VERSION_ID "${HYPERION_VERSION_ID}" +#define HYPERION_BUILD_ID "${HYPERION_BUILD_ID}" + +#define HYPERION_VERSION_MAJOR "${HYPERION_VERSION_MAJOR}" +#define HYPERION_VERSION_MINOR "${HYPERION_VERSION_MINOR}" +#define HYPERION_VERSION_PATCH "${HYPERION_VERSION_PATCH}" +#define HYPERION_VERSION "${HYPERION_VERSION_MAJOR}.${HYPERION_VERSION_MINOR}.${HYPERION_VERSION_PATCH}" + +#define HYPERION_JSON_VERSION "1.0.0" diff --git a/PULL_REQUEST_TEMPLATE b/PULL_REQUEST_TEMPLATE index 8e947083..a8e72756 100644 --- a/PULL_REQUEST_TEMPLATE +++ b/PULL_REQUEST_TEMPLATE @@ -1,6 +1,8 @@ -IMPORTANT: Please donĀ“t commit to master, we will test your changes first at the beta branch! + **1.** Tell us something about your changes. + **2.** If this changes affect the .conf file. Please provide the changed section + **3.** Reference a issue (optional) Note: For further discussions use our forum: forum.hyperion-project.org diff --git a/README.md b/README.md index ec8af595..ef708c4f 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,18 @@ HYPERION ======== -Hyperion is an opensource 'AmbiLight' implementation supported by many devices. The main features of Hyperion are: -* Low CPU load. For a led string of 50 leds the CPU usage will typically be below 1.5% on a non-overclocked Pi. -* Json interface which allows easy integration into scripts. -* A command line utility allows easy testing and configuration of the color transforms (Transformation settings are not preserved over a restart at the moment...). -* Priority channels are not coupled to a specific led data provider which means that a provider can post led data and leave without the need to maintain a connection to Hyperion. This is ideal for a remote application (like our Android app). -* HyperCon. A tool which helps generate a Hyperion configuration file. -* Kodi-checker which checks the playing status of Kodi and decides whether or not to capture the screen. -* Black border detector. -* A scriptable effect engine. -* Generic software architecture to support new devices and new algorithms easily. +This is a (alpha) development branch for the next major version of hyperion + + +Current new deps (libs) +QT5 +- sudo apt-get install libqt5core5a libqt5network5 libqt5gui5 libqt5serialport5 libusb-1.0-0 + +zeroconf +- apt-get install libavahi-core-dev libavahi-compat-libdnssd-dev + + +94MB free disc space for deps More information can be found on the official Hyperion [Wiki](https://wiki.hyperion-project.org) diff --git a/cmake/FindGitVersion.cmake b/cmake/FindGitVersion.cmake index 3ce5fe93..bbcdfb79 100644 --- a/cmake/FindGitVersion.cmake +++ b/cmake/FindGitVersion.cmake @@ -4,6 +4,6 @@ execute_process( COMMAND sh -c "git branch | grep '^*' | sed 's;^*;;g' " WORKING STRING ( STRIP "${BUILD_ID}" BUILD_ID ) STRING ( STRIP "${VERSION_ID}" VERSION_ID ) -SET ( HYPERION_VERSION_ID "${VERSION_ID} (${BUILD_ID}" ) -message ( STATUS "Current Version: ${HYPERION_VERSION_ID})" ) +SET ( HYPERION_BUILD_ID "${VERSION_ID} (${BUILD_ID})" ) +message ( STATUS "Current Version: ${HYPERION_BUILD_ID}" ) diff --git a/cmake/packages.cmake b/cmake/packages.cmake index ca821a5c..74889ec7 100644 --- a/cmake/packages.cmake +++ b/cmake/packages.cmake @@ -18,9 +18,9 @@ SET ( CPACK_RPM_PACKAGE_NAME "hyperion" ) SET ( CPACK_RPM_PACKAGE_URL "https://github.com/hyperion-project/hyperion" ) SET ( CPACK_RPM_POST_INSTALL_SCRIPT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/cmake/rpm/postinst" ) -SET(CPACK_PACKAGE_VERSION_MAJOR "1") -SET(CPACK_PACKAGE_VERSION_MINOR "3") -SET(CPACK_PACKAGE_VERSION_PATCH "0") +SET(CPACK_PACKAGE_VERSION_MAJOR "${HYPERION_VERSION_MAJOR}") +SET(CPACK_PACKAGE_VERSION_MINOR "${HYPERION_VERSION_MINOR}") +SET(CPACK_PACKAGE_VERSION_PATCH "${HYPERION_VERSION_PATCH}") SET ( CPACK_COMPONENTS_ALL ambilight ) SET ( CPACK_ARCHIVE_COMPONENT_INSTALL ON ) diff --git a/config/hyperion.config.json.example b/config/hyperion.config.json.commented similarity index 87% rename from config/hyperion.config.json.example rename to config/hyperion.config.json.commented index 9d09f39c..bf5098de 100644 --- a/config/hyperion.config.json.example +++ b/config/hyperion.config.json.commented @@ -7,14 +7,14 @@ /// Device configuration contains the following fields: /// * 'name' : The user friendly name of the device (only used for display purposes) /// * 'type' : The type of the device or leds (known types for now are - /// APA102, WS2801, P9813, LPD6803, LPD8806, ---------PWM---------, WS2812b (just RPi1), WS281X (RPi1, RPi2, RPi3), --------OTHER--------, PhilipsHUE, AtmoOrb, PiBlaster, Tinkerforge, FadeCandy, RawHID (USB), UDP, SEDU, TPM2, USBASP-WS2801, USBASP-WS2812, ------3rd PARTY------, Adalight, AdalightAPA102, AmbiLed, Atmo, Lightpack, Multi-Lightpack, Paintpack, Test (file), None) + /// APA102, WS2801, P9813, LPD6803, LPD8806, ---------PWM---------, WS2812b (just RPi1), WS281X (RPi1, RPi2, RPi3), --------OTHER--------, PhilipsHUE, AtmoOrb, PiBlaster, Tinkerforge, FadeCandy, RawHID (USB), UDP, SEDU, TPM2, USBASP-WS2801, USBASP-WS2812, ------3rd PARTY------, Adalight, AdalightAPA102, Atmo, Lightpack, Multi-Lightpack, Paintpack, Test (file), None) /// * [device type specific configuration] /// * 'colorOrder' : The order of the color bytes ('rgb', 'rbg', 'bgr', etc.). "device" : { "name" : "MyHyperionConfig", - "type" : "ws2801", - "output" : "/dev/spidev0.0", + "type" : "file", + "output" : "/dev/null", "rate" : 1000000, "colorOrder" : "rgb" }, @@ -134,134 +134,6 @@ } }, - /// The black border configuration, contains the following items: - /// * enable : true if the detector should be activated - /// * threshold : Value below which a pixel is regarded as black (value between 0.0 and 1.0) - /// * unknownFrameCnt : Number of frames without any detection before the border is set to 0 (default 600) - /// * borderFrameCnt : Number of frames before a consistent detected border gets set (default 50) - /// * maxInconsistentCnt : Number of inconsistent frames that are ignored before a new border gets a chance to proof consistency - /// * blurRemoveCnt : Number of pixels that get removed from the detected border to cut away blur (default 1) - /// * mode : Border detection mode (values=default,classic,osd) - "blackborderdetector" : - { - "enable" : true, - "threshold" : 0.0, - "unknownFrameCnt" : 600, - "borderFrameCnt" : 50, - "maxInconsistentCnt" : 10, - "blurRemoveCnt" : 1, - "mode" : "default" - }, - - /// The configuration of the effect engine, contains the following items: - /// * paths : An array with absolute/relative location(s) of directories with effects - "effects" : - { - "paths" : - [ - "/usr/share/hyperion/effects" - ] - }, - - /// Boot sequence configuration. Start effect / set color at startup of hyperion - /// HINT inital background color is not shown, when any other grabber is active - /// * color : Set initial background color on startup -> set effect to "" (empty) and input the values [R,G,B] and set duration_ms NOT to 0 (use 1) instead - /// * effect : The effect is shown when hyperion starts - /// * duration_ms : The duration of the selected effect (0=endless) - /// * priority : The priority of the selected effect/initial background color (default=990, if duration is 0) - /// when duration > 0 => priority is set to 0, otherwise priority is set to configured value - /// HINT: lower value result in HIGHER priority! - "bootsequence" : - { - "color" : [0,0,0], - "effect" : "Rainbow swirl fast", - "duration_ms" : 3000, - "priority" : 990 - }, - - /// Configuration of webserver integrated in hyperion. - /// * enable : enable the server or not - /// * document_root : path to hyperion webapp files - /// * port : the port where hyperion webapp is accasible - "webConfig" : - { - "enable" : true, - "document_root" : "/usr/share/hyperion/webconfig", - "port" : 8099 - }, - - /// The configuration of the Json/Proto forwarder. Forward messages to multiple instances of Hyperion on same and/or other hosts - /// 'proto' is mostly used for video streams and 'json' for effects - /// * proto : Proto server adress and port of your target. Syntax:[IP:PORT] -> ["127.0.0.1:19447"] or more instances to forward ["127.0.0.1:19447","192.168.0.24:19449"] - /// * json : Json server adress and port of your target. Syntax:[IP:PORT] -> ["127.0.0.1:19446"] or more instances to forward ["127.0.0.1:19446","192.168.0.24:19448"] - /// HINT:If you redirect to "127.0.0.1" (localhost) you could start a second hyperion with another device/led config! - /// Be sure your client(s) is/are listening on the configured ports. The second Hyperion (if used) also needs to be configured! (HyperCon -> External -> Json Server/Proto Server) - "forwarder" : - { - "proto" : ["127.0.0.1:19447"], - "json" : ["127.0.0.1:19446"] - }, - - /// The configuration for the frame-grabber, contains the following items: - /// * width : The width of the grabbed frames [pixels] - /// * height : The height of the grabbed frames [pixels] - /// * frequency_Hz : The frequency of the frame grab [Hz] - /// * priority : The priority of the frame-gabber (Default=890) HINT: lower value result in HIGHER priority! - /// * ATTENTION : Power-of-Two resolution is not supported and leads to unexpected behaviour! - "framegrabber" : - { - "width" : 64, - "height" : 64, - "frequency_Hz" : 10.0, - "priority" : 890 - }, - - /// The configuration of the Kodi connection used to enable and disable the frame-grabber. Contains the following fields: - /// * xbmcAddress : The IP address of the Kodi-host - /// * xbmcTcpPort : The TCP-port of the Kodi-server - /// * grabVideo : Flag indicating that the frame-grabber is on(true) during video playback - /// * grabPictures : Flag indicating that the frame-grabber is on(true) during picture show - /// * grabAudio : Flag indicating that the frame-grabber is on(true) during audio playback - /// * grabMenu : Flag indicating that the frame-grabber is on(true) at the Kodi menu - /// * grabPause : Flag indicating that the frame-grabber is on(true) at player state "pause" - /// * grabScreensaver : Flag indicating that the frame-grabber is on(true) when Kodi is on screensaver - /// * enable3DDetection : Flag indicating that the frame-grabber should switch to a 3D compatible modus if a 3D video is playing - "xbmcVideoChecker" : - { - "xbmcAddress" : "127.0.0.1", - "xbmcTcpPort" : 9090, - "grabVideo" : true, - "grabPictures" : true, - "grabAudio" : true, - "grabMenu" : false, - "grabPause" : false, - "grabScreensaver" : true, - "enable3DDetection" : true - }, - - /// The configuration of the Json server which enables the json remote interface - /// * port : Port at which the json server is started - "jsonServer" : - { - "port" : 19444 - }, - - /// The configuration of the Proto server which enables the protobuffer remote interface - /// * port : Port at which the protobuffer server is started - "protoServer" : - { - "port" : 19445 - }, - - /// The configuration of the boblight server which enables the boblight remote interface - /// * port : Port at which the boblight server is started - /// * priority : Priority of the boblight server (Default=900) HINT: lower value result in HIGHER priority! - "boblightServer" : - { - "port" : 19333, - "priority" : 900 - }, - /// Configuration for the embedded V4L2 grabber /// * device : V4L2 Device to use [default="/dev/video0"] /// * input : V4L2 input to use [default=0] @@ -299,6 +171,155 @@ "blueSignalThreshold" : 0.0 }, + /// The configuration for the frame-grabber, contains the following items: + /// * width : The width of the grabbed frames [pixels] + /// * height : The height of the grabbed frames [pixels] + /// * frequency_Hz : The frequency of the frame grab [Hz] + /// * priority : The priority of the frame-gabber (Default=890) HINT: lower value result in HIGHER priority! + /// * ATTENTION : Power-of-Two resolution is not supported and leads to unexpected behaviour! + "framegrabber" : + { + "width" : 64, + "height" : 64, + "frequency_Hz" : 10.0, + "priority" : 890 + }, + + /// The black border configuration, contains the following items: + /// * enable : true if the detector should be activated + /// * threshold : Value below which a pixel is regarded as black (value between 0.0 and 1.0) + /// * unknownFrameCnt : Number of frames without any detection before the border is set to 0 (default 600) + /// * borderFrameCnt : Number of frames before a consistent detected border gets set (default 50) + /// * maxInconsistentCnt : Number of inconsistent frames that are ignored before a new border gets a chance to proof consistency + /// * blurRemoveCnt : Number of pixels that get removed from the detected border to cut away blur (default 1) + /// * mode : Border detection mode (values=default,classic,osd) + "blackborderdetector" : + { + "enable" : true, + "threshold" : 0.0, + "unknownFrameCnt" : 600, + "borderFrameCnt" : 50, + "maxInconsistentCnt" : 10, + "blurRemoveCnt" : 1, + "mode" : "default" + }, + + /// The configuration of the Kodi connection used to enable and disable the frame-grabber. Contains the following fields: + /// * xbmcAddress : The IP address of the Kodi-host + /// * xbmcTcpPort : The TCP-port of the Kodi-server + /// * grabVideo : Flag indicating that the frame-grabber is on(true) during video playback + /// * grabPictures : Flag indicating that the frame-grabber is on(true) during picture show + /// * grabAudio : Flag indicating that the frame-grabber is on(true) during audio playback + /// * grabMenu : Flag indicating that the frame-grabber is on(true) at the Kodi menu + /// * grabPause : Flag indicating that the frame-grabber is on(true) at player state "pause" + /// * grabScreensaver : Flag indicating that the frame-grabber is on(true) when Kodi is on screensaver + /// * enable3DDetection : Flag indicating that the frame-grabber should switch to a 3D compatible modus if a 3D video is playing + "xbmcVideoChecker" : + { + "xbmcAddress" : "127.0.0.1", + "xbmcTcpPort" : 9090, + "grabVideo" : true, + "grabPictures" : true, + "grabAudio" : true, + "grabMenu" : false, + "grabPause" : false, + "grabScreensaver" : true, + "enable3DDetection" : true + }, + + /// Initial Effect sets a "booteffect" or "color" (foreground-effect) and optional set a "effect" or "color" during inactive grabbers and network receivers (background-effect) + /// * background-effect : 2 options: set a effect (example: "Rainbow swirl fast") or set a color (RGB) (example: [255,134,0]) + /// * background-effect-args : Set optional effect arguments (Have a look at the select effect to get the possible values) + /// * foreground-effect : 2 options: set a effect (example: "Rainbow swirl fast") or set a color (RGB) (example: [255,134,0]) + /// * foreground-effect-args : Set optional effect arguments (Have a look at the select effect to get the possible values) + /// * foreground-duration_ms : The duration of the selected foreground-effect or color (0=endless) + /// HINT: "foreground-effect" starts always with priority 0, so it blocks all remotes and grabbers if the loop is endless + /// HINT: Set a empty value if you want to disable a component (example: "") + "initialEffect" : + { + "background-effect" : "Full color mood blobs", + "background-effect-args" : {}, + "foreground-effect" : "Rainbow swirl fast", + "foreground-effect-args" : {}, + "foreground-duration_ms" : 3000 + }, + + /// The configuration of the Json/Proto forwarder. Forward messages to multiple instances of Hyperion on same and/or other hosts + /// 'proto' is mostly used for video streams and 'json' for effects + /// * proto : Proto server adress and port of your target. Syntax:[IP:PORT] -> ["127.0.0.1:19447"] or more instances to forward ["127.0.0.1:19447","192.168.0.24:19449"] + /// * json : Json server adress and port of your target. Syntax:[IP:PORT] -> ["127.0.0.1:19446"] or more instances to forward ["127.0.0.1:19446","192.168.0.24:19448"] + /// HINT:If you redirect to "127.0.0.1" (localhost) you could start a second hyperion with another device/led config! + /// Be sure your client(s) is/are listening on the configured ports. The second Hyperion (if used) also needs to be configured! (HyperCon -> External -> Json Server/Proto Server) + "forwarder" : + { + "proto" : ["127.0.0.1:19447"], + "json" : ["127.0.0.1:19446"] + }, + + /// The configuration of the Json server which enables the json remote interface + /// * port : Port at which the json server is started + "jsonServer" : + { + "port" : 19444 + }, + + /// The configuration of the Proto server which enables the protobuffer remote interface + /// * port : Port at which the protobuffer server is started + "protoServer" : + { + "port" : 19445 + }, + + /// The configuration of the boblight server which enables the boblight remote interface + /// * enable : Enable or disable the boblight server (true/false) + /// * port : Port at which the boblight server is started + /// * priority : Priority of the boblight server (Default=800) HINT: lower value result in HIGHER priority! + "boblightServer" : + { + "enable" : false, + "port" : 19333, + "priority" : 800 + }, + + /// The configuration of the udp listener + /// * enable : Enable or disable the udp listener (true/false) + /// * address : The listener address, pre configured is multicast which listen also to unicast ip addresses at the same time. If emtpy, multicast is disabled and it also accepts unicast from all IPs + /// * port : Port at which the udp listener starts + /// * priority : Priority of the udp lstener server (Default=800) + /// * timeout : The timeout sets the timelimit for a "soft" off of the udp listener, if no packages are received (for example to switch to a gabber or InitialEffect - background-effect) + /// * shared : If true, the udp listener is shared across all hyperion instances (if using more than one (forwarder)) + "udpListener" : + { + "enable" : false, + "address" : "239.255.28.01", + "port" : 2801, + "priority" : 800, + "timeout" : 10000, + "shared" : false + }, + + /// Configuration of the Hyperion webserver + /// * enable : enable ir disable the webserver (true/false) + /// * document_root : path to hyperion webapp files + /// * port : the port where hyperion webapp is accasible + "webConfig" : + { + "enable" : true, + "document_root" : "/usr/share/hyperion/webconfig", + "port" : 8099 + }, + + /// The configuration of the effect engine, contains the following items: + /// * paths : An array with absolute/relative location(s) of directories with effects + "effects" : + { + "paths" : + [ + "/storage/hyperion/effects", + "/usr/share/hyperion/effects" + ] + }, + /// The configuration for each individual led. This contains the specification of the area /// averaged of an input image for each led to determine its color. Each item in the list /// contains the following fields: @@ -308,6 +329,7 @@ /// (minimum and maximum inclusive) /// * vscan: The fractional part of the image along the vertical used for the averaging /// (minimum and maximum inclusive) + "leds" : [ { diff --git a/config/hyperion.config.json.default b/config/hyperion.config.json.default new file mode 100644 index 00000000..ed20e340 --- /dev/null +++ b/config/hyperion.config.json.default @@ -0,0 +1,429 @@ +{ + "device" : + { + "name" : "DefaultHyperionConfig", + "type" : "file", + "output" : "/dev/null", + "rate" : 1000000, + "colorOrder" : "rgb" + }, + + "color" : + { + "channelAdjustment" : + [ + { + "id" : "default", + "leds" : "*", + "pureRed" : + { + "redChannel" : 255, + "greenChannel" : 0, + "blueChannel" : 0 + }, + "pureGreen" : + { + "redChannel" : 0, + "greenChannel" : 255, + "blueChannel" : 0 + }, + "pureBlue" : + { + "redChannel" : 0, + "greenChannel" : 0, + "blueChannel" : 255 + } + } + ], + "temperature" : + [ + { + "id" : "default", + "leds" : "*", + "correctionValues" : + { + "red" : 255, + "green" : 255, + "blue" : 255 + } + } + ], + "transform" : + [ + { + "id" : "default", + "leds" : "*", + "hsl" : + { + "saturationGain" : 1.0000, + "luminanceGain" : 1.0000, + "luminanceMinimum" : 0.0000 + }, + "red" : + { + "threshold" : 0.0000, + "gamma" : 2.5000 + }, + "green" : + { + "threshold" : 0.0000, + "gamma" : 2.5000 + }, + "blue" : + { + "threshold" : 0.0000, + "gamma" : 2.5000 + } + } + ], + "smoothing" : + { + "type" : "linear", + "time_ms" : 200, + "updateFrequency" : 20.0000, + "updateDelay" : 0 + } + }, + + "grabber-v4l2" : + { + "device" : "/dev/video0", + "input" : 0, + "standard" : "PAL", + "width" : -1, + "height" : -1, + "frameDecimation" : 2, + "sizeDecimation" : 8, + "priority" : 900, + "mode" : "2D", + "cropLeft" : 15, + "cropRight" : 12, + "cropTop" : 5, + "cropBottom" : 5, + "redSignalThreshold" : 0.0, + "greenSignalThreshold" : 0.0, + "blueSignalThreshold" : 0.0 + }, + + "framegrabber" : + { + "width" : 128, + "height" : 128, + "frequency_Hz" : 10.0, + "priority" : 890 + }, + + "blackborderdetector" : + { + "enable" : true, + "threshold" : 0.0, + "mode" : "default" + }, + + "xbmcVideoChecker" : + { + "xbmcAddress" : "localhost", + "xbmcTcpPort" : 9090, + "grabVideo" : true, + "grabPictures" : true, + "grabAudio" : true, + "grabMenu" : false, + "grabPause" : false, + "grabScreensaver" : true, + "enable3DDetection" : true + }, + + "initialEffect" : + { + "background-effect" : "Full color mood blobs", + "background-effect-args" : {}, + "foreground-effect" : "Rainbow swirl fast", + "foreground-effect-args" : {}, + "foreground-duration_ms" : 3000 + }, + + "forwarder" : + { + "json" : ["127.0.0.1:19446"], + "proto" : ["127.0.0.1:19447"] + }, + + "jsonServer" : + { + "port" : 19444 + }, + + "protoServer" : + { + "port" : 19445 + }, + + "boblightServer" : + { + "enable" : false, + "port" : 19333, + "priority" : 800 + }, + + "udpListener" : + { + "enable" : false, + "address" : "239.255.28.01", + "port" : 2801, + "priority" : 800, + "timeout" : 10000, + "shared" : false + }, + + "webConfig" : + { + "enable" : true, + "document_root" : "/usr/share/hyperion/webconfig", + "port" : 8099 + }, + + "effects" : + { + "paths" : + [ + "/storage/hyperion/effects", + "/usr/share/hyperion/effects" + ] + }, + + "leds" : + [ + { + "index" : 0, + "hscan" : { "minimum" : 0.5000, "maximum" : 0.5625 }, + "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } + }, + { + "index" : 1, + "hscan" : { "minimum" : 0.4375, "maximum" : 0.5000 }, + "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } + }, + { + "index" : 2, + "hscan" : { "minimum" : 0.3750, "maximum" : 0.4375 }, + "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } + }, + { + "index" : 3, + "hscan" : { "minimum" : 0.3125, "maximum" : 0.3750 }, + "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } + }, + { + "index" : 4, + "hscan" : { "minimum" : 0.2500, "maximum" : 0.3125 }, + "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } + }, + { + "index" : 5, + "hscan" : { "minimum" : 0.1875, "maximum" : 0.2500 }, + "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } + }, + { + "index" : 6, + "hscan" : { "minimum" : 0.1250, "maximum" : 0.1875 }, + "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } + }, + { + "index" : 7, + "hscan" : { "minimum" : 0.0625, "maximum" : 0.1250 }, + "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } + }, + { + "index" : 8, + "hscan" : { "minimum" : 0.0000, "maximum" : 0.0625 }, + "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } + }, + { + "index" : 9, + "hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, + "vscan" : { "minimum" : 0.8571, "maximum" : 1.0000 } + }, + { + "index" : 10, + "hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, + "vscan" : { "minimum" : 0.7143, "maximum" : 0.8571 } + }, + { + "index" : 11, + "hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, + "vscan" : { "minimum" : 0.5714, "maximum" : 0.7143 } + }, + { + "index" : 12, + "hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, + "vscan" : { "minimum" : 0.4286, "maximum" : 0.5714 } + }, + { + "index" : 13, + "hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, + "vscan" : { "minimum" : 0.2857, "maximum" : 0.4286 } + }, + { + "index" : 14, + "hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, + "vscan" : { "minimum" : 0.1429, "maximum" : 0.2857 } + }, + { + "index" : 15, + "hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.1429 } + }, + { + "index" : 16, + "hscan" : { "minimum" : 0.0000, "maximum" : 0.0625 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } + }, + { + "index" : 17, + "hscan" : { "minimum" : 0.0625, "maximum" : 0.1250 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } + }, + { + "index" : 18, + "hscan" : { "minimum" : 0.1250, "maximum" : 0.1875 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } + }, + { + "index" : 19, + "hscan" : { "minimum" : 0.1875, "maximum" : 0.2500 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } + }, + { + "index" : 20, + "hscan" : { "minimum" : 0.2500, "maximum" : 0.3125 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } + }, + { + "index" : 21, + "hscan" : { "minimum" : 0.3125, "maximum" : 0.3750 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } + }, + { + "index" : 22, + "hscan" : { "minimum" : 0.3750, "maximum" : 0.4375 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } + }, + { + "index" : 23, + "hscan" : { "minimum" : 0.4375, "maximum" : 0.5000 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } + }, + { + "index" : 24, + "hscan" : { "minimum" : 0.5000, "maximum" : 0.5625 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } + }, + { + "index" : 25, + "hscan" : { "minimum" : 0.5625, "maximum" : 0.6250 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } + }, + { + "index" : 26, + "hscan" : { "minimum" : 0.6250, "maximum" : 0.6875 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } + }, + { + "index" : 27, + "hscan" : { "minimum" : 0.6875, "maximum" : 0.7500 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } + }, + { + "index" : 28, + "hscan" : { "minimum" : 0.7500, "maximum" : 0.8125 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } + }, + { + "index" : 29, + "hscan" : { "minimum" : 0.8125, "maximum" : 0.8750 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } + }, + { + "index" : 30, + "hscan" : { "minimum" : 0.8750, "maximum" : 0.9375 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } + }, + { + "index" : 31, + "hscan" : { "minimum" : 0.9375, "maximum" : 1.0000 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } + }, + { + "index" : 32, + "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, + "vscan" : { "minimum" : 0.0000, "maximum" : 0.1429 } + }, + { + "index" : 33, + "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, + "vscan" : { "minimum" : 0.1429, "maximum" : 0.2857 } + }, + { + "index" : 34, + "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, + "vscan" : { "minimum" : 0.2857, "maximum" : 0.4286 } + }, + { + "index" : 35, + "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, + "vscan" : { "minimum" : 0.4286, "maximum" : 0.5714 } + }, + { + "index" : 36, + "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, + "vscan" : { "minimum" : 0.5714, "maximum" : 0.7143 } + }, + { + "index" : 37, + "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, + "vscan" : { "minimum" : 0.7143, "maximum" : 0.8571 } + }, + { + "index" : 38, + "hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, + "vscan" : { "minimum" : 0.8571, "maximum" : 1.0000 } + }, + { + "index" : 39, + "hscan" : { "minimum" : 0.9375, "maximum" : 1.0000 }, + "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } + }, + { + "index" : 40, + "hscan" : { "minimum" : 0.8750, "maximum" : 0.9375 }, + "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } + }, + { + "index" : 41, + "hscan" : { "minimum" : 0.8125, "maximum" : 0.8750 }, + "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } + }, + { + "index" : 42, + "hscan" : { "minimum" : 0.7500, "maximum" : 0.8125 }, + "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } + }, + { + "index" : 43, + "hscan" : { "minimum" : 0.6875, "maximum" : 0.7500 }, + "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } + }, + { + "index" : 44, + "hscan" : { "minimum" : 0.6250, "maximum" : 0.6875 }, + "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } + }, + { + "index" : 45, + "hscan" : { "minimum" : 0.5625, "maximum" : 0.6250 }, + "vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } + } + ], + + "endOfJson" : "endOfJson" +} diff --git a/dependencies/CMakeLists.txt b/dependencies/CMakeLists.txt index 26dd96c5..07dc7af4 100644 --- a/dependencies/CMakeLists.txt +++ b/dependencies/CMakeLists.txt @@ -1,7 +1,6 @@ add_subdirectory(build/getoptPlusPlus) add_subdirectory(build/hidapi) add_subdirectory(build/jsoncpp) -add_subdirectory(build/serial) add_subdirectory(build/tinkerforge) if(ENABLE_WS281XPWM) diff --git a/dependencies/build/serial/CMakeLists.txt b/dependencies/build/serial/CMakeLists.txt deleted file mode 100644 index b41ad700..00000000 --- a/dependencies/build/serial/CMakeLists.txt +++ /dev/null @@ -1,23 +0,0 @@ - -project(serialport) - -include_directories(../../include) - -## Sources -set(serial_SRCS - src/serial.cc - ../../include/serial/serial.h - ../../include/serial/v8stdint.h) - -if(UNIX) - list(APPEND serial_SRCS src/impl/unix.cc) -else() - list(APPEND serial_SRCS src/impl/win.cc) -endif() - -## Add serial library -add_library(${PROJECT_NAME} ${serial_SRCS}) - -if(UNIX AND NOT APPLE) - target_link_libraries(${PROJECT_NAME} rt) -endif() diff --git a/dependencies/build/serial/include/serial/impl/unix.h b/dependencies/build/serial/include/serial/impl/unix.h deleted file mode 100644 index a7985da3..00000000 --- a/dependencies/build/serial/include/serial/impl/unix.h +++ /dev/null @@ -1,204 +0,0 @@ -/*! - * \file serial/impl/unix.h - * \author William Woodall - * \author John Harrison - * \version 0.1 - * - * \section LICENSE - * - * The MIT License - * - * Copyright (c) 2012 William Woodall, John Harrison - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * \section DESCRIPTION - * - * This provides a unix based pimpl for the Serial class. This implementation is - * based off termios.h and uses select for multiplexing the IO ports. - * - */ - -#if !defined(_WIN32) - -#ifndef SERIAL_IMPL_UNIX_H -#define SERIAL_IMPL_UNIX_H - -#include "serial/serial.h" - -#include - -namespace serial { - -using std::size_t; -using std::string; -using std::invalid_argument; - -using serial::SerialException; -using serial::IOException; - -class serial::Serial::SerialImpl { -public: - SerialImpl (const string &port, - unsigned long baudrate, - bytesize_t bytesize, - parity_t parity, - stopbits_t stopbits, - flowcontrol_t flowcontrol); - - virtual ~SerialImpl (); - - void - open (); - - void - close (); - - bool - isOpen () const; - - size_t - available (); - - size_t - read (uint8_t *buf, size_t size = 1); - - size_t - write (const uint8_t *data, size_t length); - - void - flush (); - - void - flushInput (); - - void - flushOutput (); - - void - sendBreak (int duration); - - void - setBreak (bool level); - - void - setRTS (bool level); - - void - setDTR (bool level); - - bool - waitForChange (); - - bool - getCTS (); - - bool - getDSR (); - - bool - getRI (); - - bool - getCD (); - - void - setPort (const string &port); - - string - getPort () const; - - void - setTimeout (Timeout &timeout); - - Timeout - getTimeout () const; - - void - setBaudrate (unsigned long baudrate); - - unsigned long - getBaudrate () const; - - void - setBytesize (bytesize_t bytesize); - - bytesize_t - getBytesize () const; - - void - setParity (parity_t parity); - - parity_t - getParity () const; - - void - setStopbits (stopbits_t stopbits); - - stopbits_t - getStopbits () const; - - void - setFlowcontrol (flowcontrol_t flowcontrol); - - flowcontrol_t - getFlowcontrol () const; - - void - readLock (); - - void - readUnlock (); - - void - writeLock (); - - void - writeUnlock (); - -protected: - void reconfigurePort (); - -private: - string port_; // Path to the file descriptor - int fd_; // The current file descriptor - - bool is_open_; - bool xonxoff_; - bool rtscts_; - - Timeout timeout_; // Timeout for read operations - unsigned long baudrate_; // Baudrate - - parity_t parity_; // Parity - bytesize_t bytesize_; // Size of the bytes - stopbits_t stopbits_; // Stop Bits - flowcontrol_t flowcontrol_; // Flow Control - - // Mutex used to lock the read functions - pthread_mutex_t read_mutex; - // Mutex used to lock the write functions - pthread_mutex_t write_mutex; -}; - -} - -#endif // SERIAL_IMPL_UNIX_H - -#endif // !defined(_WIN32) diff --git a/dependencies/build/serial/include/serial/impl/win.h b/dependencies/build/serial/include/serial/impl/win.h deleted file mode 100644 index 605f5d0f..00000000 --- a/dependencies/build/serial/include/serial/impl/win.h +++ /dev/null @@ -1,201 +0,0 @@ -/*! - * \file serial/impl/windows.h - * \author William Woodall - * \author John Harrison - * \version 0.1 - * - * \section LICENSE - * - * The MIT License - * - * Copyright (c) 2012 William Woodall, John Harrison - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * \section DESCRIPTION - * - * This provides a windows implementation of the Serial class interface. - * - */ - -#if defined(_WIN32) - -#ifndef SERIAL_IMPL_WINDOWS_H -#define SERIAL_IMPL_WINDOWS_H - -#include "serial/serial.h" - -#include "windows.h" - -namespace serial { - -using std::string; -using std::wstring; -using std::invalid_argument; - -using serial::SerialException; -using serial::IOException; - -class serial::Serial::SerialImpl { -public: - SerialImpl (const string &port, - unsigned long baudrate, - bytesize_t bytesize, - parity_t parity, - stopbits_t stopbits, - flowcontrol_t flowcontrol); - - virtual ~SerialImpl (); - - void - open (); - - void - close (); - - bool - isOpen () const; - - size_t - available (); - - size_t - read (uint8_t *buf, size_t size = 1); - - size_t - write (const uint8_t *data, size_t length); - - void - flush (); - - void - flushInput (); - - void - flushOutput (); - - void - sendBreak (int duration); - - void - setBreak (bool level); - - void - setRTS (bool level); - - void - setDTR (bool level); - - bool - waitForChange (); - - bool - getCTS (); - - bool - getDSR (); - - bool - getRI (); - - bool - getCD (); - - void - setPort (const string &port); - - string - getPort () const; - - void - setTimeout (Timeout &timeout); - - Timeout - getTimeout () const; - - void - setBaudrate (unsigned long baudrate); - - unsigned long - getBaudrate () const; - - void - setBytesize (bytesize_t bytesize); - - bytesize_t - getBytesize () const; - - void - setParity (parity_t parity); - - parity_t - getParity () const; - - void - setStopbits (stopbits_t stopbits); - - stopbits_t - getStopbits () const; - - void - setFlowcontrol (flowcontrol_t flowcontrol); - - flowcontrol_t - getFlowcontrol () const; - - void - readLock (); - - void - readUnlock (); - - void - writeLock (); - - void - writeUnlock (); - -protected: - void reconfigurePort (); - -private: - wstring port_; // Path to the file descriptor - HANDLE fd_; - - bool is_open_; - - Timeout timeout_; // Timeout for read operations - unsigned long baudrate_; // Baudrate - - parity_t parity_; // Parity - bytesize_t bytesize_; // Size of the bytes - stopbits_t stopbits_; // Stop Bits - flowcontrol_t flowcontrol_; // Flow Control - - // Mutex used to lock the read functions - HANDLE read_mutex; - // Mutex used to lock the write functions - HANDLE write_mutex; -}; - -} - -#endif // SERIAL_IMPL_WINDOWS_H - -#endif // if defined(_WIN32) diff --git a/dependencies/build/serial/include/serial/serial.h b/dependencies/build/serial/include/serial/serial.h deleted file mode 100644 index bf664c9c..00000000 --- a/dependencies/build/serial/include/serial/serial.h +++ /dev/null @@ -1,700 +0,0 @@ -/*! - * \file serial/serial.h - * \author William Woodall - * \author John Harrison - * \version 0.1 - * - * \section LICENSE - * - * The MIT License - * - * Copyright (c) 2012 William Woodall - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * \section DESCRIPTION - * - * This provides a cross platform interface for interacting with Serial Ports. - */ - -#ifndef SERIAL_H -#define SERIAL_H - -#include -#include -#include -#include -#include -#include -#include -#include - -#define THROW(exceptionClass, message) throw exceptionClass(__FILE__, \ -__LINE__, (message) ) - -namespace serial { - -/*! - * Enumeration defines the possible bytesizes for the serial port. - */ -typedef enum { - fivebits = 5, - sixbits = 6, - sevenbits = 7, - eightbits = 8 -} bytesize_t; - -/*! - * Enumeration defines the possible parity types for the serial port. - */ -typedef enum { - parity_none = 0, - parity_odd = 1, - parity_even = 2 -} parity_t; - -/*! - * Enumeration defines the possible stopbit types for the serial port. - */ -typedef enum { - stopbits_one = 1, - stopbits_two = 2, - stopbits_one_point_five -} stopbits_t; - -/*! - * Enumeration defines the possible flowcontrol types for the serial port. - */ -typedef enum { - flowcontrol_none = 0, - flowcontrol_software, - flowcontrol_hardware -} flowcontrol_t; - -/*! - * Structure for setting the timeout of the serial port, times are - * in milliseconds. - * - * In order to disable the interbyte timeout, set it to Timeout::max(). - */ -struct Timeout { -#ifdef max -# undef max -#endif - static uint32_t max() {return std::numeric_limits::max();} - /*! - * Convenience function to generate Timeout structs using a - * single absolute timeout. - * - * \param timeout A long that defines the time in milliseconds until a - * timeout occurs after a call to read or write is made. - * - * \return Timeout struct that represents this simple timeout provided. - */ - static Timeout simpleTimeout(uint32_t timeout) { - return Timeout(max(), timeout, 0, timeout, 0); - } - - /*! Number of milliseconds between bytes received to timeout on. */ - uint32_t inter_byte_timeout; - /*! A constant number of milliseconds to wait after calling read. */ - uint32_t read_timeout_constant; - /*! A multiplier against the number of requested bytes to wait after - * calling read. - */ - uint32_t read_timeout_multiplier; - /*! A constant number of milliseconds to wait after calling write. */ - uint32_t write_timeout_constant; - /*! A multiplier against the number of requested bytes to wait after - * calling write. - */ - uint32_t write_timeout_multiplier; - - explicit Timeout (uint32_t inter_byte_timeout_=0, - uint32_t read_timeout_constant_=0, - uint32_t read_timeout_multiplier_=0, - uint32_t write_timeout_constant_=0, - uint32_t write_timeout_multiplier_=0) - : inter_byte_timeout(inter_byte_timeout_), - read_timeout_constant(read_timeout_constant_), - read_timeout_multiplier(read_timeout_multiplier_), - write_timeout_constant(write_timeout_constant_), - write_timeout_multiplier(write_timeout_multiplier_) - {} -}; - -/*! - * Class that provides a portable serial port interface. - */ -class Serial { -public: - /*! - * Creates a Serial object and opens the port if a port is specified, - * otherwise it remains closed until serial::Serial::open is called. - * - * \param port A std::string containing the address of the serial port, - * which would be something like 'COM1' on Windows and '/dev/ttyS0' - * on Linux. - * - * \param baudrate An unsigned 32-bit integer that represents the baudrate - * - * \param timeout A serial::Timeout struct that defines the timeout - * conditions for the serial port. \see serial::Timeout - * - * \param bytesize Size of each byte in the serial transmission of data, - * default is eightbits, possible values are: fivebits, sixbits, sevenbits, - * eightbits - * - * \param parity Method of parity, default is parity_none, possible values - * are: parity_none, parity_odd, parity_even - * - * \param stopbits Number of stop bits used, default is stopbits_one, - * possible values are: stopbits_one, stopbits_one_point_five, stopbits_two - * - * \param flowcontrol Type of flowcontrol used, default is - * flowcontrol_none, possible values are: flowcontrol_none, - * flowcontrol_software, flowcontrol_hardware - * - * \throw serial::PortNotOpenedException - * \throw serial::IOException - * \throw std::invalid_argument - */ - Serial (const std::string &port = "", - uint32_t baudrate = 9600, - Timeout timeout = Timeout(), - bytesize_t bytesize = eightbits, - parity_t parity = parity_none, - stopbits_t stopbits = stopbits_one, - flowcontrol_t flowcontrol = flowcontrol_none); - - /*! Destructor */ - virtual ~Serial (); - - /*! - * Opens the serial port as long as the port is set and the port isn't - * already open. - * - * If the port is provided to the constructor then an explicit call to open - * is not needed. - * - * \see Serial::Serial - * - * \throw std::invalid_argument - * \throw serial::SerialException - * \throw serial::IOException - */ - void - open (); - - /*! Gets the open status of the serial port. - * - * \return Returns true if the port is open, false otherwise. - */ - bool - isOpen () const; - - /*! Closes the serial port. */ - void - close (); - - /*! Return the number of characters in the buffer. */ - size_t - available (); - - /*! Read a given amount of bytes from the serial port into a given buffer. - * - * The read function will return in one of three cases: - * * The number of requested bytes was read. - * * In this case the number of bytes requested will match the size_t - * returned by read. - * * A timeout occurred, in this case the number of bytes read will not - * match the amount requested, but no exception will be thrown. One of - * two possible timeouts occurred: - * * The inter byte timeout expired, this means that number of - * milliseconds elapsed between receiving bytes from the serial port - * exceeded the inter byte timeout. - * * The total timeout expired, which is calculated by multiplying the - * read timeout multiplier by the number of requested bytes and then - * added to the read timeout constant. If that total number of - * milliseconds elapses after the initial call to read a timeout will - * occur. - * * An exception occurred, in this case an actual exception will be thrown. - * - * \param buffer An uint8_t array of at least the requested size. - * \param size A size_t defining how many bytes to be read. - * - * \return A size_t representing the number of bytes read as a result of the - * call to read. - */ - size_t - read (uint8_t *buffer, size_t size); - - /*! Read a given amount of bytes from the serial port into a give buffer. - * - * \param buffer A reference to a std::vector of uint8_t. - * \param size A size_t defining how many bytes to be read. - * - * \return A size_t representing the number of bytes read as a result of the - * call to read. - */ - size_t - read (std::vector &buffer, size_t size = 1); - - /*! Read a given amount of bytes from the serial port into a give buffer. - * - * \param buffer A reference to a std::string. - * \param size A size_t defining how many bytes to be read. - * - * \return A size_t representing the number of bytes read as a result of the - * call to read. - */ - size_t - read (std::string &buffer, size_t size = 1); - - /*! Read a given amount of bytes from the serial port and return a string - * containing the data. - * - * \param size A size_t defining how many bytes to be read. - * - * \return A std::string containing the data read from the port. - */ - std::string - read (size_t size = 1); - - /*! Reads in a line or until a given delimiter has been processed. - * - * Reads from the serial port until a single line has been read. - * - * \param buffer A std::string reference used to store the data. - * \param size A maximum length of a line, defaults to 65536 (2^16) - * \param eol A string to match against for the EOL. - * - * \return A size_t representing the number of bytes read. - */ - size_t - readline (std::string &buffer, size_t size = 65536, std::string eol = "\n"); - - /*! Reads in a line or until a given delimiter has been processed. - * - * Reads from the serial port until a single line has been read. - * - * \param size A maximum length of a line, defaults to 65536 (2^16) - * \param eol A string to match against for the EOL. - * - * \return A std::string containing the line. - */ - std::string - readline (size_t size = 65536, std::string eol = "\n"); - - /*! Reads in multiple lines until the serial port times out. - * - * This requires a timeout > 0 before it can be run. It will read until a - * timeout occurs and return a list of strings. - * - * \param size A maximum length of combined lines, defaults to 65536 (2^16) - * - * \param eol A string to match against for the EOL. - * - * \return A vector containing the lines. - */ - std::vector - readlines (size_t size = 65536, std::string eol = "\n"); - - /*! Write a string to the serial port. - * - * \param data A const reference containing the data to be written - * to the serial port. - * - * \param size A size_t that indicates how many bytes should be written from - * the given data buffer. - * - * \return A size_t representing the number of bytes actually written to - * the serial port. - */ - size_t - write (const uint8_t *data, size_t size); - - /*! Write a string to the serial port. - * - * \param data A const reference containing the data to be written - * to the serial port. - * - * \return A size_t representing the number of bytes actually written to - * the serial port. - */ - size_t - write (const std::vector &data); - - /*! Write a string to the serial port. - * - * \param data A const reference containing the data to be written - * to the serial port. - * - * \return A size_t representing the number of bytes actually written to - * the serial port. - */ - size_t - write (const std::string &data); - - /*! Sets the serial port identifier. - * - * \param port A const std::string reference containing the address of the - * serial port, which would be something like 'COM1' on Windows and - * '/dev/ttyS0' on Linux. - * - * \throw InvalidConfigurationException - */ - void - setPort (const std::string &port); - - /*! Gets the serial port identifier. - * - * \see Serial::setPort - * - * \throw InvalidConfigurationException - */ - std::string - getPort () const; - - /*! Sets the timeout for reads and writes using the Timeout struct. - * - * There are two timeout conditions described here: - * * The inter byte timeout: - * * The inter_byte_timeout component of serial::Timeout defines the - * maximum amount of time, in milliseconds, between receiving bytes on - * the serial port that can pass before a timeout occurs. Setting this - * to zero will prevent inter byte timeouts from occurring. - * * Total time timeout: - * * The constant and multiplier component of this timeout condition, - * for both read and write, are defined in serial::Timeout. This - * timeout occurs if the total time since the read or write call was - * made exceeds the specified time in milliseconds. - * * The limit is defined by multiplying the multiplier component by the - * number of requested bytes and adding that product to the constant - * component. In this way if you want a read call, for example, to - * timeout after exactly one second regardless of the number of bytes - * you asked for then set the read_timeout_constant component of - * serial::Timeout to 1000 and the read_timeout_multiplier to zero. - * This timeout condition can be used in conjunction with the inter - * byte timeout condition with out any problems, timeout will simply - * occur when one of the two timeout conditions is met. This allows - * users to have maximum control over the trade-off between - * responsiveness and efficiency. - * - * Read and write functions will return in one of three cases. When the - * reading or writing is complete, when a timeout occurs, or when an - * exception occurs. - * - * \param timeout A serial::Timeout struct containing the inter byte - * timeout, and the read and write timeout constants and multipliers. - * - * \see serial::Timeout - */ - void - setTimeout (Timeout &timeout); - - /*! Sets the timeout for reads and writes. */ - void - setTimeout (uint32_t inter_byte_timeout, uint32_t read_timeout_constant, - uint32_t read_timeout_multiplier, uint32_t write_timeout_constant, - uint32_t write_timeout_multiplier) - { - Timeout timeout(inter_byte_timeout, read_timeout_constant, - read_timeout_multiplier, write_timeout_constant, - write_timeout_multiplier); - return setTimeout(timeout); - } - - /*! Gets the timeout for reads in seconds. - * - * \return A Timeout struct containing the inter_byte_timeout, and read - * and write timeout constants and multipliers. - * - * \see Serial::setTimeout - */ - Timeout - getTimeout () const; - - /*! Sets the baudrate for the serial port. - * - * Possible baudrates depends on the system but some safe baudrates include: - * 110, 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 56000, - * 57600, 115200 - * Some other baudrates that are supported by some comports: - * 128000, 153600, 230400, 256000, 460800, 921600 - * - * \param baudrate An integer that sets the baud rate for the serial port. - * - * \throw InvalidConfigurationException - */ - void - setBaudrate (uint32_t baudrate); - - /*! Gets the baudrate for the serial port. - * - * \return An integer that sets the baud rate for the serial port. - * - * \see Serial::setBaudrate - * - * \throw InvalidConfigurationException - */ - uint32_t - getBaudrate () const; - - /*! Sets the bytesize for the serial port. - * - * \param bytesize Size of each byte in the serial transmission of data, - * default is eightbits, possible values are: fivebits, sixbits, sevenbits, - * eightbits - * - * \throw InvalidConfigurationException - */ - void - setBytesize (bytesize_t bytesize); - - /*! Gets the bytesize for the serial port. - * - * \see Serial::setBytesize - * - * \throw InvalidConfigurationException - */ - bytesize_t - getBytesize () const; - - /*! Sets the parity for the serial port. - * - * \param parity Method of parity, default is parity_none, possible values - * are: parity_none, parity_odd, parity_even - * - * \throw InvalidConfigurationException - */ - void - setParity (parity_t parity); - - /*! Gets the parity for the serial port. - * - * \see Serial::setParity - * - * \throw InvalidConfigurationException - */ - parity_t - getParity () const; - - /*! Sets the stopbits for the serial port. - * - * \param stopbits Number of stop bits used, default is stopbits_one, - * possible values are: stopbits_one, stopbits_one_point_five, stopbits_two - * - * \throw InvalidConfigurationException - */ - void - setStopbits (stopbits_t stopbits); - - /*! Gets the stopbits for the serial port. - * - * \see Serial::setStopbits - * - * \throw InvalidConfigurationException - */ - stopbits_t - getStopbits () const; - - /*! Sets the flow control for the serial port. - * - * \param flowcontrol Type of flowcontrol used, default is flowcontrol_none, - * possible values are: flowcontrol_none, flowcontrol_software, - * flowcontrol_hardware - * - * \throw InvalidConfigurationException - */ - void - setFlowcontrol (flowcontrol_t flowcontrol); - - /*! Gets the flow control for the serial port. - * - * \see Serial::setFlowcontrol - * - * \throw InvalidConfigurationException - */ - flowcontrol_t - getFlowcontrol () const; - - /*! Flush the input and output buffers */ - void - flush (); - - /*! Flush only the input buffer */ - void - flushInput (); - - /*! Flush only the output buffer */ - void - flushOutput (); - - /*! Sends the RS-232 break signal. See tcsendbreak(3). */ - void - sendBreak (int duration); - - /*! Set the break condition to a given level. Defaults to true. */ - void - setBreak (bool level = true); - - /*! Set the RTS handshaking line to the given level. Defaults to true. */ - void - setRTS (bool level = true); - - /*! Set the DTR handshaking line to the given level. Defaults to true. */ - void - setDTR (bool level = true); - - /*! - * Blocks until CTS, DSR, RI, CD changes or something interrupts it. - * - * Can throw an exception if an error occurs while waiting. - * You can check the status of CTS, DSR, RI, and CD once this returns. - * Uses TIOCMIWAIT via ioctl if available (mostly only on Linux) with a - * resolution of less than +-1ms and as good as +-0.2ms. Otherwise a - * polling method is used which can give +-2ms. - * - * \return Returns true if one of the lines changed, false if something else - * occurred. - * - * \throw SerialException - */ - bool - waitForChange (); - - /*! Returns the current status of the CTS line. */ - bool - getCTS (); - - /*! Returns the current status of the DSR line. */ - bool - getDSR (); - - /*! Returns the current status of the RI line. */ - bool - getRI (); - - /*! Returns the current status of the CD line. */ - bool - getCD (); - -private: - // Disable copy constructors - Serial(const Serial&); - Serial& operator=(const Serial&); - - std::string read_cache_; //!< Cache for doing reads in chunks. - - // Pimpl idiom, d_pointer - class SerialImpl; - SerialImpl *pimpl_; - - // Scoped Lock Classes - class ScopedReadLock; - class ScopedWriteLock; - - // Read common function - size_t - read_ (uint8_t *buffer, size_t size); - // Write common function - size_t - write_ (const uint8_t *data, size_t length); - -}; - -class SerialException : public std::exception -{ - // Disable copy constructors - SerialException& operator=(const SerialException&); - std::string e_what_; -public: - SerialException (const char *description) { - std::stringstream ss; - ss << "SerialException " << description << " failed."; - e_what_ = ss.str(); - } - SerialException (const SerialException& other) : e_what_(other.e_what_) {} - virtual ~SerialException() throw() {} - virtual const char* what () const throw () { - return e_what_.c_str(); - } -}; - -class IOException : public std::exception -{ - // Disable copy constructors - IOException& operator=(const IOException&); - std::string file_; - int line_; - std::string e_what_; - int errno_; -public: - explicit IOException (std::string file, int line, int errnum) - : file_(file), line_(line), errno_(errnum) { - std::stringstream ss; -#if defined(_WIN32) - char error_str [1024]; - strerror_s(error_str, 1024, errnum); -#else - char * error_str = strerror(errnum); -#endif - ss << "IO Exception (" << errno_ << "): " << error_str; - ss << ", file " << file_ << ", line " << line_ << "."; - e_what_ = ss.str(); - } - explicit IOException (std::string file, int line, const char * description) - : file_(file), line_(line), errno_(0) { - std::stringstream ss; - ss << "IO Exception: " << description; - ss << ", file " << file_ << ", line " << line_ << "."; - e_what_ = ss.str(); - } - virtual ~IOException() throw() {} - IOException (const IOException& other) : e_what_(other.e_what_), line_(other.line_), errno_(other.errno_) {} - - int getErrorNumber () { return errno_; } - - virtual const char* what () const throw () { - return e_what_.c_str(); - } -}; - -class PortNotOpenedException : public std::exception -{ - // Disable copy constructors - const PortNotOpenedException& operator=(PortNotOpenedException); - std::string e_what_; -public: - PortNotOpenedException (const char * description) { - std::stringstream ss; - ss << "PortNotOpenedException " << description << " failed."; - e_what_ = ss.str(); - } - PortNotOpenedException (const PortNotOpenedException& other) : e_what_(other.e_what_) {} - virtual ~PortNotOpenedException() throw() {} - virtual const char* what () const throw () { - return e_what_.c_str(); - } -}; - -} // namespace serial - -#endif diff --git a/dependencies/build/serial/include/serial/v8stdint.h b/dependencies/build/serial/include/serial/v8stdint.h deleted file mode 100644 index f3be96b1..00000000 --- a/dependencies/build/serial/include/serial/v8stdint.h +++ /dev/null @@ -1,57 +0,0 @@ -// This header is from the v8 google project: -// http://code.google.com/p/v8/source/browse/trunk/include/v8stdint.h - -// Copyright 2012 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Load definitions of standard types. - -#ifndef V8STDINT_H_ -#define V8STDINT_H_ - -#include -#include - -#if defined(_WIN32) && !defined(__MINGW32__) - -typedef signed char int8_t; -typedef unsigned char uint8_t; -typedef short int16_t; // NOLINT -typedef unsigned short uint16_t; // NOLINT -typedef int int32_t; -typedef unsigned int uint32_t; -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; -// intptr_t and friends are defined in crtdefs.h through stdio.h. - -#else - -#include - -#endif - -#endif // V8STDINT_H_ diff --git a/dependencies/build/serial/src/impl/unix.cc b/dependencies/build/serial/src/impl/unix.cc deleted file mode 100755 index 596b1aba..00000000 --- a/dependencies/build/serial/src/impl/unix.cc +++ /dev/null @@ -1,1025 +0,0 @@ -/* Copyright 2012 William Woodall and John Harrison - * - * Additional Contributors: Christopher Baker @bakercp - */ - -#if !defined(_WIN32) - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(__linux__) -# include -#endif - -#include -#include -#include -#ifdef __MACH__ -#include -#include -#endif - -#include "serial/impl/unix.h" - -#ifndef TIOCINQ -#ifdef FIONREAD -#define TIOCINQ FIONREAD -#else -#define TIOCINQ 0x541B -#endif -#endif - -#if defined(MAC_OS_X_VERSION_10_3) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3) -#include -#endif - -using std::string; -using std::stringstream; -using std::invalid_argument; -using serial::Serial; -using serial::SerialException; -using serial::PortNotOpenedException; -using serial::IOException; - - -Serial::SerialImpl::SerialImpl (const string &port, unsigned long baudrate, - bytesize_t bytesize, - parity_t parity, stopbits_t stopbits, - flowcontrol_t flowcontrol) - : port_ (port), fd_ (-1), is_open_ (false), xonxoff_ (false), rtscts_ (false), - baudrate_ (baudrate), parity_ (parity), - bytesize_ (bytesize), stopbits_ (stopbits), flowcontrol_ (flowcontrol) -{ - pthread_mutex_init(&this->read_mutex, NULL); - pthread_mutex_init(&this->write_mutex, NULL); - if (port_.empty () == false) - open (); -} - -Serial::SerialImpl::~SerialImpl () -{ - close(); - pthread_mutex_destroy(&this->read_mutex); - pthread_mutex_destroy(&this->write_mutex); -} - -void -Serial::SerialImpl::open () -{ - if (port_.empty ()) { - throw invalid_argument ("Empty port is invalid."); - } - if (is_open_ == true) { - throw SerialException ("Serial port already open."); - } - - fd_ = ::open (port_.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK); - - if (fd_ == -1) { - switch (errno) { - case EINTR: - // Recurse because this is a recoverable error. - open (); - return; - case ENFILE: - case EMFILE: - THROW (IOException, "Too many file handles open."); - default: - THROW (IOException, errno); - } - } - - reconfigurePort(); - is_open_ = true; -} - -void -Serial::SerialImpl::reconfigurePort () -{ - if (fd_ == -1) { - // Can only operate on a valid file descriptor - THROW (IOException, "Invalid file descriptor, is the serial port open?"); - } - - struct termios options; // The options for the file descriptor - - if (tcgetattr(fd_, &options) == -1) { - THROW (IOException, "::tcgetattr"); - } - - // set up raw mode / no echo / binary - options.c_cflag |= (tcflag_t) (CLOCAL | CREAD); - options.c_lflag &= (tcflag_t) ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | - ISIG | IEXTEN); //|ECHOPRT - - options.c_oflag &= (tcflag_t) ~(OPOST); - options.c_iflag &= (tcflag_t) ~(INLCR | IGNCR | ICRNL | IGNBRK); -#ifdef IUCLC - options.c_iflag &= (tcflag_t) ~IUCLC; -#endif -#ifdef PARMRK - options.c_iflag &= (tcflag_t) ~PARMRK; -#endif - - // setup baud rate - bool custom_baud = false; - speed_t baud; - switch (baudrate_) { -#ifdef B0 - case 0: baud = B0; break; -#endif -#ifdef B50 - case 50: baud = B50; break; -#endif -#ifdef B75 - case 75: baud = B75; break; -#endif -#ifdef B110 - case 110: baud = B110; break; -#endif -#ifdef B134 - case 134: baud = B134; break; -#endif -#ifdef B150 - case 150: baud = B150; break; -#endif -#ifdef B200 - case 200: baud = B200; break; -#endif -#ifdef B300 - case 300: baud = B300; break; -#endif -#ifdef B600 - case 600: baud = B600; break; -#endif -#ifdef B1200 - case 1200: baud = B1200; break; -#endif -#ifdef B1800 - case 1800: baud = B1800; break; -#endif -#ifdef B2400 - case 2400: baud = B2400; break; -#endif -#ifdef B4800 - case 4800: baud = B4800; break; -#endif -#ifdef B7200 - case 7200: baud = B7200; break; -#endif -#ifdef B9600 - case 9600: baud = B9600; break; -#endif -#ifdef B14400 - case 14400: baud = B14400; break; -#endif -#ifdef B19200 - case 19200: baud = B19200; break; -#endif -#ifdef B28800 - case 28800: baud = B28800; break; -#endif -#ifdef B57600 - case 57600: baud = B57600; break; -#endif -#ifdef B76800 - case 76800: baud = B76800; break; -#endif -#ifdef B38400 - case 38400: baud = B38400; break; -#endif -#ifdef B115200 - case 115200: baud = B115200; break; -#endif -#ifdef B128000 - case 128000: baud = B128000; break; -#endif -#ifdef B153600 - case 153600: baud = B153600; break; -#endif -#ifdef B230400 - case 230400: baud = B230400; break; -#endif -#ifdef B256000 - case 256000: baud = B256000; break; -#endif -#ifdef B460800 - case 460800: baud = B460800; break; -#endif -#ifdef B500000 - case 500000: baud = B500000; break; -#endif -#ifdef B921600 - case 921600: baud = B921600; break; -#endif -#ifdef B1000000 - case 1000000: baud = B1000000; break; -#endif -#ifdef B1152000 - case 1152000: baud = B1152000; break; -#endif -#ifdef B1500000 - case 1500000: baud = B1500000; break; -#endif -#ifdef B2000000 - case 2000000: baud = B2000000; break; -#endif -#ifdef B2500000 - case 2500000: baud = B2500000; break; -#endif -#ifdef B3000000 - case 3000000: baud = B3000000; break; -#endif -#ifdef B3500000 - case 3500000: baud = B3500000; break; -#endif -#ifdef B4000000 - case 4000000: baud = B4000000; break; -#endif - default: - custom_baud = true; - // OS X support -#if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4) - // Starting with Tiger, the IOSSIOSPEED ioctl can be used to set arbitrary baud rates - // other than those specified by POSIX. The driver for the underlying serial hardware - // ultimately determines which baud rates can be used. This ioctl sets both the input - // and output speed. - speed_t new_baud = static_cast(baudrate_); - if (-1 == ioctl (fd_, IOSSIOSPEED, &new_baud, 1)) { - THROW (IOException, errno); - } - // Linux Support -#elif defined(__linux__) && defined (TIOCSSERIAL) - struct serial_struct ser; - - if (-1 == ioctl (fd_, TIOCGSERIAL, &ser)) { - THROW (IOException, errno); - } - - // set custom divisor - ser.custom_divisor = ser.baud_base / (int) baudrate_; - // update flags - ser.flags &= ~ASYNC_SPD_MASK; - ser.flags |= ASYNC_SPD_CUST; - - if (-1 == ioctl (fd_, TIOCSSERIAL, &ser)) { - THROW (IOException, errno); - } -#else - throw invalid_argument ("OS does not currently support custom bauds"); -#endif - } - if (custom_baud == false) { -#ifdef _BSD_SOURCE - ::cfsetspeed(&options, baud); -#else - ::cfsetispeed(&options, baud); - ::cfsetospeed(&options, baud); -#endif - } - - // setup char len - options.c_cflag &= (tcflag_t) ~CSIZE; - if (bytesize_ == eightbits) - options.c_cflag |= CS8; - else if (bytesize_ == sevenbits) - options.c_cflag |= CS7; - else if (bytesize_ == sixbits) - options.c_cflag |= CS6; - else if (bytesize_ == fivebits) - options.c_cflag |= CS5; - else - throw invalid_argument ("invalid char len"); - // setup stopbits - if (stopbits_ == stopbits_one) - options.c_cflag &= (tcflag_t) ~(CSTOPB); - else if (stopbits_ == stopbits_one_point_five) - // ONE POINT FIVE same as TWO.. there is no POSIX support for 1.5 - options.c_cflag |= (CSTOPB); - else if (stopbits_ == stopbits_two) - options.c_cflag |= (CSTOPB); - else - throw invalid_argument ("invalid stop bit"); - // setup parity - options.c_iflag &= (tcflag_t) ~(INPCK | ISTRIP); - if (parity_ == parity_none) { - options.c_cflag &= (tcflag_t) ~(PARENB | PARODD); - } else if (parity_ == parity_even) { - options.c_cflag &= (tcflag_t) ~(PARODD); - options.c_cflag |= (PARENB); - } else if (parity_ == parity_odd) { - options.c_cflag |= (PARENB | PARODD); - } else { - throw invalid_argument ("invalid parity"); - } - // setup flow control - if (flowcontrol_ == flowcontrol_none) { - xonxoff_ = false; - rtscts_ = false; - } - if (flowcontrol_ == flowcontrol_software) { - xonxoff_ = true; - rtscts_ = false; - } - if (flowcontrol_ == flowcontrol_hardware) { - xonxoff_ = false; - rtscts_ = true; - } - // xonxoff -#ifdef IXANY - if (xonxoff_) - options.c_iflag |= (IXON | IXOFF); //|IXANY) - else - options.c_iflag &= (tcflag_t) ~(IXON | IXOFF | IXANY); -#else - if (xonxoff_) - options.c_iflag |= (IXON | IXOFF); - else - options.c_iflag &= (tcflag_t) ~(IXON | IXOFF); -#endif - // rtscts -#ifdef CRTSCTS - if (rtscts_) - options.c_cflag |= (CRTSCTS); - else - options.c_cflag &= (unsigned long) ~(CRTSCTS); -#elif defined CNEW_RTSCTS - if (rtscts_) - options.c_cflag |= (CNEW_RTSCTS); - else - options.c_cflag &= (unsigned long) ~(CNEW_RTSCTS); -#else -#error "OS Support seems wrong." -#endif - - // http://www.unixwiz.net/techtips/termios-vmin-vtime.html - // this basically sets the read call up to be a polling read, - // but we are using select to ensure there is data available - // to read before each call, so we should never needlessly poll - options.c_cc[VMIN] = 0; - options.c_cc[VTIME] = 0; - - // activate settings - ::tcsetattr (fd_, TCSANOW, &options); -} - -void -Serial::SerialImpl::close () -{ - if (is_open_ == true) { - if (fd_ != -1) { - ::close (fd_); // Ignoring the outcome - fd_ = -1; - } - is_open_ = false; - } -} - -bool -Serial::SerialImpl::isOpen () const -{ - return is_open_; -} - -size_t -Serial::SerialImpl::available () -{ - if (!is_open_) { - return 0; - } - int count = 0; - if (-1 == ioctl (fd_, TIOCINQ, &count)) { - THROW (IOException, errno); - } else { - return static_cast (count); - } -} - -inline void -get_time_now (struct timespec &time) -{ -# ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time - clock_serv_t cclock; - mach_timespec_t mts; - host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); - clock_get_time(cclock, &mts); - mach_port_deallocate(mach_task_self(), cclock); - time.tv_sec = mts.tv_sec; - time.tv_nsec = mts.tv_nsec; -# else - clock_gettime(CLOCK_REALTIME, &time); -# endif -} - -inline void -diff_timespec (timespec &start, timespec &end, timespec &result) { - if (start.tv_sec > end.tv_sec) { - throw SerialException ("Timetravel, start time later than end time."); - } - result.tv_sec = end.tv_sec - start.tv_sec; - result.tv_nsec = end.tv_nsec - start.tv_nsec; - if (result.tv_nsec < 0) { - result.tv_nsec = 1e9 - result.tv_nsec; - result.tv_sec -= 1; - } -} - -size_t -Serial::SerialImpl::read (uint8_t *buf, size_t size) -{ - // If the port is not open, throw - if (!is_open_) { - throw PortNotOpenedException ("Serial::read"); - } - fd_set readfds; - size_t bytes_read = 0; - // Setup the total_timeout timeval - // This timeout is maximum time before a timeout after read is called - struct timeval total_timeout; - // Calculate total timeout in milliseconds t_c + (t_m * N) - long total_timeout_ms = timeout_.read_timeout_constant; - total_timeout_ms += timeout_.read_timeout_multiplier*static_cast(size); - total_timeout.tv_sec = total_timeout_ms / 1000; - total_timeout.tv_usec = static_cast(total_timeout_ms % 1000); - total_timeout.tv_usec *= 1000; // To convert to micro seconds - // Setup the inter byte timeout - struct timeval inter_byte_timeout; - inter_byte_timeout.tv_sec = timeout_.inter_byte_timeout / 1000; - inter_byte_timeout.tv_usec = - static_cast (timeout_.inter_byte_timeout % 1000); - inter_byte_timeout.tv_usec *= 1000; // To convert to micro seconds - while (bytes_read < size) { - // Setup the select timeout timeval - struct timeval timeout; - // If the total_timeout is less than the inter_byte_timeout - if (total_timeout.tv_sec < inter_byte_timeout.tv_sec - || (total_timeout.tv_sec == inter_byte_timeout.tv_sec - && total_timeout.tv_usec < inter_byte_timeout.tv_sec)) - { - // Then set the select timeout to use the total time - timeout = total_timeout; - } else { - // Else set the select timeout to use the inter byte time - timeout = inter_byte_timeout; - } - FD_ZERO (&readfds); - FD_SET (fd_, &readfds); - // Begin timing select - struct timespec start, end; - get_time_now (start); - // Call select to block for serial data or a timeout - int r = select (fd_ + 1, &readfds, NULL, NULL, &timeout); - // Calculate difference and update the structure - get_time_now (end); - // Calculate the time select took - struct timespec diff; - diff_timespec (start, end, diff); - // Update the timeout - if (total_timeout.tv_sec <= diff.tv_sec) { - total_timeout.tv_sec = 0; - } else { - total_timeout.tv_sec -= diff.tv_sec; - } - if (total_timeout.tv_usec <= (diff.tv_nsec / 1000)) { - total_timeout.tv_usec = 0; - } else { - total_timeout.tv_usec -= (diff.tv_nsec / 1000); - } - - // Figure out what happened by looking at select's response 'r' - /** Error **/ - if (r < 0) { - // Select was interrupted, try again - if (errno == EINTR) { - continue; - } - // Otherwise there was some error - THROW (IOException, errno); - } - /** Timeout **/ - if (r == 0) { - break; - } - /** Something ready to read **/ - if (r > 0) { - // Make sure our file descriptor is in the ready to read list - if (FD_ISSET (fd_, &readfds)) { - // This should be non-blocking returning only what is available now - // Then returning so that select can block again. - ssize_t bytes_read_now = - ::read (fd_, buf + bytes_read, size - bytes_read); - // read should always return some data as select reported it was - // ready to read when we get to this point. - if (bytes_read_now < 1) { - // Disconnected devices, at least on Linux, show the - // behavior that they are always ready to read immediately - // but reading returns nothing. - throw SerialException ("device reports readiness to read but " - "returned no data (device disconnected?)"); - } - // Update bytes_read - bytes_read += static_cast (bytes_read_now); - // If bytes_read == size then we have read everything we need - if (bytes_read == size) { - break; - } - // If bytes_read < size then we have more to read - if (bytes_read < size) { - continue; - } - // If bytes_read > size then we have over read, which shouldn't happen - if (bytes_read > size) { - throw SerialException ("read over read, too many bytes where " - "read, this shouldn't happen, might be " - "a logical error!"); - } - } - // This shouldn't happen, if r > 0 our fd has to be in the list! - THROW (IOException, "select reports ready to read, but our fd isn't" - " in the list, this shouldn't happen!"); - } - } - return bytes_read; -} - -size_t -Serial::SerialImpl::write (const uint8_t *data, size_t length) -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::write"); - } - fd_set writefds; - size_t bytes_written = 0; - struct timeval timeout; - timeout.tv_sec = timeout_.write_timeout_constant / 1000; - timeout.tv_usec = static_cast (timeout_.write_timeout_multiplier % 1000); - timeout.tv_usec *= 1000; // To convert to micro seconds - while (bytes_written < length) { - FD_ZERO (&writefds); - FD_SET (fd_, &writefds); - // On Linux the timeout struct is updated by select to contain the time - // left on the timeout to make looping easier, but on other platforms this - // does not occur. -#if !defined(__linux__) - // Begin timing select - struct timespec start, end; - get_time_now(start); -#endif - // Do the select - int r = select (fd_ + 1, NULL, &writefds, NULL, &timeout); -#if !defined(__linux__) - // Calculate difference and update the structure - get_time_now(end); - // Calculate the time select took - struct timespec diff; - diff_timespec(start, end, diff); - // Update the timeout - if (timeout.tv_sec <= diff.tv_sec) { - timeout.tv_sec = 0; - } else { - timeout.tv_sec -= diff.tv_sec; - } - if (timeout.tv_usec <= (diff.tv_nsec / 1000)) { - timeout.tv_usec = 0; - } else { - timeout.tv_usec -= (diff.tv_nsec / 1000); - } -#endif - - // Figure out what happened by looking at select's response 'r' - /** Error **/ - if (r < 0) { - // Select was interrupted, try again - if (errno == EINTR) { - continue; - } - // Otherwise there was some error - THROW (IOException, errno); - } - /** Timeout **/ - if (r == 0) { - break; - } - /** Port ready to write **/ - if (r > 0) { - // Make sure our file descriptor is in the ready to write list - if (FD_ISSET (fd_, &writefds)) { - // This will write some - ssize_t bytes_written_now = - ::write (fd_, data + bytes_written, length - bytes_written); - // write should always return some data as select reported it was - // ready to write when we get to this point. - if (bytes_written_now < 1) { - // Disconnected devices, at least on Linux, show the - // behavior that they are always ready to write immediately - // but writing returns nothing. - throw SerialException ("device reports readiness to write but " - "returned no data (device disconnected?)"); - } - // Update bytes_written - bytes_written += static_cast (bytes_written_now); - // If bytes_written == size then we have written everything we need to - if (bytes_written == length) { - break; - } - // If bytes_written < size then we have more to write - if (bytes_written < length) { - continue; - } - // If bytes_written > size then we have over written, which shouldn't happen - if (bytes_written > length) { - throw SerialException ("write over wrote, too many bytes where " - "written, this shouldn't happen, might be " - "a logical error!"); - } - } - // This shouldn't happen, if r > 0 our fd has to be in the list! - THROW (IOException, "select reports ready to write, but our fd isn't" - " in the list, this shouldn't happen!"); - } - } - return bytes_written; -} - -void -Serial::SerialImpl::setPort (const string &port) -{ - port_ = port; -} - -string -Serial::SerialImpl::getPort () const -{ - return port_; -} - -void -Serial::SerialImpl::setTimeout (serial::Timeout &timeout) -{ - timeout_ = timeout; -} - -serial::Timeout -Serial::SerialImpl::getTimeout () const -{ - return timeout_; -} - -void -Serial::SerialImpl::setBaudrate (unsigned long baudrate) -{ - baudrate_ = baudrate; - if (is_open_) - reconfigurePort (); -} - -unsigned long -Serial::SerialImpl::getBaudrate () const -{ - return baudrate_; -} - -void -Serial::SerialImpl::setBytesize (serial::bytesize_t bytesize) -{ - bytesize_ = bytesize; - if (is_open_) - reconfigurePort (); -} - -serial::bytesize_t -Serial::SerialImpl::getBytesize () const -{ - return bytesize_; -} - -void -Serial::SerialImpl::setParity (serial::parity_t parity) -{ - parity_ = parity; - if (is_open_) - reconfigurePort (); -} - -serial::parity_t -Serial::SerialImpl::getParity () const -{ - return parity_; -} - -void -Serial::SerialImpl::setStopbits (serial::stopbits_t stopbits) -{ - stopbits_ = stopbits; - if (is_open_) - reconfigurePort (); -} - -serial::stopbits_t -Serial::SerialImpl::getStopbits () const -{ - return stopbits_; -} - -void -Serial::SerialImpl::setFlowcontrol (serial::flowcontrol_t flowcontrol) -{ - flowcontrol_ = flowcontrol; - if (is_open_) - reconfigurePort (); -} - -serial::flowcontrol_t -Serial::SerialImpl::getFlowcontrol () const -{ - return flowcontrol_; -} - -void -Serial::SerialImpl::flush () -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::flush"); - } - tcdrain (fd_); -} - -void -Serial::SerialImpl::flushInput () -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::flushInput"); - } - tcflush (fd_, TCIFLUSH); -} - -void -Serial::SerialImpl::flushOutput () -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::flushOutput"); - } - tcflush (fd_, TCOFLUSH); -} - -void -Serial::SerialImpl::sendBreak (int duration) -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::sendBreak"); - } - tcsendbreak (fd_, static_cast (duration / 4)); -} - -void -Serial::SerialImpl::setBreak (bool level) -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::setBreak"); - } - - if (level) { - if (-1 == ioctl (fd_, TIOCSBRK)) - { - stringstream ss; - ss << "setBreak failed on a call to ioctl(TIOCSBRK): " << errno << " " << strerror(errno); - throw(SerialException(ss.str().c_str())); - } - } else { - if (-1 == ioctl (fd_, TIOCCBRK)) - { - stringstream ss; - ss << "setBreak failed on a call to ioctl(TIOCCBRK): " << errno << " " << strerror(errno); - throw(SerialException(ss.str().c_str())); - } - } -} - -void -Serial::SerialImpl::setRTS (bool level) -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::setRTS"); - } - - int command = TIOCM_RTS; - - if (level) { - if (-1 == ioctl (fd_, TIOCMBIS, &command)) - { - stringstream ss; - ss << "setRTS failed on a call to ioctl(TIOCMBIS): " << errno << " " << strerror(errno); - throw(SerialException(ss.str().c_str())); - } - } else { - if (-1 == ioctl (fd_, TIOCMBIC, &command)) - { - stringstream ss; - ss << "setRTS failed on a call to ioctl(TIOCMBIC): " << errno << " " << strerror(errno); - throw(SerialException(ss.str().c_str())); - } - } -} - -void -Serial::SerialImpl::setDTR (bool level) -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::setDTR"); - } - - int command = TIOCM_DTR; - - if (level) { - if (-1 == ioctl (fd_, TIOCMBIS, &command)) - { - stringstream ss; - ss << "setDTR failed on a call to ioctl(TIOCMBIS): " << errno << " " << strerror(errno); - throw(SerialException(ss.str().c_str())); - } - } else { - if (-1 == ioctl (fd_, TIOCMBIC, &command)) - { - stringstream ss; - ss << "setDTR failed on a call to ioctl(TIOCMBIC): " << errno << " " << strerror(errno); - throw(SerialException(ss.str().c_str())); - } - } -} - -bool -Serial::SerialImpl::waitForChange () -{ -#ifndef TIOCMIWAIT - -while (is_open_ == true) { - - int status; - - if (-1 == ioctl (fd_, TIOCMGET, &status)) - { - stringstream ss; - ss << "waitForChange failed on a call to ioctl(TIOCMGET): " << errno << " " << strerror(errno); - throw(SerialException(ss.str().c_str())); - } - else - { - if (0 != (status & TIOCM_CTS) - || 0 != (status & TIOCM_DSR) - || 0 != (status & TIOCM_RI) - || 0 != (status & TIOCM_CD)) - { - return true; - } - } - - usleep(1000); - } - - return false; -#else - int command = (TIOCM_CD|TIOCM_DSR|TIOCM_RI|TIOCM_CTS); - - if (-1 == ioctl (fd_, TIOCMIWAIT, &command)) { - stringstream ss; - ss << "waitForDSR failed on a call to ioctl(TIOCMIWAIT): " - << errno << " " << strerror(errno); - throw(SerialException(ss.str().c_str())); - } - return true; -#endif -} - -bool -Serial::SerialImpl::getCTS () -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::getCTS"); - } - - int status; - - if (-1 == ioctl (fd_, TIOCMGET, &status)) - { - stringstream ss; - ss << "getCTS failed on a call to ioctl(TIOCMGET): " << errno << " " << strerror(errno); - throw(SerialException(ss.str().c_str())); - } - else - { - return 0 != (status & TIOCM_CTS); - } -} - -bool -Serial::SerialImpl::getDSR () -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::getDSR"); - } - - int status; - - if (-1 == ioctl (fd_, TIOCMGET, &status)) - { - stringstream ss; - ss << "getDSR failed on a call to ioctl(TIOCMGET): " << errno << " " << strerror(errno); - throw(SerialException(ss.str().c_str())); - } - else - { - return 0 != (status & TIOCM_DSR); - } -} - -bool -Serial::SerialImpl::getRI () -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::getRI"); - } - - int status; - - if (-1 == ioctl (fd_, TIOCMGET, &status)) - { - stringstream ss; - ss << "getRI failed on a call to ioctl(TIOCMGET): " << errno << " " << strerror(errno); - throw(SerialException(ss.str().c_str())); - } - else - { - return 0 != (status & TIOCM_RI); - } -} - -bool -Serial::SerialImpl::getCD () -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::getCD"); - } - - int status; - - if (-1 == ioctl (fd_, TIOCMGET, &status)) - { - stringstream ss; - ss << "getCD failed on a call to ioctl(TIOCMGET): " << errno << " " << strerror(errno); - throw(SerialException(ss.str().c_str())); - } - else - { - return 0 != (status & TIOCM_CD); - } -} - -void -Serial::SerialImpl::readLock () -{ - int result = pthread_mutex_lock(&this->read_mutex); - if (result) { - THROW (IOException, result); - } -} - -void -Serial::SerialImpl::readUnlock () -{ - int result = pthread_mutex_unlock(&this->read_mutex); - if (result) { - THROW (IOException, result); - } -} - -void -Serial::SerialImpl::writeLock () -{ - int result = pthread_mutex_lock(&this->write_mutex); - if (result) { - THROW (IOException, result); - } -} - -void -Serial::SerialImpl::writeUnlock () -{ - int result = pthread_mutex_unlock(&this->write_mutex); - if (result) { - THROW (IOException, result); - } -} - -#endif // !defined(_WIN32) diff --git a/dependencies/build/serial/src/impl/win.cc b/dependencies/build/serial/src/impl/win.cc deleted file mode 100644 index b3b4c0e8..00000000 --- a/dependencies/build/serial/src/impl/win.cc +++ /dev/null @@ -1,601 +0,0 @@ -#if defined(_WIN32) - -/* Copyright 2012 William Woodall and John Harrison */ - -#include "serial/impl/win.h" - -using std::string; -using std::wstring; -using std::stringstream; -using std::invalid_argument; -using serial::Serial; -using serial::Timeout; -using serial::bytesize_t; -using serial::parity_t; -using serial::stopbits_t; -using serial::flowcontrol_t; -using serial::SerialException; -using serial::PortNotOpenedException; -using serial::IOException; - - -Serial::SerialImpl::SerialImpl (const string &port, unsigned long baudrate, - bytesize_t bytesize, - parity_t parity, stopbits_t stopbits, - flowcontrol_t flowcontrol) - : port_ (port.begin(), port.end()), fd_ (INVALID_HANDLE_VALUE), is_open_ (false), - baudrate_ (baudrate), parity_ (parity), - bytesize_ (bytesize), stopbits_ (stopbits), flowcontrol_ (flowcontrol) -{ - read_mutex = CreateMutex(NULL, false, NULL); - write_mutex = CreateMutex(NULL, false, NULL); - if (port_.empty () == false) - open (); -} - -Serial::SerialImpl::~SerialImpl () -{ - this->close(); - CloseHandle(read_mutex); - CloseHandle(write_mutex); -} - -void -Serial::SerialImpl::open () -{ - if (port_.empty ()) { - throw invalid_argument ("Empty port is invalid."); - } - if (is_open_ == true) { - throw SerialException ("Serial port already open."); - } - - LPCWSTR lp_port = port_.c_str(); - fd_ = CreateFileW(lp_port, - GENERIC_READ | GENERIC_WRITE, - 0, - 0, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - 0); - - if (fd_ == INVALID_HANDLE_VALUE) { - DWORD errno_ = GetLastError(); - stringstream ss; - switch (errno_) { - case ERROR_FILE_NOT_FOUND: - // Use this->getPort to convert to a std::string - ss << "Specified port, " << this->getPort() << ", does not exist."; - THROW (IOException, ss.str().c_str()); - default: - ss << "Unknown error opening the serial port: " << errno; - THROW (IOException, ss.str().c_str()); - } - } - - reconfigurePort(); - is_open_ = true; -} - -void -Serial::SerialImpl::reconfigurePort () -{ - if (fd_ == INVALID_HANDLE_VALUE) { - // Can only operate on a valid file descriptor - THROW (IOException, "Invalid file descriptor, is the serial port open?"); - } - - DCB dcbSerialParams = {0}; - - dcbSerialParams.DCBlength=sizeof(dcbSerialParams); - - if (!GetCommState(fd_, &dcbSerialParams)) { - //error getting state - THROW (IOException, "Error getting the serial port state."); - } - - // setup baud rate - switch (baudrate_) { -#ifdef CBR_0 - case 0: dcbSerialParams.BaudRate = CBR_0; break; -#endif -#ifdef CBR_50 - case 50: dcbSerialParams.BaudRate = CBR_50; break; -#endif -#ifdef CBR_75 - case 75: dcbSerialParams.BaudRate = CBR_75; break; -#endif -#ifdef CBR_110 - case 110: dcbSerialParams.BaudRate = CBR_110; break; -#endif -#ifdef CBR_134 - case 134: dcbSerialParams.BaudRate = CBR_134; break; -#endif -#ifdef CBR_150 - case 150: dcbSerialParams.BaudRate = CBR_150; break; -#endif -#ifdef CBR_200 - case 200: dcbSerialParams.BaudRate = CBR_200; break; -#endif -#ifdef CBR_300 - case 300: dcbSerialParams.BaudRate = CBR_300; break; -#endif -#ifdef CBR_600 - case 600: dcbSerialParams.BaudRate = CBR_600; break; -#endif -#ifdef CBR_1200 - case 1200: dcbSerialParams.BaudRate = CBR_1200; break; -#endif -#ifdef CBR_1800 - case 1800: dcbSerialParams.BaudRate = CBR_1800; break; -#endif -#ifdef CBR_2400 - case 2400: dcbSerialParams.BaudRate = CBR_2400; break; -#endif -#ifdef CBR_4800 - case 4800: dcbSerialParams.BaudRate = CBR_4800; break; -#endif -#ifdef CBR_7200 - case 7200: dcbSerialParams.BaudRate = CBR_7200; break; -#endif -#ifdef CBR_9600 - case 9600: dcbSerialParams.BaudRate = CBR_9600; break; -#endif -#ifdef CBR_14400 - case 14400: dcbSerialParams.BaudRate = CBR_14400; break; -#endif -#ifdef CBR_19200 - case 19200: dcbSerialParams.BaudRate = CBR_19200; break; -#endif -#ifdef CBR_28800 - case 28800: dcbSerialParams.BaudRate = CBR_28800; break; -#endif -#ifdef CBR_57600 - case 57600: dcbSerialParams.BaudRate = CBR_57600; break; -#endif -#ifdef CBR_76800 - case 76800: dcbSerialParams.BaudRate = CBR_76800; break; -#endif -#ifdef CBR_38400 - case 38400: dcbSerialParams.BaudRate = CBR_38400; break; -#endif -#ifdef CBR_115200 - case 115200: dcbSerialParams.BaudRate = CBR_115200; break; -#endif -#ifdef CBR_128000 - case 128000: dcbSerialParams.BaudRate = CBR_128000; break; -#endif -#ifdef CBR_153600 - case 153600: dcbSerialParams.BaudRate = CBR_153600; break; -#endif -#ifdef CBR_230400 - case 230400: dcbSerialParams.BaudRate = CBR_230400; break; -#endif -#ifdef CBR_256000 - case 256000: dcbSerialParams.BaudRate = CBR_256000; break; -#endif -#ifdef CBR_460800 - case 460800: dcbSerialParams.BaudRate = CBR_460800; break; -#endif -#ifdef CBR_921600 - case 921600: dcbSerialParams.BaudRate = CBR_921600; break; -#endif - default: - // Try to blindly assign it - dcbSerialParams.BaudRate = baudrate_; - } - - // setup char len - if (bytesize_ == eightbits) - dcbSerialParams.ByteSize = 8; - else if (bytesize_ == sevenbits) - dcbSerialParams.ByteSize = 7; - else if (bytesize_ == sixbits) - dcbSerialParams.ByteSize = 6; - else if (bytesize_ == fivebits) - dcbSerialParams.ByteSize = 5; - else - throw invalid_argument ("invalid char len"); - - // setup stopbits - if (stopbits_ == stopbits_one) - dcbSerialParams.StopBits = ONESTOPBIT; - else if (stopbits_ == stopbits_one_point_five) - dcbSerialParams.StopBits = ONE5STOPBITS; - else if (stopbits_ == stopbits_two) - dcbSerialParams.StopBits = TWOSTOPBITS; - else - throw invalid_argument ("invalid stop bit"); - - // setup parity - if (parity_ == parity_none) { - dcbSerialParams.Parity = NOPARITY; - } else if (parity_ == parity_even) { - dcbSerialParams.Parity = EVENPARITY; - } else if (parity_ == parity_odd) { - dcbSerialParams.Parity = ODDPARITY; - } else { - throw invalid_argument ("invalid parity"); - } - - // setup flowcontrol - if (flowcontrol_ == flowcontrol_none) { - dcbSerialParams.fOutxCtsFlow = false; - dcbSerialParams.fRtsControl = 0x00; - dcbSerialParams.fOutX = false; - dcbSerialParams.fInX = false; - } - if (flowcontrol_ == flowcontrol_software) { - dcbSerialParams.fOutxCtsFlow = false; - dcbSerialParams.fRtsControl = 0x00; - dcbSerialParams.fOutX = true; - dcbSerialParams.fInX = true; - } - if (flowcontrol_ == flowcontrol_hardware) { - dcbSerialParams.fOutxCtsFlow = true; - dcbSerialParams.fRtsControl = 0x03; - dcbSerialParams.fOutX = false; - dcbSerialParams.fInX = false; - } - - // activate settings - if (!SetCommState(fd_, &dcbSerialParams)){ - THROW (IOException, "Error setting serial port settings."); - } - - // Setup timeouts - COMMTIMEOUTS timeouts = {0}; - timeouts.ReadIntervalTimeout = timeout_.inter_byte_timeout; - timeouts.ReadTotalTimeoutConstant = timeout_.read_timeout_constant; - timeouts.ReadTotalTimeoutMultiplier = timeout_.read_timeout_multiplier; - timeouts.WriteTotalTimeoutConstant = timeout_.write_timeout_constant; - timeouts.WriteTotalTimeoutMultiplier = timeout_.write_timeout_multiplier; - if (!SetCommTimeouts(fd_, &timeouts)) { - THROW (IOException, "Error setting timeouts."); - } -} - -void -Serial::SerialImpl::close () -{ - if (is_open_ == true) { - if (fd_ != INVALID_HANDLE_VALUE) { - CloseHandle(fd_); - fd_ = INVALID_HANDLE_VALUE; - } - is_open_ = false; - } -} - -bool -Serial::SerialImpl::isOpen () const -{ - return is_open_; -} - -size_t -Serial::SerialImpl::available () -{ - if (!is_open_) { - return 0; - } - COMSTAT cs; - if (!ClearCommError(fd_, NULL, &cs)) { - stringstream ss; - ss << "Error while checking status of the serial port: " << GetLastError(); - THROW (IOException, ss.str().c_str()); - } - return static_cast(cs.cbInQue); -} - -size_t -Serial::SerialImpl::read (uint8_t *buf, size_t size) -{ - if (!is_open_) { - throw PortNotOpenedException ("Serial::read"); - } - DWORD bytes_read; - if (!ReadFile(fd_, buf, size, &bytes_read, NULL)) { - stringstream ss; - ss << "Error while reading from the serial port: " << GetLastError(); - THROW (IOException, ss.str().c_str()); - } - return (size_t) (bytes_read); -} - -size_t -Serial::SerialImpl::write (const uint8_t *data, size_t length) -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::write"); - } - DWORD bytes_written; - if (!WriteFile(fd_, data, length, &bytes_written, NULL)) { - stringstream ss; - ss << "Error while writing to the serial port: " << GetLastError(); - THROW (IOException, ss.str().c_str()); - } - return (size_t) (bytes_written); -} - -void -Serial::SerialImpl::setPort (const string &port) -{ - port_ = wstring(port.begin(), port.end()); -} - -string -Serial::SerialImpl::getPort () const -{ - return string(port_.begin(), port_.end()); -} - -void -Serial::SerialImpl::setTimeout (serial::Timeout &timeout) -{ - timeout_ = timeout; - if (is_open_) { - reconfigurePort (); - } -} - -serial::Timeout -Serial::SerialImpl::getTimeout () const -{ - return timeout_; -} - -void -Serial::SerialImpl::setBaudrate (unsigned long baudrate) -{ - baudrate_ = baudrate; - if (is_open_) { - reconfigurePort (); - } -} - -unsigned long -Serial::SerialImpl::getBaudrate () const -{ - return baudrate_; -} - -void -Serial::SerialImpl::setBytesize (serial::bytesize_t bytesize) -{ - bytesize_ = bytesize; - if (is_open_) { - reconfigurePort (); - } -} - -serial::bytesize_t -Serial::SerialImpl::getBytesize () const -{ - return bytesize_; -} - -void -Serial::SerialImpl::setParity (serial::parity_t parity) -{ - parity_ = parity; - if (is_open_) { - reconfigurePort (); - } -} - -serial::parity_t -Serial::SerialImpl::getParity () const -{ - return parity_; -} - -void -Serial::SerialImpl::setStopbits (serial::stopbits_t stopbits) -{ - stopbits_ = stopbits; - if (is_open_) { - reconfigurePort (); - } -} - -serial::stopbits_t -Serial::SerialImpl::getStopbits () const -{ - return stopbits_; -} - -void -Serial::SerialImpl::setFlowcontrol (serial::flowcontrol_t flowcontrol) -{ - flowcontrol_ = flowcontrol; - if (is_open_) { - reconfigurePort (); - } -} - -serial::flowcontrol_t -Serial::SerialImpl::getFlowcontrol () const -{ - return flowcontrol_; -} - -void -Serial::SerialImpl::flush () -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::flush"); - } - FlushFileBuffers (fd_); -} - -void -Serial::SerialImpl::flushInput () -{ - THROW (IOException, "flushInput is not supported on Windows."); -} - -void -Serial::SerialImpl::flushOutput () -{ - THROW (IOException, "flushOutput is not supported on Windows."); -} - -void -Serial::SerialImpl::sendBreak (int duration) -{ - THROW (IOException, "sendBreak is not supported on Windows."); -} - -void -Serial::SerialImpl::setBreak (bool level) -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::setBreak"); - } - if (level) { - EscapeCommFunction (fd_, SETBREAK); - } else { - EscapeCommFunction (fd_, CLRBREAK); - } -} - -void -Serial::SerialImpl::setRTS (bool level) -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::setRTS"); - } - if (level) { - EscapeCommFunction (fd_, SETRTS); - } else { - EscapeCommFunction (fd_, CLRRTS); - } -} - -void -Serial::SerialImpl::setDTR (bool level) -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::setDTR"); - } - if (level) { - EscapeCommFunction (fd_, SETDTR); - } else { - EscapeCommFunction (fd_, CLRDTR); - } -} - -bool -Serial::SerialImpl::waitForChange () -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::waitForChange"); - } - DWORD dwCommEvent; - - if (!SetCommMask(fd_, EV_CTS | EV_DSR | EV_RING | EV_RLSD)) { - // Error setting communications mask - return false; - } - - if (!WaitCommEvent(fd_, &dwCommEvent, NULL)) { - // An error occurred waiting for the event. - return false; - } else { - // Event has occurred. - return true; - } -} - -bool -Serial::SerialImpl::getCTS () -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::getCTS"); - } - DWORD dwModemStatus; - if (!GetCommModemStatus(fd_, &dwModemStatus)) { - THROW (IOException, "Error getting the status of the CTS line."); - } - - return (MS_CTS_ON & dwModemStatus) != 0; -} - -bool -Serial::SerialImpl::getDSR () -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::getDSR"); - } - DWORD dwModemStatus; - if (!GetCommModemStatus(fd_, &dwModemStatus)) { - THROW (IOException, "Error getting the status of the DSR line."); - } - - return (MS_DSR_ON & dwModemStatus) != 0; -} - -bool -Serial::SerialImpl::getRI() -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::getRI"); - } - DWORD dwModemStatus; - if (!GetCommModemStatus(fd_, &dwModemStatus)) { - THROW (IOException, "Error getting the status of the RI line."); - } - - return (MS_RING_ON & dwModemStatus) != 0; -} - -bool -Serial::SerialImpl::getCD() -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::getCD"); - } - DWORD dwModemStatus; - if (!GetCommModemStatus(fd_, &dwModemStatus)) { - // Error in GetCommModemStatus; - THROW (IOException, "Error getting the status of the CD line."); - } - - return (MS_RLSD_ON & dwModemStatus) != 0; -} - -void -Serial::SerialImpl::readLock() -{ - if (WaitForSingleObject(read_mutex, INFINITE) != WAIT_OBJECT_0) { - THROW (IOException, "Error claiming read mutex."); - } -} - -void -Serial::SerialImpl::readUnlock() -{ - if (!ReleaseMutex(read_mutex)) { - THROW (IOException, "Error releasing read mutex."); - } -} - -void -Serial::SerialImpl::writeLock() -{ - if (WaitForSingleObject(write_mutex, INFINITE) != WAIT_OBJECT_0) { - THROW (IOException, "Error claiming write mutex."); - } -} - -void -Serial::SerialImpl::writeUnlock() -{ - if (!ReleaseMutex(write_mutex)) { - THROW (IOException, "Error releasing write mutex."); - } -} - -#endif // #if defined(_WIN32) - diff --git a/dependencies/build/serial/src/serial.cc b/dependencies/build/serial/src/serial.cc deleted file mode 100755 index a2478411..00000000 --- a/dependencies/build/serial/src/serial.cc +++ /dev/null @@ -1,397 +0,0 @@ -/* Copyright 2012 William Woodall and John Harrison */ -#if !defined(_WIN32) && !defined(__OpenBSD__) -# include -#endif - -#include "serial/serial.h" - -#ifdef _WIN32 -#include "serial/impl/win.h" -#else -#include "serial/impl/unix.h" -#endif - -using std::invalid_argument; -using std::min; -using std::numeric_limits; -using std::vector; -using std::size_t; -using std::string; - -using serial::Serial; -using serial::SerialException; -using serial::IOException; -using serial::bytesize_t; -using serial::parity_t; -using serial::stopbits_t; -using serial::flowcontrol_t; - -class Serial::ScopedReadLock { -public: - ScopedReadLock(SerialImpl *pimpl) : pimpl_(pimpl) { - this->pimpl_->readLock(); - } - ~ScopedReadLock() { - this->pimpl_->readUnlock(); - } -private: - // Disable copy constructors - ScopedReadLock(const ScopedReadLock&); - const ScopedReadLock& operator=(ScopedReadLock); - - SerialImpl *pimpl_; -}; - -class Serial::ScopedWriteLock { -public: - ScopedWriteLock(SerialImpl *pimpl) : pimpl_(pimpl) { - this->pimpl_->writeLock(); - } - ~ScopedWriteLock() { - this->pimpl_->writeUnlock(); - } -private: - // Disable copy constructors - ScopedWriteLock(const ScopedWriteLock&); - const ScopedWriteLock& operator=(ScopedWriteLock); - SerialImpl *pimpl_; -}; - -Serial::Serial (const string &port, uint32_t baudrate, serial::Timeout timeout, - bytesize_t bytesize, parity_t parity, stopbits_t stopbits, - flowcontrol_t flowcontrol) - : read_cache_(""), pimpl_(new SerialImpl (port, baudrate, bytesize, parity, - stopbits, flowcontrol)) -{ - pimpl_->setTimeout(timeout); -} - -Serial::~Serial () -{ - delete pimpl_; -} - -void -Serial::open () -{ - pimpl_->open (); -} - -void -Serial::close () -{ - pimpl_->close (); -} - -bool -Serial::isOpen () const -{ - return pimpl_->isOpen (); -} - -size_t -Serial::available () -{ - return pimpl_->available (); -} - -size_t -Serial::read_ (uint8_t *buffer, size_t size) -{ - return this->pimpl_->read (buffer, size); -} - -size_t -Serial::read (uint8_t *buffer, size_t size) -{ - ScopedReadLock (this->pimpl_); - return this->pimpl_->read (buffer, size); -} - -size_t -Serial::read (std::vector &buffer, size_t size) -{ - ScopedReadLock (this->pimpl_); - uint8_t *buffer_ = new uint8_t[size]; - size_t bytes_read = this->pimpl_->read (buffer_, size); - buffer.insert (buffer.end (), buffer_, buffer_+bytes_read); - delete[] buffer_; - return bytes_read; -} - -size_t -Serial::read (std::string &buffer, size_t size) -{ - ScopedReadLock (this->pimpl_); - uint8_t *buffer_ = new uint8_t[size]; - size_t bytes_read = this->pimpl_->read (buffer_, size); - buffer.append (reinterpret_cast(buffer_), bytes_read); - delete[] buffer_; - return bytes_read; -} - -string -Serial::read (size_t size) -{ - std::string buffer; - this->read (buffer, size); - return buffer; -} - -size_t -Serial::readline (string &buffer, size_t size, string eol) -{ - ScopedReadLock (this->pimpl_); - size_t eol_len = eol.length (); - uint8_t *buffer_ = static_cast - (alloca (size * sizeof (uint8_t))); - size_t read_so_far = 0; - while (true) - { - size_t bytes_read = this->read_ (buffer_ + read_so_far, 1); - read_so_far += bytes_read; - if (bytes_read == 0) { - break; // Timeout occured on reading 1 byte - } - if (string (reinterpret_cast - (buffer_ + read_so_far - eol_len), eol_len) == eol) { - break; // EOL found - } - if (read_so_far == size) { - break; // Reached the maximum read length - } - } - buffer.append(reinterpret_cast (buffer_), read_so_far); - return read_so_far; -} - -string -Serial::readline (size_t size, string eol) -{ - std::string buffer; - this->readline (buffer, size, eol); - return buffer; -} - -vector -Serial::readlines (size_t size, string eol) -{ - ScopedReadLock (this->pimpl_); - std::vector lines; - size_t eol_len = eol.length (); - uint8_t *buffer_ = static_cast - (alloca (size * sizeof (uint8_t))); - size_t read_so_far = 0; - size_t start_of_line = 0; - while (read_so_far < size) { - size_t bytes_read = this->read_ (buffer_+read_so_far, 1); - read_so_far += bytes_read; - if (bytes_read == 0) { - if (start_of_line != read_so_far) { - lines.push_back ( - string (reinterpret_cast (buffer_ + start_of_line), - read_so_far - start_of_line)); - } - break; // Timeout occured on reading 1 byte - } - if (string (reinterpret_cast - (buffer_ + read_so_far - eol_len), eol_len) == eol) { - // EOL found - lines.push_back( - string(reinterpret_cast (buffer_ + start_of_line), - read_so_far - start_of_line)); - start_of_line = read_so_far; - } - if (read_so_far == size) { - if (start_of_line != read_so_far) { - lines.push_back( - string(reinterpret_cast (buffer_ + start_of_line), - read_so_far - start_of_line)); - } - break; // Reached the maximum read length - } - } - return lines; -} - -size_t -Serial::write (const string &data) -{ - ScopedWriteLock(this->pimpl_); - return this->write_ (reinterpret_cast(data.c_str()), - data.length()); -} - -size_t -Serial::write (const std::vector &data) -{ - ScopedWriteLock(this->pimpl_); - return this->write_ (&data[0], data.size()); -} - -size_t -Serial::write (const uint8_t *data, size_t size) -{ - ScopedWriteLock(this->pimpl_); - return this->write_(data, size); -} - -size_t -Serial::write_ (const uint8_t *data, size_t length) -{ - return pimpl_->write (data, length); -} - -void -Serial::setPort (const string &port) -{ - ScopedReadLock(this->pimpl_); - ScopedWriteLock(this->pimpl_); - bool was_open = pimpl_->isOpen (); - if (was_open) close(); - pimpl_->setPort (port); - if (was_open) open (); -} - -string -Serial::getPort () const -{ - return pimpl_->getPort (); -} - -void -Serial::setTimeout (serial::Timeout &timeout) -{ - pimpl_->setTimeout (timeout); -} - -serial::Timeout -Serial::getTimeout () const { - return pimpl_->getTimeout (); -} - -void -Serial::setBaudrate (uint32_t baudrate) -{ - pimpl_->setBaudrate (baudrate); -} - -uint32_t -Serial::getBaudrate () const -{ - return uint32_t(pimpl_->getBaudrate ()); -} - -void -Serial::setBytesize (bytesize_t bytesize) -{ - pimpl_->setBytesize (bytesize); -} - -bytesize_t -Serial::getBytesize () const -{ - return pimpl_->getBytesize (); -} - -void -Serial::setParity (parity_t parity) -{ - pimpl_->setParity (parity); -} - -parity_t -Serial::getParity () const -{ - return pimpl_->getParity (); -} - -void -Serial::setStopbits (stopbits_t stopbits) -{ - pimpl_->setStopbits (stopbits); -} - -stopbits_t -Serial::getStopbits () const -{ - return pimpl_->getStopbits (); -} - -void -Serial::setFlowcontrol (flowcontrol_t flowcontrol) -{ - pimpl_->setFlowcontrol (flowcontrol); -} - -flowcontrol_t -Serial::getFlowcontrol () const -{ - return pimpl_->getFlowcontrol (); -} - -void Serial::flush () -{ - ScopedReadLock(this->pimpl_); - ScopedWriteLock(this->pimpl_); - pimpl_->flush (); - read_cache_.clear (); -} - -void Serial::flushInput () -{ - ScopedReadLock(this->pimpl_); - pimpl_->flushInput (); -} - -void Serial::flushOutput () -{ - ScopedWriteLock(this->pimpl_); - pimpl_->flushOutput (); - read_cache_.clear (); -} - -void Serial::sendBreak (int duration) -{ - pimpl_->sendBreak (duration); -} - -void Serial::setBreak (bool level) -{ - pimpl_->setBreak (level); -} - -void Serial::setRTS (bool level) -{ - pimpl_->setRTS (level); -} - -void Serial::setDTR (bool level) -{ - pimpl_->setDTR (level); -} - -bool Serial::waitForChange() -{ - return pimpl_->waitForChange(); -} - -bool Serial::getCTS () -{ - return pimpl_->getCTS (); -} - -bool Serial::getDSR () -{ - return pimpl_->getDSR (); -} - -bool Serial::getRI () -{ - return pimpl_->getRI (); -} - -bool Serial::getCD () -{ - return pimpl_->getCD (); -} diff --git a/dependencies/include/serial/impl/unix.h b/dependencies/include/serial/impl/unix.h deleted file mode 100644 index a7985da3..00000000 --- a/dependencies/include/serial/impl/unix.h +++ /dev/null @@ -1,204 +0,0 @@ -/*! - * \file serial/impl/unix.h - * \author William Woodall - * \author John Harrison - * \version 0.1 - * - * \section LICENSE - * - * The MIT License - * - * Copyright (c) 2012 William Woodall, John Harrison - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * \section DESCRIPTION - * - * This provides a unix based pimpl for the Serial class. This implementation is - * based off termios.h and uses select for multiplexing the IO ports. - * - */ - -#if !defined(_WIN32) - -#ifndef SERIAL_IMPL_UNIX_H -#define SERIAL_IMPL_UNIX_H - -#include "serial/serial.h" - -#include - -namespace serial { - -using std::size_t; -using std::string; -using std::invalid_argument; - -using serial::SerialException; -using serial::IOException; - -class serial::Serial::SerialImpl { -public: - SerialImpl (const string &port, - unsigned long baudrate, - bytesize_t bytesize, - parity_t parity, - stopbits_t stopbits, - flowcontrol_t flowcontrol); - - virtual ~SerialImpl (); - - void - open (); - - void - close (); - - bool - isOpen () const; - - size_t - available (); - - size_t - read (uint8_t *buf, size_t size = 1); - - size_t - write (const uint8_t *data, size_t length); - - void - flush (); - - void - flushInput (); - - void - flushOutput (); - - void - sendBreak (int duration); - - void - setBreak (bool level); - - void - setRTS (bool level); - - void - setDTR (bool level); - - bool - waitForChange (); - - bool - getCTS (); - - bool - getDSR (); - - bool - getRI (); - - bool - getCD (); - - void - setPort (const string &port); - - string - getPort () const; - - void - setTimeout (Timeout &timeout); - - Timeout - getTimeout () const; - - void - setBaudrate (unsigned long baudrate); - - unsigned long - getBaudrate () const; - - void - setBytesize (bytesize_t bytesize); - - bytesize_t - getBytesize () const; - - void - setParity (parity_t parity); - - parity_t - getParity () const; - - void - setStopbits (stopbits_t stopbits); - - stopbits_t - getStopbits () const; - - void - setFlowcontrol (flowcontrol_t flowcontrol); - - flowcontrol_t - getFlowcontrol () const; - - void - readLock (); - - void - readUnlock (); - - void - writeLock (); - - void - writeUnlock (); - -protected: - void reconfigurePort (); - -private: - string port_; // Path to the file descriptor - int fd_; // The current file descriptor - - bool is_open_; - bool xonxoff_; - bool rtscts_; - - Timeout timeout_; // Timeout for read operations - unsigned long baudrate_; // Baudrate - - parity_t parity_; // Parity - bytesize_t bytesize_; // Size of the bytes - stopbits_t stopbits_; // Stop Bits - flowcontrol_t flowcontrol_; // Flow Control - - // Mutex used to lock the read functions - pthread_mutex_t read_mutex; - // Mutex used to lock the write functions - pthread_mutex_t write_mutex; -}; - -} - -#endif // SERIAL_IMPL_UNIX_H - -#endif // !defined(_WIN32) diff --git a/dependencies/include/serial/impl/win.h b/dependencies/include/serial/impl/win.h deleted file mode 100644 index 605f5d0f..00000000 --- a/dependencies/include/serial/impl/win.h +++ /dev/null @@ -1,201 +0,0 @@ -/*! - * \file serial/impl/windows.h - * \author William Woodall - * \author John Harrison - * \version 0.1 - * - * \section LICENSE - * - * The MIT License - * - * Copyright (c) 2012 William Woodall, John Harrison - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * \section DESCRIPTION - * - * This provides a windows implementation of the Serial class interface. - * - */ - -#if defined(_WIN32) - -#ifndef SERIAL_IMPL_WINDOWS_H -#define SERIAL_IMPL_WINDOWS_H - -#include "serial/serial.h" - -#include "windows.h" - -namespace serial { - -using std::string; -using std::wstring; -using std::invalid_argument; - -using serial::SerialException; -using serial::IOException; - -class serial::Serial::SerialImpl { -public: - SerialImpl (const string &port, - unsigned long baudrate, - bytesize_t bytesize, - parity_t parity, - stopbits_t stopbits, - flowcontrol_t flowcontrol); - - virtual ~SerialImpl (); - - void - open (); - - void - close (); - - bool - isOpen () const; - - size_t - available (); - - size_t - read (uint8_t *buf, size_t size = 1); - - size_t - write (const uint8_t *data, size_t length); - - void - flush (); - - void - flushInput (); - - void - flushOutput (); - - void - sendBreak (int duration); - - void - setBreak (bool level); - - void - setRTS (bool level); - - void - setDTR (bool level); - - bool - waitForChange (); - - bool - getCTS (); - - bool - getDSR (); - - bool - getRI (); - - bool - getCD (); - - void - setPort (const string &port); - - string - getPort () const; - - void - setTimeout (Timeout &timeout); - - Timeout - getTimeout () const; - - void - setBaudrate (unsigned long baudrate); - - unsigned long - getBaudrate () const; - - void - setBytesize (bytesize_t bytesize); - - bytesize_t - getBytesize () const; - - void - setParity (parity_t parity); - - parity_t - getParity () const; - - void - setStopbits (stopbits_t stopbits); - - stopbits_t - getStopbits () const; - - void - setFlowcontrol (flowcontrol_t flowcontrol); - - flowcontrol_t - getFlowcontrol () const; - - void - readLock (); - - void - readUnlock (); - - void - writeLock (); - - void - writeUnlock (); - -protected: - void reconfigurePort (); - -private: - wstring port_; // Path to the file descriptor - HANDLE fd_; - - bool is_open_; - - Timeout timeout_; // Timeout for read operations - unsigned long baudrate_; // Baudrate - - parity_t parity_; // Parity - bytesize_t bytesize_; // Size of the bytes - stopbits_t stopbits_; // Stop Bits - flowcontrol_t flowcontrol_; // Flow Control - - // Mutex used to lock the read functions - HANDLE read_mutex; - // Mutex used to lock the write functions - HANDLE write_mutex; -}; - -} - -#endif // SERIAL_IMPL_WINDOWS_H - -#endif // if defined(_WIN32) diff --git a/dependencies/include/serial/serial.h b/dependencies/include/serial/serial.h deleted file mode 100644 index 0b3165a1..00000000 --- a/dependencies/include/serial/serial.h +++ /dev/null @@ -1,700 +0,0 @@ -/*! - * \file serial/serial.h - * \author William Woodall - * \author John Harrison - * \version 0.1 - * - * \section LICENSE - * - * The MIT License - * - * Copyright (c) 2012 William Woodall - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * \section DESCRIPTION - * - * This provides a cross platform interface for interacting with Serial Ports. - */ - -#ifndef SERIAL_H -#define SERIAL_H - -#include -#include -#include -#include -#include -#include -#include -#include - -#define THROW(exceptionClass, message) throw exceptionClass(__FILE__, \ -__LINE__, (message) ) - -namespace serial { - -/*! - * Enumeration defines the possible bytesizes for the serial port. - */ -typedef enum { - fivebits = 5, - sixbits = 6, - sevenbits = 7, - eightbits = 8 -} bytesize_t; - -/*! - * Enumeration defines the possible parity types for the serial port. - */ -typedef enum { - parity_none = 0, - parity_odd = 1, - parity_even = 2 -} parity_t; - -/*! - * Enumeration defines the possible stopbit types for the serial port. - */ -typedef enum { - stopbits_one = 1, - stopbits_two = 2, - stopbits_one_point_five -} stopbits_t; - -/*! - * Enumeration defines the possible flowcontrol types for the serial port. - */ -typedef enum { - flowcontrol_none = 0, - flowcontrol_software, - flowcontrol_hardware -} flowcontrol_t; - -/*! - * Structure for setting the timeout of the serial port, times are - * in milliseconds. - * - * In order to disable the interbyte timeout, set it to Timeout::max(). - */ -struct Timeout { -#ifdef max -# undef max -#endif - static uint32_t max() {return std::numeric_limits::max();} - /*! - * Convenience function to generate Timeout structs using a - * single absolute timeout. - * - * \param timeout A long that defines the time in milliseconds until a - * timeout occurs after a call to read or write is made. - * - * \return Timeout struct that represents this simple timeout provided. - */ - static Timeout simpleTimeout(uint32_t timeout) { - return Timeout(max(), timeout, 0, timeout, 0); - } - - /*! Number of milliseconds between bytes received to timeout on. */ - uint32_t inter_byte_timeout; - /*! A constant number of milliseconds to wait after calling read. */ - uint32_t read_timeout_constant; - /*! A multiplier against the number of requested bytes to wait after - * calling read. - */ - uint32_t read_timeout_multiplier; - /*! A constant number of milliseconds to wait after calling write. */ - uint32_t write_timeout_constant; - /*! A multiplier against the number of requested bytes to wait after - * calling write. - */ - uint32_t write_timeout_multiplier; - - explicit Timeout (uint32_t inter_byte_timeout_=0, - uint32_t read_timeout_constant_=0, - uint32_t read_timeout_multiplier_=0, - uint32_t write_timeout_constant_=0, - uint32_t write_timeout_multiplier_=0) - : inter_byte_timeout(inter_byte_timeout_), - read_timeout_constant(read_timeout_constant_), - read_timeout_multiplier(read_timeout_multiplier_), - write_timeout_constant(write_timeout_constant_), - write_timeout_multiplier(write_timeout_multiplier_) - {} -}; - -/*! - * Class that provides a portable serial port interface. - */ -class Serial { -public: - /*! - * Creates a Serial object and opens the port if a port is specified, - * otherwise it remains closed until serial::Serial::open is called. - * - * \param port A std::string containing the address of the serial port, - * which would be something like 'COM1' on Windows and '/dev/ttyS0' - * on Linux. - * - * \param baudrate An unsigned 32-bit integer that represents the baudrate - * - * \param timeout A serial::Timeout struct that defines the timeout - * conditions for the serial port. \see serial::Timeout - * - * \param bytesize Size of each byte in the serial transmission of data, - * default is eightbits, possible values are: fivebits, sixbits, sevenbits, - * eightbits - * - * \param parity Method of parity, default is parity_none, possible values - * are: parity_none, parity_odd, parity_even - * - * \param stopbits Number of stop bits used, default is stopbits_one, - * possible values are: stopbits_one, stopbits_one_point_five, stopbits_two - * - * \param flowcontrol Type of flowcontrol used, default is - * flowcontrol_none, possible values are: flowcontrol_none, - * flowcontrol_software, flowcontrol_hardware - * - * \throw serial::PortNotOpenedException - * \throw serial::IOException - * \throw std::invalid_argument - */ - Serial (const std::string &port = "", - uint32_t baudrate = 9600, - Timeout timeout = Timeout(), - bytesize_t bytesize = eightbits, - parity_t parity = parity_none, - stopbits_t stopbits = stopbits_one, - flowcontrol_t flowcontrol = flowcontrol_none); - - /*! Destructor */ - virtual ~Serial (); - - /*! - * Opens the serial port as long as the port is set and the port isn't - * already open. - * - * If the port is provided to the constructor then an explicit call to open - * is not needed. - * - * \see Serial::Serial - * - * \throw std::invalid_argument - * \throw serial::SerialException - * \throw serial::IOException - */ - void - open (); - - /*! Gets the open status of the serial port. - * - * \return Returns true if the port is open, false otherwise. - */ - bool - isOpen () const; - - /*! Closes the serial port. */ - void - close (); - - /*! Return the number of characters in the buffer. */ - size_t - available (); - - /*! Read a given amount of bytes from the serial port into a given buffer. - * - * The read function will return in one of three cases: - * * The number of requested bytes was read. - * * In this case the number of bytes requested will match the size_t - * returned by read. - * * A timeout occurred, in this case the number of bytes read will not - * match the amount requested, but no exception will be thrown. One of - * two possible timeouts occurred: - * * The inter byte timeout expired, this means that number of - * milliseconds elapsed between receiving bytes from the serial port - * exceeded the inter byte timeout. - * * The total timeout expired, which is calculated by multiplying the - * read timeout multiplier by the number of requested bytes and then - * added to the read timeout constant. If that total number of - * milliseconds elapses after the initial call to read a timeout will - * occur. - * * An exception occurred, in this case an actual exception will be thrown. - * - * \param buffer An uint8_t array of at least the requested size. - * \param size A size_t defining how many bytes to be read. - * - * \return A size_t representing the number of bytes read as a result of the - * call to read. - */ - size_t - read (uint8_t *buffer, size_t size); - - /*! Read a given amount of bytes from the serial port into a give buffer. - * - * \param buffer A reference to a std::vector of uint8_t. - * \param size A size_t defining how many bytes to be read. - * - * \return A size_t representing the number of bytes read as a result of the - * call to read. - */ - size_t - read (std::vector &buffer, size_t size = 1); - - /*! Read a given amount of bytes from the serial port into a give buffer. - * - * \param buffer A reference to a std::string. - * \param size A size_t defining how many bytes to be read. - * - * \return A size_t representing the number of bytes read as a result of the - * call to read. - */ - size_t - read (std::string &buffer, size_t size = 1); - - /*! Read a given amount of bytes from the serial port and return a string - * containing the data. - * - * \param size A size_t defining how many bytes to be read. - * - * \return A std::string containing the data read from the port. - */ - std::string - read (size_t size = 1); - - /*! Reads in a line or until a given delimiter has been processed. - * - * Reads from the serial port until a single line has been read. - * - * \param buffer A std::string reference used to store the data. - * \param size A maximum length of a line, defaults to 65536 (2^16) - * \param eol A string to match against for the EOL. - * - * \return A size_t representing the number of bytes read. - */ - size_t - readline (std::string &buffer, size_t size = 65536, std::string eol = "\n"); - - /*! Reads in a line or until a given delimiter has been processed. - * - * Reads from the serial port until a single line has been read. - * - * \param size A maximum length of a line, defaults to 65536 (2^16) - * \param eol A string to match against for the EOL. - * - * \return A std::string containing the line. - */ - std::string - readline (size_t size = 65536, std::string eol = "\n"); - - /*! Reads in multiple lines until the serial port times out. - * - * This requires a timeout > 0 before it can be run. It will read until a - * timeout occurs and return a list of strings. - * - * \param size A maximum length of combined lines, defaults to 65536 (2^16) - * - * \param eol A string to match against for the EOL. - * - * \return A vector containing the lines. - */ - std::vector - readlines (size_t size = 65536, std::string eol = "\n"); - - /*! Write a string to the serial port. - * - * \param data A const reference containing the data to be written - * to the serial port. - * - * \param size A size_t that indicates how many bytes should be written from - * the given data buffer. - * - * \return A size_t representing the number of bytes actually written to - * the serial port. - */ - size_t - write (const uint8_t *data, size_t size); - - /*! Write a string to the serial port. - * - * \param data A const reference containing the data to be written - * to the serial port. - * - * \return A size_t representing the number of bytes actually written to - * the serial port. - */ - size_t - write (const std::vector &data); - - /*! Write a string to the serial port. - * - * \param data A const reference containing the data to be written - * to the serial port. - * - * \return A size_t representing the number of bytes actually written to - * the serial port. - */ - size_t - write (const std::string &data); - - /*! Sets the serial port identifier. - * - * \param port A const std::string reference containing the address of the - * serial port, which would be something like 'COM1' on Windows and - * '/dev/ttyS0' on Linux. - * - * \throw InvalidConfigurationException - */ - void - setPort (const std::string &port); - - /*! Gets the serial port identifier. - * - * \see Serial::setPort - * - * \throw InvalidConfigurationException - */ - std::string - getPort () const; - - /*! Sets the timeout for reads and writes using the Timeout struct. - * - * There are two timeout conditions described here: - * * The inter byte timeout: - * * The inter_byte_timeout component of serial::Timeout defines the - * maximum amount of time, in milliseconds, between receiving bytes on - * the serial port that can pass before a timeout occurs. Setting this - * to zero will prevent inter byte timeouts from occurring. - * * Total time timeout: - * * The constant and multiplier component of this timeout condition, - * for both read and write, are defined in serial::Timeout. This - * timeout occurs if the total time since the read or write call was - * made exceeds the specified time in milliseconds. - * * The limit is defined by multiplying the multiplier component by the - * number of requested bytes and adding that product to the constant - * component. In this way if you want a read call, for example, to - * timeout after exactly one second regardless of the number of bytes - * you asked for then set the read_timeout_constant component of - * serial::Timeout to 1000 and the read_timeout_multiplier to zero. - * This timeout condition can be used in conjunction with the inter - * byte timeout condition with out any problems, timeout will simply - * occur when one of the two timeout conditions is met. This allows - * users to have maximum control over the trade-off between - * responsiveness and efficiency. - * - * Read and write functions will return in one of three cases. When the - * reading or writing is complete, when a timeout occurs, or when an - * exception occurs. - * - * \param timeout A serial::Timeout struct containing the inter byte - * timeout, and the read and write timeout constants and multipliers. - * - * \see serial::Timeout - */ - void - setTimeout (Timeout &timeout); - - /*! Sets the timeout for reads and writes. */ - void - setTimeout (uint32_t inter_byte_timeout, uint32_t read_timeout_constant, - uint32_t read_timeout_multiplier, uint32_t write_timeout_constant, - uint32_t write_timeout_multiplier) - { - Timeout timeout(inter_byte_timeout, read_timeout_constant, - read_timeout_multiplier, write_timeout_constant, - write_timeout_multiplier); - return setTimeout(timeout); - } - - /*! Gets the timeout for reads in seconds. - * - * \return A Timeout struct containing the inter_byte_timeout, and read - * and write timeout constants and multipliers. - * - * \see Serial::setTimeout - */ - Timeout - getTimeout () const; - - /*! Sets the baudrate for the serial port. - * - * Possible baudrates depends on the system but some safe baudrates include: - * 110, 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 56000, - * 57600, 115200 - * Some other baudrates that are supported by some comports: - * 128000, 153600, 230400, 256000, 460800, 921600 - * - * \param baudrate An integer that sets the baud rate for the serial port. - * - * \throw InvalidConfigurationException - */ - void - setBaudrate (uint32_t baudrate); - - /*! Gets the baudrate for the serial port. - * - * \return An integer that sets the baud rate for the serial port. - * - * \see Serial::setBaudrate - * - * \throw InvalidConfigurationException - */ - uint32_t - getBaudrate () const; - - /*! Sets the bytesize for the serial port. - * - * \param bytesize Size of each byte in the serial transmission of data, - * default is eightbits, possible values are: fivebits, sixbits, sevenbits, - * eightbits - * - * \throw InvalidConfigurationException - */ - void - setBytesize (bytesize_t bytesize); - - /*! Gets the bytesize for the serial port. - * - * \see Serial::setBytesize - * - * \throw InvalidConfigurationException - */ - bytesize_t - getBytesize () const; - - /*! Sets the parity for the serial port. - * - * \param parity Method of parity, default is parity_none, possible values - * are: parity_none, parity_odd, parity_even - * - * \throw InvalidConfigurationException - */ - void - setParity (parity_t parity); - - /*! Gets the parity for the serial port. - * - * \see Serial::setParity - * - * \throw InvalidConfigurationException - */ - parity_t - getParity () const; - - /*! Sets the stopbits for the serial port. - * - * \param stopbits Number of stop bits used, default is stopbits_one, - * possible values are: stopbits_one, stopbits_one_point_five, stopbits_two - * - * \throw InvalidConfigurationException - */ - void - setStopbits (stopbits_t stopbits); - - /*! Gets the stopbits for the serial port. - * - * \see Serial::setStopbits - * - * \throw InvalidConfigurationException - */ - stopbits_t - getStopbits () const; - - /*! Sets the flow control for the serial port. - * - * \param flowcontrol Type of flowcontrol used, default is flowcontrol_none, - * possible values are: flowcontrol_none, flowcontrol_software, - * flowcontrol_hardware - * - * \throw InvalidConfigurationException - */ - void - setFlowcontrol (flowcontrol_t flowcontrol); - - /*! Gets the flow control for the serial port. - * - * \see Serial::setFlowcontrol - * - * \throw InvalidConfigurationException - */ - flowcontrol_t - getFlowcontrol () const; - - /*! Flush the input and output buffers */ - void - flush (); - - /*! Flush only the input buffer */ - void - flushInput (); - - /*! Flush only the output buffer */ - void - flushOutput (); - - /*! Sends the RS-232 break signal. See tcsendbreak(3). */ - void - sendBreak (int duration); - - /*! Set the break condition to a given level. Defaults to true. */ - void - setBreak (bool level = true); - - /*! Set the RTS handshaking line to the given level. Defaults to true. */ - void - setRTS (bool level = true); - - /*! Set the DTR handshaking line to the given level. Defaults to true. */ - void - setDTR (bool level = true); - - /*! - * Blocks until CTS, DSR, RI, CD changes or something interrupts it. - * - * Can throw an exception if an error occurs while waiting. - * You can check the status of CTS, DSR, RI, and CD once this returns. - * Uses TIOCMIWAIT via ioctl if available (mostly only on Linux) with a - * resolution of less than +-1ms and as good as +-0.2ms. Otherwise a - * polling method is used which can give +-2ms. - * - * \return Returns true if one of the lines changed, false if something else - * occurred. - * - * \throw SerialException - */ - bool - waitForChange (); - - /*! Returns the current status of the CTS line. */ - bool - getCTS (); - - /*! Returns the current status of the DSR line. */ - bool - getDSR (); - - /*! Returns the current status of the RI line. */ - bool - getRI (); - - /*! Returns the current status of the CD line. */ - bool - getCD (); - -private: - // Disable copy constructors - Serial(const Serial&); - Serial& operator=(const Serial&); - - std::string read_cache_; //!< Cache for doing reads in chunks. - - // Pimpl idiom, d_pointer - class SerialImpl; - SerialImpl *pimpl_; - - // Scoped Lock Classes - class ScopedReadLock; - class ScopedWriteLock; - - // Read common function - size_t - read_ (uint8_t *buffer, size_t size); - // Write common function - size_t - write_ (const uint8_t *data, size_t length); - -}; - -class SerialException : public std::exception -{ - // Disable copy constructors - SerialException& operator=(const SerialException&); - std::string e_what_; -public: - SerialException (const char *description) { - std::stringstream ss; - ss << "SerialException " << description << " failed."; - e_what_ = ss.str(); - } - SerialException (const SerialException& other) : e_what_(other.e_what_) {} - virtual ~SerialException() throw() {} - virtual const char* what () const throw () { - return e_what_.c_str(); - } -}; - -class IOException : public std::exception -{ - // Disable copy constructors - IOException& operator=(const IOException&); - std::string file_; - int line_; - std::string e_what_; - int errno_; -public: - explicit IOException (std::string file, int line, int errnum) - : file_(file), line_(line), errno_(errnum) { - std::stringstream ss; -#if defined(_WIN32) - char error_str [1024]; - strerror_s(error_str, 1024, errnum); -#else - char * error_str = strerror(errnum); -#endif - ss << "IO Exception (" << errno_ << "): " << error_str; - ss << ", file " << file_ << ", line " << line_ << "."; - e_what_ = ss.str(); - } - explicit IOException (std::string file, int line, const char * description) - : file_(file), line_(line), errno_(0) { - std::stringstream ss; - ss << "IO Exception: " << description; - ss << ", file " << file_ << ", line " << line_ << "."; - e_what_ = ss.str(); - } - virtual ~IOException() throw() {} - IOException (const IOException& other) : file_(other.file_), line_(other.line_), e_what_(other.e_what_), errno_(other.errno_) {} - - int getErrorNumber () { return errno_; } - - virtual const char* what () const throw () { - return e_what_.c_str(); - } -}; - -class PortNotOpenedException : public std::exception -{ - // Disable copy constructors - const PortNotOpenedException& operator=(PortNotOpenedException); - std::string e_what_; -public: - PortNotOpenedException (const char * description) { - std::stringstream ss; - ss << "PortNotOpenedException " << description << " failed."; - e_what_ = ss.str(); - } - PortNotOpenedException (const PortNotOpenedException& other) : e_what_(other.e_what_) {} - virtual ~PortNotOpenedException() throw() {} - virtual const char* what () const throw () { - return e_what_.c_str(); - } -}; - -} // namespace serial - -#endif diff --git a/dependencies/include/serial/v8stdint.h b/dependencies/include/serial/v8stdint.h deleted file mode 100644 index f3be96b1..00000000 --- a/dependencies/include/serial/v8stdint.h +++ /dev/null @@ -1,57 +0,0 @@ -// This header is from the v8 google project: -// http://code.google.com/p/v8/source/browse/trunk/include/v8stdint.h - -// Copyright 2012 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Load definitions of standard types. - -#ifndef V8STDINT_H_ -#define V8STDINT_H_ - -#include -#include - -#if defined(_WIN32) && !defined(__MINGW32__) - -typedef signed char int8_t; -typedef unsigned char uint8_t; -typedef short int16_t; // NOLINT -typedef unsigned short uint16_t; // NOLINT -typedef int int32_t; -typedef unsigned int uint32_t; -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; -// intptr_t and friends are defined in crtdefs.h through stdio.h. - -#else - -#include - -#endif - -#endif // V8STDINT_H_ diff --git a/include/boblightserver/BoblightServer.h b/include/boblightserver/BoblightServer.h index d6180ba3..e324a715 100644 --- a/include/boblightserver/BoblightServer.h +++ b/include/boblightserver/BoblightServer.h @@ -25,7 +25,7 @@ public: /// @param hyperion Hyperion instance /// @param port port number on which to start listening for connections /// - BoblightServer(Hyperion * hyperion, const int priority, uint16_t port = 19333); + BoblightServer(const int priority, uint16_t port = 19333); ~BoblightServer(); /// diff --git a/include/effectengine/EffectEngine.h b/include/effectengine/EffectEngine.h index 7acb1eea..163869d6 100644 --- a/include/effectengine/EffectEngine.h +++ b/include/effectengine/EffectEngine.h @@ -12,6 +12,7 @@ // Effect engine includes #include #include +#include // pre-declarioation class Effect; @@ -57,8 +58,10 @@ private: std::list _availableEffects; std::list _activeEffects; - + std::list _availableActiveEffects; - PyThreadState * _mainThreadState; + PyThreadState * _mainThreadState; + + Logger * _log; }; diff --git a/include/leddevice/LedDevice.h b/include/leddevice/LedDevice.h index 64018f10..ad65d3ac 100644 --- a/include/leddevice/LedDevice.h +++ b/include/leddevice/LedDevice.h @@ -7,6 +7,7 @@ #include #include #include +#include /// /// Interface (pure virtual base class) for LedDevices. @@ -14,14 +15,11 @@ class LedDevice { public: - + LedDevice(); /// /// Empty virtual destructor for pure virtual base class /// - virtual ~LedDevice() - { - // empty - } + virtual ~LedDevice() {} /// /// Writes the RGB-Color values to the leds. @@ -34,4 +32,7 @@ public: /// Switch the leds off virtual int switchOff() = 0; + +protected: + Logger * _log; }; diff --git a/include/udplistener/UDPListener.h b/include/udplistener/UDPListener.h new file mode 100644 index 00000000..457b603b --- /dev/null +++ b/include/udplistener/UDPListener.h @@ -0,0 +1,93 @@ +#pragma once + +// system includes +#include + +// Qt includes +#include +#include +#include + +// Hyperion includes +#include +#include + +class UDPClientConnection; + +/// +/// This class creates a UDP server which accepts connections from boblight clients. +/// +class UDPListener : public QObject +{ + Q_OBJECT + +public: + /// + /// UDPListener constructor + /// @param hyperion Hyperion instance + /// @param port port number on which to start listening for connections + /// + UDPListener(const int priority, const int timeout, const std::string& address, quint16 listenPort, bool shared); + ~UDPListener(); + + /// + /// @return the port number on which this UDP listens for incoming connections + /// + uint16_t getPort() const; + + /// + /// @return true if server is active (bind to a port) + /// + bool active() { return _isActive; }; + +public slots: + /// + /// bind server to network + /// + void start(); + + /// + /// close server + /// + void stop(); + +signals: + void statusChanged(bool isActive); + +private slots: + /// + /// Slot which is called when a client tries to create a new connection + /// + void readPendingDatagrams(); + void processTheDatagram(const QByteArray * _datagram); + +private: + /// Hyperion instance + Hyperion * _hyperion; + + /// The UDP server object + QUdpSocket * _server; + + /// List with open connections + QSet _openConnections; + + /// hyperion priority + int _priority; + + /// hyperion priority + int _timeout; + + /// The latest led color data + std::vector _ledColors; + + /// Logger instance + Logger * _log; + + /// state of connection + bool _isActive; + + /// address to bind + QHostAddress _listenAddress; + quint16 _listenPort; + QAbstractSocket::BindFlag _bondage; +}; diff --git a/include/utils/Logger.h b/include/utils/Logger.h index 77413150..518bf148 100644 --- a/include/utils/Logger.h +++ b/include/utils/Logger.h @@ -25,9 +25,11 @@ class Logger { public: - enum LogLevel { DEBUG=0, INFO=1,WARNING=2,ERROR=3 }; + enum LogLevel { UNSET=0,DEBUG=1, INFO=2,WARNING=3,ERROR=4,OFF=5 }; static Logger* getInstance(std::string name="", LogLevel minLevel=Logger::INFO); + static void deleteInstance(std::string name=""); + static void setLogLevel(LogLevel level,std::string name=""); void Message(LogLevel level, const char* sourceFile, const char* func, unsigned int line, const char* fmt, ...); void setMinLevel(LogLevel level) { _minLevel = level; }; @@ -38,6 +40,7 @@ protected: private: static std::map *LoggerMap; + static LogLevel GLOBAL_MIN_LOG_LEVEL; std::string _name; std::string _appname; diff --git a/libsrc/CMakeLists.txt b/libsrc/CMakeLists.txt index 2d109c02..4a8da206 100644 --- a/libsrc/CMakeLists.txt +++ b/libsrc/CMakeLists.txt @@ -9,6 +9,7 @@ add_subdirectory(jsonserver) add_subdirectory(protoserver) add_subdirectory(bonjour) add_subdirectory(boblightserver) +add_subdirectory(udplistener) add_subdirectory(leddevice) add_subdirectory(utils) add_subdirectory(xbmcvideochecker) diff --git a/libsrc/boblightserver/BoblightServer.cpp b/libsrc/boblightserver/BoblightServer.cpp index 600a7d72..d06c2909 100644 --- a/libsrc/boblightserver/BoblightServer.cpp +++ b/libsrc/boblightserver/BoblightServer.cpp @@ -5,9 +5,9 @@ #include #include "BoblightClientConnection.h" -BoblightServer::BoblightServer(Hyperion *hyperion, const int priority,uint16_t port) : +BoblightServer::BoblightServer(const int priority,uint16_t port) : QObject(), - _hyperion(hyperion), + _hyperion(Hyperion::getInstance()), _server(), _openConnections(), _priority(priority) diff --git a/libsrc/boblightserver/CMakeLists.txt b/libsrc/boblightserver/CMakeLists.txt index 3bf97fb3..15c2b6e0 100644 --- a/libsrc/boblightserver/CMakeLists.txt +++ b/libsrc/boblightserver/CMakeLists.txt @@ -26,8 +26,6 @@ add_library(boblightserver ${BoblightServer_HEADERS_MOC} ) -qt5_use_modules(boblightserver Widgets) - target_link_libraries(boblightserver hyperion hyperion-utils diff --git a/libsrc/bonjour/CMakeLists.txt b/libsrc/bonjour/CMakeLists.txt index 48371507..52a251d7 100644 --- a/libsrc/bonjour/CMakeLists.txt +++ b/libsrc/bonjour/CMakeLists.txt @@ -5,7 +5,6 @@ set(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/bonjour) # Group the headers that go through the MOC compiler set(Bonjour_QT_HEADERS - ${CURRENT_HEADER_DIR}/bonjourrecord.h ${CURRENT_HEADER_DIR}/bonjourserviceregister.h ) @@ -31,14 +30,14 @@ add_library(bonjour ${Bonjour_RESOURCES_RCC} ) -qt5_use_modules(bonjour Widgets Network) +qt5_use_modules(bonjour Network) target_link_libraries(bonjour hyperion hyperion-utils ${QT_LIBRARIES}) -set(USE_SHARED_AVAHI_LIBS OFF CACHE BOOL "use avahi libraries from system") +set(USE_SHARED_AVAHI_LIBS ${DEFAULT_USE_SHARED_AVAHI_LIBS} CACHE BOOL "use avahi libraries from system") if (USE_SHARED_AVAHI_LIBS) target_link_libraries(bonjour diff --git a/libsrc/bonjour/main.cpp b/libsrc/bonjour/main.cpp deleted file mode 100755 index 3d8db515..00000000 --- a/libsrc/bonjour/main.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2004-2007 Trolltech ASA. All rights reserved. -** -** This file is part of the example classes of the Qt Toolkit. -** -** This file may be used under the terms of the GNU General Public -** License version 2.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of -** this file. Please review the following information to ensure GNU -** General Public Licensing requirements will be met: -** http://www.trolltech.com/products/qt/opensource.html -** -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://www.trolltech.com/products/qt/licensing.html or contact the -** sales department at sales@trolltech.com. -** -** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -** -****************************************************************************/ - -#include -#include - -#include - -#include "server.h" - -int main(int argc, char *argv[]) -{ - QApplication app(argc, argv); - Server server; - server.show(); - qsrand(QTime(0,0,0).secsTo(QTime::currentTime())); - int x = server.exec(); - return x; -} diff --git a/libsrc/bonjour/server.cpp b/libsrc/bonjour/server.cpp deleted file mode 100755 index 06768edf..00000000 --- a/libsrc/bonjour/server.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2004-2007 Trolltech ASA. All rights reserved. -** -** This file is part of the example classes of the Qt Toolkit. -** -** This file may be used under the terms of the GNU General Public -** License version 2.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of -** this file. Please review the following information to ensure GNU -** General Public Licensing requirements will be met: -** http://www.trolltech.com/products/qt/opensource.html -** -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://www.trolltech.com/products/qt/licensing.html or contact the -** sales department at sales@trolltech.com. -** -** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -** -****************************************************************************/ - -#include -#include - -#include - -#include "server.h" -#include "bonjourserviceregister.h" -Server::Server(QWidget *parent) - : QDialog(parent) -{ - setWindowModality(Qt::ApplicationModal); - statusLabel = new QLabel; - quitButton = new QPushButton(tr("Quit")); - quitButton->setAutoDefault(false); - - tcpServer = new QTcpServer(this); - if (!tcpServer->listen()) { - QMessageBox::critical(this, tr("Fortune Server"), - tr("Unable to start the server: %1.") - .arg(tcpServer->errorString())); - close(); - return; - } - - statusLabel->setText(tr("The server is running on port %1.\n" - "Run the Fortune Client example now.") - .arg(tcpServer->serverPort())); - - fortunes << tr("You've been leading a dog's life. Stay off the furniture.") - << tr("You've got to think about tomorrow.") - << tr("You will be surprised by a loud noise.") - << tr("You will feel hungry again in another hour.") - << tr("You might have mail.") - << tr("You cannot kill time without injuring eternity.") - << tr("Computers are not intelligent. They only think they are."); - - connect(quitButton, SIGNAL(clicked()), this, SLOT(close())); - connect(tcpServer, SIGNAL(newConnection()), this, SLOT(sendFortune())); - - QHBoxLayout *buttonLayout = new QHBoxLayout; - buttonLayout->addStretch(1); - buttonLayout->addWidget(quitButton); - buttonLayout->addStretch(1); - - QVBoxLayout *mainLayout = new QVBoxLayout; - mainLayout->addWidget(statusLabel); - mainLayout->addLayout(buttonLayout); - setLayout(mainLayout); - - bonjourRegister = new BonjourServiceRegister(this); - bonjourRegister->registerService(BonjourRecord(tr("Fortune Server on %1").arg(QHostInfo::localHostName()), - QLatin1String("_trollfortune._tcp"), QString()), - tcpServer->serverPort()); - setWindowTitle(tr("Fortune Server")); -} - -void Server::sendFortune() -{ - QByteArray block; - QDataStream out(&block, QIODevice::WriteOnly); - out.setVersion(QDataStream::Qt_4_0); - out << (quint16)0; - out << fortunes.at(qrand() % fortunes.size()); - out.device()->seek(0); - out << (quint16)(block.size() - sizeof(quint16)); - - QTcpSocket *clientConnection = tcpServer->nextPendingConnection(); - connect(clientConnection, SIGNAL(disconnected()), - clientConnection, SLOT(deleteLater())); - - clientConnection->write(block); - clientConnection->disconnectFromHost(); -} diff --git a/libsrc/bonjour/server.h b/libsrc/bonjour/server.h deleted file mode 100755 index 45852b11..00000000 --- a/libsrc/bonjour/server.h +++ /dev/null @@ -1,52 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2004-2007 Trolltech ASA. All rights reserved. -** -** This file is part of the example classes of the Qt Toolkit. -** -** This file may be used under the terms of the GNU General Public -** License version 2.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of -** this file. Please review the following information to ensure GNU -** General Public Licensing requirements will be met: -** http://www.trolltech.com/products/qt/opensource.html -** -** If you are unsure which license is appropriate for your use, please -** review the following information: -** http://www.trolltech.com/products/qt/licensing.html or contact the -** sales department at sales@trolltech.com. -** -** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -** -****************************************************************************/ - -#ifndef SERVER_H -#define SERVER_H - -#include - -class QLabel; -class QPushButton; -class QTcpServer; -class BonjourServiceRegister; - -class Server : public QDialog -{ - Q_OBJECT - -public: - Server(QWidget *parent = 0); - -private slots: - void sendFortune(); - -private: - QLabel *statusLabel; - QPushButton *quitButton; - QTcpServer *tcpServer; - QStringList fortunes; - BonjourServiceRegister *bonjourRegister; -}; - -#endif diff --git a/libsrc/effectengine/CMakeLists.txt b/libsrc/effectengine/CMakeLists.txt index 6d204203..c153bca8 100644 --- a/libsrc/effectengine/CMakeLists.txt +++ b/libsrc/effectengine/CMakeLists.txt @@ -39,8 +39,6 @@ add_library(effectengine ${EffectEngineSOURCES} ) -qt5_use_modules(effectengine Widgets) - target_link_libraries(effectengine hyperion jsoncpp diff --git a/libsrc/effectengine/Effect.cpp b/libsrc/effectengine/Effect.cpp index 7f5d3534..c2c25419 100644 --- a/libsrc/effectengine/Effect.cpp +++ b/libsrc/effectengine/Effect.cpp @@ -10,6 +10,7 @@ // effect engin eincludes #include "Effect.h" +#include // Python method table PyMethodDef Effect::effectMethods[] = { @@ -112,7 +113,7 @@ void Effect::run() } else { - std::cerr << "EFFECTENGINE ERROR: Unable to open script file " << _script << std::endl; + Error(Logger::getInstance("EFFECTENGINE"), "Unable to open script file %s", _script.c_str()); } fclose(file); @@ -356,7 +357,7 @@ Effect * Effect::getEffect() { // something is wrong Py_XDECREF(module); - std::cerr << "EFFECTENGINE ERROR: Unable to retrieve the effect object from the Python runtime" << std::endl; + Error(Logger::getInstance("EFFECTENGINE"), "Unable to retrieve the effect object from the Python runtime"); return nullptr; } @@ -368,7 +369,7 @@ Effect * Effect::getEffect() { // something is wrong Py_XDECREF(effectCapsule); - std::cerr << "EFFECTENGINE ERROR: Unable to retrieve the effect object from the Python runtime" << std::endl; + Error(Logger::getInstance("EFFECTENGINE"), "Unable to retrieve the effect object from the Python runtime"); return nullptr; } diff --git a/libsrc/effectengine/Effect.h b/libsrc/effectengine/Effect.h index 0ef49315..7d8e7703 100644 --- a/libsrc/effectengine/Effect.h +++ b/libsrc/effectengine/Effect.h @@ -83,3 +83,4 @@ private: /// Buffer for colorData std::vector _colors; }; + diff --git a/libsrc/effectengine/EffectEngine.cpp b/libsrc/effectengine/EffectEngine.cpp index 459fe239..2def554a 100644 --- a/libsrc/effectengine/EffectEngine.cpp +++ b/libsrc/effectengine/EffectEngine.cpp @@ -22,7 +22,8 @@ EffectEngine::EffectEngine(Hyperion * hyperion, const Json::Value & jsonEffectCo _hyperion(hyperion), _availableEffects(), _activeEffects(), - _mainThreadState(nullptr) + _mainThreadState(nullptr), + _log(Logger::getInstance("EFFECTENGINE")) { qRegisterMetaType>("std::vector"); @@ -49,17 +50,17 @@ EffectEngine::EffectEngine(Hyperion * hyperion, const Json::Value & jsonEffectCo efxCount++; } } - std::cerr << "EFFECTENGINE INFO: " << efxCount << " effects loaded from directory " << path << std::endl; + Info(_log, "%d effects loaded from directory %s", efxCount, path.c_str()); } } if (_availableEffects.size() == 0) { - std::cerr << "EFFECTENGINE ERROR: no effects found, check your effect directories" << std::endl; + Error(_log, "no effects found, check your effect directories"); } // initialize the python interpreter - std::cout << "EFFECTENGINE INFO: Initializing Python interpreter" << std::endl; + Debug(_log,"Initializing Python interpreter"); Effect::registerHyperionExtensionModule(); Py_InitializeEx(0); PyEval_InitThreads(); // Create the GIL @@ -69,7 +70,7 @@ EffectEngine::EffectEngine(Hyperion * hyperion, const Json::Value & jsonEffectCo EffectEngine::~EffectEngine() { // clean up the Python interpreter - std::cout << "EFFECTENGINE INFO: Cleaning up Python interpreter" << std::endl; + Debug(_log, "Cleaning up Python interpreter"); PyEval_RestoreThread(_mainThreadState); Py_Finalize(); } @@ -101,9 +102,10 @@ bool EffectEngine::loadEffectDefinition(const std::string &path, const std::stri std::string fileName = path + QDir::separator().toLatin1() + effectConfigFile; std::ifstream file(fileName.c_str()); + Logger * log = Logger::getInstance("EFFECTENGINE"); if (!file.is_open()) { - std::cerr << "EFFECTENGINE ERROR: Effect file '" << fileName << "' could not be loaded" << std::endl; + Error( log, "Effect file '%s' could not be loaded", fileName.c_str()); return false; } @@ -112,7 +114,7 @@ bool EffectEngine::loadEffectDefinition(const std::string &path, const std::stri Json::Value config; if (!jsonReader.parse(file, config, false)) { - std::cerr << "EFFECTENGINE ERROR: Error while reading effect '" << fileName << "': " << jsonReader.getFormattedErrorMessages() << std::endl; + Error( log, "Error while reading effect '%s': %s", fileName.c_str(), jsonReader.getFormattedErrorMessages().c_str()); return false; } @@ -126,7 +128,7 @@ bool EffectEngine::loadEffectDefinition(const std::string &path, const std::stri { const std::list & errors = schemaChecker.getMessages(); foreach (const std::string & error, errors) { - std::cerr << "EFFECTENGINE ERROR: Error while checking '" << fileName << "':" << error << std::endl; + Error( log, "Error while checking '%s':", fileName.c_str(), error.c_str()); } return false; } @@ -148,7 +150,7 @@ int EffectEngine::runEffect(const std::string &effectName, int priority, int tim int EffectEngine::runEffect(const std::string &effectName, const Json::Value &args, int priority, int timeout) { - std::cout << "EFFECTENGINE INFO: run effect " << effectName << " on channel " << priority << std::endl; + Info( _log, "run effect %s on channel %d", effectName.c_str(), priority); const EffectDefinition * effectDefinition = nullptr; for (const EffectDefinition & e : _availableEffects) @@ -162,7 +164,7 @@ int EffectEngine::runEffect(const std::string &effectName, const Json::Value &ar if (effectDefinition == nullptr) { // no such effect - std::cerr << "EFFECTENGINE ERROR: effect " << effectName << " not found" << std::endl; + Error(_log, "effect %s not found", effectName.c_str()); return -1; } @@ -213,7 +215,7 @@ void EffectEngine::effectFinished(Effect *effect) _hyperion->clear(effect->getPriority()); } - std::cout << "EFFECTENGINE INFO: effect finished" << std::endl; + Info( _log, "effect finished"); for (auto effectIt = _activeEffects.begin(); effectIt != _activeEffects.end(); ++effectIt) { if (*effectIt == effect) diff --git a/libsrc/grabber/v4l2/CMakeLists.txt b/libsrc/grabber/v4l2/CMakeLists.txt index 3db5667e..1539bd90 100644 --- a/libsrc/grabber/v4l2/CMakeLists.txt +++ b/libsrc/grabber/v4l2/CMakeLists.txt @@ -25,8 +25,6 @@ add_library(v4l2-grabber ${V4L2_HEADERS_MOC} ) -qt5_use_modules(v4l2-grabber Widgets) - target_link_libraries(v4l2-grabber hyperion ${QT_LIBRARIES} diff --git a/libsrc/grabber/x11/CMakeLists.txt b/libsrc/grabber/x11/CMakeLists.txt index 51eefceb..8e309860 100644 --- a/libsrc/grabber/x11/CMakeLists.txt +++ b/libsrc/grabber/x11/CMakeLists.txt @@ -10,10 +10,6 @@ include_directories( ${X11_INCLUDES} ) -SET(X11_QT_HEADERS - ${CURRENT_HEADER_DIR}/X11Grabber.h -) - SET(X11_HEADERS ${CURRENT_HEADER_DIR}/X11Grabber.h ) diff --git a/libsrc/hyperion/CMakeLists.txt b/libsrc/hyperion/CMakeLists.txt index 42c611b5..c41a54f3 100644 --- a/libsrc/hyperion/CMakeLists.txt +++ b/libsrc/hyperion/CMakeLists.txt @@ -53,13 +53,10 @@ add_library(hyperion ${Hyperion_RESOURCES_RCC} ) -qt5_use_modules(hyperion Widgets) - target_link_libraries(hyperion blackborder hyperion-utils leddevice effectengine - serialport ${QT_LIBRARIES} ) diff --git a/libsrc/jsonserver/CMakeLists.txt b/libsrc/jsonserver/CMakeLists.txt index 7888179b..f40baadb 100644 --- a/libsrc/jsonserver/CMakeLists.txt +++ b/libsrc/jsonserver/CMakeLists.txt @@ -33,7 +33,7 @@ add_library(jsonserver ${JsonServer_RESOURCES_RCC} ) -qt5_use_modules(jsonserver Widgets Network) +qt5_use_modules(jsonserver Network) target_link_libraries(jsonserver hyperion diff --git a/libsrc/jsonserver/JsonClientConnection.cpp b/libsrc/jsonserver/JsonClientConnection.cpp index 79a749ad..d9dced17 100644 --- a/libsrc/jsonserver/JsonClientConnection.cpp +++ b/libsrc/jsonserver/JsonClientConnection.cpp @@ -593,9 +593,11 @@ void JsonClientConnection::handleServerInfoCommand(const Json::Value &) } // Add Hyperion Version, build time - Json::Value & version = info["hyperion_build"] = Json::Value(Json::arrayValue); + Json::Value & version = info["hyperion"] = Json::Value(Json::arrayValue); Json::Value ver; - ver["version"] = HYPERION_VERSION_ID; + ver["jsonrpc_version"] = HYPERION_JSON_VERSION; + ver["version"] = HYPERION_VERSION; + ver["build"] = HYPERION_BUILD_ID; ver["time"] = __DATE__ " " __TIME__; version.append(ver); diff --git a/libsrc/leddevice/CMakeLists.txt b/libsrc/leddevice/CMakeLists.txt index c2148226..fa988195 100755 --- a/libsrc/leddevice/CMakeLists.txt +++ b/libsrc/leddevice/CMakeLists.txt @@ -5,7 +5,7 @@ SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/leddevice) #add libusb and pthreads (required for the Lighpack usb device) find_package(libusb-1.0 REQUIRED) -find_package(Threads REQUIRED) +#find_package(Threads REQUIRED) include_directories( ../../include/hidapi @@ -21,7 +21,6 @@ SET(Leddevice_QT_HEADERS ${CURRENT_SOURCE_DIR}/LedDevicePhilipsHue.h ${CURRENT_SOURCE_DIR}/LedHIDDevice.h ${CURRENT_SOURCE_DIR}/LedDeviceRawHID.h - ${CURRENT_SOURCE_DIR}/LedDeviceFile.h ${CURRENT_SOURCE_DIR}/LedDeviceFadeCandy.h ) @@ -45,6 +44,7 @@ SET(Leddevice_HEADERS ) SET(Leddevice_SOURCES + ${CURRENT_SOURCE_DIR}/LedDevice.cpp ${CURRENT_SOURCE_DIR}/LedDeviceFactory.cpp ${CURRENT_SOURCE_DIR}/LedRs232Device.cpp @@ -137,11 +137,11 @@ add_library(leddevice ${Leddevice_SOURCES} ) -qt5_use_modules(leddevice Widgets Network) +qt5_use_modules(leddevice Network SerialPort) target_link_libraries(leddevice hyperion-utils - serialport +# serialport ${LIBUSB_1_LIBRARIES} #apt-get install libusb-1.0-0-dev ${CMAKE_THREAD_LIBS_INIT} ${QT_LIBRARIES} diff --git a/libsrc/leddevice/LedDevice.cpp b/libsrc/leddevice/LedDevice.cpp new file mode 100644 index 00000000..0373b9f6 --- /dev/null +++ b/libsrc/leddevice/LedDevice.cpp @@ -0,0 +1,6 @@ +#include + +LedDevice::LedDevice() + : _log(Logger::getInstance("LedDevice")) +{ +} diff --git a/libsrc/leddevice/LedDeviceAPA102.cpp b/libsrc/leddevice/LedDeviceAPA102.cpp index e7dc7eb6..85b3bac8 100644 --- a/libsrc/leddevice/LedDeviceAPA102.cpp +++ b/libsrc/leddevice/LedDeviceAPA102.cpp @@ -27,9 +27,6 @@ int LedDeviceAPA102::write(const std::vector &ledValues) const unsigned int endFrameSize = std::max(((max_leds + 15) / 16), 4); const unsigned int APAbufferSize = (max_leds * 4) + startFrameSize + endFrameSize; -//printf ("_mLedCount %d _HW_ledcount %d max_leds %d APAbufferSize %d\n", -// _mLedCount, _HW_ledcount, max_leds, APAbufferSize); - if(_ledBuffer.size() != APAbufferSize){ _ledBuffer.resize(APAbufferSize, 0xFF); _ledBuffer[0] = 0x00; @@ -54,15 +51,6 @@ int LedDeviceAPA102::write(const std::vector &ledValues) _ledBuffer[4+iLed*4+3] = 0x00; } -/* -for (unsigned i=0; i< _ledBuffer.size(); i+=4) { - printf ("i %2d led %2d RGB 0x0%02x%02x%02x%02x\n",i, i/4-1, - _ledBuffer[i+0], - _ledBuffer[i+1], - _ledBuffer[i+2], - _ledBuffer[i+3]); -} -*/ return writeBytes(_ledBuffer.size(), _ledBuffer.data()); } diff --git a/libsrc/leddevice/LedDeviceAtmo.cpp b/libsrc/leddevice/LedDeviceAtmo.cpp index dbcb48bd..0f69725b 100644 --- a/libsrc/leddevice/LedDeviceAtmo.cpp +++ b/libsrc/leddevice/LedDeviceAtmo.cpp @@ -22,8 +22,8 @@ int LedDeviceAtmo::write(const std::vector &ledValues) // (19 bytes) for the hardware to recognize the data if (ledValues.size() != 5) { - std::cerr << "AtmoLight: " << ledValues.size() << " channels configured. This should always be 5!" << std::endl; - return 0; + Error( _log, "%d channels configured. This should always be 5!", ledValues.size()); + return 0; } // write data diff --git a/libsrc/leddevice/LedDeviceFactory.cpp b/libsrc/leddevice/LedDeviceFactory.cpp index d688c722..a2e39f87 100755 --- a/libsrc/leddevice/LedDeviceFactory.cpp +++ b/libsrc/leddevice/LedDeviceFactory.cpp @@ -1,5 +1,6 @@ // Stl includes #include +#include #include // Build configuration @@ -7,6 +8,7 @@ // Leddevice includes #include +#include // Local Leddevice includes #ifdef ENABLE_SPIDEV @@ -50,7 +52,10 @@ LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig) { - std::cout << "LEDDEVICE INFO: configuration: " << deviceConfig << std::endl; + Logger * log = Logger::getInstance("LedDevice"); + std::stringstream ss; + ss << deviceConfig; + Info(log, "configuration: %s ", ss.str().c_str()); std::string type = deviceConfig.get("type", "UNSPECIFIED").asString(); std::transform(type.begin(), type.end(), type.begin(), ::tolower); @@ -287,11 +292,6 @@ LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig) device = new LedDeviceAtmoOrb(output, useOrbSmoothing, transitiontime, skipSmoothingDiff, port, numLeds, orbIds); } - else if (type == "file") - { - const std::string output = deviceConfig.get("output", "/dev/null").asString(); - device = new LedDeviceFile(output); - } else if (type == "fadecandy") { const std::string host = deviceConfig.get("output", "127.0.0.1").asString(); @@ -361,9 +361,13 @@ LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig) #endif else { - std::cout << "LEDDEVICE ERROR: Unknown/Unimplemented device " << type << std::endl; - // Unknown / Unimplemented device - exit(1); + if (type != "file") + { + Error(log, "Dummy device used, because unknown device %s set.", type.c_str()); + } + const std::string output = deviceConfig.get("output", "/dev/null").asString(); + device = new LedDeviceFile(output); } + return device; } diff --git a/libsrc/leddevice/LedDeviceFadeCandy.cpp b/libsrc/leddevice/LedDeviceFadeCandy.cpp index 2e6a1411..183e97b8 100644 --- a/libsrc/leddevice/LedDeviceFadeCandy.cpp +++ b/libsrc/leddevice/LedDeviceFadeCandy.cpp @@ -33,7 +33,7 @@ bool LedDeviceFadeCandy::tryConnect() if ( _client.state() == QAbstractSocket::UnconnectedState ) { _client.connectToHost( _host.c_str(), _port); if ( _client.waitForConnected(1000) ) - qDebug("fadecandy/opc: connected to %s:%i on channel %i", _host.c_str(), _port, _channel); + Info(_log,"fadecandy/opc: connected to %s:%i on channel %i", _host.c_str(), _port, _channel); } return isConnected(); @@ -48,7 +48,7 @@ int LedDeviceFadeCandy::write( const std::vector & ledValues ) if (nrLedValues > MAX_NUM_LEDS) { - std::cerr << "fadecandy/opc: Invalid attempt to write led values. Not more than " << MAX_NUM_LEDS << " leds are allowed." << std::endl; + Error(_log, "fadecandy/opc: Invalid attempt to write led values. Not more than %d leds are allowed.", MAX_NUM_LEDS); return -1; } diff --git a/libsrc/leddevice/LedDeviceHyperionUsbasp.cpp b/libsrc/leddevice/LedDeviceHyperionUsbasp.cpp index 9eddde90..2027de0c 100644 --- a/libsrc/leddevice/LedDeviceHyperionUsbasp.cpp +++ b/libsrc/leddevice/LedDeviceHyperionUsbasp.cpp @@ -45,12 +45,12 @@ int LedDeviceHyperionUsbasp::open() // initialize the usb context if ((error = libusb_init(&_libusbContext)) != LIBUSB_SUCCESS) { - std::cerr << "Error while initializing USB context(" << error << "): " << libusb_error_name(error) << std::endl; + Error(_log, "Error while initializing USB context(%s):%s", error, libusb_error_name(error)); _libusbContext = nullptr; return -1; } //libusb_set_debug(_libusbContext, 3); - std::cout << "USB context initialized" << std::endl; + Debug(_log, "USB context initialized"); // retrieve the list of usb devices libusb_device ** deviceList; @@ -74,7 +74,7 @@ int LedDeviceHyperionUsbasp::open() if (_deviceHandle == nullptr) { - std::cerr << "No " << _usbProductDescription << " has been found" << std::endl; + Error(_log, "No %s has been found", _usbProductDescription.c_str()); } return _deviceHandle == nullptr ? -1 : 0; @@ -86,7 +86,7 @@ int LedDeviceHyperionUsbasp::testAndOpen(libusb_device * device) int error = libusb_get_device_descriptor(device, &deviceDescriptor); if (error != LIBUSB_SUCCESS) { - std::cerr << "Error while retrieving device descriptor(" << error << "): " << libusb_error_name(error) << std::endl; + Error(_log, "Error while retrieving device descriptor(%s): %s", error, libusb_error_name(error)); return -1; } @@ -99,18 +99,18 @@ int LedDeviceHyperionUsbasp::testAndOpen(libusb_device * device) int busNumber = libusb_get_bus_number(device); int addressNumber = libusb_get_device_address(device); - std::cout << _usbProductDescription << " found: bus=" << busNumber << " address=" << addressNumber << std::endl; + Info(_log, "%s found: bus=%s address=%s", _usbProductDescription.c_str(), busNumber, addressNumber); try { _deviceHandle = openDevice(device); - std::cout << _usbProductDescription << " successfully opened" << std::endl; + Info(_log, "%s successfully opened", _usbProductDescription.c_str() ); return 0; } catch(int e) { _deviceHandle = nullptr; - std::cerr << "Unable to open " << _usbProductDescription << ". Searching for other device(" << e << "): " << libusb_error_name(e) << std::endl; + Error(_log, "Unable to open %s. Searching for other device(%s): %s", _usbProductDescription.c_str(), e, libusb_error_name(e)); } } @@ -134,7 +134,7 @@ int LedDeviceHyperionUsbasp::write(const std::vector &ledValues) // Disabling interupts for a little while on the device results in a PIPE error. All seems to keep functioning though... if(nbytes < 0 && nbytes != LIBUSB_ERROR_PIPE) { - std::cerr << "Error while writing data to " << _usbProductDescription << " (" << libusb_error_name(nbytes) << ")" << std::endl; + Error(_log, "Error while writing data to %s (%s)", _usbProductDescription.c_str(), libusb_error_name(nbytes)); return -1; } @@ -149,12 +149,13 @@ int LedDeviceHyperionUsbasp::switchOff() libusb_device_handle * LedDeviceHyperionUsbasp::openDevice(libusb_device *device) { + Logger * log = Logger::getInstance("LedDevice"); libusb_device_handle * handle = nullptr; int error = libusb_open(device, &handle); if (error != LIBUSB_SUCCESS) { - std::cerr << "unable to open device(" << error << "): " << libusb_error_name(error) << std::endl; + Error(log, "unable to open device(%s): %s",error,libusb_error_name(error)); throw error; } @@ -164,7 +165,7 @@ libusb_device_handle * LedDeviceHyperionUsbasp::openDevice(libusb_device *device error = libusb_detach_kernel_driver(handle, 0); if (error != LIBUSB_SUCCESS) { - std::cerr << "unable to detach kernel driver(" << error << "): " << libusb_error_name(error) << std::endl; + Error(log, "unable to detach kernel driver(%s): %s",error,libusb_error_name(error)); libusb_close(handle); throw error; } @@ -173,7 +174,7 @@ libusb_device_handle * LedDeviceHyperionUsbasp::openDevice(libusb_device *device error = libusb_claim_interface(handle, 0); if (error != LIBUSB_SUCCESS) { - std::cerr << "unable to claim interface(" << error << "): " << libusb_error_name(error) << std::endl; + Error(log, "unable to claim interface(%s): %s", error, libusb_error_name(error)); libusb_attach_kernel_driver(handle, 0); libusb_close(handle); throw error; diff --git a/libsrc/leddevice/LedDeviceLightpack-hidapi.cpp b/libsrc/leddevice/LedDeviceLightpack-hidapi.cpp index e23f7148..b53e64a8 100644 --- a/libsrc/leddevice/LedDeviceLightpack-hidapi.cpp +++ b/libsrc/leddevice/LedDeviceLightpack-hidapi.cpp @@ -62,10 +62,10 @@ int LedDeviceLightpackHidapi::open(const std::string & serialNumber) int error = hid_init(); if (error != 0) { - std::cerr << "Error while initializing the hidapi context" << std::endl; + Error(_log, "Error while initializing the hidapi context"); return -1; } - std::cout << "Hidapi initialized" << std::endl; + Info("Hidapi initialized"); // retrieve the list of usb devices hid_device_info * deviceList = hid_enumerate(0x0, 0x0); @@ -90,11 +90,11 @@ int LedDeviceLightpackHidapi::open(const std::string & serialNumber) { if (_serialNumber.empty()) { - std::cerr << "No Lightpack device has been found" << std::endl; + Error(_log, "No Lightpack device has been found"); } else { - std::cerr << "No Lightpack device has been found with serial " << _serialNumber << std::endl; + Error(_log, "No Lightpack device has been found with serial %s", _serialNumber); } } @@ -106,7 +106,7 @@ int LedDeviceLightpackHidapi::testAndOpen(hid_device_info *device, const std::st if ((device->vendor_id == USB_VENDOR_ID && device->product_id == USB_PRODUCT_ID) || (device->vendor_id == USB_OLD_VENDOR_ID && device->product_id == USB_OLD_PRODUCT_ID)) { - std::cout << "Found a lightpack device. Retrieving more information..." << std::endl; + Debug(_log, "Found a lightpack device. Retrieving more information..."); // get the serial number std::string serialNumber = ""; @@ -126,10 +126,10 @@ int LedDeviceLightpackHidapi::testAndOpen(hid_device_info *device, const std::st } else { - std::cerr << "No serial number for Lightpack device" << std::endl; + Error(_log, "No serial number for Lightpack device"); } - std::cout << "Lightpack device found: path=" << device->path << " serial=" << serialNumber << std::endl; + Debug(_log, "Lightpack device found: path=%s serial=%s", device->path.c_str(), serialNumber.c_str()); // check if this is the device we are looking for if (requestedSerialNumber.empty() || requestedSerialNumber == serialNumber) @@ -141,7 +141,7 @@ int LedDeviceLightpackHidapi::testAndOpen(hid_device_info *device, const std::st { _serialNumber = serialNumber; - std::cout << "Lightpack device successfully opened" << std::endl; + Info(_log, "Lightpack device successfully opened"); // get the firmware version uint8_t buffer[256]; @@ -149,7 +149,7 @@ int LedDeviceLightpackHidapi::testAndOpen(hid_device_info *device, const std::st int error = hid_get_feature_report(_deviceHandle, buffer, sizeof(buffer)); if (error < 4) { - std::cerr << "Unable to retrieve firmware version number from Lightpack device" << std::endl; + Error(_log, "Unable to retrieve firmware version number from Lightpack device"); } else { @@ -190,12 +190,12 @@ int LedDeviceLightpackHidapi::testAndOpen(hid_device_info *device, const std::st _ledBuffer[1] = CMD_UPDATE_LEDS; // return success - std::cout << "Lightpack device opened: path=" << device->path << " serial=" << _serialNumber << " version=" << _firmwareVersion.majorVersion << "." << _firmwareVersion.minorVersion << std::endl; + Debug(_log,"Lightpack device opened: path=%s serial=%s version=%s.%s.%s", device->path.c_str(), _serialNumber.c_str(), _firmwareVersion.majorVersion.c_str(), _firmwareVersion.minorVersion.c_str()); return 0; } else { - std::cerr << "Unable to open Lightpack device. Searching for other device" << std::endl; + Warning(_log, "Unable to open Lightpack device. Searching for other device"); } } } @@ -259,7 +259,7 @@ int LedDeviceLightpackHidapi::writeBytes(uint8_t *data, int size) return 0; } - std::cerr << "Unable to write " << size << " bytes to Lightpack device(" << error << ")" << std::endl; + Error(_log, "Unable to write %s bytes to Lightpack device(%s)", size, error); return error; } diff --git a/libsrc/leddevice/LedDeviceLightpack.cpp b/libsrc/leddevice/LedDeviceLightpack.cpp index 0deac582..70762ae3 100644 --- a/libsrc/leddevice/LedDeviceLightpack.cpp +++ b/libsrc/leddevice/LedDeviceLightpack.cpp @@ -71,12 +71,12 @@ int LedDeviceLightpack::open(const std::string & serialNumber) // initialize the usb context if ((error = libusb_init(&_libusbContext)) != LIBUSB_SUCCESS) { - std::cerr << "Error while initializing USB context(" << error << "): " << libusb_error_name(error) << std::endl; + Error(_log, "Error while initializing USB context(%s): %s", error, libusb_error_name(error)); _libusbContext = nullptr; return -1; } //libusb_set_debug(_libusbContext, 3); - std::cout << "USB context initialized" << std::endl; + Debug(_log, "USB context initialized"); // retrieve the list of usb devices libusb_device ** deviceList; @@ -102,11 +102,11 @@ int LedDeviceLightpack::open(const std::string & serialNumber) { if (_serialNumber.empty()) { - std::cerr << "No Lightpack device has been found" << std::endl; + Warning(_log, "No Lightpack device has been found"); } else { - std::cerr << "No Lightpack device has been found with serial " << _serialNumber << std::endl; + Error(_log,"No Lightpack device has been found with serial %s", _serialNumber.c_str()); } } @@ -119,14 +119,14 @@ int LedDeviceLightpack::testAndOpen(libusb_device * device, const std::string & int error = libusb_get_device_descriptor(device, &deviceDescriptor); if (error != LIBUSB_SUCCESS) { - std::cerr << "Error while retrieving device descriptor(" << error << "): " << libusb_error_name(error) << std::endl; + Error(_log, "Error while retrieving device descriptor(%s): %s", error, libusb_error_name(error)); return -1; } if ((deviceDescriptor.idVendor == USB_VENDOR_ID && deviceDescriptor.idProduct == USB_PRODUCT_ID) || (deviceDescriptor.idVendor == USB_OLD_VENDOR_ID && deviceDescriptor.idProduct == USB_OLD_PRODUCT_ID)) { - std::cout << "Found a lightpack device. Retrieving more information..." << std::endl; + Info(_log, "Found a lightpack device. Retrieving more information..."); // get the hardware address int busNumber = libusb_get_bus_number(device); @@ -142,12 +142,12 @@ int LedDeviceLightpack::testAndOpen(libusb_device * device, const std::string & } catch (int e) { - std::cerr << "unable to retrieve serial number from Lightpack device(" << e << "): " << libusb_error_name(e) << std::endl; + Error(_log, "unable to retrieve serial number from Lightpack device(%s): %s", e, libusb_error_name(e)); serialNumber = ""; } } - std::cout << "Lightpack device found: bus=" << busNumber << " address=" << addressNumber << " serial=" << serialNumber << std::endl; + Debug(_log,"Lightpack device found: bus=%d address=%d serial=%s", busNumber, addressNumber, serialNumber.c_str()); // check if this is the device we are looking for if (requestedSerialNumber.empty() || requestedSerialNumber == serialNumber) @@ -160,7 +160,7 @@ int LedDeviceLightpack::testAndOpen(libusb_device * device, const std::string & _busNumber = busNumber; _addressNumber = addressNumber; - std::cout << "Lightpack device successfully opened" << std::endl; + Info(_log, "Lightpack device successfully opened"); // get the firmware version uint8_t buffer[256]; @@ -173,7 +173,7 @@ int LedDeviceLightpack::testAndOpen(libusb_device * device, const std::string & buffer, sizeof(buffer), 1000); if (error < 3) { - std::cerr << "Unable to retrieve firmware version number from Lightpack device(" << error << "): " << libusb_error_name(error) << std::endl; + Error(_log, "Unable to retrieve firmware version number from Lightpack device(%s): %s", error, libusb_error_name(error)); } else { @@ -213,13 +213,13 @@ int LedDeviceLightpack::testAndOpen(libusb_device * device, const std::string & _ledBuffer[0] = CMD_UPDATE_LEDS; // return success - std::cout << "Lightpack device opened: bus=" << _busNumber << " address=" << _addressNumber << " serial=" << _serialNumber << " version=" << _firmwareVersion.majorVersion << "." << _firmwareVersion.minorVersion << std::endl; + Debug(_log, "Lightpack device opened: bus=%d address=%d serial=%s version=%s.%s.", _busNumber, _addressNumber, _serialNumber.c_str(), _firmwareVersion.majorVersion, _firmwareVersion.minorVersion ); return 0; } catch(int e) { _deviceHandle = nullptr; - std::cerr << "Unable to open Lightpack device. Searching for other device(" << e << "): " << libusb_error_name(e) << std::endl; + Warning(_log, "Unable to open Lightpack device. Searching for other device(%s): %s", e, libusb_error_name(e)); } } } @@ -289,7 +289,7 @@ int LedDeviceLightpack::writeBytes(uint8_t *data, int size) return 0; } - std::cerr << "Unable to write " << size << " bytes to Lightpack device(" << error << "): " << libusb_error_name(error) << std::endl; + Error(_log, "Unable to write %d bytes to Lightpack device(%s): %s", size, error, libusb_error_name(error)); return error; } @@ -302,11 +302,11 @@ int LedDeviceLightpack::disableSmoothing() libusb_device_handle * LedDeviceLightpack::openDevice(libusb_device *device) { libusb_device_handle * handle = nullptr; - + Logger * log = Logger::getInstance("LedDevice"); int error = libusb_open(device, &handle); if (error != LIBUSB_SUCCESS) { - std::cerr << "unable to open device(" << error << "): " << libusb_error_name(error) << std::endl; + Error(log, "unable to open device(%s): %s", error, libusb_error_name(error)); throw error; } @@ -316,7 +316,7 @@ libusb_device_handle * LedDeviceLightpack::openDevice(libusb_device *device) error = libusb_detach_kernel_driver(handle, LIGHTPACK_INTERFACE); if (error != LIBUSB_SUCCESS) { - std::cerr << "unable to detach kernel driver(" << error << "): " << libusb_error_name(error) << std::endl; + Error(log, "unable to detach kernel driver(%s): %s", error, libusb_error_name(error)); libusb_close(handle); throw error; } @@ -325,7 +325,7 @@ libusb_device_handle * LedDeviceLightpack::openDevice(libusb_device *device) error = libusb_claim_interface(handle, LIGHTPACK_INTERFACE); if (error != LIBUSB_SUCCESS) { - std::cerr << "unable to claim interface(" << error << "): " << libusb_error_name(error) << std::endl; + Error(log, "unable to claim interface(%s): %s", error, libusb_error_name(error)); libusb_attach_kernel_driver(handle, LIGHTPACK_INTERFACE); libusb_close(handle); throw error; diff --git a/libsrc/leddevice/LedDeviceMultiLightpack.cpp b/libsrc/leddevice/LedDeviceMultiLightpack.cpp index d6acc253..9a9fcbf4 100644 --- a/libsrc/leddevice/LedDeviceMultiLightpack.cpp +++ b/libsrc/leddevice/LedDeviceMultiLightpack.cpp @@ -42,7 +42,7 @@ int LedDeviceMultiLightpack::open() // open each lightpack device for (const std::string & serial : serialList) { - LedDeviceLightpack * device = new LedDeviceLightpack(); + LedDeviceLightpack * device = new LedDeviceLightpack(); int error = device->open(serial); if (error == 0) @@ -51,18 +51,18 @@ int LedDeviceMultiLightpack::open() } else { - std::cerr << "Error while creating Lightpack device with serial " << serial << std::endl; + Error(_log, "Error while creating Lightpack device with serial %s", serial.c_str()); delete device; } } if (_lightpacks.size() == 0) { - std::cerr << "No Lightpack devices were found" << std::endl; + Warning(_log, "No Lightpack devices were found"); } else { - std::cout << _lightpacks.size() << " Lightpack devices were found" << std::endl; + Info(_log, "%d Lightpack devices were found", _lightpacks.size()); } return _lightpacks.size() > 0 ? 0 : -1; @@ -86,7 +86,7 @@ int LedDeviceMultiLightpack::write(const std::vector &ledValues) } else { - std::cout << "Unable to write data to Lightpack device: no more led data available" << std::endl; + Warning(_log, "Unable to write data to Lightpack device: no more led data available"); } } @@ -106,20 +106,20 @@ int LedDeviceMultiLightpack::switchOff() std::list LedDeviceMultiLightpack::getLightpackSerials() { std::list serialList; - - std::cout << "Getting list of Lightpack serials" << std::endl; + Logger * log = Logger::getInstance("LedDevice"); + Debug(log, "Getting list of Lightpack serials"); // initialize the usb context libusb_context * libusbContext; int error = libusb_init(&libusbContext); if (error != LIBUSB_SUCCESS) { - std::cerr << "Error while initializing USB context(" << error << "): " << libusb_error_name(error) << std::endl; + Error(log,"Error while initializing USB context(%s): %s", error, libusb_error_name(error)); libusbContext = nullptr; return serialList; } //libusb_set_debug(_libusbContext, 3); - std::cout << "USB context initialized in multi Lightpack device" << std::endl; + Info(log, "USB context initialized in multi Lightpack device"); // retrieve the list of usb devices libusb_device ** deviceList; @@ -132,14 +132,14 @@ std::list LedDeviceMultiLightpack::getLightpackSerials() error = libusb_get_device_descriptor(deviceList[i], &deviceDescriptor); if (error != LIBUSB_SUCCESS) { - std::cerr << "Error while retrieving device descriptor(" << error << "): " << libusb_error_name(error) << std::endl; + Error(log, "Error while retrieving device descriptor(%s): %s", error, libusb_error_name(error)); continue; } if ((deviceDescriptor.idVendor == USB_VENDOR_ID && deviceDescriptor.idProduct == USB_PRODUCT_ID) || (deviceDescriptor.idVendor == USB_OLD_VENDOR_ID && deviceDescriptor.idProduct == USB_OLD_PRODUCT_ID)) { - std::cout << "Found a lightpack device. Retrieving serial..." << std::endl; + Info(log, "Found a lightpack device. Retrieving serial..."); // get the serial number std::string serialNumber; @@ -151,12 +151,12 @@ std::list LedDeviceMultiLightpack::getLightpackSerials() } catch (int e) { - std::cerr << "Unable to retrieve serial number(" << e << "): " << libusb_error_name(e) << std::endl; + Error(log,"Unable to retrieve serial number(%s): %s", e, libusb_error_name(e)); continue; } } - std::cout << "Lightpack device found with serial " << serialNumber << std::endl; + Error(log, "Lightpack device found with serial %s", serialNumber.c_str());; serialList.push_back(serialNumber); } } diff --git a/libsrc/leddevice/LedDevicePhilipsHue.cpp b/libsrc/leddevice/LedDevicePhilipsHue.cpp index fe9e359d..b0c46981 100755 --- a/libsrc/leddevice/LedDevicePhilipsHue.cpp +++ b/libsrc/leddevice/LedDevicePhilipsHue.cpp @@ -278,8 +278,7 @@ void LedDevicePhilipsHue::saveStates(unsigned int nLights) { for (Json::ValueIterator it = json.begin(); it != json.end() && lightIds.size() < nLights; it++) { int lightId = atoi(it.key().asCString()); lightIds.push_back(lightId); - std::cout << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): found light with id " << lightId - << "." << std::endl; + Debug(_log, "nLights=%d: found light with id %d.", nLights, lightId); } // Check if we found enough lights. if (lightIds.size() != nLights) { @@ -294,20 +293,17 @@ void LedDevicePhilipsHue::saveStates(unsigned int nLights) { Json::Value json; if (!reader.parse(QString(response).toStdString(), json)) { // Error occured, break loop. - std::cerr << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): got invalid response from light " - << getUrl(getRoute(lightIds.at(i))).toStdString() << "." << std::endl; + Error(_log, "saveStates(nLights=%d): got invalid response from light %s.", nLights, getUrl(getRoute(lightIds.at(i))).toStdString().c_str()); break; } // Get state object values which are subject to change. Json::Value state(Json::objectValue); if (!json.isMember("state")) { - std::cerr << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): got no state for light from " - << getUrl(getRoute(lightIds.at(i))).toStdString() << std::endl; + Error(_log, "saveStates(nLights=%d): got no state for light from %s", nLights, getUrl(getRoute(lightIds.at(i))).toStdString().c_str()); break; } if (!json["state"].isMember("on")) { - std::cerr << "LedDevicePhilipsHue::saveStates(nLights=" << nLights << "): got no valid state from light " - << getUrl(getRoute(lightIds.at(i))).toStdString() << std::endl; + Error(_log, "saveStates(nLights=%d,): got no valid state from light %s", nLights, getUrl(getRoute(lightIds.at(i))).toStdString().c_str()); break; } state["on"] = json["state"]["on"]; diff --git a/libsrc/leddevice/LedDevicePiBlaster.cpp b/libsrc/leddevice/LedDevicePiBlaster.cpp index ced94ed4..b1bc4994 100644 --- a/libsrc/leddevice/LedDevicePiBlaster.cpp +++ b/libsrc/leddevice/LedDevicePiBlaster.cpp @@ -39,13 +39,13 @@ LedDevicePiBlaster::LedDevicePiBlaster(const std::string & deviceName, const Jso const int gpio = gpioMap.get("gpio",-1).asInt(); const int ledindex = gpioMap.get("ledindex",-1).asInt(); const std::string ledcolor = gpioMap.get("ledcolor","z").asString(); -// printf ("got gpio %d ledindex %d color %c\n", gpio,ledindex, ledcolor[0]); + // ignore missing/invalid settings if ( (gpio >= 0) && (gpio < signed(TABLE_SZ)) && (ledindex >= 0) ){ _gpio_to_led[gpio] = ledindex; _gpio_to_color[gpio] = ledcolor[0]; // 1st char of string } else { - printf ("IGNORING gpio %d ledindex %d color %c\n", gpio,ledindex, ledcolor[0]); + Warning( _log, "IGNORING gpio %d ledindex %d color %c", gpio,ledindex, ledcolor[0]); } } } @@ -67,7 +67,7 @@ int LedDevicePiBlaster::open(bool report) // The file pointer is already open if (report) { - std::cerr << "Attempt to open allready opened device (" << _deviceName << ")" << std::endl; + Error( _log, "Device (%s) is already open.", _deviceName.c_str() ); } return -1; } @@ -76,7 +76,7 @@ int LedDevicePiBlaster::open(bool report) { if (report) { - std::cerr << "The device(" << _deviceName << ") does not yet exist, can not connect (yet)." << std::endl; + Error( _log, "The device (%s) does not yet exist.", _deviceName.c_str() ); } return -1; } @@ -86,12 +86,12 @@ int LedDevicePiBlaster::open(bool report) { if (report) { - std::cerr << "Failed to open device (" << _deviceName << "). Error message: " << strerror(errno) << std::endl; + Error( _log, "Failed to open device (%s). Error message: %s", _deviceName.c_str(), strerror(errno) ); } return -1; } - std::cout << "Connect to device(" << _deviceName << ")" << std::endl; + Info( _log, "Connected to device(%s)", _deviceName.c_str()); return 0; } @@ -111,7 +111,6 @@ int LedDevicePiBlaster::write(const std::vector & ledValues) if ( (valueIdx >= 0) && (valueIdx < (signed) ledValues.size()) ) { double pwmDutyCycle = 0.0; -// printf ("iPin %d valueIdx %d color %c\n", iPin, valueIdx, _gpio_to_color[ iPins[iPin] ] ) ; switch (_gpio_to_color[ i ]) { case 'r': diff --git a/libsrc/leddevice/LedDevicePiBlaster.h b/libsrc/leddevice/LedDevicePiBlaster.h index 531372a6..ea9a9cdf 100644 --- a/libsrc/leddevice/LedDevicePiBlaster.h +++ b/libsrc/leddevice/LedDevicePiBlaster.h @@ -58,4 +58,5 @@ private: /// File-Pointer to the PiBlaster device FILE * _fid; + }; diff --git a/libsrc/leddevice/LedDeviceSedu.cpp b/libsrc/leddevice/LedDeviceSedu.cpp index c81eb2c4..4c92ac43 100644 --- a/libsrc/leddevice/LedDeviceSedu.cpp +++ b/libsrc/leddevice/LedDeviceSedu.cpp @@ -47,7 +47,7 @@ int LedDeviceSedu::write(const std::vector &ledValues) if (_ledBuffer.size() == 0) { - std::cout << "More rgb-channels required then available" << std::endl; + Warning(_log, "More rgb-channels required then available"); return -1; } } diff --git a/libsrc/leddevice/LedDeviceTinkerforge.cpp b/libsrc/leddevice/LedDeviceTinkerforge.cpp index 83367042..9bfa0778 100644 --- a/libsrc/leddevice/LedDeviceTinkerforge.cpp +++ b/libsrc/leddevice/LedDeviceTinkerforge.cpp @@ -40,7 +40,7 @@ int LedDeviceTinkerforge::open() // Check if connection is already createds if (_ipConnection != nullptr) { - std::cout << "Attempt to open existing connection; close before opening" << std::endl; + Error(_log, "Attempt to open existing connection; close before opening"); return -1; } @@ -51,7 +51,7 @@ int LedDeviceTinkerforge::open() int connectionStatus = ipcon_connect(_ipConnection, _host.c_str(), _port); if (connectionStatus < 0) { - std::cerr << "Attempt to connect to master brick (" << _host << ":" << _port << ") failed with status " << connectionStatus << std::endl; + Warning(_log, "Attempt to connect to master brick (%s:%d) failed with status %d", _host.c_str(), _port, connectionStatus); return -1; } @@ -62,7 +62,7 @@ int LedDeviceTinkerforge::open() int frameStatus = led_strip_set_frame_duration(_ledStrip, _interval); if (frameStatus < 0) { - std::cerr << "Attempt to connect to led strip bricklet (led_strip_set_frame_duration()) failed with status " << frameStatus << std::endl; + Error(_log,"Attempt to connect to led strip bricklet (led_strip_set_frame_duration()) failed with status %d", frameStatus); return -1; } @@ -75,7 +75,7 @@ int LedDeviceTinkerforge::write(const std::vector &ledValues) if (nrLedValues > MAX_NUM_LEDS) { - std::cerr << "Invalid attempt to write led values. Not more than " << MAX_NUM_LEDS << " leds are allowed." << std::endl; + Error(_log,"Invalid attempt to write led values. Not more than %d leds are allowed.", MAX_NUM_LEDS); return -1; } @@ -134,7 +134,7 @@ int LedDeviceTinkerforge::transferLedData(LEDStrip *ledStrip, unsigned index, un const int status = led_strip_set_rgb_values(ledStrip, i, copyLength, reds, greens, blues); if (status != E_OK) { - std::cerr << "Setting led values failed with status " << status << std::endl; + Warning(_log, "Setting led values failed with status %d", status); return status; } } diff --git a/libsrc/leddevice/LedDeviceUdp.cpp b/libsrc/leddevice/LedDeviceUdp.cpp index 71078ed0..42a858ce 100644 --- a/libsrc/leddevice/LedDeviceUdp.cpp +++ b/libsrc/leddevice/LedDeviceUdp.cpp @@ -54,7 +54,7 @@ LedDeviceUdp::LedDeviceUdp(const std::string& output, const unsigned baudrate, c hints.ai_socktype = SOCK_DGRAM; if ((rv = getaddrinfo(hostname.c_str() , port.c_str(), &hints, &servinfo)) != 0) { - fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); + Debug(_log, "getaddrinfo: %s", gai_strerror(rv)); assert(rv==0); } @@ -70,7 +70,7 @@ LedDeviceUdp::LedDeviceUdp(const std::string& output, const unsigned baudrate, c } if (p == NULL) { - fprintf(stderr, "talker: failed to create socket\n"); + Error(_log,"talker: failed to create socket"); assert(p!=NULL); } } diff --git a/libsrc/leddevice/LedDeviceWS281x.cpp b/libsrc/leddevice/LedDeviceWS281x.cpp index 8349c70b..600a0cca 100644 --- a/libsrc/leddevice/LedDeviceWS281x.cpp +++ b/libsrc/leddevice/LedDeviceWS281x.cpp @@ -6,13 +6,13 @@ LedDeviceWS281x::LedDeviceWS281x(const int gpio, const int leds, const uint32_t freq, const int dmanum, const int pwmchannel, const int invert, const int rgbw, const std::string& whiteAlgorithm) { _whiteAlgorithm = whiteAlgorithm; -std::cout << "whiteAlgorithm :" << whiteAlgorithm << ":\n"; + Debug( _log, "whiteAlgorithm : %s", whiteAlgorithm.c_str()); initialized = false; led_string.freq = freq; led_string.dmanum = dmanum; if (pwmchannel != 0 && pwmchannel != 1) { - std::cout << "WS281x: invalid PWM channel; must be 0 or 1." << std::endl; + Error( _log, "WS281x: invalid PWM channel; must be 0 or 1."); throw -1; } chan = pwmchannel; @@ -32,7 +32,7 @@ std::cout << "whiteAlgorithm :" << whiteAlgorithm << ":\n"; led_string.channel[!chan].brightness = 0; led_string.channel[!chan].strip_type = WS2811_STRIP_RGB; if (ws2811_init(&led_string) < 0) { - std::cout << "Unable to initialize ws281x library." << std::endl; + Error( _log, "Unable to initialize ws281x library."); throw -1; } initialized = true; @@ -95,7 +95,6 @@ LedDeviceWS281x::~LedDeviceWS281x() { if (initialized) { - std::cout << "Shutdown WS281x PWM and DMA channel" << std::endl; ws2811_fini(&led_string); } initialized = false; diff --git a/libsrc/leddevice/LedHIDDevice.cpp b/libsrc/leddevice/LedHIDDevice.cpp index 0ed53524..e8dd25ff 100644 --- a/libsrc/leddevice/LedHIDDevice.cpp +++ b/libsrc/leddevice/LedHIDDevice.cpp @@ -37,19 +37,19 @@ int LedHIDDevice::open() int error = hid_init(); if (error != 0) { - std::cerr << "Error while initializing the hidapi context" << std::endl; + Error(_log, "Error while initializing the hidapi context"); return -1; } - std::cout << "Hidapi initialized" << std::endl; + Debug(_log,"Hidapi initialized"); // Open the device - printf("Opening device: VID %04hx PID %04hx\n", _VendorId, _ProductId); + Info(_log, "Opening device: VID %04hx PID %04hx\n", _VendorId, _ProductId); _deviceHandle = hid_open(_VendorId, _ProductId, nullptr); if (_deviceHandle == nullptr) { // Failed to open the device - std::cerr << "Failed to open HID device. Maybe your PID/VID setting is wrong? Make sure to add a udev rule/use sudo." << std::endl; + Error(_log,"Failed to open HID device. Maybe your PID/VID setting is wrong? Make sure to add a udev rule/use sudo."); // http://www.signal11.us/oss/hidapi/ /* @@ -70,8 +70,9 @@ int LedHIDDevice::open() return -1; } - else{ - std::cout << "Opened HID device successful" << std::endl; + else + { + Info(_log,"Opened HID device successful"); } // Wait after device got opened if enabled @@ -79,7 +80,7 @@ int LedHIDDevice::open() { _blockedForDelay = true; QTimer::singleShot(_delayAfterConnect_ms, this, SLOT(unblockAfterDelay())); - std::cout << "Device blocked for " << _delayAfterConnect_ms << " ms" << std::endl; + Debug(_log, "Device blocked for %d ms", _delayAfterConnect_ms); } return 0; @@ -98,10 +99,10 @@ int LedHIDDevice::writeBytes(const unsigned size, const uint8_t * data) auto status = open(); if(status < 0){ // Try again in 3 seconds - int seconds = 3000; + int delay_ms = 3000; _blockedForDelay = true; - QTimer::singleShot(seconds, this, SLOT(unblockAfterDelay())); - std::cout << "Device blocked for " << seconds << " ms" << std::endl; + QTimer::singleShot(delay_ms, this, SLOT(unblockAfterDelay())); + Debug(_log,"Device blocked for %d ms", delay_ms); } // Return here, to not write led data if the device should be blocked after connect return status; @@ -123,7 +124,7 @@ int LedHIDDevice::writeBytes(const unsigned size, const uint8_t * data) // Handle first error if(ret < 0){ - std::cerr << "Failed to write to HID device." << std::endl; + Error(_log,"Failed to write to HID device."); // Try again if(_useFeature){ @@ -135,7 +136,7 @@ int LedHIDDevice::writeBytes(const unsigned size, const uint8_t * data) // Writing failed again, device might have disconnected if(ret < 0){ - std::cerr << "Failed to write to HID device." << std::endl; + Error(_log,"Failed to write to HID device."); hid_close(_deviceHandle); _deviceHandle = nullptr; @@ -147,6 +148,6 @@ int LedHIDDevice::writeBytes(const unsigned size, const uint8_t * data) void LedHIDDevice::unblockAfterDelay() { - std::cout << "Device unblocked" << std::endl; + Debug(_log,"Device unblocked"); _blockedForDelay = false; } diff --git a/libsrc/leddevice/LedRs232Device.cpp b/libsrc/leddevice/LedRs232Device.cpp index ca9c4b32..9030088a 100644 --- a/libsrc/leddevice/LedRs232Device.cpp +++ b/libsrc/leddevice/LedRs232Device.cpp @@ -6,9 +6,6 @@ // Qt includes #include -// Serial includes -#include - // Local Hyperion includes #include "LedRs232Device.h" @@ -16,112 +13,73 @@ LedRs232Device::LedRs232Device(const std::string& outputDevice, const unsigned b _deviceName(outputDevice), _baudRate_Hz(baudrate), _delayAfterConnect_ms(delayAfterConnect_ms), - _rs232Port(), + _rs232Port(this), _blockedForDelay(false) { - // empty } LedRs232Device::~LedRs232Device() { if (_rs232Port.isOpen()) - { _rs232Port.close(); - } } + int LedRs232Device::open() { - try - { - std::cout << "Opening UART: " << _deviceName << std::endl; - _rs232Port.setPort(_deviceName); - _rs232Port.setBaudrate(_baudRate_Hz); - _rs232Port.open(); + Info(_log, "Opening UART: %s", _deviceName.c_str()); + _rs232Port.setPortName(_deviceName.c_str()); - if (_delayAfterConnect_ms > 0) - { - _blockedForDelay = true; - QTimer::singleShot(_delayAfterConnect_ms, this, SLOT(unblockAfterDelay())); - std::cout << "Device blocked for " << _delayAfterConnect_ms << " ms" << std::endl; - } - } - catch (const std::exception& e) - { - std::cerr << "Unable to open RS232 device (" << e.what() << ")" << std::endl; - return -1; - } - - return 0; + return tryOpen() ? 0 : -1; } + +bool LedRs232Device::tryOpen() +{ + if ( ! _rs232Port.isOpen() ) + { + if ( ! _rs232Port.open(QIODevice::WriteOnly) ) + { + Error(_log, "Unable to open RS232 device (%s)", _deviceName.c_str()); + return false; + } + _rs232Port.setBaudRate(_baudRate_Hz); + } + + if (_delayAfterConnect_ms > 0) + { + _blockedForDelay = true; + QTimer::singleShot(_delayAfterConnect_ms, this, SLOT(unblockAfterDelay())); + Debug(_log, "Device blocked for %d ms", _delayAfterConnect_ms); + } + + return _rs232Port.isOpen(); +} + + int LedRs232Device::writeBytes(const unsigned size, const uint8_t * data) { if (_blockedForDelay) - { return 0; - } if (!_rs232Port.isOpen()) { - // try to reopen - int status = open(); - if(status == -1){ - // Try again in 3 seconds - int seconds = 3000; - _blockedForDelay = true; - QTimer::singleShot(seconds, this, SLOT(unblockAfterDelay())); - std::cout << "Device blocked for " << seconds << " ms" << std::endl; - } - return status; + _delayAfterConnect_ms = 3000; + return tryOpen() ? 0 : -1; } -// for (int i = 0; i < 20; ++i) -// std::cout << std::hex << (int)data[i] << " "; -// std::cout << std::endl; + _rs232Port.flush(); + int result = _rs232Port.write(reinterpret_cast(data), size); + _rs232Port.waitForBytesWritten(100); + Debug(_log, "write %d ", result); + _rs232Port.flush(); - try - { - _rs232Port.flushOutput(); - _rs232Port.write(data, size); - _rs232Port.flush(); - } - catch (const serial::SerialException & serialExc) - { - // TODO[TvdZ]: Maybe we should limit the frequency of this error report somehow - std::cerr << "Serial exception caught while writing to device: " << serialExc.what() << std::endl; - std::cout << "Attempting to re-open the device." << std::endl; - - // First make sure the device is properly closed - try - { - _rs232Port.close(); - } - catch (const std::exception & e) {} - - // Attempt to open the device and write the data - try - { - _rs232Port.open(); - _rs232Port.write(data, size); - _rs232Port.flush(); - } - catch (const std::exception & e) - { - // We failed again, this not good, do nothing maybe in the next loop we have more success - } - } - catch (const std::exception& e) - { - std::cerr << "Unable to write to RS232 device (" << e.what() << ")" << std::endl; - return -1; - } - - return 0; + return (result<0) ? -1 : 0; } + void LedRs232Device::unblockAfterDelay() { - std::cout << "Device unblocked" << std::endl; + Debug(_log, "Device unblocked"); _blockedForDelay = false; } diff --git a/libsrc/leddevice/LedRs232Device.h b/libsrc/leddevice/LedRs232Device.h index e11d0a8a..0fdabda9 100644 --- a/libsrc/leddevice/LedRs232Device.h +++ b/libsrc/leddevice/LedRs232Device.h @@ -1,9 +1,7 @@ #pragma once #include - -// Serial includes -#include +#include // Leddevice includes #include @@ -52,17 +50,20 @@ private slots: void unblockAfterDelay(); private: + // tries to open device if not opened + bool tryOpen(); + /// The name of the output device const std::string _deviceName; /// The used baudrate of the output device - const int _baudRate_Hz; + const qint32 _baudRate_Hz; /// Sleep after the connect before continuing - const int _delayAfterConnect_ms; + int _delayAfterConnect_ms; /// The RS232 serial-device - serial::Serial _rs232Port; + QSerialPort _rs232Port; bool _blockedForDelay; }; diff --git a/libsrc/leddevice/LedSpiDevice.cpp b/libsrc/leddevice/LedSpiDevice.cpp index a4c7125c..fb258385 100644 --- a/libsrc/leddevice/LedSpiDevice.cpp +++ b/libsrc/leddevice/LedSpiDevice.cpp @@ -3,6 +3,7 @@ #include #include #include +#include // Linux includes #include @@ -10,6 +11,7 @@ // Local Hyperion includes #include "LedSpiDevice.h" +#include LedSpiDevice::LedSpiDevice(const std::string& outputDevice, const unsigned baudrate, const int latchTime_ns) : @@ -34,7 +36,7 @@ int LedSpiDevice::open() if (mFid < 0) { - std::cerr << "Failed to open device('" << mDeviceName << "') " << std::endl; + Error( _log, "Failed to open device (%s). Error message: %s", mDeviceName.c_str(), strerror(errno) ); return -1; } diff --git a/libsrc/leddevice/LedUdpDevice.cpp b/libsrc/leddevice/LedUdpDevice.cpp index b8126592..39717b5e 100644 --- a/libsrc/leddevice/LedUdpDevice.cpp +++ b/libsrc/leddevice/LedUdpDevice.cpp @@ -15,18 +15,16 @@ // Local Hyperion includes #include "LedUdpDevice.h" - LedUdpDevice::LedUdpDevice(const std::string& outputDevice, const unsigned baudrate, const int latchTime_ns) : mDeviceName(outputDevice), mBaudRate_Hz(baudrate), - mLatchTime_ns(latchTime_ns), - mFid(-1) + mLatchTime_ns(latchTime_ns) { udpSocket = new QUdpSocket(); QString str = QString::fromStdString(mDeviceName); QStringList _list = str.split(":"); if (_list.size() != 2) { - printf ("ERROR: LedUdpDevice: Error parsing hostname:port\n"); + Error( _log, "Error parsing hostname:port"); exit (-1); } QHostInfo info = QHostInfo::fromName(_list.at(0)); @@ -39,38 +37,26 @@ LedUdpDevice::LedUdpDevice(const std::string& outputDevice, const unsigned baudr LedUdpDevice::~LedUdpDevice() { -// close(mFid); + udpSocket->close(); } int LedUdpDevice::open() { - udpSocket->bind(QHostAddress::Any, 7755); + QHostAddress _localAddress = QHostAddress::Any; + quint16 _localPort = 0; - -/* - if (mFid < 0) - { - std::cerr << "Failed to open device('" << mDeviceName << "') " << std::endl; - return -1; - } -*/ + WarningIf( !udpSocket->bind(_localAddress, _localPort), + _log, "Couldnt bind local address: %s", strerror(errno)); return 0; } int LedUdpDevice::writeBytes(const unsigned size, const uint8_t * data) { -/* - if (mFid < 0) - { - return -1; - } -*/ -// int retVal = udpSocket->writeDatagram((const char *)data,size,QHostAddress::LocalHost,9998); - int retVal = udpSocket->writeDatagram((const char *)data,size,_address,_port); + qint64 retVal = udpSocket->writeDatagram((const char *)data,size,_address,_port); - if (retVal == 0 && mLatchTime_ns > 0) + if (retVal >= 0 && mLatchTime_ns > 0) { // The 'latch' time for latching the shifted-value into the leds timespec latchTime; @@ -79,6 +65,8 @@ int LedUdpDevice::writeBytes(const unsigned size, const uint8_t * data) // Sleep to latch the leds (only if write succesfull) nanosleep(&latchTime, NULL); + } else { + Warning( _log, "Error sending: %s", strerror(errno)); } return retVal; diff --git a/libsrc/leddevice/LedUdpDevice.h b/libsrc/leddevice/LedUdpDevice.h index cd9e2463..9afec475 100644 --- a/libsrc/leddevice/LedUdpDevice.h +++ b/libsrc/leddevice/LedUdpDevice.h @@ -7,6 +7,7 @@ // Hyperion includes #include +#include /// /// The LedUdpDevice implements an abstract base-class for LedDevices using the SPI-device. diff --git a/libsrc/protoserver/CMakeLists.txt b/libsrc/protoserver/CMakeLists.txt index 61324dc9..060155a3 100644 --- a/libsrc/protoserver/CMakeLists.txt +++ b/libsrc/protoserver/CMakeLists.txt @@ -46,7 +46,7 @@ add_library(protoserver ${ProtoServer_PROTO_HDRS} ) -qt5_use_modules(protoserver Widgets) +qt5_use_modules(protoserver Gui) target_link_libraries(protoserver hyperion diff --git a/libsrc/udplistener/CMakeLists.txt b/libsrc/udplistener/CMakeLists.txt new file mode 100644 index 00000000..5b90a7c3 --- /dev/null +++ b/libsrc/udplistener/CMakeLists.txt @@ -0,0 +1,30 @@ + +# Define the current source locations +set(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/udplistener) +set(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/udplistener) + +# Group the headers that go through the MOC compiler +set(UDPListener_QT_HEADERS + ${CURRENT_HEADER_DIR}/UDPListener.h +) + +set(UDPListener_HEADERS +) + +set(UDPListener_SOURCES + ${CURRENT_SOURCE_DIR}/UDPListener.cpp +) + +qt5_wrap_cpp(UDPListener_HEADERS_MOC ${UDPListener_QT_HEADERS}) + +add_library(udplistener + ${UDPListener_HEADERS} + ${UDPListener_QT_HEADERS} + ${UDPListener_SOURCES} + ${UDPListener_HEADERS_MOC} +) + +target_link_libraries(udplistener + hyperion + hyperion-utils + ${QT_LIBRARIES}) diff --git a/libsrc/udplistener/UDPListener.cpp b/libsrc/udplistener/UDPListener.cpp new file mode 100644 index 00000000..70ed4c77 --- /dev/null +++ b/libsrc/udplistener/UDPListener.cpp @@ -0,0 +1,119 @@ +// system includes +#include + +// project includes +#include + +// hyperion util includes +#include "hyperion/ImageProcessorFactory.h" +#include "hyperion/ImageProcessor.h" +#include "utils/ColorRgb.h" +#include "HyperionConfig.h" + +UDPListener::UDPListener(const int priority, const int timeout, const std::string& address, quint16 listenPort, bool shared) : + QObject(), + _hyperion(Hyperion::getInstance()), + _server(), + _openConnections(), + _priority(priority), + _timeout(timeout), + _ledColors(Hyperion::getInstance()->getLedCount(), ColorRgb::BLACK), + _log(Logger::getInstance("UDPLISTENER")), + _isActive(false), + _bondage(shared ? QAbstractSocket::ShareAddress : QAbstractSocket::DefaultForPlatform) +{ + _server = new QUdpSocket(this); + QHostAddress listenAddress = address.empty() + ? QHostAddress::AnyIPv4 + : QHostAddress( QString::fromStdString(address) ); + + // Set trigger for incoming connections + connect(_server, SIGNAL(readyRead()), this, SLOT(readPendingDatagrams())); +} + +UDPListener::~UDPListener() +{ + // clear the current channel + stop(); + delete _server; + _hyperion->clear(_priority); +} + + +void UDPListener::start() +{ + if ( active() ) + return; + + QHostAddress mcastGroup; + if (_listenAddress.isInSubnet(QHostAddress::parseSubnet("224.0.0.0/4"))) { + mcastGroup = _listenAddress; + } + + if (!_server->bind(_listenAddress, _listenPort, _bondage)) + { + Warning(_log, "Could not bind to %s:%d", _listenAddress.toString().toStdString().c_str(), _listenPort); + } + else + { + Info(_log, "Started, listening on %s:%d", _listenAddress.toString().toStdString().c_str(), _listenPort); + if (!mcastGroup.isNull()) { + bool joinGroupOK = _server->joinMulticastGroup(_listenAddress); + InfoIf ( joinGroupOK, _log, "Multicast enabled"); + WarningIf( ! joinGroupOK, _log, "Multicast failed"); + } + _isActive = true; + emit statusChanged(_isActive); + } +} + +void UDPListener::stop() +{ + if ( ! active() ) + return; + + _server->close(); + _isActive = false; + emit statusChanged(_isActive); +} + + +uint16_t UDPListener::getPort() const +{ + return _server->localPort(); +} + + +void UDPListener::readPendingDatagrams() +{ + while (_server->hasPendingDatagrams()) { + QByteArray datagram; + datagram.resize(_server->pendingDatagramSize()); + QHostAddress sender; + quint16 senderPort; + + _server->readDatagram(datagram.data(), datagram.size(), + &sender, &senderPort); + + processTheDatagram(&datagram); + + } +} + + +void UDPListener::processTheDatagram(const QByteArray * datagram) +{ + int packlen = datagram->size()/3; + int ledlen = _ledColors.size(); + int maxled = std::min(packlen , ledlen); + + for (int ledIndex=0; ledIndex < maxled; ledIndex++) { + ColorRgb & rgb = _ledColors[ledIndex]; + rgb.red = datagram->at(ledIndex*3+0); + rgb.green = datagram->at(ledIndex*3+1); + rgb.blue = datagram->at(ledIndex*3+2); + } + + _hyperion->setColors(_priority, _ledColors, _timeout, -1); + +} diff --git a/libsrc/utils/CMakeLists.txt b/libsrc/utils/CMakeLists.txt index e9dd49e8..3e4c2074 100644 --- a/libsrc/utils/CMakeLists.txt +++ b/libsrc/utils/CMakeLists.txt @@ -49,7 +49,7 @@ add_library(hyperion-utils ${CURRENT_SOURCE_DIR}/jsonschema/JsonSchemaChecker.cpp ) -qt5_use_modules(hyperion-utils Widgets) +qt5_use_modules(hyperion-utils Core) target_link_libraries(hyperion-utils jsoncpp diff --git a/libsrc/utils/Logger.cpp b/libsrc/utils/Logger.cpp index 4046d2a1..b9f59114 100644 --- a/libsrc/utils/Logger.cpp +++ b/libsrc/utils/Logger.cpp @@ -13,31 +13,67 @@ std::string getBaseName( std::string sourceFile) return fi.fileName().toStdString(); } -static const char * LogLevelStrings[] = { "DEBUG", "INFO", "WARNING", "ERROR" }; -static const int LogLevelSysLog[] = { LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERR }; +static const char * LogLevelStrings[] = { "", "DEBUG", "INFO", "WARNING", "ERROR" }; +static const int LogLevelSysLog[] = { LOG_DEBUG, LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERR }; static unsigned int loggerCount = 0; static unsigned int loggerId = 0; + std::map *Logger::LoggerMap = nullptr; +Logger::LogLevel Logger::GLOBAL_MIN_LOG_LEVEL = Logger::UNSET; Logger* Logger::getInstance(std::string name, Logger::LogLevel minLevel) { - if (Logger::LoggerMap == nullptr) + if (LoggerMap == nullptr) { - Logger::LoggerMap = new std::map; + LoggerMap = new std::map; } if ( LoggerMap->find(name) == LoggerMap->end() ) { Logger* log = new Logger(name,minLevel); - Logger::LoggerMap->insert(std::pair(name,log)); // compat version, replace it with following line if we have 100% c++11 - //Logger::LoggerMap->emplace(name,log); // not compat with older linux distro's e.g. wheezy + LoggerMap->insert(std::pair(name,log)); // compat version, replace it with following line if we have 100% c++11 + //LoggerMap->emplace(name,log); // not compat with older linux distro's e.g. wheezy return log; } - return Logger::LoggerMap->at(name); + return LoggerMap->at(name); } +void Logger::deleteInstance(std::string name) +{ + if (LoggerMap == nullptr) + return; + + if ( name.empty() ) + { + std::map::iterator it; + for ( it=LoggerMap->begin(); it != LoggerMap->end(); it++) + { + delete it->second; + } + LoggerMap->clear(); + } + else if (LoggerMap->find(name) != LoggerMap->end()) + { + delete LoggerMap->at(name); + LoggerMap->erase(name); + } + +} + +void Logger::setLogLevel(LogLevel level,std::string name) +{ + if ( name.empty() ) + { + GLOBAL_MIN_LOG_LEVEL = level; + } + else + { + Logger* log = Logger::getInstance(name,level); + log->setMinLevel(level); + } +} Logger::Logger ( std::string name, LogLevel minLevel ): @@ -54,12 +90,7 @@ Logger::Logger ( std::string name, LogLevel minLevel ): std::transform(_appname.begin(), _appname.end(),_appname.begin(), ::toupper); loggerCount++; - -// if (pLoggerMap == NULL) -// pLoggerMap = new std::map; -// -// - + if (_syslogEnabled && loggerCount == 1 ) { openlog (program_invocation_short_name, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL0); @@ -68,7 +99,7 @@ Logger::Logger ( std::string name, LogLevel minLevel ): Logger::~Logger() { - //LoggerMap.erase(_loggerId); + Debug(this, "logger '%s' destroyed", _name.c_str() ); loggerCount--; if ( loggerCount == 0 ) closelog(); @@ -77,9 +108,11 @@ Logger::~Logger() void Logger::Message(LogLevel level, const char* sourceFile, const char* func, unsigned int line, const char* fmt, ...) { - if ( level < _minLevel ) + if ( (GLOBAL_MIN_LOG_LEVEL == Logger::UNSET && level < _minLevel) // no global level, use level from logger + || (GLOBAL_MIN_LOG_LEVEL > Logger::UNSET && level < GLOBAL_MIN_LOG_LEVEL) ) // global level set, use global level return; + char msg[512]; va_list args; va_start (args, fmt); diff --git a/libsrc/webconfig/CMakeLists.txt b/libsrc/webconfig/CMakeLists.txt index c26c5f68..59e42e8e 100644 --- a/libsrc/webconfig/CMakeLists.txt +++ b/libsrc/webconfig/CMakeLists.txt @@ -6,7 +6,6 @@ set(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/webconfig) # Group the headers that go through the MOC compiler set(WebConfig_QT_HEADERS ${CURRENT_SOURCE_DIR}/QtHttpClientWrapper.h - ${CURRENT_SOURCE_DIR}/QtHttpHeader.h ${CURRENT_SOURCE_DIR}/QtHttpReply.h ${CURRENT_SOURCE_DIR}/QtHttpRequest.h ${CURRENT_SOURCE_DIR}/QtHttpServer.h @@ -38,7 +37,7 @@ add_library(webconfig ${WebConfig_HEADERS_MOC} ) -qt5_use_modules(webconfig Widgets Network) +qt5_use_modules(webconfig Network) target_link_libraries(webconfig hyperion diff --git a/libsrc/webconfig/WebConfig.cpp b/libsrc/webconfig/WebConfig.cpp index fdba72c5..a312fa5a 100644 --- a/libsrc/webconfig/WebConfig.cpp +++ b/libsrc/webconfig/WebConfig.cpp @@ -10,6 +10,7 @@ WebConfig::WebConfig(QObject * parent) _hyperion = Hyperion::getInstance(); const Json::Value &config = _hyperion->getJsonConfig(); _baseUrl = QString::fromStdString(WEBCONFIG_DEFAULT_PATH); + _port = WEBCONFIG_DEFAULT_PORT; bool webconfigEnable = true; diff --git a/libsrc/xbmcvideochecker/CMakeLists.txt b/libsrc/xbmcvideochecker/CMakeLists.txt index 693cb906..7d300d67 100644 --- a/libsrc/xbmcvideochecker/CMakeLists.txt +++ b/libsrc/xbmcvideochecker/CMakeLists.txt @@ -24,8 +24,6 @@ add_library(xbmcvideochecker ${XBMCVideoChecker_SOURCES} ) -qt5_use_modules(xbmcvideochecker Widgets) - target_link_libraries(xbmcvideochecker hyperion ${QT_LIBRARIES}) diff --git a/src/hyperion-aml/CMakeLists.txt b/src/hyperion-aml/CMakeLists.txt index f70f5ba5..ae270576 100644 --- a/src/hyperion-aml/CMakeLists.txt +++ b/src/hyperion-aml/CMakeLists.txt @@ -38,6 +38,6 @@ target_link_libraries(${PROJECT_NAME} pthread ) -qt5_use_modules(${PROJECT_NAME} Widgets Core Gui Network) +qt5_use_modules(${PROJECT_NAME} Core Gui Network) install ( TARGETS ${PROJECT_NAME} DESTINATION "bin" COMPONENT ambilight ) diff --git a/src/hyperion-aml/hyperion-aml.cpp b/src/hyperion-aml/hyperion-aml.cpp index efd95fec..887daad1 100644 --- a/src/hyperion-aml/hyperion-aml.cpp +++ b/src/hyperion-aml/hyperion-aml.cpp @@ -27,7 +27,7 @@ int main(int argc, char ** argv) { std::cout << "hyperion-aml:" << std::endl - << "\tversion : " << HYPERION_VERSION_ID << std::endl + << "\tVersion : " << HYPERION_VERSION << " (" << HYPERION_BUILD_ID << ")" << std::endl << "\tbuild time: " << __DATE__ << " " << __TIME__ << std::endl; QCoreApplication app(argc, argv); diff --git a/src/hyperion-dispmanx/CMakeLists.txt b/src/hyperion-dispmanx/CMakeLists.txt index 841203fe..fe903678 100644 --- a/src/hyperion-dispmanx/CMakeLists.txt +++ b/src/hyperion-dispmanx/CMakeLists.txt @@ -40,6 +40,6 @@ target_link_libraries( ${PROJECT_NAME} pthread ) -qt5_use_modules(${PROJECT_NAME} Widgets Core Gui Network) +qt5_use_modules(${PROJECT_NAME} Core Gui Network) install ( TARGETS ${PROJECT_NAME} DESTINATION "bin" COMPONENT ambilight ) diff --git a/src/hyperion-dispmanx/hyperion-dispmanx.cpp b/src/hyperion-dispmanx/hyperion-dispmanx.cpp index bf8b1794..853fe2dd 100644 --- a/src/hyperion-dispmanx/hyperion-dispmanx.cpp +++ b/src/hyperion-dispmanx/hyperion-dispmanx.cpp @@ -25,7 +25,7 @@ int main(int argc, char ** argv) { std::cout << "hyperion-dispmanx:" << std::endl - << "\tversion : " << HYPERION_VERSION_ID << std::endl + << "\tVersion : " << HYPERION_VERSION << " (" << HYPERION_BUILD_ID << ")" << std::endl << "\tbuild time: " << __DATE__ << " " << __TIME__ << std::endl; QCoreApplication app(argc, argv); diff --git a/src/hyperion-framebuffer/CMakeLists.txt b/src/hyperion-framebuffer/CMakeLists.txt index 4e91f192..159183e4 100644 --- a/src/hyperion-framebuffer/CMakeLists.txt +++ b/src/hyperion-framebuffer/CMakeLists.txt @@ -38,6 +38,6 @@ target_link_libraries( ${PROJECT_NAME} pthread ) -qt5_use_modules(${PROJECT_NAME} Widgets Core Gui Network) +qt5_use_modules(${PROJECT_NAME} Core Gui Network) install ( TARGETS ${PROJECT_NAME} DESTINATION "bin" COMPONENT ambilight ) diff --git a/src/hyperion-osx/CMakeLists.txt b/src/hyperion-osx/CMakeLists.txt index c9dcd332..870e2b1f 100644 --- a/src/hyperion-osx/CMakeLists.txt +++ b/src/hyperion-osx/CMakeLists.txt @@ -38,6 +38,6 @@ target_link_libraries( ${PROJECT_NAME} pthread ) -qt5_use_modules(${PROJECT_NAME} Widgets Core Gui Network) +qt5_use_modules(${PROJECT_NAME} Core Gui Network) install ( TARGETS ${PROJECT_NAME} DESTINATION "bin" COMPONENT ambilight ) diff --git a/src/hyperion-remote/CMakeLists.txt b/src/hyperion-remote/CMakeLists.txt index 1125b5dd..64817c83 100644 --- a/src/hyperion-remote/CMakeLists.txt +++ b/src/hyperion-remote/CMakeLists.txt @@ -30,7 +30,7 @@ target_link_libraries(${PROJECT_NAME} getoptPlusPlus ${QT_LIBRARIES}) -qt5_use_modules(${PROJECT_NAME} Widgets Core Network) +qt5_use_modules(${PROJECT_NAME} Gui Core Network) install ( TARGETS ${PROJECT_NAME} DESTINATION "bin" COMPONENT ambilight ) diff --git a/src/hyperion-remote/hyperion-remote.cpp b/src/hyperion-remote/hyperion-remote.cpp index 24145e6d..5827dc41 100644 --- a/src/hyperion-remote/hyperion-remote.cpp +++ b/src/hyperion-remote/hyperion-remote.cpp @@ -33,7 +33,7 @@ int main(int argc, char * argv[]) { std::cout << "hyperion-remote:" << std::endl - << "\tversion : " << HYPERION_VERSION_ID << std::endl + << "\tVersion : " << HYPERION_VERSION << " (" << HYPERION_BUILD_ID << ")" << std::endl << "\tbuild time: " << __DATE__ << " " << __TIME__ << std::endl; QCoreApplication app(argc, argv); diff --git a/src/hyperion-v4l2/CMakeLists.txt b/src/hyperion-v4l2/CMakeLists.txt index b9855e89..bf4cb996 100644 --- a/src/hyperion-v4l2/CMakeLists.txt +++ b/src/hyperion-v4l2/CMakeLists.txt @@ -43,6 +43,6 @@ target_link_libraries(${PROJECT_NAME} ${QT_LIBRARIES} ) -qt5_use_modules(${PROJECT_NAME} Widgets Core Gui Network) +qt5_use_modules(${PROJECT_NAME} Core Gui Network) install ( TARGETS ${PROJECT_NAME} DESTINATION "bin" COMPONENT ambilight ) diff --git a/src/hyperion-v4l2/hyperion-v4l2.cpp b/src/hyperion-v4l2/hyperion-v4l2.cpp index 747bd4a5..31895dbc 100644 --- a/src/hyperion-v4l2/hyperion-v4l2.cpp +++ b/src/hyperion-v4l2/hyperion-v4l2.cpp @@ -38,10 +38,10 @@ void saveScreenshot(void *, const Image & image) int main(int argc, char** argv) { - std::cout - << "hyperion-v4l2:" << std::endl - << "\tversion : " << HYPERION_VERSION_ID << std::endl - << "\tbuild time: " << __DATE__ << " " << __TIME__ << std::endl; + std::cout + << "hyperion-v4l2:" << std::endl + << "\tVersion : " << HYPERION_VERSION << " (" << HYPERION_BUILD_ID << ")" << std::endl + << "\tbuild time: " << __DATE__ << " " << __TIME__ << std::endl; QCoreApplication app(argc, argv); diff --git a/src/hyperion-x11/CMakeLists.txt b/src/hyperion-x11/CMakeLists.txt index 4a6f3d81..d65c4a53 100644 --- a/src/hyperion-x11/CMakeLists.txt +++ b/src/hyperion-x11/CMakeLists.txt @@ -41,6 +41,6 @@ target_link_libraries(${PROJECT_NAME} pthread ) -qt5_use_modules(${PROJECT_NAME} Widgets Core Gui Network) +qt5_use_modules(${PROJECT_NAME} Core Gui Network) install ( TARGETS ${PROJECT_NAME} DESTINATION "bin" COMPONENT ambilight ) diff --git a/src/hyperion-x11/hyperion-x11.cpp b/src/hyperion-x11/hyperion-x11.cpp index 8c399aff..75e1e72d 100644 --- a/src/hyperion-x11/hyperion-x11.cpp +++ b/src/hyperion-x11/hyperion-x11.cpp @@ -24,7 +24,7 @@ int main(int argc, char ** argv) { std::cout << "hyperion-x11:" << std::endl - << "\tversion : " << HYPERION_VERSION_ID << std::endl + << "\tVersion : " << HYPERION_VERSION << " (" << HYPERION_BUILD_ID << ")" << std::endl << "\tbuild time: " << __DATE__ << " " << __TIME__ << std::endl; QCoreApplication app(argc, argv); diff --git a/src/hyperiond/CMakeLists.txt b/src/hyperiond/CMakeLists.txt index cae89651..3ee7d6ba 100644 --- a/src/hyperiond/CMakeLists.txt +++ b/src/hyperiond/CMakeLists.txt @@ -9,6 +9,7 @@ target_link_libraries(hyperiond effectengine jsonserver boblightserver + udplistener protoserver webconfig bonjour diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index f0003af6..cb2d8364 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -5,6 +5,9 @@ #include #include #include +#include +#include +#include #include "HyperionConfig.h" @@ -17,6 +20,7 @@ #include #include #include +#include #include "hyperiond.h" @@ -28,15 +32,16 @@ HyperionDaemon::HyperionDaemon(std::string configFile, QObject *parent) , _jsonServer(nullptr) , _protoServer(nullptr) , _boblightServer(nullptr) + , _udpListener(nullptr) , _v4l2Grabber(nullptr) , _dispmanx(nullptr) , _amlGrabber(nullptr) , _fbGrabber(nullptr) , _osxGrabber(nullptr) - , _webConfig(nullptr) + , _hyperion(nullptr) { loadConfig(configFile); - Hyperion::initInstance(_config, configFile); + _hyperion = Hyperion::initInstance(_config, configFile); Info(_log, "Hyperion started and initialised"); } @@ -51,28 +56,27 @@ HyperionDaemon::~HyperionDaemon() delete _jsonServer; delete _protoServer; delete _boblightServer; - delete _webConfig; + delete _udpListener; + delete _hyperion; } void HyperionDaemon::run() { - startBootsequence(); + startInitialEffect(); createXBMCVideoChecker(); // ---- network services ----- startNetworkServices(); - _webConfig = new WebConfig(this); // ---- grabber ----- createGrabberV4L2(); createGrabberDispmanx(); createGrabberAmlogic(); createGrabberFramebuffer(); - createGrabberDispmanx(); #if !defined(ENABLE_DISPMANX) && !defined(ENABLE_OSX) && !defined(ENABLE_FB) - ErrorIf(_config.isMember("framegrabber"), log, "No grabber can be instantiated, because all grabbers have been left out from the build"); + ErrorIf(_config.isMember("framegrabber"), _log, "No grabber can be instantiated, because all grabbers have been left out from the build"); #endif } @@ -101,54 +105,69 @@ void HyperionDaemon::loadConfig(const std::string & configFile) } -void HyperionDaemon::startBootsequence() +void HyperionDaemon::startInitialEffect() { Hyperion *hyperion = Hyperion::getInstance(); // create boot sequence if the configuration is present - if (_config.isMember("bootsequence")) + if (_config.isMember("initialEffect")) { - const Json::Value effectConfig = _config["bootsequence"]; - - // Get the parameters for the bootsequence - const std::string effectName = effectConfig["effect"].asString(); - const unsigned duration_ms = effectConfig["duration_ms"].asUInt(); - const int priority = (duration_ms != 0) ? 0 : effectConfig.get("priority",990).asInt(); - const int bootcolor_priority = (priority > 990) ? priority+1 : 990; + const Json::Value effectConfig = _config["initialEffect"]; + const int HIGHEST_PRIORITY = 0; + const int DURATION_INFINITY = 0; + const int LOWEST_PRIORITY = std::numeric_limits::max()-1; // clear the leds - ColorRgb boot_color = ColorRgb::BLACK; - hyperion->setColor(bootcolor_priority, boot_color, 0, false); + hyperion->setColor(HIGHEST_PRIORITY, ColorRgb::BLACK, DURATION_INFINITY, false); - // start boot effect - if ( ! effectName.empty() ) + // initial foreground effect/color + const Json::Value fgEffectConfig = effectConfig["foreground-effect"]; + int default_fg_duration_ms = 3000; + int fg_duration_ms = effectConfig.get("foreground-effect-duration_ms",default_fg_duration_ms).asUInt(); + if (fg_duration_ms == DURATION_INFINITY) { - int result; - std::cout << "INFO: Boot sequence '" << effectName << "' "; - if (effectConfig.isMember("args")) - { - std::cout << " (with user defined arguments) "; - const Json::Value effectConfigArgs = effectConfig["args"]; - result = hyperion->setEffect(effectName, effectConfigArgs, priority, duration_ms); - } - else - { - result = hyperion->setEffect(effectName, priority, duration_ms); - } - std::cout << ((result == 0) ? "started" : "failed") << std::endl; + fg_duration_ms = default_fg_duration_ms; + Warning(_log, "foreground effect duration 'infinity' is forbidden, set to default value %d ms",default_fg_duration_ms); } - - // static color - if ( ! effectConfig["color"].isNull() && effectConfig["color"].isArray() && effectConfig["color"].size() == 3 ) + if ( ! fgEffectConfig.isNull() && fgEffectConfig.isArray() && fgEffectConfig.size() == 3 ) { - boot_color = { - (uint8_t)effectConfig["color"][0].asUInt(), - (uint8_t)effectConfig["color"][1].asUInt(), - (uint8_t)effectConfig["color"][2].asUInt() + ColorRgb fg_color = { + (uint8_t)fgEffectConfig[0].asUInt(), + (uint8_t)fgEffectConfig[1].asUInt(), + (uint8_t)fgEffectConfig[2].asUInt() }; + hyperion->setColor(HIGHEST_PRIORITY, fg_color, fg_duration_ms, false); + Info(_log,"Inital foreground color set (%d %d %d)",fg_color.red,fg_color.green,fg_color.blue); + } + else if (! fgEffectConfig.isNull() && fgEffectConfig.isString()) + { + const std::string bgEffectName = fgEffectConfig.asString(); + int result = effectConfig.isMember("foreground-effect-args") + ? hyperion->setEffect(bgEffectName, effectConfig["foreground-effect-args"], HIGHEST_PRIORITY, fg_duration_ms) + : hyperion->setEffect(bgEffectName, HIGHEST_PRIORITY, fg_duration_ms); + Info(_log,"Inital foreground effect '%s' %s", bgEffectName.c_str(), ((result == 0) ? "started" : "failed")); } - hyperion->setColor(bootcolor_priority, boot_color, 0, false); + // initial background effect/color + const Json::Value bgEffectConfig = effectConfig["background-effect"]; + if ( ! bgEffectConfig.isNull() && bgEffectConfig.isArray() && bgEffectConfig.size() == 3 ) + { + ColorRgb bg_color = { + (uint8_t)bgEffectConfig[0].asUInt(), + (uint8_t)bgEffectConfig[1].asUInt(), + (uint8_t)bgEffectConfig[2].asUInt() + }; + hyperion->setColor(LOWEST_PRIORITY, bg_color, DURATION_INFINITY, false); + Info(_log,"Inital background color set (%d %d %d)",bg_color.red,bg_color.green,bg_color.blue); + } + else if (! bgEffectConfig.isNull() && bgEffectConfig.isString()) + { + const std::string bgEffectName = bgEffectConfig.asString(); + int result = effectConfig.isMember("background-effect-args") + ? hyperion->setEffect(bgEffectName, effectConfig["background-effect-args"], LOWEST_PRIORITY, DURATION_INFINITY) + : hyperion->setEffect(bgEffectName, LOWEST_PRIORITY, DURATION_INFINITY); + Info(_log,"Inital background effect '%s' %s", bgEffectName.c_str(), ((result == 0) ? "started" : "failed")); + } } } @@ -177,7 +196,6 @@ void HyperionDaemon::createXBMCVideoChecker() void HyperionDaemon::startNetworkServices() { - Hyperion *hyperion = Hyperion::getInstance(); XBMCVideoChecker* xbmcVideoChecker = XBMCVideoChecker::getInstance(); // Create Json server if configuration is present @@ -213,45 +231,68 @@ void HyperionDaemon::startNetworkServices() if (_config.isMember("boblightServer")) { const Json::Value & boblightServerConfig = _config["boblightServer"]; - _boblightServer = new BoblightServer(hyperion, boblightServerConfig.get("priority",900).asInt(), boblightServerConfig["port"].asUInt()); - Info(_log, "Boblight server created and started on port %d", _boblightServer->getPort()); + if ( boblightServerConfig.get("enable", true).asBool() ) + { + _boblightServer = new BoblightServer( + boblightServerConfig.get("priority",900).asInt(), + boblightServerConfig["port"].asUInt() + ); + Info(_log, "Boblight server created and started on port %d", _boblightServer->getPort()); + } } - // zeroconf + // Create UDP listener if configuration is present + if (_config.isMember("udpListener")) + { + const Json::Value & udpListenerConfig = _config["udpListener"]; + _udpListener = new UDPListener( + udpListenerConfig.get("priority",700).asInt(), + udpListenerConfig.get("timeout",10000).asInt(), + udpListenerConfig.get("address", "").asString(), + udpListenerConfig.get("port", 2801).asUInt(), + udpListenerConfig.get("shared", false).asBool() + ); + Info(_log, "UDP listener created on port %d", _udpListener->getPort()); + + if ( udpListenerConfig.get("enable", true).asBool() ) + { + Info(_log, "UDP listener started" ); + _udpListener->start(); + } + } + + // zeroconf description - $leddevicename@$hostname const Json::Value & deviceConfig = _config["device"]; - const std::string deviceName = deviceConfig.get("name", "").asString(); - const std::string hostname = QHostInfo::localHostName().toStdString(); + const std::string mDNSDescr = ( deviceConfig.get("name", "").asString() + + "@" + + QHostInfo::localHostName().toStdString() + ); + + // zeroconf udp listener + if (_udpListener != nullptr) { + BonjourServiceRegister *bonjourRegister_udp = new BonjourServiceRegister(); + bonjourRegister_udp->registerService( + BonjourRecord(mDNSDescr.c_str(), "_hyperiond-rgbled._udp", QString()), + _udpListener->getPort() + ); + Info(_log, "UDP LIstener mDNS responder started"); + } // zeroconf json - std::string mDNSDescr_json = hostname; - std::string mDNSService_json = "_hyperiond_json._tcp"; - if (_config.isMember("jsonServer")) - { - const Json::Value & jsonServerConfig = _config["jsonServer"]; - mDNSDescr_json = jsonServerConfig.get("mDNSDescr", mDNSDescr_json).asString(); - mDNSService_json = jsonServerConfig.get("mDNSService", mDNSService_json).asString(); - } - BonjourServiceRegister *bonjourRegister_json = new BonjourServiceRegister(); - bonjourRegister_json->registerService(BonjourRecord((deviceName + " @ " + mDNSDescr_json).c_str(), mDNSService_json.c_str(), - QString()), _jsonServer->getPort() ); + bonjourRegister_json->registerService( + BonjourRecord(mDNSDescr.c_str(), "_hyperiond-json._tcp", QString()), + _jsonServer->getPort() + ); Info(_log, "Json mDNS responder started"); // zeroconf proto - std::string mDNSDescr_proto = hostname; - std::string mDNSService_proto = "_hyperiond_proto._tcp"; - if (_config.isMember("protoServer")) - { - const Json::Value & protoServerConfig = _config["protoServer"]; - mDNSDescr_proto = protoServerConfig.get("mDNSDescr", mDNSDescr_proto).asString(); - mDNSService_proto = protoServerConfig.get("mDNSService", mDNSService_proto).asString(); - } - BonjourServiceRegister *bonjourRegister_proto = new BonjourServiceRegister(); - bonjourRegister_proto->registerService(BonjourRecord((deviceName + " @ " + mDNSDescr_proto).c_str(), mDNSService_proto.c_str(), - QString()), _protoServer->getPort() ); + bonjourRegister_proto->registerService( + BonjourRecord(mDNSDescr.c_str(), "_hyperiond-proto._tcp", QString()), + _protoServer->getPort() + ); Info(_log, "Proto mDNS responder started"); - } void HyperionDaemon::createGrabberDispmanx() diff --git a/src/hyperiond/hyperiond.h b/src/hyperiond/hyperiond.h index fd1354d2..07f84d04 100644 --- a/src/hyperiond/hyperiond.h +++ b/src/hyperiond/hyperiond.h @@ -39,6 +39,7 @@ #include #include #include +#include class HyperionDaemon : public QObject { @@ -49,7 +50,7 @@ public: void loadConfig(const std::string & configFile); void run(); - void startBootsequence(); + void startInitialEffect(); void createXBMCVideoChecker(); void startNetworkServices(); @@ -67,10 +68,12 @@ private: JsonServer* _jsonServer; ProtoServer* _protoServer; BoblightServer* _boblightServer; + UDPListener* _udpListener; V4L2Wrapper* _v4l2Grabber; DispmanxWrapper* _dispmanx; AmlogicWrapper* _amlGrabber; FramebufferWrapper* _fbGrabber; OsxWrapper* _osxGrabber; WebConfig* _webConfig; + Hyperion* _hyperion; }; diff --git a/src/hyperiond/main.cpp b/src/hyperiond/main.cpp index 183e349b..7177d2ea 100644 --- a/src/hyperiond/main.cpp +++ b/src/hyperiond/main.cpp @@ -11,8 +11,7 @@ #include #include - - +#include #include "hyperiond.h" @@ -40,7 +39,9 @@ void startNewHyperion(int parentPid, std::string hyperionFile, std::string confi int main(int argc, char** argv) { - Logger* log = Logger::getInstance("MAIN", Logger::INFO); + // initialize main logger and set global log level + Logger* log = Logger::getInstance("MAIN"); + Logger::setLogLevel(Logger::WARNING); // Initialising QCoreApplication QCoreApplication app(argc, argv); @@ -58,12 +59,40 @@ int main(int argc, char** argv) SwitchParameter<> & argVersion = parameters.add> (0x0, "version", "Show version information"); IntParameter & argParentPid = parameters.add (0x0, "parent", "pid of parent hyperiond"); + SwitchParameter<> & argSilent = parameters.add> (0x0, "silent", "do not print any outputs"); + SwitchParameter<> & argVerbose = parameters.add> (0x0, "verbose", "Increase verbosity"); + SwitchParameter<> & argDebug = parameters.add> (0x0, "debug", "Show debug messages"); SwitchParameter<> & argHelp = parameters.add> ('h', "help", "Show this help message and exit"); argParentPid.setDefault(0); optionParser.parse(argc, const_cast(argv)); const std::vector configFiles = optionParser.getFiles(); + int logLevelCheck = 0; + if (argSilent.isSet()) + { + Logger::setLogLevel(Logger::OFF); + logLevelCheck++; + } + + if (argVerbose.isSet()) + { + Logger::setLogLevel(Logger::INFO); + logLevelCheck++; + } + + if (argDebug.isSet()) + { + Logger::setLogLevel(Logger::DEBUG); + logLevelCheck++; + } + + if (logLevelCheck > 1) + { + Error(log, "aborting, because options --silent --verbose --debug can't used together"); + return 0; + } + // check if we need to display the usage. exit if we do. if (argHelp.isSet()) { @@ -75,7 +104,7 @@ int main(int argc, char** argv) { std::cout << "Hyperion Ambilight Deamon (" << getpid() << ")" << std::endl - << "\tVersion : " << HYPERION_VERSION_ID << std::endl + << "\tVersion : " << HYPERION_VERSION << " (" << HYPERION_BUILD_ID << ")" << std::endl << "\tBuild Time: " << __DATE__ << " " << __TIME__ << std::endl; return 0; @@ -108,15 +137,28 @@ int main(int argc, char** argv) Error(log, "No valid config found"); return 1; } - - HyperionDaemon* hyperiond = new HyperionDaemon(configFiles[argvId], &app); - hyperiond->run(); + HyperionDaemon* hyperiond = nullptr; + try + { + hyperiond = new HyperionDaemon(configFiles[argvId], &app); + hyperiond->run(); + } + catch (...) + { + Error(log, "Hyperion Daemon aborted"); + } + + WebConfig* webConfig = new WebConfig(&app); + // run the application int rc = app.exec(); Info(log, "INFO: Application closed with code %d", rc); + // delete components + delete webConfig; delete hyperiond; + Logger::deleteInstance(); return rc; }