Home Manual Reference Source Test Repository

src/drivers/pin/PinDriver.js

'use strict';

/** @namespace drivers.pin */

const EventEmitter = require('events').EventEmitter;

const TAG = 'PinDriver';

/**
 * Communicates with pins on microcontrollers.
 * @memberOf drivers.pin
 * @author Darko Lukic <[email protected]>
 */
class PinDriver extends EventEmitter {
    constructor(name, config) {
        super();

        this.config = Object.assign({
            mode: 'analog',     // `analog` or `digital`
            direction: 'input', // `input` or `output`
        }, config);
        this.name = name;

        if (this.config.cid === undefined) {
            throw Error(TAG, this.name, 'You must provide a communication ID');
        }

        this._onDataReceived = this._onDataReceived.bind(this);
        this.uniqueDataReceivedCallback = null;

        // Set-up communicator
        this.communicator = null;
        if (this.config._communicator !== undefined) {
            // For testing purposes only (experiments)
            this.communicator = this.config._communicator;
        } else {
            this.communicator = Mep.DriverManager.getDriver(this.config['@dependencies'].communicator);
        }
        this.communicator.on('data_' + this.config.cid, this._onDataReceived);
    }

    _onDataReceived(data) {
        if (this.uniqueDataReceivedCallback !== null) {
            this.uniqueDataReceivedCallback(data);
        }

        if (this.config.direction === 'input') {
            this.emit('changed', data.readUInt8(0));
        }
    }

    /**
     * Read value of given pin
     * @returns {Promise}
     */
    read() {
        return new Promise((resolve, reject) => {
            if (this.config.direction === 'input') {
                this.uniqueDataReceivedCallback = (data) => {
                    resolve(data.readUint8(0));
                    this.uniqueDataReceivedCallback = null;
                };
                this.communicator.send(this.config.cid, Buffer.from([]));
            } else {
                throw Error('Cannot read output pin');
            }
        });
    }

    /**
     * Write value to given pin
     * @param value {Number} - [0, 1] for digital pins or [0 - 255] for analog pins
     */
    write(value) {
        if (this.config.direction === 'output') {
            if (this.config.mode === 'digital' && value != 1 && value != 0) {
                value = 1;
            }
            this.communicator.send(this.config.cid, Buffer.from([value]));
        } else {
            throw Error('Cannot write to input pin');
        }
    }
}

module.exports = PinDriver;