01 System Overview
Public edge, mini-program, backend, database, MQTT, device, and external providers.
Runtime Architecture
flowchart LR
subgraph WeChat["WeChat Ecosystem"]
Mini["banban-mini\nTaro WeChat mini-program"]
WxLogin["WeChat login / phone APIs"]
WxMP["WeChat Official Account\nnotifications and bind"]
end
subgraph Edge["Public Edge"]
Domain["banban.api.talkingq.com"]
Nginx["Nginx / TLS"]
end
subgraph Backend["talkingq-url FastAPI backend"]
Main["main.py\nFastAPI app + lifespan"]
AuthMW["banban auth middleware"]
BanbanRouter["banban routers\nchildren, devices, binding, chat,\nlocation, alarms, firmware, roles,\nwechat-mp"]
MqttSvc["TalkingQMQTTService"]
Scheduler["TaskScheduler\ncleanup and periodic tasks"]
StaticAssets["/assets static files"]
end
subgraph Data["Stateful Services"]
MySQL["MySQL\nshared banban schema"]
COS["Tencent COS\nmessage audio files"]
MQTT["MQTT broker"]
end
subgraph DeviceSide["Device Side"]
Device["TalkingQ device"]
NFC["NFC card"]
end
subgraph External["External Providers"]
MapSvc["Map / reverse geocoding provider"]
SMS["SMS provider"]
end
Mini -->|HTTPS /banban/*| Domain --> Nginx --> Main
Main --> AuthMW --> BanbanRouter
Main --> StaticAssets
Main --> Scheduler
Main --> MqttSvc
BanbanRouter --> MySQL
MqttSvc --> MQTT
Device -->|device/{id}/event,response| MQTT
MQTT -->|subscribed messages| MqttSvc
MqttSvc --> MySQL
Device --> NFC
BanbanRouter --> COS
MqttSvc --> COS
BanbanRouter --> WxLogin
BanbanRouter --> WxMP
BanbanRouter --> SMS
MqttSvc --> MapSvc
talkingq-url/main.py, banban-mini/src/services/*, database/talkingq_shared_schema.sql02 Device Bootstrap
How IMEI mappings become active Banban device identities.
Bootstrap Flow
sequenceDiagram
autonumber
participant Factory as Factory Excel / import CSV
participant Mapping as device_imei_mapping
participant Device as TalkingQ device
participant MQTT as MQTT broker
participant Handler as TalkingQMQTTService
participant Init as device_identity_initializer
participant Auth as device_auth
Factory->>Mapping: Insert imei, device_id, serial_number, status=pending
Device->>MQTT: Publish device/{imei}/event msg_id=012
MQTT->>Handler: Deliver identity init event
Handler->>Init: initialize_by_imei(imei)
Init->>Mapping: SELECT mapping by imei
alt mapping missing or incomplete
Init-->>Handler: DeviceIdentityInitializationError
Handler-->>MQTT: device/{imei}/event_resp status=failed
else mapping found
Init->>Auth: SELECT device_auth by device_id
alt no auth row
Init->>Auth: INSERT device_id, serial_number, is_active=1
else auth row exists and serial matches
Init->>Auth: UPDATE is_active=1
else serial mismatch
Init-->>Handler: device_auth serial_number conflict
Handler-->>MQTT: device/{imei}/event_resp status=failed
end
Init->>Mapping: UPDATE status=activated, activated_at=now
Handler-->>MQTT: device/{imei}/event_resp with device_id and device_sn
MQTT-->>Device: Receive assigned identity
end
Data Model
erDiagram
device_imei_mapping {
int id PK
varchar imei UK
varchar device_id UK
varchar serial_number
varchar status
datetime activated_at
datetime created_at
datetime updated_at
}
device_auth {
int id PK
varchar device_id UK
varchar serial_number
varchar batch_id
tinyint is_active
datetime created_at
datetime updated_at
}
device_imei_mapping ||--o| device_auth : activates
talkingq-url/services/device_identity_initializer.py, talkingq-url/handlers/mqtt_handler.py03 Binding Flow
How a parent binds an authenticated device to a child through NFC confirmation.
Device Binding
sequenceDiagram
autonumber
participant Parent as Parent in mini-program
participant Mini as banban-mini bind page
participant API as /banban/bind APIs
participant Binding as BindingService
participant DAO as BindingDAO
participant Auth as device_auth
participant MQTT as TalkingQMQTTService
participant Device as TalkingQ device
participant Card as cards
participant Bindings as device_bindings
participant History as device_bind_history
Parent->>Mini: Scan QR or open bind URL
Mini->>API: start_bind(device_id, serial_number, child_id)
API->>Binding: start_bind(user_id, device_id, serial_number, child_id)
Binding->>Auth: get_device_auth(device_id)
alt device missing, inactive, or serial mismatch
Binding-->>API: BindingError
API-->>Mini: 4xx error
else device is bindable
Binding->>DAO: ensure no active device binding
Binding->>DAO: create device_bind_session
Binding->>MQTT: send_bind_nfc_command(msg_id=006)
MQTT-->>Device: device/{device_id}/command
API-->>Mini: bind_token, expires_at
end
Device->>MQTT: NFC response / card UUID
MQTT->>Binding: finalize_nfc_bind(device_id, card_uuid)
Binding->>DAO: load latest pending bind session
Binding->>Card: activate_card(card_uuid, device_id)
Binding->>Bindings: create active binding
Binding->>History: write bind audit history
Binding->>DAO: mark session completed
Related Tables
erDiagram
parents ||--o{ children : owns
parents ||--o{ device_bindings : owns
children ||--o{ device_bindings : current_child
device_auth ||--o{ device_bindings : device
device_auth ||--o{ device_bind_sessions : pending_bind
device_auth ||--o{ cards : card_owner_device
device_bindings ||--o{ device_bind_history : audit
banban-mini/src/pages/bind/index.tsx, talkingq-url/banban/service/binding.py04 Voice And IM Flow
Parent voice upload, IM persistence, COS audio, and device delivery.
Parent Voice Message To Device
sequenceDiagram
autonumber
participant Parent as Parent
participant Mini as Chat detail page
participant API as /banban chat APIs
participant Audio as Upload / audio handling
participant COS as Tencent COS
participant IM as IM service / DAO
participant DB as im_conversations + im_messages
participant Pending as device_pending_voice_messages
participant MQTT as MQTT broker
participant Device as TalkingQ device
Parent->>Mini: Long press "press to leave message"
Mini->>Mini: Taro.getRecorderManager records mp3/aac
Mini->>API: upload voice file + metadata
API->>Audio: validate and store audio
Audio->>COS: upload message audio
COS-->>Audio: media_file_key / public URL
API->>IM: create parent voice IM message
IM->>DB: upsert conversation and insert message
IM->>Pending: create pending voice delivery row
API-->>Mini: message item with media URL
Device->>MQTT: device/{device_id}/event msg_id=005 NFC listen
MQTT->>API: MQTT handler receives event
API->>Pending: find pending voice for card/device
API-->>MQTT: device/{device_id}/event_resp with audio URL(s)
MQTT-->>Device: Play pending audio
API->>Pending: mark delivered / increment delivery count
Device / Child Voice Into IM
flowchart TD
Device["Device short press / voice upload\nmsg_id=011 or compatibility path"]
MQTT["TalkingQMQTTService"]
Upload["Audio upload / archive service"]
Resolve["Resolve bound owner and child\nfrom device_bindings"]
IM["IM service"]
Tables["im_conversations\nim_messages"]
Mini["banban-mini chat list/detail"]
Device --> MQTT --> Upload --> Resolve --> IM --> Tables
Tables -->|GET chat APIs| Mini
Audio Domain
flowchart LR
Message["im_messages.media_file_key"]
Presenter["present_message_item / chat service"]
URL["mediaUrl returned to mini-program"]
Player["Taro InnerAudioContext"]
COS["COS downloadFile legal domain"]
Message --> Presenter --> URL --> Player
URL --> COS
banban-mini/src/pages/chat/detail/index.tsx, talkingq-url/banban/service/im.py05 Location Flow
Device-sourced current location and trajectory shown in the mini-program.
Device-Sourced Location
sequenceDiagram
autonumber
participant Device as TalkingQ device
participant MQTT as MQTT broker
participant Handler as TalkingQMQTTService
participant Location as Location service
participant Current as child_location_current
participant History as child_location_history
participant Mini as banban-mini location page
participant API as /banban/devices/{device_id}/location
Device->>MQTT: msg_id=000 with latitude/longitude or GPS response
MQTT->>Handler: deliver device event/response
Handler->>Location: report_mqtt_device_location(...)
Location->>Location: resolve active child binding
Location->>Current: upsert latest location
Location->>History: insert location history point
Handler-->>MQTT: success event_resp
Mini->>API: GET current location
API->>Current: read current row for bound child/device
API-->>Mini: current location, accuracy, battery, address fields
Mini->>API: GET trajectory
API->>History: read recent/today points
API-->>Mini: trajectory points
Data Model
erDiagram
device_auth ||--o{ child_location_current : device
children ||--o{ child_location_current : child
device_auth ||--o{ child_location_history : device
children ||--o{ child_location_history : child
device_bindings ||--o{ child_location_current : active_binding_source
banban-mini/src/pages/location/index.tsx, talkingq-url/banban/service/location.py06 Alarm And Notification Flow
Device alarm persistence and user-visible notifications.
Device Alarm To User Notification
sequenceDiagram
autonumber
participant Device as TalkingQ device
participant MQTT as MQTT broker
participant Handler as TalkingQMQTTService
participant Alarm as Alarm service
participant Location as Location snapshot
participant DB as device_alarm_events
participant Banner as system banner polling
participant Mini as banban-mini
participant WxMP as WeChat Official Account
participant SMS as SMS provider
Device->>MQTT: alarm event msg_id=010
MQTT->>Handler: deliver alarm payload
Handler->>Alarm: create alarm event
Alarm->>Location: attach current location snapshot if available
Alarm->>DB: insert device_alarm_events
Alarm->>WxMP: schedule/send template notification if bound
Alarm->>SMS: send SMS if phone notification is enabled
Banner->>DB: poll latest/new alarm
Mini->>Banner: show banner / alarm history on device home
Handler-->>MQTT: alarm event_resp
Supporting Notification Bind
flowchart TD
Mini["banban-mini management page"]
Phone["WeChat phone authorization"]
WxBind["WeChat MP bind start/status"]
Backend["talkingq-url wechat-mp routers/services"]
Parent["parents / parent_wechat_* tables"]
Notify["wechat_mp_notification_service"]
Mini --> Phone --> Backend --> Parent
Mini --> WxBind --> Backend --> Parent
Parent --> Notify
Key Tables
erDiagram
device_auth ||--o{ device_alarm_events : reports
children ||--o{ device_alarm_events : alarm_owner
parents ||--o{ parent_wechat_accounts : mp_account
parents ||--o{ parent_wechat_identities : wx_identity
parents ||--o{ wechat_mp_bind_states : bind_state
banban-mini/src/services/system-banner.ts, talkingq-url/banban/service/wechat_mp_notification.py07 Deployment
Public API host, reverse proxy, backend process, database, MQTT, COS, and certificate renewal.
Public Deployment Shape
flowchart TD
User["WeChat mini-program user"]
Domain["banban.api.talkingq.com"]
Nginx["Nginx container\nTLS + reverse proxy + static verify files"]
FastAPI["talkingq-url FastAPI process\n/home/ubuntu/banban-backend"]
MySQL["1Panel MySQL container\nMySQL 8.x"]
MQTT["Configured MQTT broker"]
COS["Tencent COS"]
Certbot["certbot container\nLet's Encrypt renewals"]
User -->|HTTPS| Domain --> Nginx --> FastAPI
FastAPI --> MySQL
FastAPI --> MQTT
FastAPI --> COS
Certbot --> Nginx
Startup Responsibilities
sequenceDiagram
autonumber
participant Proc as FastAPI process
participant Init as init_db
participant Scheduler as TaskScheduler
participant MQTT as TalkingQMQTTService
participant Roles as role_manager
participant Firmware as firmware_scanner
Proc->>Init: initialize and migrate database tables
Proc->>Scheduler: start periodic tasks
Proc->>MQTT: connect to configured broker
Proc->>Roles: initialize role definitions
Proc->>Firmware: scan firmware files
Proc-->>Proc: serve API routes and assets
talkingq-url/docker-compose.yml, talkingq-url/nginx.conf, talkingq-url/main.pyIf diagrams do not render, open this file with network access enabled or render the Markdown files in a Mermaid-capable viewer such as GitHub, GitLab, VS Code with Mermaid support, or Mermaid Live Editor.