sphero-pwn
Version:
Driver for Sphero robots
120 lines (108 loc) • 3.98 kB
text/coffeescript
# Buffer holding a command that will be sent to the robot.
class Command
# @return {Buffer} the underlying Buffer
buffer: null
# Creates a buffer for a command.
#
# The command's buffer must be finalized by calling {Command#setSequence}
# before it is transmitted to the robot.
#
# @param {Number} deviceId the ID of the virtual device that receives the
# command
# @param {Number} commandId the ID of the command within the virtual device
# @param {Number} dataLength the number of extra bytes in the command
# @param {Object?} flags (optional) flags that apply to all commands
# @option flags {Boolean} noResponse if true, the robot will be instructed
# not to provide a response to the command
# @option flags {Boolean} noTimeoutReset if true, sending this command will
# not reset the client interactivity timeout
constructor: (deviceId, commandId, dataLength, flags) ->
@_dataLength = dataLength
@buffer = new Buffer 7 + @_dataLength
@buffer[0] = 0xFF
@buffer[2] = deviceId
@buffer[3] = commandId
@buffer[5] = if dataLength > 254 then 0xFF else dataLength + 1
sop2 = 0xFF
if flags
if flags.noResponse
sop2 &= 0xFE
if flags.noTimeoutReset
sop2 &= 0xFD
@buffer[1] = sop2
# Sets the sequence number and checksum bytes in the command buffer.
#
# After this method is called, the buffer can be transmitted to the robot.
#
# @param {Number} sequence the sequence number to be set
# @return {Command} this
setSequence: (sequence) ->
@buffer[4] = sequence
@buffer[6 + @_dataLength] = Command.checksum @buffer, 2, 6 + @_dataLength
@
# Sets a byte in the data buffer.
#
# @param {Number} offset the byte's offset in the data field of the command
# buffer
# @param {Number} value the byte value to set
# @return {Command} this
setDataUint8: (offset, value) ->
@buffer.writeUInt8 value, offset + 6
@
# Sets a 16-bit unsigned integer in the data buffer.
#
# The integer is assumed to be big-endian, as that is the standard Sphero API
# format.
#
# @param {Number} offset the integer's offset in the data field of the
# command buffer
# @param {Number} value the 16-bit unsigned integer value to set
# @return {Command} this
setDataUint16: (offset, value) ->
@buffer.writeUInt16BE value, offset + 6
@
# Sets a 32-bit unsigned integer in the data buffer.
#
# The integer is assumed to be big-endian, as that is the standard Sphero API
# format.
#
# @param {Number} offset the integer's offset in the data field of the
# command buffer
# @param {Number} value the 32-bit unsigned integer value to set
# @return {Command} this
setDataUint32: (offset, value) ->
@buffer.writeUInt32BE value, offset + 6
@
# Sets a string field in the data buffer.
#
# @param {Number} offset the string's offset in the data field of the
# command buffer
# @param {String} value the string to set
# @return {Command} this
setDataString: (offset, value) ->
@buffer.write value, offset + 6, value.length, 'utf8'
@
# Sets a sequence of bytes in the data buffer.
#
# @param {Number} offset the offset of the sequence's first byte in the data
# field of the command buffer
# @param {Buffer} value the sequence of bytes to be set
# @return {Command} this
setDataBytes: (offset, value) ->
value.copy @buffer, offset + 6
@
# Computes the checksum over a range of bytes in a buffer
#
# @param {Buffer} buffer
# @param {Number} start the index of the first byte in the buffer whose
# checksum will be computed
# @param {Number} end one past the index of the last byte in the buffer whose
# checksum will be computed
# @return {Number} the computed checksum
@checksum: (buffer, start, end) ->
sum = 0
while start < end
sum = (sum + buffer[start]) & 0xFF
start += 1
sum ^ 0xFF
module.exports = Command