Add serial parameter

pull/2/head
Simon Stürz 2018-01-02 18:48:07 +01:00
parent eb093b27cc
commit bbc9cb0ba1
10 changed files with 295 additions and 166 deletions

View File

@ -39,24 +39,24 @@ ZigbeeNetworkManager::ZigbeeNetworkManager(const int &channel, const QString &se
qCDebug(dcZigbee()) << "Using channel" << channel << "for the zigbee network.";
}
// Call init methods
erasePersistentData();
//resetController();
getVersion();
setExtendedPanId(m_extendedPanId);
setChannelMask(channelMask);
setDeviceType(NodeTypeCoordinator);
startNetwork();
// // Call init methods
// erasePersistentData();
// //resetController();
// getVersion();
// setExtendedPanId(m_extendedPanId);
// setChannelMask(channelMask);
// setDeviceType(NodeTypeCoordinator);
// startNetwork();
//startScan();
//getPermitJoiningStatus();
enableWhitelist();
permitJoining();
//getPermitJoiningStatus();
// //startScan();
// //getPermitJoiningStatus();
// enableWhitelist();
// permitJoining();
// //getPermitJoiningStatus();
//startScan();
initiateTouchLink();
// //startScan();
// initiateTouchLink();
}
QString ZigbeeNetworkManager::controllerVersion() const
@ -69,16 +69,16 @@ QList<ZigbeeNode *> ZigbeeNetworkManager::nodeList() const
return m_nodeList;
}
quint64 ZigbeeNetworkManager::extendedPanId() const
{
return m_extendedPanId;
}
bool ZigbeeNetworkManager::networkRunning() const
{
return m_networkRunning;
}
void ZigbeeNetworkManager::reset()
{
qCCritical(dcZigbee()) << "Reset networkmanager: TODO: needs to be implementet";
}
quint64 ZigbeeNetworkManager::generateRandomPanId()
{
srand(static_cast<int>(QDateTime::currentMSecsSinceEpoch() / 1000));
@ -86,6 +86,59 @@ quint64 ZigbeeNetworkManager::generateRandomPanId()
return (ULLONG_MAX - 0) * (qrand()/(double)RAND_MAX);
}
void ZigbeeNetworkManager::parseNetworkFormed(const QByteArray &data)
{
// Parse network status
quint8 networkStatus = static_cast<quint8>(data.at(0));
QString networkStatusString;
if (networkStatus == 0) {
networkStatusString = "joined";
} else if (networkStatus == 1) {
networkStatusString = "created";
} else if (networkStatus >= 128 && networkStatus <= 244) {
networkStatusString = "failed: Zigbee event code: " + QString::number(networkStatus);
} else {
networkStatusString = "unknown";
}
// Parse short network address
quint16 shortAddress = data.at(1);
shortAddress <<= 8;
shortAddress |= data.at(2);
// Parse extended network address
quint64 extendedAddress = data.at(3);
extendedAddress <<= 8;
extendedAddress |= data.at(4);
extendedAddress <<= 8;
extendedAddress |= data.at(5);
extendedAddress <<= 8;
extendedAddress |= data.at(6);
extendedAddress <<= 8;
extendedAddress |= data.at(7);
extendedAddress <<= 8;
extendedAddress |= data.at(8);
extendedAddress <<= 8;
extendedAddress |= data.at(9);
extendedAddress <<= 8;
extendedAddress |= data.at(10);
// Parse network channel
quint8 channel = static_cast<quint8>(data.at(11));
qCDebug(dcZigbee()).noquote() << "Network" << networkStatusString;
qCDebug(dcZigbee()) << " Address:" << ZigbeeUtils::convertUint16ToHexString(shortAddress);
qCDebug(dcZigbee()) << " Extended address:" << ZigbeeAddress(extendedAddress);
qCDebug(dcZigbee()) << " Channel:" << channel;
// Set the node information
setShortAddress(shortAddress);
setExtendedAddress(ZigbeeAddress(extendedAddress));
}
void ZigbeeNetworkManager::loadNetwork()
{
qCDebug(dcZigbee()) << "Loading network nodes";
@ -100,7 +153,7 @@ void ZigbeeNetworkManager::loadNetwork()
node->setExtendedAddress(ZigbeeAddress(nodeAddress));
node->setShortAddress(shortAddress);
m_nodeList.append(node);
node->init();
//node->init();
}
}
@ -194,7 +247,17 @@ void ZigbeeNetworkManager::setDeviceType(const NodeType &deviceType)
stream << deviceTypeValue;
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeSetDeviceType, data));
request.setDescription("Set device type");
switch (deviceType) {
case NodeTypeCoordinator:
request.setDescription("Set device type coordinator");
break;
case NodeTypeRouter:
request.setDescription("Set device type router");
break;
default:
break;
}
ZigbeeInterfaceReply *reply = controller()->sendRequest(request);
connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onSetDeviceTypeFinished);
@ -265,6 +328,16 @@ void ZigbeeNetworkManager::initiateTouchLink()
connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onInitiateTouchLinkFinished);
}
void ZigbeeNetworkManager::touchLinkFactoryReset()
{
ZigbeeInterfaceRequest request(ZigbeeInterfaceMessage(Zigbee::MessageTypeTouchlinkFactoryReset));
request.setDescription("Touch link factory reset");
ZigbeeInterfaceReply *reply = controller()->sendRequest(request);
connect(reply, &ZigbeeInterfaceReply::finished, this, &ZigbeeNetworkManager::onTouchLinkFactoryResetFinished);
}
void ZigbeeNetworkManager::requestMatchDescriptor(const quint16 &shortAddress, const Zigbee::ZigbeeProfile &profile)
{
QByteArray data;
@ -402,54 +475,7 @@ void ZigbeeNetworkManager::onStartNetworkFinished()
qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully";
qCDebug(dcZigbeeController()) << reply->additionalMessage();
// Parse network status
quint8 networkStatus = static_cast<quint8>(reply->additionalMessage().data().at(0));
QString networkStatusString;
if (networkStatus == 0) {
networkStatusString = "joined";
} else if (networkStatus == 1) {
networkStatusString = "created";
} else if (networkStatus >= 128 && networkStatus <= 244) {
networkStatusString = "failed: Zigbee event code: " + QString::number(networkStatus);
} else {
networkStatusString = "unknown";
}
// Parse short network address
quint16 shortAddress = reply->additionalMessage().data().at(1);
shortAddress <<= 8;
shortAddress |= reply->additionalMessage().data().at(2);
// Parse extended network address
quint64 extendedAddress = reply->additionalMessage().data().at(3);
extendedAddress <<= 8;
extendedAddress |= reply->additionalMessage().data().at(4);
extendedAddress <<= 8;
extendedAddress |= reply->additionalMessage().data().at(5);
extendedAddress <<= 8;
extendedAddress |= reply->additionalMessage().data().at(6);
extendedAddress <<= 8;
extendedAddress |= reply->additionalMessage().data().at(7);
extendedAddress <<= 8;
extendedAddress |= reply->additionalMessage().data().at(8);
extendedAddress <<= 8;
extendedAddress |= reply->additionalMessage().data().at(9);
extendedAddress <<= 8;
extendedAddress |= reply->additionalMessage().data().at(10);
// Parse network channel
quint8 channel = static_cast<quint8>(reply->additionalMessage().data().at(11));
qCDebug(dcZigbee()).noquote() << "Network" << networkStatusString;
qCDebug(dcZigbee()) << " Address:" << ZigbeeUtils::convertUint16ToHexString(shortAddress);
qCDebug(dcZigbee()) << " Extended address:" << ZigbeeAddress(extendedAddress);
qCDebug(dcZigbee()) << " Channel:" << channel;
// Set the node information
setShortAddress(shortAddress);
setExtendedAddress(ZigbeeAddress(extendedAddress));
parseNetworkFormed(reply->additionalMessage().data());
init();
@ -468,6 +494,9 @@ void ZigbeeNetworkManager::onStartScanFinished()
qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully";
qCDebug(dcZigbeeController()) << reply->additionalMessage();
parseNetworkFormed(reply->additionalMessage().data());
}
void ZigbeeNetworkManager::onGetPermitJoiningStatusFinished()
@ -537,6 +566,19 @@ void ZigbeeNetworkManager::onInitiateTouchLinkFinished()
qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully";
}
void ZigbeeNetworkManager::onTouchLinkFactoryResetFinished()
{
ZigbeeInterfaceReply *reply = static_cast<ZigbeeInterfaceReply *>(sender());
reply->deleteLater();
if (reply->status() != ZigbeeInterfaceReply::Success) {
qCWarning(dcZigbeeController()) << "Could not" << reply->request().description() << reply->status() << reply->statusErrorMessage();
return;
}
qCDebug(dcZigbeeController()) << reply->request().description() << "finished successfully";
}
void ZigbeeNetworkManager::processLoggingMessage(const ZigbeeInterfaceMessage &message)
{
quint8 logLevel = static_cast<quint8>(message.data().at(0));

View File

@ -14,14 +14,31 @@ public:
explicit ZigbeeNetworkManager(const int &channel = 0, const QString &serialPort = "/dev/ttyS0", QObject *parent = nullptr);
QString controllerVersion() const;
QList<ZigbeeNode *> nodeList() const;
void reset();
quint64 extendedPanId() const;
bool networkRunning() const;
// Controller methods
void resetController();
void erasePersistentData();
void sendDataManagerAvailableResponse();
void getVersion();
void setExtendedPanId(const quint64 &panId);
void setChannelMask(const quint32 &channelMask);
void setDeviceType(const NodeType &deviceType);
void startNetwork();
void startScan();
void permitJoining(quint16 targetAddress = 0xfffc, const quint8 advertisingIntervall = 254);
void getPermitJoiningStatus();
void enableWhitelist();
void initiateTouchLink();
void touchLinkFactoryReset();
void requestMatchDescriptor(const quint16 &shortAddress, const Zigbee::ZigbeeProfile &profile);
private:
ZigbeeBridgeController *m_controller = nullptr;
QString m_controllerVersion;
@ -33,24 +50,7 @@ private:
quint64 generateRandomPanId();
// Controller methods
void resetController();
void erasePersistentData();
void sendDataManagerAvailableResponse();
void getVersion();
void setExtendedPanId(const quint64 &panId);
void setChannelMask(const quint32 &channelMask);
void setDeviceType(const NodeType &deviceType);
void startNetwork();
void startScan();
void permitJoining(quint16 targetAddress = 0xfffc, const quint8 advertisingIntervall = 254);
void getPermitJoiningStatus();
void enableWhitelist();
void initiateTouchLink();
void requestMatchDescriptor(const quint16 &shortAddress, const Zigbee::ZigbeeProfile &profile);
void parseNetworkFormed(const QByteArray &data);
signals:
void runningChanged(const bool &running);
@ -75,6 +75,7 @@ private slots:
void onEnableWhitelistFinished();
void onInitiateTouchLinkFinished();
void onTouchLinkFactoryResetFinished();
void onRequestMatchDescriptorFinished();

View File

@ -253,3 +253,9 @@ void ZigbeeNode::onRequestPowerDescriptorFinished()
qCDebug(dcZigbee()) << " Status:" << ZigbeeUtils::convertByteToHexString(status);
qCDebug(dcZigbee()) << " Bitfiled:" << ZigbeeUtils::convertUint16ToHexString(bitField);
}
QDebug operator<<(QDebug debug, ZigbeeNode *node)
{
debug.nospace().noquote() << "Node(" << node->shortAddress() << ", " << node->extendedAddress().toString() << ") ";
return debug;
}

View File

@ -73,4 +73,7 @@ public slots:
};
QDebug operator<<(QDebug debug, ZigbeeNode *node);
#endif // ZIGBEENODE_H

View File

@ -2,40 +2,37 @@
#include "loggingcategory.h"
#include "QCoreApplication"
Core::Core(const int &channel, QObject *parent) :
QObject(parent)
Core::Core(const QString &serialPort, const int &channel, QObject *parent) :
QObject(parent),
m_serialPort(serialPort)
{
m_manager = new ZigbeeNetworkManager(channel, "/dev/ttyS0", this);
m_manager = new ZigbeeNetworkManager(channel, m_serialPort, this);
// Set commands
m_commands.append(TerminalCommand("run", "Run the zigbee controller in a normal non interactive mode."));
TerminalCommand runCommand("run", "Run the zigbee controller in a normal non interactive mode.");
QStringList optionalParams;
optionalParams.append("router");
optionalParams.append("coordinator");
runCommand.setOptionalParameters(optionalParams);
m_commands.append(runCommand);
m_commands.append(TerminalCommand("start", "Start the zigbee network"));
m_commands.append(TerminalCommand("stop", "Stop the zigbee network"));
m_commands.append(TerminalCommand("reset", "Reset the zigbee controller"));
m_commands.append(TerminalCommand("scan", "Start scanning for zigbee networks"));
m_commands.append(TerminalCommand("version", "Print the version of the zigbee controll bridge firmware"));
m_commands.append(TerminalCommand("list-nodes", "List all nodes and information of the current network"));
m_commands.append(TerminalCommand("permit-join", "Permit nodes to join the network"));
m_commands.append(TerminalCommand("touch-link", "Initiate touch link pairing"));
m_commands.append(TerminalCommand("reset-touchlink", "Touch link factory reset"));
m_commands.append(TerminalCommand("whitelist", "Enable the white list joining"));
TerminalCommander::instance()->setCommands(m_commands);
TerminalCommander::instance()->start();
m_testTimer = new QTimer(this);
m_testTimer->setInterval(5000);
m_testTimer->setSingleShot(false);
connect(m_testTimer, &QTimer::timeout, this, &Core::onTimeout);
//m_testTimer->start();
connect(TerminalCommander::instance(), &TerminalCommander::commandReceived, this, &Core::onCommandReceived);
connect(TerminalCommander::instance(), &TerminalCommander::finished, QCoreApplication::instance(), &QCoreApplication::quit);
}
void Core::onTimeout()
{
qCDebug(dcZigbee()) << "[+] This is a test message from the zigbee thread";
}
void Core::onCommandReceived(const QStringList &tokens)
{
TerminalCommand command;
@ -54,10 +51,48 @@ void Core::onCommandReceived(const QStringList &tokens)
// TODO: Process command
qCDebug(dcZigbee()) << "Executing" << tokens.join(" ");
if (command.command() == "start") {
//m_manager->startNetwork();
if (command.command() == "run") {
ZigbeeNetworkManager::NodeType nodeType = ZigbeeNetworkManager::NodeTypeCoordinator;
if (tokens.count() > 1) {
if (!command.optionalParameters().contains(tokens.at(1))) {
qCWarning(dcZigbee()) << "Unknown paramter" << tokens.at(1);
return;
}
if (tokens.at(1) == "router") {
nodeType = ZigbeeNetworkManager::NodeTypeRouter;
}
}
m_manager->erasePersistentData();
m_manager->getVersion();
m_manager->setExtendedPanId(m_manager->extendedPanId());
m_manager->setChannelMask(0);
m_manager->setDeviceType(nodeType);
} else if (command.command() == "start") {
m_manager->startNetwork();
} else if (command.command() == "version") {
//m_manager->getVersion();
m_manager->getVersion();
} else if (command.command() == "scan") {
m_manager->startScan();
} else if (command.command() == "reset") {
m_manager->resetController();
} else if (command.command() == "permit-join") {
m_manager->permitJoining();
} else if (command.command() == "touch-link") {
m_manager->initiateTouchLink();
} else if (command.command() == "touch-link-reset") {
m_manager->touchLinkFactoryReset();
} else if (command.command() == "enable-whitelist") {
m_manager->enableWhitelist();
} else if (command.command() == "list-nodes") {
qCDebug(dcZigbee()) << "--> Host:" << m_manager;
foreach (ZigbeeNode *node, m_manager->nodeList()) {
qCDebug(dcZigbee()) << "-->" << node;
}
}
}

View File

@ -15,19 +15,18 @@ class Core : public QObject
{
Q_OBJECT
public:
explicit Core(const int &channel, QObject *parent = nullptr);
explicit Core(const QString &serialPort, const int &channel, QObject *parent = nullptr);
private:
ZigbeeNetworkManager *m_manager = nullptr;
QTimer *m_testTimer = nullptr;
QList<TerminalCommand> m_commands;
QString m_serialPort;
signals:
private slots:
void onTimeout();
void onCommandReceived(const QStringList &tokens);
};
#endif // CORE_H

View File

@ -14,49 +14,49 @@
static QHash<QString, bool> s_loggingFilters;
//static bool s_aboutToShutdown = false;
static bool s_aboutToShutdown = false;
//static void catchUnixSignals(const std::vector<int>& quitSignals, const std::vector<int>& ignoreSignals = std::vector<int>()) {
// auto handler = [](int sig) -> void {
// switch (sig) {
// case SIGQUIT:
// qCDebug(dcZigbee()) << "Cought SIGQUIT quit signal...";
// break;
// case SIGINT:
// qCDebug(dcZigbee()) << "Cought SIGINT quit signal...";
// break;
// case SIGTERM:
// qCDebug(dcZigbee()) << "Cought SIGTERM quit signal...";
// break;
// case SIGHUP:
// qCDebug(dcZigbee()) << "Cought SIGHUP quit signal...";
// break;
// case SIGSEGV: {
// qCDebug(dcZigbee()) << "Cought SIGSEGV signal. Segmentation fault!";
// exit(1);
// }
// default:
// break;
// }
static void catchUnixSignals(const std::vector<int>& quitSignals, const std::vector<int>& ignoreSignals = std::vector<int>()) {
auto handler = [](int sig) -> void {
switch (sig) {
case SIGQUIT:
qCDebug(dcZigbee()) << "Cought SIGQUIT quit signal...";
break;
case SIGINT:
qCDebug(dcZigbee()) << "Cought SIGINT quit signal...";
break;
case SIGTERM:
qCDebug(dcZigbee()) << "Cought SIGTERM quit signal...";
break;
case SIGHUP:
qCDebug(dcZigbee()) << "Cought SIGHUP quit signal...";
break;
case SIGSEGV: {
qCDebug(dcZigbee()) << "Cought SIGSEGV signal. Segmentation fault!";
exit(1);
}
default:
break;
}
// if (s_aboutToShutdown) {
// return;
// }
if (s_aboutToShutdown) {
return;
}
// s_aboutToShutdown = true;
// TerminalCommander::instance()->destroy();
// TerminalCommander::instance()->quit();
// };
s_aboutToShutdown = true;
TerminalCommander::instance()->destroy();
TerminalCommander::instance()->quit();
};
// // all these signals will be ignored.
// for (int sig : ignoreSignals)
// signal(sig, SIG_IGN);
// all these signals will be ignored.
for (int sig : ignoreSignals)
signal(sig, SIG_IGN);
// for (int sig : quitSignals)
// signal(sig, handler);
//}
for (int sig : quitSignals)
signal(sig, handler);
}
static void loggingCategoryFilter(QLoggingCategory *category)
{
@ -102,7 +102,7 @@ int main(int argc, char *argv[])
QCoreApplication application(argc, argv);
//catchUnixSignals({SIGQUIT, SIGINT, SIGTERM, SIGHUP, SIGSEGV});
catchUnixSignals({SIGQUIT, SIGINT, SIGTERM, SIGHUP, SIGSEGV});
application.setOrganizationName("guh");
application.setApplicationName("qt-zigbee");
@ -111,14 +111,21 @@ int main(int argc, char *argv[])
QCommandLineParser parser;
parser.addHelpOption();
parser.addVersionOption();
parser.setApplicationDescription(QString("\nDaemon for the zigbee NXP uart bridge.\n\nCopyright %1 2016 Simon Stürz <simon.stuerz@guh.io>\nAll rights reserved.").arg(QChar(0xA9)));
parser.setApplicationDescription(QString("\nCommand line tool for the zigbee NXP uart control bridge.\n\nCopyright %1 2018 Simon Stürz <simon.stuerz@guh.io>\nAll rights reserved.").arg(QChar(0xA9)));
// Debug level
QCommandLineOption debugLevelOption(QStringList() << "d" << "debug-level", "Set debug level [1-4].");
QCommandLineOption debugLevelOption(QStringList() << "d" << "debug-level", "Set debug level [1-4]. Default 1.");
debugLevelOption.setDefaultValue("1");
debugLevelOption.setValueName("level");
parser.addOption(debugLevelOption);
// Debug level
QCommandLineOption serialOption(QStringList() << "s" << "serial-port", "Set the serial port for the NXP controller. Default '/dev/ttyUSB0'.");
serialOption.setDefaultValue("/dev/ttyUSB0");
serialOption.setValueName("port");
parser.addOption(serialOption);
// Channel
QCommandLineOption channelOption(QStringList() << "c" << "channel", "Set channel for the zigbee network. Channel between [11-26] are allowed. If not specified, the quitest channel will be choosen automatically.");
channelOption.setDefaultValue(0);
@ -135,6 +142,7 @@ int main(int argc, char *argv[])
debugLevel = 1;
}
s_loggingFilters.insert("Application", true);
s_loggingFilters.insert("Zigbee", true);
s_loggingFilters.insert("ZigbeeController", (debugLevel > 1));
s_loggingFilters.insert("ZigbeeInterface", (debugLevel > 2));
@ -152,7 +160,9 @@ int main(int argc, char *argv[])
}
}
Core core(channel);
Core core(parser.value(serialOption), channel);
return application.exec();
}

View File

@ -52,7 +52,23 @@ void TerminalCommand::setOptionalParameters(const QStringList &parameters)
m_optionalParameters = parameters;
}
QString TerminalCommand::defaultParameter() const
{
return m_defaultParamter;
}
void TerminalCommand::setDefaultParameters(const QString &parameter)
{
m_defaultParamter = parameter;
}
bool TerminalCommand::isValid()
{
return !m_command.isEmpty() && !m_description.isEmpty();
}
QDebug operator<<(QDebug debug, const TerminalCommand &command)
{
debug << command.command() << command.description();
return debug;
}

View File

@ -1,6 +1,7 @@
#ifndef TERMINALCOMMAND_H
#define TERMINALCOMMAND_H
#include <QDebug>
#include <QString>
#include <QStringList>
@ -22,14 +23,21 @@ public:
QStringList optionalParameters() const;
void setOptionalParameters(const QStringList &parameters);
QString defaultParameter() const;
void setDefaultParameters(const QString &parameter);
bool isValid();
private:
QString m_command;
QString m_description;
QString m_defaultParamter;
QStringList m_mandatorysParameters;
QStringList m_optionalParameters;
};
QDebug operator<<(QDebug debug, const TerminalCommand &command);
#endif // TERMINALCOMMAND_H

View File

@ -18,7 +18,7 @@ TerminalCommander *TerminalCommander::instance()
void TerminalCommander::destroy()
{
qCDebug(dcZigbee()) << "Shut down terminal commander. Have a nice day.b";
qCDebug(dcZigbee()) << "Shut down terminal commander. Have a nice day!";
stopProcess();
}
@ -61,13 +61,21 @@ void TerminalCommander::stopProcess()
void TerminalCommander::run()
{
m_abort = false;
qCDebug(dcZigbee()) << "Command list:";
foreach (const TerminalCommand &command, m_commands) {
qCDebug(dcZigbee()) << " -->" << command;
}
rl_attempted_completion_function = commandCompletion;
rl_set_prompt(QString("%1[zigbee]%2 ").arg(terminalColorBoldGray).arg(terminalColorNormal).toStdString().data());
rl_redisplay();
rl_bind_key('\t',rl_complete);
rl_clear_signals();
rl_set_signals();
//rl_clear_signals();
rl_catch_signals = 1;
while (true) {
@ -102,11 +110,11 @@ void TerminalCommander::run()
QMutexLocker locker(&m_mutex);
if (m_abort) {
qDebug() << "";
rl_on_new_line();
rl_replace_line("", 0);
rl_redisplay();
qCDebug(dcZigbee()) << "Terminal thread stopped";
//qDebug() << "";
//rl_on_new_line();
//rl_replace_line("", 0);
//rl_redisplay();
//qCDebug(dcZigbee()) << "Terminal thread stopped";
return;
}
}
@ -174,7 +182,7 @@ char **commandCompletion(const char *text, int start, int end)
char *commandCompletionGenerator(const char *text, int state)
{
//qCDebug(dcZigbee) << text << state << TerminalCommander::instance()->commands();
//qCDebug(dcZigbee()) << text << state;
static int list_index, len;
const char *name;
@ -185,6 +193,7 @@ char *commandCompletionGenerator(const char *text, int state)
}
while (list_index < TerminalCommander::instance()->commands().count() && (name = TerminalCommander::instance()->commands().at(list_index).command().toStdString().data())) {
//qCDebug(dcZigbee()) << " " << TerminalCommander::instance()->commands().at(list_index).command().toStdString().data();
list_index++;
if (strncmp (name, text, len) == 0) return strdup (name);
}