Giter VIP home page Giter VIP logo

knot-fog-connector's Introduction

KNoT Fog connector service

This is a KNoT Gateway service that connects the fog to a cloud service.

Supported services

Quickstart

$ npm install
$ npm run build
$ npm start

Development Environment Setup

In order to test changes made to the supported services, one must setup a development environment and run required services locally. Let it be noted, though, that changes should also be properly tested directly on KNoT Gateway.

Prerequisites

knot-fog-connector requires rabbitMQ to be running. The default access ip and port for RabbitMQ are localhost:5672.

Configuration

Configuration is made via a JSON file placed into knot-fog-connector/config/ folder (see config package documentation for more information). Find below, the parameters for such file.

  • fog Object Fog service parameters.
  • cloudType String cloud provider name. Currently, only KNOT_CLOUD or FIWARE are supported options.
  • cloud Object CloudType specific parameters (see below).

Fog

  • fog Object fog parameters
    • token String User access token.
    • hostname String AMQP broker hostname.
    • port Number AMQP broker port.
    • username String AMQP broker username.
    • password String AMQP broker password.
{
  "fog": {
    "token": "<knot-fog-user-token>",
    "hostname": "localhost",
    "port": 5672,
    "username": "knot",
    "password": "knot"
  }
}

KNoT-Cloud

NOTE: The KNoT Cloud is an extended version of the currently supported fog solution and for that reason, their configuration looks similar. However, it's important to notice the cloud instance should be running with its own message broker instance.

  • cloud Object cloud parameters
    • amqp Object AMQP Broker parameters
      • token String User access token.
      • hostname String Broker hostname.
      • port Number Broker port.
      • username String Broker username.
      • password String Broker password.
    • http Object HTTP Server parameters
      • hostname String Server hostname.
      • port Number Server port.
      • protocol String Server protocol (HTTP|HTTPS).
{
  "cloudType": "KNOT_CLOUD",
  "cloud": {
    "amqp": {
      "token": "<knot-cloud-user-token>",
      "hostname": "broker.knot.cloud",
      "port": 5672,
      "username": "knot",
      "password": "knot"
    },
    "http": {
      "hostname": "api.knot.cloud",
      "port": "443",
      "protocol": "https"
    }
  }
}

FIWARE

  • cloud Object cloud parameters
    • iota Object object with hostname and port parameters
      • hostname String
      • port Number
    • orion Object object with hostname and port parameters
      • hostname String
      • port Number
{
  "cloudType": "FIWARE",
  "cloud": {
    "iota": {
      "hostname": "localhost",
      "port": 4041
    },
    "orion": {
      "hostname": "localhost",
      "port": 1026
    }
  }
}

Creating a connector

A connector is as a library that exports by default the Connector class. This service will use the library as follows:

import CustomCloudConnector from '@cesarbr/knot-fog-connector-customcloud';

...
const connector = new CustomCloudConnector(config);
await connector.start();

Methods

constructor(config)

Create the connector using a configuration object that will be loaded from a JSON file and passed directly to this constructor. No work, such as connecting to a service, must be done in this constructor.

Arguments
  • config Object configuration parameters defined by the connector
Example
import CustomCloudConnector from '@cesarbr/knot-fog-connector-customcloud';

const connector = new CustomCloudConnector({
  hostname: 'localhost',
  port: 3000,
  ...,
});

start(): Promise<Void>

Start the connector. This is the method where initialization procedures, such as connecting to external services, must be done.

Example
import CustomCloudConnector from '@cesarbr/knot-fog-connector-customcloud';

const connector = new CustomCloudConnector({ ... });
await connector.start();

addDevice(device): Promise<Void>

Add a device to the cloud. Called when a new device is added to the fog.

Arguments
  • device Object device specification containing the following properties:
    • id String device ID (KNoT ID)
    • name String device name
Result
  • device Object device registered on the cloud.
    • id String device ID (KNoT ID)
    • token String device token
Example
await connector.start();
await connector.addDevice({
  id: '918f2e0f4e19f990',
  name: 'Front door',
});

// {
//   id: '918f2e0f4e19f990',
//   token: '5b67ce6bef21701331152d6297e1bd2b22f91787'
// }

removeDevice(id): Promise<Void>

Remove a device from the cloud. Called when a device is removed from the fog.

Arguments
  • id String device ID (KNoT ID)
Example
await connector.start();
await connector.removeDevice('918f2e0f4e19f990');

authDevice(id, token): Promise<Boolean>

Authenticate a device on the cloud. Called when it's necessary to verify if a device is valid on the cloud provider.

Arguments
  • id String device ID (KNoT ID)
  • token String device token
Result
  • status Boolean response that represents the authentication status (true/false).
Example
await connector.start();
const status = await connector.authDevice(
  '918f2e0f4e19f990',
  '0c20c12e2ac058d0513d81dc58e33b2f9ff8c83d'
);
console.log(status);

// true

listDevices(): Promise<Object>

List the devices registered on the cloud for the current gateway.

Result
  • devices Array devices registered on the cloud or an empty array. Each device is an object in the following format:
    • id String device ID (KNoT ID)
    • name String device name
    • config Array config items, as specified in updateConfig()
Example
await connector.start();
const devices = await connector.listDevices();
console.log(devices);

// [
//   { id: '918f2e0f4e19f990', name: 'Front door', schema: [{ sensorId: 1, ... }, ...] },
//   { id: '918f2e0f4e19f990', name: 'Back door', schema: [{ sensorId: 1, ... }, ...] }
// ]

publishData(id, data): Promise<Void>

Publish data as a device. Called when a device publishes data on the fog.

Arguments
  • id String device ID (KNoT ID)
  • data Array data items to be published, each one formed by:
    • sensorId Number sensor ID
    • value Number|Boolean|String sensor value
Example
await connector.start();
await connector.publishData('918f2e0f4e19f990', [
  {
    sensorId: 1,
    value: false,
  },
  {
    sensorId: 2,
    value: 1000,
  },
]);

updateConfig(id, config): Promise<Void>

Update the device config. Called when a device updates its config on the fog.

Arguments
  • id String device ID (KNoT ID)
  • config Array config items, each one formed by:
    • sensorId Number sensor ID
    • schema JSON Object schema item, formed by:
      • typeId Number semantic value type (voltage, current, temperature, etc)
      • unit Number sensor unit (V, A, W, etc)
      • valueType Number data value type (boolean, integer, etc)
      • name String sensor name
    • event JSON Object - Optional event item, formed by:
      • change Boolean enable sending sensor data when its value changes
      • timeSec Number - Optional time interval in seconds that indicates when data must be sent to the cloud
      • lowerThreshold (Depends on schema's valueType) - Optional send data to the cloud if it's lower than this threshold
      • upperThreshold (Depends on schema's valueType) - Optional send data to the cloud if it's upper than this threshold

Refer to the protocol for more information on the possible values for each field.

NOTE: config will always contain the whole config and not a difference from a last update.

Example
await connector.start();
await connector.updateConfig('918f2e0f4e19f990', [
  {
    sensorId: 1,
    schema: {
        typeId: 0xFFF1,
        unit: 0,
        valueType: 3,
        name: "Door lock"
      },
      event: {
        change: true,
        timeSec: 10,
        lowerThreshold: 1000,
        upperThreshold: 3000
      }
  },
  {
    sensorId: 2,
    ...
  }
]);

onDataRequested(cb): Promise<Void>

Register a callback to handle data requests from the cloud. Called when a cloud application requests the last value of a device's sensor.

Arguments
  • cb Function event handler defined as cb(id, sensorId) where:
    • id Number device ID (KNoT ID)
    • sensorIds Array IDs of the sensor to send last value (Number)
Example
await connector.start();
await connector.onDataRequested((id, sensorIds) => {
  console.log(
    `New data from '${sensorIds}' on device '${id}' is being requested`
  );
});

// New data from '1,2' on device '918f2e0f4e19f990' is being requested

onDataUpdated(cb): Promise<Void>

Register a callback to handle data updates from the cloud. Called when a cloud application requests to update a device's actuator.

Arguments
  • cb Function event handler defined as cb(id, data) where:
    • id Number device ID (KNoT ID)
    • data Array updates for sensors/actuators, each one formed by:
      • sensorId Number ID of the sensor to update
      • data Number|Boolean|String data to be written
Example
await connector.start();
await connector.onDataUpdated((id, sensorId, data) => {
  console.log(`Update actuator '${sensorId}' on device '${id}' to ${data}`);
});

// Update actuator '2' on device '918f2e0f4e19f990' to 1000

onDeviceUnregistered(cb): Promise<Void>

Register a callback to handle devices removed from the cloud. Called when a cloud removes a device.

Arguments
  • cb Function event handler defined as cb(id) where:
    • id Number device ID (KNoT ID)
Example
await connector.start();
await connector.onDeviceUnregistered((id) => {
  console.log(`Device '${id}' removed`);
});

// Device '2' removed

onDisconnected(cb): Promise<Void>

Register a callback to handle gateway disconnection.

Arguments
  • cb Function event handler.
Example
await connector.start();
await connector.onDisconnected(() => {
  console.log('Disconnected');
});

// Disconnected

onReconnected(cb): Promise<Void>

Register a callback to handle gateway reconnection.

Arguments
  • cb Function event handler.
Example
await connector.start();
await connector.onReconnected(() => {
  console.log('Reconnected');
});

// Reconnected

knot-fog-connector's People

Contributors

arthurcrs avatar esdrasjnr avatar figueredo avatar lcbm avatar lcc avatar pauloserrafh avatar ramonhpr avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

knot-fog-connector's Issues

Update production logging configuration to enable syslog

In order to improve debugging when running the connector in a production environment (such as Raspberry Pi X devices), we should send the service's logs to the system log.

To accomplish that, the config/production.json file should be updated to include the necessary configuration based on the config/default.json file, enabling the syslog option.

Invalid events are remaining in the message queue

The invalid messages should be removed from the message queue since it won't be used. This is causing the log to get dirty and the message queue to use memory unnecessarily.

(node:31382) UnhandledPromiseRejectionWarning: Error: Unknown event type cloud.device.auth
    at MessageHandler.getHandler (/Users/jneto/workspace/knot/gw/knot-fog-connector/src/network/MessageHandler.js:51:13)
    at MessageHandler.getHandler [as handleMessage] (/Users/jneto/workspace/knot/gw/knot-fog-connector/src/network/MessageHandler.js:70:26)
    at Channel.BaseChannel.dispatchMessage (/Users/jneto/workspace/knot/gw/knot-fog-connector/node_modules/amqplib/lib/channel.js:484:12)
    at Channel.BaseChannel.handleDelivery (/Users/jneto/workspace/knot/gw/knot-fog-connector/node_modules/amqplib/lib/channel.js:493:15)
    at Channel.emit (events.js:198:13)
    at /Users/jneto/workspace/knot/gw/knot-fog-connector/node_modules/amqplib/lib/channel.js:279:10
    at Channel.content (/Users/jneto/workspace/knot/gw/knot-fog-connector/node_modules/amqplib/lib/channel.js:332:9)
    at Channel.C.acceptMessageFrame (/Users/jneto/workspace/knot/gw/knot-fog-connector/node_modules/amqplib/lib/channel.js:247:31)
    at Channel.C.accept (/Users/jneto/workspace/knot/gw/knot-fog-connector/node_modules/amqplib/lib/channel.js:400:17)
    at Connection.mainAccept [as accept] (/Users/jneto/workspace/knot/gw/knot-fog-connector/node_modules/amqplib/lib/connection.js:64:33)
    at Socket.go (/Users/jneto/workspace/knot/gw/knot-fog-connector/node_modules/amqplib/lib/connection.js:478:48)
    at Socket.emit (events.js:198:13)
    at emitReadable_ (_stream_readable.js:539:12)
    at process._tickCallback (internal/process/next_tick.js:63:19)
(node:31382) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:31382) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Document connector AMQP API

As a platform developer, I want to know the events and data formats I need to send to connector via RabbitMQ when updating devices or publishing data. Besides, I also want to know which events are expected from connector.

DoD:

  • Add device.register
  • Add device.unregister
  • Add schema.update
  • Add data.publish
  • Add data.update
  • Add data.request

Not registering devices to the cloud after a while

Occurred once

New devices are registered to the fog and appear on the gateway control screen (knot.local). But are not being registered to the cloud after some time running.

I suspect that adding multiple devices to the gateway may help at reproducing it.

Improve connector configuration

As a platform developer, I want to have a better way to configure the connector cloud settings from another service. At the moment, it is configured directly through the config files.

  • Add endpoint to configure the connector on babeltower
  • Receive cloud configuration via AMQP on the connector

Connector doesn't try to reconnect to rabbitmq if fail

Expected Behavior

Connect to rabbitmq if rabbitmq-server is not up yet.

Current Behavior

The connector doesn't connect to rabbitmq if a fail occured.
Bellow there is the current syslog output:

Dec 16 19:53:08 knot daemon.err knotd[515]: amqp_connection_close: socket is closed
Dec 16 19:53:09 knot daemon.debug knotd[515]: Trying to connect to rabbitmq
Dec 16 19:53:09 knot daemon.err knotd[515]: error opening socket: a socket error occurred
Dec 16 19:53:09 knot daemon.err knotd[515]: amqp_connection_close: socket is closed
Dec 16 19:53:09 knot daemon.info knot-fog-connector[620]: KNoT Fog Connnector started
Dec 16 19:53:09 knot daemon.info knot-fog-connector[620]: Connecting to 'KNOT_CLOUD' cloud
Dec 16 19:53:10 knot daemon.debug knotd[515]: Trying to connect to rabbitmq
Dec 16 19:53:10 knot daemon.err knotd[515]: error opening socket: a socket error occurred
Dec 16 19:53:10 knot daemon.err knotd[515]: amqp_connection_close: socket is closed
Dec 16 19:53:11 knot daemon.debug knotd[515]: Trying to connect to rabbitmq
Dec 16 19:53:11 knot daemon.err knotd[515]: error opening socket: a socket error occurred
Dec 16 19:53:11 knot daemon.err knotd[515]: amqp_connection_close: socket is closed
Dec 16 19:53:12 knot daemon.debug knotd[515]: Trying to connect to rabbitmq
Dec 16 19:53:12 knot daemon.err knotd[515]: error opening socket: a socket error occurred
Dec 16 19:53:12 knot daemon.err knotd[515]: amqp_connection_close: socket is closed
Dec 16 19:53:13 knot daemon.err knot-fog-connector[620]: Error: connect ECONNREFUSED 127.0.0.1:5672     at Object._errnoException (util.js:1003:13)     at _exceptionWithHostPort (util.js:1024:20)     at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1194:14)
Dec 16 19:53:13 knot daemon.debug knotd[515]: Trying to connect to rabbitmq
Dec 16 19:53:13 knot daemon.err knotd[515]: error opening socket: a socket error occurred
Dec 16 19:53:13 knot daemon.err knotd[515]: amqp_connection_close: socket is closed
Dec 16 19:53:14 knot daemon.debug knotd[515]: Trying to connect to rabbitmq
Dec 16 19:53:14 knot daemon.err knotd[515]: error opening socket: a socket error occurred
Dec 16 19:53:14 knot daemon.err knotd[515]: amqp_connection_close: socket is closed
Dec 16 19:53:15 knot daemon.debug knotd[515]: Trying to connect to rabbitmq
Dec 16 19:53:15 knot daemon.info knotd[515]: Connected to amqp://guest:guest@localhost:5672//
Dec 16 19:53:15 knot daemon.info knotd[515]: Cloud CONNECTED
Dec 16 19:53:17 knot daemon.info knot-web[621]: KNOT Web UI
Dec 16 19:53:18 knot daemon.info knot-web[621]: Watching devices service initialization and shutdown
Dec 16 19:53:18 knot daemon.info knot-web[621]: Devices service is up
Dec 16 19:53:18 knot daemon.info knot-web[621]: Monitoring devices being added and removed
Dec 16 19:53:18 knot daemon.info knot-web[621]: Listening on 80
Dec 16 19:53:18 knot daemon.info knot-web[621]: KNoT Web UI server process is now running as a special user

Possible Solution

Implement connection retry mechanism like exponential backoff.

Steps to Reproduce

  1. Setup the raspberry pi image to log on syslog;
    1.1. vi /usr/local/bin/knot-fog-connector/config/default.json (set log.syslog to true and log.level to debug);
  2. Reboot the raspberry;

Context (Environment)

The raspberry should be already configured with a user.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.