Esempio n. 1
0
        public void AudioBuffer_Persist()
        {
            byte[]      rawBytes = new byte[] { 1, 2, 3, 4, 5, 6 };
            var         wf       = WaveFormatEx.Create(WaveFormatTag.WAVE_FORMAT_APTX, 16000, 16, 2, 0, 16000);
            AudioBuffer buffer   = new AudioBuffer(rawBytes, wf);
            AudioBuffer bresult  = default(AudioBuffer);

            var p1    = Pipeline.Create();
            var store = PsiStore.Create(p1, "audio", null);

            Generators.Return(p1, buffer).Write("audio", store);
            p1.RunAsync();

            var p2     = Pipeline.Create();
            var store2 = PsiStore.Open(p2, "audio", null);

            store2.OpenStream <AudioBuffer>("audio").Do(b => bresult = b);
            p2.RunAsync();
            System.Threading.Thread.Sleep(100);
            p1.Dispose();
            p2.Dispose();

            Assert.AreEqual(6, bresult.Length);
            Assert.AreEqual(6, bresult.Data.Length);
            Assert.AreEqual(wf, bresult.Format);
            CollectionAssert.AreEqual(rawBytes, bresult.Data);
        }
Esempio n. 2
0
        /// <summary>
        /// Exports data based on the specified export command.
        /// </summary>
        /// <param name="exportCommand">The export command.</param>
        /// <returns>An error code or 0 if success.</returns>
        public static int Run(Verbs.ExportCommand exportCommand)
        {
            const string videoStreamName        = "VideoImageCameraView";
            const string videoEncodedStreamName = "VideoEncodedImageCameraView";
            const string audioStreamName        = "Audio";

            var pngEncoder = new ImageToPngStreamEncoder();
            var decoder    = new ImageFromStreamDecoder();

            // Create a pipeline
            using var p = Pipeline.Create(deliveryPolicy: DeliveryPolicy.Unlimited);

            // Open the psi store for reading
            var store = PsiStore.Open(p, exportCommand.StoreName, exportCommand.StorePath);

            // Get references to the various streams. If a stream is not present in the store,
            // the reference will be null.
            var accelerometer = store.OpenStreamOrDefault <(Vector3D, DateTime)[]>("Accelerometer");
Esempio n. 3
0
        /// <summary>
        /// Transport messages from stream to the file system, message queue, etc.
        /// </summary>
        /// <param name="stream">Stream name.</param>
        /// <param name="store">Store name.</param>
        /// <param name="path">Store path.</param>
        /// <param name="transport">Transport component (FileWriter, NetMQWriter, etc.)</param>
        /// <returns>Success flag.</returns>
        private static int TransportStreamMessages(string stream, string store, string path, Func <Pipeline, IConsumer <dynamic> > transport)
        {
            using (var pipeline = Pipeline.Create())
            {
                var data     = PsiStore.Open(pipeline, store, Path.GetFullPath(path));
                var messages = data.OpenDynamicStream(stream);
                messages.PipeTo(transport(pipeline));
                messages.Count().Do(i =>
                {
                    if (i % 100 == 0)
                    {
                        Console.Write('.');
                    }
                });
                pipeline.Run();
                Console.WriteLine();
            }

            return(0);
        }
        public void CrossFrameworkDeserializeMembers()
        {
            if (!File.Exists(OtherTestExe))
            {
                Assert.Inconclusive($"Unable to locate {OtherTestExe} to generate the test store for {nameof(this.CrossFrameworkDeserializeMembers)}.");
            }

            this.ExecuteTest(OtherTestExe, $"!{nameof(this.CrossFrameworkSerializeMembers)}");

            TypeMembers result = null;

            using (var p = Pipeline.Create())
            {
                var store = PsiStore.Open(p, "Store2", this.testPath);
                store.OpenStream <TypeMembers>("TypeMembers").Do(x => result = x.DeepClone());
                p.Run();
            }

            Assert.AreEqual(0x7777AAA, result.IntValue);
            Assert.AreEqual(0xBB, result.ByteValue);
            Assert.AreEqual(true, result.BoolValue);
            Assert.AreEqual(0x7CDD, result.ShortValue);
            Assert.AreEqual(0x77777777EEEEEEEE, result.LongValue);
            Assert.AreEqual('G', result.CharValue);
            Assert.AreEqual("This is a test.", result.StringValue);
            Assert.AreEqual(Math.PI, result.DoubleValue);
            Assert.AreEqual(-1.234f, result.FloatValue);
            CollectionAssert.AreEqual(new[] { 0.1f, 2.3f }, result.FloatArray);
            CollectionAssert.AreEqual(new[] { "one", "two" }, result.StringList);
            CollectionAssert.AreEqual(new[] { "bbb", "ccc" }, result.StringArraySegment.ToArray());
            CollectionAssert.AreEqual(new[] { TimeSpan.Zero, TimeSpan.FromSeconds(1) }, result.Queue);
            Assert.IsTrue(result.IntComparer.Equals(1952, 1952));
            Assert.AreEqual("This is a tuple.", result.Tuple.Item2);
            Assert.AreEqual(new DateTime(2020, 1, 2), result.ValueTuple.Item1);
            CollectionAssert.AreEqual(new[] { 782, 33 }, result.ValueTuple.Item2);
            CollectionAssert.AreEqual(new[] { "three", "four" }, result.StringArray);
            Assert.IsTrue(result.EnumComparer.Equals(DayOfWeek.Friday, DayOfWeek.Friday));
            Assert.AreEqual(2, result.Dictionary.Count);
            Assert.AreEqual(1, result.Dictionary["one"]);
            Assert.AreEqual(2, result.Dictionary["two"]);
        }
        private dynamic InstanceToDynamic <T>(T instance)
        {
            // Rube Goldberg machine to convert instance to dynamic by
            // writing to a store (typed) and reading back as dynamic
            using (var p = Pipeline.Create())
            {
                var gen      = Generators.Return(p, instance);
                var exporter = PsiStore.Create(p, "Test", this.path);
                exporter.Write(gen.Out, "Data", true);
                p.Run();
            }

            using (var p = Pipeline.Create())
            {
                var importer = PsiStore.Open(p, "Test", this.path);
                var data     = importer.OpenDynamicStream("Data");
                var result   = data.ToEnumerable();
                p.Run();
                return(result.First());
            }
        }
        static void Main(string[] args)
        {
            using (Pipeline pipeline = Pipeline.Create())
            {
                //var store = Store.Create(pipeline, "deepSpeechTest", ".\\recordings");
                //var storeIn = Store.Open(pipeline, "deepSpeechTest", ".\\recordings\\deepSpeechTest.0000");
                var storeIn = PsiStore.Open(pipeline, "mmr", "\\Users\\wwilson\\source\\repos\\MultimodalRecorder\\data\\DataStores");

                var replay = true;
                IProducer <AudioBuffer> audioSource;
                if (replay)
                {
                    audioSource = storeIn.OpenStream <AudioBuffer>("AudioIn");
                    //audioSource = null;
                }
                else
                {
                    audioSource = new AudioCapture(
                        pipeline,
                        new AudioCaptureConfiguration()
                    {
                        Format = Microsoft.Psi.Audio.WaveFormat.Create16kHz1Channel16BitPcm(),
                        DropOutOfOrderPackets = true
                    }
                        );

                    //audioSource.Write("Audio", store);
                }

                var dsr = new DeepSpeechRecognizer(pipeline);

                audioSource.PipeTo(dsr.AudioIn);
                //audioSource.Do(x => Console.Write('x'));
                dsr.TextOut.Do(x => Console.WriteLine(x));

                Console.WriteLine("Starting...");
                pipeline.Run();
                Console.ReadLine();
            }
        }
Esempio n. 7
0
        /// <summary>
        /// Display stream metadata info.
        /// </summary>
        /// <param name="stream">Stream name.</param>
        /// <param name="store">Store name.</param>
        /// <param name="path">Store path.</param>
        /// <returns>Success flag.</returns>
        internal static int DisplayStreamInfo(string stream, string store, string path)
        {
            Console.WriteLine($"Stream Metadata (stream={stream}, store={store}, path={path})");
            using (var pipeline = Pipeline.Create())
            {
                var data = PsiStore.Open(pipeline, store, Path.GetFullPath(path));
                var meta = data.AvailableStreams.First(s => s.Name == stream) as PsiStreamMetadata;
                if (meta == null)
                {
                    throw new NotSupportedException("Currently, only Psi Stores are supported.");
                }

                Console.WriteLine($"ID: {meta.Id}");
                Console.WriteLine($"Name: {meta.Name}");
                Console.WriteLine($"TypeName: {meta.TypeName}");
                Console.WriteLine($"SupplementalMetadataTypeName: {meta.SupplementalMetadataTypeName}");
                Console.WriteLine($"MessageCount: {meta.MessageCount}");
                Console.WriteLine($"AverageFrequency: {meta.AverageFrequency}");
                Console.WriteLine($"AverageLatency: {meta.AverageLatency}");
                Console.WriteLine($"AverageMessageSize: {meta.AverageMessageSize}");
                Console.WriteLine($"FirstMessageOriginatingTime: {meta.FirstMessageOriginatingTime}");
                Console.WriteLine($"LastMessageOriginatingTime: {meta.LastMessageOriginatingTime}");
                Console.WriteLine($"IsClosed: {meta.IsClosed}");
                Console.WriteLine($"IsIndexed: {meta.IsIndexed}");
                Console.WriteLine($"IsPersisted: {meta.IsPersisted}");
                Console.WriteLine($"IsPolymorphic: {meta.IsPolymorphic}");
                if (meta.IsPolymorphic)
                {
                    Console.WriteLine("RuntimeTypes:");
                    foreach (var type in meta.RuntimeTypes.Values)
                    {
                        Console.WriteLine(type);
                    }
                }
            }

            return(0);
        }
Esempio n. 8
0
        /// <summary>
        /// List streams within store.
        /// </summary>
        /// <param name="store">Store name.</param>
        /// <param name="path">Store path.</param>
        /// <param name="showSize">Indicates whether to show the stream size information.</param>
        /// <returns>Success flag.</returns>
        internal static int ListStreams(string store, string path, bool showSize = false)
        {
            var stringBuilder = new StringBuilder();

            using (var pipeline = Pipeline.Create())
            {
                var data = PsiStore.Open(pipeline, store, Path.GetFullPath(path));

                stringBuilder.AppendLine($"{data.AvailableStreams.Count()} Available Streams (store={store}, path={path})");
                if (showSize)
                {
                    stringBuilder.AppendLine("[Avg. Message Size / Total Size]; * marks indexed streams");
                    foreach (var stream in data.AvailableStreams.OrderByDescending(s => (double)s.MessageCount * s.AverageMessageSize))
                    {
                        var psiStream = stream as PsiStreamMetadata;
                        if (psiStream == null)
                        {
                            throw new NotSupportedException("Currently, only Psi Stores are supported.");
                        }

                        var isIndexed = psiStream.IsIndexed ? "* " : "  ";
                        stringBuilder.AppendLine($"{isIndexed}[{(double)stream.AverageMessageSize / 1024:0.00}Kb / {(stream.AverageMessageSize * (double)stream.MessageCount) / (1024 * 1024):0.00}Mb] {stream.Name} ({stream.TypeName.Split(',')[0]})");
                    }
                }
                else
                {
                    foreach (var stream in data.AvailableStreams)
                    {
                        stringBuilder.AppendLine($"{stream.Name} ({stream.TypeName.Split(',')[0]})");
                    }
                }
            }

            Console.WriteLine(stringBuilder.ToString());

            return(0);
        }
Esempio n. 9
0
        /// <summary>
        /// Print (first n) messages from stream.
        /// </summary>
        /// <param name="stream">Stream name.</param>
        /// <param name="store">Store name.</param>
        /// <param name="path">Store path.</param>
        /// <param name="number">Number of messages to display.</param>
        /// <returns>Success flag.</returns>
        internal static int DisplayStreamMessages(string stream, string store, string path, int number)
        {
            Console.WriteLine($"Stream Messages (stream={stream}, store={store}, path={path}, number={number})");
            using (var pipeline = Pipeline.Create())
            {
                var count = 0;
                var data  = PsiStore.Open(pipeline, store, Path.GetFullPath(path));
                data.OpenDynamicStream(stream).Do((m, e) =>
                {
                    if (count++ < number)
                    {
                        PrintMessage(m, e);
                    }
                });
                pipeline.RunAsync();

                while (count < number)
                {
                    Thread.Sleep(100);
                }
            }

            return(0);
        }
Esempio n. 10
0
        public async Task SessionCreateDerivedPartition()
        {
            var dataset = new Dataset();
            var session = dataset.CreateSession();

            // generate a test store
            var originalStoreName = "OriginalStore";

            GenerateTestStore(originalStoreName, StorePath);

            // add a partition
            var partition0 = session.AddPsiStorePartition(originalStoreName, StorePath, "Partition_0");

            Assert.AreEqual(1, session.Partitions.Count);
            Assert.AreEqual("Partition_0", session.Partitions[0].Name);

            int multiplier = 7;

            // create a derived partition which contains the values from the original stream multiplied by a multiplier
            await session.CreateDerivedPsiPartitionAsync(
                (pipeline, importer, exporter, parameter) =>
            {
                var inputStream   = importer.OpenStream <int>("Root");
                var derivedStream = inputStream.Select(x => x *parameter).Write("DerivedStream", exporter);
            },
                multiplier,
                "Partition_1",
                false,
                "DerivedStore",
                StorePath);

            // should have created a new store partition
            Assert.AreEqual(2, session.Partitions.Count);
            Assert.IsTrue(PsiStore.Exists("OriginalStore", StorePath));
            Assert.IsTrue(PsiStore.Exists("DerivedStore", StorePath));

            // verify partition metadata
            var originalPartition = session.Partitions[0] as Partition <PsiStoreStreamReader>;

            Assert.AreEqual("Partition_0", originalPartition.Name);
            Assert.AreEqual("OriginalStore", originalPartition.StoreName);
            Assert.AreEqual($"{StorePath}{Path.DirectorySeparatorChar}OriginalStore.0000", originalPartition.StorePath);

            var derivedPartition = session.Partitions[1] as Partition <PsiStoreStreamReader>;

            Assert.AreEqual("Partition_1", derivedPartition.Name);
            Assert.AreEqual("DerivedStore", derivedPartition.StoreName);
            Assert.AreEqual(StorePath, derivedPartition.StorePath);

            // collections to capture stream values
            var originalValues = new List <int>();
            var originalTimes  = new List <DateTime>();
            var derivedValues  = new List <int>();
            var derivedTimes   = new List <DateTime>();

            // read stream values from the partitions
            using (var pipeline = Pipeline.Create())
            {
                var originalPartitionImporter = PsiStore.Open(pipeline, originalPartition.StoreName, originalPartition.StorePath);
                originalPartitionImporter.OpenStream <int>("Root").Do(
                    (i, e) =>
                {
                    originalValues.Add(i);
                    originalTimes.Add(e.OriginatingTime);
                });

                var derivedPartitionImporter = PsiStore.Open(pipeline, derivedPartition.StoreName, derivedPartition.StorePath);
                derivedPartitionImporter.OpenStream <int>("DerivedStream").Do(
                    (i, e) =>
                {
                    derivedValues.Add(i);
                    derivedTimes.Add(e.OriginatingTime);
                });

                pipeline.Run();
            }

            // verify that we read the data
            Assert.AreEqual(10, originalValues.Count);
            Assert.AreEqual(10, originalTimes.Count);
            Assert.AreEqual(10, derivedValues.Count);
            Assert.AreEqual(10, derivedTimes.Count);

            // verify values from both streams are what we expect
            CollectionAssert.AreEqual(originalValues.Select(x => x * multiplier).ToList(), derivedValues);
            CollectionAssert.AreEqual(originalTimes, derivedTimes);
        }
Esempio n. 11
0
        /// <summary>
        /// Builds and runs a speech recognition pipeline using the Azure speech recognizer. Requires a valid Cognitive Services
        /// subscription key. See https://docs.microsoft.com/en-us/azure/cognitive-services/cognitive-services-apis-create-account.
        /// </summary>
        /// <remarks>
        /// If you are getting a <see cref="System.InvalidOperationException"/> with the message 'AzureSpeechRecognizer returned
        /// OnConversationError with error code: LoginFailed. Original error text: Transport error', this most likely is due to
        /// an invalid subscription key. Please check your Azure portal at https://portal.azure.com and ensure that you have
        /// added a subscription to the Azure Speech API on your account.
        /// </remarks>
        /// <param name="outputLogPath">The path under which to write log data.</param>
        /// <param name="inputLogPath">The path from which to read audio input data.</param>
        public static void RunAzureSpeech(string outputLogPath = null, string inputLogPath = null)
        {
            // Create the pipeline object.
            using (Pipeline pipeline = Pipeline.Create())
            {
                // Use either live audio from the microphone or audio from a previously saved log
                IProducer <AudioBuffer> audioInput = null;
                if (inputLogPath != null)
                {
                    // Open the MicrophoneAudio stream from the last saved log
                    var store = PsiStore.Open(pipeline, Program.AppName, inputLogPath);
                    audioInput = store.OpenStream <AudioBuffer>($"{Program.AppName}.MicrophoneAudio");
                }
                else
                {
                    // Create the AudioCapture component to capture audio from the default device in 16 kHz 1-channel
                    // PCM format as required by both the voice activity detector and speech recognition components.
                    audioInput = new AudioCapture(pipeline, WaveFormat.Create16kHz1Channel16BitPcm());
                }

                // Perform voice activity detection using the voice activity detector component
                var vad = new SystemVoiceActivityDetector(pipeline);
                audioInput.PipeTo(vad);

                // Create Azure speech recognizer component
                var recognizer = new AzureSpeechRecognizer(pipeline, new AzureSpeechRecognizerConfiguration()
                {
                    SubscriptionKey = Program.azureSubscriptionKey, Region = Program.azureRegion
                });

                // The input audio to the Azure speech recognizer needs to be annotated with a voice activity flag.
                // This can be constructed by using the Psi Join() operator to combine the audio and VAD streams.
                var annotatedAudio = audioInput.Join(vad);

                // Subscribe the recognizer to the annotated audio
                annotatedAudio.PipeTo(recognizer);

                // Partial and final speech recognition results are posted on the same stream. Here
                // we use Psi's Where() operator to filter out only the final recognition results.
                var finalResults = recognizer.Out.Where(result => result.IsFinal);

                // Print the recognized text of the final recognition result to the console.
                finalResults.Do(result => Console.WriteLine(result.Text));

                // Create a data store to log the data to if necessary. A data store is necessary
                // only if output logging is enabled.
                var dataStore = CreateDataStore(pipeline, outputLogPath);

                // For disk logging only
                if (dataStore != null)
                {
                    // Log the microphone audio and recognition results
                    audioInput.Write($"{Program.AppName}.MicrophoneAudio", dataStore);
                    finalResults.Write($"{Program.AppName}.FinalRecognitionResults", dataStore);
                    vad.Write($"{Program.AppName}.VoiceActivity", dataStore);
                }

                // Register an event handler to catch pipeline errors
                pipeline.PipelineExceptionNotHandled += Pipeline_PipelineException;

                // Register an event handler to be notified when the pipeline completes
                pipeline.PipelineCompleted += Pipeline_PipelineCompleted;

                // Run the pipeline
                pipeline.RunAsync();

                // Azure speech transcribes speech to text
                Console.WriteLine("Say anything");

                Console.WriteLine("Press any key to exit...");
                Console.ReadKey(true);
            }
        }
Esempio n. 12
0
        /// <summary>
        /// Builds and runs a speech recognition pipeline using the .NET System.Speech recognizer and a set of fixed grammars.
        /// </summary>
        /// <param name="outputLogPath">The path under which to write log data.</param>
        /// <param name="inputLogPath">The path from which to read audio input data.</param>
        public static void RunSystemSpeech(string outputLogPath = null, string inputLogPath = null)
        {
            // Create the pipeline object.
            using (Pipeline pipeline = Pipeline.Create())
            {
                // Use either live audio from the microphone or audio from a previously saved log
                IProducer <AudioBuffer> audioInput = null;
                if (inputLogPath != null)
                {
                    // Open the MicrophoneAudio stream from the last saved log
                    var store = PsiStore.Open(pipeline, Program.AppName, inputLogPath);
                    audioInput = store.OpenStream <AudioBuffer>($"{Program.AppName}.MicrophoneAudio");
                }
                else
                {
                    // Create the AudioCapture component to capture audio from the default device in 16 kHz 1-channel
                    // PCM format as required by both the voice activity detector and speech recognition components.
                    audioInput = new AudioCapture(pipeline, WaveFormat.Create16kHz1Channel16BitPcm());
                }

                // Create System.Speech recognizer component
                var recognizer = new SystemSpeechRecognizer(
                    pipeline,
                    new SystemSpeechRecognizerConfiguration()
                {
                    Language = "en-US",
                    Grammars = new GrammarInfo[]
                    {
                        new GrammarInfo()
                        {
                            Name = Program.AppName, FileName = "SampleGrammar.grxml"
                        },
                    },
                });

                // Subscribe the recognizer to the input audio
                audioInput.PipeTo(recognizer);

                // Partial and final speech recognition results are posted on the same stream. Here
                // we use Psi's Where() operator to filter out only the final recognition results.
                var finalResults = recognizer.Out.Where(result => result.IsFinal);

                // Print the final recognition result to the console.
                finalResults.Do(result =>
                {
                    Console.WriteLine($"{result.Text} (confidence: {result.Confidence})");
                });

                // Create a data store to log the data to if necessary. A data store is necessary
                // only if output logging is enabled.
                var dataStore = CreateDataStore(pipeline, outputLogPath);

                // For disk logging only
                if (dataStore != null)
                {
                    // Log the microphone audio and recognition results
                    audioInput.Write($"{Program.AppName}.MicrophoneAudio", dataStore);
                    finalResults.Write($"{Program.AppName}.FinalRecognitionResults", dataStore);
                }

                // Register an event handler to catch pipeline errors
                pipeline.PipelineExceptionNotHandled += Pipeline_PipelineException;

                // Register an event handler to be notified when the pipeline completes
                pipeline.PipelineCompleted += Pipeline_PipelineCompleted;

                // Run the pipeline
                pipeline.RunAsync();

                // The file SampleGrammar.grxml defines a grammar to transcribe numbers
                Console.WriteLine("Say any number between 0 and 100");

                Console.WriteLine("Press any key to exit...");
                Console.ReadKey(true);
            }
        }
Esempio n. 13
0
 /// <summary>
 /// Initializes a new instance of the <see cref="RemoteImporter"/> class.
 /// </summary>
 /// <param name="pipeline">Pipeline to which to attach.</param>
 /// <param name="host">Remote host name.</param>
 /// <param name="port">TCP port on which to connect (default 11411).</param>
 /// <param name="allowSequenceRestart">Whether to allow sequence ID restarts upon connection loss/reacquire.</param>
 /// <remarks>In this case the start is a special behavior that is `DateTime.UtcNow` _at the sending `RemoteExporter`_.</remarks>
 public RemoteImporter(Pipeline pipeline, string host, int port = RemoteExporter.DefaultPort, bool allowSequenceRestart = true)
     : this(name => PsiStore.Open(pipeline, name, null), new TimeInterval(DateTime.MinValue, DateTime.MaxValue), true, host, port, $"RemoteImporter_{Guid.NewGuid().ToString()}", null, allowSequenceRestart)
 {
 }
Esempio n. 14
0
 /// <summary>
 /// Initializes a new instance of the <see cref="RemoteImporter"/> class.
 /// </summary>
 /// <param name="pipeline">Pipeline to which to attach.</param>
 /// <param name="replay">Time interval to be replayed from remote source.</param>
 /// <param name="host">Remote host name.</param>
 /// <param name="port">TCP port on which to connect (default 11411).</param>
 /// <param name="allowSequenceRestart">Whether to allow sequence ID restarts upon connection loss/reacquire.</param>
 public RemoteImporter(Pipeline pipeline, TimeInterval replay, string host, int port = RemoteExporter.DefaultPort, bool allowSequenceRestart = true)
     : this(name => PsiStore.Open(pipeline, name, null), replay, false, host, port, $"RemoteImporter_{Guid.NewGuid().ToString()}", null, allowSequenceRestart)
 {
 }
        public void CrossFrameworkDeserialize()
        {
            if (!File.Exists(OtherTestExe))
            {
                Assert.Inconclusive($"Unable to locate {OtherTestExe} to generate the test store for {nameof(this.CrossFrameworkDeserializeMembers)}.");
            }

            this.ExecuteTest(OtherTestExe, $"!{nameof(this.CrossFrameworkSerialize)}");

            int    intValue    = 0;
            byte   byteValue   = 0;
            bool   boolValue   = false;
            short  shortValue  = 0;
            long   longValue   = 0;
            char   charValue   = '\0';
            string stringValue = null;
            double doubleValue = 0;
            float  floatValue  = 0;

            float[]                floatArray         = null;
            List <string>          stringList         = null;
            ArraySegment <string>  stringArraySegment = default;
            Queue <TimeSpan>       queue       = null;
            EqualityComparer <int> intComparer = null;
            Tuple <long, string>   tuple       = null;

            (DateTime, Stack <int>)valueTuple = default;
            Array             intArray     = null;
            ICollection       stringArray  = null;
            IEqualityComparer enumComparer = null;

            using (var p = Pipeline.Create())
            {
                var store = PsiStore.Open(p, "Store1", this.testPath);
                store.Serializers.Register <System.Drawing.Point>();
                store.OpenStream <int>("int").Do(x => intValue                     = x);
                store.OpenStream <byte>("byte").Do(x => byteValue                  = x);
                store.OpenStream <bool>("bool").Do(x => boolValue                  = x);
                store.OpenStream <short>("short").Do(x => shortValue               = x);
                store.OpenStream <long>("long").Do(x => longValue                  = x);
                store.OpenStream <char>("char").Do(x => charValue                  = x);
                store.OpenStream <string>("string").Do(x => stringValue            = x);
                store.OpenStream <double>("double").Do(x => doubleValue            = x);
                store.OpenStream <float>("float").Do(x => floatValue               = x);
                store.OpenStream <float[]>("floatArray").Do(x => floatArray        = x.DeepClone());
                store.OpenStream <List <string> >("stringList").Do(x => stringList = x.DeepClone());
                store.OpenStream <ArraySegment <string> >("stringArraySegment").Do(x => stringArraySegment = x.DeepClone());
                store.OpenStream <Queue <TimeSpan> >("queue").Do(x => queue = x.DeepClone());
                store.OpenStream <EqualityComparer <int> >("intComparer").Do(x => intComparer = x.DeepClone());
                store.OpenStream <Tuple <long, string> >("tuple").Do(x => tuple = x.DeepClone());
                store.OpenStream <(DateTime, Stack <int>)>("dateStackTuple").Do(x => valueTuple = x.DeepClone());
                store.OpenStream <Array>("intArray").Do(x => intArray                     = x.DeepClone());
                store.OpenStream <ICollection>("stringArray").Do(x => stringArray         = x.DeepClone());
                store.OpenStream <IEqualityComparer>("enumComparer").Do(x => enumComparer = x.DeepClone());
                p.Run();
            }

            Assert.AreEqual(0x7777AAA, intValue);
            Assert.AreEqual(0xBB, byteValue);
            Assert.AreEqual(true, boolValue);
            Assert.AreEqual(0x7CDD, shortValue);
            Assert.AreEqual(0x77777777EEEEEEEE, longValue);
            Assert.AreEqual('G', charValue);
            Assert.AreEqual("This is a test.", stringValue);
            Assert.AreEqual(Math.PI, doubleValue);
            Assert.AreEqual(-1.234f, floatValue);
            CollectionAssert.AreEqual(new[] { 0.1f, 2.3f }, floatArray);
            CollectionAssert.AreEqual(new[] { "one", "two" }, stringList);
            CollectionAssert.AreEqual(new[] { "bbb", "ccc" }, stringArraySegment.ToArray());
            CollectionAssert.AreEqual(new[] { TimeSpan.Zero, TimeSpan.FromSeconds(1) }, queue);
            Assert.IsTrue(intComparer.Equals(1952, 1952));
            Assert.AreEqual(0x77777777EEEEEEEE, tuple.Item1);
            Assert.AreEqual("This is a tuple.", tuple.Item2);
            Assert.AreEqual(new DateTime(2020, 1, 2), valueTuple.Item1);
            CollectionAssert.AreEqual(new[] { 782, 33 }, valueTuple.Item2);
            CollectionAssert.AreEqual(new[] { 0, 3 }, intArray);
            CollectionAssert.AreEqual(new[] { "three", "four" }, stringArray);
            Assert.IsTrue(enumComparer.Equals(DayOfWeek.Friday, DayOfWeek.Friday));
        }
Esempio n. 16
0
        /// <summary>
        /// Execute task against each message in a stream.
        /// </summary>
        /// <param name="stream">Stream name.</param>
        /// <param name="store">Store name.</param>
        /// <param name="path">Store path.</param>
        /// <param name="name">Task name.</param>
        /// <param name="assemblies">Optional assemblies containing task.</param>
        /// <param name="args">Additional configuration arguments.</param>
        /// <returns>Success flag.</returns>
        internal static int ExecuteTask(string stream, string store, string path, string name, IEnumerable <string> assemblies, IEnumerable <string> args)
        {
            Console.WriteLine($"Execute Task (stream={stream}, store={store}, path={path}, name={name}, assemblies={assemblies}, args={args})");

            // find task
            var tasks = LoadTasks(assemblies).Where(t => t.Attribute.Name == name).ToArray();

            if (tasks.Length == 0)
            {
                throw new Exception($"Could not find task named '{name}'.");
            }
            else if (tasks.Length > 1)
            {
                throw new Exception($"Ambiguous task name ({tasks.Count()} tasks found named '{name}').");
            }

            var task = tasks[0];

            // process task
            using (var pipeline = Pipeline.Create())
            {
                var importer = store != null?PsiStore.Open(pipeline, store, Path.GetFullPath(path)) : null;

                // prepare parameters
                var streamMode    = stream?.Length > 0;
                var messageIndex  = -1;
                var envelopeIndex = -1;
                var argList       = args.ToArray();
                var argIndex      = 0;
                var parameterInfo = task.Method.GetParameters();
                var parameters    = new object[parameterInfo.Length];
                for (var i = 0; i < parameterInfo.Length; i++)
                {
                    var p = parameterInfo[i];
                    if (p.ParameterType.IsAssignableFrom(typeof(Importer)))
                    {
                        if (importer == null)
                        {
                            throw new ArgumentException("Error: Task requires a store, but no store argument supplied (-s).");
                        }

                        parameters[i] = importer;
                    }
                    else if (p.ParameterType.IsAssignableFrom(typeof(Pipeline)))
                    {
                        parameters[i] = pipeline;
                    }
                    else if (p.ParameterType.IsAssignableFrom(typeof(Envelope)))
                    {
                        envelopeIndex = i;
                    }
                    else if (streamMode && messageIndex == -1)
                    {
                        messageIndex = i; // assumed first arg
                    }
                    else
                    {
                        Action <string, Func <string, object> > processArgs = (friendlyName, parser) =>
                        {
                            if (argIndex < args.Count())
                            {
                                // take from command-line args
                                try
                                {
                                    parameters[i] = parser(argList[argIndex++]);
                                }
                                catch (Exception ex)
                                {
                                    throw new ArgumentException($"Error: Parameter '{p.Name}' ({i}) expected {friendlyName}.", ex);
                                }
                            }
                            else
                            {
                                // get value interactively
                                do
                                {
                                    try
                                    {
                                        Console.Write($"{p.Name} ({friendlyName})? ");
                                        parameters[i] = parser(Console.ReadLine());
                                    }
                                    catch
                                    {
                                        Console.WriteLine($"Error: Expected {friendlyName}.");
                                    }
                                }while (parameters[i] == null);
                            }
                        };

                        if (p.ParameterType.IsAssignableFrom(typeof(double)))
                        {
                            processArgs("double", v => double.Parse(v));
                        }
                        else if (p.ParameterType.IsAssignableFrom(typeof(int)))
                        {
                            processArgs("integer", v => int.Parse(v));
                        }
                        else if (p.ParameterType.IsAssignableFrom(typeof(bool)))
                        {
                            processArgs("boolean", v => bool.Parse(v));
                        }
                        else if (p.ParameterType.IsAssignableFrom(typeof(DateTime)))
                        {
                            processArgs("datetime", v => DateTime.Parse(v));
                        }
                        else if (p.ParameterType.IsAssignableFrom(typeof(TimeSpan)))
                        {
                            processArgs("timespan", v => TimeSpan.Parse(v));
                        }
                        else if (p.ParameterType.IsAssignableFrom(typeof(string)))
                        {
                            processArgs("string", v => v);
                        }
                        else
                        {
                            throw new ArgumentException($"Unexpected parameter type ({p.ParameterType}).");
                        }
                    }
                }

                if (streamMode)
                {
                    if (importer == null)
                    {
                        throw new ArgumentException("Error: Task requires a stream within a store, but no store argument supplied (-s).");
                    }

                    importer.OpenDynamicStream(stream).Do((m, e) =>
                    {
                        if (messageIndex != -1)
                        {
                            parameters[messageIndex] = m;
                        }

                        if (envelopeIndex != -1)
                        {
                            parameters[envelopeIndex] = e;
                        }

                        task.Method.Invoke(null, parameters);
                    });
                }
                else
                {
                    task.Method.Invoke(null, parameters);
                }

                if (importer != null)
                {
                    pipeline.ProgressReportInterval = TimeSpan.FromSeconds(1);
                    pipeline.RunAsync(null, new Progress <double>(p => Console.WriteLine($"Progress: {p * 100.0:F2}%")));
                    pipeline.WaitAll();
                }
            }

            return(0);
        }