Memristor-Robotics/mep-master

View on GitHub
src/drivers/pin/PinDriver.js

Summary

Maintainability
A
1 hr
Test Coverage
'use strict';

/** @namespace drivers.pin */

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

const TAG = 'PinDriver';

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

        this.config = Object.assign({
            min: 0,
            max: 255,
            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._value = 0;

        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 (data.length !== 1) return;

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

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

    /**
     * Get last value
     * @example let value = Mep.getDriver('PinDriver').getLastState();
     * @returns {Number} High or low
     */
    getLastValue() {
        return this._value;
    }

    /**
     * Read value of given pin
     * @example Mep.getDriver('PinDriver').read((value) => { console.log(value) });
     * @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 {Number} value [0, 1] for digital pins or [0 - 255] for analog pins
     */
    write(value) {
        if (this.config.direction === 'output') {
            if (this.config.mode === 'digital') {
                if (value > 1 || value < 0) {
                    value = 1;
                }
            } else {
                if (value > this.config.max) {
                    value = this.config.max;
                    Mep.Log.error(TAG, this.name, 'Max value is:', this.config.max);
                }
                else if (value < this.config.min) {
                    value = this.config.min;
                    Mep.Log.error(TAG, this.name, 'Min value is:', this.config.min);
                }
            }
            let buffer = Buffer.from([value]);
            this.communicator.send(this.config.cid, buffer);
        } else {
            throw Error('Cannot write to input pin');
        }
    }

    getGroups() {
        return [];
    }
}

module.exports = PinDriver;