aqc_embedded_doc
README. hw-keeper. Сервис, контроллирующий критически важную для работоспособности функциональность устройства

Зависимости

Building

  • c++17
  • libdbus
  • libjansson
  • libhwhelper (1.4.0)
  • contactless.h из libaqc_emv_ctls_l1

Runtime

  • ofono
  • connman
  • udev
  • libdbus
  • libjansson
  • libhwhelper

Building documentation

Для создания документации сначала установите зависимости (doxygen, doxyqml and dot):

sudo apt install doxygen graphviz doxyqml

Затем создайте документацию:

doxygen ./Doxyfile

Документация будет создана в папке ./doc/html/. Чтобы открыть документацию, откройте файл ./doc/html/pages.html в браузере.

Терминология

Сервис - программа hw-keeper

Офоно - программа ofono

Коннман - программа connman

АЦП/ADC - Аналогово-цифровой преобразователь / Analog-to-digital converter

Пульсация (на GPIO) - попеременное включение и выключение GPIO с заданной длительностью и периодом.

Описание

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

Задачи Сервиса:

  • Выполнять настройку куба (timezone, логгирование)
  • Выполнять настройку модема.
  • Выполнять первичную активацию контекста. При первом запуске модема коннман не активирует контекст.
  • Восстанавливать соединение, если связь была потеряна. Коннман не всегда может сам восстановить связь, и для этого необходимо переактивировать контекст либо перезагрузить модем.
  • Мониторинг значений АЦП, с помощью которых определяется значения силы тока и напряжения источника питания, а также температура устройства, получаемая из термистра. Предоставляется DBus интерфейс.
  • Pipe интерфейс для выполнения звукового сигнала по команде.
  • Выполнение пульсаций по команде через DBus интерфейс.

Сервис по своему функционалу разделен на следующие логические модули:

  • HwMonitor - мониторинг подключенных/отключенных устройств. Нужен для обнаружения модема.
  • Modem - включение, настройка, выключение модема.
  • CellularManager - менеджер мобильной связи. Активация контекста, контроль соединения.
  • AdcReader - мониторинг значений АЦП и уведомление
  • Beeper - ожидание команды по fifo для бипера
  • PulsatorManager - менеджер пульсаций. Выполняет поступившую команду на запуск пульсации.
  • DBusServer - предоставление DBus API.

Все модули выполняются в отдельном одноименном треде (кроме PulsatorManger).

Некоторые модули изменяют значения GPIO. Соответствие имени и пути до файла:

PB14: /sys/class/gpio/PB14/direction // направление
/sys/class/gpio/PB14/value // значение

Запись "PB14 -> 1" означает запись значения 1 в value файл. Перед этим в direction будет записано out.

Сервис также имеет функционал, не относящийся к какому-либо из перечисленных модулей. Они описаны в разделе "Прочие возможности".

Параметры

Документация по всем параметрам ведётся здесь: https://gitlab.aqsi.ru/pg-group/documentation/aqsi/-/blob/test/models/cube-settings-admin.md

Параметры берутся из общей конфигурации куба, из файла /mnt/data/aqsi-config.json.

Сервис поддерживает сигнал SIGHUP, при котором происходит обновление значений всех параметров из файла конфигурации, а также их применение.

В начале описания каждого модуля приведен список параметров, влияющих на функционал модуля, в формате

"ИмяПараметра": ДефолтноеЗначение // Комментарий

Если параметр обозначает какое-то время (таймаут), то он указывается в миллисекундах (например, ModemPowerCommandSwitchTimeout). Если в конце имени параметра есть S, то в секундах (например, RestartModemOnErrorTimeoutS).

HwMonitor

Модуль с помощью libudev определяет, какое оборудование в кубе подключается и отключается. Реализация близка к той, что в офоно:

С помощью udev rules usb-модему с определенным VID/PID ставится метка OFONO_DRIVER, в которой записывается название модема (gemalto, quectel). При подключении устройства, офоно и Сервис смотрят на эту метку и определяют, как дальше с ним работать. Сервис передает дальше управление модулю Modem.

Modem

Параметры:

"StartModemOnPoweron": 1 // Поведение при включении
"ModemStopStartTimeout": 3000 // Время между выключением и включением модема
"ModemPowerCommandSwitchTimeout": 800 // Время "зажима" кнопки включения модема

Модуль запускает и настраивает модем, найденный с помощью HwMonitor.

В зависимости от StartModemOnPoweron различается поведение при старте:

0. Модем не включается

  1. Модем включается, если не обнаружен
  2. Модем перезапускается

Поддерживается 2 типа модема: gemalto, quectel. Если модем неизвестен, используется схема работы для quectel.

Управление модема происходит с помощью записи в GPIO:

  • PB14 - подача питания. Для cube-a используется PB15
  • PC10 - команда (кнопка) включения

Включение

  1. PB14 -> 1
  2. sleep 30 ms
  3. PC10 -> 1
  4. sleep ModemPowerCommandSwitchTimeout ms
  5. PC10 -> 0

Выключение (gemalto)

  1. AT^SMSO
  2. Ожидание выключения, не более 3 секунд
  3. PB14 -> 0

Выключение (quectel)

  1. PC10 -> 1
  2. sleep ModemPowerCommandSwitchTimeout ms
  3. PC10 -> 0
  4. sleep 30 ms
  5. PB14 -> 0

Перезапуск

  1. Выключение
  2. sleep ModemStopStartTimeout ms
  3. Включение

Настройка (gemalto)

После включения происходит настройка с помощью AT команд. Проверяются следующие параметры, если отличны, то устанавливаются:

  • AT^SCFG="Gpio/mode/SYNC" - "std"
  • AT^SCFG="Serial/Interface/Allocation" - "2"
  • AT^SLED=2,10
  • В случае cube-a дополнительно устанавливает AT^SCPIN=1,6,1,0 (для контроля ADC)

Настройка (quectel)

Не происходит

CellularManager

Параметры:

"PingServer": "yandex.ru" // Адрес для проверки соединения через ping
"PingServers": [] // Если не пустой, пингует указанный список адресов (PingServer в этом случае игнорируется)
// Пример списка: ["yandex.ru", "google.com", "ru.wikipedia.org"]
"PingTimeoutS": 60 // время ожидания ping
"PingDataSize": 0 // аргумент опции ping -s
"PingRetries": 3 // сколько пингов в рамках одной проверки соединения
"CellularManagerMode": 1 // Варианты: 0, 1, 2
"CellularAutoSetup": 0 // Режим автонастройки
"CellularAPN": "" // Настройка контекста AccessPointName
"CellularUsername": "" // Настройка контекста Username
"CellularPassword": "" // Настройка контекста Password
"CellularAuthMethod": "" // Настройка контекста AuthenticationMethod, варианты: "pap", "chap", "none". В случае иной строки не меняется
"CellularProtocol": "" // Настройка контекста Protocol, варианты: "ip", "ipv6", "dual". В случае иной строки не меняется
"CellularEnableRoaming": 1 // Роуминг включен. Нужен для M2M симкарт
"RestartModemOnErrorTimeoutS": 480 // 8 * 60, время ожидания появления связи после включения модема
"RestartModemOnErrorMaximumTimeoutS": 28800 // 3600 * 8, максимальное время ожидания

Модуль осуществляет активацию и переактивацию контекста при необходимости, так же по необходимости отправляет в Modem команду на перезапуск модема.

Данный функционал был написан как дополнение возможностей коннмана в плане управления контекстом, потому что существуют следующие сценарии, при которых connman не способен самостоятельно восстановить связь:

  • Временно отошёл контакт симки
  • Ухудшение качества связи, попытка активации, бесконечный ответ от офоно OperationInProgress при фактическом наличии связи
  • Ухудшение качества связи, попытка активации, ошибка офоно OpeationFailed при фактическом наличии связи

Программно невозможно дифференцировать случаи, когда для восстановления связи достаточно переактивировать контекст, а когда нужно перезапускать модем, поэтому используется следующий алгоритм:

  1. Пропала связь
  2. Переактивация контекста
  3. Если связь не появилась в течение таймаута RestartModemOnErrorTimeoutS, перезапустить модем
  4. Таймаут ожидания появления связи увеличивается вдвое (но не более, чем RestartModemOnErrorMaximumTimeoutS)

Активация контекста

Основная задача, которую выполняет модуль - это активация контекста. Процесс реализован в виде конечного автомата. Переключение состояний в логе отображается как

(State1) -> (State2)

Список состояний:

  • Default - изначальное состояние
  • Initializing - ожидание модема
  • InitializingLong - ожидание модема без таймера на перезапуск модема
  • FindingObjectPath - получение object_path от офоно
  • CheckingSimPresenting - проверка наличия симкарты
  • FindingContextPath - получение context_path (по признаку type "internet")
  • SettingUpInternetSettings - выставление настроек роуминга, APN, Username, Password, AuthMethod, Protocol
  • ActivatingContext - команда активации контекста
  • CheckingConnection - проверка соединения через пинг

Диаграмма переходов состояний:

CellularManagerStatesDiagram

Если во время действия внутри состояния произошла ошибка, действие повторяется через 3 секунды.

Default

В этом состоянии модуль находится изначально. Поведение различается в зависимости от CellularManagerMode:

0. Модуль отключен, находится в режиме ожидания, пока параметр не примет другое значение.

  1. Происходит первичная активация контекста, после чего идёт проверка соединения без указания интерфейса. Таким образом, если есть подключение по ethernet, то даже если нет связи по модему, он не будет переактивироваться/перезапускаться.
  2. Как в п.1, только проверка соединения идет по интерфейсу ppp0. Даже если есть связь по ethernet, модем будет переактивироваться/перезапускаться.

Initializing / InitializingLong

Ожидание модуля Modem до момента, когда модем будет включен и настроен (инициализирован).

FindingObjectPath

Получение object_path модема (здесь и далее все команды выполняются через офоно)

Команда: org.ofono.Manager.GetModems

CheckingSimPresenting

Проверка наличия симкарты. Если симкарты нет, остаёмся на этом состоянии.

Команда: org.ofono.SimManager.GetProperties

Проверяется Present property.

FindingContextPath

Получение информации о контексте, в частности path.

Команда: org.ofono.ConnectionManager.GetContexts

Ищется контекст с ConnectionContext property Type = "internet".

Помимо пути из контекста получаем настройки:

Команда: org.ofono.ConnectionContext.GetProperties

Properties:

  • AccessPointName
  • Username
  • Password
  • AuthenticationMethod
  • Protocol

SettingUpInternetSettings

Поведение различно, в зависимости от CellularAutoSetup:

0. Параметры выставляются исходя из параметров CellularAPN, CellularUsername, CellularPassword. Если в них пустая строка, то ничего не меняется.

  1. APN/User/Pass выставляются исходя из таблицы в Приложении 1. В этом случае вышеуказанные параметры не используются.

Сначала выставляется CellularEnableRoaming с помощью команды:

org.ofono.ConnectionManager.SetProperty(RoamingAllowed)

После чего выставляются остальные настройки в порядке, указанном в списке "Properties" в FindingContextPath.

Команда: org.ofono.ConnectionContext.SetProperty

Перед каждым вызовом ConnectionContext.SetProperty происходит отключение cellular technology на уровне коннмана, т.к. иначе настройка не применится. Для этого используется команда net.connman.Technology.SetProperty , property Powered -> false. После завершения ConnectionContext.SetProperty, Powered снова выставляется в true.

ActivatingContext

Команда: org.ofono.ConnectionContext.SetProperty

Active -> true

CheckingConnection

После того, как контекст активирован, происходит проверка соединения с помощью команды ping.

Адрес пинга берется из PingServer либо PingServers.

  • PingServer - строка, например "yandex.ru". Пинг идет PingRetries раз до "yandex.ru"
  • PingServers - массив строк, например ["google.com", "yandex.ru"]. Пинг идёт PingRetries раз сначала до "google.com", потом PingRetries раз до "yandex.ru". Если PingServers не пустой, то PingServer игнорируется.

Как только пройдёт хотя бы 1 пинг, проверка считается успешной, связь есть.

Итоговая команда зависит от CellularManagerMode:

  1. ``` ping -c1 -s <PingDataSize> <Address from PingServer(s)>
    2.
    ping -c1 -I ppp0 -s <PingDataSize> <Address from PingServer(s)>
    Если по результатам проверки связь отсутствует, происходит отключение контекста (команда та же, что и при включении, только с параметров false). После этого происходит переход в состояние Initializing.
    #### Механизм перезапуска модема
    В модуле присутствует таймер перезапуска модема, далее - Таймер. У таймера есть Интервал, который изначально равен `RestartModemOnErrorTimeoutS`. Интервал не может превышать `RestartModemOnErrorMaximumTimeoutS`.
    Таймер:
    * Запускается в состоянии Default
    * Сбрасывается в состоянии InitializingLong
    * Сбрасывается в состоянии ConnectionChecking в случае успешной проверки связи
    * Не учитывается при срабатывании в случае, если отсутствует симка
    При срабатывании таймера, в каком бы состоянии не находились, происходит перезапуск модема и переход в состояние Initializing. Так же при этом Интервал увеличивается вдвое.
    ### AdcReader
    Параметры:
    "AdcReadTimeout": 500 // задержка после чтения данных из АЦП "AdcErrorReportTimeout": 5000 // Период отправки сигнала о том, что значения выходят за допустимые пределы "TemperatureCheckTimeout": 3000 // Период проверки температуры "TemperatureMax": 60 // Верхняя граница допустимой температуры "TemperatureMin": -20 // Нижняя граница допустимой температуры "PsuCurrentMax": 4 // Верхняя граница допустимой силы тока "PsuVoltageMin": 7 // Нижняя граница допустимого напряжения "PsuVoltageMax": 62 // Верхняя граница допустимого напряжения
    Параметры (скрытые, только для разработчиков):
    "PsuCurrentAmpVolt": 3.3333333333 // 5A : 1.5V - ампер-вольтная характеристика

// cube-a "PsuCurrentDivider": 0.244 // Делитель тока "PsuVoltageDivider": 0.031 // Делитель напряжения

// cube-b "PsuCurrentDivider": 1.3 "PsuVoltageDivider": 0.031

// cube-c (and others) "PsuCurrentDivider": 1.3 "PsuVoltageDivider": 0.04

Мониторинг АЦП. Значения берутся из файлов:

/sys/bus/iio/devices/iio:device0/in_voltage_scale /sys/bus/iio/devices/iio:device0/in_voltaged_raw

В зависимости от ревизии куба отличается схема подключения входов АЦП:
* cube-a: на входе АЦП внешний мультиплексор, который переключил каналы измерения тока и напряжения. Переключение происходит с помощью GPIO модема. Выход АЦП - 5 канал (`in_voltage5_raw`)
* cube-b: как в cube-a, но переключение происходит с помощью GPIO 503 куба.
* cube-c и выше: вход измерения силы тока подключен к 5 выходу АЦП (`in_voltage5_raw`) , вход измерения напряжения подключен к 6 выходу АЦП (`in_voltage6_raw`).
Термистор доступен на 4 (`in_voltage4_raw`) выходе АЦП. Температура берется исходя из таблицы соответствия сопротивления и температуры, которая предварительно рассчитывается для конкретного термистра (в нашем случае ERT-J0ET473J).
Формула расчета для таблицы зависимости сопротивлений от температуры

R = EXP(B*((1/(x + 273.15))-(1/298.15))), where B = 4450

Модуль занимается мониторингом значений тока, напряжения, температуры. Формулы рассчетов:

value = <in_voltaged_raw> * <in_voltage_scale> / 1000 I = value / <PsuVoltageDivider> * <PsuCurrentAmpVolt> U = value / <PsuVoltageDivider>

Более подробная информация находится в Приложении 2.
Модуль постоянно считывает значения с АЦП с задержкой в `AdcReadTimeout`. Температура считывается с периодом `TemperatureCheckTimeout`. Значения проверяются на соответствие диапазонам, указанным с помощью параметров `TemperatureMax`, `TemperatureMin`, `PsuVoltageMax`, `PsuVoltageMin`, `PsuCurrentMax`. Если значения выходят за диапазон, то отправляется DBus сигнал `OutOfRange`. Подробнее в разделе DBus API.
### Beeper
Параметры:

"BeeperTimeout": 0 // Задержка после обработки команды

Модуль слушает fifo файл (pipe) по пути [EMVL1_PIPE_NAME_BEEPER](https://gitlab.aqsi.ru/aqc_embedded/libaqc_emv_ctls_l1/-/blob/master/contactless.h#L10) (на момент написания это "/tmp/aqc.emv.l1.ctls.beeper")
Если пришел байт [EMVL1_BEEP_OK](https://gitlab.aqsi.ru/aqc_embedded/libaqc_emv_ctls_l1/-/blob/master/contactless.h#L29) (0x00), пищит 1 раз 500 мс.
Если пришел байт [EMVL1_BEEP_FAIL](https://gitlab.aqsi.ru/aqc_embedded/libaqc_emv_ctls_l1/-/blob/master/contactless.h#L30) (0x01), пищит 2 раза по 200 мс с перерывом в 200 мс.
Если пришло несколько байт, выполняется последний. После выполнения команды выполняется задержка в `BeeperTimeout` мс.
### PulsatorManager
Параметры:

"OutputPulseDuration": 500 // длительность нахождения в верхнем состоянии, в микросекундах "OutputPulsePeriod": 1000 // период пульса, в микросекундах "OutputPulsePolarity": 1 // состояние пина в режиме ожидания (0/1)

Вызов DBus метода `GeneratePulse(pin, count)` запускает пульсацию на определенном GPIO. Под каждый пульс создается отдельный тред с именем `Pulse <pin>`, где `<pin> `- номер GPIO.
Если запустить пульсацию на пине, где уже пульсация идет, то она продлится на
заданное количество тиков.
Параметры пульсации настраиваются с помощью `OutputPulseDuration`, `OutputPulsePeriod`, `OutputPulsePolarity`
### DBus API
Примеры использования из шелла в Приложении 3.

Service org.hwkeeper Interface org.hwkeeper Object path /

Methods double GetTemperature()

                Возвращает температуру устройства в °C, .1 точность

            double GetPSUVoltage()

                Возвращает значение напряжения на источнике питания в вольтах.

            double GetPSUCurrent()

                Возвращает значение силы тока на источнике питания в амперах.

            void UpdateConfig()

                Перезагружает конфигурационный файл.
                Deprecated, используйте SIGHUP.

            void GpioWrite(int32 n, boolean val)

                Записывает значение в GPIO n.
                Deprecated, используйте библиотеку hwhelper

            boolean GpioRead(int32 n)

                Считывает значение GPIO n.
                Deprecated, используйте библиотеку hwhelper

            void GpioDirection(int32 n, boolean val)

                Изменяет значение direction GPIO n (false - input, true - output)
                Deprecated, используйте библиотеку hwhelper

            void GeneratePulse(int32 n, int32 count)

                Запускает пульсацию на GPIO n в размере count тиков.

            void ModemTurnOn()

                Включает модем

            void ModemTurnOff()

                Выключает модем

            void ModemRestart()

                Перезапускает модем

Service org.hwkeeper Interface org.hwkeeper Object path /cellular

Methods boolean GetOnline()

                true, если есть связь согласно логике CellularManager
                (прошел ping до PingServer/PingServers)

Signals OnlineChanged(boolean val)

                Отправляется при изменении online-статуса CellularManager.

Service org.hwkeeper Interface org.hwkeeper Object path /adc/temperature, /adc/psu_current, /adc/psu_voltage

Signals OutOfRange(double value)

            Значение температуры, напряжения или тока за пределами допустимого
### Прочие возможности
#### Режим отладки
Параметр:

"HwKeeperDebug": 1 // 0 - выключено (default), 1 - включено

В этом режиме приложение пишет больше сообщений в лог, чем обычно, что может помочь при отладке.
#### Настройка часового пояса
Параметр:

"Timezone": 3 // от -12 до 14

Создается ссылка в `/mnt/data/localtime`, указывающая на `/usr/share/zoneinfo/Etc/GMT<inverted-sign><value>`, где `<inverted-sign>` это инвертированный знак `Timezone`, а `<value>` - абсолютное значение `Timezone`.
Например, если `Timezone` = 3, то создается ссылка на `/usr/share/zoneinfo/Etc/GMT-3`
#### Настройка параметров логгирования
Параметры:

"LogLocation": "/media/sdcard"
"LogSize": 10485760 // 10 Mb "ElasticsearchConfigPreset": "" // test, prod, disable

`ElasticsearchConfigPreset`- пресет настроек для elasticsearch.
* "" (пустая строка) - оставляет все по-умолчанию (по-умолчаню логи не шлются)
* "disable" - отправка логов отключена
* "prod" - включена отправка на продовый сервер (https://elk-cube.aqsi.ru)
* "test" - включена отправка на тестовый сервер (https://elk-cube-test.aqsi.ru)
Реализовано через управление таргета ссылки `/etc/rsyslog.d/elasticsearch.conf`
`LogLocation` - корень местоположения логов. Внутри указанной директории создается поддиректория "syslog", внутри которой - файлы `syslog.log` и `syslog.1.log`, каждый размером не более, чем `LogSize`/2.
* "/var/log" - логи хранятся в оперативной памяти, стираются при перезагрузке.
* "/mnt/data" - логи хранятся в постоянной памяти, при перезагрузке не стираются, но тратят ресурс флеш-памяти.
* "/media/sdcard" - логи хранятся на microSD-карте, если она присутствует.
Если в строке указано иное, либо если указанный путь не смонтирован в системе, используется "/var/log".
`LogSize` - размер лог-файла (в байтах). Запись идёт в файл `<LogLocation>/syslog/syslog.log`. По достижению половины значения файл переименовывается с заменой в `syslog.1.log`, создается новый `syslog.log`
## Приложения
### Приложение 1
Значения APN/User/Pass в случае, если `CellularAuthMethod` = 1:

Оператор APN Username Password

MTS internet.mts.ru mts mts Beeline internet.beeline.ru beeline beeline Megafon internet gdata gdata Tele2 internet.tele2.ru - - Yota internet.yota - -

### Приложение 2
Информация, связанная с АЦП:
https://ru.mouser.com/datasheet/2/315/AUA0000C11-1100844.pdf
https://datasheet.octopart.com/ERT-J0ET473J-Panasonic-datasheet-78377388.pdf
http://ww1.microchip.com/downloads/en/Appnotes/AN_3250-How-to-use-SAMA5D2-ADC-under-Linux-00003250a.pdf
![img](README.assets/AdcTable.png)

Для ревизии RevA:

PD23 - ADCIN4 - NTC Thermistor 47k (ERT-J0ET473J with Pull_UP 47k 3V3) PD24 - ADCIN5 - VIN (57V max 0.031 divider) CURRENT_OUT (divider 0.244)(1.5V@5A) WM_GPIO7 (PWM) - ADCIN5_SLCT - управление мультиплексором на входе ADCIN5. При 0 к ADCIN5 подключен сигнал линейно пропорциональный току потребления от главного источника питания 5В. При 1 к ADCIN5 подключен сигнал линейно пропорциональный напряжению на входе устройства. PD25 - ADCIN6 - WM_EP (WM Analog audio) PD30 - ADCIN11 - AUX_35 (30V max 0.099 divider)

Для ревизии RevB & CubeT RevA:

PD23 - ADCIN4 - NTC Thermistor 47k (ERT-J0ET473J with Pull_UP 47k 3V3) PD24 - ADCIN5 - VIN (57V max 0.031 divider) CURRENT_OUT (divider 1.3)(1.5V@5A) gpio503 - ADCIN5_SLCT - управление мультиплексором на входе ADCIN5. При 0 к ADCIN5 подключен сигнал линейно пропорциональный току потребления от главного источника питания 5В. При 1 к ADCIN5 подключен сигнал линейно пропорциональный напряжению на входе устройства. PD25 - ADCIN6 - WM_EP (WM Analog audio) PD30 - ADCIN11 - AUX_35 (30V max 0.099 divider)

Для ревизии RevC & RevD & CubeT RevB:

PD23 - ADCIN4 - NTC Thermistor 47k (ERT-J0ET473J with Pull_UP 47k 3V3) PD24 - ADCIN5 - CURRENT_OUT (divider 1.3)(1.5V@5A) PD25 - ADCIN6 - VIN (57V max 0.04 divider) PD30 - ADCIN11 - AUX_35 (30V max 0.099 divider)

### Приложение 3
Примеры команд из шела для использования DBus API:
Мониторить изменение свойства PropertyChanged на интерфейсе org.ofono.ConnectionContext:

dbus-monitor –system interface='org.ofono.ConnectionContext',member='PropertyChanged'

Получить ток, напряжение, температуру:

dbus-send –system –print-reply –dest=org.hwkeeper / org.hwkeeper.GetPSUCurrent dbus-send –system –print-reply –dest=org.hwkeeper / org.hwkeeper.GetPSUVoltage dbus-send –system –print-reply –dest=org.hwkeeper / org.hwkeeper.GetTemperature

Включение, выключение, перезапуск модема:

dbus-send –system –print-reply –dest=org.hwkeeper / org.hwkeeper.ModemTurnOn dbus-send –system –print-reply –dest=org.hwkeeper / org.hwkeeper.ModemTurnOff dbus-send –system –print-reply –dest=org.hwkeeper / org.hwkeeper.ModemRestart

Выдать звук:

echo -ne "\x00" > "/tmp/aqc.emv.l1.ctls.beeper" echo -ne "\x01" > "/tmp/aqc.emv.l1.ctls.beeper" ```