@robotical/ricjs
Version:
Javascript/TS library for Robotical RIC
442 lines (396 loc) • 9.48 kB
text/typescript
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// RICJS
// Communications Library
//
// Rob Dobson & Chris Greening 2020-2022
// (C) 2020-2022
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
import { RICConnEvent } from './RICConnEvents';
import {
ROSSerialSmartServos,
ROSSerialIMU,
ROSSerialPowerStatus,
ROSSerialAddOnStatusList,
ROSSerialRobotStatus,
ROSSerialMagneto,
} from './RICROSSerial';
import { RICUpdateEvent } from './RICUpdateEvents';
export enum RICIFType {
RIC_INTERFACE_BLE,
RIC_INTERFACE_WIFI,
}
export enum RICFileSendType {
RIC_NORMAL_FILE,
RIC_FIRMWARE_UPDATE,
}
export enum RICStreamType {
RIC_REAL_TIME_STREAM,
}
export type RICEventFn = (
eventType: string,
eventEnum: RICConnEvent | RICUpdateEvent,
eventName: string,
data?: object | string | null,
) => void;
export interface RICSubscription {
remove(): void;
}
export class RICFriendlyName {
friendlyName = '';
friendlyNameIsSet?= false;
req?= '';
rslt?= 'commsFail';
validMs?= 0;
}
export class RICSystemInfo {
rslt = '';
SystemName = 'Unknown';
SystemVersion = '0.0.0';
RicHwRevNo = 0;
MAC?= "";
SerialNo?= "";
validMs?= 0;
}
export class RICCalibInfo {
rslt = '';
calDone = 0;
validMs?= 0;
}
export class RICOKFail {
RIC_OK = 'ok';
set(rsltFlag: boolean) {
if (rsltFlag) {
this.rslt = this.RIC_OK;
} else {
this.rslt = 'fail';
}
}
rslt = 'commsFail';
isOk() {
return this.rslt === this.RIC_OK;
}
}
export class RICReportMsg {
msgType?: string;
rslt = '';
timeReceived?: number;
hexRd?: string;
elemName?: string;
IDNo?: number;
msgKey?: string;
addr?: number;
msgBody?: string;
}
export class RICHWFWStat {
s = '';
m = '';
v = '';
n = '';
p = 0;
i = 0;
}
export class RICHWFWUpdRslt {
req = '';
rslt = 'commsFail';
st: RICHWFWStat = new RICHWFWStat();
}
export type RICFWInfo = {
elemType: string;
version: string;
destname: string;
md5: string;
releaseNotes: string;
comments: string;
updaters: Array<string>;
downloadUrl: string;
firmware?: string;
};
export type RICUpdateInfo = {
rslt: string;
firmwareVersion: string;
ricRevision: string;
files: Array<RICFWInfo>;
minimumUpdaterVersion: Dictionary<string>;
note: string;
};
export type RICFileStartResp = {
rslt: string;
batchMsgSize: number;
batchAckSize: number;
};
export type RICStreamStartResp = {
rslt: string;
streamID: number;
maxBlockSize?: number;
};
export class RICStateInfo {
smartServos: ROSSerialSmartServos = new ROSSerialSmartServos();
smartServosValidMs = 0;
imuData: ROSSerialIMU = new ROSSerialIMU();
imuDataValidMs = 0;
magnetoData: ROSSerialMagneto = new ROSSerialMagneto();
magnetoDataValidMs = 0;
power: ROSSerialPowerStatus = new ROSSerialPowerStatus();
powerValidMs = 0;
addOnInfo: ROSSerialAddOnStatusList = new ROSSerialAddOnStatusList();
addOnInfoValidMs = 0;
robotStatus: ROSSerialRobotStatus = new ROSSerialRobotStatus();
robotStatusValidMs = 0;
}
export type RICFile = {
name: string;
size: number;
};
export class RICFileList {
req = '';
rslt = 'ok';
fsName = 'spiffs';
fsBase = '/spiffs';
diskSize = 0;
diskUsed = 0;
folder = '/spiffs/';
files: Array<RICFile> = [];
}
/**
* RICHWElem
*
* @description
* Information about a hardware element
*
* @field name: string - element name
* @field type: string - element type
* @field busName: string - name of bus (e.g. I2C) attached to
* @field addr: string - address of element on the bus
* @field addrValid: number - 1 if address is valid
* @field IDNo: string - unique identifier of element
* @field whoAmI: string - name of element type
* @field whoAmITypeCode: string - number of element type
* @field SN: string - Serial number
* @field versionStr: string - Version
* @field commsOk: number - 1 if communications OK, 0 if not, -1 if device is invalid
*/
export type RICHWElem = {
name: string;
type: string;
busName: string;
addr: string;
addrValid: number;
IDNo: string;
whoAmI: string;
whoAmITypeCode: string;
SN: string;
versionStr: string;
commsOk: number;
};
export class RICHWElemList {
req = '';
rslt = 'ok';
hw: Array<RICHWElem> = [];
}
// Minimum key length version of RICHWElem
export type RICHWElem_Min = {
n: string;
t: string;
I: string;
w: string;
W: string;
S: string;
v: string;
c: number;
};
export class RICHWElemList_Min {
// Members
req = '';
rslt = 'ok';
hw: Array<RICHWElem_Min> = [];
// Method to convert to RICHWElemList
static expand(hwMin: RICHWElemList_Min): RICHWElemList {
const hwList = new RICHWElemList();
for (const hwElem of hwMin.hw) {
hwList.hw.push({
name: hwElem.n,
type: hwElem.t,
busName: '',
addr: '',
addrValid: 0,
IDNo: hwElem.I,
whoAmI: hwElem.w,
whoAmITypeCode: hwElem.W,
SN: hwElem.S,
versionStr: hwElem.v,
commsOk: hwElem.c,
});
}
return hwList;
}
}
// Single encoded string version of RICHWElem
export type RICHWElem_Str = {
a: string;
};
export type RICHWElemList_Name = {
rslt: string;
hw: Array<string>;
};
// RICHWElemList containing coded strings for each HWElem field
export class RICHWElemList_Str {
req = '';
rslt = 'ok';
hw: Array<RICHWElem_Str> = [];
// Method to convert to RICHWElemList
static expand(hwStr: RICHWElemList_Str): RICHWElemList {
const hwList = new RICHWElemList();
for (const hwElem of hwStr.hw) {
if (hwElem.a) {
const hwElemStr = hwElem.a.split('|');
hwList.hw.push({
name: RICHWElemList_Str.unesc(hwElemStr[0]),
type: RICHWElemList_Str.unesc(hwElemStr[1]),
busName: "",
addr: "",
addrValid: 0,
IDNo: RICHWElemList_Str.unesc(hwElemStr[2]),
whoAmI: RICHWElemList_Str.unesc(hwElemStr[3]),
whoAmITypeCode: RICHWElemList_Str.unesc(hwElemStr[4]),
SN: RICHWElemList_Str.unesc(hwElemStr[5]),
versionStr: RICHWElemList_Str.unesc(hwElemStr[6]),
commsOk: Number(hwElemStr[7]),
});
}
}
return hwList;
}
// Method to unescape a pipe character
static unesc(s: string): string {
return s.replace(/\/x7c/g, '|');
}
}
/**
* RICAddOn
*
* @description
* Information about an add-on
*
* @field name: string - Name of add-on
* @field SN: string - Serial number
* @field poll: string - polling type ("status")
* @field pollRd: string - hex data most recently read
* @field pollHz: number - rate of polling
*/
export type RICAddOn = {
name: string;
SN: string;
poll: string;
pollRd: number;
pollHz: number;
};
export class RICConfiguredAddOns {
req = '';
rslt = 'ok';
addons: Array<RICAddOn> = [];
}
/**
* AddOnElemAndConfig
*
* @description
* Carrier of information about an add-on combining
* the add-on element and the add-on configuration
*
* @field addOnConfig: RICAddOn - Add-on configuration
* @field hwElemRec: RICHWElem - Add-on element
* @field elemIdx: number - Index of the add-on element
*/
export class AddOnElemAndConfig {
constructor(
addOnConfig: RICAddOn | null,
hwElemRec: RICHWElem | null,
elemIdx: number,
) {
this.isConfigured = addOnConfig !== null;
this.isConnected = hwElemRec !== null;
if (addOnConfig != null) {
this.SN = addOnConfig.SN;
this.name = addOnConfig.name;
} else if (hwElemRec != null) {
this.SN = hwElemRec.SN;
this.name = hwElemRec.name;
}
this.addOnConfig = addOnConfig;
this.hwElemRec = hwElemRec;
this.id = elemIdx.toString();
}
// Fields from config (stored in RIC NVS using addon REST API)
addOnConfig: RICAddOn | null = null;
// Fields from HWElem (from hwstatus command)
hwElemRec: RICHWElem | null = null;
// Fields allocated when combining records
name = '';
SN = '';
id = '0';
isConnected = false;
isConfigured = false;
}
export class RICSysModInfoBLEMan {
req?= '';
rslt = 'ok';
isConn = false;
isAdv = false;
advName?= "";
BLEMAC = "";
rssi = -200;
rxM = 0;
rxB = 0;
rxBPS = 0.0;
txM = 0;
txB = 0;
txBPS = 0.0;
txErr = 0;
txErrPS = 0;
tM?= 0;
tB?= 0;
tBPS?= 0.0;
tSeqErrs?= 0;
tDatErrs?= 0;
}
export type RICProgressCBType = (received: number, total: number) => void;
export class RICFileDownloadResult {
fileData: Uint8Array | null = null;
downloadedOk = false;
}
export type RICFileDownloadFn = (downloadUrl: string, progressCB: RICProgressCBType) => Promise<RICFileDownloadResult>;
export type RICLEDPatternCheckerColour = {
led: string;
lcd: string;
}
export type RICLedLcdColours = Array<RICLEDPatternCheckerColour>;
export interface Dictionary<T> {
[key: string]: T;
}
export type RICWifiScanResults = {
req: string;
rslt: string;
wifi: WifiScanWifiItem[];
};
export type WifiScanWifiItem = {
ssid: string;
rssi: number;
ch1: number;
ch2: number;
auth: string;
bssid: string;
pair: string;
group: string;
};
export type PystatusMsgType = {
req: string;
running: string;
rslt: string;
};
export type RICServoFaultFlags = {
intermittentConnection: boolean,
noConnection: boolean,
faultyConnection: boolean,
servoHornPositionError: boolean
};