Kaynağa Gözat

添加应用文件

guohui 1 yıl önce
ebeveyn
işleme
0510a8f4f4

+ 76 - 0
f407/applications/lang.c

@@ -0,0 +1,76 @@
+#include <string.h>
+#include "lang.h"
+#include "elog.h"
+
+
+#if 1
+    #define LOGD            log_d
+    #define LOGE            log_e
+    #define LOGW            log_w
+#else
+    #define LOGD            printf
+    #define LOGE            printf
+    #define LOGW            printf
+#endif
+
+
+const char *s_lang_str[LANG_ID_MAX][STR_ID_MAX]={
+    
+    {//LANG_ID_CHINESE
+        
+    },
+    
+    {//LANG_ID_ENGLISH
+        
+    },
+    
+    {//LANG_ID_RUSSIAN
+        
+    },
+    
+    {//LANG_ID_SPANISH
+        
+    },
+    
+    {//LANG_ID_PORTYGYESE
+        
+    },
+    
+    {//LANG_ID_GERMAN
+        
+    },
+    
+    {//LANG_ID_FRENCH
+        
+    },
+    
+    {//LANG_ID_ITALIAN
+        
+    },
+    
+    {//LANG_ID_JAPANESE
+        
+    },
+    
+    
+}
+
+
+
+
+static int s_lang_id=LANG_ID_CHINESE;
+int lang_init(int lang_id)
+{
+    s_lang_id = lang_id;
+}
+
+
+int lang_get(char *buf, int buflen, ...)
+{
+    
+}
+
+int lang_get_ex(int lang_id, char *buf, int buflen, ...)
+{
+    
+}

+ 91 - 0
f407/applications/lang.h

@@ -0,0 +1,91 @@
+#ifndef __LANG_Hx__
+#define __LANG_Hx__
+
+
+enum {
+    LANG_ID_CHINESE=0,
+    LANG_ID_ENGLISH,
+    LANG_ID_RUSSIAN,
+    LANG_ID_SPANISH,
+    LANG_ID_PORTYGYESE,
+    LANG_ID_GERMAN,
+    LANG_ID_FRENCH,
+    LANG_ID_ITALIAN,
+    LANG_ID_JAPANESE,
+
+    LANG_ID_MAX
+};
+
+enum {
+    STR_ID_ROOT_NAME=0,
+    STR_ID_NICK_NAME,
+    STR_ID_USER_MANAGER,
+    STR_ID_ROLE_MANAGER,
+    STR_ID_MENU_MANAGER,
+    STR_ID_POWER_MONITOR,
+    STR_ID_STAT_MONITOR,
+    
+    STR_ID_POWER_CH_STAT_MONITOR,
+    STR_ID_POWER_SW_STAT_MONITOR,
+    STR_ID_POWER_HISTORY_SEARCH,
+    STR_ID_SENSOR_MONITOR,
+    STR_ID_SENSOR_STAT_MONITOR,
+    STR_ID_SENSOR_HISTORY_SEARCH,
+    
+    STR_ID_ALARM_PROTECTION,
+    STR_ID_ALARM_SYSTEM,
+    STR_ID_ALARM_THRESHOLD_RULE,
+    STR_ID_LOG_INFO,
+    STR_ID_LOG_ALARM,
+    STR_ID_NICK_NAME,
+    
+    STR_ID_NICK_NAME,
+    STR_ID_NICK_NAME,
+    STR_ID_NICK_NAME,
+    STR_ID_NICK_NAME,
+    STR_ID_NICK_NAME,
+    STR_ID_NICK_NAME,
+    
+    STR_ID_NICK_NAME,
+    STR_ID_NICK_NAME,
+    STR_ID_NICK_NAME,
+    STR_ID_NICK_NAME,
+    STR_ID_NICK_NAME,
+    STR_ID_NICK_NAME,
+    
+    STR_ID_NICK_NAME,
+    STR_ID_NICK_NAME,
+    STR_ID_NICK_NAME,
+    STR_ID_NICK_NAME,
+    STR_ID_NICK_NAME,
+    STR_ID_NICK_NAME,
+    
+    
+    STR_ID_NICK_NAME,
+    STR_ID_NICK_NAME,
+    STR_ID_NICK_NAME,
+    STR_ID_NICK_NAME,
+    STR_ID_NICK_NAME,
+    STR_ID_NICK_NAME,
+    STR_ID_NICK_NAME,
+    STR_ID_NICK_NAME,
+    STR_ID_NICK_NAME,
+    STR_ID_NICK_NAME,
+    STR_ID_NICK_NAME,
+    STR_ID_NICK_NAME,
+    STR_ID_NICK_NAME,
+    STR_ID_NICK_NAME,
+    STR_ID_NICK_NAME,
+    STR_ID_NICK_NAME,
+    STR_ID_NICK_NAME,
+    STR_ID_NICK_NAME,
+    
+    
+    
+    
+    
+    STR_ID_MAX
+};
+
+
+#endif

+ 138 - 0
f407/applications/lock.c

@@ -0,0 +1,138 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <rtdbg.h>
+#include "lock.h"
+
+
+#if 0
+    #define LOGD  LOG_D
+    #define LOGE  LOG_E
+#else
+    #define LOGD  rt_kprintf
+    #define LOGE  rt_kprintf
+#endif
+
+#define MALLOC    malloc
+#define FREE      free
+
+
+//static global lock 
+
+static pthread_mutex_t *mutex_pool[LOCK_ID_MAX]={0};
+int lock_s_init(void)
+{
+    int i,r;
+    pthread_mutex_t *m=NULL;
+    
+    for(i=0; i<LOCK_ID_MAX; i++) {
+        m = MALLOC(sizeof(pthread_mutex_t));
+        if(m) {
+            r = pthread_mutex_init(m, NULL);
+            if(r) {
+                LOGE("lock_s_init %d failed\n", i);
+                FREE(m); m = NULL;
+            }
+            mutex_pool[i] = m;
+        }
+    }
+    
+    return 0;
+}
+
+
+int lock_s_deinit(void)
+{
+    int i,r;
+    
+    for(i=0; i<LOCK_ID_MAX; i++) {
+        if(mutex_pool[i]) {
+            r = pthread_mutex_destroy(mutex_pool[i]);
+            if(r) {
+                LOGE("lock_s_deinit %d failed\n", i);
+                continue;
+            }
+            
+            mutex_pool[i] = NULL;
+        }
+    }
+    
+    return 0;
+}
+
+
+int lock_s_hold(int id)
+{
+    if(id<0 || id>=LOCK_ID_MAX || !mutex_pool[id]) {
+        return -1;
+    }
+    
+     return pthread_mutex_lock(mutex_pool[id]);
+}
+
+
+int lock_s_release(int id)
+{
+    if(id<0 || id>=LOCK_ID_MAX || !mutex_pool[id]) {
+        return -1;
+    }
+    
+    return pthread_mutex_unlock(mutex_pool[id]);
+}
+
+
+///////////////////////////////////////////////////////
+
+lock_t lock_d_init(void)
+{
+    int r;
+    pthread_mutex_t *m=MALLOC(sizeof(pthread_mutex_t));
+    if(!m) {
+        return 0;
+    }
+    
+    r = pthread_mutex_init(m, NULL);
+    if(r) {
+        LOGE("pthread_mutex_create failed\n");
+        FREE(m); return 0;
+    }
+    
+    return (lock_t)m;
+}
+
+
+int lock_d_deinit(lock_t h)
+{
+    int r;
+    
+    if(!h) {
+        return -1;
+    }
+    
+    r = pthread_mutex_destroy((pthread_mutex_t*)h);
+    FREE((void*)h);
+    return r;
+}
+
+
+int lock_d_hold(lock_t h)
+{
+    if(!h) {
+        return -1;
+    }
+    
+    return pthread_mutex_lock((pthread_mutex_t*)h);
+}
+
+
+int lock_d_release(lock_t h)
+{
+    if(!h) {
+        return -1;
+    }
+    
+    return pthread_mutex_unlock((pthread_mutex_t*)h);
+}
+
+
+

+ 37 - 0
f407/applications/lock.h

@@ -0,0 +1,37 @@
+#ifndef __LOCK_Hx__
+#define __LOCK_Hx__
+
+
+enum {
+    LOCK_ID_DB=0,
+    LOCK_ID_MQTT,
+    LOCK_ID_MAIL,
+    LOCK_ID_PARAS,
+    LOCK_ID_SENSOR,
+    LOCK_ID_BREAKER,
+    LOCK_ID_NETSWITCH,
+    LOCK_ID_POWER_TIMER,
+    LOCK_ID_POWER_UPDATE,
+    
+    LOCK_ID_MAX
+};
+
+
+//static lock
+int lock_s_init(void);
+int lock_s_deinit(void);
+int lock_s_hold(int id);
+int lock_s_release(int id);
+
+
+//dynamic lock
+typedef unsigned long lock_t;
+
+lock_t lock_d_init(void);
+int lock_d_deinit(lock_t h);
+int lock_d_hold(lock_t h);
+int lock_d_release(lock_t h);
+
+
+#endif
+

+ 550 - 0
f407/applications/mail.c

@@ -0,0 +1,550 @@
+#include <stdint.h>
+#include <pthread.h>
+#include "cfg.h"
+#include "common.h"
+#include "thread.h"
+#include "xlist.h"
+#include "elog.h"
+#include "lock.h"
+#include "sqlite_handle.h"
+#include <curl/curl.h>
+#include "mail.h"
+
+
+#if 1
+    #define LOGD            log_d
+    #define LOGE            log_e
+    #define LOGW            log_w
+#else
+    #define LOGD            printf
+    #define LOGE            printf
+    #define LOGW            printf
+#endif
+
+
+typedef struct {
+    char sub[128];
+    char body[2048];
+    char attach[128];
+}mail_pkt_t;
+typedef struct {
+    handle_t      list;
+    mail_info_t   *info;
+
+    GlobalDeviceManager *dm;
+    int           inited;
+}mail_handle_t;
+static mail_handle_t maHandle;
+
+
+static char send_buff[4096];
+struct upload_status 
+{
+    size_t bytes_read;
+};
+static size_t payload_source(char *ptr, size_t size, size_t nmemb, void *userp)
+{
+    struct upload_status *upload_ctx = (struct upload_status *)userp;
+    const char *data;
+    size_t room = size * nmemb;
+
+    if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) {
+        return 0;
+    }
+
+    data = &send_buff[upload_ctx->bytes_read];
+    if(data) {
+        size_t len = strlen(data);
+        if(room < len)
+            len = room;
+        memcpy(ptr, data, len);
+        upload_ctx->bytes_read += len;
+        return len;
+    }
+ 
+    return 0;
+}
+static void fill_send_buff(char *dst_buf, const char *to,const char *from,const char *subject,const char *body)
+{
+  time_t timer;//time_t就是long int 类型
+  struct tm *tblock;
+  timer = time(NULL);
+  tblock = localtime(&timer);
+  
+  sprintf(dst_buf,"Subject: %s\r\n"
+                    "From: %s\r\n"
+                    "To: %s\r\n"
+                    "Date: %s\r\n"
+                    "\r\n"
+                    "%s\r\n"
+                    "\r\n",subject,from,to,asctime(tblock),body);
+}
+static int curl_add_files(curl_mime *mm, char *attach)
+{
+    curl_mimepart *part;
+    int nlen=strlen(attach);
+    char *p,*tmp=strdup(attach),*p2;
+
+    if(!tmp) {
+        return -1;
+    }
+
+    p = tmp;
+    p2 = tmp+nlen;
+    while(*p) {
+        if((*p)==';') *p=0;
+         p++;
+    }
+
+    p = tmp;
+    while(1) {
+        if(p>=p2) break;
+        part = curl_mime_addpart(mm);
+        if(!part) {
+            printf("____part is null!\n");
+            free(tmp); return -1;
+        }
+
+        curl_mime_name(part, "file");
+        curl_mime_filedata(part, p);
+        p += strlen(p)+1;
+    }
+    free(tmp);
+    return 0;
+}
+static int send_mail(mail_send_t *send, void *addr, char *sub, char *body, char *attach, int multi)
+{
+    int i=0;
+    CURLcode r=CURLE_OK;
+    char tmp[100];
+    char url_buff[256]={0};
+    char to_buff[256]={0};
+    mail_handle_t *h=&maHandle;
+    struct upload_status upload_ctx = { 0 };
+    struct curl_slist *recipients = NULL;
+    mail_recv_t *recv=(mail_recv_t*)addr;
+    curl_mime *mm=NULL,*alt=NULL;
+    curl_mimepart *part=NULL;
+    struct curl_slist *slist=NULL;
+    struct curl_slist *headers=NULL;
+    const char **cpp;
+    
+    lock_s_hold(LOCK_ID_MAIL);
+
+    CURL *curl = curl_easy_init();
+    if(!curl) {
+        goto out;
+    }
+
+    sprintf(url_buff,"%s:%s",send->server,send->port);
+    r = curl_easy_setopt(curl,CURLOPT_URL,url_buff);
+
+    //curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "EXPN");
+    //curl_easy_setopt(curl, CURLOPT_MAIL_AUTH, "<secret@cave>");
+    //curl_easy_setopt(curl, CURLOPT_SASL_AUTHZID, "ursel");
+    
+    //sprintf(tmp, "AUTH=%s", send->auth);
+    //curl_easy_setopt(curl, CURLOPT_LOGIN_OPTIONS, tmp);
+    
+    r = curl_easy_setopt(curl, CURLOPT_USERNAME, send->account);        //setting user
+    r = curl_easy_setopt(curl, CURLOPT_PASSWORD, send->password);      //setting password
+
+    
+    if(strcmp(send->port, "587")==0) { //tls
+        r = curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);    //setting openssl/tls
+        //curl_easy_setopt(curl, CURLOPT_CAINFO, "/path/to/certificate.pem");
+    }
+
+    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
+    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
+    //curl_easy_setopt(curl, CURLOPT_USERAGENT, CLIENT_USERAGENT);
+
+    r = curl_easy_setopt(curl, CURLOPT_MAIL_FROM, send->account);
+    r = curl_easy_setopt(curl, CURLOPT_READFUNCTION, payload_source);
+    r = curl_easy_setopt(curl, CURLOPT_READDATA, &upload_ctx);
+    
+    if(multi) {
+        for(int i=0; i<MAIL_RECV_MAX; i++) {
+            if(recv[i].use && strlen(recv[i].account)>0) {
+                recipients = curl_slist_append(recipients, recv[i].account);
+                //recipients = curl_slist_append(recipients, CC_MAIL);
+                strcat(to_buff,recv[i].account);
+                strcat(to_buff,";");
+            }
+        }
+    }
+    else {
+        char *sendto=(char*)addr;
+        recipients = curl_slist_append(recipients,sendto);
+        strcat(to_buff,sendto);
+        strcat(to_buff,";");
+    }
+    fill_send_buff(send_buff,to_buff,send->account,sub,body);
+
+    if(attach && strlen(attach)>0) {
+        mm = curl_mime_init(curl);
+        alt = curl_mime_init(curl);
+        
+        headers = curl_slist_append(headers, send_buff);
+        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
+
+        part = curl_mime_addpart(alt);
+        curl_mime_data(part, sub, CURL_ZERO_TERMINATED);
+
+        part = curl_mime_addpart(mm);
+        curl_mime_subparts(part, alt);
+        curl_mime_type(part, "multipart/alternative");
+        slist = curl_slist_append(NULL, "Content-Disposition: inline");
+        curl_mime_headers(part, slist, 1);
+
+        //part = curl_mime_addpart(mm);
+        //curl_mime_name(part, "file");
+        //curl_mime_filedata(part, attach);
+        curl_add_files(mm, attach);
+        curl_easy_setopt(curl, CURLOPT_MIMEPOST, mm);
+    }
+
+    r = curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
+    r = curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients);
+    r = curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
+
+    r = curl_easy_perform(curl);
+    if(r != CURLE_OK) {
+        LOGE("send mail failed, %s\n", curl_easy_strerror(r));
+    }
+    else {
+        LOGD("send mail ok!\n");
+    }
+    curl_slist_free_all(recipients);
+    curl_mime_free(mm);
+
+out:
+    if(curl) curl_easy_cleanup(curl);
+    lock_s_release(LOCK_ID_MAIL);
+
+    return (r==CURLE_OK)?0:-1;
+}
+////////////////////////////////////////////////////////////////////////////
+static void sleep_ms(int ms)
+{
+    usleep(ms*1000);
+}
+
+static void* mail_thread(void *arg)
+{
+#ifdef USE_MAIL
+    int r;
+    thread_handle_t *th=(thread_handle_t*)arg;
+    mail_handle_t   *h=(mail_handle_t*)th->arg;
+    list_node_t     *ln=NULL;
+    mail_pkt_t      *pkt=NULL;
+    mail_send_t     *send=&h->info->send;
+    mail_recv_t     *recv=h->info->recv;
+
+    while(th->quit==0) {
+        r = xlist_take_node(h->list, &ln, 0);
+        if(r==0) {
+            pkt = (mail_pkt_t*)ln->data.buf;
+            send_mail(send, recv, pkt->sub, pkt->body, pkt->attach, 1);
+            xlist_back_node(h->list, ln);
+        }
+        sleep_ms(100);
+    }
+#endif
+
+    pthread_exit(NULL);
+}
+
+
+int mail_init(void)
+{
+#ifdef USE_MAIL
+    list_cfg_t lc;
+    mail_handle_t *h=&maHandle;
+    GlobalDeviceManager *dm=&__globalDeviceManage;
+
+    lc.mode = LIST_FULL_FIFO;
+    lc.max = 100;
+    lc.log = 0;
+    h->list = xlist_init(&lc);
+
+    h->dm = dm;
+    h->info = &h->dm->mailInfo;
+
+    dev_mail_init(dm->db, h->info);
+    thread_start(THREAD_ID_MAIL, mail_thread, h);
+    h->inited = 1;
+
+    //mail_test();
+#endif
+
+    return 0;
+}
+
+
+int mail_deinit(void)
+{
+#ifdef USE_MAIL
+    mail_handle_t *h=&maHandle;
+
+    thread_stop(THREAD_ID_MAIL);
+    xlist_free(h->list);
+    h->inited = 0;
+#endif
+
+    return 0;
+}
+
+
+static int post_data(char *sub, char *body, char *attach)
+{
+    int r=0;
+
+#ifdef USE_MAIL
+    mail_pkt_t pkt;
+    mail_handle_t *h=&maHandle;
+
+    snprintf(pkt.sub, sizeof(pkt.sub), "%s", sub?sub:"");
+    snprintf(pkt.body, sizeof(pkt.body), "%s", body?body:"");
+    snprintf(pkt.attach, sizeof(pkt.attach), "%s", attach?attach:"");
+    r = xlist_append(h->list, 0, &pkt, sizeof(pkt));
+#endif
+
+    return r;
+}
+
+
+int mail_send(char *sub, char *body, char *attach)
+{
+    int r=-1;
+
+#ifdef USE_MAIL
+    mail_handle_t *h=&maHandle;
+
+    if(!h->inited || !h->info || !h->info->send.mode) {
+        return -1;
+    }
+    r = send_mail(&h->info->send, h->info->recv, sub?sub:"", body?body:"", attach?attach:"", 1);
+#endif
+
+    return r;
+}
+
+int mail_post(char *sub, char *body, char *attach)
+{
+    int r=-1;
+
+#ifdef USE_MAIL
+    mail_handle_t *h=&maHandle;
+
+    if(!h->inited || !h->info || !h->info->send.mode) {
+        return -1;
+    }
+    r = post_data(sub, body, attach);
+#endif
+
+    return r;
+}
+
+
+int mail_post_alarm(int type, int subtype, int alarm_type, char *content)
+{
+    int r=0;
+
+#ifdef USE_MAIL
+    mail_pkt_t pkt;
+    char temp[128];
+    mail_handle_t *h=&maHandle;
+
+    if(!h->inited || !content || !h->info || !h->info->send.mode) {
+        return -1;
+    }
+    char *prod_name=h->dm->_globalDevInfo.product.name;
+    int prod_id=h->dm->_globalDevInfo.product.id;
+    int langID=h->dm->_globalDevInfo.product.language;
+
+    switch(type) {
+        case ALARM_TYPE_POWER:
+        {
+            if(subtype) {
+                switch(alarm_type) {
+                    case ENABLE_TAC_V_UP:
+                    case ENABLE_TAC_V_DOWN:
+                    snprintf(temp, sizeof(temp), "%s %d %s %s %s", prod_name, prod_id, language_alarm_V[langID], language_exceed[langID], language_alarm[langID]);
+                    break;
+
+                    case ENABLE_TAC_A_UP:
+                    snprintf(temp, sizeof(temp), "%s %d %s %s %s", prod_name, prod_id, language_alarm_A[langID], language_exceed[langID], language_alarm[langID]);
+                    break;
+
+                    case ENABLE_TAC_W_UP:
+                    snprintf(temp, sizeof(temp), "%s %d %s %s %s", prod_name, prod_id, language_alarm_W[langID], language_exceed[langID], language_alarm[langID]);
+                    break;
+
+                    case ENABLE_TAC_P_UP:
+                    snprintf(temp, sizeof(temp), "%s %d %s %s %s", prod_name, prod_id, language_alarm_P[langID], language_exceed[langID], language_alarm[langID]);
+                    break;
+
+                    case ENABLE_TAC_STIME:
+                    case ENABLE_TAC_ETIME:
+                    snprintf(temp, sizeof(temp), "%s %d %s %s", prod_name, prod_id, language_alarm_phase_lose[langID], language_alarm[langID]);
+                    break;
+
+                    default:
+                    return -1;
+                }
+            }
+            else {
+                switch(alarm_type) {
+                    case WARNING_V_UP:
+                    case WARNING_V_DOWN:
+                    snprintf(temp, sizeof(temp), "%s %d %s %s %s", prod_name, prod_id, language_alarm_V[langID], language_exceed[langID], language_alarm[langID]);
+                    break;
+
+                    case WARNING_A_UP:
+                    snprintf(temp, sizeof(temp), "%s %d %s %s %s", prod_name, prod_id, language_alarm_A[langID], language_exceed[langID], language_alarm[langID]);
+                    break;
+
+                    case WARNING_W_UP:
+                    snprintf(temp, sizeof(temp), "%s %d %s %s %s", prod_name, prod_id, language_alarm_W[langID], language_exceed[langID], language_alarm[langID]);
+                    break;
+
+                    case WARNING_P_UP:
+                    snprintf(temp, sizeof(temp), "%s %d %s %s %s", prod_name, prod_id, language_alarm_P[langID], language_exceed[langID], language_alarm[langID]);
+                    break;
+
+                    case 0 ... 2:
+                    snprintf(temp, sizeof(temp), "%s %d %s %s", prod_name, prod_id, language_alarm_phase_lose[langID], language_alarm[langID]);
+                    break;
+
+                    default:
+                    return -1;
+                }
+            }
+        }
+        break;
+
+        case ALARM_TYPE_SENSOR:
+        {
+            switch(subtype) {
+                case SENSOR_TYPE_TEMP_DOUBLE:
+                case SENSOR_TYPE_TEMP_HUMI:
+                case SENSOR_TYPE_TEMP:
+                snprintf(temp, sizeof(temp), "%s %d %s %s", prod_name, prod_id, language_temperature[langID], language_alarm[langID]);
+                break;
+
+                case SENSOR_TYPE_SMOKE:
+                snprintf(temp, sizeof(temp), "%s %d %s %s", prod_name, prod_id, language_sensor_smoke[langID], language_alarm[langID]);
+                break;
+
+                case SENSOR_TYPE_WATER:
+                snprintf(temp, sizeof(temp), "%s %d %s %s", prod_name, prod_id, language_humidity[langID], language_alarm[langID]);
+                break;
+
+                case SENSOR_TYPE_ACCESS:
+                snprintf(temp, sizeof(temp), "%s %d %s %s", prod_name, prod_id, language_sensor_access[langID], language_alarm[langID]);
+                break;
+
+                case SENSOR_TYPE_GAS:
+                snprintf(temp, sizeof(temp), "%s %d %s %s", prod_name, prod_id, language_atmosphere_gas[langID], language_alarm[langID]);
+                break;
+
+                case SENSOR_TYPE_AIR_PRESS:
+                snprintf(temp, sizeof(temp), "%s %d %s %s", prod_name, prod_id, language_atmosphere_pressure[langID], language_alarm[langID]);
+                break;
+
+                case SENSOR_TYPE_LEAK:
+                snprintf(temp, sizeof(temp), "%s %d %s %s", prod_name, prod_id, language_leak[langID], language_alarm[langID]);
+                break;
+
+                default:
+                return -1;
+            }
+        }
+        break;
+
+        case ALARM_TYPE_NETWORK:
+        {
+            snprintf(temp, sizeof(temp), "%s %d %s", prod_name, prod_id, language_alarm_Type_Network[langID]);
+        }
+        break;
+
+        default:
+        return -1;
+    }
+
+    replace_sequences(content, h->dm->alarmTab);
+    r = post_data(temp, content, NULL);
+#endif
+
+    return r;
+}
+
+
+
+int mail_test(void)
+{
+    int r=0,cnt=0;
+    
+#ifdef USE_MAIL
+    char temp[200];
+    mail_handle_t *h=&maHandle;
+
+    mail_info_t info={
+    .send = {
+      .id = 0,
+      .mode = 1,
+
+#if 0
+      .account = "rcp064867@163.com",
+      .password = "YWKVURARCJXYXQVS",
+      .server = "smtp.163.com",
+
+      .port = "25",
+      //.port = "465",
+      //.port = "587",
+
+      .auth = "PLAIN",
+      //.auth = "LOGIN",
+      //.auth = "CRAM-MD5",
+#else
+      .account = "jiuci4902@gmail.com",
+      .password = "wmfoedxaycdwllvs",
+      .server = "smtp.gmail.com",
+
+      //.port = "25",
+      //.port = "465",
+      .port = "587",
+
+      //.auth = "PLAIN",
+      .auth = "LOGIN",
+      //.auth = "CRAM-MD5",
+#endif
+
+
+    },
+
+      .recv = {
+          {0, 1, "1556907721@qq.com"},
+          {1, 1, "rcp064867@163.com"},
+          {2, 1, "cijiu0219@sina.com"},
+          {3, 1, "jiuci4902@gmail.com"},
+          {4, 1, "cijiu0219@hotmail.com"},
+          {5, 1, "cijiu990219@outlook.com"},
+          {6, 1, "iauther@163.com"},
+      }
+  };
+  *h->info = info;
+
+  char *sub="123";
+  char *body="hello everyone";
+  while(cnt++<5) {
+      sprintf(temp, "%s %d", body, cnt);
+      r = mail_send(sub, temp, NULL);
+      sleep(2);
+  }
+#endif
+
+    return r;
+}
+

+ 13 - 0
f407/applications/mail.h

@@ -0,0 +1,13 @@
+#ifndef __MAIL_Hx__
+#define __MAIL_Hx__
+
+int mail_init(void);
+int mail_deinit(void);
+
+int mail_test(void);
+int mail_send(char *sub, char *body, char *attachment);
+int mail_post(char *sub, char *body, char *attachment);
+int mail_post_alarm(int type, int subtype, int alarm_type, char *content);
+
+#endif /* __SMTP_Hx__ */
+

+ 192 - 0
f407/applications/md5.c

@@ -0,0 +1,192 @@
+#include <string.h>
+#include "md5.h"  
+  
+uint8_t PADDING[]={0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};  
+  
+void md5_init(md5_ctx_t *ctx)
+{  
+    ctx->count[0] = 0;
+    ctx->count[1] = 0;
+    ctx->state[0] = 0x67452301;
+    ctx->state[1] = 0xEFCDAB89;
+    ctx->state[2] = 0x98BADCFE;
+    ctx->state[3] = 0x10325476;
+}  
+void md5_update(md5_ctx_t* ctx, uint8_t *input,uint32_t inputlen)
+{  
+    uint32_t i = 0,index = 0,partlen = 0;  
+    index = (ctx->count[0] >> 3) & 0x3F;
+    partlen = 64 - index;  
+    ctx->count[0] += inputlen << 3;
+    if(ctx->count[0] < (inputlen << 3))
+        ctx->count[1]++;
+    ctx->count[1] += inputlen >> 29;
+  
+    if(inputlen >= partlen)  
+    {  
+        memcpy(&ctx->buffer[index],input,partlen);
+        md5_transform(ctx->state, ctx->buffer);
+        for(i = partlen;i+64 <= inputlen;i+=64)  
+            md5_transform(ctx->state,&input[i]);
+        index = 0;          
+    }    
+    else  
+    {  
+        i = 0;  
+    }  
+    memcpy(&ctx->buffer[index],&input[i],inputlen-i);
+}  
+void md5_final(md5_ctx_t* ctx,uint8_t digest[16])
+{  
+    uint32_t index = 0,padlen = 0;  
+    uint8_t bits[8];  
+    index = (ctx->count[0] >> 3) & 0x3F;
+    padlen = (index < 56)?(56-index):(120-index);  
+    md5_encode(bits, ctx->count,8);
+    md5_update(ctx,PADDING,padlen);
+    md5_update(ctx,bits,8);
+    md5_encode(digest, ctx->state,16);
+}  
+void md5_encode(uint8_t *output,uint32_t *input,uint32_t len)  
+{  
+    uint32_t i = 0,j = 0;  
+    while(j < len)  
+    {  
+        output[j] = input[i] & 0xFF;    
+        output[j+1] = (input[i] >> 8) & 0xFF;  
+        output[j+2] = (input[i] >> 16) & 0xFF;  
+        output[j+3] = (input[i] >> 24) & 0xFF;  
+        i++;  
+        j+=4;  
+    }  
+}  
+void md5_decode(uint32_t *output,uint8_t *input,uint32_t len)  
+{  
+    uint32_t i = 0,j = 0;  
+    while(j < len)  
+    {  
+        output[i] = (input[j]) |  
+            (input[j+1] << 8) |  
+            (input[j+2] << 16) |  
+            (input[j+3] << 24);  
+        i++;  
+        j+=4;   
+    }  
+}  
+void md5_transform(uint32_t state[4],uint8_t block[64])  
+{  
+    uint32_t a = state[0];  
+    uint32_t b = state[1];  
+    uint32_t c = state[2];  
+    uint32_t d = state[3];  
+    uint32_t x[64];  
+    md5_decode(x,block,64);  
+    FF(a, b, c, d, x[ 0], 7, 0xd76aa478);   
+    FF(d, a, b, c, x[ 1], 12, 0xe8c7b756);   
+    FF(c, d, a, b, x[ 2], 17, 0x242070db);   
+    FF(b, c, d, a, x[ 3], 22, 0xc1bdceee);   
+    FF(a, b, c, d, x[ 4], 7, 0xf57c0faf);   
+    FF(d, a, b, c, x[ 5], 12, 0x4787c62a);   
+    FF(c, d, a, b, x[ 6], 17, 0xa8304613);   
+    FF(b, c, d, a, x[ 7], 22, 0xfd469501);   
+    FF(a, b, c, d, x[ 8], 7, 0x698098d8);   
+    FF(d, a, b, c, x[ 9], 12, 0x8b44f7af);   
+    FF(c, d, a, b, x[10], 17, 0xffff5bb1);   
+    FF(b, c, d, a, x[11], 22, 0x895cd7be);   
+    FF(a, b, c, d, x[12], 7, 0x6b901122);   
+    FF(d, a, b, c, x[13], 12, 0xfd987193);   
+    FF(c, d, a, b, x[14], 17, 0xa679438e);   
+    FF(b, c, d, a, x[15], 22, 0x49b40821);   
+  
+      
+    GG(a, b, c, d, x[ 1], 5, 0xf61e2562);   
+    GG(d, a, b, c, x[ 6], 9, 0xc040b340);   
+    GG(c, d, a, b, x[11], 14, 0x265e5a51);   
+    GG(b, c, d, a, x[ 0], 20, 0xe9b6c7aa);   
+    GG(a, b, c, d, x[ 5], 5, 0xd62f105d);   
+    GG(d, a, b, c, x[10], 9,  0x2441453);   
+    GG(c, d, a, b, x[15], 14, 0xd8a1e681);   
+    GG(b, c, d, a, x[ 4], 20, 0xe7d3fbc8);   
+    GG(a, b, c, d, x[ 9], 5, 0x21e1cde6);   
+    GG(d, a, b, c, x[14], 9, 0xc33707d6);   
+    GG(c, d, a, b, x[ 3], 14, 0xf4d50d87);   
+    GG(b, c, d, a, x[ 8], 20, 0x455a14ed);   
+    GG(a, b, c, d, x[13], 5, 0xa9e3e905);   
+    GG(d, a, b, c, x[ 2], 9, 0xfcefa3f8);   
+    GG(c, d, a, b, x[ 7], 14, 0x676f02d9);   
+    GG(b, c, d, a, x[12], 20, 0x8d2a4c8a);   
+  
+      
+    HH(a, b, c, d, x[ 5], 4, 0xfffa3942);   
+    HH(d, a, b, c, x[ 8], 11, 0x8771f681);   
+    HH(c, d, a, b, x[11], 16, 0x6d9d6122);   
+    HH(b, c, d, a, x[14], 23, 0xfde5380c);   
+    HH(a, b, c, d, x[ 1], 4, 0xa4beea44);   
+    HH(d, a, b, c, x[ 4], 11, 0x4bdecfa9);   
+    HH(c, d, a, b, x[ 7], 16, 0xf6bb4b60);   
+    HH(b, c, d, a, x[10], 23, 0xbebfbc70);   
+    HH(a, b, c, d, x[13], 4, 0x289b7ec6);   
+    HH(d, a, b, c, x[ 0], 11, 0xeaa127fa);   
+    HH(c, d, a, b, x[ 3], 16, 0xd4ef3085);   
+    HH(b, c, d, a, x[ 6], 23,  0x4881d05);   
+    HH(a, b, c, d, x[ 9], 4, 0xd9d4d039);   
+    HH(d, a, b, c, x[12], 11, 0xe6db99e5);   
+    HH(c, d, a, b, x[15], 16, 0x1fa27cf8);   
+    HH(b, c, d, a, x[ 2], 23, 0xc4ac5665);   
+  
+      
+    II(a, b, c, d, x[ 0], 6, 0xf4292244);   
+    II(d, a, b, c, x[ 7], 10, 0x432aff97);   
+    II(c, d, a, b, x[14], 15, 0xab9423a7);   
+    II(b, c, d, a, x[ 5], 21, 0xfc93a039);   
+    II(a, b, c, d, x[12], 6, 0x655b59c3);   
+    II(d, a, b, c, x[ 3], 10, 0x8f0ccc92);   
+    II(c, d, a, b, x[10], 15, 0xffeff47d);   
+    II(b, c, d, a, x[ 1], 21, 0x85845dd1);   
+    II(a, b, c, d, x[ 8], 6, 0x6fa87e4f);   
+    II(d, a, b, c, x[15], 10, 0xfe2ce6e0);   
+    II(c, d, a, b, x[ 6], 15, 0xa3014314);   
+    II(b, c, d, a, x[13], 21, 0x4e0811a1);   
+    II(a, b, c, d, x[ 4], 6, 0xf7537e82);   
+    II(d, a, b, c, x[11], 10, 0xbd3af235);   
+    II(c, d, a, b, x[ 2], 15, 0x2ad7d2bb);   
+    II(b, c, d, a, x[ 9], 21, 0xeb86d391);   
+    state[0] += a;  
+    state[1] += b;  
+    state[2] += c;  
+    state[3] += d;  
+}
+
+#define CHAR(b) (b<=9)?(b+0x30):(b-10+0x61);
+static void byte2char(char *chr, uint8_t b)
+{
+    char h,l;
+    
+    l = b&0x0f;
+    h = (b>>4)&0x0f;
+    
+    chr[0] = CHAR(h);
+    chr[1] = CHAR(l);
+}
+
+int md5_calc(void *p1, int len1, void *p2, int len2, char *md5)
+{
+    int i;
+    uint8_t tmp[16];
+    md5_ctx_t ctx;
+    
+    md5_init(&ctx);
+    md5_update(&ctx, (uint8_t*)p1, len1);
+    md5_update(&ctx, (uint8_t*)p2, len2);
+    md5_final(&ctx, tmp);
+    
+    for (i=0; i<16; i++) {
+        byte2char(&md5[i*2], tmp[i]);
+    }
+    
+    return 0;
+}
+

+ 68 - 0
f407/applications/md5.h

@@ -0,0 +1,68 @@
+#ifndef MD5_H  
+#define MD5_H  
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct
+{
+	uint32_t count[2];
+	uint32_t state[4];
+	uint8_t buffer[64];
+}md5_ctx_t;
+
+
+#define F(x,y,z) ((x & y) | (~x & z))  
+#define G(x,y,z) ((x & z) | (y & ~z))  
+#define H(x,y,z) (x^y^z)  
+#define I(x,y,z) (y ^ (x | ~z))  
+#define ROTATE_LEFT(x,n) ((x << n) | (x >> (32-n)))  
+
+#define FF(a,b,c,d,x,s,ac) \
+	{ \
+		a += F(b, c, d) + x + ac; \
+		a = ROTATE_LEFT(a, s); \
+		a += b; \
+	}
+
+#define GG(a,b,c,d,x,s,ac) \
+	{ \
+		a += G(b, c, d) + x + ac; \
+		a = ROTATE_LEFT(a, s); \
+		a += b; \
+	}
+
+#define HH(a,b,c,d,x,s,ac) \
+	{ \
+		a += H(b, c, d) + x + ac; \
+		a = ROTATE_LEFT(a, s); \
+		a += b; \
+	}
+
+#define II(a,b,c,d,x,s,ac) \
+	{ \
+		a += I(b, c, d) + x + ac; \
+		a = ROTATE_LEFT(a, s); \
+		a += b; \
+	}
+
+void md5_init(md5_ctx_t* context);
+void md5_update(md5_ctx_t* context, uint8_t* input, uint32_t inputlen);
+void md5_final(md5_ctx_t* context, uint8_t digest[16]);
+void md5_transform(uint32_t state[4], uint8_t block[64]);
+void md5_encode(uint8_t* output, uint32_t* input, uint32_t len);
+void md5_decode(uint32_t* output, uint8_t* input, uint32_t len);
+
+int md5_calc(void* p1, int len1, void* p2, int len2, char* md5);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+#endif  

Dosya farkı çok büyük olduğundan ihmal edildi
+ 1248 - 0
f407/applications/mqtt.c


+ 44 - 0
f407/applications/mqtt.h

@@ -0,0 +1,44 @@
+#ifndef __MQTT_Hx__
+#define __MQTT_Hx__
+
+#include <stdint.h>
+
+
+enum {
+    MQTT_SUB_CMD_POWER_ALL=0,
+    MQTT_SUB_CMD_POWER_CHN,
+    MQTT_SUB_CMD_SENSOR,
+    MQTT_SUB_CMD_RESTART,
+    MQTT_SUB_CMD_RESET,
+    MQTT_SUB_CMD_SERVICE,
+
+    MQTT_SUB_MAX
+};
+enum {
+    MQTT_PUB_INFO_DEVICE=0,
+    MQTT_PUB_STAT_NETWORK,
+    MQTT_PUB_STAT_POWER_ALL,
+    MQTT_PUB_STAT_POWER_CHN,
+    MQTT_PUB_STAT_SENSOR,
+    MQTT_PUB_STAT_SERVICE,
+    MQTT_PUB_ALARM_NETWORK,
+    MQTT_PUB_ALARM_POWER,
+    MQTT_PUB_ALARM_SENSOR,
+
+    MQTT_PUB_MAX
+};
+
+typedef struct {
+    int id;
+    int nalarm;
+    int action;
+    int actionId;
+}alarm_para_t;
+
+int mqtt_init(void);
+int mqtt_deinit(void);
+
+int mqtt_post_alarm(int type, int subtype, char *content, alarm_para_t *para);
+int mqtt_test(void);
+
+#endif

+ 428 - 0
f407/applications/net.c

@@ -0,0 +1,428 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <limits.h>
+#include "rtdbg.h"
+#include "sys.h"
+#include "paras.h"
+#include "cfg.h"
+#include "fs.h"
+
+#if 1
+    #define LOGE  LOG_E
+    #define LOGW  LOG_W
+    #define LOGD  LOG_D
+#else
+    #define LOGD  rt_printf
+    #define LOGW  rt_printf
+    #define LOGE  rt_printf
+#endif
+
+
+#define DFLT_NIC            "e0"
+
+
+
+////////////////////////////////////////////////
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <lwip/sockets.h>
+#include <lwip/ip_addr.h>
+#include <lwip/ip6_addr.h>
+
+void print_net(char*s, network_data_t *p)
+{
+    LOGD("__%s__net.mode:    %d\n", s, p->mode);
+    LOGD("__%s__net.addr:    %s\n", s, p->ip_address);
+    LOGD("__%s__net.mask:    %s\n", s, p->mask);
+    LOGD("__%s__net.gateway: %s\n", s, p->gateway);
+    LOGD("__%s__net.dns1:    %s\n", s, p->dns1);
+    LOGD("__%s__net.dns2:    %s\n", s, p->dns2);
+}
+void print_modbus(char*s, modbus_data_t *p)
+{
+    LOGD("__%s__mbus.mode:    %d\n", s, p->mode);
+    LOGD("__%s__mbus.addr:    %d\n", s, p->addr);
+    LOGD("__%s__mbus.baud:    %d\n", s, p->baudrate);
+    LOGD("__%s__mbus.path:    %s\n", s, p->path);
+}
+
+static int set_ipaddr(int family, const char* iface, const char* addr, const char* netmask)
+{
+    ip4_addr_t  ipaddr4;
+    ip6_addr_t  ipaddr6;
+
+    if(family==AF_INET) {
+        //ip4_addr_set(&ipaddr4, IP4_ADDR(&ipaddr4, 0xbeef, 0xfeed, 0xdead, 0xbeef));
+    }
+    else {
+        //ip6_addr_set(&ipaddr6, IP6_ADDR(&ipaddr6, 0xbeef, 0xfeed, 0xdead, 0xbeef, 0x1337, 0xbabe, 0xbaad, 0xface));
+        
+        //netif_add_ip6_address(&netif, &ipaddr_v6, &chosen_idx);
+        //netif.ip6_addr_state[chosen_idx] = IP6_ADDR_VALID;
+        //ip6_addr_assign_zone(ip_2_ip6(&netif.ip6_addr[0]), IP6_UNICAST, &netif);
+        //netif_ip6_addr_set_state(&netif, 0, IP6_ADDR_TENTATIVE);
+    }
+    
+    return 0;
+}
+static int get_ipaddr(int family, char *iface, char *addr, char *netmask)
+{
+    
+    
+    return 0;
+}
+
+static int set_gateway(int family, const char* gateway)
+{
+    
+    
+    return 0;
+
+}
+static int get_gateway(int family, const char* gateway)
+{
+
+    return 0;
+}
+static int set_dhcp(int on)
+{
+    if(on) {
+        
+    }
+    else {
+        
+    }
+    return 0;
+}
+static int is_number(char *str)
+{
+    while (*str) {
+        if (!isdigit(*str)) {
+            return 0;
+        }
+        str++;
+    }
+    return 1;
+}
+static int ip_check(char* addr)
+{
+    int flag=IP_ERR;
+    struct in_addr addr4;
+    struct in6_addr addr6;
+
+    if (inet_pton(AF_INET, addr, &addr4) == 1) {
+        flag = IP_V4;
+    } else if (inet_pton(AF_INET6, addr, &addr6) == 1) {
+        flag = IP_V6;
+    }
+
+    if(flag==IP_ERR) {
+        LOGE("____ wrong ip addr: %s\n", addr);
+    }
+    
+    return flag;
+}
+static int is_ipv6_prefix(char *ss)
+{
+    if(is_number(ss)) {
+        int val = atoi(ss);
+        if(val>1 && val<128) {
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
+
+
+
+static int nw_check(network_data_t *para, int ipv)
+{
+    if(ipv==IP_V4) {
+        if((ip_check(para->ipaddr)!=IP_V4) || (ip_check(para->mask)!=IP_V4) || (ip_check(para->gateway)!=IP_V4)) {
+            return -1;
+        }
+    }
+    else {
+        if((ip_check(para->ipaddr)!=IP_V6) || (!is_ipv6_prefix(para->mask)) || (ip_check(para->gateway)!=IP_V6)) {
+            return -1;
+        }
+    }
+
+    return 0;
+}
+static int get_net(network_data_t *para, int ipv)
+{
+    return 0;
+}
+static int set_net(network_data_t *para, int ipv)
+{
+    int r,ipv2;
+    network_data_t info4,info6,*info;
+
+    get_net(&info4, IP_V4);
+    get_net(&info6, IP_V6);
+
+    info = ((ipv==IP_V4)?&info4:&info6);
+    
+    if(para->mode<2 && para->mode!=info->mode) {
+        info->mode = para->mode;
+    }
+    
+    ipv2 = ip_check(para->ipaddr);
+    if((ipv==ipv2) && strcmp(para->ipaddr, info->ipaddr)) {
+        strcpy(info->ipaddr, para->ipaddr);
+    }
+    
+    if(ipv==IP_V4) {
+        ipv2 = ip_check(para->mask);
+    }
+    else {
+        ipv2=is_ipv6_prefix(para->mask)?IP_V6:IP_ERR;
+    }
+    if((ipv==ipv2) && strcmp(para->mask, info->mask)) {
+        strcpy(info->mask, para->mask);
+    }
+
+    ipv2 = ip_check(para->gateway);
+    if((ipv==ipv2) && strcmp(para->gateway, info->gateway)) {
+        strcpy(info->gateway, para->gateway);
+    }
+    
+
+    return r;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+int sys_set_net(network_data_t *para, int ip_version)
+{
+    int r,ipv;
+
+    network_data_t para2;
+    r = get_net(&para2, ip_version);
+    if(r==0) {
+        if(memcmp(para, &para2, sizeof(network_data_t))==0) {
+            LOGW("%s NetworkInfo is same, no need to set\n", DFLT_NIC);
+            return -1;
+        }
+        set_dns(para);
+        r = set_net(para, ipVersion);
+        if(r==0) {
+            sys_reboot();
+            //nic_restart(DFLT_NIC); exit(0);
+        }
+    }
+    else {
+        LOGE("get_net failed\n");
+    }
+    
+    return r;
+}
+
+int sys_get_net(network_data_t *para, int ip_version)
+{
+    int r;
+
+    r = get_net(para, ip_version);
+
+    return r;
+}
+
+
+int sys_get_mac(char *mac, int maclen)
+{
+    int sock;
+    struct ifreq ifr;
+
+    if(!mac || maclen<6) {
+        return -1;
+    }
+
+    sock = socket(AF_INET, SOCK_DGRAM, 0);
+    if (sock == -1){
+        return -1;
+    }
+
+    strcpy(ifr.ifr_name, "eth0");
+    if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0){
+        close(sock); return -1;
+    }
+    close(sock);
+
+    //uint8_t *p = (uint8_t*)ifr.ifr_hwaddr.sa_data;
+    //snprintf(mac, maclen, "%02x%02x%02x%02x%02x%02x", p[0], p[1], p[2], p[3], p[4], p[5]);
+
+    return 0;
+}
+
+int sys_get_chip_id(int *id)
+{
+    int sock;
+    struct ifreq ifr;
+
+    if(!id) {
+        return -1;
+    }
+
+    
+    return 0;
+}
+
+
+int sys_ip_check(char *ip)
+{
+    return ip_check(ip);
+}
+
+
+
+///////////////////////////////////////////////////////////////////////
+#define MAX_BUFFER_SIZE 1024
+static void* plug_thread(void *arg)
+{
+    int nlSock;
+    struct sockaddr_nl srcAddr;
+    struct nlmsghdr *nlMsg;
+    char buffer[MAX_BUFFER_SIZE];
+    int plug_in=0,plug_out=0;
+    thread_handle_t *h=(thread_handle_t*)arg;
+
+    printf("___plug_thread start\n");
+
+    nlSock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+    if (nlSock < 0) {
+        printf("Failed to create Netlink socket");
+        goto quit;
+    }
+
+    memset(&srcAddr, 0, sizeof(srcAddr));
+    srcAddr.nl_family = AF_NETLINK;
+    srcAddr.nl_groups = RTMGRP_LINK | RTMGRP_NOTIFY;
+
+    if (bind(nlSock, (struct sockaddr *)&srcAddr, sizeof(srcAddr)) < 0) {
+        perror("Failed to bind Netlink socket");
+        close(nlSock);
+        goto quit;
+    }
+
+	int flags = fcntl(nlSock, F_GETFL, 0);
+    fcntl(nlSock, F_SETFL, flags | O_NONBLOCK);
+
+    while (h->quit==0) {
+        fd_set readSet;
+        FD_ZERO(&readSet);
+        FD_SET(nlSock, &readSet);
+
+        // 设置超时时间为 1 秒
+        struct timeval timeout;
+        timeout.tv_sec = 1;
+        timeout.tv_usec = 0;
+
+        // 监视 Netlink Socket 的可读状态
+        int result = select(nlSock + 1, &readSet, NULL, NULL, &timeout);
+        if (result == -1) {
+            perror("Failed to select");
+            goto quit;
+        } else if (result == 0) {
+            // 超时,没有新数据到达
+            //printf("Timeout\n");
+            continue;
+        }
+
+        if (FD_ISSET(nlSock, &readSet)) {
+            // 接收消息
+            int bytesRead = recv(nlSock, buffer, MAX_BUFFER_SIZE, 0);
+            if (bytesRead < 0) {
+                perror("Failed to receive message from Netlink socket");
+                close(nlSock);
+                goto quit;
+            }
+
+            // 遍历接收到的消息,获取到Netlink的消息头。
+            nlMsg = (struct nlmsghdr *)buffer;
+            while (NLMSG_OK(nlMsg, bytesRead)) {
+                if (nlMsg->nlmsg_type == NLMSG_DONE) {
+                    break;
+                }
+
+                if (nlMsg->nlmsg_type == RTM_NEWLINK || nlMsg->nlmsg_type == RTM_DELLINK) {
+                    //NLMSG_DATA()获取完整的ifinfomsg结构体的指针
+                    //根据消息头nlMsg获取到其后面的数据部分ifinfomsg结构体的指针
+                    struct ifinfomsg *ifInfo = (struct ifinfomsg *)NLMSG_DATA(nlMsg);
+                    if (ifInfo->ifi_family == AF_UNSPEC) {
+                        //获取路由信息的属性,以及消息负载的长度,通过这两个参数来判断本次的数据是否有效
+                        struct rtattr *attribute = IFLA_RTA(ifInfo);
+                        int attributeLen = IFLA_PAYLOAD(nlMsg);
+                        
+                        while (RTA_OK(attribute, attributeLen)) {
+                            char *ifaceName = (char *)RTA_DATA(attribute);
+                            if ((attribute->rta_type == IFLA_IFNAME) && (strcmp(ifaceName, "eth0")==0)) {
+                            
+                                //printf("____Interface: %s \n", ifaceName);
+                                if((ifInfo->ifi_flags & IFF_LOWER_UP)) {
+                                    if(plug_in==0) {
+                                        system("ifup eth0");
+                                        printf("____eth0 plug in\n");
+                                        plug_in = 1; plug_out = 0;
+                                    }
+                                }
+                                else  {
+                                    if(plug_out==0) {
+                                        system("ifdown eth0");
+                                        printf("____eth0 plug out\n");
+                                        plug_in = 0; plug_out = 1;
+                                    }
+                                }
+                            }
+                            attribute = RTA_NEXT(attribute, attributeLen);
+                        }
+                    }
+                }
+                nlMsg = NLMSG_NEXT(nlMsg, bytesRead);
+            }
+        }
+    }
+
+    close(nlSock);
+
+quit:
+    printf("___plug_thread exit\n");
+    pthread_exit(NULL);
+}
+///////////////////////////////////////////////////////////
+
+
+
+static void* polling_thread(void *arg)
+{
+    thread_handle_t *h=(thread_handle_t*)arg;
+
+    //wdog_init();
+    //tmp_create();
+    while(h->quit==0) {
+        
+        sleep(1);
+    }
+    pthread_exit(NULL);
+}
+
+
+
+
+int sys_init(void)
+{
+    lock_s_init();
+    paras_init();
+    
+    thread_start(THREAD_ID_POLLING, polling_thread, NULL);
+
+    return 0;
+}
+

+ 22 - 0
f407/applications/net.h

@@ -0,0 +1,22 @@
+#ifndef __SYS_H__
+#define __SYS_H__
+
+#include <stdint.h>
+#include "protocol.h"
+
+enum {
+    IP_DHCP=0,
+    IP_STATIC,
+};
+enum {
+    IP_ERR=0,
+    IP_V4,
+    IP_V6,
+};
+
+int net_ip_check(char *ip);
+int netget_mac(char *mac, int maclen);
+int net_get_net(network_data_t *para, int ip_version);
+int net_set_net(network_data_t *para, int ip_version);
+
+#endif

+ 402 - 0
f407/applications/protocol.h

@@ -0,0 +1,402 @@
+#ifndef __PROTOCOL_Hx__
+#define __PROTOCOL_Hx__
+
+#include <stdint.h>
+
+#define CH_MAX          12
+#define BRD_MAX         32
+
+
+enum {
+    RW_READ=0,                                 //读
+    RW_WRITE                                   //写
+};
+
+enum {
+    TIME_ABS=0,                                 //绝对时间
+    TIME_REL                                    //相对时间
+};
+enum {
+    LOOP_HOUR=0,
+    LOOP_DAY,
+    LOOP_WEEK,
+    LOOP_MONTH,
+    LOOP_YEAR,
+    
+    LOOP_USER
+};
+
+enum {
+    PDU_AC_I1O1=0,
+    PDU_DC_I1O1,
+    PDU_AC_I3O3=3,
+    PDU_AC_I3O1,
+    PDU_AC_I3O3_X,
+};
+
+enum {
+    ALARM_TYPE_POWER=0,
+    ALARM_TYPE_SENSOR,
+    ALARM_TYPE_NETWORK,
+    ALARM_TYPE_OPRATION,
+    ALARM_TYPE_RUNNING,
+    
+    ALARM_TYPE_MAX
+};
+enum {
+    THRESHOLD_V_UPPER = (1<<0), //电压超上限
+    THRESHOLD_V_LOWER = (1<<1), //电压超下限
+    THRESHOLD_C_UPPER = (1<<2), //电流超上限
+    THRESHOLD_P_UPPER = (1<<3), //功率超上限
+    THRESHOLD_W_UPPER = (1<<4), //电能超上限
+};
+
+enum {
+    IP_MODE_DHCP=0,
+    IP_MODE_STATIC,
+};
+enum {
+    IP_VER_ERR=0,
+    IP_VER_V4,
+    IP_VER_V6,
+};
+enum {
+    MODBUS_MASTER=0,
+    MODBUS_SLAVE,
+};
+enum {
+    SNMP_AUTH_NONE=0,
+    SNMP_AUTH_MD5,
+    SNMP_AUTH_SHA,
+
+    SNMP_AUTH_MAX
+};
+enum {
+    SNMP_ENCYPT_NONE=0,
+    SNMP_ENCYPT_DES,
+    SNMP_ENCYPT_AES,
+
+    SNMP_ENCYPT_MAX
+};
+enum
+{
+    SENSOR_TYPE_TEMP_HUMI   = 0 , //温湿度传感器
+    SENSOR_TYPE_SMOKE       = 1 , //烟雾传感器
+    SENSOR_TYPE_WATER       = 2 , //水浸传感器
+    SENSOR_TYPE_ACCESS      = 3 , //门禁传感器
+    SENSOR_TYPE_GAS         = 4 , //气体传感器
+    SENSOR_TYPE_AIR_PRESS   = 5 , //气压传感器
+    SENSOR_TYPE_AIR_COND    = 6,  //空条传感器
+    SENSOR_TYPE_LEAK        = 7,  //泄漏传感器
+    SENSOR_TYPE_TEMP        = 8,  //温度传感器
+    SENSOR_TYPE_TEMP_DOUBLE = 9,  //双温度传感器
+    SENSOR_TYPE_PRESS       = 10, //压力传感器
+
+    SENSOR_TYPE_MAX,
+};
+enum {
+    SENSOR_TYPE_TEMP_HUMI_RSWSN01PVC=0,
+    SENSOR_TYPE_TEMP_HUMI_HKSHT301T1H536VRS485,
+
+    SENSOR_TYPE_TEMP_HUMI_MAX
+};
+enum {
+    SENSOR_TYPE_TEMP_DOUBLE_DL10BM485V24D2=0,
+
+    SENSOR_TYPE_TEMP_DOUBLE_MAX
+};
+enum {
+    SENSOR_TYPE_TEMP_BTG50H8EL3200=0,
+
+    SENSOR_TYPE_TEMP_MAX
+};
+enum {
+    SENSOR_TYPE_LEAK_XWDC01A=0,
+
+    SENSOR_TYPE_LEAK_MAX
+};
+
+enum {
+    LANG_ID_CHINESE=0,
+    LANG_ID_ENGLISH,
+    LANG_ID_RUSSIAN,
+    LANG_ID_SPANISH,
+    LANG_ID_PORTYGYESE,
+    LANG_ID_GERMAN,
+    LANG_ID_FRENCH,
+    LANG_ID_ITALIAN,
+    LANG_ID_JAPANESE,
+
+    LANG_ID_MAX
+};
+////////////////////////////////////////////////
+#pragma pack (1)
+typedef struct
+{
+    uint8_t             mode;
+    uint8_t             addr;               
+    uint32_t            baud;
+}modbus_data_t;
+
+typedef struct
+{
+    int                 mode;               //0:DHCP  1:STATIC  
+    char                ipaddr[48];         //
+    char                mask[48];           //
+    char                gateway[48];        //
+    char                dns1[48];           //dns1
+    char                dns2[48];           //dns2
+}network_data_t;
+
+typedef struct {
+    uint32_t    id;                         //产品ID   
+    char        pname[32];                  //产品名称
+    char        pnumber[32];                //产品编号    
+    char        status[32];                 //产品状态
+    
+    char        name[32];                   //设备名称
+    char        number[32];                 //设备编号    
+    char        date[32];                   //设备生产日期
+    char        batch[32];                  //设备生产批次
+
+    uint8_t     type;                       //产品类型
+    uint8_t     pwr_type;                   //电源类型
+    char        version[8];                 //软件版本
+    uint8_t     language;                   //多国语言
+    uint8_t     count;                      //级联设备数
+    uint32_t    samp_time;                  //采集周期 单位ms
+    uint32_t    save_time;                  //采集周期 单位ms
+
+    uint16_t    ph_group;                   //三组相数
+    uint16_t    ch_delay;                   //通道延时
+}product_data_t;
+
+typedef struct {
+    uint8_t             watchdog;
+    int32_t             flip_time;
+}misc_data_t;
+
+typedef struct {
+    char                name[256];
+    char                site[256];
+    char                mail[256];
+    char                addr[256];
+    char                tele[32];
+}service_data_t;
+
+typedef struct {
+    uint32_t            id[3];
+    uint32_t            chns;
+    uint32_t            time;
+    char                ver[12];
+}board_data_t;
+
+typedef struct {
+    modbus_data_t       cas;
+    misc_data_t         misc;
+    product_data_t      prod;
+    service_data_t      serv;
+    network_data_t      netwk;
+}paras_data_t;
+
+
+typedef struct {
+    uint8_t             lang;
+}sys_data_t;
+
+typedef struct {
+    
+}sys_stat_t;
+
+typedef struct {
+    float               voltage;                //电压
+    float               current;                //电流
+    float               power;                  //功率
+    float               freq;                   //频率
+    float               consum;                 //耗电量consumption
+    float               factor;                 //功率因素    
+    uint8_t             status;                 //开关状态     
+    uint8_t             nwire;                  //零线状态
+    uint32_t            time;
+}power_data_t;
+typedef struct {
+    uint8_t             ch_idx;                 //该通道在全部板上的所排序号
+    uint8_t             ch_idx2;                //该通道在其所在的板上的序号
+    uint8_t             ph_order;               //0:A相 1:B相 2:C相
+    
+    power_data_t        *pdata;
+}ch_power_t;
+
+typedef struct {
+    uint8_t             en;
+    float               value;                  //threashold value
+    uint8_t             action;
+    uint8_t             action_para;
+}threshold_t;
+typedef struct {
+    threshold_t         volt_upper;
+    threshold_t         volt_lower;
+    threshold_t         volt_over;
+    threshold_t         curr_upper;             //current
+    threshold_t         power_upper;
+    threshold_t         pcons_upper;            //power consumption
+}ch_threshold_t;
+
+typedef struct {
+    ch_power_t          pwr;
+    ch_threshold_t      thr;
+}ch_data_t;
+
+typedef struct {
+    uint8_t             type;
+    uint8_t             addr;
+    
+    ch_data_t           *pch[CH_MAX];
+}power_board_t;
+
+typedef struct {
+    power_board_t       *pbrd[BRD_MAX];
+}power_all_t;
+
+typedef struct {
+    float               voltage;                //电压
+    float               current;                //电流
+    float               power;                  //功率
+    float               freq;                   //频率
+    float               consum;                 //耗电量
+    
+    float               active;                 //有功功率
+    float               reactive;               //无功功率
+    float               apparent;               //视在功率
+}power_total_t;
+
+typedef struct {
+    uint8_t             type;
+    float               data;
+    uint8_t             time;
+}sensor_data_t;
+
+typedef struct {
+    uint8_t             type;
+    uint32_t            str_id;
+    uint32_t            sep_id;
+    uint32_t            time;
+}alarm_data_t;
+
+typedef struct {
+    uint32_t            brd[BRD_MAX];
+    
+    uint8_t             time_mode;              //绝对时间/相对时间
+    uint32_t            time_s;                 //起始时间, 单位: 秒
+    uint32_t            time_inv;               //间隔时间, 单位: 秒
+    
+    int8_t              loop_mode;              //按日/周/月/年
+    int32_t             loop_times;             //循环次数, 负值为无限循环
+}schedule_data_t;
+
+typedef struct {
+    sys_data_t          sys;
+    
+    power_all_t         pall;
+    power_total_t       ptotal;
+}all_data_t;
+//////////////////////////////
+typedef struct 
+{
+    uint8_t             userID;    				//用户ID
+    char                name[32];               //用户名-登录
+    char                password[32]; 		    //用户密码
+    char                nick[32]; 			    //用户名称
+    uint8_t             roleID;    		        //角色ID
+    uint32_t            time;                   //用户创建时间     
+}user_data_t;
+typedef struct 
+{
+    uint8_t             roleID;    				//角色ID
+    char                roleName[32];           //角色名称
+    uint8_t             roleLevel; 		        //角色等级
+    char                auth[32]; 		        //角色权限
+    int                 roleSort;    		    //显示顺序
+    uint32_t            time;                   //创建时间
+}role_data_t;
+
+typedef struct {
+    char                alg[12];
+    char                passwd[64];
+}crypt_data_t;
+typedef struct {
+    char                user[32];
+    crypt_data_t        auth;
+    crypt_data_t        priv;
+}crypt_t;
+typedef struct {
+    uint8_t             mode;
+    uint8_t             version;
+    char                public[64];
+    uint8_t             trapmode;
+
+    crypt_t             crypt;
+    char                nms_ip[64];
+}snmp_data_t;
+
+typedef struct
+{
+    int                 id;
+    int                 use;
+    char                account[64];
+}mail_recv_t;
+typedef struct 
+{
+    uint8_t             id;
+    uint8_t             mode;    				        //0: open   1: close
+    char                account[64];                    //用户账号
+    char                password[24]; 		            //用户密码
+    char                server[64]; 			        //服务器
+    char                port[10];    		            //端口
+    char                auth[16];    			        //认证方式  
+    char                *ca;                            //ca cert
+}mail_send_t;
+typedef struct
+{
+    mail_send_t         send;
+
+    #define MAIL_RECV_MAX  10
+    mail_recv_t         recv[MAIL_RECV_MAX];            //接收账号列表
+}mail_info_t;
+
+enum {
+    MQTT_PLAT_EMQX=0,
+    MQTT_PLAT_ALIYUN,
+    
+    MQTT_PLAT_MAX
+};
+
+typedef struct {
+    uint8_t             id;    		                    //id
+    uint8_t             plat;                           //0: emqx   1: aliyun
+    uint8_t             mode;    				        //0: open   1: close
+    char                proto[16];                      //mqtt, mqtts, ws, wss
+    char                name[32];                       //server name
+    char                server[256]; 		            //server ip
+    char                port[10]; 			            //server port
+    char                cid[64];    		            //client ID
+    char                user[32];    			        //
+    char                password[32];
+    char                *cert;
+    uint8_t             status;
+}mqtt_server_t;
+typedef struct {
+    #define MQTT_SER_MAX   5
+    mqtt_server_t       ser[MQTT_SER_MAX];
+}mqtt_info_t;
+
+#pragma pack ()
+
+#define DB_NAME         "smartPDU.db"
+#define INI_NAME        "smartPDU.ini"
+#define INF_NAME        "PDUInfo.txt"
+
+#define CASCADE_MAX     32
+
+#endif
+

+ 82 - 0
f407/applications/sys.c

@@ -0,0 +1,82 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <limits.h>
+#include "rtdbg.h"
+#include "sys.h"
+#include "paras.h"
+#include "cfg.h"
+#include "fs.h"
+#include "thread.h"
+
+#if 1
+    #define LOGE  LOG_E
+    #define LOGW  LOG_W
+    #define LOGD  LOG_D
+#else
+    #define LOGD  rt_printf
+    #define LOGW  rt_printf
+    #define LOGE  rt_printf
+#endif
+
+
+
+////////////////////////////////////////////////////////////////////
+int sys_reboot(void)
+{
+    int r=0;
+
+    r = system("reboot");
+    if(r) {
+        LOGE("sys_reboot failed!\n");
+        return -1;
+    }
+
+    return r;
+}
+
+
+
+
+
+int sys_get_chip_id(int *id)
+{
+    if(!id) {
+        return -1;
+    }
+
+    
+    return 0;
+}
+
+
+
+
+
+static void* poll_thread(void *arg)
+{
+    thread_handle_t *h=(thread_handle_t*)arg;
+
+    //wdog_init();
+    //tmp_create();
+    while(h->quit==0) {
+        
+        sleep(1);
+    }
+    pthread_exit(NULL);
+}
+
+
+
+
+int sys_init(void)
+{
+    paras_init();
+    
+    //thread_start(THREAD_ID_POLL, poll_thread, NULL);
+
+    return 0;
+}
+

+ 34 - 0
f407/applications/sys.h

@@ -0,0 +1,34 @@
+#ifndef __SYS_H__
+#define __SYS_H__
+
+#include <stdint.h>
+#include "protocol.h"
+
+enum {
+    IP_DHCP=0,
+    IP_STATIC,
+};
+enum {
+    IP_ERR=0,
+    IP_V4,
+    IP_V6,
+};
+
+
+int sys_init(void);
+int sys_reboot(void);
+int sys_set_factory(void);
+
+int sys_chmod(void);
+int sys_get_disk_ava_MB(char *path);
+int sys_get_mem_ava_MB(void);
+int sys_is_running(char *prog);
+int sys_get_path(char *path, char *name);
+int sys_get_net(network_data_t *para, int ipVersion);
+int sys_set_net(network_data_t *para, int ipVersion);
+int sys_get_mac(char *mac, int maclen);
+int sys_get_chip_id(int *id);
+int sys_ip_check(char *ip);
+int sys_get_prod(product_data_t *prod);
+
+#endif

+ 577 - 0
f407/applications/upg.c

@@ -0,0 +1,577 @@
+#include <errno.h>
+#include <stdio.h>
+#include <sys/ipc.h> 
+#include <sys/msg.h>
+#include "elog.h"
+#include "upg.h"
+#include "file.h"
+#include "thread.h"
+#include "modbus_handle.h"
+
+
+#if 1
+    #define LOGD  log_d
+    #define LOGE  log_e
+#else
+    #define LOGD  printf
+    #define LOGE  printf
+#endif
+
+#define RETRY_MAX           3
+
+#define REG_UPG_READ        1501
+#define REG_UPG_WRITE       1550
+
+#define REG_UPG_JUMP        6330
+#define REG_BOARD_INFO      6331
+
+enum {
+    OFFLINE=0,
+    ONLINE,
+    UPGRADING,
+    UPGRADE_OK,
+    UPGRADE_FAIL,
+};
+
+#pragma pack (1)
+typedef struct {
+    int16_t   pid;
+    uint16_t  dlen;
+    uint8_t   data[0];
+}upg_pkt_t;
+#pragma pack ()
+
+typedef struct {
+    uint32_t id[3];
+    uint32_t channels;
+    char ver[12];
+    char date[32];
+}switch_info_t;
+
+
+typedef struct {
+    int  upging;
+    char path[200];
+}upg_arg_t;
+
+typedef struct {
+    key_t        key;
+    upg_arg_t    arg;
+    handle_t     upg;
+    handle_t     all;
+    GlobalDeviceManager *dm;
+    int          init;
+}upg_handle_t;
+static upg_handle_t uHandle={0};
+
+static int upg_board_scan(void);
+static void* board_thread(void *arg);
+
+
+static void mem_swap(void *buf, int len)
+{
+    int i;
+    uint8_t tmp,*pbuf=(uint8_t*)buf;
+    for(i=0; i<len; i+=2) {
+        tmp = pbuf[i];
+        pbuf[i] = pbuf[i+1];
+        pbuf[i+1] = tmp;
+    }
+}
+static int mb_read(Modbus_Manger *mm, uint16_t addr, uint16_t reg, void *data, int len, int timeout)
+{
+    int to,r,cnt=(len+len%2)/2;
+    
+    g_modbus_get_timeout(mm, &to);
+    g_modbus_set_timeout(mm, timeout);
+    r = g_modbus_read_x_reg(mm, addr, reg, cnt, data);
+    g_modbus_set_timeout(mm, to);
+    //if(r>0) mem_swap(data, r*2);
+    return (r==cnt)?0:-1;
+
+}
+static int mb_write(Modbus_Manger *mm, uint16_t addr, uint16_t reg, void *data, int len, int timeout)
+{
+    int to,r,cnt=(len+len%2)/2;
+
+    g_modbus_get_timeout(mm, &to);
+    g_modbus_set_timeout(mm, timeout);
+    r = g_modbus_write_x_reg(mm, addr, reg, cnt, data);
+    g_modbus_set_timeout(mm, to);
+
+    return (r==cnt)?0:-1;
+}
+//////////////////////////////////////////////////////////////////////
+#define UPG_RW_TIMEOUT   200
+static void sw_to_info(int addr, board_info_t *info, switch_info_t *swinfo, int status)
+{
+    info->addr = addr;
+    info->brd_id = swinfo->id[0];
+    info->channels = swinfo->channels;
+    info->status = status;
+
+    strcpy(info->name, "Board");
+    strcpy(info->ver, swinfo->ver);
+    get_bldtime2(info->date, swinfo->date);
+}
+static int board_is_upgrading(Modbus_Manger* mm, int addr)
+{
+    int r;
+    uint16_t tmp;
+    
+    r = mb_read(mm, addr, REG_UPG_READ, &tmp, sizeof(tmp), UPG_RW_TIMEOUT);
+    return (r==0)?1:0;
+}
+static int board_upgrade_jump(Modbus_Manger* mm, int addr)
+{
+    int r;
+    uint16_t tmp=1;
+
+    r = mb_write(mm, addr, REG_UPG_JUMP, &tmp, sizeof(tmp), UPG_RW_TIMEOUT);
+    return r;
+}
+static int board_get_info(Modbus_Manger* mm, int addr, switch_info_t *info)
+{
+    int r;
+    r = mb_read(mm, addr, REG_BOARD_INFO, info, sizeof(switch_info_t), UPG_RW_TIMEOUT);
+    if(r==0) {
+        LOGD("___board %d ver: %s\n",  addr, info->ver);
+        LOGD("___board %d date: %s\n", addr, info->date);
+    }
+    return r;
+}
+
+static int set_info(handle_t l, node_t *nd, node_t *xd, void *arg, int *act)
+{
+    board_info_t *info1=(board_info_t*)nd->buf;
+    board_info_t *info2=(board_info_t*)xd->buf;
+
+    if(info1->addr<=0) {
+        info2->status = info1->status;
+        return 0;
+    }
+    else {
+        if(info1->addr==info2->addr) {
+            *act = LIST_ACT_STOP;
+            *info2 = *info1;
+            return 0;
+        }
+        else {
+            return -1;
+        }
+    }
+}
+static int board_info_set(board_info_t *info)
+{
+    int r=-1;
+    node_t node;
+    handle_t l=uHandle.all;
+
+    node.buf = info;
+    node.dlen = sizeof(board_info_t);
+    node.blen = sizeof(board_info_t);
+    r = xlist_iterator(l, &node, set_info, NULL);
+    return r;
+}
+static int board_send(Modbus_Manger *mm, uint16_t addr, char *data, int dlen)
+{
+    int r,pid=0;
+    char temp[400];
+    int slen=0,onelen=0,onemax=128;
+
+    upg_pkt_t *pkt=(upg_pkt_t*)temp;
+    r = board_upgrade_jump(mm, addr);
+    while(1) {
+        if((slen+onemax)>=dlen) {
+            //onelen = dlen-(slen+onemax);
+            onelen = onemax;
+            pid = -1;
+        }
+        else {
+            onelen = onemax;
+        }
+        memcpy(pkt->data, data+slen, onelen);
+        pkt->pid = pid;
+        pkt->dlen = onelen;
+        r = mb_write(mm, addr, REG_UPG_WRITE, pkt, onelen+sizeof(upg_pkt_t), 10);
+        slen += onelen;
+        if(pid==0) sleep(1);
+        else       usleep(10000);
+
+        if(pid<0) break;
+        pid++;
+    }
+    sleep(1);
+
+    return 0;
+}
+static int board_proc(upg_handle_t *h, int quit)
+{
+    int ok=0,err=0;
+    buf_t fbuf;
+    int i,r,timeout;
+    switch_info_t swinfo;
+    handle_t l=h->upg;
+    list_node_t *ln=NULL;
+    board_info_t info,*tmp;
+    Modbus_Manger *mm=&h->dm->_globalRelaySampManger;
+
+    r = file_load(h->arg.path, &fbuf);
+    if(r) {
+        return -1;
+    }
+    info.addr = -1;
+    info.status = UPGRADING;
+    board_info_set(&info);
+
+    //broadcase upgrade file
+    board_send(mm, 0, fbuf.buf, fbuf.dlen);
+    while(1) {
+        r = xlist_get_node(l, &ln, 0);
+        if(r) {
+            break;
+        }
+
+        tmp = (board_info_t*)ln->data.buf;
+        for(i=0; i<RETRY_MAX; i++) {
+            r = board_get_info(mm, tmp->addr, &swinfo);
+            if(r==0) {
+                break;
+            }
+            LOGE("___ board upgrade failed, retry %d\n", i+1);
+            board_send(mm, i, fbuf.buf, fbuf.dlen);
+        }
+
+        if(r) {
+            tmp->status = UPGRADE_FAIL;
+            err++;
+        }
+        else {
+            sw_to_info(tmp->addr, tmp, &swinfo, UPGRADE_OK);
+            ok++;
+        }
+        board_info_set(tmp);
+        
+        xlist_remove(l, 0);
+    }
+    free(fbuf.buf);
+
+    exit(0);        //restart app
+
+    return 0;
+}
+static int board_scan(void)
+{
+    int i,r;
+    board_info_t info={0};
+    upg_handle_t *h=&uHandle;
+    handle_t l=h->upg;
+    Modbus_Manger *mm=&h->dm->_globalRelaySampManger;
+    
+    for(i=1; i<=h->dm->brdMax; i++) {
+        r = board_is_upgrading(mm, i);
+        if(r) {
+            info.addr = i;
+            info.status = UPGRADE_FAIL;
+            xlist_append(l, 0, &info, sizeof(info));
+        }
+    }
+
+    return 0;
+}
+
+static void start_threads(int flag)
+{
+    if(flag) {
+        thread_start2(THREAD_ID_SNMP);
+        thread_start2(THREAD_ID_POWER);
+        //thread_start2(THREAD_ID_CASCADE);
+        //thread_start2(THREAD_ID_CASCADE_SCAN);
+        //thread_start2(THREAD_ID_BREAKER);
+        //thread_start2(THREAD_ID_BREAKER_SCANNER);
+    }
+    else {
+        thread_stop(THREAD_ID_SNMP);
+        thread_stop(THREAD_ID_POWER);
+        //thread_stop(THREAD_ID_CASCADE);
+        //thread_stop(THREAD_ID_CASCADE_SCAN);
+        //thread_stop(THREAD_ID_BREAKER);
+        //thread_stop(THREAD_ID_BREAKER_SCANNER);
+    }
+}
+static void* board_thread(void *arg)
+{
+    int r;
+    thread_handle_t *th=(thread_handle_t*)arg;
+    upg_handle_t *h=(upg_handle_t*)th->arg;
+    Modbus_Manger *mm=&h->dm->_globalRelaySampManger;
+
+    board_scan();
+    upg_board_all_update();
+
+    while(th->quit==0) {
+        if(h->arg.upging) {
+            
+            start_threads(0);
+            r = board_proc(h, th->quit);
+            start_threads(1);
+            
+            file_remove(h->arg.path);
+            h->arg.upging = 0;
+        }
+        else {
+            sleep(2);
+        }
+    }
+    pthread_exit(NULL);
+}
+/////////////////////////////////////////////////////
+int upg_init(void)
+{
+    int r,msgid;
+    list_cfg_t lc={0,LIST_FULL_FIFO,-1};
+    upg_handle_t *h=&uHandle;
+    
+    memset(h, 0, sizeof(upg_handle_t));
+    h->dm = &__globalDeviceManage;
+
+    h->key = ftok(UPG_KEY_PATH, UPG_KEY_SN);
+    if(h->key<0) {
+        LOGE("ftok %s failed, errno: %d\n", UPG_KEY_PATH, errno);
+        return -1;
+    }
+
+    h->upg = xlist_init(&lc);
+    h->all = xlist_init(&lc);
+    h->init = 1;
+
+#ifdef USE_BOARD_UPGRADE
+    thread_start(THREAD_ID_BOARD, board_thread, h);
+#endif
+
+    upg_host_send(UPGRADE_EVT_APP_RUNNING);
+    
+    return 0;
+}
+
+int upg_host_send(int evt)
+{
+    int r,msgid;
+    msgbuf_t mb;
+    upg_handle_t *h=&uHandle;
+
+    msgid = msgget(h->key, 0666|IPC_CREAT);
+    //LOGD("+++++++++++ key: %d, msgid: %d\n", ukey, msgid);
+    
+    mb.evt = evt;
+    r = msgsnd(msgid, &mb, sizeof(mb.evt), IPC_NOWAIT);
+    if(r<0) {
+        LOGE("msgsnd failed, %d, errno: %d\n", r, errno);
+    }
+    else {
+        LOGD("msgsnd evt 0x%02x ok\n", evt);
+    }
+    
+    return r;
+}
+
+
+/////////////////////////////////////////////////////////
+handle_t upg_board_list_get(void)
+{
+    upg_handle_t *h=&uHandle;
+    return h->upg;
+}
+
+int upg_board_list_set(char *s)
+{
+    int i=0,n=0,max=0;
+    char tmp[10],*p=s;
+    char *tok="productId=";
+    board_info_t info={0};
+    handle_t l=uHandle.upg;
+
+    if(!s) {
+        return -1;
+    }
+
+    p = strstr(p, tok);
+    if(!p) {
+        return -1;
+    }
+    p += strlen(tok);
+
+    while(1) {
+        if((*p)==',' || (*p)=='&') {
+            tmp[i] = 0;
+            info.addr = atoi(tmp);
+            xlist_append(l, 0, &info, sizeof(info));
+
+            i = 0; n++;
+            if((*p)=='&') {
+                break;
+            }
+        }
+        else {
+            tmp[i++] = *p;
+        }
+        p++;
+    }
+
+    return (n>0)?0:-1;
+}
+
+
+handle_t upg_board_all_get(void)
+{
+    int r;
+    upg_handle_t *h=&uHandle;
+    return h->all;
+}
+
+int upg_board_all_update(void)
+{
+    int i,r,addr;
+    list_node_t *ln=NULL;
+    upg_handle_t *h=&uHandle;
+    handle_t l=h->all;
+    Modbus_Manger *mm=&h->dm->_globalRelaySampManger;
+    GlobalPowerManger *tmp,*hd=&h->dm->_globalPowerManger;
+    switch_info_t swinfo;
+    board_info_t  info;
+
+    if(!h->init) {
+        return -1;
+    }
+
+    xlist_clear(l);
+    list_for_each_entry(tmp,&hd->list,list) {
+        if(tmp->product_saddr>0) {
+            addr = tmp->product_saddr;
+            for(i=0; i<RETRY_MAX; i++) {
+                r = board_get_info(mm, addr, &swinfo);
+                if(r==0) {
+                    sw_to_info(addr, &info, &swinfo, ONLINE);
+                    xlist_append(l, 0, &info, sizeof(info));
+                    break;
+                }
+            }
+        }
+    }
+
+    while(1) {
+        r = xlist_take_node(h->upg, &ln, 0);
+        if(r) {
+            break;
+        }
+        xlist_append_node(h->all, ln);
+    }
+
+    return 0;
+}
+
+static int fw_check(char *path);
+int upg_board_start(char *path)
+{
+    upg_handle_t *h=&uHandle;
+
+    if(h->arg.upging==1) {
+        return -1;
+    }
+
+    strcpy(h->arg.path,path);
+    h->arg.upging = 1;
+
+    return 0;
+}
+
+#include "md5.h"
+#include "file.h"
+#define FW_HEAD_MAGIC "GOWONE_UPGRADE"
+#pragma pack (1)
+typedef union {
+	struct {
+		uint8_t         magic[14];
+		uint16_t        size;
+		uint32_t        partition;
+		uint32_t		version;
+	}hdr;
+	uint8_t				padd[128];
+}fw_hdr_t;
+#pragma pack ()
+
+#define CHAR(b) (((b)<=9)?((b)+0x30):((b)-10+0x61));
+static void byte2char(char *chr, uint8_t b)
+{
+    chr[0] = CHAR(b>>4);
+    chr[1] = CHAR(b&0x0f);
+}
+static void print_md5(char *s, md5_t *m)
+{
+    int i;
+    
+    printf("__%s", s);
+    for(i=0; i<32; i++) {
+        printf("%c", m->data[i]);
+    }
+    printf("\n");
+}
+//md5相同返回0,否则返回1
+static int md5_check(buf_t *fb)
+{
+    md5_t m1,m2;
+    md5_ctx_t ctx;
+    uint8_t i,tmp[16];
+
+    md5_init(&ctx);
+    md5_update(&ctx, (uint8_t*)fb->buf, fb->dlen-32);
+    md5_final(&ctx, tmp);
+
+    for (i=0; i<16; i++) {
+        byte2char(&m2.data[i*2], tmp[i]);
+    }
+    memcpy(&m1, fb->buf+fb->dlen-32, sizeof(md5_t));
+
+    print_md5("ori md5: ", &m1);
+    print_md5("cal md5: ", &m2);
+    if(memcmp(&m1, &m2, sizeof(md5_t))) {
+        return -1;
+    }
+
+    return 0;
+}
+
+int upg_board_file_check(char *path)
+{
+    int r=UPG_OK;
+    buf_t fb;
+    upg_handle_t *h=&uHandle;
+
+    if(h->arg.upging==1) {
+        return UPG_BUSYING;
+    }
+
+    r = file_load(path, &fb);
+    if(r) {
+        return -1;
+    }
+
+    fw_hdr_t *fh=(fw_hdr_t*)fb.buf;
+    if(memcmp(fh->hdr.magic,FW_HEAD_MAGIC,sizeof(FW_HEAD_MAGIC))) {
+        LOGE("not found %s, invalid board firmware\n", FW_HEAD_MAGIC);
+        r = UPG_HDR_FAIL;
+    }
+
+    if(md5_check(&fb)) {
+        LOGE("md5 check failed, invalid board firmware\n");
+        r = UPG_MD5_FAIL;
+    }
+    free(fb.buf);
+
+    return r;
+}
+
+int upg_host_file_check(char *path)
+{
+    return 0;
+}

+ 27 - 0
f407/applications/upg.h

@@ -0,0 +1,27 @@
+#ifndef __UPG_Hx__
+#define __UPG_Hx__
+
+#include "upgrade.h"
+#include "common.h"
+#include "xlist.h"
+
+enum {
+    UPG_OK=0,
+    UPG_BUSYING,
+    UPG_HDR_FAIL,
+    UPG_MD5_FAIL,
+};
+
+
+int upg_init(void);
+int upg_host_send(int evt);
+
+int upg_board_list_set(char *s);
+handle_t upg_board_all_get(void);
+int upg_board_all_update(void);
+int upg_board_start(char *path);
+
+int upg_host_file_check(char *path);
+int upg_board_file_check(char *path);
+#endif
+

+ 1 - 1
f407/rt-thread/components/fal/samples/porting/fal_flash_sfud_port.c

@@ -17,7 +17,7 @@
 #endif
 
 #ifndef FAL_USING_NOR_FLASH_DEV_NAME
-#define FAL_USING_NOR_FLASH_DEV_NAME             "norflash0"
+#define FAL_USING_NOR_FLASH_DEV_NAME             "nor"
 #endif
 
 static int init(void);

+ 87 - 0
f407/tools/mb/cfg.h

@@ -0,0 +1,87 @@
+#ifndef _CFG_H_
+#define _CFG_H_
+
+#include "stdint.h"
+
+
+
+#define BOOT_LOADER              					((uint32_t)(0x08000000))	      	//boot loadr addr
+#define BOOT_LOADER_SIZE									(20*1024)													//boot loade size
+
+
+#define META_DATA 				 								((uint32_t)(0x08005000))					//meta data addr
+#define META_DATA_SIZE     								(1*1024)													//meta data size
+
+
+#define PROGRAME_APP1			 								((uint32_t)(0x08005400))					//App1 Rom Start addr
+#define PROGRAME_APP1_SIZE								(50*1024)													//App1 programe Max size
+
+
+#define PROGRAME_APP2											((uint32_t)(0x08011C00))					//App2 Rom Start addr
+#define PROGRAME_APP2_SIZE								(50*1024)													//App2 programe Max size
+
+#define VERSION                          		"V1.0.0.0"
+
+#define MODBUS_HEAD                        	"GOWONE_UPGRADE"
+
+#define PARTITION													 	 (1)															//upgrade patition
+#define PAGE_SIZE              						 (1024)
+
+
+
+#define UPGRADE_FLAG_ADDR									 (META_DATA		  )
+#define STARTUP_PARTATION									 (META_DATA + 4 )								//Start area
+#define STARTUP_ERROR											 (META_DATA + 8 )								//The most recent error code
+#define STARTUP_NUMBEAR										 (META_DATA + 12)								//the count of fataly error
+#define	STARTUP_ROM_ADDR									 (META_DATA + 16)
+#define STARTUP_LAST_RUNNING_TIME					 (META_DATA + 20)								//
+#define STARTUP_APP_VERSION								 (META_DATA + 24)								//
+
+
+#define APP1_VERSION											 (META_DATA + 28)
+#define APP1_ROM_ADDR											 (META_DATA + 32)
+#define APP1_PARTATION										 (META_DATA + 36)
+
+#define APP2_VERSION											 (META_DATA + 40)
+#define APP2_ROM_ADDR											 (META_DATA + 44)
+#define APP2_PARTATION										 (META_DATA + 48)
+
+#define APP1_MD5													 (META_DATA + 52)
+#define APP2_MD5 													 (META_DATA + 84)
+
+
+
+#define UNIQU_1                       			0x1FFFF7AC
+#define UNIQU_2                       			0x1FFFF7B0
+#define UNIQU_3                       			0x1FFFF7B4
+
+
+typedef struct {
+	uint32_t operation_flag;						// 0
+	uint32_t partition;									// 1
+	uint32_t errno;											// 0
+	uint32_t error_count;								// 0
+	uint32_t rom_addr;									// PROGRAME_APP1 0x08005400
+	uint32_t recent_running_time;				// 0
+	uint32_t running_app_version;				// V1.0.0.0   (1<<24 | 0 << 16 | 0 << 8 | 0)
+	uint32_t app1_version;							// V1.0.0.0   (1<<24 | 0 << 16 | 0 << 8 | 0)
+	uint32_t app1_rom_addr;							// PROGRAME_APP1 0x08005400
+	uint32_t app1_partition;						// 1
+	uint32_t app2_version;							// V1.0.0.0   (1<<24 | 0 << 16 | 0 << 8 | 0)
+	uint32_t app2_rom_addr;							// PROGRAME_APP2 0x0800A400
+	uint32_t app2_partition;						// 2
+}META_DATA_S;
+
+
+typedef struct {
+		uint32_t uniq_ID_64_95;
+		uint32_t uniq_ID_32_63;
+		uint32_t uniq_ID_00_31;
+    int  channels;
+		char ver[8];
+    char date[20];
+}information_t;
+
+
+#endif
+

+ 507 - 0
f407/tools/mb/mb.cpp

@@ -0,0 +1,507 @@
+#include <windows.h>
+#include <tchar.h>
+#include <time.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+#include "md5.h"
+
+//https://blog.csdn.net/phunxm/article/details/5082618
+//https://blog.csdn.net/byxdaz/article/details/80507510
+
+
+#pragma pack (1)
+typedef struct {
+	uint8_t	 digit[32];
+}md5_t;
+typedef struct {
+	char  *data;
+	uint32_t blen;
+	uint32_t dlen;
+}data_t;
+typedef union {
+	struct {
+		uint8_t         magic[14];
+		uint16_t        size;
+		uint32_t        partition;
+		uint32_t		version;
+		char            md5[32];
+	}hdr;
+	uint8_t				padd[128];
+}fw_hdr_t;
+typedef struct {
+	uint32_t operation_flag;				// 0
+	uint32_t partition;						// 1
+	uint32_t err;							// 0
+	uint32_t error_count;					// 0
+	uint32_t rom_addr;						// PROGRAME_APP1 0x08005400
+	uint32_t recent_running_time;			// 0
+	uint32_t running_app_version;			// V1.0.0.0   (1<<24 | 0 << 16 | 0 << 8 | 0)
+	uint32_t app1_version;					// V1.0.0.0   (1<<24 | 0 << 16 | 0 << 8 | 0)
+	uint32_t app1_rom_addr;					// PROGRAME_APP1 0x08005400
+	uint32_t app1_partition;				// 1
+	uint32_t app2_version;					// V1.0.0.0   (1<<24 | 0 << 16 | 0 << 8 | 0)
+	uint32_t app2_rom_addr;					// PROGRAME_APP2 0x0800A400
+	uint32_t app2_partition;				// 1
+	char     md5_1[32];
+	char     md5_2[32];
+	uint32_t app1_len;
+	uint32_t app2_len;
+}fw_info_t;
+
+typedef struct {
+	data_t boot;
+	data_t info;
+	data_t app1;
+	data_t app2;
+}fw_image_t;
+#pragma pack ()
+
+static void print_md5(const char* s, char* m)
+{
+	uint8_t i; 
+
+	printf("__%s", s);
+	for (i = 0; i < 32; i++) {
+		printf("%c", m[i]);
+	}
+	printf("\n");
+}
+static char* my_malloc(uint32_t len)
+{
+	char* p = (char*)malloc(len);
+	if (p) {
+		memset(p, 0xff, len);
+	}
+	return p;
+}
+static int str_cpy(char *dst, char *src)
+{
+	char* p = strchr(src, '"');
+	if (!p) {
+		return -1;
+	}
+	p += 1;
+
+	while ((*p) != '"') {
+		*dst++ = *p++;
+	}
+	*dst = 0;
+
+	return 0;
+}
+static int digit_cpy(char* dst, char* src)
+{
+	int x = 10;
+	char* p = src;
+
+	if (p[0] == '0' && (p[1]=='x' || p[1]=='X')) {
+		memcpy(dst, p, 2);
+		dst += 2; p += 2;
+		x = 16;
+	}
+
+	while (isxdigit(*p)) {
+		*dst++ = *p++;
+	}
+	*dst = 0;
+
+	return x;
+}
+static char* get_token(char *buf, const char *tok)
+{
+	char* p = strstr(buf, tok);
+	if (!p) {
+		printf("%s not found!!!\n", tok);
+		return NULL;
+	}
+	p += strlen(tok);
+
+	while (isblank(*p)) p++;
+	return p;
+}
+static uint32_t get_addr(char* buf, const char* tok)
+{
+	int x;
+	char tmp[100];
+	char* p = get_token(buf, tok);
+	if (!p) {
+		return -1;
+	}
+	x = digit_cpy(tmp, p);
+	return (uint32_t)strtol(tmp, NULL, x);
+}
+static char* strstr_line(char *s, const char *tok)
+{
+	char* p1 = strstr(s, tok);
+	char* p2 = strchr(s, '\n');
+
+	if (p1 && p2 && p1<p2) {
+		return p1;
+	}
+	return NULL;
+}
+static uint32_t get_int(char* buf, const char* tok)
+{
+	int x;
+	uint32_t v = 1;
+	char *t,tmp[100];
+	char* p = get_token(buf, tok);
+	if (!p) {
+		return -1;
+	}
+	t = strstr_line(p, "0x");
+	if (!t) {
+		t = strstr_line(p, "0X");
+	}
+	if (t) {
+		p = t;
+	}
+
+	while (1) {
+		if (isdigit(*p)) {
+			x = digit_cpy(tmp, p);
+			v *= strtol(tmp, NULL, x);
+			p += strlen(tmp);
+		}
+		else {
+			if (!isgraph(*p)) {
+				break;
+			}
+			p++;
+		}
+	}
+
+	return v;
+}
+/////////////////////////////////////////////
+static uint32_t get_version(char *buf, const char *tok)
+{
+	char tmp[10];
+	uint32_t v, i = 0, j = 3;
+	uint8_t* p8 = (uint8_t*)&v;
+	char* p = get_token(buf, tok);
+
+	if (!p) {
+		return -1;
+	}
+	while (!isdigit(*p)) p++;
+
+	while (*p) {
+		if (isdigit(*p)) {
+			tmp[i++] = *p;
+		}
+		else {
+			if (!isgraph(*p)) {
+				break;
+			}
+			if (i > 0) {
+				tmp[i] = 0;
+				p8[j--] = (uint8_t)atoi(tmp);
+			}
+			i = 0;
+		}
+		p++;
+	}
+	return v;
+}
+static int get_magic(char *buf, const char *tok, void *magic)
+{
+	static char tmp[500];
+	char* p = get_token(buf, tok);
+	if (!p) {
+		return -1;
+	}
+	str_cpy(tmp, p);
+	memcpy(magic, tmp, strlen(tmp));
+	return 0;
+}
+static int get_info(char *buf, fw_hdr_t *hdr, fw_info_t *inf, fw_image_t *img)
+{
+	uint32_t version = get_version(buf, "VERSION");
+	uint32_t partition = get_int(buf, "PARTITION");
+	uint32_t rom_addr = get_int(buf, "PROGRAME_APP1");
+
+	//fill hdr
+	memset(hdr, 0xff, sizeof(fw_hdr_t));
+	get_magic(buf, "MODBUS_HEAD", hdr->hdr.magic);
+	hdr->hdr.size = 0;
+	hdr->hdr.version = version;
+	hdr->hdr.partition = partition;
+	
+	//fill inf
+	inf->operation_flag = 0;			                    // 0
+	inf->partition = 1;					                    // 1
+	inf->err = 0;						                    // 0
+	inf->error_count = 0;				                    // 0
+	inf->rom_addr = rom_addr;			                    // PROGRAME_APP1 0x08005400
+	inf->recent_running_time;			                    // 0
+	inf->running_app_version;			                    // V1.0.0.0   (1<<24 | 0 << 16 | 0 << 8 | 0)
+	inf->app1_version = version;							// V1.0.0.0   (1<<24 | 0 << 16 | 0 << 8 | 0)
+	inf->app1_rom_addr = rom_addr;							// PROGRAME_APP1 0x08005400
+	inf->app1_partition = 1;								// 1
+	inf->app2_version = version;							// V1.0.0.0   (1<<24 | 0 << 16 | 0 << 8 | 0)
+	inf->app2_rom_addr = get_int(buf, "PROGRAME_APP2");		// PROGRAME_APP2 0x0800A400
+	inf->app2_partition = 2;								// 1
+
+	//fill img
+	img->boot.blen = get_int(buf, "BOOT_LOADER_SIZE");
+	img->boot.data = my_malloc(img->boot.blen);
+
+	img->info.blen = get_int(buf, "META_DATA_SIZE");
+	img->info.data = my_malloc(img->info.blen);
+
+	img->app1.blen = get_int(buf, "PROGRAME_APP1_SIZE");
+	img->app1.data = my_malloc(img->app1.blen);
+
+	img->app2.blen = get_int(buf, "PROGRAME_APP2_SIZE");
+	img->app2.data = my_malloc(img->app2.blen);
+
+	return 0;
+}
+/////////////////////////////////////////////
+static TCHAR* char_to_tchar(char* str)
+{
+	DWORD dwNum = 0;
+	dwNum = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
+	TCHAR* pUni = new TCHAR[dwNum];
+	MultiByteToWideChar(CP_ACP, 0, str, -1, pUni, dwNum);
+	return pUni;
+}
+
+static int file_read(const TCHAR* path, data_t *data)
+{
+	int r=-1;
+	HANDLE hFile;
+	DWORD  flen,rlen;
+
+	hFile = CreateFile(path,			//name
+		GENERIC_READ,                   //以读方式打开
+		FILE_SHARE_READ,                //可共享读
+		NULL,                           //默认安全设置
+		OPEN_EXISTING,                   //只打开已经存在的文件
+		FILE_ATTRIBUTE_NORMAL,           //常规文件属性
+		NULL);                           //无模板
+	if (hFile== INVALID_HANDLE_VALUE) {
+		_tprintf(_T("%s open failed\n"), path);
+		return -1;
+	}
+
+	flen = GetFileSize(hFile, NULL);
+	if (flen== INVALID_FILE_SIZE) {
+		printf("invalid file len\n");
+		goto quit;
+	}
+
+	if(data->data==NULL) {
+		data->data = (char*)malloc(flen);
+		if (data->data == NULL) {
+			printf("___ data->data is NULL\n");
+			goto quit;
+		}
+	}
+	data->dlen = flen;
+	
+	r = ReadFile(hFile, data->data, data->dlen, &rlen, NULL);
+	if (r==FALSE) {
+		_tprintf(_T("%s read failed\n"), path);
+		goto quit;
+	}
+	r = 0;
+
+quit:
+	CloseHandle(hFile);
+
+	return r;
+}
+
+static int get_time(TCHAR* path, char* time, int len)
+{
+	FILETIME IpCreationTime;                 //文件的创建时间
+	FILETIME IpLastAccessTime;               //对文件的最近访问时间
+	FILETIME IpLastWriteTime;                //文件的最近修改时间
+	FILETIME ltime;
+	SYSTEMTIME rtime;
+
+	HANDLE hFile = CreateFile(path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+	if (hFile == INVALID_HANDLE_VALUE)
+	{
+		printf("Get the dictionary failed!\n");
+		CloseHandle(hFile);
+		return -1;
+	}
+	if (!GetFileTime(hFile, &IpCreationTime, &IpLastAccessTime, &IpLastWriteTime)) {
+		return -1;
+	}
+	CloseHandle(hFile);
+
+	FileTimeToLocalFileTime(&IpLastWriteTime, &ltime);
+	FileTimeToSystemTime(&ltime, &rtime);        //将文件时间转化为系统时间
+	snprintf(time, len, "%04u%02u%02u_%02u%02u%02u", rtime.wYear, rtime.wMonth, rtime.wDay, rtime.wHour, rtime.wMinute, rtime.wSecond);
+
+	return 0;
+}
+static int get_ver(char *ver, uint32_t v)
+{
+	uint8_t* p = (uint8_t*) & v;
+	sprintf(ver, "v%d.%d.%d.%d", p[3], p[2], p[1], p[0]);
+	return 0;
+}
+//////////////////////////////////////////
+static TCHAR* cfgPath = (TCHAR*)__TEXT("./cfg.h");
+
+int main(char argc, char *argv[])
+{
+	int r=0,flen;
+	HANDLE hFile=NULL;
+	char* path1, * path2;
+	char imgPath[500],*dot;
+	fw_hdr_t fwHdr = { 0 };
+	fw_info_t fwInfo = { 0 };
+	fw_image_t fwImg = { 0 };
+	data_t fcfg = {0}, fupg = {0};
+	char time1[100],time2[100],*ptime;
+	TCHAR* xpath1=NULL, * xpath2 = NULL,* xpath3 = NULL;
+	int make_single_bin = 0;
+	char version[32],md5[32];
+
+	if (argc==2) {
+		printf("make a upgrade file\n");
+	}
+	else if(argc == 3){
+		printf("make a single bin\n");
+		make_single_bin = 1;
+	}
+	else {
+		printf("usage: mb app.bin or mb boot.bin app.bin\n");
+		return -1;
+	}
+	r = file_read(cfgPath, &fcfg);
+	if (r) {
+		goto fail;
+	}
+	
+	get_info(fcfg.data, &fwHdr, &fwInfo, &fwImg);
+	get_ver(version, fwHdr.hdr.version);
+
+	path1 = argv[1];
+	if (make_single_bin) {
+		
+		xpath1 = char_to_tchar(path1);
+		flen = file_read(xpath1, &fwImg.boot);
+		if (flen < 0) {
+			goto fail;
+		}
+
+		path2 = argv[2];
+		xpath2 = char_to_tchar(path2);
+		flen = file_read(xpath2, &fwImg.app1);
+		if (flen < 0) {
+			goto fail;
+		}
+		md5_calc(fwImg.app1.data, fwImg.app1.dlen, md5);
+
+		if (fwImg.info.data) {
+			fwInfo.app1_len = fwImg.app1.dlen;
+			fwInfo.app2_len = fwImg.app1.dlen;
+
+			memcpy(fwInfo.md5_1, md5, sizeof(md5));
+			memcpy(fwInfo.md5_2, md5, sizeof(md5));
+			memcpy(fwImg.info.data, &fwInfo, sizeof(fwInfo));
+		}
+
+		get_time(xpath1, time1, sizeof(time1));
+		get_time(xpath2, time2, sizeof(time2));
+		if (memcmp(time1, time2, sizeof(time1)) > 0) {
+			ptime = time1;
+		}
+		else {
+			ptime = time2;
+		}
+
+		strcpy(imgPath, path1);
+		dot = strrchr(imgPath, '\\');
+		if (dot) {
+			dot[1] = 0;
+		}
+		else {
+			imgPath[0] = 0;
+		}
+
+		strcat(imgPath, "all_");
+		strcat(imgPath, version);
+		strcat(imgPath, "_");
+		strcat(imgPath, ptime);
+		strcat(imgPath, ".bin");
+
+		xpath3 = char_to_tchar(imgPath);
+		hFile = CreateFile(xpath3,			//name
+			GENERIC_WRITE,                  //以写方式打开
+			0,                              //可共享读
+			NULL,                           //默认安全设置
+			CREATE_ALWAYS,                  //创建新文件
+			FILE_ATTRIBUTE_NORMAL,          //常规文件属性
+			NULL);
+		if (!hFile) {
+			goto fail;
+		}
+		WriteFile(hFile, fwImg.boot.data, fwImg.boot.blen, NULL, NULL);
+		WriteFile(hFile, fwImg.info.data, fwImg.info.blen, NULL, NULL);
+		WriteFile(hFile, fwImg.app1.data, fwImg.app1.blen, NULL, NULL);
+		WriteFile(hFile, fwImg.app1.data, fwImg.app1.blen, NULL, NULL);
+	}
+	else {
+		xpath1 = char_to_tchar(path1);
+		flen = file_read(xpath1, &fupg);
+		if (flen < 0) {
+			goto fail;
+		}
+		get_time(xpath1, time1, sizeof(time1));
+
+		strcpy(imgPath, path1);
+		dot = strrchr(imgPath, '\\');
+		if (dot) {
+			dot[1] = 0;
+		}
+		else {
+			imgPath[0] = 0;
+		}
+
+		strcat(imgPath, "app_");
+		strcat(imgPath, version);
+		strcat(imgPath, "_");
+		strcat(imgPath, time1);
+		strcat(imgPath, ".upg");
+
+		xpath3 = char_to_tchar(imgPath);
+		hFile = CreateFile(xpath3,			//name
+			GENERIC_WRITE,                  //以写方式打开
+			0,                              //可共享读
+			NULL,                           //默认安全设置
+			CREATE_ALWAYS,                  //创建新文件
+			FILE_ATTRIBUTE_NORMAL,          //常规文件属性
+			NULL);
+		if (!hFile) {
+			goto fail;
+		}
+		
+		md5_calc(fupg.data, fupg.dlen, md5);
+
+		fwHdr.hdr.size = fupg.dlen;
+		memcpy(fwHdr.hdr.md5, md5, sizeof(md5));
+
+		WriteFile(hFile, &fwHdr, sizeof(fwHdr), NULL, NULL);
+		WriteFile(hFile, fupg.data, fupg.dlen, NULL, NULL);
+		//WriteFile(hFile, &md5, sizeof(md5), NULL, NULL);
+
+		print_md5("md5: ", md5);
+	}
+
+fail:
+	if(hFile) CloseHandle(hFile);
+	delete xpath1;delete xpath2;delete xpath3;
+
+	return r;
+}
+

+ 31 - 0
f407/tools/mb/mb.sln

@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.9.34902.65
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mb", "mb.vcxproj", "{2105DF33-3711-405F-8DDE-CDA04F7D926B}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|x64 = Debug|x64
+		Debug|x86 = Debug|x86
+		Release|x64 = Release|x64
+		Release|x86 = Release|x86
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{2105DF33-3711-405F-8DDE-CDA04F7D926B}.Debug|x64.ActiveCfg = Debug|x64
+		{2105DF33-3711-405F-8DDE-CDA04F7D926B}.Debug|x64.Build.0 = Debug|x64
+		{2105DF33-3711-405F-8DDE-CDA04F7D926B}.Debug|x86.ActiveCfg = Debug|Win32
+		{2105DF33-3711-405F-8DDE-CDA04F7D926B}.Debug|x86.Build.0 = Debug|Win32
+		{2105DF33-3711-405F-8DDE-CDA04F7D926B}.Release|x64.ActiveCfg = Release|x64
+		{2105DF33-3711-405F-8DDE-CDA04F7D926B}.Release|x64.Build.0 = Release|x64
+		{2105DF33-3711-405F-8DDE-CDA04F7D926B}.Release|x86.ActiveCfg = Release|Win32
+		{2105DF33-3711-405F-8DDE-CDA04F7D926B}.Release|x86.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {0558E62C-8D67-4FBA-AC34-BF1BD6ACF5E1}
+	EndGlobalSection
+EndGlobal

+ 138 - 0
f407/tools/mb/mb.vcxproj

@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <VCProjectVersion>17.0</VCProjectVersion>
+    <Keyword>Win32Proj</Keyword>
+    <ProjectGuid>{2105df33-3711-405f-8dde-cda04f7d926b}</ProjectGuid>
+    <RootNamespace>mb</RootNamespace>
+    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v143</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v143</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v143</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+    <UseOfMfc>false</UseOfMfc>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v143</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="Shared">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ConformanceMode>true</ConformanceMode>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="mb.cpp" />
+    <ClCompile Include="md5.c" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>

+ 25 - 0
f407/tools/mb/mb.vcxproj.filters

@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="源文件">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="头文件">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
+    </Filter>
+    <Filter Include="资源文件">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="mb.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
+    <ClCompile Include="md5.c">
+      <Filter>源文件</Filter>
+    </ClCompile>
+  </ItemGroup>
+</Project>

+ 7 - 0
f407/tools/mb/mb.vcxproj.user

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <LocalDebuggerCommandArguments>a.bin b.bin</LocalDebuggerCommandArguments>
+    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+  </PropertyGroup>
+</Project>

+ 191 - 0
f407/tools/mb/md5.c

@@ -0,0 +1,191 @@
+#include <string.h>
+#include "md5.h"  
+  
+uint8_t PADDING[]={0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};  
+  
+void md5_init(md5_ctx_t *ctx)
+{  
+    ctx->count[0] = 0;
+    ctx->count[1] = 0;
+    ctx->state[0] = 0x67452301;
+    ctx->state[1] = 0xEFCDAB89;
+    ctx->state[2] = 0x98BADCFE;
+    ctx->state[3] = 0x10325476;
+}  
+void md5_update(md5_ctx_t* ctx, uint8_t *input,uint32_t inputlen)
+{  
+    uint32_t i = 0,index = 0,partlen = 0;  
+    index = (ctx->count[0] >> 3) & 0x3F;
+    partlen = 64 - index;  
+    ctx->count[0] += inputlen << 3;
+    if(ctx->count[0] < (inputlen << 3))
+        ctx->count[1]++;
+    ctx->count[1] += inputlen >> 29;
+  
+    if(inputlen >= partlen)  
+    {  
+        memcpy(&ctx->buffer[index],input,partlen);
+        md5_transform(ctx->state, ctx->buffer);
+        for(i = partlen;i+64 <= inputlen;i+=64)  
+            md5_transform(ctx->state,&input[i]);
+        index = 0;          
+    }    
+    else  
+    {  
+        i = 0;  
+    }  
+    memcpy(&ctx->buffer[index],&input[i],inputlen-i);
+}  
+void md5_final(md5_ctx_t* ctx,uint8_t digest[16])
+{  
+    uint32_t index = 0,padlen = 0;  
+    uint8_t bits[8];  
+    index = (ctx->count[0] >> 3) & 0x3F;
+    padlen = (index < 56)?(56-index):(120-index);  
+    md5_encode(bits, ctx->count,8);
+    md5_update(ctx,PADDING,padlen);
+    md5_update(ctx,bits,8);
+    md5_encode(digest, ctx->state,16);
+}  
+void md5_encode(uint8_t *output,uint32_t *input,uint32_t len)  
+{  
+    uint32_t i = 0,j = 0;  
+    while(j < len)  
+    {  
+        output[j] = input[i] & 0xFF;    
+        output[j+1] = (input[i] >> 8) & 0xFF;  
+        output[j+2] = (input[i] >> 16) & 0xFF;  
+        output[j+3] = (input[i] >> 24) & 0xFF;  
+        i++;  
+        j+=4;  
+    }  
+}  
+void md5_decode(uint32_t *output,uint8_t *input,uint32_t len)  
+{  
+    uint32_t i = 0,j = 0;  
+    while(j < len)  
+    {  
+        output[i] = (input[j]) |  
+            (input[j+1] << 8) |  
+            (input[j+2] << 16) |  
+            (input[j+3] << 24);  
+        i++;  
+        j+=4;   
+    }  
+}  
+void md5_transform(uint32_t state[4],uint8_t block[64])  
+{  
+    uint32_t a = state[0];  
+    uint32_t b = state[1];  
+    uint32_t c = state[2];  
+    uint32_t d = state[3];  
+    uint32_t x[64];  
+    md5_decode(x,block,64);  
+    FF(a, b, c, d, x[ 0], 7, 0xd76aa478);   
+    FF(d, a, b, c, x[ 1], 12, 0xe8c7b756);   
+    FF(c, d, a, b, x[ 2], 17, 0x242070db);   
+    FF(b, c, d, a, x[ 3], 22, 0xc1bdceee);   
+    FF(a, b, c, d, x[ 4], 7, 0xf57c0faf);   
+    FF(d, a, b, c, x[ 5], 12, 0x4787c62a);   
+    FF(c, d, a, b, x[ 6], 17, 0xa8304613);   
+    FF(b, c, d, a, x[ 7], 22, 0xfd469501);   
+    FF(a, b, c, d, x[ 8], 7, 0x698098d8);   
+    FF(d, a, b, c, x[ 9], 12, 0x8b44f7af);   
+    FF(c, d, a, b, x[10], 17, 0xffff5bb1);   
+    FF(b, c, d, a, x[11], 22, 0x895cd7be);   
+    FF(a, b, c, d, x[12], 7, 0x6b901122);   
+    FF(d, a, b, c, x[13], 12, 0xfd987193);   
+    FF(c, d, a, b, x[14], 17, 0xa679438e);   
+    FF(b, c, d, a, x[15], 22, 0x49b40821);   
+  
+      
+    GG(a, b, c, d, x[ 1], 5, 0xf61e2562);   
+    GG(d, a, b, c, x[ 6], 9, 0xc040b340);   
+    GG(c, d, a, b, x[11], 14, 0x265e5a51);   
+    GG(b, c, d, a, x[ 0], 20, 0xe9b6c7aa);   
+    GG(a, b, c, d, x[ 5], 5, 0xd62f105d);   
+    GG(d, a, b, c, x[10], 9,  0x2441453);   
+    GG(c, d, a, b, x[15], 14, 0xd8a1e681);   
+    GG(b, c, d, a, x[ 4], 20, 0xe7d3fbc8);   
+    GG(a, b, c, d, x[ 9], 5, 0x21e1cde6);   
+    GG(d, a, b, c, x[14], 9, 0xc33707d6);   
+    GG(c, d, a, b, x[ 3], 14, 0xf4d50d87);   
+    GG(b, c, d, a, x[ 8], 20, 0x455a14ed);   
+    GG(a, b, c, d, x[13], 5, 0xa9e3e905);   
+    GG(d, a, b, c, x[ 2], 9, 0xfcefa3f8);   
+    GG(c, d, a, b, x[ 7], 14, 0x676f02d9);   
+    GG(b, c, d, a, x[12], 20, 0x8d2a4c8a);   
+  
+      
+    HH(a, b, c, d, x[ 5], 4, 0xfffa3942);   
+    HH(d, a, b, c, x[ 8], 11, 0x8771f681);   
+    HH(c, d, a, b, x[11], 16, 0x6d9d6122);   
+    HH(b, c, d, a, x[14], 23, 0xfde5380c);   
+    HH(a, b, c, d, x[ 1], 4, 0xa4beea44);   
+    HH(d, a, b, c, x[ 4], 11, 0x4bdecfa9);   
+    HH(c, d, a, b, x[ 7], 16, 0xf6bb4b60);   
+    HH(b, c, d, a, x[10], 23, 0xbebfbc70);   
+    HH(a, b, c, d, x[13], 4, 0x289b7ec6);   
+    HH(d, a, b, c, x[ 0], 11, 0xeaa127fa);   
+    HH(c, d, a, b, x[ 3], 16, 0xd4ef3085);   
+    HH(b, c, d, a, x[ 6], 23,  0x4881d05);   
+    HH(a, b, c, d, x[ 9], 4, 0xd9d4d039);   
+    HH(d, a, b, c, x[12], 11, 0xe6db99e5);   
+    HH(c, d, a, b, x[15], 16, 0x1fa27cf8);   
+    HH(b, c, d, a, x[ 2], 23, 0xc4ac5665);   
+  
+      
+    II(a, b, c, d, x[ 0], 6, 0xf4292244);   
+    II(d, a, b, c, x[ 7], 10, 0x432aff97);   
+    II(c, d, a, b, x[14], 15, 0xab9423a7);   
+    II(b, c, d, a, x[ 5], 21, 0xfc93a039);   
+    II(a, b, c, d, x[12], 6, 0x655b59c3);   
+    II(d, a, b, c, x[ 3], 10, 0x8f0ccc92);   
+    II(c, d, a, b, x[10], 15, 0xffeff47d);   
+    II(b, c, d, a, x[ 1], 21, 0x85845dd1);   
+    II(a, b, c, d, x[ 8], 6, 0x6fa87e4f);   
+    II(d, a, b, c, x[15], 10, 0xfe2ce6e0);   
+    II(c, d, a, b, x[ 6], 15, 0xa3014314);   
+    II(b, c, d, a, x[13], 21, 0x4e0811a1);   
+    II(a, b, c, d, x[ 4], 6, 0xf7537e82);   
+    II(d, a, b, c, x[11], 10, 0xbd3af235);   
+    II(c, d, a, b, x[ 2], 15, 0x2ad7d2bb);   
+    II(b, c, d, a, x[ 9], 21, 0xeb86d391);   
+    state[0] += a;  
+    state[1] += b;  
+    state[2] += c;  
+    state[3] += d;  
+}
+
+#define CHAR(b) (b<=9)?(b+0x30):(b-10+0x61);
+static void byte2char(char *chr, uint8_t b)
+{
+    char h,l;
+    
+    l = b&0x0f;
+    h = (b>>4)&0x0f;
+    
+    chr[0] = CHAR(h);
+    chr[1] = CHAR(l);
+}
+
+int md5_calc(void *p, int len, char *md5)
+{
+    int i;
+    uint8_t tmp[16];
+    md5_ctx_t ctx;
+    
+    md5_init(&ctx);
+    md5_update(&ctx, (uint8_t*)p, len);
+    md5_final(&ctx, tmp);
+    
+    for (i=0; i<16; i++) {
+        byte2char(&md5[i*2], tmp[i]);
+    }
+    
+    return 0;
+}
+

+ 68 - 0
f407/tools/mb/md5.h

@@ -0,0 +1,68 @@
+#ifndef MD5_H  
+#define MD5_H  
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct
+{
+	uint32_t count[2];
+	uint32_t state[4];
+	uint8_t buffer[64];
+}md5_ctx_t;
+
+
+#define F(x,y,z) ((x & y) | (~x & z))  
+#define G(x,y,z) ((x & z) | (y & ~z))  
+#define H(x,y,z) (x^y^z)  
+#define I(x,y,z) (y ^ (x | ~z))  
+#define ROTATE_LEFT(x,n) ((x << n) | (x >> (32-n)))  
+
+#define FF(a,b,c,d,x,s,ac) \
+	{ \
+		a += F(b, c, d) + x + ac; \
+		a = ROTATE_LEFT(a, s); \
+		a += b; \
+	}
+
+#define GG(a,b,c,d,x,s,ac) \
+	{ \
+		a += G(b, c, d) + x + ac; \
+		a = ROTATE_LEFT(a, s); \
+		a += b; \
+	}
+
+#define HH(a,b,c,d,x,s,ac) \
+	{ \
+		a += H(b, c, d) + x + ac; \
+		a = ROTATE_LEFT(a, s); \
+		a += b; \
+	}
+
+#define II(a,b,c,d,x,s,ac) \
+	{ \
+		a += I(b, c, d) + x + ac; \
+		a = ROTATE_LEFT(a, s); \
+		a += b; \
+	}
+
+void md5_init(md5_ctx_t* context);
+void md5_update(md5_ctx_t* context, uint8_t* input, uint32_t inputlen);
+void md5_final(md5_ctx_t* context, uint8_t digest[16]);
+void md5_transform(uint32_t state[4], uint8_t block[64]);
+void md5_encode(uint8_t* output, uint32_t* input, uint32_t len);
+void md5_decode(uint32_t* output, uint8_t* input, uint32_t len);
+
+int md5_calc(void* p, int len, char* md5);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+#endif  

+ 104 - 0
f407/tools/mb/mu.cpp

@@ -0,0 +1,104 @@
+#include "myFile.h"
+#include "protocol.h"
+#include "datetime.h"
+#include "md5.h"
+
+
+TCHAR* cfgPath = (TCHAR*)__TEXT("./user/cfg.h");
+
+static void print_fw(const char* s, fw_hdr_t* hdr)
+{
+	printf("\n");
+	printf("__%s__hdr.fw.magic:     0x%08x\n", s, hdr->fw.magic);
+	printf("__%s__hdr.fw.version:   %s\n", s, hdr->fw.version);
+	printf("__%s__hdr.fw.length:    %d\n", s, hdr->fw.length);
+	printf("__%s__hdr.fw.bldtime:   %s\n", s, hdr->fw.bldtime);
+
+	printf("__%s__hdr.upg.obj:      %d\n", s, hdr->upg.obj);
+	printf("__%s__hdr.upg.force:    %d\n", s, hdr->upg.force);
+	printf("__%s__hdr.upg.erase:    %d\n", s, hdr->upg.erase);
+	printf("__%s__hdr.upg.flag :    %d\n", s, hdr->upg.flag);
+	printf("__%s__hdr.upg.jumpAddr: 0x%08x\n", s, hdr->upg.jumpAddr);
+	printf("\n");
+}
+
+
+static void print_md5(const char* s, md5_t* m)
+{
+	U8 i;
+
+	printf("__%s", s);
+	for (i = 0; i < 32; i++) {
+		printf("%c", m->digit[i]);
+	}
+	printf("\n");
+}
+
+int main(char argc, char *argv[])
+{
+	int r;
+	FILE* fp;
+	data_t dat;
+	md5_t md5;
+	char newPath[1000];
+	fw_hdr_t hdr;
+	char* path = argv[1];
+	//char* goal = argv[1];
+	TCHAR* xPath;
+	myFile mf;
+
+	//TCHAR curPath[500];
+	//GetCurrentDirectory(500, curPath);
+	//_tprintf(_T("curPath: %s\n"), curPath);
+    
+	if(argc<2) {
+		printf("usage: mu.exe app.bin\n");
+		return -1;
+	}
+
+	xPath = mf.char_to_tchar(path);
+	if (!xPath) {
+		printf("char_to_tchar failed\n");
+		return -1;
+	}
+
+	strcpy(newPath, path);
+	char* dot = strrchr(newPath, '.');
+	if (dot) *(dot + 1) = 0;
+	strcat(newPath, "upg");
+
+	fp = fopen(newPath, "wb");
+	if (!fp) {
+		printf("%s create failed\r\n", newPath);
+		return -1;
+	}
+
+	r = mf.read_file(xPath, &dat);
+	if (r) {
+		return -1;
+	}
+
+	hdr.upg.obj = OBJ_APP;
+	hdr.upg.force = 0;
+	hdr.upg.erase = 0;
+	hdr.upg.flag = 0;
+	hdr.upg.jumpAddr = 0;
+	hdr.fw.magic = FW_MAGIC;
+	hdr.fw.length = dat.dlen;
+	mf.get_version(cfgPath, hdr.fw.version, sizeof(hdr.fw.version));
+	mf.get_time(xPath, (char*)hdr.fw.bldtime, sizeof(hdr.fw.bldtime));
+	print_fw("$$$", &hdr);
+
+	md5_calc(&hdr, sizeof(hdr), dat.data, dat.dlen, (char*)md5.digit);
+	fwrite(&hdr, 1, sizeof(hdr), fp);
+	fwrite(dat.data, 1, dat.dlen, fp);
+	fwrite(&md5, 1, sizeof(md5), fp);
+	print_md5("md5: ", &md5);
+
+	fclose(fp);
+	free(dat.data);
+	delete xPath;
+
+	return 0;
+}
+