merge to local


Former-commit-id: ebba9a31b2139201b75dc098eba8c8ee9d630ebf
This commit is contained in:
penfold42
2016-02-13 23:01:04 +11:00
61 changed files with 1322 additions and 198 deletions

View File

@@ -20,6 +20,8 @@ SET(Leddevice_QT_HEADERS
${CURRENT_SOURCE_DIR}/LedDevicePhilipsHue.h
${CURRENT_SOURCE_DIR}/LedHIDDevice.h
${CURRENT_SOURCE_DIR}/LedDeviceRawHID.h
${CURRENT_SOURCE_DIR}/LedDeviceTest.h
${CURRENT_SOURCE_DIR}/LedDeviceFadeCandy.h
)
SET(Leddevice_HEADERS
@@ -31,8 +33,9 @@ SET(Leddevice_HEADERS
${CURRENT_SOURCE_DIR}/LedDevicePaintpack.h
${CURRENT_SOURCE_DIR}/LedDevicePiBlaster.h
${CURRENT_SOURCE_DIR}/LedDeviceSedu.h
${CURRENT_SOURCE_DIR}/LedDeviceTest.h
${CURRENT_SOURCE_DIR}/LedDeviceUdp.h
${CURRENT_SOURCE_DIR}/LedDeviceTest.h
${CURRENT_SOURCE_DIR}/LedDeviceFadeCandy.h
${CURRENT_SOURCE_DIR}/LedDeviceUdp.h
${CURRENT_SOURCE_DIR}/LedDeviceHyperionUsbasp.h
${CURRENT_SOURCE_DIR}/LedDeviceTpm2.h
${CURRENT_SOURCE_DIR}/LedDeviceAtmo.h
@@ -53,8 +56,9 @@ SET(Leddevice_SOURCES
${CURRENT_SOURCE_DIR}/LedDevicePaintpack.cpp
${CURRENT_SOURCE_DIR}/LedDevicePiBlaster.cpp
${CURRENT_SOURCE_DIR}/LedDeviceSedu.cpp
${CURRENT_SOURCE_DIR}/LedDeviceTest.cpp
${CURRENT_SOURCE_DIR}/LedDeviceUdp.cpp
${CURRENT_SOURCE_DIR}/LedDeviceTest.cpp
${CURRENT_SOURCE_DIR}/LedDeviceFadeCandy.cpp
${CURRENT_SOURCE_DIR}/LedDeviceUdp.cpp
${CURRENT_SOURCE_DIR}/LedDeviceHyperionUsbasp.cpp
${CURRENT_SOURCE_DIR}/LedDevicePhilipsHue.cpp
${CURRENT_SOURCE_DIR}/LedDeviceTpm2.cpp
@@ -104,8 +108,12 @@ if(ENABLE_TINKERFORGE)
)
endif(ENABLE_TINKERFORGE)
if(ENABLE_QT5)
QT5_WRAP_CPP(Leddevice_HEADERS_MOC ${Leddevice_QT_HEADERS})
else(ENABLE_QT5)
QT4_WRAP_CPP(Leddevice_HEADERS_MOC ${Leddevice_QT_HEADERS})
endif(ENABLE_QT5)
add_library(leddevice
${Leddevice_HEADERS}
@@ -114,9 +122,13 @@ add_library(leddevice
${Leddevice_SOURCES}
)
if(ENABLE_QT5)
qt5_use_modules(leddevice Widgets Network)
endif(ENABLE_QT5)
target_link_libraries(leddevice
hyperion-utils
serialport
serialport
${LIBUSB_1_LIBRARIES} #apt-get install libusb-1.0-0-dev
${CMAKE_THREAD_LIBS_INIT}
${QT_LIBRARIES}

View File

@@ -1,9 +1,7 @@
// STL includes
#include <cstring>
#include <cstdio>
#include <iostream>
#include <algorithm>
// Linux includes
#include <fcntl.h>
@@ -19,27 +17,46 @@ LedDeviceAPA102::LedDeviceAPA102(const std::string& outputDevice, const unsigned
// empty
}
#define MIN(a,b) ((a)<(b)?(a):(b))
#define MAX(a,b) ((a)>(b)?(a):(b))
#define APA102_START_FRAME_BYTES 4
#define APA102_LED_BYTES 4
#define APA102_END_FRAME_BITS_MIN 32
#define APA102_END_FRAME_BITS(leds) MAX((((leds-1)/2)+1),APA102_END_FRAME_BITS_MIN)
#define APA102_END_FRAME_BYTES(leds) (((APA102_END_FRAME_BITS(leds)-1)/8)+1)
#define APA102_LED_HEADER 0xe0
#define APA102_LED_MAX_INTENSITY 0x1f
int LedDeviceAPA102::write(const std::vector<ColorRgb> &ledValues)
{
const unsigned int startFrameSize = 4;
const unsigned int endFrameSize = std::max<unsigned int>(((ledValues.size() + 15) / 16), 4);
const unsigned int mLedCount = (ledValues.size() * 4) + startFrameSize + endFrameSize;
if(_ledBuffer.size() != mLedCount){
_ledBuffer.resize(mLedCount, 0xFF);
_ledBuffer[0] = 0x00;
_ledBuffer[1] = 0x00;
_ledBuffer[2] = 0x00;
_ledBuffer[3] = 0x00;
const unsigned int startFrameSize = APA102_START_FRAME_BYTES;
const unsigned int ledsCount = ledValues.size() ;
const unsigned int ledsSize = ledsCount * APA102_LED_BYTES ;
const unsigned int endFrameBits = APA102_END_FRAME_BITS(ledsCount) ;
const unsigned int endFrameSize = APA102_END_FRAME_BYTES(ledsCount) ;
const unsigned int transferSize = startFrameSize + ledsSize + endFrameSize ;
if(_ledBuffer.size() != transferSize){
_ledBuffer.resize(transferSize, 0x00);
}
for (unsigned iLed=1; iLed<=ledValues.size(); ++iLed) {
const ColorRgb& rgb = ledValues[iLed-1];
_ledBuffer[iLed*4] = 0xFF;
_ledBuffer[iLed*4+1] = rgb.red;
_ledBuffer[iLed*4+2] = rgb.green;
_ledBuffer[iLed*4+3] = rgb.blue;
unsigned idx = 0, i;
for (i=0; i<APA102_START_FRAME_BYTES; i++) {
_ledBuffer[idx++] = 0x00 ;
}
for (i=0; i<ledsCount; i++) {
const ColorRgb& rgb = ledValues[i];
_ledBuffer[idx++] = APA102_LED_HEADER + APA102_LED_MAX_INTENSITY;
_ledBuffer[idx++] = rgb.red;
_ledBuffer[idx++] = rgb.green;
_ledBuffer[idx++] = rgb.blue;
}
for(i=0; i<endFrameSize; i++)
_ledBuffer[idx++] = 0x00 ;
return writeBytes(_ledBuffer.size(), _ledBuffer.data());
}

View File

@@ -3,7 +3,6 @@
#include <cstring>
#include <cstdio>
#include <iostream>
#include <algorithm>
// Linux includes
#include <fcntl.h>
@@ -13,30 +12,38 @@
#include "LedDeviceAdalightApa102.h"
LedDeviceAdalightApa102::LedDeviceAdalightApa102(const std::string& outputDevice, const unsigned baudrate, int delayAfterConnect_ms) :
LedDeviceAdalight(outputDevice, baudrate, delayAfterConnect_ms),
LedRs232Device(outputDevice, baudrate, delayAfterConnect_ms),
_ledBuffer(0),
_timer()
{
// setup the timer
_timer.setSingleShot(false);
_timer.setInterval(5000);
connect(&_timer, SIGNAL(timeout()), this, SLOT(rewriteLeds()));
// start the timer
_timer.start();
}
//comparing to ws2801 adalight, the following changes were needed:
// 1- differnt data frame (4 bytes instead of 3)
// 2 - in order to accomodate point 1 above, number of leds sent to adalight is increased by 1/3rd
int LedDeviceAdalightApa102::write(const std::vector<ColorRgb> & ledValues)
{
ledCount = ledValues.size();
const unsigned int startFrameSize = 4;
const unsigned int endFrameSize = std::max<unsigned int>(((ledValues.size() + 15) / 16), 4);
const unsigned int mLedCount = (ledValues.size() * 4) + startFrameSize + endFrameSize;
if(_ledBuffer.size() != mLedCount){
_ledBuffer.resize(mLedCount, 0xFF);
const unsigned int endFrameSize = std::max<unsigned int>(((ledCount + 15) / 16), 4);
const unsigned int mLedCount = (ledCount * 4) + startFrameSize + endFrameSize;
if(_ledBuffer.size() != mLedCount+6){
_ledBuffer.resize(mLedCount+6, 0x00);
_ledBuffer[0] = 'A';
_ledBuffer[1] = 'd';
_ledBuffer[2] = 'a';
_ledBuffer[3] = (((unsigned int)(ledValues.size() * 1.33) - 1) >> 8) & 0xFF; // LED count high byte
_ledBuffer[4] = ((unsigned int)(ledValues.size() * 1.33) - 1) & 0xFF; // LED count low byte
_ledBuffer[3] = (((unsigned int)(ledValues.size())) >> 8) & 0xFF; // LED count high byte
_ledBuffer[4] = ((unsigned int)(ledValues.size())) & 0xFF; // LED count low byte
_ledBuffer[5] = _ledBuffer[3] ^ _ledBuffer[4] ^ 0x55; // Checksum
}
for (unsigned iLed=1; iLed<=ledValues.size(); iLed++) {
for (unsigned iLed=1; iLed<=ledCount; iLed++) {
const ColorRgb& rgb = ledValues[iLed-1];
_ledBuffer[iLed*4+6] = 0xFF;
_ledBuffer[iLed*4+1+6] = rgb.red;
@@ -51,4 +58,25 @@ int LedDeviceAdalightApa102::write(const std::vector<ColorRgb> & ledValues)
return writeBytes(_ledBuffer.size(), _ledBuffer.data());
}
int LedDeviceAdalightApa102::switchOff()
{
for (unsigned iLed=1; iLed<=ledCount; iLed++) {
_ledBuffer[iLed*4+6] = 0xFF;
_ledBuffer[iLed*4+1+6] = 0x00;
_ledBuffer[iLed*4+2+6] = 0x00;
_ledBuffer[iLed*4+3+6] = 0x00;
}
// restart the timer
_timer.start();
// write data
return writeBytes(_ledBuffer.size(), _ledBuffer.data());
}
void LedDeviceAdalightApa102::rewriteLeds()
{
writeBytes(_ledBuffer.size(), _ledBuffer.data());
}

View File

@@ -7,12 +7,12 @@
#include <QTimer>
// hyperion incluse
#include "LedDeviceAdalight.h"
#include "LedRs232Device.h"
///
/// Implementation of the LedDevice interface for writing to an Adalight led device for APA102.
///
class LedDeviceAdalightApa102 : public LedDeviceAdalight
class LedDeviceAdalightApa102 : public LedRs232Device
{
Q_OBJECT
@@ -32,13 +32,17 @@ public:
/// @return Zero on succes else negative
///
virtual int write(const std::vector<ColorRgb> & ledValues);
virtual int switchOff();
private slots:
/// Write the last data to the leds again
void rewriteLeds();
private:
/// The buffer containing the packed RGB values
std::vector<uint8_t> _ledBuffer;
unsigned int ledCount;
/// Timer object which makes sure that led data is written at a minimum rate
/// The Adalight device will switch off when it does not receive data at least
/// every 15 seconds

View File

@@ -30,6 +30,7 @@
#include "LedDevicePiBlaster.h"
#include "LedDeviceSedu.h"
#include "LedDeviceTest.h"
#include "LedDeviceFadeCandy.h"
#include "LedDeviceUdp.h"
#include "LedDeviceHyperionUsbasp.h"
#include "LedDevicePhilipsHue.h"
@@ -245,6 +246,13 @@ LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig)
const std::string output = deviceConfig["output"].asString();
device = new LedDeviceTest(output);
}
else if (type == "fadecandy")
{
const std::string host = deviceConfig.get("output", "127.0.0.1").asString();
const uint16_t port = deviceConfig.get("port", 7890).asInt();
const uint16_t channel = deviceConfig.get("channel", 0).asInt();
device = new LedDeviceFadeCandy(host, port, channel);
}
else if (type == "udp")
{
const std::string output = deviceConfig["output"].asString();

View File

@@ -0,0 +1,90 @@
#include "LedDeviceFadeCandy.h"
static const ssize_t MAX_NUM_LEDS = 10000; // OPC can handle 21845 leds - in theory, fadecandy device should handle 10000 leds
static const ssize_t OPC_SET_PIXELS = 0; // OPC command codes
static const ssize_t OPC_HEADER_SIZE = 4; // OPC header size
LedDeviceFadeCandy::LedDeviceFadeCandy(const std::string& host, const uint16_t port, const unsigned channel) :
_host(host), _port(port), _channel(channel)
{
_opc_data.resize( OPC_HEADER_SIZE );
_opc_data[0] = channel;
_opc_data[1] = OPC_SET_PIXELS;
_opc_data[2] = 0;
_opc_data[3] = 0;
}
LedDeviceFadeCandy::~LedDeviceFadeCandy()
{
_client.close();
}
bool LedDeviceFadeCandy::isConnected()
{
return _client.state() == QAbstractSocket::ConnectedState;
}
bool LedDeviceFadeCandy::tryConnect()
{
if ( _client.state() == QAbstractSocket::UnconnectedState ) {
_client.connectToHost( _host.c_str(), _port);
if ( _client.waitForConnected(1000) )
qDebug("fadecandy/opc: connected to %s:%i on channel %i", _host.c_str(), _port, _channel);
}
return isConnected();
}
int LedDeviceFadeCandy::write( const std::vector<ColorRgb> & ledValues )
{
ssize_t nrLedValues = ledValues.size();
ssize_t led_data_size = nrLedValues * 3; // 3 color bytes
ssize_t opc_data_size = led_data_size + OPC_HEADER_SIZE;
if (nrLedValues > MAX_NUM_LEDS)
{
std::cerr << "fadecandy/opc: Invalid attempt to write led values. Not more than " << MAX_NUM_LEDS << " leds are allowed." << std::endl;
return -1;
}
if ( opc_data_size != _opc_data.size() )
_opc_data.resize( opc_data_size );
_opc_data[2] = led_data_size >> 8;
_opc_data[3] = led_data_size & 0xff;
uint idx = OPC_HEADER_SIZE;
for (const ColorRgb& color : ledValues)
{
_opc_data[idx ] = unsigned( color.red );
_opc_data[idx+1] = unsigned( color.green );
_opc_data[idx+2] = unsigned( color.blue );
idx += 3;
}
return ( transferData()<0 ? -1 : 0 );
}
int LedDeviceFadeCandy::transferData()
{
if ( isConnected() || tryConnect() )
return _client.write( _opc_data, _opc_data.size() );
return -2;
}
int LedDeviceFadeCandy::switchOff()
{
for ( int idx=OPC_HEADER_SIZE; idx < _opc_data.size(); idx++ )
_opc_data[idx] = 0;
return ( transferData()<0 ? -1 : 0 );
}

View File

@@ -0,0 +1,71 @@
#pragma once
// STL/Qt includes
#include <fstream>
#include <QObject>
#include <QTcpSocket>
// Leddevice includes
#include <leddevice/LedDevice.h>
///
/// Implementation of the LedDevice interface for sending to
/// fadecandy/opc-server via network by using the 'open pixel control' protocol.
///
class LedDeviceFadeCandy : public QObject, public LedDevice
{
Q_OBJECT
public:
///
/// Constructs the LedDevice for fadecandy/opc server
///
/// @param host The ip address/host name of fadecandy/opc server
/// @param port The port to use (fadecandy default is 7890)
///
LedDeviceFadeCandy(const std::string& host, const uint16_t port, const unsigned channel);
///
/// Destructor of the LedDevice; closes the tcp client
///
virtual ~LedDeviceFadeCandy();
///
/// Writes the led color values to the led-device
///
/// @param ledValues The color-value per led
/// @return Zero on succes else negative
///
virtual int write(const std::vector<ColorRgb> & ledValues);
/// Switch the leds off
virtual int switchOff();
private:
QTcpSocket _client;
const std::string _host;
const uint16_t _port;
const unsigned _channel;
QByteArray _opc_data;
/// try to establish connection to opc server, if not connected yet
///
/// @return true if connection is established
///
bool tryConnect();
/// return the conenction state
///
/// @return True if connection established
///
bool isConnected();
/// transfer current opc_data buffer to opc server
///
/// @return amount of transfered bytes. -1 error while transfering, -2 error while connecting
///
int transferData();
};

View File

@@ -5,10 +5,9 @@
#include <json/json.h>
// qt includes
#include <QtCore/qmath.h>
#include <QUrl>
#include <QHttpRequestHeader>
#include <QtCore/qmath.h>
#include <QEventLoop>
#include <QNetworkReply>
#include <set>
@@ -144,14 +143,14 @@ LedDevicePhilipsHue::LedDevicePhilipsHue(const std::string& output, const std::s
int transitiontime, std::vector<unsigned int> lightIds) :
host(output.c_str()), username(username.c_str()), switchOffOnBlack(switchOffOnBlack), transitiontime(
transitiontime), lightIds(lightIds) {
http = new QHttp(host);
manager = new QNetworkAccessManager();
timer.setInterval(3000);
timer.setSingleShot(true);
connect(&timer, SIGNAL(timeout()), this, SLOT(restoreStates()));
}
LedDevicePhilipsHue::~LedDevicePhilipsHue() {
delete http;
delete manager;
}
int LedDevicePhilipsHue::write(const std::vector<ColorRgb> & ledValues) {
@@ -215,34 +214,30 @@ int LedDevicePhilipsHue::switchOff() {
return 0;
}
void LedDevicePhilipsHue::put(QString route, QString content) {
QString url = QString("/api/%1/%2").arg(username).arg(route);
QHttpRequestHeader header("PUT", url);
header.setValue("Host", host);
header.setValue("Accept-Encoding", "identity");
header.setValue("Connection", "keep-alive");
header.setValue("Content-Length", QString("%1").arg(content.size()));
QEventLoop loop;
// Connect requestFinished signal to quit slot of the loop.
loop.connect(http, SIGNAL(requestFinished(int, bool)), SLOT(quit()));
void LedDevicePhilipsHue::put(QString route, QString content) {
QString url = QString("http://%1/api/%2/%3").arg(host).arg(username).arg(route);
// Perfrom request
http->request(header, content.toAscii());
QNetworkRequest request(url);
QNetworkReply* reply = manager->put(request, content.toLatin1());
// Connect finished signal to quit slot of the loop.
QEventLoop loop;
loop.connect(reply, SIGNAL(finished()), SLOT(quit()));
// Go into the loop until the request is finished.
loop.exec();
}
QByteArray LedDevicePhilipsHue::get(QString route) {
QString url = QString("/api/%1/%2").arg(username).arg(route);
// Event loop to block until request finished.
QEventLoop loop;
// Connect requestFinished signal to quit slot of the loop.
loop.connect(http, SIGNAL(requestFinished(int, bool)), SLOT(quit()));
QByteArray LedDevicePhilipsHue::get(QString route) {
QString url = QString("http://%1/api/%2/%3").arg(host).arg(username).arg(route);
// Perfrom request
http->get(url);
QNetworkRequest request(url);
QNetworkReply* reply = manager->get(request);
// Connect requestFinished signal to quit slot of the loop.
QEventLoop loop;
loop.connect(reply, SIGNAL(finished()), SLOT(quit()));
// Go into the loop until the request is finished.
loop.exec();
// Read all data of the response.
return http->readAll();
// Read all data of the response.
return reply->readAll();
}
QString LedDevicePhilipsHue::getStateRoute(unsigned int lightId) {

View File

@@ -6,9 +6,8 @@
// Qt includes
#include <QObject>
#include <QString>
#include <QHttp>
#include <QNetworkAccessManager>
#include <QTimer>
// Leddevice includes
#include <leddevice/LedDevice.h>
@@ -164,8 +163,8 @@ private:
QString host;
/// User name for the API ("newdeveloper")
QString username;
/// Qhttp object for sending requests.
QHttp* http;
/// QNetworkAccessManager object for sending requests.
QNetworkAccessManager* manager;
/// Use timer to reset lights when we got into "GRABBINGMODE_OFF".
QTimer timer;
///