# AMB82-MINI Web sockets: why "start model"?

**URL:** <https://forum.amebaiot.com/t/amb82-mini-web-sockets-why-start-model/5109>\
**Category:** Multimedia\
**Created:** [October 2, 2026, 1:17am UTC](https://forum.amebaiot.com/t/amb82-mini-web-sockets-why-start-model/5109 "2026-10-02T01:17:46Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![jimmiedave](https://avatars.discourse-cdn.com/v4/letter/j/bbe5ce/32.png) [@jimmiedave](https://forum.amebaiot.com/u/jimmiedave)\
**Post date:** [October 2, 2026, 1:17am UTC](https://forum.amebaiot.com/t/amb82-mini-web-sockets-why-start-model/5109/1 "2026-10-02T01:17:46Z")

</div>

I’m using the 82-mini as a streaming camera, and props to you guys for the Web sockets demo. I’ve figured how to modify the htdocs files, have things generally working very well, but on the serial monitor, I see:

```auto
23:57:23.630 -> 
Processing command: {"cmd":"stop_model","param":["yolo4t","retinaface","mobilenetface","yamnet","object_tracking","palm_detection","hand_landmark"]}
23:57:23.630 -> 
Received stop_model command

23:57:23.630 -> 
Process stop_model command

23:57:23.662 -> 
stop_model called

23:57:23.662 -> 
[wsfs_echo] received message (32 bytes, opcode=1)
23:57:23.662 -> 
Processing command: {"cmd":"start_model","param":[]}
23:57:23.662 -> 
Received start_model command

23:57:23.662 -> 
Process start_model command

23:57:23.662 -> 
start_model called

23:57:23.662 -> 
[wsfs_echo] received message (45 bytes, opcode=1)
23:57:23.662 -> 
Processing command: {"cmd":"get_model_meta","param":["classify"]}
23:57:23.695 -> 
Received get_model_meta command

```

Why is a streaming webcam demo doing ANYTHING with a classification model? Where are these commands coming from? Doesn’t look like anywhere in the example code.

I’m looking for smoothest possible stream, don’t want it wasting a cycle on a classifier: I’m not using that stuff at all.

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex016/uploads/ameba/original/2X/7/7009caf971627f868f3de3d34312aff2d14c61e3.png) [@system](https://forum.amebaiot.com/u/system)\
**Post date:** [October 2, 2026, 1:17am UTC](https://forum.amebaiot.com/t/amb82-mini-web-sockets-why-start-model/5109/2 "2026-10-02T01:17:49Z")

</div>

👋 Thanks for posting!

For documentation, SDK resources, FAQs, and community guidelines, please visit: [here](https://forum.amebaiot.com/t/forum-community-guidelines-and-resources/4969)

For commercial users, if you would like to have dedicated technical support or to connect with us, please fill in the [Private User Form](https://forms.cloud.microsoft/r/FK9WxDhvDg)

Happy building with Ameba!

* * *

👋 感謝您的分享！

如需查閱技術文件、SDK 資源、常見問題及社群指南，請參考: [這裡](https://forum.amebaiot.com/t/forum-community-guidelines-and-resources/4969)

若您是商業用戶，希望獲得專屬技術支援或與我們聯繫，請填寫 [Private User Form (商業用戶表單)](https://forms.cloud.microsoft/r/FK9WxDhvDg)

祝您使用 Ameba 開發順利！

---

<div class="post-metadata">

**Author:** ![KevinKL](https://sea2.discourse-cdn.com/flex016/user_avatar/forum.amebaiot.com/kevinkl/32/2632_2.png) [@KevinKL](https://forum.amebaiot.com/u/KevinKL)\
**Post date:** [October 2, 2026, 12:15pm UTC](https://forum.amebaiot.com/t/amb82-mini-web-sockets-why-start-model/5109/3 "2026-10-02T12:15:35Z")

</div>

Hi @jimmiedave ,

These commands are not coming from the example C code.

They come from the browser page and they spend zero cycles on classification.

**Where the commands are actually sent**

Your board serves an HTTP page (htdocs.bin from websocket\_viewer\_web\_source.zip). That page’s js/ai\_player.js opens a WebSocket back to the board and has  
an onopen handler that runs on every connect — automatically, whether or not you asked for any AI. So the start\_model / stop\_model / get\_model\_meta messages you see in the serial log are just the page doing its standard “AI handshake”, so it always sends these regardless of what the firmware actually supports. Nothing in `example_websocket_viewer.c` calls them.

**Do they waste a cycle on your stream?** No.

On the device these all land in the dispatcher in `component/application/websocket_viewer/web_service.c`, and the handlers are empty stubs:

> static void start\_model(wsfs\_connection\_t \*conn, void \*p)  
> {  
> printf(“%s called\r\n”, **FUNCTION** ); // ← no-op  
> }  
> static void stop\_model(wsfs\_connection\_t \*conn, void \*p)  
> {  
> printf(“%s called\r\n”, **FUNCTION** ); // ← no-op  
> }

`get_model_meta` isn’t even registered in the command table — it just prints “Received … command” and is dropped. No model is loaded, nothing runs at runtime; only a  
couple of printfs happen once at connect time. Your H.264 encode → WebSocket send path is completely untouched.

**What to do about the log noise**

- Fix the page (permanent): in ai\_player.js, delete the stopModel/startModel/getModelMeta lines from onopen (~line 1528), or just call startVideo() there.
- Silence on device (quick): remove the three stubs from app\_cmd in web\_service.c — streaming still works fine, you just lose the “Received …/Process …” prints for them.

Thank you.

---

<div class="post-metadata">

**Author:** ![jimmiedave](https://avatars.discourse-cdn.com/v4/letter/j/bbe5ce/32.png) [@jimmiedave](https://forum.amebaiot.com/u/jimmiedave)\
**Post date:** [October 2, 2026, 1:19pm UTC](https://forum.amebaiot.com/t/amb82-mini-web-sockets-why-start-model/5109/4 "2026-10-02T13:19:52Z")

</div>

Very clear. Thanks so much!

---

<div class="post-metadata">

**Author:** ![jimmiedave](https://avatars.discourse-cdn.com/v4/letter/j/bbe5ce/32.png) [@jimmiedave](https://forum.amebaiot.com/u/jimmiedave)\
**Post date:** [October 2, 2026, 11:44pm UTC](https://forum.amebaiot.com/t/amb82-mini-web-sockets-why-start-model/5109/5 "2026-10-02T23:44:36Z")

</div>

That worked great, thanks again.

Is there any already-created way I can reach into the browser DOM or have the browser’s Javascript ask for data to write into it?

I’d like to be able to set the unit-dependent data (WiFi creds, manual exposure, and **browser window title** ) with info pulled up from an SD card, which lives, of course, on the Arduino side of things. I can have the Arduino “know” what the browser title should be, but I’m interested in whether there’s an API pipe into the Javascript for passing info back.

---

<div class="post-metadata">

**Author:** ![KevinKL](https://sea2.discourse-cdn.com/flex016/user_avatar/forum.amebaiot.com/kevinkl/32/2632_2.png) [@KevinKL](https://forum.amebaiot.com/u/KevinKL)\
**Post date:** [October 5, 2026, 5:57am UTC](https://forum.amebaiot.com/t/amb82-mini-web-sockets-why-start-model/5109/6 "2026-10-05T05:57:44Z")

</div>

Hi @jimmiedave ,

The 8081 WebSocket is bidirectional and the page already has a generic JSON handler (`CommandLink.onmessage`, switch on `obj.type`).

What’s missing is the device side: the [FreeRTOS SDK](https://github.com/Ameba-AIoT/ameba-rtos-pro2/blob/main/component/application/websocket_viewer/wsfs/src/wsfs_server.c) exposes `wsfs_connection_send_text()`, but the current example’s firmware never calls it, every command handler (including `get_version`) is a print-only stub. So the pipe is there, the simplest fix is to add one command handler in `web_service.c` that reads your per-unit data from SD and replies with `{"type":"unit_info","result":{...}}`, then add one case “`unit_info`”: in `ai_player.js` that sets `document.title` / fills the exposure and WiFi fields. After changes have been made, you might need to compile `libwebsocket_viewer.a` to replace `packages\realtek\hardware\AmebaPro2\<version>\variants\common_libs\libwebsocket_viewer.a`

Alternatively, add a dynamic HTTP endpoint like the existing `/fw_ver` and fetch it with the `updateText()` helper. Either way the browser pulls the data; the device can’t inject into the DOM unilaterally.

Thank you.

---

<div class="post-metadata">

**Author:** ![jimmiedave](https://avatars.discourse-cdn.com/v4/letter/j/bbe5ce/32.png) [@jimmiedave](https://forum.amebaiot.com/u/jimmiedave)\
**Post date:** [October 9, 2026, 8:18pm UTC](https://forum.amebaiot.com/t/amb82-mini-web-sockets-why-start-model/5109/7 "2026-10-09T20:18:14Z")

</div>

Thanks for this info. I’m certain that I can handle the C coding to add a command handler, adjust the html.bin/html.h files to do a GET, etc.

However, I could use a few breadcrumbs to help understand how to get it compiled and installed for the example.

I have the RTOS 10.4.1 toolchain set up on my Linux x86-64 machine, have built the GCC-RELEASE successfully, per instructions, and can locate the relevant files for the command handler in:  
`/ameba-rtos-pro2-main/component/application/websocket_viewer`

Once I’ve written my handler, my two challenges: 1. how do I get websocket\_viewer’s code built, and 2. how do I drop it into my Arduino environment?

Any help appreciated.

DC

---

<div class="post-metadata">

**Author:** ![KevinKL](https://sea2.discourse-cdn.com/flex016/user_avatar/forum.amebaiot.com/kevinkl/32/2632_2.png) [@KevinKL](https://forum.amebaiot.com/u/KevinKL)\
**Post date:** [October 12, 2026, 2:39am UTC](https://forum.amebaiot.com/t/amb82-mini-web-sockets-why-start-model/5109/8 "2026-10-12T02:39:20Z")

</div>

Hi @jimmiedave ,

After making changes in the relevant files, you may compile the code and replace the lib by following the steps below:

**Building the websocket\_viewer code in FreeRTOS SDK**

navigate to: `/project/realtek_amebapro2_v0_example/GCC-RELEASE/build`

execute the following commands to compile the media\_websocket\_viewer example directly:  
`cmake ../ -G"Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=../toolchain.cmake -DEXAMPLE=media_websocket_viewer`

`cmake --build . --target flash -j12`

**Dropping it into your Arduino environment**

navigate to: `/project/realtek_amebapro2_v0_example/GCC-RELEASE/build/application/output`

Copy the new `libwebsocket_viewer.a` into your Arduino SDK, replacing the old one at: `Arduino15/packages/realtek/hardware/AmebaPro2/<version>/variants/common_libs/libwebsocket_viewer.a`

Recompile and run under Arduino IDE to verify the update.

Thank you.

---

<div class="post-metadata">

**Author:** ![jimmiedave](https://avatars.discourse-cdn.com/v4/letter/j/bbe5ce/32.png) [@jimmiedave](https://forum.amebaiot.com/u/jimmiedave)\
**Post date:** [October 12, 2026, 7:36pm UTC](https://forum.amebaiot.com/t/amb82-mini-web-sockets-why-start-model/5109/9 "2026-10-12T19:36:14Z")

</div>

Thanks very much for that- much clearer.

I’ve worked through some CMake warnings, and have the build run without complaint, but it looks like the output files aren’t being rebuilt (this after I made a trivial change, added a string print to log, to make sure compilation was working). They have the same date as the date I installed the SDK a couple days ago.

Is it simply a matter of cleaning out the output directory, or is there a switch I’m missing? In looking through the readme, I’ve tried the cmake switch to build libraries = ON - no help there.

---

<div class="post-metadata">

**Author:** ![KevinKL](https://sea2.discourse-cdn.com/flex016/user_avatar/forum.amebaiot.com/kevinkl/32/2632_2.png) [@KevinKL](https://forum.amebaiot.com/u/KevinKL)\
**Post date:** [October 13, 2026, 3:24am UTC](https://forum.amebaiot.com/t/amb82-mini-web-sockets-why-start-model/5109/10 "2026-10-13T03:24:58Z")

</div>

Hi @jimmiedave ,

You are on the right track. Kindly remove everything in your build folder and execute the following commands to compile the media\_websocket\_viewer example cleanly,  
`cmake ../ -G"Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=../toolchain.cmake -DEXAMPLE=media_websocket_viewer`

`cmake --build . --target flash -j12`

Then, you will be able to find the updated `libwebsocket_viewer.a` in `/project/realtek_amebapro2_v0_example/GCC-RELEASE/build/application/output`

Thank you.

---

<div class="post-metadata">

**Author:** ![jimmiedave](https://avatars.discourse-cdn.com/v4/letter/j/bbe5ce/32.png) [@jimmiedave](https://forum.amebaiot.com/u/jimmiedave)\
**Post date:** [October 13, 2026, 11:49pm UTC](https://forum.amebaiot.com/t/amb82-mini-web-sockets-why-start-model/5109/11 "2026-10-13T23:49:11Z")

</div>

Thanks. I’m getting some traction there, but now have this error:

`cmake --build . --target flash -j12`  
`[0%] Built target fcs_isp_iq`  
`[1%] Built target bootfcs`  
`[4%] Built target websocket_viewer`  
`[9%] Built target iperf3`  
`[9%] Built target bootloader`  
`[71%] Built target outsrc`  
`[71%] Linking CXX executable application.ntz`  
`/home/theowner/AmebaPro/asdk-10.4.1/linux/newlib/bin/../lib/gcc/arm-none-eabi/10.4.1/../../../../arm-none-eabi/bin/ld: warning: section .ddr.bss' type changed to PROGBITS /usr/bin/objcopy: Unable to recognise the architecture of the input file application.ntz.axf'`  
`gmake[3]: *** [application/CMakeFiles/application.ntz.dir/build.make:3139: application/application.ntz] Error 1`  
`gmake[3]: *** Deleting file 'application/application.ntz'`  
`gmake[2]: *** [CMakeFiles/Makefile2:607: application/CMakeFiles/application.ntz.dir/all] Error 2`  
`gmake[1]: *** [CMakeFiles/Makefile2:225: CMakeFiles/flash.dir/rule] Error 2`  
`gmake: *** [Makefile:158: flash] Error 2`

---

<div class="post-metadata">

**Author:** ![KevinKL](https://sea2.discourse-cdn.com/flex016/user_avatar/forum.amebaiot.com/kevinkl/32/2632_2.png) [@KevinKL](https://forum.amebaiot.com/u/KevinKL)\
**Post date:** [October 14, 2026, 2:25am UTC](https://forum.amebaiot.com/t/amb82-mini-web-sockets-why-start-model/5109/12 "2026-10-14T02:25:13Z")

</div>

Hi @jimmiedave ,

It seems like the system is using the default /usr/bin/objcopy instead of arm-none-eabi-objcopy. Kindly export the toolchain path before running the cmake commands if you have not done so,

```bash
export PATH=/home/theowner/AmebaPro/asdk-10.4.1/linux/newlib/bin:$PATH

```

Alternatively, you may clean up your build folder and execute the following,

```bash
cmake ../ -G"Unix Makefiles" \
-DCMAKE_TOOLCHAIN_FILE=../toolchain.cmake \
-DEXAMPLE=media_websocket_viewer \
-DCMAKE_OBJCOPY=/home/theowner/AmebaPro/asdk-10.4.1/linux/newlib/bin/arm-none-eabi-objcopy

cmake --build . --target flash -j12

```

Thank you.

---

<div class="post-metadata">

**Author:** ![jimmiedave](https://avatars.discourse-cdn.com/v4/letter/j/bbe5ce/32.png) [@jimmiedave](https://forum.amebaiot.com/u/jimmiedave)\
**Post date:** [October 14, 2026, 4:24am UTC](https://forum.amebaiot.com/t/amb82-mini-web-sockets-why-start-model/5109/13 "2026-10-14T04:24:30Z")

</div>

That’s it! Thanks so much.

I was adding to the `PATH` but not `export`ing it.

---

<div class="post-metadata">

**Author:** ![jimmiedave](https://avatars.discourse-cdn.com/v4/letter/j/bbe5ce/32.png) [@jimmiedave](https://forum.amebaiot.com/u/jimmiedave)\
**Post date:** [October 17, 2026, 4:13pm UTC](https://forum.amebaiot.com/t/amb82-mini-web-sockets-why-start-model/5109/14 "2026-10-17T16:13:24Z")

</div>

Is there a way I can pass information from the Arduino context into my get\_unit\_info function/method on the RTOS side? Looks like `extern` alone isn’t going to get it.

---

<div class="post-metadata">

**Author:** ![KevinKL](https://sea2.discourse-cdn.com/flex016/user_avatar/forum.amebaiot.com/kevinkl/32/2632_2.png) [@KevinKL](https://forum.amebaiot.com/u/KevinKL)\
**Post date:** [October 19, 2026, 10:42am UTC](https://forum.amebaiot.com/t/amb82-mini-web-sockets-why-start-model/5109/15 "2026-10-19T10:42:05Z")

</div>

Hi @jimmiedave

You might need to rebuild libwebsocket\_viewer.a, and add a bridge to the RTOS side. Please take the implementation steps below as a reference.

* * *

Step 1 — RTOS side: add the handler

In component/application/websocket\_viewer/web\_service.c, declare your bridge symbols as weak defaults:  
**`attribute`** `((weak)) char unit_title[64] = "";`  
**`attribute`** `((weak)) int unit_exposure = 0;`  
**`attribute`** `((weak)) char unit_ssid[33] = "";`  
**`attribute`** `((weak)) int ard_get_unit_info(int *len) { *len = 0; return -1; }`

Then the handler:

`static void get_unit_info(wsfs_connection_t *conn, void *p)`  
`{`  
`char json[256];`  
`int len = 0;`  
`ard_get_unit_info(&len);`  
`snprintf(json, sizeof(json),`  
`"{"type":"unit_info","result":{"status":"ok","`  
`""title":"%s","exposure":%d,"ssid":"%s"}}",`  
`unit_title, unit_exposure, unit_ssid);`  
`wsfs_connection_send_text(conn, json, strlen(json));`  
`}`

And register it in `app_cmd[]`, before the `{0, 0}` terminator:

`{"get_unit_info", get_unit_info},`

* * *

Step 2 — Rebuild the library

`libwebsocket_viewer.a`

* * *

Step 3 — Drop it into the Arduino SDK

cp application/libwebsocket\_viewer.a  
~/.arduino15/packages/realtek/hardware/AmebaPro2//variants/common\_libs/

* * *

Step 4 — Arduino side: the extern “C” bridge

Put these in the sketch folder, not in the .ino — Arduino auto-generates prototypes for functions in the .ino, and those get C++ linkage, which can silently defeat your  
extern “C”.

**unit\_info.h:**

#ifndef UNIT\_INFO\_H  
#define UNIT\_INFO\_H

#ifdef \_\_cplusplus  
extern “C” {  
#endif

extern char unit\_title[64];  
extern int unit\_exposure;  
extern char unit\_ssid[33];  
int ard\_get\_unit\_info(int \*len);

#ifdef \_\_cplusplus  
}  
#endif

#endif

**unit\_info.cpp:**

#include “unit\_info.h”  
#include \<string.h\>

char unit\_title[64] = “Test-title”;  
int unit\_exposure = 120;  
char unit\_ssid[33] = “Test-AP”;

extern “C” int ard\_get\_unit\_info(int \*len)  
{  
\*len = (int)strlen(unit\_title);  
return 0;  
}

* * *

Step 5 — Browser side

In htdocs/js/ai\_player.js, add a case to the onmessage switch (next to case “get\_version”:):

case “unit\_info”:  
document.title = obj.result.title;  
$(“#exposure”).val(obj.result.exposure);  
$(“#ssid”).val(obj.result.ssid);  
break;

Add a sender next to getVersion():

getUnitInfo() {  
this.send(JSON.stringify({cmd:“get\_unit\_info”}));  
}

And call it from this.onopen, right after this.getVersion();:

this.getVersion();  
this.getUnitInfo();

Regenerate the bundle with the genbin.cpp tool in the web-source zip, then either drop htdocs.bin on the SD card or regenerate htdocs.h with bin2h.c and replace it in  
libraries/Multimedia/src/.

Thank you.

---

<div class="post-metadata">

**Author:** ![jimmiedave](https://avatars.discourse-cdn.com/v4/letter/j/bbe5ce/32.png) [@jimmiedave](https://forum.amebaiot.com/u/jimmiedave)\
**Post date:** [October 19, 2026, 9:38pm UTC](https://forum.amebaiot.com/t/amb82-mini-web-sockets-why-start-model/5109/16 "2026-10-19T21:38:21Z")

</div>

Thanks once more.

If I’m reading this right, `char json` is a place the RTOS side will park the json string, `len` is the length of the `unit_title` obtained from the Arduino side, and this is called to pick up info from the Arduino side when the html page (actually `aiplayer.js`) asks for it in `get_unit_info`. The RTOS package is using snprintf to assemble the `json` string the Arduino side has dumped into the RTOS attributes.

That right?

I’d already got most of this working - can modify my code to fit it.

---

<div class="post-metadata">

**Author:** ![KevinKL](https://sea2.discourse-cdn.com/flex016/user_avatar/forum.amebaiot.com/kevinkl/32/2632_2.png) [@KevinKL](https://forum.amebaiot.com/u/KevinKL)\
**Post date:** [October 20, 2026, 10:07am UTC](https://forum.amebaiot.com/t/amb82-mini-web-sockets-why-start-model/5109/17 "2026-10-20T10:07:16Z")

</div>

Hi @jimmiedave ,

Yes, that’s very close. Two small corrections though.

Correct: `char json[256]` is a scratch buffer on the handler’s stack where the reply gets formatted, and snprintf assembles the JSON from the values. The trigger flow is exactly as you describe: ai\_player.js sends {“cmd”:“get\_unit\_info”} → process\_command() matches it in app\_cmd → get\_unit\_info(conn, param) runs.

Correction 1: `len` isn’t doing what you think. It’s just an out-parameter for the optional accessor `ard_get_unit_info()`. In the code as written, len gets filled in and then never read again — snprintf pulls the title straight from `unit_title`, not via `len`. So it’s effectively dead code, I included it only to show how you’d use a function-style accessor if you needed one (to do locking, return a status, or compute a value on demand). If you only need to read the three values, you can delete both `ard_get_unit_info` and int `len` entirely and the handler is simpler.

Correction 2: nothing gets “dumped” from Arduino into RTOS attributes. There’s no copy step, no registration, no runtime handoff.  
`unit_title` on the RTOS side and unit\_title in your sketch are the same variable — the linker resolves them to a single memory location. The **attribute** ((weak)) definition in `web_service.c` is only a fallback that exists so the SDK can still link on its own; when your sketch is in the build, its strong definition replaces the weak one at link time.

So when snprintf reads `unit_title`, it’s reading your sketch’s buffer directly, there’s no intermediate store, and no synchronisation needed between the two sides. (You still need to finish writing the value before `ws_viewer.init()` starts the server thread, since the handler runs on that thread.)

The reason this works at all is that global variables aren’t name-mangled in C++, so the C side and C++ side agree on the symbol name. Functions would need extern “C”, that’s the only reason the accessor has it.

If you’d rather keep a function boundary, say you want to grab the values under a lock, or derive them on demand rather than exposing raw globals, keep `ard_get_unit_info` and actually use `len` (or return the values through it).

Sounds like you are nearly there, happy to look at your version if anything doesn’t line up.
