/// <summary> /// Mark tasks claimed. /// </summary> public GXTasksClaimResponse(GXClaimedTask[] tasks) { if (tasks != null) { int pos = -1; this.Tasks = new GXClaimedTask[tasks.Length]; for (int i = 0; i < tasks.Length; i++) { this.Tasks[++pos] = tasks[i]; } } }
public void ExecuteTransaction(GXClaimedTask taskinfo) { object target; if (taskinfo.Task.TargetType == TargetType.Device) { target = Device; } else { target = Device.FindItemByID(taskinfo.Task.TargetID); } if (target is GXDevice) { if (taskinfo.Task.TaskType == TaskType.Read) { (target as GXDevice).Read(); } } else if (target is GXCategory) { if (taskinfo.Task.TaskType == TaskType.Read) { (target as GXCategory).Read(); } } else if (target is GXTable) { if (!string.IsNullOrEmpty(taskinfo.Task.Data)) { Gurux.Device.Editor.IGXPartialRead pr = target as Gurux.Device.Editor.IGXPartialRead; string[] parameters = taskinfo.Task.Data.Split(new char[] { ';' }); pr.Type = (PartialReadType) Convert.ToInt32(parameters[0]); //Read by entry (index and count).. if (pr.Type == PartialReadType.Entry) { int start = Convert.ToInt32(parameters[1]); int end = Convert.ToInt32(parameters[2]); //Read all values. if (start == 0 && end == 0) { pr.Type = PartialReadType.All; } else { pr.Start = start; pr.End = end; } } //Read by range (between start and end time). else if (pr.Type == PartialReadType.Range) { pr.Start = Convert.ToDateTime(parameters[1]); pr.End = Convert.ToDateTime(parameters[2]); } else { throw new ArgumentException("Invalid type."); } } //In default read new values. if (taskinfo.Task.TaskType == TaskType.Read) { (target as GXTable).Read(); } } else if (target is GXProperty) { if (taskinfo.Task.TaskType == TaskType.Read) { (target as GXProperty).Read(); } } else { throw new ArgumentException("Unknown target."); } }
/// <summary> /// Load device template and connect to the device. /// </summary> /// <param name="path"></param> /// <param name="taskinfo"></param> public void Connect(string path, GXClaimedTask taskinfo) { ExecutedTask = taskinfo; //If already connected. if (Device != null) { UpdateParameters(); if ((Device.Status & DeviceStates.Connected) == 0) { Device.Connect(); } return; } DeviceList = new GXDeviceList(); DeviceList.OnError += new Gurux.Common.ErrorEventHandler(DeviceList_OnError); DeviceList.OnUpdated += new ItemUpdatedEventHandler(DeviceList_OnUpdated); GXDeviceGroup group = new GXDeviceGroup(); DeviceList.DeviceGroups.Add(group); TargetDirectory = path; AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); AppDomain.CurrentDomain.TypeResolve += new ResolveEventHandler(CurrentDomain_TypeResolve); GXDeviceList.Update(path); string filename = Path.Combine(path, taskinfo.Device.ProfileGuid + ".gxp"); Device = GXDevice.Load(filename); Device.ID = taskinfo.Device.Id; group.Devices.Add(Device); Device.Name = taskinfo.Device.Name; //taskinfo.Device.AutoConnect; // ForcePerPropertyRead Device.UpdateInterval = taskinfo.Device.UpdateInterval; Device.WaitTime = taskinfo.Device.WaitTime; Device.ResendCount = taskinfo.Device.ResendCount; Device.DisabledActions = taskinfo.Device.DisabledActions; /* TODO: Device.FailTryCount = taskinfo.Device.FailTryCount; Device.FailWaitTime = taskinfo.Device.FailWaitTime; Device.ConnectionTryCount = taskinfo.Device.ConnectionTryCount; Device.ConnectionFailWaitTime = taskinfo.Device.ConnectionFailWaitTime; */ //Update parameters. UpdateParameters(); //Load medias to this assembly domin. Gurux.Communication.GXClient.GetAvailableMedias(); if (taskinfo.Device.TraceLevel != System.Diagnostics.TraceLevel.Off) { Device.Trace = taskinfo.Device.TraceLevel; Device.OnTrace += new TraceEventHandler(Device_OnTrace); } Exception lastException = null; int pos = -1; Gurux.Common.IGXMedia media = null; foreach (var it in taskinfo.MediaSettings) { try { ++pos; //If media is changed. if (media == null || media.MediaType != taskinfo.MediaSettings[pos].Key) { media = Device.GXClient.SelectMedia(taskinfo.MediaSettings[pos].Key); Device.GXClient.AssignMedia(media); } media.Settings = taskinfo.MediaSettings[pos].Value.Value; lastException = null; Device.Connect(); break; } catch (Exception ex) { //If connection fails try next redundant connectio. lastException = ex; } } if (lastException != null) { throw lastException; } }
/// <summary> /// Mark task(s) as claimed. /// </summary> /// <param name="request"></param> /// <returns></returns> public GXTasksClaimResponse Post(GXTasksClaimRequest request) { List<GXEventsItem> events = new List<GXEventsItem>(); List<GXClaimedTask> infoList = new List<GXClaimedTask>(); AppHost host = this.ResolveService<AppHost>(); Guid guid; IAuthSession s = this.GetSession(false); if (!GXBasicAuthProvider.IsGuid(s.UserAuthName, out guid)) { throw new ArgumentException("Access denied."); } lock (Db) { DateTime claimTime = DateTime.Now; foreach (ulong it in request.TaskIDs) { GXAmiDataCollector collector = null; //Try to get wanted task. If that is taken get next available task. List<GXAmiTask> tasks = Db.Select<GXAmiTask>(q => q.Id == it && q.ClaimTime == null); //Make sure that no one else is has not claim the task. GXAmiTask task = null; bool wantedTask = tasks.Count != 0; if (wantedTask) { #if !SS4 task = Db.GetById<GXAmiTask>(it); #else task = Db.SingleById<GXAmiTask>(it); #endif } else { tasks = Db.Select<GXAmiTask>(q => q.ClaimTime == null); if (tasks.Count != 0) { task = tasks[0]; } } if (task != null) { task.Data = GetData(it, false); task.SenderDataCollectorGuid = guid; //If DC is clamiming the task for it self. if (task.TargetDeviceID == null && task.DataCollectorGuid != Guid.Empty) { //DC can claim only own tasks. if (task.DataCollectorGuid != guid) { throw new ArgumentException("Access denied."); } List<GXAmiDataCollector> collectors = Db.Select<GXAmiDataCollector>(q => q.Guid == guid); if (collectors.Count != 1) { throw new ArgumentException("Access denied."); } collector = collectors[0]; } else //If DC is claiming device task. { //Get list of DC that can access Device. string query = string.Format("SELECT DISTINCT {0}.* FROM {0} INNER JOIN {1} ON ({0}.ID = {1}.DataCollectorId OR {1}.DataCollectorId IS NULL) WHERE DeviceID = {2} AND Guid = '{3}'", GuruxAMI.Server.AppHost.GetTableName<GXAmiDataCollector>(Db), GuruxAMI.Server.AppHost.GetTableName<GXAmiDeviceMedia>(Db), task.TargetDeviceID.Value, guid.ToString().Replace("-", "")); List<GXAmiDataCollector> collectors = Db.Select<GXAmiDataCollector>(query); //If DC can't access task. if (collectors.Count == 0) { throw new ArgumentException("Access denied."); } collector = collectors[0]; } //Find device template Guid. if (task.TargetDeviceID != null) { string query = string.Format("SELECT {0}.* FROM {0} INNER JOIN {1} ON {0}.ID = {1}.ProfileId WHERE {1}.ID = {2}", GuruxAMI.Server.AppHost.GetTableName<GXAmiDeviceProfile>(Db), GuruxAMI.Server.AppHost.GetTableName<GXAmiDevice>(Db), task.TargetDeviceID.Value); List<GXAmiDeviceProfile> profiles = Db.Select<GXAmiDeviceProfile>(query); if (profiles.Count != 1) { throw new ArgumentException("Access denied."); } GXClaimedTask info = new GXClaimedTask(); if (!wantedTask) { info.Task = task; } info.DeviceProfile = profiles[0].Guid; query = string.Format("SELECT {0}.* FROM {0} WHERE {0}.ID = {1}", GuruxAMI.Server.AppHost.GetTableName<GXAmiDevice>(Db), task.TargetDeviceID.Value); List<GXAmiDevice> devices = Db.Select<GXAmiDevice>(query); if (devices.Count != 1) { throw new ArgumentException("Access denied."); } info.Device = devices[0]; info.Device.Parameters = Db.Select<GXAmiParameter>(q => q.ParentID == info.Device.Id).ToArray(); info.Device.Categories = Db.Select<GXAmiCategory>(q => q.DeviceID == info.Device.Id).ToArray(); foreach (GXAmiCategory cat in info.Device.Categories) { cat.Parameters = Db.Select<GXAmiParameter>(q => q.ParentID == cat.Id).ToArray(); cat.Properties = Db.Select<GXAmiProperty>(q => q.ParentID == cat.Id).ToArray(); foreach (GXAmiProperty p in cat.Properties) { p.Parameters = Db.Select<GXAmiParameter>(q => q.ParentID == p.Id).ToArray(); } } info.Device.Tables = Db.Select<GXAmiDataTable>(q => q.DeviceID == info.Device.Id).ToArray(); foreach (GXAmiDataTable table in info.Device.Tables) { table.Parameters = Db.Select<GXAmiParameter>(q => q.ParentID == table.Id).ToArray(); table.Columns = Db.Select<GXAmiProperty>(q => q.ParentID == table.Id).ToArray(); foreach (GXAmiProperty p in table.Columns) { p.Parameters = Db.Select<GXAmiParameter>(q => q.ParentID == p.Id).ToArray(); } } info.Device.ProfileGuid = profiles[0].Guid; List<GXAmiDeviceMedia> Medias = Db.Select<GXAmiDeviceMedia>(q => q.DeviceId == info.Device.Id); foreach(GXAmiDeviceMedia it2 in Medias) { if (it2.DataCollectorId == null || it2.DataCollectorId == collector.Id) { info.MediaSettings.Add(new KeyValuePair<string, KeyValuePair<string, string>>(it2.Name, new KeyValuePair<string, string>(it2.Name, it2.Settings))); } } info.Data = task.Data; infoList.Add(info); } else //DC claims the task to itself. { GXClaimedTask info = new GXClaimedTask(); if (task.TargetType == TargetType.Media) { if (task.TaskType == TaskType.MediaOpen) { string[] data = task.Data.Split(new string[] { "\r\n" }, StringSplitOptions.None); info.MediaSettings.Clear(); info.MediaSettings.Add(new KeyValuePair<string, KeyValuePair<string, string>>(data[0], new KeyValuePair<string, string>(data[1], data[2]))); task.Data = null; } else if (task.TaskType == TaskType.MediaClose) { string[] data = task.Data.Split(new string[] { "\r\n" }, StringSplitOptions.None); info.MediaSettings.Clear(); info.MediaSettings.Add(new KeyValuePair<string, KeyValuePair<string, string>>(data[0], new KeyValuePair<string, string>(data[1], ""))); task.Data = null; } else if (task.TaskType == TaskType.MediaWrite) { string[] data = task.Data.Split(new string[] { "\r\n" }, StringSplitOptions.None); info.MediaSettings.Clear(); info.MediaSettings.Add(new KeyValuePair<string, KeyValuePair<string, string>>(data[0], new KeyValuePair<string, string>(data[1], ""))); task.Data = data[2]; } else if (task.TaskType == TaskType.MediaGetProperty) { string[] data = task.Data.Split(new string[] { "\r\n" }, StringSplitOptions.None); info.MediaSettings.Clear(); info.MediaSettings.Add(new KeyValuePair<string, KeyValuePair<string, string>>(data[0], new KeyValuePair<string, string>(data[1], ""))); task.Data = data[2]; } else if (task.TaskType == TaskType.MediaSetProperty) { string[] data = task.Data.Split(new string[] { "\r\n" }, StringSplitOptions.None); info.MediaSettings.Clear(); info.MediaSettings.Add(new KeyValuePair<string, KeyValuePair<string, string>>(data[0], new KeyValuePair<string, string>(data[1], ""))); task.Data = data[2] + Environment.NewLine + data[3]; } } info.DataCollectorID = collector.Id; info.Data = task.Data; infoList.Add(info); } task.ClaimTime = claimTime; task.State = TaskState.Processing; task.DataCollectorID = collector.Id; task.DataCollectorGuid = guid; task.SenderDataCollectorGuid = guid; Db.Update(task); events.Add(new GXEventsItem(ActionTargets.Task, Actions.Edit, task)); } } } //Notify that task is claimed. host.SetEvents(Db, this.Request, 0, events); return new GXTasksClaimResponse(infoList.ToArray()); }
private void HandleDevice(GXClaimedInfo info, GXProxyClass pc, ref string path, ref bool leaveConnectionOpen, GXClaimedTask taskinfo) { try { //If device template is not loaded yet. if (path == null) { path = Path.Combine(Gurux.Common.GXCommon.ApplicationDataPath, "Gurux"); if (!Directory.Exists(path)) { Directory.CreateDirectory(path); Gurux.Common.GXFileSystemSecurity.UpdateDirectorySecurity(path); } path = Path.Combine(path, "Gurux.DeviceSuite"); if (!Directory.Exists(path)) { Directory.CreateDirectory(path); Gurux.Common.GXFileSystemSecurity.UpdateDirectorySecurity(path); } path = Path.Combine(path, "DeviceProfiles"); if (!Directory.Exists(path)) { Directory.CreateDirectory(path); Gurux.Common.GXFileSystemSecurity.UpdateDirectorySecurity(path); } path = Path.Combine(path, taskinfo.DeviceProfile.ToString()); //Load Device template if not loaded yet. if (!Directory.Exists(path)) { Directory.CreateDirectory(path); Gurux.Common.GXFileSystemSecurity.UpdateDirectorySecurity(path); byte[] data = DC.GetDeviceProfilesData(taskinfo.DeviceProfile); GXDeviceProfile type = pc.Import(data, path); if (!(type is GXPublishedDeviceProfile)) { File.Copy(type.Path, Path.Combine(path, taskinfo.DeviceProfile.ToString() + ".gxp"), true); } } } } catch (Exception ex) { path = null; if (Directory.Exists(path)) { Directory.Delete(path, true); } lock (info.Exceptions) { info.Exceptions.Add(taskinfo, ex); taskinfo.Task.State = TaskState.Failed; } } try { //Save executed task. This is used if error occures. pc.Connect(path, taskinfo); //Read or write device. if (taskinfo.Task.TaskType == TaskType.Read || taskinfo.Task.TaskType == TaskType.Write) { System.Diagnostics.Debug.WriteLine("DC start to read target: " + taskinfo.Task.Id.ToString() + " " + taskinfo.Task.TargetDeviceID.ToString()); pc.ExecuteTransaction(taskinfo); taskinfo.Task.State = TaskState.Succeeded; System.Diagnostics.Debug.WriteLine("DC end reading target: " + taskinfo.Task.Id.ToString() + " " + Guid.ToString()); } else if (taskinfo.Task.TaskType == TaskType.StartMonitor) { leaveConnectionOpen = true; pc.StartMonitoring(); taskinfo.Task.State = TaskState.Succeeded; } else if (taskinfo.Task.TaskType == TaskType.StopMonitor) { leaveConnectionOpen = false; pc.StopMonitoring(); taskinfo.Task.State = TaskState.Succeeded; } else { throw new Exception("Invalid task type."); } } catch (Exception ex) { lock (info.Exceptions) { info.Exceptions.Add(taskinfo, ex); taskinfo.Task.State = TaskState.Failed; } if (m_Error != null) { m_Error(this, ex); } } }
/// <summary> /// Save executed tasks so they can be retreaved if app is restarted. /// </summary> /// <remarks> /// Example monitoring uses this. /// </remarks> static void SaveExecutedTask(Guid guid, GXClaimedTask task) { XmlWriterSettings settings = new XmlWriterSettings(); settings.Indent = true; settings.Encoding = System.Text.Encoding.UTF8; settings.CloseOutput = true; settings.CheckCharacters = false; System.Runtime.Serialization.DataContractSerializer x = new System.Runtime.Serialization.DataContractSerializer(typeof(GXClaimedTask)); using (XmlWriter writer = XmlWriter.Create(guid.ToString() + "executingTask.xml", settings)) { x.WriteObject(writer, task); } }