IOT:基于oblog的应用

一、资料目录

  1. wiki地址
  2. 应用实例:
  3. easy IOT
  4. Azure IoT链接

二、相关项目

  1. 10分钟DIY一个物联网甲醛监测装置了!
  2. [基础教程]基于物联网平台的自动化农业控制系统
  3. 【OBLOQ-IOT物联网】初试智能家庭
  4. [高级教程]让小朋友们打造自己的手机APP,通过OBLOQ-IOT联网控制…

三、wiki内容整理

1. 技术规格

供电电压:3.3~5.0V
工作电流:<240mA
接口类型:Gravity UART 4PIN
接口速率:9600
无线模式:IEEE802.11b/g/n
加密类型:WPA WPA2/WPA2–PSK
无线频率:2.4GHz
产品尺寸:35mm * 32mm / 1.38inch * 1.26inch
内置协议:TCP/IP 协议栈

2. 引脚说明

OBLOQ引脚说明
引脚定义

标号名称功能描述
1TX串口发送端
2RX串口接收端
3GND
4VCC电源

3. EASY IOT教程

OBLOQ模块具备的两个基础功能:发送数据到物联网和接收物联网数据。下面通过实验演示这两个功能:

  • Arduino读取温度传感器LM35数据,通过OBLOQ模块发送温度数据到物联网设备。
  • 物联网设备发送数据,OBLOQ接收数据并发送给Arduino,Arduino再通过串口显示接收的数据。
  • 扩展程序,可实现更强大的功能,如:监听多个设备(一个OBLOQ最多监听5个物联网设备),发送多个传感器数据,远程控制继电器,小灯,风扇等等设备。

3.1 硬件准备

  • 1 x Arduino UNO控制板
  • 1 x 模拟LM35线性温度传感器
  • 1 x OBLOQ模块
  • 若干 连接线

3.2 软件

Arduino IDE (1.0.x或1.8.x), 点击下载Arduino IDE,下载完成后安装!
makecode库地址:https://github.com/DFRobot/pxt-ObloqV1

3.3 创建物联网设备

点击链接:访问EasyIOT,注册账号并登陆。
登录后,点击菜单栏的工作间,进入工作间后可点击“+”号创建物联网设备,程序中通过绑定设备的Topic来完成对特定设备的消息发送和接收。
下面演示创建一个设备Button:

  1. 进入菜单栏工作间
  2. 点击“+”号创建物联网设备,创建成功会出现一个新设备,第一次创建设备名为新设备1
  3. 将鼠标移动至设备名,会出现铅笔状小图标,点击铅笔小图标可修改设备名,修改为Button。
  4. 记录账号相关信息:Iot_id(user),Iot_pwd(password),Client ID和设备Topic,其中Iot_id和Iot_pwd可点击左侧状态栏的小眼睛图标查看。

3.4 硬件连接

OBLOQ模块的TX,RX,GND和VIN引脚分别连接到Arduino UNO的D10,D11,GND和VCC引脚,温度传感器LM35连接到A0引脚。可通过修改程序来自定义相关引脚,此次测试硬件连接参考下图:

在这里插入图片描述

3. 5 Arduino ide代码编程

3. 5.1 发送传感器数据

实现功能:Arduino读取温度传感器LM35数据,通过OBLOQ模块发送温度数据到物联网设备。修改代码中以下信息,然后烧录代码到Arduino UNO。

//you need change all these according to your own situations

#define WIFISSID "DFRobot-guest"                    //wifi账号
#define WIFIPWD  "dfrobot@2017"                     //wifi密码
#define SERVER   "iot.dfrobot.com.cn"               //Iot主机地址,此处不用更改
#define PORT     1883                               //Iot连接端口,此处不用更改
#define IOTID    "r1qHJFJ4Z"                        //iot_id,创建设备的时候记录的相关信息
#define IOTPWD   "SylqH1Y1VZ"                       //iot_pwd,创建设备的时候记录的相关信息
...
...
publish("Hy6z0Pb1G",(String)temperature); ; //向Hy6z0Pb1G设备发送温度数据
...
  1. 样例代码

/代码内容简介:每隔一段时间,向指定DF-IoT物联网设备发送消息,消息内容是此时读取的LM35温度数据/

//#include <Arduino.h>
#include <SoftwareSerial.h>
#include <Oblog.h>

#define WIFISSID "DFRobot-guest" 
#define WIFIPWD  "dfrobot@2017" 
#define SERVER   "iot.dfrobot.com.cn"
#define PORT     1883
#define IOTID    "r1qHJFJ4Z"
#define IOTPWD   "SylqH1Y1VZ"


const String separator = "|";
bool pingOn = true;
bool obloqConnectMqtt = false;
static unsigned long pingInterval = 2000;
static unsigned long sendMessageInterval = 10000;
unsigned long previousPingTime = 0;
unsigned long previousSendMessageTime = 0;

//wifi异常断开检测变量
bool wifiConnect = false;
bool wifiAbnormalDisconnect = false;

//mqtt因为网络断开后重新连接标志
bool mqttReconnectFlag = false;

SoftwareSerial softSerial(10,11);  //rx,tx

enum state{
    WAIT,
    PINGOK,
    WIFIOK,
    MQTTCONNECTOK
}obloqState;

/********************************************************************************************
Function    : sendMessage      
Description : 通过串口向OBLOQ发送一次消息
Params      : 无
Return      : 无 
********************************************************************************************/
void sendMessage(String message)
{
    softSerial.print(message+"\r"); 
}

/********************************************************************************************
Function    : ping      
Description : 通过串口向OBLOQ发送一次字符串"|1|1|",尝试与OBLOQ取得连接
Params      : 无
Return      : 无 
********************************************************************************************/
void ping()
{
    String pingMessage = "|1|1|";
    sendMessage(pingMessage);
}

/********************************************************************************************
Function    : connectWifi      
Description : 连接wifi   
Params      : ssid 连接wifi的ssid;pwd 连接wifi的password
Return      : 无 
********************************************************************************************/
void connectWifi(String ssid,String pwd)
{
    String wifiMessage = "|2|1|" + ssid + "," + pwd + separator;
    sendMessage(wifiMessage);
} 

/********************************************************************************************
Function    : connectMqtt      
Description : 连接DF-IoT    
Params      : server 物联网网址;port 端口;iotid 物联网登录后分配的iotid;iotpwd 物联网登录后分配的iotpwd
Return      : 无 
********************************************************************************************/
void connectMqtt(String server, String port, String iotid, String iotpwd)
{
    String mqttConnectMessage = "|4|1|1|" + server + separator + port + separator + iotid + separator + iotpwd + separator;
    sendMessage(mqttConnectMessage);
}


/********************************************************************************************
Function    : reconnectMqtt      
Description : 重新连接DF-IoT    
Params      : 无 
Return      : 无 
********************************************************************************************/
void reconnectMqtt()
{
    String mqttReconnectMessage = "|4|1|5|"; 
    sendMessage(mqttReconnectMessage);
}


/********************************************************************************************
Function    : publish      
Description : 向DF-IoT物联网设备发送信息    
Params      : topic DF-IoT物联网设备编号;message 发送的消息内容
Return      : 无 
********************************************************************************************/
void publish(String topic,String message)
{
    String publishMessage = "|4|1|3|" + topic + separator + message + separator;
    sendMessage(publishMessage);
}

/********************************************************************************************
Function    : handleUart      
Description : 处理串口传回的数据      
Params      : 无   
Return      : 无 
********************************************************************************************/
void handleUart()
{
    while(softSerial.available() > 0)
    {
        String receivedata = softSerial.readStringUntil('\r');
        const char* obloqMessage = receivedata.c_str();
        if (strcmp(obloqMessage, "|1|1|") == 0)
		{
			Serial.println("Pong");
			pingOn = false;
			obloqState = PINGOK;
		}
        if(strcmp(obloqMessage, "|2|1|") == 0)
        {
            if(wifiConnect)
            {
                wifiConnect = false;
                wifiAbnormalDisconnect = true;
            }
        }
		else if (strstr(obloqMessage,"|2|3|") != NULL && strlen(obloqMessage) != 9)
		{
			Serial.println("Wifi ready");
            wifiConnect = true;
            if(wifiAbnormalDisconnect)
            {
                wifiAbnormalDisconnect = false;
                return;
            }
			obloqState = WIFIOK;
		}
		else if (strcmp(obloqMessage, "|4|1|1|1|") == 0)
		{
			Serial.println("Mqtt ready");
            obloqConnectMqtt = true;
            if(mqttReconnectFlag)
            {
                mqttReconnectFlag = false;
                return;
            }
            obloqState = MQTTCONNECTOK;
		}
    }
}

/********************************************************************************************
Function    : sendPing      
Description : 每隔pingInterval一段时间,通过串口向OBLOQ ping一次      
Params      : 无   
Return      : 无 
********************************************************************************************/
void sendPing()
{
    if(pingOn && millis() - previousPingTime > pingInterval)
    {
        previousPingTime = millis();
        ping();
    }
}

/********************************************************************************************
Function    : execute      
Description : 根据OBLOQ的状态,进行下一步相应操作。      
Params      : 无
Return      : 无 
********************************************************************************************/
void execute()
{
    switch(obloqState)
    {
        case PINGOK: connectWifi(WIFISSID,WIFIPWD); obloqState = WAIT; break;
        case WIFIOK: connectMqtt(SERVER,String(PORT),IOTID,IOTPWD);obloqState = WAIT; break;
        case MQTTCONNECTOK : obloqState = WAIT; break;
        default: break;
    }
}

/********************************************************************************************
Function    : checkWifiState      
Description : 检查wifi状态,如果检测到wifi热点断开会间隔1分钟去重新连接wifi
Params      : 无
Return      : 无
********************************************************************************************/
void checkWifiState()
{
    static unsigned long previousTime = 0;
    static bool reconnectWifi = false;
    if(wifiAbnormalDisconnect && millis() - previousTime > 60000)
    {
        previousTime = millis();
        Serial.println("Wifi abnormal disconnect");
        reconnectWifi = true;
        obloqConnectMqtt = false;
        connectWifi(WIFISSID,WIFIPWD);
    }
    if(!wifiAbnormalDisconnect && reconnectWifi)
    {
        reconnectWifi = false;
        mqttReconnectFlag = true;
        Serial.println("Reconnect mqtt");
        reconnectMqtt();
    }

}

/********************************************************************************************
Function    : getTemp      
Description : 获得LM35测得的温度
Params      : 无
Return      : 无 
********************************************************************************************/
float getTemp()
{
    uint16_t val;
    float dat;
    val=analogRead(A0);//Connect LM35 on Analog 0
    dat = (float) val * (5/10.24);
    return dat;
}

void setup()
{
    Serial.begin(9600);
    softSerial.begin(9600);    
}

void loop()
{
    sendPing();
    execute();
    handleUart();
    checkWifiState();

    if(obloqConnectMqtt && millis() - previousSendMessageTime > 5000) //每隔5s,向Hy6z0Pb1G设备发送消息,消息内容是此时读取的LM35温度数据
    {
        previousSendMessageTime = millis();
        //获取温度数据
        float temperature = getTemp();
        Serial.println(temperature);
        publish("Hy6z0Pb1G",(String)temperature); 
        
    }
}
  1. 结果演示
    程序烧录成功后,复位OBLOQ模块,再复位Arduino。当没有连接wifi的时候,OBLOQ指示灯显示红色,正在连接wifi时显示蓝色,连接到wifi后,OBLOQ指示灯显示绿色。
    打开Arduino串口,观察上传到EASY IOT设备的数据。登录EASY IOT打开工作间,点击设备下方的查看详情可查看上传的温度数据。
LM35温度数据物联网端设备数据
在这里插入图片描述在这里插入图片描述
3.5.2 监听EASY IOT设备

实现功能:物联网设备发送数据,OBLOQ接收数据并发送给Arduino,Arduino再通过串口显示接收的数据。修改代码中以下信息,然后烧录代码到Arduino UNO。

//you need change all these according to your own situations

#define WIFISSID "DFRobot-guest"                    //wifi账号
#define WIFIPWD  "dfrobot@2017"                     //wifi密码
#define SERVER   "iot.dfrobot.com.cn"               //Iot主机地址,此处不用更改
#define PORT     1883                               //Iot连接端口,此处不同更改
#define IOTID    "r1qHJFJ4Z"                        //iot_id,创建设备的时候记录的相关信息
#define IOTPWD   "SylqH1Y1VZ"                       //iot_pwd,创建设备的时候记录的相关信息
...
...
subscribeSingleTopic("Hy6z0Pb1G");;                  //监控一个设备,设备号为"Hy6z0Pb1G"
...
  1. 样例代码
/*代码内容简介:在DF-IoT物联网监听设备号(topic)为Hy6z0Pb1G的物联网设备*/

//#include <Arduino.h>
#include <SoftwareSerial.h>
#include <Oblog.h>

#define WIFISSID "DFRobot-guest" 
#define WIFIPWD  "dfrobot@2017" 
#define SERVER   "iot.dfrobot.com.cn"
#define IOTID    "r1qHJFJ4Z"
#define IOTPWD   "SylqH1Y1VZ"
#define PORT     1883


const String separator = "|";
bool pingOn = true;
bool obloqConnectMqtt = false;
bool subscribeMqttTopic = false;
static unsigned long pingInterval = 2000;

static unsigned long sendMessageInterval = 10000;
unsigned long previousPingTime = 0;
bool subscribeSuccess = false;
String receiveStringIndex[10] = {};

//wifi异常断开检测变量
bool wifiConnect = false;
bool wifiAbnormalDisconnect = false;

//mqtt因为网络断开后重新连接标志
bool mqttReconnectFlag = false;


SoftwareSerial softSerial(10,11);

enum state{
    WAIT,
    PINGOK,
    WIFIOK,
    MQTTCONNECTOK
}obloqState;

/********************************************************************************************
Function    : sendMessage      
Description : 通过串口向OBLOQ发送一次消息
Params      : 无
Return      : 无 
********************************************************************************************/
void sendMessage(String message)
{
    softSerial.print(message+"\r"); 
}

/********************************************************************************************
Function    : ping      
Description : 通过串口向OBLOQ发送一次字符串"|1|1|",尝试与OBLOQ取得连接
Params      : 无
Return      : 无 
********************************************************************************************/
void ping()
{
    String pingMessage = "|1|1|";
    sendMessage(pingMessage);
}

/********************************************************************************************
Function    : connectWifi      
Description : 连接wifi   
Params      : ssid 连接wifi的ssid;pwd 连接wifi的password
Return      : 无 
********************************************************************************************/
void connectWifi(String ssid,String pwd)
{
    String wifiMessage = "|2|1|" + ssid + "," + pwd + separator;
    sendMessage(wifiMessage);
} 

/********************************************************************************************
Function    : connectMqtt      
Description : 连接DF-IoT    
Params      : server 物联网网址;port 端口;iotid 物联网登录后分配的iotid;iotpwd 物联网登录后分配的iotpwd
Return      : 无 
********************************************************************************************/
void connectMqtt(String server, String port, String iotid, String iotpwd)
{
    String mqttConnectMessage = "|4|1|1|" + server + separator + port + separator + iotid + separator + iotpwd + separator;
    sendMessage(mqttConnectMessage);
}

/********************************************************************************************
Function    : reconnectMqtt      
Description : 重新连接DF-IoT    
Params      : 无 
Return      : 无 
********************************************************************************************/
void reconnectMqtt()
{
    String mqttReconnectMessage = "|4|1|5|"; 
    sendMessage(mqttReconnectMessage);
}

/********************************************************************************************
Function    : publish      
Description : 向DF-IoT物联网设备发送信息    
Params      : topic DF-IoT物联网设备编号;message 发送的消息内容
Return      : 无 
********************************************************************************************/
void publish(String topic,String message)
{
    String publishMessage = "|4|1|3|" + topic + separator + message + separator;
    sendMessage(publishMessage);
}

/********************************************************************************************
Function    : subscribe      
Description : 订阅DF-IoT物联网设备     
Params      : topic DF-IoT物联网设备编号
Return      : 无 
********************************************************************************************/
void subscribe(String topic)
{
    String subscribeMessage = "|4|1|2|" + topic + separator;
    sendMessage(subscribeMessage);
}

/********************************************************************************************
Function    : splitString      
Description : 剔除分隔符,逐一提取字符串     
Params      : data[] 提取的字符串的目标储存地址;str 源字符串;delimiters 分隔符
Return      : 共提取的字符串的个数 
********************************************************************************************/
int splitString(String data[],String str,const char* delimiters)
{
  char *s = (char *)(str.c_str());
  int count = 0;
  data[count] = strtok(s, delimiters);
  while(data[count]){
    data[++count] = strtok(NULL, delimiters);
  }
  return count;
}

/********************************************************************************************
Function    : handleUart      
Description : 处理串口传回的数据      
Params      : 无   
Return      : 无 
********************************************************************************************/
void handleUart()
{
    while(softSerial.available() > 0)
    {
        String receivedata = softSerial.readStringUntil('\r');
        const char* obloqMessage = receivedata.c_str();
        // Serial.print("receivedata = ");
        // Serial.println(receivedata);
        if (strcmp(obloqMessage, "|1|1|") == 0)
		{
			Serial.println("Pong");
			pingOn = false;
			obloqState = PINGOK;
		}
        if(strcmp(obloqMessage, "|2|1|") == 0)
        {
            if(wifiConnect)
            {
                wifiConnect = false;
                wifiAbnormalDisconnect = true;
            }
        }
        else if (strstr(obloqMessage,"|2|3|") != NULL && strlen(obloqMessage) != 9)
		{
			Serial.println("Wifi ready");
            wifiConnect = true;
            if(wifiAbnormalDisconnect)
            {
                wifiAbnormalDisconnect = false;
                return;
            }
			obloqState = WIFIOK;
		}
		else if (strcmp(obloqMessage, "|4|1|1|1|") == 0)
		{
			Serial.println("Mqtt ready");
            obloqConnectMqtt = true;
            if(mqttReconnectFlag)
            {
                mqttReconnectFlag = false;
                return;
            }
            obloqState = MQTTCONNECTOK;
        }
        else if (strcmp(obloqMessage, "|4|1|2|1|") == 0)
		{
			Serial.println("subscribe successed");
            //subscribeMqttTopic = false;
        }
        //DF-IoT接收到消息,topic和message传入receiveMessageCallbak函数
        else if (strstr(obloqMessage, "|4|1|5|") != NULL)
        {
            splitString(receiveStringIndex,receivedata,"|");
            receiveMessageCallbak(receiveStringIndex[3],receiveStringIndex[4]);
        }

    }
}

/********************************************************************************************
Function    : sendPing      
Description : 每隔pingInterval一段时间,通过串口向OBLOQ ping一次      
Params      : 无   
Return      : 无 
********************************************************************************************/
void sendPing()
{
    if(pingOn && millis() - previousPingTime > pingInterval)
    {
        previousPingTime = millis();
        ping();
    }
}

/********************************************************************************************
Function    : execute      
Description : 根据OBLOQ的状态,进行下一步相应操作。      
Params      : 无
Return      : 无 
********************************************************************************************/
void execute()
{
    switch(obloqState)
    {
        case PINGOK: connectWifi(WIFISSID,WIFIPWD); obloqState = WAIT; break;
        case WIFIOK: connectMqtt(SERVER,String(PORT),IOTID,IOTPWD);obloqState = WAIT; break;
        case MQTTCONNECTOK :  obloqState = WAIT; break;
        default: break;
    }
}

/********************************************************************************************
Function    : subscribeSingleTopic      
Description : 监听单个DF-IoT物联网设备  
Params      : topic DF-IoT物联网设备编号
Return      : 无 
********************************************************************************************/
void subscribeSingleTopic(String topic)
{
    if(!subscribeMqttTopic && obloqConnectMqtt)
    {
        subscribeMqttTopic = true;
        subscribe(topic);
    }    
}

/********************************************************************************************
Function    : checkWifiState      
Description : 检查wifi状态
Params      : 无
Return      : 无 
********************************************************************************************/
void checkWifiState()
{
    static unsigned long previousTime = 0;
    static bool reconnectWifi = false;
    if(wifiAbnormalDisconnect && millis() - previousTime > 60000)
    {
        previousTime = millis();
        reconnectWifi = true;
        obloqConnectMqtt = false;
        Serial.println("Wifi abnormal disconnect");
        connectWifi(WIFISSID,WIFIPWD);
    }
    if(!wifiAbnormalDisconnect && reconnectWifi)
    {
        reconnectWifi = false;
        mqttReconnectFlag = true;
        Serial.println("Reconnect mqtt");
        reconnectMqtt();
    }
}

/********************************************************************************************
Function    : receiveMessageCallbak      
Description : 接收消息的回调函数  
Params      : topic 发出消息的DF-IoT物联网设备编号;message 收到的消息内容
Return      : 无 
********************************************************************************************/
void receiveMessageCallbak(String topic,String message)
{
    Serial.println("Message from: " + topic);
    Serial.println("Message content: " + message);
}


void setup()
{
    Serial.begin(9600);
    softSerial.begin(9600);    
}

void loop()
{
    sendPing();
    execute();
    subscribeSingleTopic("Hy6z0Pb1G");
    handleUart();
    checkWifiState();
}
  1. 结果演示
    程序烧录成功后,复位OBLOQ模块,再复位Arduino。当没有连接wifi的时候,OBLOQ指示灯显示红色,正在连接wifi时显示蓝色,连接到wifi后,OBLOQ指示灯显示绿色。
    登陆物联网,进入工作间,点击监控设备(Topic:Hy6z0Pb1G)下面的查看详情可发送消息到OBLOQ,通过Arduino串口可查看发送消息的设备和消息内容。
物联网端设备发送消息串口接收数据
在这里插入图片描述在这里插入图片描述

4. Azure IOT教程

OBLOQ模块具备的两个基础功能:发送数据到物联网和接收物联网数据。下面通过实验演示向Azure IOT设备发送数据的功能,更多样例见附件:

Arduino读取温度传感器LM35数据,通过OBLOQ模块发送温度数据到物联网设备。

4.1 硬件准备

1 x Arduino UNO控制板
1 x 模拟LM35线性温度传感器
1 x OBLOQ模块
若干 连接线

4.2 创建Azure IOT设备

4.3 硬件连接

OBLOQ模块的TX,RX,GND和VIN引脚分别连接到Arduino UNO的D10,D11,GND和VCC引脚,温度传感器LM35连接到A0引脚。可通过修改程序来自定义相关引脚,此次测试硬件连接参考下图:
在这里插入图片描述

发射和接收(无扩展板)

4.4 发送传感器数据

实现功能:Arduino读取温度传感器LM35数据,通过OBLOQ模块发送温度数据到Azure IOT设备。修改代码中以下信息,然后烧录代码到Arduino UNO.

//you need change all these according to your own situations


#define WIFISSID "DFRobot-guest" 
#define WIFIPWD  "dfrobot@2017" 

//Azure IOT 设备连接字符串,连接不同的设备需要修改这个字符串
const String connectionString = "HostName=dfrobot.azure-devices.cn;DeviceId=temperature;SharedAccessKey=CR5gUclNaT7skX9WP+e6oIB/BnkZnTIEReKBX870SNY=";
  1. 样例代码
//#include <Arduino.h>
#include <SoftwareSerial.h>
#include <Oblog.h>

#define WIFISSID "DFRobot-guest" 
#define WIFIPWD  "dfrobot@2017" 

//Azure IOT 设备连接字符串,连接不同的设备需要修改这个字符串
const String connectionString = "HostName=dfrobot.azure-devices.cn;DeviceId=temperature;SharedAccessKey=CR5gUclNaT7skX9WP+e6oIB/BnkZnTIEReKBX870SNY=";

const String separator = "|";
bool pingOn = true;
bool createIoTClientSuccess = false;
static unsigned long previoustGetTempTime = 0;
static unsigned long pingInterval = 2000;
static unsigned long sendMessageInterval = 10000;
unsigned long previousPingTime = 0;
String receiveStringIndex[10] = {};
bool wifiConnect = false;
bool wifiAbnormalDisconnect = false;

SoftwareSerial softSerial(10,11);

enum state{
    WAIT,
    PINGOK,
    WIFIOK,
    AZURECONNECT
}obloqState;

/********************************************************************************************
Function    : sendMessage
Description : 串口发送消息      
Params      : message 设备连接字符串   
Return      : 无 
********************************************************************************************/
void sendMessage(String message)
{
    softSerial.print(message+"\r"); 
}

/********************************************************************************************
Function    : ping      
Description : 检查串口是否正常通信,串口接收到敲门命令会返回:|1|1|\r
Return      : 无 
********************************************************************************************/
void ping()
{
    String pingMessage = F("|1|1|");
    sendMessage(pingMessage);
}

/********************************************************************************************
Function    : connectWifi 
Description : 连接wifi,连接成功串口返回:|2|3|ip|\r 
Params      : ssid  wifi账号 
Params      : pwd   wifi密码 
Return      : 无 
********************************************************************************************/
void connectWifi(String ssid,String pwd)
{
    String wifiMessage = "|2|1|" + ssid + "," + pwd + separator;
    sendMessage(wifiMessage);
} 

/********************************************************************************************
Function    : createIoTClient      
Description : 创建设备凭据,创建成功串口返回:|4|2|1|1|\r
Params      : connecttionString  设备连接字符串
Return      : 无 
********************************************************************************************/
void createIoTClient(String connecttionString)
{
    String azureConnectMessage = "|4|2|1|" + connecttionString + separator;
    sendMessage(azureConnectMessage);
}

/********************************************************************************************
Function    : subscribeDevice      
Description : 监听设备,接收到消息会返回消息内容,
Params      : 无 
Return      : 无 
********************************************************************************************/
void subscribeDevice()
{
    String subscribeDeviceMessage = "|4|2|2|";
    sendMessage(subscribeDeviceMessage);
}

/********************************************************************************************
Function    : unsubscribeDevice      
Description : 取消对设备的监听,发送成功串口返回:|4|2|6|1|\r      
Params      : 无 
Return      : 无 
********************************************************************************************/
void unsubscribeDevice()
{
    String unsubscribeDeviceMessage = "|4|2|6|";
    sendMessage(unsubscribeDeviceMessage);
}


/********************************************************************************************
Function    : publish
Description : 发送消息 ,必须先创建设备凭据
Params      : message 发布的消息内容,发送成功串口返回: |4|2|3|1|\r
Return      : 无 
********************************************************************************************/
void publish(String message)
{
    String publishMessage = "|4|2|3|" + message + separator;
    sendMessage(publishMessage);
}

/********************************************************************************************
Function    : disconnect 
Description : 销毁设备凭据: |4|2|4|1|\r
Params      : 无 
Return      : 无 
********************************************************************************************/
void distoryIotClient()
{
    String distoryIotClientMessage = "|4|2|4|";
    sendMessage(distoryIotClientMessage);
}

/********************************************************************************************
Function    : recreateIoTClient 
Description : 重新穿件设备凭据,创建成功返回: |4|2|1|1|\r
Params      : 无
Return      : 无 
********************************************************************************************/
void recreateIoTClient()
{
    String recreateIoTClientMessage = "|4|2|5|";
    sendMessage(recreateIoTClientMessage);
}

/********************************************************************************************
Function    : splitString 
Description : 切割字符串 
Params      : data 存储切割后的字符数组
Params      : str  被切割的字符串 
Params      : data 切割字符串的标志 
Return      : 无 
********************************************************************************************/
int splitString(String data[],String str,const char* delimiters)
{
  char *s = (char *)(str.c_str());
  int count = 0;
  data[count] = strtok(s, delimiters);
  while(data[count]){
    data[++count] = strtok(NULL, delimiters);
  }
  return count;
}

/********************************************************************************************
Function    : handleUart 
Description : 处理串口数据      
Params      : 无 
Return      : 无 
********************************************************************************************/
void handleUart()
{
    while(softSerial.available() > 0)
    {
        String receivedata = softSerial.readStringUntil('\r');
        const char* obloqMessage = receivedata.c_str();
        if(strcmp(obloqMessage, "|1|1|") == 0)
		{
			Serial.println("Pong");
			pingOn = false;
			obloqState = PINGOK;
		}
        if(strcmp(obloqMessage, "|2|1|") == 0)
        {
            if(wifiConnect)
            {
                wifiConnect = false;
                wifiAbnormalDisconnect = true;
            }
        }
		else if(strstr(obloqMessage, "|2|3|") != 0 && strlen(obloqMessage) != 9)
		{
			Serial.println("Wifi ready");
            wifiConnect = true;
            if(wifiAbnormalDisconnect)
            {
                wifiAbnormalDisconnect = false;
                createIoTClientSuccess = true;
                return; 
            }
			obloqState = WIFIOK;
		}
		else if(strcmp(obloqMessage, "|4|2|1|1|") == 0)
		{
			Serial.println("Azure ready");
            obloqState = AZURECONNECT;
		}
    }
}

/********************************************************************************************
Function    : sendPing
Description : 验证串口是否正常通信
Params      : 无 
Return      : 无 
********************************************************************************************/
void sendPing()
{
    if(pingOn && millis() - previousPingTime > pingInterval)
    {
        previousPingTime = millis();
        ping();
    }
}

/********************************************************************************************
Function    : execute 
Description : 根据不同的状态发送不同的命令      
Params      : 无 
Return      : 无 
********************************************************************************************/
void execute()
{
    switch(obloqState)
    {
        case PINGOK: connectWifi(WIFISSID,WIFIPWD); obloqState = WAIT; break;
        case WIFIOK: createIoTClient(connectionString);obloqState = WAIT; break;
        case AZURECONNECT : obloqState = WAIT; break;
        default: break;
    }
}

/********************************************************************************************
Function    : getTemp      
Description : 获得LM35测得的温度
Params      : 无
Return      : 无 
********************************************************************************************/
float getTemp()
{
    uint16_t val;
    float dat;
    val=analogRead(A0);//Connect LM35 on Analog 0
    dat = (float) val * (5/10.24);
    return dat;
}

/********************************************************************************************
Function    : checkWifiState 
Description : 接收消息的回调函数:      
Params      : message  接收到的消息字符串  
Return      : 无 
********************************************************************************************/
void checkWifiState()
{
    static unsigned long previousTime = 0;
    if(wifiAbnormalDisconnect && millis() - previousTime > 60000)  //wifi异常断开后一分钟重连一次
    {
        previousTime = millis();
        createIoTClientSuccess = false;
        connectWifi(WIFISSID,WIFIPWD);
    }
}

void setup()
{
    Serial.begin(9600);
    softSerial.begin(9600);    
}

void loop()
{
    sendPing();
    execute();
    handleUart();
    checkWifiState();
    //每隔5秒发送一次数据
    if(createIoTClientSuccess && millis() - previoustGetTempTime > 5000)
    {
        previoustGetTempTime = millis();

        //获取温度传感器数据
        float temperature = getTemp();
        publish((String)temperature);
        Serial.println(temperature);
    }
}
  1. 结果演示
    程序烧录成功后,复位OBLOQ模块,再复位Arduino。当没有连接wifi的时候,OBLOQ指示灯显示红色,正在连接wifi时显示蓝色,连接到wifi后,OBLOQ指示灯显示绿色。
    打开Arduino串口,观察上传到Azure IOT设备的数据,打开Device Explorer工具,监听发送消息的设备查看温度数据。
串口数据Device Explorer监听数据
在这里插入图片描述在这里插入图片描述

拓展

OBLOQ除了能连接标志的MQTT协议的物联网,还能连接Microsoft Azure IOT,更多样例代码可参考附件

常见问题
Q 1. 如何上传多个传感器数据?

A:
在物联网端建立多个设备,分别上传不同的数据。优点:可以直接通过网页端表格查看数据变化的波动情况。缺点:网页端需要创建的设备数量增多
将多个传感器数据组合一个字符串,发送到一个设备。优点:节省网页端创建的设备的数量,如果只是查看数据,建议使用这种方式。
Q 2. 如何监听多个传感器设备?
A: 监听设备需要时间,所以在前一个设备监听成功的情况下再去监听另外一个设备,以此内推,具体代码可参考附件,

Q 3. OBLOQ指示灯一直显示蓝色?
A: 表示OBLOQ正在连接wifi,需要一定时间,如果超过一分钟依然显示蓝灯,则可能为wifi账号密码设置错误,请检查程序

Q 4. OBLOQ指示灯一直显示紫色?

A: 表示OBLOQ的wifi连接成功但是mqtt异常断开,尝试检查所在wifi是否断网,也有可能easyiot服务器问题,等待一会儿再连接或联系论坛管理员。

Q 4. OBLOQ指示灯一直显示红色?

A: 表示OBLOQ的wifi连接不成功,尝试检查是否tx和rx接反了(调换一下tx和rx接线顺序),或者是wifi有问题(使用手机开热点,不要用中文WIFI名称),然后就是参数有没有填错(物联网网站里面的参数)。

五、附件

样例代码

六、利用库函数实现

oblog-库:https://github.com/DFRobot/Obloq

6.1 库中函数

//******************************************************MQTT API********************************************
    /** 
     * @brief 设置原始数据回调函数,当有错误发生时会调用设置的回调函数来返回错误信息
     * @param   handle:回调函数
     * @return:*/
    void setRawHandle(RawHandle handle);

    /** 
     * @brief   设置Iot设备接收消息回调函数,返回接收消息的tpoic和消息内容
     * @param   handle:回调函数
     * @return: 无
     */
    void setMsgHandle(MsgHandle handle);

    /** 
     * @brief   设置http返回消息回调函数
     * @param   handle:回调函数
     * @return: 无
     */
    void setHttpMsgHandle(HttpMsgHandle handle);

    /** 
     * @brief   获取OBLOQ连接Iot状态
     * @return: true:连接成功 ,false:连接失败
     */
    bool enable() const {return this->_enable;}

    /** 
     * @brief   获取wifi连接是否成功 
     * @return: true:wifi连接成功,wifi连接失败
     */
    bool isWifiConnected();

    /** 
     * @brief   获取设备IP,OBLOQ正常连接wifi后会获得一个特定的IP地址 
     * @return: 设备ip
     */
    String getIp() const {return this->_ip;}

    /** 
     * @brief  获取OBLOQ固件版本号
     * @return: 固件版本号,如果返回"xxx",表示版本号没有获取成功
     */
    String getFirmwareVersion() const {return this->_firmwareVersion;}

    /** 
     * @brief   循环检测OBLOQ当前状态和解析串口数据,需要放在Arduino loop()函数里面 
     * @return: 无
     */
    void update();
    
    /** 
     * @brief   监听Iot设备,实际上是记录监听的topic
     * @param   topic:监听设备的Topic
     * @return: 无
     */
    void subscribe(String topic);

    /** 
     * @brief   Iot设备发送消息
     * @param   topic:发送消息的设备Topic 
     * @param   message:发送的消息内容
     * @return: 无
     */
    void publish(const String& topic, const String& message);


    //******************************************************Http API********************************************
    /** 
     * @brief   Http get请求
     * @param   url : get请求的网址 
     * @return:*/
    void get(const String& url);

    /** 
     * @brief   Http post请求
     * @param   url: post请求的网址
     * @param   content: post的消息内容
     * @return: 无
     */
    void post(const String& url, const String& content);

6.2 示例

1. 单个设备的接收

#include "Arduino.h"
#include "SoftwareSerial.h"
#include "Obloq.h"

SoftwareSerial softSerial(10, 11);
//生成OBLOQ对象,参数:串口指针,wifiSsid,WifiPwd,iotId,iotPwd
Obloq olq(&softSerial, "DFRobot-guest", "dfrobot@2017", "SJG02MoBSf", "Sk7AnMsBrG");

//已监听设备的消息回调函数,可以在这个函数里面对接收的消息做判断和相应处理,需要用setMsgHandle()来设置这个回掉函数
void msgHandle(const String& topic, const String& message)
{
  Serial.println("Topic : " + topic + " , " + "Message : " + message);
}

void setup()
{
  Serial.begin(115200);
  softSerial.begin(9600);
  olq.setMsgHandle(msgHandle);//注册消息回掉函数
  olq.subscribe("S1TOmpqUG"); //监听设备,设备Topic:S1TOmpqUG
}
void loop()
{
  olq.update();
}

6.2 多个设备的接收

#include "Arduino.h"
#include "SoftwareSerial.h"
#include "Obloq.h"

SoftwareSerial softSerial(10, 11);
//生成OBLOQ对象,参数:串口指针,wifiSsid,WifiPwd,iotId,iotPwd
Obloq olq(&softSerial, "DFRobot-guest", "dfrobot@2017", "SJG02MoBSf", "Sk7AnMsBrG");

//设备的消息回调函数,监听的设备检测到消息会调用这个函数,可以在这个函数里面对接收的消息做判断和相应处理,需要用setMsgHandle()来设置这个回掉函数
void msgHandle(const String& topic, const String& message)
{
  Serial.println("Topic : " + topic + " , " + "Message : " + message);
}

void setup()
{
  Serial.begin(115200);
  softSerial.begin(9600);
  olq.setMsgHandle(msgHandle);//注册消息回掉函数
  olq.subscribe("H15OXaqUG"); //监听多个设备
  olq.subscribe("HkoO7acIM");
  olq.subscribe("S1TOmpqUG");
  olq.subscribe("B1-t76c8f");
  olq.subscribe("r1GKmT9UG");
}
void loop()
{
  olq.update();
}

6.3 智能灯

#include <SoftwareSerial.h>
#include "Obloq.h"

SoftwareSerial softSerial(10,11);
//生成OBLOQ对象,参数:串口指针,wifiSsid,WifiPwd,iotId,iotPwd
Obloq olq(&softSerial,"DFRobot-guest","dfrobot@2017","SJG02MoBSf","Sk7AnMsBrG");
const String devTopic = "HkfVZ9BBz";
 //led小灯引脚
int ledPin = 2;

//已监听设备的消息回调函数,可以在这个函数里面对接收的消息做判断和相应处理,需要用setMsgHandle()来设置这个回调函数
void msgHandle(const String& topic,const String& message)
{
    if(devTopic == topic)
    {
        if(message == "0")
          digitalWrite(ledPin,LOW);
        else if(message == "1")
          digitalWrite(ledPin,HIGH);
    }
}

void setup()
{
    pinMode(ledPin,OUTPUT);
    softSerial.begin(9600);
    olq.setMsgHandle(msgHandle);//注册消息回掉函数
    olq.subscribe(devTopic); //监听设备

}
void loop()
{
    olq.update();
}

6.4 按钮

#include <SoftwareSerial.h>
#include "Obloq.h"
#include "Button.h"

Button button;
SoftwareSerial softSerial(10, 11);
//生成OBLOQ对象,参数:串口指针,wifiSsid,WifiPwd,iotId,iotPwd
Obloq olq(&softSerial, "DFRobot-guest", "dfrobot@2017", "SJG02MoBSf", "Sk7AnMsBrG");
//Iot设备Topic:HkfVZ9BBz
const String devTopic = "HkfVZ9BBz";
String buttonMessage = "";

void setup()
{
  button.init(2);
  softSerial.begin(9600);
}

void loop()
{
  olq.update();
  button.update();
  if (button.click())
  {
    olq.publish(devTopic, buttonMessage); //向Iot设备发送消息
    if (buttonMessage == "1")
      buttonMessage = "0";
    else
      buttonMessage = "1";
  }
}
在使用系统前,请一定要设置好conn.asp及config.asp文件中的以下参数: 1、blog程序所在路径选项\nconstblogdir='/' blog程序所在目录,非常重要,默认为根目录,如为网站的blog目录,请改\u4e3aconstblogdir='/blog/' 2、生成用户日志页面的文件后缀 constf_ext='html' 生成的日志静态文件后缀,可以为htm,html,shtml,asp四种格式,默认为html文件格式,若为生成htm文件,请改为constf_ext='htm' 如果您是原来oBlog用户,请阅读升级目录信息。 如果您是第一次使用oBlog,在确认您同意oBlog版权声明后请详细阅读以下说明文档。 1、下载oBlog oBlog每次发布最新版本,都会第一时间公布于http://www.oBlog.cn,请密切关注网站的最新情况。 2、解压oBlog 将下载回的oBlog解压到指定的目录 3、安装oBlog 1)在本地安装论坛执行本操作前请确认您拥有安装要求中所需要的环境,在确认您有运行论坛的环境后,您需要做以下工作: 将解压后的文件拷贝到本地WEB目录中,IIS或者PWS默认Web目录为C:\inetpub\wwwroot,比如您可以装到C:\inetpub\wwwroot\oblog目录下 然后敲入本地测试网址访问,默认为:http://localhost/或者http://ip/,比如您装到C:\inetpub\wwwroot\oblog目录下,那么就可以用http://localhost/oblog/index.asp进行访问 2)在服务器或者虚拟空间进行安装 如果有服务器的直接操作权限,那么您可以使用类似本地安装的方法进行安装 如果您是虚拟空间,那么您可以使用FTP软件将论坛文件上传到网站目录,比如您将论坛文件传到空间中的blog目录,那么您就可以使用http://www.xxx.com/blog/index.asp来进行浏览 4、仔细阅读http://www.oBlog.cn网站关于安装的说明,并按步骤进行操作,重要! 5、后台登陆地址为安装目录下的admin_login.asp,用默认超级管理员(用户名:admin,密码:admin888)登录,进入管理页面完成站点的设置;为了保障系统的安全性,进入后台超级管理后最好在管理员管理中重新设置管理员信息。(前台管理员应在后台用户管理中给予权限) 6、完成了以上步骤后,就可以正常使用oBlog了;为了保障系统的稳定和安全性,请您在安装结束后,一定要详细阅读帮助文档中的数据库安全文档 7、有何问题可以到http://bbs.oBlog.cn的oBlog专区提出,对共享版本谢绝电话来访和在线支持。 数据库安装说明: 1、将您blog网站数据库下载回本地(默认为oblog4.mdb)。 2、将您的论坛数据库命名为.asp后缀,如oblog4.asp, 建议将文件名更改为更复杂的名称,如w34blog33-oblog4.asp 接着修改conn.asp文件中的数据库连接地址,改好后将文件上传即可正常使用。 以后如果想对数据库进行修改,只需要将数据库重新命名后缀为.mdb的就可以用了。
同步更新官方最新版 oBlog多用户博客程序是目前国内应用最广泛的博客程序。OBLOG程序已经广泛应用在国内数万家网站,覆盖国内上千万上网人群,并经过上千家知名网站的严格检测,被称为国内博客建站第一程序oBlog多用户博客程序”是目前国内应用最广泛的博客程序。OBLOG程序已经广泛应用在国内数万家网站,覆盖国内上千万上网人群,并经过上千家知名网站的严格检测,被称为国内博客建站第一程序oBlog多用户博客程序”是目前国内应用最广泛的博客程序。OBLOG程序已经广泛应用在国内数万家网站,覆盖国内上千万上网人群,并经过上千家知名网站的严格检测,被称为国内博客建站第一程序oBlog多用户博客程序”是目前国内应用最广泛的博客程序。OBLOG程序已经广泛应用在国内数万家网站,覆盖国内上千万上网人群,并经过上千家知名网站的严格检测,被称为国内博客建站第一程序。   更新时间20090610       01、解决在圈子发布日志的用户被删除后圈子日志没法管理的问题;       02、解决留言审核后没有自动更新的问题;       03、解决用户后台修改二级域名,没有经过关键字过滤的问题;       04、解决删除用户的时候没有删除该用户的友情链接问题;       05、解决用户日志评论里编辑器参数问题;       06、解决digg查询的一个错误;       07、解决因oblog官方换域名引起的问题;       08、解决用户发布相片不强制选择系统分类的问题;       09、解决系统统计标签对评论的统计不准确的问题;       10、解决show_hottag标签第二个参数把锁定tag算在内的问题;       11、解决访问私密圈子提示不友好的问题;       12、解决不支持火狐上传文件的问题;       13、解决删除用户该用户发表的评论没有删除的问题;       14、解决js调用不支持虚拟目录的问题;       15、解决了一处安全问题。 本版本修改了系统后台网站信息配置中“留言与回复是否默认通过审核”的选项,默认选择“否”,同时去掉了用户后台设置中对“留言与回复控制”的选项。 演示网站:http://oblog.demo.aobosoft.com   更新时间:2009年06月23日 这个版本解决了OBLOG4.6 081029版本中存在的问题,以下为修改说明:
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值