Special topics for Developers


Authentication

In order to access API one need to authenticate itself. Z-Way uses sessions to authenticate users. Z-Way session is called ZWAYSession.

If remote access is used, the find.z-wave.me service will issue an additional token called ZBW_SESSID.

Please read in 13.1.4 about the token lifetime, permanent tokens and token usage guide before selecting your preferred authentication method.


Local authentication

If used in local network, Z-Way can be directly addressed via

http://IP:8083

Note that if Z-Way is used in trusted network and only Z-Wave API is supposed to be used, you might consider to skip authentication and check option Public API access in Z-Wave Binding app.

Z-Way session can be obtained by sending login and password in JSON format using POST to URL

/ZAutomation/api/v1/login
User credentials should look like {"login":"admin", "password":"admin"}.

It is also possible to use Basic Authentication to transmit login and password.

In return the session will be sent in three forms:

Example of successful login will look like:

[Successful login reply]
{
    "data": {
        "sid": "ba69cb5b-b2fd-5ce0-5b75-9bae3e8bc369",
        "id": 1,
        "role": 1,
        "name": "Administrator",
        "lang": "en",
        "color": "#dddddd",
        "dashboard": [],
        "interval": 2000,
        "rooms": [
            0
        ],
        "hide_all_device_events": false,
        "hide_system_events": false,
        "hide_single_device_events": []
    },
    "code": 200,
    "message": "200 OK",
    "error": null
}

[Wrong login/password reply]
{
    "data": null,
    "code": 401,
    "message": "401 Unauthorized",
    "error": "User login/password is wrong."
}

Once obtained, the session can be sent to the Z-Way server via the following ways:

Below are few examples of local authentication.

With cURL using cookies:

curl -H "Accept: application/json" -H "Content-Type: application/json" -X POST -d '{"form": true, "login": "admin", "password": "admin"}' http://192.168.0.62:8083/ZAutomation/api/v1/login -c cookie.txt curl http://192.168.0.62:8083/ZAutomation/api/v1/... -b cookie.txt

With cURL using Basic Authentication:

curl -u admin:admin http://192.168.0.62:8083/ZAutomation/api/v1/...

With wget using Basic Authentication:

wget –auth-no-challenge –user=admin –password=pwd 192.168.0.62:8083/ZAutomation/api/v1/...

From the browser using jQuery and Basic Authentication:

[Login with jQuery]
jQuery('img').click(function() {
    jQuery.ajax({
        url: "http://192.168.0.62:8083/ZAutomation/api/v1/...",
        beforeSend: function (xhr) { xhr.setRequestHeader ("Authorization", "Basic " + btoa("admin" + ":" + "password")); }
    });
});


Remote authentication

If not disabled by the user, Z-Way provides remote access service to the controller via

https://find.z-wave.me
See section 3.3 for more information on the Z-Way remote access service.

This service accepts Z-Way Platform ID , username and password, checks entered credentials agains your Z-Way and if accepted returns back two sessions ZWAYSession and ZBW_SESSID in two forms:

The session can be obtained by

Figure 13.1: Example of login on find.z-wave.me using Postman
Image find-login-postman

Once logged in with act=login, the user is redirected to the / of the Z-Way (in most cases it then redirects to /smarthome/). If you want the user to be redirected to some specific URL after log in add one more parameter ruri=... (see examples below).

The obtained session will be returned

To suppress the redirect use act=auth.

The credential can be used in subsequent requests in one of the three forms listed below (in order they are checked in Z-Way):

Below are examples of remote authentication.

With cURL using cookies:

curl -H "Accept: application/json" -X POST -d 'act=login&login=132339/admin&pass=admin1' https://find.z-wave.me/zboxweb -c cookie.txt curl https://find.z-wave.me/ZAutomation/api/v1/... -b cookie.txt

If you want the user to be redirected to a specific page after login, you can also use the following url:

https://find.z-wave.me/zboxweb?ruri=/expert
or
https://find.z-wave.me/zboxweb?ruri=/expert&id=123456&login=admin
to pre-fill Z-Way Platform ID and user name.


Remote authentication and access error handling

The tables below describe possible errors returned by the remote access service. Errors are order exactly as the request is handled.

Authentication on https://find.z-wave.me/zboxweb with act=login:

Condition HTTP code Redirect URL
Box not connected to the server 302
Box connected, but default login/password admin/admin is used
302
Box not connected to find.z-wave.me
502  
Box connected, but login/password is invalid 302
Box connected and authentication is successful
302
https://find.z-wave.me/

Authentication on https://find.z-wave.me/zboxweb with act=auth:

Condition HTTP code HTTP error message
Box not connected to the server 403 Forbidden
Wrong username or password
Box connected, but default login/password admin/admin is used 403 insecure_login_pass
Your (username, pass) pair is insecure
Box not connected to find.z-wave.me 502  
Box connected, but login/password is invalid 403 Forbidden
Wrong username or password
Box connected and authentication is successful 200  

Subsequent requests to https://find.z-wave.me/PATH, where PATH is not equal to zboxweb or zboxweb/*:

Condition HTTP code Redirect URL
No token (no Authorization header, no X-ZBW-SESSID header, no ZBW_SESSID cookie) 307
https://find.z-wave.me/zboxweb/r//PATH
Invalid token (incorrect or expired or revoked) 307
https://find.z-wave.me/zboxweb/r//PATH
Box not connected to find.z-wave.me 502  
Server side error 500  


Token lifetime

Each time you log in using methods described above a new session is created. This session will live for one week (might be changed on Z-Way side and on find.z-wave.me side, do not rely on this period).

Those login methods are good to obtain the token once to the access the API via token or for rare single actions. Creating a new session each time will pollute user profile in Z-Way.

Tokens can be deleted at any time in User management (4.3.1) panel. This will lead to log-out of the application that is using this token. This application will loose access to Z-Way and will require again a log in via username and password.

To use tokens long term we recommend to make them permanent. You can make any token permanent by pressing a button in User management (4.3.1). Permanent token do never expire until deleted. Only Z-Way token can be made permanent that way.

To make both find.z-wave.me and Z-Way token permanent use Authentication Bearer way to transmit tokens.

Both find.z-wave.me remote access service and Z-Way do support Authentication Bearer HTTP header. This header is commonly used in OAuth2 authentication protocol, but you can use it without OAuth2 too.

Z-Way and find.z-wave.me will automatically mark tokens as permanent if they are received in Authentication Bearer header.

The format of the header is: Authorization: Bearer ZBW_SESSID/ZWAYSession. Note that if direct access is needed (not via find.z-wave.me), ZBW_SESSID can be omitted. In this case a slash / should still preceed ZWAYSession

A typical application should take usename and password to log in via find.z-wave.me and get both ZWAYSession and ZBW_SESSID tokens to form Authentication Bearer token. The username and password should then be erased from the memory, while Authentication Bearer token should be saved for future use. It is not recommended to save user credentials.

Like other tokens user can delete the permanent token in the User management (4.3.1) panel.


OAuth2

Z-Way do also support OAuth2 authentication method to provide access to smart home devices to third party services like voice assistances (Amazon Alexa, Google Home, Yandex Alice), IFTTT and some others.

To get integrated one should provide to the Z-Wave.Me team redirect_uri and get back OAuth2 server URL, client_id and client_secret. Please contact info@z-wave.me.

To let the user authenticate and grant access to his devices you should redirect him to one of the two pages:

https://z-wave.me/oauth2/?state=...&redirect_uri=https://...&response_type=code&client_id=...
https://find.z-wave.me/zboxweb?lang=...&hide_diruris=1&ruri=/smarthome/%23/oauth2%3Fstate%3D...%26redirect_uri%3Dhttps%3A%2F%2F...%26response_type%3Dcode%26client_id%3D...

In this request:

After the user logs in to Z-Way he is asked to mark rooms and devices to be granted access to. A new user will then be created with the corresponding permissions and a session token will be generated. The session is saved on the Z-Wave.Me OAuth2 server together with an authorization code.

On the next step the user is redirected back to the service using URL

redirect_uri?state=...&code=...
In this request:

The service can now make a POST request to the Z-Wave.Me OAuth2 server on

/token
providing client_id, client_secret and code. The request can use JSON format or form data or url encoded form. The response is a JSON with access_token or error message.

The resulting access_token is to be used in the Authentication Bearer HTTP header. This token never expires unless deleted by the user.

[Request of Access token via Authorization code (JSON format)]
Content-type: application/json
{
    "client_id": "...",
    "client_secret": "...",
    "code": "..."
}

[Request of Access token via Authorization code (URL encoded form)]
Content-Type: application/x-www-form-urlencoded
client_id=...&client_secret=...&code=... (URL encoded!)

[Request of Access token via Authorization code (form data)]
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarytufRVLxOz9VdsQbA

------WebKitFormBoundarytufRVLxOz9VdsQbA
Content-Disposition: form-data; name="client_id"

...
------WebKitFormBoundarytufRVLxOz9VdsQbA
Content-Disposition: form-data; name="client_secret"

...
------WebKitFormBoundarytufRVLxOz9VdsQbA
Content-Disposition: form-data; name="code"

...
------WebKitFormBoundarytufRVLxOz9VdsQbA--

[Access token successfuly retrieved]
{
    "access_token": ".../...",
    "token_type": "bearer"
}

[Authorization code is invalid (400 Bad request)]
{
    "error": "invalid_grant"
}

[Wrong credentials (400 Bad request)]
{
    "error": "invalid_client"
}


How to write own Apps for Z-Way

According to Chapter 12.5 apps have two core files:

The following chapter explains these two files more in detail.

module.js

Module.js defines the general behavior of the app and the interface to the user side. Table 13.1 shows the structure of the file module.js with an explanation of each line item.


Table 13.1: Module.json details
{ "singleton" : false, Boolean to set if there can be multiple Instances of the module allowed or not
"dependencies": [], An array list of all module names from which this module is dependent. Modules in this list should be 'singleton'.Thew module cannot be instantiated if at least one of the modules in the list does not have an instance.
"category": "automation_basics", The app category this module is shown in the app store. Known app store categories are: 'basic_gateway_modules', 'legacy_products_workaround', 'support_external_ui', 'support_external_dev', 'automation_basic', 'device_enhancements', 'developers_stuff', 'complex_applications', 'automation', 'security', 'peripherals', 'surveillance', 'logging', 'scripting', 'scheduling', 'climate', 'environment', 'scenes', 'notifications', 'tagging'
"author": "Z-Wave.Me", Author name of the Module
"homepage": "http://razberry.z-wave.me", If you have a news homepage, it can be linked here.
"icon": "icon.png", Name of the icon which is shown for this module on the UI
"moduleName": "AppClassName", Module name have to the same like the class reference
"version": "1.0.0", Version number of this module
"maturity": "beta", Status if the app is still in development or released
"repository": { Repository optional "type": "git", Kind of the repository "source": https://github.com/ZWaveMe/homeautomation }, Address of the repository
"defaults" : { "title" : "__m_title__", The title placeholder for the Language files
"description" : { "_m_descr__" }, The description placeholder for the language files
"schema" : {}, Description of the data structure of the form for instantiating the module. See explanation of schema for details
"options" : {}} Showing options of the setup form
"description" : { "_m_descr__" }, The description placeholder for the language files


Schema

The schema is a JSON Structure to define the user interface of the module. It lists all input parameters and options to be shown in the setup dialog of the app:

[Schema Structure]
{
  "schema": {
    "type": "object",
    "properties": {
    }
  }
}

The structure of the schema is the following. Inside the 'properties' space the single 'properties' can be defined. They become the parameter of the module during the initiation and they are shown as configuration parameters in the setup dialog. There are different types of input parameters:

Primitive data types like integer, float or string

[Schema Structure Simple Type]
{
  //Parametername
  "name": {
    "type": "array",
    "items": {
      "title": "Device",
      "type": "radio",
      //array of choosable items
      "enum": ["Adult", "Child"],
      "default": "Child",
      "required": true
    }
  },
  //Parametername
  "name": {
    "type": "integer",
    "required": true
  },
}

Name Spaces - Enumerations with a choice

[Schema Structure Enumerations with a choice]
{
  //Parametername
  "name": {
    "field": "enum",
    "datasource": "namespaces",
    //special namespacedestination
    "enum": "namespaces:devices\_all:deviceId",
    "required": true
  },
}

Name spaces refer to the internal Z-Way structure. It allows to list elements from the Z-Way data model and filter it. The statement "namespaces:devices_all:deviceId" will offer a selection of all devices.

Namespaces can also be combined like

namespaces:devices_doorlock:deviceId,namespaces:devices_switchBinary:deviceId

which means devices doorlock and all binary switches. Namespaces can also be REST paths like

server:port/v1/namespaces/devices_DEVICETYPE.PATH

The file index.js

Thew file index.js contains the application as such. It can include other js files is needed but Z-Way will always look for a index.js file to load first. Table 13.2 list the basic structure of index.js with the minimum functions.


Table 13.2: Details of index.js
function AppClassName (id, controller) AppClassName.super_.call(this, id, controller); Constructor method: This line is a call of the Superconstructor. It has always to be first line of the constructor
inherits(AppClassName, AutomationModule); inheration call:
_module = AppClassName; The definition of the class reference
AppClassName.prototype.init = function (config) AppClassName.super_.prototype.init.call(this, config); var self = this; ; Initialization method: Variable to refer to in the class in own methods (this is context dependent in JavaScript). Here you can register 'listeners' for the event bus. For details on event bus please refer to chapter 12.4
AppClassName.prototype.stop = function () AppClassName.super_.prototype.stop.call(this);; Destroy method: Here you have to unregister 'listeners'.
AppClassName.prototype.Methodname= function(parameter) Own Methods: Write your own Methods here.


More information e.g. about the list of probe types etc. you find on

http://docs.zwayhomeautomation.apiary.io/


Write you own Device Description Files

This part of the manual is not yet published because the service for creating own Device Description Files is not yet available.


Extending EnOcean

How to include a new EnOcean Device (example Hoppe Door handle)

(1) Check if the profile is in /opt/z-way-server/config/Profile.xml. Not that you just need to know the profile the given product supports. There is no way to find out automatically!

[EnOcean Profile Entry]
<Profile rorg="0xf6" func="0x10" type="0x00" rorgDescription="RPS Telegram"
    funcDescription="Mechanical Handle" typeDescription="Window Handle">
  <Field offset="0" size="4" name="windowHandle" type="int" description="Movement of the window handle" short="WIN" />
</Profile>

(2) Add the device record of the device to

/opt/z-wave-server/htdocs/smarthome/storage/data/devices_encoean.json. Here the rorg, funcid and type are set. Now the device record will be created and the right values are changed on message reception. Now you need to make sure the right element is rendered and updated. This is in /opt/z-wave-server/automation/modules/Enocean/index.js

First add a filter to catch the events and call the correct function:

[Catch Device IDs]
if (matchDevice(0xf6, 0x10, 0x01)) {
  // Hoppe Window handle
  windowHandle("contact", "window", "Windor Handle");
}
now you add the function that handles the value changes and renders the element accordingly. For the window handle we use the binary sensor element but overwrite the status information according to the information of the window handle moves.

[Handle Device]
function windowHandle(dh, type, title) {
	var vDev = self.controller.devices.create({
	deviceId: vDevIdPrefix + type,
	defaults: {
		deviceType: 'sensorBinary',
		metrics: {
			probeTitle: type,
			scaleTitle: ”,
			icon: type,
			level: ”,
			title: title
		}
	},
	overlay: {},
	handler: function(command) {},
	moduleId: self.id
});

if (vDev) {
	self.dataBind(self.gateDataBinding, self.zeno, nodeId, dh, 
	function(type) {
		try {
			if (this. handleValue == 13)
				vDev.set("metrics:level", "tilt");
			if (this. handleValue == 15)
				vDev.set("metrics:level", "closed");
			if (this. handleValue == 12 || this. handleValue == 14)
				vDev.set("metrics:level", "open");
		} catch (e) {}
	}, "value");
}
}