1. 故障
服务器上未看到某个节点的数据。
2. 使用伪代码分析节点代码
(分析后发现潜在问题蛮多的)
main 函数
1
2
3
4
5
6
7
8
9
10
初始化硬件
初始化 OS
如果初始化成功{
使能滴答时钟
创建 main_thread
如果创建成功{
启动 OS (不会返回)
}
}
loop{} // 如果前面的流程出错,会运行到这个地方
main_thread:
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
剩余发送尝试次数赋初始值
获取序列号
射频驱动初始化
初始化数据缓冲区
loop{
打印时间
如果剩余发送尝试次数没变{
读传感器数据
封装数据
打印 封装好的数据
}
信道活跃检测,最多三次
如果检测超时{
打印 检测超时 // to do:需要处理超时的情况
} 否则如果检测到信道活跃 {
打印 信道冲突 // to do:需要处理冲突的情况
} 否则 {
打印 信道检测完成
}
发送数据
如果发送没有超时{
打印 发送完成
} 否则 {
打印 发送超时 // to do:需要处理发送超时的情况
}
接收数据
如果接收完成{
打印 接收完成
从缓冲区读数据
如果读到了数据{
校验应答消息
如果校验成功{
剩余发送尝试次数改为初始值
} 否则 {
打印 应答消息无效
}
序列号+1
设置定时唤醒
停机
}
// to do:需要处理没读到数据的情况
} 否则如果接收超时 {
如果剩余发送尝试次数不为0{
剩余发送尝试次数-1
延时
} 否则 {
剩余发送尝试次数改为初始值
序列号+1
设置定时唤醒
停机
}
}
// to do:没有处理以上两种情况之外的情况
}
3. 故障分析过程
(1)捕捉异常信息
虽然网页上没有看到该节点的数据,网关上看到该数据格式有误,且一直收到固定的数据(格式有误,数值未变化)
1
2
[2020-09-21 19:45:58 ERROR gw:original_data_handle_thread] convert from data template failed: d":2,"name":"SN-002","temperature":24.16,"humidity":53.37,"voltage":4.69,"status":0}
[2020-09-21 19:51:05 ERROR gw:original_data_handle_thread] convert from data template failed: d":2,"name":"SN-002","temperature":24.16,"humidity":53.37,"voltage":4.69,"status":0}
完成的数据应该为:
1
{"id":2,"name":"SN-002","temperature":24.16,"humidity":53.37,"voltage":4.69,"status":0}
节点串口打印:
1
2
3
4
5
6
7
8
9
10
time:00:13:17
Cad done.
Tx done.
Rx done.
Error(7)
time:00:18:24
Cad done.
Tx done.
Rx done.
Error(7)
(2)原因分析
a. 数值未变化的原因分析
从节点串口打印看,没有打印数据,即剩余发送尝试次数发生了变化。剩余发送尝试次数只有在接收超时的情况下才会减1,即发生过接收超时。超时后再次发送,应答消息校验未通过,发生了停机。醒来后继续运行,剩余发送尝试次数发生了变化,跳过数据读取,发送、接收,应答消息校验未通过(网关 mcu 功能开发不全,应答消息一直无效),停机,醒来…一直这样循环。
b. 数据不完整的可能性分析
(1)网关 mcu
另一个节点的数据一直是正常的,网关 mcu 出问题的概率不大
(2)网关 linux 侧的应用程序(使用 rust 编写)
另一个节点的数据一直是正常的,这里出问题的概率也不大
(3)节点
封装好的数据前面有四个字节的头,包含网关地址;节点上 id
是调用 strcpy 复制的,未复制完全的概率不大;网关收到了数据,说明头校验通过了,发送这块没问题。 但是发送和接收用的是同一块缓冲区,接收一次数据后就会有问题。
发送的数据:
1
{0xff, 0xff, 0x00, 0x00, '{', '"', 'i', 'd', ...}
接收数据后(前四个字节未网关发过来的头,应该还是 {0xff, 0xff, 0x00, 0x00}):
1
{____, ____, ____, ____, 0x00, 0x01, 0x00, 'd', ...}
数据的前三个字节都是不可见字符,用 rust 实现的网关应用程序收到数据后,转换出来的字符串应该会有问题,很可能从 ‘d’ 开始。
验证:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
fn main() {
let a: [u8; 4] = [0, 1, 0, 100];
let b: [u8; 4] = [123, 22, 105, 100];
let a_slice: &[u8; 4] = &a;
let b_slice: &[u8; 4] = &b;
let r = String::from_utf8(a_slice[0..4 as usize].to_vec());
if let Ok(string) = r {
println!("a: {}", string)
}
let r = String::from_utf8(b_slice[0..4 as usize].to_vec());
if let Ok(string) = r {
println!("b: {}", string)
}
}
输出:
1
2
a: d
b: {id