Copyright Micropelt

Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 9 Next »

Milesight Codec Uplink Decoder

function get_user_mode(input) {
  var user_mode = input[9] & 0x7;
  switch (user_mode) {
    case 0:
      return "Valve_Position";
    case 1:
      return "RESERVED";
    case 2:
      return "SP_Ambient_Temperature";
    case 3:
      return "Detecting_Opening_Point";
    case 4:
      return "Slow_Harvesting";
    case 5:
      return "Temperature_Drop";
    case 6:
      return "Freeze_Protect";
    case 7:
      return "Forced_Heating";
    default:
      return "Unknown Operating Mode";
  }
}

function get_user_value(input) {
  var user_mode = get_user_mode(input);
  switch (user_mode) {
    case "Valve_Position":
    case "Freeze_Protect":
    case "Forced_Heating":
      return input[10];
    case "SP_Ambient_Temperature":
      return input[10] * 0.5;
    case "Detecting_Opening_Point":
    case "Slow_Harvesting":
      return input[10] * 0.25;
    default:
      return "Invalid User Mode";
  }
}

function decode_port_1(bytes) {
  var output = {};
  {
    
    output.DEV_EUI = LoRaObject.devEUI;
    output.RSSI = LoRaObject.rxInfo[0].rssi;
    output.SNR = LoRaObject.rxInfo[0].loRaSNR;
    output.Data = LoRaObject.data;
    output.ADR = LoRaObject.txInfo.adr;
    output.coderate = LoRaObject.txInfo.codeRate;
    output.FCnt = LoRaObject.fCnt;
    output.Port = LoRaObject.fPort;
    output.Frequency = LoRaObject.txInfo.frequency;
    output.Modulation = LoRaObject.txInfo.dataRate.modulation;
    output.Bandwidth = LoRaObject.txInfo.dataRate.bandwidth;
    output.SpreadingFactor = LoRaObject.txInfo.dataRate.spreadFactor;

    output.Current_Valve_Position = bytes[0];
    output.Flow_Sensor_Raw = bytes[1] * 0.5;
    output.Flow_Temperature = bytes[2] * 0.5;
    output.Ambient_Sensor_Raw = bytes[3] * 0.25;
    output.Ambient_Temperature = bytes[4] * 0.25;
    output.Energy_Storage = bytes[5] >> 6 & 0x01;
    output.Harvesting_Active = bytes[5] >> 5 & 0x01;
    output.Ambient_Sensor_Failure = bytes[5] >> 4 & 0x01;
    output.Flow_Sensor_Failure = bytes[5] >> 3 & 0x01;
    output.Radio_Communication_Error = bytes[5] >> 2 & 0x01;
    output.Received_Signal_Strength = bytes[5] >> 1 & 0x01;
    output.Motor_Error = bytes[5] >> 0 & 0x01;
    output.Storage_Voltage = Number((bytes[6] * 0.02).toFixed(2));
    output.Average_Current_Consumed = bytes[7] * 10;
    output.Average_Current_Generated = bytes[8] * 10;
    output.Operating_Condition= bytes[9] >> 7 & 0x01,
    output.Storage_Fully_Charged= bytes[9] >> 6 & 0x01,
    output.Zero_Error= bytes[9] >> 5 & 0x01,
    output.Calibration_OK= bytes[9] >> 4 & 0x01,

    output.User_Mode = get_user_mode(bytes);
    output.User_Value = get_user_value(bytes);
  }

  return output;
}

function decode_port_2(bytes) {
  var output = {};
  {
    var REV_Major = (bytes[0] & 0xF).toString();
    var REV_Minor = ((bytes[0] >> 4) & 0xF).toString(16);
    output.REV = REV_Major + "." + REV_Minor;
  }
  {
    var HW_Major = (bytes[1] & 0xF).toString();
    var HW_Minor = ((bytes[1] >> 4) & 0xF).toString();
    output.HW = HW_Major + "." + HW_Minor;
  }
  {
    var FW_Year = bytes[2].toString();
    var FW_Month = bytes[3].toString();
    var FW_Day = bytes[4].toString();
    var FW_Minor = bytes[5].toString();
    output.FW = "20" + FW_Year + "." + FW_Month + "." + FW_Day + "." + FW_Minor;
  }
  return output;
}

function decode_port_3(bytes) {
  var output = {};
  switch (bytes[0]) {
    case 0:
      output.motor_range = 2.56048;
      break;
    case 7:
      output.motor_range = 1.456;
      break;
    case 8:
      output.motor_range = 1.664;
      break;
    case 9:
      output.motor_range = 1.872;
      break;
    case 10:
      output.motor_range = 2.080;
      break;
    case 11:
      output.motor_range = 2.288;
      break;
    case 12:
      output.motor_range = 2.496;
      break;
    default:
      output.motor_range = 0;
      break;
  }
  return output;
}

function Decode(fPort, bytes) {
  var output = {};
  switch (fPort) {
    case 1:
      output = decode_port_1(bytes);
      break;
    case 2:
      output = decode_port_2(bytes);
      break;
    case 3:
      output = decode_port_3(bytes);
      break;
    default:
      return {
        errors: ['unknown FPort'],
      };
  }
  return output;
}

Milesight Codec Downlink Encoder

// Possible Options:
// userMode          : "Ambient_Temperature" or "Valve_Position"
// setValue          : 0 to 40  (0.5° resolution) for "Ambient_Temperature"
// setValue          : 0 to 100 (1% resolution)   for "Valve_Position"

// safetyMode        : "Ambient_Temperature" or "Valve_Position"
// safetyValue       : 0 to 40  (0.5° resolution) for "Ambient_Temperature"
// safetyValue       : 0 to 100 (1% resolution)   for "Valve_Position"

// roomTemperature   : 0 (Internal Ambient Estimate) or Temperature from External Sensor (0.25° resolution)
// radioInterval     : 5 or 10 or 60 or 120 or 480 (minutes)
// doReferenceRunNow : 0 or 1 (0-False; 1-True)

function Encode(fPort, obj)  {
    var mode = obj.userMode; // "Ambient_Temperature" or "Valve_Position"
    var safetyMode = obj.safetyMode; // "Ambient_Temperature" or "Valve_Position"
    var setValue = obj.setValue; // 0-40 for Ambient_Temperature, 0-100 for Valve_Position
    var roomTemperature = obj.roomTemperature; // 0-40
    var safetyValue = obj.safetyValue; // 0-40 for Ambient_Temperature, 0-100 for Valve_Position
    var radioInterval = obj.radioInterval; // 5, 10, 60, 120, 480
    var doReferenceRunNow = obj.doReferenceRunNow; // 0 or 1
  
    var bytes = [0, 0, 0, 0, 0, 0];
  
    // Byte 1: Set value
    if (typeof setValue === "undefined") {
        throw new Error("Invalid setValue");
    }
    else if (mode === "Ambient_Temperature") {
        if (setValue < 0 || setValue > 40) {
          throw new Error("Set value out of range for ambient mode");
        }
        else {
          bytes[0] = setValue *2;
        }         
    } else if (mode === "Valve_Position") {
        if (setValue < 0 || setValue > 100) {
          throw new Error("Set value out of range for valve mode");
        } 
        else {
          bytes[0] = setValue;
        }
    }
  
    // Byte 2: Room temperature (0-40)
    if (roomTemperature < 0 || roomTemperature > 40) {
      throw new Error("Room temperature out of range");
    }
    else if (typeof roomTemperature === "undefined") {
      throw new Error("Invalid roomTemperature");
    }
    else {
        bytes[1] = roomTemperature * 4;
    }
  
    // Byte 3: Safety value
    if (typeof safetyValue === "undefined") {
        throw new Error("Invalid safetyValue");
    }
    else if (safetyMode === "Ambient_Temperature") {
        if (safetyValue < 0 || safetyValue > 40) {
          throw new Error("Safety value out of range for ambient mode");
        } 
        else {
          bytes[2] = safetyValue * 2;
        }
    } else if (safetyMode === "Valve_Position") {
        if (safetyValue < 0 || safetyValue > 100) {
          throw new Error("Safety value out of range for valve mode");
        } 
        else {
          bytes[2] = safetyValue;
        }
    }
  
    // Byte 4: Radio interval, user mode, safety mode
    var radioBits;
    switch (radioInterval) {
        case 5:
            radioBits = 1 << 4; // Radio interval 5 minutes
            break;
        case 10:
            radioBits = 0 << 4; // Radio interval 10 minutes
            break;
        case 60:
            radioBits = 2 << 4; // Radio interval 60 minutes
            break;
        case 120:
            radioBits = 3 << 4; // Radio interval 120 minutes
            break;
        case 480:
            radioBits = 4 << 4; // Radio interval 480 minutes
            break;
        default:
            throw new Error("Invalid radioInterval");
    }
  
    var userModeBits;
    if (mode === "Ambient_Temperature") {
        userModeBits = 2 << 2; // User mode "Ambient_Temperature" in bits 3 and 4
    } else if (typeof mode === "undefined") {
        throw new Error("Invalid userMode");
    }
    else if (mode === "Valve_Position") {
        userModeBits = 0 << 2; // User mode "Valve_Position" in bits 3 and 4
    }
  
    var safetyModeBits;
    if (safetyMode === "Ambient_Temperature") {
        safetyModeBits = 0 << 0; // Safety mode "Ambient_Temperature" in bits 1 and 2
    } else if (typeof safetyMode === "undefined") {
        throw new Error("Invalid safetyMode");
    }
    else if (safetyMode === "Valve_Position") {
        safetyModeBits = 2 << 0; // Safety mode "Valve_Position" in bits 1 and 2
    }
  
    bytes[3] = radioBits | userModeBits | safetyModeBits;
  
    // Byte 5: Reserved (set to 0)
    bytes[4] = 0;
  
    // Byte 6: doReferenceRunNow bit (bit 8)
    if (doReferenceRunNow < 0 || doReferenceRunNow > 1) {
      throw new Error("Invalid doReferenceRunNow value");
    }
    else if (typeof doReferenceRunNow === "undefined") {
        throw new Error("Invalid doReferenceRunNow");
    }
    else {
      bytes[5] = doReferenceRunNow << 7;
    }
  
    return bytes;
  }

Downlink example

// Example 1
{
      "userMode": "Valve_Position",
      "setValue": 42,
      "roomTemperature": 0,
      "safetyMode": "Ambient_Temperature",
      "safetyValue": 19,
      "radioInterval": 5, 
      "doReferenceRunNow": 1
}

// Example 2
{
      "userMode": "Ambient_Temperature",
      "setValue": 21.5,
      "roomTemperature": 24,
      "safetyMode": "Valve_Position",
      "safetyValue": 0,
      "radioInterval": 60, 
      "doReferenceRunNow": 0
}

// Example 3
{
      "userMode": "Valve_Position",
      "setValue": 36,
      "roomTemperature": 0,
      "safetyMode": "Valve_Position",
      "safetyValue": 21,
      "radioInterval": 5, 
      "doReferenceRunNow": 1 
}

// Example 4
{
      "userMode": "Ambient_Temperature",
      "setValue": 20.5,
      "roomTemperature": 23.75,
      "safetyMode": "Ambient_Temperature",
      "safetyValue": 18,
      "radioInterval": 10, 
      "doReferenceRunNow": 0 
}

  • No labels