Merged branch master into master

This commit is contained in:
brindosch 2016-06-27 10:59:34 +02:00
commit 353d60b9d3
91 changed files with 1339 additions and 5114 deletions

7
.travis.yml Normal file
View File

@ -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

View File

@ -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)

View File

@ -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/

View File

@ -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"

View File

@ -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

View File

@ -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)

View File

@ -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}" )

View File

@ -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 )

View File

@ -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" :
[
{

View File

@ -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"
}

View File

@ -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)

View File

@ -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()

View File

@ -1,204 +0,0 @@
/*!
* \file serial/impl/unix.h
* \author William Woodall <wjwwood@gmail.com>
* \author John Harrison <ash@greaterthaninfinity.com>
* \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 <pthread.h>
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)

View File

@ -1,201 +0,0 @@
/*!
* \file serial/impl/windows.h
* \author William Woodall <wjwwood@gmail.com>
* \author John Harrison <ash@greaterthaninfinity.com>
* \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)

View File

@ -1,700 +0,0 @@
/*!
* \file serial/serial.h
* \author William Woodall <wjwwood@gmail.com>
* \author John Harrison <ash.gti@gmail.com>
* \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 <limits>
#include <vector>
#include <string>
#include <cstring>
#include <sstream>
#include <exception>
#include <stdexcept>
#include <serial/v8stdint.h>
#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<uint32_t>::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<uint8_t> &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<string> containing the lines.
*/
std::vector<std::string>
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<uint8_t> &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

View File

@ -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 <stddef.h>
#include <stdio.h>
#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 <stdint.h>
#endif
#endif // V8STDINT_H_

File diff suppressed because it is too large Load Diff

View File

@ -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<size_t>(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)

View File

@ -1,397 +0,0 @@
/* Copyright 2012 William Woodall and John Harrison */
#if !defined(_WIN32) && !defined(__OpenBSD__)
# include <alloca.h>
#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<uint8_t> &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<const char*>(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<uint8_t*>
(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<const char*>
(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<const char*> (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<string>
Serial::readlines (size_t size, string eol)
{
ScopedReadLock (this->pimpl_);
std::vector<std::string> lines;
size_t eol_len = eol.length ();
uint8_t *buffer_ = static_cast<uint8_t*>
(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<const char*> (buffer_ + start_of_line),
read_so_far - start_of_line));
}
break; // Timeout occured on reading 1 byte
}
if (string (reinterpret_cast<const char*>
(buffer_ + read_so_far - eol_len), eol_len) == eol) {
// EOL found
lines.push_back(
string(reinterpret_cast<const char*> (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<const char*> (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<const uint8_t*>(data.c_str()),
data.length());
}
size_t
Serial::write (const std::vector<uint8_t> &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 ();
}

View File

@ -1,204 +0,0 @@
/*!
* \file serial/impl/unix.h
* \author William Woodall <wjwwood@gmail.com>
* \author John Harrison <ash@greaterthaninfinity.com>
* \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 <pthread.h>
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)

View File

@ -1,201 +0,0 @@
/*!
* \file serial/impl/windows.h
* \author William Woodall <wjwwood@gmail.com>
* \author John Harrison <ash@greaterthaninfinity.com>
* \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)

View File

@ -1,700 +0,0 @@
/*!
* \file serial/serial.h
* \author William Woodall <wjwwood@gmail.com>
* \author John Harrison <ash.gti@gmail.com>
* \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 <limits>
#include <vector>
#include <string>
#include <cstring>
#include <sstream>
#include <exception>
#include <stdexcept>
#include <serial/v8stdint.h>
#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<uint32_t>::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<uint8_t> &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<string> containing the lines.
*/
std::vector<std::string>
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<uint8_t> &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

View File

@ -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 <stddef.h>
#include <stdio.h>
#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 <stdint.h>
#endif
#endif // V8STDINT_H_

View File

@ -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();
///

View File

@ -12,6 +12,7 @@
// Effect engine includes
#include <effectengine/EffectDefinition.h>
#include <effectengine/ActiveEffectDefinition.h>
#include <utils/Logger.h>
// pre-declarioation
class Effect;
@ -57,8 +58,10 @@ private:
std::list<EffectDefinition> _availableEffects;
std::list<Effect *> _activeEffects;
std::list<ActiveEffectDefinition> _availableActiveEffects;
PyThreadState * _mainThreadState;
PyThreadState * _mainThreadState;
Logger * _log;
};

View File

@ -7,6 +7,7 @@
#include <utils/ColorRgb.h>
#include <utils/ColorRgbw.h>
#include <utils/RgbToRgbw.h>
#include <utils/Logger.h>
///
/// 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;
};

View File

@ -0,0 +1,93 @@
#pragma once
// system includes
#include <cstdint>
// Qt includes
#include <QUdpSocket>
#include <QSet>
#include <QHostAddress>
// Hyperion includes
#include <hyperion/Hyperion.h>
#include <utils/Logger.h>
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<UDPClientConnection *> _openConnections;
/// hyperion priority
int _priority;
/// hyperion priority
int _timeout;
/// The latest led color data
std::vector<ColorRgb> _ledColors;
/// Logger instance
Logger * _log;
/// state of connection
bool _isActive;
/// address to bind
QHostAddress _listenAddress;
quint16 _listenPort;
QAbstractSocket::BindFlag _bondage;
};

View File

@ -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<std::string,Logger*> *LoggerMap;
static LogLevel GLOBAL_MIN_LOG_LEVEL;
std::string _name;
std::string _appname;

View File

@ -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)

View File

@ -5,9 +5,9 @@
#include <boblightserver/BoblightServer.h>
#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)

View File

@ -26,8 +26,6 @@ add_library(boblightserver
${BoblightServer_HEADERS_MOC}
)
qt5_use_modules(boblightserver Widgets)
target_link_libraries(boblightserver
hyperion
hyperion-utils

View File

@ -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

View File

@ -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 <QApplication>
#include <QtCore>
#include <stdlib.h>
#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;
}

View File

@ -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 <QtGui>
#include <QtNetwork>
#include <stdlib.h>
#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();
}

View File

@ -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 <QDialog>
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

View File

@ -39,8 +39,6 @@ add_library(effectengine
${EffectEngineSOURCES}
)
qt5_use_modules(effectengine Widgets)
target_link_libraries(effectengine
hyperion
jsoncpp

View File

@ -10,6 +10,7 @@
// effect engin eincludes
#include "Effect.h"
#include <utils/Logger.h>
// 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;
}

View File

@ -83,3 +83,4 @@ private:
/// Buffer for colorData
std::vector<ColorRgb> _colors;
};

View File

@ -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<ColorRgb>>("std::vector<ColorRgb>");
@ -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<std::string> & 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)

View File

@ -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}

View File

@ -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
)

View File

@ -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}
)

View File

@ -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

View File

@ -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);

View File

@ -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}

View File

@ -0,0 +1,6 @@
#include <leddevice/LedDevice.h>
LedDevice::LedDevice()
: _log(Logger::getInstance("LedDevice"))
{
}

View File

@ -27,9 +27,6 @@ int LedDeviceAPA102::write(const std::vector<ColorRgb> &ledValues)
const unsigned int endFrameSize = std::max<unsigned int>(((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<ColorRgb> &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());
}

View File

@ -22,8 +22,8 @@ int LedDeviceAtmo::write(const std::vector<ColorRgb> &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

View File

@ -1,5 +1,6 @@
// Stl includes
#include <string>
#include <sstream>
#include <algorithm>
// Build configuration
@ -7,6 +8,7 @@
// Leddevice includes
#include <leddevice/LedDeviceFactory.h>
#include <utils/Logger.h>
// 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;
}

View File

@ -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<ColorRgb> & 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;
}

View File

@ -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<ColorRgb> &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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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<ColorRgb> &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<std::string> LedDeviceMultiLightpack::getLightpackSerials()
{
std::list<std::string> 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<std::string> 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<std::string> 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);
}
}

View File

@ -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"];

View File

@ -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<ColorRgb> & 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':

View File

@ -58,4 +58,5 @@ private:
/// File-Pointer to the PiBlaster device
FILE * _fid;
};

View File

@ -47,7 +47,7 @@ int LedDeviceSedu::write(const std::vector<ColorRgb> &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;
}
}

View File

@ -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<ColorRgb> &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;
}
}

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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;
}

View File

@ -6,9 +6,6 @@
// Qt includes
#include <QTimer>
// Serial includes
#include <serial/serial.h>
// 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<const char*>(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;
}

View File

@ -1,9 +1,7 @@
#pragma once
#include <QObject>
// Serial includes
#include <serial/serial.h>
#include <QSerialPort>
// Leddevice includes
#include <leddevice/LedDevice.h>
@ -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;
};

View File

@ -3,6 +3,7 @@
#include <cstring>
#include <cstdio>
#include <iostream>
#include <cerrno>
// Linux includes
#include <fcntl.h>
@ -10,6 +11,7 @@
// Local Hyperion includes
#include "LedSpiDevice.h"
#include <utils/Logger.h>
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;
}

View File

@ -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;

View File

@ -7,6 +7,7 @@
// Hyperion includes
#include <leddevice/LedDevice.h>
#include <utils/Logger.h>
///
/// The LedUdpDevice implements an abstract base-class for LedDevices using the SPI-device.

View File

@ -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

View File

@ -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})

View File

@ -0,0 +1,119 @@
// system includes
#include <stdexcept>
// project includes
#include <udplistener/UDPListener.h>
// 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);
}

View File

@ -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

View File

@ -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<std::string,Logger*> *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<std::string,Logger*>;
LoggerMap = new std::map<std::string,Logger*>;
}
if ( LoggerMap->find(name) == LoggerMap->end() )
{
Logger* log = new Logger(name,minLevel);
Logger::LoggerMap->insert(std::pair<std::string,Logger*>(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<std::string,Logger*>(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<std::string,Logger*>::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<unsigned int,Logger*>;
//
//
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);

View File

@ -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

View File

@ -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;

View File

@ -24,8 +24,6 @@ add_library(xbmcvideochecker
${XBMCVideoChecker_SOURCES}
)
qt5_use_modules(xbmcvideochecker Widgets)
target_link_libraries(xbmcvideochecker
hyperion
${QT_LIBRARIES})

View File

@ -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 )

View File

@ -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);

View File

@ -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 )

View File

@ -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);

View File

@ -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 )

View File

@ -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 )

View File

@ -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 )

View File

@ -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);

View File

@ -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 )

View File

@ -38,10 +38,10 @@ void saveScreenshot(void *, const Image<ColorRgb> & 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);

View File

@ -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 )

View File

@ -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);

View File

@ -9,6 +9,7 @@ target_link_libraries(hyperiond
effectengine
jsonserver
boblightserver
udplistener
protoserver
webconfig
bonjour

View File

@ -5,6 +5,9 @@
#include <QLocale>
#include <QFile>
#include <QHostInfo>
#include <QHostAddress>
#include <cstdint>
#include <limits>
#include "HyperionConfig.h"
@ -17,6 +20,7 @@
#include <jsonserver/JsonServer.h>
#include <protoserver/ProtoServer.h>
#include <boblightserver/BoblightServer.h>
#include <udplistener/UDPListener.h>
#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<int>::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()

View File

@ -39,6 +39,7 @@
#include <protoserver/ProtoServer.h>
#include <boblightserver/BoblightServer.h>
#include <webconfig/WebConfig.h>
#include <udplistener/UDPListener.h>
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;
};

View File

@ -11,8 +11,7 @@
#include <getoptPlusPlus/getoptpp.h>
#include <utils/Logger.h>
#include <webconfig/WebConfig.h>
#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<SwitchParameter<>> (0x0, "version", "Show version information");
IntParameter & argParentPid = parameters.add<IntParameter> (0x0, "parent", "pid of parent hyperiond");
SwitchParameter<> & argSilent = parameters.add<SwitchParameter<>> (0x0, "silent", "do not print any outputs");
SwitchParameter<> & argVerbose = parameters.add<SwitchParameter<>> (0x0, "verbose", "Increase verbosity");
SwitchParameter<> & argDebug = parameters.add<SwitchParameter<>> (0x0, "debug", "Show debug messages");
SwitchParameter<> & argHelp = parameters.add<SwitchParameter<>> ('h', "help", "Show this help message and exit");
argParentPid.setDefault(0);
optionParser.parse(argc, const_cast<const char **>(argv));
const std::vector<std::string> 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;
}