Hello,
I have the following code. It works fine.
private static void method1()
{
string server = "someserver";
VideoOS.Platform.Login.LoginSettings loginSettings = VideoOS.Platform.Login.LoginSettingsCache.GetLoginSettings(server);
string token = loginSettings.Token;
foreach (var rs in FindAllRecorders())
{
VideoOS.Platform.SDK.Proxy.Status2.RecorderStatusService2 client = new VideoOS.Platform.SDK.Proxy.Status2.RecorderStatusService2(rs.FQID.ServerId.Uri);
var storages = client.GetRecordingStorageStatus(token);
foreach(var storage in storages)
{
var total = storage.FreeSpaceInBytes + storage.UsedSpaceInBytes;
}
}
}
private static IEnumerable<Item> FindAllRecorders()
{
Item serverItem = Configuration.Instance.GetItem(EnvironmentManager.Instance.MasterSite);
List<Item> serverItems = serverItem.GetChildren();
foreach (Item item in serverItems)
{
if (item.FQID.Kind == Kind.Server && item.FQID.ServerId.ServerType == ServerId.CorporateRecordingServerType)
yield return item;
}
}
But I found the ConfigurationItems API, and it looks much cleaner/simpler. I thus tried to translate the code to that:
private static void method2()
{
var ms = new ManagementServer(EnvironmentManager.Instance.MasterSite);
foreach (var rs in ms.RecordingServerFolder.RecordingServers)
{
foreach (var storage in rs.StorageFolder.Storages)
{
var infoTask = storage.ReadStorageInformation();
while (infoTask.State != StateEnum.Error && infoTask.State != StateEnum.Success)
{
System.Threading.Thread.Sleep(1000);
infoTask.UpdateState();
}
if (infoTask.State == StateEnum.Error)
throw new ApplicationException(String.Format("Error retrieving storage {0} {1}", rs.Name, storage.Name));
var total = "what code here instead of this string?";
}
}
}
As you see I’m stuck. It looks like with the ConfigurationItems API I don’t have access to the same information.
Can you guys clarify when we should use the ConfigurationItems API and when we need to go through the “Item” API (Proxy.Status2.RecorderStatusService2)? Can we easily go from the ConfigurationItems API to the Item API? For example to get an Item out of a RecordingServer I tried to call rs.GetItem() but that does not work.
I could extract the used space information by doing the following amendment to your code:
ManagementServer ms = new ManagementServer(EnvironmentManager.Instance.MasterSite);
foreach (var rs in ms.RecordingServerFolder.RecordingServers)
{
foreach (var storage in rs.StorageFolder.Storages)
{
var infoTask = storage.ReadStorageInformation();
while (infoTask.State != StateEnum.Error && infoTask.State != StateEnum.Success)
{
System.Threading.Thread.Sleep(1000);
infoTask.UpdateState();
}
if (infoTask.State == StateEnum.Error)
throw new ApplicationException(String.Format("Error retrieving storage {0} {1}", rs.Name, storage.Name));
var si = new StorageInformation(EnvironmentManager.Instance.MasterSite.ServerId, infoTask.Path);
var usedSpace = si.UsedSpace;
MessageBox.Show("Used space " + usedSpace.ToString() +" Maximum space " + storage.MaxSize.ToString());
}
}
I guess there is a route to contact each recording server and use the RecorderStatusService2 from each recording server, even though the Configuration API and the RecorderStatusService2 are not closely related by implementation, but I have an idea that the answer above is the one you will prefer to use. (Correct me if I am wrong in this assumption.)
Ah great! So this is what I was missing, how to go from a task to a StorageInformation (by using the task path).
This part of the design is really under-documented, so I guess from it that all items can be constructed using the right path, and that for some things that need runtime computing you launch tasks to prepare these paths.
So, basically I’d use the ConfigurationItems API and only for things unsupported by it I’d fall back to the RecorderStatusService2 API?
There is a lot of things where the information is hard to find, for example I’m trying to modify the “Frames per second” used by the first channel of a camera, is that in “camera.ClientSettingsFolder.ClientSettings” or “camera.DeviceDriverSettingsFolder.DeviceDriverSettings”? these seems to hold generic properties and I guess by listing the keys I’ll figure it out, but pointers appreciated 
One very important difference is that Configuration API give you the configuration, so if a camera is setup to default deliver 5 fps this is the value you will get. RecorderStatusService2 gives you the actual used fps value. The two values are not always the same, one scenario where they will differ is if you have a rule that changes the fps of a camera, the value the Configuration API gives you is still the configuration of the default value.
For real-time data the RecorderStatusService2 is the better choice, for configuration the Configuration API can be used to read, but also to change, values. One is very dynamic and the other is static in nature.
Thanks a lot. I’d be great if all these insights you give on the APIs were written down somewhere, maybe in some “API overview” section 
@Bo Ellegård Andersen (Milestone Systems) I just noticed that the ConfigurationAPI gives wrong values for “si.UsedSpace” when running on 2017 R3. It works fine with 2020 R1.
The RecorderStatusService2 does not have this problem. Do you know why?
I found a known issue concerning UsedSpace, the issue was fixed in 2020R1. This was judged to be a minor bug and no hot-fixes for the versions older than 2020R1 was developed.
Alright thanks for the info. Will use RecorderStatusService2 for older clients.