Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add package.json #1

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,6 @@
*.exe
*.out
*.app

# Node.js modules
**/node_modules/
58 changes: 43 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,27 @@
# cluon-javascript
This project provides a minimum viable product (MVP) demonstrating how to communicate between JavaScript and [OD4Sessions](https://github.com/chalmers-revere/opendlv) using [libcluon](https://github.com/chrberger/libcluon) and hence, connecting JavaScript and C++ to exchange data bi-directionally.

[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) [![x86_64/js](https://img.shields.io/badge/js-x86_64-blue.svg)](https://hub.docker.com/r/chrberger/cluon-javascript-js-amd64/tags/) [![x86_64/cpp](https://img.shields.io/badge/cpp-x86_64-blue.svg)](https://hub.docker.com/r/chrberger/cluon-javascript-cpp-amd64/tags/) [![armhf/js](https://img.shields.io/badge/js-armhf-blue.svg)](https://hub.docker.com/r/chrberger/cluon-javascript-js-armhf/tags/) [![armhf/cpp](https://img.shields.io/badge/cpp-armhf-blue.svg)](https://hub.docker.com/r/chrberger/cluon-javascript-cpp-armhf/tags/)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)

*cluon-javascript* is the JavaScript version of [cluon](https://github.com/chrberger/libcluon), a C++ library to connect microservices with minimal overhead.
The JavaScript library is auto-compiled from the C++ version.

To install *cluon-javascript*, run:

```
npm install libcluon
```

or:

```
yarn add libcluon
```
.

## Table of Contents
* [Features](#features)
* [Dependencies](#dependencies)
* [Usage](#usage)
* [Usage example](#usage-example)
* [Building](#building)
* [License](#license)

Expand All @@ -24,28 +39,41 @@ project as it ships its dependencies as part of the source distribution:
* [libcluon](https://github.com/chrberger/libcluon) - [![License: GPLv3](https://img.shields.io/badge/license-GPL--3-blue.svg
)](https://www.gnu.org/licenses/gpl-3.0.txt)

## Usage
**Note:**: If you want to install the Node.js example we provide, some additional dependencies will be installed. However, these are dependencies of the Node.js example and not of *cluon-javascript* itself.

## Usage example
This project provides a minimum viable product (MVP) demonstrating how to communicate between JavaScript and [OD4Sessions](https://github.com/chalmers-revere/opendlv) using [libcluon](https://github.com/chrberger/libcluon) and hence, connecting JavaScript and C++ to exchange data bi-directionally.

[![x86_64/js](https://img.shields.io/badge/js-x86_64-blue.svg)](https://hub.docker.com/r/chrberger/cluon-javascript-js-amd64/tags/) [![x86_64/cpp](https://img.shields.io/badge/cpp-x86_64-blue.svg)](https://hub.docker.com/r/chrberger/cluon-javascript-cpp-amd64/tags/) [![armhf/js](https://img.shields.io/badge/js-armhf-blue.svg)](https://hub.docker.com/r/chrberger/cluon-javascript-js-armhf/tags/) [![armhf/cpp](https://img.shields.io/badge/cpp-armhf-blue.svg)](https://hub.docker.com/r/chrberger/cluon-javascript-cpp-armhf/tags/)

This microservice is provided via Docker's public registry for:
* [![x86_64/js](https://img.shields.io/badge/js-x86_64-blue.svg)](https://hub.docker.com/r/chrberger/cluon-javascript-js-amd64/tags/)
* [![x86_64/cpp](https://img.shields.io/badge/cpp-x86_64-blue.svg)](https://hub.docker.com/r/chrberger/cluon-javascript-cpp-amd64/tags/)
* [![armhf/js](https://img.shields.io/badge/js-armhf-blue.svg)](https://hub.docker.com/r/chrberger/cluon-javascript-js-armhf/tags/)
* [![armhf/cpp](https://img.shields.io/badge/cpp-armhf-blue.svg)](https://hub.docker.com/r/chrberger/cluon-javascript-cpp-armhf/tags/)

1. Running the webserver to serve the JavaScript application serving data from [OD4Session](https://github.com/chalmers-revere/opendlv) `111`:
```
docker run --rm -ti --net=host chrberger/cluon-javascript-js-amd64:latest --cid=111
```
1. Start the webserver that hosts the JavaScript front end that serves the data from [OD4Session](https://github.com/chalmers-revere/opendlv) `111`:

2. Running the C++ demo program to send data in time-triggered mode:
```
docker run --rm -ti --net=host chrberger/cluon-javascript-cpp-amd64:latest ping-pong --cid=111
```
```
docker run --rm -ti --net=host chrberger/cluon-javascript-js-amd64:latest --cid=111
```

Now, simply point your web-browser to http://localhost:8082 and open the JavaScript console to see the output.
2. Run the C++ demo program to send data in time-triggered mode:

```
docker run --rm -ti --net=host chrberger/cluon-javascript-cpp-amd64:latest ping-pong --cid=111
```

Now, simply point your web-browser to http://localhost:8082 and open the JavaScript console to see the output.

3. **Optionally**, you can also run the [Node.js](https://nodejs.org/en/) version of the application by navigating into
``nodejs-example``, installing the dependencies with ``npm install`` and running ``node index.js`` (default IP and port), or ``node index.js <ip>:<port>``, e.g. ``node index.js 192.168.99.100:8082``.
```

## Building
* Description of the [C++](https://github.com/chrberger/cluon-javascript/blob/master/cpp/README.md) part of this ping-pong application
* Description of the [JavaScript](https://github.com/chrberger/cluon-javascript/blob/master/js/README.md) part of this ping-pong application
* Description of the [C++](https://github.com/chrberger/cluon-javascript/blob/master/cpp-example/README.md) part of the ping-pong application
* Description of the [JavaScript](https://github.com/chrberger/cluon-javascript/blob/master/js-example/README.md) front end part of the ping-pong application
* Description of the [Node.js](https://github.com/chrberger/cluon-javascript/blob/master/nodejs-example/README.md) client for the ping-pong application

## License

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
3 changes: 2 additions & 1 deletion js/Dockerfile.amd64 → js-browser-example/Dockerfile.amd64
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@
FROM chalmersrevere/opendlv-ui-server-amd64:v0.0.8
MAINTAINER Christian Berger "[email protected]"

ADD . /opt/cluon-javascript-example
ADD ./js-browser-example /opt/cluon-javascript-example
ADD ./bin/libcluon.js /opt/cluon-javascript-example/libcluon.js
ENTRYPOINT ["/usr/bin/opendlv-ui-server", "--http-root=/opt/cluon-javascript-example", "--port=8082"]
3 changes: 2 additions & 1 deletion js/Dockerfile.armhf → js-browser-example/Dockerfile.armhf
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@
FROM chalmersrevere/opendlv-ui-server-armhf:v0.0.8
MAINTAINER Christian Berger "[email protected]"

ADD . /opt/cluon-javascript-example/
ADD ./js-browser-example /opt/cluon-javascript-example
ADD ./bin/libcluon.js /opt/cluon-javascript-example/libcluon.js
ENTRYPOINT ["/usr/bin/opendlv-ui-server", "--http-root=/opt/cluon-javascript-example", "--port=8082"]
File renamed without changes.
14 changes: 9 additions & 5 deletions js/README.md → js-browser-example/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# cluon-javascript-js
# cluon-javascript-js: browser
This sub-project contains the JavaScript part of the JavaScript--C++ communication demo.

## Table of Contents
Expand All @@ -15,12 +15,15 @@ to send a message from a C++ program via WebSockets to JavaScript. In a JavaScri
application, this message is received, unpacked, and responded to.

First, a recent version of [libcluon](https://github.com/chrberger/libcluon) needs
to be added; a complete list of current version is available here: https://bintray.com/chrberger/libcluon/javascript#files
to be added; a complete list of current versions is available here: https://bintray.com/chrberger/libcluon/javascript#files

```javascript
<script src="libcluon-v0.0.97.js"></script>
<script src="./libcluon.js"></script>
```

Note that you can also install the library as an npm package:
``npm install libcluon``.

Next, you need to set a handle to [libcluon](https://github.com/chrberger/libcluon)
so that you can access the built-in functions:

Expand Down Expand Up @@ -137,10 +140,11 @@ docker run --rm -ti --net=host chrberger/cluon-javascript-js-amd64:latest --cid=
Now, point your web-browser to http://localhost:8082.

## Building
To build this microservice, simply build it using Docker:
To build this microservice, simply build it using Docker, from the **root directory** of this project
(if you are in the ``js-browser-example``, cd to ``../``):

```
docker build -t javascript-example -f Dockerfile.amd64 .
build -t javascript-example -f js-browser-example/Dockerfile.amd64 .
```

Then, you can run your microservice:
Expand Down
File renamed without changes.
47 changes: 24 additions & 23 deletions js/index.html → js-browser-example/index.html
Original file line number Diff line number Diff line change
@@ -1,30 +1,31 @@
<!--
Copyright (c) 2018 Christian Berger <[email protected]>

Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
-->

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!--
Copyright (c) 2018 Christian Berger <[email protected]>

Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
-->

<!-- Load libcluon. -->
<script src="libcluon-v0.0.104.js"></script>
<script src="./libcluon.js"></script>
</head>
<body>

Expand Down
149 changes: 149 additions & 0 deletions nodejs-example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
# cluon-javascript-js: Node.js
This sub-project contains the Node.js client the JavaScript--C++ communication demo.

Start the [Node.js](https://nodejs.org/en/) version of the application by navigating into ``nodejs-example``, installing the dependencies with ``npm install`` and running:

```
node index.js
```

# Working with the example code
In this brief tutorial, you learn how to write a *libcluon* client for Node.js.

## Dependencies
Besides libcluon, the example Node.js client has the [websocket](https://www.npmjs.com/package/websocket) library as a dependency.
Set up your project with ``npm init`` and install the dependencies with ``npm install libcluon websocket --save``.

## Code
First, import all dependencies and run the ``libcluon`` initiation function:

```JavaScript
const fs = require('fs')

const libcluon = require('libcluon')
const WebSocketClient = require('websocket').w3cwebsocket
const __libcluon = libcluon()
```

Note that ``fs`` is a Node.js standard library for accessing the file system.

Then, add two helper functions for decoding and encoding base-64 ASCII strings:

```JavaScript
// Helper function to decode base-64 ASCII as String object
function atob(string) {
if (Buffer.byteLength(string) !== string.length) {
throw new Error(`bad string: ${string}`)
}
return new Buffer(string, 'base64').toString('binary')
}

// Helper function to encode String object as base-64 ASCII
function btoa(string) {
if (Buffer.byteLength(string) !== string.length) {
throw new Error(`bad string: ${string}`)
}
return Buffer(string, 'binary').toString('base64')
}
```

Note that you don't need to implement these functions when running a similar application from a web browser.

Keep the functions at the end of the file and add the following code above them.

Write an argument parser for optionally overwriting the default port and IP address the client connects to:

```JavaScript
// Set ip, port from args, else defaults
let ip, port
if (process.argv[2]) {
ip = process.argv[2].split(':')[0]
port = process.argv[2].split(':')[1]
} else {
ip = '127.0.0.1'
port = '8082'
}
```

Next, connect to the websocket server:

```JavaScript
const url = `ws://${ip}:${port}/`
console.log(`Attempting to connect to ${url}...`)
// Read data in binary from the WebSocket, channel "od4".
const client = new WebSocketClient(`ws://${ip}:${port}/`, 'od4')
```

Now you can write the websocket handlers.
Log connection errors and closures:

```JavaScript
// Log failed connection attempts
client.onerror = function(error) {
console.log('Failed to connect.')
}

// Log connection closure
client.onclose = function() {
console.log('Connection is closed.')
}
```

When opening a connection, load and set the example ``odvd`` message specification:

```JavaScript
client.onopen = function() {
console.log('Connected.')

// Load the ODVD message specification file to have information about the messages to decode and encode.
fs.readFile('../js-browser-example/example.odvd', {encoding: 'utf-8'}, (err, data) => {
err ?
console.log(err) :
console.log(`Loaded${__libcluon.setMessageSpecification(data)} messages from specification.`)
})
}
```

Finally, add a message handler that responds to all messages with the data type ``2221`` You find a detailed explanation of the message handler code in the [JavaScript browser tutorial](https://github.com/chrberger/cluon-javascript/blob/master/js/README.md):

```JavaScript
client.onmessage = function(evt) {
console.log(evt.data)
// Got new data from the WebSocket; now, try to decode it into JSON using the supplied message specification file.
const data = JSON.parse(__libcluon.decodeEnvelopeToJSON(evt.data))
console.log(data)

// Check for message ID 2221...
if (data.dataType == 2221) {
// found message. Now, extract values from the fields and do something with the data...
const number = data.example_Ping.number * 1.1

const textInBase64 = data.example_Ping.text
const textDecodedFromBase64 = atob(textInBase64)
const textReversed = textDecodedFromBase64.split('').reverse().join('')

// ...and reply with message ID 2222.
{
const replyTextInBase64 = btoa(textReversed)
const replyInJSON = `{"text":"${replyTextInBase64}","number":${number}`

// Transform JSON response into binary Protobuf-encoded data...
const MESSAGE_ID = 2222
const SENDER_STAMP = 0 // If you have multiple messages of the same type that you want to distinguish at the receiver, simply set the SENDER_STAMP to different values.
const replyInProtobuf = __libcluon.encodeEnvelopeFromJSONWithoutTimeStamps(replyInJSON, MESSAGE_ID, SENDER_STAMP)

// convert into uint8 array buffer...
strToAB = str =>
new Uint8Array(str.split('')
.map(c => c.charCodeAt(0))).buffer

// and send via the websocket.
client.send(strToAB(replyInProtobuf), { binary: true })
}
}
}
```

## Running the example code
To run the example code, follow the instructions in the project's [main README](https://github.com/chrberger/cluon-javascript).

Loading