RaspberrPi project source code
guowenxue
8 hours ago 72fea370ff20ecb2494ab985c4431b4bd691e7cd
update lighted program
13 files deleted
7 files modified
4 files added
3015 ■■■■■ changed files
.gitignore 1 ●●●● patch | view | raw | blame | history
project/lightd/config.c 291 ●●●●● patch | view | raw | blame | history
project/lightd/config.h 76 ●●●●● patch | view | raw | blame | history
project/lightd/etc/iotd.conf 83 ●●●●● patch | view | raw | blame | history
project/lightd/etc/lightd.conf 70 ●●●●● patch | view | raw | blame | history
project/lightd/hal/ds18b20.c 106 ●●●●● patch | view | raw | blame | history
project/lightd/hal/ds18b20.h 19 ●●●●● patch | view | raw | blame | history
project/lightd/hal/gpio.c 112 ●●●●● patch | view | raw | blame | history
project/lightd/hal/gpio.h 29 ●●●●● patch | view | raw | blame | history
project/lightd/hal/hal.c 89 ●●●●● patch | view | raw | blame | history
project/lightd/hal/hal.h 42 ●●●●● patch | view | raw | blame | history
project/lightd/hal/makefile 27 ●●●● patch | view | raw | blame | history
project/lightd/hal/sht20.c 466 ●●●●● patch | view | raw | blame | history
project/lightd/hal/sht20.h 33 ●●●●● patch | view | raw | blame | history
project/lightd/hal/tsl2561.c 154 ●●●● patch | view | raw | blame | history
project/lightd/hal/tsl2561.h 46 ●●●●● patch | view | raw | blame | history
project/lightd/lightd.c 378 ●●●●● patch | view | raw | blame | history
project/lightd/main.c 223 ●●●●● patch | view | raw | blame | history
project/lightd/makefile 26 ●●●●● patch | view | raw | blame | history
project/lightd/src/conf.c 309 ●●●●● patch | view | raw | blame | history
project/lightd/src/conf.h 46 ●●●●● patch | view | raw | blame | history
project/lightd/src/makefile 15 ●●●●● patch | view | raw | blame | history
project/lightd/src/mqtt.c 329 ●●●●● patch | view | raw | blame | history
project/lightd/src/mqtt.h 45 ●●●●● patch | view | raw | blame | history
.gitignore
@@ -33,4 +33,5 @@
# binary file
project/gpsd/gpsd
project/lightd/lightd
project/thingsboard/thingsboard
project/lightd/config.c
New file
@@ -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;
}
project/lightd/config.h
New file
@@ -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_  ----- */
project/lightd/etc/iotd.conf
File was deleted
project/lightd/etc/lightd.conf
New file
@@ -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
project/lightd/hal/ds18b20.c
File was deleted
project/lightd/hal/ds18b20.h
File was deleted
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;
}
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)
project/lightd/hal/hal.c
File was deleted
project/lightd/hal/hal.h
File was deleted
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
project/lightd/hal/sht20.c
File was deleted
project/lightd/hal/sht20.h
File was deleted
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;
}
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_  ----- */
project/lightd/lightd.c
New file
@@ -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;
}
project/lightd/main.c
File was deleted
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
project/lightd/src/conf.c
File was deleted
project/lightd/src/conf.h
File was deleted
project/lightd/src/makefile
File was deleted
project/lightd/src/mqtt.c
File was deleted
project/lightd/src/mqtt.h
File was deleted