ESP8266制作天气预报海藻球微景观生态缸记录(七)-实现网页控制灯光颜色【base64编码传递】

原理是:

  1. 打开浏览器时,将晴天颜色变量中的JSON串发送给浏览器。
  2. 浏览器接收到JSON串,解析之,并以三原色滑块的形式展现出来
  3. 用户滑动滑块,预览当前颜色,点击“保存”按钮后,发送请求给后台,改变晴天颜色变量,以此实现对晴天颜色的控制。
  4. 以此类推,其他天气的颜色同样处理,预期实现的效果是这样的

但在实际运行时出现错误,因为把从后端返回来的JSON串赋值给前端的时候,因为双引号的问题导致出错。

var result="{"r":255,"g":255,"b":150}"

类似这样的结果,会引发js错误,导致网页无法正常显示和运行。

无奈才疏学浅,尝试了各种办法都不行,只好把这个JSON串编码为base64发送给网页,然后js再解码这个base64字符串,然后再进行JSON解析,最终成功。

目前已经可以实现用网页来设定各种天气下的颜色效果,下一步,将设定后的效果保存进EEPROM就基本上完成这个小制作了。

大致的代码原理:

#include <base64.h>//多引用了一个库,用来进行base64编码
const char* PARAM_INPUT_QINGTIANVALUE = "qingtianValue";//定义晴天web请求名
const char* PARAM_INPUT_DUOYUNVALUE = "duoyunValue";//定义多云web请求名,其他天气以此类推
String rgbJsonQing = "{\"r\":255,\"g\":255,\"b\":150}";//定义晴天颜色json
String rgbJsonDuoyun = "{\"r\":255,\"g\":255,\"b\":225}";//定义多云颜色json,其他天气以此类推
//设置这个异步网页服务器的端口为80
AsyncWebServer server(80);
//要打印的首页
//标记在%之间的LIGHTVALUE,是要向网页处理器发出名为LIGHTVALUE的请求,然后获得值[对于本例,就是灯光亮度]
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style>
        table {
            border: 1px solid #000000;
            border-collapse: collapse
        }
        td {
            border: 1px solid #000000;
            border-collapse: collapse
        }
    </style>
    <title>彩灯控制</title>
</head>
<body onload="firstLoad()">
    <h2>亮度控制</h2>
    <p>当前灯光亮度:<span id="textLightValue">%LIGHTVALUE%</span>/255</p>
    <p>设置灯光亮度:<input type="range" min="0" max="255" value="%LIGHTVALUE%" step="1" onchange="changeLightValue(this.value)"></p>
    <hr />
    <h2>颜色控制</h2>
    <h3>未来12小时天气:%TIANQINAME%</h3>
    <p id="table"></p>
    <script>
        var arr = new Array("qingtian", "duoyun");
        function base64_decode (input) { // 解码,配合decodeURIComponent使用
            var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
            var output = "";
            var chr1, chr2, chr3;
            var enc1, enc2, enc3, enc4;
            var i = 0;
            input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
            while (i < input.length) {
                enc1 = base64EncodeChars.indexOf(input.charAt(i++));
                enc2 = base64EncodeChars.indexOf(input.charAt(i++));
                enc3 = base64EncodeChars.indexOf(input.charAt(i++));
                enc4 = base64EncodeChars.indexOf(input.charAt(i++));
                chr1 = (enc1 << 2) | (enc2 >> 4);
                chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
                chr3 = ((enc3 & 3) << 6) | enc4;
                output = output + String.fromCharCode(chr1);
                if (enc3 != 64) {
                    output = output + String.fromCharCode(chr2);
                }
                if (enc4 != 64) {
                    output = output + String.fromCharCode(chr3);
                }
            }
            return utf8_decode(output);
        }
        function utf8_decode (utftext) { // utf-8解码
            var string = '';
            let i = 0;
            let c = 0;
            let c1 = 0;
            let c2 = 0;
            while (i < utftext.length) {
                c = utftext.charCodeAt(i);
                if (c < 128) {
                    string += String.fromCharCode(c);
                    i++;
                } else if ((c > 191) && (c < 224)) {
                    c1 = utftext.charCodeAt(i + 1);
                    string += String.fromCharCode(((c & 31) << 6) | (c1 & 63));
                    i += 2;
                } else {
                    c1 = utftext.charCodeAt(i + 1);
                    c2 = utftext.charCodeAt(i + 2);
                    string += String.fromCharCode(((c & 15) << 12) | ((c1 & 63) << 6) | (c2 & 63));
                    i += 3;
                }
            }
            return string;
        }
        function firstLoad() {
            var chName = "";
            var table = "<table>";
            table += "<tr>";
            table += "<td></td>";
            table += "<td>颜色值</td>";
            table += "<td>原始颜色</td>";
            table += "<td>新颜色</td>";
            table += "<td></td>";
            table += "</tr>";
            for (var i in arr) {
                switch (arr[i]) {
                    case "qingtian":
                        chName = "晴天"
                        break;
                    case "duoyun":
                        chName = "多云"
                        break;
                    default:
                        chName = "未知天气"
                        break;
                }
                table += "<tr>";
                table += "<td>" + chName+"</td>";
                table += "<td>";
                table += "红色<input type=\"range\" id=\"" + arr[i] + "_r\" value=\"100\" min=\"0\" max=\"255\" onchange=\"changeColor('" + arr[i] +"')\" /><br />";
                table += "绿色<input type=\"range\" id=\"" + arr[i] + "_g\" value=\"100\" min=\"0\" max=\"255\" onchange=\"changeColor('" + arr[i] +"')\" /><br />";
                table += "蓝色<input type=\"range\" id=\"" + arr[i] + "_b\" value=\"100\" min=\"0\" max=\"255\" onchange=\"changeColor('" + arr[i] +"')\" />";
                table += "</td>";
                table += " <td id=\"td_yuanshi_" + arr[i] +"\"></td>";
                table += "<td id=\"td_" + arr[i] +"\"></td>";
                table += "<td><input type=\"button\" value=\"保存并生效\" onclick=\"saveColor('" + arr[i] +"')\" /></td>";
                table += "</tr>";
            }
            table += "</table>";
            document.getElementById("table").innerHTML = table;
            firstSetColor();
        }
        //改变灯光亮度
        function changeLightValue(value) {
            var sliderValue = value;
            document.getElementById("textLightValue").innerHTML = sliderValue;
            console.log(sliderValue);
            var xhr = new XMLHttpRequest();
            xhr.open("GET", "/sliderLight?lightValue=" + sliderValue, true);
            xhr.send();
        }
        //打开页面时,初始化各种天气下的框值和颜色预览
        function firstSetColor() {
            firstSetColorDo("qingtian", "%QINGTIANVALUE%");
            firstSetColorDo("duoyun", "%DUOYUNVALUE%");
        }
        //为配合上述方法的共用方法
        function firstSetColorDo(str, rgbstr) {
            var RGB = JSON.parse(base64_decode(rgbstr));
            document.getElementById(str + "_r").value = RGB["r"];
            document.getElementById(str + "_g").value = RGB["g"];
            document.getElementById(str + "_b").value = RGB["b"];
            document.getElementById("td_yuanshi_" + str).innerHTML = "<div style='background-color:rgb(" + RGB["r"] + "," + RGB["g"] + "," + RGB["b"] + ");'> </div>";
            document.getElementById("td_" + str).innerHTML = "<div style='background-color:rgb(" + RGB["r"] + "," + RGB["g"] + "," + RGB["b"] + ");'> </div>";
        }
        //输入颜色时,改变颜色预览
        function changeColor(str) {
            var r = document.getElementById(str + "_r").value;
            var g = document.getElementById(str + "_g").value;
            var b = document.getElementById(str + "_b").value;
            document.getElementById("td_" + str).innerHTML = "<div style='background-color:rgb(" + r + "," + g + "," + b + ");'> </div>";
        }
        //确认,发送命令到webserver,
        function saveColor(str) {
            var r = document.getElementById(str + "_r").value;
            var g = document.getElementById(str + "_g").value;
            var b = document.getElementById(str + "_b").value;
            var sliderValue = "{\"r\":" + r + ",\"g\":" + g + ",\"b\":" + b + "}";
            var xhr = new XMLHttpRequest();
            xhr.open("GET", "/sliderRGB?" + str + "Value=" + sliderValue, true);
            xhr.send();
            document.getElementById("td_yuanshi_" + str).innerHTML = "<div style='background-color:rgb(" + r + "," + g + "," + b + ");'> </div>";
        }
    </script>
</body>
</html>
)rawliteral";
//网页处理器,根据从网页中发送的不同调用请求返回值
String processor(const String& var){
  if (var == "QINGTIANVALUE"){
    return base64::encode(rgbJsonQing);
  }
  if (var == "DUOYUNVALUE"){
    return base64::encode(rgbJsonDuoyun);
  }
  return String();
}
//解析颜色json串的方法
void formatRGBFromJson(String json)
{
  Serial.println(json);
  DynamicJsonDocument doc(100);//rgb字符串长度不会大于100,所以这里设定100即可
  DeserializationError error = deserializeJson(doc, json);
  if (error) {
    Serial.print(F("deserializeJson() failed: "));
    Serial.println(error.f_str());
    return;
  }
  JsonObject obj = doc.as<JsonObject>();
  color = strip.Color(obj["r"], obj["g"], obj["b"]);
}
//不同天气,赋值不同颜色。这里可以自己任意修改。
void setLed()
{
  if (tianqi == 0 || tianqi == 1 || tianqi == 2 || tianqi == 3) //晴
  {
    formatRGBFromJson(rgbJsonQing);
  }
  else if (tianqi == 4 || tianqi == 5 || tianqi == 6 || tianqi == 7 || tianqi == 8) //多云
  {
    formatRGBFromJson(rgbJsonDuoyun);
  }
  else
  {
    formatRGBFromJson(rgbJsonQing);
  }
  for (i = 0; i < 9; i++)
  {
    strip.setPixelColor(i, color);
  }
}
void setup() {
 // 开始设置web服务器——彩灯颜色控制设置
  server.on("/sliderRGB", HTTP_GET, [] (AsyncWebServerRequest *request) {
    String inputMessage;
    if (request->hasParam(PARAM_INPUT_QINGTIANVALUE)) {
      inputMessage = request->getParam(PARAM_INPUT_QINGTIANVALUE)->value();//get传递过来的value参数
      rgbJsonQing = inputMessage;//设置晴天的颜色
      set_String(indexQing,indexQing+1,rgbJsonQing);//保存进EEPROM
    }
    if (request->hasParam(PARAM_INPUT_DUOYUNVALUE)) {
      inputMessage = request->getParam(PARAM_INPUT_DUOYUNVALUE)->value();//get传递过来的value参数
      rgbJsonDuoyun= inputMessage;//设置多云的颜色
      set_String(indexDuoyun,indexDuoyun+1,rgbJsonDuoyun);//保存进EEPROM
    }
    Serial.println(inputMessage);
    request->send(200, "text/plain", "OK");
  });
  // 启动网页服务
  server.begin();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

玩编程的小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值