APP下载

Android

扫描二维码下载安装

download_qr_code

Android download qr code

账号

注册

  1. 使用邮箱进行注册,填入邮箱和密码之后,点击发送验证码。

  2. 将邮箱收到的验证码填入,点击注册即可。

  3. 如图示。

register

邮箱登录

填入完整的邮箱和密码,之后点击登录。如图示。

login

修改密码

如图所示,进行修改即可。如图示。

modify_pwd_1
modify_pwd_2
modify_pwd_3

忘记密码

如图所示,按照图示进行修改即可。如图示。

forget_pwd_1
forget_pwd_2

设备

多媒体设备

添加设备

按照图示顺序进行操作,默认将房间添加到全屋。

在使用的过程中,需要打开位置服务、蓝牙,以及在设置中,将此应用的位置权限打开。

add_device_1
add_device_2
add_device_3
add_device_4
add_device_5
add_device_6

移除设备

长按图示区域,会弹出提示框。

remove_device_1
remove_device_2

设备操作

首页点击已添加的设备,会进入此设备的操作界面。包含各种功能控制按钮。默认进入之后,会打开camera。

camera_operation_1

AI玩具

添加设备

按照图示顺序进行操作,默认将房间添加到全屋。

添加设备之前,请确保此设备已经被移除。(请参考下节:移除设备

在使用的过程中,需要打开位置服务、蓝牙,以及在设置中,将此应用的位置权限打开。

add_ai_device_1
add_ai_device_2
add_ai_device_3
add_ai_device_4
add_ai_device_5
add_ai_device_6
add_ai_device_7

移除设备

长按图示区域,会弹出提示框。

remove_ai_device_1
remove_ai_device_2

家庭

默认家庭为:我的家。默认家庭不可被删除。

创建家庭

点击+,输入家庭名称和家庭位置即可,如图示。

create_family_1
create_family_2

修改家庭名称

如图示

modify_family_name_1

删除家庭

如图示

remove_family_1

房间

添加房间

如图示

add_room_1
add_room_2

修改房间名称

如图示

modify_room_name_1
modify_room_name_2

删除房间

如图示。

remove_room_1

家庭成员

角色以及权限

分为3种角色:创建者、管理员、成员,不同角色权限不同。

角 色

邀请 管理员

邀请 成员

删除 其他成员

退出 家庭

删除 家庭

修改 家庭信息

修改 成员角色

创 建 者

yes

yes

yes

no

yes

yes

yes

管 理 员

no

yes

no

yes

no

yes

no

成 员

no

no

no

yes

no

no

no

邀请家庭成员

如图示。

invite_member_1

删除家庭成员

如图示。

remove_member_1

更改其他成员角色

如图示

modify_member_role_1

debug模式

进入debug模式

如图示。

debug_add_device_1

选择配置

如图示,选择你需要的各种配置。

debug_config_1
debug_config_2

扫描与配网

如图示。

debug_scan_1

连接

如图示。

debug_connect_1

功能界面

如图示。

debug_function_1

mjpeg解码

名词解释、注释

  • 涉及到的移位操作,每个都会进行无符号处理。

  • 每帧图片数据,会拆成多个数据包,并顺序发送。

  • 每帧图片数据,可能不会一次发送完成。

  • 涉及到的名词解释:

    • rxData:接收到的mjpeg数据,字节数组。

    • TransmissionUnpacked:数据结构,未解包的数据对象。

    • Head:头信息。

    • CameraPacket:数据结构,携带图片信息的数据结构。

    • MAGIC_LB:标志位,必须是值为0xD5的字节。

    • MAGIC_HB:标志位,必须是值为0xF0的字节。

    • flags:标志位。

    • timestamp:时间戳,信息发送时间。

    • sequence:当前包的序列号。

    • length:携带的CameraPacket的数据长度。

    • crc:校验码。

    • id:当前包所在的图片帧的序列号。

    • eof:当前包是否是所属图片帧的最后一包。1为是,其余为否。

    • count:当前包在所属图片帧拆包后,对应的序列号。如一帧数据顺序拆了5包,其中一包数据的序列号为3。

    • size:携带的真实图片数据payload的长度。

    • ImageFrame:数据结构,解析出的payload根据序列号组装而成。

结构图

rxData
imageFrame

流程

  1. 从接收到的数据中解析出所有TransimissionUnpacked

  2. 从TransimissionUnpacked中取出CameraPacket

  3. 对CameraPacket进行解析取值

  4. 将CameraPacket组装成ImageFrame

  5. 解码器,对ImageFrame进行解码

解包

名词解释

  • index:int类型,初始为0。

  • reversed:字节数组,长度为3,初始值均为0。

  • cached:解包遗留的数据,会继续使用,长度不固定。

  • unpackedList:未解包的数据列表,顺序链表结构,存储的是TransmissionUnpacked对象。

  • offset:int类型,初始值为0。

  • packetList:待组装的数据列表,顺序链表结构,存储的是CameraPacket对象。

  • imageFrame:正在组装的帧,ImageFrame对象。

取分包数据

  1. 如果cached长度为0的话

    1. 如果当前index + 16 大于rxData的长度的话

      1. 将rxDta的index以及之后的数据,赋值到cached中。

      2. 退出循环。

    2. 判断条件:rxData的index位为0xD5且index+1位为0xF0

      1. 如果满足的话

        1. 赋值flags:将rxData的第index+3位左移8位,将rxData的第index+2位数值取出,两个结果进行或操作,将最终结果赋值给flags

        2. 赋值timestamp:将rxData的第index+7位左移24位,将rxData的第index+6位左移16位,将rxData的第index+5位左移8位,将rxData的第index+4位取出,四个结果进行或操作,将最终结果赋值给timestamp

        3. 赋值sequence:将rxData的第index+9位左移8位,将rxData的第index+8位数值取出,两个结果进行或操作,将最终结果赋值给sequence

        4. 赋值length:将rxData的第index+11位左移8位,将rxData的第index+10位数值取出,两个结果进行或操作,将最终结果赋值给sequence

        5. 赋值crc:将rxData的第index+12位数值取出,赋值给crc

        6. 赋值reversed:将rxData的第index+13、第index+14、第index+15依次填入reversed

      2. 不满足

        1. 打印异常

        2. 退出循环

    3. 如果index+16+length大于rxData的长度的话

      1. 将rxDta的index以及之后的数据,赋值到cached中

      2. 退出循环

    4. 以index+16为起始位,以length为长度,将对应的rxData的数据,赋值给一个临时字节数组,channelData

    5. 将flags、timeStamp、sequence、crc、length、channelData、reversed赋值给TransmissionUnpacked

    6. 将TransmissionUnpacked添加到unpackedList列表之中。

    7. 赋值index:index = index+16+length

  2. 如果cached长度大于0

    1. 如果cache的长度小于16

      1. 如果index+16大于rxDdata的长度

        1. 赋值offset:cached的长度赋给offset

        2. 拓展cached的长度为:offset+rxData的长度-index

        3. 将rxDta的index以及之后的数据,赋值到cached的offset之后

        4. 退出循环

      2. 如果index+16小于等于rxDdata的长度

        1. 赋值offset:cached的长度赋给offset

        2. 拓展cached的长度为:16

        3. 以index为起始位,以16-offset为长度,将对应的rxData的数据,赋值到cached的offset之后

        4. 赋值index:index= index + 16 - offset

    2. 判断是否满足调教:cached的第0位为0xD5且第一位为0xF0

      1. 满足

        1. 赋值flags:将cached的第3位左移8位,将cached的第2位数值取出,两个结果进行或操作,将最终结果赋值给flags

        2. 赋值timestamp:将cached的第7位左移24位,将cached的第6位左移16位,将cached的第5位左移8位,将cached的第4位取出,四个结果进行或操作,将最终结果赋值给timestamp

        3. 赋值sequence:将cached的第9位左移8位,将cached的第8位数值取出,两个结果进行或操作,将最终结果赋值给sequence

        4. 赋值length:将cached的第11位左移8位,将cached的第10位数值取出,两个结果进行或操作,将最终结果赋值给sequence

        5. 赋值crc:将cached的第12位数值取出,赋值给crc

        6. 赋值reversed:将cached的第13、第14、第15依次填入reversed

      2. 不满足

        1. 打印异常

        2. 退出循环

    3. 判断是否满足条件:cached的长度小于16+length

      1. 满足

        1. 如果cached的长度小于16+length

          1. 如果index + 16 + length - cached.length大于rxData的length

            1. 赋值offset:cached的长度赋给offset

            2. 拓展cached的长度为:offset + rxData.length - index

            3. 以index为起始位,以rxData.length - index为长度,将对应的rxData的数据,赋值到cached的offset之后

            4. 退出循环

          2. 赋值offset:cached的长度赋给offset

          3. 赋值一个名为copyLen的int变量:值为16 + length - offset

          4. 拓展cached的长度为:16+length

          5. 以index为起始位,以copyLen为长度,将对应的rxData的数据,赋值到cached的offset之后

          6. 赋值index:index = index+copyLen

          7. 以16为起始位,以length为长度,将对应的cached的数据,赋值给一个临时字节数组,channelData

          8. 将flags、timeStamp、sequence、crc、length、channelData、reversed赋值给TransmissionUnpacked

          9. 将TransmissionUnpacked添加到unpackedList列表之中。

          10. cached数据清空

      2. 不满足

        1. 退出循环

  3. 如果index小于rxData的长度的话,继续执行循环

  4. 退出循环之后,将cached返回并保存,供下次使用,将unpackedList返回

组图片帧

  1. imageFrame,依次接收并处理每一个TransmissionUnpacked。

  2. 取出length,根据length,取出对应的CameraPacket的数据。

  3. CameraPacket,从对应的位中取出id、count、eof、size,根据size取出payload。

  4. 判断条件:当前packet和上一个packet的id一致

    1. 满足

      1. 存入packetList

    2. 不满足

      1. 清空所有的packetList

      2. 不再执行后续流程

  5. 判断条件:当前packet的eof值为1

    1. 不满足

      1. 不再执行后续流程

    2. 满足

      1. 将packetlist中的所有数据count进行排序。

      2. 将链表中的camerapacket的payload赋值到一个字节数组中frameData中,并将链表清空。

      3. frameData,就是最终的图片帧数据。

解码

  1. 在解包过程中,会得到图片帧数据,格式为字节数组。

  2. 使用解码器进行解码。

    1. android可以使用BitmapFactory.decodeByteArray。