13
强 AI 很弱,弱 AI 很强。
——薛定饿(作者的猫,图见文末)

首先,感谢 SF 和 Rokid 提供的 试用机会

SF的小伙伴们,大家好,欢迎收看这一期的 Integ's Hack Show
今天我们来测评的是来自 Rokid 的一款 ALL in ONE 全栈开发套件
Rokid 原本是一款智能音箱产品,这次测评的套件可以说是 Rokid 智能音箱去掉扬声器后,再加上 debug 接口,给智能硬件爱好者和开发者提供的一套智能硬件开发板,可玩度非常高。
所谓全栈开发套件,应该是说等我们彻底玩转这套智能硬件设备后,软件硬件前端后端机器学习,这些技能点都会被点亮吧。

硬件

套件拼装完成后效果图:

图片描述

开箱时 debug 板并没有与核心板安装在一起。自己找来 3 个铜柱把 debug 板装上去。

这套智能套件共分三层从上到下分别是:

  1. 麦克风+LED: 麦克风*4, 彩色 LED*12
    cpu_board_bottom_side.png
  2. 核心板:
    cpu_board_top_side.png

    • SoC:Amlogic S905D A54x4
    • Memory: 2GB LPDDR3 + 16GB eMMC
    • 博通 AP6255: 802.11ac + bluetooth 4.1/BLE
  3. debug 板: 调试串口,GPIO, 按键 等
    图片描述

    (这个是V1.0的接口图片,这次测评的V1.1版少了一个USB 2.0 OTG 接口,其他大致形同)

从 SoC 方面看,这套 Amlogic S950 的 Android 方案也常被用来开发各种智能电视机顶盒,比如小米盒子3。不过在这块 Amlogic S905D 集成的 Mali-450 GPU 在不接显示器的情况下,是肯定用不上了。

2G + 16G 的存储方案,对于智能音箱这种不需要大量存储本地数据的 Android 智能家居应用来说已经够用。

开机

先把自己的耳机或音箱插到核心板上的耳机口上。再把核心板和 debug 板的两个 USB Type-C 都插上线,分别连接到电脑的两个 USB 口上。

图片描述

此时电脑会识别到两个USB设备,一个是名为 rn102 的 Android 设备(可用 adb shell 调试),另一个是一个
USB 转串口设备(可输出启动及内核信息)。打开串口工具,选择波特率 115200,可以看到如下启动信息:

GXL:BL1:9ac50e:a1974b;FEAT:ADFC318C;POC:3;RCY:0;EMMC:0;READ:0;0.0;CHK:0;
TE: 214524

BL2 Built : 20:04:24, Aug 17 2017.
gxl g440fda4 - xiaobo.gu@droid12

rn5t618_power_init
set vdd cpu_b to 1050 mv
Board ID = 2
CPU clk: 1200MHz
DQS-corr enabled
DDR scramble enabled
LPDDR3 chl: Rank0+1 @ 768MHz - PASS
Rank0: 1024MB-2T-3
Rank1: 1024MB-2T-3
DataBus test pass!
AddrBus test pass!
-s
Load fip header from eMMC, src: 0x0000c200, des: 0x01400000, size: 0x00004000
New fip structure!
Load bl30 from eMMC, src: 0x00010200, des: 0x01100000, size: 0x0000d600
Load bl31 from eMMC, src: 0x00020200, des: 0x10100000, size: 0x00015400
Load bl33 from eMMC, src: 0x00038200, des: 0x01000000, size: 0x000b5c00
NOTICE:  BL3-1: v1.0(debug):fb68908
NOTICE:  BL3-1: Built : 18:30:11, Nov  1 2016
aml log : bl31 normal boot !
[Image: gxl_v1.1.3154-065f772 2016-09-29 14:08:54 yan.wang@droid05]
OPS=0x02
17 b9 88 e0 da e1 72 39 6d 2d 1 22 [0.484399 Inits done]
secure task start!
high task start!
low task start!
INFO:    BL3-1: Initializing runtime services
WARNING: No OPTEE provided by BL2 boot loader
ERROR:   Error initializing runtime service opteed_fast
INFO:    BL3-1: Preparing for EL3 exit to normal world
INFO:    BL3-1: Next image address = 0x1000000
INFO:    BL3-1: Next image spsr = 0x3c9


U-Boot 2015.01-gcd65a08 (Oct 26 2017 - 23:37:46), Build: jenkins-pebble-amlogic-                                                                                                                                                             s9xx_nana-t_dev-20

DRAM:  2 GiB
Relocation Offset is: 76ebc000
register usb cfg[0][6] = 0000000077f5d130
register usb cfg[2][0] = 0000000077f5d108
vpu: error: vpu: check dts: FDT_ERR_BADMAGIC, load default parameters
vpu: clk_level = 7
vpu: set clk: 666667000Hz, readback: 666660000Hz(0x300)
vpp: vpp_init
boot_device_flag : 1
Nand PHY Ver:1.01.001.0006 (c) 2013 Amlogic Inc.
init bus_cycle=6, bus_timing=7, system=5.0ns
reset failed
get_chip_type and ret:fffffffe
get_chip_type and ret:fffffffe
chip detect failed and ret:fffffffe
nandphy_init failed and ret=0xfffffff1
MMC:   aml_priv->desc_buf = 0x0000000073ebc6b0
aml_priv->desc_buf = 0x0000000073ebe9d0
SDIO Port B: 0, SDIO Port C: 1
emmc/sd response timeout, cmd8, status=0x1ff2800
emmc/sd response timeout, cmd55, status=0x1ff2800
[mmc_startup] mmc refix success
[mmc_init] mmc init success
start dts,buffer=0000000073ec0cf0,dt_addr=0000000073ec0cf0
parts: 11
00:      logo   0000000002000000 1
01:  recovery   0000000002000000 1
02:       rsv   0000000000800000 1
03:       tee   0000000000800000 1
04:     crypt   0000000002000000 1
05:      misc   0000000002000000 1
06: instaboot   0000000020000000 1
07:      boot   0000000002000000 1
08:    system   0000000080000000 1
09:     cache   0000000008000000 2
10:      data   ffffffffffffffff 4
eMMC/TSD partition table have been checked OK!
mmc env offset: 0xf400000
In:    serial
Out:   serial
Err:   serial
reboot_mode=cold_boot
hpd_state=0
cvbs performance type = 6, table = 0
[store]To run cmd[emmc dtb_read 0x1000000 0x40000]
_verify_dtb_checksum()-932: calc 8c24ddf3, store 8c24ddf3
_verify_dtb_checksum()-932: calc 8c24ddf3, store 8c24ddf3
dtb_read()-1042: total valid 2
dtb_read()-1109: do nothing
PMU fault status:
reg[0x9A] = 0x00
LSI version:00, OTP version:00
PMU type:RN5T618
[RN5T618] DUMP ALL REGISTERS
0x00 - 0f: 00 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00
0x10 - 1f: 00 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00
0x20 - 2f: 00 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00
0x30 - 3f: 00 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00
0x40 - 4f: 00 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00
0x50 - 5f: 00 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00
0xb0 - bf: 00 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00
USB3.0 XHCI init start
detect usb battery charger mode: SDP (PC)
[pmic]  :limit usb current to 500mA && limit ADP current 500mA
[RN5T618]rn5t618_set_dcin_current_limit, set dcin current limit to 500
[RN5T618]rn5t618_set_usb_current_limit, set usb current limit to 500
rn5t618_set_charging_current, 500mA
board_usb_stop cfg: 2
get_cpu_id flag_12bit=1
SARADC channel(1) is 0xa7.
hardwareid :0x2
enter cold_boot mode when detect boot reason
boot_reason: reg[09]: 0, boot reason: 1
Net:   dwmac.c9410000
wipe_data=successful
wipe_cache=successful
upgrade_step=2
[OSD]load fb addr from dts
[OSD]failed to get fb addr for logo
[OSD]use default fb_addr parameters
[OSD]fb_addr for logo: 0x3d800000
[OSD]load fb addr from dts
[OSD]failed to get fb addr for logo
[OSD]use default fb_addr parameters
[OSD]fb_addr for logo: 0x3d800000
[CANVAS]canvas init
[CANVAS]addr=0x3d800000 width=3840, height=2160
get_cpu_id flag_12bit=1
enter cold_boot mode
amlkey_init() enter!
[EFUSE_MSG]keynum is 3
[BL31]: tee size: 0
[BL31]: tee size: 0
[BL31]: tee size: 0
[BL31]: tee size: 0
[BL31]: tee size: 0
success:serialno=0001121743000214
[BL31]: tee size: 0
[BL31]: tee size: 0
[BL31]: tee size: 0
[BL31]: tee size: 0
success:rokidseed=0hCg6mu8jen40Sbs947J919jir9338
Hit Enter or space or Ctrl+C key to stop autoboot -- :  0
ee_gate_off ...
## Booting Android Image at 0x01080000 ...
reloc_addr =73f40ec0
copy done
load dtb from 0x1000000 ......
   Uncompressing Kernel Image ... OK
   kernel loaded at 0x01080000, end = 0x0231d4c0
   Loading Ramdisk to 73dc8000, end 73ea9e96 ... OK
   Loading Device Tree to 000000001fff3000, end 000000001ffffa6f ... OK
signature:
fdt_instaboot: no instaboot image

Starting kernel ...

uboot time: 2962890 us
[    0.000000@0] Initializing cgroup subsys cpu
[    0.000000@0] Initializing cgroup subsys cpuacct
[    0.000000@0] Linux version 3.14.29-g09f9591 (jenkins@build-4) (gcc version 4                                                                                                                                                             .9.2 20140904 (prerelease) (crosstool-NG linaro-1.13.1-4.9-2014.09 - Linaro GCC                                                                                                                                                              4.9-2014.09) ) #1 SMP PREEMPT Fri Oct 27 00:00:12 HKT 2017
[    0.000000@0] CPU: AArch64 Processor [410fd034] revision 4
[    0.000000@0] no prop version_code
[    0.000000@0] bootconsole [earlycon0] enabled
[    0.000000@0] fdt Reserved memory table:
[    0.000000@0]            linux,meson-fb: 0x000000007e000000 - 0x0000000080000                                                                                                                                                             000  (32 MiB)
[    0.000000@0]                  linux,di: 0x000000007c200000 - 0x000000007e000                                                                                                                                                             000  (30 MiB)
[    0.000000@0] DI: DI reserved memory: created CMA memory pool at 0x000000007c                                                                                                                                                             200000, size 30 MiB
[    0.000000@0]             linux,ion-dev: 0x000000007b200000 - 0x000000007c200                                                                                                                                                             000  (16 MiB)
[    0.000000@0]               linux,ppmgr: 0x000000007b200000 - 0x000000007b200                                                                                                                                                             000  (0 MiB)
[    0.000000@0]        linux,codec_mm_cma: 0x0000000075000000 - 0x000000007b000                                                                                                                                                             000  (96 MiB)
[    0.000000@0]              linux,picdec: 0x000000007b200000 - 0x000000007b200                                                                                                                                                             000  (0 MiB)
[    0.000000@0] Reserved memory: incorrect alignment of CMA region
[    0.000000@0]   linux,codec_mm_reserved: 0x0000000071c00000 - 0x0000000073d00                                                                                                                                                             000  (33 MiB)
[    0.000000@0] fdt Reserved memory total:  210 MiB
[    0.000000@0] cma: Reserved 8 MiB at 74800000
[    0.000000@0] psci: probing function IDs from device-tree
[    0.000000@0] PERCPU: Embedded 12 pages/cpu @ffffffc07b1a0000 s19968 r8192 d2                                                                                                                                                             0992 u49152
[    0.000000@0] Built 1 zonelists in Zone order, mobility grouping on.  Total p                                                                                                                                                             ages: 506004
[    0.000000@0] Kernel command line: rootfstype=ramfs init=/init console=ttyS0,                                                                                                                                                             115200 no_console_suspend earlyprintk=aml-uart,0xc81004c0 ramoops.pstore_en=1 ra                                                                                                                                                             moops.record_size=0x8000 ramoops.console_size=0x4000 androidboot.selinux=permiss                                                                                                                                                             ive logo=osd1,loaded,0x3d800000,576cvbs maxcpus=4 vout=576cvbs,enable hdmimode=1                                                                                                                                                             080p60hz cvbsmode=576cvbs hdmitx= cvbsdrv=0 androidboot.firstboot=0 jtag=disable                                                                                                                                                              androidboot.serialno=0001121743000214 androidboot.rokidseed=0hCg6mu8jen40Sbs947                                                                                                                                                             J919jir9338 androidboot.hardware=amlogic boardinfo.hardwareid=0x2 androidboot.ft                                                                                                                                                             m= androidboot.factory_date= androidboot.mode=
[    0.000000@0] logo: osd1
[    0.000000@0] logo: loaded
[    0.000000@0] logo: 0x3d800000
[    0.000000@0] logo: 576cvbs
[    0.000000@0] vout_serve: 576cvbs
[    0.000000@0] vout_serve: enable: 1
[    0.000000@0] logo: get hdmimode: 1080p60hz
[    0.000000@0] logo: get cvbsmode: 576cvbs
[    0.000000@0] tv_vout: cvbs performance line = 0
[    0.000000@0] jtag: jtag select -1
[    0.000000@0] PID hash table entries: 4096 (order: 3, 32768 bytes)
[    0.000000@0] Dentry cache hash table entries: 262144 (order: 9, 2097152 byte                                                                                                                                                             s)
[    0.000000@0] Inode-cache hash table entries: 131072 (order: 8, 1048576 bytes                                                                                                                                                             )
[    0.000000@0] Memory: 1804080K/2060288K available (10640K kernel code, 3213K                                                                                                                                                              rwdata, 3936K rodata, 1263K init, 6381K bss, 256208K reserved)
...

很好,U-Boot 先加载 eMMC 中的内核,直到把整个 Android 跑起来。

此时套件还没有连上网,但是蓝牙已经可以使用了。在电脑上搜索附近的蓝牙设备,可以看到一个名为Rokid-pebble-XXXXXX的蓝牙音箱,配对上去,在电脑上放首歌。嗯,不错,可以通过蓝牙听到电脑上音乐了。

然后是给套件配置网络,图省事的话可以直接在手机上下载 Rokid 的 App,通过手机蓝牙给套件配网。这里我们用adb shell 通过命令配置网络。

先通过 adb 连接上设备

$ adb devices
List of devices attached
0001121743000XXX        device
$ adb shell
root@p230:/ # uname -a
Linux localhost 3.14.29 #1 SMP PREEMPT Fri Oct 27 00:00:12 HKT 2017 armv8l

搜索附近的 Wifi:

root@p230:/ # wpa_cli -i wlan0 -p /data/misc/wifi/sockets
wpa_cli v2.5-devel-6.0.1
Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi> and contributors

This software may be distributed under the terms of the BSD license.
See README for more details.

Interactive mode

> scan
OK
> scan_results
bssid / frequency / signal level / flags / ssid
XX:XX:35:3a:19:18       2447    -43     [WPA-PSK-CCMP][WPA2-PSK-CCMP][ESS]      1202
XX:XX:8e:8f:86:91       2412    -56     [WPA-PSK-CCMP][WPA2-PSK-CCMP][ESS]      LY
XX:XX:17:14:d4:40       2437    -67     [WPA-PSK-CCMP][WPA2-PSK-CCMP][ESS]      wahaha88888
...

如果发现搜不到自己的 Wifi, 一般是因为套件 Wifi 驱动的国家字段跟自己路由器中的设置不一样,用下面的命令修改一下(AU 是澳大利亚,频段比较多):

root@p230:/ # wpa_cli -i wlan0 DRIVER COUNTRY AU

这样每次重启都得要改一下,比较麻烦,用下面的命令可以永久生效:

root@p230:/ # mount -o remount,rw /system
root@p230:/ # sed -i '2c ccode=AU' /system/etc/wifi/6255/config.txt

修改后再 scan 一下就能搜到了。然后是联网:

root@p230:/ # wpa_cli -i wlan0 -p /data/misc/wifi/sockets
wpa_cli v2.5-devel-6.0.1
Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi> and contributors

This software may be distributed under the terms of the BSD license.
See README for more details.

Interactive mode

> list_networks
network id / ssid / bssid / flags
> add_network
0
> set_network 0 ssid "XXXX"   #wifi name 
OK
> set_network 0 psk "XXXX"    #wifi password
OK
> enable_network 0  
OK
> list_networks
network id / ssid / bssid / flags
0       Int&Ade_5G      any    [current]
> save_config
OK
> quit

好了,现在我们的套件已经连上了网络,你也可以通过语音和 Rokid 交流了。

软件

pm 看看套件中都安装了那些 app

root@p230:/ # pm list packages
package:com.android.providers.telephony
package:com.android.providers.calendar
package:com.android.tv.settings
package:com.android.providers.media
package:com.android.wallpapercropper
package:com.rokid.app.timer
package:com.rokid.rkengine
package:com.droidlogic.PPPoE
package:com.android.documentsui
package:com.android.externalstorage
package:com.android.providers.downloads
package:com.rokid.life
package:com.rokid.childstory
package:com.droidlogic
package:com.android.defcontainer
package:com.android.pacprocessor
package:com.rokid.tts
package:com.rokid.runtime
package:com.rokid.networkstarter
package:com.android.certinstaller
package:android
package:com.android.camera2
package:com.alibaba.cloudpushdemo
package:com.rokid.activation
package:com.rokid.crosstalk
package:com.rokid.openvoice.rokidstore
package:com.android.backupconfirm
package:com.rokid.service
package:com.android.provision
package:com.android.statementservice
package:com.rokid.alarm1
package:com.rokid.app.rs
package:com.android.providers.settings
package:com.android.sharedstoragebackup
package:com.droidlogic.service.remotecontrol
package:com.android.dreams.basic
package:com.android.webview
package:com.android.inputdevices
package:com.droidlogic.readlog
package:com.rokid.systemui
package:com.rokid.rkasragent
package:com.android.onetimeinitializer
package:com.android.keychain
package:com.rokid.soundbook
package:com.android.packageinstaller
package:com.example.android.home
package:com.android.proxyhandler
package:com.rokid.fm
package:com.android.dreams.phototable
package:com.rokid.connection
package:com.android.smspush
package:com.rokid.launcher
package:com.rokid.calendar1
package:com.rokid.cloudappclient
package:com.rokid.openlecture
package:com.android.settings
package:com.android.vpndialogs
package:com.android.shell
package:com.rokid.weather1
package:com.android.providers.userdictionary
package:com.rokid.talkshow
package:com.android.location.fused
package:com.rokid.appchannel
package:com.android.systemui
package:com.rokid.server.rkupdate
package:com.rokid.light
package:com.rokid.homebase
package:com.rokid.time1
package:com.rokid.rkfirstguide
package:com.android.bluetooth
package:com.android.providers.contacts
package:com.android.captiveportallogin
package:com.rokid.historicalreading
root@p230:/ # 

screencap 截个屏

$ adb shell screencap /sdcard/DCIM/screen.png
$ adb pull /sdcard/DCIM/screen.png

图片描述
看来系统和 Rokid Pebble 是一样的,默认 1920*1080 的分辨率,板子上有 macro HDMI 接口,找机会连个显示器试试。

查看下权限

root@p230:/ # type su
su is /system/xbin/su
root@p230:/ # mount
rootfs / rootfs ro,seclabel 0 0
tmpfs /dev tmpfs rw,seclabel,nosuid,relatime,mode=755 0 0
devpts /dev/pts devpts rw,seclabel,relatime,mode=600 0 0
proc /proc proc rw,relatime 0 0
sysfs /sys sysfs rw,seclabel,relatime 0 0
selinuxfs /sys/fs/selinux selinuxfs rw,relatime 0 0
/sys/kernel/debug /sys/kernel/debug debugfs rw,seclabel,relatime 0 0
configfs /sys/kernel/config configfs rw,relatime 0 0
none /acct cgroup rw,relatime,cpuacct 0 0
none /sys/fs/cgroup tmpfs rw,seclabel,relatime,mode=750,gid=1000 0 0
tmpfs /mnt tmpfs rw,seclabel,relatime,mode=755,gid=1000 0 0
none /dev/cpuctl cgroup rw,relatime,cpu 0 0
pstore /sys/fs/pstore pstore rw,seclabel,relatime 0 0
/dev/block/system /system ext4 ro,seclabel,relatime,data=ordered 0 0
/dev/block/data /data ext4 rw,seclabel,nosuid,nodev,noatime,nodelalloc,errors=panic,data=ordered 0 0
/dev/block/cache /cache ext4 rw,seclabel,nosuid,nodev,noatime,nodelalloc,errors=panic,data=ordered 0 0
/dev/block/tee /tee ext4 rw,seclabel,nosuid,nodev,noatime,nodelalloc,errors=panic,data=ordered 0 0
/dev/block/zram0 /swap_zram0 ext4 rw,seclabel,relatime,data=ordered 0 0
tmpfs /storage tmpfs rw,seclabel,relatime,mode=755,gid=1000 0 0
adb /dev/usb-ffs/adb functionfs rw,relatime 0 0
/dev/fuse /mnt/runtime/default/emulated fuse rw,nosuid,nodev,noexec,noatime,user_id=1023,group_id=1023,default_permissions,allow_other 0 0
/dev/fuse /storage/emulated fuse rw,nosuid,nodev,noexec,noatime,user_id=1023,group_id=1023,default_permissions,allow_other 0 0
/dev/fuse /mnt/runtime/read/emulated fuse rw,nosuid,nodev,noexec,noatime,user_id=1023,group_id=1023,default_permissions,allow_other 0 0
/dev/fuse /mnt/runtime/write/emulated fuse rw,nosuid,nodev,noexec,noatime,user_id=1023,group_id=1023,default_permissions,allow_other 0 0

已经有了root 权限,/data/storage 是可以读写的,/system 只读。
用下面的命令重新 mount /system 为可读写:

root@p230:/ # mount -o remount,rw /system

这样就可以为所欲为了。

可以 adb pull Rokid 的 apk 到本地:

adb pull /data/app ./rokid_app

发现系统里一个喜闻乐见的小玩具 node-android。以后可以利用下,用 express 搭个 web server。

root@p230:/ # node-android --version
v6.9.0
root@p230:/ # node-android -h
Usage: node [options] [ -e script | script.js ] [arguments]
       node debug script.js [arguments]

Options:
  -v, --version         print Node.js version
  -e, --eval script     evaluate script
  -p, --print           evaluate script and print result
  -c, --check           syntax check script without executing
  -i, --interactive     always enter the REPL even if stdin
                        does not appear to be a terminal
  -r, --require         module to preload (option can be repeated)
  --no-deprecation      silence deprecation warnings
  --trace-deprecation   show stack traces on deprecations
  --throw-deprecation   throw an exception anytime a deprecated function is used
  --no-warnings         silence all process warnings
  --trace-warnings      show stack traces on process warnings
  --trace-sync-io       show stack trace when use of sync IO
                        is detected after the first tick
  --track-heap-objects  track heap object allocations for heap snapshots
  --prof-process        process v8 profiler output generated
                        using --prof
  --zero-fill-buffers   automatically zero-fill all newly allocated
                        Buffer and SlowBuffer instances
  --v8-options          print v8 command line options
  --v8-pool-size=num    set v8's thread pool size
  --tls-cipher-list=val use an alternative default TLS cipher list
  --openssl-config=path load OpenSSL configuration file from the
                        specified path

Environment variables:
NODE_PATH                ':'-separated list of directories
                         prefixed to the module search path.
NODE_DISABLE_COLORS      set to 1 to disable colors in the REPL
NODE_REPL_HISTORY        path to the persistent REPL history file

Documentation can be found at https://nodejs.org/

最后习惯性地用 nmap 扫一下端口:

$ nmap 192.168.1.12
Nmap scan report for 192.168.1.12
Host is up (0.016s latency).
Not shown: 999 closed ports
PORT     STATE SERVICE
5555/tcp open  freeciv
MAC Address: CC:B8:A8:09:C2:56 (Unknown)

Nmap done: 1 IP address (1 host up) scanned in 1.18 seconds

$ adb connect 192.168.1.12:5555
connected to 192.168.1.12:5555
$ adb -e shell

5555 是 Android 远程调试的端口,应该是为了方便开发者,默认打开了 Android 的远程调试。

结语

好的,本期的开箱体验就告一段落。
未来我还会尝试通过 Rokid 的自定义技能服务,给这块All in One 套件添加一些好玩的功能,敬请期待!

若琪与猫
图片描述

本文参与了 SegmentFault「Rokid 开发板试用,开启你的嵌入式开发之旅」活动,欢迎正在阅读的你申请试用,一起交流开发心得。

Integ
5.6k 声望295 粉丝

全栈溢出工程师,兼职拆段错误水表,代写内核紧张拉丁语情书。


引用和评论

0 条评论