<commit_before>class WebSocketCanOpen extends WebSocketCan {
  messageHandler(handler) {
    return function(event) {
      let init = Object.assign({}, event);
      init.data = CanOpenMessage.from(new Uint8Array(event.data));
      handler(new MessageEvent(event.type, init));
    }
  }
}

class CanOpenMessage extends CanMessage {
  constructor(functionCode, nodeId, data=[]) {
    super((functionCode << 7) + nodeId, data, false, false, false);
  }

  static get FUNCTION_CODE_NMT() { return 0x0; }
  static get FUNCTION_CODE_SYNC() { return 0x1; }
  static get FUNCTION_CODE_EMCY() { return 0x1; }
  static get FUNCTION_CODE_TIME_STAMP() { return 0x2; }
  static get FUNCTION_CODE_TPDO1() { return 0x3; }
  static get FUNCTION_CODE_RPDO1() { return 0x4; }
  static get FUNCTION_CODE_TPDO2() { return 0x5; }
  static get FUNCTION_CODE_RPDO2() { return 0x6; }
  static get FUNCTION_CODE_TPDO3() { return 0x7; }
  static get FUNCTION_CODE_RPDO3() { return 0x8; }
  static get FUNCTION_CODE_TPDO4() { return 0x9; }
  static get FUNCTION_CODE_RPDO4() { return 0xA; }
  static get FUNCTION_CODE_SDO_TX() { return 0xB; }
  static get FUNCTION_CODE_SDO_RX() { return 0xC; }
  static get FUNCTION_CODE_NMT_ERROR_CONTROL() { return 0xE; }

  get functionCode() {
    return this.arbitrationId >> 7;
  }

  set functionCode(fc) {
    this.arbitrationId = ((fc & 0xF) << 7) + this.nodeId;
  }

  get nodeId() {
    return this.arbitrationId & 0x7F;
  }

  set nodeId(id) {
    this.arbitrationId = (this.functionCode << 7) + (id & 0x7F);
  }

  static from(byteArray) { // Factory from SocketCAN-formatted byte array
      let nodeId = byteArray[0] & 0x7F;
      let functionCode = byteArray[0] >> 7;
      functionCode += (byteArray[1] & 0x7) << 1;
      let dlc = byteArray[4];
      let data = byteArray.slice(8, 8 + dlc);
      return new this(functionCode, nodeId, data);
  }
}

class CanOpenNmtErrorControlMessage extends CanOpenMessage {
  constructor(nodeId, data) {
    super(CanOpenMessage.FUNCTION_CODE_NMT_ERROR_CONTROL, nodeId, data);
  }
}

class CanOpenBootupMessage extends CanOpenNmtErrorControlMessage {
  constructor(nodeId) {
    super(nodeId, [0]);
  }
}

class CanOpenHeartbeatMessage extends CanOpenNmtErrorControlMessage {
  constructor(nodeId, nmtState) {
    super(nodeId, [nmtState]);
  }
}

class CanOpenSdoMessage extends CanOpenMessage {
  constructor(functionCode, nodeId, sdoHeader, sdoData) {
    sdoData.unshift(sdoHeader);
    super(functionCode, nodeId, new Uint8Array(sdoData));
  }

  // Bit positions and masks
  static get CS_BITNUM() { return 5; }

  // Command specifiers
  static get CCS_DOWNLOAD_SEGMENT() { return 0; }
  static get CCS_DOWNLOAD_INITIATE() { return 1; }
  static get CCS_UPLOAD_INITIATE() { return 2; }
  static get CCS_UPLOAD_SEGMENT() { return 3; }
  static get CS_ABORT() { return 4; }
  static get SCS_UPLOAD_SEGMENT() { return 0; }
  static get SCS_DOWNLOAD_SEGMENT() { return 1; }
  static get SCS_UPLOAD_INITIATE() { return 2; }
  static get SCS_DOWNLOAD_INITIATE() { return 3; }

  // Derived properties
  get cs() { return (this.data[0] >> CanOpenSdoMessage.CS_BITNUM) & 0x7; }
}

const CanOpenSdoInitiateMixIn = superclass => class extends superclass {
  static get S_BITNUM() { return 0; }
  static get E_BITNUM() { return 1; }
  static get N_BITNUM() { return 2; }
  static get N_MASK() { return 0xC; }
  get s() { return (this.data[0] >> this.S_BITNUM) & 0x1; }
  get e() { return (this.data[0] >> this.E_BITNUM) & 0x1; }
  get n() { return (this.data[0] >> this.N_BITNUM) & 0x3; }
  get index() { return (this.data[2] << 8) + this.data[1]; }
  get subIndex() { return this.data[3]; }
};

const CanOpenSdoSegmentMixIn = superclass => class extends superclass {
  static get T_BITNUM() { return 4; }
  static get N_BITNUM() { return 1; }
  static get N_MASK() { return 0xE; }
  static get C_BITNUM() { return 0; }
  get t() { return (this.data[0] >> this.T_BITNUM) & 0x1; }
  get n() { return (this.data[0] >> this.N_BITNUM) & 0x7; }
  get c() { return (this.data[0] >> this.C_BITNUM) & 0x1; }
};

class CanOpenSdoRequest extends CanOpenSdoMessage {
  constructor(nodeId, sdoHeader, sdoData) {
    super(CanOpenMessage.FUNCTION_CODE_SDO_RX, nodeId, sdoHeader, sdoData);
  }
}

class CanOpenSdoResponse extends CanOpenSdoMessage {
  constructor(nodeId, sdoHeader, sdoData) {
    super(CanOpenMessage.FUNCTION_CODE_SDO_TX, nodeId, sdoHeader, sdoData);
  }
}

class CanOpenSdoAbortResponse extends CanOpenSdoResponse {

  // Abort codes
  static get ABORT_INVALID_CS() { return 0x05040001; }
  static get ABORT_WO() { return 0x06010001; }
  static get ABORT_RO() { return 0x06010002; }
  static get ABORT_OBJECT_DNE() { return 0x06020000; }
  static get ABORT_SUBINDEX_DNE() { return 0x06090011; }
  static get ABORT_GENERAL() { return 0x08000000; }
  
  constructor(nodeId, index, subIndex, abortCode) {
    let sdoHeader = CanOpenSdoMessage.CS_ABORT << CanOpenSdoMessage.CS_BITNUM;
    let sdoData = [index & 0xFF, index >> 8, subIndex];
    sdoData.push((abortCode >> 0) & 0xFF);
    sdoData.push((abortCode >> 8) & 0xFF);
    sdoData.push((abortCode >> 16) & 0xFF);
    sdoData.push((abortCode >> 24) & 0xFF);
    super(nodeId, sdoHeader, sdoData);
  }
}

class CanOpenSdoDownloadInitiateRequest extends CanOpenSdoInitiateMixIn(CanOpenSdoRequest) {
  constructor(nodeId, n, e, s, index, subIndex, data) {
    let sdoHeader = CanOpenSdoMessage.CCS_DOWNLOAD_INITIATE << CanOpenSdoMessage.CS_BITNUM;
    sdoHeader += n << CanOpenSdoInitiateMixIn(CanOpenSdoRequest).N_BITNUM;
    sdoHeader += e << CanOpenSdoInitiateMixIn(CanOpenSdoRequest).E_BITNUM;
    sdoHeader += s << CanOpenSdoInitiateMixIn(CanOpenSdoRequest).S_BITNUM;
    let sdoData = [index & 0xFF, index >> 8, subIndex];
    sdoData.push((data >> 0) & 0xFF);
    sdoData.push((data >> 8) & 0xFF);
    sdoData.push((data >> 16) & 0xFF);
    sdoData.push((data >> 24) & 0xFF);
    super(nodeId, sdoHeader, sdoData);
  }
}

class CanOpenSdoDownloadInitiateResponse extends CanOpenSdoInitiateMixIn(CanOpenSdoResponse) {
  constructor(nodeId, index, subIndex) {
    let sdoHeader = CanOpenSdoMessage.SCS_DOWNLOAD_INITIATE << CanOpenSdoMessage.CS_BITNUM;
    let sdoData = [index & 0xFF, index >> 8, subIndex, 0, 0, 0, 0];
    super(nodeId, sdoHeader, sdoData);
  }
}

class CanOpenSdoUploadInitiateRequest extends CanOpenSdoInitiateMixIn(CanOpenSdoRequest) {
  constructor(nodeId, index, subIndex) {
    let sdoHeader = CanOpenSdoMessage.CCS_UPLOAD_INITIATE << CanOpenSdoMessage.CS_BITNUM;
    let sdoData = [index & 0xFF, index >> 8, subIndex, 0 ,0 ,0 ,0];
    super(nodeId, sdoHeader, sdoData);
  }
}

class CanOpenSdoUploadInitiateResponse extends CanOpenSdoInitiateMixIn(CanOpenSdoResponse) {
  constructor(nodeId, n, e, s, index, subIndex, data) {
    let sdoHeader = CanOpenSdoMessage.SCS_UPLOAD_INITIATE << CanOpenSdoMessage.CS_BITNUM;
    sdoHeader += n << CanOpenSdoInitiateMixIn(CanOpenSdoRequest).N_BITNUM;
    sdoHeader += e << CanOpenSdoInitiateMixIn(CanOpenSdoRequest).E_BITNUM;
    sdoHeader += s << CanOpenSdoInitiateMixIn(CanOpenSdoRequest).S_BITNUM;
    let sdoData = [index & 0xFF, index >> 8, subIndex];
    sdoData.push((data >> 0) & 0xFF);
    sdoData.push((data >> 8) & 0xFF);
    sdoData.push((data >> 16) & 0xFF);
    sdoData.push((data >> 24) & 0xFF);
    super(nodeId, sdoHeader, sdoData);
  }
}

class CanOpenObject extends Object {
  static get ACCESS_TYPE_RO() { return "ro"; }
  static get ACCESS_TYPE_WO() { return "wo"; }
  static get ACCESS_TYPE_RW() { return "rw"; }<commit_msg>Adding CanOpenTimeOfDay class to websocketcanopen.js<commit_after>class WebSocketCanOpen extends WebSocketCan {
  messageHandler(handler) {
    return function(event) {
      let init = Object.assign({}, event);
      init.data = CanOpenMessage.from(new Uint8Array(event.data));
      handler(new MessageEvent(event.type, init));
    }
  }
}

class CanOpenMessage extends CanMessage {
  constructor(functionCode, nodeId, data=[]) {
    super((functionCode << 7) + nodeId, data, false, false, false);
  }

  static get FUNCTION_CODE_NMT() { return 0x0; }
  static get FUNCTION_CODE_SYNC() { return 0x1; }
  static get FUNCTION_CODE_EMCY() { return 0x1; }
  static get FUNCTION_CODE_TIME_STAMP() { return 0x2; }
  static get FUNCTION_CODE_TPDO1() { return 0x3; }
  static get FUNCTION_CODE_RPDO1() { return 0x4; }
  static get FUNCTION_CODE_TPDO2() { return 0x5; }
  static get FUNCTION_CODE_RPDO2() { return 0x6; }
  static get FUNCTION_CODE_TPDO3() { return 0x7; }
  static get FUNCTION_CODE_RPDO3() { return 0x8; }
  static get FUNCTION_CODE_TPDO4() { return 0x9; }
  static get FUNCTION_CODE_RPDO4() { return 0xA; }
  static get FUNCTION_CODE_SDO_TX() { return 0xB; }
  static get FUNCTION_CODE_SDO_RX() { return 0xC; }
  static get FUNCTION_CODE_NMT_ERROR_CONTROL() { return 0xE; }

  get functionCode() {
    return this.arbitrationId >> 7;
  }

  set functionCode(fc) {
    this.arbitrationId = ((fc & 0xF) << 7) + this.nodeId;
  }

  get nodeId() {
    return this.arbitrationId & 0x7F;
  }

  set nodeId(id) {
    this.arbitrationId = (this.functionCode << 7) + (id & 0x7F);
  }

  static from(byteArray) { // Factory from SocketCAN-formatted byte array
      let nodeId = byteArray[0] & 0x7F;
      let functionCode = byteArray[0] >> 7;
      functionCode += (byteArray[1] & 0x7) << 1;
      let dlc = byteArray[4];
      let data = byteArray.slice(8, 8 + dlc);
      return new this(functionCode, nodeId, data);
  }
}

class CanOpenNmtErrorControlMessage extends CanOpenMessage {
  constructor(nodeId, data) {
    super(CanOpenMessage.FUNCTION_CODE_NMT_ERROR_CONTROL, nodeId, data);
  }
}

class CanOpenBootupMessage extends CanOpenNmtErrorControlMessage {
  constructor(nodeId) {
    super(nodeId, [0]);
  }
}

class CanOpenHeartbeatMessage extends CanOpenNmtErrorControlMessage {
  constructor(nodeId, nmtState) {
    super(nodeId, [nmtState]);
  }
}

class CanOpenSdoMessage extends CanOpenMessage {
  constructor(functionCode, nodeId, sdoHeader, sdoData) {
    sdoData.unshift(sdoHeader);
    super(functionCode, nodeId, new Uint8Array(sdoData));
  }

  // Bit positions and masks
  static get CS_BITNUM() { return 5; }

  // Command specifiers
  static get CCS_DOWNLOAD_SEGMENT() { return 0; }
  static get CCS_DOWNLOAD_INITIATE() { return 1; }
  static get CCS_UPLOAD_INITIATE() { return 2; }
  static get CCS_UPLOAD_SEGMENT() { return 3; }
  static get CS_ABORT() { return 4; }
  static get SCS_UPLOAD_SEGMENT() { return 0; }
  static get SCS_DOWNLOAD_SEGMENT() { return 1; }
  static get SCS_UPLOAD_INITIATE() { return 2; }
  static get SCS_DOWNLOAD_INITIATE() { return 3; }

  // Derived properties
  get cs() { return (this.data[0] >> CanOpenSdoMessage.CS_BITNUM) & 0x7; }
}

const CanOpenSdoInitiateMixIn = superclass => class extends superclass {
  static get S_BITNUM() { return 0; }
  static get E_BITNUM() { return 1; }
  static get N_BITNUM() { return 2; }
  static get N_MASK() { return 0xC; }
  get s() { return (this.data[0] >> this.S_BITNUM) & 0x1; }
  get e() { return (this.data[0] >> this.E_BITNUM) & 0x1; }
  get n() { return (this.data[0] >> this.N_BITNUM) & 0x3; }
  get index() { return (this.data[2] << 8) + this.data[1]; }
  get subIndex() { return this.data[3]; }
};

const CanOpenSdoSegmentMixIn = superclass => class extends superclass {
  static get T_BITNUM() { return 4; }
  static get N_BITNUM() { return 1; }
  static get N_MASK() { return 0xE; }
  static get C_BITNUM() { return 0; }
  get t() { return (this.data[0] >> this.T_BITNUM) & 0x1; }
  get n() { return (this.data[0] >> this.N_BITNUM) & 0x7; }
  get c() { return (this.data[0] >> this.C_BITNUM) & 0x1; }
};

class CanOpenSdoRequest extends CanOpenSdoMessage {
  constructor(nodeId, sdoHeader, sdoData) {
    super(CanOpenMessage.FUNCTION_CODE_SDO_RX, nodeId, sdoHeader, sdoData);
  }
}

class CanOpenSdoResponse extends CanOpenSdoMessage {
  constructor(nodeId, sdoHeader, sdoData) {
    super(CanOpenMessage.FUNCTION_CODE_SDO_TX, nodeId, sdoHeader, sdoData);
  }
}

class CanOpenSdoAbortResponse extends CanOpenSdoResponse {

  // Abort codes
  static get ABORT_INVALID_CS() { return 0x05040001; }
  static get ABORT_WO() { return 0x06010001; }
  static get ABORT_RO() { return 0x06010002; }
  static get ABORT_OBJECT_DNE() { return 0x06020000; }
  static get ABORT_SUBINDEX_DNE() { return 0x06090011; }
  static get ABORT_GENERAL() { return 0x08000000; }
  
  constructor(nodeId, index, subIndex, abortCode) {
    let sdoHeader = CanOpenSdoMessage.CS_ABORT << CanOpenSdoMessage.CS_BITNUM;
    let sdoData = [index & 0xFF, index >> 8, subIndex];
    sdoData.push((abortCode >> 0) & 0xFF);
    sdoData.push((abortCode >> 8) & 0xFF);
    sdoData.push((abortCode >> 16) & 0xFF);
    sdoData.push((abortCode >> 24) & 0xFF);
    super(nodeId, sdoHeader, sdoData);
  }
}

class CanOpenSdoDownloadInitiateRequest extends CanOpenSdoInitiateMixIn(CanOpenSdoRequest) {
  constructor(nodeId, n, e, s, index, subIndex, data) {
    let sdoHeader = CanOpenSdoMessage.CCS_DOWNLOAD_INITIATE << CanOpenSdoMessage.CS_BITNUM;
    sdoHeader += n << CanOpenSdoInitiateMixIn(CanOpenSdoRequest).N_BITNUM;
    sdoHeader += e << CanOpenSdoInitiateMixIn(CanOpenSdoRequest).E_BITNUM;
    sdoHeader += s << CanOpenSdoInitiateMixIn(CanOpenSdoRequest).S_BITNUM;
    let sdoData = [index & 0xFF, index >> 8, subIndex];
    sdoData.push((data >> 0) & 0xFF);
    sdoData.push((data >> 8) & 0xFF);
    sdoData.push((data >> 16) & 0xFF);
    sdoData.push((data >> 24) & 0xFF);
    super(nodeId, sdoHeader, sdoData);
  }
}

class CanOpenSdoDownloadSegmentRequest extends CanOpenSdoSegmentMixIn(CanOpenSdoRequest) {
  constructor(nodeId, t, sdoData) {
    let sdoHeader = CanOpenSdoMessage.CCS_DOWNLOAD_SEGMENT << CanOpenSdoMessage.CS_BITNUM;
    sdoHeader += t << CanOpenSdoSegmentMixIn.T_BITNUM;
    sdoHeader += n << CanOpenSdoSegmentMixIn.N_BITNUM;
    sdoHeader += c << CanOpenSdoSegmentMixIn.C_BITNUM;
    super(nodeId, sdoHeader, sdoData);
  }
}

class CanOpenSdoDownloadSegmentResponse extends CanOpenSdoSegmentMixIn(CanOpenSdoResponse) {
  constructor(nodeId, t) {
    let sdoHeader = CanOpenSdoMessage.SCS_DOWNLOAD_SEGMENT << CanOpenSdoMessage.CS_BITNUM;
    sdoHeader += t << CanOpenSdoDownloadSegmentResponse.T_BITNUM;
    let sdoData = Array(7).fill(0x00);
    super(nodeId, sdoHeader, sdoData);
  }
}

class CanOpenSdoDownloadInitiateResponse extends CanOpenSdoInitiateMixIn(CanOpenSdoResponse) {
  constructor(nodeId, index, subIndex) {
    let sdoHeader = CanOpenSdoMessage.SCS_DOWNLOAD_INITIATE << CanOpenSdoMessage.CS_BITNUM;
    let sdoData = [index & 0xFF, index >> 8, subIndex, 0, 0, 0, 0];
    super(nodeId, sdoHeader, sdoData);
  }
}

class CanOpenSdoUploadInitiateRequest extends CanOpenSdoInitiateMixIn(CanOpenSdoRequest) {
  constructor(nodeId, index, subIndex) {
    let sdoHeader = CanOpenSdoMessage.CCS_UPLOAD_INITIATE << CanOpenSdoMessage.CS_BITNUM;
    let sdoData = [index & 0xFF, index >> 8, subIndex, 0 ,0 ,0 ,0];
    super(nodeId, sdoHeader, sdoData);
  }
}

class CanOpenSdoUploadInitiateResponse extends CanOpenSdoInitiateMixIn(CanOpenSdoResponse) {
  constructor(nodeId, n, e, s, index, subIndex, data) {
    let sdoHeader = CanOpenSdoMessage.SCS_UPLOAD_INITIATE << CanOpenSdoMessage.CS_BITNUM;
    sdoHeader += n << CanOpenSdoInitiateMixIn(CanOpenSdoRequest).N_BITNUM;
    sdoHeader += e << CanOpenSdoInitiateMixIn(CanOpenSdoRequest).E_BITNUM;
    sdoHeader += s << CanOpenSdoInitiateMixIn(CanOpenSdoRequest).S_BITNUM;
    let sdoData = [index & 0xFF, index >> 8, subIndex];
    sdoData.push((data >> 0) & 0xFF);
    sdoData.push((data >> 8) & 0xFF);
    sdoData.push((data >> 16) & 0xFF);
    sdoData.push((data >> 24) & 0xFF);
    super(nodeId, sdoHeader, sdoData);
  }
}

class CanOpenSdoUploadSegmentRequest extends CanOpenSdoSegmentMixIn(CanOpenSdoRequest) {
  constructor(nodeId, t) {
    let sdoHeader = CanOpenSdoMessage.CCS_UPLOAD_SEGMENT << CanOpenSdoMessage.CS_BITNUM;
    sdoHeader += t << CanOpenSdoUploadSegmentRequest.T_BITNUM;
    let sdoData = Array(7).fill(0x00);
    super(nodeId, sdoHeader, sdoData);
  }
}

class CanOpenSdoUploadSegmentResponse extends CanOpenSdoSegmentMixIn(CanOpenSdoResponse) {
  constructor(nodeId, t, n, c, sdoData) {
    let sdoHeader = CanOpenSdoMessage.SCS_UPLOAD_SEGMENT << CanOpenSdoMessage.CS_BITNUM;
    sdoHeader += t << CanOpenSdoSegmentMixIn.T_BITNUM;
    sdoHeader += n << CanOpenSdoSegmentMixIn.N_BITNUM;
    sdoHeader += c << CanOpenSdoSegmentMixIn.C_BITNUM;
    super(nodeId, sdoHeader, sdoData);
  }
}

class CanOpenTimeOfDay {
  static get EPOCH() { return new Date("01 Jan 1984 00:00:00 GMT"); }

  constructor(days, milliseconds) {
     this.days = days;
     this.milliseconds = milliseconds;
  }

  [Symbol.iterator]() {
    let tod = this;
    return {
      next() {
        switch(this._cursor++) {
          case 0: return {value: tod.milliseconds && 0xFF, done: false};
          case 1: return {value: (tod.milliseconds >> 8) & 0xFF, done: false};
          case 2: return {value: (tod.milliseconds >> 16) & 0xFF,done: false};
          case 3: return {value: tod.milliseconds >> 24, done: false};
          case 4: return {value: tod.days & 0xFF, done: false};
          case 5: return {value: tod.days >> 8, done: false};
          case 6:
            this._cursor = 0;
            return {done: true};
          default:
        }
      },
      _cursor: 0
    }
  }

  toDate() {
    let d = CanOpenTimeOfDay.EPOCH;
    d.setDate(d.getDate() + this.days);
    d.setMilliseconds(this.milliseconds);
    return d;
  }

  static from(byteArray) {
    let milliseconds = byteArray[0];
    milliseconds += byteArray[1] << 8;
    milliseconds += byteArray[2] << 16;
    milliseconds += (byteArray[3] & 0x0F) << 24;
    let days = byteArray[4];
    days += byteArray[5] << 8;
    return new this(days, milliseconds);
  }

  static fromDate(d) {
    let milliseconds = (d - this.EPOCH);
    let days = Math.floor(milliseconds / 1000 / 3600 / 24);
    milliseconds -= days * 24 * 3600 * 1000;
    return new this(days, milliseconds);
  }
}

class CanOpenObject extends Object {
  static get ACCESS_TYPE_RO() { return "ro"; }
  static get ACCESS_TYPE_WO() { return "wo"; }
  static get ACCESS_TYPE_RW() { return "rw"; }
{'fraction_non_alphanumeric': 0.12093942054433714, 'fraction_numerical': 0.026284021071115014, 'mean_word_length': 4.151215375918598, 'pattern_counts': {'":': 0, '<': 99, '<?xml version=': 0, '>': 119, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 7, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7631255', 'n_tokens_mistral': 6949, 'n_tokens_neox': 6632, 'n_words': 1449}