Qtインテリジェントホームアプリケーション開発:ハードウェアデバイスがインテリジェントネットワーク構成を実現する際、サードパーティsmart configライブラリをどのように使用するか
背景
読む前の予備知識:安暁輝先生のqt for androidコアプログラミング(Qtの中でc++がjavaを呼び出す方法を理解し、javaライブラリがqtプロジェクトにどのように追加するかを理解する) qt android wifi開発編 現在、インテリジェントハードウェアデバイスは、モジュール化された流行のwifiチップを使用してクラウドに接続し、リアルタイム通信とデータインタラクションを実現しています.以前、wifiチップを使用すると、wifiデバイスの初期化の過程で、apモードから接続ルータを手動で構成するという問題がよくありました.この操作の流れは開発者にとって簡単に見えます.ルータを交換する時、リセットボタンを押して手動で配置すればいいです.今でもこのような製品をたくさん見ています.例えば、ネットカメラ、いくつかの遠隔制御設備はこのモードです.学校のスタジオで先生がスマートホーム設備を買いました.私达は1册の说明书を见て流れに従って手动的にネットを配置します.つまり今大部分の知能の设备はやはりこの问题が存在します(実はすでに解决策があって、开発者はまだ今流行している知能のネットの配置の机能に気づいていないかもしれなくて、これは欠点の抜け穴があるかどうか私は知らないで、结局私も初心者で、この技术だけで简単な知能のホームシステムをしたことがあります).
wifiデバイスによるネットワーク構成方式の違い
従来のapモードのウェブページ構成wifチップネットワークやシリアルポート構成ネットワークよりも、smartconfigは新型のスマートネットワーク構成機能であり、操作がよりスマートで便利で、時物ネットワークチップ製品の大きな傾向である.違い:
apモードでのWebページ形式構成
ap(apモードとは、wifiチップをイメージングルータに起動させるように、他のwifi端末をこのwifiチップに接続させることができる)モードでのウェブページ形式は、wifi端末を介してwifiチップが開いているapサービスを手動で検索し、そのwifiチップに接続することである.次にwifi端末でブラウザを開き、wifiチップのアドレス(例えば:http://192.168.0.1 )は、wifiチップがもともとapモードをサポートしているため、ルータへの接続を再開するなど、wifiチップが提供する設定項目サービスを設定する権限を得る簡単なウェブサイトサービスとなっている.
シリアルポート構成
ほとんどのwifiチップはシリアルポートコマンド制御wifiチップのすべての機能をサポートしています.この場合、シリアルポートコマンド領域を介してwifiチップを制御する必要があります.
smartconfig
smartconfigはソフトウェア開発者向けのスマートネットワーク構成機能です.ハードウェア開発者は、自分のwifiチップがどのようにルータに接続されているかに関係なく、動的なルーティングがどのように切り替えられているかを知る必要はありません.smartconfigでは端末ソフトでwifiチップをルータに接続するからです.具体的な実現原理の参考:インテリジェントハードウェアアクセスクラウドプラットフォームソリューション
WeChatハードウェアプラットフォーム
微信ハードウェアプラットフォームの中にairkiss技術というものがあります.以下の2つの製品はこの技術をサポートしています.スマートネットワークの構成機能を実現するには、比較的完璧なプラットフォームと方案です.詳細な学習は自分でプラットフォームの公式サイトに入ってドキュメントを見てください.
hi-flyシリーズwifiチップ(筆者のプロジェクトはこのチップを使う)
Esp 8266 wifiチップ
hi-flyとespシリーズのチップは大同小異に見え、知識esp 8266チップはインテリジェントなネットワーク配置を実現するのが面倒で、その中には実現ソースコードしかなく、javaライブラリにカプセル化して使用していない.hi-fly製品はメーカーにjavaライブラリを提供し、後でqtの中でこのライブラリをどのように使用するかを重点的に紹介する.
wifiチップ学習:
公式評価版があれば、HF-LPT 220 wifiモジュール評価版を完全に参考にしてガイド学習を使用して完全なデバッグ環境を構築することができます.もしなければ、HF-LPT 220 wifiモジュールユーザーマニュアルというドキュメントを参考にデバッグボードを作ってください.
このプレートは自分で作ったもので、HF-LPT 220チップを使っています.回路設計は状況に応じて、シリアルポートとリセットキーを残して、公式評価版として使用することができます.
前期のハードウェア開発はwifiチップの操作を理解しなければならない. wifiチップシリアルからのデータを傍受する 透過モード を知るは、シリアルポートデータ伝送およびwifiシリアルポート制御コマンドを理解する.
ソフトウェア実装smartconfig
私のプロジェクトを分析します.
Qt androidプロジェクトを作成するときは、hi-flyingが提供するhiflying-iots-android-smartlink 7.0.2.jarをandroid/libsディレクトリにコピーします.
次にc++呼び出しjavaインタフェースクラスに書きます:SmartLinkManager.java
そしてc++はこのライブラリをスケジューリングすることができます:wifidevicemanager.h
wifidevicemanager.cpp
ここはsmartlinkライブラリのコア実装部分を呼び出して、この機能を実現する過程で、多くのjavaインタフェースの穴に遭遇しました.しかし、ソースコードの実装全体がqtの中で完璧に走り始めました.この時、私たちのappは、smartlinkを通じて初期化のためのwifiデバイスに対してキー配置ネットワークを実現することができます!(数十台のwifiデバイスがあっても、appで直接設定してwifiデバイスを検索できますハハ!)機能スクリーンショット:
読む前の予備知識:
wifiデバイスによるネットワーク構成方式の違い
従来のapモードのウェブページ構成wifチップネットワークやシリアルポート構成ネットワークよりも、smartconfigは新型のスマートネットワーク構成機能であり、操作がよりスマートで便利で、時物ネットワークチップ製品の大きな傾向である.違い:
apモードでのWebページ形式構成
ap(apモードとは、wifiチップをイメージングルータに起動させるように、他のwifi端末をこのwifiチップに接続させることができる)モードでのウェブページ形式は、wifi端末を介してwifiチップが開いているapサービスを手動で検索し、そのwifiチップに接続することである.次にwifi端末でブラウザを開き、wifiチップのアドレス(例えば:http://192.168.0.1 )は、wifiチップがもともとapモードをサポートしているため、ルータへの接続を再開するなど、wifiチップが提供する設定項目サービスを設定する権限を得る簡単なウェブサイトサービスとなっている.
シリアルポート構成
ほとんどのwifiチップはシリアルポートコマンド制御wifiチップのすべての機能をサポートしています.この場合、シリアルポートコマンド領域を介してwifiチップを制御する必要があります.
smartconfig
smartconfigはソフトウェア開発者向けのスマートネットワーク構成機能です.ハードウェア開発者は、自分のwifiチップがどのようにルータに接続されているかに関係なく、動的なルーティングがどのように切り替えられているかを知る必要はありません.smartconfigでは端末ソフトでwifiチップをルータに接続するからです.具体的な実現原理の参考:インテリジェントハードウェアアクセスクラウドプラットフォームソリューション
WeChatハードウェアプラットフォーム
微信ハードウェアプラットフォームの中にairkiss技術というものがあります.以下の2つの製品はこの技術をサポートしています.スマートネットワークの構成機能を実現するには、比較的完璧なプラットフォームと方案です.詳細な学習は自分でプラットフォームの公式サイトに入ってドキュメントを見てください.
hi-flyシリーズwifiチップ(筆者のプロジェクトはこのチップを使う)
Esp 8266 wifiチップ
hi-flyとespシリーズのチップは大同小異に見え、知識esp 8266チップはインテリジェントなネットワーク配置を実現するのが面倒で、その中には実現ソースコードしかなく、javaライブラリにカプセル化して使用していない.hi-fly製品はメーカーにjavaライブラリを提供し、後でqtの中でこのライブラリをどのように使用するかを重点的に紹介する.
wifiチップ学習:
公式評価版があれば、HF-LPT 220 wifiモジュール評価版を完全に参考にしてガイド学習を使用して完全なデバッグ環境を構築することができます.もしなければ、HF-LPT 220 wifiモジュールユーザーマニュアルというドキュメントを参考にデバッグボードを作ってください.
このプレートは自分で作ったもので、HF-LPT 220チップを使っています.回路設計は状況に応じて、シリアルポートとリセットキーを残して、公式評価版として使用することができます.
前期のハードウェア開発はwifiチップの操作を理解しなければならない.
ソフトウェア実装smartconfig
私のプロジェクトを分析します.
Qt androidプロジェクトを作成するときは、hi-flyingが提供するhiflying-iots-android-smartlink 7.0.2.jarをandroid/libsディレクトリにコピーします.
次にc++呼び出しjavaインタフェースクラスに書きます:SmartLinkManager.java
package com.tommego;
//hifly smart link libs
import 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 "+
"
mac:"+module.getMac()+ "
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_OBJECT
public:
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()<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デバイスを検索できますハハ!)機能スクリーンショット: