21 Replies Latest reply on May 14, 2015 9:55 AM by robertm

    How to "Manage" a Responder incident using DataServices API

    david renz

      Can anyone give me a lead on how to manage a responder incident using the DataServices API?

      I need to be able to programmatically "Execute All" for each open incident in the rx_incidents table.

       

      We are testing a new callback system and want to put test incidents into our test db.

      We have used the DataServices API to add incidents to our rx tables, but now need a way to programmatically "Manage" them all (without having to open responder and individually doing each).

       

      Can some tell me how to close an incident and have all the data go to the correct tables in the Responder schema?

      There are just too many potential problems in trying to do it manually.

       

      Or, if you know each table involved, can you tell me that?

       

      Essentially, I am looking for code samples (which don't really exist for DataServices API).

      So, if you have some code to share to do this, I would love to take a look.

       

      thanks

      David

        • Re: How to "Manage" a Responder incident using DataServices API

          David, this might help you out, but it uses device information that we already know about.

           

          IDataServices dataServices = ResponderServices.GetDataServices();

          FindIncidentByGeoRowRequest request = new FindIncidentByGeoRowRequest(device.FCID, device.OID);

          request = (FindIncidentByGeoRowRequest)dataServices.ExecuteRequest(request);

          DataSet existingIncidentDataset = request.RequestedDataSet;

          DataTable incidents = existingIncidentDataset.Tables[RxDb.Tables.Incidents];

          DataRow incident = incidents.Rows[0];

          incident[RxDb.Tables.Incidents.Status] = 2; //Restored

          dataServices.SubmitAndForget(existingIncidentDataset);

           

          Kim Despins has also been posting code sample recently under the GIS Developers section of Exchange.

           

          Jeff

          • Re: How to "Manage" a Responder incident using DataServices API
            Erik Hooper

            If you are asking about the Manage Incident dialog there isn't really a way to use that with the dataservices API, all that logic is stored within that control. You can't(within reason) call that control without using the UI component.

            If you are asking about completing and restoring incidents you can do that though the API but is involved. If you are still interested I can send something your way.

              • Re: How to "Manage" a Responder incident using DataServices API
                david renz

                Erik,

                 

                I am interested in doing it through the API. I would love it if you could send something our way to help us with this.

                 

                Thanks

                David

                  • Re: How to "Manage" a Responder incident using DataServices API
                    david renz

                    Erik,

                     

                    Do you have any code to share related to this?

                     

                    thanks

                    David

                      • Re: How to "Manage" a Responder incident using DataServices API
                        david renz

                        OK ... i have the incidentIds ... so now how do I manage them?

                         

                         

                                        if (_dataServices == null) _dataServices = ResponderServices.GetDataServices();

                                        Miner.Responder.Shared.Requests.FindIncidentsRequest req = new FindIncidentsRequest("STATUS = 0");

                                        req = (FindIncidentsRequest)_dataServices.ExecuteRequest(req);

                         

                                        DataSet ds = req.RequestedDataSet;

                                        List<int> IDs = (ds.Tables["rx_incidents"].Rows.Cast<DataRow>().Select(dr => Int32.Parse(dr["ID"].ToString()))).ToList();

                         

                        Can anyone get me to that next step? ... "Manage" the incident?

                         

                        thanks

                        David

                        • Re: How to "Manage" a Responder incident using DataServices API
                          Erik Hooper

                          the simplest possible implementation would look something like:

                                  public static void RestoreAndCloseIncident(int id)

                                  {

                                      var findIncident = new FindIncidentAndRelatedTablesRequest(id);

                                      var ds = findIncident.Execute().RequestedDataSet;

                           

                           

                                      // confirm incidents

                                      var incident = IncidentsObject.FindAll(ds).Single();

                                      incident.Confirmed = ConfirmedStateDomain.Confirmed;

                                      // set device status to restored.

                                      var devices = IncidentDevicesObject.FindAll(ds);

                                      foreach (var device in devices)

                                      {

                                          device.ActualStatus = device.ExpectedStatus;

                                      }

                           

                                      ResponderServices.Submit(ds);

                           

                                      // everything should be restored assuming no crews or other features on the incident. we can now complete and close

                                      incident = IncidentsObject.FindAll(ds).Single();

                                      incident.Status = IncidentStatusDomain.Completed;

                                      //submit

                                      ResponderServices.Submit(ds);

                           

                           

                                      incident = IncidentsObject.FindAll(ds).Single();

                                      incident.Status = IncidentStatusDomain.Closed;

                                      //submit

                                      ResponderServices.Submit(ds);

                                  }

                            • Re: How to "Manage" a Responder incident using DataServices API
                              david renz

                              Erik,

                               

                              I am guessing that the above is a more current version of ArcFM than we are using.

                              We are using 10.0.2.

                               

                              This does not work for me:

                              var ds = findIncident.Execute().RequestedDataSet;


                              I am getting this an option:

                              var ds = findIncident.Execute(DataSource source, DataSession session)


                              How does one get the source and session?

                               

                              And what kind of objects are "IncidentsObject"  and "IncidentDevicesObject"?

                              Can you include their instantiation in the example? Those vars are obscuring the Type.

                               

                              Is there someplace where I can actually find examples for 10.0.2? What a pain!

                               

                               

                              thanks

                              David

                                • Re: How to "Manage" a Responder incident using DataServices API
                                  James Wright

                                  David,

                                   

                                  You are correct, the code provided by Eric will not work at 10.0.2 and unfortunately there are no examples of what you are trying to do on that specific version.

                                   

                                  The IncidentObjects and IncidentDeviceObject are static classes which were introduced in 10.0.3 SP1 I believe.

                                   

                                  Here is a guide to the 10.0.2 Responder Developer guide. Specifically: FindCallsAndRelatedCustomersRequest

                                  Responder Developer Guide

                                   

                                  If you note and follow the implemented Interfaces listed for that class you will see that the Miner.Responder.Data.IDataRequest interface has this remark: (Note number 2)

                                   

                                  There are a few conventions that should be followed when implementing this interface.

                                  1. The deriving class must be serializable. There are a few ways of doing this, but the easiest is to mark the class with the [Serializable] attribute.
                                  2. The caller is not intended to call the Execute method, so please use explicit interface member implementation to exclude the Execute method from the public interface of the class.
                                  3. Include a constructor that allows the caller to pass arguments to the class for use in the Execute method (which is executed in the middle-tier business server application).


                                  I believe you should simply create the request and then simply retrieve the data set.


                                  var findIncident = new FindIncidentAndRelatedTablesRequest(id);

                                  var ds = findIncident.RequestedDataSet;


                                  Execute is not required as it should be handled internally.

                                    • Re: How to "Manage" a Responder incident using DataServices API
                                      david renz

                                      James,


                                      thanks for your response.

                                      I am finding that the execute is required.Which seems to work alright.


                                      I have taken some of what Jeff Mertz suggested above to get what might be a working something going, but the update does not seem to happen.

                                      Can you tell me why this is not updating my database?

                                       

                                       

                                                      var incidentTablesRequest = new FindIncidentAndRelatedTablesRequest(id);

                                                      incidentTablesRequest =  (FindIncidentAndRelatedTablesRequest)_dataServices.ExecuteRequest(incidentTablesRequest);

                                                      var ds = incidentTablesRequest.RequestedDataSet;

                                       

                                                      var incidentTable = ds.Tables[RxDb.Tables.Incidents];

                                                      var singleIncident = incidentTable.Rows[0];

                                                      singleIncident[RxDb.Tables.Incidents.Status] = 2;

                                       

                                                      _dataServices.SubmitAndForget(ds);

                                       

                                       

                                      Thanks

                                      david

                                        • Re: How to "Manage" a Responder incident using DataServices API
                                          James Wright

                                          For troubleshooting purposes. Could you try Submit instead of SubmitAndForget.

                                           

                                          Also, are you receiving any errors in the Miner Event logs after performing the SubmitAndForget call?

                                            • Re: How to "Manage" a Responder incident using DataServices API
                                              david renz

                                              OK ... the status change is now working (was a permission issue).

                                               

                                              But how do I close and complete the incident?

                                              The key for what I need to do is to get the incidents into the Archive table.

                                               

                                              thanks for the help, James.

                                                • Re: How to "Manage" a Responder incident using DataServices API
                                                  david renz

                                                  So, I have gotten to what I think is how it SHOULD work, but the incident does not move from the incidents table.

                                                  What am I missing here?

                                                                

                                                                 var incidentTablesRequest = new FindIncidentAndRelatedTablesRequest(i);

                                                                  incidentTablesRequest =  (FindIncidentAndRelatedTablesRequest)_dataServices.ExecuteRequest(incidentTablesRequest);

                                                                  var ds = incidentTablesRequest.RequestedDataSet;

                                                   

                                                                  var incidentTable = ds.Tables[RxDb.Tables.Incidents];

                                                                  var singleIncident = incidentTable.Rows[0];

                                                   

                                                                  // confirm the incident

                                                                  singleIncident[RxDb.Tables.Incidents.Confirmed] = 1;

                                                                  _dataServices.Submit(ds);

                                                   

                                                                  // restore the incident

                                                                  singleIncident[RxDb.Tables.Incidents.Status] = 2;

                                                                  singleIncident[RxDb.Tables.Incidents.TimeRestored] = DateTime.Now;

                                                                  _dataServices.Submit(ds);

                                                   

                                                                  // get the devices

                                                                  var incidentDeviceRequest = new FindDevicesForIncidentRequest(i);

                                                                  incidentDeviceRequest = (FindDevicesForIncidentRequest)_dataServices.ExecuteRequest(incidentDeviceRequest);

                                                                  Miner.Responder.Framework.DeviceInfo[] devices = incidentDeviceRequest.RequestedDevices;

                                                                  foreach (var device in devices)

                                                                  {

                                                                      device.ActualStatus = device.ExpectedStatus;

                                                                  }

                                                                  _dataServices.Submit(ds);

                                                   

                                                                  // complete the incident

                                                                  singleIncident[RxDb.Tables.Incidents.Status] = 3;  //completed

                                                                  _dataServices.Submit(ds);

                                                   

                                                                  // close that thing

                                                                  singleIncident[RxDb.Tables.Incidents.Status] = 6;  //closed

                                                                  _dataServices.Submit(ds);

                                                   

                                                   

                                                  I get the following error when I try to Commit the Status to 3:

                                                   

                                                  "

                                                  Record 'Incident 156554' was not updated because of a conflict.\r\nIncidents.STATUS was not updated from 'Created' to 'Completed' because it was already changed to 'Restored' by another user.\r\nIncidents.TIME_RESTORED was not updated from NULL to to_date('08/06/2014 07:57:04', 'MM/DD/YYYY HH24:MI:SS') because it was already changed to to_date('08/06/2014 07:57:04', 'MM/DD/YYYY HH24:MI:SS') by another user.\r\nIncidents.CONFIRMED was not updated from 'Unconfirmed' to 'Confirmed' because it was already changed to 'Confirmed' by another user."}System.Exception {System.Data.DBConcurrencyException}"

                                                   

                                                   

                                                  Thanks

                                                  David

                                                    • Re: How to "Manage" a Responder incident using DataServices API
                                                      david renz

                                                      OK ...  I think I got it.

                                                       

                                                      I am not sure what the SubmitAndForget vs the Submit does, but it seems to have done the trick.

                                                       

                                                      Dear Schneider ... I really think that you could have some incredible solutions out there, by your users, if you would simply document your API! Please study how ArcObjects changed the solutions that developers could come up with, once the AO API was released and fully documented and incorporated into ESRI's core strategy. ... Just sayin

                                                        • Re: How to "Manage" a Responder incident using DataServices API
                                                          Erik Hooper

                                                          Sorry I was out yesterday, glad you figured it out though. Just a note I would NEVER use the submit and forget, that will never give you any indication if the task was successful or not. You really need to make sure the submit was successful and wait for it to succeeded. The IncidentObjects + IncidentDeviceObjects classes were added at 10.1 as wrappers around a data set for ease or use. ( The beginnings of a real API). There is one for every OOTB table that we have.

                                                            • Re: How to "Manage" a Responder incident using DataServices API
                                                              david renz

                                                              Well, I certainly only cobbled it together. For some reason, I was not able to grab a ds from the FindIncidentAndRelatedTablesRequest and use it across all the operations involved in the "Manage" scenario. I had to make it fetch a new ds for each incident. I don't understand why. I also had to not use the FindIncidentAndRelatedTablesRequest in the ManageIncidents function (below), rather had to pass in the list of incidentIDs, but i will probably refactor that. If you have a moment to help me optimize the code I would appreciate it. If not, no sweat, it is working for now.

                                                               

                                                                      public bool ManageOpenIncidents()

                                                                      {

                                                                          Initialize();

                                                                          var incidents = ReturnIncidents();

                                                                          return ManageIncidents((incidents.Tables[RxDb.Tables.Incidents].Rows.Cast<DataRow>().Select(dr => Int32.Parse(dr[RxDb.Tables.Incidents.ID].ToString()))).ToList());

                                                                      }

                                                               

                                                                      public bool ManageIncidents(List<int> incidents)

                                                                      {

                                                                          try

                                                                          {

                                                                              foreach (var incidentId in incidents)

                                                                              {

                                                                                  ConfirmIncident(incidentId);

                                                                                  RestoreIncident(incidentId);

                                                                                  RestoreIncidentDevices(incidentId);

                                                                                  UpdateIncidentStatus(incidentId, 3);

                                                                                  UpdateIncidentStatus(incidentId, 6);

                                                                              }

                                                                              return true;

                                                                          }

                                                                          catch (Exception ex)

                                                                          {

                                                                             throw new Exception("Errors occurred in ManageIncidents:: " + ex.Message);

                                                                          }

                                                                      }

                                                               

                                                                      public bool ConfirmIncident(int incidentId)

                                                                      {

                                                                          try

                                                                          {

                                                                              var incidentInfo = ReturnIncidentInfoByIncidentId(incidentId);

                                                                              var incidentTable = incidentInfo.Tables[RxDb.Tables.Incidents];

                                                                              var singleIncident = incidentTable.Rows[0];

                                                               

                                                                              // confirm the incident

                                                                              singleIncident[RxDb.Tables.Incidents.Confirmed] = 1; // 1 = confirmed

                                                                              _dataServices.Submit(incidentInfo);

                                                                              return true;

                                                                          }

                                                                          catch(Exception ex)

                                                                          {

                                                                              throw new Exception("Errors occurred in ConfirmOpenIncidents:: " + ex.Message);

                                                                          }

                                                                      }

                                                               

                                                                      public bool RestoreIncident(int incidentId)

                                                                      {

                                                                          try

                                                                          {

                                                                              var incidentInfo = ReturnIncidentInfoByIncidentId(incidentId);

                                                                              var incidentTable = incidentInfo.Tables[RxDb.Tables.Incidents];

                                                                              var singleIncident = incidentTable.Rows[0];

                                                               

                                                                              // restore the incident

                                                                              singleIncident[RxDb.Tables.Incidents.Status] = 2;

                                                                              singleIncident[RxDb.Tables.Incidents.TimeRestored] = DateTime.Now;

                                                                              _dataServices.Submit(incidentInfo);

                                                               

                                                                              return true;

                                                                          }

                                                                          catch (Exception ex)

                                                                          {

                                                                              throw new Exception("Errors occurred in RestoreIncidents:: " + ex.Message);

                                                                          }

                                                                      }

                                                               

                                                                      public bool RestoreIncidentDevices(int incidentId)

                                                                      {

                                                                          try

                                                                          {

                                                                              var incidentInfo = ReturnIncidentInfoByIncidentId(incidentId);

                                                               

                                                                              // get the devices

                                                                              var incidentDeviceRequest = new FindDevicesForIncidentRequest(incidentId);

                                                                              incidentDeviceRequest = (FindDevicesForIncidentRequest) _dataServices.ExecuteRequest(incidentDeviceRequest);

                                                                              Miner.Responder.Framework.DeviceInfo[] devices = incidentDeviceRequest.RequestedDevices;

                                                               

                                                                              foreach (var device in devices)

                                                                              {

                                                                                  device.ActualStatus = device.ExpectedStatus;

                                                                              }

                                                                              _dataServices.Submit(incidentInfo);

                                                               

                                                                              return true;

                                                                          }

                                                                          catch (Exception ex)

                                                                          {

                                                                              throw new Exception("Errors occurred in RestoreIncidentDevices:: " + ex.Message);

                                                                          }

                                                                      }

                                                               

                                                                      public bool UpdateIncidentStatus(int incidentId, int statusId)

                                                                      {

                                                                          try

                                                                          {

                                                                              var incidentInfo = ReturnIncidentInfoByIncidentId(incidentId);

                                                                              var incidentTable = incidentInfo.Tables[RxDb.Tables.Incidents];

                                                                              var singleIncident = incidentTable.Rows[0];

                                                               

                                                                              // complete the incident

                                                                              singleIncident[RxDb.Tables.Incidents.Status] = statusId; //completed

                                                                              _dataServices.Submit(incidentInfo);

                                                               

                                                                              return true;

                                                                          }

                                                                          catch (Exception ex)

                                                                          {

                                                                              throw new Exception("Errors occurred in UpdateIncidentStatus:: " + ex.Message);

                                                                          }

                                                                      }

                                                                • Re: How to "Manage" a Responder incident using DataServices API
                                                                  david renz

                                                                  And ... refactored a bit more .... seems it needed AcceptChanges on the dataset ... thanks for the help everyone.

                                                                   

                                                                   

                                                                          public DataSet ReturnIncidentInfoByIncidentStatus(int status)

                                                                          {

                                                                              if (_dataServices == null) _dataServices = ResponderServices.GetDataServices();

                                                                              var incidentTablesRequest = new FindIncidentAndRelatedTablesRequest("rx_incidents.STATUS = " + status);

                                                                              incidentTablesRequest =

                                                                                  (FindIncidentAndRelatedTablesRequest)_dataServices.ExecuteRequest(incidentTablesRequest);

                                                                              return incidentTablesRequest.RequestedDataSet;

                                                                          }

                                                                   

                                                                          public bool ManageIncidents()

                                                                          {

                                                                              try

                                                                              {

                                                                                  var incidents = ReturnIncidentInfoByIncidentStatus(0);

                                                                   

                                                                                  foreach (DataRow singleIncident in incidents.Tables["rx_incidents"].Rows)

                                                                                  {

                                                                                      // confirm the incident

                                                                                      singleIncident[RxDb.Tables.Incidents.Confirmed] = 1; // 1 = confirmed

                                                                                      _dataServices.Submit(incidents);

                                                                   

                                                                                      // restore the incident

                                                                                      singleIncident[RxDb.Tables.Incidents.Status] = 2;

                                                                                      singleIncident[RxDb.Tables.Incidents.TimeRestored] = DateTime.Now;

                                                                                      _dataServices.Submit(incidents);

                                                                                      incidents.AcceptChanges();

                                                                   

                                                                                      // get the devices

                                                                                      var incidentDeviceRequest = new FindDevicesForIncidentRequest(Int32.Parse(singleIncident["ID"].ToString()));

                                                                                      incidentDeviceRequest = (FindDevicesForIncidentRequest)_dataServices.ExecuteRequest(incidentDeviceRequest);

                                                                                      Miner.Responder.Framework.DeviceInfo[] devices = incidentDeviceRequest.RequestedDevices;

                                                                   

                                                                                      foreach (var device in devices)

                                                                                      {

                                                                                          device.ActualStatus = device.ExpectedStatus;

                                                                                      }

                                                                                      _dataServices.Submit(incidents);

                                                                                      incidents.AcceptChanges();

                                                                   

                                                                                      // complete the incident

                                                                                      singleIncident[RxDb.Tables.Incidents.Status] = 3; //completed

                                                                                      _dataServices.Submit(incidents);

                                                                                      incidents.AcceptChanges();

                                                                   

                                                                                      // complete the incident

                                                                                      singleIncident[RxDb.Tables.Incidents.Status] = 6; //completed

                                                                                      _dataServices.Submit(incidents);

                                                                                      incidents.AcceptChanges();

                                                                                  }

                                                                                  return true;

                                                                              }

                                                                              catch (Exception ex)

                                                                              {

                                                                                 throw new Exception("Errors occurred in ManageIncidents:: " + ex.Message);

                                                                              }

                                                                          }

                                                                    • Re: How to "Manage" a Responder incident using DataServices API
                                                                      Erik Hooper

                                                                      I'm not sure this works

                                                                                          var incidentDeviceRequest = new FindDevicesForIncidentRequest(Int32.Parse(singleIncident["ID"].ToString()));

                                                                                          incidentDeviceRequest = (FindDevicesForIncidentRequest)_dataServices.ExecuteRequest(incidentDeviceRequest);

                                                                                          Miner.Responder.Framework.DeviceInfo[] devices = incidentDeviceRequest.RequestedDevices;

                                                                       

                                                                                          foreach (var device in devices)

                                                                                          {

                                                                                              device.ActualStatus = device.ExpectedStatus;

                                                                                          }

                                                                                          _dataServices.Submit(incidents);

                                                                      I think you are just setting a property on the deviceinfo which doesn't relate back to the incidents dataset.

                                                                      I would replace with

                                                                                          var devices =singleIncident.ChildRelations(RxDb.Relations.Incidents_IncidentDevices);

                                                                                          foreach (var device in devices)

                                                                                          {

                                                                                                device[RxDb.Tables.IncidentDevices.ActualStatus] = device[RxDb.Tables.IncidentDevices.ExpectedStatus];

                                                                                          }

                                                                                          _dataServices.Submit(singleIncident);

                                                                                          singleIncident.AcceptChanges();

                                                                      this will also avoid another request to ds. Hopefully this helps.