File I/O Service (Using Node.js Module)

About Code Sample

Using this service we extend the capabilities of a web app by taking advantage of the File IO features of Node.js. This service contains methods for creating a file, writing to a file, reading a file and deleting a file.

Creating a Project

You can create a new project with this command, using SDK command line tools. 

ares-generate app

 

Without using the -t option, the default bootplate-moonstone template is used. Also, we used "app" for app directory name for which any name can be used.

See Using webOS TV CLI for information on CLI commands used in this guide such as ares-generate, ares-package, ares-install, and ares-launch.

 

You now have a skeleton project on which to build the HelloWorld App and Service from.

Writing an App

We now have a skeleton project on which to build the HelloWorld app and service from. Before you start writing an app, open appinfo.json and specify the app name at "id:" field. In this code sample, I set it to com.mycompany.fileioservice.

 

First, we will create the app to call the service with. Using your favorite editor open the source/views/views.js file and replace the code with the code below.

The enyo.LunaService kind is provided by the enyo-webos library (which is included in the bootplate-moonstone template) and is what you use to call webOS services. By default, the enyo-webos library is commented out of the source/package.js. You should modify the package.js file to use the enyo-webos library.

// FileIOService Enyo kind
// An Enyo kind to make calls to our custom service easier
enyo.kind ({
    name: "FileIOService",
    kind: "enyo.LunaService",
    service: "luna://com.mycompany.app.fileioservice.service/"
});

// Our app's main view
enyo.kind({
	name: "myapp.MainView",
	kind: "moon.Panels",
	classes: "moon enyo-fit main-view",
	pattern:"activity",
	components: [
		{kind: "moon.Panel", title: "Read/Write with Node Service", components: [
            {
                name: "FileIOWriteService",
                kind: "FileIOService",
                method: "write",
                onComplete: "writeServiceResponse"
            },
            {
                name: "FileIOReadService",
                kind: "FileIOService",
                method: "read",
                onComplete: "readServiceResponse"
            },
            {
                name: "FileIODeleteService",
                kind: "FileIOService",
                method: "delete",
                onComplete: "deleteServiceResponse"
            },
            {
                name: "FileIOWatchService",
                kind: "FileIOService",
                method: "fileWatch",
                subscribe: true,
                onComplete: "watchServiceResponse"
            },
            {kind: 'moon.Scroller', fit: true, components: [
                {classes: "moon-button-sample-wrapper", components: [
                    {name: "CallWriteServiceButton", kind: "moon.Button", content: "Call 'write' service", ontap: "writeButtonTapped"},
                    {kind: "moon.Input", name:"nameInput",placeholder: "Enter your name"},
                    {kind: "moon.BodyText", name: "writeResult", allowHtml: true, content: "Button not pressed yet."}

                ]},
                {classes: "moon-button-sample-wrapper", components: [
                    {name: "CallReadServiceButton", kind: "moon.Button", content: "Call 'read' service", ontap: "readButtonTapped"},
                    {kind: "moon.BodyText", name: "readResult", allowHtml: true, content: "Button not pressed yet."}

                ]},
                {classes: "moon-button-sample-wrapper", components: [
                    {name: "CallDeleteServiceButton", kind: "moon.Button", content: "Call 'delete' service", ontap: "deleteButtonTapped"},
                    {kind: "moon.BodyText", name: "deleteResult", allowHtml: true, content: "Button not pressed yet."}

                ]},
                {classes: "moon-button-sample-wrapper", components: [
                    {kind: "moon.BodyText", name: "watchResult", allowHtml: true, content: ""}
                ]}
            ]}
        ]}
	],

    create: function() {
        this.inherited(arguments);
        // Start the FileIOWatchService when the app is created
        this.$.FileIOWatchService.send({});
        this.$.watchResult.setContent("Registered fileWatch service.")
    },

    writeButtonTapped: function(inSender, inEvent) {
        this.$.writeResult.setContent("Calling write service with : " + this.$.nameInput.getValue());
        this.$.FileIOWriteService.send({name:this.$.nameInput.getValue()});
    },

    readButtonTapped: function(inSender, inEvent) {
        this.$.readResult.setContent("Calling read service.");
        this.$.FileIOReadService.send({});
    },

    deleteButtonTapped: function(inSender, inEvent) {
        this.$.deleteResult.setContent("Calling delete service.");
        this.$.FileIODeleteService.send({});
    },

    writeServiceResponse: function(inSender, inResponse){
        if (inResponse.returnValue)
            this.$.writeResult.setContent("Service response: " + inResponse.response);
        else
            this.$.writeResult.setContent("Service error :" + inResponse.errorText);
    },

    readServiceResponse: function(inSender, inResponse){
        if (inResponse.returnValue)
            this.$.readResult.setContent("Service response: " + inResponse.response);
        else
            this.$.readResult.setContent("Service error: " + inResponse.errorText);
    },

    watchServiceResponse: function(inSender, inResponse){
        if (inResponse.returnValue) {
            this.count++;
            this.$.watchResult.setContent(this.count + ") fileWatch service response: " + inResponse.response + "
" + this.$.watchResult.getContent());
        }
        else
            this.$.watchResult.setContent("Service error");
    },

    deleteServiceResponse: function(inSender, inResponse){
        if (inResponse.returnValue)
            this.$.deleteResult.setContent("Service response: " + inResponse.response);
        else
            this.$.deleteResult.setContent("Service error: " + inResponse.errorText);
    }
});

Writing a Service

Now create a service to an application at a separate directoryCreate a new folder called service. You can use any name for service folder. A service is made up of three files, which we will add in order. First create a new file called FileIOService.js containing the following code.

// File I/O Service
// A webOS service sample using Node fs library functions

var Service = require('webos-service');
var service = new Service("com.mycompany.app.fileioservice.service");

var fs = require('fs');

// Register the "write" service call which writes a text string to "message.txt"
service.register("write", function(message) {

    fs.writeFile('message.txt', 'Hello ' + message.payload.name, function (err) {
        if (err) {
            message.respond({
                returnValue: false,
                errorCode: 1,
                errorText: err.message
            });
        } else {
            message.respond({
                response: "Hello " + message.payload.name + " written to message.txt.",
                returnValue: true
            });
        }
    });
});

// Register the "read" service call which returns the contents of "message.txt"
service.register("read", function(message) {

    fs.readFile('message.txt', function (err, messageData) {

        if (err) {
            message.respond({
                returnValue: false,
                errorCode: 1,
                errorText: err.message
            });
        }
        else {
            message.respond({
                response: messageData.toString(),
                returnValue: true
            });
        }
    });
});

// Register the "fileWatch" service call which reports changes to "message.txt"
service.register("fileWatch", function(message) {

    fs.watch('message.txt', function (event, filename) {

        message.respond({
            response: event + " " + filename,
            returnValue: true
        });
    });
});

// Register the "delete" service call which deletes the "message.txt" file
service.register("delete", function(message) {

    // fs.unlink() is how Node deletes files
    fs.unlink('message.txt', function (err) {

        if (err) {
            message.respond({
                returnValue: false,
                errorCode: 1,
                errorText: err.message
            });
        } else {
            message.respond({
                response: "File message.txt deleted",
                returnValue: true
            });
        }
    });
});

 

In the same folder, create another file called services.json and insert the following code. This file defines our service and the methods available to be call on that service.

{
    "id": "com.mycompany.app.fileioservice.service",
    "description": "Sample file I/O service",
    "services": [
        {
            "name": "com.mycompany.app.fileioservice.service",
            "description": "Sample file I/O service",
            "commands": [
                {
                    "name": "write",
                    "description": "Write text with the parameter passed in to message.txt"
                },
                {
                    "name": "read",
                    "description": "Read text from message.txt"
                },
                {
                    "name": "delete",
                    "description": "Delete message.txt"
                },
                {
                    "name": "fileWatch",
                    "description": "Watch for changes to message.txt"
                }
            ]
        }
    ]
}

 

Finally, create a new file called package.json and insert the following code.

{
    "name": "com.mycompany.app.fileioservice.service",
    "main": "FileIOService.js"
}

Packaging the App

We are now ready to package our app and test it out on the emulator or device. Create the package with SDK command line tools using 

ares-package app service

Installing and Launching the App

You can test the JS service app on emulator only. If you test the JS service app with USB on webOS TV using App Test, the JS service does not work properly.

 

Install the package on emulator using

ares-install com.mycompany.app.fileioservice_0.0.1_all.ipk

 

Finally, run the app using

ares-launch com.mycompany.app.fileioservice

 

Once the app is running, enter any text in the text box, then click Call 'Write' Service button. The app will call the service with the text enter as a parameter and return the response. Also, try Call 'Read' Service and Call 'Delete' Service buttons.

fileio.png

Sample App Source Code

To download the source code for this sample app and service, click here.

Do's and Don'ts

  • DO start service method names with a lower-case letter
  • DO set "errorText" and "errorCode" properties in the response only if an error occurs
  • DON'T expect this to work in a browser.

 

Navigation