Minimize contract, add ADC read and send its data to coonsole

This commit is contained in:
2026-04-13 00:04:48 +03:00
parent 732a2dfa32
commit 977227296e
12 changed files with 269 additions and 67 deletions

View File

@@ -2,7 +2,7 @@
"$schema": "http://json-schema.org/draft-07/schema#", "$schema": "http://json-schema.org/draft-07/schema#",
"$id": "contract/ingest/common.schema.json", "$id": "contract/ingest/common.schema.json",
"type": "object", "type": "object",
"required": ["v", "id", "type", "ts", "deviceId", "payload"], "required": ["v", "t", "id", "ts", "d", "p"],
"additionalProperties": false, "additionalProperties": false,
"properties": { "properties": {
"v": { "v": {
@@ -10,28 +10,68 @@
"const": 1 "const": 1
}, },
"id": { "id": {
"type": "string", "type": "integer",
"minLength": 1 "minimum": 1,
"maximum": 4294967295,
"description": "Autoincrement message id. Unique per session"
}, },
"type": { "t": {
"type": "string", "type": "string",
"enum": ["telemetry", "event"] "enum": ["t", "e", "c"],
"description": "Message type (<t>elemetry, <e>vent, <c>ommand)"
}, },
"ts": { "ts": {
"type": "integer", "type": "integer",
"minimum": 1600000000000, "minimum": 1600000000,
"description": "Unix time in milliseconds (UTC)" "description": "Unix time in seconds (UTC)"
}, },
"deviceId": { "d": {
"type": "string", "type": "integer",
"minLength": 1 "minimum": 1,
"description": "Device ID. Unique per scope"
}, },
"payload": { "p": {
"type": "object"
},
"meta": {
"type": "object", "type": "object",
"additionalProperties": true "description": "User data. Type-specific."
}
},
"allOf": [
{
"if": {
"required": ["t"],
"properties": { "t": { "const": "t" } }
},
"then": {
"required": ["p"],
"properties": {
"p": { "$ref": "telemetry.schema.json" }
}
}
},
{
"if": {
"required": ["t"],
"properties": { "t": { "const": "e" } }
},
"then": {
"required": ["p"],
"properties": {
"p": { "$ref": "event.schema.json" }
}
}
},
{
"if": {
"required": ["t"],
"properties": { "t": { "const": "c" } }
},
"then": {
"required": ["p"],
"properties": {
"p": { "$ref": "command.schema.json" }
} }
} }
} }
]
}

View File

@@ -1,46 +1,44 @@
{ {
"$schema": "http://json-schema.org/draft-07/schema#", "$schema": "http://json-schema.org/draft-07/schema#",
"$id": "contract/ingest/telemetry.schema.json", "$id": "contract/ingest/telemetry.schema.json",
"allOf": [
{ "$ref": "contract/ingest/common.schema.json" },
{
"type": "object", "type": "object",
"properties": { "required": ["m", "s", "u", "v"],
"payload": {
"type": "object",
"required": ["measurements"],
"additionalProperties": false, "additionalProperties": false,
"properties": { "properties": {
"measurements": { "m": {
"type": "string",
"minLength": 1,
"description": "Metric type (e.g. t=temperature, h=humidity)"
},
"s": {
"type": "string",
"minLength": 1,
"description": "Source identifier (sensor/channel)"
},
"u": {
"type": "string",
"minLength": 1,
"description": "Unit (e.g. c, pct, v)"
},
"v": {
"type": "array", "type": "array",
"minItems": 1, "minItems": 1,
"items": { "items": {
"type": "object", "type": "array",
"required": ["metric", "value"], "minItems": 2,
"additionalProperties": false, "maxItems": 2,
"properties": { "items": [
"metric": { {
"type": "string", "type": "integer",
"minLength": 1 "minimum": 0,
"description": "Delta time (seconds) from base ts"
}, },
"value": { {
"type": ["number", "string", "boolean"] "type": "number",
}, "description": "Measured value"
"unit": {
"type": "string"
},
"source": {
"type": "string"
},
"ts": {
"type": "integer"
}
}
}
}
}
}
}
} }
] ]
} }
}
}
}

View File

@@ -1,7 +1,7 @@
idf_component_register( idf_component_register(
SRCS "main.cpp" "protocol.cpp" "wifi_manager.cpp" "system_init.cpp" "time_sync.cpp" SRCS "main.cpp" "protocol.cpp" "wifi_manager.cpp" "system_init.cpp" "time_sync.cpp" "adc_reader.cpp" "ringbuf.cpp" "sampler_task.cpp" "sender_task.cpp"
INCLUDE_DIRS "." INCLUDE_DIRS "."
REQUIRES nvs_flash esp_wifi esp_netif freertos log cjson esp_timer REQUIRES nvs_flash esp_wifi esp_netif freertos log cjson esp_timer esp_adc
) )
# добавляем кастомный Kconfig # добавляем кастомный Kconfig
set(COMPONENT_KCONFIG "Kconfig") set(COMPONENT_KCONFIG "Kconfig")

26
esp32/main/adc_reader.cpp Normal file
View File

@@ -0,0 +1,26 @@
#include "adc_reader.h"
extern "C" {
#include "esp_adc/adc_oneshot.h"
}
static adc_oneshot_unit_handle_t adc_handle;
void adc_reader_init() {
adc_oneshot_unit_init_cfg_t init_config = {};
init_config.unit_id = ADC_UNIT_1;
adc_oneshot_new_unit(&init_config, &adc_handle);
adc_oneshot_chan_cfg_t config = {};
config.atten = ADC_ATTEN_DB_12;
config.bitwidth = ADC_BITWIDTH_DEFAULT;
adc_oneshot_config_channel(adc_handle, ADC_CHANNEL_7, &config); // GPIO35
}
int adc_reader_read() {
int val = 0;
adc_oneshot_read(adc_handle, ADC_CHANNEL_7, &val);
return val;
}

7
esp32/main/adc_reader.h Normal file
View File

@@ -0,0 +1,7 @@
#pragma once
// Инициализация ADC
void adc_reader_init();
// Прочитать значение (GPIO35)
int adc_reader_read();

View File

@@ -4,6 +4,8 @@
#include "freertos/projdefs.h" #include "freertos/projdefs.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "protocol.h" #include "protocol.h"
#include "sampler_task.h"
#include "sender_task.h"
static const char* TAG = "iot_fish"; static const char* TAG = "iot_fish";
@@ -11,16 +13,8 @@ extern "C" void app_main(void)
{ {
system_init(); system_init();
for (int i=0; i<5; i++) sampler_task_start();
{ sender_task_start();
char buf[512];
int len = build_telemetry_single(buf, sizeof(buf), "123", "dev1", 123456, "temperature", 22.5, "C", nullptr, 0);
if (len > 0) {
ESP_LOGI("protocol", "%s\n", buf);
}
vTaskDelay(pdMS_TO_TICKS(1000));
}
system_finalize(); system_finalize();
} }

21
esp32/main/ringbuf.cpp Normal file
View File

@@ -0,0 +1,21 @@
#include "ringbuf.h"
void ringbuf_init(ringbuf_t *rb) {
rb->head = 0;
for (int i = 0; i < RINGBUF_SIZE; i++) {
rb->values[i] = 0;
}
}
void ringbuf_push(ringbuf_t *rb, int v) {
rb->values[rb->head] = v;
rb->head = (rb->head + 1) % RINGBUF_SIZE;
}
void ringbuf_copy(const ringbuf_t *rb, int *out) {
int idx = rb->head;
for (int i = 0; i < RINGBUF_SIZE; i++) {
out[i] = rb->values[(idx + i) % RINGBUF_SIZE];
}
}

19
esp32/main/ringbuf.h Normal file
View File

@@ -0,0 +1,19 @@
#pragma once
#include <stdint.h>
#define RINGBUF_SIZE 10
typedef struct {
int values[RINGBUF_SIZE];
int head;
} ringbuf_t;
// Инициализация
void ringbuf_init(ringbuf_t *rb);
// Добавить значение
void ringbuf_push(ringbuf_t *rb, int v);
// Скопировать данные (в порядке времени)
void ringbuf_copy(const ringbuf_t *rb, int *out);

View File

@@ -0,0 +1,39 @@
#include "sampler_task.h"
#include "adc_reader.h"
#include "ringbuf.h"
extern "C" {
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
}
// буфер объявим здесь (глобальный для простоты)
static ringbuf_t rb;
// дать доступ другим модулям (sender потом возьмёт)
ringbuf_t* sampler_get_buffer() {
return &rb;
}
static void sampler_task(void *arg) {
while (1) {
int val = adc_reader_read();
ringbuf_push(&rb, val);
vTaskDelay(pdMS_TO_TICKS(100)); // 10 Гц
}
}
void sampler_task_start() {
ringbuf_init(&rb);
adc_reader_init();
xTaskCreate(
sampler_task,
"sampler",
2048,
NULL,
5,
NULL
);
}

View File

@@ -0,0 +1,6 @@
#pragma once
#include "ringbuf.h"
void sampler_task_start();
ringbuf_t* sampler_get_buffer(); // ← ВОТ ЭТО

View File

@@ -0,0 +1,48 @@
#include "sender_task.h"
#include "sampler_task.h"
#include "ringbuf.h"
#include <stdio.h>
#include <time.h>
extern "C" {
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
}
static uint32_t msg_id = 1;
static void sender_task(void *arg) {
int data[RINGBUF_SIZE];
while (1) {
vTaskDelay(pdMS_TO_TICKS(1000)); // 1 Гц
ringbuf_t *rb = sampler_get_buffer();
ringbuf_copy(rb, data);
time_t now = time(NULL);
// формируем JSON
printf("{\"v\":1,\"t\":\"t\",\"id\":%lu,\"ts\":%lld,\"d\":1,\"p\":{",
(unsigned long)msg_id++, (long long)now);
printf("\"m\":\"v\",\"s\":\"adc35\",\"u\":\"raw\",\"v\":[");
for (int i = 0; i < RINGBUF_SIZE; i++) {
printf("[%d,%d]%s", i, data[i], (i < RINGBUF_SIZE - 1) ? "," : "");
}
printf("]}}\n");
}
}
void sender_task_start() {
xTaskCreate(
sender_task,
"sender",
4096,
NULL,
5,
NULL
);
}

4
esp32/main/sender_task.h Normal file
View File

@@ -0,0 +1,4 @@
#pragma once
// Запуск задачи отправки (1 Гц)
void sender_task_start();