Developing Web Things with Python, Client. js, and Java

The Mozilla IoT team lately released the Things Framework , which allows you to build IoT gadgets that speak the Web Matter API . Last week, James constructed an ESP8266 web thing . This time, I’ m going to demonstrate how to build web things with Python, Node. js, or Java. These types of languages are definitely not optimal just for small embedded devices; this guide is intended for higher-end devices that may run these languages with ease, as well as your own desktop computer.

To show, we’ ll be turning the particular Music Player Daemon (MPD) into a web thing. The your local library we’ ll be using here are webthing-python , webthing-node , and webthing-java .

Intro towards the Music Player Daemon (MPD)

The Music Player Daemon is an open-source music player that has been about since 2003. MPD operates in the client/server model, and is controllable more than TCP with a simple text-based process. I won’ t cover set up here, but MPD can be set up via your package manager upon Linux, Homebrew on Mac OPERATING SYSTEM X, or with binaries upon Windows .

Several Quick Notes

Even though this example is written just for MPD, it would be easily portable to music players with an API, or perhaps you could build your own player employing this example as a base. More importantly, this particular example is primarily meant to show the Things Framework, which can be used to develop an endless variety of web things.

The Python, Node. js, and Java web thing your local library all have essentially the same API. While they may not be entirely idiomatic for respective languages, doing this allows us to preserve all the libraries more easily, which is extremely valuable while the Web Thing API is still a living draft.

Getting Started

To start, initialize an empty project for your language of preference. For example , you might create a new task in IntelliJ IDEA for Java, or run npm init to start a new Node. js task. You’ ll then want to include the webthing library as an addiction. Instructions for doing so can be found for the respective Github project page, you can also look here .

Now we’ re ready to compose some code. Essentially we’ lmost all do the following:

  1. Create a Thing .
    1. Define its qualities.
    2. Define its activities.
    3. Define its occasions.
  2. Connect the Thing to a WebThingServer .

Produce a Thing

First off, let’ s import our library of preference.

Python

 from webthing import Action, Event, Property, Issue, Value, WebThingServer 
 

JavaScript

 const 
  Action,
  Event,
  Property,
  Thing,
  Value,
  WebThingServer,
 = require('webthing'); 
 

Java

 import org. mozilla. iot. webthing. Action;
transfer org. mozilla. iot. webthing. Occasion;
import org. mozilla. iot. webthing. Property;
import org. mozilla. iot. webthing. Thing;
import org. mozilla. iot. webthing. Value;
import org. mozilla. iot. webthing. WebThingServer; 
 

Now, we’ ll create a basic subclass associated with Thing .

Python

 class MPDThing(Thing):
def __init__(self):
Thing. __init__(self, 'MPD', 'musicPlayer', 'Music Player Daemon') 
 

JavaScript

 class MPDThing stretches Thing 
  constructor() 
    super('MPD', 'musicPlayer', 'Music Player Daemon');
  
 
 

Java

 public class MPDThing extends Point 
    public MPDThing() 
        super("MPD", "musicPlayer", "Music Player Daemon");
    
 
 

Add Properties

Since we have our MPDThing , we’ ll need to then add properties to it. Obviously, a very good music player will have quite a few properties. To demonstrate, I am going to show you how to add one, plus I’ ll link to the rest of the program code at the end of this post.

To include a property, you can do the following inside the MPDThing constructor.

Python

 position = self. get_status()
self. add_property(
Property(self,
'volume',
Value(self. get_volume(status), personal. set_volume),
 metadata= 
                 'type': 'number',
                 'description': 'Playback volume',
                 'minimum': 0,
                 'maximum': 100,
              )) 
 

JavaScript

 this. getStatus(). then((status) => 
  this.getVolume(status).then((v) => 
    this.addProperty(
      new Property(this,
                   'volume',
                   new Value(v, this.setVolume.bind(this)),
                   
                     type: 'number',
                     description: 'Playback volume',
                     minimum: 0,
                     maximum: 100,
                   ));
  );
 ); 
 

Coffee

 ServerStatus status = this particular. client. getServerStatus();
Map< String, Object> volumeMetadata = new HashMap< > ();
volumeMetadata. put("type", "number");
volumeMetadata. put("description", "Playback volume");
volumeMetadata. put("minimum", 0);
volumeMetadata. put("maximum", 100);
this particular. volumeValue =
new Value(status. getVolume(), v -> this. setVolume((int)v));
this particular. addProperty(new Property(this,
"volume",
this. volumeValue,
volumeMetadata)); 
 

We’ ve now created a Property which allows us to GET and PUT the play-back volume. The Worth piece is an item that essentially stores a cached value and a “ value forwarder” callback. When the volume is set with a PUT request, the value forwarder can be used to forward the new value towards the actual device, which in this situation is the MPD server. We’ ve also set up some metadata for your property, including a description, worth type, and a minimum and optimum value.

Add Activities

A music player may also have a lot of actions. While the MPD web thing has several simple actions like play, pause, plus skip, I’ ve added one which takes some additional input, that will queue a series of random songs. Actions inputs are verified with a JSON Schema validator .

First, let’ s create a good Action subclass.

Python

 class QueueRandomAction(Action):
def __init__(self, issue, input_):
Action. __init__(
self, uuid. uuid4(). hex, thing, 'queueRandom', input_=input_)

def perform_action(self):
songs = personal. thing. list()
if songs:
meant for _ in range(0, int(self. insight['count'])):
self. thing. add(random. choice(songs))

playlist = self. matter. get_playlist()
if playlist is not Not one:
self. thing. add_event(
PlaylistUpdatedEvent(self. factor, playlist)) 
 

JavaScript

 course QueueRandomAction extends Action 
  constructor(thing, input) 
    super(uuidv4(), thing, 'queueRandom', input);
  

  performAction() 
    return this.thing.list().then((songs) => 
      const promises =  [] ;

      if (songs) 
        for (let i = 0; i < this.input.count; ++i) 
          const uri = songs [Math.floor(Math.random() * songs.length)] .file;
          promises.push(this.thing.add(uri));
        

        promises.push(this.thing.getPlaylist().then((playlist) => 
          if (playlist) 
            this.thing.addEvent(new PlaylistUpdatedEvent(this.thing, playlist));
          
        ));
      

      return Promise.all(promises);
    );
  
 
 

Java

 public static course QueueRandomAction extends Action 
    public QueueRandomAction(Thing thing, JSONObject input) 
        super(UUID.randomUUID().toString(), thing, "queueRandom", input);
    

    @Override
    public void performAction() 
        MPDThing thing = (MPDThing)this.getThing();
        Random random = new Random();
        List<MPDFile> songs = thing.list();

        for (int i = 0; i < this.getInput().getInt("count"); ++i) 
            MPDFile file = songs.get(random.nextInt(songs.size()));
            thing.add(file);
        

        String playlist = thing.getPlaylist();
        thing.addEvent(new PlaylistUpdatedEvent(thing, playlist));
    
 
 

QueueRandomAction takes an insight, count , lines that number of random songs to the present playlist, and then emits a PlaylistUpdatedEvent (to be defined shortly). To add this particular new action to our MPDThing , do the following within the MPDThing constructor:

Python

 self. add_available_action(
'queueRandom',
'description': 'Queue a series of random songs',
     'input': 
         'type': 'object',
         'required':  [
             'count',
         ] ,
         'properties': 
             'count': 
                 'type': 'number',
                 'minimum': 1,
             ,
         ,
     ,
 QueueRandomAction) 
 

JavaScript

 this. addAvailableAction(
'queueRandom',

    description: 'Queue a series of random songs',
    input: 
      type: 'object',
      required:  [
        'count',
      ] ,
      properties: 
        count: 
          type: 'number',
          minimum: 1,
        ,
      ,
    ,
  ,
QueueRandomAction); 
 

Coffee

 Map< String, Object> queueRandomMetadata = new HashMap< > ();
queueRandomMetadata. put("description",
"Queue a series of unique songs");
Map< String, Object> queueRandomInputMetadata = new HashMap< < > ();
queueRandomInputMetadata. put("type", "object");
queueRandomInputMetadata. put("required", new String[]"count" );
Map< String, Object> queueRandomInputPropertiesMetadata =
new HashMap< > ();
Map< String, Object> queueRandomInputPropertiesCountMetadata sama dengan
new HashedMap();
queueRandomInputPropertiesCountMetadata. put("type", "number");
queueRandomInputPropertiesCountMetadata. put("minimum", 1);
queueRandomInputPropertiesMetadata. put("count",
queueRandomInputPropertiesCountMetadata);
queueRandomInputMetadata. put("properties",
queueRandomInputPropertiesMetadata);
queueRandomMetadata. put("input", queueRandomInputMetadata);
this. addAvailableAction("queueRandom",
queueRandomMetadata,
QueueRandomAction. class); 
 

Add Events

The final piece of our Thing is the events. Since MPD is a client/server model, it can be updated externally simply by any number of other clients. As such, We created an event that will fire once the current playlist is updated.

As with Factor and Action , we’ ll develop an Event subclass.

Python

 class PlaylistUpdatedEvent(Event):
def __init__(self, thing, data):
Event. __init__(self, factor, 'playlistUpdated', data=data) 
 

JavaScript

 class PlaylistUpdatedEvent extends Event 
  constructor(thing, data) 
    super(thing, 'playlistUpdated', data);
  
 
 

Java

 public stationary class PlaylistUpdatedEvent extends Event 
    public PlaylistUpdatedEvent(Thing thing, String data) 
        super(thing, "playlistUpdated", data);
    
 
 

It is a basic Event . The data member will be filled along with a string representation of the present playlist.

To add this particular Event to our thing, we’ ll the actual following in the MPDThing constructor:

Python

 self. add_available_event(
'playlistUpdated',
 'description': 'The current playlist has been updated',
     'type': 'string' ) 
 

JavaScript

 this. addAvailableEvent(
'playlistUpdated',

    description: 'The current playlist has been updated',
    type: 'string',
   ); 
 

Java

 Map< Chain, Object> playlistUpdatedMetadata = new HashMap< > ();
playlistUpdatedMetadata. put("description",
"The current playlist has been updated");
playlistUpdatedMetadata. put("type", "string");
this. addAvailableEvent("playlistUpdated", playlistUpdatedMetadata); 
 

Produce a WebThingServer

Now that we now have a thing with properties, actions, plus events, we’ ll create a WebThingServer plus attach the MPDThing to it.

Python

  thing = MPDThing()

server = WebThingServer([thing], port=8888)

try:
server. start()
except KeyboardInterrupt:
server. stop() 
 

JavaScript

 const thing = new MPDThing();

const server = new WebThingServer([thing], null, 8888);

process. on('SIGINT', () => 
  server.stop();
  process.exit();
 );

machine. start(); 
 

Java

 MPDThing thing = new MPDThing();

List< Thing> things = new ArrayList< > ();
things. add(thing);

test 
    WebThingServer server = new WebThingServer(things, null, 8888);

    Runtime.getRuntime()
           .addShutdownHook(new Thread(() -> server.stop()));

    server.start(false);
 catch (IOException e) 
    System.out.println(e);
    System.exit(1);
 
 

Managing the Web Thing

The web thing is complete plus it’ s now controllable with the Web Thing API. Here’ s i9000 how to add it to the Elements Gateway :

The Things Gateway doesn’ t currently provide a way to make use of actions or display events, yet those are in the works.

Alternatively, you can control the internet thing via cURL or any additional HTTP library you choose:

Shell

  $ curl 
 -X POST http://127.0.0.1:8888/actions 
-H 'Content-Type: application/json' 
 -d ' "play": ' 
 

Wrapping Up

Your own imagination is really your only restrict as to what you can turn into a web matter. If you’ d like to view the rest of this example and how the particular MPD controls are implemented, all the code is available on Github .

If you have any queries or suggestions, you can head over to Talk or find all of us in #iot on irc. mozilla. org . Additionally , feel free to create problems, or even better, submit pull requests, towards the webthing library repositories!

Erina is a software engineer at Mozilla working on Project Things.

More posts by Michael Stegeman…

If you liked Developing Web Things with Python, Client. js, and Java by Michael Stegeman Then you'll love Web Design Agency Miami

Add a Comment

Your email address will not be published. Required fields are marked *

Shares