add Hue EntertainmentAPI + Forwarder & other Fixes (#592)

* whitespaces + typo fixes

* JS / LGTM fixes

* SSDP Handler crash fix

* MessageForwarder handlePriorityChanges Slave fixes

* use aboutToQuit Signal

* complete rewriten Hue Entertainment API structure
combined Philips Hue and Entertainment API
with new MbedTLS based SSL UDP Provider

* add required cross-compile submodules

* logical rebuild fn: initLeds, setLights + new logs
-more detailed checks and error handling inside iniLeds and setLights
- logical script procedure before ProviderUdpSSL init
- first steps for multiple ProviderUdpSSL usage
- better fallback support to old RestAPI, if entertainment api is not supported
- just 4 u LordGrey: new log fn for cosmetic config outputs ;)

* add OSX CompileHowTo - undo from CrossCompileHowTo

* whitespace fixes

* lightID toString fix

* fix unsigned int E-API + debug output

* bugfixes, reworked black signal detection, wizard:
- change device config field light-ids from int to string -> real unsigned int fix
- add signal detection brightness minimum threshold value
0.0 for 0% brightness - 1.0 for 100% brightness to count for blacklight signal detection
reason: input may not 100% black, like mine - i have a deep dark gray input signal
-> my threshold value is set to 0.005 for 0.5% minimum brightness = 1 (from max 255) to count as black
- wizard optimations, with fallback without entertainment support (beta state)
- whitespace fixes

* cleanup + minor fixes

* change fixed Hue UPD SSL config to _devConfig paras

* Hotfix SSL Connection, new light models, wizard:
- Fix UPD SSL Connection failed Problems
- add new supported gamut C light models: LCG002, LCA001, LCA002, LCA003
- wizard: extend fallback support to classic mode + hints

* whitespace, typo fix

* uncheck useEntertainmentAPI, if noAPISupport detected + hint

* coredump fix -> add _blackLightsTimer nullptr init

* code cleanup / remove old debugs + whitespacefixes

* add gamut C LCP001, LCP002

* SSL UDP config made more flexible + remove qDebug
-> switch to hyerion.ng _log
-> replace logCommand with verbose
-> code cleanups etc...

* extended mbedtls debugging infos

* add adjustable ssl timeout settings

* error handling

* streamdebugger bugfixes

* UPDSSL psk / psk_identity bugfixes! + hue wizard fn typo fix +
- verbose option available without dependencies
- whitespace fixes

* Philips Hue Assistant now recognizes non-original bridges better...
+ Added note if no clientkey is set when using the entertainment API
+ User creation (+ clientkey) for non-original bridges can now also be used
+ Minor changes and bug fixes

* CMAKE mbedTLS  detection

* minor bug fixes + code cleanups

* FindMbedTLS.cmake remove Path-Hints + wizard.js: ajax timeout handling
Test - content_grabber.js: run relevant code only, if V4L2_AVAIL is true:
conf_grabber don't displays other devices, if V4L2 is not available

* compile mbedtls via cmake as static lib

* remove libmbedtls-dev from compileHowto / scripts

* Fix Windows build

* Fix windows build (part 2)

* removed unnecessary osx x11 include directory path

* QTimer Shutdown bugfix

* cmake win32 fix + minor bugfixes

* cmake debug msg used mbedtls libs

* Bugfix: noSignalDetection wasn't switchedOn again
if no signal was previously detected

* Some code fixes based on alerts from lgtm.com

Co-authored-by: Paulchen Panther <16664240+Paulchen-Panther@users.noreply.github.com>
This commit is contained in:
SJunkies 2020-05-22 19:40:50 +02:00 committed by GitHub
parent 4aebd55715
commit 259becea04
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 3832 additions and 1302 deletions

View File

@ -46,6 +46,7 @@ SET ( DEFAULT_AVAHI ON )
SET ( DEFAULT_USE_SHARED_AVAHI_LIBS ON )
SET ( DEFAULT_USE_SYSTEM_FLATBUFFERS_LIBS OFF )
SET ( DEFAULT_USE_SYSTEM_PROTO_LIBS OFF )
SET ( DEFAULT_USE_SYSTEM_MBEDTLS_LIBS OFF )
SET ( DEFAULT_TESTS OFF )
IF ( ${CMAKE_SYSTEM} MATCHES "Linux" )
@ -190,7 +191,7 @@ SET ( FLATBUFFERS_INSTALL_LIB_DIR ${CMAKE_BINARY_DIR}/flatbuf )
SET ( PROTOBUF_INSTALL_BIN_DIR ${CMAKE_BINARY_DIR}/proto )
SET ( PROTOBUF_INSTALL_LIB_DIR ${CMAKE_BINARY_DIR}/proto )
# check all json files
# check all json files
FILE ( GLOB_RECURSE HYPERION_SCHEMAS RELATIVE ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/libsrc/*schema*.json )
SET( JSON_FILES
config/hyperion.config.json.default
@ -298,6 +299,8 @@ if(WIN32)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")
endif()
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -v")
# Use GNU gold linker if available
if (NOT WIN32)
include (${CMAKE_CURRENT_SOURCE_DIR}/cmake/LDGold.cmake)
@ -310,7 +313,7 @@ endif()
# setup -rpath to search for shared libs in BINARY/../lib folder
if (UNIX AND NOT APPLE)
SET(CMAKE_SKIP_BUILD_RPATH FALSE)
SET(CMAKE_SKIP_BUILD_RPATH FALSE)
SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_RPATH}:$ORIGIN/../lib")
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
@ -367,7 +370,6 @@ if (ENABLE_V4L2)
endif()
endif (TURBOJPEG_FOUND)
if (TURBOJPEG_FOUND OR JPEG_FOUND)
add_definitions(-DHAVE_JPEG_DECODER)
endif()

View File

@ -40,7 +40,7 @@ wget -qN https://raw.github.com/hyperion-project/hyperion.ng/master/bin/scripts/
```
sudo apt-get update
sudo apt-get install git cmake build-essential qtbase5-dev libqt5serialport5-dev libusb-1.0-0-dev python3-dev libxrender-dev libavahi-core-dev libavahi-compat-libdnssd-dev libjpeg-dev libturbojpeg0-dev libqt5sql5-sqlite libssl-dev
sudo apt-get install git cmake build-essential qtbase5-dev libqt5serialport5-dev libusb-1.0-0-dev python3-dev libxrender-dev libavahi-core-dev libavahi-compat-libdnssd-dev libjpeg-dev libturbojpeg0-dev libqt5sql5-sqlite libssl-dev zlib1g-dev
```
**on RPI you need the videocore IV headers**
@ -72,6 +72,7 @@ brew install python3
brew install cmake
brew install libusb
brew install doxygen
brew install zlib
```
## Windows (WIP)

View File

@ -4,14 +4,14 @@ Use a clean Raspbian Stretch Lite (on target) and Ubuntu 18/19 (on host) to exec
## On the Target system (here Raspberry Pi)
Install required additional packages.
```
sudo apt-get install qtbase5-dev libqt5serialport5-dev libusb-1.0-0-dev python3-dev libxrender-dev libavahi-core-dev libavahi-compat-libdnssd-dev libjpeg-dev libturbojpeg0-dev libqt5sql5-sqlite aptitude show qt5-default rsync
sudo apt-get install qtbase5-dev libqt5serialport5-dev libusb-1.0-0-dev python3-dev libxrender-dev libavahi-core-dev libavahi-compat-libdnssd-dev libjpeg-dev libturbojpeg0-dev libqt5sql5-sqlite aptitude qt5-default rsync libssl-dev zlib1g-dev
```
## On the Host system (here Ubuntu)
Update the Ubuntu environment to the latest stage and install required additional packages.
```
sudo apt-get update
sudo apt-get upgrade
sudo apt-get -qq -y install git rsync cmake build-essential qtbase5-dev libqt5serialport5-dev libusb-1.0-0-dev python3-dev libxrender-dev libavahi-core-dev libavahi-compat-libdnssd-dev libjpeg-dev libturbojpeg0-dev libqt5sql5-sqlite
sudo apt-get -qq -y install git rsync cmake build-essential qtbase5-dev libqt5serialport5-dev libusb-1.0-0-dev python3-dev libxrender-dev libavahi-core-dev libavahi-compat-libdnssd-dev libjpeg-dev libturbojpeg0-dev libqt5sql5-sqlite libssl-dev zlib1g-dev
```
Refine the target IP or hostname, plus userID as required and set-up cross-compilation environment:

View File

@ -159,9 +159,19 @@
"conf_leds_layout_preview_l1": "Das ist die erste LED (Einspeisung)",
"conf_leds_layout_preview_l2": "Das visualisiert die Richtung des Datenstroms (zweite/dritte LED)",
"conf_leds_layout_cl_top": "Oben",
"conf_leds_layout_cl_topleft": "Oben Links (Ecke)",
"conf_leds_layout_cl_topright": "Oben Rechts (Ecke)",
"conf_leds_layout_cl_bottom": "Unten",
"conf_leds_layout_cl_bottomleft": "Unten Links (Ecke)",
"conf_leds_layout_cl_bottomright": "Unten Rechts (Ecke)",
"conf_leds_layout_cl_left": "Links",
"conf_leds_layout_cl_lefttop": "Links 0% - 50% von Oben",
"conf_leds_layout_cl_leftmiddle": "Links 25% - 75% Mitte",
"conf_leds_layout_cl_leftbottom": "Links 50% - 100% Unten",
"conf_leds_layout_cl_right": "Rechts",
"conf_leds_layout_cl_righttop": "Rechts 0% - 50% von Oben",
"conf_leds_layout_cl_rightmiddle": "Rechts 25% - 75% Mitte",
"conf_leds_layout_cl_rightbottom": "Rechts 50% - 100% Unten",
"conf_leds_layout_cl_gaglength": "Lückenlänge",
"conf_leds_layout_cl_gappos": "Lückenposition",
"conf_leds_layout_cl_inppos": "Einspeisepunkt",
@ -356,6 +366,7 @@
"wiz_hue_desc2": "Nun kannst du auswählen, welche der Lampen (IDs) hinzugefügt werden sollen. Mit der Position wählst du aus, wo die jeweilige Lampe \"im Bild\" sitzen soll. Deaktivierte Lampen werden nicht hinzugefügt. Als Hilfe zur Identifizierung kannst du sie mit einem Klick auf den rechten Button kurz aufleuchten lassen.",
"wiz_hue_ip": "Hue Bridge IP:",
"wiz_hue_username": "Benutzer ID:",
"wiz_hue_clientkey": "Clientkey:",
"wiz_hue_create_user": "Neuen Benutzer erstellen",
"wiz_hue_failure_ip": "Keine Hue Bridge gefunden, bitte überprüfe die IP",
"wiz_hue_failure_connection": "Zeitüberschreitung. Bitte drücke die Taste auf deiner Hue Bridge rechtzeitig",
@ -368,6 +379,19 @@
"wiz_hue_searchb": "Suche nach Hue Bridge...",
"wiz_hue_blinkblue": "Lasse ID $1 blau aufleuchten",
"wiz_hue_ident": "Identifiziere",
"wiz_hue_e_create_user": "Neuen Benutzer und Clientkey erstellen",
"wiz_hue_e_clientkey_needed": "Für die Verwendung der Entertainment API, ist ein zum Usernamen passender Clientkey erforderlich. Bitte einen vorhandenen eingeben oder über die Schaltflächen unten einen neuen erstellen.",
"wiz_hue_e_use_groupid": "Gruppen ID $1 verwenden",
"wiz_hue_e_noegrpids": "Es wurden keine Entertainment Gruppen in dieser Hue Bridge gefunden.",
"wiz_hue_e_nogrpids": "Diese Hue Bridge hat keine definierten Gruppen, bitte erstelle zuvor wenigstens eine in der Hue App.",
"wiz_hue_e_noapisupport": "Der Assistent hat die Entertainment API Unterstützung deaktiviert und wird mit der klassischen API weitergeführt.",
"wiz_hue_e_noapisupport_hint": "Die Einstellung \"<b>Hue Entertainment API verwenden</b>\" wurde deaktiviert.",
"wiz_hue_e_title": "Philips Hue Entertainment Assistent",
"wiz_hue_e_intro1": "Dieser Assistent hilft dir bei der Konfiguration von Hyperion für Philips Hue Entertainment. Zu den Funktionen zählen ein automatisches finden der Hue Bridge, einen neuen Benutzer und dazugehörigen Clientkey zum verwenden der Entertainment API erstellen, eine Entertainment Gruppenauswahl und die zur Gruppe gehörenden Lampen unterschiedlichen Bereichen im Bild zuzuordnen, sowie weitere Einstellungen von Hyperion automatisch anzupassen. Kurz gesagt: Komplette Einrichtung mit ein paar Klicks.",
"wiz_hue_e_desc1": "Es wird automatisch nach der Hue Bridge gesucht, solltest sie nicht gefunden werden, gebe die IP an und drücke den \"neu laden\" Button. Danach benötigst du eine gültige Benutzer ID und den dazugehörigen Clientkey, damit die Entertainment API verwendet werden kann. Beides kann auch automatisch erstellt werden.",
"wiz_hue_e_desc2": "Nun kannst du die Entertainment Gruppe auswählen, welche die Lampen zur Verwendung mit Hyperion beinhaltet.",
"wiz_hue_e_desc3": "Nun kannst du auswählen, mit welcher Position die jeweilige Lampe \"im Bild\" sitzen soll. Eine Vorauswahl der Position, wurde Anhand der konfigurierten Positionen der Lampen in der Entertainment Gruppe gewählt. Dies ist nur eine Empfehlung und kann beliebig angepasst werden. Als Hilfe zur Identifizierung kannst du sie mit einem Klick auf den rechten Button kurz aufleuchten lassen und die Auswahl zu verbessern.",
"wiz_hue_e_use_group": "Gruppe verwenden",
"wiz_cc_title": "Farbkalibrierungs Assistent",
"wiz_cc_intro1": "Der Assistent wird dich durch die Kalibrierung deiner LEDs leiten. Sofern du Kodi nutzt, können die Bilder und Testvideos direkt an Kodi geschickt werden. Andernfalls musst du das Material selbst herunterladen und anwenden.",
"wiz_cc_kwebs": "Kodi Webserver (IP:Port)",
@ -424,9 +448,20 @@
"edt_dev_spec_lightid_title": "Lampen ID(s)",
"edt_dev_spec_lightid_itemtitle": "ID",
"edt_dev_spec_transistionTime_title": "Übergangszeit",
"edt_dev_spec_blackLightsTimeout_title": "Signal Erkennung Timeout bei schwarz",
"edt_dev_spec_brightnessThreshold_title": "Signal Erkennung Helligkeitsminimum",
"edt_dev_spec_switchOffOnBlack_title": "Aus bei schwarz",
"edt_dev_spec_brightnessFactor_title": "Helligkeitsfaktor",
"edt_dev_spec_restoreOriginalState_title" : "Lampen Originalzustand wiederhestellen",
"edt_dev_spec_brightnessMin_title": "Helligkeit minimum",
"edt_dev_spec_brightnessMax_title": "Helligkeit maximum",
"edt_dev_spec_sslReadTimeout_title" : "Streamer lese Timeout",
"edt_dev_spec_sslHSTimeoutMin_title" : "Streamer Handshake minimum Timeout",
"edt_dev_spec_sslHSTimeoutMax_title" : "Streamer Handshake maximum Timeout",
"edt_dev_spec_verbose_title": "Logge alle Hue Commandos",
"edt_dev_spec_debugStreamer_title": "Streamer Debugging",
"edt_dev_spec_debugLevel_title": "Streamer Verbindung Debug Stufe",
"edt_dev_spec_restoreOriginalState_title" : "Lampen Originalzustand wiederherstellen",
"edt_dev_spec_useEntertainmentAPI_title": "Hue Entertainment API verwenden",
"edt_dev_spec_ledType_title": "LED typ",
"edt_dev_spec_uid_title": "UID",
"edt_dev_spec_intervall_title": "Intervall",
@ -449,7 +484,9 @@
"edt_dev_spec_gpioBcm_title": "GPIO Pin",
"edt_dev_spec_ledIndex_title": "LED index",
"edt_dev_spec_colorComponent_title": "Farbkomponente",
"edt_dev_spec_clientKey_title": "Clientkey",
"edt_dev_spec_printTimeStamp_title" : "Mit Zeitstempel",
"edt_dev_spec_groupId_title": "Gruppen ID",
"edt_conf_general_enable_title": "Aktiviert",
"edt_conf_general_enable_expl": "Wenn aktiviert, ist die Komponente aktiv.",
"edt_conf_general_priority_title": "Priorität",
@ -479,6 +516,11 @@
"edt_conf_enum_bbclassic": "Klassisch",
"edt_conf_enum_bbosd": "OSD",
"edt_conf_enum_automatic": "Automatisch",
"edt_conf_enum_dl_nodebug": "kein Debugging",
"edt_conf_enum_dl_error": "nur Fehler",
"edt_conf_enum_dl_statechange": "bei Änderungen",
"edt_conf_enum_dl_informational": "informativ",
"edt_conf_enum_dl_verbose": "sehr detailiert",
"edt_conf_enum_custom": "Benutzerdefiniert",
"edt_conf_gen_heading_title": "Allgemeine Einstellungen",
"edt_conf_gen_name_title": "Name der Konfiguration",

View File

@ -157,10 +157,20 @@
"conf_leds_layout_preview_ledpower" : "Max. power consumption: $1 A",
"conf_leds_layout_preview_l1" : "This is your first led (input position)",
"conf_leds_layout_preview_l2" : "This visualizes the data direction (second/third led)",
"conf_leds_layout_cl_top" : "Top",
"conf_leds_layout_cl_bottom" : "Bottom",
"conf_leds_layout_cl_left" : "Left",
"conf_leds_layout_cl_right" : "Right",
"conf_leds_layout_cl_top": "Top",
"conf_leds_layout_cl_topleft": "Top Left (Corner)",
"conf_leds_layout_cl_topright": "Top Right (Corner)",
"conf_leds_layout_cl_bottom": "Bottom",
"conf_leds_layout_cl_bottomleft": "Bottom Left (Corner)",
"conf_leds_layout_cl_bottomright": "Bottom Right (Corner)",
"conf_leds_layout_cl_left": "Left",
"conf_leds_layout_cl_lefttop": "Left 0% - 50% Top",
"conf_leds_layout_cl_leftmiddle": "Left 25% - 75% Middle",
"conf_leds_layout_cl_leftbottom": "Left 50% - 100% Bottom",
"conf_leds_layout_cl_right": "Right",
"conf_leds_layout_cl_righttop": "Right 0% - 50% Top",
"conf_leds_layout_cl_rightmiddle": "Right 25% - 75% Middle",
"conf_leds_layout_cl_rightbottom": "Right 50% - 100% Bottom",
"conf_leds_layout_cl_gaglength" : "Gap length",
"conf_leds_layout_cl_gappos" : "gap position",
"conf_leds_layout_cl_inppos" : "Input position",
@ -355,6 +365,7 @@
"wiz_hue_desc2" : "Now choose which lamps should be added. The position assigns the lamp to a specific position on your \"picture\". Disabled lamps won't be added. To identify single lamps press the button on the right.",
"wiz_hue_ip" : "Hue Bridge IP:",
"wiz_hue_username" : "User ID:",
"wiz_hue_clientkey" : "Clientkey:",
"wiz_hue_create_user" : "Create new User",
"wiz_hue_failure_ip" : "No Bridge found, please type in a valid ip",
"wiz_hue_failure_connection" : "Timeout: Please press the bridge button within the period of 30 seconds",
@ -367,8 +378,21 @@
"wiz_hue_searchb": "Searching for bridge...",
"wiz_hue_blinkblue": "Let ID $1 light up blue",
"wiz_hue_ident" : "Identify",
"wiz_cc_title" : "Color calibration wizard",
"wiz_cc_intro1" : "This wizard will guide you through your led calibration. If you are using Kodi, the calibration pictures and videos can be send directly to kodi without further tasks on your side. If not, you need to download these files yourself and apply them, if the wizard wants it.",
"wiz_hue_e_create_user" : "Create new User and clientkey",
"wiz_hue_e_clientkey_needed": "A clientkey that matches the username is required to use the entertainment API. Please enter an existing one or use the button below to create a new one.",
"wiz_hue_e_use_groupid": "Use group ID $1",
"wiz_hue_e_noegrpids": "No entertainment groups in this Hue bridge defined.",
"wiz_hue_e_nogrpids": "This Hue bridge has no groups defined, please create at least one before with the Hue Apps.",
"wiz_hue_e_noapisupport": "The Wizard has disabled entertainment API support and will continue in classic mode.",
"wiz_hue_e_noapisupport_hint": "The option \"<b>Use Hue Entertainment API</b>\" was unchecked.",
"wiz_hue_e_title" : "Philips Hue Entertainment Wizard",
"wiz_hue_e_intro1" : "This wizards configures Hyperion for the well known Philips Hue Entertainment system. Features are Hue Bridge auto detection, user and clientkey creation, entertainment group selection and set group lights to a specific position on your picture and tune the Hyperion settings automatically! So in short: All you need are some clicks and you are done!",
"wiz_hue_e_desc1" : "It searches automatically for a hue bridge, in case it can't find one you need to provide the ip address and push the reload button on the right. Now you need a user id and the clientkey, if you don't have both, create a new one.",
"wiz_hue_e_desc2" : "Now choose your entertainment group, which has all your lights inside for use with Hyperion.",
"wiz_hue_e_desc3": "Now you can choose in which position the respective lamp should be \"in the picture\". A preselection of the position was made based on the configured positions of the lights in the entertainment group. This is just a recommendation and can be customized as desired. You can therefore highlight them briefly by clicking on the right button to improve the selection.",
"wiz_hue_e_use_group" : "Use group",
"wiz_cc_title" : "Colour calibration wizard",
"wiz_cc_intro1" : "This wizard will guide you through your led calibration. If you are using Kodi, the calibration pictures and videos can be sent directly to it without further actions on your side. If not, you will need to download these files yourself and display them when the wizard needs you to adjust the setting.",
"wiz_cc_kwebs" : "Kodi webserver (IP:Port)",
"wiz_cc_kodidiscon" : "Kodi webserver not found, proceed without Kodi support.",
"wiz_cc_kodidisconlink" : "Download link pictures:",
@ -422,10 +446,21 @@
"edt_dev_spec_username_title" : "Username",
"edt_dev_spec_lightid_title" : "Light ID(s)",
"edt_dev_spec_lightid_itemtitle" : "ID",
"edt_dev_spec_transistionTime_title" : "Transistion time",
"edt_dev_spec_transistionTime_title" : "Transition time",
"edt_dev_spec_blackLightsTimeout_title": "Signal detection timeout on black",
"edt_dev_spec_brightnessThreshold_title": "Signal detection brightness minimum",
"edt_dev_spec_switchOffOnBlack_title" : "Switch off on black",
"edt_dev_spec_brightnessFactor_title" : "Brightness factor",
"edt_dev_spec_brightnessMin_title": "Brightness minimum",
"edt_dev_spec_brightnessMax_title": "Brightness maximum",
"edt_dev_spec_sslReadTimeout_title" : "Streamer read timeout",
"edt_dev_spec_sslHSTimeoutMin_title" : "Streamer handshake timeout minimum",
"edt_dev_spec_sslHSTimeoutMax_title" : "Streamer handshake timeout maximum",
"edt_dev_spec_verbose_title": "Log all Hue commands",
"edt_dev_spec_debugStreamer_title": "Streamer Debug",
"edt_dev_spec_debugLevel_title": "Streamer Connection Debug Level",
"edt_dev_spec_restoreOriginalState_title" : "Restore lights' original state",
"edt_dev_spec_useEntertainmentAPI_title": "Use Hue Entertainment API",
"edt_dev_spec_ledType_title" : "LED Type",
"edt_dev_spec_uid_title" : "UID",
"edt_dev_spec_intervall_title" : "Intervall",
@ -447,7 +482,10 @@
"edt_dev_spec_PBFiFo_title" : "Pi-Blaster FiFo",
"edt_dev_spec_gpioBcm_title" : "GPIO Pin",
"edt_dev_spec_ledIndex_title" : "LED index",
"edt_dev_spec_colorComponent_title" : "Color component",
"edt_dev_spec_colorComponent_title" : "Colour component",
"edt_dev_spec_printTimeStamp_title" : "Add timestamp",
"edt_dev_spec_clientKey_title" : "Clientkey",
"edt_dev_spec_groupId_title" : "Group Id",
"edt_conf_general_enable_title" : "Activate",
"edt_conf_general_enable_expl" : "If checked, the component is enabled.",
"edt_conf_general_priority_title" : "Priority channel",
@ -477,6 +515,11 @@
"edt_conf_enum_bbclassic" : "Classic",
"edt_conf_enum_bbosd" : "OSD",
"edt_conf_enum_automatic" : "Automatic",
"edt_conf_enum_dl_nodebug": "No Debug",
"edt_conf_enum_dl_error": "Error",
"edt_conf_enum_dl_statechange": "State Change",
"edt_conf_enum_dl_informational": "Informational",
"edt_conf_enum_dl_verbose": "Verbose",
"edt_conf_enum_custom": "Custom",
"edt_conf_gen_heading_title" : "General Settings",
"edt_conf_gen_name_title" : "Configuration name",

View File

@ -180,9 +180,11 @@ $(document).ready( function() {
//create introduction
if(window.showOptHelp)
{
createHint("intro", $.i18n('conf_general_intro'), "editor_container");
createHint("intro", $.i18n('conf_general_tok_desc'), "tok_desc_cont");
createHint("intro", $.i18n('conf_general_inst_desc'), "inst_desc_cont");
}
removeOverlay();
});

View File

@ -1,205 +1,207 @@
$(document).ready( function() {
performTranslation();
var conf_editor_v4l2 = null;
var conf_editor_fg = null;
performTranslation();
var conf_editor_v4l2 = null;
var conf_editor_fg = null;
var conf_editor_instCapt = null;
var V4L2_AVAIL = window.serverInfo.grabbers.available.includes("v4l2");
// Dynamic v4l2 enum schema
var v4l2_dynamic_enum_schema = {
"available_devices":
{
"type": "string",
"title": "edt_conf_v4l2_device_title",
"propertyOrder" : 1,
"required" : true
},
"resolutions":
{
"type": "string",
"title": "edt_conf_v4l2_resolution_title",
"propertyOrder" : 4,
"required" : true
},
"framerates":
{
"type": "string",
"title": "edt_conf_v4l2_framerate_title",
"propertyOrder" : 7,
"required" : true
}
};
if(V4L2_AVAIL) {
// Dynamic v4l2 enum schema
var v4l2_dynamic_enum_schema = {
"available_devices":
{
"type": "string",
"title": "edt_conf_v4l2_device_title",
"propertyOrder" : 1,
"required" : true
},
"resolutions":
{
"type": "string",
"title": "edt_conf_v4l2_resolution_title",
"propertyOrder" : 4,
"required" : true
},
"framerates":
{
"type": "string",
"title": "edt_conf_v4l2_framerate_title",
"propertyOrder" : 7,
"required" : true
}
};
// Build dynamic v4l2 enum schema parts
var buildSchemaPart = function(key, schema, device) {
if (schema[key]) {
var enumVals = [];
var enumTitelVals = [];
var v4l2_properties = JSON.parse(JSON.stringify(window.serverInfo.grabbers.v4l2_properties));
// Build dynamic v4l2 enum schema parts
var buildSchemaPart = function(key, schema, device) {
if (schema[key]) {
var enumVals = [];
var enumTitelVals = [];
var v4l2_properties = JSON.parse(JSON.stringify(window.serverInfo.grabbers.v4l2_properties));
if (key === 'available_devices') {
for (var i = 0; i < v4l2_properties.length; i++) {
enumVals.push(v4l2_properties[i]['device']);
if (key === 'available_devices') {
for (var i = 0; i < v4l2_properties.length; i++) {
enumVals.push(v4l2_properties[i]['device']);
v4l2_properties[i].hasOwnProperty('name')
? enumTitelVals.push(v4l2_properties[i]['name'])
: enumTitelVals.push(v4l2_properties[i]['device']);
}
} else if (key == 'resolutions' || key == 'framerates') {
for (var i = 0; i < v4l2_properties.length; i++) {
if (v4l2_properties[i]['device'] == device) {
enumVals = enumTitelVals = v4l2_properties[i][key];
break;
}
}
}
v4l2_properties[i].hasOwnProperty('name')
? enumTitelVals.push(v4l2_properties[i]['name'])
: enumTitelVals.push(v4l2_properties[i]['device']);
}
} else if (key == 'resolutions' || key == 'framerates') {
for (var i = 0; i < v4l2_properties.length; i++) {
if (v4l2_properties[i]['device'] == device) {
enumVals = enumTitelVals = v4l2_properties[i][key];
break;
}
}
}
window.schema.grabberV4L2.properties[key] = {
"type": schema[key].type,
"title": schema[key].title,
"enum": [].concat(["auto"], enumVals, ["custom"]),
"options" :
{
"enum_titles" : [].concat(["edt_conf_enum_automatic"], enumTitelVals, ["edt_conf_enum_custom"]),
},
"propertyOrder" : schema[key].propertyOrder,
"required" : schema[key].required
};
}
};
window.schema.grabberV4L2.properties[key] = {
"type": schema[key].type,
"title": schema[key].title,
"enum": [].concat(["auto"], enumVals, ["custom"]),
"options" :
{
"enum_titles" : [].concat(["edt_conf_enum_automatic"], enumTitelVals, ["edt_conf_enum_custom"]),
},
"propertyOrder" : schema[key].propertyOrder,
"required" : schema[key].required
};
}
};
// Switch between visible states
function toggleOption(option, state) {
$('[data-schemapath*="root.grabberV4L2.'+option+'"]').toggle(state);
if (state) (
$('[data-schemapath*="root.grabberV4L2.'+option+'"]').addClass('col-md-12'),
$('label[for="root_grabberV4L2_'+option+'"]').css('left','10px'),
$('[id="root_grabberV4L2_'+option+'"]').css('left','10px')
);
}
// Switch between visible states
function toggleOption(option, state) {
$('[data-schemapath*="root.grabberV4L2.'+option+'"]').toggle(state);
if (state) (
$('[data-schemapath*="root.grabberV4L2.'+option+'"]').addClass('col-md-12'),
$('label[for="root_grabberV4L2_'+option+'"]').css('left','10px'),
$('[id="root_grabberV4L2_'+option+'"]').css('left','10px')
);
}
// Watch all v4l2 dynamic fields
var setWatchers = function(schema) {
var path = 'root.grabberV4L2.';
Object.keys(schema).forEach(function(key) {
conf_editor_v4l2.watch(path + key, function() {
var ed = conf_editor_v4l2.getEditor(path + key);
var val = ed.getValue();
// Watch all v4l2 dynamic fields
var setWatchers = function(schema) {
var path = 'root.grabberV4L2.';
Object.keys(schema).forEach(function(key) {
conf_editor_v4l2.watch(path + key, function() {
var ed = conf_editor_v4l2.getEditor(path + key);
var val = ed.getValue();
if (key == 'available_devices') {
var V4L2properties = ['resolutions', 'framerates'];
if (val == 'custom') {
var grabberV4L2 = ed.parent;
V4L2properties.forEach(function(item) {
buildSchemaPart(item, v4l2_dynamic_enum_schema, 'none');
grabberV4L2.original_schema.properties[item] = window.schema.grabberV4L2.properties[item];
grabberV4L2.schema.properties[item] = window.schema.grabberV4L2.properties[item];
if (key == 'available_devices') {
var V4L2properties = ['resolutions', 'framerates'];
if (val == 'custom') {
var grabberV4L2 = ed.parent;
V4L2properties.forEach(function(item) {
buildSchemaPart(item, v4l2_dynamic_enum_schema, 'none');
grabberV4L2.original_schema.properties[item] = window.schema.grabberV4L2.properties[item];
grabberV4L2.schema.properties[item] = window.schema.grabberV4L2.properties[item];
grabberV4L2.removeObjectProperty(item);
delete grabberV4L2.cached_editors[item];
grabberV4L2.addObjectProperty(item);
grabberV4L2.removeObjectProperty(item);
delete grabberV4L2.cached_editors[item];
grabberV4L2.addObjectProperty(item);
conf_editor_v4l2.getEditor(path + item).enable();
});
conf_editor_v4l2.getEditor(path + item).enable();
});
toggleOption('device', true);
} else if (val == 'auto') {
V4L2properties.forEach(function(item) {
conf_editor_v4l2.getEditor(path + item).setValue('auto');
conf_editor_v4l2.getEditor(path + item).disable();
});
toggleOption('device', true);
} else if (val == 'auto') {
V4L2properties.forEach(function(item) {
conf_editor_v4l2.getEditor(path + item).setValue('auto');
conf_editor_v4l2.getEditor(path + item).disable();
});
(toggleOption('device', false), toggleOption('width', false),
toggleOption('height', false), toggleOption('fps', false));
} else {
var grabberV4L2 = ed.parent;
V4L2properties.forEach(function(item) {
buildSchemaPart(item, v4l2_dynamic_enum_schema, val);
grabberV4L2.original_schema.properties[item] = window.schema.grabberV4L2.properties[item];
grabberV4L2.schema.properties[item] = window.schema.grabberV4L2.properties[item];
(toggleOption('device', false), toggleOption('width', false),
toggleOption('height', false), toggleOption('fps', false));
} else {
var grabberV4L2 = ed.parent;
V4L2properties.forEach(function(item) {
buildSchemaPart(item, v4l2_dynamic_enum_schema, val);
grabberV4L2.original_schema.properties[item] = window.schema.grabberV4L2.properties[item];
grabberV4L2.schema.properties[item] = window.schema.grabberV4L2.properties[item];
grabberV4L2.removeObjectProperty(item);
delete grabberV4L2.cached_editors[item];
grabberV4L2.addObjectProperty(item);
grabberV4L2.removeObjectProperty(item);
delete grabberV4L2.cached_editors[item];
grabberV4L2.addObjectProperty(item);
conf_editor_v4l2.getEditor(path + item).enable();
});
conf_editor_v4l2.getEditor(path + item).enable();
});
toggleOption('device', false);
}
}
toggleOption('device', false);
}
}
if (key == 'resolutions')
val != 'custom'
? (toggleOption('width', false), toggleOption('height', false))
: (toggleOption('width', true), toggleOption('height', true));
if (key == 'resolutions')
val != 'custom'
? (toggleOption('width', false), toggleOption('height', false))
: (toggleOption('width', true), toggleOption('height', true));
if (key == 'framerates')
val != 'custom'
? toggleOption('fps', false)
: toggleOption('fps', true);
});
});
};
if (key == 'framerates')
val != 'custom'
? toggleOption('fps', false)
: toggleOption('fps', true);
});
});
};
// Insert dynamic v4l2 enum schema parts
Object.keys(v4l2_dynamic_enum_schema).forEach(function(key) {
buildSchemaPart(key, v4l2_dynamic_enum_schema, window.serverConfig.grabberV4L2.device);
});
// Insert dynamic v4l2 enum schema parts
Object.keys(v4l2_dynamic_enum_schema).forEach(function(key) {
buildSchemaPart(key, v4l2_dynamic_enum_schema, window.serverConfig.grabberV4L2.device);
});
}
if(window.showOptHelp) {
// Instance Capture
$('#conf_cont').append(createRow('conf_cont_instCapt'));
$('#conf_cont_instCapt').append(createOptPanel('fa-camera', $.i18n("edt_conf_instCapture_heading_title"), 'editor_container_instCapt', 'btn_submit_instCapt'));
$('#conf_cont_instCapt').append(createHelpTable(window.schema.instCapture.properties, $.i18n("edt_conf_instCapture_heading_title")));
if(window.showOptHelp) {
// Instance Capture
$('#conf_cont').append(createRow('conf_cont_instCapt'));
$('#conf_cont_instCapt').append(createOptPanel('fa-camera', $.i18n("edt_conf_instCapture_heading_title"), 'editor_container_instCapt', 'btn_submit_instCapt'));
$('#conf_cont_instCapt').append(createHelpTable(window.schema.instCapture.properties, $.i18n("edt_conf_instCapture_heading_title")));
// Framegrabber
$('#conf_cont').append(createRow('conf_cont_fg'));
$('#conf_cont_fg').append(createOptPanel('fa-camera', $.i18n("edt_conf_fg_heading_title"), 'editor_container_fg', 'btn_submit_fg'));
$('#conf_cont_fg').append(createHelpTable(window.schema.framegrabber.properties, $.i18n("edt_conf_fg_heading_title")));
// Framegrabber
$('#conf_cont').append(createRow('conf_cont_fg'));
$('#conf_cont_fg').append(createOptPanel('fa-camera', $.i18n("edt_conf_fg_heading_title"), 'editor_container_fg', 'btn_submit_fg'));
$('#conf_cont_fg').append(createHelpTable(window.schema.framegrabber.properties, $.i18n("edt_conf_fg_heading_title")));
// V4L2 - hide if not available
if(V4L2_AVAIL){
if(V4L2_AVAIL) {
$('#conf_cont').append(createRow('conf_cont_v4l'));
$('#conf_cont_v4l').append(createOptPanel('fa-camera', $.i18n("edt_conf_v4l2_heading_title"), 'editor_container_v4l2', 'btn_submit_v4l2'));
$('#conf_cont_v4l').append(createHelpTable(window.schema.grabberV4L2.properties, $.i18n("edt_conf_v4l2_heading_title")));
}
} else {
$('#conf_cont').addClass('row');
$('#conf_cont').append(createOptPanel('fa-camera', $.i18n("edt_conf_instCapture_heading_title"), 'editor_container_instCapt', 'btn_submit_instCapt'));
} else {
$('#conf_cont').addClass('row');
$('#conf_cont').append(createOptPanel('fa-camera', $.i18n("edt_conf_instCapture_heading_title"), 'editor_container_instCapt', 'btn_submit_instCapt'));
$('#conf_cont').append(createOptPanel('fa-camera', $.i18n("edt_conf_fg_heading_title"), 'editor_container_fg', 'btn_submit_fg'));
if(V4L2_AVAIL){
if(V4L2_AVAIL) {
$('#conf_cont').append(createOptPanel('fa-camera', $.i18n("edt_conf_v4l2_heading_title"), 'editor_container_v4l2', 'btn_submit_v4l2'));
}
}
}
// Instance Capture
conf_editor_instCapt = createJsonEditor('editor_container_instCapt', {
instCapture: window.schema.instCapture
}, true, true);
// Instance Capture
conf_editor_instCapt = createJsonEditor('editor_container_instCapt', {
instCapture: window.schema.instCapture
}, true, true);
conf_editor_instCapt.on('change',function() {
conf_editor_instCapt.validate().length ? $('#btn_submit_instCapt').attr('disabled', true) : $('#btn_submit_instCapt').attr('disabled', false);
});
conf_editor_instCapt.on('change',function() {
conf_editor_instCapt.validate().length ? $('#btn_submit_instCapt').attr('disabled', true) : $('#btn_submit_instCapt').attr('disabled', false);
});
$('#btn_submit_instCapt').off().on('click',function() {
requestWriteConfig(conf_editor_instCapt.getValue());
});
$('#btn_submit_instCapt').off().on('click',function() {
requestWriteConfig(conf_editor_instCapt.getValue());
});
// Framegrabber
conf_editor_fg = createJsonEditor('editor_container_fg', {
framegrabber: window.schema.framegrabber
}, true, true);
// Framegrabber
conf_editor_fg = createJsonEditor('editor_container_fg', {
framegrabber: window.schema.framegrabber
}, true, true);
conf_editor_fg.on('change',function() {
conf_editor_fg.validate().length ? $('#btn_submit_fg').attr('disabled', true) : $('#btn_submit_fg').attr('disabled', false);
});
conf_editor_fg.on('change',function() {
conf_editor_fg.validate().length ? $('#btn_submit_fg').attr('disabled', true) : $('#btn_submit_fg').attr('disabled', false);
});
$('#btn_submit_fg').off().on('click',function() {
requestWriteConfig(conf_editor_fg.getValue());
});
$('#btn_submit_fg').off().on('click',function() {
requestWriteConfig(conf_editor_fg.getValue());
});
if(V4L2_AVAIL){
if(V4L2_AVAIL) {
conf_editor_v4l2 = createJsonEditor('editor_container_v4l2', {
grabberV4L2 : window.schema.grabberV4L2
}, true, true);
@ -258,35 +260,35 @@ $(document).ready( function() {
});
}
//////////////////////////////////////////////////
//////////////////////////////////////////////////
//create introduction
if(window.showOptHelp) {
//create introduction
if(window.showOptHelp) {
createHint("intro", $.i18n('conf_grabber_fg_intro'), "editor_container_fg");
if(V4L2_AVAIL){
createHint("intro", $.i18n('conf_grabber_v4l_intro'), "editor_container_v4l2");
}
}
}
function hideEl(el) {
for(var i = 0; i<el.length; i++) {
$('[data-schemapath*="root.framegrabber.'+el[i]+'"]').toggle(false);
}
}
function hideEl(el) {
for(var i = 0; i<el.length; i++) {
$('[data-schemapath*="root.framegrabber.'+el[i]+'"]').toggle(false);
}
}
//hide specific options
conf_editor_fg.on('ready',function() {
var grabbers = window.serverInfo.grabbers.available;
//hide specific options
conf_editor_fg.on('ready',function() {
var grabbers = window.serverInfo.grabbers.available;
if (grabbers.indexOf('dispmanx') > -1)
hideEl(["device","pixelDecimation"]);
else if (grabbers.indexOf('x11') > -1)
hideEl(["device","width","height"]);
else if (grabbers.indexOf('osx') > -1 )
hideEl(["device","pixelDecimation"]);
else if (grabbers.indexOf('amlogic') > -1)
hideEl(["pixelDecimation"]);
});
if (grabbers.indexOf('dispmanx') > -1)
hideEl(["device","pixelDecimation"]);
else if (grabbers.indexOf('x11') > -1)
hideEl(["device","width","height"]);
else if (grabbers.indexOf('osx') > -1 )
hideEl(["device","pixelDecimation"]);
else if (grabbers.indexOf('amlogic') > -1)
hideEl(["pixelDecimation"]);
});
removeOverlay();
removeOverlay();
});

View File

@ -163,7 +163,6 @@ $(document).ready(function () {
requestTokenAuthorization(loginToken)
else
loadContentTo("#page-content", "login")
}
});

View File

@ -39,12 +39,12 @@ function createLedPreview(leds, origin){
{
var led = leds[idx];
var led_id='ledc_'+[idx];
var bgcolor = "background-color:hsl("+(idx*360/leds.length)+",100%,50%);";
var bgcolor = "background-color:hsla("+(idx*360/leds.length)+",100%,50%,0.75);";
var pos = "left:"+(led.hmin * canvas_width)+"px;"+
"top:"+(led.vmin * canvas_height)+"px;"+
"width:"+((led.hmax-led.hmin) * (canvas_width-1))+"px;"+
"height:"+((led.vmax-led.vmin) * (canvas_height-1))+"px;";
leds_html += '<div id="'+led_id+'" class="led" style="'+bgcolor+pos+'" title="'+idx+'"><span id="'+led_id+'_num" class="led_prev_num">'+idx+'</span></div>';
leds_html += '<div id="'+led_id+'" class="led" style="'+bgcolor+pos+'" title="'+idx+'"><span id="'+led_id+'_num" class="led_prev_num">'+((led.name) ? led.name : idx)+'</span></div>';
}
$('#leds_preview').html(leds_html);
$('#ledc_0').css({"background-color":"black","z-index":"12"});
@ -496,9 +496,13 @@ $(document).ready(function() {
$("#leddevices").off().on("change", function() {
var generalOptions = window.serverSchema.properties.device;
// Modified schema enty "hardwareLedCount" in generalOptions to minimum LedCount
// Modified schema entry "hardwareLedCount" in generalOptions to minimum LedCount
var ledType = $(this).val();
var specificOptions = window.serverSchema.properties.alldevices[$(this).val()];
//philipshueentertainment backward fix
if(ledType == "philipshueentertainment") ledType = "philipshue";
var specificOptions = window.serverSchema.properties.alldevices[ledType];
conf_editor = createJsonEditor('editor_container', {
generalOptions : generalOptions,
specificOptions : specificOptions,
@ -506,21 +510,19 @@ $(document).ready(function() {
var values_general = {};
var values_specific = {};
var isCurrentDevice = (window.serverConfig.device.type == $(this).val());
var isCurrentDevice = (window.serverConfig.device.type == ledType);
for(var key in window.serverConfig.device){
if (key != "type" && key in generalOptions.properties)
values_general[key] = window.serverConfig.device[key];
for(var key in window.serverConfig.device) {
if (key != "type" && key in generalOptions.properties) values_general[key] = window.serverConfig.device[key];
};
conf_editor.getEditor("root.generalOptions").setValue( values_general );
if (isCurrentDevice)
{
var specificOptions_val = conf_editor.getEditor("root.specificOptions").getValue()
var specificOptions_val = conf_editor.getEditor("root.specificOptions").getValue();
for(var key in specificOptions_val){
values_specific[key] = (key in window.serverConfig.device) ? window.serverConfig.device[key] : specificOptions_val[key];
values_specific[key] = (key in window.serverConfig.device) ? window.serverConfig.device[key] : specificOptions_val[key];
};
conf_editor.getEditor("root.specificOptions").setValue( values_specific );
};
@ -528,18 +530,29 @@ $(document).ready(function() {
conf_editor.validate().length ? $('#btn_submit_controller').attr('disabled', true) : $('#btn_submit_controller').attr('disabled', false);
// led controller sepecific wizards
if($(this).val() == "philipshue")
{
createHint("wizard", $.i18n('wiz_hue_title'), "btn_wiz_holder","btn_led_device_wiz");
$('#btn_led_device_wiz').off().on('click',startWizardPhilipsHue);
}
else
{
$('#btn_wiz_holder').html("")
$('#btn_led_device_wiz').off();
}
$('#btn_wiz_holder').html("")
$('#btn_led_device_wiz').off();
if(ledType == "philipshue") {
$('#root_specificOptions_useEntertainmentAPI').bind("change", function() {
var ledWizardType = (this.checked) ? "philipshueentertainment" : ledType;
var data = { type: ledWizardType };
var hue_title = (this.checked) ? 'wiz_hue_e_title' : 'wiz_hue_title';
changeWizard(data, hue_title, startWizardPhilipsHue);
});
$("#root_specificOptions_useEntertainmentAPI").trigger("change");
}
function changeWizard(data, hint, fn) {
$('#btn_wiz_holder').html("")
createHint("wizard", $.i18n(hint), "btn_wiz_holder","btn_led_device_wiz");
$('#btn_led_device_wiz').off().on('click', data , fn);
}
});
//philipshueentertainment backward fix
if(window.serverConfig.device.type == "philipshueentertainment") window.serverConfig.device.type = "philipshue";
// create led device selection
var ledDevices = window.serverInfo.ledDevices.available;
var devRPiSPI = ['apa102', 'apa104', 'ws2801', 'lpd6803', 'lpd8806', 'p9813', 'sk6812spi', 'sk6822spi', 'ws2812spi'];

View File

@ -147,15 +147,19 @@ $(document).ready(function() {
//roundRect(ledsCanvasNodeCtx, led.hmin * canvas_width, led.vmin * canvas_height, (led.hmax-led.hmin) * canvas_width, (led.vmax-led.vmin) * canvas_height, 4, true, colors[idx])
//ledsCanvasNodeCtx.fillRect(led.hmin * canvas_width, led.vmin * canvas_height, (led.hmax-led.hmin) * canvas_width, (led.vmax-led.vmin) * canvas_height);
ledsCanvasNodeCtx.fillStyle = (useColor) ? "rgba("+colors[cPos]+","+colors[cPos+1]+","+colors[cPos+2]+",0.9)" : "hsl("+(idx*360/leds.length)+",100%,50%)";
ledsCanvasNodeCtx.fillStyle = (useColor) ? "rgba("+colors[cPos]+","+colors[cPos+1]+","+colors[cPos+2]+",0.75)" : "hsla("+(idx*360/leds.length)+",100%,50%,0.75)";
ledsCanvasNodeCtx.fill(twoDPaths[idx]);
ledsCanvasNodeCtx.stroke(twoDPaths[idx]);
if(toggleLedsNum)
{
ledsCanvasNodeCtx.fillStyle = "blue";
//ledsCanvasNodeCtx.shadowOffsetX = 1;
//ledsCanvasNodeCtx.shadowOffsetY = 1;
//ledsCanvasNodeCtx.shadowColor = "black";
//ledsCanvasNodeCtx.shadowBlur = 4;
ledsCanvasNodeCtx.fillStyle = "white";
ledsCanvasNodeCtx.textAlign = "center";
ledsCanvasNodeCtx.fillText(idx, (led.hmin * canvas_width) + ( ((led.hmax-led.hmin) * canvas_width) / 2), (led.vmin * canvas_height) + ( ((led.vmax-led.vmin) * canvas_height) / 2));
ledsCanvasNodeCtx.fillText(((led.name) ? led.name : idx), (led.hmin * canvas_width) + ( ((led.hmax-led.hmin) * canvas_width) / 2), (led.vmin * canvas_height) + ( ((led.vmax-led.vmin) * canvas_height) / 2));
}
// increment colorsPosition

View File

@ -247,7 +247,7 @@
String.locale = String.locale || $( 'html' ).attr( 'lang' );
if ( !String.locale ) {
if ( typeof window.navigator !== undefined ) {
if ( typeof window.navigator !== 'undefined' ) {
nav = window.navigator;
String.locale = nav.language || nav.userLanguage || '';
} else {

View File

@ -360,7 +360,7 @@
// Check if the restore to Latin number flag is set:
if ( integer ) {
if ( parseFloat( num, 10 ) === num ) {
if ( parseFloat( num ) === num ) {
return num;
}
@ -381,7 +381,7 @@
}
}
return integer ? parseFloat( convertedNumber, 10 ) : convertedNumber;
return integer ? parseFloat( convertedNumber ) : convertedNumber;
},
/**

View File

@ -157,20 +157,16 @@ $(document).ready( function() {
{
if(lsys != window.wSess[i].host+':'+window.wSess[i].port)
{
var hyperionAddress
if (window.wSess[i].address.indexOf(':') > -1 && window.wSess[i].address.length == 36)
hyperionAddress = 'http://['+window.wSess[i].address+']:'+window.wSess[i].port
else
hyperionAddress = 'http://'+window.wSess[i].address+':'+window.wSess[i].port
$('#id_select').append(createSelOpt(hyperionAddress, window.wSess[i].host))
var hyperionAddress = window.wSess[i].address;
if(hyperionAddress.indexOf(':') > -1 && hyperionAddress.length == 36) hyperionAddress = '['+hyperionAddress+']';
hyperionAddress = 'http://'+hyperionAddress+':'+window.wSess[i].port;
$('#id_select').append(createSelOpt(hyperionAddress, window.wSess[i].name));
}
}
$('#id_btn_saveset').off().on('click',function() {
$("#loading_overlay").addClass("overlay");
window.location.href = $('#id_select').val()
window.location.href = $('#id_select').val();
});
});

View File

@ -2,7 +2,7 @@ $(document).ready( function() {
// check if browser supports streaming
if(window.navigator.mediaDevices && window.navigator.mediaDevices.getDisplayMedia){
$("#btn_streamer").toggle()
$("#btn_streamer").toggle();
}
// variables

View File

@ -109,7 +109,7 @@ function loadContent(event, forceRefresh)
var lastSelectedInstance = getStorage('lastSelectedInstance', false);
if (lastSelectedInstance && (lastSelectedInstance != window.currentHyperionInstance))
if (typeof(window.serverInfo.instance[lastSelectedInstance].running) !== 'undefined' && window.serverInfo.instance[lastSelectedInstance].running)
if (typeof(window.serverInfo.instance[lastSelectedInstance].running) !== 'undefined' && window.serverInfo.instance[lastSelectedInstance].running)
instanceSwitch(lastSelectedInstance);
else
removeStorage('lastSelectedInstance', false);
@ -890,12 +890,12 @@ function getReleases(callback)
continue;
if(releases[i].tag_name.includes('alpha'))
{
{
if (sem = semverLite.gt(releases[i].tag_name, highestAlphaRelease.tag_name))
highestAlphaRelease = releases[i];
highestAlphaRelease = releases[i];
}
else if (releases[i].tag_name.includes('beta'))
{
{
if (sem = semverLite.gt(releases[i].tag_name, highestBetaRelease.tag_name))
highestBetaRelease = releases[i];
}
@ -907,7 +907,7 @@ function getReleases(callback)
else
{
if (semverLite.gt(releases[i].tag_name, highestRelease.tag_name))
highestRelease = releases[i];
highestRelease = releases[i];
}
}
window.latestStableVersion = highestRelease;
@ -915,7 +915,7 @@ function getReleases(callback)
window.latestAlphaVersion= highestAlphaRelease;
window.latestRcVersion = highestRcRelease;
if(window.serverConfig.general.watchedVersionBranch == "Beta" && semverLite.gt(highestBetaRelease.tag_name, highestRelease.tag_name))
window.latestVersion = highestBetaRelease;
else
@ -951,4 +951,4 @@ function handleDarkMode()
setStorage("darkMode", "on", false);
$('#btn_darkmode_icon').removeClass('fa fa-moon-o');
$('#btn_darkmode_icon').addClass('fa fa-sun-o');
}
}

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,7 @@ CFG="${2:-Release}"
INST="$( [ "${3:-}" = "install" ] && echo true || echo false )"
sudo apt-get update
sudo apt-get install git cmake build-essential qtbase5-dev libqt5serialport5-dev libusb-1.0-0-dev libturbojpeg0-dev python3-dev libxrender-dev libavahi-core-dev libavahi-compat-libdnssd-dev libssl-dev || exit 1
sudo apt-get install git cmake build-essential qtbase5-dev libqt5serialport5-dev libusb-1.0-0-dev libturbojpeg0-dev python3-dev libxrender-dev libavahi-core-dev libavahi-compat-libdnssd-dev libssl-dev libjpeg-dev libqt5sql5-sqlite zlib1g-dev || exit 1
if [ -e /dev/vc-cma -a -e /dev/vc-mem ]
then

View File

@ -19,7 +19,7 @@ fi
#Welcome message
echo '*******************************************************************************'
echo 'This script will remove Hyperion and it´s services'
echo 'This script will remove Hyperion and its services'
echo '-----> Please BACKUP your hyperion.config.json if necessary <-----'
echo 'Created by brindosch - hyperion-project.org - the official Hyperion source.'
echo '*******************************************************************************'
@ -29,7 +29,7 @@ if [ "$1" = "" ]; then
#Prompt for confirmation to proceed
while true
do
echo -n "---> Do you really want to remove Hyperion and it´s services? (y or n) :"
echo -n "---> Do you really want to remove Hyperion and its services? (y or n) :"
read CONFIRM
case $CONFIRM in
y|Y|YES|yes|Yes) break ;;

25
cmake/Findmbedtls.cmake Normal file
View File

@ -0,0 +1,25 @@
find_path(MBEDTLS_INCLUDE_DIR mbedtls/ssl.h)
find_library(MBEDTLS_SSL_LIBRARY mbedtls)
find_library(MBEDTLS_X509_LIBRARY mbedx509)
find_library(MBEDTLS_CRYPTO_LIBRARY mbedcrypto)
set(MBEDTLS_LIBRARIES ${MBEDTLS_SSL_LIBRARY} ${MBEDTLS_X509_LIBRARY} ${MBEDTLS_CRYPTO_LIBRARY})
if (MBEDTLS_INCLUDE_DIR AND EXISTS "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h")
file(STRINGS "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h" _MBEDTLS_VERSION_STRING REGEX "^#[\t ]*define[\t ]+MBEDTLS_VERSION_STRING[\t ]+\"[0-9]+.[0-9]+.[0-9]+\"")
string(REGEX REPLACE "^.*MBEDTLS_VERSION_STRING.*([0-9]+.[0-9]+.[0-9]+).*" "\\1" MBEDTLS_VERSION "${_MBEDTLS_VERSION_STRING}")
endif ()
if (MBEDTLS_INCLUDE_DIR AND MBEDTLS_LIBRARIES AND MBEDTLS_VERSION)
find_package_handle_standard_args(mbedtls
REQUIRED_VARS
MBEDTLS_INCLUDE_DIR
MBEDTLS_LIBRARIES
VERSION_VAR
MBEDTLS_VERSION
)
mark_as_advanced (MBEDTLS_INCLUDE_DIR MBEDTLS_LIBRARIES MBEDTLS_SSL_LIBRARY MBEDTLS_X509_LIBRARY MBEDTLS_CRYPTO_LIBRARY)
endif (MBEDTLS_INCLUDE_DIR AND MBEDTLS_LIBRARIES AND MBEDTLS_VERSION)

37
dependencies/CMakeLists-mbedtls.txt.in vendored Normal file
View File

@ -0,0 +1,37 @@
cmake_minimum_required(VERSION 3.2)
project(mbedtls)
set(DOWNLOAD_DIR "@MBEDTLS_DOWNLOAD_DIR@")
set(SOURCE_DIR "@MBEDTLS_SOURCE_DIR@")
set(BINARY_DIR "@MBEDTLS_BINARY_DIR@")
set(INSTALL_DIR "@MBEDTLS_INSTALL_DIR@")
set(CMAKE_ARGS "@MBEDTLS_CMAKE_ARGS@")
set(LOGGING "@MBEDTLS_LOGGING@")
include(ExternalProject)
ExternalProject_Add(
mbedtls
GIT_REPOSITORY "https://github.com/ARMmbed/mbedtls.git"
GIT_TAG origin/master
BUILD_ALWAYS OFF
DOWNLOAD_DIR "${DOWNLOAD_DIR}"
SOURCE_DIR "${SOURCE_DIR}"
BINARY_DIR "${BINARY_DIR}"
INSTALL_DIR "${INSTALL_DIR}"
CMAKE_ARGS ${CMAKE_ARGS}
CONFIGURE_COMMAND ""
UPDATE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
LOG_DOWNLOAD ${LOGGING}
LOG_UPDATE ${LOGGING}
LOG_PATCH ${LOGGING}
LOG_CONFIGURE ${LOGGING}
LOG_BUILD ${LOGGING}
LOG_INSTALL ${LOGGING}
LOG_TEST ${LOGGING}
LOG_MERGED_STDOUTERR ${LOGGING}
LOG_OUTPUT_ON_FAILURE ${LOGGING}
)

View File

@ -58,7 +58,6 @@ endif()
message(STATUS "Using flatbuffers compiler: " ${FLATBUFFERS_FLATC_EXECUTABLE})
function(compile_flattbuffer_schema SRC_FBS OUTPUT_DIR)
string(REGEX REPLACE "\\.fbs$" "_generated.h" GEN_HEADER ${SRC_FBS})
set_property(SOURCE ${GEN_HEADER} PROPERTY SKIP_AUTOMOC ON)
@ -193,3 +192,132 @@ function(PROTOBUF_GENERATE_CPP SRCS HDRS)
set(${SRCS} ${${SRCS}} PARENT_SCOPE)
set(${HDRS} ${${HDRS}} PARENT_SCOPE)
endfunction()
#=============================================================================
# MBEDTLS
#=============================================================================
set(USE_SYSTEM_MBEDTLS_LIBS ${DEFAULT_USE_SYSTEM_MBEDTLS_LIBS} CACHE BOOL "use mbedtls library from system")
if (USE_SYSTEM_MBEDTLS_LIBS)
find_package(mbedtls REQUIRED)
if (NOT MBEDTLS_FOUND)
message(STATUS "Could NOT find mbedtls system libraries, build static mbedtls libraries")
#Fallback: build mbedtls static libray inside project
set(DEFAULT_USE_SYSTEM_MBEDTLS_LIBS OFF PARENT_SCOPE)
set(USE_SYSTEM_MBEDTLS_LIBS OFF)
endif (NOT MBEDTLS_FOUND)
endif (USE_SYSTEM_MBEDTLS_LIBS)
if (NOT USE_SYSTEM_MBEDTLS_LIBS)
set(DEFAULT_USE_SYSTEM_MBEDTLS_LIBS OFF CACHE BOOL "system mbedtls libraries not found, disable use system mbedtls libraries")
set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build shared mbedtls libraries")
set(ENABLE_TESTING OFF CACHE BOOL "Disable mbedTLS tests")
set(ENABLE_PROGRAMS OFF CACHE BOOL "Disable mbedTLS programs")
set(USE_SHARED_MBEDTLS_LIBRARY OFF CACHE BOOL "Disable mbedTLS shared libraries")
set(USE_STATIC_MBEDTLS_LIBRARY ON CACHE BOOL "Enable mbedTLS static libraries")
set(MBEDTLS_DOWNLOAD_DIR "${CMAKE_BINARY_DIR}/dependencies/external/mbedtls/download")
set(MBEDTLS_SOURCE_DIR "${CMAKE_BINARY_DIR}/dependencies/external/mbedtls/src")
set(MBEDTLS_BINARY_DIR "${CMAKE_BINARY_DIR}/dependencies/external/mbedtls/build")
set(MBEDTLS_INSTALL_DIR "${CMAKE_BINARY_DIR}")
if(${CMAKE_BUILD_TYPE} EQUAL "Debug")
set(MBEDTLS_LOGGING 1)
else ()
set(MBEDTLS_LOGGING 0)
endif ()
set(MBEDTLS_CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX:PATH=${MBEDTLS_INSTALL_DIR}
-DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
-DUSE_SHARED_MBEDTLS_LIBRARY:BOOL=OFF
-DUSE_STATIC_MBEDTLS_LIBRARY:BOOL=ON
-DENABLE_TESTING:BOOL=OFF
-DENABLE_PROGRAMS:BOOL=OFF
-DLINK_WITH_PTHREAD:BOOL=ON
-Wno-dev
#-DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=TRUE
)
set(ENABLE_MBEDTLS_FETCH_CONTENT ON)
if (ENABLE_MBEDTLS_FETCH_CONTENT AND CMAKE_VERSION VERSION_GREATER_EQUAL 3.11)
include(FetchContent)
FetchContent_Declare(
mbedtls
GIT_REPOSITORY https://github.com/ARMmbed/mbedtls.git
GIT_TAG origin/master
BUILD_ALWAYS OFF
GIT_PROGRESS 1
DOWNLOAD_DIR "${MBEDTLS_DOWNLOAD_DIR}"
SOURCE_DIR "${MBEDTLS_SOURCE_DIR}"
BINARY_DIR "${MBEDTLS_BINARY_DIR}"
INSTALL_DIR "${MBEDTLS_INSTALL_DIR}"
CMAKE_ARGS ${MBEDTLS_CMAKE_ARGS}
BUILD_COMMAND ""
INSTALL_COMMAND ""
LOG_DOWNLOAD ${MBEDTLS_LOGGING}
LOG_UPDATE ${MBEDTLS_LOGGING}
LOG_PATCH ${MBEDTLS_LOGGING}
LOG_CONFIGURE ${MBEDTLS_LOGGING}
LOG_BUILD ${MBEDTLS_LOGGING}
LOG_INSTALL ${MBEDTLS_LOGGING}
LOG_TEST ${MBEDTLS_LOGGING}
LOG_MERGED_STDOUTERR ${MBEDTLS_LOGGING}
LOG_OUTPUT_ON_FAILURE ${MBEDTLS_LOGGING}
)
if (CMAKE_VERSION VERSION_LESS 3.14)
macro (FetchContent_MakeAvailable NAME)
FetchContent_GetProperties(${NAME})
if (NOT ${NAME}_POPULATED)
FetchContent_Populate(${NAME})
add_subdirectory(${${NAME}_SOURCE_DIR} ${${NAME}_BINARY_DIR})
endif ()
endmacro ()
endif ()
FetchContent_MakeAvailable(mbedtls)
else ()
set(ENABLE_MBEDTLS_FETCH_CONTENT OFF PARENT_SCOPE)
if(NOT DEFINED BUILD_MBEDTLS_ONCE)
set(BUILD_MBEDTLS_ONCE CACHE INTERNAL "Done")
configure_file(${CMAKE_SOURCE_DIR}/dependencies/CMakeLists-mbedtls.txt.in ${MBEDTLS_DOWNLOAD_DIR}/CMakeLists.txt @ONLY)
execute_process(COMMAND ${CMAKE_COMMAND} -DCMAKE_INSTALL_PREFIX:PATH=${MBEDTLS_INSTALL_DIR} -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} -G "${CMAKE_GENERATOR}" . WORKING_DIRECTORY ${MBEDTLS_DOWNLOAD_DIR})
execute_process(COMMAND ${CMAKE_COMMAND} --build . WORKING_DIRECTORY ${MBEDTLS_DOWNLOAD_DIR})
add_subdirectory(${MBEDTLS_SOURCE_DIR} ${MBEDTLS_BINARY_DIR})
endif()
endif ()
set (MBEDTLS_INCLUDE_DIR "${MBEDTLS_SOURCE_DIR}/include")
set (MBEDTLS_INCLUDE_DIR ${MBEDTLS_INCLUDE_DIR} PARENT_SCOPE)
if (MBEDTLS_INCLUDE_DIR AND EXISTS "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h")
file(STRINGS "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h" _MBEDTLS_VERSION_STRING REGEX "^#[\t ]*define[\t ]+MBEDTLS_VERSION_STRING[\t ]+\"[0-9]+.[0-9]+.[0-9]+\"")
string(REGEX REPLACE "^.*MBEDTLS_VERSION_STRING.*([0-9]+.[0-9]+.[0-9]+).*" "\\1" MBEDTLS_VERSION "${_MBEDTLS_VERSION_STRING}")
message(STATUS "Using static mbedtls libraries (build version \"${MBEDTLS_VERSION}\")")
endif ()
include_directories(${MBEDTLS_INCLUDE_DIR})
if(WIN32)
set (MBEDTLS_LIB_INSTALL_DIR_WITH_LIB_PREFIX "${MBEDTLS_INSTALL_DIR}/lib/${CMAKE_CFG_INTDIR}/")
else()
set (MBEDTLS_LIB_INSTALL_DIR_WITH_LIB_PREFIX "${MBEDTLS_INSTALL_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}")
endif ()
set (MBEDTLS_SSL_LIBRARY "${MBEDTLS_LIB_INSTALL_DIR_WITH_LIB_PREFIX}mbedtls${CMAKE_STATIC_LIBRARY_SUFFIX}")
set (MBEDTLS_X509_LIBRARY "${MBEDTLS_LIB_INSTALL_DIR_WITH_LIB_PREFIX}mbedx509${CMAKE_STATIC_LIBRARY_SUFFIX}")
set (MBEDTLS_CRYPTO_LIBRARY "${MBEDTLS_LIB_INSTALL_DIR_WITH_LIB_PREFIX}mbedcrypto${CMAKE_STATIC_LIBRARY_SUFFIX}")
set (MBEDTLS_LIBRARIES ${MBEDTLS_SSL_LIBRARY} ${MBEDTLS_X509_LIBRARY} ${MBEDTLS_CRYPTO_LIBRARY})
set (MBEDTLS_LIBRARIES ${MBEDTLS_LIBRARIES} PARENT_SCOPE)
if(${CMAKE_BUILD_TYPE} EQUAL "Debug")
message(STATUS "mbedtls libraries: ${MBEDTLS_LIBRARIES}")
endif ()
mark_as_advanced (MBEDTLS_INCLUDE_DIR MBEDTLS_LIBRARIES MBEDTLS_SSL_LIBRARY MBEDTLS_X509_LIBRARY MBEDTLS_CRYPTO_LIBRARY)
endif (NOT USE_SYSTEM_MBEDTLS_LIBS)

View File

@ -177,13 +177,13 @@ protected:
/// Timer object which makes sure that led data is written at a minimum rate
/// e.g. Adalight device will switch off when it does not receive data at least every 15 seconds
QTimer* _refresh_timer;
int _refresh_timer_interval;
int _refresh_timer_interval;
/// timestamp of last write
qint64 _last_write_time;
/// Time a device requires mandatorily between two writes
int _latchTime_ms;
int _latchTime_ms;
protected slots:
@ -208,7 +208,7 @@ protected slots:
///
/// @param errorMsg The error message to be logged
///
virtual void setInError( const QString& errorMsg);
virtual void setInError( const QString& errorMsg);
private:

View File

@ -22,6 +22,11 @@ public:
SSDPHandler(WebServer* webserver, const quint16& flatBufPort, const quint16& jsonServerPort, const QString &name, QObject * parent = nullptr);
~SSDPHandler();
///
/// @brief Sends BYE BYE and stop server
///
void stopServer();
public slots:
///
/// @brief Init SSDP after thread start

View File

@ -196,7 +196,6 @@ void HyperionIManager::handleFinished()
hyperion->deleteLater();
emit instanceStateChanged(H_STOPPED, instance);
emit change();
}
void HyperionIManager::handleStarted()

View File

@ -111,9 +111,9 @@ void MessageForwarder::handlePriorityChanges(const quint8 &priority)
const QJsonObject obj = _hyperion->getSetting(settings::NETFORWARD).object();
if (priority != 0 && _forwarder_enabled && obj["enable"].toBool())
{
_flatSlaves.clear();
while (!_forwardClients.isEmpty())
delete _forwardClients.takeFirst();
//_flatSlaves.clear();
//while (!_forwardClients.isEmpty())
// delete _forwardClients.takeFirst();
hyperion::Components activeCompId = _hyperion->getPriorityInfo(priority).componentId;
if (activeCompId == hyperion::COMP_GRABBER || activeCompId == hyperion::COMP_V4L)
@ -181,7 +181,7 @@ void MessageForwarder::addJsonSlave(QString slave)
return;
}
if (_forwarder_enabled)
if (_forwarder_enabled && !_jsonSlaves.contains(slave))
_jsonSlaves << slave;
}
@ -210,7 +210,7 @@ void MessageForwarder::addFlatbufferSlave(QString slave)
return;
}
if (_forwarder_enabled)
if (_forwarder_enabled && !_flatSlaves.contains(slave))
{
_flatSlaves << slave;
FlatBufferConnection* flatbuf = new FlatBufferConnection("Forwarder", slave.toLocal8Bit().constData(), _priority, false);

View File

@ -87,7 +87,7 @@ target_link_libraries(leddevice
${CMAKE_THREAD_LIBS_INIT}
Qt5::Network
Qt5::SerialPort
ssdp
ssdp
)
if(WIN32)
@ -109,3 +109,11 @@ if (ENABLE_USB_HID)
target_link_libraries(leddevice ${LIBUSB_1_LIBRARIES} hidapi-libusb)
endif()
endif()
if (NOT DEFAULT_USE_SYSTEM_MBEDTLS_LIBS)
if (MBEDTLS_LIBRARIES)
include_directories(${MBEDTLS_INCLUDE_DIR})
target_link_libraries(leddevice ${MBEDTLS_LIBRARIES})
target_include_directories(leddevice PRIVATE ${MBEDTLS_INCLUDE_DIR})
endif (MBEDTLS_LIBRARIES)
endif ()

View File

@ -25,7 +25,7 @@ LedDevice::LedDevice(const QJsonObject& config, QObject* parent)
, _latchTime_ms(0)
, _componentRegistered(false)
, _enabled(false)
, _refresh_enabled (false)
, _refresh_enabled(false)
{
// setup refreshTimer
_refresh_timer->setTimerType(Qt::PreciseTimer);
@ -74,7 +74,7 @@ void LedDevice::close()
void LedDevice::setEnable(bool enable)
{
if (!_deviceReady && enable)
if ( !_deviceReady && enable )
{
Debug(_log, "Device '%s' was not ready! Trying to re-open.", QSTRING_CSTR(_activeDeviceType));
if ( open() < 0 )
@ -90,19 +90,19 @@ void LedDevice::setEnable(bool enable)
}
// emit signal when state changed
if (_enabled != enable)
if ( _enabled != enable )
{
emit enableStateChanged(enable);
}
// switch off device when disabled, default: set black to leds when they should go off
if ( _enabled && !enable)
if ( _enabled && !enable )
{
switchOff();
}
else
{
// switch on device when enabled
if ( !_enabled && enable)
if ( !_enabled && enable )
{
switchOn();
}
@ -123,19 +123,18 @@ bool LedDevice::init(const QJsonObject &deviceConfig)
_activeDeviceType = deviceConfig["type"].toString("file").toLower();
setLedCount(static_cast<unsigned int>( deviceConfig["currentLedCount"].toInt(1) )); // property injected to reflect real led count
_latchTime_ms =deviceConfig["latchTime"].toInt( _latchTime_ms );
_refresh_timer_interval = deviceConfig["rewriteTime"].toInt( _refresh_timer_interval);
_latchTime_ms = deviceConfig["latchTime"].toInt( _latchTime_ms );
_refresh_timer_interval = deviceConfig["rewriteTime"].toInt( _refresh_timer_interval);
if ( _refresh_timer_interval > 0 )
{
_refresh_enabled = true;
if (_refresh_timer_interval <= _latchTime_ms )
if ( _refresh_timer_interval <= _latchTime_ms )
{
int new_refresh_timer_interval = _latchTime_ms + 10;
Warning(_log, "latchTime(%d) is bigger/equal rewriteTime(%d), set rewriteTime to %dms", _latchTime_ms, _refresh_timer_interval, new_refresh_timer_interval);
_refresh_timer_interval = new_refresh_timer_interval;
_refresh_timer->setInterval( _refresh_timer_interval );
}
//Debug(_log, "Refresh interval = %dms",_refresh_timer_interval );
@ -150,7 +149,7 @@ bool LedDevice::init(const QJsonObject &deviceConfig)
void LedDevice::startRefreshTimer()
{
if ( _deviceReady)
if ( _deviceReady )
{
_refresh_timer->start();
}
@ -164,7 +163,7 @@ void LedDevice::stopRefreshTimer()
int LedDevice::updateLeds(const std::vector<ColorRgb>& ledValues)
{
int retval = 0;
if ( !_deviceReady || _deviceInError)
if ( !_deviceReady || _deviceInError )
{
//std::cout << "LedDevice::updateLeds(), LedDevice NOT ready!" << std::endl;
return -1;
@ -243,8 +242,8 @@ int LedDevice::rewriteLeds()
if ( _deviceReady )
{
//qint64 elapsedTime = QDateTime::currentMSecsSinceEpoch() - _last_write_time;
//std::cout << "LedDevice::rewriteLeds(): Rewrite Leds now, elapsedTime [" << elapsedTime << "] ms" << std::endl;
// qint64 elapsedTime = QDateTime::currentMSecsSinceEpoch() - _last_write_time;
// std::cout << "LedDevice::rewriteLeds(): Rewrite Leds now, elapsedTime [" << elapsedTime << "] ms" << std::endl;
// //:TESTING: Inject "white" output records to differentiate from normal writes
// _last_ledValues.clear();
// _last_ledValues.resize(static_cast<unsigned long>(_ledCount), ColorRgb::WHITE);
@ -262,7 +261,7 @@ int LedDevice::rewriteLeds()
return retval;
}
void LedDevice::printLedValues(const std::vector<ColorRgb>& ledValues )
void LedDevice::printLedValues(const std::vector<ColorRgb>& ledValues)
{
std::cout << "LedValues [" << ledValues.size() <<"] [";
for (const ColorRgb& color : ledValues)

View File

@ -428,8 +428,6 @@ QJsonDocument LedDeviceNanoleaf::handleReply(QNetworkReply* const &reply )
return jsonDoc;
}
int LedDeviceNanoleaf::write(const std::vector<ColorRgb> & ledValues)
{

File diff suppressed because it is too large Load Diff

View File

@ -2,16 +2,38 @@
// STL includes
#include <set>
#include <string>
#include <stdarg.h>
// Qt includes
#include <QNetworkAccessManager>
#include <QTimer>
#include <QEventLoop>
#include <QNetworkReply>
#include <QtCore/qmath.h>
#include <QStringList>
// Leddevice includes
#include <leddevice/LedDevice.h>
#include "ProviderUdpSSL.h"
// Forward declaration
struct CiColorTriangle;
/**
* A XY color point in the color space of the hue system without brightness.
*/
struct XYColor
{
/// X component.
double x;
/// Y component.
double y;
};
/**
* Color triangle to define an available color space for the hue lamps.
*/
struct CiColorTriangle
{
XYColor red, green, blue;
};
/**
* A color point in the color space of the hue system.
@ -37,14 +59,14 @@ struct CiColor
///
/// @return color point
///
static CiColor rgbToCiColor(double red, double green, double blue, CiColorTriangle colorSpace);
static CiColor rgbToCiColor(double red, double green, double blue, const CiColorTriangle &colorSpace);
///
/// @param p the color point to check
///
/// @return true if the color point is covered by the lamp color space
///
static bool isPointInLampsReach(CiColor p, CiColorTriangle colorSpace);
static bool isPointInLampsReach(CiColor p, const CiColorTriangle &colorSpace);
///
/// @param p1 point one
@ -53,7 +75,7 @@ struct CiColor
///
/// @return the cross product between p1 and p2
///
static double crossProduct(CiColor p1, CiColor p2);
static double crossProduct(XYColor p1, XYColor p2);
///
/// @param a reference point one
@ -64,7 +86,7 @@ struct CiColor
///
/// @return the closest color point of p to a and b
///
static CiColor getClosestPointToPoint(CiColor a, CiColor b, CiColor p);
static XYColor getClosestPointToPoint(XYColor a, XYColor b, CiColor p);
///
/// @param p1 point one
@ -73,20 +95,12 @@ struct CiColor
///
/// @return the distance between the two points
///
static double getDistanceBetweenTwoPoints(CiColor p1, CiColor p2);
static double getDistanceBetweenTwoPoints(CiColor p1, XYColor p2);
};
bool operator==(const CiColor& p1, const CiColor& p2);
bool operator!=(const CiColor& p1, const CiColor& p2);
/**
* Color triangle to define an available color space for the hue lamps.
*/
struct CiColorTriangle
{
CiColor red, green, blue;
};
/**
* Simple class to hold the id, the latest color, the color space and the original state.
*/
@ -120,13 +134,12 @@ public:
///
/// @param transitionTime the transition time between colors in multiples of 100 ms
///
void setTransitionTime(unsigned int _transitionTime);
void setTransitionTime(unsigned int transitionTime);
///
/// @param color the color to set
///
void setColor(const CiColor& _color);
void setColor(const CiColor& color);
unsigned int getId() const;
@ -138,9 +151,7 @@ public:
/// @return the color space of the light determined by the model id reported by the bridge.
CiColorTriangle getColorSpace() const;
QString getOriginalState();
QString getOriginalState() const;
private:
@ -167,7 +178,7 @@ private:
CiColor _originalColor;
};
class LedDevicePhilipsHueBridge : public LedDevice
class LedDevicePhilipsHueBridge : public ProviderUdpSSL
{
Q_OBJECT
@ -183,24 +194,22 @@ public:
/// @return true if success
virtual bool init(const QJsonObject &deviceConfig) override;
///
/// @param route the route of the POST request.
///
/// @param content the content of the POST request.
///
void post(const QString& route, const QString& content);
QJsonDocument post(const QString& route, const QString& content);
void setLightState(unsigned int lightId = 0, QString state = "");
const QMap<quint16,QJsonObject>& getLightMap();
// /// Set device in error state
// ///
// /// @param errorMsg The error message to be logged
// ///
// virtual void setInError( const QString& errorMsg) override;
const QMap<quint16,QJsonObject>& getGroupMap();
QString getGroupName(unsigned int groupId = 0);
QJsonArray getGroupLights(unsigned int groupId = 0);
public slots:
///
@ -209,11 +218,6 @@ public slots:
virtual int open(void) override;
virtual int open( const QString& hostname, const QString& port, const QString& username );
//signals:
// ///
// /// Emits with a QMap of current bridge light/value pairs
// ///
// void newLights(QMap<quint16,QJsonObject> map);
protected:
/// Ip address of the bridge
@ -222,6 +226,18 @@ protected:
/// User name for the API ("newdeveloper")
QString _username;
bool _useHueEntertainmentAPI;
QJsonDocument getGroupState( unsigned int groupId );
QJsonDocument setGroupState( unsigned int groupId, bool state);
bool isStreamOwner(const QString streamOwner);
bool initMaps();
void log(const char* msg, const char* type, ...);
const int * getCiphersuites() override;
private:
///
@ -267,6 +283,11 @@ private:
///
QJsonDocument handleReply(QNetworkReply* const &reply );
QJsonDocument getAllBridgeInfos();
void setBridgeConfig( QJsonDocument doc );
void setLightsMap( QJsonDocument doc );
void setGroupMap( QJsonDocument doc );
/// QNetworkAccessManager for sending requests.
QNetworkAccessManager* _networkmanager;
@ -282,10 +303,9 @@ private:
bool _isHueEntertainmentReady;
QMap<quint16,QJsonObject> _lightsMap;
QMap<quint16,QJsonObject> _groupsMap;
};
/**
* Implementation for the Philips Hue system.
*
@ -296,7 +316,6 @@ private:
*/
class LedDevicePhilipsHue: public LedDevicePhilipsHueBridge
{
Q_OBJECT
public:
@ -337,10 +356,16 @@ public:
unsigned int getLightsCount() const { return _lightsCount; }
void setLightsCount( unsigned int lightsCount);
bool initStream();
bool getStreamGroupState();
bool setStreamGroupState(bool state);
bool startStream();
bool stopStream();
void setOnOffState(PhilipsHueLight& light, bool on);
void setTransitionTime(PhilipsHueLight& light, unsigned int transitionTime);
void setColor(PhilipsHueLight& light, const CiColor& color, double brightnessFactor);
void setState(PhilipsHueLight& light, bool on, const CiColor& color, double brightnessFactor, unsigned int transitionTime);
void setTransitionTime(PhilipsHueLight& light);
void setColor(PhilipsHueLight& light, CiColor& color);
void setState(PhilipsHueLight& light, bool on, const CiColor& color);
void restoreOriginalState();
@ -357,7 +382,9 @@ private slots:
///
/// @param map Map of lightid/value pairs of bridge
///
void updateLights(QMap<quint16, QJsonObject> map);
bool updateLights(QMap<quint16, QJsonObject> map);
void noSignalTimeout();
protected:
@ -374,6 +401,7 @@ protected:
/// @return True, if Nanoleaf device capabilities fit configuration
///
bool initLeds();
bool reinitLeds();
///
/// Writes the RGB-Color values to the leds.
@ -386,8 +414,18 @@ protected:
private:
bool setLights();
int writeSingleLights(const std::vector<ColorRgb>& ledValues);
void writeStream();
bool noSignalDetection();
void stopBlackTimeoutTimer();
QByteArray prepareStreamData();
///
bool _switchOffOnBlack;
/// The brightness factor to multiply on color change.
@ -397,6 +435,8 @@ private:
unsigned int _transitionTime;
bool _isRestoreOrigState;
bool _lightStatesRestored;
bool _isInitLeds;
/// Array of the light ids.
std::vector<unsigned int> _lightIds;
@ -404,6 +444,26 @@ private:
std::vector<PhilipsHueLight> _lights;
unsigned int _lightsCount;
unsigned int _groupId;
double _brightnessMin;
double _brightnessMax;
bool _allLightsBlack;
QTimer* _blackLightsTimer;
unsigned int _blackLightsTimeout;
double _brightnessThreshold;
int _handshake_timeout_min;
int _handshake_timeout_max;
int _ssl_read_timeout;
bool _stopConnection;
QString _groupName;
QString _streamOwner;
int start_retry_left;
int stop_retry_left;
};

View File

@ -77,7 +77,7 @@ bool ProviderUdp::initNetwork()
{
bool isInitOK = false;
_udpSocket =new QUdpSocket(this);
_udpSocket = new QUdpSocket(this);
if ( _udpSocket != nullptr)
{

View File

@ -0,0 +1,801 @@
// STL includes
#include <cstdio>
#include <exception>
// Linux includes
#include <fcntl.h>
#ifndef _WIN32
#include <sys/ioctl.h>
#endif
// Local Hyperion includes
#include "ProviderUdpSSL.h"
ProviderUdpSSL::ProviderUdpSSL()
: LedDevice()
, client_fd()
, entropy()
, ssl()
, conf()
, ctr_drbg()
, timer()
, _transport_type("DTLS")
, _custom("dtls_client")
, _address("127.0.0.1")
, _defaultHost("127.0.0.1")
, _port(1)
, _ssl_port(1)
, _server_name()
, _psk()
, _psk_identity()
, _read_timeout(0)
, _handshake_timeout_min(400)
, _handshake_timeout_max(1000)
, _handshake_attempts(5)
, _retry_left(MAX_RETRY)
, _stopConnection(true)
, _debugStreamer(false)
, _debugLevel(0)
{
_deviceReady = false;
_latchTime_ms = 1;
}
ProviderUdpSSL::~ProviderUdpSSL()
{
}
bool ProviderUdpSSL::init(const QJsonObject &deviceConfig)
{
bool isInitOK = LedDevice::init(deviceConfig);
_debugStreamer = deviceConfig["debugStreamer"].toBool(false);
_debugLevel = deviceConfig["debugLevel"].toString().toInt(0);
//PSK Pre Shared Key
_psk = deviceConfig["psk"].toString();
_psk_identity = deviceConfig["psk_identity"].toString();
_port = deviceConfig["sslport"].toInt(2100);
_server_name = deviceConfig["servername"].toString();
if( deviceConfig.contains("transport_type") ) _transport_type = deviceConfig["transport_type"].toString("DTLS");
if( deviceConfig.contains("seed_custom") ) _custom = deviceConfig["seed_custom"].toString("dtls_client");
if( deviceConfig.contains("retry_left") ) _retry_left = deviceConfig["retry_left"].toInt(MAX_RETRY);
if( deviceConfig.contains("read_timeout") ) _read_timeout = deviceConfig["read_timeout"].toInt(0);
if( deviceConfig.contains("hs_timeout_min") ) _handshake_timeout_min = deviceConfig["hs_timeout_min"].toInt(400);
if( deviceConfig.contains("hs_timeout_max") ) _handshake_timeout_max = deviceConfig["hs_timeout_max"].toInt(1000);
if( deviceConfig.contains("hs_attempts") ) _handshake_attempts = deviceConfig["hs_attempts"].toInt(5);
QString host = deviceConfig["host"].toString(_defaultHost);
QStringList debugLevels = QStringList() << "No Debug" << "Error" << "State Change" << "Informational" << "Verbose";
configLog( "SSL Streamer Debug", "%s", ( _debugStreamer ) ? "yes" : "no" );
configLog( "SSL DebugLevel", "[%d] %s", _debugLevel, QSTRING_CSTR( debugLevels[ _debugLevel ]) );
configLog( "SSL Servername", "%s", QSTRING_CSTR( _server_name ) );
configLog( "SSL Host", "%s", QSTRING_CSTR( host ) );
configLog( "SSL Port", "%d", _port );
configLog( "PSK", "%s", QSTRING_CSTR( _psk ) );
configLog( "PSK-Identity", "%s", QSTRING_CSTR( _psk_identity ) );
configLog( "SSL Transport Type", "%s", QSTRING_CSTR( _transport_type ) );
configLog( "SSL Seed Custom", "%s", QSTRING_CSTR( _custom ) );
configLog( "SSL Retry Left", "%d", _retry_left );
configLog( "SSL Read Timeout", "%d", _read_timeout );
configLog( "SSL Handshake Timeout min", "%d", _handshake_timeout_min );
configLog( "SSL Handshake Timeout max", "%d", _handshake_timeout_max );
configLog( "SSL Handshake attempts", "%d", _handshake_attempts );
if ( _address.setAddress(host) )
{
Debug( _log, "Successfully parsed %s as an ip address.", QSTRING_CSTR( host ) );
}
else
{
Debug( _log, "Failed to parse [%s] as an ip address.", QSTRING_CSTR( host ) );
QHostInfo info = QHostInfo::fromName(host);
if ( info.addresses().isEmpty() )
{
Debug( _log, "Failed to parse [%s] as a hostname.", QSTRING_CSTR( host ) );
QString errortext = QString("Invalid target address [%1]!").arg(host);
this->setInError( errortext );
isInitOK = false;
}
else
{
Debug( _log, "Successfully parsed %s as a hostname.", QSTRING_CSTR( host ) );
_address = info.addresses().first();
}
}
int config_port = deviceConfig["sslport"].toInt(_port);
if ( config_port <= 0 || config_port > MAX_PORT_SSL )
{
QString errortext = QString ("Invalid target port [%1]!").arg(config_port);
this->setInError( errortext );
isInitOK = false;
}
else
{
_ssl_port = config_port;
Debug( _log, "UDP SSL using %s:%u", QSTRING_CSTR( _address.toString() ), _ssl_port );
}
return isInitOK;
}
int ProviderUdpSSL::open()
{
int retval = -1;
QString errortext;
_deviceReady = false;
if ( init(_devConfig) )
{
if ( !initNetwork() )
{
this->setInError( "UDP SSL Network error!" );
}
else
{
// Everything is OK -> enable device
_deviceReady = true;
setEnable(true);
retval = 0;
}
}
return retval;
}
void ProviderUdpSSL::close()
{
LedDevice::close();
closeSSLConnection();
}
void ProviderUdpSSL::closeSSLConnection()
{
if( _deviceReady && !_stopConnection )
{
closeSSLNotify();
freeSSLConnection();
}
}
const int *ProviderUdpSSL::getCiphersuites()
{
return mbedtls_ssl_list_ciphersuites();
}
void ProviderUdpSSL::configLog(const char* msg, const char* type, ...)
{
if( _debugStreamer )
{
const size_t max_val_length = 1024;
char val[max_val_length];
va_list args;
va_start(args, type);
vsnprintf(val, max_val_length, type, args);
va_end(args);
std::string s = msg;
int max = 30;
s.append(max - s.length(), ' ');
Debug( _log, "%s: %s", s.c_str(), val );
}
}
void ProviderUdpSSL::sslLog(const QString &msg, const char* errorType)
{
sslLog( QSTRING_CSTR( msg ), errorType );
}
void ProviderUdpSSL::sslLog(const char* msg, const char* errorType)
{
if( strcmp("fatal", errorType) == 0 ) Error( _log, "%s", msg );
if( _debugStreamer )
{
if( strcmp("debug", errorType) == 0 ) Debug( _log, "%s", msg );
if( strcmp("warning", errorType) == 0 ) Warning( _log, "%s", msg );
if( strcmp("error", errorType) == 0 ) Error( _log, "%s", msg );
}
}
bool ProviderUdpSSL::initNetwork()
{
sslLog( "init SSL Network..." );
QMutexLocker locker(&_hueMutex);
if (!initConnection()) return false;
sslLog( "init SSL Network...ok" );
_stopConnection = false;
return true;
}
bool ProviderUdpSSL::initConnection()
{
sslLog( "init SSL Network -> initConnection" );
mbedtls_net_init(&client_fd);
mbedtls_ssl_init(&ssl);
mbedtls_ssl_config_init(&conf);
mbedtls_x509_crt_init(&cacert);
mbedtls_ctr_drbg_init(&ctr_drbg);
if(!seedingRNG()) return false;
return setupStructure();
}
bool ProviderUdpSSL::seedingRNG()
{
int ret = 0;
sslLog( "Seeding the random number generator..." );
mbedtls_entropy_init(&entropy);
sslLog( "Set mbedtls_ctr_drbg_seed..." );
const char* custom = QSTRING_CSTR( _custom );
if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, reinterpret_cast<const unsigned char *>(custom), strlen(custom))) != 0)
{
sslLog( QString("mbedtls_ctr_drbg_seed FAILED %1").arg( errorMsg( ret ) ), "error" );
return false;
}
sslLog( "Seeding the random number generator...ok" );
return true;
}
bool ProviderUdpSSL::setupStructure()
{
int ret = 0;
sslLog( QString( "Setting up the %1 structure").arg( _transport_type ) );
//TLS MBEDTLS_SSL_TRANSPORT_STREAM
//DTLS MBEDTLS_SSL_TRANSPORT_DATAGRAM
int transport = ( _transport_type == "DTLS" ) ? MBEDTLS_SSL_TRANSPORT_DATAGRAM : MBEDTLS_SSL_TRANSPORT_STREAM;
if ((ret = mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_CLIENT, transport, MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
{
sslLog( QString("mbedtls_ssl_config_defaults FAILED %1").arg( errorMsg( ret ) ), "error" );
return false;
}
const int * ciphersuites = getCiphersuites();
if( _debugStreamer )
{
int s = ( sizeof( ciphersuites ) ) / sizeof( int );
QString cipher_values;
for(int i=0; i<s; i++)
{
if(i > 0) cipher_values.append(", ");
cipher_values.append(QString::number(ciphersuites[i]));
}
sslLog( ( QString("used ciphersuites value: %1").arg( cipher_values ) ) );
}
mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_REQUIRED);
//mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
//mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_NONE);
mbedtls_ssl_conf_ca_chain(&conf, &cacert, NULL);
mbedtls_ssl_conf_ciphersuites(&conf, ciphersuites);
mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg);
if ( _debugLevel > 0)
{
mbedtls_ssl_conf_verify(&conf, ProviderUdpSSLVerify, NULL);
mbedtls_ssl_conf_dbg(&conf, ProviderUdpSSLDebug, NULL);
mbedtls_debug_set_threshold( _debugLevel );
}
if( _read_timeout > 0 ) mbedtls_ssl_conf_read_timeout(&conf, _read_timeout);
mbedtls_ssl_conf_handshake_timeout(&conf, _handshake_timeout_min, _handshake_timeout_max);
if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0)
{
sslLog( QString("mbedtls_ssl_setup FAILED %1").arg( errorMsg( ret ) ), "error" );
return false;
}
if ((ret = mbedtls_ssl_set_hostname(&ssl, QSTRING_CSTR( _server_name ))) != 0)
{
sslLog( QString("mbedtls_ssl_set_hostname FAILED %1").arg( errorMsg( ret ) ), "error" );
return false;
}
sslLog( QString( "Setting up the %1 structure...ok").arg( _transport_type ) );
return startUPDConnection();
}
bool ProviderUdpSSL::startUPDConnection()
{
sslLog( "init SSL Network -> startUPDConnection" );
int ret = 0;
mbedtls_ssl_session_reset(&ssl);
if(!setupPSK()) return false;
sslLog( QString("Connecting to udp %1:%2").arg( _address.toString() ).arg( _ssl_port ) );
if ((ret = mbedtls_net_connect( &client_fd, _address.toString().toUtf8(), std::to_string(_ssl_port).c_str(), MBEDTLS_NET_PROTO_UDP)) != 0)
{
sslLog( QString("mbedtls_net_connect FAILED %1").arg( errorMsg( ret ) ), "error" );
return false;
}
mbedtls_ssl_set_bio(&ssl, &client_fd, mbedtls_net_send, mbedtls_net_recv, mbedtls_net_recv_timeout);
mbedtls_ssl_set_timer_cb(&ssl, &timer, mbedtls_timing_set_delay, mbedtls_timing_get_delay);
sslLog( "Connecting...ok" );
return startSSLHandshake();
}
bool ProviderUdpSSL::setupPSK()
{
int ret;
QByteArray pskArray = _psk.toUtf8();
QByteArray pskRawArray = QByteArray::fromHex(pskArray);
QByteArray pskIdArray = _psk_identity.toUtf8();
QByteArray pskIdRawArray = pskIdArray;
if (0 != (ret = mbedtls_ssl_conf_psk( &conf, ( const unsigned char* ) pskRawArray.data(), pskRawArray.length() * sizeof(char), reinterpret_cast<const unsigned char *> ( pskIdRawArray.data() ), pskIdRawArray.length() * sizeof(char) ) ) )
{
sslLog( QString("mbedtls_ssl_conf_psk FAILED %1").arg( errorMsg( ret ) ), "error" );
return false;
}
return true;
}
bool ProviderUdpSSL::startSSLHandshake()
{
sslLog( "init SSL Network -> startSSLHandshake" );
int ret = 0;
sslLog( QString( "Performing the SSL/%1 handshake...").arg( _transport_type ) );
for (unsigned int attempt = 1; attempt <= _handshake_attempts; ++attempt)
{
sslLog( QString("handshake attempt %1/%2").arg( attempt ).arg( _handshake_attempts ) );
do
{
ret = mbedtls_ssl_handshake(&ssl);
}
while (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE);
if (ret == 0)
{
break;
}
else
{
sslLog( QString("mbedtls_ssl_handshake attempt %1/%2 FAILED %3").arg( attempt ).arg( _handshake_attempts ).arg( errorMsg( ret ) ) );
}
QThread::msleep(200);
}
if (ret != 0)
{
sslLog( QString("mbedtls_ssl_handshake FAILED %1").arg( errorMsg( ret ) ), "error" );
handleReturn(ret);
sslLog( "UDP SSL Connection failed!", "fatal" );
return false;
}
else
{
if( ( mbedtls_ssl_get_verify_result( &ssl ) ) != 0 ) {
sslLog( "SSL certificate verification failed!", "fatal" );
return false;
}
}
sslLog( QString( "Performing the SSL/%1 handshake...ok").arg( _transport_type ) );
return true;
}
void ProviderUdpSSL::freeSSLConnection()
{
sslLog( "SSL Connection cleanup..." );
_stopConnection = true;
try
{
mbedtls_ssl_session_reset(&ssl);
mbedtls_net_free(&client_fd);
mbedtls_ssl_free(&ssl);
mbedtls_ssl_config_free(&conf);
mbedtls_x509_crt_free(&cacert);
mbedtls_ctr_drbg_free(&ctr_drbg);
mbedtls_entropy_free(&entropy);
sslLog( "SSL Connection cleanup...ok" );
}
catch (std::exception &e)
{
sslLog( QString("SSL Connection cleanup Error: %s").arg( e.what() ) );
}
catch (...)
{
sslLog( "SSL Connection cleanup Error: <unknown>" );
}
}
void ProviderUdpSSL::writeBytes(const unsigned size, const unsigned char * data)
{
if( _stopConnection ) return;
QMutexLocker locker(&_hueMutex);
int ret = 0;
do
{
ret = mbedtls_ssl_write(&ssl, data, size);
}
while (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE);
if (ret <= 0)
{
handleReturn(ret);
}
}
void ProviderUdpSSL::handleReturn(int ret)
{
bool closeNotify = false;
bool gotoExit = false;
switch (ret)
{
case MBEDTLS_ERR_SSL_TIMEOUT:
sslLog( errorMsg( ret ), "warning" );
if ( _retry_left-- > 0 ) return;
gotoExit = true;
break;
case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
sslLog( "SSL Connection was closed gracefully", "warning" );
ret = 0;
closeNotify = true;
break;
default:
sslLog( QString("mbedtls_ssl_read returned %1").arg( errorMsg( ret ) ), "warning" );
gotoExit = true;
}
if (closeNotify)
{
closeSSLNotify();
gotoExit = true;
}
if (gotoExit)
{
sslLog( "Exit SSL connection" );
_stopConnection = true;
}
}
QString ProviderUdpSSL::errorMsg(int ret) {
QString msg;
#ifdef MBEDTLS_ERROR_C
char error_buf[1024];
mbedtls_strerror(ret, error_buf, 1024);
msg = QString("Last error was: %1 - %2").arg( ret ).arg( error_buf );
#else
switch (ret)
{
#if defined(MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE)
case MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE:
msg = "The requested feature is not available. - MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE -0x7080";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_BAD_INPUT_DATA)
case MBEDTLS_ERR_SSL_BAD_INPUT_DATA:
msg = "Bad input parameters to function. - MBEDTLS_ERR_SSL_BAD_INPUT_DATA -0x7100";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_INVALID_MAC)
case MBEDTLS_ERR_SSL_INVALID_MAC:
msg = "Verification of the message MAC failed. - MBEDTLS_ERR_SSL_INVALID_MAC -0x7180";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_INVALID_RECORD)
case MBEDTLS_ERR_SSL_INVALID_RECORD:
msg = "An invalid SSL record was received. - MBEDTLS_ERR_SSL_INVALID_RECORD -0x7200";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_CONN_EOF)
case MBEDTLS_ERR_SSL_CONN_EOF:
msg = "The connection indicated an EOF. - MBEDTLS_ERR_SSL_CONN_EOF -0x7280";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_UNKNOWN_CIPHER)
case MBEDTLS_ERR_SSL_UNKNOWN_CIPHER:
msg = "An unknown cipher was received. - MBEDTLS_ERR_SSL_UNKNOWN_CIPHER -0x7300";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN)
case MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN:
msg = "The server has no ciphersuites in common with the client. - MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN -0x7380";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_NO_RNG)
case MBEDTLS_ERR_SSL_NO_RNG:
msg = "No RNG was provided to the SSL module. - MBEDTLS_ERR_SSL_NO_RNG -0x7400";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE)
case MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE:
msg = "No client certification received from the client, but required by the authentication mode. - MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE -0x7480";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE)
case MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE:
msg = "Our own certificate(s) is/are too large to send in an SSL message. - MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE -0x7500";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED)
case MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED:
msg = "The own certificate is not set, but needed by the server. - MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED -0x7580";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED)
case MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED:
msg = "The own private key or pre-shared key is not set, but needed. - MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED -0x7600";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED)
case MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED:
msg = "No CA Chain is set, but required to operate. - MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED -0x7680";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE)
case MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE:
msg = "An unexpected message was received from our peer. - MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE -0x7700";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE)
case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE:
msg = "A fatal alert message was received from our peer. - MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE -0x7780";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED)
case MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED:
msg = "Verification of our peer failed. - MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED -0x7800";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY)
case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
msg = "The peer notified us that the connection is going to be closed. - MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY -0x7880";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO)
case MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO:
msg = "Processing of the ClientHello handshake message failed. - MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO -0x7900";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO)
case MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO:
msg = "Processing of the ServerHello handshake message failed. - MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO -0x7980";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE)
case MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE:
msg = "Processing of the Certificate handshake message failed. - MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE -0x7A00";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST)
case MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST:
msg = "Processing of the CertificateRequest handshake message failed. - MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST -0x7A80";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE)
case MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE:
msg = "Processing of the ServerKeyExchange handshake message failed. - MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE -0x7B00";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE)
case MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE:
msg = "Processing of the ServerHelloDone handshake message failed. - MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE -0x7B80";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE)
case MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE:
msg = "Processing of the ClientKeyExchange handshake message failed. - MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE -0x7C00";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP)
case MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP:
msg = "Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public. - MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP -0x7C80";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS)
case MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS:
msg = "Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret. - MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS -0x7D00";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY)
case MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY:
msg = "Processing of the CertificateVerify handshake message failed. - MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY -0x7D80";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC)
case MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC:
msg = "Processing of the ChangeCipherSpec handshake message failed. - MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC -0x7E00";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_BAD_HS_FINISHED)
case MBEDTLS_ERR_SSL_BAD_HS_FINISHED:
msg = "Processing of the Finished handshake message failed. - MBEDTLS_ERR_SSL_BAD_HS_FINISHED -0x7E80";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_ALLOC_FAILED)
case MBEDTLS_ERR_SSL_ALLOC_FAILED:
msg = "Memory allocation failed. - MBEDTLS_ERR_SSL_ALLOC_FAILED -0x7F00";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_HW_ACCEL_FAILED)
case MBEDTLS_ERR_SSL_HW_ACCEL_FAILED:
msg = "Hardware acceleration function returned with error. - MBEDTLS_ERR_SSL_HW_ACCEL_FAILED -0x7F80";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH)
case MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH:
msg = "Hardware acceleration function skipped / left alone data. - MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH -0x6F80";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_COMPRESSION_FAILED)
case MBEDTLS_ERR_SSL_COMPRESSION_FAILED:
msg = "Processing of the compression / decompression failed. - MBEDTLS_ERR_SSL_COMPRESSION_FAILED -0x6F00";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION)
case MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION:
msg = "Handshake protocol not within min/max boundaries. - MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION -0x6E80";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET)
case MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET:
msg = "Processing of the NewSessionTicket handshake message failed. - MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET -0x6E00";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED)
case MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED:
msg = "Session ticket has expired. - MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED -0x6D80";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH)
case MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH:
msg = "Public key type mismatch (eg, asked for RSA key exchange and presented EC key) - MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH -0x6D00";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY)
case MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY:
msg = "Unknown identity received (eg, PSK identity) - MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY -0x6C80";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_INTERNAL_ERROR)
case MBEDTLS_ERR_SSL_INTERNAL_ERROR:
msg = "Internal error (eg, unexpected failure in lower-level module) - MBEDTLS_ERR_SSL_INTERNAL_ERROR -0x6C00";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_COUNTER_WRAPPING)
case MBEDTLS_ERR_SSL_COUNTER_WRAPPING:
msg = "A counter would wrap (eg, too many messages exchanged). - MBEDTLS_ERR_SSL_COUNTER_WRAPPING -0x6B80";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO)
case MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO:
msg = "Unexpected message at ServerHello in renegotiation. - MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO -0x6B00";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED)
case MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED:
msg = "DTLS client must retry for hello verification. - MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED -0x6A80";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL)
case MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL:
msg = "A buffer is too small to receive or write a message. - MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL -0x6A00";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE)
case MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE:
msg = "None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages). - MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE -0x6980";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_WANT_READ)
case MBEDTLS_ERR_SSL_WANT_READ:
msg = "No data of requested type currently available on underlying transport. - MBEDTLS_ERR_SSL_WANT_READ -0x6900";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_WANT_WRITE)
case MBEDTLS_ERR_SSL_WANT_WRITE:
msg = "Connection requires a write call. - MBEDTLS_ERR_SSL_WANT_WRITE -0x6880";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_TIMEOUT)
case MBEDTLS_ERR_SSL_TIMEOUT:
msg = "The operation timed out. - MBEDTLS_ERR_SSL_TIMEOUT -0x6800";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_CLIENT_RECONNECT)
case MBEDTLS_ERR_SSL_CLIENT_RECONNECT:
msg = "The client initiated a reconnect from the same port. - MBEDTLS_ERR_SSL_CLIENT_RECONNECT -0x6780";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_UNEXPECTED_RECORD)
case MBEDTLS_ERR_SSL_UNEXPECTED_RECORD:
msg = "Record header looks valid but is not expected. - MBEDTLS_ERR_SSL_UNEXPECTED_RECORD -0x6700";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_NON_FATAL)
case MBEDTLS_ERR_SSL_NON_FATAL:
msg = "The alert message received indicates a non-fatal error. - MBEDTLS_ERR_SSL_NON_FATAL -0x6680";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH)
case MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH:
msg = "Couldn't set the hash for verifying CertificateVerify. - MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH -0x6600";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_CONTINUE_PROCESSING)
case MBEDTLS_ERR_SSL_CONTINUE_PROCESSING:
msg = "Internal-only message signaling that further message-processing should be done. - MBEDTLS_ERR_SSL_CONTINUE_PROCESSING -0x6580";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS)
case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS:
msg = "The asynchronous operation is not completed yet. - MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS -0x6500";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_EARLY_MESSAGE)
case MBEDTLS_ERR_SSL_EARLY_MESSAGE:
msg = "Internal-only message signaling that a message arrived early. - MBEDTLS_ERR_SSL_EARLY_MESSAGE -0x6480";
break;
#endif
#if defined(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS)
case MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS:
msg = "A cryptographic operation is in progress. - MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS -0x7000";
break;
#endif
default:
msg.append("Last error was: ").append( QString::number(ret) );
}
#endif
return msg;
}
void ProviderUdpSSL::closeSSLNotify()
{
int ret = 0;
sslLog( "Closing SSL connection..." );
/* No error checking, the connection might be closed already */
do
{
ret = mbedtls_ssl_close_notify(&ssl);
}
while (ret == MBEDTLS_ERR_SSL_WANT_WRITE);
sslLog( "SSL Connection successful closed" );
}

View File

@ -0,0 +1,210 @@
#pragma once
#include <leddevice/LedDevice.h>
#include <utils/Logger.h>
// Qt includes
#include <QMutex>
#include <QMutexLocker>
#include <QHostInfo>
#include <QThread>
//----------- mbedtls
#if !defined(MBEDTLS_CONFIG_FILE)
#include <mbedtls/config.h>
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_PLATFORM_C)
#include <mbedtls/platform.h>
#else
#include <stdio.h>
#include <stdlib.h>
#define mbedtls_time time
#define mbedtls_time_t time_t
#define mbedtls_printf printf
#define mbedtls_fprintf fprintf
#define mbedtls_snprintf snprintf
#define mbedtls_calloc calloc
#define mbedtls_free free
#define mbedtls_exit exit
#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
#endif
#include <string.h>
#include <cstring>
#include <mbedtls/net_sockets.h>
#include <mbedtls/ssl_ciphersuites.h>
#include <mbedtls/entropy.h>
#include <mbedtls/timing.h>
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/error.h>
#include <mbedtls/debug.h>
#define READ_TIMEOUT_MS 1000
#define MAX_RETRY 5
//----------- END mbedtls
const ushort MAX_PORT_SSL = 65535;
class ProviderUdpSSL : public LedDevice
{
Q_OBJECT
public:
///
/// Constructs specific LedDevice
///
ProviderUdpSSL();
///
/// Destructor of the LedDevice; closes the output device if it is open
///
virtual ~ProviderUdpSSL() override;
///
/// Sets configuration
///
/// @param deviceConfig the json device config
/// @return true if success
virtual bool init(const QJsonObject &deviceConfig) override;
public slots:
///
/// Closes the output device.
/// Includes switching-off the device and stopping refreshes
///
virtual void close() override;
protected:
///
/// Initialise device's network details
///
/// @return True if success
///
bool initNetwork();
///
/// Opens and configures the output device
///
/// @return Zero on succes else negative
///
int open() override;
///
/// Writes the given bytes/bits to the UDP-device and sleeps the latch time to ensure that the
/// values are latched.
///
/// @param[in] size The length of the data
/// @param[in] data The data
///
void writeBytes(const unsigned size, const uint8_t *data);
///
/// get ciphersuites list from mbedtls_ssl_list_ciphersuites
///
/// @return const int * array
///
virtual const int * getCiphersuites();
void sslLog(const QString &msg, const char* errorType = "debug");
void sslLog(const char* msg, const char* errorType = "debug");
void configLog(const char* msg, const char* type, ...);
/**
* Debug callback for mbed TLS
* Just prints on the USB serial port
*/
static void ProviderUdpSSLDebug(void *ctx, int level, const char *file, int line, const char *str)
{
const char *p, *basename;
(void) ctx;
/* Extract basename from file */
for(p = basename = file; *p != '\0'; p++)
{
if(*p == '/' || *p == '\\')
{
basename = p + 1;
}
}
mbedtls_printf("%s:%04d: |%d| %s", basename, line, level, str);
}
/**
* Certificate verification callback for mbed TLS
* Here we only use it to display information on each cert in the chain
*/
static int ProviderUdpSSLVerify(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags)
{
const uint32_t buf_size = 1024;
char *buf = new char[buf_size];
(void) data;
mbedtls_printf("\nVerifying certificate at depth %d:\n", depth);
mbedtls_x509_crt_info(buf, buf_size - 1, " ", crt);
mbedtls_printf("%s", buf);
if (*flags == 0)
mbedtls_printf("No verification issue for this certificate\n");
else
{
mbedtls_x509_crt_verify_info(buf, buf_size, " ! ", *flags);
mbedtls_printf("%s\n", buf);
}
delete[] buf;
return 0;
}
///
/// closeSSLNotify and freeSSLConnection
///
void closeSSLConnection();
private:
bool buildConnection();
bool initConnection();
bool seedingRNG();
bool setupStructure();
bool startUPDConnection();
bool setupPSK();
bool startSSLHandshake();
void handleReturn(int ret);
QString errorMsg(int ret);
void closeSSLNotify();
void freeSSLConnection();
mbedtls_net_context client_fd;
mbedtls_entropy_context entropy;
mbedtls_ssl_context ssl;
mbedtls_ssl_config conf;
mbedtls_x509_crt cacert;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_timing_delay_context timer;
QMutex _hueMutex;
QString _transport_type;
QString _custom;
QHostAddress _address;
QString _defaultHost;
int _port;
int _ssl_port;
QString _server_name;
QString _psk;
QString _psk_identity;
uint32_t _read_timeout;
uint32_t _handshake_timeout_min;
uint32_t _handshake_timeout_max;
unsigned int _handshake_attempts;
int _retry_left;
bool _stopConnection;
bool _debugStreamer;
int _debugLevel;
};

View File

@ -14,45 +14,233 @@
"default": "",
"propertyOrder" : 2
},
"clientkey": {
"type": "string",
"title":"edt_dev_spec_clientKey_title",
"default" : "",
"options": {
"dependencies": {
"useEntertainmentAPI": true
}
},
"propertyOrder" : 3
},
"useEntertainmentAPI": {
"type": "boolean",
"title":"edt_dev_spec_useEntertainmentAPI_title",
"default" : false,
"propertyOrder" : 4
},
"transitiontime": {
"type": "integer",
"type": "number",
"title":"edt_dev_spec_transistionTime_title",
"default" : 1,
"append" : "x100ms",
"propertyOrder" : 3
"options": {
"dependencies": {
"useEntertainmentAPI": false
}
},
"propertyOrder" : 5
},
"switchOffOnBlack": {
"type": "boolean",
"title":"edt_dev_spec_switchOffOnBlack_title",
"default" : true,
"propertyOrder" : 4
},
"brightnessFactor": {
"type": "number",
"title":"edt_dev_spec_brightnessFactor_title",
"default" : 1.0,
"minimum" : 0.5,
"maximum" : 10.0,
"propertyOrder" : 5
"options": {
"dependencies": {
"useEntertainmentAPI": false
}
},
"propertyOrder" : 6
},
"restoreOriginalState": {
"type": "boolean",
"title":"edt_dev_spec_restoreOriginalState_title",
"default" : true,
"propertyOrder" : 6
"propertyOrder" : 7
},
"lightIds": {
"type": "array",
"title":"edt_dev_spec_lightid_title",
"minItems": 1,
"uniqueItems" : true,
"items" : {
"type" : "integer",
"type" : "string",
"minimum" : 0,
"title" : "edt_dev_spec_lightid_itemtitle"
},
"propertyOrder" : 7
"options": {
"dependencies": {
"useEntertainmentAPI": false
}
},
"propertyOrder" : 8
},
"groupId": {
"type": "number",
"title":"edt_dev_spec_groupId_title",
"default" : 0,
"options": {
"dependencies": {
"useEntertainmentAPI": true
}
},
"propertyOrder" : 9
},
"blackLightsTimeout": {
"type": "number",
"title":"edt_dev_spec_blackLightsTimeout_title",
"default" : 15000,
"step": 500,
"minimum" : 10000,
"maximum" : 60000,
"access" : "advanced",
"append" : "edt_append_ms",
"options": {
"dependencies": {
"useEntertainmentAPI": true
}
},
"propertyOrder" : 10
},
"brightnessThreshold": {
"type": "number",
"title":"edt_dev_spec_brightnessThreshold_title",
"default" : 0,
"step": 0.005,
"minimum" : 0,
"maximum" : 1.0,
"access" : "advanced",
"options": {
"dependencies": {
"useEntertainmentAPI": true
}
},
"propertyOrder" : 11
},
"brightnessFactor": {
"type": "number",
"title":"edt_dev_spec_brightnessFactor_title",
"default" : 1.0,
"step": 0.25,
"minimum" : 0.5,
"maximum" : 10.0,
"access" : "advanced",
"propertyOrder" : 12
},
"brightnessMin": {
"type": "number",
"title":"edt_dev_spec_brightnessMin_title",
"default" : 0,
"step": 0.05,
"minimum" : 0,
"maximum" : 1.0,
"access" : "advanced",
"options": {
"dependencies": {
"useEntertainmentAPI": true
}
},
"propertyOrder" : 13
},
"brightnessMax": {
"type": "number",
"title":"edt_dev_spec_brightnessMax_title",
"default" : 1.0,
"step": 0.05,
"minimum" : 0,
"maximum" : 1.0,
"access" : "advanced",
"options": {
"dependencies": {
"useEntertainmentAPI": true
}
},
"propertyOrder" : 14
},
"sslReadTimeout": {
"type": "number",
"title":"edt_dev_spec_sslReadTimeout_title",
"default" : 0,
"step": 100,
"minimum" : 0,
"maximum" : 30000,
"access" : "expert",
"append" : "edt_append_ms",
"options": {
"dependencies": {
"useEntertainmentAPI": true
}
},
"propertyOrder" : 15
},
"sslHSTimeoutMin": {
"type": "number",
"title":"edt_dev_spec_sslHSTimeoutMin_title",
"default" : 400,
"step": 100,
"minimum" : 0,
"maximum" : 30000,
"access" : "expert",
"append" : "edt_append_ms",
"options": {
"dependencies": {
"useEntertainmentAPI": true
}
},
"propertyOrder" : 16
},
"sslHSTimeoutMax": {
"type": "number",
"title":"edt_dev_spec_sslHSTimeoutMax_title",
"default" : 1000,
"step": 100,
"minimum" : 0,
"maximum" : 30000,
"access" : "expert",
"append" : "edt_append_ms",
"options": {
"dependencies": {
"useEntertainmentAPI": true
}
},
"propertyOrder" : 17
},
"verbose": {
"type": "boolean",
"title":"edt_dev_spec_verbose_title",
"default" : false,
"access" : "expert",
"propertyOrder" : 18
},
"debugStreamer": {
"type": "boolean",
"title":"edt_dev_spec_debugStreamer_title",
"default" : false,
"access" : "expert",
"options": {
"dependencies": {
"useEntertainmentAPI": true
}
},
"propertyOrder" : 19
},
"debugLevel": {
"type": "string",
"title":"edt_dev_spec_debugLevel_title",
"enum" : ["0", "1", "2", "3", "4"],
"default" : "0",
"options" : {
"enum_titles" : ["edt_conf_enum_dl_nodebug", "edt_conf_enum_dl_error", "edt_conf_enum_dl_statechange", "edt_conf_enum_dl_informational", "edt_conf_enum_dl_verbose"],
"dependencies": {
"useEntertainmentAPI": true
}
},
"minimum" : 0,
"maximum" : 4,
"access" : "expert",
"propertyOrder" : 20
}
},
"additionalProperties": true

View File

@ -24,7 +24,7 @@ SSDPHandler::SSDPHandler(WebServer* webserver, const quint16& flatBufPort, const
SSDPHandler::~SSDPHandler()
{
sendAnnounceList(false);
stopServer();
}
void SSDPHandler::initServer()
@ -60,6 +60,12 @@ void SSDPHandler::initServer()
}
}
void SSDPHandler::stopServer()
{
sendAnnounceList(false);
SSDPServer::stop();
}
void SSDPHandler::handleSettingsUpdate(const settings::type& type, const QJsonDocument& config)
{
if(type == settings::FLATBUFSERVER)

View File

@ -112,6 +112,9 @@ HyperionDaemon::HyperionDaemon(const QString rootPath, QObject *parent, const bo
//connect(_hyperion,SIGNAL(closing()),this,SLOT(freeObjects())); // TODO for app restart, refactor required
//Cleaning up Hyperion before quit
connect(parent, SIGNAL(aboutToQuit()), this, SLOT(freeObjects()));
// pipe settings changes and component state changes from HyperionIManager to Daemon
connect(_instanceManager, &HyperionIManager::settingsChanged, this, &HyperionDaemon::settingsChanged);
connect(_instanceManager, &HyperionIManager::compStateChangeRequest, this, &HyperionDaemon::compStateChangeRequest);
@ -141,7 +144,6 @@ HyperionDaemon::HyperionDaemon(const QString rootPath, QObject *parent, const bo
HyperionDaemon::~HyperionDaemon()
{
freeObjects();
delete _settingsManager;
delete _pyInit;
}
@ -162,6 +164,8 @@ const QJsonDocument HyperionDaemon::getSetting(const settings::type &type)
void HyperionDaemon::freeObjects()
{
Debug(_log, "Cleaning up Hyperion before quit.");
// destroy network first as a client might want to access hyperion
delete _jsonServer;
_flatBufferServer->thread()->quit();

View File

@ -1,5 +1,6 @@
#pragma once
#include <QApplication>
#include <QObject>
#include <QJsonObject>