锂电池通信(docs/锂电池协议20230324.docx): - 协议层 BatProtocol:自检0x0000(2B)/设备控制0x0001(17B)/电池组状态0x0003(80B)/ 电池包报警0x0004(68B),uint32字节和校验、小端 - 链路层 BatLinkManager:动力/仪表锂电池独立UDP链路,本机监听与远端IP端口 均由.moos配置(dyn_bat_*/ins_bat_*/bat_work_condition) - SystemData/SnapshotBuilder/网页:电池数据按动力/仪表归类展示(运行状态/接触器 电气量/电池包电压温度/报警),收发帧落库SQLite,网页新增电池标签页 操作->指令下发(PowerCoordinator): - 操作接口:自检/上下电(母线接触器55H接通77H断开,含预充)/功率设定(0~500kW)/ 电池切换(低压->高压6步、高压->低压5步,按协议时序) - 步骤引擎:每电池独立步骤队列,下发->状态反馈确认->超时兜底;周期1s心跳控制帧 - PM操控指令insBatCmd/dynBatCmd/dynBatPower自动映射为电池操作 电源协调状态机骨架(CoordFsm, TinyFSM): - 事件Tick/PmControl/StepDone + 状态Normal/Switching/Fault,react均为TODO占位 - 当前未接线(无start/dispatch调用,运行行为与接入前一致),CoordFsm.hpp头部附接线指南 测试与部署: - pccuTest新增电池协议编解码/帧长/链路分发用例(175项通过);集成测试覆盖电池 心跳、启停映射(0x10->0x55/0x20->0x77)、状态落库;同步pccu_it.moos与ws_check - h100.moos与pCCU.moos增加锂电池链路配置;归档锂电池协议文档
252 lines
7.2 KiB
C++
252 lines
7.2 KiB
C++
/*
|
|
* TinyFSM - Tiny Finite State Machine Processor
|
|
*
|
|
* Copyright (c) 2012-2022 Axel Burri
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
* THE SOFTWARE.
|
|
*/
|
|
|
|
/* ---------------------------------------------------------------------
|
|
* Version: 0.3.3
|
|
*
|
|
* API documentation: see "../doc/50-API.md"
|
|
*
|
|
* The official TinyFSM website is located at:
|
|
* https://digint.ch/tinyfsm/
|
|
*
|
|
* Author:
|
|
* Axel Burri <axel@tty0.ch>
|
|
* ---------------------------------------------------------------------
|
|
*/
|
|
|
|
#ifndef TINYFSM_HPP_INCLUDED
|
|
#define TINYFSM_HPP_INCLUDED
|
|
|
|
#ifndef TINYFSM_NOSTDLIB
|
|
#include <type_traits>
|
|
#endif
|
|
|
|
// #include <iostream>
|
|
// #define DBG(str) do { std::cerr << str << std::endl; } while( false )
|
|
// DBG("*** dbg_example *** " << __PRETTY_FUNCTION__);
|
|
|
|
namespace tinyfsm
|
|
{
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
struct Event { };
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
#ifdef TINYFSM_NOSTDLIB
|
|
// remove dependency on standard library (silent fail!).
|
|
// useful in conjunction with -nostdlib option, e.g. if your compiler
|
|
// does not provide a standard library.
|
|
// NOTE: this silently disables all static_assert() calls below!
|
|
template<typename F, typename S>
|
|
struct is_same_fsm { static constexpr bool value = true; };
|
|
#else
|
|
// check if both fsm and state class share same fsmtype
|
|
template<typename F, typename S>
|
|
struct is_same_fsm : std::is_same< typename F::fsmtype, typename S::fsmtype > { };
|
|
#endif
|
|
|
|
template<typename S>
|
|
struct _state_instance
|
|
{
|
|
using value_type = S;
|
|
using type = _state_instance<S>;
|
|
static S value;
|
|
};
|
|
|
|
template<typename S>
|
|
typename _state_instance<S>::value_type _state_instance<S>::value;
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
template<typename F>
|
|
class Fsm
|
|
{
|
|
public:
|
|
|
|
using fsmtype = Fsm<F>;
|
|
using state_ptr_t = F *;
|
|
|
|
static state_ptr_t current_state_ptr;
|
|
|
|
// public, leaving ability to access state instance (e.g. on reset)
|
|
template<typename S>
|
|
static constexpr S & state(void) {
|
|
static_assert(is_same_fsm<F, S>::value, "accessing state of different state machine");
|
|
return _state_instance<S>::value;
|
|
}
|
|
|
|
template<typename S>
|
|
static constexpr bool is_in_state(void) {
|
|
static_assert(is_same_fsm<F, S>::value, "accessing state of different state machine");
|
|
return current_state_ptr == &_state_instance<S>::value;
|
|
}
|
|
|
|
/// state machine functions
|
|
public:
|
|
|
|
// explicitely specialized in FSM_INITIAL_STATE macro
|
|
static void set_initial_state();
|
|
|
|
static void reset() { };
|
|
|
|
static void enter() {
|
|
current_state_ptr->entry();
|
|
}
|
|
|
|
static void start() {
|
|
set_initial_state();
|
|
enter();
|
|
}
|
|
|
|
template<typename E>
|
|
static void dispatch(E const & event) {
|
|
current_state_ptr->react(event);
|
|
}
|
|
|
|
|
|
/// state transition functions
|
|
protected:
|
|
|
|
template<typename S>
|
|
void transit(void) {
|
|
static_assert(is_same_fsm<F, S>::value, "transit to different state machine");
|
|
current_state_ptr->exit();
|
|
current_state_ptr = &_state_instance<S>::value;
|
|
current_state_ptr->entry();
|
|
}
|
|
|
|
template<typename S, typename ActionFunction>
|
|
void transit(ActionFunction action_function) {
|
|
static_assert(is_same_fsm<F, S>::value, "transit to different state machine");
|
|
current_state_ptr->exit();
|
|
// NOTE: do not send events in action_function definisions.
|
|
action_function();
|
|
current_state_ptr = &_state_instance<S>::value;
|
|
current_state_ptr->entry();
|
|
}
|
|
|
|
template<typename S, typename ActionFunction, typename ConditionFunction>
|
|
void transit(ActionFunction action_function, ConditionFunction condition_function) {
|
|
if(condition_function()) {
|
|
transit<S>(action_function);
|
|
}
|
|
}
|
|
};
|
|
|
|
template<typename F>
|
|
typename Fsm<F>::state_ptr_t Fsm<F>::current_state_ptr;
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
template<typename... FF>
|
|
struct FsmList;
|
|
|
|
template<> struct FsmList<> {
|
|
static void set_initial_state() { }
|
|
static void reset() { }
|
|
static void enter() { }
|
|
template<typename E>
|
|
static void dispatch(E const &) { }
|
|
};
|
|
|
|
template<typename F, typename... FF>
|
|
struct FsmList<F, FF...>
|
|
{
|
|
using fsmtype = Fsm<F>;
|
|
|
|
static void set_initial_state() {
|
|
fsmtype::set_initial_state();
|
|
FsmList<FF...>::set_initial_state();
|
|
}
|
|
|
|
static void reset() {
|
|
F::reset();
|
|
FsmList<FF...>::reset();
|
|
}
|
|
|
|
static void enter() {
|
|
fsmtype::enter();
|
|
FsmList<FF...>::enter();
|
|
}
|
|
|
|
static void start() {
|
|
set_initial_state();
|
|
enter();
|
|
}
|
|
|
|
template<typename E>
|
|
static void dispatch(E const & event) {
|
|
fsmtype::template dispatch<E>(event);
|
|
FsmList<FF...>::template dispatch<E>(event);
|
|
}
|
|
};
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
template<typename... SS> struct StateList;
|
|
template<> struct StateList<> {
|
|
static void reset() { }
|
|
};
|
|
template<typename S, typename... SS>
|
|
struct StateList<S, SS...>
|
|
{
|
|
static void reset() {
|
|
_state_instance<S>::value = S();
|
|
StateList<SS...>::reset();
|
|
}
|
|
};
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
template<typename F>
|
|
struct MooreMachine : tinyfsm::Fsm<F>
|
|
{
|
|
virtual void entry(void) { }; /* entry actions in some states */
|
|
void exit(void) { }; /* no exit actions */
|
|
};
|
|
|
|
template<typename F>
|
|
struct MealyMachine : tinyfsm::Fsm<F>
|
|
{
|
|
// input actions are modeled in react():
|
|
// - conditional dependent of event type or payload
|
|
// - transit<>(ActionFunction)
|
|
void entry(void) { }; /* no entry actions */
|
|
void exit(void) { }; /* no exit actions */
|
|
};
|
|
|
|
} /* namespace tinyfsm */
|
|
|
|
|
|
#define FSM_INITIAL_STATE(_FSM, _STATE) \
|
|
namespace tinyfsm { \
|
|
template<> void Fsm< _FSM >::set_initial_state(void) { \
|
|
current_state_ptr = &_state_instance< _STATE >::value; \
|
|
} \
|
|
}
|
|
|
|
#endif /* TINYFSM_HPP_INCLUDED */
|