Initial Commit
parent
0a4e296937
commit
4172078d7b
@ -0,0 +1,293 @@
|
||||
/*
|
||||
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 13
|
||||
|
||||
#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 adress 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);
|
||||
|
||||
/* 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,66 @@
|
||||
#ifndef _COMMON_H
|
||||
#define _COMMON_H
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include "cJSON.h"
|
||||
|
||||
#define MAX_ITEM_LEN 32
|
||||
|
||||
#define CFG_FILE "dev_desc.json"
|
||||
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef int int32_t;
|
||||
typedef short int16_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* data */
|
||||
char port[MAX_ITEM_LEN];
|
||||
char addr[MAX_ITEM_LEN];
|
||||
char desc[MAX_ITEM_LEN];
|
||||
char model[MAX_ITEM_LEN];
|
||||
}DEV_DESC_TYPE;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* data */
|
||||
char baud[MAX_ITEM_LEN];
|
||||
char bits[MAX_ITEM_LEN];
|
||||
char parity[MAX_ITEM_LEN];
|
||||
}PORT_CFG_TYPE;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* data */
|
||||
DEV_DESC_TYPE dev_desc;
|
||||
PORT_CFG_TYPE port_cfg;
|
||||
}DEV_CFG_INFO;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* data */
|
||||
uint32_t cmd;
|
||||
uint32_t t;
|
||||
uint32_t argv[250];
|
||||
}COM_MSG_TYPE;
|
||||
|
||||
|
||||
extern DEV_CFG_INFO dev_cfg;
|
||||
|
||||
char *get_time_in_json(void);
|
||||
char *make_token(char *token,char len);
|
||||
char *read_file(char *file_name,int32_t *ret);
|
||||
int32_t read_dev_cfg(DEV_CFG_INFO *p);
|
||||
cJSON *file_to_json(char *file);
|
||||
int split(char *src,const char *separator,char **dest);
|
||||
|
||||
int32_t save_to_file(char *file,uint32_t pos,uint8_t *buf,uint32_t size);
|
||||
int32_t load_from_file(char *file,uint32_t pos,uint8_t *buf,uint32_t size);
|
||||
#endif
|
@ -0,0 +1,9 @@
|
||||
#ifndef _CRC_H
|
||||
#define _CRC_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
uint16_t crc16(unsigned char *puchMsg,unsigned int usDataLen);
|
||||
void crc16_ex(unsigned char *puchMsg,unsigned int usDataLen,unsigned char *result);
|
||||
|
||||
#endif
|
@ -0,0 +1,8 @@
|
||||
#ifndef __dynamic_libs_h__
|
||||
#define __dynamic_libs_h__
|
||||
|
||||
/* #include "apue.h" */
|
||||
int dynamic_lib_func_add(int i1, int i2);
|
||||
int dynamic_lib_func_mul(int i1, int i2);
|
||||
|
||||
#endif
|
@ -0,0 +1,38 @@
|
||||
#ifndef _IEC61850_PROCESS_H
|
||||
#define _IEC61850_PROCESS_H
|
||||
|
||||
#include "scl_shm.h"
|
||||
|
||||
|
||||
#define IEC61850_RX_MQ "/iec_rx_mq"
|
||||
#define IEC61850_RX_MAX_MESSAGE 32
|
||||
#define IEC61850_RX_MESSAGE_SIZE 1024
|
||||
#define IEC61850_RX_MQ_PRIO 31
|
||||
|
||||
|
||||
#define CMD_SEND_PRI_DATA 16
|
||||
|
||||
typedef struct
|
||||
{
|
||||
USR_MV AccPri[19];
|
||||
USR_MV AccSec[7];
|
||||
USR_MV EnvNoiPri;
|
||||
USR_MV EnvNoiSec;
|
||||
USR_MV NeuCur;
|
||||
USR_MV MoDevConf;
|
||||
USR_MV MoDevDetF;
|
||||
USR_MV MoDevSigF;
|
||||
USR_MV ModevPowF;
|
||||
USR_MV EnvNoiPriAlm;
|
||||
USR_MV EnvNoiSecAlm;
|
||||
USR_MV NeuCurAlm;
|
||||
USR_MV AccPriAlm[19];
|
||||
USR_MV AccSecAlm[7];
|
||||
}LN_SVBR_TYPE;
|
||||
|
||||
|
||||
extern int iec61850_rx_init(void);
|
||||
extern int iec61850_send_msg(void *msg,int msg_len);
|
||||
|
||||
|
||||
#endif
|
@ -0,0 +1,13 @@
|
||||
#ifndef _MAIN_H
|
||||
#define _MAIN_H
|
||||
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
#include "common.h"
|
||||
|
||||
#endif
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright © 2001-2011 Stéphane Raimbault <stephane.raimbault@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
#ifndef MODBUS_RTU_H
|
||||
#define MODBUS_RTU_H
|
||||
|
||||
#include "modbus.h"
|
||||
|
||||
MODBUS_BEGIN_DECLS
|
||||
|
||||
/* Modbus_Application_Protocol_V1_1b.pdf Chapter 4 Section 1 Page 5
|
||||
* RS232 / RS485 ADU = 253 bytes + slave (1 byte) + CRC (2 bytes) = 256 bytes
|
||||
*/
|
||||
#define MODBUS_RTU_MAX_ADU_LENGTH 256
|
||||
|
||||
MODBUS_API modbus_t* modbus_new_rtu(const char *device, int baud, char parity,
|
||||
int data_bit, int stop_bit);
|
||||
|
||||
#define MODBUS_RTU_RS232 0
|
||||
#define MODBUS_RTU_RS485 1
|
||||
|
||||
MODBUS_API int modbus_rtu_set_serial_mode(modbus_t *ctx, int mode);
|
||||
MODBUS_API int modbus_rtu_get_serial_mode(modbus_t *ctx);
|
||||
|
||||
#define MODBUS_RTU_RTS_NONE 0
|
||||
#define MODBUS_RTU_RTS_UP 1
|
||||
#define MODBUS_RTU_RTS_DOWN 2
|
||||
|
||||
MODBUS_API int modbus_rtu_set_rts(modbus_t *ctx, int mode);
|
||||
MODBUS_API int modbus_rtu_get_rts(modbus_t *ctx);
|
||||
|
||||
MODBUS_API int modbus_rtu_set_custom_rts(modbus_t *ctx, void (*set_rts) (modbus_t *ctx, int on));
|
||||
|
||||
MODBUS_API int modbus_rtu_set_rts_delay(modbus_t *ctx, int us);
|
||||
MODBUS_API int modbus_rtu_get_rts_delay(modbus_t *ctx);
|
||||
|
||||
MODBUS_END_DECLS
|
||||
|
||||
#endif /* MODBUS_RTU_H */
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright © 2001-2010 Stéphane Raimbault <stephane.raimbault@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
#ifndef MODBUS_TCP_H
|
||||
#define MODBUS_TCP_H
|
||||
|
||||
#include "modbus.h"
|
||||
|
||||
MODBUS_BEGIN_DECLS
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
/* Win32 with MinGW, supplement to <errno.h> */
|
||||
#include <winsock2.h>
|
||||
#if !defined(ECONNRESET)
|
||||
#define ECONNRESET WSAECONNRESET
|
||||
#endif
|
||||
#if !defined(ECONNREFUSED)
|
||||
#define ECONNREFUSED WSAECONNREFUSED
|
||||
#endif
|
||||
#if !defined(ETIMEDOUT)
|
||||
#define ETIMEDOUT WSAETIMEDOUT
|
||||
#endif
|
||||
#if !defined(ENOPROTOOPT)
|
||||
#define ENOPROTOOPT WSAENOPROTOOPT
|
||||
#endif
|
||||
#if !defined(EINPROGRESS)
|
||||
#define EINPROGRESS WSAEINPROGRESS
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define MODBUS_TCP_DEFAULT_PORT 502
|
||||
#define MODBUS_TCP_SLAVE 0xFF
|
||||
|
||||
/* Modbus_Application_Protocol_V1_1b.pdf Chapter 4 Section 1 Page 5
|
||||
* TCP MODBUS ADU = 253 bytes + MBAP (7 bytes) = 260 bytes
|
||||
*/
|
||||
#define MODBUS_TCP_MAX_ADU_LENGTH 260
|
||||
|
||||
MODBUS_API modbus_t* modbus_new_tcp(const char *ip_address, int port);
|
||||
MODBUS_API int modbus_tcp_listen(modbus_t *ctx, int nb_connection);
|
||||
MODBUS_API int modbus_tcp_accept(modbus_t *ctx, int *s);
|
||||
|
||||
MODBUS_API modbus_t* modbus_new_tcp_pi(const char *node, const char *service);
|
||||
MODBUS_API int modbus_tcp_pi_listen(modbus_t *ctx, int nb_connection);
|
||||
MODBUS_API int modbus_tcp_pi_accept(modbus_t *ctx, int *s);
|
||||
|
||||
MODBUS_END_DECLS
|
||||
|
||||
#endif /* MODBUS_TCP_H */
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright © 2010-2014 Stéphane Raimbault <stephane.raimbault@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef MODBUS_VERSION_H
|
||||
#define MODBUS_VERSION_H
|
||||
|
||||
/* The major version, (1, if %LIBMODBUS_VERSION is 1.2.3) */
|
||||
#define LIBMODBUS_VERSION_MAJOR (3)
|
||||
|
||||
/* The minor version (2, if %LIBMODBUS_VERSION is 1.2.3) */
|
||||
#define LIBMODBUS_VERSION_MINOR (1)
|
||||
|
||||
/* The micro version (3, if %LIBMODBUS_VERSION is 1.2.3) */
|
||||
#define LIBMODBUS_VERSION_MICRO (6)
|
||||
|
||||
/* The full version, like 1.2.3 */
|
||||
#define LIBMODBUS_VERSION 3.1.6
|
||||
|
||||
/* The full version, in string form (suited for string concatenation)
|
||||
*/
|
||||
#define LIBMODBUS_VERSION_STRING "3.1.6"
|
||||
|
||||
/* Numerically encoded version, eg. v1.2.3 is 0x010203 */
|
||||
#define LIBMODBUS_VERSION_HEX ((LIBMODBUS_VERSION_MAJOR << 16) | \
|
||||
(LIBMODBUS_VERSION_MINOR << 8) | \
|
||||
(LIBMODBUS_VERSION_MICRO << 0))
|
||||
|
||||
/* Evaluates to True if the version is greater than @major, @minor and @micro
|
||||
*/
|
||||
#define LIBMODBUS_VERSION_CHECK(major,minor,micro) \
|
||||
(LIBMODBUS_VERSION_MAJOR > (major) || \
|
||||
(LIBMODBUS_VERSION_MAJOR == (major) && \
|
||||
LIBMODBUS_VERSION_MINOR > (minor)) || \
|
||||
(LIBMODBUS_VERSION_MAJOR == (major) && \
|
||||
LIBMODBUS_VERSION_MINOR == (minor) && \
|
||||
LIBMODBUS_VERSION_MICRO >= (micro)))
|
||||
|
||||
#endif /* MODBUS_VERSION_H */
|
@ -0,0 +1,293 @@
|
||||
/*
|
||||
* Copyright © 2001-2013 Stéphane Raimbault <stephane.raimbault@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
#ifndef MODBUS_H
|
||||
#define MODBUS_H
|
||||
|
||||
/* Add this for macros that defined unix flavor */
|
||||
#if (defined(__unix__) || defined(unix)) && !defined(USG)
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#include <stdint.h>
|
||||
#else
|
||||
#include "stdint.h"
|
||||
#endif
|
||||
|
||||
#include "modbus-version.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# if defined(DLLBUILD)
|
||||
/* define DLLBUILD when building the DLL */
|
||||
# define MODBUS_API __declspec(dllexport)
|
||||
# else
|
||||
# define MODBUS_API __declspec(dllimport)
|
||||
# endif
|
||||
#else
|
||||
# define MODBUS_API
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
# define MODBUS_BEGIN_DECLS extern "C" {
|
||||
# define MODBUS_END_DECLS }
|
||||
#else
|
||||
# define MODBUS_BEGIN_DECLS
|
||||
# define MODBUS_END_DECLS
|
||||
#endif
|
||||
|
||||
MODBUS_BEGIN_DECLS
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef OFF
|
||||
#define OFF 0
|
||||
#endif
|
||||
|
||||
#ifndef ON
|
||||
#define ON 1
|
||||
#endif
|
||||
|
||||
/* Modbus function codes */
|
||||
#define MODBUS_FC_READ_COILS 0x01
|
||||
#define MODBUS_FC_READ_DISCRETE_INPUTS 0x02
|
||||
#define MODBUS_FC_READ_HOLDING_REGISTERS 0x03
|
||||
#define MODBUS_FC_READ_INPUT_REGISTERS 0x04
|
||||
#define MODBUS_FC_WRITE_SINGLE_COIL 0x05
|
||||
#define MODBUS_FC_WRITE_SINGLE_REGISTER 0x06
|
||||
#define MODBUS_FC_READ_EXCEPTION_STATUS 0x07
|
||||
#define MODBUS_FC_WRITE_MULTIPLE_COILS 0x0F
|
||||
#define MODBUS_FC_WRITE_MULTIPLE_REGISTERS 0x10
|
||||
#define MODBUS_FC_REPORT_SLAVE_ID 0x11
|
||||
#define MODBUS_FC_MASK_WRITE_REGISTER 0x16
|
||||
#define MODBUS_FC_WRITE_AND_READ_REGISTERS 0x17
|
||||
|
||||
#define MODBUS_BROADCAST_ADDRESS 0
|
||||
|
||||
/* Modbus_Application_Protocol_V1_1b.pdf (chapter 6 section 1 page 12)
|
||||
* Quantity of Coils to read (2 bytes): 1 to 2000 (0x7D0)
|
||||
* (chapter 6 section 11 page 29)
|
||||
* Quantity of Coils to write (2 bytes): 1 to 1968 (0x7B0)
|
||||
*/
|
||||
#define MODBUS_MAX_READ_BITS 2000
|
||||
#define MODBUS_MAX_WRITE_BITS 1968
|
||||
|
||||
/* Modbus_Application_Protocol_V1_1b.pdf (chapter 6 section 3 page 15)
|
||||
* Quantity of Registers to read (2 bytes): 1 to 125 (0x7D)
|
||||
* (chapter 6 section 12 page 31)
|
||||
* Quantity of Registers to write (2 bytes) 1 to 123 (0x7B)
|
||||
* (chapter 6 section 17 page 38)
|
||||
* Quantity of Registers to write in R/W registers (2 bytes) 1 to 121 (0x79)
|
||||
*/
|
||||
#define MODBUS_MAX_READ_REGISTERS 125
|
||||
#define MODBUS_MAX_WRITE_REGISTERS 123
|
||||
#define MODBUS_MAX_WR_WRITE_REGISTERS 121
|
||||
#define MODBUS_MAX_WR_READ_REGISTERS 125
|
||||
|
||||
/* The size of the MODBUS PDU is limited by the size constraint inherited from
|
||||
* the first MODBUS implementation on Serial Line network (max. RS485 ADU = 256
|
||||
* bytes). Therefore, MODBUS PDU for serial line communication = 256 - Server
|
||||
* address (1 byte) - CRC (2 bytes) = 253 bytes.
|
||||
*/
|
||||
#define MODBUS_MAX_PDU_LENGTH 253
|
||||
|
||||
/* Consequently:
|
||||
* - RTU MODBUS ADU = 253 bytes + Server address (1 byte) + CRC (2 bytes) = 256
|
||||
* bytes.
|
||||
* - TCP MODBUS ADU = 253 bytes + MBAP (7 bytes) = 260 bytes.
|
||||
* so the maximum of both backend in 260 bytes. This size can used to allocate
|
||||
* an array of bytes to store responses and it will be compatible with the two
|
||||
* backends.
|
||||
*/
|
||||
#define MODBUS_MAX_ADU_LENGTH 260
|
||||
|
||||
/* Random number to avoid errno conflicts */
|
||||
#define MODBUS_ENOBASE 112345678
|
||||
|
||||
/* Protocol exceptions */
|
||||
enum {
|
||||
MODBUS_EXCEPTION_ILLEGAL_FUNCTION = 0x01,
|
||||
MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS,
|
||||
MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,
|
||||
MODBUS_EXCEPTION_SLAVE_OR_SERVER_FAILURE,
|
||||
MODBUS_EXCEPTION_ACKNOWLEDGE,
|
||||
MODBUS_EXCEPTION_SLAVE_OR_SERVER_BUSY,
|
||||
MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE,
|
||||
MODBUS_EXCEPTION_MEMORY_PARITY,
|
||||
MODBUS_EXCEPTION_NOT_DEFINED,
|
||||
MODBUS_EXCEPTION_GATEWAY_PATH,
|
||||
MODBUS_EXCEPTION_GATEWAY_TARGET,
|
||||
MODBUS_EXCEPTION_MAX
|
||||
};
|
||||
|
||||
#define EMBXILFUN (MODBUS_ENOBASE + MODBUS_EXCEPTION_ILLEGAL_FUNCTION)
|
||||
#define EMBXILADD (MODBUS_ENOBASE + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS)
|
||||
#define EMBXILVAL (MODBUS_ENOBASE + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE)
|
||||
#define EMBXSFAIL (MODBUS_ENOBASE + MODBUS_EXCEPTION_SLAVE_OR_SERVER_FAILURE)
|
||||
#define EMBXACK (MODBUS_ENOBASE + MODBUS_EXCEPTION_ACKNOWLEDGE)
|
||||
#define EMBXSBUSY (MODBUS_ENOBASE + MODBUS_EXCEPTION_SLAVE_OR_SERVER_BUSY)
|
||||
#define EMBXNACK (MODBUS_ENOBASE + MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE)
|
||||
#define EMBXMEMPAR (MODBUS_ENOBASE + MODBUS_EXCEPTION_MEMORY_PARITY)
|
||||
#define EMBXGPATH (MODBUS_ENOBASE + MODBUS_EXCEPTION_GATEWAY_PATH)
|
||||
#define EMBXGTAR (MODBUS_ENOBASE + MODBUS_EXCEPTION_GATEWAY_TARGET)
|
||||
|
||||
/* Native libmodbus error codes */
|
||||
#define EMBBADCRC (EMBXGTAR + 1)
|
||||
#define EMBBADDATA (EMBXGTAR + 2)
|
||||
#define EMBBADEXC (EMBXGTAR + 3)
|
||||
#define EMBUNKEXC (EMBXGTAR + 4)
|
||||
#define EMBMDATA (EMBXGTAR + 5)
|
||||
#define EMBBADSLAVE (EMBXGTAR + 6)
|
||||
|
||||
extern const unsigned int libmodbus_version_major;
|
||||
extern const unsigned int libmodbus_version_minor;
|
||||
extern const unsigned int libmodbus_version_micro;
|
||||
|
||||
typedef struct _modbus modbus_t;
|
||||
|
||||
typedef struct _modbus_mapping_t {
|
||||
int nb_bits;
|
||||
int start_bits;
|
||||
int nb_input_bits;
|
||||
int start_input_bits;
|
||||
int nb_input_registers;
|
||||
int start_input_registers;
|
||||
int nb_registers;
|
||||
int start_registers;
|
||||
uint8_t *tab_bits;
|
||||
uint8_t *tab_input_bits;
|
||||
uint16_t *tab_input_registers;
|
||||
uint16_t *tab_registers;
|
||||
} modbus_mapping_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MODBUS_ERROR_RECOVERY_NONE = 0,
|
||||
MODBUS_ERROR_RECOVERY_LINK = (1<<1),
|
||||
MODBUS_ERROR_RECOVERY_PROTOCOL = (1<<2)
|
||||
} modbus_error_recovery_mode;
|
||||
|
||||
MODBUS_API int modbus_set_slave(modbus_t* ctx, int slave);
|
||||
MODBUS_API int modbus_get_slave(modbus_t* ctx);
|
||||
MODBUS_API int modbus_set_error_recovery(modbus_t *ctx, modbus_error_recovery_mode error_recovery);
|
||||
MODBUS_API int modbus_set_socket(modbus_t *ctx, int s);
|
||||
MODBUS_API int modbus_get_socket(modbus_t *ctx);
|
||||
|
||||
MODBUS_API int modbus_get_response_timeout(modbus_t *ctx, uint32_t *to_sec, uint32_t *to_usec);
|
||||
MODBUS_API int modbus_set_response_timeout(modbus_t *ctx, uint32_t to_sec, uint32_t to_usec);
|
||||
|
||||
MODBUS_API int modbus_get_byte_timeout(modbus_t *ctx, uint32_t *to_sec, uint32_t *to_usec);
|
||||
MODBUS_API int modbus_set_byte_timeout(modbus_t *ctx, uint32_t to_sec, uint32_t to_usec);
|
||||
|
||||
MODBUS_API int modbus_get_indication_timeout(modbus_t *ctx, uint32_t *to_sec, uint32_t *to_usec);
|
||||
MODBUS_API int modbus_set_indication_timeout(modbus_t *ctx, uint32_t to_sec, uint32_t to_usec);
|
||||
|
||||
MODBUS_API int modbus_get_header_length(modbus_t *ctx);
|
||||
|
||||
MODBUS_API int modbus_connect(modbus_t *ctx);
|
||||
MODBUS_API void modbus_close(modbus_t *ctx);
|
||||
|
||||
MODBUS_API void modbus_free(modbus_t *ctx);
|
||||
|
||||
MODBUS_API int modbus_flush(modbus_t *ctx);
|
||||
MODBUS_API int modbus_set_debug(modbus_t *ctx, int flag);
|
||||
|
||||
MODBUS_API const char *modbus_strerror(int errnum);
|
||||
|
||||
MODBUS_API int modbus_read_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest);
|
||||
MODBUS_API int modbus_read_input_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest);
|
||||
MODBUS_API int modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest);
|
||||
MODBUS_API int modbus_read_input_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest);
|
||||
MODBUS_API int modbus_write_bit(modbus_t *ctx, int coil_addr, int status);
|
||||
MODBUS_API int modbus_write_register(modbus_t *ctx, int reg_addr, const uint16_t value);
|
||||
MODBUS_API int modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t *data);
|
||||
MODBUS_API int modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *data);
|
||||
MODBUS_API int modbus_mask_write_register(modbus_t *ctx, int addr, uint16_t and_mask, uint16_t or_mask);
|
||||
MODBUS_API int modbus_write_and_read_registers(modbus_t *ctx, int write_addr, int write_nb,
|
||||
const uint16_t *src, int read_addr, int read_nb,
|
||||
uint16_t *dest);
|
||||
MODBUS_API int modbus_report_slave_id(modbus_t *ctx, int max_dest, uint8_t *dest);
|
||||
|
||||
MODBUS_API modbus_mapping_t* modbus_mapping_new_start_address(
|
||||
unsigned int start_bits, unsigned int nb_bits,
|
||||
unsigned int start_input_bits, unsigned int nb_input_bits,
|
||||
unsigned int start_registers, unsigned int nb_registers,
|
||||
unsigned int start_input_registers, unsigned int nb_input_registers);
|
||||
|
||||
MODBUS_API modbus_mapping_t* modbus_mapping_new(int nb_bits, int nb_input_bits,
|
||||
int nb_registers, int nb_input_registers);
|
||||
MODBUS_API void modbus_mapping_free(modbus_mapping_t *mb_mapping);
|
||||
|
||||
MODBUS_API int modbus_send_raw_request(modbus_t *ctx, const uint8_t *raw_req, int raw_req_length);
|
||||
|
||||
MODBUS_API int modbus_receive(modbus_t *ctx, uint8_t *req);
|
||||
|
||||
MODBUS_API int modbus_receive_confirmation(modbus_t *ctx, uint8_t *rsp);
|
||||
|
||||
MODBUS_API int modbus_reply(modbus_t *ctx, const uint8_t *req,
|
||||
int req_length, modbus_mapping_t *mb_mapping);
|
||||
MODBUS_API int modbus_reply_exception(modbus_t *ctx, const uint8_t *req,
|
||||
unsigned int exception_code);
|
||||
|
||||
/**
|
||||
* UTILS FUNCTIONS
|
||||
**/
|
||||
|
||||
#define MODBUS_GET_HIGH_BYTE(data) (((data) >> 8) & 0xFF)
|
||||
#define MODBUS_GET_LOW_BYTE(data) ((data) & 0xFF)
|
||||
#define MODBUS_GET_INT64_FROM_INT16(tab_int16, index) \
|
||||
(((int64_t)tab_int16[(index) ] << 48) + \
|
||||
((int64_t)tab_int16[(index) + 1] << 32) + \
|
||||
((int64_t)tab_int16[(index) + 2] << 16) + \
|
||||
(int64_t)tab_int16[(index) + 3])
|
||||
#define MODBUS_GET_INT32_FROM_INT16(tab_int16, index) ((tab_int16[(index)] << 16) + tab_int16[(index) + 1])
|
||||
#define MODBUS_GET_INT16_FROM_INT8(tab_int8, index) ((tab_int8[(index)] << 8) + tab_int8[(index) + 1])
|
||||
#define MODBUS_SET_INT16_TO_INT8(tab_int8, index, value) \
|
||||
do { \
|
||||
tab_int8[(index)] = (value) >> 8; \
|
||||
tab_int8[(index) + 1] = (value) & 0xFF; \
|
||||
} while (0)
|
||||
#define MODBUS_SET_INT32_TO_INT16(tab_int16, index, value) \
|
||||
do { \
|
||||
tab_int16[(index) ] = (value) >> 16; \
|
||||
tab_int16[(index) + 1] = (value); \
|
||||
} while (0)
|
||||
#define MODBUS_SET_INT64_TO_INT16(tab_int16, index, value) \
|
||||
do { \
|
||||
tab_int16[(index) ] = (value) >> 48; \
|
||||
tab_int16[(index) + 1] = (value) >> 32; \
|
||||
tab_int16[(index) + 2] = (value) >> 16; \
|
||||
tab_int16[(index) + 3] = (value); \
|
||||
} while (0)
|
||||
|
||||
MODBUS_API void modbus_set_bits_from_byte(uint8_t *dest, int idx, const uint8_t value);
|
||||
MODBUS_API void modbus_set_bits_from_bytes(uint8_t *dest, int idx, unsigned int nb_bits,
|
||||
const uint8_t *tab_byte);
|
||||
MODBUS_API uint8_t modbus_get_byte_from_bits(const uint8_t *src, int idx, unsigned int nb_bits);
|
||||
MODBUS_API float modbus_get_float(const uint16_t *src);
|
||||
MODBUS_API float modbus_get_float_abcd(const uint16_t *src);
|
||||
MODBUS_API float modbus_get_float_dcba(const uint16_t *src);
|
||||
MODBUS_API float modbus_get_float_badc(const uint16_t *src);
|
||||
MODBUS_API float modbus_get_float_cdab(const uint16_t *src);
|
||||
|
||||
MODBUS_API void modbus_set_float(float f, uint16_t *dest);
|
||||
MODBUS_API void modbus_set_float_abcd(float f, uint16_t *dest);
|
||||
MODBUS_API void modbus_set_float_dcba(float f, uint16_t *dest);
|
||||
MODBUS_API void modbus_set_float_badc(float f, uint16_t *dest);
|
||||
MODBUS_API void modbus_set_float_cdab(float f, uint16_t *dest);
|
||||
|
||||
#include "modbus-tcp.h"
|
||||
#include "modbus-rtu.h"
|
||||
|
||||
MODBUS_END_DECLS
|
||||
|
||||
#endif /* MODBUS_H */
|
@ -0,0 +1,14 @@
|
||||
#ifndef _MODBUS_RTU_SLAVE_H
|
||||
#define _MODBUS_RTU_SLAVE_H
|
||||
|
||||
//J24.1 J24.2 ===> A-B
|
||||
#define MODBUS_RTU_SERIAL "/dev/ttyO3"
|
||||
#define MODBUS_RTU_BAUD 38400
|
||||
#define SERVER_ID 1
|
||||
|
||||
|
||||
//extern YSP_MODBUS_REGS ysp_modbus_data;
|
||||
|
||||
int modbus_rtu_slave_init(void);
|
||||
void modbus_rtu_data_fresh(void *data,int is_new);
|
||||
#endif
|
@ -0,0 +1,15 @@
|
||||
#ifndef _MSQ_H
|
||||
#define _MSQ_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <mqueue.h>
|
||||
#include <time.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
mqd_t create_mq(const char *mq_name,long int mq_maxmsg,long int mq_msgsize);
|
||||
mqd_t open_mq(const char *mq_name);
|
||||
ssize_t recv_mq_wait(mqd_t mq,void *msg,int size,int timeouts);
|
||||
|
||||
#endif
|
@ -0,0 +1,137 @@
|
||||
#ifndef _SHM_H
|
||||
#define _SHM_H
|
||||
|
||||
|
||||
#define TYPE_MX 1
|
||||
#define TYPE_ST 2
|
||||
#define TYPE_SE 3
|
||||
#define TYPE_SG 4
|
||||
#define TYPE_SGCB 5
|
||||
#define TYPE_CO 6
|
||||
#define TYPE_SP 7
|
||||
#define TYPE_SV 8
|
||||
|
||||
#define CMD_WR_MX 1
|
||||
#define CMD_WR_ST 2
|
||||
#define CMD_WR_SE 3
|
||||
#define CMD_WR_SG 4
|
||||
#define CMD_WR_SGCB 5
|
||||
#define CMD_WR_CO 6
|
||||
#define CMD_WR_SP 7
|
||||
#define CMD_WR_SV 8
|
||||
|
||||
typedef union
|
||||
{
|
||||
float f;
|
||||
int i;
|
||||
char stVal;
|
||||
void *ptr;
|
||||
}GEN_VAL;
|
||||
|
||||
typedef struct{
|
||||
unsigned int secs;
|
||||
unsigned int ms;
|
||||
}TimeStamp;
|
||||
|
||||
|
||||
typedef struct utc_time_tag
|
||||
{
|
||||
unsigned int secs; // Number of seconds since January 1, 1970
|
||||
unsigned int fraction; // Fraction of a second
|
||||
unsigned int qflags; // Quality flags, 8 least-significant bits only
|
||||
} UTC_TIME;
|
||||
|
||||
|
||||
typedef struct{
|
||||
GEN_VAL v;
|
||||
int q;
|
||||
TimeStamp t;
|
||||
//#ifdef SUB_ENABLE
|
||||
int subEna;
|
||||
GEN_VAL subVal;
|
||||
int subQ;
|
||||
//#endif
|
||||
}SCL_MV; //
|
||||
|
||||
|
||||
typedef struct{
|
||||
GEN_VAL v;
|
||||
int q;
|
||||
TimeStamp t;
|
||||
}USR_MV; //
|
||||
|
||||
|
||||
typedef struct{
|
||||
GEN_VAL ctlVal;
|
||||
char ctlNum;
|
||||
TimeStamp t;
|
||||
char Test;
|
||||
char Check;
|
||||
int valType;
|
||||
}SCL_CO;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char NumOfSG; //1-n
|
||||
unsigned char ActSG; //1-n
|
||||
unsigned char EditSG; //0-n,0
|
||||
unsigned char CnfEdit;
|
||||
UTC_TIME LActTm;// TimeStamp
|
||||
}SGCB_CTRL;
|
||||
|
||||
|
||||
typedef union
|
||||
{
|
||||
USR_MV ana_mv;
|
||||
SCL_MV scl_mv;
|
||||
SCL_CO scl_co;
|
||||
SGCB_CTRL sgcb_ctrl;
|
||||
}SCL_VAL;
|
||||
|
||||
|
||||
typedef struct{
|
||||
int type;
|
||||
int grp;
|
||||
int num;
|
||||
int ofs;
|
||||
GEN_VAL v;
|
||||
}SCL_DATA_SPEC;
|
||||
|
||||
typedef struct{
|
||||
int cmd;
|
||||
union
|
||||
{
|
||||
SCL_DATA_SPEC data_spec;
|
||||
}u;
|
||||
}SCL_MSG_TYPE;
|
||||
|
||||
|
||||
int start_scl_mem();
|
||||
int stop_scl_mem();
|
||||
void lock_scl_mem();
|
||||
void unlock_scl_mem();
|
||||
|
||||
|
||||
char *put_scl_data(int grp,int index,void *ptr,int num_bytes);
|
||||
char *get_scl_data(int grp,int index,void *ptr,int num_bytes);
|
||||
|
||||
SCL_VAL* put_mv_data(int grp,int index,USR_MV *usr_mv,int num_do);
|
||||
SCL_VAL* get_mv_data(int grp,int index,USR_MV *usr_data,int num_do);
|
||||
SCL_VAL *put_do_data(int grp,int index,SCL_VAL *scl_do,int num_of_do);
|
||||
SCL_VAL *get_do_data(int grp,int index,SCL_VAL *scl_do,int num_of_do);
|
||||
|
||||
SGCB_CTRL* get_sgcb_data(int index,SGCB_CTRL *sgcb);
|
||||
SGCB_CTRL* put_sgcb_data(int index,SGCB_CTRL *sgcb);
|
||||
char *get_sg_data(int grp,int index,char *ptr,int num_bytes);
|
||||
char *put_sg_data(int grp,int index,char *ptr,int num_bytes);
|
||||
char *get_se_data(int grp,int index,char *ptr,int num_bytes);
|
||||
char *put_se_data(int grp,int index,char *ptr,int num_bytes);
|
||||
|
||||
int get_usr_data(int offs,void *ptr,int num_bytes);
|
||||
int put_usr_data(int offs,void *ptr,int num_bytes);
|
||||
|
||||
int write_scl_msg(int cmd,SCL_DATA_SPEC *data_spec);
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -0,0 +1,17 @@
|
||||
#ifndef _SERIAL_H
|
||||
#define _SERIAL_H
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <termios.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int SerialOpen(const char *dev_name,int baud,int databit,int stopbit,int chk_mode);
|
||||
int SerialRead(int m_comFd,unsigned char *buf,int sz,int timeout);
|
||||
int SerialWrite(int m_comFd,const unsigned char *buf,int sz);
|
||||
int SerialReadEx(int m_comFd,unsigned char *buf,int sz,int timeout);
|
||||
|
||||
#endif
|
@ -0,0 +1,55 @@
|
||||
#ifndef _MODBUS_H
|
||||
#define _MODBUS_H
|
||||
|
||||
#include "crc.h"
|
||||
#include "common.h"
|
||||
#include "string.h"
|
||||
#include "sjzd_serial.h"
|
||||
|
||||
#define FRM_ERR_NONE 0
|
||||
#define FRM_ERR_START -1
|
||||
#define FRM_ERR_RX_TIMEOUT -2
|
||||
#define FRM_ERR_SLAVE_ADDR -3
|
||||
#define FRM_ERR_FC -4
|
||||
#define FRM_ERR_BYTE_COUNT -5
|
||||
#define FRM_ERR_CRC -6
|
||||
|
||||
|
||||
#define MAX_PAYLOAD_SIZE 1024
|
||||
#define FRM_MAX_LEN (MAX_PAYLOAD_SIZE+8)
|
||||
#define FRM_HEADER_LEN 4
|
||||
|
||||
#define SJZD_RD_REGS 1
|
||||
#define SJZD_WR_REGS 2
|
||||
#define SJZD_RD_FILE_START 3
|
||||
#define SJZD_RD_FILE_CONTENT 4
|
||||
#define SJZD_RD_FILE_END 5
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float AccPri[19];
|
||||
float AccSec[7];
|
||||
float EnvNoiPri;
|
||||
float EnvNoiSec;
|
||||
float NeuCur;
|
||||
int MoDevConf;
|
||||
int MoDevDetF;
|
||||
int MoDevSigF;
|
||||
int ModevPowF;
|
||||
int EnvNoiPriAlm;
|
||||
int EnvNoiSecAlm;
|
||||
int NeuCurAlm;
|
||||
int AccPriAlm[19];
|
||||
int AccSecAlm[7];
|
||||
}SVBR_PRI_TYPE;
|
||||
|
||||
|
||||
int32_t sjzd_master_init(char *port,char *baud,char *parity);
|
||||
int32_t sjzd_make_frm(uint8_t *enc_buf,uint8_t slave_addr,uint8_t cmd,uint8_t *data,uint16_t data_len);
|
||||
int32_t sjzd_chk_frm(uint8_t *buf,uint16_t len,uint8_t slave_addr,uint8_t cmd);
|
||||
|
||||
int32_t sjzd_reg_rd(uint8_t slave_node,uint32_t reg_addr,uint8_t *reg_tbl,uint32_t nbr_reg);
|
||||
int32_t sjzd_reg_wr(uint8_t slave_node,uint32_t reg_addr,uint8_t *reg_tbl,uint32_t nbr_reg,uint8_t *rlt);
|
||||
int32_t sjzd_file_rd(uint8_t slave_node,char *in_file,char *out_file);
|
||||
|
||||
#endif
|
@ -0,0 +1,15 @@
|
||||
#ifndef _MODBUS_SERIAL_H
|
||||
#define _MODBUS_SERIAL_H
|
||||
|
||||
#include "serial.h"
|
||||
#include "common.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define MODBUS_TIMEOUT 10
|
||||
|
||||
int32_t sjzd_serial_init(char *port,int baud,char databit,char parity);
|
||||
int32_t sjzd_serial_read(uint8_t *pucBuffer,uint16_t usNBytes,uint16_t *usNBytesRead);
|
||||
int32_t sjzd_serial_write(uint8_t *pucBuffer,uint16_t usNBytes);
|
||||
|
||||
#endif
|
||||
|
@ -0,0 +1,10 @@
|
||||
#ifndef _THREAD_H
|
||||
#define _THREAD_H
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
|
||||
extern pthread_t task_create(void *(*start_routine)(void *),void *arg,int prio,int stacksize);
|
||||
|
||||
#endif
|
||||
|
@ -0,0 +1,273 @@
|
||||
/*
|
||||
* This file is part of the EasyLogger Library.
|
||||
*
|
||||
* Copyright (c) 2015-2019, Armink, <armink.ztl@gmail.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Function: It is an head file for this library. You can see all be called functions.
|
||||
* Created on: 2015-04-28
|
||||
*/
|
||||
|
||||
#ifndef __ELOG_H__
|
||||
#define __ELOG_H__
|
||||
|
||||
#include <elog_cfg.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* output log's level */
|
||||
#define ELOG_LVL_ASSERT 0
|
||||
#define ELOG_LVL_ERROR 1
|
||||
#define ELOG_LVL_WARN 2
|
||||
#define ELOG_LVL_INFO 3
|
||||
#define ELOG_LVL_DEBUG 4
|
||||
#define ELOG_LVL_VERBOSE 5
|
||||
|
||||
/* the output silent level and all level for filter setting */
|
||||
#define ELOG_FILTER_LVL_SILENT ELOG_LVL_ASSERT
|
||||
#define ELOG_FILTER_LVL_ALL ELOG_LVL_VERBOSE
|
||||
|
||||
/* output log's level total number */
|
||||
#define ELOG_LVL_TOTAL_NUM 6
|
||||
|
||||
/* EasyLogger software version number */
|
||||
#define ELOG_SW_VERSION "2.2.99"
|
||||
|
||||
/* EasyLogger assert for developer. */
|
||||
#ifdef ELOG_ASSERT_ENABLE
|
||||
#define ELOG_ASSERT(EXPR) \
|
||||
if (!(EXPR)) \
|
||||
{ \
|
||||
if (elog_assert_hook == NULL) { \
|
||||
elog_a("elog", "(%s) has assert failed at %s:%ld.", #EXPR, __FUNCTION__, __LINE__); \
|
||||
while (1); \
|
||||
} else { \
|
||||
elog_assert_hook(#EXPR, __FUNCTION__, __LINE__); \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define ELOG_ASSERT(EXPR) ((void)0);
|
||||
#endif
|
||||
|
||||
#ifndef ELOG_OUTPUT_ENABLE
|
||||
#define elog_assert(tag, ...)
|
||||
#define elog_error(tag, ...)
|
||||
#define elog_warn(tag, ...)
|
||||
#define elog_info(tag, ...)
|
||||
#define elog_debug(tag, ...)
|
||||
#define elog_verbose(tag, ...)
|
||||
#else /* ELOG_OUTPUT_ENABLE */
|
||||
#if ELOG_OUTPUT_LVL >= ELOG_LVL_ASSERT
|
||||
#define elog_assert(tag, ...) \
|
||||
elog_output(ELOG_LVL_ASSERT, tag, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
#else
|
||||
#define elog_assert(tag, ...)
|
||||
#endif /* ELOG_OUTPUT_LVL >= ELOG_LVL_ASSERT */
|
||||
|
||||
#if ELOG_OUTPUT_LVL >= ELOG_LVL_ERROR
|
||||
#define elog_error(tag, ...) \
|
||||
elog_output(ELOG_LVL_ERROR, tag, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
#else
|
||||
#define elog_error(tag, ...)
|
||||
#endif /* ELOG_OUTPUT_LVL >= ELOG_LVL_ERROR */
|
||||
|
||||
#if ELOG_OUTPUT_LVL >= ELOG_LVL_WARN
|
||||
#define elog_warn(tag, ...) \
|
||||
elog_output(ELOG_LVL_WARN, tag, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
#else
|
||||
#define elog_warn(tag, ...)
|
||||
#endif /* ELOG_OUTPUT_LVL >= ELOG_LVL_WARN */
|
||||
|
||||
#if ELOG_OUTPUT_LVL >= ELOG_LVL_INFO
|
||||
#define elog_info(tag, ...) \
|
||||
elog_output(ELOG_LVL_INFO, tag, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
#else
|
||||
#define elog_info(tag, ...)
|
||||
#endif /* ELOG_OUTPUT_LVL >= ELOG_LVL_INFO */
|
||||
|
||||
#if ELOG_OUTPUT_LVL >= ELOG_LVL_DEBUG
|
||||
#define elog_debug(tag, ...) \
|
||||
elog_output(ELOG_LVL_DEBUG, tag, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
#else
|
||||
#define elog_debug(tag, ...)
|
||||
#endif /* ELOG_OUTPUT_LVL >= ELOG_LVL_DEBUG */
|
||||
|
||||
#if ELOG_OUTPUT_LVL == ELOG_LVL_VERBOSE
|
||||
#define elog_verbose(tag, ...) \
|
||||
elog_output(ELOG_LVL_VERBOSE, tag, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
#else
|
||||
#define elog_verbose(tag, ...)
|
||||
#endif /* ELOG_OUTPUT_LVL == ELOG_LVL_VERBOSE */
|
||||
#endif /* ELOG_OUTPUT_ENABLE */
|
||||
|
||||
/* all formats index */
|
||||
typedef enum {
|
||||
ELOG_FMT_LVL = 1 << 0, /**< level 级别*/
|
||||
ELOG_FMT_TAG = 1 << 1, /**< tag 标签*/
|
||||
ELOG_FMT_TIME = 1 << 2, /**< current time 当前时间*/
|
||||
ELOG_FMT_P_INFO = 1 << 3, /**< process info 进程信息*/
|
||||
ELOG_FMT_T_INFO = 1 << 4, /**< thread info 线程信息*/
|
||||
ELOG_FMT_DIR = 1 << 5, /**< file directory and name 文件路径和文件名*/
|
||||
ELOG_FMT_FUNC = 1 << 6, /**< function name 函数名称*/
|
||||
ELOG_FMT_LINE = 1 << 7, /**< line number 行号*/
|
||||
} ElogFmtIndex;
|
||||
|
||||
/* macro definition for all formats */
|
||||
#define ELOG_FMT_ALL (ELOG_FMT_LVL|ELOG_FMT_TAG|ELOG_FMT_TIME|ELOG_FMT_P_INFO|ELOG_FMT_T_INFO| \
|
||||
ELOG_FMT_DIR|ELOG_FMT_FUNC|ELOG_FMT_LINE)
|
||||
|
||||
/* output log's tag filter */
|
||||
typedef struct {
|
||||
uint8_t level;
|
||||
char tag[ELOG_FILTER_TAG_MAX_LEN + 1];
|
||||
bool tag_use_flag; /**< false : tag is no used true: tag is used */
|
||||
} ElogTagLvlFilter, *ElogTagLvlFilter_t;
|
||||
|
||||
/* output log's filter */
|
||||
typedef struct {
|
||||
uint8_t level;
|
||||
char tag[ELOG_FILTER_TAG_MAX_LEN + 1];
|
||||
char keyword[ELOG_FILTER_KW_MAX_LEN + 1];
|
||||
ElogTagLvlFilter tag_lvl[ELOG_FILTER_TAG_LVL_MAX_NUM];
|
||||
} ElogFilter, *ElogFilter_t;
|
||||
|
||||
/* easy logger */
|
||||
typedef struct {
|
||||
ElogFilter filter;
|
||||
size_t enabled_fmt_set[ELOG_LVL_TOTAL_NUM];
|
||||
bool init_ok;
|
||||
bool output_enabled;
|
||||
bool output_lock_enabled;
|
||||
bool output_is_locked_before_enable;
|
||||
bool output_is_locked_before_disable;
|
||||
|
||||
#ifdef ELOG_COLOR_ENABLE
|
||||
bool text_color_enabled;
|
||||
#endif
|
||||
|
||||
}EasyLogger, *EasyLogger_t;
|
||||
|
||||
/* EasyLogger error code */
|
||||
typedef enum {
|
||||
ELOG_NO_ERR,
|
||||
} ElogErrCode;
|
||||
|
||||
/* elog.c */
|
||||
ElogErrCode elog_init(void);
|
||||
void elog_start(void);
|
||||
void elog_set_output_enabled(bool enabled);
|
||||
bool elog_get_output_enabled(void);
|
||||
void elog_set_text_color_enabled(bool enabled);
|
||||
bool elog_get_text_color_enabled(void);
|
||||
void elog_set_fmt(uint8_t level, size_t set);//每个输出级别都可以单独设置输出内容格式
|
||||
void elog_set_filter(uint8_t level, const char *tag, const char *keyword);
|
||||
void elog_set_filter_lvl(uint8_t level);//设置输出过滤级别
|
||||
void elog_set_filter_tag(const char *tag);//设置输出过滤标签
|
||||
void elog_set_filter_kw(const char *keyword);
|
||||
void elog_set_filter_tag_lvl(const char *tag, uint8_t level);
|
||||
uint8_t elog_get_filter_tag_lvl(const char *tag);
|
||||
void elog_raw(const char *format, ...);
|
||||
void elog_output(uint8_t level, const char *tag, const char *file, const char *func,
|
||||
const long line, const char *format, ...);
|
||||
void elog_output_lock_enabled(bool enabled);
|
||||
extern void (*elog_assert_hook)(const char* expr, const char* func, size_t line);
|
||||
void elog_assert_set_hook(void (*hook)(const char* expr, const char* func, size_t line));
|
||||
int8_t elog_find_lvl(const char *log);
|
||||
const char *elog_find_tag(const char *log, uint8_t lvl, size_t *tag_len);
|
||||
void elog_hexdump(const char *name, uint8_t width, uint8_t *buf, uint16_t size);
|
||||
|
||||
#define elog_a(tag, ...) elog_assert(tag, __VA_ARGS__)
|
||||
#define elog_e(tag, ...) elog_error(tag, __VA_ARGS__)
|
||||
#define elog_w(tag, ...) elog_warn(tag, __VA_ARGS__)
|
||||
#define elog_i(tag, ...) elog_info(tag, __VA_ARGS__)
|
||||
#define elog_d(tag, ...) elog_debug(tag, __VA_ARGS__)
|
||||
#define elog_v(tag, ...) elog_verbose(tag, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* log API short definition
|
||||
* NOTE: The `LOG_TAG` and `LOG_LVL` must defined before including the <elog.h> when you want to use log_x API.
|
||||
*/
|
||||
#if !defined(LOG_TAG)
|
||||
#define LOG_TAG "NO_TAG"
|
||||
#endif
|
||||
#if !defined(LOG_LVL)
|
||||
#define LOG_LVL ELOG_LVL_VERBOSE
|
||||
#endif
|
||||
#if LOG_LVL >= ELOG_LVL_ASSERT
|
||||
#define log_a(...) elog_a(LOG_TAG, __VA_ARGS__)
|
||||
#else
|
||||
#define log_a(...) ((void)0);
|
||||
#endif
|
||||
#if LOG_LVL >= ELOG_LVL_ERROR
|
||||
#define log_e(...) elog_e(LOG_TAG, __VA_ARGS__)
|
||||
#else
|
||||
#define log_e(...) ((void)0);
|
||||
#endif
|
||||
#if LOG_LVL >= ELOG_LVL_WARN
|
||||
#define log_w(...) elog_w(LOG_TAG, __VA_ARGS__)
|
||||
#else
|
||||
#define log_w(...) ((void)0);
|
||||
#endif
|
||||
#if LOG_LVL >= ELOG_LVL_INFO
|
||||
#define log_i(...) elog_i(LOG_TAG, __VA_ARGS__)
|
||||
#else
|
||||
#define log_i(...) ((void)0);
|
||||
#endif
|
||||
#if LOG_LVL >= ELOG_LVL_DEBUG
|
||||
#define log_d(...) elog_d(LOG_TAG, __VA_ARGS__)
|
||||
#else
|
||||
#define log_d(...) ((void)0);
|
||||
#endif
|
||||
#if LOG_LVL >= ELOG_LVL_VERBOSE
|
||||
#define log_v(...) elog_v(LOG_TAG, __VA_ARGS__)
|
||||
#else
|
||||
#define log_v(...) ((void)0);
|
||||
#endif
|
||||
|
||||
/* assert API short definition */
|
||||
#if !defined(assert)
|
||||
#define assert ELOG_ASSERT
|
||||
#endif
|
||||
|
||||
/* elog_buf.c */
|
||||
void elog_buf_enabled(bool enabled);
|
||||
void elog_flush(void);
|
||||
|
||||
/* elog_async.c */
|
||||
void elog_async_enabled(bool enabled);
|
||||
size_t elog_async_get_log(char *log, size_t size);
|
||||
size_t elog_async_get_line_log(char *log, size_t size);
|
||||
|
||||
/* elog_utils.c */
|
||||
size_t elog_strcpy(size_t cur_len, char *dst, const char *src);
|
||||
size_t elog_cpyln(char *line, const char *log, size_t len);
|
||||
void *elog_memcpy(void *dst, const void *src, size_t count);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ELOG_H__ */
|
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* This file is part of the EasyLogger Library.
|
||||
*
|
||||
* Copyright (c) 2015, Armink, <armink.ztl@gmail.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Function: It is the configure head file for this library.
|
||||
* Created on: 2015-07-30
|
||||
*/
|
||||
|
||||
#ifndef _ELOG_CFG_H_
|
||||
#define _ELOG_CFG_H_
|
||||
|
||||
/* enable log output. default open this macro 日志输出使能*/
|
||||
#define ELOG_OUTPUT_ENABLE
|
||||
/* enable log write file. default open this macro 日志存入文件使能*/
|
||||
#define ELOG_FILE_ENABLE
|
||||
/* enable flush file cache. default open this macro 使能日志文件缓冲*/
|
||||
#define ELOG_FILE_FLUSH_CAHCE_ENABLE
|
||||
/* setting static output log level 设置日志静态输出级别,级别高于它的都会输出(值大于它),低于它的不输出*/
|
||||
#define ELOG_OUTPUT_LVL ELOG_LVL_VERBOSE
|
||||
/* enable assert check 使能assert*/
|
||||
#define ELOG_ASSERT_ENABLE
|
||||
/* buffer size for every line's log 日志行缓冲大小*/
|
||||
#define ELOG_LINE_BUF_SIZE 512
|
||||
/* output line number max length */
|
||||
#define ELOG_LINE_NUM_MAX_LEN 5
|
||||
/* output filter's tag max length 标签的最大长度,就是日志行首部的字符串*/
|
||||
#define ELOG_FILTER_TAG_MAX_LEN 16
|
||||
/* output filter's keyword max length */
|
||||
#define ELOG_FILTER_KW_MAX_LEN 16
|
||||
/* output filter's tag level max num */
|
||||
#define ELOG_FILTER_TAG_LVL_MAX_NUM 5
|
||||
/* output newline sign */
|
||||
#define ELOG_NEWLINE_SIGN "\n"
|
||||
/* enable log color */
|
||||
#define ELOG_COLOR_ENABLE
|
||||
/* enable asynchronous output mode 使能异步输出模式*/
|
||||
#define ELOG_ASYNC_OUTPUT_ENABLE
|
||||
/* the highest output level for async mode, other level will sync output 异步输出的最高级别*/
|
||||
#define ELOG_ASYNC_OUTPUT_LVL ELOG_LVL_DEBUG
|
||||
/* buffer size for asynchronous output mode 异步输出模式的缓冲区大小*/
|
||||
#define ELOG_ASYNC_OUTPUT_BUF_SIZE (ELOG_LINE_BUF_SIZE*100)
|
||||
/* each asynchronous output's log which must end with newline sign */
|
||||
//#define ELOG_ASYNC_LINE_OUTPUT
|
||||
/* asynchronous output mode using POSIX pthread implementation */
|
||||
#define ELOG_ASYNC_OUTPUT_USING_PTHREAD
|
||||
|
||||
#endif /* _ELOG_CFG_H_ */
|
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* This file is part of the EasyLogger Library.
|
||||
*
|
||||
* Copyright (c) 2015-2019, Qintl, <qintl_linux@163.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Function: It is an head file for file log plugin. You can see all be called functions.
|
||||
* Created on: 2019-01-05
|
||||
*/
|
||||
|
||||
#ifndef __ELOG_FILE__H__
|
||||
#define __ELOG_FILE__H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <elog.h>
|
||||
#include <elog_file_cfg.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* EasyLogger file log plugin's software version number */
|
||||
#define ELOG_FILE_SW_VERSION "V1.0.0"
|
||||
#ifdef linux
|
||||
#define likely(x) __builtin_expect(!!(x), 1)
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
#else
|
||||
#define likely(x) (x)
|
||||
#define unlikely(x) (x)
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
char *name; /* file name */
|
||||
size_t max_size; /* file max size */
|
||||
int max_rotate; /* max rotate file count */
|
||||
} ElogFileCfg;
|
||||
|
||||
/* elog_file.c */
|
||||
ElogErrCode elog_file_init(void);
|
||||
void elog_file_write(const char *log, size_t size);
|
||||
void elog_file_config(ElogFileCfg *cfg);
|
||||
void elog_file_deinit(void);
|
||||
|
||||
/* elog_file_port.c */
|
||||
ElogErrCode elog_file_port_init(void);
|
||||
void elog_file_port_lock(void);
|
||||
void elog_file_port_unlock(void);
|
||||
void elog_file_port_deinit(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* This file is part of the EasyLogger Library.
|
||||
*
|
||||
* Copyright (c) 2015-2019, Qintl, <qintl_linux@163.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Function: It is the configure head file for this flash log plugin.
|
||||
* Created on: 2019-01-05
|
||||
*/
|
||||
|
||||
#ifndef _ELOG_FILE_CFG_H_
|
||||
#define _ELOG_FILE_CFG_H_
|
||||
|
||||
/* EasyLogger file log plugin's using file name */
|
||||
#define ELOG_FILE_NAME "elog_file.log"
|
||||
|
||||
/* EasyLogger file log plugin's using file max size */
|
||||
#define ELOG_FILE_MAX_SIZE (1 * 1024 * 1024)
|
||||
|
||||
/* EasyLogger file log plugin's using max rotate file count */
|
||||
#define ELOG_FILE_MAX_ROTATE 4
|
||||
|
||||
#endif /* _ELOG_FILE_CFG_H_ */
|
@ -0,0 +1,873 @@
|
||||
/*
|
||||
* This file is part of the EasyLogger Library.
|
||||
*
|
||||
* Copyright (c) 2015-2018, Armink, <armink.ztl@gmail.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Function: Initialize function and other general function.
|
||||
* Created on: 2015-04-28
|
||||
*/
|
||||
|
||||
#define LOG_TAG "elog"
|
||||
|
||||
#include <elog.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if !defined(ELOG_OUTPUT_LVL)
|
||||
#error "Please configure static output log level (in elog_cfg.h)"
|
||||
#endif
|
||||
|
||||
#if !defined(ELOG_LINE_NUM_MAX_LEN)
|
||||
#error "Please configure output line number max length (in elog_cfg.h)"
|
||||
#endif
|
||||
|
||||
#if !defined(ELOG_LINE_BUF_SIZE)
|
||||
#error "Please configure buffer size for every line's log (in elog_cfg.h)"
|
||||
#endif
|
||||
|
||||
#if !defined(ELOG_FILTER_TAG_MAX_LEN)
|
||||
#error "Please configure output filter's tag max length (in elog_cfg.h)"
|
||||
#endif
|
||||
|
||||
#if !defined(ELOG_FILTER_KW_MAX_LEN)
|
||||
#error "Please configure output filter's keyword max length (in elog_cfg.h)"
|
||||
#endif
|
||||
|
||||
#if !defined(ELOG_NEWLINE_SIGN)
|
||||
#error "Please configure output newline sign (in elog_cfg.h)"
|
||||
#endif
|
||||
|
||||
/* output filter's tag level max num */
|
||||
#ifndef ELOG_FILTER_TAG_LVL_MAX_NUM
|
||||
#define ELOG_FILTER_TAG_LVL_MAX_NUM 4
|
||||
#endif
|
||||
|
||||
#ifdef ELOG_COLOR_ENABLE
|
||||
/**
|
||||
* CSI(Control Sequence Introducer/Initiator) sign
|
||||
* more information on https://en.wikipedia.org/wiki/ANSI_escape_code
|
||||
*/
|
||||
#define CSI_START "\033["
|
||||
#define CSI_END "\033[0m"
|
||||
/* output log front color */
|
||||
#define F_BLACK "30;"
|
||||
#define F_RED "31;"
|
||||
#define F_GREEN "32;"
|
||||
#define F_YELLOW "33;"
|
||||
#define F_BLUE "34;"
|
||||
#define F_MAGENTA "35;"
|
||||
#define F_CYAN "36;"
|
||||
#define F_WHITE "37;"
|
||||
/* output log background color */
|
||||
#define B_NULL
|
||||
#define B_BLACK "40;"
|
||||
#define B_RED "41;"
|
||||
#define B_GREEN "42;"
|
||||
#define B_YELLOW "43;"
|
||||
#define B_BLUE "44;"
|
||||
#define B_MAGENTA "45;"
|
||||
#define B_CYAN "46;"
|
||||
#define B_WHITE "47;"
|
||||
/* output log fonts style */
|
||||
#define S_BOLD "1m"
|
||||
#define S_UNDERLINE "4m"
|
||||
#define S_BLINK "5m"
|
||||
#define S_NORMAL "22m"
|
||||
/* output log default color definition: [front color] + [background color] + [show style] */
|
||||
#ifndef ELOG_COLOR_ASSERT
|
||||
#define ELOG_COLOR_ASSERT (F_MAGENTA B_NULL S_NORMAL)
|
||||
#endif
|
||||
#ifndef ELOG_COLOR_ERROR
|
||||
#define ELOG_COLOR_ERROR (F_RED B_NULL S_NORMAL)
|
||||
#endif
|
||||
#ifndef ELOG_COLOR_WARN
|
||||
#define ELOG_COLOR_WARN (F_YELLOW B_NULL S_NORMAL)
|
||||
#endif
|
||||
#ifndef ELOG_COLOR_INFO
|
||||
#define ELOG_COLOR_INFO (F_CYAN B_NULL S_NORMAL)
|
||||
#endif
|
||||
#ifndef ELOG_COLOR_DEBUG
|
||||
#define ELOG_COLOR_DEBUG (F_GREEN B_NULL S_NORMAL)
|
||||
#endif
|
||||
#ifndef ELOG_COLOR_VERBOSE
|
||||
#define ELOG_COLOR_VERBOSE (F_BLUE B_NULL S_NORMAL)
|
||||
#endif
|
||||
#endif /* ELOG_COLOR_ENABLE */
|
||||
|
||||
/* EasyLogger object */
|
||||
static EasyLogger elog;
|
||||
/* every line log's buffer */
|
||||
static char log_buf[ELOG_LINE_BUF_SIZE] = { 0 };
|
||||
/* level output info */
|
||||
static const char *level_output_info[] = {
|
||||
[ELOG_LVL_ASSERT] = "A/",
|
||||
[ELOG_LVL_ERROR] = "E/",
|
||||
[ELOG_LVL_WARN] = "W/",
|
||||
[ELOG_LVL_INFO] = "I/",
|
||||
[ELOG_LVL_DEBUG] = "D/",
|
||||
[ELOG_LVL_VERBOSE] = "V/",
|
||||
};
|
||||
|
||||
#ifdef ELOG_COLOR_ENABLE
|
||||
/* color output info */
|
||||
static const char *color_output_info[] = {
|
||||
[ELOG_LVL_ASSERT] = ELOG_COLOR_ASSERT,
|
||||
[ELOG_LVL_ERROR] = ELOG_COLOR_ERROR,
|
||||
[ELOG_LVL_WARN] = ELOG_COLOR_WARN,
|
||||
[ELOG_LVL_INFO] = ELOG_COLOR_INFO,
|
||||
[ELOG_LVL_DEBUG] = ELOG_COLOR_DEBUG,
|
||||
[ELOG_LVL_VERBOSE] = ELOG_COLOR_VERBOSE,
|
||||
};
|
||||
#endif /* ELOG_COLOR_ENABLE */
|
||||
|
||||
static bool get_fmt_enabled(uint8_t level, size_t set);
|
||||
static void elog_set_filter_tag_lvl_default();
|
||||
|
||||
/* EasyLogger assert hook */
|
||||
void (*elog_assert_hook)(const char* expr, const char* func, size_t line);
|
||||
|
||||
extern void elog_port_output(const char *log, size_t size);
|
||||
extern void elog_port_output_lock(void);
|
||||
extern void elog_port_output_unlock(void);
|
||||
|
||||
/**
|
||||
* EasyLogger initialize.
|
||||
*
|
||||
* @return result
|
||||
*/
|
||||
ElogErrCode elog_init(void) {
|
||||
extern ElogErrCode elog_port_init(void);
|
||||
extern ElogErrCode elog_async_init(void);
|
||||
|
||||
ElogErrCode result = ELOG_NO_ERR;
|
||||
|
||||
if (elog.init_ok == true) {
|
||||
return result;
|
||||
}
|
||||
|
||||
/* port initialize */
|
||||
result = elog_port_init();
|
||||
if (result != ELOG_NO_ERR) {
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef ELOG_ASYNC_OUTPUT_ENABLE
|
||||
result = elog_async_init();
|
||||
if (result != ELOG_NO_ERR) {
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* enable the output lock */
|
||||
elog_output_lock_enabled(true);
|
||||
/* output locked status initialize */
|
||||
elog.output_is_locked_before_enable = false;
|
||||
elog.output_is_locked_before_disable = false;
|
||||
|
||||
#ifdef ELOG_COLOR_ENABLE
|
||||
/* disable text color by default */
|
||||
elog_set_text_color_enabled(false);
|
||||
#endif
|
||||
|
||||
/* set level is ELOG_LVL_VERBOSE */
|
||||
elog_set_filter_lvl(ELOG_LVL_VERBOSE);
|
||||
|
||||
/* set tag_level to default val */
|
||||
elog_set_filter_tag_lvl_default();
|
||||
|
||||
elog.init_ok = true;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* EasyLogger start after initialize.
|
||||
*/
|
||||
void elog_start(void) {
|
||||
/* enable output */
|
||||
elog_set_output_enabled(true);
|
||||
|
||||
#if defined(ELOG_ASYNC_OUTPUT_ENABLE)
|
||||
elog_async_enabled(true);
|
||||
#elif defined(ELOG_BUF_OUTPUT_ENABLE)
|
||||
elog_buf_enabled(true);
|
||||
#endif
|
||||
|
||||
/* show version */
|
||||
//log_i("EasyLogger V%s is initialize success.", ELOG_SW_VERSION);
|
||||
elog_raw("EasyLogger V%s is initialize success.\n", ELOG_SW_VERSION);
|
||||
}
|
||||
|
||||
/**
|
||||
* set output enable or disable
|
||||
*
|
||||
* @param enabled TRUE: enable FALSE: disable
|
||||
*/
|
||||
void elog_set_output_enabled(bool enabled) {
|
||||
ELOG_ASSERT((enabled == false) || (enabled == true));
|
||||
|
||||
elog.output_enabled = enabled;
|
||||
}
|
||||
|
||||
#ifdef ELOG_COLOR_ENABLE
|
||||
/**
|
||||
* set log text color enable or disable
|
||||
*
|
||||
* @param enabled TRUE: enable FALSE:disable
|
||||
*/
|
||||
void elog_set_text_color_enabled(bool enabled) {
|
||||
elog.text_color_enabled = enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* get log text color enable status
|
||||
*
|
||||
* @return enable or disable
|
||||
*/
|
||||
bool elog_get_text_color_enabled(void) {
|
||||
return elog.text_color_enabled;
|
||||
}
|
||||
#endif /* ELOG_COLOR_ENABLE */
|
||||
|
||||
/**
|
||||
* get output is enable or disable
|
||||
*
|
||||
* @return enable or disable
|
||||
*/
|
||||
bool elog_get_output_enabled(void) {
|
||||
return elog.output_enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* set log output format. only enable or disable
|
||||
*
|
||||
* @param level level
|
||||
* @param set format set
|
||||
*/
|
||||
void elog_set_fmt(uint8_t level, size_t set) {
|
||||
ELOG_ASSERT(level <= ELOG_LVL_VERBOSE);
|
||||
|
||||
elog.enabled_fmt_set[level] = set;
|
||||
}
|
||||
|
||||
/**
|
||||
* set log filter all parameter
|
||||
*
|
||||
* @param level level
|
||||
* @param tag tag
|
||||
* @param keyword keyword
|
||||
*/
|
||||
void elog_set_filter(uint8_t level, const char *tag, const char *keyword) {
|
||||
ELOG_ASSERT(level <= ELOG_LVL_VERBOSE);
|
||||
|
||||
elog_set_filter_lvl(level);
|
||||
elog_set_filter_tag(tag);
|
||||
elog_set_filter_kw(keyword);
|
||||
}
|
||||
|
||||
/**
|
||||
* set log filter's level
|
||||
*
|
||||
* @param level level
|
||||
*/
|
||||
void elog_set_filter_lvl(uint8_t level) {
|
||||
ELOG_ASSERT(level <= ELOG_LVL_VERBOSE);
|
||||
|
||||
elog.filter.level = level;
|
||||
}
|
||||
|
||||
/**
|
||||
* set log filter's tag
|
||||
*
|
||||
* @param tag tag
|
||||
*/
|
||||
void elog_set_filter_tag(const char *tag) {
|
||||
strncpy(elog.filter.tag, tag, ELOG_FILTER_TAG_MAX_LEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* set log filter's keyword
|
||||
*
|
||||
* @param keyword keyword
|
||||
*/
|
||||
void elog_set_filter_kw(const char *keyword) {
|
||||
strncpy(elog.filter.keyword, keyword, ELOG_FILTER_KW_MAX_LEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* lock output
|
||||
*/
|
||||
void elog_output_lock(void) {
|
||||
if (elog.output_lock_enabled) {
|
||||
elog_port_output_lock();
|
||||
elog.output_is_locked_before_disable = true;
|
||||
} else {
|
||||
elog.output_is_locked_before_enable = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* unlock output
|
||||
*/
|
||||
void elog_output_unlock(void) {
|
||||
if (elog.output_lock_enabled) {
|
||||
elog_port_output_unlock();
|
||||
elog.output_is_locked_before_disable = false;
|
||||
} else {
|
||||
elog.output_is_locked_before_enable = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* set log filter's tag level val to default
|
||||
*/
|
||||
static void elog_set_filter_tag_lvl_default()
|
||||
{
|
||||
uint8_t i = 0;
|
||||
|
||||
for (i =0; i< ELOG_FILTER_TAG_LVL_MAX_NUM; i++){
|
||||
memset(elog.filter.tag_lvl[i].tag, '\0', ELOG_FILTER_TAG_MAX_LEN + 1);
|
||||
elog.filter.tag_lvl[i].level = ELOG_FILTER_LVL_SILENT;
|
||||
elog.filter.tag_lvl[i].tag_use_flag = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the filter's level by different tag.
|
||||
* The log on this tag which level is less than it will stop output.
|
||||
*
|
||||
* example:
|
||||
* // the example tag log enter silent mode
|
||||
* elog_set_filter_tag_lvl("example", ELOG_FILTER_LVL_SILENT);
|
||||
* // the example tag log which level is less than INFO level will stop output
|
||||
* elog_set_filter_tag_lvl("example", ELOG_LVL_INFO);
|
||||
* // remove example tag's level filter, all level log will resume output
|
||||
* elog_set_filter_tag_lvl("example", ELOG_FILTER_LVL_ALL);
|
||||
*
|
||||
* @param tag log tag
|
||||
* @param level The filter level. When the level is ELOG_FILTER_LVL_SILENT, the log enter silent mode.
|
||||
* When the level is ELOG_FILTER_LVL_ALL, it will remove this tag's level filer.
|
||||
* Then all level log will resume output.
|
||||
*
|
||||
*/
|
||||
void elog_set_filter_tag_lvl(const char *tag, uint8_t level)
|
||||
{
|
||||
ELOG_ASSERT(level <= ELOG_LVL_VERBOSE);
|
||||
ELOG_ASSERT(tag != ((void *)0));
|
||||
uint8_t i = 0;
|
||||
|
||||
if (!elog.init_ok) {
|
||||
return;
|
||||
}
|
||||
|
||||
elog_port_output_lock();
|
||||
/* find the tag in arr */
|
||||
for (i =0; i< ELOG_FILTER_TAG_LVL_MAX_NUM; i++){
|
||||
if (elog.filter.tag_lvl[i].tag_use_flag == true &&
|
||||
!strncmp(tag, elog.filter.tag_lvl[i].tag,ELOG_FILTER_TAG_MAX_LEN)){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < ELOG_FILTER_TAG_LVL_MAX_NUM){
|
||||
/* find OK */
|
||||
if (level == ELOG_FILTER_LVL_ALL){
|
||||
/* remove current tag's level filter when input level is the lowest level */
|
||||
elog.filter.tag_lvl[i].tag_use_flag = false;
|
||||
memset(elog.filter.tag_lvl[i].tag, '\0', ELOG_FILTER_TAG_MAX_LEN + 1);
|
||||
elog.filter.tag_lvl[i].level = ELOG_FILTER_LVL_SILENT;
|
||||
} else{
|
||||
elog.filter.tag_lvl[i].level = level;
|
||||
}
|
||||
} else{
|
||||
/* only add the new tag's level filer when level is not ELOG_FILTER_LVL_ALL */
|
||||
if (level != ELOG_FILTER_LVL_ALL){
|
||||
for (i =0; i< ELOG_FILTER_TAG_LVL_MAX_NUM; i++){
|
||||
if (elog.filter.tag_lvl[i].tag_use_flag == false){
|
||||
strncpy(elog.filter.tag_lvl[i].tag, tag, ELOG_FILTER_TAG_MAX_LEN);
|
||||
elog.filter.tag_lvl[i].level = level;
|
||||
elog.filter.tag_lvl[i].tag_use_flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
elog_output_unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* get the level on tag's level filer
|
||||
*
|
||||
* @param tag tag
|
||||
*
|
||||
* @return It will return the lowest level when tag was not found.
|
||||
* Other level will return when tag was found.
|
||||
*/
|
||||
uint8_t elog_get_filter_tag_lvl(const char *tag)
|
||||
{
|
||||
ELOG_ASSERT(tag != ((void *)0));
|
||||
uint8_t i = 0;
|
||||
uint8_t level = ELOG_FILTER_LVL_ALL;
|
||||
|
||||
if (!elog.init_ok) {
|
||||
return level;
|
||||
}
|
||||
|
||||
elog_port_output_lock();
|
||||
/* find the tag in arr */
|
||||
for (i =0; i< ELOG_FILTER_TAG_LVL_MAX_NUM; i++){
|
||||
if (elog.filter.tag_lvl[i].tag_use_flag == true &&
|
||||
!strncmp(tag, elog.filter.tag_lvl[i].tag,ELOG_FILTER_TAG_MAX_LEN)){
|
||||
level = elog.filter.tag_lvl[i].level;
|
||||
break;
|
||||
}
|
||||
}
|
||||
elog_output_unlock();
|
||||
|
||||
return level;
|
||||
}
|
||||
|
||||
/**
|
||||
* output RAW format log
|
||||
*
|
||||
* @param format output format
|
||||
* @param ... args
|
||||
*/
|
||||
void elog_raw(const char *format, ...) {
|
||||
va_list args;
|
||||
size_t log_len = 0;
|
||||
int fmt_result;
|
||||
|
||||
/* check output enabled */
|
||||
if (!elog.output_enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* args point to the first variable parameter */
|
||||
va_start(args, format);
|
||||
|
||||
/* lock output */
|
||||
elog_output_lock();
|
||||
|
||||
/* package log data to buffer */
|
||||
fmt_result = vsnprintf(log_buf, ELOG_LINE_BUF_SIZE, format, args);
|
||||
|
||||
/* output converted log */
|
||||
if ((fmt_result > -1) && (fmt_result <= ELOG_LINE_BUF_SIZE)) {
|
||||
log_len = fmt_result;
|
||||
} else {
|
||||
log_len = ELOG_LINE_BUF_SIZE;
|
||||
}
|
||||
/* output log */
|
||||
#if defined(ELOG_ASYNC_OUTPUT_ENABLE)
|
||||
extern void elog_async_output(uint8_t level, const char *log, size_t size);
|
||||
/* raw log will using assert level */
|
||||
elog_async_output(ELOG_LVL_ASSERT, log_buf, log_len);
|
||||
#elif defined(ELOG_BUF_OUTPUT_ENABLE)
|
||||
extern void elog_buf_output(const char *log, size_t size);
|
||||
elog_buf_output(log_buf, log_len);
|
||||
#else
|
||||
elog_port_output(log_buf, log_len);
|
||||
#endif
|
||||
/* unlock output */
|
||||
elog_output_unlock();
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
/**
|
||||
* output the log
|
||||
*
|
||||
* @param level level
|
||||
* @param tag tag
|
||||
* @param file file name
|
||||
* @param func function name
|
||||
* @param line line number
|
||||
* @param format output format
|
||||
* @param ... args
|
||||
*
|
||||
*/
|
||||
void elog_output(uint8_t level, const char *tag, const char *file, const char *func,
|
||||
const long line, const char *format, ...) {
|
||||
extern const char *elog_port_get_time(void);
|
||||
extern const char *elog_port_get_p_info(void);
|
||||
extern const char *elog_port_get_t_info(void);
|
||||
|
||||
size_t tag_len = strlen(tag), log_len = 0, newline_len = strlen(ELOG_NEWLINE_SIGN);
|
||||
char line_num[ELOG_LINE_NUM_MAX_LEN + 1] = { 0 };
|
||||
char tag_sapce[ELOG_FILTER_TAG_MAX_LEN / 2 + 1] = { 0 };
|
||||
va_list args;
|
||||
int fmt_result;
|
||||
|
||||
ELOG_ASSERT(level <= ELOG_LVL_VERBOSE);
|
||||
|
||||
/* check output enabled */
|
||||
if (!elog.output_enabled) {
|
||||
return;
|
||||
}
|
||||
/* level filter */
|
||||
if (level > elog.filter.level || level > elog_get_filter_tag_lvl(tag)) {
|
||||
return;
|
||||
} else if (!strstr(tag, elog.filter.tag)) { /* tag filter */
|
||||
return;
|
||||
}
|
||||
/* args point to the first variable parameter */
|
||||
va_start(args, format);
|
||||
/* lock output */
|
||||
elog_output_lock();
|
||||
|
||||
#ifdef ELOG_COLOR_ENABLE
|
||||
/* add CSI start sign and color info */
|
||||
if (elog.text_color_enabled) {
|
||||
log_len += elog_strcpy(log_len, log_buf + log_len, CSI_START);
|
||||
log_len += elog_strcpy(log_len, log_buf + log_len, color_output_info[level]);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* package level info */
|
||||
if (get_fmt_enabled(level, ELOG_FMT_LVL)) {
|
||||
log_len += elog_strcpy(log_len, log_buf + log_len, level_output_info[level]);
|
||||
}
|
||||
/* package tag info */
|
||||
if (get_fmt_enabled(level, ELOG_FMT_TAG)) {
|
||||
log_len += elog_strcpy(log_len, log_buf + log_len, tag);
|
||||
/* if the tag length is less than 50% ELOG_FILTER_TAG_MAX_LEN, then fill space */
|
||||
if (tag_len <= ELOG_FILTER_TAG_MAX_LEN / 2) {
|
||||
memset(tag_sapce, ' ', ELOG_FILTER_TAG_MAX_LEN / 2 - tag_len);
|
||||
log_len += elog_strcpy(log_len, log_buf + log_len, tag_sapce);
|
||||
}
|
||||
log_len += elog_strcpy(log_len, log_buf + log_len, " ");
|
||||
}
|
||||
/* package time, process and thread info */
|
||||
if (get_fmt_enabled(level, ELOG_FMT_TIME | ELOG_FMT_P_INFO | ELOG_FMT_T_INFO)) {
|
||||
log_len += elog_strcpy(log_len, log_buf + log_len, "[");
|
||||
/* package time info */
|
||||
if (get_fmt_enabled(level, ELOG_FMT_TIME)) {
|
||||
log_len += elog_strcpy(log_len, log_buf + log_len, elog_port_get_time());
|
||||
if (get_fmt_enabled(level, ELOG_FMT_P_INFO | ELOG_FMT_T_INFO)) {
|
||||
log_len += elog_strcpy(log_len, log_buf + log_len, " ");
|
||||
}
|
||||
}
|
||||
/* package process info */
|
||||
if (get_fmt_enabled(level, ELOG_FMT_P_INFO)) {
|
||||
log_len += elog_strcpy(log_len, log_buf + log_len, elog_port_get_p_info());
|
||||
if (get_fmt_enabled(level, ELOG_FMT_T_INFO)) {
|
||||
log_len += elog_strcpy(log_len, log_buf + log_len, " ");
|
||||
}
|
||||
}
|
||||
/* package thread info */
|
||||
if (get_fmt_enabled(level, ELOG_FMT_T_INFO)) {
|
||||
log_len += elog_strcpy(log_len, log_buf + log_len, elog_port_get_t_info());
|
||||
}
|
||||
log_len += elog_strcpy(log_len, log_buf + log_len, "] ");
|
||||
}
|
||||
/* package file directory and name, function name and line number info */
|
||||
if (get_fmt_enabled(level, ELOG_FMT_DIR | ELOG_FMT_FUNC | ELOG_FMT_LINE)) {
|
||||
log_len += elog_strcpy(log_len, log_buf + log_len, "(");
|
||||
/* package time info */
|
||||
if (get_fmt_enabled(level, ELOG_FMT_DIR)) {
|
||||
log_len += elog_strcpy(log_len, log_buf + log_len, file);
|
||||
if (get_fmt_enabled(level, ELOG_FMT_FUNC)) {
|
||||
log_len += elog_strcpy(log_len, log_buf + log_len, " ");
|
||||
} else if (get_fmt_enabled(level, ELOG_FMT_LINE)) {
|
||||
log_len += elog_strcpy(log_len, log_buf + log_len, ":");
|
||||
}
|
||||
}
|
||||
/* package process info */
|
||||
if (get_fmt_enabled(level, ELOG_FMT_FUNC)) {
|
||||
log_len += elog_strcpy(log_len, log_buf + log_len, func);
|
||||
if (get_fmt_enabled(level, ELOG_FMT_LINE)) {
|
||||
log_len += elog_strcpy(log_len, log_buf + log_len, ":");
|
||||
}
|
||||
}
|
||||
/* package thread info */
|
||||
if (get_fmt_enabled(level, ELOG_FMT_LINE)) {
|
||||
snprintf(line_num, ELOG_LINE_NUM_MAX_LEN, "%ld", line);
|
||||
log_len += elog_strcpy(log_len, log_buf + log_len, line_num);
|
||||
}
|
||||
log_len += elog_strcpy(log_len, log_buf + log_len, ")");
|
||||
}
|
||||
/* package other log data to buffer. '\0' must be added in the end by vsnprintf. */
|
||||
fmt_result = vsnprintf(log_buf + log_len, ELOG_LINE_BUF_SIZE - log_len, format, args);
|
||||
|
||||
va_end(args);
|
||||
/* calculate log length */
|
||||
if ((log_len + fmt_result <= ELOG_LINE_BUF_SIZE) && (fmt_result > -1)) {
|
||||
log_len += fmt_result;
|
||||
} else {
|
||||
/* using max length */
|
||||
log_len = ELOG_LINE_BUF_SIZE;
|
||||
}
|
||||
/* overflow check and reserve some space for CSI end sign and newline sign */
|
||||
#ifdef ELOG_COLOR_ENABLE
|
||||
if (log_len + (sizeof(CSI_END) - 1) + newline_len > ELOG_LINE_BUF_SIZE) {
|
||||
/* using max length */
|
||||
log_len = ELOG_LINE_BUF_SIZE;
|
||||
/* reserve some space for CSI end sign */
|
||||
log_len -= (sizeof(CSI_END) - 1);
|
||||
#else
|
||||
if (log_len + newline_len > ELOG_LINE_BUF_SIZE) {
|
||||
/* using max length */
|
||||
log_len = ELOG_LINE_BUF_SIZE;
|
||||
#endif /* ELOG_COLOR_ENABLE */
|
||||
/* reserve some space for newline sign */
|
||||
log_len -= newline_len;
|
||||
}
|
||||
/* keyword filter */
|
||||
if (elog.filter.keyword[0] != '\0') {
|
||||
/* add string end sign */
|
||||
log_buf[log_len] = '\0';
|
||||
/* find the keyword */
|
||||
if (!strstr(log_buf, elog.filter.keyword)) {
|
||||
/* unlock output */
|
||||
elog_output_unlock();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ELOG_COLOR_ENABLE
|
||||
/* add CSI end sign */
|
||||
if (elog.text_color_enabled) {
|
||||
log_len += elog_strcpy(log_len, log_buf + log_len, CSI_END);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* package newline sign */
|
||||
log_len += elog_strcpy(log_len, log_buf + log_len, ELOG_NEWLINE_SIGN);
|
||||
/* output log */
|
||||
#if defined(ELOG_ASYNC_OUTPUT_ENABLE)
|
||||
extern void elog_async_output(uint8_t level, const char *log, size_t size);
|
||||
elog_async_output(level, log_buf, log_len);
|
||||
#elif defined(ELOG_BUF_OUTPUT_ENABLE)
|
||||
extern void elog_buf_output(const char *log, size_t size);
|
||||
elog_buf_output(log_buf, log_len);
|
||||
#else
|
||||
elog_port_output(log_buf, log_len);
|
||||
#endif
|
||||
/* unlock output */
|
||||
elog_output_unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* get format enabled
|
||||
*
|
||||
* @param level level
|
||||
* @param set format set
|
||||
*
|
||||
* @return enable or disable
|
||||
*/
|
||||
static bool get_fmt_enabled(uint8_t level, size_t set) {
|
||||
ELOG_ASSERT(level <= ELOG_LVL_VERBOSE);
|
||||
|
||||
if (elog.enabled_fmt_set[level] & set) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* enable or disable logger output lock
|
||||
* @note disable this lock is not recommended except you want output system exception log
|
||||
*
|
||||
* @param enabled true: enable false: disable
|
||||
*/
|
||||
void elog_output_lock_enabled(bool enabled) {
|
||||
elog.output_lock_enabled = enabled;
|
||||
/* it will re-lock or re-unlock before output lock enable */
|
||||
if (elog.output_lock_enabled) {
|
||||
if (!elog.output_is_locked_before_disable && elog.output_is_locked_before_enable) {
|
||||
/* the output lock is unlocked before disable, and the lock will unlocking after enable */
|
||||
elog_port_output_lock();
|
||||
} else if (elog.output_is_locked_before_disable && !elog.output_is_locked_before_enable) {
|
||||
/* the output lock is locked before disable, and the lock will locking after enable */
|
||||
elog_port_output_unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a hook function to EasyLogger assert. It will run when the expression is false.
|
||||
*
|
||||
* @param hook the hook function
|
||||
*/
|
||||
void elog_assert_set_hook(void (*hook)(const char* expr, const char* func, size_t line)) {
|
||||
elog_assert_hook = hook;
|
||||
}
|
||||
|
||||
/**
|
||||
* find the log level
|
||||
* @note make sure the log level is output on each format
|
||||
*
|
||||
* @param log log buffer
|
||||
*
|
||||
* @return log level, found failed will return -1
|
||||
*/
|
||||
int8_t elog_find_lvl(const char *log) {
|
||||
ELOG_ASSERT(log);
|
||||
/* make sure the log level is output on each format */
|
||||
ELOG_ASSERT(elog.enabled_fmt_set[ELOG_LVL_ASSERT] & ELOG_FMT_LVL);
|
||||
ELOG_ASSERT(elog.enabled_fmt_set[ELOG_LVL_ERROR] & ELOG_FMT_LVL);
|
||||
ELOG_ASSERT(elog.enabled_fmt_set[ELOG_LVL_WARN] & ELOG_FMT_LVL);
|
||||
ELOG_ASSERT(elog.enabled_fmt_set[ELOG_LVL_INFO] & ELOG_FMT_LVL);
|
||||
ELOG_ASSERT(elog.enabled_fmt_set[ELOG_LVL_DEBUG] & ELOG_FMT_LVL);
|
||||
ELOG_ASSERT(elog.enabled_fmt_set[ELOG_LVL_VERBOSE] & ELOG_FMT_LVL);
|
||||
|
||||
#ifdef ELOG_COLOR_ENABLE
|
||||
uint8_t i;
|
||||
size_t csi_start_len = strlen(CSI_START);
|
||||
for(i = 0; i < ELOG_LVL_TOTAL_NUM; i ++) {
|
||||
if (!strncmp(color_output_info[i], log + csi_start_len, strlen(color_output_info[i]))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
/* found failed */
|
||||
return -1;
|
||||
#else
|
||||
switch (log[0]) {
|
||||
case 'A': return ELOG_LVL_ASSERT;
|
||||
case 'E': return ELOG_LVL_ERROR;
|
||||
case 'W': return ELOG_LVL_WARN;
|
||||
case 'I': return ELOG_LVL_INFO;
|
||||
case 'D': return ELOG_LVL_DEBUG;
|
||||
case 'V': return ELOG_LVL_VERBOSE;
|
||||
default: return -1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* find the log tag
|
||||
* @note make sure the log tag is output on each format
|
||||
* @note the tag don't have space in it
|
||||
*
|
||||
* @param log log buffer
|
||||
* @param lvl log level, you can get it by @see elog_find_lvl
|
||||
* @param tag_len found tag length
|
||||
*
|
||||
* @return log tag, found failed will return NULL
|
||||
*/
|
||||
const char *elog_find_tag(const char *log, uint8_t lvl, size_t *tag_len) {
|
||||
const char *tag = NULL, *tag_end = NULL;
|
||||
|
||||
ELOG_ASSERT(log);
|
||||
ELOG_ASSERT(tag_len);
|
||||
ELOG_ASSERT(lvl < ELOG_LVL_TOTAL_NUM);
|
||||
/* make sure the log tag is output on each format */
|
||||
ELOG_ASSERT(elog.enabled_fmt_set[lvl] & ELOG_FMT_TAG);
|
||||
|
||||
#ifdef ELOG_COLOR_ENABLE
|
||||
tag = log + strlen(CSI_START) + strlen(color_output_info[lvl]) + strlen(level_output_info[lvl]);
|
||||
#else
|
||||
tag = log + strlen(level_output_info[lvl]);
|
||||
#endif
|
||||
/* find the first space after tag */
|
||||
if ((tag_end = memchr(tag, ' ', ELOG_FILTER_TAG_MAX_LEN)) != NULL) {
|
||||
*tag_len = tag_end - tag;
|
||||
} else {
|
||||
tag = NULL;
|
||||
}
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* dump the hex format data to log
|
||||
*
|
||||
* @param name name for hex object, it will show on log header
|
||||
* @param width hex number for every line, such as: 16, 32
|
||||
* @param buf hex buffer
|
||||
* @param size buffer size
|
||||
*/
|
||||
void elog_hexdump(const char *name, uint8_t width, uint8_t *buf, uint16_t size)
|
||||
{
|
||||
#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
|
||||
|
||||
uint16_t i, j;
|
||||
uint16_t log_len = 0;
|
||||
char dump_string[8] = {0};
|
||||
int fmt_result;
|
||||
|
||||
if (!elog.output_enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* level filter */
|
||||
if (ELOG_LVL_DEBUG > elog.filter.level) {
|
||||
return;
|
||||
} else if (!strstr(name, elog.filter.tag)) { /* tag filter */
|
||||
return;
|
||||
}
|
||||
|
||||
/* lock output */
|
||||
elog_output_lock();
|
||||
|
||||
for (i = 0; i < size; i += width) {
|
||||
/* package header */
|
||||
fmt_result = snprintf(log_buf, ELOG_LINE_BUF_SIZE, "D/HEX %s: %04X-%04X: ", name, i, i + width - 1);
|
||||
/* calculate log length */
|
||||
if ((fmt_result > -1) && (fmt_result <= ELOG_LINE_BUF_SIZE)) {
|
||||
log_len = fmt_result;
|
||||
} else {
|
||||
log_len = ELOG_LINE_BUF_SIZE;
|
||||
}
|
||||
/* dump hex */
|
||||
for (j = 0; j < width; j++) {
|
||||
if (i + j < size) {
|
||||
snprintf(dump_string, sizeof(dump_string), "%02X ", buf[i + j]);
|
||||
} else {
|
||||
strncpy(dump_string, " ", sizeof(dump_string));
|
||||
}
|
||||
log_len += elog_strcpy(log_len, log_buf + log_len, dump_string);
|
||||
if ((j + 1) % 8 == 0) {
|
||||
log_len += elog_strcpy(log_len, log_buf + log_len, " ");
|
||||
}
|
||||
}
|
||||
log_len += elog_strcpy(log_len, log_buf + log_len, " ");
|
||||
/* dump char for hex */
|
||||
for (j = 0; j < width; j++) {
|
||||
if (i + j < size) {
|
||||
snprintf(dump_string, sizeof(dump_string), "%c", __is_print(buf[i + j]) ? buf[i + j] : '.');
|
||||
log_len += elog_strcpy(log_len, log_buf + log_len, dump_string);
|
||||
}
|
||||
}
|
||||
/* overflow check and reserve some space for newline sign */
|
||||
if (log_len + strlen(ELOG_NEWLINE_SIGN) > ELOG_LINE_BUF_SIZE) {
|
||||
log_len = ELOG_LINE_BUF_SIZE - strlen(ELOG_NEWLINE_SIGN);
|
||||
}
|
||||
/* package newline sign */
|
||||
log_len += elog_strcpy(log_len, log_buf + log_len, ELOG_NEWLINE_SIGN);
|
||||
/* do log output */
|
||||
#if defined(ELOG_ASYNC_OUTPUT_ENABLE)
|
||||
extern void elog_async_output(uint8_t level, const char *log, size_t size);
|
||||
elog_async_output(ELOG_LVL_DEBUG, log_buf, log_len);
|
||||
#elif defined(ELOG_BUF_OUTPUT_ENABLE)
|
||||
extern void elog_buf_output(const char *log, size_t size);
|
||||
elog_buf_output(log_buf, log_len);
|
||||
#else
|
||||
elog_port_output(log_buf, log_len);
|
||||
#endif
|
||||
}
|
||||
/* unlock output */
|
||||
elog_output_unlock();
|
||||
}
|
@ -0,0 +1,352 @@
|
||||
/*
|
||||
* This file is part of the EasyLogger Library.
|
||||
*
|
||||
* Copyright (c) 2016-2017, Armink, <armink.ztl@gmail.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Function: Logs asynchronous output.
|
||||
* Created on: 2016-11-06
|
||||
*/
|
||||
|
||||
#include <elog.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef ELOG_ASYNC_OUTPUT_ENABLE
|
||||
|
||||
#ifdef ELOG_ASYNC_OUTPUT_USING_PTHREAD
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#include <semaphore.h>
|
||||
/* thread default stack size */
|
||||
#ifndef ELOG_ASYNC_OUTPUT_PTHREAD_STACK_SIZE
|
||||
#if PTHREAD_STACK_MIN > 4*1024
|
||||
#define ELOG_ASYNC_OUTPUT_PTHREAD_STACK_SIZE PTHREAD_STACK_MIN
|
||||
#else
|
||||
#define ELOG_ASYNC_OUTPUT_PTHREAD_STACK_SIZE (1*1024)
|
||||
#endif
|
||||
/* thread default priority */
|
||||
#ifndef ELOG_ASYNC_OUTPUT_PTHREAD_PRIORITY
|
||||
#define ELOG_ASYNC_OUTPUT_PTHREAD_PRIORITY (sched_get_priority_max(SCHED_RR) - 1)
|
||||
#endif
|
||||
/* output thread poll get log buffer size */
|
||||
#ifndef ELOG_ASYNC_POLL_GET_LOG_BUF_SIZE
|
||||
#define ELOG_ASYNC_POLL_GET_LOG_BUF_SIZE (ELOG_LINE_BUF_SIZE - 4)
|
||||
#endif
|
||||
#endif /* ELOG_ASYNC_OUTPUT_USING_PTHREAD */
|
||||
|
||||
/* asynchronous output log notice */
|
||||
static sem_t output_notice;
|
||||
/* asynchronous output pthread thread */
|
||||
static pthread_t async_output_thread;
|
||||
#endif /* ELOG_ASYNC_OUTPUT_USING_PTHREAD */
|
||||
|
||||
/* the highest output level for async mode, other level will sync output */
|
||||
#ifdef ELOG_ASYNC_OUTPUT_LVL
|
||||
#define OUTPUT_LVL ELOG_ASYNC_OUTPUT_LVL
|
||||
#else
|
||||
#define OUTPUT_LVL ELOG_LVL_ASSERT
|
||||
#endif /* ELOG_ASYNC_OUTPUT_LVL */
|
||||
|
||||
/* buffer size for asynchronous output mode */
|
||||
#ifdef ELOG_ASYNC_OUTPUT_BUF_SIZE
|
||||
#define OUTPUT_BUF_SIZE ELOG_ASYNC_OUTPUT_BUF_SIZE
|
||||
#else
|
||||
#define OUTPUT_BUF_SIZE (ELOG_LINE_BUF_SIZE * 10)
|
||||
#endif /* ELOG_ASYNC_OUTPUT_BUF_SIZE */
|
||||
|
||||
/* Initialize OK flag */
|
||||
static bool init_ok = false;
|
||||
/* asynchronous output mode enabled flag */
|
||||
static bool is_enabled = false;
|
||||
/* asynchronous output mode's ring buffer */
|
||||
static char log_buf[OUTPUT_BUF_SIZE] = { 0 };
|
||||
/* log ring buffer write index */
|
||||
static size_t write_index = 0;
|
||||
/* log ring buffer read index */
|
||||
static size_t read_index = 0;
|
||||
/* log ring buffer full flag */
|
||||
static bool buf_is_full = false;
|
||||
/* log ring buffer empty flag */
|
||||
static bool buf_is_empty = true;
|
||||
|
||||
extern void elog_port_output(const char *log, size_t size);
|
||||
extern void elog_output_lock(void);
|
||||
extern void elog_output_unlock(void);
|
||||
|
||||
/**
|
||||
* asynchronous output ring buffer used size
|
||||
*
|
||||
* @return used size
|
||||
*/
|
||||
static size_t elog_async_get_buf_used(void) {
|
||||
if (write_index > read_index) {
|
||||
return write_index - read_index;
|
||||
} else {
|
||||
if (!buf_is_full && !buf_is_empty) {
|
||||
return OUTPUT_BUF_SIZE - (read_index - write_index);
|
||||
} else if (buf_is_full) {
|
||||
return OUTPUT_BUF_SIZE;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* asynchronous output ring buffer remain space
|
||||
*
|
||||
* @return remain space
|
||||
*/
|
||||
static size_t async_get_buf_space(void) {
|
||||
return OUTPUT_BUF_SIZE - elog_async_get_buf_used();
|
||||
}
|
||||
|
||||
/**
|
||||
* put log to asynchronous output ring buffer
|
||||
*
|
||||
* @param log put log buffer
|
||||
* @param size log size
|
||||
*
|
||||
* @return put log size, the log which beyond ring buffer space will be dropped
|
||||
*/
|
||||
static size_t async_put_log(const char *log, size_t size) {
|
||||
size_t space = 0;
|
||||
|
||||
space = async_get_buf_space();
|
||||
/* no space */
|
||||
if (!space) {
|
||||
size = 0;
|
||||
goto __exit;
|
||||
}
|
||||
/* drop some log */
|
||||
if (space <= size) {
|
||||
size = space;
|
||||
buf_is_full = true;
|
||||
}
|
||||
|
||||
if (write_index + size < OUTPUT_BUF_SIZE) {
|
||||
memcpy(log_buf + write_index, log, size);
|
||||
write_index += size;
|
||||
} else {
|
||||
memcpy(log_buf + write_index, log, OUTPUT_BUF_SIZE - write_index);
|
||||
memcpy(log_buf, log + OUTPUT_BUF_SIZE - write_index,
|
||||
size - (OUTPUT_BUF_SIZE - write_index));
|
||||
write_index += size - OUTPUT_BUF_SIZE;
|
||||
}
|
||||
|
||||
buf_is_empty = false;
|
||||
|
||||
__exit:
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
#ifdef ELOG_ASYNC_LINE_OUTPUT
|
||||
/**
|
||||
* Get line log from asynchronous output ring buffer.
|
||||
* It will copy all log when the newline sign isn't find.
|
||||
*
|
||||
* @param log get line log buffer
|
||||
* @param size line log size
|
||||
*
|
||||
* @return get line log size, the log size is less than ring buffer used size
|
||||
*/
|
||||
size_t elog_async_get_line_log(char *log, size_t size) {
|
||||
size_t used = 0, cpy_log_size = 0;
|
||||
/* lock output */
|
||||
elog_output_lock();
|
||||
used = elog_async_get_buf_used();
|
||||
|
||||
/* no log */
|
||||
if (!used || !size) {
|
||||
goto __exit;
|
||||
}
|
||||
/* less log */
|
||||
if (used <= size) {
|
||||
size = used;
|
||||
}
|
||||
|
||||
if (read_index + size < OUTPUT_BUF_SIZE) {
|
||||
cpy_log_size = elog_cpyln(log, log_buf + read_index, size);
|
||||
read_index += cpy_log_size;
|
||||
} else {
|
||||
cpy_log_size = elog_cpyln(log, log_buf + read_index, OUTPUT_BUF_SIZE - read_index);
|
||||
if (cpy_log_size == OUTPUT_BUF_SIZE - read_index) {
|
||||
cpy_log_size += elog_cpyln(log + cpy_log_size, log_buf, size - cpy_log_size);
|
||||
read_index += cpy_log_size - OUTPUT_BUF_SIZE;
|
||||
} else {
|
||||
read_index += cpy_log_size;
|
||||
}
|
||||
}
|
||||
|
||||
if (used == cpy_log_size) {
|
||||
buf_is_empty = true;
|
||||
}
|
||||
|
||||
if (cpy_log_size) {
|
||||
buf_is_full = false;
|
||||
}
|
||||
|
||||
__exit:
|
||||
/* lock output */
|
||||
elog_output_unlock();
|
||||
return cpy_log_size;
|
||||
}
|
||||
#else
|
||||
/**
|
||||
* get log from asynchronous output ring buffer
|
||||
*
|
||||
* @param log get log buffer
|
||||
* @param size log size
|
||||
*
|
||||
* @return get log size, the log size is less than ring buffer used size
|
||||
*/
|
||||
size_t elog_async_get_log(char *log, size_t size) {
|
||||
size_t used = 0;
|
||||
/* lock output */
|
||||
elog_output_lock();
|
||||
used = elog_async_get_buf_used();
|
||||
/* no log */
|
||||
if (!used || !size) {
|
||||
size = 0;
|
||||
goto __exit;
|
||||
}
|
||||
/* less log */
|
||||
if (used <= size) {
|
||||
size = used;
|
||||
buf_is_empty = true;
|
||||
}
|
||||
|
||||
if (read_index + size < OUTPUT_BUF_SIZE) {
|
||||
memcpy(log, log_buf + read_index, size);
|
||||
read_index += size;
|
||||
} else {
|
||||
memcpy(log, log_buf + read_index, OUTPUT_BUF_SIZE - read_index);
|
||||
memcpy(log + OUTPUT_BUF_SIZE - read_index, log_buf,
|
||||
size - (OUTPUT_BUF_SIZE - read_index));
|
||||
read_index += size - OUTPUT_BUF_SIZE;
|
||||
}
|
||||
|
||||
buf_is_full = false;
|
||||
|
||||
__exit:
|
||||
/* lock output */
|
||||
elog_output_unlock();
|
||||
return size;
|
||||
}
|
||||
#endif /* ELOG_ASYNC_LINE_OUTPUT */
|
||||
|
||||
void elog_async_output(uint8_t level, const char *log, size_t size) {
|
||||
/* this function must be implement by user when ELOG_ASYNC_OUTPUT_USING_PTHREAD is not defined */
|
||||
extern void elog_async_output_notice(void);
|
||||
size_t put_size;
|
||||
|
||||
if (is_enabled) {
|
||||
if (level >= OUTPUT_LVL) {
|
||||
put_size = async_put_log(log, size);
|
||||
/* notify output log thread */
|
||||
if (put_size > 0) {
|
||||
elog_async_output_notice();
|
||||
}
|
||||
} else {
|
||||
elog_port_output(log, size);
|
||||
}
|
||||
} else {
|
||||
elog_port_output(log, size);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ELOG_ASYNC_OUTPUT_USING_PTHREAD
|
||||
void elog_async_output_notice(void) {
|
||||
sem_post(&output_notice);
|
||||
}
|
||||
|
||||
static void *async_output(void *arg) {
|
||||
size_t get_log_size = 0;
|
||||
static char poll_get_buf[ELOG_ASYNC_POLL_GET_LOG_BUF_SIZE];
|
||||
|
||||
while(true) {
|
||||
/* waiting log */
|
||||
sem_wait(&output_notice);
|
||||
/* polling gets and outputs the log */
|
||||
while(true) {
|
||||
|
||||
#ifdef ELOG_ASYNC_LINE_OUTPUT
|
||||
get_log_size = elog_async_get_line_log(poll_get_buf, ELOG_ASYNC_POLL_GET_LOG_BUF_SIZE);
|
||||
#else
|
||||
get_log_size = elog_async_get_log(poll_get_buf, ELOG_ASYNC_POLL_GET_LOG_BUF_SIZE);
|
||||
#endif
|
||||
|
||||
if (get_log_size) {
|
||||
elog_port_output(poll_get_buf, get_log_size);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* enable or disable asynchronous output mode
|
||||
* the log will be output directly when mode is disabled
|
||||
*
|
||||
* @param enabled true: enabled, false: disabled
|
||||
*/
|
||||
void elog_async_enabled(bool enabled) {
|
||||
is_enabled = enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* asynchronous output mode initialize
|
||||
*
|
||||
* @return result
|
||||
*/
|
||||
ElogErrCode elog_async_init(void) {
|
||||
ElogErrCode result = ELOG_NO_ERR;
|
||||
|
||||
if (init_ok) {
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef ELOG_ASYNC_OUTPUT_USING_PTHREAD
|
||||
pthread_attr_t thread_attr;
|
||||
struct sched_param thread_sched_param;
|
||||
|
||||
sem_init(&output_notice, 0, 0);
|
||||
|
||||
pthread_attr_init(&thread_attr);
|
||||
pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
|
||||
pthread_attr_setstacksize(&thread_attr, ELOG_ASYNC_OUTPUT_PTHREAD_STACK_SIZE);
|
||||
pthread_attr_setschedpolicy(&thread_attr, SCHED_RR);
|
||||
thread_sched_param.sched_priority = ELOG_ASYNC_OUTPUT_PTHREAD_PRIORITY;
|
||||
pthread_attr_setschedparam(&thread_attr, &thread_sched_param);
|
||||
pthread_create(&async_output_thread, &thread_attr, async_output, NULL);
|
||||
pthread_attr_destroy(&thread_attr);
|
||||
#endif
|
||||
|
||||
init_ok = true;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif /* ELOG_ASYNC_OUTPUT_ENABLE */
|
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* This file is part of the EasyLogger Library.
|
||||
*
|
||||
* Copyright (c) 2016, Armink, <armink.ztl@gmail.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Function: Logs buffered output.
|
||||
* Created on: 2016-11-09
|
||||
*/
|
||||
|
||||
#include <elog.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef ELOG_BUF_OUTPUT_ENABLE
|
||||
#if !defined(ELOG_BUF_OUTPUT_BUF_SIZE)
|
||||
#error "Please configure buffer size for buffered output mode (in elog_cfg.h)"
|
||||
#endif
|
||||
|
||||
/* buffered output mode's buffer */
|
||||
static char log_buf[ELOG_BUF_OUTPUT_BUF_SIZE] = { 0 };
|
||||
/* log buffer current write size */
|
||||
static size_t buf_write_size = 0;
|
||||
/* buffered output mode enabled flag */
|
||||
static bool is_enabled = false;
|
||||
|
||||
extern void elog_port_output(const char *log, size_t size);
|
||||
extern void elog_output_lock(void);
|
||||
extern void elog_output_unlock(void);
|
||||
|
||||
/**
|
||||
* output buffered logs when buffer is full
|
||||
*
|
||||
* @param log will be buffered line's log
|
||||
* @param size log size
|
||||
*/
|
||||
void elog_buf_output(const char *log, size_t size) {
|
||||
size_t write_size = 0, write_index = 0;
|
||||
|
||||
if (!is_enabled) {
|
||||
elog_port_output(log, size);
|
||||
return;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (buf_write_size + size > ELOG_BUF_OUTPUT_BUF_SIZE) {
|
||||
write_size = ELOG_BUF_OUTPUT_BUF_SIZE - buf_write_size;
|
||||
memcpy(log_buf + buf_write_size, log + write_index, write_size);
|
||||
write_index += write_size;
|
||||
size -= write_size;
|
||||
buf_write_size += write_size;
|
||||
/* output log */
|
||||
elog_port_output(log_buf, buf_write_size);
|
||||
/* reset write index */
|
||||
buf_write_size = 0;
|
||||
} else {
|
||||
memcpy(log_buf + buf_write_size, log + write_index, size);
|
||||
buf_write_size += size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* flush all buffered logs to output device
|
||||
*/
|
||||
void elog_flush(void) {
|
||||
/* lock output */
|
||||
elog_output_lock();
|
||||
/* output log */
|
||||
elog_port_output(log_buf, buf_write_size);
|
||||
/* reset write index */
|
||||
buf_write_size = 0;
|
||||
/* unlock output */
|
||||
elog_output_unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* enable or disable buffered output mode
|
||||
* the log will be output directly when mode is disabled
|
||||
*
|
||||
* @param enabled true: enabled, false: disabled
|
||||
*/
|
||||
void elog_buf_enabled(bool enabled) {
|
||||
is_enabled = enabled;
|
||||
}
|
||||
#endif /* ELOG_BUF_OUTPUT_ENABLE */
|
@ -0,0 +1,165 @@
|
||||
/*
|
||||
* This file is part of the EasyLogger Library.
|
||||
*
|
||||
* Copyright (c) 2015-2019, Qintl, <qintl_linux@163.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Function: Save log to file.
|
||||
* Created on: 2019-01-05
|
||||
*/
|
||||
|
||||
#define LOG_TAG "elog.file"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "elog_file.h"
|
||||
|
||||
/* initialize OK flag */
|
||||
static bool init_ok = false;
|
||||
static FILE *fp = NULL;
|
||||
static ElogFileCfg local_cfg;
|
||||
|
||||
ElogErrCode elog_file_init(void)
|
||||
{
|
||||
ElogErrCode result = ELOG_NO_ERR;
|
||||
ElogFileCfg cfg;
|
||||
|
||||
if (init_ok)
|
||||
goto __exit;
|
||||
|
||||
elog_file_port_init();
|
||||
|
||||
cfg.name = ELOG_FILE_NAME;
|
||||
cfg.max_size = ELOG_FILE_MAX_SIZE;
|
||||
cfg.max_rotate = ELOG_FILE_MAX_ROTATE;
|
||||
|
||||
elog_file_config(&cfg);
|
||||
|
||||
init_ok = true;
|
||||
__exit:
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* rotate the log file xxx.log.n-1 => xxx.log.n, and xxx.log => xxx.log.0
|
||||
*/
|
||||
static bool elog_file_rotate(void)
|
||||
{
|
||||
#define SUFFIX_LEN 10
|
||||
/* mv xxx.log.n-1 => xxx.log.n, and xxx.log => xxx.log.0 */
|
||||
int n, err = 0;
|
||||
char oldpath[256], newpath[256];
|
||||
size_t base = strlen(local_cfg.name);
|
||||
bool result = true;
|
||||
FILE *tmp_fp;
|
||||
|
||||
memcpy(oldpath, local_cfg.name, base);
|
||||
memcpy(newpath, local_cfg.name, base);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
for (n = local_cfg.max_rotate - 1; n >= 0; --n) {
|
||||
snprintf(oldpath + base, SUFFIX_LEN, n ? ".%d" : "", n - 1);
|
||||
snprintf(newpath + base, SUFFIX_LEN, ".%d", n);
|
||||
/* remove the old file */
|
||||
if ((tmp_fp = fopen(newpath , "r")) != NULL) {
|
||||
fclose(tmp_fp);
|
||||
remove(newpath);
|
||||
}
|
||||
/* change the new log file to old file name */
|
||||
if ((tmp_fp = fopen(oldpath , "r")) != NULL) {
|
||||
fclose(tmp_fp);
|
||||
err = rename(oldpath, newpath);
|
||||
}
|
||||
|
||||
if (err < 0) {
|
||||
result = false;
|
||||
goto __exit;
|
||||
}
|
||||
}
|
||||
|
||||
__exit:
|
||||
/* reopen the file */
|
||||
fp = fopen(local_cfg.name, "a+");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void elog_file_write(const char *log, size_t size)
|
||||
{
|
||||
size_t file_size = 0;
|
||||
|
||||
ELOG_ASSERT(init_ok);
|
||||
ELOG_ASSERT(log);
|
||||
|
||||
elog_file_port_lock();
|
||||
|
||||
fseek(fp, 0L, SEEK_END);
|
||||
file_size = ftell(fp);
|
||||
|
||||
if (unlikely(file_size > local_cfg.max_size)) {
|
||||
#if ELOG_FILE_MAX_ROTATE > 0
|
||||
if (!elog_file_rotate()) {
|
||||
goto __exit;
|
||||
}
|
||||
#else
|
||||
goto __exit;
|
||||
#endif
|
||||
}
|
||||
|
||||
fwrite(log, size, 1, fp);
|
||||
|
||||
#ifdef ELOG_FILE_FLUSH_CAHCE_ENABLE
|
||||
fflush(fp);
|
||||
#endif
|
||||
|
||||
__exit:
|
||||
elog_file_port_unlock();
|
||||
}
|
||||
|
||||
void elog_file_deinit(void)
|
||||
{
|
||||
ELOG_ASSERT(init_ok);
|
||||
|
||||
elog_file_port_deinit();
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void elog_file_config(ElogFileCfg *cfg)
|
||||
{
|
||||
if (fp) {
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
elog_file_port_lock();
|
||||
|
||||
local_cfg.name = cfg->name;
|
||||
local_cfg.max_size = cfg->max_size;
|
||||
local_cfg.max_rotate = cfg->max_rotate;
|
||||
|
||||
fp = fopen(local_cfg.name, "a+");
|
||||
|
||||
elog_file_port_unlock();
|
||||
}
|
@ -0,0 +1,160 @@
|
||||
/*
|
||||
* This file is part of the EasyLogger Library.
|
||||
*
|
||||
* Copyright (c) 2015-2019, Qintl, <qintl_linux@163.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Function: Portable interface for EasyLogger's file log pulgin.
|
||||
* Created on: 2019-01-05
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/sem.h>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <elog_file.h>
|
||||
#include <elog_file_cfg.h>
|
||||
|
||||
#define ELOG_FILE_SEM_KEY ((key_t)0x19910612)
|
||||
#ifdef _SEM_SEMUN_UNDEFINED
|
||||
union semun {
|
||||
int val; /* Value for SETVAL */
|
||||
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
|
||||
unsigned short *array; /* Array for GETALL, SETALL */
|
||||
struct seminfo *__buf; /* Buffer for IPC_INFO
|
||||
(Linux-specific) */
|
||||
};
|
||||
#endif
|
||||
|
||||
static int semid = -1;
|
||||
static struct sembuf const up = {0, 1, SEM_UNDO};
|
||||
static struct sembuf const down = {0, -1, SEM_UNDO};
|
||||
|
||||
static void lock_init(void);
|
||||
static int lock_open(void);
|
||||
/**
|
||||
* EasyLogger flile log pulgin port initialize
|
||||
*
|
||||
* @return result
|
||||
*/
|
||||
ElogErrCode elog_file_port_init(void) {
|
||||
ElogErrCode result = ELOG_NO_ERR;
|
||||
|
||||
lock_init();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* file log lock
|
||||
*/
|
||||
void inline elog_file_port_lock(void)
|
||||
{
|
||||
semid == -1 ? -1 : semop(semid, (struct sembuf *)&down, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* file log unlock
|
||||
*/
|
||||
void inline elog_file_port_unlock(void)
|
||||
{
|
||||
semid == -1 ? -1 : semop(semid, (struct sembuf *)&up, 1);
|
||||
}
|
||||
/**
|
||||
* file log deinit
|
||||
*/
|
||||
void elog_file_port_deinit(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* initialize the lock
|
||||
*/
|
||||
static void lock_init(void)
|
||||
{
|
||||
int id, rc;
|
||||
union semun arg;
|
||||
struct sembuf sembuf;
|
||||
|
||||
id = semget(ELOG_FILE_SEM_KEY, 1, IPC_CREAT | IPC_EXCL | 0666);
|
||||
if(likely(id == -1)) {
|
||||
id = lock_open();
|
||||
if (id == -1)
|
||||
goto __exit;
|
||||
} else {
|
||||
arg.val = 0;
|
||||
rc = semctl(id, 0, SETVAL, arg);
|
||||
if (rc == -1)
|
||||
goto __exit;
|
||||
|
||||
sembuf.sem_num = 0;
|
||||
sembuf.sem_op = 1;
|
||||
sembuf.sem_flg = 0;
|
||||
|
||||
rc = semop(id, &sembuf, 1);
|
||||
if (rc == -1)
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
semid = id;
|
||||
__exit:
|
||||
return ;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the lock
|
||||
*/
|
||||
static int lock_open(void)
|
||||
{
|
||||
int id, rc, i;
|
||||
union semun arg;
|
||||
struct semid_ds ds;
|
||||
|
||||
id = semget(ELOG_FILE_SEM_KEY, 1, 0666);
|
||||
if(unlikely(id == -1))
|
||||
goto err;
|
||||
|
||||
arg.buf = &ds;
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
rc = semctl(id, 0, IPC_STAT, arg);
|
||||
if (unlikely(rc == -1))
|
||||
goto err;
|
||||
|
||||
if(ds.sem_otime != 0)
|
||||
break;
|
||||
|
||||
usleep(10 * 1000);
|
||||
}
|
||||
|
||||
if (unlikely(ds.sem_otime == 0))
|
||||
goto err;
|
||||
|
||||
return id;
|
||||
err:
|
||||
return -1;
|
||||
}
|
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* This file is part of the EasyLogger Library.
|
||||
*
|
||||
* Copyright (c) 2015, Armink, <armink.ztl@gmail.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Function: Portable interface for linux.
|
||||
* Created on: 2015-04-28
|
||||
*/
|
||||
|
||||
#include <elog.h>
|
||||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef ELOG_FILE_ENABLE
|
||||
#include <elog_file.h>
|
||||
#endif
|
||||
static pthread_mutex_t output_lock;
|
||||
|
||||
/**
|
||||
* EasyLogger port initialize
|
||||
*
|
||||
* @return result
|
||||
*/
|
||||
ElogErrCode elog_port_init(void) {
|
||||
ElogErrCode result = ELOG_NO_ERR;
|
||||
|
||||
pthread_mutex_init(&output_lock, NULL);
|
||||
|
||||
#ifdef ELOG_FILE_ENABLE
|
||||
elog_file_init();
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* output log port interface
|
||||
*
|
||||
* @param log output of log
|
||||
* @param size log size
|
||||
*/
|
||||
void elog_port_output(const char *log, size_t size) {
|
||||
/* output to terminal */
|
||||
printf("%.*s", (int)size, log);
|
||||
#ifdef ELOG_FILE_ENABLE
|
||||
/* write the file */
|
||||
elog_file_write(log, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* output lock
|
||||
*/
|
||||
void elog_port_output_lock(void) {
|
||||
pthread_mutex_lock(&output_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* output unlock
|
||||
*/
|
||||
void elog_port_output_unlock(void) {
|
||||
pthread_mutex_unlock(&output_lock);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* get current time interface
|
||||
*
|
||||
* @return current time
|
||||
*/
|
||||
const char *elog_port_get_time(void) {
|
||||
static char cur_system_time[24] = { 0 };
|
||||
time_t timep;
|
||||
struct tm *p;
|
||||
|
||||
time(&timep);
|
||||
p = localtime(&timep);
|
||||
if (p == NULL) {
|
||||
return "";
|
||||
}
|
||||
snprintf(cur_system_time, 18, "%02d-%02d %02d:%02d:%02d", p->tm_mon + 1, p->tm_mday,
|
||||
p->tm_hour, p->tm_min, p->tm_sec);
|
||||
|
||||
return cur_system_time;
|
||||
}
|
||||
|
||||
/**
|
||||
* get current process name interface
|
||||
*
|
||||
* @return current process name
|
||||
*/
|
||||
const char *elog_port_get_p_info(void) {
|
||||
static char cur_process_info[10] = { 0 };
|
||||
|
||||
snprintf(cur_process_info, 10, "pid:%04d", getpid());
|
||||
|
||||
return cur_process_info;
|
||||
}
|
||||
|
||||
/**
|
||||
* get current thread name interface
|
||||
*
|
||||
* @return current thread name
|
||||
*/
|
||||
const char *elog_port_get_t_info(void) {
|
||||
static char cur_thread_info[10] = { 0 };
|
||||
|
||||
snprintf(cur_thread_info, 10, "tid:%04ld", pthread_self());
|
||||
|
||||
return cur_thread_info;
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* This file is part of the EasyLogger Library.
|
||||
*
|
||||
* Copyright (c) 2015-2018, Armink, <armink.ztl@gmail.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Function: Some utils for this library.
|
||||
* Created on: 2015-04-28
|
||||
*/
|
||||
|
||||
#include <elog.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* another copy string function
|
||||
*
|
||||
* @param cur_len current copied log length, max size is ELOG_LINE_BUF_SIZE
|
||||
* @param dst destination
|
||||
* @param src source
|
||||
*
|
||||
* @return copied length
|
||||
*/
|
||||
size_t elog_strcpy(size_t cur_len, char *dst, const char *src) {
|
||||
const char *src_old = src;
|
||||
|
||||
assert(dst);
|
||||
assert(src);
|
||||
|
||||
while (*src != 0) {
|
||||
/* make sure destination has enough space */
|
||||
if (cur_len++ < ELOG_LINE_BUF_SIZE) {
|
||||
*dst++ = *src++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return src - src_old;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy line log split by newline sign. It will copy all log when the newline sign isn't find.
|
||||
*
|
||||
* @param line line log buffer
|
||||
* @param log origin log buffer
|
||||
* @param len origin log buffer length
|
||||
*
|
||||
* @return copy size
|
||||
*/
|
||||
size_t elog_cpyln(char *line, const char *log, size_t len) {
|
||||
size_t newline_len = strlen(ELOG_NEWLINE_SIGN), copy_size = 0;
|
||||
|
||||
assert(line);
|
||||
assert(log);
|
||||
|
||||
while (len--) {
|
||||
*line++ = *log++;
|
||||
copy_size++;
|
||||
if (copy_size >= newline_len && !strncmp(log - newline_len, ELOG_NEWLINE_SIGN, newline_len)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return copy_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will copy memory content from source address to destination
|
||||
* address.
|
||||
*
|
||||
* @param dst the address of destination memory
|
||||
* @param src the address of source memory
|
||||
* @param count the copied length
|
||||
*
|
||||
* @return the address of destination memory
|
||||
*/
|
||||
void *elog_memcpy(void *dst, const void *src, size_t count) {
|
||||
char *tmp = (char *) dst, *s = (char *) src;
|
||||
|
||||
assert(dst);
|
||||
assert(src);
|
||||
|
||||
while (count--)
|
||||
*tmp++ = *s++;
|
||||
|
||||
return dst;
|
||||
}
|
@ -0,0 +1,288 @@
|
||||
# Generic Makefile by tmb
|
||||
# Program name
|
||||
PROGRAM = sjzd_app
|
||||
|
||||
#PLAT = x86
|
||||
PLAT = arm
|
||||
|
||||
#VER = debug
|
||||
VER = release
|
||||
|
||||
TYPE = bin
|
||||
#TYPE = so
|
||||
|
||||
##==========================================================================
|
||||
PROGRAM := $(strip $(PROGRAM))
|
||||
PLAY := $(strip $(TYPE))
|
||||
VER := $(strip $(VER))
|
||||
|
||||
MY_CFLAGS = -fmessage-length=0
|
||||
|
||||
ifeq ($(PLAT),x86)
|
||||
MY_LIBS = -lpthread -L../lib -lrt -ldl -lscl_shm -lm -lgo
|
||||
else
|
||||
MY_LIBS = -L../lib -lpthread -lrt -ldl -lscl_shm -lm -lgo
|
||||
endif
|
||||
|
||||
# The pre-processor options used by the cpp (man cpp for more).
|
||||
#CPPFLAGS = -DHAVE_CONFIG_H -Wall -Wextra -Wno-invalid-offsetof
|
||||
CPPFLAGS = -Wall -Wextra
|
||||
|
||||
# The options used in linking as well as in any direct use of ld.
|
||||
ifeq ($(TYPE),so)
|
||||
LDFLAGS = -shared -fPIC
|
||||
else
|
||||
LDFLAGS =
|
||||
endif
|
||||
|
||||
# The directories in which source files reside.
|
||||
# If not specified, only the current directory will be serached.
|
||||
SRCDIRS =
|
||||
|
||||
## Implicit Section: change the following only when necessary.
|
||||
##==========================================================================
|
||||
|
||||
# The source file types (headers excluded).
|
||||
# .c indicates C source files, and others C++ ones.
|
||||
SRCEXTS = .c .C .cc .cpp .CPP .c++ .cxx .cp
|
||||
|
||||
# The header file types.
|
||||
HDREXTS = .h .H .hh .hpp .HPP .h++ .hxx .hp
|
||||
|
||||
# The pre-processor and compiler options.
|
||||
# Users can override those variables from the command line.
|
||||
ifeq ($(VER),debug)
|
||||
ifeq ($(TYPE),so)
|
||||
CFLAGS = -ggdb -pipe -O0 -fPIC -I. -I../inc
|
||||
CXXFLAGS= -ggdb -pipe -O0 -fPIC -I. -I../inc
|
||||
else
|
||||
CFLAGS = -ggdb -pipe -O0 -I. -I../inc
|
||||
CXXFLAGS= -ggdb -pipe -O0 -I. -I../inc
|
||||
endif
|
||||
else
|
||||
ifeq ($(TYPE),so)
|
||||
CFLAGS = -O2 -pipe -fPIC -I. -I../inc
|
||||
CXXFLAGS= -O2 -pipe -fPIC -I. -I../inc
|
||||
else
|
||||
CFLAGS = -O2 -pipe -I. -I../inc
|
||||
CXXFLAGS= -O2 -pipe -I. -I../inc
|
||||
endif
|
||||
endif
|
||||
|
||||
# The C program compiler.
|
||||
ifeq ($(PLAT),x86)
|
||||
CC = gcc
|
||||
else
|
||||
CC = arm-linux-gnueabihf-gcc
|
||||
endif
|
||||
|
||||
# The C++ program compiler.
|
||||
ifeq ($(PLAT),x86)
|
||||
CXX = g++
|
||||
else
|
||||
CXX = arm-linux-gnueabihf-g++
|
||||
endif
|
||||
|
||||
# Un-comment the following line to compile C programs as C++ ones.
|
||||
#CC = $(CXX)
|
||||
|
||||
ifeq ($(PLAT),x86)
|
||||
STRIP = strip
|
||||
else
|
||||
STRIP = arm-none-linux-gnueabi-strip
|
||||
endif
|
||||
|
||||
# The command used to delete file.
|
||||
#RM = rm -f
|
||||
|
||||
ETAGS = etags
|
||||
ETAGSFLAGS =
|
||||
|
||||
CTAGS = ctags
|
||||
CTAGSFLAGS =
|
||||
|
||||
## Stable Section: usually no need to be changed.
|
||||
##==========================================================================
|
||||
SHELL = /bin/sh
|
||||
EMPTY =
|
||||
SPACE = $(EMPTY) $(EMPTY)
|
||||
ifeq ($(PROGRAM),)
|
||||
CUR_PATH_NAMES = $(subst /,$(SPACE),$(subst $(SPACE),_,$(CURDIR)))
|
||||
PROGRAM = $(word $(words $(CUR_PATH_NAMES)),$(CUR_PATH_NAMES))
|
||||
ifeq ($(PROGRAM),)
|
||||
PROGRAM = a.out
|
||||
endif
|
||||
endif
|
||||
ifeq ($(SRCDIRS),)
|
||||
SRCDIRS = .
|
||||
endif
|
||||
SOURCES = $(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(SRCEXTS))))
|
||||
HEADERS = $(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(HDREXTS))))
|
||||
SRC_CXX = $(filter-out %.c,$(SOURCES))
|
||||
OBJS = $(addsuffix .o, $(basename $(SOURCES)))
|
||||
DEPS = $(OBJS:.o=.d)
|
||||
|
||||
## Define some useful variables.
|
||||
#DEP_OPT = $(shell if `$(CC) --version | grep "GCC"`; then echo "-MM -MP"; else echo "-M"; fi )
|
||||
DEP_OPT = -M
|
||||
DEPEND = $(CC) $(DEP_OPT) $(MY_CFLAGS) $(CFLAGS) $(CPPFLAGS)
|
||||
DEPEND.d = $(subst -g ,,$(DEPEND))
|
||||
COMPILE.c = $(CC) $(MY_CFLAGS) $(CFLAGS) $(CPPFLAGS) -c
|
||||
COMPILE.cxx = $(CXX) $(MY_CFLAGS) $(CXXFLAGS) $(CPPFLAGS) -c
|
||||
LINK.c = $(CC) $(MY_CFLAGS) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS)
|
||||
LINK.cxx = $(CXX) $(MY_CFLAGS) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS)
|
||||
|
||||
.PHONY: all objs tags ctags clean distclean help show objclean
|
||||
|
||||
# Delete the default suffixes
|
||||
.SUFFIXES:
|
||||
|
||||
all: $(PROGRAM)
|
||||
|
||||
# Rules for creating dependency files (.d).
|
||||
#------------------------------------------
|
||||
|
||||
%.d:%.c
|
||||
@echo -n $(dir $<) > $@
|
||||
@$(DEPEND.d) $< >> $@
|
||||
|
||||
%.d:%.C
|
||||
@echo -n $(dir $<) > $@
|
||||
@$(DEPEND.d) $< >> $@
|
||||
|
||||
%.d:%.cc
|
||||
@echo -n $(dir $<) > $@
|
||||
@$(DEPEND.d) $< >> $@
|
||||
|
||||
%.d:%.cpp
|
||||
@echo -n $(dir $<) > $@
|
||||
@$(DEPEND.d) $< >> $@
|
||||
|
||||
%.d:%.CPP
|
||||
@echo -n $(dir $<) > $@
|
||||
@$(DEPEND.d) $< >> $@
|
||||
|
||||
%.d:%.c++
|
||||
@echo -n $(dir $<) > $@
|
||||
@$(DEPEND.d) $< >> $@
|
||||
|
||||
%.d:%.cp
|
||||
@echo -n $(dir $<) > $@
|
||||
@$(DEPEND.d) $< >> $@
|
||||
|
||||
%.d:%.cxx
|
||||
@echo -n $(dir $<) > $@
|
||||
@$(DEPEND.d) $< >> $@
|
||||
|
||||
# Rules for generating object files (.o).
|
||||
#----------------------------------------
|
||||
objs:$(OBJS)
|
||||
|
||||
%.o:%.c
|
||||
@$(COMPILE.c) $< -o $@
|
||||
@echo "[M] $@"
|
||||
|
||||
%.o:%.C
|
||||
@$(COMPILE.cxx) $< -o $@
|
||||
@echo "[M] $@"
|
||||
|
||||
%.o:%.cc
|
||||
@$(COMPILE.cxx) $< -o $@
|
||||
@echo "[M] $@"
|
||||
|
||||
%.o:%.cpp
|
||||
@$(COMPILE.cxx) $< -o $@
|
||||
@echo "[M] $@"
|
||||
|
||||
%.o:%.CPP
|
||||
$(COMPILE.cxx) $< -o $@
|
||||
|
||||
%.o:%.c++
|
||||
$(COMPILE.cxx) $< -o $@
|
||||
|
||||
%.o:%.cp
|
||||
$(COMPILE.cxx) $< -o $@
|
||||
|
||||
%.o:%.cxx
|
||||
@$(COMPILE.cxx) $< -o $@
|
||||
@echo "[M] $@"
|
||||
|
||||
# Rules for generating the tags.
|
||||
#-------------------------------------
|
||||
tags: $(HEADERS) $(SOURCES)
|
||||
$(ETAGS) $(ETAGSFLAGS) $(HEADERS) $(SOURCES)
|
||||
|
||||
ctags: $(HEADERS) $(SOURCES)
|
||||
$(CTAGS) $(CTAGSFLAGS) $(HEADERS) $(SOURCES)
|
||||
|
||||
# Rules for generating the executable.
|
||||
#-------------------------------------
|
||||
$(PROGRAM):$(OBJS)
|
||||
ifeq ($(SRC_CXX),)
|
||||
@$(LINK.c) $(OBJS) $(MY_LIBS) -o $@
|
||||
@echo "[L] $@"
|
||||
@$(STRIP) $(PROGRAM)
|
||||
@echo "[S] $(PROGRAM)"
|
||||
@$(RM) $(DEPS)
|
||||
@echo "*** version:$(VER)-$(PLAT): Build $@ Finished ***"
|
||||
else
|
||||
@$(LINK.cxx) $(OBJS) $(MY_LIBS) -o $@
|
||||
@echo "[L] $@"
|
||||
@$(STRIP) $(PROGRAM)
|
||||
@echo "[S] $(PROGRAM)"
|
||||
@$(RM) $(DEPS)
|
||||
@echo "*** version:$(VER)-$(PLAT): Build $@ Finished ***"
|
||||
endif
|
||||
|
||||
ifndef NODEP
|
||||
ifneq ($(DEPS),)
|
||||
sinclude $(DEPS)
|
||||
endif
|
||||
endif
|
||||
|
||||
clean:
|
||||
$(RM) $(OBJS) $(PROGRAM) $(DEPS)
|
||||
|
||||
distclean: clean
|
||||
$(RM) $(DEPS) TAGS
|
||||
|
||||
objclean:
|
||||
$(RM) $(OBJ) $(DEPS)
|
||||
|
||||
# Show help.
|
||||
help:
|
||||
@echo 'Generic Makefile for C/C++ Programs version'
|
||||
@echo
|
||||
@echo 'Usage: make [TARGET]'
|
||||
@echo 'TARGETS:'
|
||||
@echo ' all (=make) compile and link.'
|
||||
@echo ' NODEP=yes make without generating dependencies.'
|
||||
@echo ' objs compile only (no linking).'
|
||||
@echo ' tags create tags for Emacs editor.'
|
||||
@echo ' ctags create ctags for VI editor.'
|
||||
@echo ' clean clean objects and the executable file.'
|
||||
@echo ' distclean clean objects, the executable and dependencies.'
|
||||
@echo ' show show variables (for debug use only).'
|
||||
@echo ' help print this message.'
|
||||
@echo
|
||||
@$(RM) $(DEPS)
|
||||
|
||||
# Show variables (for debug use only.)
|
||||
show:
|
||||
@echo 'PROGRAM :' $(PROGRAM)
|
||||
@echo 'PLAT :' $(PLAT)
|
||||
@echo 'TYPE :' $(TYPE)
|
||||
@echo 'SRCDIRS :' $(SRCDIRS)
|
||||
@echo 'HEADERS :' $(HEADERS)
|
||||
@echo 'SOURCES :' $(SOURCES)
|
||||
@echo 'SRC_CXX :' $(SRC_CXX)
|
||||
@echo 'OBJS :' $(OBJS)
|
||||
@echo 'DEPS :' $(DEPS)
|
||||
@echo 'DEPEND :' $(DEPEND)
|
||||
@echo 'COMPILE.c :' $(COMPILE.c)
|
||||
@echo 'COMPILE.cxx :' $(COMPILE.cxx)
|
||||
@echo 'link.c :' $(LINK.c)
|
||||
@echo 'link.cxx :' $(LINK.cxx)
|
||||
|
||||
|
||||
############################# End of the Makefile ################################
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,98 @@
|
||||
#define LOG_TAG "iec61850"
|
||||
#include "elog.h"
|
||||
#include "common.h"
|
||||
#include <stdlib.h>
|
||||
#include "thread.h"
|
||||
#include <pthread.h>
|
||||
#include "msq.h"
|
||||
#include "scl_shm.h"
|
||||
#include "iec61850_process.h"
|
||||
|
||||
mqd_t iec61850_rx_mq;//
|
||||
SCL_MSG_TYPE recv_iec_msg;
|
||||
static char iec61850_rx_buf[1024];
|
||||
|
||||
|
||||
int iec61850_send_msg(void *msg,int msg_len)
|
||||
{
|
||||
static mqd_t iec61850_rx_slave_mq=(mqd_t)-1;
|
||||
if(iec61850_rx_slave_mq==-1)
|
||||
{
|
||||
if((iec61850_rx_slave_mq= open_mq(IEC61850_RX_MQ))==((mqd_t)-1))
|
||||
return -1;
|
||||
}
|
||||
if(mq_send(iec61850_rx_slave_mq,(const char *)msg,msg_len,IEC61850_RX_MQ_PRIO)==-1)
|
||||
return -2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int send_ysp_msg(void *svbr_pri,uint32_t len)
|
||||
{
|
||||
static unsigned char sjzd_msg_buf[512];
|
||||
unsigned int cmd;
|
||||
cmd=CMD_SEND_PRI_DATA;
|
||||
memcpy(sjzd_msg_buf,&cmd,sizeof(cmd));
|
||||
memcpy(&sjzd_msg_buf[4],(const void *)svbr_pri,len);
|
||||
return iec61850_send_msg(sjzd_msg_buf,len+4);
|
||||
}
|
||||
|
||||
|
||||
void *iec61850_rx_routine(void *arg)
|
||||
{
|
||||
int i;
|
||||
time_t now;
|
||||
LN_SVBR_TYPE ln_svbr;
|
||||
|
||||
start_scl_mem();
|
||||
if((iec61850_rx_mq=create_mq(IEC61850_RX_MQ,IEC61850_RX_MAX_MESSAGE,IEC61850_RX_MESSAGE_SIZE))<0)
|
||||
{
|
||||
log_e("create iec61850 rx message queue failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
while(1)
|
||||
{
|
||||
if(recv_mq_wait(iec61850_rx_mq,(void *)iec61850_rx_buf,sizeof(iec61850_rx_buf),1000000)>0)
|
||||
{
|
||||
memcpy(&recv_iec_msg,iec61850_rx_buf,sizeof(recv_iec_msg));
|
||||
switch(recv_iec_msg.cmd)
|
||||
{
|
||||
case CMD_SEND_PRI_DATA:
|
||||
log_d("receive CMD_SEND_PRI_DATA\n");
|
||||
now=time(NULL);
|
||||
//lock_input_data();
|
||||
//unlock_input_data();
|
||||
lock_scl_mem();
|
||||
put_mv_data(0,0,(USR_MV *)&ln_svbr,sizeof(ln_svbr)/sizeof(USR_MV));
|
||||
unlock_scl_mem();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
now=time(NULL);
|
||||
//lock_input_data();
|
||||
//unlock_input_data();
|
||||
lock_scl_mem();
|
||||
put_mv_data(0,0,(USR_MV *)&ln_svbr,sizeof(ln_svbr)/sizeof(USR_MV));
|
||||
unlock_scl_mem();
|
||||
}
|
||||
}
|
||||
stop_scl_mem();
|
||||
}
|
||||
|
||||
|
||||
int iec61850_rx_init(void)
|
||||
{
|
||||
pthread_t iec61850_rx_thread;
|
||||
if((iec61850_rx_thread=task_create(iec61850_rx_routine,NULL,0,0))==-1)
|
||||
{
|
||||
log_e("create iec61850_rx_routine failed\n");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,171 @@
|
||||
#define LOG_TAG "main"
|
||||
#include "main.h"
|
||||
#include "elog.h"
|
||||
#include "modbus_rtu_slave.h"
|
||||
#include "sjzd.h"
|
||||
#include <time.h>
|
||||
#include "iec61850_process.h"
|
||||
|
||||
#define APP_VERSION "SV01.002"
|
||||
#define START_SMP_HOUR 8 //8点开始采样
|
||||
#define SMP_INV 60 //60分钟采样一次
|
||||
|
||||
#define SJZD_PORT "/dev/ttySZ3"
|
||||
#define SJZD_BAUD "38400"
|
||||
#define SJZD_PARITY "no"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t has_new_data;
|
||||
uint32_t new_data_len;
|
||||
uint32_t data_timestamp;
|
||||
uint32_t rsv;
|
||||
} SLAVE_REG_TYPE;
|
||||
|
||||
|
||||
static int doit=0;
|
||||
|
||||
void ctrlCfun(int i)
|
||||
{
|
||||
doit = 1;
|
||||
}
|
||||
|
||||
int log_init(void)
|
||||
{
|
||||
/* close printf buffer */
|
||||
setbuf(stdout,NULL);
|
||||
/* initialize EasyLogger */
|
||||
elog_init();
|
||||
/* set EasyLogger log format */
|
||||
elog_set_fmt(ELOG_LVL_ASSERT, ELOG_FMT_ALL);//设置assert级别的输出内容格式
|
||||
elog_set_fmt(ELOG_LVL_ERROR, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME);//错误日志输出消息级别,标签,时间
|
||||
elog_set_fmt(ELOG_LVL_WARN, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME);//警告日志输出格式设置
|
||||
elog_set_fmt(ELOG_LVL_INFO, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME);
|
||||
elog_set_fmt(ELOG_LVL_DEBUG, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME);
|
||||
elog_set_fmt(ELOG_LVL_VERBOSE, ELOG_FMT_ALL & ~ELOG_FMT_FUNC);
|
||||
#ifdef ELOG_COLOR_ENABLE
|
||||
elog_set_text_color_enabled(true);
|
||||
#endif
|
||||
/* start EasyLogger */
|
||||
elog_start();
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *make_file_name(uint32_t sn,uint8_t addr)
|
||||
{
|
||||
static char data_file_name[64];
|
||||
struct tm *p;
|
||||
memset(data_file_name,0,sizeof(data_file_name));
|
||||
p=localtime((time_t *)&sn);
|
||||
sprintf(data_file_name,"%04d%02d%02d_%02d%02d%02d_%d",p->tm_year+1900,p->tm_mon+1,p->tm_mday,p->tm_hour,p->tm_min,p->tm_sec,addr);
|
||||
return data_file_name;
|
||||
}
|
||||
|
||||
//1.串口轮询线程,
|
||||
//2.通讯协议AA+55+addr(2byte)+data_len(2bytes)+data(n)+crc_val+##
|
||||
int main(int argc,char **args)
|
||||
{
|
||||
int32_t ret;
|
||||
SLAVE_REG_TYPE slave_regs[3];
|
||||
uint32_t tmp_reg;
|
||||
uint8_t rlt,slave_addr;
|
||||
int32_t i;
|
||||
time_t now;
|
||||
struct tm *p;
|
||||
uint32_t last_smp_time=0;
|
||||
char *curr_file;
|
||||
|
||||
signal(SIGINT,ctrlCfun);
|
||||
|
||||
log_init();
|
||||
|
||||
elog_raw("Application Version:%s\r\n",APP_VERSION);
|
||||
|
||||
//if(read_dev_cfg(&dev_cfg)!=0)
|
||||
//{
|
||||
// log_e("load device config failed");
|
||||
//}
|
||||
|
||||
if(sjzd_master_init(SJZD_PORT,SJZD_BAUD,SJZD_PARITY)!=0)
|
||||
{
|
||||
log_e("sjzd master init failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
now=time(NULL);
|
||||
p=localtime((time_t *)&now);
|
||||
if(p->tm_hour<START_SMP_HOUR)
|
||||
{
|
||||
last_smp_time=now-(now%86400)+START_SMP_HOUR*3600-SMP_INV*60;
|
||||
}
|
||||
else
|
||||
{
|
||||
last_smp_time=now-(now%86400)+(START_SMP_HOUR*3600)+(((now%86400)-START_SMP_HOUR*3600)/(SMP_INV*60))*(SMP_INV*60);
|
||||
}
|
||||
|
||||
modbus_rtu_slave_init();
|
||||
iec61850_rx_init();
|
||||
while(!doit)
|
||||
{
|
||||
usleep(500*1000);
|
||||
now=time(NULL);
|
||||
p=localtime((time_t *)&now);
|
||||
|
||||
for(i=0;i<3;i++)
|
||||
{
|
||||
//读寄存器
|
||||
slave_addr=i+1;
|
||||
ret=sjzd_reg_rd(slave_addr,0,(uint8_t *)&slave_regs[i],sizeof(SLAVE_REG_TYPE));
|
||||
if(FRM_ERR_NONE==ret)
|
||||
{
|
||||
if(slave_regs[i].has_new_data)//判断是否有新数据
|
||||
{
|
||||
//读数据文件
|
||||
curr_file=make_file_name(now,slave_addr);
|
||||
if(sjzd_file_rd(slave_addr,"dummy_file",curr_file)>0)
|
||||
{
|
||||
log_d("read data from slave %d ok",slave_addr);
|
||||
//分析数据文件curr_file
|
||||
}
|
||||
else
|
||||
{
|
||||
log_e("read data from slave %d failed",slave_addr);
|
||||
}
|
||||
|
||||
//清数据标志
|
||||
tmp_reg=0;
|
||||
if(sjzd_reg_wr(slave_addr,0,(uint8_t *)&tmp_reg,sizeof(tmp_reg),&rlt)!=FRM_ERR_NONE)
|
||||
{
|
||||
log_e("clear slave %d data failed",slave_addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//判断是否需要启动采样
|
||||
if(p->tm_hour>=START_SMP_HOUR)
|
||||
{
|
||||
if(now>=(last_smp_time+SMP_INV*60))
|
||||
{
|
||||
for(i=0;i<3;i++)
|
||||
{
|
||||
slave_addr=i+1;
|
||||
//发送启动采样命令
|
||||
tmp_reg=1;
|
||||
if(sjzd_reg_wr(slave_addr,16,(uint8_t *)&tmp_reg,1,&rlt)!=FRM_ERR_NONE)
|
||||
{
|
||||
if(sjzd_reg_wr(slave_addr,16,(uint8_t *)&tmp_reg,1,&rlt)!=FRM_ERR_NONE)
|
||||
log_e("clear slave %d data failed",slave_addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
log_d("start slave %d sample succeed",slave_addr);
|
||||
}
|
||||
}
|
||||
last_smp_time=now;
|
||||
}
|
||||
}
|
||||
|
||||
}//end while(!doit)
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
#include "msq.h"
|
||||
#include <sys/time.h>
|
||||
/*
|
||||
#define S_IRWXU 00700
|
||||
#define S_IRUSR 00400
|
||||
#define S_IWUSR 00200
|
||||
#define S_IXUSR 00100
|
||||
|
||||
#define S_IRWXG 00070
|
||||
#define S_IRGRP 00040
|
||||
#define S_IWGRP 00020
|
||||
#define S_IXGRP 00010
|
||||
|
||||
#define S_IRWXO 00007
|
||||
#define S_IROTH 00004
|
||||
#define S_IWOTH 00002
|
||||
#define S_IXOTH 00001
|
||||
#define MODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
|
||||
*/
|
||||
|
||||
#define MODE S_IRWXU|S_IRWXG|S_IRWXO
|
||||
mqd_t create_mq(const char *mq_name,long int mq_maxmsg,long int mq_msgsize)
|
||||
{
|
||||
mqd_t my_mq=(mqd_t)(-1);
|
||||
struct mq_attr my_attr;
|
||||
|
||||
my_attr.mq_flags=0;
|
||||
my_attr.mq_maxmsg=mq_maxmsg;
|
||||
my_attr.mq_msgsize=mq_msgsize;
|
||||
my_mq=mq_open(mq_name,O_CREAT|O_RDONLY/*|O_NONBLOCK*/,MODE,&my_attr);
|
||||
return my_mq;
|
||||
}
|
||||
|
||||
|
||||
mqd_t open_mq(const char *mq_name)
|
||||
{
|
||||
return mq_open(mq_name,O_WRONLY|O_NONBLOCK,0,NULL);
|
||||
}
|
||||
|
||||
|
||||
//timeouts is in us
|
||||
ssize_t recv_mq_wait(mqd_t mq,void *msg,int size,int timeouts)
|
||||
{
|
||||
struct timespec timeout;
|
||||
struct timeval now;
|
||||
ssize_t length;
|
||||
|
||||
gettimeofday(&now,NULL);
|
||||
now.tv_usec+=timeouts;
|
||||
if(now.tv_usec>=1000000)
|
||||
{
|
||||
now.tv_sec+=(now.tv_usec/1000000);
|
||||
now.tv_usec=now.tv_usec%1000000;
|
||||
}
|
||||
timeout.tv_sec=now.tv_sec;
|
||||
timeout.tv_nsec= now.tv_usec*1000;
|
||||
length=mq_timedreceive(mq,(char*)msg,size,NULL,&timeout);
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,91 @@
|
||||
#define LOG_TAG "sjzd_serial"
|
||||
#include "sjzd_serial.h"
|
||||
#include "elog.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* data */
|
||||
char *virtual_serial;
|
||||
char *system_serial;
|
||||
}SERIAL_MAP_TYPE;
|
||||
|
||||
|
||||
SERIAL_MAP_TYPE serial_map_tbl[]={
|
||||
{"RS485_1","/dev/ttySZ3"},
|
||||
{"RS485_2","/dev/ttySZ4"},
|
||||
{"RS485_3","/dev/ttySZ5"},
|
||||
{"RS485_4","/dev/ttySZ6"},
|
||||
{"RS232_1","/dev/ttySZ5"},
|
||||
{"RS232_2","/dev/ttySZ6"},
|
||||
};
|
||||
|
||||
static int sjzd_serial_fd = -1;//串口句柄
|
||||
|
||||
static char *sjzd_get_port_by_name(char *vname)
|
||||
{
|
||||
uint32_t i;
|
||||
for(i=0;i<(sizeof(serial_map_tbl)/sizeof(SERIAL_MAP_TYPE));i++)
|
||||
{
|
||||
//printf("tbl[%d]:%s,%s\n",i,serial_map_tbl[i].virtual_serial,vname);
|
||||
if(strcmp(serial_map_tbl[i].virtual_serial,vname)==0)
|
||||
{
|
||||
return serial_map_tbl[i].system_serial;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int32_t sjzd_serial_init(char *port,int baud,char databit,char parity)
|
||||
{
|
||||
char *dev_name;
|
||||
if(port==NULL)
|
||||
{
|
||||
log_e("port is null in sjzd_serial_init");
|
||||
return -1;
|
||||
}
|
||||
if((dev_name=sjzd_get_port_by_name(port))==NULL)
|
||||
{
|
||||
log_e("get %s failed",port);
|
||||
return -2;
|
||||
}
|
||||
if((sjzd_serial_fd=SerialOpen(dev_name,baud,databit,1,parity))>=0)//0:无校验 1:奇校验 2:偶校验
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
log_e("open %s failed",dev_name);
|
||||
return -3;
|
||||
}
|
||||
|
||||
int32_t sjzd_serial_close(void)
|
||||
{
|
||||
if(sjzd_serial_fd!=-1)
|
||||
{
|
||||
close(sjzd_serial_fd);
|
||||
sjzd_serial_fd=-1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t sjzd_serial_read(uint8_t *pucBuffer,uint16_t usNBytes,uint16_t *usNBytesRead)
|
||||
{
|
||||
int rx_len;
|
||||
rx_len=SerialReadEx(sjzd_serial_fd,pucBuffer,usNBytes,MODBUS_TIMEOUT);
|
||||
if(usNBytesRead!=NULL)
|
||||
{
|
||||
if(rx_len>0)
|
||||
{
|
||||
*usNBytesRead=rx_len;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* code */
|
||||
*usNBytesRead=0;
|
||||
}
|
||||
}
|
||||
return rx_len;
|
||||
}
|
||||
|
||||
int32_t sjzd_serial_write(uint8_t *pucBuffer,uint16_t usNBytes)
|
||||
{
|
||||
return SerialWrite(sjzd_serial_fd,pucBuffer,usNBytes);
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* thread.c
|
||||
*
|
||||
* Created on: Mar 9, 2012
|
||||
* Author: tsx
|
||||
*/
|
||||
#define LOG_TAG "thread"
|
||||
#include "thread.h"
|
||||
#include "elog.h"
|
||||
|
||||
pthread_t task_create(void *(*start_routine)(void *),void *arg,int prio,int stacksize)
|
||||
{
|
||||
struct sched_param sch;
|
||||
pthread_attr_t attr;
|
||||
pthread_t pt;
|
||||
int ret;
|
||||
|
||||
if(prio!=0&&stacksize!=0)
|
||||
{
|
||||
pthread_attr_init(&attr);
|
||||
//get attr
|
||||
pthread_attr_getschedparam(&attr,&sch);
|
||||
//set prio
|
||||
sch.sched_priority=prio;
|
||||
pthread_attr_setschedparam(&attr,&sch);
|
||||
//set stack size
|
||||
pthread_attr_setstacksize(&attr,stacksize);
|
||||
//create thread
|
||||
ret=pthread_create(&pt,&attr,start_routine,arg);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret=pthread_create(&pt,NULL,start_routine,arg);
|
||||
}
|
||||
|
||||
if(ret!=0)
|
||||
{
|
||||
log_e("create thread failed");
|
||||
return -1;
|
||||
}
|
||||
return pt;
|
||||
}
|
Loading…
Reference in New Issue