private async Task ProvideLinkConfigurationAsync(IOnPremiseConnectionContext onPremiseConnectionContext) { try { var config = _linkRepository.GetLinkConfiguration(onPremiseConnectionContext.LinkId); config.ApplyDefaults(_configuration); var requestId = Guid.NewGuid().ToString(); _logger?.Debug("Sending configuration to OPC. connection-id={ConnectionId}, link-id={LinkId}, connector-version={ConnectorVersion}, link-configuration={@LinkConfiguration}, request-id={RequestId}", onPremiseConnectionContext.ConnectionId, onPremiseConnectionContext.LinkId, onPremiseConnectionContext.ConnectorVersion, config, requestId); var request = new OnPremiseConnectorRequest() { HttpMethod = "CONFIG", Url = String.Empty, RequestStarted = DateTime.UtcNow, OriginId = OriginId, RequestId = requestId, AcknowledgmentMode = AcknowledgmentMode.Auto, Body = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(config)), }; // configs, like heartbeats, do not go through the message dispatcher but directly to the connection await onPremiseConnectionContext.RequestAction(request, CancellationToken.None).ConfigureAwait(false); } catch (Exception ex) { _logger?.Error(ex, "An error happened while sending the link config to the connected OPC."); } }
private async Task SendHeartbeatAsync(IOnPremiseConnectionContext connectionContext, CancellationToken token) { if (connectionContext == null) { throw new ArgumentNullException(nameof(connectionContext)); } if (connectionContext.NextHeartbeat > DateTime.UtcNow) { return; } connectionContext.NextHeartbeat = DateTime.UtcNow.Add(_heartbeatInterval); try { _logger?.Verbose("Sending {PingMethod}. connection-id={ConnectionId}", connectionContext.SupportsHeartbeat ? "Heartbeat" : "Ping (as heartbeat)", connectionContext.ConnectionId); var requestId = Guid.NewGuid().ToString(); var request = new OnPremiseConnectorRequest() { HttpMethod = connectionContext.SupportsHeartbeat ? "HEARTBEAT" : "PING", Url = String.Empty, RequestStarted = DateTime.UtcNow, OriginId = _backendCommunication.OriginId, RequestId = requestId, AcknowledgmentMode = AcknowledgmentMode.Auto, HttpHeaders = connectionContext.SupportsConfiguration ? null : new Dictionary <string, string> { ["X-TTRELAY-HEARTBEATINTERVAL"] = _heartbeatInterval.TotalSeconds.ToString(CultureInfo.InvariantCulture) }, }; // wait for the response of the Heartbeat / Ping var task = _backendCommunication.GetResponseAsync(requestId, _configuration.ActiveConnectionTimeout); // heartbeats do NOT go through the message dispatcher as we want to heartbeat the connections directly await connectionContext.RequestAction(request, token).ConfigureAwait(false); var response = await task.ConfigureAwait(false); if (response != null) { await _backendCommunication.RenewLastActivityAsync(connectionContext.ConnectionId).ConfigureAwait(false); } } catch (Exception ex) { _logger?.Error(ex, "Error during sending heartbeat to a client. link-id={LinkId}, connection-id={ConnectionId}, connector-version={ConnectorVersion}", connectionContext.LinkId, connectionContext.ConnectionId, connectionContext.ConnectorVersion); } }
public async Task RegisterOnPremiseAsync(IOnPremiseConnectionContext onPremiseConnectionContext) { CheckDisposed(); _logger?.Debug("Registering link. link-id={LinkId}, connection-id={ConnectionId}, user-name={UserName}, role={Role} connector-version={ConnectorVersion}, connector-assembly-version={ConnectorAssemblyVersion}", onPremiseConnectionContext.LinkId, onPremiseConnectionContext.ConnectionId, onPremiseConnectionContext.UserName, onPremiseConnectionContext.Role, onPremiseConnectionContext.ConnectorVersion, onPremiseConnectionContext.ConnectorAssemblyVersion); await _linkRepository.AddOrRenewActiveConnectionAsync(onPremiseConnectionContext.LinkId, OriginId, onPremiseConnectionContext.ConnectionId, onPremiseConnectionContext.ConnectorVersion, onPremiseConnectionContext.ConnectorAssemblyVersion).ConfigureAwait(false); lock (_requestSubscriptions) { if (!_requestSubscriptions.ContainsKey(onPremiseConnectionContext.ConnectionId)) { _requestSubscriptions[onPremiseConnectionContext.ConnectionId] = _messageDispatcher.OnRequestReceived(onPremiseConnectionContext.LinkId, onPremiseConnectionContext.ConnectionId, !onPremiseConnectionContext.SupportsAck) .Subscribe(request => onPremiseConnectionContext.RequestAction(request, _cancellationToken)); onPremiseConnectionContext.IsActive = true; } } _connectionContexts.TryAdd(onPremiseConnectionContext.ConnectionId, onPremiseConnectionContext); if (onPremiseConnectionContext.SupportsConfiguration) { await ProvideLinkConfigurationAsync(onPremiseConnectionContext).ConfigureAwait(false); } }