博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Qt智能家居应用开发:硬件设备实现智能网络配置时候,如何使用第三方smart config 库...
阅读量:7006 次
发布时间:2019-06-27

本文共 12474 字,大约阅读时间需要 41 分钟。

背景

阅读前预备知识:

  • 学习安晓辉老师的qt for android 核心编程(了解怎么在Qt 里边c++ 调用java,java库怎么加进qt工程中)

现在做智能硬件设备,都是使用模块化的流行wifi芯片来接入云端,实现实时通讯和数据交互的工作.以前使用wifi芯片我们经常会遇到一个问题:在wifi设备初始化过程中,我们要手动从ap模式配置连接路由器,这个操作流程对于我们开发人员来说看起来很简单,当换路由器的时候,按复位键然后手动配置就好了.甚至现在我看到许多这样的产品比如网络摄像头,一些远程控制设备都是这个模式.甚至我在学校工作室的时候老师买了一套智能家居设备,我们要看着一本说明书按着流程来手动配置网络.也就是现在大部分智能设备还是存在这个问题(其实已经有解决方案了,也许开发商还没有留意到现在流行的智能网络配置功能,这个有没缺点漏洞我不知道,毕竟我也是新手,只用这个技术做过简单的智能家居系统).

wifi设备实现网络配置方式之间差异

比起传统的ap模式网页配置wif芯片网络或者串口配置网络,smartconfig是一种新型的智能网络配置功能,操作起来更智能方便,时物联网芯片产品的一大趋向。

区别:

ap模式下的网页形式配置

ap (所谓ap模式就是把wifi芯片启动成像路由器一样,可以让其他wifi终端连接到这个wifi芯片)模式下的网页形式是通过wifi终端手动搜索wifi芯片开的ap服务,然后连接该wifi芯片。接着在wifi终端打开浏览器,访问wifi芯片的地址(比如: ),由于wifi芯片本来支持ap模式,它已经是一个简单的网站服务,通过这网页去获取权限设置wifi芯片提供的设置项服务,比如重启连接到路由器等等。

串口配置

大部分wifi芯片都支持串口命令控制wifi芯片的所有功能。这时候就需要通过串口命令区控制wifi芯片了。

smartconfig

smartconfig 是一个面向软件开发者的智能网络配置功能。硬件开发商无需关系自己的wifi芯片怎么连接到路由器,也无需知道动态的路由怎么被切换。因为smartconfig时通过终端软件去让wifi芯片连接到路由器的。具体实现原理参考:智能硬件接入云平台解决方案


微信硬件平台里边有一个叫做airkiss 技术,下面的两个产品都支持这个技术,对于实现智能网络配置功能,它是一个相对完美的平台和方案.详细的学习请自行进平台官网看文档.


hi-fly和esp系列芯片看起来大同小异,知识esp8266芯片实现智能网络配置比较麻烦,它里边只有实现源码,并没有封装成java库来使用,hi-fly产品就产商提供了一个java库,后边着重介绍怎么在qt里边使用这个库.

wifi芯片学习:

如果有官方评估版可以完全参考HF-LPT220wifi模块评估版使用指南学习搭建完整的调试环境,如果没有的话请参考HF-LPT220wifi模块用户手册这份文档做一个调试板子。

clipboard.png

这个板子是自己做的,使用的时HF-LPT220芯片。电路设计按情况,留出串口和复位键,就可以当作官方评估版使用了。

前期硬件开发要了解wifi芯片的操作:

  • 监听wifi芯片串口传来的数据

  • 了解透传模式

  • 了解串口数据传输和wifi串口控制命令。

软件实现smartconfig

就拿来作分析:

clipboard.png

我们在创建qt android项目的时候要把hi-flying 提供的hiflying-iots-android-smartlink7.0.2.jar 拷贝到android/libs目录下

然后写给c++调用的java接口类:

SmartLinkManager.java

package com.tommego;//hifly smart link libsimport com.hiflying.smartlink.ISmartLinker;import com.hiflying.smartlink.OnSmartLinkListener;import com.hiflying.smartlink.SmartLinkedModule;import com.hiflying.smartlink.v3.SnifferSmartLinker;import com.hiflying.smartlink.v7.MulticastSmartLinker;import android.net.ConnectivityManager;import android.net.NetworkInfo;import android.net.wifi.WifiInfo;import android.net.wifi.WifiManager;import android.os.Bundle;import android.os.Handler;import android.app.Activity;import android.app.ProgressDialog;import android.content.BroadcastReceiver;import android.content.Context;import android.content.DialogInterface;import android.content.DialogInterface.OnDismissListener;import android.content.Intent;import android.content.IntentFilter;import android.util.Log;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;import android.widget.Toast;//屏幕像素密度import android.util.DisplayMetrics;public class SmartLinkManager extends org.qtproject.qt5.android.bindings.QtActivity implements OnSmartLinkListener{    private static SmartLinkManager m_instance;    //smart link    protected static ISmartLinker mSnifferSmartLinker;    private static boolean  mIsConncting = false;    protected static Handler mViewHandler = new Handler();//    protected static ProgressDialog mWaitingDialog;    private static BroadcastReceiver mWifiChangedReceiver;    private static String mSSID;    public SmartLinkManager(){        m_instance = this;        //smart linker initialization        mSnifferSmartLinker = MulticastSmartLinker.getInstance();    }    public static void startSmartLink(String ssid,String pwd){        // TODO Auto-generated method stub        if(!mIsConncting){                //设置要配置的ssid 和pswd                try {                        mViewHandler.post(new Runnable() {                            @Override                            public void run() {                                    // TODO Auto-generated method stub                                    Toast.makeText(m_instance.getApplicationContext(), "正在后台配置wifi,请稍后",                                                    Toast.LENGTH_LONG).show();                            }                        });                        mSnifferSmartLinker.setOnSmartLinkListener(m_instance);//                        showDialog();                        //开始 smartLink                        mSnifferSmartLinker.start(m_instance.getApplicationContext(), pwd.trim(),                                        ssid.trim());                        mIsConncting = true;//                        mWaitingDialog.show();                } catch (Exception e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                }        }    }    public static void stopSmartLink(){        mSnifferSmartLinker.stop();        mIsConncting = false;//        closeDialog();    }    public static String getSSID(){        WifiManager conMan = (WifiManager) m_instance.getSystemService(Context.WIFI_SERVICE);        return conMan.getConnectionInfo().getSSID();    }    @Override    public void onLinked(final SmartLinkedModule module) {            // TODO Auto-generated method stub//            Log.w(TAG, "onLinked");            mViewHandler.post(new Runnable() {                    @Override                    public void run() {                            Toast.makeText(m_instance.getApplicationContext(), "发现新wifi模块"+                             "\n mac:"+module.getMac()+ "\n ip:"+module.getModuleIP(),                                            Toast.LENGTH_SHORT).show();                    }            });    }    @Override    public void onCompleted() {//            Log.w(TAG, "onCompleted");            mViewHandler.post(new Runnable() {                    @Override                    public void run() {                            // TODO Auto-generated method stub                            Toast.makeText(m_instance.getApplicationContext(), "智能配置完成!",                                            Toast.LENGTH_SHORT).show();//                            mWaitingDialog.dismiss();                            mIsConncting = false;//                            closeDialog();                    }            });    }    @Override    public void onTimeOut() {//            Log.w(TAG, "onTimeOut");            mViewHandler.post(new Runnable() {                    @Override                    public void run() {                            // TODO Auto-generated method stub                            Toast.makeText(m_instance.getApplicationContext(), "配置超时!",                                            Toast.LENGTH_SHORT).show();//                            mWaitingDialog.dismiss();                            mIsConncting = false;                    }            });    }    //获取屏幕像素密度    public static double getDentisy(){        DisplayMetrics metrics=new DisplayMetrics();        m_instance.getWindowManager().getDefaultDisplay().getMetrics(metrics);        return metrics.density;    }//    public static native void showDialog();//    public static native void closeDialog();}

然后c++ 就可以调度这个库了:

wifidevicemanager.h

#ifndef WIFIDEVICEMANAGER_H#define WIFIDEVICEMANAGER_H#include 
#include
#include
#include
#include
#include
#include
#include
#include
struct WifiDevice{ QString ip,mac;};class WifiDeviceManager : public QObject{ Q_OBJECTpublic: explicit WifiDeviceManager(QObject *parent = 0); //device list Q_PROPERTY(QString deviceList READ deviceList NOTIFY deviceListChanged) QString deviceList(); Q_PROPERTY(QString revDatas READ revDatas NOTIFY revDatasChanged) QString revDatas(); Q_PROPERTY(QString revTcpDatas READ revTcpDatas NOTIFY revTcpDatasChanged) QString revTcpDatas(); //tcp socket properties Q_PROPERTY(QString tcpState READ tcpState NOTIFY tcpStateChanged) QString tcpState(); //tcp con Q_INVOKABLE void connectTcp(QString ip); Q_INVOKABLE void sendDatasTcp(QString data); //smart config Q_INVOKABLE void startSmartLink(QString SSID,QString pwd); Q_PROPERTY(QString ssID READ ssID NOTIFY ssIDChanged) QString ssID(){ return mssid; } //send udp datas Q_INVOKABLE void searchDevice(); //send datas Q_INVOKABLE void sendDatas(QString datas); Q_INVOKABLE void sendDatas(QString datas,int port); Q_INVOKABLE void setDAddress(QString ad){ this->dAddress=ad; }signals: void deviceListChanged(); void ssIDChanged(); void revDatasChanged(); void tcpStateChanged(); void revTcpDatasChanged();public slots: void readDatas(); void readTcpDatas();private: QString myAddress; QList
mdeviceList; QUdpSocket *socket; QTcpSocket *tcpSocket; int port; QString mssid; QString mrevDatas; QString mRevTcpDatas; QString dAddress; QString m_tcpState;};#endif // WIFIDEVICEMANAGER_H

wifidevicemanager.cpp

#include "wifidevicemanager.h"WifiDeviceManager::WifiDeviceManager(QObject *parent) : QObject(parent){    //init socket    port=48899;    socket=new QUdpSocket(this);    socket->bind(QHostAddress::Broadcast,port);    tcpSocket=new QTcpSocket();    tcpSocket->bind (8899);    connect(socket,SIGNAL(readyRead()),this,SLOT(readDatas()));    connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(readTcpDatas()));    this->m_tcpState="unConnected";    tcpStateChanged();    //init ssid    QAndroidJniObject str=QAndroidJniObject::callStaticObjectMethod("com/tommego/SmartLinkManager",                                                                             "getSSID",                                                                             "()Ljava/lang/String;");    this->mssid=str.toString();    ssIDChanged();    //init address    QHostAddress address;    myAddress=address.toString();}QString WifiDeviceManager::deviceList(){    return "";}void WifiDeviceManager::readDatas(){    socket->waitForReadyRead(100);//    qDebug()<<"&&&&&&&&&&&&&&&&&&&&&datas:"<
readAll(); this->mrevDatas=socket->readAll(); while (socket->hasPendingDatagrams()) { QByteArray datagram; datagram.resize(socket->pendingDatagramSize()); QHostAddress sender; quint16 senderPort;// currentDatas="aa";// mdataChanged(); socket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort); mrevDatas=datagram.data(); revDatasChanged();// mdataChanged(); } revDatasChanged();}void WifiDeviceManager::startSmartLink(QString SSID, QString pwd){ QAndroidJniObject cssid=QAndroidJniObject::fromString(SSID); QAndroidJniObject cpwd=QAndroidJniObject::fromString(pwd); QAndroidJniObject::callStaticMethod
("com/tommego/SmartLinkManager", "startSmartLink", "(Ljava/lang/String;Ljava/lang/String;)V", cssid.object
(), cpwd.object
());}void WifiDeviceManager::searchDevice(){ QByteArray cmd; cmd.append("HF-A11ASSISTHREAD"); QString address="192.168.0.255"; QHostAddress ad(address); socket->writeDatagram(cmd,ad,port);// socket->writeDatagram(cmd,"192.168.1.255",port);}void WifiDeviceManager::sendDatas(QString datas){ QByteArray cmd; cmd.append(datas); QString address="192.168.0.255"; QHostAddress ad(address); socket->writeDatagram(cmd,ad,port);// socket->writeDatagram(cmd,"192.168.1.255",port);}QString WifiDeviceManager::revDatas(){ return this->mrevDatas;}void WifiDeviceManager::sendDatas(QString datas, int mport){ QByteArray cmd; cmd.append(datas); QString address="192.168.0.255"; QHostAddress ad(address); socket->writeDatagram(cmd,ad,mport);}QString WifiDeviceManager::tcpState (){ return this->m_tcpState;}void WifiDeviceManager::connectTcp (QString ip){ if(tcpSocket->state()==QTcpSocket::ConnectedState) return ; QHostAddress address(ip); tcpSocket->connectToHost(address,8899); if(tcpSocket->state()==QTcpSocket::ConnectedState) this->m_tcpState="connected"; else this->m_tcpState="unConnected"; tcpStateChanged();}void WifiDeviceManager::sendDatasTcp (QString data){ if(tcpSocket->state()==QTcpSocket::ConnectedState){ QByteArray mdata; mdata.append(data); this->tcpSocket->write (mdata); }}void WifiDeviceManager::readTcpDatas(){ tcpSocket->waitForReadyRead(500); mRevTcpDatas=tcpSocket->readAll(); revTcpDatasChanged();}QString WifiDeviceManager::revTcpDatas(){ return this->mRevTcpDatas;}

这里是调用smartlink库核心实现部分,在实现这个功能过程,遇到了很多java接口的坑.不过还好,整个源码实现完美在qt中跑起来了.这时候我们的app,就可以通过smartlink实现对为初始化的wifi设备进行一键配置网络了!(就算是有几十台wifi设备,都能直接在app中一键配置并且搜到wifi设备哈哈!)

功能截图:

clipboard.png

clipboard.png

转载地址:http://lvytl.baihongyu.com/

你可能感兴趣的文章
中介者模式
查看>>
购物搜索引擎架构的变与不变——淘宝网曲琳
查看>>
C# WPF vs WinForm
查看>>
Java内部类总结
查看>>
Cognos 图表用图片取代”没有数据显示”
查看>>
51 EEPROM操作模板
查看>>
Fedora 15 KDE中如何打开software management及如何应用
查看>>
Hadoop之回收站
查看>>
ESRI ArcGIS 9.0系列软件报价(转)
查看>>
Google Plugin for Eclipse
查看>>
FIREDAC驱动ORACLE的配置
查看>>
IOS数据类型对应输出格式
查看>>
GDI+中发生一般性错误的解决办法(转)
查看>>
PIL(Python Image Library)生成验证码
查看>>
中文分词器ICTCLAS使用方法(Java)
查看>>
UX最佳实践:提高用户体验影响力的艺术
查看>>
移动互联:用户体验设计指南
查看>>
BZOJ 2666: [cqoi2012]组装
查看>>
iOS 开发笔记-Objective-C之KVC、KVO
查看>>
PHP5与MySQL数据库操作
查看>>