Browse Source

#IQRV #comment [Healthmanger] DeviceControl 接口 DeployTerminal 功能迁移到 Healthmanager

gifur 4 năm trước cách đây
mục cha
commit
68ae1088dc

+ 10 - 2
Module/mod_healthmanager/CMakeLists.txt

@@ -4,9 +4,12 @@ set(${MODULE_PREFIX}_SRCS
 	mod_healthmanager.cpp
 	mod_healthmanager.h
 	HealthManagerFSM.cpp
-	HealthManagerFSM.h)
+	HealthManagerFSM.h
+	TerminalInfoQueryConn.cpp
+	TerminalInfoQueryConn.h
+	)
 
-set(MOD_VERSION_STRING "1.0.1-dev1")
+set(MOD_VERSION_STRING "1.0.2-dev1")
 add_module_libraries(${MODULE_PREFIX} ${MODULE_NAME} ${MOD_VERSION_STRING})
 
 target_include_directories(${MODULE_NAME} PRIVATE
@@ -23,6 +26,11 @@ target_include_directories(${MODULE_NAME} PRIVATE
 	${MODULE_BASE_DIR}/mod_interactioncontext
 	${MODULE_BASE_DIR}/mod_UpgradeMgr
 	${RVC_OTHER_DEPENDENIES_DIR}/libpublicFun
+	${MODULE_BASE_DIR}/mod_CenterSetting
+	${MODULE_BASE_DIR}/mod_Initializer
+	${MODULE_BASE_DIR}/mod_accessauth
+	${MODULE_BASE_DIR}/mod_pinpad
+	${MODULE_BASE_DIR}/mod_CameraConfigManage #for header file
 )
 
 # 添加实体需要依赖的其他共享库(包括系统库)

+ 85 - 0
Module/mod_healthmanager/TerminalInfoQueryConn.cpp

@@ -0,0 +1,85 @@
+#include "TerminalInfoQueryConn.h"
+#include <memory>
+
+CTerminalInfoQuery::CTerminalInfoQuery(CEntityBase* pEntity)
+    :SpSecureClient(pEntity)
+
+{
+
+}
+
+bool CTerminalInfoQuery::ConnectServer(const std::string& serverAddr, int port)
+{
+    return Connect(serverAddr.c_str(), port, 3);
+}
+
+void CTerminalInfoQuery::OnDisconnect()
+{
+    Dbg("connection disconnected");
+}
+
+void CTerminalInfoQuery::OnPkgAnswer(const CSmartPointer<IPackage>& pRecvPkg)
+{
+    const std::string serviceCode = pRecvPkg->GetServiceCode();
+
+}
+
+ErrorCodeEnum CTerminalInfoQuery::GetTerminalInfo(const std::string& terminalNo, TerminalRegistRet* terminalInfo)
+{
+    SendSayHelloReq(terminalNo);
+    auto result = GetFunction()->ReceivePackage(5);
+    ErrorCodeEnum err = DealSayHelloRet(result);
+    if (Error_Succeed == err) {
+        memcpy(terminalInfo, &terminalAns, sizeof(TerminalRegistRet));
+    } else {
+        Dbg("Deal with SayHello return value failed!: %s", SpStrError(err));
+    }
+    return err;
+}
+
+ErrorCodeEnum CTerminalInfoQuery::SendSayHelloReq(const std::string& terminalNo)
+{
+    TerminalRegistReq req;
+    memset(&req, 0, sizeof(TerminalRegistReq));
+    strcpy(req.TerminalNo, terminalNo.c_str());
+    CSmartPointer<IPackage> package = GetFunction()->CreateNewPackage("SayHello");
+    package->AddStruct("TerminalRegistReq", false, false, (BYTE*)&req, sizeof(req));
+    return SendPackage(package) != "" ? Error_Succeed : Error_Unexpect;
+}
+
+ErrorCodeEnum CTerminalInfoQuery::DealSayHelloRet(const CSmartPointer<IPackage>& pRecvPkg)
+{
+    ErrorCodeEnum result(Error_Unexpect);
+
+    DWORD dwSysCode, dwUserCode;
+    std::string strErrMsg;
+
+    memset(&terminalAns, 0, sizeof(terminalAns));
+
+    if (pRecvPkg->GetErrMsg(dwSysCode, dwUserCode, strErrMsg)) {
+        CSimpleStringA str = CSimpleStringA::Format("[%u] %s", dwUserCode, strErrMsg.c_str());
+        StoreErrorMsg(str.GetData());
+        result = static_cast<ErrorCodeEnum>(dwSysCode);
+    } else {
+        int nLen = pRecvPkg->GetStructLen("TerminalRegistRet");
+        if (nLen <= 0) {
+            StoreErrorMsg("not find struct [TerminalRegistRet] in package");
+        } else {
+            BYTE* pBuf = new BYTE[nLen];
+            memset(pBuf, 0, nLen);
+            int nArrayNum = 0;
+            if (!pRecvPkg->GetStructData("TerminalRegistRet", (BYTE*)pBuf, &nLen, &nArrayNum)) {
+                delete[] pBuf;
+                StoreErrorMsg("get struct [TerminalRegistRet] data fail");
+            } else {
+                TerminalRegistRet* pReq = (TerminalRegistRet *)pBuf;
+                Dbg("receive ret1: %s, %d %d", pReq->TerminalNo, nLen, nArrayNum);
+                memcpy(&terminalAns, pReq, sizeof(TerminalRegistRet));
+                delete[] pBuf;
+                result = Error_Succeed;
+            }
+        }
+    }
+
+    return result;
+}

+ 166 - 0
Module/mod_healthmanager/TerminalInfoQueryConn.h

@@ -0,0 +1,166 @@
+/***********************************//**
+ * @file TerminalInfoQueryConn.h
+ * @author Gifur
+ * @email guifaliao@gmail.com
+ * @version 1.0.0.0
+ * @date 2021-08-21
+ * @copyright China Merchants Bank Co.,Ltd All rights reserved
+ *
+ * @brief 
+ * @details 
+ **************************************/
+#pragma once
+#ifndef RVC_TERMINAL_QUERY_INFO_HEADER
+#define RVC_TERMINAL_QUERY_INFO_HEADER
+
+#include "SpSecureClient.h"
+
+#pragma pack(1)
+typedef struct _DevInfoReq
+{
+    char TerminalNo[16];
+
+} TerminalRegistReq;
+
+typedef struct _DevInfoRcv
+{
+    char TerminalNo[16];
+    char DeviceNo[16];
+    char OutletNo[6];
+    char Initializer[32];
+    BYTE InitIP[4];
+    BYTE CreateTime[4];
+    char PadDeviceID[32];
+    char MachineType[16];
+    BYTE MachineVersion[4];
+    char Sites[16];
+    BYTE EnrolGPS[8];
+    char EnrolAddr[512];
+    BYTE AuthorizedTime[4];
+    BYTE BusinessStructID[8];
+    BYTE StructID[8];
+    char Editor[32];
+    BYTE EditTime[4];
+    char State;
+    char PublicKey[512];
+    char FingerPrint[512];
+
+} TerminalRegistRet;
+
+typedef struct _md5_req
+{
+    char filePath[128];
+
+}MD5_REQ;
+
+typedef struct _RegisteQuery_
+{
+    char UkeyID[16];
+
+} RegisteQuery;
+
+typedef struct _RegisteQueryReply_
+{
+    char IPAddress[512];
+
+} RegisteQueryReply;
+
+typedef struct _InstallQuery_
+{
+    char MType[16];
+} InstallQuery;
+
+typedef struct _InstallReply_
+{
+    char InsStep[60000];
+
+} InstallReply;
+
+typedef struct
+{
+    char curVersion[16];
+
+} SoftwareVerReq;
+
+typedef struct
+{
+    int isForce;
+    char updataVer[16];
+
+} SoftwareVerRet;
+
+typedef struct _FILE_REQ
+{
+    int pos;	//ask for which piece
+
+} FILE_REQ;
+
+typedef struct _FILE_RCV
+{
+    int pos;				        //rev which piece
+    int totalPiece;			//total pieces
+    int length;				//piece length
+    char dataPiece[10240];	//piece
+
+} FILE_RCV;
+
+typedef struct _FILE_PUBLIC_REQ
+{
+    int pos;
+    char filePath[128];
+
+} FILE_PUBLIC_REQ;
+
+typedef struct _FILE_PUBLIC_RVC
+{
+    int pos;				//rev which piece
+    int totalPiece;			//total pieces
+    int length;				//piece length
+    char dataPiece[50000];	//piece
+
+} FILE_PUBLIC_RVC;
+
+typedef struct _STR_REQ
+{
+    char machineNo[16];
+    char deviceNo[16];
+    BYTE initIp[4];
+    char AgentID[32];
+    char sites[16];
+
+} STR_REQ;
+
+#pragma pack()
+
+
+/*!
+ * @class classname
+ * @brief 
+ * 
+ * @note matters needing attention
+ */
+
+class CTerminalInfoQuery : public SpSecureClient
+{
+public:
+    CTerminalInfoQuery(CEntityBase* pEntity);
+
+    bool ConnectServer(const std::string& serverAddr, int port);
+    ErrorCodeEnum GetTerminalInfo(const std::string& terminalNo, TerminalRegistRet* terminalInfo);
+
+private:
+
+    virtual ~CTerminalInfoQuery(void) {}
+
+    void StoreErrorMsg(const std::string& msg) { Dbg(msg.c_str()); }
+    ErrorCodeEnum SendSayHelloReq(const std::string& terminalNo);
+    ErrorCodeEnum DealSayHelloRet(const CSmartPointer<IPackage>& pRecvPkg);
+
+    virtual void OnDisconnect();
+    virtual void OnPkgAnswer(const CSmartPointer<IPackage>& pRecvPkg);
+
+private:
+    TerminalRegistRet terminalAns;
+};
+
+#endif //RVC_TERMINAL_QUERY_INFO_HEADER

+ 357 - 2
Module/mod_healthmanager/mod_healthmanager.cpp

@@ -19,16 +19,21 @@
 #include <sys/reboot.h>
 #endif //RVC_OS_WIN
 
-#include "toolkit.h"
 #include <vector>
 #include <iostream>
 #include <fstream>
+#include <regex.h>
+#include "toolkit.h"
+#include "array.h"
+#include "fileutil.h"
+#include "iniutil.h"
 
 using namespace std;
 
 #include "mod_healthmanager.h"
 #include "CommEntityUtil.hpp"
 #include "GetDevInfoHelper.h"
+#include "TerminalInfoQueryConn.h"
 
 #if defined(RVC_OS_WIN)
 #pragma comment( lib, "advapi32.lib" )
@@ -49,6 +54,21 @@ const DWORD HEALTHMANAGER_TIMER_INTERVAL_MINUTE = (HEALTHMANAGER_TIMER_INTERVAL/
 #define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
 #define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
 
+#define DEPLOYSTATE_NOTINIT 0
+#define DEPLOYSTATE_DONE 1
+#define DEPLOYSTATE_FAILED 2
+
+
+#include "CenterSetting_client_g.h"	
+using namespace CenterSetting;
+
+#include "Initializer_client_g.h"
+using namespace Initializer;
+
+//for defines in header file
+#include "CameraConfigManage_def_g.h"
+using namespace CameraConfigManage;
+
 template<class T>
 class TimerOutHelper : public ITimerListener
 {
@@ -69,6 +89,24 @@ private:
 	FuncTimer m_pTimer;
 	bool m_bDeleteSelf;
 };
+
+static void PrintTerminalRegistInfo(const TerminalRegistRet* info)
+{
+    Dbg("TerminalNo: %s", info->TerminalNo);
+    Dbg("DeviceNo: %s", info->DeviceNo);
+    Dbg("OutletNo: %s", info->OutletNo);
+    Dbg("Initializer: %s", info->Initializer);
+    Dbg("PadDeviceID: %s", info->PadDeviceID);
+    Dbg("MachineType: %s", info->MachineType);
+    Dbg("MachineVersion: %s", info->MachineVersion);
+    Dbg("Sites: %s", info->Sites);
+    Dbg("EnrolAddr: %s", info->EnrolAddr);
+    Dbg("Editor: %s", info->Editor);
+    Dbg("State: %c", info->State);
+    Dbg("PublicKey: %s", info->PublicKey);
+    Dbg("FingerPrint: %s", info->FingerPrint);
+}
+
 void HealthManagerSession::Handle_EnterState(SpReqAnsContext<HealthManagerService_EnterState_Req, HealthManagerService_EnterState_Ans>::Pointer ctx)
 {
 	LOG_FUNCTION();
@@ -105,13 +143,17 @@ void HealthManagerSession::Handle_ReadCenterConfigStr(SpReqAnsContext<HealthMana
 {
 	LOG_FUNCTION();
 }
-
 void HealthManagerSession::Handle_ControlTerminalLife(
 	SpReqAnsContext<HealthManagerService_ControlTerminalLife_Req, HealthManagerService_ControlTerminalLife_Ans>::Pointer ctx)
 {
     LOG_FUNCTION();
 	m_pEntity->ControlTerminalLife(ctx);
 }
+void HealthManagerSession::Handle_DeployTerminal(SpReqAnsContext<HealthManagerService_DeployTerminal_Req, HealthManagerService_DeployTerminal_Ans>::Pointer ctx)
+{
+    LOG_FUNCTION();
+    m_pEntity->DeployTerminal(ctx);
+}
 
 bool CHealthManagerEntity::DoWatchDog(WatchDogOp eOp)
 {
@@ -2059,6 +2101,319 @@ void CHealthManagerEntity::OnBroadcastEvent(CUUID SubID, const char *pszEntityNa
 	}
 }
 
+void CHealthManagerEntity::DeployTerminal(SpReqAnsContext<HealthManagerService_DeployTerminal_Req, HealthManagerService_DeployTerminal_Ans>::Pointer ctx)
+{
+
+    LOG_FUNCTION();
+
+    ErrorCodeEnum result(Error_Succeed);
+    int tmpResult = 0;
+    CSimpleStringA tmpMsg(true);
+
+    Dbg("Cmd: %d", ctx->Req.currStep);
+
+    switch (ctx->Req.currStep) {
+    case DeployStep_Begin:
+        result = Error_NotImpl;
+        break;
+    case DeployStep_GetTerminalInfo:
+    {
+        CTerminalInfoQuery* pCnn = new CTerminalInfoQuery(this);
+        CAutoArray<CSimpleStringA> arrs = ctx->Req.param4.Split('|');
+        const CSimpleStringA& terminalNo = arrs[0];
+        const CSimpleStringA& vendorType = arrs[1];
+        const CSimpleStringA& serverIP = ctx->Req.param3;
+        Dbg("server ip: %s, terminal no: %s, vendor: %s", serverIP.GetData(), (LPCTSTR)terminalNo, (LPCTSTR)vendorType);
+
+        /** 1050 是固定的服务端实体端口 [Gifur@20211013]*/
+        pCnn->ConnectServer(serverIP.GetData(), 1050);
+        Dbg("Connect finished!");
+        if (pCnn->IsConnectionOK()) {
+            Dbg("Connect OK!");
+            TerminalRegistRet info;
+            result = pCnn->GetTerminalInfo(terminalNo.GetData(), &info);
+            pCnn->Close();
+            PrintTerminalRegistInfo(&info);
+            if (strlen(info.TerminalNo) == 0) {
+                result = Error_NotExist;
+            } else if (terminalNo.Compare(info.TerminalNo) != 0) {
+                result = Error_MisMatched;
+            } else {
+                ErrorCodeEnum ec(Error_Succeed);
+                CSmartPointer<IConfigInfo> pConfig;
+                GetFunction()->OpenConfig(Config_Cache, pConfig);
+                do {
+                    Dbg("record to cache...");
+                    const ErrorCodeEnum ec0 = pConfig->WriteConfigValue("TerminalDeploy", "TerminalNo", terminalNo);
+                    const ErrorCodeEnum ec1 = pConfig->WriteConfigValue("TerminalDeploy", "Manufacturer", vendorType);
+                    const ErrorCodeEnum ec2 = pConfig->WriteConfigValue("TerminalDeploy", "ServerIP", serverIP);
+                    const ErrorCodeEnum ec3 = pConfig->WriteConfigValueInt("TerminalDeploy", "CurrStep", ctx->Req.currStep);
+                    if (!ec0 && !ec1 && !ec2 && !ec3) {
+                        ec = pConfig->WriteConfigValueInt("TerminalDeploy", "CurrState", DEPLOYSTATE_DONE);
+                        Dbg("record step: %s", SpStrError(ec));
+                    } else {
+                        Dbg("record failed: %s, %s, %s, %s", SpStrError(ec), SpStrError(ec1), SpStrError(ec2), SpStrError(ec3));
+                        ec = Error_IO;
+                    }
+
+                } while (false);
+
+                do {
+                    CSimpleStringA strRootCfgPath;
+                    ec = GetFunction()->GetPath("HardwareCfg", strRootCfgPath);
+                    if (ec == Error_Succeed && !strRootCfgPath.IsNullOrEmpty()) {
+                        CSimpleStringA strRootIniFullPath(strRootCfgPath.GetData());
+                        strRootIniFullPath += SPLIT_SLASH_STR;
+                        strRootIniFullPath += "root.ini";
+                        if (ExistsFileA(strRootIniFullPath)) {
+                            fileutil_copy_file(strRootIniFullPath + ".bak", strRootIniFullPath);
+                            fileutil_delete_file(strRootIniFullPath);
+                            Dbg("root.ini exists!");
+                        }
+
+                        array_header_t* subs = fileutil_get_sub_files_a(strRootCfgPath);
+                        if (subs) {
+                            regex_t reg;
+                            CSimpleStringA machineType("Stand2S");
+                            CSimpleStringA rootPattern("root");
+                            CSimpleStringA pattern = rootPattern + "\\-" + machineType + "\\-" + vendorType + "\\-[a-zA-Z0-9_\\(\\)\\-]*" + ".ini";
+                            int ret = regcomp(&reg, pattern, REG_EXTENDED | REG_NOSUB);
+                            if (ret) {
+                                char ebuff[256];
+                                regerror(ret, &reg, ebuff, 256);
+                                Dbg("regex failed: %s", ebuff);
+                                tmpMsg = CSimpleStringA::Format("内部错误:REGEX %s", ebuff);
+                                break;
+                            }
+                            Dbg("pattern: %s", pattern.GetData());
+                            CSimpleStringA strRootChosenFile(true);
+                            for (int i = 0; i < subs->nelts; ++i) {
+                                char* filenamePath = ARRAY_IDX(subs, i, char*);
+                                char* filename = &filenamePath[strRootCfgPath.GetLength() + 1];
+                                Dbg("filename: %s", filename);
+                                ret = regexec(&reg, filename, 0, NULL, 0);
+                                if (0 == ret) {
+                                    Dbg("matched!");
+                                    strRootChosenFile = filenamePath;
+                                    break;
+                                }
+                                Dbg("not matched.");
+
+                            }
+                            toolkit_array_free2(subs);
+
+                            if (!strRootChosenFile.IsNullOrEmpty()) {
+                                CSimpleStringA strRootTmpFile = strRootIniFullPath + ".cur";
+                                fileutil_copy_file(strRootTmpFile, strRootChosenFile);
+                                inifile_write_str(strRootTmpFile, "Terminal", "TerminalNo", terminalNo);
+                                //inifile_write_str(strRootTmpFile, "Terminal", "Manufacturer", vendorType);
+                                //TODO: Addr
+                                fileutil_copy_file(strRootIniFullPath, strRootTmpFile);
+                                fileutil_delete_file(strRootTmpFile);
+
+                                pConfig->WriteConfigValueInt("TerminalDeploy", "CurrStep", ctx->Req.nextStep);
+                                pConfig->WriteConfigValueInt("TerminalDeploy", "CurrState", DEPLOYSTATE_NOTINIT);
+
+                            } else {
+                                tmpMsg = "找不到匹配的备选文件,请确认安装包完整性并尝试重新安装";
+                                tmpResult = 1;
+                            }
+                        }
+                    }
+
+                } while (false);
+
+                ctx->Ans.param2 = serverIP;
+                ctx->Ans.nextStep = ctx->Req.nextStep;
+                ctx->Ans.result = tmpResult;
+                ctx->Ans.additionalMsg = tmpMsg;
+            }
+
+        } else {
+            Dbg("Connect Failed!");
+            result = Error_ConnectFailed;
+        }
+        pCnn->DecRefCount();
+        pCnn = NULL;
+    }
+    break;
+    case DeployStep_FetchCenterSettings:
+    {
+        const CSimpleStringA& serverIP = ctx->Req.param3;
+        const int nPort = ctx->Req.param1;
+
+        if (serverIP.IsNullOrEmpty() || nPort <= 0) {
+            result = Error_Param;
+            break;
+        }
+
+        ErrorCodeEnum ec(Error_Succeed);
+        CSmartPointer<IConfigInfo> pConfig;
+        GetFunction()->OpenConfig(Config_Cache, pConfig);
+
+        Dbg("to connect centersetting...%s::%d", serverIP.GetData(), nPort);
+        auto pCenterSettingClient = new CenterSettingService_ClientBase(this);
+        ec = pCenterSettingClient->Connect();
+        if (ec != Error_Succeed) {
+            tmpMsg = CSimpleStringA::Format("连接集中配置模块失败: %s", SpStrError(ec));
+            pCenterSettingClient->SafeDelete();
+            Dbg("connect to centersetting failed: %s", SpStrError(ec));
+            tmpResult = ec;
+        } else {
+            CenterSettingService_Download_Req req = {};
+            req.strAddr = serverIP;
+            req.nPort = nPort;
+            CenterSettingService_Download_Ans ans = {};
+            /**TODO(Gifur@10/14/2021): 未知行内还是行外的情况 */
+            Dbg("to download...");
+            ec = pCenterSettingClient->Download(req, ans, 10000);
+            if (ec != Error_Succeed) {
+                tmpMsg = CSimpleStringA::Format("集中配置模块调用失败: %s", SpStrError(ec));
+                tmpResult = ec;
+                Dbg("to download failed: %s", SpStrError(ec));
+            } else {
+                pConfig->WriteConfigValueInt("TerminalDeploy", "CurrStep", ctx->Req.nextStep);
+                pConfig->WriteConfigValueInt("TerminalDeploy", "CurrState", DEPLOYSTATE_NOTINIT);
+            }
+            pCenterSettingClient->GetFunction()->CloseSession();
+        }
+
+        ctx->Ans.param2 = serverIP;
+        ctx->Ans.nextStep = ctx->Req.nextStep;
+        ctx->Ans.result = tmpResult;
+        ctx->Ans.additionalMsg = tmpMsg;
+    }
+    break;
+    case DeployStep_AccessAuthorize:
+    {
+        const CSimpleStringA& serverIP = ctx->Req.param3;
+        const int nPort = ctx->Req.param1;
+
+        if (serverIP.IsNullOrEmpty() || nPort <= 0) {
+            result = Error_Param;
+            break;
+        }
+
+        ErrorCodeEnum ec(Error_Succeed);
+        CSmartPointer<IConfigInfo> pConfig;
+        GetFunction()->OpenConfig(Config_Cache, pConfig);
+
+        Dbg("to connect initializer...%s::%d", serverIP.GetData(), nPort);
+        auto pClient = new InitializerService_ClientBase(this);
+        ec = pClient->Connect();
+        if (ec != Error_Succeed) {
+            tmpMsg = CSimpleStringA::Format("连接初始化模块失败: %s", SpStrError(ec));
+            pClient->SafeDelete();
+            Dbg("connect to initializer module failed: %s", SpStrError(ec));
+            tmpResult = ec;
+        } else {
+            InitializerService_InitializeNew_Req req = {};
+            req.strAuthServer = serverIP;
+            req.nAuthPort = nPort;
+            req.strUserID = "admin";
+            req.strPassword = "88888888";
+
+            InitializerService_InitializeNew_Ans ans = {};
+            Dbg("to initializer...");
+            ec = pClient->InitializeNew(req, ans, 30000);
+            if (ec != Error_Succeed) {
+                tmpMsg = CSimpleStringA::Format("初始化调用失败: %s", SpStrError(ec));
+                tmpResult = ec;
+                Dbg("to initialize failed: %s", SpStrError(ec));
+            } else {
+
+                const int errUserCode = (int)(ans.Errcode);
+                if (errUserCode != 0) {
+                    if (ans.ErrMsg.IsNullOrEmpty()) {
+                        tmpMsg = CSimpleStringA::Format("%d", errUserCode);
+                    } else {
+                        tmpMsg = CSimpleStringA::Format("%s", ans.ErrMsg.GetData());
+                    }
+                    tmpResult = errUserCode;
+                    Dbg("initialize failed: %s", (LPCTSTR)tmpMsg);
+                } else {
+                    Dbg("initialize succ.");
+                    pConfig->WriteConfigValueInt("TerminalDeploy", "CurrStep", ctx->Req.nextStep);
+                    pConfig->WriteConfigValueInt("TerminalDeploy", "CurrState", DEPLOYSTATE_NOTINIT);
+                }
+            }
+            pClient->GetFunction()->CloseSession();
+        }
+
+        ctx->Ans.param2 = serverIP;
+        ctx->Ans.nextStep = ctx->Req.nextStep;
+        ctx->Ans.result = tmpResult;
+        ctx->Ans.additionalMsg = tmpMsg;
+    }
+    break;
+    case DeployStep_MediaConfig:
+    {
+        ErrorCodeEnum ec(Error_Succeed);
+        CSmartPointer<IConfigInfo> pConfig, pRootConfig;
+
+        GetFunction()->OpenConfig(Config_Cache, pConfig);
+        GetFunction()->OpenConfig(Config_Root, pRootConfig);
+
+        for (int i = 0; i < ctx->Req.array1.GetCount(); ++i) {
+            CSimpleStringA key(true), value(ctx->Req.array2[i]);
+            const int type = ctx->Req.array1[i];
+            Dbg("%d: %s - %d", i, value.GetData(), type);
+            switch (type) {
+            case MediaDev_OutSpeaker:
+                key = "handfree_out_dev";
+                break;
+            case MediaDev_InSpeaker:
+                key = "pickup_out_dev";
+                break;
+            case MediaDev_OutMicrophone:
+                key = "handfree_in_dev";
+                break;
+            case MediaDev_InMicrophone:
+                key = "pickup_in_dev";
+                break;
+            default:
+                ec = Error_Param;
+                break;
+            }
+
+            if (!key.IsNullOrEmpty()) {
+                ec = pRootConfig->WriteConfigValue("Audio", key, value);
+                Dbg("write %s=%s into root.ini: %s", key.GetData(), value.GetData(), SpStrError(ec));
+            } else {
+                Dbg("unrecognize: %d, %s", type, value.GetData());
+            }
+        }
+
+        pConfig->WriteConfigValueInt("TerminalDeploy", "CurrStep", DeployStep_MediaConfig);
+        pConfig->WriteConfigValueInt("TerminalDeploy", "CurrState", (ec != Error_Succeed) ? DEPLOYSTATE_FAILED : DEPLOYSTATE_DONE);
+
+        ctx->Ans.nextStep = ctx->Req.nextStep;
+        ctx->Ans.result = ec;
+        ctx->Ans.additionalMsg = tmpMsg;
+    }
+    break;
+    case DeployStep_Finished:
+    {
+        ErrorCodeEnum ec(Error_Succeed);
+        CSmartPointer<IConfigInfo> pConfig;
+        GetFunction()->OpenConfig(Config_Cache, pConfig);
+        pConfig->WriteConfigValueInt("TerminalDeploy", "CurrStep", DeployStep_Finished);
+        pConfig->WriteConfigValueInt("TerminalDeploy", "CurrState", DEPLOYSTATE_DONE);
+        CSimpleStringA strRootCfgPath;
+        ec = GetFunction()->GetPath("HardwareCfg", strRootCfgPath);
+        CSimpleStringA strRootIniFullPath(strRootCfgPath.GetData());
+        strRootIniFullPath += SPLIT_SLASH_STR;
+        strRootIniFullPath += "root.ini";
+    }
+    break;
+    default:
+        result = Error_MisMatched;
+        break;
+    }
+    ctx->Answer(result);
+}
+
+
 bool CHealthManagerEntity::IsTestMode()
 {
 	static int flag = -1;

+ 7 - 1
Module/mod_healthmanager/mod_healthmanager.h

@@ -3,6 +3,8 @@
 
 #include <map>
 #include "SpBase.h"
+#include "modVer.h"
+#include "SpTest.h"
 #include "HealthManagerFSM.h"
 #include "EventCode.h"
 #include "HealthManager_server_g.h"
@@ -78,6 +80,7 @@ public:
 	virtual void Handle_QueryHardwareInfo(SpReqAnsContext<HealthManagerService_QueryHardwareInfo_Req, HealthManagerService_QueryHardwareInfo_Ans>::Pointer ctx);
 	virtual void Handle_ReadCenterConfigStr(SpReqAnsContext<HealthManagerService_ReadCenterConfigStr_Req, HealthManagerService_ReadCenterConfigStr_Ans>::Pointer ctx);
 	void Handle_ControlTerminalLife(SpReqAnsContext<HealthManagerService_ControlTerminalLife_Req, HealthManagerService_ControlTerminalLife_Ans>::Pointer ctx);
+    virtual void Handle_DeployTerminal(SpReqAnsContext<HealthManagerService_DeployTerminal_Req, HealthManagerService_DeployTerminal_Ans>::Pointer ctx);
 
 private:
 	CHealthManagerEntity *m_pEntity;
@@ -95,7 +98,7 @@ public:
 		, m_bEnterMainPageEver(false), m_connectStatus(0), m_bAccessSuc(false), m_pfShake(NULL),m_pfUpgradeRestart(NULL){}
 	virtual ~CHealthManagerEntity() {}
 	virtual const char *GetEntityName() const { return "HealthManager"; }
-	
+	const char* GetEntityVersion() const { return MODULE_VERSION_FULL; }
 	virtual void OnPreStart(CAutoArray<CSimpleStringA> strArgs,CSmartPointer<ITransactionContext> pTransactionContext) 
 	{
 		DoRestart();
@@ -198,6 +201,9 @@ public:
 	virtual void OnSysVarEvent(const char *pszKey,
 		const char *pszValue, const char *pszOldValue, const char *pszEntityName);
 	virtual void OnBroadcastEvent(CUUID SubID, const char *pszEntityName, DWORD dwMessageId, DWORD dwMessageSignature, CAutoBuffer Buffer);
+
+    void DeployTerminal(SpReqAnsContext<HealthManagerService_DeployTerminal_Req, HealthManagerService_DeployTerminal_Ans>::Pointer ctx);
+
 private:
 	CHealthManagerFSM m_fsm;
 	//the following is useless?just one var is ok? oiltmp

+ 6 - 6
addin/res/ManagerDesktop/js/guide.js

@@ -211,7 +211,7 @@ $(function () {
         req.array2 = [''];
 
         utilStartSubmitDialog();
-        RVC.DeviceControlEntityCtrl.DeployTerminal(req, function(ret) {
+        RVC.HealthmanagerEntityCtrl.DeployTerminal(req, function(ret) {
             utilStopSubmitDialog();
             if(ret.errorCode === 0) {
                 let result = JSON.parse(ret[RVC.EntityController.sigResponseUUID])
@@ -223,7 +223,7 @@ $(function () {
                     utilStartAlertDialog("操作失败:[" + result.result + "] " + result.additionalMsg);
                 }
             } else {
-                RVC.DeviceControlEntityCtrl.commErrorCallback(ret);
+                RVC.HealthmanagerEntityCtrl.commErrorCallback(ret);
             }
         });
     }
@@ -243,7 +243,7 @@ $(function () {
         req.array2 = [''];
 
         utilStartSubmitDialog();
-        RVC.DeviceControlEntityCtrl.DeployTerminal(req, function(ret) {
+        RVC.HealthmanagerEntityCtrl.DeployTerminal(req, function(ret) {
             utilStopSubmitDialog();
             if(ret.errorCode === 0) {
                 let result = JSON.parse(ret[RVC.EntityController.sigResponseUUID])
@@ -256,7 +256,7 @@ $(function () {
                     utilStartAlertDialog("操作失败:[" + result.result + "] " + result.additionalMsg);
                 }
             } else {
-                RVC.DeviceControlEntityCtrl.commErrorCallback(ret);
+                RVC.HealthmanagerEntityCtrl.commErrorCallback(ret);
             }
         });
     }
@@ -412,7 +412,7 @@ $(function () {
         req.array2 = [output_outfree, output_infree, input_outfree, input_infree];
 
         utilStartSubmitDialog();
-        RVC.DeviceControlEntityCtrl.DeployTerminal(req, function(ret) {
+        RVC.HealthmanagerEntityCtrl.DeployTerminal(req, function(ret) {
             utilStopSubmitDialog();
             if(ret.errorCode === 0) {
                 let result = JSON.parse(ret[RVC.EntityController.sigResponseUUID])
@@ -424,7 +424,7 @@ $(function () {
                     utilStartAlertDialog("操作失败:[" + result.result + "] " + result.additionalMsg);
                 }
             } else {
-                RVC.DeviceControlEntityCtrl.commErrorCallback(ret);
+                RVC.HealthmanagerEntityCtrl.commErrorCallback(ret);
             }
         });
 

+ 11 - 11
addin/res/ManagerDesktop/js/public.js

@@ -1648,15 +1648,13 @@ $(function () {
             QueryHardwareInfo: 4,
             ReadCenterConfigStr: 5,
             ReadConfigValue: 6,
-            TestConnectivity: 7,
-            DeployTerminal : 8
+            TestConnectivity: 7
         },
         methodSignature: {
             QueryHardwareInfo: 1706767096,
             ReadCenterConfigStr: -673154017,
             ReadConfigValue: 730234720,
-            TestConnectivity : -42627632,
-            DeployTerminal : 1049464622
+            TestConnectivity : -42627632
         },
 
         QueryHardwareInfo: function (req, callback) {
@@ -1684,11 +1682,6 @@ $(function () {
             this.webSocketInvokeEx(req, 
                 ({id:this.methodID.TestConnectivity, sig:this.methodSignature.TestConnectivity}),
                  callback);
-        },
-        DeployTerminal: function (req, callback) {
-            this.webSocketInvokeEx(req, 
-                ({id:this.methodID.DeployTerminal, sig:this.methodSignature.DeployTerminal}),
-                 callback);
         }
     });
 
@@ -1696,10 +1689,12 @@ $(function () {
         entityName: 'HealthManager',
         className: 'HealthManagerService',
         methodID: {
-            ControlTerminalLife: 7
+            ControlTerminalLife: 7,
+            DeployTerminal : 8
         },
         methodSignature: {
-            ControlTerminalLife: 397251033
+            ControlTerminalLife: 397251033,
+            DeployTerminal : -1435088905
         },
 
         ControlTerminalLife: function (req, callback) {
@@ -1710,6 +1705,11 @@ $(function () {
     
             this.webSocketInvoke(req, callback);
         },
+        DeployTerminal: function (req, callback) {
+            this.webSocketInvokeEx(req, 
+                ({id:this.methodID.DeployTerminal, sig:this.methodSignature.DeployTerminal}),
+                 callback);
+        },
 
         ControlTerminalLifeNo: function(cmdValue) {
             let req = new Request();