From abc798a4792b36f46cb5aea17fc988a06b2e67d1 Mon Sep 17 00:00:00 2001 From: penfold42 Date: Sun, 22 Jan 2017 20:27:01 +1100 Subject: [PATCH 1/5] Updated adalight sketch to use the number of leds sent in the header (#374) - NUM_LEDS becomes MAX_LEDS and any led data beyond that is ignored Added a python udp listener and serial sender. - Intended for windows users with a COM port based led strip. - Works with hyperion --- assets/firmware/arduino/adalight/adalight.ino | 52 ++--- .../network_bridge/udpraw_serialadalight.py | 197 ++++++++++++++++++ 2 files changed, 225 insertions(+), 24 deletions(-) create mode 100755 assets/firmware/arduino/network_bridge/udpraw_serialadalight.py diff --git a/assets/firmware/arduino/adalight/adalight.ino b/assets/firmware/arduino/adalight/adalight.ino index d7ce571c..470c9595 100644 --- a/assets/firmware/arduino/adalight/adalight.ino +++ b/assets/firmware/arduino/adalight/adalight.ino @@ -9,10 +9,11 @@ set following values to your needs **************************************/ -#define INITAL_LED_TEST_ENABLED true +#define INITIAL_LED_TEST_ENABLED true +#define INITIAL_LED_TEST_BRIGHTNESS 32 // 0..255 // Number of leds in your strip. set to "1" and ANALOG_OUTPUT_ENABLED to "true" to activate analog only -#define NUM_LEDS 100 +#define MAX_LEDS 100 // type of your led controller, possible values, see below #define LED_TYPE WS2812B @@ -54,8 +55,9 @@ #define COLOR_CORRECTION TypicalLEDStrip // predefined fastled color correction //#define COLOR_CORRECTION CRGB(255,255,255) // or RGB value describing the color correction -// Baudrate, higher rate allows faster refresh rate and more LEDs (defined in /etc/boblight.conf) +// Baudrate, higher rate allows faster refresh rate and more LEDs #define serialRate 460800 // use 115200 for ftdi based boards +//#define serialRate 115200 // use 115200 for ftdi based boards /************************************** @@ -70,7 +72,7 @@ uint8_t prefix[] = {'A', 'd', 'a'}, hi, lo, chk, i; unsigned long endTime; // Define the array of leds -CRGB leds[NUM_LEDS]; +CRGB leds[MAX_LEDS]; // set rgb to analog led stripe void showAnalogRGB(const CRGB& led) { @@ -86,7 +88,7 @@ void showAnalogRGB(const CRGB& led) { // set color to all leds void showColor(const CRGB& led) { - #if NUM_LEDS > 1 || ANALOG_OUTPUT_ENABLED == false + #if MAX_LEDS > 1 || ANALOG_OUTPUT_ENABLED == false LEDS.showColor(led); #endif showAnalogRGB(led); @@ -94,8 +96,8 @@ void showColor(const CRGB& led) { // switch of digital and analog leds void switchOff() { - #if NUM_LEDS > 1 || ANALOG_OUTPUT_ENABLED == false - memset(leds, 0, NUM_LEDS * sizeof(struct CRGB)); + #if MAX_LEDS > 1 || ANALOG_OUTPUT_ENABLED == false + memset(leds, 0, MAX_LEDS * sizeof(struct CRGB)); FastLED.show(); #endif showAnalogRGB(leds[0]); @@ -118,25 +120,25 @@ bool checkIncommingData() { // main function that setups and runs the code void setup() { - - // additional ground pin to make wiring a bit easier - pinMode(ANALOG_GROUND_PIN, OUTPUT); - digitalWrite(ANALOG_GROUND_PIN, LOW); + Serial.begin(serialRate); // analog output if (ANALOG_OUTPUT_ENABLED) { + // additional ground pin to make wiring a bit easier + pinMode(ANALOG_GROUND_PIN, OUTPUT); + digitalWrite(ANALOG_GROUND_PIN, LOW); pinMode(ANALOG_BLUE_PIN , OUTPUT); pinMode(ANALOG_RED_PIN , OUTPUT); pinMode(ANALOG_GREEN_PIN, OUTPUT); } // Uncomment/edit one of the following lines for your leds arrangement. - int ledCount = NUM_LEDS; + int ledCount = MAX_LEDS; if (ANALOG_MODE == ANALOG_MODE_LAST_LED) { ledCount--; } - #if NUM_LEDS > 1 || ANALOG_OUTPUT_ENABLED == false + #if MAX_LEDS > 1 || ANALOG_OUTPUT_ENABLED == false FastLED.addLeds(leds, ledCount); #endif @@ -147,14 +149,14 @@ void setup() { FastLED.setDither ( DITHER_MODE ); // initial RGB flash - #if INITAL_LED_TEST_ENABLED == true - showColor(CRGB(255, 0, 0)); delay(400); - showColor(CRGB(0, 255, 0)); delay(400); - showColor(CRGB(0, 0, 255)); delay(400); + #if INITIAL_LED_TEST_ENABLED == true + Serial.println("initial test"); + showColor(CRGB(INITIAL_LED_TEST_BRIGHTNESS, 0, 0)); delay(400); + showColor(CRGB(0, INITIAL_LED_TEST_BRIGHTNESS, 0)); delay(400); + showColor(CRGB(0, 0, INITIAL_LED_TEST_BRIGHTNESS )); delay(400); #endif showColor(CRGB(0, 0, 0)); - Serial.begin(serialRate); Serial.print("Ada\n"); // Send "Magic Word" string to host @@ -183,14 +185,16 @@ void setup() { // if checksum does not match go back to wait if (chk != (hi ^ lo ^ 0x55)) continue; - memset(leds, 0, NUM_LEDS * sizeof(struct CRGB)); + memset(leds, 0, MAX_LEDS * sizeof(struct CRGB)); transmissionSuccess = true; sum_r = 0; sum_g = 0; sum_b = 0; + int num_leds = (hi<<8) + lo + 1; + // read the transmission data and set LED values - for (uint8_t idx = 0; idx < NUM_LEDS; idx++) { + for (uint8_t idx = 0; idx < min(num_leds,MAX_LEDS); idx++) { byte r, g, b; if (!checkIncommingData()) { transmissionSuccess = false; @@ -220,22 +224,22 @@ void setup() { // shows new values if (transmissionSuccess) { endTime = millis() + OFF_TIMEOUT; - #if NUM_LEDS > 1 || ANALOG_OUTPUT_ENABLED == false + #if MAX_LEDS > 1 || ANALOG_OUTPUT_ENABLED == false FastLED.show(); #endif #if ANALOG_OUTPUT_ENABLED == true #if ANALOG_MODE == ANALOG_MODE_LAST_LED - showAnalogRGB(leds[NUM_LEDS-1]); + showAnalogRGB(leds[MAX_LEDS-1]); #else - showAnalogRGB(CRGB(sum_r/NUM_LEDS, sum_g/NUM_LEDS, sum_b/NUM_LEDS)); + showAnalogRGB(CRGB(sum_r/MAX_LEDS, sum_g/MAX_LEDS, sum_b/MAX_LEDS)); #endif #endif } } } // end of setup - void loop() { // Not used. See note in setup() function. } + diff --git a/assets/firmware/arduino/network_bridge/udpraw_serialadalight.py b/assets/firmware/arduino/network_bridge/udpraw_serialadalight.py new file mode 100755 index 00000000..2d49363d --- /dev/null +++ b/assets/firmware/arduino/network_bridge/udpraw_serialadalight.py @@ -0,0 +1,197 @@ +#!/usr/bin/env python +# + +# Simple UDP to Serial redirector. +# Author: https://github.com/penfold42 + +# raw udp packets to raw serial: +# python.exe udp_adalight.py -P 2801 COM4 115200 + +# raw udp packets to adalight serial protocol: +# python.exe udp_adalight.py -a -P 2801 COM4 115200 + +# Derived from: https://github.com/pyserial/pyserial/blob/master/examples/tcp_serial_redirect.py +# +# (C) 2002-2016 Chris Liechti +# +# SPDX-License-Identifier: BSD-3-Clause + +import sys +import socket +import serial +import serial.threaded +import time + + +class SerialToNet(serial.threaded.Protocol): + """serial->socket""" + + def __init__(self): + self.socket = None + + def __call__(self): + return self + + def data_received(self, data): + if self.socket is not None: + self.socket.sendall(data) + + +if __name__ == '__main__': # noqa + import argparse + + parser = argparse.ArgumentParser( + description='Simple UDP to Serial redirector.', + epilog="""\ +NOTE: no security measures are implemented. Anyone can remotely connect +to this service over the network. +""") + + parser.add_argument( + 'SERIALPORT', + help="serial port name") + + parser.add_argument( + 'BAUDRATE', + type=int, + nargs='?', + help='set baud rate, default: %(default)s', + default=115200) + + parser.add_argument( + '-q', '--quiet', + action='store_true', + help='suppress non error messages', + default=False) + + parser.add_argument( + '-a', '--ada', + action='store_true', + help='prepend adalight header to serial packets', + default=False) + + parser.add_argument( + '--develop', + action='store_true', + help='Development mode, prints Python internals on errors', + default=False) + + group = parser.add_argument_group('serial port') + + group.add_argument( + "--parity", + choices=['N', 'E', 'O', 'S', 'M'], + type=lambda c: c.upper(), + help="set parity, one of {N E O S M}, default: N", + default='N') + + group.add_argument( + '--rtscts', + action='store_true', + help='enable RTS/CTS flow control (default off)', + default=False) + + group.add_argument( + '--xonxoff', + action='store_true', + help='enable software flow control (default off)', + default=False) + + group.add_argument( + '--rts', + type=int, + help='set initial RTS line state (possible values: 0, 1)', + default=None) + + group.add_argument( + '--dtr', + type=int, + help='set initial DTR line state (possible values: 0, 1)', + default=None) + + group = parser.add_argument_group('network settings') + + exclusive_group = group.add_mutually_exclusive_group() + + exclusive_group.add_argument( + '-P', '--localport', + type=int, + help='local UDP port', + default=2801) + + args = parser.parse_args() + + # connect to serial port + ser = serial.serial_for_url(args.SERIALPORT, do_not_open=True) + ser.baudrate = args.BAUDRATE + ser.parity = args.parity + ser.rtscts = args.rtscts + ser.xonxoff = args.xonxoff + + if args.rts is not None: + ser.rts = args.rts + + if args.dtr is not None: + ser.dtr = args.dtr + + if not args.quiet: + sys.stderr.write( + '--- UDP to Serial redirector\n' + '--- listening on udp port {a.localport}\n' + '--- sending to {p.name} {p.baudrate},{p.bytesize}{p.parity}{p.stopbits}\n' + '--- type Ctrl-C / BREAK to quit\n'.format(p=ser, a=args)) + + try: + ser.open() + except serial.SerialException as e: + sys.stderr.write('Could not open serial port {}: {}\n'.format(ser.name, e)) + sys.exit(1) + + ser_to_net = SerialToNet() + serial_worker = serial.threaded.ReaderThread(ser, ser_to_net) + serial_worker.start() + + srv = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + srv.bind(('', args.localport)) + + try: + intentional_exit = False + while True: + try: + while True: + try: + data,addr = srv.recvfrom(1024) + if not data: + break + + if args.ada: + numleds = len(data)/3 + hi = (numleds-1)/256 + lo = (numleds-1)&255 + sum = hi^lo^0x55 + ser.write ("Ada"+ chr(hi) + chr(lo) + chr(sum)) + + ser.write(data) # get a bunch of bytes and send them + except socket.error as msg: + if args.develop: + raise + sys.stderr.write('ERROR: {}\n'.format(msg)) + # probably got disconnected + break + except KeyboardInterrupt: + intentional_exit = True + raise + except socket.error as msg: + if args.develop: + raise + sys.stderr.write('ERROR: {}\n'.format(msg)) + finally: + ser_to_net.socket = None + sys.stderr.write('Disconnected\n') + except KeyboardInterrupt: + pass + + sys.stderr.write('\n--- exit ---\n') + serial_worker.stop() + From 3aa2573b88335b1de4dbed468ab12ca80c333b43 Mon Sep 17 00:00:00 2001 From: redPanther Date: Sun, 22 Jan 2017 14:31:11 +0100 Subject: [PATCH 2/5] destroy grabbers and other stuff on hyperiond restart via webui (#375) * remove obsolete kodi code for grabbers * destroy grabbers and other stuff on hyperiond restart via webui --- include/hyperion/Hyperion.h | 1 + libsrc/grabber/v4l2/V4L2Grabber.cpp | 1 + libsrc/hyperion/GrabberWrapper.cpp | 2 ++ libsrc/hyperion/Hyperion.cpp | 2 ++ src/hyperiond/CMakeLists.txt | 9 ++++++++- src/hyperiond/hyperiond.cpp | 20 ++++++++++++++++++-- src/hyperiond/hyperiond.h | 4 ++++ 7 files changed, 36 insertions(+), 3 deletions(-) diff --git a/include/hyperion/Hyperion.h b/include/hyperion/Hyperion.h index f320e197..4320a63d 100644 --- a/include/hyperion/Hyperion.h +++ b/include/hyperion/Hyperion.h @@ -289,6 +289,7 @@ signals: void imageToLedsMappingChanged(int mappingType); void emitImage(int priority, const Image & image, const int timeout_ms); + void closing(); private slots: /// diff --git a/libsrc/grabber/v4l2/V4L2Grabber.cpp b/libsrc/grabber/v4l2/V4L2Grabber.cpp index 8e71406b..c04587f7 100644 --- a/libsrc/grabber/v4l2/V4L2Grabber.cpp +++ b/libsrc/grabber/v4l2/V4L2Grabber.cpp @@ -74,6 +74,7 @@ V4L2Grabber::~V4L2Grabber() void V4L2Grabber::uninit() { + Debug(_log,"uninit grabber: %s", _deviceName.c_str()); // stop if the grabber was not stopped if (_initialized) { diff --git a/libsrc/hyperion/GrabberWrapper.cpp b/libsrc/hyperion/GrabberWrapper.cpp index 2ef9951d..dcdd28de 100644 --- a/libsrc/hyperion/GrabberWrapper.cpp +++ b/libsrc/hyperion/GrabberWrapper.cpp @@ -27,6 +27,8 @@ GrabberWrapper::GrabberWrapper(std::string grabberName, const int priority, hype GrabberWrapper::~GrabberWrapper() { + stop(); + Debug(_log,"Close grabber: %s", _grabberName.c_str()); delete _processor; } diff --git a/libsrc/hyperion/Hyperion.cpp b/libsrc/hyperion/Hyperion.cpp index c6f17504..53dc5291 100644 --- a/libsrc/hyperion/Hyperion.cpp +++ b/libsrc/hyperion/Hyperion.cpp @@ -449,6 +449,8 @@ Hyperion::Hyperion(const QJsonObject &qjsonConfig, const QString configFile) void Hyperion::freeObjects() { + emit closing(); + // switch off all leds clearall(); _device->switchOff(); diff --git a/src/hyperiond/CMakeLists.txt b/src/hyperiond/CMakeLists.txt index 820a23ef..08929a55 100644 --- a/src/hyperiond/CMakeLists.txt +++ b/src/hyperiond/CMakeLists.txt @@ -1,11 +1,18 @@ +SET(Hyperiond_QT_HEADERS + hyperiond.h +) + +QT5_WRAP_CPP(Hyperiond_HEADERS_MOC ${Hyperiond_QT_HEADERS}) + add_executable(hyperiond + ${Hyperiond_QT_HEADERS} + ${Hyperiond_HEADERS_MOC} configMigratorBase.cpp configMigratorBase.h configMigrator.cpp configMigrator.h hyperiond.cpp - hyperiond.h main.cpp ) diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index 781504ff..77bb9196 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -79,6 +79,13 @@ HyperionDaemon::HyperionDaemon(QString configFile, QObject *parent) HyperionDaemon::~HyperionDaemon() { + freeObjects(); + delete _hyperion; +} + +void HyperionDaemon::freeObjects() +{ + Debug(_log, "destroy grabbers and network stuff"); delete _amlGrabber; delete _dispmanx; delete _fbGrabber; @@ -92,8 +99,17 @@ HyperionDaemon::~HyperionDaemon() delete _protoServer; delete _boblightServer; delete _udpListener; - delete _hyperion; + _v4l2Grabbers.clear(); + _amlGrabber = nullptr; + _dispmanx = nullptr; + _fbGrabber = nullptr; + _osxGrabber = nullptr; + _kodiVideoChecker = nullptr; + _jsonServer = nullptr; + _protoServer = nullptr; + _boblightServer = nullptr; + _udpListener = nullptr; } void HyperionDaemon::run() @@ -113,7 +129,7 @@ void HyperionDaemon::run() #endif Info(_log, "Hyperion started"); - + connect(_hyperion,SIGNAL(closing()),this,SLOT(freeObjects())); } int HyperionDaemon::tryLoadConfig(const QString & configFile, const int schemaVersion) diff --git a/src/hyperiond/hyperiond.h b/src/hyperiond/hyperiond.h index f5dce843..a1f3acd7 100644 --- a/src/hyperiond/hyperiond.h +++ b/src/hyperiond/hyperiond.h @@ -49,6 +49,7 @@ class HyperionDaemon : public QObject { + Q_OBJECT public: HyperionDaemon(QString configFile, QObject *parent=nullptr); ~HyperionDaemon(); @@ -65,6 +66,9 @@ public: void createGrabberV4L2(); void createSystemFrameGrabber(); +public slots: + void freeObjects(); + private: void createGrabberDispmanx(); void createGrabberAmlogic(); From cde5a4dff17c2a26802eb32edc166b0250398e9b Mon Sep 17 00:00:00 2001 From: redPanther Date: Sun, 22 Jan 2017 19:36:52 +0100 Subject: [PATCH 3/5] send close signal only on restart to avoid problems while destructiong on normal exit (#376) --- include/hyperion/Hyperion.h | 2 +- libsrc/hyperion/Hyperion.cpp | 9 ++++++--- libsrc/jsonserver/JsonClientConnection.cpp | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/include/hyperion/Hyperion.h b/include/hyperion/Hyperion.h index 4320a63d..26d6be9e 100644 --- a/include/hyperion/Hyperion.h +++ b/include/hyperion/Hyperion.h @@ -70,7 +70,7 @@ public: /// /// free all alocated objects, should be called only from constructor or before restarting hyperion /// - void freeObjects(); + void freeObjects(bool emitCloseSignal=false); static Hyperion* initInstance(const QJsonObject& qjsonConfig, const QString configFile); static Hyperion* getInstance(); diff --git a/libsrc/hyperion/Hyperion.cpp b/libsrc/hyperion/Hyperion.cpp index 53dc5291..70715cfb 100644 --- a/libsrc/hyperion/Hyperion.cpp +++ b/libsrc/hyperion/Hyperion.cpp @@ -447,9 +447,12 @@ Hyperion::Hyperion(const QJsonObject &qjsonConfig, const QString configFile) } -void Hyperion::freeObjects() +void Hyperion::freeObjects(bool emitCloseSignal) { - emit closing(); + if (emitCloseSignal) + { + emit closing(); + } // switch off all leds clearall(); @@ -464,7 +467,7 @@ void Hyperion::freeObjects() Hyperion::~Hyperion() { - freeObjects(); + freeObjects(false); } unsigned Hyperion::getLedCount() const diff --git a/libsrc/jsonserver/JsonClientConnection.cpp b/libsrc/jsonserver/JsonClientConnection.cpp index e5ef87a8..4773eb11 100644 --- a/libsrc/jsonserver/JsonClientConnection.cpp +++ b/libsrc/jsonserver/JsonClientConnection.cpp @@ -930,7 +930,7 @@ void JsonClientConnection::handleConfigCommand(const QJsonObject& message, const } else if (subcommand == "reload") { - _hyperion->freeObjects(); + _hyperion->freeObjects(true); Process::restartHyperion(); sendErrorReply("failed to restart hyperion", full_command, tan); } From 8a4d1c5088b6478fa9a2e8d2a37d85022cd3f0ba Mon Sep 17 00:00:00 2001 From: redPanther Date: Mon, 23 Jan 2017 23:21:04 +0100 Subject: [PATCH 4/5] implement 404 for webserver - this is a quick hack, should be refactored later (#378) --- libsrc/webconfig/StaticFileServing.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libsrc/webconfig/StaticFileServing.cpp b/libsrc/webconfig/StaticFileServing.cpp index 00e43bca..8796b365 100644 --- a/libsrc/webconfig/StaticFileServing.cpp +++ b/libsrc/webconfig/StaticFileServing.cpp @@ -73,6 +73,13 @@ static inline void printErrorToReply (QtHttpReply * reply, QString errorMessage) reply->appendRawData (errorMessage.toLocal8Bit ()); } +static inline void printError404ToReply (QtHttpReply * reply, QString errorMessage) +{ + reply->setStatusCode(QtHttpReply::NotFound); + reply->addHeader ("Content-Type", QByteArrayLiteral ("text/plain")); + reply->appendRawData (errorMessage.toLocal8Bit ()); +} + void StaticFileServing::onRequestNeedsReply (QtHttpRequest * request, QtHttpReply * reply) { QString command = request->getCommand (); @@ -103,7 +110,7 @@ void StaticFileServing::onRequestNeedsReply (QtHttpRequest * request, QtHttpRepl Q_INIT_RESOURCE(WebConfig); QFileInfo info(_baseUrl % "/" % path); - if ( path == "/" || path.isEmpty() || ! info.exists() ) + if ( path == "/" || path.isEmpty() ) { path = "index.html"; } @@ -134,7 +141,7 @@ void StaticFileServing::onRequestNeedsReply (QtHttpRequest * request, QtHttpRepl } else { - printErrorToReply (reply, "Requested file " % path % " couldn't be found !"); + printError404ToReply (reply, "404 Not Found\n" % path % " couldn't be found !"); } } else From ed4785251862aaa4e128af76023a2493ed71881b Mon Sep 17 00:00:00 2001 From: Paulchen Panther Date: Mon, 23 Jan 2017 23:25:12 +0100 Subject: [PATCH 5/5] Remove duplicated Code (#377) * Reduce Duplicate Code * Reduce Duplicate Code * No Error Logging when "document_root" in Json config is empty * Update JsonClientConnection.cpp * Remove obsolete functions * create readConfig and readSchema function * set forgotten _error variable --- include/utils/jsonschema/QJsonFactory.h | 57 ++++++++++++++++--- include/utils/jsonschema/QJsonSchemaChecker.h | 17 ------ libsrc/jsonserver/JsonClientConnection.cpp | 2 +- .../utils/jsonschema/QJsonSchemaChecker.cpp | 1 + libsrc/webconfig/WebConfig.cpp | 4 +- src/hyperiond/hyperiond.cpp | 48 ++++------------ test/TestConfigFile.cpp | 39 +++---------- 7 files changed, 73 insertions(+), 95 deletions(-) diff --git a/include/utils/jsonschema/QJsonFactory.h b/include/utils/jsonschema/QJsonFactory.h index 63bbed3a..83b2a53e 100644 --- a/include/utils/jsonschema/QJsonFactory.h +++ b/include/utils/jsonschema/QJsonFactory.h @@ -21,8 +21,8 @@ public: static int load(const QString& schema, const QString& config, QJsonObject& json) { // Load the schema and the config trees - QJsonObject schemaTree = readJson(schema); - QJsonObject configTree = readJson(config); + QJsonObject schemaTree = readSchema(schema); + QJsonObject configTree = readConfig(config); // create the validator QJsonSchemaChecker schemaChecker; @@ -45,15 +45,15 @@ public: return 0; } - static QJsonObject readJson(const QString& path) + static QJsonObject readConfig(const QString& path) { QFile file(path); QJsonParseError error; - + if (!file.open(QIODevice::ReadOnly)) { std::stringstream sstream; - sstream << "Configuration file not found: " << file.errorString().toStdString(); + sstream << "Configuration file not found: '" << path.toStdString() << "' (" << file.errorString().toStdString() << ")"; throw std::runtime_error(sstream.str()); } @@ -61,12 +61,13 @@ public: config.remove(QRegularExpression("([^:]?\\/\\/.*)")); QJsonDocument doc = QJsonDocument::fromJson(config.toUtf8(), &error); - + file.close(); + if (error.error != QJsonParseError::NoError) { // report to the user the failure and their locations in the document. int errorLine(0), errorColumn(0); - + for( int i=0, count=qMin( error.offset,config.size()); igetConfigFileName())); + result["result"] = QJsonFactory::readConfig(QString::fromStdString(_hyperion->getConfigFileName())); } catch(...) { diff --git a/libsrc/utils/jsonschema/QJsonSchemaChecker.cpp b/libsrc/utils/jsonschema/QJsonSchemaChecker.cpp index 5f53a578..6b3e738d 100644 --- a/libsrc/utils/jsonschema/QJsonSchemaChecker.cpp +++ b/libsrc/utils/jsonschema/QJsonSchemaChecker.cpp @@ -115,6 +115,7 @@ void QJsonSchemaChecker::validate(const QJsonValue & value, const QJsonObject &s else { // no check function defined for this attribute + _error = true; setMessage(std::string("No check function defined for attribute ") + attribute.toStdString()); continue; } diff --git a/libsrc/webconfig/WebConfig.cpp b/libsrc/webconfig/WebConfig.cpp index 9e776dba..6d1f0696 100644 --- a/libsrc/webconfig/WebConfig.cpp +++ b/libsrc/webconfig/WebConfig.cpp @@ -23,7 +23,7 @@ WebConfig::WebConfig(QObject * parent) _baseUrl = webconfigConfig["document_root"].toString(_baseUrl); } - if (_baseUrl != ":/webconfig") + if ( (_baseUrl != ":/webconfig") && !_baseUrl.trimmed().isEmpty()) { QFileInfo info(_baseUrl); if (!info.exists() || !info.isDir()) @@ -32,6 +32,8 @@ WebConfig::WebConfig(QObject * parent) _baseUrl = WEBCONFIG_DEFAULT_PATH; } } + else + _baseUrl = WEBCONFIG_DEFAULT_PATH; Debug(log, "WebUI initialized, document root: %s", _baseUrl.toUtf8().constData()); if ( webconfigEnable ) diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index 77bb9196..ff5a7b33 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -136,49 +136,26 @@ int HyperionDaemon::tryLoadConfig(const QString & configFile, const int schemaVe { // make sure the resources are loaded (they may be left out after static linking) Q_INIT_RESOURCE(resource); - QJsonParseError error; // read the json schema from the resource QString schemaFile = ":/hyperion-schema"; if (schemaVersion > 0) - schemaFile += "-" + QString::number(schemaVersion); - QFile schemaData(schemaFile); - if (!schemaData.open(QIODevice::ReadOnly)) - { - std::stringstream error; - error << "Schema not found or not supported: " << schemaData.errorString().toStdString(); - throw std::runtime_error(error.str()); - } - - QByteArray schema = schemaData.readAll(); - QJsonDocument schemaJson = QJsonDocument::fromJson(schema, &error); - schemaData.close(); - - if (error.error != QJsonParseError::NoError) - { - // report to the user the failure and their locations in the document. - int errorLine(0), errorColumn(0); - - for( int i=0, count=qMin( error.offset,schema.size()); i::const_iterator i = schemaChecker.getMessages().begin(); i != schemaChecker.getMessages().end(); ++i) @@ -193,7 +170,6 @@ int HyperionDaemon::tryLoadConfig(const QString & configFile, const int schemaVe return generalConfig["configVersion"].toInt(-1); } - void HyperionDaemon::loadConfig(const QString & configFile, const int neededConfigVersion) { Info(_log, "Selected configuration file: %s", configFile.toUtf8().constData()); @@ -488,7 +464,7 @@ void HyperionDaemon::createSystemFrameGrabber() else if (type == "x11") createGrabberX11(grabberConfig); else { Warning( _log, "unknown framegrabber type '%s'", type.toUtf8().constData()); grabberCompState = false; } - _hyperion->getComponentRegister().componentStateChanged(hyperion::COMP_GRABBER, grabberCompState); +// _hyperion->getComponentRegister().componentStateChanged(hyperion::COMP_GRABBER, grabberCompState); _hyperion->setComponentState(hyperion::COMP_GRABBER, grabberCompState ); } } diff --git a/test/TestConfigFile.cpp b/test/TestConfigFile.cpp index 9c8d31c3..a654816c 100644 --- a/test/TestConfigFile.cpp +++ b/test/TestConfigFile.cpp @@ -16,53 +16,30 @@ bool loadConfig(const QString & configFile) { // make sure the resources are loaded (they may be left out after static linking) Q_INIT_RESOURCE(resource); - QJsonParseError error; //////////////////////////////////////////////////////////// // read and set the json schema from the resource //////////////////////////////////////////////////////////// - QFile schemaData(":/hyperion-schema-"+QString::number(CURRENT_CONFIG_VERSION)); - - if (!schemaData.open(QIODevice::ReadOnly)) + QJsonObject schemaJson; + + try { - std::stringstream error; - error << "Schema not found: " << schemaData.errorString().toStdString(); - throw std::runtime_error(error.str()); + schemaJson = QJsonFactory::readSchema(":/hyperion-schema"); } - - QByteArray schema = schemaData.readAll(); - QJsonDocument schemaJson = QJsonDocument::fromJson(schema, &error); - - if (error.error != QJsonParseError::NoError) + catch(const std::runtime_error& error) { - // report to the user the failure and their locations in the document. - int errorLine(0), errorColumn(0); - - for( int i=0, count=qMin( error.offset,schema.size()); i