0

我正在尝试以编程方式更改 IoT Edge 模块的“状态”(运行或停止)和“restartPolicy”,以便停止模块,而无需为设备重新创建整个部署。

我已经看到 Edge Agent 的 Twin 在他的 desiredProperties 中有模块的部署信息,我尝试使用以下代码(它使用 Microsoft.Azure.Devices NuGet 包)来修补它

   public async Task ShutdownModule(string deviceId, string moduleId)
    {
        var twinEdgeAgent = await _registryManager.GetTwinAsync(deviceId, "$edgeAgent");

        var patchJson = $"{{\"properties\":{{\"desired\":{{\"modules\":{{\"{moduleId}\":{{\"status\": \"stopped\", \"restartPolicy\": \"never\"}}}}}}}}}}";
        await _registryManager.UpdateTwinAsync(deviceId, "$edgeAgent", patchJson, twinEdgeAgent.ETag);
    } 

不幸的是,这不起作用,我收到一条UnauthorizedException消息“错误代码:SystemModuleModifyUnauthorizedAccess;未经授权修改保留模块。”。看起来我无法更改边缘代理模块的所需属性。

有没有办法更改此属性而无需重新创建整个部署 JSON,或者至少有办法获取此部署 JSON,以便我可以修改需要更改的属性?

4

1 回答 1

1

我首先通过 EdgeAgent、EdgeHub 和所有模块孪生重构现有部署,从而通过部署 API 设法做到了这一点。

这是我最终编写的方法的简历:

var modulesContent = new Dictionary<string, IDictionary<string, object>>();

var twinEdgeAgent = await _registryManager.GetTwinAsync(deviceId, "$edgeAgent");
var agentModules = twinEdgeAgent.Properties.Desired[ModulesJsonPropertyName];

agentModules[myModuleId]["status"] = "stopped";
agentModules[myModuleId]["restartPolicy"] = "never";

var desiredProperties = twinEdgeAgent.GetDesiredPropertiesDictionary();

modulesContent.Add("$edgeAgent", edgeHubDesiredProperties);

var twinEdgeHub = await _registryManager.GetTwinAsync(deviceId, "$edgeHub");
var edgeHubDesiredProperties = twinEdgeHub.GetDesiredPropertiesDictionary();
modulesContent.Add("$edgeHub", edgeHubDesiredProperties);

// foreach modules contained in agentModules also add 
// the module's twin desired properties in the dictionary (not shown for brevity)

await _registryManager.ApplyConfigurationContentOnDeviceAsync(
            deviceId,
            new ConfigurationContent { ModulesContent = modulesContent });

internal static class TwinExtensions
{
    private const string DesiredPropertiesAttribute = "properties.desired";

    public static IDictionary<string, object> GetDesiredPropertiesDictionary(this Twin twin)
    {
        if (twin == null)
        {
            throw new ArgumentNullException(nameof(twin));
        }

        var twinDesiredProperties = twin.Properties.Desired;
        twinDesiredProperties.ClearMetadata();

        var twinDesiredPropertiesDictionary =
            JsonConvert.DeserializeObject<Dictionary<string, object>>(twinDesiredProperties.ToJson());

        return new Dictionary<string, object> {{DesiredPropertiesAttribute, twinDesiredPropertiesDictionary}};
    }
}

也许有更好/更简单的解决方案,但我们正在使用类似的方法来自动升级模块的运行时映像和其他一些事情,因此我能够在同一代码中重新组合所有这些更改。

如果有办法直接获取部署JSON,那将大大简化,但我没有找到。

于 2020-11-26T08:45:43.570 回答