Заключительная часть работы с облаком 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.
Так же, сделаем для второго правила Low_temp_PowerOffRelay_and_send_to_web@devdotnet.org.
Из минуса функции отправки 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);
}
Интерфейс
Итоги
Облако для сбора данных освобождает от построения своей инфраструктуры, что снижает затраты на покупку аппаратного и программного обеспечения. Конфигурирование устройств, датчиков выполняется очень просто. Развитый API позволяет не только получать данные и управлять устройством, но и сформировать собственную панель администрирования. Данные передаются без существенных задержек, запросы не теряются. Доступно две роли: администратор и пользователь. Администратору для добавления пользователя, требуется указать новый email, и на этот адрес придет письмо с приглашением(invite). В процессе регистрации нового пользователя, пользователю будет задан вопрос о принятие приглашения на доступ(invite). Таким образом сам пользователь занимается управлением свое учетной записи, включай изменения пароля. Из недостатков, нельзя в сообщение SMS включать показания датчиков, только заранее заготовленный шаблон. Для email отсутствую шаблоны, только стандартный вид с табличкой показания датчиков. Еще была обнаружена одна особенность, заключающаяся в очередности обработки правил. Иногда наблюдалась ситуация с выключение реле сразу же после включения. Причем согласно логике реле должно было выключаться только после снижения температуры ниже 28 С. Условия логики правил и код на устройстве не содержало ошибок. Ситуация разрешилось просмотром журнала оповещений, новые оповещения добавляются в конец списка.
Событие №39 сработало последним, хотя оно по времени предшествовало событию 38. Реле включилось на секунду, и выключилось, не смотря на дальнейшее повышение температуры. Возможно, это связанно с еще не законченным сервисом. На текущий момент облако Intel IoT Analytics в разработке(статус BETA).
Приложение
Тестовый рабочий вариант web.devdotnet.org.
Проект доступен по ссылке.
Исходный код
<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>
@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>
Оглавление
- Intel Edison. Первый запуск
- Intel Edison. Работа с облаком Intel IoT Analytics: регистрация и отправка данных
- Intel Edison. Работа с облаком Intel IoT Analytics: создание правил и отправка уведомлений
- Intel Edison. Облако Intel IoT Analytics: отправка SMS и RESTful клиент на ASP.NET
Автор: devzona