Skip to content

Latest commit

 

History

History
621 lines (431 loc) · 17 KB

vscp_websocket.md

File metadata and controls

621 lines (431 loc) · 17 KB

VSCP websocket

VSCP Daemon VSCP Websocket Interface

The daemon exports a HTML5 websocket interface from version 0.3.3. This interface makes it possible to have web widgets that are self contained and entirely written in JavaScript which can send and receive VSCP events. This means that you can create a simple web page, place your widgets on it and with or without a stand alone web server have a lightweight user interface. As phone, tablets and other devices generally also support HTML5. That is you have a general way for user interface creation. If you prefer apps. you can compile your interface code using phonegap or similar tools.

The websocket server can be reached on port 8080(default) just as the internal web server and will use SSL if the web server is configured to use it. The VSCP & Friends package comes with a few simple test pages.

One important design goal when this interface was designed was to create an interface that also could be implemented on low end devices which needs a user interface. With just a few commands and some simple rules we have managed to do that. This means that we can expect user interfaces interacting with both small devices and larger software units as the VSCP daemon.

If you want to test this there is a simple walkthrough. The Javascript library and samples can be found on GitHub

ws1 - String based websocket interface :id=ws1-description

VSCP websocket server security :id=websocket-security

The websocket interface is protected by a user/password pair. The username is sent a digest over the net but the password is a hash over "username:authdomain|realtext-password".

I addition to the username/password which also groups users in security levels it is possible to have table where the hosts allowed to connect to the system is stored.

In addition to this SSL can be enabled on the interface.

Also a privilege based system is used to protect critical functionality. A user need a specific privilege to send an event for example and can be set up to be allowed just to send a limited set of events. Also a filter on incoming events is possible to set up to limit what a user can receive.

There is also a privilege system for the websocket interface just as it is for the TCP/IP interface

Command Privilege Description
NOOP 0 No operation
AUTH 0 Authentication
OPEN 0 Open channel
CLOSE 0 Close channel
SETFILTER 6 Set filter
CLRQUEUE 1 Clear input queue
Send event 6 Send event

Put together this makes the VSCP Daemon one of the safest systems to use for remote maintenance of IoT/m2m systems.

You may be missing a receive event above but received events are automatically delivered asynchronously to you after a channel has been opened. Very convenient when you want to keep a graphical element updated.

VSCP Daemon Websocket Protocol Description :id=websocket-protocol-description

From version 14.0.0 there is two versions of the VSCP daemon websocket interface. ws1 which is the original implementation and ws2 which is a JSON based implementation. The same set of command are available for both.

Furthermore the variable and table handling commands has been removed. Support for this functionality will be provided in higher levels of the VSCP family of functionality.

You enable both versions by setting the enable attribute to true in the vscpd.conf configuration file.

<websockets enable="true" />

You reach the ws1 interface at

http[s]://server:port/ws1

and the ws2 interface at

http[s]://server:port/ws2

Server and port will be the same as configured as attribute to webserver. which also must be enabled for the websocket interfaces to work.

The protocol is a text based protocol that is simple and effective. Only AUTH and NOOP commands are valid in a system where the client has not been authenticated.

Packet format :id=ws1-packet-format

Message traffic on the socket is in semicolon separated text format as of below

Format for commands :id=ws1-format-commands
'C' ; command ; optional data that may be separated by additional semicolons.

Positive reply

'+' ; originator

Negative reply

'-' ; originator ; Error code ; Error in real text

Example:

-;E;Transmit buffer full

events :id=ws1-events

Both sent and received events have the same format.

'E' ; head , vscp_class , vscp_type ,obid, datetime, timestamp, GUID, data

Positive reply

'+' 

Negative reply

'-'

** Example:**

E;0,30,5,0,2000-01-01T12:33:14,0,FF:FF:FF:FF:FF:FF:FF:FE:00:26:55:CA:00:06:00:00,0x01,0x01
Code Description
C Command. Parameter is command and optional parameter(s).
+ Positive Reply. If send in response to a command the command is also returned on the form '+;command'
- Negative reply. Payload is error code followed by error message in English. '-;2;Syntax Error'
E Event. Payload is VSCP event.

Commands :id=ws1-commands

The following commands are currently available. NOOP is typically used to test if a connection is working. OPEN/CLOSE can be used to stop the stream from incoming events. Note that events still are collected at the server side and will be sent after a closed socket has been opened again. Use CLRQUEUE to clear the queue at the server before opening the stream if you don't want to receive collected events.

NOOP :id=ws1-noop

No operation. Will always give a positive response.

C;NOOP
CHALLENGE :id=ws1-challenge
C;CHALLENGE

Send this command to initiate the authentication. This is process is normally started automatically on a connect.

AUTH :id=ws1-auth

This command is used by a client to authenticate itself. When connecting to a ws1 websocket the VSCP daemon will send something like

"+;AUTH0:5a475c082c80dcdf7f2dfbd976253b24" 

as a security challenge to the client (Also sent after a CHALLENGE command has been sent to a host by a client.). The "5a475c082c80dcdf7f2dfbd976253b24" is a session id or sid that is different for every connection.

The client now should send an authentication message on the form

"C;AUTH;sid;crypto"  

for example

C;AUTH;5a475c082c80dcdf7f2dfbd976253b24;69b1180d2f4809d39be34e19c750107f

where the sid is used as a 16.byte random iv for AES-128 encryption over

"username:password"

using the vscpkey as a common secret key. If the credentials are valid the server will respond with

"+;AUTH1;userid;name;password;fullname;filtermask;rights;remotes;events;note"

and if invalid the server will respond with

"-;8,Not authorized"

Note that in addition to the credentials the server IP address must also be valid as of the configuration for this user.

Note: its is not allowed to have a username with a semicolon in the name.

The standard vscp password hash is calculated over "username:authdomain:password".

rights a bit array presented as eight bytes separated with semicolon.

OPEN :id=ws1-open

Start receiving events. Collected events in queue will be sent. Positive/negative response is returned.

Example:

“C;OPEN” 

positive response is

“+;OPEN”
CLOSE :id=ws1-close

Stop receiving events. Events are still collected in queue on server side. Positive/negative response is returned.

Example:

“C;CLOSE” 

positive response is

“+;CLOSE”
CLRQUEUE / CLRQ :id=ws1-clrq

Clear events in input queue. Positive/negative response is returned.

Example:

“C;CLRQE” 

positive response is

“+;CLRQ”

SETFILTER / SF :id=ws1-sf

Set filter/mask for incoming data. Positive/negative response is returned.

Example:

“C;SF;filter-priority, filter-class, 
    filter-type, filter-GUID;mask-priority, 
    mask-class, mask-type, mask-GUID” 

positive response is

“+;SF”

Note that there is a semicolon between filter and mask information and commas between parts of each filter and mask.

Send event :id=ws1-send-event

The same format is used to send events as they are received.

'E';head,vscp_class,vscp_type,obid,datetime,timestamp,GUID,data

and

+;EVENT

is received if it got sent and

-;EVENT;error-code;realtext-error

is returned if there was a problem sending the event.

Errors :id=ws1-error-codes

This table list the errors that currently is defined

Error code Error message
0 No error
1 Syntax error.
2 Unknown command.
3 Transmit buffer full.
4 Problem allocating memory.
5 Not authorized.
6 Not authorized to send events.
7 Not allowed to do that.
8 Parse error, invalid format.
9 Unknown type, only know "COMMAND" and "EVENT".

ws2 - JSON based websocket interface :id=ws2-description

The protocol is a JSON based protocol that is simple and effective. Only AUTH and NOOP commands are valid in a system where the client has not been authenticated.

Packet format

Message traffic on the socket is on JSON format and there are a few different objects used.

Command object :id=ws2-command-object

{
    "type" : "C|CMD|COMMAND",
    "command" : "command",
    "args" : {
        arg-pairs or "null"
    },
    "error-code" : n,
    "error-str" : "error message"
}

This is the object a client send to execute a command. The type can be set to either "C", "CMD" or "COMMAND".

command should be set to the command to execute.

args is either null if the command has no arguments or a list of argument pairs if it have arguments.

Se AUTH command below for a command with arguments and the NOOP command for a command without arguments.

Positive reply object :id=ws2-positive-reply-object

{
    "type" : "+",
    "command" : "command",
    "args" : {
        ....
    }
}

A positive reply. command tells which command the positive reply is associated with. The args are optional arguments to the reply and is null if there aree no arguments as in

{
    "type" : "+",
    "command" : "command",
    "args" : null
}

Negative reply object :id=ws2-negative-reply-object

{
    "type" : "-",
    "command" : "command",
    "errcode" : n,
    "errstr" : "error message"
}

A negative reply. command tells which command the negative reply is associated with. error-code is set to a numerical error code describing the problem and error-str is set to real text message that describe the error. Error codes are the same as for ws1 above.

VSCP event object :id=ws2-event-object

This is either an event from a client to the VSCP daemon or an event from the daemon to the client. A client sending an event object will get a positive or negative reply object in return where command is set to "EVENT"

{
    "type" : "EVENT",
    "event" :  {
       "vscpHead": 0,
       "vscpObId":  5,
       "vscpDateTime": "2020-01-27T20:47:55Z",
       "vscpTimeStamp": 3906069311,
       "vscpClass": 20,
       "vscpType": 3,
       "vscpGuid": "FF:FF:FF:FF:FF:FF:FF:F5:00:00:00:00:00:05:00:00",
       "vscpData": [15,14,13,12,11,10,9,8,7,6,5,4,3,2,0,0,1,35],
       "vscpNote": "An event note"
   }
}

Commands :id=ws2-command

AUTH :id=ws2-command-auth

The client send the AUTH command to create a session with the server. This session is active until the client disconnect from the websocket and can be over tls if needed.

Two arguments must be supplied

iv :id=ws2-commands-auth-sid crypto

When connecting to a ws2 websocket the VSCP daemon will send something like

{    
    "type" : "+",
    "command": "AUTH0", 
    "args" : [
    	"AUTH0",
        "5a475c082c80dcdf7f2dfbd976253b24"
    ]
}

as a security challenge to the client (Also sent after a CHALLENGE command has been sent to a host by a client.). The "5a475c082c80dcdf7f2dfbd976253b24" here is a session id or sid that is random and different for every connection.

crypto :id=ws2-commands-auth-crypto

The sid argument is used as a 16 byte random iv for AES-128 encryption over

"username:password"

using the vscpkey as a common secret key.

If the credentials is valid the server will respond with

{ 
    "type" : "+",  
    "command" : "AUTH",
    "args" : null  
}

The sid received form the VSCP daemon is just there for convenience for clients that have hard to to create a 128 bit random number with enough entropy. If your client can come up with a good enough value you can use that value instead.

A client that want to create a new session should send an authentication message on the form

{
    "type": "cmd",
    "command": "auth",
    "args": {
        "iv":"5a475c082c80dcdf7f2dfbd976253b24",
        "crypto":657u0"69b1180d2f4809d39be34e19c750107f"
    }
}

If the credentials are valid the response will be

{ 
    "type" : "+",  
    "command" : "AUTH",  
}

and if invalid the server will respond with

{ 
    "type" : "-",  
    "command" : "AUTH",  
    "error-code" : 8,
    "error-str" : "Not authorized"
}

The error code/message may be different depending on the cause of the negative reply. See possible error codes above.

Note that in addition to the credentials the client ip address must also be valid as of the configuration allowfrom for this user.

CHALLENGE :id=ws2-command-challenge
{
  "type" : "CMD",
  "command" : "CHALLENGE"
  "args" : null
}

The challenge command can be sent to get the session id. The response is the same as the object received when connecting to the server

{
    "type" : "+",
    "command": "CHALLENGE", 
    "args" : {
        "sid" : "3ded39018dbf0e8e4512a7cac79fd487"
    }
}
OPEN :id=ws2-command-open
{
  "type" : "CMD",
  "command" : "OPEN"
  "args" : null
}

Open the communication channel. It is now possible to send events and incoming events will be received instead of just being queued.

CLOSE :id=ws2-command-close
{
  "type" : "CMD",
  "command" : "CLOSE"
  "args" : null
}

Close the communication channel. It is no longer possible to send events after this has been done and incoming events will be queued.

SETFILTER / SF :id=ws2-command-setfilter
{
  "type" : "CMD",
  "command" : "SETFILTER"
  "args" : {
    "mask_priority" : number,
    "mask_class" : number,
    "mask_type" : number,
    "mask_guid" : "00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00",
    "filter_priority" : number,
    "filter_class" : number,
    "filter_type" : number,
    "filter_guid" : "00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00"
  }
}

Set filter/mask for the communication channel so the channel just receive the events that is of interest to the client.

The reply is either a positive or a negative reply object.

CLRQUEUE / CLRQ :id=ws2-command-clrqueue
{
  "type" : "CMD",
  "coommand" : "CLRQUEUE"
  "args" : null
}

Clear the incoming event queue for the communication channel.

The reply is either a positive or a negative reply object.

VERSION / VER :id=ws2-command-version
{
  "type" : "CMD",
  "coommand" : "VERSION"
  "args" : null
}

Get the version for the VSCP daemon.

The reply is the following object

{
  "type" : "+",
  "coommand" : "VERSION"
  "args" : {
      "version" : "major.minor.release-build"
  }
}
COPYRIGHT :id=ws2-command-copyright
{
  "type" : "CMD",
  "command" : "COPYRIGHT"
  "args" : null
}

Get copyright information.

The reply is the following object

{
  "type" : "+",
  "command" : "COPYRIGHT"
  "args" : {
      "copyright" : "copyright text"
  }
}

WS2 examples

HTML5

A simple ws2 interface connection example is here

Python

Code that issue some commands, send an event and waiting for incoming events is here

node.js

Code that issue some commands, send an event and waiting for incoming events is here

filename