物联网设备流程的行为

时间:2017-09-15 09:26:34

标签: erlang

我有一台Erlang服务器,许多IoT摄像机使用TCP连接并使用序列号注册自己。

同一台服务器还运行一个提供API的Web服务(牛仔)。

我想创建一个可以从IoT相机中获取照片的API。

我在考虑将IoT流程建模为gen_server,并使用IoT序列号注册全局名称。

当收到牛仔的请求时,我会做一个gen_server:call()并等待照片下载。

我的问题是,如果设备未注册gen_server:call()将使进程崩溃。我宁愿只返回错误信息而不是崩溃所以我在考虑使用try ... catch。

有更好的方法吗?或者更好的方式来模拟物联网流程?

1 个答案:

答案 0 :(得分:2)

在了解您希望对此进行建模的方式之前,需要清除一些不同的问题。

在进一步深入之前,我会做一些广泛的假设。

  • 任何跟踪设备的中央服务也会保留这些设备产生的数据(因此无论数据是否正确连接,都可以检索数据,并且数据检索可以是异步/历史)。
  • 大多数设备都会尝试通过TCP维持持久连接。
  • TCP连接将失败。
  • 设备会记住他们的身份(MAC,序列号,标签,位置或其他独特的东西)。

有了这些假设,我们就可以开始工作了。

将您的设备建模为流程,每个连接一个流程。

有一个单独的进程根据其ID随时间的变化维护这些设备的注册表(并且您将需要一种不具有这种欺骗的方式,因为设备可能比用户连接更难以保护 - 这可能是如果无法为设备分配公钥/私钥对,则是您最烦人的挑战。

注册表进程维护一个图像请求队列。每当相机连接其队列时,如果有任何请求待处理,则发出该队列。每当请求进入并且注册表指示相机在线时,立即发出请求。有时这就像制作像

这样的数据结构一样容易
[{CameraID :: mac(), Status :: pid() | [image_request()]}]

(我假设您熟悉typespec language Erlang implements。如果没有,请仔细阅读 - 真的很有用!)

如果你有很多相机,它可能是一张地图:

#{CameraID := PID | [Request]}

或者你可以使用带标记的元组来实现灵活(并且更容易解密和调试):

#{CameraID := {pid, PID} | {requests, [Request]}}

当您查找相机时,您将检索列表或PID。您收到的是哪种类型向您显示相机当前是否已连接 - 因此您可以将消息发送到PID(如果您收到的话),如果您收到列表,则将请求添加到图像请求列表,以及每当相机连接到您时在继续之前将请求列表发送给它。您的注册表进程需要monitor/2您的相机的连接处理流程。从注册表的角度来看,这些连接处理程序相机。每当一个终止时(进程崩溃,连接失败,数据变得有趣,无论如何),您的注册表必须知道将失败的摄像机的注册数据从pid()切换为请求列表。 / p>

传入的图像将保存到磁盘并记录在单独的注册表中(如果您不需要超出图像格式和系统文件名+目录名称可提供的元数据,则可以将文件系统用作自己的注册表)。

牛仔将基于它在数据目录中找到的任何内容,或者基于它从图像注册表中检索的内容(如果您决定创建这样的过程)来提供服务。

无论如何,你会发现""与之通信的摄像机不是通过全球注册的名称,而是通过注册过程将消息路由(并顺序化)到您的摄像机,以保持对摄像机的了解。

如果您需要持久性数据,那么您希望将相机ID保存到磁盘,但如果没有,那么只需让他们自行注册并以某种方式对其进行身份验证。

还要考虑

您可能不需要随时间维护数据,并且您可能永远不想为当前断开连接的摄像机排队请求。它可能只是一个"只有生活"系统。在这种情况下,任务更容易 - 注册表只是消息路由器。我可能仍然希望将图像数据保存到磁盘,因为否则会出现奇怪的拥塞。在这种情况下,在检索/查看图像后删除图像并不罕见。

通过这种方式,您可以发出异步图像请求,并构建最大图像每分钟(或任何间隔)的规则,其中对在过去X秒(或分钟)拍摄图像的相机发出任何请求,无论如何)将服务于当前缓存的图像,而不是麻烦采取新的。根据具体情况,这可以极大地提高性能。

在任何情况下,允许请求为cast而不是call允许您打破Web服务和摄像头之间的强链接(可能会在超时时崩溃)。如果图像尚未存在,则网络界面无法看到它。如果它正在等待,请说明并提供超时 - 但将这些内容保留在Web界面上,同时仅显示当前连接的摄像头。