      example => d/mode/3?type=INPUT
    */
   {"d/mode/", &switchPinModeTask},
+
+
+  /*
+     attachInterrupt
+     format  => d/int/on/{num}?type={type}
+     {num}   => number of interrupt.
+     {type}  => LOW | CHANGE | RISING | FALLING
+     example => d/int/on/0?type=LOW
+
+     LOW ピンがLOWのとき発生
+     CHANGE ピンの状態が変化したときに発生
+     RISING ピンの状態がLOWからHIGHに変わったときに発生
+     FALLING ピンの状態がHIGHからLOWに変わったときに発生
+
+     // TODO: typeじゃなくてmodeにしたい
+   */
+  {"d/int/on/", &attachInterruptTask},
+
+
+  /*
+     detachInterrupt
+     format  => d/int/off/{num}
+     {num}   => number of interrupt.
+     example => d/int/off/0
+   */
+  {"d/int/off/", &detachInterruptTask},
 
   /*
     DI連続転送ON

  {"EXTERNAL", EXTERNAL}
};

#endif

const prog_char ILLEGAL_COMMAND[] PROGMEM       = "Illegal command.";

  return NULL;
}

// {port}?type={type string}なqueryを分解.
// typeのバッファに16文字コピーを行うので、
// typeのバッファサイズは16以上にすること。
// またtypeの文字列は16文字未満の文字列とすること.
char* checkPortWithType(String portWithType, uint8_t *port, char *type){
  String typeQuery;

  char* error = checkPortWithQuery(portWithType, port, &typeQuery);
  if(error){
    return error;
  }

  if(typeQuery.startsWith("type=")){
    typeQuery.replace("type=", "");
    if(typeQuery.length() > 16){
      return NgReturnJson(ILLEGAL_QUERY);
    }
    typeQuery.toCharArray(type, 16);
  }else{
    return NgReturnJson(ILLEGAL_QUERY);
  }
  return NULL;
}

char* checkPortWithValue(String portWithValue, uint8_t *port, int *val){

  String valQuery;
