• Главная
  • Контакты
Подписаться:
  • Twitter
  • Facebook
  • RSS
  • VK
  • PushAll
logo

logo

  • Все
    • Положительные
    • Отрицательные
  • За сегодня
    • Положительные
    • Отрицательные
  • За вчера
    • Положительные
    • Отрицательные
  • За 3 дня
    • Положительные
    • Отрицательные
  • За неделю
    • Положительные
    • Отрицательные
  • За месяц
    • Положительные
    • Отрицательные
  • За год
    • Положительные
    • Отрицательные
  • Сортировка
    • По дате (возр)
    • По дате (убыв)
    • По рейтингу (возр)
    • По рейтингу (убыв)
    • По комментам (возр)
    • По комментам (убыв)
    • По просмотрам (возр)
    • По просмотрам (убыв)
Главная
  • Все
    • Положительные
    • Отрицательные
  • За сегодня
    • Положительные
    • Отрицательные
  • За вчера
    • Положительные
    • Отрицательные
  • За 3 дня
    • Положительные
    • Отрицательные
  • За неделю
    • Положительные
    • Отрицательные
  • За месяц
    • Положительные
    • Отрицательные
  • Главная
  • Добавление счетчика SDM-220 в OpenHab

Добавление счетчика SDM-220 в OpenHab +13

24.04.2017 07:21
alk0v 6 4100 Источник
Умный дом, DIY или Сделай сам*, Блог компании Plarium
Прошел почти год с момента моей первой публикации об электросчетчике с RS485/ModBus интерфейсом SDM-220, затем была вторая статья о том, как собирать с него данные и обрабатывать статистику. Это третья, надеюсь, последняя. Она о том, как интегрировать счетчик с OpenHab. Результат наконец-то меня полностью устраивает.



Итак, первая попытка собирать статистику со счетчика предпринималась с использованием внешнего облачного сервиса ThingSpeak. В качестве локального сервера, который опрашивает счетчик, использовался тонкий клиент (мини-компьютер) с установленным на флешку Ubuntu Server. Это была первая ошибка — флешка «умерла» через 3 месяца (случайность, подумал я). Не сделав никаких выводов, вторую флешку я убил за 2 месяца (закономерность). В третьей версии в качестве хранилища уже использовался usb-карман с винтом 2,5".

Сам сервис ThingSpeak позволяет производить некоторую обработку, но не дает достаточной гибкости с манипуляциями данными. Данные за сутки, например, собирались как сумма данных по часам. Если какой-то пакет данных на сервер не поступил или я отправил несколько данных во время тестирования, появлялась ошибка. Мысли о том, что придется вести двухтарифный учет с привязкой по времени суток, оптимизма не добавляли.

В общем, решил я осваивать OpenHab.

Задача первая: получить сырые данные со счетчика.


Установка самого OpenHab подробно изложена в инструкции. После установки нужно через панель Paper UI > Bindings установить ModBus binding — binding-modbus1 — 1.9.0

Опрос шины ModВus происходит через USB-RS485 адаптер, поэтому нужно убедиться, что адаптер есть в системе, и добавить пользователю openhab права на доступ к порту:

lsusb
Bus 002 Device 002: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC

ls /dev/ttyUSB*
/dev/ttyUSB0

sudo adduser openhab dialout
sudo adduser openhab tty

Затем рекомендуется настроить разрешения для Java (об этом также подробно написано в инструкции по установке OpenHab):

sudo vi /etc/default/openhab2 
EXTRA_JAVA_OPTS="-Dgnu.io.rxtx.SerialPorts=/dev/ttyUSB0"

После этих манипуляций нужно настроить конфигурационный файл services/modbus.cfg:

 sudo vi  /etc/openhab2/services/modbus.cfg

#Период опроса счетчика
poll=30000

#Счетчик не позволяет вычитать все регистры за одно обращение, поэтому нужно создать отдельную запись для каждого регистра. Поле start - номер регистра. В строке connection указываем номер и параметры порта (9600,8,n,1), задержку перед чтением каждого регистра и таймаут ответа.

#напряжение - 0x00
serial.slave1.connection=/dev/ttyUSB0:9600:8:none:1:rtu:2000:1000:none:none
serial.slave1.type=input
serial.slave1.start=0
serial.slave1.length=2
serial.slave1.valuetype=float32

#ток - 0x06
serial.slave2.connection=/dev/ttyUSB0:9600:8:none:1:rtu:2000:1000:none:none
serial.slave2.type=input
serial.slave2.start=6
serial.slave2.length=2
serial.slave2.valuetype=float32

#активная мощность - 0x0C
serial.slave3.connection=/dev/ttyUSB0:9600:8:none:1:rtu:2000:1000:none:none
serial.slave3.type=input
serial.slave3.start=12
serial.slave3.length=2
serial.slave3.valuetype=float32

#показания счетчика (активная энергия) - 0x156
serial.slave4.connection=/dev/ttyUSB0:9600:8:none:1:rtu:2000:1000:none:none
serial.slave4.type=input
serial.slave4.start=342
serial.slave4.length=2
serial.slave4.valuetype=float32

Затем нужно создать элементы данных в файле items/sdm220.items:

sudo vi /etc/openhab2/items/sdm220.items

#Определяем группу для элементов
Group gSDM220

#и указываем, откуда их брать и как выводить, energy - это имя иконки из стандартного набора
Number sdm220_voltage  "Напряжение  [%.1f В]" <energy> (gSDM220) {modbus="slave1:0"}
Number sdm220_current  "Ток  [%.2f А]" <energy> (gSDM220) {modbus="slave2:0"}
Number sdm220_actpower  "Мощность  [%.1f Вт]" <energy> (gSDM220) {modbus="slave3:0"}
Number sdm220_actcounter  "Счетчик электроэнергии  [%.1f кВт*ч]" <energy> (gSDM220) {modbus="slave4:0"}

Осталось добавить текущие показания на dashboard. Для этого редактируем файл sitemaps/default.sitemap:

sudo vi /etc/openhab2/sitemaps/default.sitemap 

sitemap default label="alk0v SmartHome (default sitemap)" {
    Frame label="Электросчетчик" {
        Text item=sdm220_voltage
        Text item=sdm220_current
        Text item=sdm220_actpower
        Text item=sdm220_actcounter
    }
}

В принципе, этого достаточно, чтобы увидеть текущие показания счетчика:



Задача вторая: настройка HabPanel и визуализация показаний


OpenHab поддерживает несколько панелей управления. Мне внешне больше всего понравилась HabPanel. Через Paper UI > User Interfaces устанавливаем HabPanel — ui-habpanel — 2.0.0.

Для отрисовки графиков также нужно где-то хранить данные. OpenHab использует термин Persistence для баз данных. Мне хотелось использовать базу MySQL, в community обсуждали много проблем с этой базой, в итоге я нашел инструкцию, которая заработала и у меня.

Итак, устанавливаем MySQL Persistence (persistence-mysql — 1.9.0).

Устанавливаем MySQL:

sudo apt-get install mysql-server
sudo mysql -u root -p

Настраиваем базу:

CREATE DATABASE OpenHAB;
CREATE USER 'openhab'@'localhost' IDENTIFIED BY 'YOURPASSWORD';
GRANT ALL PRIVILEGES ON OpenHAB.* TO 'openhab'@'localhost';
quit

Рестартуем openhab:

sudo service openhab2 stop
sudo service openhab2 start

Правим services/mysql.cfg:

# the database url like 'jdbc:mysql://<host>:<port>/<database>' (without quotes)
url=jdbc:mysql://localhost:3306/openhab

# the database user
user=openhab

# the database password
password=YOURPASSWORD

Правим persistence/mysql.persist. По умолчанию значения всех Items будут заноситься в базу при каждом изменении:

Strategies {
        // if no strategy is specified for an item entry below, the default list will be used
        everyMinute     : "0 * * * * ?"
        every5Minutes : "0 */5 * * * ?"
        everyHour   : "0 0 * * * ?"
        everyDay    : "0 0 0 * * ?"
        default = everyChange
}

Items {
    // persist all items once a day and on every change and restore them from the db at startup
    * : strategy = default, restoreOnStartup
}

Если всё настроено правильно, в базе должна появиться таблица Items и таблицы ItemXX для каждого Item.


mysql> use openhab;
Database changed

mysql> show tables;
+-------------------+
| Tables_in_openhab |
+-------------------+
| Item1             |
| Item2             |
| Item3             |
| Item4             |
| Items             |
+-------------------+
5 rows in set (0.00 sec)

mysql> select * from Items;
+--------+--------------------------+
| ItemId | ItemName                 |
+--------+--------------------------+
|      1 | sdm220_voltage           |
|      2 | sdm220_actpower          |
|      3 | sdm220_actcounter        |
|      4 | sdm220_current           |
+--------+--------------------------+
4 rows in set (0.00 sec)

Теперь можно наводить красоту в HabPanel.

Добавляем Dashboard, на него добавляем новые виджеты. Для вывода значений используется виджет Dummy, для вывода графиков — Chart. Тут всё интуитивно понятно. Параметры мощности и напряжения я вывел на один график, используя две разных шкалы Y.

Указываем в качестве источника данных mysql:



Настраиваем пороги для оси напряжения:



Добавляем Items, указываем для них цвет и тип линии, для напряжения указываем ось Secondary:



Получаем результат :)



Задача третья: почасовый и посуточный учет затраченной электроэнергии


Отображение изменения состояния во времени — это хорошо, но хотелось еще получить статистику расхода за час, сутки, месяц. То есть задача — периодически производить некоторые вычисления. Тут на помощь приходит механизм правил в OpenHab.

Итак, настраиваем Rules.

Сначала нужно добавить новые Items в items/sdm220.items:

Number sdm220_hourcounter (gSDM220)
Number sdm220_daycounter (gSDM220)

Затем создаем файл rules/energy.rules, в котором нужно указать 2 правила: одно будет выполняться раз в час, второе — раз в сутки.

rule "Energy by hour"
when
        Time cron "0 0 * * * ?"
then
//вычисление расхода. Из текущих показаний счетчика вычитаются значения из базы на час раньше   
        var hour = sdm220_actcounter.state as DecimalType - sdm220_actcounter.historicState(now.minusHours(1), "mysql":).state as DecimalType
//вывод данных в лог для отладки
        logInfo("TEST","sdm220_hourcounter = "+hour)
//присваиваем значение Item
        postUpdate(sdm220_hourcounter, hour)
end

rule "Energy by day"
when
        Time cron "0 0 0 * * ?"
then
        var day = sdm220_actcounter.state as DecimalType - sdm220_actcounter.historicState(now.minusDays(1), "mysql":).state as DecimalType
        postUpdate(sdm220_daycounter, day)

Для отладки можно использовать консоль OpenHab. Стандартные логин и пароль: openhab/habopen. Подключиться к ней можно командой:

ssh -p 8101 openhab@localhost
openhab> log:tail

19:22:00.012 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_hourcounter_day = 0.526123046875
19:22:00.014 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_daycounter = 10.861083984375
19:22:09.462 [INFO ] [marthome.event.ItemStateChangedEvent] - sdm220_current changed from 16.0433025360107421875 to 5.69449329376220703125
19:22:11.500 [INFO ] [marthome.event.ItemStateChangedEvent] - sdm220_actcounter changed from 2387.51904296875 to 2387.5458984375
19:22:13.532 [INFO ] [marthome.event.ItemStateChangedEvent] - sdm220_voltage changed from 192.7679595947265625 to 200.4195098876953125
19:22:15.568 [INFO ] [marthome.event.ItemStateChangedEvent] - sdm220_actpower changed from 2271.8486328125 to 1132.8717041015625
19:23:00.014 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_hourcounter_day = 0.515869140625
19:23:00.015 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_daycounter = 10.8769531250

Или можно просматривать файл лога:

tail -f /var/log/openhab2/openhab.log
2017-04-18 19:17:45.587 [INFO ] [el.core.internal.ModelRepositoryImpl] - Refreshing model 'energy.rules'
2017-04-18 19:18:00.259 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_hourcounter_day = 0.571044921875
2017-04-18 19:18:00.272 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_daycounter = 10.8330078125
2017-04-18 19:19:00.015 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_daycounter = 10.83789062500
2017-04-18 19:19:00.025 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_hourcounter_day = 0.557861328125
2017-04-18 19:20:00.013 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_hourcounter_day = 0.55517578125
2017-04-18 19:20:00.024 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_daycounter = 10.859130859375

Я планирую менять основной электросчетчик на двухтарифный, по которому электроэнергия, потребляемая в диапазоне с 23:00 до 07:00, оплачивается с коэффициентом 0.5, поэтому хотелось бы видеть ожидаемый эффект и вести двухтарифный учет. Сначала я просто добавил в Items и Rules дополнительные условия для времени и складывал дневные и ночные показания в две разных таблицы. В базе всё было красиво, а вот на графике выглядело коряво, так как график соединял два последних значения прямой линией:



Чтобы потешить свое чувство прекрасного, пришлось немного заморочиться.

Итак, финальный скрипт Rules для двухтарифного учета выглядит так:

rule "Energy by hour"
when
        Time cron "0 0 * * * ?"
then
        var hour = sdm220_actcounter.state as DecimalType - sdm220_actcounter.historicState(now.minusHours(1), "mysql":).state as DecimalType
//определяем диапазоны времени
        if(now.getHourOfDay > 7 && now.getHourOfDay < 23)
        {
                logInfo("TEST","sdm220_hourcounter_day = "+hour)
                postUpdate(sdm220_hourcounter_day, hour)
        }
        else
        {
//на границе диапазонов добавляем нулевые значения в график
//так как в таблице в качестве primary key используется timestamp, между добавлениями данных в одну и ту же таблицу стоит пауза в одну секунду
                if(now.getHourOfDay==7)
                {
                        postUpdate(sdm220_hourcounter_night, hour)
                        Thread::sleep(1000)
                        postUpdate(sdm220_hourcounter_night, 0)
                        Thread::sleep(1000)
                        postUpdate(sdm220_hourcounter_day, 0)
                        Thread::sleep(1000)
                        postUpdate(sdm220_hourcounter_day, hour)
                }
                else if(now.getHourOfDay==23)
                {
                        postUpdate(sdm220_hourcounter_day, hour)
                        Thread::sleep(1000)
                        postUpdate(sdm220_hourcounter_day,0)
                        Thread::sleep(1000)
                        postUpdate(sdm220_hourcounter_night, 0)
                        Thread::sleep(1000)
                        postUpdate(sdm220_hourcounter_night, hour)
                }
                else
                {
                        postUpdate(sdm220_hourcounter_night, hour)
                }
        }
        postUpdate(sdm220_hourcounter, hour)
end

rule "Energy by day"
when
        Time cron "0 0 0 * * ?"
then
        var day = sdm220_actcounter.state as DecimalType - sdm220_actcounter.historicState(now.minusDays(1), "mysql":).state as DecimalType
        //night counter, 00:00..07:00 + 23:00..00:00
        var day2 = sdm220_actcounter.historicState(now.minusHours(17),"mysql":).state as DecimalType - sdm220_actcounter.historicState(now.minusDays(1), "mysql":).state as DecimalType + sdm220_actcounter.state as DecimalType - sdm220_actcounter.historicState(now.minusHours(1),"mysql":).state as DecimalType
        //day counter, 07:00..23:00
        var day1 = sdm220_actcounter.historicState(now.minusHours(1),"mysql":).state as DecimalType - sdm220_actcounter.historicState(now.minusHours(17),"mysql":).state as DecimalType
        logInfo("TEST","sdm220_daycounter_day = "+day1)
        logInfo("TEST","sdm220_daycounter_night = "+day2)
        logInfo("TEST","sdm220_daycounter = "+day)
        postUpdate(sdm220_daycounter, day)
        postUpdate(sdm220_daycounter_day, day1)
        postUpdate(sdm220_daycounter_night, day2)
end

Перед редактированием скрипта добавить нужные Items:

Number sdm220_hourcounter_day (gSDM220)
Number sdm220_hourcounter_night (gSDM220)
Number sdm220_daycounter_day (gSDM220)
Number sdm220_daycounter_night (gSDM220)

Теперь график почасового и посуточного расхода выглядит так:



На этом, пожалуй, все. В планах еще добавить подсчет расхода электроэнергии и денег за месяц по дневному и ночному тарифу и генерацию отчета с отправкой на почту.
Поделиться с друзьями
-->

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


  1. Nizametdinov
    24.04.2017 11:46
    #10022722

    Сижу на oh 1.8.*, смотрю двойка уже совсем ожила и можно мигрить. Как она в жизни? Падения, глюки?


    1. alk0v
      24.04.2017 12:40
      #10022882

      Работает уже 2 недели, пока все адекватно, глюков не обнаружил


      1. av0000
        24.04.2017 15:17
        #10023290

        А я трижды уже пытался "переехать", но пока остаюсь на 1.8, хотя и обновленный гуй в 2.0 ощутимо приятнее...


        Особенную "боль" доставляют скрипты из 1.8, которые в 80% случаев надо переписывать. Также сильно иначе стал работать JSONPATH (в частности, не удалось вытянуть данные вида "transform("JSONPATH",$.data[?(@.name=='abc')][0].value)" и пришлось писать JS функцию, генерящую готовый объект по имени поля)


        Сейчас неспешно перевожу всю логику на NodeRed, а openhab занимается только отображением. В планах таки переползти под 2.0 на raspberry pi с read-only root.


        1. alk0v
          24.04.2017 16:10
          #10023458

          Я, честно говоря, года полтора назад пробовал разворачивать у себя первую версию но как-то не пошло, забросил, поэтому 2.0 фактически ставил с чистого листа не опираясь на опыт первой версии, все показалось довольно простым и логичным. С трансформациями пока не сталкивался.


  1. mslr
    24.04.2017 12:40
    #10022884
    +1

    Кому интересно удаленное снятие статистики для SDM220 через ESP8266 вот ролик в котором описана железная часть.


  1. martiniman
    24.04.2017 16:30
    #10023506
    +1

    Тоже сначала это счетчик подключал через модбас биндинг, но потом сделал через MQTT и ESP8266.
    Положил на форум openHAB

МЕТКИ

  • Хабы
  • Теги

Умный дом

DIY или Сделай сам

Блог компании Plarium

SDM220

openhab

habpanel

учет электроэнергии

умный дом

СЕРВИСЫ
  • logo

    CloudLogs.ru - Облачное логирование

    • Храните логи вашего сервиса или приложения в облаке. Удобно просматривайте и анализируйте их.
Все публикации автора
  • Acorn Electron — неудачный наследник BBC Micro +20

    • 21.06.2017 19:40

    BBC Micro — компьютер, который обыграл ZX Spectrum +27

    • 26.05.2017 07:41

    Добавление счетчика SDM-220 в OpenHab +13

    • 24.04.2017 07:21

    Silicon Graphics O2 — Маленькая станция с большими возможностями +42

    • 21.03.2017 01:06

    Apple Power Mac G4 Cube и его современники в небольшом фотообзоре +22

    • 26.02.2017 23:18

    История и обзор Atari 5200 +40

    • 22.01.2017 14:20

    Osborne 1 — давно обещанный обзор +58

    • 09.01.2017 19:00

    Композитный видеовыход для приставки Atari 2600 Jr +53

    • 11.09.2016 17:14

    Nexon Computer Museum на острове Jeju, Корея +22

    • 02.08.2016 13:37

    The 3DO Company и 3DO Interactive Multiplayer (Panasonic и не только) +11

    • 19.06.2016 22:56

Подписка


ЛУЧШЕЕ

  • Сегодня
  • Вчера
  • Позавчера
04:15

«Ошибка выжившего», или как я, проработав тренером 10 лет, с первого собеседования попал в IT +22

06:18

Авторизация в Kafka: управление изменениями, когда у тебя тысячи клиентов и миллионы RPS +18

08:07

Раздувание таблиц в PostgreSQL: работа с vacuum и pg_repack +14

05:26

Больше никаких правок! Или как я сдаю прототипы с первого раза +13

07:06

10 мифов об A/B-тестировании: как избежать распространённых заблуждений в статистическом анализе +12

08:02

Шум вокруг ИИ подобен парадоксу Солоу +10

07:35

Трудности перевода: поучительные истории о работе проджекта с зарубежными клиентами +8

07:47

Подкаст «Скрамное ИТ». 404: Взрослая жизнь не найдена +7

05:01

PHP и Laravel дайджест новостей за май 2025 года +7

07:30

Между печеньем и морковкой: удержание команды в условиях неопределенности +6

06:31

Заходят как-то в бар Сократ, DeepSeek и 1000 серверов +6

08:13

Математики нашли совершенно новый способ поиска простых чисел +5

07:30

Как спасти проект, если нашли баги перед релизом +5

07:07

Ваше лицо устарело и больше не поддерживается: как отсутствие зубов ломает архитектуру тела и рендеринг внешности +5

07:31

Ремонт Nintendo Switch Lite после залития водой. Это не всегда приговор +4

06:42

Радиобаттон Авито с функцией чекмарка: спорный паттерн или гениальное решение? +4

06:00

Как разработчику написать своего K8S-оператора. Часть 1: о Kubernetes +4

04:00

Hello, self driving world! (Carla Simulator) +4

08:12

Ошибки ИИ, которые спасают вашу работу: как нейросети генерируют баги +3

08:12

Ваша работа и диабет. Как ежедневная рутина разгоняет риски диабета до 47% +3

07:49

Юра, мы всё: как Россия проиграла новую космическую гонку +180

13:01

Что же такое TPU +49

13:16

Visopsys — ОС, которую написал один человек +40

10:03

Как мы учим роботов ходить плавно, или Почему градиент градиента — это не опечатка, а ключ к безопасной робототехнике +40

11:18

Основная проблема с кадрами или на заметку HR +36

18:06

Всё, что мы узнали с юристом о запрете рекламы в запрещённых соцсетях с 1 сентября +32

09:01

Жизнь и смерть Карла Коха: первый хакер на службе КГБ в поисках всемирного заговора и тайны числа 23. Часть 8 +31

13:24

BA + UX: смешать, но не взбалтывать. Как мы объединили дизайн и аналитику на примере очень запутанной фичи +28

11:41

Эволюция UI за 35 лет: от GIF и Comic Sans к нейросетям и адаптивам +28

11:05

Запускаем MIPI DSI экраны от смартфонов. Разработка схемы основной платы. Часть 1. Обзор решений, создаём своё +28

08:02

Интерфейсы без экрана: как разговаривают голосовые ассистенты, когда никто не слышит +26

13:16

Почему Go такой странный, и ещё 8 холиварных тем про Golang +20

12:47

Я тестировщик и два месяца работал без рук. Вот, что я понял +18

09:02

Под капотом WordPress — разбираем движок и изучаем инструменты +18

10:40

Использование open source в KasperskyOS +17

09:16

Обнаружение дронов (БПЛА) с использованием ИИ и компьютерного зрения +17

07:20

Китайцы разработали ИИ-платформу для разработки чипов. Что это за инструмент? +11

09:46

Как обобрать дерево в несколько потоков? +10

09:10

Тест-драйв WAF: как быстро и на практике проверить, подходит ли вам файервол +10

13:46

«IT-Планета 2025»: задачи второго этапа по PostgreSQL +9

09:05

Сервер за копейки +168

02:42

Недавно потенциальный клиент спросил, сколько стоит час моей работы +71

13:01

Цифровая чёрно-белая фотография +69

07:00

Как недовольный инженер часовые пояса придумал +63

09:04

Hello, World!“ и прощай: Почему новички сливаются из IT быстрее, чем успевают написать первую программу +55

11:06

Что на сегодня ясно про распад жира ( внутри человека ) +42

11:11

Нестыдные вопросы про телеком: как устроена опорная сеть 5G простыми словами +41

08:01

Векторный поиск внутри PostgreSQL: что умеет и где может пригодиться pgvector +40

15:14

Генерация юнит-тестов с LLM: если бы посуда мылась сама +36

09:02

Почему в бюджете ЦОДа лидирует статья «электричество» +36

07:30

Похмелье и тесты, где мужчины плакали +34

07:52

Как прошел день рождения Хабра с авторами, компаниями и партнерами +30

20:31

Плохие JOIN’ы: приемы, которые (нечаянно) кладут прод +28

10:31

Уникальная компания Disco и её система Will: работа как игра +27

09:35

Пошаговое руководство по написанию эксплойта ядра iOS +25

06:48

Штрафуем рёбра: новая логика перестроения маршрутов в 2ГИС +21

12:30

HandReader и Znaki — лучшая архитектура и самый большой набор данных для распознавания русского дактиля +18

13:34

Новые модели электронных книг 2025 года и кое-что еще. Что предлагает рынок? +16

12:59

Топ-5 нейросетей для генерации видео в 2025 году +16

14:38

Как спроектировать потокобезопасный класс в Java +15

ОБСУЖДАЕМОЕ

  • Юра, мы всё: как Россия проиграла новую космическую гонку +180

    • 411   49000

    Сервер за копейки +168

    • 199   49000

    Hello, World!“ и прощай: Почему новички сливаются из IT быстрее, чем успевают написать первую программу +55

    • 179   34000

    Что на сегодня ясно про распад жира ( внутри человека ) +42

    • 60   7000

    Почему сознание нельзя запрограммировать (критика механистических теорий сознания) +6

    • 57   1700

    Цифровая чёрно-белая фотография +69

    • 52   5000

    Недавно потенциальный клиент спросил, сколько стоит час моей работы +71

    • 46   23000

    Это база(!) -2

    • 41   4500

    Обнаружение дронов (БПЛА) с использованием ИИ и компьютерного зрения +17

    • 39   3100

    «Вайтишная» — сервис, где тебя обучают реальные специалисты, а не школы -6

    • 34   2400

    Как недовольный инженер часовые пояса придумал +63

    • 33   6400

    Как новичку выбрать компьютер для программирования -1

    • 30   4100

    C#, Кодогенерация и DDD. Часть 2 — Получаем данные и пробуем генерировать +1

    • 29   2100

    Всё, что мы узнали с юристом о запрете рекламы в запрещённых соцсетях с 1 сентября +32

    • 23   3300

    Основная проблема с кадрами или на заметку HR +36

    • 23   4000
  • Главная
  • Контакты
© 2025. Все публикации принадлежат авторам.