updating code from Flying Laptop
This is the framework of Flying Laptop OBSW version A.13.0.
This commit is contained in:
parent
1d22a6c97e
commit
575f70ba03
202
LICENSE
Normal file
202
LICENSE
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
21
NOTICE
Normal file
21
NOTICE
Normal file
@ -0,0 +1,21 @@
|
||||
Flight Software Framework
|
||||
|
||||
The initial version of the Flight Software Framework was developed during
|
||||
the Flying Laptop Project by the Universität Stuttgart in coorporation
|
||||
with Airbus Defence and Space GmbH.
|
||||
|
||||
Copyrights in the Flight Software Framework are retained by their contributors.
|
||||
No copyright assignment is required to contribute to the Flight Software Framework.
|
||||
|
||||
Some files include explicit copyright notices and/or license notices.
|
||||
For full authorship information, see the version control history.
|
||||
|
||||
Except as otherwise noted (below and/or in individual files), the
|
||||
Flight Software Framework is licensed under the Apache License, Version 2.0.
|
||||
|
||||
The Flight Software Framework includes modules written by third parties.
|
||||
The following third party modules are included, and carry
|
||||
their own copyright notices and license terms:
|
||||
|
||||
under contrib/:
|
||||
* sgp4: sgp4 code developed by david vallado under public domain, see https://www.celestrak.com/publications/AIAA/2006-6753/
|
5
THANKYOU
5
THANKYOU
@ -1,5 +0,0 @@
|
||||
Besides Bastian Bätz and Ulrich Mohr, who were the main developers for Flying Laptop's Onboard Software, the following PhD Students contributed to the project:
|
||||
|
||||
Rouven Witt, who developed the FDIR concept and kept morale high as the team's Spaßbeauftragter.
|
||||
Marek Dittmar, who started work on the ACS code and later tried to keep the development in time.
|
||||
Nico Bucher, who performed software tests and as such was invaluable during the development.
|
@ -1,8 +1,7 @@
|
||||
|
||||
#include <framework/action/ActionHelper.h>
|
||||
#include <framework/action/HasActionsIF.h>
|
||||
#include <framework/objectmanager/ObjectManagerIF.h>
|
||||
ActionHelper::ActionHelper(HasActionsIF* setOwner, MessageQueue* useThisQueue) :
|
||||
ActionHelper::ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue) :
|
||||
owner(setOwner), queueToUse(useThisQueue), ipcStore(
|
||||
NULL) {
|
||||
}
|
||||
@ -41,6 +40,10 @@ void ActionHelper::finish(MessageQueueId_t reportTo, ActionId_t commandId, Retur
|
||||
queueToUse->sendMessage(reportTo, &reply);
|
||||
}
|
||||
|
||||
void ActionHelper::setQueueToUse(MessageQueueIF* queue) {
|
||||
queueToUse = queue;
|
||||
}
|
||||
|
||||
void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId,
|
||||
store_address_t dataAddress) {
|
||||
const uint8_t* dataPtr = NULL;
|
||||
@ -62,31 +65,38 @@ void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t act
|
||||
}
|
||||
}
|
||||
|
||||
void ActionHelper::reportData(MessageQueueId_t reportTo, ActionId_t replyId, SerializeIF* data) {
|
||||
ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo, ActionId_t replyId, SerializeIF* data, bool hideSender) {
|
||||
CommandMessage reply;
|
||||
store_address_t storeAddress;
|
||||
uint8_t *dataPtr;
|
||||
uint32_t maxSize = data->getSerializedSize();
|
||||
if (maxSize == 0) {
|
||||
return;
|
||||
//No error, there's simply nothing to report.
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
uint32_t size = 0;
|
||||
ReturnValue_t result = ipcStore->getFreeElement(&storeAddress, maxSize,
|
||||
&dataPtr);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
//TODO event?
|
||||
return;
|
||||
return result;
|
||||
}
|
||||
result = data->serialize(&dataPtr, &size, maxSize, true);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
ipcStore->deleteData(storeAddress);
|
||||
//TODO event?
|
||||
return;
|
||||
return result;
|
||||
}
|
||||
//We don't need to report the objectId, as we receive REQUESTED data before the completion success message.
|
||||
//True aperiodic replies need to be reported with another dedicated message.
|
||||
ActionMessage::setDataReply(&reply, replyId, storeAddress);
|
||||
if (queueToUse->sendMessage(reportTo, &reply) != HasReturnvaluesIF::RETURN_OK){
|
||||
|
||||
//TODO Service Implementation sucks at the moment
|
||||
if (hideSender){
|
||||
result = MessageQueueSenderIF::sendMessage(reportTo, &reply);
|
||||
} else {
|
||||
result = queueToUse->sendMessage(reportTo, &reply);
|
||||
}
|
||||
if ( result != HasReturnvaluesIF::RETURN_OK){
|
||||
ipcStore->deleteData(storeAddress);
|
||||
}
|
||||
//We don't neeed the objectId, as we receive REQUESTED data before the completion success message.
|
||||
//True aperiodic replies need to be reported with dedicated DH message.
|
||||
return result;
|
||||
}
|
||||
|
@ -1,25 +1,26 @@
|
||||
|
||||
#ifndef ACTIONHELPER_H_
|
||||
#define ACTIONHELPER_H_
|
||||
|
||||
#include <framework/action/ActionMessage.h>
|
||||
#include <framework/serialize/SerializeIF.h>
|
||||
#include <framework/ipc/MessageQueueIF.h>
|
||||
|
||||
class HasActionsIF;
|
||||
//TODO: Change MessageQueueId usage.
|
||||
|
||||
class ActionHelper {
|
||||
public:
|
||||
ActionHelper(HasActionsIF* setOwner, MessageQueue* useThisQueue);
|
||||
ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue);
|
||||
virtual ~ActionHelper();
|
||||
ReturnValue_t handleActionMessage(CommandMessage* command);
|
||||
ReturnValue_t initialize();
|
||||
void step(uint8_t step, MessageQueueId_t reportTo, ActionId_t commandId, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||
void finish(MessageQueueId_t reportTo, ActionId_t commandId, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||
void reportData(MessageQueueId_t reportTo, ActionId_t replyId, SerializeIF* data);
|
||||
ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId, SerializeIF* data, bool hideSender = false);
|
||||
void setQueueToUse(MessageQueueIF *queue);
|
||||
protected:
|
||||
static const uint8_t STEP_OFFSET = 1;
|
||||
HasActionsIF* owner;
|
||||
MessageQueue* queueToUse;
|
||||
MessageQueueIF* queueToUse;
|
||||
StorageManagerIF* ipcStore;
|
||||
virtual void prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId, store_address_t dataAddress);
|
||||
void resetHelper();
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
#include <framework/action/ActionMessage.h>
|
||||
#include <framework/objectmanager/ObjectManagerIF.h>
|
||||
#include <framework/storagemanager/StorageManagerIF.h>
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
#ifndef ACTIONMESSAGE_H_
|
||||
#define ACTIONMESSAGE_H_
|
||||
|
||||
@ -11,7 +10,7 @@ class ActionMessage {
|
||||
private:
|
||||
ActionMessage();
|
||||
public:
|
||||
static const uint8_t MESSAGE_ID = FUNCTION_MESSAGE_ID;
|
||||
static const uint8_t MESSAGE_ID = MESSAGE_TYPE::ACTION;
|
||||
static const Command_t EXECUTE_ACTION = MAKE_COMMAND_ID(1);
|
||||
static const Command_t STEP_SUCCESS = MAKE_COMMAND_ID(2);
|
||||
static const Command_t STEP_FAILED = MAKE_COMMAND_ID(3);
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
#include <framework/action/ActionMessage.h>
|
||||
#include <framework/action/CommandActionHelper.h>
|
||||
#include <framework/action/CommandsActionsIF.h>
|
||||
|
@ -1,13 +1,12 @@
|
||||
|
||||
#ifndef COMMANDACTIONHELPER_H_
|
||||
#define COMMANDACTIONHELPER_H_
|
||||
|
||||
#include <framework/action/ActionMessage.h>
|
||||
#include <framework/ipc/MessageQueue.h>
|
||||
#include <framework/objectmanager/ObjectManagerIF.h>
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <framework/serialize/SerializeIF.h>
|
||||
#include <framework/storagemanager/StorageManagerIF.h>
|
||||
#include <framework/ipc/MessageQueueIF.h>
|
||||
|
||||
class CommandsActionsIF;
|
||||
|
||||
@ -25,7 +24,7 @@ public:
|
||||
uint8_t getCommandCount() const;
|
||||
private:
|
||||
CommandsActionsIF* owner;
|
||||
MessageQueue* queueToUse;
|
||||
MessageQueueIF* queueToUse;
|
||||
StorageManagerIF* ipcStore;
|
||||
uint8_t commandCount;
|
||||
MessageQueueId_t lastTarget;
|
||||
|
@ -1,10 +1,9 @@
|
||||
|
||||
#ifndef COMMANDSACTIONSIF_H_
|
||||
#define COMMANDSACTIONSIF_H_
|
||||
|
||||
#include <framework/action/CommandActionHelper.h>
|
||||
#include <framework/ipc/MessageQueue.h>
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <framework/ipc/MessageQueueIF.h>
|
||||
|
||||
/**
|
||||
* Interface to separate commanding actions of other objects.
|
||||
@ -18,11 +17,11 @@
|
||||
class CommandsActionsIF {
|
||||
friend class CommandActionHelper;
|
||||
public:
|
||||
static const uint8_t INTERFACE_ID = COMMANDS_ACTIONS_IF;
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::COMMANDS_ACTIONS_IF;
|
||||
static const ReturnValue_t OBJECT_HAS_NO_FUNCTIONS = MAKE_RETURN_CODE(1);
|
||||
static const ReturnValue_t ALREADY_COMMANDING = MAKE_RETURN_CODE(2);
|
||||
virtual ~CommandsActionsIF() {}
|
||||
virtual MessageQueue* getCommandQueuePtr() = 0;
|
||||
virtual MessageQueueIF* getCommandQueuePtr() = 0;
|
||||
protected:
|
||||
virtual void stepSuccessfulReceived(ActionId_t actionId, uint8_t step) = 0;
|
||||
virtual void stepFailedReceived(ActionId_t actionId, uint8_t step, ReturnValue_t returnCode) = 0;
|
||||
|
@ -1,21 +1,14 @@
|
||||
/*
|
||||
* HasActionsIF.h
|
||||
*
|
||||
* Created on: 20.02.2014
|
||||
* Author: baetz
|
||||
*/
|
||||
|
||||
#ifndef HASACTIONSIF_H_
|
||||
#define HASACTIONSIF_H_
|
||||
|
||||
#include <framework/action/ActionHelper.h>
|
||||
#include <framework/action/ActionMessage.h>
|
||||
#include <framework/action/SimpleActionHelper.h>
|
||||
#include <framework/ipc/MessageQueue.h>
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <framework/ipc/MessageQueueIF.h>
|
||||
class HasActionsIF {
|
||||
public:
|
||||
static const uint8_t INTERFACE_ID = HAS_ACTIONS_IF;
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::HAS_ACTIONS_IF;
|
||||
static const ReturnValue_t IS_BUSY = MAKE_RETURN_CODE(1);
|
||||
static const ReturnValue_t INVALID_PARAMETERS = MAKE_RETURN_CODE(2);
|
||||
static const ReturnValue_t EXECUTION_FINISHED = MAKE_RETURN_CODE(3);
|
||||
|
@ -1,8 +1,7 @@
|
||||
|
||||
#include <framework/action/HasActionsIF.h>
|
||||
#include <framework/action/SimpleActionHelper.h>
|
||||
SimpleActionHelper::SimpleActionHelper(HasActionsIF* setOwner,
|
||||
MessageQueue* useThisQueue) :
|
||||
MessageQueueIF* useThisQueue) :
|
||||
ActionHelper(setOwner, useThisQueue), isExecuting(false), lastCommander(
|
||||
0), lastAction(0), stepCount(0) {
|
||||
}
|
||||
@ -24,8 +23,8 @@ void SimpleActionHelper::finish(ReturnValue_t result) {
|
||||
resetHelper();
|
||||
}
|
||||
|
||||
void SimpleActionHelper::reportData(SerializeIF* data) {
|
||||
ActionHelper::reportData(lastCommander, lastAction, data);
|
||||
ReturnValue_t SimpleActionHelper::reportData(SerializeIF* data) {
|
||||
return ActionHelper::reportData(lastCommander, lastAction, data);
|
||||
}
|
||||
|
||||
void SimpleActionHelper::resetHelper() {
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
#ifndef SIMPLEACTIONHELPER_H_
|
||||
#define SIMPLEACTIONHELPER_H_
|
||||
|
||||
@ -6,11 +5,11 @@
|
||||
|
||||
class SimpleActionHelper: public ActionHelper {
|
||||
public:
|
||||
SimpleActionHelper(HasActionsIF* setOwner, MessageQueue* useThisQueue);
|
||||
SimpleActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue);
|
||||
virtual ~SimpleActionHelper();
|
||||
void step(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||
void finish(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||
void reportData(SerializeIF* data);
|
||||
ReturnValue_t reportData(SerializeIF* data);
|
||||
void resetHelper();
|
||||
protected:
|
||||
void prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId, store_address_t dataAddress);
|
||||
|
@ -17,7 +17,7 @@ template<typename T, typename count_t = uint8_t>
|
||||
class ArrayList {
|
||||
template<typename U, typename count> friend class SerialArrayListAdapter;
|
||||
public:
|
||||
static const uint8_t INTERFACE_ID = ARRAY_LIST;
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::ARRAY_LIST;
|
||||
static const ReturnValue_t FULL = MAKE_RETURN_CODE(0x01);
|
||||
|
||||
/**
|
||||
@ -80,13 +80,17 @@ public:
|
||||
return value;
|
||||
}
|
||||
|
||||
const T *operator->() const{
|
||||
return value;
|
||||
}
|
||||
|
||||
//SHOULDDO this should be implemented as non-member
|
||||
bool operator==(const typename ArrayList<T, count_t>::Iterator& other) {
|
||||
bool operator==(const typename ArrayList<T, count_t>::Iterator& other) const{
|
||||
return (value == other.value);
|
||||
}
|
||||
|
||||
//SHOULDDO this should be implemented as non-member
|
||||
bool operator!=(const typename ArrayList<T, count_t>::Iterator& other) {
|
||||
bool operator!=(const typename ArrayList<T, count_t>::Iterator& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
}
|
||||
@ -116,9 +120,10 @@ public:
|
||||
*
|
||||
* @param storage the array to use as backend
|
||||
* @param maxSize size of storage
|
||||
* @param size size of data already present in storage
|
||||
*/
|
||||
ArrayList(T *storage, count_t maxSize) :
|
||||
size(0), entries(storage), maxSize_(maxSize), allocated(false) {
|
||||
ArrayList(T *storage, count_t maxSize, count_t size = 0) :
|
||||
size(size), entries(storage), maxSize_(maxSize), allocated(false) {
|
||||
}
|
||||
|
||||
/**
|
||||
@ -170,6 +175,12 @@ public:
|
||||
*/
|
||||
T *back() {
|
||||
return &entries[size - 1];
|
||||
//Alternative solution
|
||||
//return const_cast<T*>(static_cast<const T*>(*this).back());
|
||||
}
|
||||
|
||||
const T* back() const{
|
||||
return &entries[size-1];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -212,11 +223,6 @@ public:
|
||||
count_t remaining() {
|
||||
return (maxSize_ - size);
|
||||
}
|
||||
protected:
|
||||
/**
|
||||
* pointer to the array in which the entries are stored
|
||||
*/
|
||||
T *entries;
|
||||
private:
|
||||
/**
|
||||
* This is the copy constructor
|
||||
@ -230,7 +236,11 @@ private:
|
||||
size(other.size), entries(other.entries), maxSize_(other.maxSize_), allocated(
|
||||
false) {
|
||||
}
|
||||
private:
|
||||
protected:
|
||||
/**
|
||||
* pointer to the array in which the entries are stored
|
||||
*/
|
||||
T *entries;
|
||||
/**
|
||||
* remembering the maximum size
|
||||
*/
|
||||
|
@ -1,10 +1,3 @@
|
||||
/*
|
||||
* BinaryTree.h
|
||||
*
|
||||
* Created on: 09.03.2015
|
||||
* Author: baetz
|
||||
*/
|
||||
|
||||
#ifndef FRAMEWORK_CONTAINER_BINARYTREE_H_
|
||||
#define FRAMEWORK_CONTAINER_BINARYTREE_H_
|
||||
|
||||
@ -99,9 +92,6 @@ public:
|
||||
}
|
||||
iterator insert(bool insertLeft, iterator parentNode, Node* newNode ) {
|
||||
newNode->parent = parentNode.element;
|
||||
//TODO: Why do I delete the child references of the node? This kills reconnection :-p
|
||||
// newNode->left = NULL;
|
||||
// newNode->right = NULL;
|
||||
if (parentNode.element != NULL) {
|
||||
if (insertLeft) {
|
||||
parentNode.element->left = newNode;
|
||||
|
@ -54,7 +54,7 @@ public:
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
}
|
||||
static const uint8_t INTERFACE_ID = FIFO_CLASS;
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::FIFO_CLASS;
|
||||
static const ReturnValue_t FULL = MAKE_RETURN_CODE(1);
|
||||
static const ReturnValue_t EMPTY = MAKE_RETURN_CODE(2);
|
||||
};
|
||||
|
@ -9,7 +9,7 @@
|
||||
template<typename key_t, typename T>
|
||||
class FixedMap: public SerializeIF {
|
||||
public:
|
||||
static const uint8_t INTERFACE_ID = FIXED_MAP;
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MAP;
|
||||
static const ReturnValue_t KEY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01);
|
||||
static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x02);
|
||||
static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x03);
|
||||
|
@ -1,10 +1,3 @@
|
||||
/*
|
||||
* FixedOrderedMultimap.h
|
||||
*
|
||||
* Created on: 22.01.2015
|
||||
* Author: baetz
|
||||
*/
|
||||
|
||||
#ifndef FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_H_
|
||||
#define FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_H_
|
||||
|
||||
@ -15,7 +8,7 @@
|
||||
template<typename key_t, typename T, typename KEY_COMPARE = std::less<key_t>>
|
||||
class FixedOrderedMultimap {
|
||||
public:
|
||||
static const uint8_t INTERFACE_ID = FIXED_MAP;
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MAP;
|
||||
static const ReturnValue_t KEY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01);
|
||||
static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x02);
|
||||
static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x03);
|
||||
|
700
container/IndexedRingMemoryArray.h
Normal file
700
container/IndexedRingMemoryArray.h
Normal file
@ -0,0 +1,700 @@
|
||||
#ifndef FRAMEWORK_CONTAINER_INDEXEDRINGMEMORY_H_
|
||||
#define FRAMEWORK_CONTAINER_INDEXEDRINGMEMORY_H_
|
||||
|
||||
#include <framework/container/ArrayList.h>
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <framework/serialize/SerialArrayListAdapter.h>
|
||||
#include <framework/globalfunctions/crc_ccitt.h>
|
||||
#include <cmath>
|
||||
|
||||
template<typename T>
|
||||
class Index: public SerializeIF{
|
||||
/**
|
||||
* Index is the Type used for the list of indices. The template parameter is the type which describes the index, it needs to be a child of SerializeIF to be able to make it persistent
|
||||
*/
|
||||
static_assert(std::is_base_of<SerializeIF,T>::value,"Wrong Type for Index, Type must implement SerializeIF");
|
||||
public:
|
||||
Index():blockStartAddress(0),size(0),storedPackets(0){}
|
||||
|
||||
Index(uint32_t startAddress):blockStartAddress(startAddress),size(0),storedPackets(0){
|
||||
|
||||
}
|
||||
|
||||
void setBlockStartAddress(uint32_t newAddress){
|
||||
this->blockStartAddress = newAddress;
|
||||
}
|
||||
|
||||
uint32_t getBlockStartAddress() const {
|
||||
return blockStartAddress;
|
||||
}
|
||||
|
||||
const T* getIndexType() const {
|
||||
return &indexType;
|
||||
}
|
||||
|
||||
T* modifyIndexType(){
|
||||
return &indexType;
|
||||
}
|
||||
/**
|
||||
* Updates the index Type. Uses = operator
|
||||
* @param indexType Type to copy from
|
||||
*/
|
||||
void setIndexType(T* indexType) {
|
||||
this->indexType = *indexType;
|
||||
}
|
||||
|
||||
uint32_t getSize() const {
|
||||
return size;
|
||||
}
|
||||
|
||||
void setSize(uint32_t size) {
|
||||
this->size = size;
|
||||
}
|
||||
|
||||
void addSize(uint32_t size){
|
||||
this->size += size;
|
||||
}
|
||||
|
||||
void setStoredPackets(uint32_t newStoredPackets){
|
||||
this->storedPackets = newStoredPackets;
|
||||
}
|
||||
|
||||
void addStoredPackets(uint32_t packets){
|
||||
this->storedPackets += packets;
|
||||
}
|
||||
|
||||
uint32_t getStoredPackets() const{
|
||||
return this->storedPackets;
|
||||
}
|
||||
|
||||
ReturnValue_t serialize(uint8_t** buffer, uint32_t* size,
|
||||
const uint32_t max_size, bool bigEndian) const {
|
||||
ReturnValue_t result = AutoSerializeAdapter::serialize(&blockStartAddress,buffer,size,max_size,bigEndian);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||
return result;
|
||||
}
|
||||
result = indexType.serialize(buffer,size,max_size,bigEndian);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||
return result;
|
||||
}
|
||||
result = AutoSerializeAdapter::serialize(&this->size,buffer,size,max_size,bigEndian);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||
return result;
|
||||
}
|
||||
result = AutoSerializeAdapter::serialize(&this->storedPackets,buffer,size,max_size,bigEndian);
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size,
|
||||
bool bigEndian){
|
||||
ReturnValue_t result = AutoSerializeAdapter::deSerialize(&blockStartAddress,buffer,size,bigEndian);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||
return result;
|
||||
}
|
||||
result = indexType.deSerialize(buffer,size,bigEndian);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||
return result;
|
||||
}
|
||||
result = AutoSerializeAdapter::deSerialize(&this->size,buffer,size,bigEndian);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||
return result;
|
||||
}
|
||||
result = AutoSerializeAdapter::deSerialize(&this->storedPackets,buffer,size,bigEndian);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t getSerializedSize() const {
|
||||
uint32_t size = AutoSerializeAdapter::getSerializedSize(&blockStartAddress);
|
||||
size += indexType.getSerializedSize();
|
||||
size += AutoSerializeAdapter::getSerializedSize(&this->size);
|
||||
size += AutoSerializeAdapter::getSerializedSize(&this->storedPackets);
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
bool operator==(const Index<T>& other){
|
||||
return ((blockStartAddress == other.getBlockStartAddress()) && (size==other.getSize())) && (indexType == *(other.getIndexType()));
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t blockStartAddress;
|
||||
uint32_t size;
|
||||
uint32_t storedPackets;
|
||||
T indexType;
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<typename T>
|
||||
class IndexedRingMemoryArray: public SerializeIF, public ArrayList<Index<T>, uint32_t>{
|
||||
/**
|
||||
* Indexed Ring Memory Array is a class for a ring memory with indices. It assumes that the newest data comes in last
|
||||
* It uses the currentWriteBlock as pointer to the current writing position
|
||||
* The currentReadBlock must be set manually
|
||||
*/
|
||||
public:
|
||||
IndexedRingMemoryArray(uint32_t startAddress, uint32_t size, uint32_t bytesPerBlock, SerializeIF* additionalInfo,
|
||||
bool overwriteOld) :ArrayList<Index<T>,uint32_t>(NULL,(uint32_t)10,(uint32_t)0),totalSize(size),indexAddress(startAddress),currentReadSize(0),currentReadBlockSizeCached(0),lastBlockToReadSize(0), additionalInfo(additionalInfo),overwriteOld(overwriteOld){
|
||||
|
||||
//Calculate the maximum number of indices needed for this blocksize
|
||||
uint32_t maxNrOfIndices = floor(static_cast<double>(size)/static_cast<double>(bytesPerBlock));
|
||||
|
||||
//Calculate the Size needeed for the index itself
|
||||
uint32_t serializedSize = 0;
|
||||
if(additionalInfo!=NULL){
|
||||
serializedSize += additionalInfo->getSerializedSize();
|
||||
}
|
||||
//Size of current iterator type
|
||||
Index<T> tempIndex;
|
||||
serializedSize += tempIndex.getSerializedSize();
|
||||
|
||||
//Add Size of Array
|
||||
serializedSize += sizeof(uint32_t); //size of array
|
||||
serializedSize += (tempIndex.getSerializedSize() * maxNrOfIndices); //size of elements
|
||||
serializedSize += sizeof(uint16_t); //size of crc
|
||||
|
||||
//Calculate new size after index
|
||||
if(serializedSize > totalSize){
|
||||
error << "IndexedRingMemory: Store is too small for index" << std::endl;
|
||||
}
|
||||
uint32_t useableSize = totalSize - serializedSize;
|
||||
//Update the totalSize for calculations
|
||||
totalSize = useableSize;
|
||||
|
||||
//True StartAddress
|
||||
uint32_t trueStartAddress = indexAddress + serializedSize;
|
||||
|
||||
//Calculate True number of Blocks and reset size of true Number of Blocks
|
||||
uint32_t trueNumberOfBlocks = floor(static_cast<double>(totalSize) / static_cast<double>(bytesPerBlock));
|
||||
|
||||
//allocate memory now
|
||||
this->entries = new Index<T>[trueNumberOfBlocks];
|
||||
this->size = trueNumberOfBlocks;
|
||||
this->maxSize_ = trueNumberOfBlocks;
|
||||
this->allocated = true;
|
||||
|
||||
//Check trueNumberOfBlocks
|
||||
if(trueNumberOfBlocks<1){
|
||||
error << "IndexedRingMemory: Invalid Number of Blocks: " << trueNumberOfBlocks;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Fill address into index
|
||||
uint32_t address = trueStartAddress;
|
||||
for (typename IndexedRingMemoryArray<T>::Iterator it = this->begin();it!=this->end();++it) {
|
||||
it->setBlockStartAddress(address);
|
||||
it->setSize(0);
|
||||
it->setStoredPackets(0);
|
||||
address += bytesPerBlock;
|
||||
}
|
||||
|
||||
|
||||
//Initialize iterators
|
||||
currentWriteBlock = this->begin();
|
||||
currentReadBlock = this->begin();
|
||||
lastBlockToRead = this->begin();
|
||||
|
||||
//Check last blockSize
|
||||
uint32_t lastBlockSize = (trueStartAddress + useableSize) - (this->back()->getBlockStartAddress());
|
||||
if((lastBlockSize<bytesPerBlock) && (this->size > 1)){
|
||||
//remove the last Block so the second last block has more size
|
||||
this->size -= 1;
|
||||
debug << "IndexedRingMemory: Last Block is smaller than bytesPerBlock, removed last block" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the whole index, the iterators and executes the given reset function on every index type
|
||||
* @param typeResetFnc static reset function which accepts a pointer to the index Type
|
||||
*/
|
||||
void reset(void (*typeResetFnc)(T*)){
|
||||
currentReadBlock = this->begin();
|
||||
currentWriteBlock = this->begin();
|
||||
lastBlockToRead = this->begin();
|
||||
currentReadSize = 0;
|
||||
currentReadBlockSizeCached = 0;
|
||||
lastBlockToReadSize = 0;
|
||||
for(typename IndexedRingMemoryArray<T>::Iterator it = this->begin();it!=this->end();++it){
|
||||
it->setSize(0);
|
||||
it->setStoredPackets(0);
|
||||
(*typeResetFnc)(it->modifyIndexType());
|
||||
}
|
||||
}
|
||||
|
||||
void resetBlock(typename IndexedRingMemoryArray<T>::Iterator it,void (*typeResetFnc)(T*)){
|
||||
it->setSize(0);
|
||||
it->setStoredPackets(0);
|
||||
(*typeResetFnc)(it->modifyIndexType());
|
||||
}
|
||||
|
||||
/*
|
||||
* Reading
|
||||
*/
|
||||
|
||||
void setCurrentReadBlock(typename IndexedRingMemoryArray<T>::Iterator it){
|
||||
currentReadBlock = it;
|
||||
currentReadBlockSizeCached = it->getSize();
|
||||
}
|
||||
|
||||
void resetRead(){
|
||||
currentReadBlock = this->begin();
|
||||
currentReadSize = 0;
|
||||
currentReadBlockSizeCached = this->begin()->getSize();
|
||||
lastBlockToRead = currentWriteBlock;
|
||||
lastBlockToReadSize = currentWriteBlock->getSize();
|
||||
}
|
||||
/**
|
||||
* Sets the last block to read to this iterator.
|
||||
* Can be used to dump until block x
|
||||
* @param it The iterator for the last read block
|
||||
*/
|
||||
void setLastBlockToRead(typename IndexedRingMemoryArray<T>::Iterator it){
|
||||
lastBlockToRead = it;
|
||||
lastBlockToReadSize = it->getSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the read pointer to the first written Block, which is the first non empty block in front of the write block
|
||||
* Can be the currentWriteBlock as well
|
||||
*/
|
||||
void readOldest(){
|
||||
resetRead();
|
||||
currentReadBlock = getNextNonEmptyBlock();
|
||||
currentReadBlockSizeCached = currentReadBlock->getSize();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current read iterator to the next Block and resets the current read size
|
||||
* The current size of the block will be cached to avoid race condition between write and read
|
||||
* If the end of the ring is reached the read pointer will be set to the begin
|
||||
*/
|
||||
void readNext(){
|
||||
currentReadSize = 0;
|
||||
if((this->size != 0) && (currentReadBlock.value ==this->back())){
|
||||
currentReadBlock = this->begin();
|
||||
}else{
|
||||
currentReadBlock++;
|
||||
}
|
||||
|
||||
currentReadBlockSizeCached = currentReadBlock->getSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the address which is currently read from
|
||||
* @return Address to read from
|
||||
*/
|
||||
uint32_t getCurrentReadAddress() const {
|
||||
return getAddressOfCurrentReadBlock() + currentReadSize;
|
||||
}
|
||||
/**
|
||||
* Adds readSize to the current size and checks if the read has no more data left and advances the read block
|
||||
* @param readSize The size that was read
|
||||
* @return Returns true if the read can go on
|
||||
*/
|
||||
bool addReadSize(uint32_t readSize) {
|
||||
if(currentReadBlock == lastBlockToRead){
|
||||
//The current read block is the last to read
|
||||
if((currentReadSize+readSize)<lastBlockToReadSize){
|
||||
//the block has more data -> return true
|
||||
currentReadSize += readSize;
|
||||
return true;
|
||||
}else{
|
||||
//Reached end of read -> return false
|
||||
currentReadSize = lastBlockToReadSize;
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
//We are not in the last Block
|
||||
if((currentReadSize + readSize)<currentReadBlockSizeCached){
|
||||
//The current Block has more data
|
||||
currentReadSize += readSize;
|
||||
return true;
|
||||
}else{
|
||||
//The current block is written completely
|
||||
readNext();
|
||||
if(currentReadBlockSizeCached==0){
|
||||
//Next block is empty
|
||||
typename IndexedRingMemoryArray<T>::Iterator it(currentReadBlock);
|
||||
//Search if any block between this and the last block is not empty
|
||||
for(;it!=lastBlockToRead;++it){
|
||||
if(it == this->end()){
|
||||
//This is the end, next block is the begin
|
||||
it = this->begin();
|
||||
if(it == lastBlockToRead){
|
||||
//Break if the begin is the lastBlockToRead
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(it->getSize()!=0){
|
||||
//This is a non empty block. Go on reading with this block
|
||||
currentReadBlock = it;
|
||||
currentReadBlockSizeCached = it->getSize();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
//reached lastBlockToRead and every block was empty, check if the last block is also empty
|
||||
if(lastBlockToReadSize!=0){
|
||||
//go on with last Block
|
||||
currentReadBlock = lastBlockToRead;
|
||||
currentReadBlockSizeCached = lastBlockToReadSize;
|
||||
return true;
|
||||
}
|
||||
//There is no non empty block left
|
||||
return false;
|
||||
}
|
||||
//Size is larger than 0
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
uint32_t getRemainigSizeOfCurrentReadBlock() const{
|
||||
if(currentReadBlock == lastBlockToRead){
|
||||
return (lastBlockToReadSize - currentReadSize);
|
||||
}else{
|
||||
return (currentReadBlockSizeCached - currentReadSize);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t getAddressOfCurrentReadBlock() const {
|
||||
return currentReadBlock->getBlockStartAddress();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the next non empty Block after the current write block,
|
||||
* @return Returns the iterator to the block. If there is non, the current write block is returned
|
||||
*/
|
||||
typename IndexedRingMemoryArray<T>::Iterator getNextNonEmptyBlock() const {
|
||||
for(typename IndexedRingMemoryArray<T>::Iterator it = getNextWrite();it!=currentWriteBlock;++it){
|
||||
if(it == this->end()){
|
||||
it = this->begin();
|
||||
if(it == currentWriteBlock){
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(it->getSize()!=0){
|
||||
return it;
|
||||
}
|
||||
}
|
||||
return currentWriteBlock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of the oldest Index type
|
||||
* @return Type of Index
|
||||
*/
|
||||
T* getOldest(){
|
||||
return (getNextNonEmptyBlock()->modifyIndexType());
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Writing
|
||||
*/
|
||||
uint32_t getAddressOfCurrentWriteBlock() const{
|
||||
return currentWriteBlock->getBlockStartAddress();
|
||||
}
|
||||
|
||||
uint32_t getSizeOfCurrentWriteBlock() const{
|
||||
return currentWriteBlock->getSize();
|
||||
}
|
||||
|
||||
uint32_t getCurrentWriteAddress() const{
|
||||
return getAddressOfCurrentWriteBlock() + getSizeOfCurrentWriteBlock();
|
||||
}
|
||||
|
||||
void clearCurrentWriteBlock(){
|
||||
currentWriteBlock->setSize(0);
|
||||
currentWriteBlock->setStoredPackets(0);
|
||||
}
|
||||
|
||||
void addCurrentWriteBlock(uint32_t size, uint32_t storedPackets){
|
||||
currentWriteBlock->addSize(size);
|
||||
currentWriteBlock->addStoredPackets(storedPackets);
|
||||
}
|
||||
|
||||
T* modifyCurrentWriteBlockIndexType(){
|
||||
return currentWriteBlock->modifyIndexType();
|
||||
}
|
||||
void updatePreviousWriteSize(uint32_t size, uint32_t storedPackets){
|
||||
typename IndexedRingMemoryArray<T>::Iterator it = getPreviousBlock(currentWriteBlock);
|
||||
it->addSize(size);
|
||||
it->addStoredPackets(storedPackets);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the block has enough space for sizeToWrite
|
||||
* @param sizeToWrite The data to be written in the Block
|
||||
* @return Returns true if size to write is smaller the remaining size of the block
|
||||
*/
|
||||
bool hasCurrentWriteBlockEnoughSpace(uint32_t sizeToWrite){
|
||||
typename IndexedRingMemoryArray<T>::Iterator next = getNextWrite();
|
||||
uint32_t addressOfNextBlock = next->getBlockStartAddress();
|
||||
uint32_t availableSize = ((addressOfNextBlock+totalSize) - (getAddressOfCurrentWriteBlock()+getSizeOfCurrentWriteBlock()))%totalSize;
|
||||
return (sizeToWrite < availableSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the store is full if overwrite old is false
|
||||
* @return Returns true if it is writeable and false if not
|
||||
*/
|
||||
bool isNextBlockWritable(){
|
||||
//First check if this is the end of the list
|
||||
typename IndexedRingMemoryArray<T>::Iterator next;
|
||||
next = getNextWrite();
|
||||
if((next->getSize()!=0) && (!overwriteOld)){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates current write Block Index Type
|
||||
* @param infoOfNewBlock
|
||||
*/
|
||||
void updateCurrentBlock(T* infoOfNewBlock){
|
||||
currentWriteBlock->setIndexType(infoOfNewBlock);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Succeed to next block, returns FAILED if overwrite is false and the store is full
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t writeNext(){
|
||||
//Check Next Block
|
||||
if(!isNextBlockWritable()){
|
||||
//The Index is full and does not overwrite old
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
//Next block can be written, update Metadata
|
||||
currentWriteBlock = getNextWrite();
|
||||
currentWriteBlock->setSize(0);
|
||||
currentWriteBlock->setStoredPackets(0);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes the Index and calculates the CRC.
|
||||
* Parameters according to HasSerializeIF
|
||||
* @param buffer
|
||||
* @param size
|
||||
* @param max_size
|
||||
* @param bigEndian
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t serialize(uint8_t** buffer, uint32_t* size,
|
||||
const uint32_t max_size, bool bigEndian) const{
|
||||
uint8_t* crcBuffer = *buffer;
|
||||
uint32_t oldSize = *size;
|
||||
if(additionalInfo!=NULL){
|
||||
additionalInfo->serialize(buffer,size,max_size,bigEndian);
|
||||
}
|
||||
ReturnValue_t result = currentWriteBlock->serialize(buffer,size,max_size,bigEndian);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||
return result;
|
||||
}
|
||||
result = AutoSerializeAdapter::serialize(&this->size,buffer,size,max_size,bigEndian);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t i = 0;
|
||||
while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->size)) {
|
||||
result = SerializeAdapter<Index<T> >::serialize(&this->entries[i], buffer, size,
|
||||
max_size, bigEndian);
|
||||
++i;
|
||||
}
|
||||
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||
return result;
|
||||
}
|
||||
uint16_t crc = Calculate_CRC(crcBuffer,(*size-oldSize));
|
||||
result = AutoSerializeAdapter::serialize(&crc,buffer,size,max_size,bigEndian);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the serialized Size of the index
|
||||
* @return The serialized size of the index
|
||||
*/
|
||||
uint32_t getSerializedSize() const {
|
||||
|
||||
uint32_t size = 0;
|
||||
if(additionalInfo!=NULL){
|
||||
size += additionalInfo->getSerializedSize();
|
||||
}
|
||||
size += currentWriteBlock->getSerializedSize();
|
||||
size += AutoSerializeAdapter::getSerializedSize(&this->size);
|
||||
size += (this->entries[0].getSerializedSize()) * this->size;
|
||||
uint16_t crc = 0;
|
||||
size += AutoSerializeAdapter::getSerializedSize(&crc);
|
||||
return size;
|
||||
}
|
||||
/**
|
||||
* DeSerialize the Indexed Ring from a buffer, deSerializes the current write iterator
|
||||
* CRC Has to be checked before!
|
||||
* @param buffer
|
||||
* @param size
|
||||
* @param bigEndian
|
||||
* @return
|
||||
*/
|
||||
|
||||
ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size,
|
||||
bool bigEndian){
|
||||
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
if(additionalInfo!=NULL){
|
||||
result = additionalInfo->deSerialize(buffer,size,bigEndian);
|
||||
}
|
||||
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||
return result;
|
||||
}
|
||||
|
||||
Index<T> tempIndex;
|
||||
result = tempIndex.deSerialize(buffer,size,bigEndian);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||
return result;
|
||||
}
|
||||
uint32_t tempSize = 0;
|
||||
result = AutoSerializeAdapter::deSerialize(&tempSize,buffer,size,bigEndian);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||
return result;
|
||||
}
|
||||
if(this->size != tempSize){
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
uint32_t i = 0;
|
||||
while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->size)) {
|
||||
result = SerializeAdapter<Index<T> >::deSerialize(
|
||||
&this->entries[i], buffer, size,
|
||||
bigEndian);
|
||||
++i;
|
||||
}
|
||||
if(result != HasReturnvaluesIF::RETURN_OK){
|
||||
return result;
|
||||
}
|
||||
typename IndexedRingMemoryArray<T>::Iterator cmp(&tempIndex);
|
||||
for(typename IndexedRingMemoryArray<T>::Iterator it= this->begin();it!=this->end();++it){
|
||||
if(*(cmp.value) == *(it.value)){
|
||||
currentWriteBlock = it;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
}
|
||||
//Reached if current write block iterator is not found
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
uint32_t getIndexAddress() const {
|
||||
return indexAddress;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Statistics
|
||||
*/
|
||||
uint32_t getStoredPackets() const {
|
||||
uint32_t size = 0;
|
||||
for(typename IndexedRingMemoryArray<T>::Iterator it= this->begin();it!=this->end();++it){
|
||||
size += it->getStoredPackets();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
uint32_t getTotalSize() const {
|
||||
return totalSize;
|
||||
}
|
||||
|
||||
uint32_t getCurrentSize() const{
|
||||
uint32_t size = 0;
|
||||
for(typename IndexedRingMemoryArray<T>::Iterator it= this->begin();it!=this->end();++it){
|
||||
size += it->getSize();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
bool isEmpty() const{
|
||||
return getCurrentSize()==0;
|
||||
}
|
||||
|
||||
double getPercentageFilled() const{
|
||||
uint32_t filledSize = 0;
|
||||
for(typename IndexedRingMemoryArray<T>::Iterator it= this->begin();it!=this->end();++it){
|
||||
filledSize += it->getSize();
|
||||
}
|
||||
|
||||
return (double)filledSize/(double)this->totalSize;
|
||||
}
|
||||
|
||||
typename IndexedRingMemoryArray<T>::Iterator getCurrentWriteBlock() const{
|
||||
return currentWriteBlock;
|
||||
}
|
||||
/**
|
||||
* Get the next block of the currentWriteBlock.
|
||||
* Returns the first one if currentWriteBlock is the last one
|
||||
* @return Iterator pointing to the next block after currentWriteBlock
|
||||
*/
|
||||
typename IndexedRingMemoryArray<T>::Iterator getNextWrite() const{
|
||||
typename IndexedRingMemoryArray<T>::Iterator next(currentWriteBlock);
|
||||
if((this->size != 0) && (currentWriteBlock.value == this->back())){
|
||||
next = this->begin();
|
||||
}else{
|
||||
++next;
|
||||
}
|
||||
return next;
|
||||
}
|
||||
/**
|
||||
* Get the block in front of the Iterator
|
||||
* Returns the last block if it is the first block
|
||||
* @param it iterator which you want the previous block from
|
||||
* @return pointing to the block before it
|
||||
*/
|
||||
typename IndexedRingMemoryArray<T>::Iterator getPreviousBlock(typename IndexedRingMemoryArray<T>::Iterator it) {
|
||||
if(this->begin() == it){
|
||||
typename IndexedRingMemoryArray<T>::Iterator next((this->back()));
|
||||
return next;
|
||||
}
|
||||
typename IndexedRingMemoryArray<T>::Iterator next(it);
|
||||
--next;
|
||||
return next;
|
||||
}
|
||||
private:
|
||||
//The total size used by the blocks (without index)
|
||||
uint32_t totalSize;
|
||||
|
||||
//The address of the index
|
||||
const uint32_t indexAddress;
|
||||
|
||||
//The iterators for writing and reading
|
||||
typename IndexedRingMemoryArray<T>::Iterator currentWriteBlock;
|
||||
typename IndexedRingMemoryArray<T>::Iterator currentReadBlock;
|
||||
|
||||
//How much of the current read block is read already
|
||||
uint32_t currentReadSize;
|
||||
|
||||
//Cached Size of current read block
|
||||
uint32_t currentReadBlockSizeCached;
|
||||
|
||||
//Last block of current write (should be write block)
|
||||
typename IndexedRingMemoryArray<T>::Iterator lastBlockToRead;
|
||||
//current size of last Block to read
|
||||
uint32_t lastBlockToReadSize;
|
||||
|
||||
//Additional Info to be serialized with the index
|
||||
SerializeIF* additionalInfo;
|
||||
|
||||
//Does it overwrite old blocks?
|
||||
const bool overwriteOld;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* FRAMEWORK_CONTAINER_INDEXEDRINGMEMORY_H_ */
|
@ -1,27 +0,0 @@
|
||||
/**
|
||||
* @file LinkedElementDecorator.h
|
||||
* @brief This file defines the LinkedElementDecorator class.
|
||||
* @date 22.07.2014
|
||||
* @author baetz
|
||||
*/
|
||||
#ifndef LINKEDELEMENTDECORATOR_H_
|
||||
#define LINKEDELEMENTDECORATOR_H_
|
||||
|
||||
#include <framework/container/SinglyLinkedList.h>
|
||||
#include <utility>
|
||||
|
||||
//TODO: This generates multiple inheritance from non-IF parents.
|
||||
template<typename T, typename IF_T>
|
||||
class LinkedElementDecorator : public LinkedElement<IF_T>, public T {
|
||||
public:
|
||||
template<typename... Args>
|
||||
LinkedElementDecorator(Args... args) : LinkedElement<IF_T>(this), T(std::forward<Args>(args)...) {
|
||||
}
|
||||
|
||||
virtual ~LinkedElementDecorator() {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* LINKEDELEMENTDECORATOR_H_ */
|
@ -1,10 +1,3 @@
|
||||
/*
|
||||
* PlacementFactory.h
|
||||
*
|
||||
* Created on: 10.03.2015
|
||||
* Author: baetz
|
||||
*/
|
||||
|
||||
#ifndef FRAMEWORK_CONTAINER_PLACEMENTFACTORY_H_
|
||||
#define FRAMEWORK_CONTAINER_PLACEMENTFACTORY_H_
|
||||
|
||||
@ -30,7 +23,8 @@ public:
|
||||
}
|
||||
template<typename T>
|
||||
ReturnValue_t destroy(T* thisElement) {
|
||||
//TODO: Shouldn't we call the destructor here first, in case something was allocated by the object (shouldn't do that, however).
|
||||
//Need to call destructor first, in case something was allocated by the object (shouldn't do that, however).
|
||||
thisElement->~T();
|
||||
uint8_t* pointer = (uint8_t*) (thisElement);
|
||||
return dataBackend->deleteData(pointer, sizeof(T));
|
||||
}
|
||||
|
@ -1,10 +1,3 @@
|
||||
/*
|
||||
* RingBufferBase.h
|
||||
*
|
||||
* Created on: 06.02.2015
|
||||
* Author: baetz
|
||||
*/
|
||||
|
||||
#ifndef FRAMEWORK_CONTAINER_RINGBUFFERBASE_H_
|
||||
#define FRAMEWORK_CONTAINER_RINGBUFFERBASE_H_
|
||||
|
||||
@ -77,16 +70,16 @@ public:
|
||||
uint32_t readTillWrap(uint8_t n = 0) {
|
||||
return (start + size) - read[n];
|
||||
}
|
||||
const uint32_t getStart() const {
|
||||
uint32_t getStart() const {
|
||||
return start;
|
||||
}
|
||||
const bool overwritesOld() const {
|
||||
bool overwritesOld() const {
|
||||
return overwriteOld;
|
||||
}
|
||||
uint32_t maxSize() const {
|
||||
return size - 1;
|
||||
}
|
||||
private:
|
||||
protected:
|
||||
const uint32_t start;
|
||||
uint32_t write;
|
||||
uint32_t read[N_READ_PTRS];
|
||||
|
79
container/RingBufferTest.cpp.ignore
Normal file
79
container/RingBufferTest.cpp.ignore
Normal file
@ -0,0 +1,79 @@
|
||||
|
||||
#include <iostream>
|
||||
#include "SimpleRingBuffer.h"
|
||||
|
||||
|
||||
int main() {
|
||||
using namespace std;
|
||||
SimpleRingBuffer buffer(64, false);
|
||||
uint8_t data[8] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'};
|
||||
ReturnValue_t result = buffer.writeData(data, 8);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
cout << "writeData failed." << endl;
|
||||
}
|
||||
result = buffer.writeData(data, 8);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
cout << "writeData failed." << endl;
|
||||
}
|
||||
uint8_t buffer2[47] = {0};
|
||||
for (uint8_t count = 0; count<sizeof(buffer2); count++) {
|
||||
buffer2[count] = count;
|
||||
}
|
||||
result = buffer.writeData(buffer2, sizeof(buffer2));
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
cout << "writeData failed." << endl;
|
||||
}
|
||||
result = buffer.writeData(buffer2, sizeof(buffer2));
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
cout << "writeData failed." << endl;
|
||||
}
|
||||
uint8_t readBuffer[64] = {0};
|
||||
uint32_t writtenData = 0;
|
||||
result = buffer.readData(readBuffer, 12, true, &writtenData);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
cout << "readData failed." << endl;
|
||||
} else {
|
||||
cout << "Read data: " << writtenData << endl;
|
||||
for (uint32_t count = 0; count < writtenData; count++) {
|
||||
cout << hex << (uint16_t)readBuffer[count] << " ";
|
||||
}
|
||||
cout << dec << endl;
|
||||
}
|
||||
|
||||
result = buffer.readData(readBuffer, 60, true, &writtenData);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
cout << "readData failed." << endl;
|
||||
} else {
|
||||
cout << "Read data: " << writtenData << endl;
|
||||
for (uint32_t count = 0; count < writtenData; count++) {
|
||||
cout << hex << (uint16_t)readBuffer[count] << " ";
|
||||
}
|
||||
cout << dec << endl;
|
||||
}
|
||||
result = buffer.writeData(data, sizeof(data));
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
cout << "writeData failed." << endl;
|
||||
}
|
||||
result = buffer.readData(readBuffer, 60, true, &writtenData);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
cout << "readData failed." << endl;
|
||||
} else {
|
||||
cout << "Read data: " << writtenData << endl;
|
||||
for (uint32_t count = 0; count < writtenData; count++) {
|
||||
cout << hex << (uint16_t)readBuffer[count] << " ";
|
||||
}
|
||||
cout << dec << endl;
|
||||
}
|
||||
result = buffer.writeData(readBuffer, sizeof(readBuffer));
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
cout << "writeData failed." << endl;
|
||||
}
|
||||
result = buffer.writeData(readBuffer, sizeof(readBuffer)-1);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
cout << "writeData failed." << endl;
|
||||
} else {
|
||||
cout << "write done." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
68
container/SimpleRingBuffer.cpp
Normal file
68
container/SimpleRingBuffer.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
#include <framework/container/SimpleRingBuffer.h>
|
||||
#include <string.h>
|
||||
|
||||
SimpleRingBuffer::SimpleRingBuffer(uint32_t size, bool overwriteOld) :
|
||||
RingBufferBase<>(0, size, overwriteOld), buffer(NULL) {
|
||||
buffer = new uint8_t[size];
|
||||
}
|
||||
|
||||
SimpleRingBuffer::~SimpleRingBuffer() {
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
ReturnValue_t SimpleRingBuffer::writeData(const uint8_t* data,
|
||||
uint32_t amount) {
|
||||
if (availableWriteSpace() >= amount || overwriteOld) {
|
||||
uint32_t amountTillWrap = writeTillWrap();
|
||||
if (amountTillWrap >= amount) {
|
||||
memcpy(&buffer[write], data, amount);
|
||||
} else {
|
||||
memcpy(&buffer[write], data, amountTillWrap);
|
||||
memcpy(buffer, data + amountTillWrap, amount - amountTillWrap);
|
||||
}
|
||||
incrementWrite(amount);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
} else {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t SimpleRingBuffer::readData(uint8_t* data, uint32_t amount,
|
||||
bool readRemaining, uint32_t* trueAmount) {
|
||||
uint32_t availableData = availableReadData(READ_PTR);
|
||||
uint32_t amountTillWrap = readTillWrap(READ_PTR);
|
||||
if (availableData < amount) {
|
||||
if (readRemaining) {
|
||||
amount = availableData;
|
||||
} else {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
if (trueAmount != NULL) {
|
||||
*trueAmount = amount;
|
||||
}
|
||||
if (amountTillWrap >= amount) {
|
||||
memcpy(data, &buffer[read[READ_PTR]], amount);
|
||||
} else {
|
||||
memcpy(data, &buffer[read[READ_PTR]], amountTillWrap);
|
||||
memcpy(data + amountTillWrap, buffer, amount - amountTillWrap);
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t SimpleRingBuffer::deleteData(uint32_t amount,
|
||||
bool deleteRemaining, uint32_t* trueAmount) {
|
||||
uint32_t availableData = availableReadData(READ_PTR);
|
||||
if (availableData < amount) {
|
||||
if (deleteRemaining) {
|
||||
amount = availableData;
|
||||
} else {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
if (trueAmount != NULL) {
|
||||
*trueAmount = amount;
|
||||
}
|
||||
incrementRead(amount, READ_PTR);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
21
container/SimpleRingBuffer.h
Normal file
21
container/SimpleRingBuffer.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_
|
||||
#define FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_
|
||||
|
||||
#include <framework/container/RingBufferBase.h>
|
||||
#include <stddef.h>
|
||||
|
||||
class SimpleRingBuffer: public RingBufferBase<> {
|
||||
public:
|
||||
SimpleRingBuffer(uint32_t size, bool overwriteOld);
|
||||
virtual ~SimpleRingBuffer();
|
||||
ReturnValue_t writeData(const uint8_t* data, uint32_t amount);
|
||||
ReturnValue_t readData(uint8_t* data, uint32_t amount, bool readRemaining = false, uint32_t* trueAmount = NULL);
|
||||
ReturnValue_t deleteData(uint32_t amount, bool deleteRemaining = false, uint32_t* trueAmount = NULL);
|
||||
private:
|
||||
// static const uint8_t TEMP_READ_PTR = 1;
|
||||
static const uint8_t READ_PTR = 0;
|
||||
uint8_t* buffer;
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ */
|
||||
|
@ -49,7 +49,7 @@ public:
|
||||
virtual ~LinkedElement(){
|
||||
|
||||
}
|
||||
virtual LinkedElement* const getNext() const {
|
||||
virtual LinkedElement* getNext() const {
|
||||
return next;
|
||||
}
|
||||
|
||||
|
4
contrib/sgp4/LICENSE
Normal file
4
contrib/sgp4/LICENSE
Normal file
@ -0,0 +1,4 @@
|
||||
There is no license associated with the code and you may use it for any purpose —personal or commercial— as you
|
||||
wish. We ask only that you include citations in your documentation and source code to show the source of the code
|
||||
and provide links to https://www.celestrak.com/publications/AIAA/2006-6753/, to facilitate communications
|
||||
regarding any questions on the theory or source code.
|
2090
contrib/sgp4/sgp4unit.cpp
Normal file
2090
contrib/sgp4/sgp4unit.cpp
Normal file
File diff suppressed because it is too large
Load Diff
117
contrib/sgp4/sgp4unit.h
Normal file
117
contrib/sgp4/sgp4unit.h
Normal file
@ -0,0 +1,117 @@
|
||||
#ifndef _sgp4unit_
|
||||
#define _sgp4unit_
|
||||
/* ----------------------------------------------------------------
|
||||
*
|
||||
* sgp4unit.h
|
||||
*
|
||||
* this file contains the sgp4 procedures for analytical propagation
|
||||
* of a satellite. the code was originally released in the 1980 and 1986
|
||||
* spacetrack papers. a detailed discussion of the theory and history
|
||||
* may be found in the 2006 aiaa paper by vallado, crawford, hujsak,
|
||||
* and kelso.
|
||||
*
|
||||
* companion code for
|
||||
* fundamentals of astrodynamics and applications
|
||||
* 2007
|
||||
* by david vallado
|
||||
*
|
||||
* (w) 719-573-2600, email dvallado@agi.com
|
||||
*
|
||||
* current :
|
||||
* 20 apr 07 david vallado
|
||||
* misc fixes for constants
|
||||
* changes :
|
||||
* 11 aug 06 david vallado
|
||||
* chg lyddane choice back to strn3, constants, misc doc
|
||||
* 15 dec 05 david vallado
|
||||
* misc fixes
|
||||
* 26 jul 05 david vallado
|
||||
* fixes for paper
|
||||
* note that each fix is preceded by a
|
||||
* comment with "sgp4fix" and an explanation of
|
||||
* what was changed
|
||||
* 10 aug 04 david vallado
|
||||
* 2nd printing baseline working
|
||||
* 14 may 01 david vallado
|
||||
* 2nd edition baseline
|
||||
* 80 norad
|
||||
* original baseline
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// -------------------------- structure declarations ----------------------------
|
||||
typedef enum
|
||||
{
|
||||
wgs72old,
|
||||
wgs72,
|
||||
wgs84
|
||||
} gravconsttype;
|
||||
|
||||
typedef struct elsetrec
|
||||
{
|
||||
long int satnum;
|
||||
int epochyr, epochtynumrev;
|
||||
int error;
|
||||
char init, method;
|
||||
|
||||
/* Near Earth */
|
||||
int isimp;
|
||||
double aycof , con41 , cc1 , cc4 , cc5 , d2 , d3 , d4 ,
|
||||
delmo , eta , argpdot, omgcof , sinmao , t , t2cof, t3cof ,
|
||||
t4cof , t5cof , x1mth2 , x7thm1 , mdot , nodedot, xlcof , xmcof ,
|
||||
nodecf;
|
||||
|
||||
/* Deep Space */
|
||||
int irez;
|
||||
double d2201 , d2211 , d3210 , d3222 , d4410 , d4422 , d5220 , d5232 ,
|
||||
d5421 , d5433 , dedt , del1 , del2 , del3 , didt , dmdt ,
|
||||
dnodt , domdt , e3 , ee2 , peo , pgho , pho , pinco ,
|
||||
plo , se2 , se3 , sgh2 , sgh3 , sgh4 , sh2 , sh3 ,
|
||||
si2 , si3 , sl2 , sl3 , sl4 , gsto , xfact , xgh2 ,
|
||||
xgh3 , xgh4 , xh2 , xh3 , xi2 , xi3 , xl2 , xl3 ,
|
||||
xl4 , xlamo , zmol , zmos , atime , xli , xni;
|
||||
|
||||
double a , altp , alta , epochdays, jdsatepoch , nddot , ndot ,
|
||||
bstar , rcse , inclo , nodeo , ecco , argpo , mo ,
|
||||
no;
|
||||
} elsetrec;
|
||||
|
||||
// --------------------------- function declarations ----------------------------
|
||||
int sgp4init
|
||||
(
|
||||
gravconsttype whichconst, const int satn, const double epoch,
|
||||
const double xbstar, const double xecco, const double xargpo,
|
||||
const double xinclo, const double xmo, const double xno,
|
||||
const double xnodeo,
|
||||
elsetrec& satrec
|
||||
);
|
||||
|
||||
int sgp4
|
||||
(
|
||||
gravconsttype whichconst,
|
||||
elsetrec& satrec, double tsince,
|
||||
double r[], double v[]
|
||||
);
|
||||
|
||||
double gstime
|
||||
(
|
||||
double
|
||||
);
|
||||
|
||||
void getgravconst
|
||||
(
|
||||
gravconsttype,
|
||||
double&,
|
||||
double&,
|
||||
double&,
|
||||
double&,
|
||||
double&,
|
||||
double&,
|
||||
double&,
|
||||
double&
|
||||
);
|
||||
|
||||
#endif
|
||||
|
@ -1,15 +1,20 @@
|
||||
#include <framework/subsystem/SubsystemBase.h>
|
||||
#include <framework/controller/ControllerBase.h>
|
||||
#include <framework/subsystem/SubsystemBase.h>
|
||||
#include <framework/ipc/QueueFactory.h>
|
||||
#include <framework/action/HasActionsIF.h>
|
||||
|
||||
ControllerBase::ControllerBase(uint32_t setObjectId, uint32_t parentId,
|
||||
size_t commandQueueDepth) :
|
||||
SystemObject(setObjectId), parentId(parentId), mode(MODE_OFF), submode(
|
||||
SUBMODE_NONE), commandQueue(commandQueueDepth), modeHelper(
|
||||
this), healthHelper(this, setObjectId) {
|
||||
SUBMODE_NONE), commandQueue(NULL), modeHelper(
|
||||
this), healthHelper(this, setObjectId),hkSwitcher(this) {
|
||||
commandQueue = QueueFactory::instance()->createMessageQueue(commandQueueDepth);
|
||||
|
||||
}
|
||||
|
||||
ControllerBase::~ControllerBase() {
|
||||
QueueFactory::instance()->deleteMessageQueue(commandQueue);
|
||||
}
|
||||
|
||||
ReturnValue_t ControllerBase::initialize() {
|
||||
@ -38,18 +43,23 @@ ReturnValue_t ControllerBase::initialize() {
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = hkSwitcher.initialize();
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
MessageQueueId_t ControllerBase::getCommandQueue() const {
|
||||
return commandQueue.getId();
|
||||
return commandQueue->getId();
|
||||
}
|
||||
|
||||
void ControllerBase::handleQueue() {
|
||||
CommandMessage message;
|
||||
ReturnValue_t result;
|
||||
for (result = commandQueue.receiveMessage(&message); result == RETURN_OK;
|
||||
result = commandQueue.receiveMessage(&message)) {
|
||||
for (result = commandQueue->receiveMessage(&message); result == RETURN_OK;
|
||||
result = commandQueue->receiveMessage(&message)) {
|
||||
|
||||
result = modeHelper.handleModeCommand(&message);
|
||||
if (result == RETURN_OK) {
|
||||
@ -64,21 +74,21 @@ void ControllerBase::handleQueue() {
|
||||
if (result == RETURN_OK) {
|
||||
continue;
|
||||
}
|
||||
message.clearCommandMessage();
|
||||
CommandMessage reply(CommandMessage::REPLY_REJECTED,
|
||||
CommandMessage::UNKNOW_COMMAND, 0);
|
||||
commandQueue.reply(&reply);
|
||||
message.setToUnknownCommand();
|
||||
commandQueue->reply(&message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ControllerBase::startTransition(Mode_t mode, Submode_t submode) {
|
||||
changeHK(this->mode, this->submode, false);
|
||||
triggerEvent(CHANGING_MODE, mode, submode);
|
||||
modeHelper.modeChanged(mode, submode);
|
||||
modeChanged(mode, submode);
|
||||
this->mode = mode;
|
||||
this->submode = submode;
|
||||
modeHelper.modeChanged(mode, submode);
|
||||
modeChanged(mode, submode);
|
||||
announceMode(false);
|
||||
changeHK(this->mode, this->submode, true);
|
||||
}
|
||||
|
||||
void ControllerBase::getMode(Mode_t* mode, Submode_t* submode) {
|
||||
@ -94,8 +104,9 @@ void ControllerBase::announceMode(bool recursive) {
|
||||
triggerEvent(MODE_INFO, mode, submode);
|
||||
}
|
||||
|
||||
ReturnValue_t ControllerBase::performOperation() {
|
||||
ReturnValue_t ControllerBase::performOperation(uint8_t opCode) {
|
||||
handleQueue();
|
||||
hkSwitcher.performOperation();
|
||||
performControlOperation();
|
||||
return RETURN_OK;
|
||||
}
|
||||
@ -118,3 +129,6 @@ ReturnValue_t ControllerBase::setHealth(HealthState health) {
|
||||
HasHealthIF::HealthState ControllerBase::getHealth() {
|
||||
return healthHelper.getHealth();
|
||||
}
|
||||
|
||||
void ControllerBase::changeHK(Mode_t mode, Submode_t submode, bool enable) {
|
||||
}
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include <framework/modes/ModeHelper.h>
|
||||
#include <framework/objectmanager/SystemObject.h>
|
||||
#include <framework/tasks/ExecutableObjectIF.h>
|
||||
#include <framework/datapool/HkSwitchHelper.h>
|
||||
|
||||
|
||||
class ControllerBase: public HasModesIF,
|
||||
public HasHealthIF,
|
||||
@ -17,14 +19,15 @@ public:
|
||||
|
||||
static const Mode_t MODE_NORMAL = 2;
|
||||
|
||||
ControllerBase(uint32_t setObjectId, uint32_t parentId, size_t commandQueueDepth = 3);
|
||||
ControllerBase(uint32_t setObjectId, uint32_t parentId,
|
||||
size_t commandQueueDepth = 3);
|
||||
virtual ~ControllerBase();
|
||||
|
||||
ReturnValue_t initialize();
|
||||
|
||||
virtual MessageQueueId_t getCommandQueue() const;
|
||||
|
||||
virtual ReturnValue_t performOperation();
|
||||
virtual ReturnValue_t performOperation(uint8_t opCode);
|
||||
|
||||
virtual ReturnValue_t setHealth(HealthState health);
|
||||
|
||||
@ -36,12 +39,14 @@ protected:
|
||||
|
||||
Submode_t submode;
|
||||
|
||||
MessageQueue commandQueue;
|
||||
MessageQueueIF* commandQueue;
|
||||
|
||||
ModeHelper modeHelper;
|
||||
|
||||
HealthHelper healthHelper;
|
||||
|
||||
HkSwitchHelper hkSwitcher;
|
||||
|
||||
void handleQueue();
|
||||
|
||||
virtual ReturnValue_t handleCommandMessage(CommandMessage *message) = 0;
|
||||
@ -53,6 +58,7 @@ protected:
|
||||
virtual void getMode(Mode_t *mode, Submode_t *submode);
|
||||
virtual void setToExternalControl();
|
||||
virtual void announceMode(bool recursive);
|
||||
virtual void changeHK(Mode_t mode, Submode_t submode, bool enable);
|
||||
};
|
||||
|
||||
#endif /* CONTROLLERBASE_H_ */
|
||||
|
@ -6,36 +6,31 @@
|
||||
#include <cmath>
|
||||
|
||||
|
||||
//TODO move time stuff to OSAL
|
||||
|
||||
void CoordinateTransformations::positionEcfToEci(const double* ecfPosition,
|
||||
double* eciPosition) {
|
||||
ecfToEci(ecfPosition, eciPosition, NULL);
|
||||
double* eciPosition, timeval *timeUTC) {
|
||||
ecfToEci(ecfPosition, eciPosition, NULL, timeUTC);
|
||||
|
||||
}
|
||||
|
||||
void CoordinateTransformations::velocityEcfToEci(const double* ecfVelocity,
|
||||
const double* ecfPosition, double* eciVelocity) {
|
||||
ecfToEci(ecfVelocity, eciVelocity, ecfPosition);
|
||||
const double* ecfPosition, double* eciVelocity, timeval *timeUTC) {
|
||||
ecfToEci(ecfVelocity, eciVelocity, ecfPosition, timeUTC);
|
||||
}
|
||||
|
||||
double CoordinateTransformations::getEarthRotationAngle(timeval time) {
|
||||
void CoordinateTransformations::positionEciToEcf(const double* eciCoordinates, double* ecfCoordinates,timeval *timeUTC){
|
||||
eciToEcf(eciCoordinates,ecfCoordinates,NULL,timeUTC);
|
||||
};
|
||||
|
||||
double jD2000UTC = (time.tv_sec - 946728000. + time.tv_usec / 1000000.)
|
||||
/ 24. / 3600.;
|
||||
void CoordinateTransformations::velocityEciToEcf(const double* eciVelocity,const double* eciPosition, double* ecfVelocity,timeval* timeUTC){
|
||||
eciToEcf(eciVelocity,ecfVelocity,eciPosition,timeUTC);
|
||||
}
|
||||
|
||||
//value of unix time at J2000TT
|
||||
static const double J2000TtUnix = 946727935.816;
|
||||
double CoordinateTransformations::getEarthRotationAngle(timeval timeUTC) {
|
||||
|
||||
//TT does not have leap seconds
|
||||
//so we need to add the leap seconds since J2000 to our UTC based clock
|
||||
//Conveniently, GPS gives us access to the leap seconds since 1980
|
||||
//between 1980 and 2000 13 leap seconds happened
|
||||
uint8_t leapSecondsSinceJ2000 = utcGpsOffset - 13;
|
||||
double jD2000UTC;
|
||||
Clock::convertTimevalToJD2000(timeUTC, &jD2000UTC);
|
||||
|
||||
//Julean centuries since J2000 //TODO fails for dates before now?
|
||||
double TTt2000 = (time.tv_sec + time.tv_usec / 1000000. - J2000TtUnix
|
||||
+ leapSecondsSinceJ2000) / 24. / 3600. / 36525.;
|
||||
double TTt2000 = getJuleanCenturiesTT(timeUTC);
|
||||
|
||||
double theta = 2 * Math::PI
|
||||
* (0.779057273264 + 1.00273781191135448 * jD2000UTC);
|
||||
@ -48,9 +43,9 @@ double CoordinateTransformations::getEarthRotationAngle(timeval time) {
|
||||
return theta;
|
||||
}
|
||||
|
||||
void CoordinateTransformations::getEarthRotationMatrix(timeval time,
|
||||
void CoordinateTransformations::getEarthRotationMatrix(timeval timeUTC,
|
||||
double matrix[][3]) {
|
||||
double theta = getEarthRotationAngle(time);
|
||||
double theta = getEarthRotationAngle(timeUTC);
|
||||
|
||||
matrix[0][0] = cos(theta);
|
||||
matrix[0][1] = sin(theta);
|
||||
@ -65,120 +60,35 @@ void CoordinateTransformations::getEarthRotationMatrix(timeval time,
|
||||
|
||||
void CoordinateTransformations::ecfToEci(const double* ecfCoordinates,
|
||||
double* eciCoordinates,
|
||||
const double* ecfPositionIfCoordinatesAreVelocity) {
|
||||
//TODO all calculations only work with a correct time
|
||||
const double* ecfPositionIfCoordinatesAreVelocity, timeval *timeUTCin) {
|
||||
|
||||
timeval time;
|
||||
OSAL::getClock_timeval(&time);
|
||||
|
||||
//value of unix time at J2000TT
|
||||
static const double J2000TtUnix = 946727935.816;
|
||||
|
||||
//we need TT which does not have leap seconds
|
||||
//so we need to add the leap seconds since J2000 to our UTC based clock
|
||||
//Conveniently, GPS gives us access to the leap seconds since 1980
|
||||
//between 1980 and 2000 13 leap seconds happened
|
||||
uint8_t leapSecondsSinceJ2000 = utcGpsOffset - 13;
|
||||
|
||||
//Julean centuries since J2000 //TODO fails for dates before now?
|
||||
double TTt2000 = (time.tv_sec + time.tv_usec / 1000000. - J2000TtUnix
|
||||
+ leapSecondsSinceJ2000) / 24. / 3600. / 36525.;
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Calculate Precession Matrix
|
||||
|
||||
double zeta = 0.0111808609 * TTt2000
|
||||
+ 1.46355554053347E-006 * TTt2000 * TTt2000
|
||||
+ 8.72567663260943E-008 * TTt2000 * TTt2000 * TTt2000;
|
||||
double theta_p = 0.0097171735 * TTt2000
|
||||
- 2.06845757045384E-006 * TTt2000 * TTt2000
|
||||
- 2.02812107218552E-007 * TTt2000 * TTt2000 * TTt2000;
|
||||
double z = zeta + 3.8436028638364E-006 * TTt2000 * TTt2000
|
||||
+ 0.000000001 * TTt2000 * TTt2000 * TTt2000;
|
||||
|
||||
double mPrecession[3][3];
|
||||
|
||||
mPrecession[0][0] = -sin(z) * sin(zeta) + cos(z) * cos(theta_p) * cos(zeta);
|
||||
mPrecession[1][0] = cos(z) * sin(zeta) + sin(z) * cos(theta_p) * cos(zeta);
|
||||
mPrecession[2][0] = sin(theta_p) * cos(zeta);
|
||||
|
||||
mPrecession[0][1] = -sin(z) * cos(zeta) - cos(z) * cos(theta_p) * sin(zeta);
|
||||
mPrecession[1][1] = cos(z) * cos(zeta) - sin(z) * cos(theta_p) * sin(zeta);
|
||||
mPrecession[2][1] = -sin(theta_p) * sin(zeta);
|
||||
|
||||
mPrecession[0][2] = -cos(z) * sin(theta_p);
|
||||
mPrecession[1][2] = -sin(z) * sin(theta_p);
|
||||
mPrecession[2][2] = cos(theta_p);
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Calculate Nutation Matrix
|
||||
|
||||
double omega_moon = 2.1824386244 - 33.7570459338 * TTt2000
|
||||
+ 3.61428599267159E-005 * TTt2000 * TTt2000
|
||||
+ 3.87850944887629E-008 * TTt2000 * TTt2000 * TTt2000;
|
||||
|
||||
double deltaPsi = -0.000083388 * sin(omega_moon);
|
||||
double deltaEpsilon = 4.46174030725106E-005 * cos(omega_moon);
|
||||
|
||||
double epsilon = 0.4090928042 - 0.0002269655 * TTt2000
|
||||
- 2.86040071854626E-009 * TTt2000 * TTt2000
|
||||
+ 8.78967203851589E-009 * TTt2000 * TTt2000 * TTt2000;
|
||||
|
||||
double mNutation[3][3];
|
||||
|
||||
mNutation[0][0] = cos(deltaPsi);
|
||||
mNutation[1][0] = cos(epsilon + deltaEpsilon) * sin(deltaPsi);
|
||||
mNutation[2][0] = sin(epsilon + deltaEpsilon) * sin(deltaPsi);
|
||||
|
||||
mNutation[0][1] = -cos(epsilon) * sin(deltaPsi);
|
||||
mNutation[1][1] = cos(epsilon) * cos(epsilon + deltaEpsilon) * cos(deltaPsi)
|
||||
+ sin(epsilon) * sin(epsilon + deltaEpsilon);
|
||||
mNutation[2][1] = cos(epsilon) * sin(epsilon + deltaEpsilon) * cos(deltaPsi)
|
||||
- sin(epsilon) * cos(epsilon + deltaEpsilon);
|
||||
|
||||
mNutation[0][2] = -sin(epsilon) * sin(deltaPsi);
|
||||
mNutation[1][2] = sin(epsilon) * cos(epsilon + deltaEpsilon) * cos(deltaPsi)
|
||||
- cos(epsilon) * sin(epsilon + deltaEpsilon);
|
||||
mNutation[2][2] = sin(epsilon) * sin(epsilon + deltaEpsilon) * cos(deltaPsi)
|
||||
+ cos(epsilon) * cos(epsilon + deltaEpsilon);
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Calculate Earth rotation matrix
|
||||
|
||||
//calculate theta
|
||||
|
||||
double mTheta[3][3];
|
||||
getEarthRotationMatrix(time, mTheta);
|
||||
|
||||
//polar motion is neglected
|
||||
timeval timeUTC;
|
||||
if (timeUTCin != NULL) {
|
||||
timeUTC = *timeUTCin;
|
||||
} else {
|
||||
Clock::getClock_timeval(&timeUTC);
|
||||
}
|
||||
|
||||
double Tfi[3][3];
|
||||
double Ttemp[3][3];
|
||||
double Tif[3][3];
|
||||
|
||||
MatrixOperations<double>::multiply(mNutation[0], mPrecession[0], Ttemp[0],
|
||||
3, 3, 3);
|
||||
MatrixOperations<double>::multiply(mTheta[0], Ttemp[0], Tfi[0], 3, 3, 3);
|
||||
getTransMatrixECITOECF(timeUTC,Tfi);
|
||||
|
||||
MatrixOperations<double>::transpose(Tfi[0], Tif[0], 3);
|
||||
|
||||
MatrixOperations<double>::multiply(Tif[0], ecfCoordinates, eciCoordinates,
|
||||
3, 3, 1);
|
||||
|
||||
|
||||
|
||||
|
||||
if (ecfPositionIfCoordinatesAreVelocity != NULL) {
|
||||
|
||||
double Tdotfi[3][3];
|
||||
double Tdotif[3][3];
|
||||
double Trot[3][3] = { { 0, Earth::OMEGA, 0 },
|
||||
{ 0 - Earth::OMEGA, 0, 0 }, { 0, 0, 0 } };
|
||||
double Ttemp2[3][3];
|
||||
|
||||
MatrixOperations<double>::multiply(mNutation[0], mPrecession[0],
|
||||
Ttemp[0], 3, 3, 3);
|
||||
MatrixOperations<double>::multiply(mTheta[0], Ttemp[0], Ttemp2[0], 3, 3,
|
||||
3);
|
||||
|
||||
MatrixOperations<double>::multiply(Trot[0], Ttemp2[0], Tdotfi[0], 3, 3,
|
||||
MatrixOperations<double>::multiply(Trot[0], Tfi[0], Tdotfi[0], 3, 3,
|
||||
3);
|
||||
|
||||
MatrixOperations<double>::transpose(Tdotfi[0], Tdotif[0], 3);
|
||||
@ -194,13 +104,124 @@ void CoordinateTransformations::ecfToEci(const double* ecfCoordinates,
|
||||
}
|
||||
}
|
||||
|
||||
CoordinateTransformations::CoordinateTransformations(uint8_t offset) :
|
||||
utcGpsOffset(offset) {
|
||||
double CoordinateTransformations::getJuleanCenturiesTT(timeval timeUTC) {
|
||||
timeval timeTT;
|
||||
Clock::convertUTCToTT(timeUTC, &timeTT);
|
||||
double jD2000TT;
|
||||
Clock::convertTimevalToJD2000(timeTT, &jD2000TT);
|
||||
|
||||
return jD2000TT / 36525.;
|
||||
}
|
||||
|
||||
CoordinateTransformations::~CoordinateTransformations() {
|
||||
}
|
||||
void CoordinateTransformations::eciToEcf(const double* eciCoordinates,
|
||||
double* ecfCoordinates,
|
||||
const double* eciPositionIfCoordinatesAreVelocity,timeval *timeUTCin){
|
||||
timeval timeUTC;
|
||||
if (timeUTCin != NULL) {
|
||||
timeUTC = *timeUTCin;
|
||||
}else{
|
||||
Clock::getClock_timeval(&timeUTC);
|
||||
}
|
||||
|
||||
void CoordinateTransformations::setUtcGpsOffset(uint8_t offset) {
|
||||
}
|
||||
double Tfi[3][3];
|
||||
|
||||
getTransMatrixECITOECF(timeUTC,Tfi);
|
||||
|
||||
MatrixOperations<double>::multiply(Tfi[0],eciCoordinates,ecfCoordinates,3,3,1);
|
||||
|
||||
if (eciPositionIfCoordinatesAreVelocity != NULL) {
|
||||
|
||||
double Tdotfi[3][3];
|
||||
double Trot[3][3] = { { 0, Earth::OMEGA, 0 },
|
||||
{ 0 - Earth::OMEGA, 0, 0 }, { 0, 0, 0 } };
|
||||
|
||||
MatrixOperations<double>::multiply(Trot[0], Tfi[0], Tdotfi[0], 3, 3,
|
||||
3);
|
||||
|
||||
double velocityCorrection[3];
|
||||
|
||||
MatrixOperations<double>::multiply(Tdotfi[0],
|
||||
eciPositionIfCoordinatesAreVelocity, velocityCorrection, 3, 3,
|
||||
1);
|
||||
|
||||
VectorOperations<double>::add(ecfCoordinates, velocityCorrection,
|
||||
ecfCoordinates, 3);
|
||||
}
|
||||
};
|
||||
|
||||
void CoordinateTransformations::getTransMatrixECITOECF(timeval timeUTC,double Tfi[3][3]){
|
||||
double TTt2000 = getJuleanCenturiesTT(timeUTC);
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Calculate Precession Matrix
|
||||
|
||||
double zeta = 0.0111808609 * TTt2000
|
||||
+ 1.46355554053347E-006 * TTt2000 * TTt2000
|
||||
+ 8.72567663260943E-008 * TTt2000 * TTt2000 * TTt2000;
|
||||
double theta_p = 0.0097171735 * TTt2000
|
||||
- 2.06845757045384E-006 * TTt2000 * TTt2000
|
||||
- 2.02812107218552E-007 * TTt2000 * TTt2000 * TTt2000;
|
||||
double z = zeta + 3.8436028638364E-006 * TTt2000 * TTt2000
|
||||
+ 0.000000001 * TTt2000 * TTt2000 * TTt2000;
|
||||
|
||||
double mPrecession[3][3];
|
||||
|
||||
mPrecession[0][0] = -sin(z) * sin(zeta) + cos(z) * cos(theta_p) * cos(zeta);
|
||||
mPrecession[1][0] = cos(z) * sin(zeta) + sin(z) * cos(theta_p) * cos(zeta);
|
||||
mPrecession[2][0] = sin(theta_p) * cos(zeta);
|
||||
|
||||
mPrecession[0][1] = -sin(z) * cos(zeta) - cos(z) * cos(theta_p) * sin(zeta);
|
||||
mPrecession[1][1] = cos(z) * cos(zeta) - sin(z) * cos(theta_p) * sin(zeta);
|
||||
mPrecession[2][1] = -sin(theta_p) * sin(zeta);
|
||||
|
||||
mPrecession[0][2] = -cos(z) * sin(theta_p);
|
||||
mPrecession[1][2] = -sin(z) * sin(theta_p);
|
||||
mPrecession[2][2] = cos(theta_p);
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Calculate Nutation Matrix
|
||||
|
||||
double omega_moon = 2.1824386244 - 33.7570459338 * TTt2000
|
||||
+ 3.61428599267159E-005 * TTt2000 * TTt2000
|
||||
+ 3.87850944887629E-008 * TTt2000 * TTt2000 * TTt2000;
|
||||
|
||||
double deltaPsi = -0.000083388 * sin(omega_moon);
|
||||
double deltaEpsilon = 4.46174030725106E-005 * cos(omega_moon);
|
||||
|
||||
double epsilon = 0.4090928042 - 0.0002269655 * TTt2000
|
||||
- 2.86040071854626E-009 * TTt2000 * TTt2000
|
||||
+ 8.78967203851589E-009 * TTt2000 * TTt2000 * TTt2000;
|
||||
|
||||
|
||||
double mNutation[3][3];
|
||||
|
||||
mNutation[0][0] = cos(deltaPsi);
|
||||
mNutation[1][0] = cos(epsilon + deltaEpsilon) * sin(deltaPsi);
|
||||
mNutation[2][0] = sin(epsilon + deltaEpsilon) * sin(deltaPsi);
|
||||
|
||||
mNutation[0][1] = -cos(epsilon) * sin(deltaPsi);
|
||||
mNutation[1][1] = cos(epsilon) * cos(epsilon + deltaEpsilon) * cos(deltaPsi)
|
||||
+ sin(epsilon) * sin(epsilon + deltaEpsilon);
|
||||
mNutation[2][1] = cos(epsilon) * sin(epsilon + deltaEpsilon) * cos(deltaPsi)
|
||||
- sin(epsilon) * cos(epsilon + deltaEpsilon);
|
||||
|
||||
mNutation[0][2] = -sin(epsilon) * sin(deltaPsi);
|
||||
mNutation[1][2] = sin(epsilon) * cos(epsilon + deltaEpsilon) * cos(deltaPsi)
|
||||
- cos(epsilon) * sin(epsilon + deltaEpsilon);
|
||||
mNutation[2][2] = sin(epsilon) * sin(epsilon + deltaEpsilon) * cos(deltaPsi)
|
||||
+ cos(epsilon) * cos(epsilon + deltaEpsilon);
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// Calculate Earth rotation matrix
|
||||
//calculate theta
|
||||
|
||||
double mTheta[3][3];
|
||||
double Ttemp[3][3];
|
||||
getEarthRotationMatrix(timeUTC, mTheta);
|
||||
|
||||
//polar motion is neglected
|
||||
MatrixOperations<double>::multiply(mNutation[0], mPrecession[0], Ttemp[0],
|
||||
3, 3, 3);
|
||||
|
||||
MatrixOperations<double>::multiply(mTheta[0], Ttemp[0], Tfi[0], 3, 3, 3);
|
||||
};
|
||||
|
@ -1,28 +1,32 @@
|
||||
#ifndef COORDINATETRANSFORMATIONS_H_
|
||||
#define COORDINATETRANSFORMATIONS_H_
|
||||
|
||||
#include <framework/osal/OSAL.h>
|
||||
#include <framework/timemanager/Clock.h>
|
||||
|
||||
class CoordinateTransformations {
|
||||
public:
|
||||
CoordinateTransformations(uint8_t utcGpsOffset);
|
||||
static void positionEcfToEci(const double* ecfCoordinates, double* eciCoordinates, timeval *timeUTC = NULL);
|
||||
|
||||
virtual ~CoordinateTransformations();
|
||||
|
||||
void positionEcfToEci(const double* ecfCoordinates, double* eciCoordinates);
|
||||
|
||||
void velocityEcfToEci(const double* ecfVelocity,
|
||||
static void velocityEcfToEci(const double* ecfVelocity,
|
||||
const double* ecfPosition,
|
||||
double* eciVelocity);
|
||||
double* eciVelocity, timeval *timeUTC = NULL);
|
||||
|
||||
double getEarthRotationAngle(timeval time);
|
||||
static void positionEciToEcf(const double* eciCoordinates, double* ecfCoordinates,timeval *timeUTC = NULL);
|
||||
static void velocityEciToEcf(const double* eciVelocity,const double* eciPosition, double* ecfVelocity,timeval* timeUTC = NULL);
|
||||
|
||||
void getEarthRotationMatrix(timeval time, double matrix[][3]);
|
||||
void setUtcGpsOffset(uint8_t offset);
|
||||
static double getEarthRotationAngle(timeval timeUTC);
|
||||
|
||||
static void getEarthRotationMatrix(timeval timeUTC, double matrix[][3]);
|
||||
private:
|
||||
uint8_t utcGpsOffset;
|
||||
void ecfToEci(const double* ecfCoordinates, double* eciCoordinates,
|
||||
const double* ecfPositionIfCoordinatesAreVelocity);
|
||||
CoordinateTransformations();
|
||||
static void ecfToEci(const double* ecfCoordinates, double* eciCoordinates,
|
||||
const double* ecfPositionIfCoordinatesAreVelocity, timeval *timeUTCin);
|
||||
static void eciToEcf(const double* eciCoordinates,
|
||||
double* ecfCoordinates,
|
||||
const double* eciPositionIfCoordinatesAreVelocity,timeval *timeUTCin);
|
||||
|
||||
static double getJuleanCenturiesTT(timeval timeUTC);
|
||||
static void getTransMatrixECITOECF(timeval time,double Tfi[3][3]);
|
||||
|
||||
};
|
||||
|
||||
|
180
coordinates/Jgm3Model.h
Normal file
180
coordinates/Jgm3Model.h
Normal file
@ -0,0 +1,180 @@
|
||||
#ifndef FRAMEWORK_COORDINATES_JGM3MODEL_H_
|
||||
#define FRAMEWORK_COORDINATES_JGM3MODEL_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <framework/coordinates/CoordinateTransformations.h>
|
||||
#include <framework/globalfunctions/math/VectorOperations.h>
|
||||
#include <framework/globalfunctions/timevalOperations.h>
|
||||
#include <framework/globalfunctions/constants.h>
|
||||
#include <memory.h>
|
||||
|
||||
|
||||
template<uint8_t DEGREE,uint8_t ORDER>
|
||||
class Jgm3Model {
|
||||
public:
|
||||
static const uint32_t factorialLookupTable[DEGREE+3]; //This table is used instead of factorial calculation, must be increased if order or degree is higher
|
||||
|
||||
Jgm3Model() {
|
||||
y0[0] = 0;
|
||||
y0[1] = 0;
|
||||
y0[2] = 0;
|
||||
y0[3] = 0;
|
||||
y0[4] = 0;
|
||||
y0[5] = 0;
|
||||
|
||||
lastExecutionTime.tv_sec = 0;
|
||||
lastExecutionTime.tv_usec = 0;
|
||||
}
|
||||
virtual ~Jgm3Model(){};
|
||||
|
||||
//double acsNavOrbit(double posECF[3],double velECF[3],timeval gpsTime);
|
||||
|
||||
double y0[6]; //position and velocity at beginning of RK step in EC
|
||||
timeval lastExecutionTime; //Time of last execution
|
||||
|
||||
|
||||
void accelDegOrd(const double pos[3],const double S[ORDER+1][DEGREE+1],const double C[ORDER+1][DEGREE+1],double* accel){
|
||||
//Get radius of this position
|
||||
double r = VectorOperations<double>::norm(pos,3);
|
||||
|
||||
|
||||
|
||||
//Initialize the V and W matrix
|
||||
double V[DEGREE+2][ORDER+2] = {{0}};
|
||||
double W[DEGREE+2][ORDER+2] = {{0}};
|
||||
|
||||
for(uint8_t m=0;m<(ORDER+2);m++){
|
||||
for(uint8_t n=m;n<(DEGREE+2);n++){
|
||||
if((n==0) && (m==0)){
|
||||
//Montenbruck "Satellite Orbits Eq.3.31"
|
||||
V[0][0] = Earth::MEAN_RADIUS / r;
|
||||
W[0][0] = 0;
|
||||
}else{
|
||||
if(n==m){
|
||||
//Montenbruck "Satellite Orbits Eq.3.29"
|
||||
V[m][m] = (2*m-1)* (pos[0]*Earth::MEAN_RADIUS/pow(r,2)*V[m-1][m-1] - pos[1]*Earth::MEAN_RADIUS/pow(r,2)*W[m-1][m-1]);
|
||||
W[m][m] = (2*m-1)* (pos[0]*Earth::MEAN_RADIUS/pow(r,2)*W[m-1][m-1] + pos[1]*Earth::MEAN_RADIUS/pow(r,2)*V[m-1][m-1]);
|
||||
}else{
|
||||
//Montenbruck "Satellite Orbits Eq.3.30"
|
||||
V[n][m] = ((2*n-1)/(double)(n-m))*pos[2]*Earth::MEAN_RADIUS / pow(r,2)*V[n-1][m];
|
||||
W[n][m] = ((2*n-1)/(double)(n-m))*pos[2]*Earth::MEAN_RADIUS / pow(r,2)*W[n-1][m];
|
||||
if(n!=(m+1)){
|
||||
V[n][m] = V[n][m] - (((n+m-1)/(double)(n-m)) * (pow(Earth::MEAN_RADIUS,2) / pow(r,2)) * V[n-2][m]);
|
||||
W[n][m] = W[n][m] - (((n+m-1)/(double)(n-m)) * (pow(Earth::MEAN_RADIUS,2) / pow(r,2)) * W[n-2][m]);
|
||||
}//End of if(n!=(m+1))
|
||||
}//End of if(n==m){
|
||||
}//End of if(n==0 and m==0)
|
||||
}//End of for(uint8_t n=0;n<(DEGREE+1);n++)
|
||||
}//End of for(uint8_t m=0;m<(ORDER+1);m++)
|
||||
|
||||
|
||||
//overwrite accel if not properly initialized
|
||||
accel[0] = 0;
|
||||
accel[1] = 0;
|
||||
accel[2] = 0;
|
||||
|
||||
for(uint8_t m=0;m<(ORDER+1);m++){
|
||||
for(uint8_t n=m;n<(DEGREE+1);n++){
|
||||
//Use table lookup to get factorial
|
||||
double partAccel[3] = {0};
|
||||
double factor = Earth::STANDARD_GRAVITATIONAL_PARAMETER/pow(Earth::MEAN_RADIUS,2);
|
||||
if(m==0){
|
||||
//Montenbruck "Satellite Orbits Eq.3.33"
|
||||
partAccel[0] = factor * (-C[n][0]*V[n+1][1]);
|
||||
partAccel[1] = factor * (-C[n][0]*W[n+1][1]);
|
||||
}else{
|
||||
double factMN = static_cast<double>(factorialLookupTable[n-m+2]) / static_cast<double>(factorialLookupTable[n-m]);
|
||||
partAccel[0] = factor * 0.5 * ((-C[n][m]*V[n+1][m+1]-S[n][m]*W[n+1][m+1])+factMN*(C[n][m]*V[n+1][m-1]+S[n][m]*W[n+1][m-1]));
|
||||
partAccel[1] = factor * 0.5 * ((-C[n][m]*W[n+1][m+1]+S[n][m]*V[n+1][m+1])+factMN*(-C[n][m]*W[n+1][m-1]+S[n][m]*V[n+1][m-1]));
|
||||
}
|
||||
|
||||
partAccel[2] = factor * ((n-m+1)*(-C[n][m]*V[n+1][m]-S[n][m]*W[n+1][m]));
|
||||
|
||||
|
||||
accel[0] += partAccel[0];
|
||||
accel[1] += partAccel[1];
|
||||
accel[2] += partAccel[2];
|
||||
}//End of for(uint8_t n=0;n<DEGREE;n++)
|
||||
}//End of uint8_t m=0;m<ORDER;m++
|
||||
}
|
||||
|
||||
void initializeNavOrbit(const double position[3],const double velocity[3], timeval timeUTC){
|
||||
CoordinateTransformations::positionEcfToEci(position,&y0[0],&timeUTC);
|
||||
CoordinateTransformations::velocityEcfToEci(velocity,position,&y0[3],&timeUTC);
|
||||
lastExecutionTime = timeUTC;
|
||||
}
|
||||
|
||||
|
||||
void acsNavOrbit(timeval timeUTC, const double S[ORDER+1][DEGREE+1],const double C[ORDER+1][DEGREE+1], double outputPos[3],double outputVel[3]){
|
||||
|
||||
//RK4 Integration for this timestamp
|
||||
double deltaT = timevalOperations::toDouble(timeUTC-lastExecutionTime);
|
||||
|
||||
double y0dot[6] = {0,0,0,0,0,0};
|
||||
double yA[6] = {0,0,0,0,0,0};
|
||||
double yAdot[6] = {0,0,0,0,0,0};
|
||||
double yB[6] = {0,0,0,0,0,0};
|
||||
double yBdot[6] = {0,0,0,0,0,0};
|
||||
double yC[6] = {0,0,0,0,0,0};
|
||||
double yCdot[6] = {0,0,0,0,0,0};
|
||||
|
||||
//Step One
|
||||
rungeKuttaStep(y0,y0dot,lastExecutionTime,S,C);
|
||||
|
||||
//Step Two
|
||||
VectorOperations<double>::mulScalar(y0dot,deltaT/2,yA,6);
|
||||
VectorOperations<double>::add(y0,yA,yA,6);
|
||||
rungeKuttaStep(yA,yAdot,lastExecutionTime,S,C);
|
||||
|
||||
//Step Three
|
||||
VectorOperations<double>::mulScalar(yAdot,deltaT/2,yB,6);
|
||||
VectorOperations<double>::add(y0,yB,yB,6);
|
||||
rungeKuttaStep(yB,yBdot,lastExecutionTime,S,C);
|
||||
|
||||
//Step Four
|
||||
VectorOperations<double>::mulScalar(yBdot,deltaT,yC,6);
|
||||
VectorOperations<double>::add(y0,yC,yC,6);
|
||||
rungeKuttaStep(yC,yCdot,lastExecutionTime,S,C);
|
||||
|
||||
//Calc new State
|
||||
VectorOperations<double>::mulScalar(yAdot,2,yAdot,6);
|
||||
VectorOperations<double>::mulScalar(yBdot,2,yBdot,6);
|
||||
VectorOperations<double>::add(y0dot,yAdot,y0dot,6);
|
||||
VectorOperations<double>::add(y0dot,yBdot,y0dot,6);
|
||||
VectorOperations<double>::add(y0dot,yCdot,y0dot,6);
|
||||
VectorOperations<double>::mulScalar(y0dot,1./6.*deltaT,y0dot,6);
|
||||
VectorOperations<double>::add(y0,y0dot,y0,6);
|
||||
|
||||
CoordinateTransformations::positionEciToEcf(&y0[0],outputPos,&timeUTC);
|
||||
CoordinateTransformations::velocityEciToEcf(&y0[3],&y0[0],outputVel,&timeUTC);
|
||||
|
||||
lastExecutionTime = timeUTC;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void rungeKuttaStep(const double* yIn,double* yOut,timeval time, const double S[ORDER+1][DEGREE+1],const double C[ORDER+1][DEGREE+1]){
|
||||
double rECF[3] = {0,0,0};
|
||||
double rDotECF[3] = {0,0,0};
|
||||
double accelECF[3] = {0,0,0};
|
||||
double accelECI[3] = {0,0,0};
|
||||
|
||||
|
||||
CoordinateTransformations::positionEciToEcf(&yIn[0],rECF,&time);
|
||||
CoordinateTransformations::velocityEciToEcf(&yIn[3],&yIn[0],rDotECF,&time);
|
||||
accelDegOrd(rECF,S,C,accelECF);
|
||||
//This is not correct, as the acceleration would have derived terms but we don't know the velocity and position at that time
|
||||
//Tests showed that a wrong velocity does make the equation worse than neglecting it
|
||||
CoordinateTransformations::positionEcfToEci(accelECF,accelECI,&time);
|
||||
memcpy(&yOut[0],&yIn[3],sizeof(yOut[0])*3);
|
||||
memcpy(&yOut[3],accelECI,sizeof(yOut[0])*3);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* FRAMEWORK_COORDINATES_JGM3MODEL_H_ */
|
@ -1,14 +1,12 @@
|
||||
#include <framework/osal/OSAL.h>
|
||||
#include <framework/coordinates/CoordinateTransformations.h>
|
||||
#include <framework/coordinates/Sgp4Propagator.h>
|
||||
#include <framework/globalfunctions/constants.h>
|
||||
#include <framework/globalfunctions/math/MatrixOperations.h>
|
||||
#include <framework/globalfunctions/math/VectorOperations.h>
|
||||
#include <framework/globalfunctions/timevalOperations.h>
|
||||
#include <framework/osal/OSAL.h>
|
||||
|
||||
#include <cstring>
|
||||
Sgp4Propagator::Sgp4Propagator() :
|
||||
whichconst(wgs84) {
|
||||
initialized(false), epoch({0, 0}), whichconst(wgs84) {
|
||||
|
||||
}
|
||||
|
||||
@ -16,7 +14,6 @@ Sgp4Propagator::~Sgp4Propagator() {
|
||||
|
||||
}
|
||||
|
||||
//TODO move to OSAL
|
||||
void jday(int year, int mon, int day, int hr, int minute, double sec,
|
||||
double& jd) {
|
||||
jd = 367.0 * year - floor((7 * (year + floor((mon + 9) / 12.0))) * 0.25)
|
||||
@ -25,7 +22,6 @@ void jday(int year, int mon, int day, int hr, int minute, double sec,
|
||||
// - 0.5*sgn(100.0*year + mon - 190002.5) + 0.5;
|
||||
}
|
||||
|
||||
//TODO move to OSAL
|
||||
void days2mdhms(int year, double days, int& mon, int& day, int& hr, int& minute,
|
||||
double& sec) {
|
||||
int i, inttemp, dayofyr;
|
||||
@ -169,14 +165,14 @@ ReturnValue_t Sgp4Propagator::initialize(const uint8_t* line1,
|
||||
|
||||
// ---------------- initialize the orbit at sgp4epoch -------------------
|
||||
uint8_t result = sgp4init(whichconst, satrec.satnum,
|
||||
satrec.jdsatepoch
|
||||
- 2433282.5 /*TODO verify, source says it's 2433281.5*/,
|
||||
satrec.bstar, satrec.ecco, satrec.argpo, satrec.inclo, satrec.mo,
|
||||
satrec.no, satrec.nodeo, satrec);
|
||||
satrec.jdsatepoch - 2433281.5, satrec.bstar, satrec.ecco,
|
||||
satrec.argpo, satrec.inclo, satrec.mo, satrec.no, satrec.nodeo,
|
||||
satrec);
|
||||
|
||||
if (result != 00) {
|
||||
return MAKE_RETURN_CODE(result);
|
||||
} else {
|
||||
initialized = true;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
@ -185,9 +181,14 @@ ReturnValue_t Sgp4Propagator::initialize(const uint8_t* line1,
|
||||
ReturnValue_t Sgp4Propagator::propagate(double* position, double* velocity,
|
||||
timeval time, uint8_t gpsUtcOffset) {
|
||||
|
||||
if (!initialized) {
|
||||
return TLE_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
//Time since epoch in minutes
|
||||
timeval timeSinceEpoch = time - epoch;
|
||||
double minutesSinceEpoch = timeSinceEpoch.tv_sec / 60. + timeSinceEpoch.tv_usec / 60000000.;
|
||||
double minutesSinceEpoch = timeSinceEpoch.tv_sec / 60.
|
||||
+ timeSinceEpoch.tv_usec / 60000000.;
|
||||
|
||||
double yearsSinceEpoch = minutesSinceEpoch / 60 / 24 / 365;
|
||||
|
||||
@ -206,8 +207,7 @@ ReturnValue_t Sgp4Propagator::propagate(double* position, double* velocity,
|
||||
|
||||
//Transform to ECF
|
||||
double earthRotationMatrix[3][3];
|
||||
CoordinateTransformations transform(gpsUtcOffset);
|
||||
transform.getEarthRotationMatrix(time,
|
||||
CoordinateTransformations::getEarthRotationMatrix(time,
|
||||
earthRotationMatrix);
|
||||
|
||||
MatrixOperations<double>::multiply(earthRotationMatrix[0], positionTEME,
|
||||
@ -221,7 +221,7 @@ ReturnValue_t Sgp4Propagator::propagate(double* position, double* velocity,
|
||||
VectorOperations<double>::subtract(velocity, velocityCorrection, velocity);
|
||||
|
||||
if (result != 0) {
|
||||
return MAKE_RETURN_CODE(result);
|
||||
return MAKE_RETURN_CODE(result || 0xB0);
|
||||
} else {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
@ -7,14 +7,15 @@
|
||||
|
||||
class Sgp4Propagator {
|
||||
public:
|
||||
static const uint8_t INTERFACE_ID = SGP4PROPAGATOR_CLASS;
|
||||
static const ReturnValue_t INVALID_ECCENTRICITY = MAKE_RETURN_CODE(0x01);
|
||||
static const ReturnValue_t INVALID_MEAN_MOTION = MAKE_RETURN_CODE(0x02);
|
||||
static const ReturnValue_t INVALID_PERTURBATION_ELEMENTS = MAKE_RETURN_CODE(0x03);
|
||||
static const ReturnValue_t INVALID_SEMI_LATUS_RECTUM = MAKE_RETURN_CODE(0x04);
|
||||
static const ReturnValue_t INVALID_EPOCH_ELEMENTS = MAKE_RETURN_CODE(0x05);
|
||||
static const ReturnValue_t SATELLITE_HAS_DECAYED = MAKE_RETURN_CODE(0x06);
|
||||
static const ReturnValue_t TLE_TOO_OLD = MAKE_RETURN_CODE(0xA1);
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::SGP4PROPAGATOR_CLASS;
|
||||
static const ReturnValue_t INVALID_ECCENTRICITY = MAKE_RETURN_CODE(0xA1);
|
||||
static const ReturnValue_t INVALID_MEAN_MOTION = MAKE_RETURN_CODE(0xA2);
|
||||
static const ReturnValue_t INVALID_PERTURBATION_ELEMENTS = MAKE_RETURN_CODE(0xA3);
|
||||
static const ReturnValue_t INVALID_SEMI_LATUS_RECTUM = MAKE_RETURN_CODE(0xA4);
|
||||
static const ReturnValue_t INVALID_EPOCH_ELEMENTS = MAKE_RETURN_CODE(0xA5);
|
||||
static const ReturnValue_t SATELLITE_HAS_DECAYED = MAKE_RETURN_CODE(0xA6);
|
||||
static const ReturnValue_t TLE_TOO_OLD = MAKE_RETURN_CODE(0xB1);
|
||||
static const ReturnValue_t TLE_NOT_INITIALIZED = MAKE_RETURN_CODE(0xB2);
|
||||
|
||||
|
||||
|
||||
@ -33,6 +34,7 @@ public:
|
||||
ReturnValue_t propagate(double *position, double *velocity, timeval time, uint8_t gpsUtcOffset);
|
||||
|
||||
private:
|
||||
bool initialized;
|
||||
timeval epoch;
|
||||
elsetrec satrec;
|
||||
gravconsttype whichconst;
|
||||
|
@ -15,8 +15,7 @@
|
||||
*/
|
||||
class CCSDSReturnValuesIF: public HasReturnvaluesIF {
|
||||
public:
|
||||
static const uint8_t INTERFACE_ID = CCSDS_HANDLER_IF; //!< Basic ID of the interface.
|
||||
static const ReturnValue_t FRAME_OK = RETURN_OK; //!< A value to indicate that a frame is ok.
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::CCSDS_HANDLER_IF; //!< Basic ID of the interface.
|
||||
|
||||
static const ReturnValue_t BC_IS_SET_VR_COMMAND = MAKE_RETURN_CODE( 0x01 ); //!< A value to describe a BC frame.
|
||||
static const ReturnValue_t BC_IS_UNLOCK_COMMAND = MAKE_RETURN_CODE( 0x02 ); //!< A value to describe a BC frame.
|
||||
|
@ -1,13 +1,5 @@
|
||||
/*
|
||||
* DataLinkLayer.cpp
|
||||
*
|
||||
* Created on: 02.03.2012
|
||||
* Author: baetz
|
||||
*/
|
||||
|
||||
#include <framework/datalinklayer/DataLinkLayer.h>
|
||||
#include <framework/globalfunctions/crc_ccitt.h>
|
||||
#include <framework/osal/OSAL.h>
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
|
||||
DataLinkLayer::DataLinkLayer(uint8_t* set_frame_buffer, ClcwIF* setClcw,
|
||||
@ -25,15 +17,15 @@ ReturnValue_t DataLinkLayer::frameDelimitingAndFillRemoval() {
|
||||
if ((receivedDataLength - startSequenceLength) < FRAME_PRIMARY_HEADER_LENGTH) {
|
||||
return SHORTER_THAN_HEADER;
|
||||
}
|
||||
//Removing start sequence
|
||||
//TODO: What does the start sequence look like? Better search for the pattern.
|
||||
//Removing start sequence.
|
||||
//SHOULDDO: Not implemented here.
|
||||
while ( *frameBuffer == START_SEQUENCE_PATTERN ) {
|
||||
frameBuffer++;
|
||||
}
|
||||
TcTransferFrame frame_candidate(frameBuffer);
|
||||
this->currentFrame = frame_candidate; //should work with shallow copy.
|
||||
|
||||
return FRAME_OK;
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t DataLinkLayer::frameValidationCheck() {
|
||||
@ -64,14 +56,14 @@ ReturnValue_t DataLinkLayer::frameValidationCheck() {
|
||||
if (USE_CRC) {
|
||||
return this->frameCheckCRC();
|
||||
}
|
||||
return FRAME_OK;
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t DataLinkLayer::frameCheckCRC() {
|
||||
uint16_t checkValue = ::Calculate_CRC(this->currentFrame.getFullFrame(),
|
||||
this->currentFrame.getFullSize());
|
||||
if (checkValue == 0) {
|
||||
return FRAME_OK;
|
||||
return RETURN_OK;
|
||||
} else {
|
||||
return CRC_FAILED;
|
||||
}
|
||||
@ -80,7 +72,7 @@ ReturnValue_t DataLinkLayer::frameCheckCRC() {
|
||||
|
||||
ReturnValue_t DataLinkLayer::allFramesReception() {
|
||||
ReturnValue_t status = this->frameDelimitingAndFillRemoval();
|
||||
if (status != FRAME_OK) {
|
||||
if (status != RETURN_OK) {
|
||||
return status;
|
||||
}
|
||||
return this->frameValidationCheck();
|
||||
@ -96,7 +88,7 @@ ReturnValue_t DataLinkLayer::virtualChannelDemultiplexing() {
|
||||
virtualChannelIterator iter = virtualChannels.find(vcId);
|
||||
if (iter == virtualChannels.end()) {
|
||||
//Do not report because passive board will get this error all the time.
|
||||
return FRAME_OK;
|
||||
return RETURN_OK;
|
||||
} else {
|
||||
return (iter->second)->frameAcceptanceAndReportingMechanism(¤tFrame, clcw);
|
||||
}
|
||||
@ -105,7 +97,7 @@ ReturnValue_t DataLinkLayer::virtualChannelDemultiplexing() {
|
||||
ReturnValue_t DataLinkLayer::processFrame(uint16_t length) {
|
||||
receivedDataLength = length;
|
||||
ReturnValue_t status = allFramesReception();
|
||||
if (status != FRAME_OK) {
|
||||
if (status != RETURN_OK) {
|
||||
error << "DataLinkLayer::processFrame: frame reception failed. Error code: " << std::hex
|
||||
<< status << std::dec << std::endl;
|
||||
// currentFrame.print();
|
||||
|
@ -1,10 +1,3 @@
|
||||
/*
|
||||
* DataLinkLayer.h
|
||||
*
|
||||
* Created on: Feb 29, 2012
|
||||
* Author: baetz
|
||||
*/
|
||||
|
||||
#ifndef DATALINKLAYER_H_
|
||||
#define DATALINKLAYER_H_
|
||||
|
||||
@ -26,11 +19,11 @@ class VirtualChannelReception;
|
||||
class DataLinkLayer : public CCSDSReturnValuesIF {
|
||||
public:
|
||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SYSTEM_1;
|
||||
static const Event RF_AVAILABLE = MAKE_EVENT(0, SEVERITY::INFO); //!< The CCSDS Board detected a RF available signal.
|
||||
static const Event RF_LOST = MAKE_EVENT(1, SEVERITY::INFO); //!< The CCSDS Board lost a previously found RF available signal.
|
||||
static const Event BIT_LOCK = MAKE_EVENT(2, SEVERITY::INFO); //!< The CCSDS Board detected a Bit Lock signal.
|
||||
static const Event BIT_LOCK_LOST = MAKE_EVENT(3, SEVERITY::INFO); //!< The CCSDS Board lost a previously found Bit Lock signal.
|
||||
static const Event RF_CHAIN_LOST = MAKE_EVENT(4, SEVERITY::INFO); //!< The CCSDS Board detected that either bit lock or RF available or both are lost.
|
||||
static const Event RF_AVAILABLE = MAKE_EVENT(0, SEVERITY::INFO); //!< A RF available signal was detected. P1: raw RFA state, P2: 0
|
||||
static const Event RF_LOST = MAKE_EVENT(1, SEVERITY::INFO); //!< A previously found RF available signal was lost. P1: raw RFA state, P2: 0
|
||||
static const Event BIT_LOCK = MAKE_EVENT(2, SEVERITY::INFO); //!< A Bit Lock signal. Was detected. P1: raw BLO state, P2: 0
|
||||
static const Event BIT_LOCK_LOST = MAKE_EVENT(3, SEVERITY::INFO); //!< A previously found Bit Lock signal was lost. P1: raw BLO state, P2: 0
|
||||
// static const Event RF_CHAIN_LOST = MAKE_EVENT(4, SEVERITY::INFO); //!< The CCSDS Board detected that either bit lock or RF available or both are lost. No parameters.
|
||||
static const Event FRAME_PROCESSING_FAILED = MAKE_EVENT(5, SEVERITY::LOW); //!< The CCSDS Board could not interpret a TC
|
||||
/**
|
||||
* The Constructor sets the passed parameters and nothing else.
|
||||
@ -80,19 +73,19 @@ private:
|
||||
std::map<uint8_t, VirtualChannelReceptionIF*> virtualChannels; //!< Map of all virtual channels assigned.
|
||||
/**
|
||||
* Method that performs all possible frame validity checks (as specified).
|
||||
* @return Various error codes or @c FRAME_OK on success.
|
||||
* @return Various error codes or @c RETURN_OK on success.
|
||||
*/
|
||||
ReturnValue_t frameValidationCheck();
|
||||
/**
|
||||
* First method to call.
|
||||
* Removes start sequence bytes and checks if the complete frame was received.
|
||||
* TODO: Maybe handling the start sequence must be done more variable.
|
||||
* @return @c FRAME_OK or @c TOO_SHORT.
|
||||
* SHOULDDO: Maybe handling the start sequence must be done more variable.
|
||||
* @return @c RETURN_OK or @c TOO_SHORT.
|
||||
*/
|
||||
ReturnValue_t frameDelimitingAndFillRemoval();
|
||||
/**
|
||||
* Small helper method to check the CRC of the Frame.
|
||||
* @return @c FRAME_OK or @c CRC_FAILED.
|
||||
* @return @c RETURN_OK or @c CRC_FAILED.
|
||||
*/
|
||||
ReturnValue_t frameCheckCRC();
|
||||
/**
|
||||
|
@ -22,7 +22,7 @@ ReturnValue_t Farm1StateOpen::handleADFrame(TcTransferFrame* frame,
|
||||
if (diff == 0 ) {
|
||||
myVC->vR++;
|
||||
clcw->setRetransmitFlag(false);
|
||||
return FRAME_OK;
|
||||
return RETURN_OK;
|
||||
} else if (diff < myVC->positiveWindow && diff > 0 ) {
|
||||
clcw->setRetransmitFlag(true);
|
||||
return NS_POSITIVE_W;
|
||||
|
@ -35,7 +35,7 @@ public:
|
||||
* change to Farm1StateLockout.
|
||||
* @param frame The frame to handle.
|
||||
* @param clcw Any changes to the CLCW shall be done with the help of this interface.
|
||||
* @return If the Sequence Number is ok, it returns #FRAME_OK. Otherwise either #NS_POSITIVE_W,
|
||||
* @return If the Sequence Number is ok, it returns #RETURN_OK. Otherwise either #NS_POSITIVE_W,
|
||||
* #NS_NEGATIVE_W or NS_LOCKOUT is returned.
|
||||
*/
|
||||
ReturnValue_t handleADFrame( TcTransferFrame* frame, ClcwIF* clcw );
|
||||
|
@ -6,17 +6,19 @@
|
||||
*/
|
||||
|
||||
#include <framework/datalinklayer/MapPacketExtraction.h>
|
||||
#include <framework/ipc/QueueFactory.h>
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
#include <framework/storagemanager/StorageManagerIF.h>
|
||||
#include <framework/tmtcpacket/SpacePacketBase.h>
|
||||
#include <framework/tmtcservices/AcceptsTelecommandsIF.h>
|
||||
#include <framework/tmtcservices/TmTcMessage.h>
|
||||
#include <string.h>
|
||||
|
||||
MapPacketExtraction::MapPacketExtraction(uint8_t setMapId,
|
||||
object_id_t setPacketDestination) :
|
||||
lastSegmentationFlag(NO_SEGMENTATION), mapId(setMapId), packetLength(0), bufferPosition(
|
||||
packetBuffer), packetDestination(setPacketDestination), packetStore(
|
||||
NULL) {
|
||||
NULL), tcQueueId(MessageQueueSenderIF::NO_QUEUE) {
|
||||
memset(packetBuffer, 0, sizeof(packetBuffer));
|
||||
}
|
||||
|
||||
@ -32,7 +34,7 @@ ReturnValue_t MapPacketExtraction::extractPackets(TcTransferFrame* frame) {
|
||||
if (packetLength <= MAX_PACKET_SIZE) {
|
||||
memcpy(packetBuffer, frame->getDataField(), packetLength);
|
||||
bufferPosition = &packetBuffer[packetLength];
|
||||
status = FRAME_OK;
|
||||
status = RETURN_OK;
|
||||
} else {
|
||||
error
|
||||
<< "MapPacketExtraction::extractPackets. Packet too large! Size: "
|
||||
@ -54,7 +56,7 @@ ReturnValue_t MapPacketExtraction::extractPackets(TcTransferFrame* frame) {
|
||||
status = sendCompletePacket(packetBuffer, packetLength);
|
||||
clearBuffers();
|
||||
}
|
||||
status = FRAME_OK;
|
||||
status = RETURN_OK;
|
||||
} else {
|
||||
error
|
||||
<< "MapPacketExtraction::extractPackets. Packet too large! Size: "
|
||||
@ -97,7 +99,7 @@ ReturnValue_t MapPacketExtraction::unpackBlockingPackets(
|
||||
packet.getFullSize());
|
||||
totalLength -= packet.getFullSize();
|
||||
position += packet.getFullSize();
|
||||
status = FRAME_OK;
|
||||
status = RETURN_OK;
|
||||
} else {
|
||||
status = DATA_CORRUPTED;
|
||||
totalLength = 0;
|
||||
@ -115,7 +117,7 @@ ReturnValue_t MapPacketExtraction::sendCompletePacket(uint8_t* data,
|
||||
ReturnValue_t status = this->packetStore->addData(&store_id, data, size);
|
||||
if (status == RETURN_OK) {
|
||||
TmTcMessage message(store_id);
|
||||
status = this->tcQueue.sendToDefault(&message);
|
||||
status = MessageQueueSenderIF::sendMessage(tcQueueId,&message);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@ -132,7 +134,7 @@ ReturnValue_t MapPacketExtraction::initialize() {
|
||||
AcceptsTelecommandsIF* distributor = objectManager->get<
|
||||
AcceptsTelecommandsIF>(packetDestination);
|
||||
if ((packetStore != NULL) && (distributor != NULL)) {
|
||||
tcQueue.setDefaultDestination(distributor->getRequestQueue());
|
||||
tcQueueId = distributor->getRequestQueue();
|
||||
return RETURN_OK;
|
||||
} else {
|
||||
return RETURN_FAILED;
|
||||
|
@ -9,9 +9,10 @@
|
||||
#define MAPPACKETEXTRACTION_H_
|
||||
|
||||
#include <framework/datalinklayer/MapPacketExtractionIF.h>
|
||||
#include <framework/ipc/MessageQueueSender.h>
|
||||
#include <framework/objectmanager/ObjectManagerIF.h>
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <framework/ipc/MessageQueueSenderIF.h>
|
||||
|
||||
class StorageManagerIF;
|
||||
|
||||
/**
|
||||
@ -30,7 +31,7 @@ private:
|
||||
uint8_t packetBuffer[MAX_PACKET_SIZE]; //!< The internal Space Packet Buffer.
|
||||
object_id_t packetDestination;
|
||||
StorageManagerIF* packetStore; //!< Pointer to the store where full TC packets are stored.
|
||||
MessageQueueSender tcQueue; //!< Sender Queue to send found packets to the distributor.
|
||||
MessageQueueId_t tcQueueId; //!< QueueId to send found packets to the distributor.
|
||||
/**
|
||||
* Debug method to print the packet Buffer's content.
|
||||
*/
|
||||
@ -39,7 +40,7 @@ private:
|
||||
* Method that is called if the segmentation flag is @c NO_SEGMENTATION.
|
||||
* The method extracts one or more packets within the frame and forwards them to the OBSW.
|
||||
* @param frame The TC Transfer Frame to work on.
|
||||
* @return @c FRAME_OK if all Packets were extracted. If something is entirely wrong,
|
||||
* @return @c RETURN_OK if all Packets were extracted. If something is entirely wrong,
|
||||
* @c DATA_CORRUPTED is returned, if some bytes are left over @c RESIDUAL_DATA.
|
||||
*/
|
||||
ReturnValue_t unpackBlockingPackets(TcTransferFrame* frame);
|
||||
|
@ -48,15 +48,22 @@ ReturnValue_t VirtualChannelReception::doFARM(TcTransferFrame* frame, ClcwIF* cl
|
||||
|
||||
ReturnValue_t VirtualChannelReception::frameAcceptanceAndReportingMechanism(TcTransferFrame* frame,
|
||||
ClcwIF* clcw) {
|
||||
ReturnValue_t status = FRAME_OK;
|
||||
status = doFARM(frame, &internalClcw);
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
result = doFARM(frame, &internalClcw);
|
||||
internalClcw.setReceiverFrameSequenceNumber(vR);
|
||||
internalClcw.setFarmBCount(farmBCounter);
|
||||
clcw->setWhole(internalClcw.getAsWhole());
|
||||
if (status == FRAME_OK) {
|
||||
status = mapDemultiplexing(frame);
|
||||
switch (result) {
|
||||
case RETURN_OK:
|
||||
return mapDemultiplexing(frame);
|
||||
case BC_IS_SET_VR_COMMAND:
|
||||
case BC_IS_UNLOCK_COMMAND:
|
||||
//Need to catch these codes to avoid error reporting later.
|
||||
return RETURN_OK;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return status;
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t VirtualChannelReception::addMapChannel(uint8_t mapId, MapPacketExtractionIF* object) {
|
||||
@ -71,7 +78,7 @@ ReturnValue_t VirtualChannelReception::addMapChannel(uint8_t mapId, MapPacketExt
|
||||
|
||||
ReturnValue_t VirtualChannelReception::handleBDFrame(TcTransferFrame* frame, ClcwIF* clcw) {
|
||||
farmBCounter++;
|
||||
return FRAME_OK;
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t VirtualChannelReception::handleBCFrame(TcTransferFrame* frame, ClcwIF* clcw) {
|
||||
|
@ -67,7 +67,7 @@ protected:
|
||||
* required.
|
||||
* @param frame The Tc Transfer Frame to handle.
|
||||
* @param clcw Any changes on the CLCW shall be done with this method.
|
||||
* @return Always returns @c FRAME_OK.
|
||||
* @return Always returns @c RETURN_OK.
|
||||
*/
|
||||
ReturnValue_t handleBDFrame( TcTransferFrame* frame, ClcwIF* clcw );
|
||||
/**
|
||||
|
@ -38,7 +38,7 @@ public:
|
||||
* Handling the Frame includes forwarding to higher-level procedures.
|
||||
* @param frame The Tc Transfer Frame that was received and checked.
|
||||
* @param clcw Any changes to the CLCW value are forwarded by using this parameter.
|
||||
* @return The return Value shall indicate successful processing with @c FRAME_OK.
|
||||
* @return The return Value shall indicate successful processing with @c RETURN_OK.
|
||||
*/
|
||||
virtual ReturnValue_t frameAcceptanceAndReportingMechanism( TcTransferFrame* frame, ClcwIF* clcw ) = 0;
|
||||
/**
|
||||
|
14
datapool/ControllerSet.cpp
Normal file
14
datapool/ControllerSet.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
#include <framework/datapool/ControllerSet.h>
|
||||
|
||||
ControllerSet::ControllerSet() {
|
||||
|
||||
}
|
||||
|
||||
ControllerSet::~ControllerSet() {
|
||||
}
|
||||
|
||||
void ControllerSet::setInvalid() {
|
||||
read();
|
||||
setToDefault();
|
||||
commit(PoolVariableIF::INVALID);
|
||||
}
|
15
datapool/ControllerSet.h
Normal file
15
datapool/ControllerSet.h
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef CONTROLLERSET_H_
|
||||
#define CONTROLLERSET_H_
|
||||
|
||||
#include <framework/datapool/DataSet.h>
|
||||
|
||||
class ControllerSet :public DataSet {
|
||||
public:
|
||||
ControllerSet();
|
||||
virtual ~ControllerSet();
|
||||
|
||||
virtual void setToDefault() = 0;
|
||||
void setInvalid();
|
||||
};
|
||||
|
||||
#endif /* CONTROLLERSET_H_ */
|
@ -1,24 +1,16 @@
|
||||
/*
|
||||
* DataPool.cpp
|
||||
*
|
||||
* Created on: 17.10.2012
|
||||
* Author: baetz
|
||||
*/
|
||||
|
||||
|
||||
#include <framework/datapool/DataPool.h>
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
#include <framework/ipc/MutexFactory.h>
|
||||
|
||||
DataPool::DataPool( void ( *initFunction )( std::map<uint32_t, PoolEntryIF*>* pool_map ) ) {
|
||||
this->mutex = new MutexId_t;
|
||||
OSAL::createMutex( OSAL::buildName('M','T','X','0'), ( this->mutex ) );
|
||||
mutex = MutexFactory::instance()->createMutex();
|
||||
if (initFunction != NULL ) {
|
||||
initFunction( &this->data_pool );
|
||||
}
|
||||
}
|
||||
|
||||
DataPool::~DataPool() {
|
||||
OSAL::deleteMutex( this->mutex );
|
||||
delete this->mutex;
|
||||
MutexFactory::instance()->deleteMutex(mutex);
|
||||
for ( std::map<uint32_t, PoolEntryIF*>::iterator it = this->data_pool.begin(); it != this->data_pool.end(); ++it ) {
|
||||
delete it->second;
|
||||
}
|
||||
@ -61,7 +53,7 @@ PoolEntryIF* DataPool::getRawData( uint32_t data_pool_id ) {
|
||||
//}
|
||||
|
||||
ReturnValue_t DataPool::freeDataPoolLock() {
|
||||
ReturnValue_t status = OSAL::unlockMutex( this->mutex );
|
||||
ReturnValue_t status = mutex->unlockMutex();
|
||||
if ( status != RETURN_OK ) {
|
||||
error << "DataPool::DataPool: unlock of mutex failed with error code: " << status << std::endl;
|
||||
}
|
||||
@ -69,7 +61,7 @@ ReturnValue_t DataPool::freeDataPoolLock() {
|
||||
}
|
||||
|
||||
ReturnValue_t DataPool::lockDataPool() {
|
||||
ReturnValue_t status = OSAL::lockMutex( this->mutex, OSAL::NO_TIMEOUT );
|
||||
ReturnValue_t status = mutex->lockMutex(MutexIF::NO_TIMEOUT);
|
||||
if ( status != RETURN_OK ) {
|
||||
error << "DataPool::DataPool: lock of mutex failed with error code: " << status << std::endl;
|
||||
}
|
||||
@ -112,14 +104,17 @@ uint32_t DataPool::poolIdAndPositionToPid(uint32_t poolId, uint8_t index) {
|
||||
return (poolId << 8) + index;
|
||||
}
|
||||
|
||||
//TODO: This is not 100% clean. Should return returnValue and type by passing...
|
||||
//TODO: Do we need a mutex lock here... I don't think so, as we only check static const values of elements in a list that do not change.
|
||||
Type DataPool::getType(uint32_t parameter_id) {
|
||||
|
||||
//SHOULDDO: Do we need a mutex lock here... I don't think so, as we only check static const values of elements in a list that do not change.
|
||||
//there is no guarantee in the standard, but it seems to me that the implementation is safe -UM
|
||||
ReturnValue_t DataPool::getType(uint32_t parameter_id, Type* type) {
|
||||
std::map<uint32_t, PoolEntryIF*>::iterator it = this->data_pool.find( PIDToDataPoolId(parameter_id));
|
||||
if ( it != this->data_pool.end() ) {
|
||||
return it->second->getType();
|
||||
*type = it->second->getType();
|
||||
return RETURN_OK;
|
||||
} else {
|
||||
return Type::UNKNOWN_TYPE;
|
||||
*type = Type::UNKNOWN_TYPE;
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
#include <framework/datapool/PoolEntry.h>
|
||||
#include <framework/globalfunctions/Type.h>
|
||||
#include <framework/osal/OSAL.h>
|
||||
#include <framework/ipc/MutexIF.h>
|
||||
#include <map>
|
||||
|
||||
/**
|
||||
@ -50,7 +50,7 @@ public:
|
||||
* \brief The mutex is created in the constructor and makes access mutual exclusive.
|
||||
* \details Locking and unlocking the pool is only done by the DataSet class.
|
||||
*/
|
||||
MutexId_t* mutex;
|
||||
MutexIF* mutex;
|
||||
/**
|
||||
* \brief In the classes constructor, the passed initialization function is called.
|
||||
* \details To enable filling the pool,
|
||||
@ -113,7 +113,14 @@ public:
|
||||
*/
|
||||
static uint32_t poolIdAndPositionToPid( uint32_t poolId, uint8_t index );
|
||||
|
||||
Type getType( uint32_t parameter_id );
|
||||
/**
|
||||
* Method to return the type of a pool variable.
|
||||
* @param parameter_id A parameterID (not pool id) of a DP member.
|
||||
* @param type Returns the type or TYPE::UNKNOWN_TYPE
|
||||
* @return RETURN_OK if parameter exists, RETURN_FAILED else.
|
||||
*/
|
||||
ReturnValue_t getType( uint32_t parameter_id, Type* type );
|
||||
|
||||
/**
|
||||
* Method to check if a PID exists.
|
||||
* Does not lock, as there's no possibility to alter the list that is checked during run-time.
|
||||
@ -123,7 +130,6 @@ public:
|
||||
bool exists(uint32_t parameterId);
|
||||
};
|
||||
|
||||
//TODO: Remove this, if data pool is get by Satellite Manager
|
||||
//Better make clean Singleton.
|
||||
//We assume someone globally instantiates a DataPool.
|
||||
extern DataPool dataPool;
|
||||
#endif /* DATAPOOL_H_ */
|
||||
|
@ -1,67 +1,126 @@
|
||||
/*
|
||||
* DataPoolAdmin.cpp
|
||||
*
|
||||
* Created on: 05.12.2013
|
||||
* Author: baetz
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <framework/datapool/DataPool.h>
|
||||
#include <framework/datapool/DataPoolAdmin.h>
|
||||
#include <framework/datapool/DataSet.h>
|
||||
#include <framework/datapool/PoolRawAccess.h>
|
||||
#include <framework/ipc/CommandMessage.h>
|
||||
#include <framework/ipc/QueueFactory.h>
|
||||
#include <framework/parameters/ParameterMessage.h>
|
||||
|
||||
|
||||
DataPoolAdmin::DataPoolAdmin(object_id_t objectId ) : SystemObject(objectId), commandQueue(), memoryHelper(this, &commandQueue){
|
||||
DataPoolAdmin::DataPoolAdmin(object_id_t objectId) :
|
||||
SystemObject(objectId), storage(NULL), commandQueue(NULL), memoryHelper(
|
||||
this, commandQueue), actionHelper(this, commandQueue) {
|
||||
commandQueue = QueueFactory::instance()->createMessageQueue();
|
||||
}
|
||||
|
||||
ReturnValue_t DataPoolAdmin::performOperation() {
|
||||
DataPoolAdmin::~DataPoolAdmin() {
|
||||
QueueFactory::instance()->deleteMessageQueue(commandQueue);
|
||||
}
|
||||
|
||||
ReturnValue_t DataPoolAdmin::performOperation(uint8_t opCode) {
|
||||
handleCommand();
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
MessageQueueId_t DataPoolAdmin::getCommandQueue() const {
|
||||
return commandQueue.getId();
|
||||
return commandQueue->getId();
|
||||
}
|
||||
|
||||
ReturnValue_t DataPoolAdmin::executeAction(ActionId_t actionId,
|
||||
MessageQueueId_t commandedBy, const uint8_t* data, uint32_t size) {
|
||||
if (actionId != SET_VALIDITY) {
|
||||
return INVALID_ACTION_ID;
|
||||
}
|
||||
|
||||
if (size != 5) {
|
||||
return INVALID_PARAMETERS;
|
||||
}
|
||||
|
||||
uint32_t address = (data[0] << 24) | (data[1] << 16) | (data[2] << 8)
|
||||
| data[3];
|
||||
|
||||
uint8_t valid = data[4];
|
||||
|
||||
uint32_t poolId = ::dataPool.PIDToDataPoolId(address);
|
||||
|
||||
DataSet mySet;
|
||||
PoolRawAccess variable(poolId, 0, &mySet, PoolVariableIF::VAR_READ_WRITE);
|
||||
ReturnValue_t status = mySet.read();
|
||||
if (status != RETURN_OK) {
|
||||
return INVALID_ADDRESS;
|
||||
}
|
||||
if (valid != 0) {
|
||||
variable.setValid(PoolVariableIF::VALID);
|
||||
} else {
|
||||
variable.setValid(PoolVariableIF::INVALID);
|
||||
}
|
||||
|
||||
mySet.commit();
|
||||
|
||||
return EXECUTION_FINISHED;
|
||||
}
|
||||
|
||||
ReturnValue_t DataPoolAdmin::getParameter(uint8_t domainId,
|
||||
uint16_t parameterId, ParameterWrapper* parameterWrapper,
|
||||
const ParameterWrapper* newValues, uint16_t startAtIndex) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
void DataPoolAdmin::handleCommand() {
|
||||
CommandMessage command;
|
||||
ReturnValue_t result = commandQueue.receiveMessage(&command);
|
||||
ReturnValue_t result = commandQueue->receiveMessage(&command);
|
||||
if (result != RETURN_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
result = actionHelper.handleActionMessage(&command);
|
||||
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
result = handleParameterCommand(&command);
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
result = memoryHelper.handleMemoryCommand(&command);
|
||||
if (result != RETURN_OK) {
|
||||
command.setToUnknownCommand(command.getCommand());
|
||||
commandQueue.reply( &command );
|
||||
command.setToUnknownCommand();
|
||||
commandQueue->reply(&command);
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t DataPoolAdmin::handleMemoryLoad(uint32_t address,
|
||||
const uint8_t* data, uint32_t size, uint8_t** dataPointer) {
|
||||
uint32_t poolId = ::dataPool.PIDToDataPoolId( address );
|
||||
uint8_t arrayIndex = ::dataPool.PIDToArrayIndex( address );
|
||||
uint32_t poolId = ::dataPool.PIDToDataPoolId(address);
|
||||
uint8_t arrayIndex = ::dataPool.PIDToArrayIndex(address);
|
||||
DataSet testSet;
|
||||
PoolRawAccess varToGetSize( poolId, arrayIndex, &testSet, PoolVariableIF::VAR_READ );
|
||||
PoolRawAccess varToGetSize(poolId, arrayIndex, &testSet,
|
||||
PoolVariableIF::VAR_READ);
|
||||
ReturnValue_t status = testSet.read();
|
||||
if (status != RETURN_OK) {
|
||||
return INVALID_ADDRESS;
|
||||
}
|
||||
uint8_t typeSize = varToGetSize.getSizeOfType();
|
||||
if ( size > varToGetSize.getSizeTillEnd() ) {
|
||||
|
||||
if (size % typeSize != 0) {
|
||||
return INVALID_SIZE;
|
||||
}
|
||||
|
||||
if (size > varToGetSize.getSizeTillEnd()) {
|
||||
return INVALID_SIZE;
|
||||
}
|
||||
const uint8_t* readPosition = data;
|
||||
for ( ; size > 0; size -= typeSize ) {
|
||||
|
||||
for (; size > 0; size -= typeSize) {
|
||||
DataSet rawSet;
|
||||
PoolRawAccess variable( poolId, arrayIndex, &rawSet, PoolVariableIF::VAR_READ_WRITE );
|
||||
PoolRawAccess variable(poolId, arrayIndex, &rawSet,
|
||||
PoolVariableIF::VAR_READ_WRITE);
|
||||
status = rawSet.read();
|
||||
if (status == RETURN_OK) {
|
||||
status = variable.setEntryFromBigEndian( readPosition, typeSize );
|
||||
status = variable.setEntryFromBigEndian(readPosition, typeSize);
|
||||
if (status == RETURN_OK) {
|
||||
status = rawSet.commit(PoolVariableIF::VALID);
|
||||
status = rawSet.commit();
|
||||
}
|
||||
}
|
||||
arrayIndex += 1;
|
||||
@ -72,27 +131,29 @@ ReturnValue_t DataPoolAdmin::handleMemoryLoad(uint32_t address,
|
||||
|
||||
ReturnValue_t DataPoolAdmin::handleMemoryDump(uint32_t address, uint32_t size,
|
||||
uint8_t** dataPointer, uint8_t* copyHere) {
|
||||
uint32_t poolId = ::dataPool.PIDToDataPoolId( address );
|
||||
uint8_t arrayIndex = ::dataPool.PIDToArrayIndex( address );
|
||||
uint32_t poolId = ::dataPool.PIDToDataPoolId(address);
|
||||
uint8_t arrayIndex = ::dataPool.PIDToArrayIndex(address);
|
||||
DataSet testSet;
|
||||
PoolRawAccess varToGetSize( poolId, arrayIndex, &testSet, PoolVariableIF::VAR_READ );
|
||||
PoolRawAccess varToGetSize(poolId, arrayIndex, &testSet,
|
||||
PoolVariableIF::VAR_READ);
|
||||
ReturnValue_t status = testSet.read();
|
||||
if (status != RETURN_OK) {
|
||||
return INVALID_ADDRESS;
|
||||
}
|
||||
uint8_t typeSize = varToGetSize.getSizeOfType();
|
||||
if ( size > varToGetSize.getSizeTillEnd() ) {
|
||||
if (size > varToGetSize.getSizeTillEnd()) {
|
||||
return INVALID_SIZE;
|
||||
}
|
||||
uint8_t* ptrToCopy = copyHere;
|
||||
for ( ; size > 0; size -= typeSize ) {
|
||||
for (; size > 0; size -= typeSize) {
|
||||
DataSet rawSet;
|
||||
PoolRawAccess variable( poolId, arrayIndex, &rawSet, PoolVariableIF::VAR_READ );
|
||||
PoolRawAccess variable(poolId, arrayIndex, &rawSet,
|
||||
PoolVariableIF::VAR_READ);
|
||||
status = rawSet.read();
|
||||
if (status == RETURN_OK) {
|
||||
uint32_t temp = 0;
|
||||
status = variable.getEntryEndianSafe( ptrToCopy, &temp, size);
|
||||
if ( status != RETURN_OK ) {
|
||||
status = variable.getEntryEndianSafe(ptrToCopy, &temp, size);
|
||||
if (status != RETURN_OK) {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
} else {
|
||||
@ -105,8 +166,135 @@ ReturnValue_t DataPoolAdmin::handleMemoryDump(uint32_t address, uint32_t size,
|
||||
}
|
||||
|
||||
ReturnValue_t DataPoolAdmin::initialize() {
|
||||
if (memoryHelper.initialize() == RETURN_OK) {
|
||||
return SystemObject::initialize();
|
||||
ReturnValue_t result = SystemObject::initialize();
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
return RETURN_FAILED;
|
||||
|
||||
result = memoryHelper.initialize();
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
storage = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
|
||||
if (storage == NULL) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
result = actionHelper.initialize();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//mostly identical to ParameterHelper::handleParameterMessage()
|
||||
ReturnValue_t DataPoolAdmin::handleParameterCommand(CommandMessage* command) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
|
||||
switch (command->getCommand()) {
|
||||
case ParameterMessage::CMD_PARAMETER_DUMP: {
|
||||
uint8_t domain = HasParametersIF::getDomain(
|
||||
ParameterMessage::getParameterId(command));
|
||||
uint16_t parameterId = HasParametersIF::getMatrixId(
|
||||
ParameterMessage::getParameterId(command));
|
||||
|
||||
DataPoolParameterWrapper wrapper;
|
||||
result = wrapper.set(domain, parameterId);
|
||||
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
result = sendParameter(command->getSender(),
|
||||
ParameterMessage::getParameterId(command), &wrapper);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ParameterMessage::CMD_PARAMETER_LOAD: {
|
||||
|
||||
uint8_t domain = HasParametersIF::getDomain(
|
||||
ParameterMessage::getParameterId(command));
|
||||
uint16_t parameterId = HasParametersIF::getMatrixId(
|
||||
ParameterMessage::getParameterId(command));
|
||||
uint8_t index = HasParametersIF::getIndex(
|
||||
ParameterMessage::getParameterId(command));
|
||||
|
||||
const uint8_t *storedStream;
|
||||
uint32_t storedStreamSize;
|
||||
result = storage->getData(ParameterMessage::getStoreId(command),
|
||||
&storedStream, &storedStreamSize);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
break;
|
||||
}
|
||||
|
||||
ParameterWrapper streamWrapper;
|
||||
result = streamWrapper.set(storedStream, storedStreamSize);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
storage->deleteData(ParameterMessage::getStoreId(command));
|
||||
break;
|
||||
}
|
||||
|
||||
DataPoolParameterWrapper poolWrapper;
|
||||
result = poolWrapper.set(domain, parameterId);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
storage->deleteData(ParameterMessage::getStoreId(command));
|
||||
break;
|
||||
}
|
||||
|
||||
result = poolWrapper.copyFrom(&streamWrapper, index);
|
||||
|
||||
storage->deleteData(ParameterMessage::getStoreId(command));
|
||||
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
result = sendParameter(command->getSender(),
|
||||
ParameterMessage::getParameterId(command), &poolWrapper);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
rejectCommand(command->getSender(), result, command->getCommand());
|
||||
}
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
|
||||
}
|
||||
|
||||
//identical to ParameterHelper::sendParameter()
|
||||
ReturnValue_t DataPoolAdmin::sendParameter(MessageQueueId_t to, uint32_t id,
|
||||
const DataPoolParameterWrapper* wrapper) {
|
||||
uint32_t serializedSize = wrapper->getSerializedSize();
|
||||
|
||||
uint8_t *storeElement;
|
||||
store_address_t address;
|
||||
|
||||
ReturnValue_t result = storage->getFreeElement(&address, serializedSize,
|
||||
&storeElement);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t storeElementSize = 0;
|
||||
|
||||
result = wrapper->serialize(&storeElement, &storeElementSize,
|
||||
serializedSize, true);
|
||||
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
storage->deleteData(address);
|
||||
return result;
|
||||
}
|
||||
|
||||
CommandMessage reply;
|
||||
|
||||
ParameterMessage::setParameterDumpReply(&reply, id, address);
|
||||
|
||||
commandQueue->sendMessage(to, &reply);
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
//identical to ParameterHelper::rejectCommand()
|
||||
void DataPoolAdmin::rejectCommand(MessageQueueId_t to, ReturnValue_t reason,
|
||||
Command_t initialCommand) {
|
||||
CommandMessage reply;
|
||||
reply.setReplyRejected(reason, initialCommand);
|
||||
commandQueue->sendMessage(to, &reply);
|
||||
}
|
||||
|
@ -1,35 +1,58 @@
|
||||
/*
|
||||
* DataPoolAdmin.h
|
||||
*
|
||||
* Created on: 05.12.2013
|
||||
* Author: baetz
|
||||
*/
|
||||
|
||||
#ifndef DATAPOOLADMIN_H_
|
||||
#define DATAPOOLADMIN_H_
|
||||
|
||||
#include <framework/ipc/MessageQueue.h>
|
||||
#include <framework/memory/MemoryHelper.h>
|
||||
#include <framework/action/HasActionsIF.h>
|
||||
#include <framework/action/SimpleActionHelper.h>
|
||||
#include <framework/objectmanager/SystemObject.h>
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <framework/tasks/ExecutableObjectIF.h>
|
||||
#include <framework/parameters/ReceivesParameterMessagesIF.h>
|
||||
#include <framework/datapool/DataPoolParameterWrapper.h>
|
||||
#include <framework/ipc/MessageQueueIF.h>
|
||||
|
||||
class DataPoolAdmin : public ExecutableObjectIF, public AcceptsMemoryMessagesIF, public HasReturnvaluesIF, public SystemObject {
|
||||
private:
|
||||
MessageQueue commandQueue;
|
||||
MemoryHelper memoryHelper;
|
||||
void handleCommand();
|
||||
class DataPoolAdmin: public HasActionsIF,
|
||||
public ExecutableObjectIF,
|
||||
public AcceptsMemoryMessagesIF,
|
||||
public HasReturnvaluesIF,
|
||||
public ReceivesParameterMessagesIF,
|
||||
public SystemObject {
|
||||
public:
|
||||
static const ActionId_t SET_VALIDITY = 1;
|
||||
|
||||
DataPoolAdmin(object_id_t objectId);
|
||||
|
||||
ReturnValue_t performOperation();
|
||||
~DataPoolAdmin();
|
||||
|
||||
ReturnValue_t performOperation(uint8_t opCode);
|
||||
|
||||
MessageQueueId_t getCommandQueue() const;
|
||||
|
||||
ReturnValue_t handleMemoryLoad(uint32_t address, const uint8_t* data, uint32_t size, uint8_t** dataPointer);
|
||||
ReturnValue_t handleMemoryDump(uint32_t address, uint32_t size, uint8_t** dataPointer, uint8_t* copyHere );
|
||||
ReturnValue_t handleMemoryLoad(uint32_t address, const uint8_t* data,
|
||||
uint32_t size, uint8_t** dataPointer);
|
||||
ReturnValue_t handleMemoryDump(uint32_t address, uint32_t size,
|
||||
uint8_t** dataPointer, uint8_t* copyHere);
|
||||
|
||||
ReturnValue_t executeAction(ActionId_t actionId,
|
||||
MessageQueueId_t commandedBy, const uint8_t* data, uint32_t size);
|
||||
|
||||
//not implemented as ParameterHelper is no used
|
||||
ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
||||
ParameterWrapper *parameterWrapper,
|
||||
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
||||
|
||||
ReturnValue_t initialize();
|
||||
private:
|
||||
StorageManagerIF *storage;
|
||||
MessageQueueIF* commandQueue;
|
||||
MemoryHelper memoryHelper;
|
||||
SimpleActionHelper actionHelper;
|
||||
void handleCommand();
|
||||
ReturnValue_t handleParameterCommand(CommandMessage *command);
|
||||
ReturnValue_t sendParameter(MessageQueueId_t to, uint32_t id,
|
||||
const DataPoolParameterWrapper* wrapper);
|
||||
void rejectCommand(MessageQueueId_t to, ReturnValue_t reason,
|
||||
Command_t initialCommand);
|
||||
};
|
||||
|
||||
|
||||
#endif /* DATAPOOLADMIN_H_ */
|
||||
|
181
datapool/DataPoolParameterWrapper.cpp
Normal file
181
datapool/DataPoolParameterWrapper.cpp
Normal file
@ -0,0 +1,181 @@
|
||||
#include "DataPoolParameterWrapper.h"
|
||||
|
||||
//for returncodes
|
||||
#include <framework/parameters/HasParametersIF.h>
|
||||
|
||||
#include <framework/datapool/DataSet.h>
|
||||
#include <framework/datapool/PoolRawAccess.h>
|
||||
|
||||
DataPoolParameterWrapper::DataPoolParameterWrapper() :
|
||||
type(Type::UNKNOWN_TYPE), rows(0), columns(0), poolId(
|
||||
PoolVariableIF::NO_PARAMETER) {
|
||||
|
||||
}
|
||||
|
||||
DataPoolParameterWrapper::~DataPoolParameterWrapper() {
|
||||
|
||||
}
|
||||
|
||||
ReturnValue_t DataPoolParameterWrapper::set(uint8_t domainId,
|
||||
uint16_t parameterId) {
|
||||
poolId = (domainId << 16) + parameterId;
|
||||
|
||||
DataSet mySet;
|
||||
PoolRawAccess raw(poolId, 0, &mySet, PoolVariableIF::VAR_READ);
|
||||
ReturnValue_t status = mySet.read();
|
||||
if (status != HasReturnvaluesIF::RETURN_OK) {
|
||||
//should only fail for invalid pool id
|
||||
return HasParametersIF::INVALID_MATRIX_ID;
|
||||
}
|
||||
|
||||
type = raw.getType();
|
||||
rows = raw.getArraySize();
|
||||
columns = 1;
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t DataPoolParameterWrapper::serialize(uint8_t** buffer,
|
||||
uint32_t* size, const uint32_t max_size, bool bigEndian) const {
|
||||
ReturnValue_t result;
|
||||
|
||||
result = SerializeAdapter<Type>::serialize(&type, buffer, size, max_size,
|
||||
bigEndian);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = SerializeAdapter<uint8_t>::serialize(&columns, buffer, size,
|
||||
max_size, bigEndian);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
result = SerializeAdapter<uint8_t>::serialize(&rows, buffer, size, max_size,
|
||||
bigEndian);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
for (uint8_t index = 0; index < rows; index++){
|
||||
DataSet mySet;
|
||||
PoolRawAccess raw(poolId, index, &mySet,PoolVariableIF::VAR_READ);
|
||||
mySet.read();
|
||||
result = raw.serialize(buffer,size,max_size,bigEndian);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK){
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
//same as ParameterWrapper
|
||||
uint32_t DataPoolParameterWrapper::getSerializedSize() const {
|
||||
uint32_t serializedSize = 0;
|
||||
serializedSize += type.getSerializedSize();
|
||||
serializedSize += sizeof(rows);
|
||||
serializedSize += sizeof(columns);
|
||||
serializedSize += rows * columns * type.getSize();
|
||||
|
||||
return serializedSize;
|
||||
}
|
||||
|
||||
ReturnValue_t DataPoolParameterWrapper::deSerialize(const uint8_t** buffer,
|
||||
int32_t* size, bool bigEndian) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ReturnValue_t DataPoolParameterWrapper::deSerializeData(uint8_t startingRow,
|
||||
uint8_t startingColumn, const void* from, uint8_t fromRows) {
|
||||
//treat from as a continuous Stream as we copy all of it
|
||||
const uint8_t *fromAsStream = (const uint8_t *) from;
|
||||
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
|
||||
for (uint8_t fromRow = 0; fromRow < fromRows; fromRow++) {
|
||||
|
||||
DataSet mySet;
|
||||
PoolRawAccess raw(poolId, startingRow + fromRow, &mySet,
|
||||
PoolVariableIF::VAR_READ_WRITE);
|
||||
mySet.read();
|
||||
|
||||
result = raw.setEntryFromBigEndian(fromAsStream, sizeof(T));
|
||||
|
||||
fromAsStream += sizeof(T);
|
||||
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
mySet.commit();
|
||||
}
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t DataPoolParameterWrapper::copyFrom(const ParameterWrapper* from,
|
||||
uint16_t startWritingAtIndex) {
|
||||
if (poolId == PoolVariableIF::NO_PARAMETER) {
|
||||
return ParameterWrapper::NOT_SET;
|
||||
}
|
||||
|
||||
if (type != from->type) {
|
||||
return ParameterWrapper::DATATYPE_MISSMATCH;
|
||||
}
|
||||
|
||||
//check if from fits into this
|
||||
uint8_t startingRow = startWritingAtIndex / columns;
|
||||
uint8_t startingColumn = startWritingAtIndex % columns;
|
||||
|
||||
if ((from->rows > (rows - startingRow))
|
||||
|| (from->columns > (columns - startingColumn))) {
|
||||
return ParameterWrapper::TOO_BIG;
|
||||
}
|
||||
|
||||
ReturnValue_t result;
|
||||
//copy data
|
||||
if (from->pointsToStream) {
|
||||
switch (type) {
|
||||
case Type::UINT8_T:
|
||||
result = deSerializeData<uint8_t>(startingRow, startingColumn,
|
||||
from->readonlyData, from->rows);
|
||||
break;
|
||||
case Type::INT8_T:
|
||||
result = deSerializeData<int8_t>(startingRow, startingColumn,
|
||||
from->readonlyData, from->rows);
|
||||
break;
|
||||
case Type::UINT16_T:
|
||||
result = deSerializeData<uint16_t>(startingRow, startingColumn,
|
||||
from->readonlyData, from->rows);
|
||||
break;
|
||||
case Type::INT16_T:
|
||||
result = deSerializeData<int16_t>(startingRow, startingColumn,
|
||||
from->readonlyData, from->rows);
|
||||
break;
|
||||
case Type::UINT32_T:
|
||||
result = deSerializeData<uint32_t>(startingRow, startingColumn,
|
||||
from->readonlyData, from->rows);
|
||||
break;
|
||||
case Type::INT32_T:
|
||||
result = deSerializeData<int32_t>(startingRow, startingColumn,
|
||||
from->readonlyData, from->rows);
|
||||
break;
|
||||
case Type::FLOAT:
|
||||
result = deSerializeData<float>(startingRow, startingColumn,
|
||||
from->readonlyData, from->rows);
|
||||
break;
|
||||
case Type::DOUBLE:
|
||||
result = deSerializeData<double>(startingRow, startingColumn,
|
||||
from->readonlyData, from->rows);
|
||||
break;
|
||||
default:
|
||||
result = ParameterWrapper::UNKNOW_DATATYPE;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
//not supported
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
38
datapool/DataPoolParameterWrapper.h
Normal file
38
datapool/DataPoolParameterWrapper.h
Normal file
@ -0,0 +1,38 @@
|
||||
#ifndef DATAPOOLPARAMETERWRAPPER_H_
|
||||
#define DATAPOOLPARAMETERWRAPPER_H_
|
||||
|
||||
#include <framework/globalfunctions/Type.h>
|
||||
#include <framework/parameters/ParameterWrapper.h>
|
||||
|
||||
class DataPoolParameterWrapper: public SerializeIF {
|
||||
public:
|
||||
DataPoolParameterWrapper();
|
||||
virtual ~DataPoolParameterWrapper();
|
||||
|
||||
ReturnValue_t set(uint8_t domainId, uint16_t parameterId);
|
||||
|
||||
virtual ReturnValue_t serialize(uint8_t** buffer, uint32_t* size,
|
||||
const uint32_t max_size, bool bigEndian) const;
|
||||
|
||||
virtual uint32_t getSerializedSize() const;
|
||||
|
||||
virtual ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size,
|
||||
bool bigEndian);
|
||||
|
||||
ReturnValue_t copyFrom(const ParameterWrapper *from,
|
||||
uint16_t startWritingAtIndex);
|
||||
|
||||
private:
|
||||
Type type;
|
||||
uint8_t rows;
|
||||
uint8_t columns;
|
||||
|
||||
uint32_t poolId;
|
||||
|
||||
template<typename T>
|
||||
ReturnValue_t deSerializeData(uint8_t startingRow, uint8_t startingColumn,
|
||||
const void *from, uint8_t fromRows);
|
||||
|
||||
};
|
||||
|
||||
#endif /* DATAPOOLPARAMETERWRAPPER_H_ */
|
@ -1,10 +1,3 @@
|
||||
/*
|
||||
* DataSet.cpp
|
||||
*
|
||||
* Created on: 24.10.2012
|
||||
* Author: baetz
|
||||
*/
|
||||
|
||||
#include <framework/datapool/DataSet.h>
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
|
||||
@ -45,12 +38,7 @@ ReturnValue_t DataSet::read() {
|
||||
}
|
||||
|
||||
ReturnValue_t DataSet::commit(uint8_t valid) {
|
||||
for (uint16_t count = 0; count < fill_count; count++) {
|
||||
if (registeredVariables[count]->getReadWriteMode()
|
||||
!= PoolVariableIF::VAR_READ) {
|
||||
registeredVariables[count]->setValid(valid);
|
||||
}
|
||||
}
|
||||
setValid(valid);
|
||||
return commit();
|
||||
}
|
||||
|
||||
@ -139,6 +127,15 @@ uint32_t DataSet::getSerializedSize() const {
|
||||
return size;
|
||||
}
|
||||
|
||||
void DataSet::setValid(uint8_t valid) {
|
||||
for (uint16_t count = 0; count < fill_count; count++) {
|
||||
if (registeredVariables[count]->getReadWriteMode()
|
||||
!= PoolVariableIF::VAR_READ) {
|
||||
registeredVariables[count]->setValid(valid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t DataSet::deSerialize(const uint8_t** buffer, int32_t* size,
|
||||
bool bigEndian) {
|
||||
ReturnValue_t result = RETURN_FAILED;
|
||||
|
@ -38,7 +38,7 @@
|
||||
*/
|
||||
class DataSet: public DataSetIF, public HasReturnvaluesIF, public SerializeIF {
|
||||
private:
|
||||
//TODO we could use a linked list of datapool variables
|
||||
//SHOULDDO we could use a linked list of datapool variables
|
||||
static const uint8_t DATA_SET_MAX_SIZE = 63; //!< This definition sets the maximum number of variables to register in one DataSet.
|
||||
|
||||
/**
|
||||
@ -75,7 +75,7 @@ private:
|
||||
uint8_t freeDataPoolLock();
|
||||
|
||||
public:
|
||||
static const uint8_t INTERFACE_ID = DATA_SET_CLASS;
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::DATA_SET_CLASS;
|
||||
static const ReturnValue_t INVALID_PARAMETER_DEFINITION =
|
||||
MAKE_RETURN_CODE( 0x01 );
|
||||
static const ReturnValue_t SET_WAS_ALREADY_READ = MAKE_RETURN_CODE( 0x02 );
|
||||
@ -139,6 +139,13 @@ public:
|
||||
*/
|
||||
void registerVariable(PoolVariableIF* variable);
|
||||
|
||||
/**
|
||||
* Set the valid information of all variables contained in the set which are not readonly
|
||||
*
|
||||
* @param valid Validity information from PoolVariableIF.
|
||||
*/
|
||||
void setValid(uint8_t valid);
|
||||
|
||||
ReturnValue_t serialize(uint8_t** buffer, uint32_t* size,
|
||||
const uint32_t max_size, bool bigEndian) const;
|
||||
|
||||
|
@ -12,9 +12,6 @@
|
||||
#ifndef DATASETIF_H_
|
||||
#define DATASETIF_H_
|
||||
|
||||
|
||||
#include <framework/osal/OSAL.h>
|
||||
|
||||
class PoolVariableIF;
|
||||
|
||||
/**
|
||||
|
75
datapool/HkSwitchHelper.cpp
Normal file
75
datapool/HkSwitchHelper.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
#include <framework/datapool/HkSwitchHelper.h>
|
||||
#include <mission/tmtcservices/HKService_03.h>
|
||||
#include <framework/ipc/QueueFactory.h>
|
||||
|
||||
HkSwitchHelper::HkSwitchHelper(EventReportingProxyIF* eventProxy) :
|
||||
commandActionHelper(this), eventProxy(eventProxy) {
|
||||
actionQueue = QueueFactory::instance()->createMessageQueue();
|
||||
}
|
||||
|
||||
HkSwitchHelper::~HkSwitchHelper() {
|
||||
// TODO Auto-generated destructor stub
|
||||
}
|
||||
|
||||
ReturnValue_t HkSwitchHelper::initialize() {
|
||||
ReturnValue_t result = commandActionHelper.initialize();
|
||||
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t HkSwitchHelper::performOperation(uint8_t operationCode) {
|
||||
CommandMessage message;
|
||||
while (actionQueue->receiveMessage(&message) == HasReturnvaluesIF::RETURN_OK) {
|
||||
ReturnValue_t result = commandActionHelper.handleReply(&message);
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
continue;
|
||||
}
|
||||
message.setToUnknownCommand();
|
||||
actionQueue->reply(&message);
|
||||
}
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
void HkSwitchHelper::stepSuccessfulReceived(ActionId_t actionId, uint8_t step) {
|
||||
}
|
||||
|
||||
void HkSwitchHelper::stepFailedReceived(ActionId_t actionId, uint8_t step,
|
||||
ReturnValue_t returnCode) {
|
||||
eventProxy->forwardEvent(SWITCHING_TM_FAILED, returnCode, actionId);
|
||||
}
|
||||
|
||||
void HkSwitchHelper::dataReceived(ActionId_t actionId, const uint8_t* data,
|
||||
uint32_t size) {
|
||||
}
|
||||
|
||||
void HkSwitchHelper::completionSuccessfulReceived(ActionId_t actionId) {
|
||||
}
|
||||
|
||||
void HkSwitchHelper::completionFailedReceived(ActionId_t actionId,
|
||||
ReturnValue_t returnCode) {
|
||||
eventProxy->forwardEvent(SWITCHING_TM_FAILED, returnCode, actionId);
|
||||
}
|
||||
|
||||
ReturnValue_t HkSwitchHelper::switchHK(SerializeIF* sids, bool enable) {
|
||||
ActionId_t action = HKService::DISABLE_HK;
|
||||
if (enable) {
|
||||
action = HKService::ENABLE_HK;
|
||||
}
|
||||
|
||||
ReturnValue_t result = commandActionHelper.commandAction(
|
||||
objects::PUS_HK_SERVICE, action, sids);
|
||||
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
eventProxy->forwardEvent(SWITCHING_TM_FAILED, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
MessageQueueIF* HkSwitchHelper::getCommandQueuePtr() {
|
||||
return actionQueue;
|
||||
}
|
44
datapool/HkSwitchHelper.h
Normal file
44
datapool/HkSwitchHelper.h
Normal file
@ -0,0 +1,44 @@
|
||||
#ifndef FRAMEWORK_DATAPOOL_HKSWITCHHELPER_H_
|
||||
#define FRAMEWORK_DATAPOOL_HKSWITCHHELPER_H_
|
||||
|
||||
#include <framework/tasks/ExecutableObjectIF.h>
|
||||
#include <framework/action/CommandsActionsIF.h>
|
||||
#include <framework/events/EventReportingProxyIF.h>
|
||||
|
||||
//TODO this class violations separation between mission and framework
|
||||
//but it is only a transitional solution until the Datapool is
|
||||
//implemented decentrally
|
||||
|
||||
class HkSwitchHelper: public ExecutableObjectIF, public CommandsActionsIF {
|
||||
public:
|
||||
|
||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::HK;
|
||||
static const Event SWITCHING_TM_FAILED = MAKE_EVENT(1, SEVERITY::LOW); //!< Commanding the HK Service failed, p1: error code, p2 action: 0 disable / 1 enable
|
||||
|
||||
HkSwitchHelper(EventReportingProxyIF *eventProxy);
|
||||
virtual ~HkSwitchHelper();
|
||||
|
||||
ReturnValue_t initialize();
|
||||
|
||||
virtual ReturnValue_t performOperation(uint8_t operationCode = 0);
|
||||
|
||||
ReturnValue_t switchHK(SerializeIF *sids, bool enable);
|
||||
|
||||
protected:
|
||||
virtual void stepSuccessfulReceived(ActionId_t actionId, uint8_t step);
|
||||
virtual void stepFailedReceived(ActionId_t actionId, uint8_t step,
|
||||
ReturnValue_t returnCode);
|
||||
virtual void dataReceived(ActionId_t actionId, const uint8_t* data,
|
||||
uint32_t size);
|
||||
virtual void completionSuccessfulReceived(ActionId_t actionId);
|
||||
virtual void completionFailedReceived(ActionId_t actionId,
|
||||
ReturnValue_t returnCode);
|
||||
virtual MessageQueueIF* getCommandQueuePtr();
|
||||
|
||||
private:
|
||||
CommandActionHelper commandActionHelper;
|
||||
MessageQueueIF* actionQueue;
|
||||
EventReportingProxyIF *eventProxy;
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_DATAPOOL_HKSWITCHHELPER_H_ */
|
@ -1,25 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# OPUS makefile
|
||||
#
|
||||
# Created on: Mar 04, 2010
|
||||
# Author: ziemke
|
||||
# Author: Claas Ziemke
|
||||
# Copyright 2010, Claas Ziemke <claas.ziemke@gmx.net>
|
||||
#
|
||||
|
||||
BASEDIR=../../
|
||||
include $(BASEDIR)/options.mk
|
||||
|
||||
OBJ = $(BUILDDIR)/OPUSDataPool.o \
|
||||
$(BUILDDIR)/OPUSDataPoolItem.o \
|
||||
$(BUILDDIR)/OPUSDataSet.o \
|
||||
$(BUILDDIR)/OPUSRegVar.o
|
||||
|
||||
all: $(OBJ)
|
||||
|
||||
$(BUILDDIR)/%.o: %.cpp %.h
|
||||
$(CPP) $(CFLAGS) $(DEFINES) $(CCOPT) ${INCLUDE} -c $< -o $@
|
||||
|
||||
clean:
|
||||
$(RM) *.o *.gcno *.gcda
|
@ -1,10 +1,3 @@
|
||||
/*
|
||||
* PIDReader.h
|
||||
*
|
||||
* Created on: 14.05.2014
|
||||
* Author: baetz
|
||||
*/
|
||||
|
||||
#ifndef PIDREADER_H_
|
||||
#define PIDREADER_H_
|
||||
#include <framework/datapool/DataPool.h>
|
||||
|
@ -1,10 +1,3 @@
|
||||
/*
|
||||
* PIDReaderList.h
|
||||
*
|
||||
* Created on: 15.07.2015
|
||||
* Author: baetz
|
||||
*/
|
||||
|
||||
#ifndef FRAMEWORK_DATAPOOL_PIDREADERLIST_H_
|
||||
#define FRAMEWORK_DATAPOOL_PIDREADERLIST_H_
|
||||
|
||||
|
@ -1,10 +1,3 @@
|
||||
/*
|
||||
* PoolEntry.cpp
|
||||
*
|
||||
* Created on: Oct 25, 2012
|
||||
* Author: baetz
|
||||
*/
|
||||
|
||||
#include <framework/datapool/PoolEntry.h>
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
|
||||
|
@ -3,7 +3,8 @@
|
||||
|
||||
|
||||
#include <framework/datapool/PoolEntryIF.h>
|
||||
#include <framework/osal/OSAL.h>
|
||||
#include <stddef.h>
|
||||
#include <cstring>
|
||||
/**
|
||||
* \brief This is a small helper class that defines a single data pool entry.
|
||||
*
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* \brief This interface defines the access possibilities to a single data pool entry.
|
||||
*
|
||||
|
@ -1,18 +1,13 @@
|
||||
/*
|
||||
* PoolRawAccess.cpp
|
||||
*
|
||||
* Created on: 29.10.2012
|
||||
* Author: baetz
|
||||
*/
|
||||
|
||||
#include <framework/datapool/DataPool.h>
|
||||
#include <framework/datapool/PoolEntryIF.h>
|
||||
#include <framework/datapool/PoolRawAccess.h>
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
#include <framework/osal/Endiness.h>
|
||||
|
||||
PoolRawAccess::PoolRawAccess(uint32_t set_id, uint8_t setArrayEntry,
|
||||
DataSetIF* data_set, ReadWriteMode_t setReadWriteMode) :
|
||||
dataPoolId(set_id), arrayEntry(setArrayEntry), valid(false), typeSize(
|
||||
0), sizeTillEnd(0), readWriteMode(setReadWriteMode) {
|
||||
dataPoolId(set_id), arrayEntry(setArrayEntry), valid(false), type(Type::UNKNOWN_TYPE), typeSize(
|
||||
0), arraySize(0), sizeTillEnd(0), readWriteMode(setReadWriteMode) {
|
||||
memset(value, 0, sizeof(value));
|
||||
if (data_set != NULL) {
|
||||
data_set->registerVariable(this);
|
||||
@ -28,7 +23,9 @@ ReturnValue_t PoolRawAccess::read() {
|
||||
if (read_out != NULL) {
|
||||
valid = read_out->getValid();
|
||||
if (read_out->getSize() > arrayEntry) {
|
||||
arraySize = read_out->getSize();
|
||||
typeSize = read_out->getByteSize() / read_out->getSize();
|
||||
type = read_out->getType();
|
||||
if (typeSize <= sizeof(value)) {
|
||||
uint16_t arrayPosition = arrayEntry * typeSize;
|
||||
sizeTillEnd = read_out->getByteSize() - arrayPosition;
|
||||
@ -92,10 +89,18 @@ ReturnValue_t PoolRawAccess::getEntryEndianSafe(uint8_t* buffer,
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
Type PoolRawAccess::getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
uint8_t PoolRawAccess::getSizeOfType() {
|
||||
return typeSize;
|
||||
}
|
||||
|
||||
uint8_t PoolRawAccess::getArraySize(){
|
||||
return arraySize;
|
||||
}
|
||||
|
||||
uint32_t PoolRawAccess::getDataPoolId() const {
|
||||
return dataPoolId;
|
||||
}
|
||||
|
@ -25,10 +25,18 @@ private:
|
||||
* \brief The valid information as it was stored in the data pool is copied to this attribute.
|
||||
*/
|
||||
uint8_t valid;
|
||||
/**
|
||||
* \brief This value contains the type of the data pool entry.
|
||||
*/
|
||||
Type type;
|
||||
/**
|
||||
* \brief This value contains the size of the data pool entry in bytes.
|
||||
*/
|
||||
uint8_t typeSize;
|
||||
/**
|
||||
* The size of the DP array (single values return 1)
|
||||
*/
|
||||
uint8_t arraySize;
|
||||
/**
|
||||
* The size (in bytes) from the selected entry till the end of this DataPool variable.
|
||||
*/
|
||||
@ -57,7 +65,7 @@ protected:
|
||||
*/
|
||||
ReturnValue_t commit();
|
||||
public:
|
||||
static const uint8_t INTERFACE_ID = POOL_RAW_ACCESS_CLASS;
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::POOL_RAW_ACCESS_CLASS;
|
||||
static const ReturnValue_t INCORRECT_SIZE = MAKE_RETURN_CODE(0x01);
|
||||
static const ReturnValue_t DATA_POOL_ACCESS_FAILED = MAKE_RETURN_CODE(0x02);
|
||||
uint8_t value[RAW_MAX_SIZE];
|
||||
@ -100,10 +108,19 @@ public:
|
||||
*/
|
||||
ReturnValue_t setEntryFromBigEndian(const uint8_t* buffer,
|
||||
uint32_t setSize);
|
||||
/**
|
||||
* \brief This operation returns the type of the entry currently stored.
|
||||
*/
|
||||
Type getType();
|
||||
/**
|
||||
* \brief This operation returns the size of the entry currently stored.
|
||||
*/
|
||||
uint8_t getSizeOfType();
|
||||
/**
|
||||
*
|
||||
* @return the size of the datapool array
|
||||
*/
|
||||
uint8_t getArraySize();
|
||||
/**
|
||||
* \brief This operation returns the data pool id of the variable.
|
||||
*/
|
||||
|
@ -1,10 +1,3 @@
|
||||
/*
|
||||
* PoolVarList.h
|
||||
*
|
||||
* Created on: 06.03.2014
|
||||
* Author: baetz
|
||||
*/
|
||||
|
||||
#ifndef POOLVARLIST_H_
|
||||
#define POOLVARLIST_H_
|
||||
|
||||
|
23
devicehandlers/AcceptsDeviceResponsesIF.h
Normal file
23
devicehandlers/AcceptsDeviceResponsesIF.h
Normal file
@ -0,0 +1,23 @@
|
||||
/**
|
||||
* @file AcceptsDeviceResponsesIF.h
|
||||
* @brief This file defines the AcceptsDeviceResponsesIF class.
|
||||
* @date 15.05.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#ifndef ACCEPTSDEVICERESPONSESIF_H_
|
||||
#define ACCEPTSDEVICERESPONSESIF_H_
|
||||
|
||||
#include <framework/ipc/MessageQueueSenderIF.h>
|
||||
|
||||
class AcceptsDeviceResponsesIF {
|
||||
public:
|
||||
/**
|
||||
* Default empty virtual destructor.
|
||||
*/
|
||||
virtual ~AcceptsDeviceResponsesIF() {
|
||||
}
|
||||
virtual MessageQueueId_t getDeviceQueue() = 0;
|
||||
};
|
||||
|
||||
#endif /* ACCEPTSDEVICERESPONSESIF_H_ */
|
@ -40,11 +40,6 @@ void AssemblyBase::doStartTransition(Mode_t mode, Submode_t submode) {
|
||||
ReturnValue_t result = commandChildren(mode, submode);
|
||||
if (result == NEED_SECOND_STEP) {
|
||||
internalState = STATE_NEED_SECOND_STEP;
|
||||
} else if (result != RETURN_OK) {
|
||||
//TODO: Debug
|
||||
debug << std::hex << getObjectId()
|
||||
<< ": AssemblyBase::commandChildren returned: " << result
|
||||
<< std::dec << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@ -140,7 +135,6 @@ void AssemblyBase::handleModeTransitionFailed(ReturnValue_t result) {
|
||||
if (targetMode == MODE_OFF) {
|
||||
triggerEvent(CHILD_PROBLEMS, result);
|
||||
internalState = STATE_NONE;
|
||||
//TODO: Maybe go to ERROR_ON here. Does this cause problems in subsystem?
|
||||
setMode(targetMode, targetSubmode);
|
||||
} else {
|
||||
if (handleChildrenChangedHealth()) {
|
||||
@ -157,7 +151,7 @@ void AssemblyBase::sendHealthCommand(MessageQueueId_t sendTo,
|
||||
CommandMessage command;
|
||||
HealthMessage::setHealthMessage(&command, HealthMessage::HEALTH_SET,
|
||||
health);
|
||||
if (commandQueue.sendMessage(sendTo, &command) == RETURN_OK) {
|
||||
if (commandQueue->sendMessage(sendTo, &command) == RETURN_OK) {
|
||||
commandsOutstanding++;
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
class AssemblyBase: public SubsystemBase {
|
||||
public:
|
||||
static const uint8_t INTERFACE_ID = ASSEMBLY_BASE;
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::ASSEMBLY_BASE;
|
||||
static const ReturnValue_t NEED_SECOND_STEP = MAKE_RETURN_CODE(0x01);
|
||||
static const ReturnValue_t NEED_TO_RECONFIGURE = MAKE_RETURN_CODE(0x02);
|
||||
static const ReturnValue_t MODE_FALLBACK = MAKE_RETURN_CODE(0x03);
|
||||
|
@ -6,7 +6,7 @@ ChildHandlerBase::ChildHandlerBase(uint32_t ioBoardAddress,
|
||||
object_id_t setObjectId, object_id_t deviceCommunication,
|
||||
uint32_t maxDeviceReplyLen, uint8_t setDeviceSwitch,
|
||||
uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId,
|
||||
uint32_t parent, FDIRBase* customFdir, uint32_t cmdQueueSize) :
|
||||
uint32_t parent, FailureIsolationBase* customFdir, uint32_t cmdQueueSize) :
|
||||
DeviceHandlerBase(ioBoardAddress, setObjectId, maxDeviceReplyLen,
|
||||
setDeviceSwitch, deviceCommunication, thermalStatePoolId,
|
||||
thermalRequestPoolId, (customFdir == NULL? &childHandlerFdir : customFdir), cmdQueueSize), parentId(
|
||||
|
@ -10,7 +10,7 @@ public:
|
||||
object_id_t deviceCommunication, uint32_t maxDeviceReplyLen,
|
||||
uint8_t setDeviceSwitch, uint32_t thermalStatePoolId,
|
||||
uint32_t thermalRequestPoolId, uint32_t parent,
|
||||
FDIRBase* customFdir = NULL,
|
||||
FailureIsolationBase* customFdir = NULL,
|
||||
uint32_t cmdQueueSize = 20);
|
||||
virtual ~ChildHandlerBase();
|
||||
|
||||
|
@ -1,14 +1,7 @@
|
||||
/*
|
||||
* ChildHandlerFDIR.cpp
|
||||
*
|
||||
* Created on: 08.02.2016
|
||||
* Author: baetz
|
||||
*/
|
||||
|
||||
#include <framework/devicehandlers/ChildHandlerFDIR.h>
|
||||
|
||||
ChildHandlerFDIR::ChildHandlerFDIR(object_id_t owner, object_id_t faultTreeParent, uint32_t recoveryCount) :
|
||||
DeviceHandlerFDIR(owner, faultTreeParent) {
|
||||
DeviceHandlerFailureIsolation(owner, faultTreeParent) {
|
||||
recoveryCounter.setFailureThreshold(recoveryCount);
|
||||
}
|
||||
|
||||
|
@ -1,25 +1,18 @@
|
||||
/*
|
||||
* ChildHandlerFDIR.h
|
||||
*
|
||||
* Created on: 08.02.2016
|
||||
* Author: baetz
|
||||
*/
|
||||
|
||||
#ifndef FRAMEWORK_DEVICEHANDLERS_CHILDHANDLERFDIR_H_
|
||||
#define FRAMEWORK_DEVICEHANDLERS_CHILDHANDLERFDIR_H_
|
||||
|
||||
#include <framework/devicehandlers/DeviceHandlerFDIR.h>
|
||||
#include <framework/devicehandlers/DeviceHandlerFailureIsolation.h>
|
||||
|
||||
/**
|
||||
* Very simple extension to normal FDIR.
|
||||
* Does not have a default fault tree parent and
|
||||
* allows to make the recovery count settable to 0.
|
||||
*/
|
||||
class ChildHandlerFDIR: public DeviceHandlerFDIR {
|
||||
class ChildHandlerFDIR: public DeviceHandlerFailureIsolation {
|
||||
public:
|
||||
ChildHandlerFDIR(object_id_t owner, object_id_t faultTreeParent =
|
||||
NO_FAULT_TREE_PARENT, uint32_t recoveryCount = 0);
|
||||
~ChildHandlerFDIR();
|
||||
virtual ~ChildHandlerFDIR();
|
||||
protected:
|
||||
static const object_id_t NO_FAULT_TREE_PARENT = 0;
|
||||
};
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
class DeviceCommunicationIF: public HasReturnvaluesIF {
|
||||
public:
|
||||
static const uint8_t INTERFACE_ID = DEVICE_COMMUNICATION_IF;
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_COMMUNICATION_IF;
|
||||
|
||||
static const ReturnValue_t INVALID_COOKIE_TYPE = MAKE_RETURN_CODE(0x01);
|
||||
static const ReturnValue_t NOT_ACTIVE = MAKE_RETURN_CODE(0x02);
|
||||
@ -39,7 +39,7 @@ public:
|
||||
|
||||
virtual void close(Cookie *cookie) = 0;
|
||||
|
||||
//TODO can data be const?
|
||||
//SHOULDDO can data be const?
|
||||
virtual ReturnValue_t sendMessage(Cookie *cookie, uint8_t *data,
|
||||
uint32_t len) = 0;
|
||||
|
||||
|
@ -1,52 +1,58 @@
|
||||
/*
|
||||
* DeviceHandlerBase.cpp
|
||||
*
|
||||
* Created on: 30.10.2012
|
||||
* Author: mohr
|
||||
*/
|
||||
|
||||
#include <config/datapool/dataPoolInit.h>
|
||||
#include <mission/devices/PCDUHandler.h>
|
||||
#include <config/hardware/IoBoardAddresses.h>
|
||||
#include <framework/datapool/DataSet.h>
|
||||
#include <framework/datapool/PoolVariable.h>
|
||||
#include <framework/datapool/PoolVector.h>
|
||||
#include <framework/devicehandlers/AcceptsDeviceResponsesIF.h>
|
||||
#include <framework/devicehandlers/DeviceHandlerBase.h>
|
||||
#include <framework/devicehandlers/DeviceTmReportingWrapper.h>
|
||||
#include <framework/globalfunctions/crc_ccitt.h>
|
||||
#include <framework/objectmanager/ObjectManager.h>
|
||||
#include <framework/rmap/RMAP.h>
|
||||
#include <framework/rmap/RMAPChannelIF.h>
|
||||
#include <framework/storagemanager/StorageManagerIF.h>
|
||||
#include <framework/subsystem/SubsystemBase.h>
|
||||
#include <mission/tmtcservices/AcceptsDeviceResponsesIF.h>
|
||||
#include <mission/controllers/tcs/ThermalComponentIF.h>
|
||||
#include <framework/thermal/ThermalComponentIF.h>
|
||||
#include <framework/ipc/QueueFactory.h>
|
||||
|
||||
object_id_t DeviceHandlerBase::powerSwitcherId = 0;
|
||||
object_id_t DeviceHandlerBase::rawDataReceiverId = 0;
|
||||
object_id_t DeviceHandlerBase::defaultFDIRParentId = 0;
|
||||
|
||||
DeviceHandlerBase::DeviceHandlerBase(uint32_t ioBoardAddress,
|
||||
object_id_t setObjectId, uint32_t maxDeviceReplyLen,
|
||||
uint8_t setDeviceSwitch, object_id_t deviceCommunication,
|
||||
uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId,
|
||||
FDIRBase* fdirInstance, uint32_t cmdQueueSize) :
|
||||
FailureIsolationBase* fdirInstance, uint32_t cmdQueueSize) :
|
||||
SystemObject(setObjectId), rawPacket(0), rawPacketLen(0), mode(
|
||||
MODE_OFF), submode(SUBMODE_NONE), pstStep(0), maxDeviceReplyLen(
|
||||
maxDeviceReplyLen), wiretappingMode(OFF), theOneWhoReceivesRawTraffic(
|
||||
0), storedRawData(StorageManagerIF::INVALID_ADDRESS), theOneWhoWantsToReadRawTraffic(
|
||||
0), powerSwitcher(NULL), IPCStore(NULL), deviceCommunicationId(
|
||||
deviceCommunication), communicationInterface(NULL), cookie(
|
||||
NULL), commandQueue(cmdQueueSize, CommandMessage::MAX_MESSAGE_SIZE), deviceThermalStatePoolId(
|
||||
thermalStatePoolId), deviceThermalRequestPoolId(
|
||||
maxDeviceReplyLen), wiretappingMode(OFF), defaultRawReceiver(0), storedRawData(
|
||||
StorageManagerIF::INVALID_ADDRESS), requestedRawTraffic(0), powerSwitcher(
|
||||
NULL), IPCStore(NULL), deviceCommunicationId(deviceCommunication), communicationInterface(
|
||||
NULL), cookie(
|
||||
NULL), commandQueue(NULL), deviceThermalStatePoolId(thermalStatePoolId), deviceThermalRequestPoolId(
|
||||
thermalRequestPoolId), healthHelper(this, setObjectId), modeHelper(
|
||||
this), parameterHelper(this), childTransitionFailure(RETURN_OK), ignoreMissedRepliesCount(
|
||||
0), fdirInstance(fdirInstance), defaultFDIRUsed(
|
||||
fdirInstance == NULL), switchOffWasReported(
|
||||
false), cookieInfo(), ioBoardAddress(ioBoardAddress), timeoutStart(0), childTransitionDelay(
|
||||
5000), transitionSourceMode(_MODE_POWER_DOWN), transitionSourceSubMode(
|
||||
SUBMODE_NONE), deviceSwitch(setDeviceSwitch), actionHelper(
|
||||
this, &commandQueue) {
|
||||
0), fdirInstance(fdirInstance), hkSwitcher(this), defaultFDIRUsed(
|
||||
fdirInstance == NULL), switchOffWasReported(false), executingTask(
|
||||
NULL), actionHelper(this, commandQueue), cookieInfo(), ioBoardAddress(
|
||||
//=======
|
||||
// NULL), IPCStore(NULL), deviceCommunicationId(deviceCommunication), communicationInterface(
|
||||
// NULL), cookie(
|
||||
// NULL), commandQueue(cmdQueueSize, CommandMessage::MAX_MESSAGE_SIZE), deviceThermalStatePoolId(
|
||||
// thermalStatePoolId), deviceThermalRequestPoolId(
|
||||
// thermalRequestPoolId), healthHelper(this, setObjectId), modeHelper(
|
||||
// this), parameterHelper(this), childTransitionFailure(RETURN_OK), ignoreMissedRepliesCount(
|
||||
// 0), fdirInstance(fdirInstance), defaultFDIRUsed(
|
||||
// fdirInstance == NULL), switchOffWasReported(false), actionHelper(
|
||||
// this, &commandQueue), cookieInfo(), ioBoardAddress(
|
||||
//>>>>>>> makefile
|
||||
ioBoardAddress), timeoutStart(0), childTransitionDelay(5000), transitionSourceMode(
|
||||
_MODE_POWER_DOWN), transitionSourceSubMode(SUBMODE_NONE), deviceSwitch(
|
||||
setDeviceSwitch) {
|
||||
commandQueue = QueueFactory::instance()->createMessageQueue(cmdQueueSize,
|
||||
CommandMessage::MAX_MESSAGE_SIZE);
|
||||
cookieInfo.state = COOKIE_UNUSED;
|
||||
insertInCommandMap(RAW_COMMAND_ID);
|
||||
if (this->fdirInstance == NULL) {
|
||||
this->fdirInstance = new DeviceHandlerFDIR(setObjectId);
|
||||
this->fdirInstance = new DeviceHandlerFailureIsolation(setObjectId,
|
||||
defaultFDIRParentId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,10 +61,10 @@ DeviceHandlerBase::~DeviceHandlerBase() {
|
||||
if (defaultFDIRUsed) {
|
||||
delete fdirInstance;
|
||||
}
|
||||
|
||||
QueueFactory::instance()->deleteMessageQueue(commandQueue);
|
||||
}
|
||||
|
||||
void DeviceHandlerBase::performInPST(uint8_t counter) {
|
||||
ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) {
|
||||
this->pstStep = counter;
|
||||
|
||||
if (counter == 0) {
|
||||
@ -68,9 +74,10 @@ void DeviceHandlerBase::performInPST(uint8_t counter) {
|
||||
checkSwitchState();
|
||||
decrementDeviceReplyMap();
|
||||
fdirInstance->checkForFailures();
|
||||
hkSwitcher.performOperation();
|
||||
}
|
||||
if (mode == MODE_OFF) {
|
||||
return;
|
||||
return RETURN_OK;
|
||||
}
|
||||
switch (getRmapAction()) {
|
||||
case SEND_WRITE:
|
||||
@ -92,7 +99,7 @@ void DeviceHandlerBase::performInPST(uint8_t counter) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
void DeviceHandlerBase::decrementDeviceReplyMap() {
|
||||
@ -118,7 +125,7 @@ void DeviceHandlerBase::readCommandQueue() {
|
||||
}
|
||||
|
||||
CommandMessage message;
|
||||
ReturnValue_t result = commandQueue.receiveMessage(&message);
|
||||
ReturnValue_t result = commandQueue->receiveMessage(&message);
|
||||
if (result != RETURN_OK) {
|
||||
return;
|
||||
}
|
||||
@ -171,7 +178,7 @@ void DeviceHandlerBase::doStateMachine() {
|
||||
break;
|
||||
}
|
||||
uint32_t currentUptime;
|
||||
OSAL::getUptime(¤tUptime);
|
||||
Clock::getUptime(¤tUptime);
|
||||
if (currentUptime - timeoutStart >= childTransitionDelay) {
|
||||
triggerEvent(MODE_TRANSITION_FAILED, childTransitionFailure, 0);
|
||||
setMode(transitionSourceMode, transitionSourceSubMode);
|
||||
@ -189,7 +196,7 @@ void DeviceHandlerBase::doStateMachine() {
|
||||
break;
|
||||
case _MODE_WAIT_ON: {
|
||||
uint32_t currentUptime;
|
||||
OSAL::getUptime(¤tUptime);
|
||||
Clock::getUptime(¤tUptime);
|
||||
if (currentUptime - timeoutStart >= powerSwitcher->getSwitchDelayMs()) {
|
||||
triggerEvent(MODE_TRANSITION_FAILED, PowerSwitchIF::SWITCH_TIMEOUT,
|
||||
0);
|
||||
@ -209,7 +216,7 @@ void DeviceHandlerBase::doStateMachine() {
|
||||
break;
|
||||
case _MODE_WAIT_OFF: {
|
||||
uint32_t currentUptime;
|
||||
OSAL::getUptime(¤tUptime);
|
||||
Clock::getUptime(¤tUptime);
|
||||
if (currentUptime - timeoutStart >= powerSwitcher->getSwitchDelayMs()) {
|
||||
triggerEvent(MODE_TRANSITION_FAILED, PowerSwitchIF::SWITCH_TIMEOUT,
|
||||
0);
|
||||
@ -347,6 +354,7 @@ void DeviceHandlerBase::setTransition(Mode_t modeTo, Submode_t submodeTo) {
|
||||
}
|
||||
|
||||
void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) {
|
||||
changeHK(mode, submode, false);
|
||||
submode = newSubmode;
|
||||
mode = newMode;
|
||||
modeChanged();
|
||||
@ -355,7 +363,7 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) {
|
||||
modeHelper.modeChanged(newMode, newSubmode);
|
||||
announceMode(false);
|
||||
}
|
||||
OSAL::getUptime(&timeoutStart);
|
||||
Clock::getUptime(&timeoutStart);
|
||||
|
||||
if (mode == MODE_OFF) {
|
||||
DataSet mySet;
|
||||
@ -367,6 +375,7 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) {
|
||||
}
|
||||
mySet.commit(PoolVariableIF::VALID);
|
||||
}
|
||||
changeHK(mode, submode, true);
|
||||
}
|
||||
|
||||
void DeviceHandlerBase::setMode(Mode_t newMode) {
|
||||
@ -378,10 +387,10 @@ void DeviceHandlerBase::replyReturnvalueToCommand(ReturnValue_t status,
|
||||
//This is actually the reply protocol for raw and misc dh commands.
|
||||
if (status == RETURN_OK) {
|
||||
CommandMessage reply(CommandMessage::REPLY_COMMAND_OK, 0, parameter);
|
||||
commandQueue.reply(&reply);
|
||||
commandQueue->reply(&reply);
|
||||
} else {
|
||||
CommandMessage reply(CommandMessage::REPLY_REJECTED, status, parameter);
|
||||
commandQueue.reply(&reply);
|
||||
commandQueue->reply(&reply);
|
||||
}
|
||||
}
|
||||
|
||||
@ -455,8 +464,7 @@ void DeviceHandlerBase::doGetWrite() {
|
||||
ReturnValue_t result = communicationInterface->getSendSuccess(cookie);
|
||||
if (result == RETURN_OK) {
|
||||
if (wiretappingMode == RAW) {
|
||||
replyRawData(rawPacket, rawPacketLen,
|
||||
theOneWhoWantsToReadRawTraffic, true);
|
||||
replyRawData(rawPacket, rawPacketLen, requestedRawTraffic, true);
|
||||
}
|
||||
//We need to distinguish here, because a raw command never expects a reply. (Could be done in eRIRM, but then child implementations need to be careful.
|
||||
result = enableReplyInReplyMap(cookieInfo.pendingCommand);
|
||||
@ -515,19 +523,11 @@ void DeviceHandlerBase::doGetRead() {
|
||||
return;
|
||||
|
||||
if (wiretappingMode == RAW) {
|
||||
replyRawData(receivedData, receivedDataLen,
|
||||
theOneWhoWantsToReadRawTraffic);
|
||||
replyRawData(receivedData, receivedDataLen, requestedRawTraffic);
|
||||
}
|
||||
|
||||
if (mode == MODE_RAW) {
|
||||
if ((wiretappingMode == RAW)
|
||||
&& (theOneWhoReceivesRawTraffic
|
||||
== theOneWhoWantsToReadRawTraffic)) {
|
||||
//The raw packet was already sent by the wiretapping service
|
||||
} else {
|
||||
replyRawData(receivedData, receivedDataLen,
|
||||
theOneWhoReceivesRawTraffic);
|
||||
}
|
||||
replyRawReplyIfnotWiretapped(receivedData, receivedDataLen);
|
||||
} else {
|
||||
//The loop may not execute more often than the number of received bytes (worst case).
|
||||
//This approach avoids infinite loops due to buggy scanForReply routines (seen in bug 1077).
|
||||
@ -537,12 +537,12 @@ void DeviceHandlerBase::doGetRead() {
|
||||
&foundLen);
|
||||
switch (result) {
|
||||
case RETURN_OK:
|
||||
handleReply(receivedData, foundId);
|
||||
handleReply(receivedData, foundId, foundLen);
|
||||
break;
|
||||
case APERIODIC_REPLY: {
|
||||
DataSet dataSet;
|
||||
result = interpretDeviceReply(foundId, receivedData);
|
||||
if (result != RETURN_OK) {
|
||||
replyRawReplyIfnotWiretapped(receivedData, foundLen);
|
||||
triggerEvent(DEVICE_INTERPRETING_REPLY_FAILED, result,
|
||||
foundId);
|
||||
}
|
||||
@ -552,6 +552,7 @@ void DeviceHandlerBase::doGetRead() {
|
||||
break;
|
||||
default:
|
||||
//We need to wait for timeout.. don't know what command failed and who sent it.
|
||||
replyRawReplyIfnotWiretapped(receivedData, foundLen);
|
||||
triggerEvent(DEVICE_READING_REPLY_FAILED, result, foundLen);
|
||||
break;
|
||||
}
|
||||
@ -613,15 +614,15 @@ ReturnValue_t DeviceHandlerBase::initialize() {
|
||||
}
|
||||
|
||||
AcceptsDeviceResponsesIF *rawReceiver = objectManager->get<
|
||||
AcceptsDeviceResponsesIF>(objects::PUS_DEVICE_COMMAND_SERVICE);
|
||||
AcceptsDeviceResponsesIF>(rawDataReceiverId);
|
||||
|
||||
if (rawReceiver == NULL) {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
|
||||
theOneWhoReceivesRawTraffic = rawReceiver->getDeviceQueue();
|
||||
defaultRawReceiver = rawReceiver->getDeviceQueue();
|
||||
|
||||
powerSwitcher = objectManager->get<PowerSwitchIF>(objects::PCDU_HANDLER);
|
||||
powerSwitcher = objectManager->get<PowerSwitchIF>(powerSwitcherId);
|
||||
if (powerSwitcher == NULL) {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
@ -649,6 +650,11 @@ ReturnValue_t DeviceHandlerBase::initialize() {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = hkSwitcher.initialize();
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
fillCommandAndReplyMap();
|
||||
|
||||
//Set temperature target state to NON_OP.
|
||||
@ -676,12 +682,6 @@ void DeviceHandlerBase::replyRawData(const uint8_t *data, size_t len,
|
||||
return;
|
||||
}
|
||||
|
||||
Command_t handlerCommand = DeviceHandlerMessage::REPLY_RAW_REPLY;
|
||||
|
||||
if (isCommand) {
|
||||
handlerCommand = DeviceHandlerMessage::REPLY_RAW_COMMAND;
|
||||
}
|
||||
|
||||
CommandMessage message;
|
||||
|
||||
DeviceHandlerMessage::setDeviceHandlerRawReplayMessage(&message,
|
||||
@ -689,11 +689,11 @@ void DeviceHandlerBase::replyRawData(const uint8_t *data, size_t len,
|
||||
|
||||
// this->DeviceHandlerCommand = CommandMessage::CMD_NONE;
|
||||
|
||||
result = commandQueue.sendMessage(sendTo, &message);
|
||||
result = commandQueue->sendMessage(sendTo, &message);
|
||||
|
||||
if (result != RETURN_OK) {
|
||||
IPCStore->deleteData(address);
|
||||
triggerEvent(MessageQueue::SEND_MSG_FAILED, result, sendTo);
|
||||
//Silently discard data, this indicates heavy TM traffic which should not be increased by additional events.
|
||||
}
|
||||
}
|
||||
|
||||
@ -714,23 +714,22 @@ DeviceHandlerBase::RmapAction_t DeviceHandlerBase::getRmapAction() {
|
||||
return GET_READ;
|
||||
break;
|
||||
default:
|
||||
|
||||
break;
|
||||
}
|
||||
return NOTHING;
|
||||
}
|
||||
|
||||
MessageQueueId_t DeviceHandlerBase::getCommandQueue() const {
|
||||
return commandQueue.getId();
|
||||
return commandQueue->getId();
|
||||
}
|
||||
|
||||
void DeviceHandlerBase::handleReply(const uint8_t* receivedData,
|
||||
DeviceCommandId_t foundId) {
|
||||
DeviceCommandId_t foundId, uint32_t foundLen) {
|
||||
ReturnValue_t result;
|
||||
DataSet dataSet;
|
||||
DeviceReplyMap::iterator iter = deviceReplyMap.find(foundId);
|
||||
|
||||
if (iter == deviceReplyMap.end()) {
|
||||
replyRawReplyIfnotWiretapped(receivedData, foundLen);
|
||||
triggerEvent(DEVICE_UNKNOWN_REPLY, foundId);
|
||||
return;
|
||||
}
|
||||
@ -747,12 +746,13 @@ void DeviceHandlerBase::handleReply(const uint8_t* receivedData,
|
||||
result = interpretDeviceReply(foundId, receivedData);
|
||||
if (result != RETURN_OK) {
|
||||
//Report failed interpretation to FDIR.
|
||||
replyRawReplyIfnotWiretapped(receivedData, foundLen);
|
||||
triggerEvent(DEVICE_INTERPRETING_REPLY_FAILED, result, foundId);
|
||||
}
|
||||
replyToReply(iter, result);
|
||||
} else {
|
||||
//Other completion failure messages are created by timeout.
|
||||
//Powering down the device might take some time during which periodic replys may still come in.
|
||||
//Powering down the device might take some time during which periodic replies may still come in.
|
||||
if (mode != _MODE_WAIT_OFF) {
|
||||
triggerEvent(DEVICE_UNREQUESTED_REPLY, foundId);
|
||||
}
|
||||
@ -899,7 +899,8 @@ ReturnValue_t DeviceHandlerBase::checkModeCommand(Mode_t commandedMode,
|
||||
mySet.read();
|
||||
if (thermalRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) {
|
||||
if (!ThermalComponentIF::isOperational(thermalState)) {
|
||||
triggerEvent(ThermalComponentIF::TEMP_NOT_IN_OP_RANGE, thermalState);
|
||||
triggerEvent(ThermalComponentIF::TEMP_NOT_IN_OP_RANGE,
|
||||
thermalState);
|
||||
return NON_OP_TEMPERATURE;
|
||||
}
|
||||
}
|
||||
@ -1020,6 +1021,20 @@ ReturnValue_t DeviceHandlerBase::acceptExternalDeviceCommands() {
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
void DeviceHandlerBase::setTaskIF(PeriodicTaskIF* interface) {
|
||||
executingTask = interface;
|
||||
}
|
||||
|
||||
void DeviceHandlerBase::replyRawReplyIfnotWiretapped(const uint8_t* data,
|
||||
size_t len) {
|
||||
if ((wiretappingMode == RAW)
|
||||
&& (defaultRawReceiver == requestedRawTraffic)) {
|
||||
//The raw packet was already sent by the wiretapping service
|
||||
} else {
|
||||
replyRawData(data, len, defaultRawReceiver);
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t DeviceHandlerBase::handleDeviceHandlerMessage(
|
||||
CommandMessage * message) {
|
||||
ReturnValue_t result;
|
||||
@ -1028,11 +1043,11 @@ ReturnValue_t DeviceHandlerBase::handleDeviceHandlerMessage(
|
||||
switch (DeviceHandlerMessage::getWiretappingMode(message)) {
|
||||
case RAW:
|
||||
wiretappingMode = RAW;
|
||||
theOneWhoWantsToReadRawTraffic = commandQueue.getLastPartner();
|
||||
requestedRawTraffic = commandQueue->getLastPartner();
|
||||
break;
|
||||
case TM:
|
||||
wiretappingMode = TM;
|
||||
theOneWhoWantsToReadRawTraffic = commandQueue.getLastPartner();
|
||||
requestedRawTraffic = commandQueue->getLastPartner();
|
||||
break;
|
||||
case OFF:
|
||||
wiretappingMode = OFF;
|
||||
@ -1091,23 +1106,39 @@ ReturnValue_t DeviceHandlerBase::letChildHandleMessage(
|
||||
}
|
||||
|
||||
void DeviceHandlerBase::handleDeviceTM(SerializeIF* data,
|
||||
DeviceCommandId_t replyId, bool neverInDataPool) {
|
||||
DeviceCommandId_t replyId, bool neverInDataPool, bool forceDirectTm) {
|
||||
DeviceReplyMap::iterator iter = deviceReplyMap.find(replyId);
|
||||
if (iter == deviceReplyMap.end()) {
|
||||
triggerEvent(DEVICE_UNKNOWN_REPLY, replyId);
|
||||
return;
|
||||
}
|
||||
if (iter->second.command != deviceCommandMap.end()) {
|
||||
DeviceTmReportingWrapper wrapper(getObjectId(), replyId, data);
|
||||
if (iter->second.command != deviceCommandMap.end()) {//replies to a command
|
||||
MessageQueueId_t queueId = iter->second.command->second.sendReplyTo;
|
||||
DeviceTmReportingWrapper wrapper(getObjectId(), replyId, data);
|
||||
|
||||
if (queueId != NO_COMMANDER) {
|
||||
//This may fail, but we'll ignore the fault.
|
||||
actionHelper.reportData(queueId, replyId, data);
|
||||
}
|
||||
//This check should make sure we get any TM but don't get anything doubled.
|
||||
if (wiretappingMode == TM
|
||||
&& (theOneWhoWantsToReadRawTraffic != queueId)) {
|
||||
actionHelper.reportData(theOneWhoWantsToReadRawTraffic,
|
||||
replyId, &wrapper);
|
||||
if (wiretappingMode == TM && (requestedRawTraffic != queueId)) {
|
||||
actionHelper.reportData(requestedRawTraffic, replyId, &wrapper);
|
||||
} else if (forceDirectTm && (defaultRawReceiver != queueId)) {
|
||||
|
||||
// hiding of sender needed so the service will handle it as unexpected Data, no matter what state
|
||||
//(progress or completed) it is in
|
||||
actionHelper.reportData(defaultRawReceiver, replyId, &wrapper,
|
||||
true);
|
||||
|
||||
}
|
||||
} else { //unrequested/aperiodic replies
|
||||
if (wiretappingMode == TM) {
|
||||
actionHelper.reportData(requestedRawTraffic, replyId, &wrapper);
|
||||
} else if (forceDirectTm) {
|
||||
// hiding of sender needed so the service will handle it as unexpected Data, no matter what state
|
||||
//(progress or completed) it is in
|
||||
actionHelper.reportData(defaultRawReceiver, replyId, &wrapper,
|
||||
true);
|
||||
}
|
||||
}
|
||||
//Try to cast to DataSet and commit data.
|
||||
@ -1171,7 +1202,8 @@ void DeviceHandlerBase::buildInternalCommand(void) {
|
||||
result = COMMAND_NOT_SUPPORTED;
|
||||
} else if (iter->second.isExecuting) {
|
||||
debug << std::hex << getObjectId()
|
||||
<< ": DHB::buildInternalCommand: Command " << deviceCommandId << " isExecuting" << std::endl; //so we can track misconfigurations
|
||||
<< ": DHB::buildInternalCommand: Command "
|
||||
<< deviceCommandId << " isExecuting" << std::endl; //so we can track misconfigurations
|
||||
return; //this is an internal command, no need to report a failure here, missed reply will track if a reply is too late, otherwise, it's ok
|
||||
} else {
|
||||
iter->second.sendReplyTo = NO_COMMANDER;
|
||||
@ -1232,7 +1264,9 @@ ReturnValue_t DeviceHandlerBase::getParameter(uint8_t domainId,
|
||||
}
|
||||
|
||||
bool DeviceHandlerBase::isTransitionalMode() {
|
||||
return ((mode & (TRANSITION_MODE_BASE_ACTION_MASK | TRANSITION_MODE_CHILD_ACTION_MASK)) != 0);
|
||||
return ((mode
|
||||
& (TRANSITION_MODE_BASE_ACTION_MASK
|
||||
| TRANSITION_MODE_CHILD_ACTION_MASK)) != 0);
|
||||
}
|
||||
|
||||
bool DeviceHandlerBase::commandIsExecuting(DeviceCommandId_t commandId) {
|
||||
@ -1244,3 +1278,6 @@ bool DeviceHandlerBase::commandIsExecuting(DeviceCommandId_t commandId) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void DeviceHandlerBase::changeHK(Mode_t mode, Submode_t submode, bool enable) {
|
||||
}
|
||||
|
@ -6,9 +6,7 @@
|
||||
#include <framework/datapool/DataSet.h>
|
||||
#include <framework/datapool/PoolVariableIF.h>
|
||||
#include <framework/devicehandlers/DeviceCommunicationIF.h>
|
||||
#include <framework/devicehandlers/DeviceHandlerFDIR.h>
|
||||
#include <framework/devicehandlers/DeviceHandlerIF.h>
|
||||
#include <framework/devicehandlers/PollingSequenceExecutableIF.h>
|
||||
#include <framework/health/HealthHelper.h>
|
||||
#include <framework/modes/HasModesIF.h>
|
||||
#include <framework/objectmanager/SystemObject.h>
|
||||
@ -16,7 +14,17 @@
|
||||
#include <framework/parameters/ParameterHelper.h>
|
||||
#include <framework/power/PowerSwitchIF.h>
|
||||
#include <framework/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <framework/tasks/ExecutableObjectIF.h>
|
||||
#include <framework/devicehandlers/DeviceHandlerFailureIsolation.h>
|
||||
#include <framework/datapool/HkSwitchHelper.h>
|
||||
#include <framework/serialize/SerialFixedArrayListAdapter.h>
|
||||
#include <map>
|
||||
#include <framework/ipc/MessageQueueIF.h>
|
||||
#include <framework/tasks/PeriodicTaskIF.h>
|
||||
|
||||
namespace Factory{
|
||||
void setStaticFrameworkObjectIds();
|
||||
}
|
||||
|
||||
class StorageManagerIF;
|
||||
|
||||
@ -27,7 +35,7 @@ class StorageManagerIF;
|
||||
* communication with commanding objects.
|
||||
* It inherits SystemObject and thus can be created by the ObjectManagerIF.
|
||||
*
|
||||
* This class is called by the PollingSequenceTable periodically. Thus, the execution is divided into PST cycles and steps within a cycle.
|
||||
* This class uses the opcode of ExecutableObjectIF to perform a step-wise execution.
|
||||
* For each step an RMAP action is selected and executed. If data has been received (eg in case of an RMAP Read), the data will be interpreted.
|
||||
* The action for each step can be defined by the child class but as most device handlers share a 4-call (Read-getRead-write-getWrite) structure,
|
||||
* a default implementation is provided.
|
||||
@ -36,12 +44,13 @@ class StorageManagerIF;
|
||||
*/
|
||||
class DeviceHandlerBase: public DeviceHandlerIF,
|
||||
public HasReturnvaluesIF,
|
||||
public PollingSequenceExecutableIF,
|
||||
public ExecutableObjectIF,
|
||||
public SystemObject,
|
||||
public HasModesIF,
|
||||
public HasHealthIF,
|
||||
public HasActionsIF,
|
||||
public ReceivesParameterMessagesIF {
|
||||
friend void (Factory::setStaticFrameworkObjectIds)();
|
||||
public:
|
||||
/**
|
||||
* The constructor passes the objectId to the SystemObject().
|
||||
@ -54,16 +63,16 @@ public:
|
||||
uint32_t maxDeviceReplyLen, uint8_t setDeviceSwitch,
|
||||
object_id_t deviceCommunication, uint32_t thermalStatePoolId =
|
||||
PoolVariableIF::NO_PARAMETER,
|
||||
uint32_t thermalRequestPoolId = PoolVariableIF::NO_PARAMETER, FDIRBase* fdirInstance = NULL, uint32_t cmdQueueSize = 20);
|
||||
uint32_t thermalRequestPoolId = PoolVariableIF::NO_PARAMETER,
|
||||
FailureIsolationBase* fdirInstance = NULL, uint32_t cmdQueueSize = 20);
|
||||
|
||||
virtual MessageQueueId_t getCommandQueue(void) const;
|
||||
|
||||
virtual void performInPST(uint8_t counter);
|
||||
virtual ReturnValue_t performOperation(uint8_t counter);
|
||||
|
||||
virtual ReturnValue_t initialize();
|
||||
|
||||
/**
|
||||
* MUST be called after initialize(), not before! TODO: Is this statement still valid?
|
||||
*
|
||||
* @param parentQueueId
|
||||
*/
|
||||
@ -81,13 +90,15 @@ public:
|
||||
HealthState getHealth();
|
||||
ReturnValue_t setHealth(HealthState health);
|
||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
||||
ParameterWrapper *parameterWrapper,
|
||||
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
||||
ParameterWrapper *parameterWrapper,
|
||||
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
||||
|
||||
void setTaskIF(PeriodicTaskIF* interface);
|
||||
protected:
|
||||
/**
|
||||
* The Returnvalues id of this class, required by HasReturnvaluesIF
|
||||
*/
|
||||
static const uint8_t INTERFACE_ID = DEVICE_HANDLER_BASE;
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_BASE;
|
||||
|
||||
static const ReturnValue_t INVALID_CHANNEL = MAKE_RETURN_CODE(4);
|
||||
static const ReturnValue_t APERIODIC_REPLY = MAKE_RETURN_CODE(5);
|
||||
@ -106,19 +117,6 @@ protected:
|
||||
static const DeviceCommandId_t NO_COMMAND_ID = -2;
|
||||
static const MessageQueueId_t NO_COMMANDER = 0;
|
||||
|
||||
/**
|
||||
* RMAP Action that will be executed.
|
||||
*
|
||||
* This is used by the child class to tell the base class what to do.
|
||||
*/
|
||||
enum RmapAction_t {
|
||||
SEND_WRITE, //!< RMAP send write
|
||||
GET_WRITE, //!< RMAP get write
|
||||
SEND_READ, //!< RMAP send read
|
||||
GET_READ, //!< RMAP get read
|
||||
NOTHING //!< Do nothing.
|
||||
};
|
||||
|
||||
/**
|
||||
* Pointer to the raw packet that will be sent.
|
||||
*/
|
||||
@ -143,7 +141,7 @@ protected:
|
||||
Submode_t submode;
|
||||
|
||||
/**
|
||||
* This is the counter value from performInPST().
|
||||
* This is the counter value from performOperation().
|
||||
*/
|
||||
uint8_t pstStep;
|
||||
|
||||
@ -163,11 +161,12 @@ protected:
|
||||
} wiretappingMode;
|
||||
|
||||
/**
|
||||
* the message queue which commanded raw mode
|
||||
* A message queue that accepts raw replies
|
||||
*
|
||||
* This is the one to receive raw replies
|
||||
* Statically initialized in initialize() to a configurable object. Used when there is no method
|
||||
* of finding a recipient, ie raw mode and reporting erreonous replies
|
||||
*/
|
||||
MessageQueueId_t theOneWhoReceivesRawTraffic;
|
||||
MessageQueueId_t defaultRawReceiver;
|
||||
|
||||
store_address_t storedRawData;
|
||||
|
||||
@ -176,7 +175,7 @@ protected:
|
||||
*
|
||||
* if #isWiretappingActive all raw communication from and to the device will be sent to this queue
|
||||
*/
|
||||
MessageQueueId_t theOneWhoWantsToReadRawTraffic;
|
||||
MessageQueueId_t requestedRawTraffic;
|
||||
|
||||
/**
|
||||
* the object used to set power switches
|
||||
@ -208,7 +207,7 @@ protected:
|
||||
/**
|
||||
* The MessageQueue used to receive device handler commands and to send replies.
|
||||
*/
|
||||
MessageQueue commandQueue;
|
||||
MessageQueueIF* commandQueue;
|
||||
|
||||
/**
|
||||
* this is the datapool variable with the thermal state of the device
|
||||
@ -241,12 +240,21 @@ protected:
|
||||
|
||||
uint32_t ignoreMissedRepliesCount; //!< Counts if communication channel lost a reply, so some missed replys can be ignored.
|
||||
|
||||
FDIRBase* fdirInstance; //!< Pointer to the used FDIR instance. If not provided by child, default class is instantiated.
|
||||
FailureIsolationBase* fdirInstance; //!< Pointer to the used FDIR instance. If not provided by child, default class is instantiated.
|
||||
|
||||
HkSwitchHelper hkSwitcher;
|
||||
|
||||
bool defaultFDIRUsed; //!< To correctly delete the default instance.
|
||||
|
||||
bool switchOffWasReported; //!< Indicates if SWITCH_WENT_OFF was already thrown.
|
||||
|
||||
static object_id_t powerSwitcherId; //!< Object which switches power on and off.
|
||||
|
||||
static object_id_t rawDataReceiverId; //!< Object which receives RAW data by default.
|
||||
|
||||
static object_id_t defaultFDIRParentId; //!< Object which may be the root cause of an identified fault.
|
||||
|
||||
PeriodicTaskIF* executingTask;
|
||||
/**
|
||||
* Helper function to report a missed reply
|
||||
*
|
||||
@ -593,6 +601,12 @@ protected:
|
||||
virtual void replyRawData(const uint8_t *data, size_t len,
|
||||
MessageQueueId_t sendTo, bool isCommand = false);
|
||||
|
||||
/**
|
||||
* Calls replyRawData() with #defaultRawReceiver, but checks if wiretapping is active and if so,
|
||||
* does not send the Data as the wiretapping will have sent it already
|
||||
*/
|
||||
void replyRawReplyIfnotWiretapped(const uint8_t *data, size_t len);
|
||||
|
||||
/**
|
||||
* Return the switches connected to the device.
|
||||
*
|
||||
@ -663,6 +677,11 @@ protected:
|
||||
*/
|
||||
virtual void setNormalDatapoolEntriesInvalid() = 0;
|
||||
|
||||
/**
|
||||
* build a list of sids and pass it to the #hkSwitcher
|
||||
*/
|
||||
virtual void changeHK(Mode_t mode, Submode_t submode, bool enable);
|
||||
|
||||
/**
|
||||
* Children can overwrite this function to suppress checking of the command Queue
|
||||
*
|
||||
@ -679,7 +698,7 @@ protected:
|
||||
bool isAwaitingReply();
|
||||
|
||||
void handleDeviceTM(SerializeIF *dataSet, DeviceCommandId_t commandId,
|
||||
bool neverInDataPool = false);
|
||||
bool neverInDataPool = false, bool forceDirectTm = false);
|
||||
|
||||
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
||||
uint32_t *msToReachTheMode);
|
||||
@ -732,12 +751,6 @@ protected:
|
||||
virtual ReturnValue_t acceptExternalDeviceCommands();
|
||||
|
||||
bool commandIsExecuting(DeviceCommandId_t commandId);
|
||||
private:
|
||||
|
||||
/**
|
||||
* Information about commands
|
||||
*/
|
||||
DeviceCommandMap deviceCommandMap;
|
||||
|
||||
/**
|
||||
* Information about expected replies
|
||||
@ -750,6 +763,7 @@ private:
|
||||
uint8_t periodic; //!< if this is !=0, the delayCycles will not be reset to 0 but to maxDelayCycles
|
||||
DeviceCommandMap::iterator command; //!< The command that expects this reply.
|
||||
};
|
||||
|
||||
/**
|
||||
* Definition for the important reply Map.
|
||||
*/
|
||||
@ -767,6 +781,15 @@ private:
|
||||
*/
|
||||
DeviceReplyMap deviceReplyMap;
|
||||
|
||||
/**
|
||||
* Information about commands
|
||||
*/
|
||||
DeviceCommandMap deviceCommandMap;
|
||||
|
||||
ActionHelper actionHelper;
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* State a cookie is in.
|
||||
*
|
||||
@ -837,8 +860,6 @@ private:
|
||||
*/
|
||||
const uint8_t deviceSwitch;
|
||||
|
||||
ActionHelper actionHelper;
|
||||
|
||||
/**
|
||||
* read the command queue
|
||||
*/
|
||||
@ -880,8 +901,9 @@ private:
|
||||
*
|
||||
* @param data the found packet
|
||||
* @param id the found id
|
||||
* @foundLen the length of the packet
|
||||
*/
|
||||
void handleReply(const uint8_t *data, DeviceCommandId_t id);
|
||||
void handleReply(const uint8_t *data, DeviceCommandId_t id, uint32_t foundLen);
|
||||
|
||||
void replyToReply(DeviceReplyMap::iterator iter, ReturnValue_t status);
|
||||
/**
|
||||
|
@ -1,20 +1,14 @@
|
||||
/*
|
||||
* DeviceHandlerFDIR.cpp
|
||||
*
|
||||
* Created on: 09.09.2015
|
||||
* Author: baetz
|
||||
*/
|
||||
|
||||
#include <framework/devicehandlers/DeviceHandlerBase.h>
|
||||
#include <framework/devicehandlers/DeviceHandlerFDIR.h>
|
||||
#include <framework/devicehandlers/DeviceHandlerFailureIsolation.h>
|
||||
#include <framework/health/HealthTableIF.h>
|
||||
#include <framework/power/Fuse.h>
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
#include <mission/controllers/power/Fuse.h>
|
||||
#include <mission/controllers/tcs/ThermalComponentIF.h>
|
||||
#include <framework/thermal/ThermalComponentIF.h>
|
||||
|
||||
//TODO: Mechanisms have no power FDIR..
|
||||
DeviceHandlerFDIR::DeviceHandlerFDIR(object_id_t owner, object_id_t parent) :
|
||||
FDIRBase(owner, parent), strangeReplyCount(MAX_STRANGE_REPLIES,
|
||||
object_id_t DeviceHandlerFailureIsolation::powerConfirmationId = 0;
|
||||
|
||||
DeviceHandlerFailureIsolation::DeviceHandlerFailureIsolation(object_id_t owner, object_id_t parent) :
|
||||
FailureIsolationBase(owner, parent), strangeReplyCount(MAX_STRANGE_REPLIES,
|
||||
STRANGE_REPLIES_TIME_MS, parameterDomainBase++), missedReplyCount(
|
||||
MAX_MISSED_REPLY_COUNT, MISSED_REPLY_TIME_MS,
|
||||
parameterDomainBase++), recoveryCounter(MAX_REBOOT,
|
||||
@ -22,25 +16,11 @@ DeviceHandlerFDIR::DeviceHandlerFDIR(object_id_t owner, object_id_t parent) :
|
||||
0) {
|
||||
}
|
||||
|
||||
DeviceHandlerFDIR::~DeviceHandlerFDIR() {
|
||||
DeviceHandlerFailureIsolation::~DeviceHandlerFailureIsolation() {
|
||||
}
|
||||
|
||||
ReturnValue_t DeviceHandlerFDIR::eventReceived(EventMessage* event) {
|
||||
if (fdirState != NONE) {
|
||||
//Only wait for those events, ignore all others.
|
||||
if (event->getParameter1() == HasHealthIF::HEALTHY
|
||||
&& event->getEvent() == HasHealthIF::HEALTH_INFO) {
|
||||
setFdirState(NONE);
|
||||
}
|
||||
if (event->getEvent() == HasModesIF::MODE_INFO
|
||||
&& fdirState != RECOVERY_ONGOING) {
|
||||
setFdirState(NONE);
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
if (owner->getHealth() == HasHealthIF::FAULTY
|
||||
|| owner->getHealth() == HasHealthIF::PERMANENT_FAULTY) {
|
||||
//Ignore all events in case device is already faulty.
|
||||
ReturnValue_t DeviceHandlerFailureIsolation::eventReceived(EventMessage* event) {
|
||||
if(isFdirInActionOrAreWeFaulty(event)) {
|
||||
return RETURN_OK;
|
||||
}
|
||||
ReturnValue_t result = RETURN_FAILED;
|
||||
@ -76,13 +56,11 @@ ReturnValue_t DeviceHandlerFDIR::eventReceived(EventMessage* event) {
|
||||
break;
|
||||
case StorageManagerIF::GET_DATA_FAILED:
|
||||
case StorageManagerIF::STORE_DATA_FAILED:
|
||||
case MessageQueue::SEND_MSG_FAILED:
|
||||
//Rather strange bugs, occur in RAW mode only. TODO:? By now: Ignore.
|
||||
//Rather strange bugs, occur in RAW mode only. Ignore.
|
||||
break;
|
||||
case DeviceHandlerIF::INVALID_DEVICE_COMMAND:
|
||||
//Ignore, is bad configuration. We can't do anything in flight.
|
||||
break;
|
||||
case DeviceHandlerIF::MONITORING_AMBIGUOUS:
|
||||
case HasHealthIF::HEALTH_INFO:
|
||||
case HasModesIF::MODE_INFO:
|
||||
case HasModesIF::CHANGING_MODE:
|
||||
@ -111,13 +89,17 @@ ReturnValue_t DeviceHandlerFDIR::eventReceived(EventMessage* event) {
|
||||
case ThermalComponentIF::COMPONENT_TEMP_OOL_LOW:
|
||||
case ThermalComponentIF::COMPONENT_TEMP_OOL_HIGH:
|
||||
//Well, the device is not really faulty, but it is required to stay off as long as possible.
|
||||
//*******ACS*****
|
||||
case DeviceHandlerIF::MONITORING_LIMIT_EXCEEDED:
|
||||
setFaulty(event->getEvent());
|
||||
break;
|
||||
case ThermalComponentIF::TEMP_NOT_IN_OP_RANGE:
|
||||
//Ignore, is information only.
|
||||
break;
|
||||
//*******Default monitoring variables. Are currently not used.*****
|
||||
// case DeviceHandlerIF::MONITORING_LIMIT_EXCEEDED:
|
||||
// setFaulty(event->getEvent());
|
||||
// break;
|
||||
// case DeviceHandlerIF::MONITORING_AMBIGUOUS:
|
||||
// break;
|
||||
default:
|
||||
//We don't know the event, someone else should handle it.
|
||||
return RETURN_FAILED;
|
||||
@ -125,7 +107,7 @@ ReturnValue_t DeviceHandlerFDIR::eventReceived(EventMessage* event) {
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
void DeviceHandlerFDIR::eventConfirmed(EventMessage* event) {
|
||||
void DeviceHandlerFailureIsolation::eventConfirmed(EventMessage* event) {
|
||||
switch (event->getEvent()) {
|
||||
case DeviceHandlerIF::DEVICE_SENDING_COMMAND_FAILED:
|
||||
case DeviceHandlerIF::DEVICE_REQUESTING_REPLY_FAILED:
|
||||
@ -143,13 +125,13 @@ void DeviceHandlerFDIR::eventConfirmed(EventMessage* event) {
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceHandlerFDIR::decrementFaultCounters() {
|
||||
void DeviceHandlerFailureIsolation::decrementFaultCounters() {
|
||||
strangeReplyCount.checkForDecrement();
|
||||
missedReplyCount.checkForDecrement();
|
||||
recoveryCounter.checkForDecrement();
|
||||
}
|
||||
|
||||
void DeviceHandlerFDIR::handleRecovery(Event reason) {
|
||||
void DeviceHandlerFailureIsolation::handleRecovery(Event reason) {
|
||||
clearFaultCounters();
|
||||
if (!recoveryCounter.incrementAndCheck()) {
|
||||
startRecovery(reason);
|
||||
@ -158,7 +140,7 @@ void DeviceHandlerFDIR::handleRecovery(Event reason) {
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceHandlerFDIR::wasParentsFault(EventMessage* event) {
|
||||
void DeviceHandlerFailureIsolation::wasParentsFault(EventMessage* event) {
|
||||
//We'll better ignore the SWITCH_WENT_OFF event and await a system-wide reset.
|
||||
//This means, no fault message will come through until a MODE_ or HEALTH_INFO message comes through -> Is that ok?
|
||||
//Same issue in TxFailureIsolation!
|
||||
@ -168,18 +150,18 @@ void DeviceHandlerFDIR::wasParentsFault(EventMessage* event) {
|
||||
// }
|
||||
}
|
||||
|
||||
void DeviceHandlerFDIR::clearFaultCounters() {
|
||||
void DeviceHandlerFailureIsolation::clearFaultCounters() {
|
||||
strangeReplyCount.clear();
|
||||
missedReplyCount.clear();
|
||||
}
|
||||
|
||||
ReturnValue_t DeviceHandlerFDIR::initialize() {
|
||||
ReturnValue_t result = FDIRBase::initialize();
|
||||
ReturnValue_t DeviceHandlerFailureIsolation::initialize() {
|
||||
ReturnValue_t result = FailureIsolationBase::initialize();
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
ConfirmsFailuresIF* power = objectManager->get<ConfirmsFailuresIF>(
|
||||
objects::PCDU_HANDLER);
|
||||
powerConfirmationId);
|
||||
if (power == NULL) {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
@ -187,31 +169,31 @@ ReturnValue_t DeviceHandlerFDIR::initialize() {
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
void DeviceHandlerFDIR::setFdirState(FDIRState state) {
|
||||
FDIRBase::throwFdirEvent(FDIR_CHANGED_STATE, state, fdirState);
|
||||
void DeviceHandlerFailureIsolation::setFdirState(FDIRState state) {
|
||||
FailureIsolationBase::throwFdirEvent(FDIR_CHANGED_STATE, state, fdirState);
|
||||
fdirState = state;
|
||||
}
|
||||
|
||||
void DeviceHandlerFDIR::triggerEvent(Event event, uint32_t parameter1,
|
||||
void DeviceHandlerFailureIsolation::triggerEvent(Event event, uint32_t parameter1,
|
||||
uint32_t parameter2) {
|
||||
//Do not throw error events if fdirState != none.
|
||||
//This will still forward MODE and HEALTH INFO events in any case.
|
||||
if (fdirState == NONE || EVENT::getSeverity(event) == SEVERITY::INFO) {
|
||||
FDIRBase::triggerEvent(event, parameter1, parameter2);
|
||||
FailureIsolationBase::triggerEvent(event, parameter1, parameter2);
|
||||
}
|
||||
}
|
||||
|
||||
bool DeviceHandlerFDIR::isFdirActionInProgress() {
|
||||
bool DeviceHandlerFailureIsolation::isFdirActionInProgress() {
|
||||
return (fdirState != NONE);
|
||||
}
|
||||
|
||||
void DeviceHandlerFDIR::startRecovery(Event reason) {
|
||||
void DeviceHandlerFailureIsolation::startRecovery(Event reason) {
|
||||
throwFdirEvent(FDIR_STARTS_RECOVERY, EVENT::getEventId(reason));
|
||||
setOwnerHealth(HasHealthIF::NEEDS_RECOVERY);
|
||||
setFdirState(RECOVERY_ONGOING);
|
||||
}
|
||||
|
||||
ReturnValue_t DeviceHandlerFDIR::getParameter(uint8_t domainId,
|
||||
ReturnValue_t DeviceHandlerFailureIsolation::getParameter(uint8_t domainId,
|
||||
uint16_t parameterId, ParameterWrapper* parameterWrapper,
|
||||
const ParameterWrapper* newValues, uint16_t startAtIndex) {
|
||||
ReturnValue_t result = strangeReplyCount.getParameter(domainId, parameterId,
|
||||
@ -232,8 +214,30 @@ ReturnValue_t DeviceHandlerFDIR::getParameter(uint8_t domainId,
|
||||
return INVALID_DOMAIN_ID;
|
||||
}
|
||||
|
||||
void DeviceHandlerFDIR::setFaulty(Event reason) {
|
||||
void DeviceHandlerFailureIsolation::setFaulty(Event reason) {
|
||||
throwFdirEvent(FDIR_TURNS_OFF_DEVICE, EVENT::getEventId(reason));
|
||||
setOwnerHealth(HasHealthIF::FAULTY);
|
||||
setFdirState(AWAIT_SHUTDOWN);
|
||||
}
|
||||
|
||||
bool DeviceHandlerFailureIsolation::isFdirInActionOrAreWeFaulty(
|
||||
EventMessage* event) {
|
||||
if (fdirState != NONE) {
|
||||
//Only wait for those events, ignore all others.
|
||||
if (event->getParameter1() == HasHealthIF::HEALTHY
|
||||
&& event->getEvent() == HasHealthIF::HEALTH_INFO) {
|
||||
setFdirState(NONE);
|
||||
}
|
||||
if (event->getEvent() == HasModesIF::MODE_INFO
|
||||
&& fdirState != RECOVERY_ONGOING) {
|
||||
setFdirState(NONE);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (owner->getHealth() == HasHealthIF::FAULTY
|
||||
|| owner->getHealth() == HasHealthIF::PERMANENT_FAULTY) {
|
||||
//Ignore all events in case device is already faulty.
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
@ -1,27 +1,22 @@
|
||||
/*
|
||||
* DeviceHandlerFDIR.h
|
||||
*
|
||||
* Created on: 09.09.2015
|
||||
* Author: baetz
|
||||
*/
|
||||
|
||||
#ifndef FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERFDIR_H_
|
||||
#define FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERFDIR_H_
|
||||
#ifndef FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERFAILUREISOLATION_H_
|
||||
#define FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERFAILUREISOLATION_H_
|
||||
|
||||
#include <framework/fdir/FaultCounter.h>
|
||||
#include <framework/fdir/FDIRBase.h>
|
||||
#include <framework/fdir/FailureIsolationBase.h>
|
||||
namespace Factory{
|
||||
void setStaticFrameworkObjectIds();
|
||||
}
|
||||
|
||||
class DeviceHandlerFDIR: public FDIRBase {
|
||||
|
||||
class DeviceHandlerFailureIsolation: public FailureIsolationBase {
|
||||
friend void (Factory::setStaticFrameworkObjectIds)();
|
||||
friend class Heater;
|
||||
public:
|
||||
DeviceHandlerFDIR(object_id_t owner, object_id_t parent = objects::IO_ASSEMBLY);
|
||||
~DeviceHandlerFDIR();
|
||||
virtual ReturnValue_t eventReceived(EventMessage* event);
|
||||
void eventConfirmed(EventMessage* event);
|
||||
void wasParentsFault(EventMessage* event);
|
||||
void decrementFaultCounters();
|
||||
DeviceHandlerFailureIsolation(object_id_t owner, object_id_t parent);
|
||||
~DeviceHandlerFailureIsolation();
|
||||
ReturnValue_t initialize();
|
||||
void triggerEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0);
|
||||
bool isFdirActionInProgress();
|
||||
void triggerEvent(Event event, uint32_t parameter1 = 0,
|
||||
uint32_t parameter2 = 0);bool isFdirActionInProgress();
|
||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
||||
ParameterWrapper *parameterWrapper,
|
||||
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
||||
@ -30,25 +25,28 @@ protected:
|
||||
FaultCounter missedReplyCount;
|
||||
FaultCounter recoveryCounter;
|
||||
enum FDIRState {
|
||||
NONE,
|
||||
RECOVERY_ONGOING,
|
||||
DEVICE_MIGHT_BE_OFF,
|
||||
AWAIT_SHUTDOWN
|
||||
NONE, RECOVERY_ONGOING, DEVICE_MIGHT_BE_OFF, AWAIT_SHUTDOWN
|
||||
};
|
||||
FDIRState fdirState;
|
||||
MessageQueueId_t powerConfirmation;
|
||||
//TODO: Arbitrary numbers! Adjust!
|
||||
static object_id_t powerConfirmationId;
|
||||
static const uint32_t MAX_REBOOT = 1;
|
||||
static const uint32_t REBOOT_TIME_MS = 180000;
|
||||
static const uint32_t MAX_STRANGE_REPLIES = 10;
|
||||
static const uint32_t STRANGE_REPLIES_TIME_MS = 10000;
|
||||
static const uint32_t MAX_MISSED_REPLY_COUNT = 5;
|
||||
static const uint32_t MISSED_REPLY_TIME_MS = 10000;
|
||||
virtual ReturnValue_t eventReceived(EventMessage* event);
|
||||
virtual void eventConfirmed(EventMessage* event);
|
||||
void wasParentsFault(EventMessage* event);
|
||||
void decrementFaultCounters();
|
||||
void handleRecovery(Event reason);
|
||||
virtual void clearFaultCounters();
|
||||
void setFdirState(FDIRState state);
|
||||
void startRecovery(Event reason);
|
||||
void setFaulty(Event reason);
|
||||
|
||||
bool isFdirInActionOrAreWeFaulty(EventMessage* event);
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERFDIR_H_ */
|
||||
#endif /* FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERFAILUREISOLATION_H_ */
|
@ -4,8 +4,8 @@
|
||||
#include <framework/action/HasActionsIF.h>
|
||||
#include <framework/devicehandlers/DeviceHandlerMessage.h>
|
||||
#include <framework/events/Event.h>
|
||||
#include <framework/ipc/MessageQueue.h>
|
||||
#include <framework/modes/HasModesIF.h>
|
||||
#include <framework/ipc/MessageQueueSenderIF.h>
|
||||
|
||||
/**
|
||||
* This is the Interface used to communicate with a device handler.
|
||||
@ -52,7 +52,7 @@ public:
|
||||
static const Event MONITORING_LIMIT_EXCEEDED = MAKE_EVENT(9, SEVERITY::LOW);
|
||||
static const Event MONITORING_AMBIGUOUS = MAKE_EVENT(10, SEVERITY::HIGH);
|
||||
|
||||
static const uint8_t INTERFACE_ID = DEVICE_HANDLER_IF;
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_IF;
|
||||
static const ReturnValue_t NO_COMMAND_DATA = MAKE_RETURN_CODE(0xA0);
|
||||
static const ReturnValue_t COMMAND_NOT_SUPPORTED = MAKE_RETURN_CODE(0xA1);
|
||||
static const ReturnValue_t COMMAND_ALREADY_SENT = MAKE_RETURN_CODE(0xA2);
|
||||
@ -63,6 +63,7 @@ public:
|
||||
static const ReturnValue_t BUSY = MAKE_RETURN_CODE(0xA7);
|
||||
static const ReturnValue_t NO_REPLY_EXPECTED = MAKE_RETURN_CODE(0xA8); //!< Used to indicate that this is a command-only command.
|
||||
static const ReturnValue_t NON_OP_TEMPERATURE = MAKE_RETURN_CODE(0xA9);
|
||||
static const ReturnValue_t COMMAND_NOT_IMPLEMENTED = MAKE_RETURN_CODE(0xAA);
|
||||
|
||||
//standard codes used in scan for reply
|
||||
// static const ReturnValue_t TOO_SHORT = MAKE_RETURN_CODE(0xB1);
|
||||
@ -82,6 +83,19 @@ public:
|
||||
0xD0);
|
||||
static const ReturnValue_t INVALID_NUMBER_OR_LENGTH_OF_PARAMETERS =
|
||||
MAKE_RETURN_CODE(0xD1);
|
||||
|
||||
/**
|
||||
* RMAP Action that will be executed.
|
||||
*
|
||||
* This is used by the child class to tell the base class what to do.
|
||||
*/
|
||||
enum RmapAction_t {
|
||||
SEND_WRITE,//!< RMAP send write
|
||||
GET_WRITE, //!< RMAP get write
|
||||
SEND_READ, //!< RMAP send read
|
||||
GET_READ, //!< RMAP get read
|
||||
NOTHING //!< Do nothing.
|
||||
};
|
||||
/**
|
||||
* Default Destructor
|
||||
*/
|
||||
|
@ -89,7 +89,7 @@ void DeviceHandlerMessage::clear(CommandMessage* message) {
|
||||
ipcStore->deleteData(getStoreAddress(message));
|
||||
}
|
||||
}
|
||||
/* NO BREAK*/
|
||||
/* NO BREAK falls through*/
|
||||
case CMD_SWITCH_IOBOARD:
|
||||
case CMD_WIRETAPPING:
|
||||
message->setCommand(CommandMessage::CMD_NONE);
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include <framework/ipc/CommandMessage.h>
|
||||
#include <framework/objectmanager/SystemObjectIF.h>
|
||||
#include <framework/storagemanager/StorageManagerIF.h>
|
||||
//TODO: rework the static constructors to name the type of command they are building, maybe even hide setting the commandID.
|
||||
//SHOULDDO: rework the static constructors to name the type of command they are building, maybe even hide setting the commandID.
|
||||
|
||||
/**
|
||||
* This is used to uniquely identify commands that are sent to a device
|
||||
@ -25,7 +25,7 @@ public:
|
||||
/**
|
||||
* These are the commands that can be sent to a DeviceHandlerBase
|
||||
*/
|
||||
static const uint8_t MESSAGE_ID = DEVICE_HANDLER_COMMAND_MESSAGE_ID;
|
||||
static const uint8_t MESSAGE_ID = MESSAGE_TYPE::DEVICE_HANDLER_COMMAND;
|
||||
static const Command_t CMD_RAW = MAKE_COMMAND_ID( 1 ); //!< Sends a raw command, setParameter is a ::store_id_t containing the raw packet to send
|
||||
// static const Command_t CMD_DIRECT = MAKE_COMMAND_ID( 2 ); //!< Sends a direct command, setParameter is a ::DeviceCommandId_t, setParameter2 is a ::store_id_t containing the data needed for the command
|
||||
static const Command_t CMD_SWITCH_IOBOARD = MAKE_COMMAND_ID( 3 ); //!< Requests a IO-Board switch, setParameter() is the IO-Board identifier
|
||||
|
21
devicehandlers/FixedSequenceSlot.cpp
Normal file
21
devicehandlers/FixedSequenceSlot.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
/**
|
||||
* @file PollingSlot.cpp
|
||||
* @brief This file defines the PollingSlot class.
|
||||
* @date 19.12.2012
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#include <framework/devicehandlers/FixedSequenceSlot.h>
|
||||
#include <framework/objectmanager/SystemObjectIF.h>
|
||||
#include <cstddef>
|
||||
|
||||
FixedSequenceSlot::FixedSequenceSlot(object_id_t handlerId, uint32_t setTime,
|
||||
int8_t setSequenceId, PeriodicTaskIF* executingTask) :
|
||||
handler(NULL), pollingTimeMs(setTime), opcode(setSequenceId) {
|
||||
handler = objectManager->get<ExecutableObjectIF>(handlerId);
|
||||
handler->setTaskIF(executingTask);
|
||||
}
|
||||
|
||||
FixedSequenceSlot::~FixedSequenceSlot() {
|
||||
}
|
||||
|
@ -1,44 +1,40 @@
|
||||
/**
|
||||
* @file PollingSlot.h
|
||||
* @file FixedSequenceSlot.h
|
||||
* @brief This file defines the PollingSlot class.
|
||||
* @date 19.12.2012
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#ifndef POLLINGSLOT_H_
|
||||
#define POLLINGSLOT_H_
|
||||
#ifndef FIXEDSEQUENCESLOT_H_
|
||||
#define FIXEDSEQUENCESLOT_H_
|
||||
|
||||
#include <framework/devicehandlers/PollingSequenceExecutableIF.h>
|
||||
#include <framework/objectmanager/ObjectManagerIF.h>
|
||||
#include <framework/osal/OSAL.h>
|
||||
|
||||
class PollingSequence;
|
||||
#include <framework/tasks/ExecutableObjectIF.h>
|
||||
class PeriodicTaskIF;
|
||||
|
||||
/**
|
||||
* \brief This class is the representation of a single polling sequence table entry.
|
||||
*
|
||||
* \details The PollingSlot class is the representation of a single polling sequence table entry.
|
||||
* It contains three attributes and a debug method to print its content.
|
||||
*/
|
||||
class PollingSlot {
|
||||
friend class PollingSequence;
|
||||
friend class PollingTask;
|
||||
friend ReturnValue_t pollingSequenceInitFunction(PollingSequence *thisSequence);
|
||||
friend ReturnValue_t payloadSequenceInitFunction(PollingSequence *thisSequence);
|
||||
protected:
|
||||
class FixedSequenceSlot {
|
||||
public:
|
||||
FixedSequenceSlot( object_id_t handlerId, uint32_t setTimeMs, int8_t setSequenceId, PeriodicTaskIF* executingTask );
|
||||
virtual ~FixedSequenceSlot();
|
||||
|
||||
/**
|
||||
* \brief \c handler identifies which device handler object is executed in this slot.
|
||||
*/
|
||||
PollingSequenceExecutableIF* handler;
|
||||
ExecutableObjectIF* handler;
|
||||
|
||||
/**
|
||||
* \brief This attribute defines when a device handler object is executed.
|
||||
*
|
||||
* \details The pollingTime attribute identifies the time the handler is executed in clock ticks. It must be
|
||||
* \details The pollingTime attribute identifies the time the handler is executed in ms. It must be
|
||||
* smaller than the period length of the polling sequence, what is ensured by automated calculation
|
||||
* from a database.
|
||||
*/
|
||||
Interval_t pollingTime;
|
||||
uint32_t pollingTimeMs;
|
||||
|
||||
/**
|
||||
* \brief This value defines the type of device communication.
|
||||
@ -46,16 +42,7 @@ protected:
|
||||
* \details The state of this value decides what communication routine is called in the PST executable or the device handler object.
|
||||
*/
|
||||
uint8_t opcode;
|
||||
|
||||
public:
|
||||
PollingSlot( object_id_t handlerId, Interval_t setTime, int8_t setSequenceId );
|
||||
virtual ~PollingSlot();
|
||||
|
||||
/**
|
||||
* \brief This is a small debug method to print the PollingSlot's content to a debug interface.
|
||||
*/
|
||||
void print() const;
|
||||
};
|
||||
|
||||
|
||||
#endif /* POLLINGSLOT_H_ */
|
||||
#endif /* FIXEDSEQUENCESLOT_H_ */
|
109
devicehandlers/FixedSlotSequence.cpp
Normal file
109
devicehandlers/FixedSlotSequence.cpp
Normal file
@ -0,0 +1,109 @@
|
||||
#include <framework/devicehandlers/FixedSlotSequence.h>
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
|
||||
FixedSlotSequence::FixedSlotSequence(uint32_t setLengthMs) :
|
||||
lengthMs(setLengthMs) {
|
||||
current = slotList.begin();
|
||||
}
|
||||
|
||||
FixedSlotSequence::~FixedSlotSequence() {
|
||||
std::list<FixedSequenceSlot*>::iterator slotIt;
|
||||
//Iterate through slotList and delete all entries.
|
||||
slotIt = this->slotList.begin();
|
||||
while (slotIt != this->slotList.end()) {
|
||||
delete (*slotIt);
|
||||
slotIt++;
|
||||
}
|
||||
}
|
||||
|
||||
void FixedSlotSequence::executeAndAdvance() {
|
||||
// (*this->current)->print();
|
||||
(*this->current)->handler->performOperation((*this->current)->opcode);
|
||||
// if (returnValue != RETURN_OK) {
|
||||
// this->sendErrorMessage( returnValue );
|
||||
// }
|
||||
//Increment the polling Sequence iterator
|
||||
this->current++;
|
||||
//Set it to the beginning, if the list's end is reached.
|
||||
if (this->current == this->slotList.end()) {
|
||||
this->current = this->slotList.begin();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t FixedSlotSequence::getIntervalMs() {
|
||||
uint32_t oldTime;
|
||||
std::list<FixedSequenceSlot*>::iterator it;
|
||||
it = current;
|
||||
// Get the pollingTimeMs of the current slot object.
|
||||
oldTime = (*it)->pollingTimeMs;
|
||||
// Advance to the next object.
|
||||
it++;
|
||||
// Find the next interval which is not 0.
|
||||
while (it != slotList.end()) {
|
||||
if (oldTime != (*it)->pollingTimeMs) {
|
||||
return (*it)->pollingTimeMs - oldTime;
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
// If the list end is reached (this is definitely an interval != 0),
|
||||
// the interval is calculated by subtracting the remaining time of the PST
|
||||
// and adding the start time of the first handler in the list.
|
||||
it = slotList.begin();
|
||||
return lengthMs - oldTime + (*it)->pollingTimeMs;
|
||||
}
|
||||
|
||||
bool FixedSlotSequence::slotFollowsImmediately() {
|
||||
uint32_t currentTime = (*current)->pollingTimeMs;
|
||||
std::list<FixedSequenceSlot*>::iterator it;
|
||||
it = this->current;
|
||||
// Get the pollingTimeMs of the current slot object.
|
||||
if (it == slotList.begin())
|
||||
return false;
|
||||
it--;
|
||||
if ((*it)->pollingTimeMs == currentTime) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t FixedSlotSequence::getLengthMs() const {
|
||||
return this->lengthMs;
|
||||
}
|
||||
|
||||
ReturnValue_t FixedSlotSequence::checkSequence() const {
|
||||
//Iterate through slotList and check successful creation. Checks if timing is ok (must be ascending) and if all handlers were found.
|
||||
auto slotIt = slotList.begin();
|
||||
uint32_t count = 0;
|
||||
uint32_t time = 0;
|
||||
while (slotIt != slotList.end()) {
|
||||
if ((*slotIt)->handler == NULL) {
|
||||
error << "FixedSlotSequene::initialize: ObjectId does not exist!"
|
||||
<< std::endl;
|
||||
count++;
|
||||
} else if ((*slotIt)->pollingTimeMs < time) {
|
||||
error << "FixedSlotSequence::initialize: Time: "
|
||||
<< (*slotIt)->pollingTimeMs
|
||||
<< " is smaller than previous with " << time << std::endl;
|
||||
count++;
|
||||
} else {
|
||||
//All ok, print slot.
|
||||
// (*slotIt)->print();
|
||||
}
|
||||
time = (*slotIt)->pollingTimeMs;
|
||||
slotIt++;
|
||||
}
|
||||
if (count > 0) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
void FixedSlotSequence::addSlot(object_id_t componentId, uint32_t slotTimeMs,
|
||||
int8_t executionStep, PeriodicTaskIF* executingTask) {
|
||||
this->slotList.push_back(
|
||||
new FixedSequenceSlot(componentId, slotTimeMs, executionStep,
|
||||
executingTask));
|
||||
this->current = slotList.begin();
|
||||
}
|
@ -1,24 +1,14 @@
|
||||
/**
|
||||
* @file PollingSequence.h
|
||||
* @brief This file defines the PollingSequence class.
|
||||
* @date 19.12.2012
|
||||
* @author baetz
|
||||
*/
|
||||
#ifndef FIXEDSLOTSEQUENCE_H_
|
||||
#define FIXEDSLOTSEQUENCE_H_
|
||||
|
||||
#ifndef POLLINGSEQUENCE_H_
|
||||
#define POLLINGSEQUENCE_H_
|
||||
|
||||
#include <framework/devicehandlers/PollingSequenceExecutableIF.h>
|
||||
#include <framework/devicehandlers/PollingSlot.h>
|
||||
#include <framework/devicehandlers/FixedSequenceSlot.h>
|
||||
#include <framework/objectmanager/SystemObject.h>
|
||||
#include <framework/osal/OSAL.h>
|
||||
#include<list>
|
||||
|
||||
#include <list>
|
||||
|
||||
/**
|
||||
* \brief This class is the representation of a Polling Sequence Table in software.
|
||||
*
|
||||
* \details The PollingSequence object maintains the dynamic execution of device handler objects.
|
||||
* \details The FixedSlotSequence object maintains the dynamic execution of device handler objects.
|
||||
* The main idea is to create a list of device handlers, to announce all handlers to the
|
||||
* polling sequence and to maintain a list of polling slot objects. This slot list represents the
|
||||
* Polling Sequence Table in software. Each polling slot contains information to indicate when and
|
||||
@ -26,10 +16,78 @@
|
||||
* The sequence is then executed by iterating through this slot list.
|
||||
* Handlers are invoking by calling a certain function stored in the handler list.
|
||||
*/
|
||||
class PollingSequence : public SystemObject {
|
||||
friend class PollingTask;
|
||||
friend ReturnValue_t pollingSequenceInitFunction(PollingSequence *thisSequence);
|
||||
friend ReturnValue_t payloadSequenceInitFunction(PollingSequence *thisSequence);
|
||||
class FixedSlotSequence {
|
||||
public:
|
||||
|
||||
/**
|
||||
* \brief The constructor of the FixedSlotSequence object.
|
||||
*
|
||||
* \details The constructor takes two arguments, the period length and the init function.
|
||||
*
|
||||
* \param setLength The period length, expressed in ms.
|
||||
*/
|
||||
FixedSlotSequence(uint32_t setLengthMs);
|
||||
|
||||
/**
|
||||
* \brief The destructor of the FixedSlotSequence object.
|
||||
*
|
||||
* \details The destructor frees all allocated memory by iterating through the slotList
|
||||
* and deleting all allocated resources.
|
||||
*/
|
||||
virtual ~FixedSlotSequence();
|
||||
|
||||
/**
|
||||
* \brief This is a method to add an PollingSlot object to slotList.
|
||||
*
|
||||
* \details Here, a polling slot object is added to the slot list. It is appended
|
||||
* to the end of the list. The list is currently NOT reordered.
|
||||
* Afterwards, the iterator current is set to the beginning of the list.
|
||||
*/
|
||||
void addSlot(object_id_t handlerId, uint32_t setTime, int8_t setSequenceId,
|
||||
PeriodicTaskIF* executingTask);
|
||||
|
||||
/**
|
||||
* Checks if the current slot shall be executed immediately after the one before.
|
||||
* This allows to distinguish between grouped and not grouped handlers.
|
||||
* @return - @c true if the slot has the same polling time as the previous
|
||||
* - @c false else
|
||||
*/
|
||||
bool slotFollowsImmediately();
|
||||
|
||||
/**
|
||||
* \brief This method returns the time until the next software component is invoked.
|
||||
*
|
||||
* \details This method is vitally important for the operation of the PST. By fetching the polling time
|
||||
* of the current slot and that of the next one (or the first one, if the list end is reached)
|
||||
* it calculates and returns the interval in clock ticks within which the handler execution
|
||||
* shall take place.
|
||||
*/
|
||||
uint32_t getIntervalMs();
|
||||
|
||||
/**
|
||||
* \brief This method returns the length of this FixedSlotSequence instance.
|
||||
*/
|
||||
uint32_t getLengthMs() const;
|
||||
|
||||
/**
|
||||
* \brief The method to execute the device handler entered in the current OPUSPollingSlot object.
|
||||
*
|
||||
* \details Within this method the device handler object to be executed is chosen by looking up the
|
||||
* handler address of the current slot in the handlerMap. Either the device handler's
|
||||
* talkToInterface or its listenToInterface method is invoked, depending on the isTalking flag
|
||||
* of the polling slot. After execution the iterator current is increased or, by reaching the
|
||||
* end of slotList, reset to the beginning.
|
||||
*/
|
||||
void executeAndAdvance();
|
||||
|
||||
/**
|
||||
* \brief An iterator that indicates the current polling slot to execute.
|
||||
*
|
||||
* \details This is an iterator for slotList and always points to the polling slot which is executed next.
|
||||
*/
|
||||
std::list<FixedSequenceSlot*>::iterator current;
|
||||
|
||||
ReturnValue_t checkSequence() const;
|
||||
protected:
|
||||
|
||||
/**
|
||||
@ -41,109 +99,9 @@ protected:
|
||||
* By iterating through this list the polling sequence is executed. Two entries with identical
|
||||
* polling times are executed immediately one after another.
|
||||
*/
|
||||
std::list<PollingSlot*> slotList;
|
||||
std::list<FixedSequenceSlot*> slotList;
|
||||
|
||||
/**
|
||||
* \brief An iterator that indicates the current polling slot to execute.
|
||||
*
|
||||
* \details This is an iterator for slotList and always points to the polling slot which is executed next.
|
||||
*/
|
||||
std::list<PollingSlot*>::iterator current;
|
||||
|
||||
/**
|
||||
* \brief The period of the Polling Sequence Table in clock ticks.
|
||||
*
|
||||
* \details This attribute is set within the constructor, defining the main period length of the
|
||||
* Polling Sequence Table. The length is expressed in clock ticks.
|
||||
*
|
||||
*/
|
||||
Interval_t length;
|
||||
|
||||
/**
|
||||
* \brief The init function passed by the ctor
|
||||
*
|
||||
* \details This function will be called during initialize()
|
||||
*
|
||||
*/
|
||||
ReturnValue_t (*initFunction)(PollingSequence *thisSequence);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* \brief The constructor of the PollingSequence object.
|
||||
*
|
||||
* \details The constructor takes two arguments, the period length and the init function.
|
||||
*
|
||||
* \param setLength The period length, expressed in clock ticks.
|
||||
*/
|
||||
PollingSequence( object_id_t setObjectId, Interval_t setLength, ReturnValue_t (*initFunction)(PollingSequence *thisSequence) );
|
||||
|
||||
/**
|
||||
* \brief The destructor of the PollingSequence object.
|
||||
*
|
||||
* \details The destructor frees all allocated memory by iterating through
|
||||
* handlerMap and slotList and deleting all allocated resources.
|
||||
*/
|
||||
virtual ~PollingSequence();
|
||||
|
||||
/**
|
||||
* \brief This is a method to add an OPUSPollingSlot object to slotList.
|
||||
*
|
||||
* \details Here, a polling slot object is added to the slot list. It is appended
|
||||
* to the end of the list. The list is currently NOT reordered.
|
||||
* Afterwards, the iterator current is set to the beginning of the list.
|
||||
*
|
||||
* \param setSlot This is a pointer to a OPUSPollingSlot object.
|
||||
*/
|
||||
void addSlot( PollingSlot* setSlot );
|
||||
|
||||
/**
|
||||
* Checks if the current slot shall be executed immediately after the one before.
|
||||
* This allows to distinguish between grouped and not grouped handlers.
|
||||
* @return - @c true if the slot has the same polling time as the previous
|
||||
* - @c false else
|
||||
*/
|
||||
bool slotFollowsImmediately();
|
||||
|
||||
/**
|
||||
* \brief This method returns the time until the next device handler object is invoked.
|
||||
*
|
||||
* \details This method is vitally important for the operation of the PST. By fetching the polling time
|
||||
* of the current slot and that of the next one (or the first one, if the list end is reached)
|
||||
* it calculates and returns the interval in clock ticks within which the handler execution
|
||||
* shall take place.
|
||||
*/
|
||||
Interval_t getInterval();
|
||||
|
||||
/**
|
||||
* \brief This method returns the length of this PollingSequence instance.
|
||||
*/
|
||||
Interval_t getLength();
|
||||
|
||||
/**
|
||||
* \brief The method to execute the device handler entered in the current OPUSPollingSlot object.
|
||||
*
|
||||
* \details Within this method the device handler object to be executed is chosen by looking up the
|
||||
* handler address of the current slot in the handlerMap. Either the device handler's
|
||||
* talkToInterface or its listenToInterface method is invoked, depending on the isTalking flag
|
||||
* of the polling slot. After execution the iterator current is increased or, by reaching the
|
||||
* end of slotList, reset to the beginning.
|
||||
*/
|
||||
void pollAndAdvance();
|
||||
|
||||
/**
|
||||
* \brief This is a method to print debug output.
|
||||
*
|
||||
* \details print is a simple debug method to print the whole polling sequence to the debug interface.
|
||||
* It iterates through slotList and calls all print()} functions of the announced polling slot
|
||||
* instances.
|
||||
*
|
||||
*/
|
||||
void print();
|
||||
|
||||
ReturnValue_t initialize();
|
||||
//std::string getObjectTypeAsString();
|
||||
uint32_t lengthMs;
|
||||
};
|
||||
|
||||
|
||||
#endif /* POLLINGSEQUENCE_H_ */
|
||||
#endif /* FIXEDSLOTSEQUENCE_H_ */
|
@ -1,18 +1,20 @@
|
||||
#include <framework/devicehandlers/HealthDevice.h>
|
||||
#include <framework/ipc/QueueFactory.h>
|
||||
|
||||
HealthDevice::HealthDevice(object_id_t setObjectId,
|
||||
MessageQueueId_t parentQueue) :
|
||||
SystemObject(setObjectId), lastHealth(HEALTHY), parentQueue(
|
||||
parentQueue), commandQueue(3,
|
||||
CommandMessage::COMMAND_MESSAGE_SIZE), healthHelper(this, setObjectId) {
|
||||
parentQueue), commandQueue(), healthHelper(this, setObjectId) {
|
||||
commandQueue = QueueFactory::instance()->createMessageQueue(3, CommandMessage::COMMAND_MESSAGE_SIZE);
|
||||
}
|
||||
|
||||
HealthDevice::~HealthDevice() {
|
||||
QueueFactory::instance()->deleteMessageQueue(commandQueue);
|
||||
}
|
||||
|
||||
ReturnValue_t HealthDevice::performOperation() {
|
||||
ReturnValue_t HealthDevice::performOperation(uint8_t opCode) {
|
||||
CommandMessage message;
|
||||
ReturnValue_t result = commandQueue.receiveMessage(&message);
|
||||
ReturnValue_t result = commandQueue->receiveMessage(&message);
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
healthHelper.handleHealthCommand(&message);
|
||||
}
|
||||
@ -32,7 +34,7 @@ ReturnValue_t HealthDevice::initialize() {
|
||||
}
|
||||
|
||||
MessageQueueId_t HealthDevice::getCommandQueue() const {
|
||||
return commandQueue.getId();
|
||||
return commandQueue->getId();
|
||||
}
|
||||
|
||||
void HealthDevice::setParentQueue(MessageQueueId_t parentQueue) {
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <framework/health/HealthHelper.h>
|
||||
#include <framework/objectmanager/SystemObject.h>
|
||||
#include <framework/tasks/ExecutableObjectIF.h>
|
||||
#include <framework/ipc/MessageQueueIF.h>
|
||||
|
||||
class HealthDevice: public SystemObject,
|
||||
public ExecutableObjectIF,
|
||||
@ -13,7 +14,7 @@ public:
|
||||
HealthDevice(object_id_t setObjectId, MessageQueueId_t parentQueue);
|
||||
virtual ~HealthDevice();
|
||||
|
||||
ReturnValue_t performOperation();
|
||||
ReturnValue_t performOperation(uint8_t opCode);
|
||||
|
||||
ReturnValue_t initialize();
|
||||
|
||||
@ -31,7 +32,7 @@ protected:
|
||||
HealthState lastHealth;
|
||||
|
||||
MessageQueueId_t parentQueue;
|
||||
MessageQueue commandQueue;
|
||||
MessageQueueIF* commandQueue;
|
||||
public:
|
||||
HealthHelper healthHelper;
|
||||
};
|
||||
|
@ -1,28 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# OPUS makefile
|
||||
#
|
||||
# Created on: Mar 04, 2010
|
||||
# Author: ziemke
|
||||
# Author: Claas Ziemke
|
||||
# Copyright 2010, Claas Ziemke <claas.ziemke@gmx.net>
|
||||
#
|
||||
|
||||
BASEDIR=../../
|
||||
include $(BASEDIR)options.mk
|
||||
|
||||
OBJ = $(BUILDDIR)/ChannelResetHandler.o \
|
||||
$(BUILDDIR)/RawCommandHandler.o \
|
||||
$(BUILDDIR)/RawDataHandler.o \
|
||||
$(BUILDDIR)/OPUSPollingSequence.o \
|
||||
$(BUILDDIR)/PollingTask.o \
|
||||
$(BUILDDIR)/Device.o \
|
||||
$(BUILDDIR)/RmapCookie.o \
|
||||
|
||||
all: $(OBJ)
|
||||
|
||||
$(BUILDDIR)/%.o: %.cpp %.h
|
||||
$(CPP) $(CFLAGS) $(DEFINES) $(CCOPT) ${INCLUDE} -c $< -o $@
|
||||
|
||||
clean:
|
||||
$(RM) *.o *.gcno *.gcda
|
@ -1,115 +0,0 @@
|
||||
/**
|
||||
* @file PollingSequence.cpp
|
||||
* @brief This file defines the PollingSequence class.
|
||||
* @date 19.12.2012
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#include <framework/devicehandlers/PollingSequence.h>
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
|
||||
|
||||
uint32_t PollingSequenceExecutableIF::pollingSequenceLengthMs = 0;
|
||||
uint32_t PollingSequenceExecutableIF::payloadSequenceLengthMs = 0;
|
||||
|
||||
PollingSequence::PollingSequence(object_id_t setObjectId, Interval_t setLength, ReturnValue_t (*initFunction)(PollingSequence *thisSequence)) : SystemObject( setObjectId ),
|
||||
initFunction(initFunction){
|
||||
this->length = setLength;
|
||||
// PollingSequenceExecutableIF::pollingSequenceLengthMs = (setLength * 1000)
|
||||
// / OSAL::getTicksPerSecond();
|
||||
current = slotList.begin();
|
||||
}
|
||||
|
||||
PollingSequence::~PollingSequence() {
|
||||
std::list<PollingSlot*>::iterator slotIt;
|
||||
//Iterate through slotList and delete all entries.
|
||||
slotIt = this->slotList.begin();
|
||||
while (slotIt != this->slotList.end()) {
|
||||
delete (*slotIt);
|
||||
slotIt++;
|
||||
}
|
||||
}
|
||||
|
||||
void PollingSequence::addSlot(PollingSlot* setSlot) {
|
||||
//The slot is added to the end of the list.
|
||||
this->slotList.push_back(setSlot);
|
||||
this->current = slotList.begin();
|
||||
}
|
||||
|
||||
void PollingSequence::pollAndAdvance() {
|
||||
// (*this->current)->print();
|
||||
(*this->current)->handler->performInPST( (*this->current)->opcode );
|
||||
// if (returnValue != RETURN_OK) {
|
||||
// this->sendErrorMessage( returnValue );
|
||||
// }
|
||||
//Increment the polling Sequence iterator
|
||||
this->current++;
|
||||
//Set it to the beginning, if the list's end is reached.
|
||||
if (this->current == this->slotList.end()) {
|
||||
this->current = this->slotList.begin();
|
||||
}
|
||||
}
|
||||
|
||||
Interval_t PollingSequence::getInterval() {
|
||||
Interval_t oldTime;
|
||||
std::list<PollingSlot*>::iterator it;
|
||||
it = this->current;
|
||||
// Get the pollingTime of the current slot object.
|
||||
oldTime = (*it)->pollingTime;
|
||||
// Advance to the next object.
|
||||
it++;
|
||||
// Find the next interval which is not 0.
|
||||
while ( it != slotList.end() ) {
|
||||
if ( oldTime != (*it)->pollingTime ) {
|
||||
return (*it)->pollingTime - oldTime;
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
// If the list end is reached (this is definitely an interval != 0),
|
||||
// the interval is calculated by subtracting the remaining time of the PST
|
||||
// and adding the start time of the first handler in the list.
|
||||
it = slotList.begin();
|
||||
return this->length - oldTime + (*it)->pollingTime;
|
||||
}
|
||||
|
||||
bool PollingSequence::slotFollowsImmediately() {
|
||||
Interval_t currentTime = (*current)->pollingTime;
|
||||
std::list<PollingSlot*>::iterator it;
|
||||
it = this->current;
|
||||
// Get the pollingTime of the current slot object.
|
||||
if ( it == slotList.begin() ) return false;
|
||||
it--;
|
||||
if ( (*it)->pollingTime == currentTime ) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Interval_t PollingSequence::getLength() {
|
||||
return this->length;
|
||||
}
|
||||
|
||||
void PollingSequence::print() {
|
||||
debug << "Polling sequence contains:" << std::endl;
|
||||
|
||||
//Iterate through slotList and start all PollingSlot::print() methods.
|
||||
do {
|
||||
(*current)->print();
|
||||
current++;
|
||||
} while (current != slotList.end());
|
||||
current = slotList.begin();
|
||||
}
|
||||
|
||||
//std::string PollingSequence::getObjectTypeAsString() {
|
||||
// return "PollingSequence";
|
||||
//}
|
||||
|
||||
ReturnValue_t PollingSequence::initialize() {
|
||||
ReturnValue_t result = SystemObject::initialize();
|
||||
if (result != HasReturnvaluesIF::RETURN_OK){
|
||||
return result;
|
||||
}
|
||||
return initFunction(this);
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
/*
|
||||
* PollingSequenceExecutableIF.h
|
||||
*
|
||||
* Created on: Mar 30, 2012
|
||||
* Author: baetz
|
||||
*/
|
||||
|
||||
#ifndef POLLINGSEQUENCEEXECUTABLE_H_
|
||||
#define POLLINGSEQUENCEEXECUTABLE_H_
|
||||
|
||||
//TODO clean this whole file up
|
||||
|
||||
//TODO maybe define a type to make it look cleaner and use it in the PST
|
||||
#define SEND_WRITE_CMD 0
|
||||
#define GET_WRITE_REPLY 1
|
||||
#define SEND_READ_CMD 2
|
||||
#define GET_READ_REPLY 3
|
||||
|
||||
|
||||
#include <framework/osal/OSAL.h>
|
||||
|
||||
class PollingSequenceExecutableIF {
|
||||
public:
|
||||
static uint32_t pollingSequenceLengthMs;
|
||||
static uint32_t payloadSequenceLengthMs;
|
||||
virtual void performInPST( uint8_t ) = 0;
|
||||
virtual ~PollingSequenceExecutableIF() { }
|
||||
};
|
||||
|
||||
#endif /* POLLINGSEQUENCEEXECUTABLE_H_ */
|
@ -1,29 +0,0 @@
|
||||
/**
|
||||
* @file PollingSlot.cpp
|
||||
* @brief This file defines the PollingSlot class.
|
||||
* @date 19.12.2012
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#include <framework/devicehandlers/PollingSlot.h>
|
||||
#include <framework/objectmanager/SystemObjectIF.h>
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
|
||||
PollingSlot::PollingSlot( object_id_t handlerId, Interval_t setTime, int8_t setSequenceId ) {
|
||||
//Set all attributes directly on object creation.
|
||||
this->handler = objectManager->get<PollingSequenceExecutableIF>( handlerId );
|
||||
this->pollingTime = setTime;
|
||||
this->opcode = setSequenceId;
|
||||
}
|
||||
|
||||
PollingSlot::~PollingSlot() {
|
||||
}
|
||||
|
||||
void PollingSlot::print() const {
|
||||
SystemObjectIF * systemObject = dynamic_cast<SystemObjectIF *>(handler);
|
||||
object_id_t id = (systemObject == NULL) ? 0xffffffff : systemObject->getObjectId();
|
||||
debug << "HandlerID: " << std::hex << id << std::dec << "; Polling Time: "
|
||||
<< this->pollingTime << "; Opcode: " << (uint16_t) this->opcode
|
||||
<< std::endl;
|
||||
}
|
||||
|
@ -1,103 +0,0 @@
|
||||
/**
|
||||
* \file OPUSPollingTask.cpp
|
||||
*
|
||||
* \brief This file contains the implementation for the OPUSPollingTask class.
|
||||
*
|
||||
* \author Bastian Baetz
|
||||
*
|
||||
* \date 17.03.2011
|
||||
*
|
||||
*/
|
||||
|
||||
#include <framework/devicehandlers/PollingTask.h>
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
|
||||
uint32_t PollingTask::deadlineMissedCount = 0;
|
||||
|
||||
PollingTask::PollingTask( const char *name, TaskPriority_t setPriority, size_t setStack, void (*setDeadlineMissedFunc)(), object_id_t getPst ) :
|
||||
TaskBase( setPriority, setStack, name ), periodId(0) {
|
||||
// All additional attributes are applied to the object.
|
||||
this->deadlineMissedFunc = setDeadlineMissedFunc;
|
||||
this->pst = objectManager->get<PollingSequence>( getPst );
|
||||
}
|
||||
|
||||
PollingTask::~PollingTask() {
|
||||
// The PollingSequence destructor is called, if a sequence is announced.
|
||||
if ( this->pst != NULL ) {
|
||||
this->pst->~PollingSequence();
|
||||
} else {
|
||||
// There was no memory allocation, so there's nothing to do.
|
||||
}
|
||||
}
|
||||
|
||||
TaskReturn_t PollingTask::taskEntryPoint( TaskArgument_t argument ) {
|
||||
|
||||
//The argument is re-interpreted as PollingTask.
|
||||
PollingTask *originalTask( reinterpret_cast<PollingTask*>( argument ) );
|
||||
if ( originalTask->pst != NULL ) {
|
||||
//The task's functionality is called.
|
||||
originalTask->taskFunctionality();
|
||||
} else {
|
||||
|
||||
}
|
||||
debug << "Polling task " << originalTask->getId() << " returned from taskFunctionality." << std::endl;
|
||||
}
|
||||
|
||||
void PollingTask::missedDeadlineCounter() {
|
||||
PollingTask::deadlineMissedCount++;
|
||||
if (PollingTask::deadlineMissedCount%10 == 0) {
|
||||
error << "PST missed " << PollingTask::deadlineMissedCount << " deadlines." << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t PollingTask::startTask() {
|
||||
this->setRunning( true );
|
||||
ReturnValue_t status;
|
||||
status = OSAL::startTask( &( this->id ), PollingTask::taskEntryPoint, TaskArgument_t( ( void *)this ) );
|
||||
if( status != RETURN_OK ) {
|
||||
//TODO: Call any FDIR routine?
|
||||
error << "PollingTask::startTask for " << std::hex << this->getId() << std::dec << " failed." << std::endl;
|
||||
} else {
|
||||
// debug << "PollingTask::startTask for " << std::hex << this->getId() << std::dec << " successful" << std::endl;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
void PollingTask::taskFunctionality() {
|
||||
ReturnValue_t status = OSAL::TIMEOUT;
|
||||
Interval_t interval;
|
||||
// A local iterator for the Polling Sequence Table is created to find the start time for the first entry.
|
||||
std::list<PollingSlot*>::iterator it;
|
||||
|
||||
it = this->pst->current;
|
||||
//The start time for the first entry is read.
|
||||
interval = ( *it )->pollingTime;
|
||||
//The period is set up and started with the system call.
|
||||
status = OSAL::setAndStartPeriod( interval, &( this->periodId ) );
|
||||
if( status == RETURN_OK ) {
|
||||
//The task's "infinite" inner loop is entered.
|
||||
while( this->isRunning ) {
|
||||
if ( pst->slotFollowsImmediately() ) {
|
||||
//Do nothing
|
||||
} else {
|
||||
//The interval for the next polling slot is selected.
|
||||
interval = this->pst->getInterval();
|
||||
//The period is checked and restarted with the new interval.
|
||||
//If the deadline was missed, the deadlineMissedFunc is called.
|
||||
status = OSAL::checkAndRestartPeriod( this->periodId, interval );
|
||||
if( status == OSAL::TIMEOUT ) {
|
||||
if( this->deadlineMissedFunc != NULL ) {
|
||||
this->deadlineMissedFunc();
|
||||
}
|
||||
}
|
||||
}
|
||||
//The device handler for this slot is executed and the next one is chosen.
|
||||
this->pst->pollAndAdvance();
|
||||
}
|
||||
} else {
|
||||
error << "PollingTask::setAndStartPeriod failed with status "<< status << std::endl;
|
||||
}
|
||||
//Any operating system object for periodic execution is deleted.
|
||||
debug << "Deleting the PollingTask's period." << std::endl;
|
||||
OSAL::deletePeriod( &(this->id) );
|
||||
}
|
@ -1,13 +1,3 @@
|
||||
/*
|
||||
* Event.cpp
|
||||
*
|
||||
* Created on: 25.08.2015
|
||||
* Author: baetz
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
#include <framework/events/Event.h>
|
||||
namespace EVENT {
|
||||
EventId_t getEventId(Event event) {
|
||||
|
@ -1,14 +1,9 @@
|
||||
/*
|
||||
* Event.h
|
||||
*
|
||||
* Created on: 18.08.2015
|
||||
* Author: baetz
|
||||
*/
|
||||
|
||||
#ifndef EVENTOBJECT_EVENT_H_
|
||||
#define EVENTOBJECT_EVENT_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <framework/events/fwSubsystemIdRanges.h>
|
||||
//could be move to more suitable location
|
||||
#include <config/tmtc/subsystemIdRanges.h>
|
||||
|
||||
typedef uint16_t EventId_t;
|
||||
|
@ -1,40 +1,43 @@
|
||||
#include <config/objects/translateObjects.h>
|
||||
#include <config/events/translateEvents.h>
|
||||
|
||||
#include <framework/events/EventManager.h>
|
||||
#include <framework/events/EventMessage.h>
|
||||
#include <framework/serviceinterface/ServiceInterfaceStream.h>
|
||||
#include <framework/ipc/QueueFactory.h>
|
||||
#include <framework/ipc/MutexFactory.h>
|
||||
|
||||
|
||||
const uint16_t EventManager::POOL_SIZES[N_POOLS] = {
|
||||
sizeof(EventMatchTree::Node), sizeof(EventIdRangeMatcher),
|
||||
sizeof(ReporterRangeMatcher) };
|
||||
//TODO: Rather arbitrary. Adjust!
|
||||
//If one checks registerListener calls, there are around 40 (to max 50) objects registering for certain events.
|
||||
//Each listener requires 1 or 2 EventIdMatcher and 1 or 2 ReportRangeMatcher. So a good guess is 75 to a max of 100 pools required for each, which fits well.
|
||||
const uint16_t EventManager::N_ELEMENTS[N_POOLS] = { 240, 120, 120 };
|
||||
|
||||
EventManager::EventManager(object_id_t setObjectId) :
|
||||
SystemObject(setObjectId), eventReportQueue(MAX_EVENTS_PER_CYCLE,
|
||||
EventMessage::EVENT_MESSAGE_SIZE), mutex(NULL), factoryBackend(
|
||||
SystemObject(setObjectId), eventReportQueue(NULL), mutex(NULL), factoryBackend(
|
||||
0, POOL_SIZES, N_ELEMENTS, false, true) {
|
||||
mutex = new MutexId_t;
|
||||
OSAL::createMutex(setObjectId + 1, (mutex));
|
||||
mutex = MutexFactory::instance()->createMutex();
|
||||
eventReportQueue = QueueFactory::instance()->createMessageQueue(
|
||||
MAX_EVENTS_PER_CYCLE, EventMessage::EVENT_MESSAGE_SIZE);
|
||||
}
|
||||
|
||||
EventManager::~EventManager() {
|
||||
OSAL::deleteMutex(mutex);
|
||||
delete mutex;
|
||||
QueueFactory::instance()->deleteMessageQueue(eventReportQueue);
|
||||
MutexFactory::instance()->deleteMutex(mutex);
|
||||
}
|
||||
|
||||
MessageQueueId_t EventManager::getEventReportQueue() {
|
||||
return eventReportQueue.getId();
|
||||
return eventReportQueue->getId();
|
||||
}
|
||||
|
||||
ReturnValue_t EventManager::performOperation() {
|
||||
ReturnValue_t EventManager::performOperation(uint8_t opCode) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
while (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
EventMessage message;
|
||||
result = eventReportQueue.receiveMessage(&message);
|
||||
result = eventReportQueue->receiveMessage(&message);
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
#ifdef DEBUG
|
||||
printEvent(&message);
|
||||
#endif
|
||||
notifyListeners(&message);
|
||||
}
|
||||
}
|
||||
@ -45,7 +48,7 @@ void EventManager::notifyListeners(EventMessage* message) {
|
||||
lockMutex();
|
||||
for (auto iter = listenerList.begin(); iter != listenerList.end(); ++iter) {
|
||||
if (iter->second.match(message)) {
|
||||
eventForwardingSender.sendMessage(iter->first, message,
|
||||
MessageQueueSenderIF::sendMessage(iter->first, message,
|
||||
message->getSender());
|
||||
}
|
||||
}
|
||||
@ -103,21 +106,27 @@ ReturnValue_t EventManager::unsubscribeFromEventRange(MessageQueueId_t listener,
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
//forward declaration, should be implemented by mission
|
||||
const char* translateObject(object_id_t object);
|
||||
const char * translateEvents(Event event);
|
||||
|
||||
void EventManager::printEvent(EventMessage* message) {
|
||||
const char *string = 0;
|
||||
switch (message->getSeverity()) {
|
||||
case SEVERITY::INFO:
|
||||
string = translateObject(message->getReporter());
|
||||
info << "EVENT: ";
|
||||
if (string != 0) {
|
||||
info << string;
|
||||
} else {
|
||||
info << "0x" << std::hex << message->getReporter() << std::dec;
|
||||
}
|
||||
info << " reported " << translateEvents(message->getEvent()) << " ("
|
||||
<< std::dec << message->getEventId() << std::hex << ") P1: 0x"
|
||||
<< message->getParameter1() << " P2: 0x"
|
||||
<< message->getParameter2() << std::dec << std::endl;
|
||||
// string = translateObject(message->getReporter());
|
||||
// info << "EVENT: ";
|
||||
// if (string != 0) {
|
||||
// info << string;
|
||||
// } else {
|
||||
// info << "0x" << std::hex << message->getReporter() << std::dec;
|
||||
// }
|
||||
// info << " reported " << translateEvents(message->getEvent()) << " ("
|
||||
// << std::dec << message->getEventId() << std::hex << ") P1: 0x"
|
||||
// << message->getParameter1() << " P2: 0x"
|
||||
// << message->getParameter2() << std::dec << std::endl;
|
||||
break;
|
||||
default:
|
||||
string = translateObject(message->getReporter());
|
||||
@ -135,11 +144,12 @@ void EventManager::printEvent(EventMessage* message) {
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
void EventManager::lockMutex() {
|
||||
OSAL::lockMutex(this->mutex, OSAL::NO_TIMEOUT);
|
||||
mutex->lockMutex(MutexIF::NO_TIMEOUT);
|
||||
}
|
||||
|
||||
void EventManager::unlockMutex() {
|
||||
OSAL::unlockMutex(this->mutex);
|
||||
mutex->unlockMutex();
|
||||
}
|
||||
|
@ -4,16 +4,17 @@
|
||||
#include <framework/events/eventmatching/EventMatchTree.h>
|
||||
#include <framework/events/EventManagerIF.h>
|
||||
#include <framework/objectmanager/SystemObject.h>
|
||||
#include <framework/osal/OSAL.h>
|
||||
#include <framework/storagemanager/LocalPool.h>
|
||||
#include <framework/tasks/ExecutableObjectIF.h>
|
||||
#include <framework/ipc/MessageQueueIF.h>
|
||||
#include <framework/ipc/MutexIF.h>
|
||||
#include <map>
|
||||
|
||||
class EventManager: public EventManagerIF,
|
||||
public ExecutableObjectIF,
|
||||
public SystemObject {
|
||||
public:
|
||||
static const uint16_t MAX_EVENTS_PER_CYCLE = 150;
|
||||
static const uint16_t MAX_EVENTS_PER_CYCLE = 80;
|
||||
|
||||
EventManager(object_id_t setObjectId);
|
||||
virtual ~EventManager();
|
||||
@ -32,17 +33,15 @@ public:
|
||||
EventId_t idFrom = 0, EventId_t idTo = 0, bool idInverted = false,
|
||||
object_id_t reporterFrom = 0, object_id_t reporterTo = 0,
|
||||
bool reporterInverted = false);
|
||||
ReturnValue_t performOperation();
|
||||
ReturnValue_t performOperation(uint8_t opCode);
|
||||
|
||||
protected:
|
||||
|
||||
MessageQueue eventReportQueue;
|
||||
|
||||
MessageQueueSender eventForwardingSender;
|
||||
MessageQueueIF* eventReportQueue;
|
||||
|
||||
std::map<MessageQueueId_t, EventMatchTree> listenerList;
|
||||
|
||||
MutexId_t* mutex;
|
||||
MutexIF* mutex;
|
||||
|
||||
static const uint8_t N_POOLS = 3;
|
||||
LocalPool<N_POOLS> factoryBackend;
|
||||
@ -51,7 +50,9 @@ protected:
|
||||
|
||||
void notifyListeners(EventMessage *message);
|
||||
|
||||
#ifdef DEBUG
|
||||
void printEvent(EventMessage *message);
|
||||
#endif
|
||||
|
||||
void lockMutex();
|
||||
|
||||
|
@ -3,13 +3,13 @@
|
||||
|
||||
#include <framework/events/eventmatching/eventmatching.h>
|
||||
#include <framework/events/EventMessage.h>
|
||||
#include <framework/ipc/MessageQueue.h>
|
||||
#include <framework/objectmanager/ObjectManagerIF.h>
|
||||
#include <framework/ipc/MessageQueueSenderIF.h>
|
||||
|
||||
class EventManagerIF {
|
||||
public:
|
||||
|
||||
static const uint8_t INTERFACE_ID = EVENT_MANAGER_IF;
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::EVENT_MANAGER_IF;
|
||||
static const ReturnValue_t LISTENER_NOT_FOUND = MAKE_RETURN_CODE(1);
|
||||
virtual ~EventManagerIF() {
|
||||
}
|
||||
@ -44,8 +44,7 @@ public:
|
||||
eventmanagerQueue = eventmanager->getEventReportQueue();
|
||||
}
|
||||
}
|
||||
MessageQueueSender sender(eventmanagerQueue);
|
||||
sender.sendToDefault(message, sentFrom);
|
||||
MessageQueueSenderIF::sendMessage(eventmanagerQueue, message, sentFrom);
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -15,7 +15,7 @@ public:
|
||||
static const uint8_t CONFIRMATION_REQUEST = 1; //!< Request to parent if event is caused by child or not.
|
||||
static const uint8_t YOUR_FAULT = 2; //!< The fault was caused by child, parent believes it's ok.
|
||||
static const uint8_t MY_FAULT = 3; //!< The fault was caused by the parent, child is ok.
|
||||
//TODO: Add other messageIDs here if necessary.
|
||||
//Add other messageIDs here if necessary.
|
||||
static const uint8_t EVENT_MESSAGE_SIZE = HEADER_SIZE + sizeof(Event)
|
||||
+ 3 * sizeof(uint32_t);
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user