Add GPIO keywords, buying guide, embedded templates, and update to BotDevice

- Add GPIO & IoT Keywords documentation (keywords-gpio.md)
  - GPIO MODE, SET, GET, PWM, SERVO
  - I2C SCAN, READ, WRITE
  - SPI OPEN, TRANSFER, CLOSE
  - Sensor keywords: READ TEMPERATURE, HUMIDITY, DISTANCE, MOTION, LIGHT
  - Display keywords: LCD INIT/PRINT/CLEAR, OLED INIT/PRINT/DRAW/CLEAR
  - Relay and buzzer control
  - Complete examples: doorbell, thermostat, light automation

- Add Beginner's Buying Guide (13-devices/buying-guide.md)
  - What is an SBC explained for beginners
  - Recommended starter kits by budget
  - Sample shopping lists for projects
  - Where to buy by region
  - First-time setup guide
  - Common beginner mistakes

- Add Embedded Device Templates (02-templates/template-embedded.md)
  - thermostat.bas - Smart thermostat with AI
  - doorbell.bas - Smart doorbell with notifications
  - light-control.bas - Voice-controlled lights
  - security.bas - Motion alarm system
  - plant-monitor.bas - Automatic plant watering
  - kiosk.bas - Information display

- Add SVG architecture diagram (embedded-architecture.svg)

- Update mobile.md to use BotDevice branding (renamed from BotOS)

- Update SUMMARY.md with new sections
This commit is contained in:
Rodrigo Rodriguez (Pragmatismo) 2025-12-12 14:14:53 -03:00
parent d3bc28fac6
commit 42f97de134
6 changed files with 1825 additions and 21 deletions

View file

@ -0,0 +1,825 @@
# Template: Embedded Devices
Ready-to-use templates for home automation, IoT projects, and embedded displays. Copy these templates to your `.gbdialog` folder and customize.
## Template Categories
| Template | Use Case | Hardware |
|----------|----------|----------|
| **thermostat.bas** | Smart thermostat | DHT22, Relay, OLED |
| **doorbell.bas** | Smart doorbell | Button, Camera, Buzzer |
| **light-control.bas** | Voice-controlled lights | Relay, Microphone |
| **security.bas** | Motion alarm | PIR, Buzzer, Camera |
| **plant-monitor.bas** | Plant watering | Soil sensor, Pump |
| **kiosk.bas** | Information display | HDMI display |
---
## thermostat.bas
Smart thermostat with scheduling and remote control.
```bas
' ============================================================
' SMART THERMOSTAT - Temperature control with AI assistant
' Hardware: DHT22 (GPIO 4), Relay (GPIO 17), OLED (I2C 0x3C)
' ============================================================
' Configuration
targetTemp = 22 ' Target temperature in Celsius
hysteresis = 0.5 ' Prevent rapid on/off cycling
heatingPin = 17
sensorPin = 4
' Initialize hardware
GPIO MODE heatingPin, "OUTPUT"
OLED INIT 0x3C, 128, 64
' Load saved settings
savedTarget = GET BOT MEMORY "thermostat_target"
IF savedTarget <> "" THEN
targetTemp = VAL(savedTarget)
END IF
TALK "Thermostat ready. Target: " + targetTemp + "°C"
' Main control loop
mainLoop:
' Read current temperature
currentTemp = READ TEMPERATURE sensorPin
humidity = READ HUMIDITY sensorPin
' Control logic with hysteresis
IF currentTemp < (targetTemp - hysteresis) THEN
GPIO SET heatingPin, HIGH
heating = "ON"
ELSEIF currentTemp > (targetTemp + hysteresis) THEN
GPIO SET heatingPin, LOW
heating = "OFF"
END IF
' Update display
OLED CLEAR
OLED PRINT 0, 0, "Current:", 1
OLED PRINT 0, 12, currentTemp + " C", 2
OLED PRINT 0, 35, "Target: " + targetTemp + " C", 1
OLED PRINT 0, 48, "Heat: " + heating, 1
OLED PRINT 80, 48, humidity + "%", 1
' Log to database every 5 minutes
IF MINUTE(NOW) MOD 5 = 0 AND SECOND(NOW) < 5 THEN
INSERT "temperature_log", {
"timestamp": NOW,
"temperature": currentTemp,
"humidity": humidity,
"heating": heating
}
END IF
WAIT 5
GOTO mainLoop
' ============================================================
' Voice command handler (called when user speaks)
' ============================================================
SUB handleCommand(command)
' Use LLM to understand intent
intent = LLM "Parse thermostat command: '" + command + "'. Return JSON: {action: set/status/schedule, temperature: number or null}"
intent = JSON PARSE intent
SELECT CASE intent.action
CASE "set"
targetTemp = intent.temperature
SET BOT MEMORY "thermostat_target", targetTemp
TALK "Temperature set to " + targetTemp + " degrees"
CASE "status"
TALK "Current temperature is " + currentTemp + " degrees. Target is " + targetTemp + ". Heating is " + heating
CASE "schedule"
TALK "Scheduling not yet implemented"
END SELECT
END SUB
```
---
## doorbell.bas
Smart doorbell with photo capture and notifications.
```bas
' ============================================================
' SMART DOORBELL - Ring detection with photo and notification
' Hardware: Button (GPIO 27), Buzzer (GPIO 18), LED (GPIO 17)
' Optional: Camera module, OLED display
' ============================================================
' Pin configuration
buttonPin = 27
buzzerPin = 18
ledPin = 17
' Setup
GPIO MODE buttonPin, "INPUT_PULLUP"
GPIO MODE buzzerPin, "OUTPUT"
GPIO MODE ledPin, "OUTPUT"
' Notification settings
ownerEmail = GET BOT MEMORY "doorbell_email"
IF ownerEmail = "" THEN
ownerEmail = "owner@example.com"
END IF
TALK "Doorbell system ready"
' Visual indicator that system is active
GPIO SET ledPin, LOW
mainLoop:
' Check button
IF GPIO GET buttonPin = LOW THEN
' Debounce
WAIT 0.05
IF GPIO GET buttonPin = LOW THEN
handleRing()
' Wait for button release
WHILE GPIO GET buttonPin = LOW
WAIT 0.01
WEND
END IF
END IF
WAIT 0.1
GOTO mainLoop
' ============================================================
SUB handleRing()
timestamp = FORMAT(NOW, "HH:mm:ss")
' Visual and audio feedback
GPIO SET ledPin, HIGH
BUZZER buzzerPin, 1000, 0.3
WAIT 0.1
BUZZER buzzerPin, 1500, 0.3
' Try to capture photo
ON ERROR RESUME NEXT
photo = CAPTURE PHOTO
photoPath = "doorbell_" + FORMAT(NOW, "YYYYMMDD_HHmmss") + ".jpg"
IF NOT ERROR THEN
WRITE "photos/" + photoPath, photo
END IF
ON ERROR GOTO 0
' Log the ring
INSERT "doorbell_log", {
"timestamp": NOW,
"photo": photoPath
}
' Send notification
IF photo THEN
SEND MAIL ownerEmail, "Doorbell Ring", "Someone is at the door! Time: " + timestamp, [photo]
ELSE
SEND MAIL ownerEmail, "Doorbell Ring", "Someone is at the door! Time: " + timestamp
END IF
' Announce locally
TALK "Visitor at the door"
' LED off after 2 seconds
WAIT 2
GPIO SET ledPin, LOW
END SUB
' ============================================================
' Configuration command
' ============================================================
SUB setEmail(email)
SET BOT MEMORY "doorbell_email", email
ownerEmail = email
TALK "Notification email set to " + email
END SUB
```
---
## light-control.bas
Voice-controlled lighting with scenes and schedules.
```bas
' ============================================================
' SMART LIGHTS - Voice and schedule controlled lighting
' Hardware: 4-channel relay on GPIO 17, 18, 27, 22
' ============================================================
' Room configuration
DIM rooms(4)
rooms(0) = "living room"
rooms(1) = "bedroom"
rooms(2) = "kitchen"
rooms(3) = "bathroom"
DIM pins(4)
pins(0) = 17
pins(1) = 18
pins(2) = 27
pins(3) = 22
' Initialize all relays
FOR i = 0 TO 3
GPIO MODE pins(i), "OUTPUT"
GPIO SET pins(i), LOW ' All lights off
NEXT
TALK "Light control ready. Say 'turn on' or 'turn off' followed by room name."
' ============================================================
' Main dialog loop
' ============================================================
mainLoop:
command = HEAR
IF command <> "" THEN
handleCommand(command)
END IF
' Check schedules
checkSchedules()
WAIT 0.5
GOTO mainLoop
' ============================================================
SUB handleCommand(command)
' Use LLM to parse command
prompt = "Parse light command: '" + command + "'. "
prompt = prompt + "Rooms: living room, bedroom, kitchen, bathroom, all. "
prompt = prompt + "Return JSON: {action: on/off/toggle/status/scene, room: string, scene: string or null}"
intent = LLM prompt
intent = JSON PARSE intent
SELECT CASE intent.action
CASE "on"
turnOn(intent.room)
CASE "off"
turnOff(intent.room)
CASE "toggle"
toggle(intent.room)
CASE "status"
reportStatus()
CASE "scene"
applyScene(intent.scene)
END SELECT
END SUB
' ============================================================
SUB turnOn(room)
IF room = "all" THEN
FOR i = 0 TO 3
RELAY SET pins(i), ON
NEXT
TALK "All lights on"
ELSE
FOR i = 0 TO 3
IF rooms(i) = room THEN
RELAY SET pins(i), ON
TALK room + " light on"
EXIT FOR
END IF
NEXT
END IF
END SUB
SUB turnOff(room)
IF room = "all" THEN
FOR i = 0 TO 3
RELAY SET pins(i), OFF
NEXT
TALK "All lights off"
ELSE
FOR i = 0 TO 3
IF rooms(i) = room THEN
RELAY SET pins(i), OFF
TALK room + " light off"
EXIT FOR
END IF
NEXT
END IF
END SUB
SUB toggle(room)
FOR i = 0 TO 3
IF rooms(i) = room OR room = "all" THEN
state = GPIO GET pins(i)
RELAY SET pins(i), NOT state
END IF
NEXT
TALK room + " toggled"
END SUB
SUB reportStatus()
status = "Light status: "
FOR i = 0 TO 3
state = GPIO GET pins(i)
IF state = HIGH THEN
status = status + rooms(i) + " ON, "
ELSE
status = status + rooms(i) + " off, "
END IF
NEXT
TALK status
END SUB
' ============================================================
' Scenes
' ============================================================
SUB applyScene(scene)
SELECT CASE scene
CASE "movie"
RELAY SET pins(0), OFF ' Living room dim
RELAY SET pins(1), OFF
RELAY SET pins(2), OFF
RELAY SET pins(3), OFF
TALK "Movie scene applied - all lights off"
CASE "morning"
RELAY SET pins(2), ON ' Kitchen on
RELAY SET pins(3), ON ' Bathroom on
RELAY SET pins(0), OFF
RELAY SET pins(1), OFF
TALK "Morning scene - kitchen and bathroom on"
CASE "night"
RELAY SET pins(1), ON ' Bedroom only
RELAY SET pins(0), OFF
RELAY SET pins(2), OFF
RELAY SET pins(3), OFF
TALK "Night scene - bedroom only"
CASE "all on"
FOR i = 0 TO 3
RELAY SET pins(i), ON
NEXT
TALK "All lights on"
END SELECT
END SUB
' ============================================================
' Schedule checking
' ============================================================
SUB checkSchedules()
hour = HOUR(NOW)
minute = MINUTE(NOW)
' Sunset - turn on living room
IF hour = 18 AND minute = 0 THEN
RELAY SET pins(0), ON
END IF
' Bedtime - night scene
IF hour = 22 AND minute = 30 THEN
applyScene("night")
END IF
' Late night - all off
IF hour = 23 AND minute = 30 THEN
turnOff("all")
END IF
END SUB
```
---
## security.bas
Motion-activated security system with alerts.
```bas
' ============================================================
' SECURITY SYSTEM - Motion detection with alerts
' Hardware: PIR (GPIO 7), Buzzer (GPIO 18), LED (GPIO 17)
' Optional: Camera, OLED display
' ============================================================
' Configuration
pirPin = 7
buzzerPin = 18
ledPin = 17
alertEmail = "security@example.com"
' State
armed = FALSE
alertCooldown = 0
' Initialize
GPIO MODE pirPin, "INPUT"
GPIO MODE buzzerPin, "OUTPUT"
GPIO MODE ledPin, "OUTPUT"
TALK "Security system ready. Say 'arm' to activate."
mainLoop:
' Check for motion when armed
IF armed THEN
GPIO SET ledPin, HIGH ' Armed indicator
motion = READ MOTION pirPin
IF motion AND NOW > alertCooldown THEN
handleAlert()
alertCooldown = NOW + 60 ' 1 minute cooldown
END IF
ELSE
GPIO SET ledPin, LOW
END IF
' Check for commands
command = HEAR NOWAIT
IF command <> "" THEN
handleCommand(command)
END IF
WAIT 0.5
GOTO mainLoop
' ============================================================
SUB handleCommand(command)
command = LOWER(command)
IF INSTR(command, "arm") > 0 THEN
IF INSTR(command, "disarm") > 0 THEN
disarmSystem()
ELSE
armSystem()
END IF
ELSEIF INSTR(command, "status") > 0 THEN
IF armed THEN
TALK "System is armed"
ELSE
TALK "System is disarmed"
END IF
ELSEIF INSTR(command, "test") > 0 THEN
testAlarm()
END IF
END SUB
SUB armSystem()
TALK "Arming in 10 seconds. Leave the area."
' Countdown beeps
FOR i = 10 TO 1 STEP -1
BUZZER buzzerPin, 1000, 0.1
WAIT 1
NEXT
armed = TRUE
BUZZER buzzerPin, 2000, 0.5
TALK "System armed"
END SUB
SUB disarmSystem()
armed = FALSE
GPIO SET ledPin, LOW
TALK "System disarmed"
END SUB
SUB handleAlert()
TALK "Motion detected! Alerting..."
' Sound alarm
FOR i = 1 TO 5
BUZZER buzzerPin, 2000, 0.2
WAIT 0.1
BUZZER buzzerPin, 1500, 0.2
WAIT 0.1
NEXT
' Capture photo if camera available
ON ERROR RESUME NEXT
photo = CAPTURE PHOTO
ON ERROR GOTO 0
' Log event
INSERT "security_events", {
"timestamp": NOW,
"type": "motion",
"photo": photo
}
' Send alert
IF photo THEN
SEND MAIL alertEmail, "SECURITY ALERT", "Motion detected at " + FORMAT(NOW, "HH:mm:ss"), [photo]
ELSE
SEND MAIL alertEmail, "SECURITY ALERT", "Motion detected at " + FORMAT(NOW, "HH:mm:ss")
END IF
END SUB
SUB testAlarm()
TALK "Testing alarm"
BUZZER buzzerPin, 1500, 0.5
WAIT 0.5
BUZZER buzzerPin, 2000, 0.5
TALK "Test complete"
END SUB
```
---
## plant-monitor.bas
Automatic plant watering system.
```bas
' ============================================================
' PLANT MONITOR - Soil moisture monitoring and auto-watering
' Hardware: Soil sensor (ADC 0), Water pump relay (GPIO 17)
' Optional: DHT22 for air temp/humidity
' ============================================================
' Configuration
soilChannel = 0 ' ADC channel for soil sensor
pumpPin = 17 ' Relay for water pump
dryThreshold = 300 ' Below this = dry soil (adjust for your sensor)
wetThreshold = 700 ' Above this = wet enough
waterDuration = 5 ' Seconds to run pump
' Initialize
GPIO MODE pumpPin, "OUTPUT"
GPIO SET pumpPin, LOW
TALK "Plant monitor ready"
mainLoop:
' Read soil moisture
moisture = READ LIGHT soilChannel ' Using ADC reading
' Read air conditions if sensor available
ON ERROR RESUME NEXT
airTemp = READ TEMPERATURE 4
airHumidity = READ HUMIDITY 4
ON ERROR GOTO 0
' Determine soil status
IF moisture < dryThreshold THEN
status = "DRY"
needsWater = TRUE
ELSEIF moisture > wetThreshold THEN
status = "WET"
needsWater = FALSE
ELSE
status = "OK"
needsWater = FALSE
END IF
' Auto water if dry
IF needsWater THEN
waterPlant()
END IF
' Update display
LCD CLEAR
LCD PRINT 0, 0, "Soil: " + status
LCD PRINT 1, 0, "M:" + moisture
' Log every 30 minutes
IF MINUTE(NOW) MOD 30 = 0 AND SECOND(NOW) < 10 THEN
INSERT "plant_log", {
"timestamp": NOW,
"moisture": moisture,
"status": status,
"air_temp": airTemp,
"air_humidity": airHumidity
}
END IF
WAIT 60 ' Check every minute
GOTO mainLoop
' ============================================================
SUB waterPlant()
' Only water during daytime (6am - 8pm)
hour = HOUR(NOW)
IF hour < 6 OR hour > 20 THEN
RETURN
END IF
' Check if we watered recently (within 2 hours)
lastWater = GET BOT MEMORY "last_water_time"
IF lastWater <> "" THEN
IF NOW - VAL(lastWater) < 7200 THEN ' 2 hours in seconds
RETURN
END IF
END IF
TALK "Watering plant"
' Run pump
GPIO SET pumpPin, HIGH
WAIT waterDuration
GPIO SET pumpPin, LOW
' Record watering
SET BOT MEMORY "last_water_time", NOW
INSERT "watering_log", {
"timestamp": NOW,
"duration": waterDuration
}
' Send notification
SEND MAIL "gardener@example.com", "Plant Watered", "Your plant was automatically watered at " + FORMAT(NOW, "HH:mm")
TALK "Watering complete"
END SUB
' ============================================================
' Manual commands
' ============================================================
SUB handleCommand(command)
IF INSTR(command, "water") > 0 THEN
TALK "Manual watering"
GPIO SET pumpPin, HIGH
WAIT waterDuration
GPIO SET pumpPin, LOW
TALK "Done"
ELSEIF INSTR(command, "status") > 0 THEN
TALK "Soil moisture is " + moisture + ". Status: " + status
END IF
END SUB
```
---
## kiosk.bas
Information display kiosk for lobbies and public spaces.
```bas
' ============================================================
' INFO KIOSK - Public information display with AI assistant
' Hardware: HDMI display, touch screen or keyboard
' ============================================================
' Configuration
welcomeMessage = "Welcome! How can I help you today?"
idleTimeout = 60 ' Return to welcome screen after inactivity
' State
lastActivity = NOW
' Initialize display
' (Runs in browser kiosk mode at http://localhost:8088/embedded/)
TALK welcomeMessage
mainLoop:
' Check for user input
input = HEAR NOWAIT
IF input <> "" THEN
lastActivity = NOW
handleQuery(input)
END IF
' Return to welcome screen after idle
IF NOW - lastActivity > idleTimeout THEN
showWelcome()
lastActivity = NOW
END IF
WAIT 0.5
GOTO mainLoop
' ============================================================
SUB handleQuery(query)
' Log the query
INSERT "kiosk_queries", {
"timestamp": NOW,
"query": query
}
' Determine intent
intent = LLM "Classify query: '" + query + "'. Categories: directions, hours, services, general, weather. Return JSON: {category: string, details: string}"
intent = JSON PARSE intent
SELECT CASE intent.category
CASE "directions"
handleDirections(intent.details)
CASE "hours"
handleHours(intent.details)
CASE "services"
handleServices(intent.details)
CASE "weather"
handleWeather()
CASE ELSE
handleGeneral(query)
END SELECT
END SUB
SUB handleDirections(destination)
' Look up location in database
location = FIND "locations", "name LIKE '%" + destination + "%'"
IF location THEN
TALK "To get to " + location.name + ": " + location.directions
ELSE
TALK "I'm sorry, I don't have directions to " + destination + ". Please ask at the front desk."
END IF
END SUB
SUB handleHours(department)
hours = FIND "hours", "department LIKE '%" + department + "%'"
IF hours THEN
TALK hours.department + " is open " + hours.schedule
ELSE
TALK "Standard hours are Monday to Friday, 9 AM to 5 PM."
END IF
END SUB
SUB handleServices(service)
info = FIND "services", "name LIKE '%" + service + "%'"
IF info THEN
TALK info.description
ELSE
' Use KB for general info
USE KB "services"
answer = LLM "What services are available for: " + service
TALK answer
END IF
END SUB
SUB handleWeather()
weather = WEATHER "local"
TALK "Current weather: " + weather.description + ", " + weather.temperature + " degrees."
END SUB
SUB handleGeneral(query)
' Use KB for general questions
USE KB "faq"
answer = LLM query
TALK answer
END SUB
SUB showWelcome()
TALK welcomeMessage
END SUB
```
---
## Usage
### Installing Templates
1. Create a `.gbdialog` folder in your bot package:
```bash
mkdir -p mybot.gbai/mybot.gbdialog
```
2. Copy the desired template:
```bash
cp template-embedded.md mybot.gbai/mybot.gbdialog/thermostat.bas
```
3. Edit configuration at the top of the file
4. Deploy to your device:
```bash
./scripts/deploy-embedded.sh pi@mydevice --with-ui
```
### Customizing
Each template has a configuration section at the top:
```bas
' Configuration
targetTemp = 22 ' Target temperature in Celsius
heatingPin = 17 ' GPIO pin for relay
sensorPin = 4 ' GPIO pin for sensor
```
Modify these values to match your hardware setup.
### Combining Templates
You can combine functionality from multiple templates into a single dialog:
```bas
' Combined home automation
INCLUDE "thermostat.bas"
INCLUDE "light-control.bas"
INCLUDE "security.bas"
' Main loop handles all systems
mainLoop:
checkThermostat()
checkLights()
checkSecurity()
WAIT 1
GOTO mainLoop

View file

@ -0,0 +1,528 @@
# GPIO & IoT Keywords
Control hardware directly from BASIC dialogs. These keywords work on Raspberry Pi, Orange Pi, and other SBCs running botserver.
## Overview
```
┌────────────────────────────────────────────────────────────────────────┐
│ GPIO Keyword Architecture │
├────────────────────────────────────────────────────────────────────────┤
│ │
│ BASIC Dialog botserver Hardware │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ GPIO SET │────────▶│ sysfs/ │────────▶│ Pin │ │
│ │ GPIO GET │◀────────│ gpiod │◀────────│ State │ │
│ │ I2C READ │◀────────│ i2c-dev │◀────────│ Sensor │ │
│ │ SPI WRITE│────────▶│ spidev │────────▶│ Display │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │
└────────────────────────────────────────────────────────────────────────┘
```
## GPIO Keywords
### GPIO MODE
Set a GPIO pin as input or output.
```bas
' Set pin 17 as output (for LED, relay)
GPIO MODE 17, "OUTPUT"
' Set pin 27 as input (for button, sensor)
GPIO MODE 27, "INPUT"
' Set input with pull-up resistor
GPIO MODE 27, "INPUT_PULLUP"
' Set input with pull-down resistor
GPIO MODE 22, "INPUT_PULLDOWN"
```
### GPIO SET
Set the state of an output pin.
```bas
' Turn on LED (HIGH = 3.3V)
GPIO SET 17, HIGH
' Turn off LED (LOW = 0V)
GPIO SET 17, LOW
' Using numeric values (1 = HIGH, 0 = LOW)
GPIO SET 17, 1
GPIO SET 17, 0
```
### GPIO GET
Read the state of an input pin.
```bas
' Read button state
GPIO MODE 27, "INPUT_PULLUP"
state = GPIO GET 27
IF state = LOW THEN
TALK "Button pressed!"
END IF
```
### GPIO PWM
Generate PWM signal for motor speed, LED brightness.
```bas
' Set PWM on pin 18, duty cycle 0-100
GPIO PWM 18, 50 ' 50% duty cycle
' Fade LED
FOR brightness = 0 TO 100 STEP 5
GPIO PWM 18, brightness
WAIT 0.05
NEXT
' Stop PWM
GPIO PWM 18, 0
```
### GPIO SERVO
Control servo motors (uses hardware PWM).
```bas
' Move servo to angle (0-180 degrees)
GPIO SERVO 12, 90 ' Center position
GPIO SERVO 12, 0 ' Left position
GPIO SERVO 12, 180 ' Right position
```
## I2C Keywords
For sensors and displays connected via I2C bus.
### I2C SCAN
Scan for connected I2C devices.
```bas
' Scan I2C bus 1 (default on Pi)
devices = I2C SCAN 1
FOR EACH addr IN devices
TALK "Found device at address: " + HEX(addr)
NEXT
```
### I2C READ
Read data from an I2C device.
```bas
' Read temperature from sensor at address 0x48
' Register 0x00 contains temperature
temp_raw = I2C READ 0x48, 0x00, 2 ' Read 2 bytes
' Convert to temperature
temperature = temp_raw / 256.0
TALK "Temperature: " + temperature + "°C"
```
### I2C WRITE
Write data to an I2C device.
```bas
' Write configuration to sensor
I2C WRITE 0x48, 0x01, 0x60 ' Write 0x60 to register 0x01
' Write multiple bytes
I2C WRITE 0x3C, 0x00, [0xAE, 0xD5, 0x80] ' OLED init sequence
```
## SPI Keywords
For high-speed communication with displays and sensors.
### SPI OPEN
Open SPI device.
```bas
' Open SPI device 0, chip select 0
SPI OPEN 0, 0, 1000000 ' 1MHz clock speed
```
### SPI TRANSFER
Send and receive data.
```bas
' Send command to display
response = SPI TRANSFER [0x9F] ' Read ID command
' Send data to display
SPI TRANSFER [0x00, 0xFF, 0x00, 0xFF] ' Pattern data
```
### SPI CLOSE
Close SPI connection.
```bas
SPI CLOSE 0, 0
```
## Sensor Keywords
High-level keywords for common sensors.
### READ TEMPERATURE
Read temperature from common sensors (auto-detects DHT11, DHT22, DS18B20, BME280).
```bas
temp = READ TEMPERATURE 4 ' GPIO pin 4
TALK "Temperature: " + temp + "°C"
```
### READ HUMIDITY
Read humidity from DHT11/DHT22/BME280.
```bas
humidity = READ HUMIDITY 4
TALK "Humidity: " + humidity + "%"
```
### READ DISTANCE
Read distance from ultrasonic sensor (HC-SR04).
```bas
' Trigger pin 23, Echo pin 24
distance = READ DISTANCE 23, 24
TALK "Distance: " + distance + " cm"
```
### READ MOTION
Read PIR motion sensor.
```bas
GPIO MODE 7, "INPUT"
motion = READ MOTION 7
IF motion THEN
TALK "Motion detected!"
GPIO SET 17, HIGH ' Turn on light
END IF
```
### READ LIGHT
Read light level from photoresistor or light sensor.
```bas
light = READ LIGHT 0 ' ADC channel 0 (MCP3008)
TALK "Light level: " + light
```
## Display Keywords
### LCD INIT
Initialize character LCD (HD44780).
```bas
' I2C LCD at address 0x27, 16 columns, 2 rows
LCD INIT 0x27, 16, 2
```
### LCD PRINT
Print text to LCD.
```bas
LCD PRINT "Hello World!"
' Print at specific position (row, column)
LCD PRINT 0, 0, "Line 1"
LCD PRINT 1, 0, "Line 2"
```
### LCD CLEAR
Clear the LCD display.
```bas
LCD CLEAR
```
### OLED INIT
Initialize OLED display (SSD1306).
```bas
' I2C OLED at address 0x3C, 128x64 pixels
OLED INIT 0x3C, 128, 64
```
### OLED PRINT
Print text to OLED.
```bas
OLED PRINT "Hello!"
' With position and size
OLED PRINT 0, 0, "Title", 2 ' Size 2x
OLED PRINT 0, 20, "Subtitle", 1
```
### OLED DRAW
Draw shapes on OLED.
```bas
' Draw rectangle
OLED DRAW "rect", 10, 10, 50, 30
' Draw circle
OLED DRAW "circle", 64, 32, 20
' Draw line
OLED DRAW "line", 0, 0, 127, 63
```
### OLED CLEAR
Clear the OLED display.
```bas
OLED CLEAR
```
## Relay & Actuator Keywords
### RELAY SET
Control relay module.
```bas
' Turn on relay 1 (pin 17)
RELAY SET 17, ON
' Turn off relay
RELAY SET 17, OFF
' Toggle relay
state = GPIO GET 17
RELAY SET 17, NOT state
```
### BUZZER
Control buzzer for alerts.
```bas
' Beep for 0.5 seconds
BUZZER 18, 0.5
' Play tone (frequency, duration)
BUZZER 18, 1000, 0.2 ' 1000Hz for 0.2 seconds
' Play melody
BUZZER 18, 262, 0.25 ' C4
BUZZER 18, 294, 0.25 ' D4
BUZZER 18, 330, 0.25 ' E4
```
## Complete Examples
### Smart Doorbell
```bas
' Smart doorbell with camera and notification
' Hardware: Button on GPIO 27, Buzzer on GPIO 18, LED on GPIO 17
GPIO MODE 27, "INPUT_PULLUP"
GPIO MODE 18, "OUTPUT"
GPIO MODE 17, "OUTPUT"
TALK "Doorbell system ready"
LCD PRINT "Ring the bell"
mainLoop:
button = GPIO GET 27
IF button = LOW THEN
' Button pressed
GPIO SET 17, HIGH ' LED on
BUZZER 18, 1000, 0.5 ' Ring buzzer
' Take photo (if camera connected)
photo = CAPTURE PHOTO
' Send notification
SEND MAIL "owner@home.com", "Doorbell", "Someone at the door!", photo
LCD PRINT "Visitor!"
WAIT 2
LCD PRINT "Ring the bell"
GPIO SET 17, LOW ' LED off
END IF
WAIT 0.1
GOTO mainLoop
```
### Temperature Monitor
```bas
' Temperature and humidity monitor with OLED display
' Hardware: DHT22 on GPIO 4, OLED on I2C 0x3C
OLED INIT 0x3C, 128, 64
mainLoop:
temp = READ TEMPERATURE 4
humidity = READ HUMIDITY 4
OLED CLEAR
OLED PRINT 0, 0, "Temperature:", 1
OLED PRINT 0, 15, temp + " C", 2
OLED PRINT 0, 40, "Humidity:", 1
OLED PRINT 0, 55, humidity + " %", 2
' Alert if too hot
IF temp > 30 THEN
BUZZER 18, 2000, 0.1
SEND MAIL "admin@home.com", "Alert", "Temperature high: " + temp + "C"
END IF
WAIT 5 ' Update every 5 seconds
GOTO mainLoop
```
### Light Automation
```bas
' Automatic light control based on motion and ambient light
' Hardware: PIR on GPIO 7, Light sensor on ADC0, Relay on GPIO 17
GPIO MODE 7, "INPUT"
GPIO MODE 17, "OUTPUT"
threshold = 500 ' Light threshold
timeout = 30 ' Seconds to keep light on
lastMotion = 0
mainLoop:
motion = READ MOTION 7
light = READ LIGHT 0
IF motion AND light < threshold THEN
' Dark and motion detected
RELAY SET 17, ON
lastMotion = NOW
LCD PRINT "Light ON"
END IF
' Turn off after timeout
IF NOW - lastMotion > timeout THEN
RELAY SET 17, OFF
LCD PRINT "Light OFF"
END IF
WAIT 0.5
GOTO mainLoop
```
### Voice-Controlled Lights
```bas
' Voice control for home automation
' Ask the AI to control lights
TALK "What would you like me to do?"
command = HEAR
' Use LLM to understand command
intent = LLM "Extract intent from: '" + command + "'. Return JSON: {action: on/off, room: string}"
intent = JSON PARSE intent
SELECT CASE intent.room
CASE "living room"
RELAY SET 17, intent.action = "on"
CASE "bedroom"
RELAY SET 18, intent.action = "on"
CASE "kitchen"
RELAY SET 27, intent.action = "on"
CASE "all"
RELAY SET 17, intent.action = "on"
RELAY SET 18, intent.action = "on"
RELAY SET 27, intent.action = "on"
END SELECT
TALK "Done! " + intent.room + " light is now " + intent.action
```
## Pin Reference
### Raspberry Pi GPIO
| Pin | GPIO | Common Use |
|-----|------|------------|
| 11 | GPIO17 | Output (LED, Relay) |
| 12 | GPIO18 | PWM (Motor, Servo) |
| 13 | GPIO27 | Input (Button) |
| 15 | GPIO22 | Input/Output |
| 16 | GPIO23 | Input/Output |
| 18 | GPIO24 | Input/Output |
| 3 | SDA | I2C Data |
| 5 | SCL | I2C Clock |
| 19 | MOSI | SPI Data Out |
| 21 | MISO | SPI Data In |
| 23 | SCLK | SPI Clock |
### Orange Pi GPIO
Similar pinout, but check your specific model. Orange Pi 5 uses different GPIO numbering.
## Troubleshooting
### Permission Denied
```bash
# Add user to gpio group
sudo usermod -a -G gpio $USER
sudo usermod -a -G i2c $USER
sudo usermod -a -G spi $USER
# Or run botserver with elevated privileges
sudo systemctl edit botserver
# Add: User=root
```
### I2C Not Working
```bash
# Enable I2C
sudo raspi-config # Interface Options → I2C
# Check if device detected
i2cdetect -y 1
```
### GPIO Busy
```bash
# Check what's using the GPIO
cat /sys/kernel/debug/gpio
# Release GPIO
echo 17 > /sys/class/gpio/unexport

View file

@ -0,0 +1,324 @@
# Beginner's Guide: Buying Your First SBC
A complete guide for beginners who want to buy a Single Board Computer (SBC) and start automating their home or workplace with General Bots.
## What is an SBC?
A Single Board Computer (SBC) is a complete computer on a single circuit board. Unlike a desktop PC, it's:
- **Small** - Credit card to smartphone size
- **Low power** - 2-15 watts (vs 200W+ for a PC)
- **Affordable** - $15-150 depending on power
- **Quiet** - No fans on most models
- **GPIO equipped** - Can connect to sensors and actuators
## Which SBC Should I Buy?
### Decision Flowchart
```
┌─────────────────────────┐
│ What's your budget? │
└───────────┬─────────────┘
┌───────────────────┼───────────────────┐
▼ ▼ ▼
Under $30 $30-80 $80-150
│ │ │
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ Orange Pi │ │ Raspberry Pi │ │ Orange Pi 5 │
│ Zero 3 │ │ 4 / 5 │ │ (with NPU) │
│ │ │ │ │ │
│ Basic display │ │ Full desktop │ │ Local AI/LLM │
│ Simple tasks │ │ Most projects │ │ Edge AI │
└───────────────┘ └───────────────┘ └───────────────┘
```
### Recommended Starter Kits
#### 🌟 Best for Beginners: Raspberry Pi 4 Kit (~$80)
**What to buy:**
- Raspberry Pi 4 Model B (4GB RAM) - $55
- Official power supply (USB-C 5V 3A) - $8
- 32GB microSD card (Class 10) - $8
- Case with heatsink - $10
**Where to buy:**
- [The Pi Hut](https://thepihut.com) (UK)
- [Adafruit](https://adafruit.com) (US)
- [Amazon](https://amazon.com) (Worldwide)
- AliExpress (Budget option, slower shipping)
#### 💰 Budget Option: Orange Pi Zero 3 Kit (~$35)
**What to buy:**
- Orange Pi Zero 3 (1GB RAM) - $20
- 5V 2A power supply - $5
- 16GB microSD card - $5
- Acrylic case - $5
#### 🧠 Best for AI: Orange Pi 5 Kit (~$120)
**What to buy:**
- Orange Pi 5 (8GB RAM) - $89
- 12V 2A power supply - $10
- 64GB microSD or NVMe SSD - $15
- Cooling fan case - $10
This board has a 6 TOPS NPU for accelerated AI inference!
## What Else Do I Need?
### Essential Accessories
| Item | Purpose | Price Range |
|------|---------|-------------|
| microSD Card | Operating system storage | $8-15 |
| Power Supply | Power the board | $8-15 |
| Ethernet Cable | Wired network (faster) | $5 |
| HDMI Cable | Connect to monitor/TV | $5-10 |
| USB Keyboard | Initial setup | $10-20 |
### For Display Projects
| Item | Purpose | Price Range |
|------|---------|-------------|
| **3.5" TFT LCD** | Small color touchscreen | $15-25 |
| **7" HDMI LCD** | Larger display | $40-60 |
| **16x2 LCD** | Simple text display | $5-10 |
| **0.96" OLED** | Tiny status display | $5-8 |
### For Home Automation
| Item | Purpose | Price Range |
|------|---------|-------------|
| **Relay Module (4ch)** | Control lights, appliances | $5-10 |
| **DHT22 Sensor** | Temperature & humidity | $5-8 |
| **PIR Sensor** | Motion detection | $3-5 |
| **Buzzer** | Alerts and notifications | $2-3 |
| **Jumper Wires** | Connect components | $3-5 |
| **Breadboard** | Prototyping | $3-5 |
## Sample Shopping Lists
### Home Temperature Monitor ($45)
Perfect first project - monitor and log temperature!
```
□ Orange Pi Zero 3 (1GB) $20
□ 16GB microSD card $5
□ 5V 2A power supply $5
□ DHT22 temperature sensor $6
□ 0.96" OLED display (I2C) $6
□ Jumper wires (female-female) $3
─────────────
Total: $45
```
### Smart Doorbell ($70)
AI-powered doorbell with notifications!
```
□ Raspberry Pi Zero 2 W $15
□ Pi Camera Module $25
□ Push button $1
□ Piezo buzzer $2
□ LED (with resistor) $1
□ 16GB microSD card $5
□ 5V 2.5A power supply $8
□ Case $5
□ Jumper wires $3
─────────────
Total: $70
```
### Offline AI Assistant ($150)
Run AI completely offline - no internet needed!
```
□ Orange Pi 5 (8GB RAM) $89
□ 128GB NVMe SSD $20
□ 12V 3A power supply $12
□ 7" HDMI touchscreen $45
□ USB microphone $10
□ Case with fan $15
□ Jumper wires $3
─────────────
Total: ~$195
```
### Voice-Controlled Lights ($55)
Control your lights by talking!
```
□ Raspberry Pi 4 (2GB) $35
□ 4-channel relay module $6
□ USB microphone $8
□ 16GB microSD card $5
□ 5V 3A power supply $8
□ Jumper wires $3
─────────────
Total: ~$65
```
## Where to Buy (By Region)
### United States
- **Amazon** - Fast shipping, good returns
- **Adafruit** - Quality accessories, great tutorials
- **SparkFun** - Sensors and components
- **Micro Center** - If you have one nearby!
### Europe
- **The Pi Hut** (UK) - Official Pi reseller
- **Pimoroni** (UK) - Creative accessories
- **Amazon.de/.fr/.es** - Local shipping
- **Conrad** (Germany) - Electronics store
### Asia
- **AliExpress** - Cheapest, 2-4 week shipping
- **Taobao** (China) - Even cheaper if you read Chinese
- **Amazon.co.jp** (Japan)
### South America
- **MercadoLivre** (Brazil) - Local marketplace
- **FilipeFlop** (Brazil) - Arduino/Pi specialist
- **Amazon.com.br** - Limited selection
### Tips for AliExpress
- Check seller ratings (97%+ is good)
- Read reviews with photos
- Expect 2-4 weeks shipping
- Buy from China Direct for best prices
- Consider "Choice" items for faster shipping
## First-Time Setup Guide
### Step 1: Flash the OS
1. Download [Raspberry Pi Imager](https://www.raspberrypi.com/software/)
2. Insert your microSD card
3. Select:
- **Device**: Your board
- **OS**: Raspberry Pi OS Lite (64-bit)
- **Storage**: Your microSD
4. Click **EDIT SETTINGS**:
- Set hostname: `mybot`
- Enable SSH
- Set username/password
- Configure WiFi
5. Click **WRITE**
### Step 2: First Boot
1. Insert microSD into your SBC
2. Connect power
3. Wait 2 minutes for first boot
4. Find your device:
```bash
# On your computer
ping mybot.local
# or check your router's device list
```
### Step 3: Connect via SSH
```bash
ssh pi@mybot.local
# Enter your password
```
### Step 4: Install General Bots
```bash
# Quick install
curl -fsSL https://get.generalbots.com | bash
# Or use the deploy script
git clone https://github.com/GeneralBots/botserver.git
cd botserver
./scripts/deploy-embedded.sh --local --with-ui
```
### Step 5: Access the Interface
Open in your browser:
```
http://mybot.local:8088
```
## Common Beginner Mistakes
### ❌ Wrong Power Supply
**Problem**: Board keeps rebooting or won't start
**Solution**:
- Raspberry Pi 4/5: Use **official** 5V 3A USB-C PSU
- Orange Pi 5: Use **12V** 2A, not 5V!
- Don't use phone chargers - they can't supply enough current
### ❌ Cheap/Slow microSD Card
**Problem**: Slow boot, random crashes, data corruption
**Solution**:
- Buy **Class 10** or **A1/A2** rated cards
- Good brands: SanDisk, Samsung, Kingston
- Avoid no-name cards from AliExpress
### ❌ No Heatsink/Cooling
**Problem**: Board throttles or overheats
**Solution**:
- Always use heatsinks on the CPU
- Consider a fan for Pi 4/5 or Orange Pi 5
- Use a case with ventilation
### ❌ Connecting to Wrong Voltage
**Problem**: Fried components, magic smoke
**Solution**:
- Raspberry Pi GPIO is **3.3V** only!
- Never connect 5V to GPIO pins
- Use level shifters for 5V sensors
## Getting Help
### Community Resources
- [Raspberry Pi Forums](https://forums.raspberrypi.com)
- [Orange Pi Forums](http://www.orangepi.org/orangepibbsen/)
- [General Bots Discord](https://discord.gg/generalbots)
- [r/raspberry_pi](https://reddit.com/r/raspberry_pi)
### Recommended YouTube Channels
- **ExplainingComputers** - Great SBC reviews
- **Jeff Geerling** - Deep Pi tutorials
- **Andreas Spiess** - IoT and sensors
- **DroneBot Workshop** - Beginner friendly
### Books
- "Getting Started with Raspberry Pi" - Matt Richardson
- "Make: Electronics" - Charles Platt
## Next Steps
Once you have your SBC:
1. **[Quick Start Guide](./quick-start.md)** - Get GB running in 5 minutes
2. **[GPIO Keywords](../06-gbdialog/keywords-gpio.md)** - Control hardware with BASIC
3. **[Templates](../02-templates/template-embedded.md)** - Ready-made automation projects
4. **[Local LLM](./local-llm.md)** - Add offline AI capabilities
Happy building! 🤖

View file

@ -4,15 +4,15 @@ Deploy General Bots as the primary interface on Android and HarmonyOS devices, t
## Overview
BotOS transforms any Android or HarmonyOS device into a dedicated General Bots system, removing manufacturer bloatware and installing GB as the default launcher.
BotDevice transforms any Android or HarmonyOS device into a dedicated General Bots system, removing manufacturer bloatware and installing GB as the default launcher.
```
┌─────────────────────────────────────────────────────────────────────────────┐
BotOS Architecture
BotDevice Architecture
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ BotOS App (Tauri) │ │
│ │ BotDevice App (Tauri) │ │
│ ├──────────────────────────────────────────────────────────────────┤ │
│ │ botui/ui/suite │ Tauri Android │ src/lib.rs (Rust) │ │
│ │ (Web Interface) │ (WebView + NDK) │ (Backend + Hardware) │ │
@ -46,18 +46,18 @@ BotOS transforms any Android or HarmonyOS device into a dedicated General Bots s
| Level | Requirements | What It Does |
|-------|-------------|--------------|
| **Level 1** | ADB only | Removes bloatware, installs BotOS as app |
| **Level 2** | Root + Magisk | GB boot animation, BotOS as system app |
| **Level 3** | Unlocked bootloader | Full Android replacement with BotOS |
| **Level 1** | ADB only | Removes bloatware, installs BotDevice as app |
| **Level 2** | Root + Magisk | GB boot animation, BotDevice as system app |
| **Level 3** | Unlocked bootloader | Full Android replacement with BotDevice |
## Quick Installation
### Level 1: Debloat + App (No Root)
```bash
# Clone botos repository
git clone https://github.com/GeneralBots/botos.git
cd botos/rom
# Clone botdevice repository
git clone https://github.com/GeneralBots/botdevice.git
cd botdevice/rom
# Connect device via USB (enable USB debugging first)
./install.sh
@ -66,18 +66,18 @@ cd botos/rom
The interactive installer will:
1. Detect your device and manufacturer
2. Remove bloatware automatically
3. Install BotOS APK
3. Install BotDevice APK
4. Optionally set as default launcher
### Level 2: Magisk Module (Root Required)
```bash
# Generate Magisk module
cd botos/rom/scripts
cd botdevice/rom/scripts
./build-magisk-module.sh
# Copy to device
adb push botos-magisk-v1.0.zip /sdcard/
adb push botdevice-magisk-v1.0.zip /sdcard/
# Install via Magisk app
# Magisk → Modules → + → Select ZIP → Reboot
@ -85,12 +85,12 @@ adb push botos-magisk-v1.0.zip /sdcard/
This adds:
- Custom boot animation
- BotOS as system app (privileged permissions)
- BotDevice as system app (privileged permissions)
- Debloat via overlay
### Level 3: GSI (Full Replacement)
For advanced users with unlocked bootloader. See `botos/rom/gsi/README.md`.
For advanced users with unlocked bootloader. See `botdevice/rom/gsi/README.md`.
## Bloatware Removed
@ -143,7 +143,7 @@ sudo apt install librsvg2-bin imagemagick
### Build APK
```bash
cd botos
cd botdevice
# Generate icons from SVG
./scripts/generate-icons.sh
@ -164,14 +164,14 @@ Output: `gen/android/app/build/outputs/apk/release/app-release.apk`
cargo tauri android dev
# Watch logs
adb logcat -s BotOS:*
adb logcat -s BotDevice:*
```
## Configuration
### AndroidManifest.xml
BotOS is configured as a launcher:
BotDevice is configured as a launcher:
```xml
<intent-filter>
@ -214,7 +214,7 @@ Create custom boot animation with GB branding:
```bash
# Generate animation
cd botos/scripts
cd botdevice/scripts
./create-bootanimation.sh
# Install (requires root)
@ -227,7 +227,7 @@ adb reboot
## Project Structure
```
botos/
botdevice/
├── Cargo.toml # Rust/Tauri dependencies
├── tauri.conf.json # Tauri config → botui/ui/suite
├── build.rs # Build script
@ -261,7 +261,7 @@ botos/
## Offline Mode
BotOS can work offline with local LLM:
BotDevice can work offline with local LLM:
1. Install botserver on the device (see [Local LLM](./local-llm.md))
2. Configure to use localhost:
@ -298,7 +298,7 @@ BotOS can work offline with local LLM:
# Settings → Security → Unknown Sources
# Or use ADB
adb install -r botos.apk
adb install -r botdevice.apk
```
### Debloat Not Working

View file

@ -37,6 +37,7 @@
- [Template: CRM Contacts](./02-templates/template-crm-contacts.md)
- [Template: Attendance CRM](./02-templates/template-attendance-crm.md)
- [Template: Marketing](./02-templates/template-marketing.md)
- [Template: Embedded Devices](./02-templates/template-embedded.md)
- [Template: Creating Templates](./02-templates/template-template.md)
# Part III - Knowledge Base
@ -201,6 +202,7 @@
- [QR CODE](./06-gbdialog/keyword-qrcode.md)
- [SEND SMS](./06-gbdialog/keyword-sms.md)
- [START MEET / JOIN MEET](./06-gbdialog/keyword-start-meet.md)
- [GPIO & IoT Keywords](./06-gbdialog/keywords-gpio.md)
- [File Operations](./06-gbdialog/keywords-file.md)
- [READ](./06-gbdialog/keyword-read.md)
- [WRITE](./06-gbdialog/keyword-write.md)
@ -323,6 +325,7 @@
# Part XII - Device & Offline Deployment
- [Chapter 13: Device Deployment](./13-devices/README.md)
- [Buying Guide for Beginners](./13-devices/buying-guide.md)
- [Mobile (Android & HarmonyOS)](./13-devices/mobile.md)
- [Supported Hardware (SBCs)](./13-devices/hardware.md)
- [Quick Start](./13-devices/quick-start.md)

View file

@ -0,0 +1,124 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 500" width="1200" height="500">
<defs>
<style>
.title { font: bold 20px Arial, sans-serif; fill: #333; }
.box-label { font: bold 13px Arial, sans-serif; fill: #333; }
.small-text { font: 11px Arial, sans-serif; fill: #666; }
@media (prefers-color-scheme: dark) {
.title { fill: #eee; }
.box-label { fill: #eee; }
.small-text { fill: #ccc; }
}
</style>
</defs>
<rect width="100%" height="100%" fill="transparent"/>
<text x="600" y="35" text-anchor="middle" class="title">Embedded GB Architecture</text>
<!-- User Input -->
<g transform="translate(50, 60)">
<rect width="200" height="160" rx="8" fill="#E3F2FD" stroke="#1976D2" stroke-width="2"/>
<text x="100" y="25" text-anchor="middle" class="box-label">User Input</text>
<rect x="15" y="40" width="50" height="45" rx="4" fill="#BBDEFB" stroke="#1976D2"/>
<text x="40" y="68" text-anchor="middle" class="small-text">Keyboard</text>
<rect x="75" y="40" width="50" height="45" rx="4" fill="#BBDEFB" stroke="#1976D2"/>
<text x="100" y="68" text-anchor="middle" class="small-text">Touch</text>
<rect x="135" y="40" width="50" height="45" rx="4" fill="#BBDEFB" stroke="#1976D2"/>
<text x="160" y="68" text-anchor="middle" class="small-text">GPIO</text>
<rect x="15" y="95" width="170" height="50" rx="4" fill="#BBDEFB" stroke="#1976D2"/>
<text x="100" y="125" text-anchor="middle" class="small-text">Sensors (I2C/SPI)</text>
</g>
<!-- Display Output -->
<g transform="translate(50, 250)">
<rect width="200" height="120" rx="8" fill="#F3E5F5" stroke="#7B1FA2" stroke-width="2"/>
<text x="100" y="25" text-anchor="middle" class="box-label">Display</text>
<rect x="10" y="40" width="40" height="35" rx="4" fill="#E1BEE7" stroke="#7B1FA2"/>
<text x="30" y="62" text-anchor="middle" class="small-text">LCD</text>
<rect x="55" y="40" width="40" height="35" rx="4" fill="#E1BEE7" stroke="#7B1FA2"/>
<text x="75" y="62" text-anchor="middle" class="small-text">OLED</text>
<rect x="100" y="40" width="40" height="35" rx="4" fill="#E1BEE7" stroke="#7B1FA2"/>
<text x="120" y="62" text-anchor="middle" class="small-text">TFT</text>
<rect x="145" y="40" width="45" height="35" rx="4" fill="#E1BEE7" stroke="#7B1FA2"/>
<text x="168" y="62" text-anchor="middle" class="small-text">HDMI</text>
</g>
<!-- BotServer -->
<g transform="translate(320, 80)">
<rect width="240" height="280" rx="10" fill="#E8F5E9" stroke="#388E3C" stroke-width="2"/>
<text x="120" y="30" text-anchor="middle" class="box-label">botserver (Rust)</text>
<text x="120" y="50" text-anchor="middle" class="small-text">Port 8088</text>
<rect x="20" y="70" width="200" height="40" rx="4" fill="#C8E6C9" stroke="#388E3C"/>
<text x="120" y="95" text-anchor="middle" class="small-text">BASIC Interpreter</text>
<rect x="20" y="120" width="200" height="40" rx="4" fill="#C8E6C9" stroke="#388E3C"/>
<text x="120" y="145" text-anchor="middle" class="small-text">GPIO Keywords</text>
<rect x="20" y="170" width="200" height="40" rx="4" fill="#C8E6C9" stroke="#388E3C"/>
<text x="120" y="195" text-anchor="middle" class="small-text">SQLite Database</text>
<rect x="20" y="220" width="200" height="40" rx="4" fill="#C8E6C9" stroke="#388E3C"/>
<text x="120" y="245" text-anchor="middle" class="small-text">Embedded UI Server</text>
</g>
<!-- LLM Server -->
<g transform="translate(630, 80)">
<rect width="200" height="150" rx="10" fill="#FFF3E0" stroke="#F57C00" stroke-width="2"/>
<text x="100" y="30" text-anchor="middle" class="box-label">llama.cpp</text>
<text x="100" y="50" text-anchor="middle" class="small-text">Port 8080 (Optional)</text>
<rect x="20" y="70" width="160" height="30" rx="4" fill="#FFE0B2" stroke="#F57C00"/>
<text x="100" y="90" text-anchor="middle" class="small-text">TinyLlama GGUF</text>
<rect x="20" y="105" width="160" height="30" rx="4" fill="#FFE0B2" stroke="#F57C00"/>
<text x="100" y="125" text-anchor="middle" class="small-text">NPU Acceleration</text>
</g>
<!-- SBC Hardware -->
<g transform="translate(630, 260)">
<rect width="200" height="100" rx="10" fill="#ECEFF1" stroke="#607D8B" stroke-width="2"/>
<text x="100" y="25" text-anchor="middle" class="box-label">SBC Hardware</text>
<text x="100" y="50" text-anchor="middle" class="small-text">Orange Pi / Raspberry Pi</text>
<text x="100" y="70" text-anchor="middle" class="small-text">ARM64 CPU + NPU</text>
<text x="100" y="90" text-anchor="middle" class="small-text">1-16GB RAM</text>
</g>
<!-- Actuators -->
<g transform="translate(900, 80)">
<rect width="180" height="150" rx="10" fill="#FCE4EC" stroke="#C2185B" stroke-width="2"/>
<text x="90" y="25" text-anchor="middle" class="box-label">Actuators</text>
<rect x="15" y="45" width="70" height="35" rx="4" fill="#F8BBD9" stroke="#C2185B"/>
<text x="50" y="68" text-anchor="middle" class="small-text">Relay</text>
<rect x="95" y="45" width="70" height="35" rx="4" fill="#F8BBD9" stroke="#C2185B"/>
<text x="130" y="68" text-anchor="middle" class="small-text">Motor</text>
<rect x="15" y="90" width="70" height="35" rx="4" fill="#F8BBD9" stroke="#C2185B"/>
<text x="50" y="113" text-anchor="middle" class="small-text">LED</text>
<rect x="95" y="90" width="70" height="35" rx="4" fill="#F8BBD9" stroke="#C2185B"/>
<text x="130" y="113" text-anchor="middle" class="small-text">Buzzer</text>
</g>
<!-- Cloud (Optional) -->
<g transform="translate(900, 260)">
<rect width="180" height="100" rx="10" fill="#E0F7FA" stroke="#00838F" stroke-width="2" stroke-dasharray="5,3"/>
<text x="90" y="25" text-anchor="middle" class="box-label">Cloud (Optional)</text>
<text x="90" y="50" text-anchor="middle" class="small-text">Remote botserver</text>
<text x="90" y="70" text-anchor="middle" class="small-text">LLM APIs</text>
<text x="90" y="90" text-anchor="middle" class="small-text">Updates</text>
</g>
<!-- Arrows -->
<defs>
<marker id="arrowhead" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
<polygon points="0 0, 10 3.5, 0 7" fill="#666"/>
</marker>
</defs>
<!-- Input to Server -->
<line x1="250" y1="140" x2="320" y2="180" stroke="#666" stroke-width="2" marker-end="url(#arrowhead)"/>
<!-- Display from Server -->
<line x1="320" y1="280" x2="250" y2="310" stroke="#666" stroke-width="2" marker-end="url(#arrowhead)"/>
<!-- Server to LLM -->
<line x1="560" y1="155" x2="630" y2="155" stroke="#666" stroke-width="2" marker-end="url(#arrowhead)"/>
<!-- Server to Actuators -->
<line x1="560" y1="200" x2="900" y2="155" stroke="#666" stroke-width="2" marker-end="url(#arrowhead)"/>
<!-- Server to Cloud -->
<line x1="560" y1="320" x2="900" y2="310" stroke="#666" stroke-width="2" stroke-dasharray="5,3" marker-end="url(#arrowhead)"/>
</svg>

After

Width:  |  Height:  |  Size: 6.9 KiB