mirror of
https://github.com/nymea/nymea-plugins.git
synced 2026-08-02 03:07:33 +02:00
Make gpios work with arduino based boards
This commit is contained in:
parent
42f2e9a3d7
commit
509b649fbe
@ -31,6 +31,7 @@
|
||||
#include "integrationpluginowlet.h"
|
||||
#include "plugininfo.h"
|
||||
#include "owletclient.h"
|
||||
#include "owletserialclient.h"
|
||||
|
||||
#include "hardwaremanager.h"
|
||||
#include "platform/platformzeroconfcontroller.h"
|
||||
@ -56,16 +57,44 @@ void IntegrationPluginOwlet::init()
|
||||
m_owletSerialPortParamTypeMap.insert(arduinoMiniProThingClassId, arduinoMiniProThingSerialPortParamTypeId);
|
||||
|
||||
m_zeroConfBrowser = hardwareManager()->zeroConfController()->createServiceBrowser("_nymea-owlet._tcp");
|
||||
|
||||
// Pin params of thins
|
||||
m_owletSerialPinParamTypeMap.insert(digitalOutputSerialThingClassId, digitalOutputSerialThingPinParamTypeId);
|
||||
m_owletSerialPinParamTypeMap.insert(digitalInputSerialThingClassId, digitalInputSerialThingPinParamTypeId);
|
||||
m_owletSerialPinParamTypeMap.insert(analogOutputSerialThingClassId, analogOutputSerialThingPinParamTypeId);
|
||||
m_owletSerialPinParamTypeMap.insert(analogInputSerialThingClassId, analogInputSerialThingPinParamTypeId);
|
||||
m_owletSerialPinParamTypeMap.insert(servoSerialThingClassId, servoSerialThingPinParamTypeId);
|
||||
|
||||
// Arduino Mini Pro mapping
|
||||
m_arduinoMiniProPinMapping.insert(arduinoMiniProSettingsPin2ParamTypeId, 2);
|
||||
m_arduinoMiniProPinMapping.insert(arduinoMiniProSettingsPin3ParamTypeId, 3);
|
||||
m_arduinoMiniProPinMapping.insert(arduinoMiniProSettingsPin4ParamTypeId, 4);
|
||||
m_arduinoMiniProPinMapping.insert(arduinoMiniProSettingsPin5ParamTypeId, 5);
|
||||
m_arduinoMiniProPinMapping.insert(arduinoMiniProSettingsPin6ParamTypeId, 6);
|
||||
m_arduinoMiniProPinMapping.insert(arduinoMiniProSettingsPin7ParamTypeId, 7);
|
||||
m_arduinoMiniProPinMapping.insert(arduinoMiniProSettingsPin8ParamTypeId, 8);
|
||||
m_arduinoMiniProPinMapping.insert(arduinoMiniProSettingsPin9ParamTypeId, 9);
|
||||
m_arduinoMiniProPinMapping.insert(arduinoMiniProSettingsPin10ParamTypeId, 10);
|
||||
m_arduinoMiniProPinMapping.insert(arduinoMiniProSettingsPin11ParamTypeId, 11);
|
||||
m_arduinoMiniProPinMapping.insert(arduinoMiniProSettingsPin12ParamTypeId, 12);
|
||||
m_arduinoMiniProPinMapping.insert(arduinoMiniProSettingsPin13ParamTypeId, 13);
|
||||
m_arduinoMiniProPinMapping.insert(arduinoMiniProSettingsPinA1ParamTypeId, 15);
|
||||
m_arduinoMiniProPinMapping.insert(arduinoMiniProSettingsPinA2ParamTypeId, 16);
|
||||
m_arduinoMiniProPinMapping.insert(arduinoMiniProSettingsPinA3ParamTypeId, 17);
|
||||
m_arduinoMiniProPinMapping.insert(arduinoMiniProSettingsPinA4ParamTypeId, 18);
|
||||
m_arduinoMiniProPinMapping.insert(arduinoMiniProSettingsPinA5ParamTypeId, 19);
|
||||
m_arduinoMiniProPinMapping.insert(arduinoMiniProSettingsPinA6ParamTypeId, 20);
|
||||
m_arduinoMiniProPinMapping.insert(arduinoMiniProSettingsPinA7ParamTypeId, 21);
|
||||
}
|
||||
|
||||
void IntegrationPluginOwlet::discoverThings(ThingDiscoveryInfo *info)
|
||||
{
|
||||
if (info->thingClassId() == arduinoMiniProThingClassId) {
|
||||
// Discover serial ports for arduino bords
|
||||
foreach(QSerialPortInfo port, QSerialPortInfo::availablePorts()) {
|
||||
foreach(const QSerialPortInfo &port, QSerialPortInfo::availablePorts()) {
|
||||
qCDebug(dcOwlet()) << "Found serial port" << port.systemLocation();
|
||||
QString description = port.systemLocation() + " " + port.manufacturer() + " " + port.description();
|
||||
ThingDescriptor thingDescriptor(info->thingClassId(), "Owlet Arduino Pro Mini", description);
|
||||
ThingDescriptor thingDescriptor(info->thingClassId(), "Arduino Pro Mini Owlet", description);
|
||||
ParamList parameters;
|
||||
|
||||
foreach (Thing *existingThing, myThings()) {
|
||||
@ -99,38 +128,326 @@ void IntegrationPluginOwlet::discoverThings(ThingDiscoveryInfo *info)
|
||||
void IntegrationPluginOwlet::setupThing(ThingSetupInfo *info)
|
||||
{
|
||||
Thing *thing = info->thing();
|
||||
OwletTransport *transport = nullptr;
|
||||
|
||||
if (thing->thingClassId() == arduinoMiniProThingClassId) {
|
||||
QString serialPort = thing->paramValue(arduinoMiniProThingSerialPortParamTypeId).toString();
|
||||
qCDebug(dcOwlet()) << "Setup arduino mini pro owlet on" << serialPort;
|
||||
OwletTransport *transport = new OwletSerialTransport(serialPort, 115200, this);
|
||||
OwletSerialClient *client = new OwletSerialClient(transport, transport);
|
||||
|
||||
// During setup
|
||||
connect(client, &OwletSerialClient::connected, info, [=](){
|
||||
qCDebug(dcOwlet()) << "Connected to serial owlet" << client->firmwareVersion();
|
||||
thing->setStateValue("connected", true);
|
||||
});
|
||||
|
||||
connect(client, &OwletSerialClient::error, info, [=](){
|
||||
//info->finish(Thing::ThingErrorHardwareFailure);
|
||||
transport->deleteLater();
|
||||
});
|
||||
|
||||
// Runtime
|
||||
connect(client, &OwletSerialClient::connected, thing, [=](){
|
||||
thing->setStateValue("connected", true);
|
||||
thing->setStateValue(arduinoMiniProCurrentVersionStateTypeId, client->firmwareVersion());
|
||||
foreach (Thing *childThing, myThings().filterByParentId(thing->id())) {
|
||||
childThing->setStateValue("connected", true);
|
||||
}
|
||||
});
|
||||
|
||||
connect(client, &OwletSerialClient::disconnected, thing, [=](){
|
||||
thing->setStateValue("connected", false);
|
||||
foreach (Thing *childThing, myThings().filterByParentId(thing->id())) {
|
||||
childThing->setStateValue("connected", false);
|
||||
}
|
||||
});
|
||||
|
||||
connect(thing, &Thing::settingChanged, thing, [=](const ParamTypeId ¶mTypeId, const QVariant &value){
|
||||
qCDebug(dcOwlet()) << "Arduino Mini Pro settings changed" << paramTypeId << value;
|
||||
quint8 pinId = m_arduinoMiniProPinMapping.value(paramTypeId);
|
||||
OwletSerialClient::PinMode pinMode = getPinModeFromSettingsValue(value.toString());
|
||||
|
||||
// Check if we have a thing for this pin and if we need to remove it before setting up
|
||||
Thing *existingThing = nullptr;
|
||||
foreach (Thing *childThing, myThings().filterByParentId(thing->id())) {
|
||||
int existingPinId = childThing->paramValue(m_owletSerialPinParamTypeMap.value(childThing->thingClassId())).toUInt();
|
||||
if (existingPinId == pinId) {
|
||||
qCDebug(dcOwlet()) << "Found already configured thing for pin" << pinId;
|
||||
existingThing = childThing;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (existingThing) {
|
||||
if ((pinMode == OwletSerialClient::PinModeDigitalOutput && existingThing->thingClassId() == digitalOutputSerialThingClassId) ||
|
||||
(pinMode == OwletSerialClient::PinModeDigitalInput && existingThing->thingClassId() == digitalInputSerialThingClassId) ||
|
||||
(pinMode == OwletSerialClient::PinModeAnalogOutput && existingThing->thingClassId() == analogOutputSerialThingClassId) ||
|
||||
(pinMode == OwletSerialClient::PinModeAnalogInput && existingThing->thingClassId() == analogInputSerialThingClassId) ||
|
||||
(pinMode == OwletSerialClient::PinModeServo && existingThing->thingClassId() == servoSerialThingClassId)) {
|
||||
|
||||
qCDebug(dcOwlet()) << "Thing for pin" << pinId << "is already configured as" << pinMode;
|
||||
return;
|
||||
} else {
|
||||
qCDebug(dcOwlet()) << "Have thing for pin" << pinId << "but should be configured as" << pinMode;
|
||||
qCDebug(dcOwlet()) << "Remove existing thing before setup a new one";
|
||||
emit autoThingDisappeared(existingThing->id());
|
||||
}
|
||||
}
|
||||
|
||||
setupArduinoChildThing(client, pinId, pinMode);
|
||||
});
|
||||
|
||||
m_serialClients.insert(thing, client);
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
|
||||
client->transport()->connectTransport();
|
||||
return;
|
||||
}
|
||||
|
||||
if (thing->thingClassId() == digitalOutputSerialThingClassId) {
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
|
||||
// Update states
|
||||
Thing *parent = myThings().findById(thing->parentId());
|
||||
bool parentConnected = false;
|
||||
if (parent)
|
||||
parentConnected = parent->stateValue("connected").toBool();
|
||||
|
||||
thing->setStateValue("connected", parentConnected);
|
||||
|
||||
OwletSerialClient *client = m_serialClients.value(parent);
|
||||
|
||||
quint8 pinId = thing->paramValue(digitalOutputSerialThingPinParamTypeId).toUInt();
|
||||
OwletSerialClient::PinMode pinMode = OwletSerialClient::PinModeDigitalOutput;
|
||||
|
||||
connect(client, &OwletSerialClient::connected, thing, [=](){
|
||||
configurePin(client, pinId, pinMode);
|
||||
});
|
||||
|
||||
if (parentConnected) {
|
||||
configurePin(client, pinId, pinMode);
|
||||
}
|
||||
}
|
||||
|
||||
if (thing->thingClassId() == digitalInputSerialThingClassId) {
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
|
||||
// Update states
|
||||
Thing *parent = myThings().findById(thing->parentId());
|
||||
bool parentConnected = false;
|
||||
if (parent)
|
||||
parentConnected = parent->stateValue("connected").toBool();
|
||||
|
||||
thing->setStateValue("connected", parentConnected);
|
||||
|
||||
quint8 pinId = thing->paramValue(digitalInputSerialThingPinParamTypeId).toUInt();
|
||||
OwletSerialClient::PinMode pinMode = OwletSerialClient::PinModeDigitalInput;
|
||||
|
||||
OwletSerialClient *client = m_serialClients.value(parent);
|
||||
connect(client, &OwletSerialClient::connected, thing, [=](){
|
||||
thing->setStateValue("connected", true);
|
||||
|
||||
configurePin(client, pinId, pinMode);
|
||||
|
||||
// Read current value
|
||||
quint8 pinId = thing->paramValue(digitalInputSerialThingPinParamTypeId).toUInt();
|
||||
OwletSerialClientReply *reply = client->readDigitalValue(pinId);
|
||||
connect(reply, &OwletSerialClientReply::finished, this, [=](){
|
||||
if (reply->status() != OwletSerialClient::StatusSuccess) {
|
||||
qCWarning(dcOwlet()) << "Failed to read digital pin value from" << thing << reply->status();
|
||||
return;
|
||||
}
|
||||
|
||||
if (reply->responsePayload().count() < 2) {
|
||||
qCWarning(dcOwlet()) << "Invalid response payload size from request" << pinId;
|
||||
return;
|
||||
}
|
||||
|
||||
OwletSerialClient::GPIOError configurationError = static_cast<OwletSerialClient::GPIOError>(reply->responsePayload().at(0));
|
||||
quint8 value = static_cast<quint8>(reply->responsePayload().at(1));
|
||||
if (configurationError != OwletSerialClient::GPIOErrorNoError) {
|
||||
qCWarning(dcOwlet()) << "Configure pin request finished with error" << configurationError;
|
||||
return;
|
||||
}
|
||||
|
||||
thing->setStateValue(digitalInputSerialPowerStateTypeId, value != 0x00);
|
||||
});
|
||||
});
|
||||
|
||||
connect(client, &OwletSerialClient::pinValueChanged, this, [=](quint8 id, bool power){
|
||||
if (id != pinId)
|
||||
return;
|
||||
|
||||
thing->setStateValue(digitalInputSerialPowerStateTypeId, power);
|
||||
});
|
||||
|
||||
if (parentConnected) {
|
||||
configurePin(client, pinId, pinMode);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (thing->thingClassId() == analogInputSerialThingClassId) {
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
|
||||
// Update states
|
||||
Thing *parent = myThings().findById(thing->parentId());
|
||||
bool parentConnected = false;
|
||||
if (parent)
|
||||
parentConnected = parent->stateValue("connected").toBool();
|
||||
|
||||
thing->setStateValue("connected", parentConnected);
|
||||
|
||||
OwletSerialClient *client = m_serialClients.value(parent);
|
||||
|
||||
QTimer *refreshTimer = new QTimer(thing);
|
||||
refreshTimer->setSingleShot(false);
|
||||
refreshTimer->setInterval(thing->setting(analogInputSerialSettingsRefreshRateParamTypeId).toUInt());
|
||||
connect(refreshTimer, &QTimer::timeout, this, [=](){
|
||||
// Read current value
|
||||
quint8 pinId = thing->paramValue(analogInputSerialThingPinParamTypeId).toUInt();
|
||||
OwletSerialClientReply *reply = client->readAnalogValue(pinId);
|
||||
connect(reply, &OwletSerialClientReply::finished, this, [=](){
|
||||
if (reply->status() != OwletSerialClient::StatusSuccess) {
|
||||
qCWarning(dcOwlet()) << "Failed to read analog pin value from" << thing << reply->status();
|
||||
return;
|
||||
}
|
||||
|
||||
if (reply->responsePayload().count() < 3) {
|
||||
qCWarning(dcOwlet()) << "Invalid response payload size from request" << pinId;
|
||||
return;
|
||||
}
|
||||
|
||||
QDataStream stream(reply->responsePayload());
|
||||
quint8 errorCode;
|
||||
stream >> errorCode;
|
||||
OwletSerialClient::GPIOError configurationError = static_cast<OwletSerialClient::GPIOError>(errorCode);
|
||||
if (configurationError != OwletSerialClient::GPIOErrorNoError) {
|
||||
qCWarning(dcOwlet()) << "Configure pin request finished with error" << configurationError;
|
||||
return;
|
||||
}
|
||||
quint32 value;
|
||||
stream >> value;
|
||||
qCDebug(dcOwlet()) << "Analog value of" << thing << value;
|
||||
thing->setStateValue(analogInputSerialAnalogValueStateTypeId, value);
|
||||
});
|
||||
});
|
||||
|
||||
quint8 pinId = thing->paramValue(analogInputSerialThingPinParamTypeId).toUInt();
|
||||
OwletSerialClient::PinMode pinMode = OwletSerialClient::PinModeAnalogInput;
|
||||
|
||||
connect(client, &OwletSerialClient::connected, thing, [=](){
|
||||
qCDebug(dcOwlet()) << "Starting refresh timer for" << thing;
|
||||
configurePin(client, pinId, pinMode);
|
||||
refreshTimer->start();
|
||||
});
|
||||
|
||||
connect(client, &OwletSerialClient::disconnected, thing, [=](){
|
||||
qCDebug(dcOwlet()) << "Stopping refresh timer for" << thing;
|
||||
refreshTimer->stop();
|
||||
});
|
||||
|
||||
// Start reading if already connected
|
||||
if (parentConnected) {
|
||||
qCDebug(dcOwlet()) << "Starting refresh timer for" << thing;
|
||||
configurePin(client, pinId, pinMode);
|
||||
refreshTimer->start();
|
||||
}
|
||||
|
||||
connect(thing, &Thing::settingChanged, refreshTimer, [=](const ParamTypeId ¶mTypeId, const QVariant &value){
|
||||
if (paramTypeId == analogInputSerialSettingsRefreshRateParamTypeId) {
|
||||
refreshTimer->setInterval(value.toUInt());
|
||||
refreshTimer->start();
|
||||
}
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (thing->thingClassId() == analogOutputSerialThingClassId) {
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
|
||||
// Update states
|
||||
Thing *parent = myThings().findById(thing->parentId());
|
||||
bool parentConnected = false;
|
||||
if (parent)
|
||||
parentConnected = parent->stateValue("connected").toBool();
|
||||
|
||||
thing->setStateValue("connected", parentConnected);
|
||||
|
||||
OwletSerialClient *client = m_serialClients.value(parent);
|
||||
|
||||
quint8 pinId = thing->paramValue(analogInputSerialThingPinParamTypeId).toUInt();
|
||||
OwletSerialClient::PinMode pinMode = OwletSerialClient::PinModeAnalogInput;
|
||||
|
||||
connect(client, &OwletSerialClient::connected, thing, [=](){
|
||||
configurePin(client, pinId, pinMode);
|
||||
});
|
||||
|
||||
// Start reading if already connected
|
||||
if (parentConnected) {
|
||||
configurePin(client, pinId, pinMode);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (thing->thingClassId() == servoSerialThingClassId) {
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
|
||||
// Update states
|
||||
Thing *parent = myThings().findById(thing->parentId());
|
||||
bool parentConnected = false;
|
||||
if (parent)
|
||||
parentConnected = parent->stateValue("connected").toBool();
|
||||
|
||||
thing->setStateValue("connected", parentConnected);
|
||||
|
||||
OwletSerialClient *client = m_serialClients.value(parent);
|
||||
|
||||
quint8 pinId = thing->paramValue(servoSerialThingPinParamTypeId).toUInt();
|
||||
OwletSerialClient::PinMode pinMode = OwletSerialClient::PinModeServo;
|
||||
|
||||
connect(client, &OwletSerialClient::connected, thing, [=](){
|
||||
configurePin(client, pinId, pinMode);
|
||||
});
|
||||
|
||||
// Start reading if already connected
|
||||
if (parentConnected) {
|
||||
configurePin(client, pinId, pinMode);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
QHostAddress ip;
|
||||
int port = 5555;
|
||||
|
||||
if (thing->thingClassId() != arduinoMiniProThingClassId) {
|
||||
foreach (const ZeroConfServiceEntry &entry, m_zeroConfBrowser->serviceEntries()) {
|
||||
if (entry.txt("id") == info->thing()->paramValue(m_owletIdParamTypeMap.value(info->thing()->thingClassId()))) {
|
||||
ip = entry.hostAddress();
|
||||
port = entry.port();
|
||||
break;
|
||||
}
|
||||
foreach (const ZeroConfServiceEntry &entry, m_zeroConfBrowser->serviceEntries()) {
|
||||
if (entry.txt("id") == info->thing()->paramValue(m_owletIdParamTypeMap.value(info->thing()->thingClassId()))) {
|
||||
ip = entry.hostAddress();
|
||||
port = entry.port();
|
||||
break;
|
||||
}
|
||||
// Try cached ip
|
||||
if (ip.isNull()) {
|
||||
pluginStorage()->beginGroup(thing->id().toString());
|
||||
ip = QHostAddress(pluginStorage()->value("cachedIP").toString());
|
||||
pluginStorage()->endGroup();
|
||||
}
|
||||
|
||||
if (ip.isNull()) {
|
||||
qCWarning(dcOwlet()) << "Can't find owlet in the local network.";
|
||||
info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
return;
|
||||
}
|
||||
|
||||
transport = new OwletTcpTransport(ip, port, this);
|
||||
|
||||
} else if (thing->thingClassId() == arduinoMiniProThingClassId) {
|
||||
QString serialPort = thing->paramValue(arduinoMiniProThingSerialPortParamTypeId).toString();
|
||||
qCDebug(dcOwlet()) << "Setup arduino mini pro owlet on" << serialPort;
|
||||
transport = new OwletSerialTransport(serialPort, 115200, this);
|
||||
}
|
||||
// Try cached ip
|
||||
if (ip.isNull()) {
|
||||
pluginStorage()->beginGroup(thing->id().toString());
|
||||
ip = QHostAddress(pluginStorage()->value("cachedIP").toString());
|
||||
pluginStorage()->endGroup();
|
||||
}
|
||||
|
||||
if (ip.isNull()) {
|
||||
qCWarning(dcOwlet()) << "Can't find owlet in the local network.";
|
||||
info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
return;
|
||||
}
|
||||
|
||||
OwletTransport *transport = new OwletTcpTransport(ip, port, this);
|
||||
|
||||
OwletClient *client = new OwletClient(transport, this);
|
||||
connect(client, &OwletClient::connected, info, [=](){
|
||||
@ -169,12 +486,9 @@ void IntegrationPluginOwlet::setupThing(ThingSetupInfo *info)
|
||||
connect(client, &OwletClient::connected, thing, [=](){
|
||||
thing->setStateValue("connected", true);
|
||||
|
||||
// FIXME: find a better way
|
||||
if (thing->thingClassId() != arduinoMiniProThingClassId) {
|
||||
pluginStorage()->beginGroup(thing->id().toString());
|
||||
pluginStorage()->setValue("cachedIP", ip.toString());
|
||||
pluginStorage()->endGroup();
|
||||
}
|
||||
pluginStorage()->beginGroup(thing->id().toString());
|
||||
pluginStorage()->setValue("cachedIP", ip.toString());
|
||||
pluginStorage()->endGroup();
|
||||
|
||||
qCDebug(dcOwlet()) << "Sending get platform information request...";
|
||||
int id = client->sendCommand("Platform.GetInformation");
|
||||
@ -286,6 +600,184 @@ void IntegrationPluginOwlet::executeAction(ThingActionInfo *info)
|
||||
return;
|
||||
}
|
||||
|
||||
if (info->thing()->thingClassId() == arduinoMiniProThingClassId) {
|
||||
OwletSerialClient *client = m_serialClients.value(info->thing());
|
||||
if (!client) {
|
||||
qCWarning(dcOwlet()) << "Could not execute action. There is no client available for this thing";
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!client->ready()) {
|
||||
qCWarning(dcOwlet()) << "Could not execute action. The serial client is not ready or connected.";
|
||||
info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
return;
|
||||
}
|
||||
if (info->action().actionTypeId() == arduinoMiniProPerformUpdateActionTypeId) {
|
||||
qCDebug(dcOwlet()) << "Perform firmware update on" << info->thing();
|
||||
//if (client->firmwareVersion() != )
|
||||
|
||||
// TODO: run upgrade process using avrdude
|
||||
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (info->thing()->thingClassId() == analogOutputSerialThingClassId) {
|
||||
OwletSerialClient *client = m_serialClients.value(myThings().findById(info->thing()->parentId()));
|
||||
if (!client) {
|
||||
qCWarning(dcOwlet()) << "Could not execute action. There is no client available for this thing";
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!client->ready()) {
|
||||
qCWarning(dcOwlet()) << "Could not execute action. The serial client is not ready or connected.";
|
||||
info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
return;
|
||||
}
|
||||
|
||||
if (info->action().actionTypeId() == analogOutputSerialDutyCycleActionTypeId) {
|
||||
quint8 dutyCycle = info->action().paramValue(analogOutputSerialDutyCycleActionDutyCycleParamTypeId).toUInt();
|
||||
qCDebug(dcOwlet()) << "Set PWM duty cycle of" << info->thing() << "to" << dutyCycle;
|
||||
quint8 pinId = info->thing()->paramValue(analogOutputSerialThingPinParamTypeId).toUInt();
|
||||
|
||||
OwletSerialClientReply *reply = client->writeAnalogValue(pinId, dutyCycle);
|
||||
connect(reply, &OwletSerialClientReply::finished, this, [=](){
|
||||
if (reply->status() != OwletSerialClient::StatusSuccess) {
|
||||
qCWarning(dcOwlet()) << "Failed to set power on pin" << pinId << dutyCycle << reply->status();
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
if (reply->responsePayload().count() < 1) {
|
||||
qCWarning(dcOwlet()) << "Failed to set power on pin" << pinId << dutyCycle << "Invalid response payload size from request";
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
OwletSerialClient::GPIOError gpioError = static_cast<OwletSerialClient::GPIOError>(reply->responsePayload().at(0));
|
||||
if (gpioError != OwletSerialClient::GPIOErrorNoError) {
|
||||
qCWarning(dcOwlet()) << "Set power on pin" << pinId << dutyCycle << "request finished with error" << gpioError;
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcOwlet()) << "Set PWM duty cycle finished successfully" << pinId << dutyCycle;
|
||||
info->thing()->setStateValue(analogOutputSerialDutyCycleStateTypeId, dutyCycle);
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
return;
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (info->thing()->thingClassId() == digitalOutputSerialThingClassId) {
|
||||
OwletSerialClient *client = m_serialClients.value(myThings().findById(info->thing()->parentId()));
|
||||
if (!client) {
|
||||
qCWarning(dcOwlet()) << "Could not execute action. There is no client available for this thing";
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!client->ready()) {
|
||||
qCWarning(dcOwlet()) << "Could not execute action. The serial client is not ready or connected.";
|
||||
info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
return;
|
||||
}
|
||||
|
||||
if (info->action().actionTypeId() == digitalOutputSerialPowerActionTypeId) {
|
||||
quint8 pinId = info->thing()->paramValue(digitalOutputSerialThingPinParamTypeId).toUInt();
|
||||
bool power = info->action().paramValue(digitalOutputSerialPowerActionPowerParamTypeId).toBool();
|
||||
OwletSerialClientReply *reply = client->writeDigitalValue(pinId, power);
|
||||
connect(reply, &OwletSerialClientReply::finished, this, [=](){
|
||||
if (reply->status() != OwletSerialClient::StatusSuccess) {
|
||||
qCWarning(dcOwlet()) << "Failed to set power on pin" << pinId << power << reply->status();
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
if (reply->responsePayload().count() < 1) {
|
||||
qCWarning(dcOwlet()) << "Failed to set power on pin" << pinId << power << "Invalid response payload size from request";
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
OwletSerialClient::GPIOError gpioError = static_cast<OwletSerialClient::GPIOError>(reply->responsePayload().at(0));
|
||||
if (gpioError != OwletSerialClient::GPIOErrorNoError) {
|
||||
qCWarning(dcOwlet()) << "Set power on pin" << pinId << power << "request finished with error" << gpioError;
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcOwlet()) << "Set power finished successfully" << pinId << power;
|
||||
info->thing()->setStateValue(digitalOutputSerialPowerStateTypeId, power);
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
return;
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
info->finish(Thing::ThingErrorUnsupportedFeature);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (info->thing()->thingClassId() == servoSerialThingClassId) {
|
||||
OwletSerialClient *client = m_serialClients.value(myThings().findById(info->thing()->parentId()));
|
||||
if (!client) {
|
||||
qCWarning(dcOwlet()) << "Could not execute action. There is no client available for this thing";
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!client->ready()) {
|
||||
qCWarning(dcOwlet()) << "Could not execute action. The serial client is not ready or connected.";
|
||||
info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
return;
|
||||
}
|
||||
|
||||
if (info->action().actionTypeId() == servoSerialAngleActionTypeId) {
|
||||
quint8 pinId = info->thing()->paramValue(servoSerialThingPinParamTypeId).toUInt();
|
||||
quint8 angle = info->action().paramValue(servoSerialAngleActionAngleParamTypeId).toUInt();
|
||||
OwletSerialClientReply *reply = client->writeServoValue(pinId, angle);
|
||||
connect(reply, &OwletSerialClientReply::finished, this, [=](){
|
||||
if (reply->status() != OwletSerialClient::StatusSuccess) {
|
||||
qCWarning(dcOwlet()) << "Failed to set servo angle on pin" << pinId << angle << reply->status();
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
if (reply->responsePayload().count() < 1) {
|
||||
qCWarning(dcOwlet()) << "Failed to set servo angle on pin" << pinId << angle << "Invalid response payload size from request";
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
OwletSerialClient::GPIOError gpioError = static_cast<OwletSerialClient::GPIOError>(reply->responsePayload().at(0));
|
||||
if (gpioError != OwletSerialClient::GPIOErrorNoError) {
|
||||
qCWarning(dcOwlet()) << "Set angle on servo pin" << pinId << angle << "request finished with error" << gpioError;
|
||||
info->finish(Thing::ThingErrorHardwareFailure);
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcOwlet()) << "Set servo angle finished successfully" << pinId << angle;
|
||||
info->thing()->setStateValue(servoSerialAngleStateTypeId, angle);
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
return;
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
info->finish(Thing::ThingErrorUnsupportedFeature);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Q_ASSERT_X(false, "IntegrationPluginOwlet", "Not implemented");
|
||||
@ -294,5 +786,132 @@ void IntegrationPluginOwlet::executeAction(ThingActionInfo *info)
|
||||
|
||||
void IntegrationPluginOwlet::thingRemoved(Thing *thing)
|
||||
{
|
||||
Q_UNUSED(thing)
|
||||
if (thing->thingClassId() == arduinoMiniProThingClassId && m_serialClients.contains(thing)) {
|
||||
m_serialClients.take(thing)->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
OwletSerialClient::PinMode IntegrationPluginOwlet::getPinModeFromSettingsValue(const QString &settingsValue)
|
||||
{
|
||||
if (settingsValue == "Output") {
|
||||
return OwletSerialClient::PinModeDigitalOutput;
|
||||
} else if (settingsValue == "Input") {
|
||||
return OwletSerialClient::PinModeDigitalInput;
|
||||
} else if (settingsValue == "PWM") {
|
||||
return OwletSerialClient::PinModeAnalogOutput;
|
||||
} else if (settingsValue == "Analog Input") {
|
||||
return OwletSerialClient::PinModeAnalogInput;
|
||||
} else if (settingsValue == "Servo") {
|
||||
return OwletSerialClient::PinModeServo;
|
||||
} else {
|
||||
return OwletSerialClient::PinModeUnconfigured;
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginOwlet::setupArduinoChildThing(OwletSerialClient *client, quint8 pinId, OwletSerialClient::PinMode pinMode)
|
||||
{
|
||||
Thing *parentThing = m_serialClients.key(client);
|
||||
if (!parentThing) {
|
||||
qCWarning(dcOwlet()) << "Could not setup child thing because the parent thing seems not to be available";
|
||||
return;
|
||||
}
|
||||
|
||||
// Note: pin has no thing here any more, we can set up a new one if required
|
||||
OwletSerialClientReply *reply = client->configurePin(pinId, pinMode);
|
||||
connect(reply, &OwletSerialClientReply::finished, this, [=](){
|
||||
if (reply->status() != OwletSerialClient::StatusSuccess) {
|
||||
qCWarning(dcOwlet()) << "Failed to configure pin" << pinId << pinMode << reply->status();
|
||||
return;
|
||||
}
|
||||
|
||||
if (reply->responsePayload().count() < 1) {
|
||||
qCWarning(dcOwlet()) << "Invalid configure pin response payload size from request" << pinId << pinMode;
|
||||
return;
|
||||
}
|
||||
|
||||
OwletSerialClient::GPIOError configurationError = static_cast<OwletSerialClient::GPIOError>(reply->responsePayload().at(0));
|
||||
if (configurationError != OwletSerialClient::GPIOErrorNoError) {
|
||||
qCWarning(dcOwlet()) << "Configure pin request finished with error" << configurationError;
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcOwlet()) << "Configure pin request finished successfully" << pinId << pinMode;
|
||||
|
||||
// Setup child devices
|
||||
switch (pinMode) {
|
||||
case OwletSerialClient::PinModeDigitalOutput: {
|
||||
qCDebug(dcOwlet()) << "Setting up digital output on serial owlet for pin" << pinId;
|
||||
ThingDescriptor descriptor(digitalOutputSerialThingClassId, thingClass(digitalOutputSerialThingClassId).displayName() + " (" + QString::number(pinId) + ")", QString(), parentThing->id());
|
||||
ParamList params;
|
||||
params.append(Param(digitalOutputSerialThingPinParamTypeId, pinId));
|
||||
descriptor.setParams(params);
|
||||
emit autoThingsAppeared(ThingDescriptors() << descriptor);
|
||||
break;
|
||||
}
|
||||
case OwletSerialClient::PinModeDigitalInput: {
|
||||
qCDebug(dcOwlet()) << "Setting up digital input on serial owlet for pin" << pinId;
|
||||
ThingDescriptor descriptor(digitalInputSerialThingClassId, thingClass(digitalInputSerialThingClassId).displayName() + " (" + QString::number(pinId) + ")", QString(), parentThing->id());
|
||||
ParamList params;
|
||||
params.append(Param(digitalInputSerialThingPinParamTypeId, pinId));
|
||||
descriptor.setParams(params);
|
||||
emit autoThingsAppeared(ThingDescriptors() << descriptor);
|
||||
break;
|
||||
}
|
||||
case OwletSerialClient::PinModeAnalogOutput: {
|
||||
qCDebug(dcOwlet()) << "Setting up digital output on serial owlet for pin" << pinId;
|
||||
ThingDescriptor descriptor(analogOutputSerialThingClassId, thingClass(analogOutputSerialThingClassId).displayName() + " (" + QString::number(pinId) + ")", QString(), parentThing->id());
|
||||
ParamList params;
|
||||
params.append(Param(analogOutputSerialThingPinParamTypeId, pinId));
|
||||
descriptor.setParams(params);
|
||||
emit autoThingsAppeared(ThingDescriptors() << descriptor);
|
||||
break;
|
||||
}
|
||||
case OwletSerialClient::PinModeAnalogInput: {
|
||||
qCDebug(dcOwlet()) << "Setting up analog input on serial owlet for pin" << pinId;
|
||||
ThingDescriptor descriptor(analogInputSerialThingClassId, thingClass(analogInputSerialThingClassId).displayName() + " (" + QString::number(pinId) + ")", QString(), parentThing->id());
|
||||
ParamList params;
|
||||
params.append(Param(analogInputSerialThingPinParamTypeId, pinId));
|
||||
descriptor.setParams(params);
|
||||
emit autoThingsAppeared(ThingDescriptors() << descriptor);
|
||||
break;
|
||||
}
|
||||
case OwletSerialClient::PinModeServo: {
|
||||
qCDebug(dcOwlet()) << "Setting up servo on serial owlet for pin" << pinId;
|
||||
ThingDescriptor descriptor(servoSerialThingClassId, thingClass(servoSerialThingClassId).displayName() + " (" + QString::number(pinId) + ")", QString(), parentThing->id());
|
||||
ParamList params;
|
||||
params.append(Param(servoSerialThingPinParamTypeId, pinId));
|
||||
descriptor.setParams(params);
|
||||
emit autoThingsAppeared(ThingDescriptors() << descriptor);
|
||||
break;
|
||||
}
|
||||
case OwletSerialClient::PinModeUnconfigured:
|
||||
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void IntegrationPluginOwlet::configurePin(OwletSerialClient *client, quint8 pinId, OwletSerialClient::PinMode pinMode)
|
||||
{
|
||||
OwletSerialClientReply *reply = client->configurePin(pinId, pinMode);
|
||||
connect(reply, &OwletSerialClientReply::finished, this, [=](){
|
||||
if (reply->status() != OwletSerialClient::StatusSuccess) {
|
||||
qCWarning(dcOwlet()) << "Failed to set pin mode on pin" << pinId << pinMode << reply->status();
|
||||
return;
|
||||
}
|
||||
|
||||
if (reply->responsePayload().count() < 1) {
|
||||
qCWarning(dcOwlet()) << "Failed to set pin mode on pin" << pinId << pinMode << "Invalid response payload size from request";
|
||||
return;
|
||||
}
|
||||
|
||||
OwletSerialClient::GPIOError gpioError = static_cast<OwletSerialClient::GPIOError>(reply->responsePayload().at(0));
|
||||
if (gpioError != OwletSerialClient::GPIOErrorNoError) {
|
||||
qCWarning(dcOwlet()) << "Set pin mode on pin" << pinId << pinMode << "request finished with error" << gpioError;
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcOwlet()) << "Set pin mode finished successfully" << pinId << pinMode;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -34,6 +34,8 @@
|
||||
#include "integrations/integrationplugin.h"
|
||||
#include "extern-plugininfo.h"
|
||||
|
||||
#include "owletserialclient.h"
|
||||
|
||||
class ZeroConfServiceBrowser;
|
||||
class OwletClient;
|
||||
|
||||
@ -57,8 +59,19 @@ private:
|
||||
ZeroConfServiceBrowser *m_zeroConfBrowser = nullptr;
|
||||
|
||||
QHash<Thing *, OwletClient *> m_clients;
|
||||
QHash<Thing *, OwletSerialClient *> m_serialClients;
|
||||
|
||||
QHash<ThingClassId, ParamTypeId> m_owletIdParamTypeMap;
|
||||
|
||||
// Serial owlets
|
||||
QHash<ThingClassId, ParamTypeId> m_owletSerialPortParamTypeMap;
|
||||
QHash<ThingClassId, ParamTypeId> m_owletSerialPinParamTypeMap;
|
||||
|
||||
QHash<ParamTypeId, quint8> m_arduinoMiniProPinMapping;
|
||||
OwletSerialClient::PinMode getPinModeFromSettingsValue(const QString &settingsValue);
|
||||
|
||||
void setupArduinoChildThing(OwletSerialClient *client, quint8 pinId, OwletSerialClient::PinMode pinMode);
|
||||
void configurePin(OwletSerialClient *client, quint8 pinId, OwletSerialClient::PinMode pinMode);
|
||||
};
|
||||
|
||||
#endif // INTEGRATIONPLUGINOWLET_H
|
||||
|
||||
@ -225,7 +225,7 @@
|
||||
"name": "arduinoMiniPro",
|
||||
"displayName": "Arduino Pro Mini Owlet",
|
||||
"createMethods": ["user", "discovery"],
|
||||
"interfaces": ["gateway", "connectable"],
|
||||
"interfaces": ["gateway", "update", "connectable"],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "589715a6-aaf7-4ffb-9c34-015ac22d527e",
|
||||
@ -252,8 +252,7 @@
|
||||
"allowedValues": [
|
||||
"None",
|
||||
"Input",
|
||||
"Output",
|
||||
"Interrupt"
|
||||
"Output"
|
||||
],
|
||||
"defaultValue": "None"
|
||||
},
|
||||
@ -267,7 +266,7 @@
|
||||
"Input",
|
||||
"Output",
|
||||
"PWM",
|
||||
"Interrupt"
|
||||
"Servo"
|
||||
],
|
||||
"defaultValue": "None"
|
||||
},
|
||||
@ -292,7 +291,8 @@
|
||||
"None",
|
||||
"Input",
|
||||
"Output",
|
||||
"PWM"
|
||||
"PWM",
|
||||
"Servo"
|
||||
],
|
||||
"defaultValue": "None"
|
||||
},
|
||||
@ -305,7 +305,8 @@
|
||||
"None",
|
||||
"Input",
|
||||
"Output",
|
||||
"PWM"
|
||||
"PWM",
|
||||
"Servo"
|
||||
],
|
||||
"defaultValue": "None"
|
||||
},
|
||||
@ -342,7 +343,8 @@
|
||||
"None",
|
||||
"Input",
|
||||
"Output",
|
||||
"PWM"
|
||||
"PWM",
|
||||
"Servo"
|
||||
],
|
||||
"defaultValue": "None"
|
||||
},
|
||||
@ -355,7 +357,8 @@
|
||||
"None",
|
||||
"Input",
|
||||
"Output",
|
||||
"PWM"
|
||||
"PWM",
|
||||
"Servo"
|
||||
],
|
||||
"defaultValue": "None"
|
||||
},
|
||||
@ -368,7 +371,8 @@
|
||||
"None",
|
||||
"Input",
|
||||
"Output",
|
||||
"PWM"
|
||||
"PWM",
|
||||
"Servo"
|
||||
],
|
||||
"defaultValue": "None"
|
||||
},
|
||||
@ -497,6 +501,228 @@
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"cached": false
|
||||
},
|
||||
{
|
||||
"id": "f7e86ecd-761b-412e-b5de-a2547f883f76",
|
||||
"name": "currentVersion",
|
||||
"displayName": "Firmware version",
|
||||
"displayNameEvent": "Firmware version changed",
|
||||
"type": "QString",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"id": "43afe87d-3465-4ced-be0f-170f972afea3",
|
||||
"name": "updateStatus",
|
||||
"displayName": "Update status",
|
||||
"displayNameEvent": "Update status changed",
|
||||
"type": "QString",
|
||||
"possibleValues": ["idle", "available", "updating"],
|
||||
"defaultValue": "idle"
|
||||
}
|
||||
],
|
||||
"actionTypes": [
|
||||
{
|
||||
"id": "8cfbb619-de54-441a-8761-d29c6f0c659a",
|
||||
"name": "performUpdate",
|
||||
"displayName": "Update firmware"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "43aca5c1-3972-49ae-b21f-4d1486942e1f",
|
||||
"displayName": "Digital GPIO output on owlet",
|
||||
"name": "digitalOutputSerial",
|
||||
"createMethods": ["auto"],
|
||||
"interfaces": [ "power", "connectable" ],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "6e17a423-89c0-430b-ac78-1af60a63ce50",
|
||||
"name": "pin",
|
||||
"displayName": "Pin number",
|
||||
"type": "uint",
|
||||
"defaultValue": 1
|
||||
}
|
||||
],
|
||||
"stateTypes": [
|
||||
{
|
||||
"id": "3da148b9-fe85-4bf1-9005-082b3cf0c014",
|
||||
"name": "connected",
|
||||
"displayName": "Connected",
|
||||
"displayNameEvent": "Connected changed",
|
||||
"defaultValue": false,
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"id": "2f7dd16b-c1ee-4b2b-859e-e3eacc679400",
|
||||
"name": "power",
|
||||
"displayName": "Power",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"writable": true,
|
||||
"displayNameEvent": "Power changed",
|
||||
"displayNameAction": "Set power",
|
||||
"ioType": "digitalOutput"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "884cb983-3099-4355-a2e6-693f5c1b85e7",
|
||||
"displayName": "Digital GPIO input on owlet",
|
||||
"name": "digitalInputSerial",
|
||||
"createMethods": ["auto"],
|
||||
"interfaces": [ "connectable" ],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "6e872f08-9110-425c-9e17-e24d83452b7d",
|
||||
"name": "pin",
|
||||
"displayName": "Pin number",
|
||||
"type": "uint",
|
||||
"defaultValue": 1
|
||||
}
|
||||
],
|
||||
"stateTypes": [
|
||||
{
|
||||
"id": "112dad0b-9c94-4310-8962-f81e1050c713",
|
||||
"name": "connected",
|
||||
"displayName": "Connected",
|
||||
"displayNameEvent": "Connected changed",
|
||||
"defaultValue": false,
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"id": "9fd72a32-a266-4474-b5b1-e6da9835da6d",
|
||||
"name": "power",
|
||||
"displayName": "Powered",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"displayNameEvent": "Powered changed",
|
||||
"ioType": "digitalInput"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "c6f3cbd9-1863-430a-9fc2-19f7b57b47d7",
|
||||
"displayName": "Analog input GPIO on owlet",
|
||||
"name": "analogInputSerial",
|
||||
"createMethods": ["auto"],
|
||||
"interfaces": [ "connectable" ],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "55b142ab-ae9a-41cd-a23a-5a78ec141013",
|
||||
"name": "pin",
|
||||
"displayName": "Pin number",
|
||||
"type": "uint",
|
||||
"defaultValue": 1
|
||||
}
|
||||
],
|
||||
"settingsTypes": [
|
||||
{
|
||||
"id": "cfdc6cd0-02ae-403c-aab6-8e86306405af",
|
||||
"name": "refreshRate",
|
||||
"displayName": "Refresh rate",
|
||||
"type": "uint",
|
||||
"unit": "MilliSeconds",
|
||||
"minValue": 200,
|
||||
"defaultValue": 500
|
||||
}
|
||||
],
|
||||
"stateTypes": [
|
||||
{
|
||||
"id": "b8fdd65e-dd33-451e-b02f-d7cf73a2e4e2",
|
||||
"name": "connected",
|
||||
"displayName": "Connected",
|
||||
"displayNameEvent": "Connected changed",
|
||||
"defaultValue": false,
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"id": "5b7b50c8-a3aa-494d-a454-96c38f257836",
|
||||
"name": "analogValue",
|
||||
"displayName": "Analog value",
|
||||
"displayNameEvent": "Analog value changed",
|
||||
"type": "uint",
|
||||
"defaultValue": 0,
|
||||
"minValue": 0,
|
||||
"maxValue": 1023,
|
||||
"ioType": "analogInput"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "ee228a56-9cf2-4401-84c2-8e25f288f136",
|
||||
"displayName": "PWM on owlet",
|
||||
"name": "analogOutputSerial",
|
||||
"createMethods": ["auto"],
|
||||
"interfaces": [ "connectable" ],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "e2da646f-003f-495b-8250-28067732973a",
|
||||
"name": "pin",
|
||||
"displayName": "Pin number",
|
||||
"type": "uint",
|
||||
"defaultValue": 1
|
||||
}
|
||||
],
|
||||
"stateTypes": [
|
||||
{
|
||||
"id": "d08ed1bd-0ddf-4bad-9689-cc7730a54b05",
|
||||
"name": "connected",
|
||||
"displayName": "Connected",
|
||||
"displayNameEvent": "Connected changed",
|
||||
"defaultValue": false,
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"id": "8c8065f7-b335-41bf-a015-fd2cd7e68e81",
|
||||
"name": "dutyCycle",
|
||||
"displayName": "Duty cycle",
|
||||
"displayNameEvent": "Duty cycle changed",
|
||||
"displayNameAction": "Set duty cycle",
|
||||
"type": "uint",
|
||||
"minValue": 0,
|
||||
"maxValue": 255,
|
||||
"defaultValue": 0,
|
||||
"writable": true,
|
||||
"ioType": "analogOutput"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "66d9725a-b096-4300-b0e1-adc043ee12c3",
|
||||
"displayName": "Servo on owlet",
|
||||
"name": "servoSerial",
|
||||
"createMethods": ["auto"],
|
||||
"interfaces": [ "connectable" ],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "4596b43d-93e9-46e4-8831-59f96f998606",
|
||||
"name": "pin",
|
||||
"displayName": "Pin number",
|
||||
"type": "uint",
|
||||
"defaultValue": 1
|
||||
}
|
||||
],
|
||||
"stateTypes": [
|
||||
{
|
||||
"id": "0ae0d6a4-8eb1-4d4f-b093-59ce42355ad7",
|
||||
"name": "connected",
|
||||
"displayName": "Connected",
|
||||
"displayNameEvent": "Connected changed",
|
||||
"defaultValue": false,
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"id": "eee4e07a-1cb1-44d1-98d5-d66d2e63f704",
|
||||
"name": "angle",
|
||||
"displayName": "Angle",
|
||||
"displayNameEvent": "Angle changed",
|
||||
"displayNameAction": "Set angle",
|
||||
"type": "uint",
|
||||
"minValue": 0,
|
||||
"maxValue": 180,
|
||||
"defaultValue": 0,
|
||||
"writable": true,
|
||||
"ioType": "analogOutput"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ QT += network serialport
|
||||
SOURCES += \
|
||||
integrationpluginowlet.cpp \
|
||||
owletclient.cpp \
|
||||
owletserialclient.cpp \
|
||||
owletserialtransport.cpp \
|
||||
owlettcptransport.cpp \
|
||||
owlettransport.cpp
|
||||
@ -12,6 +13,7 @@ SOURCES += \
|
||||
HEADERS += \
|
||||
integrationpluginowlet.h \
|
||||
owletclient.h \
|
||||
owletserialclient.h \
|
||||
owletserialtransport.h \
|
||||
owlettcptransport.h \
|
||||
owlettransport.h
|
||||
|
||||
249
owlet/owletserialclient.cpp
Normal file
249
owlet/owletserialclient.cpp
Normal file
@ -0,0 +1,249 @@
|
||||
#include "owletserialclient.h"
|
||||
#include "extern-plugininfo.h"
|
||||
|
||||
#include <QDataStream>
|
||||
|
||||
OwletSerialClient::OwletSerialClient(OwletTransport *transport, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_transport(transport)
|
||||
{
|
||||
connect(m_transport, &OwletTransport::dataReceived, this, &OwletSerialClient::dataReceived);
|
||||
connect(m_transport, &OwletTransport::error, this, &OwletSerialClient::error);
|
||||
connect(m_transport, &OwletTransport::connectedChanged, this, [=](bool transportConnected){
|
||||
if (!transportConnected) {
|
||||
m_ready = false;
|
||||
emit disconnected();
|
||||
|
||||
// Clean up queue
|
||||
qDeleteAll(m_pendingRequests);
|
||||
m_pendingRequests.clear();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
OwletTransport *OwletSerialClient::transport() const
|
||||
{
|
||||
return m_transport;
|
||||
}
|
||||
|
||||
bool OwletSerialClient::ready() const
|
||||
{
|
||||
return m_ready;
|
||||
}
|
||||
|
||||
OwletSerialClientReply *OwletSerialClient::getFirmwareVersion()
|
||||
{
|
||||
qCDebug(dcOwlet()) << "Request owlet firmware version";
|
||||
QByteArray requestData;
|
||||
QDataStream stream(&requestData, QIODevice::WriteOnly);
|
||||
stream << static_cast<quint8>(OwletSerialClient::CommandGetFirmwareVersion);
|
||||
stream << m_requestId++;
|
||||
|
||||
OwletSerialClientReply *reply = createReply(requestData);
|
||||
m_pendingRequests.enqueue(reply);
|
||||
sendNextRequest();
|
||||
return reply;
|
||||
}
|
||||
|
||||
OwletSerialClientReply *OwletSerialClient::configurePin(quint8 pinId, PinMode pinMode)
|
||||
{
|
||||
qCDebug(dcOwlet()) << "Configure pin" << pinId << pinMode;
|
||||
QByteArray requestData;
|
||||
QDataStream stream(&requestData, QIODevice::WriteOnly);
|
||||
stream << static_cast<quint8>(OwletSerialClient::CommandConfigurePin);
|
||||
stream << m_requestId++;
|
||||
stream << pinId << static_cast<quint8>(pinMode);
|
||||
|
||||
OwletSerialClientReply *reply = createReply(requestData);
|
||||
m_pendingRequests.enqueue(reply);
|
||||
sendNextRequest();
|
||||
return reply;
|
||||
}
|
||||
|
||||
OwletSerialClientReply *OwletSerialClient::writeDigitalValue(quint8 pinId, bool power)
|
||||
{
|
||||
qCDebug(dcOwlet()) << "Setting gpio output power of pin" << pinId << power;
|
||||
QByteArray requestData;
|
||||
QDataStream stream(&requestData, QIODevice::WriteOnly);
|
||||
stream << static_cast<quint8>(OwletSerialClient::CommandWriteDigitalPin);
|
||||
stream << m_requestId++;
|
||||
stream << pinId << static_cast<quint8>(power ? 0x01 : 0x00);
|
||||
|
||||
OwletSerialClientReply *reply = createReply(requestData);
|
||||
m_pendingRequests.enqueue(reply);
|
||||
sendNextRequest();
|
||||
return reply;
|
||||
}
|
||||
|
||||
OwletSerialClientReply *OwletSerialClient::readDigitalValue(quint8 pinId)
|
||||
{
|
||||
qCDebug(dcOwlet()) << "Reading digital gpio value of pin" << pinId;
|
||||
QByteArray requestData;
|
||||
QDataStream stream(&requestData, QIODevice::WriteOnly);
|
||||
stream << static_cast<quint8>(OwletSerialClient::CommandReadDigitalPin);
|
||||
stream << m_requestId++;
|
||||
stream << pinId;
|
||||
|
||||
OwletSerialClientReply *reply = createReply(requestData);
|
||||
m_pendingRequests.enqueue(reply);
|
||||
sendNextRequest();
|
||||
return reply;
|
||||
}
|
||||
|
||||
OwletSerialClientReply *OwletSerialClient::writeAnalogValue(quint8 pinId, quint8 dutyCycle)
|
||||
{
|
||||
qCDebug(dcOwlet()) << "Write analog gpio value of pin" << pinId << dutyCycle;
|
||||
QByteArray requestData;
|
||||
QDataStream stream(&requestData, QIODevice::WriteOnly);
|
||||
stream << static_cast<quint8>(OwletSerialClient::CommandWriteAnalogPin);
|
||||
stream << m_requestId++;
|
||||
stream << pinId;
|
||||
stream << dutyCycle;
|
||||
|
||||
OwletSerialClientReply *reply = createReply(requestData);
|
||||
m_pendingRequests.enqueue(reply);
|
||||
sendNextRequest();
|
||||
return reply;
|
||||
}
|
||||
|
||||
OwletSerialClientReply *OwletSerialClient::readAnalogValue(quint8 pinId)
|
||||
{
|
||||
qCDebug(dcOwlet()) << "Reading analog gpio value of pin" << pinId;
|
||||
QByteArray requestData;
|
||||
QDataStream stream(&requestData, QIODevice::WriteOnly);
|
||||
stream << static_cast<quint8>(OwletSerialClient::CommandReadAnalogPin);
|
||||
stream << m_requestId++;
|
||||
stream << pinId;
|
||||
|
||||
OwletSerialClientReply *reply = createReply(requestData);
|
||||
m_pendingRequests.enqueue(reply);
|
||||
sendNextRequest();
|
||||
return reply;
|
||||
}
|
||||
|
||||
OwletSerialClientReply *OwletSerialClient::writeServoValue(quint8 pinId, quint8 angle)
|
||||
{
|
||||
qCDebug(dcOwlet()) << "Setting servo angle of pin" << pinId << angle;
|
||||
QByteArray requestData;
|
||||
QDataStream stream(&requestData, QIODevice::WriteOnly);
|
||||
stream << static_cast<quint8>(OwletSerialClient::CommandWriteServoPin);
|
||||
stream << m_requestId++;
|
||||
stream << pinId;
|
||||
stream << angle;
|
||||
|
||||
OwletSerialClientReply *reply = createReply(requestData);
|
||||
m_pendingRequests.enqueue(reply);
|
||||
sendNextRequest();
|
||||
return reply;
|
||||
}
|
||||
|
||||
QString OwletSerialClient::firmwareVersion() const
|
||||
{
|
||||
return m_firmwareVersion;
|
||||
}
|
||||
|
||||
void OwletSerialClient::dataReceived(const QByteArray &data)
|
||||
{
|
||||
QDataStream stream(data);
|
||||
quint8 commandId; quint8 requestId;
|
||||
stream >> commandId >> requestId;
|
||||
|
||||
// Check if command or notification
|
||||
if (commandId < 0xF0) {
|
||||
quint8 statusId;
|
||||
stream >> statusId;
|
||||
OwletSerialClient::Command command = static_cast<OwletSerialClient::Command>(commandId);
|
||||
OwletSerialClient::Status status = static_cast<OwletSerialClient::Status>(statusId);
|
||||
if (m_currentReply) {
|
||||
if (m_currentReply->command() == command && m_currentReply->requestId() == requestId) {
|
||||
m_currentReply->m_timer.stop();
|
||||
m_currentReply->m_status = status;
|
||||
m_currentReply->m_responsePayload = data.right(data.length() - 3);
|
||||
|
||||
if (status != OwletSerialClient::StatusSuccess) {
|
||||
qCWarning(dcOwlet()) << "Request finished with error" << command << "ID:" << m_currentReply->requestId() << status;
|
||||
} else {
|
||||
qCDebug(dcOwlet()) << "Request finished" << command << "ID:" << m_currentReply->requestId() << status << "Payload:" << m_currentReply->responsePayload().toHex();
|
||||
}
|
||||
|
||||
emit m_currentReply->finished();
|
||||
}
|
||||
} else {
|
||||
qCWarning(dcOwlet()) << "Received unhandled command response data" << data.toHex();
|
||||
}
|
||||
} else {
|
||||
OwletSerialClient::Notification notification = static_cast<OwletSerialClient::Notification>(commandId);
|
||||
QByteArray notificationPayload = data.right(data.length() - 2);
|
||||
qCDebug(dcOwlet()) << "Notification received" << notification << "ID:" << requestId << notificationPayload.toHex();
|
||||
switch (notification) {
|
||||
case OwletSerialClient::NotificationReady: {
|
||||
OwletSerialClientReply *reply = getFirmwareVersion();
|
||||
connect(reply, &OwletSerialClientReply::finished, this, [this, reply](){
|
||||
if (reply->status() != OwletSerialClient::StatusSuccess) {
|
||||
qCWarning(dcOwlet()) << "Failed to get firmware version" << reply->status();
|
||||
emit error();
|
||||
return;
|
||||
}
|
||||
|
||||
if (reply->responsePayload().count() != 3) {
|
||||
qCWarning(dcOwlet()) << "Invalid firmware version payload size";
|
||||
emit error();
|
||||
return;
|
||||
}
|
||||
|
||||
quint8 major = reply->responsePayload().at(0);
|
||||
quint8 minor = reply->responsePayload().at(1);
|
||||
quint8 patch = reply->responsePayload().at(2);
|
||||
|
||||
m_firmwareVersion = QString("%1.%2.%3").arg(major).arg(minor).arg(patch);
|
||||
qCDebug(dcOwlet()) << "Connected successfully to firmware" << m_firmwareVersion;
|
||||
m_ready = true;
|
||||
emit connected();
|
||||
});
|
||||
break;
|
||||
}
|
||||
case OwletSerialClient::NotificationGpioPinChanged: {
|
||||
quint8 pinId; quint8 powerValue;
|
||||
stream >> pinId >> powerValue;
|
||||
bool power = powerValue != 0x00;
|
||||
qCDebug(dcOwlet()) << "Pin value changed" << pinId << power;
|
||||
emit pinValueChanged(pinId, power);
|
||||
break;
|
||||
}
|
||||
case OwletSerialClient::NotificationDebugMessage:
|
||||
qCDebug(dcOwlet()) << "Firmware debug:" << QString::fromUtf8(data.right(data.length() - 2));
|
||||
break;
|
||||
default:
|
||||
qCWarning(dcOwlet()) << "Unhandled notification received" << data.toHex();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OwletSerialClientReply *OwletSerialClient::createReply(const QByteArray &requestData)
|
||||
{
|
||||
OwletSerialClientReply *reply = new OwletSerialClientReply(requestData, this);
|
||||
connect(reply, &OwletSerialClientReply::finished, reply, [=](){
|
||||
reply->deleteLater();
|
||||
if (reply == m_currentReply) {
|
||||
m_currentReply = nullptr;
|
||||
}
|
||||
sendNextRequest();
|
||||
});
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
void OwletSerialClient::sendNextRequest()
|
||||
{
|
||||
if (m_currentReply)
|
||||
return;
|
||||
|
||||
if (m_pendingRequests.isEmpty())
|
||||
return;
|
||||
|
||||
m_currentReply = m_pendingRequests.dequeue();
|
||||
qCDebug(dcOwlet()) << "Sending request" << m_currentReply->command() << "ID:" << m_currentReply->requestId() << "Payload:" << m_currentReply->requestData().right(m_currentReply->requestData().length() - 2).toHex();
|
||||
m_transport->sendData(m_currentReply->requestData());
|
||||
m_currentReply->m_timer.start();
|
||||
}
|
||||
150
owlet/owletserialclient.h
Normal file
150
owlet/owletserialclient.h
Normal file
@ -0,0 +1,150 @@
|
||||
#ifndef OWLETSERIALCLIENT_H
|
||||
#define OWLETSERIALCLIENT_H
|
||||
|
||||
#include <QTimer>
|
||||
#include <QObject>
|
||||
#include <QQueue>
|
||||
|
||||
#include "owlettransport.h"
|
||||
|
||||
class OwletSerialClientReply;
|
||||
|
||||
class OwletSerialClient : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Command {
|
||||
CommandGetFirmwareVersion = 0x00,
|
||||
CommandConfigurePin = 0x01,
|
||||
CommandWriteDigitalPin = 0x02,
|
||||
CommandReadDigitalPin = 0x03,
|
||||
CommandWriteAnalogPin = 0x04,
|
||||
CommandReadAnalogPin = 0x05,
|
||||
CommandWriteServoPin = 0x06
|
||||
};
|
||||
Q_ENUM(Command)
|
||||
|
||||
enum Notification {
|
||||
NotificationReady = 0xf0,
|
||||
NotificationGpioPinChanged = 0xf1,
|
||||
NotificationDebugMessage = 0xff
|
||||
};
|
||||
Q_ENUM(Notification)
|
||||
|
||||
enum Status {
|
||||
StatusSuccess = 0x00,
|
||||
StatusInvalidProtocol = 0x01,
|
||||
StatusInvalidCommand = 0x02,
|
||||
StatusInvalidPlayload = 0x03,
|
||||
StatusTimeout = 0xfe,
|
||||
StatusUnknownError = 0xff
|
||||
};
|
||||
Q_ENUM(Status)
|
||||
|
||||
enum GPIOError {
|
||||
GPIOErrorNoError = 0x00,
|
||||
GPIOErrorUnconfigured = 0x01,
|
||||
GPIOErrorUnsupported = 0x02,
|
||||
GPIOErrorConfigurationMismatch = 0x03,
|
||||
GPIOErrorInvalidParameter = 0x04,
|
||||
GPIOErrorInvalidPin = 0x05
|
||||
};
|
||||
Q_ENUM(GPIOError)
|
||||
|
||||
enum PinMode {
|
||||
PinModeUnconfigured = 0x00,
|
||||
PinModeDigitalInput = 0x01,
|
||||
PinModeDigitalOutput = 0x02,
|
||||
PinModeAnalogInput = 0x03,
|
||||
PinModeAnalogOutput = 0x04,
|
||||
PinModeServo = 0x05
|
||||
};
|
||||
Q_ENUM(PinMode)
|
||||
|
||||
explicit OwletSerialClient(OwletTransport *transport, QObject *parent = nullptr);
|
||||
|
||||
OwletTransport *transport() const;
|
||||
|
||||
bool ready() const;
|
||||
|
||||
OwletSerialClientReply *getFirmwareVersion();
|
||||
OwletSerialClientReply *configurePin(quint8 pinId, PinMode pinMode);
|
||||
OwletSerialClientReply *writeDigitalValue(quint8 pinId, bool power);
|
||||
OwletSerialClientReply *readDigitalValue(quint8 pinId);
|
||||
OwletSerialClientReply *writeAnalogValue(quint8 pinId, quint8 dutyCycle);
|
||||
OwletSerialClientReply *readAnalogValue(quint8 pinId);
|
||||
OwletSerialClientReply *writeServoValue(quint8 pinId, quint8 angle);
|
||||
|
||||
QString firmwareVersion() const;
|
||||
|
||||
signals:
|
||||
void connected();
|
||||
void disconnected();
|
||||
void error();
|
||||
|
||||
void pinValueChanged(quint8 pinId, bool power);
|
||||
|
||||
private slots:
|
||||
void dataReceived(const QByteArray &data);
|
||||
|
||||
private:
|
||||
OwletTransport *m_transport = nullptr;
|
||||
bool m_ready = false;
|
||||
|
||||
quint8 m_requestId = 0;
|
||||
|
||||
OwletSerialClientReply *m_currentReply = nullptr;
|
||||
QQueue<OwletSerialClientReply *> m_pendingRequests;
|
||||
|
||||
QString m_firmwareVersion;
|
||||
|
||||
OwletSerialClientReply *createReply(const QByteArray &requestData);
|
||||
void sendNextRequest();
|
||||
};
|
||||
|
||||
|
||||
class OwletSerialClientReply : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
friend class OwletSerialClient;
|
||||
|
||||
public:
|
||||
QByteArray requestData() const { return m_requestData; };
|
||||
OwletSerialClient::Command command() const { return m_command; };
|
||||
quint8 requestId() const { return m_requestId; };
|
||||
OwletSerialClient::Status status() const { return m_status; };
|
||||
QByteArray responsePayload() const { return m_responsePayload; };
|
||||
|
||||
signals:
|
||||
void finished();
|
||||
|
||||
private:
|
||||
explicit OwletSerialClientReply(const QByteArray &requestData, QObject *parent = nullptr) :
|
||||
QObject(parent),
|
||||
m_requestData(requestData)
|
||||
{
|
||||
Q_ASSERT(m_requestData.length() >= 2);
|
||||
m_command = static_cast<OwletSerialClient::Command>(m_requestData.at(0));
|
||||
m_requestId = static_cast<quint8>(m_requestData.at(1));
|
||||
|
||||
m_timer.setInterval(1000);
|
||||
m_timer.setSingleShot(true);
|
||||
connect(&m_timer, &QTimer::timeout, this, [=](){
|
||||
m_status = OwletSerialClient::StatusTimeout;
|
||||
emit finished();
|
||||
});
|
||||
}
|
||||
|
||||
QTimer m_timer;
|
||||
QByteArray m_requestData;
|
||||
OwletSerialClient::Command m_command;
|
||||
quint8 m_requestId = 0;
|
||||
|
||||
// Response
|
||||
OwletSerialClient::Status m_status = OwletSerialClient::StatusUnknownError;
|
||||
QByteArray m_responsePayload;
|
||||
};
|
||||
|
||||
|
||||
#endif // OWLETSERIALCLIENT_H
|
||||
@ -27,12 +27,13 @@ OwletSerialTransport::OwletSerialTransport(const QString &serialPortName, uint b
|
||||
connect(m_serialPort, &QSerialPort::errorOccurred, this, &OwletSerialTransport::onError);
|
||||
#endif
|
||||
|
||||
|
||||
m_reconnectTimer = new QTimer(this);
|
||||
m_reconnectTimer->setInterval(5000);
|
||||
m_reconnectTimer->setSingleShot(false);
|
||||
connect(m_reconnectTimer, &QTimer::timeout, this, [=](){
|
||||
if (m_serialPort->isOpen()) {
|
||||
// Clear any buffer content
|
||||
m_serialPort->clear();
|
||||
m_reconnectTimer->stop();
|
||||
return;
|
||||
} else {
|
||||
@ -48,6 +49,8 @@ bool OwletSerialTransport::connected() const
|
||||
|
||||
void OwletSerialTransport::sendData(const QByteArray &data)
|
||||
{
|
||||
qCDebug(dcOwlet()) << "UART -->" << data.toHex();
|
||||
|
||||
// Stream bytes using SLIP
|
||||
QByteArray message;
|
||||
QDataStream stream(&message, QIODevice::WriteOnly);
|
||||
@ -71,7 +74,8 @@ void OwletSerialTransport::sendData(const QByteArray &data)
|
||||
}
|
||||
stream << static_cast<quint8>(SlipProtocolEnd);
|
||||
|
||||
qCDebug(dcOwlet()) << "UART -->" << qUtf8Printable(data) << message.toHex();
|
||||
//qCDebug(dcOwlet()) << "UART -->" << message.toHex();
|
||||
|
||||
m_serialPort->write(message);
|
||||
m_serialPort->flush();
|
||||
}
|
||||
@ -102,6 +106,7 @@ void OwletSerialTransport::connectTransport()
|
||||
if (!m_serialPort->open(QIODevice::ReadWrite)) {
|
||||
qCWarning(dcOwlet()) << "Could not open serial port on" << m_serialPortName << m_serialPort->errorString();
|
||||
m_reconnectTimer->start();
|
||||
emit error();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -120,7 +125,7 @@ void OwletSerialTransport::disconnectTransport()
|
||||
void OwletSerialTransport::onReadyRead()
|
||||
{
|
||||
QByteArray data = m_serialPort->readAll();
|
||||
qCDebug(dcOwlet()) << "UART <-- raw:" << data.toHex() << qUtf8Printable(data);
|
||||
//qCDebug(dcOwlet()) << "UART <--" << data.toHex();
|
||||
|
||||
for (int i = 0; i < data.length(); i++) {
|
||||
quint8 receivedByte = data.at(i);
|
||||
@ -144,8 +149,8 @@ void OwletSerialTransport::onReadyRead()
|
||||
switch (receivedByte) {
|
||||
case SlipProtocolEnd:
|
||||
// We are done with this package, process it and reset the buffer
|
||||
if (!m_buffer.isEmpty() && m_buffer.length() >= 3) {
|
||||
qCDebug(dcOwlet()) << "UART <--" << m_buffer.toHex() << qUtf8Printable(m_buffer);
|
||||
if (!m_buffer.isEmpty() && m_buffer.length() >= 2) {
|
||||
qCDebug(dcOwlet()) << "UART <--" << m_buffer.toHex();
|
||||
emit dataReceived(m_buffer);
|
||||
}
|
||||
m_buffer.clear();
|
||||
@ -168,6 +173,7 @@ void OwletSerialTransport::onError(QSerialPort::SerialPortError serialPortError)
|
||||
if (serialPortError != QSerialPort::NoError && serialPortError != QSerialPort::OpenError && m_serialPort->isOpen()) {
|
||||
qCWarning(dcOwlet()) << "Serial port error occured" << serialPortError << m_serialPort->errorString();
|
||||
emit error();
|
||||
|
||||
m_reconnectTimer->start();
|
||||
if (m_serialPort->isOpen()) {
|
||||
m_serialPort->close();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user