public void TestGateReaderTicketValidation()
        {
            FakeDeviceClient   fakeDeviceClient = new FakeDeviceClient();
            FakeEventScheduler fakeScheduler    = new FakeEventScheduler();

            deviceconfig.PercentOfWrongWay = 0; // make sure we don't have any wrong way swipes

            TestContext.WriteLine(string.Empty);
            TestContext.WriteLine(">> Testing the purchase ticket simulated event..");

            GateReaderDevice device = new GateReaderDevice(deviceconfig, fakeDeviceClient, fakeScheduler);

            device.InitializeAsync().Wait();

            // execute a validate ticket event and check the result, it should always be false
            Assert.IsFalse(fakeScheduler.EventList[0].EventDelegate());
            // that delegate should have sent one message to the cloud
            Assert.AreEqual(1, fakeDeviceClient.sendMessageLog.Count);

            // check the message sent to make sure its correct
            // create a sample request for comparison
            ValidateTicketRequest expectedRequest = new ValidateTicketRequest()
            {
                DeviceId      = deviceconfig.DeviceId,
                DeviceType    = deviceconfig.DeviceType,
                TransactionId = "fakeId",
                CreateTime    = System.DateTime.UtcNow,
                MethodName    = "ReceiveTicketValidationResponse"
            };
            // get request message into an object so we can compare it
            ValidateTicketRequest actualRequest = JsonConvert.DeserializeObject <ValidateTicketRequest>(fakeDeviceClient.sendMessageLog[0]);

            // compare properties to make sure they're valid.
            Assert.AreEqual(expectedRequest.DeviceId, actualRequest.DeviceId);
            Assert.AreEqual(expectedRequest.DeviceType, actualRequest.DeviceType);
            Assert.AreEqual(expectedRequest.MessageType, actualRequest.MessageType);
            Assert.AreEqual(expectedRequest.MethodName, actualRequest.MethodName);

            //
            /// test the CloudToEvent PurchaseResponse call we expect back
            //
            TestContext.WriteLine(string.Empty);
            TestContext.WriteLine(">> Testing the ticket successfully validated direct method..");

            // test the direct method itself
            ValidateTicketResponse approvePurchaseMethodkRequest = new ValidateTicketResponse()
            {
                IsApproved  = true,
                DeviceId    = expectedRequest.DeviceId,
                DeviceType  = expectedRequest.DeviceType,
                MessageType = expectedRequest.MessageType,
            };
            string requestString = JsonConvert.SerializeObject(approvePurchaseMethodkRequest);
            // execute the method
            MethodRequest  methodRequest = new MethodRequest(expectedRequest.MethodName, Encoding.UTF8.GetBytes(requestString));
            MethodResponse methodresult  = fakeDeviceClient.directMethods[0](methodRequest, null).Result;

            // check results
            Assert.AreEqual(200, methodresult.Status); // got back an ok
        }
        public void TestInvalidTicketResponse()
        {
            FakeDeviceClient   fakeDeviceClient = new FakeDeviceClient();
            FakeEventScheduler fakeScheduler    = new FakeEventScheduler();

            TestContext.WriteLine(">> Testing the Device's Ticket Validation failed notification..");

            ValidateTicketResponse approvePurchaseMethodkRequest = new ValidateTicketResponse()
            {
                DeviceId   = deviceconfig.DeviceId,
                DeviceType = deviceconfig.DeviceType,
                IsApproved = false
            };

            // create our test device
            GateReaderDevice device = new GateReaderDevice(deviceconfig, fakeDeviceClient, fakeScheduler);

            device.InitializeAsync().Wait();

            // send a ticket NOT approved event to the callback method
            TestContext.WriteLine(string.Empty);
            TestContext.WriteLine(">> validating ticket, shouldn't throw event");
            string        requestString = JsonConvert.SerializeObject(approvePurchaseMethodkRequest);
            MethodRequest methodRequest = new MethodRequest("ReceivePurchaseTicketResponse", Encoding.UTF8.GetBytes(requestString));

            MethodResponse myresult = fakeDeviceClient.directMethods[0](methodRequest, null).Result;

            // ticket validation failed, so no "gate opened" message sent
            Assert.AreEqual(0, fakeDeviceClient.sendMessageLog.Count);
        }
        /// <summary>
        /// This method is called by Azure IOT Hub and represents a direct method call to the device
        /// This is the response to 'SimulatedTicketSwipeOccured' request for a ticket validation
        /// </summary>
        private Task <MethodResponse> ReceiveTicketValidationResponse(MethodRequest methodRequest, object userContext)
        {
            var data = Encoding.UTF8.GetString(methodRequest.Data);
            ValidateTicketResponse validationResponse = JsonConvert.DeserializeObject <ValidateTicketResponse>(data);

            var json = JObject.Parse(data);

            Console.WriteLine("Executed direct method: " + methodRequest.Name);
            Console.WriteLine($"Transaction Id: {validationResponse.TransactionId}");
            Console.WriteLine($"IsApproved: {validationResponse.IsApproved}");
            Console.WriteLine();

            if (validationResponse.IsApproved)
            {
                SendGateOpenedMessageToCloud(validationResponse);
            }

            // Acknowlege the direct method call with a 200 success message
            string result = "{\"result\":\"Executed direct method: " + methodRequest.Name + "\"}";

            // restart the purchase ticket event
            this._EventScheduler.Start(0);

            return(Task.FromResult(new MethodResponse(Encoding.UTF8.GetBytes(result), 200)));
        }
        /// <summary>
        /// This is a fire and forget method that sends a message to the cloud to let it know the gate was opened.
        /// This message will be sent if the 'ReceivedTicketValidationResponse' method got a "ticket approved" response
        /// </summary>
        private bool SendGateOpenedMessageToCloud(ValidateTicketResponse responsePayload)
        {
            GateOpenedNotification issueTicketRequest = new GateOpenedNotification()
            {
                DeviceId      = this.deviceId,
                DeviceType    = this.deviceType,
                TransactionId = responsePayload.TransactionId,
                CreateTime    = System.DateTime.UtcNow
            };

            var messageString = JsonConvert.SerializeObject(issueTicketRequest);

            SendMessageToCloud(messageString);

            Console.WriteLine("{0} > Sending message: {1}", DateTime.Now, messageString);
            Console.WriteLine();

            return(false); // don't restart timer
        }
        public void TicketValidationTest()
        {
            // sample payload to test
            ValidateTicketRequest testRequest = new ValidateTicketRequest()
            {
                DeviceId      = "testID",
                DeviceType    = DeviceType.GateReader,
                TransactionId = "fakeTransactionId",
                CreateTime    = System.DateTime.UtcNow,
                MethodName    = "ReceiveTicketValidationResponse"
            };
            string requestPayload = JsonConvert.SerializeObject(testRequest);

            TestContext.WriteLine(string.Empty);
            TestContext.WriteLine(">> Testing the ticket validation method invocation.");

            FakeInvokeDeviceMethod serviceClient = new FakeInvokeDeviceMethod();
            ValidateTicketAction   action        = new ValidateTicketAction(serviceClient, requestPayload, logger);

            action.Run();

            // Assert that serviceClient.invocations count is 1
            Assert.That(Equals(1, serviceClient.invocations.Count));

            TestContext.WriteLine(string.Empty);
            TestContext.WriteLine(">> Testing the ticket validation method response.");

            // get the result and deserialize is back into our response object
            ValidateTicketResponse actualResponse = JsonConvert.DeserializeObject <ValidateTicketResponse>(serviceClient.invocations[0].method.GetPayloadAsJson());

            // Assert that various response values against expected
            Assert.AreEqual(testRequest.DeviceId, actualResponse.DeviceId, "Device IDs do not match");
            Assert.AreEqual(testRequest.DeviceType, actualResponse.DeviceType, "Device Types do not match");
            Assert.AreEqual(testRequest.MessageType, actualResponse.MessageType, "Message Types do not match");
            Assert.AreEqual(testRequest.TransactionId, actualResponse.TransactionId, "Trahsaction IDs do not match");
            Assert.AreEqual(testRequest.DeviceId, actualResponse.DeviceId, "Device IDs do not match");
            Assert.IsTrue((actualResponse.IsApproved == true || actualResponse.IsApproved == false), "IsApproved need not match range of allowed values, must be true or false");
            // Assert that the return MethodName is also correct
            Assert.AreEqual(testRequest.MethodName, serviceClient.invocations[0].method.MethodName);
        }