3个版本
0.0.3 | 2019年4月16日 |
---|---|
0.0.2 | 2019年4月16日 |
0.0.1 | 2019年2月20日 |
#297 in 身份验证
73KB
1.5K SLoC
SAFEthing框架
Secure Access For Everything
项目目标
- 为物联网软件开发者提供一种简单直接的方法,将他们的物联网设备集成到SAFE网络中,无需担心网络、安全性和/或身份验证和授权协议。
- 创建一个项目,可以作为希望学习和实施SAFE网络软件的开发者的知识库。
- 让SAFE网络社区参与一个能够为SAFE网络创造价值的项目,并有助于推广它,实现大规模采用。
- 最终,让SAFE网络社区自己设计和开发下一代物联网框架和通信协议!
激励措施
当前的物联网协议和框架(例如MQTT、CoAP)都有一系列类似的问题要解决,它们的挑战似乎主要与安全和NAT(在不公开IP的情况下连接到位于不同网络中的设备)有关。这些协议通过在网络上拥有服务器/代理来解决这些问题,这不仅增加了设备软件开发的复杂性,而且也带来了重大的安全和隐私问题,当您的物联网设备需要通过服务器进行通信时,您不得不再次信任第三方。
SAFE网络具有许多属性,使其成为解决所有这些问题的优秀解决方案,同时开发者和使用者一开始就不必担心这些问题,他们只需专注于开发物联网设备的主要逻辑!。
这个框架允许开发者轻松地将他们的物联网设备集成到SAFE网络中,甚至无需深入了解SAFE网络API或技术细节。
运行示例SAFEthing应用程序
本项目处于非常早期阶段,然而已经有一些SAFEthing应用展示了如何使用SAFEthing API来实现园艺系统。其中一个是SAFEthing管理土壤湿度传感器和水阀(core/examples/gardening_device.rs),另一个SAFEthing则作为园艺系统的监控和控制设备(core/examples/gardening_controller.rs)。
以下是对这些应用试图展示内容的总结,但在代码中还有更多关于其功能的详细注释,因此请参考以获取更多解释。
先决条件-
为了能够运行这些示例应用,请确保您已安装了rustc v1.33.0或更高版本。
-
您还需要本地运行SAFE Authenticator CLI并公开其WebService接口以授权应用,并且登录到在模拟网络上创建的SAFE账户(即
MockVault
文件)。这些SAFEthings应用中的每一个都将向https://127.0.0.1:41805/authorise/
端点发送授权请求,该端点可以通过遵循safe_auth CLI文档的这一部分中的说明来提供,确保您设置的端口号为41805
。
首先要做的事情是克隆这个仓库,并切换到其core
子目录。
$ git clone https://github.com/bochaco/safe_thing.git
$ cd ./safe_thing/core
现在您可以通过执行以下命令来运行两个SAFEthings中的任意一个,即管理土壤湿度传感器和水阀的SAFEthing
$ cargo run --features use-mock-routing --example gardening_device
这个SAFEthing应用将发布一些属性,例如动态属性moisture-level
和valve-state
,以及其他几个其他SAFEthing可以注册的主题VeryWetAlarm
和VeryDryAlarm
,以及一些可以触发的动作OpenValve
和CloseValve
,分别用于打开和关闭水阀。此SAFEthing应用还模拟了土壤湿度水平根据水阀的开启或关闭而增加或减少,只是为了理解另一个SAFEthing如何订阅主题和动态属性,以及向其发送动作请求。
现在可以运行第二个SAFEthing,即园艺控制器。为了这样做,请打开一个新的终端窗口,确保您仍在同一个safe_thing/core/
目录中,并使用以下命令运行它
$ cargo run --features use-mock-routing --example gardening_controller
园艺控制器SAFEthing将订阅由园艺设备(我们之前运行的第一个SAFEthing应用)公开的动态属性和主题,监控土壤湿度水平是否低于某个阈值。在这种情况下,它将发送一个请求来打开水阀,直到湿度水平达到一个对植物健康有益的上限,然后它会发送第二个请求来关闭水阀。这个周期将无限重复,因为当水阀关闭时,土壤湿度水平将自动开始下降。
您可以通过查看两个SAFEthing应用(在两个终端控制台中)的输出,来了解它们如何响应彼此之间发送的通知和动作请求。如果您希望看到更多细节,可以启用任何日志级别,例如,要查看由safe_thing
框架生成的日志的debug
级别,您可以使用以下命令运行它们
$ RUST_LOG=safe_thing=debug cargo run --features use-mock-routing --example gardening_device
和
$ RUST_LOG=safe_thing=debug cargo run --features use-mock-routing --example gardening_controller
库和API
SAFEthing 库由几个部分组成,但其核心仅是一个具有简单且定义良好的 Rust API 的 Rust 包。
在内部,它包含所有与 SAFE 网络(通过 safe_client_libs)通信的机制,抽象出客户端应用程序,无需应用开发者理解 SAFE 网络的工作原理。
类似于 SAFE 网络本身提供不同编程语言的绑定方式,将有一个 SAFEthing Rust FFI 接口,可用于从任何编程语言(如 C/C++)与 API 交互,同时还提供一组不同语言的绑定,以便人们可以使用 JavaScript、Python、Lua、Go 等语言开发他们的 SAFEthings 软件。
在 Rust API 之上还将创建一个 WebService API,以允许通过 REST 接口与 SAFEthings 网络进行通信。这主要旨在支持智能家居设备以及为它们提供配置所需的工具。
SAFEthings
当 SAFEthing 注册到网络时,它提供一组信息,描述其行为、功能以及/或其公开的服务。
属性属性被公开以向连接到网络的其它事物提供有关设备/事物的信息。它们也可以被人类用来在通过控制台/门户连接时识别设备及其/或其功能。
属性可以是静态的或动态的。一些静态属性的例子包括固件版本、设备名称和型号,它们的值不依赖于或根据事物的功能或状态而改变。注意这些属性可能仍然会被用户更改/修改,但就其值而言,并不与设备的状态绑定。
另一方面,一些属性可能包含动态值,这些值由 SAFEthing 更新,例如,温度传感器可以更新一个动态属性以显示当前的读数,或者一个具有更复杂功能的 SAFEthing 可以公开一个描述其当前状态的属性。
主题SAFEthing 可以公开一组主题,其它 SAFEthing 可以订阅这些主题以接收事件的通知。
不同的事件会导致不同类型的通知,主题可以描述某种类型的事件,具体取决于 SAFEthing 如何设计来公开它们。
例如,温度传感器可以公开一个“温度变化”主题,其他 SAFEthing 可以订阅并接收温度变化事件的通知。
在订阅主题时,可以提供一系列过滤器以减少要接收的通知量,只接收订阅者真正感兴趣的通知。例如,一个 SAFEthing 可能只对当前温度超过阈值时才被通知感兴趣。
待办事项:动态属性与主题事件的订阅 TODO:保留消息支持 TODO:描述订阅和通知过滤器 & 参数
待办事项:支持出生/关闭/遗书/遗嘱主题
动作与 SAFEthing 交互的另一种方式是请求一个动作。动作集通常是静态的,但可能存在 SAFEthing 只想在特定时刻或时间段内公开一些动作的情况。
每个动作都通过一个名称、一组它期望和/或支持的输入参数以及其输出的定义来公开。
动作的执行是异步的。当请求 SAFEthing 执行一个动作时,它会被添加到其动作请求队列中。每个动作的执行顺序和/或优先级是应用程序特定的,尽管框架将提供一些工具来以预定义的顺序检索它们。
访问类型SAFEthing 的属性、主题和操作都与访问类型相关联。访问类型定义了可以访问公开功能和信息的 SAFEthing 集合。
例如,您发送到 SAFEthing 打印机的数据应该加密,并且只有发送设备和打印机设备可以访问。或者,如果您有一组在家中共享交互的设备,您希望只有您的设备可以查看彼此的信息和功能,而其他人则不行。
通信协议
待办事项
用例:注册和发布订阅和通知钱包待办事项
SAFEthing Rust 客户端片段
以下是一个 SAFEthing 客户端应用程序的片段,请参阅 核心示例文件夹 以查看完整代码,并参阅 运行示例 SAFEthing 应用程序 以获取运行说明。
extern crate safe_thing;
use safe_thing::{AccessType, ActionDef, SAFEthing, ThingAttr, Topic};
pub fn main() {
// Let's create a SAFEthing id for the gardening device, this could be the device serial number
let id = "gardening-device-serial-number-01010101";
// Let's have the SAFEthing framework to authorise the device with any
// available SAFE Authentiactor rather than providing the authorisation credentials
let auth_uri = "";
let attributes = [
ThingAttr::new("name", "SAFEthing Gardening Device", false),
ThingAttr::new("firmware", "v0.1.0", false),
ThingAttr::new("moisture-level", "", true),
ThingAttr::new("pressure-psi", "50", true),
ThingAttr::new("valve_state", "closed", true),
];
let topics = [
Topic::new("VeryDryAlarm", AccessType::All),
Topic::new("VeryWetAlarm", AccessType::All),
];
let actions = [
ActionDef::new("OpenValve", AccessType::All, &["psi"]),
ActionDef::new("CloseValve", AccessType::All, &[]),
];
// Let's create an instance of SAFEthing for this device.
// We already provide the two callback functions to be called
// for subcriptions notifications and action requests respectively.
let mut safe_thing =
SAFEthing::new(&id, auth_uri, &subscriptions_notif, &action_request_notif).unwrap();
// Register the SAFEthing on the network, this won't make it active yet
// but it will just store the device's data onto the network as a SAFEthing entity
safe_thing
.register(&attributes, &topics, &actions)
.map(|()| println!("Gardening device registered on the network"))
.unwrap();
// Let's now make it active and ready for receiving action requests from other SAFEthings
safe_thing.publish().expect("Failed to publish SAFEthing");
// We now go into an infinite loop which contains the main logic of this device
loop {
let current_moisture_level: f32 = /* get soil moisture level from sensor reading */
// Let's keep the published dynamic attribute up to date for any
// other SAFEthing to be notified if it's interested in knowing about the new value
println!(
"Updating value of 'moisture_level' dynamic attribute to '{}'",
current_moisture_level
);
safe_thing
.set_attr_value("moisture-level", ¤t_moisture_level.to_string())
.unwrap();
// This device also supports two topics (VeryWetAlarm and VeryDryAlarm) that
// other SAFEthings can register to in order to receive notifications when it detects
// that the soil moisture level goes beyond thresholds. Thus we should check the current
// moisture level and send the notification for the corresponding topic.
if current_moisture_level > 8.0 {
let _ = safe_thing.notify("VeryWetAlarm", "");
} else if current_moisture_level < 3.0 {
let _ = safe_thing.notify("VeryDryAlarm", "");
}
// Let's wait for some time before going into a new cycle of reading the
// current soil moisture level and publishing the new value
thread::sleep(Duration::from_millis(3000));
}
}
项目开发路线图
- 文档 API
- 为 API 创建测试套件
- 使用测试 SAFE 网络创建展示应用
- MIPS 的交叉编译工具/文档
- ARM 的交叉编译工具/文档
- 实现 FFI 接口
- 实现 JavaScript 绑定
- 通信协议的文档
- 实现 WebService API
许可证
通用公共许可证 (GPL),版本 3 (LICENSE)
版权所有 (c) 2017-2019 Gabriel Viganotti <@bochaco>。
此文件是 SAFEthing 框架的一部分。
SAFEthing 框架是自由软件:您可以在自由软件基金会发布的 GNU 通用公共许可证的条款下重新分发和/或修改它,无论是许可证的第 3 版,还是(按您选择)此许可证的任何后续版本。
SAFEthing 框架的发布是希望它会很有用,但没有提供任何保证;甚至没有隐含的适销性或特定用途的适用性的保证。有关详细信息,请参阅 GNU 通用公共许可证。
依赖关系
~45MB
~1M SLoC