/******************************************************************************
* file lib/management/common.c
* author YuLiang
* version 1.0.0
* date 14-Sep-2021
* brief This file provides all the common operation functions.
*
******************************************************************************
* Attention
*
*
© COPYRIGHT(c) 2021 LandPower
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of LandPower nor the names of its contributors may be used to
* endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
/* 标准C库头文件. */
#include
#include
#include
#include
#include
#include
#include
/* 用户代码头文件. */
#include "vty.h"
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* 时间缓存结构体. */
typedef struct _time_cache
{
time_t last; /* 最后一次时间缓存数据. */
size_t len; /* buf中数据的长度. */
char buf[TIME_STR_LEN]; /* 时间数据转化的字符串. */
} time_cache_t;
/* Private variables ---------------------------------------------------------*/
static struct timeval sd_start, sd_end;
/* Private function prototypes -----------------------------------------------*/
extern void pd_wdg_clr(void);
/* Internal functions --------------------------------------------------------*/
/* 在时间后面根据precision长度,添加更加精确的时间字符串. */
static size_t _time_string_prec_add(char *buf, size_t len, int32_t precision, struct timeval *clock)
{
static const int divisor[] = {0, 100000, 10000, 1000, 100, 10, 1};
char *p = NULL;
/* 最多统计到us */
if (precision > 6)
precision = 6;
p = buf + len + 1 + precision;
*p-- = '\0';
clock->tv_usec /= divisor[precision];
do
{
*p-- = '0' + (clock->tv_usec % 10);
clock->tv_usec /= 10;
}
while(--precision > 0);
*p = '.';
return len + 1 + precision;
}
/* Interface functions -------------------------------------------------------*/
/* description: 将字符串转为小写.
param: str -- 需要转换的字符转
return: 转换后的字符串 */
char *str_to_lower(char *str)
{
uint32_t i = 0;
if (str != NULL)
{
for(i = 0; str[i] != '\0'; i++)
{
str[i] = tolower(str[i]);
}
}
return str;
}
/* description: 去掉字符串中的多余空格.
param: str -- 需要转换操作的字符转
omit_end -- omit_end(TRUE)表示会将字符串尾部的空格全部消除
omit_end(FALSE)表示如果尾部有空格,允许保留1个空格
return: 操作后的字符串 */
char *str_omit_space(char *str, bool omit_end)
{
char *front = str;
char *last = str;
if (NULL == str)
{
return NULL;
}
while(' ' == *front)
front++;
while((*front) != '\0')
{
if (' ' == *front)
{
while((*++front) == ' ');
if ('\0' == *front && omit_end)
;
else
{
*last = ' ';
last++;
}
}
else
{
*last = *front;
front++;
last++;
}
}
*last = '\0';
return str;
}
/* description: 根据传入的精度precision,将时间字符串填到buf.
param: precision -- 精度,几位小数
buf -- 存储转换后字符串的buffer
buflen -- buf的大小
return: 返回字符串长度,如果失败,返回0 */
size_t time_string(int32_t precision, char *buf, size_t buflen)
{
static time_cache_t cache;
struct timeval clock;
/* 获取时间数据clock. */
gettimeofday(&clock, NULL);
/* 更新时间到字符串,cache是静态的,如果两次time_string调用在1秒之内,将沿用上次的cache. */
if (cache.last != clock.tv_sec)
{
struct tm *tm = NULL;
cache.last = clock.tv_sec;
tm = localtime(&cache.last);
cache.len = strftime(cache.buf, sizeof(cache.buf), "%Y/%m/%d %H:%M:%S", tm);
}
if (buflen > cache.len)
{
memcpy(buf, cache.buf, cache.len);
/* 计算秒之后的精度. */
if ((precision > 0) && (buflen > cache.len + 1 + precision))
return _time_string_prec_add(buf, cache.len, precision, &clock);
buf[cache.len] = '\0';
return cache.len;
}
/* buf太小,无法生成字符串. */
if (buflen > 0)
buf[0] = '\0';
return 0;
}
/* description: 获取错误代码字符串.
param: errnum -- 错误代码
return: 获取的字符串 */
const char *safe_strerror(int errnum)
{
const char *s = strerror(errnum);
return (s != NULL) ? s : "Unknown error";
}
/* description: 按16进制打印buf数据.
param: buf -- 数据
len -- 数据长度
return: */
void buf_print(char *buf, int32_t len)
{
int32_t i = 0;
for(i = 0; i < len;)
{
printh("%02x ", (uint8_t)buf[i++]);
if(0 == i % 32)
{
printh("\r\n");
}
}
if(i % 32 != 0)
{
printh("\r\n");
}
return;
}
/* description: 通过 ip 生成 mac 地址.
param: ip_str -- 输入 ip 地址
mac -- 输出 mac 地址
return: E_XXXX */
int32_t mac_generate_from_ip(char *ip_str, uint8_t *mac)
{
struct sockaddr_in server;
uint32_t ip = 0;
uint32_t temp = 0;
if (NULL == ip_str || NULL == mac)
{
return E_BAD_PARAM;
}
/* 将 ip_str 转为数字. */
if (inet_aton(ip_str, &server.sin_addr) < 0)
{
DBG(DBG_M_CLI, "inet_aton ip is error!\r\n");
return E_BAD_PARAM;
}
ip = server.sin_addr.s_addr;
/* 产生 mac. */
srand(time(NULL));
temp = rand();
mac[0] = 0x68;
mac[1] = temp & 0xff;
mac[2] = (temp >> 8) & 0xff;
mac[3] = (temp >> 16) & 0xff;
mac[4] = (temp >> 24) & 0xff;
mac[5] = (ip >> 24) & 0xff;
return E_NONE;
}
/* description: 计算CRC16/MODBUS.
param: data -- 数据
size -- 数据长度
return: 计算的crc值 */
uint16_t crc16(uint8_t *data, uint16_t size)
{
uint16_t crc = 0xFFFF;
uint8_t i = 0;
while(size--)
{
crc = crc ^ *data++;
for(i = 0; i < 8; i++)
{
if ((crc & 0x0001) > 0)
{
crc = crc >> 1;
crc = crc ^ 0xa001;
}
else
crc = crc >> 1;
}
}
return crc;
}
void invert_uint8(unsigned char *dest_buf, unsigned char *src_buf)
{
int i;
unsigned char tmp[4];
tmp[0] = 0;
for (i = 0; i < 8; i++)
{
if (src_buf[0] & (1 << i))
tmp[0] |= 1 << (7 - i);
}
dest_buf[0] = tmp[0];
}
void invert_uint16(unsigned short *dest_buf, unsigned short *src_buf)
{
int i;
unsigned short tmp[4];
tmp[0] = 0;
for (i = 0; i < 16; i++)
{
if (src_buf[0] & (1 << i))
tmp[0] |= 1 << (15 - i);
}
dest_buf[0] = tmp[0];
}
uint16_t crc16_modbus(uint8_t *data, uint16_t size)
{
unsigned short wCRCin = 0xFFFF;
unsigned short wCPoly = 0x8005;
unsigned char wChar = 0;
while (size--)
{
wChar = *(data++);
invert_uint8(&wChar, &wChar);
wCRCin ^= (wChar << 8);
int i = 0;
for (i = 0; i < 8; i++)
{
if (wCRCin & 0x8000)
wCRCin = (wCRCin << 1) ^ wCPoly;
else
wCRCin = wCRCin << 1;
}
}
invert_uint16(&wCRCin, &wCRCin);
return (wCRCin);
}
/* description: 时间统计开始.
param:
return: */
void speed_detection_stat(void)
{
gettimeofday(&sd_start, NULL);
}
/* description: 时间统计结束.
param:
return: */
void speed_detection_end(void)
{
float timeuse;
gettimeofday(&sd_end, NULL);
timeuse = 1000000 * (sd_end.tv_sec - sd_start.tv_sec) + sd_end.tv_usec - sd_start.tv_usec;
timeuse /= 1000000;
printh("Used Time:%f\r\n", timeuse);
}
/* description: 通用打印函数.
param:
return: */
int printh(const char *format, ...)
{
va_list args;
va_start(args, format);
vprintf(format, args);
vty_print(format, args);
va_end(args);
return 0;
}
/* description: 获取int16_t类型的版本号.
param:
return: int16_t类型的版本号 */
uint16_t sofrware_version_get(void)
{
char version_str[16];
char *str = NULL;
char *p = NULL;
uint16_t version = 0;
snprintf(version_str, 16, "%s", version_get());
str = strtok_r(version_str, ".", &p);
while(str != NULL)
{
version = version << 8;
version |= (uint8_t)(atoi(str));
str = strtok_r(NULL, ".", &p);
}
return version;
}
/* description: 根据传入的字符串转换成mac地址.
param:
return: */
int32_t str_to_mac(char *mac_str, OUT uint8_t *mac)
{
char *str = NULL;
char *p = NULL;
uint8_t len = 0;
uint8_t i = 0;
/* 按:分词 */
str = strtok_r(mac_str, ":", &p);
while(str != NULL)
{
/* 检查mac长度 */
if (len >= 6)
{
return E_BAD_PARAM;
}
/* 检查字符串 */
for(i = 0; str[i] && str[i] != '\0'; i++)
{
if (!((str[i] >= '0' && str[i] <= '9')
|| (str[i] >= 'a' && str[i] <= 'f')
|| (str[i] >= 'A' && str[i] <= 'F')))
{
return E_BAD_PARAM;
}
}
/* 检查数据长度 */
if (i != 2)
{
return E_BAD_PARAM;
}
mac[len++] = strtol(str, NULL, 16);
/* 获取下个数据 */
str = strtok_r(NULL, ":", &p);
}
return E_NONE;
}
/* description: 根据传入的字符串转换成设备id.
param:
return: */
int32_t str_to_id(char *id_str, OUT uint32_t *id)
{
char *str = NULL;
char *p = NULL;
uint8_t len = 0;
uint8_t i = 0;
/* 按:分词 */
str = strtok_r(id_str, ".", &p);
while(str != NULL && len < 2)
{
/* 检查id长度 */
if (len >= 2)
{
return E_BAD_PARAM;
}
/* 检查字符串 */
for(i = 0; str[i] && str[i] != '\0'; i++)
{
if (!(str[i] >= '0' && str[i] <= '9'))
{
return E_BAD_PARAM;
}
}
id[len++] = strtol(str, NULL, 10);
/* 获取下个数据 */
str = strtok_r(NULL, ".", &p);
}
return E_NONE;
}
int32_t bitmap_set(uint8_t *buf, int32_t nbit, int32_t buf_len)
{
if ((NULL == buf) || (nbit >= buf_len * 8))
{
return E_BAD_PARAM;
}
buf[nbit / 8] |= 1 << (nbit % 8);
return E_NONE;
}
int32_t bitmap_reset(uint8_t *buf, int32_t nbit, int32_t buf_len)
{
if ((NULL == buf) || (nbit >= buf_len * 8))
{
return E_BAD_PARAM;
}
buf[nbit / 8] &= ~(1 << (nbit % 8));
return E_NONE;
}
int32_t is_bitmap_set(uint8_t *buf, int32_t nbit, int32_t buf_len)
{
if ((NULL == buf) || (nbit >= buf_len * 8))
{
return FALSE;
}
return buf[nbit / 8] & (1 << (nbit % 8));
}
int32_t time_str_to_long(char *date, char *time, uint32_t *t)
{
struct tm stm;
int32_t year, month, day, hour, minute,second;
if (sscanf(date, "%d-%d-%d", &year, &month, &day) != 3)
{
return E_BAD_PARAM;
}
if (sscanf(time, "%d:%d:%d", &hour, &minute, &second) != 3)
{
return E_BAD_PARAM;
}
stm.tm_year = year - 1900;
stm.tm_mon = month - 1;
stm.tm_mday = day;
stm.tm_hour = hour;
stm.tm_min = minute;
stm.tm_sec = second;
stm.tm_isdst = 0;
*t = mktime(&stm);
return E_NONE;
}
uint16_t version_str_to_int(void)
{
uint32_t version_m = 0;
uint32_t version_s = 0;
uint32_t version_hm = 0;
uint32_t version_hs = 0;
uint32_t n = 0;
n = sscanf(version_get(), "%d.%d.%d.%d", &version_hm, &version_hs, &version_m, &version_s);
if (n != 4)
{
return 0xffff;
}
return (version_m << 8 | (version_s & 0xff)) & 0xffff;
}
void time_set(time_t timestamp)
{
struct tm *p =localtime(×tamp);
struct tm tptr = {0};
struct timeval tv = {0};
tptr.tm_year = p->tm_year;
tptr.tm_mon = p->tm_mon;
tptr.tm_mday = p->tm_mday;
tptr.tm_hour = p->tm_hour;
tptr.tm_min = p->tm_min;
tptr.tm_sec = p->tm_sec;
tv.tv_sec = mktime(&tptr);
tv.tv_usec = 0;
settimeofday(&tv, NULL);
}
boot_msg_t g_bootmsg[] =
{
{BOOT_NONE, "Boot none."},
{BOOT_LOCAL_SERVER_IP_CHANGE, "Debug Tool has changed server ip."},
{BOOT_LOCAL_SERVER_PORT_CHANGE, "Debug Tool has changed server port."},
{BOOT_LOCAL_IP_CHANGE, "Debug Tool has changed device ip."},
{BOOT_LOCAL_HOST_NAME_CHANGE, "Debug Tool has changed hostname."},
{BOOT_LOCAL_RESET, "Debug Tool send reset command."},
{BOOT_LOCAL_ARM_UPGRADE, "Debug Tool send ARM upgrade command."},
{BOOT_LOCAL_FPGA_UPGRADE, "Debug Tool send FPGA upgrade command."},
{BOOT_REMOTE_SERVER_IP_CHANGE, "Remote has changed server ip."},
{BOOT_REMOTE_SERVER_PORT_CHANGE, "Remote has changed server port."},
{BOOT_REMOTE_IP_CHANGE, "Remote has changed device ip."},
{BOOT_REMOTE_HOST_NAME_CHANGE, "Remote has changed hostname."},
{BOOT_REMOTE_RESET, "Remote send reset command."},
{BOOT_UPGRADE_ALL, "Upgrade cmu and dau."},
{BOOT_UPGRADE_ARM, "Upgrade cmu only."},
{BOOT_UPGRADE_FPGA, "Upgrade dau only."},
{BOOT_SYSTEM_RESET, "System reboot..."},
{BOOT_DAU_ERR_RESET, "DAU communicate ERROR."},
{BOOT_PPP_NO_FOUND, "ppp0 not found."},
{BOOT_PPP_FOUND_LINK_FAIL, "ppp0 found but link failed."},
{BOOT_MAX, NULL}
};
void reboot_system(int module, BOOT_MSG type)
{
BOOT_MSG i;
char *pmsg = NULL;
for (i = BOOT_NONE; i < BOOT_MAX; i++)
{
if (g_bootmsg[i].type == type)
{
pmsg = g_bootmsg[i].msg;
break;
}
}
if (pmsg)
{
log_out(module, LOG_LVL_WARN, pmsg);
//log_out(module, LOG_LVL_WARN, "Now,start reboot system...");
system("sync");
sleep(3);
system("reboot -f");
}
}
void set_nonblock(int sock)
{
int flags = fcntl(sock, F_GETFL, 0);
fcntl(sock, F_SETFL, flags | O_NONBLOCK);
}
int StrToHex(unsigned char *hex, char *str, int slen)
{
unsigned int len = 0;
unsigned char tmp;
while(slen > 0)
{
len++;
tmp = *str++;
if(tmp>='0' && tmp<='9')
{
*hex = (tmp-'0')<<4;
}
else if(tmp>='a' && tmp<='f')
{
*hex = (tmp-'a'+0x0a)<<4;
}
else if(tmp>='A' && tmp<='F')
{
*hex = (tmp-'A'+0x0a)<<4;
}
else
{
len = 0;
break;
}
slen--;
if(slen == 0)
{
len = 0;
break;
}
tmp = *str++;
if(tmp>='0' && tmp<='9')
{
*hex |= (tmp-'0');
}
else if(tmp>='a' && tmp<='f')
{
*hex |= (tmp-'a'+0x0a);
}
else if(tmp>='A' && tmp<='F')
{
*hex |= (tmp-'A'+0x0a);
}
else
{
len = 0;
break;
}
slen--;
hex++;
}
return len;
/*
char h1, h2;
U8 s1, s2;
int i = 0;
for (i = 0; i < nLen; i++)
{
h1 = pszSrc[2 * i];
h2 = pszSrc[2 * i + 1];
s1 = toupper(h1) - 0x30;
if (s1 > 9)
s1 -= 7;
s2 = toupper(h2) - 0x30;
if (s2 > 9)
s2 -= 7;
pbDest[i] = s1 * 16 + s2;
}
*/
}
unsigned int dev_id_2_hex(char *dev_num)
{
char temp[16];
unsigned int uiId = 0;
unsigned char HexVal[4] = {0};
strncpy(temp,(char*)dev_num, sizeof(temp));
int strLen = strlen(temp);
if (strLen < 8)
{
printh("device id < 8 devicieNum:%s\n", temp);
return 0;
}
StrToHex(HexVal,&temp[strLen-8], 8);//取字符串后8为转换成Int类型
//ctrl->gateway = HexVal[0] << 24 | HexVal[1] << 16 | HexVal[2] << 8 | HexVal[3];
uiId = HexVal[0] << 24 | HexVal[1] << 16 | HexVal[2] << 8 | HexVal[3];
printh("uiId = 0x%x\n", uiId);
return uiId;
}
/************************ (C) COPYRIGHT LandPower ***** END OF FILE ****************/