В настоящее время к современным устройствам и гаджетам предъявляются довольно-таки высокие требования. И я говорю не только о серфинге в интернете, чтобы прочитать свою любимою новостную рассылку, проверить почту или пообщаться с друзьями в соц сети. Люди хотят гораздо большего, в современном мире просто необходимо управлять и мониторить устройства удаленно. Естественно управлять этими устройствами необходимо через Интернет. На данный момент существует огромное количество облачных решений, в данной статье рассмотрим облачное решение от компании Intel на практическом примере.
Для начала разберемся с новым облаком для Internet-of-Things.
Аналитическое облако IoT Analytics включает в себя ресурсы для сбора и анализа данных, собранных с различных сенсоров, подключенных к Intel Galileo и Intel Edison. Используя данный сервис, разработчик может с легкостью хранить и обрабатывать данные, не инвестируя в это дополнительные ресурсы, сосредоточась вместо этого на создании проектов под вышеупомянутые платы.
Рассмотрим концепцию использования IoT Analytics cloud.
Для того чтобы начать использовать облако IoT Analytics, необходимо создать админ-аккаунт, с помощью которого можно будет регистрировать девайсы, управлять оповещениями, создавать аккаунты и выполнять другие задачи на сайте. Перейти к использованию IoT Analytics Dashboard можно по ссылке. Базовые понятия и элементарные примеры использования данного облака описаны здесь.
Для того, чтобы продемонстрировать взаимодействие с облаком, продолжим работу над примером из статьи «Используем встроенный микроконтроллер в Intel Edison», в которой датчик измерения расстояния HC-SR04 подключается к плате Intel Edison и измеренное расстояние выводиться на LCD дисплей. Возьмем описанный пример измерения расстояния и добавим автоматическую загрузку полученных с датчика данных, прямиком в облако.
Сперва зарегистрируем наш датчик расстояния. Для этого заполним все необходимые поля.
Будем использовать целочисленный тип, зададим диапазон значений от -1 (ошибка) до 100 сантиметров.
Далее необходимо зарегистрировать датчик для Intel Edison. Используем следующую команду:
# iotkit-admin register dist distance.v1.0
# iotkit-admin catalog
Теперь наш датчик зарегистрирован и закреплен за данным устройством.
Отправка данных в клауд может быть произведена посредством нескольких способов.
Один из самых простых:
# iotkit-admin observation dist 10
Но, как вы понимаете, это не самый удобный способ отправлять данные в облако. Как правило, данная команда используется для тестирования.
Существует два других способа передачи данных в облако:
- Настроить на клиенте интерфейс REST (Документация по настройке).
- Отправление UDP пакетов агенту поднятому на плате. Агент конвертирует пакеты в REST вызовы и посылает запросы.
Для запуска агента на плате используем следующую команду:
# systemctl start iotkit-agent
Существует возможность отправлять UDP сообщения через localhost на порт 41234 (UDP://localhost:41234). Чтобы это сделать, необходимо создать JSON-файл (JavaScript Object Notation):
{"n": "<sensor name>", "v": "<value>" }
где “n” имя проводимого измерения, и “v” значение.
Например, так:
{ "n": "dist", "v": 17 }
{ "n": "dist", "v": 24}
Я описал, каким образом отправлять данные в облако IoT Analytics через iotkitagent. Разработчики также могут отправлять данные, используя такие языки программирования, как C/C++, JavaScript или Python. В одной из указанных в начале статей реализован пример публикации данных с помощью C/C++. Поскольку я предпочитаю концепцию более быстрого и удобного программирования, в данной статье я напишу небольшой пример используя мой любимый язык Python.
Скрипт IoTCloudManager.py:
import sys
import requests
import json
import uuid
import time
import random
import pyupm_i2clcd
host = "dashboard.us.enableiot.com"
proxies = {
# Указываем проксю
}
username = "email@gmail.com"
password = "*********"
account_name = "account_name"
# Указываем id девайса, если уже существует выдаст ошибку
device_id = "***************************************"
observations_per_hour = 1
days_of_data = 1
verify = True
api_root = "/v1/api"
base_url = "https://{0}{1}".format(host, api_root)
device_name = "Device-{0}".format(device_id)
g_user_token = ""
g_device_token = ""
def main():
global g_user_token, g_device_token
# инициализируем аутентификацию для последующих API вызовов
g_user_token = get_token(username, password)
# получаем user_id внутри Intel IoT Analytics Platform
uid = get_user_id()
print "UserId: {0}".format(uid)
aid = get_account_id(uid, account_name)
print "AccountId: {0}".format(aid)
# создаем новый девайс с акаунтом
create_device(aid, device_id, device_name)
# Обновляем код активации
ac = generate_activation_code(aid)
print "Activation code: {0}".format(ac)
# Активируем девайс
g_device_token = activate(aid, device_id, ac)
# Регистрируем сенсор измерения расстояния "Distance.v1.0". Данный вызов вернет component_id (cid)
cid = create_component(aid, device_id, "Distance.v1.0", "Dist")
print "ComponentID (cid): {0}".format(cid)
lcd = pyupm_i2clcd.Jhd1313m1(6, 0x3E, 0x62)
with open('/dev/ttymcu0', 'w+t') as f:
while True:
f.write('get_distance\n') # Send command to MCU
f.flush()
line = f.readline() # Read response from MCU, -1 = ERROR
value = int(line.strip('\n\r\t '))
# сабмитим данные в облако
create_observations(aid, device_id, cid, value)
# читаем засабмиченные данные
o = get_observations(aid, device_id, cid)
print_observation_counts(o)
lcd.clear()
if value == -1:
lcd.setColor(255, 0, 0) # RED
lcd.write('ERROR')
else:
lcd.setColor(0, 255, 0) # GREEN
lcd.write('%d cm' % (value,))
time.sleep(1)
def get_user_headers():
headers = {
'Authorization': 'Bearer ' + g_user_token,
'content-type': 'application/json'
}
return headers
def get_device_headers():
headers = {
'Authorization': 'Bearer ' + g_device_token,
'content-type': 'application/json'
}
#print "Headers = " + str(headers) (ЗАКОМЕНЧЕННЫЙ КОД)
return headers
def check(resp, code):
if resp.status_code != code:
print "Expected {0}. Got {1} {2}".format(code, resp.status_code, resp.text)
sys.exit(1)
def get_token(username, password):
url = "{0}/auth/token".format(base_url)
headers = {'content-type': 'application/json'}
payload = {"username": username, "password": password}
data = json.dumps(payload)
resp = requests.post(url, data=data, headers=headers, proxies=proxies, verify=verify)
check(resp, 200)
js = resp.json()
token = js['token']
return token
def get_user_id():
url = "{0}/auth/tokenInfo".format(base_url)
resp = requests.get(url, headers=get_user_headers(), proxies=proxies, verify=verify)
check(resp, 200)
js = resp.json()
user_id = js["payload"]["sub"]
return user_id
def get_account_id(user_id, account_name):
url = "{0}/users/{1}".format(base_url, user_id)
resp = requests.get(url, headers=get_user_headers(), proxies=proxies, verify=verify)
check(resp, 200)
js = resp.json()
if 'accounts' in js:
accounts = js["accounts"]
for k, v in accounts.iteritems():
if 'name' in v and v["name"] == account_name:
return k
print "Account name {0} not found.".format(account_name)
print "Available accounts are: {0}".format([v["name"] for k, v in accounts.iteritems()])
return None
def create_device(account, device_id, device_name):
url = "{0}/accounts/{1}/devices".format(base_url, account)
device = {
"deviceId": str(device_id),
"gatewayId": str(device_id),
"name": device_name,
"tags": ["Russia", "Moscow", "RoadShow"],
"attributes": {
"vendor": "intel",
"platform": "x86",
"os": "linux"
}
}
data = json.dumps(device)
resp = requests.post(url, data=data, headers=get_user_headers(), proxies=proxies, verify=verify)
check(resp, 201)
return resp
def generate_activation_code(account_id):
url = "{0}/accounts/{1}/activationcode/refresh".format(base_url, account_id)
resp = requests.put(url, headers=get_user_headers(), proxies=proxies, verify=verify)
check(resp, 200)
js = resp.json()
activation_code = js["activationCode"]
return activation_code
def activate(account_id, device_id, activation_code):
url = "{0}/accounts/{1}/devices/{2}/activation".format(base_url, account_id, device_id)
activation = {
"activationCode": activation_code
}
data = json.dumps(activation)
resp = requests.put(url, data=data, headers=get_user_headers(), proxies=proxies, verify=verify)
check(resp, 200)
js = resp.json()
if "deviceToken" in js:
token = js["deviceToken"]
return token
else:
print js
sys.exit(1)
def create_component(account_id, device_id, component_type_name, name):
url = "{0}/accounts/{1}/devices/{2}/components".format(base_url, account_id, device_id)
component = {
"type": component_type_name,
"name": name,
"cid": str(uuid.uuid4())
}
data = json.dumps(component)
resp = requests.post(url, data=data, headers=get_device_headers(), proxies=proxies, verify=verify)
check(resp, 201)
js = resp.json()
return js["cid"]
def create_observations(account_id, device_id, cid, val):
url = "{0}/data/{1}".format(base_url, device_id)
body = {
"accountId": account_id,
"data": []
}
o = {
"componentId": cid,
"value": str(val),
"attributes": {
"i": i
}
}
body["data"].append(o)
data = json.dumps(body)
resp = requests.post(url, data=data, headers=get_device_headers(), proxies=proxies, verify=verify)
check(resp, 201)
def get_observations(account_id, device_id, component_id):
url = "{0}/accounts/{1}/data/search".format(base_url, account_id)
search = {
"from": 0,
"targetFilter": {
"deviceList": [device_id]
},
"metrics": [
{
"id": component_id
}
]
}
data = json.dumps(search)
resp = requests.post(url, data=data, headers=get_user_headers(), proxies=proxies, verify=verify)
check(resp, 200)
js = resp.json()
return js
def print_observation_counts(js):
if 'series' in js:
series = js["series"]
series = sorted(series, key=lambda v: v["deviceName"])
for v in series:
print "Device: {0} Count: {1}".format(v["deviceName"], len(v["points"]))
if __name__ == "__main__":
main()
Посмотрим теперь, что получилось на графике для некоторого количества измерений. На графике изображены данные (в сантиметрах) измерений с датчика в разный момент времени.
Таким образом, достаточно легко загружать данные в облако.
Теперь попробуем определить максимальное и минимальное расстояние дистанции (см), которые мы отправили в облако. Получаем следующую картину.
В качестве заключения хочется отметить, что облако IoT Analytics является простым и удобным инструментом для хранения и анализа данных, получаемых с подключенных к платам датчиков.
Комментарии (4)
4robots
17.07.2015 15:33+2Спасибо. В данном примере считали расстояние сохранили в облаке. Посмотрели график. Красиво.
Есть идеи про Аналитику? Ведь облако IoT Analitycs или это просто для красоты названия?
crea7or
18.07.2015 00:30Не понимаю, в чём такая необходимость Эдисона? Он же стоит с платой больше $100. Ну вот, например, Particle Io — ARM+WIFI в размере Arduino nano: $19. Использовать очень просто. Там же можно и сотовой сетью: $39-$49. Своё облако они тоже предоставляют. Да и Azure не сложно подрубить. Или вот Node McuLua за $7 тоже с WIFI (вот тут примерно как их использовать). С ним, конечно, всё сами.
nckma
Кажется жизнь будет становиться все опасней и опасней.
Сперва хранение данных от датчиков умного дома в облаке. Потом удаленное управление домашней техникой… Утечки паролей, перехват управления домашним оборудованием хакерами: кондиционеры, газовые колонки, телевизоры и гаражная автоматика…
Ну или просто — едешь домой дистанционно включил чайник. Застрял в пробке, вода в чайнике выкипела, пожар. Оказывается в фирмваре чайника было необрабатываемое исключение, которое не обнаружили тестировщики…
Klukonin
Странно что человека минусуют.
Почему-то люди считают что, например, вирусы-локеры для персональных компьютеров не применимы к умной бытовой технике. Хотя, любая техника с интерфейсом в один прекрасный день может выдать сообщение о том что ваша стиралка/сушилка/микроволновка/холодильник подверглась блокировке и просит отправить смс на номер. Стоимость вызова мастера для перепрошивки будет, предположим, в два раза выше стоимости смс. Вполне реальный сценарий.
Логично что чем больше уровень информатизации и чем больше потенциально уязвимых узлов — тем больше рисков с этим связанных.
Риски эти нужно учитывать. При этом, выносить за скобки атаки на технику с целью нанести ущерб, по меньшей мере, глупо. И аргументы «кому я/ты/Вася нужен» не канают. Массовый вывод из строя котельных в городе или районе, допустим, зимой в -30 — прекрасный сценарий для террористической атаки.