CC2531 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╣реЛрдордмреНрд░рд┐рдЬ рдореЗрдВ ZigBee рдбрд┐рд╡рд╛рдЗрд╕реЗрд╕ рдЬреЛрдбрд╝рдирд╛

Xiaomi рдЧреЗрдЯрд╡реЗ рдЬреИрд╕реЗ рдмреНрд░рд╛рдВрдбреЗрдб рд╣рдм рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЗ рдмрд┐рдирд╛ рд╕реНрдорд╛рд░реНрдЯ рд╣реЛрдо рдХрдВрдЯреНрд░реЛрд▓ рд╕рд┐рд╕реНрдЯрдо рдХреЗ рд╕рд╛рде рд╡рд┐рднрд┐рдиреНрди рдирд┐рд░реНрдорд╛рддрд╛рдУрдВ рдХреЗ ZigBee рдбрд┐рд╡рд╛рдЗрд╕ рдмрдирд╛рдиреЗ рдХреЗ рддрд░реАрдХреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ Habr рдкрд░ рдкрд╣рд▓реЗ рд╣реА рд▓реЗрдЦ рдЖ рдЪреБрдХреЗ рд╣реИрдВ ред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдореБрдЭреЗ рд╣реЛрдордмреНрд░рд┐рдЬ рдХреЗ рд▓рд┐рдП рди рдХреЗрд╡рд▓ рд╣рдмреЗрд░рд╛ рдкрд░, рдмрд▓реНрдХрд┐ рдЕрдиреНрдп рдЗрдВрдЯрд░рдиреЗрдЯ рдЦреБрд▓реА рдЬрдЧрд╣реЛрдВ рдкрд░ рднреА рдирд┐рд░реНрджреЗрд╢ рдорд┐рд▓реЗ ред рдЗрд╕рд▓рд┐рдП, рдореИрдВ ZigBee рдЙрдкрдХрд░рдгреЛрдВ рдХреЛ рд╣реЛрдордмреНрд░рд┐рдЬ рдореЗрдВ рдЬреЛрдбрд╝рдиреЗ рдХрд╛ рдЕрдиреБрднрд╡ рд╕рд╛рдЭрд╛ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред рд╕рдВрд╕рд╛рдзрди zigbee2mqtt.io рдХреЗ рдирд┐рд░реНрдорд╛рддрд╛ рдХреЛ рдХрдИ рдзрдиреНрдпрд╡рд╛рдж рд╡реНрдпрдХреНрдд рдХрд┐рдП рдЬрд╛рдиреЗ рдЪрд╛рд╣рд┐рдП, CC2531 рдореЙрдбреЗрдо рдХреЛ рдлреНрд▓реИрд╢ рдХрд░рдиреЗ рдФрд░ рд╣реЛрдо рдЕрд╕рд┐рд╕реНрдЯреЗрдВрдЯ , рдбреЛрдореЛрдЯрд┐рдХреЛрдЬрд╝ рдФрд░ рдорд╛рдЬрд░реНрдбреЛрдореЛ рдЬреИрд╕реЗ рд╕реНрдорд╛рд░реНрдЯ рд╣реЛрдо рдХрдВрдЯреНрд░реЛрд▓ рд╕рд┐рд╕реНрдЯрдо рд╕реЗ рдХрдиреЗрдХреНрдЯ рдХрд░рдиреЗ рдХреЗ рддрд░реАрдХреЗ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╡рд╣рд╛рдВ рд╡рд░реНрдгрд┐рдд рд╣реИрдВ ред рд▓реЗрдЦ рдЙрди рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЗ рд▓рд┐рдП рд╣реИ рдЬреЛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╣реЛрдордмреНрд░рд┐рдЬ рд╕реНрдерд╛рдкрд┐рдд рдФрд░ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд┐рдП рдЧрдП рд╣реИрдВ ред


рд▓реЗрдЦ рдХреЗ рд╕рднреА рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдЙрдкрдХрд░рдг рдХреЗ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕реЗрдЯ рдХреЗ рд╕рд╛рде рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛:

  • рд░рд╛рд╕реНрдкрдмреЗрд░реА рдкрд╛рдИ 3 рдмреА + (рдУрдПрд╕ рд░рд╛рд╕реНрдкрдмрд┐рдпрди)
  • CC2531 рдбреЛрдВрдЧрд▓ (рд╕рд┐рд▓реЗ)
  • Xiaomi рдбрд┐рд╡рд╛рдЗрд╕ (рд╡рд╛рдпрд░рд▓реЗрд╕ рд╕реНрд╡рд┐рдЪ, рддрд╛рдкрдорд╛рди рдФрд░ рдЖрд░реНрджреНрд░рддрд╛ рд╕реЗрдВрд╕рд░ ...)
  • рдореИрдХрдмреБрдХ рдкреНрд░реЛ (OSX 10.14)

рд░реВрд╕реА рдореЗрдВ рдлрд░реНрдорд╡реЗрдпрд░ CC2531 рдХреЗ рд▓рд┐рдП рдирд┐рд░реНрджреЗрд╢ рдпрд╣рд╛рдВ (Pi рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ) рдФрд░ рдпрд╣рд╛рдВ (CCDebuger рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ) рд╣реИрдВ ред

рдпреЛрдЬрдирд╛ рдХреЗ рдЕрдиреБрд╕рд╛рд░, рдХрд╛рд░реНрдп рдХреА рдкреВрд░реА рд╢реНрд░реГрдВрдЦрд▓рд╛ рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рджрд░реНрд╢рд╛рдИ рдЬрд╛ рд╕рдХрддреА рд╣реИ:



рдЕрдм рдХреНрд░рдо рдореЗрдВред

рдореЙрдбреЗрдо рдХреЛ рдЪрдордХрд╛рдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдкрдХреЛ рдПрдордХреНрдпреВрдЯреАрдЯреА рдмреНрд░реЛрдХрд░ рдХреЛ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ (рдпрджрд┐ рдкрд╣рд▓реЗ рд╕реЗ рд╕реНрдерд╛рдкрд┐рдд рдирд╣реАрдВ рд╣реИ)ред

рдореИрдВ рдЗрд╕ рддрд░рд╣ рд╕реЗ рд╕реНрдерд╛рдкрд┐рдд рдореЙрд╕реНрдХрд┐рдЯреЛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ:

sudo apt install -y mosquitto mosquitto-clients # sudo services mosquitto start #  sudo systemctl enable mosquitto.service # 

рдЕрдзрд┐рдХ рд╡рд┐рд╕реНрддреГрдд рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдирд┐рд░реНрджреЗрд╢ рдпрд╣рд╛рдВ рджреЗрдЦреЗ рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВ ред

рдЕрдм рдЖрдкрдХреЛ zigbee2mqtt рд╕реЗрд╡рд╛ рдХреЛ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЬреЛ CC2531 рдореЙрдбреЗрдо рдХреЗ рд╕рд╛рде рдмрд╛рддрдЪреАрдд рдХрд░рддреА рд╣реИ рдФрд░ рдбреЗрдЯрд╛ рдХреЛ рдореЙрд╕реНрдХрд┐рдЯреЛ рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рддреА рд╣реИ:

 sudo git clone https://github.com/Koenkk/zigbee2mqtt.git /opt/zigbee2mqtt sudo chown -R pi:pi /opt/zigbee2mqtt cd /opt/zigbee2mqtt npm install 

рд╕реЗрд╡рд╛ рдХреЗ рд░реВрдк рдореЗрдВ zigbee2mqtt рдЪрд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдПрдХ рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:
/etc/systemd/system/zigbee2mqtt.service

рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕рд╛рдордЧреНрд░реА рдХреЗ рд╕рд╛рде:
 [Unit] Description=zigbee2mqtt After=network.target [Service] ExecStart=/usr/bin/npm start WorkingDirectory=/opt/zigbee2mqtt StandardOutput=inherit StandardError=inherit Restart=always User=pi [Install] WantedBy=multi-user.target 


рдпрджрд┐ рдЖрдкрдиреЗ MQTT рдмреНрд░реЛрдХрд░ рдкрд╣рд▓реЗ рд╣реА рд╕реНрдерд╛рдкрд┐рдд рдХрд░ рд▓рд┐рдпрд╛ рд╣реИ, рддреЛ рдЖрдкрдХреЛ рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдЗрд╕реЗ рдХрдиреЗрдХреНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рд╣реА рдкреИрд░рд╛рдореАрдЯрд░ рд░рдЬрд┐рд╕реНрдЯрд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:

 /opt/zigbee2mqtt/data/configuration.yaml 

рд╣рдо рд╕реЗрд╡рд╛ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕реЗ рдСрдЯреЛрд░рди рдореЗрдВ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ:

 sudo systemctl start zigbee2mqtt sudo systemctl enable zigbee2mqtt.service 

рд╣рдо рд▓реЙрдЧ рдХреЛ рджреЗрдЦрддреЗ рд╣реИрдВ:

 sudo journalctl -u zigbee2mqtt.service -f 

рдпрджрд┐ рд╕рдм рдХреБрдЫ рд╕рд╣реА рддрд░реАрдХреЗ рд╕реЗ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рддреЛ рдЖрдкрдХреЛ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд▓рд╛рдЗрдиреЗрдВ рджреЗрдЦрдиреА рдЪрд╛рд╣рд┐рдП:
 `permit_join` set to `true` in configuration.yaml. Allowing new devices to join. Set `permit_join` to `false` once you joined all devices. Zigbee: allowing new devices to join. Connecting to MQTT server at mqtt://localhost zigbee-shepherd ready Connected to MQTT server 


рдЖрдк рд╣реЛрдордмреНрд░рд┐рдЬ рдХреЗ рд╕рд╛рде рдПрдХреАрдХрд░рдг рд╢реБрд░реВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред Zigbee2mqtt.io рд╕рдВрд╕рд╛рдзрди рдореЗрдВ рдПрдХ рдЬреЛрдбрд╝реА рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдерд┐рдд рдЙрдкрдХрд░рдгреЛрдВ рдФрд░ рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреА рдПрдХ рд╕реВрдЪреА рд╣реИ ред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, Xiaomi рд╡рд╛рдпрд░рд▓реЗрд╕ рд╕реНрд╡рд┐рдЪ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред



рдореЙрд╕реНрдХрд┐рдЯреЛ рдореЗрдВ рдШрдЯрдирд╛рдУрдВ рдХреЛ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП, рдПрдордХреНрдпреВрдЯреАрдЯреА рдПрдХреНрд╕рдкреНрд▓реЛрд░рд░ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред рд╣рдо рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ, MQTT рд╕рд░реНрд╡рд░ рдХрд╛ рдкрддрд╛ рджрд░реНрдЬ рдХрд░рддреЗ рд╣реИрдВ, рдореЗрд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдпрд╣ 192.168.1.104 рдкрд░ рд╕реНрдерд┐рдд рд╣реИред рдпрджрд┐ рд╕рдм рдХреБрдЫ рд╕рд╣реА рддрд░реАрдХреЗ рд╕реЗ рд╕реНрдерд╛рдкрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рддреЛ рдкреЗрдбрд╝ рдореЗрдВ рд╣рдо zigbee2mqtt рд╢рд╛рдЦрд╛ рджреЗрдЦреЗрдВрдЧреЗред рд╣рдо рдЗрд╕рдореЗрдВ рдкрд╛рд╕ рд╣реЛ рдЧрдПред рдЕрдм Xiaomi рд╡рд╛рдпрд░рд▓реЗрд╕ рд╕реНрд╡рд┐рдЪ рдкрд░, рдбрд╛рдпреЛрдб рдмреНрд▓рд┐рдВрдХ (рд▓рдЧрднрдЧ 5 рд╕реЗрдХрдВрдб) рддрдХ рд░реАрд╕реЗрдЯ рдмрдЯрди рджрдмрд╛рдП рд░рдЦреЗрдВред Zigbee2mqtt рд╢рд╛рдЦрд╛ рдореЗрдВ рд▓рдЧрднрдЧ 10 рд╕реЗрдХрдВрдб рдХреЗ рдмрд╛рдж, рд╣рдо рдЕрдкрдиреЗ рдбрд┐рд╡рд╛рдЗрд╕ рдФрд░ рдбреЗрдЯрд╛ рдХреЛ рджреЗрдЦреЗрдВрдЧреЗ рдЬреЛ рдЗрд╕реЗ рдкреНрд░рд╕рд╛рд░рд┐рдд рдХрд░рддрд╛ рд╣реИред

рдпрджрд┐ рдРрд╕рд╛ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ, рддреЛ рдбрд╛рдпреЛрдб рдмреНрд▓рд┐рдВрдХ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдПрдХ рд╕реЗрдХрдВрдб рдХреА рдЖрд╡реГрддреНрддрд┐ рдХреЗ рд╕рд╛рде рдПрдХ рдмрд╛рд░ рд░реАрд╕реЗрдЯ рдХреЛ рджрдмрд╛рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВред рдпрд╣ рдЗрд╕ рддрд░рд╣ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП:



рдЖрдЗрдП рдбреЗрдЯрд╛ рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░реЗрдВ:

 { "linkquality":110, "battery":100, "voltage":3052, "click":"single" } 

рдХреНрд▓рд┐рдХ рдлрд╝реАрд▓реНрдб рдореЗрдВ рдХреНрд▓рд┐рдХ рдХреЗ рдкреНрд░рдХрд╛рд░ рд╣реЛрддреЗ рд╣реИрдВ; рдЙрдирдореЗрдВ рд╕реЗ рдкрд╛рдБрдЪ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ:
Click, double click, triple click, long, long_release

рд╣рдордиреЗ рд╕реАрдЦрд╛ рдХрд┐ рдбреЗрдЯрд╛ рдХреИрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЕрдм рд╣реЛрдордмреНрд░рд┐рдбрд┐рдЬ рдореЗрдВ Xiaomi рд╡рд╛рдпрд░рд▓реЗрд╕ рд╕реНрд╡рд┐рдЪ рдЬреЛрдбрд╝реЗрдВред MQTT рдХреЗ рд╕рд╛рде рдмрд╛рддрдЪреАрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рд╣реЛрдордмреНрд░рд┐рдЬ-mqttthing рдореЙрдбреНрдпреВрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред рдЕрдиреНрдп рд▓реЛрдЧреЛрдВ рдХреА рддрд░рд╣ рд╣реА рд╕реНрдерд╛рдкрд┐рдд:

 (sudo) npm install -g homebridge-mqttthing 

рдореЙрдбреНрдпреВрд▓ рд╕реНрд╡рд┐рдЪ рд╕реЗ рдерд░реНрдореЛрд╕реНрдЯреИрдЯреНрд╕ рддрдХ рдмрдбрд╝реА рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдЙрдкрдХрд░рдгреЛрдВ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИред Xiaomi рд╡рд╛рдпрд░рд▓реЗрд╕ рд╕реНрд╡рд┐рдЪ рдХреЗ рд▓рд┐рдП, StatelessProgramableSwitch рд╡рд░реНрдЧ рд╕рдмрд╕реЗ рдЙрдкрдпреБрдХреНрдд рд╣реИред рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ Topic (0x00158d00022c85ea) рдФрд░ рдХрдорд╛рдВрдбреНрд╕ рдХреЗ рдирд╛рдо рдЬрд╛рдирдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдпрд╣ рдЗрд╕ рддрд░рд╣ рдХрд╛ рд╡рд┐рдиреНрдпрд╛рд╕ рдХрд░рддрд╛ рд╣реИ:

 { "accessory": "mqttthing", "type": "statelessProgrammableSwitch", "name": "Xiaomi Single Button", "topics": { "getSwitch": { "topic": "zigbee2mqtt/0x00158d00022c85ea", "apply": "return JSON.parse(message).click;" } }, "switchValues": [ "single", "double", "long_release" ] } 

рд╕рд╛рджреГрд╢реНрдп рджреНрд╡рд╛рд░рд╛, рдореИрдВрдиреЗ рдХрд╣рд╛:

рддрд╛рдкрдорд╛рди рдФрд░ рдЖрд░реНрджреНрд░рддрд╛ рд╕реЗрдВрд╕рд░, рдЯрдЪ рд╕реЗрдВрд╕рд░, рдЙрдкрд╕реНрдерд┐рддрд┐ рд╕реЗрдВрд╕рд░ рдФрд░ рд╕реНрд╡рд┐рдЪред
 "accessories": [ { "accessory": "mqttthing", "type": "occupancySensor", "name": "Xiaomi Occupancy Sencor", "topics": { "getOccupancyDetected": { "topic": "zigbee2mqtt/0x00158d000236b492", "apply": "return JSON.parse(message).occupancy;" } }, "integerValue": true }, { "accessory": "mqttthing", "type": "contactSensor", "name": "Xiaomi Contatc Sencor", "topics": { "getContactSensorState": { "topic": "zigbee2mqtt/0x00158d000278db8c", "apply": "return !JSON.parse(message).contact;" } }, "integerValue": true }, { "accessory": "mqttthing", "type": "statelessProgrammableSwitch", "name": "Xiaomi Single Button", "topics": { "getSwitch": { "topic": "zigbee2mqtt/0x00158d00022c85ea", "apply": "return JSON.parse(message).click;" } }, "switchValues": [ "single", "double", "long_release" ] }, { "accessory": "mqttthing", "type": "temperatureSensor", "name": "Xiaomi Temperature Sencor", "topics": { "getCurrentTemperature": { "topic": "zigbee2mqtt/0x00158d000201842c", "apply": "return parseFloat(JSON.parse(message).temperature);" } }, "history": true }, { "accessory": "mqttthing", "type": "humiditySensor", "name": "Xiaomi Humidity Sencor", "topics": { "getCurrentRelativeHumidity": { "topic": "zigbee2mqtt/0x00158d000201842c", "apply": "return parseFloat(JSON.parse(message).humidity);" } }, "history": true } ] 


рд╣рдо рдЬрд╛рдБрдЪ рдХрд░рддреЗ рд╣реИрдВ:



рдореИрдВрдиреЗ рд╣реЛрдордмреНрд░рд┐рдЬ-рдПрдордЖрдИ-рдЕрдХрд╛рд░рд╛ рдореЙрдбреНрдпреВрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдерд╛, рдЬреЛ рдЬрд╝рд┐рдЧреЙрдмреА рдЧреЗрдЯрд╡реЗ рдХреЗ рд╕рд╛рде рдмрд╛рддрдЪреАрдд рдХрд░рддреЗ рд╣реБрдП рдЬрд╝рд┐рдЧрдмреА рдЙрдкрдХрд░рдгреЛрдВ рдХреЛ рдЬреЛрдбрд╝рддрд╛ рд╣реИред рдЬрдм рдЧреЗрдЯрд╡реЗ рдХреЛ рдордирд╛ рдХрд░ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдЙрдкрдХрд░рдгреЛрдВ рдХреА рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХрд╛ рд╕рдордп рдХрдо рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдореИрдВрдиреЗ рдЙрд╕ рдбрд┐рд╡рд╛рдЗрд╕ рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдкрд╛ рд▓рд┐рдпрд╛ рдЬреЛ рдореЗрд░реЗ рд╡рд╛рдИрдлрд╛рдИ рдкрд░ рдмреИрдарддрд╛ рд╣реИ рдФрд░ рд▓рдЧрд╛рддрд╛рд░ рдЗрдВрдЯрд░рдиреЗрдЯ рдкрд░ рдХреНрд░реЙрд▓ рдХрд░рддрд╛ рд╣реИред

Source: https://habr.com/ru/post/hi462459/


All Articles