• Stars
    star
    206
  • Rank 190,504 (Top 4 %)
  • Language
    Rust
  • License
    Mozilla Public Li...
  • Created over 6 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Rust implementation of a Web Thing server

webthing

Build Status Crates.io license

Implementation of an HTTP Web Thing.

Using

If you're using Cargo, just add webthing to your Cargo.toml:

[dependencies]
webthing = "0.15"

TLS Support

If you need TLS support for the server, you'll need to compile with the ssl feature set.

Example

In this example we will set up a dimmable light and a humidity sensor (both using fake data, of course). Both working examples can be found in here.

Dimmable Light

Imagine you have a dimmable light that you want to expose via the web of things API. The light can be turned on/off and the brightness can be set from 0% to 100%. Besides the name, description, and type, a Light is required to expose two properties:

  • on: the state of the light, whether it is turned on or off
    • Setting this property via a PUT {"on": true/false} call to the REST API toggles the light.
  • brightness: the brightness level of the light from 0-100%
    • Setting this property via a PUT call to the REST API sets the brightness level of this light.

First we create a new Thing:

let mut light = BaseThing::new(
    "urn:dev:ops:my-lamp-1234".to_owned(),
    "My Lamp".to_owned(),
    Some(vec!["OnOffSwitch".to_owned(), "Light".to_owned()]),
    Some("A web connected lamp".to_owned()),
);

Now we can add the required properties.

The on property reports and sets the on/off state of the light. For our purposes, we just want to log the new state if the light is switched on/off.

struct OnValueForwarder;

impl ValueForwarder for OnValueForwarder {
    fn set_value(&mut self, value: serde_json::Value) -> Result<serde_json::Value, &'static str> {
        println!("On-State is now {}", value);
        Ok(value)
    }
}

let on_description = json!({
    "@type": "OnProperty",
    "title": "On/Off",
    "type": "boolean",
    "description": "Whether the lamp is turned on"
});
let on_description = on_description.as_object().unwrap().clone();
thing.add_property(Box::new(BaseProperty::new(
    "on".to_owned(),
    json!(true),
    Some(Box::new(OnValueForwarder)),
    Some(on_description),
)));

The brightness property reports the brightness level of the light and sets the level. Like before, instead of actually setting the level of a light, we just log the level.

struct BrightnessValueForwarder;

impl ValueForwarder for BrightnessValueForwarder {
    fn set_value(&mut self, value: serde_json::Value) -> Result<serde_json::Value, &'static str> {
        println!("Brightness is now {}", value);
        Ok(value)
    }
}

let brightness_description = json!({
    "@type": "BrightnessProperty",
    "title": "Brightness",
    "type": "number",
    "description": "The level of light from 0-100",
    "minimum": 0,
    "maximum": 100,
    "unit": "percent"
});
let brightness_description = brightness_description.as_object().unwrap().clone();
thing.add_property(Box::new(BaseProperty::new(
    "brightness".to_owned(),
    json!(50),
    Some(Box::new(BrightnessValueForwarder)),
    Some(brightness_description),
)));

Now we can add our newly created thing to the server and start it:

let mut things: Vec<Arc<RwLock<Box<dyn Thing + 'static>>>> = Vec::new();
things.push(Arc::new(RwLock::new(Box::new(light)));

// If adding more than one thing, use ThingsType::Multiple() with a name.
// In the single thing case, the thing's name will be broadcast.
let mut server = WebThingServer::new(
    ThingsType::Multiple(things, "LightAndTempDevice".to_owned()),
    Some(8888),
    None,
    None,
    Box::new(Generator),
    None,
    None,
);
let server_addr = server.create();
server.start();

This will start the server, making the light available via the WoT REST API and announcing it as a discoverable resource on your local network via mDNS.

Sensor

Let's now also connect a humidity sensor to the server we set up for our light.

A MultiLevelSensor (a sensor that returns a level instead of just on/off) has one required property (besides the name, type, and optional description): level. We want to monitor this property and get notified if the value changes.

First we create a new Thing:

let mut thing = BaseThing::new(
    "urn:dev:ops:my-humidity-sensor-1234".to_owned(),
    "My Humidity Sensor".to_owned(),
    Some(vec!["MultiLevelSensor".to_owned()]),
    Some("A web connected humidity sensor".to_owned()),
);

Then we create and add the appropriate property:

  • level: tells us what the sensor is actually reading

    • Contrary to the light, the value cannot be set via an API call, as it wouldn't make much sense, to SET what a sensor is reading. Therefore, we are creating a readOnly property.
    let level_description = json!({
        "@type": "LevelProperty",
        "title": "Humidity",
        "type": "number",
        "description": "The current humidity in %",
        "minimum": 0,
        "maximum": 100,
        "unit": "percent",
        "readOnly": true
    });
    let level_description = level_description.as_object().unwrap().clone();
    thing.add_property(Box::new(BaseProperty::new(
        "level".to_owned(),
        json!(0),
        None,
        Some(level_description),
    )));

Now we have a sensor that constantly reports 0%. To make it usable, we need a thread or some kind of input when the sensor has a new reading available. For this purpose we start a thread that queries the physical sensor every few seconds. For our purposes, it just calls a fake method.

let sensor = Arc::new(RwLock::new(Box::new(sensor))));
let cloned = sensor.clone();
thread::spawn(move || {
    let mut rng = rand::thread_rng();

    // Mimic an actual sensor updating its reading every couple seconds.
    loop {
        thread::sleep(time::Duration::from_millis(3000));
        let t = cloned.clone();
        let new_value = json!(
            70.0 * rng.gen_range::<f32>(0.0, 1.0) * (-0.5 + rng.gen_range::<f32>(0.0, 1.0))
        );

        {
            let mut t = t.write().unwrap();
            let prop = t.find_property("level".to_owned()).unwrap();
            let _ = prop.set_value(new_value.clone());
        }

        t.write()
            .unwrap()
            .property_notify("level".to_owned(), new_value);
    }
});

This will update our property with random sensor readings. The new property value is then sent to all websocket listeners.

Adding to Gateway

To add your web thing to the WebThings Gateway, install the "Web Thing" add-on and follow the instructions here.

More Repositories

1

gateway

WebThings Gateway
TypeScript
2,599
star
2

wiki

Developer Wiki
Shell
291
star
3

webthing-node

Node.js implementation of a Web Thing server
TypeScript
232
star
4

webthing-arduino

Simple server for ESP8266, ESP32, Ethernet, or WiFi101-compatible boards compliant with Mozilla's proposed WoT API
C++
204
star
5

webthing-python

Python implementation of a Web Thing server
Python
177
star
6

api

Web Thing API Specification
HTML
164
star
7

registration_server

The registration server for WebThings Gateway.
Rust
78
star
8

addon-list

List of installable add-ons for WebThings Gateway
Python
77
star
9

gateway-docker

Legacy docker image for WebThings Gateway - now moved to main gateway repo at https://github.com/WebThingsIO/gateway
Dockerfile
71
star
10

webthing-java

Java implementation of a Web Thing server
Java
51
star
11

webthing-upy

MicroPython implementation of a Web Thing server
Python
50
star
12

zigbee-adapter

Zigbee adapter add-on for WebThings Gateway
JavaScript
46
star
13

example-adapter

Example adapter add-on for WebThings Gateway
JavaScript
34
star
14

homekit-adapter

HomeKit device adapter for WebThings Gateway
JavaScript
22
star
15

thing-url-adapter

Proxy adapter for Web Thing API endpoints
JavaScript
22
star
16

philips-hue-adapter

WebThings Gateway Philips Hue Adapter
TypeScript
21
star
17

mozilla-iot.github.io

Mozilla IoT Website
SCSS
20
star
18

curl-examples

Examples of using the gateway API using curl
Shell
19
star
19

gateway-addon-python

Python bindings for developing add-ons for WebThings Gateway
Python
16
star
20

zwave-adapter

Z-Wave adapter add-on for WebThings Gateway
JavaScript
15
star
21

tplink-adapter

TP-Link Kasa smart plug/bulb adapter for WebThings Gateway
Python
15
star
22

gateway-addon-node

Node bindings for developing add-ons for WebThings Gateway
TypeScript
13
star
23

virtual-things-adapter

WebThings Gateway Virtual Things Adapter for experimenting with new thing types
JavaScript
12
star
24

onvif-adapter

ONVIF Profile S video camera adapter
JavaScript
10
star
25

voice-addon

Voice control add-on for WebThings Gateway
JavaScript
8
star
26

yeelight-adapter

Yeelight device adapter for WebThings Gateway
JavaScript
7
star
27

weather-adapter

Weather adapter for WebThings Gateway
JavaScript
7
star
28

lg-tv-adapter

LG webOS TV adapter for WebThings Gateway
JavaScript
7
star
29

serial-adapter

WebThings Gateway adapter for talking to serial-mcu based software through a serial port.
JavaScript
7
star
30

deconz-api

Talk to Zigbee devices using ConBee dongle or RaspBee HAT, modelled after xbee-api
JavaScript
7
star
31

gateway-deb

Debian package for running WebThings Gateway
Shell
6
star
32

things-controller

Things Controller
Java
6
star
33

roku-adapter

Roku adapter
JavaScript
6
star
34

mozgateway-alexa-skill

Alexa Skill to interact with Mozilla WebThings Gateway
Python
6
star
35

rpi-image-builder

Builds gate files needed to create a Raspberry Pi image
Shell
6
star
36

intent-parser

Intent Parser for the Mozilla WebThings Gateway
Python
5
star
37

schemas

A Web of Things schema repository
HTML
5
star
38

zigbee-zdo

Module for parsing and building Zigbee ZDO frames for use with xbee-api or deconz-api
JavaScript
5
star
39

android-app

A Web of Things client for Android
Kotlin
5
star
40

gpio-adapter

GPIO adapter add-on for WebThings Gateway
JavaScript
5
star
41

gateway-addon-ipc-schema

JSON-Schema for add-on IPC messages
Python
5
star
42

meross-adapter

Meross smart device adapter for WebThings Gateway
Python
4
star
43

webthing-tester

Web Thing test script
Python
4
star
44

tapo-adapter

TP-Link Tapo smart plug adapter for WebThings Gateway
Python
4
star
45

tunnelclient-rs

A Rust client library for the DNS/pagekite tunnel
Rust
4
star
46

node-mozilla-iot-gateway

gateway package for OpenWRT
Makefile
3
star
47

serial-mcu

MCU side code which talks with the serial-adapter
C++
3
star
48

registration-server-docker

Docker image for WebThingsIO/registration_server
Dockerfile
3
star
49

twilio-adapter

Simple adapter exposing the texting part of the Twilio API to the WebThings Gateway
JavaScript
3
star
50

sengled-adapter

Sengled Wi-Fi smart bulb adapter for WebThings Gateway
Python
3
star
51

wake-on-lan-adapter

Wake-on-LAN adapter for WebThings gateway.
JavaScript
3
star
52

email-sender-adapter

Simple SMTP-based email sending adapter for the WebThings Gateway
JavaScript
3
star
53

crateway

Rust
3
star
54

gateway-package-turris-omnia

WebThings gateway package for theTurris Omnia
Makefile
2
star
55

le-store-certbot

Mozilla IoT's fork of le-store-certbot
JavaScript
2
star
56

device-compat

Hardware compatibility data for WebThings Gateway
JavaScript
2
star
57

cli

Command line tools for working with things
Python
2
star
58

wot-adapter

Proxy adapter for W3C compliant WoT devices
TypeScript
2
star
59

gateway-ipc-types-rust

Rust
2
star
60

pulse-adapter

Adapter which can create pulse devices.
JavaScript
2
star
61

le-challenge-dns

Mozilla's iot fork of le-challenge-dns to issue certificates automatically
JavaScript
2
star
62

example-extension

Example extension add-on for WebThings Gateway
JavaScript
2
star
63

http-on-off-wifi101

Simple HTTP server which turns an LED on or off
C++
2
star
64

gotify-notifier

Simple notifier which uses a self-hosted Gotify server.
JavaScript
2
star
65

things-browser

Things Browser
1
star
66

webthingsio.github.io

HTML
1
star
67

webhook-events

JavaScript
1
star
68

scene-control-adapter

WebThings Gateway add-on to emulate scenes
JavaScript
1
star
69

earthquake-monitor-adapter

Earthquake monitor for WebThings Gateway
Python
1
star
70

tide-calendar-adapter

Tide calendar for WebThings Gateway
Python
1
star
71

mailchimp-proxy

Python
1
star
72

speed-test-adapter

Internet speed test adapter for WebThings Gateway
Python
1
star
73

gateway-package-docker

Docker images for creating the gateway .ipk files for OpenWRT
Dockerfile
1
star
74

example-notifier

Example notifier add-on for WebThings Gateway
JavaScript
1
star
75

eufy-adapter

Eufy smart plug/bulb adapter for WebThings Gateway
Python
1
star
76

etekcity-adapter

Etekcity smart plug/switch adapter for WebThings Gateway
Python
1
star
77

xctu-logdump

Parses an XCTU log file
JavaScript
1
star
78

gateway-aur

AUR package for running WebThings Gateway
Shell
1
star