private async System.Threading.Tasks.Task GetTaskFromFMS() { // flag that we are running isRunning = true; // record the start time DateTime start = DateTime.Now; // figure out if we need to authenticate to FMS or if we're good if (token == null || token == string.Empty) { lc.LogMessage("Logging into FMS.", LoggingLevel.Information); token = await fmserver.Authenticate(); if (token.ToLower().Contains("error")) { lc.LogMessage("Authentication error: " + token, LoggingLevel.Information); token = string.Empty; // and exit but without throwing an exception, we'll just try again on the next timer event return; } else { tokenRecieved = DateTime.Now; lc.LogMessage("Token " + token + " Received at " + tokenRecieved.ToLongTimeString(), LoggingLevel.Information); } } if (token != string.Empty) { // how old is the token? TimeSpan age = start - tokenRecieved; lc.LogMessage("Timed run; Token age = " + age, LoggingLevel.Information); // query FM to see if there are any outstanding tasks var find = fmserver.FindRequest(); var request1 = find.SearchCriterium(); request1.AddFieldSearch("flag_ready", "1"); var foundResponse = await find.Execute(); if (foundResponse.errorCode > 0) { lc.LogMessage("Nothing to do. " + fmserver.lastErrorCode.ToString() + " - " + fmserver.lastErrorMessage, LoggingLevel.Error); return; } // get the first FM record, we are just going to takcle that one var record = foundResponse.data.foundSet.records.First(); // capture the record id, we'll need it to later update the record int taskId = Convert.ToInt32(record.recordId); // capture whatever is in the notes fields already so that we can append to it string notes = record.fieldsAndData.Where(pair => pair.Key == "notes").Select(pair => pair.Value).First(); string direction = record.fieldsAndData.Where(pair => pair.Key == "motor_direction").Select(pair => pair.Value).First(); uint speed = Convert.ToUInt16(record.fieldsAndData.Where(pair => pair.Key == "motor_speed").Select(pair => pair.Value).First()); int motor_number = Convert.ToInt16(record.fieldsAndData.Where(pair => pair.Key == "motor_number").Select(pair => pair.Value).First()); int how_long = Convert.ToInt16(record.fieldsAndData.Where(pair => pair.Key == "duration").Select(pair => pair.Value).First()); uint pwm_frequency = Convert.ToUInt16(record.fieldsAndData.Where(pair => pair.Key == "motor_PWM_frequency").Select(pair => pair.Value).First()); string note = ""; // hook into the mother hat // this part is not very reliable in the Adafruit library it errors out on every 2nd iteration // so we are going to loop until no exception MotorHat mh = null; int tryCount = 0; while (tryCount < 5) { try { mh = new MotorHat(); await mh.InitAsync(pwm_frequency).ConfigureAwait(false); lc.LogMessage("hat - initialized with PWM frequency of: " + pwm_frequency.ToString(), LoggingLevel.Information); } catch (Exception ex) { tryCount++; note = "init error #" + tryCount + ":" + ex.Message + " - " + ex.InnerException; lc.LogMessage("Error: " + note, LoggingLevel.Error); // wait a little bit Thread.Sleep(10); // next loop iteration continue; } // all is well break; } // hook into the DC motor as specified try { lc.LogMessage("motor - before hooking into motor: " + motor_number.ToString(), LoggingLevel.Information); MotorHat.DCMotor motor = mh.GetMotor(motor_number); lc.LogMessage("motor - before setting speed for motor: " + speed.ToString(), LoggingLevel.Information); motor.SetSpeed(speed); lc.LogMessage("motor - before creating direction command: " + direction, LoggingLevel.Information); MotorHat.DCMotor.Command which_way = (MotorHat.DCMotor.Command)Enum.Parse(typeof(MotorHat.DCMotor.Command), direction); // run he motor lc.LogMessage("motor - before running the motor.", LoggingLevel.Information); motor.Run(which_way); lc.LogMessage("motor - before pausing the motor: " + how_long.ToString() + " milliseconds", LoggingLevel.Information); await Task.Delay(how_long); lc.LogMessage("motor - before stopping the motor.", LoggingLevel.Information); motor.Run(MotorHat.DCMotor.Command.RELEASE); } catch (Exception ex) { note = ex.Message + " - " + ex.InnerException; lc.LogMessage("Error: " + note, LoggingLevel.Error); } // write an update to FMS var editRequest = fmserver.EditRequest(taskId); editRequest.AddField("flag_ready", ""); editRequest.AddField("notes", DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString() + " - Done! " + Environment.NewLine + note + Environment.NewLine + notes); // execute the edit request var response = await editRequest.Execute(); if (fmserver.lastErrorCode == 0) { lc.LogMessage("Task finished.", LoggingLevel.Information); } else { lc.LogMessage("Task failed. " + fmserver.lastErrorCode.ToString() + " - " + fmserver.lastErrorMessage, LoggingLevel.Error); } // don't log out, re-using the token for 14 minutes or so //await fmserver.Logout(); //token = string.Empty; if (DateTime.Now >= tokenRecieved.AddMinutes(14)) { // don't really need to log out after 14 minutes, we can just re-use the same token int logoutResponse = await fmserver.Logout(); token = string.Empty; tokenRecieved = DateTime.Now; lc.LogMessage("Logging out of FMS.", LoggingLevel.Information); } } }
private static async Task RunAsync() { DateTime start = DateTime.Now; Console.WriteLine(start.ToString()); int newRecordId = 0; int newRecordModId = 0; int emptyRecordId = 0; // start the connection to FMS var fmserver = new FMS(server, testAccount, testPassword); // specify what file to work with // data from related files will also be available provided // that there are table occurrences to it in this target file // and that the account has access to it fmserver.SetFile(testFile); // --------------------------------------------------------------------------------------------------- // authenticate and get the token fmserver.SetLayout(testLayoutLogin); token = await fmserver.Authenticate(); Console.WriteLine(token); // --------------------------------------------------------------------------------------------------- // create an empty record Console.WriteLine("==> Creating a new empty record..."); // set the layout you want to interact with // all interactions are done through a layout, layout determines what table and what fields // basically your context fmserver.SetLayout(testLayoutData); var response = await fmserver.CreateEmptyRecord(); if (response.errorCode == 0) { emptyRecordId = Convert.ToInt32(response.recordId); Console.WriteLine("new empty record = " + emptyRecordId.ToString() + " in " + fmserver.CurrentLayout); } else { Console.WriteLine(response.errorCode.ToString() + " - " + response.errorMessage); } // --------------------------------------------------------------------------------------------------- // create a new record and set some data Console.WriteLine("==> Creating a new record with data..."); newRecordId = 0; fmserver.SetLayout(testLayoutData); // create a new request and specify what data to set in what field var request = fmserver.NewRecordRequest(); request.AddField("country", GetRandomString()); // execute the request response = await request.Execute(); if (response.errorCode == 0) { newRecordId = Convert.ToInt32(response.recordId); Console.WriteLine("new record = " + newRecordId.ToString() + " in " + fmserver.CurrentLayout); } else { Console.WriteLine(response.errorCode.ToString() + " - " + response.errorMessage); } // --------------------------------------------------------------------------------------------------- // delete a record, we will use the newRecordId that we just created Console.WriteLine("==> deleting that last record..."); fmserver.SetLayout(testLayoutData); response = await fmserver.DeleteRecord(newRecordId); if (response.errorCode == 0) { Console.WriteLine(newRecordId.ToString() + " deleted from " + fmserver.CurrentLayout); } else { Console.WriteLine(response.errorCode.ToString() + " - " + response.errorMessage); } // --------------------------------------------------------------------------------------------------- // create a record + a related record Console.WriteLine("==> Creating a new record with related data..."); newRecordId = 0; fmserver.SetLayout(testLayoutDataPortal); // create the request request = fmserver.NewRecordRequest(); // add data to two fields, these fields belong to the table as set by the layout's context // not related fields request.AddField("cake", "Yummy Cake"); request.AddField("country", GetRandomString()); // using a relationship that does not allow the creation or records will generate // error 101 "Record is missing" //request.AddRelatedField("fruit", "cake_FRUIT", GetRandomString(), 0); // the portal itself does not need to be on the layout //fmserver.SetLayout("CAKE_utility__No_Portals"); // add the related field - use 0 for the related record id to indicate that it is a new record // FMS accepts an empty recordId to denote a new related record // here were are creating one new record and setting two related fields request.AddRelatedField("fruit", "cake_FRUIT__ac", GetRandomString(), 0); request.AddRelatedField("number_field", "cake_FRUIT__ac", "7", 0); response = await request.Execute(); if (response.errorCode == 0) { newRecordId = Convert.ToInt32(response.recordId); Console.WriteLine("new record = " + newRecordId.ToString() + " in " + fmserver.CurrentLayout); } else { Console.WriteLine(response.errorCode.ToString() + " - " + response.errorMessage); } // --------------------------------------------------------------------------------------------------- // add one more related record to this parent // ==> would be nice if this was a simpler call than having to remember to use 'add related' and 0 Console.WriteLine("==> Adding a related record to that new record..."); // create the edit request var editRequest = fmserver.EditRequest(newRecordId); // add the new related record editRequest.AddRelatedField("fruit", "cake_FRUIT__ac", GetRandomString(), 0); response = await editRequest.Execute(); if (response.errorCode == 0) { Console.WriteLine("related record added to " + newRecordId.ToString() + " in " + fmserver.CurrentLayout); } else { Console.WriteLine(response.errorCode.ToString() + " - " + response.errorMessage); } // --------------------------------------------------------------------------------------------------- // do some edits on the empty record we created earlier Console.WriteLine("==> Adding data to the empty record..."); fmserver.SetLayout(testLayoutData); // create the edit request editRequest = fmserver.EditRequest(emptyRecordId); // modify a field, in this case a repeating field editRequest.AddField("field_number_repeat", "100", 1); // execute the request response = await editRequest.Execute(); if (response.errorCode == 0) { Console.WriteLine("data added to record = " + emptyRecordId.ToString() + " in " + fmserver.CurrentLayout); } else { Console.WriteLine(response.errorCode.ToString() + " - " + response.errorMessage); } // --------------------------------------------------------------------------------------------------- // get a record and its portal data Console.WriteLine("==> Get all the record data for recordId " + newRecordId.ToString()); fmserver.SetLayout(testLayoutDataPortal); // create a find request, using the record that we create a while ago var findRequest = fmserver.FindRequest(newRecordId); // execute the record var getResponse = await findRequest.Execute(); if (getResponse.errorCode == 0) { Console.WriteLine("record count for " + newRecordId.ToString() + " in " + fmserver.CurrentLayout + " is " + getResponse.recordCount + ", with " + getResponse.data.relatedTableNames.Count + " portals"); newRecordModId = Convert.ToInt32(getResponse.data.foundSet.records[0].modId); } else { Console.WriteLine(getResponse.errorCode.ToString()); } // --------------------------------------------------------------------------------------------------- // update a specific related record // the the Table Occurrence name of the first related set of the first found record, from one of our previous requests string TOname = getResponse.data.foundSet.records[0].relatedRecordSets[0].tableName; FMRecord firstRelatedRecord = getResponse.data.foundSet.records[0].relatedRecordSets[0].records[0]; // field name from that related table, and its original value, last field in the list KeyValuePair <string, string> kv = firstRelatedRecord.fieldsAndData.Last(); string oldValue = kv.Value; string relatedFieldName = kv.Key; // record id for the first related record int relatedRecordId = Convert.ToInt32(getResponse.data.foundSet.records[0].relatedRecordSets[0].records[0].recordId); // create the edit request editRequest = fmserver.EditRequest(newRecordId); // modify a field, in this case a repeating field string newValue = "99"; editRequest.AddRelatedField(relatedFieldName, TOname, newValue, relatedRecordId); // execute the request response = await editRequest.Execute(); if (response.errorCode == 0) { Console.WriteLine("data updated on related record = " + relatedRecordId.ToString() + " in " + fmserver.CurrentLayout + ", field = " + relatedFieldName + ", old value = " + oldValue + ", new value = " + newValue); } else { Console.WriteLine(response.errorCode.ToString() + " - " + response.errorMessage); } // --------------------------------------------------------------------------------------------------- // get data that same record but with just one portal instead of everything Console.WriteLine("==> Get record data plus a selected portal..."); // get the first portal name from the previous test string portalName = getResponse.data.foundSet.records[0].relatedRecordSets[0].tableLayoutObjectName; // create the find request findRequest = fmserver.FindRequest(newRecordId); // specify the portal name to include findRequest.AddPortal(portalName); // execute the request var getResponsePartial = await findRequest.Execute(); if (getResponsePartial.errorCode == 0) { Console.WriteLine("record count for " + newRecordId.ToString() + " in " + fmserver.CurrentLayout + " is " + getResponsePartial.recordCount + ", with " + getResponsePartial.data.relatedTableNames.Count + " portals"); } else { Console.WriteLine(getResponsePartial.errorCode.ToString()); } // --------------------------------------------------------------------------------------------------- // try with a portal that does not have a layout object name, does it then use the relationship/TO name? // seems not to, always fails. Not sure if that is a bug - waiting on feedback from FMI. Console.WriteLine("==> Get record data plus a selected portal that has no object name..."); Console.WriteLine("==> EXPECTED TO FAIL WITH ERROR 477, FM requires a named portal."); // get the first portal name from the previous test portalName = getResponse.data.foundSet.records[0].relatedRecordSets[2].tableName; findRequest = fmserver.FindRequest(newRecordId); findRequest.AddPortal(portalName); getResponsePartial = await findRequest.Execute(); if (getResponsePartial.errorCode == 0) { Console.WriteLine("record count for " + newRecordId.ToString() + " in " + fmserver.CurrentLayout + " is " + getResponsePartial.recordCount + ", with " + getResponsePartial.data.relatedTableNames.Count + " portals"); } else { Console.WriteLine(getResponsePartial.errorCode.ToString()); } // --------------------------------------------------------------------------------------------------- // delete related record Console.WriteLine("==> delete a related record"); // ==> can only do one at a time otherwise json complains of duplicate 'relatedRecord" key // ==> needs to be fixed to not allow multiple // set the context fmserver.SetLayout(testLayoutDataPortal); // grab the first record FMRecord firstRecord = getResponse.data.foundSet.records[0]; // and the first related record for that record, from the first portal firstRelatedRecord = firstRecord.relatedRecordSets[0].records[0]; // get that record's id int firstReleatedRecordId = Convert.ToInt32(firstRelatedRecord.recordId); // and the table occurrence for that first related set of records string relationship = firstRecord.relatedRecordSets[0].tableName; // execute the delete command response = await fmserver.DeleteRelatedRecord(newRecordId, relationship, firstReleatedRecordId); if (response.errorCode == 0) { Console.WriteLine("related record " + firstReleatedRecordId.ToString() + " deleted in " + fmserver.CurrentLayout + " from " + relationship + " for parent record " + newRecordId); } else { Console.WriteLine(getResponse.errorCode.ToString()); } // --------------------------------------------------------------------------------------------------- // create a record and set repeating field Console.WriteLine("==> new record and set repeating field..."); // some housekeeping since we keep reusing this variable newRecordId = 0; // set the context fmserver.SetLayout(testLayoutData); // create the request request = fmserver.CreateRequest(); // add a field + value to the request request.AddField("country", GetRandomString()); // add another field, this one is a repeating field // set 2nd repetition request.AddField("field_number_repeat", "17", 2); // execute the request response = await request.Execute(); if (response.errorCode == 0) { newRecordId = Convert.ToInt32(response.recordId); Console.WriteLine("new record created and repeating field set = " + newRecordId + " in " + fmserver.CurrentLayout); } else { Console.WriteLine(response.errorCode.ToString() + " - " + response.errorMessage); } // --------------------------------------------------------------------------------------------------- // edit a record and specify a particular mod id // hat is the mod id of a newly created record, 0 or 1? --> 0 // ==> can fail because we didn't correctly capture the newRecordModId from the record we just created // we would have to do a Get on it first to know it. Console.WriteLine("==> edit a record by specifying both recordId and modId"); // set the context fmserver.SetLayout(testLayoutData); // create the request, specifying the target record by id and also specifying the mod id var requestEditWithMod = fmserver.EditRequest(newRecordId, newRecordModId); // set the value for the target field requestEditWithMod.AddField("fruit", "Lorem Ipsum"); // execute the request response = await requestEditWithMod.Execute(); if (response.errorCode == 0) { Console.WriteLine("record edited = " + newRecordId + " in " + fmserver.CurrentLayout + " - mod id was " + newRecordModId); } else { Console.WriteLine(response.errorCode.ToString() + " - " + response.errorMessage); } // --------------------------------------------------------------------------------------------------- // edit a record with non-matching mod id // -> same as above but change the mod id to lower than what is expected // --------------------------------------------------------------------------------------------------- // do a search Console.WriteLine("==> doing a find with criteria for range and start record"); // set the context fmserver.SetLayout(testLayoutDataPortal); // create the request var getSelectedRecords = fmserver.FindRequest(); // specify how many records to return getSelectedRecords.setHowManyRecords(3); // specify the start record (offset) getSelectedRecords.setStartRecord(2); // execute the request var getFindResponse = await getSelectedRecords.Execute(); if (getFindResponse.errorCode > 0) { Console.WriteLine(getFindResponse.errorCode.ToString() + " - " + getFindResponse.result); } else { // at this point you could serialize these classes in anything you like // whatever is supported by the version of .NET for your platform // XML, JSON, DataSet, DataTable,... // get some output to the console PrintOut(getFindResponse); } // --------------------------------------------------------------------------------------------------- // same search and include only two records from the first portal Console.WriteLine("==> doing a find with criteria for range and start record, and a sort, and a selected portal with limited records"); // set context fmserver.SetLayout(testLayoutDataPortal); // create the request getSelectedRecords = fmserver.FindRequest(); // add a portal, remember that you can use named parameters for any combination of startAt and howMany // those are optional parameters getSelectedRecords.AddPortal("first_portal", howManyRecords: 1, StartAtRecordNumber: 5); // specify the regular found set criteria (range and offset) getSelectedRecords.setHowManyRecords(5); getSelectedRecords.setStartRecord(10); // and also sort that found set getSelectedRecords.AddSortField("modification_id", FMS.SortDirection.descend); getSelectedRecords.AddSortField("country", FMS.SortDirection.ascend); // execute the request getFindResponse = await getSelectedRecords.Execute(); if (getFindResponse.errorCode > 0) { Console.WriteLine(getFindResponse.errorCode.ToString() + " - " + getFindResponse.result); } else { // at this point you could serialize these classes in anything you like // whatever is supported by the version of .NET for your platform // XML, JSON, DataSet, DataTable,... // get some output to the console PrintOut(getFindResponse); } // --------------------------------------------------------------------------------------------------- // do an actual search, for values in a field Console.WriteLine("==> doing a find with criteria for multiple fields"); // set the context fmserver.SetLayout(testLayoutDataPortal); // create the request getSelectedRecords = fmserver.FindRequest(); // add two sets of search criteria (group of fields), these will be executed as an AND search var request1 = getSelectedRecords.SearchCriterium(); request1.AddFieldSearch("country", "belgium"); request1.AddFieldSearch("cake", "spice"); var request2 = getSelectedRecords.SearchCriterium(); request2.AddFieldSearch("country", "belgium"); request2.AddFieldSearch("cake", "rum"); // only return related data from the first portal getSelectedRecords.AddPortal("first_portal"); // execute the request getFindResponse = await getSelectedRecords.Execute(); if (getFindResponse.errorCode > 0) { Console.WriteLine(getFindResponse.errorCode.ToString() + " - " + getFindResponse.result); } else { // at this point you could serialize these classes in anything you like // whatever is supported by the version of .NET for your platform // XML, JSON, DataSet, DataTable,... // get some output to the console PrintOut(getFindResponse); } // --------------------------------------------------------------------------------------------------- // set a global field Console.WriteLine("==> setting a single global field"); // set the context fmserver.SetLayout(testLayoutData); // set the global (executes it automatically) var globalResponse = await fmserver.SetSingleGlobalField("global_field_text", "Hello World!"); // get a random record back to confirm the values findRequest = fmserver.FindRequest(1); getFindResponse = await findRequest.Execute(); if (getFindResponse.errorCode > 0) { Console.WriteLine(getFindResponse.errorCode.ToString() + " - " + getFindResponse.result); } else { // at this point you could serialize these classes in anything you like // whatever is supported by the version of .NET for your platform // XML, JSON, DataSet, DataTable,... // get some output to the console PrintOut(getFindResponse); } // --------------------------------------------------------------------------------------------------- // add multiple globals and get the response back Console.WriteLine("==> setting multiple global fields, including repeats"); // set the context fmserver.SetLayout(testLayoutData); // create a list of global fields and their values you want to set List <Field> fields = new List <Field>(); fields.Add(new Field("global_field_number", "7")); fields.Add(new Field("global_field_text", "Lorem Ipsum")); // and setting the 3rd repeat of a global: fields.Add(new Field("global_field_number_repeat", 3, "77")); // execute it globalResponse = await fmserver.SetMultipleGlobalField(fields); // get a random record back to confirm the values findRequest = fmserver.FindRequest(1); getFindResponse = await findRequest.Execute(); if (getFindResponse.errorCode > 0) { Console.WriteLine(getFindResponse.errorCode.ToString() + " - " + getFindResponse.result); } else { // at this point you could serialize these classes in anything you like // whatever is supported by the version of .NET for your platform // XML, JSON, DataSet, DataTable,... // get some output to the console PrintOut(getFindResponse); } // --------------------------------------------------------------------------------------------------- // do something with containers too? // stream to base64 text? // probably not, FMS give you back a URL to use, you can grab the byte[] and work from that if you need to // --------------------------------------------------------------------------------------------------- // add a sort by value list name // --------------------------------------------------------------------------------------------------- // log out Console.WriteLine("Logging out..."); int responseCode = await fmserver.Logout(); Console.WriteLine("logout response = " + responseCode.ToString()); // --------------------------------------------------------------------------------------------------- // wrapping up DateTime end = DateTime.Now; double elapsed = (end - start).TotalMilliseconds; Console.WriteLine(end.ToString()); Console.WriteLine("total milliseconds = " + elapsed.ToString()); Console.WriteLine(""); Console.Beep(); Console.WriteLine("Press any key to close this window..."); Console.ReadKey(); }
private async void Timer_Tick(ThreadPoolTimer timer) { // update the display ShowPixel(pixelCounter); senseHat.Display.Update(); // record the start time DateTime start = DateTime.Now; // figure out if we need to authenticate to FMS or if we're good if (token == null || token == string.Empty) { lc.LogMessage("Logging into FMS.", LoggingLevel.Information); token = await fmserver.Authenticate(); if (token.ToLower().Contains("error")) { FillDisplayOrange(); lc.LogMessage("Authentication error: " + token, LoggingLevel.Information); token = string.Empty; // and exit but without throwing an exception, we'll just try again on the next timer event return; } else { tokenRecieved = DateTime.Now; lc.LogMessage("Token " + token + " Received at " + tokenRecieved.ToLongTimeString(), LoggingLevel.Information); } } else if (DateTime.Now >= tokenRecieved.AddMinutes(14)) { int logoutResponse = await fmserver.Logout(); token = string.Empty; tokenRecieved = DateTime.Now; lc.LogMessage("Logging out of FMS.", LoggingLevel.Information); // we'll just wait for the next timer run return; } if (token != string.Empty) { // how old is the token? TimeSpan age = start - tokenRecieved; lc.LogMessage("Timed run; Token age = " + age, LoggingLevel.Information); // get some data from the RPI itself string processorName = string.Empty; string rpiModel = string.Empty; string serial = string.Empty; try { processorName = Raspberry.Board.Current.ProcessorName; rpiModel = Raspberry.Board.Current.Model.ToString(); serial = Raspberry.Board.Current.SerialNumber; } catch (Exception ex) { lc.LogMessage("Error in Rpi package = " + ex.Message, LoggingLevel.Error); } // update the sensehat sensors and get the data double humidityReadout = 0; double?tempReadout = 0; double?pressureReadout = 0; try { senseHat.Sensors.ImuSensor.Update(); senseHat.Sensors.HumiditySensor.Update(); senseHat.Sensors.PressureSensor.Update(); humidityReadout = senseHat.Sensors.HumiditySensor.Readings.Humidity; tempReadout = senseHat.Sensors.Temperature; pressureReadout = senseHat.Sensors.Pressure; } catch (Exception ex) { lc.LogMessage("Error in Rpi package = " + ex.Message, LoggingLevel.Error); } // write it to FMS var request = fmserver.NewRecordRequest(); if (processorName != null) { request.AddField("rpiProcessor", processorName); } if (rpiModel != null) { request.AddField("rpiModel", rpiModel); } if (serial != null) { request.AddField("rpiSerial", serial); } request.AddField("when_start", start.ToString()); request.AddField("humidity", humidityReadout.ToString()); request.AddField("temperature", tempReadout.ToString()); if (pressureReadout != null) { request.AddField("pressure", pressureReadout.ToString()); } request.AddField("when", DateTime.Now.ToString()); // add a script to run // calculate the time gap since the last record request.AddScript(ScriptTypes.after, "calculate_gap"); var response = await request.Execute(); if (fmserver.lastErrorCode != 0) { lc.LogMessage("Error on sending data to FMS: " + fmserver.lastErrorMessage + " (code=" + fmserver.lastErrorCode + ")", LoggingLevel.Critical); FillDisplayRed(); Thread.Sleep(TimeSpan.FromSeconds(4)); } // if there was a script error, let's output that too if (fmserver.lastErrorCodeScript != 0) { lc.LogMessage("Script Error: " + fmserver.lastErrorCodeScript, LoggingLevel.Critical); } // don't log out, re-using the token for 14 minutes or so //await fmserver.Logout(); //token = string.Empty; } // clear the display again // this determines how long the LED is lit, the timer itself is set up top Thread.Sleep(TimeSpan.FromMilliseconds(500)); senseHat.Display.Clear(); senseHat.Display.Update(); pixelCounter++; if (pixelCounter > 63) { pixelCounter = 0; } }
private async System.Threading.Tasks.Task GetTaskFromFMS() { // flag that we are running isRunning = true; // record the start time DateTime start = DateTime.Now; // figure out if we need to authenticate to FMS or if we're good if (token == null || token == string.Empty) { lc.LogMessage("Logging into FMS.", LoggingLevel.Information); token = await fmserver.Authenticate(); if (token.ToLower().Contains("error")) { lc.LogMessage("Authentication error: " + token, LoggingLevel.Information); token = string.Empty; // and exit but without throwing an exception, we'll just try again on the next timer event return; } else { tokenRecieved = DateTime.Now; lc.LogMessage("Token " + token + " Received at " + tokenRecieved.ToLongTimeString(), LoggingLevel.Information); } } if (token != string.Empty) { // how old is the token? TimeSpan age = start - tokenRecieved; lc.LogMessage("Timed run; Token age = " + age, LoggingLevel.Information); // query FM to see if there are any outstanding tasks var find = fmserver.FindRequest(); // we only need one at most //find.SetStartRecord(1); //find.SetHowManyRecords(1); var request1 = find.SearchCriterium(); request1.AddFieldSearch("flag_ready", "1"); var foundResponse = await find.Execute(); if (foundResponse.errorCode > 0) { lc.LogMessage("Nothing to do. " + fmserver.lastErrorCode.ToString() + " - " + fmserver.lastErrorMessage, LoggingLevel.Error); return; } // get the first FM record, we are just going to takcle that one var record = foundResponse.data.foundSet.records.First(); // capture the record id, we'll need it to later update the record int taskId = Convert.ToInt32(record.recordId); // capture whatever is in the notes fields already so that we can append to it string notes = record.fieldsAndData.Where(pair => pair.Key == "notes").Select(pair => pair.Value).First(); // download the audio file string url = record.fieldsAndData.Where(pair => pair.Key == "audio_file").Select(pair => pair.Value).First(); StorageFolder folder = ApplicationData.Current.LocalFolder; fmserver.SetDownloadFolder(folder.Path + @"\"); FileInfo audioFile; string fmsMessage = string.Empty; try { audioFile = await fmserver.DownloadFileFromContainerField(url, "play.mp3"); fmsMessage = fmserver.lastErrorMessage; lc.LogMessage("audio file downloaded: " + audioFile.FullName, LoggingLevel.Information); } catch (Exception ex) { lc.LogMessage("audio file not downloaded.", LoggingLevel.Error); // unflag the FM record and write the exception to notes var req = fmserver.EditRequest(taskId); req.AddField("flag_completed_when", DateTime.Now.ToString()); req.AddField("flag_ready", ""); req.AddField("notes", DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString() + " - error! " + ex.InnerException.Message + Environment.NewLine + notes); // execute the request var resp = await req.Execute(); return; } if (audioFile != null) { try { lc.LogMessage("before playing audio file: " + audioFile.FullName, LoggingLevel.Information); // play the audio StorageFile file = await StorageFile.GetFileFromPathAsync(audioFile.FullName); //await PlayAudioThroughMediaPlayer(file); //Thread.Sleep(2000); var player = new AudioPlayer(); await player.LoadFileAsync(file); player.Play("play.mp3", 0.5); GC.Collect(); // delete the file lc.LogMessage("before deleting audio file.", LoggingLevel.Information); try { await file.DeleteAsync(); } catch (Exception ex) { lc.LogMessage("Could not delete audio file: " + ex.InnerException, LoggingLevel.Error); } lc.LogMessage("after deleting audio file.", LoggingLevel.Information); } catch (Exception ex) { fmsMessage = ex.InnerException.Message; } } // write an update to FMS var editRequest = fmserver.EditRequest(taskId); editRequest.AddField("flag_completed_when", DateTime.Now.ToString()); editRequest.AddField("flag_ready", ""); if (audioFile == null) { editRequest.AddField("notes", DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString() + " - error! No file was downloaed" + Environment.NewLine + notes); } else if (fmsMessage != "OK") { editRequest.AddField("notes", DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString() + " - error! Could not play the audio" + Environment.NewLine + notes); } else { editRequest.AddField("notes", DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString() + " - Done!" + Environment.NewLine + notes); } // execute the edit request var response = await editRequest.Execute(); if (fmserver.lastErrorCode == 0) { lc.LogMessage("Task finished.", LoggingLevel.Information); } else { lc.LogMessage("Task failed. " + fmserver.lastErrorCode.ToString() + " - " + fmserver.lastErrorMessage, LoggingLevel.Error); } // don't log out, re-using the token for 14 minutes or so //await fmserver.Logout(); //token = string.Empty; if (DateTime.Now >= tokenRecieved.AddMinutes(14)) { // don't really need to log out after 14 minutes, we can just re-use the same token int logoutResponse = await fmserver.Logout(); token = string.Empty; tokenRecieved = DateTime.Now; lc.LogMessage("Logging out of FMS.", LoggingLevel.Information); } } }