Ejemplo n.º 1
0
    public async Task StartReissuanceAsync(BobClient bobClient, IEnumerable <long> amounts, IEnumerable <long> vsizes, CancellationToken cancellationToken)
    {
        await Task.WhenAll(AmountCredentialToPresentTasks.Concat(VsizeCredentialToPresentTasks)).ConfigureAwait(false);

        IEnumerable <Credential> inputAmountCredentials = AmountCredentialToPresentTasks.Select(x => x.Result);
        IEnumerable <Credential> inputVsizeCredentials  = VsizeCredentialToPresentTasks.Select(x => x.Result);
        var amountsToRequest = AddExtraCredentialRequests(amounts, inputAmountCredentials.Sum(x => x.Value));
        var vsizesToRequest  = AddExtraCredentialRequests(vsizes, inputVsizeCredentials.Sum(x => x.Value));

        (IEnumerable <Credential> RealAmountCredentials, IEnumerable <Credential> RealVsizeCredentials)result = await bobClient.ReissueCredentialsAsync(
            amountsToRequest,
            vsizesToRequest,
            inputAmountCredentials,
            inputVsizeCredentials,
            cancellationToken).ConfigureAwait(false);

        // TODO keep the credentials that were not needed by the graph
        var(amountCredentials, _) = SeparateExtraCredentials(result.RealAmountCredentials, amounts);
        var(vsizeCredentials, _)  = SeparateExtraCredentials(result.RealVsizeCredentials, vsizes);

        foreach (var(tcs, credential) in AmountCredentialTasks.Zip(amountCredentials))
        {
            tcs.SetResult(credential);
        }
        foreach (var(tcs, credential) in VsizeCredentialTasks.Zip(vsizeCredentials))
        {
            tcs.SetResult(credential);
        }
    }
    public async Task StartReissuancesAsync(IEnumerable <AliceClient> aliceClients, BobClient bobClient, CancellationToken cancellationToken)
    {
        var aliceNodePairs = PairAliceClientAndRequestNodes(aliceClients, Graph);

        // Build tasks and link them together.
        List <SmartRequestNode> smartRequestNodes = new();
        List <Task>             allTasks          = new();

        // Temporary workaround because we don't yet have a mechanism to
        // propagate the final amounts to request amounts to AliceClient's
        // connection confirmation loop even though they are already known
        // after the final successful input registration, which may be well
        // before the connection confirmation phase actually starts.
        allTasks.Add(CompleteConnectionConfirmationAsync(aliceClients, bobClient, cancellationToken));

        using CancellationTokenSource ctsOnError = new();
        using CancellationTokenSource linkedCts  = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, ctsOnError.Token);

        foreach (var node in Graph.Reissuances)
        {
            var inputAmountEdgeTasks = Graph.InEdges(node, CredentialType.Amount).Select(edge => DependencyTasks[edge].Task);
            var inputVsizeEdgeTasks  = Graph.InEdges(node, CredentialType.Vsize).Select(edge => DependencyTasks[edge].Task);

            var outputAmountEdgeTaskCompSources = Graph.OutEdges(node, CredentialType.Amount).Select(edge => DependencyTasks[edge]);
            var outputVsizeEdgeTaskCompSources  = Graph.OutEdges(node, CredentialType.Vsize).Select(edge => DependencyTasks[edge]);

            var requestedAmounts = Graph.OutEdges(node, CredentialType.Amount).Select(edge => edge.Value);
            var requestedVSizes  = Graph.OutEdges(node, CredentialType.Vsize).Select(edge => edge.Value);

            SmartRequestNode smartRequestNode = new(
                inputAmountEdgeTasks,
                inputVsizeEdgeTasks,
                outputAmountEdgeTaskCompSources,
                outputVsizeEdgeTaskCompSources);

            var task = smartRequestNode
                       .StartReissuanceAsync(bobClient, requestedAmounts, requestedVSizes, linkedCts.Token)
                       .ContinueWith((t) =>
            {
                if (t.IsFaulted && t.Exception is { } exception)
                {
                    // If one task is failing, cancel all the tasks and throw.
                    ctsOnError.Cancel();
                    throw exception;
                }
            }, linkedCts.Token);
            allTasks.Add(task);
        }

        await Task.WhenAll(allTasks).ConfigureAwait(false);

        var amountEdges = Graph.Outputs.SelectMany(node => Graph.InEdges(node, CredentialType.Amount));
        var vsizeEdges  = Graph.Outputs.SelectMany(node => Graph.InEdges(node, CredentialType.Vsize));

        // Check if all tasks were finished, otherwise Task.Result will block.
        if (!amountEdges.Concat(vsizeEdges).All(edge => DependencyTasks[edge].Task.IsCompletedSuccessfully))
        {
            throw new InvalidOperationException("Some Output nodes in-edges failed to complete");
        }
    }
Ejemplo n.º 3
0
    public async Task StartOutputRegistrationsAsync(IEnumerable <TxOut> txOuts, BobClient bobClient, CancellationToken cancellationToken)
    {
        List <Task> outputTasks = new();

        using CancellationTokenSource ctsOnError = new();
        using CancellationTokenSource linkedCts  = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, ctsOnError.Token);

        foreach (var(node, txOut) in Enumerable.Zip(Graph.Outputs, txOuts))
        {
            var amountCredsToPresentTasks = Graph.InEdges(node, CredentialType.Amount).Select(edge => DependencyTasks[edge].Task);
            var vsizeCredsToPresentTasks  = Graph.InEdges(node, CredentialType.Vsize).Select(edge => DependencyTasks[edge].Task);

            SmartRequestNode smartRequestNode = new(
                amountCredsToPresentTasks,
                vsizeCredsToPresentTasks,
                Array.Empty <TaskCompletionSource <Credential> >(),
                Array.Empty <TaskCompletionSource <Credential> >());

            var task = smartRequestNode
                       .StartOutputRegistrationAsync(bobClient, txOut.ScriptPubKey, cancellationToken)
                       .ContinueWith((t) =>
            {
                if (t.IsFaulted && t.Exception is { } exception)
                {
                    // If one task is failing, cancel all the tasks and throw.
                    ctsOnError.Cancel();
                    throw exception;
                }
            }, linkedCts.Token);
            outputTasks.Add(task);
        }

        await Task.WhenAll(outputTasks).ConfigureAwait(false);
    }
        public async Task DoesntSwitchImmaturelyAsync()
        {
            WabiSabiConfig cfg = new()
            {
                MaxInputCountByRound           = 2,
                MinInputCountByRoundMultiplier = 0.5
            };

            var(key1, coin1, key2, coin2) = WabiSabiFactory.CreateCoinKeyPairs();

            var mockRpc = WabiSabiFactory.CreatePreconfiguredRpcClient(coin1.Coin, coin2.Coin);

            using Arena arena = await WabiSabiFactory.CreateAndStartArenaAsync(cfg, mockRpc);

            var(round, arenaClient, alices) = await CreateRoundWithTwoConfirmedConnectionsAsync(arena, key1, coin1, key2, coin2);

            var(amountCredentials1, vsizeCredentials1) = (alices[0].IssuedAmountCredentials, alices[0].IssuedVsizeCredentials);
            var(amountCredentials2, vsizeCredentials2) = (alices[1].IssuedAmountCredentials, alices[1].IssuedVsizeCredentials);

            // Register outputs.
            var bobClient = new BobClient(round.Id, arenaClient);

            using var destKey = new Key();
            await bobClient.RegisterOutputAsync(
                destKey.PubKey.WitHash.ScriptPubKey,
                amountCredentials1.Take(ProtocolConstants.CredentialNumber),
                vsizeCredentials1.Take(ProtocolConstants.CredentialNumber),
                CancellationToken.None);

            await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21));

            Assert.Equal(Phase.OutputRegistration, round.Phase);

            await arena.StopAsync(CancellationToken.None);
        }
Ejemplo n.º 5
0
        public void Stop()
        {
            this.chatServer?.Dispose();
            this.chatServer = null;

            this.bobClient?.Dispose();
            this.bobClient = null;
        }
Ejemplo n.º 6
0
    public async Task DiffTooSmallToBlameAsync()
    {
        WabiSabiConfig cfg = new()
        {
            MaxInputCountByRound           = 2,
            MinInputCountByRoundMultiplier = 0.5,
            OutputRegistrationTimeout      = TimeSpan.Zero,
            CoordinationFeeRate            = CoordinationFeeRate.Zero
        };

        var(keyChain, coin1, coin2) = WabiSabiFactory.CreateCoinKeyPairs();

        var mockRpc = WabiSabiFactory.CreatePreconfiguredRpcClient(coin1.Coin, coin2.Coin);

        using Arena arena = await ArenaBuilder.From(cfg).With(mockRpc).CreateAndStartAsync();

        var(round, arenaClient, alices) = await CreateRoundWithTwoConfirmedConnectionsAsync(arena, keyChain, coin1, coin2);

        var(amountCredentials1, vsizeCredentials1) = (alices[0].IssuedAmountCredentials, alices[0].IssuedVsizeCredentials);
        var(amountCredentials2, vsizeCredentials2) = (alices[1].IssuedAmountCredentials, alices[1].IssuedVsizeCredentials);

        // Register outputs.
        var bobClient = new BobClient(round.Id, arenaClient);

        using var destKey1 = new Key();
        using var destKey2 = new Key();
        await bobClient.RegisterOutputAsync(
            destKey1.PubKey.WitHash.ScriptPubKey,
            amountCredentials1.Take(ProtocolConstants.CredentialNumber),
            vsizeCredentials1.Take(ProtocolConstants.CredentialNumber),
            CancellationToken.None);

        await bobClient.RegisterOutputAsync(
            destKey2.PubKey.WitHash.ScriptPubKey,
            amountCredentials2.Take(ProtocolConstants.CredentialNumber),
            vsizeCredentials2.Take(ProtocolConstants.CredentialNumber),
            CancellationToken.None);

        // Add another input. The input must be able to pay for itself, but
        // the remaining amount after deducting the fees needs to be less
        // than the minimum.
        var txParams   = round.Assert <ConstructionState>().Parameters;
        var extraAlice = WabiSabiFactory.CreateAlice(txParams.FeeRate.GetFee(Constants.P2wpkhInputVirtualSize) + txParams.AllowedOutputAmounts.Min - new Money(1L), round);

        round.Alices.Add(extraAlice);
        round.CoinjoinState = round.Assert <ConstructionState>().AddInput(extraAlice.Coin);

        await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21));

        Assert.Equal(Phase.TransactionSigning, round.Phase);
        var tx = round.Assert <SigningState>().CreateTransaction();

        Assert.Equal(3, tx.Inputs.Count);
        Assert.Equal(2, tx.Outputs.Count);
        Assert.DoesNotContain(round.CoordinatorScript, tx.Outputs.Select(x => x.ScriptPubKey));

        await arena.StopAsync(CancellationToken.None);
    }
Ejemplo n.º 7
0
        /// <summary>
        /// Invoked when application execution is being suspended.  Application state is saved
        /// without knowing whether the application will be terminated or resumed with the contents
        /// of memory still intact.
        /// </summary>
        /// <param name="sender">The source of the suspend request.</param>
        /// <param name="e">Details about the suspend request.</param>
        private void OnSuspending(object sender, SuspendingEventArgs e)
        {
            var deferral = e.SuspendingOperation.GetDeferral();

            if (this.sampleTimer != null)
            {
                this.sampleTimer.Dispose();
                this.sampleTimer = null;
            }

            if (this.interoperabilityServer != null)
            {
                this.interoperabilityServer.Dispose();
                this.interoperabilityServer = null;
            }

            if (this.chatServer != null)
            {
                this.chatServer.Dispose();
                this.chatServer = null;
            }

            if (this.bobClient != null)
            {
                this.bobClient.Dispose();
                this.bobClient = null;
            }

            if (this.sensorServer != null)
            {
                this.sensorServer.Dispose();
                this.sensorServer = null;
            }

            if (this.provisioningClient != null)
            {
                this.provisioningClient.Dispose();
                this.provisioningClient = null;
            }

            if (this.thingRegistryClient != null)
            {
                this.thingRegistryClient.Dispose();
                this.thingRegistryClient = null;
            }

            if (this.xmppClient != null)
            {
                this.xmppClient.Dispose();
                this.xmppClient = null;
            }

            Log.Terminate();

            deferral.Complete();
        }
        public async Task AllBobsRegisteredAsync()
        {
            WabiSabiConfig cfg = new()
            {
                MaxInputCountByRound           = 2,
                MinInputCountByRoundMultiplier = 0.5
            };

            using Key key1 = new();
            using Key key2 = new();
            var coin1 = WabiSabiFactory.CreateCoin(key1);
            var coin2 = WabiSabiFactory.CreateCoin(key2);

            var mockRpc = WabiSabiFactory.CreatePreconfiguredRpcClient(coin1, coin2);

            using Arena arena = await WabiSabiFactory.CreateAndStartArenaAsync(cfg, mockRpc);

            var(round, arenaClient, alices) = await CreateRoundWithTwoConfirmedConnectionsAsync(arena, key1, coin1, key2, coin2);

            var(amountCredentials1, vsizeCredentials1) = (alices[0].IssuedAmountCredentials, alices[0].IssuedVsizeCredentials);
            var(amountCredentials2, vsizeCredentials2) = (alices[1].IssuedAmountCredentials, alices[1].IssuedVsizeCredentials);

            // Register outputs.
            var bobClient = new BobClient(round.Id, arenaClient);

            using var destKey1 = new Key();
            await bobClient.RegisterOutputAsync(
                coin1.Amount - round.FeeRate.GetFee(coin1.ScriptPubKey.EstimateInputVsize()),
                destKey1.PubKey.WitHash.ScriptPubKey,
                amountCredentials1.Take(ProtocolConstants.CredentialNumber),
                vsizeCredentials1.Take(ProtocolConstants.CredentialNumber),
                CancellationToken.None);

            using var destKey2 = new Key();
            await bobClient.RegisterOutputAsync(
                coin2.Amount - round.FeeRate.GetFee(coin2.ScriptPubKey.EstimateInputVsize()),
                destKey2.PubKey.WitHash.ScriptPubKey,
                amountCredentials2.Take(ProtocolConstants.CredentialNumber),
                vsizeCredentials2.Take(ProtocolConstants.CredentialNumber),
                CancellationToken.None);

            foreach (var alice in alices)
            {
                await alice.ReadyToSignAsync(CancellationToken.None);
            }

            await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21));

            Assert.Equal(Phase.TransactionSigning, round.Phase);
            var tx = round.Assert <SigningState>().CreateTransaction();

            Assert.Equal(2, tx.Inputs.Count);
            Assert.Equal(2, tx.Outputs.Count);

            await arena.StopAsync(CancellationToken.None);
        }
Ejemplo n.º 9
0
        public override void ConnectClients()
        {
            base.ConnectClients();

            Assert.AreEqual(XmppState.Connected, this.client1.State);
            Assert.AreEqual(XmppState.Connected, this.client2.State);

            this.bobClient1 = new BobClient(this.client1, "Bob1");
            this.bobClient2 = new BobClient(this.client2, "Bob2");
        }
Ejemplo n.º 10
0
        private async Task RegisterOutputAsync(CcjClientRound ongoingRound)
        {
            using (var bobClient = new BobClient(CcjHostUri, TorSocks5EndPoint))
            {
                await bobClient.PostOutputAsync(ongoingRound.RoundHash, ongoingRound.ActiveOutputAddress, ongoingRound.UnblindedSignature);

                ongoingRound.PostedOutput = true;
                Logger.LogInfo <AliceClient>($"Round ({ongoingRound.State.RoundId}) Bob Posted output.");
            }
        }
Ejemplo n.º 11
0
        public Task Stop()
        {
            this.chatServer?.Dispose();
            this.chatServer = null;

            this.bobClient?.Dispose();
            this.bobClient = null;

            return(Task.CompletedTask);
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Invoked when application execution is being suspended.  Application state is saved
        /// without knowing whether the application will be terminated or resumed with the contents
        /// of memory still intact.
        /// </summary>
        /// <param name="sender">The source of the suspend request.</param>
        /// <param name="e">Details about the suspend request.</param>
        private void OnSuspending(object sender, SuspendingEventArgs e)
        {
            var deferral = e.SuspendingOperation.GetDeferral();

            if (instance == this)
            {
                instance = null;
            }

            this.chatServer?.Dispose();
            this.chatServer = null;

            this.bobClient?.Dispose();
            this.bobClient = null;

            this.sensorServer?.Dispose();
            this.sensorServer = null;

            this.xmppClient?.Dispose();
            this.xmppClient = null;

            this.minuteTimer?.Dispose();
            this.minuteTimer = null;

#if GPIO
            this.gpioPin.Dispose();
            this.gpioPin = null;
#else
            if (this.arduino != null)
            {
                this.arduino.digitalWrite(13, PinState.LOW);
                this.arduino.pinMode(13, PinMode.INPUT);                     // Onboard LED.
                this.arduino.pinMode(9, PinMode.INPUT);                      // Relay.

                this.arduino.Dispose();
                this.arduino = null;
            }

            if (this.arduinoUsb != null)
            {
                this.arduinoUsb.end();
                this.arduinoUsb.Dispose();
                this.arduinoUsb = null;
            }
#endif
            db?.Stop()?.Wait();
            db?.Flush()?.Wait();

            Log.Terminate();

            deferral.Complete();
        }
Ejemplo n.º 13
0
        CreateRoundWithOutputsReadyToSignAsync(Arena arena, Key key1, Coin coin1, Key key2, Coin coin2)
        {
            // Create the round.
            await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21));

            var round       = Assert.Single(arena.Rounds);
            var arenaClient = WabiSabiFactory.CreateArenaClient(arena);

            // Register Alices.
            var aliceClient1 = new AliceClient(round.Id, arenaClient, coin1, round.FeeRate, key1.GetBitcoinSecret(round.Network));
            var aliceClient2 = new AliceClient(round.Id, arenaClient, coin2, round.FeeRate, key2.GetBitcoinSecret(round.Network));

            await aliceClient1.RegisterInputAsync(CancellationToken.None).ConfigureAwait(false);

            await aliceClient2.RegisterInputAsync(CancellationToken.None).ConfigureAwait(false);

            await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21));

            Assert.Equal(Phase.ConnectionConfirmation, round.Phase);

            // Confirm connections.
            await aliceClient1.ConfirmConnectionAsync(TimeSpan.FromMilliseconds(100), round.MaxVsizeAllocationPerAlice, CancellationToken.None).ConfigureAwait(false);

            await aliceClient2.ConfirmConnectionAsync(TimeSpan.FromMilliseconds(100), round.MaxVsizeAllocationPerAlice, CancellationToken.None).ConfigureAwait(false);

            await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21));

            Assert.Equal(Phase.OutputRegistration, round.Phase);

            // Register outputs.
            var bobClient = new BobClient(round.Id, arenaClient);

            using var destKey1 = new Key();
            using var destKey2 = new Key();
            await bobClient.RegisterOutputAsync(
                coin1.Amount - round.FeeRate.GetFee(coin1.ScriptPubKey.EstimateInputVsize()),
                destKey1.PubKey.WitHash.ScriptPubKey,
                aliceClient1.RealAmountCredentials,
                aliceClient1.RealVsizeCredentials,
                CancellationToken.None).ConfigureAwait(false);

            await bobClient.RegisterOutputAsync(
                coin2.Amount - round.FeeRate.GetFee(coin2.ScriptPubKey.EstimateInputVsize()),
                destKey1.PubKey.WitHash.ScriptPubKey,
                aliceClient2.RealAmountCredentials,
                aliceClient2.RealVsizeCredentials,
                CancellationToken.None).ConfigureAwait(false);

            return(round, aliceClient1, aliceClient2);
        }
Ejemplo n.º 14
0
        CreateRoundWithOutputsReadyToSignAsync(Arena arena, Key key1, SmartCoin coin1, Key key2, SmartCoin coin2)
        {
            // Create the round.
            await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21));

            var round = Assert.Single(arena.Rounds);

            round.MaxVsizeAllocationPerAlice = 11 + 31 + MultipartyTransactionParameters.SharedOverhead;
            var arenaClient = WabiSabiFactory.CreateArenaClient(arena);

            // Register Alices.
            using RoundStateUpdater roundStateUpdater = new(TimeSpan.FromSeconds(2), arena);
            await roundStateUpdater.StartAsync(CancellationToken.None);

            using var identificationKey = new Key();
            var task1 = AliceClient.CreateRegisterAndConfirmInputAsync(RoundState.FromRound(round), arenaClient, coin1, key1.GetBitcoinSecret(round.Network), identificationKey, roundStateUpdater, CancellationToken.None);
            var task2 = AliceClient.CreateRegisterAndConfirmInputAsync(RoundState.FromRound(round), arenaClient, coin2, key2.GetBitcoinSecret(round.Network), identificationKey, roundStateUpdater, CancellationToken.None);

            while (Phase.OutputRegistration != round.Phase)
            {
                await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21));
            }

            await Task.WhenAll(task1, task2);

            var aliceClient1 = task1.Result;
            var aliceClient2 = task2.Result;

            // Register outputs.
            var bobClient = new BobClient(round.Id, arenaClient);

            using var destKey1 = new Key();
            using var destKey2 = new Key();
            await bobClient.RegisterOutputAsync(
                destKey1.PubKey.WitHash.ScriptPubKey,
                aliceClient1.IssuedAmountCredentials.Take(ProtocolConstants.CredentialNumber),
                aliceClient1.IssuedVsizeCredentials.Take(ProtocolConstants.CredentialNumber),
                CancellationToken.None).ConfigureAwait(false);

            await bobClient.RegisterOutputAsync(
                destKey1.PubKey.WitHash.ScriptPubKey,
                aliceClient2.IssuedAmountCredentials.Take(ProtocolConstants.CredentialNumber),
                aliceClient2.IssuedVsizeCredentials.Take(ProtocolConstants.CredentialNumber),
                CancellationToken.None).ConfigureAwait(false);

            await roundStateUpdater.StopAsync(CancellationToken.None);

            return(round, aliceClient1, aliceClient2);
        }
Ejemplo n.º 15
0
        public CcjClient(Network network, BlindingRsaPubKey blindingPubKey, KeyManager keyManager, Uri ccjHostUri, IPEndPoint torSocks5EndPoint = null)
        {
            Network        = Guard.NotNull(nameof(network), network);
            BlindingPubKey = Guard.NotNull(nameof(blindingPubKey), blindingPubKey);
            KeyManager     = Guard.NotNull(nameof(keyManager), keyManager);
            AliceClient    = new AliceClient(ccjHostUri, torSocks5EndPoint);
            BobClient      = new BobClient(ccjHostUri, torSocks5EndPoint);
            SatoshiClient  = new SatoshiClient(ccjHostUri, torSocks5EndPoint);

            Rounds   = new List <CcjClientRound>();
            _running = 0;
            Stop     = new CancellationTokenSource();
            _frequentStatusProcessingIfNotMixing = 0;
            CoinsWaitingForMix = new List <MixCoin>();
            MixLock            = new AsyncLock();
        }
Ejemplo n.º 16
0
        public override void DisposeClients()
        {
            if (this.bobClient1 != null)
            {
                this.bobClient1.Dispose();
                this.bobClient1 = null;
            }

            if (this.bobClient2 != null)
            {
                this.bobClient2.Dispose();
                this.bobClient2 = null;
            }

            base.DisposeClients();
        }
Ejemplo n.º 17
0
    public async Task StartOutputRegistrationAsync(
        BobClient bobClient,
        Script scriptPubKey,
        CancellationToken cancellationToken)
    {
        await Task.WhenAll(AmountCredentialToPresentTasks.Concat(VsizeCredentialToPresentTasks)).ConfigureAwait(false);

        IEnumerable <Credential> inputAmountCredentials = AmountCredentialToPresentTasks.Select(x => x.Result);
        IEnumerable <Credential> inputVsizeCredentials  = VsizeCredentialToPresentTasks.Select(x => x.Result);

        await bobClient.RegisterOutputAsync(
            scriptPubKey,
            inputAmountCredentials,
            inputVsizeCredentials,
            cancellationToken).ConfigureAwait(false);
    }
        public async Task SomeBobsRegisteredTimeoutAsync()
        {
            WabiSabiConfig cfg = new()
            {
                MaxInputCountByRound           = 2,
                MinInputCountByRoundMultiplier = 0.5,
                OutputRegistrationTimeout      = TimeSpan.Zero
            };

            using Key key1 = new();
            using Key key2 = new();
            var coin1 = WabiSabiFactory.CreateCoin(key1);
            var coin2 = WabiSabiFactory.CreateCoin(key2);

            var mockRpc = WabiSabiFactory.CreatePreconfiguredRpcClient(coin1, coin2);

            using Arena arena = await WabiSabiFactory.CreateAndStartArenaAsync(cfg, mockRpc).ConfigureAwait(false);

            var(round, arenaClient, alices) = await CreateRoundWithTwoConfirmedConnectionsAsync(arena, key1, coin1, key2, coin2).ConfigureAwait(false);

            var(realAmountCredentials1, realVsizeCredentials1) = alices[0];
            var(realAmountCredentials2, realVsizeCredentials2) = alices[1];

            // Register outputs.
            var bobClient = new BobClient(round.Id, arenaClient);

            using var destKey = new Key();
            await bobClient.RegisterOutputAsync(
                coin1.Amount - round.FeeRate.GetFee(coin1.ScriptPubKey.EstimateInputVsize()),
                destKey.PubKey.WitHash.ScriptPubKey,
                realAmountCredentials1,
                realVsizeCredentials1,
                CancellationToken.None).ConfigureAwait(false);

            await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21));

            Assert.Equal(Phase.TransactionSigning, round.Phase);
            var tx = round.Assert <SigningState>().CreateTransaction();

            Assert.Equal(2, tx.Inputs.Count);
            Assert.Equal(2, tx.Outputs.Count);
            Assert.Contains(cfg.BlameScript, tx.Outputs.Select(x => x.ScriptPubKey));

            await arena.StopAsync(CancellationToken.None);
        }
Ejemplo n.º 19
0
    public async Task SomeBobsRegisteredTimeoutAsync()
    {
        WabiSabiConfig cfg = new()
        {
            MaxInputCountByRound           = 2,
            MinInputCountByRoundMultiplier = 0.5,
            OutputRegistrationTimeout      = TimeSpan.Zero,
            CoordinationFeeRate            = CoordinationFeeRate.Zero
        };

        var(keyChain, coin1, coin2) = WabiSabiFactory.CreateCoinKeyPairs();

        var mockRpc = WabiSabiFactory.CreatePreconfiguredRpcClient(coin1.Coin, coin2.Coin);

        using Arena arena = await ArenaBuilder.From(cfg).With(mockRpc).CreateAndStartAsync();

        var(round, arenaClient, alices) = await CreateRoundWithTwoConfirmedConnectionsAsync(arena, keyChain, coin1, coin2);

        var(amountCredentials1, vsizeCredentials1) = (alices[0].IssuedAmountCredentials, alices[0].IssuedVsizeCredentials);
        var(amountCredentials2, vsizeCredentials2) = (alices[1].IssuedAmountCredentials, alices[1].IssuedVsizeCredentials);

        // Register outputs.
        var bobClient = new BobClient(round.Id, arenaClient);

        using var destKey = new Key();
        await bobClient.RegisterOutputAsync(
            destKey.PubKey.WitHash.ScriptPubKey,
            amountCredentials1.Take(ProtocolConstants.CredentialNumber),
            vsizeCredentials1.Take(ProtocolConstants.CredentialNumber),
            CancellationToken.None);

        await arena.TriggerAndWaitRoundAsync(TimeSpan.FromSeconds(21));

        Assert.Equal(Phase.TransactionSigning, round.Phase);
        var tx = round.Assert <SigningState>().CreateTransaction();

        Assert.Equal(2, tx.Inputs.Count);
        Assert.Equal(2, tx.Outputs.Count);
        Assert.Contains(round.CoordinatorScript, tx.Outputs.Select(x => x.ScriptPubKey));

        await arena.StopAsync(CancellationToken.None);
    }
Ejemplo n.º 20
0
        public WaitHandle Start()
        {
            ConcentratorServer ConcentratorServer = null;
            ProvisioningClient ProvisioningClient = null;

            if (Types.TryGetModuleParameter("Concentrator", out object Obj))
            {
                ConcentratorServer = Obj as ConcentratorServer;
            }

            if (Types.TryGetModuleParameter("Provisioning", out Obj))
            {
                ProvisioningClient = Obj as ProvisioningClient;
            }

            this.bobClient  = new BobClient(Gateway.XmppClient, Path.Combine(Gateway.AppDataFolder, "BoB"));
            this.chatServer = new ChatServer(Gateway.XmppClient, this.bobClient, ConcentratorServer, ProvisioningClient);

            return(null);
        }
    public async Task StartOutputRegistrationsAsync(IEnumerable <TxOut> txOuts, BobClient bobClient, IKeyChain keyChain, ImmutableList <DateTimeOffset> outputRegistrationScheduledDates, CancellationToken cancellationToken)
    {
        using CancellationTokenSource ctsOnError = new();
        using CancellationTokenSource linkedCts  = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, ctsOnError.Token);

        var nodes = Graph.Outputs.Select(node =>
        {
            var amountCredsToPresentTasks = Graph.InEdges(node, CredentialType.Amount).Select(edge => DependencyTasks[edge].Task);
            var vsizeCredsToPresentTasks  = Graph.InEdges(node, CredentialType.Vsize).Select(edge => DependencyTasks[edge].Task);

            SmartRequestNode smartRequestNode = new(
                amountCredsToPresentTasks,
                vsizeCredsToPresentTasks,
                Array.Empty <TaskCompletionSource <Credential> >(),
                Array.Empty <TaskCompletionSource <Credential> >());
            return(smartRequestNode);
        });

        var tasks = txOuts.Zip(nodes, outputRegistrationScheduledDates,
                               async(txOut, smartRequestNode, scheduledDate) =>
        {
            try
            {
                var delay = scheduledDate - DateTimeOffset.UtcNow;
                if (delay > TimeSpan.Zero)
                {
                    await Task.Delay(delay, cancellationToken).ConfigureAwait(false);
                }
                await smartRequestNode.StartOutputRegistrationAsync(bobClient, txOut.ScriptPubKey, cancellationToken).ConfigureAwait(false);
            }
            catch (WabiSabiProtocolException ex) when(ex.ErrorCode == WabiSabiProtocolErrorCode.AlreadyRegisteredScript)
            {
                Logger.LogDebug($"Output registration error, code:'{ex.ErrorCode}' message:'{ex.Message}'.");
                if (keyChain is KeyChain {
                    KeyManager: var keyManager
                } &&
                    keyManager.TryGetKeyForScriptPubKey(txOut.ScriptPubKey, out var hdPubKey))
                {
                    hdPubKey.SetKeyState(KeyState.Used);
                }
            }
Ejemplo n.º 22
0
        private async Task RegisterOutputAsync(CcjClientRound ongoingRound)
        {
            IEnumerable <TxoRef> registeredInputs = ongoingRound.Registration.CoinsRegistered.Select(x => x.GetTxoRef());

            var shuffledOutputs = ongoingRound.Registration.ActiveOutputs.ToList();

            shuffledOutputs.Shuffle();
            foreach (var activeOutput in shuffledOutputs)
            {
                using (var bobClient = new BobClient(CcjHostUriAction, TorSocks5EndPoint))
                {
                    if (!await bobClient.PostOutputAsync(ongoingRound.RoundId, activeOutput))
                    {
                        Logger.LogWarning <AliceClient>($"Round ({ongoingRound.State.RoundId}) Bobs did not have enough time to post outputs before timeout. If you see this message, contact nopara73, so he can optimize the phase timeout periods to the worst Internet/Tor connections, which may be yours.)");
                        break;
                    }

                    // Unblind our exposed links.
                    foreach (TxoRef input in registeredInputs)
                    {
                        if (ExposedLinks.ContainsKey(input))                         // Should never not contain, but oh well, let's not disrupt the round for this.
                        {
                            var found = ExposedLinks[input].FirstOrDefault(x => x.Key.GetP2wpkhAddress(Network) == activeOutput.Address);
                            if (found != default)
                            {
                                found.IsBlinded = false;
                            }
                            else
                            {
                                // Should never happen, but oh well we can autocorrect it so why not.
                                ExposedLinks[input] = ExposedLinks[input].Append(new HdPubKeyBlindedPair(KeyManager.GetKeyForScriptPubKey(activeOutput.Address.ScriptPubKey), false));
                            }
                        }
                    }
                }
            }

            ongoingRound.Registration.SetPhaseCompleted(CcjRoundPhase.OutputRegistration);
            Logger.LogInfo <AliceClient>($"Round ({ongoingRound.State.RoundId}) Bob Posted outputs: {ongoingRound.Registration.ActiveOutputs.Count()}.");
        }
Ejemplo n.º 23
0
		/// <summary>
		/// Invoked when application execution is being suspended.  Application state is saved
		/// without knowing whether the application will be terminated or resumed with the contents
		/// of memory still intact.
		/// </summary>
		/// <param name="sender">The source of the suspend request.</param>
		/// <param name="e">Details about the suspend request.</param>
		private void OnSuspending(object sender, SuspendingEventArgs e)
		{
			var deferral = e.SuspendingOperation.GetDeferral();

			this.subscription?.Unsubscribe();
			this.subscription = null;

			this.registryClient?.Dispose();
			this.registryClient = null;

			this.chatServer?.Dispose();
			this.chatServer = null;

			this.bobClient?.Dispose();
			this.bobClient = null;

			this.sensorServer?.Dispose();
			this.sensorServer = null;

			this.sensorClient?.Dispose();
			this.sensorClient = null;

			this.controlClient?.Dispose();
			this.controlClient = null;

			this.xmppClient?.Dispose();
			this.xmppClient = null;

			this.secondTimer?.Dispose();
			this.secondTimer = null;

			db?.Stop()?.Wait();
			db?.Flush()?.Wait();

			Log.Terminate();

			deferral.Complete();
		}
Ejemplo n.º 24
0
        private async void StartActuator()
        {
            try
            {
                Log.Informational("Starting application.");

                SimpleXmppConfiguration xmppConfiguration = SimpleXmppConfiguration.GetConfigUsingSimpleConsoleDialog("xmpp.config",
                                                                                                                      Guid.NewGuid().ToString().Replace("-", string.Empty), // Default user name.
                                                                                                                      Guid.NewGuid().ToString().Replace("-", string.Empty), // Default password.
                                                                                                                      FormSignatureKey, FormSignatureSecret, typeof(App).GetTypeInfo().Assembly);

                Log.Informational("Connecting to XMPP server.");

                xmppClient = xmppConfiguration.GetClient("en", typeof(App).GetTypeInfo().Assembly, false);
                xmppClient.AllowRegistration(FormSignatureKey, FormSignatureSecret);

                if (xmppConfiguration.Sniffer && MainPage.Sniffer != null)
                {
                    xmppClient.Add(MainPage.Sniffer);
                }

                if (!string.IsNullOrEmpty(xmppConfiguration.Events))
                {
                    Log.Register(new XmppEventSink("XMPP Event Sink", xmppClient, xmppConfiguration.Events, false));
                }

                if (!string.IsNullOrEmpty(xmppConfiguration.ThingRegistry))
                {
                    thingRegistryClient = new ThingRegistryClient(xmppClient, xmppConfiguration.ThingRegistry);

                    thingRegistryClient.Claimed += (sender, e) =>
                    {
                        ownerJid = e.JID;
                        Log.Informational("Thing has been claimed.", ownerJid, new KeyValuePair <string, object>("Public", e.IsPublic));
                        this.RaiseOwnershipChanged();
                    };

                    thingRegistryClient.Disowned += (sender, e) =>
                    {
                        Log.Informational("Thing has been disowned.", ownerJid);
                        ownerJid = string.Empty;
                        this.Register();                            // Will call this.OwnershipChanged() after successful registration.
                    };

                    thingRegistryClient.Removed += (sender, e) =>
                    {
                        Log.Informational("Thing has been removed from the public registry.", ownerJid);
                    };
                }

                if (!string.IsNullOrEmpty(xmppConfiguration.Provisioning))
                {
                    provisioningClient = new ProvisioningClient(xmppClient, xmppConfiguration.Provisioning);
                }

                Timer ConnectionTimer = new Timer((P) =>
                {
                    if (xmppClient.State == XmppState.Offline || xmppClient.State == XmppState.Error || xmppClient.State == XmppState.Authenticating)
                    {
                        try
                        {
                            Log.Informational("Reconnecting.");
                            xmppClient.Reconnect();
                        }
                        catch (Exception ex)
                        {
                            Log.Critical(ex);
                        }
                    }
                }, null, 60000, 60000);

                xmppClient.OnStateChanged += (sender, NewState) =>
                {
                    Log.Informational(NewState.ToString());

                    switch (NewState)
                    {
                    case XmppState.Connected:
                        connected = true;

                        if (!registered && thingRegistryClient != null)
                        {
                            Register();
                        }
                        break;

                    case XmppState.Offline:
                        immediateReconnect = connected;
                        connected          = false;

                        if (immediateReconnect)
                        {
                            xmppClient.Reconnect();
                        }
                        break;
                    }
                };

                xmppClient.OnPresenceSubscribe += (sender, e) =>
                {
                    Log.Informational("Subscription request received from " + e.From + ".");

                    e.Accept();                         // TODO: Provisioning

                    RosterItem Item = xmppClient.GetRosterItem(e.FromBareJID);
                    if (Item == null || Item.State == SubscriptionState.None || Item.State == SubscriptionState.From)
                    {
                        xmppClient.RequestPresenceSubscription(e.FromBareJID);
                    }

                    xmppClient.SetPresence(Availability.Chat);
                };

                xmppClient.OnPresenceUnsubscribe += (sender, e) =>
                {
                    Log.Informational("Unsubscription request received from " + e.From + ".");
                    e.Accept();
                };

                xmppClient.OnRosterItemUpdated += (sender, e) =>
                {
                    if (e.State == SubscriptionState.None && e.PendingSubscription != PendingSubscription.Subscribe)
                    {
                        xmppClient.RemoveRosterItem(e.BareJid);
                    }
                };

                bool SwitchOn = false;

                sensorServer = new SensorServer(xmppClient, provisioningClient, false);
                sensorServer.OnExecuteReadoutRequest += (Sender, Request) =>
                {
                    DateTime Now = DateTime.Now;

                    Log.Informational("Readout requested", string.Empty, Request.Actor);

                    Request.ReportFields(true, new BooleanField(ThingReference.Empty, Now, "Lamp", SwitchOn, FieldType.Momentary, FieldQoS.AutomaticReadout));
                };

                controlServer = new ControlServer(xmppClient,
                                                  new BooleanControlParameter("Lamp", "Control", "Lamp switch on.", "If checked, lamp is turned on.",
                                                                              (Node) => SwitchOn,
                                                                              (Node, Value) =>
                {
                    SwitchOn = Value;
                    Log.Informational("Lamp turned " + (SwitchOn ? "ON" : "OFF"));
                    UpdateMainWindow(SwitchOn);
                }));

                this.bobClient  = new BobClient(this.xmppClient, Path.Combine(Path.GetTempPath(), "BitsOfBinary"));
                this.chatServer = new ChatServer(xmppClient, this.bobClient, this.sensorServer, this.controlServer);

                interoperabilityServer = new InteroperabilityServer(xmppClient);
                interoperabilityServer.OnGetInterfaces += (sender, e) =>
                {
                    e.Add("XMPP.IoT.Actuator.Lamp");
                };

                xmppClient.Connect();
            }
            catch (Exception ex)
            {
                Log.Emergency(ex);

                MessageDialog Dialog = new MessageDialog(ex.Message, "Error");
                await Dialog.ShowAsync();
            }
        }
Ejemplo n.º 25
0
        private async void StartSensor()
        {
            try
            {
                Log.Informational("Starting application.");

                XmppCredentials Credentials = SimpleXmppConfiguration.GetConfigUsingSimpleConsoleDialog("xmpp.config",
                                                                                                        Guid.NewGuid().ToString().Replace("-", string.Empty), // Default user name.
                                                                                                        Guid.NewGuid().ToString().Replace("-", string.Empty), // Default password.
                                                                                                        typeof(App).GetTypeInfo().Assembly);

                Log.Informational("Connecting to XMPP server.");

                xmppClient = new XmppClient(Credentials, "en", typeof(App).GetTypeInfo().Assembly);

                if (Credentials.Sniffer && MainPage.Sniffer != null)
                {
                    xmppClient.Add(MainPage.Sniffer);
                }

                if (!string.IsNullOrEmpty(Credentials.Events))
                {
                    Log.Register(new XmppEventSink("XMPP Event Sink", xmppClient, Credentials.Events, false));
                }

                if (!string.IsNullOrEmpty(Credentials.ThingRegistry))
                {
                    thingRegistryClient = new ThingRegistryClient(xmppClient, Credentials.ThingRegistry);

                    thingRegistryClient.Claimed += (sender, e) =>
                    {
                        ownerJid = e.JID;
                        Log.Informational("Thing has been claimed.", ownerJid, new KeyValuePair <string, object>("Public", e.IsPublic));
                        this.RaiseOwnershipChanged();
                    };

                    thingRegistryClient.Disowned += (sender, e) =>
                    {
                        Log.Informational("Thing has been disowned.", ownerJid);
                        ownerJid = string.Empty;
                        this.Register();                            // Will call this.OwnershipChanged() after successful registration.
                    };

                    thingRegistryClient.Removed += (sender, e) =>
                    {
                        Log.Informational("Thing has been removed from the public registry.", ownerJid);
                    };
                }

                if (!string.IsNullOrEmpty(Credentials.Provisioning))
                {
                    provisioningClient = new ProvisioningClient(xmppClient, Credentials.Provisioning);
                }

                Timer ConnectionTimer = new Timer((P) =>
                {
                    if (xmppClient.State == XmppState.Offline || xmppClient.State == XmppState.Error || xmppClient.State == XmppState.Authenticating)
                    {
                        try
                        {
                            Log.Informational("Reconnecting.");
                            xmppClient.Reconnect();
                        }
                        catch (Exception ex)
                        {
                            Log.Critical(ex);
                        }
                    }
                }, null, 60000, 60000);

                xmppClient.OnStateChanged += (sender, NewState) =>
                {
                    Log.Informational(NewState.ToString());

                    switch (NewState)
                    {
                    case XmppState.Connected:
                        connected = true;

                        if (!registered && thingRegistryClient != null)
                        {
                            this.Register();
                        }
                        break;

                    case XmppState.Offline:
                        immediateReconnect = connected;
                        connected          = false;

                        if (immediateReconnect)
                        {
                            xmppClient.Reconnect();
                        }
                        break;
                    }
                };

                xmppClient.OnPresenceSubscribe += (sender, e) =>
                {
                    Log.Informational("Subscription request received from " + e.From + ".");

                    e.Accept();                         // TODO: Provisioning

                    RosterItem Item = xmppClient.GetRosterItem(e.FromBareJID);
                    if (Item is null || Item.State == SubscriptionState.None || Item.State == SubscriptionState.From)
                    {
                        xmppClient.RequestPresenceSubscription(e.FromBareJID);
                    }

                    xmppClient.SetPresence(Availability.Chat);
                };

                xmppClient.OnPresenceUnsubscribe += (sender, e) =>
                {
                    Log.Informational("Unsubscription request received from " + e.From + ".");
                    e.Accept();
                };

                xmppClient.OnRosterItemUpdated += (sender, e) =>
                {
                    if (e.State == SubscriptionState.None && e.PendingSubscription != PendingSubscription.Subscribe)
                    {
                        xmppClient.RemoveRosterItem(e.BareJid);
                    }
                };

                LinkedList <DayHistoryRecord>    DayHistoricalValues    = new LinkedList <DayHistoryRecord>();
                LinkedList <MinuteHistoryRecord> MinuteHistoricalValues = new LinkedList <MinuteHistoryRecord>();
                DateTime SampleTime  = DateTime.Now;
                DateTime PeriodStart = SampleTime.Date;
                DateTime Now;
                DateTime MinTime            = SampleTime;
                DateTime MaxTime            = SampleTime;
                double   CurrentTemperature = this.ReadTemp();
                double   MinTemp            = CurrentTemperature;
                double   MaxTemp            = CurrentTemperature;
                double   SumTemp            = CurrentTemperature;
                int      NrTemp             = 1;
                int      NrDayRecords       = 0;
                int      NrMinuteRecords    = 0;
                object   SampleSynch        = new object();

                this.sampleTimer = new Timer((P) =>
                {
                    lock (SampleSynch)
                    {
                        Now = DateTime.Now;

                        if (Now.Date != PeriodStart.Date)
                        {
                            DayHistoryRecord Rec = new DayHistoryRecord(PeriodStart.Date, PeriodStart.Date.AddDays(1).AddMilliseconds(-1),
                                                                        MinTemp, MaxTemp, SumTemp / NrTemp);

                            DayHistoricalValues.AddFirst(Rec);

                            if (NrDayRecords < MaxRecordsPerPeriod)
                            {
                                NrDayRecords++;
                            }
                            else
                            {
                                DayHistoricalValues.RemoveLast();
                            }

                            // TODO: Persistence

                            PeriodStart = Now.Date;
                            SumTemp     = 0;
                            NrTemp      = 0;
                        }

                        CurrentTemperature = this.ReadTemp();

                        if (Now.Minute != SampleTime.Minute)
                        {
                            MinuteHistoryRecord Rec = new MinuteHistoryRecord(Now, CurrentTemperature);

                            MinuteHistoricalValues.AddFirst(Rec);

                            if (NrMinuteRecords < MaxRecordsPerPeriod)
                            {
                                NrMinuteRecords++;
                            }
                            else
                            {
                                MinuteHistoricalValues.RemoveLast();
                            }

                            // TODO: Persistence
                        }

                        SampleTime = Now;

                        if (CurrentTemperature < MinTemp)
                        {
                            MinTemp = CurrentTemperature;
                            MinTime = SampleTime;
                        }

                        if (CurrentTemperature > MaxTemp)
                        {
                            MaxTemp = CurrentTemperature;
                            MaxTime = SampleTime;
                        }

                        SumTemp += CurrentTemperature;
                        NrTemp++;
                    }

                    if (this.sensorServer.HasSubscriptions(ThingReference.Empty))
                    {
                        this.sensorServer.NewMomentaryValues(new QuantityField(ThingReference.Empty, SampleTime, "Temperature",
                                                                               CurrentTemperature, 1, "°C", FieldType.Momentary, FieldQoS.AutomaticReadout));
                    }

                    this.UpdateMainWindow(CurrentTemperature, MinTemp, MaxTemp, SumTemp / NrTemp);
                }, null, 1000 - PeriodStart.Millisecond, 1000);

                this.sensorServer = new SensorServer(xmppClient, provisioningClient, true);
                this.sensorServer.OnExecuteReadoutRequest += (Sender, Request) =>
                {
                    Log.Informational("Readout requested by " + Request.From, string.Empty, Request.Actor);

                    List <Field> Fields          = new List <Field>();
                    bool         IncludeTemp     = Request.IsIncluded("Temperature");
                    bool         IncludeTempMin  = Request.IsIncluded("Temperature, Min");
                    bool         IncludeTempMax  = Request.IsIncluded("Temperature, Max");
                    bool         IncludeTempAvg  = Request.IsIncluded("Temperature, Average");
                    bool         IncludePeak     = Request.IsIncluded(FieldType.Peak);
                    bool         IncludeComputed = Request.IsIncluded(FieldType.Computed);

                    lock (SampleSynch)
                    {
                        if (IncludeTemp && Request.IsIncluded(FieldType.Momentary))
                        {
                            Fields.Add(new QuantityField(ThingReference.Empty, SampleTime, "Temperature", CurrentTemperature, 1, "°C",
                                                         FieldType.Momentary, FieldQoS.AutomaticReadout));
                        }

                        if (IncludePeak)
                        {
                            if (IncludeTempMin)
                            {
                                Fields.Add(new QuantityField(ThingReference.Empty, MinTime, "Temperature, Min", MinTemp, 1, "°C",
                                                             FieldType.Peak, FieldQoS.AutomaticReadout));
                            }

                            if (IncludeTempMax)
                            {
                                Fields.Add(new QuantityField(ThingReference.Empty, MaxTime, "Temperature, Max", MaxTemp, 1, "°C",
                                                             FieldType.Peak, FieldQoS.AutomaticReadout));
                            }
                        }

                        if (IncludeTempAvg && IncludeComputed)
                        {
                            Fields.Add(new QuantityField(ThingReference.Empty, SampleTime, "Temperature, Average", SumTemp / NrTemp, 2, "°C",
                                                         FieldType.Computed, FieldQoS.AutomaticReadout));
                        }

                        if (Request.IsIncluded(FieldType.Historical))
                        {
                            foreach (DayHistoryRecord Rec in DayHistoricalValues)
                            {
                                if (!Request.IsIncluded(Rec.PeriodStart))
                                {
                                    continue;
                                }

                                if (Fields.Count >= 100)
                                {
                                    Request.ReportFields(false, Fields);
                                    Fields.Clear();
                                }

                                if (IncludePeak)
                                {
                                    if (IncludeTempMin)
                                    {
                                        Fields.Add(new QuantityField(ThingReference.Empty, Rec.PeriodStart, "Temperature, Min", Rec.MinTemperature, 1, "°C",
                                                                     FieldType.Peak | FieldType.Historical, FieldQoS.AutomaticReadout));
                                    }

                                    if (IncludeTempMax)
                                    {
                                        Fields.Add(new QuantityField(ThingReference.Empty, Rec.PeriodStart, "Temperature, Max", Rec.MaxTemperature, 1, "°C",
                                                                     FieldType.Peak | FieldType.Historical, FieldQoS.AutomaticReadout));
                                    }
                                }

                                if (IncludeTempAvg && IncludeComputed)
                                {
                                    Fields.Add(new QuantityField(ThingReference.Empty, Rec.PeriodStart, "Temperature, Average", Rec.AverageTemperature, 1, "°C",
                                                                 FieldType.Computed | FieldType.Historical, FieldQoS.AutomaticReadout));
                                }
                            }

                            foreach (MinuteHistoryRecord Rec in MinuteHistoricalValues)
                            {
                                if (!Request.IsIncluded(Rec.Timestamp))
                                {
                                    continue;
                                }

                                if (IncludeTemp)
                                {
                                    if (Fields.Count >= 100)
                                    {
                                        Request.ReportFields(false, Fields);
                                        Fields.Clear();
                                    }

                                    Fields.Add(new QuantityField(ThingReference.Empty, Rec.Timestamp, "Temperature", Rec.Temperature, 1, "°C",
                                                                 FieldType.Historical, FieldQoS.AutomaticReadout));
                                }
                            }
                        }
                    }

                    Request.ReportFields(true, Fields);
                };

                this.bobClient  = new BobClient(this.xmppClient, Path.Combine(Path.GetTempPath(), "BitsOfBinary"));
                this.chatServer = new ChatServer(this.xmppClient, this.bobClient, this.sensorServer, this.provisioningClient);

                this.interoperabilityServer = new InteroperabilityServer(xmppClient);
                this.interoperabilityServer.OnGetInterfaces += (sender, e) =>
                {
                    e.Add("XMPP.IoT.Sensor.Temperature",
                          "XMPP.IoT.Sensor.Temperature.History",
                          "XMPP.IoT.Sensor.Temperature.Average",
                          "XMPP.IoT.Sensor.Temperature.Average.History",
                          "XMPP.IoT.Sensor.Temperature.Min",
                          "XMPP.IoT.Sensor.Temperature.Min.History",
                          "XMPP.IoT.Sensor.Temperature.Max",
                          "XMPP.IoT.Sensor.Temperature.Max.History");
                };

                xmppClient.Connect();
            }
            catch (Exception ex)
            {
                Log.Emergency(ex);

                MessageDialog Dialog = new MessageDialog(ex.Message, "Error");
                await Dialog.ShowAsync();
            }
        }
Ejemplo n.º 26
0
        public static void Main(string[] _)
        {
            try
            {
                Console.ForegroundColor = ConsoleColor.White;

                Console.Out.WriteLine("Welcome to the PC Sensor application.");
                Console.Out.WriteLine(new string('-', 79));
                Console.Out.WriteLine("This application will publish performace couters as sensor values.");
                Console.Out.WriteLine("Values will be published over XMPP using the interface defined in the IEEE XMPP IoT extensions.");

                Log.Register(new ConsoleEventSink(false));
                Log.RegisterExceptionToUnnest(typeof(System.Runtime.InteropServices.ExternalException));
                Log.RegisterExceptionToUnnest(typeof(System.Security.Authentication.AuthenticationException));

                credentials = SimpleXmppConfiguration.GetConfigUsingSimpleConsoleDialog("xmpp.config",
                                                                                        Environment.MachineName,                              // Default user name.
                                                                                        Guid.NewGuid().ToString().Replace("-", string.Empty), // Default password.
                                                                                        typeof(Program).Assembly);

                using (XmppClient Client = new XmppClient(credentials, "en", typeof(Program).Assembly))
                {
                    if (credentials.Sniffer)
                    {
                        Client.Add(new ConsoleOutSniffer(BinaryPresentationMethod.ByteCount, LineEnding.PadWithSpaces));
                    }

                    if (!string.IsNullOrEmpty(credentials.Events))
                    {
                        Log.Register(new XmppEventSink("XMPP Event Sink", Client, credentials.Events, false));
                    }

                    if (!string.IsNullOrEmpty(credentials.ThingRegistry))
                    {
                        thingRegistryClient = new ThingRegistryClient(Client, credentials.ThingRegistry);

                        thingRegistryClient.Claimed += (sender, e) =>
                        {
                            ownerJid = e.JID;
                            Log.Informational("Thing has been claimed.", ownerJid, new KeyValuePair <string, object>("Public", e.IsPublic));
                            return(Task.CompletedTask);
                        };

                        thingRegistryClient.Disowned += (sender, e) =>
                        {
                            Log.Informational("Thing has been disowned.", ownerJid);
                            ownerJid = string.Empty;
                            Register();
                            return(Task.CompletedTask);
                        };

                        thingRegistryClient.Removed += (sender, e) =>
                        {
                            Log.Informational("Thing has been removed from the public registry.", ownerJid);
                            return(Task.CompletedTask);
                        };
                    }

                    ProvisioningClient ProvisioningClient = null;
                    if (!string.IsNullOrEmpty(credentials.Provisioning))
                    {
                        ProvisioningClient = new ProvisioningClient(Client, credentials.Provisioning);
                    }

                    Timer ConnectionTimer = new Timer((P) =>
                    {
                        if (Client.State == XmppState.Offline || Client.State == XmppState.Error || Client.State == XmppState.Authenticating)
                        {
                            try
                            {
                                Client.Reconnect();
                            }
                            catch (Exception ex)
                            {
                                Log.Critical(ex);
                            }
                        }
                    }, null, 60000, 60000);

                    bool Connected = false;
                    bool ImmediateReconnect;

                    Client.OnStateChanged += (sender, NewState) =>
                    {
                        switch (NewState)
                        {
                        case XmppState.Connected:
                            Connected = true;

                            if (!registered && thingRegistryClient != null)
                            {
                                Register();
                            }
                            break;

                        case XmppState.Offline:
                            ImmediateReconnect = Connected;
                            Connected          = false;

                            if (ImmediateReconnect)
                            {
                                Client.Reconnect();
                            }
                            break;
                        }

                        return(Task.CompletedTask);
                    };

                    Client.OnPresenceSubscribe += (sender, e) =>
                    {
                        e.Accept();                             // TODO: Provisioning

                        RosterItem Item = Client.GetRosterItem(e.FromBareJID);
                        if (Item is null || Item.State == SubscriptionState.None || Item.State == SubscriptionState.From)
                        {
                            Client.RequestPresenceSubscription(e.FromBareJID);
                        }

                        Client.SetPresence(Availability.Chat);

                        return(Task.CompletedTask);
                    };

                    Client.OnPresenceUnsubscribe += (sender, e) =>
                    {
                        e.Accept();
                        return(Task.CompletedTask);
                    };

                    Client.OnRosterItemUpdated += (sender, e) =>
                    {
                        if (e.State == SubscriptionState.None && e.PendingSubscription != PendingSubscription.Subscribe)
                        {
                            Client.RemoveRosterItem(e.BareJid);
                        }

                        return(Task.CompletedTask);
                    };

                    SortedDictionary <string, string[]> CategoryIncluded = new SortedDictionary <string, string[]>();

                    List <string> Instances = new List <string>();
                    XmlDocument   Doc       = new XmlDocument()
                    {
                        PreserveWhitespace = true
                    };
                    Doc.Load("categories.xml");

                    XSL.Validate("categories.xml", Doc, "Categories", "http://waher.se/Schema/PerformanceCounterCategories.xsd",
                                 XSL.LoadSchema("Waher.Service.PcSensor.Schema.PerformanceCounterCategories.xsd"));

                    foreach (XmlNode N in Doc.DocumentElement.ChildNodes)
                    {
                        if (N.LocalName == "Category")
                        {
                            XmlElement E       = (XmlElement)N;
                            string     Name    = XML.Attribute(E, "name");
                            bool       Include = XML.Attribute(E, "include", false);

                            if (Include)
                            {
                                Instances.Clear();

                                foreach (XmlNode N2 in N.ChildNodes)
                                {
                                    if (N2.LocalName == "Instance")
                                    {
                                        E = (XmlElement)N2;
                                        Instances.Add(XML.Attribute(E, "name"));
                                    }
                                }

                                CategoryIncluded[Name] = Instances.ToArray();
                            }
                            else
                            {
                                CategoryIncluded[Name] = null;
                            }
                        }
                    }

                    SensorServer SensorServer = new SensorServer(Client, ProvisioningClient, false);
                    SensorServer.OnExecuteReadoutRequest += (Sender, Request) =>
                    {
                        Log.Informational("Readout requested", string.Empty, Request.Actor);

                        List <Field> Fields = new List <Field>();
                        DateTime     Now    = DateTime.Now;

                        Fields.Add(new StringField(ThingReference.Empty, Now, "Machine Name", Environment.MachineName, FieldType.Identity, FieldQoS.AutomaticReadout));
                        Fields.Add(new StringField(ThingReference.Empty, Now, "OS Platform", Environment.OSVersion.Platform.ToString(), FieldType.Identity, FieldQoS.AutomaticReadout));
                        Fields.Add(new StringField(ThingReference.Empty, Now, "OS Service Pack", Environment.OSVersion.ServicePack, FieldType.Identity, FieldQoS.AutomaticReadout));
                        Fields.Add(new StringField(ThingReference.Empty, Now, "OS Version", Environment.OSVersion.VersionString, FieldType.Identity, FieldQoS.AutomaticReadout));
                        Fields.Add(new Int32Field(ThingReference.Empty, Now, "Processor Count", Environment.ProcessorCount, FieldType.Status, FieldQoS.AutomaticReadout));

                        string[] InstanceNames;
                        string   FieldName;
                        string   Unit;
                        double   Value;
                        byte     NrDec;
                        bool     Updated = false;

                        foreach (PerformanceCounterCategory Category in PerformanceCounterCategory.GetCategories())
                        {
                            FieldName = Category.CategoryName;
                            lock (CategoryIncluded)
                            {
                                if (CategoryIncluded.TryGetValue(FieldName, out InstanceNames))
                                {
                                    if (InstanceNames is null)
                                    {
                                        continue;
                                    }
                                }
                                else
                                {
                                    CategoryIncluded[FieldName] = null;
                                    Updated = true;
                                    continue;
                                }
                            }

                            if (Category.CategoryType == PerformanceCounterCategoryType.MultiInstance)
                            {
                                foreach (string InstanceName in Category.GetInstanceNames())
                                {
                                    if (InstanceNames.Length > 0 && Array.IndexOf <string>(InstanceNames, InstanceName) < 0)
                                    {
                                        continue;
                                    }

                                    foreach (PerformanceCounter Counter in Category.GetCounters(InstanceName))
                                    {
                                        FieldName = Category.CategoryName + ", " + InstanceName + ", " + Counter.CounterName;
                                        Value     = Counter.NextValue();
                                        GetUnitPrecision(ref FieldName, Value, out NrDec, out Unit);

                                        if (Fields.Count >= 100)
                                        {
                                            Request.ReportFields(false, Fields);
                                            Fields.Clear();
                                        }

                                        Fields.Add(new QuantityField(ThingReference.Empty, Now, FieldName, Value, NrDec, Unit, FieldType.Momentary, FieldQoS.AutomaticReadout));
                                    }
                                }
                            }
                            else
                            {
                                foreach (PerformanceCounter Counter in Category.GetCounters())
                                {
                                    FieldName = Category.CategoryName + ", " + Counter.CounterName;
                                    Value     = Counter.NextValue();
                                    GetUnitPrecision(ref FieldName, Value, out NrDec, out Unit);

                                    if (Fields.Count >= 100)
                                    {
                                        Request.ReportFields(false, Fields);
                                        Fields.Clear();
                                    }

                                    Fields.Add(new QuantityField(ThingReference.Empty, Now, FieldName, Value, NrDec, Unit, FieldType.Momentary, FieldQoS.AutomaticReadout));
                                }
                            }
                        }

                        Request.ReportFields(true, Fields);

                        if (Updated)
                        {
                            using (StreamWriter s = File.CreateText("categories.xml"))
                            {
                                using (XmlWriter w = XmlWriter.Create(s, XML.WriterSettings(true, false)))
                                {
                                    w.WriteStartElement("Categories", "http://waher.se/Schema/PerformanceCounterCategories.xsd");

                                    lock (CategoryIncluded)
                                    {
                                        foreach (KeyValuePair <string, string[]> P in CategoryIncluded)
                                        {
                                            w.WriteStartElement("Category");
                                            w.WriteAttributeString("name", P.Key);
                                            w.WriteAttributeString("include", CommonTypes.Encode(P.Value != null));

                                            if (P.Value != null)
                                            {
                                                foreach (string InstanceName in P.Value)
                                                {
                                                    w.WriteStartElement("Instance");
                                                    w.WriteAttributeString("name", P.Key);
                                                    w.WriteEndElement();
                                                }
                                            }

                                            w.WriteEndElement();
                                        }
                                    }

                                    w.WriteEndElement();
                                    w.Flush();
                                }
                            }
                        }

                        return(Task.CompletedTask);
                    };

                    BobClient  BobClient  = new BobClient(Client, Path.Combine(Path.GetTempPath(), "BitsOfBinary"));
                    ChatServer ChatServer = new ChatServer(Client, BobClient, SensorServer, ProvisioningClient);

                    Client.Connect();

                    while (true)
                    {
                        Thread.Sleep(1000);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.Out.WriteLine(ex.Message);
            }
            finally
            {
                Log.Terminate();
            }
        }
Ejemplo n.º 27
0
        private void AttachFeatures()
        {
            this.controlServer = new ControlServer(this.xmppClient,
                                                   new BooleanControlParameter("Output", "Actuator", "Output:", "Digital output.",
                                                                               (Node) => this.output,
                                                                               async(Node, Value) =>
            {
                try
                {
                    await this.SetOutput(Value, "XMPP");
                }
                catch (Exception ex)
                {
                    Log.Critical(ex);
                }
            }));

            this.sensorServer = new SensorServer(this.xmppClient, true);
            this.sensorServer.OnExecuteReadoutRequest += (sender, e) =>
            {
                try
                {
                    Log.Informational("Performing readout.", this.xmppClient.BareJID, e.Actor);

                    List <Field> Fields = new List <Field>();
                    DateTime     Now    = DateTime.Now;

                    if (e.IsIncluded(FieldType.Identity))
                    {
                        Fields.Add(new StringField(ThingReference.Empty, Now, "Device ID", this.deviceId, FieldType.Identity, FieldQoS.AutomaticReadout));
                    }

                    if (this.output.HasValue)
                    {
                        Fields.Add(new BooleanField(ThingReference.Empty, Now, "Output", this.output.Value,
                                                    FieldType.Momentary, FieldQoS.AutomaticReadout, true));
                    }

                    e.ReportFields(true, Fields);
                }
                catch (Exception ex)
                {
                    Log.Critical(ex);
                }
            };

            this.xmppClient.OnError           += (Sender, ex) => Log.Error(ex);
            this.xmppClient.OnPasswordChanged += (Sender, e) => Log.Informational("Password changed.", this.xmppClient.BareJID);

            this.xmppClient.OnPresenceSubscribe += (Sender, e) =>
            {
                Log.Informational("Accepting friendship request.", this.xmppClient.BareJID, e.From);
                e.Accept();
            };

            this.xmppClient.OnPresenceUnsubscribe += (Sender, e) =>
            {
                Log.Informational("Friendship removed.", this.xmppClient.BareJID, e.From);
                e.Accept();
            };

            this.xmppClient.OnPresenceSubscribed   += (Sender, e) => Log.Informational("Friendship request accepted.", this.xmppClient.BareJID, e.From);
            this.xmppClient.OnPresenceUnsubscribed += (Sender, e) => Log.Informational("Friendship removal accepted.", this.xmppClient.BareJID, e.From);

            this.bobClient  = new BobClient(this.xmppClient, Path.Combine(Path.GetTempPath(), "BitsOfBinary"));
            this.chatServer = new ChatServer(this.xmppClient, this.bobClient, this.sensorServer, this.controlServer);

            // XEP-0054: vcard-temp: http://xmpp.org/extensions/xep-0054.html
            this.xmppClient.RegisterIqGetHandler("vCard", "vcard-temp", this.QueryVCardHandler, true);
        }
    private async Task CompleteConnectionConfirmationAsync(IEnumerable <AliceClient> aliceClients, BobClient bobClient, CancellationToken cancellationToken)
    {
        var aliceNodePairs = PairAliceClientAndRequestNodes(aliceClients, Graph);

        List <Task> connectionConfirmationTasks = new();

        using CancellationTokenSource ctsOnError = new();
        using CancellationTokenSource linkedCts  = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, ctsOnError.Token);

        foreach ((var aliceClient, var node) in aliceNodePairs)
        {
            var amountEdgeTaskCompSources     = Graph.OutEdges(node, CredentialType.Amount).Select(edge => DependencyTasks[edge]);
            var vsizeEdgeTaskCompSources      = Graph.OutEdges(node, CredentialType.Vsize).Select(edge => DependencyTasks[edge]);
            SmartRequestNode smartRequestNode = new(
                aliceClient.IssuedAmountCredentials.Take(ProtocolConstants.CredentialNumber).Select(Task.FromResult),
                aliceClient.IssuedVsizeCredentials.Take(ProtocolConstants.CredentialNumber).Select(Task.FromResult),
                amountEdgeTaskCompSources,
                vsizeEdgeTaskCompSources);

            var amountsToRequest = Graph.OutEdges(node, CredentialType.Amount).Select(e => e.Value);
            var vsizesToRequest  = Graph.OutEdges(node, CredentialType.Vsize).Select(e => e.Value);

            // Although connection confirmation requests support k
            // credential requests, for now we only know which amounts to
            // request after connection confirmation has finished and the
            // final decomposition can be computed, so as a workaround we
            // unconditionally request the full amount in one credential and
            // then do an equivalent reissuance request for every connection
            // confirmation.
            var task = smartRequestNode
                       .StartReissuanceAsync(bobClient, amountsToRequest, vsizesToRequest, linkedCts.Token)
                       .ContinueWith((t) =>
            {
                if (t.IsFaulted && t.Exception is { } exception)
                {
                    // If one task is failing, cancel all the tasks and throw.
                    ctsOnError.Cancel();
                    throw exception;
                }
            }, linkedCts.Token);

            connectionConfirmationTasks.Add(task);
        }

        await Task.WhenAll(connectionConfirmationTasks).ConfigureAwait(false);

        var amountEdges = Graph.Inputs.SelectMany(node => Graph.OutEdges(node, CredentialType.Amount));
        var vsizeEdges  = Graph.Inputs.SelectMany(node => Graph.OutEdges(node, CredentialType.Vsize));

        // Check if all tasks were finished, otherwise Task.Result will block.
        if (!amountEdges.Concat(vsizeEdges).All(edge => DependencyTasks[edge].Task.IsCompletedSuccessfully))
        {
            throw new InvalidOperationException("Some Input nodes out-edges failed to complete.");
        }
    }
Ejemplo n.º 29
0
        static void Main(string[] args)
        {
            try
            {
                Console.ForegroundColor = ConsoleColor.White;

                Console.Out.WriteLine("Welcome to the Mock Temperature sensor application.");
                Console.Out.WriteLine(new string('-', 79));
                Console.Out.WriteLine("This application will simulate an outside temperature sensor.");
                Console.Out.WriteLine("Values will be published over XMPP using the interface defined in the IEEE XMPP IoT extensions.");
                Console.Out.WriteLine("You can also chat with the sensor.");

                Log.Register(new ConsoleEventSink());
                Log.RegisterExceptionToUnnest(typeof(System.Runtime.InteropServices.ExternalException));
                Log.RegisterExceptionToUnnest(typeof(System.Security.Authentication.AuthenticationException));

                credentials = SimpleXmppConfiguration.GetConfigUsingSimpleConsoleDialog("xmpp.config",
                                                                                        Guid.NewGuid().ToString().Replace("-", string.Empty), // Default user name.
                                                                                        Guid.NewGuid().ToString().Replace("-", string.Empty), // Default password.
                                                                                        typeof(Program).Assembly);

                using (XmppClient Client = new XmppClient(credentials, "en", typeof(Program).Assembly))
                {
                    if (credentials.Sniffer)
                    {
                        Client.Add(new ConsoleOutSniffer(BinaryPresentationMethod.ByteCount, LineEnding.PadWithSpaces));
                    }

                    if (!string.IsNullOrEmpty(credentials.Events))
                    {
                        Log.Register(new XmppEventSink("XMPP Event Sink", Client, credentials.Events, false));
                    }

                    if (!string.IsNullOrEmpty(credentials.ThingRegistry))
                    {
                        thingRegistryClient = new ThingRegistryClient(Client, credentials.ThingRegistry);

                        thingRegistryClient.Claimed += (sender, e) =>
                        {
                            ownerJid = e.JID;
                            Log.Informational("Thing has been claimed.", ownerJid, new KeyValuePair <string, object>("Public", e.IsPublic));
                        };

                        thingRegistryClient.Disowned += (sender, e) =>
                        {
                            Log.Informational("Thing has been disowned.", ownerJid);
                            ownerJid = string.Empty;
                            Register();
                        };

                        thingRegistryClient.Removed += (sender, e) =>
                        {
                            Log.Informational("Thing has been removed from the public registry.", ownerJid);
                        };
                    }

                    ProvisioningClient ProvisioningClient = null;
                    if (!string.IsNullOrEmpty(credentials.Provisioning))
                    {
                        ProvisioningClient = new ProvisioningClient(Client, credentials.Provisioning);
                    }

                    Timer ConnectionTimer = new Timer((P) =>
                    {
                        if (Client.State == XmppState.Offline || Client.State == XmppState.Error || Client.State == XmppState.Authenticating)
                        {
                            try
                            {
                                Client.Reconnect();
                            }
                            catch (Exception ex)
                            {
                                Log.Critical(ex);
                            }
                        }
                    }, null, 60000, 60000);

                    bool Connected = false;
                    bool ImmediateReconnect;

                    Client.OnStateChanged += (sender, NewState) =>
                    {
                        switch (NewState)
                        {
                        case XmppState.Connected:
                            Connected = true;

                            if (!registered && thingRegistryClient != null)
                            {
                                Register();
                            }
                            break;

                        case XmppState.Offline:
                            ImmediateReconnect = Connected;
                            Connected          = false;

                            if (ImmediateReconnect)
                            {
                                Client.Reconnect();
                            }
                            break;
                        }
                    };

                    Client.OnPresenceSubscribe += (sender, e) =>
                    {
                        e.Accept();                             // TODO: Provisioning

                        RosterItem Item = Client.GetRosterItem(e.FromBareJID);
                        if (Item is null || Item.State == SubscriptionState.None || Item.State == SubscriptionState.From)
                        {
                            Client.RequestPresenceSubscription(e.FromBareJID);
                        }

                        Client.SetPresence(Availability.Chat);
                    };

                    Client.OnPresenceUnsubscribe += (sender, e) =>
                    {
                        e.Accept();
                    };

                    Client.OnRosterItemUpdated += (sender, e) =>
                    {
                        if (e.State == SubscriptionState.None && e.PendingSubscription != PendingSubscription.Subscribe)
                        {
                            Client.RemoveRosterItem(e.BareJid);
                        }
                    };

                    bool SwitchOn = false;

                    SensorServer SensorServer = new SensorServer(Client, ProvisioningClient, false);
                    SensorServer.OnExecuteReadoutRequest += (Sender, Request) =>
                    {
                        DateTime Now = DateTime.Now;

                        Log.Informational("Readout requested", string.Empty, Request.Actor);

                        Request.ReportFields(true, new BooleanField(ThingReference.Empty, Now, "Lamp", SwitchOn, FieldType.Momentary, FieldQoS.AutomaticReadout));
                    };

                    ControlServer ControlServer = new ControlServer(Client,
                                                                    new BooleanControlParameter("Lamp", "Control", "Lamp switch on.", "If checked, lamp is turned on.",
                                                                                                (Node) => SwitchOn,
                                                                                                (Node, Value) =>
                    {
                        SwitchOn = Value;
                        Log.Informational(Environment.NewLine + Environment.NewLine + "Lamp turned " + (SwitchOn ? "ON" : "OFF") + Environment.NewLine + Environment.NewLine);
                    }));

                    BobClient  BobClient  = new BobClient(Client, Path.Combine(Path.GetTempPath(), "BitsOfBinary"));
                    ChatServer ChatServer = new ChatServer(Client, BobClient, SensorServer, ControlServer, ProvisioningClient);

                    InteroperabilityServer InteroperabilityServer = new InteroperabilityServer(Client);
                    InteroperabilityServer.OnGetInterfaces += (sender, e) =>
                    {
                        e.Add("XMPP.IoT.Actuator.Lamp");
                    };

                    Client.Connect();

                    while (true)
                    {
                        Thread.Sleep(1000);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.Out.WriteLine(ex.Message);
            }
            finally
            {
                Log.Terminate();
            }
        }
Ejemplo n.º 30
0
        public static void Main(string[] args)
        {
            try
            {
                Console.ForegroundColor = ConsoleColor.White;

                Console.Out.WriteLine("Welcome to the Mock Temperature sensor application.");
                Console.Out.WriteLine(new string('-', 79));
                Console.Out.WriteLine("This application will simulate an outside temperature sensor.");
                Console.Out.WriteLine("Values will be published over XMPP using the interface defined in the IEEE XMPP IoT extensions.");
                Console.Out.WriteLine("You can also chat with the sensor.");

                Log.Register(new ConsoleEventSink());
                Log.RegisterExceptionToUnnest(typeof(System.Runtime.InteropServices.ExternalException));
                Log.RegisterExceptionToUnnest(typeof(System.Security.Authentication.AuthenticationException));

                xmppConfiguration = SimpleXmppConfiguration.GetConfigUsingSimpleConsoleDialog("xmpp.config",
                                                                                              Guid.NewGuid().ToString().Replace("-", string.Empty), // Default user name.
                                                                                              Guid.NewGuid().ToString().Replace("-", string.Empty), // Default password.
                                                                                              FormSignatureKey, FormSignatureSecret, typeof(Program).Assembly);

                using (XmppClient Client = xmppConfiguration.GetClient("en", typeof(Program).Assembly, false))
                {
                    Client.AllowRegistration(FormSignatureKey, FormSignatureSecret);

                    if (xmppConfiguration.Sniffer)
                    {
                        Client.Add(new ConsoleOutSniffer(BinaryPresentationMethod.ByteCount, LineEnding.PadWithSpaces));
                    }

                    if (!string.IsNullOrEmpty(xmppConfiguration.Events))
                    {
                        Log.Register(new XmppEventSink("XMPP Event Sink", Client, xmppConfiguration.Events, false));
                    }

                    if (!string.IsNullOrEmpty(xmppConfiguration.ThingRegistry))
                    {
                        thingRegistryClient = new ThingRegistryClient(Client, xmppConfiguration.ThingRegistry);

                        thingRegistryClient.Claimed += (sender, e) =>
                        {
                            ownerJid = e.JID;
                            Log.Informational("Thing has been claimed.", ownerJid, new KeyValuePair <string, object>("Public", e.IsPublic));
                        };

                        thingRegistryClient.Disowned += (sender, e) =>
                        {
                            Log.Informational("Thing has been disowned.", ownerJid);
                            ownerJid = string.Empty;
                            Register();
                        };

                        thingRegistryClient.Removed += (sender, e) =>
                        {
                            Log.Informational("Thing has been removed from the public registry.", ownerJid);
                        };
                    }

                    ProvisioningClient ProvisioningClient = null;
                    if (!string.IsNullOrEmpty(xmppConfiguration.Provisioning))
                    {
                        ProvisioningClient = new ProvisioningClient(Client, xmppConfiguration.Provisioning);
                    }

                    Timer ConnectionTimer = new Timer((P) =>
                    {
                        if (Client.State == XmppState.Offline || Client.State == XmppState.Error || Client.State == XmppState.Authenticating)
                        {
                            try
                            {
                                Client.Reconnect();
                            }
                            catch (Exception ex)
                            {
                                Log.Critical(ex);
                            }
                        }
                    }, null, 60000, 60000);

                    bool Connected = false;
                    bool ImmediateReconnect;

                    Client.OnStateChanged += (sender, NewState) =>
                    {
                        switch (NewState)
                        {
                        case XmppState.Connected:
                            Connected = true;

                            if (!registered && thingRegistryClient != null)
                            {
                                Register();
                            }
                            break;

                        case XmppState.Offline:
                            ImmediateReconnect = Connected;
                            Connected          = false;

                            if (ImmediateReconnect)
                            {
                                Client.Reconnect();
                            }
                            break;
                        }
                    };

                    Client.OnPresenceSubscribe += (sender, e) =>
                    {
                        e.Accept();                             // TODO: Provisioning

                        RosterItem Item = Client.GetRosterItem(e.FromBareJID);
                        if (Item == null || Item.State == SubscriptionState.None || Item.State == SubscriptionState.From)
                        {
                            Client.RequestPresenceSubscription(e.FromBareJID);
                        }

                        Client.SetPresence(Availability.Chat);
                    };

                    Client.OnPresenceUnsubscribe += (sender, e) =>
                    {
                        e.Accept();
                    };

                    Client.OnRosterItemUpdated += (sender, e) =>
                    {
                        if (e.State == SubscriptionState.None && e.PendingSubscription != PendingSubscription.Subscribe)
                        {
                            Client.RemoveRosterItem(e.BareJid);
                        }
                    };

                    LinkedList <DayHistoryRecord>    DayHistoricalValues    = new LinkedList <DayHistoryRecord>();
                    LinkedList <MinuteHistoryRecord> MinuteHistoricalValues = new LinkedList <MinuteHistoryRecord>();
                    DateTime SampleTime  = DateTime.Now;
                    DateTime PeriodStart = SampleTime.Date;
                    DateTime Now;
                    DateTime MinTime            = SampleTime;
                    DateTime MaxTime            = SampleTime;
                    double   CurrentTemperature = ReadTemp();
                    double   MinTemp            = CurrentTemperature;
                    double   MaxTemp            = CurrentTemperature;
                    double   SumTemp            = CurrentTemperature;
                    int      NrTemp             = 1;
                    int      NrDayRecords       = 0;
                    int      NrMinuteRecords    = 0;
                    object   SampleSynch        = new object();

                    SensorServer SensorServer = new SensorServer(Client, ProvisioningClient, true);
                    SensorServer.OnExecuteReadoutRequest += (Sender, Request) =>
                    {
                        Log.Informational("Readout requested", string.Empty, Request.Actor);

                        List <Field> Fields          = new List <Field>();
                        bool         IncludeTemp     = Request.IsIncluded("Temperature");
                        bool         IncludeTempMin  = Request.IsIncluded("Temperature, Min");
                        bool         IncludeTempMax  = Request.IsIncluded("Temperature, Max");
                        bool         IncludeTempAvg  = Request.IsIncluded("Temperature, Average");
                        bool         IncludePeak     = Request.IsIncluded(FieldType.Peak);
                        bool         IncludeComputed = Request.IsIncluded(FieldType.Computed);

                        lock (SampleSynch)
                        {
                            if (IncludeTemp && Request.IsIncluded(FieldType.Momentary))
                            {
                                Fields.Add(new QuantityField(ThingReference.Empty, SampleTime, "Temperature", CurrentTemperature, 1, "°C",
                                                             FieldType.Momentary, FieldQoS.AutomaticReadout));
                            }

                            if (IncludePeak)
                            {
                                if (IncludeTempMin)
                                {
                                    Fields.Add(new QuantityField(ThingReference.Empty, MinTime, "Temperature, Min", MinTemp, 1, "°C",
                                                                 FieldType.Peak, FieldQoS.AutomaticReadout));
                                }

                                if (IncludeTempMax)
                                {
                                    Fields.Add(new QuantityField(ThingReference.Empty, MaxTime, "Temperature, Max", MaxTemp, 1, "°C",
                                                                 FieldType.Peak, FieldQoS.AutomaticReadout));
                                }
                            }

                            if (IncludeTempAvg && IncludeComputed)
                            {
                                Fields.Add(new QuantityField(ThingReference.Empty, SampleTime, "Temperature, Average", SumTemp / NrTemp, 2, "°C",
                                                             FieldType.Computed, FieldQoS.AutomaticReadout));
                            }

                            if (Request.IsIncluded(FieldType.Historical))
                            {
                                foreach (DayHistoryRecord Rec in DayHistoricalValues)
                                {
                                    if (!Request.IsIncluded(Rec.PeriodStart))
                                    {
                                        continue;
                                    }

                                    if (Fields.Count >= 100)
                                    {
                                        Request.ReportFields(false, Fields);
                                        Fields.Clear();
                                    }

                                    if (IncludePeak)
                                    {
                                        if (IncludeTempMin)
                                        {
                                            Fields.Add(new QuantityField(ThingReference.Empty, Rec.PeriodStart, "Temperature, Min", Rec.MinTemperature, 1, "°C",
                                                                         FieldType.Peak | FieldType.Historical, FieldQoS.AutomaticReadout));
                                        }

                                        if (IncludeTempMax)
                                        {
                                            Fields.Add(new QuantityField(ThingReference.Empty, Rec.PeriodStart, "Temperature, Max", Rec.MaxTemperature, 1, "°C",
                                                                         FieldType.Peak | FieldType.Historical, FieldQoS.AutomaticReadout));
                                        }
                                    }

                                    if (IncludeTempAvg && IncludeComputed)
                                    {
                                        Fields.Add(new QuantityField(ThingReference.Empty, Rec.PeriodStart, "Temperature, Average", Rec.AverageTemperature, 1, "°C",
                                                                     FieldType.Computed | FieldType.Historical, FieldQoS.AutomaticReadout));
                                    }
                                }

                                foreach (MinuteHistoryRecord Rec in MinuteHistoricalValues)
                                {
                                    if (!Request.IsIncluded(Rec.Timestamp))
                                    {
                                        continue;
                                    }

                                    if (IncludeTemp)
                                    {
                                        if (Fields.Count >= 100)
                                        {
                                            Request.ReportFields(false, Fields);
                                            Fields.Clear();
                                        }

                                        Fields.Add(new QuantityField(ThingReference.Empty, Rec.Timestamp, "Temperature", Rec.Temperature, 1, "°C",
                                                                     FieldType.Historical, FieldQoS.AutomaticReadout));
                                    }
                                }
                            }
                        }

                        Request.ReportFields(true, Fields);
                    };

                    Timer SampleTimer = new Timer((P) =>
                    {
                        lock (SampleSynch)
                        {
                            Now = DateTime.Now;

                            if (Now.Date != PeriodStart.Date)
                            {
                                DayHistoryRecord Rec = new DayHistoryRecord(PeriodStart.Date, PeriodStart.Date.AddDays(1).AddMilliseconds(-1),
                                                                            MinTemp, MaxTemp, SumTemp / NrTemp);

                                DayHistoricalValues.AddFirst(Rec);

                                if (NrDayRecords < MaxRecordsPerPeriod)
                                {
                                    NrDayRecords++;
                                }
                                else
                                {
                                    DayHistoricalValues.RemoveLast();
                                }

                                // TODO: Persistence

                                PeriodStart = Now.Date;
                                SumTemp     = 0;
                                NrTemp      = 0;
                            }

                            CurrentTemperature = ReadTemp();

                            if (Now.Minute != SampleTime.Minute)
                            {
                                MinuteHistoryRecord Rec = new MinuteHistoryRecord(Now, CurrentTemperature);

                                MinuteHistoricalValues.AddFirst(Rec);

                                if (NrMinuteRecords < MaxRecordsPerPeriod)
                                {
                                    NrMinuteRecords++;
                                }
                                else
                                {
                                    MinuteHistoricalValues.RemoveLast();
                                }

                                // TODO: Persistence
                            }

                            SampleTime = Now;

                            if (CurrentTemperature < MinTemp)
                            {
                                MinTemp = CurrentTemperature;
                                MinTime = SampleTime;
                            }

                            if (CurrentTemperature > MaxTemp)
                            {
                                MaxTemp = CurrentTemperature;
                                MaxTime = SampleTime;
                            }

                            SumTemp += CurrentTemperature;
                            NrTemp++;
                        }

                        if (SensorServer.HasSubscriptions(ThingReference.Empty))
                        {
                            SensorServer.NewMomentaryValues(new QuantityField(ThingReference.Empty, SampleTime, "Temperature",
                                                                              CurrentTemperature, 1, "°C", FieldType.Momentary, FieldQoS.AutomaticReadout));
                        }
                    }, null, 1000 - PeriodStart.Millisecond, 1000);

                    BobClient  BobClient  = new BobClient(Client, Path.Combine(Path.GetTempPath(), "BitsOfBinary"));
                    ChatServer ChatServer = new ChatServer(Client, BobClient, SensorServer);

                    InteroperabilityServer InteroperabilityServer = new InteroperabilityServer(Client);
                    InteroperabilityServer.OnGetInterfaces += (sender, e) =>
                    {
                        e.Add("XMPP.IoT.Sensor.Temperature",
                              "XMPP.IoT.Sensor.Temperature.History",
                              "XMPP.IoT.Sensor.Temperature.Average",
                              "XMPP.IoT.Sensor.Temperature.Average.History",
                              "XMPP.IoT.Sensor.Temperature.Min",
                              "XMPP.IoT.Sensor.Temperature.Min.History",
                              "XMPP.IoT.Sensor.Temperature.Max",
                              "XMPP.IoT.Sensor.Temperature.Max.History");
                    };

                    Client.Connect();

                    while (true)
                    {
                        Thread.Sleep(1000);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.Out.WriteLine(ex.Message);
            }
            finally
            {
                Log.Terminate();
            }
        }