Esempio n. 1
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();

                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();
        }
Esempio n. 3
0
        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;
            }
        }
Esempio n. 4
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);
                }
            }
        }