   cutover.inputMin= RECEIVER_INPUT_MAX;
 }
 
+//Processes received JSON for a given servo (e.g. ServoData struct)
+//The inputISR is the interrupt service routine function for triggering action upon receiver input
+void processServoJson(JsonObject& servoJson, ServoData& servoData, const char servoType[], void inputISR(), const char servoError[]) {
+  if (!receiverControl) {
+    //Check for any output configuration parameters for this servo
+    if (servoJson.containsKey("outputConfig")) {
+      JsonObject& outputConfig = servoJson["outputConfig"];
+      if (outputConfig.containsKey("max")) {
+        servoData.outputMax = (byte) outputConfig["max"];
+      }
+      if (outputConfig.containsKey("min")) {
+        servoData.outputMin = (byte) outputConfig["min"];
+      }
+      if (outputConfig.containsKey("pin")) {
+        if (servoData.servo.attached()) servoData.servo.detach();
+        byte servoOutPin = (byte) outputConfig["pin"];
+        servoData.servo.attach(servoOutPin);
+      }
+    }
+    //Check for any input configuration parameters for this servo
+    if (servoJson.containsKey("inputConfig")) {
+      JsonObject& inputConfig = servoJson["inputConfig"];
+      if (inputConfig.containsKey("max")) {
+        servoData.inputMax = (uint16_t) inputConfig["max"];
+      }
+      if (inputConfig.containsKey("min")) {
+        servoData.inputMin = (uint16_t) inputConfig["min"];
+      }
+      if (inputConfig.containsKey("pin")) {
+        if (servoData.inputPin != BYTE_MAX) PCintPort::detachInterrupt(servoData.inputPin);
+        servoData.inputPin = (byte) inputConfig["pin"];
+        PCintPort::attachInterrupt(servoData.inputPin, inputISR, CHANGE);
+      }
+      if (inputConfig.containsKey("receiverOnly")) {
+        servoData.receiverInputOnly = (boolean) inputConfig["receiverOnly"];
+      }
+    }
+    //Only write to servo if the phone input for this servo has permission to do so
+    if (!servoData.receiverInputOnly) {
+      //Check for any servo output values to write to the servo
+      if (servoJson.containsKey("value")) {
+        if (servoData.servo.attached()) {
+          byte value = (byte) servoJson["value"];
+          servoData.servo.write(value);
+          sendJsonServoOutput(servoType, value);
+        } else {
+          sendJsonString("error", servoError);
+        }
+      }
+    }
+  } else {
+    sendJsonString("error", "Disable receiver control to configure servos");
+  }
+}
+
 //Interrupt Service Routine (ISR) for aileron receiver input
 void listenForAileron() {
   static uint32_t aileronInStart;


//Determines whether a given value is valid receiver input
boolean isValidReceiverInput(uint16_t receiverInput) {
  if (receiverInput < RECEIVER_INPUT_MAX && receiverInput > RECEIVER_INPUT_MIN) return true;
  return false;
}

//Processes receiver input for a given servo and writes the converted output to the servo

//TODO use better calibration default
const int RECEIVER_INPUT_DEFAULT = 1500;

//Allowed distance from the default for a valid receiver input value
const int RECEIVER_INPUT_DISTANCE = 800;

//Min and max possible values to filter for receiver servo input
const int RECEIVER_INPUT_MAX = RECEIVER_INPUT_DEFAULT + RECEIVER_INPUT_DISTANCE;
const int RECEIVER_INPUT_MIN = RECEIVER_INPUT_DEFAULT - RECEIVER_INPUT_DISTANCE;

//Sets the baud rate of the Arduino
const long BAUD_RATE = 115200;
