mirror of
				https://e.coding.net/weidongshan/01_all_series_quickstart.git
				synced 2025-11-04 13:05:59 +08:00 
			
		
		
		
	完结: 嵌入式Linux应用开发实验班(快速入门)
This commit is contained in:
		
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							@@ -59,8 +59,17 @@ int main(int argc, char* argv[])
 | 
			
		||||
    MQTTClient client;
 | 
			
		||||
    MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
 | 
			
		||||
    int rc;
 | 
			
		||||
    char broker[100];
 | 
			
		||||
 | 
			
		||||
    if ((rc = MQTTClient_create(&client, ADDRESS, CLIENTID,
 | 
			
		||||
    if (argc !=2 )
 | 
			
		||||
    {
 | 
			
		||||
	    printf("Usage: %s <broker_ip>\n", argv[0]);
 | 
			
		||||
	    return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    sprintf(broker, "tcp://%s:1883", argv[1]);
 | 
			
		||||
 | 
			
		||||
    if ((rc = MQTTClient_create(&client, broker, CLIENTID,
 | 
			
		||||
        MQTTCLIENT_PERSISTENCE_NONE, NULL)) != MQTTCLIENT_SUCCESS)
 | 
			
		||||
    {
 | 
			
		||||
        printf("Failed to create client, return code %d\n", rc);
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -0,0 +1,277 @@
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * Copyright (c) 2009, 2020 IBM Corp.
 | 
			
		||||
 *
 | 
			
		||||
 * All rights reserved. This program and the accompanying materials
 | 
			
		||||
 * are made available under the terms of the Eclipse Public License v2.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.
 | 
			
		||||
 *
 | 
			
		||||
 * Contributors:
 | 
			
		||||
 *    Ian Craggs - initial API and implementation and/or initial documentation
 | 
			
		||||
 *******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file
 | 
			
		||||
 * \brief This structure represents a persistent data store, used to store 
 | 
			
		||||
 * outbound and inbound messages, in order to achieve reliable messaging.
 | 
			
		||||
 *
 | 
			
		||||
 * The MQTT Client persists QoS1 and QoS2 messages in order to meet the
 | 
			
		||||
 * assurances of delivery associated with these @ref qos levels. The messages 
 | 
			
		||||
 * are saved in persistent storage
 | 
			
		||||
 * The type and context of the persistence implementation are specified when 
 | 
			
		||||
 * the MQTT client is created (see MQTTClient_create()). The default 
 | 
			
		||||
 * persistence type (::MQTTCLIENT_PERSISTENCE_DEFAULT) uses a file system-based
 | 
			
		||||
 * persistence mechanism. The <i>persistence_context</i> argument passed to 
 | 
			
		||||
 * MQTTClient_create() when using the default peristence is a string 
 | 
			
		||||
 * representing the location of the persistence directory. If the context 
 | 
			
		||||
 * argument is NULL, the working directory will be used. 
 | 
			
		||||
 *
 | 
			
		||||
 * To use memory-based persistence, an application passes 
 | 
			
		||||
 * ::MQTTCLIENT_PERSISTENCE_NONE as the <i>persistence_type</i> to 
 | 
			
		||||
 * MQTTClient_create(). This can lead to message loss in certain situations, 
 | 
			
		||||
 * but can be appropriate in some cases (see @ref qos).
 | 
			
		||||
 *
 | 
			
		||||
 * Client applications can provide their own persistence mechanism by passing
 | 
			
		||||
 * ::MQTTCLIENT_PERSISTENCE_USER as the <i>persistence_type</i>. To implement a
 | 
			
		||||
 * custom persistence mechanism, the application must pass an initialized
 | 
			
		||||
 * ::MQTTClient_persistence structure as the <i>persistence_context</i> 
 | 
			
		||||
 * argument to MQTTClient_create().
 | 
			
		||||
 *
 | 
			
		||||
 * If the functions defined return an ::MQTTCLIENT_PERSISTENCE_ERROR then the 
 | 
			
		||||
 * state of the persisted data should remain as it was prior to the function 
 | 
			
		||||
 * being called. For example, if Persistence_put() returns 
 | 
			
		||||
 * ::MQTTCLIENT_PERSISTENCE_ERROR, then it is assumed tha tthe persistent store
 | 
			
		||||
 * does not contain the data that was passed to the function. Similarly,  if 
 | 
			
		||||
 * Persistence_remove() returns ::MQTTCLIENT_PERSISTENCE_ERROR then it is 
 | 
			
		||||
 * assumed that the data to be removed is still held in the persistent store.
 | 
			
		||||
 *
 | 
			
		||||
 * It is up to the persistence implementation to log any error information that
 | 
			
		||||
 * may be required to diagnose a persistence mechanism failure.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
/// @cond EXCLUDE
 | 
			
		||||
*/
 | 
			
		||||
#if !defined(MQTTCLIENTPERSISTENCE_H)
 | 
			
		||||
#define MQTTCLIENTPERSISTENCE_H
 | 
			
		||||
/*
 | 
			
		||||
/// @endcond
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * This <i>persistence_type</i> value specifies the default file system-based 
 | 
			
		||||
  * persistence mechanism (see MQTTClient_create()).
 | 
			
		||||
  */
 | 
			
		||||
#define MQTTCLIENT_PERSISTENCE_DEFAULT 0
 | 
			
		||||
/**
 | 
			
		||||
  * This <i>persistence_type</i> value specifies a memory-based 
 | 
			
		||||
  * persistence mechanism (see MQTTClient_create()).
 | 
			
		||||
  */
 | 
			
		||||
#define MQTTCLIENT_PERSISTENCE_NONE 1
 | 
			
		||||
/**
 | 
			
		||||
  * This <i>persistence_type</i> value specifies an application-specific 
 | 
			
		||||
  * persistence mechanism (see MQTTClient_create()).
 | 
			
		||||
  */
 | 
			
		||||
#define MQTTCLIENT_PERSISTENCE_USER 2
 | 
			
		||||
 | 
			
		||||
/** 
 | 
			
		||||
  * Application-specific persistence functions must return this error code if 
 | 
			
		||||
  * there is a problem executing the function. 
 | 
			
		||||
  */
 | 
			
		||||
#define MQTTCLIENT_PERSISTENCE_ERROR -2
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * @brief Initialize the persistent store.
 | 
			
		||||
  * 
 | 
			
		||||
  * Either open the existing persistent store for this client ID or create a new
 | 
			
		||||
  * one if one doesn't exist. If the persistent store is already open, return 
 | 
			
		||||
  * without taking any action.
 | 
			
		||||
  *
 | 
			
		||||
  * An application can use the same client identifier to connect to many
 | 
			
		||||
  * different servers. The <i>clientid</i> in conjunction with the 
 | 
			
		||||
  * <i>serverURI</i> uniquely identifies the persistence store required.
 | 
			
		||||
  *
 | 
			
		||||
  * @param handle The address of a pointer to a handle for this persistence 
 | 
			
		||||
  * implementation. This function must set handle to a valid reference to the 
 | 
			
		||||
  * persistence following a successful return. 
 | 
			
		||||
  * The handle pointer is passed as an argument to all the other
 | 
			
		||||
  * persistence functions. It may include the context parameter and/or any other
 | 
			
		||||
  * data for use by the persistence functions.
 | 
			
		||||
  * @param clientID The client identifier for which the persistent store should 
 | 
			
		||||
  * be opened.
 | 
			
		||||
  * @param serverURI The connection string specified when the MQTT client was
 | 
			
		||||
  * created (see MQTTClient_create()).
 | 
			
		||||
  * @param context A pointer to any data required to initialize the persistent
 | 
			
		||||
  * store (see ::MQTTClient_persistence).
 | 
			
		||||
  * @return Return 0 if the function completes successfully, otherwise return
 | 
			
		||||
  * ::MQTTCLIENT_PERSISTENCE_ERROR.
 | 
			
		||||
  */
 | 
			
		||||
typedef int (*Persistence_open)(void** handle, const char* clientID, const char* serverURI, void* context);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * @brief Close the persistent store referred to by the handle.
 | 
			
		||||
  *
 | 
			
		||||
  * @param handle The handle pointer from a successful call to 
 | 
			
		||||
  * Persistence_open().
 | 
			
		||||
  * @return Return 0 if the function completes successfully, otherwise return
 | 
			
		||||
  * ::MQTTCLIENT_PERSISTENCE_ERROR.
 | 
			
		||||
  */
 | 
			
		||||
typedef int (*Persistence_close)(void* handle); 
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * @brief Put the specified data into the persistent store.
 | 
			
		||||
  *
 | 
			
		||||
  * @param handle The handle pointer from a successful call to 
 | 
			
		||||
  * Persistence_open().
 | 
			
		||||
  * @param key A string used as the key for the data to be put in the store. The
 | 
			
		||||
  * key is later used to retrieve data from the store with Persistence_get().
 | 
			
		||||
  * @param bufcount The number of buffers to write to the persistence store.
 | 
			
		||||
  * @param buffers An array of pointers to the data buffers associated with 
 | 
			
		||||
  * this <i>key</i>.
 | 
			
		||||
  * @param buflens An array of lengths of the data buffers. <i>buflen[n]</i> 
 | 
			
		||||
  * gives the length of <i>buffer[n]</i>.
 | 
			
		||||
  * @return Return 0 if the function completes successfully, otherwise return
 | 
			
		||||
  * ::MQTTCLIENT_PERSISTENCE_ERROR.
 | 
			
		||||
  */
 | 
			
		||||
typedef int (*Persistence_put)(void* handle, char* key, int bufcount, char* buffers[], int buflens[]);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * @brief Retrieve the specified data from the persistent store. 
 | 
			
		||||
  *
 | 
			
		||||
  * @param handle The handle pointer from a successful call to 
 | 
			
		||||
  * Persistence_open().
 | 
			
		||||
  * @param key A string that is the key for the data to be retrieved. This is 
 | 
			
		||||
  * the same key used to save the data to the store with Persistence_put().
 | 
			
		||||
  * @param buffer The address of a pointer to a buffer. This function sets the
 | 
			
		||||
  * pointer to point at the retrieved data, if successful.
 | 
			
		||||
  * @param buflen The address of an int that is set to the length of 
 | 
			
		||||
  * <i>buffer</i> by this function if successful.
 | 
			
		||||
  * @return Return 0 if the function completes successfully, otherwise return
 | 
			
		||||
  * ::MQTTCLIENT_PERSISTENCE_ERROR.
 | 
			
		||||
  */
 | 
			
		||||
typedef int (*Persistence_get)(void* handle, char* key, char** buffer, int* buflen);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * @brief Remove the data for the specified key from the store.
 | 
			
		||||
  *
 | 
			
		||||
  * @param handle The handle pointer from a successful call to 
 | 
			
		||||
  * Persistence_open().
 | 
			
		||||
  * @param key A string that is the key for the data to be removed from the
 | 
			
		||||
  * store. This is the same key used to save the data to the store with 
 | 
			
		||||
  * Persistence_put().
 | 
			
		||||
  * @return Return 0 if the function completes successfully, otherwise return
 | 
			
		||||
  * ::MQTTCLIENT_PERSISTENCE_ERROR.
 | 
			
		||||
  */
 | 
			
		||||
typedef int (*Persistence_remove)(void* handle, char* key);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * @brief Returns the keys in this persistent data store.
 | 
			
		||||
  *
 | 
			
		||||
  * @param handle The handle pointer from a successful call to 
 | 
			
		||||
  * Persistence_open().
 | 
			
		||||
  * @param keys The address of a pointer to pointers to strings. Assuming
 | 
			
		||||
  * successful execution, this function allocates memory to hold the returned
 | 
			
		||||
  * keys (strings used to store the data with Persistence_put()). It also 
 | 
			
		||||
  * allocates memory to hold an array of pointers to these strings. <i>keys</i>
 | 
			
		||||
  * is set to point to the array of pointers to strings.
 | 
			
		||||
  * @param nkeys A pointer to the number of keys in this persistent data store. 
 | 
			
		||||
  * This function sets the number of keys, if successful.
 | 
			
		||||
  * @return Return 0 if the function completes successfully, otherwise return
 | 
			
		||||
  * ::MQTTCLIENT_PERSISTENCE_ERROR.
 | 
			
		||||
  */
 | 
			
		||||
typedef int (*Persistence_keys)(void* handle, char*** keys, int* nkeys);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * @brief Clears the persistence store, so that it no longer contains any 
 | 
			
		||||
  * persisted data.
 | 
			
		||||
  *
 | 
			
		||||
  * @param handle The handle pointer from a successful call to 
 | 
			
		||||
  * Persistence_open().
 | 
			
		||||
  * @return Return 0 if the function completes successfully, otherwise return
 | 
			
		||||
  * ::MQTTCLIENT_PERSISTENCE_ERROR.
 | 
			
		||||
  */
 | 
			
		||||
typedef int (*Persistence_clear)(void* handle);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * @brief Returns whether any data has been persisted using the specified key.
 | 
			
		||||
  *
 | 
			
		||||
  * @param handle The handle pointer from a successful call to 
 | 
			
		||||
  * Persistence_open().
 | 
			
		||||
  * @param key The string to be tested for existence in the store.
 | 
			
		||||
  * @return Return 0 if the key was found in the store, otherwise return
 | 
			
		||||
  * ::MQTTCLIENT_PERSISTENCE_ERROR.
 | 
			
		||||
  */
 | 
			
		||||
typedef int (*Persistence_containskey)(void* handle, char* key);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * @brief A structure containing the function pointers to a persistence 
 | 
			
		||||
  * implementation and the context or state that will be shared across all 
 | 
			
		||||
  * the persistence functions.
 | 
			
		||||
  */
 | 
			
		||||
typedef struct {
 | 
			
		||||
  /** 
 | 
			
		||||
    * A pointer to any data required to initialize the persistent store.
 | 
			
		||||
    */
 | 
			
		||||
	void* context;
 | 
			
		||||
  /** 
 | 
			
		||||
    * A function pointer to an implementation of Persistence_open().
 | 
			
		||||
    */
 | 
			
		||||
	Persistence_open popen;
 | 
			
		||||
  /** 
 | 
			
		||||
    * A function pointer to an implementation of Persistence_close().
 | 
			
		||||
    */
 | 
			
		||||
	Persistence_close pclose;
 | 
			
		||||
  /**
 | 
			
		||||
    * A function pointer to an implementation of Persistence_put().
 | 
			
		||||
    */
 | 
			
		||||
	Persistence_put pput;
 | 
			
		||||
  /** 
 | 
			
		||||
    * A function pointer to an implementation of Persistence_get().
 | 
			
		||||
    */
 | 
			
		||||
	Persistence_get pget;
 | 
			
		||||
  /** 
 | 
			
		||||
    * A function pointer to an implementation of Persistence_remove().
 | 
			
		||||
    */
 | 
			
		||||
	Persistence_remove premove;
 | 
			
		||||
  /** 
 | 
			
		||||
    * A function pointer to an implementation of Persistence_keys().
 | 
			
		||||
    */
 | 
			
		||||
	Persistence_keys pkeys;
 | 
			
		||||
  /** 
 | 
			
		||||
    * A function pointer to an implementation of Persistence_clear().
 | 
			
		||||
    */
 | 
			
		||||
	Persistence_clear pclear;
 | 
			
		||||
  /** 
 | 
			
		||||
    * A function pointer to an implementation of Persistence_containskey().
 | 
			
		||||
    */
 | 
			
		||||
	Persistence_containskey pcontainskey;
 | 
			
		||||
} MQTTClient_persistence;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A callback which is invoked just before a write to persistence.  This can be
 | 
			
		||||
 * used to transform the data, for instance to encrypt it.
 | 
			
		||||
 * @param context The context as set in ::MQTTAsync_setBeforePersistenceWrite
 | 
			
		||||
 * @param bufcount The number of buffers to write to the persistence store.
 | 
			
		||||
 * @param buffers An array of pointers to the data buffers.
 | 
			
		||||
 * @param buflens An array of lengths of the data buffers.
 | 
			
		||||
 * @return Return 0 if the function completes successfully, otherwise non 0.
 | 
			
		||||
 */
 | 
			
		||||
typedef int MQTTPersistence_beforeWrite(void* context, int bufcount, char* buffers[], int buflens[]);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A callback which is invoked just after a read from persistence.  This can be
 | 
			
		||||
 * used to transform the data, for instance to decrypt it.
 | 
			
		||||
 * @param context The context as set in ::MQTTAsync_setAfterPersistenceRead
 | 
			
		||||
 * @param buffer The address of a pointer to a buffer.
 | 
			
		||||
 * @param buflen The address of an int that is the length of the buffer.
 | 
			
		||||
 * @return Return 0 if the function completes successfully, otherwise non 0.
 | 
			
		||||
 */
 | 
			
		||||
typedef int MQTTPersistence_afterRead(void* context, char** buffer, int* buflen);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -0,0 +1,36 @@
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * Copyright (c) 2020, 2020 Andreas Walter
 | 
			
		||||
 *
 | 
			
		||||
 * All rights reserved. This program and the accompanying materials
 | 
			
		||||
 * are made available under the terms of the Eclipse Public License v2.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.
 | 
			
		||||
 *
 | 
			
		||||
 * Contributors:
 | 
			
		||||
 *    Andreas Walter - initially moved export declarations into separate fle
 | 
			
		||||
 *******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#if !defined(EXPORTDECLARATIONS_H)
 | 
			
		||||
#define EXPORTDECLARATIONS_H
 | 
			
		||||
 | 
			
		||||
#if defined(_WIN32) || defined(_WIN64)
 | 
			
		||||
#   if defined(PAHO_MQTT_EXPORTS)
 | 
			
		||||
#       define LIBMQTT_API __declspec(dllexport)
 | 
			
		||||
#   elif defined(PAHO_MQTT_IMPORTS)
 | 
			
		||||
#       define LIBMQTT_API __declspec(dllimport)
 | 
			
		||||
#   else
 | 
			
		||||
#       define LIBMQTT_API
 | 
			
		||||
#   endif
 | 
			
		||||
#else
 | 
			
		||||
#    if defined(PAHO_MQTT_EXPORTS)
 | 
			
		||||
#       define LIBMQTT_API  __attribute__ ((visibility ("default")))
 | 
			
		||||
#    else
 | 
			
		||||
#       define LIBMQTT_API extern
 | 
			
		||||
#    endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -0,0 +1,222 @@
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * Copyright (c) 2017, 2023 IBM Corp. and others
 | 
			
		||||
 *
 | 
			
		||||
 * All rights reserved. This program and the accompanying materials
 | 
			
		||||
 * are made available under the terms of the Eclipse Public License v2.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.
 | 
			
		||||
 *
 | 
			
		||||
 * Contributors:
 | 
			
		||||
 *    Ian Craggs - initial API and implementation and/or initial documentation
 | 
			
		||||
 *******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#if !defined(MQTTPROPERTIES_H)
 | 
			
		||||
#define MQTTPROPERTIES_H
 | 
			
		||||
 | 
			
		||||
#include "MQTTExportDeclarations.h"
 | 
			
		||||
 | 
			
		||||
#define MQTT_INVALID_PROPERTY_ID -2
 | 
			
		||||
 | 
			
		||||
/** The one byte MQTT V5 property indicator */
 | 
			
		||||
enum MQTTPropertyCodes {
 | 
			
		||||
  MQTTPROPERTY_CODE_PAYLOAD_FORMAT_INDICATOR = 1,  /**< The value is 1 */
 | 
			
		||||
  MQTTPROPERTY_CODE_MESSAGE_EXPIRY_INTERVAL = 2,   /**< The value is 2 */
 | 
			
		||||
  MQTTPROPERTY_CODE_CONTENT_TYPE = 3,              /**< The value is 3 */
 | 
			
		||||
  MQTTPROPERTY_CODE_RESPONSE_TOPIC = 8,            /**< The value is 8 */
 | 
			
		||||
  MQTTPROPERTY_CODE_CORRELATION_DATA = 9,          /**< The value is 9 */
 | 
			
		||||
  MQTTPROPERTY_CODE_SUBSCRIPTION_IDENTIFIER = 11,  /**< The value is 11 */
 | 
			
		||||
  MQTTPROPERTY_CODE_SESSION_EXPIRY_INTERVAL = 17,  /**< The value is 17 */
 | 
			
		||||
  MQTTPROPERTY_CODE_ASSIGNED_CLIENT_IDENTIFER = 18,/**< The value is 18 */
 | 
			
		||||
  MQTTPROPERTY_CODE_SERVER_KEEP_ALIVE = 19,        /**< The value is 19 */
 | 
			
		||||
  MQTTPROPERTY_CODE_AUTHENTICATION_METHOD = 21,    /**< The value is 21 */
 | 
			
		||||
  MQTTPROPERTY_CODE_AUTHENTICATION_DATA = 22,      /**< The value is 22 */
 | 
			
		||||
  MQTTPROPERTY_CODE_REQUEST_PROBLEM_INFORMATION = 23,/**< The value is 23 */
 | 
			
		||||
  MQTTPROPERTY_CODE_WILL_DELAY_INTERVAL = 24,      /**< The value is 24 */
 | 
			
		||||
  MQTTPROPERTY_CODE_REQUEST_RESPONSE_INFORMATION = 25,/**< The value is 25 */
 | 
			
		||||
  MQTTPROPERTY_CODE_RESPONSE_INFORMATION = 26,     /**< The value is 26 */
 | 
			
		||||
  MQTTPROPERTY_CODE_SERVER_REFERENCE = 28,         /**< The value is 28 */
 | 
			
		||||
  MQTTPROPERTY_CODE_REASON_STRING = 31,            /**< The value is 31 */
 | 
			
		||||
  MQTTPROPERTY_CODE_RECEIVE_MAXIMUM = 33,          /**< The value is 33*/
 | 
			
		||||
  MQTTPROPERTY_CODE_TOPIC_ALIAS_MAXIMUM = 34,      /**< The value is 34 */
 | 
			
		||||
  MQTTPROPERTY_CODE_TOPIC_ALIAS = 35,              /**< The value is 35 */
 | 
			
		||||
  MQTTPROPERTY_CODE_MAXIMUM_QOS = 36,              /**< The value is 36 */
 | 
			
		||||
  MQTTPROPERTY_CODE_RETAIN_AVAILABLE = 37,         /**< The value is 37 */
 | 
			
		||||
  MQTTPROPERTY_CODE_USER_PROPERTY = 38,            /**< The value is 38 */
 | 
			
		||||
  MQTTPROPERTY_CODE_MAXIMUM_PACKET_SIZE = 39,      /**< The value is 39 */
 | 
			
		||||
  MQTTPROPERTY_CODE_WILDCARD_SUBSCRIPTION_AVAILABLE = 40,/**< The value is 40 */
 | 
			
		||||
  MQTTPROPERTY_CODE_SUBSCRIPTION_IDENTIFIERS_AVAILABLE = 41,/**< The value is 41 */
 | 
			
		||||
  MQTTPROPERTY_CODE_SHARED_SUBSCRIPTION_AVAILABLE = 42/**< The value is 241 */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Returns a printable string description of an MQTT V5 property code.
 | 
			
		||||
 * @param value an MQTT V5 property code.
 | 
			
		||||
 * @return the printable string description of the input property code.
 | 
			
		||||
 * NULL if the code was not found.
 | 
			
		||||
 */
 | 
			
		||||
LIBMQTT_API const char* MQTTPropertyName(enum MQTTPropertyCodes value);
 | 
			
		||||
 | 
			
		||||
/** The one byte MQTT V5 property type */
 | 
			
		||||
enum MQTTPropertyTypes {
 | 
			
		||||
  MQTTPROPERTY_TYPE_BYTE,
 | 
			
		||||
  MQTTPROPERTY_TYPE_TWO_BYTE_INTEGER,
 | 
			
		||||
  MQTTPROPERTY_TYPE_FOUR_BYTE_INTEGER,
 | 
			
		||||
  MQTTPROPERTY_TYPE_VARIABLE_BYTE_INTEGER,
 | 
			
		||||
  MQTTPROPERTY_TYPE_BINARY_DATA,
 | 
			
		||||
  MQTTPROPERTY_TYPE_UTF_8_ENCODED_STRING,
 | 
			
		||||
  MQTTPROPERTY_TYPE_UTF_8_STRING_PAIR
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Returns the MQTT V5 type code of an MQTT V5 property.
 | 
			
		||||
 * @param value an MQTT V5 property code.
 | 
			
		||||
 * @return the MQTT V5 type code of the input property. -1 if the code was not found.
 | 
			
		||||
 */
 | 
			
		||||
LIBMQTT_API int MQTTProperty_getType(enum MQTTPropertyCodes value);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The data for a length delimited string
 | 
			
		||||
 */
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
	int len; /**< the length of the string */
 | 
			
		||||
	char* data; /**< pointer to the string data */
 | 
			
		||||
} MQTTLenString;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Structure to hold an MQTT version 5 property of any type
 | 
			
		||||
 */
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
  enum MQTTPropertyCodes identifier; /**<  The MQTT V5 property id. A multi-byte integer. */
 | 
			
		||||
  /** The value of the property, as a union of the different possible types. */
 | 
			
		||||
  union {
 | 
			
		||||
    unsigned char byte;       /**< holds the value of a byte property type */
 | 
			
		||||
    unsigned short integer2;  /**< holds the value of a 2 byte integer property type */
 | 
			
		||||
    unsigned int integer4;    /**< holds the value of a 4 byte integer property type */
 | 
			
		||||
    struct {
 | 
			
		||||
      MQTTLenString data;  /**< The value of a string property, or the name of a user property. */
 | 
			
		||||
      MQTTLenString value; /**< The value of a user property. */
 | 
			
		||||
    };
 | 
			
		||||
  } value;
 | 
			
		||||
} MQTTProperty;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * MQTT version 5 property list
 | 
			
		||||
 */
 | 
			
		||||
typedef struct MQTTProperties
 | 
			
		||||
{
 | 
			
		||||
  int count;     /**< number of property entries in the array */
 | 
			
		||||
  int max_count; /**< max number of properties that the currently allocated array can store */
 | 
			
		||||
  int length;    /**< mbi: byte length of all properties */
 | 
			
		||||
  MQTTProperty *array;  /**< array of properties */
 | 
			
		||||
} MQTTProperties;
 | 
			
		||||
 | 
			
		||||
#define MQTTProperties_initializer {0, 0, 0, NULL}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Returns the length of the properties structure when serialized ready for network transmission.
 | 
			
		||||
 * @param props an MQTT V5 property structure.
 | 
			
		||||
 * @return the length in bytes of the properties when serialized.
 | 
			
		||||
 */
 | 
			
		||||
int MQTTProperties_len(MQTTProperties* props);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Add a property pointer to the property array. Memory is allocated in this function,
 | 
			
		||||
 * so MQTTClient_create or MQTTAsync_create must be called first to initialize the
 | 
			
		||||
 * internal heap tracking. Alternatively MQTTAsync_global_init() can be called first
 | 
			
		||||
 * or build with the HIGH_PERFORMANCE option which disables the heap tracking.
 | 
			
		||||
 * @param props The property list to add the property to.
 | 
			
		||||
 * @param prop The property to add to the list.
 | 
			
		||||
 * @return 0 on success, -1 on failure.
 | 
			
		||||
 */
 | 
			
		||||
LIBMQTT_API int MQTTProperties_add(MQTTProperties* props, const MQTTProperty* prop);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Serialize the given property list to a character buffer, e.g. for writing to the network.
 | 
			
		||||
 * @param pptr pointer to the buffer - move the pointer as we add data
 | 
			
		||||
 * @param properties pointer to the property list, can be NULL
 | 
			
		||||
 * @return whether the write succeeded or not: number of bytes written, or < 0 on failure.
 | 
			
		||||
 */
 | 
			
		||||
int MQTTProperties_write(char** pptr, const MQTTProperties* properties);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Reads a property list from a character buffer into an array.
 | 
			
		||||
 * @param properties pointer to the property list to be filled. Should be initalized but empty.
 | 
			
		||||
 * @param pptr pointer to the character buffer.
 | 
			
		||||
 * @param enddata pointer to the end of the character buffer so we don't read beyond.
 | 
			
		||||
 * @return 1 if the properties were read successfully.
 | 
			
		||||
 */
 | 
			
		||||
int MQTTProperties_read(MQTTProperties* properties, char** pptr, char* enddata);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Free all memory allocated to the property list, including any to individual properties.
 | 
			
		||||
 * @param properties pointer to the property list.
 | 
			
		||||
 */
 | 
			
		||||
LIBMQTT_API void MQTTProperties_free(MQTTProperties* properties);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Copy the contents of a property list, allocating additional memory if needed.
 | 
			
		||||
 * @param props pointer to the property list.
 | 
			
		||||
 * @return the duplicated property list.
 | 
			
		||||
 */
 | 
			
		||||
LIBMQTT_API MQTTProperties MQTTProperties_copy(const MQTTProperties* props);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Checks if property list contains a specific property.
 | 
			
		||||
 * @param props pointer to the property list.
 | 
			
		||||
 * @param propid the property id to check for.
 | 
			
		||||
 * @return 1 if found, 0 if not.
 | 
			
		||||
 */
 | 
			
		||||
LIBMQTT_API int MQTTProperties_hasProperty(MQTTProperties *props, enum MQTTPropertyCodes propid);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Returns the number of instances of a property id. Most properties can exist only once.
 | 
			
		||||
 * User properties and subscription ids can exist more than once.
 | 
			
		||||
 * @param props pointer to the property list.
 | 
			
		||||
 * @param propid the property id to check for.
 | 
			
		||||
 * @return the number of times found.  Can be 0.
 | 
			
		||||
 */
 | 
			
		||||
LIBMQTT_API int MQTTProperties_propertyCount(MQTTProperties *props, enum MQTTPropertyCodes propid);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Returns the integer value of a specific property.  The property given must be a numeric type.
 | 
			
		||||
 * @param props pointer to the property list.
 | 
			
		||||
 * @param propid the property id to check for.
 | 
			
		||||
 * @return the integer value of the property. -9999999 on failure.
 | 
			
		||||
 */
 | 
			
		||||
LIBMQTT_API int MQTTProperties_getNumericValue(MQTTProperties *props, enum MQTTPropertyCodes propid);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Returns the integer value of a specific property when it's not the only instance.
 | 
			
		||||
 * The property given must be a numeric type.
 | 
			
		||||
 * @param props pointer to the property list.
 | 
			
		||||
 * @param propid the property id to check for.
 | 
			
		||||
 * @param index the instance number, starting at 0.
 | 
			
		||||
 * @return the integer value of the property. -9999999 on failure.
 | 
			
		||||
 */
 | 
			
		||||
LIBMQTT_API int MQTTProperties_getNumericValueAt(MQTTProperties *props, enum MQTTPropertyCodes propid, int index);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Returns a pointer to the property structure for a specific property.
 | 
			
		||||
 * @param props pointer to the property list.
 | 
			
		||||
 * @param propid the property id to check for.
 | 
			
		||||
 * @return the pointer to the property structure if found.  NULL if not found.
 | 
			
		||||
 */
 | 
			
		||||
LIBMQTT_API MQTTProperty* MQTTProperties_getProperty(MQTTProperties *props, enum MQTTPropertyCodes propid);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Returns a pointer to the property structure for a specific property when it's not the only instance.
 | 
			
		||||
 * @param props pointer to the property list.
 | 
			
		||||
 * @param propid the property id to check for.
 | 
			
		||||
 * @param index the instance number, starting at 0.
 | 
			
		||||
 * @return the pointer to the property structure if found.  NULL if not found.
 | 
			
		||||
 */
 | 
			
		||||
LIBMQTT_API MQTTProperty* MQTTProperties_getPropertyAt(MQTTProperties *props, enum MQTTPropertyCodes propid, int index);
 | 
			
		||||
 | 
			
		||||
#endif /* MQTTPROPERTIES_H */
 | 
			
		||||
@@ -0,0 +1,79 @@
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * Copyright (c) 2017, 2020 IBM Corp. and others
 | 
			
		||||
 *
 | 
			
		||||
 * All rights reserved. This program and the accompanying materials
 | 
			
		||||
 * are made available under the terms of the Eclipse Public License v2.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.
 | 
			
		||||
 *
 | 
			
		||||
 * Contributors:
 | 
			
		||||
 *    Ian Craggs - initial API and implementation and/or initial documentation
 | 
			
		||||
 *******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#if !defined(MQTTREASONCODES_H)
 | 
			
		||||
#define MQTTREASONCODES_H
 | 
			
		||||
 | 
			
		||||
#include "MQTTExportDeclarations.h"
 | 
			
		||||
 | 
			
		||||
/** The MQTT V5 one byte reason code */
 | 
			
		||||
enum MQTTReasonCodes {
 | 
			
		||||
  MQTTREASONCODE_SUCCESS = 0,
 | 
			
		||||
  MQTTREASONCODE_NORMAL_DISCONNECTION = 0,
 | 
			
		||||
  MQTTREASONCODE_GRANTED_QOS_0 = 0,
 | 
			
		||||
  MQTTREASONCODE_GRANTED_QOS_1 = 1,
 | 
			
		||||
  MQTTREASONCODE_GRANTED_QOS_2 = 2,
 | 
			
		||||
  MQTTREASONCODE_DISCONNECT_WITH_WILL_MESSAGE = 4,
 | 
			
		||||
  MQTTREASONCODE_NO_MATCHING_SUBSCRIBERS = 16,
 | 
			
		||||
  MQTTREASONCODE_NO_SUBSCRIPTION_FOUND = 17,
 | 
			
		||||
  MQTTREASONCODE_CONTINUE_AUTHENTICATION = 24,
 | 
			
		||||
  MQTTREASONCODE_RE_AUTHENTICATE = 25,
 | 
			
		||||
  MQTTREASONCODE_UNSPECIFIED_ERROR = 128,
 | 
			
		||||
  MQTTREASONCODE_MALFORMED_PACKET = 129,
 | 
			
		||||
  MQTTREASONCODE_PROTOCOL_ERROR = 130,
 | 
			
		||||
  MQTTREASONCODE_IMPLEMENTATION_SPECIFIC_ERROR = 131,
 | 
			
		||||
  MQTTREASONCODE_UNSUPPORTED_PROTOCOL_VERSION = 132,
 | 
			
		||||
  MQTTREASONCODE_CLIENT_IDENTIFIER_NOT_VALID = 133,
 | 
			
		||||
  MQTTREASONCODE_BAD_USER_NAME_OR_PASSWORD = 134,
 | 
			
		||||
  MQTTREASONCODE_NOT_AUTHORIZED = 135,
 | 
			
		||||
  MQTTREASONCODE_SERVER_UNAVAILABLE = 136,
 | 
			
		||||
  MQTTREASONCODE_SERVER_BUSY = 137,
 | 
			
		||||
  MQTTREASONCODE_BANNED = 138,
 | 
			
		||||
  MQTTREASONCODE_SERVER_SHUTTING_DOWN = 139,
 | 
			
		||||
  MQTTREASONCODE_BAD_AUTHENTICATION_METHOD = 140,
 | 
			
		||||
  MQTTREASONCODE_KEEP_ALIVE_TIMEOUT = 141,
 | 
			
		||||
  MQTTREASONCODE_SESSION_TAKEN_OVER = 142,
 | 
			
		||||
  MQTTREASONCODE_TOPIC_FILTER_INVALID = 143,
 | 
			
		||||
  MQTTREASONCODE_TOPIC_NAME_INVALID = 144,
 | 
			
		||||
  MQTTREASONCODE_PACKET_IDENTIFIER_IN_USE = 145,
 | 
			
		||||
  MQTTREASONCODE_PACKET_IDENTIFIER_NOT_FOUND = 146,
 | 
			
		||||
  MQTTREASONCODE_RECEIVE_MAXIMUM_EXCEEDED = 147,
 | 
			
		||||
  MQTTREASONCODE_TOPIC_ALIAS_INVALID = 148,
 | 
			
		||||
  MQTTREASONCODE_PACKET_TOO_LARGE = 149,
 | 
			
		||||
  MQTTREASONCODE_MESSAGE_RATE_TOO_HIGH = 150,
 | 
			
		||||
  MQTTREASONCODE_QUOTA_EXCEEDED = 151,
 | 
			
		||||
  MQTTREASONCODE_ADMINISTRATIVE_ACTION = 152,
 | 
			
		||||
  MQTTREASONCODE_PAYLOAD_FORMAT_INVALID = 153,
 | 
			
		||||
  MQTTREASONCODE_RETAIN_NOT_SUPPORTED = 154,
 | 
			
		||||
  MQTTREASONCODE_QOS_NOT_SUPPORTED = 155,
 | 
			
		||||
  MQTTREASONCODE_USE_ANOTHER_SERVER = 156,
 | 
			
		||||
  MQTTREASONCODE_SERVER_MOVED = 157,
 | 
			
		||||
  MQTTREASONCODE_SHARED_SUBSCRIPTIONS_NOT_SUPPORTED = 158,
 | 
			
		||||
  MQTTREASONCODE_CONNECTION_RATE_EXCEEDED = 159,
 | 
			
		||||
  MQTTREASONCODE_MAXIMUM_CONNECT_TIME = 160,
 | 
			
		||||
  MQTTREASONCODE_SUBSCRIPTION_IDENTIFIERS_NOT_SUPPORTED = 161,
 | 
			
		||||
  MQTTREASONCODE_WILDCARD_SUBSCRIPTIONS_NOT_SUPPORTED = 162
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Returns a printable string description of an MQTT V5 reason code.
 | 
			
		||||
 * @param value an MQTT V5 reason code.
 | 
			
		||||
 * @return the printable string description of the input reason code.
 | 
			
		||||
 * NULL if the code was not found.
 | 
			
		||||
 */
 | 
			
		||||
LIBMQTT_API const char* MQTTReasonCode_toString(enum MQTTReasonCodes value);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -0,0 +1,46 @@
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * Copyright (c) 2018 IBM Corp.
 | 
			
		||||
 *
 | 
			
		||||
 * All rights reserved. This program and the accompanying materials
 | 
			
		||||
 * are made available under the terms of the Eclipse Public License v2.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.
 | 
			
		||||
 *
 | 
			
		||||
 * Contributors:
 | 
			
		||||
 *    Ian Craggs - initial API and implementation and/or initial documentation
 | 
			
		||||
 *******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#if !defined(SUBOPTS_H)
 | 
			
		||||
#define SUBOPTS_H
 | 
			
		||||
 | 
			
		||||
/** The MQTT V5 subscribe options, apart from QoS which existed before V5. */
 | 
			
		||||
typedef struct MQTTSubscribe_options
 | 
			
		||||
{
 | 
			
		||||
	/** The eyecatcher for this structure. Must be MQSO. */
 | 
			
		||||
	char struct_id[4];
 | 
			
		||||
	/** The version number of this structure.  Must be 0.
 | 
			
		||||
	 */
 | 
			
		||||
	int struct_version;
 | 
			
		||||
	/** To not receive our own publications, set to 1.
 | 
			
		||||
	 *  0 is the original MQTT behaviour - all messages matching the subscription are received.
 | 
			
		||||
	 */
 | 
			
		||||
	unsigned char noLocal;
 | 
			
		||||
	/** To keep the retain flag as on the original publish message, set to 1.
 | 
			
		||||
	 *  If 0, defaults to the original MQTT behaviour where the retain flag is only set on
 | 
			
		||||
	 *  publications sent by a broker if in response to a subscribe request.
 | 
			
		||||
	 */
 | 
			
		||||
	unsigned char retainAsPublished;
 | 
			
		||||
	/** 0 - send retained messages at the time of the subscribe (original MQTT behaviour)
 | 
			
		||||
	 *  1 - send retained messages on subscribe only if the subscription is new
 | 
			
		||||
	 *  2 - do not send retained messages at all
 | 
			
		||||
	 */
 | 
			
		||||
	unsigned char retainHandling;
 | 
			
		||||
} MQTTSubscribe_options;
 | 
			
		||||
 | 
			
		||||
#define MQTTSubscribe_options_initializer { {'M', 'Q', 'S', 'O'}, 0, 0, 0, 0 }
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -0,0 +1,17 @@
 | 
			
		||||
TARGET=mqtt_device_wechat
 | 
			
		||||
CC=arm-buildroot-linux-gnueabihf-gcc
 | 
			
		||||
 | 
			
		||||
TOP_DIR=$(shell pwd)/../
 | 
			
		||||
PAHO_MQTT_DIR=${TOP_DIR}/paho.mqtt.c/
 | 
			
		||||
 | 
			
		||||
CFLAGS=-I${PAHO_MQTT_DIR}/build/src -O
 | 
			
		||||
LDFLAGS=-L${PAHO_MQTT_DIR}/build/src -lpaho-mqtt3c
 | 
			
		||||
 | 
			
		||||
c_files = mqtt_device_wechat.c cfg.c cJSON.c rpc_client.c
 | 
			
		||||
 | 
			
		||||
all:
 | 
			
		||||
	${CC} ${CFLAGS} -o ${TARGET} ${c_files} ${LDFLAGS}
 | 
			
		||||
 | 
			
		||||
clean:
 | 
			
		||||
	rm -f *.o ${TARGET}
 | 
			
		||||
	
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -0,0 +1,300 @@
 | 
			
		||||
/*
 | 
			
		||||
  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
 | 
			
		||||
 | 
			
		||||
  Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
  of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
  in the Software without restriction, including without limitation the rights
 | 
			
		||||
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
  copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
  furnished to do so, subject to the following conditions:
 | 
			
		||||
 | 
			
		||||
  The above copyright notice and this permission notice shall be included in
 | 
			
		||||
  all copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
  THE SOFTWARE.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef cJSON__h
 | 
			
		||||
#define cJSON__h
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C"
 | 
			
		||||
{
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
 | 
			
		||||
#define __WINDOWS__
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __WINDOWS__
 | 
			
		||||
 | 
			
		||||
/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention.  For windows you have 3 define options:
 | 
			
		||||
 | 
			
		||||
CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
 | 
			
		||||
CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
 | 
			
		||||
CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
 | 
			
		||||
 | 
			
		||||
For *nix builds that support visibility attribute, you can define similar behavior by
 | 
			
		||||
 | 
			
		||||
setting default visibility to hidden by adding
 | 
			
		||||
-fvisibility=hidden (for gcc)
 | 
			
		||||
or
 | 
			
		||||
-xldscope=hidden (for sun cc)
 | 
			
		||||
to CFLAGS
 | 
			
		||||
 | 
			
		||||
then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#define CJSON_CDECL __cdecl
 | 
			
		||||
#define CJSON_STDCALL __stdcall
 | 
			
		||||
 | 
			
		||||
/* export symbols by default, this is necessary for copy pasting the C and header file */
 | 
			
		||||
#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
 | 
			
		||||
#define CJSON_EXPORT_SYMBOLS
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(CJSON_HIDE_SYMBOLS)
 | 
			
		||||
#define CJSON_PUBLIC(type)   type CJSON_STDCALL
 | 
			
		||||
#elif defined(CJSON_EXPORT_SYMBOLS)
 | 
			
		||||
#define CJSON_PUBLIC(type)   __declspec(dllexport) type CJSON_STDCALL
 | 
			
		||||
#elif defined(CJSON_IMPORT_SYMBOLS)
 | 
			
		||||
#define CJSON_PUBLIC(type)   __declspec(dllimport) type CJSON_STDCALL
 | 
			
		||||
#endif
 | 
			
		||||
#else /* !__WINDOWS__ */
 | 
			
		||||
#define CJSON_CDECL
 | 
			
		||||
#define CJSON_STDCALL
 | 
			
		||||
 | 
			
		||||
#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
 | 
			
		||||
#define CJSON_PUBLIC(type)   __attribute__((visibility("default"))) type
 | 
			
		||||
#else
 | 
			
		||||
#define CJSON_PUBLIC(type) type
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* project version */
 | 
			
		||||
#define CJSON_VERSION_MAJOR 1
 | 
			
		||||
#define CJSON_VERSION_MINOR 7
 | 
			
		||||
#define CJSON_VERSION_PATCH 15
 | 
			
		||||
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
 | 
			
		||||
/* cJSON Types: */
 | 
			
		||||
#define cJSON_Invalid (0)
 | 
			
		||||
#define cJSON_False  (1 << 0)
 | 
			
		||||
#define cJSON_True   (1 << 1)
 | 
			
		||||
#define cJSON_NULL   (1 << 2)
 | 
			
		||||
#define cJSON_Number (1 << 3)
 | 
			
		||||
#define cJSON_String (1 << 4)
 | 
			
		||||
#define cJSON_Array  (1 << 5)
 | 
			
		||||
#define cJSON_Object (1 << 6)
 | 
			
		||||
#define cJSON_Raw    (1 << 7) /* raw json */
 | 
			
		||||
 | 
			
		||||
#define cJSON_IsReference 256
 | 
			
		||||
#define cJSON_StringIsConst 512
 | 
			
		||||
 | 
			
		||||
/* The cJSON structure: */
 | 
			
		||||
typedef struct cJSON
 | 
			
		||||
{
 | 
			
		||||
    /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
 | 
			
		||||
    struct cJSON *next;
 | 
			
		||||
    struct cJSON *prev;
 | 
			
		||||
    /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
 | 
			
		||||
    struct cJSON *child;
 | 
			
		||||
 | 
			
		||||
    /* The type of the item, as above. */
 | 
			
		||||
    int type;
 | 
			
		||||
 | 
			
		||||
    /* The item's string, if type==cJSON_String  and type == cJSON_Raw */
 | 
			
		||||
    char *valuestring;
 | 
			
		||||
    /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
 | 
			
		||||
    int valueint;
 | 
			
		||||
    /* The item's number, if type==cJSON_Number */
 | 
			
		||||
    double valuedouble;
 | 
			
		||||
 | 
			
		||||
    /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
 | 
			
		||||
    char *string;
 | 
			
		||||
} cJSON;
 | 
			
		||||
 | 
			
		||||
typedef struct cJSON_Hooks
 | 
			
		||||
{
 | 
			
		||||
      /* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */
 | 
			
		||||
      void *(CJSON_CDECL *malloc_fn)(size_t sz);
 | 
			
		||||
      void (CJSON_CDECL *free_fn)(void *ptr);
 | 
			
		||||
} cJSON_Hooks;
 | 
			
		||||
 | 
			
		||||
typedef int cJSON_bool;
 | 
			
		||||
 | 
			
		||||
/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.
 | 
			
		||||
 * This is to prevent stack overflows. */
 | 
			
		||||
#ifndef CJSON_NESTING_LIMIT
 | 
			
		||||
#define CJSON_NESTING_LIMIT 1000
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* returns the version of cJSON as a string */
 | 
			
		||||
CJSON_PUBLIC(const char*) cJSON_Version(void);
 | 
			
		||||
 | 
			
		||||
/* Supply malloc, realloc and free functions to cJSON */
 | 
			
		||||
CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
 | 
			
		||||
 | 
			
		||||
/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */
 | 
			
		||||
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
 | 
			
		||||
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
 | 
			
		||||
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length);
 | 
			
		||||
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
 | 
			
		||||
/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */
 | 
			
		||||
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
 | 
			
		||||
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated);
 | 
			
		||||
 | 
			
		||||
/* Render a cJSON entity to text for transfer/storage. */
 | 
			
		||||
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
 | 
			
		||||
/* Render a cJSON entity to text for transfer/storage without any formatting. */
 | 
			
		||||
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
 | 
			
		||||
/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
 | 
			
		||||
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
 | 
			
		||||
/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */
 | 
			
		||||
/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
 | 
			
		||||
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
 | 
			
		||||
/* Delete a cJSON entity and all subentities. */
 | 
			
		||||
CJSON_PUBLIC(void) cJSON_Delete(cJSON *item);
 | 
			
		||||
 | 
			
		||||
/* Returns the number of items in an array (or object). */
 | 
			
		||||
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
 | 
			
		||||
/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */
 | 
			
		||||
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
 | 
			
		||||
/* Get item "string" from object. Case insensitive. */
 | 
			
		||||
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
 | 
			
		||||
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);
 | 
			
		||||
CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string);
 | 
			
		||||
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
 | 
			
		||||
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
 | 
			
		||||
 | 
			
		||||
/* Check item type and return its value */
 | 
			
		||||
CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item);
 | 
			
		||||
CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item);
 | 
			
		||||
 | 
			
		||||
/* These functions check the type of an item */
 | 
			
		||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
 | 
			
		||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
 | 
			
		||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
 | 
			
		||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
 | 
			
		||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
 | 
			
		||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
 | 
			
		||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
 | 
			
		||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
 | 
			
		||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
 | 
			
		||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);
 | 
			
		||||
 | 
			
		||||
/* These calls create a cJSON item of the appropriate type. */
 | 
			
		||||
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
 | 
			
		||||
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
 | 
			
		||||
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
 | 
			
		||||
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
 | 
			
		||||
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
 | 
			
		||||
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
 | 
			
		||||
/* raw json */
 | 
			
		||||
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
 | 
			
		||||
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
 | 
			
		||||
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
 | 
			
		||||
 | 
			
		||||
/* Create a string where valuestring references a string so
 | 
			
		||||
 * it will not be freed by cJSON_Delete */
 | 
			
		||||
CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);
 | 
			
		||||
/* Create an object/array that only references it's elements so
 | 
			
		||||
 * they will not be freed by cJSON_Delete */
 | 
			
		||||
CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
 | 
			
		||||
CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);
 | 
			
		||||
 | 
			
		||||
/* These utilities create an Array of count items.
 | 
			
		||||
 * The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/
 | 
			
		||||
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
 | 
			
		||||
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
 | 
			
		||||
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
 | 
			
		||||
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count);
 | 
			
		||||
 | 
			
		||||
/* Append item to the specified array/object. */
 | 
			
		||||
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item);
 | 
			
		||||
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
 | 
			
		||||
/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object.
 | 
			
		||||
 * WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
 | 
			
		||||
 * writing to `item->string` */
 | 
			
		||||
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
 | 
			
		||||
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
 | 
			
		||||
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
 | 
			
		||||
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
 | 
			
		||||
 | 
			
		||||
/* Remove/Detach items from Arrays/Objects. */
 | 
			
		||||
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
 | 
			
		||||
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
 | 
			
		||||
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
 | 
			
		||||
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
 | 
			
		||||
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);
 | 
			
		||||
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string);
 | 
			
		||||
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
 | 
			
		||||
 | 
			
		||||
/* Update array items. */
 | 
			
		||||
CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
 | 
			
		||||
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);
 | 
			
		||||
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
 | 
			
		||||
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
 | 
			
		||||
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
 | 
			
		||||
 | 
			
		||||
/* Duplicate a cJSON item */
 | 
			
		||||
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
 | 
			
		||||
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
 | 
			
		||||
 * need to be released. With recurse!=0, it will duplicate any children connected to the item.
 | 
			
		||||
 * The item->next and ->prev pointers are always zero on return from Duplicate. */
 | 
			
		||||
/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal.
 | 
			
		||||
 * case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */
 | 
			
		||||
CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);
 | 
			
		||||
 | 
			
		||||
/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings.
 | 
			
		||||
 * The input pointer json cannot point to a read-only address area, such as a string constant, 
 | 
			
		||||
 * but should point to a readable and writable address area. */
 | 
			
		||||
CJSON_PUBLIC(void) cJSON_Minify(char *json);
 | 
			
		||||
 | 
			
		||||
/* Helper functions for creating and adding items to an object at the same time.
 | 
			
		||||
 * They return the added item or NULL on failure. */
 | 
			
		||||
CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);
 | 
			
		||||
CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
 | 
			
		||||
CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
 | 
			
		||||
CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
 | 
			
		||||
CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
 | 
			
		||||
CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
 | 
			
		||||
CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
 | 
			
		||||
CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
 | 
			
		||||
CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);
 | 
			
		||||
 | 
			
		||||
/* When assigning an integer value, it needs to be propagated to valuedouble too. */
 | 
			
		||||
#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
 | 
			
		||||
/* helper for the cJSON_SetNumberValue macro */
 | 
			
		||||
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
 | 
			
		||||
#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))
 | 
			
		||||
/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */
 | 
			
		||||
CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring);
 | 
			
		||||
 | 
			
		||||
/* If the object is not a boolean type this does nothing and returns cJSON_Invalid else it returns the new type*/
 | 
			
		||||
#define cJSON_SetBoolValue(object, boolValue) ( \
 | 
			
		||||
    (object != NULL && ((object)->type & (cJSON_False|cJSON_True))) ? \
 | 
			
		||||
    (object)->type=((object)->type &(~(cJSON_False|cJSON_True)))|((boolValue)?cJSON_True:cJSON_False) : \
 | 
			
		||||
    cJSON_Invalid\
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
/* Macro for iterating over an array or object */
 | 
			
		||||
#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
 | 
			
		||||
 | 
			
		||||
/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */
 | 
			
		||||
CJSON_PUBLIC(void *) cJSON_malloc(size_t size);
 | 
			
		||||
CJSON_PUBLIC(void) cJSON_free(void *object);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -0,0 +1,79 @@
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include "cJSON.h"
 | 
			
		||||
#include "cfg.h"
 | 
			
		||||
 | 
			
		||||
/* 配置文件的内容格式:
 | 
			
		||||
 *
 | 
			
		||||
 * { "URI":"NBL71OPZ8I.iotcloud.tencentdevices.com",
 | 
			
		||||
 *       "clientid" : "NBL71OPZ8Ihome_control_01",
 | 
			
		||||
 *		 "username" : "NBL71OPZ8Ihome_control_01;12010126;WB2UN;1726024103",
 | 
			
		||||
 *		 "password" : "023215a9420a3d983d73a2cb4c0f7d13bdbcb7a9d97c3963a36f79ea76cfc172;hmacsha256"
 | 
			
		||||
 *       "ProductID": "NBL71OPZ8I",
 | 
			
		||||
 *       "DeviceName": "home_control_01"
 | 
			
		||||
 * }
 | 
			
		||||
 * 
 | 
			
		||||
 */
 | 
			
		||||
int read_cfg(char *URI, char *clientid, char *username, char *password, char *ProductID, char *DeviceName)
 | 
			
		||||
{
 | 
			
		||||
	char buf[1000];
 | 
			
		||||
	cJSON *ptTemp;
 | 
			
		||||
	
 | 
			
		||||
	int fd = open(CFG_FILE, O_RDONLY);
 | 
			
		||||
	
 | 
			
		||||
	if (fd < 0)
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	int ret = read(fd, buf, sizeof(buf));
 | 
			
		||||
	if (ret <= 0)
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	cJSON *root = cJSON_Parse(buf);
 | 
			
		||||
 | 
			
		||||
	ptTemp = cJSON_GetObjectItem(root, "URI");
 | 
			
		||||
	if (ptTemp)
 | 
			
		||||
	{
 | 
			
		||||
		strcpy(URI, ptTemp->valuestring);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ptTemp = cJSON_GetObjectItem(root, "clientid");
 | 
			
		||||
	if (ptTemp)
 | 
			
		||||
	{
 | 
			
		||||
		strcpy(clientid, ptTemp->valuestring);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	ptTemp = cJSON_GetObjectItem(root, "username");
 | 
			
		||||
	if (ptTemp)
 | 
			
		||||
	{
 | 
			
		||||
		strcpy(username, ptTemp->valuestring);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ptTemp = cJSON_GetObjectItem(root, "password");
 | 
			
		||||
	if (ptTemp)
 | 
			
		||||
	{
 | 
			
		||||
		strcpy(password, ptTemp->valuestring);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ptTemp = cJSON_GetObjectItem(root, "ProductID");
 | 
			
		||||
	if (ptTemp)
 | 
			
		||||
	{
 | 
			
		||||
		strcpy(ProductID, ptTemp->valuestring);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ptTemp = cJSON_GetObjectItem(root, "DeviceName");
 | 
			
		||||
	if (ptTemp)
 | 
			
		||||
	{
 | 
			
		||||
		strcpy(DeviceName, ptTemp->valuestring);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cJSON_Delete(root);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -0,0 +1,8 @@
 | 
			
		||||
#ifndef _CFG_H
 | 
			
		||||
#define _CFG_H
 | 
			
		||||
 | 
			
		||||
#define CFG_FILE "/etc/wechat.cfg"
 | 
			
		||||
 | 
			
		||||
int read_cfg(char *URI, char *clientid, char *username, char *password, char *ProductID, char *DeviceName);
 | 
			
		||||
 | 
			
		||||
#endif /* _CFG_H */
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							@@ -0,0 +1,214 @@
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * Copyright (c) 2012, 2023 IBM Corp., Ian Craggs
 | 
			
		||||
 *
 | 
			
		||||
 * All rights reserved. This program and the accompanying materials
 | 
			
		||||
 * are made available under the terms of the Eclipse Public License v2.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.
 | 
			
		||||
 *
 | 
			
		||||
 * Contributors:
 | 
			
		||||
 *    Ian Craggs - initial contribution
 | 
			
		||||
 *******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include "MQTTClient.h"
 | 
			
		||||
#include "cJSON.h"
 | 
			
		||||
#include "rpc_client.h"
 | 
			
		||||
#include "cfg.h"
 | 
			
		||||
 | 
			
		||||
#define ADDRESS     "tcp://192.168.5.10:1883"
 | 
			
		||||
#define CLIENTID    "ExampleClientSub"
 | 
			
		||||
#define TOPIC_SUBSCRIBE     "/iot/down"
 | 
			
		||||
#define TOPIC_PUBLISH       "/iot/up"
 | 
			
		||||
#define QOS         1
 | 
			
		||||
#define TIMEOUT     10000L
 | 
			
		||||
 | 
			
		||||
#define USER_NAME "100ask"
 | 
			
		||||
#define PASSWORD  "100ask"
 | 
			
		||||
 | 
			
		||||
volatile MQTTClient_deliveryToken deliveredtoken;
 | 
			
		||||
 | 
			
		||||
void delivered(void *context, MQTTClient_deliveryToken dt)
 | 
			
		||||
{
 | 
			
		||||
    printf("Message with token value %d delivery confirmed\n", dt);
 | 
			
		||||
    deliveredtoken = dt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message)
 | 
			
		||||
{
 | 
			
		||||
    printf("Message arrived\n");
 | 
			
		||||
    printf("     topic: %s\n", topicName);
 | 
			
		||||
    printf("   message: %.*s\n", message->payloadlen, (char*)message->payload);
 | 
			
		||||
 | 
			
		||||
    /* 根据接收到的消息控制LED */
 | 
			
		||||
	/* 消息格式: {"method":"control","clientToken":"v2177557380FdRVD::DU2S%vwG7","params":{"LED1":0}} */
 | 
			
		||||
	cJSON *root = cJSON_Parse((char*)message->payload);
 | 
			
		||||
	cJSON *ptTemp = cJSON_GetObjectItem(root, "params");
 | 
			
		||||
	if (ptTemp)
 | 
			
		||||
	{
 | 
			
		||||
		cJSON *led1 = cJSON_GetObjectItem(ptTemp, "LED1");
 | 
			
		||||
		if (led1)
 | 
			
		||||
		{
 | 
			
		||||
			rpc_led_control(led1->valueint);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	cJSON_Delete(root);
 | 
			
		||||
 | 
			
		||||
    MQTTClient_freeMessage(&message);
 | 
			
		||||
    MQTTClient_free(topicName);
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void connlost(void *context, char *cause)
 | 
			
		||||
{
 | 
			
		||||
    printf("\nConnection lost\n");
 | 
			
		||||
    if (cause)
 | 
			
		||||
    	printf("     cause: %s\n", cause);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char* argv[])
 | 
			
		||||
{
 | 
			
		||||
    MQTTClient client;
 | 
			
		||||
    MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
 | 
			
		||||
    int rc;
 | 
			
		||||
 | 
			
		||||
	char URI[1000];
 | 
			
		||||
	char clientid[1000]; 
 | 
			
		||||
	char username[1000]; 
 | 
			
		||||
	char password[1000]; 
 | 
			
		||||
	char ProductID[1000]; 
 | 
			
		||||
	char DeviceName[1000];
 | 
			
		||||
 | 
			
		||||
	char address[1000];
 | 
			
		||||
 | 
			
		||||
	char pub_topic[1000]; /* $thing/up/property/{ProductID}/{DeviceName} */
 | 
			
		||||
	char sub_topic[1000]; /* $thing/down/property/{ProductID}/{DeviceName} */
 | 
			
		||||
 | 
			
		||||
    /* 读配置文件 /etc/wechat.cfg得到URI,CLIENTID,USERNAME,PASSWD,ProductID,DeviceName */
 | 
			
		||||
	if ( 0 != read_cfg(URI, clientid, username, password, ProductID, DeviceName))
 | 
			
		||||
	{
 | 
			
		||||
		printf("read cfg err\n");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	sprintf(address, "tcp://%s:1883", URI);
 | 
			
		||||
	sprintf(pub_topic, "$thing/up/property/%s/%s", ProductID, DeviceName);
 | 
			
		||||
	sprintf(sub_topic, "$thing/down/property/%s/%s", ProductID, DeviceName);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /* INIT RPC: connect RPC Server */    
 | 
			
		||||
    if (-1 == RPC_Client_Init())
 | 
			
		||||
	{
 | 
			
		||||
		printf("RPC_Client_Init err\n");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
    if ((rc = MQTTClient_create(&client, address, clientid,
 | 
			
		||||
        MQTTCLIENT_PERSISTENCE_NONE, NULL)) != MQTTCLIENT_SUCCESS)
 | 
			
		||||
    {
 | 
			
		||||
        printf("Failed to create client, return code %d\n", rc);
 | 
			
		||||
        rc = EXIT_FAILURE;
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((rc = MQTTClient_setCallbacks(client, NULL, connlost, msgarrvd, delivered)) != MQTTCLIENT_SUCCESS)
 | 
			
		||||
    {
 | 
			
		||||
        printf("Failed to set callbacks, return code %d\n", rc);
 | 
			
		||||
        rc = EXIT_FAILURE;
 | 
			
		||||
        goto destroy_exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    conn_opts.keepAliveInterval = 20;
 | 
			
		||||
    conn_opts.cleansession = 1;
 | 
			
		||||
    conn_opts.username = username;
 | 
			
		||||
    conn_opts.password = password;
 | 
			
		||||
 | 
			
		||||
    while (1)
 | 
			
		||||
    {
 | 
			
		||||
	    if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
 | 
			
		||||
	    {
 | 
			
		||||
		printf("Failed to connect, return code %d\n", rc);
 | 
			
		||||
		rc = EXIT_FAILURE;
 | 
			
		||||
		//goto destroy_exit;
 | 
			
		||||
	    }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    printf("Subscribing to topic %s\nfor client %s using QoS%d\n\n"
 | 
			
		||||
           "Press Q<Enter> to quit\n\n", TOPIC_SUBSCRIBE, CLIENTID, QOS);
 | 
			
		||||
    if ((rc = MQTTClient_subscribe(client, sub_topic, QOS)) != MQTTCLIENT_SUCCESS)
 | 
			
		||||
    {
 | 
			
		||||
    	printf("Failed to subscribe, return code %d\n", rc);
 | 
			
		||||
    	rc = EXIT_FAILURE;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
    	int ch;
 | 
			
		||||
        int cnt = 0;
 | 
			
		||||
        MQTTClient_message pubmsg = MQTTClient_message_initializer;
 | 
			
		||||
        char buf[1000];
 | 
			
		||||
        MQTTClient_deliveryToken token;
 | 
			
		||||
        
 | 
			
		||||
    	while (1)
 | 
			
		||||
    	{
 | 
			
		||||
            /* rpc_dht11_read */
 | 
			
		||||
			char humi, temp;
 | 
			
		||||
			
 | 
			
		||||
			while (0 !=rpc_dht11_read(&humi, &temp));
 | 
			
		||||
 | 
			
		||||
            sprintf(buf, "\
 | 
			
		||||
				{ \
 | 
			
		||||
					\"method\":\"report\",\
 | 
			
		||||
					\"clientToken\":\"v2530526688yDDou::d791c1a6-1a4b-4a44-b313-f911d704d765\",\
 | 
			
		||||
					\"timestamp\":1628646783,\
 | 
			
		||||
					\"params\":{\
 | 
			
		||||
						\"temp_value\":%d,\
 | 
			
		||||
					    \"humi_value\":%d\
 | 
			
		||||
					}\
 | 
			
		||||
				}", temp, humi);
 | 
			
		||||
				
 | 
			
		||||
            pubmsg.payload = buf;
 | 
			
		||||
            pubmsg.payloadlen = (int)strlen(buf);
 | 
			
		||||
            pubmsg.qos = QOS;
 | 
			
		||||
            pubmsg.retained = 0;
 | 
			
		||||
 | 
			
		||||
            /* 发布消息 */
 | 
			
		||||
 | 
			
		||||
            if ((rc = MQTTClient_publishMessage(client, pub_topic, &pubmsg, &token)) != MQTTCLIENT_SUCCESS)
 | 
			
		||||
            {
 | 
			
		||||
                 printf("Failed to publish message, return code %d\n", rc);
 | 
			
		||||
                 continue;
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            rc = MQTTClient_waitForCompletion(client, token, TIMEOUT);
 | 
			
		||||
            printf("Message with delivery token %d delivered\n", token);                        
 | 
			
		||||
 | 
			
		||||
			sleep(5);
 | 
			
		||||
    	} 
 | 
			
		||||
 | 
			
		||||
        if ((rc = MQTTClient_unsubscribe(client, sub_topic)) != MQTTCLIENT_SUCCESS)
 | 
			
		||||
        {
 | 
			
		||||
        	printf("Failed to unsubscribe, return code %d\n", rc);
 | 
			
		||||
        	rc = EXIT_FAILURE;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((rc = MQTTClient_disconnect(client, 10000)) != MQTTCLIENT_SUCCESS)
 | 
			
		||||
    {
 | 
			
		||||
    	printf("Failed to disconnect, return code %d\n", rc);
 | 
			
		||||
    	rc = EXIT_FAILURE;
 | 
			
		||||
    }
 | 
			
		||||
destroy_exit:
 | 
			
		||||
    MQTTClient_destroy(&client);
 | 
			
		||||
exit:
 | 
			
		||||
    return rc;
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,8 @@
 | 
			
		||||
#ifndef _RPC_H
 | 
			
		||||
#define _RPC_H
 | 
			
		||||
 | 
			
		||||
#define PORT 1234
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@@ -0,0 +1,144 @@
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <netinet/in.h>
 | 
			
		||||
#include <arpa/inet.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include "cJSON.h"
 | 
			
		||||
#include "rpc.h"
 | 
			
		||||
 | 
			
		||||
static int g_iSocketClient;
 | 
			
		||||
 | 
			
		||||
int rpc_led_control(int on)
 | 
			
		||||
{
 | 
			
		||||
    char buf[100];
 | 
			
		||||
    int iLen;
 | 
			
		||||
    int ret = -1;
 | 
			
		||||
 | 
			
		||||
    int iSocketClient = g_iSocketClient;
 | 
			
		||||
 | 
			
		||||
    sprintf(buf, "{\"method\": \"led_control\", \"params\": [%d], \"id\": \"2\" }", on);
 | 
			
		||||
    iLen = send(iSocketClient, buf, strlen(buf), 0);
 | 
			
		||||
    if (iLen ==  strlen(buf))
 | 
			
		||||
    {
 | 
			
		||||
        while (1) 
 | 
			
		||||
        {
 | 
			
		||||
            iLen = read(iSocketClient, buf, sizeof(buf));
 | 
			
		||||
            buf[iLen] = 0;
 | 
			
		||||
            if (iLen == 1 && (buf[0] == '\r' || buf[0] == '\n'))
 | 
			
		||||
                continue;
 | 
			
		||||
            else
 | 
			
		||||
                break;
 | 
			
		||||
        } 
 | 
			
		||||
        
 | 
			
		||||
        if (iLen > 0)
 | 
			
		||||
        {
 | 
			
		||||
            cJSON *root = cJSON_Parse(buf);
 | 
			
		||||
            cJSON *result = cJSON_GetObjectItem(root, "result");
 | 
			
		||||
            ret = result->valueint;
 | 
			
		||||
            cJSON_Delete(root);
 | 
			
		||||
            return ret;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            printf("read rpc reply err : %d\n", iLen);
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        printf("send rpc request err : %d, %s\n", iLen, strerror(errno));
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int rpc_dht11_read(char *humi, char *temp)
 | 
			
		||||
{
 | 
			
		||||
    char buf[300];
 | 
			
		||||
    int iLen;
 | 
			
		||||
 | 
			
		||||
    int iSocketClient = g_iSocketClient;
 | 
			
		||||
 | 
			
		||||
    sprintf(buf, "{\"method\": \"dht11_read\"," \
 | 
			
		||||
                   "\"params\": [0], \"id\": \"2\" }");        
 | 
			
		||||
            
 | 
			
		||||
    iLen = send(iSocketClient, buf, strlen(buf), 0);
 | 
			
		||||
    if (iLen ==  strlen(buf))
 | 
			
		||||
    {
 | 
			
		||||
        while (1) 
 | 
			
		||||
        {
 | 
			
		||||
            iLen = read(iSocketClient, buf, sizeof(buf));
 | 
			
		||||
            buf[iLen] = 0;
 | 
			
		||||
            if (iLen == 1 && (buf[0] == '\r' || buf[0] == '\n'))
 | 
			
		||||
                continue;
 | 
			
		||||
            else
 | 
			
		||||
                break;
 | 
			
		||||
        } 
 | 
			
		||||
        
 | 
			
		||||
        if (iLen > 0)
 | 
			
		||||
        {
 | 
			
		||||
            cJSON *root = cJSON_Parse(buf);
 | 
			
		||||
            cJSON *result = cJSON_GetObjectItem(root, "result");
 | 
			
		||||
            if (result)
 | 
			
		||||
            {
 | 
			
		||||
                cJSON * a = cJSON_GetArrayItem(result,0);
 | 
			
		||||
                cJSON * b = cJSON_GetArrayItem(result,1);
 | 
			
		||||
 | 
			
		||||
                *humi = a->valueint;
 | 
			
		||||
                *temp = b->valueint;
 | 
			
		||||
                
 | 
			
		||||
                cJSON_Delete(root);
 | 
			
		||||
                return 0;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                cJSON_Delete(root);
 | 
			
		||||
                return -1;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            printf("read rpc reply err : %d\n", iLen);
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        printf("send rpc request err : %d, %s\n", iLen, strerror(errno));
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 连接RPC Server
 | 
			
		||||
 * 返回值: (>0)socket, (-1)失败
 | 
			
		||||
 */
 | 
			
		||||
int RPC_Client_Init(void) 
 | 
			
		||||
{
 | 
			
		||||
    int iSocketClient;
 | 
			
		||||
    struct sockaddr_in tSocketServerAddr;
 | 
			
		||||
    int iRet;
 | 
			
		||||
 | 
			
		||||
    iSocketClient = socket(AF_INET, SOCK_STREAM, 0);
 | 
			
		||||
 | 
			
		||||
    tSocketServerAddr.sin_family      = AF_INET;
 | 
			
		||||
    tSocketServerAddr.sin_port        = htons(PORT);  /* host to net, short */
 | 
			
		||||
    //tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;
 | 
			
		||||
    inet_aton("127.0.0.1", &tSocketServerAddr.sin_addr);
 | 
			
		||||
    memset(tSocketServerAddr.sin_zero, 0, 8);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    iRet = connect(iSocketClient, (const struct sockaddr *)&tSocketServerAddr, sizeof(struct sockaddr));	
 | 
			
		||||
    if (-1 == iRet)
 | 
			
		||||
    {
 | 
			
		||||
        printf("connect error!\n");
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    g_iSocketClient = iSocketClient;
 | 
			
		||||
    return iSocketClient;    
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,16 @@
 | 
			
		||||
#ifndef _RPC_CLIENT_H
 | 
			
		||||
#define _RPC_CLIENT_H
 | 
			
		||||
 | 
			
		||||
int rpc_led_control(int on);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int rpc_dht11_read(char *humi, char *temp);
 | 
			
		||||
 | 
			
		||||
/* 连接RPC Server
 | 
			
		||||
 * 返回值: (>0)socket, (-1)失败
 | 
			
		||||
 */
 | 
			
		||||
int RPC_Client_Init(void) ;
 | 
			
		||||
 | 
			
		||||
#endif /* _RPC_CLIENT_H */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
		Reference in New Issue
	
	Block a user