Dongle烧写模块重构(七)-加入当前已有的Dongle烧写功能

在前面设计的基础上,现在先将非方案商的实现逻辑加进去,这一步加完了之后,就将用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);
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值