spot-sdk-js
Version:
Develop applications and payloads for Spot using the unofficial Boston Dynamics Spot Node.js SDK.
198 lines (161 loc) • 7.54 kB
JavaScript
const {BaseClient, common_header_errors} = require('./common');
const data_buffer_protos = require('../bosdyn/api/data_buffer_pb');
const data_buffer_service = require('../bosdyn/api/data_buffer_service_grpc_pb');
class InvalidArgument extends Error {
constructor(msg){
super(msg);
this.name = 'InvalidArgument';
}
};
function partial(func, args, keywords){
function newfunc(fargs, fkeywords){
var newkeywords = {keywords, fkeywords};
return func(args, fargs, newkeywords);
}
return newfunc;
}
class DataBufferClient extends BaseClient {
static default_service_name = 'data-buffer';
static service_type = 'bosdyn.api.DataBufferService';
constructor(){
super(data_buffer_service.DataBufferServiceClient);
this.log_tick_schemas = {};
this._timesync_endpoint = null;
}
update_from(other){
super.update_from(other);
try{
this._timesync_endpoint = other.time_sync.endpoint;
}catch(e){
}
}
async add_text_messages(text_messages, args){
return await this._do_add_text_messages(this.call, text_messages, args);
}
async add_text_messages_async(text_messages, args){
return await this._do_add_text_messages(this.call_async, text_messages, args);
}
async _do_add_text_messages(func, text_messages, args){
const request = new data_buffer_protos.RecordTextMessagesRequest();
for(const in_text_msg of text_messages){
request.addTextMessages(in_text_msg);
}
return await func(this._stub.recordTextMessages, request, null, common_header_errors, args);
}
async add_operator_comment(msg, robot_timestamp = null, args){
return await this._do_add_operator_comment(this.call, msg, robot_timestamp, args);
}
async add_operator_comment_async(msg, robot_timestamp = null, args){
return await this._do_add_operator_comment(this.call_async, msg, robot_timestamp, args);
}
async _do_add_operator_comment(func, msg, robot_timestamp = null, args){
const request = new data_buffer_protos.RecordOperatorCommentsRequest();
robot_timestamp = robot_timestamp || this._now_in_robot_basis("Operator Comment");
const operatorComment = new data_buffer_protos.OperatorComment()
.setMessage(msg)
.setTimestamp(robot_timestamp);
request.addOperatorComments(operatorComment);
return await func(this._stub.recordOperatorComments, request, null, common_header_errors, args);
}
async add_blob(data, type_id, channel = null, robot_timestamp = null, write_sync = false, args){
return await this._do_add_blob(this.call, data, type_id, channel, robot_timestamp, write_sync, args);
}
async add_blob_async(data, type_id, channel = null, robot_timestamp = null, write_sync = false, args){
return await this._do_add_blob(this.call_async, data, type_id, channel, robot_timestamp, write_sync, args);
}
async _do_add_blob(func, data, type_id, channel, robot_timestamp, write_sync, args){
if(!channel) channel = type_id;
const request = new data_buffer_protos.RecordDataBlobsRequest();
robot_timestamp = robot_timestamp || this._now_in_robot_basis(type_id);
const dataBlob = new data_buffer_protos.DataBlob()
.setTimestamp(robot_timestamp)
.setChannel(channel)
.setTypeId(type_id)
.setData(data);
request.addBlobData(dataBlob);
request.setSync(write_sync);
return await func(this._stub.recordDataBlobs, request, null, common_header_errors, args);
}
async add_protobuf(proto, channel = null, robot_timestamp = null, write_sync = false){
return await this._do_add_protobuf(this.add_blob, proto, channel, robot_timestamp, write_sync);
}
async add_protobuf_async(proto, channel = null, robot_timestamp = null, write_sync = false){
return await this._do_add_protobuf(this.add_blob_async, proto, channel, robot_timestamp, write_sync);
}
async _do_add_protobuf(func, proto, channel, robot_timestamp, write_sync){
const binary_data = proto.serializeBinary();
robot_timestamp = robot_timestamp || this._now_in_robot_basis(null, proto);
const type_id = proto.displayName;
channel = channel || type_id;
return await func(binary_data, type_id, channel, robot_timestamp, write_sync);
}
async add_events(events, args){
return await this._do_add_events(this.call, events, args);
}
async add_events_async(events, args){
return await this._do_add_events(this.call_async, events, args);
}
async _do_add_events(func, events, args){
const request = new data_buffer_protos.RecordEventsRequest();
for(const event of events){
request.addEvents(event);
}
return await func(this._stub.recordEvents, request, null, common_header_errors, args);
}
async register_signal_schema(variables, schema_name, args){
return await this._do_register_signal_schema(this.call, variables, schema_name, args);
}
async register_signal_schema_async(variables, schema_name, args){
return await this._do_register_signal_schema(this.call_async, variables, schema_name, args);
}
async _do_register_signal_schema(func, variables, schema_name, args){
const tick_schema = new data_buffer_protos.SignalSchema()
.setVarsList(variables)
.setSchemaName(schema_name);
const request = new data_buffer_protos.RegisterSignalSchemaRequest()
.setSchema(tick_schema);
const value_from_response = partial(this._save_schema_id, tick_schema)
return await func(this._stub.registerSignalSchema, request, value_from_response, common_header_errors, args);
}
async add_signal_tick(data, schema_id, encoding = data_buffer_protos.SignalTick.Encoding.ENCODING_RAW, sequence_id=0, source="client", args){
return await this._do_add_signal_tick(this.call, data, schema_id, encoding, sequence_id, source, args);
}
async add_signal_tick_async(data, schema_id, encoding = data_buffer_protos.SignalTick.Encoding.ENCODING_RAW, sequence_id=0, source="client", args){
return await this._do_add_signal_tick(this.call_async, data, schema_id, encoding, sequence_id, source, args);
}
async _do_add_signal_tick(func, data, schema_id, encoding, sequence_id, source, args){
if(!(schema_id in this.log_tick_schemas)) throw new RangeError(`The log tick schema id "${schema_id}" is unknown`);
const request = new data_buffer_protos.RecordSignalTicksRequest();
const tickData = new data_buffer_protos.SignalTick()
.setSequenceId(sequence_id)
.setSource(source)
.setSchemaId(schema_id)
.setEncoding(encoding)
.setData(data);
request.addTickData(tickData);
return await func(this._stub.recordSignalTicks, request, null, common_header_errors, args);
}
_save_schema_id(schema, response){
this.log_tick_schemas[response.getSchemaId()] = schema;
return response.getSchemaId();
}
_now_in_robot_basis(msg_type = null, proto = null){
if(this._timesync_endpoint){
let isCatch = false;
let converter;
try{
converter = this._timesync_endpoint.get_robot_time_converter();
}catch(e){
isCatch = true;
this.logger.debug(`[DATA BUFFER] Could not timestamp message of type ${msg_type != null ? msg_type : proto != null ? proto?.displayName : 'Unknown'}`);
}
if(!isCatch){
return converter.robot_timestamp_from_local_secs(Date.now());
}
}
return null;
}
};
module.exports = {
DataBufferClient
};