blob: 7896aa283beced6e418117597f136ed75eaf2929 [file] [log] [blame]
/**
* @author generated by eTrice
*
* Source File of ActorClass ATcpClient
*
*/
#include "ATcpClient.h"
#include "modelbase/etActor.h"
#include "debugging/etLogger.h"
#include "debugging/etMSCLogger.h"
#include "etUnit/etUnit.h"
#include "base/etMemory.h"
#include "room/basic/service/tcp/PTcpControl.h"
#include "room/basic/service/tcp/PTcpPayload.h"
#include "ATcpClient_Utils.h"
/*--------------------- begin user code ---------------------*/
static int8* bufferProvider(void* slf, int* size) {
ATcpClient* self = (ATcpClient*) slf;
*size = DTcpPayload_getMaxLength(&payloadRecvBuffer);
return payloadRecvBuffer.data;
}
static int socketReceiver(void* slf, int channel, int size, const int8* data) {
ATcpClient* self = (ATcpClient*) slf;
DTcpPayload_setData(&payloadRecvBuffer, /* cast away constness to avoid warning*/(int8*)data, size);
payloadPort_dataPackage(&payloadRecvBuffer);
return ETSOCKET_OK;
}
/*--------------------- end user code ---------------------*/
/* interface item IDs */
enum interface_items {
IFITEM_controlPort = 1,
IFITEM_payloadPort = 2
};
/* state IDs */
enum state_ids {
NO_STATE = 0,
STATE_TOP = 1,
STATE_unconnected = 2,
STATE_connected = 3,
STATE_initError = 4,
STATE_MAX = 5
};
/* transition chains */
enum ChainIDs {
CHAIN_TRANS_INITIAL_TO__cp1 = 1,
CHAIN_TRANS_tr0_FROM_unconnected_TO_cp0_BY_connectcontrolPort = 2,
CHAIN_TRANS_tr1_FROM_connected_TO_unconnected_BY_disconnectcontrolPort = 3,
CHAIN_TRANS_tr3_FROM_connected_TO_connected_BY_dataPackagepayloadPort_tr3 = 4,
CHAIN_TRANS_tr6_FROM_initError_TO_initError_BY_connectcontrolPort_tr6 = 5
};
/* triggers */
enum triggers {
POLLING = 0,
TRIG_controlPort__connect = IFITEM_controlPort + EVT_SHIFT*PTcpControl_IN_connect,
TRIG_controlPort__disconnect = IFITEM_controlPort + EVT_SHIFT*PTcpControl_IN_disconnect,
TRIG_payloadPort__dataPackage = IFITEM_payloadPort + EVT_SHIFT*PTcpPayload_IN_dataPackage
};
/* state names */
static char* stateStrings[] = {"<no state>","<top>","unconnected",
"connected",
"initError"
};
static void setState(ATcpClient* self, etInt16 new_state) {
self->state = new_state;
ET_MSC_LOGGER_CHANGE_STATE(self->constData->instName, stateStrings[new_state]);
}
static etInt16 getState(ATcpClient* self) {
return self->state;
}
/* Entry and Exit Codes */
static void entry_initError(ATcpClient* self) {
controlPort_error();
}
/* Action Codes */
static void action_TRANS_INITIAL_TO__cp1(ATcpClient* self) {
printf("Client Init!\n");
}
static void action_TRANS_tr0_FROM_unconnected_TO_cp0_BY_connectcontrolPort(ATcpClient* self, const InterfaceItemBase* ifitem, DTcpControl* transitionData) {
/* connect to server */
setErrorCode(etConnectServer(client, transitionData->IPAddr, transitionData->TcpPort));
}
static void action_TRANS_tr1_FROM_connected_TO_unconnected_BY_disconnectcontrolPort(ATcpClient* self, const InterfaceItemBase* ifitem) {
/* close read thread */
etCloseSocket(client);
controlPort_disconnected();
}
static void action_TRANS_tr2_FROM_cp0_TO_connected(ATcpClient* self, const InterfaceItemBase* ifitem, DTcpControl* transitionData) {
controlPort_connected();
}
static void action_TRANS_tr7_FROM_cp0_TO_unconnected_COND_tr7(ATcpClient* self, const InterfaceItemBase* ifitem, DTcpControl* transitionData) {
controlPort_error();
}
static void action_TRANS_tr3_FROM_connected_TO_connected_BY_dataPackagepayloadPort_tr3(ATcpClient* self, const InterfaceItemBase* ifitem, DTcpPayload* transitionData) {
setErrorCode(etWriteSocket(client, transitionData->length, transitionData->data));
if(hasError())
controlPort_error();
}
/* State Switch Methods */
/**
* calls exit codes while exiting from the current state to one of its
* parent states while remembering the history
* @param current__et - the current state
* @param to - the final parent state
*/
static void exitTo(ATcpClient* self, etInt16 current__et, etInt16 to) {
while (current__et!=to) {
switch (current__et) {
case STATE_connected:
self->history[STATE_TOP] = STATE_connected;
current__et = STATE_TOP;
break;
case STATE_initError:
self->history[STATE_TOP] = STATE_initError;
current__et = STATE_TOP;
break;
case STATE_unconnected:
self->history[STATE_TOP] = STATE_unconnected;
current__et = STATE_TOP;
break;
default:
/* should not occur */
break;
}
}
}
/**
* calls action, entry and exit codes along a transition chain. The generic data are cast to typed data
* matching the trigger of this chain. The ID of the final state is returned
* @param chain__et - the chain ID
* @param generic_data__et - the generic data pointer
* @return the +/- ID of the final state either with a positive sign, that indicates to execute the state's entry code, or a negative sign vice versa
*/
static etInt16 executeTransitionChain(ATcpClient* self, int chain__et, const InterfaceItemBase* ifitem, void* generic_data__et) {
switch (chain__et) {
case CHAIN_TRANS_INITIAL_TO__cp1:
{
action_TRANS_INITIAL_TO__cp1(self);
if (hasError()) {
return STATE_initError;}
else {
return STATE_unconnected;}
}
case CHAIN_TRANS_tr0_FROM_unconnected_TO_cp0_BY_connectcontrolPort:
{
DTcpControl* transitionData = ((DTcpControl*) generic_data__et);
action_TRANS_tr0_FROM_unconnected_TO_cp0_BY_connectcontrolPort(self, ifitem, transitionData);
if (hasError()) {
action_TRANS_tr7_FROM_cp0_TO_unconnected_COND_tr7(self, ifitem, transitionData);
return STATE_unconnected;}
else {
action_TRANS_tr2_FROM_cp0_TO_connected(self, ifitem, transitionData);
return STATE_connected;}
}
case CHAIN_TRANS_tr1_FROM_connected_TO_unconnected_BY_disconnectcontrolPort:
{
action_TRANS_tr1_FROM_connected_TO_unconnected_BY_disconnectcontrolPort(self, ifitem);
return STATE_unconnected;
}
case CHAIN_TRANS_tr3_FROM_connected_TO_connected_BY_dataPackagepayloadPort_tr3:
{
DTcpPayload* transitionData = ((DTcpPayload*) generic_data__et);
action_TRANS_tr3_FROM_connected_TO_connected_BY_dataPackagepayloadPort_tr3(self, ifitem, transitionData);
return STATE_connected;
}
case CHAIN_TRANS_tr6_FROM_initError_TO_initError_BY_connectcontrolPort_tr6:
{
DTcpControl* transitionData = ((DTcpControl*) generic_data__et);
return STATE_initError;
}
default:
/* should not occur */
break;
}
return NO_STATE;
}
/**
* calls entry codes while entering a state's history. The ID of the final leaf state is returned
* @param state__et - the state which is entered
* @return - the ID of the final leaf state
*/
static etInt16 enterHistory(ATcpClient* self, etInt16 state__et) {
etBool skip_entry__et = ET_FALSE;
if (state__et >= STATE_MAX) {
state__et = (etInt16) (state__et - STATE_MAX);
skip_entry__et = ET_TRUE;
}
while (ET_TRUE) {
switch (state__et) {
case STATE_connected:
/* in leaf state: return state id */
return STATE_connected;
case STATE_initError:
if (!(skip_entry__et)) entry_initError(self);
/* in leaf state: return state id */
return STATE_initError;
case STATE_unconnected:
/* in leaf state: return state id */
return STATE_unconnected;
case STATE_TOP:
state__et = self->history[STATE_TOP];
break;
default:
/* should not occur */
break;
}
skip_entry__et = ET_FALSE;
}
/* return NO_STATE; // required by CDT but detected as unreachable by JDT because of while (true) */
}
static void ATcpClient_executeInitTransition(ATcpClient* self) {
int chain__et = CHAIN_TRANS_INITIAL_TO__cp1;
etInt16 next__et = executeTransitionChain(self, chain__et, NULL, NULL);
next__et = enterHistory(self, next__et);
setState(self, next__et);
}
/* receiveEvent contains the main implementation of the FSM */
static void ATcpClient_receiveEventInternal(ATcpClient* self, InterfaceItemBase* ifitem, int localId, int evt, void* generic_data__et) {
int trigger__et = localId + EVT_SHIFT*evt;
int chain__et = NOT_CAUGHT;
etInt16 catching_state__et = NO_STATE;
((void)trigger__et); /* avoids unused warning */
if (!handleSystemEvent(ifitem, evt, generic_data__et)) {
switch (getState(self)) {
case STATE_connected:
switch(trigger__et) {
case TRIG_controlPort__disconnect:
{
chain__et = CHAIN_TRANS_tr1_FROM_connected_TO_unconnected_BY_disconnectcontrolPort;
catching_state__et = STATE_TOP;
}
break;
case TRIG_payloadPort__dataPackage:
{
chain__et = CHAIN_TRANS_tr3_FROM_connected_TO_connected_BY_dataPackagepayloadPort_tr3;
catching_state__et = STATE_TOP;
}
break;
default:
/* should not occur */
break;
}
break;
case STATE_initError:
switch(trigger__et) {
case TRIG_controlPort__connect:
{
chain__et = CHAIN_TRANS_tr6_FROM_initError_TO_initError_BY_connectcontrolPort_tr6;
catching_state__et = STATE_TOP;
}
break;
default:
/* should not occur */
break;
}
break;
case STATE_unconnected:
switch(trigger__et) {
case TRIG_controlPort__connect:
{
chain__et = CHAIN_TRANS_tr0_FROM_unconnected_TO_cp0_BY_connectcontrolPort;
catching_state__et = STATE_TOP;
}
break;
default:
/* should not occur */
break;
}
break;
default:
/* should not occur */
break;
}
}
if (chain__et != NOT_CAUGHT) {
exitTo(self, getState(self), catching_state__et);
{
etInt16 next__et = executeTransitionChain(self, chain__et, ifitem, generic_data__et);
next__et = enterHistory(self, next__et);
setState(self, next__et);
}
}
}
static void ATcpClient_receiveEvent(ATcpClient* self, InterfaceItemBase* ifitem, int evt, void* generic_data__et) {
int localId = (ifitem==NULL)? 0 : ifitem->localId;
ATcpClient_receiveEventInternal(self, ifitem, localId, evt, generic_data__et);
}
void ATcpClient_init(ATcpClient* self){
ET_MSC_LOGGER_SYNC_ENTRY("ATcpClient", "init")
self->state = STATE_TOP;
{
int i;
for (i=0; i<ATCPCLIENT_HISTORY_SIZE; ++i)
self->history[i] = NO_STATE;
}
ATcpClient_executeInitTransition(self);
ET_MSC_LOGGER_SYNC_EXIT
}
void ATcpClient_receiveMessage(void* self, const void* ifitem, const etMessage* msg){
ET_MSC_LOGGER_SYNC_ENTRY("ATcpClient", "_receiveMessage")
ATcpClient_receiveEvent(self, (etPort*)ifitem, msg->evtID, (void*)(((char*)msg)+MEM_CEIL(sizeof(etMessage))));
ET_MSC_LOGGER_SYNC_EXIT
}
/*--------------------- user constructor/destructor ---------------------*/
void ATcpClient_ctor(ATcpClient* self){
/* user defined constructor body */
setErrorCode(etInitSockets());
client = etCreateSocketConnectionData();
client->receiver = socketReceiver;
client->bufferProvider = bufferProvider;
client->userData = self;
}
void ATcpClient_dtor(ATcpClient* self){
/* user defined destructor body */
etCloseSocket(client);
etCleanupSockets();
etFreeSocketConnectionData(client);
}
/*--------------------- operations ---------------------*/
bool ATcpClient_hasError(ATcpClient* self) {
return lastError != ETSOCKET_OK;
}
void ATcpClient_setErrorCode(ATcpClient* self, int32 value) {
lastError = value;
}