Skip to main content

Hello World

This tutorial walks you through a minimal Hello World application, covering the complete lifecycle of an NE503 container application: write application β†’ build ARM64 image β†’ upload and deploy β†’ start β†’ verify in Web Console β†’ view logs β†’ clean up. Once you master this minimal closed loop, you can rapidly iterate on any AI application.

Hello World does not depend on the AI SDK β€” it simply prints a counter in a loop, making it ideal for verifying that the development environment and deployment pipeline are working end to end.

1. Prerequisites​

ConditionVerification
NE503 device is online and runningVisit http://<device-ip>:8080 in a browser; the Web login page should appear
Docker is installed on the development machineRun docker --version in a terminal; version >= 20.10
Development machine can ping the devicecurl -o /dev/null -w "%{http_code}" http://<device-ip>:8080 returns 200
Know the device login credentialsWeb Console default is admin / password (change after first login)
Architecture Notes

The NE503 device is ARM64 architecture. If your development machine is Apple Silicon (M-series), it is also ARM64, so you can build natively at full speed. On an x86 machine, Docker buildx will automatically use QEMU emulation β€” slightly slower but fully functional.

2. Application Structure​

The Hello World application consists of three files (full source in the repository at apps/hello-world/):

hello-world/
β”œβ”€β”€ app.py # Application main logic
β”œβ”€β”€ app.yaml # Application manifest (resources / permissions / configuration)
└── Dockerfile # Container build definition

app.py -- Pure Python, prints a counter in a loop and responds to SIGTERM for graceful shutdown (the platform sends SIGTERM when stopping an application):

import os, time, signal

class HelloWorldApp:
def __init__(self):
self.running = True
self.app_id = os.environ.get("APP_ID", "hello_world") # platform injects
self.counter = 0
signal.signal(signal.SIGTERM, self._signal_handler)

def _signal_handler(self, signum, frame):
self.running = False

def run(self):
while self.running:
self.counter += 1
print(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] #{self.counter:06d} - Hello World from AIPC!")
time.sleep(1)

if __name__ == "__main__":
HelloWorldApp().run()

app.yaml -- Application manifest, declaring the image, resource limits, and startup policy (Hello World does not require any permissions):

apiVersion: v1
kind: Application
metadata:
id: hello-world
name: Hello World
version: 1.0.0
description: A simple hello world application that prints continuously
spec:
image: aipc/hello-world:1.0.0 # must match the tag from docker build -t
resources:
cpu: "10%"
memory: "32Mi"
autostart: false
restart_policy: on-failure
restart_max_retries: 3

Dockerfile -- Based on python:3.11-alpine, lightweight:

FROM python:3.11-alpine3.19
WORKDIR /app
COPY app.py /app/app.py
ENV PYTHONUNBUFFERED=1
ENV APP_ID=hello_world
CMD ["python3", "/app/app.py"]

3. Building the Image​

Build the ARM64 image in the application directory, export it as a tar, then package it into a .aipc installation package:

cd apps/hello-world

# 1. Build ARM64 image (--load imports into local Docker)
docker buildx build --platform linux/arm64 --load -t aipc/hello-world:1.0.0 .

# 2. Export image as tar
docker save aipc/hello-world:1.0.0 -o image.tar

# 3. Package into .aipc (zip of app.yaml + image.tar)
zip hello-world.aipc app.yaml image.tar

Build artifacts (actual):

ArtifactSize
Docker image26.5 MB (113 MB disk usage)
image.tar25 MB
hello-world.aipc25 MB

The .aipc file is simply a zip archive of app.yaml + image.tar, convenient for storage and distribution. Deployment to the device uses the two files inside it (image.tar and app.yaml, see the next section); the .aipc itself is not uploaded via the API.

Build fails occasionally?

On macOS + Docker Desktop, apk add may occasionally report Failed to create ...: I/O error. This is a known intermittent issue with buildx -- simply run the build command again and it should succeed.

4. Deploying to the Device​

After building, you have two files: app.yaml (application manifest) and image.tar (container image). Three deployment options are provided below β€” the Web Console is recommended (graphical UI, no SSH required).

Prerequisite

All three options require the two separate files app.yaml and image.tar. After following the manual steps in Β§3, both files are in the app directory. If you used the repo's apps/<app>/build.sh (which deletes the intermediate image.tar after packaging .aipc), unzip it first: unzip -o <app>.aipc.

Done entirely in the browser, no SSH login required.

  1. Open the Web Console at http://<device-ip>:8080 in a browser and log in with the default credentials admin / password.

  2. Click App Management in the left sidebar to reach the app list. In the top-right corner there is an Import card β€” click it.

  3. The Application Setup Wizard dialog opens. In the first step, Source, pick the third option, Upload Package β€” this accepts both the app.yaml manifest and the image file.

  4. Under App Manifest (app.yaml) click Choose File and select your local app.yaml; under Container Image select image.tar.

Upload Package: select app.yaml + image.tar

  1. Click the Install button in the bottom-right corner. The wizard runs the remaining steps automatically (parse manifest β†’ import image β†’ register app), usually within 10–15 seconds. Back in the app list, Hello World appears (initially in Stopped state β€” you start it in the next section).

4.2 Deploy via aipc-cli (Alternative)​

If you have already SSH'd into the device, install in one command with the platform's built-in aipc-cli. First copy app.yaml and image.tar to the device:

scp app.yaml image.tar root@<device-ip>:/tmp/
ssh root@<device-ip>

Then on the device run:

aipc-cli app install app.yaml image.tar

4.3 Deploy via HTTP API (Alternative)​

For scripting / CI automation. This is the same installation as above broken into explicit HTTP calls: two-step upload + async install β€” upload the image and manifest separately, then trigger a background install task and poll for progress.

Legacy single-file upload is deprecated

curl -F 'app=@xxx.aipc' /api/v1/apps (uploading the whole .aipc at once) no longer works (the endpoint returns a JSON parse error). Use the two-step flow below.

Login to Obtain a Token​

curl -X POST http://<device-ip>:8080/api/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"password"}'

Response (note the token value includes the Bearer prefix):

{"code":0,"data":{"token":"Bearer aipc-secure-token-secret","username":"admin"}}

All subsequent API calls must include the Authorization: <the entire token string from above> header.

Upload Image and Manifest​

# Upload image (field name is file)
curl -X POST http://<device-ip>:8080/api/v1/apps/upload-image \
-H "Authorization: Bearer <token>" \
-F "file=@image.tar"
# β†’ {"data":{"path":"/opt/aipc/images/1781509627_image.tar", "image":"aipc/hello-world:1.0.0", ...}}

# Upload manifest
curl -X POST http://<device-ip>:8080/api/v1/apps/upload-manifest \
-H "Authorization: Bearer <token>" \
-F "file=@app.yaml"
# β†’ {"data":{"path":"/opt/aipc/apps/manifests/hello-world/app.yaml", ...}}

Trigger Installation and Poll Progress​

# Trigger async install (JSON body, passing both paths from above)
curl -X POST http://<device-ip>:8080/api/v1/apps/install-package \
-H "Authorization: Bearer <token>" -H "Content-Type: application/json" \
-d '{"manifest_path":"/opt/aipc/apps/manifests/hello-world/app.yaml",
"image_path":"/opt/aipc/images/1781509627_image.tar","force":true}'
# β†’ {"data":{"task_id":"0f26285a"}}

# Poll installation progress (until phase=complete)
curl http://<device-ip>:8080/api/v1/apps/install-progress/<task_id> \
-H "Authorization: Bearer <token>"

Progress evolution: phase:"pulling" percent:10 "Importing local image..." β†’ phase:"complete" percent:100 "Installation complete", typically finishing in 10-15 seconds.

5. Start and Verify​

5.1 Start the Application​

After deployment the app is in the Stopped state β€” you need to start it once manually. Pick either of the two options below.

Option 1: Start via the Web Console (recommended)

Go to App Management, find the Hello World card (status shown as Stopped), and click the Start button on the card. Normally within a few seconds the status badge switches from Stopped to Running.

Option 2: Start via the HTTP API

curl -X POST http://<device-ip>:8080/api/v1/apps/hello-world/start \
-H "Authorization: Bearer <token>"
First start times out?

The first time you start an image, the platform needs to load it into the container runtime, which may exceed the 10-second API timeout, returning code:6002 DeadlineExceeded. This is not an error β€” just call the start endpoint once more (or click Start again on the Web UI) and it will succeed.

5.2 Verify in the Web Console (simulating a user's perspective)​

After deployment, log into the Web Console at http://<device-ip>:8080 with a browser and verify the application is running normally from a real user's point of view.

Web Console login page

Log in with the default credentials admin / password to reach the Dashboard. The top of the homepage shows device status (uptime, temperature, CPU/NPU/memory/storage usage), and the Applications section in the middle shows currently running applications:

Dashboard (Hello World running)

Navigate to Applications in the left sidebar -- you should see Hello World in Running status with real-time CPU and memory usage:

Applications page (Hello World Running)

Click on Hello World to open the detail view, showing the application ID, version, install/start time, uptime, and Stop / Restart / Uninstall action buttons -- this confirms the application is fully managed by the platform:

Hello World application detail

5.3 View Runtime Logs​

Application logs can also be retrieved via the API (returned in NDJSON format, one JSON object per line):

curl "http://<device-ip>:8080/api/v1/apps/hello-world/logs?max_lines=10" \
-H "Authorization: Bearer <token>"
{"timestamp":1781509897838838800,"level":"info","message":"[2026-06-15 07:51:23] #000011 - Hello World from AIPC!"}
{"timestamp":1781509897838892960,"level":"info","message":"[2026-06-15 07:51:24] #000012 - Hello World from AIPC!"}
{"timestamp":1781509897838901400,"level":"info","message":"[2026-06-15 07:51:25] #000013 - Hello World from AIPC!"}

The counter increments every second, confirming the application is running stably.

6. Stop and Clean Up​

After verification, stop and uninstall the application:

# Stop
curl -X POST http://<device-ip>:8080/api/v1/apps/hello-world/stop -H "Authorization: Bearer <token>"
# β†’ {"data":{"message":"App stopped successfully"}}

# Uninstall
curl -X DELETE http://<device-ip>:8080/api/v1/apps/hello-world -H "Authorization: Bearer <token>"
# β†’ {"data":{"message":"App uninstalled successfully"}}

7. Summary​

Congratulations, you have completed the full closed loop for an NE503 container application:

  1. Write -- the app.py + app.yaml + Dockerfile trifecta
  2. Build -- docker buildx build --platform linux/arm64 β†’ docker save β†’ zip .aipc
  3. Deploy -- Web Console upload (recommended) / aipc-cli / HTTP two-step upload β€” pick one
  4. Verify -- confirm Running status in Web Console + check logs to confirm output
  5. Clean up -- stop + uninstall

Next, in the Person Detection Application Tutorial, you will use the same flow to deploy a real AI inference application, learning how to use the SDK, discover models and video streams, and process detection results.

Running into issues?

If you encounter errors during application deployment or startup, refer to Application Troubleshooting.