php与硬件通过wifi对接,基于ESP8266的WiFi排插接入贝壳互联实现天猫精灵控制

认识众多玩家高手/拆客/DIYer,查阅更多资源,一起学习技术知识

您需要 登录 才可以下载或查看,没有帐号?立即注册

8baaf04eb249b4474178b0078f482447.gif

9ca0cb046ba12e9f7d6500eeea1c766b.png

x

本帖最后由 hzy3774 于 2020-1-8 00:45 编辑

* 实验的对象是一个基于ESP8266的WiFi排插,目标是通过Arduino编程实现天猫精灵语音控制排插每个插孔的通断电功能。* 编写程序主要需关心的硬件配置是:ESP-12模块x1,轻触按键x1,220V插口x4,USB接口x2,Wifi信号LEDx1,电源LEDx1

* 实物如图

DSC04258.JPG (88.44 KB, 下载次数: 0)

2020-1-7 22:54 上传

* 先来看看最终效果吧,一看就明白怎么回事了。点击观看视频

* 模块与IO连接如图:

微信图片编辑_20200107233554.jpg (35.75 KB, 下载次数: 0)

2020-1-7 23:37 上传

* 下面开始写程序,首先是使用WifiManager库配网:

// 设置Wifi

WiFiManager wifiManager;

wifiManager.autoConnect();复制代码

* 之后是来初始化中断,因为插板上有一个按钮,使用中断来处理按钮事件,处理的逻辑是:如果插座全关的情况下按下按钮,则变为全开,否则就变为全关。

// 中断响应

ICACHE_RAM_ATTR void onKeyClick() {

// 全关的状态全部打开,否则都是全关闭

if ((portStatus & 0B1111000) == 0B1111000) {

portStatus &= 0B0000111;

} else {

portStatus |= 0B1111000;

}

refreshOutput();

}

void initPanelKey() {

attachInterrupt(digitalPinToInterrupt(5), onKeyClick, FALLING);

}复制代码

* 我们使用了一个变量portStatus来表示用到的所有插孔和LED的开关状态,这样我们只要修改portStatus,再调用refreshOutput()就可以改变所有输出IO状态:

//7个端口分别对应 K1, K2, K3, K4,USB,LED_WIFI, LED_ROUND

char swPorts[portNum] = {14, 12, 13, 4, 16, 0, 3};

//除了USB充电口,其他都是低电平有效

int portStatus = 0B0000110; //7个IO开关

//======================================

// 初始化插板

void initOutputMode() {

for (int i = 0; i < portNum; i++) {

pinMode(swPorts[i], OUTPUT);

}

}

// 根据开关状态刷新IO电平

void refreshOutput() {

int c = 1;

for (int i = portNum - 1; i >= 0; i--) {

digitalWrite(swPorts[i], (c & portStatus) ? HIGH : LOW);

c <<= 1;

}

}复制代码

* 有了中断,也可以修改IO输出状态,下面就是对接贝壳互联平台。

* 对接详情可以参考我的另一片帖子:ESP8266基于Arduino接入贝壳物联,使用天猫精灵控制WS2812B灯带

* 但是与其他单设备不同,我们一个设备上有4个开关,就会麻烦一点,我的做法是使用子设备:

* 先添加一个设备,设备的类型必须要选择万能遥控器,万能遥控器的子设备才会生效:

微信截图_20200108000733.png (50.39 KB, 下载次数: 0)

2020-1-8 00:09 上传

* 之后在子设备栏里添加4个子设备,当然,子设备的数量取决于主设备有多少路控制IO,这些子设备的ID会在之后编程中用到:

微信截图_20200108001109.png (52.23 KB, 下载次数: 0)

2020-1-8 00:11 上传

* 然后我们在手机天猫精灵APP里绑定账号之后,设备里一下子就会多出来4个设备:

* 在天猫精灵里可以给这些子设备设置不同的类型,冰箱,电视,空调啊,可以随意设置,不过设置了什么类型,到时候和天猫精灵语音控制的时候就要说对应的设备类型,比如:“天猫精灵,打开空调”

* 但是如果我想4路开关一起控制,那我就说“天猫精灵,打开万能遥控器”即可。

设置完成后,我们来继续写云平台相关代码:

* 一样的套路,在loop循环中,主要做两件事,定期向服务端发送心跳包,每个循环中收一下消息,再处理一下消息。

void loop() {

// 检测网络是否通畅

while (WiFi.status() != WL_CONNECTED) {

delay(1000);

Serial.print(".");

}

// 检测是否连接到服务器

if (!client.connected()) {

if (!client.connect(host, httpPort)) {

Serial.println("connection failed");

delay(5000);

return;

}

}

// 检测是否需要发送心跳包

if (millis() - lastCheckInTime > postingInterval || lastCheckInTime == 0) {

Serial.println("Send HeartBeat!!");

sendHeartBeat();

}

// 检测是否收到服务器推送

if (client.available()) {

String inputString = client.readStringUntil('\n');

onMessageReceive(inputString);

}

}复制代码

* 发送心跳包的代码:

void sendHeartBeat() {

String msg = "{"M":"checkin","ID":"" + DEVICEID + "","K":"" + APIKEY + ""}\n";

client.print(msg);

lastCheckInTime = millis();

}复制代码

* 处理推送消息的代码:

void onMessageReceive(String msg) {

msg.trim();

Serial.println(msg);

if (msg.startsWith("{") && msg.endsWith("}")) {

DynamicJsonDocument doc(1024);

deserializeJson(doc, msg);

JsonObject obj = doc.as();

String M = obj["M"];

if (M == "say") {

String S = obj["S"];

String C = obj["C"];

int device = 0B1111000;

if (S == "D1160") {

device = 0B1000000;

} else if (S == "D1161") {

device = 0B0100000;

} else if (S == "D1162") {

device = 0B0010000;

} else if (S == "D1163") {

device = 0B0001000;

}

if (C == "play") {

portStatus &= ~device;

} else if (C == "stop") {

portStatus |= device;

}

refreshOutput();

} else if (M == "checkinok") {

portStatus &= 0B1111101;

refreshOutput();

}

}

}复制代码

解释一下消息处理部分的代码:我目前只处理了say和checkinok的消息。

* checkinok消息:由于刚起机连上网的时候,设备并不能马上连接上推送服务,一般要等待几十秒到数分钟才能链接完成,连接成功后云平台会发送checkinok消息,所以收到checkinok消息时,我们把WIFI_LED点亮,表示设备联网成功了。

* say消息:表示设备需要响应命令,两个参数比较重要:C和S,

S表示子设备的id,通过S便可以知道需要操作哪个子设备(为空的话表示操作所有设备)

C表示动作,play表示打开设备,stop表示关闭设备。

当然这些都是我根据串口打印消息内容猜测的,具体情况还要参考天猫精灵和贝壳互联的说明才比较准确。

完整的代码如下,需对应修改DEVICE ID和API KEY:

#include

#include

#include

//=============  此处必须修该============

String DEVICEID = "00000"; // 你的设备编号   ==

String  APIKEY = "000000000"; // 设备密码==

unsigned long lastCheckInTime = 0; //记录上次报到时间

const unsigned long postingInterval = 40000; // 每隔40秒向服务器报到一次

const char* host = "www.bigiot.net";

const int httpPort = 8181;

WiFiClient client;

//======插座控制端口=======

const int portNum = 7;

//7个端口分别对应 K1, K2, K3, K4,USB,LED_WIFI, LED_ROUND

char swPorts[portNum] = {14, 12, 13, 4, 16, 0, 3};

//除了USB充电口,其他都是低电平有效

int portStatus = 0B0000110; //7个IO开关

//======================================

// 初始化插板

void initOutputMode() {

for (int i = 0; i < portNum; i++) {

pinMode(swPorts[i], OUTPUT);

}

}

// 根据开关状态刷新IO电平

void refreshOutput() {

int c = 1;

for (int i = portNum - 1; i >= 0; i--) {

digitalWrite(swPorts[i], (c & portStatus) ? HIGH : LOW);

c <<= 1;

}

}

// 中断响应

ICACHE_RAM_ATTR void onKeyClick() {

// 全关的状态全部打开,否则都是全关闭

if ((portStatus & 0B1111000) == 0B1111000) {

portStatus &= 0B0000111;

} else {

portStatus |= 0B1111000;

}

refreshOutput();

}

void initPanelKey() {

attachInterrupt(digitalPinToInterrupt(5), onKeyClick, FALLING);

}

void setup() {

// 设置串口

Serial.begin(115200);

//初始化输出端口

initOutputMode();

refreshOutput();

//初始化按键中断

initPanelKey();

// 设置Wifi

WiFiManager wifiManager;

wifiManager.autoConnect();

}

void loop() {

// 检测网络是否通畅

while (WiFi.status() != WL_CONNECTED) {

delay(1000);

Serial.print(".");

}

// 检测是否连接到服务器

if (!client.connected()) {

if (!client.connect(host, httpPort)) {

Serial.println("connection failed");

delay(5000);

return;

}

}

// 检测是否需要发送心跳包

if (millis() - lastCheckInTime > postingInterval || lastCheckInTime == 0) {

Serial.println("Send HeartBeat!!");

sendHeartBeat();

}

// 检测是否收到服务器推送

if (client.available()) {

String inputString = client.readStringUntil('\n');

onMessageReceive(inputString);

}

}

void onMessageReceive(String msg) {

msg.trim();

Serial.println(msg);

if (msg.startsWith("{") && msg.endsWith("}")) {

DynamicJsonDocument doc(1024);

deserializeJson(doc, msg);

JsonObject obj = doc.as();

String M = obj["M"];

if (M == "say") {

String S = obj["S"];

String C = obj["C"];

int device = 0B1111000;

if (S == "D1160") {

device = 0B1000000;

} else if (S == "D1161") {

device = 0B0100000;

} else if (S == "D1162") {

device = 0B0010000;

} else if (S == "D1163") {

device = 0B0001000;

}

if (C == "play") {

portStatus &= ~device;

} else if (C == "stop") {

portStatus |= device;

}

refreshOutput();

} else if (M == "checkinok") {

portStatus &= 0B1111101;

refreshOutput();

}

}

}

void sendHeartBeat() {

String msg = "{"M":"checkin","ID":"" + DEVICEID + "","K":"" + APIKEY + ""}\n";

client.print(msg);

lastCheckInTime = millis();

}复制代码

基于ESP8266的WiFi排插拆机加装USB调试板,改造成Arduino开发板结束

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值