Tool Libs
UMIT-TIROL Institute of Automation and Control Engineering library collection
 
Loading...
Searching...
No Matches
experiment.h
Go to the documentation of this file.
1
5#pragma once
7#include <utils/deadline.h>
8
9#include "kern.h"
10#include "evented.h"
11#include "logger.h"
12
33extern class Experiment {
34 struct ELog : Logger {
35 const uint32_t &time;
36 virtual Buffer<uint8_t> pre() override {
37 Buffer<uint8_t> ret = 256;
38 ret.len = snprintf((char*)ret.buf, ret.size,
39 "Experiment Logger (@%" PRIu32 "ms): ", time);
40 return ret;
41 }
42 ELog(const uint32_t &time, Sink<Buffer<uint8_t>> &underlying)
43 : Logger(underlying), time(time) {
44 }
45 void start(uint32_t) { info("started\n"); }
46 void stop(uint32_t) { info("stopped\n"); }
47 void timeout(uint32_t) { warn("timed out!\n"); }
48 };
49public:
51 enum State {
56 };
69 k.every(1, *this, &Experiment::tick);
70 if (fr) registerWith(*fr);
71 onEvent(INIT).call(log, &ELog::start);
72 onEvent(STOP).call(log, &ELog::stop);
73 onEvent(TIMEOUT).call(log, &ELog::timeout);
74 }
77 reg.setHandler(1, *this, &Experiment::handleFrame);
78 }
81 switch (e) {
82 case INIT: return init;
83 case STOP: return stop;
84 default: return timeout;
85 }
86 }
89 switch (s) {
90 case IDLE: return idle;
91 default: return running;
92 }
93 }
95 const State& state{state_};
97 const uint32_t& time{time_};
99 void setHeartbeatTimeout(uint32_t ms, Sink<Frame> &notify) {
100 heartbeat.timeout = ms;
101 heartbeat.reset(time);
102 // notify other side if we timeout
103 struct TMP :Schedule::Schedulable{
104 Sink<Frame> &s;
105 TMP(Sink<Frame>&s): s(s) {}
106 void call() override{
107 auto f = Frame{1}.pack(false);
108 s.trypush(std::move(f));
109 }};
110 timeout.call(new TMP{notify});
111 }
113 ELog log{time, k.log};
114
115private:
116 State state_{};
117 bool alive{};
118 void statemachine() {
119 State old = state;
120 // very simple state machine
121 state_ = alive ? RUN : IDLE;
122 if (state != old) switch(old) { // handle state transitions == events
123 case IDLE:
124 time_ = 0;
125 k.schedule(time, init);
126 idle.reset(); running.reset();
127 break;
128 case RUN:
129 k.schedule(time, stop);
130 break;
131 }
132 switch (state) { // handle states == recurring
133 case IDLE:
134 k.schedule(time, idle);
135 break;
136 case RUN :
137 k.schedule(time, running);
138 if (heartbeat && heartbeat(time)) {
139 k.schedule(time, timeout);
140 alive = false;
141 }
142 break;
143 }
144 }
145 Schedule::Evented::Registry init{}, stop{}, timeout{};
146 Schedule::Recurring::Registry idle{}, running{};
147 uint32_t time_{};
148 class _: Deadline {
149 friend Experiment;
150 uint32_t timeout{};
151 operator bool() {
152 return timeout;
153 }
154 bool reset(uint32_t now) {
155 when = now + timeout;
156 return true;
157 }
158 } heartbeat{};
159
160 void tick(uint32_t, uint32_t dt) {
161 statemachine();
162 time_ += dt;
163 }
164
165 void handleFrame(Frame &f) {
166 assert(f.id == 1);
167 struct {
168 uint8_t alive:1;
169 uint8_t heartbeat:1;
170 uint8_t _:6;
171 } b = f.unpack<decltype(b)>();
172 if (b.heartbeat) {
173 (bool)heartbeat && heartbeat.reset(time);
174 } else {
175 alive = b.alive;
176 }
177 }
178} e;
179
Experiment Controller.
Definition experiment.h:33
void registerWith(FrameRegistry &reg)
set frame registry from which Experiment will receive frames
Definition experiment.h:76
State
States during which recurring tasks can be called using during.
Definition experiment.h:51
@ RUN
running Experiment state
Definition experiment.h:55
@ IDLE
initial Experiment state
Definition experiment.h:53
ELog log
Logging facility.
Definition experiment.h:113
void setHeartbeatTimeout(uint32_t ms, Sink< Frame > &notify)
set Heartbeat timeout in ms
Definition experiment.h:99
const uint32_t & time
const access to Experiment time
Definition experiment.h:97
Schedule::Recurring::Registry & during(State s)
register recurring callbacks during Experiment states
Definition experiment.h:88
Schedule::Evented::Registry & onEvent(Event e)
register callbacks for Experiment state change events
Definition experiment.h:80
Event
Events upon which tasks can be called using onEvent.
Definition experiment.h:58
@ TIMEOUT
Event generated on missed heartbeat.
Definition experiment.h:64
@ INIT
Event generated on experiment start.
Definition experiment.h:60
@ STOP
Event generated on experiment end.
Definition experiment.h:62
Experiment(FrameRegistry *fr=nullptr)
construct. if FrameRegistry is not available at this point, call registerWith at the earliest conveni...
Definition experiment.h:68
const State & state
const access to Experiment state
Definition experiment.h:95
Copyright (c) 2023 IACE.
Copyright (c) 2023 IACE.
Copyright (c) 2023 IACE.
Copyright (c) 2023 IACE.
Copyright (c) 2023 IACE.
dynamically allocated, but fixed-size buffer template
Definition buffer.h:18
size_t size
total capacity of buffer
Definition buffer.h:23
size_t len
number of items stored in buffer
Definition buffer.h:21
simple solution for keeping track of timeouts
Definition deadline.h:15
Registry for dispatching frames to their registered destinations.
Definition frameregistry.h:61
void setHandler(uint8_t id, FuncHandler::Func f)
register pure function FrameHandler for given id
Definition frameregistry.h:91
pyWisp communication frame
Definition frameregistry.h:10
Frame & pack(T value)
pack value into Frame
Definition frameregistry.h:22
uint8_t id
buffer id: [0..63]
Definition frameregistry.h:14
T unpack()
return unpacked value from Frame
Definition frameregistry.h:46
simple printf-style logging infrastructure
Definition logger.h:21
void info(const char *fmt,...)
Info log level.
Definition logger.h:43
void warn(const char *fmt,...)
Warn log level.
Definition logger.h:50
registry of evented calls
Definition evented.h:61
void call(Func::Call func)
register function to be scheduled for calling on Event
Definition evented.h:63
registry of recurring calls
Definition timed.h:65
void reset()
reset calling times of all registered functions
Definition timed.h:83
void every(uint32_t dt_ms, typename Func::Call func)
register a function to be called every dt_ms
Definition timed.h:68
represents an object that can be scheduled for later calling
Definition schedule.h:20
bool schedule(uint32_t time, Schedule::Registry &reg)
schedule all registered schedulables of registry if necessary
Definition schedule.h:52
generic object sink, i.e.
Definition streams.h:15
void trypush(T &&t)
use this if you don't care if it's going to be successful. data gets discarded if sink is full.
Definition streams.h:28