VLCB SDK
An opinionated SDK for VLCB protocol
Loading...
Searching...
No Matches
state_machine.c
Go to the documentation of this file.
1#include "state_machine.h"
2
3#include "vlcb/common/node.h"
4#include "vlcb/module.h"
5#include "vlcb/module/state.h"
8#include "vlcb/net/socket.h"
11#include "vlcb/platform/time.h"
12#include <assert.h>
13#include <stdbool.h>
14#include <stddef.h>
15#include <string.h>
16
17#ifndef VLCB_MODULE_STATE_CHANGE_TIMEOUT_MS
18#define VLCB_MODULE_STATE_CHANGE_TIMEOUT_MS 30000
19#endif /* ifndef VLCB_MODULE_STATE_CHANGE_TIMEOUT_MS \
20 */
21
23 // TODO: do we need to also release the setup-state address, which is not
24 // persisted yet?
25 const VlcbNodeNumber addr = self->config.nodeNumber;
26
27 // release the address if it was set
28 if (addr != VLCB_NODE_ADDR_UNINITIALIZED) {
30 vlcb_net_pkt_dgram_module_ReleaseNodeNumber_Serialize(
31 &packet, (VlcbNetDgramReleaseNodeNumber){.addr = addr});
32 const VlcbNetSocketProcessErr err =
33 vlcb_net_sock_dgram_Send(self->socket, &packet);
34 if (err != VLCB_NET_SOCK_ERR_OK) {
35 // todo: log
36 return false;
37 }
38 self->config.nodeNumber = VLCB_NODE_ADDR_UNINITIALIZED;
39 }
40
42
43 return true;
44}
45
46static bool HandleTransitionToSetup(VlcbModule *const self,
49 vlcb_net_pkt_dgram_module_RequestNodeNumber_Serialize(
50 &packet, (VlcbNetDgramRequestNodeNumber){.addr = setupData.nodeAddr});
51 const VlcbNetSocketProcessErr err =
52 vlcb_net_sock_dgram_Send(self->socket, &packet);
53 if (err != VLCB_NET_SOCK_ERR_OK) {
54 // TODO: log
55 return false;
56 }
57 return true;
58}
59
60static bool HandleTransitionToNormal(VlcbModule *const self) {
61 if (self->config.nodeNumber != VLCB_NODE_ADDR_UNINITIALIZED) {
63 vlcb_net_pkt_dgram_module_ReleaseNodeNumber_Serialize(
64 &packet,
65 (VlcbNetDgramReleaseNodeNumber){.addr = self->config.nodeAddr});
66 const VlcbNetSocketProcessErr err =
67 vlcb_net_sock_dgram_Send(self->socket, &packet);
68 if (err != VLCB_NET_SOCK_ERR_OK) {
69 // TODO: log
70 return false;
71 }
72 self->config.nodeNumber =
73 VLCB_NODE_ADDR_UNINITIALIZED; // if next call fails, prevent next
74 // transition to double-release the node
75 // number
76 }
77
79 vlcb_net_pkt_dgram_module_NodeNumberAck_Serialize(
80 &packet,
81 (VlcbNetDgramNodeNumberAck){.addr = self->sm.data.setup.nodeAddr});
82 const VlcbNetSocketProcessErr err =
83 vlcb_net_sock_dgram_Send(self->socket, &packet);
84 if (err != VLCB_NET_SOCK_ERR_OK) {
85 // TODO: log
86 return false;
87 }
88
90 self->config.nodeNumber = self->sm.data.setup.nodeAddr;
91 return true;
92}
93
94static inline bool CheckForSetupTimeout(VlcbModule *const self,
95 const clock_t now) {
98}
99
101 const clock_t now) {
102 if (e.sig == MSE_INIT) {
103 // reset state, node and hw address when invalid state was resolved from
104 // config
105 VlcbModulePersistedState persistedState = self->config.state;
106 if (persistedState < VLCB_MODULE_PERSISTED_STATE_UNINITIALIZED ||
107 persistedState > VLCB_MODULE_PERSISTED_STATE_NORMAL) {
108 self->config.nodeNumber = 0;
109 memset(&self->config.hwAddr, 0, sizeof(VlcbNetHwAddr));
111 }
112 switch (self->config.state) {
115 break;
118 default:
119 assert(false);
120 }
121 _INTERFACE_CALL(self->ui, IndicateState, self->sm.state);
122 return;
123 }
124
125 // TODO: include error responses to invalid commands like in MNS 2.3.4.1
126
127 const VlcbModuleState currentState = self->sm.state;
128 switch (currentState) {
130 if (e.sig == MSE_UI_REQ_TO_SETUP) {
131 const VlcbModuleStateMachineSetupData setupData = {
132 .prevState = currentState,
133 .nodeAddr = VLCB_NODE_ADDR_UNINITIALIZED,
134 .startedAt = now};
135 if (HandleTransitionToSetup(self, setupData)) {
137 self->sm.data.setup = setupData;
138 }
139 }
140 break;
142 switch (e.sig) {
144 // Module encountered a MODE message for another module, aborting it's
145 // setup
146 // TODO: send NNACK, on fail log and either restart the module or send to
147 // uninitialized
148 self->sm.state = self->sm.data.setup.prevState;
149 break;
151 // UI or MODE requested to go back to previous state without saving
152 switch (self->sm.data.setup.prevState) {
154 // ignore req if transition failed
157 }
158 break;
161 break;
162 }
163 break;
164 case MSE_NNRSM_MSG:
167 }
168 break;
169 case MSE_SNN_MSG:
170 if (HandleTransitionToNormal(self)) {
172 }
173 break;
174 case MSE_POLL:
175 // revert state on timeout
176 if (CheckForSetupTimeout(self, now)) {
177 switch (self->sm.data.setup.prevState) {
181 }
182 break;
185 break;
186 }
187 }
188 break;
189 }
190 break;
192 switch (e.sig) {
195 const VlcbModuleStateMachineSetupData setupData = {
196 .prevState = currentState,
197 .nodeAddr = self->config.nodeNumber,
198 .startedAt = now};
199 if (HandleTransitionToSetup(self, setupData)) {
201 self->sm.data.setup = setupData;
202 }
203 break;
204 case MSE_NNRSM_MSG:
205 // ignore on failure to transition
208 }
209 break;
210 }
211 break;
212 default:
213 assert(false /* unhandled state */);
214 }
215
216 if (currentState != self->sm.state) {
217 _INTERFACE_CALL(self->ui, IndicateState, self->sm.state);
218 }
219}
#define _INTERFACE_CALL(o, m,...)
Definition interface.h:29
@ VLCB_MODULE_PERSISTED_STATE_UNINITIALIZED
@ VLCB_MODULE_PERSISTED_STATE_NORMAL
uint8_t VlcbModulePersistedState
uint16_t VlcbNodeNumber
Definition node.h:8
VlcbNetSocketDgramSendErr vlcb_net_sock_dgram_Send(VlcbNetSocketDatagram *const sock, const VlcbNetPacketDatagram *const packet)
VlcbNetSocketProcessErr
Definition socket.h:10
VlcbModuleState
Definition state.h:9
@ VLCB_MODULE_STATE_SETUP
Definition state.h:11
@ VLCB_MODULE_STATE_UNINITIALIZED
Definition state.h:10
@ VLCB_MODULE_STATE_NORMAL
Definition state.h:12
static bool HandleTransitionToNormal(VlcbModule *const self)
static bool HandleTransitionToUninitialized(VlcbModule *const self)
void state_Dispatch(VlcbModule *const self, const ModuleStateEvent e, const clock_t now)
static bool HandleTransitionToSetup(VlcbModule *const self, VlcbModuleStateMachineSetupData setupData)
static bool CheckForSetupTimeout(VlcbModule *const self, const clock_t now)
#define VLCB_MODULE_STATE_CHANGE_TIMEOUT_MS
@ MSE_NNRSM_MSG
@ MSE_POLL
@ MSE_INIT
@ MSE_MODE_MSG_FOR_ANOTHER_MODULE
@ MSE_UI_REQ_TO_SETUP
@ MSE_SNN_MSG
@ MSE_UI_REQ_TO_PREV
@ MSE_MODE_REQ_TO_SETUP
ModuleStateEventSignal sig
VlcbModulePersistedState state
VlcbModuleState prevState
Definition state.h:16
VlcbNodeNumber nodeAddr
Definition state.h:17
VlcbModuleStateMachineData data
Definition state.h:27
VlcbModuleState state
Definition state.h:26
VlcbModuleStateMachine sm
VlcbModuleConfig config
VlcbNetSocketDatagram *const socket
static double vlcb_platform_time_DiffInMs(const clock_t start, const clock_t end)
Definition time.h:10
VlcbModuleStateMachineSetupData setup
Definition state.h:22