Minimize contract, add ADC read and send its data to coonsole
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"$id": "contract/ingest/common.schema.json",
|
||||
"type": "object",
|
||||
"required": ["v", "id", "type", "ts", "deviceId", "payload"],
|
||||
"required": ["v", "t", "id", "ts", "d", "p"],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"v": {
|
||||
@@ -10,28 +10,68 @@
|
||||
"const": 1
|
||||
},
|
||||
"id": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"maximum": 4294967295,
|
||||
"description": "Autoincrement message id. Unique per session"
|
||||
},
|
||||
"type": {
|
||||
"t": {
|
||||
"type": "string",
|
||||
"enum": ["telemetry", "event"]
|
||||
"enum": ["t", "e", "c"],
|
||||
"description": "Message type (<t>elemetry, <e>vent, <c>ommand)"
|
||||
},
|
||||
"ts": {
|
||||
"type": "integer",
|
||||
"minimum": 1600000000000,
|
||||
"description": "Unix time in milliseconds (UTC)"
|
||||
"minimum": 1600000000,
|
||||
"description": "Unix time in seconds (UTC)"
|
||||
},
|
||||
"deviceId": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
"d": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"description": "Device ID. Unique per scope"
|
||||
},
|
||||
"payload": {
|
||||
"type": "object"
|
||||
},
|
||||
"meta": {
|
||||
"p": {
|
||||
"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" }
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,46 +1,44 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"$id": "contract/ingest/telemetry.schema.json",
|
||||
"allOf": [
|
||||
{ "$ref": "contract/ingest/common.schema.json" },
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"payload": {
|
||||
"type": "object",
|
||||
"required": ["measurements"],
|
||||
"required": ["m", "s", "u", "v"],
|
||||
"additionalProperties": false,
|
||||
"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",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["metric", "value"],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"metric": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
"type": "array",
|
||||
"minItems": 2,
|
||||
"maxItems": 2,
|
||||
"items": [
|
||||
{
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"description": "Delta time (seconds) from base ts"
|
||||
},
|
||||
"value": {
|
||||
"type": ["number", "string", "boolean"]
|
||||
},
|
||||
"unit": {
|
||||
"type": "string"
|
||||
},
|
||||
"source": {
|
||||
"type": "string"
|
||||
},
|
||||
"ts": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
"type": "number",
|
||||
"description": "Measured value"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
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 "."
|
||||
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
|
||||
set(COMPONENT_KCONFIG "Kconfig")
|
||||
26
esp32/main/adc_reader.cpp
Normal file
26
esp32/main/adc_reader.cpp
Normal 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
7
esp32/main/adc_reader.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
// Инициализация ADC
|
||||
void adc_reader_init();
|
||||
|
||||
// Прочитать значение (GPIO35)
|
||||
int adc_reader_read();
|
||||
@@ -4,6 +4,8 @@
|
||||
#include "freertos/projdefs.h"
|
||||
#include "freertos/task.h"
|
||||
#include "protocol.h"
|
||||
#include "sampler_task.h"
|
||||
#include "sender_task.h"
|
||||
|
||||
static const char* TAG = "iot_fish";
|
||||
|
||||
@@ -11,16 +13,8 @@ extern "C" void app_main(void)
|
||||
{
|
||||
system_init();
|
||||
|
||||
for (int i=0; i<5; i++)
|
||||
{
|
||||
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));
|
||||
}
|
||||
sampler_task_start();
|
||||
sender_task_start();
|
||||
|
||||
system_finalize();
|
||||
}
|
||||
21
esp32/main/ringbuf.cpp
Normal file
21
esp32/main/ringbuf.cpp
Normal 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
19
esp32/main/ringbuf.h
Normal 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);
|
||||
39
esp32/main/sampler_task.cpp
Normal file
39
esp32/main/sampler_task.cpp
Normal 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
|
||||
);
|
||||
}
|
||||
6
esp32/main/sampler_task.h
Normal file
6
esp32/main/sampler_task.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "ringbuf.h"
|
||||
|
||||
void sampler_task_start();
|
||||
ringbuf_t* sampler_get_buffer(); // ← ВОТ ЭТО
|
||||
48
esp32/main/sender_task.cpp
Normal file
48
esp32/main/sender_task.cpp
Normal 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
4
esp32/main/sender_task.h
Normal file
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
// Запуск задачи отправки (1 Гц)
|
||||
void sender_task_start();
|
||||
Reference in New Issue
Block a user