BT40 AddDeviceWizard updates

Just a checkpoint before BT40 pair updates to connect with
each found sensor and display current data on the pair screen.

This is so the user can select the devices they want to be
included in this device definition (if they have lots of
BTLE devices).

I guess this is gonna mostly be dcrainmaker and wahoo employees!
This commit is contained in:
Mark Liversedge
2013-01-30 13:39:07 +00:00
parent c9571e0d8b
commit 6c583da655
2 changed files with 258 additions and 4 deletions

View File

@@ -24,6 +24,7 @@
// 20. Scan for Device / select Serial
// 30. Firmware for Fortius
// 50. Pair for ANT
// 55. Pair for BTLE
// 60. Finalise
//
@@ -48,7 +49,8 @@ AddDeviceWizard::AddDeviceWizard(MainWindow *main) : QWizard(main), main(main)
setPage(10, new AddType(this)); // done
setPage(20, new AddSearch(this)); // done
setPage(30, new AddFirmware(this)); // done
setPage(50, new AddPair(this)); // todo
setPage(50, new AddPair(this)); // done
setPage(55, new AddPairBTLE(this)); // done
setPage(60, new AddFinal(this)); // todo -- including virtual power
done = false;
@@ -131,10 +133,10 @@ AddType::clicked(QString p)
if (wizard->found == false) next =20;
else {
switch(wizard->deviceTypes.Supported[wizard->current].type) {
case DEV_KICKR :
case DEV_BT40 :
case DEV_BT40 : next = 55; break;
case DEV_ANTLOCAL : next = 50; break; // pair
default:
case DEV_KICKR :
case DEV_CT : next = 60; break; // confirm and add
case DEV_FORTIUS : next = 30; break; // confirm and add
}
@@ -437,7 +439,7 @@ AddSearch::nextId() const
else {
switch(wizard->deviceTypes.Supported[wizard->current].type) {
case DEV_ANTLOCAL : return 50; break; // pair
case DEV_BT40 : //XXX need a BT40 pair screen
case DEV_BT40 : return 55; break; // pair BT devices
default:
case DEV_KICKR :
case DEV_CT : return 60; break; // confirm and add
@@ -813,6 +815,230 @@ AddPair::validatePage()
return true;
}
// Pair devices
AddPairBTLE::AddPairBTLE(AddDeviceWizard *parent) : QWizardPage(parent), wizard(parent)
{
setTitle(tr("Pair Devices"));
setSubTitle(tr("Search for and pair Bluetooth 4.0 devices"));
signalMapper = NULL;
QVBoxLayout *layout = new QVBoxLayout;
setLayout(layout);
channelWidget = new QTreeWidget(this);
layout->addWidget(channelWidget);
}
void
AddPairBTLE::cleanupPage()
{
updateValues.stop();
if (wizard->controller) {
wizard->controller->stop();
#ifdef WIN32
Sleep(1000);
#else
sleep(1);
#endif
delete wizard->controller;
wizard->controller = NULL;
}
}
void
AddPairBTLE::initializePage()
{
// setup the controller and start it off so we can
// manipulate it
if (wizard->controller) delete wizard->controller;
if (signalMapper) delete signalMapper;
wizard->controller = new ANTlocalController(NULL,NULL);
dynamic_cast<ANTlocalController*>(wizard->controller)->setDevice(wizard->portSpec);
dynamic_cast<ANTlocalController*>(wizard->controller)->myANTlocal->setConfigurationMode(true); //XXX
wizard->controller->start();
wizard->profile=""; // clear any thing thats there now
signalMapper = new QSignalMapper(this);
// Channel 0, look for any (0 devicenumber) speed and distance device
// wait for it to start
#ifdef WIN32
Sleep(1000);
#else
sleep(1);
#endif
int channels = dynamic_cast<ANTlocalController*>(wizard->controller)->channels();
// Tree Widget of the channel controls
channelWidget->clear();
channelWidget->headerItem()->setText(0, tr("Sensor"));
channelWidget->headerItem()->setText(1, tr("ANT+ Id"));
channelWidget->headerItem()->setText(2, tr("Value"));
channelWidget->headerItem()->setText(3, tr("Status"));
channelWidget->setColumnCount(4);
channelWidget->setSelectionMode(QAbstractItemView::NoSelection);
//channelWidget->setEditTriggers(QAbstractItemView::SelectedClicked); // allow edit
channelWidget->setUniformRowHeights(true);
channelWidget->setIndentation(0);
channelWidget->header()->resizeSection(0,175); // type
channelWidget->header()->resizeSection(1,75); // id
channelWidget->header()->resizeSection(2,120); // value
channelWidget->header()->resizeSection(3,110); // status
// defaults
static const int index4[4] = { 1,2,3,5 };
static const int index8[8] = { 1,2,3,4,5,0,0,0 };
const int *index = channels == 4 ? index4 : index8;
// how many devices we got then?
for (int i=0; i< channels; i++) {
QTreeWidgetItem *add = new QTreeWidgetItem(channelWidget->invisibleRootItem());
add->setFlags(add->flags() | Qt::ItemIsEditable);
// sensor type
QComboBox *sensorSelector = new QComboBox(this);
addSensorTypes(dynamic_cast<ANTlocalController*>(wizard->controller)->myANTlocal, sensorSelector);
sensorSelector->setCurrentIndex(index[i]);
channelWidget->setItemWidget(add, 0, sensorSelector);
// sensor id
QLineEdit *sensorId = new QLineEdit(this);
sensorId->setEnabled(false);
sensorId->setText("none");
channelWidget->setItemWidget(add, 1, sensorId);
// value
QLabel *value = new QLabel(this);
QFont bigger;
bigger.setPointSize(25);
value->setFont(bigger);
value->setAlignment(Qt::AlignCenter | Qt::AlignVCenter);
value->setText("0");
channelWidget->setItemWidget(add, 2, value);
// status
QLabel *status = new QLabel(this);
status->setText("Un-Paired");
channelWidget->setItemWidget(add, 3, status);
//channelWidget->verticalHeader()->resizeSection(i,40)
connect(sensorSelector, SIGNAL(currentIndexChanged(int)), signalMapper, SLOT(map()));
signalMapper->setMapping(sensorSelector, i);
}
channelWidget->setCurrentItem(channelWidget->invisibleRootItem()->child(0));
enableDisable(channelWidget);
updateValues.start(200); // 5hz
connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(sensorChanged(int)));
connect(&updateValues, SIGNAL(timeout()), this, SLOT(getChannelValues()));
connect(wizard->controller, SIGNAL(foundDevice(int,int,int)), this, SLOT(channelInfo(int,int,int)));
connect(wizard->controller, SIGNAL(searchTimeout(int)), this, SLOT(searchTimeout(int)));
//connect(wizard->controller, SIGNAL(lostDevice(int)), this, SLOT(searchTimeout(int)));
// now we're ready to get notifications - set channels
for (int i=0; i<channels; i++) sensorChanged(i);
}
void
AddPairBTLE::sensorChanged(int channel)
{
QTreeWidgetItem *item = channelWidget->invisibleRootItem()->child(channel);
enableDisable(channelWidget);
// first off lets unassign this channel
dynamic_cast<ANTlocalController*>(wizard->controller)->myANTlocal->setChannel(channel, -1, 0);
dynamic_cast<QLineEdit*>(channelWidget->itemWidget(item,1))->setText("none");
dynamic_cast<QLabel*>(channelWidget->itemWidget(item,2))->setText(0);
// what is it then? unused or restart scan?
QComboBox *p = dynamic_cast<QComboBox *>(channelWidget->itemWidget(item,0));
int channel_type = p->itemData(p->currentIndex()).toInt();
if (channel_type == ANTChannel::CHANNEL_TYPE_UNUSED) {
dynamic_cast<QLabel*>(channelWidget->itemWidget(item,3))->setText("Unused");
} else {
dynamic_cast<QLabel*>(channelWidget->itemWidget(item,3))->setText("Searching...");
dynamic_cast<ANTlocalController*>(wizard->controller)->myANTlocal->setChannel(channel, 0, channel_type);
}
}
void
AddPairBTLE::channelInfo(int channel, int device_number, int device_id)
{
Q_UNUSED(device_id);
QTreeWidgetItem *item = channelWidget->invisibleRootItem()->child(channel);
dynamic_cast<QLineEdit *>(channelWidget->itemWidget(item,1))->setText(QString("%1").arg(device_number));
dynamic_cast<QLabel *>(channelWidget->itemWidget(item,3))->setText(QString("Paired"));
}
void
AddPairBTLE::searchTimeout(int channel)
{
// Kick if off again, just mimic user reselecting the same sensor type
sensorChanged(channel);
}
void
AddPairBTLE::getChannelValues()
{
if (wizard->controller == NULL) return;
// enable disable widgets based upon sensor selection
for (int i=0; i< channelWidget->invisibleRootItem()->childCount(); i++) {
QTreeWidgetItem *item = channelWidget->invisibleRootItem()->child(i);
// is it selected or not?
bool enable = (dynamic_cast<QComboBox*>(channelWidget->itemWidget(item,0))->currentIndex() != 0);
if (enable) {
QComboBox *p =dynamic_cast<QComboBox*>(channelWidget->itemWidget(item,0));
// speed+cadence is two values!
if (p->itemData(p->currentIndex()) == ANTChannel::CHANNEL_TYPE_SandC) {
dynamic_cast<QLabel *>(channelWidget->itemWidget(item,2))->setText(QString("%1 %2")
.arg((int)dynamic_cast<ANTlocalController*>(wizard->controller)->myANTlocal->channelValue2(i) //speed
* (appsettings->value(NULL, GC_WHEELSIZE, 2100).toInt()/1000) * 60 / 1000)
.arg((int)dynamic_cast<ANTlocalController*>(wizard->controller)->myANTlocal->channelValue(i))); // cad
} else {
dynamic_cast<QLabel *>(channelWidget->itemWidget(item,2))->setText(QString("%1")
.arg((int)dynamic_cast<ANTlocalController*>(wizard->controller)->myANTlocal->channelValue(i)));
}
}
}
}
bool
AddPairBTLE::validatePage()
{
// when next is clicked we need to get the paired values
// and create a profile, a blank profile will be created if
// no devices have been paired. This means devices will be
// automatically paired at runtime
wizard->profile="";
for (int i=0; i< channelWidget->invisibleRootItem()->childCount(); i++) {
QTreeWidgetItem *item = channelWidget->invisibleRootItem()->child(i);
// what is it then? unused or restart scan?
QComboBox *p = dynamic_cast<QComboBox *>(channelWidget->itemWidget(item,0));
int channel_type = p->itemData(p->currentIndex()).toInt();
if (channel_type == ANTChannel::CHANNEL_TYPE_UNUSED) continue; // not paired
int device_number = dynamic_cast<QLineEdit*>(channelWidget->itemWidget(item,1))->text().toInt();
if (device_number)
wizard->profile += QString(wizard->profile != "" ? ", %1%2" : "%1%2")
.arg(device_number)
.arg(ANT::deviceIdCode(channel_type));
}
return true;
}
// Final confirmation
AddFinal::AddFinal(AddDeviceWizard *parent) : QWizardPage(parent), wizard(parent)
{

View File

@@ -168,6 +168,34 @@ class AddPair : public QWizardPage
QTimer updateValues;
};
class AddPairBTLE : public QWizardPage
{
Q_OBJECT
public:
AddPairBTLE(AddDeviceWizard *);
int nextId() const { return 60; }
void initializePage();
bool validatePage();
void cleanupPage();
public slots:
void getChannelValues();
// we found a device on a channel
void channelInfo(int channel, int device_number, int device_id);
// we failed to find a device on the channel
void searchTimeout(int channel);
// user interactions
void sensorChanged(int channel); // sensor selection changed
private:
AddDeviceWizard *wizard;
QTreeWidget *channelWidget;
QSignalMapper *signalMapper;
QTimer updateValues;
};
class AddFinal : public QWizardPage
{
Q_OBJECT