Commit 17741475 authored by zhoutotong's avatar zhoutotong

first commit

parents
{
"files.associations": {
"chrono": "cpp",
"ostream": "cpp"
}
}
\ No newline at end of file
{
"files.associations": {
"array": "cpp",
"bitset": "cpp",
"string_view": "cpp",
"initializer_list": "cpp",
"utility": "cpp",
"__hash_table": "cpp",
"__split_buffer": "cpp",
"__tree": "cpp",
"deque": "cpp",
"map": "cpp",
"queue": "cpp",
"stack": "cpp",
"string": "cpp",
"unordered_map": "cpp",
"vector": "cpp",
"chrono": "cpp",
"any": "cpp",
"atomic": "cpp",
"bit": "cpp",
"*.tcc": "cpp",
"cctype": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"codecvt": "cpp",
"compare": "cpp",
"concepts": "cpp",
"condition_variable": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"forward_list": "cpp",
"list": "cpp",
"set": "cpp",
"exception": "cpp",
"algorithm": "cpp",
"functional": "cpp",
"iterator": "cpp",
"memory": "cpp",
"memory_resource": "cpp",
"numeric": "cpp",
"optional": "cpp",
"random": "cpp",
"ratio": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"fstream": "cpp",
"iomanip": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"limits": "cpp",
"mutex": "cpp",
"new": "cpp",
"numbers": "cpp",
"ostream": "cpp",
"ranges": "cpp",
"semaphore": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"stop_token": "cpp",
"streambuf": "cpp",
"thread": "cpp",
"typeinfo": "cpp",
"valarray": "cpp"
}
}
\ No newline at end of file
cmake_minimum_required(VERSION 3.5)
project(barrier_gate)
set(CMAKE_CXX_STANDARD 11)
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
SET(CMAKE_CXX_EXTENSIONS ON)
execute_process(COMMAND ${CMAKE_C_COMPILER} -march=native -Q -v
OUTPUT_VARIABLE COMPILER_INFO
ERROR_VARIABLE COMPILER_INFO)
string(REGEX MATCH "Target: ([^\n]+)" TARGET_ARCH ${COMPILER_INFO})
message("Detected architecture: ${CMAKE_MATCH_1}")
if (${CMAKE_MATCH_1} STREQUAL "aarch64-linux-gnu")
link_directories(
${CMAKE_CURRENT_SOURCE_DIR}/lib/aarch64
)
else()
link_directories(
${CMAKE_CURRENT_SOURCE_DIR}/lib/x86-64
)
endif()
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/src
)
# 收集源文件
AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/src SRCS)
AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/src/mqtt SRCS)
AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/src/modbus SRCS)
AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/src/uart SRCS)
add_executable(${PROJECT_NAME} ${SRCS})
target_include_directories(${PROJECT_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
)
target_link_libraries(${PROJECT_NAME}
${Coin_LIBRARIES}
pthread
mosquitto
)
{
"mqtt_server_ip": "192.168.9.198",
"mqtt_server_port": 1883,
"mqtt_server_user": "admin/waytous",
"mqtt_server_pwd": "2023",
"self_id": "1",
"uart": "/dev/ttyUSB0",
"report_topic": "waytous/barrier_gate/1",
"control_topic": "waytous/barrier_gate/1/control"
}
This source diff could not be displayed because it is too large. You can view the blob instead.
/*
Copyright (c) 2009-2020 Roger Light <roger@atchoo.org>
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License 2.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
https://www.eclipse.org/legal/epl-2.0/
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
Contributors:
Roger Light - initial implementation and documentation.
*/
/*
* File: mosquitto_broker.h
*
* This header contains functions for use by plugins.
*/
#ifndef MOSQUITTO_BROKER_H
#define MOSQUITTO_BROKER_H
#ifdef __cplusplus
extern "C" {
#endif
#if defined(WIN32) && defined(mosquitto_EXPORTS)
# define mosq_EXPORT __declspec(dllexport)
#else
# define mosq_EXPORT
#endif
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <time.h>
struct mosquitto;
typedef struct mqtt5__property mosquitto_property;
enum mosquitto_protocol {
mp_mqtt,
mp_mqttsn,
mp_websockets
};
/* =========================================================================
*
* Section: Register callbacks.
*
* ========================================================================= */
/* Callback events */
enum mosquitto_plugin_event {
MOSQ_EVT_RELOAD = 1,
MOSQ_EVT_ACL_CHECK = 2,
MOSQ_EVT_BASIC_AUTH = 3,
MOSQ_EVT_EXT_AUTH_START = 4,
MOSQ_EVT_EXT_AUTH_CONTINUE = 5,
MOSQ_EVT_CONTROL = 6,
MOSQ_EVT_MESSAGE = 7,
MOSQ_EVT_PSK_KEY = 8,
MOSQ_EVT_TICK = 9,
MOSQ_EVT_DISCONNECT = 10,
};
/* Data for the MOSQ_EVT_RELOAD event */
struct mosquitto_evt_reload {
void *future;
struct mosquitto_opt *options;
int option_count;
void *future2[4];
};
/* Data for the MOSQ_EVT_ACL_CHECK event */
struct mosquitto_evt_acl_check {
void *future;
struct mosquitto *client;
const char *topic;
const void *payload;
mosquitto_property *properties;
int access;
uint32_t payloadlen;
uint8_t qos;
bool retain;
void *future2[4];
};
/* Data for the MOSQ_EVT_BASIC_AUTH event */
struct mosquitto_evt_basic_auth {
void *future;
struct mosquitto *client;
char *username;
char *password;
void *future2[4];
};
/* Data for the MOSQ_EVT_PSK_KEY event */
struct mosquitto_evt_psk_key {
void *future;
struct mosquitto *client;
const char *hint;
const char *identity;
char *key;
int max_key_len;
void *future2[4];
};
/* Data for the MOSQ_EVT_EXTENDED_AUTH event */
struct mosquitto_evt_extended_auth {
void *future;
struct mosquitto *client;
const void *data_in;
void *data_out;
uint16_t data_in_len;
uint16_t data_out_len;
const char *auth_method;
void *future2[3];
};
/* Data for the MOSQ_EVT_CONTROL event */
struct mosquitto_evt_control {
void *future;
struct mosquitto *client;
const char *topic;
const void *payload;
const mosquitto_property *properties;
char *reason_string;
uint32_t payloadlen;
uint8_t qos;
uint8_t reason_code;
bool retain;
void *future2[4];
};
/* Data for the MOSQ_EVT_MESSAGE event */
struct mosquitto_evt_message {
void *future;
struct mosquitto *client;
char *topic;
void *payload;
mosquitto_property *properties;
char *reason_string;
uint32_t payloadlen;
uint8_t qos;
uint8_t reason_code;
bool retain;
void *future2[4];
};
/* Data for the MOSQ_EVT_TICK event */
struct mosquitto_evt_tick {
void *future;
long now_ns;
long next_ns;
time_t now_s;
time_t next_s;
void *future2[4];
};
/* Data for the MOSQ_EVT_DISCONNECT event */
struct mosquitto_evt_disconnect {
void *future;
struct mosquitto *client;
int reason;
void *future2[4];
};
/* Callback definition */
typedef int (*MOSQ_FUNC_generic_callback)(int, void *, void *);
typedef struct mosquitto_plugin_id_t mosquitto_plugin_id_t;
/*
* Function: mosquitto_callback_register
*
* Register a callback for an event.
*
* Parameters:
* identifier - the plugin identifier, as provided by <mosquitto_plugin_init>.
* event - the event to register a callback for. Can be one of:
* * MOSQ_EVT_RELOAD
* * MOSQ_EVT_ACL_CHECK
* * MOSQ_EVT_BASIC_AUTH
* * MOSQ_EVT_EXT_AUTH_START
* * MOSQ_EVT_EXT_AUTH_CONTINUE
* * MOSQ_EVT_CONTROL
* * MOSQ_EVT_MESSAGE
* * MOSQ_EVT_PSK_KEY
* * MOSQ_EVT_TICK
* * MOSQ_EVT_DISCONNECT
* cb_func - the callback function
* event_data - event specific data
*
* Returns:
* MOSQ_ERR_SUCCESS - on success
* MOSQ_ERR_INVAL - if cb_func is NULL
* MOSQ_ERR_NOMEM - on out of memory
* MOSQ_ERR_ALREADY_EXISTS - if cb_func has already been registered for this event
* MOSQ_ERR_NOT_SUPPORTED - if the event is not supported
*/
mosq_EXPORT int mosquitto_callback_register(
mosquitto_plugin_id_t *identifier,
int event,
MOSQ_FUNC_generic_callback cb_func,
const void *event_data,
void *userdata);
/*
* Function: mosquitto_callback_unregister
*
* Unregister a previously registered callback function.
*
* Parameters:
* identifier - the plugin identifier, as provided by <mosquitto_plugin_init>.
* event - the event to register a callback for. Can be one of:
* * MOSQ_EVT_RELOAD
* * MOSQ_EVT_ACL_CHECK
* * MOSQ_EVT_BASIC_AUTH
* * MOSQ_EVT_EXT_AUTH_START
* * MOSQ_EVT_EXT_AUTH_CONTINUE
* * MOSQ_EVT_CONTROL
* * MOSQ_EVT_MESSAGE
* * MOSQ_EVT_PSK_KEY
* * MOSQ_EVT_TICK
* * MOSQ_EVT_DISCONNECT
* cb_func - the callback function
* event_data - event specific data
*
* Returns:
* MOSQ_ERR_SUCCESS - on success
* MOSQ_ERR_INVAL - if cb_func is NULL
* MOSQ_ERR_NOT_FOUND - if cb_func was not registered for this event
* MOSQ_ERR_NOT_SUPPORTED - if the event is not supported
*/
mosq_EXPORT int mosquitto_callback_unregister(
mosquitto_plugin_id_t *identifier,
int event,
MOSQ_FUNC_generic_callback cb_func,
const void *event_data);
/* =========================================================================
*
* Section: Memory allocation.
*
* Use these functions when allocating or freeing memory to have your memory
* included in the memory tracking on the broker.
*
* ========================================================================= */
/*
* Function: mosquitto_calloc
*/
mosq_EXPORT void *mosquitto_calloc(size_t nmemb, size_t size);
/*
* Function: mosquitto_free
*/
mosq_EXPORT void mosquitto_free(void *mem);
/*
* Function: mosquitto_malloc
*/
mosq_EXPORT void *mosquitto_malloc(size_t size);
/*
* Function: mosquitto_realloc
*/
mosq_EXPORT void *mosquitto_realloc(void *ptr, size_t size);
/*
* Function: mosquitto_strdup
*/
mosq_EXPORT char *mosquitto_strdup(const char *s);
/* =========================================================================
*
* Section: Utility Functions
*
* Use these functions from within your plugin.
*
* ========================================================================= */
/*
* Function: mosquitto_log_printf
*
* Write a log message using the broker configured logging.
*
* Parameters:
* level - Log message priority. Can currently be one of:
*
* * MOSQ_LOG_INFO
* * MOSQ_LOG_NOTICE
* * MOSQ_LOG_WARNING
* * MOSQ_LOG_ERR
* * MOSQ_LOG_DEBUG
* * MOSQ_LOG_SUBSCRIBE (not recommended for use by plugins)
* * MOSQ_LOG_UNSUBSCRIBE (not recommended for use by plugins)
*
* These values are defined in mosquitto.h.
*
* fmt, ... - printf style format and arguments.
*/
mosq_EXPORT void mosquitto_log_printf(int level, const char *fmt, ...);
/* =========================================================================
*
* Client Functions
*
* Use these functions to access client information.
*
* ========================================================================= */
/*
* Function: mosquitto_client_address
*
* Retrieve the IP address of the client as a string.
*/
mosq_EXPORT const char *mosquitto_client_address(const struct mosquitto *client);
/*
* Function: mosquitto_client_clean_session
*
* Retrieve the clean session flag value for a client.
*/
mosq_EXPORT bool mosquitto_client_clean_session(const struct mosquitto *client);
/*
* Function: mosquitto_client_id
*
* Retrieve the client id associated with a client.
*/
mosq_EXPORT const char *mosquitto_client_id(const struct mosquitto *client);
/*
* Function: mosquitto_client_keepalive
*
* Retrieve the keepalive value for a client.
*/
mosq_EXPORT int mosquitto_client_keepalive(const struct mosquitto *client);
/*
* Function: mosquitto_client_certificate
*
* If TLS support is enabled, return the certificate provided by a client as an
* X509 pointer from openssl. If the client did not provide a certificate, then
* NULL will be returned. This function will only ever return a non-NULL value
* if the `require_certificate` option is set to true.
*
* When you have finished with the x509 pointer, it must be freed using
* X509_free().
*
* If TLS is not supported, this function will always return NULL.
*/
mosq_EXPORT void *mosquitto_client_certificate(const struct mosquitto *client);
/*
* Function: mosquitto_client_protocol
*
* Retrieve the protocol with which the client has connected. Can be one of:
*
* mp_mqtt (MQTT over TCP)
* mp_mqttsn (MQTT-SN)
* mp_websockets (MQTT over Websockets)
*/
mosq_EXPORT int mosquitto_client_protocol(const struct mosquitto *client);
/*
* Function: mosquitto_client_protocol_version
*
* Retrieve the MQTT protocol version with which the client has connected. Can be one of:
*
* Returns:
* 3 - for MQTT v3 / v3.1
* 4 - for MQTT v3.1.1
* 5 - for MQTT v5
*/
mosq_EXPORT int mosquitto_client_protocol_version(const struct mosquitto *client);
/*
* Function: mosquitto_client_sub_count
*
* Retrieve the number of subscriptions that have been made by a client.
*/
mosq_EXPORT int mosquitto_client_sub_count(const struct mosquitto *client);
/*
* Function: mosquitto_client_username
*
* Retrieve the username associated with a client.
*/
mosq_EXPORT const char *mosquitto_client_username(const struct mosquitto *client);
/* Function: mosquitto_set_username
*
* Set the username for a client.
*
* This removes and replaces the current username for a client and hence
* updates its access.
*
* username can be NULL, in which case the client will become anonymous, but
* must not be zero length.
*
* In the case of error, the client will be left with its original username.
*
* Returns:
* MOSQ_ERR_SUCCESS - on success
* MOSQ_ERR_INVAL - if client is NULL, or if username is zero length
* MOSQ_ERR_NOMEM - on out of memory
*/
mosq_EXPORT int mosquitto_set_username(struct mosquitto *client, const char *username);
/* =========================================================================
*
* Section: Client control
*
* ========================================================================= */
/* Function: mosquitto_kick_client_by_clientid
*
* Forcefully disconnect a client from the broker.
*
* If clientid != NULL, then the client with the matching client id is
* disconnected from the broker.
* If clientid == NULL, then all clients are disconnected from the broker.
*
* If with_will == true, then if the client has a Last Will and Testament
* defined then this will be sent. If false, the LWT will not be sent.
*/
mosq_EXPORT int mosquitto_kick_client_by_clientid(const char *clientid, bool with_will);
/* Function: mosquitto_kick_client_by_username
*
* Forcefully disconnect a client from the broker.
*
* If username != NULL, then all clients with a matching username are kicked
* from the broker.
* If username == NULL, then all clients that do not have a username are
* kicked.
*
* If with_will == true, then if the client has a Last Will and Testament
* defined then this will be sent. If false, the LWT will not be sent.
*/
mosq_EXPORT int mosquitto_kick_client_by_username(const char *username, bool with_will);
/* =========================================================================
*
* Section: Publishing functions
*
* ========================================================================= */
/* Function: mosquitto_broker_publish
*
* Publish a message from within a plugin.
*
* This function allows a plugin to publish a message. Messages published in
* this way are treated as coming from the broker and so will not be passed to
* `mosquitto_auth_acl_check(, MOSQ_ACL_WRITE, , )` for checking. Read access
* will be enforced as normal for individual clients when they are due to
* receive the message.
*
* It can be used to send messages to all clients that have a matching
* subscription, or to a single client whether or not it has a matching
* subscription.
*
* Parameters:
* clientid - optional string. If set to NULL, the message is delivered to all
* clients. If non-NULL, the message is delivered only to the
* client with the corresponding client id. If the client id
* specified is not connected, the message will be dropped.
* topic - message topic
* payloadlen - payload length in bytes. Can be 0 for an empty payload.
* payload - payload bytes. If payloadlen > 0 this must not be NULL. Must
* be allocated on the heap. Will be freed by mosquitto after use if the
* function returns success.
* qos - message QoS to use.
* retain - should retain be set on the message. This does not apply if
* clientid is non-NULL.
* properties - MQTT v5 properties to attach to the message. If the function
* returns success, then properties is owned by the broker and
* will be freed at a later point.
*
* Returns:
* MOSQ_ERR_SUCCESS - on success
* MOSQ_ERR_INVAL - if topic is NULL, if payloadlen < 0, if payloadlen > 0
* and payload is NULL, if qos is not 0, 1, or 2.
* MOSQ_ERR_NOMEM - on out of memory
*/
mosq_EXPORT int mosquitto_broker_publish(
const char *clientid,
const char *topic,
int payloadlen,
void *payload,
int qos,
bool retain,
mosquitto_property *properties);
/* Function: mosquitto_broker_publish_copy
*
* Publish a message from within a plugin.
*
* This function is identical to mosquitto_broker_publish, except that a copy
* of `payload` is taken.
*
* Parameters:
* clientid - optional string. If set to NULL, the message is delivered to all
* clients. If non-NULL, the message is delivered only to the
* client with the corresponding client id. If the client id
* specified is not connected, the message will be dropped.
* topic - message topic
* payloadlen - payload length in bytes. Can be 0 for an empty payload.
* payload - payload bytes. If payloadlen > 0 this must not be NULL.
* Memory remains the property of the calling function.
* qos - message QoS to use.
* retain - should retain be set on the message. This does not apply if
* clientid is non-NULL.
* properties - MQTT v5 properties to attach to the message. If the function
* returns success, then properties is owned by the broker and
* will be freed at a later point.
*
* Returns:
* MOSQ_ERR_SUCCESS - on success
* MOSQ_ERR_INVAL - if topic is NULL, if payloadlen < 0, if payloadlen > 0
* and payload is NULL, if qos is not 0, 1, or 2.
* MOSQ_ERR_NOMEM - on out of memory
*/
mosq_EXPORT int mosquitto_broker_publish_copy(
const char *clientid,
const char *topic,
int payloadlen,
const void *payload,
int qos,
bool retain,
mosquitto_property *properties);
#ifdef __cplusplus
}
#endif
#endif
/*
Copyright (c) 2012-2020 Roger Light <roger@atchoo.org>
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License 2.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
https://www.eclipse.org/legal/epl-2.0/
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
Contributors:
Roger Light - initial implementation and documentation.
*/
#ifndef MOSQUITTO_PLUGIN_H
#define MOSQUITTO_PLUGIN_H
/*
* File: mosquitto_plugin.h
*
* This header contains function declarations for use when writing a Mosquitto plugin.
*/
#ifdef __cplusplus
extern "C" {
#endif
/* The generic plugin interface starts at version 5 */
#define MOSQ_PLUGIN_VERSION 5
/* The old auth only interface stopped at version 4 */
#define MOSQ_AUTH_PLUGIN_VERSION 4
#define MOSQ_ACL_NONE 0x00
#define MOSQ_ACL_READ 0x01
#define MOSQ_ACL_WRITE 0x02
#define MOSQ_ACL_SUBSCRIBE 0x04
#define MOSQ_ACL_UNSUBSCRIBE 0x08
#include <stdbool.h>
#include <stdint.h>
#include <mosquitto_broker.h>
struct mosquitto;
struct mosquitto_opt {
char *key;
char *value;
};
struct mosquitto_auth_opt {
char *key;
char *value;
};
struct mosquitto_acl_msg {
const char *topic;
const void *payload;
long payloadlen;
int qos;
bool retain;
};
#ifdef WIN32
# define mosq_plugin_EXPORT __declspec(dllexport)
#else
# define mosq_plugin_EXPORT
#endif
/*
* To create an authentication plugin you must include this file then implement
* the functions listed in the "Plugin Functions" section below. The resulting
* code should then be compiled as a shared library. Using gcc this can be
* achieved as follows:
*
* gcc -I<path to mosquitto_plugin.h> -fPIC -shared plugin.c -o plugin.so
*
* On Mac OS X:
*
* gcc -I<path to mosquitto_plugin.h> -fPIC -shared plugin.c -undefined dynamic_lookup -o plugin.so
*
* Authentication plugins can implement one or both of authentication and
* access control. If your plugin does not wish to handle either of
* authentication or access control it should return MOSQ_ERR_PLUGIN_DEFER. In
* this case, the next plugin will handle it. If all plugins return
* MOSQ_ERR_PLUGIN_DEFER, the request will be denied.
*
* For each check, the following flow happens:
*
* * The default password file and/or acl file checks are made. If either one
* of these is not defined, then they are considered to be deferred. If either
* one accepts the check, no further checks are made. If an error occurs, the
* check is denied
* * The first plugin does the check, if it returns anything other than
* MOSQ_ERR_PLUGIN_DEFER, then the check returns immediately. If the plugin
* returns MOSQ_ERR_PLUGIN_DEFER then the next plugin runs its check.
* * If the final plugin returns MOSQ_ERR_PLUGIN_DEFER, then access will be
* denied.
*/
/* =========================================================================
*
* Helper Functions
*
* ========================================================================= */
/* There are functions that are available for plugin developers to use in
* mosquitto_broker.h, including logging and accessor functions.
*/
/* =========================================================================
*
* Section: Plugin Functions v5
*
* This is the plugin version 5 interface, which covers authentication, access
* control, the $CONTROL topic space handling, and message inspection and
* modification.
*
* This interface is available from v2.0 onwards.
*
* There are just three functions to implement in your plugin. You should
* register callbacks to handle different events in your
* mosquitto_plugin_init() function. See mosquitto_broker.h for the events and
* callback registering functions.
*
* ========================================================================= */
/*
* Function: mosquitto_plugin_version
*
* The broker will attempt to call this function immediately after loading the
* plugin to check it is a supported plugin version. Your code must simply
* return the plugin interface version you support, i.e. 5.
*
* The supported_versions array tells you which plugin versions the broker supports.
*
* If the broker does not support the version that you require, return -1 to
* indicate failure.
*/
mosq_plugin_EXPORT int mosquitto_plugin_version(int supported_version_count, const int *supported_versions);
/*
* Function: mosquitto_plugin_init
*
* Called after the plugin has been loaded and <mosquitto_plugin_version>
* has been called. This will only ever be called once and can be used to
* initialise the plugin.
*
* Parameters:
*
* identifier - This is a pointer to an opaque structure which you must
* save and use when registering/unregistering callbacks.
* user_data - The pointer set here will be passed to the other plugin
* functions. Use to hold connection information for example.
* opts - Pointer to an array of struct mosquitto_opt, which
* provides the plugin options defined in the configuration file.
* opt_count - The number of elements in the opts array.
*
* Return value:
* Return 0 on success
* Return >0 on failure.
*/
mosq_plugin_EXPORT int mosquitto_plugin_init(mosquitto_plugin_id_t *identifier, void **userdata, struct mosquitto_opt *options, int option_count);
/*
* Function: mosquitto_plugin_cleanup
*
* Called when the broker is shutting down. This will only ever be called once
* per plugin.
*
* Parameters:
*
* user_data - The pointer provided in <mosquitto_plugin_init>.
* opts - Pointer to an array of struct mosquitto_opt, which
* provides the plugin options defined in the configuration file.
* opt_count - The number of elements in the opts array.
*
* Return value:
* Return 0 on success
* Return >0 on failure.
*/
mosq_plugin_EXPORT int mosquitto_plugin_cleanup(void *userdata, struct mosquitto_opt *options, int option_count);
/* =========================================================================
*
* Section: Plugin Functions v4
*
* This is the plugin version 4 interface, which is exclusively for
* authentication and access control, and which is still supported for existing
* plugins. If you are developing a new plugin, please use the v5 interface.
*
* You must implement these functions in your plugin.
*
* ========================================================================= */
/*
* Function: mosquitto_auth_plugin_version
*
* The broker will call this function immediately after loading the plugin to
* check it is a supported plugin version. Your code must simply return
* the version of the plugin interface you support, i.e. 4.
*/
mosq_plugin_EXPORT int mosquitto_auth_plugin_version(void);
/*
* Function: mosquitto_auth_plugin_init
*
* Called after the plugin has been loaded and <mosquitto_auth_plugin_version>
* has been called. This will only ever be called once and can be used to
* initialise the plugin.
*
* Parameters:
*
* user_data - The pointer set here will be passed to the other plugin
* functions. Use to hold connection information for example.
* opts - Pointer to an array of struct mosquitto_opt, which
* provides the plugin options defined in the configuration file.
* opt_count - The number of elements in the opts array.
*
* Return value:
* Return 0 on success
* Return >0 on failure.
*/
mosq_plugin_EXPORT int mosquitto_auth_plugin_init(void **user_data, struct mosquitto_opt *opts, int opt_count);
/*
* Function: mosquitto_auth_plugin_cleanup
*
* Called when the broker is shutting down. This will only ever be called once
* per plugin.
* Note that <mosquitto_auth_security_cleanup> will be called directly before
* this function.
*
* Parameters:
*
* user_data - The pointer provided in <mosquitto_auth_plugin_init>.
* opts - Pointer to an array of struct mosquitto_opt, which
* provides the plugin options defined in the configuration file.
* opt_count - The number of elements in the opts array.
*
* Return value:
* Return 0 on success
* Return >0 on failure.
*/
mosq_plugin_EXPORT int mosquitto_auth_plugin_cleanup(void *user_data, struct mosquitto_opt *opts, int opt_count);
/*
* Function: mosquitto_auth_security_init
*
* This function is called in two scenarios:
*
* 1. When the broker starts up.
* 2. If the broker is requested to reload its configuration whilst running. In
* this case, <mosquitto_auth_security_cleanup> will be called first, then
* this function will be called. In this situation, the reload parameter
* will be true.
*
* Parameters:
*
* user_data - The pointer provided in <mosquitto_auth_plugin_init>.
* opts - Pointer to an array of struct mosquitto_opt, which
* provides the plugin options defined in the configuration file.
* opt_count - The number of elements in the opts array.
* reload - If set to false, this is the first time the function has
* been called. If true, the broker has received a signal
* asking to reload its configuration.
*
* Return value:
* Return 0 on success
* Return >0 on failure.
*/
mosq_plugin_EXPORT int mosquitto_auth_security_init(void *user_data, struct mosquitto_opt *opts, int opt_count, bool reload);
/*
* Function: mosquitto_auth_security_cleanup
*
* This function is called in two scenarios:
*
* 1. When the broker is shutting down.
* 2. If the broker is requested to reload its configuration whilst running. In
* this case, this function will be called, followed by
* <mosquitto_auth_security_init>. In this situation, the reload parameter
* will be true.
*
* Parameters:
*
* user_data - The pointer provided in <mosquitto_auth_plugin_init>.
* opts - Pointer to an array of struct mosquitto_opt, which
* provides the plugin options defined in the configuration file.
* opt_count - The number of elements in the opts array.
* reload - If set to false, this is the first time the function has
* been called. If true, the broker has received a signal
* asking to reload its configuration.
*
* Return value:
* Return 0 on success
* Return >0 on failure.
*/
mosq_plugin_EXPORT int mosquitto_auth_security_cleanup(void *user_data, struct mosquitto_opt *opts, int opt_count, bool reload);
/*
* Function: mosquitto_auth_acl_check
*
* Called by the broker when topic access must be checked. access will be one
* of:
* MOSQ_ACL_SUBSCRIBE when a client is asking to subscribe to a topic string.
* This differs from MOSQ_ACL_READ in that it allows you to
* deny access to topic strings rather than by pattern. For
* example, you may use MOSQ_ACL_SUBSCRIBE to deny
* subscriptions to '#', but allow all topics in
* MOSQ_ACL_READ. This allows clients to subscribe to any
* topic they want, but not discover what topics are in use
* on the server.
* MOSQ_ACL_READ when a message is about to be sent to a client (i.e. whether
* it can read that topic or not).
* MOSQ_ACL_WRITE when a message has been received from a client (i.e. whether
* it can write to that topic or not).
*
* Return:
* MOSQ_ERR_SUCCESS if access was granted.
* MOSQ_ERR_ACL_DENIED if access was not granted.
* MOSQ_ERR_UNKNOWN for an application specific error.
* MOSQ_ERR_PLUGIN_DEFER if your plugin does not wish to handle this check.
*/
mosq_plugin_EXPORT int mosquitto_auth_acl_check(void *user_data, int access, struct mosquitto *client, const struct mosquitto_acl_msg *msg);
/*
* Function: mosquitto_auth_unpwd_check
*
* This function is OPTIONAL. Only include this function in your plugin if you
* are making basic username/password checks.
*
* Called by the broker when a username/password must be checked.
*
* Return:
* MOSQ_ERR_SUCCESS if the user is authenticated.
* MOSQ_ERR_AUTH if authentication failed.
* MOSQ_ERR_UNKNOWN for an application specific error.
* MOSQ_ERR_PLUGIN_DEFER if your plugin does not wish to handle this check.
*/
mosq_plugin_EXPORT int mosquitto_auth_unpwd_check(void *user_data, struct mosquitto *client, const char *username, const char *password);
/*
* Function: mosquitto_psk_key_get
*
* This function is OPTIONAL. Only include this function in your plugin if you
* are making TLS-PSK checks.
*
* Called by the broker when a client connects to a listener using TLS/PSK.
* This is used to retrieve the pre-shared-key associated with a client
* identity.
*
* Examine hint and identity to determine the required PSK (which must be a
* hexadecimal string with no leading "0x") and copy this string into key.
*
* Parameters:
* user_data - the pointer provided in <mosquitto_auth_plugin_init>.
* hint - the psk_hint for the listener the client is connecting to.
* identity - the identity string provided by the client
* key - a string where the hex PSK should be copied
* max_key_len - the size of key
*
* Return value:
* Return 0 on success.
* Return >0 on failure.
* Return MOSQ_ERR_PLUGIN_DEFER if your plugin does not wish to handle this check.
*/
mosq_plugin_EXPORT int mosquitto_auth_psk_key_get(void *user_data, struct mosquitto *client, const char *hint, const char *identity, char *key, int max_key_len);
/*
* Function: mosquitto_auth_start
*
* This function is OPTIONAL. Only include this function in your plugin if you
* are making extended authentication checks.
*
* Parameters:
* user_data - the pointer provided in <mosquitto_auth_plugin_init>.
* method - the authentication method
* reauth - this is set to false if this is the first authentication attempt
* on a connection, set to true if the client is attempting to
* reauthenticate.
* data_in - pointer to authentication data, or NULL
* data_in_len - length of data_in, in bytes
* data_out - if your plugin wishes to send authentication data back to the
* client, allocate some memory using malloc or friends and set
* data_out. The broker will free the memory after use.
* data_out_len - Set the length of data_out in bytes.
*
* Return value:
* Return MOSQ_ERR_SUCCESS if authentication was successful.
* Return MOSQ_ERR_AUTH_CONTINUE if the authentication is a multi step process and can continue.
* Return MOSQ_ERR_AUTH if authentication was valid but did not succeed.
* Return any other relevant positive integer MOSQ_ERR_* to produce an error.
*/
mosq_plugin_EXPORT int mosquitto_auth_start(void *user_data, struct mosquitto *client, const char *method, bool reauth, const void *data_in, uint16_t data_in_len, void **data_out, uint16_t *data_out_len);
mosq_plugin_EXPORT int mosquitto_auth_continue(void *user_data, struct mosquitto *client, const char *method, const void *data_in, uint16_t data_in_len, void **data_out, uint16_t *data_out_len);
#ifdef __cplusplus
}
#endif
#endif
/*
Copyright (c) 2009-2020 Roger Light <roger@atchoo.org>
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License 2.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
https://www.eclipse.org/legal/epl-2.0/
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
Contributors:
Roger Light - initial implementation and documentation.
*/
#ifndef MQTT_PROTOCOL_H
#define MQTT_PROTOCOL_H
/*
* File: mqtt_protocol.h
*
* This header contains definitions of MQTT values as defined in the specifications.
*/
#define PROTOCOL_NAME_v31 "MQIsdp"
#define PROTOCOL_VERSION_v31 3
#define PROTOCOL_NAME "MQTT"
#define PROTOCOL_VERSION_v311 4
#define PROTOCOL_VERSION_v5 5
/* Message types */
#define CMD_CONNECT 0x10U
#define CMD_CONNACK 0x20U
#define CMD_PUBLISH 0x30U
#define CMD_PUBACK 0x40U
#define CMD_PUBREC 0x50U
#define CMD_PUBREL 0x60U
#define CMD_PUBCOMP 0x70U
#define CMD_SUBSCRIBE 0x80U
#define CMD_SUBACK 0x90U
#define CMD_UNSUBSCRIBE 0xA0U
#define CMD_UNSUBACK 0xB0U
#define CMD_PINGREQ 0xC0U
#define CMD_PINGRESP 0xD0U
#define CMD_DISCONNECT 0xE0U
#define CMD_AUTH 0xF0U
/* Mosquitto only: for distinguishing CONNECT and WILL properties */
#define CMD_WILL 0x100
/* Enum: mqtt311_connack_codes
*
* The CONNACK results for MQTT v3.1.1, and v3.1.
*
* Values:
* CONNACK_ACCEPTED - 0
* CONNACK_REFUSED_PROTOCOL_VERSION - 1
* CONNACK_REFUSED_IDENTIFIER_REJECTED - 2
* CONNACK_REFUSED_SERVER_UNAVAILABLE - 3
* CONNACK_REFUSED_BAD_USERNAME_PASSWORD - 4
* CONNACK_REFUSED_NOT_AUTHORIZED - 5
*/
enum mqtt311_connack_codes {
CONNACK_ACCEPTED = 0,
CONNACK_REFUSED_PROTOCOL_VERSION = 1,
CONNACK_REFUSED_IDENTIFIER_REJECTED = 2,
CONNACK_REFUSED_SERVER_UNAVAILABLE = 3,
CONNACK_REFUSED_BAD_USERNAME_PASSWORD = 4,
CONNACK_REFUSED_NOT_AUTHORIZED = 5,
};
/* Enum: mqtt5_return_codes
* The reason codes returned in various MQTT commands.
*
* Values:
* MQTT_RC_SUCCESS - 0
* MQTT_RC_NORMAL_DISCONNECTION - 0
* MQTT_RC_GRANTED_QOS0 - 0
* MQTT_RC_GRANTED_QOS1 - 1
* MQTT_RC_GRANTED_QOS2 - 2
* MQTT_RC_DISCONNECT_WITH_WILL_MSG - 4
* MQTT_RC_NO_MATCHING_SUBSCRIBERS - 16
* MQTT_RC_NO_SUBSCRIPTION_EXISTED - 17
* MQTT_RC_CONTINUE_AUTHENTICATION - 24
* MQTT_RC_REAUTHENTICATE - 25
* MQTT_RC_UNSPECIFIED - 128
* MQTT_RC_MALFORMED_PACKET - 129
* MQTT_RC_PROTOCOL_ERROR - 130
* MQTT_RC_IMPLEMENTATION_SPECIFIC - 131
* MQTT_RC_UNSUPPORTED_PROTOCOL_VERSION - 132
* MQTT_RC_CLIENTID_NOT_VALID - 133
* MQTT_RC_BAD_USERNAME_OR_PASSWORD - 134
* MQTT_RC_NOT_AUTHORIZED - 135
* MQTT_RC_SERVER_UNAVAILABLE - 136
* MQTT_RC_SERVER_BUSY - 137
* MQTT_RC_BANNED - 138
* MQTT_RC_SERVER_SHUTTING_DOWN - 139
* MQTT_RC_BAD_AUTHENTICATION_METHOD - 140
* MQTT_RC_KEEP_ALIVE_TIMEOUT - 141
* MQTT_RC_SESSION_TAKEN_OVER - 142
* MQTT_RC_TOPIC_FILTER_INVALID - 143
* MQTT_RC_TOPIC_NAME_INVALID - 144
* MQTT_RC_PACKET_ID_IN_USE - 145
* MQTT_RC_PACKET_ID_NOT_FOUND - 146
* MQTT_RC_RECEIVE_MAXIMUM_EXCEEDED - 147
* MQTT_RC_TOPIC_ALIAS_INVALID - 148
* MQTT_RC_PACKET_TOO_LARGE - 149
* MQTT_RC_MESSAGE_RATE_TOO_HIGH - 150
* MQTT_RC_QUOTA_EXCEEDED - 151
* MQTT_RC_ADMINISTRATIVE_ACTION - 152
* MQTT_RC_PAYLOAD_FORMAT_INVALID - 153
* MQTT_RC_RETAIN_NOT_SUPPORTED - 154
* MQTT_RC_QOS_NOT_SUPPORTED - 155
* MQTT_RC_USE_ANOTHER_SERVER - 156
* MQTT_RC_SERVER_MOVED - 157
* MQTT_RC_SHARED_SUBS_NOT_SUPPORTED - 158
* MQTT_RC_CONNECTION_RATE_EXCEEDED - 159
* MQTT_RC_MAXIMUM_CONNECT_TIME - 160
* MQTT_RC_SUBSCRIPTION_IDS_NOT_SUPPORTED - 161
* MQTT_RC_WILDCARD_SUBS_NOT_SUPPORTED - 162
*/
enum mqtt5_return_codes {
MQTT_RC_SUCCESS = 0, /* CONNACK, PUBACK, PUBREC, PUBREL, PUBCOMP, UNSUBACK, AUTH */
MQTT_RC_NORMAL_DISCONNECTION = 0, /* DISCONNECT */
MQTT_RC_GRANTED_QOS0 = 0, /* SUBACK */
MQTT_RC_GRANTED_QOS1 = 1, /* SUBACK */
MQTT_RC_GRANTED_QOS2 = 2, /* SUBACK */
MQTT_RC_DISCONNECT_WITH_WILL_MSG = 4, /* DISCONNECT */
MQTT_RC_NO_MATCHING_SUBSCRIBERS = 16, /* PUBACK, PUBREC */
MQTT_RC_NO_SUBSCRIPTION_EXISTED = 17, /* UNSUBACK */
MQTT_RC_CONTINUE_AUTHENTICATION = 24, /* AUTH */
MQTT_RC_REAUTHENTICATE = 25, /* AUTH */
MQTT_RC_UNSPECIFIED = 128, /* CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT */
MQTT_RC_MALFORMED_PACKET = 129, /* CONNACK, DISCONNECT */
MQTT_RC_PROTOCOL_ERROR = 130, /* DISCONNECT */
MQTT_RC_IMPLEMENTATION_SPECIFIC = 131, /* CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT */
MQTT_RC_UNSUPPORTED_PROTOCOL_VERSION = 132, /* CONNACK */
MQTT_RC_CLIENTID_NOT_VALID = 133, /* CONNACK */
MQTT_RC_BAD_USERNAME_OR_PASSWORD = 134, /* CONNACK */
MQTT_RC_NOT_AUTHORIZED = 135, /* CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT */
MQTT_RC_SERVER_UNAVAILABLE = 136, /* CONNACK */
MQTT_RC_SERVER_BUSY = 137, /* CONNACK, DISCONNECT */
MQTT_RC_BANNED = 138, /* CONNACK */
MQTT_RC_SERVER_SHUTTING_DOWN = 139, /* DISCONNECT */
MQTT_RC_BAD_AUTHENTICATION_METHOD = 140, /* CONNACK */
MQTT_RC_KEEP_ALIVE_TIMEOUT = 141, /* DISCONNECT */
MQTT_RC_SESSION_TAKEN_OVER = 142, /* DISCONNECT */
MQTT_RC_TOPIC_FILTER_INVALID = 143, /* SUBACK, UNSUBACK, DISCONNECT */
MQTT_RC_TOPIC_NAME_INVALID = 144, /* CONNACK, PUBACK, PUBREC, DISCONNECT */
MQTT_RC_PACKET_ID_IN_USE = 145, /* PUBACK, SUBACK, UNSUBACK */
MQTT_RC_PACKET_ID_NOT_FOUND = 146, /* PUBREL, PUBCOMP */
MQTT_RC_RECEIVE_MAXIMUM_EXCEEDED = 147, /* DISCONNECT */
MQTT_RC_TOPIC_ALIAS_INVALID = 148, /* DISCONNECT */
MQTT_RC_PACKET_TOO_LARGE = 149, /* CONNACK, PUBACK, PUBREC, DISCONNECT */
MQTT_RC_MESSAGE_RATE_TOO_HIGH = 150, /* DISCONNECT */
MQTT_RC_QUOTA_EXCEEDED = 151, /* PUBACK, PUBREC, SUBACK, DISCONNECT */
MQTT_RC_ADMINISTRATIVE_ACTION = 152, /* DISCONNECT */
MQTT_RC_PAYLOAD_FORMAT_INVALID = 153, /* CONNACK, DISCONNECT */
MQTT_RC_RETAIN_NOT_SUPPORTED = 154, /* CONNACK, DISCONNECT */
MQTT_RC_QOS_NOT_SUPPORTED = 155, /* CONNACK, DISCONNECT */
MQTT_RC_USE_ANOTHER_SERVER = 156, /* CONNACK, DISCONNECT */
MQTT_RC_SERVER_MOVED = 157, /* CONNACK, DISCONNECT */
MQTT_RC_SHARED_SUBS_NOT_SUPPORTED = 158, /* SUBACK, DISCONNECT */
MQTT_RC_CONNECTION_RATE_EXCEEDED = 159, /* CONNACK, DISCONNECT */
MQTT_RC_MAXIMUM_CONNECT_TIME = 160, /* DISCONNECT */
MQTT_RC_SUBSCRIPTION_IDS_NOT_SUPPORTED = 161, /* SUBACK, DISCONNECT */
MQTT_RC_WILDCARD_SUBS_NOT_SUPPORTED = 162, /* SUBACK, DISCONNECT */
};
/* Enum: mqtt5_property
* Options for use with MQTTv5 properties.
* Options:
*
* MQTT_PROP_PAYLOAD_FORMAT_INDICATOR - property option.
* MQTT_PROP_MESSAGE_EXPIRY_INTERVAL - property option.
* MQTT_PROP_CONTENT_TYPE - property option.
* MQTT_PROP_RESPONSE_TOPIC - property option.
* MQTT_PROP_CORRELATION_DATA - property option.
* MQTT_PROP_SUBSCRIPTION_IDENTIFIER - property option.
* MQTT_PROP_SESSION_EXPIRY_INTERVAL - property option.
* MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER - property option.
* MQTT_PROP_SERVER_KEEP_ALIVE - property option.
* MQTT_PROP_AUTHENTICATION_METHOD - property option.
* MQTT_PROP_AUTHENTICATION_DATA - property option.
* MQTT_PROP_REQUEST_PROBLEM_INFORMATION - property option.
* MQTT_PROP_WILL_DELAY_INTERVAL - property option.
* MQTT_PROP_REQUEST_RESPONSE_INFORMATION - property option.
* MQTT_PROP_RESPONSE_INFORMATION - property option.
* MQTT_PROP_SERVER_REFERENCE - property option.
* MQTT_PROP_REASON_STRING - property option.
* MQTT_PROP_RECEIVE_MAXIMUM - property option.
* MQTT_PROP_TOPIC_ALIAS_MAXIMUM - property option.
* MQTT_PROP_TOPIC_ALIAS - property option.
* MQTT_PROP_MAXIMUM_QOS - property option.
* MQTT_PROP_RETAIN_AVAILABLE - property option.
* MQTT_PROP_USER_PROPERTY - property option.
* MQTT_PROP_MAXIMUM_PACKET_SIZE - property option.
* MQTT_PROP_WILDCARD_SUB_AVAILABLE - property option.
* MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE - property option.
* MQTT_PROP_SHARED_SUB_AVAILABLE - property option.
*/
enum mqtt5_property {
MQTT_PROP_PAYLOAD_FORMAT_INDICATOR = 1, /* Byte : PUBLISH, Will Properties */
MQTT_PROP_MESSAGE_EXPIRY_INTERVAL = 2, /* 4 byte int : PUBLISH, Will Properties */
MQTT_PROP_CONTENT_TYPE = 3, /* UTF-8 string : PUBLISH, Will Properties */
MQTT_PROP_RESPONSE_TOPIC = 8, /* UTF-8 string : PUBLISH, Will Properties */
MQTT_PROP_CORRELATION_DATA = 9, /* Binary Data : PUBLISH, Will Properties */
MQTT_PROP_SUBSCRIPTION_IDENTIFIER = 11, /* Variable byte int : PUBLISH, SUBSCRIBE */
MQTT_PROP_SESSION_EXPIRY_INTERVAL = 17, /* 4 byte int : CONNECT, CONNACK, DISCONNECT */
MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER = 18, /* UTF-8 string : CONNACK */
MQTT_PROP_SERVER_KEEP_ALIVE = 19, /* 2 byte int : CONNACK */
MQTT_PROP_AUTHENTICATION_METHOD = 21, /* UTF-8 string : CONNECT, CONNACK, AUTH */
MQTT_PROP_AUTHENTICATION_DATA = 22, /* Binary Data : CONNECT, CONNACK, AUTH */
MQTT_PROP_REQUEST_PROBLEM_INFORMATION = 23, /* Byte : CONNECT */
MQTT_PROP_WILL_DELAY_INTERVAL = 24, /* 4 byte int : Will properties */
MQTT_PROP_REQUEST_RESPONSE_INFORMATION = 25,/* Byte : CONNECT */
MQTT_PROP_RESPONSE_INFORMATION = 26, /* UTF-8 string : CONNACK */
MQTT_PROP_SERVER_REFERENCE = 28, /* UTF-8 string : CONNACK, DISCONNECT */
MQTT_PROP_REASON_STRING = 31, /* UTF-8 string : All except Will properties */
MQTT_PROP_RECEIVE_MAXIMUM = 33, /* 2 byte int : CONNECT, CONNACK */
MQTT_PROP_TOPIC_ALIAS_MAXIMUM = 34, /* 2 byte int : CONNECT, CONNACK */
MQTT_PROP_TOPIC_ALIAS = 35, /* 2 byte int : PUBLISH */
MQTT_PROP_MAXIMUM_QOS = 36, /* Byte : CONNACK */
MQTT_PROP_RETAIN_AVAILABLE = 37, /* Byte : CONNACK */
MQTT_PROP_USER_PROPERTY = 38, /* UTF-8 string pair : All */
MQTT_PROP_MAXIMUM_PACKET_SIZE = 39, /* 4 byte int : CONNECT, CONNACK */
MQTT_PROP_WILDCARD_SUB_AVAILABLE = 40, /* Byte : CONNACK */
MQTT_PROP_SUBSCRIPTION_ID_AVAILABLE = 41, /* Byte : CONNACK */
MQTT_PROP_SHARED_SUB_AVAILABLE = 42, /* Byte : CONNACK */
};
enum mqtt5_property_type {
MQTT_PROP_TYPE_BYTE = 1,
MQTT_PROP_TYPE_INT16 = 2,
MQTT_PROP_TYPE_INT32 = 3,
MQTT_PROP_TYPE_VARINT = 4,
MQTT_PROP_TYPE_BINARY = 5,
MQTT_PROP_TYPE_STRING = 6,
MQTT_PROP_TYPE_STRING_PAIR = 7
};
/* Enum: mqtt5_sub_options
* Options for use with MQTTv5 subscriptions.
*
* MQTT_SUB_OPT_NO_LOCAL - with this option set, if this client publishes to
* a topic to which it is subscribed, the broker will not publish the
* message back to the client.
*
* MQTT_SUB_OPT_RETAIN_AS_PUBLISHED - with this option set, messages
* published for this subscription will keep the retain flag as was set by
* the publishing client. The default behaviour without this option set has
* the retain flag indicating whether a message is fresh/stale.
*
* MQTT_SUB_OPT_SEND_RETAIN_ALWAYS - with this option set, pre-existing
* retained messages are sent as soon as the subscription is made, even
* if the subscription already exists. This is the default behaviour, so
* it is not necessary to set this option.
*
* MQTT_SUB_OPT_SEND_RETAIN_NEW - with this option set, pre-existing retained
* messages for this subscription will be sent when the subscription is made,
* but only if the subscription does not already exist.
*
* MQTT_SUB_OPT_SEND_RETAIN_NEVER - with this option set, pre-existing
* retained messages will never be sent for this subscription.
*/
enum mqtt5_sub_options {
MQTT_SUB_OPT_NO_LOCAL = 0x04,
MQTT_SUB_OPT_RETAIN_AS_PUBLISHED = 0x08,
MQTT_SUB_OPT_SEND_RETAIN_ALWAYS = 0x00,
MQTT_SUB_OPT_SEND_RETAIN_NEW = 0x10,
MQTT_SUB_OPT_SEND_RETAIN_NEVER = 0x20,
};
#define MQTT_MAX_PAYLOAD 268435455U
#endif
libmosquitto.so.1
\ No newline at end of file
libmosquitto.so.1
\ No newline at end of file
# traffic_light_control
## 0.deps
```sh
sudo apt install libprotobuf-dev protobuf-compiler
sudo apt install libmosquitto-dev
```
## 1.compile
```sh
mkdir build
cd build
cmake ..
make -j7
```
## 2.exec
```sh
cd build
./traffic_light_control ../test/config.json
```
## 3.config.json
```sh
"mqtt_server_ip": "192.168.9.30", //mqtt 服务器ip地址
"mqtt_server_port": 1883, //mqtt 服务器端口号
"mqtt_server_user": "test", //mqtt 用户名
"mqtt_server_pwd": "test", //mqtt 密码
"hdmap_topic": "/mqtt_msg_data_trans_traffic_light_layer", //订阅高精地图数据的topic
"traffic_control_topic": "/USR-M100/Control/Traffic", //下发给继电器的控制topic
"expand_size": 5, //继电器拓展的板个数
"offset_do_addr": 2, //继电器实际接线的偏移量
"lights":
[
//id: 地图给的值 do_addrs->colors: [对应到继电器的接口编号]
{"name": "light1", "id": 1, "type": "left", "do_addrs":[5, 6, 7], "colors":["red", "yellow", "green"]},
{"name": "light2", "id": 2, "type": "up", "do_addrs":[2, 3, 4], "colors":["red", "yellow", "green"]},
{"name": "light3", "id": 3, "type": "right", "do_addrs":[8, 9, 34], "colors":["red", "yellow", "green"]},
{"name": "light4", "id": 4, "type": "left", "do_addrs":[13, 14, 15], "colors":["red", "yellow", "green"]},
{"name": "light5", "id": 5, "type": "up", "do_addrs":[10, 11, 12], "colors":["red", "yellow", "green"]},
{"name": "light6", "id": 6, "type": "right", "do_addrs":[16, 17, 35], "colors":["red", "yellow", "green"]},
{"name": "light7", "id": 7, "type": "left", "do_addrs":[21, 22, 23], "colors":["red", "yellow", "green"]},
{"name": "light8", "id": 8, "type": "up", "do_addrs":[18, 19, 20], "colors":["red", "yellow", "green"]},
{"name": "light9", "id": 9, "type": "right", "do_addrs":[24, 25, 36], "colors":["red", "yellow", "green"]},
{"name": "light10", "id": 10, "type": "left", "do_addrs":[29, 30, 31], "colors":["red", "yellow", "green"]},
{"name": "light11", "id": 11, "type": "up", "do_addrs":[26, 27, 28], "colors":["red", "yellow", "green"]},
{"name": "light12", "id": 12, "type": "right", "do_addrs":[32, 33, 37], "colors":["red", "yellow", "green"]}
],
"modes":
[
{
"id": 0, //模式id
"lights": //12个灯的状态
[
{"id": 1, "color": "red"},
{"id": 2, "color": "green"},
{"id": 3, "color": "yellow"},
{"id": 4, "color": "black"},
{"id": 5, "color": "unkown"},
{"id": 6, "color": "green"},
{"id": 7, "color": "green"},
{"id": 8, "color": "green"},
{"id": 9, "color": "green"},
{"id": 10, "color": "green"},
{"id": 11, "color": "green"},
{"id": 12, "color": "green"}
]
},
{
"id": 1,
"lights":
[
{"id": 1, "color": "red"},
{"id": 2, "color": "green"},
{"id": 3, "color": "green"},
{"id": 4, "color": "green"},
{"id": 5, "color": "green"},
{"id": 6, "color": "green"},
{"id": 7, "color": "green"},
{"id": 8, "color": "green"},
{"id": 9, "color": "green"},
{"id": 10, "color": "green"},
{"id": 11, "color": "green"},
{"id": 12, "color": "green"}
]
}
]
```
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
#include "barrier_gate.hpp"
#include "modbus/crc16-modbus.hpp"
#include "3th-part/json.hpp"
#include <sstream>
#include <chrono>
#include <cstdint>
// const std::vector<const uint8_t> all_on {0x01, 0x05, 0x00, 0x00, 0xFF, 0x00, 0x8C, 0x3A};
// const std::vector<const uint8_t> all_off {};
uint64_t get_current_timestamp()
{
auto now = std::chrono::system_clock::now();
auto duration_since_epoch = now.time_since_epoch();
auto millis_since_epoch = std::chrono::duration_cast<std::chrono::milliseconds>(duration_since_epoch).count();
return static_cast<uint64_t>(millis_since_epoch);
}
void printf_hex(const std::vector<uint8_t>& data)
{
std::ostringstream ss;
for (auto& v : data) {
ss << "0x" << std::hex << (uint32_t)v << " ";
}
std::cout << ss.str() << std::endl;
}
BarrierGateControl::BarrierGateControl(nlohmann::json& config)
: self_id(config["self_id"])
, uart_name_(config["uart"])
, report_topic_(config["report_topic"])
, control_topic_(config["control_topic"])
{
init();
}
void BarrierGateControl::exec()
{
__m_running = true;
uint16_t gate_code = 0;
std::string barrier_gate_status = cvt_gate_status(GateState::OFF);
auto start = std::chrono::steady_clock::now();
while (__m_running) {
auto now = std::chrono::steady_clock::now();
// publish traffic light states once per second
if(std::chrono::duration_cast<std::chrono::milliseconds>(now - start).count() > 1000)
{
std::cout << "--------------------------------------" << std::endl;
start = now;
// send read input status request to gate
{
std::cout << "read gate input status..." << std::endl;
std::vector<uint8_t> request_cmd = {0x01, 0x03, 0x06, 0x00, 0x00, 0x01};
auto crc = tools::crc16_modbus::crc16_code(request_cmd);
request_cmd.insert(request_cmd.end(), crc.begin(), crc.end());
std::cout << "send request status to gate: ";
printf_hex(request_cmd);
uart_->write(request_cmd.data(), request_cmd.size());
}
// publish barrier gate states
{
nlohmann::json j = nlohmann::json::object();
j.emplace("self_id", self_id);
j.emplace("relay_code", gate_code);
j.emplace("status", barrier_gate_status);
auto containts = j.dump();
mqtt_dataio::subscriber_basic::DataBuffer buffer;
buffer.resize(containts.size());
std::copy(containts.begin(), containts.end(), buffer.begin());
std::cout << "publish traffic light states: " << containts << std::endl;
__m_status_puber->publish(buffer);
}
}
// read data from uart port
uint8_t buffer[1024];
int len = uart_->read(buffer, sizeof(buffer));
if(len > 0)
{
for(int i = 0; i < len; i++)
{
std::cout << std::hex << (uint32_t)buffer[i] << " ";
}
std::cout << std::endl;
// check crc code
auto crc = tools::crc16_modbus::crc16_code(std::vector<uint8_t>(buffer, buffer + len - 2));
if(crc[0] == buffer[len - 2] && crc[1] == buffer[len - 1])
{
std::cout << "crc check ok!" << std::endl;
uint8_t func_code = buffer[1];
if(func_code == 0x03)
{
gate_code = (buffer[len - 4] << 8 | buffer[len - 3]);
barrier_gate_status = cvt_gate_status(gate_code);
std::cout << "gate code: " << (int)gate_code << ", barrier gate status: " << barrier_gate_status << std::endl;
}
else if(func_code == 0x0f)
{
// TODO: this is gate control command ack package.
}
else
{
std::cout << "unknown func code: " << (int)func_code << std::endl;
}
}
else
{
std::cerr << "check gate status failed, crc error: " << buffer[len - 2] << ", " << buffer[len - 1] << ", should be: " << crc[0] << ", " << crc[1] << std::endl;
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
BarrierGateControl::~BarrierGateControl()
{
__m_running = false;
}
void BarrierGateControl::init()
{
uart_ = std::make_shared<awe::Uart>(uart_name_.c_str());
uart_->setOpt(9600, 8, 'N', 1);
// regist self to traffic light controller
nlohmann::json j = nlohmann::json::object();
j.emplace("self_id", self_id);
j.emplace("type", "traffic_light");
// publish traffic light status
__m_status_puber = std::make_shared<mqtt_dataio::publisher<mqtt_dataio::subscriber_basic::DataBuffer>>(report_topic_);
// subscribe control request
__m_control_suber = std::make_shared<mqtt_dataio::subscriber<mqtt_dataio::subscriber_basic::DataBuffer>>(control_topic_,
std::bind(&BarrierGateControl::on_control_request, this, std::placeholders::_1));
// on start up, do nothing
// current_gate_ = GateState::OFF;
// gate_control(0, current_gate_);
}
void BarrierGateControl::on_control_request(const mqtt_dataio::subscriber_basic::DataBuffer& msg)
{
std::string str;
str.resize(msg.size());
memcpy((void*)str.data(), msg.data(), msg.size());
nlohmann::json j = nlohmann::json::parse(str);
std::cout << "recv control request: " << j.dump() << std::endl;
if(j["id"] != self_id)
{
std::cerr << "invalid id: " << j["id"] << ", self id: " << self_id << ", ignore" << std::endl;
return;
}
std::string status = j["status"];
GateState gate = cvt_gate_status(status);
gate_control(0, gate);
std::cout << "change traffic light status from: " << cvt_gate_status(current_gate_) << " to " << cvt_gate_status(gate) << std::endl;
current_gate_ = gate;
}
void BarrierGateControl::gate_control(const int channel, const GateState gate)
{
std::vector<uint8_t> relay_cmd = {0x01, 0x06, 0x05, 0x05, 0x00, static_cast<uint8_t>(gate)};
auto pkg = tools::crc16_modbus::crc16_code(relay_cmd);
relay_cmd.insert(relay_cmd.end(), pkg.begin(), pkg.end());
std::cout << "send relay control cmd: ";
printf_hex(relay_cmd);
uart_->write(relay_cmd.data(), relay_cmd.size());
}
const BarrierGateControl::GateState BarrierGateControl::cvt_gate_status(const std::string& status)
{
// lower status string
std::string s = status;
std::transform(s.begin(), s.end(), s.begin(), ::tolower);
if(s == "off")
{
return GateState::OFF;
}
else if(s == "on")
{
return GateState::ON;
}
else if(s == "pause")
{
return GateState::PAUSE;
}
return GateState::UNKNOWN;
}
const std::string BarrierGateControl::cvt_gate_status(const GateState& status)
{
switch(status)
{
case GateState::ON:
return "on";
case GateState::OFF:
return "off";
case GateState::PAUSE:
return "pause";
default:
return "unknown";
}
return "unknown";
}
const std::string BarrierGateControl::cvt_gate_status(const uint16_t& status)
{
switch(status)
{
case 1: return "initilized"; break;
case 2: return "opening"; break;
case 3: return "opened"; break;
case 4: return "closing"; break;
case 5: return "closed"; break;
case 6: return "close_blocked"; break;
case 7: return "open_blocked"; break;
case 8: return "stopping"; break;
case 9: return "studdy"; break;
case 10: return "system_reset"; break;
case 11: return "reset_needed"; break;
case 12: return "remote_always_on"; break;
default: return "unknown"; break;
}
return "unknown";
}
\ No newline at end of file
#pragma once
#include "mqtt/subcriber.hpp"
#include "mqtt/publisher.hpp"
#include "uart/uart.hpp"
#include "3th-part/json.hpp"
struct traffic_light_config
{
/* data */
uint16_t id;
std::string type;
std::vector<uint16_t> do_addr;
std::vector<std::string> color;
};
struct roadside_info_config
{
std::string id;
std::string topic;
double longitude;
double latitude;
double altitude;
uint32_t isLight;
};
struct traffic_light_status_config
{
/* data */
uint16_t id;
std::string color;
};
struct traffic_mode_config
{
uint16_t id;
std::vector<traffic_light_status_config> lights;
};
class BarrierGateControl
{
public:
BarrierGateControl(nlohmann::json& config);
~BarrierGateControl();
void exec();
enum GateState
{
UNKNOWN = 0,
ON = 1,
PAUSE = 2,
OFF = 3,
};
const GateState cvt_gate_status(const std::string& status);
const std::string cvt_gate_status(const GateState& status);
const std::string cvt_gate_status(const uint16_t& status);
void gate_control(const int channel, const GateState state);
private:
void init();
const std::string self_id;
const std::string uart_name_;
const std::string report_topic_;
const std::string control_topic_;
std::shared_ptr<awe::Uart> uart_;
GateState current_gate_;
std::shared_ptr<mqtt_dataio::publisher<mqtt_dataio::subscriber_basic::DataBuffer>> __m_status_puber;
std::shared_ptr<mqtt_dataio::subscriber<mqtt_dataio::subscriber_basic::DataBuffer>> __m_control_suber;
void on_control_request(const mqtt_dataio::subscriber_basic::DataBuffer& msg);
private:
bool __m_running;
uint8_t __m_expand_size;
uint16_t __m_offset_do_addr;
};
#include <iostream>
#include <fstream>
#include <sstream>
#include "3th-part/json.hpp"
#include "mqtt/mqtt_client.hpp"
#include "barrier_gate.hpp"
int main(int argc, char *argv[])
{
if (argc < 2)
{
std::cout << "please input config file, such as config.json" << std::endl;
return 0;
}
if(access(argv[1], F_OK) != 0)
{
std::cerr << "file not exist: " << argv[1] << std::endl;
return 0;
}
std::ifstream file(argv[1]);
if (!file)
{
std::cerr << "can't open file " << argv[1] << std::endl;
return 0;
}
std::ostringstream ss;
ss << file.rdbuf();
std::string content = ss.str();
if (content.empty())
{
std::cout << "config file is empty!" << std::endl;
}
else
{
try
{
nlohmann::json j = nlohmann::json::parse(content);
std::string ip = j["mqtt_server_ip"];
uint16_t port = j["mqtt_server_port"];
std::string user = j["mqtt_server_user"];
std::string pwd = j["mqtt_server_pwd"];
mqtt_dataio::client::ins().init(ip, port, user, pwd);
auto node = std::make_shared<BarrierGateControl>(j);
node->exec();
}
catch (const std::exception &e)
{
std::cerr << "catch exception: " << e.what() << '\n';
return -1;
}
}
return 0;
}
#pragma once
#include <stdint.h>
#include <vector>
namespace tools
{
static const uint8_t crcHi[] = {
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40};
static const uint8_t crcLo[] = {
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
0x43, 0x83, 0x41, 0x81, 0x80, 0x40};
class crc16_modbus
{
private:
static uint16_t calc(const std::vector<uint8_t> &data)
{
uint8_t crchi = 0xFF;
uint8_t crclo = 0xFF;
uint16_t index = 0;
uint16_t len = data.size();
uint16_t i = 0;
while (len--)
{
uint16_t dataValue = data[i++];
index = crclo ^ dataValue;
crclo = crchi ^ crcHi[index];
crchi = crcLo[index];
}
return ((crchi << 8) | crclo);
}
public:
static std::vector<uint8_t> crc16_code(const std::vector<uint8_t> &data)
{
uint16_t _crc16_code = calc(data);
std::vector<uint8_t> ret;
uint8_t h_b = (_crc16_code >> 8) & 0xff;
uint8_t l_b = _crc16_code & 0xff;
ret.push_back(l_b);
ret.push_back(h_b);
return ret;
}
};
}
#pragma once
#include <vector>
#include <stdint.h>
namespace mqtt_dataio
{
class publisher_basic
{
public:
explicit publisher_basic(){};
virtual ~publisher_basic(){};
};
class subscriber_basic
{
public:
using DataBuffer = std::vector<uint8_t>;
explicit subscriber_basic(){};
virtual ~subscriber_basic(){};
virtual void on_message_arrival(const DataBuffer &){};
};
} // namespace mqtt_dataio
#include "mqtt_client.hpp"
namespace mqtt_dataio
{
bool client::__m_init = false;
struct mosquitto *client::__m_mosq = nullptr;
std::shared_ptr<std::thread> client::__m_thread = nullptr;
std::mutex client::__m_mtx;
std::map<std::string, mqtt_dataio::subscriber_basic *> client::__m_sub_list;
void client::init(const std::string &ip, const uint16_t &port, const std::string &user, const std::string &pwd)
{
if (__m_init)
return;
/* Required before calling other mosquitto functions */
mosquitto_lib_init();
/* Create a new client instance.
* id = NULL -> ask the broker to generate a client id for us
* clean session = true -> the broker should remove old sessions when we connect
* obj = NULL -> we aren't passing any of our private data for callbacks
*/
__m_mosq = mosquitto_new(nullptr, true, nullptr);
if (__m_mosq == nullptr)
{
std::cout << "Error: Out of memory." << std::endl;
return;
}
int rc;
rc = mosquitto_username_pw_set(__m_mosq, user.data(), pwd.data());
if (rc != MOSQ_ERR_SUCCESS)
{
std::cout << "Error: Problem setting username and password" << std::endl;
}
/* Configure callbacks. This should be done before connecting ideally. */
mosquitto_connect_callback_set(__m_mosq, &client::on_connect);
mosquitto_subscribe_callback_set(__m_mosq, &client::on_subscribe);
mosquitto_message_callback_set(__m_mosq, &client::on_message);
/* Connect to test.mosquitto.org on port 1883, with a keepalive of 60 seconds.
* This call makes the socket connection only, it does not complete the MQTT
* CONNECT/CONNACK flow, you should use mosquitto_loop_start() or
* mosquitto_loop_forever() for processing net traffic. */
rc = mosquitto_connect(__m_mosq, ip.data(), port, 60);
if (rc != MOSQ_ERR_SUCCESS)
{
mosquitto_destroy(__m_mosq);
std::cout << "Error: " << mosquitto_strerror(rc) << std::endl;
__m_init = false;
return;
}
__m_thread = std::make_shared<std::thread>([=]()
{ mosquitto_loop_forever(__m_mosq, -1, 1); });
__m_thread->detach();
{
std::lock_guard<std::mutex> lck(__m_mtx);
__m_init = true;
}
std::cout << "mqtt client init done, connecting to " << ip << ":" << port << std::endl;
}
void client::add_suber(const std::string &topic, mqtt_dataio::subscriber_basic *ptr)
{
{
std::lock_guard<std::mutex> lck(__m_mtx);
if (__m_sub_list.find(topic) == __m_sub_list.end())
{
__m_sub_list[topic] = ptr;
std::cout << "create mqtt_subcriber topic: " << topic << std::endl;
}
else
{
std::cout << "create mqtt_subcriber failed, had exist same topic: " << topic << std::endl;
}
}
int rc = mosquitto_subscribe(__m_mosq, NULL, topic.data(), 1);
if (rc != MOSQ_ERR_SUCCESS)
{
std::cout << "Error subscribing: " << mosquitto_strerror(rc) << std::endl;
/* We might as well disconnect if we were unable to subscribe */
// mosquitto_disconnect(__m_mosq);
}
}
void client::rm_suber(const std::string &topic)
{
{
std::lock_guard<std::mutex> lck(__m_mtx);
if (__m_sub_list.find(topic) != __m_sub_list.end())
{
__m_sub_list.erase(topic);
std::cout << "destroy mqtt_subcriber topic: " << topic << std::endl;
}
else
{
std::cout << "destroy mqtt_subcriber failed, not exist same topic: " << topic << std::endl;
}
}
}
void client::publish(const std::string &topic, const std::vector<uint8_t> &buff)
{
if (!__m_init)
return;
int rc = mosquitto_publish(__m_mosq, NULL, topic.data(), buff.size(), buff.data(), 1, false);
if (rc != MOSQ_ERR_SUCCESS)
{
std::cout << "Error publishing: " << mosquitto_strerror(rc) << std::endl;
}
}
client::~client()
{
mosquitto_disconnect(__m_mosq);
mosquitto_lib_cleanup();
__m_thread = nullptr;
{
std::lock_guard<std::mutex> lck(__m_mtx);
__m_sub_list.clear();
__m_init = false;
}
}
void client::on_connect(struct mosquitto *mosq, void *obj, int reason_code)
{
std::cout << "on_connect: " << mosquitto_connack_string(reason_code) << std::endl;
if (reason_code != 0)
{
/* If the connection fails for any reason, we don't want to keep on
* retrying in this example, so disconnect. Without this, the client
* will attempt to reconnect. */
// mosquitto_disconnect(mosq);
}
// /* Making subscriptions in the on_connect() callback means that if the
// * connection drops and is automatically resumed by the client, then the
// * subscriptions will be recreated when the client reconnects. */
// rc = mosquitto_subscribe(mosq, NULL, "example/temperature", 1);
// if(rc != MOSQ_ERR_SUCCESS){
// fprintf(stderr, "Error subscribing: %s\n", mosquitto_strerror(rc));
// /* We might as well disconnect if we were unable to subscribe */
// mosquitto_disconnect(mosq);
// }
}
/* Callback called when the broker sends a SUBACK in response to a SUBSCRIBE. */
void client::on_subscribe(struct mosquitto *mosq, void *obj, int mid, int qos_count, const int *granted_qos)
{
int i;
bool have_subscription = false;
/* In this example we only subscribe to a single topic at once, but a
* SUBSCRIBE can contain many topics at once, so this is one way to check
* them all. */
for (i = 0; i < qos_count; i++)
{
std::cout << "on_subscribe: " << i << " :granted qos = " << granted_qos[i] << std::endl;
if (granted_qos[i] <= 2)
{
have_subscription = true;
}
}
if (have_subscription == false)
{
/* The broker rejected all of our subscriptions, we know we only sent
* the one SUBSCRIBE, so there is no point remaining connected. */
std::cout << "Error: All subscriptions rejected." << std::endl;
// mosquitto_disconnect(mosq);
}
}
void client::on_message(struct mosquitto *mosq, void *obj, const struct mosquitto_message *msg)
{
std::string topic(msg->topic);
{
std::lock_guard<std::mutex> lck(__m_mtx);
for (auto &it : __m_sub_list)
{
if (it.first == topic)
{
std::vector<uint8_t> data;
data.resize(msg->payloadlen);
memcpy(data.data(), msg->payload, msg->payloadlen);
it.second->on_message_arrival(data);
}
}
}
}
}
\ No newline at end of file
#pragma once
#include "mqtt_basic.hpp"
#include <mosquitto.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <iostream>
#include <map>
#include <memory>
#include <functional>
#include <thread>
#include <mutex>
namespace mqtt_dataio
{
class client
{
public:
static client &ins()
{
static client ins;
return ins;
}
void init(const std::string &ip, const uint16_t &port, const std::string &user, const std::string &pwd);
void add_suber(const std::string &topic, mqtt_dataio::subscriber_basic *ptr);
void rm_suber(const std::string &topic);
void publish(const std::string &topic, const std::vector<uint8_t> &buff);
~client();
private:
client() = default;
static void on_connect(struct mosquitto *mosq, void *obj, int reason_code);
static void on_subscribe(struct mosquitto *mosq, void *obj, int mid, int qos_count, const int *granted_qos);
static void on_message(struct mosquitto *mosq, void *obj, const struct mosquitto_message *msg);
private:
static bool __m_init;
static struct mosquitto *__m_mosq;
static std::shared_ptr<std::thread> __m_thread;
static std::mutex __m_mtx;
static std::map<std::string, mqtt_dataio::subscriber_basic *> __m_sub_list;
};
}
\ No newline at end of file
#pragma once
#include "mqtt_basic.hpp"
#include "mqtt_client.hpp"
namespace mqtt_dataio
{
template <typename T>
class publisher : public publisher_basic
{
public:
publisher() = delete;
publisher(const publisher &) = delete;
publisher(const std::string &name)
: __m_name(name)
{
std::cout << "create publisher topic: " << __m_name << std::endl;
}
~publisher() override
{
std::cout << "destroy publisher topic: " << __m_name << std::endl;
}
void publish(const T &msg)
{
{
mqtt_dataio::client::ins().publish(__m_name, msg);
}
}
private:
const std::string __m_name;
};
}
#include "mqtt_basic.hpp"
#include "mqtt_client.hpp"
#include <string>
namespace mqtt_dataio
{
template <typename RT>
class subscriber : public subscriber_basic
{
public:
using DataCallback = std::function<void(const RT &)>;
public:
subscriber(const subscriber &) = delete;
subscriber &operator=(const subscriber &) = delete;
subscriber() = delete;
subscriber(const std::string &name, const DataCallback& cb)
: __m_name(name),
__m_cb(cb)
{
mqtt_dataio::client::ins().add_suber(__m_name, this);
}
~subscriber() override
{
mqtt_dataio::client::ins().rm_suber(__m_name);
}
void on_message_arrival(const DataBuffer &buff) override
{
if (__m_cb)
{
{
__m_cb(buff);
}
}
}
private:
std::string __m_name;
DataCallback __m_cb;
};
} // namespace mqtt_dataio
#include "uart.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <iostream>
static ssize_t uart_write(int __fd, const void *__buf, size_t __n)
{
return write(__fd, __buf, __n);
}
static ssize_t uart_read(int __fd, void *__buf, size_t __nbytes)
{
return read(__fd, __buf, __nbytes);
}
namespace awe
{
Uart::Uart(const char * dev) : fd(0)
{
char tty[64] = "";
strcat(tty, dev);
fd = open(tty, O_RDWR | O_NOCTTY);
//fd = open(tty, O_RDWR | O_NOCTTY | O_NDELAY);
// if (fd > 0) {
// printf("open %s!\n", tty);
// }
}
Uart::~Uart()
{
if (fd > 0)
close(fd);
}
int Uart::setOpt(uint64_t speed, int bits, char event, int stop)
{
if (fd < 0) {
return -1;
perror("Uart Init failed");
}
fcntl(fd, F_SETFL, 0);
struct termios newtio, oldtio;
if ( tcgetattr( fd, &oldtio ) != 0) {
perror("tcgetattr error");
return -1;
}
tcflush(fd, TCIOFLUSH);
bzero( &newtio, sizeof(newtio) );
newtio.c_cflag |= CLOCAL | CREAD;
newtio.c_cflag &= ~CSIZE;
newtio.c_lflag &= ~(ICANON | ISIG | ECHO | ECHOE | IEXTEN);
newtio.c_oflag &= ~OPOST;
newtio.c_iflag &= ~(IXON | IXOFF | IXANY | ICRNL | BRKINT | INPCK | ISTRIP);
newtio.c_cflag &= ~CRTSCTS;
switch ( bits ) {
case 7:
newtio.c_cflag |= CS7;
break;
case 8:
newtio.c_cflag |= CS8;
break;
}
switch (event) {
case 'O':
newtio.c_cflag |= PARENB;
newtio.c_cflag |= PARODD;
newtio.c_iflag |= (INPCK | ISTRIP);
break;
case 'E':
newtio.c_cflag |= PARENB;
newtio.c_cflag &= ~PARODD;
newtio.c_iflag |= (INPCK | ISTRIP);
break;
case 'N':
newtio.c_cflag &= ~PARENB;
break;
}
switch (speed) {
case 4800:
cfsetispeed(&newtio, B4800);
cfsetospeed(&newtio, B4800);
break;
default:
case 9600:
cfsetispeed(&newtio, B9600);
cfsetospeed(&newtio, B9600);
break;
case 19200:
cfsetispeed(&newtio, B19200);
cfsetospeed(&newtio, B19200);
break;
case 38400:
cfsetispeed(&newtio, B38400);
cfsetospeed(&newtio, B38400);
break;
case 57600:
cfsetispeed(&newtio, B57600);
cfsetospeed(&newtio, B57600);
break;
case 115200:
cfsetispeed(&newtio, B115200);
cfsetospeed(&newtio, B115200);
break;
case 230400:
cfsetispeed(&newtio, B230400);
cfsetospeed(&newtio, B230400);
break;
case 460800:
cfsetispeed(&newtio, B460800);
cfsetospeed(&newtio, B460800);
break;
case 500000:
cfsetispeed(&newtio, B500000);
cfsetospeed(&newtio, B500000);
break;
case 576000:
cfsetispeed(&newtio, B576000);
cfsetospeed(&newtio, B576000);
break;
case 921600:
cfsetispeed(&newtio, B921600);
cfsetospeed(&newtio, B921600);
break;
case 1000000:
cfsetispeed(&newtio, B1000000);
cfsetospeed(&newtio, B1000000);
break;
case 1152000:
cfsetispeed(&newtio, B1152000);
cfsetospeed(&newtio, B1152000);
break;
case 1500000:
cfsetispeed(&newtio, B1500000);
cfsetospeed(&newtio, B1500000);
break;
case 2000000:
cfsetispeed(&newtio, B2000000);
cfsetospeed(&newtio, B2000000);
break;
case 2500000:
cfsetispeed(&newtio, B2500000);
cfsetospeed(&newtio, B2500000);
break;
case 3000000:
cfsetispeed(&newtio, B3000000);
cfsetospeed(&newtio, B3000000);
break;
case 3500000:
cfsetispeed(&newtio, B3500000);
cfsetospeed(&newtio, B3500000);
break;
case 4000000:
cfsetispeed(&newtio, B4000000);
cfsetospeed(&newtio, B4000000);
break;
}
if (stop == 1) {
newtio.c_cflag &= ~CSTOPB;
}
else if (stop == 2) {
newtio.c_cflag |= CSTOPB;
}
newtio.c_cc[VTIME] = 5;
newtio.c_cc[VMIN] = 0;
if ((tcsetattr(fd, TCSANOW, &newtio)) != 0) {
perror("set opt error");
return -1;
}
tcflush(fd, TCIFLUSH);
return 0;
}
int Uart::write(uint8_t * buf, size_t size)
{
if (fd < 0) {
return -1;
perror("Uart Init failed");
}
int ret = uart_write(fd, buf, size);
if (ret < 0) {
perror("uart write failed");
}
return ret;
}
int Uart::read(uint8_t * buf, size_t size)
{
if (fd < 0) {
return -1;
perror("Uart Init failed");
}
fd_set set;
struct timeval timeout;
FD_ZERO(&set);
FD_SET(fd, &set);
timeout.tv_sec = 0;
timeout.tv_usec = 0;
int ret = select(fd + 1, &set, NULL, NULL, &timeout);
if (ret > 0) {
ret = uart_read(fd, buf, size);
}
return ret;
}
int Uart::getFd()
{
return fd;
}
}
\ No newline at end of file
#pragma once
#include <iostream>
/*
usage:
Uart uart("ttyS1");
uart.SetOpt(115200, 8, 'N' 1);
*/
namespace awe
{
class Uart
{
public:
Uart(const char * dev);
~Uart();
/**
* @brief Set the Opt object
*
* @param speed : 4800/9600/19200/38400/57600/115200
* @param bits : 7/8
* @param event : O/E/N
* @param stop : 1/2
* @return int
*/
int setOpt(uint64_t speed, int bits, char event, int stop);
int write(uint8_t * buf, size_t size);
int read(uint8_t * buf, size_t size);
int getFd();
private:
int fd;
};
} // namespace awe
#/bin/env bash
# 计算当前目录
CURRENT_DIR=$(cd `dirname $0`; pwd)
if [ "$(id -u)" -ne 0 ]; then
SUDO="sudo"
fi
PKG_NAME="barrier_gate"
# 检查是否存在 aarch64-linux-gnu-gcc 和 aarch64-linux-gnu-g++ 不存在则安装
if ! which aarch64-linux-gnu-gcc > /dev/null 2>&1; then
$SUDO apt-get install -y gcc-aarch64-linux-gnu
fi
if ! which aarch64-linux-gnu-g++ > /dev/null 2>&1; then
$SUDO apt-get install -y g++-aarch64-linux-gnu
fi
build_target() {
AARCH=$1
# 进入 ${PKG_NAME} 目录,检查是否存在 build 目录,不存在则创建
echo ">> Build <${PKG_NAME}> Now..."
cd ${PKG_NAME}
if [ -d build ]; then
rm -rf build
fi
mkdir build && cd build
CC=${AARCH}-linux-gnu-gcc CXX=${AARCH}-linux-gnu-g++ cmake -DCMAKE_BUILD_TYPE=Release .. >> /dev/null
make -j4 >> /dev/null
cd ${CURRENT_DIR}
echo ">> Build <${PKG_NAME}> Done."
# 进行打包处理
if [ ! -d package ]; then
mkdir package
fi
echo ">> Pack <${PKG_NAME}> Now..."
if [ -d package/${PKG_NAME} ]; then
rm -rf package/${PKG_NAME}
fi
mkdir -p package/${PKG_NAME}-${AARCH}
cp -ra ${PKG_NAME}/build/${PKG_NAME} package/${PKG_NAME}-${AARCH}
cp -ra ${PKG_NAME}/lib/${AARCH}/* package/${PKG_NAME}-${AARCH}
cp -ra ${PKG_NAME}/config/config.json package/${PKG_NAME}-${AARCH}
cd package && tar -zvcf ${PKG_NAME}-${AARCH}.tar.gz ${PKG_NAME}-${AARCH} >> /dev/null && rm -rf ${PKG_NAME}-${AARCH} && cd - >> /dev/null
}
build_target aarch64
build_target x86_64
echo '>> Build Done.'
cd ${CURRENT_DIR}
ls -lh package
# 闸机控制
## 构建
```bash
./build.sh
```
构建完成后将产生 x86 和
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment