added more documentation

This commit is contained in:
Simon Stürz 2014-12-12 16:23:41 +01:00 committed by Michael Zanetti
parent cf145bbe04
commit 0a79a644e2
18 changed files with 396 additions and 29 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

View File

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

View File

@ -72,7 +72,7 @@
\value DeviceErrorSetupFailed
Error setting up the \l{Device}. It will not be functional.
\value DeviceErrorDuplicateUuid
Error setting up the \l{Device}. The given DeviceId allready exists.
Error setting up the \l{Device}. The given DeviceId already exists.
\value DeviceErrorCreationMethodNotSupported
Error setting up the \l{Device}. This \l{DeviceClass}{CreateMethod} is not supported for this \l{Device}.
\value DeviceErrorSetupMethodNotSupported
@ -346,7 +346,7 @@ DeviceManager::DeviceError DeviceManager::pairDevice(const PairingTransactionId
return DeviceErrorNoError;
}
/*! Initiates a pairing with a \l{DeviceClass}{Device} with the given \a pairingTransactionId, \a deviceClassId and \a params.
/*! Initiates a pairing with a \l{DeviceClass}{Device} with the given \a pairingTransactionId, \a deviceClassId and \a deviceDescriptorId.
* Returns \l{DeviceManager::DeviceError}{DeviceError} to inform about the result. */
DeviceManager::DeviceError DeviceManager::pairDevice(const PairingTransactionId &pairingTransactionId, const DeviceClassId &deviceClassId, const DeviceDescriptorId &deviceDescriptorId)
{

View File

@ -18,21 +18,50 @@
/*!
\class Gpio
\brief The Gpio class helps to interact with the gpio pins of the Raspberry Pi.
\brief The Gpio class allows to interact with the GPIOs.
\ingroup hardware
\inmodule libguh
The Raspberry Pi offers lower-level interfaces (GPIO's) intended to connect more directly
with chips and subsystem modules. General Purpose Input/Output (a.k.a. GPIO) is a generic
pin on a chip whose behavior (including whether it is an input or output pin) can be controlled
through this class. An object of of the Gpio class represents a pin on the board.
A "General Purpose Input/Output" (GPIO) is a flexible software-controlled
digital signal. They are provided from many kinds of chip, and are familiar
to Linux developers working with embedded and custom hardware. Each GPIO
represents a bit connected to a particular pin, or "ball" on Ball Grid Array
(BGA) packages. Board schematics show which external hardware connects to
which GPIOs. Drivers can be written generically, so that board setup code
passes such pin configuration data to drivers
(\l{https://www.kernel.org/doc/Documentation/gpio/gpio.txt}{source}.
General Purpose Input/Output (a.k.a. GPIO) is a generic pin on a chip whose
behavior (including whether it is an input or output pin) can be controlled
through this class. An object of of the Gpio class represents a pin.
\chapter Example
Following example shows how to initialize and interact with a GPIO. The GPIO will be configured as an input,
set active high and the edge interrupt will be set to EDGE_BOTH.
\code
Gpio *gpio = new Gpio(this, 22);
if (!gpio->exportGpio() || !gpio->setDirection(INPUT) || !gpio->setEdgeInterrupt(EDGE_BOTH) || !gpio->setActiveLow(true)) {
return;
}
int value = gpio->getValue();
qDebug() << "value = " << value;
\endcode
\chapter Raspberry Pi GPIOs
In following table is a list of all GPIO's of the Raspberry Pi Rev. 2.0:
\image gpio.png "Gpio settings"
\image Raspberry_Pi_GPIO_Map.png "Raspberry Pi GPIO map"
Valid GPIO's for this class are those with a GPIO number (for example GPIO 22, which is on pin Nr. 15)
\chapter Beaglebone Black GPIOs
In following table is a list of all GPIO's of the Beaglebone Black (\l{http://pix.cs.olemiss.edu/csci581/BBBlackGPIOMap.png}{Source}):
\image Beaglebone_Black_GPIO_Map.png "Beaglebone Black GPIO map"
*/
#include "gpio.h"
@ -157,6 +186,15 @@ bool Gpio::setDirection(int dir)
close(fd);
return false;
}
/*! Returns the direction of this GPIO.
* \sa setDirection()
*/
int Gpio::getDirection()
{
return m_dir;
}
/*! Returns true if the digital \a value of the GPIO could be set correctly.
*
* Possible \a value 's are:
@ -315,6 +353,9 @@ bool Gpio::setEdgeInterrupt(int edge)
return false;
}
/*! This method allows to invert the logic of this GPIO.
* Returns true, if the GPIO could be set \a activeLow.
*/
bool Gpio::setActiveLow(bool activeLow)
{
char buf[64];
@ -347,16 +388,16 @@ bool Gpio::setActiveLow(bool activeLow)
return false;
}
int Gpio::gpioPin()
/*! Returns the number of this GPIO.
* \sa Gpio::Gpio()
*/
int Gpio::gpioNumber()
{
return m_gpio;
}
int Gpio::gpioDirection()
{
return m_dir;
}
/*! Returns true if the directory /sys/class/gpio does exist.
*/
bool Gpio::isAvailable()
{
QDir gpioDirectory("/sys/class/gpio");

View File

@ -83,6 +83,7 @@ public:
int openGpio();
bool setDirection(int dir);
int getDirection();
bool setValue(unsigned int value);
int getValue();
@ -90,9 +91,7 @@ public:
bool setEdgeInterrupt(int edge);
bool setActiveLow(bool activeLow);
int gpioPin();
int gpioDirection();
int gpioNumber();
bool isAvailable();
private:

View File

@ -16,13 +16,144 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*!
\class GpioMonitor
\brief The GpioMonitor class allows to monitor GPIOs.
\ingroup hardware
\inmodule libguh
An instance of this class creates a thread, which monitors each of the added GPIOs. The object
emits a signal if one of the added GPIOs changes its value. The GpioMonitor configures a GPIO as an
input, with the edge interrupt EDGE_BOTH (\l{Gpio::setEdgeInterrupt()}{setEdgeInterrupt}).
\chapter Example
Following example shows how to use the GpioMonitor class for a button on the Raspberry Pi. There are two possibilitys
to connect a button. Following picture shows the schematics:
\image Raspberry_Pi_Button_Example.png "Raspberry Pi button example"
Button A represents a clean solutin with a 10 k\unicode{0x2126} resistor (set up as activeLow = false).
Button B represents a "dirty" solution, were the 3.3V will be directly connected to the GPIO if the button is pressed (set activeLow = true).
Here is the code example for a button class:
\tt{guhbutton.h}
\code
#include <QObject>
#include <QDebug>
#include <QTimer>
#include "hardware/gpiomonitor.h"
class GuhButton : public QObject
{
Q_OBJECT
public:
explicit GuhButton(QObject *parent = 0, int gpio = 4);
bool enable();
void disable();
private:
GpioMonitor *m_monitor;
int m_gpioPin;
Gpio *m_gpio;
bool m_buttonPressed;
QTimer *m_longpressedTimer;
QTimer *m_debounceTimer;
signals:
void buttonPressed();
void buttonReleased();
void buttonLongPressed();
private slots:
void gpioChanged(const int &gpioPin, const int &value);
};
\endcode
\tt{guhbutton.cpp}
\code
#include "guhbutton.h"
GuhButton::GuhButton(QObject *parent, int gpio) :
QObject(parent), m_gpioPin(gpio)
{
m_buttonPressed = false;
}
bool GuhButton::enable()
{
qDebug() << "setup button on GPIO " << m_gpioPin;
m_monitor = new GpioMonitor(this);
m_gpio = new Gpio(this, m_gpioPin);
if(!m_monitor->addGpio(m_gpio, false)){
return false;
}
connect(m_monitor, &GpioMonitor::changed, this, &GuhButton::gpioChanged);
// Timer to generate the long pressed signal
m_longpressedTimer = new QTimer(this);
m_longpressedTimer->setInterval(500);
m_longpressedTimer->setSingleShot(true);
connect(m_longpressedTimer, &QTimer::timeout, this, &GuhButton::buttonLongPressed);
// Timer to debounce the button
m_debounceTimer = new QTimer(this);
m_debounceTimer->setSingleShot(true);
m_debounceTimer->setInterval(50);
m_monitor->enable();
return true;
}
void GuhButton::disable()
{
m_monitor->disable();
}
void GuhButton::gpioChanged(const int &gpioPin, const int &value)
{
if (gpioPin == m_gpioPin){
if(m_debounceTimer->isActive()){
return;
}
// check button state
bool buttonState = !QVariant(value).toBool();
if (m_buttonPressed != buttonState) {
if (buttonState) {
emit buttonPressed();
m_longpressedTimer->start();
m_debounceTimer->start();
} else {
emit buttonReleased();
m_longpressedTimer->stop();
}
m_buttonPressed = buttonState;
}
}
}
\endcode
*/
/*! \fn void GpioMonitor::changed(const int &gpioPin, const int &value);
* This signal will be emited, if one of the monitored \l{Gpio}{Gpios} changed his \a value. The \a gpioPin
* paramter describes which \l{Gpio} changed his \a value.
* \sa Gpio::gpioNumber()
*/
#include "gpiomonitor.h"
/*! Constructs a \l{GpioMonitor} object with the given \a parent. */
GpioMonitor::GpioMonitor(QObject *parent) :
QThread(parent)
{
}
/*! Destructs the object of this \l{GpioMonitor}.*/
GpioMonitor::~GpioMonitor()
{
foreach (Gpio* gpio, m_gpioList) {
@ -33,13 +164,28 @@ GpioMonitor::~GpioMonitor()
deleteLater();
}
void GpioMonitor::stop()
/*! Starts the \l{GpioMonitor}. While the \l{GpioMonitor} is running there can not be added new \l{Gpio}{Gpios}.
* \sa disable(), */
void GpioMonitor::enable()
{
m_enabledMutex.lock();
m_enabled = true;
m_enabledMutex.unlock();
start();
}
/*! Stops the \l{GpioMonitor}. No changes on the \l{Gpio} will be recognized.*/
void GpioMonitor::disable()
{
m_enabledMutex.lock();
m_enabled = false;
m_enabledMutex.unlock();
}
/*! Adds the given \l{Gpio} \a gpio to the monitor. This function can only be called if the monitor is not running.
* The given \a gpio will be configured as \a activeLow.
* Return true if the gpio could be added and set up correctly.
* \sa Gpio::setActiveLow(), */
bool GpioMonitor::addGpio(Gpio *gpio, bool activeLow)
{
if (!gpio->exportGpio() || !gpio->setDirection(INPUT) || !gpio->setEdgeInterrupt(EDGE_BOTH) || !gpio->setActiveLow(activeLow)) {
@ -51,6 +197,8 @@ bool GpioMonitor::addGpio(Gpio *gpio, bool activeLow)
return true;
}
/*! Returns the list of \l{Gpio}{Gpios} which currently are monitored.
* \sa addGpio(), */
QList<Gpio *> GpioMonitor::gpioList()
{
m_gpioListMutex.lock();
@ -59,6 +207,9 @@ QList<Gpio *> GpioMonitor::gpioList()
return gpioList;
}
/*! This method represents the reimplementation of the virtual void QThread::run() method. This method will be called from
* QThread by calling the method void QThread::start(). Never call this method directly.
* \sa enable(), */
void GpioMonitor::run()
{
struct pollfd *fds;
@ -90,7 +241,7 @@ void GpioMonitor::run()
lseek(fds[i].fd, 0, SEEK_SET);
retVal = read(fds[i].fd, &val, 1);
emit changed(m_gpioList[i]->gpioPin(), m_gpioList[i]->getValue());
emit changed(m_gpioList[i]->gpioNumber(), m_gpioList[i]->getValue());
if (retVal < 0) {
qWarning() << "ERROR: poll failed";

View File

@ -35,7 +35,8 @@ public:
explicit GpioMonitor(QObject *parent = 0);
~GpioMonitor();
void stop();
void enable();
void disable();
bool addGpio(Gpio *gpio, bool activeLow);
QList<Gpio*> gpioList();

View File

@ -249,7 +249,7 @@ void Radio433Receiver::handleTiming(int duration)
changeReading(true);
}
// check if we have allready a vallid protocol
// check if we have already a vallid protocol
// 1 sync bit + 48 data bit
if(m_timings.count() == 49 && checkValues(Protocol48)){
//qDebug() << "48 bit -> " << m_timings << "\n--------------------------";

View File

@ -207,7 +207,7 @@ State Device::state(const StateTypeId &stateTypeId) const
return State(StateTypeId(), DeviceId());
}
/*! Returns true, if setup of this Device is allready completed. */
/*! Returns true, if setup of this Device is already completed. */
bool Device::setupComplete() const
{
return m_setupComplete;

View File

@ -112,7 +112,10 @@ bool StateDescriptor::operator !=(const State &state) const
{
return !(operator==(state));
}
/*! Returns the true if this \l{StateDescriptor} is valid. A \l{StateDescriptor} is valid
* if the DeviceId and the StateTypeId are set and the state value of this \l{StateDescriptor} is valid.
* \sa StateDescriptor(), deviceId(), stateValue()
*/
bool StateDescriptor::isValid() const
{
return !m_deviceId.isNull() && !m_stateTypeId.isNull() && m_stateValue.isValid();

View File

@ -16,6 +16,84 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*!
\page commandlauncher.html
\title Application and script launcher
\ingroup plugins
\ingroup services
The application and script launcher plugin allows you to execute bash commands and start bash scripts.
\chapter Application launcher
The application launcher \l{DeviceClass} allows you to call bash applications or commands (with parameters)
from guh. Once, the application started, the \tt running \l{State} will change to \tt true, if the application
is finished, the \tt running \l{State} will change to \tt false.
\section3 Example
An example command could be \l{http://linux.die.net/man/1/espeak}{espeak}. (\tt{apt-get install espeak})
\code
espeak -v en "Chuck Norris is using gooe" # gooe = guh spelled correctly
\endcode
\chapter Bashscript launcher
The bashscript launcher \l{DeviceClass} allows you to call bash script (with parameters)
from guh. Once, the script is running, the \tt running \l{State} will change to \tt true, if the script
is finished, the \tt running \l{State} will change to \tt false.
\section3 Example
An example for a very usefull script could be a backup scrip like following \tt backup.sh script.
\code
#!/bin/sh
# Directories to backup...
backup_files="/home /etc /root /opt /var/www /var/lib/jenkins"
# Destination of the backup...
dest="/mnt/backup"
# Create archive filename...
day=$(date +%Y%m%d)
hostname="guh.guru"
archive_file="$day-$hostname.tgz"
# Print start status message...
echo "Backing up $backup_files to $dest/$archive_file"
date
echo
# Backup the files using tar.
tar czf $dest/$archive_file $backup_files
echo
echo "Backup finished"
date
echo "==========================="
echo " DONE, have a nice day! "
echo "==========================="
\endcode
To make the script executable use following command:
\code
chmod +x backup.sh
\endcode
\chapter Plugin properties
Following JSON file contains the definition and the description of all available \l{DeviceClass}{DeviceClasses}
and \l{Vendor}{Vendors} of this \l{DevicePlugin}.
Each \l{DeviceClass} has a list of \l{ParamType}{paramTypes}, \l{ActionType}{actionTypes}, \l{StateType}{stateTypes}
and \l{EventType}{eventTypes}. The \l{DeviceClass::CreateMethod}{createMethods} parameter describes how the \l{Device}
will be created in the system. A device can have more than one \l{DeviceClass::CreateMethod}{CreateMethod}.
The \l{DeviceClass::SetupMethod}{setupMethod} describes the setup method of the \l{Device}.
The detailed implementation of each \l{DeviceClass} can be found in the source code.
\quotefile plugins/deviceplugins/commandlauncher/deviceplugincommandlauncher.json
*/
#include "deviceplugincommandlauncher.h"
#include "plugin/device.h"
@ -71,7 +149,7 @@ DeviceManager::DeviceError DevicePluginCommandLauncher::executeAction(Device *de
if (device->deviceClassId() == applicationDeviceClassId ) {
// execute application...
if (action.actionTypeId() == executeActionTypeId) {
// check if we allready have started the application
// check if we already have started the application
if (m_applications.values().contains(device)) {
if (m_applications.key(device)->state() == QProcess::Running) {
return DeviceManager::DeviceErrorDeviceInUse;
@ -106,7 +184,7 @@ DeviceManager::DeviceError DevicePluginCommandLauncher::executeAction(Device *de
if (device->deviceClassId() == scriptDeviceClassId ) {
// execute script...
if (action.actionTypeId() == executeActionTypeId) {
// check if we allready have started the script
// check if we already have started the script
if (m_scripts.values().contains(device)) {
if (m_scripts.key(device)->state() == QProcess::Running) {
return DeviceManager::DeviceErrorDeviceInUse;

View File

@ -16,6 +16,61 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*!
\page datetime.html
\title Time
\ingroup plugins
\ingroup services
The time plugin allows you create rules based on the time, day, month, year, weekday or on weekend.
For the setup you need to specify the continent, afterwards you can select your city/timezone. The language
of the "month name" and "weekday name" depends on your locale settings. To have the correct time you need
\l{https://en.wikipedia.org/wiki/Network_Time_Protocol}{ntp}.
The weekday integer value stands for:
\table
\header
\li Weekday
\li int
\row
\li Monday
\li 1
\row
\li Tuesday
\li 2
\row
\li Wednesday
\li 3
\row
\li Thursday
\li 4
\row
\li Friday
\li 5
\row
\li Saturday
\li 6
\row
\li Sunday
\li 7
\endtable
The "weekend" \l{State} will be true, if the current weekday is Saturday or Sunday, otherwise it will be false.
\chapter Plugin properties
Following JSON file contains the definition and the description of all available \l{DeviceClass}{DeviceClasses}
and \l{Vendor}{Vendors} of this \l{DevicePlugin}.
Each \l{DeviceClass} has a list of \l{ParamType}{paramTypes}, \l{ActionType}{actionTypes}, \l{StateType}{stateTypes}
and \l{EventType}{eventTypes}. The \l{DeviceClass::CreateMethod}{createMethods} parameter describes how the \l{Device}
will be created in the system. A device can have more than one \l{DeviceClass::CreateMethod}{CreateMethod}.
The \l{DeviceClass::SetupMethod}{setupMethod} describes the setup method of the \l{Device}.
The detailed implementation of each \l{DeviceClass} can be found in the source code.
\quotefile plugins/deviceplugins/datetime/deviceplugindatetime.json
*/
#include "deviceplugindatetime.h"

View File

@ -110,7 +110,7 @@ DeviceManager::DeviceSetupStatus DevicePluginEQ3::setupDevice(Device *device)
if(device->deviceClassId() == cubeDeviceClassId){
foreach (MaxCube *cube, m_cubes.keys()) {
if(cube->serialNumber() == device->paramValue("serial number").toString()){
qDebug() << cube->serialNumber() << " allready exists...";
qDebug() << cube->serialNumber() << " already exists...";
return DeviceManager::DeviceSetupStatusFailure;
}
}

View File

@ -16,6 +16,41 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*!
\page genericelements.html
\title Generic elements
\ingroup plugins
\ingroup services
The generic elements plugin allows you create virtual buttons, which can be connected with a rule. This gives you
the possibility to execute multiple \l{Action}{Actions} with one signal. Without a rule this generic elements are
useless.
\chapter Toggle Button
With the "Toggle Button" \l{DeviceClass} you can create a button with one \l{Action} \unicode{0x2192} toggle. In the \tt state \l{State} you can find out,
what happens if the button will be pressed. The states can be true or false.
\chapter Button
With the "Button" \l{DeviceClass} you can create a button with one \l{Action} \unicode{0x2192} press. This button just creates one \l{Event}.
\chapter ON/OFF Button
With the "ON/OFF Button" \l{DeviceClass} you create a button pair with the \l{Action}{Actions} \unicode{0x2192} ON and OFF.
\chapter Plugin properties
Following JSON file contains the definition and the description of all available \l{DeviceClass}{DeviceClasses}
and \l{Vendor}{Vendors} of this \l{DevicePlugin}.
Each \l{DeviceClass} has a list of \l{ParamType}{paramTypes}, \l{ActionType}{actionTypes}, \l{StateType}{stateTypes}
and \l{EventType}{eventTypes}. The \l{DeviceClass::CreateMethod}{createMethods} parameter describes how the \l{Device}
will be created in the system. A device can have more than one \l{DeviceClass::CreateMethod}{CreateMethod}.
The \l{DeviceClass::SetupMethod}{setupMethod} describes the setup method of the \l{Device}.
The detailed implementation of each \l{DeviceClass} can be found in the source code.
\quotefile plugins/deviceplugins/genericelements/deviceplugingenericelements.json
*/
#include "deviceplugingenericelements.h"
#include "devicemanager.h"
#include "plugininfo.h"

View File

@ -23,7 +23,8 @@
\ingroup plugins
\ingroup network
This plugin allows to interact with \l{http://www.lg.com/us/experience-tvs/smart-tv}{LG Smart Tv's}.
This plugin allows to interact with \l{http://www.lg.com/us/experience-tvs/smart-tv}{LG Smart Tv's}
with the \l{http://developer.lgappstv.com/TV_HELP/index.jsp?topic=%2Flge.tvsdk.references.book%2Fhtml%2FUDAP%2FUDAP%2FLG+UDAP+2+0+Protocol+Specifications.htm}{LG UDAP 2.0 Protocol Specifications}.
\chapter Plugin properties
Following JSON file contains the definition and the description of all available \l{DeviceClass}{DeviceClasses}

View File

@ -27,6 +27,9 @@
\l{http://www.belkin.com/de/PRODUKTE/home-automation/c/wemo-home-automation/}{Belkin}
home automation system.
\underline{NOTE}: The devices can only be discovered if they are already in the local network. In order
to configure the WeMo devices please use the original software.
\chapter Plugin properties
Following JSON file contains the definition and the description of all available \l{DeviceClass}{DeviceClasses}
and \l{Vendor}{Vendors} of this \l{DevicePlugin}.
@ -72,7 +75,7 @@ DeviceManager::DeviceSetupStatus DevicePluginWemo::setupDevice(Device *device)
if(device->deviceClassId() == wemoSwitchDeviceClassId){
foreach (WemoSwitch *wemoSwitch, m_wemoSwitches.keys()) {
if(wemoSwitch->serialNumber() == device->paramValue("serial number").toString()){
qWarning() << wemoSwitch->serialNumber() << " allready exists...";
qWarning() << wemoSwitch->serialNumber() << " already exists...";
return DeviceManager::DeviceSetupStatusFailure;
}
}

View File

@ -139,7 +139,7 @@ void WemoDiscovery::readData()
}
if(!location.isEmpty() && !uuid.isEmpty()){
// check if we allready discovered this device
// check if we already discovered this device
foreach (WemoSwitch *device, m_deviceList) {
if(device->uuid() == uuid){
return;