Шпаргалка по использованию docker

1) Установка на Ubuntu:

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin
docker --version

    2) Установка приложения через docker

    docker pull jetbrains/teamcity-server

    3) Запуск:

    docker run --name teamcity-server-instance \
    -v <path to data directory>:/data/teamcity_server/datadir \
    -v <path to logs directory>:/opt/teamcity/logs \
    -p <port on host>:8111 \
    jetbrains/teamcity-server

    4) Автозапуск после перезагрузки сервера:

    docker update --restart=always teamcity-server-instance 

    Датчик давления BMP-280 на raspberry pi

    Может работать как по I2C так и по протоколу SPI. В моём случае, я подключил по I2C.

    Схема подключения:

    BMP280 PinRaspberry Pi Pin
    VCC3.3V (Pin 1)
    GNDGround (Pin 6)
    SDASDA (Pin 3, GPIO2)
    SCLSCL (Pin 5, GPIO3)

    Далее необходимо зайти в raspi-config и включить интерфейс i2c. После чего понадобится малинку перазагрузить. После перезагрузки можно посмотреть, определяется ли она:

    i2cdetect -y 1

    Должно появиться что-то вроде:

    Иногда садится на 77 порт, но чаще на 76. Далее необходимо установить библиотеки:

    sudo apt install -y python3-smbus python3-spidev python3-pip
    pip3 install adafruit-circuitpython-bmp280

    Минимальный код для проверки работоспособности:

    #!/usr/bin/env python3
    import board
    import busio
    import adafruit_bmp280
    import time
    import datetime
    import requests
    import json
    import threading
    
    # Create sensor object using the I2C port
    i2c = busio.I2C(board.SCL,board.SDA)
    sensor = adafruit_bmp280.Adafruit_BMP280_I2C(i2c, address = 0x76)
    
    
    while True:
        print("\nTemperature: %0.1f C" % sensor.temperature)
        print("Pressure: %0.1f hPa" % sensor.pressure)
        mmHg = sensor.pressure * 0.75006
        print("Pressure: %0.1f mmHg" % mmHg)
        print("Altitude: %0.2f meters" % sensor.altitude)
        print("Sea Level Pressure: %0.1f hPa " % sensor.sea_level_pressure)
        print(datetime.datetime.now())
        time.sleep(10)

    У меня выводит что-то подобное:

    Часть 4: Объединяй и властвуй (с)

    Логическое продолжение Части 1, 2,3. Итак, научился принимать данные от zigbee устройств на стик Zigbee2Mqtt и на Алису. Да вот беда, одновременно и там и там данные от одного устройства штатными средствами не получить. А только на Алису завязывать все устройства бы не хотелось, так как:

    • сценарии ограничены только поддерживаемым Алисой оборудованием. Например мои WiFi реле Sonoff DIY 3 которые я использую на батареях Алисой естественно не поддерживаются .
    • Нет интернета — нет «умного» дома

    Потому и возникла задача перебросить некоторые устройства которые есть на стике на Алису. Например датчик температуры. И в принципе штатное решение есть от самого Яндекса. Правда они выбрали весьма трудоёмкое для этого способа решение: необходимо создать виртуальное устройство, написать для него API и подключить в качестве стороннего навыка «Умный дом». Т.е. схема взаимодействия вырисовывается такая:

    Т.е. что нужно сделать по шагам:

    1. Создать навык-приложение для «Умного дома»
    2. Сделать API «виртуального устройства» по документации Яндекса
    3. Подключить виртуальное устройство в навык
    4. Добавить навык в Яндекс Алису

    Создание навыка

    Для этого переходим по ссылке https://dialogs.yandex.ru/developer/smart-home и создаём новый навык.

    Важно! Тип доступа сделать приватным, тогда модерация будет «мгновенной», ну и собственно навык не будет доступен никому кроме вас.

    После заполнения основных данных, далее необходимо создать приложение https://oauth.yandex.ru/ с типом платформы WEB:

    Так вы получите необходимые для дальнейшей настройки навыка ClientID и Client secret, которые необходимо будет прописать в навыке на странице «Связка аккаунтов»:

    Кроме того необходимо прописать эндпоинты которые будут отвечать за авторизацию навыка на вашем сервере, обновление и получение токенов.

    API виртуального устройства

    Ну собственно на стороне сервера необходимо создать эндпоинты, которые сначала авторизуют навык, а затем отдадут данные «виртуального устройства». Например датчика температуры. Далее накидаю рабочие куски кода-шаблоны, которые пойдут как основа для «допила».

    auth.php:

    $redirect_uri = $_GET["redirect_uri"];
    $state = $_GET["state"];
    $client_id = $_GET["client_id"];
    header("Location: ".$redirect_uri."?code=1234&state=$state&client_id=$client_id");

    token.php:

    $code=$_POST["code"];
    $client_secret=$_POST["client_secret"];
    $grant_type=$_POST["grant_type"];
    $client_id=$_POST["client_id"];
    $redirect_uri=$_POST["redirect_uri"];
    
    $json='{
        "access_token": "ACCESS_TOKEN",
        "token_type": "bearer",
        "expires_in": 2592000,
        "refresh_token": "REFRESH_TOKEN",
        "scope": "read",
        "uid": 100101,
        "info": {
          "name": "donpadlo",
          "email": "info@mail.ru"
        }
      }';
    
     header('Content-Type: application/json');
     echo $json;

    refresh.php:

    $json='{
        "access_token": "ACCESS_TOKEN",
        "refresh_token": "'.$_GET['refresh_token'].'",
        "token_type": "bearer",
        "expires_in": 2592000 
      }';
    
    header('Content-Type: application/json');
     echo $json;

    Всё что выше — это авторизация навыка. После чего он полезет на Redirect URI  указанный в приложении, где будет ожидать ответа в формате json на два вида возможных запроса REQUEST_URI:

    • /v1.0/user/devices — получить список поддерживаемых устройств
    • /v1.0/user/devices/query — получить обновления данных

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

    index.php

    if ($_SERVER["REQUEST_URI"]=="/v1.0/user/devices"){
        $json='{
            "request_id": "'.$_SERVER["HTTP_X_REQUEST_ID"].'",
            "payload": {
              "user_id": "gribov_pi",
              "devices": [{
                "id": "abc-123",
                "name": "Розовая комната",
                "description": "Измеряет температуру и влажность",
                "room": "спальня",
                "type": "devices.types.sensor.climate",
                "custom_data": {
                  "foo": 1,
                  "bar": "two",
                  "baz": false,
                  "qux": [1, "two", false],
                  "quux": {
                    "quuz": {
                      "corge": []
                    }
                  }
                },
                "capabilities": [],      
                "properties": '.get_properties().',
                "device_info": {
                  "manufacturer": "Грибовы.рф",
                  "model": "Датчик температуры",
                  "hw_version": "1.0",
                  "sw_version": "1.0"
                }
              }]
            }}';
    };
    if ($_SERVER["REQUEST_URI"]=="/v1.0/user/devices/query"){
      $json='{
        "request_id": "'.$_SERVER["HTTP_X_REQUEST_ID"].'",
        "payload": {
          "devices": [{
            "id": "abc-123",
            "capabilities": [],
            "properties": '.get_properties().'
          }]
        }
      }';  
    };
    header('Content-Type: application/json');
    echo $json;
    die();
    
    
    function get_properties(){
      return '[
        {
          "type": "devices.properties.float",
          "retrievable": true,
          "reportable": true,
          "parameters": {
            "instance": "temperature",
            "unit": "unit.temperature.celsius"
          },
          "state": {
            "instance": "temperature",
            "value": 30
          },
          "last_updated": "2025-12-29 12:12:12"
        },
        {
          "type": "devices.properties.float",
          "retrievable": true,
          "reportable": true,
          "parameters": {
            "instance": "humidity",
            "unit": "unit.percent"
          },
          "state": {
            "instance": "humidity",
            "value": 70
          },
          "last_updated": "2025-12-29 12:12:12"
        }
      ]';  
    };

    Подключение виртуального устройства к Алисе

    Переходим в раздел «Тестирование» и подключаем вышесозданый навык:

    Как видим виртуальное устройство отображается, данные в нём обновляются, и его можно штатно использовать для создания различных сценариев в Алисе:

    Часть 3. Получение данных с Zigbee устройства.

    В первой и второй части, был прошит и настроен стик, а так-же установлен брокер сообщений и ZigBee2mqtt, Теперь попробуем подключить устройство и получить с него данные по температуре. Устройство — самый раздешевый датчик температуры, купленный на AliExpress за 267 рублей:

    Заходим в админ панель ZigBee2mqtt, по адресу: http://ip:8080 и нажимаем кнопку «Разрешить подключения». После чего на устройстве жмем кнопку reset скрепкой. Если всё удачно, то в течении нескольких секунд устройство будет обнаружено:

    Далее собственно при получении данных с устройства, ZigBee2mqtt будет отсылать данные по нему в json формате в очередь вида zigbee2mqtt/0xa4c13812c854f0f7. Хвост у данной очереди — МАС адрес устройства. Нашей дальнейшей задачей является эти данные собственно принять и обработать. Для этого воспользуемся python библиотекой paho-mqtt:

    pip install paho-mqtt --break-system-packages

    Оформить подписку можно например так:

    import context  
    import paho.mqtt.subscribe as subscribe
    
    def print_msg(client, userdata, message):
        print(message.topic)
        print(message.payload)
    
    subscribe.callback(print_msg, "#", hostname="localhost",auth={'username':"уакукауы","password":"укепукепк"})
    

    context.py:

    # -*- coding: utf-8 -*-
    
    # Ensure can import paho package
    try:
        import paho
    
    except ImportError:
        # This part is only required to run the examples from within the examples
        # directory when the module itself is not installed.
        import inspect
        import os
        import sys
    
        cmd_subfolder = os.path.realpath(
            os.path.abspath(
                os.path.join(
                    os.path.split(
                        inspect.getfile(inspect.currentframe())
                    )[0],
                    "..",
                    "src"
                )
            )
        )
        if cmd_subfolder not in sys.path:
            sys.path.insert(0, cmd_subfolder)
    
        import paho
    

    Ну и далее на свой вкус и цвет дальше можно эти данные уже как угодно обрабатывать

    ZigBee на Raspberry, часть 2, установка софта

    Итак, в первой части мы прошили стикер CC2531, теперь наша малинка готова стать шлюзом. Обычно схема работы Raspberry следующая:

    ZigBee2MQTT — нужен для того чтобы принять пакеты со стика CC2531 и отправить их в брокер сообщений. Которые в дальнейшем уже обработают скрипты для автоматизации чего-либо.

    Сначала поставим брокер сообщений mosquitto (как самое легкое):

    sudo apt-get install mosquitto

    И настроим файл конфигурации /etc/mosquitto/mosquitto.conf :

    pid_file /run/mosquitto/mosquitto.pid
    persistence true
    persistence_location /var/lib/mosquitto/
    log_dest file /var/log/mosquitto/mosquitto.log
    include_dir /etc/mosquitto/conf.d
    allow_anonymous true   # доступ для всех
    listener 1883 0.0.0.0  # слушаем все сетевые адреса

    Можно задать логин пароль для доступа, и разрешить слушать только localhost, но я это считаю излишним, т.к. всё равно чаще всего raspberry pi лежит в локальной сети и в интернет не смотрит. Далее включаем службу и стартуем её:

    sudo systemctl enable mosquitto
    sudo systemctl restart mosquitto

    Теперь ставим и настраиваем ZigBee2MQTT. Можно по туториалу на сайте разработчиков, а можно так, как описано ниже (без подробностей).

    sudo apt-get install nodejs git
    corepack enable
    sudo mkdir /opt/zigbee2mqtt
    sudo chown -R ${USER}: /opt/zigbee2mqtt
    git clone --depth 1 https://github.com/Koenkk/zigbee2mqtt.git /opt/zigbee2mqtt
    cd /opt/zigbee2mqtt
    pnpm install --frozen-lockfile
    cd /opt/zigbee2mqtt
    pnpm start

    После успешного старта будет доступен веб интерфейс для дальнейшей настройки в браузере http://ip:8080.

    Необходимо зайти, выбрать порт где расположен стик, и ввести данные для подключения к брокеру. После сохранить. Конфиг будет сохранен в /opt/zigbee2mqtt/data/configuration.yaml

    Далее оформим запуск ZigBee2MQTT как службу, создав и сохранив файл:

    [Unit]
    Description=zigbee2mqtt
    After=network.target
    
    [Service]
    Environment=NODE_ENV=production
    Type=notify
    ExecStart=/usr/bin/node index.js
    WorkingDirectory=/opt/zigbee2mqtt
    StandardOutput=inherit
    # Or use StandardOutput=null if you don't want Zigbee2MQTT messages filling syslog, for more options see systemd.exec(5)
    StandardError=inherit
    WatchdogSec=10s
    Restart=always
    RestartSec=10s
    User=pi
    
    [Install]
    WantedBy=multi-user.target
    sudo systemctl enable zigbee2mqtt
    sudo systemctl start zigbee2mqtt

    Ну и теоретически всё. По идее можно подключать устройства zigbee. В следующей части собственно это и рассмотрю.

    Update: в итоге решил таки не хранить все яйца в одном месте, и брокер сообщений mosquitto перенес с raspberry на другое устройство. В этом случае нужно установить пароль и чуть перенастроить конфигурационный файл

    Установка пароля:

    sudo mosquitto_passwd -c /etc/mosquitto/passwd логин
    chown mosquitto /etc/mosquitto/passwd
    chmod 0700 /etc/mosquitto/passwd

    И конфиг в конечном итоге у меня выглядит так:

    pid_file /run/mosquitto/mosquitto.pid
    persistence true
    persistence_location /var/lib/mosquitto/
    log_dest file /var/log/mosquitto/mosquitto.log
    include_dir /etc/mosquitto/conf.d
    allow_anonymous false   # доступ для всех
    password_file /etc/mosquitto/passwd
    listener 1883 0.0.0.0 

    1 2 3 59