⬇️MClimate Wireless Thermostat Downlink encoder

Universal Encoder:

Supports: The Thinks Network, Milesight

// Milesight
function Encode(port, obj) {
  return encodeDownlink({ fPort: port, data: obj }).bytes;
}

function Encoder(port, obj) {
  return Encode(port, obj);
}

// The Things Industries / Main
function encodeDownlink(input) {
  var bytes = [];
  var data = (input && input.data) ? input.data : {};

  for (var key in data) {
    if (!data.hasOwnProperty(key)) continue;

    switch (key) {
      case "setKeepAlive": {
        bytes.push(0x02);
        bytes.push(data.setKeepAlive & 0xFF);
        break;
      }
      case "getKeepAliveTime": {
        bytes.push(0x12);
        break;
      }
      case "getDeviceVersions": {
        bytes.push(0x04);
        break;
      }

      case "setTargetTemperature": {
        var t = data.setTargetTemperature;     // e.g. 20
        var v = Math.round(t * 10) & 0xFFFF;   // 20.0 -> 200 (0x00C8)

        bytes.push(0x2E);
        bytes.push((v >> 8) & 0xFF);           // high byte
        bytes.push(v & 0xFF);                  // low byte
        break;
      }

      case "getTargetTemperature": {
        bytes.push(0x2F);
        break;
      }

      case "setKeysLock": {
        bytes.push(0x07);
        bytes.push(data.setKeysLock & 0xFF);
        break;
      }
      case "getKeysLock": {
        bytes.push(0x14);
        break;
      }

      case "setTemperatureRange": {
        bytes.push(0x08);
        bytes.push(data.setTemperatureRange.min & 0xFF);
        bytes.push(data.setTemperatureRange.max & 0xFF);
        break;
      }
      case "getTemperatureRange": {
        bytes.push(0x15);
        break;
      }

      case "setJoinRetryPeriod": {
        var periodToPass = (data.setJoinRetryPeriod * 60) / 5;
        periodToPass = Math.floor(periodToPass);
        if (periodToPass < 0) periodToPass = 0;
        if (periodToPass > 255) periodToPass = 255;

        bytes.push(0x10);
        bytes.push(periodToPass & 0xFF);
        break;
      }
      case "getJoinRetryPeriod": {
        bytes.push(0x19);
        break;
      }

      case "setUplinkType": {
        bytes.push(0x11);
        bytes.push(data.setUplinkType & 0xFF);
        break;
      }
      case "getUplinkType": {
        bytes.push(0x1B);
        break;
      }

      case "setWatchDogParams": {
        bytes.push(0x1C);
      }
      case "getWatchDogParams": {
        bytes.push(0x1D);
        break;
      }

      case "restartDevice": {
        bytes.push(0xA5);
        break;
      }

      case "sendCustomHexCommand": {
        var hex = data.sendCustomHexCommand;
        for (var i = 0; i < hex.length; i += 2) {
          var b = parseInt(hex.substr(i, 2), 16);
          bytes.push(b & 0xFF);
        }
        break;
      }

      default: {
        break;
      }
    }
  }

  return {
    bytes: bytes,
    fPort: 1,
    warnings: [],
    errors: [],
  };
}

function decodeDownlink(input) {
  return {
    data: { bytes: input.bytes },
    warnings: [],
    errors: [],
  };
}

// Example downlink commands
// {"setTargetTemperature":20} --> 2E00C8
// {"setTemperatureRange":{"min":15,"max":21}} --> 080F15
// {"sendCustomHexCommand":"080F15"} --> 080F15

Last updated

Was this helpful?