Merge branch 'feature/local_ctrl_no_sec' into 'master'
ESP Local Ctrl Feature Added See merge request idf/esp-idf!5348
This commit is contained in:
commit
28f1cdf5ed
39 changed files with 4700 additions and 6 deletions
1
.flake8
1
.flake8
|
@ -160,4 +160,5 @@ exclude =
|
|||
components/wifi_provisioning/python/wifi_scan_pb2.py,
|
||||
components/wifi_provisioning/python/wifi_config_pb2.py,
|
||||
components/wifi_provisioning/python/wifi_constants_pb2.py,
|
||||
components/esp_local_ctrl/python/esp_local_ctrl_pb2.py,
|
||||
examples/provisioning/custom_config/components/custom_provisioning/python/custom_config_pb2.py,
|
||||
|
|
23
components/esp_local_ctrl/CMakeLists.txt
Normal file
23
components/esp_local_ctrl/CMakeLists.txt
Normal file
|
@ -0,0 +1,23 @@
|
|||
set(include_dirs include)
|
||||
set(priv_include_dirs proto-c src ../protocomm/proto-c)
|
||||
set(srcs "src/esp_local_ctrl.c"
|
||||
"src/esp_local_ctrl_handler.c"
|
||||
"proto-c/esp_local_ctrl.pb-c.c")
|
||||
|
||||
if(CONFIG_ESP_HTTPS_SERVER_ENABLE)
|
||||
list(APPEND srcs
|
||||
"src/esp_local_ctrl_transport_httpd.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_BT_ENABLED)
|
||||
if(CONFIG_BT_BLUEDROID_ENABLED)
|
||||
list(APPEND srcs
|
||||
"src/esp_local_ctrl_transport_ble.c")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
INCLUDE_DIRS "${include_dirs}"
|
||||
PRIV_INCLUDE_DIRS "${priv_include_dirs}"
|
||||
REQUIRES protocomm esp_https_server
|
||||
PRIV_REQUIRES protobuf-c mdns)
|
11
components/esp_local_ctrl/component.mk
Normal file
11
components/esp_local_ctrl/component.mk
Normal file
|
@ -0,0 +1,11 @@
|
|||
COMPONENT_SRCDIRS := src proto-c
|
||||
COMPONENT_ADD_INCLUDEDIRS := include
|
||||
COMPONENT_PRIV_INCLUDEDIRS := src proto-c ../protocomm/proto-c/
|
||||
|
||||
ifndef CONFIG_BT_BLUEDROID_ENABLED
|
||||
COMPONENT_OBJEXCLUDE += src/esp_local_ctrl_transport_ble.o
|
||||
endif
|
||||
|
||||
ifndef CONFIG_ESP_HTTPS_SERVER_ENABLE
|
||||
COMPONENT_OBJEXCLUDE += src/esp_local_ctrl_transport_httpd.o
|
||||
endif
|
339
components/esp_local_ctrl/include/esp_local_ctrl.h
Normal file
339
components/esp_local_ctrl/include/esp_local_ctrl.h
Normal file
|
@ -0,0 +1,339 @@
|
|||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <protocomm.h>
|
||||
|
||||
/**
|
||||
* @brief Property description data structure, which is to be populated
|
||||
* and passed to the `esp_local_ctrl_add_property()` function
|
||||
*
|
||||
* Once a property is added, its structure is available for read-only access
|
||||
* inside `get_prop_values()` and `set_prop_values()` handlers.
|
||||
*/
|
||||
typedef struct esp_local_ctrl_prop {
|
||||
/**
|
||||
* Unique name of property
|
||||
*/
|
||||
char *name;
|
||||
|
||||
/**
|
||||
* Type of property. This may be set to application defined enums
|
||||
*/
|
||||
uint32_t type;
|
||||
|
||||
/**
|
||||
* Size of the property value, which:
|
||||
* - if zero, the property can have values of variable size
|
||||
* - if non-zero, the property can have values of fixed size only,
|
||||
* therefore, checks are performed internally by esp_local_ctrl
|
||||
* when setting the value of such a property
|
||||
*/
|
||||
size_t size;
|
||||
|
||||
/**
|
||||
* Flags set for this property. This could be a bit field.
|
||||
* A flag may indicate property behavior, e.g. read-only / constant
|
||||
*/
|
||||
uint32_t flags;
|
||||
|
||||
/**
|
||||
* Pointer to some context data relevant for this property. This will
|
||||
* be available for use inside the `get_prop_values` and `set_prop_values`
|
||||
* handlers as a part of this property structure. When set, this is valid
|
||||
* throughout the lifetime of a property, till either the property is
|
||||
* removed or the esp_local_ctrl service is stopped.
|
||||
*/
|
||||
void *ctx;
|
||||
|
||||
/**
|
||||
* Function used by esp_local_ctrl to internally free the property
|
||||
* context when `esp_local_ctrl_remove_property()` or
|
||||
* `esp_local_ctrl_stop()` is called.
|
||||
*/
|
||||
void (*ctx_free_fn)(void *ctx);
|
||||
} esp_local_ctrl_prop_t;
|
||||
|
||||
/**
|
||||
* @brief Property value data structure. This gets passed to the
|
||||
* `get_prop_values()` and `set_prop_values()` handlers for
|
||||
* the purpose of retrieving or setting the present value
|
||||
* of a property.
|
||||
*/
|
||||
typedef struct esp_local_ctrl_prop_val {
|
||||
/**
|
||||
* Pointer to memory holding property value
|
||||
*/
|
||||
void *data;
|
||||
|
||||
/**
|
||||
* Size of property value
|
||||
*/
|
||||
size_t size;
|
||||
|
||||
/**
|
||||
* This may be set by the application in `get_prop_values()` handler
|
||||
* to tell `esp_local_ctrl` to call this function on the data pointer
|
||||
* above, for freeing its resources after sending the `get_prop_values`
|
||||
* response.
|
||||
*/
|
||||
void (*free_fn)(void *data);
|
||||
} esp_local_ctrl_prop_val_t;
|
||||
|
||||
/**
|
||||
* @brief Handlers for receiving and responding to local
|
||||
* control commands for getting and setting properties.
|
||||
*/
|
||||
typedef struct esp_local_ctrl_handlers {
|
||||
/**
|
||||
* @brief Handler function to be implemented for retrieving current
|
||||
* values of properties
|
||||
*
|
||||
* @note If any of the properties have fixed sizes, the size field of
|
||||
* corresponding element in `prop_values` need to be set
|
||||
*
|
||||
* @param[in] props_count Total elements in the props array
|
||||
* @param[in] props Array of properties, the current values for which
|
||||
* have been requested by the client
|
||||
* @param[out] prop_values Array of empty property values, the elements of
|
||||
* which need to be populated with the current values
|
||||
* of those properties specified by props argument
|
||||
* @param[in] usr_ctx This provides value of the `usr_ctx` field of
|
||||
* `esp_local_ctrl_handlers_t` structure
|
||||
*
|
||||
* @return Returning different error codes will convey the corresponding
|
||||
* protocol level errors to the client :
|
||||
* - ESP_OK : Success
|
||||
* - ESP_ERR_INVALID_ARG : InvalidArgument
|
||||
* - ESP_ERR_INVALID_STATE : InvalidProto
|
||||
* - All other error codes : InternalError
|
||||
*/
|
||||
esp_err_t (*get_prop_values)(size_t props_count,
|
||||
const esp_local_ctrl_prop_t props[],
|
||||
esp_local_ctrl_prop_val_t prop_values[],
|
||||
void *usr_ctx);
|
||||
|
||||
/**
|
||||
* @brief Handler function to be implemented for changing values of properties
|
||||
*
|
||||
* @note If any of the properties have variable sizes, the size field
|
||||
* of the corresponding element in `prop_values` must be checked
|
||||
* explicitly before making any assumptions on the size.
|
||||
*
|
||||
* @param[in] props_count Total elements in the props array
|
||||
* @param[in] props Array of properties, the values for which the
|
||||
* client requests to change
|
||||
* @param[in] prop_values Array of property values, the elements of which
|
||||
* need to be used for updating those properties
|
||||
* specified by props argument
|
||||
* @param[in] usr_ctx This provides value of the `usr_ctx` field of
|
||||
* `esp_local_ctrl_handlers_t` structure
|
||||
*
|
||||
* @return Returning different error codes will convey the corresponding
|
||||
* protocol level errors to the client :
|
||||
* - ESP_OK : Success
|
||||
* - ESP_ERR_INVALID_ARG : InvalidArgument
|
||||
* - ESP_ERR_INVALID_STATE : InvalidProto
|
||||
* - All other error codes : InternalError
|
||||
*/
|
||||
esp_err_t (*set_prop_values)(size_t props_count,
|
||||
const esp_local_ctrl_prop_t props[],
|
||||
const esp_local_ctrl_prop_val_t prop_values[],
|
||||
void *usr_ctx);
|
||||
|
||||
/**
|
||||
* Context pointer to be passed to above handler functions upon invocation.
|
||||
* This is different from the property level context, as this is valid
|
||||
* throughout the lifetime of the `esp_local_ctrl` service, and freed only
|
||||
* when the service is stopped.
|
||||
*/
|
||||
void *usr_ctx;
|
||||
|
||||
/**
|
||||
* Pointer to function which will be internally invoked on `usr_ctx` for
|
||||
* freeing the context resources when `esp_local_ctrl_stop()` is called.
|
||||
*/
|
||||
void (*usr_ctx_free_fn)(void *usr_ctx);
|
||||
} esp_local_ctrl_handlers_t;
|
||||
|
||||
/**
|
||||
* @brief Transport mode (BLE / HTTPD) over which the service will be provided
|
||||
*
|
||||
* This is forward declaration of a private structure, implemented internally
|
||||
* by `esp_local_ctrl`.
|
||||
*/
|
||||
typedef struct esp_local_ctrl_transport esp_local_ctrl_transport_t;
|
||||
|
||||
/**
|
||||
* @brief Function for obtaining BLE transport mode
|
||||
*/
|
||||
const esp_local_ctrl_transport_t *esp_local_ctrl_get_transport_ble();
|
||||
|
||||
/**
|
||||
* @brief Function for obtaining HTTPD transport mode
|
||||
*/
|
||||
const esp_local_ctrl_transport_t *esp_local_ctrl_get_transport_httpd();
|
||||
|
||||
#define ESP_LOCAL_CTRL_TRANSPORT_BLE esp_local_ctrl_get_transport_ble()
|
||||
#define ESP_LOCAL_CTRL_TRANSPORT_HTTPD esp_local_ctrl_get_transport_httpd()
|
||||
|
||||
/**
|
||||
* @brief Configuration for transport mode BLE
|
||||
*
|
||||
* This is a forward declaration for `protocomm_ble_config_t`.
|
||||
* To use this, application must set CONFIG_BT_BLUEDROID_ENABLED
|
||||
* and include `protocomm_ble.h`.
|
||||
*/
|
||||
typedef struct protocomm_ble_config esp_local_ctrl_transport_config_ble_t;
|
||||
|
||||
/**
|
||||
* @brief Configuration for transport mode HTTPD
|
||||
*
|
||||
* This is a forward declaration for `httpd_ssl_config_t`.
|
||||
* To use this, application must set CONFIG_ESP_HTTPS_SERVER_ENABLE
|
||||
* and include `esp_https_server.h`
|
||||
*/
|
||||
typedef struct httpd_ssl_config esp_local_ctrl_transport_config_httpd_t;
|
||||
|
||||
/**
|
||||
* @brief Transport mode (BLE / HTTPD) configuration
|
||||
*/
|
||||
typedef union {
|
||||
/**
|
||||
* This is same as `protocomm_ble_config_t`. See `protocomm_ble.h` for
|
||||
* available configuration parameters.
|
||||
*/
|
||||
esp_local_ctrl_transport_config_ble_t *ble;
|
||||
|
||||
/**
|
||||
* This is same as `httpd_ssl_config_t`. See `esp_https_server.h` for
|
||||
* available configuration parameters.
|
||||
*/
|
||||
esp_local_ctrl_transport_config_httpd_t *httpd;
|
||||
} esp_local_ctrl_transport_config_t;
|
||||
|
||||
/**
|
||||
* @brief Configuration structure to pass to `esp_local_ctrl_start()`
|
||||
*/
|
||||
typedef struct esp_local_ctrl_config {
|
||||
/**
|
||||
* Transport layer over which service will be provided
|
||||
*/
|
||||
const esp_local_ctrl_transport_t *transport;
|
||||
|
||||
/**
|
||||
* Transport layer over which service will be provided
|
||||
*/
|
||||
esp_local_ctrl_transport_config_t transport_config;
|
||||
|
||||
/**
|
||||
* Register handlers for responding to get/set requests on properties
|
||||
*/
|
||||
esp_local_ctrl_handlers_t handlers;
|
||||
|
||||
/**
|
||||
* This limits the number of properties that are available at a time
|
||||
*/
|
||||
size_t max_properties;
|
||||
} esp_local_ctrl_config_t;
|
||||
|
||||
/**
|
||||
* @brief Start local control service
|
||||
*
|
||||
* @param[in] config Pointer to configuration structure
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : Success
|
||||
* - ESP_FAIL : Failure
|
||||
*/
|
||||
esp_err_t esp_local_ctrl_start(const esp_local_ctrl_config_t *config);
|
||||
|
||||
/**
|
||||
* @brief Stop local control service
|
||||
*/
|
||||
esp_err_t esp_local_ctrl_stop(void);
|
||||
|
||||
/**
|
||||
* @brief Add a new property
|
||||
*
|
||||
* This adds a new property and allocates internal resources for it.
|
||||
* The total number of properties that could be added is limited by
|
||||
* configuration option `max_properties`
|
||||
*
|
||||
* @param[in] prop Property description structure
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : Success
|
||||
* - ESP_FAIL : Failure
|
||||
*/
|
||||
esp_err_t esp_local_ctrl_add_property(const esp_local_ctrl_prop_t *prop);
|
||||
|
||||
/**
|
||||
* @brief Remove a property
|
||||
*
|
||||
* This finds a property by name, and releases the internal resources
|
||||
* which are associated with it.
|
||||
*
|
||||
* @param[in] name Name of the property to remove
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : Success
|
||||
* - ESP_ERR_NOT_FOUND : Failure
|
||||
*/
|
||||
esp_err_t esp_local_ctrl_remove_property(const char *name);
|
||||
|
||||
/**
|
||||
* @brief Get property description structure by name
|
||||
*
|
||||
* This API may be used to get a property's context structure
|
||||
* `esp_local_ctrl_prop_t` when its name is known
|
||||
*
|
||||
* @param[in] name Name of the property to find
|
||||
*
|
||||
* @return
|
||||
* - Pointer to property
|
||||
* - NULL if not found
|
||||
*/
|
||||
const esp_local_ctrl_prop_t *esp_local_ctrl_get_property(const char *name);
|
||||
|
||||
/**
|
||||
* @brief Register protocomm handler for a custom endpoint
|
||||
*
|
||||
* This API can be called by the application to register a protocomm handler
|
||||
* for an endpoint after the local control service has started.
|
||||
*
|
||||
* @note In case of BLE transport the names and uuids of all custom
|
||||
* endpoints must be provided beforehand as a part of the `protocomm_ble_config_t`
|
||||
* structure set in `esp_local_ctrl_config_t`, and passed to `esp_local_ctrl_start()`.
|
||||
*
|
||||
* @param[in] ep_name Name of the endpoint
|
||||
* @param[in] handler Endpoint handler function
|
||||
* @param[in] user_ctx User data
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : Success
|
||||
* - ESP_FAIL : Failure
|
||||
*/
|
||||
esp_err_t esp_local_ctrl_set_handler(const char *ep_name,
|
||||
protocomm_req_handler_t handler,
|
||||
void *user_ctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
942
components/esp_local_ctrl/proto-c/esp_local_ctrl.pb-c.c
Normal file
942
components/esp_local_ctrl/proto-c/esp_local_ctrl.pb-c.c
Normal file
|
@ -0,0 +1,942 @@
|
|||
/* Generated by the protocol buffer compiler. DO NOT EDIT! */
|
||||
/* Generated from: esp_local_ctrl.proto */
|
||||
|
||||
/* Do not generate deprecated warnings for self */
|
||||
#ifndef PROTOBUF_C__NO_DEPRECATED
|
||||
#define PROTOBUF_C__NO_DEPRECATED
|
||||
#endif
|
||||
|
||||
#include "esp_local_ctrl.pb-c.h"
|
||||
void cmd_get_property_count__init
|
||||
(CmdGetPropertyCount *message)
|
||||
{
|
||||
static const CmdGetPropertyCount init_value = CMD_GET_PROPERTY_COUNT__INIT;
|
||||
*message = init_value;
|
||||
}
|
||||
size_t cmd_get_property_count__get_packed_size
|
||||
(const CmdGetPropertyCount *message)
|
||||
{
|
||||
assert(message->base.descriptor == &cmd_get_property_count__descriptor);
|
||||
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
|
||||
}
|
||||
size_t cmd_get_property_count__pack
|
||||
(const CmdGetPropertyCount *message,
|
||||
uint8_t *out)
|
||||
{
|
||||
assert(message->base.descriptor == &cmd_get_property_count__descriptor);
|
||||
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
|
||||
}
|
||||
size_t cmd_get_property_count__pack_to_buffer
|
||||
(const CmdGetPropertyCount *message,
|
||||
ProtobufCBuffer *buffer)
|
||||
{
|
||||
assert(message->base.descriptor == &cmd_get_property_count__descriptor);
|
||||
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
|
||||
}
|
||||
CmdGetPropertyCount *
|
||||
cmd_get_property_count__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data)
|
||||
{
|
||||
return (CmdGetPropertyCount *)
|
||||
protobuf_c_message_unpack (&cmd_get_property_count__descriptor,
|
||||
allocator, len, data);
|
||||
}
|
||||
void cmd_get_property_count__free_unpacked
|
||||
(CmdGetPropertyCount *message,
|
||||
ProtobufCAllocator *allocator)
|
||||
{
|
||||
if(!message)
|
||||
return;
|
||||
assert(message->base.descriptor == &cmd_get_property_count__descriptor);
|
||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
||||
}
|
||||
void resp_get_property_count__init
|
||||
(RespGetPropertyCount *message)
|
||||
{
|
||||
static const RespGetPropertyCount init_value = RESP_GET_PROPERTY_COUNT__INIT;
|
||||
*message = init_value;
|
||||
}
|
||||
size_t resp_get_property_count__get_packed_size
|
||||
(const RespGetPropertyCount *message)
|
||||
{
|
||||
assert(message->base.descriptor == &resp_get_property_count__descriptor);
|
||||
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
|
||||
}
|
||||
size_t resp_get_property_count__pack
|
||||
(const RespGetPropertyCount *message,
|
||||
uint8_t *out)
|
||||
{
|
||||
assert(message->base.descriptor == &resp_get_property_count__descriptor);
|
||||
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
|
||||
}
|
||||
size_t resp_get_property_count__pack_to_buffer
|
||||
(const RespGetPropertyCount *message,
|
||||
ProtobufCBuffer *buffer)
|
||||
{
|
||||
assert(message->base.descriptor == &resp_get_property_count__descriptor);
|
||||
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
|
||||
}
|
||||
RespGetPropertyCount *
|
||||
resp_get_property_count__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data)
|
||||
{
|
||||
return (RespGetPropertyCount *)
|
||||
protobuf_c_message_unpack (&resp_get_property_count__descriptor,
|
||||
allocator, len, data);
|
||||
}
|
||||
void resp_get_property_count__free_unpacked
|
||||
(RespGetPropertyCount *message,
|
||||
ProtobufCAllocator *allocator)
|
||||
{
|
||||
if(!message)
|
||||
return;
|
||||
assert(message->base.descriptor == &resp_get_property_count__descriptor);
|
||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
||||
}
|
||||
void property_info__init
|
||||
(PropertyInfo *message)
|
||||
{
|
||||
static const PropertyInfo init_value = PROPERTY_INFO__INIT;
|
||||
*message = init_value;
|
||||
}
|
||||
size_t property_info__get_packed_size
|
||||
(const PropertyInfo *message)
|
||||
{
|
||||
assert(message->base.descriptor == &property_info__descriptor);
|
||||
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
|
||||
}
|
||||
size_t property_info__pack
|
||||
(const PropertyInfo *message,
|
||||
uint8_t *out)
|
||||
{
|
||||
assert(message->base.descriptor == &property_info__descriptor);
|
||||
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
|
||||
}
|
||||
size_t property_info__pack_to_buffer
|
||||
(const PropertyInfo *message,
|
||||
ProtobufCBuffer *buffer)
|
||||
{
|
||||
assert(message->base.descriptor == &property_info__descriptor);
|
||||
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
|
||||
}
|
||||
PropertyInfo *
|
||||
property_info__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data)
|
||||
{
|
||||
return (PropertyInfo *)
|
||||
protobuf_c_message_unpack (&property_info__descriptor,
|
||||
allocator, len, data);
|
||||
}
|
||||
void property_info__free_unpacked
|
||||
(PropertyInfo *message,
|
||||
ProtobufCAllocator *allocator)
|
||||
{
|
||||
if(!message)
|
||||
return;
|
||||
assert(message->base.descriptor == &property_info__descriptor);
|
||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
||||
}
|
||||
void cmd_get_property_values__init
|
||||
(CmdGetPropertyValues *message)
|
||||
{
|
||||
static const CmdGetPropertyValues init_value = CMD_GET_PROPERTY_VALUES__INIT;
|
||||
*message = init_value;
|
||||
}
|
||||
size_t cmd_get_property_values__get_packed_size
|
||||
(const CmdGetPropertyValues *message)
|
||||
{
|
||||
assert(message->base.descriptor == &cmd_get_property_values__descriptor);
|
||||
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
|
||||
}
|
||||
size_t cmd_get_property_values__pack
|
||||
(const CmdGetPropertyValues *message,
|
||||
uint8_t *out)
|
||||
{
|
||||
assert(message->base.descriptor == &cmd_get_property_values__descriptor);
|
||||
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
|
||||
}
|
||||
size_t cmd_get_property_values__pack_to_buffer
|
||||
(const CmdGetPropertyValues *message,
|
||||
ProtobufCBuffer *buffer)
|
||||
{
|
||||
assert(message->base.descriptor == &cmd_get_property_values__descriptor);
|
||||
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
|
||||
}
|
||||
CmdGetPropertyValues *
|
||||
cmd_get_property_values__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data)
|
||||
{
|
||||
return (CmdGetPropertyValues *)
|
||||
protobuf_c_message_unpack (&cmd_get_property_values__descriptor,
|
||||
allocator, len, data);
|
||||
}
|
||||
void cmd_get_property_values__free_unpacked
|
||||
(CmdGetPropertyValues *message,
|
||||
ProtobufCAllocator *allocator)
|
||||
{
|
||||
if(!message)
|
||||
return;
|
||||
assert(message->base.descriptor == &cmd_get_property_values__descriptor);
|
||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
||||
}
|
||||
void resp_get_property_values__init
|
||||
(RespGetPropertyValues *message)
|
||||
{
|
||||
static const RespGetPropertyValues init_value = RESP_GET_PROPERTY_VALUES__INIT;
|
||||
*message = init_value;
|
||||
}
|
||||
size_t resp_get_property_values__get_packed_size
|
||||
(const RespGetPropertyValues *message)
|
||||
{
|
||||
assert(message->base.descriptor == &resp_get_property_values__descriptor);
|
||||
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
|
||||
}
|
||||
size_t resp_get_property_values__pack
|
||||
(const RespGetPropertyValues *message,
|
||||
uint8_t *out)
|
||||
{
|
||||
assert(message->base.descriptor == &resp_get_property_values__descriptor);
|
||||
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
|
||||
}
|
||||
size_t resp_get_property_values__pack_to_buffer
|
||||
(const RespGetPropertyValues *message,
|
||||
ProtobufCBuffer *buffer)
|
||||
{
|
||||
assert(message->base.descriptor == &resp_get_property_values__descriptor);
|
||||
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
|
||||
}
|
||||
RespGetPropertyValues *
|
||||
resp_get_property_values__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data)
|
||||
{
|
||||
return (RespGetPropertyValues *)
|
||||
protobuf_c_message_unpack (&resp_get_property_values__descriptor,
|
||||
allocator, len, data);
|
||||
}
|
||||
void resp_get_property_values__free_unpacked
|
||||
(RespGetPropertyValues *message,
|
||||
ProtobufCAllocator *allocator)
|
||||
{
|
||||
if(!message)
|
||||
return;
|
||||
assert(message->base.descriptor == &resp_get_property_values__descriptor);
|
||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
||||
}
|
||||
void property_value__init
|
||||
(PropertyValue *message)
|
||||
{
|
||||
static const PropertyValue init_value = PROPERTY_VALUE__INIT;
|
||||
*message = init_value;
|
||||
}
|
||||
size_t property_value__get_packed_size
|
||||
(const PropertyValue *message)
|
||||
{
|
||||
assert(message->base.descriptor == &property_value__descriptor);
|
||||
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
|
||||
}
|
||||
size_t property_value__pack
|
||||
(const PropertyValue *message,
|
||||
uint8_t *out)
|
||||
{
|
||||
assert(message->base.descriptor == &property_value__descriptor);
|
||||
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
|
||||
}
|
||||
size_t property_value__pack_to_buffer
|
||||
(const PropertyValue *message,
|
||||
ProtobufCBuffer *buffer)
|
||||
{
|
||||
assert(message->base.descriptor == &property_value__descriptor);
|
||||
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
|
||||
}
|
||||
PropertyValue *
|
||||
property_value__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data)
|
||||
{
|
||||
return (PropertyValue *)
|
||||
protobuf_c_message_unpack (&property_value__descriptor,
|
||||
allocator, len, data);
|
||||
}
|
||||
void property_value__free_unpacked
|
||||
(PropertyValue *message,
|
||||
ProtobufCAllocator *allocator)
|
||||
{
|
||||
if(!message)
|
||||
return;
|
||||
assert(message->base.descriptor == &property_value__descriptor);
|
||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
||||
}
|
||||
void cmd_set_property_values__init
|
||||
(CmdSetPropertyValues *message)
|
||||
{
|
||||
static const CmdSetPropertyValues init_value = CMD_SET_PROPERTY_VALUES__INIT;
|
||||
*message = init_value;
|
||||
}
|
||||
size_t cmd_set_property_values__get_packed_size
|
||||
(const CmdSetPropertyValues *message)
|
||||
{
|
||||
assert(message->base.descriptor == &cmd_set_property_values__descriptor);
|
||||
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
|
||||
}
|
||||
size_t cmd_set_property_values__pack
|
||||
(const CmdSetPropertyValues *message,
|
||||
uint8_t *out)
|
||||
{
|
||||
assert(message->base.descriptor == &cmd_set_property_values__descriptor);
|
||||
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
|
||||
}
|
||||
size_t cmd_set_property_values__pack_to_buffer
|
||||
(const CmdSetPropertyValues *message,
|
||||
ProtobufCBuffer *buffer)
|
||||
{
|
||||
assert(message->base.descriptor == &cmd_set_property_values__descriptor);
|
||||
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
|
||||
}
|
||||
CmdSetPropertyValues *
|
||||
cmd_set_property_values__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data)
|
||||
{
|
||||
return (CmdSetPropertyValues *)
|
||||
protobuf_c_message_unpack (&cmd_set_property_values__descriptor,
|
||||
allocator, len, data);
|
||||
}
|
||||
void cmd_set_property_values__free_unpacked
|
||||
(CmdSetPropertyValues *message,
|
||||
ProtobufCAllocator *allocator)
|
||||
{
|
||||
if(!message)
|
||||
return;
|
||||
assert(message->base.descriptor == &cmd_set_property_values__descriptor);
|
||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
||||
}
|
||||
void resp_set_property_values__init
|
||||
(RespSetPropertyValues *message)
|
||||
{
|
||||
static const RespSetPropertyValues init_value = RESP_SET_PROPERTY_VALUES__INIT;
|
||||
*message = init_value;
|
||||
}
|
||||
size_t resp_set_property_values__get_packed_size
|
||||
(const RespSetPropertyValues *message)
|
||||
{
|
||||
assert(message->base.descriptor == &resp_set_property_values__descriptor);
|
||||
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
|
||||
}
|
||||
size_t resp_set_property_values__pack
|
||||
(const RespSetPropertyValues *message,
|
||||
uint8_t *out)
|
||||
{
|
||||
assert(message->base.descriptor == &resp_set_property_values__descriptor);
|
||||
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
|
||||
}
|
||||
size_t resp_set_property_values__pack_to_buffer
|
||||
(const RespSetPropertyValues *message,
|
||||
ProtobufCBuffer *buffer)
|
||||
{
|
||||
assert(message->base.descriptor == &resp_set_property_values__descriptor);
|
||||
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
|
||||
}
|
||||
RespSetPropertyValues *
|
||||
resp_set_property_values__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data)
|
||||
{
|
||||
return (RespSetPropertyValues *)
|
||||
protobuf_c_message_unpack (&resp_set_property_values__descriptor,
|
||||
allocator, len, data);
|
||||
}
|
||||
void resp_set_property_values__free_unpacked
|
||||
(RespSetPropertyValues *message,
|
||||
ProtobufCAllocator *allocator)
|
||||
{
|
||||
if(!message)
|
||||
return;
|
||||
assert(message->base.descriptor == &resp_set_property_values__descriptor);
|
||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
||||
}
|
||||
void local_ctrl_message__init
|
||||
(LocalCtrlMessage *message)
|
||||
{
|
||||
static const LocalCtrlMessage init_value = LOCAL_CTRL_MESSAGE__INIT;
|
||||
*message = init_value;
|
||||
}
|
||||
size_t local_ctrl_message__get_packed_size
|
||||
(const LocalCtrlMessage *message)
|
||||
{
|
||||
assert(message->base.descriptor == &local_ctrl_message__descriptor);
|
||||
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
|
||||
}
|
||||
size_t local_ctrl_message__pack
|
||||
(const LocalCtrlMessage *message,
|
||||
uint8_t *out)
|
||||
{
|
||||
assert(message->base.descriptor == &local_ctrl_message__descriptor);
|
||||
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
|
||||
}
|
||||
size_t local_ctrl_message__pack_to_buffer
|
||||
(const LocalCtrlMessage *message,
|
||||
ProtobufCBuffer *buffer)
|
||||
{
|
||||
assert(message->base.descriptor == &local_ctrl_message__descriptor);
|
||||
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
|
||||
}
|
||||
LocalCtrlMessage *
|
||||
local_ctrl_message__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data)
|
||||
{
|
||||
return (LocalCtrlMessage *)
|
||||
protobuf_c_message_unpack (&local_ctrl_message__descriptor,
|
||||
allocator, len, data);
|
||||
}
|
||||
void local_ctrl_message__free_unpacked
|
||||
(LocalCtrlMessage *message,
|
||||
ProtobufCAllocator *allocator)
|
||||
{
|
||||
if(!message)
|
||||
return;
|
||||
assert(message->base.descriptor == &local_ctrl_message__descriptor);
|
||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
||||
}
|
||||
#define cmd_get_property_count__field_descriptors NULL
|
||||
#define cmd_get_property_count__field_indices_by_name NULL
|
||||
#define cmd_get_property_count__number_ranges NULL
|
||||
const ProtobufCMessageDescriptor cmd_get_property_count__descriptor =
|
||||
{
|
||||
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
|
||||
"CmdGetPropertyCount",
|
||||
"CmdGetPropertyCount",
|
||||
"CmdGetPropertyCount",
|
||||
"",
|
||||
sizeof(CmdGetPropertyCount),
|
||||
0,
|
||||
cmd_get_property_count__field_descriptors,
|
||||
cmd_get_property_count__field_indices_by_name,
|
||||
0, cmd_get_property_count__number_ranges,
|
||||
(ProtobufCMessageInit) cmd_get_property_count__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
static const ProtobufCFieldDescriptor resp_get_property_count__field_descriptors[2] =
|
||||
{
|
||||
{
|
||||
"status",
|
||||
1,
|
||||
PROTOBUF_C_LABEL_NONE,
|
||||
PROTOBUF_C_TYPE_ENUM,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(RespGetPropertyCount, status),
|
||||
&status__descriptor,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"count",
|
||||
2,
|
||||
PROTOBUF_C_LABEL_NONE,
|
||||
PROTOBUF_C_TYPE_UINT32,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(RespGetPropertyCount, count),
|
||||
NULL,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
};
|
||||
static const unsigned resp_get_property_count__field_indices_by_name[] = {
|
||||
1, /* field[1] = count */
|
||||
0, /* field[0] = status */
|
||||
};
|
||||
static const ProtobufCIntRange resp_get_property_count__number_ranges[1 + 1] =
|
||||
{
|
||||
{ 1, 0 },
|
||||
{ 0, 2 }
|
||||
};
|
||||
const ProtobufCMessageDescriptor resp_get_property_count__descriptor =
|
||||
{
|
||||
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
|
||||
"RespGetPropertyCount",
|
||||
"RespGetPropertyCount",
|
||||
"RespGetPropertyCount",
|
||||
"",
|
||||
sizeof(RespGetPropertyCount),
|
||||
2,
|
||||
resp_get_property_count__field_descriptors,
|
||||
resp_get_property_count__field_indices_by_name,
|
||||
1, resp_get_property_count__number_ranges,
|
||||
(ProtobufCMessageInit) resp_get_property_count__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
static const ProtobufCFieldDescriptor property_info__field_descriptors[5] =
|
||||
{
|
||||
{
|
||||
"status",
|
||||
1,
|
||||
PROTOBUF_C_LABEL_NONE,
|
||||
PROTOBUF_C_TYPE_ENUM,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(PropertyInfo, status),
|
||||
&status__descriptor,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"name",
|
||||
2,
|
||||
PROTOBUF_C_LABEL_NONE,
|
||||
PROTOBUF_C_TYPE_STRING,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(PropertyInfo, name),
|
||||
NULL,
|
||||
&protobuf_c_empty_string,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"type",
|
||||
3,
|
||||
PROTOBUF_C_LABEL_NONE,
|
||||
PROTOBUF_C_TYPE_UINT32,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(PropertyInfo, type),
|
||||
NULL,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"flags",
|
||||
4,
|
||||
PROTOBUF_C_LABEL_NONE,
|
||||
PROTOBUF_C_TYPE_UINT32,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(PropertyInfo, flags),
|
||||
NULL,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"value",
|
||||
5,
|
||||
PROTOBUF_C_LABEL_NONE,
|
||||
PROTOBUF_C_TYPE_BYTES,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(PropertyInfo, value),
|
||||
NULL,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
};
|
||||
static const unsigned property_info__field_indices_by_name[] = {
|
||||
3, /* field[3] = flags */
|
||||
1, /* field[1] = name */
|
||||
0, /* field[0] = status */
|
||||
2, /* field[2] = type */
|
||||
4, /* field[4] = value */
|
||||
};
|
||||
static const ProtobufCIntRange property_info__number_ranges[1 + 1] =
|
||||
{
|
||||
{ 1, 0 },
|
||||
{ 0, 5 }
|
||||
};
|
||||
const ProtobufCMessageDescriptor property_info__descriptor =
|
||||
{
|
||||
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
|
||||
"PropertyInfo",
|
||||
"PropertyInfo",
|
||||
"PropertyInfo",
|
||||
"",
|
||||
sizeof(PropertyInfo),
|
||||
5,
|
||||
property_info__field_descriptors,
|
||||
property_info__field_indices_by_name,
|
||||
1, property_info__number_ranges,
|
||||
(ProtobufCMessageInit) property_info__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
static const ProtobufCFieldDescriptor cmd_get_property_values__field_descriptors[1] =
|
||||
{
|
||||
{
|
||||
"indices",
|
||||
1,
|
||||
PROTOBUF_C_LABEL_REPEATED,
|
||||
PROTOBUF_C_TYPE_UINT32,
|
||||
offsetof(CmdGetPropertyValues, n_indices),
|
||||
offsetof(CmdGetPropertyValues, indices),
|
||||
NULL,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
};
|
||||
static const unsigned cmd_get_property_values__field_indices_by_name[] = {
|
||||
0, /* field[0] = indices */
|
||||
};
|
||||
static const ProtobufCIntRange cmd_get_property_values__number_ranges[1 + 1] =
|
||||
{
|
||||
{ 1, 0 },
|
||||
{ 0, 1 }
|
||||
};
|
||||
const ProtobufCMessageDescriptor cmd_get_property_values__descriptor =
|
||||
{
|
||||
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
|
||||
"CmdGetPropertyValues",
|
||||
"CmdGetPropertyValues",
|
||||
"CmdGetPropertyValues",
|
||||
"",
|
||||
sizeof(CmdGetPropertyValues),
|
||||
1,
|
||||
cmd_get_property_values__field_descriptors,
|
||||
cmd_get_property_values__field_indices_by_name,
|
||||
1, cmd_get_property_values__number_ranges,
|
||||
(ProtobufCMessageInit) cmd_get_property_values__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
static const ProtobufCFieldDescriptor resp_get_property_values__field_descriptors[2] =
|
||||
{
|
||||
{
|
||||
"status",
|
||||
1,
|
||||
PROTOBUF_C_LABEL_NONE,
|
||||
PROTOBUF_C_TYPE_ENUM,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(RespGetPropertyValues, status),
|
||||
&status__descriptor,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"props",
|
||||
2,
|
||||
PROTOBUF_C_LABEL_REPEATED,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
offsetof(RespGetPropertyValues, n_props),
|
||||
offsetof(RespGetPropertyValues, props),
|
||||
&property_info__descriptor,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
};
|
||||
static const unsigned resp_get_property_values__field_indices_by_name[] = {
|
||||
1, /* field[1] = props */
|
||||
0, /* field[0] = status */
|
||||
};
|
||||
static const ProtobufCIntRange resp_get_property_values__number_ranges[1 + 1] =
|
||||
{
|
||||
{ 1, 0 },
|
||||
{ 0, 2 }
|
||||
};
|
||||
const ProtobufCMessageDescriptor resp_get_property_values__descriptor =
|
||||
{
|
||||
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
|
||||
"RespGetPropertyValues",
|
||||
"RespGetPropertyValues",
|
||||
"RespGetPropertyValues",
|
||||
"",
|
||||
sizeof(RespGetPropertyValues),
|
||||
2,
|
||||
resp_get_property_values__field_descriptors,
|
||||
resp_get_property_values__field_indices_by_name,
|
||||
1, resp_get_property_values__number_ranges,
|
||||
(ProtobufCMessageInit) resp_get_property_values__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
static const ProtobufCFieldDescriptor property_value__field_descriptors[2] =
|
||||
{
|
||||
{
|
||||
"index",
|
||||
1,
|
||||
PROTOBUF_C_LABEL_NONE,
|
||||
PROTOBUF_C_TYPE_UINT32,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(PropertyValue, index),
|
||||
NULL,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"value",
|
||||
2,
|
||||
PROTOBUF_C_LABEL_NONE,
|
||||
PROTOBUF_C_TYPE_BYTES,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(PropertyValue, value),
|
||||
NULL,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
};
|
||||
static const unsigned property_value__field_indices_by_name[] = {
|
||||
0, /* field[0] = index */
|
||||
1, /* field[1] = value */
|
||||
};
|
||||
static const ProtobufCIntRange property_value__number_ranges[1 + 1] =
|
||||
{
|
||||
{ 1, 0 },
|
||||
{ 0, 2 }
|
||||
};
|
||||
const ProtobufCMessageDescriptor property_value__descriptor =
|
||||
{
|
||||
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
|
||||
"PropertyValue",
|
||||
"PropertyValue",
|
||||
"PropertyValue",
|
||||
"",
|
||||
sizeof(PropertyValue),
|
||||
2,
|
||||
property_value__field_descriptors,
|
||||
property_value__field_indices_by_name,
|
||||
1, property_value__number_ranges,
|
||||
(ProtobufCMessageInit) property_value__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
static const ProtobufCFieldDescriptor cmd_set_property_values__field_descriptors[1] =
|
||||
{
|
||||
{
|
||||
"props",
|
||||
1,
|
||||
PROTOBUF_C_LABEL_REPEATED,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
offsetof(CmdSetPropertyValues, n_props),
|
||||
offsetof(CmdSetPropertyValues, props),
|
||||
&property_value__descriptor,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
};
|
||||
static const unsigned cmd_set_property_values__field_indices_by_name[] = {
|
||||
0, /* field[0] = props */
|
||||
};
|
||||
static const ProtobufCIntRange cmd_set_property_values__number_ranges[1 + 1] =
|
||||
{
|
||||
{ 1, 0 },
|
||||
{ 0, 1 }
|
||||
};
|
||||
const ProtobufCMessageDescriptor cmd_set_property_values__descriptor =
|
||||
{
|
||||
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
|
||||
"CmdSetPropertyValues",
|
||||
"CmdSetPropertyValues",
|
||||
"CmdSetPropertyValues",
|
||||
"",
|
||||
sizeof(CmdSetPropertyValues),
|
||||
1,
|
||||
cmd_set_property_values__field_descriptors,
|
||||
cmd_set_property_values__field_indices_by_name,
|
||||
1, cmd_set_property_values__number_ranges,
|
||||
(ProtobufCMessageInit) cmd_set_property_values__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
static const ProtobufCFieldDescriptor resp_set_property_values__field_descriptors[1] =
|
||||
{
|
||||
{
|
||||
"status",
|
||||
1,
|
||||
PROTOBUF_C_LABEL_NONE,
|
||||
PROTOBUF_C_TYPE_ENUM,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(RespSetPropertyValues, status),
|
||||
&status__descriptor,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
};
|
||||
static const unsigned resp_set_property_values__field_indices_by_name[] = {
|
||||
0, /* field[0] = status */
|
||||
};
|
||||
static const ProtobufCIntRange resp_set_property_values__number_ranges[1 + 1] =
|
||||
{
|
||||
{ 1, 0 },
|
||||
{ 0, 1 }
|
||||
};
|
||||
const ProtobufCMessageDescriptor resp_set_property_values__descriptor =
|
||||
{
|
||||
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
|
||||
"RespSetPropertyValues",
|
||||
"RespSetPropertyValues",
|
||||
"RespSetPropertyValues",
|
||||
"",
|
||||
sizeof(RespSetPropertyValues),
|
||||
1,
|
||||
resp_set_property_values__field_descriptors,
|
||||
resp_set_property_values__field_indices_by_name,
|
||||
1, resp_set_property_values__number_ranges,
|
||||
(ProtobufCMessageInit) resp_set_property_values__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
static const ProtobufCFieldDescriptor local_ctrl_message__field_descriptors[7] =
|
||||
{
|
||||
{
|
||||
"msg",
|
||||
1,
|
||||
PROTOBUF_C_LABEL_NONE,
|
||||
PROTOBUF_C_TYPE_ENUM,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(LocalCtrlMessage, msg),
|
||||
&local_ctrl_msg_type__descriptor,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"cmd_get_prop_count",
|
||||
10,
|
||||
PROTOBUF_C_LABEL_NONE,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
offsetof(LocalCtrlMessage, payload_case),
|
||||
offsetof(LocalCtrlMessage, cmd_get_prop_count),
|
||||
&cmd_get_property_count__descriptor,
|
||||
NULL,
|
||||
0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"resp_get_prop_count",
|
||||
11,
|
||||
PROTOBUF_C_LABEL_NONE,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
offsetof(LocalCtrlMessage, payload_case),
|
||||
offsetof(LocalCtrlMessage, resp_get_prop_count),
|
||||
&resp_get_property_count__descriptor,
|
||||
NULL,
|
||||
0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"cmd_get_prop_vals",
|
||||
12,
|
||||
PROTOBUF_C_LABEL_NONE,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
offsetof(LocalCtrlMessage, payload_case),
|
||||
offsetof(LocalCtrlMessage, cmd_get_prop_vals),
|
||||
&cmd_get_property_values__descriptor,
|
||||
NULL,
|
||||
0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"resp_get_prop_vals",
|
||||
13,
|
||||
PROTOBUF_C_LABEL_NONE,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
offsetof(LocalCtrlMessage, payload_case),
|
||||
offsetof(LocalCtrlMessage, resp_get_prop_vals),
|
||||
&resp_get_property_values__descriptor,
|
||||
NULL,
|
||||
0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"cmd_set_prop_vals",
|
||||
14,
|
||||
PROTOBUF_C_LABEL_NONE,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
offsetof(LocalCtrlMessage, payload_case),
|
||||
offsetof(LocalCtrlMessage, cmd_set_prop_vals),
|
||||
&cmd_set_property_values__descriptor,
|
||||
NULL,
|
||||
0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"resp_set_prop_vals",
|
||||
15,
|
||||
PROTOBUF_C_LABEL_NONE,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
offsetof(LocalCtrlMessage, payload_case),
|
||||
offsetof(LocalCtrlMessage, resp_set_prop_vals),
|
||||
&resp_set_property_values__descriptor,
|
||||
NULL,
|
||||
0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
};
|
||||
static const unsigned local_ctrl_message__field_indices_by_name[] = {
|
||||
1, /* field[1] = cmd_get_prop_count */
|
||||
3, /* field[3] = cmd_get_prop_vals */
|
||||
5, /* field[5] = cmd_set_prop_vals */
|
||||
0, /* field[0] = msg */
|
||||
2, /* field[2] = resp_get_prop_count */
|
||||
4, /* field[4] = resp_get_prop_vals */
|
||||
6, /* field[6] = resp_set_prop_vals */
|
||||
};
|
||||
static const ProtobufCIntRange local_ctrl_message__number_ranges[2 + 1] =
|
||||
{
|
||||
{ 1, 0 },
|
||||
{ 10, 1 },
|
||||
{ 0, 7 }
|
||||
};
|
||||
const ProtobufCMessageDescriptor local_ctrl_message__descriptor =
|
||||
{
|
||||
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
|
||||
"LocalCtrlMessage",
|
||||
"LocalCtrlMessage",
|
||||
"LocalCtrlMessage",
|
||||
"",
|
||||
sizeof(LocalCtrlMessage),
|
||||
7,
|
||||
local_ctrl_message__field_descriptors,
|
||||
local_ctrl_message__field_indices_by_name,
|
||||
2, local_ctrl_message__number_ranges,
|
||||
(ProtobufCMessageInit) local_ctrl_message__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
static const ProtobufCEnumValue local_ctrl_msg_type__enum_values_by_number[6] =
|
||||
{
|
||||
{ "TypeCmdGetPropertyCount", "LOCAL_CTRL_MSG_TYPE__TypeCmdGetPropertyCount", 0 },
|
||||
{ "TypeRespGetPropertyCount", "LOCAL_CTRL_MSG_TYPE__TypeRespGetPropertyCount", 1 },
|
||||
{ "TypeCmdGetPropertyValues", "LOCAL_CTRL_MSG_TYPE__TypeCmdGetPropertyValues", 4 },
|
||||
{ "TypeRespGetPropertyValues", "LOCAL_CTRL_MSG_TYPE__TypeRespGetPropertyValues", 5 },
|
||||
{ "TypeCmdSetPropertyValues", "LOCAL_CTRL_MSG_TYPE__TypeCmdSetPropertyValues", 6 },
|
||||
{ "TypeRespSetPropertyValues", "LOCAL_CTRL_MSG_TYPE__TypeRespSetPropertyValues", 7 },
|
||||
};
|
||||
static const ProtobufCIntRange local_ctrl_msg_type__value_ranges[] = {
|
||||
{0, 0},{4, 2},{0, 6}
|
||||
};
|
||||
static const ProtobufCEnumValueIndex local_ctrl_msg_type__enum_values_by_name[6] =
|
||||
{
|
||||
{ "TypeCmdGetPropertyCount", 0 },
|
||||
{ "TypeCmdGetPropertyValues", 2 },
|
||||
{ "TypeCmdSetPropertyValues", 4 },
|
||||
{ "TypeRespGetPropertyCount", 1 },
|
||||
{ "TypeRespGetPropertyValues", 3 },
|
||||
{ "TypeRespSetPropertyValues", 5 },
|
||||
};
|
||||
const ProtobufCEnumDescriptor local_ctrl_msg_type__descriptor =
|
||||
{
|
||||
PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC,
|
||||
"LocalCtrlMsgType",
|
||||
"LocalCtrlMsgType",
|
||||
"LocalCtrlMsgType",
|
||||
"",
|
||||
6,
|
||||
local_ctrl_msg_type__enum_values_by_number,
|
||||
6,
|
||||
local_ctrl_msg_type__enum_values_by_name,
|
||||
2,
|
||||
local_ctrl_msg_type__value_ranges,
|
||||
NULL,NULL,NULL,NULL /* reserved[1234] */
|
||||
};
|
383
components/esp_local_ctrl/proto-c/esp_local_ctrl.pb-c.h
Normal file
383
components/esp_local_ctrl/proto-c/esp_local_ctrl.pb-c.h
Normal file
|
@ -0,0 +1,383 @@
|
|||
/* Generated by the protocol buffer compiler. DO NOT EDIT! */
|
||||
/* Generated from: esp_local_ctrl.proto */
|
||||
|
||||
#ifndef PROTOBUF_C_esp_5flocal_5fctrl_2eproto__INCLUDED
|
||||
#define PROTOBUF_C_esp_5flocal_5fctrl_2eproto__INCLUDED
|
||||
|
||||
#include <protobuf-c/protobuf-c.h>
|
||||
|
||||
PROTOBUF_C__BEGIN_DECLS
|
||||
|
||||
#if PROTOBUF_C_VERSION_NUMBER < 1003000
|
||||
# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers.
|
||||
#elif 1003001 < PROTOBUF_C_MIN_COMPILER_VERSION
|
||||
# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c.
|
||||
#endif
|
||||
|
||||
#include "constants.pb-c.h"
|
||||
|
||||
typedef struct _CmdGetPropertyCount CmdGetPropertyCount;
|
||||
typedef struct _RespGetPropertyCount RespGetPropertyCount;
|
||||
typedef struct _PropertyInfo PropertyInfo;
|
||||
typedef struct _CmdGetPropertyValues CmdGetPropertyValues;
|
||||
typedef struct _RespGetPropertyValues RespGetPropertyValues;
|
||||
typedef struct _PropertyValue PropertyValue;
|
||||
typedef struct _CmdSetPropertyValues CmdSetPropertyValues;
|
||||
typedef struct _RespSetPropertyValues RespSetPropertyValues;
|
||||
typedef struct _LocalCtrlMessage LocalCtrlMessage;
|
||||
|
||||
|
||||
/* --- enums --- */
|
||||
|
||||
typedef enum _LocalCtrlMsgType {
|
||||
LOCAL_CTRL_MSG_TYPE__TypeCmdGetPropertyCount = 0,
|
||||
LOCAL_CTRL_MSG_TYPE__TypeRespGetPropertyCount = 1,
|
||||
LOCAL_CTRL_MSG_TYPE__TypeCmdGetPropertyValues = 4,
|
||||
LOCAL_CTRL_MSG_TYPE__TypeRespGetPropertyValues = 5,
|
||||
LOCAL_CTRL_MSG_TYPE__TypeCmdSetPropertyValues = 6,
|
||||
LOCAL_CTRL_MSG_TYPE__TypeRespSetPropertyValues = 7
|
||||
PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(LOCAL_CTRL_MSG_TYPE)
|
||||
} LocalCtrlMsgType;
|
||||
|
||||
/* --- messages --- */
|
||||
|
||||
struct _CmdGetPropertyCount
|
||||
{
|
||||
ProtobufCMessage base;
|
||||
};
|
||||
#define CMD_GET_PROPERTY_COUNT__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&cmd_get_property_count__descriptor) \
|
||||
}
|
||||
|
||||
|
||||
struct _RespGetPropertyCount
|
||||
{
|
||||
ProtobufCMessage base;
|
||||
Status status;
|
||||
uint32_t count;
|
||||
};
|
||||
#define RESP_GET_PROPERTY_COUNT__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&resp_get_property_count__descriptor) \
|
||||
, STATUS__Success, 0 }
|
||||
|
||||
|
||||
struct _PropertyInfo
|
||||
{
|
||||
ProtobufCMessage base;
|
||||
Status status;
|
||||
char *name;
|
||||
uint32_t type;
|
||||
uint32_t flags;
|
||||
ProtobufCBinaryData value;
|
||||
};
|
||||
#define PROPERTY_INFO__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&property_info__descriptor) \
|
||||
, STATUS__Success, (char *)protobuf_c_empty_string, 0, 0, {0,NULL} }
|
||||
|
||||
|
||||
struct _CmdGetPropertyValues
|
||||
{
|
||||
ProtobufCMessage base;
|
||||
size_t n_indices;
|
||||
uint32_t *indices;
|
||||
};
|
||||
#define CMD_GET_PROPERTY_VALUES__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&cmd_get_property_values__descriptor) \
|
||||
, 0,NULL }
|
||||
|
||||
|
||||
struct _RespGetPropertyValues
|
||||
{
|
||||
ProtobufCMessage base;
|
||||
Status status;
|
||||
size_t n_props;
|
||||
PropertyInfo **props;
|
||||
};
|
||||
#define RESP_GET_PROPERTY_VALUES__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&resp_get_property_values__descriptor) \
|
||||
, STATUS__Success, 0,NULL }
|
||||
|
||||
|
||||
struct _PropertyValue
|
||||
{
|
||||
ProtobufCMessage base;
|
||||
uint32_t index;
|
||||
ProtobufCBinaryData value;
|
||||
};
|
||||
#define PROPERTY_VALUE__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&property_value__descriptor) \
|
||||
, 0, {0,NULL} }
|
||||
|
||||
|
||||
struct _CmdSetPropertyValues
|
||||
{
|
||||
ProtobufCMessage base;
|
||||
size_t n_props;
|
||||
PropertyValue **props;
|
||||
};
|
||||
#define CMD_SET_PROPERTY_VALUES__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&cmd_set_property_values__descriptor) \
|
||||
, 0,NULL }
|
||||
|
||||
|
||||
struct _RespSetPropertyValues
|
||||
{
|
||||
ProtobufCMessage base;
|
||||
Status status;
|
||||
};
|
||||
#define RESP_SET_PROPERTY_VALUES__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&resp_set_property_values__descriptor) \
|
||||
, STATUS__Success }
|
||||
|
||||
|
||||
typedef enum {
|
||||
LOCAL_CTRL_MESSAGE__PAYLOAD__NOT_SET = 0,
|
||||
LOCAL_CTRL_MESSAGE__PAYLOAD_CMD_GET_PROP_COUNT = 10,
|
||||
LOCAL_CTRL_MESSAGE__PAYLOAD_RESP_GET_PROP_COUNT = 11,
|
||||
LOCAL_CTRL_MESSAGE__PAYLOAD_CMD_GET_PROP_VALS = 12,
|
||||
LOCAL_CTRL_MESSAGE__PAYLOAD_RESP_GET_PROP_VALS = 13,
|
||||
LOCAL_CTRL_MESSAGE__PAYLOAD_CMD_SET_PROP_VALS = 14,
|
||||
LOCAL_CTRL_MESSAGE__PAYLOAD_RESP_SET_PROP_VALS = 15
|
||||
PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(LOCAL_CTRL_MESSAGE__PAYLOAD)
|
||||
} LocalCtrlMessage__PayloadCase;
|
||||
|
||||
struct _LocalCtrlMessage
|
||||
{
|
||||
ProtobufCMessage base;
|
||||
LocalCtrlMsgType msg;
|
||||
LocalCtrlMessage__PayloadCase payload_case;
|
||||
union {
|
||||
CmdGetPropertyCount *cmd_get_prop_count;
|
||||
RespGetPropertyCount *resp_get_prop_count;
|
||||
CmdGetPropertyValues *cmd_get_prop_vals;
|
||||
RespGetPropertyValues *resp_get_prop_vals;
|
||||
CmdSetPropertyValues *cmd_set_prop_vals;
|
||||
RespSetPropertyValues *resp_set_prop_vals;
|
||||
};
|
||||
};
|
||||
#define LOCAL_CTRL_MESSAGE__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&local_ctrl_message__descriptor) \
|
||||
, LOCAL_CTRL_MSG_TYPE__TypeCmdGetPropertyCount, LOCAL_CTRL_MESSAGE__PAYLOAD__NOT_SET, {0} }
|
||||
|
||||
|
||||
/* CmdGetPropertyCount methods */
|
||||
void cmd_get_property_count__init
|
||||
(CmdGetPropertyCount *message);
|
||||
size_t cmd_get_property_count__get_packed_size
|
||||
(const CmdGetPropertyCount *message);
|
||||
size_t cmd_get_property_count__pack
|
||||
(const CmdGetPropertyCount *message,
|
||||
uint8_t *out);
|
||||
size_t cmd_get_property_count__pack_to_buffer
|
||||
(const CmdGetPropertyCount *message,
|
||||
ProtobufCBuffer *buffer);
|
||||
CmdGetPropertyCount *
|
||||
cmd_get_property_count__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data);
|
||||
void cmd_get_property_count__free_unpacked
|
||||
(CmdGetPropertyCount *message,
|
||||
ProtobufCAllocator *allocator);
|
||||
/* RespGetPropertyCount methods */
|
||||
void resp_get_property_count__init
|
||||
(RespGetPropertyCount *message);
|
||||
size_t resp_get_property_count__get_packed_size
|
||||
(const RespGetPropertyCount *message);
|
||||
size_t resp_get_property_count__pack
|
||||
(const RespGetPropertyCount *message,
|
||||
uint8_t *out);
|
||||
size_t resp_get_property_count__pack_to_buffer
|
||||
(const RespGetPropertyCount *message,
|
||||
ProtobufCBuffer *buffer);
|
||||
RespGetPropertyCount *
|
||||
resp_get_property_count__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data);
|
||||
void resp_get_property_count__free_unpacked
|
||||
(RespGetPropertyCount *message,
|
||||
ProtobufCAllocator *allocator);
|
||||
/* PropertyInfo methods */
|
||||
void property_info__init
|
||||
(PropertyInfo *message);
|
||||
size_t property_info__get_packed_size
|
||||
(const PropertyInfo *message);
|
||||
size_t property_info__pack
|
||||
(const PropertyInfo *message,
|
||||
uint8_t *out);
|
||||
size_t property_info__pack_to_buffer
|
||||
(const PropertyInfo *message,
|
||||
ProtobufCBuffer *buffer);
|
||||
PropertyInfo *
|
||||
property_info__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data);
|
||||
void property_info__free_unpacked
|
||||
(PropertyInfo *message,
|
||||
ProtobufCAllocator *allocator);
|
||||
/* CmdGetPropertyValues methods */
|
||||
void cmd_get_property_values__init
|
||||
(CmdGetPropertyValues *message);
|
||||
size_t cmd_get_property_values__get_packed_size
|
||||
(const CmdGetPropertyValues *message);
|
||||
size_t cmd_get_property_values__pack
|
||||
(const CmdGetPropertyValues *message,
|
||||
uint8_t *out);
|
||||
size_t cmd_get_property_values__pack_to_buffer
|
||||
(const CmdGetPropertyValues *message,
|
||||
ProtobufCBuffer *buffer);
|
||||
CmdGetPropertyValues *
|
||||
cmd_get_property_values__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data);
|
||||
void cmd_get_property_values__free_unpacked
|
||||
(CmdGetPropertyValues *message,
|
||||
ProtobufCAllocator *allocator);
|
||||
/* RespGetPropertyValues methods */
|
||||
void resp_get_property_values__init
|
||||
(RespGetPropertyValues *message);
|
||||
size_t resp_get_property_values__get_packed_size
|
||||
(const RespGetPropertyValues *message);
|
||||
size_t resp_get_property_values__pack
|
||||
(const RespGetPropertyValues *message,
|
||||
uint8_t *out);
|
||||
size_t resp_get_property_values__pack_to_buffer
|
||||
(const RespGetPropertyValues *message,
|
||||
ProtobufCBuffer *buffer);
|
||||
RespGetPropertyValues *
|
||||
resp_get_property_values__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data);
|
||||
void resp_get_property_values__free_unpacked
|
||||
(RespGetPropertyValues *message,
|
||||
ProtobufCAllocator *allocator);
|
||||
/* PropertyValue methods */
|
||||
void property_value__init
|
||||
(PropertyValue *message);
|
||||
size_t property_value__get_packed_size
|
||||
(const PropertyValue *message);
|
||||
size_t property_value__pack
|
||||
(const PropertyValue *message,
|
||||
uint8_t *out);
|
||||
size_t property_value__pack_to_buffer
|
||||
(const PropertyValue *message,
|
||||
ProtobufCBuffer *buffer);
|
||||
PropertyValue *
|
||||
property_value__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data);
|
||||
void property_value__free_unpacked
|
||||
(PropertyValue *message,
|
||||
ProtobufCAllocator *allocator);
|
||||
/* CmdSetPropertyValues methods */
|
||||
void cmd_set_property_values__init
|
||||
(CmdSetPropertyValues *message);
|
||||
size_t cmd_set_property_values__get_packed_size
|
||||
(const CmdSetPropertyValues *message);
|
||||
size_t cmd_set_property_values__pack
|
||||
(const CmdSetPropertyValues *message,
|
||||
uint8_t *out);
|
||||
size_t cmd_set_property_values__pack_to_buffer
|
||||
(const CmdSetPropertyValues *message,
|
||||
ProtobufCBuffer *buffer);
|
||||
CmdSetPropertyValues *
|
||||
cmd_set_property_values__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data);
|
||||
void cmd_set_property_values__free_unpacked
|
||||
(CmdSetPropertyValues *message,
|
||||
ProtobufCAllocator *allocator);
|
||||
/* RespSetPropertyValues methods */
|
||||
void resp_set_property_values__init
|
||||
(RespSetPropertyValues *message);
|
||||
size_t resp_set_property_values__get_packed_size
|
||||
(const RespSetPropertyValues *message);
|
||||
size_t resp_set_property_values__pack
|
||||
(const RespSetPropertyValues *message,
|
||||
uint8_t *out);
|
||||
size_t resp_set_property_values__pack_to_buffer
|
||||
(const RespSetPropertyValues *message,
|
||||
ProtobufCBuffer *buffer);
|
||||
RespSetPropertyValues *
|
||||
resp_set_property_values__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data);
|
||||
void resp_set_property_values__free_unpacked
|
||||
(RespSetPropertyValues *message,
|
||||
ProtobufCAllocator *allocator);
|
||||
/* LocalCtrlMessage methods */
|
||||
void local_ctrl_message__init
|
||||
(LocalCtrlMessage *message);
|
||||
size_t local_ctrl_message__get_packed_size
|
||||
(const LocalCtrlMessage *message);
|
||||
size_t local_ctrl_message__pack
|
||||
(const LocalCtrlMessage *message,
|
||||
uint8_t *out);
|
||||
size_t local_ctrl_message__pack_to_buffer
|
||||
(const LocalCtrlMessage *message,
|
||||
ProtobufCBuffer *buffer);
|
||||
LocalCtrlMessage *
|
||||
local_ctrl_message__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data);
|
||||
void local_ctrl_message__free_unpacked
|
||||
(LocalCtrlMessage *message,
|
||||
ProtobufCAllocator *allocator);
|
||||
/* --- per-message closures --- */
|
||||
|
||||
typedef void (*CmdGetPropertyCount_Closure)
|
||||
(const CmdGetPropertyCount *message,
|
||||
void *closure_data);
|
||||
typedef void (*RespGetPropertyCount_Closure)
|
||||
(const RespGetPropertyCount *message,
|
||||
void *closure_data);
|
||||
typedef void (*PropertyInfo_Closure)
|
||||
(const PropertyInfo *message,
|
||||
void *closure_data);
|
||||
typedef void (*CmdGetPropertyValues_Closure)
|
||||
(const CmdGetPropertyValues *message,
|
||||
void *closure_data);
|
||||
typedef void (*RespGetPropertyValues_Closure)
|
||||
(const RespGetPropertyValues *message,
|
||||
void *closure_data);
|
||||
typedef void (*PropertyValue_Closure)
|
||||
(const PropertyValue *message,
|
||||
void *closure_data);
|
||||
typedef void (*CmdSetPropertyValues_Closure)
|
||||
(const CmdSetPropertyValues *message,
|
||||
void *closure_data);
|
||||
typedef void (*RespSetPropertyValues_Closure)
|
||||
(const RespSetPropertyValues *message,
|
||||
void *closure_data);
|
||||
typedef void (*LocalCtrlMessage_Closure)
|
||||
(const LocalCtrlMessage *message,
|
||||
void *closure_data);
|
||||
|
||||
/* --- services --- */
|
||||
|
||||
|
||||
/* --- descriptors --- */
|
||||
|
||||
extern const ProtobufCEnumDescriptor local_ctrl_msg_type__descriptor;
|
||||
extern const ProtobufCMessageDescriptor cmd_get_property_count__descriptor;
|
||||
extern const ProtobufCMessageDescriptor resp_get_property_count__descriptor;
|
||||
extern const ProtobufCMessageDescriptor property_info__descriptor;
|
||||
extern const ProtobufCMessageDescriptor cmd_get_property_values__descriptor;
|
||||
extern const ProtobufCMessageDescriptor resp_get_property_values__descriptor;
|
||||
extern const ProtobufCMessageDescriptor property_value__descriptor;
|
||||
extern const ProtobufCMessageDescriptor cmd_set_property_values__descriptor;
|
||||
extern const ProtobufCMessageDescriptor resp_set_property_values__descriptor;
|
||||
extern const ProtobufCMessageDescriptor local_ctrl_message__descriptor;
|
||||
|
||||
PROTOBUF_C__END_DECLS
|
||||
|
||||
|
||||
#endif /* PROTOBUF_C_esp_5flocal_5fctrl_2eproto__INCLUDED */
|
30
components/esp_local_ctrl/proto/CMakeLists.txt
Normal file
30
components/esp_local_ctrl/proto/CMakeLists.txt
Normal file
|
@ -0,0 +1,30 @@
|
|||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
set(PROTO_COMPILER "protoc")
|
||||
set(PROTO_C_COMPILER "protoc-c")
|
||||
set(C_OUT_PATH "${CMAKE_CURRENT_LIST_DIR}/../proto-c")
|
||||
set(PY_OUT_PATH "${CMAKE_CURRENT_LIST_DIR}/../python")
|
||||
set(PROTOCOMM_INCL_PATH "${CMAKE_CURRENT_LIST_DIR}/../../protocomm/proto")
|
||||
|
||||
file(GLOB PROTO_FILES
|
||||
LIST_DIRECTORIES false
|
||||
RELATIVE ${CMAKE_CURRENT_LIST_DIR}
|
||||
"*.proto")
|
||||
|
||||
add_custom_target(c_proto
|
||||
COMMAND ${PROTO_C_COMPILER} --c_out=${C_OUT_PATH} -I . -I ${PROTOCOMM_INCL_PATH} ${PROTO_FILES}
|
||||
VERBATIM
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
|
||||
)
|
||||
|
||||
add_custom_target(python_proto
|
||||
COMMAND ${PROTO_COMPILER} --python_out=${PY_OUT_PATH} -I . -I ${PROTOCOMM_INCL_PATH} ${PROTO_FILES}
|
||||
VERBATIM
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
|
||||
)
|
||||
|
||||
add_custom_target(proto ALL
|
||||
DEPENDS c_proto python_proto
|
||||
VERBATIM
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
|
||||
)
|
25
components/esp_local_ctrl/proto/README.md
Normal file
25
components/esp_local_ctrl/proto/README.md
Normal file
|
@ -0,0 +1,25 @@
|
|||
# Protobuf files for defining ESP Local Control message structures
|
||||
|
||||
The proto files under this directory are used by esp_local_ctrl for defining protobuf messages which are sent and received over protocomm transport layer. These proto files cannot be used directly and have to be compiled into C and Python files. The generated C files are used by esp_local_ctrl itself to create, delete and manipulate transaction packets. The generated Python files can be used by python based applications for implementing client side interface to esp_local_ctrl service running on a device.
|
||||
|
||||
Note : These proto files are not automatically compiled during the build process.
|
||||
|
||||
# Compilation
|
||||
|
||||
Compilation requires protoc (Protobuf Compiler) and protoc-c (Protobuf C Compiler) installed. Since the generated files are to remain the same, as long as the proto files are not modified, therefore the generated files are already available under `components/esp_local_ctrl/proto-c` and `components/esp_local_ctrl/python` directories, and thus running `cmake` / `make` (and installing the Protobuf compilers) is optional.
|
||||
|
||||
If using `cmake` follow the below steps. If using `make`, jump to Step 2 directly.
|
||||
|
||||
## Step 1 (Only for cmake)
|
||||
|
||||
When using cmake, first create a build directory and call cmake from inside:
|
||||
|
||||
```
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
```
|
||||
|
||||
## Step 2
|
||||
|
||||
Simply run `make` to generate the respective C and Python files. The newly created files will overwrite those under `components/esp_local_ctrl/proto-c` and `components/esp_local_ctrl/python`
|
62
components/esp_local_ctrl/proto/esp_local_ctrl.proto
Normal file
62
components/esp_local_ctrl/proto/esp_local_ctrl.proto
Normal file
|
@ -0,0 +1,62 @@
|
|||
syntax = "proto3";
|
||||
|
||||
import "constants.proto";
|
||||
|
||||
message CmdGetPropertyCount {
|
||||
}
|
||||
|
||||
message RespGetPropertyCount {
|
||||
Status status = 1;
|
||||
uint32 count = 2;
|
||||
}
|
||||
|
||||
message PropertyInfo {
|
||||
Status status = 1;
|
||||
string name = 2;
|
||||
uint32 type = 3;
|
||||
uint32 flags = 4;
|
||||
bytes value = 5;
|
||||
}
|
||||
|
||||
message CmdGetPropertyValues {
|
||||
repeated uint32 indices = 1;
|
||||
}
|
||||
|
||||
message RespGetPropertyValues {
|
||||
Status status = 1;
|
||||
repeated PropertyInfo props = 2;
|
||||
}
|
||||
|
||||
message PropertyValue {
|
||||
uint32 index = 1;
|
||||
bytes value = 2;
|
||||
}
|
||||
|
||||
message CmdSetPropertyValues {
|
||||
repeated PropertyValue props = 1;
|
||||
}
|
||||
|
||||
message RespSetPropertyValues {
|
||||
Status status = 1;
|
||||
}
|
||||
|
||||
enum LocalCtrlMsgType {
|
||||
TypeCmdGetPropertyCount = 0;
|
||||
TypeRespGetPropertyCount = 1;
|
||||
TypeCmdGetPropertyValues = 4;
|
||||
TypeRespGetPropertyValues = 5;
|
||||
TypeCmdSetPropertyValues = 6;
|
||||
TypeRespSetPropertyValues = 7;
|
||||
}
|
||||
|
||||
message LocalCtrlMessage {
|
||||
LocalCtrlMsgType msg = 1;
|
||||
oneof payload {
|
||||
CmdGetPropertyCount cmd_get_prop_count = 10;
|
||||
RespGetPropertyCount resp_get_prop_count = 11;
|
||||
CmdGetPropertyValues cmd_get_prop_vals = 12;
|
||||
RespGetPropertyValues resp_get_prop_vals = 13;
|
||||
CmdSetPropertyValues cmd_set_prop_vals = 14;
|
||||
RespSetPropertyValues resp_set_prop_vals = 15;
|
||||
}
|
||||
}
|
7
components/esp_local_ctrl/proto/makefile
Normal file
7
components/esp_local_ctrl/proto/makefile
Normal file
|
@ -0,0 +1,7 @@
|
|||
all: c_proto python_proto
|
||||
|
||||
c_proto: *.proto
|
||||
@protoc-c --c_out=../proto-c/ -I . -I ../../protocomm/proto/ *.proto
|
||||
|
||||
python_proto: *.proto
|
||||
@protoc --python_out=../python/ -I . -I ../../protocomm/proto/ *.proto
|
549
components/esp_local_ctrl/python/esp_local_ctrl_pb2.py
Normal file
549
components/esp_local_ctrl/python/esp_local_ctrl_pb2.py
Normal file
|
@ -0,0 +1,549 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
# source: esp_local_ctrl.proto
|
||||
|
||||
import sys
|
||||
_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
|
||||
from google.protobuf.internal import enum_type_wrapper
|
||||
from google.protobuf import descriptor as _descriptor
|
||||
from google.protobuf import message as _message
|
||||
from google.protobuf import reflection as _reflection
|
||||
from google.protobuf import symbol_database as _symbol_database
|
||||
# @@protoc_insertion_point(imports)
|
||||
|
||||
_sym_db = _symbol_database.Default()
|
||||
|
||||
|
||||
import constants_pb2 as constants__pb2
|
||||
|
||||
|
||||
DESCRIPTOR = _descriptor.FileDescriptor(
|
||||
name='esp_local_ctrl.proto',
|
||||
package='',
|
||||
syntax='proto3',
|
||||
serialized_options=None,
|
||||
serialized_pb=_b('\n\x14\x65sp_local_ctrl.proto\x1a\x0f\x63onstants.proto\"\x15\n\x13\x43mdGetPropertyCount\">\n\x14RespGetPropertyCount\x12\x17\n\x06status\x18\x01 \x01(\x0e\x32\x07.Status\x12\r\n\x05\x63ount\x18\x02 \x01(\r\"a\n\x0cPropertyInfo\x12\x17\n\x06status\x18\x01 \x01(\x0e\x32\x07.Status\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0c\n\x04type\x18\x03 \x01(\r\x12\r\n\x05\x66lags\x18\x04 \x01(\r\x12\r\n\x05value\x18\x05 \x01(\x0c\"\'\n\x14\x43mdGetPropertyValues\x12\x0f\n\x07indices\x18\x01 \x03(\r\"N\n\x15RespGetPropertyValues\x12\x17\n\x06status\x18\x01 \x01(\x0e\x32\x07.Status\x12\x1c\n\x05props\x18\x02 \x03(\x0b\x32\r.PropertyInfo\"-\n\rPropertyValue\x12\r\n\x05index\x18\x01 \x01(\r\x12\r\n\x05value\x18\x02 \x01(\x0c\"5\n\x14\x43mdSetPropertyValues\x12\x1d\n\x05props\x18\x01 \x03(\x0b\x32\x0e.PropertyValue\"0\n\x15RespSetPropertyValues\x12\x17\n\x06status\x18\x01 \x01(\x0e\x32\x07.Status\"\xfb\x02\n\x10LocalCtrlMessage\x12\x1e\n\x03msg\x18\x01 \x01(\x0e\x32\x11.LocalCtrlMsgType\x12\x32\n\x12\x63md_get_prop_count\x18\n \x01(\x0b\x32\x14.CmdGetPropertyCountH\x00\x12\x34\n\x13resp_get_prop_count\x18\x0b \x01(\x0b\x32\x15.RespGetPropertyCountH\x00\x12\x32\n\x11\x63md_get_prop_vals\x18\x0c \x01(\x0b\x32\x15.CmdGetPropertyValuesH\x00\x12\x34\n\x12resp_get_prop_vals\x18\r \x01(\x0b\x32\x16.RespGetPropertyValuesH\x00\x12\x32\n\x11\x63md_set_prop_vals\x18\x0e \x01(\x0b\x32\x15.CmdSetPropertyValuesH\x00\x12\x34\n\x12resp_set_prop_vals\x18\x0f \x01(\x0b\x32\x16.RespSetPropertyValuesH\x00\x42\t\n\x07payload*\xc7\x01\n\x10LocalCtrlMsgType\x12\x1b\n\x17TypeCmdGetPropertyCount\x10\x00\x12\x1c\n\x18TypeRespGetPropertyCount\x10\x01\x12\x1c\n\x18TypeCmdGetPropertyValues\x10\x04\x12\x1d\n\x19TypeRespGetPropertyValues\x10\x05\x12\x1c\n\x18TypeCmdSetPropertyValues\x10\x06\x12\x1d\n\x19TypeRespSetPropertyValues\x10\x07\x62\x06proto3')
|
||||
,
|
||||
dependencies=[constants__pb2.DESCRIPTOR,])
|
||||
|
||||
_LOCALCTRLMSGTYPE = _descriptor.EnumDescriptor(
|
||||
name='LocalCtrlMsgType',
|
||||
full_name='LocalCtrlMsgType',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
values=[
|
||||
_descriptor.EnumValueDescriptor(
|
||||
name='TypeCmdGetPropertyCount', index=0, number=0,
|
||||
serialized_options=None,
|
||||
type=None),
|
||||
_descriptor.EnumValueDescriptor(
|
||||
name='TypeRespGetPropertyCount', index=1, number=1,
|
||||
serialized_options=None,
|
||||
type=None),
|
||||
_descriptor.EnumValueDescriptor(
|
||||
name='TypeCmdGetPropertyValues', index=2, number=4,
|
||||
serialized_options=None,
|
||||
type=None),
|
||||
_descriptor.EnumValueDescriptor(
|
||||
name='TypeRespGetPropertyValues', index=3, number=5,
|
||||
serialized_options=None,
|
||||
type=None),
|
||||
_descriptor.EnumValueDescriptor(
|
||||
name='TypeCmdSetPropertyValues', index=4, number=6,
|
||||
serialized_options=None,
|
||||
type=None),
|
||||
_descriptor.EnumValueDescriptor(
|
||||
name='TypeRespSetPropertyValues', index=5, number=7,
|
||||
serialized_options=None,
|
||||
type=None),
|
||||
],
|
||||
containing_type=None,
|
||||
serialized_options=None,
|
||||
serialized_start=883,
|
||||
serialized_end=1082,
|
||||
)
|
||||
_sym_db.RegisterEnumDescriptor(_LOCALCTRLMSGTYPE)
|
||||
|
||||
LocalCtrlMsgType = enum_type_wrapper.EnumTypeWrapper(_LOCALCTRLMSGTYPE)
|
||||
TypeCmdGetPropertyCount = 0
|
||||
TypeRespGetPropertyCount = 1
|
||||
TypeCmdGetPropertyValues = 4
|
||||
TypeRespGetPropertyValues = 5
|
||||
TypeCmdSetPropertyValues = 6
|
||||
TypeRespSetPropertyValues = 7
|
||||
|
||||
|
||||
|
||||
_CMDGETPROPERTYCOUNT = _descriptor.Descriptor(
|
||||
name='CmdGetPropertyCount',
|
||||
full_name='CmdGetPropertyCount',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax='proto3',
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=41,
|
||||
serialized_end=62,
|
||||
)
|
||||
|
||||
|
||||
_RESPGETPROPERTYCOUNT = _descriptor.Descriptor(
|
||||
name='RespGetPropertyCount',
|
||||
full_name='RespGetPropertyCount',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='status', full_name='RespGetPropertyCount.status', index=0,
|
||||
number=1, type=14, cpp_type=8, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='count', full_name='RespGetPropertyCount.count', index=1,
|
||||
number=2, type=13, cpp_type=3, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax='proto3',
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=64,
|
||||
serialized_end=126,
|
||||
)
|
||||
|
||||
|
||||
_PROPERTYINFO = _descriptor.Descriptor(
|
||||
name='PropertyInfo',
|
||||
full_name='PropertyInfo',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='status', full_name='PropertyInfo.status', index=0,
|
||||
number=1, type=14, cpp_type=8, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='name', full_name='PropertyInfo.name', index=1,
|
||||
number=2, type=9, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=_b("").decode('utf-8'),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='type', full_name='PropertyInfo.type', index=2,
|
||||
number=3, type=13, cpp_type=3, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='flags', full_name='PropertyInfo.flags', index=3,
|
||||
number=4, type=13, cpp_type=3, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='value', full_name='PropertyInfo.value', index=4,
|
||||
number=5, type=12, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=_b(""),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax='proto3',
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=128,
|
||||
serialized_end=225,
|
||||
)
|
||||
|
||||
|
||||
_CMDGETPROPERTYVALUES = _descriptor.Descriptor(
|
||||
name='CmdGetPropertyValues',
|
||||
full_name='CmdGetPropertyValues',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='indices', full_name='CmdGetPropertyValues.indices', index=0,
|
||||
number=1, type=13, cpp_type=3, label=3,
|
||||
has_default_value=False, default_value=[],
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax='proto3',
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=227,
|
||||
serialized_end=266,
|
||||
)
|
||||
|
||||
|
||||
_RESPGETPROPERTYVALUES = _descriptor.Descriptor(
|
||||
name='RespGetPropertyValues',
|
||||
full_name='RespGetPropertyValues',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='status', full_name='RespGetPropertyValues.status', index=0,
|
||||
number=1, type=14, cpp_type=8, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='props', full_name='RespGetPropertyValues.props', index=1,
|
||||
number=2, type=11, cpp_type=10, label=3,
|
||||
has_default_value=False, default_value=[],
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax='proto3',
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=268,
|
||||
serialized_end=346,
|
||||
)
|
||||
|
||||
|
||||
_PROPERTYVALUE = _descriptor.Descriptor(
|
||||
name='PropertyValue',
|
||||
full_name='PropertyValue',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='index', full_name='PropertyValue.index', index=0,
|
||||
number=1, type=13, cpp_type=3, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='value', full_name='PropertyValue.value', index=1,
|
||||
number=2, type=12, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=_b(""),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax='proto3',
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=348,
|
||||
serialized_end=393,
|
||||
)
|
||||
|
||||
|
||||
_CMDSETPROPERTYVALUES = _descriptor.Descriptor(
|
||||
name='CmdSetPropertyValues',
|
||||
full_name='CmdSetPropertyValues',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='props', full_name='CmdSetPropertyValues.props', index=0,
|
||||
number=1, type=11, cpp_type=10, label=3,
|
||||
has_default_value=False, default_value=[],
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax='proto3',
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=395,
|
||||
serialized_end=448,
|
||||
)
|
||||
|
||||
|
||||
_RESPSETPROPERTYVALUES = _descriptor.Descriptor(
|
||||
name='RespSetPropertyValues',
|
||||
full_name='RespSetPropertyValues',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='status', full_name='RespSetPropertyValues.status', index=0,
|
||||
number=1, type=14, cpp_type=8, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax='proto3',
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=450,
|
||||
serialized_end=498,
|
||||
)
|
||||
|
||||
|
||||
_LOCALCTRLMESSAGE = _descriptor.Descriptor(
|
||||
name='LocalCtrlMessage',
|
||||
full_name='LocalCtrlMessage',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='msg', full_name='LocalCtrlMessage.msg', index=0,
|
||||
number=1, type=14, cpp_type=8, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='cmd_get_prop_count', full_name='LocalCtrlMessage.cmd_get_prop_count', index=1,
|
||||
number=10, type=11, cpp_type=10, label=1,
|
||||
has_default_value=False, default_value=None,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='resp_get_prop_count', full_name='LocalCtrlMessage.resp_get_prop_count', index=2,
|
||||
number=11, type=11, cpp_type=10, label=1,
|
||||
has_default_value=False, default_value=None,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='cmd_get_prop_vals', full_name='LocalCtrlMessage.cmd_get_prop_vals', index=3,
|
||||
number=12, type=11, cpp_type=10, label=1,
|
||||
has_default_value=False, default_value=None,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='resp_get_prop_vals', full_name='LocalCtrlMessage.resp_get_prop_vals', index=4,
|
||||
number=13, type=11, cpp_type=10, label=1,
|
||||
has_default_value=False, default_value=None,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='cmd_set_prop_vals', full_name='LocalCtrlMessage.cmd_set_prop_vals', index=5,
|
||||
number=14, type=11, cpp_type=10, label=1,
|
||||
has_default_value=False, default_value=None,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='resp_set_prop_vals', full_name='LocalCtrlMessage.resp_set_prop_vals', index=6,
|
||||
number=15, type=11, cpp_type=10, label=1,
|
||||
has_default_value=False, default_value=None,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax='proto3',
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
_descriptor.OneofDescriptor(
|
||||
name='payload', full_name='LocalCtrlMessage.payload',
|
||||
index=0, containing_type=None, fields=[]),
|
||||
],
|
||||
serialized_start=501,
|
||||
serialized_end=880,
|
||||
)
|
||||
|
||||
_RESPGETPROPERTYCOUNT.fields_by_name['status'].enum_type = constants__pb2._STATUS
|
||||
_PROPERTYINFO.fields_by_name['status'].enum_type = constants__pb2._STATUS
|
||||
_RESPGETPROPERTYVALUES.fields_by_name['status'].enum_type = constants__pb2._STATUS
|
||||
_RESPGETPROPERTYVALUES.fields_by_name['props'].message_type = _PROPERTYINFO
|
||||
_CMDSETPROPERTYVALUES.fields_by_name['props'].message_type = _PROPERTYVALUE
|
||||
_RESPSETPROPERTYVALUES.fields_by_name['status'].enum_type = constants__pb2._STATUS
|
||||
_LOCALCTRLMESSAGE.fields_by_name['msg'].enum_type = _LOCALCTRLMSGTYPE
|
||||
_LOCALCTRLMESSAGE.fields_by_name['cmd_get_prop_count'].message_type = _CMDGETPROPERTYCOUNT
|
||||
_LOCALCTRLMESSAGE.fields_by_name['resp_get_prop_count'].message_type = _RESPGETPROPERTYCOUNT
|
||||
_LOCALCTRLMESSAGE.fields_by_name['cmd_get_prop_vals'].message_type = _CMDGETPROPERTYVALUES
|
||||
_LOCALCTRLMESSAGE.fields_by_name['resp_get_prop_vals'].message_type = _RESPGETPROPERTYVALUES
|
||||
_LOCALCTRLMESSAGE.fields_by_name['cmd_set_prop_vals'].message_type = _CMDSETPROPERTYVALUES
|
||||
_LOCALCTRLMESSAGE.fields_by_name['resp_set_prop_vals'].message_type = _RESPSETPROPERTYVALUES
|
||||
_LOCALCTRLMESSAGE.oneofs_by_name['payload'].fields.append(
|
||||
_LOCALCTRLMESSAGE.fields_by_name['cmd_get_prop_count'])
|
||||
_LOCALCTRLMESSAGE.fields_by_name['cmd_get_prop_count'].containing_oneof = _LOCALCTRLMESSAGE.oneofs_by_name['payload']
|
||||
_LOCALCTRLMESSAGE.oneofs_by_name['payload'].fields.append(
|
||||
_LOCALCTRLMESSAGE.fields_by_name['resp_get_prop_count'])
|
||||
_LOCALCTRLMESSAGE.fields_by_name['resp_get_prop_count'].containing_oneof = _LOCALCTRLMESSAGE.oneofs_by_name['payload']
|
||||
_LOCALCTRLMESSAGE.oneofs_by_name['payload'].fields.append(
|
||||
_LOCALCTRLMESSAGE.fields_by_name['cmd_get_prop_vals'])
|
||||
_LOCALCTRLMESSAGE.fields_by_name['cmd_get_prop_vals'].containing_oneof = _LOCALCTRLMESSAGE.oneofs_by_name['payload']
|
||||
_LOCALCTRLMESSAGE.oneofs_by_name['payload'].fields.append(
|
||||
_LOCALCTRLMESSAGE.fields_by_name['resp_get_prop_vals'])
|
||||
_LOCALCTRLMESSAGE.fields_by_name['resp_get_prop_vals'].containing_oneof = _LOCALCTRLMESSAGE.oneofs_by_name['payload']
|
||||
_LOCALCTRLMESSAGE.oneofs_by_name['payload'].fields.append(
|
||||
_LOCALCTRLMESSAGE.fields_by_name['cmd_set_prop_vals'])
|
||||
_LOCALCTRLMESSAGE.fields_by_name['cmd_set_prop_vals'].containing_oneof = _LOCALCTRLMESSAGE.oneofs_by_name['payload']
|
||||
_LOCALCTRLMESSAGE.oneofs_by_name['payload'].fields.append(
|
||||
_LOCALCTRLMESSAGE.fields_by_name['resp_set_prop_vals'])
|
||||
_LOCALCTRLMESSAGE.fields_by_name['resp_set_prop_vals'].containing_oneof = _LOCALCTRLMESSAGE.oneofs_by_name['payload']
|
||||
DESCRIPTOR.message_types_by_name['CmdGetPropertyCount'] = _CMDGETPROPERTYCOUNT
|
||||
DESCRIPTOR.message_types_by_name['RespGetPropertyCount'] = _RESPGETPROPERTYCOUNT
|
||||
DESCRIPTOR.message_types_by_name['PropertyInfo'] = _PROPERTYINFO
|
||||
DESCRIPTOR.message_types_by_name['CmdGetPropertyValues'] = _CMDGETPROPERTYVALUES
|
||||
DESCRIPTOR.message_types_by_name['RespGetPropertyValues'] = _RESPGETPROPERTYVALUES
|
||||
DESCRIPTOR.message_types_by_name['PropertyValue'] = _PROPERTYVALUE
|
||||
DESCRIPTOR.message_types_by_name['CmdSetPropertyValues'] = _CMDSETPROPERTYVALUES
|
||||
DESCRIPTOR.message_types_by_name['RespSetPropertyValues'] = _RESPSETPROPERTYVALUES
|
||||
DESCRIPTOR.message_types_by_name['LocalCtrlMessage'] = _LOCALCTRLMESSAGE
|
||||
DESCRIPTOR.enum_types_by_name['LocalCtrlMsgType'] = _LOCALCTRLMSGTYPE
|
||||
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
|
||||
|
||||
CmdGetPropertyCount = _reflection.GeneratedProtocolMessageType('CmdGetPropertyCount', (_message.Message,), dict(
|
||||
DESCRIPTOR = _CMDGETPROPERTYCOUNT,
|
||||
__module__ = 'esp_local_ctrl_pb2'
|
||||
# @@protoc_insertion_point(class_scope:CmdGetPropertyCount)
|
||||
))
|
||||
_sym_db.RegisterMessage(CmdGetPropertyCount)
|
||||
|
||||
RespGetPropertyCount = _reflection.GeneratedProtocolMessageType('RespGetPropertyCount', (_message.Message,), dict(
|
||||
DESCRIPTOR = _RESPGETPROPERTYCOUNT,
|
||||
__module__ = 'esp_local_ctrl_pb2'
|
||||
# @@protoc_insertion_point(class_scope:RespGetPropertyCount)
|
||||
))
|
||||
_sym_db.RegisterMessage(RespGetPropertyCount)
|
||||
|
||||
PropertyInfo = _reflection.GeneratedProtocolMessageType('PropertyInfo', (_message.Message,), dict(
|
||||
DESCRIPTOR = _PROPERTYINFO,
|
||||
__module__ = 'esp_local_ctrl_pb2'
|
||||
# @@protoc_insertion_point(class_scope:PropertyInfo)
|
||||
))
|
||||
_sym_db.RegisterMessage(PropertyInfo)
|
||||
|
||||
CmdGetPropertyValues = _reflection.GeneratedProtocolMessageType('CmdGetPropertyValues', (_message.Message,), dict(
|
||||
DESCRIPTOR = _CMDGETPROPERTYVALUES,
|
||||
__module__ = 'esp_local_ctrl_pb2'
|
||||
# @@protoc_insertion_point(class_scope:CmdGetPropertyValues)
|
||||
))
|
||||
_sym_db.RegisterMessage(CmdGetPropertyValues)
|
||||
|
||||
RespGetPropertyValues = _reflection.GeneratedProtocolMessageType('RespGetPropertyValues', (_message.Message,), dict(
|
||||
DESCRIPTOR = _RESPGETPROPERTYVALUES,
|
||||
__module__ = 'esp_local_ctrl_pb2'
|
||||
# @@protoc_insertion_point(class_scope:RespGetPropertyValues)
|
||||
))
|
||||
_sym_db.RegisterMessage(RespGetPropertyValues)
|
||||
|
||||
PropertyValue = _reflection.GeneratedProtocolMessageType('PropertyValue', (_message.Message,), dict(
|
||||
DESCRIPTOR = _PROPERTYVALUE,
|
||||
__module__ = 'esp_local_ctrl_pb2'
|
||||
# @@protoc_insertion_point(class_scope:PropertyValue)
|
||||
))
|
||||
_sym_db.RegisterMessage(PropertyValue)
|
||||
|
||||
CmdSetPropertyValues = _reflection.GeneratedProtocolMessageType('CmdSetPropertyValues', (_message.Message,), dict(
|
||||
DESCRIPTOR = _CMDSETPROPERTYVALUES,
|
||||
__module__ = 'esp_local_ctrl_pb2'
|
||||
# @@protoc_insertion_point(class_scope:CmdSetPropertyValues)
|
||||
))
|
||||
_sym_db.RegisterMessage(CmdSetPropertyValues)
|
||||
|
||||
RespSetPropertyValues = _reflection.GeneratedProtocolMessageType('RespSetPropertyValues', (_message.Message,), dict(
|
||||
DESCRIPTOR = _RESPSETPROPERTYVALUES,
|
||||
__module__ = 'esp_local_ctrl_pb2'
|
||||
# @@protoc_insertion_point(class_scope:RespSetPropertyValues)
|
||||
))
|
||||
_sym_db.RegisterMessage(RespSetPropertyValues)
|
||||
|
||||
LocalCtrlMessage = _reflection.GeneratedProtocolMessageType('LocalCtrlMessage', (_message.Message,), dict(
|
||||
DESCRIPTOR = _LOCALCTRLMESSAGE,
|
||||
__module__ = 'esp_local_ctrl_pb2'
|
||||
# @@protoc_insertion_point(class_scope:LocalCtrlMessage)
|
||||
))
|
||||
_sym_db.RegisterMessage(LocalCtrlMessage)
|
||||
|
||||
|
||||
# @@protoc_insertion_point(module_scope)
|
417
components/esp_local_ctrl/src/esp_local_ctrl.c
Normal file
417
components/esp_local_ctrl/src/esp_local_ctrl.c
Normal file
|
@ -0,0 +1,417 @@
|
|||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <esp_err.h>
|
||||
#include <esp_log.h>
|
||||
|
||||
#include <protocomm.h>
|
||||
#include <protocomm_security0.h>
|
||||
|
||||
#include <esp_local_ctrl.h>
|
||||
#include "esp_local_ctrl_priv.h"
|
||||
#include "esp_local_ctrl.pb-c.h"
|
||||
|
||||
#define ESP_LOCAL_CTRL_VERSION "v1.0"
|
||||
|
||||
struct inst_ctx {
|
||||
protocomm_t *pc;
|
||||
esp_local_ctrl_config_t config;
|
||||
esp_local_ctrl_prop_t **props;
|
||||
size_t props_count;
|
||||
};
|
||||
|
||||
struct inst_ctx *local_ctrl_inst_ctx;
|
||||
|
||||
static const char *TAG = "esp_local_ctrl";
|
||||
|
||||
esp_err_t esp_local_ctrl_start(const esp_local_ctrl_config_t *config)
|
||||
{
|
||||
esp_err_t ret;
|
||||
|
||||
if (!config) {
|
||||
ESP_LOGE(TAG, "NULL configuration provided");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (!config->transport) {
|
||||
ESP_LOGE(TAG, "No transport provided");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (config->max_properties == 0) {
|
||||
ESP_LOGE(TAG, "max_properties must be greater than 0");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (!config->handlers.get_prop_values ||
|
||||
!config->handlers.set_prop_values) {
|
||||
ESP_LOGE(TAG, "Handlers cannot be null");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (local_ctrl_inst_ctx) {
|
||||
ESP_LOGW(TAG, "Service already active");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
local_ctrl_inst_ctx = calloc(1, sizeof(struct inst_ctx));
|
||||
if (!local_ctrl_inst_ctx) {
|
||||
ESP_LOGE(TAG, "Failed to allocate memory for instance");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
memcpy(&local_ctrl_inst_ctx->config, config, sizeof(local_ctrl_inst_ctx->config));
|
||||
|
||||
local_ctrl_inst_ctx->props = calloc(local_ctrl_inst_ctx->config.max_properties,
|
||||
sizeof(esp_local_ctrl_prop_t *));
|
||||
if (!local_ctrl_inst_ctx->props) {
|
||||
ESP_LOGE(TAG, "Failed to allocate memory for properties");
|
||||
free(local_ctrl_inst_ctx);
|
||||
local_ctrl_inst_ctx = NULL;
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
/* Since the config structure will be different for different transport modes, each transport may
|
||||
* implement a `copy_config()` function, which accepts a configuration structure as input and
|
||||
* creates a copy of that, which can be kept in the context structure of the `esp_local_ctrl` instance.
|
||||
* This copy can be later be freed using `free_config()` */
|
||||
if (config->transport->copy_config) {
|
||||
ret = config->transport->copy_config(&local_ctrl_inst_ctx->config.transport_config,
|
||||
&config->transport_config);
|
||||
if (ret != ESP_OK) {
|
||||
esp_local_ctrl_stop();
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* For a selected transport mode, endpoints may need to be declared prior to starting the
|
||||
* `esp_local_ctrl` service, e.g. in case of BLE. By declaration it means that the transport layer
|
||||
* allocates some resources for an endpoint, and later, after service has started, a handler
|
||||
* is assigned for that endpoint */
|
||||
if (config->transport->declare_ep) {
|
||||
/* UUIDs are 16bit unique IDs for each endpoint. This may or may not be relevant for
|
||||
* a chosen transport. We reserve all values from FF50 to FFFF for the internal endpoints.
|
||||
* The remaining endpoints can be used by the application for its own custom endpoints */
|
||||
uint16_t start_uuid = 0xFF50;
|
||||
ret = config->transport->declare_ep(&local_ctrl_inst_ctx->config.transport_config,
|
||||
"esp_local_ctrl/version", start_uuid++);
|
||||
if (ret != ESP_OK) {
|
||||
esp_local_ctrl_stop();
|
||||
return ret;
|
||||
}
|
||||
ret = config->transport->declare_ep(&local_ctrl_inst_ctx->config.transport_config,
|
||||
"esp_local_ctrl/session", start_uuid++);
|
||||
if (ret != ESP_OK) {
|
||||
esp_local_ctrl_stop();
|
||||
return ret;
|
||||
}
|
||||
ret = config->transport->declare_ep(&local_ctrl_inst_ctx->config.transport_config,
|
||||
"esp_local_ctrl/control", start_uuid++);
|
||||
if (ret != ESP_OK) {
|
||||
esp_local_ctrl_stop();
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
local_ctrl_inst_ctx->pc = protocomm_new();
|
||||
if (!local_ctrl_inst_ctx->pc) {
|
||||
ESP_LOGE(TAG, "Failed to create new protocomm instance");
|
||||
esp_local_ctrl_stop();
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (config->transport->start_service) {
|
||||
ret = config->transport->start_service(local_ctrl_inst_ctx->pc,
|
||||
&local_ctrl_inst_ctx->config.transport_config);
|
||||
if (ret != ESP_OK) {
|
||||
esp_local_ctrl_stop();
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = protocomm_set_version(local_ctrl_inst_ctx->pc, "esp_local_ctrl/version",
|
||||
ESP_LOCAL_CTRL_VERSION);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to set version endpoint");
|
||||
esp_local_ctrl_stop();
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = protocomm_set_security(local_ctrl_inst_ctx->pc, "esp_local_ctrl/session",
|
||||
&protocomm_security0, NULL);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to set session endpoint");
|
||||
esp_local_ctrl_stop();
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = protocomm_add_endpoint(local_ctrl_inst_ctx->pc, "esp_local_ctrl/control",
|
||||
esp_local_ctrl_data_handler, NULL);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to set control endpoint");
|
||||
esp_local_ctrl_stop();
|
||||
return ret;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_local_ctrl_stop(void)
|
||||
{
|
||||
if (local_ctrl_inst_ctx) {
|
||||
if (local_ctrl_inst_ctx->config.transport->free_config) {
|
||||
local_ctrl_inst_ctx->config.transport->free_config(&local_ctrl_inst_ctx->config.transport_config);
|
||||
}
|
||||
if (local_ctrl_inst_ctx->pc) {
|
||||
if (local_ctrl_inst_ctx->config.transport->stop_service) {
|
||||
local_ctrl_inst_ctx->config.transport->stop_service(local_ctrl_inst_ctx->pc);
|
||||
}
|
||||
protocomm_delete(local_ctrl_inst_ctx->pc);
|
||||
}
|
||||
if (local_ctrl_inst_ctx->config.handlers.usr_ctx_free_fn) {
|
||||
local_ctrl_inst_ctx->config.handlers.usr_ctx_free_fn(
|
||||
local_ctrl_inst_ctx->config.handlers.usr_ctx);
|
||||
}
|
||||
|
||||
/* Iterate through all properties one by one and free them */
|
||||
for (uint32_t i = 0; i < local_ctrl_inst_ctx->config.max_properties; i++) {
|
||||
if (local_ctrl_inst_ctx->props[i] == NULL) {
|
||||
continue;
|
||||
}
|
||||
/* Release memory allocated for property data */
|
||||
free(local_ctrl_inst_ctx->props[i]->name);
|
||||
if (local_ctrl_inst_ctx->props[i]->ctx_free_fn) {
|
||||
local_ctrl_inst_ctx->props[i]->ctx_free_fn(local_ctrl_inst_ctx->props[i]->ctx);
|
||||
}
|
||||
free(local_ctrl_inst_ctx->props[i]);
|
||||
}
|
||||
free(local_ctrl_inst_ctx->props);
|
||||
free(local_ctrl_inst_ctx);
|
||||
local_ctrl_inst_ctx = NULL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static int esp_local_ctrl_get_property_index(const char *name)
|
||||
{
|
||||
if (!local_ctrl_inst_ctx || !name) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Iterate through all properties one by one
|
||||
* and find the one with matching name */
|
||||
for (uint32_t i = 0; i < local_ctrl_inst_ctx->props_count; i++) {
|
||||
if (strcmp(local_ctrl_inst_ctx->props[i]->name, name) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
esp_err_t esp_local_ctrl_add_property(const esp_local_ctrl_prop_t *prop)
|
||||
{
|
||||
if (!local_ctrl_inst_ctx) {
|
||||
ESP_LOGE(TAG, "Service not running");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
if (!prop || !prop->name) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (esp_local_ctrl_get_property_index(prop->name) >= 0) {
|
||||
ESP_LOGE(TAG, "Property with name %s exists", prop->name);
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (local_ctrl_inst_ctx->config.max_properties
|
||||
== local_ctrl_inst_ctx->props_count) {
|
||||
ESP_LOGE(TAG, "Max properties limit reached. Cannot add property %s", prop->name);
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
uint32_t i = local_ctrl_inst_ctx->props_count;
|
||||
local_ctrl_inst_ctx->props[i] = calloc(1, sizeof(esp_local_ctrl_prop_t));
|
||||
if (!local_ctrl_inst_ctx->props[i]) {
|
||||
ESP_LOGE(TAG, "Failed to allocate memory for new property %s", prop->name);
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
local_ctrl_inst_ctx->props[i]->name = strdup(prop->name);
|
||||
if (!local_ctrl_inst_ctx->props[i]->name) {
|
||||
ESP_LOGE(TAG, "Failed to allocate memory for property data %s", prop->name);
|
||||
free(local_ctrl_inst_ctx->props[i]);
|
||||
local_ctrl_inst_ctx->props[i] = NULL;
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
local_ctrl_inst_ctx->props[i]->type = prop->type;
|
||||
local_ctrl_inst_ctx->props[i]->size = prop->size;
|
||||
local_ctrl_inst_ctx->props[i]->flags = prop->flags;
|
||||
local_ctrl_inst_ctx->props[i]->ctx = prop->ctx;
|
||||
local_ctrl_inst_ctx->props[i]->ctx_free_fn = prop->ctx_free_fn;
|
||||
local_ctrl_inst_ctx->props_count++;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
esp_err_t esp_local_ctrl_remove_property(const char *name)
|
||||
{
|
||||
int idx = esp_local_ctrl_get_property_index(name);
|
||||
if (idx < 0) {
|
||||
ESP_LOGE(TAG, "Property %s not found", name);
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
/* Release memory allocated for property data */
|
||||
if (local_ctrl_inst_ctx->props[idx]->ctx_free_fn) {
|
||||
local_ctrl_inst_ctx->props[idx]->ctx_free_fn(
|
||||
local_ctrl_inst_ctx->props[idx]->ctx);
|
||||
}
|
||||
free(local_ctrl_inst_ctx->props[idx]->name);
|
||||
free(local_ctrl_inst_ctx->props[idx]);
|
||||
local_ctrl_inst_ctx->props[idx++] = NULL;
|
||||
|
||||
/* Move the following properties forward, so that there is
|
||||
* no empty space between two properties */
|
||||
for (uint32_t i = idx; i < local_ctrl_inst_ctx->props_count; i++) {
|
||||
if (local_ctrl_inst_ctx->props[i] == NULL) {
|
||||
break;
|
||||
}
|
||||
local_ctrl_inst_ctx->props[i-1] = local_ctrl_inst_ctx->props[i];
|
||||
}
|
||||
local_ctrl_inst_ctx->props_count--;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
const esp_local_ctrl_prop_t *esp_local_ctrl_get_property(const char *name)
|
||||
{
|
||||
int idx = esp_local_ctrl_get_property_index(name);
|
||||
if (idx < 0) {
|
||||
ESP_LOGE(TAG, "Property %s not found", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return local_ctrl_inst_ctx->props[idx];
|
||||
}
|
||||
|
||||
esp_err_t esp_local_ctrl_get_prop_count(size_t *count)
|
||||
{
|
||||
if (!local_ctrl_inst_ctx) {
|
||||
ESP_LOGE(TAG, "Service not running");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
if (!count) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
*count = local_ctrl_inst_ctx->props_count;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_local_ctrl_get_prop_values(size_t total_indices, uint32_t *indices,
|
||||
esp_local_ctrl_prop_t *props,
|
||||
esp_local_ctrl_prop_val_t *values)
|
||||
{
|
||||
if (!local_ctrl_inst_ctx) {
|
||||
ESP_LOGE(TAG, "Service not running");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
if (!indices || !props || !values) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* Convert indices to names */
|
||||
for (size_t i = 0; i < total_indices; i++) {
|
||||
if (indices[i] >= local_ctrl_inst_ctx->props_count) {
|
||||
ESP_LOGE(TAG, "Invalid property index %d", indices[i]);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
props[i].name = local_ctrl_inst_ctx->props[indices[i]]->name;
|
||||
props[i].type = local_ctrl_inst_ctx->props[indices[i]]->type;
|
||||
props[i].flags = local_ctrl_inst_ctx->props[indices[i]]->flags;
|
||||
props[i].size = local_ctrl_inst_ctx->props[indices[i]]->size;
|
||||
props[i].ctx = local_ctrl_inst_ctx->props[indices[i]]->ctx;
|
||||
}
|
||||
|
||||
esp_local_ctrl_handlers_t *h = &local_ctrl_inst_ctx->config.handlers;
|
||||
esp_err_t ret = h->get_prop_values(total_indices, props, values, h->usr_ctx);
|
||||
|
||||
/* Properties with fixed sizes need to be checked */
|
||||
for (size_t i = 0; i < total_indices; i++) {
|
||||
if (local_ctrl_inst_ctx->props[indices[i]]->size != 0) {
|
||||
values[i].size = local_ctrl_inst_ctx->props[indices[i]]->size;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_local_ctrl_set_prop_values(size_t total_indices, uint32_t *indices,
|
||||
const esp_local_ctrl_prop_val_t *values)
|
||||
{
|
||||
if (!local_ctrl_inst_ctx) {
|
||||
ESP_LOGE(TAG, "Service not running");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
if (!indices || !values) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_local_ctrl_prop_t *props = calloc(total_indices,
|
||||
sizeof(esp_local_ctrl_prop_t));
|
||||
if (!props) {
|
||||
ESP_LOGE(TAG, "Unable to allocate memory for properties array");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
for (size_t i = 0; i < total_indices; i++) {
|
||||
if (indices[i] >= local_ctrl_inst_ctx->props_count) {
|
||||
ESP_LOGE(TAG, "Invalid property index %d", indices[i]);
|
||||
free(props);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* Properties with fixed sizes need to be checked */
|
||||
if ((local_ctrl_inst_ctx->props[indices[i]]->size != values[i].size) &&
|
||||
(local_ctrl_inst_ctx->props[indices[i]]->size != 0)) {
|
||||
ESP_LOGE(TAG, "Invalid property size %d. Expected %d",
|
||||
values[i].size, local_ctrl_inst_ctx->props[indices[i]]->size);
|
||||
free(props);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
props[i].name = local_ctrl_inst_ctx->props[indices[i]]->name;
|
||||
props[i].type = local_ctrl_inst_ctx->props[indices[i]]->type;
|
||||
props[i].flags = local_ctrl_inst_ctx->props[indices[i]]->flags;
|
||||
props[i].size = local_ctrl_inst_ctx->props[indices[i]]->size;
|
||||
props[i].ctx = local_ctrl_inst_ctx->props[indices[i]]->ctx;
|
||||
}
|
||||
|
||||
esp_local_ctrl_handlers_t *h = &local_ctrl_inst_ctx->config.handlers;
|
||||
esp_err_t ret = h->set_prop_values(total_indices, props, values, h->usr_ctx);
|
||||
|
||||
free(props);
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_local_ctrl_set_handler(const char *ep_name,
|
||||
protocomm_req_handler_t handler,
|
||||
void *priv_data)
|
||||
{
|
||||
esp_err_t ret = ESP_ERR_INVALID_STATE;
|
||||
|
||||
if (local_ctrl_inst_ctx) {
|
||||
ret = protocomm_add_endpoint(local_ctrl_inst_ctx->pc, ep_name,
|
||||
handler, priv_data);
|
||||
}
|
||||
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to register endpoint handler");
|
||||
}
|
||||
return ret;
|
||||
}
|
298
components/esp_local_ctrl/src/esp_local_ctrl_handler.c
Normal file
298
components/esp_local_ctrl/src/esp_local_ctrl_handler.c
Normal file
|
@ -0,0 +1,298 @@
|
|||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <esp_err.h>
|
||||
#include <esp_log.h>
|
||||
|
||||
#include "esp_local_ctrl.h"
|
||||
#include "esp_local_ctrl_priv.h"
|
||||
#include "esp_local_ctrl.pb-c.h"
|
||||
|
||||
#define SAFE_ALLOCATION(type, var) \
|
||||
type *var = (type *) malloc(sizeof(type)); \
|
||||
if (!var) { \
|
||||
ESP_LOGE(TAG, "Error allocating memory"); \
|
||||
return ESP_ERR_NO_MEM; \
|
||||
}
|
||||
|
||||
static const char* TAG = "esp_local_ctrl_handler";
|
||||
|
||||
typedef struct esp_local_ctrl_cmd {
|
||||
int cmd_num;
|
||||
esp_err_t (*command_handler)(LocalCtrlMessage *req,
|
||||
LocalCtrlMessage *resp, void **ctx);
|
||||
} esp_local_ctrl_cmd_t;
|
||||
|
||||
static esp_err_t cmd_get_prop_count_handler(LocalCtrlMessage *req,
|
||||
LocalCtrlMessage *resp, void **ctx);
|
||||
|
||||
static esp_err_t cmd_get_prop_vals_handler(LocalCtrlMessage *req,
|
||||
LocalCtrlMessage *resp, void **ctx);
|
||||
|
||||
static esp_err_t cmd_set_prop_vals_handler(LocalCtrlMessage *req,
|
||||
LocalCtrlMessage *resp, void **ctx);
|
||||
|
||||
static esp_local_ctrl_cmd_t cmd_table[] = {
|
||||
{
|
||||
.cmd_num = LOCAL_CTRL_MSG_TYPE__TypeCmdGetPropertyCount,
|
||||
.command_handler = cmd_get_prop_count_handler
|
||||
},
|
||||
{
|
||||
.cmd_num = LOCAL_CTRL_MSG_TYPE__TypeCmdGetPropertyValues,
|
||||
.command_handler = cmd_get_prop_vals_handler
|
||||
},
|
||||
{
|
||||
.cmd_num = LOCAL_CTRL_MSG_TYPE__TypeCmdSetPropertyValues,
|
||||
.command_handler = cmd_set_prop_vals_handler
|
||||
}
|
||||
};
|
||||
|
||||
static uint16_t err_to_status(esp_err_t err)
|
||||
{
|
||||
uint16_t status;
|
||||
switch (err) {
|
||||
case ESP_OK:
|
||||
status = STATUS__Success;
|
||||
break;
|
||||
case ESP_ERR_INVALID_ARG:
|
||||
status = STATUS__InvalidArgument;
|
||||
break;
|
||||
case ESP_ERR_INVALID_STATE:
|
||||
status = STATUS__InvalidProto;
|
||||
break;
|
||||
default:
|
||||
status = STATUS__InternalError;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static esp_err_t cmd_get_prop_count_handler(LocalCtrlMessage *req,
|
||||
LocalCtrlMessage *resp, void **ctx)
|
||||
{
|
||||
SAFE_ALLOCATION(RespGetPropertyCount, resp_payload);
|
||||
resp_get_property_count__init(resp_payload);
|
||||
|
||||
size_t prop_count = 0;
|
||||
resp_payload->status = err_to_status(esp_local_ctrl_get_prop_count(&prop_count));
|
||||
resp_payload->count = prop_count;
|
||||
resp->payload_case = LOCAL_CTRL_MESSAGE__PAYLOAD_RESP_GET_PROP_COUNT;
|
||||
resp->resp_get_prop_count = resp_payload;
|
||||
ESP_LOGD(TAG, "Got properties count %d", prop_count);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
typedef void (*prop_val_free_fn_t)(void *val);
|
||||
|
||||
static esp_err_t cmd_get_prop_vals_handler(LocalCtrlMessage *req,
|
||||
LocalCtrlMessage *resp, void **ctx)
|
||||
{
|
||||
SAFE_ALLOCATION(RespGetPropertyValues, resp_payload);
|
||||
resp_get_property_values__init(resp_payload);
|
||||
|
||||
esp_local_ctrl_prop_val_t *vals = calloc(req->cmd_get_prop_vals->n_indices,
|
||||
sizeof(esp_local_ctrl_prop_val_t));
|
||||
esp_local_ctrl_prop_t *descs = calloc(req->cmd_get_prop_vals->n_indices,
|
||||
sizeof(esp_local_ctrl_prop_t));
|
||||
prop_val_free_fn_t *free_fns = calloc(req->cmd_get_prop_vals->n_indices,
|
||||
sizeof(prop_val_free_fn_t));
|
||||
resp_payload->props = calloc(req->cmd_get_prop_vals->n_indices,
|
||||
sizeof(PropertyInfo *));
|
||||
if (!vals || !descs || !free_fns || !resp_payload->props) {
|
||||
ESP_LOGE(TAG, "Failed to allocate memory for getting values");
|
||||
free(vals);
|
||||
free(descs);
|
||||
free(free_fns);
|
||||
free(resp_payload->props);
|
||||
free(resp_payload);
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
esp_err_t ret = esp_local_ctrl_get_prop_values(req->cmd_get_prop_vals->n_indices,
|
||||
req->cmd_get_prop_vals->indices,
|
||||
descs, vals);
|
||||
resp_payload->status = err_to_status(ret);
|
||||
if (ret == ESP_OK) {
|
||||
resp_payload->n_props = 0;
|
||||
for (size_t i = 0; i < req->cmd_get_prop_vals->n_indices; i++) {
|
||||
resp_payload->props[i] = malloc(sizeof(PropertyInfo));
|
||||
if (!resp_payload->props[i]) {
|
||||
resp_payload->status = STATUS__InternalError;
|
||||
break;
|
||||
}
|
||||
resp_payload->n_props++;
|
||||
property_info__init(resp_payload->props[i]);
|
||||
resp_payload->props[i]->name = descs[i].name;
|
||||
resp_payload->props[i]->type = descs[i].type;
|
||||
resp_payload->props[i]->flags = descs[i].flags;
|
||||
resp_payload->props[i]->value.data = vals[i].data;
|
||||
resp_payload->props[i]->value.len = vals[i].size;
|
||||
free_fns[i] = vals[i].free_fn;
|
||||
}
|
||||
}
|
||||
resp->payload_case = LOCAL_CTRL_MESSAGE__PAYLOAD_RESP_GET_PROP_VALS;
|
||||
resp->resp_get_prop_vals = resp_payload;
|
||||
(*ctx) = (void *)free_fns;
|
||||
free(vals);
|
||||
free(descs);
|
||||
|
||||
/* Unless it's a fatal error, always return ESP_OK, otherwise
|
||||
* the underlying connection will be closed by protocomm */
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t cmd_set_prop_vals_handler(LocalCtrlMessage *req,
|
||||
LocalCtrlMessage *resp, void **ctx)
|
||||
{
|
||||
SAFE_ALLOCATION(RespSetPropertyValues, resp_payload);
|
||||
resp_set_property_values__init(resp_payload);
|
||||
|
||||
uint32_t *idxs = calloc(req->cmd_set_prop_vals->n_props, sizeof(uint32_t));
|
||||
esp_local_ctrl_prop_val_t *vals = calloc(req->cmd_set_prop_vals->n_props,
|
||||
sizeof(esp_local_ctrl_prop_val_t));
|
||||
if (!idxs || !vals) {
|
||||
ESP_LOGE(TAG, "Failed to allocate memory for setting values");
|
||||
free(idxs);
|
||||
free(vals);
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
for (size_t i = 0; i < req->cmd_set_prop_vals->n_props; i++) {
|
||||
idxs[i] = req->cmd_set_prop_vals->props[i]->index;
|
||||
vals[i].data = req->cmd_set_prop_vals->props[i]->value.data;
|
||||
vals[i].size = req->cmd_set_prop_vals->props[i]->value.len;
|
||||
}
|
||||
|
||||
esp_err_t ret = esp_local_ctrl_set_prop_values(req->cmd_set_prop_vals->n_props,
|
||||
idxs, vals);
|
||||
resp_payload->status = err_to_status(ret);
|
||||
resp->payload_case = LOCAL_CTRL_MESSAGE__PAYLOAD_RESP_SET_PROP_VALS;
|
||||
resp->resp_set_prop_vals = resp_payload;
|
||||
free(idxs);
|
||||
free(vals);
|
||||
|
||||
/* Unless it's a fatal error, always return ESP_OK, otherwise
|
||||
* the underlying connection will be closed by protocomm */
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static int lookup_cmd_handler(int cmd_id)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof(cmd_table)/sizeof(esp_local_ctrl_cmd_t); i++) {
|
||||
if (cmd_table[i].cmd_num == cmd_id) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void esp_local_ctrl_command_cleanup(LocalCtrlMessage *resp, void **ctx)
|
||||
{
|
||||
if (!resp) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (resp->msg) {
|
||||
case LOCAL_CTRL_MSG_TYPE__TypeRespGetPropertyCount:
|
||||
free(resp->resp_get_prop_count);
|
||||
break;
|
||||
case LOCAL_CTRL_MSG_TYPE__TypeRespGetPropertyValues: {
|
||||
if (resp->resp_get_prop_vals) {
|
||||
prop_val_free_fn_t *free_fns = (prop_val_free_fn_t *)(*ctx);
|
||||
for (size_t i = 0; i < resp->resp_get_prop_vals->n_props; i++) {
|
||||
if (free_fns[i]) {
|
||||
free_fns[i](resp->resp_get_prop_vals->props[i]->value.data);
|
||||
}
|
||||
free(resp->resp_get_prop_vals->props[i]);
|
||||
}
|
||||
free(free_fns);
|
||||
free(resp->resp_get_prop_vals->props);
|
||||
free(resp->resp_get_prop_vals);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LOCAL_CTRL_MSG_TYPE__TypeRespSetPropertyValues:
|
||||
free(resp->resp_set_prop_vals);
|
||||
break;
|
||||
default:
|
||||
ESP_LOGE(TAG, "Unsupported response type in cleanup_handler");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static esp_err_t esp_local_ctrl_command_dispatcher(LocalCtrlMessage *req,
|
||||
LocalCtrlMessage *resp,
|
||||
void **ctx)
|
||||
{
|
||||
int cmd_index = lookup_cmd_handler(req->msg);
|
||||
if (cmd_index < 0) {
|
||||
ESP_LOGE(TAG, "Invalid command handler lookup");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_err_t ret = cmd_table[cmd_index].command_handler(req, resp, ctx);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Error executing command handler");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_local_ctrl_data_handler(uint32_t session_id, const uint8_t *inbuf, ssize_t inlen,
|
||||
uint8_t **outbuf, ssize_t *outlen, void *priv_data)
|
||||
{
|
||||
void *temp_ctx = NULL;
|
||||
LocalCtrlMessage *req = local_ctrl_message__unpack(NULL, inlen, inbuf);
|
||||
if (!req) {
|
||||
ESP_LOGE(TAG, "Unable to unpack payload data");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
LocalCtrlMessage resp;
|
||||
local_ctrl_message__init(&resp);
|
||||
resp.msg = req->msg + 1; /* Response is request + 1 */
|
||||
|
||||
esp_err_t ret = esp_local_ctrl_command_dispatcher(req, &resp, &temp_ctx);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "command dispatcher failed");
|
||||
esp_local_ctrl_command_cleanup(&resp, &temp_ctx);
|
||||
local_ctrl_message__free_unpacked(req, NULL);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
local_ctrl_message__free_unpacked(req, NULL);
|
||||
|
||||
*outlen = local_ctrl_message__get_packed_size(&resp);
|
||||
if (*outlen <= 0) {
|
||||
ESP_LOGE(TAG, "Invalid encoding for response");
|
||||
esp_local_ctrl_command_cleanup(&resp, &temp_ctx);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
*outbuf = (uint8_t *) malloc(*outlen);
|
||||
if (!*outbuf) {
|
||||
ESP_LOGE(TAG, "System out of memory");
|
||||
esp_local_ctrl_command_cleanup(&resp, &temp_ctx);
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
local_ctrl_message__pack(&resp, *outbuf);
|
||||
esp_local_ctrl_command_cleanup(&resp, &temp_ctx);
|
||||
ESP_LOG_BUFFER_HEX_LEVEL(TAG, *outbuf, *outlen, ESP_LOG_DEBUG);
|
||||
return ESP_OK;
|
||||
}
|
153
components/esp_local_ctrl/src/esp_local_ctrl_priv.h
Normal file
153
components/esp_local_ctrl/src/esp_local_ctrl_priv.h
Normal file
|
@ -0,0 +1,153 @@
|
|||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <esp_err.h>
|
||||
#include <protocomm.h>
|
||||
#include <esp_local_ctrl.h>
|
||||
|
||||
/**
|
||||
* @brief `esp_local_ctrl` transport specific structure
|
||||
*
|
||||
* Every supported transport layer should have the following functions
|
||||
* implemented for starting, stopping and configuring a protocomm service
|
||||
*/
|
||||
struct esp_local_ctrl_transport {
|
||||
/**
|
||||
* Handler for starting a protocomm service as per specified configuration
|
||||
*/
|
||||
esp_err_t (*start_service) (protocomm_t *pc,
|
||||
const esp_local_ctrl_transport_config_t *config);
|
||||
|
||||
/**
|
||||
* Handler for stopping a protocomm service
|
||||
*/
|
||||
void (*stop_service) (protocomm_t *pc);
|
||||
|
||||
/**
|
||||
* Handler for creating a copy of the transport specific configuration
|
||||
*/
|
||||
esp_err_t (*copy_config) (esp_local_ctrl_transport_config_t *dest_config,
|
||||
const esp_local_ctrl_transport_config_t *src_config);
|
||||
|
||||
/**
|
||||
* Handler for allocating resources corresponding to a protocomm endpoint.
|
||||
* Usually when adding a new endpoint `protocomm_endpoint_add()` API is used,
|
||||
* but the transport layer may need to perform resource allocation for
|
||||
* each endpoint, prior to starting the protocomm instance. This handler
|
||||
* is useful in that case, as it is called before `start_service()`.
|
||||
*/
|
||||
esp_err_t (*declare_ep) (esp_local_ctrl_transport_config_t *config,
|
||||
const char *ep_name, uint16_t ep_uuid);
|
||||
|
||||
/**
|
||||
* Handler for freeing a transport specific configuration
|
||||
*/
|
||||
void (*free_config) (esp_local_ctrl_transport_config_t *config);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Protocomm handler for `esp_local_ctrl`
|
||||
*
|
||||
* This is the handler which is responsible for processing incoming requests
|
||||
* over a protocomm channel, then invokes one of the following functions
|
||||
* depending upon the request type:
|
||||
* - `esp_local_ctrl_get_prop_count()`
|
||||
* - `esp_local_ctrl_get_prop_values()`
|
||||
* -` esp_local_ctrl_set_prop_values()`
|
||||
* The output of the above functions are used to form the response messages
|
||||
* corresponding to request types. The formed response messages are packed and
|
||||
* sent back via the protocomm channel.
|
||||
*
|
||||
* @param[in] session_id A number to identify an ongoing session between
|
||||
* device and client
|
||||
* @param[in] inbuf Buffer which holds serialized / packed request data
|
||||
* @param[in] inlen Length of input buffer
|
||||
* @param[out] outbuf Buffer which holds serialized / packed response data
|
||||
* @param[out] outlen Length of output buffer
|
||||
* @param[in] priv_data Private data associated with `esp_local_ctrl` endpoint
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : Success
|
||||
* - ESP_FAIL : Failure
|
||||
*/
|
||||
esp_err_t esp_local_ctrl_data_handler(uint32_t session_id, const uint8_t *inbuf, ssize_t inlen,
|
||||
uint8_t **outbuf, ssize_t *outlen, void *priv_data);
|
||||
|
||||
/**
|
||||
* @brief Use this for obtaining total number of properties registered
|
||||
* with `esp_local_ctrl` service
|
||||
*
|
||||
* @param[out] count Pointer to variable where the result is to be stored
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : Success
|
||||
* - ESP_FAIL : Failure
|
||||
*/
|
||||
esp_err_t esp_local_ctrl_get_prop_count(size_t *count);
|
||||
|
||||
/**
|
||||
* @brief Get descriptions and values of multiple properties at the same time.
|
||||
* The properties are requested by indices. This internally calls the
|
||||
* `get_prop_values` handler specified in the `esp_local_ctrl_handlers_t`
|
||||
* structure. Since `get_prop_values` accepts property structure, the
|
||||
* indices are first converted to the corresponding `esp_local_ctrl_prop_t`
|
||||
* internally.
|
||||
*
|
||||
* @param[in] total_indices The number of elements in the `indices` array argument
|
||||
* @param[in] indices An array of indices, that specify which properties to get
|
||||
* @param[out] props A pre-allocated array of empty property structures, elements of
|
||||
* which are to be populated with names, types and flags of those
|
||||
* properties which correspond to the provided indices
|
||||
* @param[out] values A pre-allocated array of empty value structures, elements of
|
||||
* which are to be populated with values and sizes of those
|
||||
* properties which correspond to the provided indices
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : Success
|
||||
* - ESP_FAIL : Failure
|
||||
*/
|
||||
esp_err_t esp_local_ctrl_get_prop_values(size_t total_indices, uint32_t *indices,
|
||||
esp_local_ctrl_prop_t *props,
|
||||
esp_local_ctrl_prop_val_t *values);
|
||||
|
||||
/**
|
||||
* @brief Set values of multiple properties at the same time. The properties to
|
||||
* set are specified by indices. This internally calls the `set_prop_values`
|
||||
* handler specified in the `esp_local_ctrl_handlers_t` structure. Since
|
||||
* `set_prop_values` accepts property structures, the indices are first
|
||||
* converted to the corresponding `esp_local_ctrl_prop_t` internally.
|
||||
*
|
||||
* @param[in] total_indices The number of elements in the `indices` array argument
|
||||
* @param[in] indices An array of indices, that specify which properties to set
|
||||
* @param[in] values A array of values. Every value should have the correct
|
||||
* size, if it is for setting a fixed size property, else
|
||||
* error will be generated and none of the properties will
|
||||
* be set to any of the given values
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : Success
|
||||
* - ESP_FAIL : Failure
|
||||
*/
|
||||
esp_err_t esp_local_ctrl_set_prop_values(size_t total_indices, uint32_t *indices,
|
||||
const esp_local_ctrl_prop_val_t *values);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
140
components/esp_local_ctrl/src/esp_local_ctrl_transport_ble.c
Normal file
140
components/esp_local_ctrl/src/esp_local_ctrl_transport_ble.c
Normal file
|
@ -0,0 +1,140 @@
|
|||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <esp_err.h>
|
||||
#include <esp_log.h>
|
||||
|
||||
#include <protocomm_ble.h>
|
||||
#include <esp_local_ctrl.h>
|
||||
|
||||
#include "esp_local_ctrl_priv.h"
|
||||
|
||||
#define LOCAL_CTRL_VERSION "v1.0"
|
||||
|
||||
static const char *TAG = "esp_local_ctrl_transport_ble";
|
||||
|
||||
static esp_err_t start_ble_transport(protocomm_t *pc, const esp_local_ctrl_transport_config_t *config)
|
||||
{
|
||||
if (!config || !config->ble) {
|
||||
ESP_LOGE(TAG, "NULL configuration provided");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
return protocomm_ble_start(pc, config->ble);
|
||||
}
|
||||
|
||||
static void stop_ble_transport(protocomm_t *pc)
|
||||
{
|
||||
protocomm_ble_stop(pc);
|
||||
}
|
||||
|
||||
static esp_err_t copy_ble_config(esp_local_ctrl_transport_config_t *dest_config, const esp_local_ctrl_transport_config_t *src_config)
|
||||
{
|
||||
if (!dest_config || !src_config || !src_config->ble) {
|
||||
ESP_LOGE(TAG, "NULL arguments provided");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
dest_config->ble = calloc(1, sizeof(protocomm_ble_config_t));
|
||||
if (!dest_config->ble) {
|
||||
ESP_LOGE(TAG, "Failed to allocate memory for BLE transport config");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
/* Copy BLE device name */
|
||||
memcpy(dest_config->ble->device_name,
|
||||
src_config->ble->device_name,
|
||||
sizeof(src_config->ble->device_name));
|
||||
|
||||
/* Copy Service UUID */
|
||||
memcpy(dest_config->ble->service_uuid,
|
||||
src_config->ble->service_uuid,
|
||||
sizeof(src_config->ble->service_uuid));
|
||||
|
||||
dest_config->ble->nu_lookup_count = 0;
|
||||
if (src_config->ble->nu_lookup_count) {
|
||||
/* Copy any provided name-uuid lookup table */
|
||||
dest_config->ble->nu_lookup = calloc(src_config->ble->nu_lookup_count,
|
||||
sizeof(protocomm_ble_name_uuid_t));
|
||||
if (!dest_config->ble->nu_lookup) {
|
||||
ESP_LOGE(TAG, "Failed to allocate memory for BLE characteristic names");
|
||||
free(dest_config->ble);
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
for (uint16_t i = 0; i < src_config->ble->nu_lookup_count; i++) {
|
||||
dest_config->ble->nu_lookup[i].uuid = src_config->ble->nu_lookup[i].uuid;
|
||||
if (!src_config->ble->nu_lookup[i].name) {
|
||||
ESP_LOGE(TAG, "Endpoint name cannot be null");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
dest_config->ble->nu_lookup[i].name = strdup(src_config->ble->nu_lookup[i].name);
|
||||
if (!dest_config->ble->nu_lookup[i].name) {
|
||||
ESP_LOGE(TAG, "Failed to allocate memory for endpoint name");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
dest_config->ble->nu_lookup_count++;
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t declare_endpoint(esp_local_ctrl_transport_config_t *config, const char *ep_name, uint16_t ep_uuid)
|
||||
{
|
||||
if (!config || !config->ble) {
|
||||
ESP_LOGE(TAG, "NULL configuration provided");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
protocomm_ble_name_uuid_t *nu_lookup = realloc(config->ble->nu_lookup,
|
||||
(config->ble->nu_lookup_count + 1)
|
||||
* sizeof(protocomm_ble_name_uuid_t));
|
||||
if (!nu_lookup) {
|
||||
ESP_LOGE(TAG, "Failed to allocate memory for new endpoint entry");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
config->ble->nu_lookup = nu_lookup;
|
||||
nu_lookup[config->ble->nu_lookup_count].uuid = ep_uuid;
|
||||
nu_lookup[config->ble->nu_lookup_count].name = strdup(ep_name);
|
||||
if (!nu_lookup[config->ble->nu_lookup_count].name) {
|
||||
ESP_LOGE(TAG, "Failed to allocate memory for new endpoint name");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
config->ble->nu_lookup_count++;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void free_config(esp_local_ctrl_transport_config_t *config)
|
||||
{
|
||||
if (config && config->ble) {
|
||||
for (unsigned int i = 0; i < config->ble->nu_lookup_count; i++) {
|
||||
free((void*) config->ble->nu_lookup[i].name);
|
||||
}
|
||||
free(config->ble->nu_lookup);
|
||||
free(config->ble);
|
||||
config->ble = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const esp_local_ctrl_transport_t *esp_local_ctrl_get_transport_ble(void)
|
||||
{
|
||||
static const esp_local_ctrl_transport_t tp = {
|
||||
.start_service = start_ble_transport,
|
||||
.stop_service = stop_ble_transport,
|
||||
.copy_config = copy_ble_config,
|
||||
.declare_ep = declare_endpoint,
|
||||
.free_config = free_config
|
||||
};
|
||||
return &tp;
|
||||
};
|
128
components/esp_local_ctrl/src/esp_local_ctrl_transport_httpd.c
Normal file
128
components/esp_local_ctrl/src/esp_local_ctrl_transport_httpd.c
Normal file
|
@ -0,0 +1,128 @@
|
|||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <esp_err.h>
|
||||
#include <esp_log.h>
|
||||
|
||||
#include <mdns.h>
|
||||
#include <protocomm_httpd.h>
|
||||
#include <esp_local_ctrl.h>
|
||||
#include <esp_https_server.h>
|
||||
|
||||
#include "esp_local_ctrl_priv.h"
|
||||
|
||||
#define LOCAL_CTRL_VERSION "v1.0"
|
||||
|
||||
static const char *TAG = "esp_local_ctrl_transport_httpd";
|
||||
|
||||
static httpd_handle_t server_handle = NULL;
|
||||
|
||||
static esp_err_t start_httpd_transport(protocomm_t *pc, const esp_local_ctrl_transport_config_t *config)
|
||||
{
|
||||
if (!config || !config->httpd) {
|
||||
ESP_LOGE(TAG, "NULL configuration provided");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* Extract configured port */
|
||||
uint16_t port = (
|
||||
config->httpd->transport_mode == HTTPD_SSL_TRANSPORT_SECURE ?
|
||||
config->httpd->port_secure :
|
||||
config->httpd->port_insecure
|
||||
);
|
||||
|
||||
esp_err_t err = mdns_service_add("Local Control Service", "_esp_local_ctrl",
|
||||
"_tcp", port, NULL, 0);
|
||||
if (err != ESP_OK) {
|
||||
/* mDNS is not mandatory for provisioning to work,
|
||||
* so print warning and return without failure */
|
||||
ESP_LOGW(TAG, "Error adding mDNS service! Check if mDNS is running");
|
||||
} else {
|
||||
/* Information to identify the roles of the various
|
||||
* protocomm endpoint URIs provided by the service */
|
||||
err |= mdns_service_txt_item_set("_esp_local_ctrl", "_tcp",
|
||||
"version_endpoint", "/esp_local_ctrl/version");
|
||||
err |= mdns_service_txt_item_set("_esp_local_ctrl", "_tcp",
|
||||
"session_endpoint", "/esp_local_ctrl/session");
|
||||
err |= mdns_service_txt_item_set("_esp_local_ctrl", "_tcp",
|
||||
"control_endpoint", "/esp_local_ctrl/control");
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Error adding mDNS service text item");
|
||||
}
|
||||
}
|
||||
|
||||
err = httpd_ssl_start(&server_handle, config->httpd);
|
||||
if (ESP_OK != err) {
|
||||
ESP_LOGE(TAG, "Error starting HTTPS service!");
|
||||
mdns_service_remove("_esp_local_ctrl", "_tcp");
|
||||
return err;
|
||||
}
|
||||
|
||||
protocomm_httpd_config_t pc_conf = {
|
||||
.ext_handle_provided = true,
|
||||
.data = {
|
||||
.handle = &server_handle
|
||||
}
|
||||
};
|
||||
|
||||
return protocomm_httpd_start(pc, &pc_conf);
|
||||
}
|
||||
|
||||
static void stop_httpd_transport(protocomm_t *pc)
|
||||
{
|
||||
mdns_service_remove("_esp_local_ctrl", "_tcp");
|
||||
protocomm_httpd_stop(pc);
|
||||
httpd_ssl_stop(server_handle);
|
||||
server_handle = NULL;
|
||||
}
|
||||
|
||||
static esp_err_t copy_httpd_config(esp_local_ctrl_transport_config_t *dest_config, const esp_local_ctrl_transport_config_t *src_config)
|
||||
{
|
||||
if (!dest_config || !src_config || !src_config->httpd) {
|
||||
ESP_LOGE(TAG, "NULL configuration provided");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
dest_config->httpd = calloc(1, sizeof(httpd_ssl_config_t));
|
||||
if (!dest_config->httpd) {
|
||||
ESP_LOGE(TAG, "Failed to allocate memory for HTTPD transport config");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
memcpy(dest_config->httpd,
|
||||
src_config->httpd,
|
||||
sizeof(httpd_ssl_config_t));
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void free_config(esp_local_ctrl_transport_config_t *config)
|
||||
{
|
||||
if (config && config->httpd) {
|
||||
free(config->httpd);
|
||||
config->httpd = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const esp_local_ctrl_transport_t *esp_local_ctrl_get_transport_httpd(void)
|
||||
{
|
||||
static const esp_local_ctrl_transport_t tp = {
|
||||
.start_service = start_httpd_transport,
|
||||
.stop_service = stop_httpd_transport,
|
||||
.copy_config = copy_httpd_config,
|
||||
.declare_ep = NULL,
|
||||
.free_config = free_config
|
||||
};
|
||||
return &tp;
|
||||
};
|
|
@ -48,7 +48,7 @@ typedef struct name_uuid {
|
|||
/**
|
||||
* @brief Config parameters for protocomm BLE service
|
||||
*/
|
||||
typedef struct {
|
||||
typedef struct protocomm_ble_config {
|
||||
/**
|
||||
* BLE device name being broadcast at the time of provisioning
|
||||
*/
|
||||
|
|
|
@ -107,8 +107,11 @@ INPUT = \
|
|||
../../components/mdns/include/mdns.h \
|
||||
../../components/esp_http_client/include/esp_http_client.h \
|
||||
../../components/esp_websocket_client/include/esp_websocket_client.h \
|
||||
## HTTP / HTTPS Server
|
||||
../../components/esp_http_server/include/esp_http_server.h \
|
||||
../../components/esp_https_server/include/esp_https_server.h \
|
||||
## ESP Local Ctrl
|
||||
../../components/esp_local_ctrl/include/esp_local_ctrl.h \
|
||||
##
|
||||
## Provisioning - API Reference
|
||||
##
|
||||
|
|
206
docs/en/api-reference/protocols/esp_local_ctrl.rst
Normal file
206
docs/en/api-reference/protocols/esp_local_ctrl.rst
Normal file
|
@ -0,0 +1,206 @@
|
|||
ESP Local Control
|
||||
=================
|
||||
|
||||
Overview
|
||||
--------
|
||||
ESP Local Control (**esp_local_ctrl**) component in ESP-IDF provides capability to control an ESP device over Wi-Fi + HTTPS or BLE. It provides access to application defined **properties** that are available for reading / writing via a set of configurable handlers.
|
||||
|
||||
Initialization of the **esp_local_ctrl** service over BLE transport is performed as follows:
|
||||
|
||||
.. highlight:: c
|
||||
|
||||
::
|
||||
|
||||
esp_local_ctrl_config_t config = {
|
||||
.transport = ESP_LOCAL_CTRL_TRANSPORT_BLE,
|
||||
.transport_config = {
|
||||
.ble = & (protocomm_ble_config_t) {
|
||||
.device_name = SERVICE_NAME,
|
||||
.service_uuid = {
|
||||
/* LSB <---------------------------------------
|
||||
* ---------------------------------------> MSB */
|
||||
0x21, 0xd5, 0x3b, 0x8d, 0xbd, 0x75, 0x68, 0x8a,
|
||||
0xb4, 0x42, 0xeb, 0x31, 0x4a, 0x1e, 0x98, 0x3d
|
||||
}
|
||||
}
|
||||
},
|
||||
.handlers = {
|
||||
/* User defined handler functions */
|
||||
.get_prop_values = get_property_values,
|
||||
.set_prop_values = set_property_values,
|
||||
.usr_ctx = NULL,
|
||||
.usr_ctx_free_fn = NULL
|
||||
},
|
||||
/* Maximum number of properties that may be set */
|
||||
.max_properties = 10
|
||||
};
|
||||
|
||||
/* Start esp_local_ctrl service */
|
||||
ESP_ERROR_CHECK(esp_local_ctrl_start(&config));
|
||||
|
||||
|
||||
Similarly for HTTPS transport:
|
||||
|
||||
.. highlight:: c
|
||||
|
||||
::
|
||||
|
||||
/* Set the configuration */
|
||||
httpd_ssl_config_t https_conf = HTTPD_SSL_CONFIG_DEFAULT();
|
||||
|
||||
/* Load server certificate */
|
||||
extern const unsigned char cacert_pem_start[] asm("_binary_cacert_pem_start");
|
||||
extern const unsigned char cacert_pem_end[] asm("_binary_cacert_pem_end");
|
||||
https_conf.cacert_pem = cacert_pem_start;
|
||||
https_conf.cacert_len = cacert_pem_end - cacert_pem_start;
|
||||
|
||||
/* Load server private key */
|
||||
extern const unsigned char prvtkey_pem_start[] asm("_binary_prvtkey_pem_start");
|
||||
extern const unsigned char prvtkey_pem_end[] asm("_binary_prvtkey_pem_end");
|
||||
https_conf.prvtkey_pem = prvtkey_pem_start;
|
||||
https_conf.prvtkey_len = prvtkey_pem_end - prvtkey_pem_start;
|
||||
|
||||
esp_local_ctrl_config_t config = {
|
||||
.transport = ESP_LOCAL_CTRL_TRANSPORT_HTTPD,
|
||||
.transport_config = {
|
||||
.httpd = &https_conf
|
||||
},
|
||||
.handlers = {
|
||||
/* User defined handler functions */
|
||||
.get_prop_values = get_property_values,
|
||||
.set_prop_values = set_property_values,
|
||||
.usr_ctx = NULL,
|
||||
.usr_ctx_free_fn = NULL
|
||||
},
|
||||
/* Maximum number of properties that may be set */
|
||||
.max_properties = 10
|
||||
};
|
||||
|
||||
/* Start esp_local_ctrl service */
|
||||
ESP_ERROR_CHECK(esp_local_ctrl_start(&config));
|
||||
|
||||
|
||||
Creating a property
|
||||
===================
|
||||
|
||||
Now that we know how to start the **esp_local_ctrl** service, let's add a property to it. Each property must have a unique `name` (string), a `type` (e.g. enum), `flags` (bit fields) and `size`.
|
||||
|
||||
The `size` is to be kept 0, if we want our property value to be of variable length (e.g. if its a string or bytestream). For fixed length property value data-types, like int, float, etc., setting the `size` field to the right value, helps **esp_local_ctrl** to perform internal checks on arguments received with write requests.
|
||||
|
||||
The interpretation of `type` and `flags` fields is totally upto the application, hence they may be used as enumerations, bitfields, or even simple integers. One way is to use `type` values to classify properties, while `flags` to specify characteristics of a property.
|
||||
|
||||
Here is an example property which is to function as a timestamp. It is assumed that the application defines `TYPE_TIMESTAMP` and `READONLY`, which are used for setting the `type` and `flags` fields here.
|
||||
|
||||
.. highlight:: c
|
||||
|
||||
::
|
||||
|
||||
/* Create a timestamp property */
|
||||
esp_local_ctrl_prop_t timestamp = {
|
||||
.name = "timestamp",
|
||||
.type = TYPE_TIMESTAMP,
|
||||
.size = sizeof(int32_t),
|
||||
.flags = READONLY,
|
||||
.ctx = func_get_time,
|
||||
.ctx_free_fn = NULL
|
||||
};
|
||||
|
||||
/* Now register the property */
|
||||
esp_local_ctrl_add_property(×tamp);
|
||||
|
||||
|
||||
Also notice that there is a ctx field, which is set to point to some custom `func_get_time()`. This can be used inside the property get / set handlers to retrieve timestamp.
|
||||
|
||||
Here is an example of `get_prop_values()` handler, which is used for retrieving the timestamp.
|
||||
|
||||
.. highlight:: c
|
||||
|
||||
::
|
||||
|
||||
static esp_err_t get_property_values(size_t props_count,
|
||||
const esp_local_ctrl_prop_t *props,
|
||||
esp_local_ctrl_prop_val_t *prop_values,
|
||||
void *usr_ctx)
|
||||
{
|
||||
for (uint32_t i = 0; i < props_count; i++) {
|
||||
ESP_LOGI(TAG, "Reading %s", props[i].name);
|
||||
if (props[i].type == TYPE_TIMESTAMP) {
|
||||
/* Obtain the timer function from ctx */
|
||||
int32_t (*func_get_time)(void) = props[i].ctx;
|
||||
|
||||
/* Use static variable for saving the value.
|
||||
* This is essential because the value has to be
|
||||
* valid even after this function returns.
|
||||
* Alternative is to use dynamic allocation
|
||||
* and set the free_fn field */
|
||||
static int32_t ts = func_get_time();
|
||||
prop_values[i].data = &ts;
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
Here is an example of `set_prop_values()` handler. Notice how we restrict from writing to read-only properties.
|
||||
|
||||
.. highlight:: c
|
||||
|
||||
::
|
||||
|
||||
static esp_err_t set_property_values(size_t props_count,
|
||||
const esp_local_ctrl_prop_t *props,
|
||||
const esp_local_ctrl_prop_val_t *prop_values,
|
||||
void *usr_ctx)
|
||||
{
|
||||
for (uint32_t i = 0; i < props_count; i++) {
|
||||
if (props[i].flags & READONLY) {
|
||||
ESP_LOGE(TAG, "Cannot write to read-only property %s", props[i].name);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Setting %s", props[i].name);
|
||||
|
||||
/* For keeping it simple, lets only log the incoming data */
|
||||
ESP_LOG_BUFFER_HEX_LEVEL(TAG, prop_values[i].data,
|
||||
prop_values[i].size, ESP_LOG_INFO);
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
For complete example see :example:`protocols/esp_local_ctrl`
|
||||
|
||||
Client Side Implementation
|
||||
==========================
|
||||
|
||||
The client side implementation will have establish a protocomm session with the device first, over the supported mode of transport, and then send and receive protobuf messages understood by the **esp_local_ctrl** service. The service will translate these messages into requests and then call the appropriate handlers (set / get). Then, the generated response for each handler is again packed into a protobuf message and transmitted back to the client.
|
||||
|
||||
See below the various protobuf messages understood by the **esp_local_ctrl** service:
|
||||
|
||||
1. `get_prop_count` : This should simply return the total number of properties supported by the service
|
||||
2. `get_prop_values` : This accepts an array of indices and should return the information (name, type, flags) and values of the properties corresponding to those indices
|
||||
3. `set_prop_values` : This accepts an array of indices and an array of new values, which are used for setting the values of the properties corresponding to the indices
|
||||
|
||||
Note that indices may or may not be the same for a property, across multiple sessions. Therefore, the client must only use the names of the properties to uniquely identify them. So, every time a new session is established, the client should first call `get_prop_count` and then `get_prop_values`, hence form an index to name mapping for all properties. Now when calling `set_prop_values` for a set of properties, it must first convert the names to indexes, using the created mapping. As emphasized earlier, the client must refresh the index to name mapping every time a new session is established with the same device.
|
||||
|
||||
The various protocomm endpoints provided by **esp_local_ctrl** are listed below:
|
||||
|
||||
.. list-table:: Endpoints provided by ESP Local Control
|
||||
:widths: 10 25 50
|
||||
:header-rows: 1
|
||||
|
||||
* - Endpoint Name (BLE + GATT Server)
|
||||
- URI (HTTPS Server + mDNS)
|
||||
- Description
|
||||
* - esp_local_ctrl/version
|
||||
- https://<mdns-hostname>.local/esp_local_ctrl/version
|
||||
- Endpoint used for retrieving version string
|
||||
* - esp_local_ctrl/control
|
||||
- https://<mdns-hostname>.local/esp_local_ctrl/control
|
||||
- Endpoint used for sending / receiving control messages
|
||||
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
|
||||
.. include:: /_build/inc/esp_local_ctrl.inc
|
|
@ -14,6 +14,7 @@ Application Protocols
|
|||
ASIO <asio>
|
||||
ESP-MQTT <mqtt>
|
||||
Modbus <modbus>
|
||||
Local Control <esp_local_ctrl>
|
||||
|
||||
Code examples for this API section are provided in the :example:`protocols` directory of ESP-IDF examples.
|
||||
|
||||
|
|
1
docs/zh_CN/api-reference/protocols/esp_local_ctrl.rst
Normal file
1
docs/zh_CN/api-reference/protocols/esp_local_ctrl.rst
Normal file
|
@ -0,0 +1 @@
|
|||
.. include:: ../../../en/api-reference/protocols/esp_local_ctrl.rst
|
|
@ -14,6 +14,7 @@
|
|||
ASIO <asio>
|
||||
ESP-MQTT <mqtt>
|
||||
Modbus slave <modbus>
|
||||
Local Control <esp_local_ctrl>
|
||||
|
||||
此 API 部分的示例代码在 ESP-IDF 示例工程的 :example:`protocols` 目录下提供。
|
||||
|
||||
|
|
10
examples/protocols/esp_local_ctrl/CMakeLists.txt
Normal file
10
examples/protocols/esp_local_ctrl/CMakeLists.txt
Normal file
|
@ -0,0 +1,10 @@
|
|||
# The following lines of boilerplate have to be in your project's CMakeLists
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
# (Not part of the boilerplate)
|
||||
# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection.
|
||||
set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(esp_local_ctrl)
|
9
examples/protocols/esp_local_ctrl/Makefile
Normal file
9
examples/protocols/esp_local_ctrl/Makefile
Normal file
|
@ -0,0 +1,9 @@
|
|||
#
|
||||
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
|
||||
# project subdirectory.
|
||||
#
|
||||
|
||||
PROJECT_NAME := esp_local_ctrl
|
||||
|
||||
include $(IDF_PATH)/make/project.mk
|
||||
|
93
examples/protocols/esp_local_ctrl/README.md
Normal file
93
examples/protocols/esp_local_ctrl/README.md
Normal file
|
@ -0,0 +1,93 @@
|
|||
# ESP Local Control using HTTPS server
|
||||
|
||||
This example creates a `esp_local_ctrl` service over HTTPS transport, for securely controlling the device over local network. In this case the device name is resolved through `mDNS`, which in this example is `my_esp_ctrl_device.local`.
|
||||
|
||||
See the `esp_local_ctrl` component documentation for details.
|
||||
|
||||
Before using the example, run `make menuconfig` (or `idf.py menuconfig` if using CMake build system) to configure Wi-Fi or Ethernet. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../README.md) for more details.
|
||||
|
||||
## Client Side Implementation
|
||||
|
||||
A python test script `scripts/esp_local_ctrl.py` has been provided for as a client side application for controlling the device over the same Wi-Fi network. The script relies on a pre-generated `main/certs/rootCA.pem` to verify the server certificate. The server side private key and certificate can also be found under `main/certs`, namely `prvtkey.pem` and `cacert.pem`.
|
||||
|
||||
After configuring the Wi-Fi, flashing and booting the device, run:
|
||||
|
||||
```
|
||||
python scripts/esp_local_ctrl.py
|
||||
```
|
||||
Sample output:
|
||||
|
||||
```
|
||||
python2 scripts/esp_local_ctrl.py
|
||||
|
||||
==== Acquiring properties information ====
|
||||
|
||||
==== Acquired properties information ====
|
||||
|
||||
==== Available Properties ====
|
||||
S.N. Name Type Flags Value
|
||||
[ 1] timestamp (us) TIME(us) Read-Only 168561481
|
||||
[ 2] property1 INT32 123456
|
||||
[ 3] property2 BOOLEAN Read-Only True
|
||||
[ 4] property3 STRING
|
||||
|
||||
Select properties to set (0 to re-read, 'q' to quit) : 0
|
||||
|
||||
==== Available Properties ====
|
||||
S.N. Name Type Flags Value
|
||||
[ 1] timestamp (us) TIME(us) Read-Only 22380117
|
||||
[ 2] property1 INT32 123456
|
||||
[ 3] property2 BOOLEAN Read-Only False
|
||||
[ 4] property3 STRING
|
||||
|
||||
Select properties to set (0 to re-read, 'q' to quit) : 2,4
|
||||
Enter value to set for property (property1) : -5555
|
||||
Enter value to set for property (property3) : hello world!
|
||||
|
||||
==== Available Properties ====
|
||||
S.N. Name Type Flags Value
|
||||
[ 1] timestamp (us) TIME(us) Read-Only 55110859
|
||||
[ 2] property1 INT32 -5555
|
||||
[ 3] property2 BOOLEAN Read-Only False
|
||||
[ 4] property3 STRING hello world!
|
||||
|
||||
Select properties to set (0 to re-read, 'q' to quit) : q
|
||||
Quitting...
|
||||
```
|
||||
|
||||
The script also allows to connect over BLE, and provide a custom service name. To display the list of supported parameters, run:
|
||||
|
||||
```
|
||||
python scripts/esp_local_ctrl.py --help
|
||||
```
|
||||
|
||||
## Certificates
|
||||
|
||||
You can generate a new server certificate using the OpenSSL command line tool.
|
||||
|
||||
For the purpose of this example, lets generate a rootCA, which we will use to sign the server certificates and which the client will use to verify the server certificate during SSL handshake. You will need to set a password for encrypting the generated `rootkey.pem`.
|
||||
|
||||
```
|
||||
openssl req -new -x509 -subj "/CN=root" -days 3650 -sha256 -out rootCA.pem -keyout rootkey.pem
|
||||
```
|
||||
|
||||
Now generate a certificate signing request for the server, along with its private key `prvtkey.pem`.
|
||||
|
||||
```
|
||||
openssl req -newkey rsa:2048 -nodes -keyout prvtkey.pem -days 3650 -out server.csr -subj "/CN=my_esp_ctrl_device.local"
|
||||
```
|
||||
|
||||
Now use the previously generated rootCA to process the server's certificate signing request, and generate a signed certificate `cacert.pem`. The password set for encrypting `rootkey.pem` earlier, has to be entered during this step.
|
||||
|
||||
```
|
||||
openssl x509 -req -in server.csr -CA rootCA.pem -CAkey rootkey.pem -CAcreateserial -out cacert.pem -days 500 -sha256
|
||||
```
|
||||
|
||||
Now that we have `rootCA.pem`, `cacert.pem` and `prvtkey.pem`, copy these into main/certs. Note that only the server related files (`cacert.pem` and `prvtkey.pem`) are embedded into the firmware.
|
||||
|
||||
Expiry time and metadata fields can be adjusted in the invocation.
|
||||
|
||||
Please see the `openssl` man pages (man `openssl-req`) for more details.
|
||||
|
||||
It is **strongly recommended** to not reuse the example certificate in your application;
|
||||
it is included only for demonstration.
|
8
examples/protocols/esp_local_ctrl/main/CMakeLists.txt
Normal file
8
examples/protocols/esp_local_ctrl/main/CMakeLists.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
set(COMPONENT_SRCS "app_main.c" "esp_local_ctrl_service.c")
|
||||
set(COMPONENT_ADD_INCLUDEDIRS ".")
|
||||
|
||||
set(COMPONENT_EMBED_TXTFILES
|
||||
"certs/cacert.pem"
|
||||
"certs/prvtkey.pem")
|
||||
|
||||
register_component()
|
20
examples/protocols/esp_local_ctrl/main/Kconfig.projbuild
Normal file
20
examples/protocols/esp_local_ctrl/main/Kconfig.projbuild
Normal file
|
@ -0,0 +1,20 @@
|
|||
menu "Example Configuration"
|
||||
|
||||
config ESP_WIFI_SSID
|
||||
string "WiFi SSID"
|
||||
default "myssid"
|
||||
help
|
||||
SSID (network name) for the example to connect to.
|
||||
|
||||
config ESP_WIFI_PASSWORD
|
||||
string "WiFi Password"
|
||||
default "mypassword"
|
||||
help
|
||||
WiFi password (WPA or WPA2) for the example to use.
|
||||
|
||||
config ESP_MAXIMUM_RETRY
|
||||
int "Maximum retry"
|
||||
default 5
|
||||
help
|
||||
Set the Maximum retry to avoid station reconnecting to the AP unlimited when the AP is really inexistent.
|
||||
endmenu
|
111
examples/protocols/esp_local_ctrl/main/app_main.c
Normal file
111
examples/protocols/esp_local_ctrl/main/app_main.c
Normal file
|
@ -0,0 +1,111 @@
|
|||
/* Local Ctrl Example
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_log.h"
|
||||
#include "nvs_flash.h"
|
||||
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/sys.h"
|
||||
|
||||
/* The examples use WiFi configuration that you can set via 'make menuconfig'.
|
||||
|
||||
If you'd rather not, just change the below entries to strings with
|
||||
the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid"
|
||||
*/
|
||||
#define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID
|
||||
#define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD
|
||||
#define EXAMPLE_ESP_MAXIMUM_RETRY CONFIG_ESP_MAXIMUM_RETRY
|
||||
|
||||
/* FreeRTOS event group to signal when we are connected*/
|
||||
static EventGroupHandle_t s_wifi_event_group;
|
||||
|
||||
/* The event group allows multiple bits for each event, but we only care about one event
|
||||
* - are we connected to the AP with an IP? */
|
||||
const int WIFI_CONNECTED_BIT = BIT0;
|
||||
|
||||
static const char *TAG = "local_ctrl_example";
|
||||
|
||||
static int s_retry_num = 0;
|
||||
|
||||
static void event_handler(void* arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void* event_data)
|
||||
{
|
||||
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
|
||||
esp_wifi_connect();
|
||||
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
|
||||
if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) {
|
||||
esp_wifi_connect();
|
||||
xEventGroupClearBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
|
||||
s_retry_num++;
|
||||
ESP_LOGI(TAG, "retry to connect to the AP");
|
||||
}
|
||||
ESP_LOGI(TAG,"connect to the AP fail");
|
||||
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
|
||||
ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
|
||||
ESP_LOGI(TAG, "got ip:%s",
|
||||
ip4addr_ntoa(&event->ip_info.ip));
|
||||
s_retry_num = 0;
|
||||
xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
void wifi_init_sta()
|
||||
{
|
||||
s_wifi_event_group = xEventGroupCreate();
|
||||
|
||||
tcpip_adapter_init();
|
||||
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL));
|
||||
|
||||
wifi_config_t wifi_config = {
|
||||
.sta = {
|
||||
.ssid = EXAMPLE_ESP_WIFI_SSID,
|
||||
.password = EXAMPLE_ESP_WIFI_PASS
|
||||
},
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) );
|
||||
ESP_ERROR_CHECK(esp_wifi_start() );
|
||||
|
||||
ESP_LOGI(TAG, "wifi_init_sta finished.");
|
||||
ESP_LOGI(TAG, "connect to ap SSID:%s password:%s",
|
||||
EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);
|
||||
}
|
||||
|
||||
/* Function responsible for configuring and starting the esp_local_ctrl service.
|
||||
* See local_ctrl_service.c for implementation */
|
||||
extern void start_esp_local_ctrl_service(void);
|
||||
|
||||
void app_main()
|
||||
{
|
||||
//Initialize NVS
|
||||
esp_err_t ret = nvs_flash_init();
|
||||
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
ret = nvs_flash_init();
|
||||
}
|
||||
ESP_ERROR_CHECK(ret);
|
||||
|
||||
ESP_LOGI(TAG, "ESP_WIFI_MODE_STA");
|
||||
wifi_init_sta();
|
||||
start_esp_local_ctrl_service();
|
||||
}
|
17
examples/protocols/esp_local_ctrl/main/certs/cacert.pem
Normal file
17
examples/protocols/esp_local_ctrl/main/certs/cacert.pem
Normal file
|
@ -0,0 +1,17 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIICuTCCAaECFFnose4o8INWoH5BA5TOCz2e9zAOMA0GCSqGSIb3DQEBCwUAMA8x
|
||||
DTALBgNVBAMMBHJvb3QwHhcNMTkwNjI1MTkyMTU4WhcNMjAxMTA2MTkyMTU4WjAj
|
||||
MSEwHwYDVQQDDBhteV9lc3BfY3RybF9kZXZpY2UubG9jYWwwggEiMA0GCSqGSIb3
|
||||
DQEBAQUAA4IBDwAwggEKAoIBAQDY2B46AdNfrJRGgHy7cECmEMxOWn8CvygC2g77
|
||||
Gog/DWxkqaEksBJt8qQcqGLumv+HfXE4erNPGU+RTNal+zMXHliIMVi2IiVw5uuC
|
||||
Tze7cK28HDvC5noED/TWGSJIaCQAUP/GdE0sqCJ1O7W0IhrZBjsmen4d0nPrInCz
|
||||
X9YDOfaWxdwnBJ3q0+7ZTSWETbDrKUJ0tgPe6m96j/zRYCtCo2Dpu/pZvPyIvXwT
|
||||
zt6enB8cwDtk35KwOrscAJGNqkCRyKaNvOSuHv9/02vpzwqk/J6JbIcXFVNuYSPg
|
||||
0wb0iltMqn0IwC3KyaI9gBg0VexMeOhFV/gRt8dvEYehtTB7AgMBAAEwDQYJKoZI
|
||||
hvcNAQELBQADggEBAFnKbunoBvKun4hJV4sp0ztDKpjOJevsQp3X36egm4NGCpEj
|
||||
cdHxEmAvmeiu/12C6OfvFmZ/QiqNmp2gihpy4DiuxWnI+iC9JjfYuWTsKj+xcVkw
|
||||
4IvGZbFtE9YW+XwNWqXPi1urVk9wKpZmCWpWgFWnLwPgIQs16+y3+CQF3vefX9Iy
|
||||
aqmYrTYkBpLEXRjYJeU253mvN6FXQgOoPuld1Ph+IO+DUEJr+zeM88xkmjAo37ej
|
||||
VkCMXA5HqdT64HuZC1RnnbpP76assgFW2oTycG28jzHSYjuK2q1PIoZtzpW8Sv7i
|
||||
jn17E6ryf24r1DVkQByR54rvzl6Qu3M8TJe6EYI=
|
||||
-----END CERTIFICATE-----
|
28
examples/protocols/esp_local_ctrl/main/certs/prvtkey.pem
Normal file
28
examples/protocols/esp_local_ctrl/main/certs/prvtkey.pem
Normal file
|
@ -0,0 +1,28 @@
|
|||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDY2B46AdNfrJRG
|
||||
gHy7cECmEMxOWn8CvygC2g77Gog/DWxkqaEksBJt8qQcqGLumv+HfXE4erNPGU+R
|
||||
TNal+zMXHliIMVi2IiVw5uuCTze7cK28HDvC5noED/TWGSJIaCQAUP/GdE0sqCJ1
|
||||
O7W0IhrZBjsmen4d0nPrInCzX9YDOfaWxdwnBJ3q0+7ZTSWETbDrKUJ0tgPe6m96
|
||||
j/zRYCtCo2Dpu/pZvPyIvXwTzt6enB8cwDtk35KwOrscAJGNqkCRyKaNvOSuHv9/
|
||||
02vpzwqk/J6JbIcXFVNuYSPg0wb0iltMqn0IwC3KyaI9gBg0VexMeOhFV/gRt8dv
|
||||
EYehtTB7AgMBAAECggEBAJSvM6Kgp9fdVNo2tdAsOxfjQsOjB53RhtTVwhnpamyZ
|
||||
fq5TJZwrYqejDWZdC2ECRJ4ZpG2OrK5a85T0s+Whpbl/ZEMWWvaf2T5eCDQUr2lF
|
||||
7MqkLVIJiLaKXl4DY990EONqpsbj7hrluqLZ61B1ZiVTQXGz4g/+wt8CgXZtCyiv
|
||||
7XOTTmQueugq4f54JBX5isdB7/xLaXV3kycaEK1b6ZVFYB3ii5IKKsX7RK/ksA6O
|
||||
fRrQ8702prqphPfbjZ9wPHif/zLiyiF2FG6OX1Y3aZe1npRsvuH2c3M2h+HGAQUR
|
||||
3lDxMTNbsE8E+XKZFVAVdMqot2RfxENSHoJHcp1R2YECgYEA9qe1+eOZKd0w5lC1
|
||||
PuG6FLAAbK1nuv/ovESEHtILTLFkMijgAqcWjtp1klS86IBJLnjv+GYxZu2n1WI9
|
||||
QLnh++NNTjRGCMM2Adf5SBJ/5F85rpgzz7Yur1guqkUQx/2dmErOaWQ4IO304VlM
|
||||
vrJB8+XmAiysEgJOkK0Mx8xRVcECgYEA4Q9GBADLryvwjisp/PdTRXOvd7pJRGH3
|
||||
SdC1k/nBsmpmbouc0ihqzOiiN0kUjE2yLSlhwxxWBJqNSzOk9z5/LB4TNRqH9gCL
|
||||
rUN67FgzwR5H70OblWpcjWRurFq34+ZWEmCG+1qUwZMT7dYe4CiDYnVjcwfUpQwN
|
||||
qRpjeMLDrTsCgYEAgo1CRIGzD/WDbGRLinzvgQOnNd6SiOfqx7t8MtP6Jx29as83
|
||||
wi+uQO5gTJONaYJ9OZvJaDCu9UvVCZx1z0yT0D7/K+V/LCQm8dLenscr6jR802y7
|
||||
/7TuAOEr0fO8bh5Oy8zMc/wXuVY5xwz9EfJH9lA47e23JdESxIDTwuziIAECgYEA
|
||||
qKQdPtqpxbUTKDTH3bomN6CcFwcL56XQ+wrdROidb+eyoZsUA5YtkSWwh+TG9Osz
|
||||
XAvqKZ2OBx0YSwWD05CNEq3mjqA2yOtXvpkV/wuInGjoVi0+5BMzDu/2zkecC7WJ
|
||||
QXP7MVWKqhJfmJQdxrIU4S49OvDfMl15zwDrEI5AugkCgYBn5+/KvrA8GGWD9p1r
|
||||
qwjoojGBvCJn1Kj/s+IQYePYeiRe6/eSPGFHRyON9aMGjZmeiqyBA4bW71Wf8Rs1
|
||||
X5LSwZhJpCTjO4B92w40u0r86Jxmp5Wz+zHUeM3mO2E6lAF+15YjhxpMT0YOmHFE
|
||||
+oKD8U6dMjkTqntavBauz8M8fQ==
|
||||
-----END PRIVATE KEY-----
|
19
examples/protocols/esp_local_ctrl/main/certs/rootCA.pem
Normal file
19
examples/protocols/esp_local_ctrl/main/certs/rootCA.pem
Normal file
|
@ -0,0 +1,19 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIC/zCCAeegAwIBAgIUH0R6q5vbgMnMZgD5r4xSu+WhSMwwDQYJKoZIhvcNAQEL
|
||||
BQAwDzENMAsGA1UEAwwEcm9vdDAeFw0xOTA2MjUxOTIxNDVaFw0yOTA2MjIxOTIx
|
||||
NDVaMA8xDTALBgNVBAMMBHJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
|
||||
AoIBAQDGDetEF+4HEOU5uoxvHsYAksmpF1tjw/M+aKtyGuTWInJPDJ3YjjjnF7hb
|
||||
ylx5W7Qj4O4N+TmqYkwA4ztq2CXSmX1uc7OOfxU/wED663NoC2P1Mw0fI5fX2518
|
||||
WdJeQilYymIOilmdtNqU9ad/3RdSZg+fxL5z9MTidHlUyzJG5LlO1cDiYRRURj9S
|
||||
Fc2wWEUCETGA78ADCxKsdf2gBZDcZo/PHNXZc7fi2K18T5UmkRd50aoSLWUNY5tT
|
||||
4DsyL19PUJCmtwcoLMT3p3kmepN4C0JByOxWceIvlAbq7+L3zMURWfpBcIqxXvEP
|
||||
Y/JXw7GCfTJgjUz1IoHVz/ERNtrnAgMBAAGjUzBRMB0GA1UdDgQWBBSaztoCfcw+
|
||||
mBrfMXLCBU8mOyj2BTAfBgNVHSMEGDAWgBSaztoCfcw+mBrfMXLCBU8mOyj2BTAP
|
||||
BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCSgkWG4QAblyxXN/R5
|
||||
tNLKbzQIbaMj8uXSdcVtNHrNfydA0Sq2M8w7mT7N2axiMAusN3fhgztQvkWCvKdy
|
||||
ou++NpFBb11+QJ2chgatLtoR7QPQ2TVlTUObAh2ZSt1jDOqvGQynbYqJ+9N6BKpK
|
||||
S8faScaWP78J02TSMiNIvh8iYukZPMdCyJaHw2x0PtCRYVBSlFIwC5dn/sIJgyrV
|
||||
g8RAlnsKTCQC3X20AQ851aID6JXDIaTn9pn9PN0XJC+iButpLZM4ZHHZpBtSQZ+d
|
||||
6lD0tvS8bysCEkamDMt3z8/ncsytAS08VoFqwXdY3EXF8T+sKSi7+ACJXE/kivwu
|
||||
8jvm
|
||||
-----END CERTIFICATE-----
|
7
examples/protocols/esp_local_ctrl/main/component.mk
Normal file
7
examples/protocols/esp_local_ctrl/main/component.mk
Normal file
|
@ -0,0 +1,7 @@
|
|||
#
|
||||
# "main" pseudo-component makefile.
|
||||
#
|
||||
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
||||
|
||||
COMPONENT_EMBED_TXTFILES := certs/cacert.pem
|
||||
COMPONENT_EMBED_TXTFILES += certs/prvtkey.pem
|
274
examples/protocols/esp_local_ctrl/main/esp_local_ctrl_service.c
Normal file
274
examples/protocols/esp_local_ctrl/main/esp_local_ctrl_service.c
Normal file
|
@ -0,0 +1,274 @@
|
|||
/* Local Ctrl Example
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/param.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
|
||||
#include <mdns.h>
|
||||
#include <esp_log.h>
|
||||
#include <esp_timer.h>
|
||||
#include <esp_local_ctrl.h>
|
||||
#include <esp_https_server.h>
|
||||
|
||||
static const char *TAG = "control";
|
||||
|
||||
#define SERVICE_NAME "my_esp_ctrl_device"
|
||||
|
||||
/* Custom allowed property types */
|
||||
enum property_types {
|
||||
PROP_TYPE_TIMESTAMP = 0,
|
||||
PROP_TYPE_INT32,
|
||||
PROP_TYPE_BOOLEAN,
|
||||
PROP_TYPE_STRING,
|
||||
};
|
||||
|
||||
/* Custom flags that can be set for a property */
|
||||
enum property_flags {
|
||||
PROP_FLAG_READONLY = (1 << 0)
|
||||
};
|
||||
|
||||
/********* Handler functions for responding to control requests / commands *********/
|
||||
|
||||
static esp_err_t get_property_values(size_t props_count,
|
||||
const esp_local_ctrl_prop_t props[],
|
||||
esp_local_ctrl_prop_val_t prop_values[],
|
||||
void *usr_ctx)
|
||||
{
|
||||
for (uint32_t i = 0; i < props_count; i++) {
|
||||
ESP_LOGI(TAG, "Reading property : %s", props[i].name);
|
||||
/* For the purpose of this example, to keep things simple
|
||||
* we have set the context pointer of each property to
|
||||
* point to its value (except for timestamp) */
|
||||
switch (props[i].type) {
|
||||
case PROP_TYPE_INT32:
|
||||
case PROP_TYPE_BOOLEAN:
|
||||
/* No need to set size for these types as sizes where
|
||||
* specified when declaring the properties, unlike for
|
||||
* string type. */
|
||||
prop_values[i].data = props[i].ctx;
|
||||
break;
|
||||
case PROP_TYPE_TIMESTAMP: {
|
||||
/* Get the time stamp */
|
||||
static int64_t ts = 0;
|
||||
ts = esp_timer_get_time();
|
||||
|
||||
/* Set the current time. Since this is statically
|
||||
* allocated, we don't need to provide a free_fn */
|
||||
prop_values[i].data = &ts;
|
||||
break;
|
||||
}
|
||||
case PROP_TYPE_STRING: {
|
||||
char **prop3_value = (char **) props[i].ctx;
|
||||
if (*prop3_value == NULL) {
|
||||
prop_values[i].size = 0;
|
||||
prop_values[i].data = NULL;
|
||||
} else {
|
||||
/* We could try dynamically allocating the output value,
|
||||
* and it should get freed automatically after use, as
|
||||
* `esp_local_ctrl` internally calls the provided `free_fn` */
|
||||
prop_values[i].size = strlen(*prop3_value);
|
||||
prop_values[i].data = strdup(*prop3_value);
|
||||
if (!prop_values[i].data) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
prop_values[i].free_fn = free;
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t set_property_values(size_t props_count,
|
||||
const esp_local_ctrl_prop_t props[],
|
||||
const esp_local_ctrl_prop_val_t prop_values[],
|
||||
void *usr_ctx)
|
||||
{
|
||||
for (uint32_t i = 0; i < props_count; i++) {
|
||||
/* Cannot set the value of a read-only property */
|
||||
if (props[i].flags & PROP_FLAG_READONLY) {
|
||||
ESP_LOGE(TAG, "%s is read-only", props[i].name);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
/* For the purpose of this example, to keep things simple
|
||||
* we have set the context pointer of each property to
|
||||
* point to its value (except for timestamp) */
|
||||
switch (props[i].type) {
|
||||
case PROP_TYPE_STRING: {
|
||||
/* Free the previously set string */
|
||||
char **prop3_value = (char **) props[i].ctx;
|
||||
free(*prop3_value);
|
||||
*prop3_value = NULL;
|
||||
|
||||
/* Copy the input string */
|
||||
if (prop_values[i].size) {
|
||||
*prop3_value = strndup((const char *)prop_values[i].data, prop_values[i].size);
|
||||
if (*prop3_value == NULL) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
ESP_LOGI(TAG, "Setting %s value to %s", props[i].name, (const char*)*prop3_value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PROP_TYPE_INT32: {
|
||||
const int32_t *new_value = (const int32_t *) prop_values[i].data;
|
||||
ESP_LOGI(TAG, "Setting %s value to %d", props[i].name, *new_value);
|
||||
memcpy(props[i].ctx, new_value, sizeof(int32_t));
|
||||
}
|
||||
break;
|
||||
case PROP_TYPE_BOOLEAN: {
|
||||
const bool *value = (const bool *) prop_values[i].data;
|
||||
ESP_LOGI(TAG, "Setting %s value to %d", props[i].name, *value);
|
||||
memcpy(props[i].ctx, value, sizeof(bool));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/* A custom free_fn to free a pointer to a string as
|
||||
* well as the string being pointed to */
|
||||
static void free_str(void *arg)
|
||||
{
|
||||
char **ptr_to_strptr = (char **)arg;
|
||||
if (ptr_to_strptr) {
|
||||
free(*ptr_to_strptr);
|
||||
free(ptr_to_strptr);
|
||||
}
|
||||
}
|
||||
|
||||
/* Function used by app_main to start the esp_local_ctrl service */
|
||||
void start_esp_local_ctrl_service(void)
|
||||
{
|
||||
/* Set the configuration */
|
||||
httpd_ssl_config_t https_conf = HTTPD_SSL_CONFIG_DEFAULT();
|
||||
|
||||
/* Load server certificate */
|
||||
extern const unsigned char cacert_pem_start[] asm("_binary_cacert_pem_start");
|
||||
extern const unsigned char cacert_pem_end[] asm("_binary_cacert_pem_end");
|
||||
https_conf.cacert_pem = cacert_pem_start;
|
||||
https_conf.cacert_len = cacert_pem_end - cacert_pem_start;
|
||||
|
||||
/* Load server private key */
|
||||
extern const unsigned char prvtkey_pem_start[] asm("_binary_prvtkey_pem_start");
|
||||
extern const unsigned char prvtkey_pem_end[] asm("_binary_prvtkey_pem_end");
|
||||
https_conf.prvtkey_pem = prvtkey_pem_start;
|
||||
https_conf.prvtkey_len = prvtkey_pem_end - prvtkey_pem_start;
|
||||
|
||||
esp_local_ctrl_config_t config = {
|
||||
.transport = ESP_LOCAL_CTRL_TRANSPORT_HTTPD,
|
||||
.transport_config = {
|
||||
.httpd = &https_conf
|
||||
},
|
||||
.handlers = {
|
||||
/* User defined handler functions */
|
||||
.get_prop_values = get_property_values,
|
||||
.set_prop_values = set_property_values,
|
||||
.usr_ctx = NULL,
|
||||
.usr_ctx_free_fn = NULL
|
||||
},
|
||||
/* Maximum number of properties that may be set */
|
||||
.max_properties = 10
|
||||
};
|
||||
|
||||
mdns_init();
|
||||
mdns_hostname_set(SERVICE_NAME);
|
||||
|
||||
/* Start esp_local_ctrl service */
|
||||
ESP_ERROR_CHECK(esp_local_ctrl_start(&config));
|
||||
ESP_LOGI(TAG, "esp_local_ctrl service started with name : %s", SERVICE_NAME);
|
||||
|
||||
/* Create a timestamp property. The client should see this as a read-only property.
|
||||
* Property value is fetched using `esp_timer_get_time()` in the `get_prop_values`
|
||||
* handler */
|
||||
esp_local_ctrl_prop_t timestamp = {
|
||||
.name = "timestamp (us)",
|
||||
.type = PROP_TYPE_TIMESTAMP,
|
||||
.size = sizeof(int64_t),
|
||||
.flags = PROP_FLAG_READONLY,
|
||||
.ctx = NULL,
|
||||
.ctx_free_fn = NULL
|
||||
};
|
||||
|
||||
/* Create a writable integer property. Use dynamically allocated memory
|
||||
* for storing its value and pass it as context, so that it can be accessed
|
||||
* inside the set / get handlers. */
|
||||
int32_t *prop1_value = malloc(sizeof(int32_t));
|
||||
assert(prop1_value != NULL);
|
||||
|
||||
/* Initialize the property value */
|
||||
*prop1_value = 123456789;
|
||||
|
||||
/* Populate the property structure accordingly. Since, we would want the memory
|
||||
* occupied by the property value to be freed automatically upon call to
|
||||
* `esp_local_ctrl_stop()` or `esp_local_ctrl_remove_property()`, the `ctx_free_fn`
|
||||
* field will need to be set with the appropriate de-allocation function,
|
||||
* which in this case is simply `free()` */
|
||||
esp_local_ctrl_prop_t property1 = {
|
||||
.name = "property1",
|
||||
.type = PROP_TYPE_INT32,
|
||||
.size = sizeof(int32_t),
|
||||
.flags = 0,
|
||||
.ctx = prop1_value,
|
||||
.ctx_free_fn = free
|
||||
};
|
||||
|
||||
/* Create another read-only property. Just for demonstration, we use statically
|
||||
* allocated value. No `ctx_free_fn` needs to be set for this */
|
||||
static bool prop2_value = false;
|
||||
|
||||
esp_local_ctrl_prop_t property2 = {
|
||||
.name = "property2",
|
||||
.type = PROP_TYPE_BOOLEAN,
|
||||
.size = sizeof(bool),
|
||||
.flags = PROP_FLAG_READONLY,
|
||||
.ctx = &prop2_value,
|
||||
.ctx_free_fn = NULL
|
||||
};
|
||||
|
||||
/* Create a variable sized property. Its context is a pointer for storing the
|
||||
* pointer to a dynamically allocate string, therefore it will require a
|
||||
* customized free function `free_str()` */
|
||||
char **prop3_value = calloc(1, sizeof(char *));
|
||||
assert(prop3_value != NULL);
|
||||
|
||||
esp_local_ctrl_prop_t property3 = {
|
||||
.name = "property3",
|
||||
.type = PROP_TYPE_STRING,
|
||||
.size = 0, // When zero, this is assumed to be of variable size
|
||||
.flags = 0,
|
||||
.ctx = prop3_value,
|
||||
.ctx_free_fn = free_str
|
||||
};
|
||||
|
||||
/* Now register the properties */
|
||||
ESP_ERROR_CHECK(esp_local_ctrl_add_property(×tamp));
|
||||
ESP_ERROR_CHECK(esp_local_ctrl_add_property(&property1));
|
||||
ESP_ERROR_CHECK(esp_local_ctrl_add_property(&property2));
|
||||
ESP_ERROR_CHECK(esp_local_ctrl_add_property(&property3));
|
||||
|
||||
/* Just for fun, let us keep toggling the value
|
||||
* of the boolean property2, every 1 second */
|
||||
while (1) {
|
||||
vTaskDelay(1000 / portTICK_RATE_MS);
|
||||
prop2_value = !prop2_value;
|
||||
}
|
||||
}
|
273
examples/protocols/esp_local_ctrl/scripts/esp_local_ctrl.py
Normal file
273
examples/protocols/esp_local_ctrl/scripts/esp_local_ctrl.py
Normal file
|
@ -0,0 +1,273 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
from __future__ import print_function
|
||||
from future.utils import tobytes
|
||||
from builtins import input
|
||||
import os
|
||||
import sys
|
||||
import struct
|
||||
import argparse
|
||||
|
||||
import proto
|
||||
|
||||
try:
|
||||
import esp_prov
|
||||
|
||||
except ImportError:
|
||||
idf_path = os.environ['IDF_PATH']
|
||||
sys.path.insert(1, idf_path + "/tools/esp_prov")
|
||||
import esp_prov
|
||||
|
||||
|
||||
# Set this to true to allow exceptions to be thrown
|
||||
config_throw_except = False
|
||||
|
||||
|
||||
# Property types enum
|
||||
PROP_TYPE_TIMESTAMP = 0
|
||||
PROP_TYPE_INT32 = 1
|
||||
PROP_TYPE_BOOLEAN = 2
|
||||
PROP_TYPE_STRING = 3
|
||||
|
||||
|
||||
# Property flags enum
|
||||
PROP_FLAG_READONLY = (1 << 0)
|
||||
|
||||
|
||||
def prop_typestr(prop):
|
||||
if prop["type"] == PROP_TYPE_TIMESTAMP:
|
||||
return "TIME(us)"
|
||||
elif prop["type"] == PROP_TYPE_INT32:
|
||||
return "INT32"
|
||||
elif prop["type"] == PROP_TYPE_BOOLEAN:
|
||||
return "BOOLEAN"
|
||||
elif prop["type"] == PROP_TYPE_STRING:
|
||||
return "STRING"
|
||||
return "UNKNOWN"
|
||||
|
||||
|
||||
def encode_prop_value(prop, value):
|
||||
try:
|
||||
if prop["type"] == PROP_TYPE_TIMESTAMP:
|
||||
return struct.pack('q', value)
|
||||
elif prop["type"] == PROP_TYPE_INT32:
|
||||
return struct.pack('i', value)
|
||||
elif prop["type"] == PROP_TYPE_BOOLEAN:
|
||||
return struct.pack('?', value)
|
||||
elif prop["type"] == PROP_TYPE_STRING:
|
||||
return tobytes(value)
|
||||
return value
|
||||
except struct.error as e:
|
||||
print(e)
|
||||
return None
|
||||
|
||||
|
||||
def decode_prop_value(prop, value):
|
||||
try:
|
||||
if prop["type"] == PROP_TYPE_TIMESTAMP:
|
||||
return struct.unpack('q', value)[0]
|
||||
elif prop["type"] == PROP_TYPE_INT32:
|
||||
return struct.unpack('i', value)[0]
|
||||
elif prop["type"] == PROP_TYPE_BOOLEAN:
|
||||
return struct.unpack('?', value)[0]
|
||||
elif prop["type"] == PROP_TYPE_STRING:
|
||||
return value.decode('latin-1')
|
||||
return value
|
||||
except struct.error as e:
|
||||
print(e)
|
||||
return None
|
||||
|
||||
|
||||
def str_to_prop_value(prop, strval):
|
||||
try:
|
||||
if prop["type"] == PROP_TYPE_TIMESTAMP:
|
||||
return int(strval)
|
||||
elif prop["type"] == PROP_TYPE_INT32:
|
||||
return int(strval)
|
||||
elif prop["type"] == PROP_TYPE_BOOLEAN:
|
||||
return bool(strval)
|
||||
elif prop["type"] == PROP_TYPE_STRING:
|
||||
return strval
|
||||
return strval
|
||||
except ValueError as e:
|
||||
print(e)
|
||||
return None
|
||||
|
||||
|
||||
def prop_is_readonly(prop):
|
||||
return (prop["flags"] & PROP_FLAG_READONLY) is not 0
|
||||
|
||||
|
||||
def on_except(err):
|
||||
if config_throw_except:
|
||||
raise RuntimeError(err)
|
||||
else:
|
||||
print(err)
|
||||
|
||||
|
||||
def get_transport(sel_transport, service_name):
|
||||
try:
|
||||
tp = None
|
||||
if (sel_transport == 'http'):
|
||||
example_path = os.environ['IDF_PATH'] + "/examples/protocols/esp_local_ctrl"
|
||||
cert_path = example_path + "/main/certs/rootCA.pem"
|
||||
tp = esp_prov.transport.Transport_HTTP(service_name, cert_path)
|
||||
elif (sel_transport == 'ble'):
|
||||
tp = esp_prov.transport.Transport_BLE(
|
||||
devname=service_name, service_uuid='0000ffff-0000-1000-8000-00805f9b34fb',
|
||||
nu_lookup={'esp_local_ctrl/version': '0001',
|
||||
'esp_local_ctrl/session': '0002',
|
||||
'esp_local_ctrl/control': '0003'}
|
||||
)
|
||||
return tp
|
||||
except RuntimeError as e:
|
||||
on_except(e)
|
||||
return None
|
||||
|
||||
|
||||
def version_match(tp, expected, verbose=False):
|
||||
try:
|
||||
response = tp.send_data('esp_local_ctrl/version', expected)
|
||||
return (response.lower() == expected.lower())
|
||||
except Exception as e:
|
||||
on_except(e)
|
||||
return None
|
||||
|
||||
|
||||
def get_all_property_values(tp):
|
||||
try:
|
||||
props = []
|
||||
message = proto.get_prop_count_request()
|
||||
response = tp.send_data('esp_local_ctrl/control', message)
|
||||
count = proto.get_prop_count_response(response)
|
||||
if count == 0:
|
||||
raise RuntimeError("No properties found!")
|
||||
indices = [i for i in range(count)]
|
||||
message = proto.get_prop_vals_request(indices)
|
||||
response = tp.send_data('esp_local_ctrl/control', message)
|
||||
props = proto.get_prop_vals_response(response)
|
||||
if len(props) != count:
|
||||
raise RuntimeError("Incorrect count of properties!")
|
||||
for p in props:
|
||||
p["value"] = decode_prop_value(p, p["value"])
|
||||
return props
|
||||
except RuntimeError as e:
|
||||
on_except(e)
|
||||
return []
|
||||
|
||||
|
||||
def set_property_values(tp, props, indices, values, check_readonly=False):
|
||||
try:
|
||||
if check_readonly:
|
||||
for index in indices:
|
||||
if prop_is_readonly(props[index]):
|
||||
raise RuntimeError("Cannot set value of Read-Only property")
|
||||
message = proto.set_prop_vals_request(indices, values)
|
||||
response = tp.send_data('esp_local_ctrl/control', message)
|
||||
return proto.set_prop_vals_response(response)
|
||||
except RuntimeError as e:
|
||||
on_except(e)
|
||||
return False
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(add_help=False)
|
||||
|
||||
parser = argparse.ArgumentParser(description="Control an ESP32 running esp_local_ctrl service")
|
||||
|
||||
parser.add_argument("--version", dest='version', type=str,
|
||||
help="Protocol version", default='')
|
||||
|
||||
parser.add_argument("--transport", dest='transport', type=str,
|
||||
help="transport i.e http or ble", default='http')
|
||||
|
||||
parser.add_argument("--name", dest='service_name', type=str,
|
||||
help="BLE Device Name / HTTP Server hostname or IP", default='')
|
||||
|
||||
parser.add_argument("-v", "--verbose", dest='verbose', help="increase output verbosity", action="store_true")
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.version != '':
|
||||
print("==== Esp_Ctrl Version: " + args.version + " ====")
|
||||
|
||||
if args.service_name == '':
|
||||
args.service_name = 'my_esp_ctrl_device'
|
||||
if args.transport == 'http':
|
||||
args.service_name += '.local'
|
||||
|
||||
obj_transport = get_transport(args.transport, args.service_name)
|
||||
if obj_transport is None:
|
||||
print("---- Invalid transport ----")
|
||||
exit(1)
|
||||
|
||||
if args.version != '':
|
||||
print("\n==== Verifying protocol version ====")
|
||||
if not version_match(obj_transport, args.version, args.verbose):
|
||||
print("---- Error in protocol version matching ----")
|
||||
exit(2)
|
||||
print("==== Verified protocol version successfully ====")
|
||||
|
||||
while True:
|
||||
properties = get_all_property_values(obj_transport)
|
||||
if len(properties) == 0:
|
||||
print("---- Error in reading property values ----")
|
||||
exit(4)
|
||||
|
||||
print("\n==== Available Properties ====")
|
||||
print("{0: >4} {1: <16} {2: <10} {3: <16} {4: <16}".format(
|
||||
"S.N.", "Name", "Type", "Flags", "Value"))
|
||||
for i in range(len(properties)):
|
||||
print("[{0: >2}] {1: <16} {2: <10} {3: <16} {4: <16}".format(
|
||||
i + 1, properties[i]["name"], prop_typestr(properties[i]),
|
||||
["","Read-Only"][prop_is_readonly(properties[i])],
|
||||
str(properties[i]["value"])))
|
||||
|
||||
select = 0
|
||||
while True:
|
||||
try:
|
||||
inval = input("\nSelect properties to set (0 to re-read, 'q' to quit) : ")
|
||||
if inval.lower() == 'q':
|
||||
print("Quitting...")
|
||||
exit(5)
|
||||
invals = inval.split(',')
|
||||
selections = [int(val) for val in invals]
|
||||
if min(selections) < 0 or max(selections) > len(properties):
|
||||
raise ValueError("Invalid input")
|
||||
break
|
||||
except ValueError as e:
|
||||
print(str(e) + "! Retry...")
|
||||
|
||||
if len(selections) == 1 and selections[0] == 0:
|
||||
continue
|
||||
|
||||
set_values = []
|
||||
set_indices = []
|
||||
for select in selections:
|
||||
while True:
|
||||
inval = input("Enter value to set for property (" + properties[select - 1]["name"] + ") : ")
|
||||
value = encode_prop_value(properties[select - 1],
|
||||
str_to_prop_value(properties[select - 1], inval))
|
||||
if value is None:
|
||||
print("Invalid input! Retry...")
|
||||
continue
|
||||
break
|
||||
set_values += [value]
|
||||
set_indices += [select - 1]
|
||||
|
||||
if not set_property_values(obj_transport, properties, set_indices, set_values):
|
||||
print("Failed to set values!")
|
93
examples/protocols/esp_local_ctrl/scripts/proto.py
Normal file
93
examples/protocols/esp_local_ctrl/scripts/proto.py
Normal file
|
@ -0,0 +1,93 @@
|
|||
# Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
|
||||
from __future__ import print_function
|
||||
from future.utils import tobytes
|
||||
import os
|
||||
|
||||
|
||||
def _load_source(name, path):
|
||||
try:
|
||||
from importlib.machinery import SourceFileLoader
|
||||
return SourceFileLoader(name, path).load_module()
|
||||
except ImportError:
|
||||
# importlib.machinery doesn't exists in Python 2 so we will use imp (deprecated in Python 3)
|
||||
import imp
|
||||
return imp.load_source(name, path)
|
||||
|
||||
|
||||
idf_path = os.environ['IDF_PATH']
|
||||
constants_pb2 = _load_source("constants_pb2", idf_path + "/components/protocomm/python/constants_pb2.py")
|
||||
local_ctrl_pb2 = _load_source("esp_local_ctrl_pb2", idf_path + "/components/esp_local_ctrl/python/esp_local_ctrl_pb2.py")
|
||||
|
||||
|
||||
def get_prop_count_request():
|
||||
req = local_ctrl_pb2.LocalCtrlMessage()
|
||||
req.msg = local_ctrl_pb2.TypeCmdGetPropertyCount
|
||||
payload = local_ctrl_pb2.CmdGetPropertyCount()
|
||||
req.cmd_get_prop_count.MergeFrom(payload)
|
||||
return req.SerializeToString()
|
||||
|
||||
|
||||
def get_prop_count_response(response_data):
|
||||
resp = local_ctrl_pb2.LocalCtrlMessage()
|
||||
resp.ParseFromString(tobytes(response_data))
|
||||
if (resp.resp_get_prop_count.status == 0):
|
||||
return resp.resp_get_prop_count.count
|
||||
else:
|
||||
return 0
|
||||
|
||||
|
||||
def get_prop_vals_request(indices):
|
||||
req = local_ctrl_pb2.LocalCtrlMessage()
|
||||
req.msg = local_ctrl_pb2.TypeCmdGetPropertyValues
|
||||
payload = local_ctrl_pb2.CmdGetPropertyValues()
|
||||
payload.indices.extend(indices)
|
||||
req.cmd_get_prop_vals.MergeFrom(payload)
|
||||
return req.SerializeToString()
|
||||
|
||||
|
||||
def get_prop_vals_response(response_data):
|
||||
resp = local_ctrl_pb2.LocalCtrlMessage()
|
||||
resp.ParseFromString(tobytes(response_data))
|
||||
results = []
|
||||
if (resp.resp_get_prop_vals.status == 0):
|
||||
for prop in resp.resp_get_prop_vals.props:
|
||||
results += [{
|
||||
"name": prop.name,
|
||||
"type": prop.type,
|
||||
"flags": prop.flags,
|
||||
"value": tobytes(prop.value)
|
||||
}]
|
||||
return results
|
||||
|
||||
|
||||
def set_prop_vals_request(indices, values):
|
||||
req = local_ctrl_pb2.LocalCtrlMessage()
|
||||
req.msg = local_ctrl_pb2.TypeCmdSetPropertyValues
|
||||
payload = local_ctrl_pb2.CmdSetPropertyValues()
|
||||
for i, v in zip(indices, values):
|
||||
prop = payload.props.add()
|
||||
prop.index = i
|
||||
prop.value = v
|
||||
req.cmd_set_prop_vals.MergeFrom(payload)
|
||||
return req.SerializeToString()
|
||||
|
||||
|
||||
def set_prop_vals_response(response_data):
|
||||
resp = local_ctrl_pb2.LocalCtrlMessage()
|
||||
resp.ParseFromString(tobytes(response_data))
|
||||
return (resp.resp_set_prop_vals.status == 0)
|
1
examples/protocols/esp_local_ctrl/sdkconfig.defaults
Normal file
1
examples/protocols/esp_local_ctrl/sdkconfig.defaults
Normal file
|
@ -0,0 +1 @@
|
|||
CONFIG_ESP_HTTPS_SERVER_ENABLE=y
|
|
@ -61,7 +61,7 @@ def get_transport(sel_transport, softap_endpoint=None, ble_devname=None):
|
|||
try:
|
||||
tp = None
|
||||
if (sel_transport == 'softap'):
|
||||
tp = transport.Transport_Softap(softap_endpoint)
|
||||
tp = transport.Transport_HTTP(softap_endpoint)
|
||||
elif (sel_transport == 'ble'):
|
||||
# BLE client is now capable of automatically figuring out
|
||||
# the primary service from the advertisement data and the
|
||||
|
|
|
@ -14,5 +14,5 @@
|
|||
#
|
||||
|
||||
from .transport_console import * # noqa: F403, F401
|
||||
from .transport_softap import * # noqa: F403, F401
|
||||
from .transport_http import * # noqa: F403, F401
|
||||
from .transport_ble import * # noqa: F403, F401
|
||||
|
|
|
@ -16,14 +16,25 @@
|
|||
from __future__ import print_function
|
||||
from future.utils import tobytes
|
||||
|
||||
import socket
|
||||
import http.client
|
||||
import ssl
|
||||
|
||||
from .transport import Transport
|
||||
|
||||
|
||||
class Transport_Softap(Transport):
|
||||
def __init__(self, url):
|
||||
self.conn = http.client.HTTPConnection(url, timeout=30)
|
||||
class Transport_HTTP(Transport):
|
||||
def __init__(self, hostname, certfile=None):
|
||||
try:
|
||||
socket.gethostbyname(hostname.split(':')[0])
|
||||
except socket.gaierror:
|
||||
raise RuntimeError("Unable to resolve hostname :" + hostname)
|
||||
|
||||
if certfile is None:
|
||||
self.conn = http.client.HTTPConnection(hostname, timeout=30)
|
||||
else:
|
||||
ssl_ctx = ssl.create_default_context(cafile=certfile)
|
||||
self.conn = http.client.HTTPSConnection(hostname, context=ssl_ctx, timeout=30)
|
||||
self.headers = {"Content-type": "application/x-www-form-urlencoded","Accept": "text/plain"}
|
||||
|
||||
def _send_post_request(self, path, data):
|
Loading…
Reference in a new issue