本文详细介绍以CrossApp跨平台框架为基础,利用mosquito库和easySQLite库设计实现了基于MQTT协议的PC版步进电机控制客户端。
编译环境为VS2013,使用的语言主要是C++。
一、前期准备
本文所使用的跨平台界面库:
CrossApp官网:
http://crossapp.9miao.com/
CrossApp版本 1.5.4
下载地址:
https://github.com/babyliynfg/nano-CrossApp
本文使用的两个第三方库:
1、mosquitto,下载地址:
mosquitto-1.4.9
源码:http://www.eclipse.org/downloads/download.php?file=/mosquitto/source/mosquitto-1.4.9.tar.gz
2、easySQLite
官网地址:
https://code.google.com/archive/p/easysqlite/downloads
本文将分三个部分来实现:
1、工程创建和界面的大致设计规划;
2、数据库的操作;
3、MQTT协议栈和功能实现。
以下是具体内容:
二、工程创建和界面的大致设计规划
解压之后:
双击project-creator.exe:
工程名填:StepMotorController
package Name那里中间填公司名,本项目随便填了一个MyCompany,最右边填App名字,本项目填StepMotorController
然后点击Create Project Now。
跳出一个对话框来,点确定,然后看到:
然后关闭。
看到nano-CrossApp目录下出现一个projects文件夹,这个就是我们项目存放的目录,进去之后看到StepMotorController文件夹,里面就是我们的项目了。
我们先做Windows上的版本,然后再进一步兼容其他平台。
先把框架建起来:
然后双击nano-CrossApp\projects\StepMotorController\proj.win32下的StepMotorController.sln,打开vs工程,把StepMotorController设置为启动项,在debug版编译一下,运行调试,看到:
参考CrossApp官方的test代码(在nano-CrossApp\samples\Test目录下),
从test项目下拷贝RootWindow.h、RootWindow.cpp、MenuViewController.h、MenuViewController.cpp
我们添加四个文件:StepMotorControlView.h、StepMotorControlView.cpp、SettingsViewController.h、SettingsViewController.cpp
具体内容如下:
RootWindow.h
#ifndef __HelloCpp__RootWindow__
#define __HelloCpp__RootWindow__
#include <iostream>
#include "CrossApp.h"
class RootWindow: public CAWindow, public CAKeypadDelegate
{
public:
static RootWindow* getInstance();
RootWindow();
virtual ~RootWindow();
virtual bool init();
virtual void draw();
CC_SYNTHESIZE_READONLY(CANavigationController*, m_pRootNavigationController, RootNavigationController);
CC_SYNTHESIZE_READONLY(CADrawerController*, m_pRootDrawerController, DrawerController);
void initUIView();
virtual void keyBackClicked();
void buttonCallBack(CAControl* btn,DPoint point);
};
#endif /* defined(__HelloCpp__ViewController__) */
RootWindow.cpp:
#include "RootWindow.h"
#include "MenuViewController.h"
#include "StepMotorControlView.h"
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include <jni.h>
#include "platform/android/jni/JniHelper.h"
#endif
static RootWindow* _window = NULL;
RootWindow* RootWindow::getInstance()
{
if (_window == NULL)
{
_window = new RootWindow();
_window->init();
_window->autorelease();
}
return _window;
}
RootWindow::RootWindow()
:m_pRootNavigationController(NULL)
,m_pRootDrawerController(NULL)
{
CAApplication::getApplication()->getKeypadDispatcher()->addDelegate(this);
}
RootWindow::~RootWindow()
{
CAApplication::getApplication()->getKeypadDispatcher()->removeDelegate(this);
if (m_pRootNavigationController)
m_pRootNavigationController->release();
}
bool RootWindow::init()
{
if (!CAWindow::init())
{
return false;
}
CAApplication::getApplication()->setNotificationView(CAView::createWithFrame(this->getBounds(), CAColor_green));
this->initUIView();
MenuViewController* _menuview = MenuViewController::create();
CADrawerController* drawer = new CADrawerController();
drawer->initWithController(_menuview, m_pRootNavigationController);
drawer->setBackgroundImage(CAImage::create("image/bg.jpg"));
drawer->setEffect3D(true);
this->setRootViewController(drawer);
drawer->autorelease();
m_pRootDrawerController = drawer;
CAApplication::getApplication()->setNotificationView(NULL);
return true;
}
void RootWindow::draw()
{
}
void RootWindow::initUIView()
{
do
{
CAViewController* viewController = m_pRootNavigationController ? m_pRootNavigationController->getViewControllerAtIndex(0) : NULL;
CC_BREAK_IF(dynamic_cast<StepMotorControlView*>(viewController));
StepMotorControlView* tabBarController = new StepMotorControlView();
tabBarController->init();
tabBarController->autorelease();
CANavigationBarItem* temp_nav = CANavigationBarItem::create(UTF8("控制器面板"));
CABarButtonItem* item = CABarButtonItem::create("", CAImage::create("image/ic_category_list.png"), NULL);
item->setTarget(this, CAControl_selector(RootWindow::buttonCallBack));
temp_nav->addLeftButtonItem(item);
tabBarController->setNavigationBarItem(temp_nav);
if (m_pRootNavigationController)
{
m_pRootNavigationController->replaceViewController(tabBarController, false);
}
else
{
m_pRootNavigationController = new CANavigationController();
m_pRootNavigationController->initWithRootViewController(tabBarController);
m_pRootNavigationController->setNavigationBarBackgroundImage(CAImage::create("image/navbg.jpg"));
}
} while (0);
if (m_pRootDrawerController)
{
m_pRootDrawerController->hideLeftViewController(true);
}
CAApplication::getApplication()->setStatusBarStyle(CAStatusBarStyleLightContent);
}
void RootWindow::buttonCallBack(CAControl* btn,DPoint point)
{
this->getDrawerController()->showLeftViewController(true);
}
void RootWindow::keyBackClicked()
{
CC_RETURN_IF(CAAlertView::hideWithDisplayed());
if (this->getModalViewController())
{
this->dismissModalViewController(true);
}
else if (this->getDrawerController()->isShowLeftViewController())
{
this->getDrawerController()->hideLeftViewController(true);
}
else if (this->getRootNavigationController()->getViewControllerCount() > 1)
{
this->getRootNavigationController()->popViewControllerAnimated(true);
}
else
{
CAApplication::getApplication()->end();
}
}
MenuViewController.h:
//
// MenuViewController.h
// Test
//
// Created by renhongguang on 15/4/3.
//
//
#ifndef __Test__MenuViewController__
#define __Test__MenuViewController__
#include "RootWindow.h"
class MenuViewController : public CAViewController, CATableViewDelegate,CATableViewDataSource
{
public:
MenuViewController();
virtual ~MenuViewController();
CREATE_FUNC(MenuViewController);
protected:
void viewDidLoad();
void viewDidUnload();
void changeStatusBarOrientation(CAObject* obj);
public:
virtual void tableViewDidSelectRowAtIndexPath(CATableView* table, unsigned int section, unsigned int row);
virtual CATableViewCell* tableCellAtIndex(CATableView* table, const DSize& cellSize, unsigned int section, unsigned int row);
virtual unsigned int numberOfRowsInSection(CATableView *table, unsigned int section);
virtual unsigned int numberOfSections(CATableView *table);
virtual unsigned int tableViewHeightForRowAtIndexPath(CATableView* table, unsigned int section, unsigned int row);
private:
CATableView* tableView;
CAImageView* m_pLogo;
};
#endif /* defined(__Test__MenuViewController__) */
MenuViewController.cpp:
//
// MenuViewController.cpp
// Test
//
// Created by renhongguang on 15/4/3.
//
//
#include "MenuViewController.h"
#include "SettingsViewController.h"
MenuViewController::MenuViewController()
{
CANotificationCenter::sharedNotificationCenter()->addObserver(this, callfuncO_selector(MenuViewController::changeStatusBarOrientation), CAApplicationDidChangeStatusBarOrientationNotification, NULL);
}
MenuViewController::~MenuViewController()
{
CANotificationCenter::sharedNotificationCenter()->removeObserver(this, CAApplicationDidChangeStatusBarOrientationNotification);
}
void MenuViewController::viewDidLoad()
{
this->getView()->setColor(CAColor_clear);
DLayout tableViewLayout;
DLayout logoLayout;
const CAInterfaceOrientation& orientation = CAApplication::getApplication()->getStatusBarOrientation();
if (orientation == CAInterfaceOrientationLandscape)
{
tableViewLayout = DLayout(DHorizontalLayoutFill, DVerticalLayout_B_H(0, 400));
logoLayout = DLayout(DHorizontalLayout_W_C(261, 0.5), DVerticalLayout_T_H(120, 258));
}
else
{
tableViewLayout = DLayout(DHorizontalLayoutFill, DVerticalLayout_T_B(450, 0));
logoLayout = DLayout(DHorizontalLayout_W_C(261, 0.5), DVerticalLayout_T_H(120, 258));
}
tableView = CATableView::createWithLayout(DLayoutFill);
tableView->setLayout(tableViewLayout);
tableView->setAllowsSelection(true);
tableView->setTableViewDelegate(this);
tableView->setTableViewDataSource(this);
tableView->setBackgroundColor(CAColor_clear);
tableView->setSeparatorColor(ccc4(166, 166, 166,100));
tableView->setShowsScrollIndicators(false);
tableView->setScrollEnabled(false);
this->getView()->addSubview(tableView);
m_pLogo = CAImageView::createWithImage(CAImage::create("image/logo.png"));
m_pLogo->setLayout(logoLayout);
this->getView()->addSubview(m_pLogo);
}
void MenuViewController::viewDidUnload()
{
}
void MenuViewController::changeStatusBarOrientation(CAObject* obj)
{
const CAInterfaceOrientation& orientation = CAApplication::getApplication()->getStatusBarOrientation();
DLayout tableViewLayout;
DLayout logoLayout;
if (orientation == CAInterfaceOrientationLandscape)
{
tableViewLayout = DLayout(DHorizontalLayoutFill, DVerticalLayout_B_H(0, 400));
logoLayout = DLayout(DHorizontalLayout_W_C(261, 0.5), DVerticalLayout_T_H(120, 258));
}
else
{
tableViewLayout = DLayout(DHorizontalLayoutFill, DVerticalLayout_T_B(450, 0));
logoLayout = DLayout(DHorizontalLayout_W_C(261, 0.5), DVerticalLayout_T_H(120, 258));
}
tableView->setLayout(tableViewLayout);
m_pLogo->setLayout(logoLayout);
}
void MenuViewController::tableViewDidSelectRowAtIndexPath(CATableView* table, unsigned int section, unsigned int row)
{
RootWindow::getInstance()->dismissModalViewController(true);
if (row == 0)
{
RootWindow::getInstance()->initUIView();
}
else if (row == 1)
{
CAViewController* _settingsViewController = new SettingsViewController();
_settingsViewController->init();
_settingsViewController->setTitle(" ");
_settingsViewController->autorelease();
RootWindow::getInstance()->getDrawerController()->hideLeftViewController(true);
RootWindow::getInstance()->getRootNavigationController()->pushViewController(_settingsViewController, true);
}
}
#define _T(x) L##x
#define CHAR wchar_t
static const CHAR* menuList[2] =
{
_T("控制器面板"), _T("服务器设置")//,_T("应用展示"), _T("CrossApp官网"),
};
CATableViewCell* MenuViewController::tableCellAtIndex(CATableView* table, const DSize& cellSize, unsigned int section, unsigned int row)
{
CATableViewCell* cell = table->dequeueReusableCellWithIdentifier("CrossApp");
if (cell == NULL)
{
cell = CATableViewCell::create("CrossApp");
cell->setBackgroundView(NULL);
CALabel* test = CALabel::createWithLayout(DLayout(DHorizontalLayout_L_R(50, 0), DVerticalLayoutFill));
test->setTextAlignment(CATextAlignmentLeft);
test->setVerticalTextAlignmet(CAVerticalTextAlignmentCenter);
test->setFontSize(32);
test->setColor(CAColor_white);
test->setTag(100);
cell->addSubview(test);
CAImageView* arrow = CAImageView::createWithLayout(DLayout(DHorizontalLayout_R_W(0, 64), DVerticalLayout_T_H(20, 64)));
arrow->setTag(101);
cell->addSubview(arrow);
}
CALabel* test = (CALabel*)cell->getSubviewByTag(100);
test->setText(unicode_to_utf8(menuList[row]));// menuList[row]);
CAImageView* arrow = (CAImageView*)cell->getSubviewByTag(101);
arrow->setImage(CAImage::create("source_material/cell_btn_right.png"));
return cell;
}
//菜单选项数目
unsigned int MenuViewController::numberOfRowsInSection(CATableView *table, unsigned int section)
{
return 2;
}
unsigned int MenuViewController::numberOfSections(CATableView *table)
{
return 1;
}
unsigned int MenuViewController::tableViewHeightForRowAtIndexPath(CATableView* table, unsigned int section, unsigned int row)
{
return 100;
}
SettingsViewController.h:
#ifndef __SettingsViewController_h__
#define __SettingsViewController_h__
#include "CrossApp.h"
USING_NS_CC;
class SettingsViewController : public CAViewController,public CATextFieldDelegate
{
public:
SettingsViewController();
virtual ~SettingsViewController();
void viewDidLoad();
void viewDidUnload();
public:
CAWebView* p_webView;
protected:
virtual bool textFieldShouldBeginEditing(CATextField* sender);
//If the sender doesn't want to detach from the IME, return true;
virtual bool textFieldShouldEndEditing(CATextField* sender);
//
virtual void textFieldShouldReturn(CATextField* sender);
virtual void keyBoardHeight(CATextField* sender, int height);
//Warning!!! Warning!!! Warning!!! This method is not on the OpenGL thread.
virtual bool textFieldShouldChangeCharacters(CATextField* sender,
unsigned int location,
unsigned int lenght,
const std::string& changedText);
void alertButtonCallBack(CAControl* btn,DPoint point);
private:
CATextField* m_textField_IP;
CATextField* m_textField_Port;
CATextField* m_textField_Username;
CATextField* m_textField_Password;
CAButton* m_SaveBtn;
std::string m_strIPInput;
std::string m_strPortInput;
};
#endif /* defined(__SettingsViewController__) */
SettingsViewController.cpp:
#include "SettingsViewController.h"
SettingsViewController::SettingsViewController()
{
}
SettingsViewController::~SettingsViewController()
{
this->getView()->removeSubview(p_webView);
p_webView = NULL;
}
void SettingsViewController::viewDidLoad()
{
CAImageView* view1 = CAImageView::createWithImage(CAImage::create("image/motor_control_view.jpg"));
view1->setLayout(DLayoutFill);
this->getView()->addSubview(view1);
CALabel* label = CALabel::create();
label->setColor(ccc4(51, 204, 255, 255));
label->setText( UTF8( "网络参数设置"));
label->setFontSize(36);
label->setTextAlignment(CATextAlignmentLeft);
label->setVerticalTextAlignmet(CAVerticalTextAlignmentCenter);
label->setLayout(DLayout(DHorizontalLayout_W_C(240, 0.5), DVerticalLayout_H_C(40, 0.12)));
this->getView()->addSubview(label);
std::string ctn;
m_textField_IP = CATextField::createWithLayout(DLayout(DHorizontalLayout_L_R(100,