Source: org/terraswarm/accessor/accessors/web/services/Heartbeat.js

// Copyright (c) 2017 The Regents of the University of California.
// All rights reserved.
//
// Permission is hereby granted, without written agreement and without
// license or royalty fees, to use, copy, modify, and distribute this
// software and its documentation for any purpose, provided that the above
// copyright notice and the following two paragraphs appear in all copies
// of this software.
//
// IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
// FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
// ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
// THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
//
// THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
// PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
// CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
// ENHANCEMENTS, OR MODIFICATIONS.
//

/** Send a heartbeat to a mothership monitoring web server.
 *
 * This accessor is not of much use because it requires the Mothership
 * server, which is not yet available.
 *
 * The Mothership server require a key string from the Heartbeat client.
 *
 * This accessor looks for key in $KEYSTORE/heartbeatKey, which
 * resolves to $HOME/.ptKeystore/heartbeatKey.
 *
 * The key is found in the swarmbox git repo, which not public.
 * Look for swarmbox/heartbeat/key
 * See https://www.terraswarm.org/testbeds/wiki/Main/SwarmboxGitRepo
 *
 * To download the repo using a repo.eecs.berkeley.edu username and
 * password (possibly different than your terraswarm website username
 * and password):
 *
 *   git clone https://repo.eecs.berkeley.edu/git/projects/terraswarm/swarmbox.git
 *
 * If you uploaded your SSH key to repo.eecs, then use:
 *
 *   git clone repoman@repo.eecs.berkeley.edu:projects/terraswarm/swarmbox.git
 *
 *  @accessor services/Heartbeat
 *  @author Christopher Brooks, based on heartbeat.js by Marten Lohstroh.
 *  @version $$Id$$
 *  @input {string} ipAddress The IP address of the host
 */

// Stop extra messages from jslint and jshint.  Note that there should
// be no space between the / and the * and global. See
// https://chess.eecs.berkeley.edu/ptexternal/wiki/Main/JSHint */
/*globals addInputHandler, console, error, exports, extend, get, getResource, input, output, parameter, require, send */
/*jshint globalstrict: true*/
'use strict';

var http = require('@accessors-modules/http-client');
var os = require('os');

// Mothership expects the Heartbeat clients to use a key.
var key = '';

function Heartbeat() {
    var heartbeat = {};
    heartbeat.pingMothership = function () {
        console.log("HeartBeat: pingMothership");
        var config = {};
        config.hostname = os.hostname();
        config.timestamp_sent = Math.floor(new Date()); // in ms
        var configString = JSON.stringify(config);
        var headers = {
            'Content-Type': 'application/json',
            'Content-Length': configString.length
        };

        var url = {
            host: 'terra.eecs.berkeley.edu',
            port: 8088,
            path: '/check-in?key=' + key,
            protocol: 'https'
        };
        var options = {
            url: url,
            method: 'POST',
            headers: headers,
            rejectUnauthorized: false,
            body: configString
                // We're using a self-signed certificate at the moment.
        };

        // Prepare request handler.
        var req = http.request(options, function (res) {
            if (res === null) {
                console.log("Heartbeat.pingMothership: request handler: res == null");
                return;
            }
            console.log("Heartbeat.pingMothership: request handler: res = " + res);
            // //res.setEncoding('utf-8');
            // var responseString = '';
            // // Receive a response.
            // res.on('data', function(data) {
            //     responseString += data;
            // });

            // res.on('end', function() {
            //     //console.log(responseString);
            //     //console.log('Checked in...');
            // });

            // res.on('error', function(e) {
            //     console.log('Unable to check in with server: ' + e);
            // });
        });

        // Issue request.
        // httpClient does this for us because the body is in the options.
        //req.write(configString);
        req.end();

        req.on('error', function (e) {
            console.log('Request problem: Unable to check in with server: ' + e);
        });

    };

    return heartbeat;
}

/** Set up the accessor by defining the inputs and outputs.
 */
exports.setup = function () {
    this.input('ipAddress', {
        type: "string"
    });

    // See the accessor comment for how to get the key.
    var keyFile = '$KEYSTORE/heartbeatKey';
    try {
        key = getResource('$KEYSTORE/heartbeatKey', 1000).trim();
    } catch (e) {
        console.log('Heartbeat: Could not get ' + keyFile + ":  " + e +
            '\nThe key is not public, so this accessor is only useful ' +
            'If you have the key.  See ' +
            'https://www.icyphy.org/accessors/library/index.html?accessor=services.Heartbeat');
        key = 'ThisIsNotAPipeNorIsItAWorkingKeySeeTheHeartbeatAccessorDocs';
    }
};

/** Initialize the accessor by attaching an input handler to the
 *  the *ipAddress* input.
 */
exports.initialize = function () {
    this.heartbeat = Heartbeat.call(this);
    this.addInputHandler('ipAddress', this.heartbeat.pingMothership);
};