Умный дом: Domoticz.

Тема в разделе "Глядите, что я сделал", создана пользователем ИгорьК, 17 сен 2017.

Метки:
  1. star003

    star003 Нерд

    Отправка данных с esp8266 получилась:
    Код (C++):
    #include <ArduinoJson.h>
    #include <ESP8266WiFi.h>
    #include <PubSubClient.h>
    const char* ssid = "*";
    const char* password =  "*";
    const char* mqtt_server = "*";
    const int mqtt_port = 1883;
    const char* mqtt_user = "";
    const char* mqtt_pass = "";

    long lastMsg     = 0;
    int     value = 0;
    char     msg[50];
    WiFiClient wclient;  
    PubSubClient client(wclient, mqtt_server, mqtt_port);
    void setup() {
        Serial.begin(115200);
        Serial.println();
        WiFi.begin(ssid, password);
        while (WiFi.status() != WL_CONNECTED) {
       
            delay(500);
            Serial.println("Connecting to WiFi..");
     
        }
        Serial.println("Connected to the WiFi network");
        //client.setServer(mqttServer, mqttPort);
        while (!client.connected()) {
            Serial.println("Connecting to MQTT...");
            if (client.connect(MQTT::Connect("art_esp8266_nasos")
                             .set_auth(mqtt_user, mqtt_pass))) {
                Serial.println("connected");
            } else {
                Serial.print("failed with state ");
                //Serial.print(client.state());
                delay(2000);
            }
        }
    }//setup
    void loop() {
     
        long now = millis();
        if (now - lastMsg > 4000) {
         
            lastMsg = now;
            ++value;
            StaticJsonBuffer<300> JSONbuffer;
            JsonObject& JSONencoder = JSONbuffer.createObject();
            //{ "idx" : 3, "nvalue" : 0, "svalue" : "12.3" }
            JSONencoder["idx"] = 5;
            JSONencoder["nvalue"] = 0;
            snprintf (msg, 75, "w #%ld", value);
            JSONencoder["svalue"] = msg;
            //JsonArray& values = JSONencoder.createNestedArray("svalue");
            //values.add(10);
            char JSONmessageBuffer[100];
            JSONencoder.printTo(JSONmessageBuffer, sizeof(JSONmessageBuffer));
            Serial.println("Sending message to MQTT topic..");
            Serial.println(JSONmessageBuffer);
            if (client.publish("domoticz/in", JSONmessageBuffer) == true) {
         
                Serial.println("Success sending message");
         
            } else {
         
                Serial.println("Error sending message");
         
            }
         
        } //now - lastMsg
        client.loop();
    }//loop
    Вопрос: есть ли способ воздействия на switch по средствам mqtt ? Пока только увидел выполнение скриптов при переключении.
    (В прочем,если подумать то погасить фонарь на столбе по расписанию - можно сценарием)
     
    ИгорьК нравится это.
  2. star003

    star003 Нерд

    1. Создал выключатель, привязал скрипты на включение , отключение. Получил ошибку:Error executing script command (/home/pi/domoticz/scripts/00014056_off.sh). returned: 32256

    Решение chmod 777 00014056_off.sh

    2. Путь прописываем не полностью. Если файл скрипта уже в папке scrips : script://00014056_off.sh
     
    petr0vsk нравится это.
  3. ИгорьК

    ИгорьК Гуру

    Отправьте на Домотикз в топик domoticz/in следующее:
    Код (Lua):
    {"command": "switchlight", "idx": 24, "switchcmd": "On"}
    И выключатель с idx 24 включится.
     
    Последнее редактирование: 29 сен 2017
  4. ИгорьК

    ИгорьК Гуру

    Перемудрили Вы что-то. Все работает штатными средствами.

    Хотя если парсинг json ардуиноЙaзыком вызывает проблемы, то да, можно и так.
    Скрипт, безусловно, следует делать исполняемым.
     
    Последнее редактирование: 29 сен 2017
  5. ИгорьК

    ИгорьК Гуру

    Самный простой способ затолкать Domoicz в InfluxDB - сделать так:

    upload_2017-10-2_14-59-40.png


    upload_2017-10-2_15-45-50.png

    В поле Database записать:

    Код (C++):
    domoticz&u=User&p=Password
    А слева выбирать элементы для добавления в базу:

    upload_2017-10-2_15-42-28.png
     
    Последнее редактирование: 2 окт 2017
  6. star003

    star003 Нерд

    Для тех, кто захочет обрабатывать события визуальным редактором советую прочитать сначала это: https://github.com/domoticz/domoticz/issues/1804
    Убил несколько часов на задачу инвертирования значения переменной и результатом шокирован.

    Код (C++):
    if (p ==0) {
    p=1;
    }
    else if (p==1) {
    p=0;
    }
    Очень не хочется lua изучать , но видимо придется
     
  7. DIYMan

    DIYMan Guest

    Потратьте немного времени - язык годный, на самом деле ;) Там практически всё очевидно, главная сложность в понимании, имхо - концепция метатаблиц (одновременно - это и главная фича языка).
     
    ИгорьК нравится это.
  8. ИгорьК

    ИгорьК Гуру

    Никогда не обрабатывал события визуальными редакторами любых мастей. Это сильно связанные руки.
    А Lua следует учить: он и для Domoticz и для ESP-8266.
    И на порядок проще АрдуиноЙазыка.
    Смотрите мою тему о Lua в этом разделе.
     
    Последнее редактирование: 2 окт 2017
  9. ИгорьК

    ИгорьК Гуру

    Без метатаблиц можно долго обходится в ESP-8266.
     
  10. DIYMan

    DIYMan Guest

    Чой-то решил поностальгировать, откопал старые исходники казуалки, что делали с ребятами когда-то, нашёл кой-чего интересного теоретически: реализацию алгоритма A* (поиск пути с обходом препятствий) и нахождение точек для кривой Безье, всё на Lua, ессно. Открыл, посмотрел, прослезился - я так раньше мог, оказывается :) Кстати сказать, на первой игрухе заработали аж тыщ 20 рублей - смех и грех, зато хоть скилл немного пополировал :)

    Код (Text):
    -------------------------------------------------------------------------------------
    -- класс кривой безье
    -------------------------------------------------------------------------------------
    Bezier = {}
    -------------------------------------------------------------------------------------
    function Bezier:New() -- construct


        local instance = {}

        instance.Points = {}
        instance.SourcePoints = {}

        setmetatable(instance,self)

        self.__index   = self

        return instance

    end
    -------------------------------------------------------------------------------------
    function Bezier:bsplinePoint(t, sp, cp, ep) -- вычисляет точку на сплайне

        local result = {x = 0, y = 0}
        local ax = sp.x + ((cp.x - sp.x) * t)
        local ay = sp.y + ((cp.y - sp.y) * t)
        local bx = cp.x + ((ep.x - cp.x) * t)
        local by = cp.y + ((ep.y - cp.y) * t)
       
        result.x = ax + ((bx - ax) * t)
        result.y = ay + ((by - ay) * t)
       
        return result

    end
    -------------------------------------------------------------------------------------
    function Bezier:ClassicCurve(sp, cp, ep,total_points)  -- создает набор точек по классической схеме:
                                                            -- sp, cp, ep - контрольные точки - start, control, end


        self.PointsTotal = total_points -- кол-во точек в кривой
        self.Points = {} -- очищаем массив точек
        local cntr = 1
       
        while cntr <= total_points do
            local t = (1/total_points)*cntr
            local coord = self:bsplinePoint(t, sp, cp, ep)
            table.insert(self.Points,0,coord)
            cntr = cntr + 1
        end -- while
    end
    -------------------------------------------------------------------------------------
    function Bezier:CreateCurve(x,y,tox,toy,total_points,curve_height) -- схема с указанием высоты дуги
    -- (перпендикуляр к отрезку между двумя точками, вычисляется хитромудро)

        self.x = x
        self.y = y
        self.PointsTotal = total_points -- кол-во точек в кривой
        self.CurveHeight = curve_height -- высота дуги
       
        -- готовим параметры
       
        self.Points = {} -- очищаем массив точек
       
        local h = self.CurveHeight -- параметр подъема дуги
        self.SourcePoints = {}
       
        local pt2xoffs = self.x -tox
       

        -- заполняем массив точек
        local cntPoints = self.PointsTotal -- кол-во точек всего
        local step = 1.0/cntPoints -- дельта изменения t
        local t = 0
       
        local cntr = 0
        while cntr < cntPoints do
       
            -- вычислили точку

            self.SourcePoints[0] = {["x"] = self.x,["y"] = self.y}
            self.SourcePoints[1] = {["x"] = self.x - pt2xoffs,["y"] = self.y - h}
            self.SourcePoints[2] = {["x"] = tox,["y"] = toy}
           

            local coord = self:BezierCurve(2,t)
            t = t + step
            cntr = cntr + 1
           
            -- добавляем точку в массив
            table.insert(self.Points,0,coord)
        end
       
       

    end
    -------------------------------------------------------------------------------------
    function Bezier:BezierCurve(n,t) -- вычисляет точку для кривой Безье

        local x = 0;
        local y = 0;
        local i = 0;
        local c = 0;
        local p = 0;

        c = 1;
        while i <= n do
            self.SourcePoints[i]["x"] = self.SourcePoints[i]["x"] * c;
            self.SourcePoints[i]["y"] = self.SourcePoints[i]["y"] * c;
            c = (n - i) * c / (i + 1);
           
            i = i + 1;
        end
       
        p = 1;
        i = 0;
       
        while i <= n do
            self.SourcePoints[i]["x"] = self.SourcePoints[i]["x"] * p;
            self.SourcePoints[i]["y"] = self.SourcePoints[i]["y"] * p;
            p = p * t;
            i = i + 1;
        end
       
        p = 1;
        i = n;
       
        while i >= 0 do
            self.SourcePoints[i]["x"] = self.SourcePoints[i]["x"] * p;
            self.SourcePoints[i]["y"] = self.SourcePoints[i]["y"] * p;
            p = p * (1 - t);
           
            i = i - 1;
        end
       
        x = 0;
        y = 0;
        i = 0;

        while i <= n do
            x = x + self.SourcePoints[i]["x"];
            y = y + self.SourcePoints[i]["y"];
           
            i = i + 1;

        end

        local t_res = {["x"] = x, ["y"] = y};
        return t_res;


    end
    -------------------------------------------------------------------------------------
     
     
    ИгорьК нравится это.
  11. ИгорьК

    ИгорьК Гуру

    Придется:

    Код (Lua):
    function invert(p)
        return (p==1 and 0 or 1)
    end
    print(invert(1))
    print(invert(0))
     
  12. ИгорьК

    ИгорьК Гуру

    На заметку. Общий способ передачи MQTT информации на Domoticz - отправка json-комплекта типа
    Код (Javascript):
    {"idx":39,"nvalue":0,"svalue":"15.5"}
    где idx - идентификатор принимающего компонента, nvalue и svalue (типа) цифровые и текстовые данные, но тут же начинаются исключения, которые описаны здесь, а если нет, то разбираться здесь.
    Все это побеждаемо, но ОБЩУЮ логику пока не нащупал.

    К чему это пост?
    А к тому, что есть шанс убиться, при попытке отправить данные датчика влажности.
    Инфо по нему находится здесь.
    Вроде все просто:
    Код (Javascript):
    {"idx":37,"nvalue":81.3,"svalue":"3"}
    Не пройдет! Лог будет все время выдавать ошибку:
    upload_2017-10-4_12-29-36.png

    И вы не догадаетесь долго в чем причина! А в том, что nvalue ЗДЕСЬ принимает ТОЛЬКО ЦЕЛЫЕ ЧИСЛА!
    Таким образом,
    Код (Javascript):
    {"idx":37,"nvalue":81,"svalue":"3"}
    с легкостью проходит.

    А вот как выгядит задница попугая для любителей "веселых картинок"
    upload_2017-10-4_12-37-12.png

    upload_2017-10-4_12-38-34.png
     
    Последнее редактирование: 4 окт 2017
    petr0vsk нравится это.
  13. star003

    star003 Нерд

    С датчиком влажности похоже не просто.
    mosquitto_pub -h 127.0.0.1 -m '{ "idx" : 20, "nvalue" : 40, "svalue" : "40" }' -t 'domoticz/in'
    не дает эффекта. Бился то же вчерашний день

    Решение: mosquitto_pub -h 127.0.0.1 -m '{ "idx" : 20, "nvalue" : 40, "svalue" : "40%" }' -t 'domoticz/in'

    Добавление % - сработало
     
    Последнее редактирование: 4 окт 2017
  14. ИгорьК

    ИгорьК Гуру

    Не знаю что сказать... У меня заработало именно так как описал.
    По документации здесь должно быть число от 0 до 3 как текст и выдавать:
    Код (Javascript):
    Humidity_status can be one of:
    0=Normal
    1=Comfortable
    2=Dry
    3=Wet

    upload_2017-10-4_14-17-18.png

    у меня idx 37, 38 - датчики влажности. Не ругается:
    upload_2017-10-4_14-31-38.png
     
    Последнее редактирование: 4 окт 2017
  15. ИгорьК

    ИгорьК Гуру

    http://www.ispyconnect.com/sources.aspx - база данных по камерам, как их соединять.

    Еще один прикол. Камера установилась и включилась легко. Но чтобы ее привязать к плану - требуется что-то промежуточное. Тогда ссылка на камеру появляется в управляющем окошке промежуточного устройства, которое к камере отношения не имеет. Прикол да и только. Вот Каталонцы дают... :)

    upload_2017-10-4_14-29-11.png

    upload_2017-10-4_14-27-11.png

    upload_2017-10-4_14-27-38.png

    Или так:

    upload_2017-10-4_14-35-41.png

    upload_2017-10-4_14-35-57.png
     
    Последнее редактирование: 10 апр 2018
  16. ИгорьК

    ИгорьК Гуру

    Жестокий временный костыль, но, может, кому будет полезен.
    В частности - правилами публикации.

    Суть явления. Медленно, неспеша перетекаю на Domoticz.
    Поскольку все устройства (за исключением одного) управляются самостоятельно, ничто не мешает параллельно с ОпенХаб хватать данные с брокера MQTT, переделывать в формат Domoticz и на нем неспеша формировать те же устройства, что OH.

    Поэтому временно, на один из домашних терометров на ESP-8266 навесил задачу такой трансформации.
    В частности, кусок информации бросается на Народный мониторинг отдельным устройством, которое шлет его и на брокер в топики "narod/..."

    Мой термометр подписан на этот топик, и по приходу данных отправляет их в глобальные переменные gdata и gtopic после чего вызывает dofile('analizeNarod.lua').

    Вот этот файл - analizeNarod.lua и показываю здесь.
    Код (Lua):
    -- Глоабальные топик и сообщение немедленно в локальные
    local msg = gdata
    local top = gtopic

    -- Глобальная(!!!) таблица для публикации перекодированных сообщений
    if not tableFoDomoticz then tableFoDomoticz = {} end
    -- Чтобы не было накладок публикации
    -- Каждый "прибывший" топик заполняет эту таблицу
    -- а публикация осуществояется до ее исчерпания
    pubflag = false

    -- Таблица перекодировки топиков в соответствующие idx
    -- каждая строка: название топика в ОН = idx элемента Domoticz
    local idxbase = {
        -- temprature
        ntbme               = 41,
        n280317EA0500000D   = 42,
        n28AFFED50400007C   = 43,
        n28B1AED5040000A1   = 44,

        -- humidity
        nhumi   = 45, --

        -- pressure
        npres   = 48,

        -- raw data
        nheap   = 49,

        -- switches
        nblr    = 46,
        nswitch = 50,

        -- wind
        nwind   = 51
    }
        -- В ОН и Domoticz разные команды включателей - перекодируем
        if msg == "ON" then msg = "On" end
        if msg == "OFF" then msg = "Off" end

        -- Убираем часть "narod/" из топика
        -- и начинаем все с буквы "n" потому что
        -- топики температуры приходят в виде стринга но начинающегося
        -- с цифры, что для таблиц недопустимо
        top = 'n'..string.sub(top, 7)
        print("top: ", top)
        print(msg)

        -- Каждую пару idx и данные вставляем в таблицу "tableFoDomoticz"
        -- ТАБЛИЦЕЙ {idx, данные}
        table.insert(tableFoDomoticz, {idxbase[top], msg})

        -- Функция публикации на брокер в формате Domoticz
    local function pubdata()
        -- Начали публикацию - не допускаем поторных вызовов этой функции
        -- за пределами ее самой рекурсивно
        pubflag = true
        -- Если в таблице на публикацю что-то есть
        if #tableFoDomoticz ~= 0 then
            -- Изымаем один элемент
            local para = table.remove(tableFoDomoticz)
            -- Это выключатели, публикация по их правилам
            if para[2] == "On" or para[2] == "Off" then
            -- {"command": "switchlight", "idx": 2450, "switchcmd": "On", "level": 100 }
                m:publish("domoticz/in",'{"command": "switchlight","idx":'..para[1]..',"switchcmd":"'..para[2]..'"}',0,0,pubdata)
            -- Это влажность
            elseif para[1] == 45 then
                m:publish("domoticz/in",'{"idx":'..para[1]..',"nvalue":'..math.floor(para[2])..',"svalue":"0"}',0,0,pubdata)
            -- Это давление
            elseif para[1] == 48 then
                m:publish("domoticz/in",'{"idx":'..para[1]..',"nvalue":0,"svalue":"'..para[2]..';0"}',0,0,pubdata)
            -- Это ветер
            elseif para[1] == 51 then
                m:publish("domoticz/in",'{"idx":'..para[1]..',"svalue":"0;SW;'..(para[2]*10)..';0;0;0"}',0,0,pubdata)
            -- Это все остальное - температура
            else      
                m:publish("domoticz/in",'{"idx":'..para[1]..',"nvalue":0,"svalue":"'..para[2]..'"}',0,0,pubdata)
            end
        -- Иначе все опубликовано, разрешаем следующую публикацию
        else
            pubflag = false
        end
    end

    -- Проверяем, не идет ли публикация
    if not pubflag then
        pubdata()
    end
     
    Последнее редактирование: 6 окт 2017
    sys нравится это.
  17. sav13

    sav13 Нуб

    Здравствуйте
    Поставил domoticz на Orange PI через curl
    MQTT работает, а вот создать выключатель, запускающий скрипты не могу
    Какой то модуль нужно доустанавливать?
     
  18. ИгорьК

    ИгорьК Гуру

    Не очень понял вопрос - Вы просто не можете создать выключатель?
    Любой выключатель может запускать скрипты, абсолютно любой.
     
  19. ИгорьК

    ИгорьК Гуру

    В копилку, формат отправки MQTT некторых команд на устройства Domoticz:
    Код (Lua):
    {"command":"switchlight","idx":57,"switchcmd":"On","level":30} -- Selector Switch
    {"idx":53,"nvalue":0,"svalue":"126"}  -- Counter
    {"idx":59,"nvalue":3,"svalue":"Не Фигня!"} --  Alert
    {"idx":58,"nvalue":0,"svalue":"Это текст"} -- Text
    {"idx":54,"nvalue":0,"svalue":"22"}  -- Counter Incremental
    {"idx":55,"nvalue":0,"svalue":"22.7"} -- Custom Sensor


    {"idx":129,"nvalue":0,"svalue":"15.5;22;1;900;1"}  -- Датчик температура, влажность, давление.
     
    Последнее редактирование: 25 май 2018
    Palkin81 нравится это.
  20. petr0vsk

    petr0vsk Нерд

    [​IMG]
    В поисках замены openhab наткнулся на такую занятную вещь - сервер приложений для IoT полностью написанный на Lua-C. Фронтенд на Lua Server Pages, бэкэнд на Lua-C. Как минус - нет такого количества биндингов с различными IoT протоколами как в Domoticz. С другой стороны mqtt, json, Modbus, SQM, WebSocket - в наличии. Есть сборка под Raspberry pi. Встроенный IDE для разработки LSP.
    И все это на чистом как слеза Lua!!! Что еще нужно убежденному Luнатику...
    https://makoserver.net/
    https://realtimelogic.com/ba/doc/?url=auxlua.html#tracelogger