Uniot Core
0.8.1
Loading...
Searching...
No Matches
NetworkController.h
Go to the documentation of this file.
1/*
2 * This is a part of the Uniot project.
3 * Copyright (C) 2016-2025 Uniot <contact@uniot.io>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#pragma once
20
21#include <Button.h>
22#include <CBORStorage.h>
23#include <EventListener.h>
25#include <NetworkEvents.h>
26#include <NetworkScheduler.h>
27
70
71namespace uniot {
93 public:
114 uint8_t pinBtn = UINT8_MAX,
115 uint8_t activeLevelBtn = LOW,
116 uint8_t pinLed = UINT8_MAX,
117 uint8_t activeLevelLed = HIGH,
118 uint8_t maxRebootCount = 3,
119 uint32_t rebootWindowMs = 10000)
120 : CBORStorage("ctrl.cbor"),
121 mpNetwork(&network),
122 mNetworkLastState(events::network::Msg::SUCCESS),
123 mClickCounter(0),
124 mPinLed(pinLed),
125 mActiveLevelLed(activeLevelLed),
126 mMaxRebootCount(maxRebootCount),
127 mRebootWindowMs(rebootWindowMs),
128 mRebootCount(0) {
129 if (pinLed != UINT8_MAX) {
130 pinMode(mPinLed, OUTPUT);
131 }
132 if (pinBtn != UINT8_MAX) {
133 mpConfigBtn = MakeUnique<Button>(pinBtn, activeLevelBtn, 30, [&](Button *btn, Button::Event event) {
134 switch (event) {
136 if (mClickCounter > 3)
137 mpNetwork->forget();
138 else
139 mpNetwork->reconnect();
140 break;
141 case Button::CLICK:
142 if (!mClickCounter) {
143 mpTaskResetClickCounter->attach(5000, 1);
144 }
145 mClickCounter++;
146 default:
147 break;
148 }
149 });
150 }
151 _initTasks();
152 _checkAndHandleReboot();
154 }
155
166
174 virtual bool store() override {
175 object().put("reset", mRebootCount);
176 return CBORStorage::store();
177 }
178
186 virtual bool restore() override {
187 if (CBORStorage::restore()) {
188 mRebootCount = object().getInt("reset");
189 return true;
190 }
191 return false;
192 }
193
204 virtual void onEventReceived(unsigned int topic, int msg) override {
206 int lastState = _resetNetworkLastState(msg);
207 switch (msg) {
209 if (lastState != events::network::Msg::FAILED) {
211 }
212 break;
214 statusIdle();
215 break;
217 statusBusy();
218 break;
220 if (lastState != events::network::Msg::CONNECTING) {
221 // If previous state was CONNECTING, most likely there was a manual reconnect request
222 mpNetwork->reconnect();
223 }
224 break;
226 mpNetwork->reconnect();
227 break;
229 statusAlarm();
230 mpNetwork->config();
231 break;
232 default:
233 break;
234 }
235 }
236 }
237
246 virtual void pushTo(TaskScheduler &scheduler) override {
247 scheduler.push("signal_led", mpTaskSignalLed);
248 scheduler.push("rst_reboot_count", mpTaskResetRebootCounter);
249 if (_hasButton()) {
250 scheduler.push("btn_config", mpTaskConfigBtn);
251 scheduler.push("rst_click_count", mpTaskResetClickCounter);
252 }
253 }
254
261 virtual void attach() override {
262 mpTaskResetRebootCounter->once(mRebootWindowMs);
263 if (_hasButton()) {
264 mpTaskConfigBtn->attach(100);
265 }
266 statusBusy();
267 }
268
277 mpTaskSignalLed->attach(1000);
278 }
279
286 void statusBusy() {
287 mpTaskSignalLed->attach(500);
288 }
289
296 void statusAlarm() {
297 mpTaskSignalLed->attach(200);
298 }
299
306 void statusIdle() {
307 mpTaskSignalLed->attach(200, 1);
308 }
309
318 return _hasButton() ? mpConfigBtn.get() : nullptr;
319 }
320
321 private:
329 void _initTasks() {
330 mpTaskSignalLed = TaskScheduler::make([&](SchedulerTask &self, short t) {
331 static bool signalLevel = true;
332 signalLevel = (!signalLevel && t);
334
335 if (_hasLed()) {
336 digitalWrite(mPinLed, signalLevel ? mActiveLevelLed : !mActiveLevelLed);
337 }
338 });
339
340 if (_hasButton()) {
341 mpTaskConfigBtn = TaskScheduler::make(*mpConfigBtn);
342 mpTaskResetClickCounter = TaskScheduler::make([&](SchedulerTask &self, short t) {
343 UNIOT_LOG_DEBUG("ClickCounter = %d", mClickCounter);
344 mClickCounter = 0;
345 });
346 }
347
348 mpTaskResetRebootCounter = TaskScheduler::make([&](SchedulerTask &self, short t) {
349 mRebootCount = 0;
351 });
352 }
353
362 void _checkAndHandleReboot() {
364 mRebootCount++;
365 if (mRebootCount >= mMaxRebootCount) {
366 mpTaskResetRebootCounter->detach();
367 mpNetwork->forget();
368 mRebootCount = 0;
369 }
371 }
372
382 int _resetNetworkLastState(int newState) {
383 auto oldState = mNetworkLastState;
384 mNetworkLastState = newState;
385 return oldState;
386 }
387
392 inline bool _hasButton() {
393 return mpConfigBtn.get() != nullptr;
394 }
395
400 inline bool _hasLed() {
401 return mPinLed != UINT8_MAX;
402 }
403
404 NetworkScheduler *mpNetwork;
405 int mNetworkLastState;
406
407 uint8_t mClickCounter;
408 uint8_t mPinLed;
409 uint8_t mActiveLevelLed;
410 uint8_t mMaxRebootCount;
411 uint32_t mRebootWindowMs;
412 uint8_t mRebootCount;
413
414 UniquePointer<Button> mpConfigBtn;
415
416 // Task pointers for scheduled operations
417 TaskScheduler::TaskPtr mpTaskSignalLed;
418 TaskScheduler::TaskPtr mpTaskConfigBtn;
419 TaskScheduler::TaskPtr mpTaskResetClickCounter;
420 TaskScheduler::TaskPtr mpTaskResetRebootCounter;
421};
422} // namespace uniot
423
Network event definitions for the Uniot event system.
Complete WiFi network management and configuration system.
Definition Button.h:54
Event
Defines types of button events that can be triggered.
Definition Button.h:60
@ LONG_PRESS
Button held down for longer than the defined threshold.
Definition Button.h:62
@ CLICK
Regular short button press and release.
Definition Button.h:61
long getInt(int key) const
Get an integer value at a specific integer key.
Definition CBORObject.h:399
CBORObject & put(int key, int value)
Put an integer value at a specific integer key.
Definition CBORObject.h:170
virtual bool restore() override
Restore the CBOR object from the filesystem.
Definition CBORStorage.h:92
virtual bool store() override
Store the CBOR object to the filesystem.
Definition CBORStorage.h:74
CBORStorage(const String &path)
Constructs a new CBORStorage object.
Definition CBORStorage.h:46
CBORObject & object()
Get access to the underlying CBORObject.
Definition CBORStorage.h:60
void emitEvent(unsigned int topic, int msg)
EventListener * stopListeningToEvent(unsigned int topic)
EventListener * listenToEvent(unsigned int topic)
Interface for connecting components to the TaskScheduler.
Definition ISchedulerConnectionKit.h:35
void statusIdle()
Set LED to idle status pattern.
Definition NetworkController.h:306
virtual ~NetworkController()
Destroy the NetworkController.
Definition NetworkController.h:162
NetworkController(NetworkScheduler &network, uint8_t pinBtn=UINT8_MAX, uint8_t activeLevelBtn=LOW, uint8_t pinLed=UINT8_MAX, uint8_t activeLevelLed=HIGH, uint8_t maxRebootCount=3, uint32_t rebootWindowMs=10000)
Construct a new NetworkController.
Definition NetworkController.h:113
virtual void onEventReceived(unsigned int topic, int msg) override
Handle network events and update controller state.
Definition NetworkController.h:204
void statusAlarm()
Set LED to alarm status pattern.
Definition NetworkController.h:296
void statusWaiting()
Set LED to waiting status pattern.
Definition NetworkController.h:276
void statusBusy()
Set LED to busy status pattern.
Definition NetworkController.h:286
virtual bool restore() override
Restore controller state from persistent storage.
Definition NetworkController.h:186
Button * getButton()
Get access to the configuration button.
Definition NetworkController.h:317
virtual void attach() override
Attach the controller and start initial operations.
Definition NetworkController.h:261
virtual void pushTo(TaskScheduler &scheduler) override
Push all controller tasks to the scheduler.
Definition NetworkController.h:246
virtual bool store() override
Store controller state to persistent storage.
Definition NetworkController.h:174
Complete WiFi network management and configuration scheduler.
Definition NetworkScheduler.h:100
Definition TaskScheduler.h:67
Definition TaskScheduler.h:164
std::unique_ptr< T > UniquePointer
Type alias for std::unique_ptr with cleaner syntax.
Definition Common.h:152
auto MakeUnique(Args &&...args) -> decltype(std::make_unique< T >(std::forward< Args >(args)...))
Creates a unique pointer instance, alias for std::make_unique.
Definition Common.h:179
EventListener< unsigned int, int, Bytes > CoreEventListener
Type alias for the common EventListener configuration used in the core system.
Definition EventListener.h:100
#define UNIOT_LOG_DEBUG(...)
Log an DEBUG level message Used for general information about system operation. Only compiled if UNIO...
Definition Logger.h:293
SharedPointer< SchedulerTask > TaskPtr
Shared pointer type for scheduler tasks.
Definition TaskScheduler.h:171
static TaskPtr make(SchedulerTask::SchedulerTaskCallback callback)
Static factory method to create a task with a callback.
Definition TaskScheduler.h:193
TaskScheduler & push(const char *name, TaskPtr task)
Add a named task to the scheduler.
Definition TaskScheduler.h:214
@ SUCCESS
Network operation completed successfully.
Definition NetworkEvents.h:86
@ ACCESS_POINT
Device is operating in access point mode.
Definition NetworkEvents.h:90
@ AVAILABLE
Configured network is available for connection.
Definition NetworkEvents.h:91
@ DISCONNECTED
Network connection has been lost or terminated.
Definition NetworkEvents.h:89
@ FAILED
Network operation failed (connection, scan, etc.)
Definition NetworkEvents.h:85
@ CONNECTING
Currently attempting to connect to network.
Definition NetworkEvents.h:87
@ WIFI_STATUS_LED
LED status indicators for network state.
Definition NetworkEvents.h:75
@ CONNECTION
WiFi connection state changes and operations.
Definition NetworkEvents.h:74
Definition DateEvents.h:51
Contains all classes and functions related to the Uniot Core.