/// <summary> /// Create patch twin model to upload /// </summary> /// <param name="registration"></param> /// <param name="update"></param> public static DeviceTwinModel Patch(this ApplicationRegistration registration, ApplicationRegistration update) { var twin = BaseRegistrationEx.PatchBase(registration, update); // Tags if (update?.ApplicationType != null && update?.ApplicationType != registration?.ApplicationType) { twin.Tags.Add(nameof(ApplicationRegistration.ApplicationType), JToken.FromObject(update.ApplicationType)); twin.Tags.Add(nameof(ApplicationType.Server), update.ApplicationType != ApplicationType.Client); twin.Tags.Add(nameof(ApplicationType.Client), update.ApplicationType != ApplicationType.Server && update.ApplicationType != ApplicationType.DiscoveryServer); twin.Tags.Add(nameof(ApplicationType.DiscoveryServer), update.ApplicationType == ApplicationType.DiscoveryServer); } if ((update?.ApplicationState ?? ApplicationState.New) != registration?.ApplicationState) { twin.Tags.Add(nameof(ApplicationRegistration.ApplicationState), JToken.FromObject( update?.ApplicationState ?? ApplicationState.New)); } if (update?.ApplicationUri != registration?.ApplicationUri) { twin.Tags.Add(nameof(ApplicationRegistration.ApplicationUri), update?.ApplicationUri); twin.Tags.Add(nameof(ApplicationRegistration.ApplicationUriLC), update?.ApplicationUriLC); } if (update?.RecordId != registration?.RecordId) { twin.Tags.Add(nameof(ApplicationRegistration.RecordId), update?.RecordId); } if (update?.ApplicationName != registration?.ApplicationName) { twin.Tags.Add(nameof(ApplicationRegistration.ApplicationName), update?.ApplicationName); } if (update?.Locale != registration?.Locale) { twin.Tags.Add(nameof(ApplicationRegistration.Locale), update?.Locale); } if (update?.DiscoveryProfileUri != registration?.DiscoveryProfileUri) { twin.Tags.Add(nameof(ApplicationRegistration.DiscoveryProfileUri), update?.DiscoveryProfileUri); } if (update?.GatewayServerUri != registration?.GatewayServerUri) { twin.Tags.Add(nameof(ApplicationRegistration.GatewayServerUri), update?.GatewayServerUri); } if (update?.ProductUri != registration?.ProductUri) { twin.Tags.Add(nameof(ApplicationRegistration.ProductUri), update?.ProductUri); } var urlUpdate = update?.DiscoveryUrls.DecodeAsList().SequenceEqualsSafe( registration?.DiscoveryUrls?.DecodeAsList()); if (!(urlUpdate ?? true)) { twin.Tags.Add(nameof(ApplicationRegistration.DiscoveryUrls), update?.DiscoveryUrls == null ? null : JToken.FromObject(update.DiscoveryUrls)); } var capsUpdate = update?.Capabilities.DecodeAsSet().SetEqualsSafe( registration?.Capabilities?.DecodeAsSet()); if (!(capsUpdate ?? true)) { twin.Tags.Add(nameof(ApplicationRegistration.Capabilities), update?.Capabilities == null ? null : JToken.FromObject(update.Capabilities)); } var namesUpdate = update?.LocalizedNames.DictionaryEqualsSafe( registration?.LocalizedNames); if (!(namesUpdate ?? true)) { twin.Tags.Add(nameof(ApplicationRegistration.LocalizedNames), update?.LocalizedNames == null ? null : JToken.FromObject(update.LocalizedNames)); } var hostsUpdate = update?.HostAddresses.DecodeAsList().SequenceEqualsSafe( registration?.HostAddresses?.DecodeAsList()); if (!(hostsUpdate ?? true)) { twin.Tags.Add(nameof(ApplicationRegistration.HostAddresses), update?.HostAddresses == null ? null : JToken.FromObject(update.HostAddresses)); } if (update?.ApproveAuthorityId != registration?.ApproveAuthorityId) { twin.Tags.Add(nameof(ApplicationRegistration.ApproveAuthorityId), update?.ApproveAuthorityId); } if (update?.ApproveTime != registration?.ApproveTime) { twin.Tags.Add(nameof(ApplicationRegistration.ApproveTime), update?.ApproveTime); } if (update?.CreateAuthorityId != registration?.CreateAuthorityId) { twin.Tags.Add(nameof(ApplicationRegistration.CreateAuthorityId), update?.CreateAuthorityId); } if (update?.CreateTime != registration?.CreateTime) { twin.Tags.Add(nameof(ApplicationRegistration.CreateTime), update?.CreateTime); } if (update?.UpdateAuthorityId != registration?.UpdateAuthorityId) { twin.Tags.Add(nameof(ApplicationRegistration.UpdateAuthorityId), update?.UpdateAuthorityId); } if (update?.UpdateTime != registration?.UpdateTime) { twin.Tags.Add(nameof(ApplicationRegistration.UpdateTime), update?.UpdateTime); } // Recalculate identity var applicationUri = registration?.ApplicationUri; if (update?.ApplicationUri != null) { applicationUri = update?.ApplicationUri; } if (applicationUri == null) { throw new ArgumentException(nameof(ApplicationRegistration.ApplicationUri)); } var siteOrSupervisorId = registration?.SiteId ?? registration?.SupervisorId; if (update?.SupervisorId != null || update?.SiteId != null) { siteOrSupervisorId = update?.SiteId ?? update?.SupervisorId; } var applicationType = registration?.ApplicationType; if (update?.ApplicationType != null) { applicationType = update?.ApplicationType; } var applicationId = ApplicationInfoModelEx.CreateApplicationId( siteOrSupervisorId, applicationUri, applicationType); twin.Tags.Remove(nameof(ApplicationId)); twin.Tags.Add(nameof(ApplicationId), applicationId); twin.Id = applicationId; if (registration?.DeviceId != twin.Id) { twin.Etag = null; // Force creation of new identity } return(twin); }
/// <summary> /// Create patch twin model to upload /// </summary> /// <param name="existing"></param> /// <param name="update"></param> public static DeviceTwinModel Patch(this EndpointRegistration existing, EndpointRegistration update) { var twin = BaseRegistrationEx.PatchBase(existing, update); // Tags if (update?.EndpointRegistrationUrl != null && update.EndpointRegistrationUrl != existing?.EndpointRegistrationUrl) { twin.Tags.Add(nameof(EndpointRegistration.EndpointUrlLC), update.EndpointUrlLC); twin.Tags.Add(nameof(EndpointRegistration.EndpointRegistrationUrl), update.EndpointRegistrationUrl); } if (update?.SecurityLevel != existing?.SecurityLevel) { twin.Tags.Add(nameof(EndpointRegistration.SecurityLevel), update?.SecurityLevel == null ? null : JToken.FromObject(update?.SecurityLevel)); } if (update?.Activated != null && update.Activated != existing?.Activated) { twin.Tags.Add(nameof(EndpointRegistration.Activated), update?.Activated); } var methodEqual = update?.AuthenticationMethods.DecodeAsList().SetEqualsSafe( existing?.AuthenticationMethods?.DecodeAsList(), JToken.DeepEquals); if (!(methodEqual ?? true)) { twin.Tags.Add(nameof(EndpointRegistration.AuthenticationMethods), update?.AuthenticationMethods == null ? null : JToken.FromObject(update.AuthenticationMethods, new JsonSerializer { NullValueHandling = NullValueHandling.Ignore })); } // Endpoint Property if (update?.EndpointUrl != null && update.EndpointUrl != existing?.EndpointUrl) { twin.Properties.Desired.Add(nameof(EndpointRegistration.EndpointUrl), update.EndpointUrl); } var urlsEqual = update?.AlternativeUrls.DecodeAsList().ToHashSetSafe().SetEqualsSafe( existing?.AlternativeUrls?.DecodeAsList()); if (!(urlsEqual ?? true)) { twin.Properties.Desired.Add(nameof(EndpointRegistration.AlternativeUrls), update?.AlternativeUrls == null ? null : JToken.FromObject(update.AlternativeUrls)); } if (update?.SecurityMode != null && update.SecurityMode != existing?.SecurityMode) { twin.Properties.Desired.Add(nameof(EndpointRegistration.SecurityMode), JToken.FromObject(update.SecurityMode)); } if (update?.SecurityPolicy != null && update?.SecurityPolicy != existing?.SecurityPolicy) { twin.Properties.Desired.Add(nameof(EndpointRegistration.SecurityPolicy), update.SecurityPolicy); } if (update?.CredentialType != existing?.CredentialType) { twin.Properties.Desired.Add(nameof(EndpointRegistration.CredentialType), update?.CredentialType == null ? null : JToken.FromObject(update?.CredentialType)); } if (!JToken.DeepEquals(update?.Credential, existing?.Credential)) { twin.Properties.Desired.Add(nameof(EndpointRegistration.Credential), update?.Credential); } var certEqual = update?.Certificate.DecodeAsByteArray().SequenceEqualsSafe( existing?.Certificate.DecodeAsByteArray()); if (update?.Certificate != null && !(certEqual ?? true)) { twin.Properties.Desired.Add(nameof(EndpointRegistration.Certificate), update?.Certificate == null ? null : JToken.FromObject(update.Certificate)); } // Recalculate identity var reportedEndpointUrl = existing?.EndpointRegistrationUrl; if (update?.EndpointRegistrationUrl != null) { reportedEndpointUrl = update.EndpointRegistrationUrl; } if (reportedEndpointUrl == null) { throw new ArgumentException(nameof(EndpointRegistration.EndpointUrl)); } var applicationId = existing?.ApplicationId; if (update?.ApplicationId != null) { applicationId = update.ApplicationId; } if (applicationId == null) { throw new ArgumentException(nameof(EndpointRegistration.ApplicationId)); } var securityMode = existing?.SecurityMode; if (update?.SecurityMode != null) { securityMode = update.SecurityMode; } var securityPolicy = existing?.SecurityPolicy; if (update?.SecurityPolicy != null) { securityPolicy = update.SecurityPolicy; } twin.Id = EndpointInfoModelEx.CreateEndpointId( applicationId, reportedEndpointUrl, securityMode, securityPolicy); if (existing?.DeviceId != twin.Id) { twin.Etag = null; // Force creation of new identity } return(twin); }