diff --git a/HISTORY.txt b/HISTORY.txt index 98193adce..0be2551ff 100644 --- a/HISTORY.txt +++ b/HISTORY.txt @@ -1,5 +1,12 @@ Short summary of changes. For a complete list see the git log. +2011-10-11 +Fix for the Mac telemetry rates and specifically how long enumeration took. + +2011-10-08 +Make the flash chip need to be have bad magic for a full second before erasing +settings. Should avoid random lost settings. + 2011-09-12 Max rate now ONLY applies to attitude and axis lock mode. Manual rate is the only term that limits the rate mode now (and in axis lock when you push stick @@ -56,3 +63,4 @@ selected from ManualControlSettings.InputMode and the aircraft must be rebooted after changing this. Also for CopterControl the HwSettings object must indicate which modules are connected to which ports. PPM currently not working. + diff --git a/flight/Bootloaders/AHRS/Makefile b/flight/Bootloaders/AHRS/Makefile index 18bf8a269..fe52f8ae0 100644 --- a/flight/Bootloaders/AHRS/Makefile +++ b/flight/Bootloaders/AHRS/Makefile @@ -354,7 +354,7 @@ $(eval $(call PARTIAL_COMPILE_ARM_TEMPLATE, SRCARM)) $(OUTDIR)/$(TARGET).bin.o: $(OUTDIR)/$(TARGET).bin # Add jtag targets (program and wipe) -$(eval $(call JTAG_TEMPLATE,$(OUTDIR)/$(TARGET).bin,$(BL_BANK_BASE),$(BL_BANK_SIZE))) +$(eval $(call JTAG_TEMPLATE,$(OUTDIR)/$(TARGET).bin,$(FW_BANK_BASE),$(FW_BANK_SIZE),$(OPENOCD_CONFIG))) .PHONY: elf lss sym hex bin bino elf: $(OUTDIR)/$(TARGET).elf diff --git a/flight/Bootloaders/CopterControl/Makefile b/flight/Bootloaders/CopterControl/Makefile index 99521020d..cc98fb777 100644 --- a/flight/Bootloaders/CopterControl/Makefile +++ b/flight/Bootloaders/CopterControl/Makefile @@ -413,7 +413,7 @@ $(eval $(call PARTIAL_COMPILE_ARM_TEMPLATE, SRCARM)) $(OUTDIR)/$(TARGET).bin.o: $(OUTDIR)/$(TARGET).bin # Add jtag targets (program and wipe) -$(eval $(call JTAG_TEMPLATE,$(OUTDIR)/$(TARGET).bin,$(BL_BANK_BASE),$(BL_BANK_SIZE))) +$(eval $(call JTAG_TEMPLATE,$(OUTDIR)/$(TARGET).bin,$(FW_BANK_BASE),$(FW_BANK_SIZE),$(OPENOCD_CONFIG))) .PHONY: elf lss sym hex bin bino elf: $(OUTDIR)/$(TARGET).elf diff --git a/flight/Bootloaders/OpenPilot/Makefile b/flight/Bootloaders/OpenPilot/Makefile index cad11dedf..d4a944c0d 100644 --- a/flight/Bootloaders/OpenPilot/Makefile +++ b/flight/Bootloaders/OpenPilot/Makefile @@ -419,7 +419,7 @@ $(eval $(call PARTIAL_COMPILE_ARM_TEMPLATE, SRCARM)) $(OUTDIR)/$(TARGET).bin.o: $(OUTDIR)/$(TARGET).bin # Add jtag targets (program and wipe) -$(eval $(call JTAG_TEMPLATE,$(OUTDIR)/$(TARGET).bin,$(BL_BANK_BASE),$(BL_BANK_SIZE))) +$(eval $(call JTAG_TEMPLATE,$(OUTDIR)/$(TARGET).bin,$(FW_BANK_BASE),$(FW_BANK_SIZE),$(OPENOCD_CONFIG))) .PHONY: elf lss sym hex bin bino elf: $(OUTDIR)/$(TARGET).elf diff --git a/flight/Bootloaders/PipXtreme/Makefile b/flight/Bootloaders/PipXtreme/Makefile index 19b651a5f..94d7206ed 100644 --- a/flight/Bootloaders/PipXtreme/Makefile +++ b/flight/Bootloaders/PipXtreme/Makefile @@ -414,7 +414,7 @@ $(eval $(call PARTIAL_COMPILE_ARM_TEMPLATE, SRCARM)) $(OUTDIR)/$(TARGET).bin.o: $(OUTDIR)/$(TARGET).bin # Add jtag targets (program and wipe) -$(eval $(call JTAG_TEMPLATE,$(OUTDIR)/$(TARGET).bin,$(BL_BANK_BASE),$(BL_BANK_SIZE))) +$(eval $(call JTAG_TEMPLATE,$(OUTDIR)/$(TARGET).bin,$(FW_BANK_BASE),$(FW_BANK_SIZE),$(OPENOCD_CONFIG))) .PHONY: elf lss sym hex bin bino elf: $(OUTDIR)/$(TARGET).elf diff --git a/flight/Modules/ManualControl/manualcontrol.c b/flight/Modules/ManualControl/manualcontrol.c index e8b18fefb..6186a6af9 100644 --- a/flight/Modules/ManualControl/manualcontrol.c +++ b/flight/Modules/ManualControl/manualcontrol.c @@ -456,7 +456,7 @@ static bool updateRcvrActivityCompare(uint32_t rcvr_id, struct rcvr_activity_fsm break; } - ReceiverActivityActiveGroupSet(&group); + ReceiverActivityActiveGroupSet((uint8_t*)&group); ReceiverActivityActiveChannelSet(&channel); activity_updated = true; } diff --git a/flight/Modules/System/systemmod.c b/flight/Modules/System/systemmod.c index 1cbd1d6e3..47c76816b 100644 --- a/flight/Modules/System/systemmod.c +++ b/flight/Modules/System/systemmod.c @@ -49,7 +49,6 @@ #include "hwsettings.h" #include "watchdogstatus.h" #include "taskmonitor.h" -#include "pios.h" // Private constants @@ -115,6 +114,7 @@ int32_t SystemModInitialize(void) // Must registers objects here for system thread because ObjectManager started in OpenPilotInit SystemSettingsInitialize(); SystemStatsInitialize(); + FlightStatusInitialize(); ObjectPersistenceInitialize(); #if defined(DIAGNOSTICS) TaskInfoInitialize(); diff --git a/flight/OpenPilot/System/inc/pios_config_posix.h b/flight/OpenPilot/System/inc/pios_config_posix.h index d65a87e59..1148a497c 100644 --- a/flight/OpenPilot/System/inc/pios_config_posix.h +++ b/flight/OpenPilot/System/inc/pios_config_posix.h @@ -64,6 +64,14 @@ /* Stabilization options */ #define PIOS_QUATERNION_STABILIZATION +/* Alarm Thresholds */ +#define HEAP_LIMIT_WARNING 4000 +#define HEAP_LIMIT_CRITICAL 1000 +#define IRQSTACK_LIMIT_WARNING 150 +#define IRQSTACK_LIMIT_CRITICAL 80 +#define CPULOAD_LIMIT_WARNING 80 +#define CPULOAD_LIMIT_CRITICAL 95 + /* GPS options */ #define PIOS_GPS_SETS_HOMELOCATION diff --git a/flight/OpenPilot/System/pios_board_posix.c b/flight/OpenPilot/System/pios_board_posix.c index dab971f85..679110ea5 100644 --- a/flight/OpenPilot/System/pios_board_posix.c +++ b/flight/OpenPilot/System/pios_board_posix.c @@ -34,11 +34,19 @@ #include "attitudeactual.h" #include "positionactual.h" #include "velocityactual.h" +#include "manualcontrolsettings.h" +#if defined(PIOS_INCLUDE_RCVR) #include "pios_rcvr_priv.h" -struct pios_rcvr_channel_map pios_rcvr_channel_to_id_map[PIOS_RCVR_MAX_CHANNELS]; -uint32_t pios_rcvr_max_channel; +/* One slot per selectable receiver group. + * eg. PWM, PPM, GCS, SPEKTRUM1, SPEKTRUM2, SBUS + * NOTE: No slot in this map for NONE. + */ +uint32_t pios_rcvr_group_map[MANUALCONTROLSETTINGS_CHANNELGROUPS_NONE]; + +#endif /* PIOS_INCLUDE_RCVR */ + void Stack_Change() { } diff --git a/flight/PiOS.posix/inc/pios_rcvr.h b/flight/PiOS.posix/inc/pios_rcvr.h index a32160894..ab493cd35 100644 --- a/flight/PiOS.posix/inc/pios_rcvr.h +++ b/flight/PiOS.posix/inc/pios_rcvr.h @@ -31,21 +31,24 @@ #ifndef PIOS_RCVR_H #define PIOS_RCVR_H -struct pios_rcvr_channel_map { - uint32_t id; - uint8_t channel; -}; - -extern struct pios_rcvr_channel_map pios_rcvr_channel_to_id_map[]; - struct pios_rcvr_driver { - void (*init)(uint32_t id); - int32_t (*read)(uint32_t id, uint8_t channel); + void (*init)(uint32_t id); + int32_t (*read)(uint32_t id, uint8_t channel); }; /* Public Functions */ extern int32_t PIOS_RCVR_Read(uint32_t rcvr_id, uint8_t channel); +/*! Define error codes for PIOS_RCVR_Get */ +enum PIOS_RCVR_errors { + /*! Indicates that a failsafe condition or missing receiver detected for that channel */ + PIOS_RCVR_TIMEOUT = 0, + /*! Channel is invalid for this driver (usually out of range supported) */ + PIOS_RCVR_INVALID = -1, + /*! Indicates that the driver for this channel has not been initialized */ + PIOS_RCVR_NODRIVER = -2 +}; + #endif /* PIOS_RCVR_H */ /** diff --git a/flight/PiOS.posix/posix/pios_rcvr.c b/flight/PiOS.posix/posix/pios_rcvr.c index 652730547..719cb9769 100644 --- a/flight/PiOS.posix/posix/pios_rcvr.c +++ b/flight/PiOS.posix/posix/pios_rcvr.c @@ -21,32 +21,39 @@ static bool PIOS_RCVR_validate(struct pios_rcvr_dev * rcvr_dev) } #if defined(PIOS_INCLUDE_FREERTOS) && 0 -static struct pios_rcvr_dev * PIOS_RCVR_alloc(void) -{ - struct pios_rcvr_dev * rcvr_dev; - - rcvr_dev = (struct pios_rcvr_dev *)malloc(sizeof(*rcvr_dev)); - if (!rcvr_dev) return (NULL); - - rcvr_dev->magic = PIOS_RCVR_DEV_MAGIC; - return(rcvr_dev); -} +//static struct pios_rcvr_dev * PIOS_RCVR_alloc(void) +//{ +// struct pios_rcvr_dev * rcvr_dev; +// +// rcvr_dev = (struct pios_rcvr_dev *)pvPortMalloc(sizeof(*rcvr_dev)); +// if (!rcvr_dev) return (NULL); +// +// rcvr_dev->magic = PIOS_RCVR_DEV_MAGIC; +// return(rcvr_dev); +//} #else static struct pios_rcvr_dev pios_rcvr_devs[PIOS_RCVR_MAX_DEVS]; static uint8_t pios_rcvr_num_devs; -static struct pios_rcvr_dev * PIOS_RCVR_alloc(void) +static uint32_t PIOS_RCVR_alloc(void) { struct pios_rcvr_dev * rcvr_dev; if (pios_rcvr_num_devs >= PIOS_RCVR_MAX_DEVS) { - return (NULL); + return (PIOS_RCVR_MAX_DEVS+1); } rcvr_dev = &pios_rcvr_devs[pios_rcvr_num_devs++]; rcvr_dev->magic = PIOS_RCVR_DEV_MAGIC; - return (rcvr_dev); + return (pios_rcvr_num_devs); } +static struct pios_rcvr_dev * PIOS_RCVR_find_dev(uint32_t rcvr_dev_id) +{ + if (!rcvr_dev_id) return NULL; + if (rcvr_dev_id>pios_rcvr_num_devs+1) return NULL; + return &pios_rcvr_devs[rcvr_dev_id-1]; +} + #endif /** @@ -56,35 +63,53 @@ static struct pios_rcvr_dev * PIOS_RCVR_alloc(void) * \param[in] id * \return < 0 if initialisation failed */ -int32_t PIOS_RCVR_Init(uint32_t * rcvr_id, const struct pios_rcvr_driver * driver, const uint32_t lower_id) +int32_t PIOS_RCVR_Init(uint32_t * rcvr_id, const struct pios_rcvr_driver * driver, uint32_t lower_id) { PIOS_DEBUG_Assert(rcvr_id); PIOS_DEBUG_Assert(driver); + uint32_t rcvr_dev_id; struct pios_rcvr_dev * rcvr_dev; - rcvr_dev = (struct pios_rcvr_dev *) PIOS_RCVR_alloc(); + rcvr_dev_id = PIOS_RCVR_alloc(); + rcvr_dev = PIOS_RCVR_find_dev(rcvr_dev_id); if (!rcvr_dev) goto out_fail; rcvr_dev->driver = driver; rcvr_dev->lower_id = lower_id; - - *rcvr_id = pios_rcvr_num_devs - 1; - + *rcvr_id = rcvr_dev_id; return(0); out_fail: return(-1); } +/** + * @brief Reads an input channel from the appropriate driver + * @param[in] rcvr_id driver to read from + * @param[in] channel channel to read + * @returns Unitless input value + * @retval PIOS_RCVR_TIMEOUT indicates a failsafe or timeout from that channel + * @retval PIOS_RCVR_INVALID invalid channel for this driver (usually out of range supported) + * @retval PIOS_RCVR_NODRIVER driver was not initialized + */ int32_t PIOS_RCVR_Read(uint32_t rcvr_id, uint8_t channel) { - struct pios_rcvr_dev * rcvr_dev = &pios_rcvr_devs[rcvr_id]; + // Publicly facing API uses channel 1 for first channel + if(channel == 0) + return PIOS_RCVR_INVALID; + else + channel--; + + if (rcvr_id == 0) + return PIOS_RCVR_NODRIVER; + + struct pios_rcvr_dev * rcvr_dev = PIOS_RCVR_find_dev(rcvr_id); if (!PIOS_RCVR_validate(rcvr_dev)) { /* Undefined RCVR port for this board (see pios_board.c) */ - PIOS_DEBUG_Assert(0); + PIOS_Assert(0); } PIOS_DEBUG_Assert(rcvr_dev->driver->read); diff --git a/flight/PiOS.posix/posix/pios_udp.c b/flight/PiOS.posix/posix/pios_udp.c index f7f91f620..5ccbae767 100644 --- a/flight/PiOS.posix/posix/pios_udp.c +++ b/flight/PiOS.posix/posix/pios_udp.c @@ -194,7 +194,7 @@ static void PIOS_UDP_TxStart(uint32_t udp_id, uint16_t tx_bytes_avail) length = (udp_dev->tx_out_cb)(udp_dev->tx_out_context, udp_dev->tx_buffer, PIOS_UDP_RX_BUFFER_SIZE, NULL, &tx_need_yield); rem = length; while (rem>0) { - len = sendto(udp_dev->socket, udp_dev->tx_buffer, length, 0, + len = sendto(udp_dev->socket, udp_dev->tx_buffer+length-rem, rem, 0, (struct sockaddr *) &udp_dev->client, sizeof(udp_dev->client)); if (len<=0) { diff --git a/flight/PiOS/Common/pios_flashfs_objlist.c b/flight/PiOS/Common/pios_flashfs_objlist.c index 2b2fe06fa..b252ef81e 100644 --- a/flight/PiOS/Common/pios_flashfs_objlist.c +++ b/flight/PiOS/Common/pios_flashfs_objlist.c @@ -61,7 +61,7 @@ struct fileHeader { #define OBJECT_TABLE_START 0x00000010 #define OBJECT_TABLE_END 0x00001000 #define SECTOR_SIZE 0x00001000 -#define MAX_BADMAGIC 4 +#define MAX_BADMAGIC 1000 /** * @brief Initialize the flash object setting FS @@ -72,7 +72,7 @@ int32_t PIOS_FLASHFS_Init() // Check for valid object table or create one uint32_t object_table_magic; - uint8_t magic_fail_count = 0; + uint32_t magic_fail_count = 0; bool magic_good = false; while(!magic_good) { @@ -85,7 +85,7 @@ int32_t PIOS_FLASHFS_Init() magic_fail_count = 0; magic_good = true; } else { - PIOS_DELAY_WaituS(100); + PIOS_DELAY_WaituS(1000); } } diff --git a/ground/openpilotgcs/src/plugins/config/Config.pluginspec b/ground/openpilotgcs/src/plugins/config/Config.pluginspec index 0a9da6e94..83013fd28 100644 --- a/ground/openpilotgcs/src/plugins/config/Config.pluginspec +++ b/ground/openpilotgcs/src/plugins/config/Config.pluginspec @@ -9,5 +9,6 @@ + diff --git a/ground/openpilotgcs/src/plugins/config/config.pro b/ground/openpilotgcs/src/plugins/config/config.pro index 29d872ec9..b99fc9edc 100644 --- a/ground/openpilotgcs/src/plugins/config/config.pro +++ b/ground/openpilotgcs/src/plugins/config/config.pro @@ -8,7 +8,7 @@ include(../../plugins/uavtalk/uavtalk.pri) include(../../plugins/coreplugin/coreplugin.pri) include(../../plugins/uavobjects/uavobjects.pri) include(../../plugins/uavobjectutil/uavobjectutil.pri) - +include(../../plugins/uavsettingsimportexport/uavsettingsimportexport.pri) INCLUDEPATH += ../../libs/eigen OTHER_FILES += Config.pluginspec diff --git a/ground/openpilotgcs/src/plugins/config/configairframewidget.cpp b/ground/openpilotgcs/src/plugins/config/configairframewidget.cpp index a12d34dca..96393b381 100644 --- a/ground/openpilotgcs/src/plugins/config/configairframewidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configairframewidget.cpp @@ -36,6 +36,10 @@ #include #include #include +#include "systemsettings.h" +#include "mixersettings.h" +#include "actuatorsettings.h" +#include /** Helper delegate for the custom mixer editor table. @@ -443,6 +447,8 @@ void ConfigAirframeWidget::updateCustomThrottle2CurveValue(QList list, d */ void ConfigAirframeWidget::refreshWidgetsValues() { + if(!allObjectsUpdated()) + return; bool dirty=isDirty(); // Get the Airframe type from the system settings: UAVDataObject* obj = dynamic_cast(getObjectManager()->getObject(QString("SystemSettings"))); @@ -1516,6 +1522,16 @@ bool ConfigAirframeWidget::setupFrameVtail() */ bool ConfigAirframeWidget::setupMixer(double mixerFactors[8][3]) { + qDebug()<<"Mixer factors"; + qDebug()< mmList; mmList << m_aircraft->multiMotor1 << m_aircraft->multiMotor2 << m_aircraft->multiMotor3 @@ -1533,11 +1549,15 @@ bool ConfigAirframeWidget::setupMixer(double mixerFactors[8][3]) double pFactor = (double)m_aircraft->mrPitchMixLevel->value()/100; double rFactor = (double)m_aircraft->mrRollMixLevel->value()/100; double yFactor = (double)m_aircraft->mrYawMixLevel->value()/100; + qDebug()<currentIndex()-1; - if (channel > -1) - setupQuadMotor(channel, mixerFactors[i][0]*pFactor, - rFactor*mixerFactors[i][1], yFactor*mixerFactors[i][2]); + if(mmList.at(i)->isEnabled()) + { + int channel = mmList.at(i)->currentIndex()-1; + if (channel > -1) + setupQuadMotor(channel, mixerFactors[i][0]*pFactor, + rFactor*mixerFactors[i][1], yFactor*mixerFactors[i][2]); + } } // obj->updated(); return true; @@ -1549,6 +1569,7 @@ bool ConfigAirframeWidget::setupMixer(double mixerFactors[8][3]) */ void ConfigAirframeWidget::setupQuadMotor(int channel, double pitch, double roll, double yaw) { + qDebug()<(getObjectManager()->getObject(QString("MixerSettings"))); Q_ASSERT(obj); UAVObjectField *field = obj->getField(mixerTypes.at(channel)); @@ -1560,10 +1581,13 @@ void ConfigAirframeWidget::setupQuadMotor(int channel, double pitch, double roll field->setValue(127, ti); ti = field->getElementNames().indexOf("Roll"); field->setValue(roll*127,ti); + qDebug()<<"Set roll="<getElementNames().indexOf("Pitch"); field->setValue(pitch*127,ti); + qDebug()<<"Set pitch="<getElementNames().indexOf("Yaw"); field->setValue(yaw*127,ti); + qDebug()<<"Set yaw="<setData(attitudeSettingsData); } else { @@ -134,7 +134,6 @@ void ConfigCCAttitudeWidget::startAccelCalibration() { // Disable gyro bias correction to see raw data AttitudeSettings::DataFields attitudeSettingsData = AttitudeSettings::GetInstance(getObjectManager())->getData(); - initialBiasCorrected = attitudeSettingsData.BiasCorrectGyro; attitudeSettingsData.BiasCorrectGyro = AttitudeSettings::BIASCORRECTGYRO_FALSE; AttitudeSettings::GetInstance(getObjectManager())->setData(attitudeSettingsData); diff --git a/ground/openpilotgcs/src/plugins/config/configccattitudewidget.h b/ground/openpilotgcs/src/plugins/config/configccattitudewidget.h index 09dfdb222..af107f670 100644 --- a/ground/openpilotgcs/src/plugins/config/configccattitudewidget.h +++ b/ground/openpilotgcs/src/plugins/config/configccattitudewidget.h @@ -57,7 +57,6 @@ private: Ui_ccattitude *ui; QTimer timer; UAVObject::Metadata initialMdata; - quint8 initialBiasCorrected; int updates; diff --git a/ground/openpilotgcs/src/plugins/config/configtaskwidget.cpp b/ground/openpilotgcs/src/plugins/config/configtaskwidget.cpp index 98b10683c..c7a082507 100644 --- a/ground/openpilotgcs/src/plugins/config/configtaskwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configtaskwidget.cpp @@ -26,14 +26,17 @@ */ #include "configtaskwidget.h" #include - +#include "uavsettingsimportexport/uavsettingsimportexportfactory.h" +#include "configgadgetwidget.h" ConfigTaskWidget::ConfigTaskWidget(QWidget *parent) : QWidget(parent),isConnected(false),smartsave(NULL),dirty(false) { pm = ExtensionSystem::PluginManager::instance(); objManager = pm->getObject(); - connect(parent, SIGNAL(autopilotConnected()),this, SLOT(onAutopilotConnect())); - connect(parent, SIGNAL(autopilotDisconnected()),this, SLOT(onAutopilotDisconnect())); + connect((ConfigGadgetWidget*)parent, SIGNAL(autopilotConnected()),this, SLOT(onAutopilotConnect())); + connect((ConfigGadgetWidget*)parent, SIGNAL(autopilotDisconnected()),this, SLOT(onAutopilotDisconnect())); + UAVSettingsImportExportFactory * importexportplugin = pm->getObject(); + connect(importexportplugin,SIGNAL(importAboutToBegin()),this,SLOT(invalidateObjects())); } void ConfigTaskWidget::addWidget(QWidget * widget) { @@ -62,6 +65,8 @@ void ConfigTaskWidget::addUAVObjectToWidgetRelation(QString object, QString fiel { obj = objManager->getObject(QString(object)); Q_ASSERT(obj); + objectUpdates.insert(obj,true); + connect(obj, SIGNAL(objectUpdated(UAVObject*)),this, SLOT(objectUpdated(UAVObject*))); connect(obj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(refreshWidgetsValues())); } //smartsave->addObject(obj); @@ -123,6 +128,7 @@ ConfigTaskWidget::~ConfigTaskWidget() void ConfigTaskWidget::saveObjectToSD(UAVObject *obj) { + qDebug()<<"ConfigTaskWidget::saveObjectToSD"; // saveObjectToSD is now handled by the UAVUtils plugin in one // central place (and one central queue) ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); @@ -153,10 +159,12 @@ void ConfigTaskWidget::onAutopilotDisconnect() { isConnected=false; enableControls(false); + invalidateObjects(); } void ConfigTaskWidget::onAutopilotConnect() { + invalidateObjects(); dirty=false; isConnected=true; enableControls(true); @@ -189,6 +197,10 @@ void ConfigTaskWidget::populateWidgets() { cb->setValue(ow->field->getValue(ow->index).toInt()/ow->scale); } + else if(QCheckBox * cb=qobject_cast(ow->widget)) + { + cb->setChecked(ow->field->getValue(ow->index).toBool()); + } } setDirty(dirtyBack); } @@ -218,6 +230,10 @@ void ConfigTaskWidget::refreshWidgetsValues() { cb->setValue(ow->field->getValue(ow->index).toInt()/ow->scale); } + else if(QCheckBox * cb=qobject_cast(ow->widget)) + { + cb->setChecked(ow->field->getValue(ow->index).toBool()); + } } setDirty(dirtyBack); } @@ -246,6 +262,10 @@ void ConfigTaskWidget::updateObjectsFromWidgets() { ow->field->setValue(cb->value()* ow->scale,ow->index); } + else if(QCheckBox * cb=qobject_cast(ow->widget)) + { + ow->field->setValue((cb->isChecked()?"TRUE":"FALSE"),ow->index); + } } } @@ -308,6 +328,30 @@ void ConfigTaskWidget::enableObjUpdates() } } +void ConfigTaskWidget::objectUpdated(UAVObject *obj) +{ + objectUpdates[obj]=true; +} + +bool ConfigTaskWidget::allObjectsUpdated() +{ + bool ret=true; + foreach(UAVObject *obj, objectUpdates.keys()) + { + ret=ret & objectUpdates[obj]; + } + qDebug()<<"ALL OBJECTS UPDATE:"< objectUpdates; bool dirty; protected slots: virtual void disableObjUpdates(); diff --git a/ground/openpilotgcs/src/plugins/config/images/camera.png b/ground/openpilotgcs/src/plugins/config/images/camera.png index 50ee47904..b412c28d6 100644 Binary files a/ground/openpilotgcs/src/plugins/config/images/camera.png and b/ground/openpilotgcs/src/plugins/config/images/camera.png differ diff --git a/ground/openpilotgcs/src/plugins/config/smartsavebutton.cpp b/ground/openpilotgcs/src/plugins/config/smartsavebutton.cpp index c74f22691..69ddb9cb2 100644 --- a/ground/openpilotgcs/src/plugins/config/smartsavebutton.cpp +++ b/ground/openpilotgcs/src/plugins/config/smartsavebutton.cpp @@ -49,7 +49,7 @@ void smartSaveButton::processClick() } if(up_result==false) { - //qDebug()<<"Object upload error:"<getName(); + qDebug()<<"Object upload error:"<getName(); error=true; continue; } @@ -59,7 +59,7 @@ void smartSaveButton::processClick() { for(int i=0;i<3;++i) { - //qDebug()<<"try to save:"<getName(); + qDebug()<<"try to save:"<getName(); connect(utilMngr,SIGNAL(saveCompleted(int,bool)),this,SLOT(saving_finished(int,bool))); connect(&timer,SIGNAL(timeout()),&loop,SLOT(quit())); utilMngr->saveObjectToSD(obj); @@ -73,6 +73,7 @@ void smartSaveButton::processClick() } if(sv_result==false) { + qDebug()<<"failed to save:"<getName(); error=true; } } diff --git a/ground/openpilotgcs/src/plugins/debuggadget/DebugGadget.pluginspec b/ground/openpilotgcs/src/plugins/debuggadget/DebugGadget.pluginspec new file mode 100644 index 000000000..05cea6931 --- /dev/null +++ b/ground/openpilotgcs/src/plugins/debuggadget/DebugGadget.pluginspec @@ -0,0 +1,10 @@ + + The OpenPilot Project + (C) 2010 OpenPilot Project + The GNU Public License (GPL) Version 3 + An debug gadget + http://www.openpilot.org + + + + diff --git a/ground/openpilotgcs/src/plugins/debuggadget/debug.ui b/ground/openpilotgcs/src/plugins/debuggadget/debug.ui new file mode 100644 index 000000000..72adcb7ee --- /dev/null +++ b/ground/openpilotgcs/src/plugins/debuggadget/debug.ui @@ -0,0 +1,31 @@ + + + Form + + + + 0 + 0 + 400 + 300 + + + + Form + + + + + + Save to file + + + + + + + + + + + diff --git a/ground/openpilotgcs/src/plugins/debuggadget/debugengine.cpp b/ground/openpilotgcs/src/plugins/debuggadget/debugengine.cpp new file mode 100644 index 000000000..48ec18525 --- /dev/null +++ b/ground/openpilotgcs/src/plugins/debuggadget/debugengine.cpp @@ -0,0 +1,13 @@ +#include "debugengine.h" +debugengine::debugengine() +{ +} + +void debugengine::writeToStdErr(const QString &level, const QList &msgs) +{ + emit dbgMsgError(level,msgs); +} +void debugengine::writeToStdOut(const QString &level, const QList &msgs) +{ + emit dbgMsg(level,msgs); +} diff --git a/ground/openpilotgcs/src/plugins/debuggadget/debugengine.h b/ground/openpilotgcs/src/plugins/debuggadget/debugengine.h new file mode 100644 index 000000000..5452f7590 --- /dev/null +++ b/ground/openpilotgcs/src/plugins/debuggadget/debugengine.h @@ -0,0 +1,18 @@ +#ifndef DEBUGENGINE_H +#define DEBUGENGINE_H +#include "qxtbasicstdloggerengine.h" +#include +class debugengine:public QObject,public QxtBasicSTDLoggerEngine +{ + Q_OBJECT +public: + debugengine(); +protected: + void writeToStdErr ( const QString & level, const QList & msgs ); + void writeToStdOut ( const QString & level, const QList & msgs ); +signals: + void dbgMsgError( const QString & level, const QList & msgs ); + void dbgMsg( const QString & level, const QList & msgs ); +}; + +#endif // DEBUGENGINE_H diff --git a/ground/openpilotgcs/src/plugins/debuggadget/debuggadget.cpp b/ground/openpilotgcs/src/plugins/debuggadget/debuggadget.cpp new file mode 100644 index 000000000..05c147c03 --- /dev/null +++ b/ground/openpilotgcs/src/plugins/debuggadget/debuggadget.cpp @@ -0,0 +1,39 @@ +/** + ****************************************************************************** + * + * @file debuggadget.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @addtogroup GCSPlugins GCS Plugins + * @{ + * @addtogroup DebugGadgetPlugin Debug Gadget Plugin + * @{ + * @brief A place holder gadget plugin + *****************************************************************************/ +/* + * 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 "debuggadget.h" +#include "debuggadgetwidget.h" + +DebugGadget::DebugGadget(QString classId, DebugGadgetWidget *widget, QWidget *parent) : + IUAVGadget(classId, parent), + m_widget(widget) +{ +} + +DebugGadget::~DebugGadget() +{ + delete m_widget; +} diff --git a/ground/openpilotgcs/src/plugins/debuggadget/debuggadget.h b/ground/openpilotgcs/src/plugins/debuggadget/debuggadget.h new file mode 100644 index 000000000..b39f8b5b5 --- /dev/null +++ b/ground/openpilotgcs/src/plugins/debuggadget/debuggadget.h @@ -0,0 +1,59 @@ +/** + ****************************************************************************** + * + * @file debuggadget.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @addtogroup GCSPlugins GCS Plugins + * @{ + * @addtogroup DebugGadgetPlugin Debug Gadget Plugin + * @{ + * @brief A place holder gadget plugin + *****************************************************************************/ +/* + * 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 DEBUGGADGET_H_ +#define DEBUGGADGET_H_ + +#include + +namespace Core { +class IUAVGadget; +} +//class QWidget; +//class QString; +class DebugGadgetWidget; + +using namespace Core; + +class DebugGadget : public Core::IUAVGadget +{ + Q_OBJECT +public: + DebugGadget(QString classId, DebugGadgetWidget *widget, QWidget *parent = 0); + ~DebugGadget(); + + QList context() const { return m_context; } + QWidget *widget() { return m_widget; } + QString contextHelpId() const { return QString(); } + +private: + QWidget *m_widget; + QList m_context; +}; + + +#endif // DEBUGGADGET_H_ diff --git a/ground/openpilotgcs/src/plugins/debuggadget/debuggadget.pro b/ground/openpilotgcs/src/plugins/debuggadget/debuggadget.pro new file mode 100644 index 000000000..8434e723d --- /dev/null +++ b/ground/openpilotgcs/src/plugins/debuggadget/debuggadget.pro @@ -0,0 +1,21 @@ +TEMPLATE = lib +TARGET = DebugGadget + +include(../../openpilotgcsplugin.pri) +include(../../plugins/coreplugin/coreplugin.pri) +include(../../libs/libqxt/core/logengines.pri) +HEADERS += debugplugin.h \ + debugengine.h +HEADERS += debuggadget.h +HEADERS += debuggadgetwidget.h +HEADERS += debuggadgetfactory.h +SOURCES += debugplugin.cpp \ + debugengine.cpp +SOURCES += debuggadget.cpp +SOURCES += debuggadgetfactory.cpp +SOURCES += debuggadgetwidget.cpp + +OTHER_FILES += DebugGadget.pluginspec + +FORMS += \ + debug.ui diff --git a/ground/openpilotgcs/src/plugins/debuggadget/debuggadgetfactory.cpp b/ground/openpilotgcs/src/plugins/debuggadget/debuggadgetfactory.cpp new file mode 100644 index 000000000..f7d925b39 --- /dev/null +++ b/ground/openpilotgcs/src/plugins/debuggadget/debuggadgetfactory.cpp @@ -0,0 +1,47 @@ +/** + ****************************************************************************** + * + * @file debuggadgetfactory.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @addtogroup GCSPlugins GCS Plugins + * @{ + * @addtogroup DebugGadgetPlugin Debug Gadget Plugin + * @{ + * @brief A place holder gadget plugin + *****************************************************************************/ +/* + * 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 "debuggadgetfactory.h" +#include "debuggadgetwidget.h" +#include "debuggadget.h" +#include + +DebugGadgetFactory::DebugGadgetFactory(QObject *parent) : + IUAVGadgetFactory(QString("DebugGadget"), + tr("DebugGadget"), + parent) +{ +} + +DebugGadgetFactory::~DebugGadgetFactory() +{ + +} + +IUAVGadget* DebugGadgetFactory::createGadget(QWidget *parent) { + DebugGadgetWidget* gadgetWidget = new DebugGadgetWidget(parent); + return new DebugGadget(QString("DebugGadget"), gadgetWidget, parent); +} diff --git a/ground/openpilotgcs/src/plugins/debuggadget/debuggadgetfactory.h b/ground/openpilotgcs/src/plugins/debuggadget/debuggadgetfactory.h new file mode 100644 index 000000000..186fca5f6 --- /dev/null +++ b/ground/openpilotgcs/src/plugins/debuggadget/debuggadgetfactory.h @@ -0,0 +1,50 @@ +/** + ****************************************************************************** + * + * @file debuggadgetfactory.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @addtogroup GCSPlugins GCS Plugins + * @{ + * @addtogroup DebugGadgetPlugin Debug Gadget Plugin + * @{ + * @brief A place holder gadget plugin + *****************************************************************************/ +/* + * 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 DEBUGGADGETFACTORY_H_ +#define DEBUGGADGETFACTORY_H_ + +#include + +namespace Core { +class IUAVGadget; +class IUAVGadgetFactory; +} + +using namespace Core; + +class DebugGadgetFactory : public IUAVGadgetFactory +{ + Q_OBJECT +public: + DebugGadgetFactory(QObject *parent = 0); + ~DebugGadgetFactory(); + + IUAVGadget *createGadget(QWidget *parent); +}; + +#endif // DEBUGGADGETFACTORY_H_ diff --git a/ground/openpilotgcs/src/plugins/debuggadget/debuggadgetwidget.cpp b/ground/openpilotgcs/src/plugins/debuggadget/debuggadgetwidget.cpp new file mode 100644 index 000000000..34043c806 --- /dev/null +++ b/ground/openpilotgcs/src/plugins/debuggadget/debuggadgetwidget.cpp @@ -0,0 +1,96 @@ +/** + ****************************************************************************** + * + * @file debuggadgetwidget.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @addtogroup GCSPlugins GCS Plugins + * @{ + * @addtogroup DebugGadgetPlugin Debug Gadget Plugin + * @{ + * @brief A place holder gadget plugin + *****************************************************************************/ +/* + * 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 "debuggadgetwidget.h" + +#include +#include +#include +#include +#include +#include +#include "qxtlogger.h" +#include "debugengine.h" +#include +#include +#include +#include +#include +DebugGadgetWidget::DebugGadgetWidget(QWidget *parent) : QLabel(parent) +{ + m_config = new Ui_Form(); + m_config->setupUi(this); + debugengine * de=new debugengine(); + QxtLogger::getInstance()->addLoggerEngine("debugplugin", de); + connect(de,SIGNAL(dbgMsg(QString,QList)),this,SLOT(dbgMsg(QString,QList))); + connect(de,SIGNAL(dbgMsgError(QString,QList)),this,SLOT(dbgMsgError(QString,QList))); + connect(m_config->pushButton,SIGNAL(clicked()),this,SLOT(saveLog())); +} + +DebugGadgetWidget::~DebugGadgetWidget() +{ + // Do nothing +} + +void DebugGadgetWidget::dbgMsg(const QString &level, const QList &msgs) +{ + m_config->plainTextEdit->setTextColor(Qt::red); + + m_config->plainTextEdit->append(QString("%2[%0]%1").arg(level).arg(msgs[0].toString()).arg(QTime::currentTime().toString())); + + QScrollBar *sb = m_config->plainTextEdit->verticalScrollBar(); + sb->setValue(sb->maximum()); +} + +void DebugGadgetWidget::dbgMsgError(const QString &level, const QList &msgs) +{ + m_config->plainTextEdit->setTextColor(Qt::black); + + + m_config->plainTextEdit->append(QString("%2[%0]%1").arg(level).arg(msgs[0].toString()).arg(QTime::currentTime().toString())); + + QScrollBar *sb = m_config->plainTextEdit->verticalScrollBar(); + sb->setValue(sb->maximum()); +} +void DebugGadgetWidget::saveLog() +{ + QString fileName = QFileDialog::getSaveFileName(0, tr("Save log File As"), ""); + if (fileName.isEmpty()) { + return; + } + + QFile file(fileName); + if (file.open(QIODevice::WriteOnly) && + (file.write(m_config->plainTextEdit->toHtml().toAscii()) != -1)) { + file.close(); + } else { + QMessageBox::critical(0, + tr("Log Save"), + tr("Unable to save log: ") + fileName, + QMessageBox::Ok); + return; + } +} diff --git a/ground/openpilotgcs/src/plugins/debuggadget/debuggadgetwidget.h b/ground/openpilotgcs/src/plugins/debuggadget/debuggadgetwidget.h new file mode 100644 index 000000000..ed71f73c2 --- /dev/null +++ b/ground/openpilotgcs/src/plugins/debuggadget/debuggadgetwidget.h @@ -0,0 +1,49 @@ +/** + ****************************************************************************** + * + * @file debuggadgetwidget.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @addtogroup GCSPlugins GCS Plugins + * @{ + * @addtogroup DebugGadgetPlugin Debug Gadget Plugin + * @{ + * @brief A place holder gadget plugin + *****************************************************************************/ +/* + * 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 DEBUGGADGETWIDGET_H_ +#define DEBUGGADGETWIDGET_H_ + +#include +#include "ui_debug.h" +class DebugGadgetWidget : public QLabel +{ + Q_OBJECT + +public: + DebugGadgetWidget(QWidget *parent = 0); + ~DebugGadgetWidget(); + +private: + Ui_Form *m_config; +private slots: + void saveLog(); + void dbgMsgError( const QString & level, const QList & msgs ); + void dbgMsg( const QString & level, const QList & msgs ); +}; + +#endif /* DEBUGGADGETWIDGET_H_ */ diff --git a/ground/openpilotgcs/src/plugins/debuggadget/debugplugin.cpp b/ground/openpilotgcs/src/plugins/debuggadget/debugplugin.cpp new file mode 100644 index 000000000..f83395ef7 --- /dev/null +++ b/ground/openpilotgcs/src/plugins/debuggadget/debugplugin.cpp @@ -0,0 +1,65 @@ +/** + ****************************************************************************** + * + * @file debugplugin.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @addtogroup GCSPlugins GCS Plugins + * @{ + * @addtogroup DebugGadgetPlugin Debug Gadget Plugin + * @{ + * @brief A place holder gadget plugin + *****************************************************************************/ +/* + * 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 "debugplugin.h" +#include "debuggadgetfactory.h" +#include +#include +#include +#include + + +DebugPlugin::DebugPlugin() +{ + // Do nothing +} + +DebugPlugin::~DebugPlugin() +{ + // Do nothing +} + +bool DebugPlugin::initialize(const QStringList& args, QString *errMsg) +{ + Q_UNUSED(args); + Q_UNUSED(errMsg); + mf = new DebugGadgetFactory(this); + addAutoReleasedObject(mf); + + return true; +} + +void DebugPlugin::extensionsInitialized() +{ + // Do nothing +} + +void DebugPlugin::shutdown() +{ + // Do nothing +} +Q_EXPORT_PLUGIN(DebugPlugin) + diff --git a/ground/openpilotgcs/src/plugins/debuggadget/debugplugin.h b/ground/openpilotgcs/src/plugins/debuggadget/debugplugin.h new file mode 100644 index 000000000..9cdbefd02 --- /dev/null +++ b/ground/openpilotgcs/src/plugins/debuggadget/debugplugin.h @@ -0,0 +1,47 @@ +/** + ****************************************************************************** + * + * @file debugplugin.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @addtogroup GCSPlugins GCS Plugins + * @{ + * @addtogroup DebugGadgetPlugin Debug Gadget Plugin + * @{ + * @brief A place holder gadget plugin + *****************************************************************************/ +/* + * 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 DEBUGPLUGIN_H_ +#define DEBUGPLUGIN_H_ + +#include + +class DebugGadgetFactory; + +class DebugPlugin : public ExtensionSystem::IPlugin +{ +public: + DebugPlugin(); + ~DebugPlugin(); + + void extensionsInitialized(); + bool initialize(const QStringList & arguments, QString * errorString); + void shutdown(); +private: + DebugGadgetFactory *mf; +}; +#endif /* DEBUGPLUGIN_H_ */ diff --git a/ground/openpilotgcs/src/plugins/plugins.pro b/ground/openpilotgcs/src/plugins/plugins.pro index 7a86f53be..8079fa880 100644 --- a/ground/openpilotgcs/src/plugins/plugins.pro +++ b/ground/openpilotgcs/src/plugins/plugins.pro @@ -19,6 +19,12 @@ plugin_emptygadget.subdir = emptygadget plugin_emptygadget.depends = plugin_coreplugin SUBDIRS += plugin_emptygadget +# UAV Settings Import/Export plugin +plugin_debuggadget.subdir = debuggadget +#plugin_debughelper.depends = plugin_coreplugin +#plugin_debughelper.depends += plugin_uavobjects +SUBDIRS += plugin_debuggadget + # Welcome plugin plugin_welcome.subdir = welcome plugin_welcome.depends = plugin_coreplugin @@ -107,6 +113,7 @@ SUBDIRS += plugin_systemhealth plugin_config.subdir = config plugin_config.depends = plugin_coreplugin plugin_config.depends += plugin_uavobjects +plugin_config.depends += plugin_uavsettingsimportexport SUBDIRS += plugin_config #GPS Display gadget diff --git a/ground/openpilotgcs/src/plugins/rawhid/pjrc_rawhid.h b/ground/openpilotgcs/src/plugins/rawhid/pjrc_rawhid.h index b8e2459a2..3ff096db5 100644 --- a/ground/openpilotgcs/src/plugins/rawhid/pjrc_rawhid.h +++ b/ground/openpilotgcs/src/plugins/rawhid/pjrc_rawhid.h @@ -37,7 +37,6 @@ #if defined( Q_OS_MAC) -// todo: #elif defined(Q_OS_UNIX) //#elif defined(Q_OS_LINUX) @@ -104,10 +103,12 @@ public: void mytest(int num); signals: void deviceUnplugged(int);//just to make pips changes compile -private: #if defined( Q_OS_MAC) - // todo: +#endif + +private: +#if defined( Q_OS_MAC) #elif defined(Q_OS_UNIX) //#elif defined(Q_OS_LINUX) diff --git a/ground/openpilotgcs/src/plugins/rawhid/pjrc_rawhid_mac.cpp b/ground/openpilotgcs/src/plugins/rawhid/pjrc_rawhid_mac.cpp index 34c78fa8f..382c43829 100644 --- a/ground/openpilotgcs/src/plugins/rawhid/pjrc_rawhid_mac.cpp +++ b/ground/openpilotgcs/src/plugins/rawhid/pjrc_rawhid_mac.cpp @@ -44,6 +44,18 @@ #include #include #include +#include +#include +#include + +class delay : public QThread +{ +public: + static void msleep(unsigned long msecs) + { + QThread::msleep(msecs); + } +}; #define BUFFER_SIZE 64 @@ -54,6 +66,8 @@ typedef struct hid_struct hid_t; typedef struct buffer_struct buffer_t; static hid_t *first_hid = NULL; static hid_t *last_hid = NULL; +// Make sure we use the correct runloop +CFRunLoopRef the_correct_runloop = NULL; struct hid_struct { IOHIDDeviceRef ref; int open; @@ -75,9 +89,10 @@ static void free_all_hid(void); static void hid_close(hid_t *); static void attach_callback(void *, IOReturn, void *, IOHIDDeviceRef); static void detach_callback(void *, IOReturn, void *hid_mgr, IOHIDDeviceRef dev); -static void timeout_callback(CFRunLoopTimerRef, void *); static void input_callback(void *, IOReturn, void *, IOHIDReportType, uint32_t, uint8_t *, CFIndex); static void output_callback(hid_t *context, IOReturn ret, void *sender, IOHIDReportType type, uint32_t id, uint8_t *data, CFIndex len); +static void timeout_callback(CFRunLoopTimerRef, void *); + pjrc_rawhid::pjrc_rawhid() { @@ -164,6 +179,8 @@ int pjrc_rawhid::open(int max, int vid, int pid, int usage_page, int usage) CFRelease(hid_manager); return 0; } + // Set the run loop reference: + the_correct_runloop = CFRunLoopGetCurrent(); printf("run loop\n"); // let it do the callback for all devices while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true) == kCFRunLoopRunHandledSource) ; @@ -183,47 +200,56 @@ int pjrc_rawhid::open(int max, int vid, int pid, int usage_page, int usage) // int pjrc_rawhid::receive(int num, void *buf, int len, int timeout) { - hid_t *hid; - buffer_t *b; - CFRunLoopTimerRef timer=NULL; - CFRunLoopTimerContext context; - int ret=0, timeout_occurred=0; + hid_t *hid; + buffer_t *b; + CFRunLoopTimerRef timer=NULL; + CFRunLoopTimerContext context; + int ret=0, timeout_occurred=0; - if (len < 1) return 0; - hid = get_hid(num); - if (!hid || !hid->open) return -1; - if ((b = hid->first_buffer) != NULL) { - if (len > b->len) len = b->len; - memcpy(buf, b->buf, len); - hid->first_buffer = b->next; - free(b); - return len; - } - memset(&context, 0, sizeof(context)); - context.info = &timeout_occurred; - timer = CFRunLoopTimerCreate(NULL, CFAbsoluteTimeGetCurrent() + - (double)timeout / 1000.0, 0, 0, 0, timeout_callback, &context); - CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopDefaultMode); - while (1) { - CFRunLoopRun(); - if ((b = hid->first_buffer) != NULL) { - if (len > b->len) len = b->len; - memcpy(buf, b->buf, len); - hid->first_buffer = b->next; - free(b); - ret = len; + if (len < 1) return 0; + hid = get_hid(num); + if (!hid || !hid->open) return -1; + if ((b = hid->first_buffer) != NULL) { + if (len > b->len) len = b->len; + memcpy(buf, b->buf, len); + hid->first_buffer = b->next; + free(b); + return len; + } + memset(&context, 0, sizeof(context)); + context.info = &timeout_occurred; + timer = CFRunLoopTimerCreate(NULL, CFAbsoluteTimeGetCurrent() + + (double)timeout / 1000.0, 0, 0, 0, timeout_callback, &context); + CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopDefaultMode); + the_correct_runloop = CFRunLoopGetCurrent(); + //qDebug("--"); + while (1) { + //qDebug("."); + CFRunLoopRun(); // Found the problem: somehow the input_callback does not + // stop this CFRunLoopRun because it is hooked to a different run loop !!! + // Hence the use of the "correct_runloop" variable above. + //qDebug(" .."); + + if ((b = hid->first_buffer) != NULL) { + if (len > b->len) len = b->len; + memcpy(buf, b->buf, len); + hid->first_buffer = b->next; + free(b); + ret = len; + //qDebug("*************"); + break; + } + if (!hid->open) { + printf("pjrc_rawhid_recv, device not open\n"); + ret = -1; + break; + } + if (timeout_occurred) break; - } - if (!hid->open) { - printf("pjrc_rawhid_recv, device not open\n"); - ret = -1; - break; - } - if (timeout_occurred) break; - } - CFRunLoopTimerInvalidate(timer); - CFRelease(timer); - return ret; + } + CFRunLoopTimerInvalidate(timer); + CFRelease(timer); + return ret; } // send - send a packet @@ -335,10 +361,11 @@ static void input_callback(void *context, IOReturn ret, void *sender, IOHIDRepor buffer_t *n; hid_t *hid; - printf("input_callback, report id: %i buf: %x %x, len: %d\n", id, data[0], data[1], len); + //qDebug("input_callback, ret: %i - report id: %i buf: %x %x, len: %d\n", ret, id, data[0], data[1], len); if (ret != kIOReturnSuccess || len < 1) return; hid = (hid_t*)context; if (!hid || hid->ref != sender) return; + printf("Processing packet"); n = (buffer_t *)malloc(sizeof(buffer_t)); if (!n) return; if (len > BUFFER_SIZE) len = BUFFER_SIZE; @@ -352,14 +379,16 @@ static void input_callback(void *context, IOReturn ret, void *sender, IOHIDRepor hid->last_buffer->next = n; hid->last_buffer = n; } - CFRunLoopStop(CFRunLoopGetCurrent()); + //qDebug() << "Stop CFRunLoop from input_callback" << CFRunLoopGetCurrent(); + CFRunLoopStop(the_correct_runloop); } static void timeout_callback(CFRunLoopTimerRef timer, void *info) { - printf("timeout_callback\n"); - *(int *)info = 1; - CFRunLoopStop(CFRunLoopGetCurrent()); + //qDebug("timeout_callback\n"); + *(int *)info = 1; + //qDebug() << "Stop CFRunLoop from timeout_callback" << CFRunLoopGetCurrent(); + CFRunLoopStop(CFRunLoopGetCurrent()); } static void add_hid(hid_t *h) diff --git a/ground/openpilotgcs/src/plugins/rawhid/usbmonitor_mac.cpp b/ground/openpilotgcs/src/plugins/rawhid/usbmonitor_mac.cpp index e094a9a68..51fd6cce7 100644 --- a/ground/openpilotgcs/src/plugins/rawhid/usbmonitor_mac.cpp +++ b/ground/openpilotgcs/src/plugins/rawhid/usbmonitor_mac.cpp @@ -117,7 +117,7 @@ void USBMonitor::removeDevice(IOHIDDeviceRef dev) { */ void USBMonitor::detach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev) { - + qDebug() << "USBMonitor: Device detached event"; instance()->removeDevice(dev); } @@ -136,6 +136,8 @@ void USBMonitor::attach_callback(void *context, IOReturn r, void *hid_mgr, IOHID deviceInfo.dev_handle = dev; + qDebug() << "USBMonitor: Device attached event"; + // Populate the device info structure got_properties &= HID_GetIntProperty(dev, CFSTR( kIOHIDVendorIDKey ), &deviceInfo.vendorID); got_properties &= HID_GetIntProperty(dev, CFSTR( kIOHIDProductIDKey ), &deviceInfo.productID); @@ -149,6 +151,7 @@ void USBMonitor::attach_callback(void *context, IOReturn r, void *hid_mgr, IOHID // Currently only enumerating objects that have the complete list of properties if(got_properties) { + qDebug() << "USBMonitor: Adding device"; instance()->addDevice(deviceInfo); } } diff --git a/ground/openpilotgcs/src/plugins/uavsettingsimportexport/uavsettingsimportexport.cpp b/ground/openpilotgcs/src/plugins/uavsettingsimportexport/uavsettingsimportexport.cpp index 342b845e9..5418b455c 100644 --- a/ground/openpilotgcs/src/plugins/uavsettingsimportexport/uavsettingsimportexport.cpp +++ b/ground/openpilotgcs/src/plugins/uavsettingsimportexport/uavsettingsimportexport.cpp @@ -31,7 +31,7 @@ #include #include #include - +#include "importsummary.h" // for menu item #include #include @@ -62,321 +62,20 @@ UAVSettingsImportExportPlugin::~UAVSettingsImportExportPlugin() bool UAVSettingsImportExportPlugin::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_FILE); - Core::Command* cmd = am->registerAction(new QAction(this), - "UAVSettingsImportExportPlugin.UAVSettingsExport", - QList() << - Core::Constants::C_GLOBAL_ID); - cmd->setDefaultKeySequence(QKeySequence("Ctrl+E")); - cmd->action()->setText(tr("Export UAV Settings...")); - ac->addAction(cmd, Core::Constants::G_FILE_SAVE); - connect(cmd->action(), SIGNAL(triggered(bool)), this, SLOT(exportUAVSettings())); - - cmd = am->registerAction(new QAction(this), - "UAVSettingsImportExportPlugin.UAVSettingsImport", - QList() << - Core::Constants::C_GLOBAL_ID); - cmd->setDefaultKeySequence(QKeySequence("Ctrl+I")); - cmd->action()->setText(tr("Import UAV Settings...")); - ac->addAction(cmd, Core::Constants::G_FILE_SAVE); - connect(cmd->action(), SIGNAL(triggered(bool)), this, SLOT(importUAVSettings())); - - cmd = am->registerAction(new QAction(this), - "UAVSettingsImportExportPlugin.UAVDataExport", - QList() << - Core::Constants::C_GLOBAL_ID); - cmd->action()->setText(tr("Export UAV Data...")); - ac->addAction(cmd, Core::Constants::G_FILE_SAVE); - connect(cmd->action(), SIGNAL(triggered(bool)), this, SLOT(exportUAVData())); - + Q_UNUSED(args); + Q_UNUSED(errMsg); + mf = new UAVSettingsImportExportFactory(this); + addAutoReleasedObject(mf); return true; -} - -void UAVSettingsImportExportPlugin::extensionsInitialized() -{ - // Do nothing -} - - -// Slot called by the menu manager on user action -void UAVSettingsImportExportPlugin::importUAVSettings() -{ - // ask for file name - QString fileName; - QString filters = tr("UAVSettings XML files (*.uav);; XML files (*.xml)"); - fileName = QFileDialog::getOpenFileName(0, tr("Import UAV Settings"), "", filters); - if (fileName.isEmpty()) { - return; - } - - // Now open the file - QFile file(fileName); - QDomDocument doc("UAVSettings"); - file.open(QFile::ReadOnly|QFile::Text); - if (!doc.setContent(file.readAll())) { - QMessageBox msgBox; - msgBox.setText(tr("File Parsing Failed.")); - msgBox.setInformativeText(tr("This file is not a correct XML file")); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.exec(); - return; - } - file.close(); - - QDomElement root = doc.documentElement(); - if (root.tagName() != "settings") { - QMessageBox msgBox; - msgBox.setText(tr("Wrong file contents.")); - msgBox.setInformativeText(tr("This file is not a correct UAVSettings file")); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.exec(); - return; - } - - // We are now ok: setup the import summary dialog & update it as we - // go along. - ImportSummaryDialog swui; - - ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); - UAVObjectManager *objManager = pm->getObject(); - swui.show(); - - QDomNode node = root.firstChild(); - while (!node.isNull()) { - QDomElement e = node.toElement(); - if (e.tagName() == "object") { - // - Read each object - QString uavObjectName = e.attribute("name"); - uint uavObjectID = e.attribute("id").toUInt(NULL,16); - - // Sanity Check: - UAVObject* obj = objManager->getObject(uavObjectName); - if (obj == NULL) { - // This object is unknown! - qDebug() << "Object unknown:" << uavObjectName << uavObjectID; - swui.addLine(uavObjectName, "Error (Object unknown)", false); - - } else { - // - Update each field - // - Issue and "updated" command - bool error=false; - QDomNode field = node.firstChild(); - while(!field.isNull()) { - QDomElement f = field.toElement(); - if (f.tagName() == "field") { - UAVObjectField *uavfield = obj->getField(f.attribute("name")); - if (uavfield) { - QStringList list = f.attribute("values").split(","); - if (list.length() == 1) { - uavfield->setValue(f.attribute("values")); - } else { - // This is an enum: - int i=0; - QStringList list = f.attribute("values").split(","); - foreach (QString element, list) { - uavfield->setValue(element,i++); - } - } - error = false; - } else { - error = true; - } - } - field = field.nextSibling(); - } - obj->updated(); - if (error) { - swui.addLine(uavObjectName, "Warning (Object field unknown)", true); - } else if (uavObjectID != obj->getObjID()) { - qDebug() << "Mismatch for Object " << uavObjectName << uavObjectID << " - " << obj->getObjID(); - swui.addLine(uavObjectName, "Warning (ObjectID mismatch)", true); - } else - swui.addLine(uavObjectName, "OK", true); - } - } - node = node.nextSibling(); - } - swui.exec(); - - - -} - -// Create an XML document from UAVObject database -QString UAVSettingsImportExportPlugin::createXMLDocument( - const QString docName, const bool isSettings, const bool fullExport) -{ - // generate an XML first (used for all export formats as a formatted data source) - ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); - UAVObjectManager *objManager = pm->getObject(); - - QDomDocument doc(docName); - QDomElement root = doc.createElement(isSettings ? "settings" : "data"); - doc.appendChild(root); - QDomElement versionInfo =doc.createElement("versionInfo"); - root.appendChild(versionInfo); - QDomElement fw=doc.createElement("Embedded"); - UAVObjectUtilManager* utilMngr = pm->getObject(); - - fw.setAttribute("gitcommittag",utilMngr->getBoardDescriptionStruct().gitTag); - fw.setAttribute("fwtag",utilMngr->getBoardDescriptionStruct().description); - fw.setAttribute("cpuSerial",QString(utilMngr->getBoardCPUSerial().toHex())); - - versionInfo.appendChild(fw); - QDomElement gcs=doc.createElement("GCS"); - gcs.setAttribute("revision",QString::fromLatin1(Core::Constants::GCS_REVISION_STR)); - versionInfo.appendChild(gcs); - // iterate over settings objects - QList< QList > objList = objManager->getDataObjects(); - foreach (QList list, objList) { - foreach (UAVDataObject* obj, list) { - if (obj->isSettings() == isSettings) { - - // add each object to the XML - QDomElement o = doc.createElement("object"); - o.setAttribute("name", obj->getName()); - o.setAttribute("id", QString("0x")+ QString().setNum(obj->getObjID(),16).toUpper()); - if (fullExport) { - QDomElement d = doc.createElement("description"); - QDomText t = doc.createTextNode(obj->getDescription().remove("@Ref ", Qt::CaseInsensitive)); - d.appendChild(t); - o.appendChild(d); - } - - // iterate over fields - QList fieldList = obj->getFields(); - - foreach (UAVObjectField* field, fieldList) { - QDomElement f = doc.createElement("field"); - - // iterate over values - QString vals; - quint32 nelem = field->getNumElements(); - for (unsigned int n = 0; n < nelem; ++n) { - vals.append(QString("%1,").arg(field->getValue(n).toString())); - } - vals.chop(1); - - f.setAttribute("name", field->getName()); - f.setAttribute("values", vals); - if (fullExport) { - f.setAttribute("type", field->getTypeAsString()); - f.setAttribute("units", field->getUnits()); - f.setAttribute("elements", nelem); - if (field->getType() == UAVObjectField::ENUM) { - f.setAttribute("options", field->getOptions().join(",")); - } - } - o.appendChild(f); - } - root.appendChild(o); - } - } - } - - return doc.toString(4); -} - -// Slot called by the menu manager on user action -void UAVSettingsImportExportPlugin::exportUAVSettings() -{ - // ask for file name - QString fileName; - QString filters = tr("UAVSettings XML files (*.uav)"); - - fileName = QFileDialog::getSaveFileName(0, tr("Save UAV Settings File As"), "", filters); - if (fileName.isEmpty()) { - return; - } - - bool fullExport = false; - // If the filename ends with .xml, we will do a full export, otherwise, a simple export - if (fileName.endsWith(".xml")) { - fullExport = true; - } else if (!fileName.endsWith(".uav")) { - fileName.append(".uav"); - } - - // generate an XML first (used for all export formats as a formatted data source) - QString xml = createXMLDocument("UAVSettings", true, fullExport); - - // save file - QFile file(fileName); - if (file.open(QIODevice::WriteOnly) && - (file.write(xml.toAscii()) != -1)) { - file.close(); - } else { - QMessageBox::critical(0, - tr("UAV Settings Export"), - tr("Unable to save settings: ") + fileName, - QMessageBox::Ok); - return; - } - - QMessageBox msgBox; - msgBox.setText(tr("Settings saved.")); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.exec(); -} - -// Slot called by the menu manager on user action -void UAVSettingsImportExportPlugin::exportUAVData() -{ - if (QMessageBox::question(0, tr("Are you sure?"), - tr("This option is only useful for passing your current " - "system data to the technical support staff. " - "Do you really want to export?"), - QMessageBox::Ok | QMessageBox::Cancel, - QMessageBox::Ok) != QMessageBox::Ok) { - return; - } - - // ask for file name - QString fileName; - QString filters = tr("UAVData XML files (*.uav)"); - - fileName = QFileDialog::getSaveFileName(0, tr("Save UAV Data File As"), "", filters); - if (fileName.isEmpty()) { - return; - } - - bool fullExport = false; - // If the filename ends with .xml, we will do a full export, otherwise, a simple export - if (fileName.endsWith(".xml")) { - fullExport = true; - } else if (!fileName.endsWith(".uav")) { - fileName.append(".uav"); - } - - // generate an XML first (used for all export formats as a formatted data source) - QString xml = createXMLDocument("UAVData", false, fullExport); - - // save file - QFile file(fileName); - if (file.open(QIODevice::WriteOnly) && - (file.write(xml.toAscii()) != -1)) { - file.close(); - } else { - QMessageBox::critical(0, - tr("UAV Data Export"), - tr("Unable to save data: ") + fileName, - QMessageBox::Ok); - return; - } - - QMessageBox msgBox; - msgBox.setText(tr("Data saved.")); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.exec(); } void UAVSettingsImportExportPlugin::shutdown() { // Do nothing } +void UAVSettingsImportExportPlugin::extensionsInitialized() +{ +} Q_EXPORT_PLUGIN(UAVSettingsImportExportPlugin) + + diff --git a/ground/openpilotgcs/src/plugins/uavsettingsimportexport/uavsettingsimportexport.h b/ground/openpilotgcs/src/plugins/uavsettingsimportexport/uavsettingsimportexport.h index ff8972227..a63454153 100644 --- a/ground/openpilotgcs/src/plugins/uavsettingsimportexport/uavsettingsimportexport.h +++ b/ground/openpilotgcs/src/plugins/uavsettingsimportexport/uavsettingsimportexport.h @@ -29,9 +29,10 @@ #include #include "uavobjectutil/uavobjectutilmanager.h" -#include "importsummary.h" +#include "uavsettingsimportexport_global.h" #include "../../../../../build/ground/openpilotgcs/gcsversioninfo.h" -class UAVSettingsImportExportPlugin : public ExtensionSystem::IPlugin +#include "uavsettingsimportexportfactory.h" +class UAVSETTINGSIMPORTEXPORT_EXPORT UAVSettingsImportExportPlugin : public ExtensionSystem::IPlugin { Q_OBJECT @@ -42,16 +43,10 @@ public: void extensionsInitialized(); bool initialize(const QStringList & arguments, QString * errorString); void shutdown(); - private: - QString createXMLDocument(const QString docName, - const bool isSettings, - const bool fullExport); + UAVSettingsImportExportFactory *mf; + -private slots: - void importUAVSettings(); - void exportUAVSettings(); - void exportUAVData(); }; diff --git a/ground/openpilotgcs/src/plugins/uavsettingsimportexport/uavsettingsimportexport.pri b/ground/openpilotgcs/src/plugins/uavsettingsimportexport/uavsettingsimportexport.pri new file mode 100644 index 000000000..bddd38181 --- /dev/null +++ b/ground/openpilotgcs/src/plugins/uavsettingsimportexport/uavsettingsimportexport.pri @@ -0,0 +1,2 @@ +include(uavsettingsimportexport_dependencies.pri) +LIBS *= -l$$qtLibraryName(UAVSettingsImportExport) diff --git a/ground/openpilotgcs/src/plugins/uavsettingsimportexport/uavsettingsimportexport.pro b/ground/openpilotgcs/src/plugins/uavsettingsimportexport/uavsettingsimportexport.pro index fcdc11ae6..aa8abccf1 100644 --- a/ground/openpilotgcs/src/plugins/uavsettingsimportexport/uavsettingsimportexport.pro +++ b/ground/openpilotgcs/src/plugins/uavsettingsimportexport/uavsettingsimportexport.pro @@ -3,14 +3,16 @@ TEMPLATE = lib QT += xml TARGET = UAVSettingsImportExport - +DEFINES += UAVSETTINGSIMPORTEXPORT_LIBRARY include(../../openpilotgcsplugin.pri) include(uavsettingsimportexport_dependencies.pri) HEADERS += uavsettingsimportexport.h \ - importsummary.h + importsummary.h \ + uavsettingsimportexportfactory.h SOURCES += uavsettingsimportexport.cpp \ - importsummary.cpp + importsummary.cpp \ + uavsettingsimportexportfactory.cpp OTHER_FILES += uavsettingsimportexport.pluginspec diff --git a/ground/openpilotgcs/src/plugins/uavsettingsimportexport/uavsettingsimportexport_global.h b/ground/openpilotgcs/src/plugins/uavsettingsimportexport/uavsettingsimportexport_global.h new file mode 100644 index 000000000..703771b4f --- /dev/null +++ b/ground/openpilotgcs/src/plugins/uavsettingsimportexport/uavsettingsimportexport_global.h @@ -0,0 +1,40 @@ +/** + ****************************************************************************** + * + * @file uavsettingsimportexport_global.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 + * @{ + * @brief + *****************************************************************************/ +/* + * 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 UAVSETTINGSIMPORTEXPORT_GLOBAL_H +#define UAVSETTINGSIMPORTEXPORT_GLOBAL_H + +#include + +#if defined(UAVSETTINGSIMPORTEXPORT_LIBRARY) +# define UAVSETTINGSIMPORTEXPORT_EXPORT Q_DECL_EXPORT +#else +# define UAVSETTINGSIMPORTEXPORT_EXPORT Q_DECL_IMPORT +#endif + +#endif // UAVSETTINGSIMPORTEXPORT_GLOBAL_H diff --git a/ground/openpilotgcs/src/plugins/uavsettingsimportexport/uavsettingsimportexportfactory.cpp b/ground/openpilotgcs/src/plugins/uavsettingsimportexport/uavsettingsimportexportfactory.cpp new file mode 100644 index 000000000..ff6eb233b --- /dev/null +++ b/ground/openpilotgcs/src/plugins/uavsettingsimportexport/uavsettingsimportexportfactory.cpp @@ -0,0 +1,365 @@ +/** + ****************************************************************************** + * + * @file uavsettingsimportexportfactory.cpp + * @author (C) 2011 The OpenPilot Team, http://www.openpilot.org + * @addtogroup GCSPlugins GCS Plugins + * @{ + * @addtogroup UAVSettingsImportExport UAVSettings Import/Export Plugin + * @{ + * @brief UAVSettings Import/Export Plugin + *****************************************************************************/ +/* + * 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 "uavsettingsimportexportfactory.h" +#include +#include +#include +#include +#include "importsummary.h" +// for menu item +#include +#include +#include +#include + +// for UAVObjects +#include "uavdataobject.h" +#include "uavobjectmanager.h" +#include "extensionsystem/pluginmanager.h" + +// for XML object +#include + +// for file dialog and error messages +#include +#include + + + +UAVSettingsImportExportFactory::~UAVSettingsImportExportFactory() +{ + // Do nothing +} + +UAVSettingsImportExportFactory::UAVSettingsImportExportFactory(QObject * parent):QObject(parent) +{ + + // Add Menu entry + Core::ActionManager* am = Core::ICore::instance()->actionManager(); + Core::ActionContainer* ac = am->actionContainer(Core::Constants::M_FILE); + Core::Command* cmd = am->registerAction(new QAction(this), + "UAVSettingsImportExportPlugin.UAVSettingsExport", + QList() << + Core::Constants::C_GLOBAL_ID); + cmd->setDefaultKeySequence(QKeySequence("Ctrl+E")); + cmd->action()->setText(tr("Export UAV Settings...")); + ac->addAction(cmd, Core::Constants::G_FILE_SAVE); + connect(cmd->action(), SIGNAL(triggered(bool)), this, SLOT(exportUAVSettings())); + + cmd = am->registerAction(new QAction(this), + "UAVSettingsImportExportPlugin.UAVSettingsImport", + QList() << + Core::Constants::C_GLOBAL_ID); + cmd->setDefaultKeySequence(QKeySequence("Ctrl+I")); + cmd->action()->setText(tr("Import UAV Settings...")); + ac->addAction(cmd, Core::Constants::G_FILE_SAVE); + connect(cmd->action(), SIGNAL(triggered(bool)), this, SLOT(importUAVSettings())); + + cmd = am->registerAction(new QAction(this), + "UAVSettingsImportExportPlugin.UAVDataExport", + QList() << + Core::Constants::C_GLOBAL_ID); + cmd->action()->setText(tr("Export UAV Data...")); + ac->addAction(cmd, Core::Constants::G_FILE_SAVE); + connect(cmd->action(), SIGNAL(triggered(bool)), this, SLOT(exportUAVData())); + +} + +// Slot called by the menu manager on user action +void UAVSettingsImportExportFactory::importUAVSettings() +{ + // ask for file name + QString fileName; + QString filters = tr("UAVSettings XML files (*.uav);; XML files (*.xml)"); + fileName = QFileDialog::getOpenFileName(0, tr("Import UAV Settings"), "", filters); + if (fileName.isEmpty()) { + return; + } + + // Now open the file + QFile file(fileName); + QDomDocument doc("UAVSettings"); + file.open(QFile::ReadOnly|QFile::Text); + if (!doc.setContent(file.readAll())) { + QMessageBox msgBox; + msgBox.setText(tr("File Parsing Failed.")); + msgBox.setInformativeText(tr("This file is not a correct XML file")); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.exec(); + return; + } + file.close(); + emit importAboutToBegin(); + qDebug()<<"Import about to begin"; + QDomElement root = doc.documentElement(); + if (root.tagName() != "settings") { + QMessageBox msgBox; + msgBox.setText(tr("Wrong file contents.")); + msgBox.setInformativeText(tr("This file is not a correct UAVSettings file")); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.exec(); + return; + } + + // We are now ok: setup the import summary dialog & update it as we + // go along. + ImportSummaryDialog swui; + + ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); + UAVObjectManager *objManager = pm->getObject(); + swui.show(); + + QDomNode node = root.firstChild(); + while (!node.isNull()) { + QDomElement e = node.toElement(); + if (e.tagName() == "object") { + // - Read each object + QString uavObjectName = e.attribute("name"); + uint uavObjectID = e.attribute("id").toUInt(NULL,16); + + // Sanity Check: + UAVObject* obj = objManager->getObject(uavObjectName); + if (obj == NULL) { + // This object is unknown! + qDebug() << "Object unknown:" << uavObjectName << uavObjectID; + swui.addLine(uavObjectName, "Error (Object unknown)", false); + + } else { + // - Update each field + // - Issue and "updated" command + bool error=false; + QDomNode field = node.firstChild(); + while(!field.isNull()) { + QDomElement f = field.toElement(); + if (f.tagName() == "field") { + UAVObjectField *uavfield = obj->getField(f.attribute("name")); + if (uavfield) { + QStringList list = f.attribute("values").split(","); + if (list.length() == 1) { + uavfield->setValue(f.attribute("values")); + } else { + // This is an enum: + int i=0; + QStringList list = f.attribute("values").split(","); + foreach (QString element, list) { + uavfield->setValue(element,i++); + } + } + error = false; + } else { + error = true; + } + } + field = field.nextSibling(); + } + obj->updated(); + if (error) { + swui.addLine(uavObjectName, "Warning (Object field unknown)", true); + } else if (uavObjectID != obj->getObjID()) { + qDebug() << "Mismatch for Object " << uavObjectName << uavObjectID << " - " << obj->getObjID(); + swui.addLine(uavObjectName, "Warning (ObjectID mismatch)", true); + } else + swui.addLine(uavObjectName, "OK", true); + } + } + node = node.nextSibling(); + } + qDebug()<<"End import"; + swui.exec(); + + + +} + +// Create an XML document from UAVObject database +QString UAVSettingsImportExportFactory::createXMLDocument( + const QString docName, const bool isSettings, const bool fullExport) +{ + // generate an XML first (used for all export formats as a formatted data source) + ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); + UAVObjectManager *objManager = pm->getObject(); + + QDomDocument doc(docName); + QDomElement root = doc.createElement(isSettings ? "settings" : "data"); + doc.appendChild(root); + QDomElement versionInfo =doc.createElement("versionInfo"); + root.appendChild(versionInfo); + QDomElement fw=doc.createElement("Embedded"); + UAVObjectUtilManager* utilMngr = pm->getObject(); + + fw.setAttribute("gitcommittag",utilMngr->getBoardDescriptionStruct().gitTag); + fw.setAttribute("fwtag",utilMngr->getBoardDescriptionStruct().description); + fw.setAttribute("cpuSerial",QString(utilMngr->getBoardCPUSerial().toHex())); + + versionInfo.appendChild(fw); + QDomElement gcs=doc.createElement("GCS"); + gcs.setAttribute("revision",QString::fromLatin1(Core::Constants::GCS_REVISION_STR)); + versionInfo.appendChild(gcs); + // iterate over settings objects + QList< QList > objList = objManager->getDataObjects(); + foreach (QList list, objList) { + foreach (UAVDataObject* obj, list) { + if (obj->isSettings() == isSettings) { + + // add each object to the XML + QDomElement o = doc.createElement("object"); + o.setAttribute("name", obj->getName()); + o.setAttribute("id", QString("0x")+ QString().setNum(obj->getObjID(),16).toUpper()); + if (fullExport) { + QDomElement d = doc.createElement("description"); + QDomText t = doc.createTextNode(obj->getDescription().remove("@Ref ", Qt::CaseInsensitive)); + d.appendChild(t); + o.appendChild(d); + } + + // iterate over fields + QList fieldList = obj->getFields(); + + foreach (UAVObjectField* field, fieldList) { + QDomElement f = doc.createElement("field"); + + // iterate over values + QString vals; + quint32 nelem = field->getNumElements(); + for (unsigned int n = 0; n < nelem; ++n) { + vals.append(QString("%1,").arg(field->getValue(n).toString())); + } + vals.chop(1); + + f.setAttribute("name", field->getName()); + f.setAttribute("values", vals); + if (fullExport) { + f.setAttribute("type", field->getTypeAsString()); + f.setAttribute("units", field->getUnits()); + f.setAttribute("elements", nelem); + if (field->getType() == UAVObjectField::ENUM) { + f.setAttribute("options", field->getOptions().join(",")); + } + } + o.appendChild(f); + } + root.appendChild(o); + } + } + } + + return doc.toString(4); +} + +// Slot called by the menu manager on user action +void UAVSettingsImportExportFactory::exportUAVSettings() +{ + // ask for file name + QString fileName; + QString filters = tr("UAVSettings XML files (*.uav)"); + + fileName = QFileDialog::getSaveFileName(0, tr("Save UAV Settings File As"), "", filters); + if (fileName.isEmpty()) { + return; + } + + bool fullExport = false; + // If the filename ends with .xml, we will do a full export, otherwise, a simple export + if (fileName.endsWith(".xml")) { + fullExport = true; + } else if (!fileName.endsWith(".uav")) { + fileName.append(".uav"); + } + + // generate an XML first (used for all export formats as a formatted data source) + QString xml = createXMLDocument("UAVSettings", true, fullExport); + + // save file + QFile file(fileName); + if (file.open(QIODevice::WriteOnly) && + (file.write(xml.toAscii()) != -1)) { + file.close(); + } else { + QMessageBox::critical(0, + tr("UAV Settings Export"), + tr("Unable to save settings: ") + fileName, + QMessageBox::Ok); + return; + } + + QMessageBox msgBox; + msgBox.setText(tr("Settings saved.")); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.exec(); +} + +// Slot called by the menu manager on user action +void UAVSettingsImportExportFactory::exportUAVData() +{ + if (QMessageBox::question(0, tr("Are you sure?"), + tr("This option is only useful for passing your current " + "system data to the technical support staff. " + "Do you really want to export?"), + QMessageBox::Ok | QMessageBox::Cancel, + QMessageBox::Ok) != QMessageBox::Ok) { + return; + } + + // ask for file name + QString fileName; + QString filters = tr("UAVData XML files (*.uav)"); + + fileName = QFileDialog::getSaveFileName(0, tr("Save UAV Data File As"), "", filters); + if (fileName.isEmpty()) { + return; + } + + bool fullExport = false; + // If the filename ends with .xml, we will do a full export, otherwise, a simple export + if (fileName.endsWith(".xml")) { + fullExport = true; + } else if (!fileName.endsWith(".uav")) { + fileName.append(".uav"); + } + + // generate an XML first (used for all export formats as a formatted data source) + QString xml = createXMLDocument("UAVData", false, fullExport); + + // save file + QFile file(fileName); + if (file.open(QIODevice::WriteOnly) && + (file.write(xml.toAscii()) != -1)) { + file.close(); + } else { + QMessageBox::critical(0, + tr("UAV Data Export"), + tr("Unable to save data: ") + fileName, + QMessageBox::Ok); + return; + } + + QMessageBox msgBox; + msgBox.setText(tr("Data saved.")); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.exec(); +} diff --git a/ground/openpilotgcs/src/plugins/uavsettingsimportexport/uavsettingsimportexportfactory.h b/ground/openpilotgcs/src/plugins/uavsettingsimportexport/uavsettingsimportexportfactory.h new file mode 100644 index 000000000..a130d5c4a --- /dev/null +++ b/ground/openpilotgcs/src/plugins/uavsettingsimportexport/uavsettingsimportexportfactory.h @@ -0,0 +1,55 @@ +/** + ****************************************************************************** + * + * @file uavsettingsimportexportfactory.h + * @author (C) 2011 The OpenPilot Team, http://www.openpilot.org + * @addtogroup GCSPlugins GCS Plugins + * @{ + * @addtogroup UAVSettingsImportExport UAVSettings Import/Export Plugin + * @{ + * @brief UAVSettings Import/Export Plugin + *****************************************************************************/ +/* + * 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 UAVSETTINGSIMPORTEXPORTFACTORY_H +#define UAVSETTINGSIMPORTEXPORTFACTORY_H +#include "uavsettingsimportexport_global.h" +#include "uavobjectutil/uavobjectutilmanager.h" +#include "../../../../../build/ground/openpilotgcs/gcsversioninfo.h" +class UAVSETTINGSIMPORTEXPORT_EXPORT UAVSettingsImportExportFactory : public QObject +{ + Q_OBJECT + +public: + UAVSettingsImportExportFactory(QObject *parent = 0); + ~UAVSettingsImportExportFactory(); + +private: + QString createXMLDocument(const QString docName, + const bool isSettings, + const bool fullExport); + +private slots: + void importUAVSettings(); + void exportUAVSettings(); + void exportUAVData(); +signals: + void importAboutToBegin(); + void importEnded(); + +}; + +#endif // UAVSETTINGSIMPORTEXPORTFACTORY_H diff --git a/ground/openpilotgcs/src/plugins/uploader/op_dfu.cpp b/ground/openpilotgcs/src/plugins/uploader/op_dfu.cpp index b1e215f91..db2c60782 100644 --- a/ground/openpilotgcs/src/plugins/uploader/op_dfu.cpp +++ b/ground/openpilotgcs/src/plugins/uploader/op_dfu.cpp @@ -80,29 +80,26 @@ DFUObject::DFUObject(bool _debug,bool _use_serial,QString portname): } else { - send_delay=10; - use_delay=true; -// int numDevices=0; QList devices; - int count=0; - while((devices.length()==0) && count < 10) - { - if (debug) - qDebug() << "."; - delay::msleep(500); - // processEvents enables XP to process the system - // plug/unplug events, otherwise it will not process - // those events before the end of the call! - QApplication::processEvents(); - devices = USBMonitor::instance()->availableDevices(0x20a0,-1,-1,USBMonitor::Bootloader); - count++; - } - if (devices.length()==1) { + devices = USBMonitor::instance()->availableDevices(0x20a0,-1,-1,USBMonitor::Bootloader); + if (devices.length()==1) { hidHandle.open(1,devices.first().vendorID,devices.first().productID,0,0); } else { - qDebug() << devices.length() << " device(s) detected, don't know what to do!"; - mready = false; - } + // Wait for the board to appear on the USB bus: + QEventLoop m_eventloop; + connect(USBMonitor::instance(), SIGNAL(deviceDiscovered(USBPortInfo)),&m_eventloop, SLOT(quit())); + QTimer::singleShot(5000,&m_eventloop, SLOT(quit())); + m_eventloop.exec(); + devices = USBMonitor::instance()->availableDevices(0x20a0,-1,-1,USBMonitor::Bootloader); + if (devices.length()==1) { + delay::msleep(2000); // Let the USB Subsystem settle (especially important on Mac!) + hidHandle.open(1,devices.first().vendorID,devices.first().productID,0,0); + } + else { + qDebug() << devices.length() << " device(s) detected, don't know what to do!"; + mready = false; + } + } } } diff --git a/ground/openpilotgcs/src/plugins/uploader/op_dfu.h b/ground/openpilotgcs/src/plugins/uploader/op_dfu.h index 420e0a3ea..1fc92637c 100644 --- a/ground/openpilotgcs/src/plugins/uploader/op_dfu.h +++ b/ground/openpilotgcs/src/plugins/uploader/op_dfu.h @@ -17,6 +17,7 @@ #include "delay.h" #include #include +#include #include "SSP/qssp.h" #include "SSP/port.h" #include "SSP/qsspt.h" diff --git a/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.cpp b/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.cpp index 397533c2b..0f3affaa2 100755 --- a/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.cpp +++ b/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.cpp @@ -48,7 +48,8 @@ UploaderGadgetWidget::UploaderGadgetWidget(QWidget *parent) : QWidget(parent) connect(m_config->resetButton, SIGNAL(clicked()), this, SLOT(systemReset())); connect(m_config->bootButton, SIGNAL(clicked()), this, SLOT(systemBoot())); connect(m_config->rescueButton, SIGNAL(clicked()), this, SLOT(systemRescue())); - + Core::ConnectionManager *cm = Core::ICore::instance()->connectionManager(); + connect(cm,SIGNAL(deviceConnected(QIODevice*)),this,SLOT(onPhisicalHWConnect())); getSerialPorts(); QIcon rbi; @@ -105,7 +106,12 @@ QString UploaderGadgetWidget::getPortDevice(const QString &friendName) } return ""; } - +void UploaderGadgetWidget::onPhisicalHWConnect() +{ + m_config->bootButton->setEnabled(false); + m_config->rescueButton->setEnabled(false); + m_config->telemetryLink->setEnabled(false); +} /** Enables widget buttons if autopilot connected @@ -235,9 +241,7 @@ void UploaderGadgetWidget::goToBootloader(UAVObject* callerObj, bool success) currentStep = IAP_STATE_BOOTLOADER; // Tell the mainboard to get into bootloader state: - log("Detecting devices, please wait 5 seconds..."); - this->repaint(); - delay::msleep(5100); // Required to let the board(s) settle + log("Detecting devices, please wait a few seconds..."); if (!dfu) { if (dlj.startsWith("USB")) dfu = new DFUObject(DFU_DEBUG, false, QString()); diff --git a/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.h b/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.h index 075dc18a0..74a48425b 100755 --- a/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.h +++ b/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.h @@ -85,6 +85,7 @@ private: QLineEdit* openFileNameLE; QEventLoop m_eventloop; private slots: + void onPhisicalHWConnect(); void error(QString errorString,int errorNumber); void info(QString infoString,int infoNumber); void goToBootloader(UAVObject* = NULL, bool = false);