/*****************************************************************************
* file lib/process/ca_land.c
* author YuLiang
* version 1.0.0
* date 20-Dec-2023
* brief This file provides all the LandPower protocol related operation functions.
******************************************************************************
* Attention
*
*
© COPYRIGHT(c) 2023 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
#ifdef CFG_DEV_TYPE_LAND_CA
/* 标准C库头文件. */
#include
#include
#include
#include
#include
#include
/* 用户代码头文件. */
#include "cmd.h"
#include "process.h"
#include "ca_land.h"
#include "ca_collect.h"
/* Private define ------------------------------------------------------------*/
#define CA_LAND_BUF_SIZE 1512
#define CA_LAND_CMD_BUF_LEN 3024
#define CA_LAND_SHIQUCHA 28800
#define CA_LAND_CMD_REPLY_RD 0xC081
#define CA_LAND_CMD_REQ_ID 0xC401
#define CA_LAND_START_FLAG 0x5555AAAA
#define CA_LAND_END_FLAG 0x5AA55AA5
#define CA_LAND_HEAD_LEN (sizeof(ca_land_head_t) + 8) //包头加包尾长度
/* Private macro -------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* BEGIN: 以下结构体为私有协议数据 */
#pragma pack(1)
typedef struct{
uint32_t StartFlag1; //设备ID 0x40110304=ID=40110304
uint8_t FarmeType; //帧类型: 0x00 定时发送
uint32_t RunSecCnt; //系统运行时间 0x01020304=16909060秒
uint16_t Local_Vbat; //本机电池电压 0x1965= 6505/1000=6.501V
int16_t RoomIn_Temp; //本机温度 0x0C02=(3074/10)-273.1=34.3摄氏度
float RMS_Ia; //CH1:A相接地电流
float RMS_Ib; //CH2:B相接地电流
float RMS_Ic; //CH3:C相接地电流
float RMS_In; //CH4: [主缆电流]
float RMS_Ground; //CH5: [总接地电流]
float RMS_rIa; //CH6:A相运行电流
float RMS_rIb; //CH7:B相运行电流
float RMS_rIc; //CH8:C相运行电流
int16_t RoomOut_Temp; //环境温度 0x0C02=(3074/10)-273.1=34.3摄氏度
uint16_t I16A_Gx; //A相接头振动X轴 0x6655=(26197-16000=10197mg)
uint16_t I16A_Gy; //A相接头振动Y轴 0x6655=(26197-16000=10197mg)
uint16_t I16A_Gz; //A相接头振动Z轴 0x6655=(26197-16000=10197mg)
uint16_t I16A_Temp1; //A相电缆接头温度 0x0C02=(3074/10)-273.1=34.3摄氏度
uint16_t I16A_Temp2; //A相电缆表面温度 同上
uint16_t I16B_Gx; //B相接头振动X轴 0x6655=(26197-16000=10197mg)
uint16_t I16B_Gy; //B相接头振动Y轴 0x6655=(26197-16000=10197mg)
uint16_t I16B_Gz; //B相接头振动Z轴 0x6655=(26197-16000=10197mg)
uint16_t I16B_Temp1; //B相接头温度 0x0C02=(3074/10)-273.1=34.3摄氏度
uint16_t I16B_Temp2; //B相电缆表面温度 同上
uint16_t I16C_Gx; //C相接头振动X轴 0x6655=(26197-16000=10197mg)
uint16_t I16C_Gy; //C相接头振动Y轴 0x6655=(26197-16000=10197mg)
uint16_t I16C_Gz; //C相接头振动Z轴 0x6655=(26197-16000=10197mg)
uint16_t I16C_Temp1; //C相接头温度 0x0C02=(3074/10)-273.1=34.3摄氏度
uint16_t I16C_Temp2; //C相电缆表面温度 同上
uint8_t Status_AG; //A相姿态告警 0x01 告警 0x00正常 复归 故障
uint8_t Status_BG; //B相姿态告警 0x01 故障 0x00正常
uint8_t Status_CG; //C相姿态告警 0x01故障 0x00正常
uint8_t Status_A_OT; //A相温度超限告警 0x01故障 0x00正常
uint8_t Status_B_OT; //B相温度超限告警 0x01故障 0x00正常
uint8_t Status_C_OT; //C相温度超限告警 0x01故障 0x00正常
uint8_t Status_Bat; //电池电路硬件状态0x01故障 0x00正常
uint8_t Error_AT; //A相温度硬件状态 0x01故障 0x00正常
uint8_t Error_BT; //B相温度硬件状态 0x01故障 0x00正常
uint8_t Error_CT; //C相温度硬件状态 0x01故障 0x00正常
uint8_t Error_AG; //A相ADXL硬件状态 0x01故障 0x00正常
uint8_t Error_BG; //B相ADXL硬件状态 0x01故障 0x00正常
uint8_t Error_CG; //C相ADXL硬件状态 0x01故障 0x00正常
uint8_t Error_ROT; //环境温度硬件状态 0x01故障 0x00正常
uint16_t WaterLevel; //水位 0x20=32cm
uint16_t RoomOut_Humidity; //环境湿度 0x0321 = (801/10) = 80.1%
uint8_t Error_Humidity; //环境湿度硬件状态 1:告警,0:正常
uint32_t Gas_O2; //氧气浓度 0x000100013= (0x0013)=19 %VOL
uint32_t Gas_CH4; //甲烷浓度 同上
uint32_t Gas_H2s; //硫化氢浓度 同上
uint32_t Gas_CO; //一氧化碳浓度 同上
float RMS_Va; //A相电压
float RMS_Vb; //B相电压
float RMS_Vc; //C相电压
uint16_t reserve; //保留
uint16_t endFlag; //值:0X0D 0X0A 结束符 “/r/n”
}ca_land_rd_t;//实时数据报文 128 Byte
typedef struct{
uint32_t StartFlag1; //设备ID 0x40110304=ID=40110304
uint8_t FarmeType; //帧类型: 0x01 告警发送
uint32_t RunSecCnt; //系统运行时间 0x01020304=16909060秒
uint8_t WaveNum; //当前的录波物理编号:最新的文件 值:[0-127]
uint8_t RMS_Ig_Err; //总接地电流告 0x01 告警 0x00正常
uint16_t RMS_Ig_Before; //总接地电流变化前 0x0533=1331/10=133.1A
uint16_t RMS_Ig_After; //总接地电流变化后 0x0533=1331/10=133.1A
uint8_t RMS_Ia_Err; //A相电流告警 0x01 告警 0x00正常
uint16_t RMS_Ia_Before; //A相电流变化前 0x0533=1331/10=133.1A
uint16_t RMS_Ia_After; //A相电流变化后 0x0533=1331/10=133.1A
uint8_t Sanke_a_Err; //A相振动告警 0x01 告警 0x00正常
uint16_t Sanke_a_x; //A相X振动值
uint16_t Sanke_a_y; //A相Y振动值
uint16_t Sanke_a_z; //A相Z振动值
uint8_t Temper_a_Err; //A相温度告警 0x01 告警 0x00正常
uint8_t Temper_a_Change; //A相温度变化值 0x02 升高了2度
uint16_t Temper_a_Before; //A相温度前 0x0C02=(3074/10)-273.1=34.3摄氏度
uint16_t Temper_a_After; //A相温度后 0x0C02=(3074/10)-273.1=34.3摄氏度
uint8_t RMS_Ib_Err; //B相电流告警 0x01 告警 0x00正常
uint16_t RMS_Ib_Before; //B相电流变化前 0x0533=1331/10=133.1A
uint16_t RMS_Ib_After; //B相电流变化后 0x0533=1331/10=133.1A
uint8_t Sanke_b_Err; //B相振动告警 0x01 告警 0x00正常
uint16_t Sanke_b_x; //B相X振动值
uint16_t Sanke_b_y; //B相Y振动值
uint16_t Sanke_b_z; //B相Z振动值
uint8_t Temper_b_Err; //B相温度告警 0x01 告警 0x00正常
uint8_t Temper_b_Change; //B相温度变化值 0x02 升高了2度
uint16_t Temper_b_Before; //B相温度前 0x0C02=(3074/10)-273.1=34.3摄氏度
uint16_t Temper_b_After; //B相温度后 0x0C02=(3074/10)-273.1=34.3摄氏度
uint8_t RMS_Ic_Err; //C相电流告警 0x01 告警 0x00正常
uint16_t RMS_Ic_Before; //C相电流变化前 0x0533=1331/10=133.1A
uint16_t RMS_Ic_After; //C相电流变化后 0x0533=1331/10=133.1A
uint8_t Sanke_c_Err; //C相振动告警 0x01 告警 0x00正常
uint16_t Sanke_c_x; //C相X振动值
uint16_t Sanke_c_y; //C相Y振动值
uint16_t Sanke_c_z; //C相Z振动值
uint8_t Temper_c_Err; //C相温度告警 0x01 告警 0x00正常
uint8_t Temper_c_Change; //C相温度变化值 0x02 升高了2度
uint16_t Temper_c_Before; //C相温度前 0x0C02=(3074/10)-273.1=34.3摄氏度
uint16_t Temper_c_After; //C相温度后 0x0C02=(3074/10)-273.1=34.3摄氏度
uint16_t endFlag; //值:0X0D 0X0A 结束符 “/r/n”
}ca_land_war_t;//告警数据 71Byte
typedef struct{
uint32_t StatusA; //24个通道的温度数据的正确性判断 Bit24: 0 开关量正常 1开关量报警
int16_t TempA[24]; //测温带的温度 (I16)/16【原始值】
uint32_t StatusB;
int16_t TempB[24];
uint32_t StatusC;
int16_t TempC[24];
} ca_land_tmp_t;//测温带数据 156 Byte
typedef struct{
uint32_t proVer; //协议版本号 0x00000363
uint32_t utc;
ca_land_rd_t rtd;
uint32_t reslved1; //调试工具 用来存历史数据条数
ca_land_war_t war;
uint8_t reslved2;
ca_land_tmp_t mul;
uint32_t reslved3;
uint32_t powertatus;
uint32_t vbat;
uint32_t vout;
uint32_t batteryStatus;
float Gpslatitude;
float Gpslongitude;
uint8_t PowerFail[8]; //电源故障 485
uint32_t vsc;
uint8_t reslved4[104];
} ca_land_date_t;//512Byte
#pragma pack()
typedef struct{
uint32_t Head; //StartFlag1 0X5555AAAA
uint16_t Len; //报文长度:所有字节总长度
uint16_t Type; //报文类型
uint32_t ID; //从机ID: 【ex. 0x40111234 】
uint32_t LifeCnt; //主机每次加1,从机应答收到的值
uint16_t gNum; //报文分组数目:(1-65535);
uint16_t gNumIndex; //报文分组编号;0 ~ (gNum-1)
} ca_land_head_t;//朗德协议包头
typedef struct{
uint32_t CheckSum;
uint32_t EndFlag1;
} ca_land_tail_t;//朗德协议包尾
/* END: 以上结构体为私有协议数据 */
/* 私有协议全局控制结构 */
typedef struct{
int fd; // TCP server 监听使用的 socket
char buf[CA_LAND_BUF_SIZE]; // 通讯使用收发包 buf
ca_land_state_t state; // 协议状态
} ca_land_ctrl_t;
ca_land_ctrl_t ca_land_ctrl; // 全局控制结构
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Internal functions --------------------------------------------------------*/
/* description: 显示当前状态
param:
return: CMD_XXX */
CMD(ca_land_show_state,
ca_land_show_state_cmd,
"show land",
"Show\n"
"LandPower protocol\n")
{
ca_land_state_show();
return CMD_SUCCESS;
}
/* description: 私有协议 socket 属性配置
param: fd - socket 描述符
return: E_XXX */
int32_t _ca_land_socket_set(int fd)
{
//int keep_alive = 1;
//int keep_idle = 60;
//int keep_interval = 6;
//int keep_count = 10;
int keep_time = 30000;
struct timeval timeout;
#if 0
/* 开启保活, 保活参数表示 60 秒内无交互后, 每隔 6 秒检测一次. 10 次都没得到响应时会断开连接 */
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &keep_alive, sizeof(keep_alive)))
{
DBG(DBG_M_CA_LAND_ERR, "Error setsockopt(SO_KEEPALIVE) failed, return %s!\r\n", safe_strerror(errno));
return E_SYS_CALL;
}
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &keep_idle, sizeof(keep_idle)))
{
DBG(DBG_M_CA_LAND_ERR, "Error setsockopt(TCP_KEEPIDLE) failed, return %s!\r\n", safe_strerror(errno));
return E_SYS_CALL;
}
if (setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, (void *)&keep_interval, sizeof(keep_interval)))
{
DBG(DBG_M_CA_LAND_ERR, "Error setsockopt(TCP_KEEPINTVL) failed, return %s!\r\n", safe_strerror(errno));
return E_SYS_CALL;
}
if (setsockopt(fd, SOL_TCP, TCP_KEEPCNT, (void *)&keep_count, sizeof(keep_count)))
{
DBG(DBG_M_CA_LAND_ERR, "Error setsockopt(TCP_KEEPCNT) failed, return %s!\r\n", safe_strerror(errno));
return E_SYS_CALL;
}
#endif
/* 发送超时配置 */
if (setsockopt(fd, SOL_TCP, TCP_USER_TIMEOUT, (void *)&keep_time, sizeof(keep_time)))
{
DBG(DBG_M_CA_LAND_ERR, "Error setsockopt(TCP_USER_TIMEOUT) failed, return %s!\r\n", safe_strerror(errno));
return E_SYS_CALL;
}
/* 发送超时 */
timeout.tv_sec = 30;
timeout.tv_usec = 0;
if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)))
{
DBG(DBG_M_CA_LAND_ERR, "Error setsockopt(SO_SNDTIMEO) failed, return %s!\r\n", safe_strerror(errno));
return E_SYS_CALL;
}
return E_NONE;
}
/* description: 初始化报文头
param: cmd - 命令字
len - 数据长度
return: */
void _ca_land_head_init(uint16_t cmd, int32_t len)
{
char *pkt = ca_land_ctrl.buf;
ca_land_head_t *head = (ca_land_head_t*)pkt;
memset(pkt, 0, CA_LAND_BUF_SIZE);
head->Head = CA_LAND_START_FLAG;
head->Len = CA_LAND_HEAD_LEN + len;
head->Type = cmd;
head->ID = device_info.dev_id;
head->LifeCnt = 1;
head->gNum = 1;
head->gNumIndex = 0;
}
/* description: 报文校验和计算
param: data_len - 报文总长度
return: */
void _ca_land_cheak_sum(int32_t data_len)
{
char *pkt = ca_land_ctrl.buf;
uint32_t *temp = (uint32_t*)(pkt + 4);
ca_land_tail_t *tail = (ca_land_tail_t*)(pkt + data_len - 8);
int32_t i = 0;
int32_t len = (data_len - 12) >> 2; // 起始位和报文尾不参与计算
uint32_t cheakSum = 0;
for(i = 0; i < len; i++ )
{
cheakSum += *temp;
temp++;
}
tail->CheckSum = cheakSum;
tail->EndFlag1 = CA_LAND_END_FLAG;
}
int32_t _ca_land_heart_send(void)
{
char *pkt = ca_land_ctrl.buf;
ca_land_head_t *head = (ca_land_head_t*)pkt;
int fd = ca_land_ctrl.fd;
/* 初始化报文头 */
_ca_land_head_init(CA_LAND_CMD_REQ_ID, 36);
_ca_land_cheak_sum(head->Len);
/* 发送数据 */
if (send(fd, pkt, head->Len, 0) < 0)
{
DBG(DBG_M_CA_LAND_ERR, "LAND send ERR!\r\n");
return E_SYS_CALL;
}
/* 调试打印 */
DBG(DBG_M_CA_LAND, "LAND send(%d): %d %d\r\n", head->Len, time(NULL));
if (dbg_stat_get(DBG_M_CA_LAND))
{
buf_print(pkt, 32);
}
return E_NONE;
}
/* description: 数据报文组装
param: data - 环流数据段
return: */
void _ca_land_date(ca_land_rd_t *data)
{
ca_coll_dev_data_t *dev_data = ca_coll_cable_data_get();
data->StartFlag1 = device_info.dev_id;
data->endFlag = 0x0A0D;
data->Local_Vbat = dev_data->vbat;
data->RoomIn_Temp = dev_data->temperature +2731;
data->RunSecCnt = start_time;
data->RMS_Ia = dev_data->elec[0] / 1000.0;
data->RMS_Ib = dev_data->elec[1] / 1000.0;
data->RMS_Ic = dev_data->elec[2] / 1000.0;
data->RMS_rIa = dev_data->elec[3] / 1000.0;
data->RMS_Ground = dev_data->elec[4] / 1000.0;
}
/* description: 数据报文发送
param: data - 环流数据段
return: E_XXX */
int32_t _ca_land_real_data_send(void)
{
char *pkt = ca_land_ctrl.buf;
ca_land_head_t *head = (ca_land_head_t*)pkt;
ca_land_date_t *rd = (ca_land_date_t*)(pkt + sizeof(ca_land_head_t));
ca_coll_dev_data_t *dev_data = ca_coll_cable_data_get();
time_t now = time(NULL);
int fd = ca_land_ctrl.fd;
/* 初始化报文头 */
_ca_land_head_init(CA_LAND_CMD_REPLY_RD, sizeof(ca_land_date_t));
/* 填充数据 */
rd->proVer = 0x00000601;
rd->utc = now - CA_LAND_SHIQUCHA;
rd->powertatus = 0;
rd->batteryStatus = 0;
rd->vbat = dev_data->vbat;
rd->vsc = dev_data->vsc;
rd->vout = dev_data->vin;
rd->Gpslatitude = 0;
rd->Gpslongitude = 0;
rd->reslved1 = 0;
_ca_land_date(&rd->rtd);
_ca_land_cheak_sum(head->Len);
/* 发送数据 */
if (send(fd, pkt, head->Len, 0) < 0)
{
DBG(DBG_M_CA_LAND_ERR, "LAND send ERR!\r\n");
return E_SYS_CALL;
}
/* 调试打印 */
DBG(DBG_M_CA_LAND, "LAND send(%d): %d %d\r\n", head->Len, now);
if (dbg_stat_get(DBG_M_CA_LAND))
{
buf_print(pkt, 32);
}
return E_NONE;
}
/* description: 私有协议数据发送线程
param:
return: */
void *_ca_land_handle_send(void *arg)
{
static uint8_t cnt = 0;
ca_coll_cfg_t *cfg = ca_coll_cfg_get();
ca_coll_state_t *state = ca_coll_cable_state_get();
struct sockaddr_in server;
int fd = ca_land_ctrl.fd;
int8_t err_cnt = 0;
while (!is_system_init)
{
sleep(1);
}
/* 绑定端口 */
bzero(&server, sizeof(server));
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr(cfg->land_ip);
server.sin_port = htons(cfg->land_port);
printf("land_ip:%s land_port:%d\n", cfg->land_ip, cfg->land_port);
while (1)
{
sleep(30);
/* 创建 socket */
fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0)
{
log_err(LOG_CA_LAND, "ERROR at socket create return %s!", safe_strerror(errno));
continue;
}
if (connect(fd, (struct sockaddr*)&server, sizeof(server)) < 0)
{
DBG(DBG_M_CA_LAND_ERR, "ERROR at socket connect return %s!\r\n", safe_strerror(errno));
close(fd);
/* 如果 4G 连接, 服务器未连接, 假 4G 连接需要重启设备 */
if (cfg->is_4G && state->is_4g_connect)
{
err_cnt++;
if (err_cnt >= 10)
{
// 如果是私网卡会连不上
//reboot_system(LOG_CA_LAND, BOOT_CONNECT_ERR);
}
}
else
{
err_cnt = 0;
}
continue;
}
_ca_land_socket_set(fd);
ca_land_ctrl.fd = fd;
/* 定时发送数据 */
cnt = 0;
while(1)
{
if (ca_land_ctrl.state.is_send_data)
{
ca_land_ctrl.state.is_send_data = FALSE;
if (_ca_land_real_data_send() != E_NONE)
{
ca_land_ctrl.state.is_connect = FALSE;
DBG(DBG_M_CA_LAND_ERR, "ERROR at server disconnect!\r\n");
close(fd);
break;
}
ca_land_ctrl.state.is_connect = TRUE;
}
else if(cnt >= 30)
{
cnt = 0;
if (_ca_land_heart_send() != E_NONE)
{
ca_land_ctrl.state.is_connect = FALSE;
DBG(DBG_M_CA_LAND_ERR, "ERROR at server disconnect!\r\n");
close(fd);
break;
}
ca_land_ctrl.state.is_connect = TRUE;
}
sleep(1);
cnt++;
}
}
return NULL;
}
/* Interface functions -------------------------------------------------------*/
/* description: 私有协预初始化
param:
return: E_XXX */
int32_t ca_land_init(void)
{
cmd_install_element(COMMON_NODE, &ca_land_show_state_cmd);
return E_NONE;
}
/* description: 朗德协议初始化函数.
param: 111.47.21.141
return: */
int32_t ca_land_init_after(void)
{
ca_coll_cfg_t *cfg = ca_coll_cfg_get();
struct sched_param param;
pthread_attr_t attr;
pthread_t pid;
int32_t rv = 0;
if (!cfg->is_land)
{
return E_NONE;
}
pthread_attr_init(&attr);
param.sched_priority = 25;
pthread_attr_setschedpolicy(&attr, SCHED_RR);
pthread_attr_setschedparam(&attr, ¶m);
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
rv = pthread_create(&pid, &attr, _ca_land_handle_send, NULL);
if (rv != 0)
{
log_err(LOG_CA_LAND, "Can't create debug pthread %d!", rv);
return E_SYS_CALL;
}
else
{
thread_m_add("CA_LAND", pid);
}
pthread_attr_destroy(&attr);
return E_NONE;
}
/* description: 私有协议状态结构体获取
param:
return: ca_land_state_t - 私有协议状态结构体指针 */
ca_land_state_t* ca_land_state_get(void)
{
return &ca_land_ctrl.state;
}
/* description: 私有协议状态显示
param:
return: */
void ca_land_state_show(void)
{
ca_land_state_t *state = &ca_land_ctrl.state;
printh("Connect: %s\r\n\n", state->is_connect ? "yes" : "no");
}
#endif
/************************ (C) COPYRIGHT LandPower ***** END OF FILE ****************/