@robotical/roboticaljs
Version:
Javascript/TS library for Robotical products
190 lines (160 loc) • 6.17 kB
text/typescript
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// RICJS
// Communications Library
//
// Rob Dobson & Chris Greening 2020-2022
// (C) 2020-2022
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
import { RaftConnEvent, RaftConnEventFn, RaftLog, RaftMsgHandler, RaftOKFail } from '@robotical/raftjs';
import { CogLEDPatternCheckerColour, CogLedLcdColours } from './CogTypes';
export default class CogLEDPatternChecker {
// LED pattern refresh
private _ledPatternTimeoutMs = 10000;
private _ledPatternRefreshTimer: ReturnType<typeof setTimeout> | null = null;
// Verification of correct device
private _ledColours: Array<string> = new Array<string>();
private _lcdColours: Array<string> = new Array<string>();
private _bleVerifActive = false;
// Message handler, etc
private _msgHandler: RaftMsgHandler | null = null;
private _onConnEvent: RaftConnEventFn | null = null;
private _isConnectedFn: () => boolean = () => false;
/**
* Start checking correct RIC using LED pattern
*
* @param {RICLedLcdColours} ricLedLcdColours - available colours
* @param {RaftMsgHandler} msgHandler - message handler
* @param {RaftConnEventFn} onConnEvent - connection event handler
* @param {() => boolean} isConnectedFn - function to check if connected
* @return boolean - true if started ok
*
*/
async checkCorrectRICStart(ricLedLcdColours: CogLedLcdColours,
msgHandler: RaftMsgHandler,
onConnEvent: RaftConnEventFn,
isConnectedFn: () => boolean): Promise<boolean> {
// Store the onConnEvent, etc
this._msgHandler = msgHandler;
this._onConnEvent = onConnEvent;
this._isConnectedFn = isConnectedFn;
// Set colour pattern checker colours
const randomColours = this.setupColours(ricLedLcdColours);
// Start timer to repeat checking LED pattern
RaftLog.debug(`checkCorrectRICStart: starting LED pattern checker`);
if (!await this._checkCorrectRICRefreshLEDs()) {
return false;
}
// Event
onConnEvent(RaftConnEvent.CONN_VERIFYING_CORRECT, randomColours);
// Start timer to repeat sending of LED pattern
// This is because RIC's LED pattern override times out after a while
// so has to be refreshed periodically
this._ledPatternRefreshTimer = setInterval(async () => {
RaftLog.verbose(`checkCorrectRICStart: loop`);
if (!this._checkCorrectRICRefreshLEDs()) {
RaftLog.debug('checkCorrectRICStart no longer active - clearing timer');
this._clearLedPatternRefreshTimer();
}
}, this._ledPatternTimeoutMs / 2.1);
return true;
}
/**
* Stop checking correct RIC
* @param {boolean} confirmCorrectRIC - true if user confirmed correct RIC
* @return void
*
*/
async checkCorrectRICStop(confirmCorrectRIC: boolean): Promise<boolean> {
// Stop refreshing LED pattern on RIC
this._clearLedPatternRefreshTimer();
// Stop the LED pattern checker if connected
if (this._isConnectedFn()) {
await this.clearRICColors();
}
// Check correct
if (!confirmCorrectRIC) {
// Event
if (this._onConnEvent)
this._onConnEvent(RaftConnEvent.CONN_REJECTED);
// Indicate as rejected if we're not connected or if user didn't confirm
return false;
}
// Event
if (this._onConnEvent)
this._onConnEvent(RaftConnEvent.CONN_VERIFIED_CORRECT);
return true;
}
/**
* Refresh LED pattern on RIC
*
* @return boolean - true if checking still active
*
*/
async _checkCorrectRICRefreshLEDs(): Promise<boolean> {
// Check LED pattern is active
if (!this.isActive()) {
return false;
}
// Check connected
RaftLog.debug(`_verificationRepeat getting isConnected`);
if (!this._isConnectedFn()) {
console.warn('_verificationRepeat not connected');
return false;
}
// Repeat the LED pattern (RIC times out the LED override after ~10 seconds)
RaftLog.debug(`_verificationRepeat setting pattern`);
return await this.setRICColors();
}
_clearLedPatternRefreshTimer(): void {
if (this._ledPatternRefreshTimer) {
clearInterval(this._ledPatternRefreshTimer);
this._ledPatternRefreshTimer = null;
}
}
isActive(): boolean {
return this._bleVerifActive;
}
clear(): void {
this._bleVerifActive = false;
}
setupColours(availableColors: CogLEDPatternCheckerColour[]): string[] {
// Check length of available colours
if (availableColors.length == 0) {
RaftLog.warn('start no available colours');
}
// Random colour selection
const LED_1 =
availableColors[Math.floor(Math.random() * availableColors.length)];
const LED_2 =
availableColors[Math.floor(Math.random() * availableColors.length)];
const LED_3 =
availableColors[Math.floor(Math.random() * availableColors.length)];
// LED and LCD colours are different to attempt to be visually similar
// 12 in total. 4 each
this._ledColours = [LED_1.led, LED_1.led, LED_1.led, LED_1.led, LED_2.led, LED_2.led, LED_2.led, LED_2.led, LED_3.led, LED_3.led, LED_3.led, LED_3.led];
this._lcdColours = [LED_1.lcd, LED_1.lcd, LED_1.lcd, LED_1.lcd, LED_2.lcd, LED_2.lcd, LED_2.lcd, LED_2.lcd, LED_3.lcd, LED_3.lcd, LED_3.lcd, LED_3.lcd];
// Set the colours to display on LEDs
this._bleVerifActive = true;
// Return LCD colours to display
return this._lcdColours;
}
async setRICColors(): Promise<boolean> {
// Set bonding colours
RaftLog.debug('setRICColors setting colours');
this._msgHandler?.sendRICRESTURL<RaftOKFail>(`led/ring/setleds/${this._ledColours.join('').replace(/#/g, '')}`);
return true;
}
async clearRICColors(): Promise<void> {
// Clear the LED colours
RaftLog.debug('clearRICColors');
try {
if (this._msgHandler) {
await this._msgHandler.sendRICRESTURL<RaftOKFail>(`led/ring/color/#000000`);
}
} catch (error) {
RaftLog.debug(`clearRICColors failed to send ${error}`);
}
}
}