Compare commits

4 Commits

Author SHA1 Message Date
sd
418ec5b3af Add version 2025-11-24 13:47:23 +03:00
sd
25eeb1d78c Correct build for wsl2 2025-11-24 13:31:14 +03:00
sd
df932dadd0 Initial set values for blocks config 2025-11-24 13:20:45 +03:00
sd
d8cea4e1c6 Initial all get params 2025-11-24 12:42:56 +03:00
25 changed files with 1921 additions and 147 deletions

3
.gitignore vendored
View File

@@ -1,4 +1,5 @@
.vscode
.idea
cache
build
build
lib

View File

@@ -12,20 +12,78 @@ if (BUILD_FOR_JLV135)
# Настройки компиляции
set(CMAKE_C_FLAGS "-Os -fdata-sections -ffunction-sections -mno-unaligned-access")
set(CMAKE_EXE_LINKER_FLAGS "-Wl,--gc-sections")
else()
# Для разработки/тестирования на обычной системе используем файловую систему
add_compile_definitions(JL_CONFIG_USE_FILE)
endif()
# Генерация версии из git
execute_process(
COMMAND git describe --tags --abbrev=0
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_TAG
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(NOT GIT_TAG)
set(GIT_TAG "none")
endif()
execute_process(
COMMAND git branch --show-current
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_BRANCH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND git show -s --format=%h
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
# Получаем дату и время сборки
string(TIMESTAMP BUILD_DATE "%Y-%m-%d %H:%M:%S" UTC)
# Формируем короткую версию (без хеша и даты)
if(GIT_BRANCH STREQUAL "main")
set(VERSION_SHORT "${GIT_TAG}")
set(VERSION_STRING "${GIT_TAG} ${GIT_HASH} (${BUILD_DATE})")
else()
set(VERSION_SHORT "${GIT_TAG}-${GIT_BRANCH}")
set(VERSION_STRING "${GIT_TAG}-${GIT_BRANCH} ${GIT_HASH} (${BUILD_DATE})")
endif()
configure_file(
${CMAKE_SOURCE_DIR}/inc/jlv135_cli/version.h.in
${CMAKE_BINARY_DIR}/inc/jlv135_cli/version.h
@ONLY
)
# Создание исполняемого файла
add_executable(${PROJECT_NAME}
src/jl_modbus/jl_modbus_config.c
src/jl_modbus/jl_config.c
src/jlv135_cli/jl_block.c
src/jlv135_cli/jl_block_modbus.c
src/jlv135_cli/jl_block_wifi.c
src/jlv135_cli/jl_block_display.c
src/jlv135_cli/jl_block_feature.c
src/jlv135_cli/jl_block_datatime.c
src/jlv135_cli/jl_block_sensor.c
src/jlv135_cli/jl_block_secure.c
src/jlv135_cli/jl_block_service.c
src/jlv135_cli/main.c)
# Настройка библиотек
target_link_libraries(${CMAKE_PROJECT_NAME} pthread)
# Добавление каталогов для поиска заголовков
target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE
inc)
target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE
inc
${CMAKE_BINARY_DIR}/inc)
if (BUILD_FOR_JLV135)
# Опция strip

44
cmake/version.cmake Normal file
View File

@@ -0,0 +1,44 @@
# Скрипт для генерации версии на основе git
# Получаем ближайший тег
execute_process(
COMMAND git describe --tags --abbrev=0
WORKING_DIRECTORY ${SOURCE_DIR}
OUTPUT_VARIABLE GIT_TAG
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(NOT GIT_TAG)
set(GIT_TAG "none")
endif()
# Получаем текущую ветку
execute_process(
COMMAND git branch --show-current
WORKING_DIRECTORY ${SOURCE_DIR}
OUTPUT_VARIABLE GIT_BRANCH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
# Получаем короткий хеш коммита
execute_process(
COMMAND git show -s --format=%h
WORKING_DIRECTORY ${SOURCE_DIR}
OUTPUT_VARIABLE GIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
# Формируем строку версии
if(GIT_BRANCH STREQUAL "main")
set(VERSION_STRING "${GIT_TAG} ${GIT_HASH}")
else()
set(VERSION_STRING "${GIT_TAG}-${GIT_BRANCH} ${GIT_HASH}")
endif()
# Генерируем заголовочный файл
configure_file(
${SOURCE_DIR}/inc/jlv135_cli/version.h.in
${BINARY_DIR}/inc/jlv135_cli/version.h
@ONLY
)

28
inc/jlv135_cli/jl_block.h Normal file
View File

@@ -0,0 +1,28 @@
#ifndef JLV135_CLI_BLOCK_H
#define JLV135_CLI_BLOCK_H
#include <stdbool.h>
// Структура блока конфигурации (модуля)
typedef struct jl_block
{
const char *name; // Имя блока (wifi, modbus, display, и т.д.)
// Метод get: отображает все параметры блока с текущими значениями
// Возвращает 0 при успехе, != 0 при ошибке
int (*get)(void);
// Метод set: изменяет параметры блока
// argc - количество аргументов после "set <blockname>"
// argv - массив аргументов
// Возвращает 0 при успехе, != 0 при ошибке
int (*set)(int argc, const char *argv[]);
} jl_block_t;
// Получить список всех доступных блоков
const jl_block_t *jl_block_get_all(void);
// Найти блок по имени
const jl_block_t *jl_block_find(const char *name);
#endif // JLV135_CLI_BLOCK_H

View File

@@ -0,0 +1,10 @@
#ifndef JLV135_CLI_BLOCK_DATATIME_H
#define JLV135_CLI_BLOCK_DATATIME_H
// Метод get для модуля datatime
int jl_block_datatime_get(void);
// Метод set для модуля datatime
int jl_block_datatime_set(int argc, const char *argv[]);
#endif // JLV135_CLI_BLOCK_DATATIME_H

View File

@@ -0,0 +1,10 @@
#ifndef JLV135_CLI_BLOCK_DISPLAY_H
#define JLV135_CLI_BLOCK_DISPLAY_H
// Метод get для модуля display
int jl_block_display_get(void);
// Метод set для модуля display
int jl_block_display_set(int argc, const char *argv[]);
#endif // JLV135_CLI_BLOCK_DISPLAY_H

View File

@@ -0,0 +1,10 @@
#ifndef JLV135_CLI_BLOCK_FEATURE_H
#define JLV135_CLI_BLOCK_FEATURE_H
// Метод get для модуля feature
int jl_block_feature_get(void);
// Метод set для модуля feature
int jl_block_feature_set(int argc, const char *argv[]);
#endif // JLV135_CLI_BLOCK_FEATURE_H

View File

@@ -0,0 +1,10 @@
#ifndef JLV135_CLI_BLOCK_MODBUS_H
#define JLV135_CLI_BLOCK_MODBUS_H
// Метод get для модуля modbus
int jl_block_modbus_get(void);
// Метод set для модуля modbus
int jl_block_modbus_set(int argc, const char *argv[]);
#endif // JLV135_CLI_BLOCK_MODBUS_H

View File

@@ -0,0 +1,10 @@
#ifndef JLV135_CLI_BLOCK_SECURE_H
#define JLV135_CLI_BLOCK_SECURE_H
// Метод get для модуля secure
int jl_block_secure_get(void);
// Метод set для модуля secure
int jl_block_secure_set(int argc, const char *argv[]);
#endif // JLV135_CLI_BLOCK_SECURE_H

View File

@@ -0,0 +1,10 @@
#ifndef JLV135_CLI_BLOCK_SENSOR_H
#define JLV135_CLI_BLOCK_SENSOR_H
// Метод get для модуля sensor
int jl_block_sensor_get(void);
// Метод set для модуля sensor
int jl_block_sensor_set(int argc, const char *argv[]);
#endif // JLV135_CLI_BLOCK_SENSOR_H

View File

@@ -0,0 +1,10 @@
#ifndef JLV135_CLI_BLOCK_SERVICE_H
#define JLV135_CLI_BLOCK_SERVICE_H
// Метод get для модуля service
int jl_block_service_get(void);
// Метод set для модуля service
int jl_block_service_set(int argc, const char *argv[]);
#endif // JLV135_CLI_BLOCK_SERVICE_H

View File

@@ -0,0 +1,10 @@
#ifndef JLV135_CLI_BLOCK_WIFI_H
#define JLV135_CLI_BLOCK_WIFI_H
// Метод get для модуля wifi
int jl_block_wifi_get(void);
// Метод set для модуля wifi
int jl_block_wifi_set(int argc, const char *argv[]);
#endif // JLV135_CLI_BLOCK_WIFI_H

View File

@@ -0,0 +1,7 @@
#ifndef JLV135_VERSION_H
#define JLV135_VERSION_H
#define JLV135_VERSION "@VERSION_STRING@"
#define JLV135_VERSION_SHORT "@VERSION_SHORT@"
#endif // JLV135_VERSION_H

View File

@@ -1,48 +1,89 @@
# Руководство по использованию команды `jlv135_cli`
## Описание
Команда `jlv135_cli` представляет собой интерфейс командной строки для работы с устройством JLV135.
Команда `jlv135_cli` представляет собой интерфейс командной строки для работы с устройством JLV135. Программа работает с блоками конфигурации как модулями расширения, каждый из которых имеет методы `get` (просмотр параметров) и `set` (изменение параметров).
## Вывод текущих настроек
## Основные команды
Вызов без параметров позволяет отобразить текущие настройки пульта без изменения текущих.
### Синтаксис
### Справка
Вызов без параметров отображает справку по использованию и список доступных блоков:
```bash
jlv135_cli
```
## Изменение скорости
### Синтаксис
### Просмотр параметров блока (get)
Просмотр всех параметров блока с текущими значениями и расшифровкой:
```bash
jlv135_cli --modbus --rs485 --speed <значение>
jlv135_cli get <блок>
```
### Параметры
### Изменение параметров блока (set)
Изменение параметров указанного блока:
```bash
jlv135_cli set <блок> <параметры...>
```
| Параметр | Описание |
|------------|-------------------------------------------------------------------------|
| `--modbus` | Активирует работу с протоколом Modbus |
| `--rs485` | Указывает на использование RS-485 |
| `--speed` | Задает скорость передачи данных (бодрейт) для RS-485 |
## Доступные блоки конфигурации
### Примеры использования
Список блоков определяется в `src/jl_modbus/jl_config.c` (массив `backup_blocks`):
- `modbus` - настройки протокола Modbus
- `wifi` - настройки WiFi (не реализован)
- `display` - настройки дисплея (не реализован)
- `feature` - функциональные возможности (не реализован)
- `datatime` - дата и время (не реализован)
- `sensor` - датчики (не реализован)
- `secure` - безопасность (не реализован)
- `service` - служебные параметры (не реализован)
1. Запуск с типичной скоростью 9600 бод:
```bash
jlv135_cli --modbus --rs485 --speed 9600
```
## Примеры использования
2. Использование высокой скорости 115200 бод:
```bash
jlv135_cli --modbus --rs485 --speed 115200
```
### Блок Modbus
### Поддерживаемые скорости
Программа может поддерживать различные стандартные скорости передачи данных:
#### Просмотр всех параметров Modbus:
```bash
jlv135_cli get modbus
```
Пример вывода:
```
Modbus Config:
num_port: 1
addr: 1
tcycle: 100
Modbus RS485 Port:
speed: 9600
prop_p: 0
prop_s: 0
repeate: 3
timeout: 500
Modbus TCP Port:
addr: 192.168.1.100
port: 502
repeate: 3
timeout: 1000
```
#### Изменение скорости RS485:
```bash
jlv135_cli set modbus rs485 speed 9600
jlv135_cli set modbus rs485 speed 115200
```
### Поддерживаемые скорости RS485
- 9600 бод (наиболее распространенная)
- 19200 бод
- 38400 бод
- 57600 бод
- 115200 бод
- 115200 бод
## Архитектура
Программа построена на модульной архитектуре:
- Каждый блок конфигурации - это отдельный модуль с методами `get` и `set`
- Добавление нового блока требует:
1. Создания заголовочного файла `inc/jlv135_cli/jl_block_<name>.h`
2. Создания файла реализации `src/jlv135_cli/jl_block_<name>.c`
3. Регистрации блока в `src/jlv135_cli/jl_block.c`
4. Добавления файлов в `CMakeLists.txt`

View File

@@ -1,9 +1,10 @@
#include <jl_modbus/jl_config.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#if JL_CONFIG_SAVE_TO_FILE
static const char *jl_config_path = JL_CONFIG_SAVE_TO_FILE_PATH;
#ifdef JL_CONFIG_USE_FILE
static const char* jl_config_path = "./";
void
jl_config_load(const char *name, void *def, size_t size)
{

48
src/jlv135_cli/jl_block.c Normal file
View File

@@ -0,0 +1,48 @@
#include <jlv135_cli/jl_block.h>
#include <jlv135_cli/jl_block_modbus.h>
#include <jlv135_cli/jl_block_wifi.h>
#include <jlv135_cli/jl_block_display.h>
#include <jlv135_cli/jl_block_feature.h>
#include <jlv135_cli/jl_block_datatime.h>
#include <jlv135_cli/jl_block_sensor.h>
#include <jlv135_cli/jl_block_secure.h>
#include <jlv135_cli/jl_block_service.h>
#include <string.h>
// Список всех доступных блоков конфигурации
static const jl_block_t blocks[] = {
{.name = "wifi", .get = jl_block_wifi_get, .set = jl_block_wifi_set},
{.name = "modbus", .get = jl_block_modbus_get, .set = jl_block_modbus_set},
{.name = "display", .get = jl_block_display_get, .set = jl_block_display_set},
{.name = "feature", .get = jl_block_feature_get, .set = jl_block_feature_set},
{.name = "datatime", .get = jl_block_datatime_get, .set = jl_block_datatime_set},
{.name = "sensor", .get = jl_block_sensor_get, .set = jl_block_sensor_set},
{.name = "secure", .get = jl_block_secure_get, .set = jl_block_secure_set},
{.name = "service", .get = jl_block_service_get, .set = jl_block_service_set},
{.name = NULL, .get = NULL, .set = NULL} // Терминатор списка
};
// Получить список всех доступных блоков
const jl_block_t *
jl_block_get_all(void)
{
return blocks;
}
// Найти блок по имени
const jl_block_t *
jl_block_find(const char *name)
{
const jl_block_t *block = blocks;
while (block->name != NULL)
{
if (strcmp(block->name, name) == 0)
{
return block;
}
block++;
}
return NULL;
}

View File

@@ -0,0 +1,153 @@
#include <jl_modbus/jl_config.h>
#include <jlv135_cli/jl_block_datatime.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
typedef struct _jl_datatime_config_t
{
uint8_t ntp_en; // автоматически обновлять время с сервера NTP
uint8_t settime_en; // разрешено пульту устанавливать время в контроллер
int8_t correction; // корректировка времени за сутки
int8_t gmt; // часовой пояс от -12 до +12
} jl_datatime_config_t;
// Метод get: отображает все параметры блока datatime
int
jl_block_datatime_get(void)
{
jl_datatime_config_t conf = {};
jl_config_load("datatime", &conf, sizeof(jl_datatime_config_t));
printf("Date/Time Configuration:\n");
printf(" NTP Sync: %s\n", conf.ntp_en ? "Enabled" : "Disabled");
printf(" Set Time: %s\n", conf.settime_en ? "Allowed" : "Not allowed");
printf(" Time Correction: %d sec/day\n", conf.correction);
printf(" GMT Offset: %+d hours\n", conf.gmt);
return 0;
}
// Метод set: изменяет параметры блока datatime
int
jl_block_datatime_set(int argc, const char *argv[])
{
if (argc < 1)
{
fprintf(stderr, "Error: insufficient arguments for 'set datatime'\n");
fprintf(stderr, "Usage:\n");
fprintf(stderr, " jlv135_cli set datatime ntp <on|off>\n");
fprintf(stderr, " jlv135_cli set datatime settime <on|off>\n");
fprintf(stderr, " jlv135_cli set datatime gmt <-12..+12>\n");
fprintf(stderr, " jlv135_cli set datatime correction <-127..127>\n");
return 1;
}
jl_datatime_config_t conf = {};
jl_config_load("datatime", &conf, sizeof(jl_datatime_config_t));
// NTP enable
if (strcmp(argv[0], "ntp") == 0)
{
if (argc < 2)
{
fprintf(stderr, "Error: ntp value required (on|off)\n");
return 1;
}
if (strcmp(argv[1], "on") == 0 || strcmp(argv[1], "1") == 0)
{
conf.ntp_en = 1;
}
else if (strcmp(argv[1], "off") == 0 || strcmp(argv[1], "0") == 0)
{
conf.ntp_en = 0;
}
else
{
fprintf(stderr, "Error: invalid ntp value '%s' (use on|off)\n", argv[1]);
return 1;
}
jl_config_save("datatime", &conf, sizeof(jl_datatime_config_t));
printf("NTP sync %s\n", conf.ntp_en ? "enabled" : "disabled");
return 0;
}
// Set time enable
else if (strcmp(argv[0], "settime") == 0)
{
if (argc < 2)
{
fprintf(stderr, "Error: settime value required (on|off)\n");
return 1;
}
if (strcmp(argv[1], "on") == 0 || strcmp(argv[1], "1") == 0)
{
conf.settime_en = 1;
}
else if (strcmp(argv[1], "off") == 0 || strcmp(argv[1], "0") == 0)
{
conf.settime_en = 0;
}
else
{
fprintf(stderr, "Error: invalid settime value '%s' (use on|off)\n", argv[1]);
return 1;
}
jl_config_save("datatime", &conf, sizeof(jl_datatime_config_t));
printf("Set time %s\n", conf.settime_en ? "allowed" : "not allowed");
return 0;
}
// GMT offset
else if (strcmp(argv[0], "gmt") == 0)
{
if (argc < 2)
{
fprintf(stderr, "Error: GMT offset value required\n");
return 1;
}
long val = strtol(argv[1], NULL, 10);
if (val < -12 || val > 12)
{
fprintf(stderr, "Error: GMT offset must be between -12 and +12\n");
return 1;
}
conf.gmt = (int8_t)val;
jl_config_save("datatime", &conf, sizeof(jl_datatime_config_t));
printf("GMT offset set to %+d hours\n", conf.gmt);
return 0;
}
// Time correction
else if (strcmp(argv[0], "correction") == 0)
{
if (argc < 2)
{
fprintf(stderr, "Error: correction value required\n");
return 1;
}
long val = strtol(argv[1], NULL, 10);
if (val < -127 || val > 127)
{
fprintf(stderr, "Error: correction must be between -127 and +127\n");
return 1;
}
conf.correction = (int8_t)val;
jl_config_save("datatime", &conf, sizeof(jl_datatime_config_t));
printf("Time correction set to %d sec/day\n", conf.correction);
return 0;
}
else
{
fprintf(stderr, "Error: unknown parameter '%s'\n", argv[0]);
return 1;
}
return 0;
}

View File

@@ -0,0 +1,262 @@
#include <jl_modbus/jl_config.h>
#include <jlv135_cli/jl_block_display.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
typedef enum
{
JLV_SSAVER_TYPE_NONE,
JLV_SSAVER_TYPE_DISABLE,
JLV_SSAVER_TYPE_TIME,
JLV_SSAVER_TYPE_SENSOR,
JLV_SSAVER_TYPE_METEO,
JLV_SSAVER_TYPE_MAX,
} jlv_ssaver_type_t;
typedef enum
{
JLV_SSAVER_METEO_LIGHT,
JLV_SSAVER_METEO_DARK,
JLV_SSAVER_METEO_AUTO,
JLV_SSAVER_METEO_MAX,
} jlv_ssaver_meteo_type_t;
typedef struct _jlv_time_t
{
uint8_t hour;
uint8_t min;
} jlv_time_t;
typedef struct _jlv_color_t
{
uint8_t r;
uint8_t g;
uint8_t b;
} jlv_color_t;
typedef struct _jlv_ssaver_t
{
jlv_ssaver_type_t type;
uint8_t min;
bool night_backlight : 1;
bool power_indicator : 1;
jlv_color_t color_bg;
jlv_color_t color_text;
jlv_ssaver_meteo_type_t meteo_type;
} jlv_ssaver_t;
typedef struct _jlv_display_t
{
uint8_t backlight;
uint8_t night_backlight;
jlv_time_t night_begin;
jlv_time_t night_end;
bool night : 1;
bool led_disable : 1;
jlv_ssaver_t ssaver;
uint8_t pu_temper;
uint8_t pu_hum;
} jlv_display_t;
static const char *
ssaver_type_to_string(jlv_ssaver_type_t type)
{
switch (type)
{
case JLV_SSAVER_TYPE_NONE:
return "None";
case JLV_SSAVER_TYPE_DISABLE:
return "Disabled";
case JLV_SSAVER_TYPE_TIME:
return "Time";
case JLV_SSAVER_TYPE_SENSOR:
return "Sensor";
case JLV_SSAVER_TYPE_METEO:
return "Meteo";
default:
return "Unknown";
}
}
static const char *
ssaver_meteo_type_to_string(jlv_ssaver_meteo_type_t type)
{
switch (type)
{
case JLV_SSAVER_METEO_LIGHT:
return "Light";
case JLV_SSAVER_METEO_DARK:
return "Dark";
case JLV_SSAVER_METEO_AUTO:
return "Auto";
default:
return "Unknown";
}
}
// Метод get: отображает все параметры блока display
int
jl_block_display_get(void)
{
jlv_display_t conf = {};
jl_config_load("display", &conf, sizeof(jlv_display_t));
printf("Display Configuration:\n");
printf(" Backlight: %u%%\n", conf.backlight);
printf(" Night backlight: %u%%\n", conf.night_backlight);
printf(" Night mode: %s\n", conf.night ? "On" : "Off");
printf(" Night begin: %02u:%02u\n", conf.night_begin.hour, conf.night_begin.min);
printf(" Night end: %02u:%02u\n", conf.night_end.hour, conf.night_end.min);
printf(" LED: %s\n", conf.led_disable ? "Disabled" : "Enabled");
printf(" PU Temperature: %s\n", conf.pu_temper ? "From controller" : "Local sensor");
printf(" PU Humidity: %s\n", conf.pu_hum ? "From controller" : "Local sensor");
printf("\n");
printf("Screensaver:\n");
printf(" Type: %s\n", ssaver_type_to_string(conf.ssaver.type));
printf(" Timeout: %u min\n", conf.ssaver.min);
printf(" Night backlight: %s\n", conf.ssaver.night_backlight ? "On" : "Off");
printf(" Power indicator: %s\n", conf.ssaver.power_indicator ? "On" : "Off");
printf(" BG Color: RGB(%u, %u, %u)\n", conf.ssaver.color_bg.r,
conf.ssaver.color_bg.g, conf.ssaver.color_bg.b);
printf(" Text Color: RGB(%u, %u, %u)\n", conf.ssaver.color_text.r,
conf.ssaver.color_text.g, conf.ssaver.color_text.b);
printf(" Meteo Type: %s\n", ssaver_meteo_type_to_string(conf.ssaver.meteo_type));
return 0;
}
// Метод set: изменяет параметры блока display
int
jl_block_display_set(int argc, const char *argv[])
{
if (argc < 1)
{
fprintf(stderr, "Error: insufficient arguments for 'set display'\n");
fprintf(stderr, "Usage:\n");
fprintf(stderr, " jlv135_cli set display backlight <0-100>\n");
fprintf(stderr, " jlv135_cli set display night_backlight <0-100>\n");
fprintf(stderr, " jlv135_cli set display night <on|off>\n");
fprintf(stderr, " jlv135_cli set display led <on|off>\n");
fprintf(stderr, " jlv135_cli set display pu_temper <0|1>\n");
fprintf(stderr, " jlv135_cli set display pu_hum <0|1>\n");
return 1;
}
jlv_display_t conf = {};
jl_config_load("display", &conf, sizeof(jlv_display_t));
if (argc < 2)
{
fprintf(stderr, "Error: value required\n");
return 1;
}
// Backlight
if (strcmp(argv[0], "backlight") == 0)
{
long val = strtol(argv[1], NULL, 10);
if (val < 0 || val > 100)
{
fprintf(stderr, "Error: backlight must be between 0 and 100\n");
return 1;
}
conf.backlight = (uint8_t)val;
jl_config_save("display", &conf, sizeof(jlv_display_t));
printf("Backlight set to %u%%\n", conf.backlight);
return 0;
}
// Night backlight
else if (strcmp(argv[0], "night_backlight") == 0)
{
long val = strtol(argv[1], NULL, 10);
if (val < 0 || val > 100)
{
fprintf(stderr, "Error: night_backlight must be between 0 and 100\n");
return 1;
}
conf.night_backlight = (uint8_t)val;
jl_config_save("display", &conf, sizeof(jlv_display_t));
printf("Night backlight set to %u%%\n", conf.night_backlight);
return 0;
}
// Night mode
else if (strcmp(argv[0], "night") == 0)
{
if (strcmp(argv[1], "on") == 0 || strcmp(argv[1], "1") == 0)
{
conf.night = true;
}
else if (strcmp(argv[1], "off") == 0 || strcmp(argv[1], "0") == 0)
{
conf.night = false;
}
else
{
fprintf(stderr, "Error: invalid night value '%s' (use on|off)\n", argv[1]);
return 1;
}
jl_config_save("display", &conf, sizeof(jlv_display_t));
printf("Night mode %s\n", conf.night ? "enabled" : "disabled");
return 0;
}
// LED
else if (strcmp(argv[0], "led") == 0)
{
if (strcmp(argv[1], "on") == 0 || strcmp(argv[1], "1") == 0)
{
conf.led_disable = false;
}
else if (strcmp(argv[1], "off") == 0 || strcmp(argv[1], "0") == 0)
{
conf.led_disable = true;
}
else
{
fprintf(stderr, "Error: invalid led value '%s' (use on|off)\n", argv[1]);
return 1;
}
jl_config_save("display", &conf, sizeof(jlv_display_t));
printf("LED %s\n", conf.led_disable ? "disabled" : "enabled");
return 0;
}
// PU Temperature source
else if (strcmp(argv[0], "pu_temper") == 0)
{
long val = strtol(argv[1], NULL, 10);
if (val < 0 || val > 1)
{
fprintf(stderr, "Error: pu_temper must be 0 or 1\n");
return 1;
}
conf.pu_temper = (uint8_t)val;
jl_config_save("display", &conf, sizeof(jlv_display_t));
printf("PU Temperature set to %s\n", conf.pu_temper ? "from controller" : "local sensor");
return 0;
}
// PU Humidity source
else if (strcmp(argv[0], "pu_hum") == 0)
{
long val = strtol(argv[1], NULL, 10);
if (val < 0 || val > 1)
{
fprintf(stderr, "Error: pu_hum must be 0 or 1\n");
return 1;
}
conf.pu_hum = (uint8_t)val;
jl_config_save("display", &conf, sizeof(jlv_display_t));
printf("PU Humidity set to %s\n", conf.pu_hum ? "from controller" : "local sensor");
return 0;
}
else
{
fprintf(stderr, "Error: unknown parameter '%s'\n", argv[0]);
fprintf(stderr, "Note: screensaver settings are not yet supported via set command\n");
return 1;
}
return 0;
}

View File

@@ -0,0 +1,227 @@
#include <jl_modbus/jl_config.h>
#include <jlv135_cli/jl_block_feature.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdbool.h>
#include <stdint.h>
typedef struct _jl_feature_t
{
bool sound : 1;
bool wifi : 1;
bool remote : 1;
bool socket1 : 1;
bool socket2 : 1;
bool mb_server : 1;
bool socket1_auto_disable : 1;
bool socket1_mb_disable : 1;
int extra_sensor;
int socket1_server;
int socket2_server;
time_t socket1_disable;
} jl_feature_t;
// Метод get: отображает все параметры блока feature
int
jl_block_feature_get(void)
{
jl_feature_t conf = {};
jl_config_load("feature", &conf, sizeof(jl_feature_t));
printf("Feature Configuration:\n");
printf(" Sound: %s\n", conf.sound ? "Enabled" : "Disabled");
printf(" WiFi: %s\n", conf.wifi ? "Enabled" : "Disabled");
printf(" Remote: %s\n", conf.remote ? "Enabled" : "Disabled");
printf(" Socket1: %s\n", conf.socket1 ? "Enabled" : "Disabled");
printf(" Socket2: %s\n", conf.socket2 ? "Enabled" : "Disabled");
printf(" Modbus Server: %s\n", conf.mb_server ? "Enabled" : "Disabled");
printf(" Socket1 Auto Disable: %s\n", conf.socket1_auto_disable ? "Yes" : "No");
printf(" Socket1 MB Disable: %s\n", conf.socket1_mb_disable ? "Yes" : "No");
printf(" Extra Sensor: %d\n", conf.extra_sensor);
printf(" Socket1 Server: %d\n", conf.socket1_server);
printf(" Socket2 Server: %d\n", conf.socket2_server);
printf(" Socket1 Disable Time: %ld\n", conf.socket1_disable);
return 0;
}
// Метод set: изменяет параметры блока feature
int
jl_block_feature_set(int argc, const char *argv[])
{
if (argc < 1)
{
fprintf(stderr, "Error: insufficient arguments for 'set feature'\n");
fprintf(stderr, "Usage:\n");
fprintf(stderr, " jlv135_cli set feature sound <on|off>\n");
fprintf(stderr, " jlv135_cli set feature wifi <on|off>\n");
fprintf(stderr, " jlv135_cli set feature remote <on|off>\n");
fprintf(stderr, " jlv135_cli set feature socket1 <on|off>\n");
fprintf(stderr, " jlv135_cli set feature socket2 <on|off>\n");
fprintf(stderr, " jlv135_cli set feature mb_server <on|off>\n");
fprintf(stderr, " jlv135_cli set feature extra_sensor <value>\n");
return 1;
}
jl_feature_t conf = {};
jl_config_load("feature", &conf, sizeof(jl_feature_t));
if (argc < 2)
{
fprintf(stderr, "Error: value required\n");
return 1;
}
// Вспомогательная функция для парсинга on/off значений
bool value_bool;
if (strcmp(argv[1], "on") == 0 || strcmp(argv[1], "1") == 0)
{
value_bool = true;
}
else if (strcmp(argv[1], "off") == 0 || strcmp(argv[1], "0") == 0)
{
value_bool = false;
}
else
{
// Если это не on/off, то может быть числовое значение для integer полей
value_bool = false; // будет использоваться только для boolean полей
}
// Boolean features
if (strcmp(argv[0], "sound") == 0)
{
if (strcmp(argv[1], "on") != 0 && strcmp(argv[1], "1") != 0 &&
strcmp(argv[1], "off") != 0 && strcmp(argv[1], "0") != 0)
{
fprintf(stderr, "Error: invalid sound value '%s' (use on|off)\n", argv[1]);
return 1;
}
conf.sound = value_bool;
jl_config_save("feature", &conf, sizeof(jl_feature_t));
printf("Feature sound %s\n", conf.sound ? "enabled" : "disabled");
return 0;
}
else if (strcmp(argv[0], "wifi") == 0)
{
if (strcmp(argv[1], "on") != 0 && strcmp(argv[1], "1") != 0 &&
strcmp(argv[1], "off") != 0 && strcmp(argv[1], "0") != 0)
{
fprintf(stderr, "Error: invalid wifi value '%s' (use on|off)\n", argv[1]);
return 1;
}
conf.wifi = value_bool;
jl_config_save("feature", &conf, sizeof(jl_feature_t));
printf("Feature wifi %s\n", conf.wifi ? "enabled" : "disabled");
return 0;
}
else if (strcmp(argv[0], "remote") == 0)
{
if (strcmp(argv[1], "on") != 0 && strcmp(argv[1], "1") != 0 &&
strcmp(argv[1], "off") != 0 && strcmp(argv[1], "0") != 0)
{
fprintf(stderr, "Error: invalid remote value '%s' (use on|off)\n", argv[1]);
return 1;
}
conf.remote = value_bool;
jl_config_save("feature", &conf, sizeof(jl_feature_t));
printf("Feature remote %s\n", conf.remote ? "enabled" : "disabled");
return 0;
}
else if (strcmp(argv[0], "socket1") == 0)
{
if (strcmp(argv[1], "on") != 0 && strcmp(argv[1], "1") != 0 &&
strcmp(argv[1], "off") != 0 && strcmp(argv[1], "0") != 0)
{
fprintf(stderr, "Error: invalid socket1 value '%s' (use on|off)\n", argv[1]);
return 1;
}
conf.socket1 = value_bool;
jl_config_save("feature", &conf, sizeof(jl_feature_t));
printf("Feature socket1 %s\n", conf.socket1 ? "enabled" : "disabled");
return 0;
}
else if (strcmp(argv[0], "socket2") == 0)
{
if (strcmp(argv[1], "on") != 0 && strcmp(argv[1], "1") != 0 &&
strcmp(argv[1], "off") != 0 && strcmp(argv[1], "0") != 0)
{
fprintf(stderr, "Error: invalid socket2 value '%s' (use on|off)\n", argv[1]);
return 1;
}
conf.socket2 = value_bool;
jl_config_save("feature", &conf, sizeof(jl_feature_t));
printf("Feature socket2 %s\n", conf.socket2 ? "enabled" : "disabled");
return 0;
}
else if (strcmp(argv[0], "mb_server") == 0)
{
if (strcmp(argv[1], "on") != 0 && strcmp(argv[1], "1") != 0 &&
strcmp(argv[1], "off") != 0 && strcmp(argv[1], "0") != 0)
{
fprintf(stderr, "Error: invalid mb_server value '%s' (use on|off)\n", argv[1]);
return 1;
}
conf.mb_server = value_bool;
jl_config_save("feature", &conf, sizeof(jl_feature_t));
printf("Feature mb_server %s\n", conf.mb_server ? "enabled" : "disabled");
return 0;
}
else if (strcmp(argv[0], "socket1_auto_disable") == 0)
{
if (strcmp(argv[1], "on") != 0 && strcmp(argv[1], "1") != 0 &&
strcmp(argv[1], "off") != 0 && strcmp(argv[1], "0") != 0)
{
fprintf(stderr, "Error: invalid socket1_auto_disable value '%s' (use on|off)\n", argv[1]);
return 1;
}
conf.socket1_auto_disable = value_bool;
jl_config_save("feature", &conf, sizeof(jl_feature_t));
printf("Feature socket1_auto_disable %s\n", conf.socket1_auto_disable ? "enabled" : "disabled");
return 0;
}
else if (strcmp(argv[0], "socket1_mb_disable") == 0)
{
if (strcmp(argv[1], "on") != 0 && strcmp(argv[1], "1") != 0 &&
strcmp(argv[1], "off") != 0 && strcmp(argv[1], "0") != 0)
{
fprintf(stderr, "Error: invalid socket1_mb_disable value '%s' (use on|off)\n", argv[1]);
return 1;
}
conf.socket1_mb_disable = value_bool;
jl_config_save("feature", &conf, sizeof(jl_feature_t));
printf("Feature socket1_mb_disable %s\n", conf.socket1_mb_disable ? "enabled" : "disabled");
return 0;
}
// Integer features
else if (strcmp(argv[0], "extra_sensor") == 0)
{
conf.extra_sensor = (int)strtol(argv[1], NULL, 10);
jl_config_save("feature", &conf, sizeof(jl_feature_t));
printf("Extra sensor set to %d\n", conf.extra_sensor);
return 0;
}
else if (strcmp(argv[0], "socket1_server") == 0)
{
conf.socket1_server = (int)strtol(argv[1], NULL, 10);
jl_config_save("feature", &conf, sizeof(jl_feature_t));
printf("Socket1 server set to %d\n", conf.socket1_server);
return 0;
}
else if (strcmp(argv[0], "socket2_server") == 0)
{
conf.socket2_server = (int)strtol(argv[1], NULL, 10);
jl_config_save("feature", &conf, sizeof(jl_feature_t));
printf("Socket2 server set to %d\n", conf.socket2_server);
return 0;
}
else
{
fprintf(stderr, "Error: unknown parameter '%s'\n", argv[0]);
return 1;
}
return 0;
}

View File

@@ -0,0 +1,311 @@
#include <jl_modbus/jl_config.h>
#include <jl_modbus/jl_modbus_config.h>
#include <jlv135_cli/jl_block_modbus.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Вспомогательные функции для печати
static void
print_rs485_baud_rates(uint16_t speed_index)
{
if (jl_modbus_rs485_baud_rate_is_index_valid(speed_index))
{
printf(" Speed: %u baud\n", jl_modbus_rs485_baud_rates[speed_index]);
}
else
{
printf(" Speed: %s\n", "unknown");
}
}
static void
print_rs485_port(jl_modbus_rs485_port_t *rs485)
{
printf("\nModbus RS485 (RTU) Port:\n");
print_rs485_baud_rates(rs485->speed);
printf(" Parity P: %u\n", rs485->prop_p);
printf(" Parity S: %u\n", rs485->prop_s);
printf(" Repeat Count: %u\n", rs485->repeate);
printf(" Timeout: %u ms\n", rs485->timeout);
}
static void
print_tcp_port(jl_modbus_tcp_port_t *tcp)
{
// Преобразуем IP адрес из uint32_t в читаемый формат
uint8_t *ip = (uint8_t *)&tcp->addr;
printf("\nModbus TCP Port:\n");
printf(" IP Address: %u.%u.%u.%u\n", ip[0], ip[1], ip[2], ip[3]);
printf(" Port: %u\n", tcp->port);
printf(" Repeat Count: %u\n", tcp->repeate);
printf(" Timeout: %u ms\n", tcp->timeout);
}
static void
print_modbus_config(jl_modbus_config_t *config)
{
printf("Modbus Configuration:\n");
printf(" Active Port: %u (0=RS485, 1=TCP)\n", config->num_port);
printf(" Device Address: %u\n", config->addr);
printf(" Polling Cycle: %u ms\n", config->tcycle);
print_rs485_port(&config->port_rtu);
print_tcp_port(&config->port_tcp);
}
// Метод get: отображает все параметры блока modbus
int
jl_block_modbus_get(void)
{
jl_modbus_config_t conf = {};
jl_config_load("modbus", &conf, sizeof(jl_modbus_config_t));
print_modbus_config(&conf);
return 0;
}
// Метод set: изменяет параметры блока modbus
int
jl_block_modbus_set(int argc, const char *argv[])
{
if (argc < 1)
{
fprintf(stderr, "Error: insufficient arguments for 'set modbus'\n");
fprintf(stderr, "Usage examples:\n");
fprintf(stderr, " jlv135_cli set modbus rs485 speed <value>\n");
fprintf(stderr, " jlv135_cli set modbus rs485 timeout <ms>\n");
fprintf(stderr, " jlv135_cli set modbus rs485 repeat <count>\n");
fprintf(stderr, " jlv135_cli set modbus tcp ip <x.x.x.x>\n");
fprintf(stderr, " jlv135_cli set modbus tcp port <number>\n");
fprintf(stderr, " jlv135_cli set modbus tcp timeout <ms>\n");
fprintf(stderr, " jlv135_cli set modbus tcp repeat <count>\n");
fprintf(stderr, " jlv135_cli set modbus addr <1-247>\n");
fprintf(stderr, " jlv135_cli set modbus active_port <0|1>\n");
fprintf(stderr, " jlv135_cli set modbus tcycle <ms>\n");
return 1;
}
jl_modbus_config_t conf = {};
jl_config_load("modbus", &conf, sizeof(jl_modbus_config_t));
// RS485 параметры
if (strcmp(argv[0], "rs485") == 0)
{
if (argc < 3)
{
fprintf(stderr, "Error: insufficient arguments for 'set modbus rs485'\n");
fprintf(stderr, "Usage: jlv135_cli set modbus rs485 <speed|timeout|repeat> <value>\n");
return 1;
}
// RS485 speed
if (strcmp(argv[1], "speed") == 0)
{
long val = strtol(argv[2], NULL, 10);
int idx = jl_modbus_rs485_baud_rate_get_index_by_baud(val);
if (idx == -1)
{
fprintf(stderr, "Error: invalid speed value '%s'\n", argv[2]);
fprintf(stderr, "Supported speeds: ");
for (size_t i = 0; i < sizeof(jl_modbus_rs485_baud_rates) / sizeof(uint32_t); i++)
{
printf("%u ", jl_modbus_rs485_baud_rates[i]);
}
printf("\n");
return 1;
}
conf.port_rtu.speed = idx;
jl_config_save("modbus", &conf, sizeof(jl_modbus_config_t));
printf("RS485 speed set to %u baud\n", jl_modbus_rs485_baud_rates[idx]);
return 0;
}
// RS485 timeout
else if (strcmp(argv[1], "timeout") == 0)
{
long val = strtol(argv[2], NULL, 10);
if (val < 0 || val > 65535)
{
fprintf(stderr, "Error: timeout must be between 0 and 65535 ms\n");
return 1;
}
conf.port_rtu.timeout = (uint16_t)val;
jl_config_save("modbus", &conf, sizeof(jl_modbus_config_t));
printf("RS485 timeout set to %u ms\n", conf.port_rtu.timeout);
return 0;
}
// RS485 repeat
else if (strcmp(argv[1], "repeat") == 0)
{
long val = strtol(argv[2], NULL, 10);
if (val < 0 || val > 65535)
{
fprintf(stderr, "Error: repeat count must be between 0 and 65535\n");
return 1;
}
conf.port_rtu.repeate = (uint16_t)val;
jl_config_save("modbus", &conf, sizeof(jl_modbus_config_t));
printf("RS485 repeat count set to %u\n", conf.port_rtu.repeate);
return 0;
}
else
{
fprintf(stderr, "Error: unknown RS485 parameter '%s'\n", argv[1]);
return 1;
}
}
// TCP параметры
else if (strcmp(argv[0], "tcp") == 0)
{
if (argc < 3)
{
fprintf(stderr, "Error: insufficient arguments for 'set modbus tcp'\n");
fprintf(stderr, "Usage: jlv135_cli set modbus tcp <ip|port|timeout|repeat> <value>\n");
return 1;
}
// TCP IP address
if (strcmp(argv[1], "ip") == 0)
{
unsigned int ip[4];
if (sscanf(argv[2], "%u.%u.%u.%u", &ip[0], &ip[1], &ip[2], &ip[3]) != 4)
{
fprintf(stderr, "Error: invalid IP address format '%s' (use x.x.x.x)\n", argv[2]);
return 1;
}
for (int i = 0; i < 4; i++)
{
if (ip[i] > 255)
{
fprintf(stderr, "Error: IP address octets must be between 0 and 255\n");
return 1;
}
}
// Упаковываем IP адрес в uint32_t
conf.port_tcp.addr = (ip[0]) | (ip[1] << 8) | (ip[2] << 16) | (ip[3] << 24);
jl_config_save("modbus", &conf, sizeof(jl_modbus_config_t));
printf("TCP IP address set to %u.%u.%u.%u\n", ip[0], ip[1], ip[2], ip[3]);
return 0;
}
// TCP port
else if (strcmp(argv[1], "port") == 0)
{
long val = strtol(argv[2], NULL, 10);
if (val < 1 || val > 65535)
{
fprintf(stderr, "Error: port must be between 1 and 65535\n");
return 1;
}
conf.port_tcp.port = (uint16_t)val;
jl_config_save("modbus", &conf, sizeof(jl_modbus_config_t));
printf("TCP port set to %u\n", conf.port_tcp.port);
return 0;
}
// TCP timeout
else if (strcmp(argv[1], "timeout") == 0)
{
long val = strtol(argv[2], NULL, 10);
if (val < 0 || val > 65535)
{
fprintf(stderr, "Error: timeout must be between 0 and 65535 ms\n");
return 1;
}
conf.port_tcp.timeout = (uint16_t)val;
jl_config_save("modbus", &conf, sizeof(jl_modbus_config_t));
printf("TCP timeout set to %u ms\n", conf.port_tcp.timeout);
return 0;
}
// TCP repeat
else if (strcmp(argv[1], "repeat") == 0)
{
long val = strtol(argv[2], NULL, 10);
if (val < 0 || val > 65535)
{
fprintf(stderr, "Error: repeat count must be between 0 and 65535\n");
return 1;
}
conf.port_tcp.repeate = (uint16_t)val;
jl_config_save("modbus", &conf, sizeof(jl_modbus_config_t));
printf("TCP repeat count set to %u\n", conf.port_tcp.repeate);
return 0;
}
else
{
fprintf(stderr, "Error: unknown TCP parameter '%s'\n", argv[1]);
return 1;
}
}
// Device address
else if (strcmp(argv[0], "addr") == 0)
{
if (argc < 2)
{
fprintf(stderr, "Error: address value required\n");
return 1;
}
long val = strtol(argv[1], NULL, 10);
if (val < 1 || val > 247)
{
fprintf(stderr, "Error: device address must be between 1 and 247\n");
return 1;
}
conf.addr = (uint16_t)val;
jl_config_save("modbus", &conf, sizeof(jl_modbus_config_t));
printf("Device address set to %u\n", conf.addr);
return 0;
}
// Active port
else if (strcmp(argv[0], "active_port") == 0)
{
if (argc < 2)
{
fprintf(stderr, "Error: active_port value required (0=RS485, 1=TCP)\n");
return 1;
}
long val = strtol(argv[1], NULL, 10);
if (val < 0 || val > 1)
{
fprintf(stderr, "Error: active_port must be 0 (RS485) or 1 (TCP)\n");
return 1;
}
conf.num_port = (uint16_t)val;
jl_config_save("modbus", &conf, sizeof(jl_modbus_config_t));
printf("Active port set to %u (%s)\n", conf.num_port,
conf.num_port == 0 ? "RS485" : "TCP");
return 0;
}
// Polling cycle
else if (strcmp(argv[0], "tcycle") == 0)
{
if (argc < 2)
{
fprintf(stderr, "Error: tcycle value required\n");
return 1;
}
long val = strtol(argv[1], NULL, 10);
if (val < 0 || val > 65535)
{
fprintf(stderr, "Error: polling cycle must be between 0 and 65535 ms\n");
return 1;
}
conf.tcycle = (uint16_t)val;
jl_config_save("modbus", &conf, sizeof(jl_modbus_config_t));
printf("Polling cycle set to %u ms\n", conf.tcycle);
return 0;
}
else
{
fprintf(stderr, "Error: unknown parameter '%s'\n", argv[0]);
fprintf(stderr, "Use 'jlv135_cli set modbus' without arguments to see usage\n");
return 1;
}
return 0;
}

View File

@@ -0,0 +1,122 @@
#include <jl_modbus/jl_config.h>
#include <jlv135_cli/jl_block_secure.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
typedef struct _jlv_secure_t
{
uint32_t user_pass;
uint32_t service_pass;
bool user_block : 1;
bool service_block : 1;
} jlv_secure_t;
// Метод get: отображает все параметры блока secure
int
jl_block_secure_get(void)
{
jlv_secure_t conf = {};
jl_config_load("secure", &conf, sizeof(jlv_secure_t));
printf("Security Configuration:\n");
printf(" User Password: %s\n", conf.user_pass ? "Set" : "Not set");
printf(" Service Password: %s\n", conf.service_pass ? "Set" : "Not set");
printf(" User Lock: %s\n", conf.user_block ? "Enabled" : "Disabled");
printf(" Service Lock: %s\n", conf.service_block ? "Enabled" : "Disabled");
return 0;
}
// Метод set: изменяет параметры блока secure
int
jl_block_secure_set(int argc, const char *argv[])
{
if (argc < 1)
{
fprintf(stderr, "Error: insufficient arguments for 'set secure'\n");
fprintf(stderr, "Usage:\n");
fprintf(stderr, " jlv135_cli set secure user_pass <password>\n");
fprintf(stderr, " jlv135_cli set secure service_pass <password>\n");
fprintf(stderr, " jlv135_cli set secure user_lock <on|off>\n");
fprintf(stderr, " jlv135_cli set secure service_lock <on|off>\n");
return 1;
}
jlv_secure_t conf = {};
jl_config_load("secure", &conf, sizeof(jlv_secure_t));
if (argc < 2)
{
fprintf(stderr, "Error: value required\n");
return 1;
}
// User password
if (strcmp(argv[0], "user_pass") == 0)
{
conf.user_pass = (uint32_t)strtoul(argv[1], NULL, 10);
jl_config_save("secure", &conf, sizeof(jlv_secure_t));
printf("User password set\n");
return 0;
}
// Service password
else if (strcmp(argv[0], "service_pass") == 0)
{
conf.service_pass = (uint32_t)strtoul(argv[1], NULL, 10);
jl_config_save("secure", &conf, sizeof(jlv_secure_t));
printf("Service password set\n");
return 0;
}
// User lock
else if (strcmp(argv[0], "user_lock") == 0)
{
if (strcmp(argv[1], "on") == 0 || strcmp(argv[1], "1") == 0)
{
conf.user_block = true;
}
else if (strcmp(argv[1], "off") == 0 || strcmp(argv[1], "0") == 0)
{
conf.user_block = false;
}
else
{
fprintf(stderr, "Error: invalid user_lock value '%s' (use on|off)\n", argv[1]);
return 1;
}
jl_config_save("secure", &conf, sizeof(jlv_secure_t));
printf("User lock %s\n", conf.user_block ? "enabled" : "disabled");
return 0;
}
// Service lock
else if (strcmp(argv[0], "service_lock") == 0)
{
if (strcmp(argv[1], "on") == 0 || strcmp(argv[1], "1") == 0)
{
conf.service_block = true;
}
else if (strcmp(argv[1], "off") == 0 || strcmp(argv[1], "0") == 0)
{
conf.service_block = false;
}
else
{
fprintf(stderr, "Error: invalid service_lock value '%s' (use on|off)\n", argv[1]);
return 1;
}
jl_config_save("secure", &conf, sizeof(jlv_secure_t));
printf("Service lock %s\n", conf.service_block ? "enabled" : "disabled");
return 0;
}
else
{
fprintf(stderr, "Error: unknown parameter '%s'\n", argv[0]);
return 1;
}
return 0;
}

View File

@@ -0,0 +1,139 @@
#include <jl_modbus/jl_config.h>
#include <jlv135_cli/jl_block_sensor.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
typedef struct _jlv_sensor_t
{
uint8_t send_TH; // 1 - отправлять в ПУ температуру и влажность
uint8_t send_P; // 1 - отправлять в ПУ давление
float TK_delta; // температурный коэффициент разницы "гор"-"хол"
float TNot_lin; // температурный коэффициент нелинейности
} jlv_sensor_t;
// Метод get: отображает все параметры блока sensor
int
jl_block_sensor_get(void)
{
jlv_sensor_t conf = {};
jl_config_load("sensor", &conf, sizeof(jlv_sensor_t));
printf("Sensor Configuration:\n");
printf(" Send T/H: %s\n", conf.send_TH ? "Enabled" : "Disabled");
printf(" Send Pressure: %s\n", conf.send_P ? "Enabled" : "Disabled");
printf(" TK Delta: %.3f\n", conf.TK_delta);
printf(" TNot Linear: %.3f\n", conf.TNot_lin);
return 0;
}
// Метод set: изменяет параметры блока sensor
int
jl_block_sensor_set(int argc, const char *argv[])
{
if (argc < 1)
{
fprintf(stderr, "Error: insufficient arguments for 'set sensor'\n");
fprintf(stderr, "Usage:\n");
fprintf(stderr, " jlv135_cli set sensor send_th <on|off>\n");
fprintf(stderr, " jlv135_cli set sensor send_p <on|off>\n");
fprintf(stderr, " jlv135_cli set sensor tk_delta <value>\n");
fprintf(stderr, " jlv135_cli set sensor tnot_lin <value>\n");
return 1;
}
jlv_sensor_t conf = {};
jl_config_load("sensor", &conf, sizeof(jlv_sensor_t));
// Send T/H
if (strcmp(argv[0], "send_th") == 0)
{
if (argc < 2)
{
fprintf(stderr, "Error: send_th value required (on|off)\n");
return 1;
}
if (strcmp(argv[1], "on") == 0 || strcmp(argv[1], "1") == 0)
{
conf.send_TH = 1;
}
else if (strcmp(argv[1], "off") == 0 || strcmp(argv[1], "0") == 0)
{
conf.send_TH = 0;
}
else
{
fprintf(stderr, "Error: invalid send_th value '%s' (use on|off)\n", argv[1]);
return 1;
}
jl_config_save("sensor", &conf, sizeof(jlv_sensor_t));
printf("Send T/H %s\n", conf.send_TH ? "enabled" : "disabled");
return 0;
}
// Send Pressure
else if (strcmp(argv[0], "send_p") == 0)
{
if (argc < 2)
{
fprintf(stderr, "Error: send_p value required (on|off)\n");
return 1;
}
if (strcmp(argv[1], "on") == 0 || strcmp(argv[1], "1") == 0)
{
conf.send_P = 1;
}
else if (strcmp(argv[1], "off") == 0 || strcmp(argv[1], "0") == 0)
{
conf.send_P = 0;
}
else
{
fprintf(stderr, "Error: invalid send_p value '%s' (use on|off)\n", argv[1]);
return 1;
}
jl_config_save("sensor", &conf, sizeof(jlv_sensor_t));
printf("Send Pressure %s\n", conf.send_P ? "enabled" : "disabled");
return 0;
}
// TK Delta
else if (strcmp(argv[0], "tk_delta") == 0)
{
if (argc < 2)
{
fprintf(stderr, "Error: tk_delta value required\n");
return 1;
}
conf.TK_delta = strtof(argv[1], NULL);
jl_config_save("sensor", &conf, sizeof(jlv_sensor_t));
printf("TK Delta set to %.3f\n", conf.TK_delta);
return 0;
}
// TNot Linear
else if (strcmp(argv[0], "tnot_lin") == 0)
{
if (argc < 2)
{
fprintf(stderr, "Error: tnot_lin value required\n");
return 1;
}
conf.TNot_lin = strtof(argv[1], NULL);
jl_config_save("sensor", &conf, sizeof(jlv_sensor_t));
printf("TNot Linear set to %.3f\n", conf.TNot_lin);
return 0;
}
else
{
fprintf(stderr, "Error: unknown parameter '%s'\n", argv[0]);
return 1;
}
return 0;
}

View File

@@ -0,0 +1,170 @@
#include <jl_modbus/jl_config.h>
#include <jlv135_cli/jl_block_service.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#define JL_FILTER_MAX 4
typedef struct _jlv_filter_state_t
{
uint16_t min_p;
uint16_t max_p;
} jlv_filter_state_t;
typedef struct _jlv_filter_t
{
jlv_filter_state_t single;
jlv_filter_state_t duplex;
bool duplex_filter : 1;
bool checkbox_duplex_filter : 1;
} jlv_filter_t;
typedef struct _jlv_service_t
{
jlv_filter_t filters[JL_FILTER_MAX];
} jlv_service_t;
// Метод get: отображает все параметры блока service
int
jl_block_service_get(void)
{
jlv_service_t conf = {};
jl_config_load("service", &conf, sizeof(jlv_service_t));
printf("Service Configuration:\n");
for (int i = 0; i < JL_FILTER_MAX; i++)
{
printf("\nFilter %d:\n", i + 1);
printf(" Duplex Mode: %s\n", conf.filters[i].duplex_filter ? "Yes" : "No");
printf(" Checkbox Duplex: %s\n",
conf.filters[i].checkbox_duplex_filter ? "Yes" : "No");
if (conf.filters[i].duplex_filter)
{
printf(" Single Min/Max: %u / %u\n", conf.filters[i].single.min_p,
conf.filters[i].single.max_p);
printf(" Duplex Min/Max: %u / %u\n", conf.filters[i].duplex.min_p,
conf.filters[i].duplex.max_p);
}
else
{
printf(" Min/Max: %u / %u\n", conf.filters[i].single.min_p,
conf.filters[i].single.max_p);
}
}
return 0;
}
// Метод set: изменяет параметры блока service
int
jl_block_service_set(int argc, const char *argv[])
{
if (argc < 1)
{
fprintf(stderr, "Error: insufficient arguments for 'set service'\n");
fprintf(stderr, "Usage:\n");
fprintf(stderr, " jlv135_cli set service filter <1-4> min <value>\n");
fprintf(stderr, " jlv135_cli set service filter <1-4> max <value>\n");
fprintf(stderr, " jlv135_cli set service filter <1-4> duplex <on|off>\n");
fprintf(stderr, " jlv135_cli set service filter <1-4> duplex_min <value>\n");
fprintf(stderr, " jlv135_cli set service filter <1-4> duplex_max <value>\n");
return 1;
}
jlv_service_t conf = {};
jl_config_load("service", &conf, sizeof(jlv_service_t));
// Filter configuration
if (strcmp(argv[0], "filter") == 0)
{
if (argc < 4)
{
fprintf(stderr, "Error: insufficient arguments for filter configuration\n");
fprintf(stderr, "Usage: jlv135_cli set service filter <1-4> <parameter> <value>\n");
return 1;
}
// Получаем номер фильтра (1-4)
long filter_num = strtol(argv[1], NULL, 10);
if (filter_num < 1 || filter_num > JL_FILTER_MAX)
{
fprintf(stderr, "Error: filter number must be between 1 and %d\n", JL_FILTER_MAX);
return 1;
}
int filter_idx = (int)filter_num - 1;
// Min value (single)
if (strcmp(argv[2], "min") == 0)
{
conf.filters[filter_idx].single.min_p = (uint16_t)strtoul(argv[3], NULL, 10);
jl_config_save("service", &conf, sizeof(jlv_service_t));
printf("Filter %ld min set to %u\n", filter_num, conf.filters[filter_idx].single.min_p);
return 0;
}
// Max value (single)
else if (strcmp(argv[2], "max") == 0)
{
conf.filters[filter_idx].single.max_p = (uint16_t)strtoul(argv[3], NULL, 10);
jl_config_save("service", &conf, sizeof(jlv_service_t));
printf("Filter %ld max set to %u\n", filter_num, conf.filters[filter_idx].single.max_p);
return 0;
}
// Duplex mode
else if (strcmp(argv[2], "duplex") == 0)
{
if (strcmp(argv[3], "on") == 0 || strcmp(argv[3], "1") == 0)
{
conf.filters[filter_idx].duplex_filter = true;
}
else if (strcmp(argv[3], "off") == 0 || strcmp(argv[3], "0") == 0)
{
conf.filters[filter_idx].duplex_filter = false;
}
else
{
fprintf(stderr, "Error: invalid duplex value '%s' (use on|off)\n", argv[3]);
return 1;
}
jl_config_save("service", &conf, sizeof(jlv_service_t));
printf("Filter %ld duplex mode %s\n", filter_num,
conf.filters[filter_idx].duplex_filter ? "enabled" : "disabled");
return 0;
}
// Min value (duplex)
else if (strcmp(argv[2], "duplex_min") == 0)
{
conf.filters[filter_idx].duplex.min_p = (uint16_t)strtoul(argv[3], NULL, 10);
jl_config_save("service", &conf, sizeof(jlv_service_t));
printf("Filter %ld duplex min set to %u\n", filter_num,
conf.filters[filter_idx].duplex.min_p);
return 0;
}
// Max value (duplex)
else if (strcmp(argv[2], "duplex_max") == 0)
{
conf.filters[filter_idx].duplex.max_p = (uint16_t)strtoul(argv[3], NULL, 10);
jl_config_save("service", &conf, sizeof(jlv_service_t));
printf("Filter %ld duplex max set to %u\n", filter_num,
conf.filters[filter_idx].duplex.max_p);
return 0;
}
else
{
fprintf(stderr, "Error: unknown filter parameter '%s'\n", argv[2]);
return 1;
}
}
else
{
fprintf(stderr, "Error: unknown parameter '%s'\n", argv[0]);
return 1;
}
return 0;
}

View File

@@ -0,0 +1,111 @@
#include <jl_modbus/jl_config.h>
#include <jlv135_cli/jl_block_wifi.h>
#include <stdio.h>
#include <string.h>
#define JLV_WIFI_SSID_BYTES 32
typedef struct _jlv_wifi_t
{
char ssid[JLV_WIFI_SSID_BYTES];
char password[64];
bool enable : 1;
} jlv_wifi_t;
// Метод get: отображает все параметры блока wifi
int
jl_block_wifi_get(void)
{
jlv_wifi_t conf = {};
jl_config_load("wifi", &conf, sizeof(jlv_wifi_t));
printf("WiFi Configuration:\n");
printf(" SSID: %s\n", conf.ssid);
printf(" Password: %s\n", conf.password[0] ? "********" : "(empty)");
printf(" Enabled: %s\n", conf.enable ? "Yes" : "No");
return 0;
}
// Метод set: изменяет параметры блока wifi
int
jl_block_wifi_set(int argc, const char *argv[])
{
if (argc < 1)
{
fprintf(stderr, "Error: insufficient arguments for 'set wifi'\n");
fprintf(stderr, "Usage:\n");
fprintf(stderr, " jlv135_cli set wifi ssid <network_name>\n");
fprintf(stderr, " jlv135_cli set wifi password <password>\n");
fprintf(stderr, " jlv135_cli set wifi enable <on|off>\n");
return 1;
}
jlv_wifi_t conf = {};
jl_config_load("wifi", &conf, sizeof(jlv_wifi_t));
// SSID
if (strcmp(argv[0], "ssid") == 0)
{
if (argc < 2)
{
fprintf(stderr, "Error: SSID value required\n");
return 1;
}
strncpy(conf.ssid, argv[1], JLV_WIFI_SSID_BYTES - 1);
conf.ssid[JLV_WIFI_SSID_BYTES - 1] = '\0';
jl_config_save("wifi", &conf, sizeof(jlv_wifi_t));
printf("WiFi SSID set to: %s\n", conf.ssid);
return 0;
}
// Password
else if (strcmp(argv[0], "password") == 0)
{
if (argc < 2)
{
fprintf(stderr, "Error: password value required\n");
return 1;
}
strncpy(conf.password, argv[1], sizeof(conf.password) - 1);
conf.password[sizeof(conf.password) - 1] = '\0';
jl_config_save("wifi", &conf, sizeof(jlv_wifi_t));
printf("WiFi password set\n");
return 0;
}
// Enable/Disable
else if (strcmp(argv[0], "enable") == 0)
{
if (argc < 2)
{
fprintf(stderr, "Error: enable value required (on|off)\n");
return 1;
}
if (strcmp(argv[1], "on") == 0 || strcmp(argv[1], "1") == 0)
{
conf.enable = true;
}
else if (strcmp(argv[1], "off") == 0 || strcmp(argv[1], "0") == 0)
{
conf.enable = false;
}
else
{
fprintf(stderr, "Error: invalid enable value '%s' (use on|off)\n", argv[1]);
return 1;
}
jl_config_save("wifi", &conf, sizeof(jlv_wifi_t));
printf("WiFi %s\n", conf.enable ? "enabled" : "disabled");
return 0;
}
else
{
fprintf(stderr, "Error: unknown parameter '%s'\n", argv[0]);
return 1;
}
return 0;
}

View File

@@ -1,139 +1,110 @@
#include <jl_modbus/jl_config.h>
#include <jl_modbus/jl_modbus_config.h>
#include <jlv135_cli/jl_block.h>
#include <jlv135_cli/version.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define JLV135_CLI_OK 0
#define JLV135_CLI_ERROR 1
void
print_version(jl_version_t *ver)
// Печать справки
static void
print_help(const char *program_name)
{
printf("Version:\n");
printf(" major: %u\n", ver->major);
printf(" minor: %u\n", ver->minor);
printf(" path: %u\n\n", ver->path);
}
printf("Usage: %s [COMMAND] [BLOCK] [PARAMETERS...]\n\n", program_name);
printf("Commands:\n");
printf(" get <block> Display all parameters of the specified block\n");
printf(" set <block> ... Modify parameters of the specified block\n");
printf(" version Display full version information\n");
printf(" ver Display short version\n\n");
printf("Available blocks:\n");
// Функция для печати TCP порта
void
print_tcp_port(jl_modbus_tcp_port_t *tcp)
{
printf("Modbus TCP Port:\n");
printf(" addr: %u\n", tcp->addr);
printf(" port: %u\n", tcp->port);
printf(" repeate: %u\n", tcp->repeate);
printf(" timeout: %u\n\n", tcp->timeout);
}
void
print_rs485_baud_rates(uint16_t speed_index)
{
if (jl_modbus_rs485_baud_rate_is_index_valid(speed_index))
const jl_block_t *block = jl_block_get_all();
while (block->name != NULL)
{
printf(" speed: %u\n", jl_modbus_rs485_baud_rates[speed_index]);
printf(" - %s\n", block->name);
block++;
}
else
{
printf(" speed: %s\n", "unknown");
}
}
// Функция для печати RS485 порта
void
print_rs485_port(jl_modbus_rs485_port_t *rs485)
{
printf("Modbus RS485 Port:\n");
print_rs485_baud_rates(rs485->speed);
printf(" prop_p: %u\n", rs485->prop_p);
printf(" prop_s: %u\n", rs485->prop_s);
printf(" repeate: %u\n", rs485->repeate);
printf(" timeout: %u\n\n", rs485->timeout);
}
// Функция для печати конфигурации Modbus
void
print_modbus_config(jl_modbus_config_t *config)
{
printf("Modbus Config:\n");
printf(" num_port: %u\n", config->num_port);
printf(" addr: %u\n", config->addr);
printf(" tcycle: %u\n", config->tcycle);
printf("\n");
// Печатаем вложенные структуры
print_rs485_port(&config->port_rtu);
print_tcp_port(&config->port_tcp);
printf("\nExamples:\n");
printf(" %s get modbus\n", program_name);
printf(" %s set modbus rs485 speed 9600\n", program_name);
}
int
main(int argc, const char *argv[])
{
jl_modbus_config_t conf = {};
jl_config_load("modbus", &conf, sizeof(jl_modbus_config_t));
// Вызов без аргументов - показываем справку
if (argc == 1)
{
print_modbus_config(&conf);
print_help(argv[0]);
return JLV135_CLI_OK;
}
const char *command = argv[1];
// Команда get
if (strcmp(command, "get") == 0)
{
if (argc < 3)
{
fprintf(stderr, "Error: 'get' command requires a block name\n");
fprintf(stderr, "Usage: %s get <block>\n", argv[0]);
return JLV135_CLI_ERROR;
}
const char *block_name = argv[2];
const jl_block_t *block = jl_block_find(block_name);
if (block == NULL)
{
fprintf(stderr, "Error: unknown block '%s'\n", block_name);
fprintf(stderr, "Run '%s' to see available blocks\n", argv[0]);
return JLV135_CLI_ERROR;
}
return block->get();
}
// Команда set
else if (strcmp(command, "set") == 0)
{
if (argc < 3)
{
fprintf(stderr, "Error: 'set' command requires a block name\n");
fprintf(stderr, "Usage: %s set <block> <parameters...>\n", argv[0]);
return JLV135_CLI_ERROR;
}
const char *block_name = argv[2];
const jl_block_t *block = jl_block_find(block_name);
if (block == NULL)
{
fprintf(stderr, "Error: unknown block '%s'\n", block_name);
fprintf(stderr, "Run '%s' to see available blocks\n", argv[0]);
return JLV135_CLI_ERROR;
}
// Передаем оставшиеся аргументы в метод set блока
return block->set(argc - 3, &argv[3]);
}
// Команда version
else if (strcmp(command, "version") == 0)
{
printf("jlv135_cli version %s\n", JLV135_VERSION);
return JLV135_CLI_OK;
}
// Команда ver (короткая версия)
else if (strcmp(command, "ver") == 0)
{
printf("%s\n", JLV135_VERSION_SHORT);
return JLV135_CLI_OK;
}
else
{
bool modbus_mode = false; // Флаг, что был передан --modbus
bool modbus_rs485_mode = true; // Флаг, что был передан --rs485
for (int i = 1; i < argc; i++)
{
if (strcmp(argv[i], "--modbus") == 0)
{
modbus_mode = true;
continue;
}
else if (modbus_mode)
{
// Эти параметры обрабатываются только если был --modbus
if (modbus_mode && strcmp(argv[i], "--rs485") == 0)
{
modbus_rs485_mode = true;
continue;
}
else if (modbus_rs485_mode && strcmp(argv[i], "--speed") == 0)
{
if (i + 1 < argc)
{
long val = strtol(argv[i + 1], NULL, 10);
int idx = jl_modbus_rs485_baud_rate_get_index_by_baud(val);
if (idx == -1)
{
fprintf(stderr, "Error: invalid speed value\n");
return JLV135_CLI_ERROR;
}
else
{
conf.port_rtu.speed = idx;
jl_config_save("modbus", &conf, sizeof(jl_modbus_config_t));
}
break;
}
else
{
fprintf(stderr, "Error: --speed requires a value\n");
return JLV135_CLI_ERROR;
}
}
else
{
fprintf(stderr, "Unknown parameter for --modbus: %s\n", argv[i]);
return JLV135_CLI_ERROR;
}
}
else
{
fprintf(stderr, "Unknown parameter: %s (did you forget --modbus?)\n", argv[i]);
return JLV135_CLI_ERROR;
}
}
fprintf(stderr, "Error: unknown command '%s'\n", command);
fprintf(stderr, "Run '%s' to see usage\n", argv[0]);
return JLV135_CLI_ERROR;
}
return JLV135_CLI_OK;
}