first commit
1
code/SmallCart/SmallCartMain/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
d55db5fb-33b8-4a23-bda7-c40e5abf7980
|
||||
37
code/SmallCart/SmallCartMain/SmallCartMain.ino
Normal file
@@ -0,0 +1,37 @@
|
||||
#include "src/led/led.h"
|
||||
#include "src/config/config.h"
|
||||
#include "src/wifi/wifi.h"
|
||||
#include "src/motion/motion.h"
|
||||
#include "src/web/web.h"
|
||||
#include "src/socket/socket.h"
|
||||
#include "src/buzzer/buzzer.h"
|
||||
|
||||
Web web;
|
||||
Socket socket;
|
||||
ConfigWifi wifi;
|
||||
Motion motion;
|
||||
Buzzer buzzer;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(9600);
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
digitalWrite(LED_BUILTIN, LOW);
|
||||
|
||||
// 初始化wifi,ap模式
|
||||
wifi.init();
|
||||
// 初始化电机驱动的各个引脚 和 舵机,和运动方法封装
|
||||
motion.init();
|
||||
// 蜂鸣器
|
||||
buzzer.init();
|
||||
// 初始化 websocket 服务
|
||||
socket.init();
|
||||
// 初始化 httpServer 服务,主要加载Web的控制面板
|
||||
web.init();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
socket.Server->loop();
|
||||
web.WebController->handleClient();
|
||||
}
|
||||
1
code/SmallCart/SmallCartMain/data/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
fc2363c0-9720-43c0-bced-f43fcaabb0c7
|
||||
1
code/SmallCart/SmallCartMain/data/css/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
7682cea9-47ad-46fa-8ada-afd10dfa0655
|
||||
161
code/SmallCart/SmallCartMain/data/css/index.css
Normal file
@@ -0,0 +1,161 @@
|
||||
body,
|
||||
ul,
|
||||
li,
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
p {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
body,
|
||||
html {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
position: relative;
|
||||
background: url("http://192.168.4.4:81/stream");
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.remote_rod {
|
||||
position: absolute;
|
||||
padding: 0 30px;
|
||||
width: 100%;
|
||||
bottom: 40px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.rod {
|
||||
width: 128px;
|
||||
height: 128px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.vertical {
|
||||
background: url("../img/vertical.png");
|
||||
}
|
||||
|
||||
.level {
|
||||
background: url("../img/level.png");
|
||||
}
|
||||
.level img {
|
||||
position: absolute;
|
||||
font-size: 32px;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
border-radius: 100%;
|
||||
}
|
||||
.level .action img {
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
}
|
||||
.icon-zidongdadeng {
|
||||
width: 43px !important;
|
||||
height: 43px !important;
|
||||
top: -70px;
|
||||
right: 0;
|
||||
}
|
||||
.icon-jinggao_o {
|
||||
left: -24px;
|
||||
top: -44px;
|
||||
}
|
||||
.icon-xiaolaba {
|
||||
left: -68px;
|
||||
top: 43px;
|
||||
}
|
||||
.icon-hand {
|
||||
left: -68px;
|
||||
top: 43px;
|
||||
}
|
||||
.level .active {
|
||||
color: #f8b84ef2;
|
||||
}
|
||||
.top_action {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: 15px;
|
||||
padding: 0 15px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.back {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #c5c5d5;
|
||||
margin-right: 20px;
|
||||
}
|
||||
.right_action .back:last-child {
|
||||
margin-right: 0 !important;
|
||||
}
|
||||
.top_action .obstacle,
|
||||
.icon-hand {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
.speed {
|
||||
width: 100px;
|
||||
border: 1px solid #000;
|
||||
padding: 5px 15px;
|
||||
border-radius: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.speed img {
|
||||
margin-right: 15px;
|
||||
}
|
||||
.right_action {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.lamp {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 200px;
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.lamp img {
|
||||
padding: 0px 12px;
|
||||
background: #c5c4d5;
|
||||
color: #fff;
|
||||
border-radius: 30px;
|
||||
height: 35px;
|
||||
}
|
||||
|
||||
.open {
|
||||
animation: openLamp 0.8s infinite alternate;
|
||||
}
|
||||
|
||||
@keyframes openLamp {
|
||||
from {
|
||||
background: #a2a1a1;
|
||||
}
|
||||
|
||||
to {
|
||||
background: #f8bd5d;
|
||||
}
|
||||
}
|
||||
1
code/SmallCart/SmallCartMain/data/img/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
a388ed8d-0d80-4fac-8a45-35c99b4a5c34
|
||||
BIN
code/SmallCart/SmallCartMain/data/img/action.mp3
Normal file
BIN
code/SmallCart/SmallCartMain/data/img/hand.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
code/SmallCart/SmallCartMain/data/img/headlight.png
Normal file
|
After Width: | Height: | Size: 748 B |
BIN
code/SmallCart/SmallCartMain/data/img/horn.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
code/SmallCart/SmallCartMain/data/img/joystick-blue.png
Normal file
|
After Width: | Height: | Size: 9.2 KiB |
BIN
code/SmallCart/SmallCartMain/data/img/joystick-speed.png
Normal file
|
After Width: | Height: | Size: 8.3 KiB |
BIN
code/SmallCart/SmallCartMain/data/img/leftlight.png
Normal file
|
After Width: | Height: | Size: 522 B |
BIN
code/SmallCart/SmallCartMain/data/img/level.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
code/SmallCart/SmallCartMain/data/img/obstacle.png
Normal file
|
After Width: | Height: | Size: 895 B |
BIN
code/SmallCart/SmallCartMain/data/img/rightlight.png
Normal file
|
After Width: | Height: | Size: 523 B |
BIN
code/SmallCart/SmallCartMain/data/img/stop.png
Normal file
|
After Width: | Height: | Size: 569 B |
BIN
code/SmallCart/SmallCartMain/data/img/vertical.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
code/SmallCart/SmallCartMain/data/img/warning.png
Normal file
|
After Width: | Height: | Size: 970 B |
57
code/SmallCart/SmallCartMain/data/index.html
Normal file
@@ -0,0 +1,57 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>智能小车控制面板</title>
|
||||
<link rel="stylesheet" href="./css/index.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="remote_rod">
|
||||
|
||||
<div class="vertical rod">
|
||||
<img id="stick1" src="./img/joystick-speed.png" />
|
||||
</div>
|
||||
|
||||
<div class="level rod">
|
||||
<img id="stick2" src="./img/joystick-blue.png" />
|
||||
<div class="action">
|
||||
<img class="icon-zidongdadeng" src="./img/headlight.png" alt="">
|
||||
<img class="icon-jinggao_o" src="./img/warning.png" alt="">
|
||||
<img class="icon-xiaolaba" src="./img/horn.png" alt="">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="top_action">
|
||||
<div></div>
|
||||
<div class="speed">
|
||||
<img src="./img/stop.png" alt=""> 0km/h
|
||||
</div>
|
||||
<div class="right_action">
|
||||
<div class="back hand_wrap">
|
||||
<img class="icon-hand" src="./img/hand.png" alt="">
|
||||
</div>
|
||||
<div class="back obstacle_wrap">
|
||||
<img class="obstacle" src="./img/obstacle.png" alt="">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <div class="lamp">
|
||||
<img class="open" src="./img/leftlight.png" alt="">
|
||||
<img src="./img/rightlight.png" alt="">
|
||||
</div> -->
|
||||
|
||||
<audio class="actionAudio" src="./img/action.mp3" controls hidden></audio>
|
||||
</body>
|
||||
<script src="./js/utils.js"></script>
|
||||
<script src="./js/WebSocket.js"></script>
|
||||
<script src="./js/Joystick.js"></script>
|
||||
<script src="./js/index.js"></script>
|
||||
|
||||
</html>
|
||||
1
code/SmallCart/SmallCartMain/data/js/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
525da242-f4be-4a40-9f41-1589a0071a96
|
||||
134
code/SmallCart/SmallCartMain/data/js/Joystick.js
Normal file
@@ -0,0 +1,134 @@
|
||||
class Joystick {
|
||||
|
||||
// 元素id,最大移动距离
|
||||
constructor(stickID, direction, callback) {
|
||||
this.id = stickID;
|
||||
this.maxDistance = 64;
|
||||
this.direction = direction;
|
||||
this.callback = callback;
|
||||
this.time = null
|
||||
this.stick = document.getElementById(stickID);
|
||||
|
||||
// 开始拖动的位置,用于计算偏移量
|
||||
this.dragStart = null;
|
||||
|
||||
// 如果存在多个操纵手柄,则跟踪触摸标识符
|
||||
this.touchId = null;
|
||||
|
||||
this.active = false;
|
||||
this.EventListener();
|
||||
}
|
||||
|
||||
handleDown(event) {
|
||||
|
||||
this.active = true;
|
||||
this.stick.style.transition = '0s';
|
||||
|
||||
// 阻止默认事件
|
||||
event.preventDefault();
|
||||
|
||||
// 记录初始点击的坐标
|
||||
if (event.changedTouches) {
|
||||
this.dragStart = { x: event.changedTouches[0].clientX, y: event.changedTouches[0].clientY };
|
||||
} else {
|
||||
this.dragStart = { x: event.clientX, y: event.clientY };
|
||||
}
|
||||
|
||||
// console.log("event: ", event);
|
||||
// console.log("event.changedTouches: ", event.changedTouches);
|
||||
|
||||
// 记录点击的id
|
||||
if (event.changedTouches) {
|
||||
this.touchId = event.changedTouches[0].identifier;
|
||||
}
|
||||
|
||||
}
|
||||
handleMove(event) {
|
||||
if (!this.active) return;
|
||||
if (event.changedTouches && this.touchId != event.changedTouches[0].identifier) return;
|
||||
|
||||
// 处理多点触控
|
||||
if (event.changedTouches) {
|
||||
for (let i = 0; i < event.changedTouches.length; i++) {
|
||||
if (this.touchId == event.changedTouches[i].identifier) {
|
||||
event.clientX = event.changedTouches[i].clientX;
|
||||
event.clientY = event.changedTouches[i].clientY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 计算 x 轴距离
|
||||
const xDiff = event.clientX - this.dragStart.x;
|
||||
// 计算 y 轴距离
|
||||
const yDiff = event.clientY - this.dragStart.y;
|
||||
|
||||
// 计算 角度
|
||||
const angle = Math.atan2(yDiff, xDiff);
|
||||
|
||||
// 计算 距离
|
||||
const distance = Math.min(this.maxDistance, Math.hypot(xDiff, yDiff));
|
||||
|
||||
|
||||
// 计算 x,y 的新位置
|
||||
const xPosition = distance * Math.cos(angle);
|
||||
const yPosition = distance * Math.sin(angle);
|
||||
|
||||
if (this.time && (Date.now() - this.time) < 30) return
|
||||
this.time = Date.now()
|
||||
|
||||
if (this.direction == "x") {
|
||||
// console.log("xPosition: ", Math.sign(xPosition));
|
||||
// 左边 0 ~ -64 -1 3
|
||||
if (xPosition < 0) {
|
||||
if (xPosition < -63) {
|
||||
console.log("左边: ", xPosition);
|
||||
this.callback(3)
|
||||
}
|
||||
// 右边 1 4
|
||||
} else if (xPosition > 0){
|
||||
if (xPosition > 63) {
|
||||
console.log("右边: ", xPosition);
|
||||
this.callback(4)
|
||||
}
|
||||
}
|
||||
// 将图片移动到新位置
|
||||
this.stick.style.transform = `translate3d(${xPosition}px,0px, 0px)`;
|
||||
// this.callback(Math.sign(xPosition) == -1 ? 3 : 4)
|
||||
} else {
|
||||
console.log("yPosition: ", yPosition);
|
||||
this.stick.style.transform = `translate3d(0px,${yPosition}px, 0px)`;
|
||||
this.callback(Math.sign(yPosition) == -1 ? 1 : 2, Math.round(255 * Math.round(Math.abs(yPosition)) / 64))
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
handleUp(event) {
|
||||
|
||||
if (!this.active) return;
|
||||
if (event.changedTouches && this.touchId != event.changedTouches[0].identifier) return;
|
||||
|
||||
this.active = false;
|
||||
|
||||
// console.log("3 handleUp ==== ", this.active);
|
||||
|
||||
|
||||
this.stick.style.transition = '.2s';
|
||||
this.stick.style.transform = `translate3d(0px, 0px, 0px)`;
|
||||
this.touchId = null;
|
||||
|
||||
this.callback(0, 0)
|
||||
}
|
||||
EventListener() {
|
||||
// 鼠标 & 手指 按下
|
||||
this.stick.addEventListener('mousedown', this.handleDown.bind(this));
|
||||
this.stick.addEventListener('touchstart', this.handleDown.bind(this));
|
||||
|
||||
// 鼠标 & 手指 移动
|
||||
document.addEventListener('mousemove', this.handleMove.bind(this), { passive: false });
|
||||
document.addEventListener('touchmove', this.handleMove.bind(this), { passive: false });
|
||||
|
||||
// 鼠标 & 手指 松开
|
||||
document.addEventListener('mouseup', this.handleUp.bind(this));
|
||||
document.addEventListener('touchend', this.handleUp.bind(this));
|
||||
}
|
||||
}
|
||||
38
code/SmallCart/SmallCartMain/data/js/WebSocket.js
Normal file
@@ -0,0 +1,38 @@
|
||||
class WS {
|
||||
constructor() {
|
||||
this.ws = null;
|
||||
this.connect();
|
||||
this.onopen();
|
||||
this.onclose();
|
||||
this.onerror();
|
||||
}
|
||||
|
||||
connect() {
|
||||
this.ws = new WebSocket("ws://192.168.4.1:81");
|
||||
console.log("this.ws: ", this.ws);
|
||||
}
|
||||
|
||||
onopen() {
|
||||
this.ws.onopen = () => {
|
||||
console.log("WebSocket open");
|
||||
}
|
||||
}
|
||||
|
||||
onmessage(callback) {
|
||||
this.ws.onmessage = (e) => {
|
||||
callback(e.data)
|
||||
}
|
||||
}
|
||||
|
||||
onclose() {
|
||||
this.ws.onclose = (e) => {
|
||||
console.log("close");
|
||||
}
|
||||
}
|
||||
|
||||
onerror() {
|
||||
this.ws.onerror = (e) => {
|
||||
console.log("onerror");
|
||||
}
|
||||
}
|
||||
}
|
||||
157
code/SmallCart/SmallCartMain/data/js/index.js
Normal file
@@ -0,0 +1,157 @@
|
||||
/**
|
||||
* wx.send("操作类型|操作状态|其他数值")
|
||||
* 操作类型:y 代表速度摇杆
|
||||
* x 代表方向摇杆
|
||||
* o 代表其他操作
|
||||
*/
|
||||
class IndexPage {
|
||||
constructor() {
|
||||
|
||||
// 自动壁障的开关
|
||||
this.obstacleStatus =
|
||||
localStorage.getItem("obstacleStatus") == null
|
||||
? false
|
||||
: JSON.parse(localStorage.getItem("obstacleStatus"))
|
||||
|
||||
// 前大灯的开关
|
||||
this.fronLamp =
|
||||
localStorage.getItem("fronLamp") == null
|
||||
? false
|
||||
: JSON.parse(localStorage.getItem("fronLamp"))
|
||||
|
||||
// 双闪的开关
|
||||
this.doubleStatus =
|
||||
localStorage.getItem("doubleStatus") == null
|
||||
? false
|
||||
: JSON.parse(localStorage.getItem("doubleStatus"))
|
||||
|
||||
|
||||
// 手势跟随的开关
|
||||
this.handStatus =
|
||||
localStorage.getItem("handStatus") == null
|
||||
? false
|
||||
: JSON.parse(localStorage.getItem("handStatus"))
|
||||
|
||||
|
||||
this.doubleIntervalId = null;
|
||||
this.socket = new WS();
|
||||
this.Joystick();
|
||||
this.bindActionButton();
|
||||
}
|
||||
|
||||
Joystick() {
|
||||
// 前进后退摇杆
|
||||
// status:-1 前进 1 后退,0 停止
|
||||
// speed:前进后退的速度 0 ~ 255 之间
|
||||
var s1 = new Joystick("stick1", "y", (status, speed) => {
|
||||
this.socket.ws.send(`y|${status}|${speed}`)
|
||||
});
|
||||
|
||||
// 左右转向摇杆
|
||||
// status:3左转 4右转 0 转向恢复原样(直行)
|
||||
var s2 = new Joystick("stick2", "x", (status) => {
|
||||
this.socket.ws.send(`x|${status}`)
|
||||
});
|
||||
|
||||
this.socket.onmessage((res) => {
|
||||
console.log("res = ",res);
|
||||
alert("web收到请求为:")
|
||||
alert(JSON.stringify(res))
|
||||
res = res.split("|");
|
||||
switch (res[0]) {
|
||||
case "server":
|
||||
if (res[1] == "y") {
|
||||
$("#stick1").style = "";
|
||||
$("#stick2").style = "";
|
||||
s1.active = false;
|
||||
s1.dragStart = { x: 0, y: 0 };
|
||||
|
||||
s2.active = false;
|
||||
s2.dragStart = { x: 0, y: 0 };
|
||||
}
|
||||
break;
|
||||
case "client":
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
bindActionButton() {
|
||||
|
||||
if (this.obstacleStatus) {
|
||||
$(".obstacle_wrap").classList.add("open")
|
||||
}
|
||||
|
||||
if (this.fronLamp) {
|
||||
$(".icon-zidongdadeng").classList.add("open")
|
||||
}
|
||||
|
||||
if (this.doubleStatus) {
|
||||
$(".icon-jinggao_o").classList.add("open")
|
||||
}
|
||||
|
||||
if (this.handStatus) {
|
||||
$(".hand_wrap").classList.add("open")
|
||||
}
|
||||
|
||||
// 喇叭开关
|
||||
$(".icon-xiaolaba").onclick = () => {
|
||||
this.play();
|
||||
this.socket.ws.send(`b|buzzer|1`)
|
||||
}
|
||||
|
||||
// 手势跟随
|
||||
$(".hand_wrap").onclick = () => {
|
||||
this.play();
|
||||
this.handStatus = !this.handStatus
|
||||
$(".hand_wrap").classList.toggle("open")
|
||||
localStorage.setItem("handStatus", this.handStatus)
|
||||
this.socket.ws.send(`b|openHand|${this.handStatus ? '1' : '0'}`)
|
||||
}
|
||||
|
||||
// 前面大灯
|
||||
$(".icon-zidongdadeng").onclick = () => {
|
||||
this.play();
|
||||
this.fronLamp = !this.fronLamp
|
||||
$(".icon-zidongdadeng").classList.toggle("open")
|
||||
localStorage.setItem("fronLamp", this.fronLamp)
|
||||
this.socket.ws.send(`b|fronLamp|${this.fronLamp ? '1' : '0'}`)
|
||||
}
|
||||
|
||||
// 双闪
|
||||
$(".icon-jinggao_o").onclick = () => {
|
||||
this.play();
|
||||
this.doubleStatus = !this.doubleStatus
|
||||
$(".icon-jinggao_o").classList.toggle("open")
|
||||
localStorage.setItem("doubleStatus", this.doubleStatus)
|
||||
if (this.doubleStatus) {
|
||||
this.doubleIntervalId = setInterval(() => this.socket.ws.send(`b|doubleFlash|1`), 1000)
|
||||
} else {
|
||||
clearInterval(this.doubleIntervalId)
|
||||
this.socket.ws.send(`b|doubleFlash|0`)
|
||||
}
|
||||
}
|
||||
|
||||
$(".obstacle_wrap").onclick = () => {
|
||||
this.play();
|
||||
// 1 true, 0 false
|
||||
this.obstacleStatus = !this.obstacleStatus
|
||||
|
||||
$(".obstacle_wrap").classList.toggle("open")
|
||||
localStorage.setItem("obstacleStatus", this.obstacleStatus)
|
||||
this.socket.ws.send(`b|obstacle|${this.obstacleStatus ? '1' : '0'}`)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
play() {
|
||||
$(".actionAudio").play();
|
||||
}
|
||||
}
|
||||
|
||||
new IndexPage();
|
||||
20
code/SmallCart/SmallCartMain/data/js/utils.js
Normal file
@@ -0,0 +1,20 @@
|
||||
class Utils {
|
||||
$(className) {
|
||||
return document.querySelector(className);
|
||||
}
|
||||
|
||||
|
||||
debounce(fn, delay = 1000) {
|
||||
let timer = null //借助闭包
|
||||
return function () {
|
||||
if (timer) {
|
||||
clearTimeout(timer)
|
||||
}
|
||||
timer = setTimeout(fn, delay) // 简化写法
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
var { $, debounce } = new Utils();
|
||||
133
code/SmallCart/SmallCartMain/data/test.html
Normal file
@@ -0,0 +1,133 @@
|
||||
class Joystick {
|
||||
|
||||
// 元素id,最大移动距离
|
||||
constructor(stickID, direction, callback) {
|
||||
this.id = stickID;
|
||||
this.maxDistance = 64;
|
||||
this.direction = direction;
|
||||
this.callback = callback;
|
||||
this.time = null
|
||||
this.stick = document.getElementById(stickID);
|
||||
|
||||
// 开始拖动的位置,用于计算偏移量
|
||||
this.dragStart = null;
|
||||
|
||||
// 如果存在多个操纵手柄,则跟踪触摸标识符
|
||||
this.touchId = null;
|
||||
|
||||
this.active = false;
|
||||
this.EventListener();
|
||||
}
|
||||
|
||||
handleDown(event) {
|
||||
|
||||
this.active = true;
|
||||
this.stick.style.transition = '0s';
|
||||
|
||||
// 阻止默认事件
|
||||
event.preventDefault();
|
||||
|
||||
// 记录初始点击的坐标
|
||||
if (event.changedTouches) {
|
||||
this.dragStart = { x: event.changedTouches[0].clientX, y: event.changedTouches[0].clientY };
|
||||
} else {
|
||||
this.dragStart = { x: event.clientX, y: event.clientY };
|
||||
}
|
||||
|
||||
// console.log("event: ", event);
|
||||
// console.log("event.changedTouches: ", event.changedTouches);
|
||||
|
||||
// 记录点击的id
|
||||
if (event.changedTouches) {
|
||||
this.touchId = event.changedTouches[0].identifier;
|
||||
}
|
||||
|
||||
}
|
||||
handleMove(event) {
|
||||
if (!this.active) return;
|
||||
|
||||
// 处理多点触控
|
||||
if (event.changedTouches) {
|
||||
for (let i = 0; i < event.changedTouches.length; i++) {
|
||||
if (this.touchId == event.changedTouches[i].identifier) {
|
||||
event.clientX = event.changedTouches[i].clientX;
|
||||
event.clientY = event.changedTouches[i].clientY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 计算 x 轴距离
|
||||
const xDiff = event.clientX - this.dragStart.x;
|
||||
// 计算 y 轴距离
|
||||
const yDiff = event.clientY - this.dragStart.y;
|
||||
|
||||
// 计算 角度
|
||||
const angle = Math.atan2(yDiff, xDiff);
|
||||
|
||||
// 计算 距离
|
||||
const distance = Math.min(this.maxDistance, Math.hypot(xDiff, yDiff));
|
||||
|
||||
|
||||
// 计算 x,y 的新位置
|
||||
const xPosition = distance * Math.cos(angle);
|
||||
const yPosition = distance * Math.sin(angle);
|
||||
|
||||
if (this.time && (Date.now() - this.time) < 160) return
|
||||
this.time = Date.now()
|
||||
|
||||
if (this.direction == "x") {
|
||||
// console.log("xPosition: ", Math.sign(xPosition));
|
||||
// 左边 0 ~ -64 -1 3
|
||||
if (xPosition < 0) {
|
||||
if (xPosition < -63) {
|
||||
console.log("左边: ", xPosition);
|
||||
this.callback(3)
|
||||
}
|
||||
// 右边 1 4
|
||||
} else if (xPosition > 0){
|
||||
if (xPosition > 63) {
|
||||
console.log("右边: ", xPosition);
|
||||
this.callback(4)
|
||||
}
|
||||
}
|
||||
// 将图片移动到新位置
|
||||
this.stick.style.transform = `translate3d(${xPosition}px,0px, 0px)`;
|
||||
// this.callback(Math.sign(xPosition) == -1 ? 3 : 4)
|
||||
} else {
|
||||
console.log("yPosition: ", yPosition);
|
||||
this.stick.style.transform = `translate3d(0px,${yPosition}px, 0px)`;
|
||||
this.callback(Math.sign(yPosition) == -1 ? 1 : 2, Math.round(255 * Math.round(Math.abs(yPosition)) / 64))
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
handleUp(event) {
|
||||
|
||||
if (!this.active) return;
|
||||
if (event.changedTouches && this.touchId != event.changedTouches[0].identifier) return;
|
||||
|
||||
this.active = false;
|
||||
|
||||
// console.log("3 handleUp ==== ", this.active);
|
||||
|
||||
|
||||
this.stick.style.transition = '.2s';
|
||||
this.stick.style.transform = `translate3d(0px, 0px, 0px)`;
|
||||
this.touchId = null;
|
||||
|
||||
this.callback(0, 0)
|
||||
}
|
||||
EventListener() {
|
||||
// 鼠标 & 手指 按下
|
||||
this.stick.addEventListener('mousedown', this.handleDown.bind(this));
|
||||
this.stick.addEventListener('touchstart', this.handleDown.bind(this));
|
||||
|
||||
// 鼠标 & 手指 移动
|
||||
document.addEventListener('mousemove', this.handleMove.bind(this), { passive: false });
|
||||
document.addEventListener('touchmove', this.handleMove.bind(this), { passive: false });
|
||||
|
||||
// 鼠标 & 手指 松开
|
||||
document.addEventListener('mouseup', this.handleUp.bind(this));
|
||||
document.addEventListener('touchend', this.handleUp.bind(this));
|
||||
}
|
||||
}
|
||||
1
code/SmallCart/SmallCartMain/src/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
e6d74282-79e8-4c4b-82d4-91695dc62e77
|
||||
1
code/SmallCart/SmallCartMain/src/buzzer/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
60f5f62f-30da-4cf5-b7c7-ee2d02be432a
|
||||
24
code/SmallCart/SmallCartMain/src/buzzer/buzzer.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#include "buzzer.h"
|
||||
#include "../config/config.h"
|
||||
|
||||
void Buzzer::init()
|
||||
{
|
||||
Serial.println("Buzzer init....");
|
||||
pinMode(BuzzerPin, OUTPUT);
|
||||
digitalWrite(BuzzerPin, LOW);
|
||||
}
|
||||
void Buzzer::on()
|
||||
{
|
||||
digitalWrite(BuzzerPin, HIGH);
|
||||
}
|
||||
void Buzzer::off()
|
||||
{
|
||||
digitalWrite(BuzzerPin, LOW);
|
||||
}
|
||||
|
||||
void Buzzer::warning()
|
||||
{
|
||||
on();
|
||||
delay(200);
|
||||
off();
|
||||
}
|
||||
14
code/SmallCart/SmallCartMain/src/buzzer/buzzer.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef _BUZZER_H__
|
||||
#define _BUZZER_H__
|
||||
#include <Arduino.h>
|
||||
|
||||
class Buzzer
|
||||
{
|
||||
public:
|
||||
void init();
|
||||
void on();
|
||||
void off();
|
||||
void warning();
|
||||
};
|
||||
|
||||
#endif
|
||||
1
code/SmallCart/SmallCartMain/src/config/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
7c54a6e6-291e-460a-b441-b17b9557640e
|
||||
0
code/SmallCart/SmallCartMain/src/config/config.cpp
Normal file
52
code/SmallCart/SmallCartMain/src/config/config.h
Normal file
@@ -0,0 +1,52 @@
|
||||
#ifndef _CONFIG_H__
|
||||
#define _CONFIG_H__
|
||||
#include <Arduino.h>
|
||||
|
||||
// 自己家中的 2.4G wifi名称
|
||||
#define WifiName "bmy"
|
||||
// 自己家中的 2.4G wifi密码
|
||||
#define WifiPwd "lb714500"
|
||||
|
||||
// WiFiManager 自动生成的wifi名和密码,用于小车的自动配网!
|
||||
#define AutoWiFiManagerName "AutoWiFiManager"
|
||||
#define AutoWiFiManagerPwd "123456789"
|
||||
|
||||
#define WebSocketsPort 81
|
||||
#define WebServerPort 80
|
||||
|
||||
// 蜂鸣器
|
||||
#define BuzzerPin 1 // TX 引脚
|
||||
|
||||
// 双闪灯(转向灯)
|
||||
#define BottomLeftPin 10 // SD3 引脚
|
||||
#define BottomRightPin 3 // RX 引脚
|
||||
|
||||
// 小车的五种 状态码
|
||||
#define STOP 0 // 停止
|
||||
#define FORWARD 1 // 前进
|
||||
#define BACKWARD 2 // 后退
|
||||
#define TURNLEFT 3 // 左转
|
||||
#define TURNRIGHT 4 // 右转
|
||||
#define STRAIGHT 5 // 直行
|
||||
|
||||
// 电机驱动接线说明
|
||||
// D5, D6, D8, D2 是 PWM引脚,可以用来控制减速电机的速度 0 ~ 255
|
||||
// D0, D1, D3, D4, D7 是普通引脚,可以通过高低电压来控制车轮转向
|
||||
#define leftMotor1 16 // D0 红线
|
||||
#define leftMotor2 5 // D1 褐线
|
||||
#define leftPWM 4 // D2 橙线
|
||||
|
||||
#define rightMotor1 0 // D3 黑线
|
||||
#define rightMotor2 2 // D4 白线
|
||||
#define rightPWM 14 // D5 灰线
|
||||
|
||||
// 转向舵机
|
||||
#define servoPin 13 // D7 白线
|
||||
|
||||
|
||||
class Config
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
1
code/SmallCart/SmallCartMain/src/led/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
24e58c56-59f7-4ab6-979c-95196881b5f2
|
||||
53
code/SmallCart/SmallCartMain/src/led/led.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
#include "LED.h"
|
||||
#include "../config/config.h"
|
||||
|
||||
void LED::init()
|
||||
{
|
||||
Serial.println("LED init....");
|
||||
pinMode(BottomLeftPin, OUTPUT);
|
||||
pinMode(BottomRightPin, OUTPUT);
|
||||
|
||||
analogWrite(BottomLeftPin, 0);
|
||||
analogWrite(BottomRightPin, 0);
|
||||
}
|
||||
|
||||
// 后边两个灯的双闪
|
||||
void LED::open()
|
||||
{
|
||||
analogWrite(BottomLeftPin, 255);
|
||||
analogWrite(BottomRightPin, 255);
|
||||
delay(300);
|
||||
analogWrite(BottomLeftPin, 0);
|
||||
analogWrite(BottomRightPin, 0);
|
||||
delay(300);
|
||||
}
|
||||
|
||||
void LED::close()
|
||||
{
|
||||
analogWrite(BottomLeftPin, 0);
|
||||
analogWrite(BottomRightPin, 0);
|
||||
}
|
||||
|
||||
// 开左转灯
|
||||
void LED::TurnLeft()
|
||||
{
|
||||
analogWrite(BottomLeftPin, 255);
|
||||
}
|
||||
|
||||
// 关左转灯
|
||||
void LED::TurnLeftClose()
|
||||
{
|
||||
analogWrite(BottomLeftPin, 0);
|
||||
}
|
||||
|
||||
// 开右转灯
|
||||
void LED::TurnRight()
|
||||
{
|
||||
analogWrite(BottomRightPin, 255);
|
||||
}
|
||||
|
||||
// 关右转灯
|
||||
void LED::TurnRightClose()
|
||||
{
|
||||
analogWrite(BottomRightPin, 0);
|
||||
}
|
||||
19
code/SmallCart/SmallCartMain/src/led/led.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef _LED_H__
|
||||
#define _LED_H__
|
||||
#include <Arduino.h>
|
||||
|
||||
class LED
|
||||
{
|
||||
public:
|
||||
void init();
|
||||
void open();
|
||||
void close();
|
||||
|
||||
void TurnLeft();
|
||||
void TurnLeftClose();
|
||||
|
||||
void TurnRight();
|
||||
void TurnRightClose();
|
||||
};
|
||||
|
||||
#endif
|
||||
1
code/SmallCart/SmallCartMain/src/motion/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
02f5af40-b6df-49d1-9324-aafad03ffbf8
|
||||
124
code/SmallCart/SmallCartMain/src/motion/motion.cpp
Normal file
@@ -0,0 +1,124 @@
|
||||
#include "motion.h"
|
||||
#include "../config/config.h"
|
||||
#include "../led/led.h"
|
||||
#include <Servo.h>
|
||||
Servo servo;
|
||||
LED led;
|
||||
|
||||
// 初始化电机驱动各个引脚
|
||||
void Motion::init() {
|
||||
led.init();
|
||||
pinMode(leftMotor1, OUTPUT);
|
||||
pinMode(leftMotor2, OUTPUT);
|
||||
pinMode(leftPWM, OUTPUT);
|
||||
|
||||
pinMode(rightMotor1, OUTPUT);
|
||||
pinMode(rightMotor2, OUTPUT);
|
||||
pinMode(rightPWM, OUTPUT);
|
||||
|
||||
servo.attach(servoPin);
|
||||
servo.write(98);
|
||||
}
|
||||
|
||||
// 设置小车速度
|
||||
void Motion::speed(int LevelSpeed) {
|
||||
// 设置运动的速度
|
||||
analogWrite(leftPWM, LevelSpeed);
|
||||
analogWrite(rightPWM, LevelSpeed);
|
||||
}
|
||||
|
||||
// 运动函数
|
||||
void Motion::run(int cmd)
|
||||
{
|
||||
switch (cmd)
|
||||
{
|
||||
case FORWARD:
|
||||
digitalWrite(leftMotor1, LOW);
|
||||
digitalWrite(leftMotor2, HIGH);
|
||||
digitalWrite(rightMotor1, LOW);
|
||||
digitalWrite(rightMotor2, HIGH);
|
||||
led.TurnLeftClose();
|
||||
led.TurnRightClose();
|
||||
break;
|
||||
case BACKWARD:
|
||||
digitalWrite(leftMotor1, HIGH);
|
||||
digitalWrite(leftMotor2, LOW);
|
||||
digitalWrite(rightMotor1, HIGH);
|
||||
digitalWrite(rightMotor2, LOW);
|
||||
led.TurnRight();
|
||||
led.TurnLeft();
|
||||
break;
|
||||
case TURNLEFT:
|
||||
led.TurnLeft();
|
||||
led.TurnRightClose();
|
||||
servo.write(40);
|
||||
break;
|
||||
case TURNRIGHT:
|
||||
led.TurnRight();
|
||||
led.TurnLeftClose();
|
||||
servo.write(140);
|
||||
break;
|
||||
case STRAIGHT:
|
||||
led.TurnLeftClose();
|
||||
led.TurnRightClose();
|
||||
servo.write(100);
|
||||
break;
|
||||
default:
|
||||
led.TurnLeftClose();
|
||||
led.TurnRightClose();
|
||||
digitalWrite(leftMotor1, LOW);
|
||||
digitalWrite(leftMotor2, LOW);
|
||||
digitalWrite(rightMotor1, LOW);
|
||||
digitalWrite(rightMotor2, LOW);
|
||||
}
|
||||
}
|
||||
|
||||
// 控制舵机转向一定角度
|
||||
void Motion::turn(int nums) {
|
||||
servo.write(nums);
|
||||
}
|
||||
|
||||
// 开启双闪
|
||||
void Motion::open() {
|
||||
led.open();
|
||||
}
|
||||
|
||||
// 开启双闪
|
||||
void Motion::close() {
|
||||
led.close();
|
||||
}
|
||||
|
||||
// 后退并前进
|
||||
void Motion::left() {
|
||||
// backOff();
|
||||
speed(100);
|
||||
delay(100);
|
||||
run(1);
|
||||
}
|
||||
|
||||
// 后退并前进
|
||||
void Motion::right() {
|
||||
// backOff();
|
||||
speed(100);
|
||||
delay(100);
|
||||
run(1);
|
||||
}
|
||||
|
||||
// 前进
|
||||
void Motion::straight() {
|
||||
// 设置电机速度
|
||||
speed(100);
|
||||
// 直行
|
||||
servo.write(90);
|
||||
delay(100);
|
||||
run(1);
|
||||
}
|
||||
|
||||
// 后退
|
||||
void Motion::backOff() {
|
||||
speed(180);
|
||||
run(2);
|
||||
delay(1000);
|
||||
run(0);
|
||||
delay(100);
|
||||
}
|
||||
20
code/SmallCart/SmallCartMain/src/motion/motion.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef _MOTION_H__
|
||||
#define _MOTION_H__
|
||||
#include <Arduino.h>
|
||||
|
||||
class Motion
|
||||
{
|
||||
public:
|
||||
void init();
|
||||
void run(int cmd);
|
||||
void speed(int LevelSpeed);
|
||||
void turn(int nums);
|
||||
void open();
|
||||
void close();
|
||||
void left();
|
||||
void right();
|
||||
void straight();
|
||||
void backOff();
|
||||
};
|
||||
|
||||
#endif
|
||||
1
code/SmallCart/SmallCartMain/src/socket/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
f498de60-f87e-4eaf-a7a0-3b7a83c2547a
|
||||
173
code/SmallCart/SmallCartMain/src/socket/socket.cpp
Normal file
@@ -0,0 +1,173 @@
|
||||
#include "socket.h"
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <WebSocketsServer.h>
|
||||
#include "../config/config.h"
|
||||
#include "../motion/motion.h"
|
||||
#include "../buzzer/buzzer.h"
|
||||
|
||||
Motion motionSocket;
|
||||
Buzzer buzzerSocket;
|
||||
|
||||
Socket::Socket() {
|
||||
Server = new WebSocketsServer(WebSocketsPort);
|
||||
}
|
||||
|
||||
void Socket::init () {
|
||||
// 启动WebSocket服务器
|
||||
Server->begin();
|
||||
// 指定事件处理函数
|
||||
Server->onEvent([&](uint8_t num, WStype_t type, uint8_t *payload, size_t length) {
|
||||
switch (type)
|
||||
{
|
||||
case WStype_CONNECTED:
|
||||
Serial.println("New connection!");
|
||||
break;
|
||||
case WStype_DISCONNECTED:
|
||||
Serial.println("Close the connection.");
|
||||
break;
|
||||
case WStype_TEXT:
|
||||
String data = (char *)payload;
|
||||
Serial.print("data ====== ");
|
||||
Serial.println(data);
|
||||
|
||||
// digitalWrite(LED_BUILTIN, HIGH);
|
||||
|
||||
String type = getValue(data, '|', 0);
|
||||
// 如果是红色摇杆
|
||||
if (type == "y")
|
||||
{
|
||||
|
||||
// 获取前进或是后退的方向
|
||||
String direction = getValue(data, '|', 1);
|
||||
|
||||
Serial.println("direction ====== ");
|
||||
Serial.print(direction);
|
||||
// 获取前进或是后退的速度
|
||||
String speed = getValue(data, '|', 2);
|
||||
// 设置运动的速度
|
||||
motionSocket.speed(speed.toInt());
|
||||
// 设置前进的方向
|
||||
motionSocket.run(direction.toInt());
|
||||
// 如果是蓝色摇杆
|
||||
}
|
||||
else if (type == "x")
|
||||
{
|
||||
// 获取摇杆的左右方向
|
||||
String level = getValue(data, '|', 1);
|
||||
// 为0 表示松开摇杆,车轮恢复直行
|
||||
if (!level.compareTo("0"))
|
||||
{
|
||||
motionSocket.run(5);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 转向
|
||||
motionSocket.run(level.toInt());
|
||||
}
|
||||
}
|
||||
// 如果web前端的按钮操作
|
||||
else if (type == "b")
|
||||
{
|
||||
String bType = getValue(data, '|', 1);
|
||||
// 打开蜂鸣器
|
||||
if (bType == "buzzer") {
|
||||
buzzerSocket.warning();
|
||||
|
||||
// 开始自动避障
|
||||
} else if (bType == "obstacle") {
|
||||
String va = getValue(data, '|', 2);
|
||||
SendClient(String("client|Automatic|")+String(va), IPAddress(192, 168, 4, 2));
|
||||
|
||||
} else if (bType == "fronLamp") {
|
||||
String status = getValue(data, '|', 2);
|
||||
SendClient(String("client|fronLamp|")+String(status), IPAddress(192, 168, 4, 2));
|
||||
|
||||
} else if (bType == "doubleFlash") {
|
||||
String flash = getValue(data, '|', 2);
|
||||
flash == "1" ? motionSocket.open() : motionSocket.close();
|
||||
SendClient(String("client|doubleFlash|")+String(flash), IPAddress(192, 168, 4, 2));
|
||||
} else if (bType == "openHand") {
|
||||
String hand = getValue(data, '|', 2);
|
||||
SendClient(String("client|AutoHand|")+String(hand), IPAddress(192, 168, 4, 2));
|
||||
}
|
||||
|
||||
// 如果是各种传感器
|
||||
} else if (type == "sensor") {
|
||||
// 获取是哪一类传感器
|
||||
String sensorType = getValue(data, '|', 1);
|
||||
|
||||
// 超声波传感器
|
||||
if (sensorType == "ultrasonic") {
|
||||
String actionType = getValue(data, '|', 2);
|
||||
|
||||
if (actionType == "stop") {
|
||||
digitalWrite(LED_BUILTIN, HIGH);
|
||||
motionSocket.run(0);
|
||||
// 通知前端,自动停车后复位现在用户的拖动状态
|
||||
// SendClient(String("server|y|reset"), IPAddress(192, 168, 4, 3));
|
||||
} else {
|
||||
digitalWrite(LED_BUILTIN, LOW);
|
||||
}
|
||||
|
||||
// 控制舵机转动
|
||||
} else if (sensorType == "servo") {
|
||||
String pos = getValue(data, '|', 2);
|
||||
motionSocket.turn(pos.toInt());
|
||||
|
||||
// 转弯并前进
|
||||
} else if (sensorType == "motor") {
|
||||
|
||||
String turnDirection = getValue(data, '|', 2);
|
||||
if (turnDirection == "left") {
|
||||
motionSocket.left();
|
||||
} else if (turnDirection == "right") {
|
||||
motionSocket.right();
|
||||
} else if (turnDirection == "straight") {
|
||||
motionSocket.straight();
|
||||
} else if (turnDirection == "back") {
|
||||
motionSocket.backOff();
|
||||
}
|
||||
} else {
|
||||
digitalWrite(LED_BUILTIN, LOW);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
String Socket::getValue(String data, char separator, int index) {
|
||||
int found = 0;
|
||||
int strIndex[] = {0, -1};
|
||||
int maxIndex = data.length() - 1;
|
||||
|
||||
for (int i = 0; i <= maxIndex && found <= index; i++)
|
||||
{
|
||||
if (data.charAt(i) == separator || i == maxIndex)
|
||||
{
|
||||
found++;
|
||||
strIndex[0] = strIndex[1] + 1;
|
||||
strIndex[1] = (i == maxIndex) ? i + 1 : i;
|
||||
}
|
||||
}
|
||||
return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
|
||||
}
|
||||
|
||||
//通过IP地址获取客户端编号
|
||||
int8_t Socket::GetIp(IPAddress ip_needed) {
|
||||
for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
|
||||
IPAddress ip = Server->remoteIP(i);
|
||||
if(ip == ip_needed) {
|
||||
// ip found
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 向指定ip的设备发送消息
|
||||
void Socket::SendClient(String data, IPAddress ip) {
|
||||
Server->sendTXT(GetIp(ip), data);
|
||||
}
|
||||
20
code/SmallCart/SmallCartMain/src/socket/socket.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef _SOCKET_H__
|
||||
#define _SOCKET_H__
|
||||
#include <Arduino.h>
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <WebSocketsServer.h>
|
||||
|
||||
class Socket
|
||||
{
|
||||
public:
|
||||
Socket();
|
||||
void init();
|
||||
WebSocketsServer *Server;
|
||||
int8_t GetIp(IPAddress ip_needed);
|
||||
void SendClient(String data, IPAddress ip);
|
||||
|
||||
private:
|
||||
String getValue(String data, char separator, int index);
|
||||
};
|
||||
|
||||
#endif
|
||||
1
code/SmallCart/SmallCartMain/src/web/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
c72523c9-04ee-40de-9873-84ae5ef8571b
|
||||
85
code/SmallCart/SmallCartMain/src/web/web.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
#include "web.h"
|
||||
#include "../config/config.h"
|
||||
#include <ESP8266WebServer.h>
|
||||
#include <FS.h>
|
||||
|
||||
Web::Web()
|
||||
{
|
||||
WebController = new ESP8266WebServer(WebServerPort);
|
||||
}
|
||||
|
||||
void Web::init()
|
||||
{
|
||||
// 启动闪存文件系统
|
||||
if (SPIFFS.begin()) {
|
||||
Serial.println("SPIFFS Started.");
|
||||
} else {
|
||||
Serial.println("SPIFFS Failed to Start.");
|
||||
}
|
||||
|
||||
WebController->onNotFound(
|
||||
std::bind(&Web::handleUserRequest, this)
|
||||
);
|
||||
WebController->begin();
|
||||
Serial.println("HTTP server started");
|
||||
}
|
||||
|
||||
void Web::handleUserRequest()
|
||||
{
|
||||
String reqResource = WebController->uri();
|
||||
Serial.print("reqResource: ");
|
||||
Serial.println(reqResource);
|
||||
bool fileReadOK = handleFileRead(reqResource);
|
||||
if (!fileReadOK)
|
||||
{
|
||||
WebController->send(404, "text/plain", "404 Not Found");
|
||||
}
|
||||
}
|
||||
|
||||
bool Web::handleFileRead(String resource)
|
||||
{
|
||||
if (resource.endsWith("/"))
|
||||
{ // 如果访问地址以"/"为结尾
|
||||
resource = "/index.html"; // 则将访问地址修改为/index.html便于SPIFFS访问
|
||||
}
|
||||
String contentType = getContentType(resource); // 获取文件类型
|
||||
|
||||
if (SPIFFS.exists(resource))
|
||||
{ // 如果访问的文件可以在SPIFFS中找到
|
||||
Serial.println("have file.....");
|
||||
File file = SPIFFS.open(resource, "r"); // 则尝试打开该文件
|
||||
WebController->streamFile(file, contentType); // 并且将该文件返回给浏览器
|
||||
file.close(); // 并且关闭文件
|
||||
return true; // 返回true
|
||||
}
|
||||
return false; // 如果文件未找到,则返回false
|
||||
}
|
||||
|
||||
String Web::getContentType(String filename)
|
||||
{
|
||||
if (filename.endsWith(".htm"))
|
||||
return "text/html";
|
||||
else if (filename.endsWith(".html"))
|
||||
return "text/html";
|
||||
else if (filename.endsWith(".css"))
|
||||
return "text/css";
|
||||
else if (filename.endsWith(".js"))
|
||||
return "application/javascript";
|
||||
else if (filename.endsWith(".png"))
|
||||
return "image/png";
|
||||
else if (filename.endsWith(".gif"))
|
||||
return "image/gif";
|
||||
else if (filename.endsWith(".jpg"))
|
||||
return "image/jpeg";
|
||||
else if (filename.endsWith(".ico"))
|
||||
return "image/x-icon";
|
||||
else if (filename.endsWith(".xml"))
|
||||
return "text/xml";
|
||||
else if (filename.endsWith(".pdf"))
|
||||
return "application/x-pdf";
|
||||
else if (filename.endsWith(".zip"))
|
||||
return "application/x-zip";
|
||||
else if (filename.endsWith(".gz"))
|
||||
return "application/x-gzip";
|
||||
return "text/plain";
|
||||
}
|
||||
19
code/SmallCart/SmallCartMain/src/web/web.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef _WEB_H__
|
||||
#define _WEB_H__
|
||||
#include <Arduino.h>
|
||||
#include <ESP8266WebServer.h>
|
||||
|
||||
class Web
|
||||
{
|
||||
public:
|
||||
Web();
|
||||
void init();
|
||||
ESP8266WebServer *WebController;
|
||||
|
||||
private:
|
||||
void handleUserRequest();
|
||||
bool handleFileRead(String resource);
|
||||
String getContentType(String filename);
|
||||
};
|
||||
|
||||
#endif
|
||||
1
code/SmallCart/SmallCartMain/src/wifi/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
302e0f8f-350d-4802-9546-03c85d2d5457
|
||||
21
code/SmallCart/SmallCartMain/src/wifi/wifi.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <DNSServer.h>
|
||||
#include <ESP8266WebServer.h>
|
||||
#include "wifi.h"
|
||||
#include "../config/config.h"
|
||||
|
||||
// 清除之前的wifi配置
|
||||
void ConfigWifi::init() {
|
||||
// 设置WiFi运行模式为无线终端模式
|
||||
WiFi.mode(WIFI_AP);
|
||||
Serial.println(WiFi.softAP(AutoWiFiManagerName, AutoWiFiManagerPwd) ? "Ready" : "Failed!");
|
||||
Connect();
|
||||
}
|
||||
|
||||
|
||||
void ConfigWifi::Connect() {
|
||||
Serial.print("Wifi Name: ");
|
||||
Serial.println(AutoWiFiManagerName);
|
||||
Serial.print("IP address:");
|
||||
Serial.println(WiFi.softAPIP());
|
||||
}
|
||||
17
code/SmallCart/SmallCartMain/src/wifi/wifi.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef _WIFI_H__
|
||||
#define _WIFI_H__
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include <WiFiManager.h>
|
||||
|
||||
class ConfigWifi
|
||||
{
|
||||
private:
|
||||
WiFiManager wifiManager;
|
||||
public:
|
||||
void init();
|
||||
void Connect();
|
||||
};
|
||||
|
||||
#endif
|
||||