QDateTime read_date(int *bytes_read = NULL, int *sum = NULL) { int sec = bcd2Int(read_bytes(1, bytes_read, sum)); int min = bcd2Int(read_bytes(1, bytes_read, sum)); int hour = bcd2Int(read_bytes(1, bytes_read, sum)); int day = bcd2Int(read_bytes(1, bytes_read, sum)); int month = bcd2Int(read_bytes(1, bytes_read, sum)); int year = bcd2Int(read_bytes(1, bytes_read, sum)); return QDateTime(QDate(2000+year,month,day), QTime(hour,min,sec)); }
bool JouleDevice::getDownloadableRides(QList<DeviceStoredRideItem> &rides, bool isJouleGPS_GPSPLUS, QString &err) { emit updateStatus(tr("Read summary...")); if (JOULE_DEBUG) printf("Read summary\n"); JoulePacket request(READ_RIDE_SUMMARY); if (!request.write(dev, err)) return false; JoulePacket response = JoulePacket(READ_RIDE_SUMMARY); if (response.read(dev, err)) { int length = (isJouleGPS_GPSPLUS?20:16); int count = response.payload.length()/length; for (int i=0; i<count; i++) { int j = i*length; int sec = (isJouleGPS_GPSPLUS ? bcd2Int(response.payload.at(j)) : qByteArray2Int(response.payload.mid(j,1)) ); int min = (isJouleGPS_GPSPLUS ? bcd2Int(response.payload.at(j+1)) : qByteArray2Int(response.payload.mid(j+1,1)) ); int hour = (isJouleGPS_GPSPLUS ? bcd2Int(response.payload.at(j+2)) : qByteArray2Int(response.payload.mid(j+2,1)) ); int day = (isJouleGPS_GPSPLUS ? bcd2Int(response.payload.at(j+3)) : qByteArray2Int(response.payload.mid(j+3,1)) ); int month = (isJouleGPS_GPSPLUS ? bcd2Int(response.payload.at(j+4)) : qByteArray2Int(response.payload.mid(j+4,1)) ); int year = (isJouleGPS_GPSPLUS ? bcd2Int(response.payload.at(j+5)) : qByteArray2Int(response.payload.mid(j+5,1)) ); QDateTime date = QDateTime(QDate(year+2000,month-1,day), QTime(hour,min,sec)); int total = qByteArray2Int(response.payload.mid(j+length-2,2)); if (total > 0) { DeviceStoredRideItem ride; ride.id = i; ride.startTime = date; rides.append(ride); } } emit updateStatus(QString(tr("%1 detailed activities")).arg(rides.count())); return true; } return false; }
bool MacroDevice::download( const QDir &tmpdir, QList<DeviceDownloadFile> &files, QString &err) { if (MACRO_DEBUG) printf("download O-Synce Macro"); if (!dev->open(err)) { err = tr("ERROR: open failed: ") + err; return false; } emit updateStatus(tr("Request number of training...")); if (MACRO_DEBUG) printf("Request number of training\n"); MacroPacket cmd(NUMBER_OF_TRAINING_REQUESTS); cmd.addToPayload(UNKNOWN); if (!cmd.write(dev, err)) return false; if(m_Cancelled) { err = tr("download cancelled"); return false; } MacroPacket response = MacroPacket(); response.read(dev, 2, err); if (response.payload.size() == 0) { err = tr("no data"); return false; } char count = response.payload.at(0); if (count == 0) { err = tr("no data"); return false; } response.read(dev, 7*count, err); if (!response.verifyCheckSum(dev, err)) { err = tr("data error"); return false; } if(m_Cancelled) { err = tr("download cancelled"); return false; } // create temporary file QString tmpl = tmpdir.absoluteFilePath(".macrodl.XXXXXX"); QTemporaryFile tmp(tmpl); tmp.setAutoRemove(false); if (!tmp.open()) { err = tr("Failed to create temporary file ") + tmpl + ": " + tmp.error(); return false; } if (MACRO_DEBUG) printf("Acknowledge"); cmd= MacroPacket(ACKNOWLEDGE); cmd.addToPayload(response.command); if (!cmd.write(dev, err)) return false; // timestamp from the first training struct tm start; start.tm_sec = bcd2Int(response.payload.at(2)); start.tm_min = bcd2Int(response.payload.at(3)); start.tm_hour = bcd2Int(response.payload.at(4)); start.tm_mday = bcd2Int(response.payload.at(5)); start.tm_mon = hex2Int(response.payload.at(6)) -1; start.tm_year = bcd2Int(response.payload.at(7)) -100; start.tm_isdst = -1; DeviceDownloadFile file; file.extension = "osyn"; file.name = tmp.fileName(); file.startTime.setTime_t( mktime( &start )); files.append(file); QTextStream os(&tmp); os << hex; for (int i = 0; i < count; i++) { if (MACRO_DEBUG) printf("Request training %d\n",i); emit updateStatus( QString(tr("Request datas of training %1 / %2...")) .arg(i+1).arg((int)count) ); if(m_Cancelled) { err = tr("download cancelled"); return false; } cmd = MacroPacket(TRAINING_DETAIL_REQUEST); cmd.addToPayload(i); if (!cmd.write(dev, err)) return false; if(m_Cancelled) { err = tr("download cancelled"); return false; } bool lastpage = false; while (!lastpage) { MacroPacket response2 = MacroPacket(); response2.read(dev, 259, err); if (!response2.verifyCheckSum(dev, err)) { err = tr("data error"); return false; } if (hexHex2Int(response2.payload.at(0), response2.payload.at(1)) == LAST_PAGE) lastpage = true; //int training_flag = hex2Int(response2.payload.at(43)); tmp.write(response2.dataArray()); emit updateProgress( QString(tr("training %1/%2... (%3 Bytes)")) .arg(i+1) .arg((int)count) .arg(tmp.size()) ); if(m_Cancelled) { err = tr("download cancelled"); return false; } if (MACRO_DEBUG) printf("Acknowledge\n"); cmd= MacroPacket(ACKNOWLEDGE); cmd.addToPayload(response2.command); if (!cmd.write(dev, err)) return false; } } tmp.close(); dev->close(); // QTemporaryFile initially has permissions set to 0600. // Make it readable by everyone. tmp.setPermissions(tmp.permissions() | QFile::ReadOwner | QFile::ReadUser | QFile::ReadGroup | QFile::ReadOther); return true; }
bool JouleDevice::download( const QDir &tmpdir, QList<DeviceDownloadFile> &files, QString &err) { if (JOULE_DEBUG) printf("download Joule 1.0, GPS or GPS+"); if (!dev->open(err)) { err = tr("ERROR: open failed: ") + err; return false; } dev->setBaudRate(57600, err); JoulePacket versionResponse; JoulePacket systemResponse; if (!getUnitVersion(versionResponse, err)) { return false; } if (!getSystemInfo(systemResponse, err)) { return false; } bool isJouleGPS = getJouleType(versionResponse) == JOULE_GPS; bool isJouleGPSPLUS = getJouleType(versionResponse) == JOULE_GPS_PLUS; emit updateStatus(QString(tr("Joule %1 identified")).arg(isJouleGPS?"GPS":(isJouleGPSPLUS?"GPS+":"1.0"))); bool isJouleGPS_GPSPLUS = isJouleGPS || isJouleGPSPLUS; QList<DeviceStoredRideItem> trainings; if (!getDownloadableRides(trainings, isJouleGPS_GPSPLUS, err)) return false; for (int i=0; i<trainings.count(); i++) { emit updateProgress(QString(tr("Read detail for activity %1/%2")).arg(i+1).arg(trainings.count())); JoulePacket request(READ_RIDE_DETAIL); int id1 = (trainings.at(i).id>255?trainings.at(i).id-255:trainings.at(i).id); int id2 = (trainings.at(i).id>255?trainings.at(i).id%255:0); request.addToPayload((char)id1); request.addToPayload((char)id2); request.addToPayload((uint16_t)0xFFFF); // Total Ride# request.addToPayload((uint16_t)0x0000); // Start Page# if (!request.write(dev, err)) return false; if(m_Cancelled) { err = tr("download cancelled"); return false; } JoulePacket response = JoulePacket(PAGE_RIDE_DETAIL); if (response.read(dev, err)) { if (response.payload.size() < 4096) { err = tr("no data"); return false; } int page = qByteArray2Int(response.payload.left(2)); int data_version = qByteArray2Int(response.payload.mid(2,1)); int firmware = qByteArray2Int(response.payload.mid(3,1)); QString data = QString("%1 %2-%3").arg(page).arg(data_version).arg(firmware); qDebug() << data; if (page < 65535) { // create temporary file QString tmpl = tmpdir.absoluteFilePath(".joule.XXXXXX"); // temp file QTemporaryFile tmp(tmpl); tmp.setAutoRemove(false); if (!tmp.open()) { err = tr("Failed to create temporary file ") + tmpl + ": " + tmp.error(); return false; } // timestamp from the first training struct tm start; start.tm_sec = (isJouleGPS_GPSPLUS ? bcd2Int(response.payload.at(4)) : qByteArray2Int(response.payload.mid(4,1)) ); start.tm_min = (isJouleGPS_GPSPLUS ? bcd2Int(response.payload.at(5)) : qByteArray2Int(response.payload.mid(5,1)) ); start.tm_hour = (isJouleGPS_GPSPLUS ? bcd2Int(response.payload.at(6)) : qByteArray2Int(response.payload.mid(6,1)) ); start.tm_mday = (isJouleGPS_GPSPLUS ? bcd2Int(response.payload.at(7)) : qByteArray2Int(response.payload.mid(7,1)) ); start.tm_mon = (isJouleGPS_GPSPLUS ? bcd2Int(response.payload.at(8))-1 : qByteArray2Int(response.payload.mid(8,1))-1 ); start.tm_year = (isJouleGPS_GPSPLUS ? bcd2Int(response.payload.at(9))+100 : qByteArray2Int(response.payload.mid(9,1))+100 ); start.tm_isdst = -1; DeviceDownloadFile file; file.extension = "bin2"; file.name = tmp.fileName(); file.startTime.setTime_t( mktime( &start )); files.append(file); QTextStream os(&tmp); os << hex; qDebug() << tmp.fileName() << "-" << tmpl; tmp.write(versionResponse.dataArray()); tmp.write(systemResponse.dataArray()); tmp.write(response.dataArray()); int _try = 1; while (page < 65535) { if (JOULE_DEBUG) printf("page %d\n", page); request = JoulePacket(PAGE_RIDE_DETAIL); request.addToPayload(response.payload.left(2).data(),2); if (!request.write(dev, err)) return false; response = JoulePacket(PAGE_RIDE_DETAIL); bool success = false; while (!success) { if (response.read(dev, err)) { page = qByteArray2Int(response.payload.left(2)); tmp.write(response.dataArray()); success = true; } else { if (_try == 3) return false; else { JoulePacket request(READ_RIDE_DETAIL); //request.addToPayload((uint16_t)0x0200); // Ride# request.addToPayload((char)i); request.addToPayload((char)0x00); request.addToPayload((uint16_t)0xFFFF); // Total Ride# request.addToPayload((uint16_t)page); // Start Page# if (!request.write(dev, err)) return false; response = JoulePacket(PAGE_RIDE_DETAIL); _try ++; } } } } tmp.close(); } if (JOULE_DEBUG) printf("Acknowledge\n"); request = JoulePacket(PAGE_RIDE_DETAIL); request.addToPayload(response.payload.left(2).data(),2); if (!request.write(dev, err)) return false; } else i=99; } dev->close(); return true; }