code: function validateMsg(node, msg) {
      var validMsg = true;
  
      if (!(typeof msg.payload === "object")) {
        node.error(RED._("blindcontroller.error.invalid-msg-payload"), msg);
        validMsg = false;
      } else {
        switch (msg.topic) {
          case "sun":
            validMsg = validateSunPositionMsg(node, msg);
            break;
          case "blindPosition":
            validMsg = validateBlindPositionMsg(node, msg);
            break;
          case "blindPositionReset":
            validMsg = validateBlindPositionResetMsg(node, msg);
            break;
          case "blind":
            validMsg = validateBlindMsg(node, msg);
            break;
          case "weather":
            validMsg = validateWeatherMsg(node, msg);
            break;
          case "mode":
            validMsg = validateModeMsg(node, msg);
            break;
          default:
            node.error(
              RED._("blindcontroller.error.unknown-msg-topic") + msg.topic,
              msg
            );
            validMsg = false;
        }
      }
      return validMsg;
    }
docs: /*
  Tests the validity of the input msg.payload before using this payload to
  run the calculation.  As the node consumes 4 different message type, the
  topic is used as the mechanism of identifying the type.  The validations
  differ for each message type.
  
  The validations performed are:
  - existence of mandatory properties e.g. channel must exist
  - range checks on property values e.g. orientation should be a value
  between 0 and 360 inclusive
  - consistency checks between property values e.g. bottom of window should
  be higher than the top