// $Id: JGControlManager.cpp,v 1.9 2003/03/16 14:51:00 fukasawa Exp $

//=============================================================================
/**
 *  @file    JGControlManager.cpp
 *
 *  @author  Fukasawa Mitsuo
 *
 *
 *    Copyright (C) 2001-2003 BEE Co.,Ltd. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
//=============================================================================

#define BEE_BUILD_DLL

#include "JGControlManager.h"
#include "JGEquipment.h"
#include "JGInfoManager.h"
#include "JGEventManager.h"
#include "JGCommManager.h"
#include "JGTaskTrigger.h"
#include "BS2ACKMessage.h"
#include "BS2ErrorMessage.h"
#include "BS2ListItem.h"
#include "BS2DeclAtoms.h"
#include "BS2Driver.h"

/*
 * Control Manager Class
 */
MANAGER_STATE(JGControlState, JGControlManager, CATEGORY_CONTROL);
    CONDITION_STATE(CondControl);
    CONDITION_STATE(CondOffline);
    CONDITION_STATE(CondOnline);
    EDGE_STATE(EquipmentOffline);
    EDGE_STATE(AttemptOnline);
    EDGE_STATE(HostOffline);
    EDGE_STATE(ControlLocal);
    EDGE_STATE(ControlRemote);

    // Define transit and state functions
    const BCHAR * toOnlineLocal(JGTrigger * trigger);
    const BCHAR * toOnlineRemote(JGTrigger * trigger);
    const BCHAR * toStop(JGTrigger * trigger);

    // Utility
    int   updateState(int state, int selector);

END_ROOT_STATE();

//------------------------------------------------------------------------------
// State
//------------------------------------------------------------------------------
// Status names
#define STATE_CONTROL            _TX("/CONTROL")
#define STATE_OFFLINE            _TX("/CONTROL/OFFLINE")
#define STATE_ONLINE             _TX("/CONTROL/ONLINE")
#define STATE_EQUIPMENT_OFFLINE  _TX("/CONTROL/OFFLINE/EQUIPMENT_OFFLINE")
#define STATE_ATTEMPT_ONLINE     _TX("/CONTROL/OFFLINE/ATTEMPT_ONLINE")
#define STATE_HOST_OFFLINE       _TX("/CONTROL/OFFLINE/HOST_OFFLINE")
#define STATE_ONLINE_LOCAL       _TX("/CONTROL/ONLINE/LOCAL")
#define STATE_ONLINE_REMOTE      _TX("/CONTROL/ONLINE/REMOTE")

// Instance base state
static JGControlState::CondControl      _st_control(STATE_CONTROL);
static JGControlState::CondOffline      _st_offline(STATE_OFFLINE);
static JGControlState::CondOnline       _st_online(STATE_ONLINE);
static JGControlState::EquipmentOffline _st_equip_offline(STATE_EQUIPMENT_OFFLINE);
static JGControlState::AttemptOnline    _st_attempt_online(STATE_ATTEMPT_ONLINE);
static JGControlState::HostOffline      _st_host_offline(STATE_HOST_OFFLINE);
static JGControlState::ControlLocal     _st_online_local(STATE_ONLINE_LOCAL);
static JGControlState::ControlRemote    _st_online_remote(STATE_ONLINE_REMOTE);

//------------------------------------------------------------------------------
//
//  Declare Transition Data of JGControlManager
//
//------------------------------------------------------------------------------
DEF_ACTION(JGControlState, toOnlineLocal);
DEF_ACTION(JGControlState, toOnlineRemote);
DEF_ACTION(JGControlState, toStop);

//------------------------------------------------------------------------------
BEGIN_STATIC_STATE_TABLE(JGControlState);
    NEXT_TRANSITION(&JGStateTask::Root, TRIGGER_START, STATE_CONTROL, _TX("NULL"));
    NODE_TRANSITION(&_st_control, _TX("to CONTROL"));
    NODE_TRANSITION(&_st_offline, _TX("to OFFLINE"));
    NODE_TRANSITION(&_st_online,  _TX("to ONLINE"));
    ACT_TRANSITION(&_st_equip_offline,
                   TRIGGER_ONLINE_LOCAL,
                   toOnlineLocal,
                   _TX("Equipment OFF-LINE to ON-LINE(LOCAL)") );
    ACT_TRANSITION(&_st_equip_offline,
                   TRIGGER_ONLINE_REMOTE,
                   toOnlineRemote,
                   _TX("Equipment OFF-LINE to ON-LINE(REMOTE)"));
    NEXT_TRANSITION(&_st_attempt_online,
                    TRIGGER_TIMEOUT,
                    STATE_EQUIPMENT_OFFLINE,
                    _TX("Attempt ON-LINE to OFF-LINE"));
    NEXT_TRANSITION(&_st_attempt_online,
                    TRIGGER_S1F0,
                    STATE_EQUIPMENT_OFFLINE,
                    _TX("Attempt ON-LINE to OFF-LINE"));
    NEXT_TRANSITION(&_st_attempt_online,
                    TRIGGER_S1F2,
                    STATE_ONLINE,
                    _TX("Attempt ON-LINE to ON-LINE"));
    NEXT_TRANSITION(&_st_online,
                    TRIGGER_OFFLINE,
                    STATE_EQUIPMENT_OFFLINE,
                    _TX("ON-LINE to OFF-LINE"));
    NEXT_TRANSITION(&_st_online_local,
                    TRIGGER_ONLINE_REMOTE,
                    STATE_ONLINE_REMOTE,
                    _TX("LOCAL to REMOTE"));
    NEXT_TRANSITION(&_st_online_remote,
                    TRIGGER_ONLINE_LOCAL,
                    STATE_ONLINE_LOCAL,
                    _TX("REMOTE to LOCAL"));
    NEXT_TRANSITION(&_st_online,
                    TRIGGER_S1F15,
                    STATE_HOST_OFFLINE,
                    _TX("ONLINE to Host OFF-LINE"));
    NEXT_TRANSITION(&_st_host_offline,
                    TRIGGER_S1F17,
                    STATE_ONLINE,
                    _TX("HOST-OFFLINE to ON-LINE"));
    NEXT_TRANSITION(&_st_host_offline,
                    TRIGGER_OFFLINE,
                    STATE_EQUIPMENT_OFFLINE,
                    _TX("Host OFF-LINE to OFF-LINE"));
    ACT_TRANSITION(&_st_control,
                   TRIGGER_FINISH,
                   toStop,
                   _TX("to Root Node"));
END_STATE_TABLE();


//-----------------------------------------------------------------------------
// Action: Equipment OFF-LINE
//-----------------------------------------------------------------------------
int JGControlState::actEquipmentOffline(JGState * prev, JGTrigger * trigger)
{
    TRACE_FUNCTION(TRL_LOW, "JGControlState::actEquipmentOffline");
    ACE_UNUSED_ARG(prev);
    ACE_UNUSED_ARG(trigger);

    m_manager->updOffline(CONTROL_EQUIPMENT_OFFLINE, NULL);

    if (prev->name() == STATE_ONLINE_LOCAL ||
        prev->name() == STATE_ONLINE_REMOTE ||
        prev->name() == STATE_HOST_OFFLINE)
    {
        m_manager->sendS6F11(EVT_OFFLINE);
    }
    return BEE_SUCCESS;
}

//-----------------------------------------------------------------------------
// Action: Host OFF-LINE
//-----------------------------------------------------------------------------
int JGControlState::actHostOffline(JGState * prev, JGTrigger * trigger)
{
    TRACE_FUNCTION(TRL_LOW, "JGControlState::actHostOffline");
    ACE_UNUSED_ARG(prev);
    ACE_UNUSED_ARG(trigger);

    BS2Message * msg = NULL;
    if (trigger->name() == TRIGGER_S1F15)
    {
        msg = ((JGMessageTrigger *)trigger)->message();
    }

    m_manager->updOffline(CONTROL_HOST_OFFLINE, msg);

    if (prev->name() == STATE_ONLINE_LOCAL ||
        prev->name() == STATE_ONLINE_REMOTE)
    {
        m_manager->sendS6F11(EVT_OFFLINE);
    }
    return BEE_SUCCESS;
}

//-----------------------------------------------------------------------------
// Action: Attempt ON-LINE
//-----------------------------------------------------------------------------
int JGControlState::actAttemptOnline(JGState * prev, JGTrigger * trigger)
{
    TRACE_FUNCTION(TRL_LOW, "JGControlState::actAttemptOnline");
    ACE_UNUSED_ARG(prev);
    ACE_UNUSED_ARG(trigger);

    m_manager->sendS1F1();
    m_manager->updOffline(CONTROL_ATTEMPT_ONLINE, NULL);
    return BEE_SUCCESS;
}

//-----------------------------------------------------------------------------
// Action: LOCAL
//-----------------------------------------------------------------------------
int JGControlState::actControlLocal(JGState * prev, JGTrigger * trigger)
{
    TRACE_FUNCTION(TRL_LOW, "JGControlState::actControlLocal");
    ACE_UNUSED_ARG(prev);
    ACE_UNUSED_ARG(trigger);

    BS2Message * msg = NULL;
    if (trigger->name() == TRIGGER_S1F17)
    {
        msg = ((JGMessageTrigger *)trigger)->message();
    }
    m_manager->updOnline(CONTROL_ONLINE_LOCAL, msg);

    m_manager->sendS6F11(EVT_LOCAL);
    return BEE_SUCCESS;
}

//-----------------------------------------------------------------------------
// Action: REMOTE
//-----------------------------------------------------------------------------
int JGControlState::actControlRemote(JGState * prev, JGTrigger * trigger)
{
    TRACE_FUNCTION(TRL_LOW, "JGControlState::actControlRemote");
    ACE_UNUSED_ARG(prev);
    ACE_UNUSED_ARG(trigger);

    BS2Message * msg = NULL;
    if (trigger->name() == TRIGGER_S1F17)
    {
        msg = ((JGMessageTrigger *)trigger)->message();
    }
    m_manager->updOnline(CONTROL_ONLINE_REMOTE, msg);

    m_manager->sendS6F11(EVT_REMOTE);
    return BEE_SUCCESS;
}

//------------------------------------------------------------------------------
// Condition node actions
//------------------------------------------------------------------------------
const BCHAR * JGControlState::actCondControl(JGTrigger * trigger)
{
    TRACE_FUNCTION(TRL_LOW, "JGControlState::actCondControl");
    ACE_UNUSED_ARG(trigger);

    BCHAR * nextName;
    JGvalue defaultState(m_manager->m_systemDefault->getv());
    int defcode = defaultState.getInt();
    if (defcode == CONTROL_ONLINE_LOCAL || defcode == CONTROL_ONLINE_REMOTE)
    {
        nextName = STATE_ATTEMPT_ONLINE;
    }
    else if (defcode == CONTROL_HOST_OFFLINE)
    {
        nextName = STATE_HOST_OFFLINE;
    }
    else /* if (default == CONTROL_EQUIPMENT_OFFLINE) */
    {
        nextName = STATE_EQUIPMENT_OFFLINE;
    }
    return nextName;
}

//------------------------------------------------------------------------------
const BCHAR * JGControlState::actCondOffline(JGTrigger * trigger)
{
    TRACE_FUNCTION(TRL_LOW, "JGControlState::actCondOffline");
    ACE_UNUSED_ARG(trigger);

    BCHAR * nextName;
    JGvalue defaultState(m_manager->m_offline->getv());
    int defcode = defaultState.getInt();
    if (defcode == CONTROL_EQUIPMENT_OFFLINE)
    {
        nextName = STATE_EQUIPMENT_OFFLINE;
    }
    else if (defcode == CONTROL_ATTEMPT_ONLINE)
    {
        nextName = STATE_ATTEMPT_ONLINE;
    }
    else /* if (defcode == CONTROL_HOST_OFFLINE) */
    {
        nextName = STATE_HOST_OFFLINE;
    }
    return nextName;
}

//------------------------------------------------------------------------------
const BCHAR * JGControlState::actCondOnline(JGTrigger * trigger)
{
    TRACE_FUNCTION(TRL_LOW, "JGControlState::actCondOnline");
    ACE_UNUSED_ARG(trigger);

    BCHAR * nextName;
    JGvalue defaultState(m_manager->m_online->getv());
    int defcode = defaultState.getInt();
    if (defcode == CONTROL_ONLINE_REMOTE)
    {
        nextName = STATE_ONLINE_REMOTE;
    }
    else /* if (defcode == CONTROL_ONLINE_LOCAL) */
    {
        nextName = STATE_ONLINE_LOCAL;
    }
    return nextName;
}

//-----------------------------------------------------------------------------
// ACTION : offline to online
//-----------------------------------------------------------------------------
const BCHAR * JGControlState::toOnlineLocal(JGTrigger * trigger)
{
    TRACE_FUNCTION(TRL_LOW, "JGControlState::toOnlineLocal");
    ACE_UNUSED_ARG(trigger);

    const BCHAR * nextState = STATE_ATTEMPT_ONLINE;
    this->updateState(CONTROL_ONLINE_LOCAL, CONTROL_ONLINE_LOCAL);
    return nextState;
}

//------------------------------------------------------------------------------
const BCHAR * JGControlState::toOnlineRemote(JGTrigger * trigger)
{
    TRACE_FUNCTION(TRL_LOW, "JGControlState::toOnlineRemote");
    ACE_UNUSED_ARG(trigger);

    const BCHAR * nextState = STATE_ATTEMPT_ONLINE;
    this->updateState(CONTROL_ONLINE_REMOTE, CONTROL_ONLINE_REMOTE);
    return nextState;
}

//------------------------------------------------------------------------------
const BCHAR * JGControlState::toStop(JGTrigger * trigger)
{
    TRACE_FUNCTION(TRL_HIGH, "JGControlState::toStop");
    ACE_UNUSED_ARG(trigger);

    const BCHAR * nextState = STATE_ROOT;
    this->updateState(0, 0);
    return nextState;
}

//-----------------------------------------------------------------------------
// Update current state.
//-----------------------------------------------------------------------------
int JGControlState::updateState(int state, int selector)
{
    TRACE_FUNCTION(TRL_LOW, "JGControlState::updateState");
    m_manager->m_controlState->setInt(state);
    m_manager->m_controlSelector->setInt(selector);
    return BEE_SUCCESS;
}

//-----------------------------------------------------------------------------
// Unexpected event
//-----------------------------------------------------------------------------
int JGControlState::unexpect(b_trigger * trigger)
{
    TRACE_FUNCTION(TRL_MIDDLE, "JGControlState::unexpect");
    ACE_UNUSED_ARG(trigger);

    BS2Message * replymsg = NULL;
    const BS2Message * msg = ((JGMessageTrigger *)trigger)->message();
    if (trigger->name() == TRIGGER_S1F15)
    {
        replymsg = m_manager->makeS1F16(msg, BEE_ERROR);
    }
    else if (trigger->name() == TRIGGER_S1F17)
    {
        if (m_manager->isOnline())
        {
            replymsg = m_manager->makeS1F18(msg, 1);  // Already online
        }
        else
        {
            replymsg = m_manager->makeS1F18(msg, BEE_ERROR);
        }
    }
    else
    {
        this->b_context::unexpect(trigger);
    }
    if (replymsg != NULL)
    {   // Send Not Acknowledge Message
        m_manager->send(replymsg);
    }
    return BEE_ERROR;
}

///////////////////////////////////////////////////////////////////////////////
//
// C O N T R O L
//
//
//-----------------------------------------------------------------------------
// Return own.
//-----------------------------------------------------------------------------
static JGControlManager * _manager = NULL;

JGControlManager * JGControlManager::instance()
{
    TRACE_FUNCTION(TRL_LOW, "JGControlManager::instance");
    if (_manager == NULL)
    {
        _manager = new JGControlManager;
    }
    return _manager;
}

//-----------------------------------------------------------------------------
// Constructor/Destoructor
//-----------------------------------------------------------------------------
JGControlManager::JGControlManager() : JGManager(CATEGORY_CONTROL)
{
    TRACE_FUNCTION(TRL_LOW, "JGControlManager::JGControlManager");
}


//-----------------------------------------------------------------------------
// Initialize
//-----------------------------------------------------------------------------
int JGControlManager::init(void * parm)
{
    TRACE_FUNCTION(TRL_LOW, "JGControlManager::init");
    ACE_UNUSED_ARG(parm);

    // Get Variables of Communications
    m_controlState = m_equipment->variable(VAR_CONTROL_STATE);
    m_controlSelector = m_equipment->variable(VAR_CONTROL_SELECTOR);
    m_systemDefault = m_equipment->variable(VAR_CONTROL_SYSTEM_DEFAULT);
    m_online = m_equipment->variable(VAR_ONLINE_SYSTEM_DEFAULT);
    m_offline = m_equipment->variable(VAR_OFFLINE_SYSTEM_DEFAULT);

    // Initial State Model
    m_stateModel = _JGControlState::instance();
    m_stateModel->manager(this);
    m_stateModel->equipment(m_equipment);
    m_stateModel->init();         // initialized transitions
    // m_stateModel->open();      // start thread

    return BEE_SUCCESS;
}

//-----------------------------------------------------------------------------
// Get current control status.
//-----------------------------------------------------------------------------
int JGControlManager::state()
{
    TRACE_FUNCTION(TRL_LOW, "JGControlManager::state");

    return m_controlState->getv().getInt();
}

//-----------------------------------------------------------------------------
// Change Control Status (for Operator)
//-----------------------------------------------------------------------------
int JGControlManager::change(int newState)
{
    TRACE_FUNCTION(TRL_LOW, "JGControlManager::change");

    BS2Assert(newState >= CONTROL_EQUIPMENT_OFFLINE &&
              newState <= CONTROL_ONLINE_REMOTE);
    JGvalue cur_val(m_controlState->getv());  // control status (current)
    int current = cur_val.getInt();
    if (current == newState)
    {   // As same status, ignore.
        return current;
    }

    JGTrigger * trigger = NULL;
    switch (newState)
    {
    case CONTROL_EQUIPMENT_OFFLINE:
        trigger = new JGNotifyTrigger(TRIGGER_OFFLINE);
        break;
    case CONTROL_ONLINE_LOCAL:
        if (current == CONTROL_ONLINE_REMOTE)
        {
            trigger = new JGNotifyTrigger(TRIGGER_ONLINE_LOCAL);
        }
        else /* current == OFFLINE */
        {
            trigger = new JGNotifyTrigger(TRIGGER_ONLINE_LOCAL);
        }
        break;
    case CONTROL_ONLINE_REMOTE:
        if (current == CONTROL_ONLINE_LOCAL)
        {
            trigger = new JGNotifyTrigger(TRIGGER_ONLINE_REMOTE);
        }
        else /* current == OFFLINE */
        {
            trigger = new JGNotifyTrigger(TRIGGER_ONLINE_REMOTE);
        }
        break;
#if 0
    case CONTROL_ONLINE:   // undefine !
        if (current == CONTROL_ONLINE_LOCAL)
        {
            int online = m_online->get().getInt();  // control status (default)
            if (online == CONTROL_ONLINE_REMOTE)
            {
                trigger = new JGNotifyTrigger(TRIGGER_ONLINE_REMOTE);
            }
            else
            {
                trigger = new JGNotifyTrigger(TRIGGER_ONLINE_LOCAL);
            }
        }
        break;
#endif
    case CONTROL_HOST_OFFLINE:
    case CONTROL_ATTEMPT_ONLINE:
    default:
        break;
    }

    if (trigger != NULL)
    {   // send the trigger for svc thread
        this->JGManager::notify(trigger);
    }

    return current;
}

//-----------------------------------------------------------------------------
// Accept trigger from the variable.
//-----------------------------------------------------------------------------
int JGControlManager::notify(const string& category, JGVariable * var,
                             void * arg)
{
    TRACE_FUNCTION(TRL_LOW, "JGControlManager::notify");

    TRACE_ERROR((_TX("%s : %s = %s\n"), category.c_str(), var->charName(),
                                        var->getv().toString().c_str()));

    JGDeviceRequest * devReq = new JGDeviceRequest(category, var, arg, this);
    this->put(devReq);
    return BEE_SUCCESS;
}

//-----------------------------------------------------------------------------
// Send S1F1
//-----------------------------------------------------------------------------
int JGControlManager::sendS1F1()
{
    TRACE_FUNCTION(TRL_LOW, "JGControlManager::sendS1F1");
    BS2Message * msg = BS2Message::factory(SFCODE(1,1));
    this->send(msg);
    return BEE_SUCCESS;
}

//-----------------------------------------------------------------------------
// ACTION : Send S6F11
//-----------------------------------------------------------------------------
int JGControlManager::sendS6F11(const BCHAR * event)
{
    TRACE_FUNCTION(TRL_LOW, "JGControlManager::sendS6F11");
    m_equipment->sendEvent(this, event);
    return BEE_SUCCESS;
}

//-----------------------------------------------------------------------------
// ACTION : Update current & offline default status
//-----------------------------------------------------------------------------
int JGControlManager::updOffline(int state, BS2Message * msg)
{
    TRACE_FUNCTION(TRL_LOW, "JGControlManager::updOffline");
    m_controlState->setInt(state);
    m_controlSelector->setInt(state);
    // m_offline->setInt(state);  //@ Not set to system default.
    if (msg != NULL)
    {
        BS2Message * replymsg = makeS1F16(msg, BEE_SUCCESS);
        this->send(replymsg);
    }
    return BEE_SUCCESS;
}

//------------------------------------------------------------------------------
int JGControlManager::updOnline(int state, BS2Message * msg)
{
    TRACE_FUNCTION(TRL_LOW, "JGControlManager::updOnline");
    m_controlState->setInt(state);
    m_controlSelector->setInt(state);
    // m_online->setInt(state);    //@ Not set to system default.
    if (msg != NULL)
    {
        BS2Message * replymsg = makeS1F18(msg, BEE_SUCCESS);
        this->send(replymsg);
    }
    return BEE_SUCCESS;
}

//-----------------------------------------------------------------------------
// Reply : S1F2
//-----------------------------------------------------------------------------
BS2Message * JGControlManager::makeS1F2(const BS2Message * msg)
{
    TRACE_FUNCTION(TRL_LOW, "JGControlManager::makeS1F2");

    BS2Assert(msg->sf() == SFCODE(1,1));
    BS2Message * replymsg = BS2Message::response(msg);
    BS2ListItem * listitem = new BS2ListItem;
    JGvalue mdln(m_equipment->value(VAR_EQUOP_MODEL));
    BS2Item * item = BS2Item::factory(_TX("MDLN"), mdln);
    listitem->add(item);

    JGvalue softrev(m_equipment->value(VAR_EQUIP_SOFTREV));
    item = BS2Item::factory(_TX("SOFTREV"), softrev);
    listitem->add(item);
    replymsg->add(listitem);

    return replymsg;
}

//-----------------------------------------------------------------------------
// Reply : S1F16
//-----------------------------------------------------------------------------
BS2Message * JGControlManager::makeS1F16(const BS2Message * msg, int result)
{
    TRACE_FUNCTION(TRL_LOW, "JGControlManager::makeS1F16");

    BYTE ack = (result == BEE_SUCCESS) ? ACK_OK : ACK_NG;
    BS2Message * replymsg = BS2Message::response(msg, ack, _TX("OFLACK"));

    return replymsg;
}

//-----------------------------------------------------------------------------
// Reply : S1F18
//-----------------------------------------------------------------------------
BS2Message * JGControlManager::makeS1F18(const BS2Message * msg, int result)
{
    TRACE_FUNCTION(TRL_LOW, "JGControlManager::makeS1F18");

    BYTE ack = ACK_OK;    // result == 0(BEE_SUCCESS)
    if (result < 0)
    {
        ack = ACK_NG;
    }
    else if (result > 0)
    {
        ack = 2;          // Equipment Already ON-LINE
    }
    BS2Message * replymsg = BS2Message::response(msg, ack, _TX("ONLACK"));
    return replymsg;
}

//-----------------------------------------------------------------------------
//
// Service of received message.
//
//-----------------------------------------------------------------------------
BS2Message * JGControlManager::msg_svc(JGMessageTrigger * trigger,
                                       BS2Message * msg)
{
    ACE_UNUSED_ARG(trigger);

    BS2Message * replymsg = NULL;
    int result;

    if (msg->sf() == SFCODE(1,1))
    {
        if (m_equipment->isCommunicating() && this->isOnline())
        {
            replymsg = makeS1F2(msg);
        }
        else
        {
            replymsg = new BS2S1F0Message();
        }
    }
    else if (msg->sf() == SFCODE(1,0) || msg->sf() == SFCODE(1,2) ||
             msg->sf() == SFCODE(1,15) || msg->sf() == SFCODE(1,17))
    {
        result = m_stateModel->accept(trigger);   // message dispatch

    }
    else
    {   // Unexpected message
        replymsg = this->unrecognized(msg);
    }

    return replymsg;
}

