参考手册 / 应用笔记 · 2020年2月15日

SenML传感器标记语言概要

转自 brookmil
https://blog.csdn.net/brookmill/article/details/52141147

“ML”和HTML、XML一样,都是”Markup Language”。前面的”Sen”来自Sensor,所以全名就是”Sensor Markup Language”。其实我觉得还不如就叫SensorML。为什么不叫SML呢?原来已经被占用了。

在IoT的潮流下,人民群众想要把传感器也都连入互联网。如果有一种标准的语言可以描述各行各业五花八门的所有传感器的数据,那当然是很方便的。SenML的编码结果可以作为HTTP或者CoAP的负载来传输。

SenML现在还在起草阶段,目前最新的版本是https://tools.ietf.org/html/draft-ietf-core-senml-02
最早是cisco一个叫jennings的帅锅一个人写的,后来陆续有其它公司的几个人加入。其中的Shelby和Bormann也参与了RFC7252(CoAP)的编写,可见两者有着紧密的联系。从历史记录来看,最早这个文档叫draft-jennings-senml,后来改名叫draft-jennings-core-senml,直到现在的draft-ietf-core-senml,中间一共有二十来个版本,不知道什么时候能成为正式的RFC。

以下就按照原文章节的顺序,把内容大概过一遍。其实都很简单,就当是简单翻译一下。

2.
先来看一个例子:
   [
       { “n”: “urn:dev:ow:10e2073a01080063”,
         “t”: 1276020076, “v”:23.5, “u”:”Cel” },
       { “n”: “urn:dev:ow:10e2073a01080063”,
         “t”: 1276020091, “v”:23.6, “u”:”Cel” }
   ]
这里面的”n”=Name, “t”=Time, “v”=Value, “u”=Unit. 它包含了同一个温度计测量的两个数据,第一个是23.5摄氏度,第二个是23.6摄氏度。时间是1970年1月1日以来的秒数,所以两次的测量的时间相差15秒,都发生在2010年6月。这大概就是作者最早开始写这篇文档的时间吧。

3.
提到了两个概念:record和pack。前面那个例子就是一个SenML Pack,它包含了两个SenML Records.

4.
前面例子里的name、unit等等都属于attributes。每个attribute都可以有两种:base和regular。base必须出现在一个pack的第一个record里面,它适用于整个pack的每一个record。regular可以出现在任何一个record,它只适用于所在record的本身。base和regular都不是必须有的,比如前面例子就只有regular没有base。

虽然各种base attributes都是适用于每一个record,他们的具体用法都不一样,这里要稍微注意一下。
Name = BaseName + RegularName
Time = BaseTime + RegularTime
Unit = (RegularUnit存在) ? RegularUnit : BaseUnit
Value = BaseValue + RegularValue
再来看看前面的例子。因为两条记录的名字一样,就没必要写两遍,用一个base name就行了:
   [
       { “bn”: “urn:dev:ow:10e2073a01080063”,
         “t”: 1276020076, “v”:23.5, “u”:”Cel” },
       {  “t”: 1276020091, “v”:23.6, “u”:”Cel” }
   ]

Name必须是能唯一标识一个传感器的,类似URI。
Value根据类型的不同可以有几种: vs(string), vb(boolean),等等。一般每个record是必须要有个value的,不然这个record就没有意义了。唯一的例外是如果存在一个Sum(累计值),就允许没有Value。
Update Time: 在这个时间之前,会有一个新的测量结果。

上面这一段不知道写清楚没有。我自己都觉得写的别扭,没办法,语文一向不好。没看懂也没关系,看看后面第5章的几个例子应该就能明白了。

4.3
除了本文列出的Name、Value这些之外,将来可能会增加一些新的attributes。所以,写代码的时候,对于不认识的attributes不能报错,直接忽视就好了。

关于时间:
Time = BaseTime + RegularTime
if (Time > 0)
{
    这个值是从1970年1月1日以来的秒数
}
else
{
    传感器自己没有年月日的概念,所以没法提供绝对时间,只有相对时间
    if (Time == 0)
    {
        这个数据是刚刚测到的
    }
    else
    {
        比如Time的值如果是-5,就说明这个数据是5秒前测的
    }
}

关于传感器自身的一些特征,比如说精度,大概不容易找到一个通用的方法能适合各种传感器的。以后可能会有新的设计来满足这方面的需求。看到这句我就不厚道的笑了,因为我想起了以前一个同事说的: We always want to do something later, but later never comes.

5.
这张表列出了现有的attributes
                    +—————+——-+———+
                    |          Name | label | Type    |
                    +—————+——-+———+
                    |     Base Name | bn    | String  |
                    |     Base Time | bt    | Number  |
                    |     Base Unit | bu    | String  |
                    |    Base Value | bv    | Number  |
                    |       Version | bver  | Number  |
                    |          Name | n     | String  |
                    |          Unit | u     | String  |
                    |         Value | v     | Number  |
                    |  String Value | vs    | String  |
                    | Boolean Value | vb    | Boolean |
                    |    Data Value | vd    | String  |
                    |     Value Sum | s     | Number  |
                    |          Time | t     | Number  |
                    |   Update Time | ut    | Number  |
                    +—————+——-+———+
                        Table 1: JSON SenML Labels

5.1.2
还是看例子最简单
   [ {“bn”: “urn:dev:ow:10e2073a01080063”,
      “n”: “voltage”, “t”: 0, “u”: “V”, “v”: 120.1 },
     {“n”: “current”, “t”: 0, “u”: “A”, “v”: 1.2 }
   ]
上面给出了两个传感器的数据:电压表的名字是”urn:dev:ow:10e2073a01080063voltage” , 数据是120.1伏特。电流表的名字是”urn:dev:ow:10e2073a01080063current”,数据是1.2安培。两个数据的时间都是0,说明这两个数据都是刚测的,而两个传感器都不知道年月日。

   [{“bn”: “urn:dev:ow:10e2073a01080063/”,
     “bt”: 1276020076.001,
     “bu”: “A”,
     “bver”: 5,
     “n”: “voltage”, “u”: “V”, “v”: 120.1 },
      { “n”: “current”, “t”: -5, “v”: 1.2 },
      { “n”: “current”, “t”: -4, “v”: 1.30 },
      { “n”: “current”, “t”: -3, “v”: 0.14e1 },
      { “n”: “current”, “t”: -2, “v”: 1.5 },
      { “n”: “current”, “t”: -1, “v”: 1.6 },
      { “n”: “current”, “t”: 0,  “v”: 1.7 }
   ]
这个稍微复杂一点。同样是两个传感器,电压表的名字是”urn:dev:ow:10e2073a01080063/voltage”,电流表的名字是”urn:dev:ow:10e2073a01080063/current”。这次包括了BaseTime,BaseUnit,和BaseVersion。电压表的数据没有RegularTime,所以他的时间就是BaseTime。电压表包括了RegularUnit是伏特,所以BaseUnit对它不适用。电流表没有RegularUnit,所以他的单位就是BaseUnit安培。电流表的数据一共有6个,分别测量于1276020071.001(1.2安培)到1276020076.001(1.7安培)之间,每个间隔一秒。

5.1.3
再来一个例子
   [{“bn”: “urn:dev:ow:10e2073a01080063”,
     “bt”: 1320067464,
     “bu”: “%RH”,
        “v”: 20.0, “t”: 0 },
      { “v”: 24.30621, “u”: “lon”, “t”: 0 },
      { “v”: 60.07965, “u”: “lat”, “t”: 0 },
      { “v”: 20.3, “t”: 60 },
      { “v”: 24.30622, “u”: “lon”, “t”: 60 },
      { “v”: 60.07965, “u”: “lat”, “t”: 60 },
      { “v”: 20.7, “t”: 120 },
      { “v”: 24.30623, “u”: “lon”, “t”: 120 },
      { “v”: 60.07966, “u”: “lat”, “t”: 120 },
      { “v”: 98.0, “u”: “%EL”, “t”: 150 },
      { “v”: 21.2, “t”: 180 },
      { “v”: 24.30628, “u”: “lon”, “t”: 180 },
      { “v”: 60.07967, “u”: “lat”, “t”: 180 }
   ]
这是个多功能传感器,可以测量多种数据。BaseTime是UTC 2011年10月31日13:24:24,从BaseTime开始每分钟测量一组数据,每组数据都包括了湿度、经度和纬度。在BaseTime+150秒的时候还测量了一个数据,电池的余量98%。

9
这一章讨论了关于Sum累积和的使用。有些场合用Sum是很合理的,比如电表、水表,它可以减少累积误差,而且中间传输的数据有些丢失也不会导致大问题。有些情况,比如温度计,使用Sum就会显得很奇怪,但也可能有用,比如统计平均值就很方便了。当然任何时候用Sum都需要注意数据溢出的问题。

11.1
这里有张表列出了所有的测量单位。比如5.1.3的例子里面有个单位是”%EL”,如果不知道它是什么,查了这张表就知道是相对湿度。注意单位都是区分大小写的。如果需要用到一个单位但是这个表里没有,可以申请加进来。

13
SenML没有任何的安全机制。如果敏感数据有安全的需求,那就只好从底层想办法,比如TLS或者DTLS。
————————————————
版权声明:本文为CSDN博主「brookmill」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/brookmill/article/details/52141147