在前面设计的基础上,现在先将非方案商的实现逻辑加进去,这一步加完了之后,就将用codeblocks编译的工程改为用脚本编译。
现在看下当前的实现:
一、设计四个行为簇
IBurnDongle
class IBurnDongle
{
public:
IBurnDongle();
virtual ~IBurnDongle();
virtual bool burnDongle() = 0;
protected:
private:
};
IBurnDongle有一个具体派生行为:
class BurnDongle : public IBurnDongle
{
public:
BurnDongle();
virtual ~BurnDongle();
bool burnDongle();
protected:
private:
};
IGetDongleInfo
class IGetDongleInfo
{
public:
/** Default constructor */
IGetDongleInfo();
/** Default destructor */
virtual ~IGetDongleInfo();
virtual bool getDongleInfo()=0;
protected:
private:
};
IGetDongleInfo有一个具体派生行为:
class GetDongleInfo : public IGetDongleInfo
{
public:
GetDongleInfo();
virtual ~GetDongleInfo();
bool getDongleInfo();
protected:
private:
};
IScanDongle
class IScanDongle
{
public:
/** Default constructor */
IScanDongle();
/** Default destructor */
virtual ~IScanDongle();
//将接口申明为纯虚函数,接口为纯虚类,以便具体方法继承此此接口来实现具体的行为
virtual bool scanDongle() = 0;
protected:
private:
};
IScanDongle有一个具体派生行为:
class ScanDonglebyBluetooth : public IScanDongle
{
public:
/** Default constructor */
ScanDonglebyBluetooth();
/** Default destructor */
virtual ~ScanDonglebyBluetooth();
bool scanDongle();
protected:
private:
};
ISetDongleMode
class ISetDongleMode
{
public:
ISetDongleMode();
virtual ~ISetDongleMode();
virtual bool setDongleMode(int mode) = 0;
protected:
private:
};
ISetDongleMode有两个具体派生行为:
class SetDongleToIspMode : public ISetDongleMode
{
public:
SetDongleToIspMode();
virtual ~SetDongleToIspMode();
bool setDongleMode(int mode);
protected:
private:
};
class SetDongleToNormalMode : public ISetDongleMode
{
public:
SetDongleToNormalMode();
virtual ~SetDongleToNormalMode();
bool setDongleMode(int mode);
protected:
private:
};
二、设计一个方案商类簇
class SolutionProvider
{
public:
/** Default constructor */
SolutionProvider();
/** Default destructor */
virtual ~SolutionProvider();
// 加入实例变量以在运行时引用正确的行为类型
IScanDongle *iScanDongle;
IBurnDongle *iBurnDongle;
IGetDongleInfo *iGetDongleInfo;
ISetDongleMode *iSetDongleMode;
//用大的表示一类行为的方法来取代具体的行为,这也是便于运行时确定具体行为
virtual bool scanDongle() = 0;
virtual bool burnDongle() = 0;
virtual bool getDongleInfo() = 0;
virtual bool setDongleMode(int mode) = 0;
//virtual void SetDongleToIspMode();
//virtual void SetDongleToNomalMode();
protected:
private:
};
有两个具体的派生方案上A和B
class SolutionProviderA : public SolutionProvider
{
public:
/** Default constructor */
SolutionProviderA();
/** Default destructor */
virtual ~SolutionProviderA();
bool scanDongle();
bool burnDongle();
bool getDongleInfo();
bool setDongleMode(int mode);
protected:
private:
};
class SolutionProviderB:public SolutionProvider
{
public:
/** Default constructor */
SolutionProviderB();
/** Default destructor */
virtual ~SolutionProviderB();
bool scanDongle();
bool getDongleInfo();
bool setDongleMode(int mode);
protected:
private:
};
以及一个方案商工厂:
class SolutionProviderFactory
{
public:
/** Default constructor */
SolutionProviderFactory();
/** Default destructor */
virtual ~SolutionProviderFactory();
//工厂中有一个对象句柄
SolutionProvider *solutionProvider;
//有一个方法用来创建对象
SolutionProvider* CreateSolutionProvider(int providerId);
protected:
private:
};
方案商工厂可以根据传入的方案商编号来选择具体方案商:
//工厂根据传入的id参数来创建相应的对象
SolutionProvider* SolutionProviderFactory::CreateSolutionProvider(int providerId)
{
if(providerId == 1)
{
cout<< "new a SolutionProvider A in SolutionProviderFactoryAaaaa" <<endl;
solutionProvider= new SolutionProviderA();
}else if(providerId == 2)
{
cout<< "new a SolutionProvider B in SolutionProviderFactoryB" <<endl;
}
return solutionProvider;
}
三、当然还有一个我们的Dongle模块类,因为我们考虑拓展性,后续还可能加入其他模块,也可照此框架设计
class DongleModule
{
public:
/** Default constructor */
DongleModule();
//模块里有一个工厂句柄,是对工厂对象的一个引用
SolutionProviderFactory *solutionProviderFactory;
SolutionProvider *solutionProvider;
//在构造函数中对工厂进行初始化
DongleModule(SolutionProviderFactory *factory);
/** Default destructor */
virtual ~DongleModule();
void BurnDongle(int providerId);
char FILE_PATH[255];
char UDISK_DIR[15];
int findUpdateBinFromUDisk();
void my_progress_callback(int stage, int max, int current);
//int burnDongleFromUdisk(const char* filename,int dongleID);
int scan_dir(char *dir, int depth);
int file_exists(const char *filename);
protected:
private:
};
四、模拟上层和模块通信,还有一个Command类簇
class Command
{
public:
/** Default constructor */
Command();
/** Default destructor */
virtual ~Command();
virtual bool execute() = 0;
protected:
private:
};
Command有一个具体实现类DongleModuleCommand
class DongleModuleCommand:public Command
{
public:
/** Default constructor */
DongleModuleCommand();
/** Default destructor */
virtual ~DongleModuleCommand();
DongleModule dongleModule;
DongleModuleCommand(DongleModule donglemodule);
bool execute();
protected:
private:
};
命令控制类:
class ModuleControl
{
public:
/** Default constructor */
ModuleControl();
/** Default destructor */
virtual ~ModuleControl();
Command *command;
void SendCommand(Command *cmd);
protected:
private:
};
五、测试模块,也就是主函数
cout << "test begin.." << endl;
ModuleControl *moduleControl = new ModuleControl();
//先创建一个方案商工厂,专门用来创建方案商
SolutionProviderFactory *factory = new SolutionProviderFactory();
DongleModule *dongleModule = new DongleModule(factory);
DongleModuleCommand dongleModuleCommand(*dongleModule);
moduleControl->SendCommand(&dongleModuleCommand);
cout << "test end..." << endl;
//先创建一个方案商工厂,专门用来创建方案商
//SolutionProviderFactory *factory = new SolutionProviderFactory();
//创建一个Dongle模块对象,这个Dongle模块对象内部有一个工厂句柄,在这里将工厂传入
//DongleModule dongleModule(factory);
//之后因为工厂已经传入,这个时候,就可以利用工厂来创建方案商,并执行方案商的函数了
//dongleModule.BurnDongle(1);
cout << "test end..." << endl;
这里测试的是burnDongle这个功能:
bool DongleModuleCommand::execute()
{
//在这里确定传递的方案商参数是否合适?
cout<<"DongleModuleCommand::execute() excuting!!!!!!!!!!!!"<<endl;
dongleModule.BurnDongle(1);
return true;
}
BurnDongle里实现是这样的:
DongleModule::DongleModule(SolutionProviderFactory *factory):solutionProviderFactory(factory)
{
cout<<"DongleModule::DongleModule(SolutionProviderFactory factory):solutionProviderFactory(factory)"<<endl;
}
int DongleModule::file_exists(const char *filename)
{
return (access(filename, 0) == 0);
}
int DongleModule::scan_dir(char *dir, int depth)
{
DIR *dp;
int result =0;
struct dirent *entry;
struct stat statbuf;
if((dp = opendir(dir)) == NULL)
{
//LOGE("can't open dir.\n");
return result;
}
chdir (dir);
while((entry = readdir(dp)) != NULL)
{
lstat(entry->d_name, &statbuf);
if(S_IFDIR &statbuf.st_mode)
{
if (strcmp(".", entry->d_name) == 0 || strcmp("..", entry->d_name) == 0)
continue;
//LOGI("%*s%s/\n", depth, "", entry->d_name);
sprintf(FILE_PATH, "%s/%s/%s", "/mnt/usb",entry->d_name,"dongle_update.bin");
if (file_exists(FILE_PATH)) {
//LOGE("find the bin in udisk success,this path:%s \n",FILE_PATH);
result =1;
break;
}else{
//LOGE("can't find the bin in udisk success,this path:%s \n",FILE_PATH);
continue;
}
}
else
{
//LOGI("%*s%s\n", depth, "", entry->d_name);
}
}
chdir("..");
closedir(dp);
return result;
}
void DongleModule::my_progress_callback(int stage, int max, int current) {
SAVE_CURSOR();
MOVETO(1, 1);
CLEAR_END();
MOVETO(1, 10);
switch (stage) {
case APROM_PROGRAM_STAGE_START:
//LOGI("APROM PROGRAM START...");
break;
case APROM_PROGRAM_ERASING:
//LOGI("APROM PROGRAM ERASING...");
break;
case APROM_PROGRAM_WRITING:
//LOGI("APROM PROGRAM WRITING...");
break;
case APROM_PROGRAM_VERIFYING:
//LOGI("APROM PROGRAM VERIFYING...");
break;
case APROM_PROGRAM_STAGE_END:
//LOGI("APROM PROGRAM STAGE END");
break;
case APROM_DATA_STAGE_START:
//LOGI("APROM Data STAGE_START...");
break;
case APROM_DATA_ERASING:
//LOGI("APROM Data ERASING...");
break;
case APROM_DATA_WRITING:
//LOGI("APROM Data WRITING...");
break;
case APROM_DATA_VERIFYING:
//LOGI("APROM Data VERIFYING...");
break;
case APROM_DATA_STAGE_END:
//LOGI("APROM Data STAGE END...");
break;
}
if (max != 0) {
//LOGI("%d%%\n", current);
}
RESTORE_CURSOR();
}
int DongleModule::findUpdateBinFromUDisk(){
int result =0;
if(scan_dir(UDISK_DIR, 0)){
result =1;
}else{
//LOGE("can't find the bin in udisk\n");
}
return result;
}
void DongleModule::BurnDongle(int providerId)
{
cout<<"DongleModule::BurnDongle();..这里是我们调用方案商接口对我们想实现的行为的实现,\n相当于BurnDongle.cpp的main函数"<<endl;
//在这里利用工厂来初始化方案商这个对象
solutionProvider = solutionProviderFactory->CreateSolutionProvider(providerId);
CLEAR();
DONGLE_INFO dongleInfo;
DONGLE_INFO* pDongleInfo = &dongleInfo;
int selected = -1;
int result =-1;
int result_fd = -1;
char buffer[2]={0,0};
//const char * filename=0;
main_menu:
cout<<"====================================\n"<<endl;
cout<<"main_menu begin..."<<endl;
solutionProvider->burnDongle();
//int count = ScanForDongle();
int count = solutionProvider->scanDongle();
for (int i=0; i<count; ++i) {
DONGLE_INFO dongleInfo = {0};
//if (!GetDongleInfo(i, &dongleInfo)) continue;
//这里有问题,如果没有获取成功的话,会进入死循环
if(!solutionProvider->getDongleInfo()) continue;
}
selected = 0;
//if (!GetDongleInfo(selected, pDongleInfo)) {
if(solutionProvider->getDongleInfo()){
//LOGE("Get Dongle Info falied!\n");
result = NO_DONGLE_PLUG_IN ;
goto main_finish;
}
if(!findUpdateBinFromUDisk()){
//LOGE("Can't find the update_bin from udisk!\n");
result = FAIL_FIND_BIN_IN_UDISK;
goto main_finish;
}
if(pDongleInfo->mode == DONGLE_MODE_ISP){
//LOGI("goto burn dongle right now!\n");
goto burn_dongle;
}else{
//if(!SetDongleToIspMode(pDongleInfo->dongleID)) {
if(!solutionProvider->setDongleMode(1)){
//LOGE("failed to set dongle to isp mode!\n");
result = FAIL_SET_DONGLE_ISP_MODE;
goto main_finish;
}else{
//LOGI("success to set dongle to isp mode!\n");
goto main_menu;
}
}
burn_dongle:
//LOGI("file path = %s\n",FILE_PATH);
if(solutionProvider->burnDongle()){
//if(!BurnDongle(dongleID, filename, NULL, true, my_progress_callback)){
//LOGI("success to burn dongle!\n");
//if(!SetDongleToNormalMode(pDongleInfo->dongleID)){
if(solutionProvider->setDongleMode(2)){
//LOGE("failed to set dongle to normal mode!\n");
result = FAIL_SET_DONGLE_NORMAL_MODE;
goto main_finish;
}else{
//LOGI("success to set dongle to normal mode!\n");
result = SUCCESS_BURN_DONGLE;
}
}else{
result = FAIL_BURN_DONGLE;
goto main_finish;
}
main_finish:
result_fd=open("/data/dongle_update_flag.ini",O_RDWR|O_TRUNC|O_CREAT,0666);
if(result_fd == -1){
//LOGE("can't open /data/dongle_update_flag.ini!\n");
}else{
if(result==-1){
buffer[0] = '0';
}else{
buffer[0]=char(result)+'0';
}
if(write(result_fd,buffer,sizeof(buffer))!=1){
//LOGI("write /data/dongle_update_flag.ini success!\n");
}
else{
//LOGI("can't write /data/dongle_update_flag.ini!\n");
}
close(result_fd);
}
}