From 72fea370ff20ecb2494ab985c4431b4bd691e7cd Mon Sep 17 00:00:00 2001
From: guowenxue <guowenxue@gmail.com>
Date: Mon, 17 Nov 2025 15:11:05 +0800
Subject: [PATCH] update lighted program

---
 /dev/null                      |   45 --
 project/lightd/hal/makefile    |   27 +
 project/lightd/makefile        |   26 
 .gitignore                     |    1 
 project/lightd/config.c        |  291 +++++++++++++
 project/lightd/etc/lightd.conf |   70 +++
 project/lightd/hal/gpio.h      |   29 
 project/lightd/config.h        |   76 +++
 project/lightd/hal/tsl2561.h   |   46 -
 project/lightd/lightd.c        |  378 ++++++++++++++++++
 project/lightd/hal/gpio.c      |  112 +---
 project/lightd/hal/tsl2561.c   |  154 ++++---
 12 files changed, 1,004 insertions(+), 251 deletions(-)

diff --git a/.gitignore b/.gitignore
index 005a0ec..e66af8e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -33,4 +33,5 @@
 
 # binary file
 project/gpsd/gpsd
+project/lightd/lightd
 project/thingsboard/thingsboard
diff --git a/project/lightd/config.c b/project/lightd/config.c
new file mode 100644
index 0000000..f9c646c
--- /dev/null
+++ b/project/lightd/config.c
@@ -0,0 +1,291 @@
+/*********************************************************************************
+ *      Copyright:  (C) 2019 LingYun IoT System Studio
+ *                  All rights reserved.
+ *
+ *       Filename:  config.c
+ *    Description:  This file is mqttd configure file parser function
+ *
+ *        Version:  1.0.0(2019年06月25日)
+ *         Author:  Guo Wenxue <guowenxue@gmail.com>
+ *      ChangeLog:  1, Release initial version on "2019年06月25日 22时23分55秒"
+ *
+ ********************************************************************************/
+#include "config.h"
+#include "logger.h"
+#include "iniparser.h"
+
+enum
+{
+    _TYPE_INPUT,
+    _TYPE_OUTPUT,
+};
+int parser_gpio_info(int type, gpio_t *gpio, char *conf);
+
+int parser_conf(const char *conf_file, iotd_ctx_t *ctx, int debug)
+{
+    dictionary         *ini;
+    const char         *str;
+    int                 val;
+    int                 rv = 0;
+    logger_t           *logger;
+    hwinfo_t           *hwinfo;
+    mqtt_ctx_t         *mqtt;
+
+    if( !conf_file || !ctx )
+    {
+        fprintf(stderr, "%s() Invalid input arguments\n", __func__);
+        return -1;
+    }
+
+    memset(ctx, 0, sizeof(*ctx));
+    logger = &ctx->logger;
+    hwinfo = &ctx->hwinfo;
+    mqtt = &ctx->mqtt;
+
+    ini = iniparser_load(conf_file);
+    if( !ini )
+    {
+        fprintf(stderr, "ERROR: Configure file '%s' load failed\n", conf_file);
+        return -2;
+    }
+
+    /*+------------------------------------------------------+
+     *|    parser logger settings and start logger system    |
+     *+------------------------------------------------------+*/
+    if( !debug )
+    {
+        str = iniparser_getstring(ini, "logger:file", "/tmp/thingsboard.log");
+        strncpy(logger->logfile, str, sizeof(logger->logfile));
+        logger->logsize = iniparser_getint(ini, "logger:size", 1024);
+        logger->loglevel = iniparser_getint(ini, "logger:level", LOG_LEVEL_INFO);
+    }
+    else
+    {
+        strncpy(logger->logfile, "console", sizeof(logger->logfile));
+        logger->loglevel = LOG_LEVEL_DEBUG;
+        logger->logsize = 0;
+    }
+
+    if( log_open(logger->logfile, logger->loglevel, logger->logsize, LOG_LOCK_DISABLE) < 0 )
+    {
+        fprintf(stderr, "Logger system initialise failure\n");
+        return -2;
+    }
+
+    log_info("Logger system initialise ok\n");
+
+
+    /*+------------------------------------------------------+
+     *|               parser production ID                   |
+     *+------------------------------------------------------+*/
+
+    if( !(str=iniparser_getstring(ini, "common:devid", NULL)) )
+    {
+        log_error("ERROR: Parser device ID failure\n");
+        rv = -3;
+        goto cleanup;
+    }
+    /* cJSON parser ID will get ""  */
+    snprintf(mqtt->devid, sizeof(mqtt->devid), "\"%s\"", str);
+    log_info("Parser device ID [%s]\n", mqtt->devid);
+
+
+    /*+------------------------------------------------------+
+     *|       parser hardware module configuration           |
+     *+------------------------------------------------------+*/
+
+    /* parser GPIO output pins  */
+    if( !(str=iniparser_getstring(ini, "hardware:gpio_outpin", NULL)) )
+    {
+        log_warn("parser no GPIO output pins\n");
+    }
+    else
+    {
+        parser_gpio_info(_TYPE_OUTPUT, &hwinfo->gpio, (char *)str);
+        log_info("parser [%d] GPIO output pins configured\n", hwinfo->gpio.outcnt);
+    }
+
+    hwinfo->light_intval = iniparser_getint(ini, "hardware:light_intval", 20);
+    log_info("parser relay controled light interval time [%d]\n", hwinfo->light_intval);
+
+    /* parser GPIO input pins  */
+    if( !(str=iniparser_getstring(ini, "hardware:gpio_inpin", NULL)) )
+    {
+        log_warn("parser no GPIO input pins\n");
+    }
+    else
+    {
+        parser_gpio_info(_TYPE_INPUT, &hwinfo->gpio, (char *)str);
+        log_info("parser [%d] GPIO input pins\n", hwinfo->gpio.incnt);
+    }
+
+    hwinfo->lux_threshold = iniparser_getdouble(ini, "hardware:lux_threshold", 0.1);
+    log_info("parser LUX enable and threshold value set be [%.03f]\n", hwinfo->lux_threshold);
+
+
+    /*+------------------------------------------------------+
+     *|              parser broker settings                  |
+     *+------------------------------------------------------+*/
+
+    if( !(str=iniparser_getstring(ini, "broker:hostname", NULL)) )
+    {
+        log_error("ERROR: Parser MQTT broker server hostname failure\n");
+        rv = -4;
+        goto cleanup;
+    }
+    strncpy(mqtt->host, str, sizeof(mqtt->host) );
+
+    if( (val=iniparser_getint(ini, "broker:port", -1)) < 0 )
+    {
+        log_error("ERROR: Parser MQTT broker server port failure\n");
+        rv = -5;
+        goto cleanup;
+    }
+    mqtt->port = val;
+    log_info("Parser MQTT broker server [%s:%d]\n", mqtt->host, mqtt->port);
+
+    str=iniparser_getstring(ini, "broker:token", NULL);
+    strncpy(mqtt->token, str, sizeof(mqtt->uid) );
+
+    str=iniparser_getstring(ini, "broker:username", NULL);
+    strncpy(mqtt->uid, str, sizeof(mqtt->uid) );
+
+    str=iniparser_getstring(ini, "broker:password", NULL);
+    strncpy(mqtt->pwd, str, sizeof(mqtt->pwd) );
+
+    if( mqtt->uid && mqtt->pwd )
+        log_info("Parser broker author by [%s:%s]\n", mqtt->uid, mqtt->pwd);
+
+    mqtt->keepalive = iniparser_getint(ini, "broker:keepalive", DEF_KEEPALIVE);
+    log_info("Parser broker keepalive timeout [%d] seconds\n", mqtt->keepalive);
+
+    /*+------------------------------------------------------+
+     *|             parser publisher settings                |
+     *+------------------------------------------------------+*/
+
+    if( !(str=iniparser_getstring(ini, "publisher:pubTopic", NULL)) )
+    {
+        log_error("ERROR: Parser MQTT broker publisher topic failure\n");
+        rv = -6;
+        goto cleanup;
+    }
+    strncpy(mqtt->pubTopic, str, sizeof(mqtt->pubTopic) );
+
+    mqtt->pubQos = iniparser_getint(ini, "publisher:pubQos", DEF_QOS);
+    mqtt->interval = iniparser_getint(ini, "publisher:interval", DEF_PUBINTERVAL);
+    log_info("Parser publisher topic \"%s\" with Qos[%d] interval[%d]\n", mqtt->pubTopic, mqtt->pubQos, mqtt->interval);
+
+    /*+------------------------------------------------------+
+     *|             parser subscriber settings               |
+     *+------------------------------------------------------+*/
+
+    if( !(str=iniparser_getstring(ini, "subsciber:subTopic", NULL)) )
+    {
+        log_error("ERROR: Parser MQTT broker publisher topic failure\n");
+        rv = -7;
+        goto cleanup;
+    }
+    strncpy(mqtt->subTopic, str, sizeof(mqtt->subTopic) );
+
+    mqtt->subQos = iniparser_getint(ini, "subsciber:subQos", DEF_QOS);
+    log_info("Parser subscriber topic \"%s\" with Qos[%d]\n", mqtt->subTopic, mqtt->subQos);
+
+cleanup:
+    if( ini )
+        iniparser_freedict(ini);
+
+    if( rv )
+        log_close();
+
+    return rv;
+}
+
+/* conf format:  "{light_indoor:6:0},{light_hallway:26:0}"  */
+int parser_gpio_info(int type, gpio_t *gpio, char *conf)
+{
+    char              *ptr;
+    char              *pstart;
+    char              *pend;
+    char               buf[64];
+    int                cnt = 0;
+    int                rv = 0;
+
+    if( !gpio || !conf || strlen(conf)<3 )
+    {
+        log_error("Invalid input arguments.\n");
+        return -1;
+    }
+
+    pstart = strchr(conf, '{');
+    if( !pstart )
+        return 0;
+
+    pend = strchr(pstart, '}');
+
+    while( pstart && pend )
+    {
+        memset(buf, 0, sizeof(buf));
+
+        strncpy(buf, pstart+1, pend-pstart-1);
+
+        /* parser and get the GPIO name, BCM pin number, active power level */
+
+        {
+            /* check GPIO configure name too long or not */
+            ptr = strchr(buf, ':');
+            if( !ptr )
+            {
+                log_error("Found invalid GPIO configure: %s\n", buf);
+                goto NEXT_LOOP;
+            }
+
+            if( ptr-buf > sizeof(gpio->input[cnt].name) )
+            {
+                log_error("Found GPIO name too long\n", buf);
+                goto NEXT_LOOP;
+            }
+
+            /* use sscanf() to parser GPIO configured values */
+            if(_TYPE_INPUT == type )
+            {
+                rv = sscanf(buf, "%[^:]:%d:%d", gpio->input[cnt].name, &gpio->input[cnt].pin, &gpio->input[cnt].active_level);
+                if( 3 == rv)
+                {
+                    log_info("parser GPIO input[%s] BCM[%d] active[%d]\n", gpio->input[cnt].name, gpio->input[cnt].pin, gpio->input[cnt].active_level);
+                    if( strstr(gpio->input[cnt].name, "infrared") )
+                    {
+                        log_info("parser GPIO enable infrared detect\n");
+                    }
+                    cnt++;
+                    gpio->incnt = cnt;
+                }
+                else
+                {
+                    log_error("Found invalid GPIO configure: %s\n", buf);
+                }
+            }
+            else
+            {
+                rv = sscanf(buf, "%[^:]:%d:%d", gpio->output[cnt].name, &gpio->output[cnt].pin, &gpio->output[cnt].active_level);
+                if( 3 == rv)
+                {
+                    log_info("parser GPIO output[%s] BCM[%d] active[%d]\n", gpio->output[cnt].name, gpio->output[cnt].pin, gpio->output[cnt].active_level);
+                    cnt++;
+                    gpio->outcnt = cnt;
+                }
+                else
+                {
+                    log_error("Found invalid GPIO configure: %s\n", buf);
+                }
+            }
+        }
+
+NEXT_LOOP:
+        pstart = strchr(pend, '{');
+        if( pstart )
+            pend = strchr(pstart, '}');
+    }
+
+
+    return gpio->outcnt;
+}
diff --git a/project/lightd/config.h b/project/lightd/config.h
new file mode 100644
index 0000000..5bff2bc
--- /dev/null
+++ b/project/lightd/config.h
@@ -0,0 +1,76 @@
+/*********************************************************************************
+ *      Copyright:  (C) 2019 LingYun IoT System Studio
+ *                  All rights reserved.
+ *
+ *       Filename:  config.h
+ *    Description:  This file is mqttd configure file parser function
+ *
+ *        Version:  1.0.0(2019年06月25日)
+ *         Author:  Guo Wenxue <guowenxue@gmail.com>
+ *      ChangeLog:  1, Release initial version on "2019年06月25日 22时23分55秒"
+ *
+ ********************************************************************************/
+#ifndef  __CONF_H_
+#define  __CONF_H_
+
+#include "gpio.h"
+
+enum
+{
+    Qos0, /* 发送者只发送一次消息,不进行重试,Broker不会返回确认消息。在Qos0情况下,Broker可能没有接受到消息 */
+    Qos1, /* 发送者最少发送一次消息,确保消息到达Broker,Broker需要返回确认消息PUBACK。在Qos1情况下,Broker可能接受到重复消息 */
+    Qos2, /* Qos2使用两阶段确认来保证消息的不丢失和不重复。在Qos2情况下,Broker肯定会收到消息,且只收到一次  */
+};
+
+#define DEF_KEEPALIVE       30
+#define DEF_PUBINTERVAL     120
+#define DEF_QOS             Qos2
+
+typedef struct mqtt_ctx_s
+{
+    char          devid[32];    /*  device ID */
+
+    /* Broker settings  */
+    char            host[128];  /* MQTT broker server name  */
+    int             port;       /* MQTT broker listen port  */
+    char            token[64];  /* token */
+    char            uid[64];    /* username */
+    char            pwd[64];    /* password */
+    int             keepalive;  /* MQTT broker send PING message to subsciber/publisher keepalive timeout<seconds> */
+
+    /* Publisher settings */
+    char            pubTopic[256]; /* Publisher topic  */
+    int             pubQos;        /* Publisher Qos */
+    int             interval ;     /* Publish sensor data interval time, unit seconds */
+
+    /* Subscriber settings */
+    char            subTopic[256]; /* Subscriber topic */
+    int             subQos;        /* Subscriber Qos  */
+} mqtt_ctx_t;
+
+typedef struct logger_s
+{
+    /* logger settings */
+    char            logfile[128]; /* logger record file */
+    int             loglevel;     /* logger level  */
+    int             logsize;      /* logger file maxsize, oversize will rollback */
+} logger_t;
+
+typedef struct hwinfo_s
+{
+    gpio_t          gpio;         /* gpio information */
+    int             light_intval; /* light on interval */
+    float           lux_threshold;/* lux threshold value  */
+} hwinfo_t;
+
+typedef struct iotd_ctx_s
+{
+    logger_t        logger;
+    hwinfo_t        hwinfo;
+    mqtt_ctx_t      mqtt;
+} iotd_ctx_t;
+
+extern int parser_conf(const char *conf_file, iotd_ctx_t *ctx, int debug);
+
+#endif   /* ----- #ifndef _CONF_H_  ----- */
+
diff --git a/project/lightd/etc/iotd.conf b/project/lightd/etc/iotd.conf
deleted file mode 100644
index b54f3e6..0000000
--- a/project/lightd/etc/iotd.conf
+++ /dev/null
@@ -1,83 +0,0 @@
-
-[common]
-id="RPI3B#01"
-
-[logger]
-
-# 日志记录文件
-file=/tmp/iotd.log
-
-# 日志级别: 0:error 1:warnning 2:info 3:debug 4:trace
-level=2
-
-# 日志回滚大小
-size=1024
-
-
-#+-------------------------------------------+
-#|         Hardware configuration            |
-#+-------------------------------------------+
-
-# 树莓派连接的外设信息,0:禁用或未连接  其他: 使能或相关硬件连接的Pin管脚(BCM)
-[hardware]
-
-# LED或继电器等GPIO输出控制, 格式: {名称:BCM编码:控制电平}
-# Relay(1) <-> 19      Relay(2) <-> 26
-gpio_outpin={light_indoor:19:1},{light_hallway:26:1}
-
-# 红外探测到人后,继电器控制灯亮的时长
-light_intval=15
-
-# 按键或红外感应灯GPIO输入控制, 格式: {名称:BCM编码:控制:电平}
-# Indoor(23)<->(black/gray)    Hallway(24)<->(yellow/red)
-gpio_inpin={infrared_indoor:23:1},{infrared_hallway:24:1}
-
-# 是否使能 TSL2561 光强传感器模块,0:禁用  X:光强阈值
-lux=1
-lux_threshold=0.10
-
-# 是否使能 DS18b20 温度传感器模块,0:禁用  1:是能
-# ds18b20=1
-
-# 是否使能 SHT2X 温湿度传感器模块,0:禁用  1:使能
-# sht2x=0
-
-#+-------------------------------------------+
-#|           MQTT configuration              |
-#+-------------------------------------------+
-
-[broker]
-
-# broker 服务器地址和端口号
-hostname="weike-iot.com"
-port=10883
-
-# broker 认证连接的用户名和密码
-username="lingyun"
-password="lingyun"
-
-# broker给subsciber和publisher发送PING报文保持 keepalive 的时间周期,单位是秒
-keepalive=30
-
-# Qos0: 发送者只发送一次消息,不进行重试,Broker不会返回确认消息。在Qos0情况下,Broker可能没有接受到消息
-# Qos1: 发送者最少发送一次消息,确保消息到达Broker,Broker需要返回确认消息PUBACK。在Qos1情况下,Broker可能接受到重复消息
-# Qos2: Qos2使用两阶段确认来保证消息的不丢失和不重复。在Qos2情况下,Broker肯定会收到消息,且只收到一次
-
-
-[subsciber]
-
-subTopic="$Sys/Studio/Downlink/iotd"
-subQos=0
-
-
-[publisher]
-
-enable=0
-
-pubTopic="$Sys/Studio/Uplink/"
-pubQos=0
-
-# Publisher上报传感器数据的周期,单位是秒
-interval=60
-
-
diff --git a/project/lightd/etc/lightd.conf b/project/lightd/etc/lightd.conf
new file mode 100644
index 0000000..13494b9
--- /dev/null
+++ b/project/lightd/etc/lightd.conf
@@ -0,0 +1,70 @@
+[common]
+devid="RaspberryPi#1"
+
+# 树莓派连接的外设信息,使能或相关硬件连接的Pin管脚
+[hardware]
+
+# 红外感应灯GPIO输入控制, 格式: {名称:BCM编码:控制电平} 
+# Indoor(#16)<->(black/gray)    Hallway(#18)<->(yellow/red)
+gpio_inpin={infrared_indoor:23:1},{infrared_hallway:24:1}
+
+# 继电器GPIO输出控制,     格式: {名称:BCM编码:控制电平} 
+#            Relay(1) <-> #35     Relay(2) <-> #37 
+gpio_outpin={light_indoor:19:1},{light_hallway:26:1}
+
+# TSL2561 光强传感器光强阈值
+lux_threshold=0.10
+
+# 红外探测到人后,继电器控制灯亮的时长
+light_intval=15
+
+
+[logger]
+
+# 日志记录文件
+file=/var/log/lightd.log
+
+# 日志级别: 0:ERROR 1:WARN 2:INFO 3:DEBUG 4:TRACE 
+level=2
+
+# 日志回滚大小
+size=1024
+
+
+[broker]
+
+# broker 服务器地址和端口号
+hostname="weike-iot.com"
+port=2262
+
+# broker 认证连接的 token
+token="gu8wq8mfj1gadkyh6yo5"
+
+# broker 认证连接的用户名和密码
+username="lingyun"
+password="lingyun"
+
+# broker给subsciber和publisher发送PING报文保持 keepalive 的时间周期,单位是秒
+keepalive=30
+
+# Qos0: 发送者只发送一次消息,不进行重试,Broker不会返回确认消息。在Qos0情况下,Broker可能没有接受到消息
+# Qos1: 发送者最少发送一次消息,确保消息到达Broker,Broker需要返回确认消息PUBACK。在Qos1情况下,Broker可能接受到重复消息
+# Qos2: Qos2使用两阶段确认来保证消息的不丢失和不重复。在Qos2情况下,Broker肯定会收到消息,且只收到一次
+
+[publisher]
+
+# mosquitto_pub -h weike-iot.com -p 2262 -u "gu8wq8mfj1gadkyh6yo5" -t v1/devices/me/telemetry -m '{"temperature":66.66, "humidity":88.88}'
+pubTopic="v1/devices/me/telemetry"
+pubQos=0
+
+# Publisher上报传感器数据的周期,单位是秒
+interval=60
+
+[subsciber]
+
+# mosquitto_sub -h weike-iot.com -p 2262 -u "gu8wq8mfj1gadkyh6yo5" -t "v1/devices/me/rpc/request/+" 
+#  {"method":"setValue","params":{"device":"lightIndoor","status":true}}
+#  {"method":"setValue","params":{"device":"lightHallway","status":true}}
+subTopic="v1/devices/me/rpc/request/+"
+subQos=0
+
diff --git a/project/lightd/hal/ds18b20.c b/project/lightd/hal/ds18b20.c
deleted file mode 100644
index 2037af5..0000000
--- a/project/lightd/hal/ds18b20.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/*********************************************************************************
- *      Copyright:  (C) 2018 LingYun IoT System Studio
- *                  All rights reserved.
- *
- *       Filename:  ds18b20.c
- *    Description:  This file is temperature sensor DS18B20 code
- *
- *        Version:  1.0.0(2018/10/14)
- *         Author:  Guo Wenxue <guowenxue@gmail.com>
- *      ChangeLog:  1, Release initial version on "2018/10/14 12:13:26"
- *
- ********************************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <string.h>
-#include <time.h>
-#include <errno.h>
-
-#include "logger.h"
-
-/* File Content:
-   pi@raspberrypi:~/guowenxue $ cat /sys/bus/w1/devices/28-041731f7c0ff/w1_slave
-   3a 01 4b 46 7f ff 0c 10 a5 : crc=a5 YES
-   3a 01 4b 46 7f ff 0c 10 a5 t=19625
- */
-
-int ds18b20_get_temperature(float *temp)
-{
-    char            w1_path[50] = "/sys/bus/w1/devices/";
-    char            chip[20];
-    char            buf[128];
-    DIR            *dirp;
-    struct dirent  *direntp;
-    int             fd =-1;
-    char           *ptr;
-    int             found = 0;
-
-    if( !temp )
-    {
-            return -1;
-    }
-
-    /*+-------------------------------------------------------------------+
-     *|  open dierectory /sys/bus/w1/devices to get chipset Serial Number |
-     *+-------------------------------------------------------------------+*/
-    if((dirp = opendir(w1_path)) == NULL)
-    {
-        log_error("opendir '%s' error: %s\n", w1_path, strerror(errno));
-        return -2;
-    }
-
-    while((direntp = readdir(dirp)) != NULL)
-    {
-        if(strstr(direntp->d_name,"28-"))
-        {
-            /* find and get the chipset SN filename */
-            strcpy(chip,direntp->d_name);
-            found = 1;
-        break;
-        }
-    }
-    closedir(dirp);
-
-    if( !found )
-    {
-            log_error("Can not find ds18b20 in %s\n", w1_path);
-            return -3;
-    }
-
-    /* get DS18B20 sample file full path: /sys/bus/w1/devices/28-xxxx/w1_slave */
-    strncat(w1_path, chip, sizeof(w1_path)-strlen(w1_path));
-    strncat(w1_path, "/w1_slave", sizeof(w1_path)-strlen(w1_path));
-
-    /* open file /sys/bus/w1/devices/28-xxxx/w1_slave to get temperature */
-    if( (fd=open(w1_path, O_RDONLY)) < 0 )
-    {
-            log_error("open %s error: %s\n", w1_path, strerror(errno));
-            return -4;
-    }
-
-    if(read(fd, buf, sizeof(buf)) < 0)
-    {
-            log_error("read %s error: %s\n", w1_path, strerror(errno));
-            return -5;
-    }
-
-    ptr = strstr(buf, "t=");
-    if( !ptr )
-    {
-            log_error("ERROR: Can not get temperature\n");
-            return -6;
-    }
-
-    ptr+=2;
-
-    /* convert string value to float value */
-    *temp = atof(ptr)/1000;
-
-    close(fd);
-
-    return 0;
-}
diff --git a/project/lightd/hal/ds18b20.h b/project/lightd/hal/ds18b20.h
deleted file mode 100644
index 58540a8..0000000
--- a/project/lightd/hal/ds18b20.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*********************************************************************************
- *      Copyright:  (C) 2018 LingYun IoT System Studio
- *                  All rights reserved.
- *
- *       Filename:  ds18b20.c
- *    Description:  This file is temperature sensor DS18B20 code
- *
- *        Version:  1.0.0(2018/10/14)
- *         Author:  Guo Wenxue <guowenxue@gmail.com>
- *      ChangeLog:  1, Release initial version on "2018/10/14 12:13:26"
- *
- ********************************************************************************/
-
-#ifndef __DS18B20_H
-#define __DS18B20_H
-
-extern int ds18b20_get_temperature(float *temp);
-
-#endif
diff --git a/project/lightd/hal/gpio.c b/project/lightd/hal/gpio.c
index 01cc363..d0e781c 100644
--- a/project/lightd/hal/gpio.c
+++ b/project/lightd/hal/gpio.c
@@ -11,13 +11,16 @@
  *
  ********************************************************************************/
 
-#include <stdio.h>
-#include <stdlib.h>
 #include <unistd.h>
-#include <fcntl.h>
-#include <dirent.h>
+#include <stdlib.h>
 #include <string.h>
-#include <time.h>
+#include <errno.h>
+
+#include "logger.h"
+#include "util_proc.h"
+#include "gpio.h"
+
+#define RPI_GPIONAME        "gpiochip0"
 #include <errno.h>
 
 #include "logger.h"
@@ -35,13 +38,11 @@
     int                 rv;
 
     s_gpio = gpio;
-
     if( !gpio )
     {
         log_error("Invalid input arguments $gpio\n");
         return -1;
     }
-
 
     if( !gpio->incnt && !gpio->outcnt )
     {
@@ -58,7 +59,6 @@
     }
     log_info("gpiod initialise open chip ok\n");
 
-
     /*  gpiod request all output pins */
     for(i=0; i<gpio->outcnt; i++)
     {
@@ -66,19 +66,21 @@
         if( !gpio->output[i].line )
         {
             log_error("gpiod get line for '%s' pin[#%d] failure\n", gpio->output[i].name, gpio->output[i].pin );
-            return -2;
+            rv = -3;
+            goto failed;
         }
 
         if( gpiod_line_request_output(gpio->output[i].line, gpio->output[i].name, !gpio->output[i].active_level) < 0 )
         {
             log_error("gpiod request '%s' pin[#%d] output failure: %s\n", gpio->output[i].name, gpio->output[i].pin, strerror(errno));
+            rv = -3;
+            goto failed;
         }
         else
         {
             log_info("gpiod request '%s' pin[#%d] output ok\n", gpio->output[i].name, gpio->output[i].pin);
         }
     }
-
 
     /*  gpiod request all input pins */
     for(i=0; i<gpio->incnt; i++)
@@ -87,7 +89,8 @@
         if( !gpio->input[i].line )
         {
             log_error("gpiod get line for '%s' pin[#%d] failure\n", gpio->input[i].name, gpio->input[i].pin );
-            return -2;
+            rv = -4;
+            goto failed;
         }
 
         if( gpio->output[i].active_level )
@@ -99,6 +102,8 @@
         {
             log_error("gpiod request '%s' pin[#%d] event edge [%s] failure: %s\n",
                     gpio->input[i].name, gpio->input[i].pin, gpio->output[i].active_level?"rising":"falling", strerror(errno));
+            rv = -4;
+            goto failed;
         }
         else
         {
@@ -108,6 +113,10 @@
     }
 
     return 0;
+
+failed:
+    gpiod_chip_close(s_chip);
+    return rv;
 }
 
 
@@ -122,12 +131,10 @@
         return ;
     }
 
-
     for(i=0; i<s_gpio->outcnt; i++)
     {
         gpiod_line_release(s_gpio->output[i].line);
     }
-
 
     for(i=0; i<s_gpio->incnt; i++)
     {
@@ -137,14 +144,16 @@
     gpiod_chip_close(s_chip);
 }
 
-void gpio_out(char *name, char *cmd)
+/* Turn light ON or OFF */
+void turn_light(char *name, int status)
 {
     int              i;
     int              found = 0;
+    int              value;
 
     for( i=0; i<s_gpio->outcnt; i++ )
     {
-        if( !strncasecmp(s_gpio->output[i].name, name, strlen(name)))
+        if( strstr(s_gpio->output[i].name, name) )
         {
             found = 1;
             break;
@@ -157,60 +166,11 @@
         return ;
     }
 
-    if( strstr(cmd, "on") )
-    {
-        gpiod_line_set_value(s_gpio->output[i].line, s_gpio->output[i].active_level);
-    }
-    else if( strstr(cmd, "off") )
-    {
-        gpiod_line_set_value(s_gpio->output[i].line, !s_gpio->output[i].active_level);
-    }
+    log_info("Turn %s light %s\n", name, status?"on":"off");
+    value = status ? s_gpio->output[i].active_level : !s_gpio->output[i].active_level;
+    gpiod_line_set_value(s_gpio->output[i].line, value);
 
     return ;
-}
-
-
-void *light_on_worker(void *arg)
-{
-    int                      i;
-    int                      found = 0;
-    char                    *name = (char *)arg;
-    gpio_info_t             *gpiout;
-
-    if( !name )
-    {
-        log_error("Invalid input arugment\n");
-        return NULL;
-    }
-
-    if( s_gpio->light_intval <= 0 )
-    {
-        log_error("Invalid light_intval value[%d] in configure file\n", s_gpio->light_intval);
-        return NULL;
-    }
-
-    for(i=0; i<s_gpio->outcnt; i++)
-    {
-        if( strstr(s_gpio->output[i].name, name) )
-        {
-            gpiout = &(s_gpio->output[i]);
-            found = 1;
-        }
-    }
-
-    if( !found )
-    {
-        log_error("Light '%s' not found\n", name);
-        return NULL;
-    }
-
-    log_info("Trun on %s for [%d] seconds\n", gpiout->name, s_gpio->light_intval);
-
-    gpio_out(gpiout->name, "on");
-    sleep(s_gpio->light_intval);
-    gpio_out(gpiout->name, "off");
-
-    return NULL;
 }
 
 /* Return value: 0(LOW): Nobody detected, !0: indoor or hallway detected */
@@ -218,14 +178,12 @@
 {
     int                      i;
     int                      rv = 0;
-    int                      res = 0;
+    int                      result = 0;
+    int                      num_lines = 0;
 
     struct gpiod_line_event  ev;
     struct gpiod_line_bulk   bulk, event_bulk;
     struct gpiod_line       *line;
-
-    int                      num_lines = 0;
-
 
     gpiod_line_bulk_init(&bulk);
 
@@ -244,7 +202,7 @@
         return 0;
     }
 
-    log_debug("infrared start detect event now...\n");
+    log_debug("infrared start detect event(blocked) now...\n");
     rv = gpiod_line_event_wait_bulk(&bulk, NULL, &event_bulk);
     if( rv <= 0 )
     {
@@ -270,25 +228,23 @@
             {
                 if( s_gpio->input[i].active_level != gpiod_line_get_value(line) )
                 {
-                    //log_debug("infrared '%s' detect get wrong power level\n", s_gpio->input[i].name);
+                    log_debug("infrared '%s' detect get wrong power level\n", s_gpio->input[i].name);
                     continue;
                 }
 
                 if( strstr(s_gpio->input[i].name, "indoor") )
                 {
                     log_debug("indoor infrared gpiod wait get event.\n", s_gpio->input[i].name);
-                    res |= FLAG_INFRARED_INDOOR;
+                    result |= FLAG_INFRARED_INDOOR;
                 }
                 else if( strstr(s_gpio->input[i].name, "hallway") )
                 {
                     log_debug("hallway infrared gpiod wait get event.\n", s_gpio->input[i].name);
-                    res |= FLAG_INFRARED_HALLWAY;
+                    result |= FLAG_INFRARED_HALLWAY;
                 }
             }
         }
     }
 
-    return res;
+    return result;
 }
-
-
diff --git a/project/lightd/hal/gpio.h b/project/lightd/hal/gpio.h
index 29e970a..3a085e1 100644
--- a/project/lightd/hal/gpio.h
+++ b/project/lightd/hal/gpio.h
@@ -21,33 +21,28 @@
 
 typedef struct gpio_info_s
 {
-    char                 name[32];      /*  GPIO connected module name */
-    int                  pin;           /*  GPIO BCM pin number */
-    int                  active_level;  /*  active power level */
-    struct gpiod_line   *line;          /*  gpiod line */
+    struct gpiod_line  *line;          /*  gpiod line */
+    char                name[32];      /*  GPIO connected module name */
+    int                 pin;           /*  GPIO BCM pin number */
+    int                 active_level;  /*  active power level */
 } gpio_info_t;
-
 
 typedef struct gpio_s
 {
-    gpio_info_t          output[GPIO_MAXOUT]; /* GPIO output pins */
-    int                  outcnt;              /* GPIO output numbers */
-    int                  light_intval;        /* light on interval time */
+    gpio_info_t         output[GPIO_MAXOUT]; /* GPIO output pins */
+    int                 outcnt;              /* GPIO output numbers */
 
-    gpio_info_t          input[GPIO_MAXIN];   /* GPIO input pins */
-    int                  incnt;               /* GPIO input numbers */
-    int                  infrared_enable;     /* infrared enable or not */
+    gpio_info_t         input[GPIO_MAXIN];   /* GPIO input pins */
+    int                 incnt;               /* GPIO input numbers */
 } gpio_t;
 
 extern int gpio_init(gpio_t *gpio);
 extern void gpio_term(void);
 
-/* turn which light on/off */
-extern void gpio_out(char *name, char *cmd);
-
-
-/*thread work body to turn light $name on for some seconds */
-void *light_on_worker(void *arg);
+/* turn which light ON/OFF */
+#define OFF         0
+#define ON          1
+extern void turn_light(char *name, int status);
 
 /* Return value: 0(LOW): Nobody detected, !0: Which infrared detect incoming */
 #define FLAG_INFRARED_INDOOR          (1<<0)
diff --git a/project/lightd/hal/hal.c b/project/lightd/hal/hal.c
deleted file mode 100644
index 4c40b0e..0000000
--- a/project/lightd/hal/hal.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/*********************************************************************************
- *      Copyright:  (C) 2019 LingYun IoT System Studio
- *                  All rights reserved.
- *
- *       Filename:  hal.c
- *    Description:  This file is RPi HAL(Hardware Abstract Layer) initial functions
- *
- *        Version:  1.0.0(2019年06月24日)
- *         Author:  Guo Wenxue <guowenxue@gmail.com>
- *      ChangeLog:  1, Release initial version on "2019年06月24日 23时46分47秒"
- *
- ********************************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <string.h>
-#include <time.h>
-#include <errno.h>
-
-#include "logger.h"
-#include "hal.h"
-
-int hal_init(hal_ctx_t *ctx)
-{
-    if(!ctx)
-    {
-        log_error("Invalid input arguments\n");
-        return -1;
-    }
-
-    if( ctx->sht2x_enable )
-    {
-        if( sht2x_init()< 0 )
-        {
-            log_error("R&H sensor SHT2X initialise failure\n");
-            return -2;
-        }
-        else
-        {
-            log_info("R&H sensor SHT2X initialise okay\n");
-        }
-    }
-
-    if( ctx->lux_enable )
-    {
-        if( tsl2561_init() < 0 )
-        {
-            log_error("LUX sensor TSL2561 initialise failure\n");
-            return -2;
-        }
-        else
-        {
-            log_info("LUX sensor TSL2561 initialise okay\n");
-        }
-    }
-
-    gpio_init(&ctx->gpio);
-
-    return 0;
-}
-
-
-void hal_term(hal_ctx_t *ctx)
-{
-    if(!ctx)
-    {
-        log_error("Invalid input arguments\n");
-        return ;
-    }
-
-
-    if( ctx->sht2x_enable )
-    {
-        sht2x_term();
-    }
-
-    if( ctx->lux_enable )
-    {
-        tsl2561_term();
-    }
-
-    gpio_term();
-
-    return ;
-}
-
diff --git a/project/lightd/hal/hal.h b/project/lightd/hal/hal.h
deleted file mode 100644
index be4af23..0000000
--- a/project/lightd/hal/hal.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*********************************************************************************
- *      Copyright:  (C) 2019 LingYun IoT System Studio
- *                  All rights reserved.
- *
- *       Filename:  hal.h
- *    Description:  This file is RPi HAL(Hardware Abstract Layer) initial functions
- *
- *        Version:  1.0.0(2019年06月24日)
- *         Author:  Guo Wenxue <guowenxue@gmail.com>
- *      ChangeLog:  1, Release initial version on "2019年06月24日 23时46分47秒"
- *
- ********************************************************************************/
-
-#ifndef  _HAL_H_
-#define  _HAL_H_
-
-#include "ds18b20.h"
-#include "sht20.h"
-#include "tsl2561.h"
-#include "gpio.h"
-
-
-typedef struct hal_ctx_s
-{
-    int                  ds18b20_enable; /* 0:Disable   !0: Enable */
-    int                  sht2x_enable;   /* 0:Disable   !0: Enable */
-
-    int                  lux_enable;     /* 0:Disable   !0: Enable */
-    float                lux_threshold;  /* Lux Threshold value */
-
-    gpio_t               gpio;           /* gpio intput/output pins  */
-} hal_ctx_t;
-
-
-/* init hardware */
-extern int hal_init(hal_ctx_t *ctx);
-
-/* terminal hardware */
-extern void hal_term(hal_ctx_t *ctx);
-
-#endif   /* ----- #ifndef _HAL_H_  ----- */
-
diff --git a/project/lightd/hal/makefile b/project/lightd/hal/makefile
index 608137a..3525db8 100644
--- a/project/lightd/hal/makefile
+++ b/project/lightd/hal/makefile
@@ -1,15 +1,36 @@
+#********************************************************************************
+#      Copyright:  (C) 2023 LingYun IoT System Studio
+#                  All rights reserved.
+#
+#       Filename:  Makefile
+#    Description:  This file used compile all the source code to static library
+#
+#        Version:  1.0.0(11/08/23)
+#         Author:  Guo Wenxue <guowenxue@gmail.com>
+#      ChangeLog:  1, Release initial version on "11/08/23 16:18:43"
+#
+#*******************************************************************************
 
-PWD=$(shell pwd )
+PWD=$(shell pwd)
+
+BUILD_ARCH=$(shell uname -m)
+ifneq ($(findstring $(BUILD_ARCH), "x86_64" "i386"),)
+    CROSS_COMPILE?=arm-linux-gnueabihf-
+endif
+
+#CROSS_COMPILE=
 
 LIBNAME=$(shell basename ${PWD} )
 TOPDIR=$(shell dirname ${PWD} )
 
 all: clean
 	@rm -f *.o
-	@${CROSSTOOL}gcc ${CFLAGS} -I${TOPDIR} -c *.c 
-	${CROSSTOOL}ar -rcs  lib${LIBNAME}.a *.o
+	@${CROSS_COMPILE}gcc ${CFLAGS} -I${TOPDIR} -c *.c
+	${CROSS_COMPILE}ar -rcs  lib${LIBNAME}.a *.o
 
 clean:
 	@rm -f *.o
 	@rm -f *.a
 
+distclean:
+	@make clean
diff --git a/project/lightd/hal/sht20.c b/project/lightd/hal/sht20.c
deleted file mode 100644
index 25a2dc6..0000000
--- a/project/lightd/hal/sht20.c
+++ /dev/null
@@ -1,466 +0,0 @@
-/*********************************************************************************
- *      Copyright:  (C) 2018 LingYun IoT System Studio
- *                  All rights reserved.
- *
- *       Filename:  sht20.c
- *    Description:  This file is temperature and relative humidity sensor SHT20 code
- *
- *        Version:  1.0.0(2018/10/14)
- *         Author:  Guo Wenxue <guowenxue@gmail.com>
- *      ChangeLog:  1, Release initial version on "2018/10/14 12:13:26"
- *
- ********************************************************************************/
-
-#include <stdio.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <linux/types.h>
-#include <sys/stat.h>
-#include <linux/i2c.h>
-#include <linux/i2c-dev.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <string.h>
-#include <stdint.h>
-#include <time.h>
-#include <errno.h>
-#include <string.h>
-
-#include "sht20.h"
-#include "logger.h"
-#include "util_proc.h"
-
-static int s_sht2x_fd = -1;
-
-void sht2x_term(void)
-{
-    close(s_sht2x_fd);
-    s_sht2x_fd = -1;
-    log_warn("Terminate SHT2X\n");
-}
-
-static inline void dump_buf(const char *prompt, uint8_t *buf, int size)
-{
-    int          i;
-
-    if( !buf )
-    {
-        return ;
-    }
-
-    if( prompt )
-    {
-        printf("%s ", prompt);
-    }
-
-    for(i=0; i<size; i++)
-    {
-        printf("%02x ", buf[i]);
-    }
-    printf("\n");
-
-    return ;
-}
-
-#ifdef I2C_API_RDWR  /* Use I2C userspace driver read/write API */
-
-int sht2x_softreset(int fd)
-{
-    uint8_t           buf[4];
-
-    if( fd<0 )
-    {
-        log_error("Invalid input arguments\n");
-        return -1;
-    }
-
-    /* software reset SHT2x */
-    memset(buf, 0, sizeof(buf));
-
-    buf[0] = SOFTRESET;
-    write(fd, buf, 1);
-
-    msleep(50);
-
-    return 0;
-}
-
-int sht2x_init(void)
-{
-
-    if( (s_sht2x_fd=open("/dev/i2c-1", O_RDWR)) < 0)
-    {
-        log_error("i2c device open failed: %s\n", strerror(errno));
-        return -1;
-    }
-
-    /* set I2C mode and SHT2x slave address */
-    ioctl(s_sht2x_fd, I2C_TENBIT, 0);    /* Not 10-bit but 7-bit mode */
-    ioctl(s_sht2x_fd, I2C_SLAVE, 0x40); /* set SHT2x slava address 0x40*/
-
-    if( sht2x_softreset(s_sht2x_fd) < 0 )
-    {
-        log_error("SHT2x softreset failure\n");
-        sht2x_term();
-        return -2;
-    }
-
-    log_debug("SHT2X initialise ok, s_sht2x_fd=%d\n", s_sht2x_fd);
-    return s_sht2x_fd;
-}
-
-int sht2x_get_temp_humidity(float *temp, float *rh)
-{
-    uint8_t           buf[4];
-
-    if( !temp || !rh )
-    {
-        log_error("Invalid input arguments\n");
-        return -1;
-    }
-
-    if( s_sht2x_fd < 0 )
-    {
-        if( sht2x_init() < 0)
-        {
-            log_error("SHT2x initialise failure\n");
-            return -2;
-        }
-    }
-
-    /* send trigger temperature measure command and read the data */
-    memset(buf, 0, sizeof(buf));
-    buf[0]=TRIGGER_TEMPERATURE_NO_HOLD;
-    write(s_sht2x_fd, buf, 1);
-
-    msleep(85); /* datasheet: typ=66, max=85 */
-
-    memset(buf, 0, sizeof(buf));
-    read(s_sht2x_fd, buf, 3);
-    //dump_buf("Temperature sample data: ", buf, 3);
-    *temp = 175.72 * (((((int) buf[0]) << 8) + buf[1]) / 65536.0) - 46.85;
-
-    /* send trigger humidity measure command and read the data */
-    memset(buf, 0, sizeof(buf));
-    buf[0] = TRIGGER_HUMIDITY_NO_HOLD;
-    write(s_sht2x_fd, buf, 1);
-
-    msleep(29); /* datasheet: typ=22, max=29 */
-    memset(buf, 0, sizeof(buf));
-
-    read(s_sht2x_fd, buf, 3);
-    //dump_buf("Relative humidity sample data: ", buf, 3);
-    *rh = 125 * (((((int) buf[0]) << 8) + buf[1]) / 65536.0) - 6;
-
-    return 0;
-}
-
-int sht2x_get_serialnumber(uint8_t *serialnumber, int size)
-{
-    uint8_t           buf[4];
-
-    if( !serialnumber || size!=8 )
-    {
-        log_error("Invalid input arguments\n");
-        return -1;
-    }
-
-    if( s_sht2x_fd < 0 )
-    {
-        if( sht2x_init() < 0)
-        {
-            log_error("SHT2x initialise failure\n");
-            return -2;
-        }
-    }
-
-    /* Read SerialNumber from Location 1 */
-    memset(buf, 0, sizeof(buf));
-    buf[0] = 0xfa;  /* command for readout on-chip memory */
-    buf[1] = 0x0f;  /* on-chip memory address */
-    write(s_sht2x_fd, buf, 2);
-
-    memset(buf, 0, sizeof(buf));
-    read(s_sht2x_fd, buf, 4);
-
-    serialnumber[5]=buf[0]; /* Read SNB_3 */
-    serialnumber[4]=buf[1]; /* Read SNB_2 */
-    serialnumber[3]=buf[2]; /* Read SNB_1 */
-    serialnumber[2]=buf[3]; /* Read SNB_0 */
-
-    /* Read SerialNumber from Location 2 */
-    memset(buf, 0, sizeof(buf) );
-    buf[0]=0xfc;  /* command for readout on-chip memory */
-    buf[1]=0xc9;  /* on-chip memory address */
-    write(s_sht2x_fd, buf, 2);
-
-    memset(buf, 0, sizeof(buf) );
-    read(s_sht2x_fd, buf, 4);
-
-    serialnumber[1]=buf[0]; /* Read SNC_1 */
-    serialnumber[0]=buf[1]; /* Read SNC_0 */
-    serialnumber[7]=buf[2]; /* Read SNA_1 */
-    serialnumber[6]=buf[3]; /* Read SNA_0 */
-
-    //dump_buf("SHT2x Serial number: ", serialnumber, 8);
-
-    return 0;
-}
-
-#elif (defined I2C_API_IOCTL)  /* Use I2C userspace driver read/write API */
-
-int sht2x_softreset(int fd)
-{
-    struct i2c_msg               msg;
-    struct i2c_rdwr_ioctl_data   sht2x_data;
-    uint8_t                      buf[2];
-
-    if( fd<0 )
-    {
-        log_error("Invalid input arguments\n");
-        return -1;
-    }
-
-    msg.addr= 0x40;
-    msg.flags=0; //write
-    msg.len= 1;
-    msg.buf= buf;
-    msg.buf[0]=SOFTRESET;
-
-    sht2x_data.nmsgs= 1;
-    sht2x_data.msgs= &msg;
-
-    if( ioctl(fd, I2C_RDWR, &sht2x_data) < 0 )
-    {
-        log_error("sht2x I2C_RDWR ioctl failure: %s\n", strerror(errno));
-        sht2x_term();
-        return -2;
-    }
-
-    msleep(50);
-
-    return 0;
-}
-
-
-int sht2x_init(void)
-{
-    if( (s_sht2x_fd=open("/dev/i2c-1", O_RDWR)) < 0)
-    {
-        log_error("i2c device open failed: %s\n", strerror(errno));
-        return -1;
-    }
-
-    if( sht2x_softreset(s_sht2x_fd) < 0 )
-    {
-        log_error("SHT2x softreset failure\n");
-        sht2x_term();
-        return -2;
-    }
-
-    log_debug("SHT2X initialise ok, s_sht2x_fd=%d\n", s_sht2x_fd);
-    return 0;
-}
-
-int sht2x_get_serialnumber(uint8_t *serialnumber, int size)
-{
-    struct i2c_msg               msgs[2];
-    struct i2c_rdwr_ioctl_data   sht2x_data;
-    uint8_t                      sbuf[2];
-    uint8_t                      rbuf[4];
-
-    if( !serialnumber || size!=8 )
-    {
-        log_error("Invalid input arguments\n");
-        return -1;
-    }
-
-    if( s_sht2x_fd < 0 )
-    {
-        if( sht2x_init() < 0)
-        {
-            log_error("SHT2x initialise failure\n");
-            return -2;
-        }
-    }
-
-    /*+------------------------------------------+
-     *|     Read SerialNumber from Location 1    |
-     *+------------------------------------------+*/
-
-    msgs[0].addr= 0x40;
-    msgs[0].flags=0; //write
-    msgs[0].len= 2;
-    msgs[0].buf= sbuf;
-    msgs[0].buf[0]=0xfa;  /* command for readout on-chip memory */
-    msgs[0].buf[1]=0x0f;  /* on-chip memory address */
-
-    msgs[1].addr=0x40;
-    msgs[1].flags=I2C_M_RD; //write
-    msgs[1].len= 4;
-    msgs[1].buf= rbuf;
-
-    sht2x_data.nmsgs= 2;
-    sht2x_data.msgs= msgs;
-
-    if( ioctl(s_sht2x_fd, I2C_RDWR, &sht2x_data) < 0 )
-    {
-        log_error("sht2x I2C_RDWR ioctl failure: %s\n", strerror(errno));
-        sht2x_term();
-        return -2;
-    }
-
-    serialnumber[5]=rbuf[0]; /* Read SNB_3 */
-    serialnumber[4]=rbuf[1]; /* Read SNB_2 */
-    serialnumber[3]=rbuf[2]; /* Read SNB_1 */
-    serialnumber[2]=rbuf[3]; /* Read SNB_0 */
-
-
-    /*+------------------------------------------+
-     *|     Read SerialNumber from Location 2    |
-     *+------------------------------------------+*/
-
-    msgs[0].addr= 0x40;
-    msgs[0].flags=0; //write
-    msgs[0].len= 2;
-    msgs[0].buf= sbuf;
-    msgs[0].buf[0]=0xfc;  /* command for readout on-chip memory */
-    msgs[0].buf[1]=0xc9;  /* on-chip memory address */
-
-    msgs[1].addr=0x40;
-    msgs[1].flags=I2C_M_RD; //write
-    msgs[1].len= 4;
-    msgs[1].buf= rbuf;
-
-    sht2x_data.nmsgs= 2;
-    sht2x_data.msgs= msgs;
-
-    if( ioctl(s_sht2x_fd, I2C_RDWR, &sht2x_data) < 0 )
-    {
-        log_error("sht2x I2C_RDWR ioctl failure: %s\n", strerror(errno));
-        sht2x_term();
-        return -2;
-    }
-
-    serialnumber[1]=rbuf[0]; /* Read SNC_1 */
-    serialnumber[0]=rbuf[1]; /* Read SNC_0 */
-    serialnumber[7]=rbuf[2]; /* Read SNA_1 */
-    serialnumber[6]=rbuf[3]; /* Read SNA_0 */
-
-    //dump_buf("SHT2x Serial number: ", serialnumber, 8);
-
-    return 0;
-}
-
-
-int sht2x_get_temp_humidity(float *temp, float *rh)
-{
-    struct i2c_msg               msg;
-    struct i2c_rdwr_ioctl_data   sht2x_data;
-    uint8_t                      buf[4];
-
-    if( !temp || !rh )
-    {
-        log_error("Invalid input arguments\n");
-        return -1;
-    }
-
-    if( s_sht2x_fd < 0 )
-    {
-        if( sht2x_init() < 0)
-        {
-            log_error("SHT2x initialise failure\n");
-            return -2;
-        }
-    }
-
-    /*+------------------------------------------+
-     *|       measure and get temperature        |
-     *+------------------------------------------+*/
-
-    msg.addr= 0x40;
-    msg.flags=0; //write
-    msg.len= 1;
-    msg.buf= buf;
-    msg.buf[0]=TRIGGER_TEMPERATURE_NO_HOLD;  /* trigger temperature without hold I2C bus */
-
-    sht2x_data.nmsgs= 1;
-    sht2x_data.msgs= &msg;
-
-    if( ioctl(s_sht2x_fd, I2C_RDWR, &sht2x_data) < 0 )
-    {
-        log_error("sht2x I2C_RDWR ioctl failure: %s\n", strerror(errno));
-        sht2x_term();
-        return -2;
-    }
-
-    msleep(85);
-
-    memset(buf, 0, sizeof(buf));
-    msg.addr=0x40;
-    msg.flags=I2C_M_RD; //write
-    msg.len= 3;
-    msg.buf= buf;
-
-    sht2x_data.nmsgs= 1;
-    sht2x_data.msgs= &msg;
-
-    if( ioctl(s_sht2x_fd, I2C_RDWR, &sht2x_data) < 0 )
-    {
-        log_error("sht2x I2C_RDWR ioctl failure: %s\n", strerror(errno));
-        sht2x_term();
-        return -2;
-    }
-
-    //dump_buf("Temperature sample data: ", buf, 3);
-    *temp = 175.72 * (((((int) buf[0]) << 8) + buf[1]) / 65536.0) - 46.85;
-
-
-    /*+------------------------------------------+
-     *|    measure and get relative humidity     |
-     *+------------------------------------------+*/
-
-    msg.addr= 0x40;
-    msg.flags=0; //write
-    msg.len= 1;
-    msg.buf= buf;
-    msg.buf[0]=TRIGGER_HUMIDITY_NO_HOLD;  /* trigger humidity without hold I2C bus */
-
-    sht2x_data.nmsgs= 1;
-    sht2x_data.msgs= &msg;
-
-    if( ioctl(s_sht2x_fd, I2C_RDWR, &sht2x_data) < 0 )
-    {
-        log_error("sht2x I2C_RDWR ioctl failure: %s\n", strerror(errno));
-        sht2x_term();
-        return -2;
-    }
-
-    msleep(29);
-
-    memset(buf, 0, sizeof(buf));
-    msg.addr=0x40;
-    msg.flags=I2C_M_RD; //write
-    msg.len= 3;
-    msg.buf= buf;
-
-    sht2x_data.nmsgs= 1;
-    sht2x_data.msgs= &msg;
-
-    if( ioctl(s_sht2x_fd, I2C_RDWR, &sht2x_data) < 0 )
-    {
-        log_error("sht2x I2C_RDWR ioctl failure: %s\n", strerror(errno));
-        sht2x_term();
-        return -2;
-    }
-
-    //dump_buf("Relative humidity sample data: ", buf, 3);
-    *rh = 125 * (((((int) buf[0]) << 8) + buf[1]) / 65536.0) - 6;
-
-    return 0;
-}
-
-#endif
-
diff --git a/project/lightd/hal/sht20.h b/project/lightd/hal/sht20.h
deleted file mode 100644
index e327105..0000000
--- a/project/lightd/hal/sht20.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*********************************************************************************
- *      Copyright:  (C) 2018 LingYun IoT System Studio
- *                  All rights reserved.
- *
- *       Filename:  sht20.c
- *    Description:  This file is temperature and relative humidity sensor SHT20 code
- *
- *        Version:  1.0.0(2018/10/14)
- *         Author:  Guo Wenxue <guowenxue@gmail.com>
- *      ChangeLog:  1, Release initial version on "2018/10/14 12:13:26"
- *
- ********************************************************************************/
-#ifndef __SHT20_H
-#define __SHT20_H
-
-#include <stdio.h>
-#include <stdint.h>
-#include <time.h>
-
-#define SOFTRESET                        0xFE
-#define TRIGGER_TEMPERATURE_NO_HOLD      0xF3
-#define TRIGGER_HUMIDITY_NO_HOLD         0xF5
-
-//#define I2C_API_IOCTL  /* Use I2C userspace driver ioctl API */
-#define I2C_API_RDWR /* Use I2C userspace driver read/write API */
-
-int sht2x_init(void);
-int sht2x_get_serialnumber(uint8_t *serialnumber, int size);
-int sht2x_get_temp_humidity(float *temp, float *rh);
-void sht2x_term(void);
-
-#endif
-
diff --git a/project/lightd/hal/tsl2561.c b/project/lightd/hal/tsl2561.c
index 2a8dcb6..b912433 100644
--- a/project/lightd/hal/tsl2561.c
+++ b/project/lightd/hal/tsl2561.c
@@ -1,14 +1,23 @@
 /*********************************************************************************
- *      Copyright:  (C) 2019 LingYun IoT System Studio
+ *      Copyright:  (C) 2023 LingYun IoT System Studio
  *                  All rights reserved.
  *
  *       Filename:  tsl2561.c
- *    Description:  This file is the Lux sensor TSL2561 API functions on RaspberryPi,
- *                  which connected to I2C-1
+ *    Description:  This file is the Lux sensor TSL2561 code
  *
- *        Version:  1.0.0(04/07/19)
+ *        Version:  1.0.0(10/08/23)
  *         Author:  Guo Wenxue <guowenxue@gmail.com>
- *      ChangeLog:  1, Release initial version on "04/07/19 17:39:38"
+ *      ChangeLog:  1, Release initial version on "10/08/23 17:52:00"
+ *
+ * Pin connection:
+ *              TSL2561 Module           Raspberry Pi Board
+ *                   VCC      <----->      #Pin1(3.3V)
+ *                   SDA0     <----->      #Pin27(SDA, BCM GPIO0)
+ *                   SCL0     <----->      #Pin28(SCL, BCM GPIO1)
+ *                   GND      <----->      GND
+ *
+ * /boot/config.txt:
+ *                  dtoverlay=i2c0,pins_0_1
  *
  ********************************************************************************/
 
@@ -17,57 +26,52 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <math.h>
-#include <errno.h>
 #include <time.h>
-
+#include <errno.h>
+#include <libgen.h>
+#include <getopt.h>
+#include <fcntl.h>
 #include <sys/ioctl.h>
 #include <linux/i2c.h>
 #include <linux/i2c-dev.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <fcntl.h>
 
-#include "logger.h"
 #include "util_proc.h"
+#include "logger.h"
 #include "tsl2561.h"
 
-int s_tsl_fd = -1;
+
+#define CONTROL_REG                     0x80
+#define REG_COUNT                       4
+
+#define POWER_UP                        0x03
+#define POWER_DOWN                      0x00
+
+#define OFF                             0
+#define ON                              1
+
+/* Register Address  */
+enum
+{
+    /* Channel_0 = DATA0HIGH<<8 + DATA0LOW */
+    DATA0LOW = 0x8C,
+    DATA0HIGH,
+
+    /* Channel_1 = DATA1HIGH<<8 + DATA1LOW */
+    DATA1LOW,
+    DATA1HIGH,
+};
 
 static const int  regs_addr[REG_COUNT]={DATA0LOW, DATA0HIGH, DATA1LOW, DATA1HIGH};
 
-int tsl2561_init(void)
-{
-    if(s_tsl_fd > 0)
-        return 0;
-
-    if( (s_tsl_fd=open("/dev/i2c-1", O_RDWR)) < 0)
-    {
-        log_error("TSL2561 I2C device setup failure: %s\n", strerror(errno));
-        return -1;
-    }
-
-    log_debug("TSL2561 initialise ok, s_tsl_fd=%d\n", s_tsl_fd);
-    return s_tsl_fd;
-}
-
-void tsl2561_term(void)
-{
-    close(s_tsl_fd);
-    s_tsl_fd = -1;
-    log_warn("Terminate TSL2561.\n");
-}
-
-
-#define ON          1
-#define OFF         0
-
-int tsl2561_power(int cmd)
+void tsl2561_power(int fd, int cmd)
 {
     struct i2c_msg               msg;
     struct i2c_rdwr_ioctl_data   data;
     unsigned char                buf[2];
 
-    msg.addr= TSL2561_I2C_ADDR;
+    msg.addr= TSL2561_I2CADDR;
     msg.flags=0;  /* write */
     msg.len= 1;
     msg.buf= buf;
@@ -76,10 +80,10 @@
     data.msgs= &msg;
 
     msg.buf[0]=CONTROL_REG;
-    if( ioctl(s_tsl_fd, I2C_RDWR, &data) < 0 )
+    if( ioctl(fd, I2C_RDWR, &data) < 0 )
     {
         log_error("%s() ioctl failure: %s\n", __func__, strerror(errno));
-        return -1;
+        return ;
     }
 
 
@@ -88,22 +92,22 @@
     else
         msg.buf[0]=POWER_DOWN;
 
-    if( ioctl(s_tsl_fd, I2C_RDWR, &data) < 0 )
+    if( ioctl(fd, I2C_RDWR, &data) < 0 )
     {
         log_error("%s() ioctl failure: %s\n", __func__, strerror(errno));
-        return -1;
+        return ;
     }
 
-    return 0;
+    return ;
 }
 
-int tsl2561_readreg(unsigned char regaddr, unsigned char *regval)
+int tsl2561_readreg(int fd, unsigned char regaddr, unsigned char *regval)
 {
     struct i2c_msg               msg;
     struct i2c_rdwr_ioctl_data   data;
     unsigned char                buf[2];
 
-    msg.addr= TSL2561_I2C_ADDR;
+    msg.addr= TSL2561_I2CADDR;
     msg.flags=0;  /* write */
     msg.len= 1;
     msg.buf= buf;
@@ -112,7 +116,7 @@
     data.nmsgs= 1;
     data.msgs= &msg;
 
-    if( ioctl(s_tsl_fd, I2C_RDWR, &data) < 0 )
+    if( ioctl(fd, I2C_RDWR, &data) < 0 )
     {
         log_error("%s() ioctl failure: %s\n", __func__, strerror(errno));
         return -1;
@@ -120,7 +124,7 @@
 
     memset(buf, 0, sizeof(buf));
 
-    msg.addr= TSL2561_I2C_ADDR;
+    msg.addr= TSL2561_I2CADDR;
     msg.flags=I2C_M_RD;  /* read */
     msg.len= 1;
     msg.buf= buf;
@@ -128,7 +132,7 @@
     data.nmsgs= 1;
     data.msgs= &msg;
 
-    if( ioctl(s_tsl_fd, I2C_RDWR, &data) < 0 )
+    if( ioctl(fd, I2C_RDWR, &data) < 0 )
     {
         log_error("%s() ioctl failure: %s\n", __func__, strerror(errno));
         return -1;
@@ -138,28 +142,39 @@
     return 0;
 }
 
-
-
-float tsl2561_get_lux(void)
+int tsl2561_get_lux(float *lux)
 {
-    int                 i;
-    unsigned char       reg_data[REG_COUNT];
+    int                 i, fd;
+    int                 rv = 0;
+    char               *dev = TSL2561_I2CDEV;
+    float               div = 0.0;
 
+    unsigned char       reg_data[REG_COUNT];
     int                 chn0_data = 0;
     int                 chn1_data = 0;
 
-    float               div = 0.0;
-    float               lux = 0.0;
+    if( !lux )
+    {
+        log_error("Invalid input arguments\n");
+        return -1;
+    }
 
+    if( (fd=open(dev, O_RDWR)) < 0)
+    {
+        log_error("i2c device '%s' open failed: %s\n", dev, strerror(errno));
+        return -2;
+    }
 
-    tsl2561_power(ON);
+    tsl2561_power(fd, ON);
 
     msleep(410);  /* t(CONV) MAX 400ms */
 
     /* Read register Channel0 and channel1 data from register */
     for(i=0; i<REG_COUNT; i++)
     {
-        tsl2561_readreg(regs_addr[i], &reg_data[i]);
+        rv = tsl2561_readreg(fd, regs_addr[i], &reg_data[i]);
+        if( rv < 0)
+            goto failed;
     }
 
     chn0_data = reg_data[1]*256 + reg_data[0]; /* Channel0 = DATA0HIGH<<8 + DATA0LOW  */
@@ -167,32 +182,31 @@
 
     if( chn0_data<=0 || chn1_data<0 )
     {
-        lux = 0.0;
-        goto OUT;
+        rv = -2;
+        goto cleanup;
     }
 
     div = (float)chn1_data / (float)chn0_data;
 
     if( div>0 && div<=0.5 )
-        lux = 0.304*chn0_data-0.062*chn0_data*pow(div,1.4);
+        *lux = 0.304*chn0_data-0.062*chn0_data*pow(div,1.4);
 
     else if( div>0.5 && div<=0.61 )
-        lux = 0.0224*chn0_data-0.031*chn1_data;
+        *lux = 0.0224*chn0_data-0.031*chn1_data;
 
     else if( div>0.61 && div<=0.8 )
-        lux = 0.0128*chn0_data-0.0153*chn1_data;
+        *lux = 0.0128*chn0_data-0.0153*chn1_data;
 
     else if( div>0.8 && div<=1.3 )
-        lux = 0.00146*chn0_data-0.00112*chn1_data;
+        *lux = 0.00146*chn0_data-0.00112*chn1_data;
 
     else if( div>1.3 )
-        lux = 0.0;
+        *lux = 0.0;
 
-    log_debug("TSLl2561 get lux: %.3f\n", lux);
+cleanup:
+    tsl2561_power(fd, OFF);
 
-OUT:
-    tsl2561_power(OFF);
-    return lux;
+failed:
+    close(fd);
+    return rv;
 }
-
-
diff --git a/project/lightd/hal/tsl2561.h b/project/lightd/hal/tsl2561.h
index 3a92a6a..540a0bd 100644
--- a/project/lightd/hal/tsl2561.h
+++ b/project/lightd/hal/tsl2561.h
@@ -1,42 +1,34 @@
-/********************************************************************************
- *      Copyright:  (C) 2019 LingYun IoT System Studio
+/*********************************************************************************
+ *      Copyright:  (C) 2023 LingYun IoT System Studio
  *                  All rights reserved.
  *
  *       Filename:  tsl2561.h
- *    Description:  This head file is the Lux sensor TSL2561 API functions on RaspberryPi
+ *    Description:  This file is the Lux sensor TSL2561 code
  *
- *        Version:  1.0.0(04/07/19)
+ *        Version:  1.0.0(10/08/23)
  *         Author:  Guo Wenxue <guowenxue@gmail.com>
- *      ChangeLog:  1, Release initial version on "04/07/19 17:42:35"
+ *      ChangeLog:  1, Release initial version on "10/08/23 17:52:00"
+ *
+ * Pin connection:
+ *              TSL2561 Module           Raspberry Pi Board
+ *                   VCC      <----->      #Pin1(3.3V)
+ *                   SDA0     <----->      #Pin27(SDA, BCM GPIO0)
+ *                   SCL0     <----->      #Pin28(SCL, BCM GPIO1)
+ *                   GND      <----->      GND
+ *
+ * /boot/config.txt:
+ *                  dtoverlay=i2c0,pins_0_1
  *
  ********************************************************************************/
 
 #ifndef  _TSL2561_H_
 #define  _TSL2561_H_
 
-#define TSL2561_I2C_ADDR                0x39
+#define TSL2561_I2CDEV                 "/dev/i2c-0"
+#define TSL2561_I2CADDR                 0x39
 
-#define CONTROL_REG                     0x80
-#define REG_COUNT                       4
-
-#define POWER_UP                        0x03
-#define POWER_DOWN                      0x00
-
-/* Register Address  */
-enum
-{
-    /* Channel_0 = DATA0HIGH<<8 + DATA0LOW */
-    DATA0LOW = 0x8C,
-    DATA0HIGH,
-
-    /* Channel_1 = DATA1HIGH<<8 + DATA1LOW */
-    DATA1LOW,
-    DATA1HIGH,
-};
-
-extern int tsl2561_init(void);
-extern void tsl2561_term(void);
-extern float tsl2561_get_lux(void);
+extern int tsl2561_get_lux(float *lux);
 
 #endif   /* ----- #ifndef _TSL2561_H_  ----- */
 
+
diff --git a/project/lightd/lightd.c b/project/lightd/lightd.c
new file mode 100644
index 0000000..3e70513
--- /dev/null
+++ b/project/lightd/lightd.c
@@ -0,0 +1,378 @@
+/*********************************************************************************
+ *      Copyright:  (C) 2019 LingYun IoT System Studio
+ *                  All rights reserved.
+ *
+ *       Filename:  main.c
+ *    Description:  This file
+ *
+ *        Version:  1.0.0(29/01/19)
+ *         Author:  Guo Wenxue <guowenxue@gmail.com>
+ *      ChangeLog:  1, Release initial version on "29/01/19 15:34:41"
+ *
+ ********************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <getopt.h>
+#include <libgen.h>
+#include <string.h>
+#include <errno.h>
+
+#include <mosquitto.h>
+#include <cjson/cJSON.h>
+
+#include "logger.h"
+#include "util_proc.h"
+#include "config.h"
+#include "tsl2561.h"
+
+#define PROG_VERSION               "v1.0.0"
+#define DAEMON_PIDFILE             "/tmp/.lightd.pid"
+
+int check_sample_time(time_t *last_time, int interval);
+void *thingsboard_subsciber(void *args);
+void *thingsboard_publisher(void *args);
+
+static void program_usage(char *progname)
+{
+
+    printf("Usage: %s [OPTION]...\n", progname);
+    printf(" %s is LingYun studio MQTT daemon program running on RaspberryPi\n", progname);
+
+    printf("\nMandatory arguments to long options are mandatory for short options too:\n");
+    printf(" -b[daemon  ]  Running in daemon mode\n");
+    printf(" -d[debug   ]  Running in debug mode\n");
+    printf(" -c[conf    ]  Specify configure file\n");
+    printf(" -h[help    ]  Display this help information\n");
+    printf(" -v[version ]  Display the program version\n");
+
+    printf("\n%s version %s\n", progname, PROG_VERSION);
+    return;
+}
+
+int main (int argc, char **argv)
+{
+    int                daemon = 0;
+    char               *conf_file="/etc/lightd.conf";
+    int                debug = 0;
+    int                opt;
+    char              *progname=NULL;
+    pthread_t          tid;
+
+    int                rv;
+    float              lux = 0.0;
+    time_t             last_time = 0;
+    iotd_ctx_t         ctx;
+    hwinfo_t          *hwinfo = &ctx.hwinfo;
+
+    struct option long_options[] = {
+        {"conf", required_argument, NULL, 'c'},
+        {"daemon", no_argument, NULL, 'b'},
+        {"debug", no_argument, NULL, 'd'},
+        {"version", no_argument, NULL, 'v'},
+        {"help", no_argument, NULL, 'h'},
+        {NULL, 0, NULL, 0}
+    };
+
+    progname = (char *)basename(argv[0]);
+
+    /* parser the command line parameters */
+    while ((opt = getopt_long(argc, argv, "c:bdvh", long_options, NULL)) != -1)
+    {
+        switch (opt)
+        {
+            case 'c': /* Set configure file */
+                conf_file = optarg;
+                break;
+
+            case 'b': /* Set daemon running */
+                daemon = 1;
+                break;
+
+            case 'd': /* Set debug running */
+                debug = 1;
+                break;
+
+            case 'v':  /* Get software version */
+                printf("%s version %s\n", progname, PROG_VERSION);
+                return 0;
+
+            case 'h':  /* Get help information */
+                program_usage(progname);
+                return 0;
+
+            default:
+                break;
+        }
+
+    }
+
+    /* parser configure file */
+    if( parser_conf(conf_file, &ctx, debug)<0 )
+    {
+        fprintf(stderr, "Parser thingsboard configure file failure\n");
+        return -2;
+    }
+
+    /* install signal proc handler */
+    install_default_signal();
+
+    /* check program already running or not, if already running then exit, or set running as daemon */
+    if( check_set_program_running(daemon, DAEMON_PIDFILE) < 0 )
+        goto cleanup;
+
+    /* initial mosquitto library */
+    mosquitto_lib_init();
+
+    /* initial gpio hardware */
+    gpio_init(&hwinfo->gpio);
+
+    /*
+     * +--------------------------------+
+     * |    MQTT Subscriber Thread      |
+     * +--------------------------------+
+     */
+    if( thread_start(&tid, thingsboard_subsciber, &ctx.mqtt ) < 0 )
+    {
+        log_error("Start MQTT subsciber worker thread failure\n");
+        goto cleanup;
+    }
+    log_info("Start MQTT subsciber worker thread ok\n");
+
+    /*
+     * +--------------------------------+
+     * |   Auto Light Control Thread    |
+     * +--------------------------------+
+     */
+
+    log_info("Auto light control thread start\n");
+    while( ! g_signal.stop )
+    {
+        /* TSL2561 update lux in every 5 minutes  */
+        if(check_sample_time(&last_time, 300))
+        {
+            if( tsl2561_get_lux(&lux) < 0 )
+            {
+                log_error("TSL2561 sample Lux failed\n");
+                lux = hwinfo->lux_threshold + 100.0;
+            }
+
+            if( lux > hwinfo->lux_threshold )
+                log_info("Lux[%.3f] > Treshold[%.3f], don't auto light\n", lux, hwinfo->lux_threshold);
+            else
+                log_info("Lux[%.3f] <= Treshold[%.3f], need auto light\n", lux, hwinfo->lux_threshold);
+        }
+
+        if( lux > hwinfo->lux_threshold )
+        {
+            sleep(1);
+            continue;
+        }
+
+        rv = infrared_detect();
+        if( rv != 0 )
+        {
+            log_warn("Someone incoming detected by %s infrared\n", rv&FLAG_INFRARED_INDOOR?"indoor":"hallway");
+
+            turn_light("indoor", ON);
+            turn_light("hallway", ON);
+
+            sleep(hwinfo->light_intval);
+
+            turn_light("indoor", ON);
+            turn_light("hallway", ON);
+        }
+
+        msleep(100);
+    }
+
+cleanup:
+    mosquitto_lib_cleanup();
+    log_close();
+
+    return 0;
+}
+
+int check_sample_time(time_t *last_time, int interval)
+{
+    int                  need = 0; /* no need sample now */
+    time_t               now;
+
+    time(&now);
+
+    if( difftime(now, *last_time)>interval )
+    {
+        need = 1; /* need sample now  */
+        *last_time = now;
+    }
+
+    return need;
+}
+
+void sub_connect_callback(struct mosquitto *mosq, void *userdata, int result)
+{
+    mqtt_ctx_t             *ctx = (mqtt_ctx_t *)userdata;
+
+    if( result )
+    {
+        log_error("Subscriber connect to broker server failed, rv=%d\n", result);
+        return ;
+    }
+
+    log_info("Subscriber connect to broker server[%s:%d] successfully\n", ctx->host, ctx->port);
+    mosquitto_subscribe(mosq, NULL, ctx->subTopic, ctx->subQos);
+}
+
+void sub_disconnect_callback(struct mosquitto *mosq, void *userdata, int result)
+{
+    mqtt_ctx_t             *ctx = (mqtt_ctx_t *)userdata;
+
+    log_warn("Subscriber disconnect to broker server[%s:%d], reason=%d\n", ctx->host, ctx->port, result);
+}
+
+void proc_json_items(cJSON *root, mqtt_ctx_t *ctx)
+{
+    cJSON *item_method;
+    cJSON *item_params;
+    cJSON *item_device;
+    cJSON *item_status;
+
+    char *method;
+    char *device;
+    int status;
+
+    /* 获取 method 字段 */
+    item_method = cJSON_GetObjectItem(root, "method");
+    if (item_method == NULL || !cJSON_IsString(item_method))
+    {
+        log_error("JSON missing method\n");
+        return;
+    }
+    method = item_method->valuestring;
+
+    /* 只处理 setValue 命令 */
+    if (strcmp(method, "setValue") != 0)
+    {
+        log_error("Ignore method: %s\n", method);
+        return;
+    }
+
+    /* 获取 params 对象 */
+    item_params = cJSON_GetObjectItem(root, "params");
+    if (item_params == NULL || !cJSON_IsObject(item_params))
+    {
+        log_error("JSON missing params\n");
+        return;
+    }
+
+    /* 获取 params.device */
+    item_device = cJSON_GetObjectItem(item_params, "device");
+    if (item_device == NULL || !cJSON_IsString(item_device))
+    {
+        log_error("JSON missing params.device\n");
+        return;
+    }
+    device = item_device->valuestring;
+
+    /* 获取 params.status (布尔值) */
+    item_status = cJSON_GetObjectItem(item_params, "status");
+    if (item_status == NULL || !(cJSON_IsBool(item_status)))
+    {
+        log_error("JSON missing params.status\n");
+        return;
+    }
+    status = cJSON_IsTrue(item_status) ? ON : OFF;
+
+    log_info("parser JSON message to control '%s' status '%d'\n", device, status);
+
+    /* 映射 Light 名称并调用控制函数 */
+    if ( strstr(device, "Indoor") || strstr(device, "indoor"))
+    {
+        turn_light("indoor", status);
+    }
+    else if ( strstr(device, "Hallway") || strstr(device, "hallway") )
+    {
+        turn_light("hallway", status);
+    }
+
+    return;
+}
+
+void sub_message_callback(struct mosquitto *mosq, void *userdata, const struct mosquitto_message *message)
+{
+    mqtt_ctx_t             *ctx = (mqtt_ctx_t *)userdata;
+
+    cJSON                  *root = NULL;
+
+    if ( !message->payloadlen )
+    {
+        log_error("%s (null)\n", message->topic);
+        return ;
+    }
+
+    log_info("Subscriber receive message: '%s'\n", message->payload);
+
+    root = cJSON_Parse(message->payload);
+    if( !root )
+    {
+        log_error("cJSON_Parse parser failure: %s\n", cJSON_GetErrorPtr());
+        return ;
+    }
+
+    proc_json_items(root, ctx);
+
+    /* must delete it, or it will result memory leak */
+    cJSON_Delete(root);
+
+    return ;
+}
+
+void *thingsboard_subsciber(void *args)
+{
+    mqtt_ctx_t             *ctx = (mqtt_ctx_t *)args;
+    struct mosquitto       *mosq;
+    bool                    session = true;
+
+    mosq = mosquitto_new(ctx->devid, session, ctx);
+    if( !mosq )
+    {
+        log_error("mosquitto_new failure\n");
+        return NULL;
+    }
+
+    /* connnect to broker by token or uid/pwd */
+    if( strlen(ctx->token ) > 0)
+    {
+        log_info("Using token authentication\n");
+        mosquitto_username_pw_set(mosq, ctx->token, NULL);
+    }
+    else if( strlen(ctx->uid)> 0  && strlen(ctx->pwd)> 0 )
+    {
+        log_info("Using username/password authentication\n");
+        mosquitto_username_pw_set(mosq, ctx->uid, ctx->pwd);
+    }
+
+    /* set callback functions */
+    mosquitto_connect_callback_set(mosq, sub_connect_callback);
+    mosquitto_disconnect_callback_set(mosq, sub_disconnect_callback);
+    mosquitto_message_callback_set(mosq, sub_message_callback);
+
+    while( !g_signal.stop )
+    {
+        /* connect to MQTT broker  */
+        if( mosquitto_connect(mosq, ctx->host, ctx->port, ctx->keepalive) )
+        {
+            log_error("Subscriber connect to broker[%s:%d] failure: %s\n", ctx->host, ctx->port, strerror(errno));
+            msleep(1000);
+            continue;
+        }
+
+        /* -1: use default timeout 1000ms  1: unused */
+        mosquitto_loop_forever(mosq, -1, 1);
+    }
+
+    mosquitto_destroy(mosq);
+    return NULL;
+}
+
diff --git a/project/lightd/main.c b/project/lightd/main.c
deleted file mode 100644
index c72ecce..0000000
--- a/project/lightd/main.c
+++ /dev/null
@@ -1,223 +0,0 @@
-/*********************************************************************************
- *      Copyright:  (C) 2019 LingYun IoT System Studio
- *                  All rights reserved.
- *
- *       Filename:  main.c
- *    Description:  This is the lux/relay/infrared auto light program
- *
- *        Version:  1.0.0(29/01/19)
- *         Author:  Guo Wenxue <guowenxue@gmail.com>
- *      ChangeLog:  1, Release initial version on "29/01/19 15:34:41"
- *
- ********************************************************************************/
-#include <stdio.h>
-#include <time.h>
-#include <unistd.h>
-#include <getopt.h>
-#include <libgen.h>
-#include <string.h>
-#include <math.h>
-
-#include <cjson/cJSON.h>
-#include <mosquitto.h>
-
-#include "util_proc.h"
-#include "logger.h"
-#include "hal.h"
-
-#include "conf.h"
-#include "mqtt.h"
-
-#define PROG_VERSION               "v1.0.0"
-#define DAEMON_PIDFILE             "/tmp/.iotd.pid"
-
-void control_thread_loop(void *args);
-
-static void program_usage(char *progname)
-{
-    printf("Usage: %s [OPTION]...\n", progname);
-    printf(" %s is LingYun studio MQTT daemon program running on RaspberryPi\n", progname);
-
-    printf("\nMandatory arguments to long options are mandatory for short options too:\n");
-    printf(" -d[debug   ]  Running in debug mode\n");
-    printf(" -c[conf    ]  Specify configure file\n");
-    printf(" -h[help    ]  Display this help information\n");
-    printf(" -v[version ]  Display the program version\n");
-
-    printf("\n%s version %s\n", progname, PROG_VERSION);
-    return;
-}
-
-int main (int argc, char **argv)
-{
-    int                daemon = 1;
-    pthread_t          tid;
-    iotd_ctx_t         ctx;
-    hal_ctx_t         *hal_ctx = &ctx.hal_ctx;
-    char               *conf_file="/etc/iotd.conf";
-    int                debug = 0;
-    int                opt;
-    char              *progname=NULL;
-
-    struct option long_options[] = {
-        {"conf", required_argument, NULL, 'c'},
-        {"debug", no_argument, NULL, 'd'},
-        {"version", no_argument, NULL, 'v'},
-        {"help", no_argument, NULL, 'h'},
-        {NULL, 0, NULL, 0}
-    };
-
-    progname = (char *)basename(argv[0]);
-
-    /* Parser the command line parameters */
-    while ((opt = getopt_long(argc, argv, "c:dvh", long_options, NULL)) != -1)
-    {
-        switch (opt)
-        {
-            case 'c': /* Set configure file */
-                conf_file = optarg;
-                break;
-
-            case 'd': /* Set debug running */
-                daemon = 0;
-                debug = 1;
-                break;
-
-            case 'v':  /* Get software version */
-                printf("%s version %s\n", progname, PROG_VERSION);
-                return 0;
-
-            case 'h':  /* Get help information */
-                program_usage(progname);
-                return 0;
-
-            default:
-                break;
-        }
-
-    }
-
-
-    if( !conf_file )
-        debug = 1;
-
-    if( parser_conf(conf_file, &ctx, debug)<0 )
-    {
-        fprintf(stderr, "Parser mqtted configure file failure\n");
-        return -2;
-    }
-
-
-    if( hal_init(hal_ctx) < 0 )
-    {
-        log_error("Initialise hardware failure\n");
-        return -3;
-    }
-    log_info("Initialise hardware okay.\n");
-
-
-    install_default_signal();
-    if( check_set_program_running(daemon, DAEMON_PIDFILE) < 0 )
-        goto OUT;
-
-
-    mosquitto_lib_init();
-
-    /*+--------------------------------------------+
-     *|  Start  MQTT subsciber thread if enable    |
-     *+--------------------------------------------+*/
-    if( ctx.mqtt_ctx.sub_enable )
-    {
-        if( thread_start(&tid, mqtt_sub_worker, &ctx ) < 0 )
-        {
-            log_error("Start MQTT subsciber worker thread failure\n");
-            goto OUT;
-        }
-        else
-        {
-            log_info("Start MQTT subsciber worker thread ok\n");
-        }
-    }
-
-    /*+--------------------------------------------+
-     *|  Start  MQTT publisher thread if enable    |
-     *+--------------------------------------------+*/
-    if( ctx.mqtt_ctx.pub_enable )
-    {
-        if( thread_start(&tid, mqtt_pub_worker, &ctx ) < 0 )
-        {
-            log_error("Start MQTT publisher worker thread failure\n");
-            goto OUT;
-        }
-        else
-        {
-            log_info("Start MQTT publisher worker thread ok\n");
-        }
-    }
-
-    /*+--------------------------------------------+
-     *|      Control thread start dead loop        |
-     *+--------------------------------------------+*/
-    control_thread_loop(&ctx);
-
-OUT:
-    mosquitto_lib_cleanup();
-    hal_term(hal_ctx);
-    log_close();
-
-    return 0;
-} /* ----- End of main() ----- */
-
-
-void control_thread_loop(void *args)
-{
-    iotd_ctx_t            *ctx = (iotd_ctx_t *)args;
-    hal_ctx_t             *hal_ctx;
-    float                  lux = 0.0;
-    int                    rv;
-
-    hal_ctx = &ctx->hal_ctx;
-
-    log_debug("infrared configured [%d], lux configured [%d]\n", hal_ctx->gpio.infrared_enable, hal_ctx->lux_enable);
-
-    while( ! g_signal.stop )
-    {
-        if( hal_ctx->gpio.infrared_enable )
-        {
-            if( hal_ctx->lux_enable )
-            {
-                lux = tsl2561_get_lux();
-
-                log_debug("TSL2561 get Lux[%.3f] Treshold[%.3f].\n", lux, hal_ctx->lux_threshold);
-
-                if( lux > hal_ctx->lux_threshold )
-                {
-                    log_info("Lux[%.3f] > Treshold[%.3f], don't need light on and sleep now.\n", lux, hal_ctx->lux_threshold);
-                    if( hal_ctx->gpio.light_intval > 0)
-                        sleep( hal_ctx->gpio.light_intval );
-                    else
-                        sleep(30);
-
-                    continue;
-                }
-            }
-
-            rv = infrared_detect();
-            if( rv & FLAG_INFRARED_INDOOR )
-            {
-                log_info("Someone incoming detected by indoor infrared\n");
-                thread_start(NULL, light_on_worker, "indoor" );
-            }
-
-            if( rv & FLAG_INFRARED_HALLWAY )
-            {
-                log_info("Someone incoming detected by hallway infrared\n");
-                thread_start(NULL, light_on_worker, "hallway" );
-            }
-        }
-
-        msleep(100);
-    }
-}
-
-
diff --git a/project/lightd/makefile b/project/lightd/makefile
index 3797387..2920afa 100644
--- a/project/lightd/makefile
+++ b/project/lightd/makefile
@@ -12,7 +12,7 @@
 #*******************************************************************************
 
 PRJ_PATH=$(shell pwd)
-APP_NAME = iotd
+APP_NAME = lightd 
 
 BUILD_ARCH=$(shell uname -m)
 ifneq ($(findstring $(BUILD_ARCH), "x86_64" "i386"),)
@@ -25,8 +25,8 @@
 # common CFLAGS for our source code
 CFLAGS = -Wall -Wshadow -Wundef -Wmaybe-uninitialized -D_GNU_SOURCE
 
-# sub-directory compiled to a library and need to link
-SRCS=src hal booster
+# C source file in sub-directory
+SRCS=booster hal
 SRCS_PATH=$(patsubst %,${PRJ_PATH}/%,$(SRCS))
 CFLAGS+=$(patsubst %,-I%,$(SRCS_PATH))
 LDFLAGS+=$(patsubst %,-L%,$(SRCS_PATH))
@@ -34,20 +34,24 @@
 LDFLAGS+=${LIBS}
 
 # Open source libraries
-LDFLAGS+=-lmosquitto -lgpiod -lcjson -lm
+CFLAGS+=-I ${PRJ_PATH}/openlibs/install/include
+LDFLAGS+=-L ${PRJ_PATH}/openlibs/install/lib
 
-# sub-directory need to entry and compile
-SUBDIR=${SRCS}
+# libraries
+libs=openlibs ${SRCS}
+LDFLAGS+=-lmosquitto -lcjson -lssl -lcrypto -lgpiod -lm
+
+LDFLAGS+=-lpthread
 
 all: entry subdir
-	${CROSS_COMPILE}gcc ${CFLAGS} main.c -o ${APP_NAME} ${LDFLAGS}
+	${CROSS_COMPILE}gcc ${CFLAGS} ${SRCFILES} -o ${APP_NAME} ${LDFLAGS}
 
 entry:
 	@echo "Building ${APP_NAME} on ${BUILD_ARCH}"
 
 subdir:
-	@for dir in ${SUBDIR} ; do if [ ! -e $${dir} ] ; then ln -s ../$${dir}; fi; done
-	@for dir in ${SUBDIR} ;  do make CFLAGS="${CFLAGS}" -C $${dir} ; done
+	@for dir in ${libs} ; do if [ ! -e $${dir} ] ; then ln -s ../$${dir}; fi; done
+	@for dir in ${libs} ;  do CFLAGS="${CFLAGS}" make -C $${dir} ; done
 
 install:
 	cp ${APP_NAME} /tftp
@@ -57,8 +61,8 @@
 	@rm -f ${APP_NAME}
 
 distclean:
-	@for dir in ${SUBDIR} ; do if [ -e $${dir} ] ; then make clean -C $${dir}; fi; done
+	@for dir in ${libs} ; do if [ -e $${dir} ] ; then make clean -C $${dir}; fi; done
+	@for dir in ${libs} ; do if [ -e $${dir} ] ; then unlink $${dir}; fi; done
 	@rm -f ${APP_NAME}
 	@rm -f cscope.* tags
-	@rm -f *.log *.db
 
diff --git a/project/lightd/src/conf.c b/project/lightd/src/conf.c
deleted file mode 100644
index da13d01..0000000
--- a/project/lightd/src/conf.c
+++ /dev/null
@@ -1,309 +0,0 @@
-/*********************************************************************************
- *      Copyright:  (C) 2019 LingYun IoT System Studio
- *                  All rights reserved.
- *
- *       Filename:  conf.c
- *    Description:  This file is iotd configure file parser function
- *
- *        Version:  1.0.0(2019年06月25日)
- *         Author:  Guo Wenxue <guowenxue@gmail.com>
- *      ChangeLog:  1, Release initial version on "2019年06月25日 22时23分55秒"
- *
- ********************************************************************************/
-#include "conf.h"
-#include "logger.h"
-#include "iniparser.h"
-
-enum
-{
-    _TYPE_INPUT,
-    _TYPE_OUTPUT,
-};
-
-/* conf format:  "{light_indoor:6:0},{light_livroomL:13:0},{light_livroomR:19:0},{light_hallway:26:0}"  */
-int parser_gpio_info(int type, gpio_t *gpio, char *conf)
-{
-    char              *ptr;
-    char              *pstart;
-    char              *pend;
-    char               buf[64];
-    int                cnt = 0;
-    int                rv = 0;
-
-    if( !gpio || !conf || strlen(conf)<3 )
-    {
-        log_error("Invalid input arguments.\n");
-        return -1;
-    }
-
-    pstart = strchr(conf, '{');
-    if( !pstart )
-        return 0;
-
-    pend = strchr(pstart, '}');
-
-    while( pstart && pend )
-    {
-        memset(buf, 0, sizeof(buf));
-
-        strncpy(buf, pstart+1, pend-pstart-1);
-
-        /* parser and get the GPIO name, BCM pin number, active power level */
-
-        {
-            /* check GPIO configure name too long or not */
-            ptr = strchr(buf, ':');
-            if( !ptr )
-            {
-                log_error("Found invalid GPIO configure: %s\n", buf);
-                goto NEXT_LOOP;
-            }
-
-            if( ptr-buf > sizeof(gpio->input[cnt].name) )
-            {
-                log_error("Found GPIO name too long\n", buf);
-                goto NEXT_LOOP;
-            }
-
-            /* use sscanf() to parser GPIO configured values */
-            if(_TYPE_INPUT == type )
-            {
-                rv = sscanf(buf, "%[^:]:%d:%d", gpio->input[cnt].name, &gpio->input[cnt].pin, &gpio->input[cnt].active_level);
-                if( 3 == rv)
-                {
-                    log_info("parser GPIO input[%s] BCM[%d] active[%d]\n", gpio->input[cnt].name, gpio->input[cnt].pin, gpio->input[cnt].active_level);
-                    if( strstr(gpio->input[cnt].name, "infrared") )
-                    {
-                        log_info("parser GPIO enable infrared detect\n");
-                        gpio->infrared_enable = 1;
-                    }
-                    cnt++;
-                    gpio->incnt = cnt;
-                }
-                else
-                {
-                    log_error("Found invalid GPIO configure: %s\n", buf);
-                }
-            }
-            else
-            {
-                rv = sscanf(buf, "%[^:]:%d:%d", gpio->output[cnt].name, &gpio->output[cnt].pin, &gpio->output[cnt].active_level);
-                if( 3 == rv)
-                {
-                    log_info("parser GPIO output[%s] BCM[%d] active[%d]\n", gpio->output[cnt].name, gpio->output[cnt].pin, gpio->output[cnt].active_level);
-                    cnt++;
-                    gpio->outcnt = cnt;
-                }
-                else
-                {
-                    log_error("Found invalid GPIO configure: %s\n", buf);
-                }
-            }
-        }
-
-NEXT_LOOP:
-        pstart = strchr(pend, '{');
-        if( pstart )
-            pend = strchr(pstart, '}');
-    }
-
-
-    return gpio->outcnt;
-}
-
-int parser_conf(const char *conf_file, iotd_ctx_t *ctx, int debug)
-{
-    dictionary          *ini;
-    const char          *str;
-    int                  val;
-    log_ctx_t           *log_ctx;
-    hal_ctx_t           *hal_ctx;
-    mqtt_ctx_t          *mqtt_ctx;
-    gpio_t              *gpio;
-
-
-    if( !conf_file || !ctx )
-    {
-        fprintf(stderr, "ERROR: parser configure file or ctx is NULL\n");
-        return 0;
-    }
-
-    memset(ctx, 0, sizeof(*ctx));
-
-    log_ctx = &ctx->log_ctx;
-    hal_ctx = &ctx->hal_ctx;
-    mqtt_ctx = &ctx->mqtt_ctx;
-
-
-    ini = iniparser_load(conf_file);
-    if( !ini )
-    {
-        fprintf(stderr, "ERROR: cannot parse file: '%s'\n", conf_file);
-        return -1;
-    }
-
-
-    /*+------------------------------------------------------+
-     *|    parser logger settings and start logger system    |
-     *+------------------------------------------------------+*/
-    if( !debug )
-    {
-        str = iniparser_getstring(ini, "logger:file", "/tmp/iotd.log");
-        strncpy(log_ctx->logfile, str, sizeof(log_ctx->logfile));
-        log_ctx->logsize = iniparser_getint(ini, "logger:size", 1024);
-        log_ctx->loglevel = iniparser_getint(ini, "logger:level", LOG_LEVEL_DEBUG);
-    }
-    else
-    {
-        strncpy(log_ctx->logfile, "console", sizeof(log_ctx->logfile));
-        log_ctx->loglevel = LOG_LEVEL_DEBUG;
-    }
-
-    if( log_open(log_ctx->logfile, log_ctx->loglevel, log_ctx->logsize, LOG_LOCK_DISABLE) < 0 )
-    {
-        fprintf(stderr, "Logger system initialise failure\n");
-        return -2;
-    }
-
-    log_info("Logger system initialise ok\n");
-
-
-    /*+------------------------------------------------------+
-     *|               parser production ID                   |
-     *+------------------------------------------------------+*/
-
-    if( !(str=iniparser_getstring(ini, "common:id", NULL)) )
-    {
-        log_error("ERROR: parser production ID failure\n");
-        return -2;
-    }
-    /* cJSON parser ID will get ""  */
-    snprintf(mqtt_ctx->id, sizeof(mqtt_ctx->id), "\"%s\"", str);
-    log_info("parser production ID [%s]\n", mqtt_ctx->id);
-
-
-    /*+------------------------------------------------------+
-     *|      parser hardware module configuration ID         |
-     *+------------------------------------------------------+*/
-
-    gpio = &hal_ctx->gpio;
-
-    /* parser GPIO output pins  */
-    if( !(str=iniparser_getstring(ini, "hardware:gpio_outpin", NULL)) )
-    {
-        log_warn("parser no GPIO output pins\n");
-    }
-    else
-    {
-        parser_gpio_info(_TYPE_OUTPUT, gpio, (char *)str);
-        log_info("parser [%d] GPIO output pins configured\n", gpio->outcnt);
-    }
-
-    gpio->light_intval = iniparser_getint(ini, "hardware:light_intval", 20);
-    log_info("parser relay controled light interval time [%d]\n", gpio->light_intval);
-
-    /* parser GPIO input pins  */
-    if( !(str=iniparser_getstring(ini, "hardware:gpio_inpin", NULL)) )
-    {
-        log_warn("parser no GPIO input pins\n");
-    }
-    else
-    {
-        parser_gpio_info(_TYPE_INPUT, gpio, (char *)str);
-        log_info("parser [%d] GPIO input pins\n", gpio->incnt);
-    }
-
-    hal_ctx->lux_enable = iniparser_getint(ini, "hardware:lux", 0);
-    if( hal_ctx->lux_enable )
-    {
-        hal_ctx->lux_threshold = iniparser_getdouble(ini, "hardware:lux_threshold", 0.1);
-        log_info("parser LUX enable and threshold value set be [%.03f]\n", hal_ctx->lux_threshold);
-    }
-
-    hal_ctx->sht2x_enable = iniparser_getint(ini, "hardware:sht2x", 0);
-    if( hal_ctx->sht2x_enable )
-    {
-        log_info("parser SHT2x sensor enabled\n");
-    }
-
-    hal_ctx->ds18b20_enable = iniparser_getint(ini, "hardware:ds18b20", 0);
-    if( hal_ctx->ds18b20_enable )
-    {
-        log_info("parser DS18B20 sensor enabled\n");
-    }
-
-
-    /*+------------------------------------------------------+
-     *|              parser broker settings                  |
-     *+------------------------------------------------------+*/
-
-    if( !(str=iniparser_getstring(ini, "broker:hostname", NULL)) )
-    {
-        log_error("ERROR: Parser broker server hostname failure\n");
-        return -2;
-    }
-    strncpy(mqtt_ctx->host, str, sizeof(mqtt_ctx->host) );
-
-    if( (val=iniparser_getint(ini, "broker:port", -1)) < 0 )
-    {
-        log_error("ERROR: Parser broker server port failure\n");
-        return -2;
-    }
-    mqtt_ctx->port = val;
-    log_info("Parser broker server [%s:%d]\n", mqtt_ctx->host, mqtt_ctx->port);
-
-    str=iniparser_getstring(ini, "broker:username", NULL);
-    strncpy(mqtt_ctx->uid, str, sizeof(mqtt_ctx->uid) );
-
-    str=iniparser_getstring(ini, "broker:password", NULL);
-    strncpy(mqtt_ctx->pwd, str, sizeof(mqtt_ctx->pwd) );
-
-    log_info("Parser broker author by [%s:%s]\n", mqtt_ctx->uid, mqtt_ctx->pwd);
-
-    mqtt_ctx->keepalive = iniparser_getint(ini, "broker:keepalive", 30);
-    log_info("Parser broker keepalive timeout [%d] seconds\n", mqtt_ctx->keepalive);
-
-    /*+------------------------------------------------------+
-     *|             parser subscriber settings               |
-     *+------------------------------------------------------+*/
-
-    if( !(str=iniparser_getstring(ini, "subsciber:subTopic", NULL)) )
-    {
-        log_warn("WARNNING: Parser MQTT subscribe topic failure\n");
-    }
-    else
-    {
-        strncpy(mqtt_ctx->subTopic, str, sizeof(mqtt_ctx->subTopic) );
-        mqtt_ctx->subQos = iniparser_getint(ini, "subsciber:subQos", 0);
-        mqtt_ctx->sub_enable = 1;
-
-        log_info("Parser subscriber topic \"%s\" with Qos[%d]\n", mqtt_ctx->subTopic, mqtt_ctx->subQos);
-    }
-
-    /*+------------------------------------------------------+
-     *|             parser publisher settings                |
-     *+------------------------------------------------------+*/
-
-    if( !(str=iniparser_getstring(ini, "publisher:pubTopic", NULL)) )
-    {
-        log_warn("WARNNING: Parser MQTT publisher topic failure\n");
-        return 0;
-    }
-
-
-    mqtt_ctx->pub_enable = iniparser_getint(ini, "publisher:enable", 0);
-    if( !mqtt_ctx->pub_enable )
-    {
-        log_warn("WARNNING: Parser MQTT publisher disabled\n");
-        return 0;
-    }
-
-    strncpy(mqtt_ctx->pubTopic, str, sizeof(mqtt_ctx->pubTopic) );
-    mqtt_ctx->pubQos = iniparser_getint(ini, "publisher:pubQos", 0);
-    mqtt_ctx->interval = iniparser_getint(ini, "publisher:interval", 60);
-
-    log_info("Parser publisher topic \"%s\" with Qos[%d]\n", mqtt_ctx->pubTopic, mqtt_ctx->pubQos);
-
-    return 0;
-}
-
diff --git a/project/lightd/src/conf.h b/project/lightd/src/conf.h
deleted file mode 100644
index 0c37f03..0000000
--- a/project/lightd/src/conf.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*********************************************************************************
- *      Copyright:  (C) 2019 LingYun IoT System Studio
- *                  All rights reserved.
- *
- *       Filename:  conf.h
- *    Description:  This file is iotd configure file parser function
- *
- *        Version:  1.0.0(2019年06月25日)
- *         Author:  Guo Wenxue <guowenxue@gmail.com>
- *      ChangeLog:  1, Release initial version on "2019年06月25日 22时23分55秒"
- *
- ********************************************************************************/
-#ifndef  __CONF_H_
-#define  __CONF_H_
-
-#include "hal.h"
-#include "mqtt.h"
-
-enum
-{
-    Qos0, /* 发送者只发送一次消息,不进行重试,Broker不会返回确认消息。在Qos0情况下,Broker可能没有接受到消息 */
-    Qos1, /* 发送者最少发送一次消息,确保消息到达Broker,Broker需要返回确认消息PUBACK。在Qos1情况下,Broker可能接受到重复消息 */
-    Qos2, /* Qos2使用两阶段确认来保证消息的不丢失和不重复。在Qos2情况下,Broker肯定会收到消息,且只收到一次  */
-};
-
-
-typedef struct log_ctx_s
-{
-    /* logger settings */
-    char          logfile[128]; /* logger record file */
-    int           loglevel;     /* logger level  */
-    int           logsize;      /* logger file maxsize, oversize will rollback */
-} log_ctx_t;
-
-typedef struct iotd_ctx_s
-{
-    log_ctx_t     log_ctx;
-    hal_ctx_t     hal_ctx;
-    mqtt_ctx_t    mqtt_ctx;
-} iotd_ctx_t;
-
-
-extern int parser_conf(const char *conf_file, iotd_ctx_t *ctx, int debug);
-
-#endif   /* ----- #ifndef _CONF_H_  ----- */
-
diff --git a/project/lightd/src/makefile b/project/lightd/src/makefile
deleted file mode 100644
index 3b18c24..0000000
--- a/project/lightd/src/makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-
-PWD=$(shell pwd )
-
-LIBNAME=$(shell basename ${PWD} )
-TOPDIR=$(shell dirname ${PWD} )
-
-all: clean
-	@rm -f *.o
-	${CROSSTOOL}gcc ${CFLAGS} -I${TOPDIR} -c *.c 
-	${CROSSTOOL}ar -rcs  lib${LIBNAME}.a *.o
-
-clean:
-	@rm -f *.o
-	@rm -f *.a
-
diff --git a/project/lightd/src/mqtt.c b/project/lightd/src/mqtt.c
deleted file mode 100644
index 05707b6..0000000
--- a/project/lightd/src/mqtt.c
+++ /dev/null
@@ -1,329 +0,0 @@
-/********************************************************************************
- *      Copyright:  (C) 2021 LingYun IoT System Studio
- *                  All rights reserved.
- *
- *       Filename:  mqtt.h
- *    Description:  This head file is MQTT subscriber and publisher thread code
- *
- *        Version:  1.0.0(20/04/21)
- *         Author:  Guo Wenxue <guowenxue@gmail.com>
- *      ChangeLog:  1, Release initial version on "20/04/21 15:46:42"
- *
- ********************************************************************************/
-
-#include <string.h>
-#include <math.h>
-#include <cjson/cJSON.h>
-#include <mosquitto.h>
-#include <errno.h>
-
-#include "util_proc.h"
-#include "logger.h"
-#include "hal.h"
-#include "conf.h"
-
-
-/*+-------------------------------------------+
- *|                                           |
- *|    MQTT publisher thread worker code      |
- *|                                           |
- *+-------------------------------------------+*/
-
-
-void pub_connect_callback(struct mosquitto *mosq, void *userdata, int result)
-{
-    iotd_ctx_t             *ctx = (iotd_ctx_t *)userdata;
-    mqtt_ctx_t             *mqtt_ctx;
-    hal_ctx_t              *hal_ctx;
-    int                     rv = 0;
-    char                    msg[128];
-    float                   temp = 0.0; /* temperature */
-    float                   rh = 0.0;   /* relative humidity */
-    int                     retain = 0;
-
-    mqtt_ctx = &ctx->mqtt_ctx;
-    hal_ctx = &ctx->hal_ctx;
-
-
-    if( result )
-    {
-        log_error("Publisher connect to broker server[%s:%d] failed, rv=%d\n", mqtt_ctx->host, mqtt_ctx->port, result);
-        return ;
-    }
-    log_info("Publisher connect to broker server[%s:%d] successfully\n", mqtt_ctx->host, mqtt_ctx->port);
-
-
-    if( hal_ctx->ds18b20_enable )
-    {
-        memset(msg, 0, sizeof(msg));
-
-        if( ds18b20_get_temperature(&temp) < 0 )
-            snprintf(msg, sizeof(msg), "{ \"id\":%s, \"temp\":\"error\" }", mqtt_ctx->id);
-        else
-            snprintf(msg, sizeof(msg), "{ \"id\":%s, \"temp\":\"%.2f\" }", mqtt_ctx->id, temp);
-
-        rv = mosquitto_publish(mosq, NULL, mqtt_ctx->pubTopic, strlen(msg), msg, mqtt_ctx->pubQos, retain);
-        if( rv )
-        {
-            log_error("Publisher broadcast message '%s' failure: %d\n", msg, rv);
-        }
-        else
-        {
-            log_info("Publisher broadcast message '%s' ok\n", msg);
-        }
-    }
-
-    if( hal_ctx->sht2x_enable )
-    {
-        memset(msg, 0, sizeof(msg));
-
-        if( sht2x_get_temp_humidity(&temp, &rh) < 0 )
-            snprintf(msg, sizeof(msg), "{ \"id\":%s, \"temp\":\"error\", \"RH\":\"error\" }", mqtt_ctx->id);
-        else
-            snprintf(msg, sizeof(msg), "{ \"id\":%s, \"temp\":\"%.2f\", \"RH\":\"%.2f\" }", mqtt_ctx->id, temp, rh);
-
-        rv = mosquitto_publish(mosq, NULL, mqtt_ctx->pubTopic, strlen(msg), msg, mqtt_ctx->pubQos, retain);
-        if( rv )
-        {
-            log_error("Publisher broadcast message '%s' failure: %d\n", msg, rv);
-        }
-        else
-        {
-            log_info("Publisher broadcast message '%s' ok\n", msg);
-        }
-    }
-
-
-    log_info("Publisher broadcast over and disconnect broker now\n", mqtt_ctx->host, mqtt_ctx->port);
-    mosquitto_disconnect(mosq);
-
-    return ;
-}
-
-
-void *mqtt_pub_worker(void *args)
-{
-    struct mosquitto       *mosq;
-    bool                    session = true;
-
-    iotd_ctx_t             *ctx = (iotd_ctx_t *)args;
-    mqtt_ctx_t             *mqtt_ctx;
-
-    if( !ctx )
-    {
-        log_error("Invalid input arguments\n");
-        return NULL;
-    }
-
-    mqtt_ctx = &ctx->mqtt_ctx;
-
-
-    mosq = mosquitto_new(NULL, session, ctx);
-    if( !mosq )
-    {
-        log_error("mosquitto_new failure\n");
-        return NULL;
-    }
-
-    /* set connnect to broker username and password  */
-    if( strlen(mqtt_ctx->uid)> 0  && strlen(mqtt_ctx->pwd)> 0 )
-        mosquitto_username_pw_set(mosq, mqtt_ctx->uid, mqtt_ctx->pwd);
-
-    /* set callback functions */
-    mosquitto_connect_callback_set(mosq, pub_connect_callback);
-
-    while( !g_signal.stop )
-    {
-        /* connect to MQTT broker  */
-        if( mosquitto_connect(mosq, mqtt_ctx->host, mqtt_ctx->port, mqtt_ctx->keepalive) )
-        {
-            log_error("Publisher connect to broker[%s:%d] failure: %s\n", mqtt_ctx->host, mqtt_ctx->port, strerror(errno));
-            msleep(1000);
-            continue;
-        }
-
-        /* -1: use default timeout 1000ms  1: unused */
-        mosquitto_loop_forever(mosq, -1, 1);
-
-        /* Publisher broadcast sensors data message interval time, unit seconds */
-        sleep( mqtt_ctx->interval );
-    }
-
-    mosquitto_destroy(mosq);
-    return NULL;
-}
-
-/*+-------------------------------------------+
- *|                                           |
- *|    MQTT Subscriber thread worker code     |
- *|                                           |
- *+-------------------------------------------+*/
-
-void sub_connect_callback(struct mosquitto *mosq, void *userdata, int result)
-{
-    iotd_ctx_t             *ctx = (iotd_ctx_t *)userdata;
-
-    if( result )
-    {
-        log_error("Subscriber connect to broker server failed, rv=%d\n", result);
-        return ;
-    }
-
-    log_info("Subscriber connect to broker server[%s:%d] successfully\n", ctx->mqtt_ctx.host, ctx->mqtt_ctx.port);
-
-    log_info("Subscriber subTopic '%s' with Qos[%d]\n", ctx->mqtt_ctx.subTopic, ctx->mqtt_ctx.subQos);
-    mosquitto_subscribe(mosq, NULL, ctx->mqtt_ctx.subTopic, ctx->mqtt_ctx.subQos);
-}
-
-void sub_disconnect_callback(struct mosquitto *mosq, void *userdata, int result)
-{
-    iotd_ctx_t             *ctx = (iotd_ctx_t *)userdata;
-
-    log_warn("Subscriber disconnect to broker server[%s:%d], reason=%d\n",
-            ctx->mqtt_ctx.host, ctx->mqtt_ctx.port, result);
-}
-
-void proc_json_items(cJSON *root)
-{
-    int                    i;
-    char                  *value;
-    cJSON                 *item;
-
-    if( !root )
-    {
-        log_error("Invalid input arguments $root\n");
-        return ;
-    }
-
-    for( i=0; i<cJSON_GetArraySize(root); i++ )
-    {
-        item = cJSON_GetArrayItem(root, i);
-        if( !item )
-            break;
-
-        /* if item is cJSON_Object, then recursive call proc_json */
-        if( cJSON_Object == item->type )
-        {
-            proc_json_items(item);
-        }
-        else if( cJSON_Array != item->type )
-        {
-            value = cJSON_Print(item);
-
-            log_debug("JSON Parser key: %s value: %s\n", item->string, value);
-            if( strstr(item->string, "light") || strstr(item->string, "led") || strstr(item->string, "relay"))
-            {
-                if( strstr(value, "on") || strstr(value, "off") )
-                {
-                    log_info("parser get turn '%s' %s from JSON string\n", item->string, value);
-                    gpio_out(item->string, value);
-                }
-            }
-
-            free(value); /* must free it, or it will result memory leak */
-        }
-    }
-}
-
-void sub_message_callback(struct mosquitto *mosq, void *userdata, const struct mosquitto_message *message)
-{
-    iotd_ctx_t             *ctx = (iotd_ctx_t *)userdata;
-
-    cJSON                  *root = NULL;
-    cJSON                  *item;
-    char                   *value;
-
-
-    if ( !message->payloadlen )
-    {
-        log_error("%s (null)\n", message->topic);
-        return ;
-    }
-
-    log_debug("Subscriber receive message: '%s'\n", message->payload);
-
-    root = cJSON_Parse(message->payload);
-    if( !root )
-    {
-        log_error("cJSON_Parse parser failure: %s\n", cJSON_GetErrorPtr());
-        return ;
-    }
-
-    /* check ID matched or not */
-    item = cJSON_GetObjectItem(root, "id");
-    if( !item )
-    {
-        log_error("cJSON_Parse get ID failure: %s\n", cJSON_GetErrorPtr());
-        goto OUT;
-    }
-
-    value = cJSON_PrintUnformatted(item);
-    if( strcasecmp(value, ctx->mqtt_ctx.id) )
-    {
-        log_warn("cJSON_Parse get ID not matchs [%s<->%s], drop this message!\n", value, ctx->mqtt_ctx.id);
-        free(value);
-        goto OUT;
-    }
-
-    free(value);
-
-    /* proc JSON mesage */
-    proc_json_items(root);
-
-OUT:
-    cJSON_Delete(root); /* must delete it, or it will result memory leak */
-    return ;
-}
-
-
-void *mqtt_sub_worker(void *args)
-{
-    struct mosquitto       *mosq;
-    bool                    session = true;
-
-    iotd_ctx_t             *ctx = (iotd_ctx_t *)args;
-    mqtt_ctx_t             *mqtt_ctx;
-
-    if( !ctx )
-    {
-        log_error("Invalid input arguments\n");
-        return NULL;
-    }
-
-    mqtt_ctx = &ctx->mqtt_ctx;
-
-
-    mosq = mosquitto_new(NULL, session, ctx);
-    if( !mosq )
-    {
-        log_error("mosquitto_new failure\n");
-        return NULL;
-    }
-
-    /* set connnect to broker username and password  */
-    if( strlen(mqtt_ctx->uid)> 0  && strlen(mqtt_ctx->pwd)> 0 )
-        mosquitto_username_pw_set(mosq, mqtt_ctx->uid, mqtt_ctx->pwd);
-
-    /* set callback functions */
-    mosquitto_connect_callback_set(mosq, sub_connect_callback);
-    mosquitto_disconnect_callback_set(mosq, sub_disconnect_callback);
-    mosquitto_message_callback_set(mosq, sub_message_callback);
-
-    while( !g_signal.stop )
-    {
-        /* connect to MQTT broker  */
-        if( mosquitto_connect(mosq, mqtt_ctx->host, mqtt_ctx->port, mqtt_ctx->keepalive) )
-        {
-            log_error("Subscriber connect to broker[%s:%d] failure: %s\n", mqtt_ctx->host, mqtt_ctx->port, strerror(errno));
-            msleep(1000);
-            continue;
-        }
-
-        /* -1: use default timeout 1000ms  1: unused */
-        mosquitto_loop_forever(mosq, -1, 1);
-    }
-
-    mosquitto_destroy(mosq);
-    return NULL;
-}
-
diff --git a/project/lightd/src/mqtt.h b/project/lightd/src/mqtt.h
deleted file mode 100644
index 6e2605a..0000000
--- a/project/lightd/src/mqtt.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/********************************************************************************
- *      Copyright:  (C) 2021 LingYun IoT System Studio
- *                  All rights reserved.
- *
- *       Filename:  mqtt.h
- *    Description:  This head file is MQTT subscriber and publisher thread code
- *
- *        Version:  1.0.0(20/04/21)
- *         Author:  Guo Wenxue <guowenxue@gmail.com>
- *      ChangeLog:  1, Release initial version on "20/04/21 15:46:42"
- *
- ********************************************************************************/
-#ifndef  _MQTT_H_
-#define  _MQTT_H_
-
-
-typedef struct mqtt_ctx_s
-{
-    char          id[32];       /*  production ID */
-
-    /* Broker settings  */
-    char          host[128];  /* MQTT broker server name  */
-    int           port;       /* MQTT broker listen port  */
-    char          uid[64];    /* username */
-    char          pwd[64];    /* password */
-    int           keepalive;  /* MQTT broker send PING message to subsciber/publisher keepalive timeout<seconds> */
-
-    /* Subscriber settings */
-    int           sub_enable;    /* Subscriber enable or not  */
-    char          subTopic[256]; /* Subscriber topic */
-    int           subQos;        /* Subscriber Qos  */
-
-    /* Publisher settings */
-    int           pub_enable;    /* Publisher enable or not  */
-    char          pubTopic[256]; /* Publisher topic */
-    int           pubQos;        /* Publisher Qos   */
-    int           interval;      /* Publish interval */
-} mqtt_ctx_t;
-
-
-extern void *mqtt_pub_worker(void *args);
-extern void *mqtt_sub_worker(void *args);
-
-#endif   /* ----- #ifndef _MQTT_H_  ----- */
-

--
Gitblit v1.9.1