diff --git a/ground/openpilotgcs/src/plugins/powerlog/PowerLog.pluginspec b/ground/openpilotgcs/src/plugins/powerlog/PowerLog.pluginspec
new file mode 100644
index 000000000..fab57c77a
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/powerlog/PowerLog.pluginspec
@@ -0,0 +1,11 @@
+
+ The OpenPilot Project
+ (C) 2010 OpenPilot
+ The GNU Public License (GPL) Version 3
+ A plugin that downloads the log from a Junsi PowerLog6S to a file
+ http://www.openpilot.org
+
+
+
+
+
diff --git a/ground/openpilotgcs/src/plugins/powerlog/powerlog.pro b/ground/openpilotgcs/src/plugins/powerlog/powerlog.pro
new file mode 100644
index 000000000..e521ad17c
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/powerlog/powerlog.pro
@@ -0,0 +1,11 @@
+TEMPLATE = lib
+TARGET = PowerLog
+DEFINES += POWERLOG_LIBRARY
+include(../../openpilotgcsplugin.pri)
+include(powerlog_dependencies.pri)
+HEADERS += powerlogplugin.h
+
+SOURCES += powerlogplugin.cpp
+
+OTHER_FILES += PowerLog.pluginspec
+
diff --git a/ground/openpilotgcs/src/plugins/powerlog/powerlog_dependencies.pri b/ground/openpilotgcs/src/plugins/powerlog/powerlog_dependencies.pri
new file mode 100644
index 000000000..7418c99b1
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/powerlog/powerlog_dependencies.pri
@@ -0,0 +1,2 @@
+include(../../plugins/coreplugin/coreplugin.pri)
+include(../../plugins/rawhid/rawhid.pri)
diff --git a/ground/openpilotgcs/src/plugins/powerlog/powerlogplugin.cpp b/ground/openpilotgcs/src/plugins/powerlog/powerlogplugin.cpp
new file mode 100644
index 000000000..e0124789e
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/powerlog/powerlogplugin.cpp
@@ -0,0 +1,374 @@
+/**
+ ******************************************************************************
+ *
+ * @file powerlogplugin.cpp
+ * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
+ * @see The GNU Public License (GPL) Version 3
+ * @brief Junsi Powerlog utility Plugin
+ * @addtogroup GCSPlugins GCS Plugins
+ * @{
+ * @addtogroup PowerLog
+ * @{
+ *
+ *****************************************************************************/
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "powerlogplugin.h"
+#include "rawhid/usbmonitor.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+
+
+/**
+ * Sets the file to use for logging and takes the parent plugin
+ * to connect to stop logging signal
+ * @param[in] file File name to write to
+ * @param[in] parent plugin
+ */
+bool PowerlogThread::openFile(QString file, PowerlogPlugin * parent)
+{
+ logFile.setFileName(file);
+ logFile.open(QIODevice::WriteOnly);
+ fileStream.setDevice(&logFile);
+
+ connect(parent,SIGNAL(stopLoggingSignal()),this,SLOT(stopLogging()));
+
+ return true;
+};
+
+/**
+ * Get all logs from Powerlog
+ */
+void PowerlogThread::run()
+{
+
+
+ // TODO: pop up a dialog here!
+
+ qDebug() << "Connect a Junsi PowerLog 6S and watch the logging output";
+ pjrc_rawhid hidHandle;
+ int numDevices = hidHandle.open(1, 0x0483,0x5750,0,0); //0xff9c,0x0001);
+ if( numDevices == 0 )
+ numDevices = hidHandle.open(1,0x0483,0,0,0);
+
+ qDebug() << numDevices << " device(s) opened";
+ if (numDevices == 0)
+ return;
+
+ //hidHandle.mytest(0);
+
+ char buf[BUF_LEN];
+ buf[0] = 2;
+ buf[1] = 0;
+
+ fileStream << "Interval,Current,Volt,Cap,Cell1,Cell2,Cell3,Cell4,Cell5,Cell6,RPM,Temp0,Temp1,Temp2,Temp3,Period,Pulse\n";
+
+ while (int received = hidHandle.receive(0, buf, BUF_LEN, 3500) ) {
+ ShowInf(buf);
+ fileStream.flush(); // Just to be sure...
+ }
+
+ stopLogging();
+
+}
+
+/**
+ * Pass this command to the correct thread then close the file
+ */
+void PowerlogThread::stopLogging()
+{
+ QWriteLocker locker(&lock);
+ fileStream.flush();
+ logFile.close();
+ quit();
+}
+
+/**
+ * Formats the content of the buffer we just read and write
+ * to the logfile
+ */
+void PowerlogThread::ShowInf(char *pBuf)
+{
+ POWERLOG_HID_PACK Inf;
+ int i;
+ int Count;
+
+ Count=0;
+ Inf.Len = pBuf[Count];
+ Count += sizeof(Inf.Len);
+
+ Inf.Type = pBuf[Count];
+ Count += sizeof(Inf.Type);
+
+ Inf.Interval = *((DWORD *)&pBuf[Count]);
+ fileStream << QString::number(Inf.Interval) << ",";
+
+ Count += sizeof(Inf.Interval);
+
+ Inf.LogState = pBuf[Count];
+ Count += sizeof(Inf.LogState);
+
+ if(((Inf.Type == TYPE_DATA_ONLINE)||(Inf.Type == TYPE_DATA_OFFLINE)) && (Inf.Len == 0x29))//0x27
+ {
+ Inf.Current = *((SHORT *)&pBuf[Count]);
+ Count += sizeof(Inf.Current);
+ GetShowValue(QString("Current"),Inf.Current,5,2);
+
+ Inf.Volt = *((USHORT *)&pBuf[Count]);
+ Count += sizeof(Inf.Volt);
+ GetShowValue(QString("Voltage"),Inf.Volt,5,2);
+
+ Inf.Cap = *((DWORD *)&pBuf[Count]);
+ Count += sizeof(Inf.Cap);
+ GetShowValue(QString("Cap"),Inf.Cap,6,0);
+
+ for(i=0;i<6;i++)
+ {
+ Inf.Cell[i] = *((SHORT *)&pBuf[Count]);
+ Count += sizeof(Inf.Cell[i]);
+ }
+ GetShowValue(QString("Cell 1"),Inf.Cell[0],5,3);
+ GetShowValue(QString("Cell 2"),Inf.Cell[1],5,3);
+ GetShowValue(QString("Cell 3"),Inf.Cell[2],5,3);
+ GetShowValue(QString("Cell 4"),Inf.Cell[3],5,3);
+ GetShowValue(QString("Cell 5"),Inf.Cell[4],5,3);
+ GetShowValue(QString("Cell 6"),Inf.Cell[5],5,3);
+
+ Inf.RPM = *((USHORT *)&pBuf[Count]);
+ Count += sizeof(Inf.RPM);
+ GetShowValue(QString("RPM"),Inf.RPM,6,0);
+
+ for(i=0;i<4;i++)
+ {
+ Inf.Temp[i] = *((SHORT *)&pBuf[Count]);
+ Count += sizeof(Inf.Temp[i]);
+
+ }
+ GetShowValue(QString("Int Temp0"),Inf.Temp[0],4,1);
+
+ if (Inf.Temp[1]==0x7fff)
+ fileStream << "0.0,";
+ else
+ GetShowValue(QString("Ext temp1"),Inf.Temp[1],4,1);
+
+ if (Inf.Temp[2]==0x7fff)
+ fileStream << "0.0,";
+ else
+ GetShowValue(QString("Ext temp2"),Inf.Temp[2],4,1);
+
+ if (Inf.Temp[3]==0x7fff)
+ fileStream << "0.0,";
+ else
+ GetShowValue(QString("Ext temp3"),Inf.Temp[3],4,1);
+
+ Inf.Period = *((USHORT *)&pBuf[Count]);
+ Count += sizeof(Inf.Period);
+ GetShowValue(QString("Period:"),Inf.Period,6,0);
+
+ Inf.Pulse = *((USHORT *)&pBuf[Count]);
+ Count += sizeof(Inf.Pulse);
+ GetShowValue(QString("Pulse:"),Inf.Pulse,6,0);
+
+ fileStream << "\n";
+ }
+}
+
+/**
+ * Formats a numeric value
+ */
+void PowerlogThread::GetShowValue(QString label, DWORD Value, WORD Len, WORD Dot)
+{
+ QString out;
+
+ if (Value < 0) {
+ fileStream << "-";
+ Value = -Value;
+ }
+
+ if(Dot==1)
+ fileStream << Value/10 << "." << Value%10; // printf("%ld.%01lu",Value/10,Value%10);
+ else if(Dot==2)
+ fileStream << Value/100 << "." << Value%100; // printf("%ld.%02lu",Value/100,Value%100);
+ else if(Dot==3)
+ fileStream << Value/1000 << "." << Value%1000; // printf("%ld.%03lu",Value/1000,Value%1000);
+ else if(Dot==4)
+ fileStream << Value/10000 << "." << Value%10000; // printf("%ld.%04lu",Value/10000,Value%10000);
+ else
+ fileStream << Value; // printf("%ld",Value);
+
+ fileStream << out << ",";
+
+}
+
+
+
+/****************************************************************
+ Logging plugin
+ ********************************/
+
+
+PowerlogPlugin::PowerlogPlugin() :
+ devSerialNumber(""),
+ logging(false),
+ loggingThread(NULL)
+{
+
+}
+
+PowerlogPlugin::~PowerlogPlugin()
+{
+
+}
+
+/**
+ * Add Powerlog plugin entry to File menu
+ */
+bool PowerlogPlugin::initialize(const QStringList& args, QString *errMsg)
+{
+ Q_UNUSED(args);
+ Q_UNUSED(errMsg);
+
+
+ // Add Menu entry
+ Core::ActionManager* am = Core::ICore::instance()->actionManager();
+ Core::ActionContainer* ac = am->actionContainer(Core::Constants::M_TOOLS);
+
+ // Command to start logging
+ cmd = am->registerAction(new QAction(this),
+ "PowerlogPlugin.Transfer",
+ QList() <<
+ Core::Constants::C_GLOBAL_ID);
+ cmd->action()->setText("Receive from PowerLog6S...");
+
+ ac->menu()->addSeparator();
+ ac->appendGroup("Utilities");
+ ac->addAction(cmd, "Utilities");
+
+ connect(cmd->action(), SIGNAL(triggered(bool)), this, SLOT(receiveLog()));
+
+ // At this stage we know that other plugins we depend upon are
+ // initialized, in prticular the USB Monitor is now running:
+ USBMonitor *mon = USBMonitor::instance();
+ connect(mon,SIGNAL(deviceDiscovered(USBPortInfo)), this, SLOT(devConnected(USBPortInfo)));
+ connect(mon,SIGNAL(deviceRemoved(USBPortInfo)), this, SLOT(devRemoved(USBPortInfo)));
+
+ return true;
+}
+
+/**
+ * The action that is triggered by the menu item which opens the
+ * file and begins log reception if successful
+ */
+void PowerlogPlugin::receiveLog()
+{
+ if (logging) {
+ loggingThread->stopLogging();
+ logging = false;
+ cmd->action()->setText("Receive from PowerLog6S...");
+ } else {
+ QString fileName = QFileDialog::getSaveFileName(NULL, tr("Log filename"),
+ tr("PowerLog-%0.csv").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd_hh-mm-ss")),
+ tr("Comma Separated Values (*.csv)"));
+ if (fileName.isEmpty())
+ return;
+
+ loggingThread = new PowerlogThread();
+ if (loggingThread->openFile(fileName,this)) {
+ loggingThread->start();
+ cmd->action()->setText("Stop PowerLog6S reception");
+ logging = true;
+ }
+ }
+
+}
+
+/**
+ Device connected, check whether it is a powerlog & act accordingly
+ */
+void PowerlogPlugin::devConnected(USBPortInfo port)
+{
+ if (devSerialNumber.length() > 0)
+ return;
+ if ((port.vendorID == 0x0483) && (port.productID==0x5750)) {
+ devSerialNumber = port.serialNumber;
+ cmd->action()->setEnabled(true);
+ }
+}
+
+
+/**
+ Device Removed, check whether it is a powerlog & act accordingly.
+ As when the device is removed, we don't get the info on the device,
+ we have to list all available remaining devices and check if the serial
+ number of our device is missing...
+ */
+void PowerlogPlugin::devRemoved(USBPortInfo port)
+{
+ bool foundDevice;
+ QList ports = USBMonitor::instance()->availableDevices();
+ foreach(USBPortInfo port, ports) {
+ if ((port.vendorID == 0x0483) && (port.productID==0x5750) &&
+ (devSerialNumber == port.serialNumber)) {
+ foundDevice = true;
+ break;
+ }
+ }
+ if (!foundDevice) {
+ devSerialNumber = QString("");
+ cmd->action()->setEnabled(false);
+ // Also stop logging in case we were logging:
+ if (loggingThread)
+ loggingThread->stopLogging();
+ }
+}
+
+
+void PowerlogPlugin::extensionsInitialized()
+{
+ cmd->action()->setEnabled(false);
+ QList ports = USBMonitor::instance()->availableDevices();
+ foreach(USBPortInfo port, ports) {
+ if ((port.vendorID == 0x0483) && (port.productID==0x5750)) {
+ devSerialNumber = port.serialNumber;
+ cmd->action()->setEnabled(true);
+ break;
+ }
+ }
+}
+
+void PowerlogPlugin::shutdown()
+{
+ // Do nothing
+}
+Q_EXPORT_PLUGIN(PowerlogPlugin)
+
+/**
+ * @}
+ * @}
+ */
diff --git a/ground/openpilotgcs/src/plugins/powerlog/powerlogplugin.h b/ground/openpilotgcs/src/plugins/powerlog/powerlogplugin.h
new file mode 100644
index 000000000..bcb971447
--- /dev/null
+++ b/ground/openpilotgcs/src/plugins/powerlog/powerlogplugin.h
@@ -0,0 +1,143 @@
+/**
+ ******************************************************************************
+ * @file powerlogplugin.h
+ * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
+ * @see The GNU Public License (GPL) Version 3
+ * @addtogroup GCSPlugins GCS Plugins
+ * @{
+ * @addtogroup powerlogplugin
+ * @{
+ *****************************************************************************/
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef POWERLOGPLUGIN_H_
+#define POWERLOGPLUGIN_H_
+
+#include
+#include
+#include
+#include
+#include
+#include "rawhid/usbmonitor.h"
+#include "rawhid/pjrc_rawhid.h"
+
+#include
+#include
+#include
+
+using namespace std;
+
+typedef unsigned long ULONG; // 4 Bytes
+typedef short SHORT;
+typedef unsigned short USHORT; // 2 Bytes
+typedef unsigned char BYTE; // 1 Byte
+typedef unsigned short WORD; // 2 Bytes
+typedef unsigned long DWORD; // 4 Bytes
+
+
+
+#define BUF_LEN 64
+struct POWERLOG_HID_PACK
+{
+ BYTE Len;
+ BYTE Type;
+ DWORD Interval;
+ BYTE LogState;
+ SHORT Current;
+ USHORT Volt;
+ DWORD Cap;
+ SHORT Cell[6];
+ USHORT RPM;
+ SHORT Temp[4];
+ USHORT Period;
+ USHORT Pulse;
+};
+
+enum
+{
+ TYPE_DATA_ONLINE = 0x10,
+ TYPE_DATA_OFFLINE = 0x11,
+ TYPE_ORDER = 0x20,
+};
+
+
+
+
+class PowerlogPlugin;
+
+class PowerlogThread : public QThread
+{
+ Q_OBJECT
+
+public:
+ bool openFile(QString file, PowerlogPlugin * parent);
+
+private slots:
+
+public slots:
+ void stopLogging();
+
+protected:
+ void run();
+ QReadWriteLock lock;
+ QFile logFile;
+ QTextStream fileStream;
+
+private:
+ void ShowInf(char *pBuf);
+ void GetShowValue(QString label,DWORD Value,WORD Len,WORD Dot);
+};
+
+
+class PowerlogPlugin : public ExtensionSystem::IPlugin
+{
+ Q_OBJECT
+
+
+public:
+ PowerlogPlugin();
+ ~PowerlogPlugin();
+
+ void extensionsInitialized();
+ bool initialize(const QStringList & arguments, QString * errorString);
+ void shutdown();
+
+ void setPowerlogMenuTitle(QString str);
+
+
+signals:
+ void stopLoggingSignal(void);
+
+protected:
+
+private slots:
+ void receiveLog();
+ void devConnected(USBPortInfo);
+ void devRemoved(USBPortInfo);
+
+private:
+ Core::Command* cmd;
+ QString devSerialNumber;
+ PowerlogThread* loggingThread;
+ bool logging;
+
+};
+#endif /* POWERLOGPLUGIN_H_ */
+/**
+ * @}
+ * @}
+ */