{"id":22923493,"url":"https://github.com/ams-osram/osp_aoapps","last_synced_at":"2026-05-02T19:34:15.698Z","repository":{"id":265482306,"uuid":"869433102","full_name":"ams-OSRAM/OSP_aoapps","owner":"ams-OSRAM","description":"A library with reusable \"apps\" for OSP chains.","archived":false,"fork":false,"pushed_at":"2025-03-03T11:05:01.000Z","size":88,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-01T14:49:50.812Z","etag":null,"topics":["arduino","as1163","e3731i","library","osp","rgb-led"],"latest_commit_sha":null,"homepage":"https://github.com/ams-OSRAM/OSP_aotop","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ams-OSRAM.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"license.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-10-08T09:36:16.000Z","updated_at":"2025-03-03T11:04:01.000Z","dependencies_parsed_at":"2024-11-29T15:40:46.912Z","dependency_job_id":"6fb8beef-eb43-4c40-bcc0-0cfd527ffe9c","html_url":"https://github.com/ams-OSRAM/OSP_aoapps","commit_stats":null,"previous_names":["ams-osram/osp_aoapps"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/ams-OSRAM/OSP_aoapps","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ams-OSRAM%2FOSP_aoapps","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ams-OSRAM%2FOSP_aoapps/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ams-OSRAM%2FOSP_aoapps/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ams-OSRAM%2FOSP_aoapps/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ams-OSRAM","download_url":"https://codeload.github.com/ams-OSRAM/OSP_aoapps/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ams-OSRAM%2FOSP_aoapps/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32547650,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-02T19:18:06.202Z","status":"ssl_error","status_checked_at":"2026-05-02T19:16:21.335Z","response_time":132,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["arduino","as1163","e3731i","library","osp","rgb-led"],"created_at":"2024-12-14T08:15:51.704Z","updated_at":"2026-05-02T19:34:15.684Z","avatar_url":"https://github.com/ams-OSRAM.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# OSP ReusableApps aoapps\n\nLibrary \"OSP ReusableApps aoapps\", usually abbreviated to \"aoapps\", \nis one of the **aolibs**; short for Arduino OSP libraries from ams-OSRAM.\nThis suite implements support for chips that use the Open System Protocol, \nlike the AS1163 (\"SAID\") or the OSIRE E3731i (\"RGBi\").\nThe landing page for the _aolibs_ is on \n[GitHub](https://github.com/ams-OSRAM/OSP_aotop).\n\n\n## Introduction\n\nLibrary _aoapps_ is a library with reusable \"apps\" for OSP chains.\nMultiple apps form one _firmware image_ or _executable_ for the ESP32 \nas explained below.\n\n\n![aoapps in context](extras/aolibs-aoapps.drawio.png)\n\n\nThis library contains several apps. In this context, and app is a module \nthat exposes a `step()` function, which is constantly called from the \nmain loop, and which manages the animation implemented by the app.\n\nIn addition to the apps, this library also contains an _app manager_. \nA sketch includes the manager and registers one or more apps, \neither from this library or from elsewhere (self developed). Typically \nthe \"A\" button on the OSP32 board is used to tell the app manager\nto switch from one app to the next.\n\nSee below a high level sketch of the app (manager) architecture.\n\n```cpp\nvoid apps_register() {\n  aoapps_aniscript_register();\n  aoapps_runled_register();\n  aoapps_swflag_register();\n  aoapps_dither_register();\n}\n\n\nvoid setup() {\n  ...\n\n  // Init the Library\n  aoapps_init();\n  \n  // Register all apps\n  apps_register();\n\n  // Start the first app\n  aoapps_mngr_start();\n}\n\n\nvoid loop() {\n  // Check physical buttons\n  aoui32_but_scan();\n\n  // Switch to next app when A was pressed\n  if( aoui32_but_wentdown(AOUI32_BUT_A) ) aoapps_mngr_switchnext();\n\n  // Let current app progress\n  aoapps_mngr_step();\n}\n```\n\n\n## Examples\n\nThis library comes with the following examples.\nYou can find them in the Arduino IDE via \n[File \u003e Examples \u003e OSP ReusableApps aoapps \u003e ...](examples):\n\n- **aoapps_switch** ([source](examples/aoapps_switch))  \n  This demo implements an executable with two (dummy) apps, \n  App1 and App2, which are part of the example.\n  By pressing but A, the user can switch between the apps.\n  The name of the active app is shown on the OLED.\n  The green and red signaling LED show heart beat and error.\n  App1 shows how to process button presses.\n  App2 goes into error after a while (to show that the green heart beat \n  LED stops and the red error LED switches on).\n\n- **aoapps_runled** ([source](examples/aoapps_runled))  \n  This demo shows how to run an app.\n  It uses the \"runled\" app, which has been made to expose its internals;\n  the start, step and stop function.\n\n- **aoapps_sensors** ([source](examples/aoapps_sensors))  \n  This is a template for a sketch using multiple apps and the app manager.\n  It contains two apps (\"runled\" and \"sensors\"). The \"A\" button switches to \n  the next app. For simplicity the command interpreter has not been added. \n\n\n## Module architecture\n\nThis library contains several modules, see figure below (arrows indicate `#include`).\n\n![Modules](extras/aoapps-modules.drawio.png)\n\n- **aomw_mngr** (`aomw_mngr.cpp` and `aomw_mngr.h`) is the only non-app module.\n  It is the app manager. It implements a register of apps in the\n  sketch. It implements functions to start, step and stop an app. These\n  are called from the main loop, and forwarded to the running app.\n  In practice, the `step()` function is constantly called from the main loop \n  and manages the animation implemented by the app.\n  \n  This module also implements a command (to be registered with `aocmd_cint` \n  if so desired). This handler allows the user to see which apps are \n  available, which is running, and it allows to switch the running app.\n  \n- **aoapps_runled** (`aoapps_runled.cpp` and `aoapps_runled.h`) is one of the stock apps.\n  - There is a \"virtual cursor\" that runs from the begin of the chain to the end and then back.\n  - Chain length and node types are auto detected.\n  - Every 25ms the cursor advances one LED and paints that in the current color.\n  - Every time the cursor hits the begin or end of the chain, it steps color.\n  - Color palette: red, yellow, green, cyan, magenta.\n  - The X and Y buttons control the dim level (RGB brightness).\n  - The goal is to show that various OSP nodes can be mixed and have color/brightness matched.\n\n- **aoapps_swflag** (`aoapps_swflag.cpp` and `aoapps_swflag.h`) is one of the stock apps.\n  - Shows one (static) flag at a time, e.g. the Dutch national flag red/white/blue spread over the OSP chain.\n  - Tries to find a SAID with an I2C bridge with a \"selector\", an I/O-expander with four buttons and four indicator LEDs.\n  - If there is no selector, shows four static flags switching on a time basis.\n  - If there are multiple selectors the first SAIDbasic one is taken, or the first SAIDsense when no SAIDbasic.\n  - When a selector is found the four buttons select which flag to show.\n  - The indicator LEDs indicate which button/flag was selected.\n  - The X and Y buttons control the dim level (RGB brightness).\n  - This app adds a command to configure which four flags will be shown.\n  - The goal is to show a \"sensor\" (button) being accessible from the root MCU (the ESP).\n\n- **aoapps_dither** (`aoapps_dither.cpp` and `aoapps_dither.h`) is one of the stock apps.\n  - The LEDs are in a dimming cycle (dim up, then dim down, then up again, etc).\n  - All LEDs dim synchronously and at the same level (so RGBs look white).\n  - Dithering (SAID LED driver feature) can be enabled/disabled.\n  - The X button toggles dim cycling on/off.\n  - The Y button toggles dithering on/off.\n  - The goal is to show the effect of dithering.\n\n- **aoapps_aniscript** (`aoapps_aniscript.cpp` and `aoapps_aniscript.h`) is one of the stock apps.\n  - Plays a light show as defined by an animation script.\n  - Tries to find a SAID with an I2C bridge with an EEPROM.\n  - If there is an external EEPROM stick (I2C address 0x51) it favors that over an internal EEPROM (address 0x50).\n  - If there are multiple (of the same kind, external or internal) the first one is taken.\n  - If no EEPROM is found, uses the heartbeat script included in the firmware.\n  - If an EEPROM is found, loads the script from the EEPROM and plays that.\n  - The internal EEPROM (on the SAIDbasic board) contains the rainbow script.\n  - External EEPROMs are flashed with bouncing-block and color-mix.\n  - The X and Y buttons control the FPS level (frames-per-second animation speed).\n  - The goal is to show that the root MCU can access I2C devices (EEPROM) e.g. for calibration values.\n  - Note, the tool [eepromflasher](https://github.com/ams-OSRAM/OSP_aotop/tree/main/examples/eepromflasher)\n    allows flashing EEPROMs with the various animation scripts.\n\n- **aoapps_sensors** (`aoapps_sensors.cpp` and `aoapps_sensors.h`) is one of the stock apps.\n  - Measures the temperature using an AS6212 temperature sensor.\n  - Measures the angle of the knob using an AS5600 rotary sensor.\n  - Measures the light intensity using an SFH5721 ambient light sensor.\n  - Only one of the three sensors is active at one time.\n  - To change the active sensor, either press the X button to cycle to next,\n    or press one of the selector buttons TEMP, ROTARY, ALS (and EXT) on \n    the SAIDsense board.\n  - The indicator LED (paired with the selector button) of the active \n    sensor switches on.\n  - The quad 7-segment display shows the readout of the active sensor.\n  - When the temperature sensor is active, the OSP chains shows a red part\n    and a blue part that change with temperature.\n  - When the angle sensor is active, the knob angle (0-360) determines how \n    many triplets are yellow (0..num triplets).\n  - When ambient light sensor is active, the higher the ambient light level,\n    the greener the triplets.\n  - This app is written for the SAIDsense board.\n  - For backward compatibility with older board, this app supports a board \n    without light sensor, rotary sensor, or selector.\n  - The Y button scrolls the type number of the sensor.\n  - The X button toggles between temperature, angle or light sensor being active.\n  - Upon a press the display shows the units for a short moment.\n  - Active sensor has its indicator LED on.\n  - Goal is to show a sensor can be used in OSP (eg for climate control, light adaption).\n\n\n## API\n\nThe header [aoapps.h](src/aoapps.h) contains the API of this library.\nIt includes the module headers [aoapps_mngr.h](src/aoapps_mngr.h), \n[aoapps_runled.h](src/aoapps_runled.h), [aoapps_swflag.h](src/aoapps_swflag.h), \n[aoapps_dither.h](src/aoapps_dither.h), and\n[aoapps_aniscript.h](src/aoapps_aniscript.h).\nThe headers contain little documentation; for that see the module source files. \n\n### aoapps\n\n- `aoapps_init()` to initialize the library (the apps manager).\n- `AOAPPS_VERSION`  identifies the version of the library.\n\n\n### aoapps_mngr\n\nThere is an init function, but that is called from the library's init.\n- `void aoapps_mngr_init()`.\n\nAn important aspect of the app manager is app registration. \n- `aoapps_mngr_register(...)` registers an app (its name, some OLED labels, \n  its start, step an stop functions, an optional command handler, and some flags).\n- `aoapps_mngr_start_t`, `aoapps_mngr_step_t`, `aoapps_mngr_stop_t` types for\n  to start, step and stop function.\n- `AOAPPS_MNGR_FLAGS_HIDDEN`, `AOAPPS_MNGR_FLAGS_WITHTOPO`, \n  `AOAPPS_MNGR_FLAGS_WITHREPAIR` and `AOAPPS_MNGR_FLAGS_NEXTONERR` \n  registration flags.\n- `AOAPPS_MNGR_REGISTRATION_SLOTS` maximum number of apps that can \n  be registered.\n\nThe top level sketch needs to start an app, but also continuously step it.\n\n- `aoapps_mngr_start(appix)` start an app; e.g. called from `setup()`.\n- `aoapps_mngr_step()` step an app continuously for its animation; e.g. called from `loop()`.\n- `aoapps_mngr_stop()` stop an app (to switch off hardware), before starting another app.\n- `aoapps_mngr_switch(appix)` shorthand for stopping current app and starting app `appix`.\n- `aoapps_mngr_switchnext()` shorthand for stopping current app and starting next app (in registration order).\n\nThere are some observers of the state of the running app, \ntypically these are not needed by the application.\n\n- `aoapps_mngr_app_appix()` index of current app.\n- `aoapps_mngr_app_running()` indicates if current app is running.\n\nThere are some observers for the registry, \ntypically these are not needed by the application.\n\n- `aoapps_mngr_app_count()` count of registered apps.\n- `aoapps_mngr_app_name(appix)` (short) name (identifier) of an app\n- `aoapps_mngr_app_oled(appix)` (long) name (human readable on OLED) of an app.\n\nThis module also implements a command (to be registered with `aocmd_cint` if\nso desired). This handler allows the user manage apps.\n\n- `aoapps_mngr_cmd_register()` registers the app manager with the command interpreter.\n  See \"Configuration commands\" below for details.\n\n\n### aoapps_runled \n\n- `aoapps_runled_register()` registers the runled app with the app manager.\n\n- `aoapps_runled_start()`, `aoapps_runled_step()`, `aoapps_runled_stop()`\n   are external, making it easier to demo this app without the manager.\n   For the other apps these functions are kept private.\n\n\n### aoapps_swflag\n\n- `aoapps_swflag_register()` registers the swflag app with the app manager.\n- `aoapps_swflag_resethw()` resets the selector, thereby \n  switching off the indicator LEDs attached to it. \n  This helps reset the PCB state when the MCU is reset.\n\n\n### aoapps_dither\n\n- `aoapps_dither_register()` registers the dither app with the app manager.\n\n\n### aoapps_aniscript\n\n- `aoapps_aniscript_register()` registers the aniscript app with the app manager.\n\n\n### aoapps_sensors\n\n- `aoapps_sensors_register()` registers the sensors app with the app manager.\n- `aoapps_sensors_resethw()` resets the selector and the quad 7-segment display, \n  thereby switching off the LEDs attached to them. \n  This helps reset the PCB state when the MCU is reset.\n\n\n## Execution architecture\n\nTo keep execution architecture simple, top-level sketches employ a \n\"main loop\", e.g. the `loop()` function in Arduino. The down side of a \nmain loop architecture is that individual actions (function calls) \nexecuted by the main loop must be short. That way they can be interleaved\nand deadlines are not exceeded.\n\nFor this reason, apps have a start/step/stop interface.\nThe start is called once, and sets up the internal state machine of the app.\nNext the step is continuously called, and the app uses these triggers\nto advance its state machine, in effect running some kind of animation\nor sensor polling. The stop is usually empty, but some apps need to do some\ncleanup (reset app specific hardware).\n\nMost apps are build on top of the `aomw_topo` module since this abstracts\naway the differences between various node types; apps then simply query \nhow many RGB triplets there are an animate over all of them. To make using \ntopo simple, app registration can pass the flag `AOAPPS_MNGR_FLAGS_WITHTOPO`.\nWith this flag the app manager will first build the topo map \n(in many \"steps\") before calling the app's start.\n\nThe OSP32 board has a rather poor power supply (1A USB). In larger demo's, \nespecially with higher levels of RGB brightness, nodes tend to be hit by \n\"under voltage faults\", making their LEDs switch off. When an app registers \nwith the flag `AOAPPS_MNGR_FLAGS_WITHREPAIR`, the app manager will \nperiodically broadcast a \"clear error\" and \"go active\" telegram to mitigate\nthis problem. By the way, it is also possible to power the OSP32 board\nvia a pin header instead of via USB, bypassing the 1A USB limit.\n\nIf an app runs into errors, its `step()` will return an error code. The\napp manager normally flashes the green heart beat LED, but will then stop\ndoing that and instead switch on the red error LED. It will also show the\nerror on the OLED. In effect that \"app crashed\" and nothing will happen \nanymore. The user is still able to press A to switch to the next app. More\npresses on A will eventually re-start the offending app (which might crash \nagain). When an app registers with the flag `AOAPPS_MNGR_FLAGS_NEXTONERR`, \nthe app manager will, when that app returns an error, do as before (stop\nheart beat, switch on red LED, show error on OLED), but after a time-out start\nthe next app.\n\nThe list of registered apps can become long. For a specific demo, apps\ncan be hidden, so that the demonstration can focus on specific apps. \nWhen an app is hidden, it is skipped in the `switchnext()` cycle, which is \ntypically executed when pressing the A button. The voidapp registers itself \nas hidden, for other apps hide them via the command `apps hide \u003capp\u003e`, \ne.g. in `boot.cmd`.\n\nSome apps have configuration parameters that can be observed and changed via\na command. The command handler can also be passed during app registration, \nsee the next chapter.\n\n\n## Configuration commands\n\nThis module also implements a command `apps` (to be registered with \n`aocmd_cint` if so desired). This handler allows the user to manage the apps.\n\n- show a list of all registered apps\n- switch to a different app\n- configure an app as hidden\n- configure an app via its handler\n\nIf an individual app has something to configure, its shall pass its \nconfiguration handler (just another command handler) during its registration \nwith the app manager. As an example see the registration of the `swflag` app:\n\n```cpp\n// The registration function for app swflag.\nvoid aoapps_swflag_register() {\n  aoapps_mngr_register(\"swflag\", \"Switch flag\", \"dim -\", \"dim +\", \n    AOAPPS_MNGR_FLAGS_WITHTOPO | AOAPPS_MNGR_FLAGS_WITHREPAIR,  \n    aoapps_swflag_start, aoapps_swflag_step, aoapps_swflag_stop, \n    aoapps_swflag_cmd_main, aoapps_swflag_cmd_help );\n}\n```\n\nOn the last line we see that the registration includes a configuration \nhelp string `aoapps_swflag_cmd_help` and a configuration command function \n`aoapps_swflag_cmd_main`. \n\nThe command handlers that configure and app are not top-level commands,\nrather they are sub-commands of the `apps config` command.\n\nWhen running `apps config` a list is shown of configurable apps.\nThe help string for an app is shown when the user executes the \n`config` for that app.\n\n```cpp\n\u003e\u003e apps config\nConfigurable apps\n swflag\n\u003e\u003e apps config swflag\nSYNTAX: apps config swflag list\n- shows available flags\nSYNTAX: apps config swflag get\n- shows configured flags\nSYNTAX: apps config swflag set \u003cflag1\u003e \u003cflag2\u003e \u003cflag3\u003e \u003cflag4\u003e\n- configures four flags (from list)\n```\n\nWe see that the `swflag` app has three configuration commands: `list` shows\nwhich flags are available, `get` shows which four flags are configured (that \nis, associated with the four buttons) and `set` configures four flags.\n\nTypically, the wanted four flags would be set with `file record` in \nthe `boot.cmd` which is executed at startup, for example:\n`apps config sw set  dutch mali europe italy`.\n\n\n## The voidapp\n\nThe app manager has one app always registered, the \"voidapp\". This app\ndoes nothing. It does not start with topo init, its start, step and stop \nare empty, and it does not deploy repair actions, but it is hidden by default.\n\nThis app is useful when the user wants to take over control via the\nSerial over USB command interface. If the user gives the command\n`apps switch voidapp` (or by app index `apps switch 0`, or the short \nhands `a s v` respectively `a s 0`) the app manager switches to the \nvoidapp.\n\nSince the voidapp does not do anything, the user is in full control\nof the OSP chain, without app telegrams interfering.\n\n\n## Version history _aoapps_\n\n- **2026 April 29 , 0.4.1**\n  - The `apps list` now has 12 positions for name.\n\n- **2025 September 17, 0.4.0**\n  - Updated documentation.\n  - `aoapps_swflag.cpp` switched to new driver `aomw_iox4b4l`; it also supports selector SAIDsense (next to the one on SAIDbasic).\n  - Added module `aoapps_sensors` (to be used with the SAIDsense demo board) and example `aoapps_sensors.ino`.\n  - Added link to examples.\n\n- **2025 March 3, 0.3.0**\n  - Added the feature that an app can be hidden; the `hide` commands toggles.\n  - The voidapp no longer is hardwired hidden; it uses the new hidden feature.\n  - Corrected `swflags` to `swflag`.\n  - Fixed prefix error in `aoapps_swflag.cpp`.\n  - Fixed documentation error for `aoapps_init()`.\n\n- **2024 November 29, 0.2.10**\n  - Fixed typos (including I/O-expander).\n\n- **2024 October 8, 0.2.9**  \n  - Fixed parsing problems Doxygen.\n  - Prefixed `modules.drawio.png` with library short name.\n  - Added example `aoapps_runled.ino`.\n  - Moved domain from `github.com/ams-OSRAM-Group` to `github.com/ams-OSRAM`.\n  - Term cleanup (\"indicator LEDs\" and \"I/O-expander\").\n  - Cleanup of `readme.md`.\n  - Added BEHAVIOR to `aoapps_switch.ino`.\n  - `aoapps_mngr` now uses `\"apps\"` in error messages, no longer `\"mngr\"`.\n  - More uniform error messages in command `swflags`.\n  - Now prints flags in `apps list` (with help, fixed bug).\n  - Added feature `AOAPPS_MNGR_FLAGS_NEXTONERR` in app manager (next app on error).\n  - Added links in `readme.md` for all example sketches.\n  - Fixed typos in `aoapps_xxx_register()` documentation.\n  - Corrected link to GitHub from `aotop` to `OSP_aotop`.\n  - Remove \"oalib\" from `sentence=` in `library.properties`.\n  - Arduino name changed from `OSP Reusable apps - aoapps` to `OSP ReusableApps aoapps`.\n  - Renamed dir `extra` to `extras`.\n  - `license.txt` line endings changed from LF to CR+LF.\n\n- **2024 July 02, 0.2.8**  \n  - Initial release candidate.\n\n\n(end)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fams-osram%2Fosp_aoapps","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fams-osram%2Fosp_aoapps","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fams-osram%2Fosp_aoapps/lists"}