Skip to content
Cristiano Aguzzi edited this page Sep 16, 2021 · 7 revisions

WAM tutorial

Install the WAM package as described in the README.md; after that, you are ready to create your first WoT application! This tutorial will follow same steps and code presented here by @egekorkan.

Application

We are going to build a simple thing application script that exposes one single Web Thing. The Thing will represent a thermostat that has the following affordance:

  • a property called temperature which returns the current temperature
  • an action to increment the target temperature
  • an action to decrement the target temperature
  • an event that fires when the temperature surpasses 45 C°

Before to jump straight to the code we need first to create your very first WAM project.

Initialize the project

cd yourWorkspace
wam init ./wotTutorialThermostat

After that command, WAM will ask you some questions to better configure your development environment:

choices

Answer all of them and you should get the following message:

choices

Done 🎉 your project is ready and now you can develop your application.

Developing your application

Disclaimer: The following steps consider that you are using VSCode as editor for your WoT application. Some statements might be valid also for other IDEs or editors, but it is encouraged to use VSCode to follow this tutorial

First let's develop our 'backend' side of the application: the logic that will emulate the thermostat behavior.

cd ../wotTutorialThermostat
code .

This will open VScode in your project folder. We are going to split the application into three separate files, just to show the bundling capabilities of WAM.

Create a file called thermostat.js (or thermostat.ts) inside the src folder and paste the following code:

JavaScript
class Thermostat {

    constructor(thing){
        
        this.thing = thing
        setInterval(() => {
            var curTemp = this.getTemperature();
            console.log("current temperature is ", curTemp)
            thing.writeProperty("temperature", curTemp)
            if (curTemp > 45) {
                thing.emitEvent("overheat")
            }
        }, 5000);

        // init property values
        thing.writeProperty("temperature", this.getTemperature());

        thing.setPropertyReadHandler("temperature", function () {
            return new Promise((resolve, reject) => {
                resolve(this.getTemperature());
            });
        });

        // set action handlers
        thing.setActionHandler("increment", function (value, options) {
            this.changeTemperature(logic.getTemperature() + value)
        });

        thing.setActionHandler("decrement", function (value, options) {
            this.changeTemperature(logic.getTemperature() - value)
        });
    }

    getTemperature() {
        // normally, you would call the temperature sensor's function to read the actual temperature value
        // return new Promise((resolve, reject) => {
        return Math.random() * Math.floor(50);
        // resolve(5); //uncomment to test incrementing etc.
        //  });
    }

    changeTemperature(newValue) {
        // normally, you would do physical action to change the temperature
        //do nothing
        this.thing.writeProperty("temperature", newValue);
        return;
    }
}

module.exports = Thermostat
TypeScript
import { ExposedThing } from "@node-wot/core";

export class Thermostat {
    thing: ExposedThing; 
    constructor(thing){
        
        this.thing = thing
        setInterval(() => {
            var curTemp = this.getTemperature();
            console.log("current temperature is ", curTemp)
            thing.writeProperty("temperature", curTemp)
            if (curTemp > 45) {
                thing.emitEvent("overheat")
            }
        }, 5000);
        
        // init property values
        thing.writeProperty("temperature", this.getTemperature());
        
        thing.setPropertyReadHandler("temperature", async () => {
            return this.getTemperature();
        });
        
        // set action handlers
        thing.setActionHandler("increment", async (value, options) => {
            this.changeTemperature(this.getTemperature() + value)
        });
        
        thing.setActionHandler("decrement", async (value, options) => {
            this.changeTemperature(this.getTemperature() - value)
        });
    }

    getTemperature() {
        // normally, you would call the temperature sensor's function to read the actual temperature value
        // return new Promise((resolve, reject) => {
        return Math.random() * Math.floor(50);
        // resolve(5); //uncomment to test incrementing etc.
        //  });
    }

    changeTemperature(newValue) {
        // normally, you would do physical action to change the temperature
        //do nothing
        this.thing.writeProperty("temperature", newValue);
        return;
    }
}

The code above will setup all the hooks for thing proprieties, action events. it is a convenient way to have all your Thing Application logic in one file.

Then create a file called td.js (or td.ts). We will write the skeleton of the thing description here. Copy and paste the following code:

JavaScript
module.exports = {
    title: "TemperatureController",
    description: "A Thing to control the temperature of the room and also get alerts in too high temperatures",
    properties: {
        temperature: {
            type: "integer",
            description: "Current temperature value",
            observable: true,
            readOnly: true,
            unit: "Celsius"
        }
    },
    actions: {
        increment: {
            description: "Incrementing the temperature of the room with 0 to 5 increments",
            input: {
                type: "integer",
                minimum: 0,
                maximum: 5
            }
        },
        decrement: {
            description: "Decrementing the temperature of the room with 0 to 5 increments",
            input: {
                type: "integer",
                minimum: 0,
                maximum: 5
            }
        }
    },
    events: {
        overheat: {
            description: "Alert sent when the room temperature is too high"
        }
    }
}
TypeScript
const TDbase = {
    title: "TemperatureController",
    description: "A Thing to control the temperature of the room and also get alerts in too high temperatures",
    properties: {
        temperature: {
            type: "integer",
            description: "Current temperature value",
            observable: true,
            readOnly: true,
            unit: "Celsius"
        }
    },
    actions: {
        increment: {
            description: "Incrementing the temperature of the room with 0 to 5 increments",
            input: {
                type: "integer",
                minimum: 0,
                maximum: 5
            }
        },
        decrement: {
            description: "Decrementing the temperature of the room with 0 to 5 increments",
            input: {
                type: "integer",
                minimum: 0,
                maximum: 5
            }
        }
    },
    events: {
        overheat: {
            description: "Alert sent when the room temperature is too high"
        }
    }
}

export default TDbase;

Now we are going to write the main file, where the thing gets created and exposed to possible clients. You should have already a file called thing.js (or thing.ts) in your src folder; go there and copy the following code:

JavaScript
const Thermostat = require("./thermostat")
const TDbase = require("./td")

WoT.produce(TDbase)
  .then(function (thing) {
    console.log("Produced " + thing.getThingDescription().title);
    
    const logic = new Thermostat(thing)
    thing.expose()
});
TypeScript
import { Thermostat } from "./thermostat";
import TDbase from "./td";

(async () => {
    try {

        const thing = await WoT.produce(TDbase)
        console.log("Produced " + thing.getThingDescription().title);
        const logic = new Thermostat(thing)
        thing.expose()
    } catch (err) {
        console.log(err);
    }
})();

Finally, you are ready to build and start your first WoT application! First have a look to your project folder, it should look like the following:

choices

To start your application you have simply to run the next commands in you preferred terminal:

npm run build
npm start

The former command will concatenate all your files and create a bundle file in you dist directory. The latter will run your bundle file in the default servient.

Congrats!🎉you have created your first WoT thing using WAM.

Clone this wiki locally