海绵宝宝队参赛部分代码。
详细代码见
https://arduino.esp8266.com/stable/package_esp8266com_index.json
(22条消息) nodeMCU_esp8266管脚示意图/特殊管脚的使用避坑(D3/D4/D8/..)_xuchaoxin1375的博客-CSDN博客_esp8266nodemcu引脚图及其功能
Websockets@2.3.6 by Markus Sattler
Adafruit_SSD1306@2.5.3 by Adafruit
DHT sensor library@1.4.3 by Adafruit
地址为0X3C。
/*--------------------WIFI-----------------------------------------*/
#include <ESP8266WiFi.h>
#include <WebSocketsClient.h>
#include <DHT.h>
#define DHTPIN 12
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
WebSocketsClient wsClient;
#define SN "abcdefg"
#ifndef STASSID
#define STASSID "1021"
#define STAPSK "5p2O546L6YK16IuP546L5a6J"
#endif
const char* ssid = STASSID;
const char* password = STAPSK;
/*--------------------OLED-----------------------------------------*/
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
void setup() {
Serial.begin(115200);
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
//Adafruit_GFX
display.display();
delay(2000);
display.clearDisplay();
display.setTextSize(1); // Normal 1:1 pixel scale
display.setTextColor(WHITE); // Draw white text
display.setTextWrap(false);
// We start by connecting to a WiFi network
Serial.println();
Serial.println();
Serial.print(F("Connecting to "));
println(F("Connecting to ")+String(ssid));
Serial.println(ssid);
/* Explicitly set the ESP8266 to be a WiFi-client, otherwise, it by default,
would try to act as both a client and an access-point and could cause
network-issues with your other WiFi-devices on your WiFi-network. */
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(F("."));
print(F("."));
}
Serial.println("");
Serial.println("WiFi connected");
println(F("WiFi connected"));
Serial.println("IP address: ");
println(F("IP address: "));
Serial.println(WiFi.localIP());
println(WiFi.localIP().toString());
// 启动WebSocketsClient,设定WebSocket服务器地址为remoteHost,端口号为81
wsClient.begin("119.29.115.242", 80);
// 指定事件处理函数
wsClient.onEvent([](WStype_t type, uint8_t * payload, size_t length) {
/* param:
type: 事件类型
payload: 事件携带数据
length: 事件携带数据长度
*/
if (type == WStype_TEXT){
String data = (char*)payload;
Serial.println(data);
println(data);
wsClient.sendTXT("你好!");
if(data=="hello"){
String msg="{\"cmd\":\"init\",\"args\":{\"sn\":\""+String(SN)+"\"}}";
Serial.println(msg);
wsClient.sendTXT(msg);
}else if(data=="watering"){
digitalWrite(14, HIGH);
}else if(data=="stopWatering"){
digitalWrite(14, LOW);
}
}
});
dht.begin();
pinMode(14,OUTPUT);
delay(3000);
}
String dhtData="";
void loop() {
wsClient.loop();
// Wait a few seconds between measurements.
// Reading temperature or humidity takes about 250 milliseconds!
// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
float h = dht.readHumidity();
// Read temperature as Celsius (the default)
float t = dht.readTemperature();
// Read temperature as Fahrenheit (isFahrenheit = true)
float f = dht.readTemperature(true);
// Check if any reads failed and exit early (to try again).
if (isnan(h) || isnan(t) || isnan(f)) {
Serial.println(F("Failed to read from DHT sensor!"));
return;
}
// Compute heat index in Fahrenheit (the default)
float hif = dht.computeHeatIndex(f, h);
// Compute heat index in Celsius (isFahreheit = false)
float hic = dht.computeHeatIndex(t, h, false);
if(dhtData!=String(h)+","+String(t)){
dhtData=String(h)+","+String(t);
println(F("H:")+String(h)+","+F("T:")+String(t));
String msg="{\"cmd\":\"report\",\"args\":{\"type\":\"dht\",\"data\":\""+dhtData+"\"}}";
Serial.println(msg);
wsClient.sendTXT(msg);
}
}
/*--------------------屏幕滚动-----------------------------------------*/
String lines[8];
int firstLineIndex=-7;
int lastLineIndex=0;
bool endlLock=true;
void println(String line) {
if(!endlLock){
lastLineIndex++;
lastLineIndex%=8;
firstLineIndex++;
firstLineIndex%=8;
}
endlLock=true;
lines[lastLineIndex]=line;
display.clearDisplay();
display.setCursor(0, 0);
for(int i=0;i<8;i++){
display.println(lines[(max(firstLineIndex,0)+i)%8]);
}
display.display();
lastLineIndex++;
lastLineIndex%=8;
firstLineIndex++;
firstLineIndex%=8;
}
void print(String line) {
endlLock=false;
lines[lastLineIndex]+=line;
display.clearDisplay();
display.setCursor(0, 0);
for(int i=0;i<8;i++){
display.println(lines[(max(firstLineIndex,0)+i)%8]);
}
display.display();
}
let {
Sensor
} = require("./db.js")
const WebSocket = require('ws')
const wss = new WebSocket.Server({
port: 80
})
let devices = {};
wss.on('connection', function(ws) {
ws.on('message', function(message) {
data = parse(message.toString())
console.log(data['cmd'])
implement(data, ws)
})
ws.on('close', function(message) {
if (devices[ws.id] != undefined) {
devices[ws.id] = undefined
console.log(`设备${ws.id}离线`)
}
})
ws.send("hello")
})
function parse(str) {
let data;
try {
data = JSON.parse(str);
} catch (e) {
return {};
}
return data
}
function implement(data, ws) {
switch (data['cmd']) {
case "init":
ws.sn = data['args']['sn']
devices[ws.sn] = ws
ws.send(`Server Connected!`)
console.log(`设备${ws.sn}已接入服务器`)
break
case "list":
ws.send(`${Object.keys(devices).join('\n')}`)
break
case "call":
let device
if (devices[data['args']['sn']] != undefined) {
device = devices[data['args']['sn']]
if (device.readyState == 1) {
device.send(data['args']['msg'])
} else {
devices[data['args']['sn']] = undefined
ws.send(`该设备未上线`)
}
} else {
ws.send(`该设备未上线`)
}
break
case "report":
//添加
row = {}
row[data['args']['type']] = data['args']['data']
row['sn'] = ws.sn
Sensor.create(row).then(row => {
ws.send(`Uploaded!`)
})
break
case "get":
Sensor.findOne({
where: {
sn: data['args']['sn']
},
order: [
["id", "DESC"]
]
}).then(row => {
ws.send(JSON.stringify(row))
})
}
}
let {
Sequelize,
DataTypes,
Op
} = require("sequelize")
let Tables = new Sequelize("galasp", "galasp", "a20030824.", {
host: "119.29.115.242",
dialect: "mysql",
logging: false,
define: {
charset: "utf8",
collate: "utf8_general_ci"
},
dialectOptions: {
dateStrings: true,
typeCast: true
},
timezone: "+08:00"
})
let Sensor = Tables.define("sensor", {
sn: {
type: DataTypes.STRING,
allowNull: false,
charset: "utf8"
},
dht: {
type: DataTypes.STRING,
charset: "utf8"
}
})
Sensor.sync({
alter: true
})
module.exports = {
Sensor
}
#include "conf.h"
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include "vkml.h"
#include "tasks.h"
#include <Ticker.h>
#include <DNSServer.h>
#include <WiFiUdp.h>
#include <Servo.h>
Servo servo;
VKML vkml;
WiFiUDP Udp;
char udpPacketBuffer[UDP_TX_PACKET_MAX_SIZE + 1];
DNSServer dnsServer;
Ticker ticker;
CONF conf;
WiFiClient wifiClient;
PubSubClient MQTT(wifiClient);
void (*resetFunc)(void) = 0;
void mqttCallback(char *topic, byte *payload, unsigned int length);
void connectWiFi();
void connectMQTT();
void udpServerLoop();
String ssid = conf.get("ssid"), pwd = conf.get("pwd"), sn = conf.get("sn"), sk = conf.get("sk");
TASKS fastLoopTasks;
TASKS slowLoopTasks;
bool slowLoopReady = false;
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println();
//检测是否被设置过
if (conf.get("status") == "") {
WiFi.mode(WIFI_AP_STA);
//没有配网,开启热点
Serial.print("Setting soft-AP ... ");
Serial.println(WiFi.softAP("rabbit-chameleon", "") ? "Ready" : "Failed!");
Serial.println("IP address: ");
Serial.println(WiFi.softAPIP());
//开启dns服务器
dnsServer.start(53, "rabbit.com", WiFi.softAPIP());
fastLoopTasks.add([]() { dnsServer.processNextRequest(); });
//开启udp
Udp.begin(8888);
fastLoopTasks.add([]() { udpServerLoop(); });
} else {
//已经配网连接wifi
connectWiFi();
//开启mqtt
connectMQTT();
fastLoopTasks.add([]() { MQTT.loop(); });
slowLoopTasks.add([]() {
//定时检测wifi连接状态
if (WiFi.status() != WL_CONNECTED) {
connectWiFi();
}
//定时检测mqtt连接状态
if (!MQTT.connected()) {
connectMQTT();
}
});
servo.attach(13);
}
// conf.set("tip","hello");
// Serial.println(conf.get("tip"));
pinMode(16, INPUT);
ticker.attach(1, []() {
slowLoopReady = true;
});
}
void loop() {
fastLoopTasks.run();
if (digitalRead(16) == LOW) {
conf.set("status", "");
delay(1000);
Serial.println("设备已重置!");
resetFunc();
}
if (slowLoopReady) {
//slowLoop
slowLoopTasks.run();
slowLoopReady = false;
}
}
void mqttCallback(char *topic, byte *payload, unsigned int length) {
char message[5] = {0x00};
for (int i = 0; i < length; i++)
message[i] = (char) payload[i];
message[length] = 0x00;
VKML data;
data.text = String(message);
String cmd = data.get("cmd");
Serial.println(data.text);
if (cmd == "reset") {
conf.set("status", "");
MQTT.publish(("from-" + sn + "-" + sk).c_str(), "设备已重置!");
delay(1000);
resetFunc();
} else if (cmd == "hello") {
MQTT.publish(("from-" + sn + "-" + sk).c_str(), "我在!");
} else if (cmd == "turn") {
int angle = data.get("angle").toInt();
servo.write(angle);
MQTT.publish(("from-" + sn + "-" + sk).c_str(), ("已转至" + String(angle) + "度!").c_str());
}
}
//void httpCallback() {
// conf.set("status", "already");
// conf.set("ssid", WebServer.arg("ssid"));
// conf.set("pwd", WebServer.arg("pwd"));
// conf.set("sn", WebServer.arg("sn"));
// conf.set("sk", WebServer.arg("sk"));
// WebServer.send(200, "text/plain", "ok");
// Serial.println(WebServer.arg("ssid"));
// Serial.println(WebServer.arg("pwd"));
// Serial.println(WebServer.arg("sn"));
// Serial.println(WebServer.arg("sk"));
// delay(1000);
// resetFunc();
//}
void connectWiFi() {
WiFi.mode(WIFI_STA);
WiFi.begin(ssid.c_str(), pwd.c_str());
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(F("."));
if (digitalRead(16) == LOW) {
conf.set("status", "");
delay(1000);
Serial.println("设备已重置!");
resetFunc();
}
}
Serial.println();
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
Serial.println("Way IP: ");
Serial.println(WiFi.gatewayIP().toString());
Serial.println(WiFi.hostname());
}
void connectMQTT() {
MQTT.setServer("119.29.115.242", 1883);
MQTT.setCallback(mqttCallback);
if (MQTT.connect((sn + "-" + sk).c_str(), NULL, NULL)) {
Serial.println("Connected to MQTT Broker");
} else {
Serial.println("MQTT Broker connection failed");
Serial.print(MQTT.state());
delay(200);
}
MQTT.publish(("from-" + sn + "-" + sk).c_str(), "我他妈来啦!");
MQTT.subscribe(("to-" + sn + "-" + sk).c_str());
}
void udpServerLoop() {
int packetSize = Udp.parsePacket();
if (packetSize) {
Serial.printf("Received packet of size %d from %s:%d\n (to %s:%d, free heap = %d B)\n",
packetSize,
Udp.remoteIP().toString().c_str(), Udp.remotePort(),
Udp.destinationIP().toString().c_str(), Udp.localPort(),
ESP.getFreeHeap());
// read the packet into udpPacketBuffer
int n = Udp.read(udpPacketBuffer, UDP_TX_PACKET_MAX_SIZE);
udpPacketBuffer[n] = 0;
Serial.println("Contents:");
Serial.println(udpPacketBuffer);
//验证是否为配置信息
vkml.text = udpPacketBuffer;
if (vkml.get("cmd") == "set") {
ssid = vkml.get("ssid"), pwd = vkml.get("pwd"), sn = vkml.get("sn"), sk = vkml.get("sk");
//回复ok
Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
Udp.write("201");
Udp.endPacket();
//打印信息
Serial.println(ssid);
Serial.println(pwd);
Serial.println(sn);
Serial.println(sk);
//尝试连接
Serial.println("正在尝试连接到WiFi");
WiFi.begin(ssid.c_str(), pwd.c_str());
int count = 0;
while (WiFi.status() != WL_CONNECTED) {
count++;
if (count > 25) {
Serial.println("连接失败!");
//回复403
Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
Udp.write("403");
Udp.endPacket();
return;
}
delay(500);
Serial.print(F("."));
if (digitalRead(16) == LOW) {
conf.set("status", "");
delay(1000);
Serial.println("设备已重置!");
resetFunc();
}
}
//配置成功回复200
Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
Udp.write("200");
Udp.endPacket();
conf.set("status", "already");
conf.set("ssid", ssid);
conf.set("pwd", pwd);
conf.set("sn", sn);
conf.set("sk", sk);
delay(1000);
resetFunc();
}
// send a reply, to the IP address and port that sent us the packet we received
}
}