×

Azure支持的AI冷冻机监视器

消耗积分:0 | 格式:zip | 大小:0.22 MB | 2022-11-22

莫联雪

分享资料个

描述

Azure 支持的 AI Freezer Monitor 是基于制造商硬件的 IoT 监视器,它使用机器学习 (ML) 来提供潜在设备故障的早期警告。本指南涵盖了构建设备、收集训练数据、设置电子邮件警报、训练自定义自动编码器机器学习模型以及将模型部署到 ESP32 开发板。

该项目旨在为低温科学冷冻机(-60 C)提供功能,目标是减少灾难性故障和保持备用冷冻机全时运行的需要。但是,请注意,该项目主要用于演示和教育目的,尚未经过广泛的测试。

这个项目大约需要一个小时才能完全完成。

Azure 设置

下面有关于此示例的成本和架构的详细信息,但如果您只想让它立即运行,这里是开始的步骤。

部署资源

1. 登录您的 Azure 帐户

2. 单击上面的Deploy to Azure链接,为该项目预配所有资源

作为替代方案,您可以使用Azure 门户中的部署自定义模板服务部署模板,并在编辑器中选择构建您自己的模板并从该存储库上传azuredeploy.json文件。

3.为项目新建资源组

4.为您的资源选择一个区域,选择一个靠近您以获得最佳性能的区域

注意:某些资源并非在所有地区都可用

5. 为所有资源提供唯一名称

注意:某些资源需要全局唯一名称

设置 Azure 函数

1. 部署完成后,使用左侧导航打开新功能应用程序

2.从左侧导航中选择功能

3.选择左上角的添加

4. 在窗口中选择以下选项:

开发环境:在门户中开发

模板:定时器触发器

新功能:dataSaver

您可以保留任何其他设置
poYBAGN6f9aATjuVAADI5xpT5II461.png
 

5. 创建函数后,从左侧导航中选择Code + Test

poYBAGN6f9iACEpwAABkTg_X3HI619.png
 

6. 在run.csx中,将所有现有代码替换为:

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

#r "Newtonsoft.Json"

using System;
using Newtonsoft.Json;

public static void Run(string myIoTHubMessage, ICollector outputTable, ILogger log)
{
    log.LogInformation($"C# IoT Hub trigger function processed a message: {myIoTHubMessage}");
    dynamic input = JsonConvert.DeserializeObject(myIoTHubMessage);
    Guid guid = Guid.NewGuid();
    log.LogInformation($"Message guid: {guid}");
    outputTable.Add(
            new outTable() { 
                PartitionKey = "test", 
                RowKey = guid.ToString(), 
                deviceId = input.deviceId.ToString(),
                temperature = input.Temperature}
            );
}

public class outTable
{
    public string PartitionKey { get; set; }
    public string RowKey { get; set; }
    public string deviceId { get; set; }
    public float temperature {get; set;}

}

导航到function.json并将所有现有代码替换为:

{
    "bindings": [
      {
        "type": "eventHubTrigger",
        "name": "myIoTHubMessage",
        "direction": "in",
        "eventHubName": "samples-workitems",
        "connection": "ai-freezer-hub_events_IOTHUB",
        "consumerGroup": "$Default"
      },
      {
        "name": "outputTable",
        "direction": "out",
        "type": "table",
        "tableName": "tempTable",
        "connection": "AzureWebJobsStorage"
      }
    ]
  }

8. 使用以下选项对异常检测器功能重复这些步骤:

开发环境:在门户中开发

模板:IoT 中心(事件中心)

新功能:异常检测器

您可以保留任何其他设置

运行.csx:

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

#r "Microsoft.WindowsAzure.Storage"
#r "Newtonsoft.Json"
#r "System.Text.Json"

using Microsoft.Extensions.Logging;
using Microsoft.WindowsAzure.Storage.Table;
using System.Threading.Tasks;
using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;

public static readonly string emailAlertUrl = Environment.GetEnvironmentVariable("EMAIL_ALERT_URL");
public static readonly HttpClient client1 = new HttpClient();

// Anomaly detection API secrets
public static readonly string subscriptionKey = Environment.GetEnvironmentVariable("ANOMALY_DETECTOR_KEY");
public static readonly string endpoint = Environment.GetEnvironmentVariable("ANOMALY_DETECTOR_ENDPOINT");

const string latestPointDetectionUrl = "/anomalydetector/v1.0/timeseries/last/detect";
public const string batchDetectionUrl = "/anomalydetector/v1.0/timeseries/entire/detect";

public static DateTimeOffset targetTime;

public static async Task Run(TimerInfo myTimer, CloudTable inputTable, ILogger log)
{
    log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
    
    // Get traget time from when to start reading the data
    targetTime = DateTime.UtcNow;
    targetTime = targetTime.AddHours(-6);
    log.LogInformation($"Target start time is: {targetTime}");

    TableQuery rangeQuery = new TableQuery().Where(
        TableQuery.GenerateFilterConditionForDate("Timestamp", QueryComparisons.GreaterThan, targetTime));

    // Execute the query and loop through the results
    List data = new List();
    foreach (DataPoint entity in 
    await inputTable.ExecuteQuerySegmentedAsync(rangeQuery, null))
    {
        data.Add(new DataPoint() {Timestamp = entity.Timestamp, temperature = entity.temperature});
    }

    // Sort data by Timestamp
    data.Sort((dp1, dp2) => DateTimeOffset.Compare(dp1.Timestamp, dp2.Timestamp));
    
    List formatedData = new List();
    data.ForEach( delegate(DataPoint point)
    {
        formatedData.Add(new FormatedData() { timestamp = point.Timestamp.ToString("yyyy-MM-ddTHH:mm:00Z"), value = point.temperature});
    });

    var options = new JsonSerializerOptions
    {
        IgnoreNullValues = true,
        // PropertyNamingPolicy = new LowerCaseNamingPolicy()
    };

    List jsonFormat = new List();
    jsonFormat.Add(new JsonFormat() {series = formatedData, granularity = "minutely", customInterval = 1, period = 90, sensitivity = 85});
    string dataToSend = JsonSerializer.Serialize(jsonFormat, options);

    // Call anomaly detection API
    var anomalies = detectAnomaliesBatch(dataToSend, log);

    if (anomalies != null){
        var json = JsonSerializer.Serialize(anomalies);
        var content = new StringContent(json, Encoding.UTF8, "application/json");
        var response = await client1.PostAsync(emailAlertUrl, content);
        log.LogInformation(response.ToString());
    }
}



static async Task Request(string apiAddress, string endpoint, string subscriptionKey, string requestData)
{
    using (HttpClient client = new HttpClient { BaseAddress = new Uri(apiAddress) })
    {
        System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", subscriptionKey);

        var content = new StringContent(requestData, Encoding.UTF8, "application/json");
        var res = await client.PostAsync(endpoint, content);
        return await res.Content.ReadAsStringAsync();
    }
}

static string detectAnomaliesBatch(string requestData, ILogger log)
{
    log.LogInformation("Detecting anomalies as a batch");
   
    requestData = requestData.TrimEnd(']').TrimStart('[');

    //construct the request
    var result = Request(
        endpoint,
        batchDetectionUrl,
        subscriptionKey,
        requestData).Result;

    //deserialize the JSON object, and display it
    dynamic jsonObj = Newtonsoft.Json.JsonConvert.DeserializeObject(result);
    System.Console.WriteLine(jsonObj);

    string foundAnomalies = "Anomalies detected in the following data positions: ";

    if (jsonObj["code"] != null)
    {
        System.Console.WriteLine($"Detection failed. ErrorCode:{jsonObj["code"]}, ErrorMessage:{jsonObj["message"]}");
        
        log.LogInformation($"Detection failed. ErrorCode:{jsonObj["code"]}, ErrorMessage:{jsonObj["message"]}");
    }
    else
    {
        // log.LogInformation(result);
        //Find and display the positions of anomalies in the data set
        bool[] anomalies = jsonObj["isAnomaly"].ToObject<bool[]>();
        System.Console.WriteLine("\nAnomalies detected in the following data positions:");
        log.LogInformation("\nAnomalies detected in the following data positions:");
        for (var i = 0; i < anomalies.Length; i++)
        {
            if (anomalies[i])
            {
                System.Console.Write(i + ", ");
                log.LogInformation(i + ", ");
                foundAnomalies += i;
                foundAnomalies += ", ";
            }
        }
        if (anomalies.Any(item => item == true))
        {
            return foundAnomalies;
        }
    }
    return null;
}

public class FormatedData
{
    public string timestamp { get; set; }
    public string value { get; set; }
}

public class DataPoint : TableEntity
{
    [JsonPropertyName("value")]
    public string temperature { get; set;}
    public string timestamp { get; set; }
    
}

public class JsonFormat
{
    public List series { get; set; }
    public string granularity { get; set; }
    public int customInterval { get; set; }
    public int period { get; set; }
    // public float maxAnomalyRatio { get; set; }
    public int sensitivity { get; set; }
}

public class LowerCaseNamingPolicy : JsonNamingPolicy
{
    public override string ConvertName(string name) =>
        name.ToLower();
}

函数.json:

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

#r "Microsoft.WindowsAzure.Storage"
#r "Newtonsoft.Json"
#r "System.Text.Json"

using Microsoft.Extensions.Logging;
using Microsoft.WindowsAzure.Storage.Table;
using System.Threading.Tasks;
using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;

public static readonly string emailAlertUrl = Environment.GetEnvironmentVariable("EMAIL_ALERT_URL");
public static readonly HttpClient client1 = new HttpClient();

// Anomaly detection API secrets
public static readonly string subscriptionKey = Environment.GetEnvironmentVariable("ANOMALY_DETECTOR_KEY");
public static readonly string endpoint = Environment.GetEnvironmentVariable("ANOMALY_DETECTOR_ENDPOINT");

const string latestPointDetectionUrl = "/anomalydetector/v1.0/timeseries/last/detect";
public const string batchDetectionUrl = "/anomalydetector/v1.0/timeseries/entire/detect";

public static DateTimeOffset targetTime;

public static async Task Run(TimerInfo myTimer, CloudTable inputTable, ILogger log)
{
    log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
    
    // Get traget time from when to start reading the data
    targetTime = DateTime.UtcNow;
    targetTime = targetTime.AddHours(-6);
    log.LogInformation($"Target start time is: {targetTime}");

    TableQuery rangeQuery = new TableQuery().Where(
        TableQuery.GenerateFilterConditionForDate("Timestamp", QueryComparisons.GreaterThan, targetTime));

    // Execute the query and loop through the results
    List data = new List();
    foreach (DataPoint entity in 
    await inputTable.ExecuteQuerySegmentedAsync(rangeQuery, null))
    {
        data.Add(new DataPoint() {Timestamp = entity.Timestamp, temperature = entity.temperature});
    }

    // Sort data by Timestamp
    data.Sort((dp1, dp2) => DateTimeOffset.Compare(dp1.Timestamp, dp2.Timestamp));
    
    List formatedData = new List();
    data.ForEach( delegate(DataPoint point)
    {
        formatedData.Add(new FormatedData() { timestamp = point.Timestamp.ToString("yyyy-MM-ddTHH:mm:00Z"), value = point.temperature});
    });

    var options = new JsonSerializerOptions
    {
        IgnoreNullValues = true,
        // PropertyNamingPolicy = new LowerCaseNamingPolicy()
    };

    List jsonFormat = new List();
    jsonFormat.Add(new JsonFormat() {series = formatedData, granularity = "minutely", customInterval = 1, period = 90, sensitivity = 85});
    string dataToSend = JsonSerializer.Serialize(jsonFormat, options);

    // Call anomaly detection API
    var anomalies = detectAnomaliesBatch(dataToSend, log);

    if (anomalies != null){
        var json = JsonSerializer.Serialize(anomalies);
        var content = new StringContent(json, Encoding.UTF8, "application/json");
        var response = await client1.PostAsync(emailAlertUrl, content);
        log.LogInformation(response.ToString());
    }
}



static async Task Request(string apiAddress, string endpoint, string subscriptionKey, string requestData)
{
    using (HttpClient client = new HttpClient { BaseAddress = new Uri(apiAddress) })
    {
        System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", subscriptionKey);

        var content = new StringContent(requestData, Encoding.UTF8, "application/json");
        var res = await client.PostAsync(endpoint, content);
        return await res.Content.ReadAsStringAsync();
    }
}

static string detectAnomaliesBatch(string requestData, ILogger log)
{
    log.LogInformation("Detecting anomalies as a batch");
   
    requestData = requestData.TrimEnd(']').TrimStart('[');

    //construct the request
    var result = Request(
        endpoint,
        batchDetectionUrl,
        subscriptionKey,
        requestData).Result;

    //deserialize the JSON object, and display it
    dynamic jsonObj = Newtonsoft.Json.JsonConvert.DeserializeObject(result);
    System.Console.WriteLine(jsonObj);

    string foundAnomalies = "Anomalies detected in the following data positions: ";

    if (jsonObj["code"] != null)
    {
        System.Console.WriteLine($"Detection failed. ErrorCode:{jsonObj["code"]}, ErrorMessage:{jsonObj["message"]}");
        
        log.LogInformation($"Detection failed. ErrorCode:{jsonObj["code"]}, ErrorMessage:{jsonObj["message"]}");
    }
    else
    {
        // log.LogInformation(result);
        //Find and display the positions of anomalies in the data set
        bool[] anomalies = jsonObj["isAnomaly"].ToObject<bool[]>();
        System.Console.WriteLine("\nAnomalies detected in the following data positions:");
        log.LogInformation("\nAnomalies detected in the following data positions:");
        for (var i = 0; i < anomalies.Length; i++)
        {
            if (anomalies[i])
            {
                System.Console.Write(i + ", ");
                log.LogInformation(i + ", ");
                foundAnomalies += i;
                foundAnomalies += ", ";
            }
        }
        if (anomalies.Any(item => item == true))
        {
            return foundAnomalies;
        }
    }
    return null;
}

public class FormatedData
{
    public string timestamp { get; set; }
    public string value { get; set; }
}

public class DataPoint : TableEntity
{
    [JsonPropertyName("value")]
    public string temperature { get; set;}
    public string timestamp { get; set; }
    
}

public class JsonFormat
{
    public List series { get; set; }
    public string granularity { get; set; }
    public int customInterval { get; set; }
    public int period { get; set; }
    // public float maxAnomalyRatio { get; set; }
    public int sensitivity { get; set; }
}

public class LowerCaseNamingPolicy : JsonNamingPolicy
{
    public override string ConvertName(string name) =>
        name.ToLower();
}

配置逻辑应用

1. 部署完成后,使用左侧导航打开新创建的 Logic App

2.从左侧导航中选择逻辑应用程序设计器

3.选择+新步骤

4. 搜索您要使用的电子邮件客户端(Office 365 Outlook、Gmail 和 Outlook.com)

poYBAGN6f9-AFqx7AAA-9pe8Y9k475.png
Azure 逻辑应用设计器
 

5. 选择发送电子邮件操作

注意:这将根据您使用的电子邮件客户端而有所不同

6. 使用您的电子邮件帐户登录

7. 自定义您的消息,此电子邮件将在任何时候检测到异常时发送。

设置物联网设备

1. 接下来,您需要获取设备的连接字符串,导航到您之前创建的 IoT 中心

2.在左侧导航中选择物联网设备

3.在页面左上角选择+新建

4.给设备一个ID

pYYBAGN6f-qAbWCDAABjuP9k5kk826.png
物联网设备配置
 

5. 按屏幕底部的保存

6.选择您创建的设备

7. 复制您将在下一节中使用的主连接字符串

pYYBAGN6f-2AVrTKAAB7a9HJXb0269.png
IoT 设备的连接字符串
 

设备构建

pYYBAGN6f--Af-MvAACU92IQLgI779.jpg
温度监视器的完整构建
 

1. 将螺丝端子焊接到 MCP9600 的顶部。

poYBAGN6f_KAfuIDAACM8kZfLJc876.jpg
 

2. 将引脚焊接到 MCP9600 的底部。

提示:将引脚放在面包板上,以便在焊接时将它们固定到位。
poYBAGN6f_WANeCIAACz9xdzg7I342.jpg
 

3. 将 ESP32 和热电偶放大器插入面包板。

4. 按照下面的接线图,使用跳线将热电偶放大器连接到 ESP32。

poYBAGN6f_eAZF56AAEbGfX1bgY829.png
 

5. 将热电偶连接到 MCP9600 上的螺丝端子

下图使用通用 ESP32 开发板,即将推出带有 Adafruit Huzzah32 的新图片!
pYYBAGN6f_qAa_mCAADAL9fVRks425.jpg
 

设备代码

1. 如果您还没有,请将此 repo 克隆到您的计算机

2.用VS Code打开AiFreezer文件夹

3.在这个文件夹中新建一个文件,命名为config.h

4. 将以下代码粘贴到config.h

const char* ssid     = "";
const char* password = "";
static const char* connectionString = "";

5. 填写您的网络凭据

6. 从 IoT 中心粘贴连接字符串

7. 按照本 [指南] 的第一部分将 ESP32 扩展添加到 Arduino IDE。

8. 使用 Arduino 的库管理器安装下面列出的库。如果您在 [此处]之前使用过库管理器,这是一个有用的指南。

9. Adafruit MCP9600

注意:如果系统提示您为这些库安装其他依赖项,请选择全部安装

10. 在 VS Code 中打开 FreezerTempAlert.ino,打开命令面板(CTL+SHIFT+P)并输入Arduino:Change Board Type然后搜索Adafruit ESP32 Feather

11.接下来选择活动串口,打开命令面板并输入Arduino:选择串口

12. 最后将您的代码上传到您的羽毛板,打开命令面板并输入Arduino:


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

评论(0)
发评论

下载排行榜

全部0条评论

快来发表一下你的评论吧 !