Авторизация
Регистрация

Напомнить пароль

Да будет свет... умным? Наделяем настольную лампу свободной волей

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

В распоряжении у меня имелась неплохая китайская лампа бренда Uniel на 5V/1.5A или 8W.


Купил ее потому, что для своей небольшой цены в ней имелись 2 светодиодные ленты с теплым и холодным светом, 3 режима интенсивности, 3 режима освещения (теплый, холодный, смешанный — всего 9 вариантов настройки) и управление всем через сенсор.


Также подкупала полезная функция отображения времени, даты и температуры в комнате. Были и другие функции, вроде настраиваемого будильника и режима подсветки дисплея, но первое не очень-то нужно владельцу смартфона, а второе — выставил один раз и забыл (да в общем не сильно-то и надо выставлять).


В свое время (2020) лампа казалось достаточно продвинутой и удобной. В процессе эксплуатации, правда, вылезло пару недостатков. Например, крайне неудобное взаимодействие с настройками времени через панель на днище светильника (еще один укол в сторону использования как будильник). А как я задолбался включать свет тремя нажатиями по сенсору, словами не передать… Случайно включаешь лампу не полностью (один-два тыка из трех), потом тыкаешь выключить — она только разгорается ярче. Или думаешь, что включил не полностью, тапаешь быстро два-три раза — она заново включена. Протыкай еще n раз. Тот, кто придумал управление в духе дешевого фонарика на сенсоре прикосновений, должен гореть в аду!


Теперь, когда у меня появился локальный сервер умного дома, я говорю: «Довольно!». Да и давно хотел глянуть, что же у нее внутри. А если вам тоже стало интересно, присаживайтесь поудобнее и заваривайте чай — прогулка обещает быть интересной.

Аппаратная часть


Итак, разбираем лампу. Для этого нужно окрутить 4 винта на днище, закрытых приклеенной антискользящей лентой.


Под ними находится плата с кнопками под 4 шурупами. Отвинтив и их, нам откроются два невидимых винта крепления задней крышки, которые надо что? Правильно.

Так же следует поступаем с двумя видимыми с задней стороны корпуса.

После этого лампа… не разберется. Да, аккуратно отщелкиваем защелки по бокам корпуса, а вы что подумали?


Внутри мы видим массивный утяжелитель, достаточно крупную основную плату, субплату с кнопками, разъем питания, дисплей. Ну и всякие проводки, конечно, видим.

Внимательно посмотрим на основную плату. Среди множества непропаянных с завода элементов можно заметить огромную черную кляксу компаунда с кучей выводов, которая очевидно отвечает за дисплей. К ней также ведут выводы термистора. Ее я в этом выпуске трогать почти не буду. Почти. Пробегаем глазами ниже и видим единственную восьминогую микросхемку с затертой маркировкой. Это контроллер светодиодов. Он отвечает за сенсоры спереди и сзади лампы и управляет теплой и холодной светодиодными лентами, а еще подсветкой дисплея. Это можно проследить по дорожкам к управляющим мосфетам и сенсорным падам, прозвонив их мультиметром. Тебя-то мне и нужно!

Теперь наконец-то можно обозначить конкретный ход проекта:
  1. Заменить чип управления светом на умный
  2. Написать прошивку для нового чипа
  3. Интегрировать устройство в умный дом
В качестве умного чипа на замену выступит ESP-12, которых у меня лежит достаточно.


Поразмыслив над схемой, я решил также вывести управление дисплейной частью (4 кнопки на днище) в умный дом. Хотя обратной связи нет, это удобнее, чем переворачивать лампу и настраивать руками. Я думал вывести температуру с градусника в лампе в умный дом, но термистор оказался привязан к дисплею, так что в итоге я решил взять модуль AM2320 датчика температуры и влажности, и закинуть в умный дом его показания. Для сенсорых падов, которые нативно не поддерживаются выводами ESP-12, я использовал сенсорные модули TTP223, по 7 рублей штука. Cхема подключения к ESP получилась такая:


Это без учета стандартной обвязки ESP. Ее спаял навесом.


Схема обвязки


Питание взял на всякий случай со стабилизатора, на плате оно не выглядело мощным. На AM2320 я решил сэкономить пин и подключить его по интерфейсу OneWire, а не I2C. Для этого в даташите нарыл схему соединения выводов. Там было написано использовать сопротивление 5.1 кОм.


5.1 у меня не было, поставил 5.4. Да и пофиг! Оно заработало. В реальности вышло как-то так.


Все сделал навесом, а макетку с питающим стабилизатором я повесил на какой-то пустующий штырек под шуруп в корпусе. Удобно, спасибо китайцам! Пришло время поговорить о прошивке.

Программная часть

Я использую ESPHome в паре с HomeAssistant. Для того, чтобы прошить, необходимо добавить новый девайс из интерфейса EspHome Builder, выбрав нужные параметры устройства. В моем случае это ESP8266.


Теперь можно залить прошивку любым удобным способом, скомпилировав и скачав. Я просто использую ESPHome hub.


Для загрузки понадобится также цепь с UART-программатором.


Теперь, когда связь с контроллером установлена через API, прошивка заливается прямо по воздуху.

Все предварительные ласки мы завершили. Теперь ну… Собственно, самый сок.

Итак, по схеме мы управляем тремя источниками света (дисплей, теплая и холодная лента). Для этого устанавливаем соответствующие пины МК как output и привязываем к ним объекты lamp.
output:
  - platform: esp8266_pwm  # Для ESP8266, замените на "ledc" для ESP32
    id: pwm_backlight
    pin: GPIO3  # Укажите свой пин
    inverted: true
    frequency: 1000 Hz  # Частота ШИМ
  - platform: esp8266_pwm  # Для ESP8266, замените на "ledc" для ESP32
    id: pwm_warm_light
    pin: GPIO4  # Укажите свой пин
    frequency: 1000 Hz  # Частота ШИМ
  - platform: esp8266_pwm  # Для ESP8266, замените на "ledc" для ESP32
    id: pwm_cold_light
    pin: GPIO5  # Укажите свой пин
    frequency: 1000 Hz  # Частота ШИМ
    light:
  - platform: monochromatic
    name: "Яркость подсветки дисплея"
    output: pwm_backlight
    id: backlight
    restore_mode: RESTORE_DEFAULT_ON  # Запоминает последнее состояние

  - platform: monochromatic
    name: "Яркость теплого света"
    output: pwm_warm_light
    id: warm_light
    restore_mode: RESTORE_DEFAULT_ON  # Запоминает последнее состояние
    default_transition_length: 1s
        
  - platform: monochromatic
    name: "Яркость холодного света"
    output: pwm_cold_light
    id: cold_light
    restore_mode: RESTORE_DEFAULT_ON  # Запоминает последнее состояние
    default_transition_length: 1s
Чтобы также получить управление над кнопками на днище лампы в блок output следует добавить соответствующие пины конфигурации, а еще добавить блок кнопок, которые «дергают» эти выводы.
#продолжение output
  - platform: gpio
    id: button_up
    pin: GPIO13
    inverted: True
  - platform: gpio
    id: button_down
    pin: GPIO01
    inverted: True
  - platform: gpio
    id: button_s
    pin: GPIO00
    inverted: True
  - platform: gpio
    id: button_m
    pin: GPIO02
    inverted: True  
button:
  - platform: output
    name: "M"
    output: button_up
    duration: 300ms   
  - platform: output
    name: "S"
    output: button_down
    duration: 300ms   
  - platform: output
    name: "Up"
    output: button_s
    duration: 300ms   
  - platform: output
    name: "Down"
    output: button_m
    duration: 300ms   
Чтобы сделать управление с сенсорных кнопок добавим template switch, который будет отвечать сразу за теплый и холодный свет. Также необходимо реализовать кнопку, которая его сможет переключать. Ничего не забыли?.. А, точно! Еще добавим логику управления подсветкой дисплея через заднюю кнопку.
switch:
  - platform: template
    name: "Лампа Вкл/Выкл"
    id: lamp_power
    lambda: |-
      // Если хотя бы одна лента включена, переключатель считается "ON"
      return (id(warm_light).current_values.is_on() || id(cold_light).current_values.is_on());
    turn_on_action:
      - switch.turn_off: fire_switch
      - script.execute: apply_preset
    turn_off_action:
      - switch.turn_off: fire_switch
      - light.turn_off: warm_light
      - light.turn_off: cold_light
binary_sensor:
  - platform: gpio
    pin:
      number: GPIO12  # Физическая кнопка на этом пине
      mode: INPUT_PULLUP
      inverted: true  # Используется PULLUP, значит логика инвертирована
    name: "Кнопка управления светом"
    filters:
      - delayed_on: 50ms  # Фильтр для устранения дребезга
    on_click:
      - switch.toggle: lamp_power
          
  - platform: gpio
    pin:
      number: GPIO14  # Физическая кнопка на этом пине
      mode: INPUT_PULLUP
      inverted: true  # Используется PULLUP, значит логика инвертирована
    name: "Кнопка управления подсветкой"
    filters:
      - delayed_on: 50ms  # Фильтр для устранения дребезга
    on_click:
      - light.toggle: backlight
Ну и последнее, сенсор температуры и влажности. Изначально я даже не выставлял model, и все прекрасно показывало в автоматическом режиме, но после одного прекрасного ребута я увидел, что в комнате похолодало до -12.


Далее ребуты уже не помогали. В общем, как-то странно работает режим авто-определения сенсора. Но после наобум выставленного DHT22 проблем не было.
  - platform: dht
    model: DHT22
    pin: GPIO16  # Подключите DATA к этому пину
    temperature:
      name: "Температура"
      id: temp_sensor
      accuracy_decimals: 1
    humidity:
      name: "Влажность"
      id: hum_sensor
      accuracy_decimals: 1
    update_interval: 60s  # Обновление данных раз в 60 секунд
Так, теперь свет у нас включается плавно, есть управление прямо из HomeAssistant, есть регулировка яркости с точностью до процента, можно смотреть температуру и влажность. Что еще надо?



А надо пресеты, как было изначально. Только лучше! Теперь-то я могу сделать настраиваемые пресеты, да и кастомные эффекты тоже.


Логика работы пресетов такая — пресет выбирается либо из умного дома, либо руками (зажатием кнопки включения). Если надо изменить пресет, необходимо из умного дома выбрать нужную яркость и нажать кнопку «сохранить». Всего я сделал 3 пресета, чтобы долго не выбирать их руками (да и этого достаточно).


Также я реализовал кастомный эффект огня, скомбинировав flicker и скрипт случайной яркости. Эффект огня я повесил на двойной клик кнопки переключения подсветки дисплея. На видео не так красиво выглядит, как на глаз.


В общем и целом код получился довольно объемным (если yaml можно назвать кодом). С первого раза может быть не совсем понятно, что здесь и зачем, но разобраться довольно легко, если вы знакомы с программированием.
Полный код проекта
substitutions:
  name: smart-desk-lamp
  friendly_name: Smart Desk Lamp

esphome:
  name: ${name}
  friendly_name: ${friendly_name}

esp8266:
  board: esp01_1m

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: !your_key

ota:
  - platform: esphome
    password: !your_pass

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Smart-Desk-Lamp Fallback Hotspot"
    password: !your_pass_hotspot

captive_portal:

globals:
  - id: warm_current_brightness
    type: float
    restore_value: no
    initial_value: "0.2"    # стартовое значение для теплой ленты (20%)
  - id: warm_target_brightness
    type: float
    restore_value: no
    initial_value: "0.2"
  - id: cold_current_brightness
    type: float
    restore_value: no
    initial_value: "0.15"   # стартовое значение для холодной ленты (15%)
  - id: cold_target_brightness
    type: float
    restore_value: no
    initial_value: "0.15"

  - id: preset1_warm
    type: float
    restore_value: no
    initial_value: "0.5"    # Пресет 1: 50% тёплая
  - id: preset1_cold
    type: float
    restore_value: no
    initial_value: "0.5"    # Пресет 1: 50% холодная
  - id: preset2_warm
    type: float
    restore_value: no
    initial_value: "0.8"    # Пресет 2: 80% тёплая
  - id: preset2_cold
    type: float
    restore_value: no
    initial_value: "0.3"    # Пресет 2: 30% холодная
  - id: preset3_warm
    type: float
    restore_value: no
    initial_value: "0.3"    # Пресет 3: 30% тёплая
  - id: preset3_cold
    type: float
    restore_value: no
    initial_value: "0.8"    # Пресет 3: 80% холодная
  - id: current_preset
    type: int
    restore_value: no
    initial_value: "1"      # Текущий пресет (1, 2 или 3)

  - id: is_effect_on
    type: bool
    restore_value: yes
    initial_value: "false"      # Световой эффект (вкл/выкл)

output:
  - platform: esp8266_pwm  # Для ESP8266, замените на "ledc" для ESP32
    id: pwm_backlight
    pin: GPIO3  # Укажите свой пин
    inverted: true
    frequency: 1000 Hz  # Частота ШИМ
  - platform: esp8266_pwm  # Для ESP8266, замените на "ledc" для ESP32
    id: pwm_warm_light
    pin: GPIO4  # Укажите свой пин
    frequency: 1000 Hz  # Частота ШИМ
  - platform: esp8266_pwm  # Для ESP8266, замените на "ledc" для ESP32
    id: pwm_cold_light
    pin: GPIO5  # Укажите свой пин
    frequency: 1000 Hz  # Частота ШИМ

  - platform: gpio
    id: button_up
    pin: GPIO13
    inverted: True
  - platform: gpio
    id: button_down
    pin: GPIO01
    inverted: True
  - platform: gpio
    id: button_s
    pin: GPIO00
    inverted: True
  - platform: gpio
    id: button_m
    pin: GPIO02
    inverted: True

sensor:
  - platform: uptime   
    name: ${name}_uptime 
    id: uptime_sec 
    internal: true 
  - platform: wifi_signal 
    name: ${name}_WiFi_Signal" 
    update_interval: 60s 

  - platform: dht
    model: DHT22
    pin: GPIO16  # Подключите DATA к этому пину
    temperature:
      name: "Температура"
      id: temp_sensor
      accuracy_decimals: 1
    humidity:
      name: "Влажность"
      id: hum_sensor
      accuracy_decimals: 1
    update_interval: 60s  # Обновление данных раз в 60 секунд

light:
  - platform: monochromatic
    name: "Яркость подсветки дисплея"
    output: pwm_backlight
    id: backlight
    restore_mode: RESTORE_DEFAULT_ON  # Запоминает последнее состояние

  - platform: monochromatic
    name: "Яркость теплого света"
    output: pwm_warm_light
    id: warm_light
    restore_mode: RESTORE_DEFAULT_ON  # Запоминает последнее состояние
    default_transition_length: 1s
    effects:
      - flicker:
          name: Flicker Effect
        
  - platform: monochromatic
    name: "Яркость холодного света"
    output: pwm_cold_light
    id: cold_light
    restore_mode: RESTORE_DEFAULT_ON  # Запоминает последнее состояние
    default_transition_length: 1s

switch:
  - platform: template
    name: "Лампа Вкл/Выкл"
    id: lamp_power
    lambda: |-
      // Если хотя бы одна лента включена, переключатель считается "ON"
      return (id(warm_light).current_values.is_on() || id(cold_light).current_values.is_on());
    turn_on_action:
      - switch.turn_off: fire_switch
      - script.execute: apply_preset
    turn_off_action:
      - switch.turn_off: fire_switch
      - light.turn_off: warm_light
      - light.turn_off: cold_light

  - platform: template
    name: "Эффект огня"
    id: fire_switch
    restore_mode: ALWAYS_OFF
    turn_on_action:
      - lambda: |-
          id(is_effect_on) = true;
      - light.turn_on: 
          id: warm_light
          effect: "Flicker Effect"
      - script.execute: fire_effect
    turn_off_action:
      - lambda: |-
          id(is_effect_on) = false;
      - script.stop: fire_effect
      - light.turn_on: 
          id: warm_light
          effect: none
      - script.execute: apply_preset
    optimistic: true

button:
  - platform: output
    name: "M"
    output: button_up
    duration: 300ms   
  - platform: output
    name: "S"
    output: button_down
    duration: 300ms   
  - platform: output
    name: "Up"
    output: button_s
    duration: 300ms   
  - platform: output
    name: "Down"
    output: button_m
    duration: 300ms   

  - platform: template
    name: "Сохранить пресет яркости"
    on_press:
      then:
        - lambda: |-
              if (id(current_preset) == 1) {
                id(preset1_warm) = id(warm_light).current_values.get_brightness();
                id(preset1_cold) = id(cold_light).current_values.get_brightness();
              } else if (id(current_preset) == 2) {
                id(preset2_warm) = id(warm_light).current_values.get_brightness();
                id(preset2_cold) = id(cold_light).current_values.get_brightness();
              } else if (id(current_preset) == 3) {
                id(preset3_warm) = id(warm_light).current_values.get_brightness();
                id(preset3_cold) = id(cold_light).current_values.get_brightness();
              }

select:
  - platform: template
    name: "Пресет лампы"
    id: lamp_preset
    options:
      - "Preset 1"
      - "Preset 2"
      - "Preset 3"
    optimistic: true
    set_action:
      - lambda: |-
          if (x == "Preset 1") {
            id(current_preset) = 1;
          } else if (x == "Preset 2") {
            id(current_preset) = 2;
          } else if (x == "Preset 3") {
            id(current_preset) = 3;
          }
          id(apply_preset).execute();
    update_interval: 1s

binary_sensor:
  - platform: gpio
    pin:
      number: GPIO12  # Физическая кнопка на этом пине
      mode: INPUT_PULLUP
      inverted: true  # Используется PULLUP, значит логика инвертирована
    name: "Кнопка управления светом"
    filters:
      - delayed_on: 50ms  # Фильтр для устранения дребезга
    on_click:
      - switch.toggle: lamp_power
    on_multi_click:
      - timing:
          - on for at least 1s
        then:
          - select.next: lamp_preset
          
  - platform: gpio
    pin:
      number: GPIO14  # Физическая кнопка на этом пине
      mode: INPUT_PULLUP
      inverted: true  # Используется PULLUP, значит логика инвертирована
    name: "Кнопка управления подсветкой"
    filters:
      - delayed_on: 50ms  # Фильтр для устранения дребезга
    on_click:
      - light.toggle: backlight
    on_double_click:
      then:
        - switch.toggle: fire_switch

text_sensor: 
  - platform: template 
    name: ${friendly_name}_uptime 
    lambda: |- 
      int seconds = (id(uptime_sec).state); 
      int days = seconds / (24 * 3600); 
      seconds = seconds % (24 * 3600);  
      int hours = seconds / 3600; 
      seconds = seconds % 3600; 
      int minutes = seconds /  60; 
      seconds = seconds % 60; 
      return { (String(days) +" д. " + String(hours) +" ч. " + String(minutes) +" мин.").c_str() }; 
    icon: mdi:clock 
    update_interval: 113s 

script:
  - id: fire_effect
    mode: restart
    then:
      - repeat:
          count: 10000  # Бесконечный цикл (либо можно указать большое число)
          then:
            - light.turn_on:
                id: warm_light
                brightness: !lambda 'return 0.2 + ((float) random(50) / 100.0);'  # 20-70%
                transition_length: 1s
            - light.turn_on:
                id: cold_light
                brightness: !lambda 'return ((float) random(30) / 100.0);'  # 0-30%
                transition_length: 1s
            - delay: !lambda 'return (float)(50 + random(200));'  # Задержка от 50 до 250 мс
  - id: apply_preset
    then:
      - if:
          condition:
            lambda: 'return id(current_preset) == 1;'
          then:
            - light.turn_on:
                id: warm_light
                brightness: !lambda 'return id(preset1_warm);'
            - light.turn_on:
                id: cold_light
                brightness: !lambda 'return id(preset1_cold);'
      - if:
          condition:
            lambda: 'return id(current_preset) == 2;'
          then:
            - light.turn_on:
                id: warm_light
                brightness: !lambda 'return id(preset2_warm);'
            - light.turn_on:
                id: cold_light
                brightness: !lambda 'return id(preset2_cold);'
      - if:
          condition:
            lambda: 'return id(current_preset) == 3;'
          then:
            - light.turn_on:
                id: warm_light
                brightness: !lambda 'return id(preset3_warm);'
            - light.turn_on:
                id: cold_light
                brightness: !lambda 'return id(preset3_cold);'

Собственно, в то время как лампа стала максимально удобной в использовании, пора творить настоящую магию. Сделаем, чтобы лампа включалась сама, когда садишься за стол вечером. А еще добавим уведомления о всяких событиях через ее мигание. Настало время…

Интеграции с умным домом

Во-первых, выведем управление яркостью и пресетами на главную страницу.


Кроме того, выведем графики влажности и температуры.


Скрипт для мигания достаточно простой.


В отсутствие настроенной системы уведомлений просто повесил его исполнение на кнопку в интерфейсе. У меня уже есть автоматизация, чтобы проигрывать голосовые сообщения (чтобы не орать из другой части дома, например), добавим на ее еще и световое уведомление.


Что касается автовключения, у меня есть еще кое-какое умное устройство с микроволновым датчиком присутствия ld2420 (о нем, пожалуй расскажу в другой статье). В датчике есть параметр расстояния. Методом тыка я нашел комфортную дистанцию, на которой лампа срабатывает уверенно при нахождении за столом. Также из своих умных жалюзи (статья) я использовал параметр освещенности. Логика простая — если за столом кто-то есть и в комнате достаточно темно или включено верхнее освещение, лампа активируется.

alias: Включение света по присутствию
description: ""
triggers:
  - trigger: numeric_state
    entity_id:
      - sensor.esphome_web_97f3af_moving_distance
    below: 170
conditions:
  - condition: or
    conditions:
      - type: is_value
        condition: device
        device_id: 6f308921f943e7d1ea97c9ce587d60d9
        entity_id: ed17ecded4455a307b5dc24e0aeddb88
        domain: sensor
        below: 1100
      - type: is_value
        condition: device
        device_id: 6f308921f943e7d1ea97c9ce587d60d9
        entity_id: ed17ecded4455a307b5dc24e0aeddb88
        domain: sensor
        above: 2500
actions:
  - type: turn_on
    device_id: 1c3fdf6ccde0e04e0d3c9638a102eb53
    entity_id: e3b0ea862766945de042cc6ccc838f88
    domain: switch
mode: single
И выключается по присутствию.

alias: Выключение света по присутствию
description: ""
triggers:
  - trigger: numeric_state
    entity_id:
      - sensor.esphome_web_97f3af_moving_distance
    above: 170
actions:
  - type: turn_off
    device_id: 1c3fdf6ccde0e04e0d3c9638a102eb53
    entity_id: e3b0ea862766945de042cc6ccc838f88
    domain: switch
mode: single

Как это работает, можете увидеть на гифке.


Ну что же, кажется план был выполнен и даже немного перевыполнен. Проект получился достаточно простой в исполнении, но гибкий за счет использования EspHome. И в отличие от всяких покупных ламп он совсем не зависит от сторонних серверов и приложений. Бонусом ко всему идет нативное голосовое управление через моего локального голосового ассистента.


Но его настройка как-то идет мимо форматов статей на PlusPda. Так что просто скажу, что создать своего локального ассистента в HomeAssistant не так уж и сложно, а гибкая архитектура позволяет даже интегрировать голосовые модели…

Что касается затрат на проект, по деньгам вышло чуть меньше 200 рублей. По времени всего пару вечеров на выходных. А результат налицо! Ну а я с вами не прощаюсь. Увидимся в следующем выпуске!
Добавить в избранное
+4 +6
свернутьразвернуть
Комментарии (6)
RSS
+
avatar
+2
  • NikoM
  • 24 февраля 2025, 00:05
Боюсь представить как у Вас работает унитаз.
+
avatar
0
  • oleg235
  • 24 февраля 2025, 00:15
неплохая китайская лампа бренда Uniel на 5V/1.5A или 8W.
Выберите что-нибудь одно.
Зачем нужны все эти извращения с прошивками и ESP8266, если в лампу на производстве забыли свет положить?
+
avatar
+1
  • Omnicorn
  • 24 февраля 2025, 00:40
Мне хватает
+
avatar
+1
  • aliex
  • 24 февраля 2025, 01:13
Да вроде для настольной лампы это с избытком даже… Всю жизнь в них 40-ваттные лампочки совали, это даже меньше света
+
avatar
+1
  • oleg235
  • 24 февраля 2025, 01:18
Всю жизнь в них 40-ваттные лампочки совали
У меня в студенческой общаге туда была вкручена 150-ка, пока комендант не отобрал.
+
avatar
+2
  • aliex
  • 24 февраля 2025, 01:47
Единственный источник света на всё комнату, что ли?
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.