mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2025-02-20 10:54:14 +01:00
Merge branch 'next' into abeck/OP-1760-autotakeoff-squashed
This commit is contained in:
commit
1e9bd43871
169
Makefile
169
Makefile
@ -49,6 +49,8 @@ export BUILD_DIR := $(ROOT_DIR)/build
|
||||
export PACKAGE_DIR := $(ROOT_DIR)/build/package
|
||||
export DIST_DIR := $(ROOT_DIR)/build/dist
|
||||
|
||||
DIRS = $(DL_DIR) $(TOOLS_DIR) $(BUILD_DIR) $(PACKAGE_DIR) $(DIST_DIR)
|
||||
|
||||
# Set up default build configurations (debug | release)
|
||||
GCS_BUILD_CONF := release
|
||||
UAVOGEN_BUILD_CONF := release
|
||||
@ -140,20 +142,6 @@ all_clean:
|
||||
.PONY: clean
|
||||
clean: all_clean
|
||||
|
||||
$(DL_DIR):
|
||||
$(MKDIR) -p $@
|
||||
|
||||
$(TOOLS_DIR):
|
||||
$(MKDIR) -p $@
|
||||
|
||||
$(BUILD_DIR):
|
||||
$(MKDIR) -p $@
|
||||
|
||||
$(PACKAGE_DIR):
|
||||
$(MKDIR) -p $@
|
||||
|
||||
$(DIST_DIR):
|
||||
$(MKDIR) -p $@
|
||||
|
||||
##############################
|
||||
#
|
||||
@ -167,10 +155,12 @@ else
|
||||
UAVOGEN_SILENT := silent
|
||||
endif
|
||||
|
||||
UAVOBJGENERATOR_DIR = $(BUILD_DIR)/uavobjgenerator
|
||||
DIRS += $(UAVOBJGENERATOR_DIR)
|
||||
|
||||
.PHONY: uavobjgenerator
|
||||
uavobjgenerator:
|
||||
$(V1) $(MKDIR) -p $(BUILD_DIR)/$@
|
||||
$(V1) ( cd $(BUILD_DIR)/$@ && \
|
||||
uavobjgenerator: | $(UAVOBJGENERATOR_DIR)
|
||||
$(V1) ( cd $(UAVOBJGENERATOR_DIR) && \
|
||||
$(QMAKE) $(ROOT_DIR)/ground/uavobjgenerator/uavobjgenerator.pro -spec $(QT_SPEC) -r CONFIG+="$(UAVOGEN_BUILD_CONF) $(UAVOGEN_SILENT)" && \
|
||||
$(MAKE) --no-print-directory -w ; \
|
||||
)
|
||||
@ -183,8 +173,7 @@ uavobjects: $(addprefix uavobjects_, $(UAVOBJ_TARGETS))
|
||||
UAVOBJ_XML_DIR := $(ROOT_DIR)/shared/uavobjectdefinition
|
||||
UAVOBJ_OUT_DIR := $(BUILD_DIR)/uavobject-synthetics
|
||||
|
||||
$(UAVOBJ_OUT_DIR):
|
||||
$(V1) $(MKDIR) -p $@
|
||||
DIRS += $(UAVOBJ_OUT_DIR)
|
||||
|
||||
uavobjects_%: $(UAVOBJ_OUT_DIR) uavobjgenerator
|
||||
$(V1) ( cd $(UAVOBJ_OUT_DIR) && \
|
||||
@ -214,6 +203,8 @@ export OPUAVTALK := $(ROOT_DIR)/flight/uavtalk
|
||||
export OPUAVSYNTHDIR := $(BUILD_DIR)/uavobject-synthetics/flight
|
||||
export OPGCSSYNTHDIR := $(BUILD_DIR)/openpilotgcs-synthetics
|
||||
|
||||
DIRS += $(OPGCSSYNTHDIR)
|
||||
|
||||
# Define supported board lists
|
||||
ALL_BOARDS := coptercontrol oplinkmini revolution osd revoproto simposix discoveryf4bare gpsplatinum
|
||||
|
||||
@ -225,7 +216,7 @@ osd_short := 'osd '
|
||||
revoproto_short := 'revp'
|
||||
simposix_short := 'posx'
|
||||
discoveryf4bare_short := 'df4b'
|
||||
gpsplatinum_short := 'gps9 '
|
||||
gpsplatinum_short := 'gps9'
|
||||
|
||||
# SimPosix only builds on Linux so drop it from the list for
|
||||
# all other platforms.
|
||||
@ -460,8 +451,9 @@ sim_osx_%: uavobjects_flight
|
||||
all_ground: openpilotgcs uploader
|
||||
|
||||
# Convenience target for the GCS
|
||||
.PHONY: gcs gcs_clean
|
||||
.PHONY: gcs gcs_qmake gcs_clean
|
||||
gcs: openpilotgcs
|
||||
gcs_qmake: openpilotgcs_qmake
|
||||
gcs_clean: openpilotgcs_clean
|
||||
|
||||
ifeq ($(V), 1)
|
||||
@ -470,32 +462,25 @@ else
|
||||
GCS_SILENT := silent
|
||||
endif
|
||||
|
||||
.NOTPARALLEL:
|
||||
.PHONY: openpilotgcs
|
||||
openpilotgcs: uavobjects_gcs openpilotgcs_qmake openpilotgcs_make
|
||||
OPENPILOTGCS_DIR := $(BUILD_DIR)/openpilotgcs_$(GCS_BUILD_CONF)
|
||||
DIRS += $(OPENPILOTGCS_DIR)
|
||||
|
||||
OPENPILOTGCS_MAKEFILE := $(OPENPILOTGCS_DIR)/Makefile
|
||||
|
||||
.PHONY: openpilotgcs_qmake
|
||||
openpilotgcs_qmake:
|
||||
ifeq ($(QMAKE_SKIP),)
|
||||
$(V1) $(MKDIR) -p $(BUILD_DIR)/openpilotgcs_$(GCS_BUILD_CONF)
|
||||
$(V1) ( cd $(BUILD_DIR)/openpilotgcs_$(GCS_BUILD_CONF) && \
|
||||
openpilotgcs_qmake $(OPENPILOTGCS_MAKEFILE): | $(OPENPILOTGCS_DIR)
|
||||
$(V1) ( cd $(OPENPILOTGCS_DIR) && \
|
||||
$(QMAKE) $(ROOT_DIR)/ground/openpilotgcs/openpilotgcs.pro -spec $(QT_SPEC) -r CONFIG+="$(GCS_BUILD_CONF) $(GCS_SILENT)" $(GCS_QMAKE_OPTS) \
|
||||
)
|
||||
else
|
||||
@$(ECHO) "skipping qmake"
|
||||
endif
|
||||
|
||||
.PHONY: openpilotgcs_make
|
||||
openpilotgcs_make:
|
||||
$(V1) $(MKDIR) -p $(BUILD_DIR)/openpilotgcs_$(GCS_BUILD_CONF)
|
||||
$(V1) ( cd $(BUILD_DIR)/openpilotgcs_$(GCS_BUILD_CONF)/$(MAKE_DIR) && \
|
||||
$(MAKE) -w ; \
|
||||
)
|
||||
.PHONY: openpilotgcs
|
||||
openpilotgcs: uavobjects_gcs $(OPENPILOTGCS_MAKEFILE)
|
||||
$(V1) $(MAKE) -w -C $(OPENPILOTGCS_DIR)/$(MAKE_DIR);
|
||||
|
||||
.PHONY: openpilotgcs_clean
|
||||
openpilotgcs_clean:
|
||||
@$(ECHO) " CLEAN $(call toprel, $(BUILD_DIR)/openpilotgcs_$(GCS_BUILD_CONF))"
|
||||
$(V1) [ ! -d "$(BUILD_DIR)/openpilotgcs_$(GCS_BUILD_CONF)" ] || $(RM) -r "$(BUILD_DIR)/openpilotgcs_$(GCS_BUILD_CONF)"
|
||||
@$(ECHO) " CLEAN $(call toprel, $(OPENPILOTGCS_DIR))"
|
||||
$(V1) [ ! -d "$(OPENPILOTGCS_DIR)" ] || $(RM) -r "$(OPENPILOTGCS_DIR)"
|
||||
|
||||
################################
|
||||
#
|
||||
@ -503,77 +488,27 @@ openpilotgcs_clean:
|
||||
#
|
||||
################################
|
||||
|
||||
.NOTPARALLEL:
|
||||
.PHONY: uploader
|
||||
uploader: uploader_qmake uploader_make
|
||||
UPLOADER_DIR := $(BUILD_DIR)/uploader_$(GCS_BUILD_CONF)
|
||||
DIRS += $(UPLOADER_DIR)
|
||||
|
||||
UPLOADER_MAKEFILE := $(UPLOADER_DIR)/Makefile
|
||||
|
||||
.PHONY: uploader_qmake
|
||||
uploader_qmake:
|
||||
ifeq ($(QMAKE_SKIP),)
|
||||
$(V1) $(MKDIR) -p $(BUILD_DIR)/uploader_$(GCS_BUILD_CONF)
|
||||
$(V1) ( cd $(BUILD_DIR)/uploader_$(GCS_BUILD_CONF) && \
|
||||
uploader_qmake $(UPLOADER_MAKEFILE): | $(UPLOADER_DIR)
|
||||
$(V1) ( cd $(UPLOADER_DIR) && \
|
||||
$(QMAKE) $(ROOT_DIR)/ground/openpilotgcs/src/experimental/USB_UPLOAD_TOOL/upload.pro -spec $(QT_SPEC) -r CONFIG+="$(GCS_BUILD_CONF) $(GCS_SILENT)" $(GCS_QMAKE_OPTS) \
|
||||
)
|
||||
else
|
||||
@$(ECHO) "skipping qmake"
|
||||
endif
|
||||
|
||||
.PHONY: uploader_make
|
||||
uploader_make:
|
||||
$(V1) $(MKDIR) -p $(BUILD_DIR)/uploader_$(GCS_BUILD_CONF)
|
||||
$(V1) ( cd $(BUILD_DIR)/uploader_$(GCS_BUILD_CONF)/$(MAKE_DIR) && \
|
||||
$(MAKE) -w ; \
|
||||
)
|
||||
.PHONY: uploader
|
||||
uploader: $(UPLOADER_MAKEFILE)
|
||||
$(V1) $(MAKE) -w -C $(UPLOADER_DIR)
|
||||
|
||||
.PHONY: uploader_clean
|
||||
uploader_clean:
|
||||
@$(ECHO) " CLEAN $(call toprel, $(BUILD_DIR)/uploader_$(GCS_BUILD_CONF))"
|
||||
$(V1) [ ! -d "$(BUILD_DIR)/uploader_$(GCS_BUILD_CONF)" ] || $(RM) -r "$(BUILD_DIR)/uploader_$(GCS_BUILD_CONF)"
|
||||
@$(ECHO) " CLEAN $(call toprel, $(UPLOADER_DIR))"
|
||||
$(V1) [ ! -d "$(UPLOADER_DIR)" ] || $(RM) -r "$(UPLOADER_DIR)"
|
||||
|
||||
|
||||
################################
|
||||
#
|
||||
# Android GCS related components
|
||||
#
|
||||
################################
|
||||
|
||||
# Build the output directory for the Android GCS build
|
||||
ANDROIDGCS_OUT_DIR := $(BUILD_DIR)/androidgcs
|
||||
$(ANDROIDGCS_OUT_DIR):
|
||||
$(V1) $(MKDIR) -p $@
|
||||
|
||||
# Build the asset directory for the android assets
|
||||
ANDROIDGCS_ASSETS_DIR := $(ANDROIDGCS_OUT_DIR)/assets
|
||||
$(ANDROIDGCS_ASSETS_DIR)/uavos:
|
||||
$(V1) $(MKDIR) -p $@
|
||||
|
||||
ifeq ($(V), 1)
|
||||
ANT_QUIET :=
|
||||
ANDROID_SILENT :=
|
||||
else
|
||||
ANT_QUIET := -q
|
||||
ANDROID_SILENT := -s
|
||||
endif
|
||||
|
||||
.PHONY: androidgcs
|
||||
androidgcs: uavo-collections_java
|
||||
$(V0) @$(ECHO) " ANDROID $(call toprel, $(ANDROIDGCS_OUT_DIR))"
|
||||
$(V1) $(MKDIR) -p $(ANDROIDGCS_OUT_DIR)
|
||||
$(V1) $(ANDROID) $(ANDROID_SILENT) update project \
|
||||
--target "Google Inc.:Google APIs:$(GOOGLE_API_VERSION)" \
|
||||
--name androidgcs \
|
||||
--path ./androidgcs
|
||||
$(V1) $(ANT) -f ./androidgcs/build.xml \
|
||||
$(ANT_QUIET) \
|
||||
-Dout.dir="../$(call toprel, $(ANDROIDGCS_OUT_DIR)/bin)" \
|
||||
-Dgen.absolute.dir="$(ANDROIDGCS_OUT_DIR)/gen" \
|
||||
$(ANDROIDGCS_BUILD_CONF)
|
||||
|
||||
.PHONY: androidgcs_clean
|
||||
androidgcs_clean:
|
||||
@$(ECHO) " CLEAN $(call toprel, $(ANDROIDGCS_OUT_DIR))"
|
||||
$(V1) [ ! -d "$(ANDROIDGCS_OUT_DIR)" ] || $(RM) -r "$(ANDROIDGCS_OUT_DIR)"
|
||||
|
||||
# We want to take snapshots of the UAVOs at each point that they change
|
||||
# to allow the GCS to be compatible with as many versions as possible.
|
||||
# We always include a pseudo collection called "srctree" which represents
|
||||
@ -695,8 +630,7 @@ ALL_UNITTESTS := logfs math lednotification
|
||||
|
||||
# Build the directory for the unit tests
|
||||
UT_OUT_DIR := $(BUILD_DIR)/unit_tests
|
||||
$(UT_OUT_DIR):
|
||||
$(V1) $(MKDIR) -p $@
|
||||
DIRS += $(UT_OUT_DIR)
|
||||
|
||||
.PHONY: all_ut
|
||||
all_ut: $(addsuffix _elf, $(addprefix ut_, $(ALL_UNITTESTS)))
|
||||
@ -771,9 +705,8 @@ OPFW_CONTENTS := \
|
||||
.PHONY: opfw_resource
|
||||
opfw_resource: $(OPFW_RESOURCE)
|
||||
|
||||
$(OPFW_RESOURCE): $(FW_TARGETS)
|
||||
$(OPFW_RESOURCE): $(FW_TARGETS) | $(OPGCSSYNTHDIR)
|
||||
@$(ECHO) Generating OPFW resource file $(call toprel, $@)
|
||||
$(V1) $(MKDIR) -p $(dir $@)
|
||||
$(V1) $(ECHO) $(QUOTE)$(OPFW_CONTENTS)$(QUOTE) > $@
|
||||
|
||||
# If opfw_resource or all firmware are requested, GCS should depend on the resource
|
||||
@ -864,9 +797,8 @@ docs_all_clean:
|
||||
##############################
|
||||
|
||||
.PHONY: build-info
|
||||
build-info:
|
||||
build-info: | $(BUILD_DIR)
|
||||
@$(ECHO) " BUILD-INFO $(call toprel, $(BUILD_DIR)/$@.txt)"
|
||||
$(V1) $(MKDIR) -p $(BUILD_DIR)
|
||||
$(V1) $(VERSION_INFO) \
|
||||
--uavodir=$(ROOT_DIR)/shared/uavobjectdefinition \
|
||||
--template="make/templates/$@.txt" \
|
||||
@ -895,6 +827,17 @@ $(DIST_NAME).gz: $(DIST_VER_INFO) .git/index | $(DIST_DIR)
|
||||
.PHONY: dist
|
||||
dist: $(DIST_NAME).gz
|
||||
|
||||
|
||||
##############################
|
||||
#
|
||||
# Directories
|
||||
#
|
||||
##############################
|
||||
|
||||
$(DIRS):
|
||||
$(V1) $(MKDIR) -p $@
|
||||
|
||||
|
||||
##############################
|
||||
#
|
||||
# Help message, the default Makefile goal
|
||||
@ -928,7 +871,6 @@ help:
|
||||
@$(ECHO) " openocd_install - Install the OpenOCD JTAG daemon"
|
||||
@$(ECHO) " stm32flash_install - Install the stm32flash tool for unbricking F1-based boards"
|
||||
@$(ECHO) " dfuutil_install - Install the dfu-util tool for unbricking F4-based boards"
|
||||
@$(ECHO) " android_sdk_install - Install the Android SDK tools"
|
||||
@$(ECHO) " Install all available tools:"
|
||||
@$(ECHO) " all_sdk_install - Install all of above (platform-dependent)"
|
||||
@$(ECHO) " build_sdk_install - Install only essential for build tools (platform-dependent)"
|
||||
@ -1000,26 +942,19 @@ help:
|
||||
@$(ECHO)
|
||||
@$(ECHO) " [GCS]"
|
||||
@$(ECHO) " gcs - Build the Ground Control System (GCS) application (debug|release)"
|
||||
@$(ECHO) " Skip qmake: QMAKE_SKIP=1"
|
||||
@$(ECHO) " Compile specific directory: MAKE_DIR=<dir>"
|
||||
@$(ECHO) " Example: make gcs QMAKE_SKIP=1 MAKE_DIR=src/plugins/coreplugin"
|
||||
@$(ECHO) " Example: make gcs MAKE_DIR=src/plugins/coreplugin"
|
||||
@$(ECHO) " gcs_qmake - Run qmake for the Ground Control System (GCS) application (debug|release)"
|
||||
@$(ECHO) " gcs_clean - Remove the Ground Control System (GCS) application (debug|release)"
|
||||
@$(ECHO) " Supported build configurations: GCS_BUILD_CONF=debug|release (default is $(GCS_BUILD_CONF))"
|
||||
@$(ECHO)
|
||||
@$(ECHO) " [Uploader Tool]"
|
||||
@$(ECHO) " uploader - Build the serial uploader tool (debug|release)"
|
||||
@$(ECHO) " Skip qmake: QMAKE_SKIP=1"
|
||||
@$(ECHO) " Example: make uploader QMAKE_SKIP=1"
|
||||
@$(ECHO) " uploader_qmake - Run qmake for the serial uploader tool (debug|release)"
|
||||
@$(ECHO) " uploader_clean - Remove the serial uploader tool (debug|release)"
|
||||
@$(ECHO) " Supported build configurations: GCS_BUILD_CONF=debug|release (default is $(GCS_BUILD_CONF))"
|
||||
@$(ECHO)
|
||||
@$(ECHO)
|
||||
@$(ECHO) " [AndroidGCS]"
|
||||
@$(ECHO) " androidgcs - Build the Android Ground Control System (GCS) application"
|
||||
@$(ECHO) " androidgcs_install - Use ADB to install the Android GCS application"
|
||||
@$(ECHO) " androidgcs_run - Run the Android GCS application"
|
||||
@$(ECHO) " androidgcs_clean - Remove the Android GCS application"
|
||||
@$(ECHO)
|
||||
@$(ECHO) " [UAVObjects]"
|
||||
@$(ECHO) " uavobjects - Generate source files from the UAVObject definition XML files"
|
||||
@$(ECHO) " uavobjects_test - Parse xml-files - check for valid, duplicate ObjId's, ..."
|
||||
|
@ -9,7 +9,7 @@
|
||||
* @{
|
||||
*
|
||||
* @file telemetry.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2015.
|
||||
* @brief Telemetry module, handles telemetry and UAVObject updates
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
*
|
||||
@ -30,6 +30,34 @@
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* Telemetry uses four tasks. Two are created for the main telemetry
|
||||
* stream called "TelTx" and "TelRx". Two are created to handle the OPLink
|
||||
* radio connection, called "RadioTx" and "RadioRx", the latter being
|
||||
* overridden by USB if connected.
|
||||
*
|
||||
* The following code uses a "local" prefix to refer to the telemetry channel
|
||||
* associated with a port on the FC and a "radio" prefix to refer to the
|
||||
* telemetry channel associated with the OPLink/USB.
|
||||
*
|
||||
* The "local" telemetry port to use is defined by PIOS_COM_TELEM_RF in
|
||||
* PIOS_Board_Init().
|
||||
*
|
||||
* A UAVTalk connection instance, telemUavTalkCon, is associated with the
|
||||
* "local" channel and another, radioUavTalkCon, with the "radio" channel.
|
||||
* Associated with each instance is a transmit routine which will send data
|
||||
* to the appropriate port.
|
||||
*
|
||||
* Data is passed on the telemetry channels using queues. If
|
||||
* PIOS_TELEM_PRIORITY_QUEUE is defined then two queues are created, one normal
|
||||
* priority and the other high priority.
|
||||
*
|
||||
* The "Tx" tasks read events first from the priority queue and then from
|
||||
* the normal queue, passing each event to processObjEvent() which ultimately
|
||||
* passes each event to the UAVTalk library which results in the appropriate
|
||||
* transmit routine being called to send the data back to the recipient on
|
||||
* the "local" or "radio" link.
|
||||
*/
|
||||
|
||||
#include <openpilot.h>
|
||||
|
||||
#include "telemetry.h"
|
||||
@ -53,62 +81,74 @@
|
||||
|
||||
#ifdef PIOS_TELEM_RADIO_RX_STACK_SIZE
|
||||
#define STACK_SIZE_RADIO_RX_BYTES PIOS_TELEM_RADIO_RX_STACK_SIZE
|
||||
#define STACK_SIZE_RADIO_TX_BYTES PIOS_TELEM_RADIO_TX_STACK_SIZE
|
||||
#else
|
||||
#define STACK_SIZE_RADIO_RX_BYTES STACK_SIZE_RX_BYTES
|
||||
#define STACK_SIZE_RADIO_TX_BYTES STACK_SIZE_TX_BYTES
|
||||
#endif
|
||||
#define TASK_PRIORITY_RX (tskIDLE_PRIORITY + 2)
|
||||
#define TASK_PRIORITY_TX (tskIDLE_PRIORITY + 2)
|
||||
#define TASK_PRIORITY_RADRX (tskIDLE_PRIORITY + 2)
|
||||
#define TASK_PRIORITY_RADTX (tskIDLE_PRIORITY + 2)
|
||||
#define REQ_TIMEOUT_MS 250
|
||||
#define MAX_RETRIES 2
|
||||
#define STATS_UPDATE_PERIOD_MS 4000
|
||||
#define CONNECTION_TIMEOUT_MS 8000
|
||||
|
||||
// Private types
|
||||
typedef struct {
|
||||
// Determine port on which to communicate telemetry information
|
||||
uint32_t (*getPort)();
|
||||
// Main telemetry queue
|
||||
xQueueHandle queue;
|
||||
#ifdef PIOS_TELEM_PRIORITY_QUEUE
|
||||
// Priority telemetry queue
|
||||
xQueueHandle priorityQueue;
|
||||
#endif /* PIOS_TELEM_PRIORITY_QUEUE */
|
||||
// Transmit/receive task handles
|
||||
xTaskHandle txTaskHandle;
|
||||
xTaskHandle rxTaskHandle;
|
||||
// Telemetry stream
|
||||
UAVTalkConnection uavTalkCon;
|
||||
} channelContext;
|
||||
|
||||
// Private variables
|
||||
static uint32_t telemetryPort;
|
||||
#ifdef PIOS_INCLUDE_RFM22B
|
||||
static uint32_t radioPort;
|
||||
#endif
|
||||
static xQueueHandle queue;
|
||||
// Main telemetry channel
|
||||
static channelContext localChannel;
|
||||
static int32_t transmitLocalData(uint8_t *data, int32_t length);
|
||||
static void registerLocalObject(UAVObjHandle obj);
|
||||
static uint32_t localPort();
|
||||
|
||||
#if defined(PIOS_TELEM_PRIORITY_QUEUE)
|
||||
static xQueueHandle priorityQueue;
|
||||
#else
|
||||
#define priorityQueue queue
|
||||
#endif
|
||||
// OPLink telemetry channel
|
||||
static channelContext radioChannel;
|
||||
static int32_t transmitRadioData(uint8_t *data, int32_t length);
|
||||
static void registerRadioObject(UAVObjHandle obj);
|
||||
static uint32_t radioPort();
|
||||
|
||||
static xTaskHandle telemetryTxTaskHandle;
|
||||
static xTaskHandle telemetryRxTaskHandle;
|
||||
#ifdef PIOS_INCLUDE_RFM22B
|
||||
static xTaskHandle radioRxTaskHandle;
|
||||
#endif
|
||||
// Telemetry stats
|
||||
static uint32_t txErrors;
|
||||
static uint32_t txRetries;
|
||||
static uint32_t timeOfLastObjectUpdate;
|
||||
static UAVTalkConnection uavTalkCon;
|
||||
#ifdef PIOS_INCLUDE_RFM22B
|
||||
static UAVTalkConnection radioUavTalkCon;
|
||||
#endif
|
||||
|
||||
// Private functions
|
||||
static void telemetryTxTask(void *parameters);
|
||||
static void telemetryRxTask(void *parameters);
|
||||
#ifdef PIOS_INCLUDE_RFM22B
|
||||
static void radioRxTask(void *parameters);
|
||||
static int32_t transmitRadioData(uint8_t *data, int32_t length);
|
||||
#endif
|
||||
static int32_t transmitData(uint8_t *data, int32_t length);
|
||||
static void registerObject(UAVObjHandle obj);
|
||||
static void updateObject(UAVObjHandle obj, int32_t eventType);
|
||||
static int32_t setUpdatePeriod(UAVObjHandle obj, int32_t updatePeriodMs);
|
||||
static int32_t setLoggingPeriod(UAVObjHandle obj, int32_t updatePeriodMs);
|
||||
static void processObjEvent(UAVObjEvent *ev);
|
||||
static void updateObject(
|
||||
channelContext *channel,
|
||||
UAVObjHandle obj,
|
||||
int32_t eventType);
|
||||
static void processObjEvent(
|
||||
channelContext *channel,
|
||||
UAVObjEvent *ev);
|
||||
static int32_t setUpdatePeriod(
|
||||
channelContext *channel,
|
||||
UAVObjHandle obj,
|
||||
int32_t updatePeriodMs);
|
||||
static int32_t setLoggingPeriod(
|
||||
channelContext *channel,
|
||||
UAVObjHandle obj,
|
||||
int32_t updatePeriodMs);
|
||||
static void updateTelemetryStats();
|
||||
static void gcsTelemetryStatsUpdated();
|
||||
static void updateSettings();
|
||||
static uint32_t getComPort(bool input);
|
||||
static void updateSettings(channelContext *channel);
|
||||
|
||||
/**
|
||||
* Initialise the telemetry module
|
||||
@ -117,28 +157,94 @@ static uint32_t getComPort(bool input);
|
||||
*/
|
||||
int32_t TelemetryStart(void)
|
||||
{
|
||||
// Process all registered objects and connect queue for updates
|
||||
UAVObjIterate(®isterObject);
|
||||
// Only start the local telemetry tasks if needed
|
||||
if (localPort()) {
|
||||
UAVObjIterate(®isterLocalObject);
|
||||
|
||||
// Listen to objects of interest
|
||||
#ifdef PIOS_TELEM_PRIORITY_QUEUE
|
||||
GCSTelemetryStatsConnectQueue(localChannel.priorityQueue);
|
||||
#else /* PIOS_TELEM_PRIORITY_QUEUE */
|
||||
GCSTelemetryStatsConnectQueue(localChannel.queue);
|
||||
#endif /* PIOS_TELEM_PRIORITY_QUEUE */
|
||||
// Start telemetry tasks
|
||||
xTaskCreate(telemetryTxTask,
|
||||
"TelTx",
|
||||
STACK_SIZE_TX_BYTES / 4,
|
||||
&localChannel,
|
||||
TASK_PRIORITY_TX,
|
||||
&localChannel.txTaskHandle);
|
||||
PIOS_TASK_MONITOR_RegisterTask(TASKINFO_RUNNING_TELEMETRYTX,
|
||||
localChannel.txTaskHandle);
|
||||
xTaskCreate(telemetryRxTask,
|
||||
"TelRx",
|
||||
STACK_SIZE_RX_BYTES / 4,
|
||||
&localChannel,
|
||||
TASK_PRIORITY_RX,
|
||||
&localChannel.rxTaskHandle);
|
||||
PIOS_TASK_MONITOR_RegisterTask(TASKINFO_RUNNING_TELEMETRYRX,
|
||||
localChannel.rxTaskHandle);
|
||||
}
|
||||
|
||||
// Start the telemetry tasks associated with Radio/USB
|
||||
UAVObjIterate(®isterRadioObject);
|
||||
|
||||
// Listen to objects of interest
|
||||
GCSTelemetryStatsConnectQueue(priorityQueue);
|
||||
#ifdef PIOS_TELEM_PRIORITY_QUEUE
|
||||
GCSTelemetryStatsConnectQueue(radioChannel.priorityQueue);
|
||||
#else /* PIOS_TELEM_PRIORITY_QUEUE */
|
||||
GCSTelemetryStatsConnectQueue(radioChannel.queue);
|
||||
#endif /* PIOS_TELEM_PRIORITY_QUEUE */
|
||||
|
||||
// Start telemetry tasks
|
||||
xTaskCreate(telemetryTxTask, "TelTx", STACK_SIZE_TX_BYTES / 4, NULL, TASK_PRIORITY_TX, &telemetryTxTaskHandle);
|
||||
PIOS_TASK_MONITOR_RegisterTask(TASKINFO_RUNNING_TELEMETRYTX, telemetryTxTaskHandle);
|
||||
xTaskCreate(telemetryRxTask, "TelRx", STACK_SIZE_RX_BYTES / 4, NULL, TASK_PRIORITY_RX, &telemetryRxTaskHandle);
|
||||
PIOS_TASK_MONITOR_RegisterTask(TASKINFO_RUNNING_TELEMETRYRX, telemetryRxTaskHandle);
|
||||
|
||||
#ifdef PIOS_INCLUDE_RFM22B
|
||||
if (radioPort) {
|
||||
xTaskCreate(radioRxTask, "RadioRx", STACK_SIZE_RADIO_RX_BYTES / 4, NULL, TASK_PRIORITY_RADRX, &radioRxTaskHandle);
|
||||
PIOS_TASK_MONITOR_RegisterTask(TASKINFO_RUNNING_RADIORX, radioRxTaskHandle);
|
||||
}
|
||||
#endif
|
||||
xTaskCreate(telemetryTxTask,
|
||||
"RadioTx",
|
||||
STACK_SIZE_RADIO_TX_BYTES / 4,
|
||||
&radioChannel,
|
||||
TASK_PRIORITY_RADTX,
|
||||
&radioChannel.txTaskHandle);
|
||||
PIOS_TASK_MONITOR_RegisterTask(TASKINFO_RUNNING_RADIOTX,
|
||||
radioChannel.txTaskHandle);
|
||||
xTaskCreate(telemetryRxTask,
|
||||
"RadioRx",
|
||||
STACK_SIZE_RADIO_RX_BYTES / 4,
|
||||
&radioChannel,
|
||||
TASK_PRIORITY_RADRX,
|
||||
&radioChannel.rxTaskHandle);
|
||||
PIOS_TASK_MONITOR_RegisterTask(TASKINFO_RUNNING_RADIORX,
|
||||
radioChannel.rxTaskHandle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Intialise a telemetry channel */
|
||||
void TelemetryInitializeChannel(channelContext *channel)
|
||||
{
|
||||
// Create object queues
|
||||
channel->queue = xQueueCreate(MAX_QUEUE_SIZE,
|
||||
sizeof(UAVObjEvent));
|
||||
#if defined(PIOS_TELEM_PRIORITY_QUEUE)
|
||||
channel->priorityQueue = xQueueCreate(MAX_QUEUE_SIZE,
|
||||
sizeof(UAVObjEvent));
|
||||
#endif /* PIOS_TELEM_PRIORITY_QUEUE */
|
||||
|
||||
// Initialise UAVTalk
|
||||
channel->uavTalkCon = UAVTalkInitialize(&transmitLocalData);
|
||||
|
||||
// Create periodic event that will be used to update the telemetry stats
|
||||
UAVObjEvent ev;
|
||||
memset(&ev, 0, sizeof(UAVObjEvent));
|
||||
|
||||
#ifdef PIOS_TELEM_PRIORITY_QUEUE
|
||||
EventPeriodicQueueCreate(&ev,
|
||||
channel->priorityQueue,
|
||||
STATS_UPDATE_PERIOD_MS);
|
||||
#else /* PIOS_TELEM_PRIORITY_QUEUE */
|
||||
EventPeriodicQueueCreate(&ev,
|
||||
channel->queue,
|
||||
STATS_UPDATE_PERIOD_MS);
|
||||
#endif /* PIOS_TELEM_PRIORITY_QUEUE */
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the telemetry module
|
||||
* \return -1 if initialisation failed
|
||||
@ -146,39 +252,37 @@ int32_t TelemetryStart(void)
|
||||
*/
|
||||
int32_t TelemetryInitialize(void)
|
||||
{
|
||||
HwSettingsInitialize();
|
||||
|
||||
FlightTelemetryStatsInitialize();
|
||||
GCSTelemetryStatsInitialize();
|
||||
|
||||
// Initialize vars
|
||||
timeOfLastObjectUpdate = 0;
|
||||
|
||||
// Create object queues
|
||||
queue = xQueueCreate(MAX_QUEUE_SIZE, sizeof(UAVObjEvent));
|
||||
#if defined(PIOS_TELEM_PRIORITY_QUEUE)
|
||||
priorityQueue = xQueueCreate(MAX_QUEUE_SIZE, sizeof(UAVObjEvent));
|
||||
#endif
|
||||
|
||||
// Update telemetry settings
|
||||
telemetryPort = PIOS_COM_TELEM_RF;
|
||||
#ifdef PIOS_INCLUDE_RFM22B
|
||||
radioPort = PIOS_COM_RF;
|
||||
#endif
|
||||
HwSettingsInitialize();
|
||||
updateSettings();
|
||||
|
||||
// Initialise UAVTalk
|
||||
uavTalkCon = UAVTalkInitialize(&transmitData);
|
||||
#ifdef PIOS_INCLUDE_RFM22B
|
||||
radioUavTalkCon = UAVTalkInitialize(&transmitRadioData);
|
||||
#endif
|
||||
|
||||
// Create periodic event that will be used to update the telemetry stats
|
||||
// FIXME STATS_UPDATE_PERIOD_MS is 4000ms while FlighTelemetryStats update period is 5000ms...
|
||||
// Reset link stats
|
||||
txErrors = 0;
|
||||
txRetries = 0;
|
||||
UAVObjEvent ev;
|
||||
memset(&ev, 0, sizeof(UAVObjEvent));
|
||||
EventPeriodicQueueCreate(&ev, priorityQueue, STATS_UPDATE_PERIOD_MS);
|
||||
|
||||
// Set channel port handlers
|
||||
localChannel.getPort = localPort;
|
||||
radioChannel.getPort = radioPort;
|
||||
|
||||
// Set the local telemetry baud rate
|
||||
updateSettings(&localChannel);
|
||||
|
||||
// Only initialise local channel if telemetry port enabled
|
||||
if (localPort()) {
|
||||
// Initialise channel
|
||||
TelemetryInitializeChannel(&localChannel);
|
||||
// Initialise UAVTalk
|
||||
localChannel.uavTalkCon = UAVTalkInitialize(&transmitLocalData);
|
||||
}
|
||||
|
||||
// Initialise channel
|
||||
TelemetryInitializeChannel(&radioChannel);
|
||||
// Initialise UAVTalk
|
||||
radioChannel.uavTalkCon = UAVTalkInitialize(&transmitRadioData);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -190,22 +294,51 @@ MODULE_INITCALL(TelemetryInitialize, TelemetryStart);
|
||||
* telemetry settings.
|
||||
* \param[in] obj Object to connect
|
||||
*/
|
||||
static void registerObject(UAVObjHandle obj)
|
||||
static void registerLocalObject(UAVObjHandle obj)
|
||||
{
|
||||
if (UAVObjIsMetaobject(obj)) {
|
||||
// Only connect change notifications for meta objects. No periodic updates
|
||||
UAVObjConnectQueue(obj, priorityQueue, EV_MASK_ALL_UPDATES);
|
||||
#ifdef PIOS_TELEM_PRIORITY_QUEUE
|
||||
UAVObjConnectQueue(obj, localChannel.priorityQueue, EV_MASK_ALL_UPDATES);
|
||||
#else /* PIOS_TELEM_PRIORITY_QUEUE */
|
||||
UAVObjConnectQueue(obj, localChannel.queue, EV_MASK_ALL_UPDATES);
|
||||
#endif /* PIOS_TELEM_PRIORITY_QUEUE */
|
||||
} else {
|
||||
// Setup object for periodic updates
|
||||
updateObject(obj, EV_NONE);
|
||||
updateObject(
|
||||
&localChannel,
|
||||
obj,
|
||||
EV_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
static void registerRadioObject(UAVObjHandle obj)
|
||||
{
|
||||
if (UAVObjIsMetaobject(obj)) {
|
||||
// Only connect change notifications for meta objects. No periodic updates
|
||||
#ifdef PIOS_TELEM_PRIORITY_QUEUE
|
||||
UAVObjConnectQueue(obj, radioChannel.priorityQueue, EV_MASK_ALL_UPDATES);
|
||||
#else /* PIOS_TELEM_PRIORITY_QUEUE */
|
||||
UAVObjConnectQueue(obj, radioChannel.queue, EV_MASK_ALL_UPDATES);
|
||||
#endif /* PIOS_TELEM_PRIORITY_QUEUE */
|
||||
} else {
|
||||
// Setup object for periodic updates
|
||||
updateObject(
|
||||
&radioChannel,
|
||||
obj,
|
||||
EV_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update object's queue connections and timer, depending on object's settings
|
||||
* \param[in] telemetry channel context
|
||||
* \param[in] obj Object to updates
|
||||
*/
|
||||
static void updateObject(UAVObjHandle obj, int32_t eventType)
|
||||
static void updateObject(
|
||||
channelContext *channel,
|
||||
UAVObjHandle obj,
|
||||
int32_t eventType)
|
||||
{
|
||||
UAVObjMetadata metadata;
|
||||
UAVObjUpdateMode updateMode, loggingMode;
|
||||
@ -228,13 +361,15 @@ static void updateObject(UAVObjHandle obj, int32_t eventType)
|
||||
switch (updateMode) {
|
||||
case UPDATEMODE_PERIODIC:
|
||||
// Set update period
|
||||
setUpdatePeriod(obj, metadata.telemetryUpdatePeriod);
|
||||
setUpdatePeriod(channel,
|
||||
obj,
|
||||
metadata.telemetryUpdatePeriod);
|
||||
// Connect queue
|
||||
eventMask |= EV_UPDATED_PERIODIC | EV_UPDATED_MANUAL | EV_UPDATE_REQ;
|
||||
break;
|
||||
case UPDATEMODE_ONCHANGE:
|
||||
// Set update period
|
||||
setUpdatePeriod(obj, 0);
|
||||
setUpdatePeriod(channel, obj, 0);
|
||||
// Connect queue
|
||||
eventMask |= EV_UPDATED | EV_UPDATED_MANUAL | EV_UPDATE_REQ;
|
||||
break;
|
||||
@ -244,7 +379,9 @@ static void updateObject(UAVObjHandle obj, int32_t eventType)
|
||||
eventMask |= EV_UPDATED | EV_UPDATED_MANUAL | EV_UPDATE_REQ;
|
||||
// Set update period on initialization and metadata change
|
||||
if (eventType == EV_NONE) {
|
||||
setUpdatePeriod(obj, metadata.telemetryUpdatePeriod);
|
||||
setUpdatePeriod(channel,
|
||||
obj,
|
||||
metadata.telemetryUpdatePeriod);
|
||||
}
|
||||
} else {
|
||||
// Otherwise, we just received an object update, so switch to periodic for the timeout period to prevent more updates
|
||||
@ -253,7 +390,7 @@ static void updateObject(UAVObjHandle obj, int32_t eventType)
|
||||
break;
|
||||
case UPDATEMODE_MANUAL:
|
||||
// Set update period
|
||||
setUpdatePeriod(obj, 0);
|
||||
setUpdatePeriod(channel, obj, 0);
|
||||
// Connect queue
|
||||
eventMask |= EV_UPDATED_MANUAL | EV_UPDATE_REQ;
|
||||
break;
|
||||
@ -261,13 +398,13 @@ static void updateObject(UAVObjHandle obj, int32_t eventType)
|
||||
switch (loggingMode) {
|
||||
case UPDATEMODE_PERIODIC:
|
||||
// Set update period
|
||||
setLoggingPeriod(obj, metadata.loggingUpdatePeriod);
|
||||
setLoggingPeriod(channel, obj, metadata.loggingUpdatePeriod);
|
||||
// Connect queue
|
||||
eventMask |= EV_LOGGING_PERIODIC | EV_LOGGING_MANUAL;
|
||||
break;
|
||||
case UPDATEMODE_ONCHANGE:
|
||||
// Set update period
|
||||
setLoggingPeriod(obj, 0);
|
||||
setLoggingPeriod(channel, obj, 0);
|
||||
// Connect queue
|
||||
eventMask |= EV_UPDATED | EV_LOGGING_MANUAL;
|
||||
break;
|
||||
@ -277,7 +414,9 @@ static void updateObject(UAVObjHandle obj, int32_t eventType)
|
||||
eventMask |= EV_UPDATED | EV_LOGGING_MANUAL;
|
||||
// Set update period on initialization and metadata change
|
||||
if (eventType == EV_NONE) {
|
||||
setLoggingPeriod(obj, metadata.loggingUpdatePeriod);
|
||||
setLoggingPeriod(channel,
|
||||
obj,
|
||||
metadata.loggingUpdatePeriod);
|
||||
}
|
||||
} else {
|
||||
// Otherwise, we just received an object update, so switch to periodic for the timeout period to prevent more updates
|
||||
@ -286,23 +425,28 @@ static void updateObject(UAVObjHandle obj, int32_t eventType)
|
||||
break;
|
||||
case UPDATEMODE_MANUAL:
|
||||
// Set update period
|
||||
setLoggingPeriod(obj, 0);
|
||||
setLoggingPeriod(channel, obj, 0);
|
||||
// Connect queue
|
||||
eventMask |= EV_LOGGING_MANUAL;
|
||||
break;
|
||||
}
|
||||
|
||||
// note that all setting objects have implicitly IsPriority=true
|
||||
#ifdef PIOS_TELEM_PRIORITY_QUEUE
|
||||
if (UAVObjIsPriority(obj)) {
|
||||
UAVObjConnectQueue(obj, priorityQueue, eventMask);
|
||||
} else {
|
||||
UAVObjConnectQueue(obj, queue, eventMask);
|
||||
}
|
||||
UAVObjConnectQueue(obj, channel->priorityQueue, eventMask);
|
||||
} else
|
||||
#endif /* PIOS_TELEM_PRIORITY_QUEUE */
|
||||
UAVObjConnectQueue(obj, channel->queue, eventMask);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Processes queue events
|
||||
*/
|
||||
static void processObjEvent(UAVObjEvent *ev)
|
||||
static void processObjEvent(
|
||||
channelContext *channel,
|
||||
UAVObjEvent *ev)
|
||||
{
|
||||
UAVObjMetadata metadata;
|
||||
UAVObjUpdateMode updateMode;
|
||||
@ -327,7 +471,10 @@ static void processObjEvent(UAVObjEvent *ev)
|
||||
// Send update to GCS (with retries)
|
||||
while (retries < MAX_RETRIES && success == -1) {
|
||||
// call blocks until ack is received or timeout
|
||||
success = UAVTalkSendObject(uavTalkCon, ev->obj, ev->instId, UAVObjGetTelemetryAcked(&metadata), REQ_TIMEOUT_MS);
|
||||
success = UAVTalkSendObject(channel->uavTalkCon,
|
||||
ev->obj,
|
||||
ev->instId,
|
||||
UAVObjGetTelemetryAcked(&metadata), REQ_TIMEOUT_MS);
|
||||
if (success == -1) {
|
||||
++retries;
|
||||
}
|
||||
@ -341,7 +488,10 @@ static void processObjEvent(UAVObjEvent *ev)
|
||||
// Request object update from GCS (with retries)
|
||||
while (retries < MAX_RETRIES && success == -1) {
|
||||
// call blocks until update is received or timeout
|
||||
success = UAVTalkSendObjectRequest(uavTalkCon, ev->obj, ev->instId, REQ_TIMEOUT_MS);
|
||||
success = UAVTalkSendObjectRequest(channel->uavTalkCon,
|
||||
ev->obj,
|
||||
ev->instId,
|
||||
REQ_TIMEOUT_MS);
|
||||
if (success == -1) {
|
||||
++retries;
|
||||
}
|
||||
@ -355,11 +505,17 @@ static void processObjEvent(UAVObjEvent *ev)
|
||||
// If this is a metaobject then make necessary telemetry updates
|
||||
if (UAVObjIsMetaobject(ev->obj)) {
|
||||
// linked object will be the actual object the metadata are for
|
||||
updateObject(UAVObjGetLinkedObj(ev->obj), EV_NONE);
|
||||
updateObject(
|
||||
channel,
|
||||
UAVObjGetLinkedObj(ev->obj),
|
||||
EV_NONE);
|
||||
} else {
|
||||
if (updateMode == UPDATEMODE_THROTTLED) {
|
||||
// If this is UPDATEMODE_THROTTLED, the event mask changes on every event.
|
||||
updateObject(ev->obj, ev->event);
|
||||
updateObject(
|
||||
channel,
|
||||
ev->obj,
|
||||
ev->event);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -380,7 +536,10 @@ static void processObjEvent(UAVObjEvent *ev)
|
||||
}
|
||||
if (updateMode == UPDATEMODE_THROTTLED) {
|
||||
// If this is UPDATEMODE_THROTTLED, the event mask changes on every event.
|
||||
updateObject(ev->obj, ev->event);
|
||||
updateObject(
|
||||
channel,
|
||||
ev->obj,
|
||||
ev->event);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -388,37 +547,43 @@ static void processObjEvent(UAVObjEvent *ev)
|
||||
/**
|
||||
* Telemetry transmit task, regular priority
|
||||
*/
|
||||
static void telemetryTxTask(__attribute__((unused)) void *parameters)
|
||||
static void telemetryTxTask(void *parameters)
|
||||
{
|
||||
channelContext *channel = (channelContext *)parameters;
|
||||
UAVObjEvent ev;
|
||||
|
||||
/* Check for a bad context */
|
||||
if (!channel) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Loop forever
|
||||
while (1) {
|
||||
/**
|
||||
* Tries to empty the high priority queue before handling any standard priority item
|
||||
*/
|
||||
#if defined(PIOS_TELEM_PRIORITY_QUEUE)
|
||||
#ifdef PIOS_TELEM_PRIORITY_QUEUE
|
||||
// empty priority queue, non-blocking
|
||||
while (xQueueReceive(priorityQueue, &ev, 0) == pdTRUE) {
|
||||
while (xQueueReceive(channel->priorityQueue, &ev, 0) == pdTRUE) {
|
||||
// Process event
|
||||
processObjEvent(&ev);
|
||||
processObjEvent(channel, &ev);
|
||||
}
|
||||
// check regular queue and process update - non-blocking
|
||||
if (xQueueReceive(queue, &ev, 0) == pdTRUE) {
|
||||
if (xQueueReceive(channel->queue, &ev, 0) == pdTRUE) {
|
||||
// Process event
|
||||
processObjEvent(&ev);
|
||||
processObjEvent(channel, &ev);
|
||||
// if both queues are empty, wait on priority queue for updates (1 tick) then repeat cycle
|
||||
} else if (xQueueReceive(priorityQueue, &ev, 1) == pdTRUE) {
|
||||
} else if (xQueueReceive(channel->priorityQueue, &ev, 1) == pdTRUE) {
|
||||
// Process event
|
||||
processObjEvent(&ev);
|
||||
processObjEvent(channel, &ev);
|
||||
}
|
||||
#else
|
||||
// wait on queue for updates (1 tick) then repeat cycle
|
||||
if (xQueueReceive(queue, &ev, 1) == pdTRUE) {
|
||||
if (xQueueReceive(channel->queue, &ev, 1) == pdTRUE) {
|
||||
// Process event
|
||||
processObjEvent(&ev);
|
||||
processObjEvent(channel, &ev);
|
||||
}
|
||||
#endif /* if defined(PIOS_TELEM_PRIORITY_QUEUE) */
|
||||
#endif /* PIOS_TELEM_PRIORITY_QUEUE */
|
||||
}
|
||||
}
|
||||
|
||||
@ -426,11 +591,18 @@ static void telemetryTxTask(__attribute__((unused)) void *parameters)
|
||||
/**
|
||||
* Telemetry receive task. Processes queue events and periodic updates.
|
||||
*/
|
||||
static void telemetryRxTask(__attribute__((unused)) void *parameters)
|
||||
static void telemetryRxTask(void *parameters)
|
||||
{
|
||||
channelContext *channel = (channelContext *)parameters;
|
||||
|
||||
/* Check for a bad context */
|
||||
if (!channel) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Task loop
|
||||
while (1) {
|
||||
uint32_t inputPort = getComPort(true);
|
||||
uint32_t inputPort = channel->getPort();
|
||||
|
||||
if (inputPort) {
|
||||
// Block until data are available
|
||||
@ -439,7 +611,7 @@ static void telemetryRxTask(__attribute__((unused)) void *parameters)
|
||||
|
||||
bytes_to_process = PIOS_COM_ReceiveBuffer(inputPort, serial_data, sizeof(serial_data), 500);
|
||||
if (bytes_to_process > 0) {
|
||||
UAVTalkProcessInputStream(uavTalkCon, serial_data, bytes_to_process);
|
||||
UAVTalkProcessInputStream(channel->uavTalkCon, serial_data, bytes_to_process);
|
||||
}
|
||||
} else {
|
||||
vTaskDelay(5);
|
||||
@ -447,28 +619,58 @@ static void telemetryRxTask(__attribute__((unused)) void *parameters)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PIOS_INCLUDE_RFM22B
|
||||
|
||||
/**
|
||||
* Radio telemetry receive task. Processes queue events and periodic updates.
|
||||
* Determine the port to be used for communication on the telemetry channel
|
||||
* \return com port number
|
||||
*/
|
||||
static void radioRxTask(__attribute__((unused)) void *parameters)
|
||||
static uint32_t localPort()
|
||||
{
|
||||
// Task loop
|
||||
while (1) {
|
||||
if (radioPort) {
|
||||
// Block until data are available
|
||||
uint8_t serial_data[16];
|
||||
uint16_t bytes_to_process;
|
||||
|
||||
bytes_to_process = PIOS_COM_ReceiveBuffer(radioPort, serial_data, sizeof(serial_data), 500);
|
||||
if (bytes_to_process > 0) {
|
||||
UAVTalkProcessInputStream(radioUavTalkCon, serial_data, bytes_to_process);
|
||||
}
|
||||
} else {
|
||||
vTaskDelay(5);
|
||||
}
|
||||
}
|
||||
return PIOS_COM_TELEM_RF;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine the port to be used for communication on the radio channel
|
||||
* \return com port number
|
||||
*/
|
||||
static uint32_t radioPort()
|
||||
{
|
||||
#ifdef PIOS_INCLUDE_RFM22B
|
||||
uint32_t port = PIOS_COM_RF;
|
||||
#else /* PIOS_INCLUDE_RFM22B */
|
||||
uint32_t port = 0;
|
||||
#endif /* PIOS_INCLUDE_RFM22B */
|
||||
#ifdef PIOS_INCLUDE_USB
|
||||
// if USB is connected, USB takes precedence for telemetry
|
||||
if (PIOS_COM_Available(PIOS_COM_TELEM_USB)) {
|
||||
port = PIOS_COM_TELEM_USB;
|
||||
}
|
||||
#endif /* PIOS_INCLUDE_USB */
|
||||
|
||||
return port;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Transmit data buffer to the modem or USB port.
|
||||
* \param[in] data Data buffer to send
|
||||
* \param[in] length Length of buffer
|
||||
* \return -1 on failure
|
||||
* \return number of bytes transmitted on success
|
||||
*/
|
||||
static int32_t transmitLocalData(uint8_t *data, int32_t length)
|
||||
{
|
||||
uint32_t outputPort = localChannel.getPort();
|
||||
|
||||
if (outputPort) {
|
||||
return PIOS_COM_SendBuffer(outputPort, data, length);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Transmit data buffer to the radioport.
|
||||
* \param[in] data Data buffer to send
|
||||
@ -478,24 +680,7 @@ static void radioRxTask(__attribute__((unused)) void *parameters)
|
||||
*/
|
||||
static int32_t transmitRadioData(uint8_t *data, int32_t length)
|
||||
{
|
||||
if (radioPort) {
|
||||
return PIOS_COM_SendBuffer(radioPort, data, length);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
#endif /* PIOS_INCLUDE_RFM22B */
|
||||
|
||||
/**
|
||||
* Transmit data buffer to the modem or USB port.
|
||||
* \param[in] data Data buffer to send
|
||||
* \param[in] length Length of buffer
|
||||
* \return -1 on failure
|
||||
* \return number of bytes transmitted on success
|
||||
*/
|
||||
static int32_t transmitData(uint8_t *data, int32_t length)
|
||||
{
|
||||
uint32_t outputPort = getComPort(false);
|
||||
uint32_t outputPort = radioChannel.getPort();
|
||||
|
||||
if (outputPort) {
|
||||
return PIOS_COM_SendBuffer(outputPort, data, length);
|
||||
@ -506,12 +691,16 @@ static int32_t transmitData(uint8_t *data, int32_t length)
|
||||
|
||||
/**
|
||||
* Set update period of object (it must be already setup for periodic updates)
|
||||
* \param[in] telemetry channel context
|
||||
* \param[in] obj The object to update
|
||||
* \param[in] updatePeriodMs The update period in ms, if zero then periodic updates are disabled
|
||||
* \return 0 Success
|
||||
* \return -1 Failure
|
||||
*/
|
||||
static int32_t setUpdatePeriod(UAVObjHandle obj, int32_t updatePeriodMs)
|
||||
static int32_t setUpdatePeriod(
|
||||
channelContext *channel,
|
||||
UAVObjHandle obj,
|
||||
int32_t updatePeriodMs)
|
||||
{
|
||||
UAVObjEvent ev;
|
||||
int32_t ret;
|
||||
@ -522,7 +711,12 @@ static int32_t setUpdatePeriod(UAVObjHandle obj, int32_t updatePeriodMs)
|
||||
ev.event = EV_UPDATED_PERIODIC;
|
||||
ev.lowPriority = true;
|
||||
|
||||
xQueueHandle targetQueue = UAVObjIsPriority(obj) ? priorityQueue : queue;
|
||||
#ifdef PIOS_TELEM_PRIORITY_QUEUE
|
||||
xQueueHandle targetQueue = UAVObjIsPriority(obj) ? channel->priorityQueue :
|
||||
channel->queue;
|
||||
#else /* PIOS_TELEM_PRIORITY_QUEUE */
|
||||
xQueueHandle targetQueue = channel->queue;
|
||||
#endif /* PIOS_TELEM_PRIORITY_QUEUE */
|
||||
|
||||
ret = EventPeriodicQueueUpdate(&ev, targetQueue, updatePeriodMs);
|
||||
if (ret == -1) {
|
||||
@ -533,12 +727,16 @@ static int32_t setUpdatePeriod(UAVObjHandle obj, int32_t updatePeriodMs)
|
||||
|
||||
/**
|
||||
* Set logging update period of object (it must be already setup for periodic updates)
|
||||
* \param[in] telemetry channel context
|
||||
* \param[in] obj The object to update
|
||||
* \param[in] updatePeriodMs The update period in ms, if zero then periodic updates are disabled
|
||||
* \return 0 Success
|
||||
* \return -1 Failure
|
||||
*/
|
||||
static int32_t setLoggingPeriod(UAVObjHandle obj, int32_t updatePeriodMs)
|
||||
static int32_t setLoggingPeriod(
|
||||
channelContext *channel,
|
||||
UAVObjHandle obj,
|
||||
int32_t updatePeriodMs)
|
||||
{
|
||||
UAVObjEvent ev;
|
||||
int32_t ret;
|
||||
@ -549,7 +747,12 @@ static int32_t setLoggingPeriod(UAVObjHandle obj, int32_t updatePeriodMs)
|
||||
ev.event = EV_LOGGING_PERIODIC;
|
||||
ev.lowPriority = true;
|
||||
|
||||
xQueueHandle targetQueue = UAVObjIsPriority(obj) ? priorityQueue : queue;
|
||||
#ifdef PIOS_TELEM_PRIORITY_QUEUE
|
||||
xQueueHandle targetQueue = UAVObjIsPriority(obj) ? channel->priorityQueue :
|
||||
channel->queue;
|
||||
#else /* PIOS_TELEM_PRIORITY_QUEUE */
|
||||
xQueueHandle targetQueue = channel->queue;
|
||||
#endif /* PIOS_TELEM_PRIORITY_QUEUE */
|
||||
|
||||
ret = EventPeriodicQueueUpdate(&ev, targetQueue, updatePeriodMs);
|
||||
if (ret == -1) {
|
||||
@ -588,10 +791,8 @@ static void updateTelemetryStats()
|
||||
uint32_t timeNow;
|
||||
|
||||
// Get stats
|
||||
UAVTalkGetStats(uavTalkCon, &utalkStats, true);
|
||||
#ifdef PIOS_INCLUDE_RFM22B
|
||||
UAVTalkAddStats(radioUavTalkCon, &utalkStats, true);
|
||||
#endif
|
||||
UAVTalkGetStats(localChannel.uavTalkCon, &utalkStats, true);
|
||||
UAVTalkAddStats(radioChannel.uavTalkCon, &utalkStats, true);
|
||||
|
||||
// Get object data
|
||||
FlightTelemetryStatsGet(&flightStats);
|
||||
@ -681,9 +882,11 @@ static void updateTelemetryStats()
|
||||
* settings, etc. Thus the HwSettings object which contains the
|
||||
* telemetry port speed is used for now.
|
||||
*/
|
||||
static void updateSettings()
|
||||
static void updateSettings(channelContext *channel)
|
||||
{
|
||||
if (telemetryPort) {
|
||||
uint32_t port = channel->getPort();
|
||||
|
||||
if (port) {
|
||||
// Retrieve settings
|
||||
uint8_t speed;
|
||||
HwSettingsTelemetrySpeedGet(&speed);
|
||||
@ -691,58 +894,30 @@ static void updateSettings()
|
||||
// Set port speed
|
||||
switch (speed) {
|
||||
case HWSETTINGS_TELEMETRYSPEED_2400:
|
||||
PIOS_COM_ChangeBaud(telemetryPort, 2400);
|
||||
PIOS_COM_ChangeBaud(port, 2400);
|
||||
break;
|
||||
case HWSETTINGS_TELEMETRYSPEED_4800:
|
||||
PIOS_COM_ChangeBaud(telemetryPort, 4800);
|
||||
PIOS_COM_ChangeBaud(port, 4800);
|
||||
break;
|
||||
case HWSETTINGS_TELEMETRYSPEED_9600:
|
||||
PIOS_COM_ChangeBaud(telemetryPort, 9600);
|
||||
PIOS_COM_ChangeBaud(port, 9600);
|
||||
break;
|
||||
case HWSETTINGS_TELEMETRYSPEED_19200:
|
||||
PIOS_COM_ChangeBaud(telemetryPort, 19200);
|
||||
PIOS_COM_ChangeBaud(port, 19200);
|
||||
break;
|
||||
case HWSETTINGS_TELEMETRYSPEED_38400:
|
||||
PIOS_COM_ChangeBaud(telemetryPort, 38400);
|
||||
PIOS_COM_ChangeBaud(port, 38400);
|
||||
break;
|
||||
case HWSETTINGS_TELEMETRYSPEED_57600:
|
||||
PIOS_COM_ChangeBaud(telemetryPort, 57600);
|
||||
PIOS_COM_ChangeBaud(port, 57600);
|
||||
break;
|
||||
case HWSETTINGS_TELEMETRYSPEED_115200:
|
||||
PIOS_COM_ChangeBaud(telemetryPort, 115200);
|
||||
PIOS_COM_ChangeBaud(port, 115200);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine input/output com port as highest priority available
|
||||
* @param[in] input Returns the approproate input com port if true, else the appropriate output com port
|
||||
*/
|
||||
#ifdef PIOS_INCLUDE_RFM22B
|
||||
static uint32_t getComPort(bool input)
|
||||
#else
|
||||
static uint32_t getComPort(__attribute__((unused)) bool input)
|
||||
#endif
|
||||
{
|
||||
#if defined(PIOS_INCLUDE_USB)
|
||||
// if USB is connected, USB takes precedence for telemetry
|
||||
if (PIOS_COM_Available(PIOS_COM_TELEM_USB)) {
|
||||
return PIOS_COM_TELEM_USB;
|
||||
} else
|
||||
#endif /* PIOS_INCLUDE_USB */
|
||||
#ifdef PIOS_INCLUDE_RFM22B
|
||||
// PIOS_COM_RF input is handled by a separate RX thread and therefore must be ignored
|
||||
if (input && telemetryPort == PIOS_COM_RF) {
|
||||
return 0;
|
||||
} else
|
||||
#endif /* PIOS_INCLUDE_RFM22B */
|
||||
if (PIOS_COM_Available(telemetryPort)) {
|
||||
return telemetryPort;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
@ -194,13 +194,18 @@ msheap_init(heap_handle_t *heap, void *base, void *limit)
|
||||
}
|
||||
|
||||
void *
|
||||
msheap_alloc(heap_handle_t *heap, uint32_t size)
|
||||
msheap_alloc(heap_handle_t *heap, void *ptr, uint32_t size)
|
||||
{
|
||||
marker_t cursor;
|
||||
marker_t best;
|
||||
uint32_t copy_data = 0;
|
||||
uint16_t old_size = 0;
|
||||
|
||||
ASSERT(3, msheap_check(heap));
|
||||
|
||||
if (size == 0)
|
||||
return 0;
|
||||
|
||||
/* convert the passed-in size to the number of marker-size units we need to allocate */
|
||||
size += marker_size;
|
||||
size = round_up(size, marker_size);
|
||||
@ -210,6 +215,39 @@ msheap_alloc(heap_handle_t *heap, uint32_t size)
|
||||
if (size > heap->heap_free)
|
||||
return 0;
|
||||
|
||||
/* realloc */
|
||||
if (ptr != 0) {
|
||||
|
||||
best = (marker_t)ptr - 1;
|
||||
ASSERT(0, region_check(heap, best));
|
||||
ASSERT(3, msheap_check(heap));
|
||||
|
||||
#ifdef HEAP_REALLOC_FREE_UNUSED_AREA
|
||||
|
||||
if (best->next.size == size)
|
||||
goto done;
|
||||
|
||||
if (best->next.size > size) {
|
||||
/* this region is free, mark it accordingly */
|
||||
best->next.free = 1;
|
||||
(best + best->next.size)->prev.free = 1;
|
||||
|
||||
traceFREE( ptr, best->next.size );
|
||||
|
||||
/* account for space we are freeing */
|
||||
heap->heap_free += best->next.size;
|
||||
|
||||
goto split;
|
||||
}
|
||||
#else
|
||||
if (best->next.size >= size)
|
||||
goto done;
|
||||
#endif
|
||||
old_size = best->next.size;
|
||||
msheap_free(heap, ptr);
|
||||
copy_data = 1;
|
||||
}
|
||||
|
||||
/* simple single-pass best-fit search */
|
||||
restart:
|
||||
cursor = heap->free_hint;
|
||||
@ -242,13 +280,28 @@ restart:
|
||||
/* no space */
|
||||
return 0;
|
||||
}
|
||||
#ifdef HEAP_REALLOC_FREE_UNUSED_AREA
|
||||
split:
|
||||
#endif
|
||||
|
||||
/* split the free region to make space */
|
||||
split_region(heap, best, size);
|
||||
|
||||
/* update free space counter */
|
||||
heap->heap_free -= size;
|
||||
|
||||
done:
|
||||
traceMALLOC( (void *)(best + 1), size );
|
||||
|
||||
/* Copy data that might be reused */
|
||||
if (copy_data && ptr) {
|
||||
size = old_size;
|
||||
size = size - 1;
|
||||
size *= marker_size;
|
||||
for(uint32_t i=0 ; i < size; i++)
|
||||
((uint8_t *)(best + 1))[i] = ((uint8_t *)ptr)[i];
|
||||
}
|
||||
|
||||
/* and return a pointer to the allocated region */
|
||||
return (void *)(best + 1);
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ extern void msheap_init(heap_handle_t *heap, void *base, void *limit);
|
||||
*
|
||||
* @param size The number of bytes required (more may be allocated).
|
||||
*/
|
||||
extern void *msheap_alloc(heap_handle_t *heap, uint32_t size);
|
||||
extern void *msheap_alloc(heap_handle_t *heap, void *ptr, uint32_t size);
|
||||
|
||||
/**
|
||||
* Free memory back to the heap.
|
||||
|
@ -74,15 +74,15 @@ heap_handle_t fast_heap;
|
||||
extern void vApplicationMallocFailedHook(void) __attribute__((weak));
|
||||
|
||||
void *
|
||||
pios_general_malloc(size_t s, bool use_fast_heap)
|
||||
pios_general_malloc(void *ptr, size_t s, bool use_fast_heap)
|
||||
{
|
||||
void *p;
|
||||
|
||||
vPortEnterCritical();
|
||||
if(use_fast_heap){
|
||||
p = msheap_alloc(&fast_heap, s);
|
||||
p = msheap_alloc(&fast_heap, ptr, s);
|
||||
} else {
|
||||
p = msheap_alloc(&sram_heap, s);
|
||||
p = msheap_alloc(&sram_heap, ptr, s);
|
||||
}
|
||||
vPortExitCritical();
|
||||
|
||||
@ -95,13 +95,13 @@ pios_general_malloc(size_t s, bool use_fast_heap)
|
||||
void *
|
||||
pvPortMalloc(size_t s)
|
||||
{
|
||||
return pios_general_malloc(s, true);
|
||||
return pios_general_malloc(NULL, s, true);
|
||||
}
|
||||
|
||||
void *
|
||||
pvPortMallocStack(size_t s)
|
||||
{
|
||||
return pios_general_malloc(s, false);
|
||||
return pios_general_malloc(NULL, s, false);
|
||||
}
|
||||
|
||||
void
|
||||
@ -154,7 +154,7 @@ malloc(size_t size)
|
||||
heap_init_done = 1;
|
||||
}
|
||||
|
||||
return msheap_alloc(sram_heap, size);
|
||||
return msheap_alloc(NULL, sram_heap, size);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -29,17 +29,32 @@
|
||||
|
||||
#ifdef PIOS_TARGET_PROVIDES_FAST_HEAP
|
||||
// relies on pios_general_malloc to perform the allocation (i.e. pios_msheap.c)
|
||||
extern void *pios_general_malloc(size_t size, bool fastheap);
|
||||
extern void *pios_general_malloc(void *ptr, size_t size, bool fastheap);
|
||||
|
||||
void *pios_fastheapmalloc(size_t size)
|
||||
{
|
||||
return pios_general_malloc(size, true);
|
||||
return pios_general_malloc(NULL, size, true);
|
||||
}
|
||||
|
||||
|
||||
void *pios_malloc(size_t size)
|
||||
{
|
||||
return pios_general_malloc(size, false);
|
||||
return pios_general_malloc(NULL, size, false);
|
||||
}
|
||||
|
||||
void *pios_realloc(__attribute__((unused)) void *ptr, __attribute__((unused)) size_t size)
|
||||
{
|
||||
#ifdef PIOS_INCLUDE_REALLOC
|
||||
return pios_general_malloc(ptr, size, false);
|
||||
|
||||
#else
|
||||
// Not allowed to use realloc without the proper define PIOS_INCLUDE_REALLOC set
|
||||
while (1) {
|
||||
;
|
||||
}
|
||||
return NULL;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void pios_free(void *p)
|
||||
@ -47,7 +62,7 @@ void pios_free(void *p)
|
||||
vPortFree(p);
|
||||
}
|
||||
|
||||
#else
|
||||
#else /* ifdef PIOS_TARGET_PROVIDES_FAST_HEAP */
|
||||
// demand to pvPortMalloc implementation
|
||||
void *pios_fastheapmalloc(size_t size)
|
||||
{
|
||||
@ -60,6 +75,21 @@ void *pios_malloc(size_t size)
|
||||
return pvPortMalloc(size);
|
||||
}
|
||||
|
||||
void *pios_realloc(__attribute__((unused)) void *ptr, __attribute__((unused)) size_t size)
|
||||
{
|
||||
#ifdef PIOS_INCLUDE_REALLOC
|
||||
return pvPortMalloc(size);
|
||||
|
||||
#else
|
||||
// Not allowed to use realloc without the proper define PIOS_INCLUDE_REALLOC set
|
||||
while (1) {
|
||||
;
|
||||
}
|
||||
return NULL;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void pios_free(void *p)
|
||||
{
|
||||
vPortFree(p);
|
||||
|
@ -32,6 +32,8 @@ void *pios_fastheapmalloc(size_t size);
|
||||
|
||||
void *pios_malloc(size_t size);
|
||||
|
||||
void *pios_realloc(void *ptr, size_t size);
|
||||
|
||||
void pios_free(void *p);
|
||||
|
||||
#endif /* PIOS_MEM_H */
|
||||
|
@ -740,10 +740,7 @@ void PIOS_Board_Init(void)
|
||||
tx_buffer, PIOS_COM_RFM22B_RF_TX_BUF_LEN)) {
|
||||
PIOS_Assert(0);
|
||||
}
|
||||
/* Set Telemetry to use OPLinkMini if no other telemetry is configured (USB always overrides anyway) */
|
||||
if (!pios_com_telem_rf_id) {
|
||||
pios_com_telem_rf_id = pios_com_rf_id;
|
||||
}
|
||||
|
||||
oplinkStatus.LinkState = OPLINKSTATUS_LINKSTATE_ENABLED;
|
||||
|
||||
// Set the RF data rate on the modem to ~2X the selected buad rate because the modem is half duplex.
|
||||
|
@ -1,36 +1,10 @@
|
||||
include(openpilotgcs.pri)
|
||||
|
||||
TEMPLATE = subdirs
|
||||
TEMPLATE = aux
|
||||
|
||||
# Copy Qt runtime libraries into the build directory (to run or package)
|
||||
equals(copyqt, 1) {
|
||||
|
||||
# Copy QtQuick2 complete directories
|
||||
# Some of these directories have a lot of files
|
||||
# Easier to copy everything
|
||||
QT_QUICK2_DIRS = QtQuick/Controls \
|
||||
QtQuick/Dialogs \
|
||||
QtQuick/Layouts \
|
||||
QtQuick/LocalStorage \
|
||||
QtQuick/Particles.2 \
|
||||
QtQuick/PrivateWidgets \
|
||||
QtQuick/Window.2 \
|
||||
QtQuick/XmlListModel \
|
||||
QtQuick.2
|
||||
|
||||
# create QtQuick directory
|
||||
data_copy.commands += -@$(MKDIR) $$targetPath(\"$$GCS_QT_QML_PATH/QtQuick\") $$addNewline()
|
||||
|
||||
for(dir, QT_QUICK2_DIRS) {
|
||||
data_copy.commands += @rm -rf $$targetPath(\"$$GCS_QT_QML_PATH/$$dir\") $$addNewline()
|
||||
data_copy.commands += $(COPY_DIR) $$targetPath(\"$$[QT_INSTALL_QML]/$$dir\") $$targetPath(\"$$GCS_QT_QML_PATH/$$dir\") $$addNewline()
|
||||
}
|
||||
|
||||
data_copy.target = FORCE
|
||||
QMAKE_EXTRA_TARGETS += data_copy
|
||||
|
||||
linux {
|
||||
|
||||
QT_LIBS = libQt5Core.so.5 \
|
||||
libQt5Gui.so.5 \
|
||||
libQt5Widgets.so.5 \
|
||||
@ -56,35 +30,21 @@ equals(copyqt, 1) {
|
||||
libicui18n.so.53 \
|
||||
libicuuc.so.53 \
|
||||
libicudata.so.53
|
||||
|
||||
data_copy.commands += -@$(MKDIR) $$targetPath(\"$$GCS_QT_LIBRARY_PATH\") $$addNewline()
|
||||
for(lib, QT_LIBS) {
|
||||
data_copy.commands += $(COPY_FILE) $$targetPath(\"$$[QT_INSTALL_LIBS]/$$lib\") $$targetPath(\"$$GCS_QT_LIBRARY_PATH/$$lib\") $$addNewline()
|
||||
addCopyFileTarget($${lib},$$[QT_INSTALL_LIBS],$${GCS_QT_LIBRARY_PATH})
|
||||
}
|
||||
|
||||
# create Qt plugin directories
|
||||
QT_PLUGIN_DIRS = iconengines \
|
||||
imageformats \
|
||||
platforms \
|
||||
mediaservice \
|
||||
sqldrivers
|
||||
for(dir, QT_PLUGIN_DIRS) {
|
||||
data_copy.commands += -@$(MKDIR) $$targetPath(\"$$GCS_QT_PLUGINS_PATH/$$dir\") $$addNewline()
|
||||
}
|
||||
QT_PLUGIN_LIBS = iconengines/libqsvgicon.so \
|
||||
imageformats/libqgif.so \
|
||||
imageformats/libqico.so \
|
||||
imageformats/libqjpeg.so \
|
||||
imageformats/libqmng.so \
|
||||
imageformats/libqsvg.so \
|
||||
imageformats/libqtiff.so \
|
||||
mediaservice/libgstaudiodecoder.so \
|
||||
mediaservice/libgstmediaplayer.so \
|
||||
platforms/libqxcb.so \
|
||||
sqldrivers/libqsqlite.so
|
||||
for(lib, QT_PLUGIN_LIBS) {
|
||||
data_copy.commands += $(COPY_FILE) $$targetPath(\"$$[QT_INSTALL_PLUGINS]/$$lib\") $$targetPath(\"$$GCS_QT_PLUGINS_PATH/$$lib\") $$addNewline()
|
||||
}
|
||||
QT_PLUGINS = iconengines/libqsvgicon.so \
|
||||
imageformats/libqgif.so \
|
||||
imageformats/libqico.so \
|
||||
imageformats/libqjpeg.so \
|
||||
imageformats/libqmng.so \
|
||||
imageformats/libqsvg.so \
|
||||
imageformats/libqtiff.so \
|
||||
mediaservice/libgstaudiodecoder.so \
|
||||
mediaservice/libgstmediaplayer.so \
|
||||
platforms/libqxcb.so \
|
||||
sqldrivers/libqsqlite.so
|
||||
}
|
||||
|
||||
win32 {
|
||||
@ -106,7 +66,6 @@ equals(copyqt, 1) {
|
||||
Qt5Script$${DS}.dll \
|
||||
Qt5Concurrent$${DS}.dll \
|
||||
Qt5PrintSupport$${DS}.dll \
|
||||
Qt5OpenGL$${DS}.dll \
|
||||
Qt5SerialPort$${DS}.dll \
|
||||
Qt5Multimedia$${DS}.dll \
|
||||
Qt5MultimediaWidgets$${DS}.dll \
|
||||
@ -120,33 +79,7 @@ equals(copyqt, 1) {
|
||||
libstdc++-6.dll \
|
||||
libwinpthread-1.dll
|
||||
for(dll, QT_DLLS) {
|
||||
data_copy.commands += $(COPY_FILE) $$targetPath(\"$$[QT_INSTALL_BINS]/$$dll\") $$targetPath(\"$$GCS_APP_PATH/$$dll\") $$addNewline()
|
||||
}
|
||||
|
||||
# create Qt plugin directories
|
||||
QT_PLUGIN_DIRS = iconengines \
|
||||
imageformats \
|
||||
platforms \
|
||||
mediaservice \
|
||||
sqldrivers \
|
||||
opengl32_32
|
||||
for(dir, QT_PLUGIN_DIRS) {
|
||||
data_copy.commands += -@$(MKDIR) $$targetPath(\"$$GCS_APP_PATH/$$dir\") $$addNewline()
|
||||
}
|
||||
|
||||
# copy Qt plugin DLLs
|
||||
QT_PLUGIN_DLLS = iconengines/qsvgicon$${DS}.dll \
|
||||
imageformats/qgif$${DS}.dll \
|
||||
imageformats/qico$${DS}.dll \
|
||||
imageformats/qjpeg$${DS}.dll \
|
||||
imageformats/qmng$${DS}.dll \
|
||||
imageformats/qsvg$${DS}.dll \
|
||||
imageformats/qtiff$${DS}.dll \
|
||||
platforms/qwindows$${DS}.dll \
|
||||
mediaservice/dsengine$${DS}.dll \
|
||||
sqldrivers/qsqlite$${DS}.dll
|
||||
for(dll, QT_PLUGIN_DLLS) {
|
||||
data_copy.commands += $(COPY_FILE) $$targetPath(\"$$[QT_INSTALL_PLUGINS]/$$dll\") $$targetPath(\"$$GCS_APP_PATH/$$dll\") $$addNewline()
|
||||
addCopyFileTarget($${dll},$$[QT_INSTALL_BINS],$${GCS_APP_PATH})
|
||||
}
|
||||
|
||||
# copy OpenSSL DLLs
|
||||
@ -154,14 +87,45 @@ equals(copyqt, 1) {
|
||||
ssleay32.dll \
|
||||
libeay32.dll
|
||||
for(dll, OPENSSL_DLLS) {
|
||||
data_copy.commands += $(COPY_FILE) $$targetPath(\"$${OPENSSL_DIR}/$$dll\") $$targetPath(\"$$GCS_APP_PATH/$$dll\") $$addNewline()
|
||||
addCopyFileTarget($${dll},$${OPENSSL_DIR},$${GCS_APP_PATH})
|
||||
}
|
||||
|
||||
# copy OpenGL DLL
|
||||
OPENGL_DLLS = \
|
||||
opengl32_32/opengl32.dll
|
||||
for(dll, OPENGL_DLLS) {
|
||||
data_copy.commands += $(COPY_FILE) $$targetPath(\"$${MESAWIN_DIR}/$$dll\") $$targetPath(\"$$GCS_APP_PATH/$$dll\") $$addNewline()
|
||||
addCopyFileTarget($${dll},$${MESAWIN_DIR},$${GCS_APP_PATH})
|
||||
}
|
||||
|
||||
QT_PLUGINS = iconengines/qsvgicon$${DS}.dll \
|
||||
imageformats/qgif$${DS}.dll \
|
||||
imageformats/qico$${DS}.dll \
|
||||
imageformats/qjpeg$${DS}.dll \
|
||||
imageformats/qmng$${DS}.dll \
|
||||
imageformats/qsvg$${DS}.dll \
|
||||
imageformats/qtiff$${DS}.dll \
|
||||
platforms/qwindows$${DS}.dll \
|
||||
mediaservice/dsengine$${DS}.dll \
|
||||
sqldrivers/qsqlite$${DS}.dll
|
||||
}
|
||||
|
||||
for(plugin, QT_PLUGINS) {
|
||||
addCopyFileTarget($${plugin},$$[QT_INSTALL_PLUGINS],$${GCS_QT_PLUGINS_PATH})
|
||||
}
|
||||
|
||||
# Copy QtQuick2 complete directories
|
||||
# Some of these directories have a lot of files
|
||||
# Easier to copy everything
|
||||
QT_QUICK2_DIRS = QtQuick/Controls \
|
||||
QtQuick/Dialogs \
|
||||
QtQuick/Layouts \
|
||||
QtQuick/LocalStorage \
|
||||
QtQuick/Particles.2 \
|
||||
QtQuick/PrivateWidgets \
|
||||
QtQuick/Window.2 \
|
||||
QtQuick/XmlListModel \
|
||||
QtQuick.2
|
||||
for(dir, QT_QUICK2_DIRS) {
|
||||
addCopyDirTarget($${dir},$$[QT_INSTALL_QML],$${GCS_QT_QML_PATH})
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,57 @@ defineReplace(qtLibraryName) {
|
||||
return($$RET)
|
||||
}
|
||||
|
||||
defineTest(addCopyFileTarget) {
|
||||
file = $$1
|
||||
src = $$2/$$1
|
||||
dest = $$3/$$1
|
||||
|
||||
$${file}.target = $$dest
|
||||
$${file}.depends = $$src
|
||||
|
||||
# create directory. Better would be an order only dependency
|
||||
$${file}.commands = -@$(MKDIR) \"$$targetPath($$dirname(dest))\" $$addNewline()
|
||||
$${file}.commands += $(COPY_FILE) \"$$targetPath($$src)\" \"$$targetPath($$dest)\"
|
||||
|
||||
QMAKE_EXTRA_TARGETS += $$file
|
||||
POST_TARGETDEPS += $$eval($${file}.target)
|
||||
|
||||
export($${file}.target)
|
||||
export($${file}.depends)
|
||||
export($${file}.commands)
|
||||
export(QMAKE_EXTRA_TARGETS)
|
||||
export(POST_TARGETDEPS)
|
||||
|
||||
return(true)
|
||||
}
|
||||
|
||||
defineTest(addCopyDirTarget) {
|
||||
dir = $$1
|
||||
src = $$2/$$1
|
||||
dest = $$3/$$1
|
||||
|
||||
$${dir}.target = $$dest
|
||||
$${dir}.depends = $$src
|
||||
# Windows does not update directory timestamp if files are modified
|
||||
win32: $${dir}.depends += FORCE
|
||||
|
||||
$${dir}.commands = @rm -rf \"$$targetPath($$dest)\" $$addNewline()
|
||||
# create directory. Better would be an order only dependency
|
||||
$${dir}.commands += -@$(MKDIR) \"$$targetPath($$dirname(dest))\" $$addNewline()
|
||||
$${dir}.commands += $(COPY_DIR) \"$$targetPath($$src)\" \"$$targetPath($$dest)\"
|
||||
|
||||
QMAKE_EXTRA_TARGETS += $$dir
|
||||
POST_TARGETDEPS += $$eval($${dir}.target)
|
||||
|
||||
export($${dir}.target)
|
||||
export($${dir}.depends)
|
||||
export($${dir}.commands)
|
||||
export(QMAKE_EXTRA_TARGETS)
|
||||
export(POST_TARGETDEPS)
|
||||
|
||||
return(true)
|
||||
}
|
||||
|
||||
# For use in custom compilers which just copy files
|
||||
win32:i_flag = i
|
||||
defineReplace(stripSrcDir) {
|
||||
@ -119,6 +170,8 @@ macx {
|
||||
|
||||
contains(TEMPLATE, vc.*)|contains(TEMPLATE_PREFIX, vc):vcproj = 1
|
||||
GCS_APP_TARGET = openpilotgcs
|
||||
|
||||
GCS_QT_PLUGINS_PATH = $$GCS_APP_PATH
|
||||
GCS_QT_QML_PATH = $$GCS_APP_PATH
|
||||
|
||||
copyqt = $$copydata
|
||||
|
13
ground/openpilotgcs/share/copydata.pro
Normal file
13
ground/openpilotgcs/share/copydata.pro
Normal file
@ -0,0 +1,13 @@
|
||||
include(../openpilotgcs.pri)
|
||||
|
||||
TEMPLATE = aux
|
||||
|
||||
DATACOLLECTIONS = cloudconfig default_configurations dials models pfd sounds diagrams mapicons stylesheets
|
||||
|
||||
equals(copydata, 1) {
|
||||
for(dir, DATACOLLECTIONS) {
|
||||
exists($$GCS_SOURCE_TREE/share/openpilotgcs/$$dir) {
|
||||
addCopyDirTarget($$dir, $$GCS_SOURCE_TREE/share/openpilotgcs, $$GCS_DATA_PATH)
|
||||
}
|
||||
}
|
||||
}
|
@ -52,7 +52,7 @@
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../src/plugins/coreplugin/generalsettings.cpp" line="+62"/>
|
||||
<location filename="../../../src/plugins/coreplugin/generalsettings.cpp" line="+64"/>
|
||||
<source>General</source>
|
||||
<translation>Général</translation>
|
||||
</message>
|
||||
@ -68,7 +68,7 @@
|
||||
<translation><Langue Système></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+112"/>
|
||||
<location line="+120"/>
|
||||
<source>Variables</source>
|
||||
<translation>Variables</translation>
|
||||
</message>
|
||||
@ -103,22 +103,35 @@
|
||||
<translation>Sélectionner automatiquement un périphérique USB OpenPilot :</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location/>
|
||||
<source>Use UDP Mirror</source>
|
||||
<translatorcomment>Typo need ":" or remove on others</translatorcomment>
|
||||
<translation>Utiliser Miroir UDP</translation>
|
||||
<translation type="vanished">Utiliser Miroir UDP</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location/>
|
||||
<source>Expert Mode</source>
|
||||
<translatorcomment>Typo need ":" or remove on others</translatorcomment>
|
||||
<translation>Mode Expert</translation>
|
||||
<translation type="vanished">Mode Expert</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location/>
|
||||
<source>Language:</source>
|
||||
<translation>Langue :</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location/>
|
||||
<source>Expert Mode:</source>
|
||||
<translation>Mode Expert :</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location/>
|
||||
<source>Contribute usage statistics:</source>
|
||||
<translation type="unfinished">Contribuer aux statistiques d'utilisation :</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location/>
|
||||
<source>Use UDP Mirror:</source>
|
||||
<translation>Utiliser Miroir UDP :</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Core::Internal::MainWindow</name>
|
||||
@ -16173,7 +16186,7 @@ IMPORTANT : Ces nouveaux paramètres ne sont pas encore enregistrés sur la cart
|
||||
<context>
|
||||
<name>ConfigCcpmWidget</name>
|
||||
<message>
|
||||
<location filename="../../../src/plugins/config/cfg_vehicletypes/configccpmwidget.cpp" line="+1081"/>
|
||||
<location filename="../../../src/plugins/config/cfg_vehicletypes/configccpmwidget.cpp" line="+1080"/>
|
||||
<source><h1>Swashplate Leveling Routine</h1></source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@ -16320,4 +16333,37 @@ Il est suggéré que si cela est une première configuration de votre contrôleu
|
||||
<translation>Réglages Actuels</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>UsageTrackerPlugin</name>
|
||||
<message>
|
||||
<location filename="../../../src/plugins/usagetracker/usagetrackerplugin.cpp" line="+80"/>
|
||||
<source>Usage feedback</source>
|
||||
<translation>Retour d'utilisation</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+2"/>
|
||||
<source>Yes, count me in</source>
|
||||
<translation>Oui, comptez sur moi</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+1"/>
|
||||
<source>No, I will not help</source>
|
||||
<translation>Non, je ne souhaite pas aider</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+1"/>
|
||||
<source>Openpilot GCS has a function to collect limited anonymous information about the usage of the application itself and the OpenPilot hardware connected to it.<p>The intention is to not include anything that can be considered sensitive or a threat to the users integrity. The collected information will be sent using a secure protocol to an OpenPilot web service and stored in a database for later analysis and statistical purposes.<br>No information will be sold or given to any third party. The sole purpose is to collect statistics about the usage of our software and hardware to enable us to make things better for you.<p>The following things are collected:<ul><li>Bootloader version</li><li>Firmware version, tag and git hash</li><li>OP Hardware type, revision and mcu serial number</li><li>Selected configuration parameters</li><li>GCS version</li><li>Operating system version and architecture</li><li>Current local time</li></ul>The information is collected only at the time when a board is connecting to GCS.<p>It is possible to enable or disable this functionality in the general settings part of the options for the GCS application at any time.<p>We need your help, with your feedback we know where to improve things and what platforms are in use. This is a community project that depends on people being involved.<br>Thank You for helping us making things better and for supporting OpenPilot!</source>
|
||||
<translation type="unfinished">Openpilot GCS possède une fonction qui permet de collecter les informations de manière anonyme sur l'utilisation de l'application en elle-même ainsi que le matériel OpenPilot connecté dessus.<p>Il n'est pas question de collecter des informations sensibles ou pouvant représenter une menace pour l'intégrité des utilisateurs. Les informations collectées seront envoyées vers un site web OpenPilot en utilisant un protocole sécurisé et stockées dans une base de données pour une analyse et des statistiques ultérieures.<br>Aucune information ne sera vendue ou donnée à une quelconque tierce partie. Le seul but est de collecter des informations à propos de l'utilisation de notre logiciel / matériel pour nous permettre de l'améliorer.<p>Les éléments suivants sont collectés :<ul><li>Version bootloader</li><li>Version firmware, tag et git hash</li><li>Type de matériel OP, révision et numéro de série CPU</li><li>Paramètres de configuration sélectionnés</li><li>Version GCS</li><li>Système d'exploitation et architecture</li><li>Fuseau horaire</li></ul>Les informations sont collectées au moment de la connexion de la carte avec GCS.<p>Il est possible d'activer ou de désactiver cette fonctionnalité à tout moment dans le menu Options > Paramètres généraux de GCS.<p>Nous avons besoin de votre aide, avec votre participation nous connaîtrons où apporter des améliorations et quelle plateforme vous utilisez. C'est un projet communautaire qui dépend de l'implication des utilisateurs.<br>Merci de nous aider à rendre les choses meilleures et soutenir OpenPilot !</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+23"/>
|
||||
<source>&Don't show this message again.</source>
|
||||
<translation>&Ne pas afficher ce message à nouveau.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location line="+148"/>
|
||||
<source>Unknown</source>
|
||||
<translation>Inconnu</translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
|
@ -1,26 +1,5 @@
|
||||
include(../openpilotgcs.pri)
|
||||
|
||||
TEMPLATE = subdirs
|
||||
SUBDIRS = openpilotgcs/translations
|
||||
|
||||
DATACOLLECTIONS = cloudconfig default_configurations dials models pfd sounds diagrams mapicons stylesheets
|
||||
SUBDIRS = openpilotgcs/translations copydata
|
||||
|
||||
equals(copydata, 1) {
|
||||
for(dir, DATACOLLECTIONS) {
|
||||
exists($$GCS_SOURCE_TREE/share/openpilotgcs/$$dir) {
|
||||
# Qt make macros (CHK_DIR_EXISTS, COPY_DIR, etc) have different syntax. They cannot be used
|
||||
# reliably to copy subdirectories in two different Windows environments (bash and cmd/QtCreator).
|
||||
# So undocumented QMAKE_SH variable is used to find out the real environment.
|
||||
!isEmpty(QMAKE_SH) {
|
||||
# sh environment (including Windows bash)
|
||||
data_copy.commands += $(MKDIR) $$targetPath(\"$$GCS_DATA_PATH/$$dir\") $$addNewline()
|
||||
data_copy.commands += $(COPY_DIR) $$targetPath(\"$$GCS_SOURCE_TREE/share/openpilotgcs/$$dir\") $$targetPath(\"$$GCS_DATA_PATH/\") $$addNewline()
|
||||
} else {
|
||||
# native Windows cmd environment
|
||||
data_copy.commands += $(COPY_DIR) $$targetPath(\"$$GCS_SOURCE_TREE/share/openpilotgcs/$$dir\") $$targetPath(\"$$GCS_DATA_PATH/$$dir\") $$addNewline()
|
||||
}
|
||||
}
|
||||
}
|
||||
data_copy.target = FORCE
|
||||
QMAKE_EXTRA_TARGETS += data_copy
|
||||
}
|
||||
copydata.file = copydata.pro
|
||||
|
@ -1,18 +1,10 @@
|
||||
equals(copydata, 1) {
|
||||
|
||||
win32 {
|
||||
# copy SDL DLL
|
||||
SDL_DLLS = \
|
||||
SDL.dll
|
||||
for(dll, SDL_DLLS) {
|
||||
data_copy.commands += $(COPY_FILE) $$targetPath(\"$${SDL_DIR}/bin/$$dll\") $$targetPath(\"$$GCS_APP_PATH/$$dll\") $$addNewline()
|
||||
addCopyFileTarget($${dll},$${SDL_DIR}/bin,$${GCS_APP_PATH})
|
||||
}
|
||||
|
||||
# add make target
|
||||
POST_TARGETDEPS += copydata
|
||||
|
||||
data_copy.target = copydata
|
||||
QMAKE_EXTRA_TARGETS += data_copy
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -674,7 +674,6 @@ void ConfigCcpmWidget::UpdateMixer()
|
||||
if (throwConfigError(QString("HeliCP"))) {
|
||||
return;
|
||||
}
|
||||
|
||||
GUIConfigDataUnion config = getConfigData();
|
||||
|
||||
useCCPM = !(config.heli.ccpmCollectivePassthroughState || !config.heli.ccpmLinkCyclicState);
|
||||
@ -1567,28 +1566,28 @@ bool ConfigCcpmWidget::throwConfigError(QString airframeType)
|
||||
|
||||
bool error = false;
|
||||
|
||||
if ((m_aircraft->ccpmServoWChannel->currentIndex() == 0) && (m_aircraft->ccpmServoWChannel->isEnabled())) {
|
||||
if ((m_aircraft->ccpmServoWChannel->currentIndex() == 0) && (m_aircraft->ccpmServoWChannel->isVisible())) {
|
||||
m_aircraft->ccpmServoWLabel->setText("<font color=red>" + m_aircraft->ccpmServoWLabel->text() + "</font>");
|
||||
error = true;
|
||||
} else {
|
||||
m_aircraft->ccpmServoWLabel->setText(QTextEdit(m_aircraft->ccpmServoWLabel->text()).toPlainText());
|
||||
}
|
||||
|
||||
if ((m_aircraft->ccpmServoXChannel->currentIndex() == 0) && (m_aircraft->ccpmServoXChannel->isEnabled())) {
|
||||
if ((m_aircraft->ccpmServoXChannel->currentIndex() == 0) && (m_aircraft->ccpmServoXChannel->isVisible())) {
|
||||
m_aircraft->ccpmServoXLabel->setText("<font color=red>" + m_aircraft->ccpmServoXLabel->text() + "</font>");
|
||||
error = true;
|
||||
} else {
|
||||
m_aircraft->ccpmServoXLabel->setText(QTextEdit(m_aircraft->ccpmServoXLabel->text()).toPlainText());
|
||||
}
|
||||
|
||||
if ((m_aircraft->ccpmServoYChannel->currentIndex() == 0) && (m_aircraft->ccpmServoYChannel->isEnabled())) {
|
||||
if ((m_aircraft->ccpmServoYChannel->currentIndex() == 0) && (m_aircraft->ccpmServoYChannel->isVisible())) {
|
||||
m_aircraft->ccpmServoYLabel->setText("<font color=red>" + m_aircraft->ccpmServoYLabel->text() + "</font>");
|
||||
error = true;
|
||||
} else {
|
||||
m_aircraft->ccpmServoYLabel->setText(QTextEdit(m_aircraft->ccpmServoYLabel->text()).toPlainText());
|
||||
}
|
||||
|
||||
if ((m_aircraft->ccpmServoZChannel->currentIndex() == 0) && (m_aircraft->ccpmServoZChannel->isEnabled())) {
|
||||
if ((m_aircraft->ccpmServoZChannel->currentIndex() == 0) && (m_aircraft->ccpmServoZChannel->isVisible())) {
|
||||
m_aircraft->ccpmServoZLabel->setText("<font color=red>" + m_aircraft->ccpmServoZLabel->text() + "</font>");
|
||||
error = true;
|
||||
} else {
|
||||
|
@ -42,10 +42,13 @@
|
||||
#include <utils/stylehelper.h>
|
||||
#include <QMessageBox>
|
||||
|
||||
#define ACCESS_MIN_MOVE -3
|
||||
#define ACCESS_MAX_MOVE 3
|
||||
#define STICK_MIN_MOVE -8
|
||||
#define STICK_MAX_MOVE 8
|
||||
#define ACCESS_MIN_MOVE -3
|
||||
#define ACCESS_MAX_MOVE 3
|
||||
#define STICK_MIN_MOVE -8
|
||||
#define STICK_MAX_MOVE 8
|
||||
|
||||
#define CHANNEL_NUMBER_NONE 0
|
||||
#define DEFAULT_FLIGHT_MODE_NUMBER 3
|
||||
|
||||
ConfigInputWidget::ConfigInputWidget(QWidget *parent) :
|
||||
ConfigTaskWidget(parent),
|
||||
@ -416,18 +419,18 @@ void ConfigInputWidget::goToWizard()
|
||||
// chooses a different TX type (which could otherwise result in
|
||||
// unexpected TX channels being enabled)
|
||||
manualSettingsData = manualSettingsObj->getData();
|
||||
previousManualSettingsData = manualSettingsData;
|
||||
memento.manualSettingsData = manualSettingsData;
|
||||
flightModeSettingsData = flightModeSettingsObj->getData();
|
||||
previousFlightModeSettingsData = flightModeSettingsData;
|
||||
memento.flightModeSettingsData = flightModeSettingsData;
|
||||
flightModeSettingsData.Arming = FlightModeSettings::ARMING_ALWAYSDISARMED;
|
||||
flightModeSettingsObj->setData(flightModeSettingsData);
|
||||
// Stash actuatorSettings
|
||||
actuatorSettingsData = actuatorSettingsObj->getData();
|
||||
previousActuatorSettingsData = actuatorSettingsData;
|
||||
memento.actuatorSettingsData = actuatorSettingsData;
|
||||
|
||||
// Stash systemSettings
|
||||
systemSettingsData = systemSettingsObj->getData();
|
||||
previousSystemSettingsData = systemSettingsData;
|
||||
memento.systemSettingsData = systemSettingsData;
|
||||
|
||||
// Now reset channel and actuator settings (disable outputs)
|
||||
resetChannelSettings();
|
||||
@ -469,10 +472,10 @@ void ConfigInputWidget::wzCancel()
|
||||
ui->stackedWidget->setCurrentIndex(0);
|
||||
|
||||
// Load settings back from beginning of wizard
|
||||
manualSettingsObj->setData(previousManualSettingsData);
|
||||
flightModeSettingsObj->setData(previousFlightModeSettingsData);
|
||||
actuatorSettingsObj->setData(previousActuatorSettingsData);
|
||||
systemSettingsObj->setData(previousSystemSettingsData);
|
||||
manualSettingsObj->setData(memento.manualSettingsData);
|
||||
flightModeSettingsObj->setData(memento.flightModeSettingsData);
|
||||
actuatorSettingsObj->setData(memento.actuatorSettingsData);
|
||||
systemSettingsObj->setData(memento.systemSettingsData);
|
||||
}
|
||||
|
||||
void ConfigInputWidget::registerControlActivity()
|
||||
@ -555,7 +558,7 @@ void ConfigInputWidget::wzNext()
|
||||
restoreMdata();
|
||||
|
||||
// Load actuator settings back from beginning of wizard
|
||||
actuatorSettingsObj->setData(previousActuatorSettingsData);
|
||||
actuatorSettingsObj->setData(memento.actuatorSettingsData);
|
||||
|
||||
// Force flight mode neutral to middle and Throttle neutral at 4%
|
||||
adjustSpecialNeutrals();
|
||||
@ -802,6 +805,12 @@ void ConfigInputWidget::wizardTearDownStep(enum wizardSteps step)
|
||||
disconnect(receiverActivityObj, SIGNAL(objectUpdated(UAVObject *)), this, SLOT(identifyControls()));
|
||||
wizardUi->wzNext->setEnabled(true);
|
||||
setTxMovement(nothing);
|
||||
/* If flight mode stick isn't identified, force flight mode number to be 1 */
|
||||
manualSettingsData = manualSettingsObj->getData();
|
||||
if (manualSettingsData.ChannelGroups[ManualControlSettings::CHANNELNUMBER_FLIGHTMODE] ==
|
||||
ManualControlSettings::CHANNELGROUPS_NONE) {
|
||||
forceOneFlightMode();
|
||||
}
|
||||
break;
|
||||
case wizardIdentifyCenter:
|
||||
manualCommandData = manualCommandObj->getData();
|
||||
@ -882,21 +891,32 @@ void ConfigInputWidget::restoreMdata()
|
||||
*/
|
||||
void ConfigInputWidget::setChannel(int newChan)
|
||||
{
|
||||
bool canBeSkipped = false;
|
||||
|
||||
if (newChan == ManualControlSettings::CHANNELGROUPS_COLLECTIVE) {
|
||||
wizardUi->identifyStickInstructions->setText(QString(tr("Please enable throttle hold mode.\n\nMove the Collective Pitch stick.")));
|
||||
wizardUi->identifyStickInstructions->setText(QString(tr("<p>Please enable throttle hold mode.</p>"
|
||||
"<p>Move the Collective Pitch stick.</p>")));
|
||||
} else if (newChan == ManualControlSettings::CHANNELGROUPS_FLIGHTMODE) {
|
||||
wizardUi->identifyStickInstructions->setText(QString(tr("Please toggle the Flight Mode switch.\n\nFor switches you may have to repeat this rapidly.")));
|
||||
wizardUi->identifyStickInstructions->setText(QString(tr("<p>Please toggle the Flight Mode switch.</p>"
|
||||
"<p>For switches you may have to repeat this rapidly.</p>"
|
||||
"<p>Alternatively, you can click Next to skip this channel, but you will get only <b>ONE</b> Flight Mode.</p>")));
|
||||
canBeSkipped = true;
|
||||
} else if ((transmitterType == heli) && (newChan == ManualControlSettings::CHANNELGROUPS_THROTTLE)) {
|
||||
wizardUi->identifyStickInstructions->setText(QString(tr("Please disable throttle hold mode.\n\nMove the Throttle stick.")));
|
||||
wizardUi->identifyStickInstructions->setText(QString(tr("<p>Please disable throttle hold mode.</p>"
|
||||
"<p>Move the Throttle stick.</p>")));
|
||||
} else {
|
||||
wizardUi->identifyStickInstructions->setText(QString(tr("Please move each control one at a time according to the instructions and picture below.\n\n"
|
||||
"Move the %1 stick.")).arg(manualSettingsObj->getField("ChannelGroups")->getElementNames().at(newChan)));
|
||||
wizardUi->identifyStickInstructions->setText(QString(tr("<p>Please move each control one at a time according to the instructions and picture below.</p>"
|
||||
"<p>Move the %1 stick.</p>")).arg(manualSettingsObj->getField("ChannelGroups")->getElementNames().at(newChan)));
|
||||
}
|
||||
|
||||
if (manualSettingsObj->getField("ChannelGroups")->getElementNames().at(newChan).contains("Accessory")) {
|
||||
wizardUi->identifyStickInstructions->setText(wizardUi->identifyStickInstructions->text() + tr("<p>Alternatively, click Next to skip this channel.</p>"));
|
||||
canBeSkipped = true;
|
||||
}
|
||||
|
||||
if (canBeSkipped) {
|
||||
wizardUi->wzNext->setEnabled(true);
|
||||
wizardUi->wzNext->setText(tr("Next / Skip"));
|
||||
wizardUi->identifyStickInstructions->setText(wizardUi->identifyStickInstructions->text() + tr(" Alternatively, click Next to skip this channel."));
|
||||
} else {
|
||||
wizardUi->wzNext->setEnabled(false);
|
||||
}
|
||||
@ -1674,7 +1694,7 @@ void ConfigInputWidget::simpleCalibration(bool enable)
|
||||
|
||||
// Stash actuatorSettings
|
||||
actuatorSettingsData = actuatorSettingsObj->getData();
|
||||
previousActuatorSettingsData = actuatorSettingsData;
|
||||
memento.actuatorSettingsData = actuatorSettingsData;
|
||||
|
||||
// Disable all actuators
|
||||
resetActuatorSettings();
|
||||
@ -1720,7 +1740,7 @@ void ConfigInputWidget::simpleCalibration(bool enable)
|
||||
manualSettingsObj->setData(manualSettingsData);
|
||||
|
||||
// Load actuator settings back from beginning of manual calibration
|
||||
actuatorSettingsObj->setData(previousActuatorSettingsData);
|
||||
actuatorSettingsObj->setData(memento.actuatorSettingsData);
|
||||
|
||||
ui->configurationWizard->setEnabled(true);
|
||||
ui->saveRCInputToRAM->setEnabled(true);
|
||||
@ -1778,9 +1798,10 @@ void ConfigInputWidget::resetChannelSettings()
|
||||
{
|
||||
manualSettingsData = manualSettingsObj->getData();
|
||||
// Clear all channel data : Channel Type (PPM,PWM..) and Number
|
||||
for (unsigned int channel = 0; channel < 9; channel++) {
|
||||
for (unsigned int channel = 0; channel < ManualControlSettings::CHANNELNUMBER_NUMELEM; channel++) {
|
||||
manualSettingsData.ChannelGroups[channel] = ManualControlSettings::CHANNELGROUPS_NONE;
|
||||
manualSettingsData.ChannelNumber[channel] = 0;
|
||||
manualSettingsData.ChannelNumber[channel] = CHANNEL_NUMBER_NONE;
|
||||
manualSettingsData.FlightModeNumber = DEFAULT_FLIGHT_MODE_NUMBER;
|
||||
manualSettingsObj->setData(manualSettingsData);
|
||||
}
|
||||
}
|
||||
@ -1819,7 +1840,7 @@ void ConfigInputWidget::resetActuatorSettings()
|
||||
|
||||
void ConfigInputWidget::forceOneFlightMode()
|
||||
{
|
||||
manualCommandData = manualCommandObj->getData();
|
||||
manualSettingsData = manualSettingsObj->getData();
|
||||
manualSettingsData.FlightModeNumber = 1;
|
||||
manualSettingsObj->setData(manualSettingsData);
|
||||
}
|
||||
|
@ -128,21 +128,25 @@ private:
|
||||
|
||||
ManualControlSettings *manualSettingsObj;
|
||||
ManualControlSettings::DataFields manualSettingsData;
|
||||
ManualControlSettings::DataFields previousManualSettingsData;
|
||||
|
||||
ActuatorSettings *actuatorSettingsObj;
|
||||
ActuatorSettings::DataFields actuatorSettingsData;
|
||||
ActuatorSettings::DataFields previousActuatorSettingsData;
|
||||
|
||||
FlightModeSettings *flightModeSettingsObj;
|
||||
FlightModeSettings::DataFields flightModeSettingsData;
|
||||
FlightModeSettings::DataFields previousFlightModeSettingsData;
|
||||
ReceiverActivity *receiverActivityObj;
|
||||
ReceiverActivity::DataFields receiverActivityData;
|
||||
|
||||
SystemSettings *systemSettingsObj;
|
||||
SystemSettings::DataFields systemSettingsData;
|
||||
SystemSettings::DataFields previousSystemSettingsData;
|
||||
|
||||
typedef struct {
|
||||
ManualControlSettings::DataFields manualSettingsData;
|
||||
ActuatorSettings::DataFields actuatorSettingsData;
|
||||
FlightModeSettings::DataFields flightModeSettingsData;
|
||||
SystemSettings::DataFields systemSettingsData;
|
||||
} Memento;
|
||||
Memento memento;
|
||||
|
||||
QSvgRenderer *m_renderer;
|
||||
|
||||
|
@ -49,6 +49,8 @@ GeneralSettings::GeneralSettings() :
|
||||
m_autoSelect(true),
|
||||
m_useUDPMirror(false),
|
||||
m_useExpertMode(false),
|
||||
m_collectUsageData(true),
|
||||
m_showUsageDataDisclaimer(true),
|
||||
m_dialog(0)
|
||||
{}
|
||||
|
||||
@ -125,6 +127,7 @@ QWidget *GeneralSettings::createPage(QWidget *parent)
|
||||
m_page->checkAutoSelect->setChecked(m_autoSelect);
|
||||
m_page->cbUseUDPMirror->setChecked(m_useUDPMirror);
|
||||
m_page->cbExpertMode->setChecked(m_useExpertMode);
|
||||
m_page->cbUsageData->setChecked(m_collectUsageData);
|
||||
m_page->colorButton->setColor(StyleHelper::baseColor());
|
||||
|
||||
connect(m_page->resetButton, SIGNAL(clicked()), this, SLOT(resetInterfaceColor()));
|
||||
@ -145,6 +148,7 @@ void GeneralSettings::apply()
|
||||
m_useExpertMode = m_page->cbExpertMode->isChecked();
|
||||
m_autoConnect = m_page->checkAutoConnect->isChecked();
|
||||
m_autoSelect = m_page->checkAutoSelect->isChecked();
|
||||
setCollectUsageData(m_page->cbUsageData->isChecked());
|
||||
}
|
||||
|
||||
void GeneralSettings::finish()
|
||||
@ -155,12 +159,15 @@ void GeneralSettings::finish()
|
||||
void GeneralSettings::readSettings(QSettings *qs)
|
||||
{
|
||||
qs->beginGroup(QLatin1String("General"));
|
||||
m_language = qs->value(QLatin1String("OverrideLanguage"), QLocale::system().name()).toString();
|
||||
m_language = qs->value(QLatin1String("OverrideLanguage"), QLocale::system().name()).toString();
|
||||
m_saveSettingsOnExit = qs->value(QLatin1String("SaveSettingsOnExit"), m_saveSettingsOnExit).toBool();
|
||||
m_autoConnect = qs->value(QLatin1String("AutoConnect"), m_autoConnect).toBool();
|
||||
m_autoSelect = qs->value(QLatin1String("AutoSelect"), m_autoSelect).toBool();
|
||||
m_useUDPMirror = qs->value(QLatin1String("UDPMirror"), m_useUDPMirror).toBool();
|
||||
m_useExpertMode = qs->value(QLatin1String("ExpertMode"), m_useExpertMode).toBool();
|
||||
m_autoConnect = qs->value(QLatin1String("AutoConnect"), m_autoConnect).toBool();
|
||||
m_autoSelect = qs->value(QLatin1String("AutoSelect"), m_autoSelect).toBool();
|
||||
m_useUDPMirror = qs->value(QLatin1String("UDPMirror"), m_useUDPMirror).toBool();
|
||||
m_useExpertMode = qs->value(QLatin1String("ExpertMode"), m_useExpertMode).toBool();
|
||||
m_collectUsageData = qs->value(QLatin1String("CollectUsageData"), m_collectUsageData).toBool();
|
||||
m_showUsageDataDisclaimer = qs->value(QLatin1String("ShowUsageDataDisclaimer"), m_showUsageDataDisclaimer).toBool();
|
||||
m_lastUsageHash = qs->value(QLatin1String("LastUsageHash"), m_lastUsageHash).toString();
|
||||
qs->endGroup();
|
||||
}
|
||||
|
||||
@ -179,6 +186,9 @@ void GeneralSettings::saveSettings(QSettings *qs)
|
||||
qs->setValue(QLatin1String("AutoSelect"), m_autoSelect);
|
||||
qs->setValue(QLatin1String("UDPMirror"), m_useUDPMirror);
|
||||
qs->setValue(QLatin1String("ExpertMode"), m_useExpertMode);
|
||||
qs->setValue(QLatin1String("CollectUsageData"), m_collectUsageData);
|
||||
qs->setValue(QLatin1String("ShowUsageDataDisclaimer"), m_showUsageDataDisclaimer);
|
||||
qs->setValue(QLatin1String("LastUsageHash"), m_lastUsageHash);
|
||||
qs->endGroup();
|
||||
}
|
||||
|
||||
@ -249,11 +259,44 @@ bool GeneralSettings::useUDPMirror() const
|
||||
return m_useUDPMirror;
|
||||
}
|
||||
|
||||
bool GeneralSettings::collectUsageData() const
|
||||
{
|
||||
return m_collectUsageData;
|
||||
}
|
||||
|
||||
bool GeneralSettings::showUsageDataDisclaimer() const
|
||||
{
|
||||
return m_showUsageDataDisclaimer;
|
||||
}
|
||||
|
||||
QString GeneralSettings::lastUsageHash() const
|
||||
{
|
||||
return m_lastUsageHash;
|
||||
}
|
||||
|
||||
bool GeneralSettings::useExpertMode() const
|
||||
{
|
||||
return m_useExpertMode;
|
||||
}
|
||||
|
||||
bool GeneralSettings::setCollectUsageData(bool collect)
|
||||
{
|
||||
if (collect && collect != m_collectUsageData) {
|
||||
setShowUsageDataDisclaimer(true);
|
||||
}
|
||||
m_collectUsageData = collect;
|
||||
}
|
||||
|
||||
bool GeneralSettings::setShowUsageDataDisclaimer(bool show)
|
||||
{
|
||||
m_showUsageDataDisclaimer = show;
|
||||
}
|
||||
|
||||
void GeneralSettings::setLastUsageHash(QString hash)
|
||||
{
|
||||
m_lastUsageHash = hash;
|
||||
}
|
||||
|
||||
void GeneralSettings::slotAutoConnect(int value)
|
||||
{
|
||||
if (value == Qt::Checked) {
|
||||
|
@ -57,10 +57,15 @@ public:
|
||||
bool autoConnect() const;
|
||||
bool autoSelect() const;
|
||||
bool useUDPMirror() const;
|
||||
bool collectUsageData() const;
|
||||
bool showUsageDataDisclaimer() const;
|
||||
QString lastUsageHash() const;
|
||||
void readSettings(QSettings *qs);
|
||||
void saveSettings(QSettings *qs);
|
||||
bool useExpertMode() const;
|
||||
signals:
|
||||
bool setCollectUsageData(bool collect);
|
||||
bool setShowUsageDataDisclaimer(bool show);
|
||||
void setLastUsageHash(QString hash);
|
||||
|
||||
private slots:
|
||||
void resetInterfaceColor();
|
||||
@ -79,6 +84,9 @@ private:
|
||||
bool m_autoSelect;
|
||||
bool m_useUDPMirror;
|
||||
bool m_useExpertMode;
|
||||
bool m_collectUsageData;
|
||||
bool m_showUsageDataDisclaimer;
|
||||
QString m_lastUsageHash;
|
||||
QPointer<QWidget> m_dialog;
|
||||
QList<QTextCodec *> m_codecs;
|
||||
};
|
||||
|
@ -11,7 +11,16 @@
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="margin">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
@ -20,17 +29,73 @@
|
||||
<string>General settings</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="colorLabel">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>User interface color:</string>
|
||||
<string>Language:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<item row="14" column="0">
|
||||
<widget class="QLabel" name="labelExpert">
|
||||
<property name="text">
|
||||
<string>Expert Mode:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="2">
|
||||
<widget class="QCheckBox" name="cbUseUDPMirror">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="2">
|
||||
<widget class="QCheckBox" name="checkAutoSelect">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Automatically connect an OpenPilot USB device:</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="2">
|
||||
<widget class="QCheckBox" name="checkBoxSaveOnExit">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<property name="margin">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="1">
|
||||
@ -82,46 +147,46 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="colorLabel">
|
||||
<property name="text">
|
||||
<string>User interface color:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="0">
|
||||
<widget class="QLabel" name="labelExpert_2">
|
||||
<property name="text">
|
||||
<string>Contribute usage statistics:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="2">
|
||||
<widget class="QWidget" name="widget_2" native="true">
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<property name="margin">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<widget class="QCheckBox" name="checkBoxSaveOnExit">
|
||||
<item row="14" column="2">
|
||||
<widget class="QCheckBox" name="cbExpertMode">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Save configuration settings on exit:</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Automatically connect an OpenPilot USB device:</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="1">
|
||||
<item row="11" column="2">
|
||||
<widget class="QCheckBox" name="checkAutoConnect">
|
||||
<property name="text">
|
||||
<string/>
|
||||
@ -131,58 +196,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Automatically select an OpenPilot USB device:</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="1">
|
||||
<widget class="QCheckBox" name="checkAutoSelect">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="1">
|
||||
<widget class="QCheckBox" name="cbUseUDPMirror">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="0">
|
||||
<widget class="QLabel" name="labelUDP">
|
||||
<property name="text">
|
||||
<string>Use UDP Mirror</string>
|
||||
<string>Use UDP Mirror:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="0">
|
||||
<widget class="QLabel" name="labelExpert">
|
||||
<property name="text">
|
||||
<string>Expert Mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="1">
|
||||
<widget class="QCheckBox" name="cbExpertMode">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<item row="0" column="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QComboBox" name="languageBox"/>
|
||||
@ -202,10 +223,33 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Language:</string>
|
||||
<string>Save configuration settings on exit:</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Automatically select an OpenPilot USB device:</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="2">
|
||||
<widget class="QCheckBox" name="cbUsageData">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -35,8 +35,6 @@ equals(copydata, 1) {
|
||||
# Windows release only
|
||||
win32:CONFIG(release, debug|release) {
|
||||
|
||||
data_copy.commands += -@$(MKDIR) $$targetPath(\"$$PLUGIN_DIR\") $$addNewline()
|
||||
|
||||
# resources and sample configuration
|
||||
PLUGIN_RESOURCES = \
|
||||
cc_off.tga \
|
||||
@ -46,7 +44,7 @@ equals(copydata, 1) {
|
||||
cc_plugin.ini \
|
||||
plugin.txt
|
||||
for(res, PLUGIN_RESOURCES) {
|
||||
data_copy.commands += $(COPY_FILE) $$targetPath(\"$$RES_DIR/$$res\") $$targetPath(\"$$PLUGIN_DIR/$$res\") $$addNewline()
|
||||
addCopyFileTarget($${res},$${RES_DIR},$${PLUGIN_DIR})
|
||||
}
|
||||
|
||||
# Qt DLLs
|
||||
@ -54,7 +52,7 @@ equals(copydata, 1) {
|
||||
Qt5Core.dll \
|
||||
Qt5Network.dll
|
||||
for(dll, QT_DLLS) {
|
||||
data_copy.commands += $(COPY_FILE) $$targetPath(\"$$[QT_INSTALL_BINS]/$$dll\") $$targetPath(\"$$SIM_DIR/$$dll\") $$addNewline()
|
||||
addCopyFileTarget($${dll},$$[QT_INSTALL_BINS],$${SIM_DIR})
|
||||
}
|
||||
|
||||
# MinGW DLLs
|
||||
@ -62,10 +60,7 @@ equals(copydata, 1) {
|
||||
# libgcc_s_dw2-1.dll \
|
||||
# mingwm10.dll
|
||||
#for(dll, MINGW_DLLS) {
|
||||
# data_copy.commands += $(COPY_FILE) $$targetPath(\"$$(QTMINGW)/$$dll\") $$targetPath(\"$$SIM_DIR/$$dll\") $$addNewline()
|
||||
# addCopyFileTarget($${dll},$$(QTMINGW),$${SIM_DIR})
|
||||
#}
|
||||
|
||||
data_copy.target = FORCE
|
||||
QMAKE_EXTRA_TARGETS += data_copy
|
||||
}
|
||||
}
|
||||
|
@ -252,3 +252,11 @@ plugin_flightlog.depends += plugin_uavobjects
|
||||
plugin_flightlog.depends += plugin_uavtalk
|
||||
SUBDIRS += plugin_flightlog
|
||||
|
||||
# Usage Tracker plugin
|
||||
plugin_usagetracker.subdir = usagetracker
|
||||
plugin_usagetracker.depends = plugin_coreplugin
|
||||
plugin_usagetracker.depends += plugin_uavobjects
|
||||
plugin_usagetracker.depends += plugin_uavtalk
|
||||
plugin_setupwizard.depends += plugin_uavobjectutil
|
||||
SUBDIRS += plugin_usagetracker
|
||||
|
||||
|
@ -0,0 +1,12 @@
|
||||
<plugin name="UsageTracker" version="1.0.0" compatVersion="1.0.0">
|
||||
<vendor>The OpenPilot Project</vendor>
|
||||
<copyright>(C) 2015 OpenPilot Project</copyright>
|
||||
<description>A plugin that tracks GCS usage</description>
|
||||
<url>http://www.openpilot.org</url>
|
||||
<dependencyList>
|
||||
<dependency name="Core" version="1.0.0"/>
|
||||
<dependency name="UAVTalk" version="1.0.0"/>
|
||||
<dependency name="UAVObjectUtil" version="1.0.0"/>
|
||||
<dependency name="UAVObjects" version="1.0.0"/>
|
||||
</dependencyList>
|
||||
</plugin>
|
@ -0,0 +1,16 @@
|
||||
|
||||
TEMPLATE = lib
|
||||
TARGET = UsageTracker
|
||||
QT += network
|
||||
|
||||
include(../../openpilotgcsplugin.pri)
|
||||
include(../../libs/version_info/version_info.pri)
|
||||
include(../../plugins/coreplugin/coreplugin.pri)
|
||||
include(../../plugins/uavobjects/uavobjects.pri)
|
||||
include(../../plugins/uavobjectutil/uavobjectutil.pri)
|
||||
include(../../plugins/uavtalk/uavtalk.pri)
|
||||
|
||||
HEADERS += usagetrackerplugin.h
|
||||
SOURCES += usagetrackerplugin.cpp
|
||||
|
||||
OTHER_FILES += usagetracker.pluginspec
|
@ -0,0 +1,280 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file usagetrackerplugin.cpp
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2015.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup UsageTrackerPlugin Usage Tracker Plugin
|
||||
* @{
|
||||
* @brief A plugin tracking GCS usage
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* 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 "usagetrackerplugin.h"
|
||||
#include <QtPlugin>
|
||||
#include <QStringList>
|
||||
#include <QtNetwork/QNetworkAccessManager>
|
||||
#include <QtNetwork/QNetworkRequest>
|
||||
#include <QtNetwork/QNetworkReply>
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
#include <QCheckBox>
|
||||
#include <QDebug>
|
||||
#include <QMessageBox>
|
||||
#include <uavobjectutil/devicedescriptorstruct.h>
|
||||
#include <uavobjectutil/uavobjectutilmanager.h>
|
||||
#include "version_info/version_info.h"
|
||||
#include "coreplugin/icore.h"
|
||||
#include <uavtalk/telemetrymanager.h>
|
||||
|
||||
UsageTrackerPlugin::UsageTrackerPlugin() :
|
||||
m_telemetryManager(NULL)
|
||||
{}
|
||||
|
||||
UsageTrackerPlugin::~UsageTrackerPlugin()
|
||||
{}
|
||||
|
||||
bool UsageTrackerPlugin::initialize(const QStringList & args, QString *errMsg)
|
||||
{
|
||||
Q_UNUSED(args);
|
||||
Q_UNUSED(errMsg);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void UsageTrackerPlugin::extensionsInitialized()
|
||||
{
|
||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
||||
|
||||
m_telemetryManager = pm->getObject<TelemetryManager>();
|
||||
connect(m_telemetryManager, SIGNAL(connected()), this, SLOT(onAutopilotConnect()));
|
||||
}
|
||||
|
||||
void UsageTrackerPlugin::shutdown()
|
||||
{
|
||||
if (m_telemetryManager != NULL) {
|
||||
disconnect(m_telemetryManager, SIGNAL(connected()), this, SLOT(onAutopilotConnect()));
|
||||
}
|
||||
}
|
||||
|
||||
void UsageTrackerPlugin::onAutopilotConnect()
|
||||
{
|
||||
Core::Internal::GeneralSettings *settings = getGeneralSettings();
|
||||
|
||||
if (settings->collectUsageData()) {
|
||||
if (settings->showUsageDataDisclaimer()) {
|
||||
QMessageBox message;
|
||||
message.setWindowTitle(tr("Usage feedback"));
|
||||
message.setIcon(QMessageBox::Information);
|
||||
message.addButton(tr("Yes, count me in"), QMessageBox::AcceptRole);
|
||||
message.addButton(tr("No, I will not help"), QMessageBox::RejectRole);
|
||||
message.setText(tr("Openpilot GCS has a function to collect limited anonymous information about "
|
||||
"the usage of the application itself and the OpenPilot hardware connected to it.<p>"
|
||||
"The intention is to not include anything that can be considered sensitive "
|
||||
"or a threat to the users integrity. The collected information will be sent "
|
||||
"using a secure protocol to an OpenPilot web service and stored in a database "
|
||||
"for later analysis and statistical purposes.<br>"
|
||||
"No information will be sold or given to any third party. The sole purpose is "
|
||||
"to collect statistics about the usage of our software and hardware to enable us "
|
||||
"to make things better for you.<p>"
|
||||
"The following things are collected:<ul>"
|
||||
"<li>Bootloader version</li>"
|
||||
"<li>Firmware version, tag and git hash</li>"
|
||||
"<li>OP Hardware type, revision and mcu serial number</li>"
|
||||
"<li>Selected configuration parameters</li>"
|
||||
"<li>GCS version</li>"
|
||||
"<li>Operating system version and architecture</li>"
|
||||
"<li>Current local time</li></ul>"
|
||||
"The information is collected only at the time when a board is connecting to GCS.<p>"
|
||||
"It is possible to enable or disable this functionality in the general "
|
||||
"settings part of the options for the GCS application at any time.<p>"
|
||||
"We need your help, with your feedback we know where to improve things and what "
|
||||
"platforms are in use. This is a community project that depends on people being involved.<br>"
|
||||
"Thank You for helping us making things better and for supporting OpenPilot!"));
|
||||
QCheckBox *disclaimerCb = new QCheckBox(tr("&Don't show this message again."));
|
||||
disclaimerCb->setChecked(true);
|
||||
message.setCheckBox(disclaimerCb);
|
||||
if (message.exec() != QMessageBox::AcceptRole) {
|
||||
settings->setCollectUsageData(false);
|
||||
settings->setShowUsageDataDisclaimer(!message.checkBox()->isChecked());
|
||||
return;
|
||||
} else {
|
||||
settings->setCollectUsageData(true);
|
||||
settings->setShowUsageDataDisclaimer(!message.checkBox()->isChecked());
|
||||
}
|
||||
}
|
||||
QTimer::singleShot(1000, this, SLOT(trackUsage()));
|
||||
}
|
||||
}
|
||||
|
||||
void UsageTrackerPlugin::trackUsage()
|
||||
{
|
||||
QMap<QString, QString> parameters;
|
||||
collectUsageParameters(parameters);
|
||||
|
||||
QUrlQuery query;
|
||||
QMapIterator<QString, QString> iter(parameters);
|
||||
while (iter.hasNext()) {
|
||||
iter.next();
|
||||
query.addQueryItem(iter.key(), iter.value());
|
||||
}
|
||||
|
||||
// Add checksum
|
||||
QString hash = getQueryHash(query.toString());
|
||||
|
||||
if (shouldSend(hash)) {
|
||||
query.addQueryItem("hash", hash);
|
||||
|
||||
QUrl url("https://www.openpilot.org/opver?" + query.toString(QUrl::FullyEncoded));
|
||||
|
||||
QNetworkAccessManager *networkAccessManager = new QNetworkAccessManager();
|
||||
|
||||
// This will delete the network access manager instance when we're done
|
||||
connect(networkAccessManager, SIGNAL(finished(QNetworkReply *)), this, SLOT(onFinished(QNetworkReply *)));
|
||||
connect(networkAccessManager, SIGNAL(finished(QNetworkReply *)), networkAccessManager, SLOT(deleteLater()));
|
||||
|
||||
qDebug() << "Sending usage tracking as:" << url.toEncoded(QUrl::FullyEncoded);
|
||||
networkAccessManager->get(QNetworkRequest(QUrl(url.toEncoded(QUrl::FullyEncoded))));
|
||||
}
|
||||
}
|
||||
|
||||
void UsageTrackerPlugin::collectUsageParameters(QMap<QString, QString> ¶meters)
|
||||
{
|
||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
||||
UAVObjectUtilManager *utilMngr = pm->getObject<UAVObjectUtilManager>();
|
||||
|
||||
QByteArray description = utilMngr->getBoardDescription();
|
||||
deviceDescriptorStruct devDesc;
|
||||
|
||||
if (UAVObjectUtilManager::descriptionToStructure(description, devDesc)) {
|
||||
int boardModel = utilMngr->getBoardModel();
|
||||
parameters["board_type"] = "0x" + QString::number(boardModel, 16).toLower();
|
||||
parameters["board_serial"] = utilMngr->getBoardCPUSerial().toHex();
|
||||
parameters["bl_version"] = QString::number(utilMngr->getBootloaderRevision());
|
||||
parameters["fw_tag"] = devDesc.gitTag;
|
||||
parameters["fw_hash"] = devDesc.gitHash;
|
||||
parameters["os_version"] = QSysInfo::prettyProductName() + " " + QSysInfo::currentCpuArchitecture();
|
||||
parameters["os_threads"] = QString::number(QThread::idealThreadCount());
|
||||
parameters["os_timezone"] = QTimeZone::systemTimeZoneId();
|
||||
parameters["gcs_version"] = VersionInfo::revision();
|
||||
|
||||
// Configuration parameters
|
||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
||||
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
|
||||
|
||||
parameters["conf_receiver"] = getUAVFieldValue(objManager, "ManualControlSettings", "ChannelGroups", 0);
|
||||
parameters["conf_vehicle"] = getUAVFieldValue(objManager, "SystemSettings", "AirframeType");
|
||||
|
||||
if ((boardModel & 0xff00) == 0x0400) {
|
||||
// CopterControl family
|
||||
parameters["conf_rport"] = getUAVFieldValue(objManager, "HwSettings", "CC_RcvrPort");
|
||||
parameters["conf_mport"] = getUAVFieldValue(objManager, "HwSettings", "CC_MainPort");
|
||||
parameters["conf_fport"] = getUAVFieldValue(objManager, "HwSettings", "CC_FlexiPort");
|
||||
} else if ((boardModel & 0xff00) == 0x0900) {
|
||||
// Revolution family
|
||||
parameters["conf_rport"] = getUAVFieldValue(objManager, "HwSettings", "RM_RcvrPort");
|
||||
parameters["conf_mport"] = getUAVFieldValue(objManager, "HwSettings", "RM_MainPort");
|
||||
parameters["conf_fport"] = getUAVFieldValue(objManager, "HwSettings", "RM_FlexiPort");
|
||||
parameters["conf_fusion"] = getUAVFieldValue(objManager, "RevoSettings", "FusionAlgorithm");
|
||||
}
|
||||
|
||||
parameters["conf_uport"] = getUAVFieldValue(objManager, "HwSettings", "USB_HIDPort");
|
||||
parameters["conf_vport"] = getUAVFieldValue(objManager, "HwSettings", "USB_VCPPort");
|
||||
|
||||
parameters["conf_rotation"] = QString("[%1:%2:%3]")
|
||||
.arg(getUAVFieldValue(objManager, "AttitudeSettings", "BoardRotation", 0))
|
||||
.arg(getUAVFieldValue(objManager, "AttitudeSettings", "BoardRotation", 1))
|
||||
.arg(getUAVFieldValue(objManager, "AttitudeSettings", "BoardRotation", 2));
|
||||
parameters["conf_pidr"] = QString("[%1:%2:%3:%4][%5:%6:%7:%8][%9:%10:%11:%12]")
|
||||
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "RollRatePID", 0))
|
||||
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "RollRatePID", 1))
|
||||
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "RollRatePID", 2))
|
||||
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "RollRatePID", 3))
|
||||
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "PitchRatePID", 0))
|
||||
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "PitchRatePID", 1))
|
||||
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "PitchRatePID", 2))
|
||||
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "PitchRatePID", 3))
|
||||
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "YawRatePID", 0))
|
||||
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "YawRatePID", 1))
|
||||
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "YawRatePID", 2))
|
||||
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "YawRatePID", 3));
|
||||
parameters["conf_pia"] = QString("[%1:%2:%3][%4:%5:%6][%7:%8:%9]")
|
||||
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "RollPI", 0))
|
||||
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "RollPI", 1))
|
||||
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "RollPI", 2))
|
||||
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "PitchPI", 0))
|
||||
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "PitchPI", 1))
|
||||
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "PitchPI", 2))
|
||||
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "YawPI", 0))
|
||||
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "YawPI", 1))
|
||||
.arg(getUAVFieldValue(objManager, "StabilizationSettingsBank1", "YawPI", 2));
|
||||
|
||||
parameters["conf_tps"] = getUAVFieldValue(objManager, "StabilizationSettingsBank1", "EnableThrustPIDScaling");
|
||||
parameters["conf_piro"] = getUAVFieldValue(objManager, "StabilizationSettingsBank1", "EnablePiroComp");
|
||||
|
||||
parameters["conf_fmcount"] = getUAVFieldValue(objManager, "ManualControlSettings", "FlightModeNumber");
|
||||
parameters["conf_fmodes"] = QString("[%1:%2:%3]").arg(getUAVFieldValue(objManager, "FlightModeSettings", "FlightModePosition", 0))
|
||||
.arg(getUAVFieldValue(objManager, "FlightModeSettings", "FlightModePosition", 1))
|
||||
.arg(getUAVFieldValue(objManager, "FlightModeSettings", "FlightModePosition", 2));
|
||||
}
|
||||
}
|
||||
|
||||
void UsageTrackerPlugin::onFinished(QNetworkReply *reply)
|
||||
{
|
||||
if (reply->error() == QNetworkReply::NoError) {
|
||||
getGeneralSettings()->setLastUsageHash(m_lastHash);
|
||||
qDebug() << "Updated last usage hash to:" << m_lastHash;
|
||||
} else {
|
||||
qDebug() << "Usage tracking failed with:" << reply->errorString();
|
||||
}
|
||||
}
|
||||
|
||||
QString UsageTrackerPlugin::getUAVFieldValue(UAVObjectManager *objManager, QString objectName, QString fieldName, int index) const
|
||||
{
|
||||
UAVObject *object = objManager->getObject(objectName);
|
||||
|
||||
if (object != NULL) {
|
||||
UAVObjectField *field = object->getField(fieldName);
|
||||
if (field != NULL) {
|
||||
return field->getValue(index).toString();
|
||||
}
|
||||
}
|
||||
return tr("Unknown");
|
||||
}
|
||||
|
||||
QString UsageTrackerPlugin::getQueryHash(QString source) const
|
||||
{
|
||||
source += "OpenPilot Fuck Yeah!";
|
||||
return QString(QCryptographicHash::hash(QByteArray(source.toStdString().c_str()), QCryptographicHash::Md5).toHex());
|
||||
}
|
||||
|
||||
Core::Internal::GeneralSettings *UsageTrackerPlugin::getGeneralSettings() const
|
||||
{
|
||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
||||
Core::Internal::GeneralSettings *settings = pm->getObject<Core::Internal::GeneralSettings>();
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
bool UsageTrackerPlugin::shouldSend(const QString &hash)
|
||||
{
|
||||
if (getGeneralSettings()->lastUsageHash() == hash) {
|
||||
return false;
|
||||
} else {
|
||||
m_lastHash = hash;
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file usagetrackerplugin.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2015.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup UsageTrackerPlugin Usage Tracker Plugin
|
||||
* @{
|
||||
* @brief A plugin tracking GCS usage
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* 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 USAGETRACKERPLUGIN_H
|
||||
#define USAGETRACKERPLUGIN_H
|
||||
|
||||
#include <extensionsystem/iplugin.h>
|
||||
#include <coreplugin/generalsettings.h>
|
||||
|
||||
class TelemetryManager;
|
||||
class UAVObjectManager;
|
||||
class QNetworkReply;
|
||||
|
||||
class UsageTrackerPlugin : public ExtensionSystem::IPlugin {
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "OpenPilot.UsageTracker")
|
||||
public:
|
||||
UsageTrackerPlugin();
|
||||
~UsageTrackerPlugin();
|
||||
|
||||
void extensionsInitialized();
|
||||
bool initialize(const QStringList & arguments, QString *errorString);
|
||||
void shutdown();
|
||||
|
||||
private slots:
|
||||
void onAutopilotConnect();
|
||||
void trackUsage();
|
||||
void collectUsageParameters(QMap<QString, QString> ¶meters);
|
||||
void onFinished(QNetworkReply *reply);
|
||||
|
||||
private:
|
||||
TelemetryManager *m_telemetryManager;
|
||||
QString m_lastHash;
|
||||
QString getUAVFieldValue(UAVObjectManager *objManager, QString objectName, QString fieldName, int index = 0) const;
|
||||
QString getQueryHash(QString source) const;
|
||||
Core::Internal::GeneralSettings *getGeneralSettings() const;
|
||||
bool shouldSend(const QString &hash);
|
||||
};
|
||||
|
||||
#endif // USAGETRACKERPLUGIN_H
|
@ -3,7 +3,7 @@
|
||||
# Copyright (c) 2009-2013, The OpenPilot Team, http://www.openpilot.org
|
||||
#
|
||||
|
||||
TEMPLATE = subdirs
|
||||
TEMPLATE = aux
|
||||
|
||||
# Some handy defines
|
||||
defineReplace(targetPath) {
|
||||
@ -64,5 +64,6 @@ win32 {
|
||||
uavobjects.commands += -spec $$SPEC CONFIG+=$${BUILD_CONFIG} -r $$addNewline()
|
||||
}
|
||||
|
||||
uavobjects.target = FORCE
|
||||
uavobjects.depends = FORCE
|
||||
QMAKE_EXTRA_TARGETS += uavobjects
|
||||
PRE_TARGETDEPS += uavobjects
|
||||
|
@ -136,7 +136,7 @@ endef
|
||||
define OPFW_TEMPLATE
|
||||
FORCE:
|
||||
|
||||
$(1).firmware_info.c: $(1) $(ROOT_DIR)/flight/templates/firmware_info.c.template FORCE
|
||||
$(1).firmware_info.c: $(1) $(ROOT_DIR)/flight/templates/firmware_info.c.template $(ROOT_DIR)/shared/uavobjectdefinition
|
||||
@$(ECHO) $(MSG_FWINFO) $$(call toprel, $$@)
|
||||
$(V1) $(VERSION_INFO) \
|
||||
--template=$(ROOT_DIR)/flight/templates/firmware_info.c.template \
|
||||
|
@ -776,8 +776,8 @@ ifeq ($(UNAME), Windows)
|
||||
$(eval $(call TOOL_INSTALL_TEMPLATE,openssl,$(OPENSSL_DIR),$(OPENSSL_URL),,$(notdir $(OPENSSL_URL))))
|
||||
|
||||
ifeq ($(shell [ -d "$(OPENSSL_DIR)" ] && $(ECHO) "exists"), exists)
|
||||
export OPENSSL := "$(OPENSSL_DIR)/bin/openssl"
|
||||
export OPENSSL_DIR := "$(OPENSSL_DIR)"
|
||||
export OPENSSL := $(OPENSSL_DIR)/bin/openssl
|
||||
export OPENSSL_DIR
|
||||
else
|
||||
# not installed, hope it's in the path...
|
||||
# $(info $(EMPTY) WARNING $(call toprel, $(OPENSSL_DIR)) not found (make openssl_install), using system PATH)
|
||||
|
@ -316,7 +316,6 @@ SectionEnd
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${InSecResources} $(DESC_InSecResources)
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${InSecSounds} $(DESC_InSecSounds)
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${InSecLocalization} $(DESC_InSecLocalization)
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${InSecFirmware} $(DESC_InSecFirmware)
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${InSecUtilities} $(DESC_InSecUtilities)
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${InSecDrivers} $(DESC_InSecDrivers)
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${InSecInstallDrivers} $(DESC_InSecInstallDrivers)
|
||||
|
@ -23,8 +23,9 @@
|
||||
<!-- telemetry -->
|
||||
<elementname>TelemetryTx</elementname>
|
||||
<elementname>TelemetryRx</elementname>
|
||||
<!-- com -->
|
||||
<elementname>RadioTx</elementname>
|
||||
<elementname>RadioRx</elementname>
|
||||
<!-- com -->
|
||||
<elementname>Com2UsbBridge</elementname>
|
||||
<elementname>Usb2ComBridge</elementname>
|
||||
<!-- optional -->
|
||||
@ -54,8 +55,9 @@
|
||||
<!-- telemetry -->
|
||||
<elementname>TelemetryTx</elementname>
|
||||
<elementname>TelemetryRx</elementname>
|
||||
<!-- com -->
|
||||
<elementname>RadioTx</elementname>
|
||||
<elementname>RadioRx</elementname>
|
||||
<!-- com -->
|
||||
<elementname>Com2UsbBridge</elementname>
|
||||
<elementname>Usb2ComBridge</elementname>
|
||||
<!-- optional -->
|
||||
@ -89,8 +91,9 @@
|
||||
<!-- telemetry -->
|
||||
<elementname>TelemetryTx</elementname>
|
||||
<elementname>TelemetryRx</elementname>
|
||||
<!-- com -->
|
||||
<elementname>RadioTx</elementname>
|
||||
<elementname>RadioRx</elementname>
|
||||
<!-- com -->
|
||||
<elementname>Com2UsbBridge</elementname>
|
||||
<elementname>Usb2ComBridge</elementname>
|
||||
<!-- optional -->
|
||||
|
Loading…
x
Reference in New Issue
Block a user