基于Webserver的数据采集

架构:

介绍:

硬件端:设备端使用modbus slave来模拟(服务器端),通过Modbus TCP协议与Modbus 采集控制程序(客户端)进行通信

通信:(进程间通信)

对于采集的传感器数据:Modbus 采集控制程序执行modbus tcp的03功能将传感器数据从slave一侧读出,通过共享内存将数据交给网页服务器,最终在网页上显示出来

对于控制信息:网页端点击操作后,网页服务器收到相应的数据(即要实现的指令),并通过消息队列将指令传给Modbus 采集控制程序,然后Modbus 采集控制程序再通过modbus tcp的05功能实现对slave的控制

网页端:搭建一个简易的网页服务器,通过HTTP协议实现网页服务器与网页之间的请求与响应

演示:

【基于webserver工业数据采集小项目】 https://www.bilibili.com/video/BV18xMbzqEMn/?share_source=copy_web\&vd_source=ca8d891b9994089253ad45652f349b9e

主要代码:

Modbus 采集控制程序:

cpp 复制代码
#include <pthread.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/msg.h>
#include <unistd.h>
#include <stdlib.h>
#include <modbus.h>
#include <stdio.h>
#include <errno.h>
// modbus client

modbus_t *ctx1,*ctx2;

//从mobus slave端读取传感器数据,并通过共享内存将读到的数据送到网页服务器
void *handler1(void *arg)
{

    int num;
    
     // 拿到key
    key_t k = ftok("a.c", 'a');
     // 获取共享内存号
    int shmid;
    shmid = shmget(k, sizeof(uint16_t)*128, IPC_CREAT | IPC_EXCL | 0777);
    if (shmid < 0)
    {
        if (errno == EEXIST)
        {
            shmid = shmget(k, sizeof(uint16_t)*128, 0777);
        }
        else
        {
            perror("shmget err");
            return NULL;
        }
    }
     // 将共享内存映射到用户空间(拿到共享内存地址)
      uint16_t* data = (  uint16_t*)shmat(shmid, NULL, 0);
    if (data == ( uint16_t*)-1)
    {
        perror("shmat err");
        return NULL;
    }
    while (1)
    {
        // 执行03功能
        num = modbus_read_registers(ctx1, 0, 4, data);
        for (int i = 0; i < num; i++)
        {
            printf("%d ", data[i]);
        }
        putchar(10);
        sleep(1);
    }
}

struct msgbuf
{
    /*消息类型(正整数)*/
    long type;//必须有!!

    /*消息正文 自定义*/
    int order;
};
//网页服务器通过消息队列发来的控制命令,对modbus slave端的硬件设备进行控制
void *handler2(void *arg)
{
    key_t key;
   key= ftok("a.c",'a');
   if(key<0)
   {
    perror("ftok err");
    return NULL;
   }
   //创建或打开消息队列
   int msgid=msgget(key,IPC_CREAT|IPC_EXCL|0777);
   if(msgid<0)
   {
        if (errno==EEXIST)
        {
             msgid=msgget(key,0777);
        }
        else
        {
                perror("msgget err");
                return NULL;
        }
       
   }

    /*读取消息*/
    //定义一个结构体变量用来接收消息
    struct msgbuf m;
    while (1)
    {
     msgrcv(msgid,&m,sizeof(m)-sizeof(long),1,IPC_NOWAIT);
    
    int order=m.order;
   
    if (order == 0) //LED on
    {

        modbus_write_bit(ctx2, 0, 1);
    }
    else if (order == 1) //LED off
    {
        modbus_write_bit(ctx2, 0, 0);
    }

    else if (order == 2) //buzzer on
    {

        modbus_write_bit(ctx2, 1, 1);
    }
    else //buzzer off
    {
        modbus_write_bit(ctx2, 1, 0);
    }
    }
    
   

    return NULL;
}

int main(int argc, char const *argv[])
{

    // 创建modbus实例
  
    //用于采集数据
    ctx1 = modbus_new_tcp(argv[3], atoi(argv[1]));
     if (ctx1 == NULL)
    {
        perror("modbus_new_tcp err");
        return -1;
    }
    else
    {
        printf("创建实例成功\n");
    }
    // 设置从机ID
    if (modbus_set_slave(ctx1, 1) < 0)
    {
        perror("modbus_set_slave err");
        return -1;
    }
    else
    {
        printf("从机ID设置成功\n");
    }
    // 建立连接
    if (modbus_connect(ctx1) < 0)
    {
        perror("modbus_connect err");
        return -1;
    }
    else
    {
        printf("连接成功\n");
    }


    //用于控制
    ctx2 = modbus_new_tcp(argv[3], atoi(argv[2]));
    if (ctx2 == NULL)
    {
        perror("modbus_new_tcp err");
        return -1;
    }
    else
    {
        printf("创建实例成功\n");
    }
    // 设置从机ID
    if (modbus_set_slave(ctx2, 2) < 0)
    {
        perror("modbus_set_slave err");
        return -1;
    }
    else
    {
        printf("从机ID设置成功\n");
    }
    // 建立连接
    if (modbus_connect(ctx2) < 0)
    {
        perror("modbus_connect err");
        return -1;
    }
    else
    {
        printf("连接成功\n");
    }

    pthread_t tid1, tid2;
    
    pthread_create(&tid1, NULL, handler1, NULL);

    printf("输入指令来设置线圈状态(0:LED开 1:LED关 2:buzzer开 3:buzzer关)\n");
 
    pthread_create(&tid2, NULL, handler2, NULL);

    pthread_join(tid1,NULL); 
    pthread_join(tid2,NULL);
    // 关闭套接字
    modbus_close(ctx1);
    modbus_close(ctx2);
    // 关闭连接
    modbus_free(ctx1);
    modbus_free(ctx2);
    return 0;
}

WEB服务器主要使用函数:

cpp 复制代码
/***********************************************************************************
Copy right:	    hqyj Tech.
Author:         jiaoyue
Date:           2023.07.01
Description:    http请求处理
***********************************************************************************/

#include <sys/types.h>
#include <sys/socket.h>
#include "custom_handle.h"

#define KB 1024
#define HTML_SIZE (64 * KB)

// 普通的文本回复需要增加html头部
#define HTML_HEAD "Content-Type: text/html\r\n" \
                  "Connection: close\r\n"

static int handle_login(int sock, const char *input)
{
    char cpy[128];
    strcpy(cpy, input);
    char reply_buf[HTML_SIZE] = {0};
    // strstr函数返回子串在主串中首次出现时的位置
    char *p = strstr(cpy, "password");
    char *passwd = p + strlen("password=");
    char *temp = passwd;
    while (*temp != '\"')
        temp++;
    *temp = '\0';

    *(p) = '\0';
    char *uname = strstr(cpy, "username=");
    uname += strlen("username=");

    // 创建和打开数据库
    sqlite3 *db;
    if (sqlite3_open("userDB.db", &db) != SQLITE_OK)
    {
        fprintf(stderr, "open err:%s\n", sqlite3_errmsg(db));
        return -1;
    }
    else
    {
        printf("打开数据库成功\n");
    }
    // 创建表
    char *errmsg;

    if (sqlite3_exec(db, "create table if not exists usermsg (name string,password int)", NULL, NULL, &errmsg) != SQLITE_OK)
    {
        fprintf(stderr, "create table err:%s\n", errmsg);
        return -1;
    }
    else
    {

        printf("打开表成功\n");
    }
    char a1[5] = "no";
    char a2[5] = "yes";
    char sql[128];
    sprintf(sql, "select * from usermsg where name='%s' and password='%s'", uname, passwd);
    printf("sql=%s\n", sql);
    char **result = NULL;    // 用于存储查询到的结果
    int row = 0, column = 0; // 记录行数和列数
    sqlite3_get_table(db, sql, &result, &row, &column, &errmsg);
   
    if (row==0)
    {
        send(sock, a1, 5, 0);
        printf("%s\n", a1);
    }
    else
    {
        send(sock, a2, 5, 0);
        printf("%s\n", a2);
    }
    return 0;
}



static int handle_add(int sock, const char *input)
{
    int number1, number2;

    // input必须是"data1=1data2=6"类似的格式,注意前端过来的字符串会有双引号
    sscanf(input, "\"data1=%ddata2=%d\"", &number1, &number2);
    printf("num1 = %d\n", number1);

    char reply_buf[HTML_SIZE] = {0};
    printf("num = %d\n", number1 + number2);
    sprintf(reply_buf, "%d", number1 + number2);
    printf("resp = %s\n", reply_buf);
    send(sock, reply_buf, strlen(reply_buf), 0);

    return 0;
}

/**
 * @brief 处理自定义请求,在这里添加进程通信
 * @param input
 * @return
 */
int count = 0;
// 采集数据
int commuwithsensor(int sock, const char *input)
{

    // 拿到key
    key_t k = ftok("/home/hq/25041/day55/a.c", 'a');
    // 获取共享内存号
    int shmid;
    shmid = shmget(k, sizeof(uint16_t) * 128, IPC_CREAT | IPC_EXCL | 0777);
    if (shmid < 0)
    {
        if (errno == EEXIST)
        {
            shmid = shmget(k, sizeof(uint16_t) * 128, 0777);
        }
        else
        {
            perror("shmget err");
            return -1;
        }
    }
    // 将共享内存映射到用户空间(拿到共享内存地址)
    uint16_t *data = (uint16_t *)shmat(shmid, NULL, 0);
    if (data == (uint16_t *)-1)
    {
        perror("shmat err");
        return -1;
    }
    // 将传感器数据从共享内存中拿到,发送给网页
    char reply_buf[HTML_SIZE] = {0};
    sprintf(reply_buf, "%d %d %d %d \n", data[0], data[1], data[2], data[3]);
    printf("resp = %s\n", reply_buf);
    send(sock, reply_buf, strlen(reply_buf), 0);
    // 将记录插入数据库
    char sql[128];
    char buf[128];
    sprintf(buf, "传感器:%d 加速度_x: %d  加速度_y:%d  加速度_z:%d ", data[0], data[1], data[2], data[3]);
    sprintf(sql, "insert into sensordata(id, data) values(%d,'%s')", count++, buf);
    commuwithdb(sql);

    return 0;
}

// 控制
int commuwithcoil(int sock, const char *input)
{

    int order;
    sscanf(input, "\"order=%d\"", &order);
    printf("order = %d \n", order);
    // 拿到key值
    key_t key;
    key = ftok("/home/hq/25041/day55/a.c", 'a');
    if (key < 0)
    {
        perror("ftok err");
        return -1;
    }
    // 创建或打开消息队列
    int msgid = msgget(key, IPC_CREAT | IPC_EXCL | 0777);
    if (msgid < 0)
    {
        if (errno == EEXIST)
        {
            msgid = msgget(key, 0777);
        }
        else
        {
            perror("msgget err");
            return -1;
        }
    }

    /*制作消息*/
    // 先定义一个结构体变量
    struct msgbuf msg;
    // 变量初始化
    msg.type = 1;
    msg.order = order;

    /*添加消息*/
    msgsnd(msgid, &msg, sizeof(msg) - sizeof(long), 0);
    // 将记录插入数据库
    char sql[128];
    char data[20];
    if (order == 0)
    {
        strcpy(data, "LED on");
    }
    else if (order == 1)
    {
        strcpy(data, "LED off");
    }
    else if (order == 2)
    {
        strcpy(data, "buzzer on");
    }
    else
    {
        strcpy(data, "buzzer off");
    }

    sprintf(sql, "insert into sensordata(id, data) values(%d,'%s')", count++, data);
    commuwithdb(sql);
}

int commuwithdb(char *sql)
{

    // 创建和打开数据库
    sqlite3 *db;
    if (sqlite3_open("userDB.db", &db) != SQLITE_OK)
    {
        fprintf(stderr, "open err:%s\n", sqlite3_errmsg(db));
        return -1;
    }
    else
    {
        printf("打开数据库成功\n");
    }
    // 创建表
    char *errmsg;

    if (sqlite3_exec(db, "create table if not exists sensordata (id int ,data string,time DATETIME DEFAULT CURRENT_TIMESTAMP)", NULL, NULL, &errmsg) != SQLITE_OK)
    {
        fprintf(stderr, "create table err:%s\n", errmsg);
        return -1;
    }
    else
    {

        printf("打开表成功\n");
    }
    if (count == 0)
    {
        if (sqlite3_exec(db, "delete from sensordata ", NULL, NULL, &errmsg) != SQLITE_OK)
        {
            fprintf(stderr, "clear table err:%s\n", errmsg);
            return -1;
        }
        else
        {

            printf("清空表成功\n");
        }
    }

    if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
    {
        fprintf(stderr, "insert err:%s\n", errmsg);
        return -1;
    }
    else
    {
        printf("插入成功\n");
    }
}

int parse_and_process(int sock, const char *query_string, const char *input)
{
    // query_string不一定能用的到

    // 先处理登录操作
    if (strstr(input, "username=") && strstr(input, "password="))
    {
        return handle_login(sock, input);
    }
    // 处理求和请求
    else if (strstr(input, "data1=") && strstr(input, "data2="))
    {
        return handle_add(sock, input);
    }
    // 读取传感器数据
    else if (strstr(input, "light=") && strstr(input, "ax=") && strstr(input, "ay=") && strstr(input, "az="))
    {
        return commuwithsensor(sock, input);
    }
    else if (strstr(input, "order="))
    {
        return commuwithcoil(sock, input);
    }

    else // 剩下的都是json请求,这个和协议有关了
    {
        // 构建要回复的JSON数据
        const char *json_response = "{\"message\": \"Hello, client!\"}";

        // 发送HTTP响应给客户端
        send(sock, json_response, strlen(json_response), 0);
    }

    return 0;
}

登录页面:

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>智能系统登录</title>
    <style>
        @keyframes float {

            0%,
            100% {
                transform: translateY(0);
            }

            50% {
                transform: translateY(-10px);
            }
        }

        @keyframes fadeIn {
            from {
                opacity: 0;
                transform: translateY(20px);
            }

            to {
                opacity: 1;
                transform: translateY(0);
            }
        }

        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            margin: 0;
            padding: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: #fff;
            overflow: hidden;
        }

        .login-container {
            width: 90%;
            max-width: 400px;
            background: rgba(255, 255, 255, 0.1);
            backdrop-filter: blur(12px);
            border-radius: 20px;
            padding: 40px;
            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
            border: 1px solid rgba(255, 255, 255, 0.1);
            text-align: center;
            animation: fadeIn 0.8s ease-out forwards;
            transform-origin: center;
            transition: transform 0.3s ease;
        }

        .login-container:hover {
            transform: scale(1.02);
        }

        .logo {
            font-size: 2.5rem;
            font-weight: 600;
            margin-bottom: 30px;
            background: linear-gradient(to right, #fff, #e0e0e0);
            -webkit-background-clip: text;
            background-clip: text;
            color: transparent;
            animation: float 4s ease-in-out infinite;
        }

        .input-group {
            margin-bottom: 25px;
            text-align: left;
        }

        label {
            display: block;
            margin-bottom: 8px;
            font-size: 0.9rem;
            color: rgba(255, 255, 255, 0.8);
            transform: translateX(5px);
            transition: all 0.3s ease;
        }

        input {
            width: 100%;
            padding: 12px 15px;
            border-radius: 8px;
            border: 1px solid rgba(255, 255, 255, 0.3);
            background: rgba(255, 255, 255, 0.1);
            color: white;
            font-size: 1rem;
            transition: all 0.3s ease;
        }

        input:focus {
            outline: none;
            border-color: rgba(255, 255, 255, 0.6);
            background: rgba(255, 255, 255, 0.2);
            box-shadow: 0 0 10px rgba(255, 255, 255, 0.2);
        }

        input:focus+label {
            color: white;
            transform: translateX(0);
        }

        .btn {
            width: 100%;
            padding: 12px;
            border-radius: 8px;
            border: none;
            background: rgba(255, 255, 255, 0.3);
            color: white;
            font-size: 1rem;
            font-weight: 500;
            cursor: pointer;
            transition: all 0.3s ease;
            margin-top: 10px;
            position: relative;
            overflow: hidden;
        }

        .btn:hover {
            background: rgba(255, 255, 255, 0.4);
        }

        .btn:active {
            transform: scale(0.98);
        }

        .btn::after {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            width: 5px;
            height: 5px;
            background: rgba(255, 255, 255, 0.5);
            opacity: 0;
            border-radius: 100%;
            transform: scale(1, 1) translate(-50%, -50%);
            transform-origin: 50% 50%;
        }

        .btn:focus:not(:active)::after {
            animation: ripple 1s ease-out;
        }

        @keyframes ripple {
            0% {
                transform: scale(0, 0);
                opacity: 0.5;
            }

            100% {
                transform: scale(20, 20);
                opacity: 0;
            }
        }

        .footer {
            margin-top: 30px;
            font-size: 0.8rem;
            color: rgba(255, 255, 255, 0.6);
            animation: fadeIn 1s ease-out 0.3s both;
        }

        a {
            color: rgba(255, 255, 255, 0.8);
            text-decoration: none;
            transition: color 0.3s ease;
            position: relative;
        }

        a:hover {
            color: white;
        }

        a::after {
            content: '';
            position: absolute;
            width: 0;
            height: 1px;
            bottom: -2px;
            left: 0;
            background-color: white;
            transition: width 0.3s ease;
        }

        a:hover::after {
            width: 100%;
        }
    </style>
</head>

<body>
    <div class="login-container">
        <div class="logo">智能系统</div>

        <div class="input-group">
            <input type="text" id="username" placeholder=" " required>
            <label for="username">用户名</label>
        </div>

        <div class="input-group">
            <input type="password" id="password" placeholder=" " required>
            <label for="password">密码</label>
        </div>

        <button class="btn" id="loginBtn">登 录</button>

        <div class="footer">
            <a href="#">忘记密码?</a> | <a href="#">注册账号</a>
        </div>
    </div>

    <script>

        document.getElementById('loginBtn').addEventListener('click', function () {
            // 如果需要验证后再跳转,可以使用以下代码:
            const u = document.getElementById('username').value;
            const p = document.getElementById('password').value;
            var x = new XMLHttpRequest();
            x.open("post", "", true);//true:异步通知
            var s = "\"" + "username=" + u + "password=" + p + "\"";
            x.send(s);
            x.onreadystatechange = function () {
                // ==:不区分数据类型的判等
                // === :区分数据类型的判等
                if (x.readyState === 4 && x.status === 200) {
                    var r = x.responseText;//响应正文  
                    
                    // console.log(encodeURIComponent(r));              
                    if (r.slice(0,2) == 'no')
                    {
                        alert('用户名密码错误,请重新输入');

                    }
                    else 
                    {

                        window.location.href = 'needsensor.html';
                    }

                }
            }



            /*
            // 直接跳转
            window.location.href = 'needsensor.html';
            
            */
        });
    </script>
</body>

</html>

主页:

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>智能设备控制面板</title>
    <style>
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            margin: 0;
            padding: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: #fff;
        }

        .container {
            width: 90%;
            max-width: 800px;
            background: rgba(255, 255, 255, 0.1);
            backdrop-filter: blur(12px);
            border-radius: 20px;
            padding: 30px;
            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
            border: 1px solid rgba(255, 255, 255, 0.1);
        }

        h1 {
            text-align: center;
            margin-bottom: 30px;
            font-weight: 600;
            font-size: 2.2rem;
            background: linear-gradient(to right, #fff, #e0e0e0);
            -webkit-background-clip: text;
            background-clip: text;
            color: transparent;
        }

        .section {
            margin-bottom: 30px;
            padding: 25px;
            border-radius: 15px;
            background: rgba(255, 255, 255, 0.15);
            backdrop-filter: blur(5px);
        }

        h2 {
            margin-top: 0;
            margin-bottom: 20px;
            font-weight: 500;
            color: #f0f0f0;
        }

        .sensor-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
            gap: 20px;
        }

        .sensor-card {
            background: rgba(255, 255, 255, 0.2);
            border-radius: 12px;
            padding: 20px;
            transition: transform 0.3s ease;
        }

        .sensor-card:hover {
            transform: translateY(-5px);
        }

        .sensor-name {
            font-size: 1rem;
            margin-bottom: 10px;
            color: rgba(255, 255, 255, 0.8);
        }

        .sensor-value {
            font-size: 1.8rem;
            font-weight: 700;
            margin-bottom: 5px;
        }

        .unit {
            font-size: 0.9rem;
            color: rgba(255, 255, 255, 0.6);
        }

        .controls {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
            gap: 20px;
        }

        .control-group {
            background: rgba(255, 255, 255, 0.2);
            border-radius: 12px;
            padding: 20px;
        }

        .radio-option {
            display: flex;
            align-items: center;
            margin-bottom: 15px;
        }

        input[type="radio"] {
            appearance: none;
            width: 20px;
            height: 20px;
            border: 2px solid rgba(255, 255, 255, 0.5);
            border-radius: 50%;
            margin-right: 10px;
            position: relative;
            cursor: pointer;
        }

        input[type="radio"]:checked {
            background: rgba(255, 255, 255, 0.3);
            border-color: #fff;
        }

        input[type="radio"]:checked::after {
            content: '';
            position: absolute;
            width: 10px;
            height: 10px;
            background: #fff;
            border-radius: 50%;
            top: 3px;
            left: 3px;
        }

        label {
            cursor: pointer;
            font-size: 1rem;
        }
    </style>
</head>

<body>
    <div class="container">
        <h1>智能设备控制面板</h1>

        <div class="section">
            <h2>传感器数据</h2>
            <div class="sensor-grid">
                <div class="sensor-card">
                    <div class="sensor-name">光照强度</div>
                    <div class="sensor-value" id="light-value">0</div>
                    <div class="unit">lux</div>
                </div>
                <div class="sensor-card">
                    <div class="sensor-name">加速度 X轴</div>
                    <div class="sensor-value" id="accel-x">0.00</div>
                    <div class="unit">m/s²</div>
                </div>
                <div class="sensor-card">
                    <div class="sensor-name">加速度 Y轴</div>
                    <div class="sensor-value" id="accel-y">0.00</div>
                    <div class="unit">m/s²</div>
                </div>
                <div class="sensor-card">
                    <div class="sensor-name">加速度 Z轴</div>
                    <div class="sensor-value" id="accel-z">9.81</div>
                    <div class="unit">m/s²</div>
                </div>
            </div>
        </div>

        <div class="section">
            <h2>设备控制</h2>
            <div class="controls">
                <div class="control-group">
                    <div class="radio-option">
                        <input type="radio" id="led-on" name="led" onclick="set0()">
                        <label for="led-on">LED灯:开启</label>
                    </div>
                    <div class="radio-option">
                        <input type="radio" id="led-off" name="led" checked onclick="set1()">
                        <label for="led-off">LED灯:关闭</label>
                    </div>
                </div>
                <div class="control-group">
                    <div class="radio-option">
                        <input type="radio" id="buzzer-on" name="buzzer" onclick="set2()">
                        <label for="buzzer-on">蜂鸣器:开启</label>
                    </div>
                    <div class="radio-option">
                        <input type="radio" id="buzzer-off" name="buzzer" onclick="set3()" checked>
                        <label for="buzzer-off">蜂鸣器:关闭</label>
                    </div>
                </div>
            </div>
        </div>
    </div>




    <script>
        //每隔一秒刷新一次获取到的传感器数据
        function updateSensorData() {
            var x = new XMLHttpRequest();
            x.open("post", "", true);//true:异步通知
            x.send("\"light=1ax=2ay=3az=4\"");
            x.onreadystatechange = function () {
                // ==:不区分数据类型的判等
                // === :区分数据类型的判等
                if (x.readyState === 4 && x.status === 200) {
                    var r = x.responseText;//响应正文
                    var s = r.split(" ");
                    document.getElementById('light-value').textContent = s[0];
                    document.getElementById('accel-x').textContent = s[1]
                    document.getElementById('accel-y').textContent = s[2]
                    document.getElementById('accel-z').textContent = s[3]

                }
            }

        }

        setInterval(updateSensorData, 1000);
        updateSensorData();
        //控制
        function set0() {

            var x = new XMLHttpRequest();
            x.open("post", "", true);//true:异步通知
            x.send("order=0");

        }
        function set1() {

            var x = new XMLHttpRequest();
            x.open("post", "", true);//true:异步通知
            x.send("\"order=1\"");

        }
        function set2() {

            var x = new XMLHttpRequest();
            x.open("post", "", true);//true:异步通知
            x.send("\"order=2\"");

        }
        function set3() {

            var x = new XMLHttpRequest();
            x.open("post", "", true);//true:异步通知
            x.send("\"order=3\"");

        }



    </script>


</body>

</html>

问题:

可以再扩展一下注册页面

还有一个让我超级无语的错误o(╥﹏╥)o,

就是这个登录页面的判断,判断用户名和密码是否在数据库中,我在服务器端使用SQL语句查询数据库之后,若能找到对应的用户名密码会给网页响应"yes",否则就响应"no",然后,我明明 r 打印出来就是"no",结果 r=="no"的判断就是0,我真的好一顿捣鼓确认就是判等的问题后,我就去查了查,结果令我十分无语,用console.log(encodeURIComponent(r)); 显示了一下完整的字符串,no后面跟了一堆%00,这要能等才神奇,我就切片了一下,果然,就成功进去了。。。( ̄ー ̄)

相关推荐
浪剑超7 小时前
https说明
网络协议·http·https
靡樊12 小时前
应用层协议HTTP
网络·网络协议·http
笨手笨脚の13 小时前
Nginx-2 详解处理 Http 请求
运维·网络协议·nginx·http
magic 24513 小时前
@RequestHeader(“Authorization“) 解析:HTTP 请求头中的 Authorization 字段
网络·网络协议·http
DjangoJason13 小时前
计算机网络 : 应用层协议HTTP
网络协议·计算机网络·http
llwszx13 小时前
“从HTTP到TCP/IP的旅程“-----深入浅出Java Web通信
java·websocket·网络协议·tcp/ip·spring·http
只喜欢赚钱的棉花没有糖21 小时前
http的缓存问题
前端·javascript·http
SZ1701102311 天前
HTTP 请求报文 方法
网络·网络协议·http
Gazer_S1 天前
【HTTP重定向与缓存机制详解】
网络协议·http·缓存