public void CreateRemoteMXReadConfigTemplate() { var d = new DateTime(2015, 11, 10, 16, 0, 0); RemoteMXPlugin.ReadConfig rc = new RemoteMXPlugin.ReadConfig() { LatestValueRead = d }; string xml = SerializeHelper.SerializeToStringWithDCS <RemoteMXPlugin.ReadConfig>(rc); Trace.WriteLine(xml); Assert.IsNotNull(xml); RemoteMXPlugin.ReadConfig dps = SerializeHelper.DeserializeWithDCS <RemoteMXPlugin.ReadConfig>(xml); Assert.IsNotNull(dps); Assert.AreEqual(dps.LatestValueRead, rc.LatestValueRead); }
/// <summary> /// The MeasurerService calls Process method periodically as defined in plugin's config ExecuteInterval element. The time is seconds. /// Note that the same instance of this class is alive the whole time as the service is alive! So make this process as sleek and lean as possible. /// </summary> public void Process() { var readConfigFile = this.settings.ReadConfigPath.GetPluginRootedPath(); ReadConfig readConfig = null; if (System.IO.File.Exists(readConfigFile)) { readConfig = SerializeHelper.DeserializeWithDCS <ReadConfig>(System.IO.File.ReadAllText(readConfigFile)); } else { readConfig = new ReadConfig(); } RemoteMXService.site response = null; DateTime readStartDate = readConfig.LatestValueRead.AddSeconds(1.0); // set startDate to latest value read + one second to not read the latest value again. // set endDate to start date + timespan of max time to read measurements or current time which ever is smaller. DateTime readEndDate = new DateTime(Math.Min(DateTime.Now.Ticks, readStartDate.Add(this.settings.MaxTimeToReadAtOnce).Ticks)); using (RemoteMXService.RdmSitesClient client = new RemoteMXService.RdmSitesClient()) { var sites = client.getSites(new RemoteMXService.user() { password = this.settings.Password, username = this.settings.UserName }); if (null == sites || sites.Length == 0) { Log.Append(string.Format("No sites found from RemoteMX for user {0}", this.settings.UserName)); } else { if (sites.Any(s => s.id == this.settings.SiteId)) { RemoteMXService.datareq request = new RemoteMXService.datareq() { siteId = this.settings.SiteId, username = this.settings.UserName, password = this.settings.Password, startDate = readStartDate, endDate = readEndDate }; response = client.getData(request); } else { string sitesString = ""; sites.ToList().ForEach(s => { sitesString += string.Format("Site id: {0}, name: {1}{2}", s.id, s.name, Environment.NewLine); }); throw new Exception(string.Format("Configured site id (SiteId: {1}) was not found from RemoteMX service with username {2}. {0}RemoteMX sites found:{0}{3}", Environment.NewLine, this.settings.SiteId, this.settings.UserName, sitesString)); } } } string serialized = string.Empty; if (null == response || null == response.data || response.data.Length == 0) { string messageTemplate = "No measurements found from RemoteMX for user {0} with site id {1} between {2} and {3}. Next reading will try with the same start time ({2})."; // No data --> update latest read value to readEndDate when the readEndDate is old enough. // This adds a little redundancy to data reading to allow service breaks etc. // Try to read the same time period for twice the duration of MaxTimeToReadAtOnce setting and after that move on. if (readEndDate.Add(this.settings.MaxTimeToReadAtOnce.Add(this.settings.MaxTimeToReadAtOnce)) < DateTime.Now) { readConfig.LatestValueRead = readEndDate; serialized = SerializeHelper.SerializeToStringWithDCS <ReadConfig>(readConfig); System.IO.File.WriteAllText(readConfigFile, serialized); messageTemplate = "No measurements found from RemoteMX for user {0} with site id {1} between {2} and {3}. Next reading will start with updated start time ({3})."; } Log.Append(string.Format(messageTemplate, this.settings.UserName, this.settings.SiteId, readStartDate, readEndDate)); return; } // we have data! // Do the measurement reading here... and then create a MeasurementPackage object with a proper key to enable saving measurements to SAMI system. MeasurementPackage p = new MeasurementPackage() { Key = this.settings.SamiKey, Measurements = new List <MeasurementModel>(response.data.Length) }; MeasurementModel mm = null; DateTime newestReadValue = readConfig.LatestValueRead; foreach (var item in response.data) { mm = new MeasurementModel() { Object = settings.MeasurementObject, Tag = settings.MeasurementTag, Timestamp = item.timestamp }; if (item.timestamp > newestReadValue) { newestReadValue = item.timestamp; } if (null != item.variables && item.variables.Length > 0) { mm.Data = new List <DataModel>(item.variables.Length); bool save = false; foreach (var val in item.variables) { // when SaveMappedValuesOnly == true --> save = false. Data is saved only when ChannelMap contains a map for the channel. // when SaveMappedValuesOnly == false --> save = true. Data is saved with or without ChannelMap info. save = !this.settings.SaveMappedValuesOnly; var tag = val.channel; if (this.settings.ChannelMap.ContainsKey(tag)) { tag = this.settings.ChannelMap[tag]; save = true; } if (save) { mm.Data.Add(new DataModel() { Tag = tag, Value = val.value }); } } } // NOTE! a measurement might not contain any Data items. p.Measurements.Add(mm); } readConfig.LatestValueRead = newestReadValue; serialized = SerializeHelper.SerializeToStringWithDCS <ReadConfig>(readConfig); System.IO.File.WriteAllText(readConfigFile, serialized); // When your plugin has something to save raise ProcessCompleted event. The Name property can be used as ProcessCompletedEventArgs source parameter. // If at some point your plugin has nothing to save, then don't raise the event. this.OnProcessCompleted(new ProcessCompletedEventArgs(this.Name, p)); }