Hello Community,
I'm having problems with preselecting a script for the measurements points. Basically what needs to be done is to check through the protocol if certain script is present, and if it is to set it up, if it is not, to leave the field as blank. Would this be possible to do?
Thanks.
Hi Miguel,
the user is supplying the script and there are cases when it will not be present.
Hi Amar,
But if the script was already provided, it will stay in the cluster unless it is intentionally removed by the user. Maybe I am missing something else?
Could it be the case that the user provides a script with a different name every time?
Hi Amar, I've used the below code in a connector QAction to create a traditional measurement point with parameter sets, based on data from a table. With some modifications to fill in the ScriptInfo property instead, I believe it should also be usable for your case.
Note that this code uses some internal SLNet calls and we do not recommend using this, as it is not officially supported and we cannot guarantee that it will still work in the future. As a rule, you should avoid using SLNet calls, as these are subject to change without notice. We recommend to instead always use the correct UI or automation options provided in DataMiner Automation or through our web API if available.
using System;
using System.Collections.Generic;
using System.Globalization;
using Skyline.DataMiner.Core.DataMinerSystem.Common;
using Skyline.DataMiner.Core.DataMinerSystem.Protocol;
using Skyline.DataMiner.Net.Messages;
using Skyline.DataMiner.Net.Messages.Advanced;
using Skyline.DataMiner.Scripting;/// <summary>
/// DataMiner QAction Class: CreateMeasuremPoints.
/// </summary>
public static class QAction
{
private static readonly int WHAT_MP = 29; // What code for getting and setting measurement points
private static readonly string MP_NAME_PREFIX = "MP_Auto_";/// <summary>
/// The QAction entry point.
/// </summary>
/// <param name="protocol">Link with SLProtocol process.</param>
public static void Run(SLProtocol protocol)
{
try
{
List<string> patterns = new List<string> { "Default", "Jump Up", "Jump Down", "Channel", "Band", "Floor" };
int button = Convert.ToInt32(protocol.GetParameter(protocol.GetTriggerParameter()));
List<MeasPtData> mptList = new List<MeasPtData>();
bool generateServices = false;var mp = GetExistingMPs(protocol);
generateServices = mp.generateServices;
mptList = mp.mptList;List<MeasPtData> newMPs = new List<MeasPtData>();
switch (button)
{
case 0: //create pattern MPs
protocol.Log("start creating pattern MPs");
newMPs = CreateBaseMPs(protocol, patterns);
CheckForDuplicates(protocol, ref mptList, newMPs);
break;
case 1: //create table MPs
protocol.Log("start creating table MPs");
int count = Convert.ToInt32(protocol.GetParameter(108) ?? 0);
for (int i = 0; i < count; i++)
{
object[] array = new object[] { i.ToString(), 0 };
protocol.AddRow(200, array);
}
newMPs = CreateNumberMPs(protocol, count);
CheckForDuplicates(protocol, ref mptList, newMPs);
break;
case 2: //delete pattern MPs
protocol.Log("deleting pattern MPs");
mptList.RemoveAll(x => x.Name.Contains(MP_NAME_PREFIX));
protocol.ClearAllKeys(200);
break;
}SetMPs(protocol, mptList);
}
catch (Exception ex)
{
protocol.Log($"QA{protocol.QActionID}|{protocol.GetTriggerParameter()}|Run|Exception thrown:{Environment.NewLine}{ex}", LogType.Error, LogLevel.NoLogging);
}
}private static void CheckForDuplicates(SLProtocol protocol, ref List<MeasPtData> mptList, List<MeasPtData> newMPs)
{
protocol.Log("check for duplicates");
// check if mp's already exist
foreach (var mpt in newMPs)
{
bool canAdd = true;
foreach (var existingMpt in mptList)
{
if (existingMpt.EqualsSkipId(mpt))
{
canAdd = false;
break;
}
}if (canAdd)
{
mptList.Add(mpt);
}
}
}private static MPInfo GetExistingMPs(SLProtocol protocol)
{
MPInfo mp = new MPInfo();
List<MeasPtData> mptList = new List<MeasPtData>();
mp.generateServices = false;
// get existing mp's
var mpreqest = new GetSpectrumInfoMessage(protocol.DataMinerID, protocol.ElementID, WHAT_MP, 0);
var mpresponses = protocol.SLNet.SendMessage(mpreqest);
foreach (var mpresponse in mpresponses)
{
if (mpresponse.GetType() == typeof(GetSpectrumInfoResponseMessage))
{
var gsirm = (GetSpectrumInfoResponseMessage)mpresponse;
mp.generateServices = Convert.ToBoolean(gsirm.Psa.Psa[0].Sa[0]);
for (int i = 1; i < gsirm.Psa.Psa.Length; i++)
{
protocol.Log(string.Join(",", gsirm.Psa.Psa[i].Sa));
MeasPtData mpd = new MeasPtData(gsirm.Psa.Psa[i].Sa, protocol);
mptList.Add(mpd);
}
}
}
mp.mptList = mptList;
return mp;
}private static void SetMPs(SLProtocol protocol, List<MeasPtData> mptList)
{
protocol.Log("Send SetMeasurementPoints request");
// send request
SetSpectrumInfoMessage ssim = new SetSpectrumInfoMessage(protocol.DataMinerID, protocol.ElementID, WHAT_MP, 0, true, string.Empty);
List<SA> sAs = new List<SA>();
foreach (var mpt in mptList)
{
sAs.Add(new SA(mpt.ToStringArray()));
}
SA[] sasArray = sAs.ToArray();
ssim.Psa = new PSA();
ssim.Psa.Psa = sasArray;
protocol.SLNet.SendMessage(ssim);
}private static List<MeasPtData> CreateBaseMPs(SLProtocol protocol, List<string> patterns)
{
List<MeasPtData> newMPs = new List<MeasPtData>();foreach ( string pattern in patterns )
{
// use id -1 for new mp's, server will automatically assign an available ID
MeasPtData mpd = new MeasPtData(-1, protocol.DataMinerID, protocol.ElementID , 101, $"{MP_NAME_PREFIX}{pattern}", "5", 0, 100, string.Empty, 0, string.Empty );
newMPs.Add( mpd );
}return newMPs;
}private static List<MeasPtData> CreateNumberMPs(SLProtocol protocol, int count)
{
var keys = protocol.GetKeys(200, NotifyProtocol.KeyType.Index);
List<MeasPtData> newMPs = new List<MeasPtData>();foreach (string key in keys)
{
// use id -1 for new mp's, server will automatically assign an available ID
MeasPtData mpd = new MeasPtData(-1, protocol.DataMinerID, protocol.ElementID, 203, $"{MP_NAME_PREFIX}{key}", "5", 0, 202, key, 0, string.Empty);
newMPs.Add(mpd);
}return newMPs;
}
}public class MPInfo
{
public bool generateServices { get; set; }
public List<MeasPtData> mptList { get; set; }
}public class MeasPtData
{
/// <summary>
/// Gets or sets measurement point ID (unique per meas pt).
/// </summary>
public int MP_ID { get; set; }/// <summary>
/// DMA id of parameter to set.
/// </summary>
public int DMA_ID { get; set; }/// <summary>
/// Element id of parameter to set.
/// </summary>
public int ElementID { get; set; }/// <summary>
/// Parameter id to set (write pid).
/// </summary>
public int WritePid { get; set; }/// <summary>
/// Name of the measurement point, e.g. "MP - " + satelliteName + " - Vertical".
/// </summary>
public string Name { get; set; }/// <summary>
/// For each parameter to set, "true" if it is of string type.
/// </summary>
public bool IsStringType { get; set; }/// <summary>
/// Value to set in the parameter.
/// </summary>
public string Value { get; set; }/// <summary>
/// Delay time after set.
/// </summary>
public int Delay { get; set; }/// <summary>
/// Read pids associated with the write parameter ids specified above.
/// </summary>
public int ReadPid { get; set; }/// <summary>
/// Table indices of the parameters to set.
/// </summary>
public string TableIndex { get; set; }/// <summary>
/// Frequency offset.
/// </summary>
public double FreqOffset { get; set; }/// <summary>
/// True to invert frequency.
/// </summary>
public bool? InvertFreq { get; set; }/// <summary>
/// automation script info (to be used instead of parameter sets)
/// example:
///"AutomationScriptName;#;OPTIONS:4;#;DEFER:False;#;CHECKSETS:False".
/// </summary>
public string ScriptInfo { get; set; }public MeasPtData(string[] saMPData, SLProtocol protocol)
{
protocol.Log("[0]: mpid = " + saMPData[0]);
MP_ID = Convert.ToInt32(saMPData[0]);protocol.Log("[1]: dmaid = " + saMPData[1]);
DMA_ID = Convert.ToInt32(saMPData[1]);protocol.Log("[2]: elementid = " + saMPData[2]);
ElementID = Convert.ToInt32(saMPData[2]);protocol.Log("[3]: writepid = " + saMPData[3]);
WritePid = Convert.ToInt32(saMPData[3]);protocol.Log("[4]: name = " + saMPData[4]);
Name = saMPData[4];protocol.Log("[5]: stringtype = " + saMPData[5]);
IsStringType = Convert.ToBoolean(saMPData[5]);protocol.Log("[6]: value = " + saMPData[6]);
Value = saMPData[6];protocol.Log("[7]: delay = " + saMPData[7]);
Delay = Convert.ToInt32(saMPData[7]);//[8] is serviceID, currently not implemented
protocol.Log("[8]: serviceId = " + saMPData[8]);protocol.Log("[9]: readpid = " + saMPData[9]);
ReadPid = Convert.ToInt32(saMPData[9]);protocol.Log("[10]: tableIndex = " + saMPData[10]);
TableIndex = saMPData[10];protocol.Log("[11]: FreqOffset = " + saMPData[11]);
FreqOffset = double.Parse(saMPData[11], NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture);protocol.Log("[12]: invertfreq = " + saMPData[12]);
InvertFreq = Convert.ToBoolean(saMPData[12]);protocol.Log("[13]: scriptinfo = " + saMPData[13]);
ScriptInfo = saMPData[13];
}public MeasPtData(int mP_ID, int dMA_ID, int elementID, int writePid, string name, string value, int delay, int readPid, string tableIndex, int freqOffset, string scriptInfo, bool isStringType = false, bool invertFreq = false)
{
MP_ID = mP_ID;
DMA_ID = dMA_ID;
ElementID = elementID;
WritePid = writePid;
Name = name;
IsStringType = isStringType;
Value = value;
Delay = delay;
ReadPid = readPid;
TableIndex = tableIndex;
FreqOffset = freqOffset;
InvertFreq = invertFreq;
ScriptInfo = scriptInfo;
}public string[] ToStringArray()
{
string[] sa = new string[13];
sa[0] = MP_ID.ToString();
sa[1] = DMA_ID.ToString();
sa[2] = ElementID.ToString();
sa[3] = WritePid.ToString();
sa[4] = Name;
sa[5] = IsStringType.ToString().ToLowerInvariant();
sa[6] = Value;
sa[7] = Delay.ToString();
sa[8] = ReadPid.ToString();
sa[9] = TableIndex;
sa[10] = FreqOffset.ToString();
sa[11] = InvertFreq.ToString().ToLowerInvariant();
sa[12] = ScriptInfo;
return sa;
}public bool EqualsSkipId(MeasPtData other)
{
if (other == null)
{
return false;
}if (Object.ReferenceEquals(this, other))
{
return true;
}if (this.GetType() != other.GetType())
{
return false;
}if (this.DMA_ID != other.DMA_ID)
{
return false;
}if (this.ElementID != other.ElementID)
{
return false;
}if (this.WritePid != other.WritePid)
{
return false;
}if (this.Name != other.Name)
{
return false;
}if (this.IsStringType != other.IsStringType)
{
return false;
}if(this.Value != other.Value)
{
return false;
}if (this.Delay != other.Delay)
{
return false;
}if (this.ReadPid != other.ReadPid)
{
return false;
}if (this.TableIndex != other.TableIndex)
{
return false;
}if (this.FreqOffset != other.FreqOffset)
{
return false;
}if (this.InvertFreq != other.InvertFreq)
{
return false;
}if (this.ScriptInfo != other.ScriptInfo)
{
return false;
}return true;
}
}
Hi Amar,
As discussed, we could implement the code snippet provided by Michiel in the protocol to create a measurement point programmatically but the user will still need to define the script to be included in the measurement point. Hardcoding the script name in a connector is not a good idea since it will only be valid for a specific implementation.
Hi Amar,
Small question, why you are checking through a protocol if the script is present?
In which cases the script will not be present? Once you deploy a script in a DMS, it will be available in the cluster.