Intel Edison. Облако Intel IoT Analytics: отправка SMS и RESTful клиент на ASP.NET

Intel IoT Analytics
Заключительная часть работы с облаком Intel IoT Analytics. Добавление отправки SMS уведомления используя HTTP шлюзы и создание простого RESTful клиента на ASP.NET. Подведение итогов.

Отправка SMS уведомления используя HTTP шлюз
В предыдущей работе Intel Edison. Работа с облаком Intel IoT Analytics: создание правил и отправка уведомлений были сформированы правила позволяющие отправлять: уведомление на e-mail и управлять питанием реле. Отправку SMS сообщения, добавим к этим двум созданным правилам.
Правила:

  • Higth_temp_PowerOnRelay_and_send_to_web@devdotnet.org
  • Low_temp_PowerOffRelay_and_send_to_web@devdotnet.org


Будем использовать SMS шлюз smsc.ru. API доступно по ссылке.
Для отправки SMS сообщения достаточно сформировать и отправить запрос GET вида:

smsc.ru/sys/send.php?login=&psw=&phones=&mes=, где:
login — Логин Клиента
psw — Пароль Клиента или MD5-хеш пароля в нижнем регистре.
phones — Номер в международном формате без знака "+"
mes — Текст отправляемого сообщения.
Добавлять заголовки Head нет необходимости, все очень просто.

Сформируем два запроса:
smsc.ru/sys/send.php?login=tele****&psw=d46d70eb6******&phones=79232******&mes=Relay_power_ON
smsc.ru/sys/send.php?login=tele****&psw=d46d70eb6******&phones=79232******&mes=Relay_power_OFF
Перейдем в раздел Rules, откроем правило Higth_temp_PowerOnRelay_and_send_to_web@devdotnet.org.

Добавим Notifications type — HTTP Endpoint и впишем URL.
Intel IoT Analytics

Так же, сделаем для второго правила Low_temp_PowerOffRelay_and_send_to_web@devdotnet.org.

Полученные SMS на телефоне
Intel IoT Analytics


Из минуса функции отправки SMS сообщения, необходимо отметить отсутствие возможности отправки динамических данных, например нельзя отправить текущее показание датчика.

Простой RESTful клиент на ASP.NET Razor
Сформируем страницу отображающую текущие показания сенсоров: температуру и давление. На странице разместим управляющую часть: включение реле и светодиода.  API облака доступно по ссылке. Реализация на ASP.NET Razor netf 4.5.  Для работы с JSON используется библиотека Newtonsoft.Json. Файл Web.config содержит логин и пароль доступа к облаку. Пример не является законченным решением, а является простой демонстрацией использования API.

Как обычно получим токен, раздел в wiki Authorization:

Код
string GetNewToken()
            {
                //чтение login и pass
                string strLogin, strPass;
                strLogin = System.Configuration.ConfigurationManager.AppSettings["Login"];
                strPass = System.Configuration.ConfigurationManager.AppSettings["Pass"];
                //авторизация, получение токена.
                //https://github.com/enableiot/iotkit-api/wiki/Authorization
                //структура JSON
                var obj = new
                {
                    username = strLogin,
                    password = strPass
                };
                string postData = JsonConvert.SerializeObject(obj, Formatting.Indented);
                //HttpWebRequest
                HttpWebRequest httpWebRequest = (HttpWebRequest)HttpWebRequest.Create("https://dashboard.us.enableiot.com/v1/api/auth/token");
                httpWebRequest.Method = "POST";
                httpWebRequest.ContentType = "application/json";
                //
                byte[] byte1 = System.Text.Encoding.UTF8.GetBytes(postData);
                httpWebRequest.ContentLength = byte1.Length;
                httpWebRequest.GetRequestStream().Write(byte1, 0, byte1.Length);
                httpWebRequest.GetRequestStream().Close();
                //
                StreamReader reader = new StreamReader(httpWebRequest.GetResponse().GetResponseStream());
                JObject objResponse = JObject.Parse(reader.ReadToEnd());
                return (string)objResponse["token"];
            }



Чтение данных, раздел в wiki Data-API:

Код
void GetStateSensors(string strToken, Dictionary<string, string> dicSensors)
            {
                //чтение данных
                //https://github.com/enableiot/iotkit-api/wiki/Data-API
                //структура JSON
                var obj = new
                {
                    from = -20,
                    targetFilter = new { deviceList = new[] { "9e-8d-22-0c-50-7b" } },
                    metrics = new[] { new {
                                                id="99fb5b73-a9e2-4ae0-8a0d-45e6a7cc0541",
                                                op="none"
                                        },
                    new {
                                                id="b3731f8a-4f31-414d-a072-b364b1792b5b",
                                                op="none"
                                        }
                                }
                };
                string postData = JsonConvert.SerializeObject(obj, Formatting.Indented);
                //HttpWebRequest
                HttpWebRequest httpWebRequest = (HttpWebRequest)HttpWebRequest.Create("https://dashboard.us.enableiot.com/v1/api/accounts/4c8c6b2e-c54f-4df5-8bbb-a5e59df85aaa/data/search");
                httpWebRequest.Method = "POST";
                httpWebRequest.ContentType = "application/json";
                //Headers
                httpWebRequest.Headers.Add("Authorization", "Bearer " + strToken);
                httpWebRequest.Headers.Add("accountId", "4c8c6b2e-c54f-4df5-8bbb-a5e59df85aaa");
                //
                byte[] byte1 = System.Text.Encoding.UTF8.GetBytes(postData);
                httpWebRequest.ContentLength = byte1.Length;
                httpWebRequest.GetRequestStream().Write(byte1, 0, byte1.Length);
                httpWebRequest.GetRequestStream().Close();
                //
                StreamReader reader = new StreamReader(httpWebRequest.GetResponse().GetResponseStream());
                JObject objResponse = JObject.Parse(reader.ReadToEnd());
                //add Dic
                string strValueSensor = (string)objResponse["series"][0]["points"][0]["value"];
                dicSensors.Add("pressure", strValueSensor);
                strValueSensor = (string)objResponse["series"][1]["points"][0]["value"];
                strValueSensor = Math.Round(decimal.Parse(strValueSensor, System.Globalization.CultureInfo.CreateSpecificCulture("en")), 2).ToString();
                dicSensors.Add("temperature", strValueSensor);
            }



Интерфейс
Intel IoT Analytics

Итоги
Облако для сбора данных освобождает от построения своей инфраструктуры, что снижает затраты на покупку аппаратного и программного обеспечения. Конфигурирование устройств, датчиков выполняется очень просто. Развитый API позволяет не только получать данные и управлять устройством, но и сформировать собственную панель администрирования. Данные передаются без существенных задержек, запросы не теряются. Доступно две роли: администратор и пользователь. Администратору для добавления пользователя, требуется указать новый email, и на этот адрес придет письмо с приглашением(invite). В процессе регистрации нового пользователя, пользователю будет задан вопрос о принятие приглашения на доступ(invite). Таким образом сам пользователь занимается  управлением свое учетной записи, включай изменения пароля. Из недостатков, нельзя в сообщение  SMS включать показания датчиков, только заранее заготовленный шаблон. Для email отсутствую шаблоны, только стандартный вид с табличкой показания датчиков. Еще была обнаружена одна особенность, заключающаяся в очередности обработки правил. Иногда наблюдалась ситуация с выключение реле сразу же после включения. Причем согласно логике реле должно было выключаться только после снижения температуры ниже 28 С. Условия логики правил и код на устройстве не содержало ошибок. Ситуация разрешилось просмотром журнала оповещений, новые оповещения добавляются в конец списка.
Intel IoT Analytics
Событие №39 сработало последним, хотя оно по времени предшествовало событию 38. Реле включилось на секунду, и выключилось, не смотря на дальнейшее повышение температуры. Возможно, это связанно с еще не законченным сервисом. На текущий момент облако Intel IoT Analytics в разработке(статус BETA).

Приложение
Тестовый рабочий вариант web.devdotnet.org.
Проект доступен по ссылке.
Исходный код

web.config
<configuration>
  <appSettings>
    <add key="Login" value="***"/>
    <add key="Pass" value="***"/>
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.5">
      <assemblies>
        <add assembly="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        <add assembly="System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
      </assemblies>
    </compilation>
    <httpRuntime targetFramework="4.5"/>
  </system.web>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35"/>
        <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0"/>
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35"/>
        <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0"/>
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>



index.cshtml
@using System.Net.Http
@using Newtonsoft.Json
@using Newtonsoft.Json.Linq

@{
    //Проверка токена в Session
    string strToken;
    strToken = (string)Session["Token"];
    if (strToken == null)
    {
        strToken = GetNewToken();
        Session["Token"] = strToken;
    }
    //Action
    if (Request["command"] != null)
    {
        string strCommand = (string)Request["command"];
        SetSateActuation(strToken,strCommand);
    }
    //Чтение данных Sensors
    Dictionary<string, string> dicSensors = new Dictionary<string, string>();
    GetStateSensors(strToken, dicSensors);
    //Чтение данных Actuation
    bool boolValueLED, boolValueRelay;
    GetStateActuations(strToken, out boolValueLED, out boolValueRelay);
}
        @functions {
            // Pass a user name to this method.
            string GetNewToken()
            {
                //чтение login и pass
                string strLogin, strPass;
                strLogin = System.Configuration.ConfigurationManager.AppSettings["Login"];
                strPass = System.Configuration.ConfigurationManager.AppSettings["Pass"];
                //авторизация, получение токена.
                //https://github.com/enableiot/iotkit-api/wiki/Authorization
                //структура JSON
                var obj = new
                {
                    username = strLogin,
                    password = strPass
                };
                string postData = JsonConvert.SerializeObject(obj, Formatting.Indented);
                //HttpWebRequest
                HttpWebRequest httpWebRequest = (HttpWebRequest)HttpWebRequest.Create("https://dashboard.us.enableiot.com/v1/api/auth/token");
                httpWebRequest.Method = "POST";
                httpWebRequest.ContentType = "application/json";
                //
                byte[] byte1 = System.Text.Encoding.UTF8.GetBytes(postData);
                httpWebRequest.ContentLength = byte1.Length;
                httpWebRequest.GetRequestStream().Write(byte1, 0, byte1.Length);
                httpWebRequest.GetRequestStream().Close();
                //
                StreamReader reader = new StreamReader(httpWebRequest.GetResponse().GetResponseStream());
                JObject objResponse = JObject.Parse(reader.ReadToEnd());
                return (string)objResponse["token"];
            }
            void GetStateSensors(string strToken, Dictionary<string, string> dicSensors)
            {
                //чтение данных
                //https://github.com/enableiot/iotkit-api/wiki/Data-API
                //структура JSON
                var obj = new
                {
                    from = -20,
                    targetFilter = new { deviceList = new[] { "9e-8d-22-0c-50-7b" } },
                    metrics = new[] { new {
                                                id="99fb5b73-a9e2-4ae0-8a0d-45e6a7cc0541",
                                                op="none"
                                        },
                    new {
                                                id="b3731f8a-4f31-414d-a072-b364b1792b5b",
                                                op="none"
                                        }
                                }
                };
                string postData = JsonConvert.SerializeObject(obj, Formatting.Indented);
                //HttpWebRequest
                HttpWebRequest httpWebRequest = (HttpWebRequest)HttpWebRequest.Create("https://dashboard.us.enableiot.com/v1/api/accounts/4c8c6b2e-c54f-4df5-8bbb-a5e59df85aaa/data/search");
                httpWebRequest.Method = "POST";
                httpWebRequest.ContentType = "application/json";
                //Headers
                httpWebRequest.Headers.Add("Authorization", "Bearer " + strToken);
                httpWebRequest.Headers.Add("accountId", "4c8c6b2e-c54f-4df5-8bbb-a5e59df85aaa");
                //
                byte[] byte1 = System.Text.Encoding.UTF8.GetBytes(postData);
                httpWebRequest.ContentLength = byte1.Length;
                httpWebRequest.GetRequestStream().Write(byte1, 0, byte1.Length);
                httpWebRequest.GetRequestStream().Close();
                //
                StreamReader reader = new StreamReader(httpWebRequest.GetResponse().GetResponseStream());
                JObject objResponse = JObject.Parse(reader.ReadToEnd());
                //add Dic
                string strValueSensor = (string)objResponse["series"][0]["points"][0]["value"];
                dicSensors.Add("pressure", strValueSensor);
                strValueSensor = (string)objResponse["series"][1]["points"][0]["value"];
                strValueSensor = Math.Round(decimal.Parse(strValueSensor, System.Globalization.CultureInfo.CreateSpecificCulture("en")), 2).ToString();
                dicSensors.Add("temperature", strValueSensor);
            }

            void GetStateActuations(string strToken, out bool boolValueLED, out bool boolValueRelay)
            {
                //чтение данных Actuation
                //https://github.com/enableiot/iotkit-api/wiki/Control-Device-API
                //HttpWebRequest
                HttpWebRequest httpWebRequest = (HttpWebRequest)HttpWebRequest.Create("https://dashboard.us.enableiot.com/v1/api/accounts/4c8c6b2e-c54f-4df5-8bbb-a5e59df85aaa/control/devices/9e-8d-22-0c-50-7b?from=-60000");
                httpWebRequest.Method = "GET";
                //Headers
                httpWebRequest.Headers.Add("Authorization", "Bearer " + strToken);
                httpWebRequest.Headers.Add("accountId", "4c8c6b2e-c54f-4df5-8bbb-a5e59df85aaa");
                //
                StreamReader reader = new StreamReader(httpWebRequest.GetResponse().GetResponseStream());
                JArray jArr = (JArray)JsonConvert.DeserializeObject(reader.ReadToEnd());
                //Parse data
                Dictionary<long, string> dicSensorLED = new Dictionary<long, string>();
                Dictionary<long, string> dicSensorRelay = new Dictionary<long, string>();
                long longTicks;
                foreach (JObject item in jArr)
                {
                    longTicks = DateTime.Parse((string)item["created"]).Ticks;
                    if ((string)item["command"] == "LED.v1.0")
                    {
                        if (!dicSensorLED.ContainsKey(longTicks)) dicSensorLED.Add(longTicks, (string)item["params"][0]["value"]);
                    }
                    else
                    {
                        if (!dicSensorRelay.ContainsKey(longTicks)) dicSensorRelay.Add(longTicks, (string)item["params"][0]["value"]);
                    }
                }
                //find last value
                string strValueLED = dicSensorLED[dicSensorLED.Max(x => x.Key)];
                string strValueRelay = dicSensorRelay[dicSensorRelay.Max(x => x.Key)];
                //
                if (strValueLED == "0") boolValueLED = false; else boolValueLED = true;
                if (strValueRelay == "0") boolValueRelay = false; else boolValueRelay = true;
                }

            void SetSateActuation(string strToken, string strCommand)
            {
                //отправка команды Actuation
                //https://github.com/enableiot/iotkit-api/wiki/Control-Device-API
                //разбор команды
                string strComponentId, strName, strValue, strComplexCommands;
                switch (strCommand)
                {
                    case "led_on":
                        {
                            strComponentId="64dbdbee-e181-403f-8b51-0872e11a289e";
                            strName="LED";
                            strValue = "1";
                            strComplexCommands = "led1_ON";
                            break;
                        }
                    case "led_off":
                        {
                            strComponentId = "64dbdbee-e181-403f-8b51-0872e11a289e";
                            strName = "LED";
                            strValue = "0";
                            strComplexCommands = "led1_OFF";
                            break;
                        }
                    case "relay_on":
                        {
                            strComponentId = "5f72e39a-463a-4e57-bac7-9b32debfd865";
                            strName = "RELAY";
                            strValue = "1";
                            strComplexCommands = "relay1_ON";
                            break;
                        }
                    case "relay_off":
                        {
                            strComponentId = "5f72e39a-463a-4e57-bac7-9b32debfd865";
                            strName = "RELAY";
                            strValue = "0";
                            strComplexCommands = "relay1_OFF";
                            break;
                        }
                    default:
                        // You can use the default case.
                        return;
                }
                //структура JSON
                var obj = new
                {
                    commands = new[] { new {
                    componentId = strComponentId,
                    parameters= new[] { new
                                        {
                                            name=strName,
                                            value=strValue
                                        }
                    },
                    transport="ws"
                }
                },
                    complexCommands = new[] { strComplexCommands }
                };
                string postData = JsonConvert.SerializeObject(obj, Formatting.Indented);
                //HttpWebRequest
                HttpWebRequest httpWebRequest = (HttpWebRequest)HttpWebRequest.Create("https://dashboard.us.enableiot.com/v1/api/accounts/4c8c6b2e-c54f-4df5-8bbb-a5e59df85aaa/control");
                httpWebRequest.Method = "POST";
                httpWebRequest.ContentType = "application/json";
                //Headers
                httpWebRequest.Headers.Add("Authorization", "Bearer " + strToken);
                httpWebRequest.Headers.Add("accountId", "4c8c6b2e-c54f-4df5-8bbb-a5e59df85aaa");
                //
                byte[] byte1 = System.Text.Encoding.UTF8.GetBytes(postData);
                httpWebRequest.ContentLength = byte1.Length;
                httpWebRequest.GetRequestStream().Write(byte1, 0, byte1.Length);
                httpWebRequest.GetRequestStream().Close();
                //
                httpWebRequest.GetResponse();
                }
            }
        }

        <html>
        <head>
            <title>Пример RESTful клиента для Intel IoT Analytics на ASP.NET Razor</title>
        </head>
        <body>
            <h1>Пример RESTful клиента для Intel IoT Analytics на ASP.NET Razor</h1>
<p>Сегодня: @DateTime.Now.ToString()</p>
    <p>Пример демонстрирует использование <a href="https://github.com/enableiot/iotkit-api/wiki/Api-Home">api облака intel iot analytics.</a></p>
    <p>Из функций API используется:</p>
    <ol>
        <li>Авторизация, получение токена</li>
        <li>Чтение данных с датчиков(sensor)</li>
        <li>Отправка управляющих команд (Actuation)</li>
    </ol>
    <h3>Состояние датчиков</h3>
    <p>Температура: @dicSensors["temperature"] *С</p>
    <p>Давление: @dicSensors["pressure"] Па</p>
     @if (boolValueLED==false)
        {
            <p>LED: OFF</p>
        }
     else
     {
        <p>LED: ON</p>
     }

    @if (boolValueRelay == false)
    {
        <p>Реле: OFF</p>
    }
    else
    {
        <p>Реле: ON</p>
    }
    <form name="formaction" action="~/index.cshtml" method="get">
        <h3>Управление Actuation</h3>
        <p> LED: 
            <button name="command" type="submit" value="led_on"> ON </button>
            <button name="command" type="submit" value="led_off"> OFF </button>
        </p>
        <p> Реле: 
            <button name="command" type="submit" value="relay_on"> ON </button>
            <button name="command" type="submit" value="relay_off"> OFF </button>
        </p>
        <p></p>
        <p>
            <button name="update" type="submit"> Обновить страницу </button>
        </p>
    </form>
</body>
</html>



Оглавление

  1. Intel Edison. Первый запуск
  2. Intel Edison. Работа с облаком Intel IoT Analytics: регистрация и отправка данных
  3. Intel Edison. Работа с облаком Intel IoT Analytics: создание правил и отправка уведомлений
  4. Intel Edison. Облако Intel IoT Analytics: отправка SMS и RESTful клиент на ASP.NET

© Geektimes