系列文章合集:IoT Power PC 端技术总结
原始数据处理
从《IoT Power PC 端技术总结 – 2 与设备通信》中我们可以了解到:单片机传输到电脑的数据,是原始的ADC采样数据。那么电脑上就需要将数据处理成可以给人实际查看和计算的电压与电流值。
这一步很简单,IoT Power
所使用的转换公式,类似于y=ax+b
,其中a
和b
会随着设备、档位的不同,使用不同的值。
我们只需要对每个采样点分别处理,即可计算出我们需要的原始值。同时为了后续计算时不怎么丢失精度,我这里直接使用了double
(akaf64
),毕竟用户电脑上的内存又不用我花钱😄
数据构成
获取到了每个点的原始值,那么就要考虑怎么存储这些值了。
这里分析一下,对于每个数据点,我们需要的是这些信息:
- 该点的原始电压值
- 该点的原始电流值
- 该点所处的时刻信息
前两者我们都获取到了,就剩该点所处的时刻信息
。这个数据我们可以约定:
MCU上报的每包数据,携带一个包序号;同时,MCU每包数据的采样间隔严格固定(MCU晶振一天误差不到1秒,已经相当可靠)。
这样我们就可以根据包序号、包数据量、包时间间隔,计算得出每个点的具体时刻。
数据的临时存储
上面的数据还只是一个点,那么这种多个点的情况,如何存储呢?这是就需要考虑一下数组数据的存储方式了。
我们这些数据十分有规律,所有数据的时间信息都是从小到大排列,并且新数据只有可能被附加到列表的末尾,我们可以利用这套特性来实现一些功能。
按存储的方式,我们可以分为两种:内存
、硬盘文件
。两种存储方式各有优劣,所以我在软件中同时支持了这两种方式,并提供给用户自由选择的权利。
影响 | 存到内存 | 存到硬盘 |
---|---|---|
附加数据速度 | 快 | 慢 |
获取数据 | 快 | 慢 |
空间 | 被内存大小限制 | 被硬盘大小限制 |
临时存到内存中
这种存储方式就很简单了,直接用List<T>
进行存储即可。存取迅速,.Net
平台自身的优化也足够使用。
临时存到硬盘中
存储时可以在配置文件目录,新建一个临时文件进行存储,文件每增加一个点,文件末尾增加以下信息:
- 点数据的时间
- 点的电压
- 点的电流
这样可以保证每个数据点使用的字节数都完全相等,如果需要读取哪一个点,只需要将文件的指针通过seek
更改到对应的字节位置读取解析即可,不会太影响计算效率。
获取某个时间的点
如果阅读过前面的操作,会有一个这种需求:获取某个指定的时间点附近的点数据。
显然我们不能通过下标来获取,但是由于每个点都是按时间顺序存储在数组中的,所以可以用二分查找
来实现这个功能。
可能有读者会疑惑:不是每个点时间间隔相同吗?实际上在硬件交互的场景下,丢包是不可避免的,这个方式并不可靠。并且在早期硬件版本(V1)中,包上报的间隔并不固定,这就更不可能假设每个点的间隔绝对固定。
数据的永久存储
缓存数据大一点对大部分人来说都是可以接收的,毕竟都是为了速度考虑。但如果说你想分享自己抓取的文件给别人,原始数据就相当大了,这里可以计算看一小时的数据量:
[4字节(时间戳) + 8字节(电压) + 8字节(电流)] * 10_000Hz * 3600
= 720,000,000 字节
= 686.6 MB
为了使得存储分享时占用的空间没有那么夸张,我选择使用压缩来处理导出的文件。
导出时并不需要极致的压缩率,相反,如果到导出时间过长,反而会更加影响使用体验。
所以这里的压缩算法使用的是LZ4
,压缩率平均下来可以达到20%
,最重要的是压缩速度极快,对用户来说就像是复制文件一样,速度基本不受影响。
数据的导入
这一部分就没有什么太多可讨论的了,就是前面存储的方式逆转过来操作。