Arduino, ESP8266 Lua, Raspberry Pi 2 && OpenHab. Умный дом: азы управления.

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

  1. ИгорьК

    ИгорьК Гуру

    О таймере tmr.now(). ESP-8266.
    Собственно, по ссылке все написано, но как-то вскользь и скромно:
    То есть, таймер возвращает системное время в микросекундах, Предел счета - 31 бит. После достижения - таймер слетает в ноль. Это имеет значение, если вы используете эту функцию для подавления дребезга или "удушения(?)" GPIO.

    Кроме того, достаточно давно был опубликован код подавления дребезга, который и был скопипащен сюда (естественно со ссылкой на первоисточник).

    На тестировании код отлично справляется со своей задачей. Однако, со временем устройство подвисает.
    Понять источник не удавалось. Наконец, ситуация прояснилась.
    Все дело как раз в этом таймере.
    • Таймер слетает в ноль на 31 битах,
    • сам счетчик - 32битовый
    • переменная типа UNSIGNED Lua неведома.
    Результат - вычисление выражения time.now - time.last через некоторое время приводит к отрицательным результатам. Это не беззнаковая арифметика.
    При отрицательном результате программа функционирует неправильно.
    Выход, в частности, показан здесь.
    Ну и, соответственно, перенесен в эту ветку и в код проверки.

    Почему проблема так долго не выплывала и не слишком известна? Дело в том, что в Lua время отмеряется, в подавляющем большинстве, не анализом системного времени, а установкой таймеров tmr.alarm. Соответственно, необходимость проверки системного времени практически не возникает.

    Столкнулся с ней лишь при подготовке скрипта по проверке счетчиков воды. А вот при поливе теплицы - так и не увидел: ни разу руками кран с приводом так и не открывал, все автоматически.
    Пост к учету всем изучающим ESP-8266 на Lua.
     
    Последнее редактирование: 5 дек 2016
    alp69 нравится это.
  2. alp69

    alp69 Форумчанин

    здесь в коде. В случае отсутствия wifi запускаете функцию Change_wifi(). Она будет далее проверять наличие wifi каждые 10 сек., параллельно включив точку доступа и предоставив страницу выбора сети. После успешной авторизации, функция прекращает мониторинг wifi, переводит точку доступа модуля в режим клиента и останавливает действие модуля enduser, экономя таким образом память и энергоресурсы.
    А там, где написано Start() - это команда на выполнение функции Start(), которой Вы можете назначить все, что угодно. Или вообще это строку закомментировать. В любом случае функция остановится после получения устройством ip-адреса от DHCP-сервера сети, к которой подключаемся.
     
  3. alp69

    alp69 Форумчанин

    Пол-года назад столкнулся с этим при разработке устройства с бистабильными реле. Чуть голову не вывихнул. Но вовремя остановился, поняв, что грамоты не хватает, и подставил костыли из tmr.delay. :cool:
     
  4. dimm71

    dimm71 Нерд

    Тогда получается как то так нужно сделать? Но мы ещё не отключили AP. Если повторно включит существующую АР не будет конфликта?

    Код (C++):
    function Change_wifi()
        wifi.setmode(wifi.STATIONAP) -- включаем точку доступа
        wifi.ap.config({ssid="ИМЯ_ТОЧКИ_ДОСТУПА", auth=wifi.OPEN}) -- вписать имя устройства
        enduser_setup.manual(true) -- включаем плюшку )))
        enduser_setup.start(function()
        print("Подключение к сети. Текущий IP-адрес:" .. wifi.sta.getip())
        end,
        function(err, str)
        print("enduser_setup: Err #" .. err .. ": " .. str)
        end
        )

    tmr.alarm(6,10000,1, function() -- мониторим наличие сети
        if (wifi.sta.status() == 5) and (wifi.sta.getip() ~= nil) then
            print("Есть Wi-Fi!")
    --       Start() -- что-то делаем если подключение появилось
            tmr.stop(6) -- тормозим таймер проверки wi-fi
            wifi.setmode(wifi.STATION) -- переводим модуль из режима точки доступа в режим клиента
            enduser_setup.stop() -- останавливаем модуль дистанционной настройки wi-fi
        else
            print("Нет Wi-Fi!")
            Change_wifi()
            print("Включаем AP!")
        end
    end)
    end
     
  5. alp69

    alp69 Форумчанин

    Перед тем, как выполнять в коде какие-то действия, для которых нужна сеть (подписка, прием-отправка данных и т.д.) запускаем что-то типа такого:

    Код (Lua):
    if (wifi.sta.status() == 5) and (wifi.sta.getip() ~= nil) then --если есть wifi и есть ip-адрес
               -- далее до "else" выполняем шаманства с сетью (прием/передача/подписка/ит.д.
    else     -- иначе
           Change_wifi() -- запускаем функцию, которая поправит положение дел.
    end
     
     
    Последнее редактирование: 5 дек 2016
  6. ИгорьК

    ИгорьК Гуру

    43.Читаем счетчики расхода воды. Beta 2.
    (Начало здесь.)
    А вот она. И это начинает мне нравиться.
    Код (Lua):
    water = {
        cool = 0,
        hot = 0,
        bat = 3,
        unit = "water01"
    }
    sent = {
        cool = 0,
        hot = 0,
    }
    -- timeNextCheck = 3600000 -- One Hour
    timeNextCheck = 20000 -- 20 second

    Broker="broker.mqtt-dashboard.com"
    --port=1883
    port=1883
    myClient="water0177721"
    pass="pass"

    m = mqtt.Client(myClient, 180, myClient, pass)
    m:lwt("/lwt", myClient, 0, 0)

    function connecting(call)
        print('Connecting')
        wifi.setmode(wifi.STATION)
        wifi.sta.config("AP", "Password", 0)
        -- wifi.sta.setip(cfg)
        wifi.sta.connect()

        function getWiFi()
            tmr.alarm(5, 500, 1, function()
                if wifi.sta.status() == 5 and wifi.sta.getip() ~= nil then
                    getConnect(call)
                    tmr.unregister(5)
                    tmr.start(6)
                end
            end)
        end

        function getConnect(call)
            print("Got WiFi!")
            m:connect(Broker, port, 0, 0,
                function(conn)
                    tmr.stop(6)
                    print("Connected")
                    if call then
                        call()
                    else
                        m:subscribe(myClient.."/#",0, function(conn)
                            print("Subscribed")
                        end)
                    end
            end)
        end
        getWiFi()
        tmr.register(6, 90000, 1, function()
            getConnect()
        end)
    end
    function publ(datt)
        water.bat = adc.readvdd33()/1000
        print("got pub")
        if(datt) then
            topic = myClient.."/report"
            dt = datt
            m:publish(topic, dt,0,0,function(conn)
                print("Published!")
                closeWiFi()
                --collectgarbage()
                return
            end)
        end

        local send = coroutine.create(function(close)
            for k,v in pairs(water) do
                print('Send '..k..' and '..v)
                pub(k,v)
                coroutine.yield()
            end
            return close()
        end)

        function pub(topic, info)
            if topic ~= nil and info ~= nil then
                print("Publish Topic: "..topic.." and Info: "..info)
                m:publish(myClient.."/"..topic,info,1,1, function()
                    coroutine.resume(send)
                end)
            end
        end
        coroutine.resume(send, closeWiFi)
        sent.cool = water.cool
        sent.hot = water.hot
    end

    m:on("message", function(conn, topic, data)
        if (string.find(topic, "state")) == nil then
            local top = string.gsub(topic, myClient.."/","")
            if top == "cool" then water.cool =  tonumber(data)  end
            if top == "hot" then  water.hot = tonumber(data) end
        end
        if water.cool ~= 0 and water.hot ~=0 then
            m:unsubscribe(myClient.."/#", function(conn) print("unsubscribe success") end)
            publ("Got and Ready!")
        end
        -- collectgarbage()
    end)

    function closeWiFi()
        wifi.setmode(wifi.NULLMODE)
        -- wifi.sta.disconnect()
        print("WiFi switched OFF")
    end


    function debounce (func, pinn)
        local last = 0
        local delay = 50000

        return function (...)
            local now = tmr.now()
            local delta = now - last
            if delta < 0 then delta = delta + 2147483647 end;
            if delta < delay then return end;
            last = now
            return func(pinn)
        end
    end

    function onChange (which)
        if(which == "cool") then
            water.cool = water.cool + 10
            print("Cool got "..water.cool.." liters.")
        else
            water.hot = water.hot + 10
            print("Hot got "..water.hot.." liters.")
        end
    end
    function setPins()
        gpio.mode(3, gpio.INT)
        gpio.trig(3, 'down', debounce(onChange, "hot"))
        gpio.mode(4, gpio.INT)
        gpio.trig(4, 'down', debounce(onChange, "cool"))
        wifi.setmode(wifi.NULLMODE)
    end
    setPins()
    connecting()

    tmr.alarm(1, timeNextCheck, tmr.ALARM_AUTO,
        function()
            -- print(water.cool, sent.cool, water.hot, sent.hot)
            if((water.cool ~= sent.cool) or (water.hot ~= sent.hot)) then
                connecting(publ)
            end
        end)

    В чем суть.
    • Публикация осуществляется с уровнем обслуживания 1 и установкой флага Retain.
    • Ушел от общей публикации json, вернулся к публикации по отдельным топикам (coroutine).
    • Подписка при старте на два отдельных топика.
    Что это дает?
    При запуске устройство подписывается на топики cool и hot, получает информацию о текущем состоянии расхода воды и уходит в сон. Все это осуществояется автоматически. Дальше начинаются публикации по проверке времени при изменении показаний счетчиков.
    Как все это запустить в работу?
    Перед подсоединением батарейки - загнать в ОН информацию о расходе воды с флагом Retain.
    Все.
    Также можно использовать сторонние брокеры без ОН. Достаточно смартфона.
    Позже распишу все подробнее, пусть отлежится.
    Пока картинки для красоты. Оформить можно так:
    water5.jpg

    И получить почасовой график расхода воды (пример):
    water6.jpg
    Иконки для разнообразия.
    Итемы:
    Код (Java):
    Group Water "Вода" <waterControl>
    // Этот итем для прежних вариантов
    //String water01 "Дата [%s]" (Water) { mqtt="<[mosquitto:water01/data:state:default]" }

    Number water01Cool "Расход [%.3f m³]" <waterCool> (Water) { mqtt="<[mosquitto:water01/cool:state:default]" }
    Number water01CoolHourly "За час [%.3f m³]" <waterCool> (Water)
    Number water01Hot "Расход [%.3f m³]" <waterHot> (Water)   { mqtt="<[mosquitto:water01/hot:state:default]" }
    Number water01HotHourly "За час [%.3f m³]" <waterHot> (Water)
    Number water01Bat "Питание [%.2f v]" <batary01> (Water) { mqtt="<[mosquitto:water01/bat:state:default]" }
    Правило:
    Код (Java):
    rule "Send hour water"
        when
            // Настроить cron на час самостоятельно
            Time cron "0 0/1 * * * ?"
        then
            var Number oldCool = (water01Cool.historicState(now.minusSeconds(120)).state) as DecimalType
            var Number nowCool = water01Cool.state as DecimalType
            var Number gotHourCool = nowCool - oldCool
            var Number oldHot = (water01Hot.historicState(now.minusSeconds(120)).state) as DecimalType
            var Number nowHot = water01Hot.state as DecimalType
            var Number gotHourHot = nowHot - oldHot
            postUpdate(water01CoolHourly, gotHourCool)
            postUpdate(water01HotHourly, gotHourHot)
     
    end
    /*

    Правило для передачи в JSON, старое,
    может кому пригодится

    rule "Mqtt Water Decript"
      when
      Item water01 received update
      then
      var String json = (water01.state as StringType).toString
      //{"bat":3,"hot":1620,"cool":1840,"unit":"water01"}
    var String unit = transform("JSONPATH", "$.unit", json)
      if (unit == "water01") {
    var String cool = transform("JSONPATH", "$.cool", json)
    var String hot = transform("JSONPATH", "$.hot", json)
    var String bat = transform("JSONPATH", "$.bat", json)
    postUpdate(water01Cool, cool)
    postUpdate(water01Hot, hot)
    postUpdate(water01Bat, bat)
    }
    end

    */

     
    ... но код ещё надо чистить... :) Идем дальше.
     

    Вложения:

    Последнее редактирование: 6 мар 2017
    alp69 и Securbond нравится это.
  7. ИгорьК

    ИгорьК Гуру

    43.Читаем счетчики расхода воды. RC.
    И вот результат. Код задействует публичный брокер http://broker.hivemq.com
    Код почистил, больше его трогать пока не буду:
    Код (Javascript):
    water = {
        cool = 0,
        hot = 0,
        bat = 3,
        unit = "water01"
    }
    sent = {
        cool = 0,
        hot = 0,
    }
    -- timeNextCheck = 3600000 -- One  Hour
    timeNextCheck = 20000 -- 20 seconds

    Broker="broker.hivemq.com"
    port=1883
    myClient="water0177721"
    pass="pass"

    m = mqtt.Client(myClient, 180, myClient, pass)
    m:lwt("/lwt", myClient, 0, 0)

    function connecting(call)
        print('Connecting')
        wifi.setmode(wifi.STATION)
        wifi.sta.config("AP", "pass", 0)
        -- wifi.sta.setip(cfg)
        wifi.sta.connect()

        function getWiFi()
            tmr.alarm(5, 500, 1, function()
                if wifi.sta.status() == 5 and wifi.sta.getip() ~= nil then
                    getConnect(call)
                    tmr.unregister(5)
                    tmr.start(6)
                end
            end)
        end

        function getConnect(call)
            print("Got WiFi!")
            m:connect(Broker, port, 0, 0,
                function(conn)
                    tmr.stop(6)
                    print("Connected")
                    if call then
                        call()
                    else
                        m:subscribe({[myClient.."/cool"]=1,[myClient.."/hot"]=1}, function(conn)
                            print("Subscribed")
                        end)
                    end
            end)
        end
        getWiFi()
        tmr.register(6, 90000, 1, function()
            getConnect()
        end)
    end
    function publ(datt)
        local send = coroutine.create(function(close)
            water.bat = adc.readvdd33()/1000
            for k,v in pairs(water) do
                -- print('Send '..k..' and '..v)
                pub(k,v)
                coroutine.yield()
            end
            return close()
        end)

        function pub(topic, info)
                print(topic..": "..info)
                m:publish(myClient.."/"..topic,info,1,1, function()
                    coroutine.resume(send)
                end)
        end

        if(datt) then
            m:publish(myClient.."/report", datt,0,0,function(conn)
                print("Cool: "..water.cool)
                print("Hot: "..water.hot)
                print(datt)
                closeWiFi()
                return
            end)
        else
            coroutine.resume(send, closeWiFi)
        end
    end


    m:on("message", function(conn, topic, data)
        if (string.find(topic, "state")) == nil then
            local top = string.gsub(topic, myClient.."/","")
            if top == "cool" then
                water.cool =  tonumber(data)
            end
            if top == "hot" then
                water.hot = tonumber(data)
            end
        end
        if water.cool ~= 0 and water.hot ~=0 then
            m:unsubscribe(myClient.."/#", function(conn) print("Unsubscribed.") end)
            publ("Got and Ready!")
        end
    end)

    function closeWiFi()
        wifi.setmode(wifi.NULLMODE)
        sent.cool = water.cool
        sent.hot = water.hot
        print("WiFi switched OFF")
    end

    function debounce (func, pinn)
        local last = 0
        local delay = 50000

        return function (...)
            local now = tmr.now()
            local delta = now - last
            if delta < 0 then delta = delta + 2147483647 end;
            if delta < delay then return end;
            last = now
            return func(pinn)
        end

    end

    function onChange (which)
        if(which == "cool") then
            water.cool = water.cool + 10
            print("Cool got "..water.cool.." liters.")
        else
            water.hot = water.hot + 10
            print("Hot got "..water.hot.." liters.")
        end
    end
    function setPins()
        gpio.mode(3, gpio.INT)
        gpio.trig(3, 'down', debounce(onChange, "hot"))
        gpio.mode(4, gpio.INT)
        gpio.trig(4, 'down', debounce(onChange, "cool"))
        wifi.setmode(wifi.NULLMODE)
    end
    setPins()
    connecting()

    tmr.alarm(1, timeNextCheck, tmr.ALARM_AUTO,
        function()
            -- print(water.cool, sent.cool, water.hot, sent.hot)
            if((water.cool ~= sent.cool) or (water.hot ~= sent.hot)) then
                connecting(publ)
            end
    end)
    А вот брокер показал нам нас:
    secret2.jpg
    И мы словили отчет на смартфоне:
    Screenshot.png

    UPD 17.12.2016: Добавил время отправки. Взято у dimm71
    Исправлено вычисление GMT.
    Код (Javascript):
     rtctime.set(0, 0)
    water = {
        cool = 0,
        hot = 0,
        bat = 3,
        unit = "water01",
        report = ""
    }
    sent = {
        cool = 0,
        hot = 0,
    }
    hotp = 6
    coolp = 7

    function SNTP()
    sntp.sync('0.ru.pool.ntp.org',
      function(sec,usec,server)
        end,
      function()
       print('failed SNTP!')
      end)
    end
    [/B]
    function get_TIME()
      tm = rtctime.epoch2cal(rtctime.get()+3600*3)
      water.report = string.format("%04d/%02d/%02d %02d:%02d:%02d", tm["year"], tm["mon"], tm["day"], tm["hour"], tm["min"], tm["sec"])
    end
    [B]
    --timeNextCheck = 3600000
    timeNextCheck = 20000
    --Broker="iot.eclipse.org"
    Broker="192.168.27.91"
    port=1883
    myClient="water01"
    pass="pass"
    m = mqtt.Client(myClient, 180, myClient, pass)
    m:lwt("/lwt", myClient, 0, 0)

    function connecting(call)
        -- print('Connecting')
        wifi.setmode(wifi.STATION)
        wifi.sta.config("AP", "Pass", 0)
        wifi.sta.connect()
       
        function getWiFi()
            local count = 0
            tmr.alarm(5, 500, 1, function()
                if wifi.sta.status() == 5 and wifi.sta.getip() ~= nil then
                    getConnect(call)
                    tmr.unregister(5)
                end
                count = count + 1
                if count > 30 then
                    tmr.unregister(5)
                    closeWiFi()
                end
               
            end)
        end

        function getConnect(call)
             SNTP()
             get_TIME()
            -- print("Got WiFi!")
            m:connect(Broker, port, 0, 0,
                function(conn)
                    tmr.stop(6)
                     print("Connected")
                    if call then
                        call()
                    else              
                        m:publish(myClient.."/report","Waiting Data",0,0, function()
                            m:subscribe({[myClient.."/cool"]=1,[myClient.."/hot"]=1}, function(conn)  
                           --  print("Subscribed")
                        end)
                       
                        end)
                    end
                end,
                function(conn, reason)
                   --  print(reason)
                    closeWiFi()
                end
            )
        end
        getWiFi()

    end
    function publ(datt)
        local send = coroutine.create(function(close)
            --water.bat = adc.readvdd33()/1000
            water.bat = (((1.4* adc.read(0)) + 20)/100)
            for k,v in pairs(water) do
                pub(k,v)
                coroutine.yield()
            end
            sent.cool = water.cool
            sent.hot = water.hot
            return close()
        end)

        function pub(topic, info)
                -- print(topic..": "..info)
                m:publish(myClient.."/"..topic,info,1,1, function()
                    coroutine.resume(send)
                end)
        end
       
        if(datt) then
            m:publish(myClient.."/report", datt,0,0,function(conn)
                -- print("Cool: "..water.cool)
                -- print("Hot: "..water.hot)
                -- print(datt)
                closeWiFi()
                return
            end)
        else
            coroutine.resume(send, closeWiFi)
        end
    end


    m:on("message", function(conn, topic, data)
        if (string.find(topic, "state")) == nil then
            local top = string.gsub(topic, myClient.."/","")
            if top == "cool" then
                water.cool =  tonumber(data)
            end
            if top == "hot" then
                water.hot = tonumber(data)
            end
        end
        if water.cool ~= 0 and water.hot ~=0 then
            m:unsubscribe(myClient.."/#", function(conn)
                print("Unsubscribed.")
            end)
            local rep = "Got "..water.cool.." & "..water.hot..". Ready!"
            publ(rep)
        end
    end)

    function closeWiFi()
        m:close()
        wifi.setmode(wifi.NULLMODE)
        -- sent.cool = water.cool
        -- sent.hot = water.hot
        -- print("WiFi switched OFF")
    end

    function debounce (func, pinn)
        local last = 0
        local delay = 200000

        return function (...)
            local now = tmr.now()
            local delta = now - last
            if delta < 0 then delta = delta + 2147483647 end;
            if delta < delay then return end;
            last = now
            return func(pinn)
        end

    end

    function onChange (which)
        if(which == "cool") then
            water.cool = water.cool + 10
           --  print("Cool got "..water.cool.." liters.")
        else
            water.hot = water.hot + 10
          --   print("Hot got "..water.hot.." liters.")
        end
    end
    function setPins()
        gpio.mode(hotp, gpio.INT)
        gpio.trig(hotp, 'down', debounce(onChange, "hot"))
        gpio.mode(coolp, gpio.INT)
        gpio.trig(coolp, 'down', debounce(onChange, "cool"))
        wifi.setmode(wifi.NULLMODE)
    end
    setPins()
    connecting()

    tmr.alarm(1, timeNextCheck, tmr.ALARM_AUTO,
        function()
            if(((water.cool ~= sent.cool) or (water.hot ~= sent.hot)) and publ )then
                connecting(publ)
            end
    end)
     
    Последнее редактирование: 18 дек 2016
    alp69 и Securbond нравится это.
  8. mex79

    mex79 Нерд

    Господа есть вопрос: у кого нибудь работает парсинг с яндекса? Я так понимаю что поменяли структуру документа я смог нормально выдергивать только ветер, влажность и давление. Хотел добавить пробки, но <hint lang="ru">(*)</hint> не канает и температура тоже, а было желание брать прогнозы на завтра.
     
  9. Securbond

    Securbond Гуру

    Яндекс постоянно что-то меняет, по этому забил...
     
  10. zloy-glide

    zloy-glide Нерд

    У меня все работает и с прогнозом на завтра. Но там есть нюанс. В полночь парсинг температуры на завтра становится тыквой) tomorrow превращается в today. Через несколько часов появляется прогноз уже на следующий день. Мне не мешает, так как происходит это все ночью и в течении непродолжительного времени. Пробки не пробовал, так как общая температура по больнице не интересует. Если бы можно было конкретный маршрут задавать, то да.
     
  11. zloy-glide

    zloy-glide Нерд

    Граждане умельцы. Хотелось бы обратиться с вопросом. Делал ли кто мониторинг активности датчиков. То есть что-то типа таймера для датчика. По истечении определенного времени если от датчика не приходит информация, то выполняется какое-то действие или уведомление. На даче стоят самодельные температурные датчики, которые просыпаются раз в 10 минут. Телеметрия валится в москит установленный на роутере с юсб модемом. На моските настроен бридж с cloudmqtt. И уже дома на компе крутится опенхаб который все это хватает и обрабатывает. Раньше там стояла малина и все крутилось локально, но она уже третий раз сваливается в кернел паник. На разных сд картах. Мониторинга напряжения по mqtt на датчиках не предусмотрено. Оно мне собственно и не нужно. Нужно чтобы при отсутствии вестей от датчика опенхаб слал уведомление. Думаю это будет многим полезно.
     
  12. mex79

    mex79 Нерд

    У меня белиберда, ну и ладно, буду брать только то что нужно )
     
  13. zloy-glide

    zloy-glide Нерд

    Что именно не парсится? Вот мои итемы. Все работает, кроме озвученных ранее проблем.

    Код (Javascript):
    //Яндекс.Погода
    Group  YandexWeather
    Number YandexTemp    "Улица [%.1f °C]"    <temperature_outside> (YandexWeather, Temperature)    { http="<[http://export.yandex.ru/bar/reginfo.xml?region=10755.xml:1800000:REGEX(.*?</pressure>.*<temperature.*>(.*?)</temperature>.*<time_zone>.*?)]" }
    Number YandexHumi    "Влажность [%s %%]"    <humidity> (YandexWeather)   { http="<[http://export.yandex.ru/bar/reginfo.xml?region=10755.xml:1800000:REGEX(.*?<dampness>(.*?)</dampness>.*)]" }
    Number YandexWind    "Ветер [%.1f м/с]"    <wind> (YandexWeather)               { http="<[http://export.yandex.ru/bar/reginfo.xml?region=10755.xml:1800000:REGEX(.*?<wind_speed>(.*?)</wind_speed>.*)]" }
    Number YandexPress   "Давление [%d mm.Hg]"  <pressure> (YandexWeather) { http="<[http://export.yandex.ru/bar/reginfo.xml?region=10755.xml:1800000:REGEX(.*?<pressure>(.*?)</pressure>.*)]" }
    String YandexType    "За окном [%s]"  (YandexWeather)  { http="<[http://export.yandex.ru/bar/reginfo.xml?region=10755.xml:1800000:REGEX(.*?<weather_type>(.*?)</weather_type>.*)]" }
    Number YandexTempTom "Завтра [%.1f °C]"     <temperature_outside> (YandexWeather)   { http="<[http://export.yandex.ru/bar/reginfo.xml?region=10755.xml:1800000:REGEX(.*?<tomorrow>.*<temperature.*>(.*?)</temperature>.*</tomorrow>.*)]" }
     
     
  14. zloy-glide

    zloy-glide Нерд

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

    В шапку добавить:
    Код (Javascript):
    import org.openhab.model.script.actions.*

    var Timer System_Temperature_CPU_Update_Timer = null
    Код (Javascript):

    rule "System Temperature last update"
    when
      Item System_Temperature_CPU received update
    then
    System_Temperature_CPU_Update.postUpdate( new DateTimeType() )

    if (System_Temperature_CPU_Update_Timer != null)
                  System_Temperature_CPU_Update_Timer.cancel()
                  System_Temperature_CPU_Update_Timer = createTimer(now.plusSeconds(61))
                  [|
                  {
                    sendTelegram("bot1", "Что-то пошло не так.")
                    System_Temperature_CPU_Update_Timer.cancel()
                    System_Temperature_CPU_Update_Timer = null
                  }
                  ]

    end
     
    Единственная боль, в случае рестарта опенхаба или обновления файлов с итемами правилами и т.д., система восстанавливает последние значения итемов и срабатывает правило перезаписывающее время обновления. То есть у нас есть датчик он перестал обновляться. Пришло уведомление об этом. Я поковырялся в конфигах что-то поправил что-то добавил сохранил и бац дохлый датчик имеет время последнего обновления совпадающее с временем рестарта системы или перечитывания измененого конфига. Жить особо не мешает, но стоит иметь в виду такую особенность.
     
    Последнее редактирование: 8 дек 2016
    Securbond и ИгорьК нравится это.
  15. ИгорьК

    ИгорьК Гуру

    Вот адрес для тренировки: https://regex101.com/
     
    mex79 и alp69 нравится это.
  16. mex79

    mex79 Нерд

    Ну вот вроде с парсингом разобрался, всплыла проблеме веселее перестала обновляться страница с данными, в логах показывает что обновлено но при этом страница с данными показывает данные со времени рестарта сервиса и пинзец (

    UPD. Вопрос снят это я олень, почему то думал что время синхронизации ntp не связано с отображением времени на странице и жахнул 900000млс. чтобы не долбать лишний раз сервера, естественно тут и вышла промашка. Сейчас поставил 60000 и стало так ка надо.
     
    Последнее редактирование: 9 дек 2016
    ИгорьК нравится это.
  17. kmaximv

    kmaximv Гик

    Посмотрите у себя конфиг rrd4j.persist
    Код (C++):
    Temperature*,Weather_Chart* : strategy = everyMinute, restoreOnStartup
    Если есть параметр restoreOnStartup, то он подтягивает последние значения из базы при старте.
     
  18. ip-ua

    ip-ua Нерд

    У меня меняется цвет итема в зависимости от того как давно обновились от него даные:
    sitemap:
    Код (C++):
    Text item=Tempvhod valuecolor=[Tempvhod_LastUpdate=="Uninitialized"="lightgray", Tempvhod_LastUpdate>300="red",>240="purple",>120="orange",>0="green"]
    rule:
    Код (C++):
    rule "Records last Tempvhod update time"
        when
            Item  Tempvhod received update
        then
            postUpdate(Tempvhod_LastUpdate, new DateTimeType())
        end    
    Думаю по тому же принципу можно сделать любую реакцию обновление данных с датчика.
     
    mex79 нравится это.
  19. Securbond

    Securbond Гуру

    Изучаю Fusion360. Вот 2 лампочки On и Off.
    LampON.png Lamp OFF.png
     

    Вложения:

    • Lamp OFF.png
      Lamp OFF.png
      Размер файла:
      9,4 КБ
      Просмотров:
      644
    • LampON.png
      LampON.png
      Размер файла:
      7,3 КБ
      Просмотров:
      657
    ИгорьК нравится это.
  20. zloy-glide

    zloy-glide Нерд

    Да причина мне известна, просто думал что реализация будет более изящна чем присваивание старых значений итемам, со всеми выходящими. От восстановления показания датчиков возможно откажусь, когда приедет OrangePi и система начнет крутиться в режиме 24/7.