物联网开发操作系统
大题(代码解析)
PPT例子、实验代码看懂(理解)
其他题目
一共五章内容 绪论(比较少) 第二张比较多 3、4、6比重差不多一样多 ## 第一章 TinyOS的技术特点
- 组件化编程(Componented-Based)
- 事件驱动模式(Event-Driven)
- 轻量级线程(lightweight thread)
- 两级调度方式(Tasks And Events Concurrency Model)
- 分阶段作业(Split-Phase Operations) 六个特点理解是什么意思
TinyOS的编程语言:nesC 组件分类:
- Module组件(模块):实现某种逻辑功能;
- Configuration组件(配件):将各个组件连接起来成为一个整体。不完成功能实现
HarmonyOS三大特性
- 硬件互助、资源共享
- 分布式软总线 (最重要)
- 分布式设备虚拟化
- 分布式数据管理
- 分布式任务调度
- 一次开发、多端部署
- 提供了用户程序框架、Ability框架以及UI框架
- 支持应用开发过程中多终端的业务逻辑和界面逻辑进行复用
- 能够实现应用的一次开发、多端部署
- 提升跨平台开发效率
- 统一OS、弹性部署
- 通过组件化和小型化等设计方式,做到硬件资源可大可小
- 支持多种终端设备按需弹性部署
- 能够适配不同硬件资源和功能需求 分布式设计的基础:分布式软总线
第二章
(概念熟悉) 接口(interface):组件(Component)之间可以进行数据交换的唯一方式 接口的命令(command)函数和事件(event)函数
command是命令,根据应用层的要求操作底层硬件实现相应功能,由组件本身实现event是事件,由中断触发,标志着系统状态的改变,由组件的使用者实现
use和provide接口
use使用接口provide提供接口- 一个接口可以有多个实例
每个nesC有且只有一个顶层配件(top-level
configuration)连接内部组件,顶层配件即为makefile文件的第一行指定的COMPONENT
事件是异步中断驱动的,是有优先级区别的
Task
- 定义
task和提交post的关键字 - 返回类型为void的无参数函数
- 没有优先级,表现为FIFO(先进先出)模式。事件是有优先级的
- 后台执行(异步的)
应用程序开发步骤
- 在/opt/tinyos-2.x/apps下建立文件夹,以应用名字命名。文件夹下需包含4个文件:定制运行环境的makefile、头文件、顶层配件、核心处理模块
- 编写头文件(可选),里面定义了数据结构
- 编写顶层配件
- 接口的提供和使用情况
- 使用的组件列表
- 组件间的接口连接关系
- 编写核心处理模块
- 接口的提供、使用情况
- 具体的实现代码
error_t为command操作的成功/失败结果1
2
3
4
5
6typedef enum {
SUCCESS = 0;
FAIL = 1;
ESIZE = 2; // 传递参数过大
...
} error_t;SUCCESS和FAIL为最常用的两种返回值 ### Blink例子(重要) Blink是一个基本的应用程序,它通过开启定时器来实现周期性地切换LED灯。 其文件位置为/opt/tinyos-2.1.x/apps/Blink。 编译下载到节点上,可以看到,该应用程序在节点的3个LED灯上显示了一个计数器。它只是简单的以4Hz的频率开关LED0,以2Hz开关LED1,以1HZ开关LED2。其效果就是:每两秒3个LED显示了二进制计数从0到7。 Blink程序由两个文件组成:模块文件(BlinkC.nc)和配件文件(BlinkAppC.nc)。注意:所有程序都需要一个顶层配件,通常是以应用程序的名字命名。BlinkAppC就是Blink程序的配件,也是nesC编译器产生可执行文件的源头。而BlinkC则提供Blink程序的逻辑实现。BlinkAppC是用来连接BlinkC模块和Blink所需的其他功能组件。
BlinkAppC.nc,这是一个顶层配件 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21configuration BlinkAppC
{
// 这里一般由uses 和 provides 从句来说明使用到的和提供的接口,除了顶层
// 配件,模块和配件都可以使用和提供接口
}
Implementation //实现部分
{
components MainC, BlinkC, LedsC; //BlinkC是编写的模块
components new TimerMilliC() as Timer0; //as命名别名方便识别
components new TimerMilliC() as Timer1; //同一组件不同实例
components new TimerMilliC() as Timer2;
//components指定了这个配件用到的组件components
BlinkC -> MainC.Boot; // BlinkC.Boot -> MainC.Boot
BlinkC.Timer0 -> Timer0;//BlinkC.Timer0 -> Timer0.Timer0
BlinkC.Timer1 -> Timer1;// ->是连接的意思
BlinkC.Timer2 -> Timer2;// ->是一种包含两个内部规范元素的连接
BlinkC.Leds -> LedsC; //BlinkC.Leds -> LedsC.Leds
// 也就是把负责实现应用部分的模块BlinkC与系统的组件库连接起来
// 记住, BlinkAppC 和 BlinkC 组件是不一样的。更确切的说, BlinkAppC 是由
// Blinkc 组件连同 mainc ,ledsc 和3个 timer定时器一起组成的。
}
1 | |
第三章(通信)
message_t:消息缓冲抽象
基本通信接口,以及接口下的方法(command)
- Packet:提供了对
message_t抽象数据类型的基本访问void clear(message_t *msg)//清空消息内容void setPayloadLength(message_t *msg, uint8_t len)//设定有效载荷区的长度void *getPayload(message_t *msg, uint8_t len)//获得消息有效载荷区的指针uint8_t payloadLength(message_t *msg)//获得消息的有效载荷区长度uint8_t maxPayloadLength()//返回有效载荷区的最大长度
- Send:提供基本的面向任意地址的消息发送接口
error_t send(message_t *msg, uint8_t len)//发送消息error_t cancel(message_t *msg)//取消消息的发送void sendDone(message_t *msg, error_t error)//指示消息发送结果的事件void *getPayload(message_t *msg, uint8_t len)//返回消息有效载荷区的指针uint8_t maxPayloadLength()//返回有效载荷区的最大长度
- Receive:提供最基本的消息接收接口
提供了一个event函数receive
message_t *receive(message_t *msg,void *payload)
主动消息接口 - AMSend - AMPacket
BlinkToRadio例子(3.1.4) ### 发送消息
BlinkToRadioC.nc 文件 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66#include<Timer.h>
#include“BlinkToRadio.h“
module BlinkToRadioC{
uses interface Boot;
uses interface Leds;
uses interface Timer<TMilli> as Timer0;
// 消息发送
uses interface Packet;
uses interface AMPacket;
uses interface AMSend;
uses interface SplitControl as AMControl;
}
implementation{
uint16_t counter = 0;
// 声明一些作用域在模块内的变量,如:pkt,该变量用来存放
// 要发送的消息。还需要声明一个标识符,如:busy,用来跟踪
// 无线电信道是否处于发送忙的状态。
bool busy = FALSE;
message_t pkt;
// 无线模块的初始化工作。为了在系统启动时就可以使用无线模块,
// 必须在Boot.booted事件里调用AMControl.start命令。
event void Boot.booted(){
call AMControl.start();
}
event void Timer0.fired(){
counter++;
call Leds.set(counter);
}
// 因为TinyOS采用分阶段作业的方式,无线电功能启动和完成的
// 信号通过AMControl.startDone和AMControl.stopDone事件来传
// 递。还需要编写AMControl.startDone和AMControl.stopDone事
// 件处理函数。
event void AMControl.startDone(error_t err) {
if (err == SUCCESS) {
call Timer0.startPeriodic(TIMER_PERIOD_MILLI);
}
else {
call AMControl.start();
}
}
event void AMControl.stopDone(error_t err) {
}
// 调用所需的接口,编写应用程序的逻辑实现过程。
event void Timer0.fired() {
...
if (!busy) {
BlinkToRadioMsg* btrpkt = (BlinkToRadioMsg*)
(call Packet.getPayload(&pkt, NULL));
btrpkt->nodeid = TOS_NODE_ID;
btrpkt->counter = counter;
if (call AMSend.send(
AM_BROADCAST_ADDR,&pkt, sizeof(BlinkToRadioMsg)) == SUCCESS)
{
busy = TRUE;
}
}
}
// 实现所有使用到的接口的事件
event void AMSend.sendDone(message_t* msg, error_t error) {
if (&pkt == msg) {
busy = FALSE;
}
}
}BlinkToRadio.h文件 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#ifndef BLINKTORADIO_H
#define BLINKTORADIO_H
enum{
TIMER_PERIOD_MILLI = 250
};
typedef nx_struct BlinkToRadioMsg {
nx_uint16_t nodeid;
nx_uint16_t counter;
} BlinkToRadioMsg;
/*
不能直接用数据读写message_t的有效载荷区,而
是使用一种结构体去操纵有效载荷区
在类型名字前的nx_前缀(如 nx_uint16_t)是针对nesC语
言的特定说明,表示struct和uint16_t 是外部类型。外部
类型在所有的节点平台上具有一样的表示。
*/
#endifBlinkToRadioAppC.nc 配件(configuration)文件 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29#include<Timer.h>
#include“BlinkToRadio.h“
configuration BlinkToRadioAppC{
}
implementation{
components MainC;
components LedsC;
components BlinkToRadioC as App;
components new TimerMilliC() as Timer0;
// 对配件BlinkToRadioAppC.nc里的实现部分进行
// 修改,增加相关组件的声明。
components ActiveMessageC;
components new AMSenderC(AM_BLINKTORADIO);
// BlinkToRadioC模块使用的通信接口由这两个模块提供。
// AM_BLINKTORADIO参数指明了AMSenderC组件
// 的AM标识号(AM Type),可在BlinkToRadio.h头文件
// 里用枚举来设定AM_BLINKTORADIO的值
// 如: enum{AM_BLINKTORADIO = 6;};
// 在配件里连接从使用者到提供者的所有接口。
App.Packet -> AMSenderC;
App.AMPacket -> AMSenderC;
App.AMSend -> AMSenderC;
App.AMControl -> ActiveMessageC;
App.Boot -> MainC;
App.Leds -> LedsC;
App.Timer0 -> Timer0;
}makefile文件 1
2
3
4# 告诉编译系统BlinkToRadioAppC是顶层配件
COMPONENT=BlinkToRadioAppC
# 载入TinyOS的编译系统
include $(MAKERULES)
接收消息
认识相关的组件与接口。
更新 BlinkToRadioC.nc里的 module区,增加所需接口的uses陈述。
1
2
3
4module BlinkToRadioC {
...
uses interface Receive;
}声明新变量,增加所需初始化代码。
增加相关程序逻辑和命令。消息的接收是一个事件驱动的过程,故不需要调用命令。
实现相关的事件处理程序(非初始化)。
首先,判断消息的长度是否符合;接着,将 BlinkToRadioMsg 类型的结构体指针btrpkt指向消息的有效载荷区;最后,通过指针读取消息中的计数值,并用它来设置3个LED灯的显示状态。1
2
3
4
5
6
7event message_t* Receive.receive(message_t* msg, void* payload, uint8_t len) {
if (len == sizeof(BlinkToRadioMsg)) {
BlinkToRadioMsg* btrpkt = (BlinkToRadioMsg*)payload;
call Leds.set(btrpkt->counter);
}
return msg;
}修改BlinkToRadioAppC 配件里的 implementation 区,增加相应的组件说明。
1
2
3
4
5implementation {
...
components new AMReceiverC(AM_BLINKTORADIO);
...
}连接接口,从使用者到提供者。
1
2
3
4implementation {
...
App.Receive -> AMReceiverC;
}应用程序测试 这个应用程序可在mica或telosb的平台上运行。使用两个节点,任一节点都会显示另一个节点的计数值。 编译并下载
$ make micaz install.1 mib510,/dev/ttyS5
串口通信 1. 消息包格式 eg:
00 FF FF 00 04 04 00 06 00 04 00 01 - 00
表明此为AM类型信息包 - FF FF 目标地址 2 Byte -
00 04 链路层源地址 2 Byte - 04
消息包长度(单位:字节) 1 Byte - 00 网络组号 1 Byte -
06 AM类型 1 Byte - 00 04 Nodeid -
00 01 counter
| 目标地址 | 链路层源地址 | 消息长度 | 网络组号 | AM类型 | Nodeid | counter |
|---|---|---|---|---|---|---|
FF FF |
00 04 |
04 |
00 |
06 |
00 04 |
00 01 |
- MIG 三个参数 eg: 用什么语言生成接口消息(java/python/C),在哪个文件可以找到消息结构的定义,消息结构的名字
1
2
3
4
5
6
7
8
9
10
11
12
13
14COMPONENT = TestSerialAppC
# 在编译之前,要满足其他的依赖关系
BUILD_EXTRA_DEPS += TestSerial.class
# 当make clean时有额外文件(.class类型的文件和TestSerialMsg.java文件)需要清除
CLEAN_EXTRA = *.class TestSerialMsg.java
# 基于当前目录下所有java文件生成TestSerial.class,包括 TestSerialMsg.java
TestSerial.class: $(wildcard *.java) TestSerialMsg.java
javac *.java // 编译生成TestSerial.class
TestSerialMsg.java:
MIG java –target=null –java-classname=TestSerialMsg TestSerial.h TestSerialMsg –o $@
include $(MAKERULES)
| 参数/命令 | 含义 |
|---|---|
| MIG | 调用MIG工具 |
java |
建立java类 |
–target=null |
对象平台为null |
–java-classname=TestSerialMsg |
Java类的取名 |
TestSerial.h |
定义消息结构的头文件 |
TestSerialMsg |
消息结构的定义名称 |
–o $@ |
生成文件,指生成 TestSerialMsg.java |
启动 MainC组件负责:系统平台初始化、软件平台初始化、调度器初始化
编译系统(重点考)
make的用法(install和reinstall)区别
Makefile解释->考大题 Makefile的最简形式
1
2
3
4# 告诉编译系统BlinkToRadioAppC是顶层配件
COMPONENT=BlinkToRadioAppC
# 载入TinyOS的编译系统
include $(MAKERULES)
以下为鸿蒙部分
Java UI 用户界面设计(主要)
Java 基础(不考) JavaUI 分三层:
- 页面
- 容器组件(也叫做布局)
- 单体组件,最小单位
- 容器组件(也叫做布局)
布局:
- 定向布局(DirectionalLayout)重点考
- 依赖布局(DependentLayout)重点考
- 位置布局(PositionLayout)
- 表格布局(TableLayout)
- 自适应布局(AdaptiveBoxLayout)
- 堆叠布局(StackLayout)
定向布局
将组件按照水平或者垂直方向排布,能够方便地对齐布局内的组件。 其支持的属性:
alignment对齐方式layout_alignment对齐方式,此为定向布局DirectionalLayout所包含组件支持的属性,使得组件的对齐方式可以和父组件(DirectionalLayout)设定的alignment不同orientation子布局排列方向weight权重(所包含的组件的属性)
权重表示如图: 
alignment的取值:
| 取值 | 取值说明 |
|---|---|
| left | 表示左对齐 |
| top | 表示顶部对齐 |
| right | 表示右对齐 |
| bottom | 表示底部对齐 |
| horizontal_center | 表示水平居中对齐 |
| vertical_center | 表示垂直居中对齐 |
| center | 表示居中对齐 |
| start | 表示靠起始端对齐 |
| end | 表示靠结束端对齐 |
依赖布局
每个组件可以指定相对于其他同级组件的位置,或者指定相对于父组件的位置。
有一个属性:alignment(对齐方式)
| 取值 | 取值说明 |
|---|---|
| left | 表示左对齐 |
| top | 表示顶部对齐 |
| right | 表示右对齐 |
| bottom | 表示底部对齐 |
| horizontal_center | 表示水平居中对齐 |
| vertical_center | 表示垂直居中对齐 |
| center | 表示居中对齐 |
| start | 表示靠起始端对齐 |
| end | 表示靠结束端对齐 |
其他布局
- 表格布局 能将组件按照行列的方式放在表格中,形成整洁有序的布局方式。
- 堆叠布局(栈布局) 用来实现组件之间的层叠布局,添加到这个布局中的视图默认放到这块区域的左上角。第一个添加到布局中的视图显示在最底层,之后的组件会被添加到上层,依次堆叠。
- 位置布局
用于为组件设定特殊的位置。指定组件的
(x,y)坐标值在屏幕上显示。起始坐标(0,0)默认在左上角。 - 自适应(盒子)布局 使得页面上的多个组件在不同屏幕尺寸设备上能够自适应调整列数。
单体组件
文本组件(Text)
创建一个Text(xml版本) 1
2
3
4
5
6
7
8
9
10
11
12<Text
ohos:id="$+id:text"
ohos:width="300vp" (设置宽度: 300vp)
ohos:height="150vp" (设置高度)
ohos:text="Text组件" (文本显示内容)
ohos:background_element="$graphic:background_text" (设置背景)
ohos:text_size="66fp" (设置字体大小)
ohos:text_color="white" (设置文字颜色)
ohos:italic="true" (设置斜体)
ohos:text_weight="700" (设置字重,下面的是设置字体)
ohos:text_font="serif"
/>
最后,在MainAbilitySlice.java中,通过setUIContent()加载该xml布局。
1 | |
运行效果:
Java版:打开MainAbilitySlice.java文件,找到onStart()方法,创建Text组件。
1 | |
(和xml差不多) text
按钮组件(Button)
Button无自有的XML属性,共有XML属性继承自Text。
普通按钮和其他按钮的区别在于不需要设置任何形状,只设置文本和背景颜色即可。
1
2
3
4
5
6
7
8
9
10
11<Text
ohos:id="$+id:button"
ohos:width="200vp" (设置宽度: 200vp)
ohos:height="100vp" (设置高度)
ohos:text_size="30fp" (设置字体大小)
ohos:text="普通按钮" (按钮上文字显示的内容)
ohos:text_color="white" (设置文字颜色)
ohos:background_element="$graphic:background_button" (设置背景)
ohos:margin="25vp" (margin 为按钮外围和其他组件的间距,padding为按钮外围和按钮内部内容的间距)
ohos:padding="10vp"
/>background_element实现,设置background_element的shape属性为oval(椭圆)
-
胶囊按钮:指定background_element的背景文件为capsule_button.xml实现,在
capsule_button.xml文件中设置shape为矩形(rectangle),并且指定corners元素的
ohos:radius值。 -
圆形按钮:和椭圆按钮的区别在于组件本身的宽度和高度需要相同。
Toast对话框
1 | |
Ability (不多)
Page Ability
显示 Ability:需要调用父类Ability的onStart()方法,并使用super.setUIContent()方法加载之前创建的布局文件my_first_layout.xml。
修改1
2
3
4
5
6
7
8
9
10import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
public class MyFirstAbility extends Ability {
public void onStart(Intent intent)
{
// 调用父类onStart方法
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_my_first_layout);
}
}MyFirstAbility的配置信息的skills部分一个应用只能有一个主Ability,HarmonyOS只会显示在1
2
3
4
5
6
7
8"skills": [{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
]
}]config.json文件中遇到的第一个主Ability。销毁:
terminateAbility()
生命周期



Service Ability(只考一个小点)
开启&停止 生命周期