linux网络项目——基于WebServer的工业数据采集项目

linux网络项目——基于WebServer的工业数据采集项目

码农世界 2024-05-27 前端 72 次浏览 0个评论

一、项目目标和框图

项目目标:实现通过网页控制信息采集和通过网页控制灯泡和蜂鸣器的亮灭

二、项目分析

1.服务器源码分析

  1. 初始化服务器
  2. 循环等待连接,连接后创建线程,调用线程函数msg_request,在函数中调用handler_msg函数分析请求
  3. 在handler_msg函数中,先查看请求协议内容,其次获取请求方法、URL、参数,判断请求方法,对need_handler赋值,确定请求资源路径,如果请求地址没有携带任何资源,则默认返回index.html文件,如果资源不存在,返回404,如果需要处理(get带参数、post)调用handle_request函数,如果不需要(get请求不带参数且资源存在),调用echo_www函数,直接返回资源
  4. handle_request函数主要获取post数据,调用parse_and_process函数处理正文内容

2. 结合Modbus部分整体流程分析

三、核心功能代码

1.采集传感器数据

        modbus采集程序和webserver共同建立共享内存,modbus读取传感器得到的数据,将数据写入共享内存中;webserver将数据从共享内存中读出;

//modbus采集传感器
void *handler_thread(void *arg)
{
    key_t key;
    int shmid;
    struct msp *p;
    //创建key值
    key = ftok("1.txt", 'x');
    if (key < 0)
    {
        perror("ftok err");
        return NULL;
    }
    printf("key: %#x\n", key);
    //创建或打开共享内存
    shmid = shmget(key, 128, IPC_CREAT | IPC_EXCL | 0666); //没有则创建共享内存,已有则返回-1
    if (shmid <= 0)
    {
        if (errno == EEXIST)                //如果已存在则直接打开共享内存
            shmid = shmget(key, 128, 0666); //直接打开共享内存,返回共享内存id
        else
        {
            perror("shmget err");
            return NULL;
        }
    }
    printf("shmid: %d\n", shmid);
    //映射共享内存到用户空间
    p = (struct msp *)shmat(shmid, NULL, 0);
    if (p == (struct msp *)-1)
    {
        perror("shmat err");
        return NULL;
    }
    //操作共享内存
    while (1)
    {
        printf("handler_thread\n");
        // uint16_t dest[10] = {};
        PACK *msg = arg;
        modbus_read_registers(msg->ctx, 0, 4, p->dest);
        printf("%d %d %d %d\n", p->dest[0], p->dest[1], p->dest[2], p->dest[3]);
        //让从线程不退出,进程状态l也就是多线程
        sleep(2);
    }
    return NULL;
}
//webserver服务器
static int handler_get(int sock, const char *input)
{
    key_t key;
    int shmid;
    struct msp *p;
    //创建key值
    key = ftok("1.txt", 'x');
    if (key < 0)
    {
        perror("ftok err");
        return -1;
    }
    printf("key: %#x\n", key);
    //创建或打开共享内存
    shmid = shmget(key, 128, IPC_CREAT | IPC_EXCL | 0666); //没有则创建共享内存,已有则返回-1
    if (shmid <= 0)
    {
        if (errno == EEXIST)                //如果已存在则直接打开共享内存
            shmid = shmget(key, 128, 0666); //直接打开共享内存,返回共享内存id
        else
        {
            perror("shmget err");
            return -1;
        }
    }
    printf("shmid: %d\n", shmid);
    //映射共享内存到用户空间
    p = (struct msp *)shmat(shmid, NULL, 0);
    if (p == (struct msp *)-1)
    {
        perror("shmat err");
        return -1;
    }
    sscanf(input, "%d X%dY%dZ%d", p->dest[0], p->dest[1], p->dest[2], p->dest[3]);
     printf("g:%d X:%dY:%dZ:%d\n", p->dest[0], p->dest[1], p->dest[2], p->dest[3]);
    char reply_buf[HTML_SIZE] = {0};
    printf("handler_get\n");
    printf("%d %d%d%d\n", p->dest[0], p->dest[1], p->dest[2], p->dest[3]);
    sprintf(reply_buf, "%d %d %d %d", p->dest[0], p->dest[1], p->dest[2], p->dest[3]);
    printf("resp = %s\n", reply_buf);
    send(sock, reply_buf, strlen(reply_buf), 0);
    return 0;
}

 2.控制灯泡和蜂鸣器

       网页发出控制命令给webserver服务器控制灯和蜂鸣器的信息,webserver和modbus采集器用相同的条件建立两个程序间的消息队列,建立通信,将控制灯泡和蜂鸣器的信息传递给modbus采集器,modbus采集器用相关信息控制灯泡和蜂鸣器的开关

//modbus采集器
void *handler_thread2(void *arg)
{
    key_t key;
    int msgid;
    key = ftok(".", 9);
    if (key < 0)
    {
        perror("ftok err");
        return NULL;
    }
    printf("key:%#x\n", key);
    //打开消息队列
    msgid = msgget(key, IPC_CREAT | IPC_EXCL | 0666);
    if (msgid <= 0)
    {
        if (errno == EEXIST)
            msgid = msgget(key, 0666);
        else
        {
            perror("msgget err");
            return NULL;
        }
    }
    printf("msgid: %d\n", msgid);
    //读取消息
    struct msgbuf m;
    while(1)
    {
    msgrcv(msgid, &m, sizeof(m) - sizeof(long), 10, 0); //20:表示读取消息的类型为20,0:代表阻塞,读取完消息才返回
    printf("%d %d\n", m.num,m.num2);
   
    PACK *msg = arg;
   
        modbus_write_bit(msg->ctx2, m.num, m.num2);
        // modbus_write_bit(msg->ctx2, 1, dest[1]);
    }
//     //让从线程不退出,进程状态l也就是多线程
    return NULL;
}
//webserver服务器
static int handler_set(int sock, const char *input)
{
    key_t key;
    int msgid;
    key = ftok(".", 9);
    if (key < 0)
    {
        perror("ftok err");
        return -1;
    }
    printf("key:%#x\n", key);
    //打开消息队列
    msgid = msgget(key, IPC_CREAT | IPC_EXCL | 0666);
    if (msgid <= 0)
    {
        if (errno == EEXIST)
            msgid = msgget(key, 0666);
        else
        {
            perror("msgget err");
            return -1;
        }
    }
    printf("msgid: %d\n", msgid);
    int number1,number2;
    //input必须是"data1=1data2=6"类似的格式,注意前端过来的字符串会有双引号
    sscanf(input, "set=%dset2=%d", &number1,&number2);
     printf("num1 = %d,num2=%d\n", number1,number2);
    char reply_buf[HTML_SIZE] = {0};
    struct msgbuf mng;
    mng.type = 10;
    mng.num = number1;
    mng.num2 =number2;
    mng.ch = 'a';
    msgsnd(msgid, &mng, sizeof(mng) - sizeof(long), 0); //0:阻塞,发完消息才返回
    printf("num = %d  num=%d\n", number1 ,number2);
    sprintf(reply_buf, "set=%dset2=%d", number1,number2);
    printf("resp = %s\n", reply_buf);
    send(sock, reply_buf, strlen(reply_buf), 0);
    return 0;
}

3.http网页显示和控制

将虚拟机的IP地址在网页中打开,然后查询传感器得到的数据和控制灯泡和蜂鸣器




    
    
    
    信息采集
    


    
   

what 阿尔 donging 呢?

yes,我吃饭嘞
NO,我 dont eat

HTML(英文Hyper Text Markup Language的缩写)中文译为“超文本标记语言”。是用来描述网页的一种语言。 所谓超文本,因为它可以加入图片、声音、动画、多媒体等内容,不仅如此,它还可以从一个文件跳转到另一个文件,与世界各地主机的文件连接。 HTML 不是一种编程语言,而是一种标记语言 (markup language) Web 浏览器的作用是读取 HTML 文档,并以网页的形式显示出它们。浏览器不会显示 HTML 标签,而是使用标签来解释页面的内容

用户名:

设备控制


LED灯 on: off:
蜂鸣器 on: off:

转载请注明来自码农世界,本文标题:《linux网络项目——基于WebServer的工业数据采集项目》

百度分享代码,如果开启HTTPS请参考李洋个人博客
每一天,每一秒,你所做的决定都会改变你的人生!

发表评论

快捷回复:

评论列表 (暂无评论,72人围观)参与讨论

还没有评论,来说两句吧...

Top