Adding wavlength tuning via GUI

Change-Id: Ic82330ebb337aa8ce0b26ecdabff6d4211ac4a5e
(cherry picked from commit 6ac13ff484c70a9da6633e21dcb585c682b41c2f)
diff --git a/apps/optical-model/src/main/java/org/onosproject/net/optical/cli/PortWaveLengthCommand.java b/apps/optical-model/src/main/java/org/onosproject/net/optical/cli/PortWaveLengthCommand.java
index 568df72..74173e5 100644
--- a/apps/optical-model/src/main/java/org/onosproject/net/optical/cli/PortWaveLengthCommand.java
+++ b/apps/optical-model/src/main/java/org/onosproject/net/optical/cli/PortWaveLengthCommand.java
@@ -67,7 +67,7 @@
     private static final String CH_25 = "25";
     private static final String CH_50 = "50";
     private static final String CH_100 = "100";
-    public static final long BASE_FREQUENCY = 193100000;   //Working in Mhz
+    private static final long BASE_FREQUENCY = 193100000;   //Working in Mhz
 
     private static final Map<String, ChannelSpacing> CHANNEL_SPACING_MAP = ImmutableMap
             .<String, ChannelSpacing>builder()
@@ -135,7 +135,7 @@
             GridType gridType = ochPort.lambda().gridType();
             ChannelSpacing channelSpacing = ochPort.lambda().channelSpacing();
             int slotGranularity = ochPort.lambda().slotGranularity();
-            int multiplier = getMultplier(wavelength, gridType, channelSpacing, slotGranularity);
+            int multiplier = getMultplier(wavelength, gridType, channelSpacing);
             return new OchSignal(gridType, channelSpacing, multiplier, slotGranularity);
         } else {
             print("Connect point %s is not OChPort", cp);
@@ -144,7 +144,7 @@
 
     }
 
-    private int getMultplier(long wavelength, GridType gridType, ChannelSpacing channelSpacing, int slotGranularity) {
+    private int getMultplier(long wavelength, GridType gridType, ChannelSpacing channelSpacing) {
         long baseFreq;
         switch (gridType) {
             case DWDM:
diff --git a/apps/roadm/app/src/main/java/org/onosproject/roadm/RoadmManager.java b/apps/roadm/app/src/main/java/org/onosproject/roadm/RoadmManager.java
index d6812ba..73ea721 100644
--- a/apps/roadm/app/src/main/java/org/onosproject/roadm/RoadmManager.java
+++ b/apps/roadm/app/src/main/java/org/onosproject/roadm/RoadmManager.java
@@ -27,7 +27,6 @@
 import org.onosproject.net.Direction;
 import org.onosproject.net.ModulationScheme;
 import org.onosproject.net.OchSignal;
-import org.onosproject.net.OchSignalType;
 import org.onosproject.net.Port;
 import org.onosproject.net.PortNumber;
 import org.onosproject.net.behaviour.LambdaQuery;
@@ -348,8 +347,6 @@
 
         TrafficSelector selector = DefaultTrafficSelector.builder()
                 .add(Criteria.matchInPort(inPort))
-                .add(Criteria.matchOchSignalType(OchSignalType.FIXED_GRID))
-                .add(Criteria.matchLambda(ochSignal))
                 .build();
         TrafficTreatment treatment = DefaultTrafficTreatment.builder()
                 .add(Instructions.modL0Lambda(ochSignal))
diff --git a/apps/roadm/app/src/main/java/org/onosproject/roadm/RoadmPortViewMessageHandler.java b/apps/roadm/app/src/main/java/org/onosproject/roadm/RoadmPortViewMessageHandler.java
index 3a648c4..f87bb07 100644
--- a/apps/roadm/app/src/main/java/org/onosproject/roadm/RoadmPortViewMessageHandler.java
+++ b/apps/roadm/app/src/main/java/org/onosproject/roadm/RoadmPortViewMessageHandler.java
@@ -70,6 +70,8 @@
     private static final String ROADM_SET_TARGET_POWER_RESP = "roadmSetTargetPowerResponse";
     private static final String ROADM_SET_MODULATION_REQ = "roadmSetModulationRequest";
     private static final String ROADM_SET_MODULATION_RESP = "roadmSetModulationResponse";
+    private static final String ROADM_SET_FREQ_REQ = "roadmSetFrequencyRequest";
+    private static final String ROADM_SET_FREQ_RESP = "roadmSetFrequencyResponse";
     private static final String ROADM_SYNC_TARGET_POWER_REQ = "roadmSyncTargetPowerRequest";
     private static final String ROADM_SYNC_TARGET_POWER_RESP = "roadmSyncTargetPowerResp";
     private static final String ROADM_SHOW_ITEMS_REQ = "roadmShowPortItemsRequest";
@@ -118,7 +120,8 @@
                 new CreateShowItemsRequestHandler(),
                 new CreateOpsModeSetRequestHandler(),
                 new SyncTargetPowerRequestHandler(),
-                new SetModulationRequestHandler()
+                new SetModulationRequestHandler(),
+                new SetFrequencyRequestHandler()
         );
     }
 
@@ -346,6 +349,34 @@
         }
     }
 
+    // Handler for setting port frequency
+    private final class SetFrequencyRequestHandler extends RequestHandler {
+
+        private static final String TARGET_FREQ_MSG = "Target frequency is %s.";
+
+        private SetFrequencyRequestHandler() {
+            super(ROADM_SET_FREQ_REQ);
+        }
+
+        @Override
+        public void process(ObjectNode payload) {
+            DeviceId deviceId = DeviceId.deviceId(string(payload, RoadmUtil.DEV_ID));
+            PortNumber portNumber = PortNumber.portNumber(payload.get(ID).asLong());
+            String frequency = payload.get(CURR_FREQ).asText();
+            double freqThz = Double.parseDouble(frequency);
+            Frequency freq = Frequency.ofTHz(freqThz);
+            OchSignal ochSignal = RoadmUtil.createOchSignalFromWavelength(freq.asMHz(), deviceService,
+                    deviceId, portNumber);
+            roadmService.createConnection(deviceId, 100, true, 0,
+                    portNumber, portNumber, ochSignal);
+            ObjectNode rootNode = objectNode();
+            rootNode.put(ID, payload.get(ID).asText());
+            rootNode.put(RoadmUtil.VALID, frequency);
+            rootNode.put(RoadmUtil.MESSAGE, String.format(TARGET_FREQ_MSG, frequency));
+            sendMessage(ROADM_SET_FREQ_RESP, rootNode);
+        }
+    }
+
     // Protection switch operation type and path index
     private static final String OPS_ARRAY_INDEX = "index";
     private static final String OPS_ARRAY_OPERATION = "operation";
diff --git a/apps/roadm/app/src/main/java/org/onosproject/roadm/RoadmUtil.java b/apps/roadm/app/src/main/java/org/onosproject/roadm/RoadmUtil.java
index a20b400..73a2dba 100644
--- a/apps/roadm/app/src/main/java/org/onosproject/roadm/RoadmUtil.java
+++ b/apps/roadm/app/src/main/java/org/onosproject/roadm/RoadmUtil.java
@@ -17,6 +17,17 @@
 
 import org.onlab.util.Frequency;
 import org.onosproject.net.Annotations;
+import org.onosproject.net.ChannelSpacing;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.GridType;
+import org.onosproject.net.OchSignal;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.optical.OchPort;
+import org.onosproject.net.optical.device.OchPortHelper;
+
+import java.util.Optional;
 
 import static com.google.common.base.Strings.isNullOrEmpty;
 
@@ -36,6 +47,8 @@
     public static final String OPS_OPT_AUTO = "AUTOMATIC";
     public static final String OPS_OPT_FORCE = "FORCE";
     public static final String OPS_OPT_MANUAL = "MANUAL";
+    private static final long BASE_FREQUENCY = 193100000;   //Working in Mhz
+
 
     private RoadmUtil() {
     }
@@ -104,4 +117,45 @@
     public static String getAnnotation(Annotations annotations, String key) {
         return getAnnotation(annotations, key, NA);
     }
+
+    public static OchSignal createOchSignalFromWavelength(double wavelength, DeviceService deviceService,
+                                                          DeviceId deviceId, PortNumber portNumber) {
+        if (wavelength == 0L) {
+            return null;
+        }
+        Port port = deviceService.getPort(deviceId, portNumber);
+        Optional<OchPort> ochPortOpt = OchPortHelper.asOchPort(port);
+
+        if (ochPortOpt.isPresent()) {
+            OchPort ochPort = ochPortOpt.get();
+            GridType gridType = ochPort.lambda().gridType();
+            ChannelSpacing channelSpacing = ochPort.lambda().channelSpacing();
+            int slotGranularity = ochPort.lambda().slotGranularity();
+            int multiplier = getMultplier(wavelength, gridType, channelSpacing);
+            return new OchSignal(gridType, channelSpacing, multiplier, slotGranularity);
+        } else {
+            return null;
+        }
+
+    }
+
+    private static int getMultplier(double wavelength, GridType gridType, ChannelSpacing channelSpacing) {
+        long baseFreq;
+        switch (gridType) {
+            case DWDM:
+                baseFreq = BASE_FREQUENCY;
+                break;
+            case CWDM:
+            case FLEX:
+            case UNKNOWN:
+            default:
+                baseFreq = 0L;
+                break;
+        }
+        if (wavelength > baseFreq) {
+            return (int) ((wavelength - baseFreq) / (channelSpacing.frequency().asMHz()));
+        } else {
+            return (int) ((baseFreq - wavelength) / (channelSpacing.frequency().asMHz()));
+        }
+    }
 }
\ No newline at end of file
diff --git a/apps/roadm/web/roadm-gui/projects/roadm-gui-lib/src/lib/port/port.component.html b/apps/roadm/web/roadm-gui/projects/roadm-gui-lib/src/lib/port/port.component.html
index 26420ca..0385b03 100644
--- a/apps/roadm/web/roadm-gui/projects/roadm-gui-lib/src/lib/port/port.component.html
+++ b/apps/roadm/web/roadm-gui/projects/roadm-gui-lib/src/lib/port/port.component.html
@@ -97,7 +97,12 @@
                     <td [ngClass]="(isDelta() ? 'delta' : '')">{{port.type=='OCH'?port.minFreq:""}}</td>
                     <td [ngClass]="(isDelta() ? 'delta' : '')">{{port.type=='OCH'?port.maxFreq:""}}</td>
                     <td [ngClass]="(isDelta() ? 'delta' : '')">{{port.type=='OCH'?port.grid:""}}</td>
-                    <td [ngClass]="(isDelta() ? 'delta' : '')">{{port.type=='OCH'?port.currFreq:""}}</td>
+                    <td [ngClass]="(isDelta() ? 'delta' : '')">
+                        <form [formGroup]="freqForm" (ngSubmit)="submitFrequency(devId, port.id)" *ngIf="port.type=='OCH'">
+                            <input type="text" style="width:50px" value="{{port.type=='OCH'?port.currFreq:''}}" formControlName="newFreq" required>
+                            <button type="submit">Submit</button>
+                        </form>
+                    </td>
                     <td [ngClass]="(isDelta() ? 'delta' : '')">
                         <form [formGroup]="modulationForm" (ngSubmit)="submitModulation(devId, port.id)" *ngIf="port.type=='OCH'">
                             <select [(ngModel)]="port.modulation" formControlName="newModulation">
diff --git a/apps/roadm/web/roadm-gui/projects/roadm-gui-lib/src/lib/port/port.component.ts b/apps/roadm/web/roadm-gui/projects/roadm-gui-lib/src/lib/port/port.component.ts
index 56bd85c..9af7bf7 100644
--- a/apps/roadm/web/roadm-gui/projects/roadm-gui-lib/src/lib/port/port.component.ts
+++ b/apps/roadm/web/roadm-gui/projects/roadm-gui-lib/src/lib/port/port.component.ts
@@ -81,9 +81,11 @@
 
     powerForm: FormGroup;
     modulationForm: FormGroup;
+    freqForm: FormGroup;
     SET_POWER_REQ = 'roadmSetTargetPowerRequest';
     SET_POWER_RESP = 'roadmSetTargetPowerResponse';
     SET_MODULATION = 'roadmSetModulationRequest';
+    SET_FREQUENCY = 'roadmSetFrequencyRequest';
 
     restorePrefsConfig; // Function
 
@@ -135,6 +137,9 @@
         this.modulationForm = new FormGroup({
             newModulation: new FormControl(''),
         });
+        this.freqForm = new FormGroup({
+            newFreq: new FormControl(''),
+        });
         this.log.debug('Create Forms');
     }
 
@@ -223,6 +228,15 @@
         });
     }
 
+    submitFrequency(devId, port) {
+        this.log.debug('Set Frequency of port ', port, 'in device ', devId, 'as value ', this.freqForm.value['newFreq']);
+        this.wss.sendEvent(this.SET_FREQUENCY, {
+            'currFreq': this.freqForm.value['newFreq'],
+            'devId': devId,
+            'id': port,
+        });
+    }
+
     powerConfigCb(data) {
         if (!data.valid) {
             const info = 'The power config operation is failed. The reason is: \n' + data.message;