Skip to content

Commit dcde8b6

Browse files
author
Maarten Pennings
committed
0.3.0
- Added the feature that an app can be hidden; the `hide` commands toggles. - The voidapp no longer is hardwired hidden; it uses the new hidden feature. - Corrected `swflags` to `swflag`. - Fixed prefix error in `aoapps_swflag.cpp`. - Fixed documentation error for `aoapps_init()`.
1 parent 43d0fa8 commit dcde8b6

6 files changed

Lines changed: 84 additions & 47 deletions

File tree

library.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=OSP ReusableApps aoapps
2-
version=0.2.10
2+
version=0.3.0
33
author=ams-OSRAM
44
maintainer=ams-OSRAM
55
sentence=A library with reusable "apps" for OSP chains.

readme.md

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ void apps_register() {
4242
void setup() {
4343
...
4444

45+
// Init the Library
46+
aoapps_init();
47+
4548
// Register all apps
4649
apps_register();
4750

@@ -155,7 +158,7 @@ The headers contain little documentation; for that see the module source files.
155158

156159
### aoapps
157160

158-
- `aoapps_init()` not really needed, but added for forward compatibility.
161+
- `aoapps_init()` to initialize the library (the apps manager).
159162
- `AOAPPS_VERSION` identifies the version of the library.
160163

161164

@@ -169,8 +172,9 @@ An important aspect of the app manager is app registration.
169172
its start, step an stop functions, an optional command handler, and some flags).
170173
- `aoapps_mngr_start_t`, `aoapps_mngr_step_t`, `aoapps_mngr_stop_t` types for
171174
to start, step and stop function.
172-
- `AOAPPS_MNGR_FLAGS_WITHTOPO`, `AOAPPS_MNGR_FLAGS_WITHREPAIR` and
173-
`AOAPPS_MNGR_FLAGS_NEXTONERR` registration flags.
175+
- `AOAPPS_MNGR_FLAGS_HIDDEN`, `AOAPPS_MNGR_FLAGS_WITHTOPO`,
176+
`AOAPPS_MNGR_FLAGS_WITHREPAIR` and `AOAPPS_MNGR_FLAGS_NEXTONERR`
177+
registration flags.
174178
- `AOAPPS_MNGR_REGISTRATION_SLOTS` maximum number of apps that can
175179
be registered.
176180

@@ -269,6 +273,13 @@ the app manager will, when that app returns an error, do as before (stop
269273
heart beat, switch on red LED, show error on OLED), but after a time-out start
270274
the next app.
271275

276+
The list of registered apps can become long. For a specific demo, apps
277+
can be hidden, so that the demonstration can focus on specific apps.
278+
When an app is hidden, it is skipped in the `switchnext()` cycle, which is
279+
typically executed when pressing the A button. The voidapp registers itself
280+
as hidden, for other apps hide them via the command `apps hide <app>`,
281+
e.g. in `boot.cmd`.
282+
272283
Some apps have configuration parameters that can be observed and changed via
273284
a command. The command handler can also be passed during app registration,
274285
see the next chapter.
@@ -281,7 +292,8 @@ This module also implements a command `apps` (to be registered with
281292

282293
- show a list of all registered apps
283294
- switch to a different app
284-
- configure an app
295+
- configure an app as hidden
296+
- configure an app via its handler
285297

286298
If an individual app has something to configure, its shall pass its
287299
configuration handler (just another command handler) during its registration
@@ -335,7 +347,7 @@ the `boot.cmd` which is executed at startup, for example:
335347
336348
The app manager has one app always registered, the "voidapp". This app
337349
does nothing. It does not start with topo init, its start, step and stop
338-
are empty, and it does not deploy repair actions.
350+
are empty, and it does not deploy repair actions, but it is hidden by default.
339351
340352
This app is useful when the user wants to take over control via the
341353
Serial over USB command interface. If the user gives the command
@@ -349,6 +361,13 @@ of the OSP chain, without app telegrams interfering.
349361
350362
## Version history _aoapps_
351363
364+
- **2025 March 3, 0.3.0**
365+
- Added the feature that an app can be hidden; the `hide` commands toggles.
366+
- The voidapp no longer is hardwired hidden; it uses the new hidden feature.
367+
- Corrected `swflags` to `swflag`.
368+
- Fixed prefix error in `aoapps_swflag.cpp`.
369+
- Fixed documentation error for `aoapps_init()`.
370+
352371
- **2024 November 29, 0.2.10**
353372
- Fixed typos (including I/O-expander).
354373

src/aoapps.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424

2525
// Identifies lib version
26-
#define AOAPPS_VERSION "0.2.10"
26+
#define AOAPPS_VERSION "0.3.0"
2727

2828

2929
// Include the (headers of the) modules of this app

src/aoapps_mngr.cpp

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@
2727

2828

2929
// === voidapp ===============================================================
30-
// The void app, doing nothing, allowing unhindered USB commands
31-
// It is always registered (in init), but not part of switchnext()
30+
// The voidapp, doing nothing, allowing unhindered USB commands
31+
// It is always registered (in init), but hidden, ie not part of switchnext()
3232

3333

3434
static aoresult_t aoapps_mngr_voidapp_start() {
@@ -48,7 +48,7 @@ static void aoapps_mngr_voidapp_stop () {
4848

4949
void aoapps_mngr_voidapp_register() {
5050
aoapps_mngr_register("voidapp", "USB command", "--", "--",
51-
0, /* no dither, no repair */
51+
AOAPPS_MNGR_FLAGS_HIDDEN,
5252
aoapps_mngr_voidapp_start, aoapps_mngr_voidapp_step, aoapps_mngr_voidapp_stop,
5353
0, 0 /* no config command */ );
5454
}
@@ -362,8 +362,8 @@ void aoapps_mngr_stop() {
362362
0 <= appix < aoapps_mngr_app_count()
363363
@note It is an error when the current app is "stop" (must be "run").
364364
@note See `aoapps_mngr_start()` for start/stop/current/appix terminology.
365-
@note aoapps_mngr_switch(0) will select the voidapp; the function
366-
aoapps_mngr_switchnext() skips the voidapp.
365+
@note `aoapps_mngr_switch(0)` will select the voidapp like any other hidden
366+
app; the function `aoapps_mngr_switchnext()` skips them.
367367
@note See `aoapps_mngr_switchnext()`.
368368
*/
369369
void aoapps_mngr_switch(int appix) {
@@ -374,13 +374,18 @@ void aoapps_mngr_switch(int appix) {
374374

375375
/*!
376376
@brief Stops the current app and starts the next one.
377-
@note The next one in the sense of appix (registration order).
378-
@note Wraps around to appix 1 (so skips voidapp).
377+
@note The "next one" is in the sense of registration order.
378+
@note Wraps around, and skips apps that have their hidden flag set.
379+
@note If all apps are hidden does nothing (stays at app).
379380
@note It is an error when the current app is "stop" (must be "run").
380381
@note See `aoapps_mngr_start()` for start/stop/current/appix terminology.
381382
*/
382383
void aoapps_mngr_switchnext() {
383-
aoapps_mngr_switch( aoapps_mngr_appix % (aoapps_mngr_count-1) + 1);
384+
int appix= aoapps_mngr_appix;
385+
do {
386+
appix= (appix+1) % aoapps_mngr_count;
387+
} while( (aoapps_mngr_apps[appix].flags & AOAPPS_MNGR_FLAGS_HIDDEN) && (appix!=aoapps_mngr_appix) );
388+
if( appix!=aoapps_mngr_appix ) aoapps_mngr_switch(appix);
384389
}
385390

386391

@@ -476,7 +481,7 @@ static aoresult_t aoapps_mngr_stepwithtopo() {
476481
if( aoapps_mngr_error!=aoresult_ok ) aoapps_mngr_state= AOAPPS_MNGR_STATE_ERROR;
477482
return aoresult_ok; // loop topo build
478483
}
479-
Serial.printf("%s: starting on %d RGBs\n", aoapps_mngr_apps[aoapps_mngr_appix].name, aomw_topo_numtriplets() );
484+
// Serial.printf("%s: starting on %d RGBs\n", aoapps_mngr_apps[aoapps_mngr_appix].name, aomw_topo_numtriplets() );
480485
aoapps_mngr_error= aoapps_mngr_apps[aoapps_mngr_appix].start(); // call start of app
481486
if( aoapps_mngr_error!=aoresult_ok ) aoapps_mngr_state= AOAPPS_MNGR_STATE_ERROR;
482487
aoapps_mngr_state= AOAPPS_MNGR_STATE_APPANIM;
@@ -555,12 +560,13 @@ static void aoapps_mngr_cmd_listone(int appix) {
555560
if( appix!=cur ) mode= "stop";
556561
else if( run ) mode= "run";
557562
else mode= "idle";
558-
char flags[4]="tre";
559-
if( aoapps_mngr_apps[appix].flags & AOAPPS_MNGR_FLAGS_WITHTOPO ) flags[0]='T';
560-
if( aoapps_mngr_apps[appix].flags & AOAPPS_MNGR_FLAGS_WITHREPAIR ) flags[1]='R';
561-
if( aoapps_mngr_apps[appix].flags & AOAPPS_MNGR_FLAGS_NEXTONERR ) flags[2]='E';
563+
char flags[]="htre";
564+
if( aoapps_mngr_apps[appix].flags & AOAPPS_MNGR_FLAGS_HIDDEN ) flags[0]='H';
565+
if( aoapps_mngr_apps[appix].flags & AOAPPS_MNGR_FLAGS_WITHTOPO ) flags[1]='T';
566+
if( aoapps_mngr_apps[appix].flags & AOAPPS_MNGR_FLAGS_WITHREPAIR ) flags[2]='R';
567+
if( aoapps_mngr_apps[appix].flags & AOAPPS_MNGR_FLAGS_NEXTONERR ) flags[3]='E';
562568
const char* oled= aoapps_mngr_app_oled(appix);
563-
Serial.printf("%d %-10s %-4s %-5s %s\n",appix,name,mode,flags,oled);
569+
Serial.printf("%1d %-10s %-4s %-5s %s\n",appix,name,mode,flags,oled);
564570
}
565571

566572

@@ -569,7 +575,7 @@ static void aoapps_mngr_cmd_listall(int verbose) {
569575
if( verbose ) Serial.printf("# %-10s %-4s %5s %s\n","name","mode","flags","display name");
570576
for( int appix=0; appix<aoapps_mngr_app_count(); appix++ )
571577
aoapps_mngr_cmd_listone(appix);
572-
if( verbose ) Serial.printf("\nflags: T=withtopo R=withrepair, E=nextonerr\n");
578+
if( verbose ) Serial.printf("\nflags: H=hidden T=withtopo R=withrepair, E=nextonerr\n");
573579
}
574580

575581

@@ -582,7 +588,7 @@ static void aoapps_mngr_cmd( int argc, char * argv[] ) {
582588
if( argc!=2 ) { Serial.printf("ERROR: too many args\n" ); return; }
583589
aoapps_mngr_cmd_listall(argv[0][0]!='@');
584590
return;
585-
} else if( aocmd_cint_isprefix("switch",argv[1]) ) {
591+
} else if( aocmd_cint_isprefix("switch",argv[1]) || aocmd_cint_isprefix("hide",argv[1])) {
586592
if( argc!=3 ) { Serial.printf("ERROR: <app> missing\n" ); return; }
587593
// <app> is number?
588594
int appix;
@@ -601,8 +607,15 @@ static void aoapps_mngr_cmd( int argc, char * argv[] ) {
601607
}
602608
}
603609
if( appix==-1 ) { Serial.printf("ERROR: no app with name starting with '%s'\n",argv[2] ); return; }
604-
aoapps_mngr_switch(appix);
605-
if( argv[0][0]!='@' ) aoapps_mngr_cmd_listone(appix);
610+
if( aocmd_cint_isprefix("switch",argv[1]) ) {
611+
aoapps_mngr_switch(appix);
612+
if( argv[0][0]!='@' ) aoapps_mngr_cmd_listone(appix);
613+
} else if( aocmd_cint_isprefix("hide",argv[1]) ) {
614+
aoapps_mngr_apps[appix].flags ^= AOAPPS_MNGR_FLAGS_HIDDEN; // toggle hidden flag
615+
if( argv[0][0]!='@' ) aoapps_mngr_cmd_listone(appix);
616+
} else {
617+
AORESULT_ASSERT(false); // can not happen
618+
}
606619
return;
607620
} else if( aocmd_cint_isprefix("config",argv[1]) ) {
608621
aoapps_mngr_cmd_config(argc,argv);
@@ -621,6 +634,8 @@ static const char aoapps_mngr_cmd_longhelp[] =
621634
"- stops current app and starts <app>\n"
622635
"- <app> is either a name or an id (see list)\n"
623636
"- <app> 0 is the 'voidapp' (doing nothing): no interference with commands\n"
637+
"SYNTAX: apps hide <app>\n"
638+
"- toggles hide-flag of <app>; a hidden app is skipped in 'switchnext' list\n"
624639
"SYNTAX: apps config [...]\n"
625640
"- without arguments, shows which apps offer configuration\n"
626641
"- with app name shows help for configuration of that app\n"
@@ -630,6 +645,8 @@ static const char aoapps_mngr_cmd_longhelp[] =
630645
;
631646

632647

648+
649+
633650
/*!
634651
@brief Registers the "apps" command with the command interpreter.
635652
@return Number of remaining registration slots (or -1 if registration failed).

src/aoapps_mngr.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,11 @@ typedef void (*aoapps_mngr_cmd_t)( int argc, char * argv[] );
3939

4040
// Extra features can be enabled in the app manager
4141
#define AOAPPS_MNGR_FLAGS_NONE 0x00
42-
#define AOAPPS_MNGR_FLAGS_WITHTOPO 0x01
43-
#define AOAPPS_MNGR_FLAGS_WITHREPAIR 0x02
44-
#define AOAPPS_MNGR_FLAGS_NEXTONERR 0x04
45-
#define AOAPPS_MNGR_FLAGS_ALL (AOAPPS_MNGR_FLAGS_WITHTOPO | AOAPPS_MNGR_FLAGS_WITHREPAIR | AOAPPS_MNGR_FLAGS_NEXTONERR )
42+
#define AOAPPS_MNGR_FLAGS_HIDDEN 0x01
43+
#define AOAPPS_MNGR_FLAGS_WITHTOPO 0x02
44+
#define AOAPPS_MNGR_FLAGS_WITHREPAIR 0x04
45+
#define AOAPPS_MNGR_FLAGS_NEXTONERR 0x08
46+
#define AOAPPS_MNGR_FLAGS_ALL (AOAPPS_MNGR_FLAGS_HIDDEN | AOAPPS_MNGR_FLAGS_WITHTOPO | AOAPPS_MNGR_FLAGS_WITHREPAIR | AOAPPS_MNGR_FLAGS_NEXTONERR )
4647

4748
// To register an app pass its (identifier and oled) name, help text for the two buttons, feature flags, pointers to its three handlers, command handler and command help. Asserts when no more free slots.
4849
void aoapps_mngr_register(const char * name, const char * oled, const char * xlbl, const char * ylbl, int flags, aoapps_mngr_start_t start, aoapps_mngr_step_t step, aoapps_mngr_stop_t stop, aoapps_mngr_cmd_t cmd, const char * help);

src/aoapps_swflag.cpp

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ GOAL
5555

5656

5757
// We have a list of flag painters (indices)
58-
#define AOMW_SWFLAGS_ANIM_NUMFLAGS 4 // dictated by number of buttons in IOX
59-
static int aomw_swflags_anim_pix[AOMW_SWFLAGS_ANIM_NUMFLAGS] = {
58+
#define AOAPPS_SWFLAG_ANIM_NUMFLAGS 4 // dictated by number of buttons in IOX
59+
static int aomw_swflag_anim_pix[AOAPPS_SWFLAG_ANIM_NUMFLAGS] = {
6060
AOMW_FLAG_PIX_DUTCH, AOMW_FLAG_PIX_MALI, AOMW_FLAG_PIX_EUROPE, AOMW_FLAG_PIX_ITALY
6161
};
6262

@@ -88,15 +88,15 @@ static aoresult_t aoapps_swflag_anim() {
8888
// IOX absent: switch flags every AOAPPS_SWFLAG_ANIM_MS
8989
if( millis()-aoapps_swflag_anim_lastms > AOAPPS_SWFLAG_ANIM_MS ) {
9090
aoapps_swflag_anim_lastms= millis();
91-
flagix= (aoapps_swflag_anim_flagix+1) % AOMW_SWFLAGS_ANIM_NUMFLAGS;
91+
flagix= (aoapps_swflag_anim_flagix+1) % AOAPPS_SWFLAG_ANIM_NUMFLAGS;
9292
}
9393
}
9494

9595
// Different flag selected? Paint it
9696
if( aoapps_swflag_anim_flagix!=flagix ) {
9797
aoapps_swflag_anim_flagix = flagix;
9898
// Paint the flag
99-
result= aomw_flag_painter(aomw_swflags_anim_pix[aoapps_swflag_anim_flagix])();
99+
result= aomw_flag_painter(aomw_swflag_anim_pix[aoapps_swflag_anim_flagix])();
100100
if( result!=aoresult_ok ) return result;
101101
// Highlight the associated indicator LED
102102
if( aoapps_swflag_anim_ioxpresent ) {
@@ -130,7 +130,7 @@ static aoresult_t aoapps_swflag_buttons_check() {
130130
aomw_topo_dim_set(dim); // function clips (no need to do that here)
131131
// Serial.printf("dim %d\n", aomw_topo_dim_get());
132132
// Repaint the flag
133-
aoresult_t result= aomw_flag_painter(aomw_swflags_anim_pix[aoapps_swflag_anim_flagix])();
133+
aoresult_t result= aomw_flag_painter(aomw_swflag_anim_pix[aoapps_swflag_anim_flagix])();
134134
if( result!=aoresult_ok ) return result;
135135
}
136136
return aoresult_ok;
@@ -154,37 +154,37 @@ static int aoapps_swflag_cmd_find( const char * flag ) {
154154

155155
// Show on Serial which are the four flags
156156
static void aoapps_swflag_cmd_show( ) {
157-
for( int flagix=0; flagix<AOMW_SWFLAGS_ANIM_NUMFLAGS; flagix++ ) {
158-
Serial.printf("SW%d %s\n", flagix, aomw_flag_name(aomw_swflags_anim_pix[flagix]) );
157+
for( int flagix=0; flagix<AOAPPS_SWFLAG_ANIM_NUMFLAGS; flagix++ ) {
158+
Serial.printf("SW%d %s\n", flagix, aomw_flag_name(aomw_swflag_anim_pix[flagix]) );
159159
}
160160
}
161161

162162

163-
// The handler for the "apps config swflags" command
163+
// The handler for the "apps config swflag" command
164164
static void aoapps_swflag_cmd_main( int argc, char * argv[] ) {
165165
AORESULT_ASSERT( argc>3 );
166166
if( aocmd_cint_isprefix("list",argv[3]) ) {
167-
if( argc!=4 ) { Serial.printf("ERROR: 'swflags' has too many args\n" ); return; }
167+
if( argc!=4 ) { Serial.printf("ERROR: 'swflag' has too many args\n" ); return; }
168168
for( int pix=0; pix<aomw_flag_count(); pix++ ) {
169169
Serial.printf(" %s\n", aomw_flag_name(pix) );
170170
}
171171
return;
172172
} else if( aocmd_cint_isprefix("get",argv[3]) ) {
173-
if( argc!=4 ) { Serial.printf("ERROR: 'swflags' has too many args\n" ); return; }
173+
if( argc!=4 ) { Serial.printf("ERROR: 'swflag' has too many args\n" ); return; }
174174
aoapps_swflag_cmd_show();
175175
return;
176176
} else if( aocmd_cint_isprefix("set",argv[3]) ) {
177-
if( argc!=8 ) { Serial.printf("ERROR: 'swflags' expects <flag1> <flag2> <flag3> <flag4>\n" ); return; }
178-
AORESULT_ASSERT( AOMW_SWFLAGS_ANIM_NUMFLAGS==4 );
177+
if( argc!=8 ) { Serial.printf("ERROR: 'swflag' expects <flag1> <flag2> <flag3> <flag4>\n" ); return; }
178+
AORESULT_ASSERT( AOAPPS_SWFLAG_ANIM_NUMFLAGS==4 );
179179
// check if all entered flags exist, if so, copy them over
180180
for( int flagix=0; flagix<4; flagix++ )
181-
if( aoapps_swflag_cmd_find(argv[4+flagix])==-1 ) { Serial.printf("ERROR: 'swflags' expects flag name, not '%s'\n", argv[4+flagix] ); return; }
181+
if( aoapps_swflag_cmd_find(argv[4+flagix])==-1 ) { Serial.printf("ERROR: 'swflag' expects flag name, not '%s'\n", argv[4+flagix] ); return; }
182182
for( int flagix=0; flagix<4; flagix++ )
183-
aomw_swflags_anim_pix[flagix]= aoapps_swflag_cmd_find(argv[4+flagix]);
183+
aomw_swflag_anim_pix[flagix]= aoapps_swflag_cmd_find(argv[4+flagix]);
184184
if( argv[0][0]!='@' ) aoapps_swflag_cmd_show();
185185
return;
186186
} else {
187-
Serial.printf("ERROR: 'swflags' has unknown argument (%s)\n",argv[3] ); return;
187+
Serial.printf("ERROR: 'swflag' has unknown argument (%s)\n",argv[3] ); return;
188188
}
189189
}
190190

@@ -222,17 +222,17 @@ static aoresult_t aoapps_swflag_start() {
222222
aoapps_swflag_anim_ioxpresent= result==aoresult_ok;
223223
// Init IOX
224224
if( aoapps_swflag_anim_ioxpresent ) {
225-
Serial.printf("swflags: using I/O-expander %02x on SAID %03x \n",AOMW_IOX_DADDR7,addr);
225+
Serial.printf("swflag: using I/O-expander %02x on SAID %03x \n",AOMW_IOX_DADDR7,addr);
226226
result= aomw_iox_init( addr );
227227
if( result!=aoresult_ok ) return result;
228228
} else {
229-
Serial.printf("swflags: no I/O-expander found, cycling flags\n");
229+
Serial.printf("swflag: no I/O-expander found, cycling flags\n");
230230
}
231231

232232
// Select first flag
233233
aoapps_swflag_anim_flagix= 0;
234234
// Paint the selected flag
235-
result= aomw_flag_painter(aomw_swflags_anim_pix[aoapps_swflag_anim_flagix])();
235+
result= aomw_flag_painter(aomw_swflag_anim_pix[aoapps_swflag_anim_flagix])();
236236
if( result!=aoresult_ok ) return result;
237237
// Highlight the associated indicator LED
238238
if( aoapps_swflag_anim_ioxpresent ) {

0 commit comments

Comments
 (0)