С момента прошлой статьи (ссылка прошел почти год. И за этот год, я переосмыслил некоторые вещи, интернет и получилось что-то вроде IoT :) > интернет вещей).

Постараюсь кратко изложить новую порцию накопленных знаний, описать куда стремлюсь и чего хочу добиться > прошу к прочтению.

Noolite F v2.0


В заголовке у меня проскочили слова: pebble & noolite. Перейдем к ним!
Я ещё управляю с pebble своим светом noolite, гаражом и воротами. Про noolite уже написано достаточно много полезной информации, поиск показывает новые статьи.

Помимо блоков первого поколения системы noolite, у меня появились новые: cиловой блок SLF-1-200 (nooLite-F) с обратной связью (и шифрованием нового поколения).

image

силовой блок SB-1-150

image

и обновленный usb адаптера MTRF-64 USB.

image

Весь свет в моем доме на системе noolite.

Ещё недавно у меня в «системном домашнем корче» красовался noolite USB адаптер первого поколения и на 16 устройств, а теперь на 64 канала (MTRF-64 USB), да ещё и для устройств нового поколения с обратной связью (noolite F). Ноотехника движется в правильном направлении, создавая новый современные устройства.

Есть 2 самые главное опции новых устройств: обратная связь и принцип идентификации устройств по адресам: ID. Теперь не надо писать в 1 канал 1 устройств и управлять каналом. Теперь можно обращаться к конкретному устройств в одном канале по его ID и посылая ему команду исполнения.

Документация для блоков нового поколения доступна на сайте производителя.

Все работает через serial port, используя python код.
# -*- coding: utf-8 -*-
#!/usr/bin/env python

import serial
import time

class NooLiteCommand:
    def __init__(self, ch, cmd, mode=0, ctr=0, res=0, fmt=0, d0=0, d1=0, d2=0, d3=0, id0=0, id1=0, id2=0, id3=0):
        self.st = 171
        self.mode = mode
        self.ctr = ctr
        self.res = res
        self.ch = ch
        self.cmd = cmd
        self.fmt = fmt
        self.d0 = d0
        self.d1 = d1
        self.d2 = d2
        self.d3 = d3
        self.id0 = id0
        self.id1 = id1
        self.id2 = id2
        self.id3 = id3
        self.sp = 172

    @property
    def crc(self):
        crc = sum([
            self.st,
            self.mode,
            self.ctr,
            self.res,
            self.ch,
            self.cmd,
            self.fmt,
            self.d0,
            self.d1,
            self.d2,
            self.d3,
            self.id0,
            self.id1,
            self.id2,
            self.id3,
        ])
        return crc if crc < 256 else divmod(crc, 256)[1]

    def to_bytes(self):
        return bytearray([
            self.st,
            self.mode,
            self.ctr,
            self.res,
            self.ch,
            self.cmd,
            self.fmt,
            self.d0,
            self.d1,
            self.d2,
            self.d3,
            self.id0,
            self.id1,
            self.id2,
            self.id3,
            self.crc,
            self.sp
        ])
class NooliteSerial:
    def __init__(self, tty_name):
        self.tty = self._get_tty(tty_name)
    def on(self, ch):
        self.send_command(ch, 2, 2, 0)
        pass
    def off(self, ch):
        self.send_command(ch, 0, 2, 0)
        pass
    def status(self, ch):
        m = self.send_command(ch, 128, 2, 0)
        pass
    def send_command(self, ch, cmd, mode=0, ctr=0, res=0, fmt=0, d0=0, d1=0, d2=0, d3=0, id0=0, id1=0, id2=0, id3=0):
        command = NooLiteCommand(ch, cmd, mode, ctr, res, fmt, d0, d1, d2, d3, id0, id1, id2, id3)
        self.tty.write(command.to_bytes())
        while True:
            bytes_response = list(self.tty.read(117))
            if bytes_response:
                all_responses.append(bytes_response)
                if bytes_response[3] == 0:
                    break
            else:
                break
        return all_responses
    @staticmethod
    def _get_tty(tty_name):
        serial_port = serial.Serial(tty_name, timeout=0.1)
        if not serial_port.is_open:
            serial_port.open()
        serial_port.flushInput()
        serial_port.flushOutput()
        return serial_port
noo_serial = NooliteSerial('/dev/ttyUSB0')
#ch, cmd, mode, ctr
#noo_serial.send_command(1, 15, 2, 0) #включить привязку на канал 1
#noo_serial.send_command(0, 4, 2, 0) #switch
#noo_serial.send_command(0, 2, 2, 0) #turn on
#noo_serial.send_command(0, 3, 2, 0) #Регулировка яркости вверх
#noo_serial.send_command(0, 0, 2, 0) #turn off
#noo_serial.send_command(0, 15, 2, 0) #включить привязку
#noo_serial.send_command(0, 128, 2, 0,0,1) #CMD_Read_State + fmt = 1
#noo_serial.on(0)
#noo_serial.status(0)
#noo_serial.off(0)
#noo_serial.off(0)
#noo_serial.status(0)
#noo_serial.send_command(ch=0,ctr=8, cmd=4, id0=0,id1=0,id2=48,id3=114) #switch noolite ID 0.0.48.114



Используя нужные функции в нужное время, мы можем управлять noolite блоками и получать статус от новых. Так как у меня 99% это старые блоки, мне остается использовать старую схему записи 1 блока в 1 канал, с учетом того, что usb адаптер поддерживает и старые блоки и новые (спасибо разработчикам за совместимость без танцев бубном). На лету можно управлять и получать статус новых блоков и управлять старыми.

До недавнего времени, в доме не было ни одного кнопочного выключателя. Пришлось добавить в гараж свет (я просто добрался туда навести порядок :D ), а так же появился выключатель в подсветке зеркала для макияжа. Зная, что есть силовой блок SB-1-150, я поставил выключатель обычный и подключил блок. Подсветку зеркала сделал из белой плиты, 3w лампочек 4000 К, белый свет. SB-1-150 уникален тем, что он может быть размещен в коробке настенного выключателя, (выключателя) в разрез существующей схемы и подключением кнопочного выключателя к самому блоку.

Именно то, что надо для макияжа моим девочкам :)
image

Pebble


Когда я начал увлекаться автоматизацией, одним из главных факторов было: грамотное и удобное управление.

Управлять со смартфона вроде бы и удобно, но… и не удобно, каждый раз грузить приложение, где маленькие неудобные кнопки, левая реклама или пока доберешься до нажатия кнопки… отпадет все желание. Голосовое управление отпадает, так как это тоже неудобно и странно :) — пусть это останется в сюжетах фантастических фильмов.

image

А я решил задачу по другому — через наручные часы, которые ПОСТОЯННО со мной, не занимают места и сочетают в себе все удобства, мобильность и быстроту управления. Вообщем — Pebble жив! Но самое главное то, что, для часов все ещё можно писать приложения — свои приложения, для управления своими системами автоматизации. Это вообще так-то «бомба».


Трагичность закрытия pebble.com компании (Fitbit выкупил ради патентов весь pebble.com) не отразилось на их производительности и работе. Недавно прошло обновление ios, android — часы отвязали от облачных сервисов pebble (в случае прекращения поддержки) и авторизации.

Визуально — ничего не изменилось, зато остался жить сервис: cloudpebble.net — WTF? Это очень полезная штука. Если Вы можете писать код на JS (и нет желания тратить много времени на C++) — пожалуйста, welcome on board :) — cloud pebble позволяет Вам быстро «накидать» приложение. Ну вот как я сделал. Конечно, производительность JS не стоит сравнивать с C++ (это святое), стерпиться. дА!

Pebble cloud JS code для работы с API
var UI = require('ui');
var ajax = require('ajax');

var noolite = [
    ['ворота','http://your-home-server-ip-address:1183/mqtt/gate/slidegate', 'images/gate.png'],
    ['гараж','http://your-home-server-ip-address:1183/mqtt/gate/garage', 'images/door.png'],
    ['приехали!','http://your-home-server-ip-address:1183/noolite/switch/103', 'images/light.png'],    
    ['выкл все','http://your-home-server-ip-address:1183/noolite/switch/100', 'images/system2.png'],    
    ['1 этаж свет','', 'images/light.png'],
    ['2 этаж свет','', 'images/light.png'],    
    ['выкл 1эт','http://your-home-server-ip-address:1183/noolite/switch/101', 'images/light.png'],    
    ['выкл 2эт','http://your-home-server-ip-address:1183/noolite/switch/102', 'images/light.png'],
    ['вода','', 'images/water.png'],
    ['мусорка','http://your-home-server-ip-address:1183/admin/system/1', 'images/system1.png'],
    ];

var water = [
    ['сенди вода','http://your-home-server-ip-address:1183/admin/poliv/1', 'images/water.png'],
    ['баня вода','http://your-home-server-ip-address:1183/admin/poliv/2', 'images/water.png'],
    ['зона 1 фасад','http://your-home-server-ip-address:1183/noolite/switch/20', 'images/water.png'],
    ['зона 2 фасад','http://your-home-server-ip-address:1183/noolite/switch/21', 'images/water.png'],
    ['зона 3 фасад','http://your-home-server-ip-address:1183/noolite/switch/22', 'images/water.png'],
    ['зона 4 фасад','http://your-home-server-ip-address:1183/noolite/switch/23', 'images/water.png'],    
    ['зона 5 зад','http://your-home-server-ip-address:1183/admin/poliv/switch/5', 'images/water.png'],    
    ['зона 6 зад','http://your-home-server-ip-address:1183/admin/poliv/switch/6', 'images/water.png'],    
    ['зона 7 зад','http://your-home-server-ip-address:1183/admin/poliv/switch/7', 'images/water.png'],    
    ['зона 8 зад','http://your-home-server-ip-address:1183/admin/poliv/switch/8', 'images/water.png'],    
    ['зона 9 зад','http://your-home-server-ip-address:1183/admin/poliv/switch/9', 'images/water.png'], 
];

var light1 = [
    ['коридор свет','http://your-home-server-ip-address:1183/noolite/switch/6', 'images/light.png'],
    ['кухня свет','http://your-home-server-ip-address:1183/noolite/switch/0', 'images/light.png'],
    ['кухня стол свет','http://your-home-server-ip-address:1183/noolite/switch/1', 'images/light.png'],
    ['зал низ свет','http://your-home-server-ip-address:1183/noolite/switch/7', 'images/light.png'],
    ['зал верх свет','http://your-home-server-ip-address:1183/noolite/switch/8', 'images/light.png'],
    ['ванная 1 свет','http://your-home-server-ip-address:1183/noolite/switch/2', 'images/light.png'],
    ['ванная 1 свет','http://your-home-server-ip-address:1183/noolite/switch/3', 'images/light.png'],
    ['гостевая 1 свет','http://your-home-server-ip-address:1183/noolite/switch/4', 'images/light.png'],
    ['топочная свет','http://your-home-server-ip-address:1183/noolite/switch/5', 'images/light.png'],
    ['гараж свет','http://your-home-server-ip-address:1183/noolite/switch/9', 'images/light.png'],
];
    
var light2 = [
    ['спальня свет','http://your-home-server-ip-address:1183/noolite/switch/15', 'images/light.png'],
    ['гардероб свет','http://your-home-server-ip-address:1183/noolite/switch/16', 'images/light.png'],
    ['коридор 2 свет','http://your-home-server-ip-address:1183/noolite/switch/10', 'images/light.png'],
    ['ванная 2 свет','http://your-home-server-ip-address:1183/noolite/switch/11', 'images/light.png'],
    ['гостевая 2 свет','http://your-home-server-ip-address:1183/noolite/switch/12', 'images/light.png'],
    ['Алиса свет','http://your-home-server-ip-address:1183/noolite/switch/13', 'images/light.png'],
    ['Алиса картина свет','http://your-home-server-ip-address:1183/noolite/switch/14', 'images/light.png'],
];

var menu = new UI.Menu({
    sections: [{
        items: [{
            title: '',
            subtitle: ''
        }]
    }]
});
var menu1 = new UI.Menu({
    sections: [{
        items: [{
            title: '',
            subtitle: ''
        }]
    }]
});
var menu2 = new UI.Menu({
    sections: [{
        items: [{
            title: '',
            subtitle: ''
        }]
    }]
});
var menu3 = new UI.Menu({
    sections: [{
        items: [{
            title: '',
            subtitle: ''
        }]
    }]
});
var items = [];
for (var i=0; i<noolite.length; i++) {
    items[i] = {
        title: noolite[i][0], 
        subtitle: '',
        icon: noolite[i][2] 
    };
}    
var items1 = [];
for (var i=0; i<light1.length; i++) {
    items1[i] = {
        title: light1[i][0], 
        subtitle: '',
        icon: light1[i][2] 
    };
}
var items2 = [];
for (var i=0; i<light2.length; i++) {
    items2[i] = {
        title: light2[i][0], 
        subtitle: '',
        icon: light2[i][2] 
    };
}
var items3 = [];
for (var i=0; i<water.length; i++) {
    items3[i] = {
        title: water[i][0], 
        subtitle: '',
        icon: water[i][2] 
    };
}
menu.items(0, items);
menu1.items(0, items1);
menu2.items(0, items2);
menu3.items(0, items3);
menu.show();
menu.on('select', function(e) {
    if (e.itemIndex == 4) {
        menu1.show();
    }
    else if (e.itemIndex == 5) {
        menu2.show();
    }
    
    else if (e.itemIndex ==8) {
        menu3.show();
    }
    
    else {
        
        var url = noolite[e.itemIndex][1]; 
        console.log(url);
        ajax({ 
            url: url, 
            method: 'get'
        },
            function(data) {
                console.log('switched OK');
                             
             },
            
            function(error) {
                // Failure!
                console.log('error');
            }
  
        );
    }
});
menu1.on('select', function(e) {
        var url = light1[e.itemIndex][1]; 
        console.log(url);
        ajax({ 
            url: url, 
            method: 'get'
        },
            function(data) {
                console.log('switched OK');
                             
             },
            
            function(error) {
                // Failure!
                console.log('error');
            }
        );
        
});
menu2.on('select', function(e) {
   
        var url = light2[e.itemIndex][1]; 
        console.log(url);
        ajax({ 
            url: url, 
            method: 'get'
        },
            function(data) {
                console.log('switched OK');           
             },
            
            function(error) {
                // Failure!
                console.log('error');
            }
        );
});
menu3.on('select', function(e) {
   
        var url = water[e.itemIndex][1]; 
        ajax({ 
            url: url, 
            method: 'get'
        },
            function(data) {
                console.log('switched OK');              
             },

            function(error) {
                // Failure!
                console.log('error');
            }
        );
});



Код пишется, компилируется прямо на сайте cloud Pebble и через телефон, скачивая скомпилированное приложение, можно установить на часы — за секунды. Все настолько просто, что справится любой юный автоматизатор ;)

Жаль… очень жаль, что Pebble прекратило существование и на текущий момент альтернативы я не вижу. Pebble Time всегда будут в наших сердцах!

MQTT


В прошлом году я познакомился с таким замечательным протоколом как MQTT (История: Первая версия протокола была разработана доктором Энди Станфорд-Кларком (IBM) и Арлен Ниппер (Arcom) в 1999 году и опубликована под роялти-фри лицензией. Спецификация MQTT 3.1.1 была стандартизирована консорциумом OASIS в 2014 году. Ссылка).

Есть много информации как работает протокол и какие есть клиенты… и был сильно разочарован тем, что настоящих клиентов для мобильных приложений — нет, только на android.

Понимая, что отсутствие хорошего мобильного приложения, это весьма большая проблема (дыра) в области IoT (очень многие говорят, а делают очень мало....) — я со своей командой, на работе, решили создать клиент для android, ios, wp, чтобы он соответствовал всем критериям и был удобным. О клиенте отдельно я напишу чуть позже, а так же том, как мы подружили ESP8266+MTRF64 (Noolite) и подготовили Nodemcu прошивку. Будет здорово, удобно, дешево и красиво! Следите за новостями приложения тут.

image

Управлять Noolite освещением теперь можно будет без всяких домашних серверов и usb адаптеров за 50-100$!

Общая схема работы домашней автоматизации


Все ещё существует следующая схема:

Видеонаблюдение: xeoma видеонаблюдение [ip камеры]
Сервер на системном блоке: nginx+gunicorn+python+mqtt broker
Управление: Pebble watch + MQTT client
Модули управления (ноды системы): ESP8266 + оптопары \ датчики ds18b20, dht11[22]

Ввиду того, что я увидел в MQTT протоколе множество удобств, начиная от архитектуры подписки и мгновенным общением с конечными IoT устройствами, заканчивая тем, что MQTT сообщения могут пролетать через роутер, без «проброса» всяких там портов и танцами с бубном. Удобно! Весело! Задорно :)

Все это привело меня к децентрализации системы, то есть уход от одного «домашнего корчвагена» и переход на множество так называемых нодов и использование облачного MQTT брокера (есть бесплатные MQTT брокеры, например: mqtt.ximxim.com (на сайте логин и пасс для доступа) ) — так как esp8266 решают все задачи, а она в свою очередь работают через wifi по протоколу MQTT.

Учитывая то, что MQTT Buddy будет предоставлять сервис сценариев, я вообще не буду думать о том, что мне надо писать какие то домашние сценарии, я просто буду создавать их в cloud решении и это и будет настоящий IoT и он работает! От слов к делу!

ESP8266


Когда я познакомился с этой платой разработки, меня сразу подкупило то, что плата маленькая, есть поддержка языка программирования LUA на пошивке Nodemcu. То, что Вам надо + MQTT модуль есть. В автоматизации, простые и надежные решения — это основа. Стоимость от 2$ до 5$ за плату (за 5 модель сразу с usb адаптером на борту) позволяет быстро разворачивать подсистемы.

Подключение по WiFi быстрое, возможностей масса. Например: управление воротами\гаражом\поливом\освещением. У меня 30% полива газонов работает от системы Noolite (блоки сухого контакта), остальные 70% от esp8266 development board с управлением через LUA язык по протоколу MQTT.

Пример кода на LUA для esp8266, получение ip и вызов файла работы с MQTT
--load credentials
dofile("credentials.lua")
function init(name, pass)
    wifi.setmode(wifi.STATION)
    wifi.sta.config(name, pass)
    wifi.sta.connect()
    tmr.alarm(0, 1000, 1, function() 
            if wifi.sta.getip()== nil then 
                print("IP unavaiable, Waiting...") 
                                
            else 
                tmr.stop(0)
                print("Config done, IP is "..wifi.sta.getip())
                print("mac : "..wifi.sta.getmac())
                
                dofile("mqtt.lua")
            end 
    end)

end
print("START!")
init(SSID,PASSWORD)


— mqtt.lua file


local door = 7 -- gpio13
local window = 6 -- gpio12
local cooler = 5 --gpio14
local led = 4 --GPIO2 board led! LOW == turn ON

local light1 = 8 --gpio 15
local light2 = 1 --gpio 5
local light3 = 2 -- gpio 4

function register_myself()  
    m:subscribe("mqtt_buddy/#",0,function(conn) 
    print ("subscribed to Xim mqtt.ximxim.com server")
    end)    
end

m = mqtt.Client("MQTT_BUDDY_SHOW_ROOM", 120, MQTT_USER, MQTT_PASS)
m:on("connect", function(client) print ("connected to Xim mqtt.ximxim.com server") end)
m:on("offline", function(client) reconnect_mqtt() end)
m:on("message", function(client, topic, data) 
        --print(topic.." data:"..data)
    
        if topic == "mqtt_buddy/window" and data == "1" then
        
            print "open-close window..."
            gpio.write(window, gpio.HIGH)
            gpio.write(led, gpio.LOW)    
            
            tmr.alarm(1, 1000, tmr.ALARM_SINGLE, function() 
                gpio.write(window, gpio.LOW)
                gpio.write(led, gpio.HIGH)    
                print "command to close\open window is sent!"
                end)
                
         elseif topic == "mqtt_buddy/door" and data == "1" then
        
            print "open-close door..."
            gpio.write(door, gpio.HIGH)
            gpio.write(led, gpio.LOW)    
            
            tmr.alarm(2, 1000, tmr.ALARM_SINGLE, function() 
                gpio.write(door, gpio.LOW)
                gpio.write(led, gpio.HIGH)    
                print "command to close\open door is sent!"
                end)
                
         elseif topic == "mqtt_buddy/cooler" then
            if data == "1" then
                print "switch on fan..."
                gpio.write(cooler, gpio.HIGH)
                gpio.write(led, gpio.LOW)    

            else
                print "switch off fan..."
                gpio.write(cooler, gpio.LOW)
                gpio.write(led, gpio.HIGH)    

            end

        elseif topic == "mqtt_buddy/light1" then
            if data == "1" then
                print "switch light1 ON..."
                gpio.write(light1, gpio.HIGH)
                gpio.write(led, gpio.LOW)    

            else
                print "switch light1 off..."
                gpio.write(light1, gpio.LOW)
                gpio.write(led, gpio.HIGH)    

            end

        elseif topic == "mqtt_buddy/light2" then
            if data == "1" then
                print "switch light2 ON..."
                gpio.write(light2, gpio.HIGH)
                gpio.write(led, gpio.LOW)    

            else
                print "switch light2 off..."
                gpio.write(light2, gpio.LOW)
                gpio.write(led, gpio.HIGH)    

            end

        elseif topic == "mqtt_buddy/light3" then
            if data == "1" then
                print "switch light3 ON..."
                gpio.write(light3, gpio.HIGH)
                gpio.write(led, gpio.LOW)    

            else
                print "switch light3 off..."
                gpio.write(light3, gpio.LOW)
                gpio.write(led, gpio.HIGH)    

            end
        end    
    
 end)
m:connect(MQTT_SERVER, MQTT_SERVER_PORT, 0, function(conn) register_myself() end) 



Проблема


Обращаясь к огромному сообществу думающих людей, хотел задеть крайне важную тему, а точнее проблему, которую хочу решить, но не хватает времени на более глубокие исследования \ знаний.

Суть: при децентрализации, остается видеонаблюдение, которое так или иначе ТРЕБУЕТ наличие host машины для (минимум) передачи source images либо на сервера видеонаблюдения (например ivideon) или вообще обрабатывать видео на домашней машине, как xeoma (хотя у них тоже есть cloud) — так или иначе — надо «ПРОБРАСЫВАТЬ» видео потоки, картинки на конечные вычислительные мощности (cloud решения) — или наоборот — сделать стриминг простой.

Есть мысли получать source images с камеры (тут тоже есть проблема, не в каждой камере есть URL для получения картинки с камеры и вообще непонятно, как другие узнают этот урл....) и пробрасывать в MQTT канал, где поддерживаются бинарные данные (то есть картинку можно легко передать через mqtt протокол в бинарном виде).

Возможно, кто-то уже пробовал реализовать такие вещи = ESP8266 + IP web cam?
Отзовитесь плиз (bogdanovich.alex[@]gmail.com). Буду очень благодарен!

При реализации проброса, отпадет вопрос домашнего сервера. Зачем? Потому что он электричество кушает и топочную мне греет :)

image

Всем позитивного дня и хорошего настроения!
Поделиться с друзьями
-->

Комментарии (19)


  1. GDI
    20.04.2017 11:09

    ESP8266 слабовата для камер, но есть решения на дешевых китайских роутерах http://zftlab.org/pages/2016031400.html В статье что то я не нашел, но просто знаю, что к этому роутеру на этой прошивке можно подключить почти любую веб-камеру и картинки слать.


    1. GDI
      20.04.2017 11:14

      Во, нашел, есть раздел «Настройка USB UVC камеры:»


      1. Alex_Bogdanovich
        20.04.2017 11:28

        Спасибо за информацию — почитаю.


        1. Shyster
          20.04.2017 12:47
          +1

          Есть проект на ESP32 https://github.com/igrr/esp32-cam-demo b
          https://www.reddit.com/r/esp32/comments/64anpt/wifi_range_testing_with_esp32_webcam_10_km_using/


  1. iig
    20.04.2017 11:14

    ESP8266 + IP web cam

    Памяти в ESP8266 маловато для передачи картинки. Почему не взять камеру с WIFI?


    1. Alex_Bogdanovich
      20.04.2017 11:31

      Можно взять и WiFi камеру — Если Вы намекаете на то, что в Wifi камере всегда будет явно указан source image path — тогда да. Накрайняк, брать проверенные камеры (не OEM или NONAME).

      В текущих камерах моих (за 15$ ip web Ethernet only) — там нет явной настройки :( на путь к получения картинки.

      ESP8266 в силах ежесекундно забирать картинку с камеры и прокидывать её в MQTT. Если рассматривать обработку видео на ESP — этот момент отпадает, ввиду слабости.

      Спасибо.


      1. iig
        20.04.2017 12:10

        ESP8266 в силах ежесекундно забирать картинку с камеры и прокидывать её в MQTT

        50 К памяти достаточно?


        1. Alex_Bogdanovich
          20.04.2017 14:39

          не могу предоставить точный ответ сейчас и правильный, нужен инвестигейт. есть esp32, которая более мощнее и больше памяти. Знаю, что картинка с камеры приемлемого качества, не будет весит 1мб, меньше.

          спасибо.


          1. iig
            20.04.2017 15:05

            Но и не 50 КБ же. Если картинка в память не поместится, извернуться можно… Но нужно ли?


        1. past
          20.04.2017 15:19

          У esp8266 сильные ограничения по размеру payload. По моим измерениям — 500 байт.


      1. dkv
        20.04.2017 19:21

        Я не пойму, где именно Вы пытаетесь в этих камерах искать указание source path? Да, не все китайские камеры отдают превьюшки. Но это легко проверить для любой хоть cколь-нибудь адекватной камеры с поддержкой ONVIF: запускаете ONVIF Device Manager, в верхние поля вводите пару логин/пароль, он находит вашу камеру (если не находит, то добавляем ручками), получает с неё данные и рисует вам превьюшку. Если превьюшку нарисовал — снифаем URL и используем. Если нет, то простите, но надо было брать другую камеру :) Лимиты по памяти в ESP наверняка можно обойти передачей не всей картинки, а серией приём/передача небольшого буфера. Грубо говоря, приняли 4 пакета, 4 пакета и отправили. И далее, пока не перекачаем всю картинку. Но просто принимать-отправлять картинки через интервалы или по запросу извне или по датчику — это одно, но неплохо бы ещё и реализовать подписку на события детектора движения (делается через тот же ONVIF путём серии SOAP запросов) и вот это уже всё в комплексе обрабатывать. Запилите подобное и напишите статью — я и впрямь поверю в то, что гиктаймз ещё жив :)


  1. kondr1
    20.04.2017 11:38
    +1

    CloudPebble еще не скоро исчезнет. Есть исходники https://github.com/pebble/cloudpebble


  1. leon76
    21.04.2017 09:01
    +1

    В шоуруме жалюзи заело :)


    1. Alex_Bogdanovich
      21.04.2017 09:02

      спасибо — fixed. через шоу рум прошло уже порядка 1.000 человек — первый косяк, который был на быструю руку пофикшен неделю назад, но быстрофикс не сработал, исправили. спасибо!

      mqtt.ximxim.com/show-room/ продолжает работать


  1. ianohin
    21.04.2017 10:06

    Мне видится удобным управление через Telegram. Тут писали уже. Все никак не соберусь подключить себе к дому


    1. Alex_Bogdanovich
      21.04.2017 10:12

      Согласен, что Telegram, возможно, хороший мессенджер, но это его «возможность», но никак не основное предназначение. Пробрасывать сообщения из телеграма в mqtt, это создание дополнительного узкого места (стыка).

      Прямая работа с протоколом в приложении, предназначенным для этого, гораздно удобнее. Да и удобней кликать на кнопку, которая для этого создана, чем посылать постоянно messages (писать) — что бы включить свет ;) — ну… побаловаться — да, но никак не на постоянку.


  1. amazaev
    25.04.2017 12:09
    +1

    Сейчас борюсь с несколькими китайскими камерами. Onvif на них есть, дешевый китайский же регистратор нормально записывает потоки, но… ни на камерах, ни на регистраторе никак не работает оповещение по почте при детектировании движения. Ни камеры, ни регистратор не могут SMTP, хотя и заявлено. (Google — нет, локальный Exim и в открытую и под SSL — тоже нет, сервер ругается).

    В результате выяснилось, что они всё-таки могут ftp. Сейчас запустил рядом raspberry 3, при появлении файла в ftp папке incron mutt-ает его на gmail (работает). Пробую ещё и на telegram.

    Вылезла другая проблема: проход кошки генерит десяток оповещений, а дождь… Тогда надо отключать камеры…

    Камеры:
    https://ru.aliexpress.com/item/Free-Shipping-Sony-2-4MP-Megapixel-Full-HD-1080P-Onvif-2-0-Zoom-Varifocal-Outdoor-Security/32262005025.html?spm=2114.13010608.0.0.SjAkxN
    https://ru.aliexpress.com/item/1-3-SONY-Full-1080P-24IR-indoor-Vandalproof-IR-Dome-indoor-IP-Camera-High-resolution-Onvif/32297690252.html?spm=2114.13010608.0.0.SjAkxN

    Регистратор примерно такой (свой покупал в РФ переплатив втрое)
    https://ru.aliexpress.com/item/Onvif-H-264-P2P-High-Definition-Mini-1080P-Full-HD-4CH-8CH-Network-Video-Recorder-IP/32547115270.html?spm=2114.03010208.3.1.33m8hn&ws_ab_test=searchweb0_0,searchweb201602_3_10152_10065_10151_10068_10136_10137_10060_10138_10155_10062_10156_10154_10056_10055_10054_10059_10099_10103_10102_10096_10148_10169_10147_10052_10053_10142_10107_10050_10051_10084_10083_10119_10080_10082_10081_10110_10111_10112_10113_10114_10181_10037_10032_10078_10079_10077_10073_10070_10123_10120_10127_10124_10125,searchweb201603_1,ppcSwitch_5&btsid=8c6b886f-b6fe-46fe-9d87-afb9f3ba1495&algo_expid=d6f73a79-ab73-4c49-8544-7d5eca0296f2-0&algo_pvid=d6f73a79-ab73-4c49-8544-7d5eca0296f2


    1. iig
      25.04.2017 12:43

      Ни камеры, ни регистратор не могут SMTP, хотя и заявлено. (Google — нет, локальный Exim и в открытую и под SSL — тоже нет, сервер ругается)

      Возможно, у китайцев свое понимание SMTP. Раз сервер ругается — какая-то попытка связи есть; посмотрите траффик wireshark'ом.


      1. amazaev
        25.04.2017 13:00

        на SMTP 25 Exim сначала говорил что неправильная последовательность запросов (сейчас точно не вопроизведу) — пофиксилось правкой конфига, но после этого опять мусор. SSL — мусор, handshake не проходит.

        В общем, я с FTP это обошел, стало не важно, и плюс: я же на Raspberry могу управлять, от кого пересылать оповещения, а от кого сейчас не надо: например при дожде или тумане уличная камера бесполезна с точки зрения автоматических оповещений, но пусть записывает.